summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/libs/xpcom18a4
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4')
-rw-r--r--src/libs/xpcom18a4/Config.kmk475
-rw-r--r--src/libs/xpcom18a4/Makefile.kmk1485
-rw-r--r--src/libs/xpcom18a4/VBoxXPCOM-mangled.def1688
-rw-r--r--src/libs/xpcom18a4/VBoxXPCOM.def1687
-rw-r--r--src/libs/xpcom18a4/dependentLibs.h2
-rw-r--r--src/libs/xpcom18a4/ipc/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/Makefile.in64
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/Makefile.in59
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/ipcCID.h53
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIClientObserver.idl51
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIMessageObserver.idl64
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIService.idl228
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/public/ipcdclient.h326
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.in101
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnection.h147
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionStub.cpp70
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionUnix.cpp615
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionWin.cpp332
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcModuleFactory.cpp196
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.cpp120
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.h51
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/client/src/ipcdclient.cpp1505
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h240
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h151
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in88
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp235
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h144
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp316
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h48
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp245
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h70
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp235
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h82
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h65
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp77
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp600
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp408
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/Makefile.in53
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/ipcIDConnectService.idl79
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.in66
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp4210
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h365
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/Makefile.in33
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestClient.js106
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp268
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestServer.js66
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcILockService.idl65
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcLockCID.h53
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/Makefile.in69
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.cpp87
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.h98
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.cpp168
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.h63
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/Makefile.in92
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/ipcLockModule.cpp337
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/Makefile.in67
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp244
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/.cvsignore9
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/Makefile.in75
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmCID.h53
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmModule.cpp71
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/.cvsignore5
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/Makefile.in61
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.cpp107
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.h234
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmUtils.h93
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.cpp179
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.h160
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/.cvsignore11
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/Makefile.in100
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.cpp137
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.h109
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.cpp223
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.h186
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.cpp162
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.h147
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/Makefile.in53
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionObserver.idl100
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionService.idl239
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/.cvsignore4
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/Makefile.in64
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.cpp504
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.h196
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/.cvsignore6
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/Makefile.in68
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp323
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/ipc.pkg21
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/Makefile.in65
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.cpp104
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.h98
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.cpp62
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.h108
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcList.h211
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.cpp181
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.h111
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.cpp280
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.h214
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.cpp81
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.h206
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageQ.h46
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageUtils.h66
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.cpp80
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.h114
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.cpp303
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h502
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/test/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/test/Makefile.in69
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/test/TestIPC.cpp338
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/test/module/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/test/module/Makefile.in81
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/test/module/TestModule.cpp62
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/public/Makefile.in53
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageReader.h89
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageWriter.h99
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/src/Makefile.in56
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageReader.cpp100
-rw-r--r--src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageWriter.cpp130
-rw-r--r--src/libs/xpcom18a4/java/Makefile.kmk230
-rw-r--r--src/libs/xpcom18a4/java/README.vbox5
-rw-r--r--src/libs/xpcom18a4/java/src/MacJawt.mm47
-rw-r--r--src/libs/xpcom18a4/java/src/dlldeps-javaxpcom.cpp81
-rw-r--r--src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.cpp253
-rw-r--r--src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.h65
-rw-r--r--src/libs/xpcom18a4/java/src/nsFileStreams.cpp475
-rw-r--r--src/libs/xpcom18a4/java/src/nsFileStreams.h153
-rw-r--r--src/libs/xpcom18a4/java/src/nsIFileStreams.h209
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp557
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaInterfaces.h121
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp2020
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaWrapper.h75
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.cpp1084
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.h392
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPCOMGlue.cpp535
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPTCStub.cpp1711
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPTCStub.h153
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.cpp98
-rw-r--r--src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.h63
-rw-r--r--src/libs/xpcom18a4/java/src/nsThreadUtils.h399
-rw-r--r--src/libs/xpcom18a4/java/src/nsXPTCUtils.h128
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/GREVersionRange.java80
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IAppFileLocProvider.java92
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IGRE.java127
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IJavaXPCOMUtils.java59
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IMozilla.java63
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/INIParser.java243
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IXPCOM.java137
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java1079
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/ProfileLock.java63
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/VersionComparator.java272
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMException.java95
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMInitializationException.java56
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/GREImpl.java63
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/JavaXPCOMMethods.java104
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/MozillaImpl.java56
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMImpl.java73
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java257
-rw-r--r--src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxyBase.java53
-rw-r--r--src/libs/xpcom18a4/java/src/org/virtualbox/VBoxObjectBase.java31
-rwxr-xr-xsrc/libs/xpcom18a4/java/tools/gen-nsError.pl161
-rw-r--r--src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp952
-rw-r--r--src/libs/xpcom18a4/java/tools/genjifaces.xsl600
-rw-r--r--src/libs/xpcom18a4/nsBuildID.h23
-rw-r--r--src/libs/xpcom18a4/nsprpub/Makefile.in151
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/admin/explode.pl75
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/admin/makeTargetDirs.sh79
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/admin/repackage.sh218
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/admin/symlinks.sh75
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/.cvsignore11
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/config/Makefile.in149
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/autoconf.mk.in113
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/config.mk164
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/libc_r.h158
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/config/nfspwd.pl50
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/now.c142
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/nsinstall.c602
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/config/nspr-config.in116
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/nspr.m467
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/nsprincl.mk.in5
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/nsprincl.sh.in5
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/pathsub.h78
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/prdepend.h44
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/prmkdir.bat38
-rw-r--r--src/libs/xpcom18a4/nsprpub/config/rules.mk514
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/configure6034
-rw-r--r--src/libs/xpcom18a4/nsprpub/configure.in2556
-rw-r--r--src/libs/xpcom18a4/nsprpub/gmakefile.win96
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/Makefile.in56
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/MANIFEST7
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/Makefile.in202
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plarena.c442
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plarena.h219
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plarenas.h126
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plds.def78
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plds.rc102
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plds_symvec.opt37
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plhash.c541
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plhash.h183
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/ds/plvrsion.c125
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/Makefile.in56
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/README20
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/MANIFEST9
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/Makefile.in61
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/README7
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/plbase64.h103
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/plerror.h71
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/plgetopt.h87
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/plresolv.h108
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/include/plstr.h505
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/Makefile.in202
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/README20
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/base64.c428
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.def94
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.rc103
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/plc_symvec.opt53
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/plerror.c168
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/plgetopt.c184
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/plvrsion.c125
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strcat.c81
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strccmp.c115
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strchr.c88
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strcmp.c57
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strcpy.c84
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strcstr.c123
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strdup.c100
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strlen.c71
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strpbrk.c100
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strstr.c117
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/libc/src/strtok.c89
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/include/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/include/MANIFEST5
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/include/Makefile.in61
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/include/gcint.h129
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/include/prgc.h419
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/Makefile.in103
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/macgc.c75
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/os2gc.c83
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/prgcapi.c351
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/prmsgc.c3514
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/unixgc.c155
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/win16gc.c77
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/src/win32gc.c129
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/tests/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/tests/Makefile.in315
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/tests/gc1.c257
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/msgc/tests/thrashgc.c274
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/Makefile.in207
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/plvrsion.c125
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.cpp550
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.h153
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.rc102
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in254
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp204
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/Makefile.in259
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/arena.c401
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/base64t.c3047
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/string.c3116
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/windows/makefile82
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/windows/readme.1st37
-rw-r--r--src/libs/xpcom18a4/nsprpub/lib/tests/windows/winevent.c348
-rw-r--r--src/libs/xpcom18a4/nsprpub/makefile.win127
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/linux/Makefile.in44
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/linux/sun-nspr.spec122
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.com32
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.targ40
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/Makefile.in22
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/depend27
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/pkginfo.tmpl34
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_com31
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_i38630
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_sparc33
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/Makefile.in22
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/depend30
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/pkginfo.tmpl35
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_com28
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_sparc35
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/pkg/solaris/bld_awk_pkginfo.ksh105
-rw-r--r--src/libs/xpcom18a4/nsprpub/pkg/solaris/common_files/copyright28
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/MANIFEST52
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/Makefile.in59
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/gencfg.c309
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/Makefile.in80
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_aix.h254
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_aix32.cfg145
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_aix64.cfg146
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.cfg147
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.h612
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.cfg198
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.h214
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg172
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h306
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.cfg138
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.h221
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.cfg337
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.h290
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux.h257
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux32.cfg142
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux64.cfg143
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_iprt_atomic.h64
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_irix.h470
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_irix32.cfg149
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_irix64.cfg148
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.cfg661
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.h501
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_macos.h725
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.cfg140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.h230
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.cfg140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.h196
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.cfg289
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.h322
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.cfg255
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.h299
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nspr_pthread.h283
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.cfg150
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.h221
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.cfg387
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.h238
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.cfg146
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.h332
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.cfg151
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.h601
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_os2_errors.h162
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.cfg146
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.h255
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_pcos.h89
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_pth.h298
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.cfg96
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.h215
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.cfg145
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.h270
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.cfg148
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.h225
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.cfg140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.h204
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris.h832
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris32.cfg150
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris64.cfg151
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.cfg140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.h204
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.cfg138
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.h236
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_unix_errors.h171
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_unixos.h641
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.cfg140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.h219
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware7.cfg142
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_vbox.cfg66
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.cfg177
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.h568
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_win32_errors.h154
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.cfg200
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.h533
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.cfg200
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.h594
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/prosdep.h166
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/md/sunos4.h164
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/nspr.h75
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/obsolete/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/obsolete/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/obsolete/pralarm.h200
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/obsolete/probslet.h188
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/obsolete/protypes.h260
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/obsolete/prsem.h104
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/pratom.h172
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prbit.h117
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prclist.h140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prcmon.h107
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prcountr.h572
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prcvar.h134
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prdtoa.h96
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prenv.h162
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prerr.h278
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prerror.h339
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prinet.h126
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prinit.h260
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prinrval.h186
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prio.h2107
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/pripcsem.h141
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/Makefile.in61
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/pprio.h294
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/pprmwait.h136
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/pprthred.h414
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/primpl.h2141
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/private/prpriv.h53
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prlink.h271
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prlock.h128
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prlog.h265
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prlong.h440
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prmem.h166
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prmon.h123
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prmwait.h424
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prnetdb.h524
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prolock.h217
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prpdce.h127
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prprf.h169
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prproces.h133
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prrng.h111
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prrwlock.h128
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prshm.h297
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prshma.h279
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prsystem.h131
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prthread.h305
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prtime.h311
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prtpool.h130
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prtrace.h692
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prtypes.h570
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prvrsion.h137
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/include/prwin16.h196
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/Makefile.in422
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/Makefile.in63
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/bsrcs.mk49
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btcvar.c276
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btlocks.c116
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmisc.c104
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmon.c219
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btsem.c130
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btthread.c694
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/bthreads/objs.mk43
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/Makefile.in75
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcascii.h175
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.cpp55
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.h83
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.cpp97
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.h96
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.cpp199
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.h161
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.cpp69
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.h169
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.cpp46
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.h148
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.cpp72
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.h98
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcmon.h79
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.cpp232
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.h129
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.cpp195
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.h126
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.cpp220
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.h227
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.cpp66
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.h138
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/Makefile.in288
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/fileio.cpp65
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/interval.cpp133
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/ranfile.cpp432
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/switch.cpp266
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/thread.cpp140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/time.cpp61
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/tpd.cpp368
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/Makefile.in97
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prdir.c164
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prfdcach.c311
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prfile.c861
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prio.c202
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/priometh.c628
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/pripv6.c382
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prlayer.c769
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prlog.c617
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prmapopt.c517
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prmmap.c93
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prmwait.c1491
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prpolevt.c530
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prprf.c1229
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prscanf.c669
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prsocket.c1842
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/io/prstdio.c103
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/linking/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/linking/Makefile.in80
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/linking/prlink.c2147
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/malloc/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/malloc/Makefile.in67
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmalloc.c1174
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmem.c762
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/Makefile.in64
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bcpu.c55
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos.c264
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos_errors.c1525
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bfile.c892
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmemory.c42
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmisc.c123
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmmap.c73
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bnet.c929
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bproc.c237
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/brng.c69
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bseg.c54
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bsrcs.mk54
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/btime.c75
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/beos/objs.mk43
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MANIFEST7
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MacErrorHandling.h668
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c587
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.h57
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.c1949
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.h51
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macrng.c52
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsocket.h238
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsockotpt.c2321
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macthr.c721
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.c253
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.h51
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.c173
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.h59
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.c776
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.h51
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/prcpucfg.h136
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/Makefile.in85
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/objs.mk65
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2_errors.c1129
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2cv.c432
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2emx.s111
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2gc.c90
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2inrval.c103
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2io.c907
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2misc.c666
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2poll.c382
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2rng.c111
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sem.c93
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sock.c733
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2thred.c407
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vaclegacy.s73
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vacpp.asm293
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/prosdep.c114
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/Makefile.in135
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aix.c333
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aixwrap.c65
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/bsdi.c119
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/darwin.c110
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/dgux.c109
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/freebsd.c119
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/hpux.c261
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/irix.c1680
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/linux.c123
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/ncr.c395
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nec.c100
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/netbsd.c121
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nextstep.c284
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nto.c66
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/objs.mk63
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openbsd.c121
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openvms.c286
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_AIX.s119
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_BSD_386_2.s71
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_ppc.s92
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_x86.s109
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_HPUX.s54
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Irix.s163
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_ia64.s80
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86.s114
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86_64.s95
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_ReliantUNIX.s125
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS.s68
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_32.s117
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_sparcv9.s201
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_ultrasparc.s201
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86.s249
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86_64.s95
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/osf1.c107
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/pthreads_user.c480
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/qnx.c102
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/reliantunix.c133
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/rhapsody.c137
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/scoos.c181
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/solaris.c889
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sony.c109
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sunos4.c96
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix.c3738
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix_errors.c862
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unixware.c583
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxpoll.c708
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxproces.c1118
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxrng.c340
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxshm.c658
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxwrap.c548
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/Makefile.in121
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntdllmn.c88
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntgc.c126
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntinrval.c124
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntio.c4684
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntmisc.c929
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsec.c279
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsem.c84
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntthread.c563
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/objs.mk94
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16callb.c262
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16error.c252
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16fmem.c85
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16gc.c86
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16io.c855
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16mem.c84
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16null.c116
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16proc.c77
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16sock.c1170
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16stdio.c169
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16thred.c426
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32ipcsem.c227
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32poll.c351
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32rng.c107
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32shm.c356
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95cv.c347
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95dllmain.c71
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95io.c1511
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95sock.c658
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95thred.c295
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/windows/win32_errors.c562
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/memory/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/memory/Makefile.in69
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/memory/prgcleak.c122
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/memory/prseg.c93
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/memory/prshm.c156
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/memory/prshma.c142
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/Makefile.in107
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/pr/src/misc/compile-et.pl140
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/pralarm.c282
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/pratom.c409
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prcountr.c506
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prdtoa.c3519
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prenv.c109
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.c128
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.et135
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.properties116
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prerror.c107
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prerrortable.c240
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c880
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prinrval.c157
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/pripc.c132
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/pripcsem.c130
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prlog2.c81
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prlong.c282
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prnetdb.c2189
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prolock.c100
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prrng.c76
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prsystem.c233
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prthinfo.c247
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prtime.c1973
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prtpool.c1217
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/misc/prtrace.c922
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/nspr.def457
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/nspr.rc102
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/nspr_symvec.opt500
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/os2extra.def16
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/prvrsion.c127
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/pthreads/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/pthreads/Makefile.in79
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c4920
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptmisc.c71
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptsynch.c1126
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptthread.c1610
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/Makefile.in94
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/Makefile.in79
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/README62
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucpu.c440
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucv.c681
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prulock.c463
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prustack.c206
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/pruthr.c1918
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prcmon.c413
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prcthr.c446
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prdump.c153
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prmon.c222
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prrwlock.c512
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prsem.c174
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/threads/prtpd.c280
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/Makefile.in571
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/README.TXT434
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/accept.c524
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/acceptread.c272
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/acceptreademu.c302
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/addrstr.c114
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/affinity.c124
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c569
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/anonfm.c343
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/append.c158
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/atomic.c126
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/attach.c392
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/bigfile.c318
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/bigfile2.c127
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/bigfile3.c125
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/bug1test.c257
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/cleanup.c131
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/cltsrv.c1226
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/concur.c193
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/cvar.c334
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/cvar2.c1008
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc.c347
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc1.c141
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dceemu.c132
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/depend.c153
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dll/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dll/Makefile.in121
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dll/my.def53
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dll/mygetval.c58
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dll/mysetval.c45
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dlltest.c221
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/dtoa.c217
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/env.c221
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/errcodes.c167
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/errset.c186
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/exit.c137
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/fdcach.c259
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/fileio.c250
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/foreign.c416
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/forktest.c346
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/formattm.c59
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/freeif.c75
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/fsync.c155
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/getai.c64
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/gethost.c291
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/getproto.c114
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/i2l.c133
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/initclk.c108
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/inrval.c242
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/instrumt.c507
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/intrio.c169
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/intrupt.c373
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/io_timeout.c299
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutk.c233
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutu.c234
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/ioconthr.c146
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/ipv6.c248
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/join.c264
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/joinkk.c193
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/joinku.c199
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/joinuk.c195
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/joinuu.c197
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/layer.c465
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/lazyinit.c139
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/libfilename.c129
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/lltest.c859
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/lock.c547
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/lockfile.c276
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/logger.c167
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/makedir.c99
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/many_cv.c150
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/mbcs.c187
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/multiacc.c252
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/multiwait.c725
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/nameshm1.c599
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/nbconn.c591
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/nblayer.c707
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/nonblock.c273
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/ntioto.c317
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/ntoh.c125
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/obsints.c83
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/op_2long.c117
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/op_excl.c156
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/op_filnf.c91
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/op_filok.c110
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/op_noacc.c94
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/op_nofil.c99
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/openfile.c145
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/parent.c157
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/peek.c392
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/perf.c485
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/pipeping.c190
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/pipeping2.c192
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/pipepong.c92
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/pipepong2.c130
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/pipeself.c260
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/poll_er.c244
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/poll_nm.c399
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/poll_to.c216
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/pollable.c293
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prftest.c97
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prftest1.c152
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prftest2.c129
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/primblok.c148
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/priotest.c233
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/provider.c1447
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prpoll.c373
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prpollml.c162
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prselect.c372
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/prttools.h43
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/randseed.c162
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/ranfile.c433
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/rmdir.c127
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/pr/tests/runtests.ksh292
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/pr/tests/runtests.sh292
-rwxr-xr-xsrc/libs/xpcom18a4/nsprpub/pr/tests/runy2ktests.ksh269
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/rwlocktest.c241
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sel_spd.c567
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/selct_er.c234
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/selct_nm.c320
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/selct_to.c208
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/select2.c354
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/selintr.c81
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sem.c253
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sema.c180
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/semaerr.c142
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/semaerr1.c137
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/semaping.c203
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/semapong.c147
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sendzlf.c246
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/server_test.c634
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/servr_kk.c613
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/servr_ku.c593
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/servr_uk.c595
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/servr_uu.c593
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/short_thread.c90
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sigpipe.c131
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sleep.c134
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/socket.c2354
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sockopt.c213
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sockping.c164
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sockpong.c115
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sprintf.c454
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sproc_ch.c119
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/sproc_p.c101
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/stack.c310
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/stat.c119
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/stdio.c83
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/str2addr.c82
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/strod.c106
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/suspend.c231
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/switch.c274
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/system.c82
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/testbit.c129
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/testfile.c1008
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/threads.c249
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_client.c392
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_server.c607
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/thruput.c412
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/time.c201
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/timemac.c153
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/timetest.c782
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/tmoacc.c333
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/tmocon.c401
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/tpd.c334
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/udpsrv.c566
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/ut_ttools.h43
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/vercheck.c108
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/version.c123
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/Makefile.in99
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfile.c167
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfind.c149
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfont.c94
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.c672
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.h66
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.icobin0 -> 326 bytes
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.rc121
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popprnt0.c49
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/readme.1st37
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/writev.c234
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/xnotify.c389
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/y2k.c840
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/y2ktmo.c546
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/yield.c88
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/tests/zerolen.c282
-rw-r--r--src/libs/xpcom18a4/nsprpub/tools/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/nsprpub/tools/Makefile.in249
-rw-r--r--src/libs/xpcom18a4/nsprpub/tools/httpget.c466
-rw-r--r--src/libs/xpcom18a4/nsprpub/tools/tail.c166
-rw-r--r--src/libs/xpcom18a4/python/.cvsignore4
-rw-r--r--src/libs/xpcom18a4/python/Makefile.kmk730
-rw-r--r--src/libs/xpcom18a4/python/README.vbox5
-rwxr-xr-xsrc/libs/xpcom18a4/python/__init__.py173
-rw-r--r--src/libs/xpcom18a4/python/client/.cvsignore2
-rwxr-xr-xsrc/libs/xpcom18a4/python/client/__init__.py539
-rwxr-xr-xsrc/libs/xpcom18a4/python/components.py248
-rw-r--r--src/libs/xpcom18a4/python/doc/advanced.html176
-rw-r--r--src/libs/xpcom18a4/python/doc/architecture.html116
-rw-r--r--src/libs/xpcom18a4/python/doc/configure.html196
-rw-r--r--src/libs/xpcom18a4/python/doc/credits.html86
-rw-r--r--src/libs/xpcom18a4/python/doc/tutorial.html286
-rwxr-xr-xsrc/libs/xpcom18a4/python/file.py318
-rwxr-xr-xsrc/libs/xpcom18a4/python/gen_python_deps.py147
-rwxr-xr-xsrc/libs/xpcom18a4/python/nsError.py166
-rwxr-xr-xsrc/libs/xpcom18a4/python/primitives.py39
-rw-r--r--src/libs/xpcom18a4/python/readme.html121
-rw-r--r--src/libs/xpcom18a4/python/server/.cvsignore2
-rwxr-xr-xsrc/libs/xpcom18a4/python/server/__init__.py88
-rwxr-xr-xsrc/libs/xpcom18a4/python/server/enumerator.py58
-rwxr-xr-xsrc/libs/xpcom18a4/python/server/factory.py68
-rwxr-xr-xsrc/libs/xpcom18a4/python/server/loader.py227
-rwxr-xr-xsrc/libs/xpcom18a4/python/server/module.py108
-rwxr-xr-xsrc/libs/xpcom18a4/python/server/policy.py398
-rw-r--r--src/libs/xpcom18a4/python/src/ErrorUtils.cpp483
-rw-r--r--src/libs/xpcom18a4/python/src/PyGBase.cpp852
-rw-r--r--src/libs/xpcom18a4/python/src/PyGInputStream.cpp173
-rw-r--r--src/libs/xpcom18a4/python/src/PyGModule.cpp297
-rw-r--r--src/libs/xpcom18a4/python/src/PyGStub.cpp180
-rw-r--r--src/libs/xpcom18a4/python/src/PyGWeakReference.cpp112
-rw-r--r--src/libs/xpcom18a4/python/src/PyIClassInfo.cpp181
-rw-r--r--src/libs/xpcom18a4/python/src/PyIComponentManager.cpp138
-rw-r--r--src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp203
-rw-r--r--src/libs/xpcom18a4/python/src/PyIEnumerator.cpp235
-rw-r--r--src/libs/xpcom18a4/python/src/PyIID.cpp410
-rw-r--r--src/libs/xpcom18a4/python/src/PyIInputStream.cpp190
-rw-r--r--src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp431
-rw-r--r--src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp206
-rw-r--r--src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp202
-rw-r--r--src/libs/xpcom18a4/python/src/PyISupports.cpp621
-rw-r--r--src/libs/xpcom18a4/python/src/PyIVariant.cpp231
-rw-r--r--src/libs/xpcom18a4/python/src/PyXPCOM.h1036
-rw-r--r--src/libs/xpcom18a4/python/src/PyXPCOM_std.h56
-rw-r--r--src/libs/xpcom18a4/python/src/Pyxpt_info.cpp197
-rw-r--r--src/libs/xpcom18a4/python/src/TypeObject.cpp457
-rw-r--r--src/libs/xpcom18a4/python/src/VariantUtils.cpp3112
-rw-r--r--src/libs/xpcom18a4/python/src/dllmain.cpp352
-rw-r--r--src/libs/xpcom18a4/python/src/loader/pyloader.cpp435
-rw-r--r--src/libs/xpcom18a4/python/src/module/_xpcom.cpp950
-rw-r--r--src/libs/xpcom18a4/python/src/readme.html99
-rw-r--r--src/libs/xpcom18a4/python/test/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_com_exceptions8
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_comfile7
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_components4
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_isupports_primitives2
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_streams1
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_test_component4
-rw-r--r--src/libs/xpcom18a4/python/test/output/test_weakreferences2
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/pyxpcom_test_tools.py126
-rw-r--r--src/libs/xpcom18a4/python/test/regrtest.py91
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_com_exceptions.py124
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_comfile.py49
-rw-r--r--src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done0
-rw-r--r--src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h1411
-rw-r--r--src/libs/xpcom18a4/python/test/test_component/py_test_component.html182
-rw-r--r--src/libs/xpcom18a4/python/test/test_component/py_test_component.idl231
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_component/py_test_component.py421
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_components.py109
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_isupports_primitives.py207
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_misc.py236
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_streams.py96
-rw-r--r--src/libs/xpcom18a4/python/test/test_test_component.js138
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_test_component.py575
-rwxr-xr-xsrc/libs/xpcom18a4/python/test/test_weakreferences.py114
-rwxr-xr-xsrc/libs/xpcom18a4/python/tools/regxpcom.py68
-rwxr-xr-xsrc/libs/xpcom18a4/python/tools/tracer_demo.py113
-rwxr-xr-xsrc/libs/xpcom18a4/python/vboxxpcom.py83
-rw-r--r--src/libs/xpcom18a4/python/xpcom_consts.py272
-rwxr-xr-xsrc/libs/xpcom18a4/python/xpt.py471
-rw-r--r--src/libs/xpcom18a4/vboxdeps.cpp75
-rw-r--r--src/libs/xpcom18a4/xpcom-config.h69
-rw-r--r--src/libs/xpcom18a4/xpcom-namespace-cleanup.map34
-rw-r--r--src/libs/xpcom18a4/xpcom-private.h32
-rw-r--r--src/libs/xpcom18a4/xpcom/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/Makefile.in84
-rw-r--r--src/libs/xpcom18a4/xpcom/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in70
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c2765
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h1800
-rw-r--r--src/libs/xpcom18a4/xpcom/base/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/base/Makefile.in133
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAgg.h155
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp41
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAllocator.h50
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h1353
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsCom.h43
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp69
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp321
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleService.h89
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp477
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h61
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsError.h317
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp153
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsErrorService.h76
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp383
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsExceptionService.h94
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c127
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIAllocator.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl49
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl56
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl85
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsID.cpp152
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsID.h166
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIDebug.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl100
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIException.idl101
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl97
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIID.h41
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl54
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIMemory.idl126
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl70
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISupports.idl80
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h119
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h243
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl62
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl102
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp248
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h60
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp548
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h91
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp375
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h46
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp351
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h126
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp1444
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h109
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h48
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nscore.h468
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsrootidl.idl128
-rw-r--r--src/libs/xpcom18a4/xpcom/base/pure.h135
-rw-r--r--src/libs/xpcom18a4/xpcom/base/pure_api.c126
-rw-r--r--src/libs/xpcom18a4/xpcom/build/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/build/Makefile.in165
-rw-r--r--src/libs/xpcom18a4/xpcom/build/dlldeps.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/build/malloc.c5126
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp753
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp261
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPCOM.h217
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h174
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h228
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp1079
-rw-r--r--src/libs/xpcom18a4/xpcom/build/win32.order1514
-rw-r--r--src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg47
-rw-r--r--src/libs/xpcom18a4/xpcom/build/xpcom.pkg106
-rw-r--r--src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def252
-rw-r--r--src/libs/xpcom18a4/xpcom/components/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/components/Makefile.in107
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp799
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h159
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h88
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp3794
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManager.h339
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp271
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h185
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl101
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl132
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl109
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl111
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl351
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h43
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl243
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIFactory.idl79
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIModule.idl115
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl70
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl119
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h250
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h185
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsModule.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp1150
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h84
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h27
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp155
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h52
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp317
-rw-r--r--src/libs/xpcom18a4/xpcom/components/xcDll.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/components/xcDll.h121
-rw-r--r--src/libs/xpcom18a4/xpcom/doc/README8
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/Makefile.in171
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArray.cpp226
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArray.h118
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp210
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h87
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp67
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomService.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp616
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h101
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h127
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h458
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp170
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp162
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h267
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp534
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCRT.h301
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp180
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h194
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h149
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h127
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h62
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp627
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDeque.h405
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h505
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp108
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h64
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp253
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h129
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp153
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h201
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h315
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp46
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashSets.h107
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp896
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsHashtable.h454
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIArray.idl202
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl161
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl73
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h95
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsICollection.idl92
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl89
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl58
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl111
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h8
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl107
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl79
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl77
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl68
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl65
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl81
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl58
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl139
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl325
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl304
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl242
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h73
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl188
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsInt64.h399
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h121
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp211
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverList.h79
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp227
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsObserverService.h75
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp492
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h106
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp150
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsProperties.h72
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp182
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h72
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp443
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h208
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h197
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h65
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp217
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h81
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp261
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h122
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp684
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h172
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp148
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp880
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h358
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp62
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h429
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp1557
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h115
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTime.h143
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp613
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h64
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp141
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h65
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h207
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp304
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsValueArray.h125
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp2092
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVariant.h203
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp1560
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h410
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/pldhash.c826
-rw-r--r--src/libs/xpcom18a4/xpcom/ds/pldhash.h603
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/Makefile.in86
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp124
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h1405
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp133
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp119
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsDebug.h276
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp547
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h129
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h480
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp64
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h83
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h1246
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h230
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h162
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp151
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsMemory.h154
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h183
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp125
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h135
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp169
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h150
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/objs.mk60
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore8
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in88
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp596
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h68
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp524
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h109
-rw-r--r--src/libs/xpcom18a4/xpcom/io/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/io/Makefile.in175
-rw-r--r--src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp770
-rw-r--r--src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h136
-rw-r--r--src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c784
-rw-r--r--src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h158
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h120
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp608
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp663
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h125
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h59
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp1241
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h177
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h197
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h61
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsEscape.cpp491
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsEscape.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp2581
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h566
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h112
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp571
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h71
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl136
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl136
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl45
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl121
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl119
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl48
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl68
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl138
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl123
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl155
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIFile.idl343
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl139
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl61
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl54
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl180
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl262
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl90
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl88
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl87
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl131
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl167
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIPipe.idl211
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl73
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl102
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl107
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl191
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl138
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h94
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp224
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp495
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h156
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFile.h118
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp278
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp3554
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h137
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp1742
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h113
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp2542
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h119
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h47
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp1724
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h132
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp2440
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h113
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp389
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h63
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp1280
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h66
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp1276
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp102
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h71
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp207
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h125
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp563
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStorageStream.h98
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp583
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h111
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStringIO.h86
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStringStream.h84
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp415
-rw-r--r--src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html13
-rw-r--r--src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html13
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/Makefile.in130
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in81
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp857
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h116
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl186
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h63
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp2019
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h77
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp57
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp357
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg6
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp50
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp1367
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h782
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp547
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp879
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h116
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp1471
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp840
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp703
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp766
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp392
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h772
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl204
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp727
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h157
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl186
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h63
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp1189
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h167
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp54
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h50
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg7
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in63
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl53
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl87
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h164
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h183
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h112
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in67
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h39
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp613
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp367
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp555
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h201
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp322
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp55
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl9
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp553
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore4
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/README6
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html212
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in54
-rwxr-xr-xsrc/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl78
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h271
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc761
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc256
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in62
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in56
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp148
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s128
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp265
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s78
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in72
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp185
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp159
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm268
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp153
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp180
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp195
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm1563
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in50
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README6
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat5
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp239
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat9
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat9
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp210
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in416
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp62
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h92
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h161
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp218
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm403
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp220
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp296
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp213
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s149
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s166
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s99
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s83
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s131
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s161
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s140
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s114
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s162
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s121
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s67
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s84
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s71
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s71
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s71
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s70
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s72
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s103
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp215
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp133
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp173
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp170
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp254
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp250
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp122
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp175
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp93
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp106
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp95
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp141
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp147
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp156
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp156
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp187
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp48
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp227
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp285
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp243
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp244
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp272
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s124
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s124
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s97
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4109
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s115
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s75
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s68
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s117
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s137
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4126
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s89
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s89
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s65
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s65
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s67
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp185
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp186
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp226
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp236
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp220
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp224
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp131
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp147
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp147
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp149
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp176
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp228
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp215
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp253
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp217
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp254
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp139
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp188
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp56
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp242
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp271
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp165
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in82
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp171
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s128
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp228
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s120
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp62
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h45
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html404
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in64
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp1464
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in66
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl137
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl85
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl100
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h281
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in75
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO20
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp819
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp2126
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp710
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp63
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp432
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp102
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h981
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/Makefile.in113
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsISample.idl66
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSample.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSample.h129
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSample.js130
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp131
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp158
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/win32.order1
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html220
-rw-r--r--src/libs/xpcom18a4/xpcom/string/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/string/Makefile.in54
-rw-r--r--src/libs/xpcom18a4/xpcom/string/README.html44
-rw-r--r--src/libs/xpcom18a4/xpcom/string/doc/README.html44
-rw-r--r--src/libs/xpcom18a4/xpcom/string/doc/string-guide.html2508
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/Makefile.in86
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsAString.h96
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h131
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h784
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h60
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h158
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h116
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h102
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h87
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h370
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsString.h237
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h853
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h96
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h373
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h74
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTAString.h618
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h137
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h143
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h165
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h158
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTString.h721
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h575
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h113
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h462
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h46
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h59
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/Makefile.in77
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp51
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp50
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp52
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp83
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp49
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp1122
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsString.cpp49
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp75
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp1327
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp250
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp64
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp509
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp65
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp235
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp66
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp63
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp79
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp518
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp656
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp127
-rw-r--r--src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp261
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/.cvsignore31
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp126
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/Makefile.in116
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp162
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp93
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp101
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp72
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp78
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp231
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in76
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix4
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcpbin0 -> 245184 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix4
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix5
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix3
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix6
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix7
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc41
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h234
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp497
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp651
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestArray.cpp230
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp132
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp91
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp566
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp651
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp200
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp112
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp129
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp155
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp160
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestFactory.h69
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp939
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestID.cpp77
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp333
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp250
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp88
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp655
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp173
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp78
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp11
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp643
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp280
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp302
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp18
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in61
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp76
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp95
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp475
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/resources.h52
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp93
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/MyService.h69
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/win32.order1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/test.properties46
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp61
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/cp.js111
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/dirs.js155
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/ls.js64
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp177
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp33
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h2277
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h444
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/Makefile.in105
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp462
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/TimerThread.h122
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp435
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h383
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp632
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h89
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp450
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h77
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h78
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl89
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl107
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl151
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl32
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl44
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIThread.idl144
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsITimer.idl191
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl48
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl61
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h93
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsProcess.h71
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp363
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp188
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsThread.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsThread.h92
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp642
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h195
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/plevent.c1774
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/plevent.h690
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/Makefile.in53
-rwxr-xr-xsrc/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl177
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in77
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp404
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp104
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in88
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/README16
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrcbin0 -> 915 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrcbin0 -> 984 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c139
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h49
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp58
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp38
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h47
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp417
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h25
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp695
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h106
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp546
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrcbin0 -> 16238 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrcbin0 -> 755 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c275
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h278
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c312
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c1196
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c836
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c1053
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c1237
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c851
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in50
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in51
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h145
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h562
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h240
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in76
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c358
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c956
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c665
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in59
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c157
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c192
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in90
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c941
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c883
-rw-r--r--src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in50
-rw-r--r--src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp60
-rw-r--r--src/libs/xpcom18a4/xpcom/xpcom-config.h.in65
-rw-r--r--src/libs/xpcom18a4/xpcom/xpcom-private.h.in31
1802 files changed, 493816 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/Config.kmk b/src/libs/xpcom18a4/Config.kmk
new file mode 100644
index 00000000..3d3c349a
--- /dev/null
+++ b/src/libs/xpcom18a4/Config.kmk
@@ -0,0 +1,475 @@
+# $Id: Config.kmk $
+## @file
+# XPCOM kBuild Configuration file.
+#
+
+#
+# Copyright (C) 2006-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+# Include the top-level configure file.
+ifndef VBOX_ROOT_CONFIG_KMK_INCLUDED
+ include $(PATH_ROOT)/Config.kmk
+endif
+
+#
+# Globals.
+#
+VBOX_PATH_XPCOM_SRC := $(PATH_ROOT)/src/libs/xpcom18a4
+
+
+#
+# Template for building the XPCOM libraries (shared).
+#
+TEMPLATE_XPComDll = XPCOM libraries (shared)
+TEMPLATE_XPComDll_EXTENDS = VBoxR3DllNonPedantic
+## @todo correct inheritance here to make it use all the VBoxR3DllNonPedantic settings instead of overriding all of them.
+TEMPLATE_XPComDll_ASTOOL = $(TEMPLATE_VBoxR3DllNonPedantic_TOOL)
+TEMPLATE_XPComDll_ASFLAGS = $(NO_SUCH_VARIABLE)
+TEMPLATE_XPComDll_ASFLAGS.x86 = -m32
+TEMPLATE_XPComDll_ASFLAGS.amd64 = -m64
+TEMPLATE_XPComDll_ASDEFS = $(NO_SUCH_VARIABLE)
+TEMPLATE_XPComDll_CXXFLAGS = -g -pipe -ansi -Wall -Wno-unused -Wno-non-virtual-dtor \
+ $(VBOX_GCC_Wno-invalid-offsetof) -Wno-sign-compare -Wno-unused -Wno-ctor-dtor-privacy \
+ $(VBOX_GCC_fvisibility-inlines-hidden) $(VBOX_GCC_fvisibility-hidden) \
+ $(VBOX_GCC_Wno-delete-non-virtual-dtor) $(VBOX_GCC_Wno-multistatement-macros) $(VBOX_GCC_fdiagnostics-show-option) \
+ $(VBOX_GCC_SANITIZER_FLAGS) $(VBOX_GCC_OPT) $(VBOX_GCC_FP)
+#if !defined(VBOX_GCC_Wno-delete-non-virtual-dtor) && defined(VBOX_GCC_Wno-non-virtual-dtor)
+ifndef VBOX_GCC_Wno-delete-non-virtual-dtor
+ ifdef VBOX_GCC_Wno-non-virtual-dtor
+ TEMPLATE_XPComDll_CXXFLAGS += $(VBOX_GCC_Wno-non-virtual-dtor)
+ endif
+endif
+TEMPLATE_XPComDll_CXXFLAGS.x86 = -m32
+TEMPLATE_XPComDll_CXXFLAGS.amd64 = -m64
+TEMPLATE_XPComDll_CXXFLAGS.arm64 = -m64
+TEMPLATE_XPComDll_CXXFLAGS.darwin = -fpascal-strings -fshort-wchar -fno-common -fno-rtti $(VBOX_DARWIN_DEF_SDK_CXXFLAGS)
+TEMPLATE_XPComDll_CXXFLAGS.freebsd = -pthread
+TEMPLATE_XPComDll_CXXFLAGS.linux = -pthread
+TEMPLATE_XPComDll_CXXFLAGS.solaris = -fno-omit-frame-pointer # for now anyway.
+TEMPLATE_XPComDll_CFLAGS = -g -pipe -Wall -Wno-unused -Wno-parentheses -Wno-uninitialized $(VBOX_GCC_fvisibility-hidden) \
+ $(VBOX_GCC_Wno-multistatement-macros) $(VBOX_GCC_fdiagnostics-show-option) $(VBOX_GCC_SANITIZER_FLAGS) $(VBOX_GCC_OPT) $(VBOX_GCC_FP)
+TEMPLATE_XPComDll_CFLAGS.x86 = -m32
+TEMPLATE_XPComDll_CFLAGS.amd64 = -m64
+TEMPLATE_XPComDll_CFLAGS.arm64 = -m64
+TEMPLATE_XPComDll_CFLAGS.freebsd = -pthread
+TEMPLATE_XPComDll_CFLAGS.linux = -pthread -ansi
+TEMPLATE_XPComDll_CFLAGS.solaris = -fno-omit-frame-pointer # for now anyway.
+TEMPLATE_XPComDll_DEFS = \
+ MOZILLA_CLIENT=1 \
+ NDEBUG=1 \
+ _IMPL_NS_COM \
+ IN_RING3 \
+ VBOX_USE_IPRT_IN_XPCOM
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS += \
+ XPCOM_DLL_BASE="$(basename $(notdir $(LIB_XPCOM)))" \
+ MOZ_DLL_SUFFIX="$(suffix $(LIB_XPCOM))"
+else
+ TEMPLATE_XPComDll_DEFS += \
+ XPCOM_DLL_BASE=\"$(basename $(notdir $(LIB_XPCOM)))\" \
+ MOZ_DLL_SUFFIX=\"$(suffix $(LIB_XPCOM))\"
+endif
+
+ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ TEMPLATE_XPComDll_DEFS += VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+endif
+TEMPLATE_XPComDll_DEFS.x86 = i386=1
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.amd64 = HAVE_VA_LIST_AS_ARRAY HAVE_VA_COPY VA_COPY(a,b)=__builtin_va_copy(a,b)
+else
+ TEMPLATE_XPComDll_DEFS.amd64 = HAVE_VA_LIST_AS_ARRAY HAVE_VA_COPY VA_COPY\(a\,b\)=__builtin_va_copy\(a\,b\)
+endif
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.arm64 = HAVE_VA_LIST_AS_ARRAY HAVE_VA_COPY VA_COPY(a,b)=__builtin_va_copy(a,b)
+else
+ TEMPLATE_XPComDll_DEFS.arm64 = HAVE_VA_LIST_AS_ARRAY HAVE_VA_COPY VA_COPY\(a\,b\)=__builtin_va_copy\(a\,b\)
+endif
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.darwin = OSTYPE="Darwin8.8.1" OSARCH="Darwin" XP_UNIX=1 XP_MACOSX=1 TARGET_CARBON=1 HAVE_VISIBILITY_ATTRIBUTE=1 DARWIN=1 $(TEMPLATE_VBoxR3DllNonPedantic_DEFS.darwin)
+else
+ TEMPLATE_XPComDll_DEFS.darwin = OSTYPE=\"Darwin8.8.1\" OSARCH=\"Darwin\" XP_UNIX=1 XP_MACOSX=1 TARGET_CARBON=1 HAVE_VISIBILITY_ATTRIBUTE=1 DARWIN=1 $(TEMPLATE_VBoxR3DllNonPedantic_DEFS.darwin)
+endif
+TEMPLATE_XPComDll_DEFS.darwin.amd64 = VBOX_MACOSX_FOLLOWS_UNIX_IO
+TEMPLATE_XPComDll_DEFS.darwin.arm64 = VBOX_MACOSX_FOLLOWS_UNIX_IO
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.freebsd = OSTYPE="FreeBSD5+" OSARCH="FreeBSD" XP_UNIX=1 FREEBSD=1 HAVE_VISIBILITY_ATTRIBUTE=1
+else
+ TEMPLATE_XPComDll_DEFS.freebsd = OSTYPE=\"FreeBSD5+\" OSARCH=\"FreeBSD\" XP_UNIX=1 FREEBSD=1 HAVE_VISIBILITY_ATTRIBUTE=1
+endif
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.linux = OSTYPE="Linux2.6" OSARCH="Linux" XP_UNIX=1 _GNU_SOURCE HAVE_VISIBILITY_ATTRIBUTE=1 ## @todo LINUX=1
+else
+ TEMPLATE_XPComDll_DEFS.linux = OSTYPE=\"Linux2.6\" OSARCH=\"Linux\" XP_UNIX=1 _GNU_SOURCE HAVE_VISIBILITY_ATTRIBUTE=1 ## @todo LINUX=1
+endif
+# Don't define BSD_SELECT because bsdselect() from kLIBC <= 0.6.3 has problems on SMP
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.os2 = OSTYPE="OS/2_4.5" OSARCH="OS/2" XP_OS2 XP_PC OS2=4
+else
+ TEMPLATE_XPComDll_DEFS.os2 = OSTYPE=\"OS/2_4.5\" OSARCH=\"OS/2\" XP_OS2 XP_PC OS2=4
+endif
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComDll_DEFS.solaris = OSTYPE="Solaris10" OSARCH="Solaris" XP_UNIX=1 XP_SOLARIS=1 HAVE_LIBDL=1 HAVE_SENDFILEV=1 SOLARIS=1 _REENTRANT
+else
+ TEMPLATE_XPComDll_DEFS.solaris = OSTYPE=\"Solaris10\" OSARCH=\"Solaris\" XP_UNIX=1 XP_SOLARIS=1 HAVE_LIBDL=1 HAVE_SENDFILEV=1 SOLARIS=1 _REENTRANT
+endif
+TEMPLATE_XPComDll_LDFLAGS = $(TEMPLATE_VBoxR3DllNonPedantic_LDFLAGS)
+ifdef VBOX_WITH_RUNPATH
+ TEMPLATE_XPComDll_LDFLAGS += '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RUNPATH)'
+else ifdef VBOX_WITH_RELATIVE_RUNPATH
+ TEMPLATE_XPComDll_LDFLAGS += '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RELATIVE_RUNPATH)'
+endif
+TEMPLATE_XPComDll_LDFLAGS.x86 = -m32
+TEMPLATE_XPComDll_LDFLAGS.amd64 = -m64
+TEMPLATE_XPComDll_LDFLAGS.arm64 = -m64
+TEMPLATE_XPComDll_LDFLAGS.darwin = $(TEMPLATE_VBoxR3DllNonPedantic_LDFLAGS.darwin) \
+ -fshort-wchar -fno-rtti -fno-exceptions -fpascal-strings \
+ -current_version $(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD) \
+ -compatibility_version $(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD) \
+ -framework CoreServices \
+ -framework CoreFoundation \
+ -framework Foundation \
+ -framework AppKit \
+ -framework Carbon
+## @todo why is -fno-exceptions here.
+ifn1of ($(KBUILD_TARGET), os2 win)
+ TEMPLATE_XPComDll_CXXFLAGS += -fPIC
+ TEMPLATE_XPComDll_CFLAGS += -fPIC
+ TEMPLATE_XPComDll_LDFLAGS += -fPIC
+ TEMPLATE_XPComDll_DEFS += MOZ_PRESERVE_PIC
+endif
+TEMPLATE_XPComDll_INCS = $(VBOX_PATH_XPCOM_SRC)/xpcom/build \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/ds \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/io \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/base \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/components \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/threads \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/proxy/src \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/reflect/xptcall/src \
+ $(VBOX_PATH_XPCOM_SRC)/ipc/ipcd/client/src \
+ $(VBOX_PATH_XPCOM_SRC)/ipc/ipcd/shared/src \
+ $(VBOX_PATH_XPCOM_SRC)/ipc/ipcd/extensions/lock/src \
+ $(VBOX_PATH_XPCOM_SRC)/ipc/ipcd/extensions/transmngr/src \
+ $(VBOX_PATH_XPCOM_SRC)/ipc/ipcd/extensions/dconnect/src \
+ $(VBOX_PATH_XPCOM_SRC)/ipc/ipcd/extensions/transmngr/common \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/nsprpub \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/string \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/xpcom \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/ipcd \
+ .
+ifn1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.4 10.5 10.6 10.7) # FlatCarbon is gone starting 10.8 (or Xcode 5.0).
+ TEMPLATE_XPComDll_DEFS.darwin += VBOX_WITH_NEWER_OSX_SDK
+ TEMPLATE_XPComDll_INCS.darwin = \
+ $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/ \
+ $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/ \
+ $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/Headers/
+else
+ TEMPLATE_XPComDll_INCS.darwin = $(VBOX_PATH_MACOSX_SDK)/Developer/Headers/FlatCarbon
+endif
+TEMPLATE_XPComDll_LIBS.solaris = sendfile
+TEMPLATE_XPComDll_ORDERDEPS = $(foreach hdrinst, $(filter %-HEADERS, $(INSTALLS)), $($(hdrinst)_1_TARGET)) \
+ $(PATH_TARGET)/VBox-xpcom-idl-timestamp
+ifeq ($(KBUILD_TARGET),os2)
+ ifndef USE_OS2_TOOLKIT_HEADERS
+ TEMPLATE_XPComDll_DEFS.os2 += OS2EMX_PLAIN_CHAR
+ endif
+ TEMPLATE_XPComDll_DEFS.os2 += XP_OS2_EMX OS2=4
+ # this is at least for strnicmp()
+ TEMPLATE_XPComDll_DEFS.os2 += _EMX_SOURCE
+ # @@todo shouldn't this be somehow default for ASTOOL?
+ TEMPLATE_XPComDll_ASFLAGS.os2 += -Zomf
+endif
+
+# When using IPRT in NSRP or/and using IPRT for logging, link with IPRT.
+TEMPLATE_XPComDll_LIBS += $(LIB_RUNTIME)
+
+
+#
+# Same as XPCOM except using YASM/NASM instead of the gnu/unix assembler.
+#
+TEMPLATE_XPComDllYasm := XPCOM w/ yasm
+TEMPLATE_XPComDllYasm_EXTENDS := XPComDll
+TEMPLATE_XPComDllYasm_ASTOOL = $(TEMPLATE_VBoxR3DllNonPedantic_ASTOOL)
+TEMPLATE_XPComDllYasm_ASFLAGS = $(TEMPLATE_VBoxR3DllNonPedantic_ASFLAGS)
+TEMPLATE_XPComDllYasm_ASFLAGS.x86 = $(TEMPLATE_VBoxR3DllNonPedantic_ASFLAGS.x86)
+TEMPLATE_XPComDllYasm_ASFLAGS.amd64 = $(TEMPLATE_VBoxR3DllNonPedantic_ASFLAGS.amd64)
+TEMPLATE_XPComDllYasm_ASDEFS = $(TEMPLATE_VBoxR3DllNonPedantic_DEFS)
+
+
+#
+# Template for building the XPCOM executables.
+# Used as a base template by XPComTstExe and XPComIpcExe.
+#
+TEMPLATE_XPComExe := XPCOM executable files
+TEMPLATE_XPComExe_EXTENDS := XPComDll
+## @todo undo -fPIC.
+TEMPLATE_XPComExe_INCS = ipc/ipcd/shared/src \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/nsprpub \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/string \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/xpcom \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/ipcd \
+ .
+TEMPLATE_XPComExe_LIBS = \
+ $(VBox-xpcom-ipcshared_1_TARGET) \
+ $(VBoxXPCOM_1_TARGET) \
+ $(TEMPLATE_XPComDll_LIBS)
+TEMPLATE_XPComExe_LIBS.freebsd = $(LIB_PTHREAD)
+TEMPLATE_XPComExe_LIBS.linux = dl $(LIB_PTHREAD)
+TEMPLATE_XPComExe_LDFLAGS.darwin = -bind_at_load $(filter-out -current_version -compatibility_version $(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD),$(TEMPLATE_XPComDll_LDFLAGS.darwin))
+
+
+#
+# Template for building the XPCOM testcase executables
+#
+TEMPLATE_XPComTstExe = XPCOM executable files (testcases)
+TEMPLATE_XPComTstExe_EXTENDS = XPComExe
+TEMPLATE_XPComTstExe_CXXFLAGS = $(TEMPLATE_XPComExe_CXXFLAGS) -Wno-format
+TEMPLATE_XPComTstExe_CFLAGS = $(TEMPLATE_XPComExe_CFLAGS) -Wno-format
+TEMPLATE_XPComTstExe_INST = $(INST_TESTCASE)
+ifdef VBOX_WITH_RUNPATH
+ TEMPLATE_XPComTstExe_LDFLAGS = '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RUNPATH)' $(TEMPLATE_XPComExe_LDFLAGS)
+else ifdef VBOX_WITH_RELATIVE_RUNPATH
+ TEMPLATE_XPComTstExe_LDFLAGS = '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RELATIVE_RUNPATH)/..' $(TEMPLATE_XPComExe_LDFLAGS)
+endif
+if "$(KBUILD_TARGET)" == "win" && defined(VBOX_SIGNING_MODE)
+ TEMPLATE_XPComTstExe_POST_CMDS =
+endif
+
+
+#
+# Template for building XPCOM executables for running at build time.
+#
+# It extends the BLDPROG template in config.kmk but overrides CFLAGS
+# and CXXFLAGS completely at the moment.
+#
+TEMPLATE_XPComBldProg = XPCOM Build programs executables
+TEMPLATE_XPComBldProg_EXTENDS = VBoxBldProg
+## @todo Verify that this doesn't blow up because of template inheriance ordering. (we're assuming XPComExe is expanded when this is being used.)
+TEMPLATE_XPComBldProg_DEFS = \
+ $(TEMPLATE_VBoxBldProg_DEFS) \
+ $(filter-out VBOX_USE_IPRT_IN_XPCOM, $(TEMPLATE_XPComExe_DEFS))
+TEMPLATE_XPComBldProg_DEFS.$(KBUILD_HOST) = $(TEMPLATE_VBoxBldProg_DEFS.$(KBUILD_HOST)) $(TEMPLATE_XPComExe_DEFS.$(KBUILD_HOST))
+TEMPLATE_XPComBldProg_DEFS.x86 = $(TEMPLATE_VBoxBldProg_DEFS.x86) $(TEMPLATE_XPComExe_DEFS.x86)
+TEMPLATE_XPComBldProg_DEFS.amd64 = $(TEMPLATE_VBoxBldProg_DEFS.amd64) $(TEMPLATE_XPComExe_DEFS.amd64)
+TEMPLATE_XPComBldProg_INCS = \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/nsprpub \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/string \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/xpcom \
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/ipcd
+TEMPLATE_XPComBldProg_CFLAGS = $(filter-out $(VBOX_GCC_PEDANTIC_C), $(TEMPLATE_VBoxBldProg_CFLAGS)) \
+ $(VBOX_GCC_Wno-int-to-pointer-cast) $(VBOX_GCC_Wno-pointer-to-int-cast) $(VBOX_GCC_NON_PEDANTIC_C)
+TEMPLATE_XPComBldProg_CXXFLAGS.darwin = $(TEMPLATE_VBoxBldProg_CXXFLAGS.darwin) -fpascal-strings -fshort-wchar -fno-common -fno-rtti
+TEMPLATE_XPComBldProg_CXXFLAGS.solaris = $(TEMPLATE_VBoxBldProg_CXXFLAGS.solaris) -fno-omit-frame-pointer # for now anyway.
+TEMPLATE_XPComBldProg_LDFLAGS.darwin = $(TEMPLATE_VBoxBldProg_LDFLAGS.darwin) -fpascal-strings -fshort-wchar -fno-rtti -fno-exceptions
+TEMPLATE_XPComBldProg_ORDERDEPS = $(foreach hdrinst, $(filter %-HEADERS, $(INSTALLS)), $($(hdrinst)_1_TARGET))
+
+
+ifeq ($(VBOX_DEF_MACOSX_VERSION_MIN),10.4)
+ #
+ # Template for building VBoxPython against the Mac OS X 10.4 SDK.
+ # ASSUMES that the SDK bits are in the .darwin properties we're overriding below.
+ #
+ TEMPLATE_XPComDllOSX104 = XPCOM libraries (shared) built against the Mac OS X 10.4 SDK
+ TEMPLATE_XPComDllOSX104_EXTENDS = XPComDll
+ TEMPLATE_XPComDllOSX104_CXXFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CXXFLAGS),$(TEMPLATE_XPComDll_CXXFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_4_CXXFLAGS)
+ TEMPLATE_XPComDllOSX104_CFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CFLAGS),$(TEMPLATE_XPComDll_CFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_4_CFLAGS)
+ TEMPLATE_XPComDllOSX104_LDFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_LDFLAGS),$(TEMPLATE_XPComDll_LDFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_4_LDFLAGS)
+ TEMPLATE_XPComDllOSX104_DEFS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_DEFS),$(TEMPLATE_XPComDll_DEFS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_4_DEFS)
+ TEMPLATE_XPComDllOSX104_INCS.darwin = $(VBOX_PATH_MACOSX_SDK_10_4)/Developer/Headers/FlatCarbon
+endif
+
+#
+# Template for building VBoxPython against the Mac OS X 10.5 SDK.
+# ASSUMES that the SDK bits are in the .darwin properties we're overriding below.
+#
+TEMPLATE_XPComDllOSX105 = XPCOM libraries (shared) built against the Mac OS X 10.5 SDK
+TEMPLATE_XPComDllOSX105_EXTENDS = XPComDll
+TEMPLATE_XPComDllOSX105_CXXFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CXXFLAGS),$(TEMPLATE_XPComDll_CXXFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_5_CXXFLAGS)
+TEMPLATE_XPComDllOSX105_CFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CFLAGS),$(TEMPLATE_XPComDll_CFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_5_CFLAGS)
+TEMPLATE_XPComDllOSX105_LDFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_LDFLAGS),$(TEMPLATE_XPComDll_LDFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_5_LDFLAGS)
+TEMPLATE_XPComDllOSX105_DEFS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_DEFS),$(TEMPLATE_XPComDll_DEFS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_5_DEFS)
+TEMPLATE_XPComDllOSX105_INCS.darwin = $(VBOX_PATH_MACOSX_SDK_10_5)/Developer/Headers/FlatCarbon
+
+#
+# Template for building VBoxPython against the Mac OS X 10.6 SDK.
+# ASSUMES that the SDK bits are in the .darwin properties we're overriding below.
+#
+TEMPLATE_XPComDllOSX106 = XPCOM libraries (shared) built against the Mac OS X 10.6 SDK
+TEMPLATE_XPComDllOSX106_EXTENDS = XPComDll
+TEMPLATE_XPComDllOSX106_CXXFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CXXFLAGS),$(TEMPLATE_XPComDll_CXXFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_6_CXXFLAGS)
+TEMPLATE_XPComDllOSX106_CFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CFLAGS),$(TEMPLATE_XPComDll_CFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_6_CFLAGS)
+TEMPLATE_XPComDllOSX106_LDFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_LDFLAGS),$(TEMPLATE_XPComDll_LDFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_6_LDFLAGS)
+TEMPLATE_XPComDllOSX106_DEFS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_DEFS),$(TEMPLATE_XPComDll_DEFS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_6_DEFS)
+TEMPLATE_XPComDllOSX106_INCS.darwin = $(VBOX_PATH_MACOSX_SDK_10_6)/Developer/Headers/FlatCarbon
+
+#
+# Template for building VBoxPython against the Mac OS X 10.7 SDK.
+# ASSUMES that the SDK bits are in the .darwin properties we're overriding below.
+#
+TEMPLATE_XPComDllOSX107 = XPCOM libraries (shared) built against the Mac OS X 10.7 SDK
+TEMPLATE_XPComDllOSX107_EXTENDS = XPComDll
+TEMPLATE_XPComDllOSX107_TOOL = LLVMGXX42MACHO
+TEMPLATE_XPComDllOSX107_CXXFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CXXFLAGS),$(TEMPLATE_XPComDll_CXXFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_7_CXXFLAGS)
+TEMPLATE_XPComDllOSX107_CFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_CFLAGS),$(TEMPLATE_XPComDll_CFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_7_CFLAGS)
+TEMPLATE_XPComDllOSX107_LDFLAGS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_LDFLAGS),$(TEMPLATE_XPComDll_LDFLAGS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_7_LDFLAGS)
+TEMPLATE_XPComDllOSX107_DEFS.darwin = $(filter-out $(VBOX_DARWIN_DEF_SDK_DEFS),$(TEMPLATE_XPComDll_DEFS.darwin)) $(VBOX_DARWIN_DEF_SDK_10_7_DEFS)
+TEMPLATE_XPComDllOSX107_INCS.darwin = $(VBOX_PATH_MACOSX_SDK_10_7)/Developer/Headers/FlatCarbon
+
+
+#
+# Creates a x86 target for an XPCOM target if so desired.
+# The target is specified as the first argument: $(evalcall VBOX_XPCOM_X86,target).
+#
+ifdef VBOX_WITH_32_ON_64_MAIN_API
+ define VBOX_XPCOM_X86
+ $(1)-x86_TEMPLATE := $(strip $($(1)_TEMPLATE))-x86
+ $(1)-x86_EXTENDS := $(1)
+ endef
+else
+ define VBOX_XPCOM_X86
+ endef
+endif
+
+# Corresponding 32-bit template(s).
+TEMPLATE_XPComDll-x86 = 32-bit XPCOM libraries (shared)
+TEMPLATE_XPComDll-x86_EXTENDS = XPComDll
+TEMPLATE_XPComDll-x86_BLD_TRG_ARCH = x86
+TEMPLATE_XPComDll-x86_DEFS = $(TEMPLATE_XPComDll_DEFS) VBOX_IN_32_ON_64_MAIN_API
+TEMPLATE_XPComDll-x86_LIBS = $(subst $(LIB_RUNTIME),$(VBOX_LIB_RUNTIME_X86),$(TEMPLATE_XPComDll_LIBS))
+
+TEMPLATE_XPComDllYasm-x86 = 32-bit XPCOM libraries (shared) with YASM as assembler.
+TEMPLATE_XPComDllYasm-x86_EXTENDS = XPComDllYasm
+TEMPLATE_XPComDllYasm-x86_BLD_TRG_ARCH = x86
+TEMPLATE_XPComDllYasm-x86_DEFS = $(TEMPLATE_XPComDllYasm_DEFS) VBOX_IN_32_ON_64_MAIN_API
+TEMPLATE_XPComDllYasm-x86_LIBS = $(subst $(LIB_RUNTIME),$(VBOX_LIB_RUNTIME_X86),$(TEMPLATE_XPComDllYasm_LIBS))
+
+
+#
+# The list of XPCOM's IDL files.
+# This is used by the java bindings as well as the XPCOM build.
+#
+XPCOM_IDLFILES = \
+ xpcom/base/nsIDebug.idl \
+ xpcom/base/nsIInterfaceRequestor.idl \
+ xpcom/base/nsIMemory.idl \
+ xpcom/base/nsIProgrammingLanguage.idl \
+ xpcom/base/nsISupports.idl \
+ xpcom/base/nsITraceRefcnt.idl \
+ xpcom/base/nsIWeakReference.idl \
+ xpcom/base/nsIConsoleMessage.idl \
+ xpcom/base/nsIConsoleService.idl \
+ xpcom/base/nsIConsoleListener.idl \
+ xpcom/base/nsIErrorService.idl \
+ xpcom/base/nsIException.idl \
+ xpcom/base/nsIExceptionService.idl \
+ xpcom/base/nsrootidl.idl \
+ xpcom/components/nsIClassInfo.idl \
+ xpcom/components/nsIComponentRegistrar.idl \
+ xpcom/components/nsIFactory.idl \
+ xpcom/components/nsIModule.idl \
+ xpcom/components/nsIServiceManager.idl \
+ xpcom/components/nsIComponentManager.idl \
+ xpcom/components/nsICategoryManager.idl \
+ xpcom/components/nsIComponentLoader.idl \
+ xpcom/components/nsINativeComponentLoader.idl \
+ xpcom/components/nsIComponentManagerObsolete.idl \
+ xpcom/components/nsIComponentLoaderManager.idl \
+ xpcom/ds/nsISupportsArray.idl \
+ xpcom/ds/nsICollection.idl \
+ xpcom/ds/nsISerializable.idl \
+ xpcom/ds/nsIEnumerator.idl \
+ xpcom/ds/nsISimpleEnumerator.idl \
+ xpcom/ds/nsIObserverService.idl \
+ xpcom/ds/nsIObserver.idl \
+ xpcom/ds/nsIAtom.idl \
+ xpcom/ds/nsIAtomService.idl \
+ xpcom/ds/nsIProperties.idl \
+ xpcom/ds/nsIPersistentProperties2.idl \
+ xpcom/ds/nsIRecyclingAllocator.idl \
+ xpcom/ds/nsIStringEnumerator.idl \
+ xpcom/ds/nsISupportsPrimitives.idl \
+ xpcom/ds/nsISupportsIterators.idl \
+ xpcom/ds/nsIVariant.idl \
+ xpcom/ds/nsITimelineService.idl \
+ xpcom/ds/nsIArray.idl \
+ xpcom/ds/nsIPropertyBag.idl \
+ xpcom/ds/nsIHashable.idl \
+ xpcom/io/nsIDirectoryService.idl \
+ xpcom/io/nsIDirectoryEnumerator.idl \
+ xpcom/io/nsIFile.idl \
+ xpcom/io/nsILocalFile.idl \
+ xpcom/io/nsILocalFileMac.idl \
+ xpcom/io/nsIInputStream.idl \
+ xpcom/io/nsIObjectInputStream.idl \
+ xpcom/io/nsIBinaryInputStream.idl \
+ xpcom/io/nsIObjectOutputStream.idl \
+ xpcom/io/nsIBinaryOutputStream.idl \
+ xpcom/io/nsIOutputStream.idl \
+ xpcom/io/nsIStreamBufferAccess.idl \
+ xpcom/io/nsIByteArrayInputStream.idl \
+ xpcom/io/nsISeekableStream.idl \
+ xpcom/io/nsIFastLoadFileControl.idl \
+ xpcom/io/nsIFastLoadService.idl \
+ xpcom/io/nsIInputStreamTee.idl \
+ xpcom/io/nsIMultiplexInputStream.idl \
+ xpcom/io/nsIPipe.idl \
+ xpcom/io/nsIAsyncInputStream.idl \
+ xpcom/io/nsIAsyncOutputStream.idl \
+ xpcom/io/nsIScriptableInputStream.idl \
+ xpcom/io/nsIStorageStream.idl \
+ xpcom/io/nsIStringStream.idl \
+ xpcom/io/nsILineInputStream.idl \
+ xpcom/proxy/public/nsIProxyObjectManager.idl \
+ xpcom/threads/nsIEventQueueService.idl \
+ xpcom/threads/nsIEventQueue.idl \
+ xpcom/threads/nsIEventTarget.idl \
+ xpcom/threads/nsIRunnable.idl \
+ xpcom/threads/nsIThread.idl \
+ xpcom/threads/nsITimer.idl \
+ xpcom/threads/nsIEnvironment.idl \
+ xpcom/threads/nsITimerInternal.idl \
+ xpcom/threads/nsITimerManager.idl \
+ xpcom/threads/nsIProcess.idl \
+ xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl \
+ xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl \
+ xpcom/reflect/xptinfo/public/nsIXPTLoader.idl \
+ ipc/ipcd/client/public/ipcIService.idl \
+ ipc/ipcd/client/public/ipcIMessageObserver.idl \
+ ipc/ipcd/client/public/ipcIClientObserver.idl \
+ ipc/ipcd/extensions/lock/public/ipcILockService.idl \
+ ipc/ipcd/extensions/transmngr/public/ipcITransactionService.idl \
+ ipc/ipcd/extensions/dconnect/public/ipcIDConnectService.idl \
+ ipc/ipcd/extensions/transmngr/public/ipcITransactionObserver.idl
+
+#
+# The include path for the XPCOM IDL files above.
+#
+XPIDL_INCS = \
+ -I $(VBOX_PATH_XPCOM_SRC)/xpcom/base/ \
+ -I $(VBOX_PATH_XPCOM_SRC)/xpcom/ds/ \
+ -I $(VBOX_PATH_XPCOM_SRC)/xpcom/components/ \
+ -I $(VBOX_PATH_XPCOM_SRC)/xpcom/io/ \
+ -I $(VBOX_PATH_XPCOM_SRC)/xpcom/threads/ \
+ -I $(VBOX_PATH_XPCOM_SRC)/xpcom/reflect/xptinfo/public/
+
diff --git a/src/libs/xpcom18a4/Makefile.kmk b/src/libs/xpcom18a4/Makefile.kmk
new file mode 100644
index 00000000..b12dccfe
--- /dev/null
+++ b/src/libs/xpcom18a4/Makefile.kmk
@@ -0,0 +1,1485 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for XPCOM.
+#
+
+#
+# Copyright (C) 2006-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+# Make sure our Config.kmk is included.
+ifndef VBOX_PATH_XPCOM_SRC
+ include $(PATH_SUB_CURRENT)/Config.kmk
+endif
+
+#
+# Globals
+#
+
+# File for filtering out C symbols from the XPCOM library. Used to avoid
+# symbol namespace pollution, causing trouble with system libraries.
+XPCOM_C_NAMESPACE_MAP = $(VBOX_PATH_XPCOM_SRC)/xpcom-namespace-cleanup.map
+ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ # At the moment, only Solaris uses the generated map file. GNU ld is smart
+ # enough to handle symbol wildcards itself.
+ if1of ($(KBUILD_TARGET), solaris)
+ XPCOM_C_NAMESPACE_MAP = $(PATH_TARGET)/xpcom-namespace-cleanup.map
+ OTHER_CLEAN += $(XPCOM_C_NAMESPACE_MAP)
+ endif
+endif
+
+# @todo check whether VBoxXPCOMIPCC.so or VBoxXPCOMIPCD contain undefined
+# symbols starting with NS_, PL_, PR_ or XPT. Would move the test time failure
+# when missing a symbol renaming to a build time failure. Likewise, there
+# should be a check whether VBoxXPCOM.so contains global C symbols (at least
+# where the whitelisting of symbols via the map file is not used).
+
+#
+# Header installs.
+#
+INSTALLS += \
+ NSPRPUB-HEADERS \
+ NSPRPUB-MD-HEADERS \
+ NSPRPUB-OBS-HEADERS \
+ NSPRPUB-PRIV-HEADERS \
+ STRING-HEADERS \
+ XPCOM-HEADERS \
+ IPCD-HEADERS
+
+#
+# The IDL compiler, typelib linker and xpt files.
+#
+BLDPROGS += \
+ xpidl \
+ xpt_link
+
+BLDDIRS += \
+ $(PATH_TARGET)/VBox-xpcom-xpt-files/
+
+#
+# Always build the VBoxXPCOM import library.
+#
+IMPORT_LIBS += VBoxXPCOMImp
+
+#
+# We build several libraries so that any linker command line
+# length restrictions limit will be avoided. (Solaris, Mac?)
+#
+if !defined(VBOX_ONLY_SDK) && (!defined(VBOX_ONLY_EXTPACKS) || !defined(VBOX_ONLY_EXTPACKS_USE_IMPLIBS))
+
+ VBOX_XPCOM_LIBRARIES := \
+ VBox-xpcom-nspr \
+ VBox-xpcom-typelib \
+ VBox-xpcom-string \
+ VBox-xpcom-base \
+ VBox-xpcom-ds \
+ VBox-xpcom-io \
+ VBox-xpcom-components \
+ VBox-xpcom-threads \
+ VBox-xpcom-xptinfo \
+ VBox-xpcom-xptcall \
+ VBox-xpcom-proxy \
+ VBox-xpcom-ipcshared \
+ VBoxXPCOMGlue_s \
+ $(if $(VBOX_WITH_XPCOM_GLUE_WHICH_IS_UNUSED),VBoxXPCOMGlue,)
+ LIBRARIES += $(VBOX_XPCOM_LIBRARIES)
+
+ VBOX_XPCOM_DLLS := \
+ VBoxXPCOM \
+ VBoxXPCOMIPCC
+ DLLS += $(VBOX_XPCOM_DLLS)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ LIBRARIES += $(addsuffix -x86,$(VBOX_XPCOM_LIBRARIES))
+ DLLS += $(addsuffix -x86,$(VBOX_XPCOM_DLLS))
+ endif
+
+
+ ifdef VBOX_WITH_TESTCASES
+ PROGRAMS += \
+ tstnsIFileTest \
+ tstTestArray \
+ tstTestAutoLock \
+ tstTestCOMPtr \
+ tstTestCOMPtrEq \
+ tstTestCRT \
+ tstTestFactory \
+ tstTestHashtables \
+ tstTestID \
+ tstTestObserverService \
+ tstTestPipes \
+ tstTestThreads \
+ tstTestXPIDLString \
+ tstTestXPTCInvoke \
+ tstTestDeque \
+ tstTestAutoPtr \
+ tstTestMinStringAPI \
+ tstTestStrings \
+ tstPrimitiveTest
+ # tstnsIFileEnumerator
+ # tstTestAtoms
+ # tstTestServMgr
+ # tstTestCallTemplates
+ # tstTestPermanentAtoms
+ # tstSimpleTypeLib
+ # tstXptDump
+ # tstXptLink
+ endif # VBOX_WITH_TESTCASES
+ PROGRAMS += VBoxXPCOMIPCD
+
+endif # !VBOX_ONLY_SDK && (!defined(VBOX_ONLY_EXTPACKS) || !defined(VBOX_ONLY_EXTPACKS_USE_IMPLIBS))
+
+
+
+
+#
+# SDK headers - lot's of files to install...
+#
+# Tip: If you are going to remove files here, you might
+# wish to do a `kmk uninstall' first to avoid have
+# obsoleted files in the $(INST_SDK) directory.
+#
+NSPRPUB-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/nsprpub/
+NSPRPUB-HEADERS_IFFLAGS = -m 644
+NSPRPUB-HEADERS_SOURCES = \
+ nsprpub/pr/include/nspr.h \
+ nsprpub/lib/ds/plarena.h \
+ nsprpub/lib/ds/plarenas.h \
+ nsprpub/lib/libc/include/plbase64.h \
+ nsprpub/lib/libc/include/plerror.h \
+ nsprpub/lib/libc/include/plgetopt.h \
+ nsprpub/lib/ds/plhash.h \
+ nsprpub/lib/libc/include/plresolv.h \
+ nsprpub/lib/libc/include/plstr.h \
+ nsprpub/pr/include/pratom.h \
+ nsprpub/pr/include/prbit.h \
+ nsprpub/pr/include/prclist.h \
+ nsprpub/pr/include/prcmon.h \
+ nsprpub/pr/include/prcountr.h \
+ nsprpub/pr/include/prcvar.h \
+ nsprpub/pr/include/prdtoa.h \
+ nsprpub/pr/include/prenv.h \
+ nsprpub/pr/include/prerr.h \
+ nsprpub/pr/include/prerror.h \
+ nsprpub/pr/include/prinet.h \
+ nsprpub/pr/include/prinit.h \
+ nsprpub/pr/include/prinrval.h \
+ nsprpub/pr/include/prio.h \
+ nsprpub/pr/include/pripcsem.h \
+ nsprpub/pr/include/prlink.h \
+ nsprpub/pr/include/prlock.h \
+ nsprpub/pr/include/prlog.h \
+ nsprpub/pr/include/prlong.h \
+ nsprpub/pr/include/prmem.h \
+ nsprpub/pr/include/prmon.h \
+ nsprpub/pr/include/prmwait.h \
+ nsprpub/pr/include/prnetdb.h \
+ nsprpub/pr/include/prolock.h \
+ nsprpub/pr/include/prpdce.h \
+ nsprpub/pr/include/prprf.h \
+ nsprpub/pr/include/prproces.h \
+ nsprpub/pr/include/prrng.h \
+ nsprpub/pr/include/prrwlock.h \
+ nsprpub/pr/include/prshm.h \
+ nsprpub/pr/include/prshma.h \
+ nsprpub/pr/include/prsystem.h \
+ nsprpub/pr/include/prthread.h \
+ nsprpub/pr/include/prtime.h \
+ nsprpub/pr/include/prtpool.h \
+ nsprpub/pr/include/prtrace.h \
+ nsprpub/pr/include/prtypes.h \
+ nsprpub/pr/include/prvrsion.h \
+ nsprpub/pr/include/prwin16.h \
+ nsprpub/pr/include/md/_vbox.cfg=>prcpucfg.h
+NSPRPUB-MD-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/nsprpub/md/
+NSPRPUB-MD-HEADERS_IFFLAGS = -m 644
+NSPRPUB-MD-HEADERS_SOURCES = \
+ nsprpub/pr/include/md/_iprt_atomic.h \
+ nsprpub/pr/include/md/_darwin.h \
+ nsprpub/pr/include/md/_freebsd.h \
+ nsprpub/pr/include/md/_linux.h \
+ nsprpub/pr/include/md/_macos.h \
+ nsprpub/pr/include/md/_netbsd.h \
+ nsprpub/pr/include/md/_openbsd.h \
+ nsprpub/pr/include/md/_os2_errors.h \
+ nsprpub/pr/include/md/_os2.h \
+ nsprpub/pr/include/md/_pcos.h \
+ nsprpub/pr/include/md/_solaris.h \
+ nsprpub/pr/include/md/_unix_errors.h \
+ nsprpub/pr/include/md/_unixos.h \
+ nsprpub/pr/include/md/_pth.h \
+ nsprpub/pr/include/md/prosdep.h \
+ \
+ nsprpub/pr/include/md/_freebsd.cfg \
+ nsprpub/pr/include/md/_linux.cfg \
+ nsprpub/pr/include/md/_darwin.cfg \
+ nsprpub/pr/include/md/_netbsd.cfg \
+ nsprpub/pr/include/md/_openbsd.cfg \
+ nsprpub/pr/include/md/_os2.cfg \
+ nsprpub/pr/include/md/_solaris32.cfg \
+ nsprpub/pr/include/md/_solaris64.cfg
+NSPRPUB-OBS-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/nsprpub/obsolete/
+NSPRPUB-OBS-HEADERS_IFFLAGS = -m 644
+NSPRPUB-OBS-HEADERS_SOURCES = \
+ nsprpub/pr/include/obsolete/pralarm.h \
+ nsprpub/pr/include/obsolete/probslet.h \
+ nsprpub/pr/include/obsolete/protypes.h \
+ nsprpub/pr/include/obsolete/prsem.h
+
+NSPRPUB-PRIV-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/nsprpub/private/
+NSPRPUB-PRIV-HEADERS_IFFLAGS = -m 644
+NSPRPUB-PRIV-HEADERS_SOURCES = \
+ nsprpub/pr/include/private/pprio.h \
+ nsprpub/pr/include/private/pprthred.h \
+ nsprpub/pr/include/private/prpriv.h
+
+STRING-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/string/
+STRING-HEADERS_IFFLAGS = -m 644
+STRING-HEADERS_SOURCES = \
+ xpcom/string/public/nsAString.h \
+ xpcom/string/public/nsAlgorithm.h \
+ xpcom/string/public/nsCharTraits.h \
+ xpcom/string/public/nsDependentString.h \
+ xpcom/string/public/nsDependentSubstring.h \
+ xpcom/string/public/nsEmbedString.h \
+ xpcom/string/public/nsLiteralString.h \
+ xpcom/string/public/nsObsoleteAString.h \
+ xpcom/string/public/nsPrintfCString.h \
+ xpcom/string/public/nsPromiseFlatString.h \
+ xpcom/string/public/nsReadableUtils.h \
+ xpcom/string/public/nsString.h \
+ xpcom/string/public/nsStringAPI.h \
+ xpcom/string/public/nsStringFwd.h \
+ xpcom/string/public/nsStringIterator.h \
+ xpcom/string/public/nsSubstring.h \
+ xpcom/string/public/nsSubstringTuple.h \
+ xpcom/string/public/nsTAString.h \
+ xpcom/string/public/nsTDependentString.h \
+ xpcom/string/public/nsTDependentSubstring.h \
+ xpcom/string/public/nsTObsoleteAString.h \
+ xpcom/string/public/nsTPromiseFlatString.h \
+ xpcom/string/public/nsTString.h \
+ xpcom/string/public/nsTSubstring.h \
+ xpcom/string/public/nsTSubstringTuple.h \
+ xpcom/string/public/nsUTF8Utils.h \
+ xpcom/string/public/nsXPIDLString.h \
+ xpcom/string/public/string-template-def-char.h \
+ xpcom/string/public/string-template-def-unichar.h \
+ xpcom/string/public/string-template-undef.h
+
+XPCOM-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/xpcom/
+XPCOM-HEADERS_IFFLAGS = -m 644
+XPCOM-HEADERS_SOURCES = \
+ xpcom/base/nsAgg.h \
+ xpcom/io/nsAppDirectoryServiceDefs.h \
+ xpcom/ds/nsArray.h \
+ xpcom/ds/nsArrayEnumerator.h \
+ xpcom/ds/nsAtomService.h \
+ xpcom/ds/nsAutoBuffer.h \
+ xpcom/threads/nsAutoLock.h \
+ xpcom/base/nsAutoPtr.h \
+ xpcom/ds/nsBaseHashtable.h \
+ xpcom/ds/nsCOMArray.h \
+ xpcom/ds/nsCRT.h \
+ xpcom/components/nsCategoryManagerUtils.h \
+ xpcom/ds/nsCheapSets.h \
+ xpcom/ds/nsClassHashtable.h \
+ xpcom/base/nsCom.h \
+ xpcom/components/nsComponentManagerObsolete.h \
+ xpcom/components/nsComponentManagerUtils.h \
+ xpcom/ds/nsCppSharedAllocator.h \
+ xpcom/ds/nsDataHashtable.h \
+ xpcom/base/nsDebugImpl.h \
+ xpcom/ds/nsDeque.h \
+ xpcom/io/nsDirectoryService.h \
+ xpcom/io/nsDirectoryServiceDefs.h \
+ xpcom/io/nsDirectoryServiceUtils.h \
+ xpcom/ds/nsDoubleHashtable.h \
+ xpcom/ds/nsEnumeratorUtils.h \
+ xpcom/base/nsError.h \
+ xpcom/io/nsEscape.h \
+ xpcom/threads/nsEventQueueUtils.h \
+ xpcom/io/nsFastLoadPtr.h \
+ xpcom/io/nsFastLoadService.h \
+ xpcom/ds/nsFixedSizeAllocator.h \
+ xpcom/ds/nsHashKeys.h \
+ xpcom/ds/nsHashSets.h \
+ xpcom/ds/nsHashtable.h \
+ xpcom/base/nsIAllocator.h \
+ xpcom/ds/nsIByteBuffer.h \
+ xpcom/base/nsID.h \
+ xpcom/base/nsIID.h \
+ xpcom/components/nsIServiceManagerObsolete.h \
+ xpcom/components/nsIServiceManagerUtils.h \
+ xpcom/base/nsISupportsBase.h \
+ xpcom/base/nsISupportsObsolete.h \
+ xpcom/ds/nsIUnicharBuffer.h \
+ xpcom/io/nsIUnicharInputStream.h \
+ xpcom/ds/nsInt64.h \
+ xpcom/ds/nsInterfaceHashtable.h \
+ xpcom/io/nsLinebreakConverter.h \
+ xpcom/io/nsLocalFile.h \
+ xpcom/io/nsLocalFileUnix.h \
+ xpcom/io/nsLocalFileOS2.h \
+ xpcom/io/nsLocalFileOSX.h \
+ xpcom/components/nsModule.h \
+ xpcom/io/nsMultiplexInputStream.h \
+ xpcom/io/nsNativeCharsetUtils.h \
+ xpcom/components/nsNativeComponentLoader.h \
+ xpcom/ds/nsObserverService.h \
+ xpcom/components/nsObsoleteModuleLoading.h \
+ xpcom/threads/nsProcess.h \
+ xpcom/proxy/public/nsProxiedService.h \
+ xpcom/proxy/public/nsProxyEvent.h \
+ xpcom/proxy/public/nsProxyRelease.h \
+ xpcom/ds/nsQuickSort.h \
+ xpcom/ds/nsRecyclingAllocator.h \
+ xpcom/ds/nsRefPtrHashtable.h \
+ xpcom/io/nsScriptableInputStream.h \
+ xpcom/ds/nsStaticAtom.h \
+ xpcom/components/nsStaticComponent.h \
+ xpcom/ds/nsStaticNameTable.h \
+ xpcom/io/nsStorageStream.h \
+ xpcom/io/nsStreamUtils.h \
+ xpcom/ds/nsStringEnumerator.h \
+ xpcom/io/nsStringIO.h \
+ xpcom/io/nsStringStream.h \
+ xpcom/ds/nsSupportsArray.h \
+ xpcom/ds/nsSupportsPrimitives.h \
+ xpcom/ds/nsTHashtable.h \
+ xpcom/ds/nsTextFormatter.h \
+ xpcom/ds/nsTime.h \
+ xpcom/base/nsTraceRefcntImpl.h \
+ xpcom/ds/nsUnitConversion.h \
+ xpcom/ds/nsValueArray.h \
+ xpcom/ds/nsVariant.h \
+ xpcom/ds/nsVoidArray.h \
+ xpcom/base/nsWeakPtr.h \
+ xpcom/build/nsXPCOM.h \
+ xpcom/build/nsXPCOMCID.h \
+ xpcom/base/nscore.h \
+ xpcom/ds/pldhash.h \
+ xpcom/threads/plevent.h \
+ xpcom/components/xcDll.h \
+ xpcom/typelib/xpt/public/xpt_arena.h \
+ xpcom/typelib/xpt/public/xpt_struct.h \
+ xpcom/typelib/xpt/public/xpt_xdr.h \
+ xpcom/reflect/xptcall/public/xptcall.h \
+ xpcom/reflect/xptcall/public/xptcstubsdecl.inc \
+ xpcom/reflect/xptcall/public/xptcstubsdef.inc \
+ xpcom/reflect/xptinfo/public/xptinfo.h \
+ \
+ xpcom/glue/nsIInterfaceRequestorUtils.h \
+ xpcom/glue/nsISupportsImpl.h \
+ xpcom/glue/nsISupportsUtils.h \
+ xpcom/glue/nsIWeakReferenceUtils.h \
+ \
+ xpcom/glue/nsCOMPtr.h \
+ xpcom/glue/nsDebug.h \
+ xpcom/glue/nsGenericFactory.h \
+ xpcom/glue/nsIGenericFactory.h \
+ xpcom/glue/nsMemory.h \
+ xpcom/glue/nsTraceRefcnt.h \
+ xpcom/glue/nsWeakReference.h \
+ \
+ xpcom/glue/standalone/nsXPCOMGlue.h \
+ \
+ xpcom-config.h
+
+IPCD-HEADERS_INST = $(INST_SDK)bindings/xpcom/include/ipcd/
+IPCD-HEADERS_IFFLAGS = -m 644
+IPCD-HEADERS_SOURCES = \
+ ipc/ipcd/client/public/ipcCID.h \
+ ipc/ipcd/extensions/lock/public/ipcLockCID.h \
+ ipc/ipcd/util/public/ipcMessageReader.h \
+ ipc/ipcd/util/public/ipcMessageWriter.h \
+ ipc/ipcd/daemon/public/ipcModule.h \
+ ipc/ipcd/daemon/public/ipcModuleUtil.h \
+ ipc/ipcd/client/public/ipcdclient.h
+
+
+#
+# The IDL compiler.
+#
+# We build it statically because we cannot rely on additional .a files
+# like in the original build
+#
+xpidl_TEMPLATE = XPComBldProg
+xpidl_DEFS = EXPORT_XPT_API
+## @todo This assumes HOST == TARGET.
+xpidl_INST = $(INST_BIN)
+## Obsolete hack: MacPorts is 32-bit on 10.5 and 64-bit on 10.6. Set your KBUILD_HOST_ARCH env.vars. accordingly.
+#if "$(KBUILD_HOST).$(KBUILD_HOST_ARCH)" == "darwin.amd64" && defined(VBOX_MACOS_10_5_WORKAROUND)
+# xpidl_BLD_TRG_ARCH = x86
+# ## @todo kBuild ticket 84 workarounds:
+# xpidl_DEFS.x86 = $(TEMPLATE_XPComBldProg_DEFS.x86)
+# xpidl_CFLAGS.x86 = $(TEMPLATE_XPComBldProg_CFLAGS.x86)
+# xpidl_CXXFLAGS.x86 = $(TEMPLATE_XPComBldProg_CXXFLAGS.x86)
+# xpidl_LDFLAGS.x86 = $(TEMPLATE_XPComBldProg_LDFLAGS.x86)
+#endif
+ifdef VBOX_WITH_JAVA_SUPPORT_IN_XPIDL
+ xpidl_DEFS += VBOX_XPIDL_EMULATE_GENJIFACES VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+endif
+xpidl_SOURCES = \
+ xpcom/typelib/xpidl/xpidl.c \
+ xpcom/typelib/xpidl/xpidl_idl.c \
+ xpcom/typelib/xpidl/xpidl_util.c \
+ xpcom/typelib/xpidl/xpidl_header.c \
+ xpcom/typelib/xpidl/xpidl_typelib.c \
+ xpcom/typelib/xpidl/xpidl_doc.c \
+ xpcom/typelib/xpidl/xpidl_java.c \
+ xpcom/typelib/xpt/src/xpt_arena.c \
+ xpcom/typelib/xpt/src/xpt_struct.c \
+ xpcom/typelib/xpt/src/xpt_xdr.c
+
+ifeq ($(KBUILD_TARGET),os2)
+ # glib and libIDL needed by XPCOM on OS/2.
+ ifeq ($(VBOX_PATH_GLIB),)
+ VBOX_PATH_GLIB := $(lastword $(sort $(wildcard $(KBUILD_DEVTOOLS_TRG)/glibidl/*/glibidl/gcc335)))
+ endif
+ VBOX_PATH_LIBIDL ?= $(VBOX_PATH_GLIB)
+ ifeq ($(wildcard $(VBOX_PATH_GLIB)),)
+ $(warning VBOX_PATH_GLIB is "$(VBOX_PATH_GLIB)" which is not a valid directory!)
+ endif
+ ifeq ($(wildcard $(VBOX_PATH_LIBIDL)),)
+ $(warning VBOX_PATH_LIBIDL is "$(VBOX_PATH_LIBIDL)" which is not a valid directory!)
+ endif
+ xpidl_INCS = \
+ $(VBOX_PATH_LIBIDL)/include \
+ $(VBOX_PATH_GLIB)/include
+ xpidl_LIBS = \
+ $(VBOX_PATH_LIBIDL)/lib/libidl.lib \
+ $(VBOX_PATH_LIBIDL)/lib/glib.lib
+ # install necessary DLLs to the same place where xpidl goes
+ INSTALLS += xpidl-DLLS
+ xpidl_ORDERDEPS = $(xpidl-DLLS_1_TARGET)
+ xpidl-DLLS_INST = $(xpidl_INST)
+ # static libraries of these may be provided instead,
+ # so copy DLLs only when they are present
+ xpidl-DLLS_SOURCES += $(wildcard $(VBOX_PATH_GLIB)/lib/glib.dll)
+ xpidl-DLLS_SOURCES += $(wildcard $(VBOX_PATH_LIBIDL)/lib/libIDL.dll)
+else
+ # We do these ONCE.
+ libIDL_config_cflags := $(shell $(VBOX_LIBIDL_CONFIG) --cflags)
+ libIDL_config_libs := $(shell $(VBOX_LIBIDL_CONFIG) --libs)
+ xpidl_CFLAGS = \
+ $(libIDL_config_cflags)
+ if1of ($(KBUILD_HOST), linux solaris)
+ xpidl_LDFLAGS = \
+ $(filter-out -l%,$(libIDL_config_libs))
+ xpidl_LIBS.$(KBUILD_HOST) += \
+ $(subst -l,,$(filter -l%,$(libIDL_config_libs)))
+ else
+ xpidl_LDFLAGS = \
+ $(libIDL_config_libs)
+ endif
+ xpidl_LDFLAGS.linux = \
+ $(VBOX_LD_as_needed)
+endif
+
+#
+# The XPT linker.
+#
+xpt_link_TEMPLATE = XPComBldProg
+xpt_link_SOURCES = \
+ xpcom/typelib/xpt/tools/xpt_link.c \
+ xpcom/typelib/xpt/src/xpt_arena.c \
+ xpcom/typelib/xpt/src/xpt_struct.c \
+ xpcom/typelib/xpt/src/xpt_xdr.c
+
+
+#
+# The NSPR Library.
+#
+VBox-xpcom-nspr_TEMPLATE = XPComDll
+VBox-xpcom-nspr_INSTTYPE = none
+VBox-xpcom-nspr_DEFS = \
+ _NSPR_BUILD_ \
+ HAVE_LCHOWN=1 \
+ HAVE_STRERROR=1 \
+ FORCE_PR_LOG
+VBox-xpcom-nspr_DEFS += \
+ VBOX_USE_IPRT_IN_NSPR
+VBox-xpcom-nspr_DEFS.darwin.amd64 = \
+ VBOX_USE_MORE_IPRT_IN_NSPR
+VBox-xpcom-nspr_DEFS.darwin.arm64 = \
+ VBOX_USE_MORE_IPRT_IN_NSPR
+VBox-xpcom-nspr_DEFS.darwin = \
+ HAVE_BSD_FLOCK=1 \
+ HAVE_SOCKLEN_T=1 \
+ _PR_PTHREADS
+VBox-xpcom-nspr_DEFS.freebsd = \
+ FREEBSD=1 \
+ HAVE_CVAR_BUILT_ON_SEM \
+ _PR_PTHREADS
+## @todo filling in the missing stuff, please don't just copy it from linux.
+# FIXME: LINUX should be defined by _linux.cfg
+VBox-xpcom-nspr_DEFS.linux = \
+ LINUX=1 \
+ _POSIX_SOURCE=1 \
+ _BSD_SOURCE=1 \
+ _SVID_SOURCE=1 \
+ _DEFAULT_SOURCE \
+ _REENTRANT=1 \
+ _LARGEFILE64_SOURCE=1 \
+ HAVE_FCNTL_FILE_LOCKING=1 \
+ HAVE_CVAR_BUILT_ON_SEM \
+ _PR_PTHREADS
+# _BSD_SOURCE is here to keep the Glibc header files happy and make them include the right things
+VBox-xpcom-nspr_DEFS.netbsd = \
+ _PR_PTHREADS
+VBox-xpcom-nspr_DEFS.openbsd = \
+ _PR_PTHREADS
+VBox-xpcom-nspr_DEFS.os2 =
+VBox-xpcom-nspr_DEFS.solaris = \
+ HAVE_FCNTL_FILE_LOCKING=1 \
+ HAVE_SOCKLEN_T=1 \
+ _PR_PTHREADS
+VBox-xpcom-nspr_INCS = \
+ nsprpub/pr/include/private \
+ $(VBox-xpcom-nspr_0_OUTDIR)
+
+VBox-xpcom-nspr_SOURCES = \
+ nsprpub/pr/src/io/prfdcach.c \
+ nsprpub/pr/src/io/prmwait.c \
+ nsprpub/pr/src/io/priometh.c \
+ nsprpub/pr/src/io/pripv6.c \
+ nsprpub/pr/src/io/prmapopt.c \
+ nsprpub/pr/src/io/prlayer.c \
+ nsprpub/pr/src/io/prlog.c \
+ nsprpub/pr/src/io/prmmap.c \
+ nsprpub/pr/src/io/prpolevt.c \
+ nsprpub/pr/src/io/prprf.c \
+ nsprpub/pr/src/io/prscanf.c \
+ nsprpub/pr/src/io/prstdio.c \
+ nsprpub/pr/src/linking/prlink.c \
+ nsprpub/pr/src/malloc/prmalloc.c \
+ nsprpub/pr/src/malloc/prmem.c \
+ nsprpub/pr/src/md/prosdep.c \
+ nsprpub/pr/src/memory/prseg.c \
+ nsprpub/pr/src/memory/prshm.c \
+ nsprpub/pr/src/memory/prshma.c \
+ nsprpub/pr/src/misc/pralarm.c \
+ nsprpub/pr/src/misc/pratom.c \
+ nsprpub/pr/src/misc/prcountr.c \
+ nsprpub/pr/src/misc/prdtoa.c \
+ nsprpub/pr/src/misc/prenv.c \
+ nsprpub/pr/src/misc/prerr.c \
+ nsprpub/pr/src/misc/prerror.c \
+ nsprpub/pr/src/misc/prerrortable.c \
+ nsprpub/pr/src/misc/prinit.c \
+ nsprpub/pr/src/misc/prinrval.c \
+ nsprpub/pr/src/misc/pripc.c \
+ nsprpub/pr/src/misc/prlog2.c \
+ nsprpub/pr/src/misc/prlong.c \
+ nsprpub/pr/src/misc/prnetdb.c \
+ nsprpub/pr/src/misc/prolock.c \
+ nsprpub/pr/src/misc/prrng.c \
+ nsprpub/pr/src/misc/prsystem.c \
+ nsprpub/pr/src/misc/prtime.c \
+ nsprpub/pr/src/misc/prthinfo.c \
+ nsprpub/pr/src/misc/prtpool.c \
+ nsprpub/pr/src/misc/prtrace.c \
+ nsprpub/pr/src/threads/prcmon.c \
+ nsprpub/pr/src/threads/prrwlock.c \
+ nsprpub/pr/src/threads/prtpd.c \
+ nsprpub/pr/src/prvrsion.c \
+ nsprpub/lib/ds/plarena.c \
+ nsprpub/lib/ds/plhash.c \
+ nsprpub/lib/libc/src/strlen.c \
+ nsprpub/lib/libc/src/strcpy.c \
+ nsprpub/lib/libc/src/strdup.c \
+ nsprpub/lib/libc/src/strcat.c \
+ nsprpub/lib/libc/src/strcmp.c \
+ nsprpub/lib/libc/src/strccmp.c \
+ nsprpub/lib/libc/src/strchr.c \
+ nsprpub/lib/libc/src/strpbrk.c \
+ nsprpub/lib/libc/src/strstr.c \
+ nsprpub/lib/libc/src/strcstr.c \
+ nsprpub/lib/libc/src/strtok.c \
+ nsprpub/lib/libc/src/base64.c \
+ nsprpub/lib/libc/src/plerror.c \
+ nsprpub/lib/libc/src/plgetopt.c
+
+ifeq ($(filter-out darwin freebsd linux netbsd openbsd solaris,$(KBUILD_TARGET)),) # unixish
+ VBox-xpcom-nspr_SOURCES += \
+ nsprpub/pr/src/md/unix/unix.c \
+ nsprpub/pr/src/md/unix/unix_errors.c \
+ nsprpub/pr/src/md/unix/uxproces.c \
+ nsprpub/pr/src/md/unix/uxrng.c \
+ nsprpub/pr/src/md/unix/uxshm.c \
+ nsprpub/pr/src/md/unix/uxwrap.c \
+ nsprpub/pr/src/pthreads/ptio.c \
+ nsprpub/pr/src/pthreads/ptsynch.c \
+ nsprpub/pr/src/pthreads/ptthread.c \
+ nsprpub/pr/src/pthreads/ptmisc.c
+endif
+
+VBox-xpcom-nspr_SOURCES.darwin = nsprpub/pr/src/md/unix/darwin.c
+VBox-xpcom-nspr_SOURCES.darwin.x86 = nsprpub/pr/src/md/unix/os_Darwin_x86.s
+
+VBox-xpcom-nspr_SOURCES.freebsd = nsprpub/pr/src/md/unix/freebsd.c
+
+VBox-xpcom-nspr_SOURCES.linux = nsprpub/pr/src/md/unix/linux.c
+VBox-xpcom-nspr_SOURCES.linux.x86 = nsprpub/pr/src/md/unix/os_Linux_x86.s
+VBox-xpcom-nspr_SOURCES.linux.amd64 = nsprpub/pr/src/md/unix/os_Linux_x86_64.s
+
+VBox-xpcom-nspr_SOURCES.os2 = \
+ nsprpub/pr/src/io/prdir.c \
+ nsprpub/pr/src/io/prfile.c \
+ nsprpub/pr/src/io/prio.c \
+ nsprpub/pr/src/io/prsocket.c \
+ nsprpub/pr/src/md/os2/os2misc.c \
+ nsprpub/pr/src/md/os2/os2sem.c \
+ nsprpub/pr/src/md/os2/os2inrval.c \
+ nsprpub/pr/src/md/os2/os2gc.c \
+ nsprpub/pr/src/md/os2/os2thred.c \
+ nsprpub/pr/src/md/os2/os2io.c \
+ nsprpub/pr/src/md/os2/os2cv.c \
+ nsprpub/pr/src/md/os2/os2sock.c \
+ nsprpub/pr/src/md/os2/os2_errors.c \
+ nsprpub/pr/src/md/os2/os2poll.c \
+ nsprpub/pr/src/md/os2/os2rng.c \
+ nsprpub/pr/src/threads/prdump.c \
+ nsprpub/pr/src/threads/prmon.c \
+ nsprpub/pr/src/threads/prsem.c \
+ nsprpub/pr/src/threads/prcthr.c \
+ nsprpub/pr/src/threads/combined/prucpu.c \
+ nsprpub/pr/src/threads/combined/prucv.c \
+ nsprpub/pr/src/threads/combined/prulock.c \
+ nsprpub/pr/src/threads/combined/prustack.c \
+ nsprpub/pr/src/threads/combined/pruthr.c
+# gcc/emx sources
+VBox-xpcom-nspr_SOURCES.os2 += \
+ nsprpub/pr/src/md/os2/os2emx.s \
+ nsprpub/pr/src/md/os2/os2vaclegacy.s
+# IBM VAC sources (not used)
+#VBox-xpcom-nspr_SOURCES.os2 += \
+# nsprpub/pr/src/md/os2/os2vacpp.asm
+
+VBox-xpcom-nspr_SOURCES.solaris = nsprpub/pr/src/md/unix/solaris.c
+VBox-xpcom-nspr_SOURCES.solaris.x86 = nsprpub/pr/src/md/unix/os_SunOS_x86.s
+VBox-xpcom-nspr_SOURCES.solaris.amd64 = nsprpub/pr/src/md/unix/os_SunOS_x86_64.s
+
+# generate build stamps
+nsprpub/pr/src/prvrsion.c_DEPS = $(VBox-xpcom-nspr_0_OUTDIR)/_pr_bld.h
+nsprpub/lib/ds/plvrsion.c_DEPS = $(VBox-xpcom-nspr_0_OUTDIR)/_pl_bld.h
+VBox-xpcom-nspr_CLEAN += \
+ $(VBox-xpcom-nspr_0_OUTDIR)/_pr_bld.h \
+ $(VBox-xpcom-nspr_0_OUTDIR)/_pl_bld.h
+
+$(call KB_FN_DO_PASS0_ON_TARGET,VBox-xpcom-nspr)
+
+$$(VBox-xpcom-nspr_0_OUTDIR)/_pr_bld.h: | $$(VBox-xpcom-nspr_0_OUTDIR)/
+ $(call MSG_GENERATE,,$@)
+ $(QUIET)$(APPEND) -t $@ '#define _BUILD_STRING "$(date +%Y-%m-%d %T)"'
+
+$$(VBox-xpcom-nspr_0_OUTDIR)/_pl_bld.h: | $$(VBox-xpcom-nspr_0_OUTDIR)/
+ $(call MSG_GENERATE,,$@)
+ $(QUIET)$(APPEND) -t $@ '#define _BUILD_STRING "$(date +%Y-%m-%d %T)"'
+
+$(evalcall2 VBOX_XPCOM_X86,VBox-xpcom-nspr)
+
+
+VBox-xpcom-typelib_TEMPLATE = XPComDll
+VBox-xpcom-typelib_INSTTYPE = none
+VBox-xpcom-typelib_SOURCES = \
+ xpcom/typelib/xpt/src/xpt_arena.c \
+ xpcom/typelib/xpt/src/xpt_struct.c \
+ xpcom/typelib/xpt/src/xpt_xdr.c
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-typelib)
+
+VBox-xpcom-string_TEMPLATE = XPComDll
+VBox-xpcom-string_INSTTYPE = none
+VBox-xpcom-string_SOURCES = \
+ xpcom/string/src/nsAString.cpp \
+ xpcom/string/src/nsDependentSubstring.cpp \
+ xpcom/string/src/nsObsoleteAStringThunk.cpp \
+ xpcom/string/src/nsPrintfCString.cpp \
+ xpcom/string/src/nsPromiseFlatString.cpp \
+ xpcom/string/src/nsReadableUtils.cpp \
+ xpcom/string/src/nsSubstring.cpp \
+ xpcom/string/src/nsSubstringTuple.cpp \
+ xpcom/string/src/nsString.cpp \
+ xpcom/string/src/nsStringComparator.cpp \
+ xpcom/string/src/nsStringObsolete.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-string)
+
+VBox-xpcom-base_TEMPLATE = XPComDll
+VBox-xpcom-base_INSTTYPE = none
+VBox-xpcom-base_DEFS = _IMPL_NS_COM
+VBox-xpcom-base_SOURCES = \
+ xpcom/base/nsAllocator.cpp \
+ xpcom/base/nsConsoleMessage.cpp \
+ xpcom/base/nsConsoleService.cpp \
+ xpcom/base/nsDebugImpl.cpp \
+ xpcom/base/nsErrorService.cpp \
+ xpcom/base/nsExceptionService.cpp \
+ xpcom/base/nsID.cpp \
+ xpcom/base/nsMemoryImpl.cpp \
+ xpcom/base/nsTraceRefcntImpl.cpp \
+ xpcom/base/nsStackFrameUnix.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-base)
+
+VBox-xpcom-ds_TEMPLATE = XPComDll
+VBox-xpcom-ds_INSTTYPE = none
+VBox-xpcom-ds_DEFS = _IMPL_NS_COM
+VBox-xpcom-ds_SOURCES = \
+ xpcom/ds/pldhash.c \
+ xpcom/ds/nsAtomTable.cpp \
+ xpcom/ds/nsAtomService.cpp \
+ xpcom/ds/nsByteBuffer.cpp \
+ xpcom/ds/nsCheapSets.cpp \
+ xpcom/ds/nsCRT.cpp \
+ xpcom/ds/nsDeque.cpp \
+ xpcom/ds/nsEmptyEnumerator.cpp \
+ xpcom/ds/nsEnumeratorUtils.cpp \
+ xpcom/ds/nsFixedSizeAllocator.cpp \
+ xpcom/ds/nsHashSets.cpp \
+ xpcom/ds/nsHashtable.cpp \
+ xpcom/ds/nsObserverList.cpp \
+ xpcom/ds/nsObserverService.cpp \
+ xpcom/ds/nsProperties.cpp \
+ xpcom/ds/nsPersistentProperties.cpp \
+ xpcom/ds/nsQuickSort.cpp \
+ xpcom/ds/nsRecyclingAllocator.cpp \
+ xpcom/ds/nsStaticNameTable.cpp \
+ xpcom/ds/nsStringEnumerator.cpp \
+ xpcom/ds/nsSupportsArray.cpp \
+ xpcom/ds/nsSupportsArrayEnumerator.cpp \
+ xpcom/ds/nsSupportsPrimitives.cpp \
+ xpcom/ds/nsTHashtable.cpp \
+ xpcom/ds/nsUnicharBuffer.cpp \
+ xpcom/ds/nsVariant.cpp \
+ xpcom/ds/nsVoidArray.cpp \
+ xpcom/ds/nsTextFormatter.cpp \
+ xpcom/ds/nsTimelineService.cpp \
+ xpcom/ds/nsValueArray.cpp \
+ xpcom/ds/nsCOMArray.cpp \
+ xpcom/ds/nsArray.cpp \
+ xpcom/ds/nsArrayEnumerator.cpp
+# xpcom/ds/nsHashPropertyBag.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-ds)
+
+# @todo what about MOZ_USER_DIR?
+VBox-xpcom-io_TEMPLATE = XPComDll
+VBox-xpcom-io_INSTTYPE = none
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ VBox-xpcom-io_DEFS = _IMPL_NS_COM MOZ_USER_DIR=".mozilla"
+else
+ VBox-xpcom-io_DEFS = _IMPL_NS_COM MOZ_USER_DIR=\".mozilla\"
+endif
+if defined(VBOX_WITH_HARDENING) && defined(VBOX_PATH_APP_PRIVATE_ARCH)
+ ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ VBox-xpcom-io_DEFS += MOZ_DEFAULT_VBOX_XPCOM_HOME="$(VBOX_PATH_APP_PRIVATE_ARCH)"
+ else
+ VBox-xpcom-io_DEFS += MOZ_DEFAULT_VBOX_XPCOM_HOME=\"$(VBOX_PATH_APP_PRIVATE_ARCH)\"
+ endif
+endif
+VBox-xpcom-io_INCS.darwin = \
+ xpcom/MoreFiles
+VBox-xpcom-io_SOURCES = \
+ xpcom/io/nsAppFileLocationProvider.cpp \
+ xpcom/io/nsBinaryStream.cpp \
+ xpcom/io/nsByteArrayInputStream.cpp \
+ xpcom/io/nsDirectoryService.cpp \
+ xpcom/io/nsEscape.cpp \
+ xpcom/io/nsFastLoadFile.cpp \
+ xpcom/io/nsFastLoadService.cpp \
+ xpcom/io/nsInputStreamTee.cpp \
+ xpcom/io/nsLinebreakConverter.cpp \
+ xpcom/io/nsLocalFileCommon.cpp \
+ xpcom/io/nsMultiplexInputStream.cpp \
+ xpcom/io/nsPipe3.cpp \
+ xpcom/io/nsStreamUtils.cpp \
+ xpcom/io/nsScriptableInputStream.cpp \
+ xpcom/io/nsSegmentedBuffer.cpp \
+ xpcom/io/SpecialSystemDirectory.cpp \
+ xpcom/io/nsStorageStream.cpp \
+ xpcom/io/nsStringStream.cpp \
+ xpcom/io/nsUnicharInputStream.cpp \
+ xpcom/io/nsNativeCharsetUtils.cpp
+VBox-xpcom-io_SOURCES.darwin.x86 = \
+ xpcom/io/nsLocalFileOSX.cpp \
+ xpcom/MoreFiles/FSCopyObject.c \
+ xpcom/MoreFiles/MoreFilesX.c
+if1of ($(KBUILD_TARGET) $(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), freebsd linux netbsd openbsd solaris darwin.amd64 darwin.arm64)
+ VBox-xpcom-io_SOURCES += \
+ xpcom/io/nsLocalFileUnix.cpp
+endif
+VBox-xpcom-io_SOURCES.os2 = \
+ xpcom/io/nsLocalFileOS2.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-io)
+
+VBox-xpcom-components_TEMPLATE = XPComDll
+VBox-xpcom-components_INSTTYPE = none
+VBox-xpcom-components_DEFS = _IMPL_NS_COM EXPORT_XPTI_API
+VBox-xpcom-components_SOURCES = \
+ xpcom/components/nsCategoryManager.cpp \
+ xpcom/components/nsComponentManager.cpp \
+ xpcom/components/nsComponentManagerObsolete.cpp \
+ xpcom/components/nsNativeComponentLoader.cpp \
+ xpcom/components/nsServiceManagerObsolete.cpp \
+ xpcom/components/xcDll.cpp \
+ xpcom/components/nsStaticComponentLoader.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-components)
+
+VBox-xpcom-threads_TEMPLATE = XPComDll
+VBox-xpcom-threads_INSTTYPE = none
+VBox-xpcom-threads_DEFS = _IMPL_NS_COM
+VBox-xpcom-threads_SOURCES = \
+ xpcom/threads/plevent.c \
+ xpcom/threads/nsAutoLock.cpp \
+ xpcom/threads/nsEnvironment.cpp \
+ xpcom/threads/nsEventQueue.cpp \
+ xpcom/threads/nsEventQueueService.cpp \
+ xpcom/threads/nsThread.cpp \
+ xpcom/threads/nsTimerImpl.cpp \
+ xpcom/threads/nsProcessCommon.cpp \
+ xpcom/threads/TimerThread.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-threads)
+
+VBox-xpcom-xptinfo_TEMPLATE = XPComDll
+VBox-xpcom-xptinfo_INSTTYPE = none
+VBox-xpcom-xptinfo_DEFS = _IMPL_NS_COM _IMPL_NS_BASE EXPORT_XPTI_API EXPORT_XPT_API
+VBox-xpcom-xptinfo_SOURCES = \
+ xpcom/reflect/xptinfo/src/xptiFile.cpp \
+ xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp \
+ xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp \
+ xpcom/reflect/xptinfo/src/xptiManifest.cpp \
+ xpcom/reflect/xptinfo/src/xptiMisc.cpp \
+ xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp \
+ xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp \
+ xpcom/reflect/xptinfo/src/xptiZipItem.cpp \
+ xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-xptinfo)
+
+
+VBox-xpcom-xptcall_TEMPLATE = XPComDllYasm
+VBox-xpcom-xptcall_INSTTYPE = none
+VBox-xpcom-xptcall_DEFS = _IMPL_NS_COM _IMPL_NS_BASE EXPORT_XPTC_API
+VBox-xpcom-xptcall_DEFS.darwin = KEEP_STACK_16_BYTE_ALIGNED
+VBox-xpcom-xptcall_DEFS.os2 = MOZ_NEED_LEADING_UNDERSCORE
+VBox-xpcom-xptcall_INCS.os2 = xpcom/reflect/xptcall/src/md/unix
+VBox-xpcom-xptcall_SOURCES = xpcom/reflect/xptcall/src/xptcall.cpp
+VBox-xpcom-xptcall_SOURCES.darwin.x86 = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp \
+ xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp
+VBox-xpcom-xptcall_SOURCES.freebsd.x86 = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp \
+ xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp
+VBox-xpcom-xptcall_SOURCES.linux.x86 = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp \
+ xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp
+VBox-xpcom-xptcall_SOURCES.os2 = xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp \
+ xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp
+VBox-xpcom-xptcall_SOURCES.solaris.x86 = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp \
+ xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp
+VBox-xpcom-xptcall_SOURCES.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm
+VBox-xpcom-xptcall_SOURCES.arm64 = xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp \
+ xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
+VBox-xpcom-xptcall_SOURCES.darwin.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp # Underscore prefix.
+VBox-xpcom-xptcall_SOURCES.freebsd.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
+VBox-xpcom-xptcall_SOURCES.linux.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
+ifndef VBOX_GCC_USING_SOLARIS_AS
+ VBox-xpcom-xptcall_SOURCES.solaris.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
+else
+ VBox-xpcom-xptcall_SOURCES.solaris.amd64 = xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp
+endif
+
+xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp_CXXFLAGS = -O0
+# -O0 works fine, while -O1 doesn't. The gcc man page can't be listing all the -f*
+# stuff that -O1 enables, because when using the options without -O1, it's -fomit-frame-pointer
+# that triggers is, while -O1 -fno-omit-frame-pointer does not work. Anyway, it's probably a gcc/mozila
+# bug and it's not worth investigating as I'm not the maintainger of the solaris gcc port. [bird, 2007-09-17]
+
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-xptcall)
+
+
+VBox-xpcom-proxy_TEMPLATE = XPComDll
+VBox-xpcom-proxy_INSTTYPE = none
+VBox-xpcom-proxy_DEFS = _IMPL_NS_COM EXPORT_XPTC_API EXPORT_XPTI_API
+VBox-xpcom-proxy_SOURCES = \
+ xpcom/proxy/src/nsProxyEvent.cpp \
+ xpcom/proxy/src/nsProxyEventClass.cpp \
+ xpcom/proxy/src/nsProxyEventObject.cpp \
+ xpcom/proxy/src/nsProxyObjectManager.cpp \
+ xpcom/proxy/src/nsProxyRelease.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-proxy)
+
+
+#
+# The VBoxXPCOM Glue static libraries.
+#
+# This isn't the normal XPCOM glue (see the places in XPCOM where XPCOM_GLUE is
+# checked), VirtualBox has its own glue library and this means this isn't used
+# much (one reason is that we don't provide frozen APIs yet). All VBox XPCOM
+# client applications are dependent on the given version of both the VBox XPCOM
+# runtime (binary dependency) and VirtualBox component library (COM interface
+# dependency). For this reason, VBox client applications link to the VBox XPCOM
+# shared library directly (instead of linking to the standalone XPCOM glue
+# library that would dynamically search for and load the installed XPCOM
+# runtime). For the same reason, we link all parts of XPCOM into a single
+# shared XPCOM library below (as opposed to the original XPCOM where e.g. NSPR
+# lives in a separate DLL). Additionally there is VBox specific glue code to
+# make both the client and server side code build with both XPCOM and COM,
+# which should be made part of the SDK eventually, but this is a higher level
+# of abstraction than this XPCOM specific glue code.
+#
+VBoxXPCOMGlue_COMMON_SOURCES = \
+ xpcom/glue/nsCOMPtr.cpp \
+ xpcom/glue/nsComponentManagerUtils.cpp \
+ xpcom/glue/nsDebug.cpp \
+ xpcom/glue/nsGenericFactory.cpp \
+ xpcom/glue/nsIInterfaceRequestorUtils.cpp \
+ xpcom/glue/nsMemory.cpp \
+ xpcom/glue/nsTraceRefcnt.cpp \
+ xpcom/glue/nsWeakReference.cpp
+
+# dependent glue library which goes in to the VBoxXPCOM shared library
+VBoxXPCOMGlue_s_TEMPLATE = XPComDll
+VBoxXPCOMGlue_s_INSTTYPE = none
+VBoxXPCOMGlue_s_DEFS = _IMPL_NS_COM
+VBoxXPCOMGlue_s_SOURCES = $(VBoxXPCOMGlue_COMMON_SOURCES)
+$(evalcall VBOX_XPCOM_X86,VBoxXPCOMGlue_s)
+
+# standalone glue library which all third-party client apps (if any) will
+# link with (currently completely unused and nit built, to be part of the SDK)
+VBoxXPCOMGlue_TEMPLATE = XPComDll
+VBoxXPCOMGlue_SOURCES = $(VBoxXPCOMGlue_COMMON_SOURCES)
+#VBoxXPCOMGlue_INST = lib/ $(INST_SDK)lib/
+$(evalcall VBOX_XPCOM_X86,VBoxXPCOMGlue)
+
+
+#
+# The VBoxXPCOM Shared Object, assembling all lib files.
+#
+VBoxXPCOM_TEMPLATE = XPComDll
+VBoxXPCOM_NAME = $(basename $(notdir $(LIB_XPCOM)))
+VBoxXPCOM_DEFS = BUILD_DCONNECT=1 _IMPL_NS_COM
+ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ VBoxXPCOM_LDFLAGS.linux = -Wl,--version-script=$(XPCOM_C_NAMESPACE_MAP)
+ VBoxXPCOM_LNK_DEPS.linux += $(XPCOM_C_NAMESPACE_MAP)
+ VBoxXPCOM_LDFLAGS.solaris = -Wl,-M,$(XPCOM_C_NAMESPACE_MAP)
+ VBoxXPCOM_LNK_DEPS.solaris += $(XPCOM_C_NAMESPACE_MAP)
+endif
+VBoxXPCOM_SOURCES = \
+ xpcom/build/nsXPComInit.cpp \
+ xpcom/build/nsStringAPI.cpp
+VBoxXPCOM_SOURCES.darwin = \
+ vboxdeps.cpp
+VBoxXPCOM_SOURCES.os2 = \
+ vboxdeps.cpp
+VBoxXPCOM_SOURCES.solaris = \
+ vboxdeps.cpp
+VBoxXPCOM_LIBS = \
+ $(VBox-xpcom-typelib_1_TARGET) \
+ $(VBox-xpcom-string_1_TARGET) \
+ $(VBox-xpcom-base_1_TARGET) \
+ $(VBox-xpcom-ds_1_TARGET) \
+ $(VBox-xpcom-io_1_TARGET) \
+ $(VBox-xpcom-components_1_TARGET) \
+ $(VBox-xpcom-threads_1_TARGET) \
+ $(VBox-xpcom-xptinfo_1_TARGET) \
+ $(VBox-xpcom-xptcall_1_TARGET) \
+ $(VBox-xpcom-proxy_1_TARGET) \
+ $(VBox-xpcom-nspr_1_TARGET) \
+ $(VBoxXPCOMGlue_s_1_TARGET)
+VBoxXPCOM_LIBS.linux = \
+ pthread dl
+
+ifeq ($(filter-out freebsd linux netbsd openbsd,$(KBUILD_TARGET)),) # gnu ld.
+ VBoxXPCOM_LDFLAGS = -Wl,--whole-archive \
+ $(VBox-xpcom-typelib_1_TARGET) \
+ $(VBox-xpcom-string_1_TARGET) \
+ $(VBox-xpcom-base_1_TARGET) \
+ $(VBox-xpcom-ds_1_TARGET) \
+ $(VBox-xpcom-io_1_TARGET) \
+ $(VBox-xpcom-components_1_TARGET) \
+ $(VBox-xpcom-threads_1_TARGET) \
+ $(VBox-xpcom-xptinfo_1_TARGET) \
+ $(VBox-xpcom-xptcall_1_TARGET) \
+ $(VBox-xpcom-proxy_1_TARGET) \
+ $(VBox-xpcom-nspr_1_TARGET) \
+ $(VBoxXPCOMGlue_s_1_TARGET) \
+ -Wl,--no-whole-archive
+endif
+
+VBoxXPCOM_LDFLAGS.solaris += -Wl,-z,allextract \
+ $(VBox-xpcom-typelib_1_TARGET) \
+ $(VBox-xpcom-string_1_TARGET) \
+ $(VBox-xpcom-base_1_TARGET) \
+ $(VBox-xpcom-ds_1_TARGET) \
+ $(VBox-xpcom-io_1_TARGET) \
+ $(VBox-xpcom-components_1_TARGET) \
+ $(VBox-xpcom-threads_1_TARGET) \
+ $(VBox-xpcom-xptinfo_1_TARGET) \
+ $(VBox-xpcom-xptcall_1_TARGET) \
+ $(VBox-xpcom-proxy_1_TARGET) \
+ $(VBox-xpcom-nspr_1_TARGET) \
+ $(VBoxXPCOMGlue_s_1_TARGET) \
+ -Wl,-z,defaultextract
+
+# EF heap
+#VBoxXPCOM_LIBS += $(LIB_RUNTIME_EF)
+#VBoxXPCOM_LDFLAGS = -Wl,--whole-archive $(VBoxXPCOM_LIBS) -Wl,--no-whole-archive $(LIB_RUNTIME)
+VBoxXPCOM_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxXPCOM.dylib
+
+#
+# The 32-bit VBoxXPCOM Shared Object, assembling all lib files.
+#
+VBoxXPCOM-x86_TEMPLATE = XPComDll-x86
+VBoxXPCOM-x86_EXTENDS = VBoxXPCOM
+VBoxXPCOM-x86_NAME = VBoxXPCOM-x86
+VBoxXPCOM-x86_LIBS = \
+ $(VBox-xpcom-typelib-x86_1_TARGET) \
+ $(VBox-xpcom-string-x86_1_TARGET) \
+ $(VBox-xpcom-base-x86_1_TARGET) \
+ $(VBox-xpcom-ds-x86_1_TARGET) \
+ $(VBox-xpcom-io-x86_1_TARGET) \
+ $(VBox-xpcom-components-x86_1_TARGET) \
+ $(VBox-xpcom-threads-x86_1_TARGET) \
+ $(VBox-xpcom-xptinfo-x86_1_TARGET) \
+ $(VBox-xpcom-xptcall-x86_1_TARGET) \
+ $(VBox-xpcom-proxy-x86_1_TARGET) \
+ $(VBox-xpcom-nspr-x86_1_TARGET) \
+ $(VBoxXPCOMGlue_s-x86_1_TARGET)
+
+ifeq ($(filter-out freebsd linux netbsd openbsd,$(KBUILD_TARGET)),) # gnu ld.
+ VBoxXPCOM-x86_LDFLAGS = -Wl,--whole-archive \
+ $(VBox-xpcom-typelib-x86_1_TARGET) \
+ $(VBox-xpcom-string-x86_1_TARGET) \
+ $(VBox-xpcom-base-x86_1_TARGET) \
+ $(VBox-xpcom-ds-x86_1_TARGET) \
+ $(VBox-xpcom-io-x86_1_TARGET) \
+ $(VBox-xpcom-components-x86_1_TARGET) \
+ $(VBox-xpcom-threads-x86_1_TARGET) \
+ $(VBox-xpcom-xptinfo-x86_1_TARGET) \
+ $(VBox-xpcom-xptcall-x86_1_TARGET) \
+ $(VBox-xpcom-proxy-x86_1_TARGET) \
+ $(VBox-xpcom-nspr-x86_1_TARGET) \
+ $(VBoxXPCOMGlue_s-x86_1_TARGET) \
+ -Wl,--no-whole-archive
+endif
+
+VBoxXPCOM-x86_LDFLAGS.solaris += -Wl,-z,allextract \
+ $(VBox-xpcom-typelib-x86_1_TARGET) \
+ $(VBox-xpcom-string-x86_1_TARGET) \
+ $(VBox-xpcom-base-x86_1_TARGET) \
+ $(VBox-xpcom-ds-x86_1_TARGET) \
+ $(VBox-xpcom-io-x86_1_TARGET) \
+ $(VBox-xpcom-components-x86_1_TARGET) \
+ $(VBox-xpcom-threads-x86_1_TARGET) \
+ $(VBox-xpcom-xptinfo-x86_1_TARGET) \
+ $(VBox-xpcom-xptcall-x86_1_TARGET) \
+ $(VBox-xpcom-proxy-x86_1_TARGET) \
+ $(VBox-xpcom-nspr-x86_1_TARGET) \
+ $(VBoxXPCOMGlue_s-x86_1_TARGET) \
+ -Wl,-z,defaultextract
+
+
+#
+# VBoxXPCOMImp - Import library/hack.
+#
+ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ $(call VBOX_GENERATE_IMPORT_TARGET_FN,VBoxXPCOMImp,VBoxXPCOM,VBoxXPCOM-mangled.def)
+else
+ $(call VBOX_GENERATE_IMPORT_TARGET_FN,VBoxXPCOMImp,VBoxXPCOM,VBoxXPCOM.def)
+endif
+
+
+#
+# IPC templates.
+#
+ifdef VBOX_IPC_RELEASE_LOG
+ IPC_LOGGING = 1
+else ifneq ($(KBUILD_TYPE),release)
+ IPC_LOGGING = 1
+endif
+
+TEMPLATE_XPComIpcDll = XPCOM IPC libraries
+TEMPLATE_XPComIpcDll_EXTENDS = XPComDll
+TEMPLATE_XPComIpcDll_DEFS = $(TEMPLATE_XPComDll_DEFS) BUILD_DCONNECT=1
+ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING
+ TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME="VBoxXPCOMIPCD$(SUFF_EXE)"
+else
+ TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME=\"VBoxXPCOMIPCD$(SUFF_EXE)\"
+endif
+ifdef IPC_LOGGING
+ TEMPLATE_XPComIpcDll_DEFS += IPC_LOGGING
+endif
+TEMPLATE_XPComIpcDll_LIBS = $(VBoxXPCOM_1_TARGET) $(TEMPLATE_XPComDll_LIBS)
+ifneq ($(KBUILD_TARGET),win)
+ ifeq ($(filter-out solaris.x86 %.amd64 %.sparc32 %.sparc64,$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)),) ## TODO: cleanup!
+ if defined(VBOX_WITH_RELATIVE_RUNPATH) && !defined(VBOX_WITH_HARDENING)
+ TEMPLATE_XPComIpcDll_LDFLAGS = $(filter-out '$(VBOX_GCC_RPATH_OPT)%',$(TEMPLATE_XPComDll_LDFLAGS)) '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RELATIVE_RUNPATH)/..'
+ endif
+ else ifndef VBOX_WITH_HARDENING
+ ifdef VBOX_WITH_RELATIVE_RUNPATH
+ TEMPLATE_XPComIpcDll_LDFLAGS = $(filter-out '$(VBOX_GCC_RPATH_OPT)%',$(TEMPLATE_XPComDll_LDFLAGS)) '$(VBOX_GCC_RPATH_OPT)$(VBOX_WITH_RELATIVE_RUNPATH)/..'
+ endif
+ endif
+endif
+
+TEMPLATE_XPComIpcDll-x86 = 32-bit XPCOM IPC libraries
+TEMPLATE_XPComIpcDll-x86_EXTENDS = XPComIpcDll
+TEMPLATE_XPComIpcDll-x86_BLD_TRG_ARCH = x86
+TEMPLATE_XPComIpcDll-x86_LIBS = $(VBoxXPCOM-x86_1_TARGET) $(TEMPLATE_XPComDll-x86_LIBS)
+
+TEMPLATE_XPComIpcExe = XPCOM IPC executables
+TEMPLATE_XPComIpcExe_EXTENDS = XPComExe
+TEMPLATE_XPComIpcExe_DEFS = $(TEMPLATE_XPComExe_DEFS) BUILD_DCONNECT=1
+ifdef IPC_LOGGING
+ TEMPLATE_XPComIpcExe_DEFS += IPC_LOGGING
+endif
+
+#
+# Shared IPC code. Used by the IPC component as well as the executables.
+#
+VBox-xpcom-ipcshared_TEMPLATE = XPComIpcDll
+VBox-xpcom-ipcshared_INSTTYPE = none
+VBox-xpcom-ipcshared_SOURCES = \
+ ipc/ipcd/shared/src/ipcLog.cpp \
+ ipc/ipcd/shared/src/ipcConfig.cpp \
+ ipc/ipcd/shared/src/ipcMessage.cpp \
+ ipc/ipcd/shared/src/ipcMessagePrimitives.cpp \
+ ipc/ipcd/shared/src/ipcStringList.cpp \
+ ipc/ipcd/shared/src/ipcIDList.cpp \
+ ipc/ipcd/shared/src/ipcm.cpp
+$(evalcall VBOX_XPCOM_X86,VBox-xpcom-ipcshared)
+
+
+#
+# DCONNECT client shared object
+#
+VBoxXPCOMIPCC_TEMPLATE = XPComIpcDll
+VBoxXPCOMIPCC_NAME.os2 = VBoxIPCC
+VBoxXPCOMIPCC_INST = $(INST_BIN)components/
+#VBoxXPCOMIPCC_DEFS = HAVE_DEPENDENT_LIBS - dependentLibs.h is linux specific, so this cannot be required.
+VBoxXPCOMIPCC_SOURCES = \
+ ipc/ipcd/client/src/ipcdclient.cpp \
+ ipc/ipcd/client/src/ipcService.cpp \
+ ipc/ipcd/client/src/ipcModuleFactory.cpp \
+ ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp \
+ \
+ ipc/ipcd/util/src/ipcMessageReader.cpp \
+ ipc/ipcd/util/src/ipcMessageWriter.cpp \
+ \
+ ipc/ipcd/extensions/lock/src/ipcLockProtocol.cpp \
+ ipc/ipcd/extensions/lock/src/ipcLockService.cpp \
+ \
+ ipc/ipcd/extensions/transmngr/src/tmTransactionService.cpp \
+ \
+ ipc/ipcd/extensions/transmngr/common/tmTransaction.cpp \
+ ipc/ipcd/extensions/transmngr/common/tmVector.cpp
+
+ifeq ($(KBUILD_TARGET),win)
+ VBoxXPCOMIPCC_SOURCES += \
+ ipc/ipcd/client/src/ipcConnectionWin.cpp
+else
+ VBoxXPCOMIPCC_SOURCES += \
+ ipc/ipcd/client/src/ipcConnectionUnix.cpp
+endif
+VBoxXPCOMIPCC_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/components/VBoxXPCOMIPCC.dylib
+VBoxXPCOMIPCC_LIBS = \
+ $(VBox-xpcom-ipcshared_1_TARGET)
+
+# 32-bit version of the component.
+$(evalcall VBOX_XPCOM_X86,VBoxXPCOMIPCC)
+VBoxXPCOMIPCC-x86_LIBS = \
+ $(VBox-xpcom-ipcshared-x86_1_TARGET)
+
+
+#
+# DCONNECT daemon executable
+#
+VBoxXPCOMIPCD_TEMPLATE = XPComIpcExe
+VBoxXPCOMIPCD_SOURCES = \
+ ipc/ipcd/daemon/src/ipcd.cpp \
+ ipc/ipcd/daemon/src/ipcClient.cpp \
+ ipc/ipcd/daemon/src/ipcModuleReg.cpp \
+ ipc/ipcd/daemon/src/ipcCommandModule.cpp
+ifeq ($(KBUILD_TARGET),win)
+ VBoxXPCOMIPCD_SOURCES += \
+ ipc/ipcd/daemon/src/ipcdWin.cpp
+else
+ VBoxXPCOMIPCD_SOURCES += \
+ ipc/ipcd/daemon/src/ipcdUnix.cpp
+endif
+
+
+#
+# Include sub-makefiles for the Python<->XPCOM and Java<->XPCOM bridges.
+#
+ifndef VBOX_ONLY_EXTPACKS
+ # Find the Python headers for the Python<->XPCOM bridge if enabled.
+ ifdef VBOX_WITH_PYTHON
+ include $(PATH_SUB_CURRENT)/python/Makefile.kmk
+ endif
+
+ ifdef VBOX_WITH_JXPCOM
+ include $(PATH_SUB_CURRENT)/java/Makefile.kmk
+ endif
+endif # !VBOX_ONLY_EXTPACKS
+
+
+#
+# testcases
+#
+tstnsIFileEnumerator_TEMPLATE = XPComTstExe
+tstnsIFileEnumerator_SOURCES = xpcom/tests/nsIFileEnumerator.cpp
+tstnsIFileTest_TEMPLATE = XPComTstExe
+tstnsIFileTest_SOURCES = xpcom/tests/nsIFileTest.cpp
+tstTestArray_TEMPLATE = XPComTstExe
+tstTestArray_SOURCES = xpcom/tests/TestArray.cpp
+tstTestAtoms_TEMPLATE = XPComTstExe
+tstTestAtoms_SOURCES = xpcom/tests/TestAtoms.cpp
+tstTestAutoLock_TEMPLATE = XPComTstExe
+tstTestAutoLock_SOURCES = xpcom/tests/TestAutoLock.cpp
+tstTestCallTemplates_TEMPLATE = XPComTstExe
+tstTestCallTemplates_SOURCES = xpcom/tests/TestCallTemplates.cpp
+tstTestCOMPtr_TEMPLATE = XPComTstExe
+tstTestCOMPtr_SOURCES = xpcom/tests/TestCOMPtr.cpp
+tstTestCOMPtrEq_TEMPLATE = XPComTstExe
+tstTestCOMPtrEq_SOURCES = xpcom/tests/TestCOMPtrEq.cpp
+tstTestCRT_TEMPLATE = XPComTstExe
+tstTestCRT_SOURCES = xpcom/tests/TestCRT.cpp
+tstTestFactory_TEMPLATE = XPComTstExe
+tstTestFactory_SOURCES = xpcom/tests/TestFactory.cpp
+tstTestHashtables_TEMPLATE = XPComTstExe
+tstTestHashtables_SOURCES = xpcom/tests/TestHashtables.cpp
+tstTestID_TEMPLATE = XPComTstExe
+tstTestID_SOURCES = xpcom/tests/TestID.cpp
+tstTestObserverService_TEMPLATE = XPComTstExe
+tstTestObserverService_SOURCES = xpcom/tests/TestObserverService.cpp
+tstTestPermanentAtoms_TEMPLATE = XPComTstExe
+tstTestPermanentAtoms_SOURCES = xpcom/tests/TestPermanentAtoms.cpp
+tstTestPipes_TEMPLATE = XPComTstExe
+tstTestPipes_SOURCES = xpcom/tests/TestPipes.cpp
+tstTestServMgr_TEMPLATE = XPComTstExe
+tstTestServMgr_SOURCES = xpcom/tests/TestServMgr.cpp
+tstTestServMgr_INCS = xpcom/tests/services
+tstTestThreads_TEMPLATE = XPComTstExe
+tstTestThreads_SOURCES = xpcom/tests/TestThreads.cpp
+tstTestXPIDLString_TEMPLATE = XPComTstExe
+tstTestXPIDLString_SOURCES = xpcom/tests/TestXPIDLString.cpp
+tstTestXPTCInvoke_TEMPLATE = XPComTstExe
+tstTestXPTCInvoke_SOURCES = xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp
+tstTestDeque_TEMPLATE = XPComTstExe
+tstTestDeque_SOURCES = xpcom/tests/TestDeque.cpp
+tstTestAutoPtr_TEMPLATE = XPComTstExe
+tstTestAutoPtr_SOURCES = xpcom/tests/TestAutoPtr.cpp
+tstTestMinStringAPI_TEMPLATE = XPComTstExe
+tstTestMinStringAPI_SOURCES = xpcom/tests/TestMinStringAPI.cpp
+tstTestStrings_TEMPLATE = XPComTstExe
+tstTestStrings_SOURCES = xpcom/tests/TestStrings.cpp
+tstPrimitiveTest_TEMPLATE = XPComTstExe
+tstPrimitiveTest_SOURCES = xpcom/typelib/xpt/tests/PrimitiveTest.c
+tstSimpleTypeLib_TEMPLATE = XPComTstExe
+tstSimpleTypeLib_SOURCES = xpcom/typelib/xpt/tests/SimpleTypeLib.c
+tstXptDump_TEMPLATE = XPComTstExe
+tstXptDump_SOURCES = xpcom/typelib/xpt/tools/xpt_dump.c
+tstXptLink_TEMPLATE = XPComTstExe
+tstXptLink_SOURCES = xpcom/typelib/xpt/tools/xpt_link.c
+
+
+
+OTHER_CLEAN += \
+ $(PATH_TARGET)/VBox-xpcom-idl-timestamp \
+ $(addprefix $(VBOX_PATH_SDK)/bindings/xpcom/include,$(notdir $(subst .idl,.h,$(XPCOM_IDLFILES)))) \
+ $(addprefix $(VBOX_PATH_SDK)/bindings/xpcom/include,$(notdir $(subst .idl,.xpt,$(XPCOM_IDLFILES)))) \
+ $(addprefix $(VBOX_PATH_SDK)/bindings/xpcom/idl/,$(notdir $(XPCOM_IDLFILES))) \
+ $(addprefix $(PATH_TARGET)/VBox-xpcom-xpt-files/,$(notdir $(subst .idl,.xpt,$(XPCOM_IDLFILES))))
+
+
+#
+# Create and install VBoxXPCOMBase.xpt
+#
+INSTALLS += VBoxXPCOMBase-xpt-inst
+VBOX_XPTFILES = $(addprefix $(PATH_TARGET)/VBox-xpcom-xpt-files/, \
+ nsIConsoleListener.xpt \
+ nsIConsoleMessage.xpt \
+ nsIConsoleService.xpt \
+ nsIErrorService.xpt \
+ nsIException.xpt \
+ nsIExceptionService.xpt \
+ nsIDebug.xpt \
+ nsIInterfaceRequestor.xpt \
+ nsIMemory.xpt \
+ nsIProgrammingLanguage.xpt \
+ nsISupports.xpt \
+ nsITraceRefcnt.xpt \
+ nsIWeakReference.xpt \
+ nsrootidl.xpt \
+ nsIAtom.xpt \
+ nsIAtomService.xpt \
+ nsICollection.xpt \
+ nsIEnumerator.xpt \
+ nsIPersistentProperties2.xpt \
+ nsIPropertyBag.xpt \
+ nsIRecyclingAllocator.xpt \
+ nsIVariant.xpt \
+ nsISerializable.xpt \
+ nsIStringEnumerator.xpt \
+ nsISupportsArray.xpt \
+ nsISupportsIterators.xpt \
+ nsITimelineService.xpt \
+ nsIArray.xpt \
+ nsIObserverService.xpt \
+ nsIObserver.xpt \
+ nsIProperties.xpt \
+ nsISimpleEnumerator.xpt \
+ nsISupportsPrimitives.xpt \
+ nsIBinaryInputStream.xpt \
+ nsIBinaryOutputStream.xpt \
+ nsIByteArrayInputStream.xpt \
+ nsIFastLoadFileControl.xpt \
+ nsIFastLoadService.xpt \
+ nsIInputStreamTee.xpt \
+ nsILineInputStream.xpt \
+ nsIMultiplexInputStream.xpt \
+ nsIObjectInputStream.xpt \
+ nsIObjectOutputStream.xpt \
+ nsIPipe.xpt \
+ nsISeekableStream.xpt \
+ nsIStorageStream.xpt \
+ nsIStringStream.xpt \
+ nsIStreamBufferAccess.xpt \
+ nsIAsyncInputStream.xpt \
+ nsIAsyncOutputStream.xpt \
+ nsIDirectoryService.xpt \
+ nsIFile.xpt \
+ nsILocalFile.xpt \
+ nsIInputStream.xpt \
+ nsIOutputStream.xpt \
+ nsIScriptableInputStream.xpt \
+ nsIComponentLoader.xpt \
+ nsIComponentLoaderManager.xpt \
+ nsIComponentManagerObsolete.xpt \
+ nsINativeComponentLoader.xpt \
+ nsIClassInfo.xpt \
+ nsIComponentRegistrar.xpt \
+ nsIFactory.xpt \
+ nsIModule.xpt \
+ nsIServiceManager.xpt \
+ nsIComponentManager.xpt \
+ nsICategoryManager.xpt \
+ nsIThread.xpt \
+ nsITimer.xpt \
+ nsITimerInternal.xpt \
+ nsITimerManager.xpt \
+ nsIRunnable.xpt \
+ nsIEventTarget.xpt \
+ nsIEventQueue.xpt \
+ nsIEventQueueService.xpt \
+ nsIEnvironment.xpt \
+ nsIProcess.xpt \
+ nsIInterfaceInfo.xpt \
+ nsIInterfaceInfoManager.xpt \
+ nsIXPTLoader.xpt)
+
+VBoxXPCOMBase-xpt-inst_INST = $(INST_BIN)components/
+VBoxXPCOMBase-xpt-inst_MODE = 0644
+VBoxXPCOMBase-xpt-inst_SOURCES = \
+ $(PATH_TARGET)/VBox-xpcom-xpt-files/VBoxXPCOMBase.xpt
+VBoxXPCOMBase-xpt-inst_CLEAN = \
+ $(VBOX_XPTFILES) \
+ $(PATH_TARGET)/VBox-xpcom-xpt-files/VBoxXPCOMBase.xpt
+
+# combined typelib library
+$(PATH_TARGET)/VBox-xpcom-xpt-files/VBoxXPCOMBase.xpt: $$(VBOX_XPTFILES) | $$(xpt_link_1_TARGET) $(PATH_TARGET)/VBox-xpcom-xpt-files/
+ $(call MSG_LINK,XPCOM_TYPELIB,$@)
+ $(QUIET)$(MKDIR) -p -- $(PATH_STAGE_BIN)/components
+ $(QUIET)$(xpt_link_1_TARGET) $@ $^
+
+
+
+# generate rules
+include $(FILE_KBUILD_SUB_FOOTER)
+
+
+
+#
+# Generate IDL rules.
+#
+
+##
+# Define for compiling one IDL into a header and a typelib
+# @param idl The filename with everything.
+define def_IDL
+ $(VBOX_PATH_SDK)/bindings/xpcom/include/$(notdir $(subst .idl,.h,$(idl))) \
+ + $(PATH_TARGET)/VBox-xpcom-xpt-files/$(notdir $(subst .idl,.xpt,$(idl))): \
+ $(VBOX_PATH_XPCOM_SRC)/$(idl) \
+ | $$$$(xpidl_1_TARGET) \
+ $(PATH_TARGET)/VBox-xpcom-xpt-files/
+ $$(call MSG_TOOL,xpidl,XPCOM,$$<,$$@)
+ $$(QUIET)$(MKDIR) -p $(VBOX_PATH_SDK)/bindings/xpcom/include $(VBOX_PATH_SDK)/bindings/xpcom/idl
+ $$(QUIET)$$(xpidl_1_TARGET) -m header $(XPIDL_INCS) -e $$@ $$<
+ $$(QUIET)$$(xpidl_1_TARGET) -m typelib $(XPIDL_INCS) -e $(addprefix $(PATH_TARGET)/VBox-xpcom-xpt-files/,$(notdir $(subst .idl,.xpt,$(idl)))) $$<
+ $$(QUIET)$(CP) $$< $$(VBOX_PATH_SDK)/bindings/xpcom/idl
+endef
+
+$(foreach idl, $(XPCOM_IDLFILES), $(eval $(def_IDL)))
+
+# dummy target.
+$(PATH_TARGET)/VBox-xpcom-idl-timestamp: $$(addprefix $$(VBOX_PATH_SDK)/bindings/xpcom/include/,$$(notdir $$(subst .idl,.h,$$(XPCOM_IDLFILES))))
+ $(call MSG_L1,IDL processing completed.)
+ $(QUIET)$(MKDIR) -p $(dir $@)
+ $(QUIET)$(APPEND) -t $@
+
+#
+# HACK ALERT! Make sure main doesn't start using xpidl before we're done
+# with the idl files here. The trick here is that we're using TARGET_xpidl,
+# i.e. the copy residing in obj/, while VBOX_XPIDL is pointing to
+# xpidl_1_STAGE_TARGET which is the one in bin/.
+#
+$(VBOX_XPIDL): | $(PATH_TARGET)/VBox-xpcom-idl-timestamp
+
+
+#
+# Generate linker map file filtering out unwanted global symbols.
+#
+$(PATH_TARGET)/xpcom-namespace-cleanup.map foo.map: $$(VBoxXPCOM_LIBS) $$(VBoxXPCOM_2_OBJS)
+ $(call MSG_L1, Creating linker map $@ for scrubbing the symbol namespace)
+ $(QUIET)$(APPEND) -t $@ '{ local: *; global: '
+ $(QUIET)$(VBOX_NM) -p -g $^ \
+ | $(SED) -n \
+ -e '/^$$/b' \
+ -e '/:$$/b' \
+ -e '/ U /b' \
+ -e 's/^[^ ]* [A-Z] \(.*\)$$/\1/' \
+ -e 's/\<_Z[^ ]*$$/&;/p' \
+ -e 's/\<VBoxNs[^ ]*$$/&;/p' \
+ -e 's/\<_edata$$/&;/p' \
+ -e 's/\<_end$$/&;/p' \
+ -e 's/\<_etext$$/&;/p'\
+ -e 's/\<_fini$$/&;/p' \
+ -e 's/\<_init$$/&;/p' \
+ --append $@
+ $(QUIET)$(APPEND) $@ '};'
+#ifeq ($(KBUILD_TARGET),solaris)
+# # Temporary gcc 4.5.2 hack on Solaris which emits unknown mangled symbols for ctors/dtors for certain objects. See @bugref{5838}.
+# if $(VBOX_GCC_VERSION_CXX) == 40502
+# $(QUIET)$(SED) -re '/^_Z.*[C-D]5E/d' $@ > $@-sedtmp
+# $(QUIET)$(MV) $@-sedtmp $@
+# endif
+#endif
+
diff --git a/src/libs/xpcom18a4/VBoxXPCOM-mangled.def b/src/libs/xpcom18a4/VBoxXPCOM-mangled.def
new file mode 100644
index 00000000..0958999e
--- /dev/null
+++ b/src/libs/xpcom18a4/VBoxXPCOM-mangled.def
@@ -0,0 +1,1688 @@
+; $Id: VBoxXPCOM-mangled.def $
+;; @file
+; VirtualBox XPCOM - Import library definition file.
+
+;
+; Copyright (C) 2018-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+LIBRARY VBoxXPCOM.dll
+EXPORTS
+ ;
+ ; To regenerate run the following command line:
+ ; nm -U ../../../out/darwin.amd64/debug/dist/VirtualBox.app/Contents/MacOS/VBoxXPCOM.dylib | kmk_sed -r -e 's/^[0-9a-fA-F]+ //' -e '/^[A-Z]/!d' | sort | kmk_sed -r -e 's/[SDBC] (.+)$/ \1 DATA/' -e 's/^[A-Z] / /' -e 's/^ _/ /' >> VBoxXPCOM-mangled.def
+ ;
+
+ _ZN12nsCharTraitsIcE12sEmptyBufferE DATA
+ _ZN12nsCharTraitsItE12sEmptyBufferE DATA
+ NSGetStaticModuleInfo DATA
+ VBoxNsxpgFastLoadService_ DATA
+ _ZN17nsObsoleteAString16sCanonicalVTableE DATA
+ _ZN18nsObsoleteACString16sCanonicalVTableE DATA
+ _ZTV11nsHashtable DATA
+ _ZTV11nsLocalFile DATA
+ _ZTV11nsStringKey DATA
+ _ZTV11nsVoidArray DATA
+ _ZTV12nsCStringKey DATA
+ _ZTV13nsStringArray DATA
+ _ZTV14nsCStringArray DATA
+ _ZTV14nsGetInterface DATA
+ _ZTV14nsISupportsKey DATA
+ _ZTV14nsXPTCStubBase DATA
+ _ZTV15nsAutoVoidArray DATA
+ _ZTV15nsQueryReferent DATA
+ _ZTV15nsSupportsArray DATA
+ _ZTV15nsWeakReference DATA
+ _ZTV16nsQueryElementAt DATA
+ _ZTV17nsArrayEnumerator DATA
+ _ZTV17nsGetServiceByCID DATA
+ _ZTV17nsObjectHashtable DATA
+ _ZTV17nsUnionEnumerator DATA
+ _ZTV18nsGetWeakReference DATA
+ _ZTV19nsDirEnumeratorUnix DATA
+ _ZTV19nsSupportsHashtable DATA
+ _ZTV21nsCreateInstanceByCID DATA
+ _ZTV21nsQueryArrayElementAt DATA
+ _ZTV21nsSingletonEnumerator DATA
+ _ZTV23nsSupportsWeakReference DATA
+ _ZTV24nsGetServiceByContractID DATA
+ _ZTV25nsDefaultStringComparator DATA
+ _ZTV26nsDefaultCStringComparator DATA
+ _ZTV28nsCreateInstanceByContractID DATA
+ _ZTV28nsCreateInstanceFromCategory DATA
+ _ZTV34nsCaseInsensitiveCStringComparator DATA
+ _ZTV7nsIDKey DATA
+ _ZTV9nsHashKey DATA
+ _ZTV9nsVariant DATA
+ VBoxNsllLL_MaxInt
+ VBoxNsllLL_MaxUint
+ VBoxNsllLL_MinInt
+ VBoxNsllLL_Zero
+ VBoxNsplPL_ArenaAllocate
+ VBoxNsplPL_ArenaFinish
+ VBoxNsplPL_ArenaGrow
+ VBoxNsplPL_ArenaRelease
+ VBoxNsplPL_CompactArenaPool
+ VBoxNsplPL_CompareStrings
+ VBoxNsplPL_CompareValues
+ VBoxNsplPL_CreateEventQueue
+ VBoxNsplPL_CreateMonitoredEventQueue
+ VBoxNsplPL_CreateNativeEventQueue
+ VBoxNsplPL_DHashAllocTable
+ VBoxNsplPL_DHashClearEntryStub
+ VBoxNsplPL_DHashFinalizeStub
+ VBoxNsplPL_DHashFreeStringKey
+ VBoxNsplPL_DHashFreeTable
+ VBoxNsplPL_DHashGetKeyStub
+ VBoxNsplPL_DHashGetStubOps
+ VBoxNsplPL_DHashMatchEntryStub
+ VBoxNsplPL_DHashMatchStringKey
+ VBoxNsplPL_DHashMoveEntryStub
+ VBoxNsplPL_DHashStringKey
+ VBoxNsplPL_DHashTableDestroy
+ VBoxNsplPL_DHashTableEnumerate
+ VBoxNsplPL_DHashTableFinish
+ VBoxNsplPL_DHashTableInit
+ VBoxNsplPL_DHashTableOperate
+ VBoxNsplPL_DHashTableRawRemove
+ VBoxNsplPL_DHashTableSetAlphaBounds
+ VBoxNsplPL_DHashVoidPtrKeyStub
+ VBoxNsplPL_DequeueEvent
+ VBoxNsplPL_DestroyEvent
+ VBoxNsplPL_DestroyEventQueue
+ VBoxNsplPL_EventAvailable
+ VBoxNsplPL_EventLoop
+ VBoxNsplPL_FavorPerformanceHint
+ VBoxNsplPL_FinishArenaPool
+ VBoxNsplPL_FreeArenaPool
+ VBoxNsplPL_GetEvent
+ VBoxNsplPL_GetEventOwner
+ VBoxNsplPL_GetEventQueueMonitor
+ VBoxNsplPL_GetEventQueueSelectFD
+ VBoxNsplPL_HandleEvent
+ VBoxNsplPL_HashString
+ VBoxNsplPL_HashTableAdd
+ VBoxNsplPL_HashTableDestroy
+ VBoxNsplPL_HashTableDump
+ VBoxNsplPL_HashTableEnumerateEntries
+ VBoxNsplPL_HashTableLookup
+ VBoxNsplPL_HashTableLookupConst
+ VBoxNsplPL_HashTableRawAdd
+ VBoxNsplPL_HashTableRawLookup
+ VBoxNsplPL_HashTableRawLookupConst
+ VBoxNsplPL_HashTableRawRemove
+ VBoxNsplPL_HashTableRemove
+ VBoxNsplPL_InitArenaPool
+ VBoxNsplPL_InitEvent
+ VBoxNsplPL_IsQueueNative
+ VBoxNsplPL_IsQueueOnCurrentThread
+ VBoxNsplPL_MapEvents
+ VBoxNsplPL_NewDHashTable
+ VBoxNsplPL_NewHashTable
+ VBoxNsplPL_PostEvent
+ VBoxNsplPL_PostSynchronousEvent
+ VBoxNsplPL_ProcessPendingEvents
+ VBoxNsplPL_RevokeEvents
+ VBoxNsplPL_WaitForEvent
+ VBoxNsplPL_strcasecmp
+ VBoxNsplPL_strchr
+ VBoxNsplPL_strcmp
+ VBoxNsplPL_strcpy
+ VBoxNsplPL_strdup
+ VBoxNsplPL_strfree
+ VBoxNsplPL_strlen
+ VBoxNsplPL_strncasecmp
+ VBoxNsplPL_strnchr
+ VBoxNsplPL_strncmp
+ VBoxNsplPL_strncpy
+ VBoxNsplPL_strncpyz
+ VBoxNsplPL_strndup
+ VBoxNsplPL_strnlen
+ VBoxNsplPL_strnrchr
+ VBoxNsplPL_strnrstr
+ VBoxNsplPL_strnstr
+ VBoxNsplPL_strrchr
+ VBoxNsplPL_strrstr
+ VBoxNsplPL_strstr
+ VBoxNsprGetExecutionEnvironment
+ VBoxNsprPRP_DestroyNakedCondVar
+ VBoxNsprPRP_NakedBroadcast
+ VBoxNsprPRP_NakedNotify
+ VBoxNsprPRP_NakedWait
+ VBoxNsprPRP_NewNakedCondVar
+ VBoxNsprPRP_TryLock
+ VBoxNsprPR_Abort
+ VBoxNsprPR_Accept
+ VBoxNsprPR_AcceptRead
+ VBoxNsprPR_Access
+ VBoxNsprPR_AddWaitFileDesc
+ VBoxNsprPR_AllocFileDesc
+ VBoxNsprPR_Assert
+ VBoxNsprPR_AtomicAdd
+ VBoxNsprPR_AtomicDecrement
+ VBoxNsprPR_AtomicIncrement
+ VBoxNsprPR_AtomicSet
+ VBoxNsprPR_AttachThread
+ VBoxNsprPR_Available
+ VBoxNsprPR_Available64
+ VBoxNsprPR_Bind
+ VBoxNsprPR_BlockClockInterrupts
+ VBoxNsprPR_BlockInterrupt
+ VBoxNsprPR_CEnterMonitor
+ VBoxNsprPR_CExitMonitor
+ VBoxNsprPR_CNotify
+ VBoxNsprPR_CNotifyAll
+ VBoxNsprPR_CSetOnMonitorRecycle
+ VBoxNsprPR_CWait
+ VBoxNsprPR_CallOnce
+ VBoxNsprPR_CallOnceWithArg
+ VBoxNsprPR_Calloc
+ VBoxNsprPR_CancelWaitFileDesc
+ VBoxNsprPR_CancelWaitGroup
+ VBoxNsprPR_CeilingLog2
+ VBoxNsprPR_ChangeFileDescNativeHandle
+ VBoxNsprPR_Cleanup
+ VBoxNsprPR_ClearInterrupt
+ VBoxNsprPR_ClearThreadGCAble
+ VBoxNsprPR_Close
+ VBoxNsprPR_CloseDir
+ VBoxNsprPR_CloseFileMap
+ VBoxNsprPR_CloseSemaphore
+ VBoxNsprPR_Connect
+ VBoxNsprPR_ConnectContinue
+ VBoxNsprPR_ConvertIPv4AddrToIPv6
+ VBoxNsprPR_CreateFileMap
+ VBoxNsprPR_CreateIOLayer
+ VBoxNsprPR_CreateIOLayerStub
+ VBoxNsprPR_CreateMWaitEnumerator
+ VBoxNsprPR_CreatePipe
+ VBoxNsprPR_CreateProcess
+ VBoxNsprPR_CreateProcessDetached
+ VBoxNsprPR_CreateSocketPollFd
+ VBoxNsprPR_CreateStack
+ VBoxNsprPR_CreateThread
+ VBoxNsprPR_CreateThreadGCAble
+ VBoxNsprPR_CreateWaitGroup
+ VBoxNsprPR_Delete
+ VBoxNsprPR_DeleteSemaphore
+ VBoxNsprPR_DestroyCondVar
+ VBoxNsprPR_DestroyLock
+ VBoxNsprPR_DestroyMWaitEnumerator
+ VBoxNsprPR_DestroyMonitor
+ VBoxNsprPR_DestroyPollableEvent
+ VBoxNsprPR_DestroyProcessAttr
+ VBoxNsprPR_DestroyRWLock
+ VBoxNsprPR_DestroySem
+ VBoxNsprPR_DestroySocketPollFd
+ VBoxNsprPR_DestroyStack
+ VBoxNsprPR_DestroyWaitGroup
+ VBoxNsprPR_DetachProcess
+ VBoxNsprPR_DetachThread
+ VBoxNsprPR_DisableClockInterrupts
+ VBoxNsprPR_EmulateAcceptRead
+ VBoxNsprPR_EmulateSendFile
+ VBoxNsprPR_EnableClockInterrupts
+ VBoxNsprPR_EnterMonitor
+ VBoxNsprPR_EnumerateAddrInfo
+ VBoxNsprPR_EnumerateHostEnt
+ VBoxNsprPR_EnumerateThreads
+ VBoxNsprPR_EnumerateWaitGroup
+ VBoxNsprPR_ErrorInstallCallback
+ VBoxNsprPR_ErrorInstallTable
+ VBoxNsprPR_ErrorLanguages
+ VBoxNsprPR_ErrorToName
+ VBoxNsprPR_ErrorToString
+ VBoxNsprPR_ExitMonitor
+ VBoxNsprPR_ExplodeTime
+ VBoxNsprPR_FD_CLR
+ VBoxNsprPR_FD_ISSET
+ VBoxNsprPR_FD_NCLR
+ VBoxNsprPR_FD_NISSET
+ VBoxNsprPR_FD_NSET
+ VBoxNsprPR_FD_SET
+ VBoxNsprPR_FD_ZERO
+ VBoxNsprPR_FPrintZoneStats
+ VBoxNsprPR_FileDesc2NativeHandle
+ VBoxNsprPR_FindFunctionSymbol
+ VBoxNsprPR_FindFunctionSymbolAndLibrary
+ VBoxNsprPR_FindLibrary
+ VBoxNsprPR_FindSymbol
+ VBoxNsprPR_FindSymbolAndLibrary
+ VBoxNsprPR_FloorLog2
+ VBoxNsprPR_FormatTime
+ VBoxNsprPR_FormatTimeUSEnglish
+ VBoxNsprPR_Free
+ VBoxNsprPR_FreeAddrInfo
+ VBoxNsprPR_FreeLibraryName
+ VBoxNsprPR_GMTParameters
+ VBoxNsprPR_GetAddrInfoByName
+ VBoxNsprPR_GetCanonNameFromAddrInfo
+ VBoxNsprPR_GetConnectStatus
+ VBoxNsprPR_GetCurrentThread
+ VBoxNsprPR_GetDefaultIOMethods
+ VBoxNsprPR_GetDescType
+ VBoxNsprPR_GetEnv
+ VBoxNsprPR_GetError
+ VBoxNsprPR_GetErrorText
+ VBoxNsprPR_GetErrorTextLength
+ VBoxNsprPR_GetFileInfo
+ VBoxNsprPR_GetFileInfo64
+ VBoxNsprPR_GetFileMethods
+ VBoxNsprPR_GetHostByAddr
+ VBoxNsprPR_GetHostByName
+ VBoxNsprPR_GetIPNodeByName
+ VBoxNsprPR_GetIdentitiesLayer
+ VBoxNsprPR_GetInheritedFD
+ VBoxNsprPR_GetLayersIdentity
+ VBoxNsprPR_GetLibraryFilePathname
+ VBoxNsprPR_GetLibraryName
+ VBoxNsprPR_GetLibraryPath
+ VBoxNsprPR_GetMemMapAlignment
+ VBoxNsprPR_GetMonitorEntryCount
+ VBoxNsprPR_GetNameForIdentity
+ VBoxNsprPR_GetOSError
+ VBoxNsprPR_GetOpenFileInfo
+ VBoxNsprPR_GetOpenFileInfo64
+ VBoxNsprPR_GetPageShift
+ VBoxNsprPR_GetPageSize
+ VBoxNsprPR_GetPeerName
+ VBoxNsprPR_GetPipeMethods
+ VBoxNsprPR_GetProtoByName
+ VBoxNsprPR_GetProtoByNumber
+ VBoxNsprPR_GetSP
+ VBoxNsprPR_GetSockName
+ VBoxNsprPR_GetSocketOption
+ VBoxNsprPR_GetSpecialFD
+ VBoxNsprPR_GetTCPMethods
+ VBoxNsprPR_GetThreadAffinityMask
+ VBoxNsprPR_GetThreadID
+ VBoxNsprPR_GetThreadPriority
+ VBoxNsprPR_GetThreadPrivate
+ VBoxNsprPR_GetThreadScope
+ VBoxNsprPR_GetThreadState
+ VBoxNsprPR_GetThreadType
+ VBoxNsprPR_GetUDPMethods
+ VBoxNsprPR_GetUniqueIdentity
+ VBoxNsprPR_ImplodeTime
+ VBoxNsprPR_ImportFile
+ VBoxNsprPR_ImportPipe
+ VBoxNsprPR_ImportTCPSocket
+ VBoxNsprPR_ImportUDPSocket
+ VBoxNsprPR_Init
+ VBoxNsprPR_Initialize
+ VBoxNsprPR_InitializeNetAddr
+ VBoxNsprPR_Initialized
+ VBoxNsprPR_Interrupt
+ VBoxNsprPR_IntervalNow
+ VBoxNsprPR_IntervalToMicroseconds
+ VBoxNsprPR_IntervalToMilliseconds
+ VBoxNsprPR_IntervalToSeconds
+ VBoxNsprPR_IsNetAddrType
+ VBoxNsprPR_JoinThread
+ VBoxNsprPR_KillProcess
+ VBoxNsprPR_Listen
+ VBoxNsprPR_LoadLibrary
+ VBoxNsprPR_LoadLibraryWithFlags
+ VBoxNsprPR_LoadStaticLibrary
+ VBoxNsprPR_LocalTimeParameters
+ VBoxNsprPR_Lock
+ VBoxNsprPR_LockFile
+ VBoxNsprPR_LogFlush
+ VBoxNsprPR_LogPrint
+ VBoxNsprPR_MakeDir
+ VBoxNsprPR_Malloc
+ VBoxNsprPR_MemMap
+ VBoxNsprPR_MemUnmap
+ VBoxNsprPR_MicrosecondsToInterval
+ VBoxNsprPR_MillisecondsToInterval
+ VBoxNsprPR_MkDir
+ VBoxNsprPR_NetAddrToString
+ VBoxNsprPR_NewCondVar
+ VBoxNsprPR_NewLock
+ VBoxNsprPR_NewLogModule
+ VBoxNsprPR_NewMonitor
+ VBoxNsprPR_NewNamedMonitor
+ VBoxNsprPR_NewPollableEvent
+ VBoxNsprPR_NewProcessAttr
+ VBoxNsprPR_NewRWLock
+ VBoxNsprPR_NewSem
+ VBoxNsprPR_NewTCPSocket
+ VBoxNsprPR_NewTCPSocketPair
+ VBoxNsprPR_NewThreadPrivateIndex
+ VBoxNsprPR_NewUDPSocket
+ VBoxNsprPR_NormalizeTime
+ VBoxNsprPR_Notify
+ VBoxNsprPR_NotifyAll
+ VBoxNsprPR_NotifyAllCondVar
+ VBoxNsprPR_NotifyCondVar
+ VBoxNsprPR_Now
+ VBoxNsprPR_Open
+ VBoxNsprPR_OpenDir
+ VBoxNsprPR_OpenFile
+ VBoxNsprPR_OpenSemaphore
+ VBoxNsprPR_OpenTCPSocket
+ VBoxNsprPR_OpenUDPSocket
+ VBoxNsprPR_ParseTimeString
+ VBoxNsprPR_Poll
+ VBoxNsprPR_PopIOLayer
+ VBoxNsprPR_PostSem
+ VBoxNsprPR_PostSemaphore
+ VBoxNsprPR_ProcessAttrSetCurrentDirectory
+ VBoxNsprPR_ProcessAttrSetInheritableFD
+ VBoxNsprPR_ProcessAttrSetStdioRedirect
+ VBoxNsprPR_ProcessExit
+ VBoxNsprPR_PushIOLayer
+ VBoxNsprPR_RWLock_Rlock
+ VBoxNsprPR_RWLock_Unlock
+ VBoxNsprPR_RWLock_Wlock
+ VBoxNsprPR_Read
+ VBoxNsprPR_ReadDir
+ VBoxNsprPR_Realloc
+ VBoxNsprPR_Recv
+ VBoxNsprPR_RecvFrom
+ VBoxNsprPR_Rename
+ VBoxNsprPR_ResetProcessAttr
+ VBoxNsprPR_ResumeAll
+ VBoxNsprPR_RmDir
+ VBoxNsprPR_SecondsToInterval
+ VBoxNsprPR_Seek
+ VBoxNsprPR_Seek64
+ VBoxNsprPR_Select
+ VBoxNsprPR_Send
+ VBoxNsprPR_SendFile
+ VBoxNsprPR_SendTo
+ VBoxNsprPR_SetConcurrency
+ VBoxNsprPR_SetEnv
+ VBoxNsprPR_SetError
+ VBoxNsprPR_SetErrorText
+ VBoxNsprPR_SetFDCacheSize
+ VBoxNsprPR_SetFDInheritable
+ VBoxNsprPR_SetLibraryPath
+ VBoxNsprPR_SetLogBuffering
+ VBoxNsprPR_SetLogFile
+ VBoxNsprPR_SetNetAddr
+ VBoxNsprPR_SetPollableEvent
+ VBoxNsprPR_SetSocketOption
+ VBoxNsprPR_SetStdioRedirect
+ VBoxNsprPR_SetThreadAffinityMask
+ VBoxNsprPR_SetThreadDumpProc
+ VBoxNsprPR_SetThreadGCAble
+ VBoxNsprPR_SetThreadPriority
+ VBoxNsprPR_SetThreadPrivate
+ VBoxNsprPR_SetThreadRecycleMode
+ VBoxNsprPR_Shutdown
+ VBoxNsprPR_Sleep
+ VBoxNsprPR_Socket
+ VBoxNsprPR_StackPop
+ VBoxNsprPR_StackPush
+ VBoxNsprPR_Stat
+ VBoxNsprPR_StringToNetAddr
+ VBoxNsprPR_SuspendAll
+ VBoxNsprPR_Sync
+ VBoxNsprPR_TLockFile
+ VBoxNsprPR_TicksPerSecond
+ VBoxNsprPR_TransmitFile
+ VBoxNsprPR_USPacificTimeParameters
+ VBoxNsprPR_UnblockClockInterrupts
+ VBoxNsprPR_UnblockInterrupt
+ VBoxNsprPR_UnloadLibrary
+ VBoxNsprPR_Unlock
+ VBoxNsprPR_UnlockFile
+ VBoxNsprPR_VersionCheck
+ VBoxNsprPR_Wait
+ VBoxNsprPR_WaitCondVar
+ VBoxNsprPR_WaitForPollableEvent
+ VBoxNsprPR_WaitProcess
+ VBoxNsprPR_WaitRecvReady
+ VBoxNsprPR_WaitSem
+ VBoxNsprPR_WaitSemaphore
+ VBoxNsprPR_Write
+ VBoxNsprPR_Writev
+ VBoxNsprPR_Yield
+ VBoxNsprPR_cnvtf
+ VBoxNsprPR_dtoa
+ VBoxNsprPR_fprintf
+ VBoxNsprPR_htonl
+ VBoxNsprPR_htonll
+ VBoxNsprPR_htons
+ VBoxNsprPR_ntohl
+ VBoxNsprPR_ntohll
+ VBoxNsprPR_ntohs
+ VBoxNsprPR_smprintf
+ VBoxNsprPR_smprintf_free
+ VBoxNsprPR_snprintf
+ VBoxNsprPR_sprintf_append
+ VBoxNsprPR_sscanf
+ VBoxNsprPR_strtod
+ VBoxNsprPR_sxprintf
+ VBoxNsprPR_vfprintf
+ VBoxNsprPR_vsmprintf
+ VBoxNsprPR_vsnprintf
+ VBoxNsprPR_vsprintf_append
+ VBoxNsprPR_vsxprintf
+ VBoxNsprPT_FPrintStats
+ VBoxNsprSetExecutionEnvironment
+ VBoxNsxpNS_CStringCloneData
+ VBoxNsxpNS_CStringContainerFinish
+ VBoxNsxpNS_CStringContainerInit
+ VBoxNsxpNS_CStringCopy
+ VBoxNsxpNS_CStringGetData
+ VBoxNsxpNS_CStringSetData
+ VBoxNsxpNS_CStringSetDataRange
+ VBoxNsxpNS_CStringToUTF16
+ VBoxNsxpNS_GetComponentManager
+ VBoxNsxpNS_GetComponentRegistrar
+ VBoxNsxpNS_GetDebug
+ VBoxNsxpNS_GetFrozenFunctions
+ VBoxNsxpNS_GetMemoryManager
+ VBoxNsxpNS_GetServiceManager
+ VBoxNsxpNS_GetTraceRefcnt
+ VBoxNsxpNS_InitXPCOM2
+ VBoxNsxpNS_MeanAndStdDev
+ VBoxNsxpNS_NewByteInputStream
+ VBoxNsxpNS_NewCStringInputStream
+ VBoxNsxpNS_NewCharInputStream
+ VBoxNsxpNS_NewEmptyEnumerator
+ VBoxNsxpNS_NewLocalFile
+ VBoxNsxpNS_NewNativeLocalFile
+ VBoxNsxpNS_NewSingletonEnumerator
+ VBoxNsxpNS_NewStringInputStream
+ VBoxNsxpNS_NewUnionEnumerator
+ VBoxNsxpNS_QuickSort
+ VBoxNsxpNS_RegisterXPCOMExitRoutine
+ VBoxNsxpNS_ShutdownXPCOM
+ VBoxNsxpNS_StringCloneData
+ VBoxNsxpNS_StringContainerFinish
+ VBoxNsxpNS_StringContainerInit
+ VBoxNsxpNS_StringCopy
+ VBoxNsxpNS_StringGetData
+ VBoxNsxpNS_StringSetData
+ VBoxNsxpNS_StringSetDataRange
+ VBoxNsxpNS_UTF16ToCString
+ VBoxNsxpNS_UnregisterXPCOMExitRoutine
+ VBoxNsxpXPTC_InvokeByIndex
+ VBoxNsxpXPTI_FreeInterfaceInfoManager
+ VBoxNsxpXPTI_GetInterfaceInfoManager
+ VBoxNsxpXPT_ArenaFree
+ VBoxNsxpXPT_ArenaMalloc
+ VBoxNsxpXPT_ArenaStrDup
+ VBoxNsxpXPT_AssertFailed
+ VBoxNsxpXPT_DataOffset
+ VBoxNsxpXPT_DestroyArena
+ VBoxNsxpXPT_DestroyInterfaceDirectoryEntry
+ VBoxNsxpXPT_DestroyXDRState
+ VBoxNsxpXPT_Do16
+ VBoxNsxpXPT_Do32
+ VBoxNsxpXPT_Do64
+ VBoxNsxpXPT_Do8
+ VBoxNsxpXPT_DoCString
+ VBoxNsxpXPT_DoHeader
+ VBoxNsxpXPT_DoHeaderPrologue
+ VBoxNsxpXPT_DoIID
+ VBoxNsxpXPT_DoString
+ VBoxNsxpXPT_DoStringInline
+ VBoxNsxpXPT_DumpStats
+ VBoxNsxpXPT_FillInterfaceDirectoryEntry
+ VBoxNsxpXPT_FillMethodDescriptor
+ VBoxNsxpXPT_FillParamDescriptor
+ VBoxNsxpXPT_FreeHeader
+ VBoxNsxpXPT_FreeInterfaceDescriptor
+ VBoxNsxpXPT_GetAddrForOffset
+ VBoxNsxpXPT_GetInterfaceIndexByName
+ VBoxNsxpXPT_GetOffsetForAddr
+ VBoxNsxpXPT_GetXDRData
+ VBoxNsxpXPT_GetXDRDataLength
+ VBoxNsxpXPT_InterfaceDescriptorAddConsts
+ VBoxNsxpXPT_InterfaceDescriptorAddMethods
+ VBoxNsxpXPT_InterfaceDescriptorAddTypes
+ VBoxNsxpXPT_MakeCursor
+ VBoxNsxpXPT_NewAnnotation
+ VBoxNsxpXPT_NewArena
+ VBoxNsxpXPT_NewHeader
+ VBoxNsxpXPT_NewInterfaceDescriptor
+ VBoxNsxpXPT_NewString
+ VBoxNsxpXPT_NewStringZ
+ VBoxNsxpXPT_NewXDRState
+ VBoxNsxpXPT_NotifyDoneLoading
+ VBoxNsxpXPT_ParseVersionString
+ VBoxNsxpXPT_SeekTo
+ VBoxNsxpXPT_SetAddrForOffset
+ VBoxNsxpXPT_SetDataOffset
+ VBoxNsxpXPT_SetOffsetForAddr
+ VBoxNsxpXPT_SizeOfHeader
+ VBoxNsxpXPT_SizeOfHeaderBlock
+ _MD_LockFile
+ _MD_TLockFile
+ _MD_UnlockFile
+ _MD_gethostname
+ _MD_getsysinfo
+ _MD_unix_map_accept_error
+ _MD_unix_map_access_error
+ _MD_unix_map_bind_error
+ _MD_unix_map_close_error
+ _MD_unix_map_closedir_error
+ _MD_unix_map_connect_error
+ _MD_unix_map_default_error
+ _MD_unix_map_flock_error
+ _MD_unix_map_fstat_error
+ _MD_unix_map_fsync_error
+ _MD_unix_map_gethostname_error
+ _MD_unix_map_getpeername_error
+ _MD_unix_map_getsockname_error
+ _MD_unix_map_getsockopt_error
+ _MD_unix_map_listen_error
+ _MD_unix_map_lockf_error
+ _MD_unix_map_lseek_error
+ _MD_unix_map_mkdir_error
+ _MD_unix_map_mmap_error
+ _MD_unix_map_open_error
+ _MD_unix_map_opendir_error
+ _MD_unix_map_poll_error
+ _MD_unix_map_poll_revents_error
+ _MD_unix_map_read_error
+ _MD_unix_map_recv_error
+ _MD_unix_map_recvfrom_error
+ _MD_unix_map_rename_error
+ _MD_unix_map_rmdir_error
+ _MD_unix_map_select_error
+ _MD_unix_map_send_error
+ _MD_unix_map_sendto_error
+ _MD_unix_map_setsockopt_error
+ _MD_unix_map_shutdown_error
+ _MD_unix_map_socket_error
+ _MD_unix_map_socketavailable_error
+ _MD_unix_map_socketpair_error
+ _MD_unix_map_stat_error
+ _MD_unix_map_unlink_error
+ _MD_unix_map_write_error
+ _MD_unix_map_writev_error
+ _MD_unix_readdir_error
+ _Z10HashStringRK10nsACString
+ _Z10HashStringRK9nsAString
+ _Z10NS_NewAtomPKc
+ _Z10NS_NewAtomPKt
+ _Z10NS_NewAtomRK10nsACString
+ _Z10NS_NewAtomRK9nsAString
+ _Z11EmptyStringv
+ _Z11NS_NewArrayPP15nsIMutableArray
+ _Z11NS_NewArrayPP15nsIMutableArrayRK15nsCOMArray_base
+ _Z11NS_NewPipe2PP19nsIAsyncInputStreamPP20nsIAsyncOutputStreamiijjP9nsIMemory
+ _Z11ToLowerCaseR10nsACString
+ _Z11ToLowerCaseR12nsCSubstring
+ _Z11ToLowerCaseRK10nsACStringRS_
+ _Z11ToUpperCaseR10nsACString
+ _Z11ToUpperCaseR12nsCSubstring
+ _Z11ToUpperCaseRK10nsACStringRS_
+ _Z12EmptyCStringv
+ _Z12NS_AsyncCopyP14nsIInputStreamP15nsIOutputStreamP14nsIEventTarget15nsAsyncCopyModejPFvPvjES6_
+ _Z12NS_InitXPCOMPP17nsIServiceManagerP7nsIFile
+ _Z12NS_NewThreadPP9nsIThreadP11nsIRunnablej13PRThreadState16PRThreadPriority13PRThreadScope
+ _Z12NS_NewThreadPP9nsIThreadj13PRThreadState16PRThreadPriority13PRThreadScope
+ _Z12ToNewCStringRK10nsACString
+ _Z12ToNewCStringRK9nsAString
+ _Z12ToNewUnicodeRK10nsACString
+ _Z12ToNewUnicodeRK9nsAString
+ _Z13CopyUnicodeToRK17nsReadingIteratorItES2_R9nsAString
+ _Z13CopyUnicodeToRK9nsAStringjPtj
+ _Z14FindInReadableRK10nsACStringR17nsReadingIteratorIcES4_RK19nsCStringComparator
+ _Z14FindInReadableRK9nsAStringR17nsReadingIteratorItES4_RK18nsStringComparator
+ _Z14StringEndsWithRK10nsACStringS1_RK19nsCStringComparator
+ _Z14StringEndsWithRK9nsAStringS1_RK18nsStringComparator
+ _Z15AppendUnicodeToRK17nsReadingIteratorItES2_R9nsAString
+ _Z15CopyUTF16toUTF8PKtR10nsACString
+ _Z15CopyUTF16toUTF8RK9nsAStringR10nsACString
+ _Z15CopyUTF8toUTF16PKcR9nsAString
+ _Z15CopyUTF8toUTF16RK10nsACStringR9nsAString
+ _Z15NS_ProxyReleaseP14nsIEventTargetP11nsISupportsi
+ _Z15RFindInReadableRK10nsACStringR17nsReadingIteratorIcES4_RK19nsCStringComparator
+ _Z15RFindInReadableRK9nsAStringR17nsReadingIteratorItES4_RK18nsStringComparator
+ _Z15ToNewUTF8StringRK9nsAStringPj
+ _Z16CopyASCIItoUTF16PKcR9nsAString
+ _Z16CopyASCIItoUTF16RK10nsACStringR9nsAString
+ _Z16NS_NewByteBufferPP13nsIByteBufferP11nsISupportsj
+ _Z16StringBeginsWithRK10nsACStringS1_RK19nsCStringComparator
+ _Z16StringBeginsWithRK9nsAStringS1_RK18nsStringComparator
+ _Z16UTF8ToNewUnicodeRK10nsACStringPj
+ _Z17AppendUTF16toUTF8PKtR10nsACString
+ _Z17AppendUTF16toUTF8RK9nsAStringR10nsACString
+ _Z17AppendUTF8toUTF16PKcR9nsAString
+ _Z17AppendUTF8toUTF16RK10nsACStringR9nsAString
+ _Z18AppendASCIItoUTF16PKcR9nsAString
+ _Z18AppendASCIItoUTF16RK10nsACStringR9nsAString
+ _Z18FindCharInReadablecR17nsReadingIteratorIcERKS0_
+ _Z18FindCharInReadabletR17nsReadingIteratorItERKS0_
+ _Z19CountCharInReadableRK10nsACStringc
+ _Z19CountCharInReadableRK9nsAStringt
+ _Z19NS_GetNumberOfAtomsv
+ _Z19NS_GetWeakReferenceP11nsISupportsPj
+ _Z19NS_NewGenericModulePKcjP21nsModuleComponentInfoPFvP9nsIModuleEPS4_
+ _Z19NS_NewPermanentAtomPKc
+ _Z19NS_NewPermanentAtomPKt
+ _Z19NS_NewPermanentAtomRK10nsACString
+ _Z19NS_NewPermanentAtomRK9nsAString
+ _Z19NS_NewStorageStreamjjPP16nsIStorageStream
+ _Z19NS_NewUnicharBufferPP16nsIUnicharBufferP11nsISupportsj
+ _Z19TestSegmentedBufferv
+ _Z20NS_GetProxyForObjectP13nsIEventQueueRK4nsIDP11nsISupportsiPPv
+ _Z20NS_NewGenericFactoryPP17nsIGenericFactoryPK21nsModuleComponentInfo
+ _Z20NS_NewGenericModule2P12nsModuleInfoPP9nsIModule
+ _Z20NS_NewISupportsArrayPP16nsISupportsArray
+ _Z21LossyCopyUTF16toASCIIPKtR10nsACString
+ _Z21LossyCopyUTF16toASCIIRK9nsAStringR10nsACString
+ _Z21NS_NewArrayEnumeratorPP19nsISimpleEnumeratorP16nsISupportsArray
+ _Z21NS_NewArrayEnumeratorPP19nsISimpleEnumeratorP8nsIArray
+ _Z21NS_NewArrayEnumeratorPP19nsISimpleEnumeratorRK15nsCOMArray_base
+ _Z22NS_CopyNativeToUnicodeRK10nsACStringR9nsAString
+ _Z22NS_CopyUnicodeToNativeRK9nsAStringR10nsACString
+ _Z22NS_RegisterStaticAtomsPK12nsStaticAtomj
+ _Z22PL_DHashStubEnumRemoveP12PLDHashTableP15PLDHashEntryHdrjPv
+ _Z23LossyAppendUTF16toASCIIPKtR10nsACString
+ _Z23LossyAppendUTF16toASCIIRK9nsAStringR10nsACString
+ _Z23NS_AddFastLoadChecksumsjjj
+ _Z23NS_ErrorAccordingToNSPRv
+ _Z24NS_NewFastLoadFileReaderPP20nsIObjectInputStreamP14nsIInputStream
+ _Z24NS_NewFastLoadFileWriterPP21nsIObjectOutputStreamP15nsIOutputStreamP17nsIFastLoadFileIO
+ _Z25NS_NewFastLoadFileUpdaterPP21nsIObjectOutputStreamP15nsIOutputStreamP20nsIObjectInputStream
+ _Z25NS_NewUTF8ConverterStreamPP21nsIUnicharInputStreamP14nsIInputStreami
+ _Z27NS_NewInputStreamReadyEventPP22nsIInputStreamCallbackS0_P14nsIEventTarget
+ _Z28NS_GetGlobalComponentManagerPP19nsIComponentManager
+ _Z28NS_NewOutputStreamReadyEventPP23nsIOutputStreamCallbackS0_P14nsIEventTarget
+ _Z29CaseInsensitiveFindInReadableRK10nsACStringR17nsReadingIteratorIcES4_
+ _Z29NS_AccumulateFastLoadChecksumPjPKhji
+ _Z29NS_CreateServicesFromCategoryPKcP11nsISupportsS0_
+ _Z29StartupSpecialSystemDirectoryv
+ _Z30NS_NewISupportsArrayEnumeratorP16nsISupportsArrayPP26nsIBidirectionalEnumerator
+ _Z30NS_NewStringUnicharInputStreamPP21nsIUnicharInputStreamP8nsString
+ _Z30ShutdownSpecialSystemDirectoryv
+ _Z6IsUTF8RK10nsACString
+ _Z7CompareRK10nsACStringS1_RK19nsCStringComparator
+ _Z7CompareRK9nsAStringS1_RK18nsStringComparator
+ _Z7IsASCIIRK10nsACString
+ _Z7IsASCIIRK9nsAString
+ _ZN10nsACString11AppendASCIIEPKc
+ _ZN10nsACString11AppendASCIIEPKcj
+ _ZN10nsACString11AssignASCIIEPKc
+ _ZN10nsACString11AssignASCIIEPKcj
+ _ZN10nsACString11SetCapacityEj
+ _ZN10nsACString17GetWritableBufferEPPc
+ _ZN10nsACString3CutEjj
+ _ZN10nsACString6AppendEPKc
+ _ZN10nsACString6AppendEPKcj
+ _ZN10nsACString6AppendERK17nsCSubstringTuple
+ _ZN10nsACString6AppendERKS_
+ _ZN10nsACString6AppendEc
+ _ZN10nsACString6AssignEPKc
+ _ZN10nsACString6AssignEPKcj
+ _ZN10nsACString6AssignERK17nsCSubstringTuple
+ _ZN10nsACString6AssignERKS_
+ _ZN10nsACString6AssignEc
+ _ZN10nsACString6InsertEPKcj
+ _ZN10nsACString6InsertEPKcjj
+ _ZN10nsACString6InsertERK17nsCSubstringTuplej
+ _ZN10nsACString6InsertERKS_j
+ _ZN10nsACString6InsertEcj
+ _ZN10nsACString7ReplaceEjjRK17nsCSubstringTuple
+ _ZN10nsACString7ReplaceEjjRKS_
+ _ZN10nsACString9SetIsVoidEi
+ _ZN10nsACString9SetLengthEj
+ _ZN10nsACStringD1Ev
+ _ZN10nsACStringD2Ev
+ _ZN11nsHashtable3GetEP9nsHashKey
+ _ZN11nsHashtable3PutEP9nsHashKeyPv
+ _ZN11nsHashtable5CloneEv
+ _ZN11nsHashtable5ResetEPFiP9nsHashKeyPvS2_ES2_
+ _ZN11nsHashtable5ResetEv
+ _ZN11nsHashtable6ExistsEP9nsHashKey
+ _ZN11nsHashtable6RemoveEP9nsHashKey
+ _ZN11nsHashtable9EnumerateEPFiP9nsHashKeyPvS2_ES2_
+ _ZN11nsHashtableC1EP20nsIObjectInputStreamPFjS1_PP9nsHashKeyPPvEPFvS1_S3_S5_EPj
+ _ZN11nsHashtableC1Eji
+ _ZN11nsHashtableC2EP20nsIObjectInputStreamPFjS1_PP9nsHashKeyPPvEPFvS1_S3_S5_EPj
+ _ZN11nsHashtableC2Eji
+ _ZN11nsHashtableD0Ev
+ _ZN11nsHashtableD1Ev
+ _ZN11nsHashtableD2Ev
+ _ZN11nsIDHashKey7HashKeyEPK4nsID
+ _ZN11nsLocalFile10GlobalInitEv
+ _ZN11nsLocalFile13FillStatCacheEv
+ _ZN11nsLocalFile14GlobalShutdownEv
+ _ZN11nsLocalFile15CopyDirectoryToEP7nsIFile
+ _ZN11nsLocalFile17CreateAndKeepOpenEjijPP10PRFileDesc
+ _ZN11nsLocalFile18CreateAllAncestorsEj
+ _ZN11nsLocalFile20LocateNativeLeafNameER17nsReadingIteratorIcES2_
+ _ZN11nsLocalFile22nsLocalFileConstructorEP11nsISupportsRK4nsIDPPv
+ _ZN11nsLocalFile23GetNativeTargetPathNameEP7nsIFileRK10nsACStringRS2_
+ _ZN11nsLocalFileC1ERKS_
+ _ZN11nsLocalFileC1Ev
+ _ZN11nsLocalFileC2ERKS_
+ _ZN11nsLocalFileC2Ev
+ _ZN11nsStringKeyC1EP20nsIObjectInputStreamPj
+ _ZN11nsStringKeyC1EPKtiNS_9OwnershipE
+ _ZN11nsStringKeyC1ERK8nsString
+ _ZN11nsStringKeyC1ERK9nsAString
+ _ZN11nsStringKeyC1ERKS_
+ _ZN11nsStringKeyC2EP20nsIObjectInputStreamPj
+ _ZN11nsStringKeyC2EPKtiNS_9OwnershipE
+ _ZN11nsStringKeyC2ERK8nsString
+ _ZN11nsStringKeyC2ERK9nsAString
+ _ZN11nsStringKeyC2ERKS_
+ _ZN11nsStringKeyD0Ev
+ _ZN11nsStringKeyD1Ev
+ _ZN11nsStringKeyD2Ev
+ _ZN11nsSubstring11AssignASCIIEPKc
+ _ZN11nsSubstring11AssignASCIIEPKcj
+ _ZN11nsSubstring11SetCapacityEj
+ _ZN11nsSubstring12ReplaceASCIIEjjPKcj
+ _ZN11nsSubstring13EnsureMutableEv
+ _ZN11nsSubstring5AdoptEPtj
+ _ZN11nsSubstring6AssignEPKtj
+ _ZN11nsSubstring6AssignERK16nsSubstringTuple
+ _ZN11nsSubstring6AssignERK9nsAString
+ _ZN11nsSubstring6AssignERKS_
+ _ZN11nsSubstring7ReplaceEjjPKtj
+ _ZN11nsSubstring7ReplaceEjjRK16nsSubstringTuple
+ _ZN11nsSubstring7ReplaceEjjRK9nsAString
+ _ZN11nsSubstring9SetIsVoidEi
+ _ZN11nsSubstring9SetLengthEj
+ _ZN11nsVoidArray11GrowArrayByEi
+ _ZN11nsVoidArray11MoveElementEii
+ _ZN11nsVoidArray13RemoveElementEPv
+ _ZN11nsVoidArray15InsertElementAtEPvi
+ _ZN11nsVoidArray16InsertElementsAtERKS_i
+ _ZN11nsVoidArray16RemoveElementsAtEii
+ _ZN11nsVoidArray16ReplaceElementAtEPvi
+ _ZN11nsVoidArray17EnumerateForwardsEPFiPvS0_ES0_
+ _ZN11nsVoidArray18EnumerateBackwardsEPFiPvS0_ES0_
+ _ZN11nsVoidArray4SortEPFiPKvS1_PvES2_
+ _ZN11nsVoidArray5ClearEv
+ _ZN11nsVoidArray6SizeToEi
+ _ZN11nsVoidArray7CompactEv
+ _ZN11nsVoidArrayC1Ei
+ _ZN11nsVoidArrayC1Ev
+ _ZN11nsVoidArrayC2Ei
+ _ZN11nsVoidArrayC2Ev
+ _ZN11nsVoidArrayD0Ev
+ _ZN11nsVoidArrayD1Ev
+ _ZN11nsVoidArrayD2Ev
+ _ZN11nsVoidArrayaSERKS_
+ _ZN12nsCStringKeyC1EP20nsIObjectInputStreamPj
+ _ZN12nsCStringKeyC1EPKciNS_9OwnershipE
+ _ZN12nsCStringKeyC1ERK10nsACString
+ _ZN12nsCStringKeyC1ERK9nsCString
+ _ZN12nsCStringKeyC1ERKS_
+ _ZN12nsCStringKeyC2EP20nsIObjectInputStreamPj
+ _ZN12nsCStringKeyC2EPKciNS_9OwnershipE
+ _ZN12nsCStringKeyC2ERK10nsACString
+ _ZN12nsCStringKeyC2ERK9nsCString
+ _ZN12nsCStringKeyC2ERKS_
+ _ZN12nsCStringKeyD0Ev
+ _ZN12nsCStringKeyD1Ev
+ _ZN12nsCStringKeyD2Ev
+ _ZN12nsCSubstring11AssignASCIIEPKc
+ _ZN12nsCSubstring11AssignASCIIEPKcj
+ _ZN12nsCSubstring11SetCapacityEj
+ _ZN12nsCSubstring12ReplaceASCIIEjjPKcj
+ _ZN12nsCSubstring13EnsureMutableEv
+ _ZN12nsCSubstring5AdoptEPcj
+ _ZN12nsCSubstring6AssignEPKcj
+ _ZN12nsCSubstring6AssignERK10nsACString
+ _ZN12nsCSubstring6AssignERK17nsCSubstringTuple
+ _ZN12nsCSubstring6AssignERKS_
+ _ZN12nsCSubstring7ReplaceEjjPKcj
+ _ZN12nsCSubstring7ReplaceEjjRK10nsACString
+ _ZN12nsCSubstring7ReplaceEjjRK17nsCSubstringTuple
+ _ZN12nsCSubstring9SetIsVoidEi
+ _ZN12nsCSubstring9SetLengthEj
+ _ZN13nsAutoMonitor10NewMonitorEPKc
+ _ZN13nsAutoMonitor14DestroyMonitorEP9PRMonitor
+ _ZN13nsAutoMonitor4ExitEv
+ _ZN13nsAutoMonitor5EnterEv
+ _ZN13nsCOMPtr_base14assign_from_qiE16nsQueryInterfaceRK4nsID
+ _ZN13nsCOMPtr_base16begin_assignmentEv
+ _ZN13nsCOMPtr_base18assign_from_helperERK15nsCOMPtr_helperRK4nsID
+ _ZN13nsCOMPtr_base18assign_with_AddRefEP11nsISupports
+ _ZN13nsCOMPtr_base25assign_from_qi_with_errorERK25nsQueryInterfaceWithErrorRK4nsID
+ _ZN13nsCOMPtr_baseD1Ev
+ _ZN13nsCOMPtr_baseD2Ev
+ _ZN13nsStringArray12RemoveStringERK9nsAString
+ _ZN13nsStringArray14InsertStringAtERK9nsAStringi
+ _ZN13nsStringArray14RemoveStringAtEi
+ _ZN13nsStringArray15ReplaceStringAtERK9nsAStringi
+ _ZN13nsStringArray17EnumerateForwardsEPFiR8nsStringPvES2_
+ _ZN13nsStringArray18EnumerateBackwardsEPFiR8nsStringPvES2_
+ _ZN13nsStringArray4SortEPFiPK8nsStringS2_PvES3_
+ _ZN13nsStringArray4SortEv
+ _ZN13nsStringArray5ClearEv
+ _ZN13nsStringArrayC1Ei
+ _ZN13nsStringArrayC1Ev
+ _ZN13nsStringArrayC2Ei
+ _ZN13nsStringArrayC2Ev
+ _ZN13nsStringArrayD0Ev
+ _ZN13nsStringArrayD1Ev
+ _ZN13nsStringArrayD2Ev
+ _ZN13nsStringArrayaSERKS_
+ _ZN13nsTraceRefcnt10LogReleaseEPvjPKc
+ _ZN13nsTraceRefcnt12LogAddCOMPtrEPvP11nsISupports
+ _ZN13nsTraceRefcnt16LogReleaseCOMPtrEPvP11nsISupports
+ _ZN13nsTraceRefcnt7LogCtorEPvPKcj
+ _ZN13nsTraceRefcnt7LogDtorEPvPKcj
+ _ZN13nsTraceRefcnt9LogAddRefEPvjPKcj
+ _ZN14nsAutoCMonitor4ExitEv
+ _ZN14nsAutoCMonitor5EnterEv
+ _ZN14nsAutoLockBase4HideEv
+ _ZN14nsAutoLockBase4ShowEv
+ _ZN14nsAutoLockBaseC1EPvNS_14nsAutoLockTypeE
+ _ZN14nsAutoLockBaseC2EPvNS_14nsAutoLockTypeE
+ _ZN14nsAutoLockBaseD1Ev
+ _ZN14nsAutoLockBaseD2Ev
+ _ZN14nsCStringArray11ParseStringEPKcS1_
+ _ZN14nsCStringArray13RemoveCStringERK10nsACString
+ _ZN14nsCStringArray14SortIgnoreCaseEv
+ _ZN14nsCStringArray15InsertCStringAtERK10nsACStringi
+ _ZN14nsCStringArray15RemoveCStringAtEi
+ _ZN14nsCStringArray16ReplaceCStringAtERK10nsACStringi
+ _ZN14nsCStringArray17EnumerateForwardsEPFiR9nsCStringPvES2_
+ _ZN14nsCStringArray18EnumerateBackwardsEPFiR9nsCStringPvES2_
+ _ZN14nsCStringArray23RemoveCStringIgnoreCaseERK10nsACString
+ _ZN14nsCStringArray4SortEPFiPK9nsCStringS2_PvES3_
+ _ZN14nsCStringArray4SortEv
+ _ZN14nsCStringArray5ClearEv
+ _ZN14nsCStringArrayC1Ei
+ _ZN14nsCStringArrayC1Ev
+ _ZN14nsCStringArrayC2Ei
+ _ZN14nsCStringArrayC2Ev
+ _ZN14nsCStringArrayD0Ev
+ _ZN14nsCStringArrayD1Ev
+ _ZN14nsCStringArrayD2Ev
+ _ZN14nsCStringArrayaSERKS_
+ _ZN14nsISupportsKeyC1EP20nsIObjectInputStreamPj
+ _ZN14nsISupportsKeyC2EP20nsIObjectInputStreamPj
+ _ZN14nsXPTCStubBase14QueryInterfaceERK4nsIDPPv
+ _ZN14nsXPTCStubBase5Stub3Ev
+ _ZN14nsXPTCStubBase5Stub4Ev
+ _ZN14nsXPTCStubBase5Stub5Ev
+ _ZN14nsXPTCStubBase5Stub6Ev
+ _ZN14nsXPTCStubBase5Stub7Ev
+ _ZN14nsXPTCStubBase5Stub8Ev
+ _ZN14nsXPTCStubBase5Stub9Ev
+ _ZN14nsXPTCStubBase6Stub10Ev
+ _ZN14nsXPTCStubBase6Stub11Ev
+ _ZN14nsXPTCStubBase6Stub12Ev
+ _ZN14nsXPTCStubBase6Stub13Ev
+ _ZN14nsXPTCStubBase6Stub14Ev
+ _ZN14nsXPTCStubBase6Stub15Ev
+ _ZN14nsXPTCStubBase6Stub16Ev
+ _ZN14nsXPTCStubBase6Stub17Ev
+ _ZN14nsXPTCStubBase6Stub18Ev
+ _ZN14nsXPTCStubBase6Stub19Ev
+ _ZN14nsXPTCStubBase6Stub20Ev
+ _ZN14nsXPTCStubBase6Stub21Ev
+ _ZN14nsXPTCStubBase6Stub22Ev
+ _ZN14nsXPTCStubBase6Stub23Ev
+ _ZN14nsXPTCStubBase6Stub24Ev
+ _ZN14nsXPTCStubBase6Stub25Ev
+ _ZN14nsXPTCStubBase6Stub26Ev
+ _ZN14nsXPTCStubBase6Stub27Ev
+ _ZN14nsXPTCStubBase6Stub28Ev
+ _ZN14nsXPTCStubBase6Stub29Ev
+ _ZN14nsXPTCStubBase6Stub30Ev
+ _ZN14nsXPTCStubBase6Stub31Ev
+ _ZN14nsXPTCStubBase6Stub32Ev
+ _ZN14nsXPTCStubBase6Stub33Ev
+ _ZN14nsXPTCStubBase6Stub34Ev
+ _ZN14nsXPTCStubBase6Stub35Ev
+ _ZN14nsXPTCStubBase6Stub36Ev
+ _ZN14nsXPTCStubBase6Stub37Ev
+ _ZN14nsXPTCStubBase6Stub38Ev
+ _ZN14nsXPTCStubBase6Stub39Ev
+ _ZN14nsXPTCStubBase6Stub40Ev
+ _ZN14nsXPTCStubBase6Stub41Ev
+ _ZN14nsXPTCStubBase6Stub42Ev
+ _ZN14nsXPTCStubBase6Stub43Ev
+ _ZN14nsXPTCStubBase6Stub44Ev
+ _ZN14nsXPTCStubBase6Stub45Ev
+ _ZN14nsXPTCStubBase6Stub46Ev
+ _ZN14nsXPTCStubBase6Stub47Ev
+ _ZN14nsXPTCStubBase6Stub48Ev
+ _ZN14nsXPTCStubBase6Stub49Ev
+ _ZN14nsXPTCStubBase6Stub50Ev
+ _ZN14nsXPTCStubBase6Stub51Ev
+ _ZN14nsXPTCStubBase6Stub52Ev
+ _ZN14nsXPTCStubBase6Stub53Ev
+ _ZN14nsXPTCStubBase6Stub54Ev
+ _ZN14nsXPTCStubBase6Stub55Ev
+ _ZN14nsXPTCStubBase6Stub56Ev
+ _ZN14nsXPTCStubBase6Stub57Ev
+ _ZN14nsXPTCStubBase6Stub58Ev
+ _ZN14nsXPTCStubBase6Stub59Ev
+ _ZN14nsXPTCStubBase6Stub60Ev
+ _ZN14nsXPTCStubBase6Stub61Ev
+ _ZN14nsXPTCStubBase6Stub62Ev
+ _ZN14nsXPTCStubBase6Stub63Ev
+ _ZN14nsXPTCStubBase6Stub64Ev
+ _ZN14nsXPTCStubBase6Stub65Ev
+ _ZN14nsXPTCStubBase6Stub66Ev
+ _ZN14nsXPTCStubBase6Stub67Ev
+ _ZN14nsXPTCStubBase6Stub68Ev
+ _ZN14nsXPTCStubBase6Stub69Ev
+ _ZN14nsXPTCStubBase6Stub70Ev
+ _ZN14nsXPTCStubBase6Stub71Ev
+ _ZN14nsXPTCStubBase6Stub72Ev
+ _ZN14nsXPTCStubBase6Stub73Ev
+ _ZN14nsXPTCStubBase6Stub74Ev
+ _ZN14nsXPTCStubBase6Stub75Ev
+ _ZN14nsXPTCStubBase6Stub76Ev
+ _ZN14nsXPTCStubBase6Stub77Ev
+ _ZN14nsXPTCStubBase6Stub78Ev
+ _ZN14nsXPTCStubBase6Stub79Ev
+ _ZN14nsXPTCStubBase6Stub80Ev
+ _ZN14nsXPTCStubBase6Stub81Ev
+ _ZN14nsXPTCStubBase6Stub82Ev
+ _ZN14nsXPTCStubBase6Stub83Ev
+ _ZN14nsXPTCStubBase6Stub84Ev
+ _ZN14nsXPTCStubBase6Stub85Ev
+ _ZN14nsXPTCStubBase6Stub86Ev
+ _ZN14nsXPTCStubBase6Stub87Ev
+ _ZN14nsXPTCStubBase6Stub88Ev
+ _ZN14nsXPTCStubBase6Stub89Ev
+ _ZN14nsXPTCStubBase6Stub90Ev
+ _ZN14nsXPTCStubBase6Stub91Ev
+ _ZN14nsXPTCStubBase6Stub92Ev
+ _ZN14nsXPTCStubBase6Stub93Ev
+ _ZN14nsXPTCStubBase6Stub94Ev
+ _ZN14nsXPTCStubBase6Stub95Ev
+ _ZN14nsXPTCStubBase6Stub96Ev
+ _ZN14nsXPTCStubBase6Stub97Ev
+ _ZN14nsXPTCStubBase6Stub98Ev
+ _ZN14nsXPTCStubBase6Stub99Ev
+ _ZN14nsXPTCStubBase7Stub100Ev
+ _ZN14nsXPTCStubBase7Stub101Ev
+ _ZN14nsXPTCStubBase7Stub102Ev
+ _ZN14nsXPTCStubBase7Stub103Ev
+ _ZN14nsXPTCStubBase7Stub104Ev
+ _ZN14nsXPTCStubBase7Stub105Ev
+ _ZN14nsXPTCStubBase7Stub106Ev
+ _ZN14nsXPTCStubBase7Stub107Ev
+ _ZN14nsXPTCStubBase7Stub108Ev
+ _ZN14nsXPTCStubBase7Stub109Ev
+ _ZN14nsXPTCStubBase7Stub110Ev
+ _ZN14nsXPTCStubBase7Stub111Ev
+ _ZN14nsXPTCStubBase7Stub112Ev
+ _ZN14nsXPTCStubBase7Stub113Ev
+ _ZN14nsXPTCStubBase7Stub114Ev
+ _ZN14nsXPTCStubBase7Stub115Ev
+ _ZN14nsXPTCStubBase7Stub116Ev
+ _ZN14nsXPTCStubBase7Stub117Ev
+ _ZN14nsXPTCStubBase7Stub118Ev
+ _ZN14nsXPTCStubBase7Stub119Ev
+ _ZN14nsXPTCStubBase7Stub120Ev
+ _ZN14nsXPTCStubBase7Stub121Ev
+ _ZN14nsXPTCStubBase7Stub122Ev
+ _ZN14nsXPTCStubBase7Stub123Ev
+ _ZN14nsXPTCStubBase7Stub124Ev
+ _ZN14nsXPTCStubBase7Stub125Ev
+ _ZN14nsXPTCStubBase7Stub126Ev
+ _ZN14nsXPTCStubBase7Stub127Ev
+ _ZN14nsXPTCStubBase7Stub128Ev
+ _ZN14nsXPTCStubBase7Stub129Ev
+ _ZN14nsXPTCStubBase7Stub130Ev
+ _ZN14nsXPTCStubBase7Stub131Ev
+ _ZN14nsXPTCStubBase7Stub132Ev
+ _ZN14nsXPTCStubBase7Stub133Ev
+ _ZN14nsXPTCStubBase7Stub134Ev
+ _ZN14nsXPTCStubBase7Stub135Ev
+ _ZN14nsXPTCStubBase7Stub136Ev
+ _ZN14nsXPTCStubBase7Stub137Ev
+ _ZN14nsXPTCStubBase7Stub138Ev
+ _ZN14nsXPTCStubBase7Stub139Ev
+ _ZN14nsXPTCStubBase7Stub140Ev
+ _ZN14nsXPTCStubBase7Stub141Ev
+ _ZN14nsXPTCStubBase7Stub142Ev
+ _ZN14nsXPTCStubBase7Stub143Ev
+ _ZN14nsXPTCStubBase7Stub144Ev
+ _ZN14nsXPTCStubBase7Stub145Ev
+ _ZN14nsXPTCStubBase7Stub146Ev
+ _ZN14nsXPTCStubBase7Stub147Ev
+ _ZN14nsXPTCStubBase7Stub148Ev
+ _ZN14nsXPTCStubBase7Stub149Ev
+ _ZN14nsXPTCStubBase7Stub150Ev
+ _ZN14nsXPTCStubBase7Stub151Ev
+ _ZN14nsXPTCStubBase7Stub152Ev
+ _ZN14nsXPTCStubBase7Stub153Ev
+ _ZN14nsXPTCStubBase7Stub154Ev
+ _ZN14nsXPTCStubBase7Stub155Ev
+ _ZN14nsXPTCStubBase7Stub156Ev
+ _ZN14nsXPTCStubBase7Stub157Ev
+ _ZN14nsXPTCStubBase7Stub158Ev
+ _ZN14nsXPTCStubBase7Stub159Ev
+ _ZN14nsXPTCStubBase7Stub160Ev
+ _ZN14nsXPTCStubBase7Stub161Ev
+ _ZN14nsXPTCStubBase7Stub162Ev
+ _ZN14nsXPTCStubBase7Stub163Ev
+ _ZN14nsXPTCStubBase7Stub164Ev
+ _ZN14nsXPTCStubBase7Stub165Ev
+ _ZN14nsXPTCStubBase7Stub166Ev
+ _ZN14nsXPTCStubBase7Stub167Ev
+ _ZN14nsXPTCStubBase7Stub168Ev
+ _ZN14nsXPTCStubBase7Stub169Ev
+ _ZN14nsXPTCStubBase7Stub170Ev
+ _ZN14nsXPTCStubBase7Stub171Ev
+ _ZN14nsXPTCStubBase7Stub172Ev
+ _ZN14nsXPTCStubBase7Stub173Ev
+ _ZN14nsXPTCStubBase7Stub174Ev
+ _ZN14nsXPTCStubBase7Stub175Ev
+ _ZN14nsXPTCStubBase7Stub176Ev
+ _ZN14nsXPTCStubBase7Stub177Ev
+ _ZN14nsXPTCStubBase7Stub178Ev
+ _ZN14nsXPTCStubBase7Stub179Ev
+ _ZN14nsXPTCStubBase7Stub180Ev
+ _ZN14nsXPTCStubBase7Stub181Ev
+ _ZN14nsXPTCStubBase7Stub182Ev
+ _ZN14nsXPTCStubBase7Stub183Ev
+ _ZN14nsXPTCStubBase7Stub184Ev
+ _ZN14nsXPTCStubBase7Stub185Ev
+ _ZN14nsXPTCStubBase7Stub186Ev
+ _ZN14nsXPTCStubBase7Stub187Ev
+ _ZN14nsXPTCStubBase7Stub188Ev
+ _ZN14nsXPTCStubBase7Stub189Ev
+ _ZN14nsXPTCStubBase7Stub190Ev
+ _ZN14nsXPTCStubBase7Stub191Ev
+ _ZN14nsXPTCStubBase7Stub192Ev
+ _ZN14nsXPTCStubBase7Stub193Ev
+ _ZN14nsXPTCStubBase7Stub194Ev
+ _ZN14nsXPTCStubBase7Stub195Ev
+ _ZN14nsXPTCStubBase7Stub196Ev
+ _ZN14nsXPTCStubBase7Stub197Ev
+ _ZN14nsXPTCStubBase7Stub198Ev
+ _ZN14nsXPTCStubBase7Stub199Ev
+ _ZN14nsXPTCStubBase7Stub200Ev
+ _ZN14nsXPTCStubBase7Stub201Ev
+ _ZN14nsXPTCStubBase7Stub202Ev
+ _ZN14nsXPTCStubBase7Stub203Ev
+ _ZN14nsXPTCStubBase7Stub204Ev
+ _ZN14nsXPTCStubBase7Stub205Ev
+ _ZN14nsXPTCStubBase7Stub206Ev
+ _ZN14nsXPTCStubBase7Stub207Ev
+ _ZN14nsXPTCStubBase7Stub208Ev
+ _ZN14nsXPTCStubBase7Stub209Ev
+ _ZN14nsXPTCStubBase7Stub210Ev
+ _ZN14nsXPTCStubBase7Stub211Ev
+ _ZN14nsXPTCStubBase7Stub212Ev
+ _ZN14nsXPTCStubBase7Stub213Ev
+ _ZN14nsXPTCStubBase7Stub214Ev
+ _ZN14nsXPTCStubBase7Stub215Ev
+ _ZN14nsXPTCStubBase7Stub216Ev
+ _ZN14nsXPTCStubBase7Stub217Ev
+ _ZN14nsXPTCStubBase7Stub218Ev
+ _ZN14nsXPTCStubBase7Stub219Ev
+ _ZN14nsXPTCStubBase7Stub220Ev
+ _ZN14nsXPTCStubBase7Stub221Ev
+ _ZN14nsXPTCStubBase7Stub222Ev
+ _ZN14nsXPTCStubBase7Stub223Ev
+ _ZN14nsXPTCStubBase7Stub224Ev
+ _ZN14nsXPTCStubBase7Stub225Ev
+ _ZN14nsXPTCStubBase7Stub226Ev
+ _ZN14nsXPTCStubBase7Stub227Ev
+ _ZN14nsXPTCStubBase7Stub228Ev
+ _ZN14nsXPTCStubBase7Stub229Ev
+ _ZN14nsXPTCStubBase7Stub230Ev
+ _ZN14nsXPTCStubBase7Stub231Ev
+ _ZN14nsXPTCStubBase7Stub232Ev
+ _ZN14nsXPTCStubBase7Stub233Ev
+ _ZN14nsXPTCStubBase7Stub234Ev
+ _ZN14nsXPTCStubBase7Stub235Ev
+ _ZN14nsXPTCStubBase7Stub236Ev
+ _ZN14nsXPTCStubBase7Stub237Ev
+ _ZN14nsXPTCStubBase7Stub238Ev
+ _ZN14nsXPTCStubBase7Stub239Ev
+ _ZN14nsXPTCStubBase7Stub240Ev
+ _ZN14nsXPTCStubBase7Stub241Ev
+ _ZN14nsXPTCStubBase7Stub242Ev
+ _ZN14nsXPTCStubBase7Stub243Ev
+ _ZN14nsXPTCStubBase7Stub244Ev
+ _ZN14nsXPTCStubBase7Stub245Ev
+ _ZN14nsXPTCStubBase7Stub246Ev
+ _ZN14nsXPTCStubBase7Stub247Ev
+ _ZN14nsXPTCStubBase7Stub248Ev
+ _ZN14nsXPTCStubBase7Stub249Ev
+ _ZN14nsXPTCStubBase9Sentinel0Ev
+ _ZN14nsXPTCStubBase9Sentinel1Ev
+ _ZN14nsXPTCStubBase9Sentinel2Ev
+ _ZN14nsXPTCStubBase9Sentinel3Ev
+ _ZN14nsXPTCStubBase9Sentinel4Ev
+ _ZN15nsAutoVoidArray5ClearEv
+ _ZN15nsAutoVoidArray6SizeToEi
+ _ZN15nsAutoVoidArray7CompactEv
+ _ZN15nsAutoVoidArrayC1Ev
+ _ZN15nsAutoVoidArrayC2Ev
+ _ZN15nsCOMArray_base12RemoveObjectEP11nsISupports
+ _ZN15nsCOMArray_base14InsertObjectAtEP11nsISupportsi
+ _ZN15nsCOMArray_base14RemoveObjectAtEi
+ _ZN15nsCOMArray_base15InsertObjectsAtERKS_i
+ _ZN15nsCOMArray_base15ReplaceObjectAtEP11nsISupportsi
+ _ZN15nsCOMArray_base5ClearEv
+ _ZN15nsCOMArray_baseC1ERKS_
+ _ZN15nsCOMArray_baseC2ERKS_
+ _ZN15nsCOMArray_baseD1Ev
+ _ZN15nsCOMArray_baseD2Ev
+ _ZN15nsPrintfCStringC1EPKcz
+ _ZN15nsPrintfCStringC1EjPKcz
+ _ZN15nsPrintfCStringC2EPKcz
+ _ZN15nsPrintfCStringC2EjPKcz
+ _ZN15nsSupportsArray11DeleteArrayEv
+ _ZN15nsSupportsArray11GrowArrayByEi
+ _ZN15nsSupportsArray11LastIndexOfEPK11nsISupports
+ _ZN15nsSupportsArray11MoveElementEii
+ _ZN15nsSupportsArray13RemoveElementEPK11nsISupportsj
+ _ZN15nsSupportsArray14QueryInterfaceERK4nsIDPPv
+ _ZN15nsSupportsArray15InsertElementAtEP11nsISupportsj
+ _ZN15nsSupportsArray16InsertElementsAtEP16nsISupportsArrayj
+ _ZN15nsSupportsArray16RemoveElementsAtEjj
+ _ZN15nsSupportsArray16ReplaceElementAtEP11nsISupportsj
+ _ZN15nsSupportsArray17EnumerateForwardsEPFiP11nsISupportsPvES2_
+ _ZN15nsSupportsArray17IndexOfStartingAtEPK11nsISupportsj
+ _ZN15nsSupportsArray17RemoveLastElementEPK11nsISupports
+ _ZN15nsSupportsArray18EnumerateBackwardsEPFiP11nsISupportsPvES2_
+ _ZN15nsSupportsArray4ReadEP20nsIObjectInputStream
+ _ZN15nsSupportsArray5ClearEv
+ _ZN15nsSupportsArray5CloneEPP16nsISupportsArray
+ _ZN15nsSupportsArray5WriteEP21nsIObjectOutputStream
+ _ZN15nsSupportsArray6AddRefEv
+ _ZN15nsSupportsArray6CreateEP11nsISupportsRK4nsIDPPv
+ _ZN15nsSupportsArray6EqualsEPK16nsISupportsArray
+ _ZN15nsSupportsArray6SizeToEi
+ _ZN15nsSupportsArray7CompactEv
+ _ZN15nsSupportsArray7IndexOfEPK11nsISupports
+ _ZN15nsSupportsArray7ReleaseEv
+ _ZN15nsSupportsArray9ElementAtEj
+ _ZN15nsSupportsArray9EnumerateEPP13nsIEnumerator
+ _ZN15nsSupportsArrayC1Ev
+ _ZN15nsSupportsArrayC2Ev
+ _ZN15nsSupportsArrayD1Ev
+ _ZN15nsSupportsArrayD2Ev
+ _ZN16nsServiceManager10GetServiceEPKcRK4nsIDPP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager10GetServiceERK4nsIDS2_PP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager14ReleaseServiceEPKcP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager14ReleaseServiceERK4nsIDP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager15RegisterServiceEPKcP11nsISupports
+ _ZN16nsServiceManager15RegisterServiceERK4nsIDP11nsISupports
+ _ZN16nsServiceManager17UnregisterServiceEPKc
+ _ZN16nsServiceManager17UnregisterServiceERK4nsID
+ _ZN16nsServiceManager23GetGlobalServiceManagerEPP17nsIServiceManager
+ _ZN16nsServiceManager28ShutdownGlobalServiceManagerEPP17nsIServiceManager
+ _ZN16nsSmallVoidArray13AppendElementEPv
+ _ZN16nsSmallVoidArray13RemoveElementEPv
+ _ZN16nsSmallVoidArray14SetSingleChildEPv
+ _ZN16nsSmallVoidArray14SwitchToVectorEv
+ _ZN16nsSmallVoidArray15InsertElementAtEPvi
+ _ZN16nsSmallVoidArray15RemoveElementAtEi
+ _ZN16nsSmallVoidArray16InsertElementsAtERK11nsVoidArrayi
+ _ZN16nsSmallVoidArray16RemoveElementsAtEii
+ _ZN16nsSmallVoidArray16ReplaceElementAtEPvi
+ _ZN16nsSmallVoidArray17EnumerateForwardsEPFiPvS0_ES0_
+ _ZN16nsSmallVoidArray18EnumerateBackwardsEPFiPvS0_ES0_
+ _ZN16nsSmallVoidArray4SortEPFiPKvS1_PvES2_
+ _ZN16nsSmallVoidArray5ClearEv
+ _ZN16nsSmallVoidArray6SizeToEi
+ _ZN16nsSmallVoidArray7CompactEv
+ _ZN16nsSmallVoidArrayC1Ev
+ _ZN16nsSmallVoidArrayC2Ev
+ _ZN16nsSmallVoidArrayD1Ev
+ _ZN16nsSmallVoidArrayD2Ev
+ _ZN16nsSmallVoidArrayaSERS_
+ _ZN17nsArrayEnumeratorC1EP16nsISupportsArray
+ _ZN17nsArrayEnumeratorC2EP16nsISupportsArray
+ _ZN17nsArrayEnumeratorD1Ev
+ _ZN17nsArrayEnumeratorD2Ev
+ _ZN17nsObjectHashtable11CopyElementEP12PLDHashTableP15PLDHashEntryHdrjPv
+ _ZN17nsObjectHashtable15RemoveAndDeleteEP9nsHashKey
+ _ZN17nsObjectHashtable5CloneEv
+ _ZN17nsObjectHashtable5ResetEv
+ _ZN17nsObjectHashtableC1EPFPvP9nsHashKeyS0_S0_ES0_PFiS2_S0_S0_ES0_ji
+ _ZN17nsObjectHashtableC2EPFPvP9nsHashKeyS0_S0_ES0_PFiS2_S0_S0_ES0_ji
+ _ZN17nsObjectHashtableD0Ev
+ _ZN17nsObjectHashtableD1Ev
+ _ZN17nsObjectHashtableD2Ev
+ _ZN17nsSegmentedBuffer16AppendNewSegmentEv
+ _ZN17nsSegmentedBuffer4InitEjjP9nsIMemory
+ _ZN17nsSegmentedBuffer5EmptyEv
+ _ZN17nsTraceRefcntImpl12WalkTheStackEP7__sFILE
+ _ZN17nsTraceRefcntImpl14DemangleSymbolEPKcPci
+ _ZN17nsTraceRefcntImpl14DumpStatisticsENS_14StatisticsTypeEP7__sFILE
+ _ZN17nsTraceRefcntImpl15ResetStatisticsEv
+ _ZN17nsTraceRefcntImpl18LoadLibrarySymbolsEPKcPv
+ _ZN17nsTraceRefcntImpl18SetActivityIsLegalEi
+ _ZN17nsTraceRefcntImpl7StartupEv
+ _ZN17nsTraceRefcntImpl8ShutdownEv
+ _ZN17nsUnionEnumeratorC1EP19nsISimpleEnumeratorS1_
+ _ZN17nsUnionEnumeratorC2EP19nsISimpleEnumeratorS1_
+ _ZN17nsUnionEnumeratorD1Ev
+ _ZN17nsUnionEnumeratorD2Ev
+ _ZN18nsComponentManager10InitializeEv
+ _ZN18nsComponentManager11FindFactoryERK4nsIDPP10nsIFactory
+ _ZN18nsComponentManager12AutoRegisterEiP7nsIFile
+ _ZN18nsComponentManager12IsRegisteredERK4nsIDPi
+ _ZN18nsComponentManager13FreeLibrariesEv
+ _ZN18nsComponentManager14CreateInstanceEPKcP11nsISupportsRK4nsIDPPv
+ _ZN18nsComponentManager14CreateInstanceERK4nsIDP11nsISupportsS2_PPv
+ _ZN18nsComponentManager14GetClassObjectERK4nsIDS2_PPv
+ _ZN18nsComponentManager15EnumerateCLSIDsEPP13nsIEnumerator
+ _ZN18nsComponentManager15RegisterFactoryERK4nsIDPKcS4_P10nsIFactoryi
+ _ZN18nsComponentManager17CLSIDToContractIDEP4nsIDPPcS3_
+ _ZN18nsComponentManager17RegisterComponentERK4nsIDPKcS4_S4_ii
+ _ZN18nsComponentManager17UnregisterFactoryERK4nsIDP10nsIFactory
+ _ZN18nsComponentManager19ContractIDToClassIDEPKcP4nsID
+ _ZN18nsComponentManager19UnregisterComponentERK4nsIDPKc
+ _ZN18nsComponentManager20EnumerateContractIDsEPP13nsIEnumerator
+ _ZN18nsComponentManager20RegisterComponentLibERK4nsIDPKcS4_S4_ii
+ _ZN18nsComponentManager21AutoRegisterComponentEiP7nsIFile
+ _ZN18nsComponentManager21RegisterComponentSpecERK4nsIDPKcS4_P7nsIFileii
+ _ZN18nsComponentManager23AutoUnregisterComponentEiP7nsIFile
+ _ZN18nsComponentManager23UnregisterComponentSpecERK4nsIDP7nsIFile
+ _ZN18nsVoidHashSetSuper4InitEj
+ _ZN18nsVoidHashSetSuper6RemoveEPKv
+ _ZN18nsVoidHashSetSuper8AddEntryEPKv
+ _ZN18nsVoidHashSetSuper8GetEntryEPKv
+ _ZN18nsVoidHashSetSuperC1Ev
+ _ZN18nsVoidHashSetSuperC2Ev
+ _ZN18nsVoidHashSetSuperD1Ev
+ _ZN18nsVoidHashSetSuperD2Ev
+ _ZN19nsDirEnumeratorUnixC1Ev
+ _ZN19nsDirEnumeratorUnixC2Ev
+ _ZN19nsDirEnumeratorUnixD1Ev
+ _ZN19nsDirEnumeratorUnixD2Ev
+ _ZN19nsInt32HashSetSuper4InitEj
+ _ZN19nsInt32HashSetSuper6RemoveEi
+ _ZN19nsInt32HashSetSuper8AddEntryEi
+ _ZN19nsInt32HashSetSuper8GetEntryEi
+ _ZN19nsInt32HashSetSuperC1Ev
+ _ZN19nsInt32HashSetSuperC2Ev
+ _ZN19nsInt32HashSetSuperD1Ev
+ _ZN19nsInt32HashSetSuperD2Ev
+ _ZN19nsPromiseFlatString4InitERK11nsSubstring
+ _ZN19nsPromiseFlatString4InitERK9nsAString
+ _ZN19nsSupportsHashtable13EnumerateCopyEP12PLDHashTableP15PLDHashEntryHdrjPv
+ _ZN19nsSupportsHashtable14ReleaseElementEP9nsHashKeyPvS2_
+ _ZN19nsSupportsHashtable3GetEP9nsHashKey
+ _ZN19nsSupportsHashtable3PutEP9nsHashKeyP11nsISupportsPS3_
+ _ZN19nsSupportsHashtable5CloneEv
+ _ZN19nsSupportsHashtable5ResetEv
+ _ZN19nsSupportsHashtable6RemoveEP9nsHashKeyPP11nsISupports
+ _ZN19nsSupportsHashtableD0Ev
+ _ZN19nsSupportsHashtableD1Ev
+ _ZN19nsSupportsHashtableD2Ev
+ _ZN20nsDependentSubstring6RebindERK11nsSubstringjj
+ _ZN20nsDependentSubstring6RebindERK9nsAStringjj
+ _ZN20nsPromiseFlatCString4InitERK10nsACString
+ _ZN20nsPromiseFlatCString4InitERK12nsCSubstring
+ _ZN20nsRecyclingAllocator13AddToFreeListEPNS_5BlockE
+ _ZN20nsRecyclingAllocator13FindFreeBlockEm
+ _ZN20nsRecyclingAllocator17FreeUnusedBucketsEv
+ _ZN20nsRecyclingAllocator22nsRecycleTimerCallbackEP8nsITimerPv
+ _ZN20nsRecyclingAllocator4FreeEPv
+ _ZN20nsRecyclingAllocator4InitEjjPKc
+ _ZN20nsRecyclingAllocator6MallocEmi
+ _ZN20nsRecyclingAllocatorC1EjjPKc
+ _ZN20nsRecyclingAllocatorC2EjjPKc
+ _ZN20nsRecyclingAllocatorD1Ev
+ _ZN20nsRecyclingAllocatorD2Ev
+ _ZN20nsStringHashSetSuper4InitEj
+ _ZN20nsStringHashSetSuper6RemoveERK9nsAString
+ _ZN20nsStringHashSetSuper8AddEntryERK9nsAString
+ _ZN20nsStringHashSetSuper8GetEntryERK9nsAString
+ _ZN20nsStringHashSetSuperC1Ev
+ _ZN20nsStringHashSetSuperC2Ev
+ _ZN20nsStringHashSetSuperD1Ev
+ _ZN20nsStringHashSetSuperD2Ev
+ _ZN21nsCStringHashSetSuper4InitEj
+ _ZN21nsCStringHashSetSuper6RemoveERK10nsACString
+ _ZN21nsCStringHashSetSuper8AddEntryERK10nsACString
+ _ZN21nsCStringHashSetSuper8GetEntryERK10nsACString
+ _ZN21nsCStringHashSetSuperC1Ev
+ _ZN21nsCStringHashSetSuperC2Ev
+ _ZN21nsCStringHashSetSuperD1Ev
+ _ZN21nsCStringHashSetSuperD2Ev
+ _ZN21nsDependentCSubstring6RebindERK10nsACStringjj
+ _ZN21nsDependentCSubstring6RebindERK12nsCSubstringjj
+ _ZN21nsSingletonEnumeratorC1EP11nsISupports
+ _ZN21nsSingletonEnumeratorC2EP11nsISupports
+ _ZN21nsSingletonEnumeratorD1Ev
+ _ZN21nsSingletonEnumeratorD2Ev
+ _ZN23nsSupportsWeakReference16GetWeakReferenceEPP16nsIWeakReference
+ _ZN4nsID5ParseEPKc
+ _ZN5nsCRT12IsAsciiAlphaEt
+ _ZN5nsCRT12IsAsciiDigitEt
+ _ZN5nsCRT12IsAsciiSpaceEt
+ _ZN5nsCRT14BufferHashCodeEPKcj
+ _ZN5nsCRT14BufferHashCodeEPKtj
+ _ZN5nsCRT14HashCodeAsUTF8EPKtPj
+ _ZN5nsCRT5atollEPKc
+ _ZN5nsCRT6strcmpEPKtS1_
+ _ZN5nsCRT6strdupEPKt
+ _ZN5nsCRT6strlenEPKt
+ _ZN5nsCRT6strtokEPcPKcPS0_
+ _ZN5nsCRT7IsAsciiEPKc
+ _ZN5nsCRT7IsAsciiEPKcj
+ _ZN5nsCRT7IsAsciiEPKt
+ _ZN5nsCRT7IsAsciiEt
+ _ZN5nsCRT7IsLowerEc
+ _ZN5nsCRT7IsUpperEc
+ _ZN5nsCRT7ToLowerEc
+ _ZN5nsCRT7ToUpperEc
+ _ZN5nsCRT7strncmpEPKtS1_j
+ _ZN5nsCRT7strndupEPKtj
+ _ZN5nsCRT8HashCodeEPKcPj
+ _ZN5nsCRT8HashCodeEPKtPj
+ _ZN7nsDebug5AbortEPKci
+ _ZN7nsDebug5BreakEPKci
+ _ZN7nsDebug7WarningEPKcS1_i
+ _ZN7nsDebug9AssertionEPKcS1_S1_i
+ _ZN7nsDeque12GrowCapacityEv
+ _ZN7nsDeque14SetDeallocatorEP14nsDequeFunctor
+ _ZN7nsDeque3PopEv
+ _ZN7nsDeque4PeekEv
+ _ZN7nsDeque4PushEPv
+ _ZN7nsDeque5EmptyEv
+ _ZN7nsDeque5EraseEv
+ _ZN7nsDeque8PopFrontEv
+ _ZN7nsDeque9PeekFrontEv
+ _ZN7nsDeque9PushFrontEPv
+ _ZN7nsDequeC1EP14nsDequeFunctor
+ _ZN7nsDequeC2EP14nsDequeFunctor
+ _ZN7nsDequeD1Ev
+ _ZN7nsDequeD2Ev
+ _ZN7nsIDKeyC1EP20nsIObjectInputStreamPj
+ _ZN7nsIDKeyC2EP20nsIObjectInputStreamPj
+ _ZN8nsMemory12HeapMinimizeEi
+ _ZN8nsMemory22GetGlobalMemoryServiceEv
+ _ZN8nsMemory4FreeEPv
+ _ZN8nsMemory5AllocEm
+ _ZN8nsMemory5CloneEPKvm
+ _ZN8nsMemory7ReallocEPvm
+ _ZN8nsString10StripCharsEPKc
+ _ZN8nsString11AppendFloatEd
+ _ZN8nsString11ReplaceCharEPKct
+ _ZN8nsString11ReplaceCharEtt
+ _ZN8nsString15StripWhitespaceEv
+ _ZN8nsString16ReplaceSubstringEPKtS1_
+ _ZN8nsString16ReplaceSubstringERKS_S1_
+ _ZN8nsString18CompressWhitespaceEii
+ _ZN8nsString20AppendWithConversionEPKci
+ _ZN8nsString20AppendWithConversionERK10nsACString
+ _ZN8nsString20AssignWithConversionEPKci
+ _ZN8nsString20AssignWithConversionERK10nsACString
+ _ZN8nsString4TrimEPKciii
+ _ZN8nsString9AppendIntEii
+ _ZN8nsString9AppendIntEli
+ _ZN8nsString9SetCharAtEtj
+ _ZN8nsString9StripCharEti
+ _ZN9nsAString11AppendASCIIEPKc
+ _ZN9nsAString11AppendASCIIEPKcj
+ _ZN9nsAString11AssignASCIIEPKc
+ _ZN9nsAString11AssignASCIIEPKcj
+ _ZN9nsAString11SetCapacityEj
+ _ZN9nsAString17GetWritableBufferEPPt
+ _ZN9nsAString3CutEjj
+ _ZN9nsAString6AppendEPKt
+ _ZN9nsAString6AppendEPKtj
+ _ZN9nsAString6AppendERK16nsSubstringTuple
+ _ZN9nsAString6AppendERKS_
+ _ZN9nsAString6AppendEt
+ _ZN9nsAString6AssignEPKt
+ _ZN9nsAString6AssignEPKtj
+ _ZN9nsAString6AssignERK16nsSubstringTuple
+ _ZN9nsAString6AssignERKS_
+ _ZN9nsAString6AssignEt
+ _ZN9nsAString6InsertEPKtj
+ _ZN9nsAString6InsertEPKtjj
+ _ZN9nsAString6InsertERK16nsSubstringTuplej
+ _ZN9nsAString6InsertERKS_j
+ _ZN9nsAString6InsertEtj
+ _ZN9nsAString7ReplaceEjjRK16nsSubstringTuple
+ _ZN9nsAString7ReplaceEjjRKS_
+ _ZN9nsAString9SetIsVoidEi
+ _ZN9nsAString9SetLengthEj
+ _ZN9nsAStringD1Ev
+ _ZN9nsAStringD2Ev
+ _ZN9nsCString10StripCharsEPKc
+ _ZN9nsCString11AppendFloatEd
+ _ZN9nsCString11ReplaceCharEPKcc
+ _ZN9nsCString11ReplaceCharEcc
+ _ZN9nsCString15StripWhitespaceEv
+ _ZN9nsCString16ReplaceSubstringEPKcS1_
+ _ZN9nsCString16ReplaceSubstringERKS_S1_
+ _ZN9nsCString18CompressWhitespaceEii
+ _ZN9nsCString20AppendWithConversionEPKti
+ _ZN9nsCString20AppendWithConversionERK9nsAString
+ _ZN9nsCString20AssignWithConversionEPKti
+ _ZN9nsCString20AssignWithConversionERK9nsAString
+ _ZN9nsCString4TrimEPKciii
+ _ZN9nsCString9AppendIntEii
+ _ZN9nsCString9AppendIntEli
+ _ZN9nsCString9SetCharAtEtj
+ _ZN9nsCString9StripCharEci
+ _ZN9nsHashKeyD0Ev
+ _ZN9nsHashKeyD1Ev
+ _ZN9nsHashKeyD2Ev
+ _ZN9nsIThread10GetCurrentEPPS_
+ _ZN9nsIThread10GetIThreadEP8PRThreadPPS_
+ _ZN9nsIThread12IsMainThreadEv
+ _ZN9nsIThread13GetMainThreadEPPS_
+ _ZN9nsIThread13SetMainThreadEv
+ _ZN9nsVariant10InitializeEP20nsDiscriminatedUnion
+ _ZN9nsVariant10SetToEmptyEP20nsDiscriminatedUnion
+ _ZN9nsVariant11ConvertToIDERK20nsDiscriminatedUnionP4nsID
+ _ZN9nsVariant11SetFromBoolEP20nsDiscriminatedUnioni
+ _ZN9nsVariant11SetFromCharEP20nsDiscriminatedUnionc
+ _ZN9nsVariant11SetFromInt8EP20nsDiscriminatedUnionh
+ _ZN9nsVariant12SetFromArrayEP20nsDiscriminatedUniontPK4nsIDjPv
+ _ZN9nsVariant12SetFromFloatEP20nsDiscriminatedUnionf
+ _ZN9nsVariant12SetFromInt16EP20nsDiscriminatedUnions
+ _ZN9nsVariant12SetFromInt32EP20nsDiscriminatedUnioni
+ _ZN9nsVariant12SetFromInt64EP20nsDiscriminatedUnionl
+ _ZN9nsVariant12SetFromUint8EP20nsDiscriminatedUnionh
+ _ZN9nsVariant12SetFromWCharEP20nsDiscriminatedUniont
+ _ZN9nsVariant13ConvertToBoolERK20nsDiscriminatedUnionPi
+ _ZN9nsVariant13ConvertToCharERK20nsDiscriminatedUnionPc
+ _ZN9nsVariant13ConvertToInt8ERK20nsDiscriminatedUnionPh
+ _ZN9nsVariant13SetFromDoubleEP20nsDiscriminatedUniond
+ _ZN9nsVariant13SetFromStringEP20nsDiscriminatedUnionPKc
+ _ZN9nsVariant13SetFromUint16EP20nsDiscriminatedUniont
+ _ZN9nsVariant13SetFromUint32EP20nsDiscriminatedUnionj
+ _ZN9nsVariant13SetFromUint64EP20nsDiscriminatedUnionm
+ _ZN9nsVariant14ConvertToArrayERK20nsDiscriminatedUnionPtP4nsIDPjPPv
+ _ZN9nsVariant14ConvertToFloatERK20nsDiscriminatedUnionPf
+ _ZN9nsVariant14ConvertToInt16ERK20nsDiscriminatedUnionPs
+ _ZN9nsVariant14ConvertToInt32ERK20nsDiscriminatedUnionPi
+ _ZN9nsVariant14ConvertToInt64ERK20nsDiscriminatedUnionPl
+ _ZN9nsVariant14ConvertToUint8ERK20nsDiscriminatedUnionPh
+ _ZN9nsVariant14ConvertToWCharERK20nsDiscriminatedUnionPt
+ _ZN9nsVariant14SetFromAStringEP20nsDiscriminatedUnionRK9nsAString
+ _ZN9nsVariant14SetFromVariantEP20nsDiscriminatedUnionP10nsIVariant
+ _ZN9nsVariant14SetFromWStringEP20nsDiscriminatedUnionPKt
+ _ZN9nsVariant15ConvertToDoubleERK20nsDiscriminatedUnionPd
+ _ZN9nsVariant15ConvertToStringERK20nsDiscriminatedUnionPPc
+ _ZN9nsVariant15ConvertToUint16ERK20nsDiscriminatedUnionPt
+ _ZN9nsVariant15ConvertToUint32ERK20nsDiscriminatedUnionPj
+ _ZN9nsVariant15ConvertToUint64ERK20nsDiscriminatedUnionPm
+ _ZN9nsVariant15SetFromACStringEP20nsDiscriminatedUnionRK10nsACString
+ _ZN9nsVariant15SetToEmptyArrayEP20nsDiscriminatedUnion
+ _ZN9nsVariant16ConvertToAStringERK20nsDiscriminatedUnionR9nsAString
+ _ZN9nsVariant16ConvertToWStringERK20nsDiscriminatedUnionPPt
+ _ZN9nsVariant16SetFromISupportsEP20nsDiscriminatedUnionP11nsISupports
+ _ZN9nsVariant16SetFromInterfaceEP20nsDiscriminatedUnionRK4nsIDP11nsISupports
+ _ZN9nsVariant17ConvertToACStringERK20nsDiscriminatedUnionR10nsACString
+ _ZN9nsVariant18ConvertToISupportsERK20nsDiscriminatedUnionPP11nsISupports
+ _ZN9nsVariant18ConvertToInterfaceERK20nsDiscriminatedUnionPP4nsIDPPv
+ _ZN9nsVariant18SetFromAUTF8StringEP20nsDiscriminatedUnionRK10nsACString
+ _ZN9nsVariant20ConvertToAUTF8StringERK20nsDiscriminatedUnionR10nsACString
+ _ZN9nsVariant21SetFromStringWithSizeEP20nsDiscriminatedUnionjPKc
+ _ZN9nsVariant22SetFromWStringWithSizeEP20nsDiscriminatedUnionjPKt
+ _ZN9nsVariant23ConvertToStringWithSizeERK20nsDiscriminatedUnionPjPPc
+ _ZN9nsVariant24ConvertToWStringWithSizeERK20nsDiscriminatedUnionPjPPt
+ _ZN9nsVariant7CleanupEP20nsDiscriminatedUnion
+ _ZN9nsVariant9SetFromIDEP20nsDiscriminatedUnionRK4nsID
+ _ZN9nsVariant9SetToVoidEP20nsDiscriminatedUnion
+ _ZN9nsVariantC1Ev
+ _ZN9nsVariantC2Ev
+ _ZN9nsVariantD1Ev
+ _ZN9nsVariantD2Ev
+ _ZNK10nsACString11EqualsASCIIEPKc
+ _ZNK10nsACString11EqualsASCIIEPKcj
+ _ZNK10nsACString12IsTerminatedEv
+ _ZNK10nsACString17GetReadableBufferEPPKc
+ _ZNK10nsACString20LowerCaseEqualsASCIIEPKc
+ _ZNK10nsACString20LowerCaseEqualsASCIIEPKcj
+ _ZNK10nsACString4LastEv
+ _ZNK10nsACString5FirstEv
+ _ZNK10nsACString6EqualsEPKc
+ _ZNK10nsACString6EqualsEPKcRK19nsCStringComparator
+ _ZNK10nsACString6EqualsERKS_
+ _ZNK10nsACString6EqualsERKS_RK19nsCStringComparator
+ _ZNK10nsACString6IsVoidEv
+ _ZNK10nsACString6LengthEv
+ _ZNK10nsACString8FindCharEcj
+ _ZNK10nsACString9CountCharEc
+ _ZNK11nsHashtable5WriteEP21nsIObjectOutputStreamPFjS1_PvE
+ _ZNK11nsStringKey5CloneEv
+ _ZNK11nsStringKey5WriteEP21nsIObjectOutputStream
+ _ZNK11nsStringKey6EqualsEPK9nsHashKey
+ _ZNK11nsStringKey8HashCodeEv
+ _ZNK11nsSubstring11EqualsASCIIEPKc
+ _ZNK11nsSubstring11EqualsASCIIEPKcj
+ _ZNK11nsSubstring20LowerCaseEqualsASCIIEPKc
+ _ZNK11nsSubstring20LowerCaseEqualsASCIIEPKcj
+ _ZNK11nsSubstring6EqualsEPKt
+ _ZNK11nsSubstring6EqualsEPKtRK18nsStringComparator
+ _ZNK11nsSubstring6EqualsERK9nsAString
+ _ZNK11nsSubstring6EqualsERK9nsAStringRK18nsStringComparator
+ _ZNK11nsSubstring6EqualsERKS_
+ _ZNK11nsSubstring6EqualsERKS_RK18nsStringComparator
+ _ZNK11nsSubstring8FindCharEtj
+ _ZNK11nsSubstring9CountCharEt
+ _ZNK11nsVoidArray7IndexOfEPv
+ _ZNK12nsCStringKey5CloneEv
+ _ZNK12nsCStringKey5WriteEP21nsIObjectOutputStream
+ _ZNK12nsCStringKey6EqualsEPK9nsHashKey
+ _ZNK12nsCStringKey8HashCodeEv
+ _ZNK12nsCSubstring11EqualsASCIIEPKc
+ _ZNK12nsCSubstring11EqualsASCIIEPKcj
+ _ZNK12nsCSubstring20LowerCaseEqualsASCIIEPKc
+ _ZNK12nsCSubstring20LowerCaseEqualsASCIIEPKcj
+ _ZNK12nsCSubstring6EqualsEPKc
+ _ZNK12nsCSubstring6EqualsEPKcRK19nsCStringComparator
+ _ZNK12nsCSubstring6EqualsERK10nsACString
+ _ZNK12nsCSubstring6EqualsERK10nsACStringRK19nsCStringComparator
+ _ZNK12nsCSubstring6EqualsERKS_
+ _ZNK12nsCSubstring6EqualsERKS_RK19nsCStringComparator
+ _ZNK12nsCSubstring8FindCharEcj
+ _ZNK12nsCSubstring9CountCharEc
+ _ZNK13nsStringArray7IndexOfERK9nsAString
+ _ZNK13nsStringArray8StringAtEi
+ _ZNK13nsStringArray8StringAtEiR9nsAString
+ _ZNK14nsCStringArray17IndexOfIgnoreCaseERK10nsACString
+ _ZNK14nsCStringArray7IndexOfERK10nsACString
+ _ZNK14nsCStringArray9CStringAtEi
+ _ZNK14nsCStringArray9CStringAtEiR10nsACString
+ _ZNK14nsGetInterfaceclERK4nsIDPPv
+ _ZNK14nsISupportsKey5WriteEP21nsIObjectOutputStream
+ _ZNK15nsCOMArray_base13IndexOfObjectEP11nsISupports
+ _ZNK15nsQueryReferentclERK4nsIDPPv
+ _ZNK16nsQueryElementAtclERK4nsIDPPv
+ _ZNK16nsQueryInterfaceclERK4nsIDPPv
+ _ZNK16nsSmallVoidArray12GetArraySizeEv
+ _ZNK16nsSmallVoidArray5CountEv
+ _ZNK16nsSmallVoidArray7IndexOfEPv
+ _ZNK16nsSmallVoidArray9ElementAtEi
+ _ZNK16nsSubstringTuple13IsDependentOnEPKtS1_
+ _ZNK16nsSubstringTuple6LengthEv
+ _ZNK16nsSubstringTuple7WriteToEPtj
+ _ZNK17nsCSubstringTuple13IsDependentOnEPKcS1_
+ _ZNK17nsCSubstringTuple6LengthEv
+ _ZNK17nsCSubstringTuple7WriteToEPcj
+ _ZNK17nsGetServiceByCIDclERK4nsIDPPv
+ _ZNK18nsGetWeakReferenceclERK4nsIDPPv
+ _ZNK21nsCreateInstanceByCIDclERK4nsIDPPv
+ _ZNK21nsQueryArrayElementAtclERK4nsIDPPv
+ _ZNK24nsGetServiceByContractIDclERK4nsIDPPv
+ _ZNK25nsDefaultStringComparatorclEPKtS1_j
+ _ZNK25nsDefaultStringComparatorclEtt
+ _ZNK25nsQueryInterfaceWithErrorclERK4nsIDPPv
+ _ZNK26nsDefaultCStringComparatorclEPKcS1_j
+ _ZNK26nsDefaultCStringComparatorclEcc
+ _ZNK28nsCreateInstanceByContractIDclERK4nsIDPPv
+ _ZNK28nsCreateInstanceFromCategoryclERK4nsIDPPv
+ _ZNK34nsCaseInsensitiveCStringComparatorclEPKcS1_j
+ _ZNK34nsCaseInsensitiveCStringComparatorclEcc
+ _ZNK4nsID16ToProvidedStringERA39_c
+ _ZNK4nsID8ToStringEv
+ _ZNK7nsDeque3EndEv
+ _ZNK7nsDeque4LastEv
+ _ZNK7nsDeque5BeginEv
+ _ZNK7nsDeque7ForEachER14nsDequeFunctor
+ _ZNK7nsDeque8ObjectAtEi
+ _ZNK7nsDeque9FirstThatER14nsDequeFunctor
+ _ZNK7nsIDKey5WriteEP21nsIObjectOutputStream
+ _ZNK8nsString13FindCharInSetEPKci
+ _ZNK8nsString13FindCharInSetEPKti
+ _ZNK8nsString14RFindCharInSetEPKti
+ _ZNK8nsString16EqualsIgnoreCaseEPKci
+ _ZNK8nsString3MidERS_jj
+ _ZNK8nsString4FindEPKciii
+ _ZNK8nsString4FindEPKtii
+ _ZNK8nsString4FindERK9nsCStringiii
+ _ZNK8nsString4FindERKS_ii
+ _ZNK8nsString5RFindEPKciii
+ _ZNK8nsString5RFindEPKtii
+ _ZNK8nsString5RFindERK9nsCStringiii
+ _ZNK8nsString5RFindERKS_ii
+ _ZNK8nsString7ToFloatEPi
+ _ZNK8nsString9RFindCharEtii
+ _ZNK8nsString9ToCStringEPcjj
+ _ZNK8nsString9ToIntegerEPij
+ _ZNK9nsAString11EqualsASCIIEPKc
+ _ZNK9nsAString11EqualsASCIIEPKcj
+ _ZNK9nsAString12IsTerminatedEv
+ _ZNK9nsAString17GetReadableBufferEPPKt
+ _ZNK9nsAString20LowerCaseEqualsASCIIEPKc
+ _ZNK9nsAString20LowerCaseEqualsASCIIEPKcj
+ _ZNK9nsAString4LastEv
+ _ZNK9nsAString5FirstEv
+ _ZNK9nsAString6EqualsEPKt
+ _ZNK9nsAString6EqualsEPKtRK18nsStringComparator
+ _ZNK9nsAString6EqualsERKS_
+ _ZNK9nsAString6EqualsERKS_RK18nsStringComparator
+ _ZNK9nsAString6IsVoidEv
+ _ZNK9nsAString6LengthEv
+ _ZNK9nsAString8FindCharEtj
+ _ZNK9nsAString9CountCharEt
+ _ZNK9nsCString13FindCharInSetEPKci
+ _ZNK9nsCString14RFindCharInSetEPKci
+ _ZNK9nsCString3MidERS_jj
+ _ZNK9nsCString4FindEPKciii
+ _ZNK9nsCString4FindERKS_iii
+ _ZNK9nsCString5RFindEPKciii
+ _ZNK9nsCString5RFindERKS_iii
+ _ZNK9nsCString7CompareEPKcii
+ _ZNK9nsCString7ToFloatEPi
+ _ZNK9nsCString9RFindCharEtii
+ _ZNK9nsCString9ToIntegerEPij
+ _ZNK9nsHashKey5WriteEP21nsIObjectOutputStream
diff --git a/src/libs/xpcom18a4/VBoxXPCOM.def b/src/libs/xpcom18a4/VBoxXPCOM.def
new file mode 100644
index 00000000..94e24142
--- /dev/null
+++ b/src/libs/xpcom18a4/VBoxXPCOM.def
@@ -0,0 +1,1687 @@
+; $Id: VBoxXPCOM.def $
+;; @file
+; VirtualBox XPCOM - Import library definition file.
+
+;
+; Copyright (C) 2018-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+LIBRARY VBoxXPCOM.dll
+EXPORTS
+ ;
+ ; To regenerate run the following command line:
+ ; nm -U ../../../out/darwin.amd64/debug/dist/VirtualBox.app/Contents/MacOS/VBoxXPCOM.dylib | kmk_sed -r -e 's/^[0-9a-fA-F]+ //' -e '/^[A-Z]/!d' | sort | kmk_sed -r -e 's/[SDBC] (.+)$/ \1 DATA/' -e 's/^[A-Z] / /' -e 's/^ _/ /' >> VBoxXPCOM.def
+ ;
+ _ZN12nsCharTraitsIcE12sEmptyBufferE DATA
+ _ZN12nsCharTraitsItE12sEmptyBufferE DATA
+ NSGetStaticModuleInfo DATA
+ _ZN17nsObsoleteAString16sCanonicalVTableE DATA
+ _ZN18nsObsoleteACString16sCanonicalVTableE DATA
+ _ZTV11nsHashtable DATA
+ _ZTV11nsLocalFile DATA
+ _ZTV11nsStringKey DATA
+ _ZTV11nsVoidArray DATA
+ _ZTV12nsCStringKey DATA
+ _ZTV13nsStringArray DATA
+ _ZTV14nsCStringArray DATA
+ _ZTV14nsGetInterface DATA
+ _ZTV14nsISupportsKey DATA
+ _ZTV14nsXPTCStubBase DATA
+ _ZTV15nsAutoVoidArray DATA
+ _ZTV15nsQueryReferent DATA
+ _ZTV15nsSupportsArray DATA
+ _ZTV15nsWeakReference DATA
+ _ZTV16nsQueryElementAt DATA
+ _ZTV17nsArrayEnumerator DATA
+ _ZTV17nsGetServiceByCID DATA
+ _ZTV17nsObjectHashtable DATA
+ _ZTV17nsUnionEnumerator DATA
+ _ZTV18nsGetWeakReference DATA
+ _ZTV19nsDirEnumeratorUnix DATA
+ _ZTV19nsSupportsHashtable DATA
+ _ZTV21nsCreateInstanceByCID DATA
+ _ZTV21nsQueryArrayElementAt DATA
+ _ZTV21nsSingletonEnumerator DATA
+ _ZTV23nsSupportsWeakReference DATA
+ _ZTV24nsGetServiceByContractID DATA
+ _ZTV25nsDefaultStringComparator DATA
+ _ZTV26nsDefaultCStringComparator DATA
+ _ZTV28nsCreateInstanceByContractID DATA
+ _ZTV28nsCreateInstanceFromCategory DATA
+ _ZTV34nsCaseInsensitiveCStringComparator DATA
+ _ZTV7nsIDKey DATA
+ _ZTV9nsHashKey DATA
+ _ZTV9nsVariant DATA
+ gFastLoadService_ DATA
+ GetExecutionEnvironment
+ LL_MaxInt
+ LL_MaxUint
+ LL_MinInt
+ LL_Zero
+ NS_CStringCloneData
+ NS_CStringContainerFinish
+ NS_CStringContainerInit
+ NS_CStringCopy
+ NS_CStringGetData
+ NS_CStringSetData
+ NS_CStringSetDataRange
+ NS_CStringToUTF16
+ NS_GetComponentManager
+ NS_GetComponentRegistrar
+ NS_GetDebug
+ NS_GetFrozenFunctions
+ NS_GetMemoryManager
+ NS_GetServiceManager
+ NS_GetTraceRefcnt
+ NS_InitXPCOM2
+ NS_MeanAndStdDev
+ NS_NewByteInputStream
+ NS_NewCStringInputStream
+ NS_NewCharInputStream
+ NS_NewEmptyEnumerator
+ NS_NewLocalFile
+ NS_NewNativeLocalFile
+ NS_NewSingletonEnumerator
+ NS_NewStringInputStream
+ NS_NewUnionEnumerator
+ NS_QuickSort
+ NS_RegisterXPCOMExitRoutine
+ NS_ShutdownXPCOM
+ NS_StringCloneData
+ NS_StringContainerFinish
+ NS_StringContainerInit
+ NS_StringCopy
+ NS_StringGetData
+ NS_StringSetData
+ NS_StringSetDataRange
+ NS_UTF16ToCString
+ NS_UnregisterXPCOMExitRoutine
+ PL_ArenaAllocate
+ PL_ArenaFinish
+ PL_ArenaGrow
+ PL_ArenaRelease
+ PL_CompactArenaPool
+ PL_CompareStrings
+ PL_CompareValues
+ PL_CreateEventQueue
+ PL_CreateMonitoredEventQueue
+ PL_CreateNativeEventQueue
+ PL_DHashAllocTable
+ PL_DHashClearEntryStub
+ PL_DHashFinalizeStub
+ PL_DHashFreeStringKey
+ PL_DHashFreeTable
+ PL_DHashGetKeyStub
+ PL_DHashGetStubOps
+ PL_DHashMatchEntryStub
+ PL_DHashMatchStringKey
+ PL_DHashMoveEntryStub
+ PL_DHashStringKey
+ PL_DHashTableDestroy
+ PL_DHashTableEnumerate
+ PL_DHashTableFinish
+ PL_DHashTableInit
+ PL_DHashTableOperate
+ PL_DHashTableRawRemove
+ PL_DHashTableSetAlphaBounds
+ PL_DHashVoidPtrKeyStub
+ PL_DequeueEvent
+ PL_DestroyEvent
+ PL_DestroyEventQueue
+ PL_EventAvailable
+ PL_EventLoop
+ PL_FavorPerformanceHint
+ PL_FinishArenaPool
+ PL_FreeArenaPool
+ PL_GetEvent
+ PL_GetEventOwner
+ PL_GetEventQueueMonitor
+ PL_GetEventQueueSelectFD
+ PL_HandleEvent
+ PL_HashString
+ PL_HashTableAdd
+ PL_HashTableDestroy
+ PL_HashTableDump
+ PL_HashTableEnumerateEntries
+ PL_HashTableLookup
+ PL_HashTableLookupConst
+ PL_HashTableRawAdd
+ PL_HashTableRawLookup
+ PL_HashTableRawLookupConst
+ PL_HashTableRawRemove
+ PL_HashTableRemove
+ PL_InitArenaPool
+ PL_InitEvent
+ PL_IsQueueNative
+ PL_IsQueueOnCurrentThread
+ PL_MapEvents
+ PL_NewDHashTable
+ PL_NewHashTable
+ PL_PostEvent
+ PL_PostSynchronousEvent
+ PL_ProcessPendingEvents
+ PL_RevokeEvents
+ PL_WaitForEvent
+ PL_strcasecmp
+ PL_strchr
+ PL_strcmp
+ PL_strcpy
+ PL_strdup
+ PL_strfree
+ PL_strlen
+ PL_strncasecmp
+ PL_strnchr
+ PL_strncmp
+ PL_strncpy
+ PL_strncpyz
+ PL_strndup
+ PL_strnlen
+ PL_strnrchr
+ PL_strnrstr
+ PL_strnstr
+ PL_strrchr
+ PL_strrstr
+ PL_strstr
+ PRP_DestroyNakedCondVar
+ PRP_NakedBroadcast
+ PRP_NakedNotify
+ PRP_NakedWait
+ PRP_NewNakedCondVar
+ PRP_TryLock
+ PR_Abort
+ PR_Accept
+ PR_AcceptRead
+ PR_Access
+ PR_AddWaitFileDesc
+ PR_AllocFileDesc
+ PR_Assert
+ PR_AtomicAdd
+ PR_AtomicDecrement
+ PR_AtomicIncrement
+ PR_AtomicSet
+ PR_AttachThread
+ PR_Available
+ PR_Available64
+ PR_Bind
+ PR_BlockClockInterrupts
+ PR_BlockInterrupt
+ PR_CEnterMonitor
+ PR_CExitMonitor
+ PR_CNotify
+ PR_CNotifyAll
+ PR_CSetOnMonitorRecycle
+ PR_CWait
+ PR_CallOnce
+ PR_CallOnceWithArg
+ PR_Calloc
+ PR_CancelWaitFileDesc
+ PR_CancelWaitGroup
+ PR_CeilingLog2
+ PR_ChangeFileDescNativeHandle
+ PR_Cleanup
+ PR_ClearInterrupt
+ PR_ClearThreadGCAble
+ PR_Close
+ PR_CloseDir
+ PR_CloseFileMap
+ PR_CloseSemaphore
+ PR_Connect
+ PR_ConnectContinue
+ PR_ConvertIPv4AddrToIPv6
+ PR_CreateFileMap
+ PR_CreateIOLayer
+ PR_CreateIOLayerStub
+ PR_CreateMWaitEnumerator
+ PR_CreatePipe
+ PR_CreateProcess
+ PR_CreateProcessDetached
+ PR_CreateSocketPollFd
+ PR_CreateStack
+ PR_CreateThread
+ PR_CreateThreadGCAble
+ PR_CreateWaitGroup
+ PR_Delete
+ PR_DeleteSemaphore
+ PR_DestroyCondVar
+ PR_DestroyLock
+ PR_DestroyMWaitEnumerator
+ PR_DestroyMonitor
+ PR_DestroyPollableEvent
+ PR_DestroyProcessAttr
+ PR_DestroyRWLock
+ PR_DestroySem
+ PR_DestroySocketPollFd
+ PR_DestroyStack
+ PR_DestroyWaitGroup
+ PR_DetachProcess
+ PR_DetachThread
+ PR_DisableClockInterrupts
+ PR_EmulateAcceptRead
+ PR_EmulateSendFile
+ PR_EnableClockInterrupts
+ PR_EnterMonitor
+ PR_EnumerateAddrInfo
+ PR_EnumerateHostEnt
+ PR_EnumerateThreads
+ PR_EnumerateWaitGroup
+ PR_ErrorInstallCallback
+ PR_ErrorInstallTable
+ PR_ErrorLanguages
+ PR_ErrorToName
+ PR_ErrorToString
+ PR_ExitMonitor
+ PR_ExplodeTime
+ PR_FD_CLR
+ PR_FD_ISSET
+ PR_FD_NCLR
+ PR_FD_NISSET
+ PR_FD_NSET
+ PR_FD_SET
+ PR_FD_ZERO
+ PR_FPrintZoneStats
+ PR_FileDesc2NativeHandle
+ PR_FindFunctionSymbol
+ PR_FindFunctionSymbolAndLibrary
+ PR_FindLibrary
+ PR_FindSymbol
+ PR_FindSymbolAndLibrary
+ PR_FloorLog2
+ PR_FormatTime
+ PR_FormatTimeUSEnglish
+ PR_Free
+ PR_FreeAddrInfo
+ PR_FreeLibraryName
+ PR_GMTParameters
+ PR_GetAddrInfoByName
+ PR_GetCanonNameFromAddrInfo
+ PR_GetConnectStatus
+ PR_GetCurrentThread
+ PR_GetDefaultIOMethods
+ PR_GetDescType
+ PR_GetEnv
+ PR_GetError
+ PR_GetErrorText
+ PR_GetErrorTextLength
+ PR_GetFileInfo
+ PR_GetFileInfo64
+ PR_GetFileMethods
+ PR_GetHostByAddr
+ PR_GetHostByName
+ PR_GetIPNodeByName
+ PR_GetIdentitiesLayer
+ PR_GetInheritedFD
+ PR_GetLayersIdentity
+ PR_GetLibraryFilePathname
+ PR_GetLibraryName
+ PR_GetLibraryPath
+ PR_GetMemMapAlignment
+ PR_GetMonitorEntryCount
+ PR_GetNameForIdentity
+ PR_GetOSError
+ PR_GetOpenFileInfo
+ PR_GetOpenFileInfo64
+ PR_GetPageShift
+ PR_GetPageSize
+ PR_GetPeerName
+ PR_GetPipeMethods
+ PR_GetProtoByName
+ PR_GetProtoByNumber
+ PR_GetSP
+ PR_GetSockName
+ PR_GetSocketOption
+ PR_GetSpecialFD
+ PR_GetTCPMethods
+ PR_GetThreadAffinityMask
+ PR_GetThreadID
+ PR_GetThreadPriority
+ PR_GetThreadPrivate
+ PR_GetThreadScope
+ PR_GetThreadState
+ PR_GetThreadType
+ PR_GetUDPMethods
+ PR_GetUniqueIdentity
+ PR_ImplodeTime
+ PR_ImportFile
+ PR_ImportPipe
+ PR_ImportTCPSocket
+ PR_ImportUDPSocket
+ PR_Init
+ PR_Initialize
+ PR_InitializeNetAddr
+ PR_Initialized
+ PR_Interrupt
+ PR_IntervalNow
+ PR_IntervalToMicroseconds
+ PR_IntervalToMilliseconds
+ PR_IntervalToSeconds
+ PR_IsNetAddrType
+ PR_JoinThread
+ PR_KillProcess
+ PR_Listen
+ PR_LoadLibrary
+ PR_LoadLibraryWithFlags
+ PR_LoadStaticLibrary
+ PR_LocalTimeParameters
+ PR_Lock
+ PR_LockFile
+ PR_LogFlush
+ PR_LogPrint
+ PR_MakeDir
+ PR_Malloc
+ PR_MemMap
+ PR_MemUnmap
+ PR_MicrosecondsToInterval
+ PR_MillisecondsToInterval
+ PR_MkDir
+ PR_NetAddrToString
+ PR_NewCondVar
+ PR_NewLock
+ PR_NewLogModule
+ PR_NewMonitor
+ PR_NewNamedMonitor
+ PR_NewPollableEvent
+ PR_NewProcessAttr
+ PR_NewRWLock
+ PR_NewSem
+ PR_NewTCPSocket
+ PR_NewTCPSocketPair
+ PR_NewThreadPrivateIndex
+ PR_NewUDPSocket
+ PR_NormalizeTime
+ PR_Notify
+ PR_NotifyAll
+ PR_NotifyAllCondVar
+ PR_NotifyCondVar
+ PR_Now
+ PR_Open
+ PR_OpenDir
+ PR_OpenFile
+ PR_OpenSemaphore
+ PR_OpenTCPSocket
+ PR_OpenUDPSocket
+ PR_ParseTimeString
+ PR_Poll
+ PR_PopIOLayer
+ PR_PostSem
+ PR_PostSemaphore
+ PR_ProcessAttrSetCurrentDirectory
+ PR_ProcessAttrSetInheritableFD
+ PR_ProcessAttrSetStdioRedirect
+ PR_ProcessExit
+ PR_PushIOLayer
+ PR_RWLock_Rlock
+ PR_RWLock_Unlock
+ PR_RWLock_Wlock
+ PR_Read
+ PR_ReadDir
+ PR_Realloc
+ PR_Recv
+ PR_RecvFrom
+ PR_Rename
+ PR_ResetProcessAttr
+ PR_ResumeAll
+ PR_RmDir
+ PR_SecondsToInterval
+ PR_Seek
+ PR_Seek64
+ PR_Select
+ PR_Send
+ PR_SendFile
+ PR_SendTo
+ PR_SetConcurrency
+ PR_SetEnv
+ PR_SetError
+ PR_SetErrorText
+ PR_SetFDCacheSize
+ PR_SetFDInheritable
+ PR_SetLibraryPath
+ PR_SetLogBuffering
+ PR_SetLogFile
+ PR_SetNetAddr
+ PR_SetPollableEvent
+ PR_SetSocketOption
+ PR_SetStdioRedirect
+ PR_SetThreadAffinityMask
+ PR_SetThreadDumpProc
+ PR_SetThreadGCAble
+ PR_SetThreadPriority
+ PR_SetThreadPrivate
+ PR_SetThreadRecycleMode
+ PR_Shutdown
+ PR_Sleep
+ PR_Socket
+ PR_StackPop
+ PR_StackPush
+ PR_Stat
+ PR_StringToNetAddr
+ PR_SuspendAll
+ PR_Sync
+ PR_TLockFile
+ PR_TicksPerSecond
+ PR_TransmitFile
+ PR_USPacificTimeParameters
+ PR_UnblockClockInterrupts
+ PR_UnblockInterrupt
+ PR_UnloadLibrary
+ PR_Unlock
+ PR_UnlockFile
+ PR_VersionCheck
+ PR_Wait
+ PR_WaitCondVar
+ PR_WaitForPollableEvent
+ PR_WaitProcess
+ PR_WaitRecvReady
+ PR_WaitSem
+ PR_WaitSemaphore
+ PR_Write
+ PR_Writev
+ PR_Yield
+ PR_cnvtf
+ PR_dtoa
+ PR_fprintf
+ PR_htonl
+ PR_htonll
+ PR_htons
+ PR_ntohl
+ PR_ntohll
+ PR_ntohs
+ PR_smprintf
+ PR_smprintf_free
+ PR_snprintf
+ PR_sprintf_append
+ PR_sscanf
+ PR_strtod
+ PR_sxprintf
+ PR_vfprintf
+ PR_vsmprintf
+ PR_vsnprintf
+ PR_vsprintf_append
+ PR_vsxprintf
+ PT_FPrintStats
+ SetExecutionEnvironment
+ XPTC_InvokeByIndex
+ XPTI_FreeInterfaceInfoManager
+ XPTI_GetInterfaceInfoManager
+ XPT_ArenaFree
+ XPT_ArenaMalloc
+ XPT_ArenaStrDup
+ XPT_AssertFailed
+ XPT_DataOffset
+ XPT_DestroyArena
+ XPT_DestroyInterfaceDirectoryEntry
+ XPT_DestroyXDRState
+ XPT_Do16
+ XPT_Do32
+ XPT_Do64
+ XPT_Do8
+ XPT_DoCString
+ XPT_DoHeader
+ XPT_DoHeaderPrologue
+ XPT_DoIID
+ XPT_DoString
+ XPT_DoStringInline
+ XPT_DumpStats
+ XPT_FillInterfaceDirectoryEntry
+ XPT_FillMethodDescriptor
+ XPT_FillParamDescriptor
+ XPT_FreeHeader
+ XPT_FreeInterfaceDescriptor
+ XPT_GetAddrForOffset
+ XPT_GetInterfaceIndexByName
+ XPT_GetOffsetForAddr
+ XPT_GetXDRData
+ XPT_GetXDRDataLength
+ XPT_InterfaceDescriptorAddConsts
+ XPT_InterfaceDescriptorAddMethods
+ XPT_InterfaceDescriptorAddTypes
+ XPT_MakeCursor
+ XPT_NewAnnotation
+ XPT_NewArena
+ XPT_NewHeader
+ XPT_NewInterfaceDescriptor
+ XPT_NewString
+ XPT_NewStringZ
+ XPT_NewXDRState
+ XPT_NotifyDoneLoading
+ XPT_ParseVersionString
+ XPT_SeekTo
+ XPT_SetAddrForOffset
+ XPT_SetDataOffset
+ XPT_SetOffsetForAddr
+ XPT_SizeOfHeader
+ XPT_SizeOfHeaderBlock
+ _MD_LockFile
+ _MD_TLockFile
+ _MD_UnlockFile
+ _MD_gethostname
+ _MD_getsysinfo
+ _MD_unix_map_accept_error
+ _MD_unix_map_access_error
+ _MD_unix_map_bind_error
+ _MD_unix_map_close_error
+ _MD_unix_map_closedir_error
+ _MD_unix_map_connect_error
+ _MD_unix_map_default_error
+ _MD_unix_map_flock_error
+ _MD_unix_map_fstat_error
+ _MD_unix_map_fsync_error
+ _MD_unix_map_gethostname_error
+ _MD_unix_map_getpeername_error
+ _MD_unix_map_getsockname_error
+ _MD_unix_map_getsockopt_error
+ _MD_unix_map_listen_error
+ _MD_unix_map_lockf_error
+ _MD_unix_map_lseek_error
+ _MD_unix_map_mkdir_error
+ _MD_unix_map_mmap_error
+ _MD_unix_map_open_error
+ _MD_unix_map_opendir_error
+ _MD_unix_map_poll_error
+ _MD_unix_map_poll_revents_error
+ _MD_unix_map_read_error
+ _MD_unix_map_recv_error
+ _MD_unix_map_recvfrom_error
+ _MD_unix_map_rename_error
+ _MD_unix_map_rmdir_error
+ _MD_unix_map_select_error
+ _MD_unix_map_send_error
+ _MD_unix_map_sendto_error
+ _MD_unix_map_setsockopt_error
+ _MD_unix_map_shutdown_error
+ _MD_unix_map_socket_error
+ _MD_unix_map_socketavailable_error
+ _MD_unix_map_socketpair_error
+ _MD_unix_map_stat_error
+ _MD_unix_map_unlink_error
+ _MD_unix_map_write_error
+ _MD_unix_map_writev_error
+ _MD_unix_readdir_error
+ _Z10HashStringRK10nsACString
+ _Z10HashStringRK9nsAString
+ _Z10NS_NewAtomPKc
+ _Z10NS_NewAtomPKt
+ _Z10NS_NewAtomRK10nsACString
+ _Z10NS_NewAtomRK9nsAString
+ _Z11EmptyStringv
+ _Z11NS_NewArrayPP15nsIMutableArray
+ _Z11NS_NewArrayPP15nsIMutableArrayRK15nsCOMArray_base
+ _Z11NS_NewPipe2PP19nsIAsyncInputStreamPP20nsIAsyncOutputStreamiijjP9nsIMemory
+ _Z11ToLowerCaseR10nsACString
+ _Z11ToLowerCaseR12nsCSubstring
+ _Z11ToLowerCaseRK10nsACStringRS_
+ _Z11ToUpperCaseR10nsACString
+ _Z11ToUpperCaseR12nsCSubstring
+ _Z11ToUpperCaseRK10nsACStringRS_
+ _Z12EmptyCStringv
+ _Z12NS_AsyncCopyP14nsIInputStreamP15nsIOutputStreamP14nsIEventTarget15nsAsyncCopyModejPFvPvjES6_
+ _Z12NS_InitXPCOMPP17nsIServiceManagerP7nsIFile
+ _Z12NS_NewThreadPP9nsIThreadP11nsIRunnablej13PRThreadState16PRThreadPriority13PRThreadScope
+ _Z12NS_NewThreadPP9nsIThreadj13PRThreadState16PRThreadPriority13PRThreadScope
+ _Z12ToNewCStringRK10nsACString
+ _Z12ToNewCStringRK9nsAString
+ _Z12ToNewUnicodeRK10nsACString
+ _Z12ToNewUnicodeRK9nsAString
+ _Z13CopyUnicodeToRK17nsReadingIteratorItES2_R9nsAString
+ _Z13CopyUnicodeToRK9nsAStringjPtj
+ _Z14FindInReadableRK10nsACStringR17nsReadingIteratorIcES4_RK19nsCStringComparator
+ _Z14FindInReadableRK9nsAStringR17nsReadingIteratorItES4_RK18nsStringComparator
+ _Z14StringEndsWithRK10nsACStringS1_RK19nsCStringComparator
+ _Z14StringEndsWithRK9nsAStringS1_RK18nsStringComparator
+ _Z15AppendUnicodeToRK17nsReadingIteratorItES2_R9nsAString
+ _Z15CopyUTF16toUTF8PKtR10nsACString
+ _Z15CopyUTF16toUTF8RK9nsAStringR10nsACString
+ _Z15CopyUTF8toUTF16PKcR9nsAString
+ _Z15CopyUTF8toUTF16RK10nsACStringR9nsAString
+ _Z15NS_ProxyReleaseP14nsIEventTargetP11nsISupportsi
+ _Z15RFindInReadableRK10nsACStringR17nsReadingIteratorIcES4_RK19nsCStringComparator
+ _Z15RFindInReadableRK9nsAStringR17nsReadingIteratorItES4_RK18nsStringComparator
+ _Z15ToNewUTF8StringRK9nsAStringPj
+ _Z16CopyASCIItoUTF16PKcR9nsAString
+ _Z16CopyASCIItoUTF16RK10nsACStringR9nsAString
+ _Z16NS_NewByteBufferPP13nsIByteBufferP11nsISupportsj
+ _Z16StringBeginsWithRK10nsACStringS1_RK19nsCStringComparator
+ _Z16StringBeginsWithRK9nsAStringS1_RK18nsStringComparator
+ _Z16UTF8ToNewUnicodeRK10nsACStringPj
+ _Z17AppendUTF16toUTF8PKtR10nsACString
+ _Z17AppendUTF16toUTF8RK9nsAStringR10nsACString
+ _Z17AppendUTF8toUTF16PKcR9nsAString
+ _Z17AppendUTF8toUTF16RK10nsACStringR9nsAString
+ _Z18AppendASCIItoUTF16PKcR9nsAString
+ _Z18AppendASCIItoUTF16RK10nsACStringR9nsAString
+ _Z18FindCharInReadablecR17nsReadingIteratorIcERKS0_
+ _Z18FindCharInReadabletR17nsReadingIteratorItERKS0_
+ _Z19CountCharInReadableRK10nsACStringc
+ _Z19CountCharInReadableRK9nsAStringt
+ _Z19NS_GetNumberOfAtomsv
+ _Z19NS_GetWeakReferenceP11nsISupportsPj
+ _Z19NS_NewGenericModulePKcjP21nsModuleComponentInfoPFvP9nsIModuleEPS4_
+ _Z19NS_NewPermanentAtomPKc
+ _Z19NS_NewPermanentAtomPKt
+ _Z19NS_NewPermanentAtomRK10nsACString
+ _Z19NS_NewPermanentAtomRK9nsAString
+ _Z19NS_NewStorageStreamjjPP16nsIStorageStream
+ _Z19NS_NewUnicharBufferPP16nsIUnicharBufferP11nsISupportsj
+ _Z19TestSegmentedBufferv
+ _Z20NS_GetProxyForObjectP13nsIEventQueueRK4nsIDP11nsISupportsiPPv
+ _Z20NS_NewGenericFactoryPP17nsIGenericFactoryPK21nsModuleComponentInfo
+ _Z20NS_NewGenericModule2P12nsModuleInfoPP9nsIModule
+ _Z20NS_NewISupportsArrayPP16nsISupportsArray
+ _Z21LossyCopyUTF16toASCIIPKtR10nsACString
+ _Z21LossyCopyUTF16toASCIIRK9nsAStringR10nsACString
+ _Z21NS_NewArrayEnumeratorPP19nsISimpleEnumeratorP16nsISupportsArray
+ _Z21NS_NewArrayEnumeratorPP19nsISimpleEnumeratorP8nsIArray
+ _Z21NS_NewArrayEnumeratorPP19nsISimpleEnumeratorRK15nsCOMArray_base
+ _Z22NS_CopyNativeToUnicodeRK10nsACStringR9nsAString
+ _Z22NS_CopyUnicodeToNativeRK9nsAStringR10nsACString
+ _Z22NS_RegisterStaticAtomsPK12nsStaticAtomj
+ _Z22PL_DHashStubEnumRemoveP12PLDHashTableP15PLDHashEntryHdrjPv
+ _Z23LossyAppendUTF16toASCIIPKtR10nsACString
+ _Z23LossyAppendUTF16toASCIIRK9nsAStringR10nsACString
+ _Z23NS_AddFastLoadChecksumsjjj
+ _Z23NS_ErrorAccordingToNSPRv
+ _Z24NS_NewFastLoadFileReaderPP20nsIObjectInputStreamP14nsIInputStream
+ _Z24NS_NewFastLoadFileWriterPP21nsIObjectOutputStreamP15nsIOutputStreamP17nsIFastLoadFileIO
+ _Z25NS_NewFastLoadFileUpdaterPP21nsIObjectOutputStreamP15nsIOutputStreamP20nsIObjectInputStream
+ _Z25NS_NewUTF8ConverterStreamPP21nsIUnicharInputStreamP14nsIInputStreami
+ _Z27NS_NewInputStreamReadyEventPP22nsIInputStreamCallbackS0_P14nsIEventTarget
+ _Z28NS_GetGlobalComponentManagerPP19nsIComponentManager
+ _Z28NS_NewOutputStreamReadyEventPP23nsIOutputStreamCallbackS0_P14nsIEventTarget
+ _Z29CaseInsensitiveFindInReadableRK10nsACStringR17nsReadingIteratorIcES4_
+ _Z29NS_AccumulateFastLoadChecksumPjPKhji
+ _Z29NS_CreateServicesFromCategoryPKcP11nsISupportsS0_
+ _Z29StartupSpecialSystemDirectoryv
+ _Z30NS_NewISupportsArrayEnumeratorP16nsISupportsArrayPP26nsIBidirectionalEnumerator
+ _Z30NS_NewStringUnicharInputStreamPP21nsIUnicharInputStreamP8nsString
+ _Z30ShutdownSpecialSystemDirectoryv
+ _Z6IsUTF8RK10nsACString
+ _Z7CompareRK10nsACStringS1_RK19nsCStringComparator
+ _Z7CompareRK9nsAStringS1_RK18nsStringComparator
+ _Z7IsASCIIRK10nsACString
+ _Z7IsASCIIRK9nsAString
+ _ZN10nsACString11AppendASCIIEPKc
+ _ZN10nsACString11AppendASCIIEPKcj
+ _ZN10nsACString11AssignASCIIEPKc
+ _ZN10nsACString11AssignASCIIEPKcj
+ _ZN10nsACString11SetCapacityEj
+ _ZN10nsACString17GetWritableBufferEPPc
+ _ZN10nsACString3CutEjj
+ _ZN10nsACString6AppendEPKc
+ _ZN10nsACString6AppendEPKcj
+ _ZN10nsACString6AppendERK17nsCSubstringTuple
+ _ZN10nsACString6AppendERKS_
+ _ZN10nsACString6AppendEc
+ _ZN10nsACString6AssignEPKc
+ _ZN10nsACString6AssignEPKcj
+ _ZN10nsACString6AssignERK17nsCSubstringTuple
+ _ZN10nsACString6AssignERKS_
+ _ZN10nsACString6AssignEc
+ _ZN10nsACString6InsertEPKcj
+ _ZN10nsACString6InsertEPKcjj
+ _ZN10nsACString6InsertERK17nsCSubstringTuplej
+ _ZN10nsACString6InsertERKS_j
+ _ZN10nsACString6InsertEcj
+ _ZN10nsACString7ReplaceEjjRK17nsCSubstringTuple
+ _ZN10nsACString7ReplaceEjjRKS_
+ _ZN10nsACString9SetIsVoidEi
+ _ZN10nsACString9SetLengthEj
+ _ZN10nsACStringD1Ev
+ _ZN10nsACStringD2Ev
+ _ZN11nsHashtable3GetEP9nsHashKey
+ _ZN11nsHashtable3PutEP9nsHashKeyPv
+ _ZN11nsHashtable5CloneEv
+ _ZN11nsHashtable5ResetEPFiP9nsHashKeyPvS2_ES2_
+ _ZN11nsHashtable5ResetEv
+ _ZN11nsHashtable6ExistsEP9nsHashKey
+ _ZN11nsHashtable6RemoveEP9nsHashKey
+ _ZN11nsHashtable9EnumerateEPFiP9nsHashKeyPvS2_ES2_
+ _ZN11nsHashtableC1EP20nsIObjectInputStreamPFjS1_PP9nsHashKeyPPvEPFvS1_S3_S5_EPj
+ _ZN11nsHashtableC1Eji
+ _ZN11nsHashtableC2EP20nsIObjectInputStreamPFjS1_PP9nsHashKeyPPvEPFvS1_S3_S5_EPj
+ _ZN11nsHashtableC2Eji
+ _ZN11nsHashtableD0Ev
+ _ZN11nsHashtableD1Ev
+ _ZN11nsHashtableD2Ev
+ _ZN11nsIDHashKey7HashKeyEPK4nsID
+ _ZN11nsLocalFile10GlobalInitEv
+ _ZN11nsLocalFile13FillStatCacheEv
+ _ZN11nsLocalFile14GlobalShutdownEv
+ _ZN11nsLocalFile15CopyDirectoryToEP7nsIFile
+ _ZN11nsLocalFile17CreateAndKeepOpenEjijPP10PRFileDesc
+ _ZN11nsLocalFile18CreateAllAncestorsEj
+ _ZN11nsLocalFile20LocateNativeLeafNameER17nsReadingIteratorIcES2_
+ _ZN11nsLocalFile22nsLocalFileConstructorEP11nsISupportsRK4nsIDPPv
+ _ZN11nsLocalFile23GetNativeTargetPathNameEP7nsIFileRK10nsACStringRS2_
+ _ZN11nsLocalFileC1ERKS_
+ _ZN11nsLocalFileC1Ev
+ _ZN11nsLocalFileC2ERKS_
+ _ZN11nsLocalFileC2Ev
+ _ZN11nsStringKeyC1EP20nsIObjectInputStreamPj
+ _ZN11nsStringKeyC1EPKtiNS_9OwnershipE
+ _ZN11nsStringKeyC1ERK8nsString
+ _ZN11nsStringKeyC1ERK9nsAString
+ _ZN11nsStringKeyC1ERKS_
+ _ZN11nsStringKeyC2EP20nsIObjectInputStreamPj
+ _ZN11nsStringKeyC2EPKtiNS_9OwnershipE
+ _ZN11nsStringKeyC2ERK8nsString
+ _ZN11nsStringKeyC2ERK9nsAString
+ _ZN11nsStringKeyC2ERKS_
+ _ZN11nsStringKeyD0Ev
+ _ZN11nsStringKeyD1Ev
+ _ZN11nsStringKeyD2Ev
+ _ZN11nsSubstring11AssignASCIIEPKc
+ _ZN11nsSubstring11AssignASCIIEPKcj
+ _ZN11nsSubstring11SetCapacityEj
+ _ZN11nsSubstring12ReplaceASCIIEjjPKcj
+ _ZN11nsSubstring13EnsureMutableEv
+ _ZN11nsSubstring5AdoptEPtj
+ _ZN11nsSubstring6AssignEPKtj
+ _ZN11nsSubstring6AssignERK16nsSubstringTuple
+ _ZN11nsSubstring6AssignERK9nsAString
+ _ZN11nsSubstring6AssignERKS_
+ _ZN11nsSubstring7ReplaceEjjPKtj
+ _ZN11nsSubstring7ReplaceEjjRK16nsSubstringTuple
+ _ZN11nsSubstring7ReplaceEjjRK9nsAString
+ _ZN11nsSubstring9SetIsVoidEi
+ _ZN11nsSubstring9SetLengthEj
+ _ZN11nsVoidArray11GrowArrayByEi
+ _ZN11nsVoidArray11MoveElementEii
+ _ZN11nsVoidArray13RemoveElementEPv
+ _ZN11nsVoidArray15InsertElementAtEPvi
+ _ZN11nsVoidArray16InsertElementsAtERKS_i
+ _ZN11nsVoidArray16RemoveElementsAtEii
+ _ZN11nsVoidArray16ReplaceElementAtEPvi
+ _ZN11nsVoidArray17EnumerateForwardsEPFiPvS0_ES0_
+ _ZN11nsVoidArray18EnumerateBackwardsEPFiPvS0_ES0_
+ _ZN11nsVoidArray4SortEPFiPKvS1_PvES2_
+ _ZN11nsVoidArray5ClearEv
+ _ZN11nsVoidArray6SizeToEi
+ _ZN11nsVoidArray7CompactEv
+ _ZN11nsVoidArrayC1Ei
+ _ZN11nsVoidArrayC1Ev
+ _ZN11nsVoidArrayC2Ei
+ _ZN11nsVoidArrayC2Ev
+ _ZN11nsVoidArrayD0Ev
+ _ZN11nsVoidArrayD1Ev
+ _ZN11nsVoidArrayD2Ev
+ _ZN11nsVoidArrayaSERKS_
+ _ZN12nsCStringKeyC1EP20nsIObjectInputStreamPj
+ _ZN12nsCStringKeyC1EPKciNS_9OwnershipE
+ _ZN12nsCStringKeyC1ERK10nsACString
+ _ZN12nsCStringKeyC1ERK9nsCString
+ _ZN12nsCStringKeyC1ERKS_
+ _ZN12nsCStringKeyC2EP20nsIObjectInputStreamPj
+ _ZN12nsCStringKeyC2EPKciNS_9OwnershipE
+ _ZN12nsCStringKeyC2ERK10nsACString
+ _ZN12nsCStringKeyC2ERK9nsCString
+ _ZN12nsCStringKeyC2ERKS_
+ _ZN12nsCStringKeyD0Ev
+ _ZN12nsCStringKeyD1Ev
+ _ZN12nsCStringKeyD2Ev
+ _ZN12nsCSubstring11AssignASCIIEPKc
+ _ZN12nsCSubstring11AssignASCIIEPKcj
+ _ZN12nsCSubstring11SetCapacityEj
+ _ZN12nsCSubstring12ReplaceASCIIEjjPKcj
+ _ZN12nsCSubstring13EnsureMutableEv
+ _ZN12nsCSubstring5AdoptEPcj
+ _ZN12nsCSubstring6AssignEPKcj
+ _ZN12nsCSubstring6AssignERK10nsACString
+ _ZN12nsCSubstring6AssignERK17nsCSubstringTuple
+ _ZN12nsCSubstring6AssignERKS_
+ _ZN12nsCSubstring7ReplaceEjjPKcj
+ _ZN12nsCSubstring7ReplaceEjjRK10nsACString
+ _ZN12nsCSubstring7ReplaceEjjRK17nsCSubstringTuple
+ _ZN12nsCSubstring9SetIsVoidEi
+ _ZN12nsCSubstring9SetLengthEj
+ _ZN13nsAutoMonitor10NewMonitorEPKc
+ _ZN13nsAutoMonitor14DestroyMonitorEP9PRMonitor
+ _ZN13nsAutoMonitor4ExitEv
+ _ZN13nsAutoMonitor5EnterEv
+ _ZN13nsCOMPtr_base14assign_from_qiE16nsQueryInterfaceRK4nsID
+ _ZN13nsCOMPtr_base16begin_assignmentEv
+ _ZN13nsCOMPtr_base18assign_from_helperERK15nsCOMPtr_helperRK4nsID
+ _ZN13nsCOMPtr_base18assign_with_AddRefEP11nsISupports
+ _ZN13nsCOMPtr_base25assign_from_qi_with_errorERK25nsQueryInterfaceWithErrorRK4nsID
+ _ZN13nsCOMPtr_baseD1Ev
+ _ZN13nsCOMPtr_baseD2Ev
+ _ZN13nsStringArray12RemoveStringERK9nsAString
+ _ZN13nsStringArray14InsertStringAtERK9nsAStringi
+ _ZN13nsStringArray14RemoveStringAtEi
+ _ZN13nsStringArray15ReplaceStringAtERK9nsAStringi
+ _ZN13nsStringArray17EnumerateForwardsEPFiR8nsStringPvES2_
+ _ZN13nsStringArray18EnumerateBackwardsEPFiR8nsStringPvES2_
+ _ZN13nsStringArray4SortEPFiPK8nsStringS2_PvES3_
+ _ZN13nsStringArray4SortEv
+ _ZN13nsStringArray5ClearEv
+ _ZN13nsStringArrayC1Ei
+ _ZN13nsStringArrayC1Ev
+ _ZN13nsStringArrayC2Ei
+ _ZN13nsStringArrayC2Ev
+ _ZN13nsStringArrayD0Ev
+ _ZN13nsStringArrayD1Ev
+ _ZN13nsStringArrayD2Ev
+ _ZN13nsStringArrayaSERKS_
+ _ZN13nsTraceRefcnt10LogReleaseEPvjPKc
+ _ZN13nsTraceRefcnt12LogAddCOMPtrEPvP11nsISupports
+ _ZN13nsTraceRefcnt16LogReleaseCOMPtrEPvP11nsISupports
+ _ZN13nsTraceRefcnt7LogCtorEPvPKcj
+ _ZN13nsTraceRefcnt7LogDtorEPvPKcj
+ _ZN13nsTraceRefcnt9LogAddRefEPvjPKcj
+ _ZN14nsAutoCMonitor4ExitEv
+ _ZN14nsAutoCMonitor5EnterEv
+ _ZN14nsAutoLockBase4HideEv
+ _ZN14nsAutoLockBase4ShowEv
+ _ZN14nsAutoLockBaseC1EPvNS_14nsAutoLockTypeE
+ _ZN14nsAutoLockBaseC2EPvNS_14nsAutoLockTypeE
+ _ZN14nsAutoLockBaseD1Ev
+ _ZN14nsAutoLockBaseD2Ev
+ _ZN14nsCStringArray11ParseStringEPKcS1_
+ _ZN14nsCStringArray13RemoveCStringERK10nsACString
+ _ZN14nsCStringArray14SortIgnoreCaseEv
+ _ZN14nsCStringArray15InsertCStringAtERK10nsACStringi
+ _ZN14nsCStringArray15RemoveCStringAtEi
+ _ZN14nsCStringArray16ReplaceCStringAtERK10nsACStringi
+ _ZN14nsCStringArray17EnumerateForwardsEPFiR9nsCStringPvES2_
+ _ZN14nsCStringArray18EnumerateBackwardsEPFiR9nsCStringPvES2_
+ _ZN14nsCStringArray23RemoveCStringIgnoreCaseERK10nsACString
+ _ZN14nsCStringArray4SortEPFiPK9nsCStringS2_PvES3_
+ _ZN14nsCStringArray4SortEv
+ _ZN14nsCStringArray5ClearEv
+ _ZN14nsCStringArrayC1Ei
+ _ZN14nsCStringArrayC1Ev
+ _ZN14nsCStringArrayC2Ei
+ _ZN14nsCStringArrayC2Ev
+ _ZN14nsCStringArrayD0Ev
+ _ZN14nsCStringArrayD1Ev
+ _ZN14nsCStringArrayD2Ev
+ _ZN14nsCStringArrayaSERKS_
+ _ZN14nsISupportsKeyC1EP20nsIObjectInputStreamPj
+ _ZN14nsISupportsKeyC2EP20nsIObjectInputStreamPj
+ _ZN14nsXPTCStubBase14QueryInterfaceERK4nsIDPPv
+ _ZN14nsXPTCStubBase5Stub3Ev
+ _ZN14nsXPTCStubBase5Stub4Ev
+ _ZN14nsXPTCStubBase5Stub5Ev
+ _ZN14nsXPTCStubBase5Stub6Ev
+ _ZN14nsXPTCStubBase5Stub7Ev
+ _ZN14nsXPTCStubBase5Stub8Ev
+ _ZN14nsXPTCStubBase5Stub9Ev
+ _ZN14nsXPTCStubBase6Stub10Ev
+ _ZN14nsXPTCStubBase6Stub11Ev
+ _ZN14nsXPTCStubBase6Stub12Ev
+ _ZN14nsXPTCStubBase6Stub13Ev
+ _ZN14nsXPTCStubBase6Stub14Ev
+ _ZN14nsXPTCStubBase6Stub15Ev
+ _ZN14nsXPTCStubBase6Stub16Ev
+ _ZN14nsXPTCStubBase6Stub17Ev
+ _ZN14nsXPTCStubBase6Stub18Ev
+ _ZN14nsXPTCStubBase6Stub19Ev
+ _ZN14nsXPTCStubBase6Stub20Ev
+ _ZN14nsXPTCStubBase6Stub21Ev
+ _ZN14nsXPTCStubBase6Stub22Ev
+ _ZN14nsXPTCStubBase6Stub23Ev
+ _ZN14nsXPTCStubBase6Stub24Ev
+ _ZN14nsXPTCStubBase6Stub25Ev
+ _ZN14nsXPTCStubBase6Stub26Ev
+ _ZN14nsXPTCStubBase6Stub27Ev
+ _ZN14nsXPTCStubBase6Stub28Ev
+ _ZN14nsXPTCStubBase6Stub29Ev
+ _ZN14nsXPTCStubBase6Stub30Ev
+ _ZN14nsXPTCStubBase6Stub31Ev
+ _ZN14nsXPTCStubBase6Stub32Ev
+ _ZN14nsXPTCStubBase6Stub33Ev
+ _ZN14nsXPTCStubBase6Stub34Ev
+ _ZN14nsXPTCStubBase6Stub35Ev
+ _ZN14nsXPTCStubBase6Stub36Ev
+ _ZN14nsXPTCStubBase6Stub37Ev
+ _ZN14nsXPTCStubBase6Stub38Ev
+ _ZN14nsXPTCStubBase6Stub39Ev
+ _ZN14nsXPTCStubBase6Stub40Ev
+ _ZN14nsXPTCStubBase6Stub41Ev
+ _ZN14nsXPTCStubBase6Stub42Ev
+ _ZN14nsXPTCStubBase6Stub43Ev
+ _ZN14nsXPTCStubBase6Stub44Ev
+ _ZN14nsXPTCStubBase6Stub45Ev
+ _ZN14nsXPTCStubBase6Stub46Ev
+ _ZN14nsXPTCStubBase6Stub47Ev
+ _ZN14nsXPTCStubBase6Stub48Ev
+ _ZN14nsXPTCStubBase6Stub49Ev
+ _ZN14nsXPTCStubBase6Stub50Ev
+ _ZN14nsXPTCStubBase6Stub51Ev
+ _ZN14nsXPTCStubBase6Stub52Ev
+ _ZN14nsXPTCStubBase6Stub53Ev
+ _ZN14nsXPTCStubBase6Stub54Ev
+ _ZN14nsXPTCStubBase6Stub55Ev
+ _ZN14nsXPTCStubBase6Stub56Ev
+ _ZN14nsXPTCStubBase6Stub57Ev
+ _ZN14nsXPTCStubBase6Stub58Ev
+ _ZN14nsXPTCStubBase6Stub59Ev
+ _ZN14nsXPTCStubBase6Stub60Ev
+ _ZN14nsXPTCStubBase6Stub61Ev
+ _ZN14nsXPTCStubBase6Stub62Ev
+ _ZN14nsXPTCStubBase6Stub63Ev
+ _ZN14nsXPTCStubBase6Stub64Ev
+ _ZN14nsXPTCStubBase6Stub65Ev
+ _ZN14nsXPTCStubBase6Stub66Ev
+ _ZN14nsXPTCStubBase6Stub67Ev
+ _ZN14nsXPTCStubBase6Stub68Ev
+ _ZN14nsXPTCStubBase6Stub69Ev
+ _ZN14nsXPTCStubBase6Stub70Ev
+ _ZN14nsXPTCStubBase6Stub71Ev
+ _ZN14nsXPTCStubBase6Stub72Ev
+ _ZN14nsXPTCStubBase6Stub73Ev
+ _ZN14nsXPTCStubBase6Stub74Ev
+ _ZN14nsXPTCStubBase6Stub75Ev
+ _ZN14nsXPTCStubBase6Stub76Ev
+ _ZN14nsXPTCStubBase6Stub77Ev
+ _ZN14nsXPTCStubBase6Stub78Ev
+ _ZN14nsXPTCStubBase6Stub79Ev
+ _ZN14nsXPTCStubBase6Stub80Ev
+ _ZN14nsXPTCStubBase6Stub81Ev
+ _ZN14nsXPTCStubBase6Stub82Ev
+ _ZN14nsXPTCStubBase6Stub83Ev
+ _ZN14nsXPTCStubBase6Stub84Ev
+ _ZN14nsXPTCStubBase6Stub85Ev
+ _ZN14nsXPTCStubBase6Stub86Ev
+ _ZN14nsXPTCStubBase6Stub87Ev
+ _ZN14nsXPTCStubBase6Stub88Ev
+ _ZN14nsXPTCStubBase6Stub89Ev
+ _ZN14nsXPTCStubBase6Stub90Ev
+ _ZN14nsXPTCStubBase6Stub91Ev
+ _ZN14nsXPTCStubBase6Stub92Ev
+ _ZN14nsXPTCStubBase6Stub93Ev
+ _ZN14nsXPTCStubBase6Stub94Ev
+ _ZN14nsXPTCStubBase6Stub95Ev
+ _ZN14nsXPTCStubBase6Stub96Ev
+ _ZN14nsXPTCStubBase6Stub97Ev
+ _ZN14nsXPTCStubBase6Stub98Ev
+ _ZN14nsXPTCStubBase6Stub99Ev
+ _ZN14nsXPTCStubBase7Stub100Ev
+ _ZN14nsXPTCStubBase7Stub101Ev
+ _ZN14nsXPTCStubBase7Stub102Ev
+ _ZN14nsXPTCStubBase7Stub103Ev
+ _ZN14nsXPTCStubBase7Stub104Ev
+ _ZN14nsXPTCStubBase7Stub105Ev
+ _ZN14nsXPTCStubBase7Stub106Ev
+ _ZN14nsXPTCStubBase7Stub107Ev
+ _ZN14nsXPTCStubBase7Stub108Ev
+ _ZN14nsXPTCStubBase7Stub109Ev
+ _ZN14nsXPTCStubBase7Stub110Ev
+ _ZN14nsXPTCStubBase7Stub111Ev
+ _ZN14nsXPTCStubBase7Stub112Ev
+ _ZN14nsXPTCStubBase7Stub113Ev
+ _ZN14nsXPTCStubBase7Stub114Ev
+ _ZN14nsXPTCStubBase7Stub115Ev
+ _ZN14nsXPTCStubBase7Stub116Ev
+ _ZN14nsXPTCStubBase7Stub117Ev
+ _ZN14nsXPTCStubBase7Stub118Ev
+ _ZN14nsXPTCStubBase7Stub119Ev
+ _ZN14nsXPTCStubBase7Stub120Ev
+ _ZN14nsXPTCStubBase7Stub121Ev
+ _ZN14nsXPTCStubBase7Stub122Ev
+ _ZN14nsXPTCStubBase7Stub123Ev
+ _ZN14nsXPTCStubBase7Stub124Ev
+ _ZN14nsXPTCStubBase7Stub125Ev
+ _ZN14nsXPTCStubBase7Stub126Ev
+ _ZN14nsXPTCStubBase7Stub127Ev
+ _ZN14nsXPTCStubBase7Stub128Ev
+ _ZN14nsXPTCStubBase7Stub129Ev
+ _ZN14nsXPTCStubBase7Stub130Ev
+ _ZN14nsXPTCStubBase7Stub131Ev
+ _ZN14nsXPTCStubBase7Stub132Ev
+ _ZN14nsXPTCStubBase7Stub133Ev
+ _ZN14nsXPTCStubBase7Stub134Ev
+ _ZN14nsXPTCStubBase7Stub135Ev
+ _ZN14nsXPTCStubBase7Stub136Ev
+ _ZN14nsXPTCStubBase7Stub137Ev
+ _ZN14nsXPTCStubBase7Stub138Ev
+ _ZN14nsXPTCStubBase7Stub139Ev
+ _ZN14nsXPTCStubBase7Stub140Ev
+ _ZN14nsXPTCStubBase7Stub141Ev
+ _ZN14nsXPTCStubBase7Stub142Ev
+ _ZN14nsXPTCStubBase7Stub143Ev
+ _ZN14nsXPTCStubBase7Stub144Ev
+ _ZN14nsXPTCStubBase7Stub145Ev
+ _ZN14nsXPTCStubBase7Stub146Ev
+ _ZN14nsXPTCStubBase7Stub147Ev
+ _ZN14nsXPTCStubBase7Stub148Ev
+ _ZN14nsXPTCStubBase7Stub149Ev
+ _ZN14nsXPTCStubBase7Stub150Ev
+ _ZN14nsXPTCStubBase7Stub151Ev
+ _ZN14nsXPTCStubBase7Stub152Ev
+ _ZN14nsXPTCStubBase7Stub153Ev
+ _ZN14nsXPTCStubBase7Stub154Ev
+ _ZN14nsXPTCStubBase7Stub155Ev
+ _ZN14nsXPTCStubBase7Stub156Ev
+ _ZN14nsXPTCStubBase7Stub157Ev
+ _ZN14nsXPTCStubBase7Stub158Ev
+ _ZN14nsXPTCStubBase7Stub159Ev
+ _ZN14nsXPTCStubBase7Stub160Ev
+ _ZN14nsXPTCStubBase7Stub161Ev
+ _ZN14nsXPTCStubBase7Stub162Ev
+ _ZN14nsXPTCStubBase7Stub163Ev
+ _ZN14nsXPTCStubBase7Stub164Ev
+ _ZN14nsXPTCStubBase7Stub165Ev
+ _ZN14nsXPTCStubBase7Stub166Ev
+ _ZN14nsXPTCStubBase7Stub167Ev
+ _ZN14nsXPTCStubBase7Stub168Ev
+ _ZN14nsXPTCStubBase7Stub169Ev
+ _ZN14nsXPTCStubBase7Stub170Ev
+ _ZN14nsXPTCStubBase7Stub171Ev
+ _ZN14nsXPTCStubBase7Stub172Ev
+ _ZN14nsXPTCStubBase7Stub173Ev
+ _ZN14nsXPTCStubBase7Stub174Ev
+ _ZN14nsXPTCStubBase7Stub175Ev
+ _ZN14nsXPTCStubBase7Stub176Ev
+ _ZN14nsXPTCStubBase7Stub177Ev
+ _ZN14nsXPTCStubBase7Stub178Ev
+ _ZN14nsXPTCStubBase7Stub179Ev
+ _ZN14nsXPTCStubBase7Stub180Ev
+ _ZN14nsXPTCStubBase7Stub181Ev
+ _ZN14nsXPTCStubBase7Stub182Ev
+ _ZN14nsXPTCStubBase7Stub183Ev
+ _ZN14nsXPTCStubBase7Stub184Ev
+ _ZN14nsXPTCStubBase7Stub185Ev
+ _ZN14nsXPTCStubBase7Stub186Ev
+ _ZN14nsXPTCStubBase7Stub187Ev
+ _ZN14nsXPTCStubBase7Stub188Ev
+ _ZN14nsXPTCStubBase7Stub189Ev
+ _ZN14nsXPTCStubBase7Stub190Ev
+ _ZN14nsXPTCStubBase7Stub191Ev
+ _ZN14nsXPTCStubBase7Stub192Ev
+ _ZN14nsXPTCStubBase7Stub193Ev
+ _ZN14nsXPTCStubBase7Stub194Ev
+ _ZN14nsXPTCStubBase7Stub195Ev
+ _ZN14nsXPTCStubBase7Stub196Ev
+ _ZN14nsXPTCStubBase7Stub197Ev
+ _ZN14nsXPTCStubBase7Stub198Ev
+ _ZN14nsXPTCStubBase7Stub199Ev
+ _ZN14nsXPTCStubBase7Stub200Ev
+ _ZN14nsXPTCStubBase7Stub201Ev
+ _ZN14nsXPTCStubBase7Stub202Ev
+ _ZN14nsXPTCStubBase7Stub203Ev
+ _ZN14nsXPTCStubBase7Stub204Ev
+ _ZN14nsXPTCStubBase7Stub205Ev
+ _ZN14nsXPTCStubBase7Stub206Ev
+ _ZN14nsXPTCStubBase7Stub207Ev
+ _ZN14nsXPTCStubBase7Stub208Ev
+ _ZN14nsXPTCStubBase7Stub209Ev
+ _ZN14nsXPTCStubBase7Stub210Ev
+ _ZN14nsXPTCStubBase7Stub211Ev
+ _ZN14nsXPTCStubBase7Stub212Ev
+ _ZN14nsXPTCStubBase7Stub213Ev
+ _ZN14nsXPTCStubBase7Stub214Ev
+ _ZN14nsXPTCStubBase7Stub215Ev
+ _ZN14nsXPTCStubBase7Stub216Ev
+ _ZN14nsXPTCStubBase7Stub217Ev
+ _ZN14nsXPTCStubBase7Stub218Ev
+ _ZN14nsXPTCStubBase7Stub219Ev
+ _ZN14nsXPTCStubBase7Stub220Ev
+ _ZN14nsXPTCStubBase7Stub221Ev
+ _ZN14nsXPTCStubBase7Stub222Ev
+ _ZN14nsXPTCStubBase7Stub223Ev
+ _ZN14nsXPTCStubBase7Stub224Ev
+ _ZN14nsXPTCStubBase7Stub225Ev
+ _ZN14nsXPTCStubBase7Stub226Ev
+ _ZN14nsXPTCStubBase7Stub227Ev
+ _ZN14nsXPTCStubBase7Stub228Ev
+ _ZN14nsXPTCStubBase7Stub229Ev
+ _ZN14nsXPTCStubBase7Stub230Ev
+ _ZN14nsXPTCStubBase7Stub231Ev
+ _ZN14nsXPTCStubBase7Stub232Ev
+ _ZN14nsXPTCStubBase7Stub233Ev
+ _ZN14nsXPTCStubBase7Stub234Ev
+ _ZN14nsXPTCStubBase7Stub235Ev
+ _ZN14nsXPTCStubBase7Stub236Ev
+ _ZN14nsXPTCStubBase7Stub237Ev
+ _ZN14nsXPTCStubBase7Stub238Ev
+ _ZN14nsXPTCStubBase7Stub239Ev
+ _ZN14nsXPTCStubBase7Stub240Ev
+ _ZN14nsXPTCStubBase7Stub241Ev
+ _ZN14nsXPTCStubBase7Stub242Ev
+ _ZN14nsXPTCStubBase7Stub243Ev
+ _ZN14nsXPTCStubBase7Stub244Ev
+ _ZN14nsXPTCStubBase7Stub245Ev
+ _ZN14nsXPTCStubBase7Stub246Ev
+ _ZN14nsXPTCStubBase7Stub247Ev
+ _ZN14nsXPTCStubBase7Stub248Ev
+ _ZN14nsXPTCStubBase7Stub249Ev
+ _ZN14nsXPTCStubBase9Sentinel0Ev
+ _ZN14nsXPTCStubBase9Sentinel1Ev
+ _ZN14nsXPTCStubBase9Sentinel2Ev
+ _ZN14nsXPTCStubBase9Sentinel3Ev
+ _ZN14nsXPTCStubBase9Sentinel4Ev
+ _ZN15nsAutoVoidArray5ClearEv
+ _ZN15nsAutoVoidArray6SizeToEi
+ _ZN15nsAutoVoidArray7CompactEv
+ _ZN15nsAutoVoidArrayC1Ev
+ _ZN15nsAutoVoidArrayC2Ev
+ _ZN15nsCOMArray_base12RemoveObjectEP11nsISupports
+ _ZN15nsCOMArray_base14InsertObjectAtEP11nsISupportsi
+ _ZN15nsCOMArray_base14RemoveObjectAtEi
+ _ZN15nsCOMArray_base15InsertObjectsAtERKS_i
+ _ZN15nsCOMArray_base15ReplaceObjectAtEP11nsISupportsi
+ _ZN15nsCOMArray_base5ClearEv
+ _ZN15nsCOMArray_baseC1ERKS_
+ _ZN15nsCOMArray_baseC2ERKS_
+ _ZN15nsCOMArray_baseD1Ev
+ _ZN15nsCOMArray_baseD2Ev
+ _ZN15nsPrintfCStringC1EPKcz
+ _ZN15nsPrintfCStringC1EjPKcz
+ _ZN15nsPrintfCStringC2EPKcz
+ _ZN15nsPrintfCStringC2EjPKcz
+ _ZN15nsSupportsArray11DeleteArrayEv
+ _ZN15nsSupportsArray11GrowArrayByEi
+ _ZN15nsSupportsArray11LastIndexOfEPK11nsISupports
+ _ZN15nsSupportsArray11MoveElementEii
+ _ZN15nsSupportsArray13RemoveElementEPK11nsISupportsj
+ _ZN15nsSupportsArray14QueryInterfaceERK4nsIDPPv
+ _ZN15nsSupportsArray15InsertElementAtEP11nsISupportsj
+ _ZN15nsSupportsArray16InsertElementsAtEP16nsISupportsArrayj
+ _ZN15nsSupportsArray16RemoveElementsAtEjj
+ _ZN15nsSupportsArray16ReplaceElementAtEP11nsISupportsj
+ _ZN15nsSupportsArray17EnumerateForwardsEPFiP11nsISupportsPvES2_
+ _ZN15nsSupportsArray17IndexOfStartingAtEPK11nsISupportsj
+ _ZN15nsSupportsArray17RemoveLastElementEPK11nsISupports
+ _ZN15nsSupportsArray18EnumerateBackwardsEPFiP11nsISupportsPvES2_
+ _ZN15nsSupportsArray4ReadEP20nsIObjectInputStream
+ _ZN15nsSupportsArray5ClearEv
+ _ZN15nsSupportsArray5CloneEPP16nsISupportsArray
+ _ZN15nsSupportsArray5WriteEP21nsIObjectOutputStream
+ _ZN15nsSupportsArray6AddRefEv
+ _ZN15nsSupportsArray6CreateEP11nsISupportsRK4nsIDPPv
+ _ZN15nsSupportsArray6EqualsEPK16nsISupportsArray
+ _ZN15nsSupportsArray6SizeToEi
+ _ZN15nsSupportsArray7CompactEv
+ _ZN15nsSupportsArray7IndexOfEPK11nsISupports
+ _ZN15nsSupportsArray7ReleaseEv
+ _ZN15nsSupportsArray9ElementAtEj
+ _ZN15nsSupportsArray9EnumerateEPP13nsIEnumerator
+ _ZN15nsSupportsArrayC1Ev
+ _ZN15nsSupportsArrayC2Ev
+ _ZN15nsSupportsArrayD1Ev
+ _ZN15nsSupportsArrayD2Ev
+ _ZN16nsServiceManager10GetServiceEPKcRK4nsIDPP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager10GetServiceERK4nsIDS2_PP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager14ReleaseServiceEPKcP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager14ReleaseServiceERK4nsIDP11nsISupportsP19nsIShutdownListener
+ _ZN16nsServiceManager15RegisterServiceEPKcP11nsISupports
+ _ZN16nsServiceManager15RegisterServiceERK4nsIDP11nsISupports
+ _ZN16nsServiceManager17UnregisterServiceEPKc
+ _ZN16nsServiceManager17UnregisterServiceERK4nsID
+ _ZN16nsServiceManager23GetGlobalServiceManagerEPP17nsIServiceManager
+ _ZN16nsServiceManager28ShutdownGlobalServiceManagerEPP17nsIServiceManager
+ _ZN16nsSmallVoidArray13AppendElementEPv
+ _ZN16nsSmallVoidArray13RemoveElementEPv
+ _ZN16nsSmallVoidArray14SetSingleChildEPv
+ _ZN16nsSmallVoidArray14SwitchToVectorEv
+ _ZN16nsSmallVoidArray15InsertElementAtEPvi
+ _ZN16nsSmallVoidArray15RemoveElementAtEi
+ _ZN16nsSmallVoidArray16InsertElementsAtERK11nsVoidArrayi
+ _ZN16nsSmallVoidArray16RemoveElementsAtEii
+ _ZN16nsSmallVoidArray16ReplaceElementAtEPvi
+ _ZN16nsSmallVoidArray17EnumerateForwardsEPFiPvS0_ES0_
+ _ZN16nsSmallVoidArray18EnumerateBackwardsEPFiPvS0_ES0_
+ _ZN16nsSmallVoidArray4SortEPFiPKvS1_PvES2_
+ _ZN16nsSmallVoidArray5ClearEv
+ _ZN16nsSmallVoidArray6SizeToEi
+ _ZN16nsSmallVoidArray7CompactEv
+ _ZN16nsSmallVoidArrayC1Ev
+ _ZN16nsSmallVoidArrayC2Ev
+ _ZN16nsSmallVoidArrayD1Ev
+ _ZN16nsSmallVoidArrayD2Ev
+ _ZN16nsSmallVoidArrayaSERS_
+ _ZN17nsArrayEnumeratorC1EP16nsISupportsArray
+ _ZN17nsArrayEnumeratorC2EP16nsISupportsArray
+ _ZN17nsArrayEnumeratorD1Ev
+ _ZN17nsArrayEnumeratorD2Ev
+ _ZN17nsObjectHashtable11CopyElementEP12PLDHashTableP15PLDHashEntryHdrjPv
+ _ZN17nsObjectHashtable15RemoveAndDeleteEP9nsHashKey
+ _ZN17nsObjectHashtable5CloneEv
+ _ZN17nsObjectHashtable5ResetEv
+ _ZN17nsObjectHashtableC1EPFPvP9nsHashKeyS0_S0_ES0_PFiS2_S0_S0_ES0_ji
+ _ZN17nsObjectHashtableC2EPFPvP9nsHashKeyS0_S0_ES0_PFiS2_S0_S0_ES0_ji
+ _ZN17nsObjectHashtableD0Ev
+ _ZN17nsObjectHashtableD1Ev
+ _ZN17nsObjectHashtableD2Ev
+ _ZN17nsSegmentedBuffer16AppendNewSegmentEv
+ _ZN17nsSegmentedBuffer4InitEjjP9nsIMemory
+ _ZN17nsSegmentedBuffer5EmptyEv
+ _ZN17nsTraceRefcntImpl12WalkTheStackEP7__sFILE
+ _ZN17nsTraceRefcntImpl14DemangleSymbolEPKcPci
+ _ZN17nsTraceRefcntImpl14DumpStatisticsENS_14StatisticsTypeEP7__sFILE
+ _ZN17nsTraceRefcntImpl15ResetStatisticsEv
+ _ZN17nsTraceRefcntImpl18LoadLibrarySymbolsEPKcPv
+ _ZN17nsTraceRefcntImpl18SetActivityIsLegalEi
+ _ZN17nsTraceRefcntImpl7StartupEv
+ _ZN17nsTraceRefcntImpl8ShutdownEv
+ _ZN17nsUnionEnumeratorC1EP19nsISimpleEnumeratorS1_
+ _ZN17nsUnionEnumeratorC2EP19nsISimpleEnumeratorS1_
+ _ZN17nsUnionEnumeratorD1Ev
+ _ZN17nsUnionEnumeratorD2Ev
+ _ZN18nsComponentManager10InitializeEv
+ _ZN18nsComponentManager11FindFactoryERK4nsIDPP10nsIFactory
+ _ZN18nsComponentManager12AutoRegisterEiP7nsIFile
+ _ZN18nsComponentManager12IsRegisteredERK4nsIDPi
+ _ZN18nsComponentManager13FreeLibrariesEv
+ _ZN18nsComponentManager14CreateInstanceEPKcP11nsISupportsRK4nsIDPPv
+ _ZN18nsComponentManager14CreateInstanceERK4nsIDP11nsISupportsS2_PPv
+ _ZN18nsComponentManager14GetClassObjectERK4nsIDS2_PPv
+ _ZN18nsComponentManager15EnumerateCLSIDsEPP13nsIEnumerator
+ _ZN18nsComponentManager15RegisterFactoryERK4nsIDPKcS4_P10nsIFactoryi
+ _ZN18nsComponentManager17CLSIDToContractIDEP4nsIDPPcS3_
+ _ZN18nsComponentManager17RegisterComponentERK4nsIDPKcS4_S4_ii
+ _ZN18nsComponentManager17UnregisterFactoryERK4nsIDP10nsIFactory
+ _ZN18nsComponentManager19ContractIDToClassIDEPKcP4nsID
+ _ZN18nsComponentManager19UnregisterComponentERK4nsIDPKc
+ _ZN18nsComponentManager20EnumerateContractIDsEPP13nsIEnumerator
+ _ZN18nsComponentManager20RegisterComponentLibERK4nsIDPKcS4_S4_ii
+ _ZN18nsComponentManager21AutoRegisterComponentEiP7nsIFile
+ _ZN18nsComponentManager21RegisterComponentSpecERK4nsIDPKcS4_P7nsIFileii
+ _ZN18nsComponentManager23AutoUnregisterComponentEiP7nsIFile
+ _ZN18nsComponentManager23UnregisterComponentSpecERK4nsIDP7nsIFile
+ _ZN18nsVoidHashSetSuper4InitEj
+ _ZN18nsVoidHashSetSuper6RemoveEPKv
+ _ZN18nsVoidHashSetSuper8AddEntryEPKv
+ _ZN18nsVoidHashSetSuper8GetEntryEPKv
+ _ZN18nsVoidHashSetSuperC1Ev
+ _ZN18nsVoidHashSetSuperC2Ev
+ _ZN18nsVoidHashSetSuperD1Ev
+ _ZN18nsVoidHashSetSuperD2Ev
+ _ZN19nsDirEnumeratorUnixC1Ev
+ _ZN19nsDirEnumeratorUnixC2Ev
+ _ZN19nsDirEnumeratorUnixD1Ev
+ _ZN19nsDirEnumeratorUnixD2Ev
+ _ZN19nsInt32HashSetSuper4InitEj
+ _ZN19nsInt32HashSetSuper6RemoveEi
+ _ZN19nsInt32HashSetSuper8AddEntryEi
+ _ZN19nsInt32HashSetSuper8GetEntryEi
+ _ZN19nsInt32HashSetSuperC1Ev
+ _ZN19nsInt32HashSetSuperC2Ev
+ _ZN19nsInt32HashSetSuperD1Ev
+ _ZN19nsInt32HashSetSuperD2Ev
+ _ZN19nsPromiseFlatString4InitERK11nsSubstring
+ _ZN19nsPromiseFlatString4InitERK9nsAString
+ _ZN19nsSupportsHashtable13EnumerateCopyEP12PLDHashTableP15PLDHashEntryHdrjPv
+ _ZN19nsSupportsHashtable14ReleaseElementEP9nsHashKeyPvS2_
+ _ZN19nsSupportsHashtable3GetEP9nsHashKey
+ _ZN19nsSupportsHashtable3PutEP9nsHashKeyP11nsISupportsPS3_
+ _ZN19nsSupportsHashtable5CloneEv
+ _ZN19nsSupportsHashtable5ResetEv
+ _ZN19nsSupportsHashtable6RemoveEP9nsHashKeyPP11nsISupports
+ _ZN19nsSupportsHashtableD0Ev
+ _ZN19nsSupportsHashtableD1Ev
+ _ZN19nsSupportsHashtableD2Ev
+ _ZN20nsDependentSubstring6RebindERK11nsSubstringjj
+ _ZN20nsDependentSubstring6RebindERK9nsAStringjj
+ _ZN20nsPromiseFlatCString4InitERK10nsACString
+ _ZN20nsPromiseFlatCString4InitERK12nsCSubstring
+ _ZN20nsRecyclingAllocator13AddToFreeListEPNS_5BlockE
+ _ZN20nsRecyclingAllocator13FindFreeBlockEm
+ _ZN20nsRecyclingAllocator17FreeUnusedBucketsEv
+ _ZN20nsRecyclingAllocator22nsRecycleTimerCallbackEP8nsITimerPv
+ _ZN20nsRecyclingAllocator4FreeEPv
+ _ZN20nsRecyclingAllocator4InitEjjPKc
+ _ZN20nsRecyclingAllocator6MallocEmi
+ _ZN20nsRecyclingAllocatorC1EjjPKc
+ _ZN20nsRecyclingAllocatorC2EjjPKc
+ _ZN20nsRecyclingAllocatorD1Ev
+ _ZN20nsRecyclingAllocatorD2Ev
+ _ZN20nsStringHashSetSuper4InitEj
+ _ZN20nsStringHashSetSuper6RemoveERK9nsAString
+ _ZN20nsStringHashSetSuper8AddEntryERK9nsAString
+ _ZN20nsStringHashSetSuper8GetEntryERK9nsAString
+ _ZN20nsStringHashSetSuperC1Ev
+ _ZN20nsStringHashSetSuperC2Ev
+ _ZN20nsStringHashSetSuperD1Ev
+ _ZN20nsStringHashSetSuperD2Ev
+ _ZN21nsCStringHashSetSuper4InitEj
+ _ZN21nsCStringHashSetSuper6RemoveERK10nsACString
+ _ZN21nsCStringHashSetSuper8AddEntryERK10nsACString
+ _ZN21nsCStringHashSetSuper8GetEntryERK10nsACString
+ _ZN21nsCStringHashSetSuperC1Ev
+ _ZN21nsCStringHashSetSuperC2Ev
+ _ZN21nsCStringHashSetSuperD1Ev
+ _ZN21nsCStringHashSetSuperD2Ev
+ _ZN21nsDependentCSubstring6RebindERK10nsACStringjj
+ _ZN21nsDependentCSubstring6RebindERK12nsCSubstringjj
+ _ZN21nsSingletonEnumeratorC1EP11nsISupports
+ _ZN21nsSingletonEnumeratorC2EP11nsISupports
+ _ZN21nsSingletonEnumeratorD1Ev
+ _ZN21nsSingletonEnumeratorD2Ev
+ _ZN23nsSupportsWeakReference16GetWeakReferenceEPP16nsIWeakReference
+ _ZN4nsID5ParseEPKc
+ _ZN5nsCRT12IsAsciiAlphaEt
+ _ZN5nsCRT12IsAsciiDigitEt
+ _ZN5nsCRT12IsAsciiSpaceEt
+ _ZN5nsCRT14BufferHashCodeEPKcj
+ _ZN5nsCRT14BufferHashCodeEPKtj
+ _ZN5nsCRT14HashCodeAsUTF8EPKtPj
+ _ZN5nsCRT5atollEPKc
+ _ZN5nsCRT6strcmpEPKtS1_
+ _ZN5nsCRT6strdupEPKt
+ _ZN5nsCRT6strlenEPKt
+ _ZN5nsCRT6strtokEPcPKcPS0_
+ _ZN5nsCRT7IsAsciiEPKc
+ _ZN5nsCRT7IsAsciiEPKcj
+ _ZN5nsCRT7IsAsciiEPKt
+ _ZN5nsCRT7IsAsciiEt
+ _ZN5nsCRT7IsLowerEc
+ _ZN5nsCRT7IsUpperEc
+ _ZN5nsCRT7ToLowerEc
+ _ZN5nsCRT7ToUpperEc
+ _ZN5nsCRT7strncmpEPKtS1_j
+ _ZN5nsCRT7strndupEPKtj
+ _ZN5nsCRT8HashCodeEPKcPj
+ _ZN5nsCRT8HashCodeEPKtPj
+ _ZN7nsDebug5AbortEPKci
+ _ZN7nsDebug5BreakEPKci
+ _ZN7nsDebug7WarningEPKcS1_i
+ _ZN7nsDebug9AssertionEPKcS1_S1_i
+ _ZN7nsDeque12GrowCapacityEv
+ _ZN7nsDeque14SetDeallocatorEP14nsDequeFunctor
+ _ZN7nsDeque3PopEv
+ _ZN7nsDeque4PeekEv
+ _ZN7nsDeque4PushEPv
+ _ZN7nsDeque5EmptyEv
+ _ZN7nsDeque5EraseEv
+ _ZN7nsDeque8PopFrontEv
+ _ZN7nsDeque9PeekFrontEv
+ _ZN7nsDeque9PushFrontEPv
+ _ZN7nsDequeC1EP14nsDequeFunctor
+ _ZN7nsDequeC2EP14nsDequeFunctor
+ _ZN7nsDequeD1Ev
+ _ZN7nsDequeD2Ev
+ _ZN7nsIDKeyC1EP20nsIObjectInputStreamPj
+ _ZN7nsIDKeyC2EP20nsIObjectInputStreamPj
+ _ZN8nsMemory12HeapMinimizeEi
+ _ZN8nsMemory22GetGlobalMemoryServiceEv
+ _ZN8nsMemory4FreeEPv
+ _ZN8nsMemory5AllocEm
+ _ZN8nsMemory5CloneEPKvm
+ _ZN8nsMemory7ReallocEPvm
+ _ZN8nsString10StripCharsEPKc
+ _ZN8nsString11AppendFloatEd
+ _ZN8nsString11ReplaceCharEPKct
+ _ZN8nsString11ReplaceCharEtt
+ _ZN8nsString15StripWhitespaceEv
+ _ZN8nsString16ReplaceSubstringEPKtS1_
+ _ZN8nsString16ReplaceSubstringERKS_S1_
+ _ZN8nsString18CompressWhitespaceEii
+ _ZN8nsString20AppendWithConversionEPKci
+ _ZN8nsString20AppendWithConversionERK10nsACString
+ _ZN8nsString20AssignWithConversionEPKci
+ _ZN8nsString20AssignWithConversionERK10nsACString
+ _ZN8nsString4TrimEPKciii
+ _ZN8nsString9AppendIntEii
+ _ZN8nsString9AppendIntEli
+ _ZN8nsString9SetCharAtEtj
+ _ZN8nsString9StripCharEti
+ _ZN9nsAString11AppendASCIIEPKc
+ _ZN9nsAString11AppendASCIIEPKcj
+ _ZN9nsAString11AssignASCIIEPKc
+ _ZN9nsAString11AssignASCIIEPKcj
+ _ZN9nsAString11SetCapacityEj
+ _ZN9nsAString17GetWritableBufferEPPt
+ _ZN9nsAString3CutEjj
+ _ZN9nsAString6AppendEPKt
+ _ZN9nsAString6AppendEPKtj
+ _ZN9nsAString6AppendERK16nsSubstringTuple
+ _ZN9nsAString6AppendERKS_
+ _ZN9nsAString6AppendEt
+ _ZN9nsAString6AssignEPKt
+ _ZN9nsAString6AssignEPKtj
+ _ZN9nsAString6AssignERK16nsSubstringTuple
+ _ZN9nsAString6AssignERKS_
+ _ZN9nsAString6AssignEt
+ _ZN9nsAString6InsertEPKtj
+ _ZN9nsAString6InsertEPKtjj
+ _ZN9nsAString6InsertERK16nsSubstringTuplej
+ _ZN9nsAString6InsertERKS_j
+ _ZN9nsAString6InsertEtj
+ _ZN9nsAString7ReplaceEjjRK16nsSubstringTuple
+ _ZN9nsAString7ReplaceEjjRKS_
+ _ZN9nsAString9SetIsVoidEi
+ _ZN9nsAString9SetLengthEj
+ _ZN9nsAStringD1Ev
+ _ZN9nsAStringD2Ev
+ _ZN9nsCString10StripCharsEPKc
+ _ZN9nsCString11AppendFloatEd
+ _ZN9nsCString11ReplaceCharEPKcc
+ _ZN9nsCString11ReplaceCharEcc
+ _ZN9nsCString15StripWhitespaceEv
+ _ZN9nsCString16ReplaceSubstringEPKcS1_
+ _ZN9nsCString16ReplaceSubstringERKS_S1_
+ _ZN9nsCString18CompressWhitespaceEii
+ _ZN9nsCString20AppendWithConversionEPKti
+ _ZN9nsCString20AppendWithConversionERK9nsAString
+ _ZN9nsCString20AssignWithConversionEPKti
+ _ZN9nsCString20AssignWithConversionERK9nsAString
+ _ZN9nsCString4TrimEPKciii
+ _ZN9nsCString9AppendIntEii
+ _ZN9nsCString9AppendIntEli
+ _ZN9nsCString9SetCharAtEtj
+ _ZN9nsCString9StripCharEci
+ _ZN9nsHashKeyD0Ev
+ _ZN9nsHashKeyD1Ev
+ _ZN9nsHashKeyD2Ev
+ _ZN9nsIThread10GetCurrentEPPS_
+ _ZN9nsIThread10GetIThreadEP8PRThreadPPS_
+ _ZN9nsIThread12IsMainThreadEv
+ _ZN9nsIThread13GetMainThreadEPPS_
+ _ZN9nsIThread13SetMainThreadEv
+ _ZN9nsVariant10InitializeEP20nsDiscriminatedUnion
+ _ZN9nsVariant10SetToEmptyEP20nsDiscriminatedUnion
+ _ZN9nsVariant11ConvertToIDERK20nsDiscriminatedUnionP4nsID
+ _ZN9nsVariant11SetFromBoolEP20nsDiscriminatedUnioni
+ _ZN9nsVariant11SetFromCharEP20nsDiscriminatedUnionc
+ _ZN9nsVariant11SetFromInt8EP20nsDiscriminatedUnionh
+ _ZN9nsVariant12SetFromArrayEP20nsDiscriminatedUniontPK4nsIDjPv
+ _ZN9nsVariant12SetFromFloatEP20nsDiscriminatedUnionf
+ _ZN9nsVariant12SetFromInt16EP20nsDiscriminatedUnions
+ _ZN9nsVariant12SetFromInt32EP20nsDiscriminatedUnioni
+ _ZN9nsVariant12SetFromInt64EP20nsDiscriminatedUnionl
+ _ZN9nsVariant12SetFromUint8EP20nsDiscriminatedUnionh
+ _ZN9nsVariant12SetFromWCharEP20nsDiscriminatedUniont
+ _ZN9nsVariant13ConvertToBoolERK20nsDiscriminatedUnionPi
+ _ZN9nsVariant13ConvertToCharERK20nsDiscriminatedUnionPc
+ _ZN9nsVariant13ConvertToInt8ERK20nsDiscriminatedUnionPh
+ _ZN9nsVariant13SetFromDoubleEP20nsDiscriminatedUniond
+ _ZN9nsVariant13SetFromStringEP20nsDiscriminatedUnionPKc
+ _ZN9nsVariant13SetFromUint16EP20nsDiscriminatedUniont
+ _ZN9nsVariant13SetFromUint32EP20nsDiscriminatedUnionj
+ _ZN9nsVariant13SetFromUint64EP20nsDiscriminatedUnionm
+ _ZN9nsVariant14ConvertToArrayERK20nsDiscriminatedUnionPtP4nsIDPjPPv
+ _ZN9nsVariant14ConvertToFloatERK20nsDiscriminatedUnionPf
+ _ZN9nsVariant14ConvertToInt16ERK20nsDiscriminatedUnionPs
+ _ZN9nsVariant14ConvertToInt32ERK20nsDiscriminatedUnionPi
+ _ZN9nsVariant14ConvertToInt64ERK20nsDiscriminatedUnionPl
+ _ZN9nsVariant14ConvertToUint8ERK20nsDiscriminatedUnionPh
+ _ZN9nsVariant14ConvertToWCharERK20nsDiscriminatedUnionPt
+ _ZN9nsVariant14SetFromAStringEP20nsDiscriminatedUnionRK9nsAString
+ _ZN9nsVariant14SetFromVariantEP20nsDiscriminatedUnionP10nsIVariant
+ _ZN9nsVariant14SetFromWStringEP20nsDiscriminatedUnionPKt
+ _ZN9nsVariant15ConvertToDoubleERK20nsDiscriminatedUnionPd
+ _ZN9nsVariant15ConvertToStringERK20nsDiscriminatedUnionPPc
+ _ZN9nsVariant15ConvertToUint16ERK20nsDiscriminatedUnionPt
+ _ZN9nsVariant15ConvertToUint32ERK20nsDiscriminatedUnionPj
+ _ZN9nsVariant15ConvertToUint64ERK20nsDiscriminatedUnionPm
+ _ZN9nsVariant15SetFromACStringEP20nsDiscriminatedUnionRK10nsACString
+ _ZN9nsVariant15SetToEmptyArrayEP20nsDiscriminatedUnion
+ _ZN9nsVariant16ConvertToAStringERK20nsDiscriminatedUnionR9nsAString
+ _ZN9nsVariant16ConvertToWStringERK20nsDiscriminatedUnionPPt
+ _ZN9nsVariant16SetFromISupportsEP20nsDiscriminatedUnionP11nsISupports
+ _ZN9nsVariant16SetFromInterfaceEP20nsDiscriminatedUnionRK4nsIDP11nsISupports
+ _ZN9nsVariant17ConvertToACStringERK20nsDiscriminatedUnionR10nsACString
+ _ZN9nsVariant18ConvertToISupportsERK20nsDiscriminatedUnionPP11nsISupports
+ _ZN9nsVariant18ConvertToInterfaceERK20nsDiscriminatedUnionPP4nsIDPPv
+ _ZN9nsVariant18SetFromAUTF8StringEP20nsDiscriminatedUnionRK10nsACString
+ _ZN9nsVariant20ConvertToAUTF8StringERK20nsDiscriminatedUnionR10nsACString
+ _ZN9nsVariant21SetFromStringWithSizeEP20nsDiscriminatedUnionjPKc
+ _ZN9nsVariant22SetFromWStringWithSizeEP20nsDiscriminatedUnionjPKt
+ _ZN9nsVariant23ConvertToStringWithSizeERK20nsDiscriminatedUnionPjPPc
+ _ZN9nsVariant24ConvertToWStringWithSizeERK20nsDiscriminatedUnionPjPPt
+ _ZN9nsVariant7CleanupEP20nsDiscriminatedUnion
+ _ZN9nsVariant9SetFromIDEP20nsDiscriminatedUnionRK4nsID
+ _ZN9nsVariant9SetToVoidEP20nsDiscriminatedUnion
+ _ZN9nsVariantC1Ev
+ _ZN9nsVariantC2Ev
+ _ZN9nsVariantD1Ev
+ _ZN9nsVariantD2Ev
+ _ZNK10nsACString11EqualsASCIIEPKc
+ _ZNK10nsACString11EqualsASCIIEPKcj
+ _ZNK10nsACString12IsTerminatedEv
+ _ZNK10nsACString17GetReadableBufferEPPKc
+ _ZNK10nsACString20LowerCaseEqualsASCIIEPKc
+ _ZNK10nsACString20LowerCaseEqualsASCIIEPKcj
+ _ZNK10nsACString4LastEv
+ _ZNK10nsACString5FirstEv
+ _ZNK10nsACString6EqualsEPKc
+ _ZNK10nsACString6EqualsEPKcRK19nsCStringComparator
+ _ZNK10nsACString6EqualsERKS_
+ _ZNK10nsACString6EqualsERKS_RK19nsCStringComparator
+ _ZNK10nsACString6IsVoidEv
+ _ZNK10nsACString6LengthEv
+ _ZNK10nsACString8FindCharEcj
+ _ZNK10nsACString9CountCharEc
+ _ZNK11nsHashtable5WriteEP21nsIObjectOutputStreamPFjS1_PvE
+ _ZNK11nsStringKey5CloneEv
+ _ZNK11nsStringKey5WriteEP21nsIObjectOutputStream
+ _ZNK11nsStringKey6EqualsEPK9nsHashKey
+ _ZNK11nsStringKey8HashCodeEv
+ _ZNK11nsSubstring11EqualsASCIIEPKc
+ _ZNK11nsSubstring11EqualsASCIIEPKcj
+ _ZNK11nsSubstring20LowerCaseEqualsASCIIEPKc
+ _ZNK11nsSubstring20LowerCaseEqualsASCIIEPKcj
+ _ZNK11nsSubstring6EqualsEPKt
+ _ZNK11nsSubstring6EqualsEPKtRK18nsStringComparator
+ _ZNK11nsSubstring6EqualsERK9nsAString
+ _ZNK11nsSubstring6EqualsERK9nsAStringRK18nsStringComparator
+ _ZNK11nsSubstring6EqualsERKS_
+ _ZNK11nsSubstring6EqualsERKS_RK18nsStringComparator
+ _ZNK11nsSubstring8FindCharEtj
+ _ZNK11nsSubstring9CountCharEt
+ _ZNK11nsVoidArray7IndexOfEPv
+ _ZNK12nsCStringKey5CloneEv
+ _ZNK12nsCStringKey5WriteEP21nsIObjectOutputStream
+ _ZNK12nsCStringKey6EqualsEPK9nsHashKey
+ _ZNK12nsCStringKey8HashCodeEv
+ _ZNK12nsCSubstring11EqualsASCIIEPKc
+ _ZNK12nsCSubstring11EqualsASCIIEPKcj
+ _ZNK12nsCSubstring20LowerCaseEqualsASCIIEPKc
+ _ZNK12nsCSubstring20LowerCaseEqualsASCIIEPKcj
+ _ZNK12nsCSubstring6EqualsEPKc
+ _ZNK12nsCSubstring6EqualsEPKcRK19nsCStringComparator
+ _ZNK12nsCSubstring6EqualsERK10nsACString
+ _ZNK12nsCSubstring6EqualsERK10nsACStringRK19nsCStringComparator
+ _ZNK12nsCSubstring6EqualsERKS_
+ _ZNK12nsCSubstring6EqualsERKS_RK19nsCStringComparator
+ _ZNK12nsCSubstring8FindCharEcj
+ _ZNK12nsCSubstring9CountCharEc
+ _ZNK13nsStringArray7IndexOfERK9nsAString
+ _ZNK13nsStringArray8StringAtEi
+ _ZNK13nsStringArray8StringAtEiR9nsAString
+ _ZNK14nsCStringArray17IndexOfIgnoreCaseERK10nsACString
+ _ZNK14nsCStringArray7IndexOfERK10nsACString
+ _ZNK14nsCStringArray9CStringAtEi
+ _ZNK14nsCStringArray9CStringAtEiR10nsACString
+ _ZNK14nsGetInterfaceclERK4nsIDPPv
+ _ZNK14nsISupportsKey5WriteEP21nsIObjectOutputStream
+ _ZNK15nsCOMArray_base13IndexOfObjectEP11nsISupports
+ _ZNK15nsQueryReferentclERK4nsIDPPv
+ _ZNK16nsQueryElementAtclERK4nsIDPPv
+ _ZNK16nsQueryInterfaceclERK4nsIDPPv
+ _ZNK16nsSmallVoidArray12GetArraySizeEv
+ _ZNK16nsSmallVoidArray5CountEv
+ _ZNK16nsSmallVoidArray7IndexOfEPv
+ _ZNK16nsSmallVoidArray9ElementAtEi
+ _ZNK16nsSubstringTuple13IsDependentOnEPKtS1_
+ _ZNK16nsSubstringTuple6LengthEv
+ _ZNK16nsSubstringTuple7WriteToEPtj
+ _ZNK17nsCSubstringTuple13IsDependentOnEPKcS1_
+ _ZNK17nsCSubstringTuple6LengthEv
+ _ZNK17nsCSubstringTuple7WriteToEPcj
+ _ZNK17nsGetServiceByCIDclERK4nsIDPPv
+ _ZNK18nsGetWeakReferenceclERK4nsIDPPv
+ _ZNK21nsCreateInstanceByCIDclERK4nsIDPPv
+ _ZNK21nsQueryArrayElementAtclERK4nsIDPPv
+ _ZNK24nsGetServiceByContractIDclERK4nsIDPPv
+ _ZNK25nsDefaultStringComparatorclEPKtS1_j
+ _ZNK25nsDefaultStringComparatorclEtt
+ _ZNK25nsQueryInterfaceWithErrorclERK4nsIDPPv
+ _ZNK26nsDefaultCStringComparatorclEPKcS1_j
+ _ZNK26nsDefaultCStringComparatorclEcc
+ _ZNK28nsCreateInstanceByContractIDclERK4nsIDPPv
+ _ZNK28nsCreateInstanceFromCategoryclERK4nsIDPPv
+ _ZNK34nsCaseInsensitiveCStringComparatorclEPKcS1_j
+ _ZNK34nsCaseInsensitiveCStringComparatorclEcc
+ _ZNK4nsID16ToProvidedStringERA39_c
+ _ZNK4nsID8ToStringEv
+ _ZNK7nsDeque3EndEv
+ _ZNK7nsDeque4LastEv
+ _ZNK7nsDeque5BeginEv
+ _ZNK7nsDeque7ForEachER14nsDequeFunctor
+ _ZNK7nsDeque8ObjectAtEi
+ _ZNK7nsDeque9FirstThatER14nsDequeFunctor
+ _ZNK7nsIDKey5WriteEP21nsIObjectOutputStream
+ _ZNK8nsString13FindCharInSetEPKci
+ _ZNK8nsString13FindCharInSetEPKti
+ _ZNK8nsString14RFindCharInSetEPKti
+ _ZNK8nsString16EqualsIgnoreCaseEPKci
+ _ZNK8nsString3MidERS_jj
+ _ZNK8nsString4FindEPKciii
+ _ZNK8nsString4FindEPKtii
+ _ZNK8nsString4FindERK9nsCStringiii
+ _ZNK8nsString4FindERKS_ii
+ _ZNK8nsString5RFindEPKciii
+ _ZNK8nsString5RFindEPKtii
+ _ZNK8nsString5RFindERK9nsCStringiii
+ _ZNK8nsString5RFindERKS_ii
+ _ZNK8nsString7ToFloatEPi
+ _ZNK8nsString9RFindCharEtii
+ _ZNK8nsString9ToCStringEPcjj
+ _ZNK8nsString9ToIntegerEPij
+ _ZNK9nsAString11EqualsASCIIEPKc
+ _ZNK9nsAString11EqualsASCIIEPKcj
+ _ZNK9nsAString12IsTerminatedEv
+ _ZNK9nsAString17GetReadableBufferEPPKt
+ _ZNK9nsAString20LowerCaseEqualsASCIIEPKc
+ _ZNK9nsAString20LowerCaseEqualsASCIIEPKcj
+ _ZNK9nsAString4LastEv
+ _ZNK9nsAString5FirstEv
+ _ZNK9nsAString6EqualsEPKt
+ _ZNK9nsAString6EqualsEPKtRK18nsStringComparator
+ _ZNK9nsAString6EqualsERKS_
+ _ZNK9nsAString6EqualsERKS_RK18nsStringComparator
+ _ZNK9nsAString6IsVoidEv
+ _ZNK9nsAString6LengthEv
+ _ZNK9nsAString8FindCharEtj
+ _ZNK9nsAString9CountCharEt
+ _ZNK9nsCString13FindCharInSetEPKci
+ _ZNK9nsCString14RFindCharInSetEPKci
+ _ZNK9nsCString3MidERS_jj
+ _ZNK9nsCString4FindEPKciii
+ _ZNK9nsCString4FindERKS_iii
+ _ZNK9nsCString5RFindEPKciii
+ _ZNK9nsCString5RFindERKS_iii
+ _ZNK9nsCString7CompareEPKcii
+ _ZNK9nsCString7ToFloatEPi
+ _ZNK9nsCString9RFindCharEtii
+ _ZNK9nsCString9ToIntegerEPij
+ _ZNK9nsHashKey5WriteEP21nsIObjectOutputStream
diff --git a/src/libs/xpcom18a4/dependentLibs.h b/src/libs/xpcom18a4/dependentLibs.h
new file mode 100644
index 00000000..fa00ec80
--- /dev/null
+++ b/src/libs/xpcom18a4/dependentLibs.h
@@ -0,0 +1,2 @@
+#error "This is linux specific and it works elsewhere, so it cannot be required, can it? VBoxXPCOMIPCC was the only one which used this file."
+#define DEPENDENT_LIBS "VBoxXPCOM.so", "libpthread.so", "libdl.so",
diff --git a/src/libs/xpcom18a4/ipc/Makefile.kup b/src/libs/xpcom18a4/ipc/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/Makefile.in
new file mode 100644
index 00000000..d5f24007
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/Makefile.in
@@ -0,0 +1,64 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+
+PACKAGE_FILE = ipc.pkg
+
+DIRS = \
+ util \
+ shared/src \
+ daemon/public \
+ client/public \
+ extensions \
+ client/src \
+ daemon/src \
+ $(NULL)
+
+ifdef ENABLE_TESTS
+DIRS += test
+endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/Makefile.kup b/src/libs/xpcom18a4/ipc/ipcd/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/Makefile.kup b/src/libs/xpcom18a4/ipc/ipcd/client/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/client/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/client/public/Makefile.in
new file mode 100644
index 00000000..896e68b8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/Makefile.in
@@ -0,0 +1,59 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+
+EXPORTS = \
+ ipcdclient.h \
+ ipcCID.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ ipcIService.idl \
+ ipcIMessageObserver.idl \
+ ipcIClientObserver.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcCID.h b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcCID.h
new file mode 100644
index 00000000..4863ff0d
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcCID.h
@@ -0,0 +1,53 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcCID_h__
+#define ipcCID_h__
+
+#define IPC_SERVICE_CLASSNAME \
+ "ipcService"
+#define IPC_SERVICE_CONTRACTID \
+ "@mozilla.org/ipc/service;1"
+#define IPC_SERVICE_CID \
+{ /* 9f12676a-5168-4a08-beb8-edf8a593a1ca */ \
+ 0x9f12676a, \
+ 0x5168, \
+ 0x4a08, \
+ {0xbe, 0xb8, 0xed, 0xf8, 0xa5, 0x93, 0xa1, 0xca} \
+}
+
+#endif // !ipcCID_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIClientObserver.idl b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIClientObserver.idl
new file mode 100644
index 00000000..c72d0909
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIClientObserver.idl
@@ -0,0 +1,51 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsISupports.idl"
+
+/**
+ * ipcIClientObserver
+ */
+[scriptable, uuid(42283079-030c-4b13-b069-a08b7ad5eab2)]
+interface ipcIClientObserver : nsISupports
+{
+ const unsigned long CLIENT_UP = 1;
+ const unsigned long CLIENT_DOWN = 2;
+
+ void onClientStateChange(in unsigned long aClientID,
+ in unsigned long aClientState);
+};
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIMessageObserver.idl b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIMessageObserver.idl
new file mode 100644
index 00000000..db24b1f2
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIMessageObserver.idl
@@ -0,0 +1,64 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsISupports.idl"
+
+/**
+ * ipcIMessageObserver
+ */
+[scriptable, uuid(e40a4a3c-2dc1-470e-ab7f-5675fe1f1384)]
+interface ipcIMessageObserver : nsISupports
+{
+ /**
+ * @param aSenderID
+ * the client id of the sender of this message. if sent by the
+ * daemon (or a deamon module), then this will have a value of 0.
+ * @param aTarget
+ * the target of the message, corresponding to the target this
+ * observer was registered under. this parameter is passed to allow
+ * an observer instance to receive messages for more than one target.
+ * @param aData
+ * the data of the message.
+ * @param aDataLen
+ * the data length of the message.
+ */
+ void onMessageAvailable(in unsigned long aSenderID,
+ in nsIDRef aTarget,
+ [array, const, size_is(aDataLen)]
+ in octet aData,
+ in unsigned long aDataLen);
+};
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIService.idl b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIService.idl
new file mode 100644
index 00000000..671b557d
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcIService.idl
@@ -0,0 +1,228 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsISupports.idl"
+
+interface ipcIMessageObserver;
+interface ipcIClientObserver;
+
+/**
+ * ipcIService
+ *
+ * the IPC service provides the means to communicate with an external IPC
+ * daemon and/or other mozilla-based applications on the same physical system.
+ * the IPC daemon hosts modules (some builtin and others dynamically loaded)
+ * with which applications may interact.
+ *
+ * at application startup, the IPC service will attempt to establish a
+ * connection with the IPC daemon. the IPC daemon will be automatically
+ * started if necessary. when a connection has been established, the IPC
+ * service will enumerate the "ipc-startup-category" and broadcast an
+ * "ipc-startup" notification using the observer service.
+ *
+ * when the connection to the IPC daemon is closed, an "ipc-shutdown"
+ * notification will be broadcast.
+ *
+ * each client has a name. the client name need not be unique across all
+ * clients, but it is usually good if it is. the IPC service does not require
+ * unique names. instead, the IPC daemon assigns each client a unique ID that
+ * is good for the current "session." clients can query other clients by name
+ * or by ID. the IPC service supports forwarding messages from one client to
+ * another via the IPC daemon.
+ *
+ * for performance reasons, this system should not be used to transfer large
+ * amounts of data. instead, applications may choose to utilize shared memory,
+ * and rely on the IPC service for synchronization and small message transfer
+ * only.
+ */
+[scriptable, uuid(53d3e3a7-528f-4b09-9eab-9416272568c0)]
+interface ipcIService : nsISupports
+{
+ /**************************************************************************
+ * properties of this process
+ */
+
+ /**
+ * returns the "client ID" assigned to this process by the IPC daemon.
+ *
+ * @throws NS_ERROR_NOT_AVAILABLE if no connection to the IPC daemon.
+ */
+ readonly attribute unsigned long ID;
+
+ /**
+ * this process can appear under several client names. use the following
+ * methods to add or remove names for this process.
+ *
+ * for example, the mozilla browser might have the primary name "mozilla",
+ * but it could also register itself under the names "browser", "mail",
+ * "news", "addrbook", etc. other IPC clients can then query the IPC
+ * daemon for the client named "mail" in order to talk with a mail program.
+ *
+ * XXX An IPC client name resembles a XPCOM contract ID.
+ */
+ void addName(in string aName);
+ void removeName(in string aName);
+
+ /**
+ * add a new observer of client status change notifications.
+ */
+ void addClientObserver(in ipcIClientObserver aObserver);
+
+ /**
+ * remove an observer of client status change notifications.
+ */
+ void removeClientObserver(in ipcIClientObserver aObserver);
+
+ /**************************************************************************
+ * client query methods
+ */
+
+ /**
+ * resolve the given client name to the id of a connected client. this
+ * involves a round trip to the daemon, and as a result the calling thread
+ * may block on this function call while waiting for the daemon to respond.
+ */
+ unsigned long resolveClientName(in string aName);
+
+
+ /**
+ * tests whether a particular client is connected to the IPC daemon.
+ */
+ boolean clientExists(in unsigned long aClientID);
+
+
+ // XXX need other functions to enumerate clients, clients implementing targets, etc.
+ // enumerator getClients();
+ // enumerator getClientsSupportingTarget(in nsIDRef aTarget);
+ // enumerator getClientNames(in unsigned long aClientID);
+ // enumerator getClientTargets(in unsigned long aClientID);
+
+
+ /**************************************************************************
+ * message methods
+ */
+
+ /**
+ * set a message observer for a particular message target.
+ *
+ * @param aTarget
+ * the message target being observed. any existing observer will
+ * be replaced.
+ * @param aObserver
+ * the message observer to receive incoming messages for the
+ * specified target. pass null to remove the existing observer.
+ * @param aOnCurrentThread
+ * if true, then the message observer will be called on the same
+ * thread that calls defineTarget. otherwise, aObserver will be
+ * called on a background thread.
+ */
+ void defineTarget(in nsIDRef aTarget,
+ in ipcIMessageObserver aObserver,
+ in boolean aOnCurrentThread);
+
+ /**
+ * send message asynchronously to a client or a module in the IPC daemon.
+ * there is no guarantee that the message will be delivered.
+ *
+ * @param aClientID
+ * the client ID of the foreign application that should receive this
+ * message. pass 0 to send a message to a module in the IPC daemon.
+ * @param aTarget
+ * the target of the message. if aClientID is 0, then this is the
+ * ID of the daemon module that should receive this message.
+ * @param aData
+ * the message data.
+ * @param aDataLen
+ * the message length.
+ */
+ void sendMessage(in unsigned long aReceiverID,
+ in nsIDRef aTarget,
+ [array, const, size_is(aDataLen)]
+ in octet aData,
+ in unsigned long aDataLen);
+
+ /**
+ * block the calling thread until a matching message is received.
+ *
+ * @param aSenderID
+ * pass 0 to wait for a message from the daemon. pass PR_UINT32_MAX
+ * to wait for a message from any source. otherwise, pass a client
+ * id to wait for a message from that particular client.
+ * @param aTarget
+ * wait for a message to be delivered to this target.
+ * @param aObserver
+ * this observer's OnMessageAvailable method is called when a
+ * matching message is available. pass null to use the default
+ * observer associated with aTarget.
+ * @param aTimeout
+ * indicates maximum length of time in milliseconds that this
+ * function may block the calling thread.
+ *
+ * @throws IPC_ERROR_WOULD_BLOCK if the timeout expires.
+ *
+ * the observer's OnMessageAvailable method may throw IPC_WAIT_NEXT_MESSAGE
+ * to indicate that it does not wish to handle the message that it was
+ * given, and that it will wait to be called with the next message. this
+ * enables the observer to keep messages in the queue that do not match the
+ * desired message. messages that remain in the queue will be dispatched
+ * asynchronously to the default message handler after waitMessage finishes.
+ *
+ * NOTE: this function may hang the calling thread until a matching message
+ * is received, so use it with caution.
+ */
+ void waitMessage(in unsigned long aSenderID,
+ in nsIDRef aTarget,
+ in ipcIMessageObserver aObserver,
+ in unsigned long aTimeout);
+
+ /**
+ * Call this method to disable the default message observer for a target.
+ */
+ void disableMessageObserver(in nsIDRef aTarget);
+
+ /**
+ * Call this method to re-enable the default message observer for a target.
+ */
+ void enableMessageObserver(in nsIDRef aTarget);
+};
+
+%{C++
+// category and observer event defines (XXX not yet implemented)
+#define IPC_SERVICE_STARTUP_CATEGORY "ipc-startup-category"
+#define IPC_SERVICE_STARTUP_TOPIC "ipc-startup"
+#define IPC_SERVICE_SHUTDOWN_TOPIC "ipc-shutdown"
+%}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcdclient.h b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcdclient.h
new file mode 100644
index 00000000..5cbed879
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/public/ipcdclient.h
@@ -0,0 +1,326 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ipcdclient_h__
+#define ipcdclient_h__
+
+/*****************************************************************************
+ * This file provides a client-side API to the IPC daemon.
+ *
+ * This API can be used to communicate with other clients of the IPC daemon
+ * as well as modules running inside the IPC daemon.
+ *
+ * This API is meant to be used only on the application's main thread. It is
+ * assumed that callbacks can be dispatched via the main thread's event queue.
+ */
+
+#include "nscore.h"
+#include "nsID.h"
+#include "nsError.h"
+#include "ipcIMessageObserver.h"
+#include "ipcIClientObserver.h"
+
+/* This API is only provided for the extensions compiled into the IPCDC
+ * library, hence this API is hidden in the final DSO. */
+#define IPC_METHOD NS_HIDDEN_(nsresult)
+
+/* This value can be used to represent the client id of any client connected
+ * to the IPC daemon. */
+#define IPC_SENDER_ANY PR_UINT32_MAX
+
+/* This error code can only be returned by OnMessageAvailable, when called by
+ * IPC_WaitMessage. See IPC_WaitMessage for a description of how this error
+ * code may be used. */
+#define IPC_WAIT_NEXT_MESSAGE \
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 10)
+
+#ifdef VBOX
+/* This error code can only be returned by the selector functions called by
+ * WaitTarget. The message should be dropped without processing. */
+#define IPC_DISCARD_MESSAGE \
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 12)
+#endif /* VBOX */
+
+/* This error code is returned by IPC_WaitMessage under certain conditions. */
+#define IPC_ERROR_WOULD_BLOCK NS_BASE_STREAM_WOULD_BLOCK
+
+/*****************************************************************************
+ * Initialization and Shutdown
+ */
+
+// XXX limit these to the main thread, and call them from our module's ctor/dtor?
+
+/**
+ * Connects this process to the IPC daemon and initializes it for use as a
+ * client of the IPC daemon. This function must be called once before any
+ * other methods defined in this file can be used.
+ *
+ * @returns NS_ERROR_ALREADY_INITIALIZED if IPC_Shutdown was not called since
+ * the last time IPC_Init was called.
+ */
+IPC_METHOD IPC_Init();
+
+/**
+ * Disconnects this process from the IPC daemon. After this function is
+ * called, no other methods in this file except for IPC_Init may be called.
+ *
+ * This function calls all client observers (registered with
+ * IPC_AddClientObserver) before it actually disconnects from the IPC daemon,
+ * with aClientID parameter of the OnClientStateChange callback specially
+ * set to IPC_SENDER_ANY and aClientState set to CLIENT_DOWN. This gives
+ * the interested party an opportunity to perform a proper shutdown procedure.
+ * All IPC methods are still available inside OnClientStateChange call except
+ * the IPC_WaitMessage function, that will immediately fail with an error.
+ * OnClientStateChange is called on the same thread where this function is
+ * called.
+ *
+ * @returns NS_ERROR_NOT_INITIALIZED if IPC_Init has not been called or if
+ * IPC_Init did not return a success code.
+ */
+IPC_METHOD IPC_Shutdown();
+
+
+/*****************************************************************************
+ * The core messaging API
+ */
+
+/**
+ * Call this method to define a message target. A message target is defined
+ * by a UUID and a message observer. This observer is notified asynchronously
+ * whenever a message is sent to this target in this process.
+ *
+ * This function has three main effects:
+ * o If the message target is already defined, then this function simply
+ * resets its message observer.
+ * o If the message target is not already defined, then the message target
+ * is defined and the IPC daemon is notified of the existance of this
+ * message target.
+ * o If null is passed for the message observer, then the message target is
+ * removed, and the daemon is notified of the removal of this message target.
+ *
+ * If aOnCurrentThread is true, then notifications to the observer will occur
+ * on the current thread. This means that there must be a nsIEventTarget
+ * associated with the calling thread. If aOnCurrentThread is false, then
+ * notifications to the observer will occur on a background thread. In which
+ * case, the observer must be threadsafe.
+ */
+IPC_METHOD IPC_DefineTarget(
+ const nsID &aTarget,
+ ipcIMessageObserver *aObserver,
+ PRBool aOnCurrentThread = PR_TRUE
+);
+
+/**
+ * Call this method to temporarily disable the message observer configured
+ * for a message target.
+ */
+IPC_METHOD IPC_DisableMessageObserver(
+ const nsID &aTarget
+);
+
+/**
+ * Call this method to re-enable the message observer configured for a
+ * message target.
+ */
+IPC_METHOD IPC_EnableMessageObserver(
+ const nsID &aTarget
+);
+
+/**
+ * This function sends a message to the IPC daemon asynchronously. If
+ * aReceiverID is non-zero, then the message is forwarded to the client
+ * corresponding to that identifier.
+ *
+ * If there is no client corresponding to aRecieverID, then the IPC daemon will
+ * simply drop the message.
+ */
+IPC_METHOD IPC_SendMessage(
+ PRUint32 aReceiverID,
+ const nsID &aTarget,
+ const PRUint8 *aData,
+ PRUint32 aDataLen
+);
+
+/**
+ * This function blocks the calling thread until a message for the given target
+ * is received (optionally from the specified client).
+ *
+ * The aSenderID parameter is interpreted as follows:
+ * o If aSenderID is 0, then this function waits for a message to be sent by
+ * the IPC daemon.
+ * o If aSenderID is IPC_SENDER_ANY, then this function waits for a message
+ * to be sent from any source.
+ * o Otherwise, this function waits for a message to be sent by the client
+ * with ID given by aSenderID. If aSenderID does not identify a valid
+ * client, or if the client dies while waiting, then this function will
+ * return an error.
+ *
+ * The aObserver parameter is interpreted as follows:
+ * o If aObserver is null, then the default message observer for the target
+ * is invoked when the next message is received.
+ * o Otherwise, aObserver will be inovked when the next message is received.
+ *
+ * The aConsumer parameter is interpreted as follows:
+ * o If aObserver is null or aConsumer is null, this parameter is ignored.
+ * o Otherwise, aConsumer will be invoked right after (and only if) aObserver
+ * has accepted some message. It will receive exactly the same message
+ * that was accepted by aObserver.
+ *
+ * The aTimeout parameter is interpreted as follows:
+ * o If aTimeout is PR_INTERVAL_NO_TIMEOUT, then this function will block
+ * until a matching message is received.
+ * o If aTimeout is PR_INTERVAL_NO_WAIT, then this function will only inspect
+ * the current queue of messages. If no matching message is found, then
+ * IPC_ERROR_WOULD_BLOCK is returned.
+ * o Otherwise, aTimeout specifies the maximum amount of time to wait for a
+ * matching message to be received. If no matching message is found after
+ * the timeout expires, then IPC_ERROR_WOULD_BLOCK is returned.
+ *
+ * If aObserver's OnMessageAvailable function returns IPC_WAIT_NEXT_MESSAGE,
+ * then the function will continue blocking until the next matching message
+ * is received. Bypassed messages will be dispatched to the default message
+ * observer when the event queue, associated with the thread that called
+ * IPC_DefineTarget, is processed.
+ *
+ * There is a special case if aSenderID is IPC_SENDER_ANY and one of IPC clients
+ * dies while this function waits for a message. In this case, aObserver's
+ * OnMessageAvailable function is called with a special set of arguments:
+ * dead client id, empty target id and null message (both data and data length
+ * are zeroes). If it returns IPC_WAIT_NEXT_MESSAGE, IPC_WaitMessage continues
+ * blocking as usual, otherwise an error is immediately returned to the caller.
+ *
+ * aObserver is not expected to use any IPC system functons from within its
+ * OnMessageAvailable implementation. This is because the IPC system is not
+ * re-entrant during invocation of OnMessageAvailable function, and making other
+ * IPC calls can lead to unexpected results (like message losses or traps). On
+ * the contrary, aConsumer's OnMessageAvailable function is allowed to use the
+ * IPC system without any limitations.
+ *
+ * This function runs the risk of hanging the calling thread indefinitely if
+ * no matching message is ever received.
+ */
+IPC_METHOD IPC_WaitMessage(
+ PRUint32 aSenderID,
+ const nsID &aTarget,
+ ipcIMessageObserver *aObserver = nsnull,
+ ipcIMessageObserver *aConsumer = nsnull,
+ PRIntervalTime aTimeout = PR_INTERVAL_NO_TIMEOUT
+);
+
+/*****************************************************************************/
+
+/**
+ * Returns the "ClientID" of the current process.
+ */
+IPC_METHOD IPC_GetID(
+ PRUint32 *aClientID
+);
+
+/**
+ * Adds a new name for the current process. The IPC daemon is notified of this
+ * change, which allows other processes to discover this process by the given
+ * name.
+ */
+IPC_METHOD IPC_AddName(
+ const char *aName
+);
+
+/**
+ * Removes a name associated with the current process.
+ */
+IPC_METHOD IPC_RemoveName(
+ const char *aName
+);
+
+/**
+ * Adds client observer. Will be called on the main thread.
+ */
+IPC_METHOD IPC_AddClientObserver(
+ ipcIClientObserver *aObserver
+);
+
+/**
+ * Removes client observer.
+ */
+IPC_METHOD IPC_RemoveClientObserver(
+ ipcIClientObserver *aObserver
+);
+
+/**
+ * Resolves the given client name to a client ID of a process connected to
+ * the IPC daemon.
+ */
+IPC_METHOD IPC_ResolveClientName(
+ const char *aName,
+ PRUint32 *aClientID
+);
+
+/**
+ * Tests whether the client is connected to the IPC daemon.
+ */
+IPC_METHOD IPC_ClientExists(
+ PRUint32 aClientID,
+ PRBool *aResult
+);
+
+/*****************************************************************************/
+
+/**
+ * This class can be used to temporarily disable the default message observer
+ * defined for a particular message target.
+ */
+class ipcDisableMessageObserverForScope
+{
+public:
+ ipcDisableMessageObserverForScope(const nsID &aTarget)
+ : mTarget(aTarget)
+ {
+ IPC_DisableMessageObserver(mTarget);
+ }
+
+ ~ipcDisableMessageObserverForScope()
+ {
+ IPC_EnableMessageObserver(mTarget);
+ }
+
+private:
+ const nsID &mTarget;
+};
+
+#define IPC_DISABLE_MESSAGE_OBSERVER_FOR_SCOPE(_t) \
+ ipcDisableMessageObserverForScope ipc_dmo_for_scope##_t(_t)
+
+#endif /* ipcdclient_h__ */
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/client/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.in
new file mode 100644
index 00000000..b2854e35
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.in
@@ -0,0 +1,101 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = ipcdc
+EXPORT_LIBRARY = 1
+IS_COMPONENT = 1
+MODULE_NAME = ipcdclient
+
+REQUIRES = \
+ xpcom \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ ipcdclient.cpp \
+ ipcService.cpp \
+ ipcModuleFactory.cpp \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS += ipcConnectionWin.cpp
+else
+ifeq ($(OS_ARCH),BeOS)
+CPPSRCS += ipcConnectionStub.cpp
+else
+CPPSRCS += ipcConnectionUnix.cpp
+endif
+endif
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../shared/src \
+ -I$(srcdir)/../../extensions/lock/src \
+ -I$(srcdir)/../../extensions/transmngr/src \
+ -I$(srcdir)/../../extensions/transmngr/common \
+ $(NULL)
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)ipcdshared_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ipcdlock_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)transmgr_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)transmgrcom_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+ifneq ($(BUILD_DCONNECT),)
+DEFINES += -DBUILD_DCONNECT
+LOCAL_INCLUDES += -I$(srcdir)/../../extensions/dconnect/src
+SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)ipcddconnect_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ipcdutil_s.$(LIB_SUFFIX) \
+ $(NULL)
+endif
+
+EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(EXTRA_DSO_LIBS) \
+ $(MOZ_COMPONENT_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.kup b/src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnection.h b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnection.h
new file mode 100644
index 00000000..8773daa5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnection.h
@@ -0,0 +1,147 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ipcConnection_h__
+#define ipcConnection_h__
+
+#include "nscore.h"
+
+class ipcMessage;
+
+#define IPC_METHOD_PRIVATE_(type) NS_HIDDEN_(type)
+#define IPC_METHOD_PRIVATE IPC_METHOD_PRIVATE_(nsresult)
+
+/* ------------------------------------------------------------------------- */
+/* Platform specific IPC connection API.
+ */
+
+typedef void (* ipcCallbackFunc)(void *);
+
+/**
+ * IPC_Connect
+ *
+ * This function causes a connection to the IPC daemon to be established.
+ * If a connection already exists, then this function will be ignored.
+ *
+ * @param daemonPath
+ * Specifies the path to the IPC daemon executable.
+ *
+ * NOTE: This function must be called on the main thread.
+ */
+IPC_METHOD_PRIVATE IPC_Connect(const char *daemonPath);
+
+/**
+ * IPC_Disconnect
+ *
+ * This function causes a connection to the IPC daemon to be closed. Any
+ * unsent messages (IPC_SendMsg puts messages on a queue) will be sent to the
+ * IPC daemon before the connection is closed.
+ *
+ * NOTE: This function must be called on the main thread.
+ */
+IPC_METHOD_PRIVATE IPC_Disconnect();
+
+/**
+ * IPC_SendMsg
+ *
+ * This function sends a message to the IPC daemon. Typically, the message
+ * is put on a queue, to be delivered asynchronously to the IPC daemon. The
+ * ipcMessage object will be deleted when IPC_SendMsg is done with it. The
+ * caller must not touch |msg| after passing it to IPC_SendMsg.
+ *
+ * IPC_SendMsg cannot be called before IPC_Connect or after IPC_Disconnect.
+ *
+ * NOTE: This function may be called on any thread.
+ */
+IPC_METHOD_PRIVATE IPC_SendMsg(ipcMessage *msg);
+
+/**
+ * IPC_DoCallback
+ *
+ * This function executes a callback function on the same background thread
+ * that calls IPC_OnConnectionEnd and IPC_OnMessageAvailable.
+ *
+ * If this function succeeds, then the caller is guaranteed that |func| will
+ * be called. This guarantee is important because it allows the caller to
+ * free any memory associated with |arg| once |func| has been called.
+ *
+ * NOTE: This function may be called on any thread.
+ */
+IPC_METHOD_PRIVATE IPC_DoCallback(ipcCallbackFunc func, void *arg);
+
+/* ------------------------------------------------------------------------- */
+/* Cross-platform IPC connection methods.
+ */
+
+/**
+ * IPC_SpawnDaemon
+ *
+ * This function launches the IPC daemon process. It is called by the platform
+ * specific IPC_Connect implementation. It should not return until the daemon
+ * process is ready to receive a client connection or an error occurs.
+ *
+ * @param daemonPath
+ * Specifies the path to the IPC daemon executable.
+ */
+IPC_METHOD_PRIVATE IPC_SpawnDaemon(const char *daemonPath);
+
+/* ------------------------------------------------------------------------- */
+/* IPC connection callbacks (not implemented by the connection code).
+ *
+ * NOTE: These functions execute on a background thread!!
+ */
+
+/**
+ * IPC_OnConnectionEnd
+ *
+ * This function is called whenever the connection to the IPC daemon has been
+ * terminated. If terminated due to an abnormal error, then the error will be
+ * described by the |error| parameter. If |error| is NS_OK, then it means the
+ * connection was closed in response to a call to IPC_Disconnect.
+ */
+IPC_METHOD_PRIVATE_(void) IPC_OnConnectionEnd(nsresult error);
+
+/**
+ * IPC_OnMessageAvailable
+ *
+ * This function is called whenever an incoming message is read from the IPC
+ * daemon. The ipcMessage object, |msg|, must be deleted by the implementation
+ * of IPC_OnMessageAvailable when the object is no longer needed.
+ */
+IPC_METHOD_PRIVATE_(void) IPC_OnMessageAvailable(ipcMessage *msg);
+
+#endif // ipcConnection_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionStub.cpp b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionStub.cpp
new file mode 100644
index 00000000..8b985785
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionStub.cpp
@@ -0,0 +1,70 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "ipcConnection.h"
+#include "nsError.h"
+
+//-----------------------------------------------------------------------------
+// use this file as a template to add client-side IPC connectivity.
+//
+// NOTE: if your platform supports local domain TCP sockets, then you should
+// be able to make use of ipcConnectionUnix.cpp.
+//-----------------------------------------------------------------------------
+
+nsresult
+IPC_Connect(const char *daemonPath)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+IPC_Disconnect()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+IPC_SendMsg(ipcMessage *msg)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+IPC_DoCallback(ipcCallbackFunc func, void *arg)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionUnix.cpp b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionUnix.cpp
new file mode 100644
index 00000000..5cd7a0c8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionUnix.cpp
@@ -0,0 +1,615 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "private/pprio.h"
+#include "prerror.h"
+#include "prthread.h"
+#include "prlock.h"
+#include "prlog.h" // for PR_ASSERT (we don't actually use NSPR logging)
+#include "prio.h"
+
+#include "ipcConnection.h"
+#include "ipcMessageQ.h"
+#include "ipcConfig.h"
+#include "ipcLog.h"
+
+#ifdef VBOX
+# include "prenv.h"
+# include <stdio.h>
+# include <VBox/log.h>
+#endif
+
+
+//-----------------------------------------------------------------------------
+// NOTE: this code does not need to link with anything but NSPR. that is by
+// design, so it can be easily reused in other projects that want to
+// talk with mozilla's IPC daemon, but don't want to depend on xpcom.
+// we depend at most on some xpcom header files, but no xpcom runtime
+// symbols are used.
+//-----------------------------------------------------------------------------
+
+
+// single user systems, like OS/2, don't need these security checks.
+#ifndef XP_OS2
+#define IPC_SKIP_SECURITY_CHECKS
+#endif
+
+#ifndef IPC_SKIP_SECURITY_CHECKS
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
+
+static PRStatus
+DoSecurityCheck(PRFileDesc *fd, const char *path)
+{
+#ifndef IPC_SKIP_SECURITY_CHECKS
+ //
+ // now that we have a connected socket; do some security checks on the
+ // file descriptor.
+ //
+ // (1) make sure owner matches
+ // (2) make sure permissions match expected permissions
+ //
+ // if these conditions aren't met then bail.
+ //
+ int unix_fd = PR_FileDesc2NativeHandle(fd);
+
+ struct stat st;
+ if (fstat(unix_fd, &st) == -1) {
+ LOG(("stat failed"));
+ return PR_FAILURE;
+ }
+
+ if (st.st_uid != getuid() && st.st_uid != geteuid()) {
+ //
+ // on OSX 10.1.5, |fstat| has a bug when passed a file descriptor to
+ // a socket. it incorrectly returns a UID of 0. however, |stat|
+ // succeeds, but using |stat| introduces a race condition.
+ //
+ // XXX come up with a better security check.
+ //
+ if (st.st_uid != 0) {
+ LOG(("userid check failed"));
+ return PR_FAILURE;
+ }
+ if (stat(path, &st) == -1) {
+ LOG(("stat failed"));
+ return PR_FAILURE;
+ }
+ if (st.st_uid != getuid() && st.st_uid != geteuid()) {
+ LOG(("userid check failed"));
+ return PR_FAILURE;
+ }
+ }
+#endif
+ return PR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+
+struct ipcCallback : public ipcListNode<ipcCallback>
+{
+ ipcCallbackFunc func;
+ void *arg;
+};
+
+typedef ipcList<ipcCallback> ipcCallbackQ;
+
+//-----------------------------------------------------------------------------
+
+struct ipcConnectionState
+{
+ PRLock *lock;
+ PRPollDesc fds[2];
+ ipcCallbackQ callback_queue;
+ ipcMessageQ send_queue;
+ PRUint32 send_offset; // amount of send_queue.First() already written.
+ ipcMessage *in_msg;
+ PRBool shutdown;
+};
+
+#define SOCK 0
+#define POLL 1
+
+static void
+ConnDestroy(ipcConnectionState *s)
+{
+ if (s->lock)
+ PR_DestroyLock(s->lock);
+
+ if (s->fds[SOCK].fd)
+ PR_Close(s->fds[SOCK].fd);
+
+ if (s->fds[POLL].fd)
+ PR_DestroyPollableEvent(s->fds[POLL].fd);
+
+ if (s->in_msg)
+ delete s->in_msg;
+
+ s->send_queue.DeleteAll();
+ delete s;
+}
+
+static ipcConnectionState *
+ConnCreate(PRFileDesc *fd)
+{
+ ipcConnectionState *s = new ipcConnectionState;
+ if (!s)
+ return NULL;
+
+ s->lock = PR_NewLock();
+ s->fds[SOCK].fd = NULL;
+ s->fds[POLL].fd = PR_NewPollableEvent();
+ s->send_offset = 0;
+ s->in_msg = NULL;
+ s->shutdown = PR_FALSE;
+
+ if (!s->lock || !s->fds[1].fd)
+ {
+ ConnDestroy(s);
+ return NULL;
+ }
+
+ // disable inheritance of the IPC socket by children started
+ // using non-NSPR process API
+ PRStatus status = PR_SetFDInheritable(fd, PR_FALSE);
+ if (status != PR_SUCCESS)
+ {
+ LOG(("coudn't make IPC socket non-inheritable [err=%d]\n", PR_GetError()));
+ return NULL;
+ }
+
+ // store this only if we are going to succeed.
+ s->fds[SOCK].fd = fd;
+
+ return s;
+}
+
+static nsresult
+ConnRead(ipcConnectionState *s)
+{
+ char buf[1024];
+ nsresult rv = NS_OK;
+ PRInt32 n;
+
+ do
+ {
+ n = PR_Read(s->fds[SOCK].fd, buf, sizeof(buf));
+ if (n < 0)
+ {
+ PRErrorCode err = PR_GetError();
+ if (err == PR_WOULD_BLOCK_ERROR)
+ {
+ // socket is empty... we need to go back to polling.
+ break;
+ }
+ LOG(("PR_Read returned failure [err=%d]\n", err));
+ rv = NS_ERROR_UNEXPECTED;
+ }
+ else if (n == 0)
+ {
+ LOG(("PR_Read returned EOF\n"));
+ rv = NS_ERROR_UNEXPECTED;
+ }
+ else
+ {
+ const char *pdata = buf;
+ while (n)
+ {
+ PRUint32 bytesRead;
+ PRBool complete;
+
+ if (!s->in_msg)
+ {
+ s->in_msg = new ipcMessage;
+ if (!s->in_msg)
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if (s->in_msg->ReadFrom(pdata, n, &bytesRead, &complete) != PR_SUCCESS)
+ {
+ LOG(("error reading IPC message\n"));
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ PR_ASSERT(PRUint32(n) >= bytesRead);
+ n -= bytesRead;
+ pdata += bytesRead;
+
+ if (complete)
+ {
+ // protect against weird re-entrancy cases...
+ ipcMessage *m = s->in_msg;
+ s->in_msg = NULL;
+
+ IPC_OnMessageAvailable(m);
+ }
+ }
+ }
+ }
+ while (NS_SUCCEEDED(rv));
+
+ return rv;
+}
+
+static nsresult
+ConnWrite(ipcConnectionState *s)
+{
+ nsresult rv = NS_OK;
+
+ PR_Lock(s->lock);
+
+ // write one message and then return.
+ if (s->send_queue.First())
+ {
+ PRInt32 n = PR_Write(s->fds[SOCK].fd,
+ s->send_queue.First()->MsgBuf() + s->send_offset,
+ s->send_queue.First()->MsgLen() - s->send_offset);
+ if (n <= 0)
+ {
+ PRErrorCode err = PR_GetError();
+ if (err == PR_WOULD_BLOCK_ERROR)
+ {
+ // socket is full... we need to go back to polling.
+ }
+ else
+ {
+ LOG(("error writing to socket [err=%d]\n", err));
+ rv = NS_ERROR_UNEXPECTED;
+ }
+ }
+ else
+ {
+ s->send_offset += n;
+ if (s->send_offset == s->send_queue.First()->MsgLen())
+ {
+ s->send_queue.DeleteFirst();
+ s->send_offset = 0;
+
+ // if the send queue is empty, then we need to stop trying to write.
+ if (s->send_queue.IsEmpty())
+ s->fds[SOCK].in_flags &= ~PR_POLL_WRITE;
+ }
+ }
+ }
+
+ PR_Unlock(s->lock);
+ return rv;
+}
+
+PR_STATIC_CALLBACK(void)
+ConnThread(void *arg)
+{
+ PRInt32 num;
+ nsresult rv = NS_OK;
+
+ ipcConnectionState *s = (ipcConnectionState *) arg;
+
+ // we monitor two file descriptors in this thread. the first (at index 0) is
+ // the socket connection with the IPC daemon. the second (at index 1) is the
+ // pollable event we monitor in order to know when to send messages to the
+ // IPC daemon.
+
+ s->fds[SOCK].in_flags = PR_POLL_READ;
+ s->fds[POLL].in_flags = PR_POLL_READ;
+
+ while (NS_SUCCEEDED(rv))
+ {
+ s->fds[SOCK].out_flags = 0;
+ s->fds[POLL].out_flags = 0;
+
+ //
+ // poll on the IPC socket and NSPR pollable event
+ //
+ num = PR_Poll(s->fds, 2, PR_INTERVAL_NO_TIMEOUT);
+ if (num > 0)
+ {
+ ipcCallbackQ cbs_to_run;
+
+ // check if something has been added to the send queue. if so, then
+ // acknowledge pollable event (wait should not block), and configure
+ // poll flags to find out when we can write.
+
+ if (s->fds[POLL].out_flags & PR_POLL_READ)
+ {
+ PR_WaitForPollableEvent(s->fds[POLL].fd);
+ PR_Lock(s->lock);
+
+ if (!s->send_queue.IsEmpty())
+ s->fds[SOCK].in_flags |= PR_POLL_WRITE;
+
+ if (!s->callback_queue.IsEmpty())
+ s->callback_queue.MoveTo(cbs_to_run);
+
+ PR_Unlock(s->lock);
+ }
+
+ // check if we can read...
+ if (s->fds[SOCK].out_flags & PR_POLL_READ)
+ rv = ConnRead(s);
+
+ // check if we can write...
+ if (s->fds[SOCK].out_flags & PR_POLL_WRITE)
+ rv = ConnWrite(s);
+
+ // check if we have callbacks to run
+ while (!cbs_to_run.IsEmpty())
+ {
+ ipcCallback *cb = cbs_to_run.First();
+ (cb->func)(cb->arg);
+ cbs_to_run.DeleteFirst();
+ }
+
+ // check if we should exit this thread. delay processing a shutdown
+ // request until after all queued up messages have been sent and until
+ // after all queued up callbacks have been run.
+ PR_Lock(s->lock);
+ if (s->shutdown && s->send_queue.IsEmpty() && s->callback_queue.IsEmpty())
+ rv = NS_ERROR_ABORT;
+ PR_Unlock(s->lock);
+ }
+ else
+ {
+ LOG(("PR_Poll returned error %d (%s), os error %d\n", PR_GetError(),
+ PR_ErrorToName(PR_GetError()), PR_GetOSError()));
+ rv = NS_ERROR_UNEXPECTED;
+ }
+ }
+
+ // notify termination of the IPC connection
+ if (rv == NS_ERROR_ABORT)
+ rv = NS_OK;
+ IPC_OnConnectionEnd(rv);
+
+ LOG(("IPC thread exiting\n"));
+}
+
+//-----------------------------------------------------------------------------
+// IPC connection API
+//-----------------------------------------------------------------------------
+
+static ipcConnectionState *gConnState = NULL;
+static PRThread *gConnThread = NULL;
+
+#ifdef DEBUG
+static PRThread *gMainThread = NULL;
+#endif
+
+nsresult
+TryConnect(PRFileDesc **result)
+{
+ PRFileDesc *fd;
+ PRNetAddr addr;
+ PRSocketOptionData opt;
+ // don't use NS_ERROR_FAILURE as we want to detect these kind of errors
+ // in the frontend
+ nsresult rv = NS_ERROR_SOCKET_FAIL;
+
+ fd = PR_OpenTCPSocket(PR_AF_LOCAL);
+ if (!fd)
+ goto end;
+
+ addr.local.family = PR_AF_LOCAL;
+ IPC_GetDefaultSocketPath(addr.local.path, sizeof(addr.local.path));
+
+ // blocking connect... will fail if no one is listening.
+ if (PR_Connect(fd, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
+ goto end;
+
+#ifdef VBOX
+ if (PR_GetEnv("TESTBOX_UUID"))
+ fprintf(stderr, "IPC socket path: %s\n", addr.local.path);
+ LogRel(("IPC socket path: %s\n", addr.local.path));
+#endif
+
+ // make socket non-blocking
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(fd, &opt);
+
+ // do some security checks on connection socket...
+ if (DoSecurityCheck(fd, addr.local.path) != PR_SUCCESS)
+ goto end;
+
+ *result = fd;
+ return NS_OK;
+
+end:
+ if (fd)
+ PR_Close(fd);
+
+ return rv;
+}
+
+nsresult
+IPC_Connect(const char *daemonPath)
+{
+ // synchronous connect, spawn daemon if necessary.
+
+ PRFileDesc *fd = NULL;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (gConnState)
+ return NS_ERROR_ALREADY_INITIALIZED;
+
+ //
+ // here's the connection algorithm: try to connect to an existing daemon.
+ // if the connection fails, then spawn the daemon (wait for it to be ready),
+ // and then retry the connection. it is critical that the socket used to
+ // connect to the daemon not be inherited (this causes problems on RH9 at
+ // least).
+ //
+
+ rv = TryConnect(&fd);
+ if (NS_FAILED(rv))
+ {
+ nsresult rv1 = IPC_SpawnDaemon(daemonPath);
+ if (NS_SUCCEEDED(rv1) || rv != NS_ERROR_SOCKET_FAIL)
+ rv = rv1;
+ if (NS_SUCCEEDED(rv))
+ rv = TryConnect(&fd);
+ }
+
+ if (NS_FAILED(rv))
+ goto end;
+
+ //
+ // ok, we have a connection to the daemon!
+ //
+
+ // build connection state object
+ gConnState = ConnCreate(fd);
+ if (!gConnState)
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ goto end;
+ }
+ fd = NULL; // connection state now owns the socket
+
+ gConnThread = PR_CreateThread(PR_USER_THREAD,
+ ConnThread,
+ gConnState,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!gConnThread)
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ goto end;
+ }
+
+#ifdef DEBUG
+ gMainThread = PR_GetCurrentThread();
+#endif
+ return NS_OK;
+
+end:
+ if (gConnState)
+ {
+ ConnDestroy(gConnState);
+ gConnState = NULL;
+ }
+ if (fd)
+ PR_Close(fd);
+ return rv;
+}
+
+nsresult
+IPC_Disconnect()
+{
+ // Must disconnect on same thread used to connect!
+ PR_ASSERT(gMainThread == PR_GetCurrentThread());
+
+ if (!gConnState || !gConnThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ PR_Lock(gConnState->lock);
+ gConnState->shutdown = PR_TRUE;
+ PR_SetPollableEvent(gConnState->fds[POLL].fd);
+ PR_Unlock(gConnState->lock);
+
+ PR_JoinThread(gConnThread);
+
+ ConnDestroy(gConnState);
+
+ gConnState = NULL;
+ gConnThread = NULL;
+ return NS_OK;
+}
+
+nsresult
+IPC_SendMsg(ipcMessage *msg)
+{
+ if (!gConnState || !gConnThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ PR_Lock(gConnState->lock);
+ gConnState->send_queue.Append(msg);
+ PR_SetPollableEvent(gConnState->fds[POLL].fd);
+ PR_Unlock(gConnState->lock);
+
+ return NS_OK;
+}
+
+nsresult
+IPC_DoCallback(ipcCallbackFunc func, void *arg)
+{
+ if (!gConnState || !gConnThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ ipcCallback *callback = new ipcCallback;
+ if (!callback)
+ return NS_ERROR_OUT_OF_MEMORY;
+ callback->func = func;
+ callback->arg = arg;
+
+ PR_Lock(gConnState->lock);
+ gConnState->callback_queue.Append(callback);
+ PR_SetPollableEvent(gConnState->fds[POLL].fd);
+ PR_Unlock(gConnState->lock);
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+#ifdef TEST_STANDALONE
+
+void IPC_OnConnectionFault(nsresult rv)
+{
+ LOG(("IPC_OnConnectionFault [rv=%x]\n", rv));
+}
+
+void IPC_OnMessageAvailable(ipcMessage *msg)
+{
+ LOG(("IPC_OnMessageAvailable\n"));
+ delete msg;
+}
+
+int main()
+{
+ IPC_InitLog(">>>");
+ IPC_Connect("/builds/moz-trunk/seamonkey-debug-build/dist/bin/mozilla-ipcd");
+ IPC_Disconnect();
+ return 0;
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionWin.cpp b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionWin.cpp
new file mode 100644
index 00000000..9a99c195
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcConnectionWin.cpp
@@ -0,0 +1,332 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 <windows.h>
+
+#include "prprf.h"
+#include "prmon.h"
+#include "prthread.h"
+#include "plevent.h"
+
+#include "nsIServiceManager.h"
+#include "nsIEventQueue.h"
+#include "nsIEventQueueService.h"
+#include "nsAutoLock.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcConnection.h"
+#include "ipcm.h"
+
+
+//-----------------------------------------------------------------------------
+// NOTE: this code does not need to link with anything but NSPR. that is by
+// design, so it can be easily reused in other projects that want to
+// talk with mozilla's IPC daemon, but don't want to depend on xpcom.
+// we depend at most on some xpcom header files, but no xpcom runtime
+// symbols are used.
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// windows message thread
+//-----------------------------------------------------------------------------
+
+#define IPC_WM_SENDMSG (WM_USER + 0x1)
+#define IPC_WM_CALLBACK (WM_USER + 0x2)
+#define IPC_WM_SHUTDOWN (WM_USER + 0x3)
+
+static nsresult ipcThreadStatus = NS_OK;
+static PRThread *ipcThread = NULL;
+static PRMonitor *ipcMonitor = NULL;
+static HWND ipcDaemonHwnd = NULL;
+static HWND ipcLocalHwnd = NULL;
+static PRBool ipcShutdown = PR_FALSE; // not accessed on message thread!!
+
+//-----------------------------------------------------------------------------
+// window proc
+//-----------------------------------------------------------------------------
+
+static LRESULT CALLBACK
+ipcThreadWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LOG(("got message [msg=%x wparam=%x lparam=%x]\n", uMsg, wParam, lParam));
+
+ if (uMsg == WM_COPYDATA) {
+ COPYDATASTRUCT *cd = (COPYDATASTRUCT *) lParam;
+ if (cd && cd->lpData) {
+ ipcMessage *msg = new ipcMessage();
+ PRUint32 bytesRead;
+ PRBool complete;
+ PRStatus rv = msg->ReadFrom((const char *) cd->lpData, cd->cbData,
+ &bytesRead, &complete);
+ if (rv == PR_SUCCESS && complete)
+ IPC_OnMessageAvailable(msg); // takes ownership of msg
+ else {
+ LOG((" unable to deliver message [complete=%u]\n", complete));
+ delete msg;
+ }
+ }
+ return TRUE;
+ }
+
+ if (uMsg == IPC_WM_SENDMSG) {
+ ipcMessage *msg = (ipcMessage *) lParam;
+ if (msg) {
+ LOG((" sending message...\n"));
+ COPYDATASTRUCT cd;
+ cd.dwData = GetCurrentProcessId();
+ cd.cbData = (DWORD) msg->MsgLen();
+ cd.lpData = (PVOID) msg->MsgBuf();
+ SendMessageA(ipcDaemonHwnd, WM_COPYDATA, (WPARAM) hWnd, (LPARAM) &cd);
+ LOG((" done.\n"));
+ delete msg;
+ }
+ return 0;
+ }
+
+ if (uMsg == IPC_WM_CALLBACK) {
+ ipcCallbackFunc func = (ipcCallbackFunc) wParam;
+ void *arg = (void *) lParam;
+ (func)(arg);
+ return 0;
+ }
+
+ if (uMsg == IPC_WM_SHUTDOWN) {
+ IPC_OnConnectionEnd(NS_OK);
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+//-----------------------------------------------------------------------------
+// ipc thread functions
+//-----------------------------------------------------------------------------
+
+static void
+ipcThreadFunc(void *arg)
+{
+ LOG(("entering message thread\n"));
+
+ DWORD pid = GetCurrentProcessId();
+
+ WNDCLASS wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.lpfnWndProc = ipcThreadWindowProc;
+ wc.lpszClassName = IPC_CLIENT_WINDOW_CLASS;
+ RegisterClass(&wc);
+
+ char wName[sizeof(IPC_CLIENT_WINDOW_NAME_PREFIX) + 20];
+ PR_snprintf(wName, sizeof(wName), "%s%u", IPC_CLIENT_WINDOW_NAME_PREFIX, pid);
+
+ ipcLocalHwnd = CreateWindow(IPC_CLIENT_WINDOW_CLASS, wName,
+ 0, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
+
+ {
+ nsAutoMonitor mon(ipcMonitor);
+ if (!ipcLocalHwnd)
+ ipcThreadStatus = NS_ERROR_FAILURE;
+ mon.Notify();
+ }
+
+ if (ipcLocalHwnd) {
+ MSG msg;
+ while (GetMessage(&msg, ipcLocalHwnd, 0, 0))
+ DispatchMessage(&msg);
+
+ ipcShutdown = PR_TRUE; // assuming atomic memory write
+
+ DestroyWindow(ipcLocalHwnd);
+ ipcLocalHwnd = NULL;
+ }
+
+ LOG(("exiting message thread\n"));
+ return;
+}
+
+static PRStatus
+ipcThreadInit()
+{
+ if (ipcThread)
+ return PR_FAILURE;
+
+ ipcShutdown = PR_FALSE;
+
+ ipcMonitor = PR_NewMonitor();
+ if (!ipcMonitor)
+ return PR_FAILURE;
+
+ // spawn message thread
+ ipcThread = PR_CreateThread(PR_USER_THREAD, ipcThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ if (!ipcThread) {
+ NS_WARNING("thread creation failed");
+ PR_DestroyMonitor(ipcMonitor);
+ ipcMonitor = NULL;
+ return PR_FAILURE;
+ }
+
+ // wait for hidden window to be created
+ {
+ nsAutoMonitor mon(ipcMonitor);
+ while (!ipcLocalHwnd && NS_SUCCEEDED(ipcThreadStatus))
+ mon.Wait();
+ }
+
+ if (NS_FAILED(ipcThreadStatus)) {
+ NS_WARNING("message thread failed");
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+ipcThreadShutdown()
+{
+ if (PR_AtomicSet(&ipcShutdown, PR_TRUE) == PR_FALSE) {
+ LOG(("posting IPC_WM_SHUTDOWN message\n"));
+ PostMessage(ipcLocalHwnd, IPC_WM_SHUTDOWN, 0, 0);
+ }
+
+ LOG(("joining w/ message thread...\n"));
+ PR_JoinThread(ipcThread);
+ ipcThread = NULL;
+
+ //
+ // ok, now the message thread is dead
+ //
+
+ PR_DestroyMonitor(ipcMonitor);
+ ipcMonitor = NULL;
+
+ return PR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// windows specific IPC connection impl
+//-----------------------------------------------------------------------------
+
+nsresult
+IPC_Disconnect()
+{
+ LOG(("IPC_Disconnect\n"));
+
+ //XXX mHaveConnection = PR_FALSE;
+
+ if (!ipcDaemonHwnd)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ if (ipcThread)
+ ipcThreadShutdown();
+
+ // clear our reference to the daemon's HWND.
+ ipcDaemonHwnd = NULL;
+ return NS_OK;
+}
+
+nsresult
+IPC_Connect(const char *daemonPath)
+{
+ LOG(("IPC_Connect\n"));
+
+ NS_ENSURE_TRUE(ipcDaemonHwnd == NULL, NS_ERROR_ALREADY_INITIALIZED);
+ nsresult rv;
+
+ ipcDaemonHwnd = FindWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME);
+ if (!ipcDaemonHwnd) {
+ LOG((" daemon does not appear to be running\n"));
+ //
+ // daemon does not exist; spawn daemon...
+ //
+ rv = IPC_SpawnDaemon(daemonPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ ipcDaemonHwnd = FindWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME);
+ if (!ipcDaemonHwnd)
+ return NS_ERROR_FAILURE;
+ }
+
+ //
+ // delay creation of the message thread until we know the daemon exists.
+ //
+ if (!ipcThread && ipcThreadInit() != PR_SUCCESS) {
+ ipcDaemonHwnd = NULL;
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+IPC_SendMsg(ipcMessage *msg)
+{
+ LOG(("IPC_SendMsg\n"));
+
+ if (ipcShutdown) {
+ LOG(("unable to send message b/c message thread is shutdown\n"));
+ goto loser;
+ }
+ if (!PostMessage(ipcLocalHwnd, IPC_WM_SENDMSG, 0, (LPARAM) msg)) {
+ LOG((" PostMessage failed w/ error = %u\n", GetLastError()));
+ goto loser;
+ }
+ return NS_OK;
+loser:
+ delete msg;
+ return NS_ERROR_FAILURE;
+}
+
+nsresult
+IPC_DoCallback(ipcCallbackFunc func, void *arg)
+{
+ LOG(("IPC_DoCallback\n"));
+
+ if (ipcShutdown) {
+ LOG(("unable to send message b/c message thread is shutdown\n"));
+ return NS_ERROR_FAILURE;
+ }
+ if (!PostMessage(ipcLocalHwnd, IPC_WM_CALLBACK, (WPARAM) func, (LPARAM) arg)) {
+ LOG((" PostMessage failed w/ error = %u\n", GetLastError()));
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcModuleFactory.cpp b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcModuleFactory.cpp
new file mode 100644
index 00000000..7dcd6eab
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcModuleFactory.cpp
@@ -0,0 +1,196 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsIServiceManager.h"
+#include "nsIGenericFactory.h"
+#include "nsICategoryManager.h"
+#include "ipcdclient.h"
+#include "ipcService.h"
+#include "ipcConfig.h"
+#include "ipcCID.h"
+
+//-----------------------------------------------------------------------------
+// Define the contructor function for the objects
+//
+// NOTE: This creates an instance of objects by using the default constructor
+//-----------------------------------------------------------------------------
+NS_GENERIC_FACTORY_CONSTRUCTOR(ipcService)
+
+// enable this code to make the IPC service auto-start.
+#if 0
+NS_METHOD
+ipcServiceRegisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const char *componentType,
+ const nsModuleComponentInfo *info)
+{
+ //
+ // add ipcService to the XPCOM startup category
+ //
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman) {
+ nsXPIDLCString prevEntry;
+ catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcService",
+ IPC_SERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
+ getter_Copies(prevEntry));
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+ipcServiceUnregisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const nsModuleComponentInfo *info)
+{
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman)
+ catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
+ IPC_SERVICE_CONTRACTID, PR_TRUE);
+ return NS_OK;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// extensions
+
+#include "ipcLockService.h"
+#include "ipcLockCID.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcLockService, Init)
+
+#include "tmTransactionService.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR(tmTransactionService)
+
+#ifdef BUILD_DCONNECT
+
+#include "ipcDConnectService.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcDConnectService, Init)
+
+// enable this code to make the IPC DCONNECT service auto-start.
+NS_METHOD
+ipcDConnectServiceRegisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const char *componentType,
+ const nsModuleComponentInfo *info)
+{
+ //
+ // add ipcService to the XPCOM startup category
+ //
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman) {
+ nsXPIDLCString prevEntry;
+ catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcDConnectService",
+ IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
+ getter_Copies(prevEntry));
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+ipcDConnectServiceUnregisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const nsModuleComponentInfo *info)
+{
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman)
+ catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
+ IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE);
+ return NS_OK;
+}
+
+#endif // BUILD_DCONNECT
+
+//-----------------------------------------------------------------------------
+// Define a table of CIDs implemented by this module along with other
+// information like the function to create an instance, contractid, and
+// class name.
+//-----------------------------------------------------------------------------
+static const nsModuleComponentInfo components[] = {
+ { IPC_SERVICE_CLASSNAME,
+ IPC_SERVICE_CID,
+ IPC_SERVICE_CONTRACTID,
+ ipcServiceConstructor },
+ /*
+ ipcServiceRegisterProc,
+ ipcServiceUnregisterProc },
+ */
+ //
+ // extensions go here:
+ //
+ { IPC_LOCKSERVICE_CLASSNAME,
+ IPC_LOCKSERVICE_CID,
+ IPC_LOCKSERVICE_CONTRACTID,
+ ipcLockServiceConstructor },
+ { IPC_TRANSACTIONSERVICE_CLASSNAME,
+ IPC_TRANSACTIONSERVICE_CID,
+ IPC_TRANSACTIONSERVICE_CONTRACTID,
+ tmTransactionServiceConstructor },
+
+#ifdef BUILD_DCONNECT
+ { IPC_DCONNECTSERVICE_CLASSNAME,
+ IPC_DCONNECTSERVICE_CID,
+ IPC_DCONNECTSERVICE_CONTRACTID,
+ ipcDConnectServiceConstructor,
+ ipcDConnectServiceRegisterProc,
+ ipcDConnectServiceUnregisterProc },
+#endif
+};
+
+//-----------------------------------------------------------------------------
+
+PR_STATIC_CALLBACK(nsresult)
+ipcdclient_init(nsIModule *module)
+{
+ return IPC_Init();
+}
+
+PR_STATIC_CALLBACK(void)
+ipcdclient_shutdown(nsIModule *module)
+{
+ IPC_Shutdown();
+}
+
+//-----------------------------------------------------------------------------
+// Implement the NSGetModule() exported function for your module
+// and the entire implementation of the module object.
+//-----------------------------------------------------------------------------
+NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(ipcdclient, components,
+ ipcdclient_init,
+ ipcdclient_shutdown)
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.cpp b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.cpp
new file mode 100644
index 00000000..6c2a1326
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.cpp
@@ -0,0 +1,120 @@
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "ipcService.h"
+
+// The ipcService implementation is nothing more than a thin XPCOM wrapper
+// around the ipcdclient.h API.
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(ipcService, ipcIService)
+
+NS_IMETHODIMP
+ipcService::GetID(PRUint32 *aID)
+{
+ return IPC_GetID(aID);
+}
+
+NS_IMETHODIMP
+ipcService::AddName(const char *aName)
+{
+ return IPC_AddName(aName);
+}
+
+NS_IMETHODIMP
+ipcService::RemoveName(const char *aName)
+{
+ return IPC_RemoveName(aName);
+}
+
+NS_IMETHODIMP
+ipcService::AddClientObserver(ipcIClientObserver *aObserver)
+{
+ return IPC_AddClientObserver(aObserver);
+}
+
+NS_IMETHODIMP
+ipcService::RemoveClientObserver(ipcIClientObserver *aObserver)
+{
+ return IPC_RemoveClientObserver(aObserver);
+}
+
+NS_IMETHODIMP
+ipcService::ResolveClientName(const char *aName, PRUint32 *aID)
+{
+ return IPC_ResolveClientName(aName, aID);
+}
+
+NS_IMETHODIMP
+ipcService::ClientExists(PRUint32 aClientID, PRBool *aResult)
+{
+ return IPC_ClientExists(aClientID, aResult);
+}
+
+NS_IMETHODIMP
+ipcService::DefineTarget(const nsID &aTarget, ipcIMessageObserver *aObserver,
+ PRBool aOnCurrentThread)
+{
+ return IPC_DefineTarget(aTarget, aObserver, aOnCurrentThread);
+}
+
+NS_IMETHODIMP
+ipcService::SendMessage(PRUint32 aReceiverID, const nsID &aTarget,
+ const PRUint8 *aData, PRUint32 aDataLen)
+{
+ return IPC_SendMessage(aReceiverID, aTarget, aData, aDataLen);
+}
+
+NS_IMETHODIMP
+ipcService::WaitMessage(PRUint32 aSenderID, const nsID &aTarget,
+ ipcIMessageObserver *aObserver,
+ PRUint32 aTimeout)
+{
+ return IPC_WaitMessage(aSenderID, aTarget, aObserver, nsnull,
+ PR_MillisecondsToInterval(aTimeout));
+}
+
+NS_IMETHODIMP
+ipcService::DisableMessageObserver(const nsID &aTarget)
+{
+ return IPC_DisableMessageObserver(aTarget);
+}
+
+NS_IMETHODIMP
+ipcService::EnableMessageObserver(const nsID &aTarget)
+{
+ return IPC_EnableMessageObserver(aTarget);
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.h b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.h
new file mode 100644
index 00000000..80f953cf
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcService.h
@@ -0,0 +1,51 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcService_h__
+#define ipcService_h__
+
+#include "ipcIService.h"
+#include "ipcdclient.h"
+
+class ipcService : public ipcIService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCISERVICE
+};
+
+#endif // !defined( ipcService_h__ )
diff --git a/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcdclient.cpp b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcdclient.cpp
new file mode 100644
index 00000000..ce0f86c8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcdclient.cpp
@@ -0,0 +1,1505 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "ipcdclient.h"
+#include "ipcConnection.h"
+#include "ipcConfig.h"
+#include "ipcMessageQ.h"
+#include "ipcMessageUtils.h"
+#include "ipcLog.h"
+#include "ipcm.h"
+
+#include "nsIFile.h"
+#include "nsEventQueueUtils.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCOMPtr.h"
+#include "nsHashKeys.h"
+#include "nsRefPtrHashtable.h"
+#include "nsAutoLock.h"
+#include "nsProxyRelease.h"
+#include "nsCOMArray.h"
+
+#include "prio.h"
+#include "prproces.h"
+#include "pratom.h"
+
+#ifdef VBOX
+# include <iprt/critsect.h>
+# define VBOX_WITH_IPCCLIENT_RW_CS
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#define IPC_REQUEST_TIMEOUT PR_SecondsToInterval(30)
+
+/* ------------------------------------------------------------------------- */
+
+class ipcTargetData
+{
+public:
+ static NS_HIDDEN_(ipcTargetData*) Create();
+
+ // threadsafe addref/release
+ NS_HIDDEN_(nsrefcnt) AddRef() { return PR_AtomicIncrement(&refcnt); }
+ NS_HIDDEN_(nsrefcnt) Release() { PRInt32 r = PR_AtomicDecrement(&refcnt); if (r == 0) delete this; return r; }
+
+ NS_HIDDEN_(void) SetObserver(ipcIMessageObserver *aObserver, PRBool aOnCurrentThread);
+
+ // protects access to the members of this class
+ PRMonitor *monitor;
+
+ // this may be null
+ nsCOMPtr<ipcIMessageObserver> observer;
+
+ // the message observer is called via this event queue
+ nsCOMPtr<nsIEventQueue> eventQ;
+
+ // incoming messages are added to this list
+ ipcMessageQ pendingQ;
+
+ // non-zero if the observer has been disabled (this means that new messages
+ // should not be dispatched to the observer until the observer is re-enabled
+ // via IPC_EnableMessageObserver).
+ PRInt32 observerDisabled;
+
+private:
+
+ ipcTargetData()
+ : monitor(nsAutoMonitor::NewMonitor("ipcTargetData"))
+ , observerDisabled(0)
+ , refcnt(0)
+ {}
+
+ ~ipcTargetData()
+ {
+ if (monitor)
+ nsAutoMonitor::DestroyMonitor(monitor);
+ }
+
+ PRInt32 refcnt;
+};
+
+ipcTargetData *
+ipcTargetData::Create()
+{
+ ipcTargetData *td = new ipcTargetData;
+ if (!td)
+ return NULL;
+
+ if (!td->monitor)
+ {
+ delete td;
+ return NULL;
+ }
+ return td;
+}
+
+void
+ipcTargetData::SetObserver(ipcIMessageObserver *aObserver, PRBool aOnCurrentThread)
+{
+ observer = aObserver;
+
+ if (aOnCurrentThread)
+ NS_GetCurrentEventQ(getter_AddRefs(eventQ));
+ else
+ eventQ = nsnull;
+}
+
+/* ------------------------------------------------------------------------- */
+
+typedef nsRefPtrHashtable<nsIDHashKey, ipcTargetData> ipcTargetMap;
+
+class ipcClientState
+{
+public:
+ static NS_HIDDEN_(ipcClientState *) Create();
+
+ ~ipcClientState()
+ {
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ if (monitor)
+ nsAutoMonitor::DestroyMonitor(monitor);
+#else
+ RTCritSectRwDelete(&critSect);
+#endif
+ }
+
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ //
+ // the monitor protects the targetMap and the connected and shutdown flags.
+ //
+ // NOTE: we use a PRMonitor for this instead of a PRLock because we need
+ // the lock to be re-entrant. since we don't ever need to wait on
+ // this monitor, it might be worth it to implement a re-entrant
+ // wrapper for PRLock.
+ //
+ PRMonitor *monitor;
+#else /* VBOX_WITH_IPCCLIENT_RW_CS */
+ RTCRITSECTRW critSect;
+#endif /* VBOX_WITH_IPCCLIENT_RW_CS */
+ ipcTargetMap targetMap;
+ PRBool connected;
+ PRBool shutdown;
+
+ // our process's client id
+ PRUint32 selfID;
+
+ nsCOMArray<ipcIClientObserver> clientObservers;
+
+private:
+
+ ipcClientState()
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ : monitor(nsAutoMonitor::NewMonitor("ipcClientState"))
+ , connected(PR_FALSE)
+#else
+ : connected(PR_FALSE)
+#endif
+ , shutdown(PR_FALSE)
+ , selfID(0)
+ {
+#ifdef VBOX_WITH_IPCCLIENT_RW_CS
+ /* Not employing the lock validator here to keep performance up in debug builds. */
+ RTCritSectRwInitEx(&critSect, RTCRITSECT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
+#endif
+ }
+};
+
+ipcClientState *
+ipcClientState::Create()
+{
+ ipcClientState *cs = new ipcClientState;
+ if (!cs)
+ return NULL;
+
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ if (!cs->monitor || !cs->targetMap.Init())
+#else
+ if (!RTCritSectRwIsInitialized(&cs->critSect) || !cs->targetMap.Init())
+#endif
+ {
+ delete cs;
+ return NULL;
+ }
+
+ return cs;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static ipcClientState *gClientState;
+
+static PRBool
+GetTarget(const nsID &aTarget, ipcTargetData **td)
+{
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ nsAutoMonitor mon(gClientState->monitor);
+ return gClientState->targetMap.Get(nsIDHashKey(&aTarget).GetKey(), td);
+#else
+ RTCritSectRwEnterShared(&gClientState->critSect);
+ PRBool fRc = gClientState->targetMap.Get(nsIDHashKey(&aTarget).GetKey(), td);
+ RTCritSectRwLeaveShared(&gClientState->critSect);
+ return fRc;
+#endif
+}
+
+static PRBool
+PutTarget(const nsID &aTarget, ipcTargetData *td)
+{
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ nsAutoMonitor mon(gClientState->monitor);
+ return gClientState->targetMap.Put(nsIDHashKey(&aTarget).GetKey(), td);
+#else
+ RTCritSectRwEnterExcl(&gClientState->critSect);
+ PRBool fRc = gClientState->targetMap.Put(nsIDHashKey(&aTarget).GetKey(), td);
+ RTCritSectRwLeaveExcl(&gClientState->critSect);
+ return fRc;
+#endif
+}
+
+static void
+DelTarget(const nsID &aTarget)
+{
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ nsAutoMonitor mon(gClientState->monitor);
+ gClientState->targetMap.Remove(nsIDHashKey(&aTarget).GetKey());
+#else
+ RTCritSectRwEnterExcl(&gClientState->critSect);
+ gClientState->targetMap.Remove(nsIDHashKey(&aTarget).GetKey());
+ RTCritSectRwLeaveExcl(&gClientState->critSect);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+static nsresult
+GetDaemonPath(nsCString &dpath)
+{
+ nsCOMPtr<nsIFile> file;
+
+ nsresult rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
+ getter_AddRefs(file));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = file->AppendNative(NS_LITERAL_CSTRING(IPC_DAEMON_APP_NAME));
+ if (NS_SUCCEEDED(rv))
+ rv = file->GetNativePath(dpath);
+ }
+
+ return rv;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+ProcessPendingQ(const nsID &aTarget)
+{
+ ipcMessageQ tempQ;
+
+ nsRefPtr<ipcTargetData> td;
+ if (GetTarget(aTarget, getter_AddRefs(td)))
+ {
+ nsAutoMonitor mon(td->monitor);
+
+ // if the observer for this target has been temporarily disabled, then
+ // we must not processing any pending messages at this time.
+
+ if (!td->observerDisabled)
+ td->pendingQ.MoveTo(tempQ);
+ }
+
+ // process pending queue outside monitor
+ while (!tempQ.IsEmpty())
+ {
+ ipcMessage *msg = tempQ.First();
+
+ // it is possible that messages for other targets are in the queue
+ // (currently, this can be only a IPCM_MSG_PSH_CLIENT_STATE message
+ // initially addressed to IPCM_TARGET, see IPC_OnMessageAvailable())
+ // --ignore them.
+ if (td->observer && msg->Target().Equals(aTarget))
+ td->observer->OnMessageAvailable(msg->mMetaData,
+ msg->Target(),
+ (const PRUint8 *) msg->Data(),
+ msg->DataLen());
+ else
+ {
+ // the IPCM target does not have an observer, and therefore any IPCM
+ // messages that make it here will simply be dropped.
+ NS_ASSERTION(aTarget.Equals(IPCM_TARGET) || msg->Target().Equals(IPCM_TARGET),
+ "unexpected target");
+ LOG(("dropping IPCM message: type=%x\n", IPCM_GetType(msg)));
+ }
+ tempQ.DeleteFirst();
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+// WaitTarget enables support for multiple threads blocking on the same
+// message target. the selector is called while inside the target's monitor.
+
+typedef nsresult (* ipcMessageSelector)(
+ void *arg,
+ ipcTargetData *td,
+ const ipcMessage *msg
+);
+
+// selects any
+static nsresult
+DefaultSelector(void *arg, ipcTargetData *td, const ipcMessage *msg)
+{
+ return NS_OK;
+}
+
+static nsresult
+WaitTarget(const nsID &aTarget,
+ PRIntervalTime aTimeout,
+ ipcMessage **aMsg,
+ ipcMessageSelector aSelector = nsnull,
+ void *aArg = nsnull)
+{
+ *aMsg = nsnull;
+
+ if (!aSelector)
+ aSelector = DefaultSelector;
+
+ nsRefPtr<ipcTargetData> td;
+ if (!GetTarget(aTarget, getter_AddRefs(td)))
+ return NS_ERROR_INVALID_ARG; // bad aTarget
+
+ PRBool isIPCMTarget = aTarget.Equals(IPCM_TARGET);
+
+ PRIntervalTime timeStart = PR_IntervalNow();
+ PRIntervalTime timeEnd;
+ if (aTimeout == PR_INTERVAL_NO_TIMEOUT)
+ timeEnd = aTimeout;
+ else if (aTimeout == PR_INTERVAL_NO_WAIT)
+ timeEnd = timeStart;
+ else
+ {
+ timeEnd = timeStart + aTimeout;
+
+ // if overflowed, then set to max value
+ if (timeEnd < timeStart)
+ timeEnd = PR_INTERVAL_NO_TIMEOUT;
+ }
+
+ ipcMessage *lastChecked = nsnull, *beforeLastChecked = nsnull;
+ nsresult rv = NS_ERROR_ABORT;
+
+ nsAutoMonitor mon(td->monitor);
+
+ // only the ICPM target is allowed to wait for a message after shutdown
+ // (but before disconnection). this gives client observers called from
+ // IPC_Shutdown a chance to use IPC_SendMessage to send necessary
+ // "last minute" messages to other clients.
+
+ while (gClientState->connected && (!gClientState->shutdown || isIPCMTarget))
+ {
+ NS_ASSERTION(!lastChecked, "oops");
+
+ //
+ // NOTE:
+ //
+ // we must start at the top of the pending queue, possibly revisiting
+ // messages that our selector has already rejected. this is necessary
+ // because the queue may have been modified while we were waiting on
+ // the monitor. the impact of this on performance remains to be seen.
+ //
+ // one cheap solution is to keep a counter that is incremented each
+ // time a message is removed from the pending queue. that way we can
+ // avoid revisiting all messages sometimes.
+ //
+
+ lastChecked = td->pendingQ.First();
+ beforeLastChecked = nsnull;
+
+ // loop over pending queue until we find a message that our selector likes.
+ while (lastChecked)
+ {
+ //
+ // it is possible that this call to WaitTarget() has been initiated by
+ // some other selector, that might be currently processing the same
+ // message (since the message remains in the queue until the selector
+ // returns TRUE). here we prevent this situation by using a special flag
+ // to guarantee that every message is processed only once.
+ //
+
+ if (!lastChecked->TestFlag(IPC_MSG_FLAG_IN_PROCESS))
+ {
+ lastChecked->SetFlag(IPC_MSG_FLAG_IN_PROCESS);
+ nsresult acceptedRV = (aSelector)(aArg, td, lastChecked);
+ lastChecked->ClearFlag(IPC_MSG_FLAG_IN_PROCESS);
+
+ if (acceptedRV != IPC_WAIT_NEXT_MESSAGE)
+ {
+ if (acceptedRV == NS_OK)
+ {
+ // remove from pending queue
+ if (beforeLastChecked)
+ td->pendingQ.RemoveAfter(beforeLastChecked);
+ else
+ td->pendingQ.RemoveFirst();
+
+ lastChecked->mNext = nsnull;
+ *aMsg = lastChecked;
+ break;
+ }
+ else /* acceptedRV == IPC_DISCARD_MESSAGE */
+ {
+ ipcMessage *nextToCheck = lastChecked->mNext;
+
+ // discard from pending queue
+ if (beforeLastChecked)
+ td->pendingQ.DeleteAfter(beforeLastChecked);
+ else
+ td->pendingQ.DeleteFirst();
+
+ lastChecked = nextToCheck;
+
+ continue;
+ }
+ }
+ }
+
+ beforeLastChecked = lastChecked;
+ lastChecked = lastChecked->mNext;
+ }
+
+ if (*aMsg)
+ {
+ rv = NS_OK;
+ break;
+ }
+#ifdef VBOX
+ else
+ {
+ /* Special client liveness check if there is no message to process.
+ * This is necessary as there might be several threads waiting for
+ * a message from a single client, and only one gets the DOWN msg. */
+ nsresult aliveRV = (aSelector)(aArg, td, NULL);
+ if (aliveRV != IPC_WAIT_NEXT_MESSAGE)
+ {
+ *aMsg = NULL;
+ break;
+ }
+ }
+#endif /* VBOX */
+
+ PRIntervalTime t = PR_IntervalNow();
+ if (t > timeEnd) // check if timeout has expired
+ {
+ rv = IPC_ERROR_WOULD_BLOCK;
+ break;
+ }
+ mon.Wait(timeEnd - t);
+
+ LOG(("woke up from sleep [pendingQempty=%d connected=%d shutdown=%d isIPCMTarget=%d]\n",
+ td->pendingQ.IsEmpty(), gClientState->connected,
+ gClientState->shutdown, isIPCMTarget));
+ }
+
+ return rv;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+PostEvent(nsIEventTarget *eventTarget, PLEvent *ev)
+{
+ if (!ev)
+ return;
+
+ nsresult rv = eventTarget->PostEvent(ev);
+ if (NS_FAILED(rv))
+ {
+ NS_WARNING("PostEvent failed");
+ PL_DestroyEvent(ev);
+ }
+}
+
+static void
+PostEventToMainThread(PLEvent *ev)
+{
+ nsCOMPtr<nsIEventQueue> eventQ;
+ NS_GetMainEventQ(getter_AddRefs(eventQ));
+ if (!eventQ)
+ {
+ NS_WARNING("unable to get reference to main event queue");
+ PL_DestroyEvent(ev);
+ return;
+ }
+ PostEvent(eventQ, ev);
+}
+
+/* ------------------------------------------------------------------------- */
+
+class ipcEvent_ClientState : public PLEvent
+{
+public:
+ ipcEvent_ClientState(PRUint32 aClientID, PRUint32 aClientState)
+ : mClientID(aClientID)
+ , mClientState(aClientState)
+ {
+ PL_InitEvent(this, nsnull, HandleEvent, DestroyEvent);
+ }
+
+ PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev)
+ {
+ // maybe we've been shutdown!
+ if (!gClientState)
+ return nsnull;
+
+ ipcEvent_ClientState *self = (ipcEvent_ClientState *) ev;
+
+ for (PRInt32 i=0; i<gClientState->clientObservers.Count(); ++i)
+ gClientState->clientObservers[i]->OnClientStateChange(self->mClientID,
+ self->mClientState);
+ return nsnull;
+ }
+
+ PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *ev)
+ {
+ delete (ipcEvent_ClientState *) ev;
+ }
+
+private:
+ PRUint32 mClientID;
+ PRUint32 mClientState;
+};
+
+/* ------------------------------------------------------------------------- */
+
+class ipcEvent_ProcessPendingQ : public PLEvent
+{
+public:
+ ipcEvent_ProcessPendingQ(const nsID &aTarget)
+ : mTarget(aTarget)
+ {
+ PL_InitEvent(this, nsnull, HandleEvent, DestroyEvent);
+ }
+
+ PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev)
+ {
+ ProcessPendingQ(((ipcEvent_ProcessPendingQ *) ev)->mTarget);
+ return nsnull;
+ }
+
+ PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *ev)
+ {
+ delete (ipcEvent_ProcessPendingQ *) ev;
+ }
+
+private:
+ const nsID mTarget;
+};
+
+static void
+CallProcessPendingQ(const nsID &target, ipcTargetData *td)
+{
+ // we assume that we are inside td's monitor
+
+ PLEvent *ev = new ipcEvent_ProcessPendingQ(target);
+ if (!ev)
+ return;
+
+ nsresult rv;
+
+ if (td->eventQ)
+ rv = td->eventQ->PostEvent(ev);
+ else
+ rv = IPC_DoCallback((ipcCallbackFunc) PL_HandleEvent, ev);
+
+ if (NS_FAILED(rv))
+ PL_DestroyEvent(ev);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+DisableMessageObserver(const nsID &aTarget)
+{
+ nsRefPtr<ipcTargetData> td;
+ if (GetTarget(aTarget, getter_AddRefs(td)))
+ {
+ nsAutoMonitor mon(td->monitor);
+ ++td->observerDisabled;
+ }
+}
+
+static void
+EnableMessageObserver(const nsID &aTarget)
+{
+ nsRefPtr<ipcTargetData> td;
+ if (GetTarget(aTarget, getter_AddRefs(td)))
+ {
+ nsAutoMonitor mon(td->monitor);
+ if (td->observerDisabled > 0 && --td->observerDisabled == 0)
+ if (!td->pendingQ.IsEmpty())
+ CallProcessPendingQ(aTarget, td);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+// converts IPCM_ERROR_* status codes to NS_ERROR_* status codes
+static nsresult nsresult_from_ipcm_result(PRInt32 status)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ switch (status)
+ {
+ case IPCM_ERROR_GENERIC: rv = NS_ERROR_FAILURE; break;
+ case IPCM_ERROR_INVALID_ARG: rv = NS_ERROR_INVALID_ARG; break;
+ case IPCM_ERROR_NO_CLIENT: rv = NS_ERROR_CALL_FAILED; break;
+ // TODO: select better mapping for the below codes
+ case IPCM_ERROR_NO_SUCH_DATA:
+ case IPCM_ERROR_ALREADY_EXISTS: rv = NS_ERROR_FAILURE; break;
+ default: NS_ASSERTION(PR_FALSE, "No conversion");
+ }
+
+ return rv;
+}
+
+/* ------------------------------------------------------------------------- */
+
+// selects the next IPCM message with matching request index
+static nsresult
+WaitIPCMResponseSelector(void *arg, ipcTargetData *td, const ipcMessage *msg)
+{
+#ifdef VBOX
+ if (!msg)
+ return IPC_WAIT_NEXT_MESSAGE;
+#endif /* VBOX */
+ PRUint32 requestIndex = *(PRUint32 *) arg;
+ return IPCM_GetRequestIndex(msg) == requestIndex ? NS_OK : IPC_WAIT_NEXT_MESSAGE;
+}
+
+// wait for an IPCM response message. if responseMsg is null, then it is
+// assumed that the caller does not care to get a reference to the
+// response itself. if the response is an IPCM_MSG_ACK_RESULT, then the
+// status code is mapped to a nsresult and returned by this function.
+static nsresult
+WaitIPCMResponse(PRUint32 requestIndex, ipcMessage **responseMsg = nsnull)
+{
+ ipcMessage *msg;
+
+ nsresult rv = WaitTarget(IPCM_TARGET, IPC_REQUEST_TIMEOUT, &msg,
+ WaitIPCMResponseSelector, &requestIndex);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (IPCM_GetType(msg) == IPCM_MSG_ACK_RESULT)
+ {
+ ipcMessageCast<ipcmMessageResult> result(msg);
+ if (result->Status() < 0)
+ rv = nsresult_from_ipcm_result(result->Status());
+ else
+ rv = NS_OK;
+ }
+
+ if (responseMsg)
+ *responseMsg = msg;
+ else
+ delete msg;
+
+ return rv;
+}
+
+// make an IPCM request and wait for a response.
+static nsresult
+MakeIPCMRequest(ipcMessage *msg, ipcMessage **responseMsg = nsnull)
+{
+ if (!msg)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32 requestIndex = IPCM_GetRequestIndex(msg);
+
+ // suppress 'ProcessPendingQ' for IPCM messages until we receive the
+ // response to this IPCM request. if we did not do this then there
+ // would be a race condition leading to the possible removal of our
+ // response from the pendingQ between sending the request and waiting
+ // for the response.
+ DisableMessageObserver(IPCM_TARGET);
+
+ nsresult rv = IPC_SendMsg(msg);
+ if (NS_SUCCEEDED(rv))
+ rv = WaitIPCMResponse(requestIndex, responseMsg);
+
+ EnableMessageObserver(IPCM_TARGET);
+ return rv;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+RemoveTarget(const nsID &aTarget, PRBool aNotifyDaemon)
+{
+ DelTarget(aTarget);
+
+ if (aNotifyDaemon)
+ {
+ nsresult rv = MakeIPCMRequest(new ipcmMessageClientDelTarget(aTarget));
+ if (NS_FAILED(rv))
+ LOG(("failed to delete target: rv=%x\n", rv));
+ }
+}
+
+static nsresult
+DefineTarget(const nsID &aTarget,
+ ipcIMessageObserver *aObserver,
+ PRBool aOnCurrentThread,
+ PRBool aNotifyDaemon,
+ ipcTargetData **aResult)
+{
+ nsresult rv;
+
+ nsRefPtr<ipcTargetData> td( ipcTargetData::Create() );
+ if (!td)
+ return NS_ERROR_OUT_OF_MEMORY;
+ td->SetObserver(aObserver, aOnCurrentThread);
+
+ if (!PutTarget(aTarget, td))
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (aNotifyDaemon)
+ {
+ rv = MakeIPCMRequest(new ipcmMessageClientAddTarget(aTarget));
+ if (NS_FAILED(rv))
+ {
+ LOG(("failed to add target: rv=%x\n", rv));
+ RemoveTarget(aTarget, PR_FALSE);
+ return rv;
+ }
+ }
+
+ if (aResult)
+ NS_ADDREF(*aResult = td);
+ return NS_OK;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static nsresult
+TryConnect()
+{
+ nsCAutoString dpath;
+ nsresult rv = GetDaemonPath(dpath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = IPC_Connect(dpath.get());
+ if (NS_FAILED(rv))
+ return rv;
+
+ gClientState->connected = PR_TRUE;
+
+ rv = DefineTarget(IPCM_TARGET, nsnull, PR_FALSE, PR_FALSE, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+
+ ipcMessage *msg = NULL;
+
+ // send CLIENT_HELLO and wait for CLIENT_ID response...
+ rv = MakeIPCMRequest(new ipcmMessageClientHello(), &msg);
+ if (NS_FAILED(rv))
+ {
+#ifdef VBOX /* MakeIPCMRequest may return a failure (e.g. NS_ERROR_CALL_FAILED) and a response msg. */
+ if (msg)
+ delete msg;
+#endif
+ return rv;
+ }
+
+ if (IPCM_GetType(msg) == IPCM_MSG_ACK_CLIENT_ID)
+ gClientState->selfID = ipcMessageCast<ipcmMessageClientID>(msg)->ClientID();
+ else
+ {
+ LOG(("unexpected response from CLIENT_HELLO message: type=%x!\n",
+ IPCM_GetType(msg)));
+ rv = NS_ERROR_UNEXPECTED;
+ }
+
+ delete msg;
+ return rv;
+}
+
+nsresult
+IPC_Init()
+{
+ NS_ENSURE_TRUE(!gClientState, NS_ERROR_ALREADY_INITIALIZED);
+
+ IPC_InitLog(">>>");
+
+ gClientState = ipcClientState::Create();
+ if (!gClientState)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = TryConnect();
+ if (NS_FAILED(rv))
+ IPC_Shutdown();
+
+ return rv;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+EnumerateTargetMapAndNotify(const nsID &aKey,
+ ipcTargetData *aData,
+ void *aClosure);
+
+nsresult
+IPC_Shutdown()
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ LOG(("IPC_Shutdown: connected=%d\n",gClientState->connected));
+
+ if (gClientState->connected)
+ {
+ {
+ // first, set the shutdown flag and unblock any calls to WaitTarget.
+ // all targets but IPCM will not be able to use WaitTarget any more.
+
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ nsAutoMonitor mon(gClientState->monitor);
+#else
+ RTCritSectRwEnterExcl(&gClientState->critSect);
+#endif
+
+ gClientState->shutdown = PR_TRUE;
+ gClientState->targetMap.EnumerateRead(EnumerateTargetMapAndNotify, nsnull);
+
+#ifdef VBOX_WITH_IPCCLIENT_RW_CS
+ RTCritSectRwLeaveExcl(&gClientState->critSect);
+#endif
+ }
+
+ // inform all client observers that we're being shutdown to let interested
+ // parties gracefully uninitialize themselves. the IPCM target is still
+ // fully operational at this point, so they can use IPC_SendMessage
+ // (this is essential for the DConnect extension, for example, to do the
+ // proper uninitialization).
+
+ ipcEvent_ClientState *ev = new ipcEvent_ClientState(IPC_SENDER_ANY,
+ IPCM_CLIENT_STATE_DOWN);
+ ipcEvent_ClientState::HandleEvent (ev);
+ ipcEvent_ClientState::DestroyEvent (ev);
+
+ IPC_Disconnect();
+ }
+
+ //
+ // make gClientState nsnull before deletion to cause all public IPC_*
+ // calls (possibly made during ipcClientState destruction) to return
+ // NS_ERROR_NOT_INITIALIZED.
+ //
+ // NOTE: isn't just checking for gClientState->connected in every appropriate
+ // IPC_* method a better solution?
+ //
+ ipcClientState *aClientState = gClientState;
+ gClientState = nsnull;
+ delete aClientState;
+
+ return NS_OK;
+}
+
+/* ------------------------------------------------------------------------- */
+
+nsresult
+IPC_DefineTarget(const nsID &aTarget,
+ ipcIMessageObserver *aObserver,
+ PRBool aOnCurrentThread)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ // do not permit the re-definition of the IPCM protocol's target.
+ if (aTarget.Equals(IPCM_TARGET))
+ return NS_ERROR_INVALID_ARG;
+
+ nsresult rv;
+
+ nsRefPtr<ipcTargetData> td;
+ if (GetTarget(aTarget, getter_AddRefs(td)))
+ {
+ // clear out observer before removing target since we want to ensure that
+ // the observer is released on the main thread.
+ {
+ nsAutoMonitor mon(td->monitor);
+ td->SetObserver(aObserver, aOnCurrentThread);
+ }
+
+ // remove target outside of td's monitor to avoid holding the monitor
+ // while entering the client state's monitor.
+ if (!aObserver)
+ RemoveTarget(aTarget, PR_TRUE);
+
+ rv = NS_OK;
+ }
+ else
+ {
+ if (aObserver)
+ rv = DefineTarget(aTarget, aObserver, aOnCurrentThread, PR_TRUE, nsnull);
+ else
+ rv = NS_ERROR_INVALID_ARG; // unknown target
+ }
+
+ return rv;
+}
+
+nsresult
+IPC_DisableMessageObserver(const nsID &aTarget)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ // do not permit modifications to the IPCM protocol's target.
+ if (aTarget.Equals(IPCM_TARGET))
+ return NS_ERROR_INVALID_ARG;
+
+ DisableMessageObserver(aTarget);
+ return NS_OK;
+}
+
+nsresult
+IPC_EnableMessageObserver(const nsID &aTarget)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ // do not permit modifications to the IPCM protocol's target.
+ if (aTarget.Equals(IPCM_TARGET))
+ return NS_ERROR_INVALID_ARG;
+
+ EnableMessageObserver(aTarget);
+ return NS_OK;
+}
+
+nsresult
+IPC_SendMessage(PRUint32 aReceiverID,
+ const nsID &aTarget,
+ const PRUint8 *aData,
+ PRUint32 aDataLen)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ // do not permit sending IPCM messages
+ if (aTarget.Equals(IPCM_TARGET))
+ return NS_ERROR_INVALID_ARG;
+
+ nsresult rv;
+ if (aReceiverID == 0)
+ {
+ ipcMessage *msg = new ipcMessage(aTarget, (const char *) aData, aDataLen);
+ if (!msg)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = IPC_SendMsg(msg);
+ }
+ else
+ rv = MakeIPCMRequest(new ipcmMessageForward(IPCM_MSG_REQ_FORWARD,
+ aReceiverID,
+ aTarget,
+ (const char *) aData,
+ aDataLen));
+
+ return rv;
+}
+
+struct WaitMessageSelectorData
+{
+ PRUint32 senderID;
+ ipcIMessageObserver *observer;
+ PRBool senderDead;
+};
+
+static nsresult WaitMessageSelector(void *arg, ipcTargetData *td, const ipcMessage *msg)
+{
+ WaitMessageSelectorData *data = (WaitMessageSelectorData *) arg;
+#ifdef VBOX
+ if (!msg)
+ {
+ /* Special NULL message which asks to check whether the client is
+ * still alive. Called when there is nothing suitable in the queue. */
+ ipcIMessageObserver *obs = data->observer;
+ if (!obs)
+ obs = td->observer;
+ NS_ASSERTION(obs, "must at least have a default observer");
+
+ nsresult rv = obs->OnMessageAvailable(IPC_SENDER_ANY, nsID(), 0, 0);
+ if (rv != IPC_WAIT_NEXT_MESSAGE)
+ data->senderDead = PR_TRUE;
+
+ return rv;
+ }
+#endif /* VBOX */
+
+ // process the specially forwarded client state message to see if the
+ // sender we're waiting a message from has died.
+
+ if (msg->Target().Equals(IPCM_TARGET))
+ {
+ switch (IPCM_GetType(msg))
+ {
+ case IPCM_MSG_PSH_CLIENT_STATE:
+ {
+ ipcMessageCast<ipcmMessageClientState> status(msg);
+ if ((data->senderID == IPC_SENDER_ANY ||
+ status->ClientID() == data->senderID) &&
+ status->ClientState() == IPCM_CLIENT_STATE_DOWN)
+ {
+ LOG(("sender (%d) we're waiting a message from (%d) has died\n",
+ status->ClientID(), data->senderID));
+
+ if (data->senderID != IPC_SENDER_ANY)
+ {
+ // we're waiting on a particular client, so IPC_WaitMessage must
+ // definitely fail with the NS_ERROR_xxx result.
+
+ data->senderDead = PR_TRUE;
+ return IPC_DISCARD_MESSAGE; // consume the message
+ }
+ else
+ {
+ // otherwise inform the observer about the client death using a special
+ // null message with an empty target id, and fail IPC_WaitMessage call
+ // with NS_ERROR_xxx only if the observer accepts this message.
+
+ ipcIMessageObserver *obs = data->observer;
+ if (!obs)
+ obs = td->observer;
+ NS_ASSERTION(obs, "must at least have a default observer");
+
+ nsresult rv = obs->OnMessageAvailable(status->ClientID(), nsID(), 0, 0);
+ if (rv != IPC_WAIT_NEXT_MESSAGE)
+ data->senderDead = PR_TRUE;
+
+ return IPC_DISCARD_MESSAGE; // consume the message
+ }
+ }
+#ifdef VBOX
+ else if ((data->senderID == IPC_SENDER_ANY ||
+ status->ClientID() == data->senderID) &&
+ status->ClientState() == IPCM_CLIENT_STATE_UP)
+ {
+ LOG(("sender (%d) we're waiting a message from (%d) has come up\n",
+ status->ClientID(), data->senderID));
+ if (data->senderID == IPC_SENDER_ANY)
+ {
+ // inform the observer about the client appearance using a special
+ // null message with an empty target id, but a length of 1.
+
+ ipcIMessageObserver *obs = data->observer;
+ if (!obs)
+ obs = td->observer;
+ NS_ASSERTION(obs, "must at least have a default observer");
+
+ nsresult rv = obs->OnMessageAvailable(status->ClientID(), nsID(), 0, 1);
+ /* VBoxSVC/VBoxXPCOMIPCD auto-start can cause that a client up
+ * message arrives while we're already waiting for a response
+ * from this client. Don't declare the connection as dead in
+ * this case. A client ID wraparound can't falsely trigger
+ * this, since the waiting thread would have hit the liveness
+ * check in the mean time. We MUST consume the message, otherwise
+ * IPCM messages pile up as long as there is a pending call, which
+ * can lead to severe processing overhead. */
+ return IPC_DISCARD_MESSAGE; // consume the message
+ }
+ }
+#endif /* VBOX */
+ break;
+ }
+ default:
+ NS_NOTREACHED("unexpected message");
+ }
+ return IPC_WAIT_NEXT_MESSAGE; // continue iterating
+ }
+
+ nsresult rv = IPC_WAIT_NEXT_MESSAGE;
+
+ if (data->senderID == IPC_SENDER_ANY ||
+ msg->mMetaData == data->senderID)
+ {
+ ipcIMessageObserver *obs = data->observer;
+ if (!obs)
+ obs = td->observer;
+ NS_ASSERTION(obs, "must at least have a default observer");
+
+ rv = obs->OnMessageAvailable(msg->mMetaData,
+ msg->Target(),
+ (const PRUint8 *) msg->Data(),
+ msg->DataLen());
+ }
+
+ // stop iterating if we got a match that the observer accepted.
+ return rv != IPC_WAIT_NEXT_MESSAGE ? NS_OK : IPC_WAIT_NEXT_MESSAGE;
+}
+
+nsresult
+IPC_WaitMessage(PRUint32 aSenderID,
+ const nsID &aTarget,
+ ipcIMessageObserver *aObserver,
+ ipcIMessageObserver *aConsumer,
+ PRIntervalTime aTimeout)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ // do not permit waiting for IPCM messages
+ if (aTarget.Equals(IPCM_TARGET))
+ return NS_ERROR_INVALID_ARG;
+
+ // use aObserver as the message selector
+ WaitMessageSelectorData data = { aSenderID, aObserver, PR_FALSE };
+
+ ipcMessage *msg;
+ nsresult rv = WaitTarget(aTarget, aTimeout, &msg, WaitMessageSelector, &data);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // if the selector has accepted some message, then we pass it to aConsumer
+ // for safe processing. The IPC susbsystem is quite stable here (i.e. we're
+ // not inside any of the monitors, and the message has been already removed
+ // from the pending queue).
+ if (aObserver && aConsumer)
+ {
+ aConsumer->OnMessageAvailable(msg->mMetaData,
+ msg->Target(),
+ (const PRUint8 *) msg->Data(),
+ msg->DataLen());
+ }
+
+ delete msg;
+
+ // if the requested sender has died while waiting, return an error
+ if (data.senderDead)
+ return NS_ERROR_ABORT; // XXX better error code?
+
+ return NS_OK;
+}
+
+/* ------------------------------------------------------------------------- */
+
+nsresult
+IPC_GetID(PRUint32 *aClientID)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ *aClientID = gClientState->selfID;
+ return NS_OK;
+}
+
+nsresult
+IPC_AddName(const char *aName)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ return MakeIPCMRequest(new ipcmMessageClientAddName(aName));
+}
+
+nsresult
+IPC_RemoveName(const char *aName)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ return MakeIPCMRequest(new ipcmMessageClientDelName(aName));
+}
+
+/* ------------------------------------------------------------------------- */
+
+nsresult
+IPC_AddClientObserver(ipcIClientObserver *aObserver)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ return gClientState->clientObservers.AppendObject(aObserver)
+ ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+IPC_RemoveClientObserver(ipcIClientObserver *aObserver)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ for (PRInt32 i = 0; i < gClientState->clientObservers.Count(); ++i)
+ {
+ if (gClientState->clientObservers[i] == aObserver)
+ gClientState->clientObservers.RemoveObjectAt(i);
+ }
+
+ return NS_OK;
+}
+
+/* ------------------------------------------------------------------------- */
+
+// this function could be called on any thread
+nsresult
+IPC_ResolveClientName(const char *aName, PRUint32 *aClientID)
+{
+ NS_ENSURE_TRUE(gClientState, NS_ERROR_NOT_INITIALIZED);
+
+ ipcMessage *msg = NULL;
+
+ nsresult rv = MakeIPCMRequest(new ipcmMessageQueryClientByName(aName), &msg);
+ if (NS_FAILED(rv))
+ {
+#ifdef VBOX /* MakeIPCMRequest may return a failure (e.g. NS_ERROR_CALL_FAILED) and a response msg. */
+ if (msg)
+ delete msg;
+#endif
+ return rv;
+ }
+
+ if (IPCM_GetType(msg) == IPCM_MSG_ACK_CLIENT_ID)
+ *aClientID = ipcMessageCast<ipcmMessageClientID>(msg)->ClientID();
+ else
+ {
+ LOG(("unexpected IPCM response: type=%x\n", IPCM_GetType(msg)));
+ rv = NS_ERROR_UNEXPECTED;
+ }
+
+ delete msg;
+ return rv;
+}
+
+/* ------------------------------------------------------------------------- */
+
+nsresult
+IPC_ClientExists(PRUint32 aClientID, PRBool *aResult)
+{
+ // this is a bit of a hack. we forward a PING to the specified client.
+ // the assumption is that the forwarding will only succeed if the client
+ // exists, so we wait for the RESULT message corresponding to the FORWARD
+ // request. if that gives a successful status, then we know that the
+ // client exists.
+
+ ipcmMessagePing ping;
+
+ return MakeIPCMRequest(new ipcmMessageForward(IPCM_MSG_REQ_FORWARD,
+ aClientID,
+ IPCM_TARGET,
+ ping.Data(),
+ ping.DataLen()));
+}
+
+/* ------------------------------------------------------------------------- */
+
+nsresult
+IPC_SpawnDaemon(const char *path)
+{
+ PRFileDesc *readable = nsnull, *writable = nsnull;
+ PRProcessAttr *attr = nsnull;
+ nsresult rv = NS_ERROR_FAILURE;
+ PRFileDesc *devNull;
+ char *const argv[] = { (char *const) path, nsnull };
+ char c;
+
+ // setup an anonymous pipe that we can use to determine when the daemon
+ // process has started up. the daemon will write a char to the pipe, and
+ // when we read it, we'll know to proceed with trying to connect to the
+ // daemon.
+
+ if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS)
+ goto end;
+ PR_SetFDInheritable(writable, PR_TRUE);
+
+ attr = PR_NewProcessAttr();
+ if (!attr)
+ goto end;
+
+ if (PR_ProcessAttrSetInheritableFD(attr, writable, IPC_STARTUP_PIPE_NAME) != PR_SUCCESS)
+ goto end;
+
+ devNull = PR_Open("/dev/null", PR_RDWR, 0);
+ if (!devNull)
+ goto end;
+
+ PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull);
+ PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull);
+ PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull);
+
+ if (PR_CreateProcessDetached(path, argv, nsnull, attr) != PR_SUCCESS)
+ goto end;
+
+ // Close /dev/null
+ PR_Close(devNull);
+ // close the child end of the pipe in order to get notification on unexpected
+ // child termination instead of being infinitely blocked in PR_Read().
+ PR_Close(writable);
+ writable = nsnull;
+
+ if ((PR_Read(readable, &c, 1) != 1) || (c != IPC_STARTUP_PIPE_MAGIC))
+ goto end;
+
+ rv = NS_OK;
+end:
+ if (readable)
+ PR_Close(readable);
+ if (writable)
+ PR_Close(writable);
+ if (attr)
+ PR_DestroyProcessAttr(attr);
+ return rv;
+}
+
+/* ------------------------------------------------------------------------- */
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+EnumerateTargetMapAndNotify(const nsID &aKey,
+ ipcTargetData *aData,
+ void *aClosure)
+{
+ nsAutoMonitor mon(aData->monitor);
+
+ // wake up anyone waiting on this target.
+ mon.NotifyAll();
+
+ return PL_DHASH_NEXT;
+}
+
+// called on a background thread
+void
+IPC_OnConnectionEnd(nsresult error)
+{
+ // now, go through the target map, and tickle each monitor. that should
+ // unblock any calls to WaitTarget.
+
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ nsAutoMonitor mon(gClientState->monitor);
+#else
+ RTCritSectRwEnterExcl(&gClientState->critSect);
+#endif
+
+ gClientState->connected = PR_FALSE;
+ gClientState->targetMap.EnumerateRead(EnumerateTargetMapAndNotify, nsnull);
+
+#ifdef VBOX_WITH_IPCCLIENT_RW_CS
+ RTCritSectRwLeaveExcl(&gClientState->critSect);
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+PlaceOnPendingQ(const nsID &target, ipcTargetData *td, ipcMessage *msg)
+{
+ nsAutoMonitor mon(td->monitor);
+
+ // we only want to dispatch a 'ProcessPendingQ' event if we have not
+ // already done so.
+ PRBool dispatchEvent = td->pendingQ.IsEmpty();
+
+ // put this message on our pending queue
+ td->pendingQ.Append(msg);
+
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ char *targetStr = target.ToString();
+ LOG(("placed message on pending queue for target %s and notifying all...\n", targetStr));
+ nsMemory::Free(targetStr);
+ }
+#endif
+
+ // wake up anyone waiting on this queue
+ mon.NotifyAll();
+
+ // proxy call to target's message procedure
+ if (dispatchEvent)
+ CallProcessPendingQ(target, td);
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+EnumerateTargetMapAndPlaceMsg(const nsID &aKey,
+ ipcTargetData *aData,
+ void *userArg)
+{
+ if (!aKey.Equals(IPCM_TARGET))
+ {
+ // place a message clone to a target's event queue
+ ipcMessage *msg = (ipcMessage *) userArg;
+ PlaceOnPendingQ(aKey, aData, msg->Clone());
+ }
+
+ return PL_DHASH_NEXT;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef IPC_LOGGING
+#include "prprf.h"
+#include <ctype.h>
+#endif
+
+// called on a background thread
+void
+IPC_OnMessageAvailable(ipcMessage *msg)
+{
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ char *targetStr = msg->Target().ToString();
+ LOG(("got message for target: %s\n", targetStr));
+ nsMemory::Free(targetStr);
+
+// IPC_LogBinary((const PRUint8 *) msg->Data(), msg->DataLen());
+ }
+#endif
+
+ if (msg->Target().Equals(IPCM_TARGET))
+ {
+ switch (IPCM_GetType(msg))
+ {
+ // if this is a forwarded message, then post the inner message instead.
+ case IPCM_MSG_PSH_FORWARD:
+ {
+ ipcMessageCast<ipcmMessageForward> fwd(msg);
+ ipcMessage *innerMsg = new ipcMessage(fwd->InnerTarget(),
+ fwd->InnerData(),
+ fwd->InnerDataLen());
+ // store the sender's client id in the meta-data field of the message.
+ innerMsg->mMetaData = fwd->ClientID();
+
+ delete msg;
+
+ // recurse so we can handle forwarded IPCM messages
+ IPC_OnMessageAvailable(innerMsg);
+ return;
+ }
+ case IPCM_MSG_PSH_CLIENT_STATE:
+ {
+ ipcMessageCast<ipcmMessageClientState> status(msg);
+ PostEventToMainThread(new ipcEvent_ClientState(status->ClientID(),
+ status->ClientState()));
+
+ // go through the target map, and place this message to every target's
+ // pending event queue. that unblocks all WaitTarget calls (on all
+ // targets) giving them an opportuninty to finish wait cycle because of
+ // the peer client death, when appropriate.
+#ifndef VBOX_WITH_IPCCLIENT_RW_CS
+ nsAutoMonitor mon(gClientState->monitor);
+#else
+ RTCritSectRwEnterShared(&gClientState->critSect);
+#endif
+
+ gClientState->targetMap.EnumerateRead(EnumerateTargetMapAndPlaceMsg, msg);
+
+#ifdef VBOX_WITH_IPCCLIENT_RW_CS
+ RTCritSectRwLeaveShared(&gClientState->critSect);
+#endif
+ delete msg;
+
+ return;
+ }
+ }
+ }
+
+ nsRefPtr<ipcTargetData> td;
+ if (GetTarget(msg->Target(), getter_AddRefs(td)))
+ {
+ // make copy of target since |msg| may end up pointing to free'd memory
+ // once we notify the monitor inside PlaceOnPendingQ().
+ const nsID target = msg->Target();
+
+ PlaceOnPendingQ(target, td, msg);
+ }
+ else
+ {
+ NS_WARNING("message target is undefined");
+#ifdef VBOX
+ delete msg;
+#endif
+ }
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in
new file mode 100644
index 00000000..ad1a66b7
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/Makefile.in
@@ -0,0 +1,52 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+EXPORTS = \
+ ipcModule.h \
+ ipcModuleUtil.h \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h
new file mode 100644
index 00000000..2f299f70
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModule.h
@@ -0,0 +1,240 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcModule_h__
+#define ipcModule_h__
+
+#include "nsID.h"
+
+//
+// a client handle is used to efficiently reference a client instance object
+// used by the daemon to represent a connection with a particular client app.
+//
+// modules should treat it as an opaque type.
+//
+typedef class ipcClient *ipcClientHandle;
+
+//-----------------------------------------------------------------------------
+// interface implemented by the module:
+//-----------------------------------------------------------------------------
+
+//
+// the version of ipcModuleMethods data structure.
+//
+#define IPC_MODULE_METHODS_VERSION (1<<16) // 1.0
+
+//
+// each module defines the following structure:
+//
+struct ipcModuleMethods
+{
+ //
+ // this field holds the version of the data structure, which is always the
+ // value of IPC_MODULE_METHODS_VERSION against which the module was built.
+ //
+ PRUint32 version;
+
+ //
+ // called after this module is registered.
+ //
+ void (* init) (void);
+
+ //
+ // called when this module will no longer be accessed.
+ //
+ void (* shutdown) (void);
+
+ //
+ // called when a new message arrives for this module.
+ //
+ // params:
+ // client - an opaque "handle" to an object representing the client that
+ // sent the message. modules should not store the value of this
+ // beyond the duration fo this function call. (e.g., the handle
+ // may be invalid after this function call returns.) modules
+ // wishing to hold onto a reference to a "client" should store
+ // the client's ID (see IPC_GetClientID).
+ // target - message target
+ // data - message data
+ // dataLen - message data length
+ //
+ void (* handleMsg) (ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ //
+ // called when a new client connects to the IPC daemon.
+ //
+ void (* clientUp) (ipcClientHandle client);
+
+ //
+ // called when a client disconnects from the IPC daemon.
+ //
+ void (* clientDown) (ipcClientHandle client);
+};
+
+//-----------------------------------------------------------------------------
+// interface implemented by the daemon:
+//-----------------------------------------------------------------------------
+
+//
+// the version of ipcDaemonMethods data structure.
+//
+#define IPC_DAEMON_METHODS_VERSION (1<<16) // 1.0
+
+//
+// enumeration functions may return FALSE to stop enumeration.
+//
+typedef PRBool (* ipcClientEnumFunc) (void *closure, ipcClientHandle client, PRUint32 clientID);
+typedef PRBool (* ipcClientNameEnumFunc) (void *closure, ipcClientHandle client, const char *name);
+typedef PRBool (* ipcClientTargetEnumFunc) (void *closure, ipcClientHandle client, const nsID &target);
+
+//
+// the daemon provides the following structure:
+//
+struct ipcDaemonMethods
+{
+ PRUint32 version;
+
+ //
+ // called to send a message to another module.
+ //
+ // params:
+ // client - identifies the client from which this message originated.
+ // target - message target
+ // data - message data
+ // dataLen - message data length
+ //
+ // returns:
+ // PR_SUCCESS if message was dispatched.
+ // PR_FAILURE if message could not be dispatched (possibly because
+ // no module is registered for the given message target).
+ //
+ PRStatus (* dispatchMsg) (ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ //
+ // called to send a message to a particular client or to broadcast a
+ // message to all clients.
+ //
+ // params:
+ // client - if null, then broadcast message to all clients. otherwise,
+ // send message to the client specified.
+ // target - message target
+ // data - message data
+ // dataLen - message data length
+ //
+ // returns:
+ // PR_SUCCESS if message was sent (or queued up to be sent later).
+ // PR_FAILURE if message could not be sent (possibly because the client
+ // does not have a registered observer for the msg's target).
+ //
+ PRStatus (* sendMsg) (ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ //
+ // called to lookup a client handle given its client ID. each client has
+ // a unique ID.
+ //
+ ipcClientHandle (* getClientByID) (PRUint32 clientID);
+
+ //
+ // called to lookup a client by name or alias. names are not necessary
+ // unique to individual clients. this function returns the client first
+ // registered under the given name.
+ //
+ ipcClientHandle (* getClientByName) (const char *name);
+
+ //
+ // called to enumerate all clients.
+ //
+ void (* enumClients) (ipcClientEnumFunc func, void *closure);
+
+ //
+ // returns the client ID of the specified client.
+ //
+ PRUint32 (* getClientID) (ipcClientHandle client);
+
+ //
+ // functions for inspecting the names and targets defined for a particular
+ // client instance.
+ //
+ PRBool (* clientHasName) (ipcClientHandle client, const char *name);
+ PRBool (* clientHasTarget) (ipcClientHandle client, const nsID &target);
+ void (* enumClientNames) (ipcClientHandle client, ipcClientNameEnumFunc func, void *closure);
+ void (* enumClientTargets) (ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure);
+};
+
+//-----------------------------------------------------------------------------
+// interface exported by a DSO implementing one or more modules:
+//-----------------------------------------------------------------------------
+
+struct ipcModuleEntry
+{
+ //
+ // identifies the message target of this module.
+ //
+ nsID target;
+
+ //
+ // module methods
+ //
+ ipcModuleMethods *methods;
+};
+
+//-----------------------------------------------------------------------------
+
+#define IPC_EXPORT extern "C" NS_EXPORT
+
+//
+// IPC_EXPORT int IPC_GetModules(const ipcDaemonMethods *, const ipcModuleEntry **);
+//
+// params:
+// methods - the daemon's methods
+// entries - the module entries defined by the DSO
+//
+// returns:
+// length of the |entries| array.
+//
+typedef int (* ipcGetModulesFunc) (const ipcDaemonMethods *methods, const ipcModuleEntry **entries);
+
+#endif // !ipcModule_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h
new file mode 100644
index 00000000..0d1703a8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/public/ipcModuleUtil.h
@@ -0,0 +1,151 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcModuleUtil_h__
+#define ipcModuleUtil_h__
+
+#include "prlog.h"
+#include "ipcModule.h"
+
+extern const ipcDaemonMethods *gIPCDaemonMethods;
+
+//-----------------------------------------------------------------------------
+// inline wrapper functions
+//
+// these functions may only be called by a module that uses the
+// IPC_IMPL_GETMODULES macro.
+//-----------------------------------------------------------------------------
+
+inline PRStatus
+IPC_DispatchMsg(ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->dispatchMsg(client, target, data, dataLen);
+}
+
+inline PRStatus
+IPC_SendMsg(ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->sendMsg(client, target, data, dataLen);
+}
+
+inline ipcClientHandle
+IPC_GetClientByID(PRUint32 id)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->getClientByID(id);
+}
+
+inline ipcClientHandle
+IPC_GetClientByName(const char *name)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->getClientByName(name);
+}
+
+inline void
+IPC_EnumClients(ipcClientEnumFunc func, void *closure)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ gIPCDaemonMethods->enumClients(func, closure);
+}
+
+inline PRUint32
+IPC_GetClientID(ipcClientHandle client)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->getClientID(client);
+}
+
+inline PRBool
+IPC_ClientHasName(ipcClientHandle client, const char *name)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->clientHasName(client, name);
+}
+
+inline PRBool
+IPC_ClientHasTarget(ipcClientHandle client, const nsID &target)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ return gIPCDaemonMethods->clientHasTarget(client, target);
+}
+
+inline void
+IPC_EnumClientNames(ipcClientHandle client, ipcClientNameEnumFunc func, void *closure)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ gIPCDaemonMethods->enumClientNames(client, func, closure);
+}
+
+inline void
+IPC_EnumClientTargets(ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure)
+{
+ PR_ASSERT(gIPCDaemonMethods);
+ gIPCDaemonMethods->enumClientTargets(client, func, closure);
+}
+
+//-----------------------------------------------------------------------------
+// inline composite functions
+//-----------------------------------------------------------------------------
+
+inline PRStatus
+IPC_SendMsg(PRUint32 clientID, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ ipcClient *client = IPC_GetClientByID(clientID);
+ if (!client)
+ return PR_FAILURE;
+ return IPC_SendMsg(client, target, data, dataLen);
+}
+
+//-----------------------------------------------------------------------------
+// module factory macros
+//-----------------------------------------------------------------------------
+
+#define IPC_IMPL_GETMODULES(_modName, _modEntries) \
+ const ipcDaemonMethods *gIPCDaemonMethods; \
+ IPC_EXPORT int \
+ IPC_GetModules(const ipcDaemonMethods *dmeths, \
+ const ipcModuleEntry **ents) { \
+ /* XXX do version checking */ \
+ gIPCDaemonMethods = dmeths; \
+ *ents = _modEntries; \
+ return sizeof(_modEntries) / sizeof(ipcModuleEntry); \
+ }
+
+#endif // !ipcModuleUtil_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore
new file mode 100644
index 00000000..8d974b7c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+mozilla-ipcd
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in
new file mode 100644
index 00000000..e9ef6c38
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/Makefile.in
@@ -0,0 +1,88 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+
+# required for #include "nsID.h"
+REQUIRES = \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ ipcd.cpp \
+ ipcClient.cpp \
+ ipcModuleReg.cpp \
+ ipcCommandModule.cpp
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS += ipcdWin.cpp
+else
+ifeq ($(OS_ARCH),BeOS)
+CPPSRCS += ipcdStub.cpp
+else
+CPPSRCS += ipcdUnix.cpp
+endif
+endif
+
+PROGRAM = mozilla-ipcd$(BIN_SUFFIX)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../shared/src \
+ $(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)ipcdshared_s.$(LIB_SUFFIX) \
+ $(EXTRA_DSO_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+# For fruncate
+ifeq ($(OS_ARCH),Linux)
+DEFINES += -D_BSD_SOURCE
+endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp
new file mode 100644
index 00000000..4f68d175
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.cpp
@@ -0,0 +1,235 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "ipcLog.h"
+#include "ipcClient.h"
+#include "ipcMessage.h"
+#include "ipcModuleReg.h"
+#include "ipcd.h"
+#include "ipcm.h"
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+#include "prio.h"
+#endif
+
+PRUint32 ipcClient::gLastID = 0;
+
+//
+// called to initialize this client context
+//
+// assumptions:
+// - object's memory has already been zero'd out.
+//
+void
+ipcClient::Init()
+{
+ mID = ++gLastID;
+
+ // every client must be able to handle IPCM messages.
+ mTargets.Append(IPCM_TARGET);
+
+ // although it is tempting to fire off the NotifyClientUp event at this
+ // time, we must wait until the client sends us a CLIENT_HELLO event.
+ // see ipcCommandModule::OnClientHello.
+}
+
+//
+// called when this client context is going away
+//
+void
+ipcClient::Finalize()
+{
+ IPC_NotifyClientDown(this);
+
+ mNames.DeleteAll();
+ mTargets.DeleteAll();
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ mInMsg.Reset();
+ mOutMsgQ.DeleteAll();
+#endif
+}
+
+void
+ipcClient::AddName(const char *name)
+{
+ LOG(("adding client name: %s\n", name));
+
+ if (HasName(name))
+ return;
+
+ mNames.Append(name);
+}
+
+PRBool
+ipcClient::DelName(const char *name)
+{
+ LOG(("deleting client name: %s\n", name));
+
+ return mNames.FindAndDelete(name);
+}
+
+void
+ipcClient::AddTarget(const nsID &target)
+{
+ LOG(("adding client target\n"));
+
+ if (HasTarget(target))
+ return;
+
+ mTargets.Append(target);
+}
+
+PRBool
+ipcClient::DelTarget(const nsID &target)
+{
+ LOG(("deleting client target\n"));
+
+ //
+ // cannot remove the IPCM target
+ //
+ if (!target.Equals(IPCM_TARGET))
+ return mTargets.FindAndDelete(target);
+
+ return PR_FALSE;
+}
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+
+//
+// called to process a client socket
+//
+// params:
+// fd - the client socket
+// poll_flags - the state of the client socket
+//
+// return:
+// 0 - to end session with this client
+// PR_POLL_READ - to wait for the client socket to become readable
+// PR_POLL_WRITE - to wait for the client socket to become writable
+//
+int
+ipcClient::Process(PRFileDesc *fd, int inFlags)
+{
+ if (inFlags & (PR_POLL_ERR | PR_POLL_HUP |
+ PR_POLL_EXCEPT | PR_POLL_NVAL)) {
+ LOG(("client socket appears to have closed\n"));
+ return 0;
+ }
+
+ // expect to wait for more data
+ int outFlags = PR_POLL_READ;
+
+ if (inFlags & PR_POLL_READ) {
+ LOG(("client socket is now readable\n"));
+
+ char buf[1024]; // XXX make this larger?
+ PRInt32 n;
+
+ // find out how much data is available for reading...
+ // n = PR_Available(fd);
+
+ n = PR_Read(fd, buf, sizeof(buf));
+ if (n <= 0)
+ return 0; // cancel connection
+
+ const char *ptr = buf;
+ while (n) {
+ PRUint32 nread;
+ PRBool complete;
+
+ if (mInMsg.ReadFrom(ptr, PRUint32(n), &nread, &complete) == PR_FAILURE) {
+ LOG(("message appears to be malformed; dropping client connection\n"));
+ return 0;
+ }
+
+ if (complete) {
+ IPC_DispatchMsg(this, &mInMsg);
+ mInMsg.Reset();
+ }
+
+ n -= nread;
+ ptr += nread;
+ }
+ }
+
+ if (inFlags & PR_POLL_WRITE) {
+ LOG(("client socket is now writable\n"));
+
+ if (mOutMsgQ.First())
+ WriteMsgs(fd);
+ }
+
+ if (mOutMsgQ.First())
+ outFlags |= PR_POLL_WRITE;
+
+ return outFlags;
+}
+
+//
+// called to write out any messages from the outgoing queue.
+//
+int
+ipcClient::WriteMsgs(PRFileDesc *fd)
+{
+ while (mOutMsgQ.First()) {
+ const char *buf = (const char *) mOutMsgQ.First()->MsgBuf();
+ PRInt32 bufLen = (PRInt32) mOutMsgQ.First()->MsgLen();
+
+ if (mSendOffset) {
+ buf += mSendOffset;
+ bufLen -= mSendOffset;
+ }
+
+ PRInt32 nw = PR_Write(fd, buf, bufLen);
+ if (nw <= 0)
+ break;
+
+ LOG(("wrote %d bytes\n", nw));
+
+ if (nw == bufLen) {
+ mOutMsgQ.DeleteFirst();
+ mSendOffset = 0;
+ }
+ else
+ mSendOffset += nw;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h
new file mode 100644
index 00000000..12e479cf
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcClient.h
@@ -0,0 +1,144 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcClientUnix_h__
+#define ipcClientUnix_h__
+
+#include "prio.h"
+#include "ipcMessageQ.h"
+#include "ipcStringList.h"
+#include "ipcIDList.h"
+
+#ifdef XP_WIN
+#include <windows.h>
+#endif
+
+//-----------------------------------------------------------------------------
+// ipcClient
+//
+// NOTE: this class is an implementation detail of the IPC daemon. IPC daemon
+// modules (other than the built-in IPCM module) must not access methods on
+// this class directly. use the API provided via ipcd.h instead.
+//-----------------------------------------------------------------------------
+
+class ipcClient
+{
+public:
+ void Init();
+ void Finalize();
+
+ PRUint32 ID() const { return mID; }
+
+ void AddName(const char *name);
+ PRBool DelName(const char *name);
+ PRBool HasName(const char *name) const { return mNames.Find(name) != NULL; }
+
+ void AddTarget(const nsID &target);
+ PRBool DelTarget(const nsID &target);
+ PRBool HasTarget(const nsID &target) const { return mTargets.Find(target) != NULL; }
+
+ // list iterators
+ const ipcStringNode *Names() const { return mNames.First(); }
+ const ipcIDNode *Targets() const { return mTargets.First(); }
+
+ // returns primary client name (the one specified in the "client hello" message)
+ const char *PrimaryName() const { return mNames.First() ? mNames.First()->Value() : NULL; }
+
+ void SetExpectsSyncReply(PRBool val) { mExpectsSyncReply = val; }
+ PRBool GetExpectsSyncReply() const { return mExpectsSyncReply; }
+
+#ifdef XP_WIN
+ PRUint32 PID() const { return mPID; }
+ void SetPID(PRUint32 pid) { mPID = pid; }
+
+ HWND Hwnd() const { return mHwnd; }
+ void SetHwnd(HWND hwnd) { mHwnd = hwnd; }
+#endif
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ //
+ // called to process a client file descriptor. the value of pollFlags
+ // indicates the state of the socket.
+ //
+ // returns:
+ // 0 - to cancel client connection
+ // PR_POLL_READ - to poll for a readable socket
+ // PR_POLL_WRITE - to poll for a writable socket
+ // (both flags) - to poll for either a readable or writable socket
+ //
+ // the socket is non-blocking.
+ //
+ int Process(PRFileDesc *sockFD, int pollFlags);
+
+ //
+ // on success or failure, this function takes ownership of |msg| and will
+ // delete it when appropriate.
+ //
+ void EnqueueOutboundMsg(ipcMessage *msg) { mOutMsgQ.Append(msg); }
+#endif
+
+private:
+ static PRUint32 gLastID;
+
+ PRUint32 mID;
+ ipcStringList mNames;
+ ipcIDList mTargets;
+ PRBool mExpectsSyncReply;
+
+#ifdef XP_WIN
+ // on windows, we store the PID of the client process to help us determine
+ // the client from which a message originated. each message has the PID
+ // encoded in it.
+ PRUint32 mPID;
+
+ // the hwnd of the client's message window.
+ HWND mHwnd;
+#endif
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ ipcMessage mInMsg; // buffer for incoming message
+ ipcMessageQ mOutMsgQ; // outgoing message queue
+
+ // keep track of the amount of the first message sent
+ PRUint32 mSendOffset;
+
+ // utility function for writing out messages.
+ int WriteMsgs(PRFileDesc *fd);
+#endif
+};
+
+#endif // !ipcClientUnix_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp
new file mode 100644
index 00000000..43ac547c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.cpp
@@ -0,0 +1,316 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <stdlib.h>
+#include <string.h>
+#include "ipcLog.h"
+#include "ipcCommandModule.h"
+#include "ipcModule.h"
+#include "ipcClient.h"
+#include "ipcMessage.h"
+#include "ipcMessageUtils.h"
+#include "ipcModuleReg.h"
+#include "ipcd.h"
+#include "ipcm.h"
+
+struct ipcCommandModule
+{
+ typedef void (* MsgHandler)(ipcClient *, const ipcMessage *);
+
+ //
+ // helpers
+ //
+
+ static char **
+ BuildStringArray(const ipcStringNode *nodes)
+ {
+ size_t count = 0;
+
+ const ipcStringNode *node;
+
+ for (node = nodes; node; node = node->mNext)
+ count++;
+
+ char **strs = (char **) malloc((count + 1) * sizeof(char *));
+ if (!strs)
+ return NULL;
+
+ count = 0;
+ for (node = nodes; node; node = node->mNext, ++count)
+ strs[count] = (char *) node->Value();
+ strs[count] = 0;
+
+ return strs;
+ }
+
+ static nsID **
+ BuildIDArray(const ipcIDNode *nodes)
+ {
+ size_t count = 0;
+
+ const ipcIDNode *node;
+
+ for (node = nodes; node; node = node->mNext)
+ count++;
+
+ nsID **ids = (nsID **) calloc(count + 1, sizeof(nsID *));
+ if (!ids)
+ return NULL;
+
+ count = 0;
+ for (node = nodes; node; node = node->mNext, ++count)
+ ids[count] = (nsID *) &node->Value();
+
+ return ids;
+ }
+
+ //
+ // message handlers
+ //
+
+ static void
+ OnPing(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got PING\n"));
+
+ IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
+ }
+
+ static void
+ OnClientHello(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_HELLO\n"));
+
+ IPC_SendMsg(client, new ipcmMessageClientID(IPCM_GetRequestIndex(rawMsg), client->ID()));
+
+ //
+ // NOTE: it would almost make sense for this notification to live
+ // in the transport layer code. however, clients expect to receive
+ // a CLIENT_ID as the first message following a CLIENT_HELLO, so we
+ // must not allow modules to see a client until after we have sent
+ // the CLIENT_ID message.
+ //
+ IPC_NotifyClientUp(client);
+ }
+
+ static void
+ OnClientAddName(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_ADD_NAME\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientAddName> msg(rawMsg);
+ const char *name = msg->Name();
+ if (name) {
+ ipcClient *result = IPC_GetClientByName(msg->Name());
+ if (result) {
+ LOG((" client with such name already exists (ID = %d)\n", result->ID()));
+ status = IPCM_ERROR_ALREADY_EXISTS;
+ }
+ else
+ client->AddName(name);
+ }
+ else
+ status = IPCM_ERROR_INVALID_ARG;
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnClientDelName(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_DEL_NAME\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientDelName> msg(rawMsg);
+ const char *name = msg->Name();
+ if (name) {
+ if (!client->DelName(name)) {
+ LOG((" client doesn't have name '%s'\n", name));
+ status = IPCM_ERROR_NO_SUCH_DATA;
+ }
+ }
+ else
+ status = IPCM_ERROR_INVALID_ARG;
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnClientAddTarget(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_ADD_TARGET\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientAddTarget> msg(rawMsg);
+ if (client->HasTarget(msg->Target())) {
+ LOG((" target already defined for client\n"));
+ status = IPCM_ERROR_ALREADY_EXISTS;
+ }
+ else
+ client->AddTarget(msg->Target());
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnClientDelTarget(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got CLIENT_DEL_TARGET\n"));
+
+ PRInt32 status = IPCM_OK;
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageClientDelTarget> msg(rawMsg);
+ if (!client->DelTarget(msg->Target())) {
+ LOG((" client doesn't have the given target\n"));
+ status = IPCM_ERROR_NO_SUCH_DATA;
+ }
+
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, status));
+ }
+
+ static void
+ OnQueryClientByName(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got QUERY_CLIENT_BY_NAME\n"));
+
+ PRUint32 requestIndex = IPCM_GetRequestIndex(rawMsg);
+
+ ipcMessageCast<ipcmMessageQueryClientByName> msg(rawMsg);
+
+ ipcClient *result = IPC_GetClientByName(msg->Name());
+ if (result) {
+ LOG((" client exists w/ ID = %u\n", result->ID()));
+ IPC_SendMsg(client, new ipcmMessageClientID(requestIndex, result->ID()));
+ }
+ else {
+ LOG((" client does not exist\n"));
+ IPC_SendMsg(client, new ipcmMessageResult(requestIndex, IPCM_ERROR_NO_CLIENT));
+ }
+ }
+
+#if 0
+ static void
+ OnQueryClientInfo(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got QUERY_CLIENT_INFO\n"));
+
+ ipcMessageCast<ipcmMessageQueryClientInfo> msg(rawMsg);
+ ipcClient *result = IPC_GetClientByID(msg->ClientID());
+ if (result) {
+ char **names = BuildStringArray(result->Names());
+ nsID **targets = BuildIDArray(result->Targets());
+
+ IPC_SendMsg(client, new ipcmMessageClientInfo(result->ID(),
+ msg->RequestIndex(),
+ (const char **) names,
+ (const nsID **) targets));
+
+ free(names);
+ free(targets);
+ }
+ else {
+ LOG((" client does not exist\n"));
+ IPC_SendMsg(client, new ipcmMessageError(IPCM_ERROR_NO_CLIENT, msg->RequestIndex()));
+ }
+ }
+#endif
+
+ static void
+ OnForward(ipcClient *client, const ipcMessage *rawMsg)
+ {
+ LOG(("got FORWARD\n"));
+
+ ipcMessageCast<ipcmMessageForward> msg(rawMsg);
+
+ ipcClient *dest = IPC_GetClientByID(msg->ClientID());
+ if (!dest) {
+ LOG((" destination client not found!\n"));
+ IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_ERROR_NO_CLIENT));
+ return;
+ }
+ // inform client that its message will be forwarded
+ IPC_SendMsg(client, new ipcmMessageResult(IPCM_GetRequestIndex(rawMsg), IPCM_OK));
+
+ ipcMessage *newMsg = new ipcmMessageForward(IPCM_MSG_PSH_FORWARD,
+ client->ID(),
+ msg->InnerTarget(),
+ msg->InnerData(),
+ msg->InnerDataLen());
+ IPC_SendMsg(dest, newMsg);
+ }
+};
+
+void
+IPCM_HandleMsg(ipcClient *client, const ipcMessage *rawMsg)
+{
+ static ipcCommandModule::MsgHandler handlers[] =
+ {
+ ipcCommandModule::OnPing,
+ ipcCommandModule::OnForward,
+ ipcCommandModule::OnClientHello,
+ ipcCommandModule::OnClientAddName,
+ ipcCommandModule::OnClientDelName,
+ ipcCommandModule::OnClientAddTarget,
+ ipcCommandModule::OnClientDelTarget,
+ ipcCommandModule::OnQueryClientByName
+ };
+
+ int type = IPCM_GetType(rawMsg);
+ LOG(("IPCM_HandleMsg [type=%x]\n", type));
+
+ if (!(type & IPCM_MSG_CLASS_REQ)) {
+ LOG(("not a request -- ignoring message\n"));
+ return;
+ }
+
+ type &= ~IPCM_MSG_CLASS_REQ;
+ type--;
+ if (type < 0 || type >= (int) (sizeof(handlers)/sizeof(handlers[0]))) {
+ LOG(("unknown request -- ignoring message\n"));
+ return;
+ }
+
+ (handlers[type])(client, rawMsg);
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h
new file mode 100644
index 00000000..ea146cdc
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcCommandModule.h
@@ -0,0 +1,48 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcCommandModule_h__
+#define ipcCommandModule_h__
+
+#include "ipcm.h" // for IPCM_TARGET
+
+class ipcClient;
+class ipcMessage;
+
+void IPCM_HandleMsg(ipcClient *, const ipcMessage *);
+
+#endif // !ipcCommandModule_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp
new file mode 100644
index 00000000..09e60ab9
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.cpp
@@ -0,0 +1,245 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <string.h>
+#include <stdlib.h>
+
+#include "prlink.h"
+#include "prio.h"
+#include "prlog.h"
+#include "plstr.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcModuleReg.h"
+#include "ipcModule.h"
+#include "ipcCommandModule.h"
+#include "ipcd.h"
+
+//-----------------------------------------------------------------------------
+
+struct ipcModuleRegEntry
+{
+ nsID target;
+ ipcModuleMethods *methods;
+ PRLibrary *lib;
+};
+
+#define IPC_MAX_MODULE_COUNT 64
+
+static ipcModuleRegEntry ipcModules[IPC_MAX_MODULE_COUNT];
+static int ipcModuleCount = 0;
+
+//-----------------------------------------------------------------------------
+
+static PRStatus
+AddModule(const nsID &target, ipcModuleMethods *methods, const char *libPath)
+{
+ if (ipcModuleCount == IPC_MAX_MODULE_COUNT) {
+ LOG(("too many modules!\n"));
+ return PR_FAILURE;
+ }
+
+ if (!methods) {
+ PR_NOT_REACHED("null module methods");
+ return PR_FAILURE;
+ }
+
+ //
+ // each ipcModuleRegEntry holds a reference to a PRLibrary, and on
+ // shutdown, each PRLibrary reference will be released. this ensures
+ // that the library will not be unloaded until all of the modules in
+ // that library are shutdown.
+ //
+ ipcModules[ipcModuleCount].target = target;
+ ipcModules[ipcModuleCount].methods = methods;
+ ipcModules[ipcModuleCount].lib = PR_LoadLibrary(libPath);
+
+ ++ipcModuleCount;
+ return PR_SUCCESS;
+}
+
+static void
+InitModuleFromLib(const char *modulesDir, const char *fileName)
+{
+ LOG(("InitModuleFromLib [%s]\n", fileName));
+
+ static const ipcDaemonMethods gDaemonMethods =
+ {
+ IPC_DAEMON_METHODS_VERSION,
+ IPC_DispatchMsg,
+ IPC_SendMsg,
+ IPC_GetClientByID,
+ IPC_GetClientByName,
+ IPC_EnumClients,
+ IPC_GetClientID,
+ IPC_ClientHasName,
+ IPC_ClientHasTarget,
+ IPC_EnumClientNames,
+ IPC_EnumClientTargets
+ };
+
+ int dLen = strlen(modulesDir);
+ int fLen = strlen(fileName);
+
+ char *buf = (char *) malloc(dLen + 1 + fLen + 1);
+ memcpy(buf, modulesDir, dLen);
+ buf[dLen] = IPC_PATH_SEP_CHAR;
+ memcpy(buf + dLen + 1, fileName, fLen);
+ buf[dLen + 1 + fLen] = '\0';
+
+ PRLibrary *lib = PR_LoadLibrary(buf);
+ if (lib) {
+ ipcGetModulesFunc func =
+ (ipcGetModulesFunc) PR_FindFunctionSymbol(lib, "IPC_GetModules");
+
+ LOG((" func=%p\n", (void*) func));
+
+ if (func) {
+ const ipcModuleEntry *entries = NULL;
+ int count = func(&gDaemonMethods, &entries);
+ for (int i=0; i<count; ++i) {
+ if (AddModule(entries[i].target, entries[i].methods, buf) == PR_SUCCESS) {
+ if (entries[i].methods->init)
+ entries[i].methods->init();
+ }
+ }
+ }
+ PR_UnloadLibrary(lib);
+ }
+
+ free(buf);
+}
+
+//-----------------------------------------------------------------------------
+// ipcModuleReg API
+//-----------------------------------------------------------------------------
+
+void
+IPC_InitModuleReg(const char *exePath)
+{
+ if (!(exePath && *exePath))
+ return;
+
+ //
+ // register plug-in modules
+ //
+ char *p = PL_strrchr(exePath, IPC_PATH_SEP_CHAR);
+ if (p == NULL) {
+ LOG(("unexpected exe path\n"));
+ return;
+ }
+
+ int baseLen = p - exePath;
+ int finalLen = baseLen + 1 + sizeof(IPC_MODULES_DIR);
+
+ // build full path to ipc modules
+ char *modulesDir = (char*) malloc(finalLen);
+ memcpy(modulesDir, exePath, baseLen);
+ modulesDir[baseLen] = IPC_PATH_SEP_CHAR;
+ memcpy(modulesDir + baseLen + 1, IPC_MODULES_DIR, sizeof(IPC_MODULES_DIR));
+
+ LOG(("loading libraries in %s\n", modulesDir));
+ //
+ // scan directory for IPC modules
+ //
+ PRDir *dir = PR_OpenDir(modulesDir);
+ if (dir) {
+ PRDirEntry *ent;
+ while ((ent = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ //
+ // locate extension, and check if dynamic library
+ //
+
+ const char *p = strrchr(ent->name, '.');
+ if (p && PL_strcasecmp(p, MOZ_DLL_SUFFIX) == 0)
+ InitModuleFromLib(modulesDir, ent->name);
+ }
+ PR_CloseDir(dir);
+ }
+
+ free(modulesDir);
+}
+
+void
+IPC_ShutdownModuleReg()
+{
+ //
+ // shutdown modules in reverse order
+ //
+ while (ipcModuleCount) {
+ ipcModuleRegEntry &entry = ipcModules[--ipcModuleCount];
+ if (entry.methods->shutdown)
+ entry.methods->shutdown();
+ if (entry.lib)
+ PR_UnloadLibrary(entry.lib);
+ }
+}
+
+void
+IPC_NotifyModulesClientUp(ipcClient *client)
+{
+ for (int i = 0; i < ipcModuleCount; ++i) {
+ ipcModuleRegEntry &entry = ipcModules[i];
+ if (entry.methods->clientUp)
+ entry.methods->clientUp(client);
+ }
+}
+
+void
+IPC_NotifyModulesClientDown(ipcClient *client)
+{
+ for (int i = 0; i < ipcModuleCount; ++i) {
+ ipcModuleRegEntry &entry = ipcModules[i];
+ if (entry.methods->clientDown)
+ entry.methods->clientDown(client);
+ }
+}
+
+PRStatus
+IPC_DispatchMsg(ipcClient *client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ // dispatch message to every module registered under the given target.
+ for (int i=0; i<ipcModuleCount; ++i) {
+ ipcModuleRegEntry &entry = ipcModules[i];
+ if (entry.target.Equals(target)) {
+ if (entry.methods->handleMsg)
+ entry.methods->handleMsg(client, target, data, dataLen);
+ }
+ }
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h
new file mode 100644
index 00000000..d3fecd6c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcModuleReg.h
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcModuleReg_h__
+#define ipcModuleReg_h__
+
+#include "ipcModule.h"
+
+//
+// called to init the module registry. this may only be called once at
+// startup or once after calling IPC_ShutdownModuleReg.
+//
+// params:
+// exePath - path to the daemon executable. modules are loaded from a
+// directory relative to the daemon executable.
+//
+void IPC_InitModuleReg(const char *exePath);
+
+//
+// called to shutdown the module registry. this may be called more than
+// once and need not follow a call to IPC_InitModuleReg.
+//
+void IPC_ShutdownModuleReg();
+
+//
+// returns the ipcModuleMethods for the given target.
+//
+ipcModuleMethods *IPC_GetModuleByTarget(const nsID &target);
+
+//
+// notifies all modules of client connect/disconnect
+//
+void IPC_NotifyModulesClientUp(ipcClient *);
+void IPC_NotifyModulesClientDown(ipcClient *);
+
+#endif // !ipcModuleReg_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp
new file mode 100644
index 00000000..60aca34a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.cpp
@@ -0,0 +1,235 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "prlog.h"
+#include "prio.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcMessage.h"
+#include "ipcClient.h"
+#include "ipcModuleReg.h"
+#include "ipcModule.h"
+#include "ipcCommandModule.h"
+#include "ipcdPrivate.h"
+#include "ipcd.h"
+
+//-----------------------------------------------------------------------------
+
+void
+IPC_NotifyParent()
+{
+ PRFileDesc *fd = PR_GetInheritedFD(IPC_STARTUP_PIPE_NAME);
+ if (fd) {
+ char c = IPC_STARTUP_PIPE_MAGIC;
+ PR_Write(fd, &c, 1);
+ PR_Close(fd);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_DispatchMsg(ipcClient *client, const ipcMessage *msg)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(msg);
+
+ // remember if client is expecting SYNC_REPLY. we'll add that flag to the
+ // next message sent to the client.
+ if (msg->TestFlag(IPC_MSG_FLAG_SYNC_QUERY)) {
+ PR_ASSERT(client->GetExpectsSyncReply() == PR_FALSE);
+ // XXX shouldn't we remember the TargetID as well, and only set the
+ // SYNC_REPLY flag on the next message sent to the same TargetID?
+ client->SetExpectsSyncReply(PR_TRUE);
+ }
+
+ if (msg->Target().Equals(IPCM_TARGET)) {
+ IPCM_HandleMsg(client, msg);
+ return PR_SUCCESS;
+ }
+
+ return IPC_DispatchMsg(client, msg->Target(), msg->Data(), msg->DataLen());
+}
+
+PRStatus
+IPC_SendMsg(ipcClient *client, ipcMessage *msg)
+{
+ PR_ASSERT(msg);
+
+ if (client == NULL) {
+ //
+ // broadcast
+ //
+ for (int i=0; i<ipcClientCount; ++i)
+ IPC_SendMsg(&ipcClients[i], msg->Clone());
+ delete msg;
+ return PR_SUCCESS;
+ }
+
+ // add SYNC_REPLY flag to message if client is expecting...
+ if (client->GetExpectsSyncReply()) {
+ msg->SetFlag(IPC_MSG_FLAG_SYNC_REPLY);
+ client->SetExpectsSyncReply(PR_FALSE);
+ }
+
+ if (client->HasTarget(msg->Target()))
+ return IPC_PlatformSendMsg(client, msg);
+
+ LOG((" no registered message handler\n"));
+ return PR_FAILURE;
+}
+
+void
+IPC_NotifyClientUp(ipcClient *client)
+{
+ LOG(("IPC_NotifyClientUp: clientID=%d\n", client->ID()));
+
+ // notify modules before other clients
+ IPC_NotifyModulesClientUp(client);
+
+ for (int i=0; i<ipcClientCount; ++i) {
+ if (&ipcClients[i] != client)
+ IPC_SendMsg(&ipcClients[i],
+ new ipcmMessageClientState(client->ID(), IPCM_CLIENT_STATE_UP));
+ }
+}
+
+void
+IPC_NotifyClientDown(ipcClient *client)
+{
+ LOG(("IPC_NotifyClientDown: clientID=%d\n", client->ID()));
+
+ // notify modules before other clients
+ IPC_NotifyModulesClientDown(client);
+
+ for (int i=0; i<ipcClientCount; ++i) {
+ if (&ipcClients[i] != client)
+ IPC_SendMsg(&ipcClients[i],
+ new ipcmMessageClientState(client->ID(), IPCM_CLIENT_STATE_DOWN));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// IPC daemon methods
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_SendMsg(ipcClient *client, const nsID &target, const void *data, PRUint32 dataLen)
+{
+ return IPC_SendMsg(client, new ipcMessage(target, (const char *) data, dataLen));
+}
+
+ipcClient *
+IPC_GetClientByID(PRUint32 clientID)
+{
+ // linear search OK since number of clients should be small
+ for (int i = 0; i < ipcClientCount; ++i) {
+ if (ipcClients[i].ID() == clientID)
+ return &ipcClients[i];
+ }
+ return NULL;
+}
+
+ipcClient *
+IPC_GetClientByName(const char *name)
+{
+ // linear search OK since number of clients should be small
+ for (int i = 0; i < ipcClientCount; ++i) {
+ if (ipcClients[i].HasName(name))
+ return &ipcClients[i];
+ }
+ return NULL;
+}
+
+void
+IPC_EnumClients(ipcClientEnumFunc func, void *closure)
+{
+ PR_ASSERT(func);
+ for (int i = 0; i < ipcClientCount; ++i) {
+ if (func(closure, &ipcClients[i], ipcClients[i].ID()) == PR_FALSE)
+ break;
+ }
+}
+
+PRUint32
+IPC_GetClientID(ipcClient *client)
+{
+ PR_ASSERT(client);
+ return client->ID();
+}
+
+PRBool
+IPC_ClientHasName(ipcClient *client, const char *name)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(name);
+ return client->HasName(name);
+}
+
+PRBool
+IPC_ClientHasTarget(ipcClient *client, const nsID &target)
+{
+ PR_ASSERT(client);
+ return client->HasTarget(target);
+}
+
+void
+IPC_EnumClientNames(ipcClient *client, ipcClientNameEnumFunc func, void *closure)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(func);
+ const ipcStringNode *node = client->Names();
+ while (node) {
+ if (func(closure, client, node->Value()) == PR_FALSE)
+ break;
+ node = node->mNext;
+ }
+}
+
+void
+IPC_EnumClientTargets(ipcClient *client, ipcClientTargetEnumFunc func, void *closure)
+{
+ PR_ASSERT(client);
+ PR_ASSERT(func);
+ const ipcIDNode *node = client->Targets();
+ while (node) {
+ if (func(closure, client, node->Value()) == PR_FALSE)
+ break;
+ node = node->mNext;
+ }
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h
new file mode 100644
index 00000000..5a0f2c2a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcd.h
@@ -0,0 +1,82 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef IPCD_H__
+#define IPCD_H__
+
+#include "ipcModule.h"
+#include "ipcMessage.h"
+
+//-----------------------------------------------------------------------------
+// IPC daemon methods (see struct ipcDaemonMethods)
+//
+// these functions may only be called directly from within the daemon. plug-in
+// modules must access these through the ipcDaemonMethods structure.
+//-----------------------------------------------------------------------------
+
+PRStatus IPC_DispatchMsg (ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen);
+PRStatus IPC_SendMsg (ipcClientHandle client, const nsID &target, const void *data, PRUint32 dataLen);
+ipcClientHandle IPC_GetClientByID (PRUint32 id);
+ipcClientHandle IPC_GetClientByName (const char *name);
+void IPC_EnumClients (ipcClientEnumFunc func, void *closure);
+PRUint32 IPC_GetClientID (ipcClientHandle client);
+PRBool IPC_ClientHasName (ipcClientHandle client, const char *name);
+PRBool IPC_ClientHasTarget (ipcClientHandle client, const nsID &target);
+void IPC_EnumClientNames (ipcClientHandle client, ipcClientNameEnumFunc func, void *closure);
+void IPC_EnumClientTargets (ipcClientHandle client, ipcClientTargetEnumFunc func, void *closure);
+
+//-----------------------------------------------------------------------------
+// other internal IPCD methods
+//-----------------------------------------------------------------------------
+
+//
+// dispatch message
+//
+PRStatus IPC_DispatchMsg(ipcClientHandle client, const ipcMessage *msg);
+
+//
+// send message, takes ownership of |msg|.
+//
+PRStatus IPC_SendMsg(ipcClientHandle client, ipcMessage *msg);
+
+//
+// dispatch notifications about client connects and disconnects
+//
+void IPC_NotifyClientUp(ipcClientHandle client);
+void IPC_NotifyClientDown(ipcClientHandle client);
+
+#endif // !IPCD_H__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h
new file mode 100644
index 00000000..023b3a03
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h
@@ -0,0 +1,65 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcdPrivate_h__
+#define ipcdPrivate_h__
+
+class ipcClient;
+
+//
+// upper limit on the number of active connections
+// XXX may want to make this more dynamic
+//
+#define IPC_MAX_CLIENTS 10000
+
+//
+// array of connected clients
+//
+extern ipcClient *ipcClients;
+extern int ipcClientCount;
+
+//
+// platform specific send message function, takes ownership of |msg|.
+//
+PRStatus IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg);
+
+//
+// notify parent that it can connect to the daemon.
+//
+void IPC_NotifyParent();
+
+#endif // !ipcdPrivate_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp
new file mode 100644
index 00000000..10618110
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdStub.cpp
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "ipcd.h"
+#include "ipcdPrivate.h"
+#include "ipcLog.h"
+
+#include "prerror.h"
+
+//-----------------------------------------------------------------------------
+// use this file as a template to add server-side IPC connectivity.
+//
+// NOTE: if your platform supports local domain TCP sockets, then you should
+// be able to make use of ipcConnectionUnix.cpp.
+//-----------------------------------------------------------------------------
+
+// these variables are declared in ipcdPrivate.h and must be initialized by
+// when the daemon starts up.
+ipcClient *ipcClients = NULL;
+int ipcClientCount = 0;
+
+PRStatus
+IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg)
+{
+ const char notimplemented[] = "IPC_PlatformSendMsg not implemented";
+ PR_SetErrorText(sizeof(notimplemented), notimplemented);
+ return PR_FAILURE;
+}
+
+int main(int argc, char **argv)
+{
+ IPC_InitLog("###");
+
+ LOG(("daemon started...\n"));
+
+ /*
+ IPC_InitModuleReg(argv[0]);
+ IPC_ShutdownModuleReg();
+ */
+
+ // let the parent process know that we are up-and-running
+ IPC_NotifyParent();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp
new file mode 100644
index 00000000..026e9e52
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp
@@ -0,0 +1,600 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(VBOX) && !defined(XP_OS2)
+# include <sys/resource.h>
+# include <errno.h>
+#endif
+
+#ifdef VBOX
+# include <iprt/initterm.h>
+#endif
+
+#include "prio.h"
+#include "prerror.h"
+#include "prthread.h"
+#include "prinrval.h"
+#include "plstr.h"
+#include "prprf.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcMessage.h"
+#include "ipcClient.h"
+#include "ipcModuleReg.h"
+#include "ipcdPrivate.h"
+#include "ipcd.h"
+
+#if 0
+static void
+IPC_Sleep(int seconds)
+{
+ while (seconds > 0) {
+ LOG(("\rsleeping for %d seconds...", seconds));
+ PR_Sleep(PR_SecondsToInterval(1));
+ --seconds;
+ }
+ LOG(("\ndone sleeping\n"));
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// ipc directory and locking...
+//-----------------------------------------------------------------------------
+
+//
+// advisory file locking is used to ensure that only one IPC daemon is active
+// and bound to the local domain socket at a time.
+//
+// XXX this code does not work on OS/2.
+//
+#if !defined(XP_OS2)
+#define IPC_USE_FILE_LOCK
+#endif
+
+#ifdef IPC_USE_FILE_LOCK
+
+enum Status
+{
+ EOk = 0,
+ ELockFileOpen = -1,
+ ELockFileLock = -2,
+ ELockFileOwner = -3,
+};
+
+static int ipcLockFD = 0;
+
+static Status AcquireDaemonLock(const char *baseDir)
+{
+ const char lockName[] = "lock";
+
+ int dirLen = strlen(baseDir);
+ int len = dirLen // baseDir
+ + 1 // "/"
+ + sizeof(lockName); // "lock"
+
+ char *lockFile = (char *) malloc(len);
+ memcpy(lockFile, baseDir, dirLen);
+ lockFile[dirLen] = '/';
+ memcpy(lockFile + dirLen + 1, lockName, sizeof(lockName));
+
+#ifdef VBOX
+ //
+ // Security checks for the directory
+ //
+ struct stat st;
+ if (stat(baseDir, &st) == -1)
+ {
+ printf("Cannot stat '%s'.\n", baseDir);
+ return ELockFileOwner;
+ }
+
+ if (st.st_uid != getuid() && st.st_uid != geteuid())
+ {
+ printf("Wrong owner (%d) of '%s'", st.st_uid, baseDir);
+ if ( !stat("/tmp", &st)
+ && (st.st_mode & 07777) != 01777)
+ printf(" -- check /tmp permissions (%o should be 1777)\n",
+ st.st_mode & 07777);
+ printf(".\n");
+ return ELockFileOwner;
+ }
+
+ if (st.st_mode != (S_IRUSR | S_IWUSR | S_IXUSR | S_IFDIR))
+ {
+ printf("Wrong mode (%o) of '%s'", st.st_mode, baseDir);
+ if ( !stat("/tmp", &st)
+ && (st.st_mode & 07777) != 01777)
+ printf(" -- check /tmp permissions (%o should be 1777)\n",
+ st.st_mode & 07777);
+ printf(".\n");
+ return ELockFileOwner;
+ }
+#endif
+
+ //
+ // open lock file. it remains open until we shutdown.
+ //
+ ipcLockFD = open(lockFile, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR);
+
+#ifndef VBOX
+ free(lockFile);
+#endif
+
+ if (ipcLockFD == -1)
+ return ELockFileOpen;
+
+#ifdef VBOX
+ //
+ // Security checks for the lock file
+ //
+ if (fstat(ipcLockFD, &st) == -1)
+ {
+ printf("Cannot stat '%s'.\n", lockFile);
+ free(lockFile);
+ return ELockFileOwner;
+ }
+
+ if (st.st_uid != getuid() && st.st_uid != geteuid())
+ {
+ printf("Wrong owner (%d) of '%s'.\n", st.st_uid, lockFile);
+ free(lockFile);
+ return ELockFileOwner;
+ }
+
+ if (st.st_mode != (S_IRUSR | S_IWUSR | S_IFREG))
+ {
+ printf("Wrong mode (%o) of '%s'.\n", st.st_mode, lockFile);
+ free(lockFile);
+ return ELockFileOwner;
+ }
+
+ free(lockFile);
+#endif
+
+ //
+ // we use fcntl for locking. assumption: filesystem should be local.
+ // this API is nice because the lock will be automatically released
+ // when the process dies. it will also be released when the file
+ // descriptor is closed.
+ //
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ lock.l_whence = SEEK_SET;
+ if (fcntl(ipcLockFD, F_SETLK, &lock) == -1)
+ return ELockFileLock;
+
+ //
+ // truncate lock file once we have exclusive access to it.
+ //
+ ftruncate(ipcLockFD, 0);
+
+ //
+ // write our PID into the lock file (this just seems like a good idea...
+ // no real purpose otherwise).
+ //
+ char buf[32];
+ int nb = PR_snprintf(buf, sizeof(buf), "%u\n", (unsigned long) getpid());
+ write(ipcLockFD, buf, nb);
+
+ return EOk;
+}
+
+static Status InitDaemonDir(const char *socketPath)
+{
+ LOG(("InitDaemonDir [sock=%s]\n", socketPath));
+
+ char *baseDir = PL_strdup(socketPath);
+
+ //
+ // make sure IPC directory exists (XXX this should be recursive)
+ //
+ char *p = strrchr(baseDir, '/');
+ if (p)
+ p[0] = '\0';
+ mkdir(baseDir, 0700);
+
+ //
+ // if we can't acquire the daemon lock, then another daemon
+ // must be active, so bail.
+ //
+ Status status = AcquireDaemonLock(baseDir);
+
+ PL_strfree(baseDir);
+
+ if (status == EOk) {
+ // delete an existing socket to prevent bind from failing.
+ unlink(socketPath);
+ }
+ return status;
+}
+
+static void ShutdownDaemonDir()
+{
+ LOG(("ShutdownDaemonDir\n"));
+
+ // deleting directory and files underneath it allows another process
+ // to think it has exclusive access. better to just leave the hidden
+ // directory in /tmp and let the OS clean it up via the usual tmpdir
+ // cleanup cron job.
+
+ // this removes the advisory lock, allowing other processes to acquire it.
+ if (ipcLockFD) {
+ close(ipcLockFD);
+ ipcLockFD = 0;
+ }
+}
+
+#endif // IPC_USE_FILE_LOCK
+
+//-----------------------------------------------------------------------------
+// poll list
+//-----------------------------------------------------------------------------
+
+//
+// declared in ipcdPrivate.h
+//
+ipcClient *ipcClients = NULL;
+int ipcClientCount = 0;
+
+//
+// the first element of this array is always zero; this is done so that the
+// k'th element of ipcClientArray corresponds to the k'th element of
+// ipcPollList.
+//
+static ipcClient ipcClientArray[IPC_MAX_CLIENTS + 1];
+
+//
+// element 0 contains the "server socket"
+//
+static PRPollDesc ipcPollList[IPC_MAX_CLIENTS + 1];
+
+//-----------------------------------------------------------------------------
+
+static int AddClient(PRFileDesc *fd)
+{
+ if (ipcClientCount == IPC_MAX_CLIENTS) {
+ LOG(("reached maximum client limit\n"));
+ return -1;
+ }
+
+ int pollCount = ipcClientCount + 1;
+
+ ipcClientArray[pollCount].Init();
+
+ ipcPollList[pollCount].fd = fd;
+ ipcPollList[pollCount].in_flags = PR_POLL_READ;
+ ipcPollList[pollCount].out_flags = 0;
+
+ ++ipcClientCount;
+ return 0;
+}
+
+static int RemoveClient(int clientIndex)
+{
+ PRPollDesc *pd = &ipcPollList[clientIndex];
+
+ PR_Close(pd->fd);
+
+ ipcClientArray[clientIndex].Finalize();
+
+ //
+ // keep the clients and poll_fds contiguous; move the last one into
+ // the spot held by the one that is going away.
+ //
+ int toIndex = clientIndex;
+ int fromIndex = ipcClientCount;
+ if (fromIndex != toIndex) {
+ memcpy(&ipcClientArray[toIndex], &ipcClientArray[fromIndex], sizeof(ipcClient));
+ memcpy(&ipcPollList[toIndex], &ipcPollList[fromIndex], sizeof(PRPollDesc));
+ }
+
+ //
+ // zero out the old entries.
+ //
+ memset(&ipcClientArray[fromIndex], 0, sizeof(ipcClient));
+ memset(&ipcPollList[fromIndex], 0, sizeof(PRPollDesc));
+
+ --ipcClientCount;
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+
+static void PollLoop(PRFileDesc *listenFD)
+{
+ // the first element of ipcClientArray is unused.
+ memset(ipcClientArray, 0, sizeof(ipcClientArray));
+ ipcClients = ipcClientArray + 1;
+ ipcClientCount = 0;
+
+ ipcPollList[0].fd = listenFD;
+ ipcPollList[0].in_flags = PR_POLL_EXCEPT | PR_POLL_READ;
+
+ while (1) {
+ PRInt32 rv;
+ PRIntn i;
+
+ int pollCount = ipcClientCount + 1;
+
+ ipcPollList[0].out_flags = 0;
+
+ //
+ // poll
+ //
+ // timeout after 5 minutes. if no connections after timeout, then
+ // exit. this timeout ensures that we don't stay resident when no
+ // clients are interested in connecting after spawning the daemon.
+ //
+ // XXX add #define for timeout value
+ //
+ LOG(("calling PR_Poll [pollCount=%d]\n", pollCount));
+ rv = PR_Poll(ipcPollList, pollCount, PR_SecondsToInterval(60 * 5));
+ if (rv == -1) {
+ LOG(("PR_Poll failed [%d]\n", PR_GetError()));
+ return;
+ }
+
+ if (rv > 0) {
+ //
+ // process clients that are ready
+ //
+ for (i = 1; i < pollCount; ++i) {
+ if (ipcPollList[i].out_flags != 0) {
+ ipcPollList[i].in_flags =
+ ipcClientArray[i].Process(ipcPollList[i].fd,
+ ipcPollList[i].out_flags);
+ ipcPollList[i].out_flags = 0;
+ }
+ }
+
+ //
+ // cleanup any dead clients (indicated by a zero in_flags)
+ //
+ for (i = pollCount - 1; i >= 1; --i) {
+ if (ipcPollList[i].in_flags == 0)
+ RemoveClient(i);
+ }
+
+ //
+ // check for new connection
+ //
+ if (ipcPollList[0].out_flags & PR_POLL_READ) {
+ LOG(("got new connection\n"));
+
+ PRNetAddr clientAddr;
+ memset(&clientAddr, 0, sizeof(clientAddr));
+ PRFileDesc *clientFD;
+
+ // @todo : We need to handle errors from accept() especially something like
+ // EMFILE, which happens when we run out of file descriptors.
+ // and puts XPCOMIPCD in a poll/accept endless loop!
+ clientFD = PR_Accept(listenFD, &clientAddr, PR_INTERVAL_NO_WAIT);
+ if (clientFD == NULL) {
+ // ignore this error... perhaps the client disconnected.
+ LOG(("PR_Accept failed [%d]\n", PR_GetError()));
+ }
+ else {
+ // make socket non-blocking
+ PRSocketOptionData opt;
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(clientFD, &opt);
+
+ if (AddClient(clientFD) != 0)
+ PR_Close(clientFD);
+ }
+ }
+ }
+
+ //
+ // shutdown if no clients
+ //
+ if (ipcClientCount == 0) {
+ LOG(("shutting down\n"));
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg)
+{
+ LOG(("IPC_PlatformSendMsg\n"));
+
+ //
+ // must copy message onto send queue.
+ //
+ client->EnqueueOutboundMsg(msg);
+
+ //
+ // since our Process method may have already been called, we must ensure
+ // that the PR_POLL_WRITE flag is set.
+ //
+ int clientIndex = client - ipcClientArray;
+ ipcPollList[clientIndex].in_flags |= PR_POLL_WRITE;
+
+ return PR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenFD = NULL;
+ PRNetAddr addr;
+
+#ifdef VBOX
+ /* Set up the runtime without loading the support driver. */
+ RTR3InitExe(argc, &argv, 0);
+#endif
+
+ //
+ // ignore SIGINT so <ctrl-c> from terminal only kills the client
+ // which spawned this daemon.
+ //
+ signal(SIGINT, SIG_IGN);
+ // XXX block others? check cartman
+
+ // ensure strict file permissions
+ umask(0077);
+
+ IPC_InitLog("###");
+
+ LOG(("daemon started...\n"));
+
+ //XXX uncomment these lines to test slow starting daemon
+ //IPC_Sleep(2);
+
+ // set socket address
+ addr.local.family = PR_AF_LOCAL;
+ if (argc < 2)
+ IPC_GetDefaultSocketPath(addr.local.path, sizeof(addr.local.path));
+ else
+ PL_strncpyz(addr.local.path, argv[1], sizeof(addr.local.path));
+
+#ifdef IPC_USE_FILE_LOCK
+ Status status = InitDaemonDir(addr.local.path);
+ if (status != EOk) {
+ if (status == ELockFileLock) {
+ LOG(("Another daemon is already running, exiting.\n"));
+ // send a signal to the blocked parent to indicate success
+ IPC_NotifyParent();
+ return 0;
+ }
+ else {
+ LOG(("InitDaemonDir failed (status=%d)\n", status));
+ // don't notify the parent to cause it to fail in PR_Read() after
+ // we terminate
+#ifdef VBOX
+ if (status != ELockFileOwner)
+ printf("Cannot create a lock file for '%s'.\n"
+ "Check permissions.\n", addr.local.path);
+#endif
+ return 0;
+ }
+ }
+#endif
+
+ listenFD = PR_OpenTCPSocket(PR_AF_LOCAL);
+ if (!listenFD) {
+ LOG(("PR_OpenTCPSocket failed [%d]\n", PR_GetError()));
+ }
+ else if (PR_Bind(listenFD, &addr) != PR_SUCCESS) {
+ LOG(("PR_Bind failed [%d]\n", PR_GetError()));
+ }
+ else {
+ IPC_InitModuleReg(argv[0]);
+
+#ifdef VBOX
+ // Use large backlog, as otherwise local sockets can reject connection
+ // attempts. Usually harmless, but causes an unnecessary start attempt
+ // of IPCD (which will terminate straight away), and the next attempt
+ // usually succeeds. But better avoid unnecessary activities.
+ if (PR_Listen(listenFD, 128) != PR_SUCCESS) {
+#else /* !VBOX */
+ if (PR_Listen(listenFD, 5) != PR_SUCCESS) {
+#endif /* !VBOX */
+ LOG(("PR_Listen failed [%d]\n", PR_GetError()));
+ }
+ else {
+#ifndef VBOX
+ // redirect all standard file descriptors to /dev/null for
+ // proper daemonizing
+ PR_Close(PR_STDIN);
+ PR_Open("/dev/null", O_RDONLY, 0);
+ PR_Close(PR_STDOUT);
+ PR_Open("/dev/null", O_WRONLY, 0);
+ PR_Close(PR_STDERR);
+ PR_Open("/dev/null", O_WRONLY, 0);
+#endif
+
+ IPC_NotifyParent();
+
+#if defined(VBOX) && !defined(XP_OS2)
+ // Increase the file table size to 10240 or as high as possible.
+ struct rlimit lim;
+ if (getrlimit(RLIMIT_NOFILE, &lim) == 0)
+ {
+ if ( lim.rlim_cur < 10240
+ && lim.rlim_cur < lim.rlim_max)
+ {
+ lim.rlim_cur = lim.rlim_max <= 10240 ? lim.rlim_max : 10240;
+ if (setrlimit(RLIMIT_NOFILE, &lim) == -1)
+ printf("WARNING: failed to increase file descriptor limit. (%d)\n", errno);
+ }
+ }
+ else
+ printf("WARNING: failed to obtain per-process file-descriptor limit (%d).\n", errno);
+#endif
+
+ PollLoop(listenFD);
+ }
+
+ IPC_ShutdownModuleReg();
+ }
+
+ //IPC_Sleep(5);
+
+#ifdef IPC_USE_FILE_LOCK
+ // it is critical that we release the lock before closing the socket,
+ // otherwise, a client might launch another daemon that would be unable
+ // to acquire the lock and would then leave the client without a daemon.
+
+ ShutdownDaemonDir();
+#endif
+
+ if (listenFD) {
+ LOG(("closing socket\n"));
+ PR_Close(listenFD);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp
new file mode 100644
index 00000000..f89fba06
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdWin.cpp
@@ -0,0 +1,408 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <windows.h>
+
+#include "prthread.h"
+
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "ipcMessage.h"
+#include "ipcClient.h"
+#include "ipcModuleReg.h"
+#include "ipcdPrivate.h"
+#include "ipcd.h"
+#include "ipcm.h"
+
+//
+// declared in ipcdPrivate.h
+//
+ipcClient *ipcClients = NULL;
+int ipcClientCount = 0;
+
+static ipcClient ipcClientArray[IPC_MAX_CLIENTS];
+
+static HWND ipcHwnd = NULL;
+static PRBool ipcShutdown = PR_FALSE;
+
+#define IPC_PURGE_TIMER_ID 1
+#define IPC_WM_SENDMSG (WM_USER + 1)
+#define IPC_WM_SHUTDOWN (WM_USER + 2)
+
+//-----------------------------------------------------------------------------
+// client array manipulation
+//-----------------------------------------------------------------------------
+
+static void
+RemoveClient(ipcClient *client)
+{
+ LOG(("RemoveClient\n"));
+
+ int clientIndex = client - ipcClientArray;
+
+ client->Finalize();
+
+ //
+ // move last ipcClient object down into the spot occupied by this client.
+ //
+ int fromIndex = ipcClientCount - 1;
+ int toIndex = clientIndex;
+ if (toIndex != fromIndex)
+ memcpy(&ipcClientArray[toIndex], &ipcClientArray[fromIndex], sizeof(ipcClient));
+
+ memset(&ipcClientArray[fromIndex], 0, sizeof(ipcClient));
+
+ --ipcClientCount;
+ LOG((" num clients = %u\n", ipcClientCount));
+
+ if (ipcClientCount == 0) {
+ LOG((" shutting down...\n"));
+ KillTimer(ipcHwnd, IPC_PURGE_TIMER_ID);
+ PostQuitMessage(0);
+ ipcShutdown = PR_TRUE;
+ }
+}
+
+static void
+PurgeStaleClients()
+{
+ if (ipcClientCount == 0)
+ return;
+
+ LOG(("PurgeStaleClients [num-clients=%u]\n", ipcClientCount));
+ //
+ // walk the list of supposedly active clients, and verify the existance of
+ // their respective message windows.
+ //
+ char wName[IPC_CLIENT_WINDOW_NAME_MAXLEN];
+ for (int i=ipcClientCount-1; i>=0; --i) {
+ ipcClient *client = &ipcClientArray[i];
+
+ LOG((" checking client at index %u [client-id=%u pid=%u]\n",
+ i, client->ID(), client->PID()));
+
+ IPC_GetClientWindowName(client->PID(), wName);
+
+ // XXX dougt has ideas about how to make this better
+
+ HWND hwnd = FindWindow(IPC_CLIENT_WINDOW_CLASS, wName);
+ if (!hwnd) {
+ LOG((" client window not found; removing client!\n"));
+ RemoveClient(client);
+ }
+ }
+}
+
+static ipcClient *
+AddClient(HWND hwnd, PRUint32 pid)
+{
+ LOG(("AddClient\n"));
+
+ //
+ // before adding a new client, verify that all existing clients are
+ // still up and running. remove any stale clients.
+ //
+ PurgeStaleClients();
+
+ if (ipcClientCount == IPC_MAX_CLIENTS) {
+ LOG((" reached maximum client count!\n"));
+ return NULL;
+ }
+
+ ipcClient *client = &ipcClientArray[ipcClientCount];
+ client->Init();
+ client->SetHwnd(hwnd);
+ client->SetPID(pid); // XXX one function instead of 3
+
+ ++ipcClientCount;
+ LOG((" num clients = %u\n", ipcClientCount));
+
+ if (ipcClientCount == 1)
+ SetTimer(ipcHwnd, IPC_PURGE_TIMER_ID, 1000, NULL);
+
+ return client;
+}
+
+static ipcClient *
+GetClientByPID(PRUint32 pid)
+{
+ for (int i=0; i<ipcClientCount; ++i) {
+ if (ipcClientArray[i].PID() == pid)
+ return &ipcClientArray[i];
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// message processing
+//-----------------------------------------------------------------------------
+
+static void
+ProcessMsg(HWND hwnd, PRUint32 pid, const ipcMessage *msg)
+{
+ LOG(("ProcessMsg [pid=%u len=%u]\n", pid, msg->MsgLen()));
+
+ ipcClient *client = GetClientByPID(pid);
+
+ if (client) {
+ //
+ // if this is an IPCM "client hello" message, then reset the client
+ // instance object.
+ //
+ if (msg->Target().Equals(IPCM_TARGET) &&
+ IPCM_GetType(msg) == IPCM_MSG_REQ_CLIENT_HELLO) {
+ RemoveClient(client);
+ client = NULL;
+ }
+ }
+
+ if (client == NULL) {
+ client = AddClient(hwnd, pid);
+ if (!client)
+ return;
+ }
+
+ IPC_DispatchMsg(client, msg);
+}
+
+//-----------------------------------------------------------------------------
+
+PRStatus
+IPC_PlatformSendMsg(ipcClient *client, ipcMessage *msg)
+{
+ LOG(("IPC_PlatformSendMsg [clientID=%u clientPID=%u]\n",
+ client->ID(), client->PID()));
+
+ // use PostMessage to make this asynchronous; otherwise we might get
+ // some wierd SendMessage recursion between processes.
+
+ WPARAM wParam = (WPARAM) client->Hwnd();
+ LPARAM lParam = (LPARAM) msg;
+ if (!PostMessage(ipcHwnd, IPC_WM_SENDMSG, wParam, lParam)) {
+ LOG(("PostMessage failed\n"));
+ delete msg;
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// windows message loop
+//-----------------------------------------------------------------------------
+
+static LRESULT CALLBACK
+WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LOG(("got message [msg=%x wparam=%x lparam=%x]\n", uMsg, wParam, lParam));
+
+ if (uMsg == WM_COPYDATA) {
+ if (ipcShutdown) {
+ LOG(("ignoring message b/c daemon is shutting down\n"));
+ return TRUE;
+ }
+ COPYDATASTRUCT *cd = (COPYDATASTRUCT *) lParam;
+ if (cd && cd->lpData) {
+ ipcMessage msg;
+ PRUint32 bytesRead;
+ PRBool complete;
+ // XXX avoid extra malloc
+ PRStatus rv = msg.ReadFrom((const char *) cd->lpData, cd->cbData,
+ &bytesRead, &complete);
+ if (rv == PR_SUCCESS && complete) {
+ //
+ // grab client PID and hwnd.
+ //
+ ProcessMsg((HWND) wParam, (PRUint32) cd->dwData, &msg);
+ }
+ else
+ LOG(("ignoring malformed message\n"));
+ }
+ return TRUE;
+ }
+
+ if (uMsg == IPC_WM_SENDMSG) {
+ HWND hWndDest = (HWND) wParam;
+ ipcMessage *msg = (ipcMessage *) lParam;
+
+ COPYDATASTRUCT cd;
+ cd.dwData = GetCurrentProcessId();
+ cd.cbData = (DWORD) msg->MsgLen();
+ cd.lpData = (PVOID) msg->MsgBuf();
+
+ LOG(("calling SendMessage...\n"));
+ SendMessage(hWndDest, WM_COPYDATA, (WPARAM) hWnd, (LPARAM) &cd);
+ LOG((" done.\n"));
+
+ delete msg;
+ return 0;
+ }
+
+ if (uMsg == WM_TIMER) {
+ PurgeStaleClients();
+ return 0;
+ }
+
+#if 0
+ if (uMsg == IPC_WM_SHUTDOWN) {
+ //
+ // since this message is handled asynchronously, it is possible
+ // that other clients may have come online since this was issued.
+ // in which case, we need to ignore this message.
+ //
+ if (ipcClientCount == 0) {
+ ipcShutdown = PR_TRUE;
+ PostQuitMessage(0);
+ }
+ return 0;
+ }
+#endif
+
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+//-----------------------------------------------------------------------------
+// daemon startup synchronization
+//-----------------------------------------------------------------------------
+
+static HANDLE ipcSyncEvent;
+
+static PRBool
+AcquireLock()
+{
+ ipcSyncEvent = CreateEvent(NULL, FALSE, FALSE,
+ IPC_SYNC_EVENT_NAME);
+ if (!ipcSyncEvent) {
+ LOG(("CreateEvent failed [%u]\n", GetLastError()));
+ return PR_FALSE;
+ }
+
+ // check to see if event already existed prior to this call.
+ if (GetLastError() == ERROR_ALREADY_EXISTS) {
+ LOG((" lock already set; exiting...\n"));
+ return PR_FALSE;
+ }
+
+ LOG((" acquired lock\n"));
+ return PR_TRUE;
+}
+
+static void
+ReleaseLock()
+{
+ if (ipcSyncEvent) {
+ LOG(("releasing lock...\n"));
+ CloseHandle(ipcSyncEvent);
+ ipcSyncEvent = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// main
+//-----------------------------------------------------------------------------
+
+#ifdef DEBUG
+int
+main()
+#else
+int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
+#endif
+{
+ IPC_InitLog("###");
+
+ LOG(("daemon started...\n"));
+
+ if (!AcquireLock()) {
+ // unblock the parent; it should be able to find the IPC window of the
+ // other daemon process.
+ IPC_NotifyParent();
+ return 0;
+ }
+
+ // initialize global data
+ memset(ipcClientArray, 0, sizeof(ipcClientArray));
+ ipcClients = ipcClientArray;
+ ipcClientCount = 0;
+
+ // create message window up front...
+ WNDCLASS wc;
+ memset(&wc, 0, sizeof(wc));
+ wc.lpfnWndProc = WindowProc;
+ wc.lpszClassName = IPC_WINDOW_CLASS;
+
+ RegisterClass(&wc);
+
+ ipcHwnd = CreateWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME,
+ 0, 0, 0, 10, 10, NULL, NULL, NULL, NULL);
+
+ // unblock the parent process; it should now look for the IPC window.
+ IPC_NotifyParent();
+
+ if (!ipcHwnd)
+ return -1;
+
+ // load modules relative to the location of the executable...
+ {
+ char path[MAX_PATH];
+ GetModuleFileName(NULL, path, sizeof(path));
+ IPC_InitModuleReg(path);
+ }
+
+ LOG(("entering message loop...\n"));
+ MSG msg;
+ while (GetMessage(&msg, ipcHwnd, 0, 0))
+ DispatchMessage(&msg);
+
+ // unload modules
+ IPC_ShutdownModuleReg();
+
+ //
+ // we release the daemon lock before destroying the window because the
+ // absence of our window is what will cause clients to try to spawn the
+ // daemon.
+ //
+ ReleaseLock();
+
+ //LOG(("sleeping 5 seconds...\n"));
+ //PR_Sleep(PR_SecondsToInterval(5));
+
+ LOG(("destroying message window...\n"));
+ DestroyWindow(ipcHwnd);
+ ipcHwnd = NULL;
+
+ LOG(("exiting\n"));
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.in
new file mode 100644
index 00000000..e258946b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.in
@@ -0,0 +1,49 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+DIRS = lock transmngr dconnect
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.kup b/src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.in
new file mode 100644
index 00000000..e6a89153
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.in
@@ -0,0 +1,52 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = public src
+
+ifdef ENABLE_TESTS
+DIRS += test
+endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.kup b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/Makefile.in
new file mode 100644
index 00000000..b2b3dbaa
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/Makefile.in
@@ -0,0 +1,53 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+XPIDL_MODULE= ipcd_dconnect
+
+XPIDLSRCS = \
+ ipcIDConnectService.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/ipcIDConnectService.idl b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/ipcIDConnectService.idl
new file mode 100644
index 00000000..6ca16a2d
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/public/ipcIDConnectService.idl
@@ -0,0 +1,79 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * This service provides methods similar to nsIComponentManager and
+ * nsIServiceManager. A ClientID parameter specifies the remote process
+ * in which the object should live.
+ *
+ * ipcIService can be used to determine the ClientID of a remote process.
+ *
+ * It is assumed that both processes have access to the same typelibs.
+ */
+[scriptable, uuid(fe07ed16-2710-4a1e-a4e2-81302b62bf0e)]
+interface ipcIDConnectService : nsISupports
+{
+ void createInstance(
+ in unsigned long aClientID,
+ in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result
+ );
+
+ void createInstanceByContractID(
+ in unsigned long aClientID,
+ in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result
+ );
+
+ void getService(
+ in unsigned long aClientID,
+ in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result
+ );
+
+ void getServiceByContractID(
+ in unsigned long aClientID,
+ in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result
+ );
+};
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.in
new file mode 100644
index 00000000..a9efaadf
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.in
@@ -0,0 +1,66 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = ipcddconnect_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME = ipcd
+
+FORCE_USE_PIC = 1
+
+REQUIRES = \
+ xpcom \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ ipcDConnectService.cpp \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../../shared/src \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.kup b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/Makefile.kup
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp
new file mode 100644
index 00000000..32565df2
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp
@@ -0,0 +1,4210 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ * Dmitry A. Kuminov <dmik@innotek.de>
+ *
+ * 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 "ipcDConnectService.h"
+#include "ipcMessageWriter.h"
+#include "ipcMessageReader.h"
+#include "ipcLog.h"
+
+#include "nsIServiceManagerUtils.h"
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIExceptionService.h"
+#include "nsString.h"
+#include "nsVoidArray.h"
+#include "nsCRT.h"
+#include "nsDeque.h"
+#include "xptcall.h"
+
+#ifdef VBOX
+# include <map>
+# include <list>
+# include <iprt/err.h>
+# include <iprt/req.h>
+# include <iprt/mem.h>
+# include <iprt/time.h>
+# include <iprt/thread.h>
+#endif /* VBOX */
+
+#if defined(DCONNECT_MULTITHREADED)
+
+#if !defined(DCONNECT_WITH_IPRT_REQ_POOL)
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+#endif
+
+#if defined(DEBUG) && !defined(DCONNECT_STATS)
+#define DCONNECT_STATS
+#endif
+
+#if defined(DCONNECT_STATS)
+#include <stdio.h>
+#endif
+
+#endif
+
+// XXX TODO:
+// 1. add thread affinity field to SETUP messages
+
+//-----------------------------------------------------------------------------
+
+#define DCONNECT_IPC_TARGETID \
+{ /* 43ca47ef-ebc8-47a2-9679-a4703218089f */ \
+ 0x43ca47ef, \
+ 0xebc8, \
+ 0x47a2, \
+ {0x96, 0x79, 0xa4, 0x70, 0x32, 0x18, 0x08, 0x9f} \
+}
+static const nsID kDConnectTargetID = DCONNECT_IPC_TARGETID;
+
+//-----------------------------------------------------------------------------
+
+#define DCON_WAIT_TIMEOUT PR_INTERVAL_NO_TIMEOUT
+
+//-----------------------------------------------------------------------------
+
+//
+// +--------------------------------------+
+// | major opcode : 1 byte |
+// +--------------------------------------+
+// | minor opcode : 1 byte |
+// +--------------------------------------+
+// | flags : 2 bytes |
+// +--------------------------------------+
+// . .
+// . variable payload .
+// . .
+// +--------------------------------------+
+//
+
+// dconnect major opcodes
+#define DCON_OP_SETUP 1
+#define DCON_OP_RELEASE 2
+#define DCON_OP_INVOKE 3
+
+#define DCON_OP_SETUP_REPLY 4
+#define DCON_OP_INVOKE_REPLY 5
+
+// dconnect minor opcodes for DCON_OP_SETUP
+#define DCON_OP_SETUP_NEW_INST_CLASSID 1
+#define DCON_OP_SETUP_NEW_INST_CONTRACTID 2
+#define DCON_OP_SETUP_GET_SERV_CLASSID 3
+#define DCON_OP_SETUP_GET_SERV_CONTRACTID 4
+#define DCON_OP_SETUP_QUERY_INTERFACE 5
+
+// dconnect minor opcodes for RELEASE
+// dconnect minor opcodes for INVOKE
+
+// DCON_OP_SETUP_REPLY and DCON_OP_INVOKE_REPLY flags
+#define DCON_OP_FLAGS_REPLY_EXCEPTION 0x0001
+
+// Within this time all the worker threads must be terminated.
+#define VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS (5000)
+
+#pragma pack(1)
+
+struct DConnectOp
+{
+ PRUint8 opcode_major;
+ PRUint8 opcode_minor;
+ PRUint16 flags;
+ PRUint32 request_index; // initialized with NewRequestIndex
+};
+
+// SETUP structs
+
+struct DConnectSetup : DConnectOp
+{
+ nsID iid;
+};
+
+struct DConnectSetupClassID : DConnectSetup
+{
+ nsID classid;
+};
+
+struct DConnectSetupContractID : DConnectSetup
+{
+ char contractid[1]; // variable length
+};
+
+struct DConnectSetupQueryInterface : DConnectSetup
+{
+ DConAddr instance;
+};
+
+// SETUP_REPLY struct
+
+struct DConnectSetupReply : DConnectOp
+{
+ DConAddr instance;
+ nsresult status;
+ // optionally followed by a specially serialized nsIException instance (see
+ // ipcDConnectService::SerializeException) if DCON_OP_FLAGS_REPLY_EXCEPTION is
+ // present in flags
+};
+
+// RELEASE struct
+
+struct DConnectRelease : DConnectOp
+{
+ DConAddr instance;
+};
+
+// INVOKE struct
+
+struct DConnectInvoke : DConnectOp
+{
+ DConAddr instance;
+ PRUint16 method_index;
+ // followed by an array of in-param blobs
+};
+
+// INVOKE_REPLY struct
+
+struct DConnectInvokeReply : DConnectOp
+{
+ nsresult result;
+ // followed by an array of out-param blobs if NS_SUCCEEDED(result), and
+ // optionally by a specially serialized nsIException instance (see
+ // ipcDConnectService::SerializeException) if DCON_OP_FLAGS_REPLY_EXCEPTION is
+ // present in flags
+};
+
+#pragma pack()
+
+//-----------------------------------------------------------------------------
+
+struct DConAddrPlusPtr
+{
+ DConAddr addr;
+ void *p;
+};
+
+//-----------------------------------------------------------------------------
+
+ipcDConnectService *ipcDConnectService::mInstance = nsnull;
+
+//-----------------------------------------------------------------------------
+
+static nsresult
+SetupPeerInstance(PRUint32 aPeerID, DConnectSetup *aMsg, PRUint32 aMsgLen,
+ void **aInstancePtr);
+
+//-----------------------------------------------------------------------------
+
+// A wrapper class holding an instance to an in-process XPCOM object.
+
+class DConnectInstance
+{
+public:
+ DConnectInstance(PRUint32 peer, nsIInterfaceInfo *iinfo, nsISupports *instance)
+ : mPeer(peer)
+ , mIInfo(iinfo)
+ , mInstance(instance)
+ {}
+
+ nsISupports *RealInstance() { return mInstance; }
+ nsIInterfaceInfo *InterfaceInfo() { return mIInfo; }
+ PRUint32 Peer() { return mPeer; }
+
+ DConnectInstanceKey::Key GetKey() {
+ const nsID *iid;
+ mIInfo->GetIIDShared(&iid);
+ return DConnectInstanceKey::Key(mPeer, mInstance, iid);
+ }
+
+ NS_IMETHODIMP_(nsrefcnt) AddRef(void)
+ {
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
+ nsrefcnt count;
+ count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ return count;
+ }
+
+ NS_IMETHODIMP_(nsrefcnt) Release(void)
+ {
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ if (0 == count) {
+ NS_PRECONDITION(PRInt32(mRefCntIPC) == 0, "non-zero IPC refcnt");
+ mRefCnt = 1; /* stabilize */
+ delete this;
+ return 0;
+ }
+ return count;
+ }
+
+ // this gets called after calling AddRef() on an instance passed to the
+ // client over IPC in order to have a count of IPC client-related references
+ // separately from the overall reference count
+ NS_IMETHODIMP_(nsrefcnt) AddRefIPC(void)
+ {
+ NS_PRECONDITION(PRInt32(mRefCntIPC) >= 0, "illegal refcnt");
+ nsrefcnt count = PR_AtomicIncrement((PRInt32*)&mRefCntIPC);
+ return count;
+ }
+
+ // this gets called before calling Release() when DCON_OP_RELEASE is
+ // received from the IPC client and in other cases to balance AddRefIPC()
+ NS_IMETHODIMP_(nsrefcnt) ReleaseIPC(PRBool locked = PR_FALSE)
+ {
+ NS_PRECONDITION(0 != mRefCntIPC, "dup release");
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCntIPC);
+ if (0 == count) {
+ // If the last IPC reference is released, remove this instance from the map.
+ // ipcDConnectService is guaranteed to still exist here
+ // (DConnectInstance lifetime is bound to ipcDConnectService)
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ if (dConnect)
+ dConnect->DeleteInstance(this, locked);
+ else
+ NS_NOTREACHED("ipcDConnectService has gone before DConnectInstance");
+ }
+ return count;
+ }
+
+private:
+ nsAutoRefCnt mRefCnt;
+ nsAutoRefCnt mRefCntIPC;
+ PRUint32 mPeer; // peer process "owning" this instance
+ nsCOMPtr<nsIInterfaceInfo> mIInfo;
+ nsCOMPtr<nsISupports> mInstance;
+};
+
+void
+ipcDConnectService::ReleaseWrappers(nsVoidArray &wrappers, PRUint32 peer)
+{
+ nsAutoLock lock (mLock);
+
+ for (PRInt32 i=0; i<wrappers.Count(); ++i)
+ {
+ DConnectInstance *wrapper = (DConnectInstance *)wrappers[i];
+ if (mInstanceSet.Contains(wrapper) && wrapper->Peer() == peer)
+ {
+ wrapper->ReleaseIPC(PR_TRUE /* locked */);
+ wrapper->Release();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static nsresult
+SerializeParam(ipcMessageWriter &writer, const nsXPTType &t, const nsXPTCMiniVariant &v)
+{
+ switch (t.TagPart())
+ {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_U8:
+ writer.PutInt8(v.val.u8);
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ writer.PutInt16(v.val.u16);
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ writer.PutInt32(v.val.u32);
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ writer.PutBytes(&v.val.u64, sizeof(PRUint64));
+ break;
+
+ case nsXPTType::T_FLOAT:
+ writer.PutBytes(&v.val.f, sizeof(float));
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ writer.PutBytes(&v.val.d, sizeof(double));
+ break;
+
+ case nsXPTType::T_BOOL:
+ writer.PutBytes(&v.val.b, sizeof(PRBool));
+ break;
+
+ case nsXPTType::T_CHAR:
+ writer.PutBytes(&v.val.c, sizeof(char));
+ break;
+
+ case nsXPTType::T_WCHAR:
+ writer.PutBytes(&v.val.wc, sizeof(PRUnichar));
+ break;
+
+ case nsXPTType::T_IID:
+ {
+ AssertReturn(v.val.p, NS_ERROR_INVALID_POINTER);
+ writer.PutBytes(v.val.p, sizeof(nsID));
+ }
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ {
+ if (v.val.p)
+ {
+ int len = strlen((const char *) v.val.p);
+ writer.PutInt32(len);
+ writer.PutBytes(v.val.p, len);
+ }
+ else
+ {
+ // put -1 to indicate null string
+ writer.PutInt32((PRUint32) -1);
+ }
+ }
+ break;
+
+ case nsXPTType::T_WCHAR_STR:
+ {
+ if (v.val.p)
+ {
+ int len = 2 * nsCRT::strlen((const PRUnichar *) v.val.p);
+ writer.PutInt32(len);
+ writer.PutBytes(v.val.p, len);
+ }
+ else
+ {
+ // put -1 to indicate null string
+ writer.PutInt32((PRUint32) -1);
+ }
+ }
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ NS_NOTREACHED("this should be handled elsewhere");
+ return NS_ERROR_UNEXPECTED;
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ const nsAString *str = (const nsAString *) v.val.p;
+
+ PRUint32 len = 2 * str->Length();
+ nsAString::const_iterator begin;
+ const PRUnichar *data = str->BeginReading(begin).get();
+
+ writer.PutInt32(len);
+ writer.PutBytes(data, len);
+ }
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ const nsACString *str = (const nsACString *) v.val.p;
+
+ PRUint32 len = str->Length();
+ nsACString::const_iterator begin;
+ const char *data = str->BeginReading(begin).get();
+
+ writer.PutInt32(len);
+ writer.PutBytes(data, len);
+ }
+ break;
+
+ case nsXPTType::T_ARRAY:
+ // arrays are serialized after all other params outside this routine
+ break;
+
+ case nsXPTType::T_VOID:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ default:
+ LOG(("unexpected parameter type: %d\n", t.TagPart()));
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+static nsresult
+DeserializeParam(ipcMessageReader &reader, const nsXPTType &t, nsXPTCVariant &v)
+{
+ // defaults
+ v.ptr = nsnull;
+ v.type = t;
+ v.flags = 0;
+
+ switch (t.TagPart())
+ {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_U8:
+ v.val.u8 = reader.GetInt8();
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ v.val.u16 = reader.GetInt16();
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ v.val.u32 = reader.GetInt32();
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ reader.GetBytes(&v.val.u64, sizeof(v.val.u64));
+ break;
+
+ case nsXPTType::T_FLOAT:
+ reader.GetBytes(&v.val.f, sizeof(v.val.f));
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ reader.GetBytes(&v.val.d, sizeof(v.val.d));
+ break;
+
+ case nsXPTType::T_BOOL:
+ reader.GetBytes(&v.val.b, sizeof(v.val.b));
+ break;
+
+ case nsXPTType::T_CHAR:
+ reader.GetBytes(&v.val.c, sizeof(v.val.c));
+ break;
+
+ case nsXPTType::T_WCHAR:
+ reader.GetBytes(&v.val.wc, sizeof(v.val.wc));
+ break;
+
+ case nsXPTType::T_IID:
+ {
+ nsID *buf = (nsID *) nsMemory::Alloc(sizeof(nsID));
+ reader.GetBytes(buf, sizeof(nsID));
+ v.val.p = buf;
+ v.SetValIsAllocated();
+ }
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ {
+ PRUint32 len = reader.GetInt32();
+ if (len == (PRUint32) -1)
+ {
+ // it's a null string
+ v.val.p = nsnull;
+ }
+ else
+ {
+ char *buf = (char *) nsMemory::Alloc(len + 1);
+ reader.GetBytes(buf, len);
+ buf[len] = char(0);
+
+ v.val.p = buf;
+ v.SetValIsAllocated();
+ }
+ }
+ break;
+
+ case nsXPTType::T_WCHAR_STR:
+ {
+ PRUint32 len = reader.GetInt32();
+ if (len == (PRUint32) -1)
+ {
+ // it's a null string
+ v.val.p = nsnull;
+ }
+ else
+ {
+ PRUnichar *buf = (PRUnichar *) nsMemory::Alloc(len + 2);
+ reader.GetBytes(buf, len);
+ buf[len / 2] = PRUnichar(0);
+
+ v.val.p = buf;
+ v.SetValIsAllocated();
+ }
+ }
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ reader.GetBytes(&v.val.u64, sizeof(DConAddr));
+ // stub creation will be handled outside this routine. we only
+ // deserialize the DConAddr into v.val.u64 temporarily.
+ }
+ break;
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ PRUint32 len = reader.GetInt32();
+
+ nsString *str = new nsString();
+ str->SetLength(len / 2);
+ PRUnichar *buf = str->BeginWriting();
+ reader.GetBytes(buf, len);
+
+ v.val.p = str;
+ v.SetValIsDOMString();
+ }
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ PRUint32 len = reader.GetInt32();
+
+ nsCString *str = new nsCString();
+ str->SetLength(len);
+ char *buf = str->BeginWriting();
+ reader.GetBytes(buf, len);
+
+ v.val.p = str;
+
+ // this distinction here is pretty pointless
+ if (t.TagPart() == nsXPTType::T_CSTRING)
+ v.SetValIsCString();
+ else
+ v.SetValIsUTF8String();
+ }
+ break;
+
+ case nsXPTType::T_ARRAY:
+ // arrays are deserialized after all other params outside this routine
+ break;
+
+ case nsXPTType::T_VOID:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ default:
+ LOG(("unexpected parameter type\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+static nsresult
+SetupParam(const nsXPTParamInfo &p, nsXPTCVariant &v)
+{
+ const nsXPTType &t = p.GetType();
+
+ if (p.IsIn() && p.IsDipper())
+ {
+ v.ptr = nsnull;
+ v.flags = 0;
+
+ switch (t.TagPart())
+ {
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ v.val.p = new nsString();
+ if (!v.val.p)
+ return NS_ERROR_OUT_OF_MEMORY;
+ v.type = t;
+ v.SetValIsDOMString();
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ v.val.p = new nsCString();
+ if (!v.val.p)
+ return NS_ERROR_OUT_OF_MEMORY;
+ v.type = t;
+ v.SetValIsCString();
+ break;
+
+ default:
+ LOG(("unhandled dipper: type=%d\n", t.TagPart()));
+ return NS_ERROR_UNEXPECTED;
+ }
+ }
+ else if (p.IsOut() || p.IsRetval())
+ {
+ memset(&v.val, 0, sizeof(v.val));
+ v.ptr = &v.val;
+ v.type = t;
+ v.flags = 0;
+ v.SetPtrIsData();
+
+ // the ownership of output nsID, string, wstring, interface pointers and
+ // arrays is transferred to the receiving party. Therefore, we need to
+ // instruct FinishParam() to perform a cleanup after serializing them.
+ switch (t.TagPart())
+ {
+ case nsXPTType::T_IID:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_ARRAY:
+ v.SetValIsAllocated();
+ break;
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ v.SetValIsInterface();
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+static void
+FinishParam(nsXPTCVariant &v)
+{
+#ifdef VBOX
+ /* make valgrind happy */
+ if (!v.MustFreeVal())
+ return;
+#endif
+ if (!v.val.p)
+ return;
+
+ if (v.IsValAllocated())
+ nsMemory::Free(v.val.p);
+ else if (v.IsValInterface())
+ ((nsISupports *) v.val.p)->Release();
+ else if (v.IsValDOMString())
+ delete (nsAString *) v.val.p;
+ else if (v.IsValUTF8String() || v.IsValCString())
+ delete (nsACString *) v.val.p;
+}
+
+static nsresult
+DeserializeResult(ipcMessageReader &reader, const nsXPTType &t, nsXPTCMiniVariant &v)
+{
+ if (v.val.p == nsnull)
+ return NS_OK;
+
+ switch (t.TagPart())
+ {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_U8:
+ *((PRUint8 *) v.val.p) = reader.GetInt8();
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ *((PRUint16 *) v.val.p) = reader.GetInt16();
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ *((PRUint32 *) v.val.p) = reader.GetInt32();
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ reader.GetBytes(v.val.p, sizeof(PRUint64));
+ break;
+
+ case nsXPTType::T_FLOAT:
+ reader.GetBytes(v.val.p, sizeof(float));
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ reader.GetBytes(v.val.p, sizeof(double));
+ break;
+
+ case nsXPTType::T_BOOL:
+ reader.GetBytes(v.val.p, sizeof(PRBool));
+ break;
+
+ case nsXPTType::T_CHAR:
+ reader.GetBytes(v.val.p, sizeof(char));
+ break;
+
+ case nsXPTType::T_WCHAR:
+ reader.GetBytes(v.val.p, sizeof(PRUnichar));
+ break;
+
+ case nsXPTType::T_IID:
+ {
+ nsID *buf = (nsID *) nsMemory::Alloc(sizeof(nsID));
+ reader.GetBytes(buf, sizeof(nsID));
+ *((nsID **) v.val.p) = buf;
+ }
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ {
+ PRUint32 len = reader.GetInt32();
+ if (len == (PRUint32) -1)
+ {
+ // it's a null string
+#ifdef VBOX
+ *((char **) v.val.p) = NULL;
+#else
+ v.val.p = 0;
+#endif
+ }
+ else
+ {
+ char *buf = (char *) nsMemory::Alloc(len + 1);
+ reader.GetBytes(buf, len);
+ buf[len] = char(0);
+
+ *((char **) v.val.p) = buf;
+ }
+ }
+ break;
+
+ case nsXPTType::T_WCHAR_STR:
+ {
+ PRUint32 len = reader.GetInt32();
+ if (len == (PRUint32) -1)
+ {
+ // it's a null string
+#ifdef VBOX
+ *((PRUnichar **) v.val.p) = 0;
+#else
+ v.val.p = 0;
+#endif
+ }
+ else
+ {
+ PRUnichar *buf = (PRUnichar *) nsMemory::Alloc(len + 2);
+ reader.GetBytes(buf, len);
+ buf[len / 2] = PRUnichar(0);
+
+ *((PRUnichar **) v.val.p) = buf;
+ }
+ }
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ // stub creation will be handled outside this routine. we only
+ // deserialize the DConAddr and the original value of v.val.p
+ // into v.val.p temporarily. needs temporary memory alloc.
+ DConAddrPlusPtr *buf = (DConAddrPlusPtr *) nsMemory::Alloc(sizeof(DConAddrPlusPtr));
+ reader.GetBytes(&buf->addr, sizeof(DConAddr));
+ buf->p = v.val.p;
+ v.val.p = buf;
+ }
+ break;
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ PRUint32 len = reader.GetInt32();
+
+ nsAString *str = (nsAString *) v.val.p;
+
+ nsAString::iterator begin;
+ str->SetLength(len / 2);
+ str->BeginWriting(begin);
+
+ reader.GetBytes(begin.get(), len);
+ }
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ PRUint32 len = reader.GetInt32();
+
+ nsACString *str = (nsACString *) v.val.p;
+
+ nsACString::iterator begin;
+ str->SetLength(len);
+ str->BeginWriting(begin);
+
+ reader.GetBytes(begin.get(), len);
+ }
+ break;
+
+ case nsXPTType::T_ARRAY:
+ // arrays are deserialized after all other params outside this routine
+ break;
+
+ case nsXPTType::T_VOID:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ default:
+ LOG(("unexpected parameter type\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Returns an element from the nsXPTCMiniVariant array by properly casting it to
+// nsXPTCVariant when requested
+#define GET_PARAM(params, isXPTCVariantArray, idx) \
+ (isXPTCVariantArray ? ((nsXPTCVariant *) params) [idx] : params [idx])
+
+// isResult is PR_TRUE if the size_is and length_is params are out or retval
+// so that nsXPTCMiniVariants contain pointers to their locations instead of the
+// values themselves.
+static nsresult
+GetArrayParamInfo(nsIInterfaceInfo *iinfo, uint16 methodIndex,
+ const nsXPTMethodInfo &methodInfo, nsXPTCMiniVariant *params,
+ PRBool isXPTCVariantArray, const nsXPTParamInfo &paramInfo,
+ PRBool isResult, PRUint32 &size, PRUint32 &length,
+ nsXPTType &elemType)
+{
+ // XXX multidimensional arrays are not supported so dimension is always 0 for
+ // getting the size_is argument number of the array itself and 1 for getting
+ // the type of elements stored in the array.
+
+ nsresult rv;
+
+ // get the array size
+ PRUint8 sizeArg;
+ rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0, &sizeArg);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the number of valid elements
+ PRUint8 lenArg;
+ rv = iinfo->GetLengthIsArgNumberForParam(methodIndex, &paramInfo, 0, &lenArg);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // according to XPT specs
+ // (http://www.mozilla.org/scriptable/typelib_file.html), size_is and
+ // length_is for arrays is always uint32. Check this too.
+ {
+ nsXPTParamInfo pi = methodInfo.GetParam (sizeArg);
+ if (pi.GetType().TagPart() != nsXPTType::T_U32)
+ {
+ LOG(("unexpected size_is() parameter type: $d\n",
+ pi.GetType().TagPart()));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ pi = methodInfo.GetParam (lenArg);
+ if (pi.GetType().TagPart() != nsXPTType::T_U32)
+ {
+ LOG(("unexpected length_is() parameter type: $d\n",
+ pi.GetType().TagPart()));
+ return NS_ERROR_UNEXPECTED;
+ }
+ }
+
+ if (isResult)
+ {
+ length = *((PRUint32 *) GET_PARAM(params,isXPTCVariantArray, lenArg).val.p);
+ size = *((PRUint32 *) GET_PARAM(params, isXPTCVariantArray, sizeArg).val.p);
+ }
+ else
+ {
+ length = GET_PARAM(params, isXPTCVariantArray, lenArg).val.u32;
+ size = GET_PARAM(params, isXPTCVariantArray, sizeArg).val.u32;
+ }
+
+ if (length > size)
+ {
+ NS_WARNING("length_is() value is greater than size_is() value");
+ length = size;
+ }
+
+ // get type of array elements
+ rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &elemType);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (elemType.IsArithmetic() &&
+ (elemType.IsPointer() || elemType.IsUniquePointer() ||
+ elemType.IsReference()))
+ {
+ LOG(("arrays of pointers and references to arithmetic types are "
+ "not yet supported\n"));
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (elemType.IsArray())
+ {
+ LOG(("multidimensional arrays are not yet supported\n"));
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+GetTypeSize(const nsXPTType &type, PRUint32 &size, PRBool &isSimple)
+{
+ // get the type size in bytes
+ size = 0;
+ isSimple = PR_TRUE;
+ switch (type.TagPart())
+ {
+ case nsXPTType::T_I8: size = sizeof(PRInt8); break;
+ case nsXPTType::T_I16: size = sizeof(PRInt16); break;
+ case nsXPTType::T_I32: size = sizeof(PRInt32); break;
+ case nsXPTType::T_I64: size = sizeof(PRInt64); break;
+ case nsXPTType::T_U8: size = sizeof(PRUint8); break;
+ case nsXPTType::T_U16: size = sizeof(PRUint16); break;
+ case nsXPTType::T_U32: size = sizeof(PRUint32); break;
+ case nsXPTType::T_U64: size = sizeof(PRUint64); break;
+ case nsXPTType::T_FLOAT: size = sizeof(float); break;
+ case nsXPTType::T_DOUBLE: size = sizeof(double); break;
+ case nsXPTType::T_BOOL: size = sizeof(PRBool); break;
+ case nsXPTType::T_CHAR: size = sizeof(char); break;
+ case nsXPTType::T_WCHAR: size = sizeof(PRUnichar); break;
+ case nsXPTType::T_IID: /* fall through */
+ case nsXPTType::T_CHAR_STR: /* fall through */
+ case nsXPTType::T_WCHAR_STR: /* fall through */
+ case nsXPTType::T_ASTRING: /* fall through */
+ case nsXPTType::T_DOMSTRING: /* fall through */
+ case nsXPTType::T_UTF8STRING: /* fall through */
+ case nsXPTType::T_CSTRING: /* fall through */
+ size = sizeof(void *);
+ isSimple = PR_FALSE;
+ break;
+ case nsXPTType::T_INTERFACE: /* fall through */
+ case nsXPTType::T_INTERFACE_IS: /* fall through */
+ size = sizeof(DConAddr);
+ isSimple = PR_FALSE;
+ break;
+ default:
+ LOG(("unexpected parameter type: %d\n", type.TagPart()));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+static nsresult
+SerializeArrayParam(ipcDConnectService *dConnect,
+ ipcMessageWriter &writer, PRUint32 peerID,
+ nsIInterfaceInfo *iinfo, uint16 methodIndex,
+ const nsXPTMethodInfo &methodInfo,
+ nsXPTCMiniVariant *params, PRBool isXPTCVariantArray,
+ const nsXPTParamInfo &paramInfo,
+ void *array, nsVoidArray &wrappers)
+{
+ if (!array)
+ {
+ // put 0 to indicate null array
+ writer.PutInt8(0);
+ return NS_OK;
+ }
+
+ // put 1 to indicate non-null array
+ writer.PutInt8(1);
+
+ PRUint32 size = 0;
+ PRUint32 length = 0;
+ nsXPTType elemType;
+
+ nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
+ isXPTCVariantArray, paramInfo, PR_FALSE,
+ size, length, elemType);
+ if (NS_FAILED (rv))
+ return rv;
+
+ PRUint32 elemSize = 0;
+ PRBool isSimple = PR_TRUE;
+ rv = GetTypeSize(elemType, elemSize, isSimple);
+ if (NS_FAILED (rv))
+ return rv;
+
+ if (isSimple)
+ {
+ // this is a simple arithmetic type, write the whole array at once
+ writer.PutBytes(array, length * elemSize);
+ return NS_OK;
+ }
+
+ // iterate over valid (length_is) elements of the array
+ // and serialize each of them
+ nsXPTCMiniVariant v;
+ for (PRUint32 i = 0; i < length; ++i)
+ {
+ v.val.p = ((void **) array) [i];
+
+ if (elemType.IsInterfacePointer())
+ {
+ nsID iid;
+ rv = dConnect->GetIIDForMethodParam(iinfo, &methodInfo, paramInfo, elemType,
+ methodIndex, params, isXPTCVariantArray,
+ iid);
+ if (NS_SUCCEEDED(rv))
+ rv = dConnect->SerializeInterfaceParam(writer, peerID, iid,
+ (nsISupports *) v.val.p,
+ wrappers);
+ }
+ else
+ rv = SerializeParam(writer, elemType, v);
+
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+// isResult is PR_TRUE if the array param is out or retval
+static nsresult
+DeserializeArrayParam(ipcDConnectService *dConnect,
+ ipcMessageReader &reader, PRUint32 peerID,
+ nsIInterfaceInfo *iinfo, uint16 methodIndex,
+ const nsXPTMethodInfo &methodInfo,
+ nsXPTCMiniVariant *params, PRBool isXPTCVariantArray,
+ const nsXPTParamInfo &paramInfo,
+ PRBool isResult, void *&array)
+{
+ PRUint32 size = 0;
+ PRUint32 length = 0;
+ nsXPTType elemType;
+
+ nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
+ isXPTCVariantArray, paramInfo, isResult,
+ size, length, elemType);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint8 prefix = reader.GetInt8();
+ if (prefix == 0)
+ {
+ // it's a null array
+ array = nsnull;
+ return NS_OK;
+ }
+ // sanity
+ if (prefix != 1)
+ {
+ LOG(("unexpected array prefix: %u\n", prefix));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ PRUint32 elemSize = 0;
+ PRBool isSimple = PR_TRUE;
+ rv = GetTypeSize(elemType, elemSize, isSimple);
+ if (NS_FAILED (rv))
+ return rv;
+
+ // Note: for zero-sized arrays, we use the size of 1 because whether
+ // malloc(0) returns a null pointer or not (which is used in isNull())
+ // is implementation-dependent according to the C standard
+ void *arr = nsMemory::Alloc((size ? size : 1) * elemSize);
+ if (arr == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // initialize the unused space of the array with zeroes
+ if (length < size)
+ memset(((PRUint8 *) arr) + length * elemSize, 0,
+ (size - length) * elemSize);
+
+ if (isSimple)
+ {
+ // this is a simple arithmetic type, read the whole array at once
+ reader.GetBytes(arr, length * elemSize);
+
+ array = arr;
+ return NS_OK;
+ }
+
+ // iterate over valid (length_is) elements of the array
+ // and deserialize each of them individually
+ nsXPTCVariant v;
+ for (PRUint32 i = 0; i < length; ++i)
+ {
+ rv = DeserializeParam(reader, elemType, v);
+
+ if (NS_SUCCEEDED(rv) && elemType.IsInterfacePointer())
+ {
+ // grab the DConAddr value temporarily stored in the param
+ PtrBits bits = v.val.u64;
+
+ // DeserializeInterfaceParamBits needs IID only if it's a remote object
+ nsID iid;
+ if (bits & PTRBITS_REMOTE_BIT)
+ rv = dConnect->GetIIDForMethodParam(iinfo, &methodInfo, paramInfo,
+ elemType, methodIndex,
+ params, isXPTCVariantArray, iid);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsISupports *obj = nsnull;
+ rv = dConnect->DeserializeInterfaceParamBits(bits, peerID, iid, obj);
+ if (NS_SUCCEEDED(rv))
+ v.val.p = obj;
+ }
+ }
+
+ if (NS_FAILED(rv))
+ break;
+
+ // note that we discard extended param informaton provided by nsXPTCVariant
+ // and will have to "reconstruct" it from the type tag in FinishArrayParam()
+ ((void **) arr) [i] = v.val.p;
+ }
+
+ if (NS_FAILED(rv))
+ nsMemory::Free(arr);
+ else
+ array = arr;
+
+ return rv;
+}
+
+static void
+FinishArrayParam(nsIInterfaceInfo *iinfo, uint16 methodIndex,
+ const nsXPTMethodInfo &methodInfo, nsXPTCMiniVariant *params,
+ PRBool isXPTCVariantArray, const nsXPTParamInfo &paramInfo,
+ const nsXPTCMiniVariant &arrayVal)
+{
+ // nothing to do for a null array
+ void *arr = arrayVal.val.p;
+ if (!arr)
+ return;
+
+ PRUint32 size = 0;
+ PRUint32 length = 0;
+ nsXPTType elemType;
+
+ // note that FinishArrayParam is called only from OnInvoke to free memory
+ // after the call has been served. When OnInvoke sets up out and retval
+ // parameters for the real method, it passes pointers to the nsXPTCMiniVariant
+ // elements of the params array themselves so that they will eventually
+ // receive the returned values. For this reason, both in 'in' param and
+ // 'out/retaval' param cases, size_is and length_is may be read by
+ // GetArrayParamInfo() by value. Therefore, isResult is always PR_FALSE.
+ nsresult rv = GetArrayParamInfo(iinfo, methodIndex, methodInfo, params,
+ isXPTCVariantArray, paramInfo, PR_FALSE,
+ size, length, elemType);
+ if (NS_FAILED (rv))
+ return;
+
+ nsXPTCVariant v;
+ v.ptr = nsnull;
+ v.flags = 0;
+
+ // iterate over valid (length_is) elements of the array
+ // and free each of them
+ for (PRUint32 i = 0; i < length; ++i)
+ {
+ v.type = elemType.TagPart();
+
+ switch (elemType.TagPart())
+ {
+ case nsXPTType::T_I8: /* fall through */
+ case nsXPTType::T_I16: /* fall through */
+ case nsXPTType::T_I32: /* fall through */
+ case nsXPTType::T_I64: /* fall through */
+ case nsXPTType::T_U8: /* fall through */
+ case nsXPTType::T_U16: /* fall through */
+ case nsXPTType::T_U32: /* fall through */
+ case nsXPTType::T_U64: /* fall through */
+ case nsXPTType::T_FLOAT: /* fall through */
+ case nsXPTType::T_DOUBLE: /* fall through */
+ case nsXPTType::T_BOOL: /* fall through */
+ case nsXPTType::T_CHAR: /* fall through */
+ case nsXPTType::T_WCHAR: /* fall through */
+ // nothing to free for arithmetic types
+ continue;
+ case nsXPTType::T_IID: /* fall through */
+ case nsXPTType::T_CHAR_STR: /* fall through */
+ case nsXPTType::T_WCHAR_STR: /* fall through */
+ v.val.p = ((void **) arr) [i];
+ v.SetValIsAllocated();
+ break;
+ case nsXPTType::T_INTERFACE: /* fall through */
+ case nsXPTType::T_INTERFACE_IS: /* fall through */
+ v.val.p = ((void **) arr) [i];
+ v.SetValIsInterface();
+ break;
+ case nsXPTType::T_ASTRING: /* fall through */
+ case nsXPTType::T_DOMSTRING: /* fall through */
+ v.val.p = ((void **) arr) [i];
+ v.SetValIsDOMString();
+ break;
+ case nsXPTType::T_UTF8STRING: /* fall through */
+ v.val.p = ((void **) arr) [i];
+ v.SetValIsUTF8String();
+ break;
+ case nsXPTType::T_CSTRING: /* fall through */
+ v.val.p = ((void **) arr) [i];
+ v.SetValIsCString();
+ break;
+ default:
+ LOG(("unexpected parameter type: %d\n", elemType.TagPart()));
+ return;
+ }
+
+ FinishParam(v);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+static PRUint32
+NewRequestIndex()
+{
+ static PRInt32 sRequestIndex;
+ return (PRUint32) PR_AtomicIncrement(&sRequestIndex);
+}
+
+//-----------------------------------------------------------------------------
+
+#ifdef VBOX
+typedef struct ClientDownInfo
+{
+ ClientDownInfo(PRUint32 aClient)
+ {
+ uClient = aClient;
+ uTimestamp = PR_IntervalNow();
+ }
+
+ PRUint32 uClient;
+ PRIntervalTime uTimestamp;
+} ClientDownInfo;
+typedef std::map<PRUint32, ClientDownInfo *> ClientDownMap;
+typedef std::list<ClientDownInfo *> ClientDownList;
+
+#define MAX_CLIENT_DOWN_SIZE 10000
+
+/* Protected by the queue monitor. */
+static ClientDownMap g_ClientDownMap;
+static ClientDownList g_ClientDownList;
+
+#endif /* VBOX */
+
+class DConnectMsgSelector : public ipcIMessageObserver
+{
+public:
+ DConnectMsgSelector(PRUint32 peer, PRUint8 opCodeMajor, PRUint32 requestIndex)
+ : mPeer (peer)
+ , mOpCodeMajor(opCodeMajor)
+ , mRequestIndex(requestIndex)
+ {}
+
+ // stack based only
+ NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
+ NS_IMETHOD_(nsrefcnt) Release() { return 1; }
+
+ NS_IMETHOD QueryInterface(const nsIID &aIID, void **aInstancePtr);
+
+ NS_IMETHOD OnMessageAvailable(PRUint32 aSenderID, const nsID &aTarget,
+ const PRUint8 *aData, PRUint32 aDataLen)
+ {
+ // accept special "client dead" messages for a given peer
+ // (empty target id, zero data and data length)
+#ifndef VBOX
+ if (aSenderID == mPeer && aTarget.Equals(nsID()) && !aData && !aDataLen)
+ return NS_OK;
+#else /* VBOX */
+ if (aSenderID != IPC_SENDER_ANY && aTarget.Equals(nsID()) && !aData && !aDataLen)
+ {
+ // Insert new client down information. Start by expiring outdated
+ // entries and free one element if there's still no space (if needed).
+ PRIntervalTime now = PR_IntervalNow();
+ while (!g_ClientDownList.empty())
+ {
+ ClientDownInfo *cInfo = g_ClientDownList.back();
+ PRInt64 diff = (PRInt64)now - cInfo->uTimestamp;
+ if (diff < 0)
+ diff += (PRInt64)((PRIntervalTime)-1) + 1;
+ if (diff > PR_SecondsToInterval(15 * 60))
+ {
+ g_ClientDownMap.erase(cInfo->uClient);
+ g_ClientDownList.pop_back();
+ NS_ASSERTION(g_ClientDownMap.size() == g_ClientDownList.size(),
+ "client down info inconsistency during expiry");
+ delete cInfo;
+ }
+ else
+ break;
+ }
+
+ ClientDownMap::iterator it = g_ClientDownMap.find(aSenderID);
+ if (it == g_ClientDownMap.end())
+ {
+ /* Getting size of a map is O(1), size of a list can be O(n). */
+ while (g_ClientDownMap.size() >= MAX_CLIENT_DOWN_SIZE)
+ {
+ ClientDownInfo *cInfo = g_ClientDownList.back();
+ g_ClientDownMap.erase(cInfo->uClient);
+ g_ClientDownList.pop_back();
+ NS_ASSERTION(g_ClientDownMap.size() == g_ClientDownList.size(),
+ "client down info inconsistency during emergency evicting");
+ delete cInfo;
+ }
+
+ ClientDownInfo *cInfo = new ClientDownInfo(aSenderID);
+ RTMEM_MAY_LEAK(cInfo); /* tstVBoxAPIPerf leaks one allocated during ComPtr<IVirtualBoxClient>::createInprocObject(). */
+ g_ClientDownMap[aSenderID] = cInfo;
+ g_ClientDownList.push_front(cInfo);
+ NS_ASSERTION(g_ClientDownMap.size() == g_ClientDownList.size(),
+ "client down info inconsistency after adding entry");
+ }
+ return (aSenderID == mPeer) ? NS_OK : IPC_WAIT_NEXT_MESSAGE;
+ }
+ // accept special "client up" messages for a given peer
+ // (empty target id, zero data and data length=1)
+ if (aTarget.Equals(nsID()) && !aData && aDataLen == 1)
+ {
+ ClientDownMap::iterator it = g_ClientDownMap.find(aSenderID);
+ if (it != g_ClientDownMap.end())
+ {
+ ClientDownInfo *cInfo = it->second;
+ g_ClientDownMap.erase(it);
+ g_ClientDownList.remove(cInfo);
+ NS_ASSERTION(g_ClientDownMap.size() == g_ClientDownList.size(),
+ "client down info inconsistency in client up case");
+ delete cInfo;
+ }
+ return (aSenderID == mPeer) ? NS_OK : IPC_WAIT_NEXT_MESSAGE;
+ }
+ // accept special "client check" messages for an anonymous sender
+ // (invalid sender id, empty target id, zero data and data length
+ if (aSenderID == IPC_SENDER_ANY && aTarget.Equals(nsID()) && !aData && !aDataLen)
+ {
+ LOG(("DConnectMsgSelector::OnMessageAvailable: poll liveness for mPeer=%d\n",
+ mPeer));
+ ClientDownMap::iterator it = g_ClientDownMap.find(mPeer);
+ return (it == g_ClientDownMap.end()) ? IPC_WAIT_NEXT_MESSAGE : NS_OK;
+ }
+#endif /* VBOX */
+ const DConnectOp *op = (const DConnectOp *) aData;
+ // accept only reply messages with the given peer/opcode/index
+ // (to prevent eating replies the other thread might be waiting for)
+ // as well as any non-reply messages (to serve external requests that
+ // might arrive while we're waiting for the given reply).
+ if (aDataLen >= sizeof(DConnectOp) &&
+ ((op->opcode_major != DCON_OP_SETUP_REPLY &&
+ op->opcode_major != DCON_OP_INVOKE_REPLY) ||
+ (aSenderID == mPeer &&
+ op->opcode_major == mOpCodeMajor &&
+ op->request_index == mRequestIndex)))
+ return NS_OK;
+ else
+ return IPC_WAIT_NEXT_MESSAGE;
+ }
+
+ const PRUint32 mPeer;
+ const PRUint8 mOpCodeMajor;
+ const PRUint32 mRequestIndex;
+};
+NS_IMPL_QUERY_INTERFACE1(DConnectMsgSelector, ipcIMessageObserver)
+
+class DConnectCompletion : public ipcIMessageObserver
+{
+public:
+ DConnectCompletion(PRUint32 peer, PRUint8 opCodeMajor, PRUint32 requestIndex)
+ : mSelector(peer, opCodeMajor, requestIndex)
+ {}
+
+ // stack based only
+ NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
+ NS_IMETHOD_(nsrefcnt) Release() { return 1; }
+
+ NS_IMETHOD QueryInterface(const nsIID &aIID, void **aInstancePtr);
+
+ NS_IMETHOD OnMessageAvailable(PRUint32 aSenderID, const nsID &aTarget,
+ const PRUint8 *aData, PRUint32 aDataLen)
+ {
+ const DConnectOp *op = (const DConnectOp *) aData;
+ LOG((
+ "DConnectCompletion::OnMessageAvailable: "
+ "senderID=%d, opcode_major=%d, index=%d (waiting for %d)\n",
+ aSenderID, op->opcode_major, op->request_index, mSelector.mRequestIndex
+ ));
+ if (aSenderID == mSelector.mPeer &&
+ op->opcode_major == mSelector.mOpCodeMajor &&
+ op->request_index == mSelector.mRequestIndex)
+ {
+ OnResponseAvailable(aSenderID, op, aDataLen);
+ }
+ else
+ {
+ // ensure ipcDConnectService is not deleted before we finish
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ if (dConnect)
+ dConnect->OnMessageAvailable(aSenderID, aTarget, aData, aDataLen);
+ }
+ return NS_OK;
+ }
+
+ virtual void OnResponseAvailable(PRUint32 sender, const DConnectOp *op, PRUint32 opLen) = 0;
+
+ DConnectMsgSelector &GetSelector()
+ {
+ return mSelector;
+ }
+
+protected:
+ DConnectMsgSelector mSelector;
+};
+NS_IMPL_QUERY_INTERFACE1(DConnectCompletion, ipcIMessageObserver)
+
+//-----------------------------------------------------------------------------
+
+class DConnectInvokeCompletion : public DConnectCompletion
+{
+public:
+ DConnectInvokeCompletion(PRUint32 peer, const DConnectInvoke *invoke)
+ : DConnectCompletion(peer, DCON_OP_INVOKE_REPLY, invoke->request_index)
+ , mReply(nsnull)
+ , mParamsLen(0)
+ {}
+
+ ~DConnectInvokeCompletion() { if (mReply) free(mReply); }
+
+ void OnResponseAvailable(PRUint32 sender, const DConnectOp *op, PRUint32 opLen)
+ {
+ mReply = (DConnectInvokeReply *) malloc(opLen);
+ memcpy(mReply, op, opLen);
+
+ // the length in bytes of the parameter blob
+ mParamsLen = opLen - sizeof(*mReply);
+ }
+
+ PRBool IsPending() const { return mReply == nsnull; }
+ nsresult GetResult() const { return mReply->result; }
+
+ const PRUint8 *Params() const { return (const PRUint8 *) (mReply + 1); }
+ PRUint32 ParamsLen() const { return mParamsLen; }
+
+ const DConnectInvokeReply *Reply() const { return mReply; }
+
+private:
+ DConnectInvokeReply *mReply;
+ PRUint32 mParamsLen;
+};
+
+//-----------------------------------------------------------------------------
+
+#define DCONNECT_STUB_ID \
+{ /* 132c1f14-5442-49cb-8fe6-e60214bbf1db */ \
+ 0x132c1f14, \
+ 0x5442, \
+ 0x49cb, \
+ {0x8f, 0xe6, 0xe6, 0x02, 0x14, 0xbb, 0xf1, 0xdb} \
+}
+static NS_DEFINE_IID(kDConnectStubID, DCONNECT_STUB_ID);
+
+// this class represents the non-local object instance.
+
+class DConnectStub : public nsXPTCStubBase
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ DConnectStub(nsIInterfaceInfo *aIInfo,
+ DConAddr aInstance,
+ PRUint32 aPeerID)
+ : mIInfo(aIInfo)
+ , mInstance(aInstance)
+ , mPeerID(aPeerID)
+ , mCachedISupports(0)
+ , mRefCntLevels(0)
+ {}
+
+ NS_HIDDEN ~DConnectStub();
+
+ // return a refcounted pointer to the InterfaceInfo for this object
+ // NOTE: on some platforms this MUST not fail or we crash!
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo **aInfo);
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 aMethodIndex,
+ const nsXPTMethodInfo *aInfo,
+ nsXPTCMiniVariant *aParams);
+
+ DConAddr Instance() { return mInstance; }
+ PRUint32 PeerID() { return mPeerID; }
+
+ DConnectStubKey::Key GetKey() {
+ return DConnectStubKey::Key(mPeerID, mInstance);
+ }
+
+ NS_IMETHOD_(nsrefcnt) AddRefIPC();
+
+private:
+ nsCOMPtr<nsIInterfaceInfo> mIInfo;
+
+ // uniquely identifies this object instance between peers.
+ DConAddr mInstance;
+
+ // the "client id" of our IPC peer. this guy owns the real object.
+ PRUint32 mPeerID;
+
+ // cached nsISupports stub for this object
+ DConnectStub *mCachedISupports;
+
+ // stack of reference counter values (protected by
+ // ipcDConnectService::StubLock())
+ nsDeque mRefCntLevels;
+};
+
+NS_IMETHODIMP_(nsrefcnt)
+DConnectStub::AddRefIPC()
+{
+ // in this special version, we memorize the resulting reference count in the
+ // associated stack array. This stack is then used by Release() to determine
+ // when it is necessary to send a RELEASE request to the peer owning the
+ // object in order to balance AddRef() the peer does on DConnectInstance every
+ // time it passes an object over IPC.
+
+ // NOTE: this function is to be called from DConnectInstance::CreateStub only!
+
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ NS_ASSERTION(dConnect, "no ipcDConnectService (uninitialized?)");
+ if (!dConnect)
+ return 0;
+
+ // dConnect->StubLock() must be already locked here by
+ // DConnectInstance::CreateStub
+
+ nsrefcnt count = AddRef();
+ mRefCntLevels.Push((void *)(uintptr_t) count);
+ return count;
+}
+
+nsresult
+ipcDConnectService::CreateStub(const nsID &iid, PRUint32 peer, DConAddr instance,
+ DConnectStub **result)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ rv = GetInterfaceInfo(iid, getter_AddRefs(iinfo));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoLock lock (mLock);
+
+ if (mDisconnected)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ // we also need the stub lock which protects DConnectStub::mRefCntLevels and
+ // ipcDConnectService::mStubs
+ nsAutoLock stubLock (mStubLock);
+
+ DConnectStub *stub = nsnull;
+
+ // first try to find an existing stub for a given peer and instance
+ // (we do not care about IID because every DConAddr instance represents
+ // exactly one interface of the real object on the peer's side)
+ if (!mStubs.Get(DConnectStubKey::Key(peer, instance), &stub))
+ {
+ stub = new DConnectStub(iinfo, instance, peer);
+
+ if (NS_UNLIKELY(!stub))
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ else
+ {
+ rv = StoreStub(stub);
+ if (NS_FAILED(rv))
+ delete stub;
+ }
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ stub->AddRefIPC();
+ *result = stub;
+ }
+
+ return rv;
+}
+
+nsresult
+ipcDConnectService::SerializeInterfaceParam(ipcMessageWriter &writer,
+ PRUint32 peer, const nsID &iid,
+ nsISupports *obj,
+ nsVoidArray &wrappers)
+{
+ nsAutoLock lock (mLock);
+
+ if (mDisconnected)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ // we create an instance wrapper, and assume that the other side will send a
+ // RELEASE message when it no longer needs the instance wrapper. that will
+ // usually happen after the call returns.
+ //
+ // XXX a lazy scheme might be better, but for now simplicity wins.
+
+ // if the interface pointer references a DConnectStub corresponding
+ // to an object in the address space of the peer, then no need to
+ // create a new wrapper.
+
+ // if the interface pointer references an object for which we already have
+ // an existing wrapper, then we use it instead of creating a new one. this
+ // is based on the assumption that a valid COM object always returns exactly
+ // the same pointer value in response to every
+ // QueryInterface(NS_GET_IID(nsISupports), ...).
+
+ if (!obj)
+ {
+ // write null address
+ DConAddr nullobj = 0;
+ writer.PutBytes(&nullobj, sizeof(nullobj));
+ }
+ else
+ {
+ DConnectStub *stub = nsnull;
+ nsresult rv = obj->QueryInterface(kDConnectStubID, (void **) &stub);
+ if (NS_SUCCEEDED(rv) && (stub->PeerID() == peer))
+ {
+ DConAddr p = stub->Instance();
+ writer.PutBytes(&p, sizeof(p));
+ }
+ else
+ {
+ // create instance wrapper
+
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ rv = GetInterfaceInfo(iid, getter_AddRefs(iinfo));
+ if (NS_FAILED(rv))
+ return rv;
+
+ DConnectInstance *wrapper = nsnull;
+
+ // first try to find an existing wrapper for the given object
+ if (!FindInstanceAndAddRef(peer, obj, &iid, &wrapper))
+ {
+ wrapper = new DConnectInstance(peer, iinfo, obj);
+ if (!wrapper)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = StoreInstance(wrapper);
+ if (NS_FAILED(rv))
+ {
+ delete wrapper;
+ return rv;
+ }
+
+ // reference the newly created wrapper
+ wrapper->AddRef();
+ }
+
+ // increase the second, IPC-only, reference counter (mandatory before
+ // trying wrappers.AppendElement() to make sure ReleaseIPC() will remove
+ // the wrapper from the instance map on failure)
+ wrapper->AddRefIPC();
+
+ if (!wrappers.AppendElement(wrapper))
+ {
+ wrapper->ReleaseIPC();
+ wrapper->Release();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // wrapper remains referenced when passing it to the client
+ // (will be released upon DCON_OP_RELEASE)
+
+ // send address of the instance wrapper, and set the low bit to indicate
+ // to the remote party that this is a remote instance wrapper.
+ PtrBits bits = ((PtrBits)(uintptr_t) wrapper);
+ NS_ASSERTION((bits & PTRBITS_REMOTE_BIT) == 0, "remote bit wrong)");
+ bits |= PTRBITS_REMOTE_BIT;
+ writer.PutBytes(&bits, sizeof(bits));
+ }
+ NS_IF_RELEASE(stub);
+ }
+ return NS_OK;
+}
+
+// NOTE: peer and iid are ignored if bits doesn't contain PTRBITS_REMOTE_BIT
+nsresult
+ipcDConnectService::DeserializeInterfaceParamBits(PtrBits bits, PRUint32 peer,
+ const nsID &iid,
+ nsISupports *&obj)
+{
+ nsresult rv;
+
+ obj = nsnull;
+
+ if (bits & PTRBITS_REMOTE_BIT)
+ {
+ // pointer is to a remote object. we need to build a stub.
+
+ bits &= ~PTRBITS_REMOTE_BIT;
+
+ DConnectStub *stub;
+ rv = CreateStub(iid, peer, (DConAddr) bits, &stub);
+ if (NS_SUCCEEDED(rv))
+ obj = stub;
+ }
+ else if (bits)
+ {
+ // pointer is to one of our instance wrappers. Replace it with the
+ // real instance.
+
+ DConnectInstance *wrapper = (DConnectInstance *) bits;
+ // make sure we've been sent a valid wrapper
+ if (!CheckInstanceAndAddRef(wrapper, peer))
+ {
+ NS_NOTREACHED("instance wrapper not found");
+ return NS_ERROR_INVALID_ARG;
+ }
+ obj = wrapper->RealInstance();
+ NS_ADDREF(obj);
+ NS_RELEASE(wrapper);
+ }
+ else
+ {
+ // obj is alredy nsnull
+ }
+
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+#define EXCEPTION_STUB_ID \
+{ /* 70578d68-b25e-4370-a70c-89bbe56e6699 */ \
+ 0x70578d68, \
+ 0xb25e, \
+ 0x4370, \
+ {0xa7, 0x0c, 0x89, 0xbb, 0xe5, 0x6e, 0x66, 0x99} \
+}
+static NS_DEFINE_IID(kExceptionStubID, EXCEPTION_STUB_ID);
+
+// ExceptionStub is used to cache all primitive-typed bits of a remote nsIException
+// instance (such as the error message or line number) to:
+//
+// a) reduce the number of IPC calls;
+// b) make sure exception information is available to the calling party even if
+// the called party terminates immediately after returning an exception.
+// To achieve this, all cacheable information is serialized together with
+// the instance wrapper itself.
+
+class ExceptionStub : public nsIException
+{
+public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEXCEPTION
+
+ ExceptionStub(const nsACString &aMessage, nsresult aResult,
+ const nsACString &aName, const nsACString &aFilename,
+ PRUint32 aLineNumber, PRUint32 aColumnNumber,
+ DConnectStub *aXcptStub)
+ : mMessage(aMessage), mResult(aResult)
+ , mName(aName), mFilename(aFilename)
+ , mLineNumber (aLineNumber), mColumnNumber (aColumnNumber)
+ , mXcptStub (aXcptStub) { NS_ASSERTION(aXcptStub, "NULL"); }
+
+ ~ExceptionStub() {}
+
+ nsIException *Exception() { return (nsIException *)(nsISupports *) mXcptStub; }
+ DConnectStub *Stub() { return mXcptStub; }
+
+private:
+
+ nsCString mMessage;
+ nsresult mResult;
+ nsCString mName;
+ nsCString mFilename;
+ PRUint32 mLineNumber;
+ PRUint32 mColumnNumber;
+ nsRefPtr<DConnectStub> mXcptStub;
+};
+
+NS_IMPL_THREADSAFE_ADDREF(ExceptionStub)
+NS_IMPL_THREADSAFE_RELEASE(ExceptionStub)
+
+NS_IMETHODIMP
+ExceptionStub::QueryInterface(const nsID &aIID, void **aInstancePtr)
+{
+ NS_ASSERTION(aInstancePtr,
+ "QueryInterface requires a non-NULL destination!");
+
+ // used to discover if this is an ExceptionStub instance.
+ if (aIID.Equals(kExceptionStubID))
+ {
+ *aInstancePtr = this;
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ // regular NS_IMPL_QUERY_INTERFACE1 sequence
+
+ nsISupports* foundInterface = 0;
+
+ if (aIID.Equals(NS_GET_IID(nsIException)))
+ foundInterface = NS_STATIC_CAST(nsIException*, this);
+ else
+ if (aIID.Equals(NS_GET_IID(nsISupports)))
+ foundInterface = NS_STATIC_CAST(nsISupports*,
+ NS_STATIC_CAST(nsIException *, this));
+ else
+ if (mXcptStub)
+ {
+ // ask the real nsIException object
+ return mXcptStub->QueryInterface(aIID, aInstancePtr);
+ }
+
+ nsresult status;
+ if (!foundInterface)
+ status = NS_NOINTERFACE;
+ else
+ {
+ NS_ADDREF(foundInterface);
+ status = NS_OK;
+ }
+ *aInstancePtr = foundInterface;
+ return status;
+}
+
+/* readonly attribute string message; */
+NS_IMETHODIMP ExceptionStub::GetMessage(char **aMessage)
+{
+ AssertReturn(aMessage, NS_ERROR_INVALID_POINTER);
+ *aMessage = ToNewCString(mMessage);
+ return NS_OK;
+}
+
+/* readonly attribute nsresult result; */
+NS_IMETHODIMP ExceptionStub::GetResult(nsresult *aResult)
+{
+ AssertReturn(aResult, NS_ERROR_INVALID_POINTER);
+ *aResult = mResult;
+ return NS_OK;
+}
+
+/* readonly attribute string name; */
+NS_IMETHODIMP ExceptionStub::GetName(char **aName)
+{
+ AssertReturn(aName, NS_ERROR_INVALID_POINTER);
+ *aName = ToNewCString(mName);
+ return NS_OK;
+}
+
+/* readonly attribute string filename; */
+NS_IMETHODIMP ExceptionStub::GetFilename(char **aFilename)
+{
+ AssertReturn(aFilename, NS_ERROR_INVALID_POINTER);
+ *aFilename = ToNewCString(mFilename);
+ return NS_OK;
+}
+
+/* readonly attribute PRUint32 lineNumber; */
+NS_IMETHODIMP ExceptionStub::GetLineNumber(PRUint32 *aLineNumber)
+{
+ AssertReturn(aLineNumber, NS_ERROR_INVALID_POINTER);
+ *aLineNumber = mLineNumber;
+ return NS_OK;
+}
+
+/* readonly attribute PRUint32 columnNumber; */
+NS_IMETHODIMP ExceptionStub::GetColumnNumber(PRUint32 *aColumnNumber)
+{
+ AssertReturn(aColumnNumber, NS_ERROR_INVALID_POINTER);
+ *aColumnNumber = mColumnNumber;
+ return NS_OK;
+}
+
+/* readonly attribute nsIStackFrame location; */
+NS_IMETHODIMP ExceptionStub::GetLocation(nsIStackFrame **aLocation)
+{
+ if (Exception())
+ return Exception()->GetLocation (aLocation);
+ return NS_ERROR_UNEXPECTED;
+}
+
+/* readonly attribute nsIException inner; */
+NS_IMETHODIMP ExceptionStub::GetInner(nsIException **aInner)
+{
+ if (Exception())
+ return Exception()->GetInner (aInner);
+ return NS_ERROR_UNEXPECTED;
+}
+
+/* readonly attribute nsISupports data; */
+NS_IMETHODIMP ExceptionStub::GetData(nsISupports * *aData)
+{
+ if (Exception())
+ return Exception()->GetData (aData);
+ return NS_ERROR_UNEXPECTED;
+}
+
+/* string toString (); */
+NS_IMETHODIMP ExceptionStub::ToString(char **_retval)
+{
+ if (Exception())
+ return Exception()->ToString (_retval);
+ return NS_ERROR_UNEXPECTED;
+}
+
+nsresult
+ipcDConnectService::SerializeException(ipcMessageWriter &writer,
+ PRUint32 peer, nsIException *xcpt,
+ nsVoidArray &wrappers)
+{
+ PRBool cache_fields = PR_FALSE;
+
+ // first, seralize the nsIException pointer. The code is merely the same as
+ // in SerializeInterfaceParam() except that when the exception to serialize
+ // is an ExceptionStub instance and the real instance it stores as mXcpt
+ // is a DConnectStub corresponding to an object in the address space of the
+ // peer, we simply pass that object back instead of creating a new wrapper.
+
+ {
+ nsAutoLock lock (mLock);
+
+ if (mDisconnected)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ if (!xcpt)
+ {
+ // write null address
+#ifdef VBOX
+ // see ipcDConnectService::DeserializeException()!
+ PtrBits bits = 0;
+ writer.PutBytes(&bits, sizeof(bits));
+#else
+ writer.PutBytes(&xcpt, sizeof(xcpt));
+#endif
+ }
+ else
+ {
+ ExceptionStub *stub = nsnull;
+ nsresult rv = xcpt->QueryInterface(kExceptionStubID, (void **) &stub);
+ if (NS_SUCCEEDED(rv) && (stub->Stub()->PeerID() == peer))
+ {
+ // send the wrapper instance back to the peer
+ DConAddr p = stub->Stub()->Instance();
+ writer.PutBytes(&p, sizeof(p));
+ }
+ else
+ {
+ // create instance wrapper
+
+ const nsID &iid = nsIException::GetIID();
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ rv = GetInterfaceInfo(iid, getter_AddRefs(iinfo));
+ if (NS_FAILED(rv))
+ return rv;
+
+ DConnectInstance *wrapper = nsnull;
+
+ // first try to find an existing wrapper for the given object
+ if (!FindInstanceAndAddRef(peer, xcpt, &iid, &wrapper))
+ {
+ wrapper = new DConnectInstance(peer, iinfo, xcpt);
+ if (!wrapper)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = StoreInstance(wrapper);
+ if (NS_FAILED(rv))
+ {
+ delete wrapper;
+ return rv;
+ }
+
+ // reference the newly created wrapper
+ wrapper->AddRef();
+ }
+
+ // increase the second, IPC-only, reference counter (mandatory before
+ // trying wrappers.AppendElement() to make sure ReleaseIPC() will remove
+ // the wrapper from the instance map on failure)
+ wrapper->AddRefIPC();
+
+ if (!wrappers.AppendElement(wrapper))
+ {
+ wrapper->ReleaseIPC();
+ wrapper->Release();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // wrapper remains referenced when passing it to the client
+ // (will be released upon DCON_OP_RELEASE)
+
+ // send address of the instance wrapper, and set the low bit to indicate
+ // to the remote party that this is a remote instance wrapper.
+ PtrBits bits = ((PtrBits)(uintptr_t) wrapper) | PTRBITS_REMOTE_BIT;
+ writer.PutBytes(&bits, sizeof(bits));
+
+ // we want to cache fields to minimize the number of IPC calls when
+ // accessing exception data on the peer side
+ cache_fields = PR_TRUE;
+ }
+ NS_IF_RELEASE(stub);
+ }
+ }
+
+ if (!cache_fields)
+ return NS_OK;
+
+ nsresult rv;
+ nsXPIDLCString str;
+ PRUint32 num;
+
+ // message
+ rv = xcpt->GetMessage(getter_Copies(str));
+ if (NS_SUCCEEDED (rv))
+ {
+ PRUint32 len = str.Length();
+ nsACString::const_iterator begin;
+ const char *data = str.BeginReading(begin).get();
+ writer.PutInt32(len);
+ writer.PutBytes(data, len);
+ }
+ else
+ writer.PutInt32(0);
+
+ // result
+ nsresult res = 0;
+ xcpt->GetResult(&res);
+ writer.PutInt32(res);
+
+ // name
+ rv = xcpt->GetName(getter_Copies(str));
+ if (NS_SUCCEEDED (rv))
+ {
+ PRUint32 len = str.Length();
+ nsACString::const_iterator begin;
+ const char *data = str.BeginReading(begin).get();
+ writer.PutInt32(len);
+ writer.PutBytes(data, len);
+ }
+ else
+ writer.PutInt32(0);
+
+ // filename
+ rv = xcpt->GetFilename(getter_Copies(str));
+ if (NS_SUCCEEDED (rv))
+ {
+ PRUint32 len = str.Length();
+ nsACString::const_iterator begin;
+ const char *data = str.BeginReading(begin).get();
+ writer.PutInt32(len);
+ writer.PutBytes(data, len);
+ }
+ else
+ writer.PutInt32(0);
+
+ // lineNumber
+ num = 0;
+ xcpt->GetLineNumber(&num);
+ writer.PutInt32(num);
+
+ // columnNumber
+ num = 0;
+ xcpt->GetColumnNumber(&num);
+ writer.PutInt32(num);
+
+ return writer.HasError() ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
+}
+
+nsresult
+ipcDConnectService::DeserializeException(ipcMessageReader &reader,
+ PRUint32 peer,
+ nsIException **xcpt)
+{
+ NS_ASSERTION (xcpt, "NULL");
+ if (!xcpt)
+ return NS_ERROR_INVALID_POINTER;
+
+ nsresult rv;
+ PRUint32 len;
+
+ PtrBits bits = 0;
+ reader.GetBytes(&bits, sizeof(DConAddr));
+ if (reader.HasError())
+ return NS_ERROR_INVALID_ARG;
+
+ if (bits & PTRBITS_REMOTE_BIT)
+ {
+ // pointer is a peer-side exception instance wrapper,
+ // read cahced exception data and create a stub for it.
+
+ nsCAutoString message;
+ len = reader.GetInt32();
+ if (len)
+ {
+ message.SetLength(len);
+ char *buf = message.BeginWriting();
+ reader.GetBytes(buf, len);
+ }
+
+ nsresult result = reader.GetInt32();
+
+ nsCAutoString name;
+ len = reader.GetInt32();
+ if (len)
+ {
+ name.SetLength(len);
+ char *buf = name.BeginWriting();
+ reader.GetBytes(buf, len);
+ }
+
+ nsCAutoString filename;
+ len = reader.GetInt32();
+ if (len)
+ {
+ filename.SetLength(len);
+ char *buf = filename.BeginWriting();
+ reader.GetBytes(buf, len);
+ }
+
+ PRUint32 lineNumber = reader.GetInt32();
+ PRUint32 columnNumber = reader.GetInt32();
+
+ if (reader.HasError())
+ rv = NS_ERROR_INVALID_ARG;
+ else
+ {
+ DConAddr addr = (DConAddr) (bits & ~PTRBITS_REMOTE_BIT);
+ nsRefPtr<DConnectStub> stub;
+ rv = CreateStub(nsIException::GetIID(), peer, addr,
+ getter_AddRefs(stub));
+ if (NS_SUCCEEDED(rv))
+ {
+ // create a special exception "stub" with cached error info
+ ExceptionStub *xcptStub =
+ new ExceptionStub (message, result,
+ name, filename,
+ lineNumber, columnNumber,
+ stub);
+ if (xcptStub)
+ {
+ *xcpt = xcptStub;
+ NS_ADDREF(xcptStub);
+ }
+ else
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+ else if (bits)
+ {
+ // pointer is to our instance wrapper for nsIException we've sent before
+ // (the remote method we've called had called us back and got an exception
+ // from us that it decided to return as its own result). Replace it with
+ // the real instance.
+ DConnectInstance *wrapper = (DConnectInstance *) bits;
+ if (CheckInstanceAndAddRef(wrapper, peer))
+ {
+ *xcpt = (nsIException *) wrapper->RealInstance();
+ NS_ADDREF(wrapper->RealInstance());
+ wrapper->Release();
+ rv = NS_OK;
+ }
+ else
+ {
+ NS_NOTREACHED("instance wrapper not found");
+ rv = NS_ERROR_INVALID_ARG;
+ }
+ }
+ else
+ {
+ // the peer explicitly passed us a NULL exception to indicate that the
+ // exception on the current thread should be reset
+ *xcpt = NULL;
+ return NS_OK;
+ }
+
+
+ return rv;
+}
+
+//-----------------------------------------------------------------------------
+
+DConnectStub::~DConnectStub()
+{
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name = NULL;
+ mIInfo->GetNameShared(&name);
+ LOG(("{%p} DConnectStub::<dtor>(): peer=%d instance=0x%Lx {%s}\n",
+ this, mPeerID, mInstance, name));
+ }
+#endif
+
+ // release the cached nsISupports instance if it's not the same object
+ if (mCachedISupports != 0 && mCachedISupports != this)
+ NS_RELEASE(mCachedISupports);
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+DConnectStub::AddRef()
+{
+ nsrefcnt count;
+ count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ NS_LOG_ADDREF(this, count, "DConnectStub", sizeof(*this));
+ return count;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+DConnectStub::Release()
+{
+ nsrefcnt count;
+
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ if (dConnect)
+ {
+ // lock the stub lock on every release to make sure that once the counter
+ // drops to zero, we delete the stub from the set of stubs before a new
+ // request to create a stub on other thread tries to find the existing
+ // stub in the set (wchich could otherwise AddRef the object after it had
+ // Released to zero and pass it to the client right before its
+ // destruction).
+ nsAutoLock stubLock (dConnect->StubLock());
+
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "DConnectStub");
+
+
+ #ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ mIInfo->GetNameShared(&name);
+ LOG(("{%p} DConnectStub::Release(): peer=%d instance=0x%Lx {%s}, new count=%d\n",
+ this, mPeerID, mInstance, name, count));
+ }
+ #endif
+
+ // mRefCntLevels may already be empty here (due to the "stabilize" trick below)
+ if (mRefCntLevels.GetSize() > 0)
+ {
+ nsrefcnt top = (nsrefcnt) (long) mRefCntLevels.Peek();
+ NS_ASSERTION(top <= count + 1, "refcount is beyond the top level");
+
+ if (top == count + 1)
+ {
+ // refcount dropped to a value stored in ipcDConnectService::CreateStub.
+ // Send a RELEASE request to the peer (see also AddRefIPC).
+
+ // remove the top refcount value
+ mRefCntLevels.Pop();
+
+ if (0 == count)
+ {
+ // this is the last reference, remove from the set before we leave
+ // the lock, to provide atomicity of these two operations
+ dConnect->DeleteStub (this);
+
+ NS_ASSERTION(mRefCntLevels.GetSize() == 0, "refcnt levels are still left");
+ }
+
+ // leave the lock before sending a message
+ stubLock.unlock();
+
+ nsresult rv;
+
+ DConnectRelease msg;
+ msg.opcode_major = DCON_OP_RELEASE;
+ msg.opcode_minor = 0;
+ msg.flags = 0;
+ msg.request_index = 0; // not used, set to some unused value
+ msg.instance = mInstance;
+
+ // fire off asynchronously... we don't expect any response to this message.
+ rv = IPC_SendMessage(mPeerID, kDConnectTargetID,
+ (const PRUint8 *) &msg, sizeof(msg));
+ if (NS_FAILED(rv))
+ NS_WARNING("failed to send RELEASE event");
+ }
+ }
+ }
+ else
+ {
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "DConnectStub");
+ }
+
+ if (0 == count)
+ {
+ mRefCnt = 1; /* stabilize */
+ delete this;
+ return 0;
+ }
+
+ return count;
+}
+
+NS_IMETHODIMP
+DConnectStub::QueryInterface(const nsID &aIID, void **aInstancePtr)
+{
+ // used to discover if this is a DConnectStub instance.
+ if (aIID.Equals(kDConnectStubID))
+ {
+ *aInstancePtr = this;
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ // In order to truely support the COM Identity Rule across processes,
+ // we need to make the following code work:
+ //
+ // IFoo *foo = ...
+ // nsISupports unk;
+ // foo->QueryInterface(NS_GET_IID(nsISupports), (void **) &unk);
+ // unk->Release();
+ // nsISupports unk2;
+ // foo->QueryInterface(NS_GET_IID(nsISupports), (void **) &unk2);
+ // Assert (unk == unk2);
+ //
+ // I.e. querying nsISupports on the same object must always return the same
+ // pointer, even if the nsISupports object returned for the first time is
+ // released before it is requested for the second time, as long as the
+ // original object is kept alive (referenced by the client) between these
+ // two queries.
+ //
+ // This is done by remembering the nsISupports stub returned by the peer
+ // when nsISupports is queried for the first time. The remembered stub, when
+ // it is not the same as this object, is strongly referenced in order to
+ // keep it alive (and therefore have the same pointer value) as long as this
+ // object is alive.
+ //
+ // Besides supporting the Identity Rule, this also reduces the number of IPC
+ // calls, since an IPC call requesting nsISupports will be done only once
+ // per every stub object.
+
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ NS_ASSERTION(dConnect, "no ipcDConnectService (uninitialized?)");
+ if (!dConnect)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsresult rv;
+ PRBool needISupports = aIID.Equals(NS_GET_IID(nsISupports));
+
+ if (needISupports)
+ {
+ // XXX it would be sufficient to use cmpxchg here to protect access to
+ // mCachedISupports, but NSPR doesn't provide cross-platform cmpxchg
+ // functionality, so we have to use a shared lock instead...
+ PR_Lock(dConnect->StubQILock());
+
+ // check if we have already got a nsISupports stub for this object
+ if (mCachedISupports != 0)
+ {
+ *aInstancePtr = mCachedISupports;
+ NS_ADDREF(mCachedISupports);
+
+ PR_Unlock(dConnect->StubQILock());
+ return NS_OK;
+ }
+
+ // check if this object is nsISupports itself
+ {
+ nsIID *iid = 0;
+ rv = mIInfo->GetInterfaceIID(&iid);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && iid,
+ "nsIInterfaceInfo::GetInterfaceIID failed");
+ if (NS_SUCCEEDED(rv) && iid &&
+ iid->Equals(NS_GET_IID(nsISupports)))
+ {
+ nsMemory::Free((void*)iid);
+
+ // nsISupports is queried on nsISupports, return ourselves
+ *aInstancePtr = this;
+ NS_ADDREF_THIS();
+ // cache ourselves weakly
+ mCachedISupports = this;
+
+ PR_Unlock(dConnect->StubQILock());
+ return NS_OK;
+ }
+ if (iid)
+ nsMemory::Free((void*)iid);
+ }
+
+ // stub lock remains held until we've queried the peer
+ }
+
+ // else, we need to query the peer object by making an IPC call
+
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ mIInfo->GetNameShared(&name);
+ const char *nameQ;
+ nsCOMPtr <nsIInterfaceInfo> iinfoQ;
+ dConnect->GetInterfaceInfo(aIID, getter_AddRefs(iinfoQ));
+ if (iinfoQ) {
+ iinfoQ->GetNameShared(&nameQ);
+ LOG(("calling QueryInterface {%s} on peer object "
+ "(stub=%p, instance=0x%Lx {%s})\n",
+ nameQ, this, mInstance, name));
+ }
+ }
+#endif
+
+ DConnectSetupQueryInterface msg;
+ msg.opcode_minor = DCON_OP_SETUP_QUERY_INTERFACE;
+ msg.iid = aIID;
+ msg.instance = mInstance;
+
+ rv = SetupPeerInstance(mPeerID, &msg, sizeof(msg), aInstancePtr);
+
+ if (needISupports)
+ {
+ if (NS_SUCCEEDED(rv))
+ {
+ // cache the nsISupports object (SetupPeerInstance returns DConnectStub)
+ mCachedISupports = (DConnectStub *) *aInstancePtr;
+ // use a weak reference if nsISupports is the same object as us
+ if (this != mCachedISupports)
+ NS_ADDREF(mCachedISupports);
+ }
+
+ PR_Unlock(dConnect->StubQILock());
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+DConnectStub::GetInterfaceInfo(nsIInterfaceInfo **aInfo)
+{
+ NS_ADDREF(*aInfo = mIInfo);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+DConnectStub::CallMethod(PRUint16 aMethodIndex,
+ const nsXPTMethodInfo *aInfo,
+ nsXPTCMiniVariant *aParams)
+{
+ LOG(("DConnectStub::CallMethod [methodIndex=%hu]\n", aMethodIndex));
+
+ nsresult rv;
+
+ // reset the exception early. this is necessary because we may return a
+ // failure from here without setting an exception (which might be expected
+ // by the caller to detect the error origin: the interface we are stubbing
+ // may indicate in some way that it always sets the exception info on
+ // failure, therefore an "infoless" failure means the origin is RPC).
+ // besides that, resetting the excetion before every IPC call is exactly the
+ // same thing as Win32 RPC does, so doing this is useful for getting
+ // similarity in behaviors.
+
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
+ if (NS_FAILED (rv))
+ return rv;
+ nsCOMPtr <nsIExceptionManager> em;
+ rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
+ if (NS_FAILED (rv))
+ return rv;
+ rv = em->SetCurrentException(NULL);
+ if (NS_FAILED (rv))
+ return rv;
+
+ // ensure ipcDConnectService is not deleted before we finish
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ if (!dConnect)
+ return NS_ERROR_FAILURE;
+
+ // dump arguments
+
+ PRUint8 i, paramCount = aInfo->GetParamCount();
+
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ GetInterfaceInfo(getter_AddRefs(iinfo));
+ iinfo->GetNameShared(&name);
+ LOG((" instance=0x%Lx {%s}\n", mInstance, name));
+ LOG((" name=%s\n", aInfo->GetName()));
+ LOG((" param-count=%u\n", (PRUint32) paramCount));
+ }
+#endif
+
+
+ ipcMessageWriter writer(16 * paramCount);
+
+ // INVOKE message header
+ DConnectInvoke invoke;
+ invoke.opcode_major = DCON_OP_INVOKE;
+ invoke.opcode_minor = 0;
+ invoke.flags = 0;
+ invoke.request_index = NewRequestIndex();
+ invoke.instance = mInstance;
+ invoke.method_index = aMethodIndex;
+
+ LOG((" request-index=%d\n", (PRUint32) invoke.request_index));
+
+ writer.PutBytes(&invoke, sizeof(invoke));
+
+ // list of wrappers that get created during parameter serialization. if we
+ // are unable to send the INVOKE message, then we'll clean these up.
+ nsVoidArray wrappers;
+
+ for (i=0; i<paramCount; ++i)
+ {
+ const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);
+
+ if (paramInfo.IsIn() && !paramInfo.IsDipper())
+ {
+ const nsXPTType &type = paramInfo.GetType();
+
+ if (type.IsInterfacePointer())
+ {
+ nsID iid;
+ rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
+ aMethodIndex, aParams, PR_FALSE, iid);
+ if (NS_SUCCEEDED(rv))
+ rv = dConnect->SerializeInterfaceParam(writer, mPeerID, iid,
+ (nsISupports *) aParams[i].val.p,
+ wrappers);
+ }
+ else
+ rv = SerializeParam(writer, type, aParams[i]);
+
+ AssertMsgBreak(NS_SUCCEEDED(rv), ("i=%d rv=%#x\n", i, rv));
+ }
+ else if ((paramInfo.IsOut() || paramInfo.IsRetval()) && !aParams[i].val.p)
+ {
+ // report error early if NULL pointer is passed as an output parameter
+ rv = NS_ERROR_NULL_POINTER;
+ AssertMsgFailedBreak(("i=%d IsOut=%d IsRetval=%d NS_ERROR_NULL_POINTER\n", i, paramInfo.IsOut(), paramInfo.IsRetval()));
+ break;
+ }
+ }
+
+ if (NS_FAILED(rv))
+ {
+ // INVOKE message wasn't sent; clean up wrappers
+ dConnect->ReleaseWrappers(wrappers, mPeerID);
+ return rv;
+ }
+
+ // serialize input array parameters after everything else since the
+ // deserialization procedure will need to get a size_is value which may be
+ // stored in any preceeding or following param
+ for (i=0; i<paramCount; ++i)
+ {
+ const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);
+
+ if (paramInfo.GetType().IsArray() &&
+ paramInfo.IsIn() && !paramInfo.IsDipper())
+ {
+ rv = SerializeArrayParam(dConnect, writer, mPeerID, mIInfo, aMethodIndex,
+ *aInfo, aParams, PR_FALSE, paramInfo,
+ aParams[i].val.p, wrappers);
+ if (NS_FAILED(rv))
+ {
+ // INVOKE message wasn't sent; clean up wrappers
+ dConnect->ReleaseWrappers(wrappers, mPeerID);
+ return rv;
+ }
+ }
+ }
+
+ // temporarily disable the DConnect target observer to block normal processing
+ // of pending messages through the event queue.
+ IPC_DISABLE_MESSAGE_OBSERVER_FOR_SCOPE(kDConnectTargetID);
+
+ rv = IPC_SendMessage(mPeerID, kDConnectTargetID,
+ writer.GetBuffer(),
+ writer.GetSize());
+ LOG(("DConnectStub::CallMethod: IPC_SendMessage()=%08X\n", rv));
+ if (NS_FAILED(rv))
+ {
+ // INVOKE message wasn't delivered; clean up wrappers
+ dConnect->ReleaseWrappers(wrappers, mPeerID);
+ return rv;
+ }
+
+ // now, we wait for the method call to complete. during that time, it's
+ // possible that we'll receive other method call requests. we'll process
+ // those while waiting for out method call to complete. it's critical that
+ // we do so since those other method calls might need to complete before
+ // out method call can complete!
+
+ DConnectInvokeCompletion completion(mPeerID, &invoke);
+
+ do
+ {
+ rv = IPC_WaitMessage(IPC_SENDER_ANY, kDConnectTargetID,
+ &completion.GetSelector(), &completion,
+ DCON_WAIT_TIMEOUT);
+ LOG(("DConnectStub::CallMethod: IPC_WaitMessage()=%08X\n", rv));
+ if (NS_FAILED(rv))
+ {
+ // INVOKE message wasn't received; clean up wrappers
+ dConnect->ReleaseWrappers(wrappers, mPeerID);
+ return rv;
+ }
+ }
+ while (completion.IsPending());
+
+ ipcMessageReader reader(completion.Params(), completion.ParamsLen());
+
+ rv = completion.GetResult();
+ if (NS_SUCCEEDED(rv))
+ {
+ PRUint8 i;
+
+ // handle out-params and retvals: DCON_OP_INVOKE_REPLY has the data
+ for (i=0; i<paramCount; ++i)
+ {
+ const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);
+
+ if (paramInfo.IsOut() || paramInfo.IsRetval())
+ DeserializeResult(reader, paramInfo.GetType(), aParams[i]);
+ }
+
+ // fixup any interface pointers using a second pass so we can properly
+ // handle INTERFACE_IS referencing an IID that is an out param! This pass is
+ // also used to deserialize arrays (array data goes after all other params).
+ for (i=0; i<paramCount && NS_SUCCEEDED(rv); ++i)
+ {
+ const nsXPTParamInfo &paramInfo = aInfo->GetParam(i);
+ if ((paramInfo.IsOut() || paramInfo.IsRetval()) && aParams[i].val.p)
+ {
+ const nsXPTType &type = paramInfo.GetType();
+ if (type.IsInterfacePointer())
+ {
+ // grab the DConAddr value temporarily stored in the param, restore
+ // the pointer and free the temporarily allocated memory.
+ DConAddrPlusPtr *dptr = (DConAddrPlusPtr *)aParams[i].val.p;
+ PtrBits bits = dptr->addr;
+ aParams[i].val.p = dptr->p;
+ nsMemory::Free((void *)dptr);
+
+ // DeserializeInterfaceParamBits needs IID only if it's a remote object
+ nsID iid;
+ if (bits & PTRBITS_REMOTE_BIT)
+ rv = dConnect->GetIIDForMethodParam(mIInfo, aInfo, paramInfo, type,
+ aMethodIndex, aParams, PR_FALSE,
+ iid);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsISupports *obj = nsnull;
+ rv = dConnect->DeserializeInterfaceParamBits(bits, mPeerID, iid, obj);
+ if (NS_SUCCEEDED(rv))
+ *(void **)aParams[i].val.p = obj;
+ }
+ }
+ else if (type.IsArray())
+ {
+ void *array = nsnull;
+ rv = DeserializeArrayParam(dConnect, reader, mPeerID, mIInfo,
+ aMethodIndex, *aInfo, aParams, PR_FALSE,
+ paramInfo, PR_TRUE, array);
+ if (NS_SUCCEEDED(rv))
+ *(void **)aParams[i].val.p = array;
+ }
+ }
+ }
+ }
+
+ if (completion.Reply()->flags & DCON_OP_FLAGS_REPLY_EXCEPTION)
+ {
+ LOG(("got nsIException instance, will create a stub\n"));
+
+ nsIException *xcpt = nsnull;
+ rv = dConnect->DeserializeException (reader, mPeerID, &xcpt);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = em->SetCurrentException(xcpt);
+ NS_IF_RELEASE(xcpt);
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception");
+ }
+
+ return NS_SUCCEEDED(rv) ? completion.GetResult() : rv;
+}
+
+//-----------------------------------------------------------------------------
+
+class DConnectSetupCompletion : public DConnectCompletion
+{
+public:
+ DConnectSetupCompletion(PRUint32 peer, const DConnectSetup *setup)
+ : DConnectCompletion(peer, DCON_OP_SETUP_REPLY, setup->request_index)
+ , mSetup(setup)
+ , mStatus(NS_OK)
+ {}
+
+ void OnResponseAvailable(PRUint32 sender, const DConnectOp *op, PRUint32 opLen)
+ {
+ if (op->opcode_major != DCON_OP_SETUP_REPLY)
+ {
+ NS_NOTREACHED("unexpected response");
+ mStatus = NS_ERROR_UNEXPECTED;
+ return;
+ }
+
+ if (opLen < sizeof(DConnectSetupReply))
+ {
+ NS_NOTREACHED("unexpected response size");
+ mStatus = NS_ERROR_UNEXPECTED;
+ return;
+ }
+
+ const DConnectSetupReply *reply = (const DConnectSetupReply *) op;
+
+ LOG(("got SETUP_REPLY: status=%x instance=0x%Lx\n", reply->status, reply->instance));
+
+ mStatus = reply->status;
+
+ if (NS_SUCCEEDED(reply->status))
+ {
+ // ensure ipcDConnectService is not deleted before we finish
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ nsresult rv;
+ if (dConnect)
+ rv = dConnect->CreateStub(mSetup->iid, sender, reply->instance,
+ getter_AddRefs(mStub));
+ else
+ rv = NS_ERROR_FAILURE;
+ if (NS_FAILED(rv))
+ mStatus = rv;
+ }
+
+ if (reply->flags & DCON_OP_FLAGS_REPLY_EXCEPTION)
+ {
+ const PRUint8 *params = ((const PRUint8 *) op) + sizeof (DConnectSetupReply);
+ const PRUint32 paramsLen = opLen - sizeof (DConnectSetupReply);
+
+ ipcMessageReader reader(params, paramsLen);
+
+ LOG(("got nsIException instance, will create a stub\n"));
+
+ nsresult rv;
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
+ if (NS_SUCCEEDED(rv))
+ {
+ // ensure ipcDConnectService is not deleted before we finish
+ nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
+ if (dConnect)
+ {
+ nsIException *xcpt = nsnull;
+ rv = dConnect->DeserializeException (reader, sender, &xcpt);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = em->SetCurrentException(xcpt);
+ NS_IF_RELEASE(xcpt);
+ }
+ }
+ else
+ rv = NS_ERROR_UNEXPECTED;
+ }
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception");
+ if (NS_FAILED(rv))
+ mStatus = rv;
+ }
+ }
+
+ nsresult GetStub(void **aInstancePtr)
+ {
+ if (NS_FAILED(mStatus))
+ return mStatus;
+
+ DConnectStub *stub = mStub;
+ NS_IF_ADDREF(stub);
+ *aInstancePtr = stub;
+ return NS_OK;
+ }
+
+private:
+ const DConnectSetup *mSetup;
+ nsresult mStatus;
+ nsRefPtr<DConnectStub> mStub;
+};
+
+// static
+nsresult
+SetupPeerInstance(PRUint32 aPeerID, DConnectSetup *aMsg, PRUint32 aMsgLen,
+ void **aInstancePtr)
+{
+ *aInstancePtr = nsnull;
+
+ aMsg->opcode_major = DCON_OP_SETUP;
+ aMsg->flags = 0;
+ aMsg->request_index = NewRequestIndex();
+
+ // temporarily disable the DConnect target observer to block normal processing
+ // of pending messages through the event queue.
+ IPC_DISABLE_MESSAGE_OBSERVER_FOR_SCOPE(kDConnectTargetID);
+
+ // send SETUP message, expect SETUP_REPLY
+
+ nsresult rv = IPC_SendMessage(aPeerID, kDConnectTargetID,
+ (const PRUint8 *) aMsg, aMsgLen);
+ if (NS_FAILED(rv))
+ return rv;
+
+ DConnectSetupCompletion completion(aPeerID, aMsg);
+
+ // need to allow messages from other clients to be processed immediately
+ // to avoid distributed dead locks. the completion's OnMessageAvailable
+ // will call our default OnMessageAvailable if it receives any message
+ // other than the one for which it is waiting.
+
+ do
+ {
+ rv = IPC_WaitMessage(IPC_SENDER_ANY, kDConnectTargetID,
+ &completion.GetSelector(), &completion,
+ DCON_WAIT_TIMEOUT);
+ if (NS_FAILED(rv))
+ break;
+
+ rv = completion.GetStub(aInstancePtr);
+ }
+ while (NS_SUCCEEDED(rv) && *aInstancePtr == nsnull);
+
+ return rv;
+}
+
+//-----------------------------------------------------------------------------
+
+#if defined(DCONNECT_MULTITHREADED) && !defined(DCONNECT_WITH_IPRT_REQ_POOL)
+
+class DConnectWorker : public nsIRunnable
+{
+public:
+ // no reference counting
+ NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
+ NS_IMETHOD_(nsrefcnt) Release() { return 1; }
+ NS_IMETHOD QueryInterface(const nsIID &aIID, void **aInstancePtr);
+
+ NS_DECL_NSIRUNNABLE
+
+ DConnectWorker(ipcDConnectService *aDConnect) : mDConnect (aDConnect), mIsRunnable (PR_FALSE) {}
+ NS_HIDDEN_(nsresult) Init();
+ NS_HIDDEN_(void) Join() { mThread->Join(); };
+ NS_HIDDEN_(bool) IsRunning() { return mIsRunnable; };
+
+private:
+ nsCOMPtr <nsIThread> mThread;
+ ipcDConnectService *mDConnect;
+
+ // Indicate if thread might be quickly joined on shutdown.
+ volatile bool mIsRunnable;
+};
+
+NS_IMPL_QUERY_INTERFACE1(DConnectWorker, nsIRunnable)
+
+nsresult
+DConnectWorker::Init()
+{
+ return NS_NewThread(getter_AddRefs(mThread), this, 0, PR_JOINABLE_THREAD);
+}
+
+NS_IMETHODIMP
+DConnectWorker::Run()
+{
+ LOG(("DConnect Worker thread started.\n"));
+
+ mIsRunnable = PR_TRUE;
+
+ nsAutoMonitor mon(mDConnect->mPendingMon);
+
+ while (!mDConnect->mDisconnected)
+ {
+ DConnectRequest *request = mDConnect->mPendingQ.First();
+ if (!request)
+ {
+ mDConnect->mWaitingWorkers++;
+ {
+ // Note: we attempt to enter mWaitingWorkersMon from under mPendingMon
+ // here, but it should be safe because it's the only place where it
+ // happens. We could exit mPendingMon first, but we need to wait on it
+ // shorltly afterwards, which in turn will require us to enter it again
+ // just to exit immediately and start waiting. This seems to me a bit
+ // stupid (exit->enter->exit->wait).
+ nsAutoMonitor workersMon(mDConnect->mWaitingWorkersMon);
+ workersMon.NotifyAll();
+ }
+
+ nsresult rv = mon.Wait();
+ mDConnect->mWaitingWorkers--;
+
+ if (NS_FAILED(rv))
+ break;
+ }
+ else
+ {
+ LOG(("DConnect Worker thread got request.\n"));
+
+ // remove the request from the queue
+ mDConnect->mPendingQ.RemoveFirst();
+
+ PRBool pendingQEmpty = mDConnect->mPendingQ.IsEmpty();
+ mon.Exit();
+
+ if (pendingQEmpty)
+ {
+ nsAutoMonitor workersMon(mDConnect->mWaitingWorkersMon);
+ workersMon.NotifyAll();
+ }
+
+ // request is processed outside the queue monitor
+ mDConnect->OnIncomingRequest(request->peer, request->op, request->opLen);
+ delete request;
+
+ mon.Enter();
+ }
+ }
+
+ mIsRunnable = PR_FALSE;
+
+ LOG(("DConnect Worker thread stopped.\n"));
+ return NS_OK;
+}
+
+// called only on DConnect message thread
+nsresult
+ipcDConnectService::CreateWorker()
+{
+ DConnectWorker *worker = new DConnectWorker(this);
+ if (!worker)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = worker->Init();
+ if (NS_SUCCEEDED(rv))
+ {
+ nsAutoLock lock(mLock);
+ /* tracking an illegal join in Shutdown. */
+ NS_ASSERTION(!mDisconnected, "CreateWorker racing Shutdown");
+ if (!mWorkers.AppendElement(worker))
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ if (NS_FAILED(rv))
+ delete worker;
+ return rv;
+}
+
+#endif // defined(DCONNECT_MULTITHREADED) && !defined(DCONNECT_WITH_IPRT_REQ_POOL)
+
+//-----------------------------------------------------------------------------
+
+ipcDConnectService::ipcDConnectService()
+ : mLock(NULL)
+ , mStubLock(NULL)
+ , mDisconnected(PR_TRUE)
+ , mStubQILock(NULL)
+#if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+ , mhReqPool(NIL_RTREQPOOL)
+#endif
+{
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+EnumerateInstanceMapAndDelete (const DConnectInstanceKey::Key &aKey,
+ DConnectInstance *aData,
+ void *userArg)
+{
+ // this method is to be called on ipcDConnectService shutdown only
+ // (after which no DConnectInstances may exist), so forcibly delete them
+ // disregarding the reference counter
+
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ aData->InterfaceInfo()->GetNameShared(&name);
+ LOG(("ipcDConnectService: WARNING: deleting unreleased "
+ "instance=%p iface=%p {%s}\n", aData, aData->RealInstance(), name));
+ }
+#endif
+
+ delete aData;
+ return PL_DHASH_NEXT;
+}
+
+ipcDConnectService::~ipcDConnectService()
+{
+ if (!mDisconnected)
+ Shutdown();
+
+ mInstance = nsnull;
+ PR_DestroyLock(mStubQILock);
+ PR_DestroyLock(mStubLock);
+ PR_DestroyLock(mLock);
+#if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+ RTReqPoolRelease(mhReqPool);
+ mhReqPool = NIL_RTREQPOOL;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+
+nsresult
+ipcDConnectService::Init()
+{
+ nsresult rv;
+
+ LOG(("ipcDConnectService::Init.\n"));
+
+ rv = IPC_DefineTarget(kDConnectTargetID, this);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = IPC_AddClientObserver(this);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!mInstances.Init())
+ return NS_ERROR_OUT_OF_MEMORY;
+ if (!mInstanceSet.Init())
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mStubLock = PR_NewLock();
+ if (!mStubLock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!mStubs.Init())
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mIIM = do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mStubQILock = PR_NewLock();
+ if (!mStubQILock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+#if defined(DCONNECT_MULTITHREADED)
+# if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+ int vrc = RTReqPoolCreate(1024 /*cMaxThreads*/, 10*RT_MS_1SEC /*cMsMinIdle*/,
+ 8 /*cThreadsPushBackThreshold */, RT_MS_1SEC /* cMsMaxPushBack */,
+ "DCon", &mhReqPool);
+ if (RT_FAILURE(vrc))
+ {
+ mhReqPool = NIL_RTREQPOOL;
+ return NS_ERROR_FAILURE;
+ }
+
+ mDisconnected = PR_FALSE;
+
+# else
+
+ mPendingMon = nsAutoMonitor::NewMonitor("DConnect pendingQ monitor");
+ if (!mPendingMon)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mWaitingWorkers = 0;
+
+ mWaitingWorkersMon = nsAutoMonitor::NewMonitor("DConnect waiting workers monitor");
+ if (!mWaitingWorkersMon)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ /* The DConnectWorker::Run method checks the ipcDConnectService::mDisconnected.
+ * So mDisconnect must be set here to avoid an immediate exit of the worker thread.
+ */
+ mDisconnected = PR_FALSE;
+
+ // create a single worker thread
+ rv = CreateWorker();
+ if (NS_FAILED(rv))
+ {
+ mDisconnected = PR_TRUE;
+ return rv;
+ }
+
+# endif
+#else
+
+ mDisconnected = PR_FALSE;
+
+#endif
+
+ mInstance = this;
+
+ LOG(("ipcDConnectService::Init NS_OK.\n"));
+ return NS_OK;
+}
+
+void
+ipcDConnectService::Shutdown()
+{
+ {
+ // set the disconnected flag to make sensitive public methods
+ // unavailale from other (non worker) threads.
+ nsAutoLock lock(mLock);
+ mDisconnected = PR_TRUE;
+ }
+
+#if defined(DCONNECT_MULTITHREADED)
+# if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+
+# if defined(DCONNECT_STATS)
+ fprintf(stderr, "ipcDConnectService Stats\n");
+ fprintf(stderr,
+ " => number of worker threads: %llu (created %llu)\n"
+ " => requests processed: %llu\n"
+ " => avg requests process time: %llu ns\n"
+ " => avg requests waiting time: %llu ns\n",
+ RTReqPoolGetStat(mhReqPool, RTREQPOOLSTAT_THREADS),
+ RTReqPoolGetStat(mhReqPool, RTREQPOOLSTAT_THREADS_CREATED),
+ RTReqPoolGetStat(mhReqPool, RTREQPOOLSTAT_REQUESTS_PROCESSED),
+ RTReqPoolGetStat(mhReqPool, RTREQPOOLSTAT_NS_AVERAGE_REQ_PROCESSING),
+ RTReqPoolGetStat(mhReqPool, RTREQPOOLSTAT_NS_AVERAGE_REQ_QUEUED)
+ );
+# endif
+
+ RTReqPoolRelease(mhReqPool);
+ mhReqPool = NIL_RTREQPOOL;
+
+# else
+
+ {
+ // remove all pending messages and wake up all workers.
+ // mDisconnected is true here and they will terminate execution after
+ // processing the last request.
+ nsAutoMonitor mon(mPendingMon);
+ mPendingQ.DeleteAll();
+ mon.NotifyAll();
+ }
+
+#if defined(DCONNECT_STATS)
+ fprintf(stderr, "ipcDConnectService Stats\n");
+ fprintf(stderr, " => number of worker threads: %d\n", mWorkers.Count());
+ LOG(("ipcDConnectService Stats\n"));
+ LOG((" => number of worker threads: %d\n", mWorkers.Count()));
+#endif
+
+
+ // Iterate over currently running worker threads
+ // during VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS, join() those who
+ // exited a working loop and abandon ones which have not
+ // managed to do that when timeout occurred.
+ LOG(("Worker threads: %d\n", mWorkers.Count()));
+ uint64_t tsStart = RTTimeMilliTS();
+ while ((tsStart + VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS ) > RTTimeMilliTS() && mWorkers.Count() > 0)
+ {
+ // Some array elements might be deleted while iterating. Going from the last
+ // to the first array element (intentionally) in order to do not conflict with
+ // array indexing once element is deleted.
+ for (int i = mWorkers.Count() - 1; i >= 0; i--)
+ {
+ DConnectWorker *worker = NS_STATIC_CAST(DConnectWorker *, mWorkers[i]);
+ if (worker->IsRunning() == PR_FALSE)
+ {
+ LOG(("Worker %p joined.\n", worker));
+ worker->Join();
+ delete worker;
+ mWorkers.RemoveElementAt(i);
+ }
+ }
+
+ /* Double-ckeck if we already allowed to quit. */
+ if ((tsStart + VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS ) < RTTimeMilliTS() || mWorkers.Count() == 0)
+ break;
+
+ // Relax a bit before the next round.
+ RTThreadSleep(10);
+ }
+
+ LOG(("There are %d thread(s) left.\n", mWorkers.Count()));
+
+ // If there are some running threads left, terminate the process.
+ if (mWorkers.Count() > 0)
+ exit(1);
+
+
+ nsAutoMonitor::DestroyMonitor(mWaitingWorkersMon);
+ nsAutoMonitor::DestroyMonitor(mPendingMon);
+
+# endif
+#endif
+
+ // make sure we have released all instances
+ mInstances.EnumerateRead(EnumerateInstanceMapAndDelete, nsnull);
+
+ mInstanceSet.Clear();
+ mInstances.Clear();
+
+ // clear the stub table
+ // (this will not release stubs -- it's the client's responsibility)
+ mStubs.Clear();
+}
+
+// this should be inlined
+nsresult
+ipcDConnectService::GetInterfaceInfo(const nsID &iid, nsIInterfaceInfo **result)
+{
+ return mIIM->GetInfoForIID(&iid, result);
+}
+
+// this is adapted from the version in xpcwrappednative.cpp
+nsresult
+ipcDConnectService::GetIIDForMethodParam(nsIInterfaceInfo *iinfo,
+ const nsXPTMethodInfo *methodInfo,
+ const nsXPTParamInfo &paramInfo,
+ const nsXPTType &type,
+ PRUint16 methodIndex,
+ nsXPTCMiniVariant *dispatchParams,
+ PRBool isXPTCVariantArray,
+ nsID &result)
+{
+ PRUint8 argnum, tag = type.TagPart();
+ nsresult rv;
+
+ if (tag == nsXPTType::T_INTERFACE)
+ {
+ rv = iinfo->GetIIDForParamNoAlloc(methodIndex, &paramInfo, &result);
+ }
+ else if (tag == nsXPTType::T_INTERFACE_IS)
+ {
+ rv = iinfo->GetInterfaceIsArgNumberForParam(methodIndex, &paramInfo, &argnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const nsXPTParamInfo& arg_param = methodInfo->GetParam(argnum);
+ const nsXPTType& arg_type = arg_param.GetType();
+
+ // The xpidl compiler ensures this. We reaffirm it for safety.
+ if (!arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_IID)
+ return NS_ERROR_UNEXPECTED;
+
+ nsID *p = (nsID *) GET_PARAM(dispatchParams, isXPTCVariantArray, argnum).val.p;
+ if (!p)
+ return NS_ERROR_UNEXPECTED;
+
+ result = *p;
+ }
+ else
+ rv = NS_ERROR_UNEXPECTED;
+ return rv;
+}
+
+nsresult
+ipcDConnectService::StoreInstance(DConnectInstance *wrapper)
+{
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ wrapper->InterfaceInfo()->GetNameShared(&name);
+ LOG(("ipcDConnectService::StoreInstance(): instance=%p iface=%p {%s}\n",
+ wrapper, wrapper->RealInstance(), name));
+ }
+#endif
+
+ nsresult rv = mInstanceSet.Put(wrapper);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = mInstances.Put(wrapper->GetKey(), wrapper)
+ ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ if (NS_FAILED(rv))
+ mInstanceSet.Remove(wrapper);
+ }
+ return rv;
+}
+
+void
+ipcDConnectService::DeleteInstance(DConnectInstance *wrapper,
+ PRBool locked /* = PR_FALSE */)
+{
+ if (!locked)
+ PR_Lock(mLock);
+
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ wrapper->InterfaceInfo()->GetNameShared(&name);
+ LOG(("ipcDConnectService::DeleteInstance(): instance=%p iface=%p {%s}\n",
+ wrapper, wrapper->RealInstance(), name));
+ }
+#endif
+
+ mInstances.Remove(wrapper->GetKey());
+ mInstanceSet.Remove(wrapper);
+
+ if (!locked)
+ PR_Unlock(mLock);
+}
+
+PRBool
+ipcDConnectService::FindInstanceAndAddRef(PRUint32 peer,
+ const nsISupports *obj,
+ const nsIID *iid,
+ DConnectInstance **wrapper)
+{
+ PRBool result = mInstances.Get(DConnectInstanceKey::Key(peer, obj, iid), wrapper);
+ if (result)
+ (*wrapper)->AddRef();
+ return result;
+}
+
+PRBool
+ipcDConnectService::CheckInstanceAndAddRef(DConnectInstance *wrapper, PRUint32 peer)
+{
+ nsAutoLock lock (mLock);
+
+ if (mInstanceSet.Contains(wrapper) && wrapper->Peer() == peer)
+ {
+ wrapper->AddRef();
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+nsresult
+ipcDConnectService::StoreStub(DConnectStub *stub)
+{
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ stub->GetInterfaceInfo(getter_AddRefs(iinfo));
+ iinfo->GetNameShared(&name);
+ LOG(("ipcDConnectService::StoreStub(): stub=%p instance=0x%Lx {%s}\n",
+ stub, stub->Instance(), name));
+ }
+#endif
+
+ return mStubs.Put(stub->GetKey(), stub)
+ ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+void
+ipcDConnectService::DeleteStub(DConnectStub *stub)
+{
+#ifdef IPC_LOGGING
+ if (IPC_LOG_ENABLED())
+ {
+ const char *name;
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ stub->GetInterfaceInfo(getter_AddRefs(iinfo));
+ iinfo->GetNameShared(&name);
+ LOG(("ipcDConnectService::DeleteStub(): stub=%p instance=0x%Lx {%s}\n",
+ stub, stub->Instance(), name));
+ }
+#endif
+
+ // this method is intended to be called only from DConnectStub::Release().
+ // the stub object is not deleted when removed from the table, because
+ // DConnectStub pointers are not owned by mStubs.
+ mStubs.Remove(stub->GetKey());
+}
+
+// not currently used
+#if 0
+PRBool
+ipcDConnectService::FindStubAndAddRef(PRUint32 peer, const DConAddr instance,
+ DConnectStub **stub)
+{
+ nsAutoLock stubLock (mStubLock);
+
+ PRBool result = mStubs.Get(DConnectStubKey::Key(peer, instance), stub);
+ if (result)
+ NS_ADDREF(*stub);
+ return result;
+}
+#endif
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(ipcDConnectService, ipcIDConnectService,
+ ipcIMessageObserver,
+ ipcIClientObserver)
+
+NS_IMETHODIMP
+ipcDConnectService::CreateInstance(PRUint32 aPeerID,
+ const nsID &aCID,
+ const nsID &aIID,
+ void **aInstancePtr)
+{
+ DConnectSetupClassID msg;
+ msg.opcode_minor = DCON_OP_SETUP_NEW_INST_CLASSID;
+ msg.iid = aIID;
+ msg.classid = aCID;
+
+ return SetupPeerInstance(aPeerID, &msg, sizeof(msg), aInstancePtr);
+}
+
+NS_IMETHODIMP
+ipcDConnectService::CreateInstanceByContractID(PRUint32 aPeerID,
+ const char *aContractID,
+ const nsID &aIID,
+ void **aInstancePtr)
+{
+ size_t slen = strlen(aContractID);
+ size_t size = sizeof(DConnectSetupContractID) + slen;
+
+ DConnectSetupContractID *msg =
+ (DConnectSetupContractID *) malloc(size);
+
+ msg->opcode_minor = DCON_OP_SETUP_NEW_INST_CONTRACTID;
+ msg->iid = aIID;
+ memcpy(&msg->contractid, aContractID, slen + 1);
+
+ nsresult rv = SetupPeerInstance(aPeerID, msg, size, aInstancePtr);
+
+ free(msg);
+ return rv;
+}
+
+NS_IMETHODIMP
+ipcDConnectService::GetService(PRUint32 aPeerID,
+ const nsID &aCID,
+ const nsID &aIID,
+ void **aInstancePtr)
+{
+ DConnectSetupClassID msg;
+ msg.opcode_minor = DCON_OP_SETUP_GET_SERV_CLASSID;
+ msg.iid = aIID;
+ msg.classid = aCID;
+
+ return SetupPeerInstance(aPeerID, &msg, sizeof(msg), aInstancePtr);
+}
+
+NS_IMETHODIMP
+ipcDConnectService::GetServiceByContractID(PRUint32 aPeerID,
+ const char *aContractID,
+ const nsID &aIID,
+ void **aInstancePtr)
+{
+ size_t slen = strlen(aContractID);
+ size_t size = sizeof(DConnectSetupContractID) + slen;
+
+ DConnectSetupContractID *msg =
+ (DConnectSetupContractID *) malloc(size);
+
+ msg->opcode_minor = DCON_OP_SETUP_GET_SERV_CONTRACTID;
+ msg->iid = aIID;
+ memcpy(&msg->contractid, aContractID, slen + 1);
+
+ nsresult rv = SetupPeerInstance(aPeerID, msg, size, aInstancePtr);
+
+ free(msg);
+ return rv;
+}
+
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+ipcDConnectService::OnMessageAvailable(PRUint32 aSenderID,
+ const nsID &aTarget,
+ const PRUint8 *aData,
+ PRUint32 aDataLen)
+{
+ if (mDisconnected)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ const DConnectOp *op = (const DConnectOp *) aData;
+
+ LOG (("ipcDConnectService::OnMessageAvailable: "
+ "senderID=%d, opcode_major=%d, index=%d\n",
+ aSenderID, op->opcode_major, op->request_index));
+
+#if defined(DCONNECT_MULTITHREADED)
+# if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+
+ void *pvDataDup = RTMemDup(aData, aDataLen);
+ if (RT_UNLIKELY(!pvDataDup))
+ return NS_ERROR_OUT_OF_MEMORY;
+ int rc = RTReqPoolCallVoidNoWait(mhReqPool, (PFNRT)ProcessMessageOnWorkerThread, 4,
+ this, aSenderID, pvDataDup, aDataLen);
+ if (RT_FAILURE(rc))
+ return NS_ERROR_FAILURE;
+
+# else
+
+ nsAutoMonitor mon(mPendingMon);
+ mPendingQ.Append(new DConnectRequest(aSenderID, op, aDataLen));
+ // notify a worker
+ mon.Notify();
+ mon.Exit();
+
+ // Yield the cpu so a worker can get a chance to start working without too much fuss.
+ PR_Sleep(PR_INTERVAL_NO_WAIT);
+ mon.Enter();
+ // examine the queue
+ if (mPendingQ.Count() > mWaitingWorkers)
+ {
+ // wait a little while to let the workers empty the queue.
+ mon.Exit();
+ {
+ PRUint32 ticks = PR_MillisecondsToInterval(PR_MIN(mWorkers.Count() / 20 + 1, 10));
+ nsAutoMonitor workersMon(mWaitingWorkersMon);
+ workersMon.Wait(ticks);
+ }
+ mon.Enter();
+ // examine the queue again
+ if (mPendingQ.Count() > mWaitingWorkers)
+ {
+ // we need one more worker
+ nsresult rv = CreateWorker();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create one more worker thread");
+ rv = rv;
+ }
+ }
+
+# endif
+#else
+
+ OnIncomingRequest(aSenderID, op, aDataLen);
+
+#endif
+
+ return NS_OK;
+}
+
+struct PruneInstanceMapForPeerArgs
+{
+ ipcDConnectService *that;
+ PRUint32 clientID;
+ nsVoidArray &wrappers;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+PruneInstanceMapForPeer (const DConnectInstanceKey::Key &aKey,
+ DConnectInstance *aData,
+ void *userArg)
+{
+ PruneInstanceMapForPeerArgs *args = (PruneInstanceMapForPeerArgs *)userArg;
+ NS_ASSERTION(args, "PruneInstanceMapForPeerArgs is NULL");
+
+ if (args && args->clientID == aData->Peer())
+ {
+ nsrefcnt countIPC = aData->ReleaseIPC(PR_TRUE /* locked */);
+
+ LOG(("ipcDConnectService::PruneInstanceMapForPeer: "
+ "instance=%p: %d IPC refs to release\n",
+ aData, countIPC + 1));
+
+ // release all IPC instances of the "officially dead" client (see
+ // #OnRelease() to understand why it must be done under the lock). Note
+ // that due to true multithreading, late OnRelease() requests may still
+ // happen on other worker threads *after* OnClientStateChange() has been
+ // called, but it's OK because the instance will be removed from the map
+ // by the below code alreay and won't be deleted for the second time.
+ while (countIPC)
+ {
+ countIPC = aData->ReleaseIPC(PR_TRUE /* locked */);
+ aData->Release();
+ }
+
+ // collect the instance for the last release
+ // (we'll do it later outside the lock)
+ if (!args->wrappers.AppendElement(aData))
+ {
+ NS_NOTREACHED("Not enough memory");
+ // bad but what to do
+ aData->Release();
+ }
+ }
+ return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+ipcDConnectService::OnClientStateChange(PRUint32 aClientID,
+ PRUint32 aClientState)
+{
+ LOG(("ipcDConnectService::OnClientStateChange: aClientID=%d, aClientState=%d\n",
+ aClientID, aClientState));
+
+ if (aClientState == ipcIClientObserver::CLIENT_DOWN)
+ {
+ if (aClientID == IPC_SENDER_ANY)
+ {
+ // a special case: our IPC system is being shutdown, try to safely
+ // uninitialize everything...
+ Shutdown();
+ }
+ else
+ {
+ LOG(("ipcDConnectService::OnClientStateChange: "
+ "pruning all instances created for peer %d...\n", aClientID));
+
+ nsVoidArray wrappers;
+
+ {
+ nsAutoLock lock (mLock);
+
+ // make sure we have removed all instances from instance maps
+ PruneInstanceMapForPeerArgs args = { this, aClientID, wrappers };
+ mInstances.EnumerateRead(PruneInstanceMapForPeer, (void *)&args);
+ }
+
+ LOG(("ipcDConnectService::OnClientStateChange: "
+ "%d lost instances\n", wrappers.Count()));
+
+ // release all pending references left after PruneInstanceMapForPeer().
+ // this may call wrapper destructors so it's important to do that
+ // outside the lock because destructors will release the real objects
+ // which may need to make asynchronous use our service
+ for (PRInt32 i = 0; i < wrappers.Count(); ++i)
+ ((DConnectInstance *) wrappers[i])->Release();
+ }
+ }
+
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+#if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+/**
+ * Function called by the request thread pool to process a incoming request in
+ * the context of a worker thread.
+ */
+/* static */ DECLCALLBACK(void)
+ipcDConnectService::ProcessMessageOnWorkerThread(ipcDConnectService *aThis, PRUint32 aSenderID, void *aData, PRUint32 aDataLen)
+{
+ if (!aThis->mDisconnected)
+ aThis->OnIncomingRequest(aSenderID, (const DConnectOp *)aData, aDataLen);
+ RTMemFree(aData);
+}
+#endif
+
+void
+ipcDConnectService::OnIncomingRequest(PRUint32 peer, const DConnectOp *op, PRUint32 opLen)
+{
+ switch (op->opcode_major)
+ {
+ case DCON_OP_SETUP:
+ OnSetup(peer, (const DConnectSetup *) op, opLen);
+ break;
+ case DCON_OP_RELEASE:
+ OnRelease(peer, (const DConnectRelease *) op);
+ break;
+ case DCON_OP_INVOKE:
+ OnInvoke(peer, (const DConnectInvoke *) op, opLen);
+ break;
+ default:
+ NS_NOTREACHED("unknown opcode major");
+ }
+}
+
+void
+ipcDConnectService::OnSetup(PRUint32 peer, const DConnectSetup *setup, PRUint32 opLen)
+{
+ nsISupports *instance = nsnull;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ switch (setup->opcode_minor)
+ {
+ // CreateInstance
+ case DCON_OP_SETUP_NEW_INST_CLASSID:
+ {
+ const DConnectSetupClassID *setupCI = (const DConnectSetupClassID *) setup;
+
+ nsCOMPtr<nsIComponentManager> compMgr;
+ rv = NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (NS_SUCCEEDED(rv))
+ rv = compMgr->CreateInstance(setupCI->classid, nsnull, setupCI->iid, (void **) &instance);
+
+ break;
+ }
+
+ // CreateInstanceByContractID
+ case DCON_OP_SETUP_NEW_INST_CONTRACTID:
+ {
+ const DConnectSetupContractID *setupCI = (const DConnectSetupContractID *) setup;
+
+ nsCOMPtr<nsIComponentManager> compMgr;
+ rv = NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (NS_SUCCEEDED(rv))
+ rv = compMgr->CreateInstanceByContractID(setupCI->contractid, nsnull, setupCI->iid, (void **) &instance);
+
+ break;
+ }
+
+ // GetService
+ case DCON_OP_SETUP_GET_SERV_CLASSID:
+ {
+ const DConnectSetupClassID *setupCI = (const DConnectSetupClassID *) setup;
+
+ nsCOMPtr<nsIServiceManager> svcMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(svcMgr));
+ if (NS_SUCCEEDED(rv))
+ rv = svcMgr->GetService(setupCI->classid, setupCI->iid, (void **) &instance);
+ break;
+ }
+
+ // GetServiceByContractID
+ case DCON_OP_SETUP_GET_SERV_CONTRACTID:
+ {
+ const DConnectSetupContractID *setupCI = (const DConnectSetupContractID *) setup;
+
+ nsCOMPtr<nsIServiceManager> svcMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(svcMgr));
+ if (NS_SUCCEEDED(rv))
+ rv = svcMgr->GetServiceByContractID(setupCI->contractid, setupCI->iid, (void **) &instance);
+
+ break;
+ }
+
+ // QueryInterface
+ case DCON_OP_SETUP_QUERY_INTERFACE:
+ {
+ const DConnectSetupQueryInterface *setupQI = (const DConnectSetupQueryInterface *) setup;
+ DConnectInstance *QIinstance = (DConnectInstance *)setupQI->instance;
+
+ // make sure we've been sent a valid wrapper
+ if (!CheckInstanceAndAddRef(QIinstance, peer))
+ {
+ NS_NOTREACHED("instance wrapper not found");
+ rv = NS_ERROR_INVALID_ARG;
+ }
+ else
+ {
+ rv = QIinstance->RealInstance()->QueryInterface(setupQI->iid, (void **) &instance);
+ QIinstance->Release();
+ }
+ break;
+ }
+
+ default:
+ NS_NOTREACHED("unexpected minor opcode");
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ nsVoidArray wrappers;
+
+ // now, create instance wrapper, and store it in our instances set.
+ // this allows us to keep track of object references held on behalf of a
+ // particular peer. we can use this information to cleanup after a peer
+ // that disconnects without sending RELEASE messages for its objects.
+ DConnectInstance *wrapper = nsnull;
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ rv = GetInterfaceInfo(setup->iid, getter_AddRefs(iinfo));
+ if (NS_SUCCEEDED(rv))
+ {
+ nsAutoLock lock (mLock);
+
+ // first try to find an existing wrapper for the given object
+ if (!FindInstanceAndAddRef(peer, instance, &setup->iid, &wrapper))
+ {
+ wrapper = new DConnectInstance(peer, iinfo, instance);
+ if (!wrapper)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ else
+ {
+ rv = StoreInstance(wrapper);
+ if (NS_FAILED(rv))
+ {
+ delete wrapper;
+ wrapper = nsnull;
+ }
+ else
+ {
+ // reference the newly created wrapper
+ wrapper->AddRef();
+ }
+ }
+ }
+
+ if (wrapper)
+ {
+ // increase the second, IPC-only, reference counter (mandatory before
+ // trying wrappers.AppendElement() to make sure ReleaseIPC() will remove
+ // the wrapper from the instance map on failure)
+ wrapper->AddRefIPC();
+
+ if (!wrappers.AppendElement(wrapper))
+ {
+ wrapper->ReleaseIPC();
+ wrapper->Release();
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ // wrapper remains referenced when passing it to the client
+ // (will be released upon DCON_OP_RELEASE)
+ }
+ }
+
+ NS_IF_RELEASE(instance);
+
+ nsCOMPtr <nsIException> exception;
+ PRBool got_exception = PR_FALSE;
+
+ if (rv != NS_OK)
+ {
+ // try to fetch an nsIException possibly set by one of the setup methods
+ nsresult rv2;
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv2);
+ if (NS_SUCCEEDED(rv2))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rv2 = es->GetCurrentExceptionManager (getter_AddRefs (em));
+ if (NS_SUCCEEDED(rv2))
+ {
+ rv2 = em->GetCurrentException (getter_AddRefs (exception));
+ if (NS_SUCCEEDED(rv2))
+ {
+ LOG(("got nsIException instance, will serialize\n"));
+ got_exception = PR_TRUE;
+ }
+ }
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv2), "failed to get/serialize exception");
+ if (NS_FAILED(rv2))
+ rv = rv2;
+ }
+
+ ipcMessageWriter writer(64);
+
+ DConnectSetupReply msg;
+ msg.opcode_major = DCON_OP_SETUP_REPLY;
+ msg.opcode_minor = 0;
+ msg.flags = 0;
+ msg.request_index = setup->request_index;
+ msg.instance = (DConAddr)(uintptr_t)wrapper;
+ msg.status = rv;
+
+ if (got_exception)
+ msg.flags |= DCON_OP_FLAGS_REPLY_EXCEPTION;
+
+ writer.PutBytes(&msg, sizeof(msg));
+
+ if (got_exception)
+ {
+ rv = SerializeException(writer, peer, exception, wrappers);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialize exception");
+ }
+
+ // fire off SETUP_REPLY, don't wait for a response
+ if (NS_FAILED(rv))
+ rv = IPC_SendMessage(peer, kDConnectTargetID,
+ (const PRUint8 *) &msg, sizeof(msg));
+ else
+ rv = IPC_SendMessage(peer, kDConnectTargetID,
+ writer.GetBuffer(), writer.GetSize());
+
+ if (NS_FAILED(rv))
+ {
+ LOG(("unable to send SETUP_REPLY: rv=%x\n", rv));
+ ReleaseWrappers(wrappers, peer);
+ }
+}
+
+void
+ipcDConnectService::OnRelease(PRUint32 peer, const DConnectRelease *release)
+{
+ LOG(("ipcDConnectService::OnRelease [peer=%u instance=0x%Lx]\n",
+ peer, release->instance));
+
+ DConnectInstance *wrapper = (DConnectInstance *)release->instance;
+
+ nsAutoLock lock (mLock);
+
+ // make sure we've been sent a valid wrapper from the same peer we created
+ // this wrapper for
+ if (mInstanceSet.Contains(wrapper) && wrapper->Peer() == peer)
+ {
+ // release the IPC reference from under the lock to ensure atomicity of
+ // the "check + possible delete" sequence ("delete" is remove this wrapper
+ // from the instance map when the IPC reference counter drops to zero)
+ wrapper->ReleaseIPC(PR_TRUE /* locked */);
+ // leave the lock before Release() because it may call the destructor
+ // which will release the real object which may need to make asynchronous
+ // use our service
+ lock.unlock();
+ wrapper->Release();
+ }
+ else
+ {
+ // it is possible that the client disconnection event handler has released
+ // all client instances before the DCON_OP_RELEASE message sent by the
+ // client gets processed here (because of true multithreading). Just log
+ // a debug warning
+ LOG(("ipcDConnectService::OnRelease: WARNING: "
+ "instance wrapper %p for peer %d not found", wrapper, peer));
+ }
+}
+
+void
+ipcDConnectService::OnInvoke(PRUint32 peer, const DConnectInvoke *invoke, PRUint32 opLen)
+{
+ LOG(("ipcDConnectService::OnInvoke [peer=%u instance=0x%Lx method=%u]\n",
+ peer, invoke->instance, invoke->method_index));
+
+ DConnectInstance *wrapper = (DConnectInstance *)invoke->instance;
+
+ ipcMessageReader reader((const PRUint8 *) (invoke + 1), opLen - sizeof(*invoke));
+
+ const nsXPTMethodInfo *methodInfo;
+ nsXPTCVariant *params = nsnull;
+ nsCOMPtr<nsIInterfaceInfo> iinfo = nsnull;
+ PRUint8 i, paramCount = 0, paramUsed = 0;
+ nsresult rv;
+
+ nsCOMPtr <nsIException> exception;
+ PRBool got_exception = PR_FALSE;
+
+ // make sure we've been sent a valid wrapper
+ if (!CheckInstanceAndAddRef(wrapper, peer))
+ {
+ NS_NOTREACHED("instance wrapper not found");
+ wrapper = nsnull;
+ rv = NS_ERROR_INVALID_ARG;
+ goto end;
+ }
+
+ iinfo = wrapper->InterfaceInfo();
+
+ rv = iinfo->GetMethodInfo(invoke->method_index, &methodInfo);
+ if (NS_FAILED(rv))
+ goto end;
+
+ paramCount = methodInfo->GetParamCount();
+
+ LOG((" iface=%p\n", wrapper->RealInstance()));
+ LOG((" name=%s\n", methodInfo->GetName()));
+ LOG((" param-count=%u\n", (PRUint32) paramCount));
+ LOG((" request-index=%d\n", (PRUint32) invoke->request_index));
+
+ params = new nsXPTCVariant[paramCount];
+ if (!params)
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ goto end;
+ }
+
+ // setup |params| for xptcall
+
+ for (i=0; i<paramCount; ++i, ++paramUsed)
+ {
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+
+ // XXX are inout params an issue?
+ // yes, we will need to do v.ptr = &v.val for them (DeserializeParam doesn't
+ // currently do that) to let the callee correctly pick it up and change.
+
+ if (paramInfo.IsIn() && !paramInfo.IsDipper())
+ rv = DeserializeParam(reader, paramInfo.GetType(), params[i]);
+ else
+ rv = SetupParam(paramInfo, params[i]);
+
+ if (NS_FAILED(rv))
+ goto end;
+ }
+
+ // fixup any interface pointers. we do this with a second pass so that
+ // we can properly handle INTERFACE_IS. This pass is also used to deserialize
+ // arrays (array data goes after all other params).
+ for (i=0; i<paramCount; ++i)
+ {
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+ if (paramInfo.IsIn())
+ {
+ const nsXPTType &type = paramInfo.GetType();
+ if (type.IsInterfacePointer())
+ {
+ // grab the DConAddr value temporarily stored in the param
+#ifdef VBOX
+ PtrBits bits = params[i].val.u64;
+#else
+ PtrBits bits = (PtrBits)(uintptr_t) params[i].val.p;
+#endif
+
+ // DeserializeInterfaceParamBits needs IID only if it's a remote object
+ nsID iid;
+ if (bits & PTRBITS_REMOTE_BIT)
+ {
+ rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
+ invoke->method_index, params, PR_TRUE, iid);
+ if (NS_FAILED(rv))
+ goto end;
+ }
+
+ nsISupports *obj = nsnull;
+ rv = DeserializeInterfaceParamBits(bits, peer, iid, obj);
+ if (NS_FAILED(rv))
+ goto end;
+
+ params[i].val.p = obj;
+ // mark as interface to let FinishParam() release this param
+ params[i].SetValIsInterface();
+ }
+ else if (type.IsArray())
+ {
+ void *array = nsnull;
+ rv = DeserializeArrayParam(this, reader, peer, iinfo,
+ invoke->method_index, *methodInfo, params,
+ PR_TRUE, paramInfo, PR_FALSE, array);
+ if (NS_FAILED(rv))
+ goto end;
+
+ params[i].val.p = array;
+ // mark to let FinishParam() free this param
+ params[i].SetValIsAllocated();
+ }
+ }
+ }
+
+ rv = XPTC_InvokeByIndex(wrapper->RealInstance(),
+ invoke->method_index,
+ paramCount,
+ params);
+
+ if (rv != NS_OK)
+ {
+ // try to fetch an nsIException possibly set by the method
+ nsresult rv2;
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv2);
+ if (NS_SUCCEEDED(rv2))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rv2 = es->GetCurrentExceptionManager (getter_AddRefs (em));
+ if (NS_SUCCEEDED(rv2))
+ {
+ rv2 = em->GetCurrentException (getter_AddRefs (exception));
+ if (NS_SUCCEEDED(rv2))
+ {
+ LOG(("got nsIException instance, will serialize\n"));
+ got_exception = PR_TRUE;
+ }
+ }
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv2), "failed to get/serialize exception");
+ if (NS_FAILED(rv2))
+ rv = rv2;
+ }
+
+end:
+ LOG(("sending INVOKE_REPLY: rv=%x\n", rv));
+
+ // balance CheckInstanceAndAddRef()
+ if (wrapper)
+ wrapper->Release();
+
+ ipcMessageWriter writer(64);
+
+ DConnectInvokeReply reply;
+ reply.opcode_major = DCON_OP_INVOKE_REPLY;
+ reply.opcode_minor = 0;
+ reply.flags = 0;
+ reply.request_index = invoke->request_index;
+ reply.result = rv;
+
+ if (got_exception)
+ reply.flags |= DCON_OP_FLAGS_REPLY_EXCEPTION;
+
+ writer.PutBytes(&reply, sizeof(reply));
+
+ nsVoidArray wrappers;
+
+ if (NS_SUCCEEDED(rv) && params)
+ {
+ // serialize out-params and retvals
+ for (i=0; i<paramCount; ++i)
+ {
+ const nsXPTParamInfo paramInfo = methodInfo->GetParam(i);
+
+ if (paramInfo.IsRetval() || paramInfo.IsOut())
+ {
+ const nsXPTType &type = paramInfo.GetType();
+
+ if (type.IsInterfacePointer())
+ {
+ nsID iid;
+ rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
+ invoke->method_index, params, PR_TRUE, iid);
+ if (NS_SUCCEEDED(rv))
+ rv = SerializeInterfaceParam(writer, peer, iid,
+ (nsISupports *) params[i].val.p, wrappers);
+ }
+ else
+ rv = SerializeParam(writer, type, params[i]);
+
+ if (NS_FAILED(rv))
+ {
+ reply.result = rv;
+ break;
+ }
+ }
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ // serialize output array parameters after everything else since the
+ // deserialization procedure will need to get a size_is value which may be
+ // stored in any preceeding or following param
+ for (i=0; i<paramCount; ++i)
+ {
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+
+ if (paramInfo.GetType().IsArray() &&
+ (paramInfo.IsRetval() || paramInfo.IsOut()))
+ {
+ rv = SerializeArrayParam(this, writer, peer, iinfo, invoke->method_index,
+ *methodInfo, params, PR_TRUE, paramInfo,
+ params[i].val.p, wrappers);
+ if (NS_FAILED(rv))
+ {
+ reply.result = rv;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (got_exception)
+ {
+ rv = SerializeException(writer, peer, exception, wrappers);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialize exception");
+ }
+
+ if (NS_FAILED(rv))
+ rv = IPC_SendMessage(peer, kDConnectTargetID, (const PRUint8 *) &reply, sizeof(reply));
+ else
+ rv = IPC_SendMessage(peer, kDConnectTargetID, writer.GetBuffer(), writer.GetSize());
+ if (NS_FAILED(rv))
+ {
+ LOG(("unable to send INVOKE_REPLY: rv=%x\n", rv));
+ ReleaseWrappers(wrappers, peer);
+ }
+
+ if (params)
+ {
+ // free individual elements of arrays (note: before freeing arrays
+ // themselves in FinishParam())
+ for (i=0; i<paramUsed; ++i)
+ {
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+ if (paramInfo.GetType().IsArray())
+ FinishArrayParam(iinfo, invoke->method_index, *methodInfo,
+ params, PR_TRUE, paramInfo, params[i]);
+ }
+
+ for (i=0; i<paramUsed; ++i)
+ FinishParam(params[i]);
+ delete[] params;
+ }
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h
new file mode 100644
index 00000000..517b2650
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h
@@ -0,0 +1,365 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ * Dmitry A. Kuminov <dmik@innotek.de>
+ *
+ * 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 ***** */
+
+// DConnect service is multithreaded by default...
+#if !defined(DCONNECT_SINGLETHREADED) && !defined(DCONNECT_MULTITHREADED)
+#define DCONNECT_MULTITHREADED
+# ifdef VBOX
+//# define DCONNECT_WITH_IPRT_REQ_POOL
+# endif
+#endif
+
+#include "ipcIDConnectService.h"
+#include "ipcdclient.h"
+
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nsDataHashtable.h"
+#include "nsHashKeys.h"
+#include "nsHashSets.h"
+#include "nsVoidArray.h"
+#include "nsAutoLock.h"
+#include "xptcall.h"
+#include "xptinfo.h"
+
+#if defined(DCONNECT_MULTITHREADED)
+# if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+
+# include <iprt/req.h>
+
+# else /* !DCONNECT_WITH_IPRT_REQ_POOL*/
+
+#include "ipcList.h"
+
+struct DConnectOp;
+
+struct DConnectRequest : public ipcListNode<DConnectRequest>
+{
+ DConnectRequest (PRUint32 aPeer, const DConnectOp *aOp, PRUint32 aOpLen)
+ : peer(aPeer)
+ , opLen(aOpLen)
+ {
+ op = (const DConnectOp *) malloc(aOpLen);
+ memcpy ((void *) op, aOp, aOpLen);
+ }
+ ~DConnectRequest() { free((void *) op); }
+
+ const PRUint32 peer;
+ const DConnectOp *op;
+ const PRUint32 opLen;
+};
+
+# endif // !DCONNECT_WITH_IPRT_REQ_POOL
+#endif // DCONNECT_MULTITHREADED
+
+class nsIException;
+class ipcMessageReader;
+class ipcMessageWriter;
+
+// a key class used to identify DConnectInstance objects stored in a hash table
+// by a composite of peer ID, XPCOM object pointer and IID this pointer represents
+
+class DConnectInstanceKey : public PLDHashEntryHdr
+{
+public:
+ struct Key
+ {
+ Key(PRUint32 aPeer, const nsISupports *aObj, const nsID *aIID)
+ : mPeer (aPeer), mObj (aObj), mIID (aIID) {}
+ const PRUint32 mPeer;
+ const nsISupports *mObj;
+ const nsIID *mIID;
+ };
+
+ typedef const Key &KeyType;
+ typedef const Key *KeyTypePointer;
+
+ DConnectInstanceKey(const Key *aKey) : mKey (*aKey) {}
+ DConnectInstanceKey(const DConnectInstanceKey &toCopy) : mKey (toCopy.mKey) {}
+ ~DConnectInstanceKey() {}
+
+ KeyType GetKey() const { return mKey; }
+ KeyTypePointer GetKeyPointer() const { return &mKey; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const {
+ return mKey.mPeer == aKey->mPeer &&
+ mKey.mObj == aKey->mObj &&
+ mKey.mIID->Equals(*aKey->mIID);
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey) {
+ return aKey->mPeer ^
+ (NS_PTR_TO_INT32(aKey->mObj) >> 2) ^
+ nsIDHashKey::HashKey(aKey->mIID);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const Key mKey;
+};
+
+class DConnectInstance;
+typedef nsDataHashtable<DConnectInstanceKey, DConnectInstance *> DConnectInstanceMap;
+
+// extend nsVoidHashSet for compatibility with some nsTHashtable methods
+class DConnectInstanceSet : public nsVoidHashSet
+{
+public:
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE) {
+ return nsVoidHashSet::Init(initSize) == NS_OK;
+ }
+ void Clear() {
+ PL_DHashTableEnumerate(&mHashTable, PL_DHashStubEnumRemove, nsnull);
+ }
+};
+
+typedef PRUint64 DConAddr;
+
+// a key class used to identify DConnectStub objects stored in a hash table
+// by a composite of peer ID and DConAddr
+
+class DConnectStubKey : public PLDHashEntryHdr
+{
+public:
+ struct Key
+ {
+ Key(PRUint32 aPeer, const DConAddr aInstance)
+ : mPeer (aPeer), mInstance (aInstance) {}
+ const PRUint32 mPeer;
+ const DConAddr mInstance;
+ };
+
+ typedef const Key &KeyType;
+ typedef const Key *KeyTypePointer;
+
+ DConnectStubKey(const Key *aKey) : mKey (*aKey) {}
+ DConnectStubKey(const DConnectStubKey &toCopy) : mKey (toCopy.mKey) {}
+ ~DConnectStubKey() {}
+
+ KeyType GetKey() const { return mKey; }
+ KeyTypePointer GetKeyPointer() const { return &mKey; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const {
+ return mKey.mPeer == aKey->mPeer &&
+ mKey.mInstance == aKey->mInstance;
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey) {
+ return aKey->mPeer ^
+ (NS_PTR_TO_INT32(aKey->mInstance) >> 2);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const Key mKey;
+};
+
+// used elsewhere like nsAtomTable to safely represent the integral value
+// of an address.
+typedef PRUint64 PtrBits;
+
+// bit flag that defines if a PtrBits value represents a remote object
+#define PTRBITS_REMOTE_BIT 0x1
+
+class DConnectStub;
+typedef nsDataHashtable<DConnectStubKey, DConnectStub *> DConnectStubMap;
+
+class ipcDConnectService : public ipcIDConnectService
+ , public ipcIMessageObserver
+ , public ipcIClientObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCIDCONNECTSERVICE
+ NS_DECL_IPCIMESSAGEOBSERVER
+ NS_DECL_IPCICLIENTOBSERVER
+
+ ipcDConnectService();
+
+ NS_HIDDEN_(nsresult) Init();
+ NS_HIDDEN_(void) Shutdown();
+
+ NS_HIDDEN_(nsresult) GetInterfaceInfo(const nsID &iid, nsIInterfaceInfo **);
+ NS_HIDDEN_(nsresult) GetIIDForMethodParam(nsIInterfaceInfo *iinfo,
+ const nsXPTMethodInfo *methodInfo,
+ const nsXPTParamInfo &paramInfo,
+ const nsXPTType &type,
+ PRUint16 methodIndex,
+ nsXPTCMiniVariant *dispatchParams,
+ PRBool isXPTCVariantArray,
+ nsID &result);
+
+ NS_HIDDEN_(nsresult) SerializeInterfaceParam(ipcMessageWriter &writer,
+ PRUint32 peer, const nsID &iid,
+ nsISupports *obj,
+ nsVoidArray &wrappers);
+ NS_HIDDEN_(nsresult) DeserializeInterfaceParamBits(PtrBits bits, PRUint32 peer,
+ const nsID &iid,
+ nsISupports *&obj);
+
+ NS_HIDDEN_(nsresult) SerializeException(ipcMessageWriter &writer,
+ PRUint32 peer, nsIException *xcpt,
+ nsVoidArray &wrappers);
+ NS_HIDDEN_(nsresult) DeserializeException(ipcMessageReader &reader,
+ PRUint32 peer, nsIException **xcpt);
+
+ NS_HIDDEN_(void) ReleaseWrappers(nsVoidArray &wrappers, PRUint32 peer);
+
+ NS_HIDDEN_(nsresult) CreateStub(const nsID &, PRUint32, DConAddr, DConnectStub **);
+#if 0
+ NS_HIDDEN_(PRBool) FindStubAndAddRef(PRUint32, const DConAddr, DConnectStub **);
+#endif
+ // public only for DConnectStub::~DConnectStub()
+ NS_HIDDEN_(void) DeleteStub(DConnectStub *);
+
+ // public only for DConnectInstance::Release()
+ NS_HIDDEN_(void) DeleteInstance(DConnectInstance *, PRBool locked = PR_FALSE);
+ // public only for DConnectStub::CallMethod()
+ NS_HIDDEN_(PRBool) CheckInstanceAndAddRef(DConnectInstance *, PRUint32);
+
+ PRLock *StubLock() { return mStubLock; }
+ PRLock *StubQILock() { return mStubQILock; }
+
+ static nsRefPtr <ipcDConnectService> GetInstance() {
+ return nsRefPtr <ipcDConnectService> (mInstance);
+ }
+
+private:
+
+ NS_HIDDEN ~ipcDConnectService();
+
+ NS_HIDDEN_(nsresult) StoreInstance(DConnectInstance *);
+ NS_HIDDEN_(PRBool) FindInstanceAndAddRef(PRUint32,
+ const nsISupports *,
+ const nsIID *,
+ DConnectInstance **);
+
+ NS_HIDDEN_(nsresult) StoreStub(DConnectStub *);
+
+ NS_HIDDEN_(void) OnIncomingRequest(PRUint32 peer, const struct DConnectOp *op, PRUint32 opLen);
+
+ NS_HIDDEN_(void) OnSetup(PRUint32 peer, const struct DConnectSetup *, PRUint32 opLen);
+ NS_HIDDEN_(void) OnRelease(PRUint32 peer, const struct DConnectRelease *);
+ NS_HIDDEN_(void) OnInvoke(PRUint32 peer, const struct DConnectInvoke *, PRUint32 opLen);
+
+#if defined(DCONNECT_MULTITHREADED)
+# if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+ static DECLCALLBACK(void) ProcessMessageOnWorkerThread(ipcDConnectService *aThis, PRUint32 aSenderID, void *aData, PRUint32 aDataLen);
+# else
+ NS_HIDDEN_(nsresult) CreateWorker();
+# endif
+#endif
+
+private:
+ nsCOMPtr<nsIInterfaceInfoManager> mIIM;
+
+ // lock to protect access to instance sets and the disconnected flag
+ PRLock *mLock;
+
+ // table of local object instances allocated on behalf of a peer
+ // (keys are interface pointers of real objects these instances represent)
+ DConnectInstanceMap mInstances;
+ // hashset containing the same instances as above
+ // (used for quick parameter validity checks)
+ DConnectInstanceSet mInstanceSet;
+
+ // lock to protect access to mStubs and DConnectStub::mRefCntLevels
+ // (also guards every DConnectStub::Release call to provide atomicity)
+ PRLock *mStubLock;
+
+ // table of remote object stubs allocated to communicate with peer's instances
+ DConnectStubMap mStubs;
+
+ // this is true after IPC_Shutdown() has been called
+ PRBool mDisconnected;
+
+// member is never initialized or used, no point in wasting memory or making
+// someone believe it contains anything relevant
+#ifndef VBOX
+ // our IPC client ID
+ PRUint32 mSelfID;
+#endif
+
+ // global lock to protect access to protect DConnectStub::QueryInterface()
+ // (we cannot use mStubLock because it isn't supposed to be held long,
+ // like in case of an IPC call and such)
+ PRLock *mStubQILock;
+
+#if defined(DCONNECT_MULTITHREADED)
+# if defined(DCONNECT_WITH_IPRT_REQ_POOL)
+
+ /** Request pool. */
+ RTREQPOOL mhReqPool;
+
+# else
+
+ friend class DConnectWorker;
+
+ // pool of worker threads to serve incoming requests
+ nsVoidArray mWorkers;
+ // queue of pending requests
+ ipcList<DConnectRequest> mPendingQ;
+ // monitor to protect mPendingQ
+ PRMonitor *mPendingMon;
+ // number of waiting workers
+ PRUint32 mWaitingWorkers;
+ // monitor used to wait on changes in mWaitingWorkers.
+ PRMonitor *mWaitingWorkersMon;
+# endif
+#endif
+
+ // global ipcDConnectService instance for internal usage
+ static ipcDConnectService *mInstance;
+};
+
+#define IPC_DCONNECTSERVICE_CLASSNAME \
+ "ipcDConnectService"
+#define IPC_DCONNECTSERVICE_CONTRACTID \
+ "@mozilla.org/ipc/dconnect-service;1"
+#define IPC_DCONNECTSERVICE_CID \
+{ /* 63a5d9dc-4828-425a-bd50-bd10a4b26f2c */ \
+ 0x63a5d9dc, \
+ 0x4828, \
+ 0x425a, \
+ {0xbd, 0x50, 0xbd, 0x10, 0xa4, 0xb2, 0x6f, 0x2c} \
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/Makefile.in
new file mode 100644
index 00000000..2d511de2
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/Makefile.in
@@ -0,0 +1,33 @@
+# vim:set ts=8 sw=8 noet:
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = dconnect
+
+REQUIRES = ipcd \
+ nspr \
+ string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ TestDConnect.cpp \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(EXTRA_DSO_LIBS) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestClient.js b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestClient.js
new file mode 100644
index 00000000..8403fcdd
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestClient.js
@@ -0,0 +1,106 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+/**
+ * This file contains code that mirrors the code in TestDConnect.cpp:DoTest
+ */
+
+const ipcIService = Components.interfaces.ipcIService;
+const ipcIDConnectService = Components.interfaces.ipcIDConnectService;
+const nsIFile = Components.interfaces.nsIFile;
+const nsILocalFile = Components.interfaces.nsILocalFile;
+const nsIEventQueueService = Components.interfaces.nsIEventQueueService;
+
+// XXX use directory service for this
+const TEST_PATH = "/tmp";
+
+var serverID = 0;
+
+function findServer()
+{
+ var ipc = Components.classes["@mozilla.org/ipc/service;1"].getService(ipcIService);
+ serverID = ipc.resolveClientName("test-server");
+}
+
+function doTest()
+{
+ var dcon = Components.classes["@mozilla.org/ipc/dconnect-service;1"]
+ .getService(ipcIDConnectService);
+
+ var file = dcon.createInstanceByContractID(serverID, "@mozilla.org/file/local;1", nsIFile);
+
+ var localFile = file.QueryInterface(nsILocalFile);
+
+ localFile.initWithPath(TEST_PATH);
+
+ if (file.path != TEST_PATH)
+ {
+ dump("*** path test failed [path=" + file.path + "]\n");
+ return;
+ }
+
+ dump("file exists: " + file.exists() + "\n");
+
+ var clone = file.clone();
+
+ const node = "hello.txt";
+ clone.append(node);
+ dump("files are equal: " + file.equals(clone) + "\n");
+
+ if (!clone.exists())
+ clone.create(nsIFile.NORMAL_FILE_TYPE, 0600);
+
+ clone.moveTo(null, "helloworld.txt");
+
+ var localObj = Components.classes["@mozilla.org/file/local;1"].createInstance(nsILocalFile);
+ localObj.initWithPath(TEST_PATH);
+ dump("file.equals(localObj) = " + file.equals(localObj) + "\n");
+ dump("localObj.equals(file) = " + localObj.equals(file) + "\n");
+}
+
+function setupEventQ()
+{
+ var eqs = Components.classes["@mozilla.org/event-queue-service;1"]
+ .getService(nsIEventQueueService);
+ eqs.createMonitoredThreadEventQueue();
+}
+
+setupEventQ();
+findServer();
+dump("\n---------------------------------------------------\n");
+doTest();
+dump("---------------------------------------------------\n\n");
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp
new file mode 100644
index 00000000..8eabe13c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestDConnect.cpp
@@ -0,0 +1,268 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "ipcIService.h"
+#include "ipcIDConnectService.h"
+#include "ipcCID.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentRegistrar.h"
+
+#include "nsXPCOMCID.h"
+#include "nsILocalFile.h"
+
+#include "nsString.h"
+#include "prmem.h"
+
+#if defined( XP_WIN ) || defined( XP_OS2 )
+#define TEST_PATH "c:"
+#else
+#define TEST_PATH "/tmp"
+#endif
+
+#define RETURN_IF_FAILED(rv, step) \
+ PR_BEGIN_MACRO \
+ if (NS_FAILED(rv)) { \
+ printf("*** %s failed: rv=%x\n", step, rv); \
+ return rv;\
+ } \
+ PR_END_MACRO
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+static nsIEventQueue* gEventQ = nsnull;
+static PRBool gKeepRunning = PR_TRUE;
+
+static ipcIService *gIpcServ = nsnull;
+
+static nsresult DoTest()
+{
+ nsresult rv;
+
+ nsCOMPtr<ipcIDConnectService> dcon = do_GetService("@mozilla.org/ipc/dconnect-service;1", &rv);
+ RETURN_IF_FAILED(rv, "getting dconnect service");
+
+ PRUint32 remoteClientID = 1;
+
+ nsCOMPtr<nsIFile> file;
+ rv = dcon->CreateInstanceByContractID(remoteClientID,
+ NS_LOCAL_FILE_CONTRACTID,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(file));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISupports> sup = do_QueryInterface(file, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ printf("*** calling QueryInterface\n");
+ nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString path;
+ path.AssignLiteral(TEST_PATH);
+
+ printf("*** calling InitWithNativePath\n");
+ rv = localFile->InitWithPath(path);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString buf;
+ rv = file->GetPath(buf);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!buf.Equals(path))
+ {
+ NS_ConvertUTF16toUTF8 temp(buf);
+ printf("*** GetPath erroneously returned [%s]\n", temp.get());
+ return NS_ERROR_FAILURE;
+ }
+
+ PRBool exists;
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv))
+ {
+ printf("*** Exists test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+ printf("File exists? [%d]\n", exists);
+
+ nsCOMPtr<nsIFile> clone;
+ rv = file->Clone(getter_AddRefs(clone));
+ if (NS_FAILED(rv))
+ {
+ printf("*** Clone test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+
+ nsAutoString node;
+ node.AssignLiteral("hello.txt");
+
+ rv = clone->Append(node);
+ if (NS_FAILED(rv))
+ {
+ printf("*** Append test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+
+ PRBool match;
+ rv = file->Equals(clone, &match);
+ if (NS_FAILED(rv))
+ {
+ printf("*** Equals test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+ printf("Files are equals? [%d]\n", match);
+
+ // now test passing null for interface pointer
+
+ rv = clone->Exists(&exists);
+ if (NS_FAILED(rv))
+ {
+ printf("*** Exists test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+ if (!exists)
+ {
+ rv = clone->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
+ if (NS_FAILED(rv))
+ {
+ printf("*** Create test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ rv = clone->MoveTo(nsnull, NS_LITERAL_STRING("helloworld.txt"));
+ if (NS_FAILED(rv))
+ {
+ printf("*** MoveTo test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+
+ // now test passing local objects to a remote object
+
+ nsCOMPtr<nsILocalFile> myLocalFile;
+ rv = NS_NewLocalFile(path, PR_TRUE, getter_AddRefs(myLocalFile));
+ if (NS_FAILED(rv))
+ {
+ printf("*** NS_NewLocalFile failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = file->Equals(myLocalFile, &match);
+ if (NS_FAILED(rv))
+ {
+ printf("*** second Equals test failed [rv=%x]\n", rv);
+ return NS_ERROR_FAILURE;
+ }
+ printf("Files are equals? [%d]\n", match);
+
+ printf("*** DoTest completed successfully :-)\n");
+ return NS_OK;
+}
+
+int main(int argc, char **argv)
+{
+ nsresult rv;
+
+ PRBool serverMode = PR_FALSE;
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "-server") == 0)
+ {
+ serverMode = PR_TRUE;
+ }
+ else
+ {
+ printf("usage: %s [-server]\n", argv[0]);
+ return -1;
+ }
+ }
+
+ {
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->AutoRegister(nsnull);
+
+ // Create the Event Queue for this thread...
+ nsCOMPtr<nsIEventQueueService> eqs =
+ do_GetService(kEventQueueServiceCID, &rv);
+ RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)");
+
+ rv = eqs->CreateMonitoredThreadEventQueue();
+ RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue");
+
+ rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
+ RETURN_IF_FAILED(rv, "GetThreadEventQueue");
+
+ nsCOMPtr<ipcIService> ipcServ(do_GetService(IPC_SERVICE_CONTRACTID, &rv));
+ RETURN_IF_FAILED(rv, "do_GetService(ipcServ)");
+ NS_ADDREF(gIpcServ = ipcServ);
+
+ if (!serverMode)
+ {
+ rv = DoTest();
+ RETURN_IF_FAILED(rv, "DoTest()");
+ }
+ else
+ {
+ gIpcServ->AddName("DConnectServer");
+ }
+
+ PLEvent *ev;
+ while (gKeepRunning)
+ {
+ gEventQ->WaitForEvent(&ev);
+ gEventQ->HandleEvent(ev);
+ }
+
+ NS_RELEASE(gIpcServ);
+
+ printf("*** processing remaining events\n");
+
+ // process any remaining events
+ while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev)
+ gEventQ->HandleEvent(ev);
+
+ printf("*** done\n");
+ } // this scopes the nsCOMPtrs
+
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestServer.js b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestServer.js
new file mode 100644
index 00000000..a72e133b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/test/TestServer.js
@@ -0,0 +1,66 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+/**
+ * This file contains code for a "server" that does nothing more
+ * than set a name for itself on the IPC system so that the client
+ * can connect and control this process.
+ */
+
+const ipcIService = Components.interfaces.ipcIService;
+const nsIEventQueueService = Components.interfaces.nsIEventQueueService;
+const nsIEventQueue = Components.interfaces.nsIEventQueue;
+
+function registerServer()
+{
+ var ipc = Components.classes["@mozilla.org/ipc/service;1"].getService(ipcIService);
+ ipc.addName("test-server");
+}
+
+function runEventQ()
+{
+ var eqs = Components.classes["@mozilla.org/event-queue-service;1"]
+ .getService(nsIEventQueueService);
+ eqs.createMonitoredThreadEventQueue();
+ var queue = eqs.getSpecialEventQueue(eqs.CURRENT_THREAD_EVENT_QUEUE);
+
+ // this never returns
+ queue.eventLoop();
+}
+
+registerServer();
+runEventQ();
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/Makefile.in
new file mode 100644
index 00000000..4b94a31f
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/Makefile.in
@@ -0,0 +1,52 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = public src
+
+ifdef ENABLE_TESTS
+DIRS += test
+endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/Makefile.in
new file mode 100644
index 00000000..9a08abdb
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/Makefile.in
@@ -0,0 +1,58 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+XPIDL_MODULE = ipcd_lock
+
+EXPORTS = \
+ ipcLockCID.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ ipcILockService.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcILockService.idl b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcILockService.idl
new file mode 100644
index 00000000..1cbf8651
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcILockService.idl
@@ -0,0 +1,65 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsISupports.idl"
+
+/**
+ * This service provides named interprocess locking.
+ */
+[scriptable, uuid(9f6dbe15-d851-4b00-912a-5ac0be88a409)]
+interface ipcILockService : nsISupports
+{
+ /**
+ * Call this method to acquire a named interprocess lock.
+ *
+ * @param aLockName
+ * specifies the name of the lock
+ * @param aWaitIfBusy
+ * wait for the lock to become available; otherwise, fail if lock
+ * is already held by some other process.
+ */
+ void acquireLock(in string aLockName,
+ in boolean aWaitIfBusy);
+
+ /**
+ * Call this method to release a named lock.
+ *
+ * @param aLockName
+ * specifies the name of the lock
+ */
+ void releaseLock(in string aLockName);
+};
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcLockCID.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcLockCID.h
new file mode 100644
index 00000000..ba756d9b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/public/ipcLockCID.h
@@ -0,0 +1,53 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcLockCID_h__
+#define ipcLockCID_h__
+
+#define IPC_LOCKSERVICE_CLASSNAME \
+ "ipcLockService"
+#define IPC_LOCKSERVICE_CONTRACTID \
+ "@mozilla.org/ipc/lock-service;1"
+#define IPC_LOCKSERVICE_CID \
+{ /* d9e56bf8-e32e-4b6d-87f1-06d73b0ce7ca */ \
+ 0xd9e56bf8, \
+ 0xe32e, \
+ 0x4b6d, \
+ {0x87, 0xf1, 0x06, 0xd7, 0x3b, 0x0c, 0xe7, 0xca} \
+}
+
+#endif // !ipcLockCID_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/Makefile.in
new file mode 100644
index 00000000..26d943a8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/Makefile.in
@@ -0,0 +1,69 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = module
+
+MODULE = ipcd
+LIBRARY_NAME = ipcdlock_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME = ipcd
+
+FORCE_USE_PIC = 1
+
+REQUIRES = \
+ xpcom \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ ipcLockProtocol.cpp \
+ ipcLockService.cpp \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../../shared/src \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.cpp
new file mode 100644
index 00000000..5a7e7755
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.cpp
@@ -0,0 +1,87 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <stdlib.h>
+#include <string.h>
+#include "prlog.h"
+#include "ipcLockProtocol.h"
+
+//-----------------------------------------------------------------------------
+
+static inline PRUint8 get_opcode(const PRUint8 *buf)
+{
+ return (buf[0] & 0x0f);
+}
+
+static inline PRUint8 get_flags(const PRUint8 *buf)
+{
+ return (buf[0] & 0xf0) >> 4;
+}
+
+static inline const char *get_key(const PRUint8 *buf)
+{
+ return ((const char *) buf) + 1;
+}
+
+//-----------------------------------------------------------------------------
+
+PRUint8 *
+IPC_FlattenLockMsg(const ipcLockMsg *msg, PRUint32 *bufLen)
+{
+ PRUint32 len = 1 // header byte
+ + strlen(msg->key) // key
+ + 1; // null terminator
+
+ PRUint8 *buf = (PRUint8 *) ::operator new(len);
+ if (!buf)
+ return NULL;
+
+ buf[0] = (msg->opcode | (msg->flags << 4));
+
+ memcpy(&buf[1], msg->key, len - 1);
+ *bufLen = len;
+ return buf;
+}
+
+void
+IPC_UnflattenLockMsg(const PRUint8 *buf, PRUint32 bufLen, ipcLockMsg *msg)
+{
+ PR_ASSERT(bufLen > 2); // malformed buffer otherwise
+ msg->opcode = get_opcode(buf);
+ msg->flags = get_flags(buf);
+ msg->key = get_key(buf);
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.h
new file mode 100644
index 00000000..b74b5cde
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockProtocol.h
@@ -0,0 +1,98 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcLockProtocol_h__
+#define ipcLockProtocol_h__
+
+#include "prtypes.h"
+
+//
+// ipc lock message format:
+//
+// +----------------------------------+
+// | opcode : 4 bits |
+// +----------------------------------+
+// | flags : 4 bits |
+// +----------------------------------+
+// | key : null terminated string |
+// +----------------------------------+
+//
+
+// lock opcodes
+#define IPC_LOCK_OP_ACQUIRE 1
+#define IPC_LOCK_OP_RELEASE 2
+#define IPC_LOCK_OP_STATUS_ACQUIRED 3
+#define IPC_LOCK_OP_STATUS_FAILED 4
+#define IPC_LOCK_OP_STATUS_BUSY 5
+
+// lock flags
+#define IPC_LOCK_FL_NONBLOCKING 1
+
+// data structure for representing lock request message
+struct ipcLockMsg
+{
+ PRUint8 opcode;
+ PRUint8 flags;
+ const char * key;
+};
+
+//
+// flatten a lock message
+//
+// returns a malloc'd buffer containing the flattened message. on return,
+// bufLen contains the length of the flattened message.
+//
+PRUint8 *IPC_FlattenLockMsg(const ipcLockMsg *msg, PRUint32 *bufLen);
+
+//
+// unflatten a lock message. upon return, msg->key points into buf, so
+// buf must not be deallocated until after msg is no longer needed.
+//
+void IPC_UnflattenLockMsg(const PRUint8 *buf, PRUint32 bufLen, ipcLockMsg *msg);
+
+//
+// TargetID for message passing
+//
+#define IPC_LOCK_TARGETID \
+{ /* 703ada8a-2d38-4d5d-9d39-03d1ccceb567 */ \
+ 0x703ada8a, \
+ 0x2d38, \
+ 0x4d5d, \
+ {0x9d, 0x39, 0x03, 0xd1, 0xcc, 0xce, 0xb5, 0x67} \
+}
+
+#endif // !ipcLockProtocol_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.cpp
new file mode 100644
index 00000000..771aa787
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.cpp
@@ -0,0 +1,168 @@
+/* vim:set ts=4 sw=4 sts=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <stdlib.h>
+#include "nsDependentString.h"
+#include "nsHashKeys.h"
+#include "nsAutoPtr.h"
+#include "ipcLockService.h"
+#include "ipcLockProtocol.h"
+#include "ipcLog.h"
+#include "prthread.h"
+
+static const nsID kLockTargetID = IPC_LOCK_TARGETID;
+
+//-----------------------------------------------------------------------------
+
+struct ipcPendingLock
+{
+ const char *name;
+ nsresult status;
+ PRBool complete;
+};
+
+//-----------------------------------------------------------------------------
+
+nsresult
+ipcLockService::Init()
+{
+ if (PR_NewThreadPrivateIndex(&mTPIndex, nsnull) != PR_SUCCESS)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Configure OnMessageAvailable to be called on the IPC thread. This is
+ // done to allow us to proxy OnAcquireLockComplete events to the right
+ // thread immediately even if the main thread is blocked waiting to acquire
+ // some other lock synchronously.
+
+ return IPC_DefineTarget(kLockTargetID, this, PR_FALSE);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(ipcLockService, ipcILockService, ipcIMessageObserver)
+
+NS_IMETHODIMP
+ipcLockService::AcquireLock(const char *lockName, PRBool waitIfBusy)
+{
+ LOG(("ipcLockService::AcquireLock [lock=%s wait=%u]\n", lockName, waitIfBusy));
+
+ ipcLockMsg msg;
+ msg.opcode = IPC_LOCK_OP_ACQUIRE;
+ msg.flags = (waitIfBusy ? 0 : IPC_LOCK_FL_NONBLOCKING);
+ msg.key = lockName;
+
+ PRUint32 bufLen;
+ nsAutoPtr<PRUint8> buf( IPC_FlattenLockMsg(&msg, &bufLen) );
+ if (!buf)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ ipcPendingLock pendingLock;
+ pendingLock.name = lockName;
+ pendingLock.status = 0xDEADBEEF; // something bogus
+ pendingLock.complete = PR_FALSE;
+ if (PR_SetThreadPrivate(mTPIndex, &pendingLock) != PR_SUCCESS)
+ return NS_ERROR_UNEXPECTED;
+
+ // prevent our OnMessageAvailable from being called until we explicitly ask
+ // for it to be called via IPC_WaitMessage.
+ IPC_DISABLE_MESSAGE_OBSERVER_FOR_SCOPE(kLockTargetID);
+
+ nsresult rv = IPC_SendMessage(0, kLockTargetID, buf, bufLen);
+ if (NS_SUCCEEDED(rv)) {
+ do {
+ // block the calling thread until we get a response from the daemon
+ rv = IPC_WaitMessage(0, kLockTargetID, this, nsnull, PR_INTERVAL_NO_TIMEOUT);
+ }
+ while (NS_SUCCEEDED(rv) && !pendingLock.complete);
+
+ if (NS_SUCCEEDED(rv))
+ rv = pendingLock.status;
+ }
+
+ // we could clear the TPD, but that isn't really necessary.
+
+ return rv;
+}
+
+NS_IMETHODIMP
+ipcLockService::ReleaseLock(const char *lockName)
+{
+ LOG(("ipcLockService::ReleaseLock [lock=%s]\n", lockName));
+
+ ipcLockMsg msg;
+ msg.opcode = IPC_LOCK_OP_RELEASE;
+ msg.flags = 0;
+ msg.key = lockName;
+
+ PRUint32 bufLen;
+ PRUint8 *buf = IPC_FlattenLockMsg(&msg, &bufLen);
+ if (!buf)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = IPC_SendMessage(0, kLockTargetID, buf, bufLen);
+ delete buf;
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+// called on the same thread that called IPC_WaitMessage
+NS_IMETHODIMP
+ipcLockService::OnMessageAvailable(PRUint32 unused, const nsID &target,
+ const PRUint8 *data, PRUint32 dataLen)
+{
+ ipcLockMsg msg;
+ IPC_UnflattenLockMsg(data, dataLen, &msg);
+
+ LOG(("ipcLockService::OnMessageAvailable [lock=%s opcode=%u]\n", msg.key, msg.opcode));
+
+ ipcPendingLock *pendingLock = (ipcPendingLock *) PR_GetThreadPrivate(mTPIndex);
+ if (strcmp(pendingLock->name, msg.key) == 0) {
+ pendingLock->complete = PR_TRUE;
+ if (msg.opcode == IPC_LOCK_OP_STATUS_ACQUIRED)
+ pendingLock->status = NS_OK;
+ else
+ pendingLock->status = NS_ERROR_FAILURE;
+ return NS_OK;
+ }
+
+ LOG(("message does not match; waiting for another...\n"));
+
+ // else, we got a message that another thread is waiting to receive.
+ return IPC_WAIT_NEXT_MESSAGE;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.h
new file mode 100644
index 00000000..6014172b
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/ipcLockService.h
@@ -0,0 +1,63 @@
+/* vim:set ts=4 sw=4 sts=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcLockService_h__
+#define ipcLockService_h__
+
+#include "ipcILockService.h"
+#include "ipcdclient.h"
+
+//-----------------------------------------------------------------------------
+
+class ipcLockService : public ipcILockService
+ , public ipcIMessageObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCILOCKSERVICE
+ NS_DECL_IPCIMESSAGEOBSERVER
+
+ NS_HIDDEN_(nsresult) Init();
+
+private:
+ PRUintn mTPIndex;
+};
+
+//-----------------------------------------------------------------------------
+
+#endif // !ipcLockService_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/Makefile.in
new file mode 100644
index 00000000..b35db1bc
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/Makefile.in
@@ -0,0 +1,92 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = lockmodule
+ifeq ($(OS_ARCH), OS2)
+SHORT_LIBNAME = lockmod
+endif
+MODULE_NAME = ipcd
+
+FORCE_SHARED_LIB = 1
+NO_DIST_INSTALL = 1
+NO_INSTALL = 1
+
+ifeq ($(OS_ARCH),Darwin)
+NO_COMPONENT_LINK_MAP = 1
+MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS =
+endif
+
+# required for #include "nsID.h"
+REQUIRES = \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = ipcLockModule.cpp
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/.. \
+ $(NULL)
+
+EXTRA_OBJS = ../ipcLockProtocol.$(OBJ_SUFFIX)
+
+EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(NSPR_LIBS) \
+ $(EXTRA_DSO_LIBS) \
+ $(EXTRA_OBJS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+_IPC_FILES = \
+ $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX) \
+ $(NULL)
+
+libs:: $(_IPC_FILES)
+ $(INSTALL) $^ $(DIST)/bin/ipc/modules
+
+install:: $(_IPC_FILES)
+ $(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/ipc/modules
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/ipcLockModule.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/ipcLockModule.cpp
new file mode 100644
index 00000000..151c0f89
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/src/module/ipcLockModule.cpp
@@ -0,0 +1,337 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <stdlib.h>
+#include <stdio.h>
+#include "ipcModuleUtil.h"
+#include "ipcLockProtocol.h"
+#include "plhash.h"
+#include "plstr.h"
+
+#ifdef DEBUG
+#define LOG(args) printf args
+#else
+#define LOG(args)
+#endif
+
+static const nsID kLockTargetID = IPC_LOCK_TARGETID;
+
+static void
+ipcLockModule_Send(PRUint32 cid, const char *key, PRUint8 opcode)
+{
+ ipcLockMsg msg = { opcode, 0, key };
+ PRUint32 bufLen;
+ PRUint8 *buf = IPC_FlattenLockMsg(&msg, &bufLen);
+ if (!buf)
+ return;
+ IPC_SendMsg(cid, kLockTargetID, buf, bufLen);
+ free(buf);
+}
+
+//-----------------------------------------------------------------------------
+
+//
+// gLockTable stores mapping from lock name to ipcLockContext
+//
+static PLHashTable *gLockTable = NULL;
+
+//-----------------------------------------------------------------------------
+
+struct ipcLockContext
+{
+ PRUint32 mOwnerID; // client ID of this lock's owner
+ struct ipcLockContext *mNextPending; // pointer to client next in line to
+ // acquire this lock.
+
+ ipcLockContext(PRUint32 ownerID)
+ : mOwnerID(ownerID)
+ , mNextPending(NULL) {}
+};
+
+//-----------------------------------------------------------------------------
+
+PR_STATIC_CALLBACK(void *)
+ipcLockModule_AllocTable(void *pool, PRSize size)
+{
+ return malloc(size);
+}
+
+PR_STATIC_CALLBACK(void)
+ipcLockModule_FreeTable(void *pool, void *item)
+{
+ free(item);
+}
+
+PR_STATIC_CALLBACK(PLHashEntry *)
+ipcLockModule_AllocEntry(void *pool, const void *key)
+{
+ return (PLHashEntry *) malloc(sizeof(PLHashEntry));
+}
+
+PR_STATIC_CALLBACK(void)
+ipcLockModule_FreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+ PL_strfree((char *) he->key);
+ free(he);
+}
+
+static const PLHashAllocOps ipcLockModule_AllocOps = {
+ ipcLockModule_AllocTable,
+ ipcLockModule_FreeTable,
+ ipcLockModule_AllocEntry,
+ ipcLockModule_FreeEntry
+};
+
+//-----------------------------------------------------------------------------
+
+static void
+ipcLockModule_AcquireLock(PRUint32 cid, PRUint8 flags, const char *key)
+{
+ LOG(("$$$ acquiring lock [key=%s]\n", key));
+
+ if (!gLockTable)
+ return;
+
+ ipcLockContext *ctx;
+
+ ctx = (ipcLockContext *) PL_HashTableLookup(gLockTable, key);
+ if (ctx) {
+ //
+ // lock is already acquired, add this client to the queue. make
+ // sure this client doesn't already own the lock or live on the queue.
+ //
+ while (ctx->mOwnerID != cid && ctx->mNextPending)
+ ctx = ctx->mNextPending;
+ if (ctx->mOwnerID != cid) {
+ //
+ // if nonblocking, then send busy status message. otherwise,
+ // proceed to add this client to the pending queue.
+ //
+ if (flags & IPC_LOCK_FL_NONBLOCKING)
+ ipcLockModule_Send(cid, key, IPC_LOCK_OP_STATUS_BUSY);
+ else
+ ctx->mNextPending = new ipcLockContext(cid);
+ }
+ }
+ else {
+ //
+ // ok, add this lock to the table, and notify client that it now owns
+ // the lock!
+ //
+ ctx = new ipcLockContext(cid);
+ if (!ctx)
+ return;
+
+ PL_HashTableAdd(gLockTable, PL_strdup(key), ctx);
+
+ ipcLockModule_Send(cid, key, IPC_LOCK_OP_STATUS_ACQUIRED);
+ }
+}
+
+static PRBool
+ipcLockModule_ReleaseLockHelper(PRUint32 cid, const char *key, ipcLockContext *ctx)
+{
+ LOG(("$$$ releasing lock [key=%s]\n", key));
+
+ PRBool removeEntry = PR_FALSE;
+
+ //
+ // lock is already acquired _or_ maybe client is on the pending list.
+ //
+ if (ctx->mOwnerID == cid) {
+ if (ctx->mNextPending) {
+ //
+ // remove this element from the list. since this is the
+ // first element in the list, instead of removing it we
+ // shift the data from the next context into this one and
+ // delete the next context.
+ //
+ ipcLockContext *next = ctx->mNextPending;
+ ctx->mOwnerID = next->mOwnerID;
+ ctx->mNextPending = next->mNextPending;
+ delete next;
+ //
+ // notify client that it now owns the lock
+ //
+ ipcLockModule_Send(ctx->mOwnerID, key, IPC_LOCK_OP_STATUS_ACQUIRED);
+ }
+ else {
+ delete ctx;
+ removeEntry = PR_TRUE;
+ }
+ }
+ else {
+ ipcLockContext *prev;
+ for (;;) {
+ prev = ctx;
+ ctx = ctx->mNextPending;
+ if (!ctx)
+ break;
+ if (ctx->mOwnerID == cid) {
+ // remove ctx from list
+ prev->mNextPending = ctx->mNextPending;
+ delete ctx;
+ break;
+ }
+ }
+ }
+
+ return removeEntry;
+}
+
+static void
+ipcLockModule_ReleaseLock(PRUint32 cid, const char *key)
+{
+ if (!gLockTable)
+ return;
+
+ ipcLockContext *ctx;
+
+ ctx = (ipcLockContext *) PL_HashTableLookup(gLockTable, key);
+ if (ctx && ipcLockModule_ReleaseLockHelper(cid, key, ctx))
+ PL_HashTableRemove(gLockTable, key);
+}
+
+PR_STATIC_CALLBACK(PRIntn)
+ipcLockModule_ReleaseByCID(PLHashEntry *he, PRIntn i, void *arg)
+{
+ PRUint32 cid = *(PRUint32 *) arg;
+
+ ipcLockContext *ctx = (ipcLockContext *) he->value;
+ if (ctx->mOwnerID != cid)
+ return HT_ENUMERATE_NEXT;
+
+ LOG(("$$$ ipcLockModule_ReleaseByCID [cid=%u key=%s he=%p]\n",
+ cid, (char*)he->key, (void*)he));
+
+ if (ipcLockModule_ReleaseLockHelper(cid, (const char *) he->key, ctx))
+ return HT_ENUMERATE_REMOVE;
+
+ return HT_ENUMERATE_NEXT;
+}
+
+//-----------------------------------------------------------------------------
+
+static void
+ipcLockModule_Init()
+{
+ LOG(("$$$ ipcLockModule_Init\n"));
+
+ gLockTable = PL_NewHashTable(32,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues,
+ &ipcLockModule_AllocOps,
+ NULL);
+}
+
+static void
+ipcLockModule_Shutdown()
+{
+ LOG(("$$$ ipcLockModule_Shutdown\n"));
+
+ if (gLockTable) {
+ // XXX walk table destroying all ipcLockContext objects
+
+ PL_HashTableDestroy(gLockTable);
+ gLockTable = NULL;
+ }
+}
+
+static void
+ipcLockModule_HandleMsg(ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen)
+{
+ PRUint32 cid = IPC_GetClientID(client);
+
+ LOG(("$$$ ipcLockModule_HandleMsg [cid=%u]\n", cid));
+
+ ipcLockMsg msg;
+ IPC_UnflattenLockMsg((const PRUint8 *) data, dataLen, &msg);
+
+ switch (msg.opcode) {
+ case IPC_LOCK_OP_ACQUIRE:
+ ipcLockModule_AcquireLock(cid, msg.flags, msg.key);
+ break;
+ case IPC_LOCK_OP_RELEASE:
+ ipcLockModule_ReleaseLock(cid, msg.key);
+ break;
+ default:
+ PR_NOT_REACHED("invalid opcode");
+ }
+}
+
+static void
+ipcLockModule_ClientUp(ipcClientHandle client)
+{
+ LOG(("$$$ ipcLockModule_ClientUp [%u]\n", IPC_GetClientID(client)));
+}
+
+static void
+ipcLockModule_ClientDown(ipcClientHandle client)
+{
+ PRUint32 cid = IPC_GetClientID(client);
+
+ LOG(("$$$ ipcLockModule_ClientDown [%u]\n", cid));
+
+ //
+ // enumerate lock table, release any locks held by this client.
+ //
+
+ PL_HashTableEnumerateEntries(gLockTable, ipcLockModule_ReleaseByCID, &cid);
+}
+
+//-----------------------------------------------------------------------------
+
+static ipcModuleMethods gLockMethods =
+{
+ IPC_MODULE_METHODS_VERSION,
+ ipcLockModule_Init,
+ ipcLockModule_Shutdown,
+ ipcLockModule_HandleMsg,
+ ipcLockModule_ClientUp,
+ ipcLockModule_ClientDown
+};
+
+static ipcModuleEntry gLockModuleEntry[] =
+{
+ { IPC_LOCK_TARGETID, &gLockMethods }
+};
+
+IPC_IMPL_GETMODULES(ipcLockModule, gLockModuleEntry)
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/Makefile.in
new file mode 100644
index 00000000..bcf9299a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/Makefile.in
@@ -0,0 +1,67 @@
+# vim:set ts=8 sw=8 noet:
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is IBM Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@meer.net>
+#
+# 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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = dconnect
+
+REQUIRES = ipcd \
+ nspr \
+ string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ TestIPCLocks.cpp \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(EXTRA_DSO_LIBS) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp
new file mode 100644
index 00000000..f35e8434
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/lock/test/TestIPCLocks.cpp
@@ -0,0 +1,244 @@
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+// This test program spawns N copies of itself, and each copy spawns M threads.
+// Each thread acquires and releases a named, interprocess lock.
+// Randomized delays are injected at various points to exercise the system, and
+// help expose any race conditions that may exist.
+//
+// Usage: TestIPCLocks [-N]
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ipcILockService.h"
+#include "ipcLockCID.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIEventQueueService.h"
+#include "nsCOMPtr.h"
+#include "nsXPCOM.h"
+#include "prproces.h"
+#include "prprf.h"
+
+#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+#include <unistd.h>
+static unsigned GetPID()
+{
+ return (unsigned) getpid();
+}
+#elif defined(XP_WIN)
+#include <windows.h>
+static unsigned GetPID()
+{
+ return (unsigned) GetCurrentProcessId();
+}
+#else
+static unsigned int GetPID()
+{
+ return 0; // implement me!
+}
+#endif
+
+static void LOG(const char *fmt, ... )
+{
+ va_list ap;
+ va_start(ap, fmt);
+ PRUint32 nb = 0;
+ char buf[512];
+
+ nb = PR_snprintf(buf, sizeof(buf), "[%u:%p] ", GetPID(), PR_GetCurrentThread());
+
+ PR_vsnprintf(buf + nb, sizeof(buf) - nb, fmt, ap);
+ buf[sizeof(buf) - 1] = '\0';
+
+ fwrite(buf, strlen(buf), 1, stdout);
+ fflush(stdout);
+
+ va_end(ap);
+}
+
+static void RandomSleep(PRUint32 fromMS, PRUint32 toMS)
+{
+ PRUint32 ms = fromMS + (PRUint32) ((toMS - fromMS) * ((double) rand() / RAND_MAX));
+ //LOG("putting thread to sleep for %u ms\n", ms);
+ PR_Sleep(PR_MillisecondsToInterval(ms));
+}
+
+static ipcILockService *gLockService;
+
+PR_STATIC_CALLBACK(void) TestThread(void *arg)
+{
+ const char *lockName = (const char *) arg;
+
+ LOG("entering TestThread [lock=%s]\n", lockName);
+
+ nsresult rv;
+
+ RandomSleep(1000, 1100);
+
+ //LOG("done sleeping\n");
+
+ rv = gLockService->AcquireLock(lockName, PR_TRUE);
+ if (NS_SUCCEEDED(rv))
+ {
+ //LOG("acquired lock \"%s\"\n", lockName);
+ RandomSleep(500, 1000);
+ //LOG("releasing lock \"%s\"\n", lockName);
+ rv = gLockService->ReleaseLock(lockName);
+ if (NS_FAILED(rv))
+ {
+ LOG("failed to release lock [rv=%x]\n", rv);
+ NS_ERROR("failed to release lock");
+ }
+ }
+ else
+ {
+ LOG("failed to acquire lock [rv=%x]\n", rv);
+ NS_NOTREACHED("failed to acquire lock");
+ }
+
+ LOG("exiting TestThread [lock=%s rv=%x]\n", lockName, rv);
+}
+
+static const char *kLockNames[] = {
+ "foopy",
+ "test",
+ "1",
+ "xyz",
+ "moz4ever",
+ nsnull
+};
+
+static nsresult DoTest()
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIEventQueueService> eqs =
+ do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = eqs->CreateMonitoredThreadEventQueue();
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIEventQueue> eq;
+ rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eq));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<ipcILockService> lockService =
+ do_GetService(IPC_LOCKSERVICE_CONTRACTID);
+
+ gLockService = lockService;
+
+ PRThread *threads[10] = {0};
+ int i = 0;
+
+ for (const char **lockName = kLockNames; *lockName; ++lockName, ++i)
+ {
+ threads[i] = PR_CreateThread(PR_USER_THREAD,
+ TestThread,
+ (void *) *lockName,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ }
+
+ for (i=0; threads[i]; ++i)
+ {
+ PR_JoinThread(threads[i]);
+ threads[i] = nsnull;
+ }
+
+ gLockService = nsnull;
+
+ LOG("joined with all threads; exiting DoTest\n");
+ return NS_OK;
+}
+
+int main(int argc, char **argv)
+{
+ LOG("entering main\n");
+
+ int numProcs = 10;
+
+ // if this is a child process, then just run the test
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "-child") == 0)
+ {
+ RandomSleep(1000, 1000);
+ LOG("running child test\n");
+ NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ DoTest();
+ NS_ShutdownXPCOM(nsnull);
+ return 0;
+ }
+ else if (argv[1][0] == '-')
+ {
+ // argument is a number
+ numProcs = atoi(argv[1] + 1);
+ if (numProcs == 0)
+ {
+ printf("### usage: TestIPCLocks [-N]\n"
+ "where, N is the number of test processes to spawn.\n");
+ return -1;
+ }
+ }
+ }
+
+ LOG("sleeping for 1 second\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PRProcess **procs = (PRProcess **) malloc(sizeof(PRProcess*) * numProcs);
+ int i;
+
+ // else, spawn the child processes
+ for (i=0; i<numProcs; ++i)
+ {
+ char *const argv[] = {"./TestIPCLocks", "-child", nsnull};
+ LOG("spawning child test\n");
+ procs[i] = PR_CreateProcess("./TestIPCLocks", argv, nsnull, nsnull);
+ }
+
+ PRInt32 exitCode;
+ for (i=0; i<numProcs; ++i)
+ PR_WaitProcess(procs[i], &exitCode);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/Makefile.in
new file mode 100644
index 00000000..5f80740d
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/Makefile.in
@@ -0,0 +1,52 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = common module public src
+
+ifdef ENABLE_TESTS
+DIRS += test
+endif
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/.cvsignore
new file mode 100644
index 00000000..b292dd21
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/.cvsignore
@@ -0,0 +1,9 @@
+Makefile
+module.rc
+module.res
+tmModule.obj
+transmngr_client.dll
+transmngr_client.pdb
+transmngr_client.exp
+transmngr_client.lib
+transmngr_client.ilk \ No newline at end of file
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/Makefile.in
new file mode 100644
index 00000000..87277839
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/Makefile.in
@@ -0,0 +1,75 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = transmngr
+LIBRARY_NAME = transmngr_client
+EXPORT_LIBRARY = 1
+IS_COMPONENT = 1
+MODULE_NAME = transmngr
+
+REQUIRES = ipcd \
+ string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = tmModule.cpp
+EXPORTS = tmCID.h
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)transmngr_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)transmngrcom_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../src \
+ -I$(srcdir)/../common \
+ $(NULL)
+
+EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(EXTRA_DSO_LIBS) \
+ $(MOZ_COMPONENT_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmCID.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmCID.h
new file mode 100644
index 00000000..8ca23b84
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmCID.h
@@ -0,0 +1,53 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef tmCID_h__
+#define tmCID_h__
+
+#define TRANSACTION_SERVICE_CLASSNAME \
+ "tmTransactionService"
+#define TRANSACTION_SERVICE_CONTRACTID \
+ "@mozilla.org/transaction/service;1"
+#define TRANSACTION_SERVICE_CID \
+{ /* 1403adf4-94d1-4c67-a8ae-d9f86972d378 */ \
+ 0x1403adf4, \
+ 0x94d1, \
+ 0x4c67, \
+ {0xa8, 0xae, 0xd9, 0xf8, 0x69, 0x72, 0xd3, 0x78} \
+}
+
+#endif // !tmCID_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmModule.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmModule.cpp
new file mode 100644
index 00000000..2853ba0a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/build/tmModule.cpp
@@ -0,0 +1,71 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 "nsICategoryManager.h"
+#include "nsIGenericFactory.h"
+#include "nsIServiceManager.h"
+#include "tmCID.h"
+#include "tmTransactionService.h"
+
+//-----------------------------------------------------------------------------
+// Define the contructor function for the objects
+//
+// NOTE: This creates an instance of objects by using the default constructor
+//-----------------------------------------------------------------------------
+NS_GENERIC_FACTORY_CONSTRUCTOR(tmTransactionService)
+
+//-----------------------------------------------------------------------------
+// Define a table of CIDs implemented by this module along with other
+// information like the function to create an instance, contractid, and
+// class name.
+//-----------------------------------------------------------------------------
+static const nsModuleComponentInfo components[] = {
+ { TRANSACTION_SERVICE_CLASSNAME,
+ TRANSACTION_SERVICE_CID,
+ TRANSACTION_SERVICE_CONTRACTID,
+ tmTransactionServiceConstructor },
+ /*
+ tmTransactionServiceRegisterProc,
+ tmTransactionServiceUnregisterProc },
+ */
+};
+
+//-----------------------------------------------------------------------------
+// Implement the NSGetModule() exported function for your module
+// and the entire implementation of the module object.
+//-----------------------------------------------------------------------------
+NS_IMPL_NSGETMODULE(transmngr, components)
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/.cvsignore
new file mode 100644
index 00000000..df8a43a2
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+tmTransaction.obj
+tmVector.obj
+transmgrcom_s.pdb
+transmgrcom_s.lib
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/Makefile.in
new file mode 100644
index 00000000..4521c39a
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/Makefile.in
@@ -0,0 +1,61 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = transmgrcom_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME = ipcd
+
+FORCE_USE_PIC = 1
+
+REQUIRES = \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ tmTransaction.cpp \
+ tmVector.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.cpp
new file mode 100644
index 00000000..5fb7e5bf
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.cpp
@@ -0,0 +1,107 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 <stdlib.h>
+#include "tmTransaction.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructor(s) & Destructor
+
+tmTransaction::~tmTransaction() {
+ if (mHeader)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mHeader);
+#else
+ free(mHeader);
+#endif
+}
+
+// call only once per lifetime of object. does not reclaim the
+// raw message, only sets it.
+nsresult
+tmTransaction::Init(PRUint32 aOwnerID,
+ PRInt32 aQueueID,
+ PRUint32 aAction,
+ PRInt32 aStatus,
+ const PRUint8 *aMessage,
+ PRUint32 aLength) {
+ nsresult rv = NS_OK;
+ tmHeader *header = nsnull;
+
+ // indicates the message is the entire raw message
+ if (aQueueID == TM_INVALID_ID) {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ header = (tmHeader*) RTMemAlloc(aLength);
+#else
+ header = (tmHeader*) malloc(aLength);
+#endif
+ if (header) {
+ mRawMessageLength = aLength;
+ memcpy(header, aMessage, aLength);
+ }
+ else
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ else { // need to create the tmHeader and concat the message
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ header = (tmHeader*) RTMemAlloc (sizeof(tmHeader) + aLength);
+#else
+ header = (tmHeader*) malloc (sizeof(tmHeader) + aLength);
+#endif
+ if (header) {
+ mRawMessageLength = sizeof(tmHeader) + aLength;
+ header->action = aAction;
+ header->queueID = aQueueID;
+ header->status = aStatus;
+ header->reserved = 0x00000000;
+ if (aLength > 0) // add the message if it exists
+ memcpy((header + 1), aMessage, aLength);
+ }
+ else
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ mOwnerID = aOwnerID;
+ mHeader = header;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.h
new file mode 100644
index 00000000..b86f20f0
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmTransaction.h
@@ -0,0 +1,234 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmTransaction_H_
+#define _tmTransaction_H_
+
+#include "tmUtils.h"
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Message format
+//
+// |------------------------------------|--
+// |QueueID | |
+// |------------------------------------| |
+// | Action - Post/Flush/Attach etc | |- this is the tmHeader struct
+// |------------------------------------| |
+// |Status | |
+// |------------------------------------| |
+// |Padding | |
+// |------------------------------------|--
+// |Message Data (payload) |
+// |------------------------------------|
+//
+// The Attach call is a special case in that it doesn't have a QueueID yet. A
+// QueueID will be 0's. The message Data will be the Queue Name String which
+// will be the profile name with a domain attached, a domain being
+// [prefs|cookies|etc]
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * tmHeader contains various flags identifying
+ */
+struct tmHeader {
+ PRInt32 queueID; // will be the index of the queue in the TM, can be < 0
+ PRUint32 action; // defined by tmUtils.h will be > 0
+ PRInt32 status; // return values from methods, could be < 0
+ PRUint32 reserved; // not currently used, maintaining word alignment
+};
+
+/**
+ * Using tmTransaction:
+ *
+ * After creating a tmTransaction either through new or as a member
+ * or local variable a process must call Init() with the proper set of
+ * arguements to initialize the state of the transaction. tmTransaction is
+ * set up to accept 3 types of initialization.
+ *
+ * 1) Raw message - All data is carried in the byte pointer aMessage,
+ * args 2,3,4 should be set to TM_NO_ID and aLength
+ * must be set to the full length of aMessage, including null
+ * termination if the payload is a null-term string and the size of the
+ * tmHeader struct preceeding the message. Currently this
+ * format is used at the IPC boundary, where we receive a byte pointer
+ * from the IPC Daemon.
+ *
+ * 2) Flags only - aQueueID, aAction and aStatus are all set. aMessage
+ * should be set to nsnull and aLength to 0. This format is used when
+ * sending reply messages (except for ATTACH_REPLY) and when the TS
+ * Transaction Service is sending "control" messages to the Manager -
+ * flush, detach, etc...
+ *
+ * 3) Flags and message - All arguements are set. The aMessage is only
+ * the message for the client app. aLength should be set to the length
+ * of aMessage and not include the length of the tmHeader struct.
+ *
+ * The only data member you can set post initialization is the QueueID.
+ * You should only call Init() once in the lifetime of a tmTransaction
+ * as it doesn't clean up the exisiting data before assigning the new
+ * data. Therefore it would leak most heinously if Init() were to be
+ * called twice.
+ *
+ * mOwnerID only has relevance on the IPC daemon side of things. The
+ * Transaction Service has no knowledge of this ID and makes no use
+ * of it.
+ */
+class tmTransaction
+{
+
+public:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructor(s) & Destructor
+
+ tmTransaction(): mHeader(nsnull), mRawMessageLength(0), mOwnerID(0) { }
+
+ virtual ~tmTransaction();
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Public Member Functions
+
+ // Initializer ////////////
+
+ /**
+ * Sets up the internal data of the transaction. Allows for 3 basic ways
+ * to call this function: No flags and just one big raw message, Just
+ * flags and no message, and finally flags and message. If the message
+ * exists it is copied into the transaction.
+ *
+ * @param aOwnerID is given to us by the IPC Daemon and is specific
+ * to that transport layer. It is only set when transactions
+ * are sent from the TM to the TS.
+ *
+ * @param aQueueID is the either the destination queue, or the queue from
+ * where this transaction is eminating
+ *
+ * @param aAction is the action that occured to generate this transaction
+ *
+ * @param aStatus is the success state of the action.
+ *
+ * @param aMessage can be a raw message including the 3 flags above or it
+ * can be just the "payload" of the transaction that the destination
+ * process is going deal with.
+ *
+ * @param aLength is the length of the message. If there is a null
+ * terminated string in the message make sure the length includes
+ * the null termination.
+ *
+ * @returns NS_OK if everything was successful
+ * @returns NS_ERROR_OUT_OF_MEMORY if allocation of space for the
+ * copy of the message fails.
+ */
+ nsresult Init(PRUint32 aOwnerID,
+ PRInt32 aQueueID,
+ PRUint32 aAction,
+ PRInt32 aStatus,
+ const PRUint8 *aMessage,
+ PRUint32 aLength);
+
+ // Data Accessors /////////
+
+ /**
+ * @returns a const byte pointer to the message
+ */
+ const PRUint8* GetMessage() const { return (PRUint8*)(mHeader + 1); }
+
+ /**
+ * @returns the length of the message
+ */
+ PRUint32 GetMessageLength() const {
+ return (mRawMessageLength > sizeof(tmHeader)) ?
+ (mRawMessageLength - sizeof(tmHeader)) : 0;
+ }
+
+ /**
+ * @returns a const pointer to the memory containing the
+ * flag information followed immediately by the message
+ * data.
+ */
+ const PRUint8* GetRawMessage() const { return (PRUint8*) mHeader; }
+
+ /**
+ * @returns the length of the flags and message combined
+ */
+ PRUint32 GetRawMessageLength() const { return mRawMessageLength; }
+
+ /**
+ * @returns the id of the destination or sending queue, depending on the
+ * direction of the transaction.
+ */
+ PRInt32 GetQueueID() const { return mHeader->queueID; }
+
+ /**
+ * @returns the action represented by this transaction
+ */
+ PRUint32 GetAction() const { return mHeader->action; }
+
+ /**
+ * @returns the success state, if applicable of the action leading
+ * up to this message
+ */
+ PRInt32 GetStatus() const { return mHeader->status; }
+
+ /**
+ * @returns the client ID (in IPC daemon terms) of the client who initiated
+ * the exchange that generated this transaction.
+ */
+ PRUint32 GetOwnerID() const { return mOwnerID; }
+
+ // Data Mutator ///////////
+
+ /**
+ * Sets the ID of the destination or source queue. Init should have been
+ * called before the call to this function.
+ */
+ void SetQueueID(PRInt32 aID) { mHeader->queueID = aID; }
+
+protected:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Variables
+
+ tmHeader* mHeader; // points to beginning of entire message
+ PRUint32 mRawMessageLength; // length of entire message, incl tmHeader
+ PRUint32 mOwnerID; // client who sent this trans. - a IPC ClientID
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmUtils.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmUtils.h
new file mode 100644
index 00000000..f85184d3
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmUtils.h
@@ -0,0 +1,93 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmUtils_H_
+#define _tmUtils_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsID.h"
+#include "prlog.h"
+#include <stdio.h>
+
+// UUID used to identify the Transaction Module in both daemon and client
+// not part of the XPCOM hooks, but rather a means of identifying
+// modules withing the IPC daemon.
+#define TRANSACTION_MODULE_ID \
+{ /* c3dfbcd5-f51d-420b-abf4-3bae445b96a9 */ \
+ 0xc3dfbcd5, \
+ 0xf51d, \
+ 0x420b, \
+ {0xab, 0xf4, 0x3b, 0xae, 0x44, 0x5b, 0x96, 0xa9} \
+}
+
+//static const nsID kTransModuleID = TRANSACTION_MODULE_ID;
+
+///////////////////////////////////////////////////////////////////////////////
+// match NS_ERROR_FOO error code formats
+//
+// only create new errors for those errors that are specific to TM
+
+#define NS_ERROR_MODULE_TM 27 /* XXX goes in nserror.h -- integrating with ns error codes */
+
+#define TM_ERROR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_TM, 1)
+#define TM_ERROR_WRONG_QUEUE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_TM, 2)
+#define TM_ERROR_NOT_POSTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_TM, 3)
+#define TM_ERROR_QUEUE_EXISTS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_TM, 4)
+#define TM_SUCCESS_DELETE_QUEUE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_TM, 6)
+
+
+// XXX clean up:
+#define TM_INVALID_ID 0xFFFFFFFF
+#define TM_INVALID 0xFFFFFFFF
+#define TM_NO_ID 0xFFFFFFFE
+
+// Transaction Actions
+enum {
+ TM_ATTACH = 0,
+ TM_ATTACH_REPLY,
+ TM_POST,
+ TM_POST_REPLY,
+ TM_NOTIFY,
+ TM_FLUSH,
+ TM_FLUSH_REPLY,
+ TM_DETACH,
+ TM_DETACH_REPLY
+};
+
+#endif
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.cpp
new file mode 100644
index 00000000..99213f27
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.cpp
@@ -0,0 +1,179 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 <stdlib.h>
+#include "tmVector.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+////////////////////////////////////////////////////////////////////////////
+// Constructor(s) & Destructor
+
+// can not be responsible for reclaiming memory pointed to by the void*s in
+// the collection - how would we reclaim, don't know how they were allocated
+tmVector::~tmVector() {
+ if (mElements)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree((void*)mElements);
+#else
+ free((void*)mElements);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Public Member Functions
+
+nsresult
+tmVector::Init() {
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mElements = (void**) RTMemAllocZ (mCapacity * sizeof(void*));
+#else
+ mElements = (void**) calloc (mCapacity, sizeof(void*));
+#endif
+ if (!mElements)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// mutators
+
+PRInt32
+tmVector::Append(void *aElement){
+ PR_ASSERT(aElement);
+
+ // make sure there is room
+ if (mNext == mCapacity)
+ if (NS_FAILED(Grow()))
+ return -1;
+
+ // put the element in the array
+ mElements[mNext] = aElement;
+ mCount++;
+
+ // encapsulates the index into a success value
+ return mNext++; // post increment.
+}
+
+void
+tmVector::Remove(void *aElement) {
+ PR_ASSERT(aElement);
+
+ for (PRUint32 index = 0; index < mNext; index++) {
+ if (mElements[index] == aElement) {
+ mElements[index] = nsnull;
+ mCount--;
+ if (index == mNext-1) { // if we removed the last element
+ mNext--;
+ // don't test for success of the shrink
+ Shrink();
+ }
+ }
+ }
+}
+
+void
+tmVector::RemoveAt(PRUint32 aIndex) {
+ PR_ASSERT(aIndex < mNext);
+
+ // remove the element if it isn't already nsnull
+ if (mElements[aIndex] != nsnull) {
+ mElements[aIndex] = nsnull;
+ mCount--;
+ if (aIndex == mNext-1) { // if we removed the last element
+ mNext--;
+ // don't test for success of the shrink
+ Shrink();
+ }
+ }
+}
+
+//void*
+//tmVector::operator[](int index) {
+// if (index < mNext && index >= 0)
+// return mElements[index];
+// return nsnull;
+//}
+
+// Does not delete any of the data, merely removes references to them
+void
+tmVector::Clear(){
+ memset(mElements, 0, mCapacity);
+ mCount = 0;
+ mNext = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Protected Member Functions
+
+// increases the capacity by the growth increment
+nsresult
+tmVector::Grow() {
+
+ PRUint32 newcap = mCapacity + GROWTH_INC;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mElements = (void**) RTMemRealloc(mElements, (newcap * sizeof(void*)));
+#else
+ mElements = (void**) realloc(mElements, (newcap * sizeof(void*)));
+#endif
+ if (mElements) {
+ mCapacity = newcap;
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+// reduces the capacity by the growth increment. leaves room
+// for one more add before needing to Grow().
+nsresult
+tmVector::Shrink() {
+
+ PRUint32 newcap = mCapacity - GROWTH_INC;
+ if (mNext < newcap) {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mElements = (void**) RTMemRealloc(mElements, newcap * sizeof(void*));
+#else
+ mElements = (void**) realloc(mElements, newcap * sizeof(void*));
+#endif
+ if (!mElements)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mCapacity = newcap;
+ }
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.h
new file mode 100644
index 00000000..4ddb68ef
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/common/tmVector.h
@@ -0,0 +1,160 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmVector_H_
+#define _tmVector_H_
+
+#include "tmUtils.h"
+
+#define GROWTH_INC 5
+
+/**
+ * A simple, clear, self-growing, collection of objects. typed independant
+ * basically a growing array. Useful in situations where you need an
+ * indexed collection but do not know the size in advance and need the
+ * ability for increase and decrease in size. Not optimized for anything
+ * in particular, or any size in particular.
+ *
+ * Is able to guarantee the index of an item will
+ * not change due to removals of a lower indexed item. The growing,
+ * and shrinking all happens to the end of the collection
+ *
+ * Does not backfill, adds to the end. At some point this should be
+ * changed to make best use of space.
+ */
+class tmVector
+{
+public:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructor(s) & Destructor
+
+ /**
+ * Set some sane default values to set up the internal storage. Init()
+ * must be called after construction of the object to allcate the
+ * backing store.
+ */
+ tmVector() : mNext(0), mCount(0), mCapacity(10), mElements(nsnull) {;}
+
+ /**
+ * Reclaim the memory allocated in the Init() method.
+ */
+ virtual ~tmVector();
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Public Member Functions
+
+ /**
+ * Allocates the storage back-end
+ *
+ * @returns NS_OK if allocation succeeded
+ * @returns NS_ERROR_OUT_OF_MEMORY if the allocation failed
+ */
+ nsresult Init();
+
+ // mutators
+
+ /**
+ * @returns the index of the element added, if successful
+ * @returns -1 if an error occured during allocation of space
+ */
+ PRInt32 Append(void *aElement);
+
+ /**
+ * This does not collapse the collection, it leaves holes. Note, it also
+ * doesn't delete the element, it merely removes it from the collection
+ */
+ void Remove(void *aElement);
+
+ /**
+ * This does not collapse the collection, it leaves holes. Note, it also
+ * doesn't delete the element, it merely removes it from the collection
+ */
+ void RemoveAt(PRUint32 aIndex);
+
+ /**
+ * Does not call delete on the elements since we have no idea how to
+ * reclaim the memory. Sets all array slots to 0.
+ */
+ void Clear();
+
+ /**
+ * @returns the element at the index indicated, including nsnull if the
+ * slot is empty.
+ */
+ void* operator[](PRUint32 index) {
+ PR_ASSERT(index < mNext);
+ return mElements[index];
+ }
+
+ /**
+ * @returns the number of elements stored
+ */
+ PRUint32 Count() { return mCount; }
+
+ /**
+ * Meant to be used as the conditional in a loop. |index < size| should
+ * reach all elements of the collection and not run out of bounds. If
+ * slots 0,1,4,5,6 contain elements Size() will return 7, Count() will
+ * return 5.
+ *
+ * @returns the number of slots in the array taken, irrespective of
+ * holes in the collection.
+ */
+ PRUint32 Size() { return mNext; }
+
+protected:
+
+ nsresult Grow(); // mCapacity += GROWTH_INC - realloc()s
+ nsresult Shrink(); // mCapacity -= GROWTH_INC - dumb, free, malloc
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Variables
+
+ // bookkeeping variables
+ PRUint32 mNext; // next element insertion slot (0 based)
+ PRUint32 mCount; // how many elements in the Vector (1 based)
+ PRUint32 mCapacity; // current capacity of the Vector (1 based)
+
+ // the actual array of objects being stored
+ void **mElements;
+
+private:
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/.cvsignore
new file mode 100644
index 00000000..ccfb2bc3
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/.cvsignore
@@ -0,0 +1,11 @@
+Makefile
+module.rc
+module.res
+tmIPCModule.obj
+tmQueue.obj
+tmTransactionManager.obj
+transmgr.dll
+transmgr.exp
+transmgr.ilk
+transmgr.lib
+transmgr.pdb
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/Makefile.in
new file mode 100644
index 00000000..b8baa225
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/Makefile.in
@@ -0,0 +1,100 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = transmgr
+MODULE_NAME = ipcd
+
+FORCE_SHARED_LIB = 1
+NO_DIST_INSTALL = 1
+NO_INSTALL = 1
+
+ifeq ($(OS_ARCH),Darwin)
+NO_COMPONENT_LINK_MAP = 1
+MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS =
+endif
+
+REQUIRES = nspr \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ tmIPCModule.cpp \
+ tmQueue.cpp \
+ tmTransactionManager.cpp \
+ $(NULL)
+
+EXPORTS = \
+ tmIPCModule.h \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../common \
+ $(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(EXTRA_DSO_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(NSPR_LIBS) \
+ $(DIST)/lib/$(LIB_PREFIX)transmgrcom_s.$(LIB_SUFFIX) \
+ $(EXTRA_DSO_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+_IPC_FILES = \
+ $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX) \
+ $(NULL)
+
+libs:: $(_IPC_FILES)
+ $(INSTALL) $^ $(DIST)/bin/ipc/modules
+
+install:: $(_IPC_FILES)
+ $(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/ipc/modules
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.cpp
new file mode 100644
index 00000000..3982c93c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.cpp
@@ -0,0 +1,137 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 "tmIPCModule.h"
+#include "tmTransaction.h"
+#include "tmTransactionManager.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// IPC Daemon hookup stuff
+
+// functionpointer array giving access to this module from the IPC daemon
+static ipcModuleMethods gTransMethods =
+{
+ IPC_MODULE_METHODS_VERSION,
+ tmIPCModule::Init,
+ tmIPCModule::Shutdown,
+ tmIPCModule::HandleMsg
+};
+
+static ipcModuleEntry gTransModuleEntry[] =
+{
+ { TRANSACTION_MODULE_ID, &gTransMethods }
+};
+
+IPC_IMPL_GETMODULES(TransactionModule, gTransModuleEntry)
+
+static const nsID kTransModuleID = TRANSACTION_MODULE_ID;
+
+///////////////////////////////////////////////////////////////////////////////
+// Define global variable
+
+tmTransactionManager *tmIPCModule::tm;
+
+///////////////////////////////////////////////////////////////////////////////
+// IPC Module API
+
+void
+tmIPCModule::Init() {
+ if (!tm)
+ InitInternal();
+}
+
+void
+tmIPCModule::Shutdown() {
+ if (tm) {
+ delete tm;
+ tm = nsnull;
+ }
+}
+
+// straight pass-through, don't check args, let the TM do it.
+void
+tmIPCModule::HandleMsg(ipcClientHandle client, const nsID &target,
+ const void *data, PRUint32 dataLen) {
+
+ // make sure the trans mngr is there
+ if (!tm && (InitInternal() < 0))
+ return;
+
+ // create the transaction
+ tmTransaction *trans = new tmTransaction();
+
+ // initialize it
+ if (trans) {
+ if(NS_SUCCEEDED(trans->Init(IPC_GetClientID(client), // who owns it
+ TM_INVALID_ID, // in data
+ TM_INVALID, // in data
+ TM_INVALID, // in data
+ (PRUint8 *)data, // raw message
+ dataLen))) { // length of message
+ // pass it on to the trans mngr
+ tm->HandleTransaction(trans);
+ }
+ else
+ delete trans;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// tmIPCModule API
+
+// straight pass-through, don't check args, let the TS & TM do it.
+void
+tmIPCModule::SendMsg(PRUint32 aDestClientIPCID, tmTransaction *aTransaction) {
+
+ IPC_SendMsg(aDestClientIPCID,
+ kTransModuleID,
+ (void *)aTransaction->GetRawMessage(),
+ aTransaction->GetRawMessageLength());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Protected Methods
+
+PRInt32
+tmIPCModule::InitInternal() {
+
+ tm = new tmTransactionManager();
+ if (tm)
+ return tm->Init();
+ return -1;
+}
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.h
new file mode 100644
index 00000000..d4623b1e
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmIPCModule.h
@@ -0,0 +1,109 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmIPCModule_H_
+#define _tmIPCModule_H_
+
+#include "ipcModuleUtil.h"
+#include "tmUtils.h"
+
+// forward declarations
+class tmTransaction;
+class tmTransactionManager;
+
+/**
+ * Basically an interface between the tmTransactionManager and the IPC
+ * daemon. Does little else than format the data from one party into
+ * a format understandable to the other.
+ *
+ * The reason for this class is to try and abstract the transportation
+ * layer the transaction service uses. By using this class the Transaction
+ * Manager itself only needs to know that clients are identified by
+ * PRUint32 IDs.
+ */
+class tmIPCModule
+{
+public:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // ipcModule API - called from IPC daemon
+
+ /**
+ * Clean up the TM
+ */
+ static void Shutdown();
+
+ /**
+ * Check the TM, create it if neccessary.
+ */
+ static void Init();
+
+ /**
+ * Receives a message from the IPC daemon, creates a transaction and sends
+ * it to the TM to deal with.
+ */
+ static void HandleMsg(ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // tmIPCModule API - called from tmTransactionManager
+
+ /**
+ * Sends the message to the IPC daemon to be deliverd to the client arg.
+ */
+ static void SendMsg(PRUint32 aDestClientIPCID, tmTransaction *aTransaction);
+
+protected:
+
+ /**
+ * tm should be null coming into this method. This does NOT delete tm
+ * first.
+ *
+ * @returns NS_OK if everything succeeds
+ * @returns -1 if initialization fails
+ */
+ static PRInt32 InitInternal();
+
+ static tmTransactionManager *tm;
+
+};
+
+#endif
+
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.cpp
new file mode 100644
index 00000000..5164446f
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.cpp
@@ -0,0 +1,223 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 "plstr.h"
+#include "tmQueue.h"
+#include "tmTransaction.h"
+#include "tmTransactionManager.h"
+#include "tmUtils.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructors & Destructor
+
+tmQueue::~tmQueue() {
+
+ // empty the vectors
+ PRUint32 index = 0;
+ PRUint32 size = mTransactions.Size();
+ for ( ; index < size ; index++) {
+ if (mTransactions[index])
+ delete (tmTransaction *)mTransactions[index];
+ }
+
+ // don't need to delete the mListeners because
+ // we just insert PRUint32s, no allocation
+
+ mTM = nsnull;
+ mID = 0;
+ if (mName)
+ PL_strfree(mName);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Public Methods
+
+PRInt32
+tmQueue::Init(const char* aName, PRUint32 aID, tmTransactionManager *aTM) {
+ PR_ASSERT(mTM == nsnull);
+
+ if (NS_SUCCEEDED(mTransactions.Init()) &&
+ NS_SUCCEEDED(mListeners.Init()) &&
+ ((mName = PL_strdup(aName)) != nsnull) ) {
+ mTM = aTM;
+ mID = aID;
+ return NS_OK;
+ }
+ return -1;
+}
+
+PRInt32
+tmQueue::AttachClient(PRUint32 aClientID) {
+
+ PRInt32 status = NS_OK; // success of adding client
+
+ if (!IsAttached(aClientID)) {
+ // add the client to the listener list -- null safe call
+ status = mListeners.Append((void*) aClientID);
+ }
+ else
+ status = -2;
+
+ // create & init a reply transaction
+ tmTransaction trans;
+ if (NS_SUCCEEDED(trans.Init(aClientID, // owner's ipc ID
+ mID, // client gets our ID
+ TM_ATTACH_REPLY, // action
+ status, // success of the add
+ (PRUint8*)mName, // client matches name to ID
+ PL_strlen(mName)+1))) {
+ // send the reply
+ mTM->SendTransaction(aClientID, &trans);
+ }
+
+ // if we successfully added the client - send all current transactions
+ if (status >= 0) { // append returns the index of the added element
+
+ PRUint32 size = mTransactions.Size();
+ for (PRUint32 index = 0; index < size; index++) {
+ if (mTransactions[index])
+ mTM->SendTransaction(aClientID, (tmTransaction*) mTransactions[index]);
+ }
+ }
+ return status;
+}
+
+PRInt32
+tmQueue::DetachClient(PRUint32 aClientID) {
+
+ PRUint32 size = mListeners.Size();
+ PRUint32 id = 0;
+ PRInt32 status = -1;
+
+ for (PRUint32 index = 0; index < size; index++) {
+ id = (PRUint32)NS_PTR_TO_INT32(mListeners[index]);
+ if(id == aClientID) {
+ mListeners.RemoveAt(index);
+ status = NS_OK;
+ break;
+ }
+ }
+
+ tmTransaction trans;
+ if (NS_SUCCEEDED(trans.Init(aClientID,
+ mID,
+ TM_DETACH_REPLY,
+ status,
+ nsnull,
+ 0))) {
+ // send the reply
+ mTM->SendTransaction(aClientID, &trans);
+ }
+
+ // if we've removed all the listeners, remove the queue.
+ if (mListeners.Size() == 0)
+ return TM_SUCCESS_DELETE_QUEUE;
+ return status;
+}
+
+void
+tmQueue::FlushQueue(PRUint32 aClientID) {
+
+ if(!IsAttached(aClientID))
+ return;
+
+ PRUint32 size = mTransactions.Size();
+ for (PRUint32 index = 0; index < size; index++)
+ if (mTransactions[index])
+ delete (tmTransaction*)mTransactions[index];
+
+ mTransactions.Clear();
+
+ tmTransaction trans;
+ if (NS_SUCCEEDED(trans.Init(aClientID,
+ mID,
+ TM_FLUSH_REPLY,
+ NS_OK,
+ nsnull,
+ 0))) {
+ mTM->SendTransaction(aClientID, &trans);
+ }
+}
+
+PRInt32
+tmQueue::PostTransaction(tmTransaction *aTrans) {
+
+ PRInt32 status = -1;
+ PRUint32 ownerID = aTrans->GetOwnerID();
+
+ // if we are attached, have the right queue and have successfully
+ // appended the transaction to the queue, send the transaction
+ // to all the listeners.
+
+ if (IsAttached(ownerID) && aTrans->GetQueueID() == mID)
+ status = mTransactions.Append(aTrans);
+
+ if (status >= 0) {
+ // send the transaction to all members of mListeners except the owner
+ PRUint32 size = mListeners.Size();
+ PRUint32 id = 0;
+ for (PRUint32 index = 0; index < size; index++) {
+ id = (PRUint32)NS_PTR_TO_INT32(mListeners[index]);
+ if (ownerID != id)
+ mTM->SendTransaction(id, aTrans);
+ }
+ }
+
+ tmTransaction trans;
+ if (NS_SUCCEEDED(trans.Init(ownerID,
+ mID,
+ TM_POST_REPLY,
+ status,
+ nsnull,
+ 0))) {
+ // send the reply
+ mTM->SendTransaction(ownerID, &trans);
+ }
+ return status;
+}
+
+PRBool
+tmQueue::IsAttached(PRUint32 aClientID) {
+ // XXX could be an issue if the aClientID is 0 and there
+ // is a "hole" in the mListeners vector. - may NEED to store PRUint32*s
+ PRUint32 size = mListeners.Size();
+ for (PRUint32 index = 0; index < size; index++) {
+ if (aClientID == (PRUint32)NS_PTR_TO_INT32(mListeners[index]))
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.h
new file mode 100644
index 00000000..1c680084
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmQueue.h
@@ -0,0 +1,186 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmQueue_H_
+#define _tmQueue_H_
+
+#include "tmUtils.h"
+#include "tmVector.h"
+
+class tmClient;
+class tmTransaction;
+class tmTransactionManager;
+
+/**
+ * This class isn't so much a queue as it is storage for transactions. It
+ * is set up to recieve and store transactions in a growing collection
+ * (using tmVectors). Different messages can be recieved from the
+ * Transaction Manager(TM) the queue belongs to which can add and remove
+ * listeners, empty the queue (flush), and add messages to the queue.
+ *
+ * See the documentation in tmTransactionService.h for details on the
+ * messages you can send to and recieve from the queues in the TM
+ */
+class tmQueue
+{
+
+public:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructor & Destructor
+
+ /**
+ * Set the internal state to default values. Init() must be called
+ * after construction to allocate the storage and set the name and ID.
+ */
+ tmQueue(): mID(0), mName(nsnull), mTM(nsnull) { }
+
+ /**
+ * Reclaim the memory allocated in Init(). Destroys the transactions in
+ * the transaction storage and the ids in the listener storage
+ */
+ virtual ~tmQueue();
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Public Member Functions
+
+ /**
+ * Initialize internal storage vectors and set the name of the queue
+ * and the pointer to the TM container.
+ *
+ * @returns NS_OK if everything succeeds
+ * @returns -1 if initialization fails
+ */
+ PRInt32 Init(const char* aName, PRUint32 aID, tmTransactionManager *aTM);
+
+ // Queue Operations
+
+ /**
+ * Adds the clientID to the list of queue listeners. A reply is created
+ * and sent to the client. The reply contains both the name of the
+ * queue and the id, so the client can match the id to the name and
+ * then use the id in all further communications to the queue. All
+ * current transactions in the queue are then sent to the client.
+ *
+ * If the client was already attached the reply is sent, but not the
+ * outstanding transactions, the assumption being made that all
+ * transactions have already been sent to the client.
+ *
+ * The reply is sent for all cases, with the return value in the status
+ * field.
+ *
+ * @returns >= 0 if the client was attached successfully
+ * @returns -1 if the client was not attached
+ * @returns -2 if the client was already attached
+ */
+ PRInt32 AttachClient(PRUint32 aClientID);
+
+ /**
+ * Removes the client from the list of queue listeners. A reply is created
+ * and sent to the client to indicate the success of the removal.
+ *
+ * The reply is sent for all cases, with the status field set to either
+ * -1 or NS_OK.
+ *
+ * @returns NS_OK on success
+ * @returns -1 if client is not attached to this queue
+ * @returns TM_SUCCESS_DELETE_QUEUE if there are no more listeners,
+ * instructing the Transaction Mangaer to delete the queue.
+ */
+ PRInt32 DetachClient(PRUint32 aClientID);
+
+ /**
+ * Removes all the transactions being held in the queue.
+ * A reply is created and sent to the client to indicate the
+ * completion of the operation.
+ */
+ void FlushQueue(PRUint32 aClientID);
+
+ /**
+ * Places the transaction passed in on the queue. Takes ownership of the
+ * transaction, deletes it in the destructor. A reply is created and
+ * sent to the client to indicate the success of the posting of the
+ * transaction.
+ *
+ * The reply is sent for all cases, with the status field containing the
+ * return value.
+ *
+ * @returns >= 0 if the message was posted properly.
+ * @returns -1 if the client posting is not attached to this queue,
+ * if the transaction has been posted to the wrong queue or
+ * if an error occured when trying to add the post to the
+ * internal storage.
+ */
+ PRInt32 PostTransaction(tmTransaction *aTrans);
+
+ // Accessors
+
+ /**
+ * @returns the ID of the queue
+ */
+ PRUint32 GetID() const { return mID; }
+
+ /**
+ * @returns the name of the queue
+ */
+ const char* GetName() const { return mName; }
+
+protected:
+
+ /**
+ * Helper method to determine if the client has already attached.
+ *
+ * @returns PR_TRUE if the client is attached to the queue.
+ * @returns PR_FALSE if the client is not attached to the queue.
+ */
+ PRBool IsAttached(PRUint32 aClientID);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Variables
+
+ // storage
+ tmVector mTransactions; // transactions that have been posted
+ tmVector mListeners; // programs listening to this queue
+
+ // bookkeeping
+ PRUint32 mID; // a number linked to the name in the mTM
+ char *mName; // format: [namespace][domainname(ie prefs)]
+ tmTransactionManager *mTM; // the container that holds the queue
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.cpp
new file mode 100644
index 00000000..9d6cc98e
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.cpp
@@ -0,0 +1,162 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 "plstr.h"
+#include <stdlib.h>
+#include "tmQueue.h"
+#include "tmTransactionManager.h"
+#include "tmTransaction.h"
+#include "tmUtils.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructors & Destructor & Initializer
+
+tmTransactionManager::~tmTransactionManager() {
+
+ PRUint32 size = mQueues.Size();
+ tmQueue *queue = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ queue = (tmQueue *)mQueues[index];
+ if (queue) {
+ delete queue;
+ }
+ }
+}
+
+PRInt32
+tmTransactionManager::Init() {
+ return mQueues.Init();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// public transaction module methods
+
+void
+tmTransactionManager::HandleTransaction(tmTransaction *aTrans) {
+
+ PRUint32 action = aTrans->GetAction();
+ PRUint32 ownerID = aTrans->GetOwnerID();
+ tmQueue *queue = nsnull;
+
+ // get the right queue -- attaches do it differently
+ if (action == TM_ATTACH) {
+ const char *name = (char*) aTrans->GetMessage(); // is qName for Attaches
+ queue = GetQueue(name);
+ if (!queue) {
+ PRInt32 index = AddQueue(name);
+ if (index >= 0)
+ queue = GetQueue(index); // GetQueue may return nsnull
+ }
+ }
+ else // all other trans should have a valid queue ID already
+ queue = GetQueue(aTrans->GetQueueID());
+
+ if (queue) {
+ // All possible actions should have a case, default is not valid
+ // delete trans when done with them, let the queue own the trans
+ // that are posted to them.
+ PRInt32 result = 0;
+ switch (action) {
+ case TM_ATTACH:
+ queue->AttachClient(ownerID);
+ break;
+ case TM_POST:
+ result = queue->PostTransaction(aTrans);
+ if (result >= 0) // post failed, aTrans cached in a tmQueue
+ return;
+ break;
+ case TM_FLUSH:
+ queue->FlushQueue(ownerID);
+ break;
+ case TM_DETACH:
+ if (queue->DetachClient(ownerID) == TM_SUCCESS_DELETE_QUEUE) {
+ // the last client has been removed, remove the queue
+ RemoveQueue(aTrans->GetQueueID()); // this _could_ be out of bounds
+ }
+ break;
+ default:
+ PR_NOT_REACHED("bad action in the transaction");
+ }
+ }
+ delete aTrans;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Protected member functions
+
+//
+// Queue Handling
+//
+
+tmQueue*
+tmTransactionManager::GetQueue(const char *aQueueName) {
+
+ PRUint32 size = mQueues.Size();
+ tmQueue *queue = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ queue = (tmQueue*) mQueues[index];
+ if (queue && strcmp(queue->GetName(), aQueueName) == 0)
+ return queue;
+ }
+ return nsnull;
+}
+
+// if successful the nsresult contains the index of the added queue
+PRInt32
+tmTransactionManager::AddQueue(const char *aQueueName) {
+
+ tmQueue* queue = new tmQueue();
+ if (!queue)
+ return -1;
+ PRInt32 index = mQueues.Append(queue);
+ if (index < 0)
+ delete queue;
+ else
+ queue->Init(aQueueName, index, this);
+ return index;
+}
+
+void
+tmTransactionManager::RemoveQueue(PRUint32 aQueueID) {
+ PR_ASSERT(aQueueID <= mQueues.Size());
+
+ tmQueue *queue = (tmQueue*)mQueues[aQueueID];
+ if (queue) {
+ mQueues.RemoveAt(aQueueID);
+ delete queue;
+ }
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.h
new file mode 100644
index 00000000..a03ba528
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/module/tmTransactionManager.h
@@ -0,0 +1,147 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmTransactionManager_H_
+#define _tmTransactionManager_H_
+
+#include "plhash.h"
+#include "tmUtils.h"
+#include "tmVector.h"
+#include "tmIPCModule.h"
+
+// forward declarations
+class tmQueue;
+class tmClient;
+class tmTransaction;
+
+/**
+ * This class manages the flow of messages from the IPC daemon (coming to
+ * it through the tmIPCModule) that ultimately come from a Transaction
+ * Service (TS) in a mozilla based client somewhere. The message is
+ * delivered to the proper queue, where it is dealt with.
+ *
+ * New queues get created here as clients request them.
+ */
+class tmTransactionManager
+{
+
+public:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructor(s) & Destructor & Initializer
+
+ /**
+ * reclaim the memory allcoated during initialization
+ */
+ virtual ~tmTransactionManager();
+
+ /**
+ * Set up the storage of the queues - initialize the vector
+ *
+ * @returns NS_OK if successful
+ * @returns -1 if initialization fails
+ */
+ PRInt32 Init();
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Public Member Functions
+
+ /**
+ * Called from the tmIPCModule. Decide where to send the message and
+ * dispatch it.
+ */
+ void HandleTransaction(tmTransaction *aTrans);
+
+ /**
+ * Called by the queues when they need to get a message back out to a
+ * client.
+ */
+ void SendTransaction(PRUint32 aDestClientIPCID, tmTransaction *aTrans) {
+ PR_ASSERT(aTrans);
+ tmIPCModule::SendMsg(aDestClientIPCID, aTrans);
+ }
+
+protected:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Functions
+
+ // Queue management
+
+ /**
+ * @returns the queue indexed by the ID passed in, which could be nsnull
+ */
+ tmQueue* GetQueue(PRUint32 aQueueID) {
+ return (tmQueue*) mQueues[aQueueID];
+ }
+
+ /**
+ * @returns the queue with the name passed in
+ * @returns nsnull if there is no queue with that name
+ */
+ tmQueue* GetQueue(const char *aQueueName);
+
+ /**
+ * If all is successful a new queue with the name provided will be created,
+ * and added to the collection of queues. It will be initialized and ready
+ * to have transactions added.
+ *
+ * This doesn't check for the existance of a queue with this name. IF
+ * there is already a queue with this name then you will
+ * get that when using GetQueue(qName) and never get the new queue
+ * created here. A call to GetQueue(qID) will be able to get at the new
+ * queue, however you had better cache the ID.
+ *
+ * @returns -1 if the queue can't be created, or is not added
+ * @returns >= 0 if the queue was added successfully
+ */
+ PRInt32 AddQueue(const char *aQueueType);
+
+ /**
+ */
+ void RemoveQueue(PRUint32 aQueueID);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Variables
+
+ tmVector mQueues;
+
+private:
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/Makefile.in
new file mode 100644
index 00000000..65b126e9
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/Makefile.in
@@ -0,0 +1,53 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+XPIDL_MODULE = ipcd_transmngr
+
+XPIDLSRCS = \
+ ipcITransactionService.idl \
+ ipcITransactionObserver.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionObserver.idl b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionObserver.idl
new file mode 100644
index 00000000..c7df965d
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionObserver.idl
@@ -0,0 +1,100 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 "nsISupports.idl"
+
+[scriptable, uuid(656c0a6a-5cb3-45ec-8cb6-e7678897f937)]
+interface ipcITransactionObserver : nsISupports
+{
+ /**
+ * This gets called when a Transaction has been sent from the
+ * TransactionManager. If the data passed in needs to be stored
+ * for longer than the life of the method the observer needs
+ * to make a copy.
+ *
+ * @param aQueueID
+ * The queue from which the transaction originated
+ *
+ * @param aData
+ * The data to be sent.
+ *
+ * @param aDataLen
+ * The length of the data argument
+ */
+ void onTransactionAvailable(in unsigned long aQueueID,
+ [array, const, size_is(aDataLen)]
+ in octet aData,
+ in unsigned long aDataLen);
+
+ /**
+ * Called after an application sends an Attach message to the
+ * Transaction Manager.
+ *
+ * @param aQueueID
+ * The client has been attached to the queue with this ID
+ *
+ * @param aStatus
+ * The status of the operation, as defined in tmUtils.h
+ */
+ void onAttachReply(in unsigned long aQueueID, in unsigned long aStatus);
+
+ /**
+ * Called after an application sends a Detach message. Indicates
+ * to the client that no more messages will be coming from the
+ * the TM to this client. Also, no messages posted from this
+ * client to the indicated queue will be accepted.
+ *
+ * @param aQueueID
+ * The client has been detached from the queue with this ID
+ *
+ * @param aStatus
+ * The status of the operation, as defined in tmUtils.h
+ */
+ void onDetachReply(in unsigned long aQueueID, in unsigned long aStatus);
+
+ /**
+ * The reply from the TM indicating all messages have been removed
+ * from the queue indicated.
+ *
+ * @param aQueueID
+ * The queue that has been flushed.
+ *
+ * @param aStatus
+ * The status of the operation, as defined in tmUtils.h
+ */
+ void onFlushReply(in unsigned long aQueueID, in unsigned long aStatus);
+};
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionService.idl b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionService.idl
new file mode 100644
index 00000000..0bcbc453
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/public/ipcITransactionService.idl
@@ -0,0 +1,239 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+// from tmTransactionManager.h
+//
+// XXX documentation needs work
+//////////////////////////////////////////////////////////////////////////////
+// Overview of TransactionManager IPC Module
+//
+// Classes:
+// tmIPCModule - From the tmTransactionManager's point of view, this
+// is a proxy for the IPC daemon itself. The reverse is true
+// from the daemon's point of view. This is an interface for the
+// Transaction system to work with the IPC daemon as its transport
+// layer.
+// tmTransactionManager (TM) - Manages the different queues. Maintains
+// the queues neccessary for different clients. Receives messages
+// from the tmIPCModule and passes message to the IPC daemon through
+// the tmIPCModule.
+// tmQueue - this class manages the transactions for the different areas
+// of the profiles being shared. Broken down by functional area there
+// will be a queue for prefs, cookies etc, but not for profileA and
+// profileB, and not for pref_delete, pref_create, pref_change etc...
+// tmTransaction - the actual transaction being shared with the different
+// tmClients. It contains the type of transaction, which will equate with
+// a type of queue in existance, the owner of the transaction (an IPC daemon ID)
+// and the actual text message to be shared.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+/// XXX some docs that need to be put somewhere:
+//
+// from tmqueue.cpp
+// Docs - note that the status of the TM_ATTACH_REPLY is only for checking
+// for TM_ERROR_FAILURE. Other numbers have no importance
+// success of the status means the NS_ERROR_GET_CODE(status) will
+// yield the index of the listener.
+//
+// move to documentation page - from tmqueue.h
+//
+// a queue is specific to profile
+//
+// UUID going out from the module is a handler in the client
+// (will go to the XPCOM service impling that UUID)
+// -- does it make sense to have different UUIDs for cookies/prefs/etc
+//
+
+#include "nsISupports.idl"
+
+interface ipcITransactionObserver;
+
+[scriptable, uuid(15561efb-8c58-4a47-813a-fa91cf730895)]
+interface ipcITransactionService : nsISupports
+{
+ /**
+ * Connects the application to the transaction manager, defines the
+ * namespace and initializes internal storage
+ *
+ * @param aNamespace
+ * A string defining the scope of the transaction domains. It is
+ * used internally to seperate process listening to the same domain
+ * (ie. preferences) but for two different namespaces (ie. profile1 vs
+ * profile2).
+ *
+ * @returns NS_OK if all memory allocated properly and the IPC service was
+ * reached and attached to successfully.
+ *
+ * @returns an NS_ERROR_<foo> code specific to the failure otherwise
+ */
+ void init(in ACString aNamespace);
+
+ /**
+ * Links the observer passed in with the domain specified. This will allow
+ * the observer to post transactions dealing with this domain as well as
+ * receive transactions posted by other applications observing this
+ * domain.
+ *
+ * Return codes for this method confer information about the success of
+ * this call, not of the actual attaching of the observer to the domain.
+ * (except the TM_ERROR code - which means the observer can not attach)
+ * If the attach is successful the observer will have its OnAttachReply
+ * method called before this method returns.
+ *
+ * Note: This call is synchronous and will not return until the call to
+ * OnAttachReply is made.
+ *
+ * @param aDomainName
+ * the name of the domain, in the current namespace, to listen for
+ * transactions from. i.e. cookies
+ *
+ * @param aObserver
+ * this will be used to notify the application when transactions
+ * and messages come in.
+ *
+ * @param aLockingCall
+ * Have the Transaction Sevice acquire a lock based on the domain
+ * before attaching. This should be used when persistant storage
+ * is being used to prevent data corruption.
+ *
+ * @returns NS_OK if the attach message was sent to the Transaction Manager.
+ *
+ * @returns an NS_ERROR_<foo> code specific to the failure otherwise
+ *
+ * @returns TM_ERROR_QUEUE_EXISTS if the queue already exists which means
+ * someone has already attached to it.
+ */
+ void attach(in ACString aDomainName,
+ in ipcITransactionObserver aObserver,
+ in PRBool aLockingCall);
+
+ /**
+ * Sends a detach message to the Transaction Manager to unlink the observer
+ * associated with the domain passed in.
+ *
+ * As in attach, return codes do not indicate success of detachment. The
+ * observer will have it's OnDetach method called if it is successfully
+ * detached.
+ *
+ * Note: This call is an asynchronous call.
+ *
+ * @param aDomainName
+ * the domain, in the current namespace, from which the client
+ * should be removed.
+ *
+ * @returns NS_OK if the detach message is sent to the Transaction Manager
+ *
+ * @returns NS_ERROR_FAILURE is something goes wrong
+ *
+ * @returns NS_ERRROR_UNEXPECTD if the domain does not have an observer
+ * attached
+ */
+ void detach(in ACString aDomainName);
+
+ /**
+ * Sends a flush message to the Transaction Manager to remove all
+ * transactions for the domain. After this call there will be no
+ * transactions in the Transaction Manager for the namespace/domain
+ * pairing. It is up to the application to coordinate the flushing
+ * of the Transaction Manager with the writing of data to files,
+ * if needed.
+ *
+ * Note: This call is synchronous and will not return until the call to
+ * OnFlushReply is made.
+ *
+ * @param aDomainName
+ * The domain, in the current namespace, to flush.
+ *
+ * @param aLockingCall
+ * Have the Transaction Sevice acquire a lock based on the domain
+ * before flushing. This should be used when persistant storage
+ * is being used to prevent data corruption.
+ *
+ * @returns NS_OK if the flush message is sent to the Transaction Manager
+ *
+ * @returns NS_ERROR_FAILURE is something goes wrong
+ *
+ * @returns NS_ERRROR_UNEXPECTD if the domain does not have an observer
+ * attached
+ */
+ void flush(in ACString aDomainName, in PRBool aLockingCall);
+
+ /**
+ * Send the data to the Transaction Manager to be broadcast to any
+ * applications that have registered as observers of this particular
+ * namespace/domain pairing.
+ *
+ * If this domain is not being observed (attach has not been called for
+ * this domain) the message is queued until the attach is made and then
+ * the message is sent to the Transaction Manager with the proper domain
+ * information.
+ *
+ * XXXjg - this may not be neccessary with the synch attach call.
+ *
+ * Note: This call is an asynchronous call.
+ *
+ * @param aDomainName
+ * the domain, in the current namespace, to which the data will be
+ * sent.
+ *
+ * @param aData
+ * The actual data to be sent.
+ *
+ * @param aDataLen
+ * The length of the data argument
+ */
+ void postTransaction(in ACString aDomainName,
+ [array, const, size_is(aDataLen)]
+ in octet aData,
+ in unsigned long aDataLen);
+};
+
+%{C++
+// singleton implementing ipcITransactionService
+#define IPC_TRANSACTIONSERVICE_CLASSNAME \
+ "tmTransactionService"
+#define IPC_TRANSACTIONSERVICE_CONTRACTID \
+ "@mozilla.org/ipc/transaction-service;1"
+#define IPC_TRANSACTIONSERVICE_CID \
+{ /* 1403adf4-94d1-4c67-a8ae-d9f86972d378 */ \
+ 0x1403adf4, \
+ 0x94d1, \
+ 0x4c67, \
+ {0xa8, 0xae, 0xd9, 0xf8, 0x69, 0x72, 0xd3, 0x78} \
+}
+%}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/.cvsignore
new file mode 100644
index 00000000..7726b497
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/.cvsignore
@@ -0,0 +1,4 @@
+Makefile
+tmTransactionService.obj
+transmgr_s.lib
+transmgr_s.pdb \ No newline at end of file
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/Makefile.in
new file mode 100644
index 00000000..6510e489
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/Makefile.in
@@ -0,0 +1,64 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = transmgr_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME = ipcd
+
+REQUIRES = string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ tmTransactionService.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../common \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.cpp
new file mode 100644
index 00000000..e53d6aa7
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.cpp
@@ -0,0 +1,504 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsReadableUtils.h"
+#include "plstr.h"
+#include "ipcITransactionObserver.h"
+#include "tmTransaction.h"
+#include "tmTransactionService.h"
+#include "tmUtils.h"
+
+static const nsID kTransModuleID = TRANSACTION_MODULE_ID;
+
+struct tm_waiting_msg {
+ tmTransaction trans; // a transaction waiting to be sent to a queue
+ char* domainName; // the short queue name
+
+ ~tm_waiting_msg();
+};
+
+tm_waiting_msg::~tm_waiting_msg() {
+ if (domainName)
+ PL_strfree(domainName);
+}
+
+struct tm_queue_mapping {
+ PRInt32 queueID; // the ID in the TM
+ char* domainName; // used by the consumers of this service
+ char* joinedQueueName; // used by the service -- namespace + domain name
+
+ ~tm_queue_mapping();
+};
+
+tm_queue_mapping::~tm_queue_mapping() {
+ if (domainName)
+ PL_strfree(domainName);
+ if (joinedQueueName)
+ PL_strfree(joinedQueueName);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Constructor and Destructor
+
+tmTransactionService::~tmTransactionService() {
+
+ // just destroy this, it contains 2 pointers it doesn't own.
+ if (mObservers)
+ PL_HashTableDestroy(mObservers);
+
+ PRUint32 index = 0;
+ PRUint32 size = mWaitingMessages.Size();
+ tm_waiting_msg *msg = nsnull;
+ for ( ; index < size; index ++) {
+ msg = (tm_waiting_msg*) mWaitingMessages[index];
+ delete msg;
+ }
+
+ size = mQueueMaps.Size();
+ tm_queue_mapping *qmap = nsnull;
+ for (index = 0; index < size; index++) {
+ qmap = (tm_queue_mapping*) mQueueMaps[index];
+ if (qmap)
+ delete qmap;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ISupports
+
+NS_IMPL_ISUPPORTS2(tmTransactionService,
+ ipcITransactionService,
+ ipcIMessageObserver)
+
+//////////////////////////////////////////////////////////////////////////////
+// ipcITransactionService
+
+NS_IMETHODIMP
+tmTransactionService::Init(const nsACString & aNamespace) {
+
+ nsresult rv;
+
+ rv = IPC_DefineTarget(kTransModuleID, this, PR_TRUE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the lock service
+ lockService = do_GetService("@mozilla.org/ipc/lock-service;1");
+ if (!lockService)
+ return NS_ERROR_FAILURE;
+
+ // create some internal storage
+ mObservers = PL_NewHashTable(20,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues, 0, 0);
+ if (!mObservers)
+ return NS_ERROR_FAILURE;
+
+ // init some internal storage
+ mQueueMaps.Init();
+ mWaitingMessages.Init();
+
+ // store the namespace
+ mNamespace.Assign(aNamespace);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+tmTransactionService::Attach(const nsACString & aDomainName,
+ ipcITransactionObserver *aObserver,
+ PRBool aLockingCall) {
+
+ // if the queue already exists, then someone else is attached to it. must
+ // return an error here. Only one module attached to a queue per app.
+ if (GetQueueID(aDomainName) != TM_NO_ID)
+ return TM_ERROR_QUEUE_EXISTS;
+
+ // create the full queue name: namespace + queue
+ nsCString jQName;
+ jQName.Assign(mNamespace);
+ jQName.Append(aDomainName);
+
+ // this char* has two homes, make sure it gets PL_free()ed properly
+ char* joinedQueueName = ToNewCString(jQName);
+ if (!joinedQueueName)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // link the observer to the joinedqueuename. home #1 for joinedQueueName
+ // these currently don't get removed until the destructor on this is called.
+ PL_HashTableAdd(mObservers, joinedQueueName, aObserver);
+
+ // store the domainName and JoinedQueueName, create a place to store the ID
+ tm_queue_mapping *qm = new tm_queue_mapping();
+ if (!qm)
+ return NS_ERROR_OUT_OF_MEMORY;
+ qm->queueID = TM_NO_ID; // initially no ID for the queue
+ qm->joinedQueueName = joinedQueueName; // home #2, owner of joinedQueueName
+ qm->domainName = ToNewCString(aDomainName);
+ if (!qm->domainName) {
+ PL_HashTableRemove(mObservers, joinedQueueName);
+ delete qm;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mQueueMaps.Append(qm);
+
+ nsresult rv = NS_ERROR_FAILURE;
+ tmTransaction trans;
+
+ // acquire a lock if neccessary
+ if (aLockingCall)
+ lockService->AcquireLock(joinedQueueName, PR_TRUE);
+ // XXX need to handle lock failures
+
+ if (NS_SUCCEEDED(trans.Init(0, // no IPC client
+ TM_NO_ID, // qID gets returned to us
+ TM_ATTACH, // action
+ NS_OK, // default status
+ (PRUint8 *)joinedQueueName, // qName gets copied
+ PL_strlen(joinedQueueName)+1))) { // message length
+ // send the attach msg
+ SendMessage(&trans, PR_TRUE); // synchronous
+ rv = NS_OK;
+ }
+
+ // drop the lock if neccessary
+ if (aLockingCall)
+ lockService->ReleaseLock(joinedQueueName);
+
+ return rv;
+}
+
+// actual removal of the observer takes place when we get the detach reply
+NS_IMETHODIMP
+tmTransactionService::Detach(const nsACString & aDomainName) {
+
+ // asynchronous detach
+ return SendDetachOrFlush(GetQueueID(aDomainName), TM_DETACH, PR_FALSE);
+
+}
+
+NS_IMETHODIMP
+tmTransactionService::Flush(const nsACString & aDomainName,
+ PRBool aLockingCall) {
+ // acquire a lock if neccessary
+ if (aLockingCall)
+ lockService->AcquireLock(GetJoinedQueueName(aDomainName), PR_TRUE);
+
+ // synchronous flush
+ nsresult rv = SendDetachOrFlush(GetQueueID(aDomainName), TM_FLUSH, PR_TRUE);
+
+ // drop the lock if neccessary
+ if (aLockingCall)
+ lockService->ReleaseLock(GetJoinedQueueName(aDomainName));
+
+ return rv;
+
+}
+
+NS_IMETHODIMP
+tmTransactionService::PostTransaction(const nsACString & aDomainName,
+ const PRUint8 *aData,
+ PRUint32 aDataLen) {
+
+ tmTransaction trans;
+ if (NS_SUCCEEDED(trans.Init(0, // no IPC client
+ GetQueueID(aDomainName), // qID returned to us
+ TM_POST, // action
+ NS_OK, // default status
+ aData, // message data
+ aDataLen))) { // message length
+ if (trans.GetQueueID() == TM_NO_ID) {
+ // stack it and pack it
+ tm_waiting_msg *msg = new tm_waiting_msg();
+ if (!msg)
+ return NS_ERROR_OUT_OF_MEMORY;
+ msg->trans = trans;
+ msg->domainName = ToNewCString(aDomainName);
+ if (!msg->domainName) {
+ delete msg;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mWaitingMessages.Append(msg);
+ }
+ else {
+ // send it
+ SendMessage(&trans, PR_FALSE);
+ }
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// ipcIMessageObserver
+
+NS_IMETHODIMP
+tmTransactionService::OnMessageAvailable(const PRUint32 aSenderID,
+ const nsID & aTarget,
+ const PRUint8 *aData,
+ PRUint32 aDataLength) {
+
+ nsresult rv = NS_ERROR_OUT_OF_MEMORY; // prime the return value
+
+ tmTransaction *trans = new tmTransaction();
+ if (trans) {
+ rv = trans->Init(0, // no IPC client ID
+ TM_INVALID_ID, // in aData
+ TM_INVALID_ID, // in aData
+ TM_INVALID_ID, // in aData
+ aData, // message data
+ aDataLength); // message length
+
+ if (NS_SUCCEEDED(rv)) {
+ switch(trans->GetAction()) {
+ case TM_ATTACH_REPLY:
+ OnAttachReply(trans);
+ break;
+ case TM_POST_REPLY:
+ // OnPostReply() would be called here
+ // isn't neccessary at the current time 2/19/03
+ break;
+ case TM_DETACH_REPLY:
+ OnDetachReply(trans);
+ break;
+ case TM_FLUSH_REPLY:
+ OnFlushReply(trans);
+ break;
+ case TM_POST:
+ OnPost(trans);
+ break;
+ default: // error, should not happen
+ NS_NOTREACHED("Recieved a TM reply outside of mapped messages");
+ break;
+ }
+ }
+ delete trans;
+ }
+ return rv;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Protected Member Functions
+
+void
+tmTransactionService::SendMessage(tmTransaction *aTrans, PRBool aSync) {
+
+ NS_ASSERTION(aTrans, "tmTransactionService::SendMessage called with null transaction");
+
+ IPC_SendMessage(0, kTransModuleID,
+ aTrans->GetRawMessage(),
+ aTrans->GetRawMessageLength());
+ if (aSync)
+ IPC_WaitMessage(0, kTransModuleID, nsnull, nsnull, PR_INTERVAL_NO_TIMEOUT);
+}
+
+void
+tmTransactionService::OnAttachReply(tmTransaction *aTrans) {
+
+ // if we attached, store the queue's ID
+ if (aTrans->GetStatus() >= 0) {
+
+ PRUint32 size = mQueueMaps.Size();
+ tm_queue_mapping *qmap = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ qmap = (tm_queue_mapping*) mQueueMaps[index];
+ if (qmap &&
+ PL_strcmp(qmap->joinedQueueName, (char*) aTrans->GetMessage()) == 0) {
+
+ // set the ID in the mapping
+ qmap->queueID = aTrans->GetQueueID();
+ // send any stored messges to the queue
+ DispatchStoredMessages(qmap);
+ }
+ }
+ }
+
+ // notify the observer we have attached (or didn't)
+ ipcITransactionObserver *observer =
+ (ipcITransactionObserver *)PL_HashTableLookup(mObservers,
+ (char*)aTrans->GetMessage());
+ if (observer)
+ observer->OnAttachReply(aTrans->GetQueueID(), aTrans->GetStatus());
+}
+
+void
+tmTransactionService::OnDetachReply(tmTransaction *aTrans) {
+
+ tm_queue_mapping *qmap = GetQueueMap(aTrans->GetQueueID());
+
+ // get the observer before we release the hashtable entry
+ ipcITransactionObserver *observer =
+ (ipcITransactionObserver *)PL_HashTableLookup(mObservers,
+ qmap->joinedQueueName);
+
+ // if it was removed, clean up
+ if (aTrans->GetStatus() >= 0) {
+
+ // remove the link between observer and queue
+ PL_HashTableRemove(mObservers, qmap->joinedQueueName);
+
+ // remove the mapping of queue names and id
+ mQueueMaps.Remove(qmap);
+ delete qmap;
+ }
+
+
+ // notify the observer -- could be didn't detach
+ if (observer)
+ observer->OnDetachReply(aTrans->GetQueueID(), aTrans->GetStatus());
+}
+
+void
+tmTransactionService::OnFlushReply(tmTransaction *aTrans) {
+
+ ipcITransactionObserver *observer =
+ (ipcITransactionObserver *)PL_HashTableLookup(mObservers,
+ GetJoinedQueueName(aTrans->GetQueueID()));
+ if (observer)
+ observer->OnFlushReply(aTrans->GetQueueID(), aTrans->GetStatus());
+}
+
+void
+tmTransactionService::OnPost(tmTransaction *aTrans) {
+
+ ipcITransactionObserver *observer =
+ (ipcITransactionObserver*) PL_HashTableLookup(mObservers,
+ GetJoinedQueueName(aTrans->GetQueueID()));
+ if (observer)
+ observer->OnTransactionAvailable(aTrans->GetQueueID(),
+ aTrans->GetMessage(),
+ aTrans->GetMessageLength());
+}
+
+void
+tmTransactionService::DispatchStoredMessages(tm_queue_mapping *aQMapping) {
+
+ PRUint32 size = mWaitingMessages.Size();
+ tm_waiting_msg *msg = nsnull;
+ for (PRUint32 index = 0; index < size; index ++) {
+ msg = (tm_waiting_msg*) mWaitingMessages[index];
+ // if the message is waiting on the queue passed in
+ if (msg && strcmp(aQMapping->domainName, msg->domainName) == 0) {
+
+ // found a match, send it and remove
+ msg->trans.SetQueueID(aQMapping->queueID);
+ SendMessage(&(msg->trans), PR_FALSE);
+
+ // clean up
+ mWaitingMessages.Remove(msg);
+ delete msg;
+ }
+ }
+}
+
+// searches against the short queue name
+PRInt32
+tmTransactionService::GetQueueID(const nsACString & aDomainName) {
+
+ PRUint32 size = mQueueMaps.Size();
+ tm_queue_mapping *qmap = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ qmap = (tm_queue_mapping*) mQueueMaps[index];
+ if (qmap && aDomainName.Equals(qmap->domainName))
+ return qmap->queueID;
+ }
+ return TM_NO_ID;
+}
+
+char*
+tmTransactionService::GetJoinedQueueName(PRUint32 aQueueID) {
+
+ PRUint32 size = mQueueMaps.Size();
+ tm_queue_mapping *qmap = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ qmap = (tm_queue_mapping*) mQueueMaps[index];
+ if (qmap && qmap->queueID == aQueueID)
+ return qmap->joinedQueueName;
+ }
+ return nsnull;
+}
+
+char*
+tmTransactionService::GetJoinedQueueName(const nsACString & aDomainName) {
+
+ PRUint32 size = mQueueMaps.Size();
+ tm_queue_mapping *qmap = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ qmap = (tm_queue_mapping*) mQueueMaps[index];
+ if (qmap && aDomainName.Equals(qmap->domainName))
+ return qmap->joinedQueueName;
+ }
+ return nsnull;
+}
+
+tm_queue_mapping*
+tmTransactionService::GetQueueMap(PRUint32 aQueueID) {
+
+ PRUint32 size = mQueueMaps.Size();
+ tm_queue_mapping *qmap = nsnull;
+ for (PRUint32 index = 0; index < size; index++) {
+ qmap = (tm_queue_mapping*) mQueueMaps[index];
+ if (qmap && qmap->queueID == aQueueID)
+ return qmap;
+ }
+ return nsnull;
+}
+
+nsresult
+tmTransactionService::SendDetachOrFlush(PRUint32 aQueueID,
+ PRUint32 aAction,
+ PRBool aSync) {
+
+ // if the queue isn't attached to, just return
+ if (aQueueID == TM_NO_ID)
+ return NS_ERROR_UNEXPECTED;
+
+ tmTransaction trans;
+ if (NS_SUCCEEDED(trans.Init(0, // no IPC client
+ aQueueID, // qID to detach from
+ aAction, // action
+ NS_OK, // default status
+ nsnull, // no message
+ 0))) { // no message
+ // send it
+ SendMessage(&trans, aSync);
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.h b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.h
new file mode 100644
index 00000000..cd9310fe
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/src/tmTransactionService.h
@@ -0,0 +1,196 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+#ifndef _tmTransactionService_H_
+#define _tmTransactionService_H_
+
+#include "ipcdclient.h"
+#include "ipcILockService.h"
+#include "ipcIMessageObserver.h"
+#include "ipcITransactionService.h"
+#include "nsString.h"
+#include "nsVoidArray.h"
+#include "plhash.h"
+#include "tmTransaction.h"
+#include "tmVector.h"
+
+struct tm_queue_mapping;
+
+/**
+ * The tmTransactionService shares packets of information
+ * (transactions) with other Gecko based applications interested in the same
+ * namespace and domain. An application registers with the Transaction Service
+ * for a particular namespace and domain and then can post transactions to the
+ * service and receive transactions from the service.
+ *
+ * For applications using the Transaction Service to share changes in state that
+ * get reflected in files on disk there are certain pattersn to follow to ensure
+ * data loss does not occur.
+ *
+ * Startup: XXX docs needed
+ *
+ * Shutdown/writing to disk: XXX docs needed
+ *
+ *
+ */
+class tmTransactionService : public ipcITransactionService,
+ public ipcIMessageObserver
+{
+
+public:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Constructor & Destructor
+ tmTransactionService() : mObservers(0) {};
+
+ /**
+ * Reclaim all the memory allocated: PL_hashtable, tmVectors
+ */
+ virtual ~tmTransactionService();
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Interface Declarations
+
+ // for API docs, see the respective *.idl files
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCITRANSACTIONSERVICE
+ NS_DECL_IPCIMESSAGEOBSERVER
+
+protected:
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Functions
+
+ /**
+ * Pulls the raw message out of the transaction and sends it to the IPC
+ * service to be delivered to the TM.
+ *
+ * @param aTrans
+ * The transaction to send to the TM
+ *
+ * @param aSync
+ * If TRUE, calling thread will be blocked until a reply is
+ * received.
+ */
+ void SendMessage(tmTransaction *aTrans, PRBool aSync);
+
+ // handlers for reply messages from TransactionManager
+
+ /**
+ * Pulls the queueID out of the ATTACH_REPLY message and stores it in the
+ * proper tm_queue_mapping object. Calls DispatchStoredMessages() to make
+ * sure we send any messages that have been waiting on the ATTACH_REPLY.
+ * Also calls the OnAttachReply() method for the observer of the queue.
+ */
+ void OnAttachReply(tmTransaction *aTrans);
+
+ /**
+ * Removes the tm_queue_mapping object and calls the OnDetachReply() method
+ * on the observer of the queue detached.
+ */
+ void OnDetachReply(tmTransaction *aTrans);
+
+ /**
+ * Calls the OnFlushReply method of the observer of the queue.
+ */
+ void OnFlushReply(tmTransaction *aTrans);
+
+ /**
+ * Calls the OnPost method of the observer of the queue.
+ */
+ void OnPost(tmTransaction *aTrans);
+
+ // other helper functions
+
+ /**
+ * Cycle through the collection of transactions waiting to go out and
+ * send any that are waiting on an ATTACH_REPLY from the queue
+ * specified by the tm_queue_mapping passed in.
+ */
+ void DispatchStoredMessages(tm_queue_mapping *aQMapping);
+
+ // helper methods for accessing the void arrays
+
+ /**
+ * @returns the ID corresponding to the domain name passed in
+ * @returns TM_NO_ID if the name is not found.
+ */
+ PRInt32 GetQueueID(const nsACString & aDomainName);
+
+ /**
+ * @returns the joined queue name - namespace + domain
+ * (prefs, cookies etc) corresponding to the ID passed in.
+ * @returns nsnull if the ID is not found.
+ */
+ char* GetJoinedQueueName(PRUint32 aQueueID);
+
+ /**
+ * @returns the joined queue name - namespace + domain
+ * (prefs, cookies etc) corresponding to the ID passed in.
+ * @returns nsnull if the ID is not found.
+ */
+ char* GetJoinedQueueName(const nsACString & aDomainName);
+
+ /**
+ * @returns the tm_queue_mapping object that contains the ID passed in.
+ * @returns nsnull if the ID is not found.
+ */
+ tm_queue_mapping* GetQueueMap(PRUint32 aQueueID);
+
+ /**
+ * Helper method for Detach and Flush requests.
+ */
+ nsresult SendDetachOrFlush(PRUint32 aQueueID,
+ PRUint32 aAction,
+ PRBool aSync);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Protected Member Variables
+
+ nsCString mNamespace; // limit domains to the namespace
+ PLHashTable *mObservers; // maps qName -> ipcITransactionObserver
+
+ tmVector mQueueMaps; // queue - name - domain mappings
+ tmVector mWaitingMessages; // messages sent before ATTACH_REPLY
+
+ nsCOMPtr<ipcILockService> lockService; // cache the lock service
+
+private:
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/.cvsignore
new file mode 100644
index 00000000..e3c610be
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+tmModuleTest.exe
+tmModuleTest.ilk
+tmModuleTest.pdb
+tmModuleTest.obj
+tmModuleTest
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/Makefile.in
new file mode 100644
index 00000000..385751a3
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/Makefile.in
@@ -0,0 +1,68 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Transaction Manager.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corp.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# John Gaunt <jgaunt@netscape.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 *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = tm_test
+
+REQUIRES = ipcd \
+ nspr \
+ string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ tmModuleTest.cpp \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(EXTRA_DSO_LIBS) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp
new file mode 100644
index 00000000..5d1dccd4
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/extensions/transmngr/test/tmModuleTest.cpp
@@ -0,0 +1,323 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Transaction Manager.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Gaunt <jgaunt@netscape.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 ***** */
+
+// transaction manager includes
+#include "ipcITransactionService.h"
+#include "ipcITransactionObserver.h"
+
+// ipc daemon includes
+#include "ipcIService.h"
+
+// core & xpcom ns includes
+#include "nsDebug.h"
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsString.h"
+
+// nspr includes
+#include "prmem.h"
+#include "plgetopt.h"
+#include "nspr.h"
+#include "prlog.h"
+
+//////////////////////////////////////////////////////////////////////////////
+// Testing/Debug/Logging BEGIN
+
+const int NameSize = 1024;
+
+/* command line options */
+PRIntn optDebug = 0;
+char optMode = 's';
+char *profileName = new char[NameSize];
+char *queueName = new char[NameSize];
+
+char *data = new char[NameSize];
+PRUint32 dataLen = 10; // includes the null terminator for "test data"
+
+// Testing/Debug/Logging END
+//////////////////////////////////////////////////////////////////////////////
+
+#define RETURN_IF_FAILED(rv, step) \
+ PR_BEGIN_MACRO \
+ if (NS_FAILED(rv)) { \
+ printf("*** %s failed: rv=%x\n", step, rv); \
+ return rv;\
+ } \
+ PR_END_MACRO
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+static nsIEventQueue* gEventQ = nsnull;
+static PRBool gKeepRunning = PR_TRUE;
+//static PRInt32 gMsgCount = 0;
+static ipcIService *gIpcServ = nsnull;
+static ipcITransactionService *gTransServ = nsnull;
+
+//-----------------------------------------------------------------------------
+
+class myTransactionObserver : public ipcITransactionObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCITRANSACTIONOBSERVER
+
+ myTransactionObserver() { }
+};
+
+NS_IMPL_ISUPPORTS1(myTransactionObserver, ipcITransactionObserver)
+
+NS_IMETHODIMP myTransactionObserver::OnTransactionAvailable(PRUint32 aQueueID, const PRUint8 *aData, PRUint32 aDataLen)
+{
+ printf("tmModuleTest: myTransactionObserver::OnTransactionAvailable [%s]\n", aData);
+ return NS_OK;
+}
+
+NS_IMETHODIMP myTransactionObserver::OnAttachReply(PRUint32 aQueueID, PRUint32 aStatus)
+{
+ printf("tmModuleTest: myTransactionObserver::OnAttachReply [%d]\n", aStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP myTransactionObserver::OnDetachReply(PRUint32 aQueueID, PRUint32 aStatus)
+{
+ printf("tmModuleTest: myTransactionObserver::OnDetachReply [%d]\n", aStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP myTransactionObserver::OnFlushReply(PRUint32 aQueueID, PRUint32 aStatus)
+{
+ printf("tmModuleTest: myTransactionObserver::OnFlushReply [%d]\n", aStatus);
+ return NS_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+
+int main(PRInt32 argc, char *argv[])
+{
+ nsresult rv;
+
+ // default string values
+ strcpy(profileName, "defaultProfile");
+ strcpy(queueName, "defaultQueue");
+ strcpy(data, "test data");
+
+ { // scope the command line option gathering (needed for some reason)
+
+ // Get command line options
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "bdfhlp:q:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'b': /* broadcast a bunch of messages */
+ printf("tmModuleTest: broadcaster\n");
+ optMode = 'b';
+ break;
+ case 'd': /* debug mode */
+ printf("tmModuleTest: debugging baby\n");
+ optDebug = 1;
+ break;
+ case 'f': /* broadcast and flush */
+ printf("tmModuleTest: flusher\n");
+ optMode = 'f';
+ break;
+ case 'h': /* broadcast and detach */
+ printf("tmModuleTest: hit-n-run\n");
+ optMode = 'h';
+ break;
+ case 'l': /* don't broadcast, just listen */
+ printf("tmModuleTest: listener\n");
+ optMode = 'l';
+ break;
+ case 'p': /* set the profile name */
+ strcpy(profileName, opt->value);
+ printf("tmModuleTest: profilename:%s\n",profileName);
+ break;
+ case 'q': /* set the queue name */
+ strcpy(queueName, opt->value);
+ printf("tmModuleTest: queuename:%s\n",queueName);
+ break;
+ default:
+ printf("tmModuleTest: default\n");
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ } // scope the command line option gathering (needed for some reason)
+
+ { // scope the nsCOMPtrs
+
+ printf("tmModuleTest: Starting xpcom\n");
+
+ // xpcom startup stuff
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->AutoRegister(nsnull);
+
+ // Create the Event Queue for this thread...
+ nsCOMPtr<nsIEventQueueService> eqs = do_GetService(kEventQueueServiceCID, &rv);
+ RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)");
+
+ rv = eqs->CreateMonitoredThreadEventQueue();
+ RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue");
+
+ rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
+ RETURN_IF_FAILED(rv, "GetThreadEventQueue");
+
+ // Need to make sure the ipc system has been started
+ printf("tmModuleTest: getting ipc service\n");
+ nsCOMPtr<ipcIService> ipcServ(do_GetService("@mozilla.org/ipc/service;1", &rv));
+ RETURN_IF_FAILED(rv, "do_GetService(ipcServ)");
+ NS_ADDREF(gIpcServ = ipcServ);
+
+ // Get the transaction service
+ printf("tmModuleTest: getting transaction service\n");
+ nsCOMPtr<ipcITransactionService> transServ(do_GetService("@mozilla.org/ipc/transaction-service;1", &rv));
+ RETURN_IF_FAILED(rv, "do_GetService(transServ)");
+ NS_ADDREF(gTransServ = transServ);
+
+ // transaction specifc startup stuff, done for all cases
+
+ nsCOMPtr<ipcITransactionObserver> observ = new myTransactionObserver();
+
+ // initialize the transaction service with a specific profile
+ gTransServ->Init(nsDependentCString(profileName));
+ printf("tmModuleTest: using profileName [%s]\n", profileName);
+
+ // attach to the queue in the transaction manager
+ gTransServ->Attach(nsDependentCString(queueName), observ, PR_TRUE);
+ printf("tmModuleTest: observing queue [%s]\n", queueName);
+
+
+ // run specific patterns based on the mode
+ int i = 0; // wasn't working inside the cases
+ switch (optMode)
+ {
+ case 's':
+ printf("tmModuleTest: start standard\n");
+ // post a couple events
+ for (; i < 5 ; i++) {
+ gTransServ->PostTransaction(nsDependentCString(queueName), (PRUint8 *)data, dataLen);
+ }
+ // listen for events
+ while (gKeepRunning)
+ gEventQ->ProcessPendingEvents();
+ printf("tmModuleTest: end standard\n");
+ break;
+ case 'b':
+ printf("tmModuleTest: start broadcast\n");
+ // post a BUNCH of messages
+ for (; i < 50; i++) {
+ gTransServ->PostTransaction(nsDependentCString(queueName), (PRUint8 *)data, dataLen);
+ }
+ // listen for events
+ while (gKeepRunning)
+ gEventQ->ProcessPendingEvents();
+ printf("tmModuleTest: end broadcast\n");
+ break;
+ case 'f':
+ printf("tmModuleTest: start flush\n");
+ // post a couple events
+ for (; i < 5; i++) {
+ gTransServ->PostTransaction(nsDependentCString(queueName), (PRUint8 *)data, dataLen);
+ }
+ // flush the queue
+ gTransServ->Flush(nsDependentCString(queueName), PR_TRUE);
+ // post a couple events
+ for (i=0; i < 8; i++) {
+ gTransServ->PostTransaction(nsDependentCString(queueName), (PRUint8 *)data, dataLen);
+ }
+ // listen for events
+ while (gKeepRunning)
+ gEventQ->ProcessPendingEvents();
+ // detach
+ gTransServ->Detach(nsDependentCString(queueName));
+ printf("tmModuleTest: end flush\n");
+ break;
+ case 'h':
+ printf("tmModuleTest: start hit-n-run\n");
+ // post a couple events
+ for (; i < 5; i++) {
+ gTransServ->PostTransaction(nsDependentCString(queueName), (PRUint8 *)data, dataLen);
+ }
+ // detach
+ gTransServ->Detach(nsDependentCString(queueName));
+ printf("tmModuleTest: end hit-n-run\n");
+ break;
+ case 'l':
+ printf("tmModuleTest: start listener\n");
+ // listen for events
+ while (gKeepRunning)
+ gEventQ->ProcessPendingEvents();
+ printf("tmModuleTest: end listener\n");
+ break;
+ default :
+ printf("tmModuleTest: start & end default\n");
+ break;
+ }
+
+ // shutdown process
+
+ NS_RELEASE(gTransServ);
+ NS_RELEASE(gIpcServ);
+
+ printf("tmModuleTest: processing remaining events\n");
+
+ // process any remaining events
+ PLEvent *ev;
+ while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev)
+ gEventQ->HandleEvent(ev);
+
+ printf("tmModuleTest: done\n");
+ } // this scopes the nsCOMPtrs
+
+ // helps with shutdown on some cases
+ PR_Sleep(PR_SecondsToInterval(4));
+
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/ipc.pkg b/src/libs/xpcom18a4/ipc/ipcd/ipc.pkg
new file mode 100644
index 00000000..a2171122
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/ipc.pkg
@@ -0,0 +1,21 @@
+[gecko]
+dist/bin/mozipcd@BINS@
+#if OS_ARCH==OS2
+dist/bin/ipc/modules/@DLLP@lockmod@DLLS@
+#else
+dist/bin/ipc/modules/@DLLP@lockmodule@DLLS@
+#endif
+dist/bin/ipc/modules/@DLLP@transmgr@DLLS@
+dist/bin/components/@DLLP@ipcdc@DLLS@
+!xpt dist/bin/components/ipcd.xpt
+
+#if ENABLE_TESTS
+[gecko-tests]
+dist/bin/TestIPC@BINS@
+dist/bin/tmModuleTest@BINS@
+#if USE_SHORT_LIBNAME
+dist/bin/ipc/modules/@DLLP@testmod@DLLS@
+#else
+dist/bin/ipc/modules/@DLLP@testmodule@DLLS@
+#endif
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/shared/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/shared/src/Makefile.in
new file mode 100644
index 00000000..ffcaa10c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/Makefile.in
@@ -0,0 +1,65 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = ipcdshared_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME = ipcd
+
+# required for #include "nsID.h"
+REQUIRES = \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ ipcLog.cpp \
+ ipcConfig.cpp \
+ ipcMessage.cpp \
+ ipcMessagePrimitives.cpp \
+ ipcStringList.cpp \
+ ipcIDList.cpp \
+ ipcm.cpp
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.cpp
new file mode 100644
index 00000000..5f829626
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.cpp
@@ -0,0 +1,104 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#if defined(XP_WIN)
+#elif defined(XP_OS2) && defined(XP_OS2_NATIVEIPC)
+#else
+#include <string.h>
+#ifdef XP_UNIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#endif
+#include "ipcConfig.h"
+#include "ipcLog.h"
+#include "prenv.h"
+#include "plstr.h"
+
+#if defined(XP_OS2) && !defined(XP_OS2_NATIVEIPC)
+#ifdef VBOX
+static const char kDefaultSocketPrefix[] = "\\socket\\vbox-";
+#else
+static const char kDefaultSocketPrefix[] = "\\socket\\mozilla-";
+#endif
+static const char kDefaultSocketSuffix[] = "-ipc\\ipcd";
+#else
+#ifdef VBOX
+static const char kDefaultSocketPrefix[] = "/tmp/.vbox-";
+#else
+static const char kDefaultSocketPrefix[] = "/tmp/.mozilla-";
+#endif
+static const char kDefaultSocketSuffix[] = "-ipc/ipcd";
+#endif
+
+void IPC_GetDefaultSocketPath(char *buf, PRUint32 bufLen)
+{
+ const char *logName;
+ int len;
+
+ PL_strncpyz(buf, kDefaultSocketPrefix, bufLen);
+ buf += (sizeof(kDefaultSocketPrefix) - 1);
+ bufLen -= (sizeof(kDefaultSocketPrefix) - 1);
+
+ logName = PR_GetEnv("VBOX_IPC_SOCKETID");
+#if defined(VBOX) && defined(XP_UNIX)
+ if (!logName || !logName[0]) {
+ struct passwd *passStruct = getpwuid(getuid());
+ if (passStruct)
+ logName = passStruct->pw_name;
+ }
+#endif
+ if (!logName || !logName[0]) {
+ logName = PR_GetEnv("LOGNAME");
+ if (!logName || !logName[0]) {
+ logName = PR_GetEnv("USER");
+ if (!logName || !logName[0]) {
+ LOG(("could not determine username from environment\n"));
+ goto end;
+ }
+ }
+ }
+ PL_strncpyz(buf, logName, bufLen);
+ len = strlen(logName);
+ buf += len;
+ bufLen -= len;
+
+end:
+ PL_strncpyz(buf, kDefaultSocketSuffix, bufLen);
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.h
new file mode 100644
index 00000000..ab8b10e5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcConfig.h
@@ -0,0 +1,98 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcProto_h__
+#define ipcProto_h__
+
+#if defined(XP_WIN)
+//
+// use WM_COPYDATA messages
+//
+#include "prprf.h"
+
+#define IPC_WINDOW_CLASS "Mozilla:IPCWindowClass"
+#define IPC_WINDOW_NAME "Mozilla:IPCWindow"
+#define IPC_CLIENT_WINDOW_CLASS "Mozilla:IPCAppWindowClass"
+#define IPC_CLIENT_WINDOW_NAME_PREFIX "Mozilla:IPCAppWindow:"
+#define IPC_SYNC_EVENT_NAME "Local\\MozillaIPCSyncEvent"
+#ifndef IPC_DAEMON_APP_NAME
+#define IPC_DAEMON_APP_NAME "mozilla-ipcd.exe"
+#endif
+#define IPC_PATH_SEP_CHAR '\\'
+#define IPC_MODULES_DIR "ipc\\modules"
+
+#define IPC_CLIENT_WINDOW_NAME_MAXLEN (sizeof(IPC_CLIENT_WINDOW_NAME_PREFIX) + 20)
+
+// writes client name into buf. buf must be at least
+// IPC_CLIENT_WINDOW_NAME_MAXLEN bytes in length.
+inline void IPC_GetClientWindowName(PRUint32 pid, char *buf)
+{
+ PR_snprintf(buf, IPC_CLIENT_WINDOW_NAME_MAXLEN, "%s%u",
+ IPC_CLIENT_WINDOW_NAME_PREFIX, pid);
+}
+
+#else
+#include "nscore.h"
+//
+// use UNIX domain socket
+//
+#define IPC_PORT 0
+#define IPC_SOCKET_TYPE "ipc"
+#if defined(XP_OS2)
+#ifndef IPC_DAEMON_APP_NAME
+#define IPC_DAEMON_APP_NAME "mozilla-ipcd.exe"
+#endif
+#define IPC_PATH_SEP_CHAR '\\'
+#define IPC_MODULES_DIR "ipc\\modules"
+#else
+#ifndef IPC_DAEMON_APP_NAME
+#define IPC_DAEMON_APP_NAME "mozilla-ipcd"
+#endif
+#define IPC_PATH_SEP_CHAR '/'
+#define IPC_MODULES_DIR "ipc/modules"
+#endif
+
+NS_HIDDEN_(void) IPC_GetDefaultSocketPath(char *buf, PRUint32 bufLen);
+
+#endif
+
+// common shared configuration values
+
+#define IPC_STARTUP_PIPE_NAME "ipc:startup-pipe"
+#define IPC_STARTUP_PIPE_MAGIC 0x1C
+
+#endif // !ipcProto_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.cpp
new file mode 100644
index 00000000..0f64a3a0
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.cpp
@@ -0,0 +1,62 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "ipcIDList.h"
+
+ipcIDNode *
+ipcIDList::FindNode(ipcIDNode *node, const nsID &id)
+{
+ while (node) {
+ if (node->Equals(id))
+ return node;
+ node = node->mNext;
+ }
+ return NULL;
+}
+
+ipcIDNode *
+ipcIDList::FindNodeBefore(ipcIDNode *node, const nsID &id)
+{
+ ipcIDNode *prev = NULL;
+ while (node) {
+ if (node->Equals(id))
+ return prev;
+ prev = node;
+ node = node->mNext;
+ }
+ return NULL;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.h
new file mode 100644
index 00000000..b4fd1512
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcIDList.h
@@ -0,0 +1,108 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcIDList_h__
+#define ipcIDList_h__
+
+#include "nsID.h"
+#include "ipcList.h"
+
+//-----------------------------------------------------------------------------
+// nsID node
+//-----------------------------------------------------------------------------
+
+class ipcIDNode
+{
+public:
+ ipcIDNode(const nsID &id)
+ : mID(id)
+ { }
+
+ const nsID &Value() const { return mID; }
+
+ PRBool Equals(const nsID &id) const { return mID.Equals(id); }
+
+ class ipcIDNode *mNext;
+private:
+ nsID mID;
+};
+
+//-----------------------------------------------------------------------------
+// singly-linked list of nsIDs
+//-----------------------------------------------------------------------------
+
+class ipcIDList : public ipcList<ipcIDNode>
+{
+public:
+ typedef ipcList<ipcIDNode> Super;
+
+ void Prepend(const nsID &id)
+ {
+ Super::Prepend(new ipcIDNode(id));
+ }
+
+ void Append(const nsID &id)
+ {
+ Super::Append(new ipcIDNode(id));
+ }
+
+ const ipcIDNode *Find(const nsID &id) const
+ {
+ return FindNode(mHead, id);
+ }
+
+ PRBool FindAndDelete(const nsID &id)
+ {
+ ipcIDNode *node = FindNodeBefore(mHead, id);
+ if (node) {
+ DeleteAfter(node);
+ return PR_TRUE;
+ }
+ else if (!IsEmpty()) {
+ DeleteFirst();
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+ }
+
+private:
+ static NS_HIDDEN_(ipcIDNode *) FindNode (ipcIDNode *head, const nsID &id);
+ static NS_HIDDEN_(ipcIDNode *) FindNodeBefore(ipcIDNode *head, const nsID &id);
+};
+
+#endif // !ipcIDList_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcList.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcList.h
new file mode 100644
index 00000000..a9b9c959
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcList.h
@@ -0,0 +1,211 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcList_h__
+#define ipcList_h__
+
+#include "prtypes.h"
+
+//-----------------------------------------------------------------------------
+// simple list of singly-linked objects. class T must have the following
+// structure:
+//
+// class T {
+// ...
+// public:
+// T *mNext;
+// };
+//
+// objects added to the list must be allocated with operator new. class T may
+// optionally inherit from ipcListNode<T> if it doesn't wish to define mNext
+// explicitly.
+//-----------------------------------------------------------------------------
+
+template<class T>
+class ipcList
+{
+public:
+ ipcList()
+ : mHead(NULL)
+ , mTail(NULL)
+ { }
+ ~ipcList() { DeleteAll(); }
+
+ //
+ // prepends obj at the beginning of the list.
+ //
+ void Prepend(T *obj)
+ {
+ obj->mNext = mHead;
+ mHead = obj;
+ if (!mTail)
+ mTail = mHead;
+ }
+
+ //
+ // appends obj to the end of the list.
+ //
+ void Append(T *obj)
+ {
+ obj->mNext = NULL;
+ if (mTail) {
+ mTail->mNext = obj;
+ mTail = obj;
+ }
+ else
+ mTail = mHead = obj;
+ }
+
+ //
+ // inserts b into the list after a.
+ //
+ void InsertAfter(T *a, T *b)
+ {
+ b->mNext = a->mNext;
+ a->mNext = b;
+ if (mTail == a)
+ mTail = b;
+ }
+
+ //
+ // removes first element w/o deleting it
+ //
+ void RemoveFirst()
+ {
+ if (mHead)
+ AdvanceHead();
+ }
+
+ //
+ // removes element after the given element w/o deleting it
+ //
+ void RemoveAfter(T *obj)
+ {
+ T *rej = obj->mNext;
+ if (rej) {
+ obj->mNext = rej->mNext;
+ if (rej == mTail)
+ mTail = obj;
+ }
+ }
+
+ //
+ // deletes first element
+ //
+ void DeleteFirst()
+ {
+ T *first = mHead;
+ if (first) {
+ AdvanceHead();
+ delete first;
+ }
+ }
+
+ //
+ // deletes element after the given element
+ //
+ void DeleteAfter(T *obj)
+ {
+ T *rej = obj->mNext;
+ if (rej) {
+ RemoveAfter(obj);
+ delete rej;
+ }
+ }
+
+ //
+ // deletes all elements
+ //
+ void DeleteAll()
+ {
+ while (mHead)
+ DeleteFirst();
+ }
+
+ const T *First() const { return mHead; }
+ T *First() { return mHead; }
+ const T *Last() const { return mTail; }
+ T *Last() { return mTail; }
+
+ PRBool IsEmpty() const { return mHead == NULL; }
+
+ //
+ // moves contents of list to another list
+ //
+ void MoveTo(ipcList<T> &other)
+ {
+ other.mHead = mHead;
+ other.mTail = mTail;
+ mHead = NULL;
+ mTail = NULL;
+ }
+
+ // gets count of list elements
+ PRUint32 Count()
+ {
+ T *obj = mHead;
+ PRUint32 count = 0;
+ while (obj) {
+ count++;
+ obj = obj->mNext;
+ }
+
+ return count;
+ }
+
+protected:
+ void AdvanceHead()
+ {
+ mHead = mHead->mNext;
+ if (!mHead)
+ mTail = NULL;
+ }
+
+ T *mHead;
+ T *mTail;
+};
+
+template<class T>
+class ipcListNode
+{
+public:
+ ipcListNode() : mNext(nsnull) {}
+
+ T *mNext;
+};
+
+#endif // !ipcList_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.cpp
new file mode 100644
index 00000000..340b211c
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.cpp
@@ -0,0 +1,181 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "ipcLog.h"
+
+#ifdef IPC_LOGGING
+
+#include <string.h>
+#include <ctype.h>
+
+#include "prenv.h"
+#include "prprf.h"
+#include "prthread.h"
+#include "plstr.h"
+
+#ifdef VBOX
+# if defined(__OS2__) && defined(PAGE_SIZE)
+# undef PAGE_SIZE
+# endif
+# include <iprt/initterm.h> // for RTR3InitDll
+#else // !VBOX
+PRBool ipcLogEnabled = PR_FALSE;
+#endif // !VBOX
+
+char ipcLogPrefix[10] = {0};
+
+#ifndef VBOX
+
+//-----------------------------------------------------------------------------
+// UNIX
+//-----------------------------------------------------------------------------
+#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+
+#include <sys/types.h>
+#include <unistd.h>
+
+static inline PRUint32
+WritePrefix(char *buf, PRUint32 bufLen)
+{
+ return PR_snprintf(buf, bufLen, "[%u:%p] %s ",
+ (unsigned) getpid(),
+ PR_GetCurrentThread(),
+ ipcLogPrefix);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// WIN32
+//-----------------------------------------------------------------------------
+#ifdef XP_WIN
+#include <windows.h>
+
+static inline PRUint32
+WritePrefix(char *buf, PRUint32 bufLen)
+{
+ return PR_snprintf(buf, bufLen, "[%u:%p] %s ",
+ GetCurrentProcessId(),
+ PR_GetCurrentThread(),
+ ipcLogPrefix);
+}
+#endif
+
+#endif // !VBOX
+
+//-----------------------------------------------------------------------------
+// logging API impl
+//-----------------------------------------------------------------------------
+
+void
+IPC_InitLog(const char *prefix)
+{
+#ifdef VBOX
+ // initialize VBox Runtime
+ RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+
+ PL_strncpyz(ipcLogPrefix, prefix, sizeof(ipcLogPrefix));
+#else
+ if (PR_GetEnv("IPC_LOG_ENABLE")) {
+ ipcLogEnabled = PR_TRUE;
+ PL_strncpyz(ipcLogPrefix, prefix, sizeof(ipcLogPrefix));
+ }
+#endif
+}
+
+void
+IPC_Log(const char *fmt, ... )
+{
+ va_list ap;
+ va_start(ap, fmt);
+ PRUint32 nb = 0;
+ char buf[512];
+
+#ifdef VBOX
+ if (ipcLogPrefix[0]) {
+ nb = strlen(ipcLogPrefix);
+ if (nb > sizeof(buf) - 2)
+ nb = sizeof(buf) - 2;
+ PL_strncpy(buf, ipcLogPrefix, nb);
+ buf[nb++] = ' ';
+ }
+#else
+ if (ipcLogPrefix[0])
+ nb = WritePrefix(buf, sizeof(buf));
+#endif
+
+ PR_vsnprintf(buf + nb, sizeof(buf) - nb, fmt, ap);
+ buf[sizeof(buf) - 1] = '\0';
+
+#ifdef VBOX
+ LogFlow(("%s", buf));
+#else
+ fwrite(buf, strlen(buf), 1, stdout);
+#endif
+
+ va_end(ap);
+}
+
+void
+IPC_LogBinary(const PRUint8 *data, PRUint32 len)
+{
+ PRUint32 i, j, ln;
+ for (i=0; i<len; ) {
+ char line[100] = "";
+ const PRUint8 *p;
+
+ ln = 0;
+
+ p = &data[i];
+ for (j=0; j<PR_MIN(8, len - i); ++j, ++p)
+ ln += PR_snprintf(line + ln, sizeof(line) - ln, "%02x ", *p);
+
+ for (; ln < 32; ++ln)
+ line[ln] = ' ';
+
+ p = &data[i];
+ for (j=0; j<PR_MIN(8, len - i); ++j, ++p)
+ ln += PR_snprintf(line + ln, sizeof(line) - ln, "%c", isprint(*p) ? *p : '.');
+
+ line[ln] = '\0';
+
+ i += (p - &data[i]);
+
+ LOG(("%s\n", line));
+ }
+}
+
+#endif // IPC_LOGGING
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.h
new file mode 100644
index 00000000..e21f6211
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcLog.h
@@ -0,0 +1,111 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcLog_h__
+#define ipcLog_h__
+
+#include "nscore.h"
+#include "prtypes.h"
+
+#ifndef VBOX
+#ifdef DEBUG
+#define IPC_LOGGING
+#endif
+#endif
+
+#ifdef IPC_LOGGING
+
+#ifdef VBOX
+
+/* Redefine logging group to IPC */
+# ifdef LOG_GROUP
+# undef LOG_GROUP
+# endif
+# define LOG_GROUP LOG_GROUP_IPC
+
+/* Ensure log macros are enabled */
+# ifndef LOG_ENABLED
+# define LOG_ENABLED
+# endif
+
+#include <VBox/log.h>
+
+extern NS_HIDDEN_(void) IPC_InitLog(const char *prefix);
+extern NS_HIDDEN_(void) IPC_Log(const char *fmt, ...);
+extern NS_HIDDEN_(void) IPC_LogBinary(const PRUint8 *data, PRUint32 len);
+
+# define IPC_LOG(_args) \
+ PR_BEGIN_MACRO \
+ if (IPC_LOG_ENABLED()) \
+ IPC_Log _args; \
+ PR_END_MACRO
+
+/* IPC_Log() internally uses LogFlow() so use LogIsFlowEnabled() below */
+# define IPC_LOG_ENABLED() (LogIsFlowEnabled())
+
+# define LOG(args) IPC_LOG(args)
+
+#else /* !VBOX */
+
+extern PRBool ipcLogEnabled;
+extern NS_HIDDEN_(void) IPC_InitLog(const char *prefix);
+extern NS_HIDDEN_(void) IPC_Log(const char *fmt, ...);
+extern NS_HIDDEN_(void) IPC_LogBinary(const PRUint8 *data, PRUint32 len);
+
+#define IPC_LOG(_args) \
+ PR_BEGIN_MACRO \
+ if (ipcLogEnabled) \
+ IPC_Log _args; \
+ PR_END_MACRO
+
+#define IPC_LOG_ENABLED() ipcLogEnabled
+
+#define LOG(args) IPC_LOG(args)
+
+#endif /* !VBOX */
+
+#else // IPC_LOGGING
+
+#define IPC_InitLog(prefix) PR_BEGIN_MACRO PR_END_MACRO
+#define IPC_LogBinary(data, len) PR_BEGIN_MACRO PR_END_MACRO
+#define IPC_LOG(_args) PR_BEGIN_MACRO PR_END_MACRO
+#define IPC_LOG_ENABLED() (0)
+#define LOG(args) PR_BEGIN_MACRO PR_END_MACRO
+
+#endif // IPC_LOGGING
+
+#endif // !ipcLog_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.cpp
new file mode 100644
index 00000000..bfdc7efe
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.cpp
@@ -0,0 +1,280 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <stdlib.h>
+#include <string.h>
+#include "prlog.h"
+#include "ipcMessage.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+ipcMessage::~ipcMessage()
+{
+ if (mMsgHdr)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mMsgHdr);
+#else
+ free(mMsgHdr);
+#endif
+}
+
+void
+ipcMessage::Reset()
+{
+ if (mMsgHdr) {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mMsgHdr);
+#else
+ free(mMsgHdr);
+#endif
+ mMsgHdr = NULL;
+ }
+
+ mMsgOffset = 0;
+ mMsgComplete = PR_FALSE;
+}
+
+ipcMessage *
+ipcMessage::Clone() const
+{
+ ipcMessage *clone = new ipcMessage();
+ if (!clone)
+ return NULL;
+
+ // copy buf if non-null
+ if (mMsgHdr) {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ clone->mMsgHdr = (ipcMessageHeader *) RTMemDup(mMsgHdr, mMsgHdr->mLen);
+#else
+ clone->mMsgHdr = (ipcMessageHeader *) malloc(mMsgHdr->mLen);
+ memcpy(clone->mMsgHdr, mMsgHdr, mMsgHdr->mLen);
+#endif
+ }
+ else
+ clone->mMsgHdr = NULL;
+
+ clone->mMsgOffset = mMsgOffset;
+ clone->mMsgComplete = mMsgComplete;
+
+ return clone;
+}
+
+PRStatus
+ipcMessage::Init(const nsID &target, const char *data, PRUint32 dataLen)
+{
+ if (mMsgHdr)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mMsgHdr);
+#else
+ free(mMsgHdr);
+#endif
+ mMsgComplete = PR_FALSE;
+
+ // allocate message data
+ PRUint32 msgLen = IPC_MSG_HEADER_SIZE + dataLen;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mMsgHdr = (ipcMessageHeader *) RTMemAlloc(msgLen);
+#else
+ mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
+#endif
+ if (!mMsgHdr) {
+ mMsgHdr = NULL;
+ return PR_FAILURE;
+ }
+
+ // fill in message data
+ mMsgHdr->mLen = msgLen;
+ mMsgHdr->mVersion = IPC_MSG_VERSION;
+ mMsgHdr->mFlags = 0;
+ mMsgHdr->mTarget = target;
+
+ if (data)
+ SetData(0, data, dataLen);
+
+ mMsgComplete = PR_TRUE;
+ return PR_SUCCESS;
+}
+
+PRStatus
+ipcMessage::SetData(PRUint32 offset, const char *data, PRUint32 dataLen)
+{
+ PR_ASSERT(mMsgHdr != NULL);
+
+ if (offset + dataLen > DataLen())
+ return PR_FAILURE;
+
+ memcpy((char *) Data() + offset, data, dataLen);
+ return PR_SUCCESS;
+}
+
+PRBool
+ipcMessage::Equals(const nsID &target, const char *data, PRUint32 dataLen) const
+{
+ return mMsgComplete &&
+ mMsgHdr->mTarget.Equals(target) &&
+ DataLen() == dataLen &&
+ memcmp(Data(), data, dataLen) == 0;
+}
+
+PRBool
+ipcMessage::Equals(const ipcMessage *msg) const
+{
+ PRUint32 msgLen = MsgLen();
+ return mMsgComplete && msg->mMsgComplete &&
+ msgLen == msg->MsgLen() &&
+ memcmp(MsgBuf(), msg->MsgBuf(), msgLen) == 0;
+}
+
+PRStatus
+ipcMessage::WriteTo(char *buf,
+ PRUint32 bufLen,
+ PRUint32 *bytesWritten,
+ PRBool *complete)
+{
+ if (!mMsgComplete)
+ return PR_FAILURE;
+
+ if (mMsgOffset == MsgLen()) {
+ *bytesWritten = 0;
+ *complete = PR_TRUE;
+ return PR_SUCCESS;
+ }
+
+ PRUint32 count = MsgLen() - mMsgOffset;
+ if (count > bufLen)
+ count = bufLen;
+
+ memcpy(buf, MsgBuf() + mMsgOffset, count);
+ mMsgOffset += count;
+
+ *bytesWritten = count;
+ *complete = (mMsgOffset == MsgLen());
+
+ return PR_SUCCESS;
+}
+
+PRStatus
+ipcMessage::ReadFrom(const char *buf,
+ PRUint32 bufLen,
+ PRUint32 *bytesRead,
+ PRBool *complete)
+{
+ *bytesRead = 0;
+
+ if (mMsgComplete) {
+ *complete = PR_TRUE;
+ return PR_SUCCESS;
+ }
+
+ if (mMsgHdr) {
+ // appending data to buffer
+ if (mMsgOffset < sizeof(PRUint32)) {
+ // we haven't learned the message length yet
+ if (mMsgOffset + bufLen < sizeof(PRUint32)) {
+ // we still don't know the length of the message!
+ memcpy((char *) mMsgHdr + mMsgOffset, buf, bufLen);
+ mMsgOffset += bufLen;
+ *bytesRead = bufLen;
+ *complete = PR_FALSE;
+ return PR_SUCCESS;
+ }
+ else {
+ // we now have enough data to determine the message length
+ PRUint32 count = sizeof(PRUint32) - mMsgOffset;
+ memcpy((char *) MsgBuf() + mMsgOffset, buf, count);
+ mMsgOffset += count;
+ buf += count;
+ bufLen -= count;
+ *bytesRead = count;
+
+ if (MsgLen() > IPC_MSG_GUESSED_SIZE) {
+ // realloc message buffer to the correct size
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mMsgHdr = (ipcMessageHeader *) RTMemRealloc(mMsgHdr, MsgLen());
+#else
+ mMsgHdr = (ipcMessageHeader *) realloc(mMsgHdr, MsgLen());
+#endif
+ }
+ }
+ }
+ }
+ else {
+ if (bufLen < sizeof(PRUint32)) {
+ // not enough data available in buffer to determine allocation size
+ // allocate a partial buffer
+ PRUint32 msgLen = IPC_MSG_GUESSED_SIZE;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mMsgHdr = (ipcMessageHeader *) RTMemAlloc(msgLen);
+#else
+ mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
+#endif
+ if (!mMsgHdr)
+ return PR_FAILURE;
+ memcpy(mMsgHdr, buf, bufLen);
+ mMsgOffset = bufLen;
+ *bytesRead = bufLen;
+ *complete = PR_FALSE;
+ return PR_SUCCESS;
+ }
+ else {
+ PRUint32 msgLen = *(PRUint32 *) buf;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mMsgHdr = (ipcMessageHeader *) RTMemAlloc(msgLen);
+#else
+ mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
+#endif
+ if (!mMsgHdr)
+ return PR_FAILURE;
+ mMsgHdr->mLen = msgLen;
+ mMsgOffset = 0;
+ }
+ }
+
+ // have mMsgHdr at this point
+
+ PRUint32 count = MsgLen() - mMsgOffset;
+ if (count > bufLen)
+ count = bufLen;
+
+ memcpy((char *) mMsgHdr + mMsgOffset, buf, count);
+ mMsgOffset += count;
+ *bytesRead += count;
+
+ *complete = mMsgComplete = (mMsgOffset == MsgLen());
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.h
new file mode 100644
index 00000000..c9f8f184
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessage.h
@@ -0,0 +1,214 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcMessage_h__
+#define ipcMessage_h__
+
+#include "nsID.h"
+
+//
+// ipc message format:
+//
+// +------------------------------------+
+// | DWORD : length |
+// +------------------+-----------------+
+// | WORD : version | WORD : flags |
+// +------------------+-----------------+
+// | nsID : target |
+// +------------------------------------+
+// | data |
+// +------------------------------------+
+//
+// header is 24 bytes. flags are defined below. default value of flags is
+// zero. protocol implementations should ignore unrecognized flags. target
+// is a 16 byte UUID indicating the intended receiver of this message.
+//
+
+struct ipcMessageHeader
+{
+ PRUint32 mLen;
+ PRUint16 mVersion;
+ PRUint16 mFlags;
+ nsID mTarget;
+};
+
+#define IPC_MSG_VERSION (0x1)
+#define IPC_MSG_HEADER_SIZE (sizeof(ipcMessageHeader))
+#define IPC_MSG_GUESSED_SIZE (IPC_MSG_HEADER_SIZE + 64)
+
+//
+// the IPC message protocol supports synchronous messages. these messages can
+// only be sent from a client to the daemon. a daemon module cannot send a
+// synchronous message. the client sets the SYNC_QUERY flag to indicate that
+// it is expecting a response with the SYNC_REPLY flag set.
+//
+#define IPC_MSG_FLAG_SYNC_QUERY (0x1)
+#define IPC_MSG_FLAG_SYNC_REPLY (0x2)
+
+//
+// a special flag to prevent repeated processing of the same message by two
+// or more selectors when walking through the queue of pending messages
+// in WaitTarget().
+//
+#define IPC_MSG_FLAG_IN_PROCESS (0x4)
+
+//-----------------------------------------------------------------------------
+// ipcMessage
+//-----------------------------------------------------------------------------
+
+class ipcMessage
+{
+public:
+ ipcMessage()
+ : mNext(NULL)
+ , mMetaData(0)
+ , mMsgHdr(NULL)
+ , mMsgOffset(0)
+ , mMsgComplete(PR_FALSE)
+ { }
+ ipcMessage(const nsID &target, const char *data, PRUint32 dataLen)
+ : mNext(NULL)
+ , mMetaData(0)
+ , mMsgHdr(NULL)
+ , mMsgOffset(0)
+ { Init(target, data, dataLen); }
+ ~ipcMessage() NS_HIDDEN;
+
+ //
+ // reset message to uninitialized state
+ //
+ NS_HIDDEN_(void) Reset();
+
+ //
+ // create a copy of this message
+ //
+ NS_HIDDEN_(ipcMessage *) Clone() const;
+
+ //
+ // initialize message
+ //
+ // param:
+ // topic - message topic string
+ // data - message data (may be null to leave data uninitialized)
+ // dataLen - message data len
+ //
+ NS_HIDDEN_(PRStatus) Init(const nsID &target, const char *data, PRUint32 dataLen);
+
+ //
+ // copy data into the message's data section, starting from offset. this
+ // function can be used to write any portion of the message's data.
+ //
+ // param:
+ // offset - destination offset
+ // data - data to write
+ // dataLen - number of bytes to write
+ //
+ NS_HIDDEN_(PRStatus) SetData(PRUint32 offset, const char *data, PRUint32 dataLen);
+
+ //
+ // access message flags
+ //
+ void SetFlag(PRUint16 flag) { mMsgHdr->mFlags |= flag; }
+ void ClearFlag(PRUint16 flag) { mMsgHdr->mFlags &= ~flag; }
+ PRBool TestFlag(PRUint16 flag) const { return mMsgHdr->mFlags & flag; }
+
+ //
+ // if true, the message is complete and the members of the message
+ // can be accessed.
+ //
+ PRBool IsComplete() const { return mMsgComplete; }
+
+ //
+ // readonly accessors
+ //
+ const ipcMessageHeader *Header() const { return mMsgHdr; }
+ const nsID &Target() const { return mMsgHdr->mTarget; }
+ const char *Data() const { return (char *) mMsgHdr + IPC_MSG_HEADER_SIZE; }
+ PRUint32 DataLen() const { return mMsgHdr->mLen - IPC_MSG_HEADER_SIZE; }
+ const char *MsgBuf() const { return (char *) mMsgHdr; }
+ PRUint32 MsgLen() const { return mMsgHdr->mLen; }
+
+ //
+ // message comparison functions
+ //
+ // param:
+ // topic - message topic (may be null)
+ // data - message data (must not be null)
+ // dataLen - message data length
+ //
+ NS_HIDDEN_(PRBool) Equals(const nsID &target, const char *data, PRUint32 dataLen) const;
+ NS_HIDDEN_(PRBool) Equals(const ipcMessage *msg) const;
+
+ //
+ // write the message to a buffer segment; segment need not be large
+ // enough to hold entire message. called repeatedly.
+ //
+ NS_HIDDEN_(PRStatus) WriteTo(char *buf,
+ PRUint32 bufLen,
+ PRUint32 *bytesWritten,
+ PRBool *complete);
+
+ //
+ // read the message from a buffer segment; segment need not contain
+ // the entire messgae. called repeatedly.
+ //
+ NS_HIDDEN_(PRStatus) ReadFrom(const char *buf,
+ PRUint32 bufLen,
+ PRUint32 *bytesRead,
+ PRBool *complete);
+
+ //
+ // a message can be added to a singly-linked list.
+ //
+ class ipcMessage *mNext;
+
+ //
+ // meta data associated with this message object. the owner of the
+ // ipcMessage object is free to use this field for any purpose. by
+ // default, it is initialized to 0.
+ //
+ PRUint32 mMetaData;
+
+private:
+ ipcMessageHeader *mMsgHdr;
+
+ // XXX document me
+ PRUint32 mMsgOffset;
+ PRPackedBool mMsgComplete;
+};
+
+#endif // !ipcMessage_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.cpp
new file mode 100644
index 00000000..08753ddb
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.cpp
@@ -0,0 +1,81 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <string.h>
+#include "ipcMessagePrimitives.h"
+
+ipcMessage_DWORD_STR::ipcMessage_DWORD_STR(const nsID &target,
+ PRUint32 first,
+ const char *second)
+{
+ int sLen = strlen(second);
+ Init(target, NULL, 4 + sLen + 1);
+ SetData(0, (char *) &first, 4);
+ SetData(4, second, sLen + 1);
+}
+
+ipcMessage_DWORD_DWORD_STR::ipcMessage_DWORD_DWORD_STR(const nsID &target,
+ PRUint32 first,
+ PRUint32 second,
+ const char *third)
+{
+ int sLen = strlen(third);
+ Init(target, NULL, 8 + sLen + 1);
+ SetData(0, (char *) &first, 4);
+ SetData(4, (char *) &second, 4);
+ SetData(8, third, sLen + 1);
+}
+
+ipcMessage_DWORD_ID::ipcMessage_DWORD_ID(const nsID &target,
+ PRUint32 first,
+ const nsID &second)
+{
+ Init(target, NULL, 4 + sizeof(nsID));
+ SetData(0, (char *) &first, 4);
+ SetData(4, (char *) &second, sizeof(nsID));
+}
+
+ipcMessage_DWORD_DWORD_ID::ipcMessage_DWORD_DWORD_ID(const nsID &target,
+ PRUint32 first,
+ PRUint32 second,
+ const nsID &third)
+{
+ Init(target, NULL, 8 + sizeof(nsID));
+ SetData(0, (char *) &first, 4);
+ SetData(4, (char *) &second, 4);
+ SetData(8, (char *) &third, sizeof(nsID));
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.h
new file mode 100644
index 00000000..abfa7d69
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessagePrimitives.h
@@ -0,0 +1,206 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcMessagePrimitives_h__
+#define ipcMessagePrimitives_h__
+
+#include "ipcMessage.h"
+
+class ipcMessage_DWORD : public ipcMessage
+{
+public:
+ ipcMessage_DWORD(const nsID &target, PRUint32 first)
+ {
+ Init(target, (char *) &first, sizeof(first));
+ }
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+};
+
+class ipcMessage_DWORD_DWORD : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second)
+ {
+ PRUint32 data[2] = { first, second };
+ Init(target, (char *) data, sizeof(data));
+ }
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ PRUint32 Second() const
+ {
+ return ((PRUint32 *) Data())[1];
+ }
+};
+
+class ipcMessage_DWORD_DWORD_DWORD : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second, PRUint32 third)
+ {
+ PRUint32 data[3] = { first, second, third };
+ Init(target, (char *) data, sizeof(data));
+ }
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ PRUint32 Second() const
+ {
+ return ((PRUint32 *) Data())[1];
+ }
+
+ PRUint32 Third() const
+ {
+ return ((PRUint32 *) Data())[2];
+ }
+};
+
+class ipcMessage_DWORD_DWORD_DWORD_DWORD : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_DWORD_DWORD_DWORD(const nsID &target, PRUint32 first, PRUint32 second, PRUint32 third, PRUint32 fourth)
+ {
+ PRUint32 data[4] = { first, second, third, fourth };
+ Init(target, (char *) data, sizeof(data));
+ }
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ PRUint32 Second() const
+ {
+ return ((PRUint32 *) Data())[1];
+ }
+
+ PRUint32 Third() const
+ {
+ return ((PRUint32 *) Data())[2];
+ }
+
+ PRUint32 Fourth() const
+ {
+ return ((PRUint32 *) Data())[3];
+ }
+};
+
+class ipcMessage_DWORD_STR : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_STR(const nsID &target, PRUint32 first, const char *second) NS_HIDDEN;
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ const char *Second() const
+ {
+ return Data() + sizeof(PRUint32);
+ }
+};
+
+class ipcMessage_DWORD_DWORD_STR : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_DWORD_STR(const nsID &target, PRUint32 first, PRUint32 second, const char *third) NS_HIDDEN;
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ PRUint32 Second() const
+ {
+ return ((PRUint32 *) Data())[1];
+ }
+
+ const char *Third() const
+ {
+ return Data() + 2 * sizeof(PRUint32);
+ }
+};
+
+class ipcMessage_DWORD_ID : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_ID(const nsID &target, PRUint32 first, const nsID &second) NS_HIDDEN;
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ const nsID &Second() const
+ {
+ return * (const nsID *) (Data() + sizeof(PRUint32));
+ }
+};
+
+class ipcMessage_DWORD_DWORD_ID : public ipcMessage
+{
+public:
+ ipcMessage_DWORD_DWORD_ID(const nsID &target, PRUint32 first, PRUint32 second, const nsID &third) NS_HIDDEN;
+
+ PRUint32 First() const
+ {
+ return ((PRUint32 *) Data())[0];
+ }
+
+ PRUint32 Second() const
+ {
+ return ((PRUint32 *) Data())[1];
+ }
+
+ const nsID &Third() const
+ {
+ return * (const nsID *) (Data() + 2 * sizeof(PRUint32));
+ }
+};
+
+#endif // !ipcMessagePrimitives_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageQ.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageQ.h
new file mode 100644
index 00000000..d372713e
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageQ.h
@@ -0,0 +1,46 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcMessageQ_h__
+#define ipcMessageQ_h__
+
+#include "ipcMessage.h"
+#include "ipcList.h"
+
+typedef ipcList<ipcMessage> ipcMessageQ;
+
+#endif // !ipcMessageQ_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageUtils.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageUtils.h
new file mode 100644
index 00000000..99e3e6b8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcMessageUtils.h
@@ -0,0 +1,66 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcMessageUtils_h__
+#define ipcMessageUtils_h__
+
+class ipcMessage;
+
+//
+// given code like this:
+//
+// const ipcmMessageClientID *msg = (const ipcmMessageClientID *) rawMsg;
+//
+// we can write:
+//
+// ipcMessageCast<ipcmMessageClientID> msg(rawMsg);
+//
+// XXX ipcMessageCast is probably not the best name for this class.
+//
+template<class T>
+class ipcMessageCast
+{
+public:
+ ipcMessageCast() : mPtr(NULL) {}
+ ipcMessageCast(const ipcMessage *ptr) : mPtr((const T *) ptr) {}
+ void operator=(const ipcMessage *ptr) { mPtr = (const T *) ptr; }
+ const T *operator->() { return mPtr; }
+private:
+ const T *mPtr;
+};
+
+#endif // !ipcMessageUtils_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.cpp
new file mode 100644
index 00000000..5464f9a7
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.cpp
@@ -0,0 +1,80 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "ipcStringList.h"
+
+void *
+ipcStringNode::operator new(size_t size, const char *str) CPP_THROW_NEW
+{
+ int len = strlen(str);
+
+ size += len;
+
+ ipcStringNode *node = (ipcStringNode *) ::operator new(size);
+ if (!node)
+ return NULL;
+
+ node->mNext = NULL;
+ memcpy(node->mData, str, len);
+ node->mData[len] = '\0';
+
+ return node;
+}
+
+ipcStringNode *
+ipcStringList::FindNode(ipcStringNode *node, const char *str)
+{
+ while (node) {
+ if (node->Equals(str))
+ return node;
+ node = node->mNext;
+ }
+ return NULL;
+}
+
+ipcStringNode *
+ipcStringList::FindNodeBefore(ipcStringNode *node, const char *str)
+{
+ ipcStringNode *prev = NULL;
+ while (node) {
+ if (node->Equals(str))
+ return prev;
+ prev = node;
+ node = node->mNext;
+ }
+ return NULL;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.h
new file mode 100644
index 00000000..2a2316b6
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcStringList.h
@@ -0,0 +1,114 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcStringList_h__
+#define ipcStringList_h__
+
+#include <string.h>
+#include "plstr.h"
+#include "nscore.h"
+#include "ipcList.h"
+
+//-----------------------------------------------------------------------------
+// string node
+//-----------------------------------------------------------------------------
+
+class ipcStringNode
+{
+public:
+ ipcStringNode() {}
+
+ const char *Value() const { return mData; }
+
+ PRBool Equals(const char *val) const { return strcmp(mData, val) == 0; }
+ PRBool EqualsIgnoreCase(const char *val) const { return PL_strcasecmp(mData, val) == 0; }
+
+ class ipcStringNode *mNext;
+private:
+ void *operator new(size_t size, const char *str) CPP_THROW_NEW;
+
+ // this is actually bigger
+ char mData[1];
+
+ friend class ipcStringList;
+};
+
+//-----------------------------------------------------------------------------
+// singly-linked list of strings
+//-----------------------------------------------------------------------------
+
+class ipcStringList : public ipcList<ipcStringNode>
+{
+public:
+ typedef ipcList<ipcStringNode> Super;
+
+ void Prepend(const char *str)
+ {
+ Super::Prepend(new (str) ipcStringNode());
+ }
+
+ void Append(const char *str)
+ {
+ Super::Append(new (str) ipcStringNode());
+ }
+
+ const ipcStringNode *Find(const char *str) const
+ {
+ return FindNode(mHead, str);
+ }
+
+ PRBool FindAndDelete(const char *str)
+ {
+ ipcStringNode *node = FindNodeBefore(mHead, str);
+ if (node) {
+ DeleteAfter(node);
+ return PR_TRUE;
+ }
+ else if (!IsEmpty()) {
+ DeleteFirst();
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+ }
+
+private:
+ static NS_HIDDEN_(ipcStringNode *) FindNode (ipcStringNode *head, const char *str);
+ static NS_HIDDEN_(ipcStringNode *) FindNodeBefore(ipcStringNode *head, const char *str);
+};
+
+#endif // !ipcStringList_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.cpp b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.cpp
new file mode 100644
index 00000000..7f7ed060
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.cpp
@@ -0,0 +1,303 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 <string.h>
+#include "ipcm.h"
+#include "pratom.h"
+
+const nsID IPCM_TARGET =
+{ /* 753ca8ff-c8c2-4601-b115-8c2944da1150 */
+ 0x753ca8ff,
+ 0xc8c2,
+ 0x4601,
+ {0xb1, 0x15, 0x8c, 0x29, 0x44, 0xda, 0x11, 0x50}
+};
+
+PRUint32
+IPCM_NewRequestIndex()
+{
+ static PRInt32 sRequestIndex;
+ return (PRUint32) PR_AtomicIncrement(&sRequestIndex);
+}
+
+#if 0
+
+//
+// MSG_TYPE values
+//
+const PRUint32 ipcmMessagePing::MSG_TYPE = IPCM_MSG_TYPE_PING;
+const PRUint32 ipcmMessageError::MSG_TYPE = IPCM_MSG_TYPE_ERROR;
+const PRUint32 ipcmMessageClientHello::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_HELLO;
+const PRUint32 ipcmMessageClientID::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ID;
+const PRUint32 ipcmMessageClientInfo::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_INFO;
+const PRUint32 ipcmMessageClientAddName::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ADD_NAME;
+const PRUint32 ipcmMessageClientDelName::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_NAME;
+const PRUint32 ipcmMessageClientAddTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_ADD_TARGET;
+const PRUint32 ipcmMessageClientDelTarget::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_DEL_TARGET;
+const PRUint32 ipcmMessageQueryClientByName::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_BY_NAME;
+const PRUint32 ipcmMessageQueryClientInfo::MSG_TYPE = IPCM_MSG_TYPE_QUERY_CLIENT_INFO;
+const PRUint32 ipcmMessageForward::MSG_TYPE = IPCM_MSG_TYPE_FORWARD;
+const PRUint32 ipcmMessageClientStatus::MSG_TYPE = IPCM_MSG_TYPE_CLIENT_STATUS;
+
+//
+// CLIENT_INFO message
+//
+// +-----------------------------------------+
+// | DWORD : MSG_TYPE |
+// +--------------------+--------------------+
+// | DWORD : clientID |
+// +--------------------+--------------------+
+// | DWORD : requestIndex |
+// +--------------------+--------------------+
+// | WORD : nameStart | WORD : nameCount |
+// +--------------------+--------------------+
+// | WORD : targetStart | WORD : targetCount |
+// +--------------------+--------------------+
+// | name[0] | (null byte) |
+// +--------------------+--------------------+
+// . . .
+// . . .
+// +--------------------+--------------------+
+// | name[count - 1] | (null byte) |
+// +--------------------+--------------------+
+// | target[0] |
+// +-----------------------------------------+
+// . . .
+// . . .
+// +-----------------------------------------+
+// | target[count - 1] |
+// +-----------------------------------------+
+//
+
+struct ipcmClientInfoHeader
+{
+ PRUint32 mType;
+ PRUint32 mID;
+ PRUint32 mRequestIndex;
+ PRUint16 mNameStart;
+ PRUint16 mNameCount;
+ PRUint16 mTargetStart;
+ PRUint16 mTargetCount;
+};
+
+ipcmMessageClientInfo::ipcmMessageClientInfo(PRUint32 cID, PRUint32 rIdx, const char *names[], const nsID *targets[])
+{
+ ipcmClientInfoHeader hdr = {0};
+
+ hdr.mType = MSG_TYPE;
+ hdr.mID = cID;
+ hdr.mRequestIndex = rIdx;
+ hdr.mNameStart = sizeof(hdr);
+
+ PRUint32 i, namesLen = 0;
+
+ i = 0;
+ while (names[i]) {
+ namesLen += (strlen(names[i]) + 1);
+ ++hdr.mNameCount;
+ ++i;
+ }
+
+ i = 0;
+ while (targets[i]) {
+ ++hdr.mTargetCount;
+ ++i;
+ }
+
+ //
+ // compute target array starting offset
+ //
+ hdr.mTargetStart = hdr.mNameStart + namesLen;
+
+ //
+ // compute message length
+ //
+ PRUint32 dataLen = sizeof(hdr) + namesLen + hdr.mTargetCount * sizeof(nsID);
+
+ Init(IPCM_TARGET, NULL, dataLen);
+
+ //
+ // write message data
+ //
+ SetData(0, (const char *) &hdr, sizeof(hdr));
+
+ PRUint32 offset = sizeof(hdr);
+
+ for (i = 0; names[i]; ++i) {
+ PRUint32 len = strlen(names[i]) + 1;
+ SetData(offset, names[i], len);
+ offset += len;
+ }
+
+ for (i = 0; targets[i]; ++i) {
+ PRUint32 len = sizeof(nsID);
+ SetData(offset, (const char *) targets[i], len);
+ offset += len;
+ }
+}
+
+PRUint32
+ipcmMessageClientInfo::ClientID() const
+{
+ ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
+ return hdr->mID;
+}
+
+PRUint32
+ipcmMessageClientInfo::RequestIndex() const
+{
+ ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
+ return hdr->mRequestIndex;
+}
+
+PRUint32
+ipcmMessageClientInfo::NameCount() const
+{
+ ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
+ return hdr->mNameCount;
+}
+
+PRUint32
+ipcmMessageClientInfo::TargetCount() const
+{
+ ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
+ return hdr->mTargetCount;
+}
+
+const char *
+ipcmMessageClientInfo::NextName(const char *name) const
+{
+ ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
+
+ if (!name)
+ return (const char *) hdr + hdr->mNameStart;
+
+ name += strlen(name) + 1;
+ if (name == (const char *) hdr + hdr->mTargetStart)
+ name = NULL;
+ return name;
+}
+
+const nsID *
+ipcmMessageClientInfo::NextTarget(const nsID *target) const
+{
+ ipcmClientInfoHeader *hdr = (ipcmClientInfoHeader *) Data();
+
+ if (!target)
+ return (const nsID *) (Data() + hdr->mTargetStart);
+
+ if (++target == (const nsID *) (MsgBuf() + MsgLen()))
+ target = NULL;
+ return target;
+}
+#endif
+
+//
+// FORWARD message
+//
+// +-------------------------+
+// | DWORD : MSG_TYPE |
+// +-------------------------+
+// | clientID |
+// +-------------------------+
+// | innerMsgHeader |
+// +-------------------------+
+// | innerMsgData |
+// +-------------------------+
+//
+
+ipcmMessageForward::ipcmMessageForward(PRUint32 type,
+ PRUint32 cID,
+ const nsID &target,
+ const char *data,
+ PRUint32 dataLen)
+{
+ int len = sizeof(ipcmMessageHeader) + // IPCM header
+ sizeof(cID) + // cID
+ IPC_MSG_HEADER_SIZE + // innerMsgHeader
+ dataLen; // innerMsgData
+
+ Init(IPCM_TARGET, NULL, len);
+
+ ipcmMessageHeader ipcmHdr =
+ { type, IPCM_NewRequestIndex() };
+
+ SetData(0, (char *) &ipcmHdr, sizeof(ipcmHdr));
+ SetData(sizeof(ipcmHdr), (char *) &cID, sizeof(cID));
+
+ ipcMessageHeader hdr;
+ hdr.mLen = IPC_MSG_HEADER_SIZE + dataLen;
+ hdr.mVersion = IPC_MSG_VERSION;
+ hdr.mFlags = 0;
+ hdr.mTarget = target;
+
+ SetData(sizeof(ipcmHdr) + sizeof(cID), (char *) &hdr, IPC_MSG_HEADER_SIZE);
+ if (data)
+ SetInnerData(0, data, dataLen);
+}
+
+void
+ipcmMessageForward::SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen)
+{
+ SetData(sizeof(ipcmMessageHeader) + 4 + IPC_MSG_HEADER_SIZE + offset, data, dataLen);
+}
+
+PRUint32
+ipcmMessageForward::ClientID() const
+{
+ return ((PRUint32 *) Data())[2];
+}
+
+const nsID &
+ipcmMessageForward::InnerTarget() const
+{
+ ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 12);
+ return hdr->mTarget;
+}
+
+const char *
+ipcmMessageForward::InnerData() const
+{
+ return Data() + 12 + IPC_MSG_HEADER_SIZE;
+}
+
+PRUint32
+ipcmMessageForward::InnerDataLen() const
+{
+ ipcMessageHeader *hdr = (ipcMessageHeader *) (Data() + 12);
+ return hdr->mLen - IPC_MSG_HEADER_SIZE;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h
new file mode 100644
index 00000000..a6445654
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/shared/src/ipcm.h
@@ -0,0 +1,502 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef ipcm_h__
+#define ipcm_h__
+
+#include "ipcMessage.h"
+#include "ipcMessagePrimitives.h"
+
+//-----------------------------------------------------------------------------
+
+//
+// IPCM (IPC Manager) protocol support
+//
+
+// The IPCM message target identifier:
+extern const nsID IPCM_TARGET;
+
+//
+// Every IPCM message has the following structure:
+//
+// +-----------------------------------------+
+// | (ipc message header) |
+// +-----------------------------------------+
+// | DWORD : type |
+// +-----------------------------------------+
+// | DWORD : requestIndex |
+// +-----------------------------------------+
+// . .
+// . (payload) .
+// . .
+// +-----------------------------------------+
+//
+// where |type| is an integer uniquely identifying the message. the type is
+// composed of a message class identifier and a message number. there are 3
+// message classes:
+//
+// ACK - acknowledging a request
+// REQ - making a request
+// PSH - providing unrequested, "pushed" information
+//
+// The requestIndex field is initialized when a request is made. An
+// acknowledgement's requestIndex is equal to that of its corresponding
+// request message. This enables the requesting side of the message exchange
+// to match acknowledgements to requests. The requestIndex field is ignored
+// for PSH messages.
+//
+
+// The IPCM message class is stored in the most significant byte.
+#define IPCM_MSG_CLASS_REQ (1 << 24)
+#define IPCM_MSG_CLASS_ACK (2 << 24)
+#define IPCM_MSG_CLASS_PSH (4 << 24)
+
+// Requests
+#define IPCM_MSG_REQ_PING (IPCM_MSG_CLASS_REQ | 1)
+#define IPCM_MSG_REQ_FORWARD (IPCM_MSG_CLASS_REQ | 2)
+#define IPCM_MSG_REQ_CLIENT_HELLO (IPCM_MSG_CLASS_REQ | 3)
+#define IPCM_MSG_REQ_CLIENT_ADD_NAME (IPCM_MSG_CLASS_REQ | 4)
+#define IPCM_MSG_REQ_CLIENT_DEL_NAME (IPCM_MSG_CLASS_REQ | 5)
+#define IPCM_MSG_REQ_CLIENT_ADD_TARGET (IPCM_MSG_CLASS_REQ | 6)
+#define IPCM_MSG_REQ_CLIENT_DEL_TARGET (IPCM_MSG_CLASS_REQ | 7)
+#define IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME (IPCM_MSG_CLASS_REQ | 8)
+#define IPCM_MSG_REQ_QUERY_CLIENT_NAMES (IPCM_MSG_CLASS_REQ | 9) // TODO
+#define IPCM_MSG_REQ_QUERY_CLIENT_TARGETS (IPCM_MSG_CLASS_REQ | 10) // TODO
+
+// Acknowledgements
+#define IPCM_MSG_ACK_RESULT (IPCM_MSG_CLASS_ACK | 1)
+#define IPCM_MSG_ACK_CLIENT_ID (IPCM_MSG_CLASS_ACK | 2)
+#define IPCM_MSG_ACK_CLIENT_NAMES (IPCM_MSG_CLASS_ACK | 3) // TODO
+#define IPCM_MSG_ACK_CLIENT_TARGETS (IPCM_MSG_CLASS_ACK | 4) // TODO
+
+// Push messages
+#define IPCM_MSG_PSH_CLIENT_STATE (IPCM_MSG_CLASS_PSH | 1)
+#define IPCM_MSG_PSH_FORWARD (IPCM_MSG_CLASS_PSH | 2)
+
+//-----------------------------------------------------------------------------
+
+//
+// IPCM header
+//
+struct ipcmMessageHeader
+{
+ PRUint32 mType;
+ PRUint32 mRequestIndex;
+};
+
+//
+// returns IPCM message type.
+//
+static inline int
+IPCM_GetType(const ipcMessage *msg)
+{
+ return ((const ipcmMessageHeader *) msg->Data())->mType;
+}
+
+//
+// return IPCM message request index.
+//
+static inline PRUint32
+IPCM_GetRequestIndex(const ipcMessage *msg)
+{
+ return ((const ipcmMessageHeader *) msg->Data())->mRequestIndex;
+}
+
+//
+// return a request index that is unique to this process.
+//
+NS_HIDDEN_(PRUint32)
+IPCM_NewRequestIndex();
+
+//-----------------------------------------------------------------------------
+
+//
+// The IPCM protocol is detailed below:
+//
+
+// REQUESTS
+
+//
+// req: IPCM_MSG_REQ_PING
+// ack: IPCM_MSG_ACK_RESULT
+//
+// A PING can be sent from either a client to the daemon, or from the daemon
+// to a client. The expected acknowledgement is a RESULT message with a status
+// code of 0.
+//
+// This request message has no payload.
+//
+
+//
+// req: IPCM_MSG_REQ_FORWARD
+// ack: IPCM_MSG_ACK_RESULT
+//
+// A FORWARD is sent when a client wishes to send a message to another client.
+// The payload of this message is another message that should be forwarded by
+// the daemon's IPCM to the specified client. The expected acknowledgment is
+// a RESULT message with a status code indicating success or failure.
+//
+// When the daemon receives a FORWARD message, it creates a PSH_FORWARD message
+// and sends that on to the destination client.
+//
+// This request message has as its payload:
+//
+// +-----------------------------------------+
+// | DWORD : clientID |
+// +-----------------------------------------+
+// | (innerMsgHeader) |
+// +-----------------------------------------+
+// | (innerMsgData) |
+// +-----------------------------------------+
+//
+
+//
+// req: IPCM_MSG_REQ_CLIENT_HELLO
+// ack: IPCM_MSG_REQ_CLIENT_ID <or> IPCM_MSG_REQ_RESULT
+//
+// A CLIENT_HELLO is sent when a client connects to the IPC daemon. The
+// expected acknowledgement is a CLIENT_ID message informing the new client of
+// its ClientID. If for some reason the IPC daemon cannot accept the new
+// client, it returns a RESULT message with a failure status code.
+//
+// This request message has no payload.
+//
+
+//
+// req: IPCM_MSG_REQ_CLIENT_ADD_NAME
+// ack: IPCM_MSG_ACK_RESULT
+//
+// A CLIENT_ADD_NAME is sent when a client wishes to register an additional
+// name for itself. The expected acknowledgement is a RESULT message with a
+// status code indicating success or failure.
+//
+// This request message has as its payload a null-terminated ASCII character
+// string indicating the name of the client.
+//
+
+//
+// req: IPCM_MSG_REQ_CLIENT_DEL_NAME
+// ack: IPCM_MSG_ACK_RESULT
+//
+// A CLIENT_DEL_NAME is sent when a client wishes to unregister a name that it
+// has registered. The expected acknowledgement is a RESULT message with a
+// status code indicating success or failure.
+//
+// This request message has as its payload a null-terminated ASCII character
+// string indicating the name of the client.
+//
+
+//
+// req: IPCM_MSG_REQ_CLIENT_ADD_TARGET
+// ack: IPCM_MSG_ACK_RESULT
+//
+// A CLIENT_ADD_TARGET is sent when a client wishes to register an additional
+// target that it supports. The expected acknowledgement is a RESULT message
+// with a status code indicating success or failure.
+//
+// This request message has as its payload a 128-bit UUID indicating the
+// target to add.
+//
+
+//
+// req: IPCM_MSG_REQ_CLIENT_DEL_TARGET
+// ack: IPCM_MSG_ACK_RESULT
+//
+// A CLIENT_DEL_TARGET is sent when a client wishes to unregister a target
+// that it has registered. The expected acknowledgement is a RESULT message
+// with a status code indicating success or failure.
+//
+// This request message has as its payload a 128-bit UUID indicating the
+// target to remove.
+//
+
+//
+// req: IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME
+// ack: IPCM_MSG_ACK_CLIENT_ID <or> IPCM_MSG_ACK_RESULT
+//
+// A QUERY_CLIENT_BY_NAME may be sent by a client to discover the client that
+// is known by a common name. If more than one client matches the name, then
+// only the ID of the more recently registered client is returned. The
+// expected acknowledgement is a CLIENT_ID message carrying the ID of the
+// corresponding client. If no client matches the given name or if some error
+// occurs, then a RESULT message with a failure status code is returned.
+//
+// This request message has as its payload a null-terminated ASCII character
+// string indicating the client name to query.
+//
+
+// ACKNOWLEDGEMENTS
+
+//
+// ack: IPCM_MSG_ACK_RESULT
+//
+// This acknowledgement is returned to indicate a success or failure status.
+//
+// The payload consists of a single DWORD value.
+//
+// Possible status codes are listed below (negative values indicate failure
+// codes):
+//
+#define IPCM_OK 0 // success: generic
+#define IPCM_ERROR_GENERIC -1 // failure: generic
+#define IPCM_ERROR_NO_CLIENT -2 // failure: client does not exist
+#define IPCM_ERROR_INVALID_ARG -3 // failure: invalid request argument
+#define IPCM_ERROR_NO_SUCH_DATA -4 // failure: requested data does not exist
+#define IPCM_ERROR_ALREADY_EXISTS -5 // failure: data to set already exists
+
+//
+// ack: IPCM_MSG_ACK_CLIENT_ID
+//
+// This acknowledgement is returned to specify a client ID.
+//
+// The payload consists of a single DWORD value.
+//
+
+// PUSH MESSAGES
+
+//
+// psh: ICPM_MSG_PSH_CLIENT_STATE
+//
+// This message is sent to clients to indicate the status of other clients.
+//
+// The payload consists of:
+//
+// +-----------------------------------------+
+// | DWORD : clientID |
+// +-----------------------------------------+
+// | DWORD : clientState |
+// +-----------------------------------------+
+//
+// where, clientState is one of the following values indicating whether the
+// client has recently connected (up) or disconnected (down):
+//
+#define IPCM_CLIENT_STATE_UP 1
+#define IPCM_CLIENT_STATE_DOWN 2
+
+//
+// psh: IPCM_MSG_PSH_FORWARD
+//
+// This message is sent by the daemon to a client on behalf of another client.
+// The recipient is expected to unpack the contained message and process it.
+//
+// The payload of this message matches the payload of IPCM_MSG_REQ_FORWARD,
+// with the exception that the clientID field is set to the clientID of the
+// sender of the IPCM_MSG_REQ_FORWARD message.
+//
+
+//-----------------------------------------------------------------------------
+
+//
+// NOTE: This file declares some helper classes that simplify constructing
+// and parsing IPCM messages. Each class subclasses ipcMessage, but
+// adds no additional member variables. |operator new| should be used
+// to allocate one of the IPCM helper classes, e.g.:
+//
+// ipcMessage *msg = new ipcmMessageClientHello("foo");
+//
+// Given an arbitrary ipcMessage, it can be parsed using logic similar
+// to the following:
+//
+// void func(const ipcMessage *unknown)
+// {
+// if (unknown->Topic().Equals(IPCM_TARGET)) {
+// if (IPCM_GetMsgType(unknown) == IPCM_MSG_TYPE_CLIENT_ID) {
+// ipcMessageCast<ipcmMessageClientID> msg(unknown);
+// printf("Client ID: %u\n", msg->ClientID());
+// }
+// }
+// }
+//
+
+// REQUESTS
+
+class ipcmMessagePing : public ipcMessage_DWORD_DWORD
+{
+public:
+ ipcmMessagePing()
+ : ipcMessage_DWORD_DWORD(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_PING,
+ IPCM_NewRequestIndex()) {}
+};
+
+class ipcmMessageForward : public ipcMessage
+{
+public:
+ // @param type the type of this message: IPCM_MSG_{REQ,PSH}_FORWARD
+ // @param clientID the client id of the sender or receiver
+ // @param target the message target
+ // @param data the message data
+ // @param dataLen the message data length
+ ipcmMessageForward(PRUint32 type,
+ PRUint32 clientID,
+ const nsID &target,
+ const char *data,
+ PRUint32 dataLen) NS_HIDDEN;
+
+ // set inner message data, constrained to the data length passed
+ // to this class's constructor.
+ NS_HIDDEN_(void) SetInnerData(PRUint32 offset, const char *data, PRUint32 dataLen);
+
+ NS_HIDDEN_(PRUint32) ClientID() const;
+ NS_HIDDEN_(const nsID &) InnerTarget() const;
+ NS_HIDDEN_(const char *) InnerData() const;
+ NS_HIDDEN_(PRUint32) InnerDataLen() const;
+};
+
+class ipcmMessageClientHello : public ipcMessage_DWORD_DWORD
+{
+public:
+ ipcmMessageClientHello()
+ : ipcMessage_DWORD_DWORD(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_CLIENT_HELLO,
+ IPCM_NewRequestIndex()) {}
+};
+
+class ipcmMessageClientAddName : public ipcMessage_DWORD_DWORD_STR
+{
+public:
+ ipcmMessageClientAddName(const char *name)
+ : ipcMessage_DWORD_DWORD_STR(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_CLIENT_ADD_NAME,
+ IPCM_NewRequestIndex(),
+ name) {}
+
+ const char *Name() const { return Third(); }
+};
+
+class ipcmMessageClientDelName : public ipcMessage_DWORD_DWORD_STR
+{
+public:
+ ipcmMessageClientDelName(const char *name)
+ : ipcMessage_DWORD_DWORD_STR(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_CLIENT_DEL_NAME,
+ IPCM_NewRequestIndex(),
+ name) {}
+
+ const char *Name() const { return Third(); }
+};
+
+class ipcmMessageClientAddTarget : public ipcMessage_DWORD_DWORD_ID
+{
+public:
+ ipcmMessageClientAddTarget(const nsID &target)
+ : ipcMessage_DWORD_DWORD_ID(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_CLIENT_ADD_TARGET,
+ IPCM_NewRequestIndex(),
+ target) {}
+
+ const nsID &Target() const { return Third(); }
+};
+
+class ipcmMessageClientDelTarget : public ipcMessage_DWORD_DWORD_ID
+{
+public:
+ ipcmMessageClientDelTarget(const nsID &target)
+ : ipcMessage_DWORD_DWORD_ID(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_CLIENT_ADD_TARGET,
+ IPCM_NewRequestIndex(),
+ target) {}
+
+ const nsID &Target() const { return Third(); }
+};
+
+class ipcmMessageQueryClientByName : public ipcMessage_DWORD_DWORD_STR
+{
+public:
+ ipcmMessageQueryClientByName(const char *name)
+ : ipcMessage_DWORD_DWORD_STR(
+ IPCM_TARGET,
+ IPCM_MSG_REQ_QUERY_CLIENT_BY_NAME,
+ IPCM_NewRequestIndex(),
+ name) {}
+
+ const char *Name() const { return Third(); }
+ PRUint32 RequestIndex() const { return Second(); }
+};
+
+// ACKNOWLEDGEMENTS
+
+class ipcmMessageResult : public ipcMessage_DWORD_DWORD_DWORD
+{
+public:
+ ipcmMessageResult(PRUint32 requestIndex, PRInt32 status)
+ : ipcMessage_DWORD_DWORD_DWORD(
+ IPCM_TARGET,
+ IPCM_MSG_ACK_RESULT,
+ requestIndex,
+ (PRUint32) status) {}
+
+ PRInt32 Status() const { return (PRInt32) Third(); }
+};
+
+class ipcmMessageClientID : public ipcMessage_DWORD_DWORD_DWORD
+{
+public:
+ ipcmMessageClientID(PRUint32 requestIndex, PRUint32 clientID)
+ : ipcMessage_DWORD_DWORD_DWORD(
+ IPCM_TARGET,
+ IPCM_MSG_ACK_CLIENT_ID,
+ requestIndex,
+ clientID) {}
+
+ PRUint32 ClientID() const { return Third(); }
+};
+
+// PUSH MESSAGES
+
+class ipcmMessageClientState : public ipcMessage_DWORD_DWORD_DWORD_DWORD
+{
+public:
+ ipcmMessageClientState(PRUint32 clientID, PRUint32 clientStatus)
+ : ipcMessage_DWORD_DWORD_DWORD_DWORD(
+ IPCM_TARGET,
+ IPCM_MSG_PSH_CLIENT_STATE,
+ 0,
+ clientID,
+ clientStatus) {}
+
+ PRUint32 ClientID() const { return Third(); }
+ PRUint32 ClientState() const { return Fourth(); }
+};
+
+#endif // !ipcm_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/test/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/test/.cvsignore
new file mode 100644
index 00000000..d1a44d27
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/test/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+TestIPC
diff --git a/src/libs/xpcom18a4/ipc/ipcd/test/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/test/Makefile.in
new file mode 100644
index 00000000..bad636f3
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/test/Makefile.in
@@ -0,0 +1,69 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = module
+
+MODULE = ipcd_test
+REQUIRES = \
+ xpcom \
+ string \
+ ipcd \
+ $(NULL)
+
+CPPSRCS = \
+ TestIPC.cpp \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+LIBS = \
+ $(EXTRA_DSO_LIBS) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/test/TestIPC.cpp b/src/libs/xpcom18a4/ipc/ipcd/test/TestIPC.cpp
new file mode 100644
index 00000000..1100d674
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/test/TestIPC.cpp
@@ -0,0 +1,338 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "ipcIService.h"
+#include "ipcIMessageObserver.h"
+#include "ipcILockService.h"
+#include "ipcCID.h"
+#include "ipcLockCID.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentRegistrar.h"
+
+#include "nsString.h"
+#include "prmem.h"
+
+static const nsID kIPCMTargetID =
+{ /* 753ca8ff-c8c2-4601-b115-8c2944da1150 */
+ 0x753ca8ff,
+ 0xc8c2,
+ 0x4601,
+ {0xb1, 0x15, 0x8c, 0x29, 0x44, 0xda, 0x11, 0x50}
+};
+
+static const nsID kTestTargetID =
+{ /* e628fc6e-a6a7-48c7-adba-f241d1128fb8 */
+ 0xe628fc6e,
+ 0xa6a7,
+ 0x48c7,
+ {0xad, 0xba, 0xf2, 0x41, 0xd1, 0x12, 0x8f, 0xb8}
+};
+
+#define RETURN_IF_FAILED(rv, step) \
+ PR_BEGIN_MACRO \
+ if (NS_FAILED(rv)) { \
+ printf("*** %s failed: rv=%x\n", step, rv); \
+ return rv;\
+ } \
+ PR_END_MACRO
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+static nsIEventQueue* gEventQ = nsnull;
+static PRBool gKeepRunning = PR_TRUE;
+static ipcIService *gIpcServ = nsnull;
+static ipcILockService *gIpcLockServ = nsnull;
+
+static void
+SendMsg(ipcIService *ipc, PRUint32 cID, const nsID &target, const char *data, PRUint32 dataLen, PRBool sync = PR_FALSE)
+{
+ printf("*** sending message: [to-client=%u dataLen=%u]\n", cID, dataLen);
+
+ nsresult rv;
+
+ rv = ipc->SendMessage(cID, target, (const PRUint8 *) data, dataLen);
+ if (NS_FAILED(rv)) {
+ printf("*** sending message failed: rv=%x\n", rv);
+ return;
+ }
+
+ if (sync) {
+ rv = ipc->WaitMessage(cID, target, nsnull, PR_UINT32_MAX);
+ if (NS_FAILED(rv))
+ printf("*** waiting for message failed: rv=%x\n", rv);
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+class myIpcMessageObserver : public ipcIMessageObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCIMESSAGEOBSERVER
+};
+NS_IMPL_ISUPPORTS1(myIpcMessageObserver, ipcIMessageObserver)
+
+NS_IMETHODIMP
+myIpcMessageObserver::OnMessageAvailable(PRUint32 sender, const nsID &target, const PRUint8 *data, PRUint32 dataLen)
+{
+ printf("*** got message: [sender=%u data=%s]\n", sender, (const char *) data);
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+#if 0
+class myIpcClientQueryHandler : public ipcIClientQueryHandler
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCICLIENTQUERYHANDLER
+};
+
+NS_IMPL_ISUPPORTS1(myIpcClientQueryHandler, ipcIClientQueryHandler)
+
+NS_IMETHODIMP
+myIpcClientQueryHandler::OnQueryComplete(PRUint32 aQueryID,
+ nsresult aStatus,
+ PRUint32 aClientID,
+ const char **aNames,
+ PRUint32 aNameCount,
+ const nsID **aTargets,
+ PRUint32 aTargetCount)
+{
+ printf("*** query complete [queryID=%u status=0x%x clientID=%u]\n",
+ aQueryID, aStatus, aClientID);
+
+ PRUint32 i;
+ printf("*** names:\n");
+ for (i = 0; i < aNameCount; ++i)
+ printf("*** %d={%s}\n", i, aNames[i]);
+ printf("*** targets:\n");
+ for (i = 0; i < aTargetCount; ++i) {
+ const char *trailer;
+ if (aTargets[i]->Equals(kTestTargetID))
+ trailer = " (TEST_TARGET_ID)";
+ else if (aTargets[i]->Equals(kIPCMTargetID))
+ trailer = " (IPCM_TARGET_ID)";
+ else
+ trailer = " (unknown)";
+ char *str = aTargets[i]->ToString();
+ printf("*** %d=%s%s\n", i, str, trailer);
+ PR_Free(str);
+ }
+
+ if (aClientID != 0) {
+ const char hello[] = "hello friend!";
+ SendMsg(gIpcServ, aClientID, kTestTargetID, hello, sizeof(hello));
+ }
+
+ return NS_OK;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if 0
+class myIpcLockNotify : public ipcILockNotify
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_IPCILOCKNOTIFY
+};
+
+NS_IMPL_ISUPPORTS1(myIpcLockNotify, ipcILockNotify)
+
+NS_IMETHODIMP
+myIpcLockNotify::OnAcquireLockComplete(const char *lockName, nsresult status)
+{
+ printf("*** OnAcquireLockComplete [lock=%s status=%x]\n", lockName, status);
+ gIpcLockServ->ReleaseLock(lockName);
+ return NS_OK;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+int main(int argc, char **argv)
+{
+ nsresult rv;
+
+ {
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->AutoRegister(nsnull);
+
+ // Create the Event Queue for this thread...
+ nsCOMPtr<nsIEventQueueService> eqs =
+ do_GetService(kEventQueueServiceCID, &rv);
+ RETURN_IF_FAILED(rv, "do_GetService(EventQueueService)");
+
+ rv = eqs->CreateMonitoredThreadEventQueue();
+ RETURN_IF_FAILED(rv, "CreateMonitoredThreadEventQueue");
+
+ rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
+ RETURN_IF_FAILED(rv, "GetThreadEventQueue");
+
+ printf("*** getting ipc service\n");
+ nsCOMPtr<ipcIService> ipcServ(do_GetService(IPC_SERVICE_CONTRACTID, &rv));
+ RETURN_IF_FAILED(rv, "do_GetService(ipcServ)");
+ NS_ADDREF(gIpcServ = ipcServ);
+
+ if (argc > 1) {
+ printf("*** using client name [%s]\n", argv[1]);
+ gIpcServ->AddName(argv[1]);
+ }
+
+ ipcServ->DefineTarget(kTestTargetID, new myIpcMessageObserver(), PR_TRUE);
+
+ const char data[] =
+ "01 this is a really long message.\n"
+ "02 this is a really long message.\n"
+ "03 this is a really long message.\n"
+ "04 this is a really long message.\n"
+ "05 this is a really long message.\n"
+ "06 this is a really long message.\n"
+ "07 this is a really long message.\n"
+ "08 this is a really long message.\n"
+ "09 this is a really long message.\n"
+ "10 this is a really long message.\n"
+ "11 this is a really long message.\n"
+ "12 this is a really long message.\n"
+ "13 this is a really long message.\n"
+ "14 this is a really long message.\n"
+ "15 this is a really long message.\n"
+ "16 this is a really long message.\n"
+ "17 this is a really long message.\n"
+ "18 this is a really long message.\n"
+ "19 this is a really long message.\n"
+ "20 this is a really long message.\n"
+ "21 this is a really long message.\n"
+ "22 this is a really long message.\n"
+ "23 this is a really long message.\n"
+ "24 this is a really long message.\n"
+ "25 this is a really long message.\n"
+ "26 this is a really long message.\n"
+ "27 this is a really long message.\n"
+ "28 this is a really long message.\n"
+ "29 this is a really long message.\n"
+ "30 this is a really long message.\n"
+ "31 this is a really long message.\n"
+ "32 this is a really long message.\n"
+ "33 this is a really long message.\n"
+ "34 this is a really long message.\n"
+ "35 this is a really long message.\n"
+ "36 this is a really long message.\n"
+ "37 this is a really long message.\n"
+ "38 this is a really long message.\n"
+ "39 this is a really long message.\n"
+ "40 this is a really long message.\n"
+ "41 this is a really long message.\n"
+ "42 this is a really long message.\n"
+ "43 this is a really long message.\n"
+ "44 this is a really long message.\n"
+ "45 this is a really long message.\n"
+ "46 this is a really long message.\n"
+ "47 this is a really long message.\n"
+ "48 this is a really long message.\n"
+ "49 this is a really long message.\n"
+ "50 this is a really long message.\n"
+ "51 this is a really long message.\n"
+ "52 this is a really long message.\n"
+ "53 this is a really long message.\n"
+ "54 this is a really long message.\n"
+ "55 this is a really long message.\n"
+ "56 this is a really long message.\n"
+ "57 this is a really long message.\n"
+ "58 this is a really long message.\n"
+ "59 this is a really long message.\n"
+ "60 this is a really long message.\n";
+ SendMsg(ipcServ, 0, kTestTargetID, data, sizeof(data), PR_TRUE);
+
+// PRUint32 queryID;
+// nsCOMPtr<ipcIClientQueryHandler> handler(new myIpcClientQueryHandler());
+// ipcServ->QueryClientByName("foopy", handler, PR_FALSE, &queryID);
+
+ PRUint32 foopyID;
+ nsresult foopyRv = ipcServ->ResolveClientName("foopy", &foopyID);
+ printf("*** query for 'foopy' returned [rv=%x id=%u]\n", foopyRv, foopyID);
+
+ if (NS_SUCCEEDED(foopyRv)) {
+ const char hello[] = "hello friend!";
+ SendMsg(ipcServ, foopyID, kTestTargetID, hello, sizeof(hello));
+ }
+
+ //
+ // test lock service
+ //
+ nsCOMPtr<ipcILockService> lockService = do_GetService(IPC_LOCKSERVICE_CONTRACTID, &rv);
+ RETURN_IF_FAILED(rv, "do_GetService(ipcLockServ)");
+ NS_ADDREF(gIpcLockServ = lockService);
+
+ //nsCOMPtr<ipcILockNotify> notify(new myIpcLockNotify());
+ gIpcLockServ->AcquireLock("blah", PR_TRUE);
+
+ rv = gIpcLockServ->AcquireLock("foo", PR_TRUE);
+ printf("*** sync AcquireLock returned [rv=%x]\n", rv);
+
+ PLEvent *ev;
+ while (gKeepRunning) {
+ gEventQ->WaitForEvent(&ev);
+ gEventQ->HandleEvent(ev);
+ }
+
+ NS_RELEASE(gIpcServ);
+
+ printf("*** processing remaining events\n");
+
+ // process any remaining events
+ while (NS_SUCCEEDED(gEventQ->GetEvent(&ev)) && ev)
+ gEventQ->HandleEvent(ev);
+
+ printf("*** done\n");
+ } // this scopes the nsCOMPtrs
+
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/test/module/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/test/module/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/test/module/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/test/module/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/test/module/Makefile.in
new file mode 100644
index 00000000..aec7c169
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/test/module/Makefile.in
@@ -0,0 +1,81 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Darin Fisher <darin@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd_test
+LIBRARY_NAME = testmodule
+SHORT_LIBNAME = testmod
+MODULE_NAME = ipcd_test
+
+FORCE_SHARED_LIB = 1
+NO_DIST_INSTALL = 1
+
+REQUIRES = \
+ xpcom \
+ ipcd \
+ $(NULL)
+
+CPPSRCS = TestModule.cpp
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../common \
+ $(NULL)
+
+EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(NSPR_LIBS) \
+ $(EXTRA_DSO_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+_IPC_FILES = \
+ $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX) \
+ $(NULL)
+
+libs:: $(_IPC_FILES)
+ $(INSTALL) $^ $(DIST)/bin/ipc/modules
+
+install:: $(_IPC_FILES)
+ $(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/ipc/modules
diff --git a/src/libs/xpcom18a4/ipc/ipcd/test/module/TestModule.cpp b/src/libs/xpcom18a4/ipc/ipcd/test/module/TestModule.cpp
new file mode 100644
index 00000000..fbd78867
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/test/module/TestModule.cpp
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include "ipcModuleUtil.h"
+
+#define TEST_MODULE_ID \
+{ /* e628fc6e-a6a7-48c7-adba-f241d1128fb8 */ \
+ 0xe628fc6e, \
+ 0xa6a7, \
+ 0x48c7, \
+ {0xad, 0xba, 0xf2, 0x41, 0xd1, 0x12, 0x8f, 0xb8} \
+}
+static const nsID kTestModuleID = TEST_MODULE_ID;
+
+struct TestModule
+{
+ static void Init()
+ {
+ printf("*** TestModule::Init\n");
+ }
+
+ static void Shutdown()
+ {
+ printf("*** TestModule::Shutdown\n");
+ }
+
+ static void HandleMsg(ipcClientHandle client,
+ const nsID &target,
+ const void *data,
+ PRUint32 dataLen)
+ {
+ printf("*** TestModule::HandleMsg [%s]\n", (const char *) data);
+
+ static const char buf[] = "pong";
+ IPC_SendMsg(client, kTestModuleID, buf, sizeof(buf));
+ }
+
+ static void ClientUp(ipcClientHandle client)
+ {
+ printf("*** TestModule::ClientUp [%u]\n", IPC_GetClientID(client));
+ }
+
+ static void ClientDown(ipcClientHandle client)
+ {
+ printf("*** TestModule::ClientDown [%u]\n", IPC_GetClientID(client));
+ }
+};
+
+static ipcModuleMethods gTestMethods =
+{
+ IPC_MODULE_METHODS_VERSION,
+ TestModule::Init,
+ TestModule::Shutdown,
+ TestModule::HandleMsg,
+ TestModule::ClientUp,
+ TestModule::ClientDown
+};
+
+static ipcModuleEntry gTestModuleEntry[] =
+{
+ { TEST_MODULE_ID, &gTestMethods }
+};
+
+IPC_IMPL_GETMODULES(TestModule, gTestModuleEntry)
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/util/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/util/Makefile.in
new file mode 100644
index 00000000..323f87f8
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/Makefile.in
@@ -0,0 +1,49 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Conrad Carlen <ccarlen@netscape.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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/public/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/util/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/public/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/util/public/Makefile.in
new file mode 100644
index 00000000..84d980c4
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/public/Makefile.in
@@ -0,0 +1,53 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Conrad Carlen <ccarlen@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+
+EXPORTS = \
+ ipcMessageReader.h \
+ ipcMessageWriter.h \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageReader.h b/src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageReader.h
new file mode 100644
index 00000000..f93bfa20
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageReader.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.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 ***** */
+
+#ifndef ipcMessageReader_h__
+#define ipcMessageReader_h__
+
+#include "prtypes.h"
+
+//*****************************************************************************
+// ipcMessageReader
+//
+// Reads from a const buffer supplied to it. Does not take ownership of the
+// buffer. Bytes are read in native endianess, as ipcMessageWriter writes them
+// in native endianess.
+//*****************************************************************************
+
+class ipcMessageReader
+{
+public:
+ ipcMessageReader(const PRUint8* inBuffer, PRUint32 bufferSize) :
+ mBuf(inBuffer), mBufEnd(inBuffer + bufferSize),
+ mBufPtr(mBuf),
+ mError(PR_FALSE)
+ { }
+
+ ~ipcMessageReader()
+ { }
+
+ // Returns PR_TRUE if an error has occured at any point
+ // during the lifetime of this object. Any read operation
+ // will safely return 0 on an error condition.
+ PRBool HasError()
+ { return mError; }
+
+ PRUint8 GetInt8();
+ PRUint16 GetInt16();
+ PRUint32 GetInt32();
+ PRInt32 GetBytes(void* destBuffer, PRInt32 n);
+
+ // Returns data at the current read position.
+ const PRUint8* GetPtr()
+ { return mBufPtr; }
+
+ // Returns PR_TRUE if the new position is within the buffer.
+ // Returns PR_FALSE and sets error state if not.
+ PRBool AdvancePtr(PRInt32 n);
+
+private:
+ const PRUint8 *mBuf, *mBufEnd;
+ const PRUint8 *mBufPtr;
+ PRBool mError;
+};
+
+#endif // ipcMessageReader_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageWriter.h b/src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageWriter.h
new file mode 100644
index 00000000..8e0a8178
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/public/ipcMessageWriter.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.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 ***** */
+
+#ifndef ipcMessageWriter_h__
+#define ipcMessageWriter_h__
+
+#include "prtypes.h"
+
+//*****************************************************************************
+// ipcMessageWriter
+//
+// Creates a block of memory and resizes it in order to hold writes. The
+// block will be freed when this object is destroyed. Bytes are written in
+// native endianess, as ipcMessageReader reads them in native endianess.
+//*****************************************************************************
+
+class ipcMessageWriter
+{
+public:
+ ipcMessageWriter(PRUint32 initialCapacity) :
+ mBuf(NULL),
+ mBufPtr(NULL), mBufEnd(NULL),
+ mCapacity(0),
+ mError(PR_FALSE)
+ {
+ EnsureCapacity(initialCapacity);
+ }
+
+ ~ipcMessageWriter();
+
+ // Returns PR_TRUE if an error has occured at any point
+ // during the lifetime of this object, due to the buffer
+ // not being able to be grown to the required size.
+ PRBool HasError()
+ { return mError; }
+
+ void PutInt8(PRUint8 val);
+ void PutInt16(PRUint16 val);
+ void PutInt32(PRUint32 val);
+ PRUint32 PutBytes(const void* src, PRUint32 n);
+
+ // Returns the beginning of the buffer. Do not free this.
+ PRUint8* GetBuffer()
+ { return mBuf; }
+
+ PRInt32 GetSize()
+ { return mBufPtr - mBuf; }
+
+private:
+ PRBool EnsureCapacity(PRInt32 sizeNeeded)
+ {
+ return (mBuf && ((mBufPtr + sizeNeeded) <= mBufEnd)) ?
+ PR_TRUE : GrowCapacity(sizeNeeded);
+ }
+ PRBool GrowCapacity(PRInt32 sizeNeeded);
+
+private:
+ PRUint8 *mBuf;
+ PRUint8 *mBufPtr, *mBufEnd;
+ PRInt32 mCapacity;
+ PRBool mError;
+};
+
+#endif // ipcMessageWriter_h__
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/src/.cvsignore b/src/libs/xpcom18a4/ipc/ipcd/util/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/src/Makefile.in b/src/libs/xpcom18a4/ipc/ipcd/util/src/Makefile.in
new file mode 100644
index 00000000..6ebca736
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/src/Makefile.in
@@ -0,0 +1,56 @@
+# vim: noexpandtab ts=4 sw=4
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla IPC.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Conrad Carlen <ccarlen@netscape.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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = ipcd
+LIBRARY_NAME = ipcdutil_s
+FORCE_STATIC_LIB = 1
+MODULE_NAME = ipcd
+
+
+CPPSRCS = \
+ ipcMessageReader.cpp \
+ ipcMessageWriter.cpp
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageReader.cpp b/src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageReader.cpp
new file mode 100644
index 00000000..87279df2
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageReader.cpp
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.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 "ipcMessageReader.h"
+#include <string.h>
+
+//*****************************************************************************
+// ipcMessageReader
+//*****************************************************************************
+
+PRUint8 ipcMessageReader::GetInt8()
+{
+ if (mBufPtr < mBufEnd)
+ return *mBufPtr++;
+ mError = PR_TRUE;
+ return 0;
+}
+
+// GetInt16 and GetInt32 go to pains to avoid unaligned memory accesses that
+// are larger than a byte. On some platforms, that causes a performance penalty.
+// On other platforms, Tru64 for instance, it's an error.
+
+PRUint16 ipcMessageReader::GetInt16()
+{
+ if (mBufPtr + sizeof(PRUint16) <= mBufEnd) {
+ PRUint8 temp[2] = { mBufPtr[0], mBufPtr[1] };
+ mBufPtr += sizeof(PRUint16);
+ return *(PRUint16*)temp;
+ }
+ mError = PR_TRUE;
+ return 0;
+}
+
+PRUint32 ipcMessageReader::GetInt32()
+{
+ if (mBufPtr + sizeof(PRUint32) <= mBufEnd) {
+ PRUint8 temp[4] = { mBufPtr[0], mBufPtr[1], mBufPtr[2], mBufPtr[3] };
+ mBufPtr += sizeof(PRUint32);
+ return *(PRUint32*)temp;
+ }
+ mError = PR_TRUE;
+ return 0;
+}
+
+PRInt32 ipcMessageReader::GetBytes(void* destBuffer, PRInt32 n)
+{
+ if (mBufPtr + n <= mBufEnd) {
+ memcpy(destBuffer, mBufPtr, n);
+ mBufPtr += n;
+ return n;
+ }
+ mError = PR_TRUE;
+ return 0;
+}
+
+PRBool ipcMessageReader::AdvancePtr(PRInt32 n)
+{
+ const PRUint8 *newPtr = mBufPtr + n;
+ if (newPtr >= mBuf && newPtr <= mBufEnd) {
+ mBufPtr = newPtr;
+ return PR_TRUE;
+ }
+ mError = PR_TRUE;
+ return PR_FALSE;
+}
diff --git a/src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageWriter.cpp b/src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageWriter.cpp
new file mode 100644
index 00000000..4af0dcba
--- /dev/null
+++ b/src/libs/xpcom18a4/ipc/ipcd/util/src/ipcMessageWriter.cpp
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.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 "ipcMessageWriter.h"
+#include "prmem.h"
+#include <string.h>
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+//*****************************************************************************
+// ipcMessageWriter
+//*****************************************************************************
+
+ipcMessageWriter::~ipcMessageWriter()
+{
+ if (mBuf)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mBuf);
+#else
+ free(mBuf);
+#endif
+}
+
+void ipcMessageWriter::PutInt8(PRUint8 val)
+{
+ if (EnsureCapacity(sizeof(PRUint8)))
+ *mBufPtr++ = val;
+}
+
+// PutInt16 and PutInt32 go to pains to avoid unaligned memory accesses that
+// are larger than a byte. On some platforms, that causes a performance penalty.
+// On other platforms, Tru64 for instance, it's an error.
+
+void ipcMessageWriter::PutInt16(PRUint16 val)
+{
+ if (EnsureCapacity(sizeof(PRUint16))) {
+ PRUint8 temp[2];
+ *(PRUint16*)temp = val;
+ *mBufPtr++ = temp[0];
+ *mBufPtr++ = temp[1];
+ }
+}
+
+void ipcMessageWriter::PutInt32(PRUint32 val)
+{
+ if (EnsureCapacity(sizeof(PRUint32))) {
+ PRUint8 temp[4];
+ *(PRUint32*)temp = val;
+ *mBufPtr++ = temp[0];
+ *mBufPtr++ = temp[1];
+ *mBufPtr++ = temp[2];
+ *mBufPtr++ = temp[3];
+ }
+}
+
+PRUint32 ipcMessageWriter::PutBytes(const void* src, PRUint32 n)
+{
+ if (EnsureCapacity(n)) {
+ memcpy(mBufPtr, src, n);
+ mBufPtr += n;
+ return n;
+ }
+ return 0;
+}
+
+PRBool ipcMessageWriter::GrowCapacity(PRInt32 sizeNeeded)
+{
+ if (sizeNeeded < 0)
+ return PR_FALSE;
+ PRInt32 newCapacity = (mBufPtr - mBuf) + sizeNeeded;
+ if (mCapacity == 0)
+ mCapacity = newCapacity;
+ else
+ {
+ while (newCapacity > mCapacity && (mCapacity << 1) > 0)
+ mCapacity <<= 1;
+ if (newCapacity > mCapacity) // if we broke out because of rollover
+ return PR_FALSE;
+ }
+
+ PRInt32 curPos = mBufPtr - mBuf;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ mBuf = (PRUint8*)RTMemRealloc(mBuf, mCapacity);
+#else
+ mBuf = (PRUint8*)realloc(mBuf, mCapacity);
+#endif
+ if (!mBuf) {
+ mError = PR_TRUE;
+ return PR_FALSE;
+ }
+ mBufPtr = mBuf + curPos;
+ mBufEnd = mBuf + mCapacity;
+ return PR_TRUE;
+}
diff --git a/src/libs/xpcom18a4/java/Makefile.kmk b/src/libs/xpcom18a4/java/Makefile.kmk
new file mode 100644
index 00000000..ed447fc5
--- /dev/null
+++ b/src/libs/xpcom18a4/java/Makefile.kmk
@@ -0,0 +1,230 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for Java bindings
+#
+
+#
+# Copyright (C) 2010-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# Globals
+#
+VBOX_JXPCOM_SRC := $(PATH_SUB_CURRENT)
+
+VBOX_JXPCOM_TARGET := $(PATH_TARGET)/vboxjxpcom-gen
+VBOX_JXPCOM_JDEST := $(VBOX_JXPCOM_TARGET)/jdest
+
+VBOX_GLUE_XSLT_DIR := $(PATH_ROOT)/src/VBox/Main/glue
+
+ifndef VBOX_ONLY_SDK
+ #
+ # VBoxJXpcom - Java<->XPCOM native library
+ #
+ DLLS += VBoxJXpcom
+
+ VBoxJXpcom_TEMPLATE = XPComDll
+ VBoxJXpcom_CXXFLAGS = -Wno-write-strings
+ VBoxJXpcom_DEFS = \
+ EXPORT_XPTI_API \
+ EXPORT_XPT_API \
+ VBOX_WITH_XPCOM
+ VBoxJXpcom_NAME = libvboxjxpcom
+ VBoxJXpcom_DLLSUFF.darwin = .jnilib
+ VBoxJXpcom_INCS = \
+ src \
+ $(VBOX_JAVA_INC) \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/glue \
+ $(VBOX_PATH_XPCOM_SRC)/xpcom/build \
+ $(VBOX_JXPCOM_JDEST)
+ VBoxJXpcom_SOURCES = \
+ src/nsAppFileLocProviderProxy.cpp \
+ src/nsJavaWrapper.cpp \
+ src/nsJavaXPCOMBindingUtils.cpp \
+ src/nsJavaXPTCStub.cpp \
+ src/nsJavaXPTCStubWeakRef.cpp \
+ src/nsJavaXPCOMGlue.cpp \
+ src/nsJavaInterfaces.cpp
+ VBoxJXpcom_LIBS = \
+ $(PATH_STAGE_LIB)/VBoxCOM$(VBOX_SUFF_LIB) \
+ $(PATH_STAGE_BIN)/VBoxXPCOM$(VBOX_SUFF_DLL)
+
+ #VBoxJXpcom_ORDERDEPS = $(VBOX_JXPCOM_GENH)
+ #VBoxJXpcom_CLEAN = $(VBOX_JXPCOM_GENH)
+ VBOX_JXPCOM_GENH = \
+ $(VBOX_JXPCOM_JDEST)/org_mozilla_xpcom_internal_XPCOMImpl.h \
+ $(VBOX_JXPCOM_JDEST)/org_mozilla_xpcom_internal_GREImpl.h \
+ $(VBOX_JXPCOM_JDEST)/org_mozilla_xpcom_internal_MozillaImpl.h \
+ $(VBOX_JXPCOM_JDEST)/org_mozilla_xpcom_internal_XPCOMJavaProxy.h \
+ $(VBOX_JXPCOM_JDEST)/org_mozilla_xpcom_internal_JavaXPCOMMethods.h \
+ $(VBOX_JXPCOM_JDEST)/org_mozilla_xpcom_ProfileLock.h
+
+endif # !VBOX_ONLY_SDK
+
+#
+# Install JAR files
+#
+INSTALLS += VBoxJXpcom-inst-jar
+
+VBOX_JXPCOM_JAR = $(VBoxJXpcom-inst-jar_0_OUTDIR)/vboxjxpcom.jar
+VBOX_JXPCOM_NSERROR = $(VBOX_JXPCOM_GEN)/java/XPCOMError.java
+ifndef VBOX_WITH_JAVA_SUPPORT_IN_XPIDL
+ VBOX_JXPCOM_GEN = $(VBOX_JXPCOM_TARGET)/jxpcomgen
+else
+ VBOX_JXPCOM_GEN = $(VBOX_JXPCOM_TARGET)/jxpcomgen-idl
+endif
+
+VBoxJXpcom-inst-jar_INST = $(INST_SDK)bindings/xpcom/java/
+VBoxJXpcom-inst-jar_MODE = a+r,u+w
+VBoxJXpcom-inst-jar_SOURCES = \
+ $(VBOX_JXPCOM_JAR)
+VBoxJXpcom-inst-jar_CLEAN = \
+ $(VBOX_JXPCOM_JAR) \
+ $(VBOX_JXPCOM_NSERROR) \
+ $(VBOX_JXPCOM_GEN)/jxpcomgen.list \
+ $(VBOX_JXPCOM_GEN)/jxpcomglue.list \
+ $(wildcard \
+ $(VBOX_JXPCOM_GEN)/java/*.java \
+ $(VBOX_JXPCOM_GEN)/java/glue/*.java \
+ $(VBOX_JXPCOM_JDEST)/*.class \
+ $(VBOX_JXPCOM_JDEST)/*/*.class \
+ $(VBOX_JXPCOM_JDEST)/*/*/*.class \
+ $(VBOX_JXPCOM_JDEST)/*/*/*/*.class \
+ $(VBOX_JXPCOM_JDEST)/*/*/*/*/*.class \
+ $(VBOX_JXPCOM_JDEST)/*/*/*/*/*/*.class \
+ )
+VBoxJXpcom-inst-jar_BLDDIRS += $(VBOX_JXPCOM_GEN)/java $(VBOX_JXPCOM_GEN)/java/glue $(VBOX_JXPCOM_GEN)/java/interfaces
+
+#
+# For VBoxJXpcom, not currently used.
+#
+$(VBOX_JXPCOM_GENH): $$(VBOX_JXPCOM_JAR)
+ $(call MSG_L1,Generating $@ from $<)
+ $(QUIET)$(VBOX_JAVAH) -classpath $(VBOX_JXPCOM_JDEST) -d $(VBOX_JXPCOM_JDEST) \
+ org.mozilla.xpcom.internal.XPCOMImpl \
+ org.mozilla.xpcom.internal.GREImpl \
+ org.mozilla.xpcom.internal.MozillaImpl \
+ org.mozilla.xpcom.internal.XPCOMJavaProxy \
+ org.mozilla.xpcom.ProfileLock \
+ org.mozilla.xpcom.internal.JavaXPCOMMethods
+
+#
+# Generate error constants.
+#
+$(VBOX_JXPCOM_NSERROR): $(VBOX_PATH_XPCOM_SRC)/xpcom/base/nsError.h $(VBOX_JXPCOM_SRC)/tools/gen-nsError.pl | $(VBOX_JXPCOM_GEN)/java/
+ $(call MSG_L1,Generating $@)
+ $(QUIET)perl $(VBOX_JXPCOM_SRC)/tools/gen-nsError.pl < $< > $@
+
+ifndef VBOX_WITH_JAVA_SUPPORT_IN_XPIDL
+ #
+ # Generate .java interface files from .xidl
+ #
+
+ $(VBOX_JXPCOM_GEN)/jxpcomgen.list: \
+ $(VBOX_XIDL_FILE) \
+ $(VBOX_FILESPLIT) \
+ $(VBOX_JXPCOM_SRC)/tools/genjifaces.xsl \
+ | $(VBOX_JXPCOM_GEN)/java/interfaces/
+ $(call MSG_L1,Generating Java interface files)
+ $(QUIET)$(RM) -f $(wildcard $(VBOX_JXPCOM_GEN)/java/interfaces/*.java)
+ $(QUIET)$(VBOX_XSLTPROC) \
+ -o $(VBOX_JXPCOM_GEN)/java/interfaces/merged.file $(VBOX_JXPCOM_SRC)/tools/genjifaces.xsl $<
+ $(QUIET)$(VBOX_FILESPLIT) $(VBOX_JXPCOM_GEN)/java/interfaces/merged.file $(VBOX_JXPCOM_GEN)/java/interfaces
+ $(QUIET)echo $(VBOX_JXPCOM_GEN)/java/interfaces/*.java > $@
+
+else # VBOX_WITH_JAVA_SUPPORT_IN_XPIDL
+ #
+ # Generate .java interface files from the XPCOM and VirtualBox IDL files.
+ #
+ # Note! There is not a 1:1 relationship between input and output files here, unfortunately.
+ # Note! VBOX_JXPCOM_NSERROR shares the output directory with us.
+ #
+ $(VBOX_JXPCOM_GEN)/jxpcomgen.list: \
+ $(VBOX_PATH_SDK)/bindings/xpcom/idl/VirtualBox_XPCOM.idl \
+ $$(addprefix $(VBOX_PATH_XPCOM_SRC)/,$$(XPCOM_IDLFILES)) \
+ $(VBOX_XPIDL) \
+ | $(VBOX_JXPCOM_GEN)/java/
+ $(call MSG_L1,Generating XPCOM Java interface files from IDL)
+ $(QUIET)$(RM) -f $(filter-out %/XPCOMError.java, $(wildcard $(VBOX_JXPCOM_GEN)/java/*.java))
+ $(foreach idl, $(VBOX_PATH_SDK)/bindings/xpcom/idl/VirtualBox_XPCOM.idl $(addprefix $(VBOX_PATH_XPCOM_SRC)/,$(XPCOM_IDLFILES))\
+ , $(NLTAB)$(QUIET)$(VBOX_XPIDL) -m java $(XPIDL_INCS) -e $(VBOX_JXPCOM_GEN)/java/$(basename $(notdir $(idl))).java $(idl) )
+ $(QUIET)echo $(VBOX_JXPCOM_GEN)/java/*.java > $@
+endif # VBOX_WITH_JAVA_SUPPORT_IN_XPIDL
+
+$(VBOX_JXPCOM_GEN)/jxpcomglue.list: \
+ $(VBOX_XIDL_FILE) \
+ $(VBOX_GLUE_XSLT_DIR)/glue-java.xsl \
+ $(VBOX_FILESPLIT) \
+ | $(VBOX_JXPCOM_GEN)/java/glue/
+ $(call MSG_L1,Generating Java glue files from XIDL)
+ $(QUIET)$(RM) -f $(wildcard $(VBOX_JXPCOM_GEN)/java/glue/*.java)
+ $(QUIET)$(VBOX_XSLTPROC) \
+ --stringparam filelistonly "" \
+ --stringparam G_vboxApiSuffix $(VBOX_API_SUFFIX) \
+ --stringparam G_vboxGlueStyle xpcom \
+ --stringparam G_vboxDirPrefix "" \
+ -o $(VBOX_JXPCOM_GEN)/java/glue/merged.file $(VBOX_GLUE_XSLT_DIR)/glue-java.xsl $<
+ $(QUIET)$(VBOX_FILESPLIT) $(VBOX_JXPCOM_GEN)/java/glue/merged.file $(VBOX_JXPCOM_GEN)/java/glue/
+ $(QUIET)echo $(VBOX_JXPCOM_GEN)/java/glue/*.java > $@
+
+#
+# Compile the all java code into a JAR file.
+#
+VBOX_JXPCOM_JSRC = $(VBOX_JXPCOM_SRC)/src/org/mozilla/xpcom
+VBOX_JXPCOM_JAR_SRC = \
+ $(VBOX_JXPCOM_JSRC)/IXPCOM.java \
+ $(VBOX_JXPCOM_JSRC)/Mozilla.java \
+ $(VBOX_JXPCOM_JSRC)/VersionComparator.java \
+ $(VBOX_JXPCOM_JSRC)/GREVersionRange.java \
+ $(VBOX_JXPCOM_JSRC)/IAppFileLocProvider.java \
+ $(VBOX_JXPCOM_JSRC)/ProfileLock.java \
+ $(VBOX_JXPCOM_JSRC)/IGRE.java \
+ $(VBOX_JXPCOM_JSRC)/IJavaXPCOMUtils.java \
+ $(VBOX_JXPCOM_JSRC)/XPCOMException.java \
+ $(VBOX_JXPCOM_JSRC)/IMozilla.java \
+ $(VBOX_JXPCOM_JSRC)/XPCOMInitializationException.java \
+ $(VBOX_JXPCOM_JSRC)/INIParser.java \
+ $(VBOX_JXPCOM_JSRC)/internal/GREImpl.java \
+ $(VBOX_JXPCOM_JSRC)/internal/JavaXPCOMMethods.java \
+ $(VBOX_JXPCOM_JSRC)/internal/MozillaImpl.java \
+ $(VBOX_JXPCOM_JSRC)/internal/XPCOMImpl.java \
+ $(VBOX_JXPCOM_JSRC)/internal/XPCOMJavaProxyBase.java \
+ $(VBOX_JXPCOM_JSRC)/internal/XPCOMJavaProxy.java
+
+$$(VBOX_JXPCOM_JAR): $(VBOX_JXPCOM_JAR_SRC) $(VBOX_JXPCOM_GEN)/jxpcomgen.list $(VBOX_JXPCOM_GEN)/jxpcomglue.list $(VBOX_JXPCOM_NSERROR) $(VBOX_JXPCOM_MGR) | $$(dir $$@)
+ $(call MSG_TOOL,javac,$(notdir $@),jxpcomgen.list,)
+ $(QUIET)$(RM) -Rf $(VBOX_JXPCOM_JDEST)
+ $(QUIET)$(MKDIR) -p $(VBOX_JXPCOM_JDEST)
+ $(QUIET)$(VBOX_JAVAC) $(VBOX_JAVAC_OPTS) @$(VBOX_JXPCOM_GEN)/jxpcomgen.list \
+ -d $(VBOX_JXPCOM_JDEST) -classpath $(VBOX_JXPCOM_JDEST)
+ $(call MSG_TOOL,javac,$(notdir $@),...,)
+ $(QUIET)$(VBOX_JAVAC) $(VBOX_JAVAC_OPTS) \
+ $(VBOX_JXPCOM_JAR_SRC) \
+ $(VBOX_JXPCOM_NSERROR) \
+ @$(VBOX_JXPCOM_GEN)/jxpcomglue.list \
+ -d $(VBOX_JXPCOM_JDEST) -classpath $(VBOX_JXPCOM_JDEST)
+ $(call MSG_LINK,$(notdir $@),$@)
+ $(QUIET)$(VBOX_JAR) cf $@ -C $(VBOX_JXPCOM_JDEST) .
+
+include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/src/libs/xpcom18a4/java/README.vbox b/src/libs/xpcom18a4/java/README.vbox
new file mode 100644
index 00000000..b22acc4d
--- /dev/null
+++ b/src/libs/xpcom18a4/java/README.vbox
@@ -0,0 +1,5 @@
+ JavaXPCOM sources (see https://developer.mozilla.org/en/JavaXPCOM) were taken from
+:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot, directory extensions/java/xpcom,
+Apr 29 2010.
+
+ Imported to VirtualBox codebase in revision .
diff --git a/src/libs/xpcom18a4/java/src/MacJawt.mm b/src/libs/xpcom18a4/java/src/MacJawt.mm
new file mode 100644
index 00000000..a2d0d3f8
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/MacJawt.mm
@@ -0,0 +1,47 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 <jni.h>
+#import <JavaVM/jawt_md.h>
+#include "prtypes.h"
+
+
+PRUint64 GetPlatformHandle(JAWT_DrawingSurfaceInfo* dsi)
+{
+ JAWT_MacOSXDrawingSurfaceInfo* dsi_mac =
+ static_cast<JAWT_MacOSXDrawingSurfaceInfo*> (dsi->platformInfo);
+ return reinterpret_cast<PRUint64> (dsi_mac->cocoaViewRef);
+}
diff --git a/src/libs/xpcom18a4/java/src/dlldeps-javaxpcom.cpp b/src/libs/xpcom18a4/java/src/dlldeps-javaxpcom.cpp
new file mode 100644
index 00000000..a78d6c1d
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/dlldeps-javaxpcom.cpp
@@ -0,0 +1,81 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsJavaInterfaces.h"
+
+
+void XXXNeverCalled_javaxpcom()
+{
+ MOZILLA_NATIVE(initialize) (nsnull, nsnull);
+
+ GRE_NATIVE(initEmbedding) (nsnull, nsnull, nsnull, nsnull, nsnull);
+
+ GRE_NATIVE(termEmbedding) (nsnull, nsnull);
+
+ GRE_NATIVE(lockProfileDirectory) (nsnull, nsnull, nsnull);
+
+ GRE_NATIVE(notifyProfile) (nsnull, nsnull);
+
+ GRE_NATIVE(lockProfileDirectory) (nsnull, nsnull, nsnull);
+
+ GRE_NATIVE(notifyProfile) (nsnull, nsnull);
+
+ XPCOM_NATIVE(initXPCOM) (nsnull, nsnull, nsnull, nsnull);
+
+ XPCOM_NATIVE(shutdownXPCOM) (nsnull, nsnull, nsnull);
+
+ XPCOM_NATIVE(newLocalFile) (nsnull, nsnull, nsnull, nsnull);
+
+ XPCOM_NATIVE(getComponentManager) (nsnull, nsnull);
+
+ XPCOM_NATIVE(getComponentRegistrar) (nsnull, nsnull);
+
+ XPCOM_NATIVE(getServiceManager) (nsnull, nsnull);
+
+ JAVAPROXY_NATIVE(callXPCOMMethod) (nsnull, nsnull, nsnull, nsnull, nsnull);
+
+ JAVAPROXY_NATIVE(finalizeProxy) (nsnull, nsnull, nsnull);
+
+ JAVAPROXY_NATIVE(isSameXPCOMObject) (nsnull, nsnull, nsnull, nsnull);
+
+ LOCKPROXY_NATIVE(release) (nsnull, nsnull, nsnull);
+
+ MOZILLA_NATIVE(getNativeHandleFromAWT) (nsnull, nsnull, nsnull);
+
+ JXUTILS_NATIVE(wrapJavaObject) (nsnull, nsnull, nsnull, nsnull);
+
+ JXUTILS_NATIVE(wrapXPCOMObject) (nsnull, nsnull, nsnull, nsnull);
+}
diff --git a/src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.cpp b/src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.cpp
new file mode 100644
index 00000000..c10bf4c1
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.cpp
@@ -0,0 +1,253 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsAppFileLocProviderProxy.h"
+#include "nsJavaXPCOMBindingUtils.h"
+#include "nsILocalFile.h"
+#include "nsISimpleEnumerator.h"
+
+
+nsAppFileLocProviderProxy::nsAppFileLocProviderProxy(jobject aJavaObject)
+{
+ mJavaLocProvider = GetJNIEnv()->NewGlobalRef(aJavaObject);
+}
+
+nsAppFileLocProviderProxy::~nsAppFileLocProviderProxy()
+{
+ GetJNIEnv()->DeleteGlobalRef(mJavaLocProvider);
+}
+
+NS_IMPL_ISUPPORTS2(nsAppFileLocProviderProxy,
+ nsIDirectoryServiceProvider,
+ nsIDirectoryServiceProvider2)
+
+
+// nsIDirectoryServiceProvider
+
+NS_IMETHODIMP
+nsAppFileLocProviderProxy::GetFile(const char* aProp, PRBool* aIsPersistant,
+ nsIFile** aResult)
+{
+ // Setup params for calling Java function
+ JNIEnv* env = GetJNIEnv();
+ jstring prop = env->NewStringUTF(aProp);
+ if (!prop)
+ return NS_ERROR_OUT_OF_MEMORY;
+ jbooleanArray persistant = env->NewBooleanArray(1);
+ if (!persistant)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Create method ID
+ jmethodID mid = nsnull;
+ jclass clazz = env->GetObjectClass(mJavaLocProvider);
+ if (clazz) {
+ mid = env->GetMethodID(clazz, "getFile",
+ "(Ljava/lang/String;[Z)Ljava/io/File;");
+ }
+ if (!mid)
+ return NS_ERROR_FAILURE;
+
+ // Call Java function
+ jobject javaFile = nsnull;
+ javaFile = env->CallObjectMethod(mJavaLocProvider, mid, prop, persistant);
+ if (javaFile == nsnull || env->ExceptionCheck())
+ return NS_ERROR_FAILURE;
+
+ // Set boolean output value
+ env->GetBooleanArrayRegion(persistant, 0, 1, (jboolean*) aIsPersistant);
+
+ // Set nsIFile result value
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = File_to_nsILocalFile(env, javaFile, getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv)) {
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)aResult);
+ }
+
+ return rv;
+}
+
+
+// nsIDirectoryServiceProvider2
+
+class DirectoryEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ DirectoryEnumerator(jobjectArray aJavaFileArray)
+ : mIndex(0)
+ {
+ JNIEnv* env = GetJNIEnv();
+ mJavaFileArray = static_cast<jobjectArray>
+ (env->NewGlobalRef(aJavaFileArray));
+ mArraySize = env->GetArrayLength(aJavaFileArray);
+ }
+
+ ~DirectoryEnumerator()
+ {
+ GetJNIEnv()->DeleteGlobalRef(mJavaFileArray);
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool* aResult)
+ {
+ if (!mJavaFileArray) {
+ *aResult = PR_FALSE;
+ } else {
+ *aResult = (mIndex < mArraySize);
+ }
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports** aResult)
+ {
+ nsresult rv = NS_ERROR_FAILURE;
+
+ JNIEnv* env = GetJNIEnv();
+ jobject javaFile = env->GetObjectArrayElement(mJavaFileArray, mIndex++);
+ if (javaFile) {
+ nsCOMPtr<nsILocalFile> localFile;
+ rv = File_to_nsILocalFile(env, javaFile, getter_AddRefs(localFile));
+ env->DeleteLocalRef(javaFile);
+
+ if (NS_SUCCEEDED(rv)) {
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)aResult);
+ }
+ }
+
+ env->ExceptionClear();
+ return NS_ERROR_FAILURE;
+ }
+
+private:
+ jobjectArray mJavaFileArray;
+ PRUint32 mArraySize;
+ PRUint32 mIndex;
+};
+
+NS_IMPL_ISUPPORTS1(DirectoryEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsAppFileLocProviderProxy::GetFiles(const char* aProp,
+ nsISimpleEnumerator** aResult)
+{
+ nsresult rv = NS_OK;
+
+ // Setup params for calling Java function
+ JNIEnv* env = GetJNIEnv();
+ jstring prop = env->NewStringUTF(aProp);
+ if (!prop)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+
+ // Create method ID
+ jmethodID mid = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ jclass clazz = env->GetObjectClass(mJavaLocProvider);
+ if (clazz) {
+ mid = env->GetMethodID(clazz, "getFiles",
+ "(Ljava/lang/String;)[Ljava/io/File;");
+ env->DeleteLocalRef(clazz);
+ }
+ if (!mid)
+ rv = NS_ERROR_FAILURE;
+ }
+
+ // Call Java function
+ jobject javaFileArray = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ javaFileArray = env->CallObjectMethod(mJavaLocProvider, mid, prop);
+
+ // Handle any exception thrown by Java method.
+ jthrowable exp = env->ExceptionOccurred();
+ if (exp) {
+#ifdef DEBUG
+ env->ExceptionDescribe();
+#endif
+
+ // If the exception is an instance of XPCOMException, then get the
+ // nsresult from the exception instance. Else, default to
+ // NS_ERROR_FAILURE.
+ if (env->IsInstanceOf(exp, xpcomExceptionClass)) {
+ jfieldID fid;
+ fid = env->GetFieldID(xpcomExceptionClass, "errorcode", "J");
+ if (fid) {
+ rv = env->GetLongField(exp, fid);
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+ NS_ASSERTION(fid, "Couldn't get 'errorcode' field of XPCOMException");
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+ } else {
+ // No exception thrown. Check the result.
+ if (javaFileArray == nsnull) {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ // Parse return value
+ *aResult = new DirectoryEnumerator(static_cast<jobjectArray>
+ (javaFileArray));
+ NS_ADDREF(*aResult);
+ return NS_OK;
+ }
+
+ // Handle error conditions
+ *aResult = nsnull;
+ env->ExceptionClear();
+ return rv;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult
+NS_NewAppFileLocProviderProxy(jobject aJavaLocProvider,
+ nsIDirectoryServiceProvider** aResult)
+{
+ nsAppFileLocProviderProxy* provider =
+ new nsAppFileLocProviderProxy(aJavaLocProvider);
+ if (provider == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(provider);
+
+ *aResult = provider;
+ return NS_OK;
+}
+
diff --git a/src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.h b/src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.h
new file mode 100644
index 00000000..d3b90880
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsAppFileLocProviderProxy.h
@@ -0,0 +1,65 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+#ifndef _nsAppFileLocProviderProxy_h_
+#define _nsAppFileLocProviderProxy_h_
+
+#include "nsIDirectoryService.h"
+#include "jni.h"
+
+
+class nsAppFileLocProviderProxy : public nsIDirectoryServiceProvider2
+{
+public:
+ nsAppFileLocProviderProxy(jobject aJavaLocProvider);
+ ~nsAppFileLocProviderProxy();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+private:
+ jobject mJavaLocProvider;
+};
+
+extern "C" nsresult
+NS_NewAppFileLocProviderProxy(jobject aJavaLocProvider,
+ nsIDirectoryServiceProvider** aResult);
+
+
+#endif //_nsAppFileLocProviderProxy_h_
+
diff --git a/src/libs/xpcom18a4/java/src/nsFileStreams.cpp b/src/libs/xpcom18a4/java/src/nsFileStreams.cpp
new file mode 100644
index 00000000..435df58b
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsFileStreams.cpp
@@ -0,0 +1,475 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#include <unistd.h>
+#elif defined(XP_MAC)
+#include <Files.h>
+#elif defined(XP_WIN)
+#include <windows.h>
+#elif defined(XP_OS2)
+#define INCL_DOSERRORS
+#include <os2.h>
+#else
+// XXX add necessary include file for ftruncate (or equivalent)
+#endif
+
+#if defined(XP_MAC)
+#include "pprio.h"
+#else
+#include "private/pprio.h"
+#endif
+
+#include "nsFileStreams.h"
+#include "nsILocalFile.h"
+#include "nsXPIDLString.h"
+#include "prerror.h"
+#include "nsCRT.h"
+#include "nsInt64.h"
+#include "nsIFile.h"
+
+#define NS_NO_INPUT_BUFFERING 1 // see http://bugzilla.mozilla.org/show_bug.cgi?id=41067
+
+#if defined(PR_LOGGING)
+//
+// Log module for nsFileTransport logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=nsFileIO:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+//
+PRLogModuleInfo* gFileIOLog = nsnull;
+
+#endif /* PR_LOGGING */
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsFileStream
+
+nsFileStream::nsFileStream()
+ : mFD(nsnull)
+ , mCloseFD(PR_TRUE)
+{
+}
+
+nsFileStream::~nsFileStream()
+{
+ if (mCloseFD)
+ Close();
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileStream, nsISeekableStream)
+
+nsresult
+nsFileStream::InitWithFileDescriptor(PRFileDesc* fd, nsISupports* parent)
+{
+ NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
+ //
+ // this file stream is dependent on its parent to keep the
+ // file descriptor valid. an owning reference to the parent
+ // prevents the file descriptor from going away prematurely.
+ //
+ mFD = fd;
+ mCloseFD = PR_FALSE;
+ mParent = parent;
+ return NS_OK;
+}
+
+nsresult
+nsFileStream::Close()
+{
+ nsresult rv = NS_OK;
+ if (mFD) {
+ if (mCloseFD)
+ if (PR_Close(mFD) == PR_FAILURE)
+ rv = NS_BASE_STREAM_OSERROR;
+ mFD = nsnull;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFileStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ if (mFD == nsnull)
+ return NS_BASE_STREAM_CLOSED;
+
+ nsInt64 cnt = PR_Seek64(mFD, offset, (PRSeekWhence)whence);
+ if (cnt == nsInt64(-1)) {
+ return NS_ErrorAccordingToNSPR();
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileStream::Tell(PRInt64 *result)
+{
+ if (mFD == nsnull)
+ return NS_BASE_STREAM_CLOSED;
+
+ nsInt64 cnt = PR_Seek64(mFD, 0, PR_SEEK_CUR);
+ if (cnt == nsInt64(-1)) {
+ return NS_ErrorAccordingToNSPR();
+ }
+ *result = cnt;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileStream::SetEOF()
+{
+ if (mFD == nsnull)
+ return NS_BASE_STREAM_CLOSED;
+
+#if defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2) || defined(XP_BEOS)
+ // Some system calls require an EOF offset.
+ PRInt64 offset;
+ nsresult rv = Tell(&offset);
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+ if (ftruncate(PR_FileDesc2NativeHandle(mFD), offset) != 0) {
+ NS_ERROR("ftruncate failed");
+ return NS_ERROR_FAILURE;
+ }
+#elif defined(XP_MAC)
+ if (::SetEOF(PR_FileDesc2NativeHandle(mFD), offset) != 0) {
+ NS_ERROR("SetEOF failed");
+ return NS_ERROR_FAILURE;
+ }
+#elif defined(XP_WIN)
+ if (!SetEndOfFile((HANDLE) PR_FileDesc2NativeHandle(mFD))) {
+ NS_ERROR("SetEndOfFile failed");
+ return NS_ERROR_FAILURE;
+ }
+#elif defined(XP_OS2)
+ if (DosSetFileSize((HFILE) PR_FileDesc2NativeHandle(mFD), offset) != NO_ERROR) {
+ NS_ERROR("DosSetFileSize failed");
+ return NS_ERROR_FAILURE;
+ }
+#else
+ // XXX not implemented
+#endif
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsFileInputStream
+
+NS_IMPL_ISUPPORTS_INHERITED3(nsFileInputStream,
+ nsFileStream,
+ nsIInputStream,
+ nsIFileInputStream,
+ nsILineInputStream)
+
+NS_METHOD
+nsFileInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ NS_ENSURE_NO_AGGREGATION(aOuter);
+
+ nsFileInputStream* stream = new nsFileInputStream();
+ if (stream == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(stream);
+ nsresult rv = stream->QueryInterface(aIID, aResult);
+ NS_RELEASE(stream);
+ return rv;
+}
+
+nsresult
+nsFileInputStream::Open(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm)
+{
+ nsresult rv = NS_OK;
+
+ // If the previous file is open, close it
+ if (mFD) {
+ rv = Close();
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ // Open the file
+ nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFile, &rv);
+ if (NS_FAILED(rv)) return rv;
+ if (aIOFlags == -1)
+ aIOFlags = PR_RDONLY;
+ if (aPerm == -1)
+ aPerm = 0;
+
+ PRFileDesc* fd;
+ rv = localFile->OpenNSPRFileDesc(aIOFlags, aPerm, &fd);
+ if (NS_FAILED(rv)) return rv;
+
+ mFD = fd;
+
+ if (mBehaviorFlags & DELETE_ON_CLOSE) {
+ // POSIX compatible filesystems allow a file to be unlinked while a
+ // file descriptor is still referencing the file. since we've already
+ // opened the file descriptor, we'll try to remove the file. if that
+ // fails, then we'll just remember the nsIFile and remove it after we
+ // close the file descriptor.
+ rv = aFile->Remove(PR_FALSE);
+ if (NS_FAILED(rv) && !(mBehaviorFlags & REOPEN_ON_REWIND)) {
+ // If REOPEN_ON_REWIND is not happenin', we haven't saved the file yet
+ mFile = aFile;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::Init(nsIFile* aFile, PRInt32 aIOFlags, PRInt32 aPerm,
+ PRInt32 aBehaviorFlags)
+{
+ NS_ENSURE_TRUE(!mFD, NS_ERROR_ALREADY_INITIALIZED);
+ NS_ENSURE_TRUE(!mParent, NS_ERROR_ALREADY_INITIALIZED);
+
+ mBehaviorFlags = aBehaviorFlags;
+
+ // If the file will be reopened on rewind, save the info to open the file
+ if (mBehaviorFlags & REOPEN_ON_REWIND) {
+ mFile = aFile;
+ mIOFlags = aIOFlags;
+ mPerm = aPerm;
+ }
+
+ return Open(aFile, aIOFlags, aPerm);
+}
+
+NS_IMETHODIMP
+nsFileInputStream::Close()
+{
+ nsresult rv = nsFileStream::Close();
+ if (NS_FAILED(rv)) return rv;
+ if (mFile && (mBehaviorFlags & DELETE_ON_CLOSE)) {
+ rv = mFile->Remove(PR_FALSE);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "failed to delete file");
+ // If we don't need to save the file for reopening, free it up
+ if (!(mBehaviorFlags & REOPEN_ON_REWIND)) {
+ mFile = nsnull;
+ }
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::Available(PRUint32* aResult)
+{
+ if (!mFD) {
+ return NS_BASE_STREAM_CLOSED;
+ }
+
+ PRInt32 avail = PR_Available(mFD);
+ if (avail == -1) {
+ return NS_ErrorAccordingToNSPR();
+ }
+ *aResult = avail;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aResult)
+{
+ if (!mFD) {
+ return NS_BASE_STREAM_CLOSED;
+ }
+
+ PRInt32 bytesRead = PR_Read(mFD, aBuf, aCount);
+ if (bytesRead == -1) {
+ return NS_ErrorAccordingToNSPR();
+ }
+ // Check if we're at the end of file and need to close
+ if (mBehaviorFlags & CLOSE_ON_EOF) {
+ if (bytesRead == 0) {
+ Close();
+ }
+ }
+
+ *aResult = bytesRead;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::ReadLine(nsACString& aLine, PRBool* aResult)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ PRUint32 aCount, PRUint32* aResult)
+{
+ // ReadSegments is not implemented because it would be inefficient when
+ // the writer does not consume all data. If you want to call ReadSegments,
+ // wrap a BufferedInputStream around the file stream. That will call
+ // Read().
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ if (!mFD) {
+ if (mBehaviorFlags & REOPEN_ON_REWIND) {
+ nsresult rv = Reopen();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ } else {
+ return NS_BASE_STREAM_CLOSED;
+ }
+ }
+
+ return nsFileStream::Seek(aWhence, aOffset);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsFileOutputStream
+
+NS_IMPL_ISUPPORTS_INHERITED2(nsFileOutputStream,
+ nsFileStream,
+ nsIOutputStream,
+ nsIFileOutputStream)
+
+NS_METHOD
+nsFileOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ NS_ENSURE_NO_AGGREGATION(aOuter);
+
+ nsFileOutputStream* stream = new nsFileOutputStream();
+ if (stream == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(stream);
+ nsresult rv = stream->QueryInterface(aIID, aResult);
+ NS_RELEASE(stream);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::Init(nsIFile* file, PRInt32 ioFlags, PRInt32 perm,
+ PRInt32 behaviorFlags)
+{
+ NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
+ if (NS_FAILED(rv)) return rv;
+ if (ioFlags == -1)
+ ioFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
+ if (perm <= 0)
+ perm = 0664;
+
+ PRFileDesc* fd;
+ rv = localFile->OpenNSPRFileDesc(ioFlags, perm, &fd);
+ if (NS_FAILED(rv)) return rv;
+
+ mFD = fd;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::Close()
+{
+ return nsFileStream::Close();
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *result)
+{
+ if (mFD == nsnull)
+ return NS_BASE_STREAM_CLOSED;
+
+ PRInt32 cnt = PR_Write(mFD, buf, count);
+ if (cnt == -1) {
+ return NS_ErrorAccordingToNSPR();
+ }
+ *result = cnt;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::Flush(void)
+{
+ if (mFD == nsnull)
+ return NS_BASE_STREAM_CLOSED;
+
+ PRInt32 cnt = PR_Sync(mFD);
+ if (cnt == -1) {
+ return NS_ErrorAccordingToNSPR();
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteFrom (see source comment)");
+ return NS_ERROR_NOT_IMPLEMENTED;
+ // File streams intentionally do not support this method.
+ // If you need something like this, then you should wrap
+ // the file stream using nsIBufferedOutputStream
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteSegments (see source comment)");
+ return NS_ERROR_NOT_IMPLEMENTED;
+ // File streams intentionally do not support this method.
+ // If you need something like this, then you should wrap
+ // the file stream using nsIBufferedOutputStream
+}
+
+NS_IMETHODIMP
+nsFileOutputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_FALSE;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/java/src/nsFileStreams.h b/src/libs/xpcom18a4/java/src/nsFileStreams.h
new file mode 100644
index 00000000..7d713fc5
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsFileStreams.h
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 nsFileStreams_h__
+#define nsFileStreams_h__
+
+#include "nsIFileStreams.h"
+#include "nsIFile.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsISeekableStream.h"
+#include "nsILineInputStream.h"
+#include "nsCOMPtr.h"
+#include "prlog.h"
+#include "prio.h"
+
+template<class CharType> class nsLineBuffer;
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileStream : public nsISeekableStream
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISEEKABLESTREAM
+
+ nsFileStream();
+ virtual ~nsFileStream();
+
+ nsresult Close();
+ nsresult InitWithFileDescriptor(PRFileDesc* fd, nsISupports* parent);
+
+protected:
+ PRFileDesc* mFD;
+ nsCOMPtr<nsISupports> mParent; // strong reference to parent nsFileIO,
+ // which ensures mFD remains valid.
+ PRBool mCloseFD;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileInputStream : public nsFileStream,
+ public nsIFileInputStream,
+ public nsILineInputStream
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIFILEINPUTSTREAM
+ NS_DECL_NSILINEINPUTSTREAM
+
+ // Overrided from nsFileStream
+ NS_IMETHOD Seek(PRInt32 aWhence, PRInt64 aOffset);
+
+ nsFileInputStream() : nsFileStream()
+ {
+ mBehaviorFlags = 0;
+ }
+ virtual ~nsFileInputStream()
+ {
+ Close();
+ }
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+ /**
+ * The file being opened. Only stored when DELETE_ON_CLOSE or
+ * REOPEN_ON_REWIND are true.
+ */
+ nsCOMPtr<nsIFile> mFile;
+ /**
+ * The IO flags passed to Init() for the file open.
+ * Only set for REOPEN_ON_REWIND.
+ */
+ PRInt32 mIOFlags;
+ /**
+ * The permissions passed to Init() for the file open.
+ * Only set for REOPEN_ON_REWIND.
+ */
+ PRInt32 mPerm;
+ /**
+ * Flags describing our behavior. See the IDL file for possible values.
+ */
+ PRInt32 mBehaviorFlags;
+
+protected:
+ /**
+ * Internal, called to open a file. Parameters are the same as their
+ * Init() analogues.
+ */
+ nsresult Open(nsIFile* file, PRInt32 ioFlags, PRInt32 perm);
+ /**
+ * Reopen the file (for OPEN_ON_READ only!)
+ */
+ nsresult Reopen() { return Open(mFile, mIOFlags, mPerm); }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsFileOutputStream : public nsFileStream,
+ public nsIFileOutputStream
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIOUTPUTSTREAM
+ NS_DECL_NSIFILEOUTPUTSTREAM
+
+ nsFileOutputStream() : nsFileStream() {}
+ virtual ~nsFileOutputStream() { nsFileOutputStream::Close(); }
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsFileStreams_h__
diff --git a/src/libs/xpcom18a4/java/src/nsIFileStreams.h b/src/libs/xpcom18a4/java/src/nsIFileStreams.h
new file mode 100644
index 00000000..3df02b55
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsIFileStreams.h
@@ -0,0 +1,209 @@
+/*
+ * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIFileStreams.idl
+ */
+
+#ifndef __gen_nsIFileStreams_h__
+#define __gen_nsIFileStreams_h__
+
+
+#ifndef __gen_nsIInputStream_h__
+#include "nsIInputStream.h"
+#endif
+
+#ifndef __gen_nsIOutputStream_h__
+#include "nsIOutputStream.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+class nsIFile; /* forward declaration */
+
+
+/* starting interface: nsIFileInputStream */
+#define NS_IFILEINPUTSTREAM_IID_STR "e3d56a20-c7ec-11d3-8cda-0060b0fc14a3"
+
+#define NS_IFILEINPUTSTREAM_IID \
+ {0xe3d56a20, 0xc7ec, 0x11d3, \
+ { 0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3 }}
+
+/**
+ * An input stream that allows you to read from a file.
+ */
+class NS_NO_VTABLE nsIFileInputStream : public nsIInputStream {
+ public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILEINPUTSTREAM_IID)
+
+ /**
+ * @param file file to read from (must QI to nsILocalFile)
+ * @param ioFlags file open flags listed in prio.h
+ * @param perm file mode bits listed in prio.h
+ * @param behaviorFlags flags specifying various behaviors of the class
+ * (see enumerations in the class)
+ */
+ /* void init (in nsIFile file, in long ioFlags, in long perm, in long behaviorFlags); */
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags) = 0;
+
+ /**
+ * If this is set, the file will be deleted by the time the stream is
+ * closed. It may be removed before the stream is closed if it is possible
+ * to delete it and still read from it.
+ *
+ * If OPEN_ON_READ is defined, and the file was recreated after the first
+ * delete, the file will be deleted again when it is closed again.
+ */
+ enum { DELETE_ON_CLOSE = 2 };
+
+ /**
+ * If this is set, the file will close automatically when the end of the
+ * file is reached.
+ */
+ enum { CLOSE_ON_EOF = 4 };
+
+ /**
+ * If this is set, the file will be reopened whenever Seek(0) occurs. If
+ * the file is already open and the seek occurs, it will happen naturally.
+ * (The file will only be reopened if it is closed for some reason.)
+ */
+ enum { REOPEN_ON_REWIND = 8 };
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIFILEINPUTSTREAM \
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags); \
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIFILEINPUTSTREAM(_to) \
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags) { return _to Init(file, ioFlags, perm, behaviorFlags); } \
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIFILEINPUTSTREAM(_to) \
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags) { return !_to ? NS_ERROR_NULL_POINTER : _to->Init(file, ioFlags, perm, behaviorFlags); } \
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsFileInputStream : public nsIFileInputStream
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFILEINPUTSTREAM
+
+ nsFileInputStream();
+
+private:
+ ~nsFileInputStream();
+
+protected:
+ /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsFileInputStream, nsIFileInputStream)
+
+nsFileInputStream::nsFileInputStream()
+{
+ /* member initializers and constructor code */
+}
+
+nsFileInputStream::~nsFileInputStream()
+{
+ /* destructor code */
+}
+
+/* void init (in nsIFile file, in long ioFlags, in long perm, in long behaviorFlags); */
+NS_IMETHODIMP nsFileInputStream::Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+/* starting interface: nsIFileOutputStream */
+#define NS_IFILEOUTPUTSTREAM_IID_STR "e6f68040-c7ec-11d3-8cda-0060b0fc14a3"
+
+#define NS_IFILEOUTPUTSTREAM_IID \
+ {0xe6f68040, 0xc7ec, 0x11d3, \
+ { 0x8c, 0xda, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3 }}
+
+/**
+ * An output stream that lets you stream to a file.
+ */
+class NS_NO_VTABLE nsIFileOutputStream : public nsIOutputStream {
+ public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILEOUTPUTSTREAM_IID)
+
+ /**
+ * @param file - file to write to (must QI to nsILocalFile)
+ * @param ioFlags - file open flags listed in prio.h
+ * @param perm - file mode bits listed in prio.h
+ * @param behaviorFlags flags specifying various behaviors of the class
+ * (currently none supported)
+ */
+ /* void init (in nsIFile file, in long ioFlags, in long perm, in long behaviorFlags); */
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIFILEOUTPUTSTREAM \
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags);
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIFILEOUTPUTSTREAM(_to) \
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags) { return _to Init(file, ioFlags, perm, behaviorFlags); }
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIFILEOUTPUTSTREAM(_to) \
+ NS_IMETHOD Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags) { return !_to ? NS_ERROR_NULL_POINTER : _to->Init(file, ioFlags, perm, behaviorFlags); }
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsFileOutputStream : public nsIFileOutputStream
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFILEOUTPUTSTREAM
+
+ nsFileOutputStream();
+
+private:
+ ~nsFileOutputStream();
+
+protected:
+ /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsFileOutputStream, nsIFileOutputStream)
+
+nsFileOutputStream::nsFileOutputStream()
+{
+ /* member initializers and constructor code */
+}
+
+nsFileOutputStream::~nsFileOutputStream()
+{
+ /* destructor code */
+}
+
+/* void init (in nsIFile file, in long ioFlags, in long perm, in long behaviorFlags); */
+NS_IMETHODIMP nsFileOutputStream::Init(nsIFile *file, PRInt32 ioFlags, PRInt32 perm, PRInt32 behaviorFlags)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_nsIFileStreams_h__ */
diff --git a/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp b/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp
new file mode 100644
index 00000000..103f2f37
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp
@@ -0,0 +1,557 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsJavaInterfaces.h"
+#include "nsJavaWrapper.h"
+#include "nsJavaXPCOMBindingUtils.h"
+#include "nsJavaXPTCStub.h"
+#include "nsIComponentRegistrar.h"
+#include "nsString.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIInputStream.h"
+#include "nsEnumeratorUtils.h"
+#include "nsAppFileLocProviderProxy.h"
+#ifndef VBOX
+#include "nsXULAppAPI.h"
+#endif
+#include "nsILocalFile.h"
+
+#ifdef XP_MACOSX
+#include "jawt.h"
+#endif
+
+
+#ifdef VBOX
+#if 0
+#include "org_mozilla_xpcom_internal_GREImpl.h"
+#include "org_mozilla_xpcom_internal_JavaXPCOMMethods.h"
+#include "org_mozilla_xpcom_internal_MozillaImpl.h"
+#include "org_mozilla_xpcom_internal_XPCOMImpl.h"
+#include "org_mozilla_xpcom_internal_XPCOMJavaProxy.h"
+#include "org_mozilla_xpcom_ProfileLock.h"
+#endif
+#include <VBox/com/com.h>
+using namespace com;
+#include <iprt/initterm.h>
+#include <iprt/string.h>
+#include <alloca.h>
+#endif
+
+extern "C" NS_EXPORT void JNICALL
+MOZILLA_NATIVE(initialize) (JNIEnv* env, jobject)
+{
+ if (!InitializeJavaGlobals(env)) {
+ jclass clazz =
+ env->FindClass("org/mozilla/xpcom/XPCOMInitializationException");
+ if (clazz) {
+ env->ThrowNew(clazz, "Failed to initialize JavaXPCOM");
+ }
+ }
+}
+
+nsresult
+InitEmbedding_Impl(JNIEnv* env, jobject aLibXULDirectory,
+ jobject aAppDirectory, jobject aAppDirProvider)
+{
+ nsresult rv;
+
+ // create an nsILocalFile from given java.io.File
+ nsCOMPtr<nsILocalFile> libXULDir;
+ if (aLibXULDirectory) {
+ rv = File_to_nsILocalFile(env, aLibXULDirectory, getter_AddRefs(libXULDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ nsCOMPtr<nsILocalFile> appDir;
+ if (aAppDirectory) {
+ rv = File_to_nsILocalFile(env, aAppDirectory, getter_AddRefs(appDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // create nsAppFileLocProviderProxy from given Java object
+ nsCOMPtr<nsIDirectoryServiceProvider> provider;
+ if (aAppDirProvider) {
+ rv = NS_NewAppFileLocProviderProxy(aAppDirProvider,
+ getter_AddRefs(provider));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // init libXUL
+#ifdef VBOX
+ return 0;
+#else
+ return XRE_InitEmbedding(libXULDir, appDir, provider, nsnull, 0);
+#endif
+}
+
+extern "C" NS_EXPORT void JNICALL
+GRE_NATIVE(initEmbedding) (JNIEnv* env, jobject, jobject aLibXULDirectory,
+ jobject aAppDirectory, jobject aAppDirProvider)
+{
+ nsresult rv = InitEmbedding_Impl(env, aLibXULDirectory, aAppDirectory,
+ aAppDirProvider);
+
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "Failure in initEmbedding");
+ FreeJavaGlobals(env);
+ }
+}
+
+extern "C" NS_EXPORT void JNICALL
+GRE_NATIVE(termEmbedding) (JNIEnv *env, jobject)
+{
+ // Free globals before calling XRE_TermEmbedding(), since we need some
+ // XPCOM services.
+ FreeJavaGlobals(env);
+
+#ifndef VBOX
+ XRE_TermEmbedding();
+#endif
+}
+#ifdef VBOX
+nsresult
+InitXPCOMVBox_Impl(JNIEnv* env, jobject aVBoxBinDirectory)
+{
+#if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
+ rv = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+#else
+ const char *pszHome = nsnull;
+ const char *jhome = nsnull;
+ jstring path = nsnull;
+
+ int rv;
+ jclass clazz;
+ jmethodID getPathMID;
+
+ if (aVBoxBinDirectory &&
+ (clazz = env->FindClass("java/io/File")) &&
+ (getPathMID = env->GetMethodID(clazz, "getAbsolutePath",
+ "()Ljava/lang/String;"))
+ )
+ {
+ path = (jstring)env->CallObjectMethod(aVBoxBinDirectory, getPathMID);
+ pszHome = jhome = env->GetStringUTFChars(path, nsnull);
+ }
+
+ if (pszHome == nsnull)
+ pszHome = getenv("VBOX_PROGRAM_PATH");
+
+ if (pszHome) {
+ size_t cchHome = strlen(pszHome);
+ char *pszExePath = (char *)alloca(cchHome + 32);
+ memcpy(pszExePath, pszHome, cchHome);
+ memcpy(pszExePath + cchHome, "/javafake", sizeof("/javafake"));
+ rv = RTR3InitEx(RTR3INIT_VER_CUR, RTR3INIT_FLAGS_DLL | RTR3INIT_FLAGS_UNOBTRUSIVE, 0, NULL, pszExePath);
+ } else {
+ rv = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ }
+
+ if (jhome)
+ env->ReleaseStringUTFChars(path, jhome);
+#endif
+
+ return com::Initialize();
+}
+#endif
+
+nsresult
+InitXPCOM_Impl(JNIEnv* env, jobject aMozBinDirectory,
+ jobject aAppFileLocProvider, jobject* aResult)
+{
+ nsresult rv;
+ // create an nsILocalFile from given java.io.File
+ nsCOMPtr<nsILocalFile> directory;
+ if (aMozBinDirectory) {
+ rv = File_to_nsILocalFile(env, aMozBinDirectory, getter_AddRefs(directory));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // create nsAppFileLocProviderProxy from given Java object
+ nsCOMPtr<nsIDirectoryServiceProvider> provider;
+ if (aAppFileLocProvider) {
+ rv = NS_NewAppFileLocProviderProxy(aAppFileLocProvider,
+ getter_AddRefs(provider));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // init XPCOM
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), directory, provider);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // create Java proxy for service manager returned by NS_InitXPCOM2
+ return NativeInterfaceToJavaObject(env, servMan, NS_GET_IID(nsIServiceManager),
+ nsnull, aResult);
+}
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(initXPCOM) (JNIEnv* env, jobject, jobject aMozBinDirectory,
+ jobject aAppFileLocProvider)
+{
+#ifdef VBOX
+ nsresult rv = InitXPCOMVBox_Impl(env, aMozBinDirectory);
+ if (NS_SUCCEEDED(rv))
+ return nsnull;
+#else
+ jobject servMan;
+ nsresult rv = InitXPCOM_Impl(env, aMozBinDirectory, aAppFileLocProvider,
+ &servMan);
+ if (NS_SUCCEEDED(rv))
+ return servMan;
+#endif
+
+ ThrowException(env, rv, "Failure in initXPCOM");
+ FreeJavaGlobals(env);
+ return nsnull;
+}
+
+extern "C" NS_EXPORT void JNICALL
+#ifdef VBOX
+XPCOM_NATIVE2(shutdownXPCOM) (JNIEnv *env, jobject, jobject aServMgr)
+#else
+XPCOM_NATIVE(shutdownXPCOM) (JNIEnv *env, jobject, jobject aServMgr)
+#endif
+{
+#ifdef VBOX
+ // Free globals before calling NS_ShutdownXPCOM(), since we need some
+ // XPCOM services.
+ //FreeJavaGlobals(env);
+ //com::Shutdown();
+#else
+ nsresult rv;
+ nsIServiceManager* servMgr = nsnull;
+ if (aServMgr) {
+ // Get native XPCOM instance
+ nsISupports* instancePtr = nsnull;
+ rv = JavaObjectToNativeInterface(env, aServMgr,
+ NS_GET_IID(nsIServiceManager), (void**) &instancePtr);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && instancePtr != nsnull,
+ "Failed to get XPCOM obj for ServiceMgr.");
+ if (NS_SUCCEEDED(rv)) {
+ rv = instancePtr->QueryInterface(NS_GET_IID(nsIServiceManager),
+ (void**) &servMgr);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "QI for nsIServiceManager failed");
+ }
+
+ // Even if we failed to get the matching xpcom object, we don't abort this
+ // function. Just call NS_ShutdownXPCOM with a null service manager.
+ }
+
+ // Free globals before calling NS_ShutdownXPCOM(), since we need some
+ // XPCOM services.
+ FreeJavaGlobals(env);
+
+ rv = NS_ShutdownXPCOM(servMgr);
+ if (NS_FAILED(rv))
+ ThrowException(env, rv, "NS_ShutdownXPCOM failed");
+#endif
+}
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(newLocalFile) (JNIEnv *env, jobject, jstring aPath,
+ jboolean aFollowLinks)
+{
+ // Create a Mozilla string from the jstring
+ const PRUnichar* buf = nsnull;
+ if (aPath) {
+ buf = env->GetStringChars(aPath, nsnull);
+ if (!buf)
+ return nsnull; // exception already thrown
+ }
+
+ nsAutoString path_str(buf);
+ env->ReleaseStringChars(aPath, buf);
+
+ // Make call to given function
+ nsCOMPtr<nsILocalFile> file;
+ nsresult rv = NS_NewLocalFile(path_str, aFollowLinks, getter_AddRefs(file));
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject javaProxy;
+ rv = NativeInterfaceToJavaObject(env, file, NS_GET_IID(nsILocalFile),
+ nsnull, &javaProxy);
+ if (NS_SUCCEEDED(rv))
+ return javaProxy;
+ }
+
+ ThrowException(env, rv, "Failure in newLocalFile");
+ return nsnull;
+}
+
+extern "C" NS_EXPORT jobject JNICALL
+#ifdef VBOX
+XPCOM_NATIVE2(getComponentManager) (JNIEnv *env, jobject)
+#else
+XPCOM_NATIVE(getComponentManager) (JNIEnv *env, jobject)
+#endif
+{
+ // Call XPCOM method
+ nsCOMPtr<nsIComponentManager> cm;
+ nsresult rv = NS_GetComponentManager(getter_AddRefs(cm));
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject javaProxy;
+ rv = NativeInterfaceToJavaObject(env, cm, NS_GET_IID(nsIComponentManager),
+ nsnull, &javaProxy);
+ if (NS_SUCCEEDED(rv))
+ return javaProxy;
+ }
+
+ ThrowException(env, rv, "Failure in getComponentManager");
+ return nsnull;
+}
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(getComponentRegistrar) (JNIEnv *env, jobject)
+{
+ // Call XPCOM method
+ nsCOMPtr<nsIComponentRegistrar> cr;
+ nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(cr));
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject javaProxy;
+ rv = NativeInterfaceToJavaObject(env, cr, NS_GET_IID(nsIComponentRegistrar),
+ nsnull, &javaProxy);
+ if (NS_SUCCEEDED(rv))
+ return javaProxy;
+ }
+
+ ThrowException(env, rv, "Failure in getComponentRegistrar");
+ return nsnull;
+}
+
+#ifdef VBOX
+# include <VBox/com/NativeEventQueue.h>
+# include <iprt/err.h>
+
+extern "C" NS_EXPORT jint JNICALL
+XPCOM_NATIVE2(waitForEvents) (JNIEnv *env, jobject, jlong aTimeout)
+{
+ com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
+ NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
+ if (!aEventQ)
+ return -1;
+
+ int rc = aEventQ->processEventQueue(aTimeout < 0 ? RT_INDEFINITE_WAIT : (uint32_t)aTimeout);
+
+ if (RT_SUCCESS(rc))
+ return 0;
+
+ if ( rc == VERR_TIMEOUT
+ || rc == VERR_INTERRUPTED)
+ return 1;
+
+ return 2;
+}
+#endif
+
+extern "C" NS_EXPORT jobject JNICALL
+#ifdef VBOX
+XPCOM_NATIVE2(getServiceManager) (JNIEnv *env, jobject)
+#else
+XPCOM_NATIVE(getServiceManager) (JNIEnv *env, jobject)
+#endif
+{
+ // Call XPCOM method
+ nsCOMPtr<nsIServiceManager> sm;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(sm));
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject javaProxy;
+ rv = NativeInterfaceToJavaObject(env, sm, NS_GET_IID(nsIServiceManager),
+ nsnull, &javaProxy);
+ if (NS_SUCCEEDED(rv))
+ return javaProxy;
+ }
+
+ ThrowException(env, rv, "Failure in getServiceManager");
+ return nsnull;
+}
+
+extern "C" NS_EXPORT jobject JNICALL
+GRE_NATIVE(lockProfileDirectory) (JNIEnv* env, jobject, jobject aDirectory)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (aDirectory) {
+ nsCOMPtr<nsILocalFile> profileDir;
+ rv = File_to_nsILocalFile(env, aDirectory, getter_AddRefs(profileDir));
+
+ if (NS_SUCCEEDED(rv)) {
+ nsISupports* lock;
+#ifdef VBOX
+ rv = 0;
+ lock = 0;
+#else
+ rv = XRE_LockProfileDirectory(profileDir, &lock);
+#endif
+
+ if (NS_SUCCEEDED(rv)) {
+ jclass clazz =
+ env->FindClass("org/mozilla/xpcom/ProfileLock");
+ if (clazz) {
+ jmethodID mid = env->GetMethodID(clazz, "<init>", "(J)V");
+ if (mid) {
+ return env->NewObject(clazz, mid, reinterpret_cast<jlong>(lock));
+ }
+ }
+
+ // if we get here, then something failed
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ }
+
+ ThrowException(env, rv, "Failure in lockProfileDirectory");
+ return nsnull;
+}
+
+extern "C" NS_EXPORT void JNICALL
+GRE_NATIVE(notifyProfile) (JNIEnv *env, jobject)
+{
+#ifndef VBOX
+ XRE_NotifyProfile();
+#endif
+}
+
+#ifdef XP_MACOSX
+extern PRUint64 GetPlatformHandle(JAWT_DrawingSurfaceInfo* dsi);
+#endif
+
+extern "C" NS_EXPORT jlong JNICALL
+MOZILLA_NATIVE(getNativeHandleFromAWT) (JNIEnv* env, jobject clazz,
+ jobject widget)
+{
+ PRUint64 handle = 0;
+
+#if defined(XP_MACOSX) && !defined(VBOX)
+ JAWT awt;
+ awt.version = JAWT_VERSION_1_4;
+ jboolean result = JAWT_GetAWT(env, &awt);
+ if (result == JNI_FALSE)
+ return 0;
+
+ JAWT_DrawingSurface* ds = awt.GetDrawingSurface(env, widget);
+ if (ds != nsnull) {
+ jint lock = ds->Lock(ds);
+ if (!(lock & JAWT_LOCK_ERROR)) {
+ JAWT_DrawingSurfaceInfo* dsi = ds->GetDrawingSurfaceInfo(ds);
+ if (dsi) {
+ handle = GetPlatformHandle(dsi);
+ ds->FreeDrawingSurfaceInfo(dsi);
+ }
+
+ ds->Unlock(ds);
+ }
+
+ awt.FreeDrawingSurface(ds);
+ }
+#else
+ NS_WARNING("getNativeHandleFromAWT JNI method not implemented");
+#endif
+
+ return handle;
+}
+
+extern "C" NS_EXPORT jlong JNICALL
+JXUTILS_NATIVE(wrapJavaObject) (JNIEnv* env, jobject, jobject aJavaObject,
+ jstring aIID)
+{
+ nsresult rv;
+ void* xpcomObject = nsnull;
+
+ if (!aJavaObject || !aIID) {
+ rv = NS_ERROR_NULL_POINTER;
+ } else {
+ const char* str = env->GetStringUTFChars(aIID, nsnull);
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ nsID iid;
+ if (iid.Parse(str)) {
+ rv = JavaObjectToNativeInterface(env, aJavaObject, iid, &xpcomObject);
+ if (NS_SUCCEEDED(rv)) {
+ nsISupports *xpcom_nat_obj = (nsISupports*) xpcomObject;
+ rv = xpcom_nat_obj->QueryInterface(iid, &xpcomObject);
+ NS_IF_RELEASE(xpcom_nat_obj);
+ }
+ } else {
+ rv = NS_ERROR_INVALID_ARG;
+ }
+
+ env->ReleaseStringUTFChars(aIID, str);
+ }
+ }
+
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "Failed to create XPCOM proxy for Java object");
+ }
+ return reinterpret_cast<jlong>(xpcomObject);
+}
+
+extern "C" NS_EXPORT jobject JNICALL
+JXUTILS_NATIVE(wrapXPCOMObject) (JNIEnv* env, jobject, jlong aXPCOMObject,
+ jstring aIID)
+{
+ nsresult rv;
+ jobject javaObject = nsnull;
+ nsISupports* xpcomObject = reinterpret_cast<nsISupports*>(aXPCOMObject);
+
+ if (!xpcomObject || !aIID) {
+ rv = NS_ERROR_NULL_POINTER;
+ } else {
+ const char* str = env->GetStringUTFChars(aIID, nsnull);
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ nsID iid;
+ if (iid.Parse(str)) {
+ // XXX Should we be passing something other than NULL for aObjectLoader?
+ rv = NativeInterfaceToJavaObject(env, xpcomObject, iid, nsnull,
+ &javaObject);
+ } else {
+ rv = NS_ERROR_INVALID_ARG;
+ }
+
+ env->ReleaseStringUTFChars(aIID, str);
+ }
+ }
+
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "Failed to create XPCOM proxy for Java object");
+ }
+ return javaObject;
+}
diff --git a/src/libs/xpcom18a4/java/src/nsJavaInterfaces.h b/src/libs/xpcom18a4/java/src/nsJavaInterfaces.h
new file mode 100644
index 00000000..69d2f680
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaInterfaces.h
@@ -0,0 +1,121 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+#ifndef _nsJavaInterfaces_h_
+#define _nsJavaInterfaces_h_
+
+#include "jni.h"
+#include "nscore.h"
+
+#ifdef VBOX
+#define MOZILLA_NATIVE(func) Java_org_mozilla_xpcom_internal_MozillaImpl_##func##Native
+#define GRE_NATIVE(func) Java_org_mozilla_xpcom_internal_GREImpl_##func##Native
+#define XPCOM_NATIVE(func) Java_org_mozilla_xpcom_internal_XPCOMImpl_##func##Native
+#define XPCOM_NATIVE2(func) Java_org_mozilla_xpcom_internal_XPCOMImpl_##func
+#else
+#define MOZILLA_NATIVE(func) Java_org_mozilla_xpcom_internal_MozillaImpl_##func
+#define GRE_NATIVE(func) Java_org_mozilla_xpcom_internal_GREImpl_##func
+#define XPCOM_NATIVE(func) Java_org_mozilla_xpcom_internal_XPCOMImpl_##func
+#endif
+#define JAVAPROXY_NATIVE(func) \
+ Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_##func
+#define LOCKPROXY_NATIVE(func) Java_org_mozilla_xpcom_ProfileLock_##func
+#define JXUTILS_NATIVE(func) \
+ Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_##func
+
+
+extern "C" NS_EXPORT void JNICALL
+MOZILLA_NATIVE(initialize) (JNIEnv* env, jobject);
+
+extern "C" NS_EXPORT void JNICALL
+GRE_NATIVE(initEmbedding) (JNIEnv* env, jobject, jobject aLibXULDirectory,
+ jobject aAppDirectory, jobject aAppDirProvider);
+
+extern "C" NS_EXPORT void JNICALL
+GRE_NATIVE(termEmbedding) (JNIEnv *env, jobject);
+
+extern "C" NS_EXPORT jobject JNICALL
+GRE_NATIVE(lockProfileDirectory) (JNIEnv *, jobject, jobject aDirectory);
+
+extern "C" NS_EXPORT void JNICALL
+GRE_NATIVE(notifyProfile) (JNIEnv *env, jobject);
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(initXPCOM) (JNIEnv* env, jobject, jobject aMozBinDirectory,
+ jobject aAppFileLocProvider);
+
+extern "C" NS_EXPORT void JNICALL
+XPCOM_NATIVE(shutdownXPCOM) (JNIEnv *env, jobject, jobject aServMgr);
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(newLocalFile) (JNIEnv *env, jobject, jstring aPath,
+ jboolean aFollowLinks);
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(getComponentManager) (JNIEnv *env, jobject);
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(getComponentRegistrar) (JNIEnv *env, jobject);
+
+extern "C" NS_EXPORT jobject JNICALL
+XPCOM_NATIVE(getServiceManager) (JNIEnv *env, jobject);
+
+extern "C" NS_EXPORT jobject JNICALL
+JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
+ jstring aMethodName, jobjectArray aParams);
+
+extern "C" NS_EXPORT void JNICALL
+JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy);
+
+extern "C" NS_EXPORT jboolean JNICALL
+JAVAPROXY_NATIVE(isSameXPCOMObject) (JNIEnv *env, jclass that, jobject aProxy1,
+ jobject aProxy2);
+
+extern "C" NS_EXPORT void JNICALL
+LOCKPROXY_NATIVE(release) (JNIEnv *env, jclass that, jlong aLockObject);
+
+extern "C" NS_EXPORT jlong JNICALL
+MOZILLA_NATIVE(getNativeHandleFromAWT) (JNIEnv* env, jobject, jobject widget);
+
+extern "C" NS_EXPORT jlong JNICALL
+JXUTILS_NATIVE(wrapJavaObject) (JNIEnv* env, jobject, jobject aJavaObject,
+ jstring aIID);
+
+extern "C" NS_EXPORT jobject JNICALL
+JXUTILS_NATIVE(wrapXPCOMObject) (JNIEnv* env, jobject, jlong aXPCOMObject,
+ jstring aIID);
+
+#endif // _nsJavaInterfaces_h_
diff --git a/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp b/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp
new file mode 100644
index 00000000..a046c8a3
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaWrapper.cpp
@@ -0,0 +1,2020 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsJavaInterfaces.h"
+#include "nsJavaWrapper.h"
+#include "nsJavaXPTCStub.h"
+#include "nsJavaXPCOMBindingUtils.h"
+#include "jni.h"
+#include "xptcall.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "prmem.h"
+#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "nsProxyRelease.h"
+
+static nsID nullID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
+
+#ifdef VBOX
+#include "nsIThread.h"
+static nsresult
+NS_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
+
+#endif
+
+nsresult
+CreateJavaArray(JNIEnv* env, PRUint8 aType, PRUint32 aSize, const nsID& aIID,
+ jobject* aResult)
+{
+ jobject array = nsnull;
+ switch (aType)
+ {
+ case nsXPTType::T_I8:
+ array = env->NewByteArray(aSize);
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8:
+ array = env->NewShortArray(aSize);
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16:
+ array = env->NewIntArray(aSize);
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32:
+ array = env->NewLongArray(aSize);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ array = env->NewFloatArray(aSize);
+ break;
+
+ // XXX how do we handle unsigned 64-bit values?
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ array = env->NewDoubleArray(aSize);
+ break;
+
+ case nsXPTType::T_BOOL:
+ array = env->NewBooleanArray(aSize);
+ break;
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ array = env->NewCharArray(aSize);
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_IID:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ array = env->NewObjectArray(aSize, stringClass, nsnull);
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ nsCOMPtr<nsIInterfaceInfoManager>
+ iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ NS_ASSERTION(iim, "Failed to get InterfaceInfoManager");
+ if (!iim)
+ return NS_ERROR_FAILURE;
+
+ // Get interface info for given IID
+ nsCOMPtr<nsIInterfaceInfo> info;
+ nsresult rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Get interface name
+ const char* iface_name;
+ rv = info->GetNameShared(&iface_name);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Create proper Java interface name
+ nsCAutoString class_name("org/mozilla/interfaces/");
+ class_name.AppendASCII(iface_name);
+ jclass ifaceClass = env->FindClass(class_name.get());
+ if (!ifaceClass)
+ return NS_ERROR_FAILURE;
+
+ array = env->NewObjectArray(aSize, ifaceClass, nsnull);
+ break;
+ }
+
+ case nsXPTType::T_VOID:
+ array = env->NewLongArray(aSize);
+ break;
+
+ default:
+ NS_WARNING("unknown type");
+ return NS_ERROR_FAILURE;
+ }
+
+ if (!array)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = array;
+ return NS_OK;
+}
+
+nsresult
+GetNativeArrayElement(PRUint8 aType, void* aArray, PRUint32 aIndex,
+ nsXPTCVariant* aResult)
+{
+ switch (aType)
+ {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_U8:
+ aResult->val.u8 = static_cast<PRUint8*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ aResult->val.u16 = static_cast<PRUint16*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ aResult->val.u32 = static_cast<PRUint32*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ aResult->val.u64 = static_cast<PRUint64*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_FLOAT:
+ aResult->val.f = static_cast<float*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ aResult->val.d = static_cast<double*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_BOOL:
+ aResult->val.b = static_cast<PRBool*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_CHAR:
+ aResult->val.c = static_cast<char*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_WCHAR:
+ aResult->val.wc = static_cast<PRUnichar*>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ aResult->val.p = static_cast<char**>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_WCHAR_STR:
+ aResult->val.p = static_cast<PRUnichar**>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_IID:
+ aResult->val.p = static_cast<nsID**>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ aResult->val.p = static_cast<nsISupports**>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ aResult->val.p = static_cast<nsString**>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ aResult->val.p = static_cast<nsCString**>(aArray)[aIndex];
+ break;
+
+ case nsXPTType::T_VOID:
+ aResult->val.p = static_cast<void**>(aArray)[aIndex];
+ break;
+
+ default:
+ NS_WARNING("unknown type");
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+CreateNativeArray(PRUint8 aType, PRUint32 aSize, void** aResult)
+{
+ void* array = nsnull;
+ switch (aType)
+ {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_U8:
+ array = PR_Malloc(aSize * sizeof(PRUint8));
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ array = PR_Malloc(aSize * sizeof(PRUint16));
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ array = PR_Malloc(aSize * sizeof(PRUint32));
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ array = PR_Malloc(aSize * sizeof(PRUint64));
+ break;
+
+ case nsXPTType::T_FLOAT:
+ array = PR_Malloc(aSize * sizeof(float));
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ array = PR_Malloc(aSize * sizeof(double));
+ break;
+
+ case nsXPTType::T_BOOL:
+ array = PR_Malloc(aSize * sizeof(PRBool));
+ break;
+
+ case nsXPTType::T_CHAR:
+ array = PR_Malloc(aSize * sizeof(char));
+ break;
+
+ case nsXPTType::T_WCHAR:
+ array = PR_Malloc(aSize * sizeof(PRUnichar));
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_IID:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ array = PR_Malloc(aSize * sizeof(void*));
+ break;
+
+ case nsXPTType::T_VOID:
+ array = PR_Malloc(aSize * sizeof(void*));
+ break;
+
+ default:
+ NS_WARNING("unknown type");
+ return NS_ERROR_FAILURE;
+ }
+
+ if (!array)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = array;
+ return NS_OK;
+}
+
+/**
+ * Handle 'in' and 'inout' params.
+ */
+nsresult
+SetupParams(JNIEnv *env, const jobject aParam, PRUint8 aType, PRBool aIsOut,
+ const nsID& aIID, PRUint8 aArrayType, PRUint32 aArraySize,
+ PRBool aIsArrayElement, PRUint32 aIndex, nsXPTCVariant &aVariant)
+{
+ nsresult rv = NS_OK;
+
+ switch (aType)
+ {
+ case nsXPTType::T_I8:
+ {
+ LOG(("byte\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ aVariant.val.i8 = env->CallByteMethod(aParam, byteValueMID);
+ } else { // 'inout' & 'array'
+ jbyte value;
+ if (aParam) {
+ env->GetByteArrayRegion((jbyteArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ aVariant.val.i8 = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ static_cast<PRInt8*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8: // C++ unsigned octet <=> Java short
+ {
+ LOG(("short\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ jshort value = env->CallShortMethod(aParam, shortValueMID);
+ if (aType == nsXPTType::T_I16)
+ aVariant.val.i16 = value;
+ else
+ aVariant.val.u8 = value;
+ } else { // 'inout' & 'array'
+ jshort value;
+ if (aParam) {
+ env->GetShortArrayRegion((jshortArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ if (aType == nsXPTType::T_I16)
+ aVariant.val.i16 = value;
+ else
+ aVariant.val.u8 = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ if (aType == nsXPTType::T_I16)
+ static_cast<PRInt16*>(aVariant.val.p)[aIndex] = value;
+ else
+ static_cast<PRUint8*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16: // C++ unsigned short <=> Java int
+ {
+ LOG(("int\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ jint value = env->CallIntMethod(aParam, intValueMID);
+ if (aType == nsXPTType::T_I32)
+ aVariant.val.i32 = value;
+ else
+ aVariant.val.u16 = value;
+ } else { // 'inout' & 'array'
+ jint value;
+ if (aParam) {
+ env->GetIntArrayRegion((jintArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ if (aType == nsXPTType::T_I32)
+ aVariant.val.i32 = value;
+ else
+ aVariant.val.u16 = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ if (aType == nsXPTType::T_I32)
+ static_cast<PRInt32*>(aVariant.val.p)[aIndex] = value;
+ else
+ static_cast<PRUint16*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32: // C++ unsigned int <=> Java long
+ {
+ LOG(("long\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ jlong value = env->CallLongMethod(aParam, longValueMID);
+ if (aType == nsXPTType::T_I64)
+ aVariant.val.i64 = value;
+ else
+ aVariant.val.u32 = value;
+ } else { // 'inout' & 'array'
+ jlong value;
+ if (aParam) {
+ env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ if (aType == nsXPTType::T_I64)
+ aVariant.val.i64 = value;
+ else
+ aVariant.val.u32 = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ if (aType == nsXPTType::T_I64)
+ static_cast<PRInt64*>(aVariant.val.p)[aIndex] = value;
+ else
+ static_cast<PRUint32*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_FLOAT:
+ {
+ LOG(("float\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ aVariant.val.f = env->CallFloatMethod(aParam, floatValueMID);
+ } else { // 'inout' & 'array'
+ jfloat value;
+ if (aParam) {
+ env->GetFloatArrayRegion((jfloatArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ aVariant.val.f = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ static_cast<float*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ // XXX how do we handle unsigned 64-bit value?
+ case nsXPTType::T_U64: // C++ unsigned long <=> Java double
+ case nsXPTType::T_DOUBLE:
+ {
+ LOG(("double\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ jdouble value = env->CallDoubleMethod(aParam, doubleValueMID);
+ if (aType == nsXPTType::T_DOUBLE)
+ aVariant.val.d = value;
+ else
+ aVariant.val.u64 = static_cast<PRUint64>(value);
+ } else { // 'inout' & 'array'
+ jdouble value;
+ if (aParam) {
+ env->GetDoubleArrayRegion((jdoubleArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ if (aType == nsXPTType::T_DOUBLE)
+ aVariant.val.d = value;
+ else
+ aVariant.val.u64 = static_cast<PRUint64>(value);
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ if (aType == nsXPTType::T_DOUBLE)
+ static_cast<double*>(aVariant.val.p)[aIndex] = value;
+ else
+ static_cast<PRUint64*>(aVariant.val.p)[aIndex] =
+ static_cast<PRUint64>(value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_BOOL:
+ {
+ LOG(("boolean\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ aVariant.val.b = env->CallBooleanMethod(aParam, booleanValueMID);
+ } else { // 'inout' & 'array'
+ jboolean value;
+ if (aParam) {
+ env->GetBooleanArrayRegion((jbooleanArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ aVariant.val.b = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ static_cast<PRBool*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_CHAR:
+ {
+ LOG(("char\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ aVariant.val.c = env->CallCharMethod(aParam, charValueMID);
+ } else { // 'inout' & 'array'
+ jchar value;
+ if (aParam) {
+ env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ aVariant.val.c = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ static_cast<char*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_WCHAR:
+ {
+ LOG(("char\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ aVariant.val.wc = env->CallCharMethod(aParam, charValueMID);
+ } else { // 'inout' & 'array'
+ jchar value;
+ if (aParam) {
+ env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ aVariant.val.wc = value;
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ static_cast<PRUnichar*>(aVariant.val.p)[aIndex] = value;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ {
+ LOG(("String\n"));
+ jstring data = nsnull;
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ data = (jstring) aParam;
+ } else if (aParam) { // 'inout' & 'array'
+ data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
+ aIndex);
+ }
+
+ void* buf = nsnull;
+ if (data) {
+ jsize uniLength = env->GetStringLength(data);
+ if (uniLength > 0) {
+ if (aType == nsXPTType::T_CHAR_STR) {
+ jsize utf8Length = env->GetStringUTFLength(data);
+ buf = nsMemory::Alloc((utf8Length + 1) * sizeof(char));
+ if (!buf) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ char* char_str = static_cast<char*>(buf);
+ env->GetStringUTFRegion(data, 0, uniLength, char_str);
+ char_str[utf8Length] = '\0';
+
+ } else { // if T_WCHAR_STR
+ buf = nsMemory::Alloc((uniLength + 1) * sizeof(jchar));
+ if (!buf) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ jchar* jchar_str = static_cast<jchar*>(buf);
+ env->GetStringRegion(data, 0, uniLength, jchar_str);
+ jchar_str[uniLength] = '\0';
+ }
+ } else {
+ // create empty string
+ buf = nsMemory::Alloc(2);
+ if (!buf) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ ((jchar*)buf)[0] = '\0';
+ }
+ }
+
+ if (!aIsArrayElement) { // 'in' & 'inout'
+ aVariant.val.p = buf;
+ if (aIsOut) { // 'inout'
+ aVariant.ptr = &aVariant.val;
+ aVariant.SetPtrIsData();
+ }
+ } else { // 'array'
+ if (aType == nsXPTType::T_CHAR_STR) {
+ char* str = static_cast<char*>(buf);
+ static_cast<char**>(aVariant.val.p)[aIndex] = str;
+ } else {
+ PRUnichar* str = static_cast<PRUnichar*>(buf);
+ static_cast<PRUnichar**>(aVariant.val.p)[aIndex] = str;
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_IID:
+ {
+ LOG(("String(IID)\n"));
+ jstring data = nsnull;
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ data = (jstring) aParam;
+ } else if (aParam) { // 'inout' & 'array'
+ data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
+ aIndex);
+ }
+
+ nsID* iid = new nsID;
+ if (!iid) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ if (data) {
+ // extract IID string from Java string
+ const char* str = env->GetStringUTFChars(data, nsnull);
+ if (!str) {
+ delete iid;
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ // parse string into IID object
+ iid->Parse(str);
+ env->ReleaseStringUTFChars(data, str);
+ } else {
+ *iid = nullID;
+ }
+
+ if (!aIsArrayElement) { // 'in' & 'inout'
+ aVariant.val.p = iid;
+ if (aIsOut) { // 'inout'
+ aVariant.ptr = &aVariant.val;
+ aVariant.SetPtrIsData();
+ }
+ } else { // 'array'
+ static_cast<nsID**>(aVariant.val.p)[aIndex] = iid;
+ }
+ break;
+ }
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ LOG(("nsISupports\n"));
+ jobject java_obj = nsnull;
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ java_obj = (jobject) aParam;
+ } else if (aParam) { // 'inout' & 'array'
+ java_obj = (jobject) env->GetObjectArrayElement((jobjectArray) aParam,
+ aIndex);
+ }
+
+ void* xpcom_obj;
+ if (java_obj) {
+ // If the requested interface is nsIWeakReference, then we look for or
+ // create a stub for the nsISupports interface. Then we create a weak
+ // reference from that stub.
+ PRBool isWeakRef;
+ nsID iid;
+ if (aIID.Equals(NS_GET_IID(nsIWeakReference))) {
+ isWeakRef = PR_TRUE;
+ iid = NS_GET_IID(nsISupports);
+ } else {
+ isWeakRef = PR_FALSE;
+ iid = aIID;
+ }
+
+ rv = JavaObjectToNativeInterface(env, java_obj, iid, &xpcom_obj);
+ if (NS_FAILED(rv))
+ break;
+ NS_ENSURE_TRUE(xpcom_obj, NS_ERROR_FAILURE);
+ nsISupports *xpcom_nat_obj = (nsISupports*) xpcom_obj;
+ rv = xpcom_nat_obj->QueryInterface(iid, &xpcom_obj);
+ NS_IF_RELEASE(xpcom_nat_obj);
+ if (NS_FAILED(rv))
+ break;
+
+ // If the function expects a weak reference, then we need to
+ // create it here.
+ if (isWeakRef) {
+ nsISupports* isupports = (nsISupports*) xpcom_obj;
+ nsCOMPtr<nsISupportsWeakReference> supportsweak =
+ do_QueryInterface(isupports);
+ if (supportsweak) {
+ nsWeakPtr weakref;
+ supportsweak->GetWeakReference(getter_AddRefs(weakref));
+ NS_RELEASE(isupports);
+ xpcom_obj = weakref;
+ NS_ADDREF((nsISupports*) xpcom_obj);
+ } else {
+ xpcom_obj = nsnull;
+ }
+ }
+ } else {
+ xpcom_obj = nsnull;
+ }
+
+ if (!aIsArrayElement) { // 'in' & 'inout'
+ aVariant.val.p = xpcom_obj;
+ aVariant.SetValIsInterface();
+ if (aIsOut) { // 'inout'
+ aVariant.ptr = &aVariant.val;
+ aVariant.SetPtrIsData();
+ }
+ } else { // 'array'
+ static_cast<void**>(aVariant.val.p)[aIndex] = xpcom_obj;
+ }
+ break;
+ }
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ LOG(("String\n"));
+ // Expecting only 'in' and 'in dipper'
+ NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
+ if (aIsOut) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ jstring jstr = static_cast<jstring>(aParam);
+ nsAString* str = jstring_to_nsAString(env, jstr);
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ aVariant.val.p = str;
+ aVariant.SetValIsDOMString();
+ break;
+ }
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ LOG(("StringUTF\n"));
+ // Expecting only 'in' and 'in dipper'
+ NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
+ if (aIsOut) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ jstring jstr = static_cast<jstring>(aParam);
+ nsACString* str = jstring_to_nsACString(env, jstr);
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ aVariant.val.p = str;
+ if (aType == nsXPTType::T_CSTRING) {
+ aVariant.SetValIsCString();
+ } else {
+ aVariant.SetValIsUTF8String();
+ }
+ break;
+ }
+
+ // handle "void *" as an "long" in Java
+ case nsXPTType::T_VOID:
+ {
+ LOG(("long (void*)\n"));
+ if (!aIsOut && !aIsArrayElement) { // 'in'
+ aVariant.val.p =
+ reinterpret_cast<void*>(env->CallLongMethod(aParam, longValueMID));
+ } else { // 'inout' & 'array'
+ jlong value;
+ if (aParam) {
+ env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
+ }
+
+ if (aIsOut) { // 'inout'
+ if (aParam) {
+ aVariant.val.p = reinterpret_cast<void*>(value);
+ aVariant.ptr = &aVariant.val;
+ } else {
+ aVariant.ptr = nsnull;
+ }
+ aVariant.SetPtrIsData();
+ } else { // 'array'
+ static_cast<void**>(aVariant.val.p)[aIndex] =
+ reinterpret_cast<void*>(value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_ARRAY:
+ {
+ jobject sourceArray = nsnull;
+ if (!aIsOut) { // 'in'
+ sourceArray = aParam;
+ } else if (aParam) { // 'inout'
+ jobjectArray array = static_cast<jobjectArray>(aParam);
+ sourceArray = env->GetObjectArrayElement(array, 0);
+ }
+
+ if (sourceArray) {
+ rv = CreateNativeArray(aArrayType, aArraySize, &aVariant.val.p);
+
+ for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
+ rv = SetupParams(env, sourceArray, aArrayType, PR_FALSE, aIID, 0, 0,
+ PR_TRUE, i, aVariant);
+ }
+ }
+
+ if (aIsOut) { // 'inout'
+ aVariant.ptr = &aVariant.val.p;
+ aVariant.SetPtrIsData();
+ }
+ break;
+ }
+
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ {
+ NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
+
+ LOG(("Sized string\n"));
+ jstring data = nsnull;
+ if (!aIsOut) { // 'in'
+ data = (jstring) aParam;
+ } else if (aParam) { // 'inout'
+ data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
+ aIndex);
+ }
+
+ PRUint32 length = 0;
+ if (data) {
+ if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
+ length = env->GetStringUTFLength(data);
+ } else {
+ length = env->GetStringLength(data);
+ }
+ if (length > aArraySize) {
+ rv = NS_ERROR_ILLEGAL_VALUE;
+ break;
+ }
+ }
+
+ PRUint32 size_of_char = (aType == nsXPTType::T_PSTRING_SIZE_IS) ?
+ sizeof(char) : sizeof(jchar);
+ PRUint32 allocLength = (aArraySize + 1) * size_of_char;
+ void* buf = nsMemory::Alloc(allocLength);
+ if (!buf) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ if (data) {
+ if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
+ const char* str = env->GetStringUTFChars(data, nsnull);
+ if (!str) {
+ nsMemory::Free(buf);
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ memcpy(buf, str, length);
+ env->ReleaseStringUTFChars(data, str);
+ } else {
+ jchar* jchar_str = static_cast<jchar*>(buf);
+ env->GetStringRegion(data, 0, length, jchar_str);
+ }
+ }
+
+ aVariant.val.p = buf;
+ if (aIsOut) { // 'inout'
+ aVariant.ptr = &aVariant.val;
+ aVariant.SetPtrIsData();
+ }
+
+ break;
+ }
+
+ default:
+ NS_WARNING("unexpected parameter type");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return rv;
+}
+
+/**
+ * Does any cleanup from objects created in SetupParams, as well as converting
+ * any out params to Java.
+ *
+ * NOTE: If aInvokeResult is an error condition, then we just do cleanup in
+ * this function.
+ */
+nsresult
+FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
+ nsXPTCVariant &aVariant, const nsID& aIID,
+ PRBool aIsArrayElement, PRUint8 aArrayType, PRUint32 aArraySize,
+ PRUint32 aIndex, nsresult aInvokeResult, jobject* aParam)
+{
+ nsresult rv = NS_OK;
+
+ switch (aType)
+ {
+ case nsXPTType::T_I8:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jbyte value = aVariant.val.i8;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(byteClass, byteInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetByteArrayRegion((jbyteArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jshort value = (aType == nsXPTType::T_I16) ? aVariant.val.i16 :
+ aVariant.val.u8;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(shortClass, shortInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetShortArrayRegion((jshortArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jint value = (aType == nsXPTType::T_I32) ? aVariant.val.i32 :
+ aVariant.val.u16;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(intClass, intInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetIntArrayRegion((jintArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jlong value = (aType == nsXPTType::T_I64) ? aVariant.val.i64 :
+ aVariant.val.u32;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(longClass, longInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_FLOAT:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jfloat value = aVariant.val.f;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(floatClass, floatInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetFloatArrayRegion((jfloatArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ // XXX how do we handle unsigned 64-bit values?
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jdouble value = (aType == nsXPTType::T_DOUBLE) ? aVariant.val.d :
+ aVariant.val.u64;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(doubleClass, doubleInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetDoubleArrayRegion((jdoubleArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_BOOL:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jboolean value = aVariant.val.b;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(booleanClass, booleanInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetBooleanArrayRegion((jbooleanArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jchar value;
+ if (aType == nsXPTType::T_CHAR)
+ value = aVariant.val.c;
+ else
+ value = aVariant.val.wc;
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(charClass, charInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetCharArrayRegion((jcharArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ {
+ if ((aParamInfo.IsOut() || aIsArrayElement) &&
+ NS_SUCCEEDED(aInvokeResult))
+ {
+ // create new string from data
+ jstring str = nsnull;
+ if (aVariant.val.p) {
+ if (aType == nsXPTType::T_CHAR_STR) {
+ str = env->NewStringUTF((const char*) aVariant.val.p);
+ } else {
+ PRUint32 length = nsCRT::strlen((const PRUnichar*) aVariant.val.p);
+ str = env->NewString((const jchar*) aVariant.val.p, length);
+ }
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = str;
+ } else if (*aParam) {
+ // put new string into output array
+ env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
+ }
+ }
+
+ // cleanup
+ if (aVariant.val.p)
+ nsMemory::Free(aVariant.val.p);
+ break;
+ }
+
+ case nsXPTType::T_IID:
+ {
+ nsID* iid = static_cast<nsID*>(aVariant.val.p);
+
+ if ((aParamInfo.IsOut() || aIsArrayElement) &&
+ NS_SUCCEEDED(aInvokeResult))
+ {
+ // Create the string from nsID
+ jstring str = nsnull;
+ if (iid) {
+ char iid_str[NSID_LENGTH];
+ iid->ToProvidedString(iid_str);
+ str = env->NewStringUTF(iid_str);
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = str;
+ } else if (*aParam) {
+ // put new string into output array
+ env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
+ }
+ }
+
+ // Ordinarily, we would delete 'iid' here. But we cannot do that until
+ // we've handled all of the params. See comment in CallXPCOMMethod.
+ // We can safely delete array elements, though.
+ if (aIsArrayElement)
+ delete iid;
+
+ break;
+ }
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ nsISupports* xpcom_obj = static_cast<nsISupports*>(aVariant.val.p);
+
+ if ((aParamInfo.IsOut() || aIsArrayElement) &&
+ NS_SUCCEEDED(aInvokeResult))
+ {
+ jobject java_obj = nsnull;
+ if (xpcom_obj) {
+ // Get matching Java object for given xpcom object
+ rv = NativeInterfaceToJavaObject(env, xpcom_obj, aIID, nsnull,
+ &java_obj);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = java_obj;
+ } else if (*aParam) {
+ // put new Java object into output array
+ env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, java_obj);
+ }
+ }
+
+ // cleanup
+ NS_IF_RELEASE(xpcom_obj);
+ break;
+ }
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
+ if (!aParamInfo.IsIn()) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ nsString* str = static_cast<nsString*>(aVariant.val.p);
+ if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
+ // Create Java string from returned nsString
+ jstring jstr = nsnull;
+ if (str && !str->IsVoid()) {
+ jstr = env->NewString((const jchar*) str->get(), str->Length());
+ if (!jstr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ *aParam = jstr;
+ }
+
+ // cleanup
+ if (str) {
+ delete str;
+ }
+ break;
+ }
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
+ if (!aParamInfo.IsIn()) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ nsCString* str = static_cast<nsCString*>(aVariant.val.p);
+ if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
+ // Create Java string from returned nsString
+ jstring jstr = nsnull;
+ if (str && !str->IsVoid()) {
+ jstr = env->NewStringUTF((const char*) str->get());
+ if (!jstr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ *aParam = jstr;
+ }
+
+ // cleanup
+ if (str) {
+ delete str;
+ }
+ break;
+ }
+
+ case nsXPTType::T_VOID:
+ {
+ if (NS_SUCCEEDED(aInvokeResult)) {
+ jlong value = reinterpret_cast<jlong>(aVariant.val.p);
+ if (aParamInfo.IsRetval() && !aIsArrayElement) {
+ *aParam = env->NewObject(longClass, longInitMID, value);
+ } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
+ env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_ARRAY:
+ {
+ if (aParamInfo.IsOut() && NS_SUCCEEDED(aInvokeResult)) {
+ // Create Java array from returned native array
+ jobject jarray = nsnull;
+ if (aVariant.val.p) {
+ rv = CreateJavaArray(env, aArrayType, aArraySize, aIID, &jarray);
+ if (NS_FAILED(rv))
+ break;
+
+ nsXPTCVariant var;
+ for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
+ rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
+ if (NS_SUCCEEDED(rv)) {
+ rv = FinalizeParams(env, aParamInfo, aArrayType, var, aIID,
+ PR_TRUE, 0, 0, i, aInvokeResult, &jarray);
+ }
+ }
+ }
+
+ if (aParamInfo.IsRetval()) {
+ *aParam = jarray;
+ } else if (*aParam) {
+ // put new Java array into output array
+ env->SetObjectArrayElement((jobjectArray) *aParam, 0, jarray);
+ }
+ }
+
+ // cleanup
+ // If this is not an out param or if the invokeResult is a failure case,
+ // then the array elements have not been cleaned up. Do so now.
+ if (!aParamInfo.IsOut() || (NS_FAILED(aInvokeResult) && aVariant.val.p)) {
+ nsXPTCVariant var;
+ for (PRUint32 i = 0; i < aArraySize; i++) {
+ rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
+ if (NS_SUCCEEDED(rv)) {
+ FinalizeParams(env, aParamInfo, aArrayType, var, aIID, PR_TRUE,
+ 0, 0, i, NS_ERROR_FAILURE, nsnull);
+ }
+ }
+ }
+ PR_Free(aVariant.val.p);
+ break;
+ }
+
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ {
+ NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
+
+ if ((aParamInfo.IsOut()) && NS_SUCCEEDED(aInvokeResult))
+ {
+ // create new string from data
+ jstring str = nsnull;
+ if (aVariant.val.p) {
+ if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
+ PRUint32 len = (aArraySize + 1) * sizeof(char);
+ char* buf = (char*) nsMemory::Alloc(len);
+ if (buf) {
+ memcpy(buf, aVariant.val.p, len);
+ buf[aArraySize] = '\0';
+ str = env->NewStringUTF((const char*) buf);
+ nsMemory::Free(buf);
+ }
+ } else {
+ str = env->NewString((const jchar*) aVariant.val.p, aArraySize);
+ }
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if (aParamInfo.IsRetval()) {
+ *aParam = str;
+ } else if (*aParam) {
+ // put new string into output array
+ env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
+ }
+ }
+
+ // cleanup
+ if (aVariant.val.p)
+ nsMemory::Free(aVariant.val.p);
+ break;
+ }
+
+ default:
+ NS_WARNING("unexpected parameter type");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Check for Java exception, but don't overwrite pre-existing error code.
+ if (NS_SUCCEEDED(rv) && env->ExceptionCheck())
+ rv = NS_ERROR_FAILURE;
+
+ return rv;
+}
+
+nsresult
+QueryAttributeInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
+ PRBool aCapitalizedAttr, PRUint16* aMethodIndex,
+ const nsXPTMethodInfo** aMethodInfo)
+
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ // An 'attribute' will start with either "get" or "set". But first,
+ // we check the length, in order to skip over method names that match exactly
+ // "get" or "set".
+ if (strlen(aMethodName) > 3) {
+ if (strncmp("get", aMethodName, 3) == 0) {
+ char* getterName = strdup(aMethodName + 3);
+ if (!aCapitalizedAttr) {
+ getterName[0] = tolower(getterName[0]);
+ }
+ rv = aIInfo->GetMethodInfoForName(getterName, aMethodIndex, aMethodInfo);
+ free(getterName);
+ } else if (strncmp("set", aMethodName, 3) == 0) {
+ char* setterName = strdup(aMethodName + 3);
+ if (!aCapitalizedAttr) {
+ setterName[0] = tolower(setterName[0]);
+ }
+ rv = aIInfo->GetMethodInfoForName(setterName, aMethodIndex, aMethodInfo);
+ if (NS_SUCCEEDED(rv)) {
+ // If this succeeded, GetMethodInfoForName will have returned the
+ // method info for the 'getter'. We want the 'setter', so increase
+ // method index by one ('setter' immediately follows the 'getter'),
+ // and get its method info.
+ (*aMethodIndex)++;
+ rv = aIInfo->GetMethodInfo(*aMethodIndex, aMethodInfo);
+ if (NS_SUCCEEDED(rv)) {
+ // Double check that this methodInfo matches the given method.
+ if (!(*aMethodInfo)->IsSetter() ||
+ strcmp(setterName, (*aMethodInfo)->name) != 0) {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ }
+ free(setterName);
+ }
+ }
+
+ return rv;
+}
+
+/**
+ * Given an interface info struct and a method name, returns the method info
+ * and index, if that method exists.
+ *
+ * Most method names are lower case. Unfortunately, the method names of some
+ * interfaces (such as nsIAppShell) start with a capital letter. This function
+ * will try all of the permutations.
+ */
+nsresult
+QueryMethodInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
+ PRUint16* aMethodIndex, const nsXPTMethodInfo** aMethodInfo)
+{
+ // Skip over any leading underscores, since these are methods that conflicted
+ // with existing Java keywords
+ const char* methodName = aMethodName;
+ if (methodName[0] == '_') {
+ methodName++;
+ }
+
+ // The common case is that the method name is lower case, so we check
+ // that first.
+ nsresult rv;
+ rv = aIInfo->GetMethodInfoForName(methodName, aMethodIndex, aMethodInfo);
+ if (NS_SUCCEEDED(rv))
+ return rv;
+
+ // If there is no method called <aMethodName>, then maybe it is an
+ // 'attribute'.
+ rv = QueryAttributeInfo(aIInfo, methodName, PR_FALSE, aMethodIndex,
+ aMethodInfo);
+ if (NS_SUCCEEDED(rv))
+ return rv;
+
+ // If we get here, then maybe the method name is capitalized.
+ char* name = strdup(methodName);
+ name[0] = toupper(name[0]);
+ rv = aIInfo->GetMethodInfoForName(name, aMethodIndex, aMethodInfo);
+ free(name);
+ if (NS_SUCCEEDED(rv))
+ return rv;
+
+ // If there is no method called <aMethodName>, then maybe it is an
+ // 'attribute'.
+ rv = QueryAttributeInfo(aIInfo, methodName, PR_TRUE, aMethodIndex,
+ aMethodInfo);
+
+ return rv;
+}
+
+#ifdef VBOX
+#include <nsIExceptionService.h>
+#include <iprt/err.h>
+#include "nspr.h"
+
+static void makeErrorMessage(nsresult r, char* msg, size_t msgSize)
+{
+ bool gotMsg = false;
+
+ if (!gotMsg)
+ {
+ nsresult rc;
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
+ if (NS_SUCCEEDED (rc))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+ if (NS_SUCCEEDED (rc))
+ {
+ nsCOMPtr <nsIException> ex;
+ rc = em->GetCurrentException(getter_AddRefs (ex));
+ if (NS_SUCCEEDED (rc) && ex)
+ {
+ nsXPIDLCString emsg;
+ ex->GetMessage(getter_Copies(emsg));
+ PR_snprintf(msg, msgSize, "%s",
+ emsg.get());
+ gotMsg = true;
+ }
+ }
+ }
+ }
+
+ if (!gotMsg)
+ {
+ const RTCOMERRMSG* pMsg = RTErrCOMGet(r);
+ if (strncmp(pMsg->pszMsgFull, "Unknown", 7) != 0)
+ {
+ PR_snprintf(msg, msgSize, "%s (%s)",
+ pMsg->pszMsgFull, pMsg->pszDefine);
+ gotMsg = true;
+ }
+ }
+
+ if (!gotMsg)
+ {
+ PR_snprintf(msg, msgSize, "Error 0x%x in module 0x%x",
+ NS_ERROR_GET_CODE(r), NS_ERROR_GET_MODULE(r));
+ }
+}
+#endif
+
+/**
+ * org.mozilla.xpcom.XPCOMJavaProxy.internal.callXPCOMMethod
+ */
+extern "C" NS_EXPORT jobject JNICALL
+JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
+ jstring aMethodName, jobjectArray aParams)
+{
+ nsresult rv;
+
+ // Get native XPCOM instance
+ void* xpcom_obj;
+ rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
+ if (NS_FAILED(rv)) {
+ ThrowException(env, 0, "Failed to get matching XPCOM object");
+ return nsnull;
+ }
+ JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
+
+ // Get method info
+ PRUint16 methodIndex;
+ const nsXPTMethodInfo* methodInfo;
+ nsIInterfaceInfo* iinfo = inst->InterfaceInfo();
+ const char* methodName = env->GetStringUTFChars(aMethodName, nsnull);
+ rv = QueryMethodInfo(iinfo, methodName, &methodIndex, &methodInfo);
+ env->ReleaseStringUTFChars(aMethodName, methodName);
+
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "GetMethodInfoForName failed");
+ return nsnull;
+ }
+
+#ifdef DEBUG_JAVAXPCOM
+ const char* ifaceName;
+ iinfo->GetNameShared(&ifaceName);
+ LOG(("===> (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
+#endif
+
+ // Convert the Java params
+ PRUint8 paramCount = methodInfo->GetParamCount();
+ nsXPTCVariant* params = nsnull;
+ if (paramCount)
+ {
+ params = new nsXPTCVariant[paramCount];
+ if (!params) {
+ ThrowException(env, NS_ERROR_OUT_OF_MEMORY, "Can't create params array");
+ return nsnull;
+ }
+ memset(params, 0, paramCount * sizeof(nsXPTCVariant));
+
+ PRBool foundDependentParam = PR_FALSE;
+ for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
+ {
+ LOG(("\t Param %d: ", i));
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+ params[i].type = paramInfo.GetType();
+
+ if (params[i].type.IsDependent() && paramInfo.IsIn()) {
+ foundDependentParam = PR_TRUE;
+ continue;
+ }
+
+ if (paramInfo.IsIn()) {
+ PRUint8 type = params[i].type.TagPart();
+
+ // get IID for interface params
+ nsID iid;
+ if (type == nsXPTType::T_INTERFACE) {
+ rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
+ methodIndex, params, PR_TRUE, iid);
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject param = nsnull;
+ if (aParams && !paramInfo.IsRetval()) {
+ param = env->GetObjectArrayElement(aParams, i);
+ }
+ rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, 0, 0,
+ PR_FALSE, 0, params[i]);
+ }
+ } else {
+ LOG(("out/retval\n"));
+ params[i].ptr = &(params[i].val);
+ params[i].SetPtrIsData();
+ }
+ }
+
+ // Handle any dependent params by doing a second pass
+ if (foundDependentParam) {
+
+ for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++) {
+
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
+ params[j].type = paramInfo.GetType();
+
+ if (!params[j].type.IsDependent())
+ continue;
+
+ if (paramInfo.IsIn()) {
+ PRUint8 type = params[j].type.TagPart();
+
+ // is paramater an array or sized string?
+ PRUint8 arrayType = 0;
+ PRUint32 arraySize = 0;
+ PRBool isArray = params[j].type.IsArray();
+ PRBool isSizedString = isArray ? PR_FALSE :
+ type == nsXPTType::T_PSTRING_SIZE_IS ||
+ type == nsXPTType::T_PWSTRING_SIZE_IS;
+
+ if (isArray) {
+ // get array type
+ nsXPTType xpttype;
+ rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);
+ if (NS_FAILED(rv))
+ break;
+ arrayType = xpttype.TagPart();
+ // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
+ // therefore, treat as a signed 8bit value
+ if (arrayType == nsXPTType::T_U8)
+ arrayType = nsXPTType::T_I8;
+ }
+
+ if (isArray || isSizedString) {
+ // get size of array or string
+ PRUint8 argnum;
+ rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
+ &argnum);
+ if (NS_FAILED(rv))
+ break;
+ arraySize = params[argnum].val.u32;
+ }
+
+ // get IID for interface params
+ nsID iid;
+ if (type == nsXPTType::T_INTERFACE_IS ||
+ (type == nsXPTType::T_ARRAY &&
+ (arrayType == nsXPTType::T_INTERFACE ||
+ arrayType == nsXPTType::T_INTERFACE_IS)))
+ {
+ PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
+ rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
+ methodIndex, params, PR_TRUE, iid);
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject param = nsnull;
+ if (aParams && !paramInfo.IsRetval()) {
+ param = env->GetObjectArrayElement(aParams, j);
+ }
+ rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, arrayType,
+ arraySize, PR_FALSE, 0, params[j]);
+ }
+ }
+ }
+ }
+
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "SetupParams failed");
+ return nsnull;
+ }
+ }
+
+ // Call the XPCOM method
+ const nsIID* iid;
+ iinfo->GetIIDShared(&iid);
+ nsISupports* realObject;
+ rv = inst->GetInstance()->QueryInterface(*iid, (void**) &realObject);
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "Failed to get real XPCOM object");
+ return nsnull;
+ }
+ nsresult invokeResult = NS_InvokeByIndex(realObject, methodIndex,
+ paramCount, params);
+ NS_RELEASE(realObject);
+
+ // Clean up params
+ jobject result = nsnull;
+ for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
+ {
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
+ PRUint8 type = paramInfo.GetType().TagPart();
+
+ // is paramater an array or sized string?
+ PRUint8 arrayType = 0;
+ PRUint32 arraySize = 0;
+ PRBool isArray = params[i].type.IsArray();
+ PRBool isSizedString = isArray ? PR_FALSE :
+ type == nsXPTType::T_PSTRING_SIZE_IS ||
+ type == nsXPTType::T_PWSTRING_SIZE_IS;
+
+ if (isArray) {
+ // get array type
+ nsXPTType array_xpttype;
+ rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &array_xpttype);
+ if (NS_FAILED(rv))
+ break;
+ arrayType = array_xpttype.TagPart();
+ // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
+ // therefore, treat as a signed 8bit value
+ if (arrayType == nsXPTType::T_U8)
+ arrayType = nsXPTType::T_I8;
+ }
+
+ if (isArray || isSizedString) {
+ // get size of array
+ PRUint8 argnum;
+ rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
+ &argnum);
+ if (NS_FAILED(rv))
+ break;
+ arraySize = params[argnum].val.u32;
+ }
+
+ // get IID for interface params
+ nsID iid;
+ if (type == nsXPTType::T_INTERFACE || type == nsXPTType::T_INTERFACE_IS ||
+ (type == nsXPTType::T_ARRAY && (arrayType == nsXPTType::T_INTERFACE ||
+ arrayType == nsXPTType::T_INTERFACE_IS)))
+ {
+ PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
+ rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
+ methodIndex, params, PR_TRUE, iid);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ jobject* javaElement;
+ jobject element = nsnull;
+ if (!paramInfo.IsRetval()) {
+ element = env->GetObjectArrayElement(aParams, i);
+ javaElement = &element;
+ } else {
+ javaElement = &result;
+ }
+ rv = FinalizeParams(env, paramInfo, type, params[i], iid, PR_FALSE,
+ arrayType, arraySize, 0, invokeResult, javaElement);
+ }
+
+ // Normally, we would delete any created nsID object in the above loop.
+ // However, GetIIDForMethodParam may need some of the nsID params when it's
+ // looking for the IID of an INTERFACE_IS. Therefore, we can't delete it
+ // until we've gone through the 'Finalize' loop once and created the result.
+ for (PRUint8 j = 0; j < paramCount; j++)
+ {
+ const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
+ const nsXPTType &type = paramInfo.GetType();
+ if (type.TagPart() == nsXPTType::T_IID) {
+ nsID* iid = (nsID*) params[j].val.p;
+ delete iid;
+ }
+ }
+
+ if (params) {
+ delete params;
+ }
+
+ // If the XPCOM method invocation failed, we don't immediately throw an
+ // exception and return so that we can clean up any parameters.
+ if (NS_FAILED(invokeResult)) {
+ nsCAutoString message("The function \"");
+ message.AppendASCII(methodInfo->GetName());
+ message.AppendLiteral("\" returned an error condition");
+#ifdef VBOX
+ char vboxMsg[1024];
+ message.AppendLiteral(": \"");
+ makeErrorMessage(invokeResult, vboxMsg, sizeof vboxMsg);
+ message.AppendASCII(vboxMsg);
+ message.AppendLiteral("\"");
+#endif
+ ThrowException(env, invokeResult, message.get());
+ }
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "FinalizeParams failed");
+ return nsnull;
+ }
+
+ LOG(("<=== (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
+ return result;
+}
+
+nsresult
+GetNewOrUsedJavaWrapper(JNIEnv* env, nsISupports* aXPCOMObject,
+ const nsIID& aIID, jobject aObjectLoader,
+ jobject* aResult)
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ // Get the root nsISupports of the xpcom object
+ nsresult rv;
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(aXPCOMObject, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Get associated Java object from hash table
+ rv = gNativeToJavaProxyMap->Find(env, rootObject, aIID, aResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (*aResult)
+ return NS_OK;
+
+ // No Java object is associated with the given XPCOM object, so we
+ // create a Java proxy.
+
+ nsCOMPtr<nsIInterfaceInfoManager>
+ iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ NS_ASSERTION(iim, "Failed to get InterfaceInfoManager");
+ if (!iim)
+ return NS_ERROR_FAILURE;
+
+ // Get interface info for class
+ nsCOMPtr<nsIInterfaceInfo> info;
+ rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Wrap XPCOM object (addrefs rootObject)
+ JavaXPCOMInstance* inst = new JavaXPCOMInstance(rootObject, info);
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Get interface name
+ const char* iface_name;
+ rv = info->GetNameShared(&iface_name);
+
+ if (NS_SUCCEEDED(rv)) {
+ jobject java_obj = nsnull;
+
+ // Create proper Java interface name
+ nsCAutoString class_name("org.mozilla.interfaces.");
+ class_name.AppendASCII(iface_name);
+ jclass ifaceClass = FindClassInLoader(env, aObjectLoader, class_name.get());
+
+ if (ifaceClass) {
+ java_obj = env->CallStaticObjectMethod(xpcomJavaProxyClass,
+ createProxyMID, ifaceClass,
+ reinterpret_cast<jlong>(inst));
+ if (env->ExceptionCheck())
+ java_obj = nsnull;
+ }
+
+ if (java_obj) {
+#ifdef DEBUG_JAVAXPCOM
+ char* iid_str = aIID.ToString();
+ LOG(("+ CreateJavaProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
+ java_obj),
+ (PRUint32) rootObject, iid_str));
+ PR_Free(iid_str);
+#endif
+
+ // Associate XPCOM object with Java proxy
+ rv = gNativeToJavaProxyMap->Add(env, rootObject, aIID, java_obj);
+ if (NS_SUCCEEDED(rv)) {
+ *aResult = java_obj;
+ return NS_OK;
+ }
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+
+ // If there was an error, clean up.
+ delete inst;
+ return rv;
+}
+
+nsresult
+GetXPCOMInstFromProxy(JNIEnv* env, jobject aJavaObject, void** aResult)
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ jlong xpcom_obj = env->CallStaticLongMethod(xpcomJavaProxyClass,
+ getNativeXPCOMInstMID, aJavaObject);
+
+ if (!xpcom_obj || env->ExceptionCheck()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = reinterpret_cast<void*>(xpcom_obj);
+#ifdef DEBUG_JAVAXPCOM
+ JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(*aResult);
+ nsIID* iid;
+ inst->InterfaceInfo()->GetInterfaceIID(&iid);
+ char* iid_str = iid->ToString();
+ LOG(("< GetXPCOMInstFromProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
+ aJavaObject),
+ (PRUint32) inst->GetInstance(), iid_str));
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+#endif
+ return NS_OK;
+}
+
+/**
+ * org.mozilla.xpcom.internal.XPCOMJavaProxy.finalizeProxy
+ */
+extern "C" NS_EXPORT void JNICALL
+JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy)
+{
+#ifdef DEBUG_JAVAXPCOM
+ PRUint32 xpcom_addr = 0;
+#endif
+
+ // Due to Java's garbage collection, this finalize statement may get called
+ // after FreeJavaGlobals(). So check to make sure that everything is still
+ // initialized.
+ if (gJavaXPCOMLock) {
+ nsAutoLock lock(gJavaXPCOMLock);
+
+ // If may be possible for the lock to be acquired here when FreeGlobals is
+ // in the middle of running. If so, then this thread will sleep until
+ // FreeGlobals releases its lock. At that point, we resume this thread
+ // here, but JavaXPCOM may no longer be initialized. So we need to check
+ // that everything is legit after acquiring the lock.
+ if (gJavaXPCOMInitialized) {
+ // Get native XPCOM instance
+ void* xpcom_obj;
+ nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
+ if (NS_SUCCEEDED(rv)) {
+ JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
+#ifdef DEBUG_JAVAXPCOM
+ xpcom_addr = reinterpret_cast<PRUint32>(inst->GetInstance());
+#endif
+ nsIID* iid;
+ rv = inst->InterfaceInfo()->GetInterfaceIID(&iid);
+ if (NS_SUCCEEDED(rv)) {
+ rv = gNativeToJavaProxyMap->Remove(env, inst->GetInstance(), *iid);
+ nsMemory::Free(iid);
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to RemoveJavaProxy");
+ // Release gJavaXPCOMLock before deleting inst (see bug 340022)
+ lock.unlock();
+ delete inst;
+ }
+ }
+ }
+
+#ifdef DEBUG_JAVAXPCOM
+ LOG(("- Finalize (Java=%08x | XPCOM=%08x)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
+ aJavaProxy),
+ xpcom_addr));
+#endif
+}
+
+/**
+ * org.mozilla.xpcom.XPCOMJavaProxy.isSameXPCOMObject
+ */
+extern "C" NS_EXPORT jboolean JNICALL
+JAVAPROXY_NATIVE(isSameXPCOMObject) (JNIEnv *env, jclass that,
+ jobject aProxy1, jobject aProxy2)
+{
+ void* xpcom_obj1;
+ nsresult rv = GetXPCOMInstFromProxy(env, aProxy1, &xpcom_obj1);
+ if (NS_SUCCEEDED(rv)) {
+ void* xpcom_obj2;
+ rv = GetXPCOMInstFromProxy(env, aProxy2, &xpcom_obj2);
+ if (NS_SUCCEEDED(rv)) {
+ JavaXPCOMInstance* inst1 = static_cast<JavaXPCOMInstance*>(xpcom_obj1);
+ JavaXPCOMInstance* inst2 = static_cast<JavaXPCOMInstance*>(xpcom_obj2);
+ if (inst1->GetInstance() == inst2->GetInstance()) {
+ return JNI_TRUE;
+ }
+ }
+ }
+ return JNI_FALSE;
+}
+
+/**
+ * org.mozilla.xpcom.ProfileLock.release
+ */
+extern "C" NS_EXPORT void JNICALL
+LOCKPROXY_NATIVE(release) (JNIEnv *env, jclass that, jlong aLockObject)
+{
+ // Need to release object on the main thread.
+ nsresult rv = NS_ERROR_FAILURE;
+#ifdef VBOX
+ rv = NS_ProxyRelease(do_GetMainThreadQueue().get(), reinterpret_cast<nsISupports*>(aLockObject));
+#else
+ nsCOMPtr<nsIThread> thread = do_GetMainThread();
+ if (thread) {
+ rv = NS_ProxyRelease(thread, reinterpret_cast<nsISupports*>(aLockObject));
+ }
+#endif
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease");
+}
diff --git a/src/libs/xpcom18a4/java/src/nsJavaWrapper.h b/src/libs/xpcom18a4/java/src/nsJavaWrapper.h
new file mode 100644
index 00000000..c441a41c
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaWrapper.h
@@ -0,0 +1,75 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+#ifndef _nsJavaWrapper_h_
+#define _nsJavaWrapper_h_
+
+#include "jni.h"
+#include "nsISupports.h"
+
+
+/**
+ * Finds the associated Java wraper for the given XPCOM object and IID. If no
+ * such Java wrapper exists, then a new one is created.
+ *
+ * @param env Java environment pointer
+ * @param aXPCOMObject XPCOM object for which to find/create Java wrapper
+ * @param aIID desired interface IID for Java wrapper
+ * @param aObjectLoader Java wrapper whose class loader we use for finding
+ * classes; can be null
+ * @param aResult on success, holds reference to Java wrapper
+ *
+ * @return NS_OK if succeeded; all other return values are error codes.
+ */
+nsresult GetNewOrUsedJavaWrapper(JNIEnv* env, nsISupports* aXPCOMObject,
+ const nsIID& aIID, jobject aObjectLoader,
+ jobject* aResult);
+
+/**
+ * Returns the XPCOM object for which the given Java proxy was created.
+ *
+ * @param env pointer to Java context
+ * @param aJavaObject a Java proxy created by CreateJavaProxy()
+ * @param aResult on exit, holds pointer to XPCOM instance
+ *
+ * @return NS_OK if the XPCOM object was successfully retrieved;
+ * any other value denotes an error condition.
+ */
+nsresult GetXPCOMInstFromProxy(JNIEnv* env, jobject aJavaObject,
+ void** aResult);
+
+#endif // _nsJavaWrapper_h_
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.cpp b/src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.cpp
new file mode 100644
index 00000000..f91fdd83
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.cpp
@@ -0,0 +1,1084 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsJavaXPCOMBindingUtils.h"
+#include "nsJavaXPTCStub.h"
+#include "nsJavaWrapper.h"
+#include "jni.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsThreadUtils.h"
+#include "nsProxyRelease.h"
+#ifdef VBOX
+#ifndef NS_INT32_TO_PTR
+#define NS_INT32_TO_PTR(x) ((void *)((char *)0 + (x)))
+#endif
+#endif
+
+
+/* Java JNI globals */
+
+JavaVM* gCachedJVM = nsnull;
+
+jclass systemClass = nsnull;
+jclass booleanClass = nsnull;
+jclass charClass = nsnull;
+jclass byteClass = nsnull;
+jclass shortClass = nsnull;
+jclass intClass = nsnull;
+jclass longClass = nsnull;
+jclass floatClass = nsnull;
+jclass doubleClass = nsnull;
+jclass stringClass = nsnull;
+jclass nsISupportsClass = nsnull;
+jclass xpcomExceptionClass = nsnull;
+jclass xpcomJavaProxyClass = nsnull;
+jclass weakReferenceClass = nsnull;
+jclass javaXPCOMUtilsClass = nsnull;
+
+jmethodID hashCodeMID = nsnull;
+jmethodID booleanValueMID = nsnull;
+jmethodID booleanInitMID = nsnull;
+jmethodID charValueMID = nsnull;
+jmethodID charInitMID = nsnull;
+jmethodID byteValueMID = nsnull;
+jmethodID byteInitMID = nsnull;
+jmethodID shortValueMID = nsnull;
+jmethodID shortInitMID = nsnull;
+jmethodID intValueMID = nsnull;
+jmethodID intInitMID = nsnull;
+jmethodID longValueMID = nsnull;
+jmethodID longInitMID = nsnull;
+jmethodID floatValueMID = nsnull;
+jmethodID floatInitMID = nsnull;
+jmethodID doubleValueMID = nsnull;
+jmethodID doubleInitMID = nsnull;
+jmethodID createProxyMID = nsnull;
+jmethodID isXPCOMJavaProxyMID = nsnull;
+jmethodID getNativeXPCOMInstMID = nsnull;
+jmethodID weakReferenceConstructorMID = nsnull;
+jmethodID getReferentMID = nsnull;
+jmethodID clearReferentMID = nsnull;
+jmethodID findClassInLoaderMID = nsnull;
+
+#ifdef DEBUG_JAVAXPCOM
+jmethodID getNameMID = nsnull;
+jmethodID proxyToStringMID = nsnull;
+#endif
+
+NativeToJavaProxyMap* gNativeToJavaProxyMap = nsnull;
+JavaToXPTCStubMap* gJavaToXPTCStubMap = nsnull;
+
+PRBool gJavaXPCOMInitialized = PR_FALSE;
+PRLock* gJavaXPCOMLock = nsnull;
+
+static const char* kJavaKeywords[] = {
+ "abstract", "default" , "if" , "private" , "throw" ,
+ "boolean" , "do" , "implements", "protected" , "throws" ,
+ "break" , "double" , "import", "public" , "transient" ,
+ "byte" , "else" , "instanceof", "return" , "try" ,
+ "case" , "extends" , "int" , "short" , "void" ,
+ "catch" , "final" , "interface" , "static" , "volatile" ,
+ "char" , "finally" , "long" , "super" , "while" ,
+ "class" , "float" , "native" , "switch" ,
+ "const" , "for" , "new" , "synchronized",
+ "continue", "goto" , "package" , "this" ,
+ /* added in Java 1.2 */
+ "strictfp",
+ /* added in Java 1.4 */
+ "assert" ,
+ /* added in Java 5.0 */
+ "enum" ,
+ /* Java constants */
+ "true" , "false" , "null" ,
+ /* java.lang.Object methods *
+ * - don't worry about "toString", since it does the same thing *
+ * as Object's "toString" */
+ "clone" , "equals" , "finalize" , "getClass" , "hashCode" ,
+ "notify" , "notifyAll", /*"toString" ,*/ "wait"
+};
+
+nsTHashtable<nsDepCharHashKey>* gJavaKeywords = nsnull;
+
+
+/******************************
+ * InitializeJavaGlobals
+ ******************************/
+PRBool
+InitializeJavaGlobals(JNIEnv *env)
+{
+ if (gJavaXPCOMInitialized)
+ return PR_TRUE;
+
+ // Save pointer to JavaVM, which is valid across threads.
+ jint rc = env->GetJavaVM(&gCachedJVM);
+ if (rc != 0) {
+ NS_WARNING("Failed to get JavaVM");
+ goto init_error;
+ }
+
+ jclass clazz;
+ if (!(clazz = env->FindClass("java/lang/System")) ||
+ !(systemClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(hashCodeMID = env->GetStaticMethodID(clazz, "identityHashCode",
+ "(Ljava/lang/Object;)I")))
+ {
+ NS_WARNING("Problem creating java.lang.System globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Boolean")) ||
+ !(booleanClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(booleanValueMID = env->GetMethodID(clazz, "booleanValue", "()Z")) ||
+ !(booleanInitMID = env->GetMethodID(clazz, "<init>", "(Z)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Boolean globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Character")) ||
+ !(charClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(charValueMID = env->GetMethodID(clazz, "charValue", "()C")) ||
+ !(charInitMID = env->GetMethodID(clazz, "<init>", "(C)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Character globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Byte")) ||
+ !(byteClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(byteValueMID = env->GetMethodID(clazz, "byteValue", "()B")) ||
+ !(byteInitMID = env->GetMethodID(clazz, "<init>", "(B)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Byte globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Short")) ||
+ !(shortClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(shortValueMID = env->GetMethodID(clazz, "shortValue", "()S")) ||
+ !(shortInitMID = env->GetMethodID(clazz, "<init>", "(S)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Short globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Integer")) ||
+ !(intClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(intValueMID = env->GetMethodID(clazz, "intValue", "()I")) ||
+ !(intInitMID = env->GetMethodID(clazz, "<init>", "(I)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Integer globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Long")) ||
+ !(longClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(longValueMID = env->GetMethodID(clazz, "longValue", "()J")) ||
+ !(longInitMID = env->GetMethodID(clazz, "<init>", "(J)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Long globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Float")) ||
+ !(floatClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(floatValueMID = env->GetMethodID(clazz, "floatValue", "()F")) ||
+ !(floatInitMID = env->GetMethodID(clazz, "<init>", "(F)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Float globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/Double")) ||
+ !(doubleClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(doubleValueMID = env->GetMethodID(clazz, "doubleValue", "()D")) ||
+ !(doubleInitMID = env->GetMethodID(clazz, "<init>", "(D)V")))
+ {
+ NS_WARNING("Problem creating java.lang.Double globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/String")) ||
+ !(stringClass = (jclass) env->NewGlobalRef(clazz)))
+ {
+ NS_WARNING("Problem creating java.lang.String globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("org/mozilla/interfaces/nsISupports")) ||
+ !(nsISupportsClass = (jclass) env->NewGlobalRef(clazz)))
+ {
+ NS_WARNING("Problem creating org.mozilla.interfaces.nsISupports globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("org/mozilla/xpcom/XPCOMException")) ||
+ !(xpcomExceptionClass = (jclass) env->NewGlobalRef(clazz)))
+ {
+ NS_WARNING("Problem creating org.mozilla.xpcom.XPCOMException globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMJavaProxy")) ||
+ !(xpcomJavaProxyClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(createProxyMID = env->GetStaticMethodID(clazz, "createProxy",
+ "(Ljava/lang/Class;J)Ljava/lang/Object;")) ||
+ !(isXPCOMJavaProxyMID = env->GetStaticMethodID(clazz, "isXPCOMJavaProxy",
+ "(Ljava/lang/Object;)Z")) ||
+ !(getNativeXPCOMInstMID = env->GetStaticMethodID(xpcomJavaProxyClass,
+ "getNativeXPCOMInstance",
+ "(Ljava/lang/Object;)J")))
+ {
+ NS_WARNING("Problem creating org.mozilla.xpcom.internal.XPCOMJavaProxy globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("java/lang/ref/WeakReference")) ||
+ !(weakReferenceClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(weakReferenceConstructorMID = env->GetMethodID(weakReferenceClass,
+ "<init>","(Ljava/lang/Object;)V")) ||
+ !(getReferentMID = env->GetMethodID(weakReferenceClass,
+ "get", "()Ljava/lang/Object;")) ||
+ !(clearReferentMID = env->GetMethodID(weakReferenceClass,
+ "clear", "()V")))
+ {
+ NS_WARNING("Problem creating java.lang.ref.WeakReference globals");
+ goto init_error;
+ }
+
+ if (!(clazz = env->FindClass("org/mozilla/xpcom/internal/JavaXPCOMMethods")) ||
+ !(javaXPCOMUtilsClass = (jclass) env->NewGlobalRef(clazz)) ||
+ !(findClassInLoaderMID = env->GetStaticMethodID(clazz,
+ "findClassInLoader",
+ "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Class;")))
+ {
+ NS_WARNING("Problem creating org.mozilla.xpcom.internal.JavaXPCOMMethods globals");
+ goto init_error;
+ }
+
+#ifdef DEBUG_JAVAXPCOM
+ if (!(clazz = env->FindClass("java/lang/Class")) ||
+ !(getNameMID = env->GetMethodID(clazz, "getName","()Ljava/lang/String;")))
+ {
+ NS_WARNING("Problem creating java.lang.Class globals");
+ goto init_error;
+ }
+
+ if (!(proxyToStringMID = env->GetStaticMethodID(xpcomJavaProxyClass,
+ "proxyToString",
+ "(Ljava/lang/Object;)Ljava/lang/String;")))
+ {
+ NS_WARNING("Problem creating proxyToString global");
+ goto init_error;
+ }
+#endif
+
+ gNativeToJavaProxyMap = new NativeToJavaProxyMap();
+ if (!gNativeToJavaProxyMap || NS_FAILED(gNativeToJavaProxyMap->Init())) {
+ NS_WARNING("Problem creating NativeToJavaProxyMap");
+ goto init_error;
+ }
+ gJavaToXPTCStubMap = new JavaToXPTCStubMap();
+ if (!gJavaToXPTCStubMap || NS_FAILED(gJavaToXPTCStubMap->Init())) {
+ NS_WARNING("Problem creating JavaToXPTCStubMap");
+ goto init_error;
+ }
+
+ {
+ nsresult rv = NS_OK;
+ PRUint32 size = NS_ARRAY_LENGTH(kJavaKeywords);
+ gJavaKeywords = new nsTHashtable<nsDepCharHashKey>();
+ if (!gJavaKeywords || NS_FAILED(gJavaKeywords->Init(size))) {
+ NS_WARNING("Failed to init JavaKeywords HashSet");
+ goto init_error;
+ }
+ for (PRUint32 i = 0; i < size && NS_SUCCEEDED(rv); i++) {
+ if (!gJavaKeywords->PutEntry(kJavaKeywords[i])) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to populate JavaKeywords hash");
+ goto init_error;
+ }
+ }
+
+ gJavaXPCOMLock = PR_NewLock();
+ gJavaXPCOMInitialized = PR_TRUE;
+ return PR_TRUE;
+
+init_error:
+ // If we encounter an error during initialization, then free any globals that
+ // were allocated, and return false.
+ FreeJavaGlobals(env);
+ return PR_FALSE;
+}
+
+/*************************
+ * FreeJavaGlobals
+ *************************/
+void
+FreeJavaGlobals(JNIEnv* env)
+{
+ PRLock* tempLock = nsnull;
+ if (gJavaXPCOMLock) {
+ PR_Lock(gJavaXPCOMLock);
+
+ // null out global lock so no one else can use it
+ tempLock = gJavaXPCOMLock;
+ gJavaXPCOMLock = nsnull;
+ }
+
+ gJavaXPCOMInitialized = PR_FALSE;
+
+ // Free the mappings first, since that process depends on some of the Java
+ // globals that are freed later.
+ if (gNativeToJavaProxyMap) {
+ gNativeToJavaProxyMap->Destroy(env);
+ delete gNativeToJavaProxyMap;
+ gNativeToJavaProxyMap = nsnull;
+ }
+ if (gJavaToXPTCStubMap) {
+ gJavaToXPTCStubMap->Destroy();
+ delete gJavaToXPTCStubMap;
+ gJavaToXPTCStubMap = nsnull;
+ }
+
+ // Free remaining Java globals
+ if (systemClass) {
+ env->DeleteGlobalRef(systemClass);
+ systemClass = nsnull;
+ }
+ if (booleanClass) {
+ env->DeleteGlobalRef(booleanClass);
+ booleanClass = nsnull;
+ }
+ if (charClass) {
+ env->DeleteGlobalRef(charClass);
+ charClass = nsnull;
+ }
+ if (byteClass) {
+ env->DeleteGlobalRef(byteClass);
+ byteClass = nsnull;
+ }
+ if (shortClass) {
+ env->DeleteGlobalRef(shortClass);
+ shortClass = nsnull;
+ }
+ if (intClass) {
+ env->DeleteGlobalRef(intClass);
+ intClass = nsnull;
+ }
+ if (longClass) {
+ env->DeleteGlobalRef(longClass);
+ longClass = nsnull;
+ }
+ if (floatClass) {
+ env->DeleteGlobalRef(floatClass);
+ floatClass = nsnull;
+ }
+ if (doubleClass) {
+ env->DeleteGlobalRef(doubleClass);
+ doubleClass = nsnull;
+ }
+ if (stringClass) {
+ env->DeleteGlobalRef(stringClass);
+ stringClass = nsnull;
+ }
+ if (nsISupportsClass) {
+ env->DeleteGlobalRef(nsISupportsClass);
+ nsISupportsClass = nsnull;
+ }
+ if (xpcomExceptionClass) {
+ env->DeleteGlobalRef(xpcomExceptionClass);
+ xpcomExceptionClass = nsnull;
+ }
+ if (xpcomJavaProxyClass) {
+ env->DeleteGlobalRef(xpcomJavaProxyClass);
+ xpcomJavaProxyClass = nsnull;
+ }
+ if (weakReferenceClass) {
+ env->DeleteGlobalRef(weakReferenceClass);
+ weakReferenceClass = nsnull;
+ }
+
+ if (gJavaKeywords) {
+ delete gJavaKeywords;
+ gJavaKeywords = nsnull;
+ }
+
+ if (tempLock) {
+ PR_Unlock(tempLock);
+ PR_DestroyLock(tempLock);
+ }
+}
+
+
+/**************************************
+ * Java<->XPCOM object mappings
+ **************************************/
+
+// NativeToJavaProxyMap: The common case is that each XPCOM object will have
+// one Java proxy. But there are instances where there will be multiple Java
+// proxies for a given XPCOM object, each representing a different interface.
+// So we optimize the common case by using a hash table. Then, if there are
+// multiple Java proxies, we cycle through the linked list, comparing IIDs.
+
+nsresult
+NativeToJavaProxyMap::Init()
+{
+ mHashTable = PL_NewDHashTable(PL_DHashGetStubOps(), nsnull,
+ sizeof(Entry), 16);
+ if (!mHashTable)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+PLDHashOperator
+DestroyJavaProxyMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
+ PRUint32 aNumber, void* aData)
+{
+ JNIEnv* env = static_cast<JNIEnv*>(aData);
+ NativeToJavaProxyMap::Entry* entry =
+ static_cast<NativeToJavaProxyMap::Entry*>(aHeader);
+
+ // first, delete XPCOM instances from the Java proxies
+ nsresult rv;
+ NativeToJavaProxyMap::ProxyList* item = entry->list;
+ while(item != nsnull) {
+ void* xpcom_obj;
+ jobject javaObject = env->CallObjectMethod(item->javaObject, getReferentMID);
+ rv = GetXPCOMInstFromProxy(env, javaObject, &xpcom_obj);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get XPCOM instance from Java proxy");
+
+ if (NS_SUCCEEDED(rv)) {
+ JavaXPCOMInstance* inst = static_cast<JavaXPCOMInstance*>(xpcom_obj);
+#ifdef DEBUG_JAVAXPCOM
+ char* iid_str = item->iid.ToString();
+ LOG(("- NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
+ javaObject),
+ (PRUint32) entry, iid_str));
+ PR_Free(iid_str);
+#endif
+ delete inst; // releases native XPCOM object
+ }
+
+ NativeToJavaProxyMap::ProxyList* next = item->next;
+ env->CallVoidMethod(item->javaObject, clearReferentMID);
+ env->DeleteGlobalRef(item->javaObject);
+ delete item;
+ item = next;
+ }
+
+ return PL_DHASH_REMOVE;
+}
+
+nsresult
+NativeToJavaProxyMap::Destroy(JNIEnv* env)
+{
+ // This is only called from FreeGlobals(), which already holds the lock.
+ // nsAutoLock lock(gJavaXPCOMLock);
+
+ PL_DHashTableEnumerate(mHashTable, DestroyJavaProxyMappingEnum, env);
+ PL_DHashTableDestroy(mHashTable);
+ mHashTable = nsnull;
+
+ return NS_OK;
+}
+
+nsresult
+NativeToJavaProxyMap::Add(JNIEnv* env, nsISupports* aXPCOMObject,
+ const nsIID& aIID, jobject aProxy)
+{
+ nsAutoLock lock(gJavaXPCOMLock);
+
+ Entry* e = static_cast<Entry*>(PL_DHashTableOperate(mHashTable,
+ aXPCOMObject,
+ PL_DHASH_ADD));
+ if (!e)
+ return NS_ERROR_FAILURE;
+
+ jobject ref = nsnull;
+ jobject weakRefObj = env->NewObject(weakReferenceClass,
+ weakReferenceConstructorMID, aProxy);
+ if (weakRefObj)
+ ref = env->NewGlobalRef(weakRefObj);
+ if (!ref)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Add Java proxy weak reference ref to start of list
+ ProxyList* item = new ProxyList(ref, aIID, e->list);
+ e->key = aXPCOMObject;
+ e->list = item;
+
+#ifdef DEBUG_JAVAXPCOM
+ char* iid_str = aIID.ToString();
+ LOG(("+ NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID, aProxy),
+ (PRUint32) aXPCOMObject, iid_str));
+ PR_Free(iid_str);
+#endif
+ return NS_OK;
+}
+
+nsresult
+NativeToJavaProxyMap::Find(JNIEnv* env, nsISupports* aNativeObject,
+ const nsIID& aIID, jobject* aResult)
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_FAILURE;
+
+ nsAutoLock lock(gJavaXPCOMLock);
+
+ *aResult = nsnull;
+ Entry* e = static_cast<Entry*>(PL_DHashTableOperate(mHashTable,
+ aNativeObject,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(e))
+ return NS_OK;
+
+ ProxyList* item = e->list;
+ while (item != nsnull && *aResult == nsnull) {
+ if (item->iid.Equals(aIID)) {
+ jobject referentObj = env->CallObjectMethod(item->javaObject,
+ getReferentMID);
+ if (!env->IsSameObject(referentObj, NULL)) {
+ *aResult = referentObj;
+#ifdef DEBUG_JAVAXPCOM
+ char* iid_str = aIID.ToString();
+ LOG(("< NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
+ *aResult),
+ (PRUint32) aNativeObject, iid_str));
+ PR_Free(iid_str);
+#endif
+ }
+ }
+ item = item->next;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+NativeToJavaProxyMap::Remove(JNIEnv* env, nsISupports* aNativeObject,
+ const nsIID& aIID)
+{
+ // This is only called from finalizeProxy(), which already holds the lock.
+ // nsAutoLock lock(gJavaXPCOMLock);
+
+ Entry* e = static_cast<Entry*>(PL_DHashTableOperate(mHashTable,
+ aNativeObject,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(e)) {
+ NS_WARNING("XPCOM object not found in hash table");
+ return NS_ERROR_FAILURE;
+ }
+
+ ProxyList* item = e->list;
+ ProxyList* last = e->list;
+ while (item != nsnull) {
+ if (item->iid.Equals(aIID)) {
+#ifdef DEBUG_JAVAXPCOM
+ char* iid_str = aIID.ToString();
+ LOG(("- NativeToJavaProxyMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
+ item->javaObject),
+ (PRUint32) aNativeObject, iid_str));
+ PR_Free(iid_str);
+#endif
+
+ env->CallVoidMethod(item->javaObject, clearReferentMID);
+ env->DeleteGlobalRef(item->javaObject);
+ if (item == e->list) {
+ e->list = item->next;
+ if (e->list == nsnull)
+ PL_DHashTableOperate(mHashTable, aNativeObject, PL_DHASH_REMOVE);
+ } else {
+ last->next = item->next;
+ }
+
+ delete item;
+ return NS_OK;
+ }
+
+ last = item;
+ item = item->next;
+ }
+
+ NS_WARNING("Java proxy matching given IID not found");
+ return NS_ERROR_FAILURE;
+}
+
+nsresult
+JavaToXPTCStubMap::Init()
+{
+ mHashTable = PL_NewDHashTable(PL_DHashGetStubOps(), nsnull,
+ sizeof(Entry), 16);
+ if (!mHashTable)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+
+PLDHashOperator
+DestroyXPTCMappingEnum(PLDHashTable* aTable, PLDHashEntryHdr* aHeader,
+ PRUint32 aNumber, void* aData)
+{
+ JavaToXPTCStubMap::Entry* entry =
+ static_cast<JavaToXPTCStubMap::Entry*>(aHeader);
+
+ // The XPTC stub will be released by the XPCOM side, if it hasn't been
+ // already. We just need to delete the Java global ref held by the XPTC stub,
+ // so the Java garbage collector can handle the Java object when necessary.
+ entry->xptcstub->DeleteStrongRef();
+
+ return PL_DHASH_REMOVE;
+}
+
+nsresult
+JavaToXPTCStubMap::Destroy()
+{
+ // This is only called from FreeGlobals(), which already holds the lock.
+ // nsAutoLock lock(gJavaXPCOMLock);
+
+ PL_DHashTableEnumerate(mHashTable, DestroyXPTCMappingEnum, nsnull);
+ PL_DHashTableDestroy(mHashTable);
+ mHashTable = nsnull;
+
+ return NS_OK;
+}
+
+nsresult
+JavaToXPTCStubMap::Add(jint aJavaObjectHashCode, nsJavaXPTCStub* aProxy)
+{
+ nsAutoLock lock(gJavaXPCOMLock);
+
+ Entry* e = static_cast<Entry*>
+ (PL_DHashTableOperate(mHashTable,
+ NS_INT32_TO_PTR(aJavaObjectHashCode),
+ PL_DHASH_ADD));
+ if (!e)
+ return NS_ERROR_FAILURE;
+
+ NS_ASSERTION(e->key == nsnull,
+ "XPTCStub for given Java object already exists in hash table");
+ e->key = aJavaObjectHashCode;
+ e->xptcstub = aProxy;
+
+#ifdef DEBUG_JAVAXPCOM
+ nsIInterfaceInfo* iface_info;
+ aProxy->GetInterfaceInfo(&iface_info);
+ nsIID* iid;
+ iface_info->GetInterfaceIID(&iid);
+ char* iid_str = iid->ToString();
+ LOG(("+ JavaToXPTCStubMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) aJavaObjectHashCode, (PRUint32) aProxy, iid_str));
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+ NS_RELEASE(iface_info);
+#endif
+ return NS_OK;
+}
+
+nsresult
+JavaToXPTCStubMap::Find(jint aJavaObjectHashCode, const nsIID& aIID,
+ nsJavaXPTCStub** aResult)
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_FAILURE;
+
+ nsAutoLock lock(gJavaXPCOMLock);
+
+ *aResult = nsnull;
+ Entry* e = static_cast<Entry*>
+ (PL_DHashTableOperate(mHashTable,
+ NS_INT32_TO_PTR(aJavaObjectHashCode),
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(e))
+ return NS_OK;
+
+ nsresult rv = e->xptcstub->QueryInterface(aIID, (void**) aResult);
+
+#ifdef DEBUG_JAVAXPCOM
+ if (NS_SUCCEEDED(rv)) {
+ char* iid_str = aIID.ToString();
+ LOG(("< JavaToXPTCStubMap (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) aJavaObjectHashCode, (PRUint32) *aResult, iid_str));
+ PR_Free(iid_str);
+ }
+#endif
+
+ // NS_NOINTERFACE is not an error condition
+ if (rv == NS_NOINTERFACE)
+ rv = NS_OK;
+ return rv;
+}
+
+nsresult
+JavaToXPTCStubMap::Remove(jint aJavaObjectHashCode)
+{
+ PL_DHashTableOperate(mHashTable, NS_INT32_TO_PTR(aJavaObjectHashCode),
+ PL_DHASH_REMOVE);
+
+#ifdef DEBUG_JAVAXPCOM
+ LOG(("- JavaToXPTCStubMap (Java=%08x)\n", (PRUint32) aJavaObjectHashCode));
+#endif
+
+ return NS_OK;
+}
+
+
+/**********************************************************
+ * JavaXPCOMInstance
+ *********************************************************/
+JavaXPCOMInstance::JavaXPCOMInstance(nsISupports* aInstance,
+ nsIInterfaceInfo* aIInfo)
+ : mInstance(aInstance)
+ , mIInfo(aIInfo)
+{
+ NS_ADDREF(mInstance);
+ NS_ADDREF(mIInfo);
+}
+
+JavaXPCOMInstance::~JavaXPCOMInstance()
+{
+ nsresult rv = NS_OK;
+
+#ifdef VBOX
+# if 0
+ nsCOMPtr<nsIEventQueue> eq = do_GetMainThreadQueue();
+ rv = NS_ProxyRelease(eq.get(), mInstance);
+ rv |= NS_ProxyRelease(eq.get(), mIInfo);
+# else
+ // The above code crashes in nsTraceRefcntImpl::LogAddCOMPtr() (@bugref 7620)
+ NS_RELEASE(mInstance);
+ NS_RELEASE(mIInfo);
+ rv = NS_OK;
+# endif
+#else
+ // Need to release these objects on the main thread.
+ nsCOMPtr<nsIThread> thread = do_GetMainThread();
+ if (thread) {
+ rv = NS_ProxyRelease(thread, mInstance);
+ rv |= NS_ProxyRelease(thread, mIInfo);
+ }
+#endif
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease");
+}
+
+
+/*******************************
+ * Helper functions
+ *******************************/
+
+nsresult
+NativeInterfaceToJavaObject(JNIEnv* env, nsISupports* aXPCOMObject,
+ const nsIID& aIID, jobject aObjectLoader,
+ jobject* aResult)
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ // If the object is an nsJavaXPTCStub, then get the Java object directly
+ nsJavaXPTCStub* stub = nsnull;
+ aXPCOMObject->QueryInterface(NS_GET_IID(nsJavaXPTCStub), (void**) &stub);
+ if (stub) {
+ *aResult = stub->GetJavaObject();
+ NS_ASSERTION(*aResult != nsnull, "nsJavaXPTCStub w/o matching Java object");
+ NS_RELEASE(stub);
+ return NS_OK;
+ }
+
+ // ... else, get a Java wrapper for the native object
+ return GetNewOrUsedJavaWrapper(env, aXPCOMObject, aIID, aObjectLoader,
+ aResult);
+}
+
+nsresult
+JavaObjectToNativeInterface(JNIEnv* env, jobject aJavaObject, const nsIID& aIID,
+ void** aResult)
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+ *aResult = nsnull;
+
+ // If the given Java object is one of our Java proxies, then query the
+ // associated XPCOM object directly from the proxy.
+ jboolean isProxy = env->CallStaticBooleanMethod(xpcomJavaProxyClass,
+ isXPCOMJavaProxyMID,
+ aJavaObject);
+ if (env->ExceptionCheck())
+ return NS_ERROR_FAILURE;
+
+ if (isProxy) {
+ void* inst;
+ rv = GetXPCOMInstFromProxy(env, aJavaObject, &inst);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsISupports* rootObject =
+ static_cast<JavaXPCOMInstance*>(inst)->GetInstance();
+ rv = rootObject->QueryInterface(aIID, aResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+ }
+
+ // ... else, we get an nsJavaXPTCStub
+ return nsJavaXPTCStub::GetNewOrUsed(env, aJavaObject, aIID, aResult);
+}
+
+nsresult
+GetIIDForMethodParam(nsIInterfaceInfo *iinfo,
+ const XPTMethodDescriptor *methodInfo,
+ const nsXPTParamInfo &paramInfo, PRUint8 paramType,
+ PRUint16 methodIndex, nsXPTCMiniVariant *dispatchParams,
+ PRBool isFullVariantArray, nsID &result)
+{
+ nsresult rv;
+
+ switch (paramType)
+ {
+ case nsXPTType::T_INTERFACE:
+ rv = iinfo->GetIIDForParamNoAlloc(methodIndex, &paramInfo, &result);
+ break;
+
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ PRUint8 argnum;
+ rv = iinfo->GetInterfaceIsArgNumberForParam(methodIndex, &paramInfo,
+ &argnum);
+ if (NS_FAILED(rv))
+ break;
+
+ const nsXPTParamInfo& arg_param = methodInfo->params[argnum];
+ const nsXPTType& arg_type = arg_param.GetType();
+
+ // The xpidl compiler ensures this. We reaffirm it for safety.
+ if (!arg_type.IsPointer() || arg_type.TagPart() != nsXPTType::T_IID) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ nsID *p = nsnull;
+ if (isFullVariantArray) {
+ p = (nsID *) ((nsXPTCVariant*) dispatchParams)[argnum].val.p;
+ } else {
+ p = (nsID *) dispatchParams[argnum].val.p;
+ }
+ if (!p)
+ return NS_ERROR_UNEXPECTED;
+
+ result = *p;
+ break;
+ }
+
+ default:
+ rv = NS_ERROR_UNEXPECTED;
+ }
+ return rv;
+}
+
+
+/*******************************
+ * JNI helper functions
+ *******************************/
+
+JNIEnv*
+GetJNIEnv()
+{
+ JNIEnv* env = nsnull;
+ jint rc = gCachedJVM->GetEnv((void**) &env, JNI_VERSION_1_2);
+#ifdef VBOX
+ if (env == nsnull)
+ {
+ rc = gCachedJVM->AttachCurrentThreadAsDaemon((void**)&env, nsnull);
+ printf("attaching\n");
+ }
+#endif
+ NS_ASSERTION(rc == JNI_OK && env != nsnull,
+ "Current thread not attached to given JVM instance");
+ return env;
+}
+
+void
+ThrowException(JNIEnv* env, const nsresult aErrorCode, const char* aMessage)
+{
+ // Only throw this exception if one hasn't already been thrown, so we don't
+ // mask a previous exception/error.
+ if (env->ExceptionCheck())
+ return;
+
+ // If the error code we get is for an Out Of Memory error, try to throw an
+ // OutOfMemoryError. The JVM may have enough memory to create this error.
+ if (aErrorCode == NS_ERROR_OUT_OF_MEMORY) {
+ jclass clazz = env->FindClass("java/lang/OutOfMemoryError");
+ if (clazz) {
+ env->ThrowNew(clazz, aMessage);
+ }
+ env->DeleteLocalRef(clazz);
+ return;
+ }
+
+ // If the error was not handled above, then create an XPCOMException with the
+ // given error code and message.
+
+ // Create parameters and method signature. Max of 2 params. The error code
+ // comes before the message string.
+ PRInt64 errorCode = aErrorCode ? aErrorCode : NS_ERROR_FAILURE;
+ nsCAutoString methodSig("(J");
+ jstring message = nsnull;
+ if (aMessage) {
+ message = env->NewStringUTF(aMessage);
+ if (!message) {
+ return;
+ }
+ methodSig.AppendLiteral("Ljava/lang/String;");
+ }
+ methodSig.AppendLiteral(")V");
+
+ // In some instances (such as in shutdownXPCOM() and termEmbedding()), we
+ // will need to throw an exception when JavaXPCOM has already been
+ // terminated. In such a case, 'xpcomExceptionClass' will be null. So we
+ // reset it temporarily in order to throw the appropriate exception.
+ if (xpcomExceptionClass == nsnull) {
+ xpcomExceptionClass = env->FindClass("org/mozilla/xpcom/XPCOMException");
+ if (!xpcomExceptionClass) {
+ return;
+ }
+ }
+
+ // create exception object
+ jthrowable throwObj = nsnull;
+ jmethodID mid = env->GetMethodID(xpcomExceptionClass, "<init>",
+ methodSig.get());
+ if (mid) {
+ throwObj = (jthrowable) env->NewObject(xpcomExceptionClass, mid, errorCode,
+ message);
+ }
+ NS_ASSERTION(throwObj, "Failed to create XPCOMException object");
+
+ // throw exception
+ if (throwObj) {
+ env->Throw(throwObj);
+ }
+}
+
+nsAString*
+jstring_to_nsAString(JNIEnv* env, jstring aString)
+{
+ const PRUnichar* buf = nsnull;
+ if (aString) {
+ buf = env->GetStringChars(aString, nsnull);
+ if (!buf)
+ return nsnull; // exception already thrown
+ }
+
+ nsString* str = new nsString(buf);
+
+ if (aString) {
+ env->ReleaseStringChars(aString, buf);
+ } else {
+ str->SetIsVoid(PR_TRUE);
+ }
+
+ // returns string, or nsnull if 'new' failed
+ return str;
+}
+
+nsACString*
+jstring_to_nsACString(JNIEnv* env, jstring aString)
+{
+ const char* buf = nsnull;
+ if (aString) {
+ buf = env->GetStringUTFChars(aString, nsnull);
+ if (!buf)
+ return nsnull; // exception already thrown
+ }
+
+ nsCString* str = new nsCString(buf);
+
+ if (aString) {
+ env->ReleaseStringUTFChars(aString, buf);
+ } else {
+ str->SetIsVoid(PR_TRUE);
+ }
+
+ // returns string, or nsnull if 'new' failed
+ return str;
+}
+
+nsresult
+File_to_nsILocalFile(JNIEnv* env, jobject aFile, nsILocalFile** aLocalFile)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ jstring pathName = nsnull;
+ jclass clazz = env->FindClass("java/io/File");
+ if (clazz) {
+ jmethodID pathMID = env->GetMethodID(clazz, "getCanonicalPath",
+ "()Ljava/lang/String;");
+ if (pathMID) {
+ pathName = (jstring) env->CallObjectMethod(aFile, pathMID);
+ if (pathName != nsnull && !env->ExceptionCheck())
+ rv = NS_OK;
+ }
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ nsAString* path = jstring_to_nsAString(env, pathName);
+ if (!path)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+
+ if (NS_SUCCEEDED(rv)) {
+ rv = NS_NewLocalFile(*path, false, aLocalFile);
+ delete path;
+ }
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.h b/src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.h
new file mode 100644
index 00000000..894a8cb8
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPCOMBindingUtils.h
@@ -0,0 +1,392 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+#ifndef _nsJavaXPCOMBindingUtils_h_
+#define _nsJavaXPCOMBindingUtils_h_
+
+#include "jni.h"
+#include "xptcall.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "pldhash.h"
+#include "nsJavaXPTCStub.h"
+#include "nsAutoLock.h"
+#include "nsTHashtable.h"
+#include "nsHashKeys.h"
+#include "nsILocalFile.h"
+
+//#define DEBUG_JAVAXPCOM
+//#define DEBUG_JAVAXPCOM_REFCNT
+
+#ifdef DEBUG_JAVAXPCOM
+#define LOG(x) printf x
+#else
+#define LOG(x) /* nothing */
+#endif
+
+
+/*********************
+ * Java JNI globals
+ *********************/
+
+extern jclass systemClass;
+extern jclass booleanClass;
+extern jclass charClass;
+extern jclass byteClass;
+extern jclass shortClass;
+extern jclass intClass;
+extern jclass longClass;
+extern jclass floatClass;
+extern jclass doubleClass;
+extern jclass stringClass;
+extern jclass nsISupportsClass;
+extern jclass xpcomExceptionClass;
+extern jclass xpcomJavaProxyClass;
+extern jclass weakReferenceClass;
+extern jclass javaXPCOMUtilsClass;
+
+extern jmethodID hashCodeMID;
+extern jmethodID booleanValueMID;
+extern jmethodID booleanInitMID;
+extern jmethodID charValueMID;
+extern jmethodID charInitMID;
+extern jmethodID byteValueMID;
+extern jmethodID byteInitMID;
+extern jmethodID shortValueMID;
+extern jmethodID shortInitMID;
+extern jmethodID intValueMID;
+extern jmethodID intInitMID;
+extern jmethodID longValueMID;
+extern jmethodID longInitMID;
+extern jmethodID floatValueMID;
+extern jmethodID floatInitMID;
+extern jmethodID doubleValueMID;
+extern jmethodID doubleInitMID;
+extern jmethodID createProxyMID;
+extern jmethodID isXPCOMJavaProxyMID;
+extern jmethodID getNativeXPCOMInstMID;
+extern jmethodID weakReferenceConstructorMID;
+extern jmethodID getReferentMID;
+extern jmethodID clearReferentMID;
+extern jmethodID findClassInLoaderMID;
+
+#ifdef DEBUG_JAVAXPCOM
+extern jmethodID getNameMID;
+extern jmethodID proxyToStringMID;
+#endif
+
+class NativeToJavaProxyMap;
+extern NativeToJavaProxyMap* gNativeToJavaProxyMap;
+class JavaToXPTCStubMap;
+extern JavaToXPTCStubMap* gJavaToXPTCStubMap;
+
+extern nsTHashtable<nsDepCharHashKey>* gJavaKeywords;
+
+// The Java garbage collector runs in a separate thread. Since it calls the
+// finalizeProxy() function in nsJavaWrapper.cpp, we need to make sure that
+// all the structures touched by finalizeProxy() are multithread aware.
+extern PRLock* gJavaXPCOMLock;
+
+extern PRBool gJavaXPCOMInitialized;
+
+/**
+ * Initialize global structures used by JavaXPCOM.
+ * @param env Java environment pointer
+ * @return PR_TRUE if JavaXPCOM is initialized; PR_FALSE if an error occurred
+ */
+PRBool InitializeJavaGlobals(JNIEnv *env);
+
+/**
+ * Frees global structures that were allocated by InitializeJavaGlobals().
+ * @param env Java environment pointer
+ */
+void FreeJavaGlobals(JNIEnv* env);
+
+
+/*************************
+ * JavaXPCOMInstance
+ *************************/
+
+class JavaXPCOMInstance
+{
+public:
+ JavaXPCOMInstance(nsISupports* aInstance, nsIInterfaceInfo* aIInfo);
+ ~JavaXPCOMInstance();
+
+ nsISupports* GetInstance() { return mInstance; }
+ nsIInterfaceInfo* InterfaceInfo() { return mIInfo; }
+
+private:
+ nsISupports* mInstance;
+ nsIInterfaceInfo* mIInfo;
+};
+
+
+/**************************************
+ * Java<->XPCOM object mappings
+ **************************************/
+
+/**
+ * Maps native XPCOM objects to their associated Java proxy object.
+ */
+class NativeToJavaProxyMap
+{
+ friend PLDHashOperator DestroyJavaProxyMappingEnum(PLDHashTable* aTable,
+ PLDHashEntryHdr* aHeader,
+ PRUint32 aNumber,
+ void* aData);
+
+protected:
+ struct ProxyList
+ {
+ ProxyList(const jobject aRef, const nsIID& aIID, ProxyList* aList)
+ : javaObject(aRef)
+ , iid(aIID)
+ , next(aList)
+ { }
+
+ const jobject javaObject;
+ const nsIID iid;
+ ProxyList* next;
+ };
+
+ struct Entry : public PLDHashEntryHdr
+ {
+ nsISupports* key;
+ ProxyList* list;
+ };
+
+public:
+ NativeToJavaProxyMap()
+ : mHashTable(nsnull)
+ { }
+
+ ~NativeToJavaProxyMap()
+ {
+ NS_ASSERTION(mHashTable == nsnull,
+ "MUST call Destroy() before deleting object");
+ }
+
+ nsresult Init();
+
+ nsresult Destroy(JNIEnv* env);
+
+ nsresult Add(JNIEnv* env, nsISupports* aXPCOMObject, const nsIID& aIID,
+ jobject aProxy);
+
+ nsresult Find(JNIEnv* env, nsISupports* aNativeObject, const nsIID& aIID,
+ jobject* aResult);
+
+ nsresult Remove(JNIEnv* env, nsISupports* aNativeObject, const nsIID& aIID);
+
+protected:
+ PLDHashTable* mHashTable;
+};
+
+/**
+ * Maps Java objects to their associated nsJavaXPTCStub.
+ */
+class JavaToXPTCStubMap
+{
+ friend PLDHashOperator DestroyXPTCMappingEnum(PLDHashTable* aTable,
+ PLDHashEntryHdr* aHeader,
+ PRUint32 aNumber, void* aData);
+
+protected:
+ struct Entry : public PLDHashEntryHdr
+ {
+ jint key;
+ nsJavaXPTCStub* xptcstub;
+ };
+
+public:
+ JavaToXPTCStubMap()
+ : mHashTable(nsnull)
+ { }
+
+ ~JavaToXPTCStubMap()
+ {
+ NS_ASSERTION(mHashTable == nsnull,
+ "MUST call Destroy() before deleting object");
+ }
+
+ nsresult Init();
+
+ nsresult Destroy();
+
+ nsresult Add(jint aJavaObjectHashCode, nsJavaXPTCStub* aProxy);
+
+ nsresult Find(jint aJavaObjectHashCode, const nsIID& aIID,
+ nsJavaXPTCStub** aResult);
+
+ nsresult Remove(jint aJavaObjectHashCode);
+
+protected:
+ PLDHashTable* mHashTable;
+};
+
+
+/*******************************
+ * Helper functions
+ *******************************/
+
+/**
+ * Convert a native nsISupports to a Java object.
+ *
+ * @param env Java environment pointer
+ * @param aXPCOMObject XPCOM object for which to find/create Java object
+ * @param aIID desired interface IID for Java object
+ * @param aObjectLoader Java object whose class loader we use for finding
+ * classes; can be null
+ * @param aResult on success, holds reference to Java object
+ *
+ * @return NS_OK if succeeded; all other return values are error codes.
+ */
+nsresult NativeInterfaceToJavaObject(JNIEnv* env, nsISupports* aXPCOMObject,
+ const nsIID& aIID, jobject aObjectLoader,
+ jobject* aResult);
+
+/**
+ * Convert a Java object to a native nsISupports object.
+ *
+ * @param env Java environment pointer
+ * @param aJavaObject Java object for which to find/create XPCOM object
+ * @param aIID desired interface IID for XPCOM object
+ * @param aResult on success, holds AddRef'd reference to XPCOM object
+ *
+ * @return NS_OK if succeeded; all other return values are error codes.
+ */
+nsresult JavaObjectToNativeInterface(JNIEnv* env, jobject aJavaObject,
+ const nsIID& aIID, void** aResult);
+
+nsresult GetIIDForMethodParam(nsIInterfaceInfo *iinfo,
+ const XPTMethodDescriptor *methodInfo,
+ const nsXPTParamInfo &paramInfo,
+ PRUint8 paramType, PRUint16 methodIndex,
+ nsXPTCMiniVariant *dispatchParams,
+ PRBool isFullVariantArray,
+ nsID &result);
+
+/**
+ * Returns the Class object associated with the class or interface with the
+ * given string name, using the class loader of the given object.
+ *
+ * @param env Java environment pointer
+ * @param aObjectLoader Java object whose class loader is used to load class
+ * @param aClassName fully qualified name of class to load
+ *
+ * @return java.lang.Class object of requested Class; NULL if the class
+ * wasn't found
+ *
+ * @see http://java.sun.com/j2se/1.3/docs/guide/jni/jni-12.html#classops
+ */
+inline jclass
+FindClassInLoader(JNIEnv* env, jobject aObjectLoader, const char* aClassName)
+{
+ jclass clazz = nsnull;
+ jstring name = env->NewStringUTF(aClassName);
+ if (name)
+ clazz = (jclass) env->CallStaticObjectMethod(javaXPCOMUtilsClass,
+ findClassInLoaderMID, aObjectLoader, name);
+
+#ifdef DEBUG
+ if (!clazz)
+ fprintf(stderr, "WARNING: failed to find class [%s]\n", aClassName);
+#endif
+ return clazz;
+}
+
+
+/*******************************
+ * JNI helper functions
+ *******************************/
+
+/**
+ * Returns a pointer to the appropriate JNIEnv structure. This function is
+ * useful in callbacks or other functions that are not called directly from
+ * Java and therefore do not have the JNIEnv structure passed in.
+ *
+ * @return pointer to JNIEnv structure for current thread
+ */
+JNIEnv* GetJNIEnv();
+
+/**
+ * Constructs and throws an exception. Some error codes (such as
+ * NS_ERROR_OUT_OF_MEMORY) are handled by the appropriate Java exception/error.
+ * Otherwise, an instance of XPCOMException is created with the given error
+ * code and message.
+ *
+ * @param env Java environment pointer
+ * @param aErrorCode The error code returned by an XPCOM/Gecko function. Pass
+ * zero for the default behaviour.
+ * @param aMessage A string that provides details for throwing this
+ * exception. Pass in <code>nsnull</code> for the default
+ * behaviour.
+ *
+ * @throws OutOfMemoryError if aErrorCode == NS_ERROR_OUT_OF_MEMORY
+ * XPCOMException for all other error codes
+ */
+void ThrowException(JNIEnv* env, const nsresult aErrorCode,
+ const char* aMessage);
+
+/**
+ * Helper functions for converting from java.lang.String to
+ * nsAString/nsACstring. Caller must delete nsAString/nsACString.
+ *
+ * @param env Java environment pointer
+ * @param aString Java string to convert
+ *
+ * @return nsAString/nsACString with same content as given Java string;
+ * a 'void' nsAString/nsACString object if aString is
+ * <code>null</code>; or <code>nsnull</code> if out of memory
+ */
+nsAString* jstring_to_nsAString(JNIEnv* env, jstring aString);
+nsACString* jstring_to_nsACString(JNIEnv* env, jstring aString);
+
+/**
+ * Helper function for converting from java.io.File to nsILocalFile.
+ *
+ * @param env Java environment pointer
+ * @param aFile Java File to convert
+ * @param aLocalFile returns the converted nsILocalFile
+ *
+ * @return NS_OK for success; other values indicate error in conversion
+ */
+nsresult File_to_nsILocalFile(JNIEnv* env, jobject aFile,
+ nsILocalFile** aLocalFile);
+
+#endif // _nsJavaXPCOMBindingUtils_h_
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPCOMGlue.cpp b/src/libs/xpcom18a4/java/src/nsJavaXPCOMGlue.cpp
new file mode 100644
index 00000000..b0b6b72c
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPCOMGlue.cpp
@@ -0,0 +1,535 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "jni.h"
+#include "nsXPCOMPrivate.h" // for XPCOM_DLL defines.
+#include "nsXPCOMGlue.h"
+#include <stdlib.h>
+
+
+#ifdef VBOX
+#include <string.h>
+#include "nsDebug.h"
+#endif
+
+#if defined(XP_WIN) || defined(XP_OS2)
+#define JX_EXPORT JNIEXPORT
+#else
+#define JX_EXPORT JNIEXPORT NS_EXPORT
+#endif
+
+
+/***********************
+ * JNI Load & Unload
+ ***********************/
+
+extern "C" JX_EXPORT jint JNICALL
+JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ // Let the JVM know that we are using JDK 1.2 JNI features.
+ return JNI_VERSION_1_2;
+}
+
+extern "C" JX_EXPORT void JNICALL
+JNI_OnUnload(JavaVM* vm, void* reserved)
+{
+}
+
+/********************************
+ * JavaXPCOM JNI interfaces
+ ********************************/
+
+#define JXM_NATIVE(func) Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_##func
+
+enum {
+ kFunc_Initialize,
+ kFunc_InitEmbedding,
+ kFunc_TermEmbedding,
+ kFunc_LockProfileDirectory,
+ kFunc_NotifyProfile,
+ kFunc_InitXPCOM,
+ kFunc_ShutdownXPCOM,
+ kFunc_GetComponentManager,
+ kFunc_GetComponentRegistrar,
+ kFunc_GetServiceManager,
+ kFunc_NewLocalFile,
+ kFunc_CallXPCOMMethod,
+ kFunc_FinalizeProxy,
+ kFunc_IsSameXPCOMObject,
+ kFunc_ReleaseProfileLock,
+ kFunc_GetNativeHandleFromAWT,
+ kFunc_WrapJavaObject,
+ kFunc_WrapXPCOMObject
+};
+
+#define JX_NUM_FUNCS 18
+
+
+// Get path string from java.io.File object.
+jstring
+GetJavaFilePath(JNIEnv* env, jobject aFile)
+{
+ jclass clazz = env->FindClass("java/io/File");
+ if (clazz) {
+ jmethodID pathMID = env->GetMethodID(clazz, "getCanonicalPath",
+ "()Ljava/lang/String;");
+ if (pathMID) {
+ return (jstring) env->CallObjectMethod(aFile, pathMID);
+ }
+ }
+
+ return nsnull;
+}
+#ifdef VBOX
+
+#include "nsXPTCUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsJavaInterfaces.h"
+
+void
+ThrowException(JNIEnv* env, const nsresult aErrorCode, const char* aMessage);
+
+class nsXPTCJStub : public nsXPTCStubBase
+{
+ nsCOMPtr<nsIInterfaceInfo> mII;
+ nsIXPTCProxy* mOuter;
+ public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ nsXPTCJStub(REFNSIID aIID, nsIXPTCProxy* aOuter, nsIInterfaceInfo* ii)
+ {
+ mOuter = aOuter;
+ mII = ii;
+ }
+
+ virtual ~nsXPTCJStub()
+ {
+ }
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info)
+ {
+ *info = mII;
+ (*info)->AddRef();
+ return NS_OK;
+ }
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params)
+ {
+ return mOuter->CallMethod(methodIndex, info, params);
+ }
+};
+
+NS_IMETHODIMP_(nsrefcnt)
+nsXPTCJStub::AddRef()
+{
+ return mOuter->AddRef();
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsXPTCJStub::Release()
+{
+ return mOuter->Release();
+}
+
+NS_IMETHODIMP nsXPTCJStub::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ nsIID* mIID;
+ mII->GetInterfaceIID(&mIID);
+
+ if (mIID->Equals(aIID)) {
+ NS_ADDREF_THIS();
+ *aInstancePtr = static_cast<nsISupports*>(this);
+ return NS_OK;
+ }
+
+ return mOuter->QueryInterface(aIID, aInstancePtr);
+}
+
+nsresult
+NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
+ nsISomeInterface* *aResult)
+{
+ NS_ENSURE_ARG(aOuter && aResult);
+#if 0
+ xptiInterfaceInfoManager *iim =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+ NS_ENSURE_TRUE(iim, NS_ERROR_NOT_INITIALIZED);
+
+ xptiInterfaceEntry *iie = iim->GetInterfaceEntryForIID(&aIID);
+ if (!iie || !iie->EnsureResolved())
+ return NS_ERROR_FAILURE;
+
+ nsXPTCStubBase* newbase = new nsXPTCStubBase(aOuter, iie);
+ if (!newbase)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = newbase;
+#else
+ nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ nsresult rv;
+
+ rv = iim->GetInfoForIID(&aIID, getter_AddRefs(ii));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsXPTCStubBase* newbase = new nsXPTCJStub(aIID, aOuter, ii);
+ if (!newbase)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *aResult = newbase;
+#endif
+ return NS_OK;
+}
+
+void
+NS_DestroyXPTCallStub(nsISomeInterface* aStub)
+{
+ nsXPTCStubBase* stub = static_cast<nsXPTCStubBase*>(aStub);
+ delete(stub);
+}
+
+
+extern "C" void JAVAPROXY_NATIVE(finalizeProxy)(JNIEnv *env, jclass that, jobject aJavaProxy);
+
+nsresult
+FindVBoxMethods(JNIEnv* env, jobject aXPCOMPath, void** aFunctions)
+{
+ nsresult rv = 0;
+
+ // We only need to care about this function because the C function we offer
+ // is different from what the Java side expects
+ aFunctions[kFunc_FinalizeProxy] = (void*)JAVAPROXY_NATIVE(finalizeProxy);
+
+ return rv;
+}
+#else
+// Calls XPCOMGlueStartup using the given java.io.File object, and loads
+// the JavaXPCOM methods from the XUL shared library.
+nsresult
+LoadXULMethods(JNIEnv* env, jobject aXPCOMPath, void** aFunctions)
+{
+ jstring pathString = GetJavaFilePath(env, aXPCOMPath);
+ if (!pathString)
+ return NS_ERROR_FAILURE;
+ const char* path = env->GetStringUTFChars(pathString, nsnull);
+ if (!path)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ int len = strlen(path);
+ char* xpcomPath = (char*) malloc(len + sizeof(XPCOM_DLL) +
+ sizeof(XPCOM_FILE_PATH_SEPARATOR) + 1);
+ if (!xpcomPath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ sprintf(xpcomPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, path);
+
+ nsresult rv = XPCOMGlueStartup(xpcomPath);
+ free(xpcomPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef XP_WIN32
+ // The JNICALL calling convention defines to "__stdcall" on Win32, which
+ // mangles the name.
+ nsDynamicFunctionLoad funcs[] = {
+ { "_Java_org_mozilla_xpcom_internal_MozillaImpl_initialize@8",
+ (NSFuncPtr*) &aFunctions[kFunc_Initialize] },
+ { "_Java_org_mozilla_xpcom_internal_GREImpl_initEmbedding@20",
+ (NSFuncPtr*) &aFunctions[kFunc_InitEmbedding] },
+ { "_Java_org_mozilla_xpcom_internal_GREImpl_termEmbedding@8",
+ (NSFuncPtr*) &aFunctions[kFunc_TermEmbedding] },
+ { "_Java_org_mozilla_xpcom_internal_GREImpl_lockProfileDirectory@12",
+ (NSFuncPtr*) &aFunctions[kFunc_LockProfileDirectory] },
+ { "_Java_org_mozilla_xpcom_internal_GREImpl_notifyProfile@8",
+ (NSFuncPtr*) &aFunctions[kFunc_NotifyProfile] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_initXPCOM@16",
+ (NSFuncPtr*) &aFunctions[kFunc_InitXPCOM] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_shutdownXPCOM@12",
+ (NSFuncPtr*) &aFunctions[kFunc_ShutdownXPCOM] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentManager@8",
+ (NSFuncPtr*) &aFunctions[kFunc_GetComponentManager] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentRegistrar@8",
+ (NSFuncPtr*) &aFunctions[kFunc_GetComponentRegistrar] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getServiceManager@8",
+ (NSFuncPtr*) &aFunctions[kFunc_GetServiceManager] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_newLocalFile@16",
+ (NSFuncPtr*) &aFunctions[kFunc_NewLocalFile] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_callXPCOMMethod@20",
+ (NSFuncPtr*) &aFunctions[kFunc_CallXPCOMMethod] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_finalizeProxy@12",
+ (NSFuncPtr*) &aFunctions[kFunc_FinalizeProxy] },
+ { "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_isSameXPCOMObject@16",
+ (NSFuncPtr*) &aFunctions[kFunc_IsSameXPCOMObject] },
+ { "_Java_org_mozilla_xpcom_ProfileLock_release@16",
+ (NSFuncPtr*) &aFunctions[kFunc_ReleaseProfileLock] },
+ { "_Java_org_mozilla_xpcom_internal_MozillaImpl_getNativeHandleFromAWT@12",
+ (NSFuncPtr*) &aFunctions[kFunc_GetNativeHandleFromAWT] },
+ { "_Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapJavaObject@16",
+ (NSFuncPtr*) &aFunctions[kFunc_WrapJavaObject] },
+ { "_Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapXPCOMObject@20",
+ (NSFuncPtr*) &aFunctions[kFunc_WrapXPCOMObject] },
+ { nsnull, nsnull }
+ };
+#else
+ nsDynamicFunctionLoad funcs[] = {
+ { "Java_org_mozilla_xpcom_internal_MozillaImpl_initialize",
+ (NSFuncPtr*) &aFunctions[kFunc_Initialize] },
+ { "Java_org_mozilla_xpcom_internal_GREImpl_initEmbedding",
+ (NSFuncPtr*) &aFunctions[kFunc_InitEmbedding] },
+ { "Java_org_mozilla_xpcom_internal_GREImpl_termEmbedding",
+ (NSFuncPtr*) &aFunctions[kFunc_TermEmbedding] },
+ { "Java_org_mozilla_xpcom_internal_GREImpl_lockProfileDirectory",
+ (NSFuncPtr*) &aFunctions[kFunc_LockProfileDirectory] },
+ { "Java_org_mozilla_xpcom_internal_GREImpl_notifyProfile",
+ (NSFuncPtr*) &aFunctions[kFunc_NotifyProfile] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMImpl_initXPCOM",
+ (NSFuncPtr*) &aFunctions[kFunc_InitXPCOM] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMImpl_shutdownXPCOM",
+ (NSFuncPtr*) &aFunctions[kFunc_ShutdownXPCOM] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentManager",
+ (NSFuncPtr*) &aFunctions[kFunc_GetComponentManager] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentRegistrar",
+ (NSFuncPtr*) &aFunctions[kFunc_GetComponentRegistrar] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMImpl_getServiceManager",
+ (NSFuncPtr*) &aFunctions[kFunc_GetServiceManager] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMImpl_newLocalFile",
+ (NSFuncPtr*) &aFunctions[kFunc_NewLocalFile] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_callXPCOMMethod",
+ (NSFuncPtr*) &aFunctions[kFunc_CallXPCOMMethod] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_finalizeProxy",
+ (NSFuncPtr*) &aFunctions[kFunc_FinalizeProxy] },
+ { "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_isSameXPCOMObject",
+ (NSFuncPtr*) &aFunctions[kFunc_IsSameXPCOMObject] },
+ { "Java_org_mozilla_xpcom_ProfileLock_release",
+ (NSFuncPtr*) &aFunctions[kFunc_ReleaseProfileLock] },
+ { "Java_org_mozilla_xpcom_internal_MozillaImpl_getNativeHandleFromAWT",
+ (NSFuncPtr*) &aFunctions[kFunc_GetNativeHandleFromAWT] },
+ { "Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapJavaObject",
+ (NSFuncPtr*) &aFunctions[kFunc_WrapJavaObject] },
+ { "Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapXPCOMObject",
+ (NSFuncPtr*) &aFunctions[kFunc_WrapXPCOMObject] },
+ { nsnull, nsnull }
+ };
+#endif
+
+ rv = XPCOMGlueLoadXULFunctions(funcs);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+void
+ThrowException(JNIEnv* env, const nsresult aErrorCode, const char* aMessage)
+{
+ // Only throw this exception if one hasn't already been thrown, so we don't
+ // mask a previous exception/error.
+ if (env->ExceptionCheck())
+ return;
+
+ // If the error code we get is for an Out Of Memory error, try to throw an
+ // OutOfMemoryError. The JVM may have enough memory to create this error.
+ if (aErrorCode == NS_ERROR_OUT_OF_MEMORY) {
+ jclass clazz = env->FindClass("java/lang/OutOfMemoryError");
+ if (clazz) {
+ env->ThrowNew(clazz, aMessage);
+ }
+ env->DeleteLocalRef(clazz);
+ return;
+ }
+
+ // If the error was not handled above, then create an XPCOMException with the
+ // given error code.
+ jthrowable throwObj = nsnull;
+ jclass exceptionClass = env->FindClass("org/mozilla/xpcom/XPCOMException");
+ if (exceptionClass) {
+ jmethodID mid = env->GetMethodID(exceptionClass, "<init>",
+ "(JLjava/lang/String;)V");
+ if (mid) {
+ throwObj = (jthrowable) env->NewObject(exceptionClass, mid,
+ (PRInt64) aErrorCode,
+ env->NewStringUTF(aMessage));
+ }
+ }
+ NS_ASSERTION(throwObj, "Failed to create XPCOMException object");
+
+ // throw exception
+ if (throwObj) {
+ env->Throw(throwObj);
+ }
+}
+#endif // VBOX
+
+// Register the JavaXPCOM native methods. This associates a native Java
+// method with its C implementation.
+nsresult
+RegisterNativeMethods(JNIEnv* env, void** aFunctions)
+{
+ JNINativeMethod mozilla_methods[] = {
+ { "initializeNative", "()V",
+ (void*) aFunctions[kFunc_Initialize] },
+ { "getNativeHandleFromAWT", "(Ljava/lang/Object;)J",
+ (void*) aFunctions[kFunc_GetNativeHandleFromAWT] }
+ };
+
+ JNINativeMethod gre_methods[] = {
+ { "initEmbeddingNative",
+ "(Ljava/io/File;Ljava/io/File;Lorg/mozilla/xpcom/IAppFileLocProvider;)V",
+ (void*) aFunctions[kFunc_InitEmbedding] },
+ { "termEmbedding", "()V",
+ (void*) aFunctions[kFunc_TermEmbedding] },
+ { "lockProfileDirectory", "(Ljava/io/File;)Lorg/mozilla/xpcom/ProfileLock;",
+ (void*) aFunctions[kFunc_LockProfileDirectory] },
+ { "notifyProfile", "()V",
+ (void*) aFunctions[kFunc_NotifyProfile] },
+ };
+
+ JNINativeMethod xpcom_methods[] = {
+ { "initXPCOMNative",
+ "(Ljava/io/File;Lorg/mozilla/xpcom/IAppFileLocProvider;)Lorg/mozilla/interfaces/nsIServiceManager;",
+ (void*) aFunctions[kFunc_InitXPCOM] },
+ { "shutdownXPCOM", "(Lorg/mozilla/interfaces/nsIServiceManager;)V",
+ (void*) aFunctions[kFunc_ShutdownXPCOM] },
+ { "getComponentManager", "()Lorg/mozilla/interfaces/nsIComponentManager;",
+ (void*) aFunctions[kFunc_GetComponentManager] },
+ { "getComponentRegistrar", "()Lorg/mozilla/interfaces/nsIComponentRegistrar;",
+ (void*) aFunctions[kFunc_GetComponentRegistrar] },
+ { "getServiceManager", "()Lorg/mozilla/interfaces/nsIServiceManager;",
+ (void*) aFunctions[kFunc_GetServiceManager] },
+ { "newLocalFile", "(Ljava/lang/String;Z)Lorg/mozilla/interfaces/nsILocalFile;",
+ (void*) aFunctions[kFunc_NewLocalFile] }
+ };
+
+ JNINativeMethod proxy_methods[] = {
+ { "callXPCOMMethod",
+ "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;",
+ (void*) aFunctions[kFunc_CallXPCOMMethod] },
+ { "finalizeProxyNative", "(Ljava/lang/Object;)V",
+ (void*) aFunctions[kFunc_FinalizeProxy] },
+ { "isSameXPCOMObject", "(Ljava/lang/Object;Ljava/lang/Object;)Z",
+ (void*) aFunctions[kFunc_IsSameXPCOMObject] }
+ };
+
+ JNINativeMethod lockProxy_methods[] = {
+ { "releaseNative", "(J)V",
+ (void*) aFunctions[kFunc_ReleaseProfileLock] }
+ };
+
+ JNINativeMethod util_methods[] = {
+ { "wrapJavaObject", "(Ljava/lang/Object;Ljava/lang/String;)J",
+ (void*) aFunctions[kFunc_WrapJavaObject] },
+ { "wrapXPCOMObject", "(JLjava/lang/String;)Ljava/lang/Object;",
+ (void*) aFunctions[kFunc_WrapXPCOMObject] }
+ };
+
+ jint rc = -1;
+ jclass clazz = env->FindClass("org/mozilla/xpcom/internal/MozillaImpl");
+ if (clazz) {
+ rc = env->RegisterNatives(clazz, mozilla_methods,
+ sizeof(mozilla_methods) / sizeof(mozilla_methods[0]));
+ }
+ NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
+
+ rc = -1;
+ clazz = env->FindClass("org/mozilla/xpcom/internal/GREImpl");
+ if (clazz) {
+ rc = env->RegisterNatives(clazz, gre_methods,
+ sizeof(gre_methods) / sizeof(gre_methods[0]));
+ }
+ NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
+
+ rc = -1;
+ clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMImpl");
+ if (clazz) {
+ rc = env->RegisterNatives(clazz, xpcom_methods,
+ sizeof(xpcom_methods) / sizeof(xpcom_methods[0]));
+ }
+ NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
+
+ rc = -1;
+ clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMJavaProxy");
+ if (clazz) {
+ rc = env->RegisterNatives(clazz, proxy_methods,
+ sizeof(proxy_methods) / sizeof(proxy_methods[0]));
+ }
+ NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
+
+ rc = -1;
+ clazz = env->FindClass("org/mozilla/xpcom/ProfileLock");
+ if (clazz) {
+ rc = env->RegisterNatives(clazz, lockProxy_methods,
+ sizeof(lockProxy_methods) / sizeof(lockProxy_methods[0]));
+ }
+ NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
+
+ rc = -1;
+ clazz = env->FindClass("org/mozilla/xpcom/internal/JavaXPCOMMethods");
+ if (clazz) {
+ rc = env->RegisterNatives(clazz, util_methods,
+ sizeof(util_methods) / sizeof(util_methods[0]));
+ }
+ NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+// Load the JavaXPCOM methods from the XUL shared library, and registers them
+// as Java native methods.
+extern "C" JX_EXPORT void JNICALL
+JXM_NATIVE(registerJavaXPCOMMethodsNative) (JNIEnv *env, jclass that,
+ jobject aXPCOMPath)
+{
+ void* functions[JX_NUM_FUNCS];
+ memset(functions, 0, JX_NUM_FUNCS * sizeof(void*));
+
+#ifdef VBOX
+ nsresult rv = FindVBoxMethods(env, aXPCOMPath, functions);
+ if (NS_SUCCEEDED(rv)) {
+ rv = RegisterNativeMethods(env, functions);
+ }
+#else
+ nsresult rv = LoadXULMethods(env, aXPCOMPath, functions);
+ if (NS_SUCCEEDED(rv)) {
+ rv = RegisterNativeMethods(env, functions);
+ }
+#endif
+
+ if (NS_FAILED(rv)) {
+ ThrowException(env, rv, "Failed to register JavaXPCOM methods");
+ }
+}
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPTCStub.cpp b/src/libs/xpcom18a4/java/src/nsJavaXPTCStub.cpp
new file mode 100644
index 00000000..c8136ec4
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPTCStub.cpp
@@ -0,0 +1,1711 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsJavaXPTCStub.h"
+#include "nsJavaWrapper.h"
+#include "nsJavaXPCOMBindingUtils.h"
+#include "prmem.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsString.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsServiceManagerUtils.h"
+
+
+nsJavaXPTCStub::nsJavaXPTCStub(jobject aJavaObject, nsIInterfaceInfo *aIInfo,
+ nsresult *rv)
+ : mJavaStrongRef(nsnull)
+ , mIInfo(aIInfo)
+ , mMaster(nsnull)
+ , mWeakRefCnt(0)
+{
+ const nsIID *iid = nsnull;
+ aIInfo->GetIIDShared(&iid);
+ NS_ASSERTION(iid, "GetIIDShared must not fail!");
+
+ *rv = InitStub(*iid);
+ if (NS_FAILED(*rv))
+ return;
+
+ JNIEnv* env = GetJNIEnv();
+ jobject weakref = env->NewObject(weakReferenceClass,
+ weakReferenceConstructorMID, aJavaObject);
+ mJavaWeakRef = env->NewGlobalRef(weakref);
+ mJavaRefHashCode = env->CallStaticIntMethod(systemClass, hashCodeMID,
+ aJavaObject);
+
+#ifdef DEBUG_JAVAXPCOM
+ char* iid_str = iid->ToString();
+ LOG(("+ nsJavaXPTCStub (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) mJavaRefHashCode, (PRUint32) this, iid_str));
+ PR_Free(iid_str);
+#endif
+}
+
+nsJavaXPTCStub::~nsJavaXPTCStub()
+{
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsJavaXPTCStub::AddRefInternal()
+{
+ // If this is the first AddRef call, we create a strong global ref to the
+ // Java object to keep it from being garbage collected.
+ if (mRefCnt == 0) {
+ JNIEnv* env = GetJNIEnv();
+ jobject referent = env->CallObjectMethod(mJavaWeakRef, getReferentMID);
+ if (!env->IsSameObject(referent, NULL)) {
+ mJavaStrongRef = env->NewGlobalRef(referent);
+ }
+ NS_ASSERTION(mJavaStrongRef != nsnull, "Failed to acquire strong ref");
+ }
+
+ // if this is the master interface
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
+ NS_ASSERT_OWNINGTHREAD(nsJavaXPTCStub);
+ ++mRefCnt;
+ NS_LOG_ADDREF(this, mRefCnt, "nsJavaXPTCStub", sizeof(*this));
+ return mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsJavaXPTCStub::AddRef()
+{
+#ifdef DEBUG_JAVAXPCOM_REFCNT
+ nsIID* iid;
+ mIInfo->GetInterfaceIID(&iid);
+ char* iid_str = iid->ToString();
+ int refcnt = PRInt32(mMaster ? mMaster->mRefCnt : mRefCnt) + 1;
+ LOG(("= nsJavaXPTCStub::AddRef (XPCOM=%08x | refcnt = %d | IID=%s)\n",
+ (int) this, refcnt, iid_str));
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+#endif
+
+ nsJavaXPTCStub* master = mMaster ? mMaster : this;
+ return master->AddRefInternal();
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsJavaXPTCStub::ReleaseInternal()
+{
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ NS_ASSERT_OWNINGTHREAD(nsJavaXPTCStub);
+ --mRefCnt;
+ NS_LOG_RELEASE(this, mRefCnt, "nsJavaXPTCStub");
+ if (mRefCnt == 0) {
+ // delete strong ref; allows Java object to be garbage collected
+ DeleteStrongRef();
+
+ // If we have a weak ref, we don't delete this object.
+ if (mWeakRefCnt == 0) {
+ mRefCnt = 1; /* stabilize */
+ Destroy();
+ delete this;
+ }
+ return 0;
+ }
+ return mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsJavaXPTCStub::Release()
+{
+#ifdef DEBUG_JAVAXPCOM_REFCNT
+ nsIID* iid;
+ mIInfo->GetInterfaceIID(&iid);
+ char* iid_str = iid->ToString();
+ int refcnt = PRInt32(mMaster ? mMaster->mRefCnt : mRefCnt) - 1;
+ LOG(("= nsJavaXPTCStub::Release (XPCOM=%08x | refcnt = %d | IID=%s)\n",
+ (int) this, refcnt, iid_str));
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+#endif
+
+ nsJavaXPTCStub* master = mMaster ? mMaster : this;
+ return master->ReleaseInternal();
+}
+
+void
+nsJavaXPTCStub::Destroy()
+{
+ JNIEnv* env = GetJNIEnv();
+
+#ifdef DEBUG_JAVAXPCOM
+ nsIID* iid;
+ mIInfo->GetInterfaceIID(&iid);
+ char* iid_str = iid->ToString();
+ LOG(("- nsJavaXPTCStub (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) mJavaRefHashCode, (PRUint32) this, iid_str));
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+#endif
+
+ if (!mMaster) {
+ // delete each child stub
+ for (PRInt32 i = 0; i < mChildren.Count(); i++) {
+ delete (nsJavaXPTCStub*) mChildren[i];
+ }
+
+ // Since we are destroying this stub, also remove the mapping.
+ // It is possible for mJavaStrongRef to be NULL here. That is why we
+ // store the hash code value earlier.
+ if (gJavaXPCOMInitialized) {
+ gJavaToXPTCStubMap->Remove(mJavaRefHashCode);
+ }
+ }
+
+ env->CallVoidMethod(mJavaWeakRef, clearReferentMID);
+ env->DeleteGlobalRef(mJavaWeakRef);
+}
+
+void
+nsJavaXPTCStub::ReleaseWeakRef()
+{
+ // if this is a child
+ if (mMaster)
+ mMaster->ReleaseWeakRef();
+
+ --mWeakRefCnt;
+
+ // If there are no more associated weak refs, and no one else holds a strong
+ // ref to this object, then delete it.
+ if (mWeakRefCnt == 0 && mRefCnt == 0) {
+ NS_ASSERT_OWNINGTHREAD(nsJavaXPTCStub);
+ mRefCnt = 1; /* stabilize */
+ Destroy();
+ delete this;
+ }
+}
+
+void
+nsJavaXPTCStub::DeleteStrongRef()
+{
+ if (mJavaStrongRef == nsnull)
+ return;
+
+ GetJNIEnv()->DeleteGlobalRef(mJavaStrongRef);
+ mJavaStrongRef = nsnull;
+}
+
+NS_IMETHODIMP
+nsJavaXPTCStub::QueryInterface(const nsID &aIID, void **aInstancePtr)
+{
+ nsresult rv;
+
+ LOG(("JavaStub::QueryInterface()\n"));
+ *aInstancePtr = nsnull;
+ nsJavaXPTCStub *master = mMaster ? mMaster : this;
+
+ // This helps us differentiate between the help classes.
+ if (aIID.Equals(NS_GET_IID(nsJavaXPTCStub)))
+ {
+ *aInstancePtr = master;
+ NS_ADDREF(this);
+ return NS_OK;
+ }
+
+ // always return the master stub for nsISupports
+ if (aIID.Equals(NS_GET_IID(nsISupports)))
+ {
+ *aInstancePtr = master->mXPTCStub;
+ NS_ADDREF(master);
+ return NS_OK;
+ }
+
+ // All Java objects support weak references
+ if (aIID.Equals(NS_GET_IID(nsISupportsWeakReference)))
+ {
+ *aInstancePtr = static_cast<nsISupportsWeakReference*>(master);
+ NS_ADDREF(master);
+ return NS_OK;
+ }
+
+ // does any existing stub support the requested IID?
+ nsJavaXPTCStub *stub = master->FindStubSupportingIID(aIID);
+ if (stub)
+ {
+ *aInstancePtr = stub->mXPTCStub;
+ NS_ADDREF(stub);
+ return NS_OK;
+ }
+
+ JNIEnv* env = GetJNIEnv();
+
+ // Query Java object
+ LOG(("\tCalling Java object queryInterface\n"));
+ jobject javaObject = env->CallObjectMethod(mJavaWeakRef, getReferentMID);
+
+ jmethodID qiMID = 0;
+ jclass clazz = env->GetObjectClass(javaObject);
+ if (clazz) {
+ char* sig = "(Ljava/lang/String;)Lorg/mozilla/interfaces/nsISupports;";
+ qiMID = env->GetMethodID(clazz, "queryInterface", sig);
+ NS_ASSERTION(qiMID, "Failed to get queryInterface method ID");
+ }
+
+ if (qiMID == 0) {
+ env->ExceptionClear();
+ return NS_NOINTERFACE;
+ }
+
+ // construct IID string
+ jstring iid_jstr = nsnull;
+ char* iid_str = aIID.ToString();
+ if (iid_str) {
+ iid_jstr = env->NewStringUTF(iid_str);
+ }
+ if (!iid_str || !iid_jstr) {
+ env->ExceptionClear();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ PR_Free(iid_str);
+
+ // call queryInterface method
+ jobject obj = env->CallObjectMethod(javaObject, qiMID, iid_jstr);
+ if (env->ExceptionCheck()) {
+ env->ExceptionClear();
+ return NS_ERROR_FAILURE;
+ }
+ if (!obj)
+ return NS_NOINTERFACE;
+
+ // Get interface info for new java object
+ nsCOMPtr<nsIInterfaceInfoManager>
+ iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ rv = iim->GetInfoForIID(&aIID, getter_AddRefs(iinfo));
+ if (NS_FAILED(rv))
+ return rv;
+
+ stub = new nsJavaXPTCStub(obj, iinfo, &rv);
+ if (!stub)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (NS_FAILED(rv)) {
+ delete stub;
+ return rv;
+ }
+
+ // add stub to the master's list of children, so we can preserve
+ // symmetry in future QI calls. the master will delete each child
+ // when it is destroyed. the refcount of each child is bound to
+ // the refcount of the master. this is done to deal with code
+ // like this:
+ //
+ // nsCOMPtr<nsIBar> bar = ...;
+ // nsIFoo *foo;
+ // {
+ // nsCOMPtr<nsIFoo> temp = do_QueryInterface(bar);
+ // foo = temp;
+ // }
+ // foo->DoStuff();
+ //
+ // while this code is not valid XPCOM (since it is using |foo|
+ // after having called Release on it), such code is unfortunately
+ // very common in the mozilla codebase. the assumption this code
+ // is making is that so long as |bar| is alive, it should be valid
+ // to access |foo| even if the code doesn't own a strong reference
+ // to |foo|! clearly wrong, but we need to support it anyways.
+
+ stub->mMaster = master;
+ master->mChildren.AppendElement(stub);
+
+ *aInstancePtr = stub->mXPTCStub;
+ NS_ADDREF(stub);
+ return NS_OK;
+}
+
+PRBool
+nsJavaXPTCStub::SupportsIID(const nsID &iid)
+{
+ PRBool match;
+ nsCOMPtr<nsIInterfaceInfo> iter = mIInfo;
+ do
+ {
+ if (NS_SUCCEEDED(iter->IsIID(&iid, &match)) && match)
+ return PR_TRUE;
+
+ nsCOMPtr<nsIInterfaceInfo> parent;
+ iter->GetParent(getter_AddRefs(parent));
+ iter = parent;
+ }
+ while (iter != nsnull);
+
+ return PR_FALSE;
+}
+
+nsJavaXPTCStub *
+nsJavaXPTCStub::FindStubSupportingIID(const nsID &iid)
+{
+ NS_ASSERTION(mMaster == nsnull, "this is not a master stub");
+
+ if (SupportsIID(iid))
+ return this;
+
+ for (PRInt32 i = 0; i < mChildren.Count(); i++)
+ {
+ nsJavaXPTCStub *child = (nsJavaXPTCStub *) mChildren[i];
+ if (child->SupportsIID(iid))
+ return child;
+ }
+ return nsnull;
+}
+
+NS_IMETHODIMP
+nsJavaXPTCStub::CallMethod(PRUint16 aMethodIndex,
+ const XPTMethodDescriptor *aMethodInfo,
+ nsXPTCMiniVariant *aParams)
+{
+#ifdef DEBUG_JAVAXPCOM
+ const char* ifaceName;
+ mIInfo->GetNameShared(&ifaceName);
+ LOG(("---> (Java) %s::%s()\n", ifaceName, aMethodInfo->name));
+#endif
+
+ nsresult rv = NS_OK;
+ JNIEnv* env = GetJNIEnv();
+ jobject javaObject = env->CallObjectMethod(mJavaWeakRef, getReferentMID);
+
+ nsCAutoString methodSig("(");
+
+ // Create jvalue array to hold Java params
+ PRUint8 paramCount = aMethodInfo->num_args;
+ jvalue* java_params = nsnull;
+ const nsXPTParamInfo* retvalInfo = nsnull;
+ if (paramCount) {
+ java_params = new jvalue[paramCount];
+ if (!java_params)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
+ {
+ const nsXPTParamInfo &paramInfo = aMethodInfo->params[i];
+ if (!paramInfo.IsRetval()) {
+ rv = SetupJavaParams(paramInfo, aMethodInfo, aMethodIndex, aParams,
+ aParams[i], java_params[i], methodSig);
+ } else {
+ retvalInfo = &paramInfo;
+ }
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "SetupJavaParams failed");
+ }
+
+ // Finish method signature
+ if (NS_SUCCEEDED(rv)) {
+ methodSig.Append(')');
+ if (retvalInfo) {
+ nsCAutoString retvalSig;
+ rv = GetRetvalSig(retvalInfo, aMethodInfo, aMethodIndex, aParams,
+ retvalSig);
+ methodSig.Append(retvalSig);
+ } else {
+ methodSig.Append('V');
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "GetRetvalSig failed");
+ }
+
+ // Get Java method to call
+ jmethodID mid = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ nsCAutoString methodName;
+ if (XPT_MD_IS_GETTER(aMethodInfo->flags) ||
+ XPT_MD_IS_SETTER(aMethodInfo->flags)) {
+ if (XPT_MD_IS_GETTER(aMethodInfo->flags))
+ methodName.AppendLiteral("get");
+ else
+ methodName.AppendLiteral("set");
+ methodName.AppendASCII(aMethodInfo->name);
+ methodName.SetCharAt(toupper(methodName[3]), 3);
+ } else {
+ methodName.AppendASCII(aMethodInfo->name);
+ methodName.SetCharAt(tolower(methodName[0]), 0);
+ }
+ // If it's a Java keyword, then prepend an underscore
+ if (gJavaKeywords->GetEntry(methodName.get())) {
+ methodName.Insert('_', 0);
+ }
+
+ jclass clazz = env->GetObjectClass(javaObject);
+ if (clazz)
+ mid = env->GetMethodID(clazz, methodName.get(), methodSig.get());
+ NS_ASSERTION(mid, "Failed to get requested method for Java object");
+ if (!mid)
+ rv = NS_ERROR_FAILURE;
+ }
+
+ // Call method
+ jvalue retval;
+ if (NS_SUCCEEDED(rv)) {
+ if (!retvalInfo) {
+ env->CallVoidMethodA(javaObject, mid, java_params);
+ } else {
+ switch (retvalInfo->GetType().TagPart())
+ {
+ case nsXPTType::T_I8:
+ retval.b = env->CallByteMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8:
+ retval.s = env->CallShortMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16:
+ retval.i = env->CallIntMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32:
+ retval.j = env->CallLongMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ retval.f = env->CallFloatMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ retval.d = env->CallDoubleMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_BOOL:
+ retval.z = env->CallBooleanMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ retval.c = env->CallCharMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_IID:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ retval.l = env->CallObjectMethodA(javaObject, mid, java_params);
+ break;
+
+ case nsXPTType::T_VOID:
+ retval.j = env->CallLongMethodA(javaObject, mid, java_params);
+ break;
+
+ default:
+ NS_WARNING("Unhandled retval type");
+ break;
+ }
+ }
+
+ // Check for exception from called Java function
+ jthrowable exp = env->ExceptionOccurred();
+ if (exp) {
+ // If the exception is an instance of XPCOMException, then get the
+ // nsresult from the exception instance. Else, default to
+ // NS_ERROR_FAILURE.
+ if (env->IsInstanceOf(exp, xpcomExceptionClass)) {
+ jfieldID fid;
+ fid = env->GetFieldID(xpcomExceptionClass, "errorcode", "J");
+ if (fid) {
+ rv = env->GetLongField(exp, fid);
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+ NS_ASSERTION(fid, "Couldn't get 'errorcode' field of XPCOMException");
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ }
+
+ // Handle any 'inout', 'out' and 'retval' params
+ if (NS_SUCCEEDED(rv)) {
+ for (PRUint8 i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo &paramInfo = aMethodInfo->params[i];
+ if (paramInfo.IsIn() && !paramInfo.IsOut() && !paramInfo.IsDipper()) // 'in'
+ continue;
+
+ // If param is null, then caller is not expecting an output value.
+ if (aParams[i].val.p == nsnull)
+ continue;
+
+ if (!paramInfo.IsRetval()) {
+ rv = FinalizeJavaParams(paramInfo, aMethodInfo, aMethodIndex, aParams,
+ aParams[i], java_params[i]);
+ } else {
+ rv = FinalizeJavaParams(paramInfo, aMethodInfo, aMethodIndex, aParams,
+ aParams[i], retval);
+ }
+ }
+ NS_ASSERTION(NS_SUCCEEDED(rv), "FinalizeJavaParams/SetXPCOMRetval failed");
+ }
+
+ if (java_params)
+ delete [] java_params;
+
+#ifdef DEBUG
+ if (env->ExceptionCheck())
+ env->ExceptionDescribe();
+#endif
+ env->ExceptionClear();
+
+ LOG(("<--- (Java) %s::%s()\n", ifaceName, aMethodInfo->name));
+ return rv;
+}
+
+/**
+ * Handle 'in', 'inout', and 'out' params
+ */
+nsresult
+nsJavaXPTCStub::SetupJavaParams(const nsXPTParamInfo &aParamInfo,
+ const XPTMethodDescriptor* aMethodInfo,
+ PRUint16 aMethodIndex,
+ nsXPTCMiniVariant* aDispatchParams,
+ nsXPTCMiniVariant &aVariant, jvalue &aJValue,
+ nsACString &aMethodSig)
+{
+ nsresult rv = NS_OK;
+ JNIEnv* env = GetJNIEnv();
+ const nsXPTType &type = aParamInfo.GetType();
+
+ PRUint8 tag = type.TagPart();
+ switch (tag)
+ {
+ case nsXPTType::T_I8:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.b = aVariant.val.i8;
+ aMethodSig.Append('B');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jbyteArray array = env->NewByteArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetByteArrayRegion(array, 0, 1, (jbyte*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[B");
+ }
+ }
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.s = (tag == nsXPTType::T_I16) ? aVariant.val.i16 :
+ aVariant.val.u8;
+ aMethodSig.Append('S');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jshortArray array = env->NewShortArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetShortArrayRegion(array, 0, 1, (jshort*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[S");
+ }
+ }
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.i = (tag == nsXPTType::T_I32) ? aVariant.val.i32 :
+ aVariant.val.u16;
+ aMethodSig.Append('I');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jintArray array = env->NewIntArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetIntArrayRegion(array, 0, 1, (jint*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[I");
+ }
+ }
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.j = (tag == nsXPTType::T_I64) ? aVariant.val.i64 :
+ aVariant.val.u32;
+ aMethodSig.Append('J');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jlongArray array = env->NewLongArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetLongArrayRegion(array, 0, 1, (jlong*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[J");
+ }
+ }
+ break;
+
+ case nsXPTType::T_FLOAT:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.f = aVariant.val.f;
+ aMethodSig.Append('F');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jfloatArray array = env->NewFloatArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetFloatArrayRegion(array, 0, 1, (jfloat*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[F");
+ }
+ }
+ break;
+
+ // XXX how do we handle unsigned 64-bit values?
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.d = (tag == nsXPTType::T_DOUBLE) ? aVariant.val.d :
+ aVariant.val.u64;
+ aMethodSig.Append('D');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jdoubleArray array = env->NewDoubleArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetDoubleArrayRegion(array, 0, 1, (jdouble*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[D");
+ }
+ }
+ break;
+
+ case nsXPTType::T_BOOL:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.z = aVariant.val.b;
+ aMethodSig.Append('Z');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jbooleanArray array = env->NewBooleanArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetBooleanArrayRegion(array, 0, 1, (jboolean*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[Z");
+ }
+ }
+ break;
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ if (tag == nsXPTType::T_CHAR)
+ aJValue.c = aVariant.val.c;
+ else
+ aJValue.c = aVariant.val.wc;
+ aMethodSig.Append('C');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jcharArray array = env->NewCharArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetCharArrayRegion(array, 0, 1, (jchar*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[C");
+ }
+ }
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ {
+ void* ptr = nsnull;
+ if (!aParamInfo.IsOut()) { // 'in'
+ ptr = aVariant.val.p;
+ } else if (aVariant.val.p) { // 'inout' & 'out'
+ void** variant = static_cast<void**>(aVariant.val.p);
+ ptr = *variant;
+ }
+
+ jobject str;
+ if (ptr) {
+ if (tag == nsXPTType::T_CHAR_STR) {
+ str = env->NewStringUTF((const char*) ptr);
+ } else {
+ const PRUnichar* buf = (const PRUnichar*) ptr;
+ str = env->NewString(buf, nsCRT::strlen(buf));
+ }
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ } else {
+ str = nsnull;
+ }
+
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.l = str;
+ aMethodSig.AppendLiteral("Ljava/lang/String;");
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ aJValue.l = env->NewObjectArray(1, stringClass, str);
+ if (aJValue.l == nsnull) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[Ljava/lang/String;");
+ }
+ }
+ break;
+
+ case nsXPTType::T_IID:
+ {
+ nsID* iid = nsnull;
+ if (!aParamInfo.IsOut()) { // 'in'
+ iid = static_cast<nsID*>(aVariant.val.p);
+ } else if (aVariant.val.p) { // 'inout' & 'out'
+ nsID** variant = static_cast<nsID**>(aVariant.val.p);
+ iid = *variant;
+ }
+
+ jobject str = nsnull;
+ if (iid) {
+ char iid_str[NSID_LENGTH];
+ iid->ToProvidedString(iid_str);
+ str = env->NewStringUTF(iid_str);
+ if (!str) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.l = str;
+ aMethodSig.AppendLiteral("Ljava/lang/String;");
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ aJValue.l = env->NewObjectArray(1, stringClass, str);
+ if (aJValue.l == nsnull) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[Ljava/lang/String;");
+ }
+ }
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ nsISupports* xpcom_obj = nsnull;
+ if (!aParamInfo.IsOut()) { // 'in'
+ xpcom_obj = static_cast<nsISupports*>(aVariant.val.p);
+ } else if (aVariant.val.p) { // 'inout' & 'out'
+ nsISupports** variant = static_cast<nsISupports**>(aVariant.val.p);
+ xpcom_obj = *variant;
+ }
+
+ nsID iid;
+ rv = GetIIDForMethodParam(mIInfo, aMethodInfo, aParamInfo,
+ aParamInfo.GetType().TagPart(), aMethodIndex,
+ aDispatchParams, PR_FALSE, iid);
+ if (NS_FAILED(rv))
+ break;
+
+ // get name of interface
+ char* iface_name = nsnull;
+ nsCOMPtr<nsIInterfaceInfoManager>
+ iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ break;
+
+ rv = iim->GetNameForIID(&iid, &iface_name);
+ if (NS_FAILED(rv) || !iface_name)
+ break;
+
+ jobject java_stub = nsnull;
+ if (xpcom_obj) {
+ // Get matching Java object for given xpcom object
+ jobject objLoader = env->CallObjectMethod(mJavaWeakRef, getReferentMID);
+ rv = NativeInterfaceToJavaObject(env, xpcom_obj, iid, objLoader,
+ &java_stub);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.l = java_stub;
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ aJValue.l = env->NewObjectArray(1, nsISupportsClass, java_stub);
+ if (aJValue.l == nsnull) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.Append('[');
+ }
+
+ if (tag != nsXPTType::T_INTERFACE_IS) {
+ aMethodSig.AppendLiteral("Lorg/mozilla/interfaces/");
+ aMethodSig.AppendASCII(iface_name);
+ aMethodSig.Append(';');
+ } else {
+ aMethodSig.AppendLiteral("Lorg/mozilla/interfaces/nsISupports;");
+ }
+
+ nsMemory::Free(iface_name);
+ }
+ break;
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ // This only handle 'in' or 'in dipper' params. In XPIDL, the 'out'
+ // descriptor is mapped to 'in dipper'.
+ NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
+ if (!aParamInfo.IsIn()) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ nsString* str = static_cast<nsString*>(aVariant.val.p);
+ if (!str) {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ jstring jstr = nsnull;
+ if (!str->IsVoid()) {
+ jstr = env->NewString(str->get(), str->Length());
+ if (!jstr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ aJValue.l = jstr;
+ aMethodSig.AppendLiteral("Ljava/lang/String;");
+ }
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ // This only handle 'in' or 'in dipper' params. In XPIDL, the 'out'
+ // descriptor is mapped to 'in dipper'.
+ NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
+ if (!aParamInfo.IsIn()) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ nsCString* str = static_cast<nsCString*>(aVariant.val.p);
+ if (!str) {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ jstring jstr = nsnull;
+ if (!str->IsVoid()) {
+ jstr = env->NewStringUTF(str->get());
+ if (!jstr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ }
+
+ aJValue.l = jstr;
+ aMethodSig.AppendLiteral("Ljava/lang/String;");
+ }
+ break;
+
+ // Pass the 'void*' address as a long
+ case nsXPTType::T_VOID:
+ {
+ if (!aParamInfo.IsOut()) { // 'in'
+ aJValue.j = reinterpret_cast<jlong>(aVariant.val.p);
+ aMethodSig.Append('J');
+ } else { // 'inout' & 'out'
+ if (aVariant.val.p) {
+ jlongArray array = env->NewLongArray(1);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ env->SetLongArrayRegion(array, 0, 1, (jlong*) aVariant.val.p);
+ aJValue.l = array;
+ } else {
+ aJValue.l = nsnull;
+ }
+ aMethodSig.AppendLiteral("[J");
+ }
+ }
+ break;
+
+ case nsXPTType::T_ARRAY:
+ NS_WARNING("array types are not yet supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+ break;
+
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ default:
+ NS_WARNING("unexpected parameter type");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return rv;
+}
+
+nsresult
+nsJavaXPTCStub::GetRetvalSig(const nsXPTParamInfo* aParamInfo,
+ const XPTMethodDescriptor* aMethodInfo,
+ PRUint16 aMethodIndex,
+ nsXPTCMiniVariant* aDispatchParams,
+ nsACString &aRetvalSig)
+{
+ PRUint8 type = aParamInfo->GetType().TagPart();
+ switch (type)
+ {
+ case nsXPTType::T_I8:
+ aRetvalSig.Append('B');
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8:
+ aRetvalSig.Append('S');
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16:
+ aRetvalSig.Append('I');
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32:
+ aRetvalSig.Append('J');
+ break;
+
+ case nsXPTType::T_FLOAT:
+ aRetvalSig.Append('F');
+ break;
+
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ aRetvalSig.Append('D');
+ break;
+
+ case nsXPTType::T_BOOL:
+ aRetvalSig.Append('Z');
+ break;
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ aRetvalSig.Append('C');
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_IID:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ aRetvalSig.AppendLiteral("Ljava/lang/String;");
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ {
+ nsID iid;
+ nsresult rv = GetIIDForMethodParam(mIInfo, aMethodInfo, *aParamInfo, type,
+ aMethodIndex, aDispatchParams,
+ PR_FALSE, iid);
+ if (NS_FAILED(rv))
+ break;
+
+ // get name of interface
+ char* iface_name = nsnull;
+ nsCOMPtr<nsIInterfaceInfoManager>
+ iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ break;
+
+ rv = iim->GetNameForIID(&iid, &iface_name);
+ if (NS_FAILED(rv) || !iface_name)
+ break;
+
+ aRetvalSig.AppendLiteral("Lorg/mozilla/interfaces/");
+ aRetvalSig.AppendASCII(iface_name);
+ aRetvalSig.Append(';');
+ nsMemory::Free(iface_name);
+ break;
+ }
+
+ case nsXPTType::T_INTERFACE_IS:
+ aRetvalSig.AppendLiteral("Lorg/mozilla/interfaces/nsISupports;");
+ break;
+
+ case nsXPTType::T_VOID:
+ aRetvalSig.Append('J');
+ break;
+
+ case nsXPTType::T_ARRAY:
+ NS_WARNING("array types are not yet supported");
+ return NS_ERROR_NOT_IMPLEMENTED;
+ break;
+
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ default:
+ NS_WARNING("unexpected parameter type");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+/**
+ * Handle 'inout', 'out', and 'retval' params
+ */
+nsresult
+nsJavaXPTCStub::FinalizeJavaParams(const nsXPTParamInfo &aParamInfo,
+ const XPTMethodDescriptor *aMethodInfo,
+ PRUint16 aMethodIndex,
+ nsXPTCMiniVariant* aDispatchParams,
+ nsXPTCMiniVariant &aVariant, jvalue &aJValue)
+{
+ nsresult rv = NS_OK;
+ JNIEnv* env = GetJNIEnv();
+ const nsXPTType &type = aParamInfo.GetType();
+
+ PRUint8 tag = type.TagPart();
+ switch (tag)
+ {
+ case nsXPTType::T_I8:
+ {
+ jbyte value;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ value = aJValue.b;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetByteArrayRegion((jbyteArray) aJValue.l, 0, 1, &value);
+ }
+ if (aVariant.val.p)
+ *((PRInt8 *) aVariant.val.p) = value;
+ }
+ break;
+
+ case nsXPTType::T_U8:
+ case nsXPTType::T_I16:
+ {
+ jshort value = 0;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ value = aJValue.s;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetShortArrayRegion((jshortArray) aJValue.l, 0, 1, &value);
+ }
+
+ if (aVariant.val.p) {
+ if (tag == nsXPTType::T_U8)
+ *((PRUint8 *) aVariant.val.p) = value;
+ else
+ *((PRInt16 *) aVariant.val.p) = value;
+ }
+ }
+ break;
+
+ case nsXPTType::T_U16:
+ case nsXPTType::T_I32:
+ {
+ jint value = 0;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ value = aJValue.i;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetIntArrayRegion((jintArray) aJValue.l, 0, 1, &value);
+ }
+
+ if (aVariant.val.p) {
+ if (tag == nsXPTType::T_U16)
+ *((PRUint16 *) aVariant.val.p) = value;
+ else
+ *((PRInt32 *) aVariant.val.p) = value;
+ }
+ }
+ break;
+
+ case nsXPTType::T_U32:
+ case nsXPTType::T_I64:
+ {
+ jlong value = 0;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ value = aJValue.j;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetLongArrayRegion((jlongArray) aJValue.l, 0, 1, &value);
+ }
+
+ if (aVariant.val.p) {
+ if (tag == nsXPTType::T_U32)
+ *((PRUint32 *) aVariant.val.p) = value;
+ else
+ *((PRInt64 *) aVariant.val.p) = value;
+ }
+ }
+ break;
+
+ case nsXPTType::T_FLOAT:
+ {
+ if (aParamInfo.IsRetval()) { // 'retval'
+ *((float *) aVariant.val.p) = aJValue.f;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetFloatArrayRegion((jfloatArray) aJValue.l, 0, 1,
+ (jfloat*) aVariant.val.p);
+ }
+ }
+ break;
+
+ // XXX how do we handle 64-bit values?
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ {
+ jdouble value = 0;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ value = aJValue.d;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetDoubleArrayRegion((jdoubleArray) aJValue.l, 0, 1, &value);
+ }
+
+ if (aVariant.val.p) {
+ if (tag == nsXPTType::T_DOUBLE)
+ *((double *) aVariant.val.p) = value;
+ else
+ *((PRUint64 *) aVariant.val.p) = static_cast<PRUint64>(value);
+ }
+ }
+ break;
+
+ case nsXPTType::T_BOOL:
+ {
+ if (aParamInfo.IsRetval()) { // 'retval'
+ *((PRBool *) aVariant.val.p) = aJValue.z;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetBooleanArrayRegion((jbooleanArray) aJValue.l, 0, 1,
+ (jboolean*) aVariant.val.p);
+ }
+ }
+ break;
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ {
+ if (aParamInfo.IsRetval()) { // 'retval'
+ if (type.TagPart() == nsXPTType::T_CHAR)
+ *((char *) aVariant.val.p) = aJValue.c;
+ else
+ *((PRUnichar *) aVariant.val.p) = aJValue.c;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ jchar* array = env->GetCharArrayElements((jcharArray) aJValue.l,
+ nsnull);
+ if (!array) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ if (type.TagPart() == nsXPTType::T_CHAR)
+ *((char *) aVariant.val.p) = array[0];
+ else
+ *((PRUnichar *) aVariant.val.p) = array[0];
+
+ env->ReleaseCharArrayElements((jcharArray) aJValue.l, array, JNI_ABORT);
+ }
+ }
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ {
+ jstring str = nsnull;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ str = (jstring) aJValue.l;
+ } else { // 'inout' & 'out'
+ str = (jstring) env->GetObjectArrayElement((jobjectArray) aJValue.l, 0);
+ }
+
+ char** variant = static_cast<char**>(aVariant.val.p);
+ if (str) {
+ // Get string buffer
+ const char* char_ptr = env->GetStringUTFChars(str, nsnull);
+ if (!char_ptr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ // If new string is different from one passed in, free old string
+ // and replace with new string.
+ if (aParamInfo.IsRetval() ||
+ *variant == nsnull || strcmp(*variant, char_ptr) != 0)
+ {
+ if (!aParamInfo.IsRetval() && *variant)
+ PR_Free(*variant);
+
+ *variant = strdup(char_ptr);
+ if (*variant == nsnull) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ // don't 'break'; fall through to release chars
+ }
+ }
+
+ // Release string buffer
+ env->ReleaseStringUTFChars(str, char_ptr);
+ } else {
+ // If we were passed in a string, delete it now, and set to null.
+ // (Only for 'inout' & 'out' params)
+ if (*variant && !aParamInfo.IsRetval()) {
+ PR_Free(*variant);
+ }
+ *variant = nsnull;
+ }
+ }
+ break;
+
+ case nsXPTType::T_WCHAR_STR:
+ {
+ jstring str = nsnull;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ str = (jstring) aJValue.l;
+ } else { // 'inout' & 'out'
+ str = (jstring) env->GetObjectArrayElement((jobjectArray) aJValue.l, 0);
+ }
+
+ PRUnichar** variant = static_cast<PRUnichar**>(aVariant.val.p);
+ if (str) {
+ // Get string buffer
+ const jchar* wchar_ptr = env->GetStringChars(str, nsnull);
+ if (!wchar_ptr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ // If new string is different from one passed in, free old string
+ // and replace with new string. We
+ if (aParamInfo.IsRetval() ||
+ *variant == nsnull || nsCRT::strcmp(*variant, wchar_ptr) != 0)
+ {
+ if (!aParamInfo.IsRetval() && *variant)
+ PR_Free(*variant);
+
+ PRUint32 length = nsCRT::strlen(wchar_ptr);
+ *variant = (PRUnichar*) PR_Malloc((length + 1) * sizeof(PRUnichar));
+ if (*variant) {
+ memcpy(*variant, wchar_ptr, length * sizeof(PRUnichar));
+ (*variant)[length] = 0;
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ // don't 'break'; fall through to release chars
+ }
+ }
+
+ // Release string buffer
+ env->ReleaseStringChars(str, wchar_ptr);
+ } else {
+ // If we were passed in a string, delete it now, and set to null.
+ // (Only for 'inout' & 'out' params)
+ if (*variant && !aParamInfo.IsRetval()) {
+ PR_Free(*variant);
+ }
+ *variant = nsnull;
+ }
+ }
+ break;
+
+ case nsXPTType::T_IID:
+ {
+ jstring str = nsnull;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ str = (jstring) aJValue.l;
+ } else { // 'inout' & 'out'
+ str = (jstring) env->GetObjectArrayElement((jobjectArray) aJValue.l, 0);
+ }
+
+ nsID** variant = static_cast<nsID**>(aVariant.val.p);
+ if (str) {
+ // Get string buffer
+ const char* char_ptr = env->GetStringUTFChars(str, nsnull);
+ if (!char_ptr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ if (!aParamInfo.IsRetval() && *variant) {
+ // If we were given an nsID, set it to the new string
+ nsID* oldIID = *variant;
+ oldIID->Parse(char_ptr);
+ } else {
+ // If the argument that was passed in was null, then we need to
+ // create a new nsID.
+ nsID* newIID = new nsID;
+ if (newIID) {
+ newIID->Parse(char_ptr);
+ *variant = newIID;
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ // don't 'break'; fall through to release chars
+ }
+ }
+
+ // Release string buffer
+ env->ReleaseStringUTFChars(str, char_ptr);
+ } else {
+ // If we were passed in an nsID, delete it now, and set to null.
+ // (Free only 'inout' & 'out' params)
+ if (*variant && !aParamInfo.IsRetval()) {
+ delete *variant;
+ }
+ *variant = nsnull;
+ }
+ }
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ {
+ jobject java_obj = nsnull;
+ if (aParamInfo.IsRetval()) { // 'retval'
+ java_obj = aJValue.l;
+ } else if (aJValue.l) { // 'inout' & 'out'
+ java_obj = env->GetObjectArrayElement((jobjectArray) aJValue.l, 0);
+ }
+
+ void* xpcom_obj = nsnull;
+ if (java_obj) {
+ // Get IID for this param
+ nsID iid;
+ rv = GetIIDForMethodParam(mIInfo, aMethodInfo, aParamInfo,
+ aParamInfo.GetType().TagPart(), aMethodIndex,
+ aDispatchParams, PR_FALSE, iid);
+ if (NS_FAILED(rv))
+ break;
+
+ // If the requested interface is nsIWeakReference, then we look for or
+ // create a stub for the nsISupports interface. Then we create a weak
+ // reference from that stub.
+ PRBool isWeakRef;
+ if (iid.Equals(NS_GET_IID(nsIWeakReference))) {
+ isWeakRef = PR_TRUE;
+ iid = NS_GET_IID(nsISupports);
+ } else {
+ isWeakRef = PR_FALSE;
+ }
+
+ rv = JavaObjectToNativeInterface(env, java_obj, iid, &xpcom_obj);
+ if (NS_FAILED(rv))
+ break;
+ rv = ((nsISupports*) xpcom_obj)->QueryInterface(iid, &xpcom_obj);
+ if (NS_FAILED(rv))
+ break;
+
+ // If the function expects a weak reference, then we need to
+ // create it here.
+ if (isWeakRef) {
+ nsISupports* isupports = (nsISupports*) xpcom_obj;
+ nsCOMPtr<nsISupportsWeakReference> supportsweak =
+ do_QueryInterface(isupports);
+ if (supportsweak) {
+ nsWeakPtr weakref;
+ supportsweak->GetWeakReference(getter_AddRefs(weakref));
+ NS_RELEASE(isupports);
+ xpcom_obj = weakref;
+ NS_ADDREF((nsISupports*) xpcom_obj);
+ } else {
+ xpcom_obj = nsnull;
+ }
+ }
+ }
+
+ // For 'inout' params, if the resulting xpcom value is different than the
+ // one passed in, then we must release the incoming xpcom value.
+ nsISupports** variant = static_cast<nsISupports**>(aVariant.val.p);
+ if (aParamInfo.IsIn() && *variant) {
+ nsCOMPtr<nsISupports> in = do_QueryInterface(*variant);
+ nsCOMPtr<nsISupports> out = do_QueryInterface((nsISupports*) xpcom_obj);
+ if (in != out) {
+ NS_RELEASE(*variant);
+ }
+ }
+
+ *(static_cast<void**>(aVariant.val.p)) = xpcom_obj;
+ }
+ break;
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ {
+ NS_PRECONDITION(aParamInfo.IsDipper(), "string argument is not dipper");
+ if (!aParamInfo.IsDipper()) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ jstring jstr = (jstring) aJValue.l;
+ nsString* variant = static_cast<nsString*>(aVariant.val.p);
+
+ if (jstr) {
+ // Get string buffer
+ const jchar* wchar_ptr = env->GetStringChars(jstr, nsnull);
+ if (!wchar_ptr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ variant->Assign(wchar_ptr);
+
+ // release String buffer
+ env->ReleaseStringChars(jstr, wchar_ptr);
+ } else {
+ variant->SetIsVoid(PR_TRUE);
+ }
+ }
+ break;
+
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ {
+ NS_PRECONDITION(aParamInfo.IsDipper(), "string argument is not dipper");
+ if (!aParamInfo.IsDipper()) {
+ rv = NS_ERROR_UNEXPECTED;
+ break;
+ }
+
+ jstring jstr = (jstring) aJValue.l;
+ nsCString* variant = static_cast<nsCString*>(aVariant.val.p);
+
+ if (jstr) {
+ // Get string buffer
+ const char* char_ptr = env->GetStringUTFChars(jstr, nsnull);
+ if (!char_ptr) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+
+ variant->Assign(char_ptr);
+
+ // release String buffer
+ env->ReleaseStringUTFChars(jstr, char_ptr);
+ } else {
+ variant->SetIsVoid(PR_TRUE);
+ }
+ }
+ break;
+
+ case nsXPTType::T_VOID:
+ {
+ if (aParamInfo.IsRetval()) { // 'retval'
+ aVariant.val.p = reinterpret_cast<void*>(aJValue.j);
+ } else if (aJValue.l) { // 'inout' & 'out'
+ env->GetLongArrayRegion((jlongArray) aJValue.l, 0, 1,
+ (jlong*) aVariant.val.p);
+ }
+ }
+ break;
+
+ default:
+ NS_WARNING("unexpected parameter type");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsJavaXPTCStub::GetWeakReference(nsIWeakReference** aInstancePtr)
+{
+ if (mMaster)
+ return mMaster->GetWeakReference(aInstancePtr);
+
+ LOG(("==> nsJavaXPTCStub::GetWeakReference()\n"));
+
+ if (!aInstancePtr)
+ return NS_ERROR_NULL_POINTER;
+
+ jobject javaObject = GetJNIEnv()->CallObjectMethod(mJavaWeakRef,
+ getReferentMID);
+ nsJavaXPTCStubWeakRef* weakref;
+ weakref = new nsJavaXPTCStubWeakRef(javaObject, this);
+ if (!weakref)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *aInstancePtr = weakref;
+ NS_ADDREF(*aInstancePtr);
+ ++mWeakRefCnt;
+
+ return NS_OK;
+}
+
+jobject
+nsJavaXPTCStub::GetJavaObject()
+{
+ JNIEnv* env = GetJNIEnv();
+ jobject javaObject = env->CallObjectMethod(mJavaWeakRef, getReferentMID);
+
+#ifdef DEBUG_JAVAXPCOM
+ nsIID* iid;
+ mIInfo->GetInterfaceIID(&iid);
+ char* iid_str = iid->ToString();
+ LOG(("< nsJavaXPTCStub (Java=%08x | XPCOM=%08x | IID=%s)\n",
+ (PRUint32) mJavaRefHashCode, (PRUint32) this, iid_str));
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+#endif
+
+ return javaObject;
+}
+
+
+/*static*/ nsresult
+nsJavaXPTCStub::GetNewOrUsed(JNIEnv* env, jobject aJavaObject,
+ const nsIID& aIID, void** aResult)
+{
+ nsJavaXPTCStub* stub;
+ jint hash = env->CallStaticIntMethod(systemClass, hashCodeMID, aJavaObject);
+ nsresult rv = gJavaToXPTCStubMap->Find(hash, aIID, &stub);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (stub) {
+ // stub is already AddRef'd and QI'd
+ *aResult = stub;
+ return NS_OK;
+ }
+
+ // If there is no corresponding XPCOM object, then that means that the
+ // parameter is a non-generated class (that is, it is not one of our
+ // Java stubs that represent an exising XPCOM object). So we need to
+ // create an XPCOM stub, that can route any method calls to the class.
+
+ // Get interface info for class
+ nsCOMPtr<nsIInterfaceInfoManager>
+ iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIInterfaceInfo> iinfo;
+ rv = iim->GetInfoForIID(&aIID, getter_AddRefs(iinfo));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Create XPCOM stub
+ stub = new nsJavaXPTCStub(aJavaObject, iinfo, &rv);
+ if (!stub)
+ return NS_ERROR_OUT_OF_MEMORY;
+ if (NS_FAILED(rv)) {
+ delete stub;
+ return rv;
+ }
+
+ rv = gJavaToXPTCStubMap->Add(hash, stub);
+ if (NS_FAILED(rv)) {
+ delete stub;
+ return rv;
+ }
+
+ NS_ADDREF(stub);
+ *aResult = stub;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPTCStub.h b/src/libs/xpcom18a4/java/src/nsJavaXPTCStub.h
new file mode 100644
index 00000000..90d42c8f
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPTCStub.h
@@ -0,0 +1,153 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+#ifndef _nsJavaXPTCStub_h_
+#define _nsJavaXPTCStub_h_
+
+#include "nsXPTCUtils.h"
+#include "jni.h"
+#include "nsVoidArray.h"
+#include "nsIInterfaceInfo.h"
+#include "nsCOMPtr.h"
+#include "nsWeakReference.h"
+#include "nsJavaXPTCStubWeakRef.h"
+
+
+#define NS_JAVAXPTCSTUB_IID \
+{0x88dd8130, 0xebe6, 0x4431, {0x9d, 0xa7, 0xe6, 0xb7, 0x54, 0x74, 0xfb, 0x21}}
+
+class nsJavaXPTCStub : protected nsAutoXPTCStub,
+ public nsSupportsWeakReference
+{
+ friend class nsJavaXPTCStubWeakRef;
+
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSWEAKREFERENCE
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_JAVAXPTCSTUB_IID)
+
+ nsJavaXPTCStub(jobject aJavaObject, nsIInterfaceInfo *aIInfo,
+ nsresult *rv);
+
+ virtual ~nsJavaXPTCStub();
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 aMethodIndex,
+ const XPTMethodDescriptor *aInfo,
+ nsXPTCMiniVariant *aParams);
+
+ nsISomeInterface* GetStub() { return mXPTCStub; }
+
+ // getter for mJavaObject
+ jobject GetJavaObject();
+
+ // Deletes the strong global ref for the Java object, so it can be garbage
+ // collected if necessary. See DestroyXPTCMappingEnum().
+ void DeleteStrongRef();
+
+ /**
+ * Finds the associated nsJavaXPTCStub for the given Java object and IID.
+ * If no such stub exists, then a new one is created.
+ *
+ * @param env Java environment pointer
+ * @param aJavaObject Java object for which to find/create nsJavaXPTCStub
+ * @param aIID desired interface IID for nsJavaXPTCStub
+ * @param aResult on success, holds AddRef'd reference to nsJavaXPTCStub
+ *
+ * @return NS_OK if succeeded; all other return values are error codes.
+ */
+ static nsresult GetNewOrUsed(JNIEnv* env, jobject aJavaObject,
+ const nsIID& aIID, void** aResult);
+
+
+private:
+ NS_IMETHOD_(nsrefcnt) AddRefInternal();
+ NS_IMETHOD_(nsrefcnt) ReleaseInternal();
+
+ // Deletes this object and its members. Called by ReleaseInternal() and
+ // ReleaseWeakRef().
+ void Destroy();
+
+ // When a nsJavaXPTCStubWeakRef associated with this object is released, it
+ // calls this function to let this object know that there is one less weak
+ // ref. If there are no more weakrefs referencing this object, and no one
+ // holds a strong ref, then this function takes care of deleting the object.
+ void ReleaseWeakRef();
+
+ // returns a weak reference to a child supporting the specified interface
+ nsJavaXPTCStub * FindStubSupportingIID(const nsID &aIID);
+
+ // returns true if this stub supports the specified interface
+ PRBool SupportsIID(const nsID &aIID);
+
+ nsresult SetupJavaParams(const nsXPTParamInfo &aParamInfo,
+ const XPTMethodDescriptor* aMethodInfo,
+ PRUint16 aMethodIndex,
+ nsXPTCMiniVariant* aDispatchParams,
+ nsXPTCMiniVariant &aVariant,
+ jvalue &aJValue, nsACString &aMethodSig);
+ nsresult GetRetvalSig(const nsXPTParamInfo* aParamInfo,
+ const XPTMethodDescriptor* aMethodInfo,
+ PRUint16 aMethodIndex,
+ nsXPTCMiniVariant* aDispatchParams,
+ nsACString &aRetvalSig);
+ nsresult FinalizeJavaParams(const nsXPTParamInfo &aParamInfo,
+ const XPTMethodDescriptor* aMethodInfo,
+ PRUint16 aMethodIndex,
+ nsXPTCMiniVariant* aDispatchParams,
+ nsXPTCMiniVariant &aVariant,
+ jvalue &aJValue);
+ nsresult SetXPCOMRetval();
+
+ jobject mJavaWeakRef;
+ jobject mJavaStrongRef;
+ jint mJavaRefHashCode;
+ nsCOMPtr<nsIInterfaceInfo> mIInfo;
+
+ nsVoidArray mChildren; // weak references (cleared by the children)
+ nsJavaXPTCStub *mMaster; // strong reference
+
+ nsAutoRefCnt mWeakRefCnt; // count for number of associated weak refs
+};
+
+#ifdef VBOX
+NS_DEFINE_STATIC_IID_ACCESSOR2(nsJavaXPTCStub, NS_JAVAXPTCSTUB_IID)
+#else
+NS_DEFINE_STATIC_IID_ACCESSOR2(nsJavaXPTCStub, NS_JAVAXPTCSTUB_IID)
+#endif
+
+#endif // _nsJavaXPTCStub_h_
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.cpp b/src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.cpp
new file mode 100644
index 00000000..cb98fc9b
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.cpp
@@ -0,0 +1,98 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "jni.h"
+#include "nsJavaXPTCStubWeakRef.h"
+#include "nsJavaXPTCStub.h"
+#include "nsJavaXPCOMBindingUtils.h"
+#include "nsIInterfaceInfoManager.h"
+
+
+/**
+ * How we handle XPCOM weak references to a Java object:
+ *
+ * If XPCOM requires or asks for a weak reference of a Java object, we first
+ * find (or create) an nsJavaXPTCStub for that Java object. That way, there is
+ * always an nsJavaXPTCStub for any nsJavaXPTCStubWeakRef. However, the
+ * XPTCStub may not always be 'valid'; that is, its refcount may be zero if
+ * is not currently referenced by any XPCOM class.
+ * When an XPCOM method queries the referent from the weak reference, the
+ * weak ref checks first whether the Java object is still valid. If so, we can
+ * immediately return an addref'd nsJavaXPTCStub. The XPTCStub takes care of
+ * finding an XPTCStub for the required IID.
+ */
+
+nsJavaXPTCStubWeakRef::nsJavaXPTCStubWeakRef(jobject aJavaObject,
+ nsJavaXPTCStub* aXPTCStub)
+ : mXPTCStub(aXPTCStub)
+{
+ JNIEnv* env = GetJNIEnv();
+ jobject weakref = env->NewObject(weakReferenceClass,
+ weakReferenceConstructorMID, aJavaObject);
+ mWeakRef = env->NewGlobalRef(weakref);
+}
+
+nsJavaXPTCStubWeakRef::~nsJavaXPTCStubWeakRef()
+{
+ JNIEnv* env = GetJNIEnv();
+ env->CallVoidMethod(mWeakRef, clearReferentMID);
+ env->DeleteGlobalRef(mWeakRef);
+ mXPTCStub->ReleaseWeakRef();
+}
+
+NS_IMPL_ADDREF(nsJavaXPTCStubWeakRef)
+NS_IMPL_RELEASE(nsJavaXPTCStubWeakRef)
+
+NS_IMPL_QUERY_INTERFACE1(nsJavaXPTCStubWeakRef, nsIWeakReference)
+
+NS_IMETHODIMP
+nsJavaXPTCStubWeakRef::QueryReferent(const nsIID& aIID, void** aInstancePtr)
+{
+ LOG(("nsJavaXPTCStubWeakRef::QueryReferent()\n"));
+
+ // Is weak ref still valid?
+ // We create a strong local ref to make sure Java object isn't garbage
+ // collected during this call.
+ JNIEnv* env = GetJNIEnv();
+ jobject javaObject = env->CallObjectMethod(mWeakRef, getReferentMID);
+ if (env->IsSameObject(javaObject, NULL))
+ return NS_ERROR_NULL_POINTER;
+
+ // Java object has not been garbage collected, so return QI from XPTCStub.
+ return mXPTCStub->QueryInterface(aIID, aInstancePtr);
+}
+
diff --git a/src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.h b/src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.h
new file mode 100644
index 00000000..b538eecb
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsJavaXPTCStubWeakRef.h
@@ -0,0 +1,63 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+#ifndef _nsJavaXPTCStubWeakRef_h_
+#define _nsJavaXPTCStubWeakRef_h_
+
+#include "jni.h"
+#include "nsIWeakReference.h"
+
+
+class nsJavaXPTCStub;
+
+/**
+ * This class represents an XPCOM weak reference to a Java object.
+ */
+class nsJavaXPTCStubWeakRef : public nsIWeakReference
+{
+public:
+ nsJavaXPTCStubWeakRef(jobject aJavaObject, nsJavaXPTCStub* aXPTCStub);
+ virtual ~nsJavaXPTCStubWeakRef();
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEAKREFERENCE
+
+protected:
+ jobject mWeakRef;
+ nsJavaXPTCStub* mXPTCStub;
+};
+
+#endif // _nsJavaXPTCStubWeakRef_h_
diff --git a/src/libs/xpcom18a4/java/src/nsThreadUtils.h b/src/libs/xpcom18a4/java/src/nsThreadUtils.h
new file mode 100644
index 00000000..53f3dbdb
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsThreadUtils.h
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsThreadUtils_h__
+#define nsThreadUtils_h__
+
+
+#ifdef VBOX
+#include "nsIThread.h"
+
+inline already_AddRefed<nsIThread>
+do_GetMainThread() {
+ nsIThread *thread = nsnull;
+ nsIThread::GetMainThread(&thread);
+ return already_AddRefed<nsIThread>(thread);
+}
+
+#include "VBox/com/NativeEventQueue.h"
+
+inline already_AddRefed<nsIEventQueue> do_GetMainThreadQueue()
+{
+ com::NativeEventQueue* eq = com::NativeEventQueue::getMainEventQueue();
+ NS_ASSERTION(eq != nsnull, "Must be valid");
+ return eq->getIEventQueue();
+}
+
+#else
+#include "prthread.h"
+#include "prinrval.h"
+#include "nsIThreadManager.h"
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+#include "nsStringGlue.h"
+#include "nsCOMPtr.h"
+
+
+// This is needed on some systems to prevent collisions between the symbols
+// appearing in xpcom_core and xpcomglue. It may be unnecessary in the future
+// with better toolchain support.
+#ifdef MOZILLA_INTERNAL_API
+# define NS_NewThread NS_NewThread_P
+# define NS_GetCurrentThread NS_GetCurrentThread_P
+# define NS_GetMainThread NS_GetMainThread_P
+# define NS_IsMainThread NS_IsMainThread_P
+# define NS_DispatchToCurrentThread NS_DispatchToCurrentThread_P
+# define NS_DispatchToMainThread NS_DispatchToMainThread_P
+# define NS_ProcessPendingEvents NS_ProcessPendingEvents_P
+# define NS_HasPendingEvents NS_HasPendingEvents_P
+# define NS_ProcessNextEvent NS_ProcessNextEvent_P
+#endif
+
+//-----------------------------------------------------------------------------
+// These methods are alternatives to the methods on nsIThreadManager, provided
+// for convenience.
+
+/**
+ * Create a new thread, and optionally provide an initial event for the thread.
+ *
+ * @param result
+ * The resulting nsIThread object.
+ * @param initialEvent
+ * The initial event to run on this thread. This parameter may be null.
+ *
+ * @returns NS_ERROR_INVALID_ARG
+ * Indicates that the given name is not unique.
+ */
+extern NS_COM_GLUE NS_METHOD
+NS_NewThread(nsIThread **result, nsIRunnable *initialEvent = nsnull);
+
+/**
+ * Get a reference to the current thread.
+ *
+ * @param result
+ * The resulting nsIThread object.
+ */
+extern NS_COM_GLUE NS_METHOD
+NS_GetCurrentThread(nsIThread **result);
+
+/**
+ * Get a reference to the main thread.
+ *
+ * @param result
+ * The resulting nsIThread object.
+ */
+extern NS_COM_GLUE NS_METHOD
+NS_GetMainThread(nsIThread **result);
+
+/**
+ * Test to see if the current thread is the main thread.
+ *
+ * @returns PR_TRUE if the current thread is the main thread, and PR_FALSE
+ * otherwise.
+ */
+extern NS_COM_GLUE NS_METHOD_(PRBool)
+NS_IsMainThread();
+
+/**
+ * Dispatch the given event to the current thread.
+ *
+ * @param event
+ * The event to dispatch.
+ *
+ * @returns NS_ERROR_INVALID_ARG
+ * If event is null.
+ */
+extern NS_COM_GLUE NS_METHOD
+NS_DispatchToCurrentThread(nsIRunnable *event);
+
+/**
+ * Dispatch the given event to the main thread.
+ *
+ * @param event
+ * The event to dispatch.
+ * @param dispatchFlags
+ * The flags to pass to the main thread's dispatch method.
+ *
+ * @returns NS_ERROR_INVALID_ARG
+ * If event is null.
+ */
+extern NS_COM_GLUE NS_METHOD
+NS_DispatchToMainThread(nsIRunnable *event,
+ PRUint32 dispatchFlags = NS_DISPATCH_NORMAL);
+
+#ifndef XPCOM_GLUE_AVOID_NSPR
+/**
+ * Process all pending events for the given thread before returning. This
+ * method simply calls ProcessNextEvent on the thread while HasPendingEvents
+ * continues to return true and the time spent in NS_ProcessPendingEvents
+ * does not exceed the given timeout value.
+ *
+ * @param thread
+ * The thread object for which to process pending events. If null, then
+ * events will be processed for the current thread.
+ * @param timeout
+ * The maximum number of milliseconds to spend processing pending events.
+ * Events are not pre-empted to honor this timeout. Rather, the timeout
+ * value is simply used to determine whether or not to process another event.
+ * Pass PR_INTERVAL_NO_TIMEOUT to specify no timeout.
+ */
+extern NS_COM_GLUE NS_METHOD
+NS_ProcessPendingEvents(nsIThread *thread,
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT);
+#endif
+
+/**
+ * Shortcut for nsIThread::HasPendingEvents.
+ *
+ * It is an error to call this function when the given thread is not the
+ * current thread. This function will return PR_FALSE if called from some
+ * other thread.
+ *
+ * @param thread
+ * The current thread or null.
+ *
+ * @returns
+ * A boolean value that if "true" indicates that there are pending events
+ * in the current thread's event queue.
+ */
+extern NS_COM_GLUE PRBool
+NS_HasPendingEvents(nsIThread *thread = nsnull);
+
+/**
+ * Shortcut for nsIThread::ProcessNextEvent.
+ *
+ * It is an error to call this function when the given thread is not the
+ * current thread. This function will simply return PR_FALSE if called
+ * from some other thread.
+ *
+ * @param thread
+ * The current thread or null.
+ * @param mayWait
+ * A boolean parameter that if "true" indicates that the method may block
+ * the calling thread to wait for a pending event.
+ *
+ * @returns
+ * A boolean value that if "true" indicates that an event from the current
+ * thread's event queue was processed.
+ */
+extern NS_COM_GLUE PRBool
+NS_ProcessNextEvent(nsIThread *thread = nsnull, PRBool mayWait = PR_TRUE);
+
+//-----------------------------------------------------------------------------
+// Helpers that work with nsCOMPtr:
+
+inline already_AddRefed<nsIThread>
+do_GetCurrentThread() {
+ nsIThread *thread = nsnull;
+ NS_GetCurrentThread(&thread);
+ return already_AddRefed<nsIThread>(thread);
+}
+
+inline already_AddRefed<nsIThread>
+do_GetMainThread() {
+ nsIThread *thread = nsnull;
+ NS_GetMainThread(&thread);
+ return already_AddRefed<nsIThread>(thread);
+}
+
+//-----------------------------------------------------------------------------
+
+#ifdef MOZILLA_INTERNAL_API
+// Fast access to the current thread. Do not release the returned pointer! If
+// you want to use this pointer from some other thread, then you will need to
+// AddRef it. Otherwise, you should only consider this pointer valid from code
+// running on the current thread.
+extern NS_COM_GLUE nsIThread *NS_GetCurrentThread();
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifndef XPCOM_GLUE_AVOID_NSPR
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_COM_GLUE
+
+// This class is designed to be subclassed.
+class NS_COM_GLUE nsRunnable : public nsIRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRUNNABLE
+
+ nsRunnable() {
+ }
+
+protected:
+ virtual ~nsRunnable() {
+ }
+};
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+// An event that can be used to call a method on a class. The class type must
+// support reference counting.
+template <class T>
+class nsRunnableMethod : public nsRunnable
+{
+public:
+ typedef void (T::*Method)();
+
+ nsRunnableMethod(T *obj, Method method)
+ : mObj(obj), mMethod(method) {
+ NS_ADDREF(mObj);
+ }
+
+ NS_IMETHOD Run() {
+ (mObj->*mMethod)();
+ return NS_OK;
+ }
+
+private:
+ virtual ~nsRunnableMethod() {
+ NS_RELEASE(mObj);
+ }
+
+ T *mObj;
+ Method mMethod;
+};
+
+// Use this helper macro like so:
+//
+// nsCOMPtr<nsIRunnable> event =
+// NS_NEW_RUNNABLE_METHOD(MyClass, myObject, HandleEvent);
+// NS_DispatchToCurrentThread(event);
+//
+// Constraints:
+// - myObject must be of type MyClass
+// - MyClass must defined AddRef and Release methods
+//
+// NOTE: Attempts to make this a template function caused VC6 to barf :-(
+//
+#define NS_NEW_RUNNABLE_METHOD(class_, obj_, method_) \
+ new nsRunnableMethod<class_>(obj_, &class_::method_)
+
+#endif // XPCOM_GLUE_AVOID_NSPR
+
+// This class is designed to be used when you have an event class E that has a
+// pointer back to resource class R. If R goes away while E is still pending,
+// then it is important to "revoke" E so that it does not try use R after R has
+// been destroyed. nsRevocableEventPtr makes it easy for R to manage such
+// situations:
+//
+// class R;
+//
+// class E : public nsRunnable {
+// public:
+// void Revoke() {
+// mResource = nsnull;
+// }
+// private:
+// R *mResource;
+// };
+//
+// class R {
+// public:
+// void EventHandled() {
+// mEvent.Forget();
+// }
+// private:
+// nsRevocableEventPtr<E> mEvent;
+// };
+//
+// void R::PostEvent() {
+// // Make sure any pending event is revoked.
+// mEvent->Revoke();
+//
+// nsCOMPtr<nsIRunnable> event = new E();
+// if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) {
+// // Keep pointer to event so we can revoke it.
+// mEvent = event;
+// }
+// }
+//
+// NS_IMETHODIMP E::Run() {
+// if (!mResource)
+// return NS_OK;
+// ...
+// mResource->EventHandled();
+// return NS_OK;
+// }
+//
+template <class T>
+class nsRevocableEventPtr {
+public:
+ nsRevocableEventPtr()
+ : mEvent(nsnull) {
+ }
+
+ ~nsRevocableEventPtr() {
+ Revoke();
+ }
+
+ const nsRevocableEventPtr& operator=(T *event) {
+ Revoke();
+ mEvent = event;
+ return *this;
+ }
+
+ void Revoke() {
+ if (mEvent) {
+ mEvent->Revoke();
+ mEvent = nsnull;
+ }
+ }
+
+ void Forget() {
+ mEvent = nsnull;
+ }
+
+ PRBool IsPending() {
+ return mEvent != nsnull;
+ }
+
+private:
+ // Not implemented
+ nsRevocableEventPtr(const nsRevocableEventPtr&);
+ nsRevocableEventPtr& operator=(const nsRevocableEventPtr&);
+
+ T *mEvent;
+};
+#endif
+
+#endif // nsThreadUtils_h__
diff --git a/src/libs/xpcom18a4/java/src/nsXPTCUtils.h b/src/libs/xpcom18a4/java/src/nsXPTCUtils.h
new file mode 100644
index 00000000..9a1fe3cc
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/nsXPTCUtils.h
@@ -0,0 +1,128 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation <http://www.mozilla.org/>.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Benjamin Smedberg <benjamin@smedbergs.us> - New code
+ *
+ * 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 nsXPTCUtils_h__
+#define nsXPTCUtils_h__
+
+#include "xptcall.h"
+
+#ifdef VBOX
+
+#define NS_DECLARE_STATIC_IID_ACCESSOR(the_iid) \
+ template <class Dummy> \
+ struct COMTypeInfo \
+ { \
+ static const nsIID kIID NS_HIDDEN; \
+ }; \
+ static const nsIID& GetIID() {return COMTypeInfo<int>::kIID;}
+
+
+#define NS_DEFINE_STATIC_IID_ACCESSOR2(the_interface, the_iid) \
+ template <class Dummy> \
+ const nsIID the_interface::COMTypeInfo<Dummy>::kIID NS_HIDDEN = the_iid;
+
+
+class nsIXPTCProxy : public nsISupports
+{
+public:
+ NS_IMETHOD CallMethod(PRUint16 aMethodIndex,
+ const XPTMethodDescriptor *aInfo,
+ nsXPTCMiniVariant *aParams) = 0;
+};
+
+/**
+ * This is a typedef to avoid confusion between the canonical
+ * nsISupports* that provides object identity and an interface pointer
+ * for inheriting interfaces that aren't known at compile-time.
+ */
+typedef nsISupports nsISomeInterface;
+
+/**
+ * Get a proxy object to implement the specified interface.
+ *
+ * @param aIID The IID of the interface to implement.
+ * @param aOuter An object to receive method calls from the proxy object.
+ * The stub forwards QueryInterface/AddRef/Release to the
+ * outer object. The proxy object does not hold a reference to
+ * the outer object; it is the caller's responsibility to
+ * ensure that this pointer remains valid until the stub has
+ * been destroyed.
+ * @param aStub Out parameter for the new proxy object. The object is
+ * not addrefed. The object never destroys itself. It must be
+ * explicitly destroyed by calling
+ * NS_DestroyXPTCallStub when it is no longer needed.
+ */
+XPTC_PUBLIC_API(nsresult)
+NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
+ nsISomeInterface* *aStub);
+
+/**
+ * Destroys an XPTCall stub previously created with NS_GetXPTCallStub.
+ */
+XPTC_PUBLIC_API(void)
+NS_DestroyXPTCallStub(nsISomeInterface* aStub);
+
+
+#endif
+
+
+/**
+ * A helper class that initializes an xptcall helper at construction
+ * and releases it at destruction.
+ */
+class nsAutoXPTCStub : protected nsIXPTCProxy
+{
+public:
+ nsISomeInterface* mXPTCStub;
+
+protected:
+ nsAutoXPTCStub() : mXPTCStub(nsnull) { }
+
+ nsresult
+ InitStub(const nsIID& aIID)
+ {
+ return NS_GetXPTCallStub(aIID, this, &mXPTCStub);
+ }
+
+ ~nsAutoXPTCStub()
+ {
+ if (mXPTCStub)
+ NS_DestroyXPTCallStub(mXPTCStub);
+ }
+};
+
+#endif // nsXPTCUtils_h__
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/GREVersionRange.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/GREVersionRange.java
new file mode 100644
index 00000000..ede1a523
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/GREVersionRange.java
@@ -0,0 +1,80 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+
+public class GREVersionRange {
+
+ private String lower;
+ private boolean lowerInclusive;
+ private String upper;
+ private boolean upperInclusive;
+
+ public GREVersionRange(String aLower, boolean aLowerInclusive,
+ String aUpper, boolean aUpperInclusive) {
+ lower = aLower;
+ lowerInclusive = aLowerInclusive;
+ upper = aUpper;
+ upperInclusive = aUpperInclusive;
+ }
+
+ public boolean check(String aVersion) {
+ VersionComparator comparator = new VersionComparator();
+ int c = comparator.compare(aVersion, lower);
+ if (c < 0) {
+ return false;
+ }
+
+ if (c == 0 && !lowerInclusive) {
+ return false;
+ }
+
+ c = comparator.compare(aVersion, upper);
+ if (c > 0) {
+ return false;
+ }
+
+ if (c == 0 && !upperInclusive) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IAppFileLocProvider.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IAppFileLocProvider.java
new file mode 100644
index 00000000..633d8bbc
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IAppFileLocProvider.java
@@ -0,0 +1,92 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.io.File;
+
+
+/**
+ * Used by XPCOM's Directory Service to get file locations.
+ * <p>
+ * This interface is similar to <code>nsIDirectoryServiceProvider</code> and
+ * <code>nsIDirectoryServiceProvider2</code>, except that its methods use
+ * <code>java.io.File</code> instead of <code>nsIFile</code>.
+ * </p>
+ *
+ * @see Mozilla#initEmbedding
+ * @see Mozilla#initXPCOM
+ * @see <a href=
+ * "http://lxr.mozilla.org/mozilla/source/xpcom/io/nsIDirectoryService.idl">
+ * nsIDirectoryServiceProvider </a>
+ * @see <a href=
+ * "http://lxr.mozilla.org/mozilla/source/xpcom/io/nsDirectoryServiceDefs.h">
+ * Directory Service property names </a>
+ */
+public interface IAppFileLocProvider {
+
+ /**
+ * Directory Service calls this when it gets the first request for
+ * a property or on every request if the property is not persistent.
+ *
+ * @param prop the symbolic name of the file
+ * @param persistent an array of length one used to supply the output value:
+ * <ul>
+ * <li><code>true</code> - The returned file will be
+ * cached by Directory Service. Subsequent requests for
+ * this prop will bypass the provider and use the cache.
+ * </li>
+ * <li><code>false</code> - The provider will be asked
+ * for this prop each time it is requested. </li>
+ * </ul>
+ *
+ * @return the file represented by the property
+ */
+ File getFile(String prop, boolean[] persistent);
+
+ /**
+ * Directory Service calls this when it gets a request for
+ * a property and the requested type is nsISimpleEnumerator.
+ *
+ * @param prop the symbolic name of the file list
+ *
+ * @return an array of file locations
+ */
+ File[] getFiles(String prop);
+
+}
+
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IGRE.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IGRE.java
new file mode 100644
index 00000000..ecf000fe
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IGRE.java
@@ -0,0 +1,127 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.io.File;
+
+
+public interface IGRE {
+
+ /**
+ * Initializes libXUL for embedding purposes.
+ * <p>
+ * NOTE: This function must be called from the "main" thread.
+ * <p>
+ * NOTE: At the present time, this function may only be called once in
+ * a given process. Use <code>termEmbedding</code> to clean up and free
+ * resources allocated by <code>initEmbedding</code>.
+ *
+ * @param aLibXULDirectory The directory in which the libXUL shared library
+ * was found.
+ * @param aAppDirectory The directory in which the application components
+ * and resources can be found. This will map to
+ * the "resource:app" directory service key.
+ * @param aAppDirProvider A directory provider for the application. This
+ * provider will be aggregated by a libXUL provider
+ * which will provide the base required GRE keys.
+ *
+ * @throws XPCOMException if a failure occurred during initialization
+ */
+ void initEmbedding(File aLibXULDirectory, File aAppDirectory,
+ IAppFileLocProvider aAppDirProvider) throws XPCOMException;
+
+ /**
+ * Terminates libXUL embedding.
+ * <p>
+ * NOTE: Release any references to XPCOM objects that you may be holding
+ * before calling this function.
+ */
+ void termEmbedding();
+
+ /**
+ * Lock a profile directory using platform-specific semantics.
+ *
+ * @param aDirectory The profile directory to lock.
+ *
+ * @return A lock object. The directory will remain locked until the lock is
+ * released by invoking the <code>release</code> method, or by the
+ * termination of the JVM, whichever comes first.
+ *
+ * @throws XPCOMException if a failure occurred
+ */
+ ProfileLock lockProfileDirectory(File aDirectory) throws XPCOMException;
+
+ /**
+ * Fire notifications to inform the toolkit about a new profile. This
+ * method should be called after <code>initEmbedding</code> if the
+ * embedder wishes to run with a profile.
+ * <p>
+ * Normally the embedder should call <code>lockProfileDirectory</code>
+ * to lock the directory before calling this method.
+ * <p>
+ * NOTE: There are two possibilities for selecting a profile:
+ * <ul>
+ * <li>
+ * Select the profile before calling <code>initEmbedding</code>.
+ * The aAppDirProvider object passed to <code>initEmbedding</code>
+ * should provide the NS_APP_USER_PROFILE_50_DIR key, and
+ * may also provide the following keys:
+ * <ul>
+ * <li>NS_APP_USER_PROFILE_LOCAL_50_DIR
+ * <li>NS_APP_PROFILE_DIR_STARTUP
+ * <li>NS_APP_PROFILE_LOCAL_DIR_STARTUP
+ * </ul>
+ * In this scenario <code>notifyProfile</code> should be called
+ * immediately after <code>initEmbedding</code>. Component
+ * registration information will be stored in the profile and
+ * JS components may be stored in the fastload cache.
+ * </li>
+ * <li>
+ * Select a profile some time after calling <code>initEmbedding</code>.
+ * In this case the embedder must install a directory service
+ * provider which provides NS_APP_USER_PROFILE_50_DIR and optionally
+ * NS_APP_USER_PROFILE_LOCAL_50_DIR. Component registration information
+ * will be stored in the application directory and JS components will not
+ * fastload.
+ * </li>
+ * </ul>
+ */
+ void notifyProfile();
+
+}
+
+
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IJavaXPCOMUtils.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IJavaXPCOMUtils.java
new file mode 100644
index 00000000..7b70caf9
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IJavaXPCOMUtils.java
@@ -0,0 +1,59 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+public interface IJavaXPCOMUtils {
+
+ /**
+ * Returns a pointer to a C++ proxy object for the given Java object.
+ *
+ * @param aJavaObject Java object to encapsulate in C++ proxy
+ * @param aIID interface ID for requested proxy
+ * @return C pointer (as long) of new proxy
+ */
+ long wrapJavaObject(Object aJavaObject, String aIID);
+
+ /**
+ * Returns a Java proxy for the given C++ XPCOM object
+ *
+ * @param aXPCOMObject C++ XPCOM object to encapsulate in Java proxy
+ * @param aIID interface ID for requested proxy
+ * @return new Proxy
+ */
+ Object wrapXPCOMObject(long aXPCOMObject, String aIID);
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IMozilla.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IMozilla.java
new file mode 100644
index 00000000..b148e9a2
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IMozilla.java
@@ -0,0 +1,63 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.io.File;
+
+public interface IMozilla {
+
+ /**
+ * Initialize the Mozilla object with the given XULRunner path. All
+ * subsequent Mozilla method invocations be done against the given XULRunner
+ * version.
+ *
+ * @param aLibXULDirectory path of XULRunner build to use
+ *
+ * @throws XPCOMInitializationException if failure occurred during
+ * initialization
+ */
+ void initialize(File aLibXULDirectory) throws XPCOMInitializationException;
+
+ /**
+ * Return the native window handle for an AWT component.
+ *
+ * @param widget An AWT component (such as Canvas, Frame) that is backed by
+ * a real native window.
+ * @return the pointer to the native window (platform specific)
+ */
+ long getNativeHandleFromAWT(Object widget);
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/INIParser.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/INIParser.java
new file mode 100644
index 00000000..ba2f11c7
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/INIParser.java
@@ -0,0 +1,243 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+
+/**
+ * A simple parser for INI files.
+ */
+public class INIParser {
+
+ private HashMap<String, Properties> mSections;
+
+ /**
+ * Creates a new <code>INIParser</code> instance from the INI file at the
+ * given path. <code>aCharset</code> specifies the character encoding of
+ * the file.
+ *
+ * @param aFilename path of INI file to parse
+ * @param aCharset character encoding of file
+ * @throws FileNotFoundException if <code>aFilename</code> does not exist.
+ * @throws IOException if there is a problem reading the given file.
+ */
+ public INIParser(String aFilename, Charset aCharset)
+ throws FileNotFoundException, IOException {
+ initFromFile(new File(aFilename), aCharset);
+ }
+
+ /**
+ * Creates a new <code>INIParser</code> instance from the INI file at the
+ * given path, which is assumed to be in the <code>UTF-8</code> charset.
+ *
+ * @param aFilename path of INI file to parse
+ * @throws FileNotFoundException if <code>aFilename</code> does not exist.
+ * @throws IOException if there is a problem reading the given file.
+ */
+ public INIParser(String aFilename) throws FileNotFoundException, IOException {
+ initFromFile(new File(aFilename), Charset.forName("UTF-8"));
+ }
+
+ /**
+ * Creates a new <code>INIParser</code> instance from the given file.
+ * <code>aCharset</code> specifies the character encoding of the file.
+ *
+ * @param aFile INI file to parse
+ * @param aCharset character encoding of file
+ * @throws FileNotFoundException if <code>aFile</code> does not exist.
+ * @throws IOException if there is a problem reading the given file.
+ */
+ public INIParser(File aFile, Charset aCharset)
+ throws FileNotFoundException, IOException {
+ initFromFile(aFile, aCharset);
+ }
+
+ /**
+ * Creates a new <code>INIParser</code> instance from the given file,
+ * which is assumed to be in the <code>UTF-8</code> charset.
+ *
+ * @param aFile INI file to parse
+ * @throws FileNotFoundException if <code>aFile</code> does not exist.
+ * @throws IOException if there is a problem reading the given file.
+ */
+ public INIParser(File aFile) throws FileNotFoundException, IOException {
+ initFromFile(aFile, Charset.forName("UTF-8"));
+ }
+
+ /**
+ * Parses given INI file.
+ *
+ * @param aFile INI file to parse
+ * @param aCharset character encoding of file
+ * @throws FileNotFoundException if <code>aFile</code> does not exist.
+ * @throws IOException if there is a problem reading the given file.
+ */
+ private void initFromFile(File aFile, Charset aCharset)
+ throws FileNotFoundException, IOException {
+ FileInputStream fileStream = new FileInputStream(aFile);
+ InputStreamReader inStream = new InputStreamReader(fileStream, aCharset);
+ BufferedReader reader = new BufferedReader(inStream);
+
+ mSections = new HashMap<String, Properties>();
+ String currSection = null;
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ // skip empty lines and comment lines
+ String trimmedLine = line.trim();
+ if (trimmedLine.length() == 0 || trimmedLine.startsWith("#")
+ || trimmedLine.startsWith(";")) {
+ continue;
+ }
+
+ // Look for section headers (i.e. "[Section]").
+ if (line.startsWith("[")) {
+ /*
+ * We are looking for a well-formed "[Section]". If this header is
+ * malformed (i.e. "[Section" or "[Section]Moretext"), just skip it
+ * and go on to next well-formed section header.
+ */
+ if (!trimmedLine.endsWith("]") ||
+ trimmedLine.indexOf("]") != (trimmedLine.length() - 1)) {
+ currSection = null;
+ continue;
+ }
+
+ // remove enclosing brackets
+ currSection = trimmedLine.substring(1, trimmedLine.length() - 1);
+ continue;
+ }
+
+ // If we haven't found a valid section header, continue to next line
+ if (currSection == null) {
+ continue;
+ }
+
+ StringTokenizer tok = new StringTokenizer(line, "=");
+ if (tok.countTokens() != 2) { // looking for value pairs
+ continue;
+ }
+
+ Properties props = mSections.get(currSection);
+ if (props == null) {
+ props = new Properties();
+ mSections.put(currSection, props);
+ }
+ props.setProperty(tok.nextToken(), tok.nextToken());
+ }
+
+ reader.close();
+ }
+
+ /**
+ * Returns an iterator over the section names available in the INI file.
+ *
+ * @return an iterator over the section names
+ */
+ public Iterator getSections() {
+ return mSections.keySet().iterator();
+ }
+
+ /**
+ * Returns an iterator over the keys available within a section.
+ *
+ * @param aSection section name whose keys are to be returned
+ * @return an iterator over section keys, or <code>null</code> if no
+ * such section exists
+ */
+ public Iterator getKeys(String aSection) {
+ /*
+ * Simple wrapper class to convert Enumeration to Iterator
+ */
+ class PropertiesIterator implements Iterator {
+ private Enumeration e;
+
+ public PropertiesIterator(Enumeration aEnum) {
+ e = aEnum;
+ }
+
+ public boolean hasNext() {
+ return e.hasMoreElements();
+ }
+
+ public Object next() {
+ return e.nextElement();
+ }
+
+ public void remove() {
+ return;
+ }
+ }
+
+ Properties props = mSections.get(aSection);
+ if (props == null) {
+ return null;
+ }
+
+ return new PropertiesIterator(props.propertyNames());
+ }
+
+ /**
+ * Gets the string value for a particular section and key.
+ *
+ * @param aSection a section name
+ * @param aKey the key whose value is to be returned.
+ * @return string value of particular section and key
+ */
+ public String getString(String aSection, String aKey) {
+ Properties props = mSections.get(aSection);
+ if (props == null) {
+ return null;
+ }
+
+ return props.getProperty(aKey);
+ }
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IXPCOM.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IXPCOM.java
new file mode 100644
index 00000000..8cfbfb30
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/IXPCOM.java
@@ -0,0 +1,137 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.io.File;
+
+import org.mozilla.interfaces.nsIComponentManager;
+import org.mozilla.interfaces.nsIComponentRegistrar;
+import org.mozilla.interfaces.nsILocalFile;
+import org.mozilla.interfaces.nsIServiceManager;
+
+
+public interface IXPCOM {
+
+ /**
+ * Initializes XPCOM. You must call this method before proceeding
+ * to use XPCOM.
+ *
+ * @param aMozBinDirectory The directory containing the component
+ * registry and runtime libraries;
+ * or use <code>null</code> to use the working
+ * directory.
+ *
+ * @param aAppFileLocProvider The object to be used by Gecko that specifies
+ * to Gecko where to find profiles, the component
+ * registry preferences and so on; or use
+ * <code>null</code> for the default behaviour.
+ *
+ * @return the service manager
+ *
+ * @throws XPCOMException <ul>
+ * <li> NS_ERROR_NOT_INITIALIZED - if static globals were not initialied,
+ * which can happen if XPCOM is reloaded, but did not completly
+ * shutdown. </li>
+ * <li> Other error codes indicate a failure during initialisation. </li>
+ * </ul>
+ */
+ nsIServiceManager initXPCOM(File aMozBinDirectory,
+ IAppFileLocProvider aAppFileLocProvider) throws XPCOMException;
+
+ /**
+ * Shutdown XPCOM. You must call this method after you are finished
+ * using xpcom.
+ *
+ * @param aServMgr The service manager which was returned by initXPCOM.
+ * This will release servMgr.
+ *
+ * @throws XPCOMException if a failure occurred during termination
+ */
+ void shutdownXPCOM(nsIServiceManager aServMgr) throws XPCOMException;
+
+ /**
+ * Public Method to access to the service manager.
+ *
+ * @return the service manager
+ *
+ * @throws XPCOMException
+ */
+ nsIServiceManager getServiceManager() throws XPCOMException;
+
+ /**
+ * Public Method to access to the component manager.
+ *
+ * @return the component manager
+ *
+ * @throws XPCOMException
+ */
+ nsIComponentManager getComponentManager() throws XPCOMException;
+
+ /**
+ * Public Method to access to the component registration manager.
+ *
+ * @return the component registration manager
+ *
+ * @throws XPCOMException
+ */
+ nsIComponentRegistrar getComponentRegistrar() throws XPCOMException;
+
+ /**
+ * Public Method to create an instance of a nsILocalFile.
+ *
+ * @param aPath A string which specifies a full file path to a
+ * location. Relative paths will be treated as an
+ * error (NS_ERROR_FILE_UNRECOGNIZED_PATH).
+ * @param aFollowLinks This attribute will determine if the nsLocalFile will
+ * auto resolve symbolic links. By default, this value
+ * will be false on all non unix systems. On unix, this
+ * attribute is effectively a noop.
+ *
+ * @return an instance of an nsILocalFile that points to given path
+ *
+ * @throws XPCOMException <ul>
+ * <li> NS_ERROR_FILE_UNRECOGNIZED_PATH - raised for unrecognized paths
+ * or relative paths (must supply full file path) </li>
+ * </ul>
+ */
+ nsILocalFile newLocalFile(String aPath, boolean aFollowLinks)
+ throws XPCOMException;
+
+ // #ifdef VBOX
+ int waitForEvents(long timeout);
+ // #endif VBOX
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java
new file mode 100644
index 00000000..05314c90
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java
@@ -0,0 +1,1079 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.mozilla.interfaces.nsIComponentManager;
+import org.mozilla.interfaces.nsIComponentRegistrar;
+import org.mozilla.interfaces.nsILocalFile;
+import org.mozilla.interfaces.nsIServiceManager;
+import org.mozilla.interfaces.nsISupports;
+
+
+/**
+ * A singleton class which provides access to the Mozilla browser. Requires
+ * that XULRunner be installed on the user's system.
+ * <p>
+ * You would use to class to find a XULRunner installation, setup a profile (if
+ * necessary), and initialize embedding. A typical scenario would look like
+ * this:
+ * </p><pre>
+ * Mozilla mozilla = Mozilla.getInstance();
+ * GREVersionRange[] range = new GREVersionRange[1];
+ * range[0] = new GREVersionRange("1.8.0.*", false, "1.8.1.*", true);
+ * try {
+ * File grePath = Mozilla.getGREPathWithProperties(range, null);
+ * mozilla.initialize(grePath);
+ * profLock = mozilla.lockProfileDirectory(profileDir);
+ * // LocationProvider is a user class that implements IAppFileLocProvider
+ * LocationProvider locProvider = new LocationProvider(grePath, profileDir);
+ * mozilla.initEmbedding(grePath, grePath, locProvider);
+ * mozilla.notifyProfile();
+ * } catch (XPCOMInitializationException xie) {
+ * // handle exception
+ * } catch (XPCOMException xe) {
+ * // handle exception
+ * }
+ * </pre>
+ *
+ * @see http://www.mozilla.org/projects/embedding/GRE.html
+ */
+public class Mozilla implements IMozilla, IGRE, IXPCOM, IJavaXPCOMUtils,XPCOMError {
+
+ private static Mozilla mozillaInstance = new Mozilla();
+
+ private static final String JAVAXPCOM_JAR = "vboxjxpcom.jar";
+
+ private IMozilla mozilla = null;
+ private IGRE gre = null;
+ private IXPCOM xpcom = null;
+ private IJavaXPCOMUtils jxutils = null;
+
+ /**
+ * @return
+ */
+ public static Mozilla getInstance() {
+ return mozillaInstance;
+ }
+
+ /**
+ *
+ */
+ private Mozilla() {
+ }
+
+ /**
+ * Locates the path of a GRE with the specified properties. This method
+ * will only return GREs that support Java embedding (looks for the
+ * presence of "javaxpcom.jar").
+ * <p>
+ * Currently this uses a "first-fit" algorithm, it does not select
+ * the newest available GRE.
+ *
+ * @param aVersions An array of version ranges: if any version range
+ * matches, the GRE is considered acceptable.
+ * @param aProperties A list of GRE property/value pairs which must
+ * all be satisfied. This parameter is ignored on
+ * Macintosh, because of the manner in which the
+ * XUL frameworks are installed.
+ *
+ * @return A file object of the appropriate path. If
+ * the "local" GRE is specified (via the USE_LOCAL_GRE
+ * environment variable, for example), returns
+ * <code>null</code>.
+ *
+ * @throws FileNotFoundException if an appropriate GRE could not be found
+ */
+ public static File getGREPathWithProperties(GREVersionRange[] aVersions,
+ Properties aProperties) throws FileNotFoundException {
+ File grePath = null;
+
+ // if GRE_HOME is in the environment, use that GRE
+ String env = System.getProperty("GRE_HOME");
+ if (env != null) {
+ try {
+ grePath = new File(env).getCanonicalFile();
+ } catch (IOException e) {
+ throw new FileNotFoundException("cannot access GRE_HOME");
+ }
+ if (!grePath.exists()) {
+ throw new FileNotFoundException("GRE_HOME doesn't exist");
+ }
+ return grePath;
+ }
+
+ // the Gecko bits that sit next to the application or in the PATH
+ env = System.getProperty("USE_LOCAL_GRE");
+ if (env != null) {
+ return null;
+ }
+
+ // Search for GRE in platform specific locations. We want a GRE that
+ // supports Java, so we look for the "javaxpcom" property by default.
+ if (aProperties == null) {
+ aProperties = new Properties();
+ }
+ aProperties.setProperty("javaxpcom", "1");
+
+ String osName = System.getProperty("os.name").toLowerCase();
+ if (osName.startsWith("mac os x")) {
+ grePath = getGREPathMacOSX(aVersions);
+ } else if (osName.startsWith("windows")) {
+ grePath = getGREPathWindows(aVersions, aProperties);
+ } else {
+ // assume everything else is Unix/Linux
+ grePath = getGREPathUnix(aVersions, aProperties);
+ }
+
+ if (grePath == null) {
+ throw new FileNotFoundException("GRE not found");
+ }
+
+ return grePath;
+ }
+
+ /**
+ * @param aVersions
+ * @return
+ */
+ private static File getGREPathMacOSX(GREVersionRange[] aVersions) {
+ /*
+ * Check the application bundle first, for
+ * <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib.
+ */
+ File grePath = findGREBundleFramework();
+ if (grePath != null) {
+ return grePath;
+ }
+
+ // Check ~/Library/Frameworks/XUL.framework/Versions/<version>/libxpcom.dylib
+ String home = System.getProperty("user.home");
+ if (home != null) {
+ grePath = findGREFramework(home, aVersions);
+ if (grePath != null) {
+ return grePath;
+ }
+ }
+
+ // Check /Library/Frameworks/XUL.framework/Versions/<version>/libxpcom.dylib
+ return findGREFramework("", aVersions);
+ }
+
+ /**
+ * @return
+ */
+ private static File findGREBundleFramework() {
+ /*
+ * Use reflection to get Apple's NSBundle class, which can be used
+ * to get the bundle's "Frameworks" directory.
+ */
+ try {
+ URL[] urls = new URL[1];
+ urls[0] = new File("/System/Library/Java/").toURI().toURL();
+ ClassLoader loader = new URLClassLoader(urls);
+ Class<?> bundleClass = Class.forName("com.apple.cocoa.foundation.NSBundle",
+ true, loader);
+
+ // Get the bundle for this app. If this is not executing from
+ // a bundle, this will return null.
+ Method mainBundleMethod = bundleClass.getMethod("mainBundle", (java.lang.Class[])null);
+ Object bundle = mainBundleMethod.invoke(null, (java.lang.Object[])null);
+
+ if (bundle != null) {
+ // Get the path to the bundle's "Frameworks" directory
+ Method fwPathMethod = bundleClass.getMethod("privateFrameworksPath",
+ (java.lang.Class[])null);
+ String path = (String) fwPathMethod.invoke(bundle, (java.lang.Object[])null);
+
+ // look for libxpcom.dylib
+ if (path.length() != 0) {
+ File xulDir = new File(path, "XUL.framework");
+ if (xulDir.isDirectory()) {
+ File xpcomLib = new File(xulDir, "libxpcom.dylib");
+ if (xpcomLib.canRead()) {
+ File grePath = xpcomLib.getCanonicalFile().getParentFile();
+
+ // Since GRE Properties aren't supported on Mac OS X, we check
+ // for the existence of the "javaxpcom.jar" file in the GRE.
+ File jar = new File(grePath, JAVAXPCOM_JAR);
+ if (jar.canRead()) {
+ // found GRE
+ return grePath;
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) { }
+
+ return null;
+ }
+
+ /**
+ * @param aRootPath
+ * @param aVersions
+ * @return
+ */
+ private static File findGREFramework(String aRootPath,
+ GREVersionRange[] aVersions) {
+ File frameworkDir = new File(aRootPath +
+ "/Library/Frameworks/XUL.framework/Versions");
+ if (!frameworkDir.exists())
+ return null;
+
+ File[] files = frameworkDir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (checkVersion(files[i].getName(), aVersions)) {
+ File xpcomLib = new File(files[i], "libxpcom.dylib");
+
+ // Since GRE Properties aren't supported on Mac OS X, we check
+ // for the existence of the "javaxpcom.jar" file in the GRE.
+ File jar = new File(files[i], JAVAXPCOM_JAR);
+ if (xpcomLib.canRead() && jar.canRead()) {
+ return files[i];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param aVersions
+ * @param aProperties
+ * @return
+ */
+ private static File getGREPathWindows(GREVersionRange[] aVersions,
+ Properties aProperties) {
+ /*
+ * Note the usage of the "Software\\mozilla.org\\GRE" subkey - this allows
+ * us to have multiple versions of GREs on the same machine by having
+ * subkeys such as 1.0, 1.1, 2.0 etc. under it.
+ *
+ * Please see http://www.mozilla.org/projects/embedding/GRE.html for
+ * more info.
+ */
+
+ final String greKey = "Software\\mozilla.org\\GRE";
+
+ // See if there is a GRE registered for the current user.
+ // If not, look for one on the system.
+ String key = "HKEY_CURRENT_USER" + "\\" + greKey;
+ File grePath = getGREPathFromRegKey(key, aVersions, aProperties);
+ if (grePath == null) {
+ key = "HKEY_LOCAL_MACHINE" + "\\" + greKey;
+ grePath = getGREPathFromRegKey(key, aVersions, aProperties);
+ }
+
+ return grePath;
+ }
+
+ /**
+ * @param aRegKey
+ * @param aVersions
+ * @param aProperties
+ * @return
+ */
+ private static File getGREPathFromRegKey(String aRegKey,
+ GREVersionRange[] aVersions, Properties aProperties) {
+ // create a temp file for the registry export
+ File tempFile;
+ try {
+ tempFile = File.createTempFile("jx_registry", null);
+ } catch (IOException e) {
+ // failed to create temp file. ABORT
+ return null;
+ }
+
+ Process proc;
+ try {
+ proc = Runtime.getRuntime().exec("regedit /e " + "\"" + tempFile.getPath()
+ + "\" \"" + aRegKey + "\"");
+ proc.waitFor();
+ } catch (Exception e) {
+ // Failed to run regedit.exe. Length of temp file is zero, and that's
+ // handled next.
+ }
+
+ // If there is a key by that name in the registry, then the file length
+ // will not be zero.
+ File grePath = null;
+ if (tempFile.length() != 0) {
+ grePath = getGREPathFromRegistryFile(tempFile.getPath(),
+ aRegKey, aVersions, aProperties);
+ }
+
+ tempFile.delete();
+ return grePath;
+ }
+
+ /**
+ * @param aFileName
+ * @param aCharset
+ * @param aKeyName
+ * @param aVersions
+ * @param aProperties
+ * @return
+ */
+ private static File getGREPathFromRegistryFile(String aFileName,
+ String aKeyName, GREVersionRange[] aVersions,
+ Properties aProperties) {
+ INIParser parser;
+ try {
+ parser = new INIParser(aFileName, Charset.forName("UTF-16"));
+ } catch (Exception e) {
+ // Problem reading from file. Bail out.
+ return null;
+ }
+
+ Iterator sectionsIter = parser.getSections();
+ while (sectionsIter.hasNext()) {
+ // get 'section' name, which will be a registry key name
+ String section = (String) sectionsIter.next();
+
+ // Skip over GRE key ("<root>\Software\mozilla.org\GRE")
+ int gre_len = aKeyName.length();
+ if (section.length() <= gre_len) {
+ continue;
+ }
+
+ // Get the GRE subkey; that is, everything after
+ // "<root>\Software\mozilla.org\GRE\"
+ String subkeyName = section.substring(gre_len + 1);
+
+ // We are only interested in _immediate_ subkeys. We want
+ // "<root>\Software\mozilla.org\GRE\<version>" but not
+ // "<root>\Software\mozilla.org\GRE\<version>\<moretext>".
+ if (subkeyName.indexOf('\\') != -1) {
+ continue;
+ }
+
+ // See if this registry key has a "Version" value, and if so, compare
+ // it to our desired versions.
+ String version = parser.getString(section, "\"Version\"");
+ if (version == null) {
+ continue;
+ }
+ // remove quotes around string
+ version = version.substring(1, version.length() - 1);
+ if (!checkVersion(version, aVersions)) {
+ continue;
+ }
+
+ // All properties must match, keeping in mind that the propery/value
+ // pairs returned by regedit.exe have quotes around them.
+ if (aProperties != null) {
+ boolean ok = true;
+ Enumeration e = aProperties.propertyNames();
+ while (ok && e.hasMoreElements()) {
+ String prop = (String) e.nextElement();
+ String greValue = parser.getString(section, "\"" + prop + "\"");
+ if (greValue == null) {
+ // No such property is set for this GRE. Go on to next GRE.
+ ok = false;
+ } else {
+ // See if the value of the property for the GRE matches
+ // the given value.
+ String value = aProperties.getProperty(prop);
+ if (!greValue.equals("\"" + value + "\"")) {
+ ok = false;
+ }
+ }
+ }
+ if (!ok) {
+ continue;
+ }
+ }
+
+ String pathStr = parser.getString(section, "\"GreHome\"");
+ if (pathStr != null) {
+ // remove quotes around string
+ pathStr = pathStr.substring(1, pathStr.length() - 1);
+ File grePath = new File(pathStr);
+ if (grePath.exists()) {
+ File xpcomLib = new File(grePath, "xpcom.dll");
+ if (xpcomLib.canRead()) {
+ // found a good GRE
+ return grePath;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param aVersions
+ * @param aProperties
+ * @return
+ */
+ private static File getGREPathUnix(GREVersionRange[] aVersions,
+ Properties aProperties) {
+ File grePath = null;
+
+ String env = System.getProperty("MOZ_GRE_CONF");
+ if (env != null) {
+ grePath = getPathFromConfigFile(env, aVersions, aProperties);
+ if (grePath != null) {
+ return grePath;
+ }
+ }
+
+ final String greUserConfFile = ".gre.config";
+ final String greUserConfDir = ".gre.d";
+ final String greConfPath = "/etc/gre.conf";
+ final String greConfDir = "/etc/gre.d";
+
+ env = System.getProperty("user.home");
+ if (env != null) {
+ // Look in ~/.gre.config
+ grePath = getPathFromConfigFile(env + File.separator + greUserConfFile,
+ aVersions, aProperties);
+ if (grePath != null) {
+ return grePath;
+ }
+
+ // Look in ~/.gre.d/*.conf
+ grePath = getPathFromConfigDir(env + File.separator + greUserConfDir,
+ aVersions, aProperties);
+ if (grePath != null) {
+ return grePath;
+ }
+ }
+
+ // Look for a global /etc/gre.conf file
+ grePath = getPathFromConfigFile(greConfPath, aVersions, aProperties);
+ if (grePath != null) {
+ return grePath;
+ }
+
+ // Look for a group of config files in /etc/gre.d/
+ grePath = getPathFromConfigDir(greConfDir, aVersions, aProperties);
+ return grePath;
+ }
+
+ /**
+ * @param aFileName
+ * @param aVersions
+ * @param aProperties
+ * @return
+ */
+ private static File getPathFromConfigFile(String aFileName,
+ GREVersionRange[] aVersions, Properties aProperties) {
+ INIParser parser;
+ try {
+ parser = new INIParser(aFileName);
+ } catch (Exception e) {
+ // Problem reading from file. Bail out.
+ return null;
+ }
+
+ Iterator sectionsIter = parser.getSections();
+ while (sectionsIter.hasNext()) {
+ // get 'section' name, which will be a version string
+ String section = (String) sectionsIter.next();
+
+ // if this isn't one of the versions we are looking for, move
+ // on to next section
+ if (!checkVersion(section, aVersions)) {
+ continue;
+ }
+
+ // all properties must match
+ if (aProperties != null) {
+ boolean ok = true;
+ Enumeration e = aProperties.propertyNames();
+ while (ok && e.hasMoreElements()) {
+ String prop = (String) e.nextElement();
+ String greValue = parser.getString(section, prop);
+ if (greValue == null) {
+ // No such property is set for this GRE. Go on to next GRE.
+ ok = false;
+ } else {
+ // See if the value of the property for the GRE matches
+ // the given value.
+ if (!greValue.equals(aProperties.getProperty(prop))) {
+ ok = false;
+ }
+ }
+ }
+ if (!ok) {
+ continue;
+ }
+ }
+
+ String pathStr = parser.getString(section, "GRE_PATH");
+ if (pathStr != null) {
+ File grePath = new File(pathStr);
+ if (grePath.exists()) {
+ File xpcomLib = new File(grePath, "libxpcom.so");
+ if (xpcomLib.canRead()) {
+ // found a good GRE
+ return grePath;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param aDirName
+ * @param aVersions
+ * @param aProperties
+ * @return
+ */
+ private static File getPathFromConfigDir(String aDirName,
+ GREVersionRange[] aVersions, Properties aProperties) {
+ /*
+ * Open the directory provided and try to read any files in that
+ * directory that end with .conf. We look for an entry that might
+ * point to the GRE that we're interested in.
+ */
+
+ File dir = new File(aDirName);
+ if (!dir.isDirectory()) {
+ return null;
+ }
+
+ File grePath = null;
+ File[] files = dir.listFiles();
+ for (int i = 0; i < files.length && grePath == null; i++) {
+ // only look for files that end in '.conf'
+ if (!files[i].getName().endsWith(".conf")) {
+ continue;
+ }
+
+ grePath = getPathFromConfigFile(files[i].getPath(), aVersions,
+ aProperties);
+ }
+
+ return grePath;
+ }
+
+ /**
+ * @param aVersionToCheck
+ * @param aVersions
+ * @return
+ */
+ private static boolean checkVersion(String aVersionToCheck,
+ GREVersionRange[] aVersions) {
+ for (int i = 0; i < aVersions.length; i++) {
+ if (aVersions[i].check(aVersionToCheck)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Initialize the Mozilla object with the given XULRunner path. All
+ * subsequent Mozilla method invocations be done against the given XULRunner
+ * version.
+ *
+ * @param aLibXULDirectory path of XULRunner build to use
+ *
+ * @throws XPCOMInitializationException if failure occurred during
+ * initialization
+ */
+ public void initialize(File aLibXULDirectory)
+ throws XPCOMInitializationException {
+ File jar = new File(aLibXULDirectory, JAVAXPCOM_JAR);
+ if (!jar.exists()) {
+ jar = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
+ if (!jar.exists())
+ throw new XPCOMInitializationException("Could not find " + JAVAXPCOM_JAR +
+ " in " + aLibXULDirectory);
+ }
+
+ URL[] urls = new URL[1];
+ try {
+ urls[0] = jar.toURI().toURL();
+ } catch (MalformedURLException e) {
+ throw new XPCOMInitializationException(e);
+ }
+ ClassLoader loader = new URLClassLoader(urls,
+ this.getClass().getClassLoader());
+
+ try {
+ Class mozillaClass = Class.forName("org.mozilla.xpcom.internal.MozillaImpl",
+ true, loader);
+ mozilla = (IMozilla) mozillaClass.newInstance();
+
+ Class greClass = Class.forName("org.mozilla.xpcom.internal.GREImpl",
+ true, loader);
+ gre = (IGRE) greClass.newInstance();
+
+ Class xpcomClass = Class.forName("org.mozilla.xpcom.internal.XPCOMImpl",
+ true, loader);
+ xpcom = (IXPCOM) xpcomClass.newInstance();
+
+ Class javaXPCOMClass =
+ Class.forName("org.mozilla.xpcom.internal.JavaXPCOMMethods",
+ true, loader);
+ jxutils = (IJavaXPCOMUtils) javaXPCOMClass.newInstance();
+ } catch (Exception e) {
+ throw new XPCOMInitializationException("Could not load " +
+ "org.mozilla.xpcom.internal.* classes", e);
+ }
+
+ mozilla.initialize(aLibXULDirectory);
+ }
+
+ /**
+ * Initializes libXUL for embedding purposes.
+ * <p>
+ * NOTE: This function must be called from the "main" thread.
+ * <p>
+ * NOTE: At the present time, this function may only be called once in
+ * a given process. Use <code>termEmbedding</code> to clean up and free
+ * resources allocated by <code>initEmbedding</code>.
+ *
+ * @param aLibXULDirectory The directory in which the libXUL shared library
+ * was found.
+ * @param aAppDirectory The directory in which the application components
+ * and resources can be found. This will map to
+ * the "resource:app" directory service key.
+ * @param aAppDirProvider A directory provider for the application. This
+ * provider will be aggregated by a libXUL provider
+ * which will provide the base required GRE keys.
+ *
+ * @throws XPCOMException if a failure occurred during initialization
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public void initEmbedding(File aLibXULDirectory, File aAppDirectory,
+ IAppFileLocProvider aAppDirProvider) throws XPCOMException {
+ try {
+ gre.initEmbedding(aLibXULDirectory, aAppDirectory, aAppDirProvider);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * Terminates libXUL embedding.
+ * <p>
+ * NOTE: Release any references to XPCOM objects that you may be holding
+ * before calling this function.
+ *
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public void termEmbedding() {
+ try {
+ gre.termEmbedding();
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ } finally {
+ mozilla = null;
+ gre = null;
+ xpcom = null;
+ }
+ }
+
+ /**
+ * Lock a profile directory using platform-specific semantics.
+ *
+ * @param aDirectory The profile directory to lock.
+ *
+ * @return A lock object. The directory will remain locked until the lock is
+ * released by invoking the <code>release</code> method, or by the
+ * termination of the JVM, whichever comes first.
+ *
+ * @throws XPCOMException if profile is already locked (with
+ * <code>errorcode</code> == <code>NS_ERROR_FILE_ACCESS_DENIED</code>);
+ * or if a failure occurred
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public ProfileLock lockProfileDirectory(File aDirectory)
+ throws XPCOMException {
+ try {
+ return gre.lockProfileDirectory(aDirectory);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * Fire notifications to inform the toolkit about a new profile. This
+ * method should be called after <code>initEmbedding</code> if the
+ * embedder wishes to run with a profile.
+ * <p>
+ * Normally the embedder should call <code>lockProfileDirectory</code>
+ * to lock the directory before calling this method.
+ * <p>
+ * NOTE: There are two possibilities for selecting a profile:
+ * <ul>
+ * <li>
+ * Select the profile before calling <code>initEmbedding</code>.
+ * The aAppDirProvider object passed to <code>initEmbedding</code>
+ * should provide the NS_APP_USER_PROFILE_50_DIR key, and
+ * may also provide the following keys:
+ * <ul>
+ * <li>NS_APP_USER_PROFILE_LOCAL_50_DIR
+ * <li>NS_APP_PROFILE_DIR_STARTUP
+ * <li>NS_APP_PROFILE_LOCAL_DIR_STARTUP
+ * </ul>
+ * In this scenario <code>notifyProfile</code> should be called
+ * immediately after <code>initEmbedding</code>. Component
+ * registration information will be stored in the profile and
+ * JS components may be stored in the fastload cache.
+ * </li>
+ * <li>
+ * Select a profile some time after calling <code>initEmbedding</code>.
+ * In this case the embedder must install a directory service
+ * provider which provides NS_APP_USER_PROFILE_50_DIR and optionally
+ * NS_APP_USER_PROFILE_LOCAL_50_DIR. Component registration information
+ * will be stored in the application directory and JS components will not
+ * fastload.
+ * </li>
+ * </ul>
+ *
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public void notifyProfile() {
+ try {
+ gre.notifyProfile();
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * Initializes XPCOM. You must call this method before proceeding
+ * to use XPCOM.
+ *
+ * @param aMozBinDirectory The directory containing the component
+ * registry and runtime libraries;
+ * or use <code>null</code> to use the working
+ * directory.
+ *
+ * @param aAppFileLocProvider The object to be used by Gecko that specifies
+ * to Gecko where to find profiles, the component
+ * registry preferences and so on; or use
+ * <code>null</code> for the default behaviour.
+ *
+ * @return the service manager
+ *
+ * @throws XPCOMException <ul>
+ * <li> NS_ERROR_NOT_INITIALIZED - if static globals were not initialied,
+ * which can happen if XPCOM is reloaded, but did not completly
+ * shutdown. </li>
+ * <li> Other error codes indicate a failure during initialisation. </li>
+ * </ul>
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public nsIServiceManager initXPCOM(File aMozBinDirectory,
+ IAppFileLocProvider aAppFileLocProvider) throws XPCOMException {
+ try {
+ return xpcom.initXPCOM(aMozBinDirectory, aAppFileLocProvider);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * Shutdown XPCOM. You must call this method after you are finished
+ * using xpcom.
+ *
+ * @param aServMgr The service manager which was returned by initXPCOM.
+ * This will release servMgr.
+ *
+ * @throws XPCOMException if a failure occurred during termination
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public void shutdownXPCOM(nsIServiceManager aServMgr) throws XPCOMException {
+ try {
+ xpcom.shutdownXPCOM(aServMgr);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ } finally {
+ mozilla = null;
+ gre = null;
+ xpcom = null;
+ }
+ }
+
+ /**
+ * Public Method to access to the service manager.
+ *
+ * @return the service manager
+ *
+ * @throws XPCOMException if a failure occurred
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public nsIServiceManager getServiceManager() throws XPCOMException {
+ try {
+ return xpcom.getServiceManager();
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * Public Method to access to the component manager.
+ *
+ * @return the component manager
+ *
+ * @throws XPCOMException if a failure occurred
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public nsIComponentManager getComponentManager() throws XPCOMException {
+ try {
+ return xpcom.getComponentManager();
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * Public Method to access to the component registration manager.
+ *
+ * @return the component registration manager
+ *
+ * @throws XPCOMException if a failure occurred
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public nsIComponentRegistrar getComponentRegistrar() throws XPCOMException {
+ try {
+ return xpcom.getComponentRegistrar();
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ // #ifdef VBOX
+ public int waitForEvents(long tmo) throws XPCOMException {
+ try {
+ return xpcom.waitForEvents(tmo);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+ // #endif // VBOX
+
+ /**
+ * Public Method to create an instance of a nsILocalFile.
+ *
+ * @param aPath A string which specifies a full file path to a
+ * location. Relative paths will be treated as an
+ * error (NS_ERROR_FILE_UNRECOGNIZED_PATH).
+ * @param aFollowLinks This attribute will determine if the nsLocalFile will
+ * auto resolve symbolic links. By default, this value
+ * will be false on all non unix systems. On unix, this
+ * attribute is effectively a noop.
+ *
+ * @return an instance of an nsILocalFile that points to given path
+ *
+ * @throws XPCOMException <ul>
+ * <li> NS_ERROR_FILE_UNRECOGNIZED_PATH - raised for unrecognized paths
+ * or relative paths (must supply full file path) </li>
+ * </ul>
+ * @throws XPCOMInitializationException if Mozilla was not properly
+ * initialized
+ */
+ public nsILocalFile newLocalFile(String aPath, boolean aFollowLinks)
+ throws XPCOMException {
+ try {
+ return xpcom.newLocalFile(aPath, aFollowLinks);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ /**
+ * If you create a class that implements nsISupports, you will need to provide
+ * an implementation of the <code>queryInterface</code> method. This helper
+ * function provides a simple implementation. Therefore, if your class does
+ * not need to do anything special with <code>queryInterface</code>, your
+ * implementation would look like:
+ * <pre>
+ * public nsISupports queryInterface(String aIID) {
+ * return XPCOM.queryInterface(this, aIID);
+ * }
+ * </pre>
+ *
+ * @param aObject object to query
+ * @param aIID requested interface IID
+ *
+ * @return <code>aObject</code> if the given object supports that
+ * interface;
+ * <code>null</code> otherwise.
+ */
+ public static nsISupports queryInterface(nsISupports aObject, String aIID) {
+ ArrayList<Class> classes = new ArrayList<Class>();
+ classes.add(aObject.getClass());
+
+ while (!classes.isEmpty()) {
+ Class clazz = classes.remove(0);
+
+ // Skip over any class/interface in the "java.*" and "javax.*" domains.
+ String className = clazz.getName();
+ if (className.startsWith("java.") || className.startsWith("javax.")) {
+ continue;
+ }
+
+ // If given IID matches that of the current interface, then we
+ // know that aObject implements the interface specified by the given IID.
+ if (clazz.isInterface() && className.startsWith("org.mozilla")) {
+ String iid = Mozilla.getInterfaceIID(clazz);
+ if (iid != null && aIID.equals(iid)) {
+ return aObject;
+ }
+ }
+
+ // clazz didn't match, so add the interfaces it implements
+ Class[] interfaces = clazz.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++ ) {
+ classes.add(interfaces[i]);
+ }
+
+ // Also add its superclass
+ Class superclass = clazz.getSuperclass();
+ if (superclass != null) {
+ classes.add(superclass);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the interface IID for a particular Java interface. This is similar
+ * to NS_GET_IID in the C++ Mozilla files.
+ *
+ * @param aInterface interface which has defined an IID
+ *
+ * @return IID for given interface
+ */
+ public static String getInterfaceIID(Class aInterface) {
+ // Get short class name (i.e. "bar", not "org.blah.foo.bar")
+ StringBuffer iidName = new StringBuffer();
+ String fullClassName = aInterface.getName();
+ int index = fullClassName.lastIndexOf(".");
+ String className = index > 0 ? fullClassName.substring(index + 1)
+ : fullClassName;
+
+ // Create iid field name
+ if (className.startsWith("ns")) {
+ iidName.append("NS_");
+ iidName.append(className.substring(2).toUpperCase());
+ } else {
+ iidName.append(className.toUpperCase());
+ }
+ iidName.append("_IID");
+
+ String iid;
+ try {
+ Field iidField = aInterface.getDeclaredField(iidName.toString());
+ iid = (String) iidField.get(null);
+ } catch (NoSuchFieldException e) {
+ // Class may implement non-Mozilla interfaces, which would not have an
+ // IID method. In that case, just null.
+ iid = null;
+ } catch (IllegalAccessException e) {
+ // Not allowed to access that field for some reason. Write out an
+ // error message, but don't fail.
+ System.err.println("ERROR: Could not get field " + iidName.toString());
+ iid = null;
+ }
+
+ return iid;
+ }
+
+ public long getNativeHandleFromAWT(Object widget) {
+ try {
+ return mozilla.getNativeHandleFromAWT(widget);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ public long wrapJavaObject(Object aJavaObject, String aIID) {
+ try {
+ return jxutils.wrapJavaObject(aJavaObject, aIID);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+ public Object wrapXPCOMObject(long aXPCOMObject, String aIID) {
+ try {
+ return jxutils.wrapXPCOMObject(aXPCOMObject, aIID);
+ } catch (NullPointerException e) {
+ throw new XPCOMInitializationException("Must call " +
+ "Mozilla.getInstance().initialize() before using this method", e);
+ }
+ }
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/ProfileLock.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/ProfileLock.java
new file mode 100644
index 00000000..f995a389
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/ProfileLock.java
@@ -0,0 +1,63 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+public class ProfileLock {
+
+ private long lock = 0;
+
+ public ProfileLock(long aLockObject) {
+ lock = aLockObject;
+ }
+
+ public void release() {
+ releaseNative(lock);
+ lock = 0;
+ }
+
+ private native void releaseNative(long aLockObject);
+
+ public boolean isValid() {
+ return lock != 0;
+ }
+
+ protected void finalize() throws Throwable {
+ release();
+ super.finalize();
+ }
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/VersionComparator.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/VersionComparator.java
new file mode 100644
index 00000000..f9fb1058
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/VersionComparator.java
@@ -0,0 +1,272 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import org.mozilla.interfaces.nsISupports;
+/* import org.mozilla.interfaces.nsIVersionComparator; */
+
+
+/**
+ * Version strings are dot-separated sequences of version-parts.
+ * <p>
+ * A version-part consists of up to four parts, all of which are optional:
+ * <br><code>
+ * &lt;number-a&gt;&lt;string-b&gt;&lt;number-c&gt;
+ * &lt;string-d (everything else)&gt;
+ * </code> <p>
+ * A version-part may also consist of a single asterisk "*" which indicates
+ * "infinity".
+ * <p>
+ * Numbers are base-10, and are zero if left out.
+ * Strings are compared bytewise.
+ * <p>
+ * For additional backwards compatibility, if "string-b" is "+" then
+ * "number-a" is incremented by 1 and "string-b" becomes "pre".
+ * <p> <pre>
+ * 1.0pre1
+ * < 1.0pre2
+ * < 1.0 == 1.0.0 == 1.0.0.0
+ * < 1.1pre == 1.1pre0 == 1.0+
+ * < 1.1pre1a
+ * < 1.1pre1
+ * < 1.1pre10a
+ * < 1.1pre10
+ * </pre>
+ * Although not required by this interface, it is recommended that
+ * numbers remain within the limits of a signed char, i.e. -127 to 128.
+ */
+public class VersionComparator implements nsISupports /* implements nsIVersionComparator */ {
+
+ public nsISupports queryInterface(String aIID) {
+ return Mozilla.queryInterface(this, aIID);
+ }
+
+ /**
+ * Compare two version strings
+ * @param A a version string
+ * @param B a version string
+ * @return a value less than 0 if A < B;
+ * the value 0 if A == B;
+ * or a value greater than 0 if A > B
+ */
+ public int compare(String A, String B) {
+ int result;
+ String a = A, b = B;
+
+ do {
+ VersionPart va = new VersionPart();
+ VersionPart vb = new VersionPart();
+ a = parseVersionPart(a, va);
+ b = parseVersionPart(b, vb);
+
+ result = compareVersionPart(va, vb);
+ if (result != 0) {
+ break;
+ }
+ } while (a != null || b != null);
+
+ return result;
+ }
+
+ private class VersionPart {
+ int numA = 0;
+ String strB;
+ int numC = 0;
+ String extraD;
+ }
+
+ private static String parseVersionPart(String aVersion, VersionPart result) {
+ if (aVersion == null || aVersion.length() == 0) {
+ return aVersion;
+ }
+
+ StringTokenizer tok = new StringTokenizer(aVersion.trim(), ".");
+ String part = tok.nextToken();
+
+ if (part.equals("*")) {
+ result.numA = Integer.MAX_VALUE;
+ result.strB = "";
+ } else {
+ VersionPartTokenizer vertok = new VersionPartTokenizer(part);
+ try {
+ result.numA = Integer.parseInt(vertok.nextToken());
+ } catch (NumberFormatException e) {
+ // parsing error; default to zero like 'strtol' C function
+ result.numA = 0;
+ }
+
+ if (vertok.hasMoreElements()) {
+ String str = vertok.nextToken();
+
+ // if part is of type "<num>+"
+ if (str.charAt(0) == '+') {
+ result.numA++;
+ result.strB = "pre";
+ } else {
+ // else if part is of type "<num><alpha>..."
+ result.strB = str;
+
+ if (vertok.hasMoreTokens()) {
+ try {
+ result.numC = Integer.parseInt(vertok.nextToken());
+ } catch (NumberFormatException e) {
+ // parsing error; default to zero like 'strtol' C function
+ result.numC = 0;
+ }
+ if (vertok.hasMoreTokens()) {
+ result.extraD = vertok.getRemainder();
+ }
+ }
+ }
+ }
+ }
+
+ if (tok.hasMoreTokens()) {
+ // return everything after "."
+ return aVersion.substring(part.length() + 1);
+ }
+ return null;
+ }
+
+ private int compareVersionPart(VersionPart va, VersionPart vb) {
+ int res = compareInt(va.numA, vb.numA);
+ if (res != 0) {
+ return res;
+ }
+
+ res = compareString(va.strB, vb.strB);
+ if (res != 0) {
+ return res;
+ }
+
+ res = compareInt(va.numC, vb.numC);
+ if (res != 0) {
+ return res;
+ }
+
+ return compareString(va.extraD, vb.extraD);
+ }
+
+ private int compareInt(int n1, int n2) {
+ return n1 - n2;
+ }
+
+ private int compareString(String str1, String str2) {
+ // any string is *before* no string
+ if (str1 == null) {
+ return (str2 != null) ? 1 : 0;
+ }
+
+ if (str2 == null) {
+ return -1;
+ }
+
+ return str1.compareTo(str2);
+ }
+
+}
+
+/**
+ * Specialized tokenizer for Mozilla version strings. A token can
+ * consist of one of the four sections of a version string: <code>
+ * &lt;number-a&gt;&lt;string-b&gt;&lt;number-c&gt;
+ * &lt;string-d (everything else)&gt;</code>.
+ */
+class VersionPartTokenizer implements Enumeration {
+
+ String part;
+
+ public VersionPartTokenizer(String aPart) {
+ part = aPart;
+ }
+
+ public boolean hasMoreElements() {
+ return part.length() != 0;
+ }
+
+ public boolean hasMoreTokens() {
+ return part.length() != 0;
+ }
+
+ public Object nextElement() {
+ if (part.matches("[\\+\\-]?[0-9].*")) {
+ // if string starts with a number...
+ int index = 0;
+ if (part.charAt(0) == '+' || part.charAt(0) == '-') {
+ index = 1;
+ }
+
+ while (index < part.length() && Character.isDigit(part.charAt(index))) {
+ index++;
+ }
+
+ String numPart = part.substring(0, index);
+ part = part.substring(index);
+ return numPart;
+ } else {
+ // ... or if this is the non-numeric part of version string
+ int index = 0;
+ while (index < part.length() && !Character.isDigit(part.charAt(index))) {
+ index++;
+ }
+
+ String alphaPart = part.substring(0, index);
+ part = part.substring(index);
+ return alphaPart;
+ }
+ }
+
+ public String nextToken() {
+ return (String) nextElement();
+ }
+
+ /**
+ * Returns what remains of the original string, without tokenization. This
+ * method is useful for getting the <code>&lt;string-d (everything else)&gt;
+ * </code> section of a version string.
+ *
+ * @return remaining version string
+ */
+ public String getRemainder() {
+ return part;
+ }
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMException.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMException.java
new file mode 100644
index 00000000..9eca58f6
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMException.java
@@ -0,0 +1,95 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+
+/**
+ * This exception is thrown whenever an internal XPCOM/Gecko error occurs.
+ * You can query the error ID returned by XPCOM by checking
+ * <code>errorcode</code> field.
+ */
+public class XPCOMException extends RuntimeException {
+
+ /**
+ * The XPCOM error value.
+ */
+ public long errorcode;
+
+ private static final long serialVersionUID = 198521829884000593L;
+
+ /**
+ * Constructs a new XPCOMException instance, with a default error
+ * (NS_ERROR_FAILURE) and message.
+ */
+ public XPCOMException() {
+ this(0x80004005L, "Unspecified internal XPCOM error");
+ }
+
+ /**
+ * Constructs a new XPCOMException instance with the given message, passing
+ * NS_ERROR_FAILURE as the error code.
+ *
+ * @param message detailed message of exception
+ */
+ public XPCOMException(String message) {
+ this(0x80004005L, message);
+ }
+
+ /**
+ * Constructs a new XPCOMException instance with the given code, passing
+ * a default message.
+ *
+ * @param code internal XPCOM error ID
+ */
+ public XPCOMException(long code) {
+ this(code, "Internal XPCOM error");
+ }
+
+ /**
+ * Constructs a new XPCOMException instance with an error code and message.
+ *
+ * @param code internal XPCOM error ID
+ * @param message detailed message of exception
+ */
+ public XPCOMException(long code, String message) {
+ super(message + " (0x" + Long.toHexString(code) + ")");
+ this.errorcode = code;
+ }
+
+}
+
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMInitializationException.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMInitializationException.java
new file mode 100644
index 00000000..26ce5325
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/XPCOMInitializationException.java
@@ -0,0 +1,56 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom;
+
+
+public class XPCOMInitializationException extends RuntimeException {
+
+ private static final long serialVersionUID = -7067350325909231055L;
+
+ public XPCOMInitializationException(String message) {
+ super(message);
+ }
+
+ public XPCOMInitializationException(Throwable cause) {
+ super(cause);
+ }
+
+ public XPCOMInitializationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/GREImpl.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/GREImpl.java
new file mode 100644
index 00000000..74821c36
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/GREImpl.java
@@ -0,0 +1,63 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom.internal;
+
+import java.io.File;
+
+import org.mozilla.xpcom.IAppFileLocProvider;
+import org.mozilla.xpcom.IGRE;
+import org.mozilla.xpcom.ProfileLock;
+
+
+public class GREImpl implements IGRE {
+
+ public void initEmbedding(File aLibXULDirectory, File aAppDirectory,
+ IAppFileLocProvider aAppDirProvider) {
+ initEmbeddingNative(aLibXULDirectory, aAppDirectory, aAppDirProvider);
+ }
+
+ public native void initEmbeddingNative(File aLibXULDirectory,
+ File aAppDirectory, IAppFileLocProvider aAppDirProvider);
+
+ public native void termEmbedding();
+
+ public native ProfileLock lockProfileDirectory(File aDirectory);
+
+ public native void notifyProfile();
+
+}
+
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/JavaXPCOMMethods.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/JavaXPCOMMethods.java
new file mode 100644
index 00000000..ab0ca251
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/JavaXPCOMMethods.java
@@ -0,0 +1,104 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom.internal;
+
+import java.io.File;
+
+import org.mozilla.xpcom.IJavaXPCOMUtils;
+
+
+public class JavaXPCOMMethods implements IJavaXPCOMUtils {
+
+ public static void registerJavaXPCOMMethods(File aLibXULDirectory) {
+ // load JNI library
+ String path = "";
+ if (aLibXULDirectory != null) {
+ path = aLibXULDirectory + File.separator;
+ }
+
+ if (false)
+ {
+ String osName = System.getProperty("os.name").toLowerCase();
+ if (osName.startsWith("os/2")) {
+ System.load(path + System.mapLibraryName("jxpcmglu"));
+ } else {
+ System.load(path + System.mapLibraryName("javaxpcomglue"));
+ }
+ } else {
+ // #ifdef VBOX
+ try {
+ System.load(path + System.mapLibraryName("vboxjxpcom"));
+ } catch (java.lang.UnsatisfiedLinkError ule) {
+ System.loadLibrary("vboxjxpcom");
+ }
+ // #endif
+ }
+ registerJavaXPCOMMethodsNative(aLibXULDirectory);
+ }
+
+ public static native void
+ registerJavaXPCOMMethodsNative(File aLibXULDirectory);
+
+ /**
+ * Returns the Class object associated with the class or interface with the
+ * given string name, using the class loader of the given object.
+ *
+ * @param aObject the Java object whose class loader is used to load class
+ * @param aClassName the fully qualified name of desired class
+ * @return the Class object of requested Class; <code>null</code> if the
+ * class was not found
+ *
+ * @see http://java.sun.com/j2se/1.3/docs/guide/jni/jni-12.html#classops
+ */
+ public static Class findClassInLoader(Object aObject, String aClassName) {
+ try {
+ if (aObject == null) {
+ return Class.forName(aClassName);
+ } else {
+ return Class.forName(aClassName, true,
+ aObject.getClass().getClassLoader());
+ }
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ public native long wrapJavaObject(Object aJavaObject, String aIID);
+
+ public native Object wrapXPCOMObject(long aXPCOMObject, String aIID);
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/MozillaImpl.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/MozillaImpl.java
new file mode 100644
index 00000000..27fd9482
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/MozillaImpl.java
@@ -0,0 +1,56 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom.internal;
+
+import java.io.File;
+
+import org.mozilla.xpcom.IMozilla;
+import org.mozilla.xpcom.XPCOMInitializationException;
+
+public class MozillaImpl implements IMozilla {
+
+ public void initialize(File aLibXULDirectory)
+ throws XPCOMInitializationException {
+ JavaXPCOMMethods.registerJavaXPCOMMethods(aLibXULDirectory);
+ initializeNative();
+ }
+
+ private native void initializeNative();
+
+ public native long getNativeHandleFromAWT(Object widget);
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMImpl.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMImpl.java
new file mode 100644
index 00000000..1111a9e0
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMImpl.java
@@ -0,0 +1,73 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom.internal;
+
+import java.io.File;
+
+import org.mozilla.xpcom.IAppFileLocProvider;
+import org.mozilla.xpcom.IXPCOM;
+
+import org.mozilla.interfaces.nsIComponentManager;
+import org.mozilla.interfaces.nsIComponentRegistrar;
+import org.mozilla.interfaces.nsILocalFile;
+import org.mozilla.interfaces.nsIServiceManager;
+
+
+public class XPCOMImpl implements IXPCOM {
+
+ public nsIServiceManager initXPCOM(File aMozBinDirectory,
+ IAppFileLocProvider aAppFileLocProvider) {
+ return initXPCOMNative(aMozBinDirectory, aAppFileLocProvider);
+ }
+
+ public native nsIServiceManager initXPCOMNative(File aMozBinDirectory,
+ IAppFileLocProvider aAppFileLocProvider);
+
+ public native void shutdownXPCOM(nsIServiceManager aServMgr);
+
+ public native nsIComponentManager getComponentManager();
+
+ public native nsIComponentRegistrar getComponentRegistrar();
+
+ public native nsIServiceManager getServiceManager();
+
+ public native nsILocalFile newLocalFile(String aPath, boolean aFollowLinks);
+
+ // #ifdef VBOX
+ public native int waitForEvents(long timeout);
+ // #endif VBOX
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java
new file mode 100644
index 00000000..c6485708
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java
@@ -0,0 +1,257 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.mozilla.xpcom.XPCOMException;
+
+
+/**
+ * This class is used to pass XPCOM objects to Java functions. A
+ * <code>java.lang.reflect.Proxy</code> instance is created using the expected
+ * interface, and all calls to the proxy are forwarded to the XPCOM object.
+ */
+public class XPCOMJavaProxy implements InvocationHandler {
+
+ /**
+ * Pointer to the XPCOM object for which we are a proxy.
+ */
+ protected long nativeXPCOMPtr;
+
+ /**
+ * Default constructor.
+ *
+ * @param aXPCOMInstance address of XPCOM object as a long
+ */
+ public XPCOMJavaProxy(long aXPCOMInstance) {
+ nativeXPCOMPtr = aXPCOMInstance;
+ }
+
+ /**
+ * Returns the XPCOM object that the given proxy references.
+ *
+ * @param aProxy Proxy created by <code>createProxy</code>
+ *
+ * @return address of XPCOM object as a long
+ */
+ protected static long getNativeXPCOMInstance(Object aProxy) {
+ XPCOMJavaProxy proxy = (XPCOMJavaProxy) Proxy.getInvocationHandler(aProxy);
+ return proxy.nativeXPCOMPtr;
+ }
+
+ /**
+ * Creates a Proxy for the given XPCOM object.
+ *
+ * @param aInterface interface from which to create Proxy
+ * @param aXPCOMInstance address of XPCOM object as a long
+ *
+ * @return Proxy of given XPCOM object
+ */
+ protected static Object createProxy(Class aInterface, long aXPCOMInstance) {
+ // XXX We should really get the class loader from |aInterface|. However,
+ // that class loader doesn't know about |XPCOMJavaProxyBase|. So for
+ // now, we get the class loader that loaded |XPCOMJavaProxy|. When
+ // we get rid of the "XPCOMJavaProxyBase.java" class, we can revert
+ // to the old method below.
+// return Proxy.newProxyInstance(aInterface.getClassLoader(),
+ return Proxy.newProxyInstance(XPCOMJavaProxy.class.getClassLoader(),
+ new Class[] { aInterface, XPCOMJavaProxyBase.class },
+ new XPCOMJavaProxy(aXPCOMInstance));
+ }
+
+ /**
+ * All calls to the Java proxy are forwarded to this method. This method
+ * takes care of a few of the <code>Object</code> method calls; all other
+ * calls are forwarded to the XPCOM object.
+ *
+ * @param aProxy Proxy created by <code>createProxy</code>
+ * @param aMethod object that describes the called method
+ * @param aParams array of the arguments passed to the method
+ *
+ * @return return value as defined by given <code>aMethod</code>
+ */
+ public Object invoke(Object aProxy, Method aMethod, Object[] aParams)
+ throws Throwable {
+ String methodName = aMethod.getName();
+
+ // Handle the three java.lang.Object methods that are passed to us.
+ if (aMethod.getDeclaringClass() == Object.class) {
+ if (methodName.equals("hashCode")) {
+ return proxyHashCode(aProxy);
+ }
+ if (methodName.equals("equals")) {
+ return proxyEquals(aProxy, aParams[0]);
+ }
+ if (methodName.equals("toString")) {
+ return proxyToString(aProxy);
+ }
+ System.err.println("WARNING: Unhandled Object method [" +
+ methodName + "]");
+ return null;
+ }
+
+ // Handle the 'finalize' method called during garbage collection
+ if (aMethod.getDeclaringClass() == XPCOMJavaProxyBase.class) {
+ if (methodName.equals("finalize")) {
+ finalizeProxy(aProxy);
+ } else {
+ System.err.println("WARNING: Unhandled XPCOMJavaProxyBase method [" +
+ methodName + "]");
+ }
+ return null;
+ }
+
+ // If not already handled, pass method calls to XPCOM object.
+ return callXPCOMMethod(aProxy, methodName, aParams);
+ }
+
+ /**
+ * Handles method calls of <code>java.lang.Object.hashCode</code>
+ *
+ * @param aProxy Proxy created by <code>createProxy</code>
+ *
+ * @return Integer object representing hash code of given object
+ *
+ * @see Object#hashCode()
+ */
+ protected static Integer proxyHashCode(Object aProxy) {
+ return new Integer(System.identityHashCode(aProxy));
+ }
+
+ /**
+ * Handles method calls of <code>java.lang.Object.equals</code>
+ *
+ * @param aProxy Proxy created by <code>createProxy</code>
+ * @param aOther another object
+ *
+ * @return <code>true</code> if the given objects are the same;
+ * <code>false</code> otherwise
+ *
+ * @see Object#equals(Object)
+ */
+ protected static Boolean proxyEquals(Object aProxy, Object aOther) {
+ // See if the two are the same Java object
+ if (aProxy == aOther) {
+ return Boolean.TRUE;
+ } else {
+ // If not, then see if they represent the same XPCOM object. But first,
+ // we need to check if |aOther| is an XPCOMJavaProxy.
+ if (isXPCOMJavaProxy(aOther) && isSameXPCOMObject(aProxy, aOther)) {
+ return Boolean.TRUE;
+ }
+ }
+ return Boolean.FALSE;
+ }
+
+ /**
+ * Indicates whether the given object is an XPCOMJavaProxy.
+ *
+ * @param aObject object to check
+ *
+ * @return <code>true</code> if the given object is an XPCOMJavaProxy;
+ * <code>false</code> otherwise
+ */
+ protected static boolean isXPCOMJavaProxy(Object aObject) {
+ if (aObject != null && Proxy.isProxyClass(aObject.getClass())) {
+ InvocationHandler h = Proxy.getInvocationHandler(aObject);
+ if (h instanceof XPCOMJavaProxy) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the two given XPCOMJavaProxy objects are proxies for
+ * the same XPCOM object.
+ *
+ * @param aProxy1 XPCOMJavaProxy created by <code>createProxy</code>
+ * @param aProxy2 XPCOMJavaProxy created by <code>createProxy</code>
+ *
+ * @return <code>true</code> if both proxies represent the same XPCOM object;
+ * <code>false</code> otherwise
+ */
+ protected static native boolean isSameXPCOMObject(Object aProxy1,
+ Object aProxy2);
+
+ /**
+ * Handles method calls of <code>java.lang.Object.toString</code>
+ *
+ * @param aProxy Proxy created by <code>createProxy</code>
+ *
+ * @return String representation of given object
+ *
+ * @see Object#toString()
+ */
+ protected static String proxyToString(Object aProxy) {
+ return aProxy.getClass().getInterfaces()[0].getName() + '@' +
+ Integer.toHexString(aProxy.hashCode());
+ }
+
+ /**
+ * Called when the proxy is garbage collected by the JVM. Allows us to clean
+ * up any references to the XPCOM object.
+ *
+ * @param aProxy reference to Proxy that is being garbage collected
+ */
+ protected void finalizeProxy(Object aProxy) throws Throwable {
+ finalizeProxyNative(aProxy);
+ super.finalize();
+ }
+
+ protected static native void finalizeProxyNative(Object aProxy);
+
+ /**
+ * Calls the XPCOM object referenced by the proxy with the given method.
+ *
+ * @param aProxy Proxy created by <code>createProxy</code>
+ * @param aMethodName name of method that we want to call
+ * @param aParams array of params passed to method
+ *
+ * @return return value as defined by given method
+ *
+ * @exception XPCOMException if XPCOM method failed. Values of XPCOMException
+ * are defined by the method called.
+ */
+ protected static native Object callXPCOMMethod(Object aProxy,
+ String aMethodName, Object[] aParams);
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxyBase.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxyBase.java
new file mode 100644
index 00000000..595a7a2c
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxyBase.java
@@ -0,0 +1,53 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 ***** */
+
+package org.mozilla.xpcom.internal;
+
+
+/**
+ * This interface forms the foundation of any XPCOMJavaProxy that is created.
+ * It allows us to handle any JVM calls to <code>finalize</code> when the Proxy
+ * is garbage collected.
+ */
+public interface XPCOMJavaProxyBase {
+
+ /**
+ * @see java.lang.Object#finalize()
+ */
+ void finalize() throws Throwable;
+
+}
diff --git a/src/libs/xpcom18a4/java/src/org/virtualbox/VBoxObjectBase.java b/src/libs/xpcom18a4/java/src/org/virtualbox/VBoxObjectBase.java
new file mode 100644
index 00000000..29491595
--- /dev/null
+++ b/src/libs/xpcom18a4/java/src/org/virtualbox/VBoxObjectBase.java
@@ -0,0 +1,31 @@
+/* $Id: VBoxObjectBase.java $ */
+/*
+ * Copyright (C) 2010-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+import org.mozilla.interfaces.nsISupports;
+
+public abstract class VBoxObjectBase implements nsISupports
+{
+ public nsISupports queryInterface(String iid)
+ {
+ return org.mozilla.xpcom.Mozilla.queryInterface(this, iid);
+ }
+}
diff --git a/src/libs/xpcom18a4/java/tools/gen-nsError.pl b/src/libs/xpcom18a4/java/tools/gen-nsError.pl
new file mode 100755
index 00000000..da866b83
--- /dev/null
+++ b/src/libs/xpcom18a4/java/tools/gen-nsError.pl
@@ -0,0 +1,161 @@
+#! /usr/bin/env perl
+# ***** 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 Java XPCOM Bindings.
+#
+# The Initial Developer of the Original Code is
+# Michal Ceresna.
+# Portions created by the Initial Developer are Copyright (C) 2005
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Michal Ceresna (ceresna@dbai.tuwien.ac.at)
+# Javier Pedemonte (jhpedemonte@gmail.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 *****
+
+# Generates XPCOMError.java from xpcom/base/nsError.h
+#
+# usage: perl gen-nsErrors.pl < <topsrcdir>/xpcom/base/nsError.h > XPCOMError.java
+
+
+print "/* ***** BEGIN LICENSE BLOCK *****\n";
+print " * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n";
+print " *\n";
+print " * The contents of this file are subject to the Mozilla Public License Version\n";
+print " * 1.1 (the \"License\"); you may not use this file except in compliance with\n";
+print " * the License. You may obtain a copy of the License at\n";
+print " * http://www.mozilla.org/MPL/\n";
+print " *\n";
+print " * Software distributed under the License is distributed on an \"AS IS\" basis,\n";
+print " * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n";
+print " * for the specific language governing rights and limitations under the\n";
+print " * License.\n";
+print " *\n";
+print " * The Original Code is mozilla.org code.\n";
+print " *\n";
+print " * The Initial Developer of the Original Code is\n";
+print " * Netscape Communications Corporation.\n";
+print " * Portions created by the Initial Developer are Copyright (C) 1998\n";
+print " * the Initial Developer. All Rights Reserved.\n";
+print " *\n";
+print " * Contributor(s):\n";
+print " *\n";
+print " * Alternatively, the contents of this file may be used under the terms of\n";
+print " * either of the GNU General Public License Version 2 or later (the \"GPL\"),\n";
+print " * or the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n";
+print " * in which case the provisions of the GPL or the LGPL are applicable instead\n";
+print " * of those above. If you wish to allow use of your version of this file only\n";
+print " * under the terms of either the GPL or the LGPL, and not to allow others to\n";
+print " * use your version of this file under the terms of the MPL, indicate your\n";
+print " * decision by deleting the provisions above and replace them with the notice\n";
+print " * and other provisions required by the GPL or the LGPL. If you do not delete\n";
+print " * the provisions above, a recipient may use your version of this file under\n";
+print " * the terms of any one of the MPL, the GPL or the LGPL.\n";
+print " *\n";
+print " * ***** END LICENSE BLOCK ***** */\n";
+
+print "\n";
+print "package org.mozilla.xpcom;\n";
+print "\n\n";
+
+print "/**\n";
+print " * Mozilla error codes.\n";
+print " *\n";
+print " * THIS FILE GENERATED FROM mozilla/xpcom/base/nsError.h.\n";
+print " * PLEASE SEE THAT FILE FOR FULL DOCUMENTATION.\n";
+print " */\n";
+print "public interface XPCOMError {\n";
+
+while (<STDIN>) {
+ $line = $_;
+
+ if ($prevline) {
+ $_ = $prevline.$_;
+ }
+ if (/(.*)\\$/) {
+ #splitted line
+ $prevline = $1;
+ next;
+ }
+ $prevline = "";
+
+ if (/^\s*#define\s+(NS_[A-Z_]+)\s+(0x)?([0-9a-fA-F]+)\s*$/) {
+ #define NS_ERROR_MODULE_XPCOM 1
+ #define NS_ERROR_MODULE_BASE_OFFSET 0x45
+ print " public static final long $1 = $2$3L;\n";
+ }
+ elsif (/^\s*#define\s+(NS_[A-Z_]+)\s+\((NS_[A-Z_]+)\s+\+\s+(0x)?([0-9a-fA-F]+)\s*\)\s*/) {
+ #define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
+ #define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
+ print " public static final long $1 = $2 + $3$4L;\n";
+ }
+ elsif (/^\s*#define\s+(NS_[A-Z_]+)\s+(NS_[A-Z_]+)\s\s*/) {
+ #define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
+ print " public static final long $1 = $2;\n";
+ }
+ elsif (/^\s*#define\s+(NS_[A-Z_]+)\s+\(\(nsresult\)\s*(0x)?([0-9a-fA-F]+)L?\)\s*$/) {
+ #define NS_ERROR_BASE ((nsresult) 0xC1F30000)
+ #define NS_ERROR_ABORT ((nsresult) 0x80004004L)
+ print " public static final long $1 = $2$3L;\n";
+ }
+ elsif (/^\s*#define\s+(NS_[A-Z_]+)\s+NS_ERROR_GENERATE_FAILURE\s*\(\s*(NS_[A-Z_]+)\s*,\s*([0-9]+)\s*\)\s*$/) {
+ #define NS_BASE_STREAM_CLOSED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
+ $module = $2;
+ $code = $3;
+ print " public static final long $1 = ((NS_ERROR_SEVERITY_ERROR<<31) | (($module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | $code);\n";
+ }
+ elsif (/^\s*#define\s+(NS_[A-Z_]+)\s+NS_ERROR_GENERATE_SUCCESS\s*\(\s*(NS_[A-Z_]+)\s*,\s*([0-9]+)\s*\)\s*$/) {
+ #define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1)
+ $module = $2;
+ $code = $3;
+ print " public static final long $1 = ((NS_ERROR_SEVERITY_SUCCESS<<31) | (($module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | $code);\n";
+ }
+ elsif (/^\s*\/\*(.*)\*\/\s*$/ && !/^\s*\/\*@[\{\}]\*\/\s*$/ &&
+ !/^\s*\/\*\ -\*- Mode:/) {
+ #single line comment, but not
+ #/*@{*/, /*@}*/,
+ #/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+ print " /*$1*/\n";
+ }
+ elsif (/^\s*$/) {
+ #empty line, but write only the first
+ #line from a sequence of empty lines
+ if (!$wasEmpty) {
+ print "\n";
+ }
+ $wasEmpty = 1;
+ next;
+ }
+ else {
+ next;
+ }
+
+ $wasEmpty = 0;
+}
+
+print "}\n";
+
diff --git a/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp b/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp
new file mode 100644
index 00000000..60648beb
--- /dev/null
+++ b/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp
@@ -0,0 +1,952 @@
+/* ***** 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 Java XPCOM Bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * IBM Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Javier Pedemonte (jhpedemonte@gmail.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 "nsXPCOM.h"
+#include "nsString.h"
+#include "nsILocalFile.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+#include "nsCOMPtr.h"
+#include "prmem.h"
+#include "xptcall.h"
+#ifdef VBOX
+#include "nsFileStreams.h"
+static nsresult
+NS_NewLocalFileInputStream(nsIInputStream **aResult,
+ nsIFile *aFile,
+ PRInt32 aIOFlags = -1,
+ PRInt32 aPerm = -1,
+ PRInt32 aBehaviorFlags = 0)
+{
+ nsFileInputStream* in = new nsFileInputStream();
+ nsresult rv;
+
+ rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
+ if (NS_SUCCEEDED(rv))
+ NS_ADDREF(*aResult = in);
+
+ return rv;
+}
+
+inline nsresult
+NS_NewLocalFileOutputStream(nsIOutputStream **aResult,
+ nsIFile *aFile,
+ PRInt32 aIOFlags = -1,
+ PRInt32 aPerm = -1,
+ PRInt32 aBehaviorFlags = 0)
+{
+ nsFileOutputStream* in = new nsFileOutputStream();
+ nsresult rv;
+
+ rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
+ if (NS_SUCCEEDED(rv))
+ NS_ADDREF(*aResult = in);
+
+ return rv;
+}
+
+
+#else
+#include "nsNetUtil.h"
+#endif
+#include "nsHashSets.h"
+#include "nsIWeakReference.h"
+#include <stdio.h>
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif
+
+#define WRITE_NOSCRIPT_METHODS
+
+
+class TypeInfo
+{
+public:
+ static nsresult GetParentInfo(nsIInterfaceInfo* aIInfo,
+ nsIInterfaceInfo** aParentInfo,
+ PRUint16* aParentMethodCount,
+ PRUint16* aParentConstCount)
+ {
+ nsCOMPtr<nsIInterfaceInfo> parent;
+ nsresult rv = aIInfo->GetParent(getter_AddRefs(parent));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!parent) {
+ *aParentInfo = nsnull;
+ *aParentMethodCount = 0;
+ return NS_OK;
+ }
+
+ rv = parent->GetMethodCount(aParentMethodCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = parent->GetConstantCount(aParentConstCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aParentInfo = parent;
+ NS_ADDREF(*aParentInfo);
+ return rv;
+ }
+
+ static nsresult GetInterfaceName(nsIInterfaceInfo* aIInfo,
+ PRUint16 aMethodIndex,
+ const nsXPTParamInfo* aParamInfo,
+ char** aResult)
+ {
+ static const char isupp_str[] = "nsISupports";
+
+ nsIID* iid;
+ nsresult rv = aIInfo->GetIIDForParam(aMethodIndex, aParamInfo, &iid);
+ if (NS_FAILED(rv)) {
+ // GetIIDForParam will sometimes fail to find an interface, particularly
+ // if that interface is not defined in an IDL file. In those cases, just
+ // return |nsISupports|.
+ //
+ // For example, the |onStreamComplete| method for the interface
+ // |nsIUnicharStreamLoaderObserver| takes a param of
+ // |nsIUnicharInputStream|, which is defined in a simple header file, not
+ // an IDL file.
+ *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
+ rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
+
+ } else {
+
+ // In Javaconnect, we handle weak references internally; no need for the
+ // |nsIWeakReference| interface. So just return |nsISupports|.
+ if (iid->Equals(NS_GET_IID(nsIWeakReference))) {
+ *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
+ rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
+
+ } else {
+
+ // Some methods take parameters of non-scriptable interfaces. But we
+ // only output scriptable interfaces. So if one of the param types is
+ // a non-scriptable interface, output |nsISupports| instead of the
+ // interface name.
+ nsCOMPtr<nsIInterfaceInfo> info;
+ nsCOMPtr<nsIInterfaceInfoManager> iim =
+ getter_AddRefs(XPTI_GetInterfaceInfoManager());
+ NS_ASSERTION(iim, "could not get interface info manager");
+ rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
+ NS_ENSURE_SUCCESS(rv, rv);
+ PRBool scriptable;
+ if (NS_SUCCEEDED(rv)) {
+ info->IsScriptable(&scriptable);
+ }
+ if (NS_FAILED(rv) || !scriptable) {
+ *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
+ rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
+ } else {
+
+ // If is scriptable, get name for given IID
+ rv = iim->GetNameForIID(iid, aResult);
+ }
+ }
+
+ nsMemory::Free(iid);
+ }
+
+ return rv;
+ }
+};
+
+
+static const char* kJavaKeywords[] = {
+ "abstract", "default", "if" , "private" , "this" ,
+ "boolean" , "do" , "implements", "protected" , "throw" ,
+ "break" , "double" , "import", "public" , "throws" ,
+ "byte" , "else" , "instanceof", "return" , "transient",
+ "case" , "extends", "int" , "short" , "try" ,
+ "catch" , "final" , "interface" , "static" , "void" ,
+ "char" , "finally", "long" , "strictfp" , "volatile" ,
+ "class" , "float" , "native" , "super" , "while" ,
+ "const" , "for" , "new" , "switch" ,
+ "continue", "goto" , "package" , "synchronized",
+ "assert" , /* added in Java 1.4 */
+ "enum" , /* added in Java 5.0 */
+ "clone" , /* clone is a member function of java.lang.Object */
+ "finalize" /* finalize is a member function of java.lang.Object */
+};
+
+#ifdef WRITE_NOSCRIPT_METHODS
+// SWT uses [noscript] methods of the following interfaces, so we need to
+// output the [noscript] methods for these interfaces.
+static const char* kNoscriptMethodIfaces[] = {
+ "nsIBaseWindow", "nsIEmbeddingSiteWindow"
+};
+#endif
+
+
+class Generate
+{
+ nsILocalFile* mOutputDir;
+ nsCStringHashSet mIfaceTable;
+ nsCStringHashSet mJavaKeywords;
+#ifdef WRITE_NOSCRIPT_METHODS
+ nsCStringHashSet mNoscriptMethodsTable;
+#endif
+
+public:
+ Generate(nsILocalFile* aOutputDir)
+ : mOutputDir(aOutputDir)
+ {
+ mIfaceTable.Init(100);
+
+ PRUint32 size = NS_ARRAY_LENGTH(kJavaKeywords);
+ mJavaKeywords.Init(size);
+ for (PRUint32 i = 0; i < size; i++) {
+ mJavaKeywords.Put(nsDependentCString(kJavaKeywords[i]));
+ }
+
+#ifdef WRITE_NOSCRIPT_METHODS
+ size = NS_ARRAY_LENGTH(kNoscriptMethodIfaces);
+ mNoscriptMethodsTable.Init(size);
+ for (PRUint32 j = 0; j < size; j++) {
+ mNoscriptMethodsTable.Put(nsDependentCString(kNoscriptMethodIfaces[j]));
+ }
+#endif
+ }
+
+ ~Generate()
+ {
+ }
+
+ nsresult GenerateInterfaces()
+ {
+ nsresult rv;
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim =
+ getter_AddRefs(XPTI_GetInterfaceInfoManager());
+ NS_ASSERTION(iim, "could not get interface info manager");
+ nsCOMPtr<nsIEnumerator> etor;
+ rv = iim->EnumerateInterfaces(getter_AddRefs(etor));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // loop over interfaces
+ etor->First();
+ do {
+ // get current interface
+ nsCOMPtr<nsISupports> item;
+ rv = etor->CurrentItem(getter_AddRefs(item));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(item));
+ if (!iface)
+ break;
+
+ // we only care about scriptable interfaces, so skip over those
+ // that aren't
+ PRBool scriptable;
+ iface->IsScriptable(&scriptable);
+ if (!scriptable) {
+ // XXX SWT uses non-scriptable interface 'nsIAppShell' (bug 270892), so
+ // include that one.
+ const char* iface_name;
+ iface->GetNameShared(&iface_name);
+ if (strcmp("nsIAppShell", iface_name) != 0)
+ continue;
+ }
+
+ rv = WriteOneInterface(iface);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ } while (NS_SUCCEEDED(etor->Next()));
+
+ return NS_OK;
+ }
+
+ nsresult WriteOneInterface(nsIInterfaceInfo* aIInfo)
+ {
+ nsresult rv;
+
+ // write each interface only once
+ const char* iface_name;
+ aIInfo->GetNameShared(&iface_name);
+ if (mIfaceTable.Contains(nsDependentCString(iface_name)))
+ return NS_OK;
+
+ // write any parent interface
+ nsCOMPtr<nsIInterfaceInfo> parentInfo;
+ PRUint16 parentMethodCount, parentConstCount;
+ rv = TypeInfo::GetParentInfo(aIInfo, getter_AddRefs(parentInfo),
+ &parentMethodCount, &parentConstCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (parentInfo)
+ WriteOneInterface(parentInfo);
+
+ mIfaceTable.Put(nsDependentCString(iface_name));
+
+ // create file for interface
+ nsCOMPtr<nsIOutputStream> out;
+ rv = OpenIfaceFileStream(iface_name, getter_AddRefs(out));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // write contents to file
+ rv = WriteHeader(out, iface_name);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = WriteInterfaceStart(out, aIInfo, parentInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = WriteIID(out, aIInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = WriteConstants(out, aIInfo, parentConstCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = WriteMethods(out, aIInfo, parentMethodCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = WriteInterfaceEnd(out);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = CloseIfaceFileStream(out);
+
+ return rv;
+ }
+
+ nsresult OpenIfaceFileStream(const char* aIfaceName,
+ nsIOutputStream** aResult)
+ {
+ nsresult rv;
+
+ // create interface file in output dir
+ nsCOMPtr<nsIFile> iface_file;
+ rv = mOutputDir->Clone(getter_AddRefs(iface_file));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsAutoString filename;
+ filename.AppendASCII(aIfaceName);
+ filename.AppendLiteral(".java");
+ rv = iface_file->Append(filename);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // create interface file
+ PRBool exists;
+ iface_file->Exists(&exists);
+ if (exists)
+ iface_file->Remove(PR_FALSE);
+ rv = iface_file->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // create output stream for writing to file
+ nsCOMPtr<nsIOutputStream> out;
+ rv = NS_NewLocalFileOutputStream(getter_AddRefs(out), iface_file);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aResult = out;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+ }
+
+ nsresult CloseIfaceFileStream(nsIOutputStream* out)
+ {
+ return out->Close();
+ }
+
+ nsresult WriteHeader(nsIOutputStream* out, const char* aIfaceName)
+ {
+ static const char kHeader1[] =
+ "/**\n"
+ " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n"
+ " * FOR THE FULL DOCUMENTION AND LICENSE.\n"
+ " *\n"
+ " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=";
+ static const char kHeader2[]= "\">\n **/\n\n";
+ static const char kPackage[] = "package org.mozilla.interfaces;\n\n";
+
+ PRUint32 count;
+ nsresult rv = out->Write(kHeader1, sizeof(kHeader1) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCAutoString searchTerm;
+ searchTerm.AppendLiteral("interface+");
+ searchTerm.AppendASCII(aIfaceName);
+ // LXR limits to 29 chars
+ rv = out->Write(searchTerm.get(), PR_MIN(29, searchTerm.Length()), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = out->Write(kHeader2, sizeof(kHeader2) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(kPackage, sizeof(kPackage) - 1, &count);
+ return rv;
+ }
+
+ nsresult WriteInterfaceStart(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
+ nsIInterfaceInfo* aParentInfo)
+ {
+ static const char kIfaceDecl1[] = "public interface ";
+ static const char kParentDecl[] = " extends ";
+ static const char kIfaceDecl2[] = "\n{\n";
+
+ const char* iface_name;
+ aIInfo->GetNameShared(&iface_name);
+ PRUint32 count;
+ nsresult rv = out->Write(kIfaceDecl1, sizeof(kIfaceDecl1) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(iface_name, strlen(iface_name), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aParentInfo) {
+ const char* parent_name;
+ aParentInfo->GetNameShared(&parent_name);
+ rv = out->Write(kParentDecl, sizeof(kParentDecl) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(parent_name, strlen(parent_name), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = out->Write(kIfaceDecl2, sizeof(kIfaceDecl2) - 1, &count);
+ return rv;
+ }
+
+ nsresult WriteInterfaceEnd(nsIOutputStream* out)
+ {
+ PRUint32 count;
+ return out->Write("}\n", 2, &count);
+ }
+
+ nsresult WriteIID(nsIOutputStream* out, nsIInterfaceInfo* aIInfo)
+ {
+ static const char kIIDDecl1[] = " public static final String ";
+ static const char kIIDDecl2[] = " =\n \"";
+ static const char kIIDDecl3[] = "\";\n\n";
+
+ nsIID* iid = nsnull;
+ aIInfo->GetInterfaceIID(&iid);
+ if (!iid)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // create iid field name
+ nsCAutoString iid_name;
+ const char* iface_name;
+ aIInfo->GetNameShared(&iface_name);
+ if (strncmp("ns", iface_name, 2) == 0) {
+ iid_name.AppendLiteral("NS_");
+ iid_name.Append(iface_name + 2);
+ } else {
+ iid_name.Append(iface_name);
+ }
+ iid_name.AppendLiteral("_IID");
+ ToUpperCase(iid_name);
+
+ // get iid string
+ char* iid_str = iid->ToString();
+ if (!iid_str)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32 count;
+ nsresult rv = out->Write(kIIDDecl1, sizeof(kIIDDecl1) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(iid_name.get(), iid_name.Length(), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(kIIDDecl2, sizeof(kIIDDecl2) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(iid_str, strlen(iid_str), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(kIIDDecl3, sizeof(kIIDDecl3) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // cleanup
+ PR_Free(iid_str);
+ nsMemory::Free(iid);
+ return NS_OK;
+ }
+
+ nsresult WriteConstants(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
+ PRUint16 aParentConstCount)
+ {
+ static const char kConstDecl1[] = " public static final ";
+ static const char kConstDecl2[] = " = ";
+ static const char kConstDecl3[] = ";\n\n";
+
+ PRUint16 constCount;
+ nsresult rv = aIInfo->GetConstantCount(&constCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ for (PRUint16 i = aParentConstCount; i < constCount; i++) {
+ const nsXPTConstant* constInfo;
+ rv = aIInfo->GetConstant(i, &constInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRUint32 count;
+ rv = out->Write(kConstDecl1, sizeof(kConstDecl1) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ const nsXPTType &type = constInfo->GetType();
+ rv = WriteType(out, &type, aIInfo, nsnull, nsnull);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(" ", 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ const char* name = constInfo->GetName();
+ rv = out->Write(name, strlen(name), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(kConstDecl2, sizeof(kConstDecl2) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = WriteConstantValue(out, &type, constInfo->GetValue());
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(kConstDecl3, sizeof(kConstDecl3) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+ }
+
+ nsresult WriteConstantValue(nsIOutputStream* out, const nsXPTType* aType,
+ const nsXPTCMiniVariant* aValue)
+ {
+ char buf[32];
+ switch (aType->TagPart()) {
+ case nsXPTType::T_I8:
+ snprintf(buf, sizeof(buf), "%d", aValue->val.i8);
+ break;
+
+ case nsXPTType::T_U8:
+ snprintf(buf, sizeof(buf), "%u", aValue->val.u8);
+ break;
+
+ case nsXPTType::T_I16:
+ snprintf(buf, sizeof(buf), "%d", aValue->val.i16);
+ break;
+
+ case nsXPTType::T_U16:
+ snprintf(buf, sizeof(buf), "%u", aValue->val.u16);
+ break;
+
+ case nsXPTType::T_I32:
+ snprintf(buf, sizeof(buf), "%d", aValue->val.i32);
+ break;
+
+ case nsXPTType::T_U32:
+ snprintf(buf, sizeof(buf), "%uL", aValue->val.u32);
+ break;
+
+ case nsXPTType::T_I64:
+ snprintf(buf, sizeof(buf), "%lldL", aValue->val.i64);
+ break;
+
+ case nsXPTType::T_U64:
+ snprintf(buf, sizeof(buf), "%lluL", aValue->val.u64);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ snprintf(buf, sizeof(buf), "%f", aValue->val.f);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ snprintf(buf, sizeof(buf), "%f", aValue->val.d);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (aValue->val.b)
+ sprintf(buf, "true");
+ else
+ sprintf(buf, "false");
+ break;
+
+ case nsXPTType::T_CHAR:
+ snprintf(buf, sizeof(buf), "%c", aValue->val.c);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ snprintf(buf, sizeof(buf), "%c", aValue->val.wc);
+ break;
+
+ default:
+ NS_WARNING("unexpected constant type");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ PRUint32 count;
+ return out->Write(buf, strlen(buf), &count);
+ }
+
+ nsresult WriteMethods(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
+ PRUint16 aParentMethodCount)
+ {
+ PRUint16 methodCount;
+ nsresult rv = aIInfo->GetMethodCount(&methodCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#ifdef DEBUG_bird /* attributes first, then method. For making diffing easier. */
+ for (int pass = 0; pass < 2; pass++)
+#endif
+ for (PRUint16 i = aParentMethodCount; i < methodCount; i++) {
+ const nsXPTMethodInfo* methodInfo;
+ rv = aIInfo->GetMethodInfo(i, &methodInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#ifdef WRITE_NOSCRIPT_METHODS
+ // XXX
+ // SWT makes use of [noscript] methods in some classes, so output them
+ // for those classes.
+
+ // skip [notxpcom] methods
+ if (methodInfo->IsNotXPCOM())
+ continue;
+
+ // skip most hidden ([noscript]) methods
+ if (methodInfo->IsHidden()) {
+ const char* iface_name;
+ aIInfo->GetNameShared(&iface_name);
+ if (!mNoscriptMethodsTable.Contains(nsDependentCString(iface_name)))
+ continue;
+ }
+#else
+ // skip hidden ([noscript]) or [notxpcom] methods
+ if (methodInfo->IsHidden() || methodInfo->IsNotXPCOM())
+ continue;
+#endif
+#ifdef DEBUG_bird /* attributes first, then method. For making diffing easier. */
+ if ((methodInfo->IsSetter() || methodInfo->IsGetter()) == pass)
+ continue;
+#endif
+
+ rv = WriteOneMethod(out, aIInfo, methodInfo, i);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+ }
+
+ nsresult WriteOneMethod(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
+ const nsXPTMethodInfo* aMethodInfo,
+ PRUint16 aMethodIndex)
+ {
+ static const char kMethodDecl1[] = " public ";
+ static const char kVoidReturn[] = "void";
+ static const char kParamSeparator[] = ", ";
+ static const char kMethodDecl2[] = ");\n\n";
+
+ PRUint32 count;
+ nsresult rv = out->Write(kMethodDecl1, sizeof(kMethodDecl1) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // write return type
+ PRUint8 paramCount = aMethodInfo->GetParamCount();
+ const nsXPTParamInfo* resultInfo = nsnull;
+ for (PRUint8 i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo &paramInfo = aMethodInfo->GetParam(i);
+ if (paramInfo.IsRetval()) {
+ resultInfo = &paramInfo;
+ break;
+ }
+ }
+ if (resultInfo) {
+ rv = WriteParam(out, aIInfo, aMethodIndex, resultInfo, 0);
+ } else {
+ rv = out->Write(kVoidReturn, sizeof(kVoidReturn) - 1, &count);
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // write method name string
+ nsCAutoString method_name;
+ const char* name = aMethodInfo->GetName();
+ if (aMethodInfo->IsGetter() || aMethodInfo->IsSetter()) {
+ if (aMethodInfo->IsGetter())
+ method_name.AppendLiteral("get");
+ else
+ method_name.AppendLiteral("set");
+ method_name.Append(toupper(name[0]));
+ method_name.AppendASCII(name + 1);
+ } else {
+ method_name.Append(tolower(name[0]));
+ method_name.AppendASCII(name + 1);
+ // don't use Java keywords as method names
+ if (mJavaKeywords.Contains(method_name))
+ method_name.Append('_');
+ }
+ rv = out->Write(" ", 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write(method_name.get(), method_name.Length(), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = out->Write("(", 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // write parameters
+ for (PRUint8 j = 0; j < paramCount; j++) {
+ const nsXPTParamInfo &paramInfo = aMethodInfo->GetParam(j);
+ if (paramInfo.IsRetval())
+ continue;
+
+ if (j != 0) {
+ rv = out->Write(kParamSeparator, sizeof(kParamSeparator) - 1, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = WriteParam(out, aIInfo, aMethodIndex, &paramInfo, j + 1);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ rv = out->Write(kMethodDecl2, sizeof(kMethodDecl2) - 1, &count);
+ return rv;
+ }
+
+ nsresult WriteParam(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
+ PRUint16 aMethodIndex, const nsXPTParamInfo* aParamInfo,
+ PRUint8 aIndex)
+ {
+ const nsXPTType &type = aParamInfo->GetType();
+ nsresult rv = WriteType(out, &type, aIInfo, aMethodIndex, aParamInfo);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // if parameter is 'out' or 'inout', make it a Java array
+ PRUint32 count;
+ if (aParamInfo->IsOut() && !aParamInfo->IsRetval()) {
+ rv = out->Write("[]", 2, &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // write name for parameter (but not for 'retval' param)
+ if (aIndex) {
+ char buf[10];
+ snprintf(buf, sizeof(buf), " arg%d", aIndex);
+ rv = out->Write(buf, strlen(buf), &count);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ return NS_OK;
+ }
+
+ /**
+ * Write out the Java type for the given XPIDL type.
+ *
+ * NOTE: Java doesn't support unsigned types. So for any unsigned XPIDL type,
+ * we move up to the next largest Java type. This way we ensure that we don't
+ * lose any info.
+ */
+ nsresult WriteType(nsIOutputStream* out, const nsXPTType* aType,
+ nsIInterfaceInfo* aIInfo, PRUint16 aMethodIndex,
+ const nsXPTParamInfo* aParamInfo)
+ {
+ nsresult rv;
+ PRUint32 count;
+ switch (aType->TagPart()) {
+ case nsXPTType::T_I8:
+ rv = out->Write("byte", 4, &count);
+ break;
+
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U8:
+ rv = out->Write("short", 5, &count);
+ break;
+
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U16:
+ rv = out->Write("int", 3, &count);
+ break;
+
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U32:
+ rv = out->Write("long", 4, &count);
+ break;
+
+ case nsXPTType::T_FLOAT:
+ rv = out->Write("float", 5, &count);
+ break;
+
+ // XXX how should we handle 64-bit values?
+ case nsXPTType::T_U64:
+ case nsXPTType::T_DOUBLE:
+ rv = out->Write("double", 6, &count);
+ break;
+
+ case nsXPTType::T_BOOL:
+ rv = out->Write("boolean", 7, &count);
+ break;
+
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ rv = out->Write("char", 4, &count);
+ break;
+
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_IID:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ rv = out->Write("String", 6, &count);
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ {
+ char* iface_name = nsnull;
+ rv = TypeInfo::GetInterfaceName(aIInfo, aMethodIndex, aParamInfo,
+ &iface_name);
+ if (NS_FAILED(rv) || !iface_name) {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ rv = out->Write(iface_name, strlen(iface_name), &count);
+ nsMemory::Free(iface_name);
+ break;
+ }
+
+ case nsXPTType::T_INTERFACE_IS:
+ rv = out->Write("nsISupports", 11, &count);
+ break;
+
+ case nsXPTType::T_VOID:
+ rv = out->Write("int", 3, &count);
+ break;
+
+ case nsXPTType::T_ARRAY:
+ {
+ // get array type
+ nsXPTType xpttype;
+ rv = aIInfo->GetTypeForParam(aMethodIndex, aParamInfo, 1, &xpttype);
+ if (NS_FAILED(rv))
+ break;
+
+ rv = WriteType(out, &xpttype, aIInfo, aMethodIndex, aParamInfo);
+ if (NS_FAILED(rv))
+ break;
+
+ rv = out->Write("[]", 2, &count);
+ break;
+ }
+
+ default:
+ fprintf(stderr, "WARNING: unexpected parameter type %d\n",
+ aType->TagPart());
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return rv;
+ }
+};
+
+void PrintUsage(char** argv)
+{
+ static const char usage_str[] =
+ "Usage: %s -d path\n"
+ " -d output directory for Java interface files\n";
+ fprintf(stderr, usage_str, argv[0]);
+}
+#ifdef VBOX
+#include <VBox/com/com.h>
+using namespace com;
+
+#include <iprt/initterm.h>
+#include <iprt/string.h>
+#include <iprt/alloca.h>
+#include <iprt/stream.h>
+#endif
+
+int main(int argc, char** argv)
+{
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsILocalFile> output_dir;
+
+#ifdef VBOX
+#if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
+ rv = RTR3InitExe(argc, &argv, 0);
+#else
+ const char *pszHome = getenv("VBOX_PROGRAM_PATH");
+ if (pszHome) {
+ size_t cchHome = strlen(pszHome);
+ char *pszExePath = (char *)alloca(cchHome + 32);
+ memcpy(pszExePath, pszHome, cchHome);
+ memcpy(pszExePath + cchHome, "/pythonfake", sizeof("/pythonfake"));
+ rc = RTR3InitEx(RTR3INIT_VER_CUR, 0, argc, &argv, pszExePath);
+ } else {
+ rv = RTR3InitExe(argc, &argv, 0);
+ }
+#endif
+#endif
+
+ // handle command line arguments
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ switch (argv[i][1]) {
+ case 'd': {
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing output directory after -d\n");
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ // see if given path exists
+ rv = NS_NewNativeLocalFile(nsDependentCString(argv[++i]), PR_TRUE,
+ getter_AddRefs(output_dir));
+ PRBool val;
+ if (NS_FAILED(rv) || NS_FAILED(output_dir->Exists(&val)) || !val ||
+ NS_FAILED(output_dir->IsDirectory(&val)) || !val)
+ {
+ fprintf(stderr,
+ "ERROR: output directory doesn't exist / isn't a directory\n");
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ break;
+ }
+
+ default: {
+ fprintf(stderr, "ERROR: unknown option %s\n", argv[i]);
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ }
+ }
+
+ if (NS_FAILED(rv)) {
+ PrintUsage(argv);
+ return 1;
+ }
+
+#ifdef VBOX
+ rv = com::Initialize();
+#else
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+#endif
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ Generate gen(output_dir);
+ rv = gen.GenerateInterfaces();
+
+#ifdef VBOX
+ // very short-living XPCOM processes trigger problem on shutdown - ignoring it not a big deal anyway
+ //com::Shutdown();
+#else
+ NS_ShutdownXPCOM(nsnull);
+#endif
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/java/tools/genjifaces.xsl b/src/libs/xpcom18a4/java/tools/genjifaces.xsl
new file mode 100644
index 00000000..7e754222
--- /dev/null
+++ b/src/libs/xpcom18a4/java/tools/genjifaces.xsl
@@ -0,0 +1,600 @@
+<xsl:stylesheet version = '1.0'
+ xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+ xmlns:vbox="http://www.virtualbox.org/"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<!--
+ genjifaces.xsl:
+ XSLT stylesheet that generates Java XPCOM bridge interface code from VirtualBox.xidl.
+-->
+<!--
+ Copyright (C) 2010-2023 Oracle and/or its affiliates.
+
+ This file is part of VirtualBox base platform packages, as
+ available from https://www.virtualbox.org.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation, in version 3 of the
+ License.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <https://www.gnu.org/licenses>.
+
+ SPDX-License-Identifier: GPL-3.0-only
+-->
+
+<xsl:output
+ method="text"
+ version="1.0"
+ encoding="utf-8"
+ indent="no"/>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - -
+ global XSLT variables
+ - - - - - - - - - - - - - - - - - - - - - - -->
+
+<xsl:variable name="G_xsltFilename" select="'genjifaces.xsl'" />
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - -
+ Keys for more efficiently looking up of types.
+- - - - - - - - - - - - - - - - - - - - - - -->
+<xsl:key name="G_keyEnumsByName" match="//enum[@name]" use="@name"/>
+<xsl:key name="G_keyInterfacesByName" match="//interface[@name]" use="@name"/>
+
+<!--
+ xsltprocNewlineOutputHack - emits a single new line.
+
+ Hack Alert! This template helps xsltproc split up the output text elements
+ and avoid reallocating them into the MB range. Calls to this
+ template is made occationally while generating larger output
+ file. It's not necessary for small stuff like header.
+
+ The trick we're playing on xsltproc has to do with CDATA
+ and/or the escape setting of the xsl:text element. It forces
+ xsltproc to allocate a new output element, thus preventing
+ things from growing out of proportions and slowing us down.
+
+ This was successfully employed to reduce a 18+ seconds run to
+ around one second (possibly less due to kmk overhead).
+ -->
+<xsl:template name="xsltprocNewlineOutputHack">
+ <xsl:text disable-output-escaping="yes"><![CDATA[
+]]></xsl:text>
+</xsl:template>
+
+<xsl:template name="uppercase">
+ <xsl:param name="str" select="."/>
+ <xsl:value-of select="translate($str, 'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
+</xsl:template>
+
+<xsl:template name="capitalize">
+ <xsl:param name="str" select="."/>
+ <xsl:value-of select="
+ concat(translate(substring($str,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+ substring($str,2))"/>
+</xsl:template>
+
+<xsl:template name="makeGetterName">
+ <xsl:param name="attrname" />
+ <xsl:variable name="capsname">
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="$attrname" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('get', $capsname)" />
+</xsl:template>
+
+<xsl:template name="makeSetterName">
+ <xsl:param name="attrname" />
+ <xsl:variable name="capsname">
+ <xsl:call-template name="capitalize">
+ <xsl:with-param name="str" select="$attrname" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('set', $capsname)" />
+</xsl:template>
+
+<xsl:template name="fileheader">
+ <xsl:param name="name" />
+ <xsl:text>/** @file
+</xsl:text>
+ <xsl:value-of select="concat(' * ',$name)"/>
+<xsl:text>
+ *
+ * DO NOT EDIT! This is a generated file.
+ * Generated from: src/VBox/Main/idl/VirtualBox.xidl (VirtualBox's interface definitions in XML)
+ * Generator: src/VBox/src/libs/xpcom18a4/java/tools/genjifaces.xsl
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see &lt;https://www.gnu.org/licenses&gt;.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+</xsl:text>
+</xsl:template>
+
+<xsl:template name="startFile">
+ <xsl:param name="file" />
+
+ <xsl:value-of select="concat('&#10;// ##### BEGINFILE &quot;', $file, '&quot;&#10;&#10;')" />
+ <xsl:call-template name="fileheader">
+ <xsl:with-param name="name" select="$file" />
+ </xsl:call-template>
+
+ <xsl:value-of select=" 'package org.mozilla.interfaces;&#10;&#10;'" />
+</xsl:template>
+
+<xsl:template name="endFile">
+ <xsl:param name="file" />
+ <xsl:value-of select="concat('&#10;// ##### ENDFILE &quot;', $file, '&quot;&#10;')" />
+ <xsl:call-template name="xsltprocNewlineOutputHack"/>
+</xsl:template>
+
+
+<xsl:template name="emitHandwritten">
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsISupports.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsISupports
+{
+ public static final String NS_ISUPPORTS_IID =
+ "{00000000-0000-0000-c000-000000000046}";
+
+ public nsISupports queryInterface(String arg1);
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsISupports.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIComponentManager.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIComponentManager extends nsISupports
+{
+ public static final String NS_ICOMPONENTMANAGER_IID =
+ "{a88e5a60-205a-4bb1-94e1-2628daf51eae}";
+
+ public nsISupports getClassObject(String arg1, String arg2);
+
+ public nsISupports getClassObjectByContractID(String arg1, String arg2);
+
+ public nsISupports createInstance(String arg1, nsISupports arg2, String arg3);
+
+ public nsISupports createInstanceByContractID(String arg1, nsISupports arg2, String arg3);
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsIComponentManager.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIServiceManager.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIServiceManager extends nsISupports
+{
+ public static final String NS_ISERVICEMANAGER_IID =
+ "{8bb35ed9-e332-462d-9155-4a002ab5c958}";
+
+ public nsISupports getService(String arg1, String arg2);
+
+ public nsISupports getServiceByContractID(String arg1, String arg2);
+
+ public boolean isServiceInstantiated(String arg1, String arg2);
+
+ public boolean isServiceInstantiatedByContractID(String arg1, String arg2);
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsIServiceManager.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIExceptionManager.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIExceptionManager extends nsISupports
+{
+ public static final String NS_IEXCEPTIONMANAGER_IID =
+ "{efc9d00b-231c-4feb-852c-ac017266a415}";
+
+ public nsIException getCurrentException();
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsISupports.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIExceptionService.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIExceptionService extends nsIExceptionManager
+{
+ public static final String NS_IEXCEPTIONSERVICE_IID =
+ "{35a88f54-f267-4414-92a7-191f6454ab52}";
+
+ public nsIExceptionManager getCurrentExceptionManager();
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsISupports.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIException.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIException extends nsISupports
+{
+ public static final String NS_IEXCEPTION_IID =
+ "{f3a8d3b4-c424-4edc-8bf6-8974c983ba78}";
+
+ // No methods - placeholder
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsISupports.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIComponentRegistrar.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIComponentRegistrar extends nsISupports
+{
+ public static final String NS_ICOMPONENTREGISTRAR_IID =
+ "{2417cbfe-65ad-48a6-b4b6-eb84db174392}";
+
+ // No methods - placeholder
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsIComponentRegistrar.java'" />
+ </xsl:call-template>
+
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsIFile.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsIFile extends nsISupports
+{
+ public static final String NS_IFILE_IID =
+ "{c8c0a080-0868-11d3-915f-d9d889d48e3c}";
+
+ // No methods - placeholder
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsIFile.java'" />
+ </xsl:call-template>
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="'nsILocalFile.java'" />
+ </xsl:call-template>
+
+ <xsl:text><![CDATA[
+public interface nsILocalFile extends nsIFile
+{
+ public static final String NS_ILOCALFILE_IID =
+ "{aa610f20-a889-11d3-8c81-000064657374}";
+
+ // No methods - placeholder
+}
+]]></xsl:text>
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="'nsILocalFile.java'" />
+ </xsl:call-template>
+
+</xsl:template>
+
+<xsl:template name="genEnum">
+ <xsl:param name="enumname" />
+ <xsl:param name="filename" />
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="$filename" />
+ </xsl:call-template>
+
+ <xsl:value-of select="concat('public interface ', $enumname, ' {&#10;&#10;')" />
+
+ <xsl:variable name="uppername">
+ <xsl:call-template name="uppercase">
+ <xsl:with-param name="str" select="$enumname" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:value-of select="concat(' public static final String ', $uppername, '_IID = &#10;',
+ ' &quot;{',@uuid, '}&quot;;&#10;&#10;')" />
+
+ <xsl:for-each select="const">
+ <xsl:variable name="enumconst" select="@name" />
+ <xsl:value-of select="concat(' public static final long ', @name, ' = ', @value, 'L;&#10;&#10;')" />
+ </xsl:for-each>
+
+ <xsl:value-of select="'}&#10;&#10;'" />
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="$filename" />
+ </xsl:call-template>
+
+</xsl:template>
+
+<xsl:template name="typeIdl2Back">
+ <xsl:param name="type" />
+ <xsl:param name="safearray" />
+ <xsl:param name="forceelem" />
+
+ <xsl:variable name="needarray" select="($safearray='yes') and not($forceelem='yes')" />
+
+ <xsl:choose>
+ <xsl:when test="$type='unsigned long long'">
+ <!-- stupid, rewrite the bridge -->
+ <xsl:value-of select="'double'" />
+ </xsl:when>
+
+ <xsl:when test="$type='long long'">
+ <xsl:value-of select="'long'" />
+ </xsl:when>
+
+ <xsl:when test="$type='unsigned long'">
+ <xsl:value-of select="'long'" />
+ </xsl:when>
+
+ <xsl:when test="$type='long'">
+ <xsl:value-of select="'int'" />
+ </xsl:when>
+
+ <xsl:when test="$type='unsigned short'">
+ <xsl:value-of select="'int'" />
+ </xsl:when>
+
+ <xsl:when test="$type='short'">
+ <xsl:value-of select="'short'" />
+ </xsl:when>
+
+ <xsl:when test="$type='octet'">
+ <xsl:value-of select="'byte'" />
+ </xsl:when>
+
+ <xsl:when test="$type='boolean'">
+ <xsl:value-of select="'boolean'" />
+ </xsl:when>
+
+ <xsl:when test="$type='$unknown'">
+ <xsl:value-of select="'nsISupports'"/>
+ </xsl:when>
+
+ <xsl:when test="$type='wstring'">
+ <xsl:value-of select="'String'" />
+ </xsl:when>
+
+ <xsl:when test="$type='uuid'">
+ <xsl:value-of select="'String'" />
+ </xsl:when>
+
+ <xsl:when test="count(key('G_keyInterfacesByName', $type)) > 0">
+ <xsl:value-of select="$type" />
+ </xsl:when>
+
+ <xsl:when test="count(key('G_keyEnumsByName', $type)) > 0">
+ <xsl:value-of select="'long'" />
+ </xsl:when>
+
+ </xsl:choose>
+
+ <xsl:if test="$needarray">
+ <xsl:value-of select="'[]'" />
+ </xsl:if>
+
+</xsl:template>
+
+<xsl:template name="genIface">
+ <xsl:param name="ifname" />
+ <xsl:param name="filename" />
+
+ <xsl:call-template name="startFile">
+ <xsl:with-param name="file" select="$filename" />
+ </xsl:call-template>
+
+ <xsl:variable name="extendsidl" select="key('G_keyInterfacesByName', $ifname)/@extends" />
+
+ <xsl:variable name="extends">
+ <xsl:choose>
+ <xsl:when test="($extendsidl = '$unknown') or ($extendsidl = '$dispatched') or ($extendsidl = '$errorinfo')">
+ <xsl:value-of select="'nsISupports'" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$extendsidl" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="concat('public interface ', $ifname, ' extends ', $extends, ' {&#10;&#10;')" />
+
+ <xsl:variable name="uppername">
+ <xsl:call-template name="uppercase">
+ <xsl:with-param name="str" select="$ifname" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:value-of select="concat(' public static final String ', $uppername, '_IID =&#10;',
+ ' &quot;{',@uuid, '}&quot;;&#10;&#10;')" />
+
+ <xsl:for-each select="attribute">
+ <xsl:variable name="attrname" select="@name" />
+ <xsl:variable name="attrtype" select="@type" />
+
+ <xsl:variable name="gettername">
+ <xsl:call-template name="makeGetterName">
+ <xsl:with-param name="attrname" select="$attrname" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="backtype">
+ <xsl:call-template name="typeIdl2Back">
+ <xsl:with-param name="type" select="$attrtype" />
+ <xsl:with-param name="safearray" select="@safearray" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="callparam">
+ <xsl:if test="@safearray='yes'">
+ <xsl:value-of select="concat(' long[] ', @name, 'Size')" />
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:value-of select="concat(' public ', $backtype, ' ', $gettername, '(',$callparam,');&#10;&#10;')" />
+
+ <xsl:if test="not(@readonly='yes')">
+ <xsl:variable name="settername">
+ <xsl:call-template name="makeSetterName">
+ <xsl:with-param name="attrname" select="$attrname" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat(' public void ', $settername, '(', $backtype, ' arg1);&#10;&#10;')" />
+ </xsl:if>
+
+ </xsl:for-each>
+
+ <xsl:for-each select="method">
+ <xsl:variable name="methodname" select="@name" />
+ <xsl:variable name="returnidltype" select="param[@dir='return']/@type" />
+ <xsl:variable name="returnidlsafearray" select="param[@dir='return']/@safearray" />
+
+ <xsl:variable name="returntype">
+ <xsl:choose>
+ <xsl:when test="$returnidltype">
+ <xsl:call-template name="typeIdl2Back">
+ <xsl:with-param name="type" select="$returnidltype" />
+ <xsl:with-param name="safearray" select="$returnidlsafearray" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>void</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:value-of select="concat(' public ', $returntype, ' ', $methodname, '(')" />
+ <xsl:for-each select="param">
+ <xsl:variable name="paramtype">
+ <xsl:call-template name="typeIdl2Back">
+ <xsl:with-param name="type" select="@type" />
+ <xsl:with-param name="safearray" select="@safearray" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="(@safearray='yes') and (@dir='return')">
+ <xsl:value-of select="concat('long[] ', @name)" />
+ </xsl:when>
+ <xsl:when test="(@safearray='yes') and (@dir='out')">
+ <xsl:value-of select="concat('long[] ', @name, 'Size, ', $paramtype, '[] ', @name)" />
+ </xsl:when>
+ <xsl:when test="(@safearray='yes') and (@dir='in') and (@type='octet')">
+ <xsl:value-of select="concat($paramtype, ' ', @name)" />
+ </xsl:when>
+ <xsl:when test="(@safearray='yes') and (@dir='in')">
+ <xsl:value-of select="concat('long ', @name, 'Size, ', $paramtype, ' ', @name)" />
+ </xsl:when>
+ <xsl:when test="@dir='out'">
+ <xsl:value-of select="concat($paramtype, '[] ', @name)" />
+ </xsl:when>
+ <xsl:when test="@dir='in'">
+ <xsl:value-of select="concat($paramtype, ' ', @name)" />
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="not(position()=last()) and not(following-sibling::param[1]/@dir='return' and not(following-sibling::param[1]/@safearray='yes'))">
+ <xsl:value-of select="', '" />
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:value-of select=" ');&#10;&#10;'" />
+
+ </xsl:for-each>
+
+ <xsl:value-of select="'}&#10;&#10;'" />
+
+ <xsl:call-template name="endFile">
+ <xsl:with-param name="file" select="$filename" />
+ </xsl:call-template>
+
+</xsl:template>
+
+
+<xsl:template match="/">
+
+ <!-- Handwritten files -->
+ <xsl:call-template name="emitHandwritten"/>
+
+ <!-- Enums -->
+ <xsl:for-each select="//enum">
+ <xsl:call-template name="genEnum">
+ <xsl:with-param name="enumname" select="@name" />
+ <xsl:with-param name="filename" select="concat(@name, '.java')" />
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <!-- Interfaces -->
+ <xsl:for-each select="//interface">
+ <xsl:variable name="self_target" select="current()/ancestor::if/@target"/>
+ <xsl:variable name="module" select="current()/ancestor::module/@name"/>
+
+ <!-- We don't need WSDL-specific nor MIDL-specific interfaces here -->
+ <xsl:if test="not($self_target='wsdl') and not($self_target='midl') and not($module)">
+ <xsl:call-template name="genIface">
+ <xsl:with-param name="ifname" select="@name" />
+ <xsl:with-param name="filename" select="concat(@name, '.java')" />
+ </xsl:call-template>
+ </xsl:if>
+
+ </xsl:for-each>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/libs/xpcom18a4/nsBuildID.h b/src/libs/xpcom18a4/nsBuildID.h
new file mode 100644
index 00000000..4f674d9d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsBuildID.h
@@ -0,0 +1,23 @@
+#ifndef _NSBUILDID_H_
+#define _NSBUILDID_H_
+/* Build ID file.
+*
+* If building MOZILLLA_OFFICIAL (release build) NS_BUILD_ID will be updated
+* to a current build id. This will be used to determine if we need to
+* re-register components.
+*
+*/
+#define NS_BUILD_ID 0000000000
+
+/* GRE_BUILD_ID - GRE build version identifier
+ *
+ * If creating a release build (eg, MOZILLA_OFFICIAL is set), then
+ * GRE_BUILD_ID will be updated to contain <milestone>_<build id>.
+ * If building a milestone build (eg, MOZ_MILESTONE_RELEASE is set), then
+ * GRE_BUILD_ID will just contain <milestone>.
+ *
+ */
+#define GRE_BUILD_ID "1.8b2_0000000000"
+
+#endif /* _NSBUILDID_H_ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/Makefile.in b/src/libs/xpcom18a4/nsprpub/Makefile.in
new file mode 100644
index 00000000..9273b16d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/Makefile.in
@@ -0,0 +1,151 @@
+#! gmake
+
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+MOD_DEPTH = .
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+MAKE := $(patsubst -j%,,$(MAKE)) -j1
+
+DIRS = config pr lib
+
+ifdef MOZILLA_CLIENT
+# Make nsinstall use absolute symlinks by default for Mozilla OSX builds
+# http://bugzilla.mozilla.org/show_bug.cgi?id=193164
+ifeq ($(OS_ARCH),Darwin)
+ifndef NSDISTMODE
+NSDISTMODE=absolute_symlink
+export NSDISTMODE
+endif
+endif
+endif
+
+DIST_GARBAGE = config.cache config.log config.status
+
+all:: config.status export
+
+include $(topsrcdir)/config/rules.mk
+
+config.status:: configure
+ifeq ($(OS_ARCH),WINNT)
+ sh $(srcdir)/configure --no-create --no-recursion
+else
+ ./config.status --recheck && ./config.status
+endif
+
+#
+# The -ll option of zip converts CR LF to LF.
+#
+ifeq ($(OS_ARCH),WINNT)
+ZIP_ASCII_OPT = -ll
+endif
+
+# Delete config/autoconf.mk last because it is included by every makefile.
+distclean::
+ @echo "cd pr/tests; $(MAKE) $@"
+ @$(MAKE) -C pr/tests $@
+ rm -f config/autoconf.mk
+
+release::
+ echo $(BUILD_NUMBER) > $(RELEASE_DIR)/$(BUILD_NUMBER)/version.df
+ @if test -f imports.df; then \
+ echo "cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \
+ cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \
+ else \
+ echo "echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \
+ echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \
+ fi
+ cd $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \
+ rm -rf META-INF; mkdir META-INF; cd META-INF; \
+ echo "Manifest-Version: 1.0" > MANIFEST.MF; \
+ echo "" >> MANIFEST.MF; \
+ cd ..; rm -f mdbinary.jar; zip -r mdbinary.jar META-INF bin lib; \
+ rm -rf META-INF; \
+ cd include; \
+ rm -rf META-INF; mkdir META-INF; cd META-INF; \
+ echo "Manifest-Version: 1.0" > MANIFEST.MF; \
+ echo "" >> MANIFEST.MF; \
+ cd ..; rm -f mdheader.jar; zip $(ZIP_ASCII_OPT) -r mdheader.jar *; \
+ rm -rf META-INF
+ifeq ($(OS_ARCH),WINNT)
+ @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \
+ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
+ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)"; \
+ $(topsrcdir)/config/prmkdir.bat $(MDIST_DOS)\\$(MOD_NAME)\\$(BUILD_NUMBER); \
+ fi
+ @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); then \
+ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
+ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)"; \
+ $(topsrcdir)/config/prmkdir.bat $(MDIST_DOS)\\$(MOD_NAME)\\$(BUILD_NUMBER)\\$(RELEASE_OBJDIR_NAME); \
+ fi
+else
+ @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \
+ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
+ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)"; \
+ $(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
+ chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
+ fi
+ @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); then \
+ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
+ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)"; \
+ $(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
+ chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
+ fi
+endif
+ cd $(RELEASE_DIR)/$(BUILD_NUMBER); \
+ cp -f version.df imports.df $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \
+ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/version.df; \
+ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/imports.df; \
+ cd $(OBJDIR_NAME); \
+ cp -f mdbinary.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
+ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)/mdbinary.jar; \
+ cd include; \
+ cp -f mdheader.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \
+ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)/mdheader.jar
+
+package:
+ @echo "cd pkg; $(MAKE) publish"
+ $(MAKE) -C pkg publish
+
+depend:
+ @echo "NSPR20 has no dependencies. Skipped."
diff --git a/src/libs/xpcom18a4/nsprpub/admin/explode.pl b/src/libs/xpcom18a4/nsprpub/admin/explode.pl
new file mode 100755
index 00000000..881f21b9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/admin/explode.pl
@@ -0,0 +1,75 @@
+#!/bin/perl
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# -----------------------------------------------------------------
+#
+# explode.pl -- Unpack .jar files into bin, lib, include directories
+#
+# syntax: perl explode.pl
+#
+# Description:
+# explode.pl unpacks the .jar files created by the NSPR build
+# procedure.
+#
+# Suggested use: After copying the platform directories to
+# /s/b/c/nspr20/<release>. CD to /s/b/c/nspr20/<release> and
+# run explode.pl. This will unpack the jar files into bin, lib,
+# include directories.
+#
+# -----------------------------------------------------------------
+
+@dirs = `ls -d *.OBJ*`;
+
+foreach $dir (@dirs) {
+ chop($dir);
+ if (-l $dir) {
+ print "Skipping symbolic link $dir\n";
+ next;
+ }
+ print "Unzipping $dir/mdbinary.jar\n";
+ system ("unzip", "-o", "$dir/mdbinary.jar",
+ "-d", "$dir");
+ system ("rm", "-rf", "$dir/META-INF");
+ mkdir "$dir/include", 0755;
+ print "Unzipping $dir/mdheader.jar\n";
+ system ("unzip", "-o", "-aa",
+ "$dir/mdheader.jar",
+ "-d", "$dir/include");
+ system ("rm", "-rf", "$dir/include/META-INF");
+}
+# --- end explode.pl ----------------------------------------------
diff --git a/src/libs/xpcom18a4/nsprpub/admin/makeTargetDirs.sh b/src/libs/xpcom18a4/nsprpub/admin/makeTargetDirs.sh
new file mode 100755
index 00000000..4250ce4a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/admin/makeTargetDirs.sh
@@ -0,0 +1,79 @@
+#!/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 Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# -----------------------------------------------------------------
+# makeTargetDirs.sh -- Create target directories for building NSPR
+#
+# syntax: makeTargetDirs.sh
+#
+# Description:
+# makeTargetDirs.sh creates a set of directories intended for use
+# with NSPR's autoconf based build system.
+#
+# The enumerated directories are the same as those built for NSPR
+# 4.1.1. Adjust as needed.
+#
+# -----------------------------------------------------------------
+
+mkdir AIX4.3_64_DBG.OBJ
+mkdir AIX4.3_64_OPT.OBJ
+mkdir AIX4.3_DBG.OBJ
+mkdir AIX4.3_OPT.OBJ
+mkdir HP-UXB.11.00_64_DBG.OBJ
+mkdir HP-UXB.11.00_64_OPT.OBJ
+mkdir HP-UXB.11.00_DBG.OBJ
+mkdir HP-UXB.11.00_OPT.OBJ
+mkdir IRIX6.5_n32_PTH_DBG.OBJ
+mkdir IRIX6.5_n32_PTH_OPT.OBJ
+mkdir Linux2.2_x86_glibc_PTH_DBG.OBJ
+mkdir Linux2.2_x86_glibc_PTH_OPT.OBJ
+mkdir Linux2.4_x86_glibc_PTH_DBG.OBJ
+mkdir Linux2.4_x86_glibc_PTH_OPT.OBJ
+mkdir OSF1V4.0D_DBG.OBJ
+mkdir OSF1V4.0D_OPT.OBJ
+mkdir SunOS5.6_DBG.OBJ
+mkdir SunOS5.6_OPT.OBJ
+mkdir SunOS5.7_64_DBG.OBJ
+mkdir SunOS5.7_64_OPT.OBJ
+mkdir WIN954.0_DBG.OBJ
+mkdir WIN954.0_DBG.OBJD
+mkdir WIN954.0_OPT.OBJ
+mkdir WINNT4.0_DBG.OBJ
+mkdir WINNT4.0_DBG.OBJD
+mkdir WINNT4.0_OPT.OBJ
+# --- end makeTargetDirs.sh ---------------------------------------
diff --git a/src/libs/xpcom18a4/nsprpub/admin/repackage.sh b/src/libs/xpcom18a4/nsprpub/admin/repackage.sh
new file mode 100755
index 00000000..37ba0e16
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/admin/repackage.sh
@@ -0,0 +1,218 @@
+#! /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 Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# ------------------------------------------------------------------
+# repackage.sh -- Repackage NSPR from /s/b/c to mozilla.org format
+#
+# syntax: repackage.sh
+#
+# Description:
+# repackage.sh creates NSPR binary distributions for mozilla.org from
+# the internal binary distributions in /share/builds/components/nspr20.
+# There are reasons why we can't just push the internal binary distributions
+# to mozilla.org. External developers prefer to use the common archive
+# file format for their platforms, rather than the jar files we use internally.
+#
+# On Unix, we create a tar.gz file. On Windows, we create a zip file.
+# For example: NSPR 4.1.1, these would be nspr-4.1.1.tar.gz and nspr-4.1.1.zip.
+#
+# When unpacked, nspr-4.1.1.tar.gz or nspr-4.1.1.zip should expand to a
+# nspr-4.1.1 directory that contains three subdirectories: include, lib,
+# and bin. The header files, with the correct line endings for the
+# platform, are in nspr-4.1.1/include. The libraries are in nspr-4.1.1/lib.
+# The executable programs are in nspr-4.1.1/bin.
+#
+# Note! Files written with Gnu tar are not readable by some non-Gnu
+# versions. Sun, in particular.
+#
+#
+#
+#
+# ------------------------------------------------------------------
+
+FROMTOP=/share/builds/components/nspr20/v4.5
+TOTOP=./v4.5
+NSPRDIR=nspr-4.5
+SOURCETAG=NSPR_4_5_RTM
+
+#
+# enumerate Unix object directories on /s/b/c
+UNIX_OBJDIRS="
+AIX4.3_64_DBG.OBJ
+AIX4.3_64_OPT.OBJ
+AIX4.3_DBG.OBJ
+AIX4.3_OPT.OBJ
+HP-UXB.11.00_64_DBG.OBJ
+HP-UXB.11.00_64_OPT.OBJ
+HP-UXB.11.00_DBG.OBJ
+HP-UXB.11.00_OPT.OBJ
+IRIX6.5_n32_PTH_DBG.OBJ
+IRIX6.5_n32_PTH_OPT.OBJ
+Linux2.2_x86_glibc_PTH_DBG.OBJ
+Linux2.2_x86_glibc_PTH_OPT.OBJ
+Linux2.4_x86_glibc_PTH_DBG.OBJ
+Linux2.4_x86_glibc_PTH_OPT.OBJ
+OSF1V5.0_DBG.OBJ
+OSF1V5.0_OPT.OBJ
+SunOS5.6_DBG.OBJ
+SunOS5.6_OPT.OBJ
+SunOS5.8_64_DBG.OBJ
+SunOS5.8_64_OPT.OBJ
+SunOS5.8_DBG.OBJ
+SunOS5.8_OPT.OBJ
+"
+#
+# enumerate Windows object directories on /s/b/c
+WIN_OBJDIRS="
+WIN954.0_DBG.OBJ
+WIN954.0_DBG.OBJD
+WIN954.0_OPT.OBJ
+WINNT4.0_DBG.OBJ
+WINNT4.0_DBG.OBJD
+WINNT4.0_OPT.OBJ
+"
+
+#
+# Create the destination directory.
+#
+echo "removing directory $TOTOP"
+rm -rf $TOTOP
+echo "creating directory $TOTOP"
+mkdir -p $TOTOP
+
+#
+# Generate the tar.gz files for Unix platforms.
+#
+for OBJDIR in $UNIX_OBJDIRS; do
+ echo "removing directory $NSPRDIR"
+ rm -rf $NSPRDIR
+ echo "creating directory $NSPRDIR"
+ mkdir $NSPRDIR
+
+ echo "creating directory $NSPRDIR/include"
+ mkdir $NSPRDIR/include
+ echo "copying $FROMTOP/$OBJDIR/include"
+ cp -r $FROMTOP/$OBJDIR/include $NSPRDIR
+
+ echo "copying $FROMTOP/$OBJDIR/lib"
+ cp -r $FROMTOP/$OBJDIR/lib $NSPRDIR
+
+ echo "copying $FROMTOP/$OBJDIR/bin"
+ cp -r $FROMTOP/$OBJDIR/bin $NSPRDIR
+
+ echo "creating directory $TOTOP/$OBJDIR"
+ mkdir $TOTOP/$OBJDIR
+ echo "creating $TOTOP/$OBJDIR/$NSPRDIR.tar"
+ tar cvf $TOTOP/$OBJDIR/$NSPRDIR.tar $NSPRDIR
+ echo "gzipping $TOTOP/$OBJDIR/$NSPRDIR.tar"
+ gzip $TOTOP/$OBJDIR/$NSPRDIR.tar
+done
+
+#
+# Generate the zip files for Windows platforms.
+#
+for OBJDIR in $WIN_OBJDIRS; do
+ echo "removing directory $NSPRDIR"
+ rm -rf $NSPRDIR
+ echo "creating directory $NSPRDIR"
+ mkdir $NSPRDIR
+
+ echo "creating directory $NSPRDIR/include"
+ mkdir $NSPRDIR/include
+ echo "creating directory $NSPRDIR/include/private"
+ mkdir $NSPRDIR/include/private
+ echo "creating directory $NSPRDIR/include/obsolete"
+ mkdir $NSPRDIR/include/obsolete
+
+ # copy headers and adjust unix line-end to Windows line-end
+ # Note: Watch out for the "sed" command line.
+ # when editing the command, take care to preserve the "^M" as the literal
+ # cntl-M character! in vi, use "cntl-v cntl-m" to enter it!
+ #
+ headers=`ls $FROMTOP/$OBJDIR/include/*.h`
+ for header in $headers; do
+ sed -e 's/$/
+/g' $header > $NSPRDIR/include/`basename $header`
+ done
+ headers=`ls $FROMTOP/$OBJDIR/include/obsolete/*.h`
+ for header in $headers; do
+ sed -e 's/$/
+/g' $header > $NSPRDIR/include/obsolete/`basename $header`
+ done
+ headers=`ls $FROMTOP/$OBJDIR/include/private/*.h`
+ for header in $headers; do
+ sed -e 's/$/
+/g' $header > $NSPRDIR/include/private/`basename $header`
+ done
+
+ echo "copying $FROMTOP/$OBJDIR/lib"
+ cp -r $FROMTOP/$OBJDIR/lib $NSPRDIR
+
+ echo "copying $FROMTOP/$OBJDIR/bin"
+ cp -r $FROMTOP/$OBJDIR/bin $NSPRDIR
+
+ echo "creating directory $TOTOP/$OBJDIR"
+ mkdir $TOTOP/$OBJDIR
+ echo "creating $TOTOP/$OBJDIR/$NSPRDIR.zip"
+ zip -r $TOTOP/$OBJDIR/$NSPRDIR.zip $NSPRDIR
+done
+
+#
+# package the source from CVS
+#
+echo "Packaging source"
+echo "removing directory $NSPRDIR"
+rm -rf $NSPRDIR
+echo "creating directory $NSPRDIR"
+mkdir $NSPRDIR
+myWD=`pwd`
+cd $NSPRDIR
+echo "Pulling source from CVS with tag $SOURCETAG"
+cvs co -r $SOURCETAG mozilla/nsprpub
+cd $myWD
+mkdir $TOTOP/src
+echo "Creating source tar file: $TOTOP/src/$NSPRDIR.tar"
+tar cvf $TOTOP/src/$NSPRDIR.tar $NSPRDIR
+echo "gzip $TOTOP/src/$NSPRDIR.tar"
+gzip $TOTOP/src/$NSPRDIR.tar
+
+#
+# Remove the working directory.
+#
+echo "removing directory $NSPRDIR"
+rm -rf $NSPRDIR
+# --- end repackage.sh ---------------------------------------------
diff --git a/src/libs/xpcom18a4/nsprpub/admin/symlinks.sh b/src/libs/xpcom18a4/nsprpub/admin/symlinks.sh
new file mode 100755
index 00000000..f90582e2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/admin/symlinks.sh
@@ -0,0 +1,75 @@
+#!/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 Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# -----------------------------------------------------------------
+# symlinks.sh -- create links from NSPR builds
+#
+# syntax: symlinks.sh
+#
+# Description:
+# symlinks.sh creates some symbolic links for NSPR build targets
+# that are not actually build, but for which there are NSPR
+# binaries suitable for running on the intended target. ... got
+# that?
+#
+# Suggested use: After copying NSPR binaries to
+# /s/b/c/nspr20/<platform> run symlinks.sh to create the links
+# for all supported platforms.
+#
+# The symlinks in this script correspond to the NSPR 4.1.1
+# release. Adjust as necessary.
+#
+# -----------------------------------------------------------------
+
+ln -s SunOS5.6_DBG.OBJ SunOS5.7_DBG.OBJ
+ln -s SunOS5.6_OPT.OBJ SunOS5.7_OPT.OBJ
+
+ln -s SunOS5.6_DBG.OBJ SunOS5.8_DBG.OBJ
+ln -s SunOS5.6_OPT.OBJ SunOS5.8_OPT.OBJ
+
+ln -s SunOS5.7_64_DBG.OBJ SunOS5.8_64_DBG.OBJ
+ln -s SunOS5.7_64_OPT.OBJ SunOS5.8_64_OPT.OBJ
+
+ln -s OSF1V4.0D_DBG.OBJ OSF1V5.0_DBG.OBJ
+ln -s OSF1V4.0D_OPT.OBJ OSF1V5.0_OPT.OBJ
+
+ln -s WINNT4.0_DBG.OBJ WINNT5.0_DBG.OBJ
+ln -s WINNT4.0_DBG.OBJD WINNT5.0_DBG.OBJD
+ln -s WINNT4.0_OPT.OBJ WINNT5.0_OPT.OBJ
+# --- end symlinks.sh ---------------------------------------------
+
diff --git a/src/libs/xpcom18a4/nsprpub/config/.cvsignore b/src/libs/xpcom18a4/nsprpub/config/.cvsignore
new file mode 100644
index 00000000..bb3ee4bc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/.cvsignore
@@ -0,0 +1,11 @@
+nfspwd
+revdepth
+my_config.mk
+my_overrides.mk
+autoconf.mk
+nsprincl.mk
+nsprincl.sh
+now
+Makefile
+nsinstall
+nspr-config
diff --git a/src/libs/xpcom18a4/nsprpub/config/Makefile.in b/src/libs/xpcom18a4/nsprpub/config/Makefile.in
new file mode 100755
index 00000000..1b83ffa5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/Makefile.in
@@ -0,0 +1,149 @@
+#! gmake
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+MOD_DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+# Indicate that this directory builds build tools.
+INTERNAL_TOOLS = 1
+
+# autoconf.mk must be deleted last (from the top-level directory)
+# because it is included by every makefile.
+DIST_GARBAGE = nsprincl.mk nsprincl.sh nspr-config
+
+RELEASE_BINS = nspr-config
+
+include $(topsrcdir)/config/config.mk
+
+CSRCS = now.c
+
+# This version hasn't been ported for us; the one in mozilla/config has
+ifneq ($(OS_ARCH),OS2)
+CSRCS += nsinstall.c
+
+PLSRCS = nfspwd.pl
+endif
+
+ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+# Temporary workaround to disable the generation of
+# library build time because now.c uses the 'long long'
+# data type that's not available on some platforms.
+ifeq (,$(filter-out NEC NEXTSTEP QNX SCOOS UNIXWARE,$(OS_ARCH)))
+DEFINES += -DOMIT_LIB_BUILD_TIME
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ifndef NS_USE_GCC
+ ifeq ($(USE_N32),1)
+ XLDOPTS += -n32 -Wl,-woff,85
+ else
+ ifeq ($(USE_64),1)
+ XLDOPTS += -64
+ else
+ XLDOPTS += -32
+ endif
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+ ifeq ($(USE_64),1)
+ XLDOPTS += +DD64
+ endif
+endif
+
+ifeq ($(MOZ_OS2_TOOLS),EMX)
+XCFLAGS = $(OS_CFLAGS)
+ifeq ($(MOZ_OS2_EMX_OBJECTFORMAT),OMF)
+XLDOPTS = -Zlinker /PM:VIO
+endif
+endif
+
+ifeq ($(MOZ_OS2_TOOLS),PGCC)
+XCFLAGS = $(OS_CFLAGS)
+XLDOPTS = -Zlinker /PM:VIO
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+PROGS = $(OBJDIR)/now$(PROG_SUFFIX)
+
+ifeq (,$(CROSS_COMPILE)$(filter-out OS2 WINNT,$(OS_ARCH)))
+TARGETS = $(PROGS)
+else
+PROGS += $(OBJDIR)/nsinstall$(PROG_SUFFIX)
+TARGETS = $(PROGS) $(PLSRCS:.pl=)
+endif
+
+OUTOPTION = -o # end of the line
+ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET)))
+ifndef NS_USE_GCC
+OUTOPTION = /Fe
+endif
+endif
+
+# Redefine MAKE_OBJDIR for just this directory
+define MAKE_OBJDIR
+if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); else true; fi
+endef
+
+export:: $(TARGETS)
+ rm -f $(dist_bindir)/nspr-config
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(LD) $(EXEFLAGS) $<
+else
+ $(CC) $(XCFLAGS) $< $(LDFLAGS) $(XLDOPTS) $(OUTOPTION)$@
+endif
+
+real_install:: nspr.m4
+ $(NSINSTALL) -D $(DESTDIR)$(datadir)/aclocal
+ $(NSINSTALL) -t -m 0644 $< $(DESTDIR)$(datadir)/aclocal
diff --git a/src/libs/xpcom18a4/nsprpub/config/autoconf.mk.in b/src/libs/xpcom18a4/nsprpub/config/autoconf.mk.in
new file mode 100644
index 00000000..92800154
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/autoconf.mk.in
@@ -0,0 +1,113 @@
+# -*- Mode: Makefile -*-
+
+INCLUDED_AUTOCONF_MK = 1
+USE_AUTOCONF = 1
+@SHELL_OVERRIDE@
+MOZILLA_CLIENT = @MOZILLA_CLIENT@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+libdir = @libdir@
+datadir = @datadir@
+
+dist_prefix = @dist_prefix@
+dist_bindir = @dist_bindir@
+dist_includedir = @dist_includedir@
+dist_libdir = @dist_libdir@
+
+DIST = $(dist_prefix)
+
+RELEASE_OBJDIR_NAME = @RELEASE_OBJDIR_NAME@
+OBJDIR_NAME = @OBJDIR_NAME@
+OBJDIR = @OBJDIR@
+OBJ_SUFFIX = @OBJ_SUFFIX@
+LIB_SUFFIX = @LIB_SUFFIX@
+DLL_SUFFIX = @DLL_SUFFIX@
+ASM_SUFFIX = @ASM_SUFFIX@
+MOD_NAME = @NSPR_MODNAME@
+
+MOD_MAJOR_VERSION = @MOD_MAJOR_VERSION@
+MOD_MINOR_VERSION = @MOD_MINOR_VERSION@
+MOD_PATCH_VERSION = @MOD_PATCH_VERSION@
+
+LIBNSPR = @LIBNSPR@
+LIBPLC = @LIBPLC@
+
+CROSS_COMPILE = @CROSS_COMPILE@
+BUILD_OPT = @MOZ_OPTIMIZE@
+
+USE_CPLUS = @USE_CPLUS@
+USE_IPV6 = @USE_IPV6@
+USE_N32 = @USE_N32@
+USE_64 = @USE_64@
+GC_LEAK_DETECTOR = @GC_LEAK_DETECTOR@
+ENABLE_STRIP = @ENABLE_STRIP@
+
+USE_PTHREADS = @USE_PTHREADS@
+USE_BTHREADS = @USE_BTHREADS@
+PTHREADS_USER = @USE_USER_PTHREADS@
+CLASSIC_NSPR = @USE_NSPR_THREADS@
+
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+CC = @CC@
+CCC = @CXX@
+NS_USE_GCC = @GNU_CC@
+GCC_USE_GNU_LD = @GCC_USE_GNU_LD@
+MSC_VER = @MSC_VER@
+AR = @AR@
+AR_FLAGS = @AR_FLAGS@
+LD = @LD@
+RANLIB = @RANLIB@
+PERL = @PERL@
+RC = @RC@
+RCFLAGS = @RCFLAGS@
+STRIP = @STRIP@
+NSINSTALL = @NSINSTALL@
+FILTER = @FILTER@
+IMPLIB = @IMPLIB@
+CYGWIN_WRAPPER = @CYGWIN_WRAPPER@
+
+OS_CPPFLAGS = @CPPFLAGS@
+OS_CFLAGS = $(OS_CPPFLAGS) @CFLAGS@ $(DSO_CFLAGS)
+OS_CXXFLAGS = $(OS_CPPFLAGS) @CXXFLAGS@ $(DSO_CFLAGS)
+OS_LIBS = @OS_LIBS@
+OS_LDFLAGS = @LDFLAGS@
+OS_DLLFLAGS = @OS_DLLFLAGS@
+DLLFLAGS = @DLLFLAGS@
+EXEFLAGS = @EXEFLAGS@
+OPTIMIZER = @OPTIMIZER@
+
+MKSHLIB = @MKSHLIB@
+DSO_CFLAGS = @DSO_CFLAGS@
+DSO_LDOPTS = @DSO_LDOPTS@
+
+RESOLVE_LINK_SYMBOLS = @RESOLVE_LINK_SYMBOLS@
+
+HOST_CC = @HOST_CC@
+HOST_CFLAGS = @HOST_CFLAGS@
+
+DEFINES = @DEFINES@ @DEFS@
+
+MDCPUCFG_H = @MDCPUCFG_H@
+PR_MD_CSRCS = @PR_MD_CSRCS@
+PR_MD_ASFILES = @PR_MD_ASFILES@
+PR_MD_ARCH_DIR = @PR_MD_ARCH_DIR@
+CPU_ARCH = @CPU_ARCH@
+
+OS_TARGET = @OS_TARGET@
+OS_ARCH = @OS_ARCH@
+OS_RELEASE = @OS_RELEASE@
+OS_TEST = @OS_TEST@
+
+NOSUCHFILE = @NOSUCHFILE@
+AIX_LINK_OPTS = @AIX_LINK_OPTS@
+MOZ_OBJFORMAT = @MOZ_OBJFORMAT@
+ULTRASPARC_LIBRARY = @ULTRASPARC_LIBRARY@
+
+OBJECT_MODE = @OBJECT_MODE@
+ifdef OBJECT_MODE
+export OBJECT_MODE
+endif
diff --git a/src/libs/xpcom18a4/nsprpub/config/config.mk b/src/libs/xpcom18a4/nsprpub/config/config.mk
new file mode 100644
index 00000000..697a6015
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/config.mk
@@ -0,0 +1,164 @@
+#! gmake
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+# Configuration information for building in the NSPR source module
+
+# Define an include-at-most-once-flag
+NSPR_CONFIG_MK = 1
+
+#
+# The variable definitions in this file are inputs to NSPR's
+# build system. This file, if present, is included at the
+# beginning of config.mk.
+#
+# For example:
+#
+# BUILD_OPT=1
+# USE_PTHREADS=1
+# NS_USE_GCC=
+#
+ifndef topsrcdir
+topsrcdir=$(MOD_DEPTH)
+endif
+
+ifndef srcdir
+srcdir=.
+endif
+
+NFSPWD = $(MOD_DEPTH)/config/nfspwd
+
+CFLAGS = $(CC_ONLY_FLAGS) $(OPTIMIZER) $(OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+CCCFLAGS = $(CCC_ONLY_FLAGS) $(OPTIMIZER) $(OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+# For purify
+NOMD_CFLAGS = $(CC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+NOMD_CCFLAGS = $(CCC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\
+ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+
+LDFLAGS = $(OS_LDFLAGS)
+
+define MAKE_OBJDIR
+if test ! -d $(@D); then rm -rf $(@D); $(NSINSTALL) -D $(@D); fi
+endef
+
+LINK_DLL = $(LD) $(OS_DLLFLAGS) $(DLLFLAGS)
+
+ifeq ($(OS_ARCH),Darwin)
+PWD := $(shell pwd)
+endif
+
+ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2, $(OS_ARCH)))
+INSTALL = $(NSINSTALL)
+else
+ifeq ($(NSDISTMODE),copy)
+# copy files, but preserve source mtime
+INSTALL = $(NSINSTALL) -t
+else
+ifeq ($(NSDISTMODE),absolute_symlink)
+# install using absolute symbolic links
+ifeq ($(OS_ARCH),Darwin)
+INSTALL = $(NSINSTALL) -L $(PWD)
+else
+INSTALL = $(NSINSTALL) -L `$(NFSPWD)`
+endif
+else
+# install using relative symbolic links
+INSTALL = $(NSINSTALL) -R
+endif
+endif
+endif # (WINNT || OS2) && !CROSS_COMPILE
+
+DEPENDENCIES = $(OBJDIR)/.md
+
+ifdef BUILD_DEBUG_GC
+DEFINES += -DDEBUG_GC
+endif
+
+GARBAGE += $(DEPENDENCIES) core $(wildcard core.[0-9]*)
+
+DIST_GARBAGE += Makefile
+
+####################################################################
+#
+# The NSPR-specific configuration
+#
+####################################################################
+
+DEFINES += -DFORCE_PR_LOG
+
+ifeq ($(_PR_NO_CLOCK_TIMER),1)
+DEFINES += -D_PR_NO_CLOCK_TIMER
+endif
+
+ifeq ($(USE_PTHREADS), 1)
+DEFINES += -D_PR_PTHREADS -UHAVE_CVAR_BUILT_ON_SEM
+endif
+
+ifeq ($(PTHREADS_USER), 1)
+DEFINES += -DPTHREADS_USER -UHAVE_CVAR_BUILT_ON_SEM
+endif
+
+ifeq ($(USE_IPV6),1)
+DEFINES += -D_PR_INET6
+endif
+
+ifeq ($(MOZ_UNICODE),1)
+DEFINES += -DMOZ_UNICODE
+endif
+
+####################################################################
+#
+# Configuration for the release process
+#
+####################################################################
+
+MDIST = /m/dist
+ifeq ($(OS_ARCH),WINNT)
+MDIST = //helium/dist
+MDIST_DOS = $(subst /,\\,$(MDIST))
+endif
+
+# RELEASE_DIR is ns/dist/<module name>
+
+RELEASE_DIR = $(MOD_DEPTH)/dist/release/$(MOD_NAME)
+
+RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/include
+RELEASE_BIN_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/bin
+RELEASE_LIB_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/lib
diff --git a/src/libs/xpcom18a4/nsprpub/config/libc_r.h b/src/libs/xpcom18a4/nsprpub/config/libc_r.h
new file mode 100644
index 00000000..0f66d127
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/libc_r.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* libc_r.h -- macros, defines, etc. to make using reentrant libc calls */
+/* a bit easier. This was initially done for AIX pthreads, */
+/* but should be usable for anyone... */
+
+/* Most of these use locally defined space instead of static library space. */
+/* Because of this, we use the _INIT_R to declare/allocate space (stack), */
+/* and the plain routines to actually do it..._WARNING_: avoid allocating */
+/* memory wherever possible. Memory allocation is fairly expensive, at */
+/* least on AIX...use arrays instead (which allocate from the stack.) */
+/* I know the names are a bit strange, but I wanted to be fairly certain */
+/* that we didn't have any namespace corruption...in general, the inits are */
+/* R_<name>_INIT_R(), and the actual calls are R_<name>_R(). */
+
+#ifndef _LIBC_R_H
+#define _LIBC_R_H
+
+/************/
+/* strtok */
+/************/
+#define R_STRTOK_INIT_R() \
+ char *r_strtok_r=NULL
+
+#define R_STRTOK_R(return,source,delim) \
+ return=strtok_r(source,delim,&r_strtok_r)
+
+#define R_STRTOK_NORET_R(source,delim) \
+ strtok_r(source,delim,&r_strtok_r)
+
+/**************/
+/* strerror */
+/**************/
+#define R_MAX_STRERROR_LEN_R 8192 /* Straight from limits.h */
+
+#define R_STRERROR_INIT_R() \
+ char r_strerror_r[R_MAX_STRERROR_LEN_R]
+
+#define R_STRERROR_R(val) \
+ strerror_r(val,r_strerror_r,R_MAX_STRERROR_LEN_R)
+
+/*****************/
+/* time things */
+/*****************/
+#define R_ASCTIME_INIT_R() \
+ char r_asctime_r[26]
+
+#define R_ASCTIME_R(val) \
+ asctime_r(val,r_asctime_r)
+
+#define R_CTIME_INIT_R() \
+ char r_ctime_r[26]
+
+#define R_CTIME_R(val) \
+ ctime_r(val,r_ctime_r)
+
+#define R_GMTIME_INIT_R() \
+ struct tm r_gmtime_r
+
+#define R_GMTIME_R(time) \
+ gmtime_r(time,&r_gmtime_r)
+
+#define R_LOCALTIME_INIT_R() \
+ struct tm r_localtime_r
+
+#define R_LOCALTIME_R(val) \
+ localtime_r(val,&r_localtime_r)
+
+/***********/
+/* crypt */
+/***********/
+#include <crypt.h>
+#define R_CRYPT_INIT_R() \
+ CRYPTD r_cryptd_r; \
+ bzero(&r_cryptd_r,sizeof(CRYPTD))
+
+#define R_CRYPT_R(pass,salt) \
+ crypt_r(pass,salt,&r_cryptd_r)
+
+/**************/
+/* pw stuff */
+/**************/
+#define R_MAX_PW_LEN_R 1024
+/* The following must be after the last declaration, but */
+/* before the first bit of code... */
+#define R_GETPWNAM_INIT_R(pw_ptr) \
+ struct passwd r_getpwnam_pw_r; \
+ char r_getpwnam_line_r[R_MAX_PW_LEN_R]; \
+ pw_ptr = &r_getpwnam_pw_r
+
+#define R_GETPWNAM_R(name) \
+ getpwnam_r(name,&r_getpwnam_pw_r,r_getpwnam_line_r,R_MAX_PW_LEN_R)
+
+/*******************/
+/* gethost stuff */
+/*******************/
+#define R_GETHOSTBYADDR_INIT_R() \
+ struct hostent r_gethostbyaddr_r; \
+ struct hostent_data r_gethostbyaddr_data_r
+
+#define R_GETHOSTBYADDR_R(addr,len,type,xptr_ent) \
+ bzero(&r_gethostbyaddr_r,sizeof(struct hostent)); \
+ bzero(&r_gethostbyaddr_data_r,sizeof(struct hostent_data)); \
+ xptr_ent = &r_gethostbyaddr_r; \
+ if (gethostbyaddr_r(addr,len,type, \
+ &r_gethostbyaddr_r,&r_gethostbyaddr_data_r) == -1) { \
+ xptr_ent = NULL; \
+ }
+
+#define R_GETHOSTBYNAME_INIT_R() \
+ struct hostent r_gethostbyname_r; \
+ struct hostent_data r_gethostbyname_data_r
+
+#define R_GETHOSTBYNAME_R(name,xptr_ent) \
+ bzero(&r_gethostbyname_r,sizeof(struct hostent)); \
+ bzero(&r_gethostbyname_data_r,sizeof(struct hostent_data)); \
+ xptr_ent = &r_gethostbyname_r; \
+ if (gethostbyname_r(name, \
+ &r_gethostbyname_r,&r_gethostbyname_data_r) == -1) { \
+ xptr_ent = NULL; \
+ }
+
+#endif /* _LIBC_R_H */
diff --git a/src/libs/xpcom18a4/nsprpub/config/nfspwd.pl b/src/libs/xpcom18a4/nsprpub/config/nfspwd.pl
new file mode 100755
index 00000000..947b822a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/nfspwd.pl
@@ -0,0 +1,50 @@
+#! perl
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+require "fastcwd.pl";
+
+$_ = &fastcwd;
+if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) {
+ print("$_\n");
+} elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o)
+ && readlink("/u/$user") eq "/usr/people/$user") {
+ print("/u/$user/$rest\n");
+} else {
+ chop($host = `hostname`);
+ print("/h/$host$_\n");
+}
diff --git a/src/libs/xpcom18a4/nsprpub/config/now.c b/src/libs/xpcom18a4/nsprpub/config/now.c
new file mode 100644
index 00000000..f797ef84
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/now.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(VMS)
+#include <sys/timeb.h>
+#elif defined(XP_UNIX) || defined(XP_OS2_EMX) || defined(XP_BEOS)
+#include <sys/time.h>
+#elif defined(WIN32)
+#include <windows.h>
+#elif defined(XP_OS2_VACPP)
+#include <sys/timeb.h>
+#else
+#error "Architecture not supported"
+#endif
+
+
+int main(int argc, char **argv)
+{
+#if defined(OMIT_LIB_BUILD_TIME)
+ /*
+ * Some platforms don't have any 64-bit integer type
+ * such as 'long long'. Because we can't use NSPR's
+ * PR_snprintf in this program, it is difficult to
+ * print a static initializer for PRInt64 (a struct).
+ * So we print nothing. The makefiles that build the
+ * shared libraries will detect the empty output string
+ * of this program and omit the library build time
+ * in PRVersionDescription.
+ */
+#elif defined(VMS)
+ long long now;
+ struct timeb b;
+ ftime(&b);
+ now = b.time;
+ now *= 1000000;
+ now += (1000 * b.millitm);
+ fprintf(stdout, "%Ld", now);
+#elif defined(XP_UNIX) || defined(XP_OS2_EMX) || defined(XP_BEOS)
+ long long now;
+ struct timeval tv;
+#ifdef HAVE_SVID_GETTOD
+ gettimeofday(&tv);
+#else
+ gettimeofday(&tv, NULL);
+#endif
+ now = ((1000000LL) * tv.tv_sec) + (long long)tv.tv_usec;
+#if defined(OSF1)
+ fprintf(stdout, "%ld", now);
+#elif defined(BEOS) && defined(__POWERPC__)
+ fprintf(stdout, "%Ld", now); /* Metroworks on BeOS PPC */
+#else
+ fprintf(stdout, "%lld", now);
+#endif
+
+#elif defined(WIN32)
+ __int64 now;
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ CopyMemory(&now, &ft, sizeof(now));
+ /*
+ * 116444736000000000 is the number of 100-nanosecond intervals
+ * between Jan. 1, 1601 and Jan. 1, 1970.
+ */
+#ifdef __GNUC__
+ now = (now - 116444736000000000LL) / 10LL;
+ fprintf(stdout, "%lld", now);
+#else
+ now = (now - 116444736000000000i64) / 10i64;
+ fprintf(stdout, "%I64d", now);
+#endif
+
+#elif defined(XP_OS2_VACPP)
+/* no long long or i64 so we use a string */
+#include <string.h>
+ char buf[24];
+ char tbuf[7];
+ time_t now;
+ long mtime;
+ int i;
+
+ struct timeb b;
+ ftime(&b);
+ now = b.time;
+ _ltoa(now, buf, 10);
+
+ mtime = b.millitm * 1000;
+ if (mtime == 0){
+ ++now;
+ strcat(buf, "000000");
+ } else {
+ _ltoa(mtime, tbuf, 10);
+ for (i = strlen(tbuf); i < 6; ++i)
+ strcat(buf, "0");
+ strcat(buf, tbuf);
+ }
+ fprintf(stdout, "%s", buf);
+
+#else
+#error "Architecture not supported"
+#endif
+
+ return 0;
+} /* main */
+
+/* now.c */
diff --git a/src/libs/xpcom18a4/nsprpub/config/nsinstall.c b/src/libs/xpcom18a4/nsprpub/config/nsinstall.c
new file mode 100644
index 00000000..319a9594
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/nsinstall.c
@@ -0,0 +1,602 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Netscape portable install command.
+**
+** Brendan Eich, 7/20/95
+*/
+#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
+#include <assert.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#ifdef USE_REENTRANT_LIBC
+#include "libc_r.h"
+#endif /* USE_REENTRANT_LIBC */
+
+#include "pathsub.h"
+
+#define HAVE_FCHMOD
+
+#if defined(BEOS)
+#undef HAVE_FCHMOD
+#endif
+
+/*
+ * Does getcwd() take NULL as the first argument and malloc
+ * the result buffer?
+ */
+#if !defined(DARWIN) && !defined(NEXTSTEP) && !defined(VMS)
+#define GETCWD_CAN_MALLOC
+#endif
+
+#ifdef NEXTSTEP
+#include <bsd/libc.h>
+
+/*
+** balazs.pataki@sztaki.hu: The getcwd is broken in NEXTSTEP (returns 0),
+** when called on a mounted fs. Did anyone notice this? Here's an ugly
+** workaround ...
+*/
+#define getcwd(b,s) my_getcwd(b,s)
+
+static char *
+my_getcwd (char *buf, size_t size)
+{
+ FILE *pwd = popen("pwd", "r");
+ char *result = fgets(buf, size, pwd);
+
+ if (result) {
+ buf[strlen(buf)-1] = '\0';
+ }
+ pclose (pwd);
+ return buf;
+}
+#endif /* NEXTSTEP */
+
+#ifdef LINUX
+#include <getopt.h>
+#endif
+
+#if defined(SCO) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC) || defined(NEXTSTEP)
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
+#endif
+#endif
+
+#if defined(SNI)
+extern int fchmod(int fildes, mode_t mode);
+#endif
+
+#ifdef QNX
+#define d_ino d_stat.st_ino
+#endif
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
+ " %*s [-DdltR] file [file ...] directory\n",
+ program, (int)strlen(program), "");
+ exit(2);
+}
+
+static int
+mkdirs(char *path, mode_t mode)
+{
+ char *cp;
+ struct stat sb;
+ int res;
+
+ while (*path == '/' && path[1] == '/')
+ path++;
+ while ((cp = strrchr(path, '/')) && cp[1] == '\0')
+ *cp = '\0';
+ if (cp && cp != path) {
+ *cp = '\0';
+ if ((stat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(path, mode) < 0) {
+ return -1;
+ }
+ *cp = '/';
+ }
+ res = mkdir(path, mode);
+ if ((res != 0) && (errno == EEXIST))
+ return 0;
+ else
+ return res;
+}
+
+static uid_t
+touid(char *owner)
+{
+ struct passwd *pw;
+ uid_t uid;
+ char *cp;
+
+ pw = getpwnam(owner);
+ if (pw)
+ return pw->pw_uid;
+ uid = strtol(owner, &cp, 0);
+ if (uid == 0 && cp == owner)
+ fail("cannot find uid for %s", owner);
+ return uid;
+}
+
+static gid_t
+togid(char *group)
+{
+ struct group *gr;
+ gid_t gid;
+ char *cp;
+
+ gr = getgrnam(group);
+ if (gr)
+ return gr->gr_gid;
+ gid = strtol(group, &cp, 0);
+ if (gid == 0 && cp == group)
+ fail("cannot find gid for %s", group);
+ return gid;
+}
+
+int
+main(int argc, char **argv)
+{
+ int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
+ mode_t mode = 0755;
+ char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
+ uid_t uid;
+ gid_t gid;
+ struct stat sb, tosb;
+ struct utimbuf utb;
+
+ program = argv[0];
+ cwd = linkname = linkprefix = owner = group = 0;
+ onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
+
+ while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
+ switch (opt) {
+ case 'C':
+ cwd = optarg;
+ break;
+ case 'D':
+ onlydir = 1;
+ break;
+ case 'd':
+ dodir = 1;
+ break;
+ case 'l':
+ dolink = 1;
+ break;
+ case 'L':
+ linkprefix = optarg;
+ lplen = strlen(linkprefix);
+ dolink = 1;
+ break;
+ case 'R':
+ dolink = dorelsymlink = 1;
+ break;
+ case 'm':
+ mode = strtoul(optarg, &cp, 8);
+ if (mode == 0 && cp == optarg)
+ usage();
+ break;
+ case 'o':
+ owner = optarg;
+ break;
+ case 'g':
+ group = optarg;
+ break;
+ case 't':
+ dotimes = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2 - onlydir)
+ usage();
+
+ todir = argv[argc-1];
+ if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(todir, 0777) < 0) {
+ fail("cannot make directory %s", todir);
+ }
+ if (onlydir)
+ return 0;
+
+ if (!cwd) {
+#ifdef GETCWD_CAN_MALLOC
+ cwd = getcwd(0, PATH_MAX);
+#else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getcwd(cwd, PATH_MAX);
+#endif
+ }
+ xchdir(todir);
+#ifdef GETCWD_CAN_MALLOC
+ todir = getcwd(0, PATH_MAX);
+#else
+ todir = malloc(PATH_MAX + 1);
+ todir = getcwd(todir, PATH_MAX);
+#endif
+ tdlen = strlen(todir);
+ xchdir(cwd);
+ tdlen = strlen(todir);
+
+ uid = owner ? touid(owner) : -1;
+ gid = group ? togid(group) : -1;
+
+ while (--argc > 0) {
+ name = *argv++;
+ len = strlen(name);
+ base = xbasename(name);
+ bnlen = strlen(base);
+ toname = (char*)xmalloc(tdlen + 1 + bnlen + 1);
+ sprintf(toname, "%s/%s", todir, base);
+ exists = (lstat(toname, &tosb) == 0);
+
+ if (dodir) {
+ /* -d means create a directory, always */
+ if (exists && !S_ISDIR(tosb.st_mode)) {
+ (void) unlink(toname);
+ exists = 0;
+ }
+ if (!exists && mkdir(toname, mode) < 0)
+ fail("cannot make directory %s", toname);
+ if ((owner || group) && chown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+ } else if (dolink) {
+ if (*name == '/') {
+ /* source is absolute pathname, link to it directly */
+ linkname = 0;
+ } else {
+ if (linkprefix) {
+ /* -L implies -l and prefixes names with a $cwd arg. */
+ len += lplen + 1;
+ linkname = (char*)xmalloc(len + 1);
+ sprintf(linkname, "%s/%s", linkprefix, name);
+ } else if (dorelsymlink) {
+ /* Symlink the relative path from todir to source name. */
+ linkname = (char*)xmalloc(PATH_MAX);
+
+ if (*todir == '/') {
+ /* todir is absolute: skip over common prefix. */
+ lplen = relatepaths(todir, cwd, linkname);
+ strcpy(linkname + lplen, name);
+ } else {
+ /* todir is named by a relative path: reverse it. */
+ reversepath(todir, name, len, linkname);
+ xchdir(cwd);
+ }
+
+ len = strlen(linkname);
+ }
+ name = linkname;
+ }
+
+ /* Check for a pre-existing symlink with identical content. */
+ if (exists &&
+ (!S_ISLNK(tosb.st_mode) ||
+ readlink(toname, buf, sizeof buf) != len ||
+ strncmp(buf, name, len) != 0)) {
+ (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ exists = 0;
+ }
+ if (!exists && symlink(name, toname) < 0)
+ fail("cannot make symbolic link %s", toname);
+#ifdef HAVE_LCHOWN
+ if ((owner || group) && lchown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+#endif
+
+ if (linkname) {
+ free(linkname);
+ linkname = 0;
+ }
+ } else {
+ /* Copy from name to toname, which might be the same file. */
+ fromfd = open(name, O_RDONLY);
+ if (fromfd < 0 || fstat(fromfd, &sb) < 0)
+ fail("cannot access %s", name);
+ if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0))
+ (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ if (tofd < 0)
+ fail("cannot create %s", toname);
+
+ bp = buf;
+ while ((cc = read(fromfd, bp, sizeof buf)) > 0) {
+ while ((wc = write(tofd, bp, cc)) > 0) {
+ if ((cc -= wc) == 0)
+ break;
+ bp += wc;
+ }
+ if (wc < 0)
+ fail("cannot write to %s", toname);
+ }
+ if (cc < 0)
+ fail("cannot read from %s", name);
+
+ if (ftruncate(tofd, sb.st_size) < 0)
+ fail("cannot truncate %s", toname);
+ /*
+ ** On OpenVMS we can't chmod() until the file is closed, and we
+ ** have to utime() last since fchown/chmod alter the timestamps.
+ */
+#ifndef VMS
+ if (dotimes) {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0)
+ fail("cannot set times of %s", toname);
+ }
+#ifdef HAVE_FCHMOD
+ if (fchmod(tofd, mode) < 0)
+#else
+ if (chmod(toname, mode) < 0)
+#endif
+ fail("cannot change mode of %s", toname);
+#endif
+ if ((owner || group) && fchown(tofd, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+
+ /* Must check for delayed (NFS) write errors on close. */
+ if (close(tofd) < 0)
+ fail("cannot write to %s", toname);
+ close(fromfd);
+#ifdef VMS
+ if (chmod(toname, mode) < 0)
+ fail("cannot change mode of %s", toname);
+ if (dotimes) {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0)
+ fail("cannot set times of %s", toname);
+ }
+#endif
+ }
+
+ free(toname);
+ }
+
+ free(cwd);
+ free(todir);
+ return 0;
+}
+
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+
+char *program;
+
+void
+fail(char *format, ...)
+{
+ int error;
+ va_list ap;
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_INIT_R();
+#endif
+
+ error = errno;
+ fprintf(stderr, "%s: ", program);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if (error)
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_R(errno);
+ fprintf(stderr, ": %s", r_strerror_r);
+#else
+ fprintf(stderr, ": %s", strerror(errno));
+#endif
+
+ putc('\n', stderr);
+ exit(1);
+}
+
+char *
+getcomponent(char *path, char *name)
+{
+ if (*path == '\0')
+ return 0;
+ if (*path == '/') {
+ *name++ = '/';
+ } else {
+ do {
+ *name++ = *path++;
+ } while (*path != '/' && *path != '\0');
+ }
+ *name = '\0';
+ while (*path == '/')
+ path++;
+ return path;
+}
+
+#ifdef UNIXWARE_READDIR_BUFFER_TOO_SMALL
+/* Sigh. The static buffer in Unixware's readdir is too small. */
+struct dirent * readdir(DIR *d)
+{
+ static struct dirent *buf = NULL;
+#define MAX_PATH_LEN 1024
+
+
+ if(buf == NULL)
+ buf = (struct dirent *) malloc(sizeof(struct dirent) + MAX_PATH_LEN)
+;
+ return(readdir_r(d, buf));
+}
+#endif
+
+char *
+ino2name(ino_t ino, char *dir)
+{
+ DIR *dp;
+ struct dirent *ep;
+ char *name;
+
+ dp = opendir("..");
+ if (!dp)
+ fail("cannot read parent directory");
+ for (;;) {
+ if (!(ep = readdir(dp)))
+ fail("cannot find current directory");
+ if (ep->d_ino == ino)
+ break;
+ }
+ name = xstrdup(ep->d_name);
+ closedir(dp);
+ return name;
+}
+
+void *
+xmalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p)
+ fail("cannot allocate %u bytes", size);
+ return p;
+}
+
+char *
+xstrdup(char *s)
+{
+ return strcpy((char*)xmalloc(strlen(s) + 1), s);
+}
+
+char *
+xbasename(char *path)
+{
+ char *cp;
+
+ while ((cp = strrchr(path, '/')) && cp[1] == '\0')
+ *cp = '\0';
+ if (!cp) return path;
+ return cp + 1;
+}
+
+void
+xchdir(char *dir)
+{
+ if (chdir(dir) < 0)
+ fail("cannot change directory to %s", dir);
+}
+
+int
+relatepaths(char *from, char *to, char *outpath)
+{
+ char *cp, *cp2;
+ int len;
+ char buf[NAME_MAX];
+
+ assert(*from == '/' && *to == '/');
+ for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
+ if (*cp == '\0')
+ break;
+ while (cp[-1] != '/')
+ cp--, cp2--;
+ if (cp - 1 == to) {
+ /* closest common ancestor is /, so use full pathname */
+ len = strlen(strcpy(outpath, to));
+ if (outpath[len] != '/') {
+ outpath[len++] = '/';
+ outpath[len] = '\0';
+ }
+ } else {
+ len = 0;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ strcpy(outpath + len, "../");
+ len += 3;
+ }
+ while ((cp = getcomponent(cp, buf)) != 0) {
+ sprintf(outpath + len, "%s/", buf);
+ len += strlen(outpath + len);
+ }
+ }
+ return len;
+}
+
+void
+reversepath(char *inpath, char *name, int len, char *outpath)
+{
+ char *cp, *cp2;
+ char buf[NAME_MAX];
+ struct stat sb;
+
+ cp = strcpy(outpath + PATH_MAX - (len + 1), name);
+ cp2 = inpath;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ if (strcmp(buf, ".") == 0)
+ continue;
+ if (strcmp(buf, "..") == 0) {
+ if (stat(".", &sb) < 0)
+ fail("cannot stat current directory");
+ name = ino2name(sb.st_ino, "..");
+ len = strlen(name);
+ cp -= len + 1;
+ strcpy(cp, name);
+ cp[len] = '/';
+ free(name);
+ xchdir("..");
+ } else {
+ cp -= 3;
+ strncpy(cp, "../", 3);
+ xchdir(buf);
+ }
+ }
+ strcpy(outpath, cp);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/config/nspr-config.in b/src/libs/xpcom18a4/nsprpub/config/nspr-config.in
new file mode 100755
index 00000000..e9e18679
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/nspr-config.in
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+major_version=@MOD_MAJOR_VERSION@
+minor_version=@MOD_MINOR_VERSION@
+patch_version=@MOD_PATCH_VERSION@
+
+usage()
+{
+ cat <<EOF
+Usage: nspr-config [OPTIONS] [LIBRARIES]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--version]
+ [--libs]
+ [--cflags]
+Libraries:
+ nspr
+ plc
+ plds
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+lib_nspr=yes
+lib_plc=yes
+lib_plds=yes
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+ --prefix)
+ echo_prefix=yes
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=yes
+ ;;
+ --version)
+ echo ${major_version}.${minor_version}.${patch_version}
+ ;;
+ --cflags)
+ echo_cflags=yes
+ ;;
+ --libs)
+ echo_libs=yes
+ ;;
+ nspr)
+ lib_nspr=yes
+ ;;
+ plc)
+ lib_plc=yes
+ ;;
+ plds)
+ lib_plds=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+if test "$echo_prefix" = "yes"; then
+ echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+ echo $exec_prefix
+fi
+
+if test "$echo_cflags" = "yes"; then
+ echo -I${prefix}/include/nspr
+fi
+
+if test "$echo_libs" = "yes"; then
+ libdirs=-L${exec_prefix}/lib
+ if test -n "$lib_plds"; then
+ libdirs="$libdirs -lplds${major_version}"
+ fi
+ if test -n "$lib_plc"; then
+ libdirs="$libdirs -lplc${major_version}"
+ fi
+ if test -n "$lib_nspr"; then
+ libdirs="$libdirs -lnspr${major_version}"
+ fi
+ os_ldflags="@LDFLAGS@"
+ for i in $os_ldflags ; do
+ if echo $i | grep \^-L >/dev/null; then
+ libdirs="$libdirs $i"
+ fi
+ done
+ echo $libdirs @OS_LIBS@
+fi
+
diff --git a/src/libs/xpcom18a4/nsprpub/config/nspr.m4 b/src/libs/xpcom18a4/nsprpub/config/nspr.m4
new file mode 100644
index 00000000..8174bea9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/nspr.m4
@@ -0,0 +1,67 @@
+# -*- tab-width: 4; -*-
+# Configure paths for NSPR
+# Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
+# Based upon gtk.m4 (also PD) by Owen Taylor
+
+dnl AM_PATH_NSPR([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for NSPR, and define NSPR_CFLAGS and NSPR_LIBS
+AC_DEFUN(AM_PATH_NSPR,
+[dnl
+
+AC_ARG_WITH(nspr-prefix,
+ [ --with-nspr-prefix=PFX Prefix where NSPR is installed],
+ nspr_config_prefix="$withval",
+ nspr_config_prefix="")
+
+AC_ARG_WITH(nspr-exec-prefix,
+ [ --with-nspr-exec-prefix=PFX
+ Exec prefix where NSPR is installed],
+ nspr_config_exec_prefix="$withval",
+ nspr_config_exec_prefix="")
+
+ if test -n "$nspr_config_exec_prefix"; then
+ nspr_config_args="$nspr_config_args --exec-prefix=$nspr_config_exec_prefix"
+ if test -z "$NSPR_CONFIG"; then
+ NSPR_CONFIG=$nspr_config_exec_prefix/bin/nspr-config
+ fi
+ fi
+ if test -n "$nspr_config_prefix"; then
+ nspr_config_args="$nspr_config_args --prefix=$nspr_config_prefix"
+ if test -z "$NSPR_CONFIG"; then
+ NSPR_CONFIG=$nspr_config_prefix/bin/nspr-config
+ fi
+ fi
+
+ unset ac_cv_path_NSPR_CONFIG
+ AC_PATH_PROG(NSPR_CONFIG, nspr-config, no)
+ min_nspr_version=ifelse([$1], ,4.0.0,$1)
+ AC_MSG_CHECKING(for NSPR - version >= $min_nspr_version (skipping))
+
+ no_nspr=""
+ if test "$NSPR_CONFIG" = "no"; then
+ no_nspr="yes"
+ else
+ NSPR_CFLAGS=`$NSPR_CONFIG $nspr_config_args --cflags`
+ NSPR_LIBS=`$NSPR_CONFIG $nspr_config_args --libs`
+
+ dnl Skip version check for now
+ nspr_config_major_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ nspr_config_minor_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ nspr_config_micro_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ fi
+
+ if test -z "$no_nspr"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+
+ AC_SUBST(NSPR_CFLAGS)
+ AC_SUBST(NSPR_LIBS)
+
+])
diff --git a/src/libs/xpcom18a4/nsprpub/config/nsprincl.mk.in b/src/libs/xpcom18a4/nsprpub/config/nsprincl.mk.in
new file mode 100644
index 00000000..d56cc024
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/nsprincl.mk.in
@@ -0,0 +1,5 @@
+# Include in Makefiles to define NSPR variables
+
+NSPR_VERSION = @NSPR_VERSION@
+NSPR_LIB = -lnspr@NSPR_VERSION@
+NSPR_EXTRA_LIBS = @EXTRA_LIBS@
diff --git a/src/libs/xpcom18a4/nsprpub/config/nsprincl.sh.in b/src/libs/xpcom18a4/nsprpub/config/nsprincl.sh.in
new file mode 100644
index 00000000..be4e1450
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/nsprincl.sh.in
@@ -0,0 +1,5 @@
+# Include in shell scripts to define NSPR variables
+
+NSPR_VERSION=@NSPR_VERSION@
+NSPR_LIB=-lnspr$NSPR_VERSION
+NSPR_EXTRA_LIBS="@EXTRA_LIBS@"
diff --git a/src/libs/xpcom18a4/nsprpub/config/pathsub.h b/src/libs/xpcom18a4/nsprpub/config/pathsub.h
new file mode 100644
index 00000000..bf3fca31
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/pathsub.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef pathsub_h___
+#define pathsub_h___
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <limits.h>
+#include <sys/types.h>
+
+#if SUNOS4
+#include "../pr/include/md/sunos4.h"
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/*
+ * Just prevent stupidity
+ */
+#undef NAME_MAX
+#define NAME_MAX 256
+
+extern char *program;
+
+extern void fail(char *format, ...);
+extern char *getcomponent(char *path, char *name);
+extern char *ino2name(ino_t ino, char *dir);
+extern void *xmalloc(size_t size);
+extern char *xstrdup(char *s);
+extern char *xbasename(char *path);
+extern void xchdir(char *dir);
+
+/* Relate absolute pathnames from and to returning the result in outpath. */
+extern int relatepaths(char *from, char *to, char *outpath);
+
+/* XXX changes current working directory -- caveat emptor */
+extern void reversepath(char *inpath, char *name, int len, char *outpath);
+
+#endif /* pathsub_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/config/prdepend.h b/src/libs/xpcom18a4/nsprpub/config/prdepend.h
new file mode 100644
index 00000000..df72c568
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/prdepend.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * A dummy header file that is a dependency for all the object files.
+ * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
+ * depend builds. See comments in rules.mk.
+ */
+
+#error "Do not include this header file."
diff --git a/src/libs/xpcom18a4/nsprpub/config/prmkdir.bat b/src/libs/xpcom18a4/nsprpub/config/prmkdir.bat
new file mode 100644
index 00000000..9bea8553
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/prmkdir.bat
@@ -0,0 +1,38 @@
+REM
+REM ***** BEGIN LICENSE BLOCK *****
+REM Version: MPL 1.1/GPL 2.0/LGPL 2.1
+REM
+REM The contents of this file are subject to the Mozilla Public License Version
+REM 1.1 (the "License"); you may not use this file except in compliance with
+REM the License. You may obtain a copy of the License at
+REM http://www.mozilla.org/MPL/
+REM
+REM Software distributed under the License is distributed on an "AS IS" basis,
+REM WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+REM for the specific language governing rights and limitations under the
+REM License.
+REM
+REM The Original Code is the Netscape Portable Runtime (NSPR).
+REM
+REM The Initial Developer of the Original Code is
+REM Netscape Communications Corporation.
+REM Portions created by the Initial Developer are Copyright (C) 1998-2000
+REM the Initial Developer. All Rights Reserved.
+REM
+REM Contributor(s):
+REM
+REM Alternatively, the contents of this file may be used under the terms of
+REM either the GNU General Public License Version 2 or later (the "GPL"), or
+REM the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+REM in which case the provisions of the GPL or the LGPL are applicable instead
+REM of those above. If you wish to allow use of your version of this file only
+REM under the terms of either the GPL or the LGPL, and not to allow others to
+REM use your version of this file under the terms of the MPL, indicate your
+REM decision by deleting the provisions above and replace them with the notice
+REM and other provisions required by the GPL or the LGPL. If you do not delete
+REM the provisions above, a recipient may use your version of this file under
+REM the terms of any one of the MPL, the GPL or the LGPL.
+REM
+REM ***** END LICENSE BLOCK *****
+
+mkdir %1
diff --git a/src/libs/xpcom18a4/nsprpub/config/rules.mk b/src/libs/xpcom18a4/nsprpub/config/rules.mk
new file mode 100644
index 00000000..bba50ee7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/config/rules.mk
@@ -0,0 +1,514 @@
+#! gmake
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+################################################################################
+# We have a 4 pass build process:
+#
+# Pass 1. export - Create generated headers and stubs. Publish public headers to
+# dist/<arch>/include.
+#
+# Pass 2. libs - Create libraries. Publish libraries to dist/<arch>/lib.
+#
+# Pass 3. all - Create programs.
+#
+# Pass 4. install - Publish programs to dist/<arch>/bin.
+#
+# Parameters to this makefile (set these before including):
+#
+# a)
+# TARGETS -- the target to create
+# (defaults to $LIBRARY $PROGRAM)
+# b)
+# DIRS -- subdirectories for make to recurse on
+# (the 'all' rule builds $TARGETS $DIRS)
+# c)
+# CSRCS -- .c files to compile
+# (used to define $OBJS)
+# d)
+# PROGRAM -- the target program name to create from $OBJS
+# ($OBJDIR automatically prepended to it)
+# e)
+# LIBRARY -- the target library name to create from $OBJS
+# ($OBJDIR automatically prepended to it)
+#
+################################################################################
+
+ifndef topsrcdir
+topsrcdir=$(MOD_DEPTH)
+endif
+
+ifndef srcdir
+srcdir=.
+endif
+
+ifndef NSPR_CONFIG_MK
+include $(topsrcdir)/config/config.mk
+endif
+
+ifdef USE_AUTOCONF
+ifdef CROSS_COMPILE
+ifdef INTERNAL_TOOLS
+CC=$(HOST_CC)
+CCC=$(HOST_CXX)
+CFLAGS=$(HOST_CFLAGS)
+CXXFLAGS=$(HOST_CXXFLAGS)
+endif
+endif
+endif
+
+#
+# This makefile contains rules for building the following kinds of
+# libraries:
+# - LIBRARY: a static (archival) library
+# - SHARED_LIBRARY: a shared (dynamic link) library
+# - IMPORT_LIBRARY: an import library, used only on Windows and OS/2
+#
+# The names of these libraries can be generated by simply specifying
+# LIBRARY_NAME and LIBRARY_VERSION.
+#
+
+ifdef LIBRARY_NAME
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+
+#
+# Win95, Win16, and OS/2 require library names conforming to the 8.3 rule.
+# other platforms do not.
+#
+ifeq (,$(filter-out WIN95 OS2,$(OS_TARGET)))
+LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX)
+SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
+SHARED_LIB_PDB = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).pdb
+else
+LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX)
+SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+IMPORT_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
+SHARED_LIB_PDB = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).pdb
+endif
+
+else
+
+LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX)
+ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
+SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr.a
+else
+ifdef MKSHLIB
+SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
+endif
+endif
+
+endif
+endif
+
+ifndef TARGETS
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
+ifndef BUILD_OPT
+ifdef MSC_VER
+ifneq ($(MSC_VER),1200)
+TARGETS += $(SHARED_LIB_PDB)
+endif
+endif
+endif
+else
+TARGETS = $(LIBRARY) $(SHARED_LIBRARY)
+endif
+endif
+
+#
+# OBJS is the list of object files. It can be constructed by
+# specifying CSRCS (list of C source files) and ASFILES (list
+# of assembly language source files).
+#
+
+ifndef OBJS
+OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
+ $(addprefix $(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX)))
+endif
+
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+EXTRA_LIBS := $(patsubst -l%,$(DIST)/lib/%.$(LIB_SUFFIX),$(EXTRA_LIBS))
+endif
+
+ALL_TRASH = $(TARGETS) $(OBJS) $(filter-out . .., $(OBJDIR)) LOGS TAGS $(GARBAGE) \
+ $(NOSUCHFILE) \
+ so_locations
+
+ifeq ($(OS_ARCH),OpenVMS)
+ALL_TRASH += $(wildcard *.c*_defines)
+ifdef SHARED_LIBRARY
+VMS_SYMVEC_FILE = $(SHARED_LIBRARY:.$(DLL_SUFFIX)=_symvec.opt)
+VMS_SYMVEC_FILE_MODULE = $(srcdir)/$(LIBRARY_NAME)_symvec.opt
+ALL_TRASH += $(VMS_SYMVEC_FILE)
+endif
+endif
+
+ifndef RELEASE_LIBS_DEST
+RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR)
+endif
+
+ifdef DIRS
+LOOP_OVER_DIRS = \
+ @for d in $(DIRS); do \
+ if test -d $$d; then \
+ set -e; \
+ echo "cd $$d; $(MAKE) $@"; \
+ $(MAKE) -C $$d $@; \
+ set +e; \
+ else \
+ echo "Skipping non-directory $$d..."; \
+ fi; \
+ done
+endif
+
+################################################################################
+
+all:: export
+
+export::
+ +$(LOOP_OVER_DIRS)
+
+libs:: export
+
+install:: export
+
+clean::
+ rm -rf $(OBJS) so_locations $(NOSUCHFILE) $(GARBAGE)
+ +$(LOOP_OVER_DIRS)
+
+clobber::
+ rm -rf $(OBJS) $(TARGETS) $(filter-out . ..,$(OBJDIR)) $(GARBAGE) so_locations $(NOSUCHFILE)
+ +$(LOOP_OVER_DIRS)
+
+realclean clobber_all::
+ rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH)
+ +$(LOOP_OVER_DIRS)
+
+distclean::
+ rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH) $(DIST_GARBAGE)
+ +$(LOOP_OVER_DIRS)
+
+real_install:: $(RELEASE_BINS) $(RELEASE_HEADERS) $(RELEASE_LIBS)
+ifdef RELEASE_BINS
+ $(NSINSTALL) -t -m 0755 $(RELEASE_BINS) $(DESTDIR)$(bindir)
+endif
+ifdef RELEASE_HEADERS
+ $(NSINSTALL) -t -m 0644 $(RELEASE_HEADERS) $(DESTDIR)$(includedir)/$(include_subdir)
+endif
+ifdef RELEASE_LIBS
+ $(NSINSTALL) -t -m 0755 $(RELEASE_LIBS) $(DESTDIR)$(libdir)/$(lib_subdir)
+endif
+ +$(LOOP_OVER_DIRS)
+
+release:: export
+ifdef RELEASE_BINS
+ @echo "Copying executable programs and scripts to release directory"
+ @if test -z "$(BUILD_NUMBER)"; then \
+ echo "BUILD_NUMBER must be defined"; \
+ false; \
+ else \
+ true; \
+ fi
+ @if test ! -d $(RELEASE_BIN_DIR); then \
+ rm -rf $(RELEASE_BIN_DIR); \
+ $(NSINSTALL) -D $(RELEASE_BIN_DIR);\
+ else \
+ true; \
+ fi
+ cp $(RELEASE_BINS) $(RELEASE_BIN_DIR)
+endif
+ifdef RELEASE_LIBS
+ @echo "Copying libraries to release directory"
+ @if test -z "$(BUILD_NUMBER)"; then \
+ echo "BUILD_NUMBER must be defined"; \
+ false; \
+ else \
+ true; \
+ fi
+ @if test ! -d $(RELEASE_LIBS_DEST); then \
+ rm -rf $(RELEASE_LIBS_DEST); \
+ $(NSINSTALL) -D $(RELEASE_LIBS_DEST);\
+ else \
+ true; \
+ fi
+ cp $(RELEASE_LIBS) $(RELEASE_LIBS_DEST)
+endif
+ifdef RELEASE_HEADERS
+ @echo "Copying header files to release directory"
+ @if test -z "$(BUILD_NUMBER)"; then \
+ echo "BUILD_NUMBER must be defined"; \
+ false; \
+ else \
+ true; \
+ fi
+ @if test ! -d $(RELEASE_HEADERS_DEST); then \
+ rm -rf $(RELEASE_HEADERS_DEST); \
+ $(NSINSTALL) -D $(RELEASE_HEADERS_DEST);\
+ else \
+ true; \
+ fi
+ cp $(RELEASE_HEADERS) $(RELEASE_HEADERS_DEST)
+endif
+ +$(LOOP_OVER_DIRS)
+
+alltags:
+ rm -f TAGS tags
+ find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs etags -a
+ find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs ctags -a
+
+$(NFSPWD):
+ cd $(@D); $(MAKE) $(@F)
+
+$(PROGRAM): $(OBJS)
+ @$(MAKE_OBJDIR)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) $(OBJS) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(CC) $(OBJS) -Fe$@ $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS)
+endif
+endif
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+
+$(LIBRARY): $(OBJS)
+ @$(MAKE_OBJDIR)
+ rm -f $@
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(AR) $(subst /,\\,$(OBJS)) $(AR_FLAGS)
+else
+ $(AR) $(AR_FLAGS) $(OBJS) $(AR_EXTRA_ARGS)
+endif
+ $(RANLIB) $@
+
+ifeq ($(OS_TARGET), OS2)
+$(IMPORT_LIBRARY): $(MAPFILE)
+ rm -f $@
+ $(IMPLIB) $@ $(MAPFILE)
+endif
+
+$(SHARED_LIBRARY): $(OBJS) $(RES) $(MAPFILE)
+ @$(MAKE_OBJDIR)
+ rm -f $@
+ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1)
+ echo "#!" > $(OBJDIR)/lib$(LIBRARY_NAME)_syms
+ nm -B -C -g $(OBJS) \
+ | awk '/ [T,D] / {print $$3}' \
+ | sed -e 's/^\.//' \
+ | sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms
+ $(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \
+ -bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS)
+else # AIX 4.1
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(LINK_DLL) -MAP $(DLLBASE) $(DLL_LIBS) $(EXTRA_LIBS) $(OBJS) $(RES)
+else
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(LINK_DLL) $(DLLBASE) $(OBJS) $(OS_LIBS) $(EXTRA_LIBS) $(MAPFILE)
+else # !os2 vacpp
+ifeq ($(OS_TARGET), OpenVMS)
+ @if test ! -f $(VMS_SYMVEC_FILE); then \
+ if test -f $(VMS_SYMVEC_FILE_MODULE); then \
+ echo Creating component options file $(VMS_SYMVEC_FILE); \
+ cp $(VMS_SYMVEC_FILE_MODULE) $(VMS_SYMVEC_FILE); \
+ fi; \
+ fi
+endif # OpenVMS
+ $(MKSHLIB) $(OBJS) $(RES) $(EXTRA_LIBS)
+endif # OS2 vacpp
+endif # WINNT
+endif # AIX 4.1
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+$(RES): $(RESNAME)
+ @$(MAKE_OBJDIR)
+# The resource compiler does not understand the -U option.
+ifdef NS_USE_GCC
+ $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) -o $@ $<
+else
+ $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES) -Fo$@ $<
+endif # GCC
+ @echo $(RES) finished
+endif
+
+$(MAPFILE): $(LIBRARY_NAME).def
+ @$(MAKE_OBJDIR)
+ifeq ($(OS_ARCH),SunOS)
+ grep -v ';-' $< | \
+ sed -e 's,;+,,' -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,;,' > $@
+endif
+ifeq ($(OS_ARCH),OS2)
+ echo LIBRARY $(LIBRARY_NAME)$(LIBRARY_VERSION) INITINSTANCE TERMINSTANCE > $@
+ echo PROTMODE >> $@
+ echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@
+ echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
+ echo EXPORTS >> $@
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ grep -v ';+' $< | grep -v ';-' | \
+ sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' >> $@
+else
+ grep -v ';+' $< | grep -v ';-' | \
+ sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' -e 's,\([\t ]*\),\1_,' | \
+ awk 'BEGIN {ord=1;} { print($$0 " @" ord " RESIDENTNAME"); ord++;}' >> $@
+ $(ADD_TO_DEF_FILE)
+endif
+endif
+
+#
+# Translate source filenames to absolute paths. This is required for
+# debuggers under Windows and OS/2 to find source files automatically.
+#
+
+ifeq ($(OS_ARCH),OS2)
+NEED_ABSOLUTE_PATH = 1
+endif
+
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+NEED_ABSOLUTE_PATH = 1
+endif
+
+ifdef NEED_ABSOLUTE_PATH
+PWD := $(shell pwd)
+abspath = $(if $(findstring :,$(1)),$(1),$(if $(filter /%,$(1)),$(1),$(PWD)/$(1)))
+endif
+
+$(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp
+ @$(MAKE_OBJDIR)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CCC) -Fo$@ -c $(CCCFLAGS) $(call abspath,$<)
+else
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(CCC) -Fo$@ -c $(CCCFLAGS) $(call abspath,$<)
+else
+ifdef NEED_ABSOLUTE_PATH
+ $(CCC) -o $@ -c $(CCCFLAGS) $(call abspath,$<)
+else
+ $(CCC) -o $@ -c $(CCCFLAGS) $<
+endif
+endif
+endif
+
+WCCFLAGS1 = $(subst /,\\,$(CFLAGS))
+WCCFLAGS2 = $(subst -I,-i=,$(WCCFLAGS1))
+WCCFLAGS3 = $(subst -D,-d,$(WCCFLAGS2))
+$(OBJDIR)/%.$(OBJ_SUFFIX): %.c
+ @$(MAKE_OBJDIR)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) $(call abspath,$<)
+else
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(CC) -Fo$@ -c $(CFLAGS) $(call abspath,$<)
+else
+ifdef NEED_ABSOLUTE_PATH
+ $(CC) -o $@ -c $(CFLAGS) $(call abspath,$<)
+else
+ $(CC) -o $@ -c $(CFLAGS) $<
+endif
+endif
+endif
+
+
+$(OBJDIR)/%.$(OBJ_SUFFIX): %.s
+ @$(MAKE_OBJDIR)
+ $(AS) -o $@ $(ASFLAGS) -c $<
+
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+$(OBJDIR)/%.$(OBJ_SUFFIX): %.asm
+ @$(MAKE_OBJDIR)
+ $(AS) -Fdo:./$(OBJDIR) $(ASFLAGS) $<
+endif
+
+%.i: %.c
+ $(CC) -C -E $(CFLAGS) $< > $*.i
+
+%: %.pl
+ rm -f $@; cp $< $@; chmod +x $@
+
+#
+# HACK ALERT
+#
+# The only purpose of this rule is to pass Mozilla's Tinderbox depend
+# builds (http://tinderbox.mozilla.org/showbuilds.cgi). Mozilla's
+# Tinderbox builds NSPR continuously as part of the Mozilla client.
+# Because NSPR's make depend is not implemented, whenever we change
+# an NSPR header file, the depend build does not recompile the NSPR
+# files that depend on the header.
+#
+# This rule makes all the objects depend on a dummy header file.
+# Touch this dummy header file to force the depend build to recompile
+# everything.
+#
+# This rule should be removed when make depend is implemented.
+#
+
+DUMMY_DEPEND_H = $(topsrcdir)/config/prdepend.h
+
+$(filter $(OBJDIR)/%.$(OBJ_SUFFIX),$(OBJS)): $(OBJDIR)/%.$(OBJ_SUFFIX): $(DUMMY_DEPEND_H)
+
+# END OF HACK
+
+################################################################################
+# Special gmake rules.
+################################################################################
+
+#
+# Re-define the list of default suffixes, so gmake won't have to churn through
+# hundreds of built-in suffix rules for stuff we don't need.
+#
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJ_SUFFIX) .c .cpp .s .h .i .pl
+
+#
+# Fake targets. Always run these rules, even if a file/directory with that
+# name already exists.
+#
+.PHONY: all alltags clean export install libs realclean release
+
+#
+# List the target pattern of an implicit rule as a dependency of the
+# special target .PRECIOUS to preserve intermediate files made by
+# implicit rules whose target patterns match that file's name.
+# (See GNU Make documentation, Edition 0.51, May 1996, Sec. 10.4,
+# p. 107.)
+#
+.PRECIOUS: $(OBJDIR)/%.$(OBJ_SUFFIX)
diff --git a/src/libs/xpcom18a4/nsprpub/configure b/src/libs/xpcom18a4/nsprpub/configure
new file mode 100755
index 00000000..2046d79f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/configure
@@ -0,0 +1,6034 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --with-dist-prefix=DIST_PREFIX
+ place build files in DIST_PREFIX [dist]"
+ac_help="$ac_help
+ --with-dist-bindir=DIR build execuatables in DIR [DIST_PREFIX/bin]"
+ac_help="$ac_help
+ --with-dist-includedir=DIR
+ build include files in DIR [DIST_PREFIX/include/nspr]"
+ac_help="$ac_help
+ --with-dist-libdir=DIR build library files in DIR [DIST_PREFIX/lib]"
+ac_help="$ac_help
+ --with-mozilla Compile NSPR with Mozilla support"
+ac_help="$ac_help
+ --enable-optimize(=val) Enable code optimizations (val, ie. -O2) "
+ac_help="$ac_help
+ --disable-debug Do not compile in debugging symbols"
+ac_help="$ac_help
+ --enable-win32-target=\$t
+ Specify win32 flavor. (WIN95 or WINNT)"
+ac_help="$ac_help
+ --enable-debug-rtl Use the MSVC debug runtime library"
+ac_help="$ac_help
+ --enable-n32 Enable n32 ABI support (IRIX only)"
+ac_help="$ac_help
+ --enable-64bit Enable 64-bit support (on certain platforms)"
+ac_help="$ac_help
+ --enable-mdupdate Enable use of certain compilers' mdupdate feature"
+ac_help="$ac_help
+ --enable-macos-target=VER (default=10.1)
+ Set the minimum MacOS version needed at runtime"
+ac_help="$ac_help
+ --enable-strip Enable stripping of shared libs and programs"
+ac_help="$ac_help
+ --with-pthreads Use system pthreads library as thread subsystem"
+ac_help="$ac_help
+ --enable-user-pthreads Build using userland pthreads"
+ac_help="$ac_help
+ --enable-nspr-threads Build using classic nspr threads"
+ac_help="$ac_help
+ --with-bthreads Use system bthreads library as thread subsystem (BeOS only)"
+ac_help="$ac_help
+ --with-native-threads Use native system threads as thread subsystem (Solaris only)"
+ac_help="$ac_help
+ --enable-cplus Enable some c++ api routines"
+ac_help="$ac_help
+ --enable-ipv6 Compile ipv6 support"
+ac_help="$ac_help
+ --enable-boehm Enable the Boehm Garbage Collector"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=config/libc_r.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in ${srcdir}/build/autoconf $srcdir/${srcdir}/build/autoconf; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in ${srcdir}/build/autoconf $srcdir/${srcdir}/build/autoconf" 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:621: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:642: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:660: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+MOD_MAJOR_VERSION=4
+MOD_MINOR_VERSION=5
+MOD_PATCH_VERSION=0
+NSPR_MODNAME=nspr20
+_HAVE_PTHREADS=
+USE_PTHREADS=
+USE_USER_PTHREADS=
+USE_NSPR_THREADS=
+USE_N32=
+USE_64=
+USE_CPLUS=
+USE_IPV6=
+USE_MDUPDATE=
+MACOS_DEPLOYMENT_TARGET=
+_OPTIMIZE_FLAGS=-O
+_DEBUG_FLAGS=-g
+MOZ_DEBUG=1
+MOZ_OPTIMIZE=
+OBJDIR=.
+OBJDIR_NAME=.
+OBJDIR_SUFFIX=OBJ
+NSINSTALL='$(MOD_DEPTH)/config/$(OBJDIR_NAME)/nsinstall'
+NOSUCHFILE=/no-such-file
+LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)'
+LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)'
+CYGWIN_WRAPPER=
+
+RESOLVE_LINK_SYMBOLS=
+
+CFLAGS="${CFLAGS=}"
+CXXFLAGS="${CXXFLAGS=}"
+LDFLAGS="${LDFLAGS=}"
+HOST_CFLAGS="${HOST_CFLAGS=}"
+HOST_LDFLAGS="${HOST_LDFLAGS=}"
+
+case "$target" in
+*-cygwin*|*-mingw*)
+ # Check to see if we are really running in a msvc environemnt
+ _WIN32_MSVC=
+ for ac_prog in cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:727: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CC" && break
+done
+
+ if test "$CC" = "cl"; then
+ echo 'main() { return 0; }' > dummy.c
+ ${CC} -o dummy dummy.c >/dev/null 2>&1
+ if test $? = 0; then
+ _WIN32_MSVC=1
+ CXX=$CC
+ else
+ echo "configure: warning: $(CC) test failed. Using normal feature tests" 1>&2
+ fi
+ rm -f dummy dummy.o dummy.obj dummy.exe dummy.c
+ fi
+ ;;
+*-msvc*)
+ _WIN32_MSVC=1
+ ;;
+*-mks*)
+ _WIN32_MSVC=1
+ ;;
+esac
+
+if test -n "$_WIN32_MSVC"; then
+ SKIP_PATH_CHECKS=1
+ SKIP_COMPILER_CHECKS=1
+ SKIP_LIBRARY_CHECKS=1
+fi
+
+dist_prefix='${MOD_DEPTH}/dist'
+dist_bindir='${dist_prefix}/bin'
+dist_includedir='${dist_prefix}/include/nspr'
+dist_libdir='${dist_prefix}/lib'
+if test "${includedir}" = '${prefix}/include'; then
+ includedir='${prefix}/include/nspr'
+fi
+
+# Check whether --with-dist-prefix or --without-dist-prefix was given.
+if test "${with_dist_prefix+set}" = set; then
+ withval="$with_dist_prefix"
+ dist_prefix=$withval
+fi
+
+
+# Check whether --with-dist-bindir or --without-dist-bindir was given.
+if test "${with_dist_bindir+set}" = set; then
+ withval="$with_dist_bindir"
+ dist_bindir=$withval
+fi
+
+
+# Check whether --with-dist-includedir or --without-dist-includedir was given.
+if test "${with_dist_includedir+set}" = set; then
+ withval="$with_dist_includedir"
+ dist_includedir=$withval
+fi
+
+
+# Check whether --with-dist-libdir or --without-dist-libdir was given.
+if test "${with_dist_libdir+set}" = set; then
+ withval="$with_dist_libdir"
+ dist_libdir=$withval
+fi
+
+
+
+
+
+
+
+# Check whether --with-mozilla or --without-mozilla was given.
+if test "${with_mozilla+set}" = set; then
+ withval="$with_mozilla"
+ if test "$withval" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define MOZILLA_CLIENT 1
+EOF
+
+ MOZILLA_CLIENT=1
+ else
+ MOZILLA_CLIENT=
+ fi
+else
+ if test -n "$MOZILLA_CLIENT"; then
+ cat >> confdefs.h <<\EOF
+#define MOZILLA_CLIENT 1
+EOF
+
+ fi
+fi
+
+
+# Check whether --enable-optimize or --disable-optimize was given.
+if test "${enable_optimize+set}" = set; then
+ enableval="$enable_optimize"
+ if test "$enableval" != "no"; then
+ MOZ_OPTIMIZE=1
+ if test -n "$enableval" && test "$enableval" != "yes"; then
+ _OPTIMIZE_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
+ _SAVE_OPTIMIZE_FLAGS=$_OPTIMIZE_FLAGS
+ fi
+ else
+ MOZ_OPTIMIZE=
+ fi
+fi
+
+
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+ if test "$enableval" = "no"; then
+ MOZ_DEBUG=
+ else
+ MOZ_DEBUG=1
+ fi
+fi
+
+
+# Check whether --enable-win32-target or --disable-win32-target was given.
+if test "${enable_win32_target+set}" = set; then
+ enableval="$enable_win32_target"
+ OS_TARGET=`echo $enableval | tr a-z A-Z`
+else
+ OS_TARGET=
+fi
+
+
+# Check whether --enable-debug-rtl or --disable-debug-rtl was given.
+if test "${enable_debug_rtl+set}" = set; then
+ enableval="$enable_debug_rtl"
+ if test "$enableval" = "yes"; then
+ USE_DEBUG_RTL=1
+ fi
+fi
+
+
+# Check whether --enable-n32 or --disable-n32 was given.
+if test "${enable_n32+set}" = set; then
+ enableval="$enable_n32"
+ if test "$enableval" = "yes"; then
+ USE_N32=1
+ else if test "$enableval" = "no"; then
+ USE_N32=
+ fi
+ fi
+fi
+
+
+# Check whether --enable-64bit or --disable-64bit was given.
+if test "${enable_64bit+set}" = set; then
+ enableval="$enable_64bit"
+ if test "$enableval" = "yes"; then
+ USE_64=1
+ fi
+fi
+
+
+# Check whether --enable-mdupdate or --disable-mdupdate was given.
+if test "${enable_mdupdate+set}" = set; then
+ enableval="$enable_mdupdate"
+ if test "$enableval" = "yes"; then
+ USE_MDUPDATE=1
+ fi
+fi
+
+
+# Check whether --enable-macos-target or --disable-macos-target was given.
+if test "${enable_macos_target+set}" = set; then
+ enableval="$enable_macos_target"
+ MACOS_DEPLOYMENT_TARGET_STR=$enableval
+else
+ MACOS_DEPLOYMENT_TARGET_STR=10.1
+fi
+
+
+case "$target" in
+
+*-aix*)
+ case "${target_os}" in
+ aix3.2*)
+ USE_NSPR_THREADS=1
+ ;;
+ *)
+ USE_PTHREADS=1
+ ;;
+ esac
+ ;;
+
+esac
+
+if test -z "$CC"; then
+ case "$target" in
+
+ *-aix*)
+ if test -z "$USE_NSPR_THREADS"; then
+ CC=xlc_r
+ else
+ CC=xlc
+ fi
+ ;;
+
+ *-hpux*)
+ CC=cc
+ ;;
+
+ *-irix*)
+ CC=cc
+ ;;
+
+ *-openvms*)
+ CC=cc
+ ;;
+
+ *-osf*)
+ CC=cc
+ ;;
+
+ *-solaris*)
+ CC=cc
+ ;;
+
+ esac
+fi
+
+if test -z "$CXX"; then
+ case "$target" in
+
+ *-aix*)
+ if test -z "$USE_NSPR_THREADS"; then
+ CXX=xlC_r
+ else
+ CXX=xlC
+ fi
+ ;;
+
+ *-hpux*)
+ case "${target_os}" in
+ hpux10.30)
+ CXX=aCC
+ ;;
+ hpux11.*)
+ CXX=aCC
+ ;;
+ *)
+ CXX=CC
+ ;;
+ esac
+ ;;
+
+ *-irix*)
+ CXX=CC
+ ;;
+
+ *-openvms*)
+ CXX=cxx
+ ;;
+
+ *-osf*)
+ CXX=cxx
+ ;;
+
+ *-solaris*)
+ CXX=CC
+ ;;
+
+ esac
+fi
+
+if test -z "$SKIP_PATH_CHECKS"; then
+ # Extract the first word of "$WHOAMI whoami", so it can be a program name with args.
+set dummy $WHOAMI whoami; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1025: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_WHOAMI'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$WHOAMI" in
+ /*)
+ ac_cv_path_WHOAMI="$WHOAMI" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_WHOAMI="$WHOAMI" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_WHOAMI="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_WHOAMI" && ac_cv_path_WHOAMI="echo not_whoami"
+ ;;
+esac
+fi
+WHOAMI="$ac_cv_path_WHOAMI"
+if test -n "$WHOAMI"; then
+ echo "$ac_t""$WHOAMI" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+if test -n "$MOZ_DEBUG"; then
+ cat >> confdefs.h <<\EOF
+#define DEBUG 1
+EOF
+
+ DEFINES="$DEFINES -UNDEBUG"
+
+ case "${target_os}" in
+ beos*)
+ DEFINES="$DEFINES -DDEBUG_${USER}"
+ ;;
+ msvc*|mks*|cygwin*|mingw*|os2*)
+ DEFINES="$DEFINES -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`"
+ ;;
+ *)
+ DEFINES="$DEFINES -DDEBUG_`$WHOAMI`"
+ ;;
+ esac
+else
+ cat >> confdefs.h <<\EOF
+#define NDEBUG 1
+EOF
+
+ DEFINES="$DEFINES -UDEBUG"
+fi
+
+if test -z "$SKIP_COMPILER_CHECKS"; then
+if test "$target" != "$host"; then
+ echo "cross compiling from $host to $target"
+ cross_compiling=yes
+
+ _SAVE_CC="$CC"
+ _SAVE_CFLAGS="$CFLAGS"
+ _SAVE_LDFLAGS="$LDFLAGS"
+
+ echo $ac_n "checking for $host compiler""... $ac_c" 1>&6
+echo "configure:1096: checking for $host compiler" >&5
+ for ac_prog in $HOST_CC gcc cc /usr/ucb/cc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1102: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_HOST_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$HOST_CC"; then
+ ac_cv_prog_HOST_CC="$HOST_CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_HOST_CC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+HOST_CC="$ac_cv_prog_HOST_CC"
+if test -n "$HOST_CC"; then
+ echo "$ac_t""$HOST_CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$HOST_CC" && break
+done
+test -n "$HOST_CC" || HOST_CC=""""
+
+ if test -z "$HOST_CC"; then
+ { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+ fi
+ echo "$ac_t""$HOST_CC" 1>&6
+ if test -z "$HOST_CFLAGS"; then
+ HOST_CFLAGS="$CFLAGS"
+ fi
+ if test -z "$HOST_LDFLAGS"; then
+ HOST_LDFLAGS="$LDFLAGS"
+ fi
+
+ CC="$HOST_CC"
+ CFLAGS="$HOST_CFLAGS"
+ LDFLAGS="$HOST_LDFLAGS"
+
+ echo $ac_n "checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1148: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 1150 "configure"
+#include "confdefs.h"
+
+int main() {
+return(0);
+; return 0; }
+EOF
+if { (eval echo configure:1157: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_prog_host_cc_works=1 echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ { echo "configure: error: installation or configuration problem: $host compiler $HOST_CC cannot create executables." 1>&2; exit 1; }
+fi
+rm -f conftest*
+
+ CC=$_SAVE_CC
+ CFLAGS=$_SAVE_CFLAGS
+ LDFLAGS=$_SAVE_LDFLAGS
+
+ for ac_prog in $CC "${target_alias}-gcc" "${target}-gcc"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1177: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CC" && break
+done
+test -n "$CC" || CC="echo"
+
+ unset ac_cv_prog_CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1211: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1241: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1292: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1324: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1335 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1340: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1366: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1371: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1380: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1399: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+ for ac_prog in $CXX "${target_alias}-g++" "${target}-g++"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1435: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="echo"
+
+ unset ac_cv_prog_CXX
+ for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1471: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1503: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1514 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:1519: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cxx_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cxx_cross=no
+ else
+ ac_cv_prog_cxx_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+ { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1545: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:1550: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.C <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1559: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gxx=yes
+else
+ ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:1578: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ ac_cv_prog_cxx_g=yes
+else
+ ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+
+ for ac_prog in $RANLIB "${target_alias}-ranlib" "${target}-ranlib"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1614: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$RANLIB" && break
+done
+test -n "$RANLIB" || RANLIB="echo"
+
+ for ac_prog in $AR "${target_alias}-ar" "${target}-ar"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1649: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AR" && break
+done
+test -n "$AR" || AR="echo"
+
+ for ac_prog in $AS "${target_alias}-as" "${target}-as"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1684: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AS="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AS="$ac_cv_prog_AS"
+if test -n "$AS"; then
+ echo "$ac_t""$AS" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AS" && break
+done
+test -n "$AS" || AS="echo"
+
+ for ac_prog in $LD "${target_alias}-ld" "${target}-ld"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1719: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LD"; then
+ ac_cv_prog_LD="$LD" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LD="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+LD="$ac_cv_prog_LD"
+if test -n "$LD"; then
+ echo "$ac_t""$LD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LD" && break
+done
+test -n "$LD" || LD="echo"
+
+ for ac_prog in $STRIP "${target_alias}-strip" "${target}-strip"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1754: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_STRIP="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+STRIP="$ac_cv_prog_STRIP"
+if test -n "$STRIP"; then
+ echo "$ac_t""$STRIP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$STRIP" && break
+done
+test -n "$STRIP" || STRIP="echo"
+
+ for ac_prog in $WINDRES "${target_alias}-windres" "${target}-windres"
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1789: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_WINDRES'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$WINDRES"; then
+ ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_WINDRES="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+WINDRES="$ac_cv_prog_WINDRES"
+if test -n "$WINDRES"; then
+ echo "$ac_t""$WINDRES" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$WINDRES" && break
+done
+test -n "$WINDRES" || WINDRES="echo"
+
+
+else
+ for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1826: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CXX="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+ echo "$ac_t""$CXX" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1858: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1869 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:1874: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cxx_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cxx_cross=no
+ else
+ ac_cv_prog_cxx_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+ { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1900: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:1905: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.C <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1914: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gxx=yes
+else
+ ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:1933: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+ ac_cv_prog_cxx_g=yes
+else
+ ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+
+ if test "$CXX" = "cl" -a -z "$CC"; then
+ CC=$CXX
+ else
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1970: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2000: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2051: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:2083: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 2094 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:2099: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:2125: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:2130: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:2139: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:2158: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+ fi
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:2191: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 2206 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2212: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 2223 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2229: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 2240 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2246: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2273: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ for ac_prog in as
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2305: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_AS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$AS" in
+ /*)
+ ac_cv_path_AS="$AS" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_AS="$AS" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_AS="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+AS="$ac_cv_path_AS"
+if test -n "$AS"; then
+ echo "$ac_t""$AS" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AS" && break
+done
+test -n "$AS" || AS="$CC"
+
+ for ac_prog in ar
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2346: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$AR" in
+ /*)
+ ac_cv_path_AR="$AR" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_AR="$AR" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_AR="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+AR="$ac_cv_path_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AR" && break
+done
+test -n "$AR" || AR="echo not_ar"
+
+ for ac_prog in ld link
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2387: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$LD" in
+ /*)
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_LD="$LD" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_LD="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ echo "$ac_t""$LD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LD" && break
+done
+test -n "$LD" || LD="echo not_ld"
+
+ for ac_prog in strip
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2428: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$STRIP" in
+ /*)
+ ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_STRIP="$STRIP" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_STRIP="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+STRIP="$ac_cv_path_STRIP"
+if test -n "$STRIP"; then
+ echo "$ac_t""$STRIP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$STRIP" && break
+done
+test -n "$STRIP" || STRIP="echo not_strip"
+
+ for ac_prog in windres
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2469: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_WINDRES'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$WINDRES" in
+ /*)
+ ac_cv_path_WINDRES="$WINDRES" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_WINDRES="$WINDRES" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_WINDRES="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+WINDRES="$ac_cv_path_WINDRES"
+if test -n "$WINDRES"; then
+ echo "$ac_t""$WINDRES" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$WINDRES" && break
+done
+test -n "$WINDRES" || WINDRES="echo not_windres"
+
+ if test -z "$HOST_CC"; then
+ HOST_CC="$CC"
+ fi
+ if test -z "$HOST_CFLAGS"; then
+ HOST_CFLAGS="$CFLAGS"
+ fi
+fi
+
+if test "$GCC" = "yes"; then
+ GNU_CC=1
+fi
+if test "$GXX" = "yes"; then
+ GNU_CXX=1
+fi
+if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then
+ GNU_AS=1
+fi
+rm -f a.out
+
+if test "$cross_compiling" = "yes"; then
+ CROSS_COMPILE=1
+else
+ CROSS_COMPILE=
+fi
+
+echo $ac_n "checking for gcc -pipe support""... $ac_c" 1>&6
+echo "configure:2531: checking for gcc -pipe support" >&5
+if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then
+ echo '#include <stdio.h>' > dummy-hello.c
+ echo 'int main() { printf("Hello World\n"); return 0; }' >> dummy-hello.c
+ ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5
+ cat dummy-hello.s | ${AS} -o dummy-hello.S - 2>&5
+ if test $? = 0; then
+ _res_as_stdin="yes"
+ else
+ _res_as_stdin="no"
+ fi
+ if test "$_res_as_stdin" = "yes"; then
+ _SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -pipe"
+ cat > conftest.$ac_ext <<EOF
+#line 2546 "configure"
+#include "confdefs.h"
+ #include <stdio.h>
+int main() {
+printf("Hello World\n");
+; return 0; }
+EOF
+if { (eval echo configure:2553: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ _res_gcc_pipe="yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ _res_gcc_pipe="no"
+fi
+rm -f conftest*
+ CFLAGS=$_SAVE_CFLAGS
+ fi
+ if test "$_res_as_stdin" = "yes" && test "$_res_gcc_pipe" = "yes"; then
+ _res="yes";
+ CFLAGS="$CFLAGS -pipe"
+ CXXFLAGS="$CXXFLAGS -pipe"
+ else
+ _res="no"
+ fi
+ rm -f dummy-hello.c dummy-hello.s dummy-hello.S dummy-hello a.out
+ echo "$ac_t""$_res" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi # SKIP_COMPILER_CHECKS
+
+if test -z "$SKIP_PATH_CHECKS"; then
+ for ac_prog in perl5 perl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2586: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$PERL" in
+ /*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_PERL="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+PERL="$ac_cv_path_PERL"
+if test -n "$PERL"; then
+ echo "$ac_t""$PERL" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$PERL" && break
+done
+test -n "$PERL" || PERL="echo not_perl"
+
+elif test -z "$PERL"; then
+ PERL=perl
+fi
+
+OBJ_SUFFIX=o
+LIB_SUFFIX=a
+DLL_SUFFIX=so
+ASM_SUFFIX=s
+MKSHLIB='$(LD) $(DSO_LDOPTS) -o $@'
+PR_MD_ASFILES=
+PR_MD_CSRCS=
+PR_MD_ARCH_DIR=unix
+AR_FLAGS='cr $@'
+AS='$(CC)'
+ASFLAGS='$(CFLAGS)'
+
+if test -n "$CROSS_COMPILE"; then
+ OS_ARCH=`echo $target_os | sed -e 's|/|_|g'`
+ OS_RELEASE=
+ OS_TEST="${target_cpu}"
+ case "${target_os}" in
+ linux*) OS_ARCH=Linux ;;
+ solaris*) OS_ARCH=SunOS OS_RELEASE=5 ;;
+ mingw*) OS_ARCH=WINNT ;;
+ esac
+else
+ OS_ARCH=`uname -s | sed -e 's|/|_|g'`
+ OS_RELEASE=`uname -r`
+ OS_TEST=`uname -m`
+fi
+
+if test "$OS_ARCH" = "IRIX64"; then
+ OS_ARCH=IRIX
+fi
+
+if test "$OS_ARCH" = "AIX"; then
+ OS_RELEASE=`uname -v`.`uname -r`
+fi
+
+if test "$OS_ARCH" = "FreeBSD"; then
+ OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+fi
+
+if test "$OS_ARCH" = "Linux"; then
+ OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+ OS_RELEASE=`echo $OS_RELEASE | awk -F\. '{ print $1 "." $2 }'`
+fi
+
+if test "$OS_ARCH" = "OpenVMS"; then
+ OS_RELEASE=`uname -v`
+fi
+
+#######################################################################
+# Master "Core Components" macros for getting the OS target #
+#######################################################################
+
+#
+# Note: OS_TARGET should be specified on the command line for gmake.
+# When OS_TARGET=WIN95 is specified, then a Windows 95 target is built.
+# The difference between the Win95 target and the WinNT target is that
+# the WinNT target uses Windows NT specific features not available
+# in Windows 95. The Win95 target will run on Windows NT, but (supposedly)
+# at lesser performance (the Win95 target uses threads; the WinNT target
+# uses fibers).
+#
+# When OS_TARGET=WIN16 is specified, then a Windows 3.11 (16bit) target
+# is built. See: win16_3.11.mk for lots more about the Win16 target.
+#
+# If OS_TARGET is not specified, it defaults to $(OS_ARCH), i.e., no
+# cross-compilation.
+#
+
+#
+# The following hack allows one to build on a WIN95 machine (as if
+# s/he were cross-compiling on a WINNT host for a WIN95 target).
+# It also accomodates for MKS's uname.exe. If you never intend
+# to do development on a WIN95 machine, you don't need this hack.
+#
+if test "$OS_ARCH" = "WIN95"; then
+ OS_ARCH=WINNT
+ OS_TARGET=WIN95
+elif test "$OS_ARCH" = 'Windows_95'; then
+ OS_ARCH=Windows_NT
+ OS_TARGET=WIN95
+elif test "$OS_ARCH" = 'Windows_98'; then
+ OS_ARCH=Windows_NT
+ OS_TARGET=WIN95
+elif test "`echo $OS_ARCH | egrep -c '^(CYGWIN_9|CYGWIN_ME)' 2>/dev/null`" != 0; then
+ OS_ARCH='CYGWIN_NT-4.0'
+ OS_TARGET=WIN95
+elif test "$OS_ARCH" = "OS_2"; then
+ OS_ARCH=OS2
+ OS_TARGET=OS2
+fi
+
+#
+# On WIN32, we also define the variable CPU_ARCH.
+#
+
+if test "$OS_ARCH" = "WINNT"; then
+ CPU_ARCH=`uname -p`
+ if test "$CPU_ARCH" = "I386"; then
+ CPU_ARCH=x86
+ fi
+elif test "$OS_ARCH" = "Windows_NT"; then
+#
+# If uname -s returns "Windows_NT", we assume that we are using
+# the uname.exe in MKS toolkit.
+#
+# The -r option of MKS uname only returns the major version number.
+# So we need to use its -v option to get the minor version number.
+# Moreover, it doesn't have the -p option, so we need to use uname -m.
+#
+ OS_ARCH=WINNT
+ OS_MINOR_RELEASE=`uname -v`
+ if test "$OS_MINOR_RELEASE" = "00"; then
+ OS_MINOR_RELEASE=0
+ fi
+ OS_RELEASE="${OS_RELEASE}.${OS_MINOR_RELEASE}"
+ CPU_ARCH=`uname -m`
+ #
+ # MKS's uname -m returns "586" on a Pentium machine.
+ #
+ if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ fi
+elif echo "$OS_ARCH" | grep -c CYGWIN_NT >/dev/null; then
+#
+# If uname -s returns "CYGWIN_NT-4.0", we assume that we are using
+# the uname.exe in the Cygwin tools.
+#
+ OS_RELEASE=`echo $OS_ARCH | sed 's|^CYGWIN_NT-||'`
+ OS_ARCH=WINNT
+ CPU_ARCH=`uname -m`
+ #
+ # Cygwin's uname -m returns "i686" on a Pentium Pro machine.
+ #
+ if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ fi
+elif test "$OS_ARCH" = "CYGWIN32_NT"; then
+#
+# Prior to the Beta 20 release, Cygwin was called GNU-Win32.
+# If uname -s returns "CYGWIN32/NT", we assume that we are using
+# the uname.exe in the GNU-Win32 tools.
+#
+ OS_ARCH=WINNT
+ CPU_ARCH=`uname -m`
+ #
+ # GNU-Win32's uname -m returns "i686" on a Pentium Pro machine.
+ #
+ if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ fi
+fi
+
+if test -n "$MOZILLA_CLIENT" && test "$OS_ARCH" = "WINNT"; then
+ OS_TARGET=WIN95
+ if test -n "$MOZ_DEBUG"; then
+ USE_DEBUG_RTL=1
+ fi
+fi
+if test -z "$OS_TARGET"; then
+ OS_TARGET=$OS_ARCH
+fi
+if test "$OS_TARGET" = "WIN95"; then
+ OS_RELEASE="4.0"
+fi
+if test "$OS_TARGET" = "WIN16"; then
+ OS_RELEASE=
+fi
+OS_CONFIG="${OS_TARGET}${OS_RELEASE}"
+
+
+case "$host" in
+*-mingw*|*-cygwin*|*-msvc*|*-mks*)
+ NSINSTALL='$(CYGWIN_WRAPPER) nsinstall'
+ if test `echo "${PATH}" | grep -c \;` = 0; then
+ CYGWIN_WRAPPER='sh $(topsrcdir)/build/cygwin-wrapper'
+ fi
+ ;;
+*-beos*)
+ HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE"
+ ;;
+*os2*)
+ ;;
+*)
+ HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
+ ;;
+esac
+
+case "$target" in
+
+*-aix*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define AIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ DSO_LDOPTS='-brtl -bnortllib -bM:SRE -bnoentry -bexpall -blibpath:/usr/lib:/lib'
+ ac_safe=`echo "sys/atomic_op.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for sys/atomic_op.h""... $ac_c" 1>&6
+echo "configure:2831: checking for sys/atomic_op.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2836 "configure"
+#include "confdefs.h"
+#include <sys/atomic_op.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define AIX_HAVE_ATOMIC_OP_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ case "${target_os}" in
+ aix3.2*)
+ cat >> confdefs.h <<\EOF
+#define AIX_RENAME_SELECT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_NO_LARGE_FILES 1
+EOF
+
+ AIX_LINK_OPTS='-bnso -berok'
+ PR_MD_ASFILES=os_AIX.s
+ ;;
+ aix4.1*)
+ cat >> confdefs.h <<\EOF
+#define AIX_TIMERS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_NO_LARGE_FILES 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define AIX4_1 1
+EOF
+
+ MKSHLIB=
+ DSO_LDOPTS=
+ AIX_LINK_OPTS='-bnso -berok'
+ LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)_shr'
+ LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)_shr'
+ ;;
+ aix4.2*)
+ cat >> confdefs.h <<\EOF
+#define AIX_TIMERS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_OFF64_T 1
+EOF
+
+ AIX_LINK_OPTS='-brtl -bnso -berok'
+ ;;
+ aix4.3*)
+ cat >> confdefs.h <<\EOF
+#define AIX_TIMERS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_OFF64_T 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define AIX4_3_PLUS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_SOCKLEN_T 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ USE_IPV6=1
+ AIX_LINK_OPTS='-brtl -bnso -berok'
+ ;;
+ *)
+ cat >> confdefs.h <<\EOF
+#define AIX_TIMERS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_OFF64_T 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define AIX4_3_PLUS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_SOCKLEN_T 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ USE_IPV6=1
+ AIX_LINK_OPTS='-brtl -bnso -berok'
+ ;;
+ esac
+ CFLAGS="$CFLAGS -qro -qroconst"
+ AIX_WRAP='$(DIST)/lib/aixwrap.o'
+ AIX_TMP='./_aix_tmp.o'
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_aix64.cfg
+ OBJECT_MODE=64
+ else
+ MDCPUCFG_H=_aix32.cfg
+ fi
+ PR_MD_CSRCS=aix.c
+ RESOLVE_LINK_SYMBOLS=1
+ ;;
+
+*-beos*)
+ cat >> confdefs.h <<\EOF
+#define XP_BEOS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define BeOS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define BEOS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ DSO_LDOPTS=-nostart
+ MDCPUCFG_H=_beos.cfg
+ USE_BTHREADS=1
+ PR_MD_ARCH_DIR=beos
+ RESOLVE_LINK_SYMBOLS=1
+ case "${target_cpu}" in
+ i*86)
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS='-gdwarf-2 -O0'
+ MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@'
+ echo $ac_n "checking for gethostbyaddr in -lbind""... $ac_c" 1>&6
+echo "configure:2998: checking for gethostbyaddr in -lbind" >&5
+ac_lib_var=`echo bind'_'gethostbyaddr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lbind $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3006 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyaddr();
+
+int main() {
+gethostbyaddr()
+; return 0; }
+EOF
+if { (eval echo configure:3017: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ OS_LIBS="$OS_LIBS -lbind -lsocket"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+ powerpc)
+ CC=mwcc
+ CCC=mwcc
+ LD=mwld
+ DSO_LDOPTS='-xms -export pragma -init _init_routine_ -term _term_routine_ -lroot -lnet /boot/develop/lib/ppc/glue-noinit.a /boot/develop/lib/ppc/init_term_dyn.o /boot/develop/lib/ppc/start_dyn.o'
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS='-g -O0'
+ ;;
+ esac
+ ;;
+
+*-bsdi*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define BSDI 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NEED_BSDREGEX 1
+EOF
+
+
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ CXXFLAGS="$CXXFLAGS -Wall -Wno-format"
+
+ if echo "$OS_TEST" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ elif echo "$OS_TEST" | grep -c sparc >/dev/null; then
+ CPU_ARCH=sparc
+ fi
+
+ MDCPUCFG_H=_bsdi.cfg
+ PR_MD_CSRCS=bsdi.c
+
+ DSO_LDOPTS=-r
+
+ case "$target_os" in
+ bsdi1.1*)
+ cat >> confdefs.h <<\EOF
+#define _PR_BSDI_JMPBUF_IS_ARRAY 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_STAT_HAS_ONLY_ST_ATIME 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_NEED_H_ERRNO 1
+EOF
+
+ MKSHLIB=
+ DSO_CFLAGS=
+ DSO_LDOPTS=
+ ;;
+
+ bsdi2.1*)
+ cat >> confdefs.h <<\EOF
+#define _PR_TIMESPEC_HAS_TS_SEC 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_BSDI_JMPBUF_IS_ARRAY 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLL 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define USE_DLFCN 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_STAT_HAS_ST_ATIMESPEC 1
+EOF
+
+ PR_MD_ASFILES=os_BSD_OS_386_2.s
+ ;;
+
+ bsdi4.* | bsdi5.*)
+ cat >> confdefs.h <<\EOF
+#define _PR_SELECT_CONST_TIMEVAL 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_BSDI_JMPBUF_IS_STRUCT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLL 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define USE_DLFCN 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_STAT_HAS_ST_ATIMESPEC 1
+EOF
+
+ MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS='-shared -Wl,-soname,$(@:$(OBJDIR)/%.so=%.so)'
+ STRIP="$STRIP -d"
+ case "$target_os" in
+ bsdi4.2* | bsdi4.3* | bsdi5.*)
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETPROTO_R 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETPROTO_R_POINTER 1
+EOF
+
+ ;;
+ esac
+ ;;
+ *)
+ cat >> confdefs.h <<\EOF
+#define _PR_SELECT_CONST_TIMEVAL 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_BSDI_JMPBUF_IS_STRUCT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_DLL 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define USE_DLFCN 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_STAT_HAS_ST_ATIMESPEC 1
+EOF
+
+ ;;
+ esac
+
+ ;;
+
+*-darwin*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define DARWIN 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_FLOCK 1
+EOF
+
+ CFLAGS="$CFLAGS -Wmost -fno-common"
+ if echo $OS_TEST | grep -c 86 2>/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define i386 1
+EOF
+
+ CPU_ARCH=i386
+ else
+ cat >> confdefs.h <<\EOF
+#define ppc 1
+EOF
+
+ CPU_ARCH=ppc
+ fi
+ DSO_LDOPTS='-dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name @executable_path/$@ -headerpad_max_install_names'
+ # Use the standard preprocessor (cpp)
+ CFLAGS="$CFLAGS -no-cpp-precomp"
+ MKSHLIB='$(CC) -arch $(CPU_ARCH) $(DSO_LDOPTS) -o $@'
+ STRIP="$STRIP -x -S"
+ DLL_SUFFIX=dylib
+ USE_PTHREADS=1
+ MDCPUCFG_H=_darwin.cfg
+ PR_MD_CSRCS=darwin.c
+ if test "$CPU_ARCH" = "ppc"; then
+ PR_MD_ASFILES=os_Darwin_ppc.s
+ fi
+
+ # Add Mac OS X support for loading CFM & CFBundle plugins
+ if test -f /System/Library/Frameworks/Carbon.framework/Carbon; then
+ cat >> confdefs.h <<\EOF
+#define XP_MACOSX 1
+EOF
+
+ OS_TARGET=MacOSX
+
+
+ MACOS_VERSION_MAJOR=`echo $MACOS_DEPLOYMENT_TARGET_STR | cut -d . -f 1`
+ MACOS_VERSION_MINOR=`echo $MACOS_DEPLOYMENT_TARGET_STR | cut -d . -f 2`
+ MACOS_VERSION_MICRO=`echo $MACOS_DEPLOYMENT_TARGET_STR | cut -d . -f 3`
+ if test -z "$MACOS_VERSION_MINOR"; then
+ MACOS_VERSION_MINOR=0
+ fi
+ if test -z "$MACOS_VERSION_MICRO"; then
+ MACOS_VERSION_MICRO=0
+ fi
+ MACOS_DEPLOYMENT_TARGET=`printf "%02d%02d%02d" "$MACOS_VERSION_MAJOR" "$MACOS_VERSION_MINOR" "$MACOS_VERSION_MICRO"`
+ cat >> confdefs.h <<EOF
+#define MACOS_DEPLOYMENT_TARGET $MACOS_DEPLOYMENT_TARGET
+EOF
+
+ fi
+
+ # do the right thing for panther SDK support
+ if test "$NEXT_ROOT"; then
+ CFLAGS="-I${NEXT_ROOT}/usr/include $CFLAGS"
+ CXXFLAGS="-I${NEXT_ROOT}/usr/include $CXXFLAGS"
+ fi
+ ;;
+
+*-dgux*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define DGUX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _DGUX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX4A_DRAFT6_SOURCE 1
+EOF
+
+ DSO_LDOPTS=-G
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS=
+ MDCPUCFG_H=_dgux.cfg
+ PR_MD_CSRCS=dgux.c
+ ;;
+
+*-freebsd*)
+ if test -z "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=1
+ fi
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define FREEBSD 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_FLOCK 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_SOCKLEN_T 1
+EOF
+
+ CFLAGS="$CFLAGS $(DSO_CFLAGS) -ansi -Wall"
+ MOZ_OBJFORMAT=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ if test "$MOZ_OBJFORMAT" = "elf"; then
+ DLL_SUFFIX=so
+ else
+ DLL_SUFFIX=so.1.0
+ fi
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
+ MDCPUCFG_H=_freebsd.cfg
+ PR_MD_CSRCS=freebsd.c
+ ;;
+
+*-hpux*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HPUX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _HPUX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define hppa 1
+EOF
+
+ # OSF1 and HPUX report the POLLHUP event for a socket when the
+ # shutdown(SHUT_WR) operation is called for the remote end, even though
+ # the socket is still writeable. Use select(), instead of poll(), to
+ # workaround this problem.
+ cat >> confdefs.h <<\EOF
+#define _PR_POLL_WITH_SELECT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _USE_BIG_FDS 1
+EOF
+
+ DLL_SUFFIX=sl
+ DSO_LDOPTS='-b +h $(notdir $@)'
+ PR_MD_CSRCS=hpux.c
+ if test "$OS_TEST" != "ia64"; then
+ PR_MD_ASFILES=os_HPUX.s
+ fi
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_hpux64.cfg
+ else
+ MDCPUCFG_H=_hpux32.cfg
+ fi
+ if test -z "$GNU_CC"; then
+ CC="$CC -Ae"
+ CXX="$CXX -ext"
+ DSO_CFLAGS=+Z
+ else
+ DSO_CFLAGS=-fPIC
+ fi
+
+ if test -n "$MOZILLA_CLIENT"; then
+ DEFAULT_IMPL_STRATEGY=_EMU
+ fi
+
+ if echo "$OS_RELEASE" | grep ^A.09 >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define _PR_NEED_H_ERRNO 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HPUX9 1
+EOF
+
+ DEFAULT_IMPL_STRATEGY=_EMU
+ USE_NSPR_THREADS=1
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(A.09|B.10)' >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define _PR_NO_LARGE_FILES 1
+EOF
+
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define _PR_NEED_H_ERRNO 1
+EOF
+
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_INT_LOCALTIME_R 1
+EOF
+
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(B.10.30|B.11)' >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ fi
+
+ # HP-UX 11i (B.11.11) or higher
+
+ case "$OS_RELEASE" in
+ [C-Z]*|B.[2-9]*|B.1[2-9]*|B.11.[2-9]*|B.11.1[1-9]*)
+ USE_IPV6=1
+ ;;
+ esac
+
+
+ if test "$OS_RELEASE" = "B.10.01"; then
+ cat >> confdefs.h <<\EOF
+#define HPUX10 1
+EOF
+
+ DEFAULT_IMPL_STRATEGY=_EMU
+ fi
+
+ if test "$OS_RELEASE" = "B.10.10"; then
+ cat >> confdefs.h <<\EOF
+#define HPUX10 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HPUX10_10 1
+EOF
+
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if test "$OS_RELEASE" = "B.10.20"; then
+ cat >> confdefs.h <<\EOF
+#define HPUX10 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HPUX10_20 1
+EOF
+
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS +DAportable +DS1.1"
+ CXXFLAGS="$CXXFLAGS +DAportable +DS1.1"
+ fi
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if test "$OS_RELEASE" = "B.10.30"; then
+ cat >> confdefs.h <<\EOF
+#define HPUX10 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HPUX10_30 1
+EOF
+
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS +DAportable +DS1.1"
+ CXXFLAGS="$CXXFLAGS +DAportable +DS1.1"
+ fi
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if echo "$OS_RELEASE" | grep ^B.11 >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define HPUX10 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HPUX11 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _LARGEFILE64_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_OFF64_T 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ if test -z "$GNU_CC"; then
+ if test -z "$USE_64"; then
+ if test "$OS_TEST" = "ia64"; then
+ CFLAGS="$CFLAGS +DD32"
+ CXXFLAGS="$CXXFLAGS +DD32"
+ else
+ CFLAGS="$CFLAGS +DAportable +DS2.0"
+ CXXFLAGS="$CXXFLAGS +DAportable +DS2.0"
+ fi
+ else
+ if test "$OS_TEST" = "ia64"; then
+ CFLAGS="$CFLAGS +DD64"
+ CXXFLAGS="$CXXFLAGS +DD64"
+ else
+ CFLAGS="$CFLAGS +DA2.0W +DS2.0"
+ CXXFLAGS="$CXXFLAGS +DA2.0W +DS2.0"
+ fi
+ fi
+ fi
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if test "$DEFAULT_IMPL_STRATEGY" = "_EMU"; then
+ USE_NSPR_THREADS=1
+ USE_PTHREADS=
+ USE_USER_THREADS=
+ elif test "$DEFAULT_IMPL_STRATEGY" = "_PTH"; then
+ USE_PTHREADS=1
+ if test "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=
+ fi
+ if test "$USE_USER_PTHREADS"; then
+ USE_PTHREADS=
+ fi
+ fi
+ ;;
+
+*-irix*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define IRIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _SGI_MP_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ PR_MD_CSRCS=irix.c
+ PR_MD_ASFILES=os_Irix.s
+ MKSHLIB='$(LD) $(DSO_LDOPTS) -rdata_shared -shared -soname $(notdir $@) -o $@'
+ STRIP="$STRIP -f"
+ RESOLVE_LINK_SYMBOLS=1
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_irix64.cfg
+ else
+ MDCPUCFG_H=_irix32.cfg
+ fi
+ case "${target_os}" in
+ irix6*)
+ cat >> confdefs.h <<\EOF
+#define IRIX6 1
+EOF
+
+ USE_PTHREADS=1
+ USE_N32=1
+ COMPILER_TAG=_n32
+ IMPL_STRATEGY=_PTH
+ ;;
+ irix5*)
+ cat >> confdefs.h <<\EOF
+#define IRIX5 1
+EOF
+
+ USE_NSPR_THREADS=1
+ ;;
+ *)
+ USE_PTHREADS=1
+ USE_N32=1
+ ;;
+ esac
+ if test "$GNU_CC"; then
+ AS='$(CC) -Wp,-P -x assembler-with-cpp -D_ASM -mips2 $(INCLUDES)'
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ _OPTIMIZE_FLAGS="-O6"
+ else
+ if test -n "$USE_N32"; then
+ AS='as -D_ASM $(INCLUDES) -n32'
+ else
+ AS='as -D_ASM $(INCLUDES)'
+ fi
+ CFLAGS="$CFLAGS -fullwarn -xansi"
+ if test "$USE_N32"; then
+ _OPTIMIZE_FLAGS="-O -OPT:Olimit=4000"
+ else
+ _OPTIMIZE_FLAGS="-O -Olimit 4000"
+ fi
+ if test "$USE_MDUPDATE"; then
+ CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)"
+ fi
+ case "${target}" in
+ *-irix6.*)
+ CFLAGS="$CFLAGS -multigot"
+ DSO_LDOPTS="-no_unresolved"
+ if test "$USE_N32"; then
+ CFLAGS="$CFLAGS -n32 -woff 1209"
+ DSO_LDOPTS="$DSO_LDOPTS -n32"
+ else
+ if test "$USE_64"; then
+ CFLAGS="$CFLAGS -64"
+ else
+ CFLAGS="$CFLAGS -32"
+ fi
+ fi
+ ;;
+ *)
+ CFLAGS="$CFLAGS -xgot"
+ ;;
+ esac
+ fi
+ if test "${target_os}" = "irix5.3"; then
+ cat >> confdefs.h <<\EOF
+#define IRIX5_3 1
+EOF
+
+ fi
+ case "${target_os}" in
+ irix6.5)
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS -mips3"
+ fi
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETPROTO_R 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETPROTO_R_POINTER 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_SGI_PRDA_PROCMASK 1
+EOF
+
+ ;;
+ irix5*)
+ ;;
+ *)
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_SGI_PRDA_PROCMASK 1
+EOF
+
+ ;;
+ esac
+ ;;
+
+*-linux*)
+ if test -z "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=1
+ IMPL_STRATEGY=_PTH
+ fi
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _BSD_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _SVID_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _LARGEFILE64_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define LINUX 1
+EOF
+
+ CFLAGS="$CFLAGS -ansi -Wall"
+ CXXFLAGS="$CXXFLAGS -ansi -Wall"
+ MDCPUCFG_H=_linux.cfg
+ PR_MD_CSRCS=linux.c
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that
+ # combo is not yet good at debugging inlined
+ # functions (even when using DWARF2 as the
+ # debugging format)
+ COMPILER_TAG=_glibc
+ if echo "$OS_TEST" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ else
+ CPU_ARCH=$OS_TEST
+ fi
+ CPU_ARCH_TAG=_${CPU_ARCH}
+ case "${target_cpu}" in
+ alpha)
+ cat >> confdefs.h <<\EOF
+#define _ALPHA_ 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define __alpha 1
+EOF
+
+ CFLAGS="$CFLAGS -mieee"
+ CXXFLAGS="$CXXFLAGS -mieee"
+ ;;
+ i*86)
+ cat >> confdefs.h <<\EOF
+#define i386 1
+EOF
+
+ PR_MD_ASFILES=os_Linux_x86.s
+ ;;
+ ia64)
+ PR_MD_ASFILES=os_Linux_ia64.s
+ ;;
+ x86_64)
+ PR_MD_ASFILES=os_Linux_x86_64.s
+ ;;
+ m68k)
+ CFLAGS="$CFLAGS -m68020-60"
+ CXXFLAGS="$CXXFLAGS -m68020-60"
+ ;;
+ esac
+ ;;
+
+*-mingw*|*-cygwin*|*-msvc*|*-mks*)
+ cat >> confdefs.h <<\EOF
+#define XP_PC 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define WIN32 1
+EOF
+
+ PR_MD_ARCH_DIR=windows
+ RESOLVE_LINK_SYMBOLS=1
+
+ if test -n "$GNU_CC"; then
+ CC="$CC -mno-cygwin"
+ CXX="$CXX -mno-cygwin"
+ DLL_SUFFIX=dll
+ MKSHLIB='$(CC) -shared -Wl,--export-all-symbols -Wl,--out-implib -Wl,$(IMPORT_LIBRARY) $(DLLBASE) -o $(subst $(OBJDIR)/,,$(SHARED_LIBRARY))'
+ RC=$WINDRES
+ # Use temp file for windres (bug 213281)
+ RCFLAGS='-O coff --use-temp-file'
+ else
+ CC=cl
+ CXX=cl
+ LD=link
+ AR='lib -NOLOGO -OUT:"$@"'
+ AR_FLAGS=
+ RANLIB='echo not_ranlib'
+ STRIP='echo not_strip'
+ RC=rc.exe
+ GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb'
+ OBJ_SUFFIX=obj
+ LIB_SUFFIX=lib
+ DLL_SUFFIX=dll
+
+ # Determine compiler version
+ CC_VERSION=`"${CC}" -v 2>&1 | grep Version | sed -e 's|.* Version ||' -e 's| .*||'`
+ _CC_MAJOR_VERSION=`echo $CC_VERSION | awk -F\. '{ print $1 }'`
+ _CC_MINOR_VERSION=`echo $CC_VERSION | awk -F\. '{ print $2 }'`
+ MSC_VER=${_CC_MAJOR_VERSION}${_CC_MINOR_VERSION}
+
+ CFLAGS="$CFLAGS -W3 -nologo -GF -Gy"
+ DLLFLAGS='-OUT:"$@"'
+ _DEBUG_FLAGS=-Z7
+ _OPTIMIZE_FLAGS=-O2
+ if test -z "$MOZ_OPTIMIZE"; then
+ CFLAGS="$CFLAGS -Od"
+ fi
+
+ if test -n "$USE_DEBUG_RTL"; then
+ CFLAGS="$CFLAGS -MDd"
+ else
+ CFLAGS="$CFLAGS -MD"
+ fi
+
+ if test -n "$MOZ_DEBUG"; then
+ cat >> confdefs.h <<\EOF
+#define _DEBUG 1
+EOF
+
+ else
+ DEFINES="$DEFINES -U_DEBUG"
+ fi
+
+ if test -n "$MOZ_OPTIMIZE"; then
+ if test -n "$MOZ_PROFILE"; then
+ _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Z7"
+ fi
+ if test -n "$MOZ_DEBUG_SYMBOLS"; then
+ _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Zi"
+ fi
+ if test -n "$MOZ_PROFILE" -o -n "$MOZ_DEBUG_SYMBOLS"; then
+ DLLFLAGS="$DLLFLAGS -DEBUG -OPT:REF"
+ LDFLAGS="$LDFLAGS -DEBUG -OPT:REF"
+ fi
+ fi
+
+ if test -n "$MOZ_DEBUG"; then
+ DLLFLAGS="$DLLFLAGS -DEBUG -DEBUGTYPE:CV"
+ LDFLAGS="$LDFLAGS -DEBUG -DEBUGTYPE:CV"
+ fi
+
+ if test "$OS_TARGET" = "WINNT"; then
+ CFLAGS="$CFLAGS -GT"
+ if test "$CPU_ARCH" = "x86"; then
+ CFLAGS="$CFLAGS -G5"
+ fi
+ LIBNSPR='$(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ LIBPLC='$(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ else
+ LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ fi
+ fi # GNU_CC
+
+ if test -n "$USE_STATIC_TLS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_USE_STATIC_TLS 1
+EOF
+
+ fi
+
+ if test "$OS_TARGET" = "WINNT"; then
+ cat >> confdefs.h <<\EOF
+#define WINNT 1
+EOF
+
+ else
+ cat >> confdefs.h <<\EOF
+#define WIN95 1
+EOF
+
+ # undefine WINNT as some versions of mingw gcc define it by default
+ DEFINES="$DEFINES -UWINNT"
+ cat >> confdefs.h <<\EOF
+#define _PR_GLOBAL_THREADS_ONLY 1
+EOF
+
+ fi
+
+ if test "$CPU_ARCH" = "x86"; then
+ CPU_ARCH_TAG=
+ else
+ CPU_ARCH_TAG=$CPU_ARCH
+ fi
+
+ if test -n "$USE_DEBUG_RTL"; then
+ OBJDIR_SUFFIX=OBJD
+ fi
+
+ OS_DLLFLAGS="-nologo -DLL -SUBSYSTEM:WINDOWS"
+ if test "$MSC_VER" = "1200" -a -z "$MOZ_DEBUG_SYMBOLS"; then
+ OS_DLLFLAGS="$OS_DLLFLAGS -PDB:NONE"
+ fi
+
+ case "$OS_TARGET" in
+ WINNT)
+ MDCPUCFG_H=_winnt.cfg
+ ;;
+ WIN95)
+ MDCPUCFG_H=_win95.cfg
+ ;;
+ WIN16)
+ MDCPUCFG_H=_win16.cfg
+ ;;
+ *)
+ { echo "configure: error: Missing OS_TARGET for ${target}. Use --enable-win32-target to set." 1>&2; exit 1; }
+ ;;
+ esac
+
+ case "$target_cpu" in
+ i*86)
+ cat >> confdefs.h <<\EOF
+#define _X86_ 1
+EOF
+
+ ;;
+ alpha)
+ cat >> confdefs.h <<\EOF
+#define _ALPHA_ 1
+EOF
+
+ ;;
+ mips)
+ cat >> confdefs.h <<\EOF
+#define _MIPS_ 1
+EOF
+
+ ;;
+ *)
+ cat >> confdefs.h <<\EOF
+#define _CPU_ARCH_NOT_DEFINED 1
+EOF
+
+ ;;
+ esac
+
+ ;;
+
+*-ncr-sysv*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NCR 1
+EOF
+
+ USE_NSPR_THREADS=1
+ if test "$OS_RELEASE" = "2.03"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_STAT_HAS_ST_ATIM 1
+EOF
+
+ else
+ cat >> confdefs.h <<\EOF
+#define _PR_STAT_HAS_ST_ATIM_UNION 1
+EOF
+
+ fi
+
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS -Hnocopyr"
+ CXXFLAGS="$CXXFLAGS -Hnocopyr"
+ else
+ CFLAGS="$CFLAGS -fPIC -Wall"
+ CXXFLAGS="$CXXFLAGS -fPIC -Wall"
+ DSO_LDOPTS=-G
+ fi
+ MDCPUCFG_H=_ncr.cfg
+ PR_MD_CSRCS=ncr.c
+ ;;
+
+mips-nec-sysv*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define __SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NEC 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define nec_ews 1
+EOF
+
+ USE_NSPR_THREADS=1
+ if test -z "$GNU_CC"; then
+ CC='$(NSDEPTH)/build/hcc cc -Xa -KGnum=0 -KOlimit=4000'
+ CXX=g++
+ fi
+ OS_LIBS="$OS_LIBS -lsocket -lnsl -ldl"
+ DSO_LDOPTS=-G
+ MDCPUCFG_H=_nec.cfg
+ PR_MD_CSRCS=nec.c
+ ;;
+
+*-netbsd*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NETBSD 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_FLOCK 1
+EOF
+
+ USE_NSPR_THREADS=1
+ MDCPUCFG_H=_netbsd.cfg
+ PR_MD_CSRCS=netbsd.c
+
+ DSO_CFLAGS='-fPIC -DPIC'
+ CFLAGS="$CFLAGS -ansi -Wall"
+ CXXFLAGS="$CXXFLAGS -ansi -Wall"
+ MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)'
+
+ if test -z "$OBJECT_FMT"; then
+ if echo __ELF__ | ${CC-cc} -E - | grep -q __ELF__ 2>/dev/null; then
+ OBJECT_FMT=a.out
+ DLL_SUFFIX=so.1.0
+ DSO_LDOPTS='-shared'
+ else
+ OBJECT_FMT=ELF
+ DLL_SUFFIX=so
+ DSO_LDOPTS='-shared -Wl,-soname,$(notdir $@)'
+ fi
+ fi
+
+ if test "$LIBRUNPATH"; then
+ DSO_LDOPTS="$DSO_LDOPTS -Wl,-R$LIBRUNPATH"
+ fi
+ ;;
+
+mips-sony-newsos*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SONY 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define __svr4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define __svr4__ 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_SVID_GETTOD 1
+EOF
+
+ USE_NSPR_THREADS=1
+ CFLAGS="$CFLAGS -Xa -fullwarn"
+ CXXFLAGS="$CXXFLAGS -Xa -fullwarn"
+ DSO_LDOPTS=-G
+ MDCPUCFG_H=_sony.cfg
+ PR_MD_CSRCS=sony.c
+ ;;
+
+*-nextstep*|*-openstep*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NEXTSTEP 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_FLOCK 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ CFLAGS="$CFLAGS -Wall -fno-common -traditional-cpp -posix"
+ CXXFLAGS="$CXXFLAGS -Wall -fno-common -traditional-cpp -posix"
+ USE_NSPR_THREADS=1
+ DLL_SUFFIX=dylib
+ MDCPUCFG_H=_nextstep.cfg
+ PR_MD_CSRCS=nextstep.c
+ ;;
+
+
+*-nto*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define NTO 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _QNX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ MDCPUCFG_H=_nto.cfg
+ PR_MD_CSRCS=nto.c
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -Wl,-soname -Wl,$(notdir $@) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS=-shared
+ OS_LIBS="$OS_LIBS -lsocket"
+ _OPTIMIZE_FLAGS="-O1"
+ _DEBUG_FLAGS="-gstabs"
+ ;;
+
+*-openbsd*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define OPENBSD 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_BSD_FLOCK 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_SOCKLEN_T 1
+EOF
+
+ CFLAGS="$CFLAGS -ansi -Wall"
+ CXXFLAGS="$CXXFLAGS -ansi -Wall"
+ DLL_SUFFIX=so.1.0
+ DSO_CFLAGS=-fPIC
+ MDCPUCFG_H=_openbsd.cfg
+ PR_MD_CSRCS=openbsd.c
+ USE_NSPR_THREADS=1
+ DSO_LDOPTS='-shared -fPIC'
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ ;;
+
+*-openvms*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define VMS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define PR_GETIPNODE_NOT_THREADSAFE 1
+EOF
+
+ RESOLVE_LINK_SYMBOLS=1
+ AR_FLAGS='c $@'
+ MDCPUCFG_H=_openvms.cfg
+ PR_MD_CSRCS=openvms.c
+ DSO_LDOPTS='-shared -auto_symvec $(LDFLAGS)'
+ if test -n "$MOZ_DEBUG"; then
+ DSO_LDOPTS="$DSO_LDOPTS $_DEBUG_FLAGS"
+ else
+ DSO_LDOPTS="$DSO_LDOPTS $_OPTIMIZE_FLAGS"
+ fi
+ ;;
+
+*-osf*)
+ SHELL_OVERRIDE="SHELL = /usr/bin/ksh"
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define OSF1 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _REENTRANT 1
+EOF
+
+ # OSF1 and HPUX report the POLLHUP event for a socket when the
+ # shutdown(SHUT_WR) operation is called for the remote end, even though
+ # the socket is still writeable. Use select(), instead of poll(), to
+ # workaround this problem.
+ cat >> confdefs.h <<\EOF
+#define _PR_POLL_WITH_SELECT 1
+EOF
+
+
+ if echo "$OS_RELEASE" | egrep -c '(V2.0|V3.2)' 2>/dev/null ; then
+ USE_NSPR_THREADS=1
+ fi
+
+ if test -z "$GNU_CC"; then
+ CC="$CC -std1 -ieee_with_inexact"
+ if test "$OS_RELEASE" != "V2.0"; then
+ CC="$CC -readonly_strings"
+ fi
+ _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Olimit 4000"
+ ac_safe=`echo "machine/builtins.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for machine/builtins.h""... $ac_c" 1>&6
+echo "configure:4220: checking for machine/builtins.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4225 "configure"
+#include "confdefs.h"
+#include <machine/builtins.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4230: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define OSF1_HAVE_MACHINE_BUILTINS_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ else
+ CFLAGS="$CFLAGS -mieee"
+ CXXFLAGS="$CXXFLAGS -mieee"
+ fi
+
+ if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_INT_LOCALTIME_R 1
+EOF
+
+ else
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ fi
+ if echo $OS_RELEASE | grep -c V4.0 >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define OSF1V4_MAP_PRIVATE_BUG 1
+EOF
+
+ fi
+ DSO_LDOPTS='-shared -all -expect_unresolved "*" -soname $(notdir $@)'
+ MDCPUCFG_H=_osf1.cfg
+ PR_MD_CSRCS=osf1.c
+ ;;
+
+*-qnx*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define QNX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_NEED_H_ERRNO 1
+EOF
+
+ USE_NSPR_THREADS=1
+ MDCPUCFG_H=_qnx.cfg
+ PR_MD_CSRCS=qnx.c
+ ;;
+
+*-*-sco*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SCO 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define sco 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _SVID3 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_NEED_H_ERRNO 1
+EOF
+
+ CC='cc -b elf -KPIC'
+ CXX='$(NSDEPTH)/build/hcpp CC +.cpp +w'
+ USE_NSPR_THREADS=1
+ CPU_ARCH=x86
+ DSO_LDOPTS='-b elf -G'
+ MDCPUCFG_H=_scoos.cfg
+ PR_MD_SRCS=scoos.c
+ ;;
+
+*-sinix*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SNI 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define RELIANTUNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define sinix 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_SVID_GETTOD 1
+EOF
+
+ if echo "$OS_TEST" | grep -c 86 2>/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define i386 1
+EOF
+
+ CPU_ARCH=x86
+ else
+ CPU_ARCH=mips
+ fi
+
+ if test "$GNU_CC"; then
+ AS='$(CC) -x assembler-with-cpp'
+ if test "$CPU_ARCH" = "mips"; then
+ LD=gld
+ fi
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ else
+ AS='/usr/bin/cc'
+ _OPTIMIZE_FLAGS='-O -F Olimit,4000'
+ fi
+
+ DSO_LDOPTS='-G -z defs -h $(@:$(OBJDIR)/%.so=%.so)'
+
+ if test "$OS_RELEASE" = "5.43"; then
+ cat >> confdefs.h <<\EOF
+#define IP_MULTICAST 1
+EOF
+
+ fi
+
+ OS_LIBS="$OS_LIBS -lsocket -lnsl -lresolv -ldl -lc"
+ USE_NSPR_THREADS=1
+ MDCPUCFG_H=_reliantunix.cfg
+ PR_MD_CSRCS=reliantunix.c
+ if test "${OS_ARCH}" = "mips"; then
+ PR_MD_ASFILES=os_ReliantUNIX.s
+ fi
+ ;;
+
+*-sunos*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SUNOS4 1
+EOF
+
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ if test "$USE_MDUPDATE"; then
+ CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)"
+ fi
+ CPU_ARCH=sparc
+ DLL_SUFFIX=so.1.0
+ DSO_LDOPTS=
+ DSO_CFLAGS=-fPIC
+ USE_NSPR_THREADS=1
+ if test "$OS_RELEASE" = "4.1.3_U1"; then
+ _OPTIMIZE_FLAGS=
+ OS_LIBS="$OS_LIBS -lm"
+ fi
+ MDCPUCFG_H=_sunos4.cfg
+ PR_MD_CSRCS=sunos4.c
+ ;;
+
+*-solaris*)
+ if test -z "$USE_USER_THREADS" && test -z "$USE_NATIVE_THREADS"; then
+ USE_PTHREADS=1
+ fi
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define __svr4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define __svr4__ 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SOLARIS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_FCNTL_FILE_LOCKING 1
+EOF
+
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_solaris64.cfg
+ else
+ MDCPUCFG_H=_solaris32.cfg
+ fi
+ PR_MD_CSRCS=solaris.c
+ LD=/usr/ccs/bin/ld
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ RESOLVE_LINK_SYMBOLS=1
+ if test -n "$GNU_CC"; then
+ DSO_CFLAGS=-fPIC
+ if `$CC -print-prog-name=ld` -v 2>&1 | grep -c GNU >/dev/null; then
+ GCC_USE_GNU_LD=1
+ fi
+ DSO_LDOPTS='-shared -Wl,-h,$(notdir $@),-z,combreloc,-z,defs'
+ else
+ DSO_CFLAGS=-KPIC
+ DSO_LDOPTS='-G -h $(notdir $@) -z combreloc -z defs'
+ fi
+ if test -z "$GNU_AS"; then
+ ASFLAGS="$ASFLAGS -Wa,-P"
+ fi
+ if test -n "$GNU_CC"; then
+ CFLAGS="$CFLAGS -Wall"
+ CXXFLAGS="$CXXFLAGS -Wall"
+ if test -n "$USE_MDUPDATE"; then
+ CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)"
+ CXXFLAGS="$CXXFLAGS -MDupdate \$(DEPENDENCIES)"
+ fi
+ else
+ CFLAGS="$CFLAGS -xstrconst"
+ CXXFLAGS="$CXXFLAGS -Qoption cg -xstrconst -features=tmplife"
+ if test -z "$MOZ_OPTIMIZE"; then
+ CFLAGS="$CFLAGS -xs"
+ CXXFLAGS="$CXXFLAGS -xs"
+ fi
+ _OPTIMIZE_FLAGS=-xO4
+ fi
+ if test -n "$USE_64"; then
+ if test -n "$GNU_CC"; then
+ CC="$CC -m64"
+ CXX="$CXX -m64"
+ else
+ CC="$CC -xarch=v9"
+ CXX="$CXX -xarch=v9"
+ fi
+ fi
+ if test "$OS_TEST" = "i86pc"; then
+ cat >> confdefs.h <<\EOF
+#define i386 1
+EOF
+
+ CPU_ARCH_TAG=_$OS_TEST
+ # The default debug format, DWARF (-g), is not supported by gcc
+ # on i386-ANY-sysv4/solaris, but the stabs format is. It is
+ # assumed that the Solaris assembler /usr/ccs/bin/as is used.
+ # If your gcc uses GNU as, you do not need the -Wa,-s option.
+ if test -n "$MOZ_DEBUG" && test -n "$GNU_CC"; then
+ _DEBUG_FLAGS=-gstabs
+ if test -z "$GNU_AS"; then
+ _DEBUG_FLAGS="$_DEBUG_FLAGS -Wa,-s"
+ fi
+ fi
+ fi
+ case "${target_os}" in
+ solaris2.3*)
+ cat >> confdefs.h <<\EOF
+#define _PR_NO_LARGE_FILES 1
+EOF
+
+ ;;
+ solaris2.4*)
+ cat >> confdefs.h <<\EOF
+#define _PR_NO_LARGE_FILES 1
+EOF
+
+ ;;
+ solaris2.5*)
+ cat >> confdefs.h <<\EOF
+#define SOLARIS2_5 1
+EOF
+
+ ;;
+ *)
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_OFF64_T 1
+EOF
+
+ # The lfcompile64(5) man page on Solaris 2.6 says:
+ # For applications that do not wish to conform to the POSIX or
+ # X/Open specifications, the 64-bit transitional interfaces
+ # are available by default. No compile-time flags need to be
+ # set.
+ # But gcc 2.7.2.x fails to define _LARGEFILE64_SOURCE by default.
+ # The native compiler, gcc 2.8.x, and egcs don't have this problem.
+ if test -n "$GNU_CC"; then
+ cat >> confdefs.h <<\EOF
+#define _LARGEFILE64_SOURCE 1
+EOF
+
+ fi
+ ;;
+ esac
+ case "${target_os}" in
+ solaris2.3*)
+ ;;
+ solaris2.4*)
+ ;;
+ solaris2.5*)
+ ;;
+ solaris2.6*)
+ ;;
+ solaris2.7*)
+ ;;
+ *)
+ # Solaris 8 or higher has IPv6.
+ cat >> confdefs.h <<\EOF
+#define _PR_INET6 1
+EOF
+
+ ;;
+ esac
+ if test "$OS_TEST" = "sun4u"; then
+ # 64-bit Solaris requires SPARC V9 architecture, so the following
+ # is not needed.
+ if test -z "$USE_64"; then
+ ULTRASPARC_LIBRARY=nspr_flt
+ fi
+ fi
+ # Purify requires that binaries linked against nspr also
+ # be linked against -lrt (or -lposix4) so add it to OS_LIBS
+ _rev=`uname -r`
+ _librt=`echo $_rev 5.6 | awk '{ if ($1 > $2) print "-lrt"; else print "-lposix4" }'`
+ OS_LIBS="$OS_LIBS $_librt"
+ ;;
+
+*-sco-sysv5*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define UNIXWARE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SVR4 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SYSV 1
+EOF
+
+ USE_NSPR_THREADS=1
+ if echo $OS_RELEASE | grep -c 2.1 2>/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define _PR_NO_LARGE_FILES 1
+EOF
+
+ CC='$(NSDEPTH)/build/hcc cc'
+ CXX='$(NSDEPTH)/build/hcpp CC'
+ MDCPUCFG_H=_unixware.cfg
+ else
+ cat >> confdefs.h <<\EOF
+#define _LARGEFILE64_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_OFF64_T 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_SOCKADDR_LEN 1
+EOF
+
+ MDCPUCFG_H=_unixware7.cfg
+ fi
+ PR_MD_CSRCS=unixware.c
+ DSO_LDOPTS=-G
+ CPU_ARCH=x86
+ ;;
+
+*-os2*)
+ cat >> confdefs.h <<\EOF
+#define XP_OS2 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define XP_PC 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define BSD_SELECT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define TCPV40HDRS 1
+EOF
+
+ LIB_SUFFIX=lib
+ DLL_SUFFIX=dll
+ RC=rc.exe
+ PR_MD_ARCH_DIR=os2
+ PROG_SUFFIX=.exe
+ NSINSTALL=nsinstall
+ MDCPUCFG_H=_os2.cfg
+ RESOLVE_LINK_SYMBOLS=1
+
+ # EMX/GCC build
+ if test -n "$GNU_CC"; then
+ cat >> confdefs.h <<\EOF
+#define XP_OS2_EMX 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define OS2 1
+EOF
+
+ AR=emxomfar
+ AR_FLAGS='r $@'
+ CFLAGS="$CFLAGS -Wall -Zomf"
+ CXXFLAGS="$CFLAGS -Wall -Zomf"
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=
+ DSO_LDOPTS='-Zomf -Zdll -Zmap'
+ LDFLAGS='-Zmap'
+ _OPTIMIZE_FLAGS="-O2 -s"
+ _DEBUG_FLAGS="-g -fno-inline"
+ if test -n "$MOZ_OPTIMIZE"; then
+ DSO_LDOPTS="$DSO_LDOPTS -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA"
+ fi
+ OS_LIBS="-lsocket"
+ IMPLIB='emximp -o'
+ FILTER='emxexp -o'
+
+ # GCC for OS/2 currently predefines these, but we don't want them
+ DEFINES="$DEFINES -Uunix -U__unix -U__unix__"
+
+ # Visual Age C++ build
+ elif test "$VACPP" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define XP_OS2_VACPP 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define OS2 4
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _X86_ 1
+EOF
+
+ OBJ_SUFFIX=obj
+ AS=alp
+ ASFLAGS='-Mb'
+ ASM_SUFFIX=asm
+ AR=-ilib
+ AR_FLAGS='/NOL /NOI /O:$(subst /,\\,$@)'
+ CFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ HOST_CFLAGS="$CFLAGS"
+ OS_CFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ OS_EXE_CFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ CXXFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ OS_LIBS='so32dll.lib tcp32dll.lib'
+ LD='-ilink'
+ MKSHLIB='$(LD) $(DSO_LDOPTS)'
+ IMPLIB='implib -nologo -noignorecase'
+ FILTER='cppfilt -q -B -P'
+ _OPTIMIZE_FLAGS='/O+ /Gl+ /qtune=pentium /qarch=pentium'
+ _DEBUG_FLAGS='/Ti+ '
+ LDFLAGS='/NOL /M /L'
+ DLLFLAGS='/O:$@ /DLL /INC:_dllentry /MAP:$(@:.dll=.map) /L /NOL'
+ EXEFLAGS='/OUT:$@ /PMTYPE:VIO /MAP:$(@:.exe=.map) /L /NOL'
+ if test -n "$MOZ_DEBUG"; then
+ LDFLAGS="$LDFLAGS /DE"
+ DLLFLAGS="$DLLFLAGS /DE"
+ EXEFLAGS="$EXEFLAGS /DE"
+ fi
+ if test -n "$MOZ_OPTIMIZE"; then
+ LDFLAGS="$LDFLAGS /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA"
+ DLLFLAGS="$DLLFLAGS /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA"
+ EXEFLAGS="$EXEFLAGS /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA"
+ fi
+ LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ fi
+ ;;
+
+*)
+ cat >> confdefs.h <<\EOF
+#define XP_UNIX 1
+EOF
+
+ ;;
+
+esac
+
+if test -z "$SKIP_LIBRARY_CHECKS"; then
+
+
+
+case $target in
+*-darwin*)
+ ;;
+*)
+ echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "configure:4765: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4773 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:4784: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_safe=`echo "dlfcn.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for dlfcn.h""... $ac_c" 1>&6
+echo "configure:4801: checking for dlfcn.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4806 "configure"
+#include "confdefs.h"
+#include <dlfcn.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4811: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ OS_LIBS="-ldl $OS_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+esac
+
+
+
+
+if test $ac_cv_prog_gcc = yes; then
+ echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+echo "configure:4844: checking whether ${CC-cc} needs -traditional" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat > conftest.$ac_ext <<EOF
+#line 4850 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+else
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 4868 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+for ac_func in lchown strerror
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:4892: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4897 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+
+# Check whether --enable-strip or --disable-strip was given.
+if test "${enable_strip+set}" = set; then
+ enableval="$enable_strip"
+ if test "$enableval" = "yes"; then
+ ENABLE_STRIP=1
+ fi
+fi
+
+
+case "${target_os}" in
+hpux*)
+if test -z "$GNU_CC"; then
+
+ echo $ac_n "checking for +Olit support""... $ac_c" 1>&6
+echo "configure:4961: checking for +Olit support" >&5
+if eval "test \"`echo '$''{'ac_cv_hpux_usable_olit_option'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_hpux_usable_olit_option=no
+ rm -f conftest*
+ echo 'int main() { return 0; }' | cat > conftest.c
+ ${CC-cc} ${CFLAGS} +Olit=all -o conftest conftest.c > conftest.out 2>&1
+ if test $? -eq 0; then
+ if test -z "`egrep -i '(unrecognize|unknown)' conftest.out`"; then
+ ac_cv_hpux_usable_olit_option=yes
+ fi
+ fi
+ rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_hpux_usable_olit_option" 1>&6
+
+ if test "$ac_cv_hpux_usable_olit_option" = "yes"; then
+ CFLAGS="$CFLAGS +Olit=all"
+ CXXFLAGS="$CXXFLAGS +Olit=all"
+ else
+ CFLAGS="$CFLAGS +ESlit"
+ CXXFLAGS="$CXXFLAGS +ESlit"
+ fi
+fi
+;;
+esac
+
+
+
+
+echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6
+echo "configure:4995: checking for pthread_create in -lpthreads" >&5
+echo "
+ #include <pthread.h>
+ void *foo(void *v) { return v; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ return 0;
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lpthreads $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lpthreads $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ echo "$ac_t""yes" 1>&6
+ _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads"
+ else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
+echo "configure:5017: checking for pthread_create in -lpthread" >&5
+echo "
+ #include <pthread.h>
+ void *foo(void *v) { return v; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ return 0;
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lpthread $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lpthread $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ echo "$ac_t""yes" 1>&6
+ _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread"
+ else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
+echo "configure:5039: checking for pthread_create in -lc_r" >&5
+echo "
+ #include <pthread.h>
+ void *foo(void *v) { return v; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ return 0;
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lc_r $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lc_r $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ echo "$ac_t""yes" 1>&6
+ _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r"
+ else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6
+echo "configure:5061: checking for pthread_create in -lc" >&5
+echo "
+ #include <pthread.h>
+ void *foo(void *v) { return v; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ return 0;
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lc $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -lc $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ echo "$ac_t""yes" 1>&6
+ _HAVE_PTHREADS=1
+
+ else
+ echo "$ac_t""no" 1>&6
+
+ fi
+
+
+ fi
+
+
+ fi
+
+
+ fi
+
+
+# Check whether --with-pthreads or --without-pthreads was given.
+if test "${with_pthreads+set}" = set; then
+ withval="$with_pthreads"
+ if test "$withval" = "yes"; then
+ if test -n "$_HAVE_PTHREADS"; then
+ USE_PTHREADS=1
+ USE_USER_PTHREADS=
+ USE_NSPR_THREADS=
+ else
+ { echo "configure: error: --with-pthreads specified for a system without pthread support " 1>&2; exit 1; };
+ fi
+ else
+ USE_PTHREADS=
+ _PTHREAD_LDFLAGS=
+ fi
+else
+ if test -n "$_HAVE_PTHREADS" && test -z "$USE_USER_PTHREADS" && test -z "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=1
+ USE_USER_PTHREADS=
+ USE_NSPR_THREADS=
+ fi
+fi
+
+
+# Check whether --enable-user-pthreads or --disable-user-pthreads was given.
+if test "${enable_user_pthreads+set}" = set; then
+ enableval="$enable_user_pthreads"
+ if test "$enableval" = "yes"; then
+ if test -n "$_HAVE_PTHREADS"; then
+ USE_PTHREADS=
+ USE_USER_PTHREADS=1
+ USE_NSPR_THREADS=
+ else
+ { echo "configure: error: --enable-user-pthreads specified for a system without pthread support " 1>&2; exit 1; };
+ fi
+ fi
+fi
+
+
+# Check whether --enable-nspr-threads or --disable-nspr-threads was given.
+if test "${enable_nspr_threads+set}" = set; then
+ enableval="$enable_nspr_threads"
+ if test "$enableval" = "yes"; then
+ USE_PTHREADS=
+ USE_USER_PTHREADS=
+ USE_NSPR_THREADS=1
+ fi
+fi
+
+
+case "$target" in
+*-beos*)
+ # Check whether --with-bthreads or --without-bthreads was given.
+if test "${with_bthreads+set}" = set; then
+ withval="$with_bthreads"
+ if test "$withval" = "yes"; then
+ USE_BTHREADS=1
+ USE_USER_PTHREADS=
+ USE_PTHREADS=
+ fi
+fi
+
+ ;;
+
+*-solaris*)
+ # Check whether --with-native-threads or --without-native-threads was given.
+if test "${with_native_threads+set}" = set; then
+ withval="$with_native_threads"
+ if test "$withval" = "yes"; then
+ USE_NATIVE_THREADS=1
+ USE_USER_PTHREADS=
+ USE_PTHREADS=
+ fi
+fi
+
+ ;;
+esac
+
+fi # SKIP_LIBRARY_CHECKS
+
+# Check whether --enable-cplus or --disable-cplus was given.
+if test "${enable_cplus+set}" = set; then
+ enableval="$enable_cplus"
+ if test "$enableval" = "yes"; then
+ USE_CPLUS=1
+ fi
+fi
+
+
+# Check whether --enable-ipv6 or --disable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then
+ enableval="$enable_ipv6"
+ if test "$enableval" = "yes"; then
+ USE_IPV6=1
+ else
+ USE_IPV6=
+ fi
+fi
+
+
+
+# Check whether --enable-boehm or --disable-boehm was given.
+if test "${enable_boehm+set}" = set; then
+ enableval="$enable_boehm"
+ if test "$enableval" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define GC_LEAK_DETECTOR 1
+EOF
+
+ GC_LEAK_DETECTOR=1
+ fi
+fi
+
+
+if test -n "$USE_PTHREADS"; then
+ rm -f conftest*
+ ac_cv_have_dash_pthread=no
+ echo $ac_n "checking whether ${CC-cc} accepts -pthread""... $ac_c" 1>&6
+echo "configure:5213: checking whether ${CC-cc} accepts -pthread" >&5
+ echo 'int main() { return 0; }' | cat > conftest.c
+ ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1
+ if test $? -eq 0; then
+ if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
+ ac_cv_have_dash_pthread=yes
+ case "$target_os" in
+ freebsd*)
+# Freebsd doesn't use -pthread for compiles, it uses them for linking
+ ;;
+ *)
+ CFLAGS="$CFLAGS -pthread"
+ CXXFLAGS="$CXXFLAGS -pthread"
+ ;;
+ esac
+ fi
+ fi
+ rm -f conftest*
+ echo "$ac_t""$ac_cv_have_dash_pthread" 1>&6
+
+ ac_cv_have_dash_pthreads=no
+ if test "$ac_cv_have_dash_pthread" = "no"; then
+ echo $ac_n "checking whether ${CC-cc} accepts -pthreads""... $ac_c" 1>&6
+echo "configure:5236: checking whether ${CC-cc} accepts -pthreads" >&5
+ echo 'int main() { return 0; }' | cat > conftest.c
+ ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1
+ if test $? -eq 0; then
+ if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
+ ac_cv_have_dash_pthreads=yes
+ CFLAGS="$CFLAGS -pthreads"
+ CXXFLAGS="$CXXFLAGS -pthreads"
+ fi
+ fi
+ rm -f conftest*
+ echo "$ac_t""$ac_cv_have_dash_pthreads" 1>&6
+ fi
+
+ case "$target" in
+ *-solaris*)
+ if test "$ac_cv_have_dash_pthreads" = "yes"; then
+ _PTHREAD_LDFLAGS=
+ fi
+ ;;
+ *-freebsd*)
+ cat >> confdefs.h <<\EOF
+#define _REENTRANT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _THREAD_SAFE 1
+EOF
+
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS="-pthread"
+ else
+ _PTHREAD_LDFLAGS="-lc_r"
+ fi
+ ;;
+ *-netbsd*)
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS="-pthread"
+ fi
+ ;;
+ *-bsdi*)
+ cat >> confdefs.h <<\EOF
+#define _THREAD_SAFE 1
+EOF
+
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS=
+ fi
+ ;;
+ *-openbsd*)
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS=-pthread
+ fi
+ ;;
+ *-linux*)
+ cat >> confdefs.h <<\EOF
+#define _REENTRANT 1
+EOF
+
+ ;;
+ esac
+
+else
+ if test -n "$USE_USER_PTHREADS"; then
+ USE_PTHREADS=
+ USE_NSPR_THREADS=
+ else
+ _PTHREAD_LDFLAGS=
+ fi
+fi
+
+case "$target" in
+*-aix*)
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ case "$target_os" in
+ aix4.1*)
+ if test -z "$USE_PTHREADS"; then
+ cat >> confdefs.h <<\EOF
+#define AIX_RENAME_SELECT 1
+EOF
+
+ fi
+ ;;
+ aix4.2*)
+ if test -z "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ fi
+ ;;
+ aix4.3*)
+ if test -z "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ fi
+ if test -n "$USE_PTHREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_THREADSAFE_GETHOST 1
+EOF
+
+ fi
+ ;;
+ *)
+ if test -z "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ fi
+ if test -n "$USE_PTHREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_THREADSAFE_GETHOST 1
+EOF
+
+ fi
+ ;;
+ esac
+ ;;
+*-bsdi*)
+ if test -n "$USE_PTHREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_NEED_PTHREAD_INIT 1
+EOF
+
+ fi
+ ;;
+*-freebsd*)
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ ;;
+*-hpux*)
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ if test "$USE_PTHREADS"; then
+ if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
+ cat >> confdefs.h <<\EOF
+#define _REENTRANT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_DCETHREADS 1
+EOF
+
+ else
+ cat >> confdefs.h <<EOF
+#define _POSIX_C_SOURCE 199506L
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_THREADSAFE_GETHOST 1
+EOF
+
+ fi
+ fi
+ if test "$USE_USER_PTHREADS"; then
+ cat >> confdefs.h <<EOF
+#define _POSIX_C_SOURCE 199506L
+EOF
+
+ fi
+ ;;
+*-irix*)
+ if test "${target_os}" = "irix6.5"; then
+ if test -n "$USE_PTHREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETHOST_R 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETHOST_R_POINTER 1
+EOF
+
+ fi
+ fi
+ ;;
+*-linux*)
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ ;;
+*-mingw*|*-cygwin*|*-msvc*|*-mks*)
+ USE_PTHREADS=
+ _PTHREAD_LDFLAGS=
+ USE_USER_PTHREADS=
+ ;;
+*-netbsd*|*-openbsd*)
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ ;;
+*-osf*)
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ if test -n "$USE_PTHREADS"; then
+ if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_THREADSAFE_GETHOST 1
+EOF
+
+ fi
+ fi
+ ;;
+*-solaris*)
+ if test -n "$USE_NATIVE_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_GLOBAL_THREADS_ONLY 1
+EOF
+
+ else
+ if test -n "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_LOCAL_THREADS_ONLY 1
+EOF
+
+ fi
+ fi
+ if test -z "$USE_NSPR_THREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _REENTRANT 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_POINTER_LOCALTIME_R 1
+EOF
+
+ if test "$OS_TEST" = "i86pc"; then
+ PR_MD_ASFILES=os_SunOS_x86.s
+ else
+ PR_MD_ASFILES=os_SunOS.s
+ if test -n "$USE_64"; then
+ PR_MD_ASFILES="$PR_MD_ASFILES os_SunOS_sparcv9.s"
+ fi
+ fi
+ fi
+ ;;
+*-nto*)
+ if test -n "$USE_PTHREADS"; then
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETHOST_R 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _PR_HAVE_GETHOST_R_POINTER 1
+EOF
+
+ fi
+ ;;
+esac
+
+OS_LIBS="$_PTHREAD_LDFLAGS $OS_LIBS"
+
+if test -n "$_SAVE_OPTIMIZE_FLAGS"; then
+ _OPTIMIZE_FLAGS="$_SAVE_OPTIMIZE_FLAGS"
+fi
+
+if test -n "$MOZ_OPTIMIZE"; then
+ CFLAGS="$CFLAGS $_OPTIMIZE_FLAGS"
+ CXXFLAGS="$CXXFLAGS $_OPTIMIZE_FLAGS"
+fi
+
+if test -n "$MOZ_DEBUG"; then
+ CFLAGS="$CFLAGS $_DEBUG_FLAGS"
+ CXXFLAGS="$CXXFLAGS $_DEBUG_FLAGS"
+fi
+
+if test -n "$MOZ_OPTIMIZE"; then
+ OBJDIR_TAG=_OPT
+else
+ OBJDIR_TAG=_DBG
+fi
+
+if test -n "$USE_64"; then
+ COMPILER_TAG=_64
+fi
+
+RELEASE_OBJDIR_NAME="${OS_CONFIG}${CPU_ARCH_TAG}${COMPILER_TAG}${IMPL_STRATEGY}${OBJDIR_TAG}.${OBJDIR_SUFFIX}"
+
+case "$target_os" in
+mingw*|cygwin*|msvc*|mks*)
+ CC="\$(CYGWIN_WRAPPER) $CC"
+ CXX="\$(CYGWIN_WRAPPER) $CXX"
+ RC="\$(CYGWIN_WRAPPER) $RC"
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+MAKEFILES="
+Makefile
+config/Makefile
+config/autoconf.mk
+config/nsprincl.mk
+config/nsprincl.sh
+config/nspr-config
+lib/Makefile
+lib/ds/Makefile
+lib/libc/Makefile
+lib/libc/include/Makefile
+lib/libc/src/Makefile
+lib/tests/Makefile
+pkg/Makefile
+pkg/linux/Makefile
+pkg/solaris/Makefile
+pkg/solaris/SUNWpr/Makefile
+pkg/solaris/SUNWprx/Makefile
+pr/Makefile
+pr/include/Makefile
+pr/include/md/Makefile
+pr/include/obsolete/Makefile
+pr/include/private/Makefile
+pr/src/Makefile
+pr/src/io/Makefile
+pr/src/linking/Makefile
+pr/src/malloc/Makefile
+pr/src/md/Makefile
+pr/src/md/${PR_MD_ARCH_DIR}/Makefile
+pr/src/memory/Makefile
+pr/src/misc/Makefile
+pr/src/threads/Makefile
+pr/tests/Makefile
+pr/tests/dll/Makefile
+"
+
+
+if test -z "$USE_PTHREADS" && test -z "$USE_BTHREADS"; then
+ MAKEFILES="$MAKEFILES pr/src/threads/combined/Makefile"
+elif test -n "$USE_PTHREADS"; then
+ MAKEFILES="$MAKEFILES pr/src/pthreads/Makefile"
+elif test -n "$USE_BTHREADS"; then
+ MAKEFILES="$MAKEFILES pr/src/bthreads/Makefile"
+fi
+
+if test -n "$USE_CPLUS"; then
+ MAKEFILES="$MAKEFILES pr/src/cplus/Makefile pr/src/cplus/tests/Makefile"
+fi
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "$MAKEFILES" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@CC@%$CC%g
+s%@dist_prefix@%$dist_prefix%g
+s%@dist_bindir@%$dist_bindir%g
+s%@dist_includedir@%$dist_includedir%g
+s%@dist_libdir@%$dist_libdir%g
+s%@WHOAMI@%$WHOAMI%g
+s%@HOST_CC@%$HOST_CC%g
+s%@CXX@%$CXX%g
+s%@RANLIB@%$RANLIB%g
+s%@AR@%$AR%g
+s%@AS@%$AS%g
+s%@LD@%$LD%g
+s%@STRIP@%$STRIP%g
+s%@WINDRES@%$WINDRES%g
+s%@CPP@%$CPP%g
+s%@PERL@%$PERL%g
+s%@SHELL_OVERRIDE@%$SHELL_OVERRIDE%g
+s%@MOZILLA_CLIENT@%$MOZILLA_CLIENT%g
+s%@HOST_CFLAGS@%$HOST_CFLAGS%g
+s%@GNU_CC@%$GNU_CC%g
+s%@GCC_USE_GNU_LD@%$GCC_USE_GNU_LD%g
+s%@MSC_VER@%$MSC_VER%g
+s%@CROSS_COMPILE@%$CROSS_COMPILE%g
+s%@MOZ_OPTIMIZE@%$MOZ_OPTIMIZE%g
+s%@USE_CPLUS@%$USE_CPLUS%g
+s%@USE_IPV6@%$USE_IPV6%g
+s%@USE_N32@%$USE_N32%g
+s%@USE_64@%$USE_64%g
+s%@OBJECT_MODE@%$OBJECT_MODE%g
+s%@GC_LEAK_DETECTOR@%$GC_LEAK_DETECTOR%g
+s%@ENABLE_STRIP@%$ENABLE_STRIP%g
+s%@USE_PTHREADS@%$USE_PTHREADS%g
+s%@USE_BTHREADS@%$USE_BTHREADS%g
+s%@USE_USER_PTHREADS@%$USE_USER_PTHREADS%g
+s%@USE_NATIVE_THREADS@%$USE_NATIVE_THREADS%g
+s%@USE_NSPR_THREADS@%$USE_NSPR_THREADS%g
+s%@LIBNSPR@%$LIBNSPR%g
+s%@LIBPLC@%$LIBPLC%g
+s%@MOD_MAJOR_VERSION@%$MOD_MAJOR_VERSION%g
+s%@MOD_MINOR_VERSION@%$MOD_MINOR_VERSION%g
+s%@MOD_PATCH_VERSION@%$MOD_PATCH_VERSION%g
+s%@NSPR_MODNAME@%$NSPR_MODNAME%g
+s%@MDCPUCFG_H@%$MDCPUCFG_H%g
+s%@PR_MD_CSRCS@%$PR_MD_CSRCS%g
+s%@PR_MD_ASFILES@%$PR_MD_ASFILES%g
+s%@PR_MD_ARCH_DIR@%$PR_MD_ARCH_DIR%g
+s%@CPU_ARCH@%$CPU_ARCH%g
+s%@OBJ_SUFFIX@%$OBJ_SUFFIX%g
+s%@LIB_SUFFIX@%$LIB_SUFFIX%g
+s%@DLL_SUFFIX@%$DLL_SUFFIX%g
+s%@ASM_SUFFIX@%$ASM_SUFFIX%g
+s%@MKSHLIB@%$MKSHLIB%g
+s%@DSO_CFLAGS@%$DSO_CFLAGS%g
+s%@DSO_LDOPTS@%$DSO_LDOPTS%g
+s%@OS_TARGET@%$OS_TARGET%g
+s%@OS_ARCH@%$OS_ARCH%g
+s%@OS_RELEASE@%$OS_RELEASE%g
+s%@OS_TEST@%$OS_TEST%g
+s%@MACOS_DEPLOYMENT_TARGET@%$MACOS_DEPLOYMENT_TARGET%g
+s%@DEFINES@%$DEFINES%g
+s%@AR_FLAGS@%$AR_FLAGS%g
+s%@ASFLAGS@%$ASFLAGS%g
+s%@FILTER@%$FILTER%g
+s%@IMPLIB@%$IMPLIB%g
+s%@OS_LIBS@%$OS_LIBS%g
+s%@RESOLVE_LINK_SYMBOLS@%$RESOLVE_LINK_SYMBOLS%g
+s%@AIX_LINK_OPTS@%$AIX_LINK_OPTS%g
+s%@NOSUCHFILE@%$NOSUCHFILE%g
+s%@MOZ_OBJFORMAT@%$MOZ_OBJFORMAT%g
+s%@ULTRASPARC_LIBRARY@%$ULTRASPARC_LIBRARY%g
+s%@OBJDIR@%$OBJDIR%g
+s%@OBJDIR_NAME@%$OBJDIR_NAME%g
+s%@RELEASE_OBJDIR_NAME@%$RELEASE_OBJDIR_NAME%g
+s%@NSINSTALL@%$NSINSTALL%g
+s%@OPTIMIZER@%$OPTIMIZER%g
+s%@RC@%$RC%g
+s%@RCFLAGS@%$RCFLAGS%g
+s%@DLLFLAGS@%$DLLFLAGS%g
+s%@EXEFLAGS@%$EXEFLAGS%g
+s%@OS_DLLFLAGS@%$OS_DLLFLAGS%g
+s%@CYGWIN_WRAPPER@%$CYGWIN_WRAPPER%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"$MAKEFILES"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+chmod +x config/nspr-config
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/src/libs/xpcom18a4/nsprpub/configure.in b/src/libs/xpcom18a4/nsprpub/configure.in
new file mode 100644
index 00000000..a9ef3c2b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/configure.in
@@ -0,0 +1,2556 @@
+dnl -*- Mode: Autoconf; tab-width: 4; indent-tabs-mode: nil; -*-
+dnl
+dnl The contents of this file are subject to the Mozilla Public
+dnl License Version 1.1 (the "License"); you may not use this file
+dnl except in compliance with the License. You may obtain a copy of
+dnl the License at http://www.mozilla.org/MPL/
+dnl
+dnl Software distributed under the License is distributed on an "AS
+dnl IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+dnl implied. See the License for the specific language governing
+dnl rights and limitations under the License.
+dnl
+dnl The Original Code is the Netscape Portable Runtime (NSPR).
+dnl
+dnl The Initial Developer of the Original Code is Netscape
+dnl Communications Corporation. Portions created by Netscape are
+dnl Copyright (C) 1998o-2000 Netscape Communications Corporation. All
+dnl Rights Reserved.
+dnl
+dnl Contributor(s):
+dnl Christopher Seawood <cls@seawood.org>
+dnl
+dnl Alternatively, the contents of this file may be used under the
+dnl terms of the GNU General Public License Version 2 or later (the
+dnl "GPL"), in which case the provisions of the GPL are applicable
+dnl instead of those above. If you wish to allow use of your
+dnl version of this file only under the terms of the GPL and not to
+dnl allow others to use your version of this file under the MPL,
+dnl indicate your decision by deleting the provisions above and
+dnl replace them with the notice and other provisions required by
+dnl the GPL. If you do not delete the provisions above, a recipient
+dnl may use your version of this file under either the MPL or the
+dnl GPL.
+dnl
+
+AC_PREREQ(2.12)
+AC_INIT(config/libc_r.h)
+
+AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
+AC_CANONICAL_SYSTEM
+
+dnl ========================================================
+dnl = Defaults
+dnl ========================================================
+MOD_MAJOR_VERSION=4
+MOD_MINOR_VERSION=5
+MOD_PATCH_VERSION=0
+NSPR_MODNAME=nspr20
+_HAVE_PTHREADS=
+USE_PTHREADS=
+USE_USER_PTHREADS=
+USE_NSPR_THREADS=
+USE_N32=
+USE_64=
+USE_CPLUS=
+USE_IPV6=
+USE_MDUPDATE=
+MACOS_DEPLOYMENT_TARGET=
+_OPTIMIZE_FLAGS=-O
+_DEBUG_FLAGS=-g
+MOZ_DEBUG=1
+MOZ_OPTIMIZE=
+OBJDIR=.
+OBJDIR_NAME=.
+OBJDIR_SUFFIX=OBJ
+NSINSTALL='$(MOD_DEPTH)/config/$(OBJDIR_NAME)/nsinstall'
+NOSUCHFILE=/no-such-file
+LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)'
+LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)'
+CYGWIN_WRAPPER=
+
+dnl Link in libraries necessary to resolve all symbols for shared libs
+RESOLVE_LINK_SYMBOLS=
+
+dnl ========================================================
+dnl =
+dnl = Dont change the following lines. Doing so breaks:
+dnl =
+dnl = CFLAGS="-foo" ./configure
+dnl =
+dnl ========================================================
+CFLAGS="${CFLAGS=}"
+CXXFLAGS="${CXXFLAGS=}"
+LDFLAGS="${LDFLAGS=}"
+HOST_CFLAGS="${HOST_CFLAGS=}"
+HOST_LDFLAGS="${HOST_LDFLAGS=}"
+
+case "$target" in
+*-cygwin*|*-mingw*)
+ # Check to see if we are really running in a msvc environemnt
+ _WIN32_MSVC=
+ AC_CHECK_PROGS(CC, cl)
+ if test "$CC" = "cl"; then
+ echo 'main() { return 0; }' > dummy.c
+ ${CC} -o dummy dummy.c >/dev/null 2>&1
+ if test $? = 0; then
+ _WIN32_MSVC=1
+ CXX=$CC
+ else
+ AC_MSG_WARN([$(CC) test failed. Using normal feature tests])
+ fi
+ rm -f dummy dummy.o dummy.obj dummy.exe dummy.c
+ fi
+ ;;
+*-msvc*)
+ _WIN32_MSVC=1
+ ;;
+*-mks*)
+ _WIN32_MSVC=1
+ ;;
+esac
+
+if test -n "$_WIN32_MSVC"; then
+ SKIP_PATH_CHECKS=1
+ SKIP_COMPILER_CHECKS=1
+ SKIP_LIBRARY_CHECKS=1
+fi
+
+dnl ========================================================
+dnl =
+dnl = Check options that may affect the compiler
+dnl =
+dnl ========================================================
+dist_prefix='${MOD_DEPTH}/dist'
+dist_bindir='${dist_prefix}/bin'
+dist_includedir='${dist_prefix}/include/nspr'
+dist_libdir='${dist_prefix}/lib'
+if test "${includedir}" = '${prefix}/include'; then
+ includedir='${prefix}/include/nspr'
+fi
+
+AC_ARG_WITH(dist-prefix,
+ [ --with-dist-prefix=DIST_PREFIX
+ place build files in DIST_PREFIX [dist]],
+ dist_prefix=$withval)
+
+AC_ARG_WITH(dist-bindir,
+ [ --with-dist-bindir=DIR build execuatables in DIR [DIST_PREFIX/bin]],
+ dist_bindir=$withval)
+
+AC_ARG_WITH(dist-includedir,
+ [ --with-dist-includedir=DIR
+ build include files in DIR [DIST_PREFIX/include/nspr]],
+ dist_includedir=$withval)
+
+AC_ARG_WITH(dist-libdir,
+ [ --with-dist-libdir=DIR build library files in DIR [DIST_PREFIX/lib]],
+ dist_libdir=$withval)
+
+AC_SUBST(dist_prefix)
+AC_SUBST(dist_bindir)
+AC_SUBST(dist_includedir)
+AC_SUBST(dist_libdir)
+
+dnl Check if NSPR is being compiled for Mozilla
+dnl Let --with-arg override environment setting
+dnl
+AC_ARG_WITH(mozilla,
+ [ --with-mozilla Compile NSPR with Mozilla support],
+ [ if test "$withval" = "yes"; then
+ AC_DEFINE(MOZILLA_CLIENT)
+ MOZILLA_CLIENT=1
+ else
+ MOZILLA_CLIENT=
+ fi],
+ [ if test -n "$MOZILLA_CLIENT"; then
+ AC_DEFINE(MOZILLA_CLIENT)
+ fi])
+
+AC_ARG_ENABLE(optimize,
+ [ --enable-optimize(=val) Enable code optimizations (val, ie. -O2) ],
+ [ if test "$enableval" != "no"; then
+ MOZ_OPTIMIZE=1
+ if test -n "$enableval" && test "$enableval" != "yes"; then
+ _OPTIMIZE_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
+ _SAVE_OPTIMIZE_FLAGS=$_OPTIMIZE_FLAGS
+ fi
+ else
+ MOZ_OPTIMIZE=
+ fi ])
+
+AC_ARG_ENABLE(debug,
+ [ --disable-debug Do not compile in debugging symbols],
+ [ if test "$enableval" = "no"; then
+ MOZ_DEBUG=
+ else
+ MOZ_DEBUG=1
+ fi])
+
+AC_ARG_ENABLE(win32-target,
+ [ --enable-win32-target=\$t
+ Specify win32 flavor. (WIN95 or WINNT)],
+ OS_TARGET=`echo $enableval | tr a-z A-Z`,
+ OS_TARGET=)
+
+AC_ARG_ENABLE(debug-rtl,
+ [ --enable-debug-rtl Use the MSVC debug runtime library],
+ [ if test "$enableval" = "yes"; then
+ USE_DEBUG_RTL=1
+ fi ])
+
+AC_ARG_ENABLE(n32,
+ [ --enable-n32 Enable n32 ABI support (IRIX only)],
+ [ if test "$enableval" = "yes"; then
+ USE_N32=1
+ else if test "$enableval" = "no"; then
+ USE_N32=
+ fi
+ fi ])
+
+AC_ARG_ENABLE(64bit,
+ [ --enable-64bit Enable 64-bit support (on certain platforms)],
+ [ if test "$enableval" = "yes"; then
+ USE_64=1
+ fi ])
+
+AC_ARG_ENABLE(mdupdate,
+ [ --enable-mdupdate Enable use of certain compilers' mdupdate feature],
+ [ if test "$enableval" = "yes"; then
+ USE_MDUPDATE=1
+ fi ])
+
+AC_ARG_ENABLE(macos-target,
+ [ --enable-macos-target=VER (default=10.1)
+ Set the minimum MacOS version needed at runtime],
+ [MACOS_DEPLOYMENT_TARGET_STR=$enableval],
+ [MACOS_DEPLOYMENT_TARGET_STR=10.1])
+
+dnl ========================================================
+dnl =
+dnl = Set the threading model
+dnl =
+dnl ========================================================
+case "$target" in
+
+*-aix*)
+ case "${target_os}" in
+ aix3.2*)
+ USE_NSPR_THREADS=1
+ ;;
+ *)
+ USE_PTHREADS=1
+ ;;
+ esac
+ ;;
+
+esac
+
+dnl ========================================================
+dnl =
+dnl = Set the default C compiler
+dnl =
+dnl ========================================================
+if test -z "$CC"; then
+ case "$target" in
+
+ *-aix*)
+ if test -z "$USE_NSPR_THREADS"; then
+ CC=xlc_r
+ else
+ CC=xlc
+ fi
+ ;;
+
+ *-hpux*)
+ CC=cc
+ ;;
+
+ *-irix*)
+ CC=cc
+ ;;
+
+ *-openvms*)
+ CC=cc
+ ;;
+
+ *-osf*)
+ CC=cc
+ ;;
+
+ *-solaris*)
+ CC=cc
+ ;;
+
+ esac
+fi
+
+dnl ========================================================
+dnl =
+dnl = Set the default C++ compiler
+dnl =
+dnl ========================================================
+if test -z "$CXX"; then
+ case "$target" in
+
+ *-aix*)
+ if test -z "$USE_NSPR_THREADS"; then
+ CXX=xlC_r
+ else
+ CXX=xlC
+ fi
+ ;;
+
+ *-hpux*)
+ case "${target_os}" in
+ hpux10.30)
+ CXX=aCC
+ ;;
+ hpux11.*)
+ CXX=aCC
+ ;;
+ *)
+ CXX=CC
+ ;;
+ esac
+ ;;
+
+ *-irix*)
+ CXX=CC
+ ;;
+
+ *-openvms*)
+ CXX=cxx
+ ;;
+
+ *-osf*)
+ CXX=cxx
+ ;;
+
+ *-solaris*)
+ CXX=CC
+ ;;
+
+ esac
+fi
+
+if test -z "$SKIP_PATH_CHECKS"; then
+ AC_PATH_PROG(WHOAMI, $WHOAMI whoami, echo not_whoami)
+fi
+
+if test -n "$MOZ_DEBUG"; then
+ AC_DEFINE(DEBUG)
+ DEFINES="$DEFINES -UNDEBUG"
+
+ case "${target_os}" in
+ beos*)
+ DEFINES="$DEFINES -DDEBUG_${USER}"
+ ;;
+ msvc*|mks*|cygwin*|mingw*|os2*)
+ DEFINES="$DEFINES -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`"
+ ;;
+ *)
+ DEFINES="$DEFINES -DDEBUG_`$WHOAMI`"
+ ;;
+ esac
+else
+ AC_DEFINE(NDEBUG)
+ DEFINES="$DEFINES -UDEBUG"
+fi
+
+if test -z "$SKIP_COMPILER_CHECKS"; then
+dnl ========================================================
+dnl Checks for compilers.
+dnl ========================================================
+if test "$target" != "$host"; then
+ echo "cross compiling from $host to $target"
+ cross_compiling=yes
+
+ _SAVE_CC="$CC"
+ _SAVE_CFLAGS="$CFLAGS"
+ _SAVE_LDFLAGS="$LDFLAGS"
+
+ AC_MSG_CHECKING([for $host compiler])
+ AC_CHECK_PROGS(HOST_CC, $HOST_CC gcc cc /usr/ucb/cc, "")
+ if test -z "$HOST_CC"; then
+ AC_MSG_ERROR([no acceptable cc found in \$PATH])
+ fi
+ AC_MSG_RESULT([$HOST_CC])
+ if test -z "$HOST_CFLAGS"; then
+ HOST_CFLAGS="$CFLAGS"
+ fi
+ if test -z "$HOST_LDFLAGS"; then
+ HOST_LDFLAGS="$LDFLAGS"
+ fi
+
+ CC="$HOST_CC"
+ CFLAGS="$HOST_CFLAGS"
+ LDFLAGS="$HOST_LDFLAGS"
+
+ AC_MSG_CHECKING([whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works])
+ AC_TRY_COMPILE([], [return(0);],
+ [ac_cv_prog_host_cc_works=1 AC_MSG_RESULT([yes])],
+ AC_MSG_ERROR([installation or configuration problem: $host compiler $HOST_CC cannot create executables.]) )
+
+ CC=$_SAVE_CC
+ CFLAGS=$_SAVE_CFLAGS
+ LDFLAGS=$_SAVE_LDFLAGS
+
+ AC_CHECK_PROGS(CC, $CC "${target_alias}-gcc" "${target}-gcc", echo)
+ unset ac_cv_prog_CC
+ AC_PROG_CC
+ AC_CHECK_PROGS(CXX, $CXX "${target_alias}-g++" "${target}-g++", echo)
+ unset ac_cv_prog_CXX
+ AC_PROG_CXX
+ AC_CHECK_PROGS(RANLIB, $RANLIB "${target_alias}-ranlib" "${target}-ranlib", echo)
+ AC_CHECK_PROGS(AR, $AR "${target_alias}-ar" "${target}-ar", echo)
+ AC_CHECK_PROGS(AS, $AS "${target_alias}-as" "${target}-as", echo)
+ AC_CHECK_PROGS(LD, $LD "${target_alias}-ld" "${target}-ld", echo)
+ AC_CHECK_PROGS(STRIP, $STRIP "${target_alias}-strip" "${target}-strip", echo)
+ AC_CHECK_PROGS(WINDRES, $WINDRES "${target_alias}-windres" "${target}-windres", echo)
+
+else
+ AC_PROG_CXX
+ if test "$CXX" = "cl" -a -z "$CC"; then
+ CC=$CXX
+ else
+ AC_PROG_CC
+ fi
+ AC_PROG_CPP
+ AC_PROG_RANLIB
+ AC_PATH_PROGS(AS, as, $CC)
+ AC_PATH_PROGS(AR, ar, echo not_ar)
+ AC_PATH_PROGS(LD, ld link, echo not_ld)
+ AC_PATH_PROGS(STRIP, strip, echo not_strip)
+ AC_PATH_PROGS(WINDRES, windres, echo not_windres)
+ if test -z "$HOST_CC"; then
+ HOST_CC="$CC"
+ fi
+ if test -z "$HOST_CFLAGS"; then
+ HOST_CFLAGS="$CFLAGS"
+ fi
+fi
+
+if test "$GCC" = "yes"; then
+ GNU_CC=1
+fi
+if test "$GXX" = "yes"; then
+ GNU_CXX=1
+fi
+if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then
+ GNU_AS=1
+fi
+rm -f a.out
+
+if test "$cross_compiling" = "yes"; then
+ CROSS_COMPILE=1
+else
+ CROSS_COMPILE=
+fi
+
+dnl ========================================================
+dnl Check for gcc -pipe support
+dnl ========================================================
+AC_MSG_CHECKING([for gcc -pipe support])
+if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then
+ echo '#include <stdio.h>' > dummy-hello.c
+ echo 'int main() { printf("Hello World\n"); return 0; }' >> dummy-hello.c
+ ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5
+ cat dummy-hello.s | ${AS} -o dummy-hello.S - 2>&5
+ if test $? = 0; then
+ _res_as_stdin="yes"
+ else
+ _res_as_stdin="no"
+ fi
+ if test "$_res_as_stdin" = "yes"; then
+ _SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -pipe"
+ AC_TRY_COMPILE( [ #include <stdio.h> ],
+ [printf("Hello World\n");],
+ [_res_gcc_pipe="yes"],
+ [_res_gcc_pipe="no"] )
+ CFLAGS=$_SAVE_CFLAGS
+ fi
+ if test "$_res_as_stdin" = "yes" && test "$_res_gcc_pipe" = "yes"; then
+ _res="yes";
+ CFLAGS="$CFLAGS -pipe"
+ CXXFLAGS="$CXXFLAGS -pipe"
+ else
+ _res="no"
+ fi
+ rm -f dummy-hello.c dummy-hello.s dummy-hello.S dummy-hello a.out
+ AC_MSG_RESULT([$_res])
+else
+ AC_MSG_RESULT([no])
+fi
+
+fi # SKIP_COMPILER_CHECKS
+
+dnl ========================================================
+dnl Checks for programs.
+dnl ========================================================
+if test -z "$SKIP_PATH_CHECKS"; then
+ AC_PATH_PROGS(PERL, perl5 perl, echo not_perl)
+elif test -z "$PERL"; then
+ PERL=perl
+fi
+
+dnl ========================================================
+dnl Default platform specific options
+dnl ========================================================
+OBJ_SUFFIX=o
+LIB_SUFFIX=a
+DLL_SUFFIX=so
+ASM_SUFFIX=s
+MKSHLIB='$(LD) $(DSO_LDOPTS) -o $@'
+PR_MD_ASFILES=
+PR_MD_CSRCS=
+PR_MD_ARCH_DIR=unix
+AR_FLAGS='cr $@'
+AS='$(CC)'
+ASFLAGS='$(CFLAGS)'
+
+if test -n "$CROSS_COMPILE"; then
+ OS_ARCH=`echo $target_os | sed -e 's|/|_|g'`
+ OS_RELEASE=
+ OS_TEST="${target_cpu}"
+ case "${target_os}" in
+ linux*) OS_ARCH=Linux ;;
+ solaris*) OS_ARCH=SunOS OS_RELEASE=5 ;;
+ mingw*) OS_ARCH=WINNT ;;
+ esac
+else
+ OS_ARCH=`uname -s | sed -e 's|/|_|g'`
+ OS_RELEASE=`uname -r`
+ OS_TEST=`uname -m`
+fi
+
+if test "$OS_ARCH" = "IRIX64"; then
+ OS_ARCH=IRIX
+fi
+
+if test "$OS_ARCH" = "AIX"; then
+ OS_RELEASE=`uname -v`.`uname -r`
+fi
+
+if test "$OS_ARCH" = "FreeBSD"; then
+ OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+fi
+
+if test "$OS_ARCH" = "Linux"; then
+ OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'`
+ OS_RELEASE=`echo $OS_RELEASE | awk -F\. '{ print $1 "." $2 }'`
+fi
+
+if test "$OS_ARCH" = "OpenVMS"; then
+ OS_RELEASE=`uname -v`
+fi
+
+#######################################################################
+# Master "Core Components" macros for getting the OS target #
+#######################################################################
+
+#
+# Note: OS_TARGET should be specified on the command line for gmake.
+# When OS_TARGET=WIN95 is specified, then a Windows 95 target is built.
+# The difference between the Win95 target and the WinNT target is that
+# the WinNT target uses Windows NT specific features not available
+# in Windows 95. The Win95 target will run on Windows NT, but (supposedly)
+# at lesser performance (the Win95 target uses threads; the WinNT target
+# uses fibers).
+#
+# When OS_TARGET=WIN16 is specified, then a Windows 3.11 (16bit) target
+# is built. See: win16_3.11.mk for lots more about the Win16 target.
+#
+# If OS_TARGET is not specified, it defaults to $(OS_ARCH), i.e., no
+# cross-compilation.
+#
+
+#
+# The following hack allows one to build on a WIN95 machine (as if
+# s/he were cross-compiling on a WINNT host for a WIN95 target).
+# It also accomodates for MKS's uname.exe. If you never intend
+# to do development on a WIN95 machine, you don't need this hack.
+#
+if test "$OS_ARCH" = "WIN95"; then
+ OS_ARCH=WINNT
+ OS_TARGET=WIN95
+elif test "$OS_ARCH" = 'Windows_95'; then
+ OS_ARCH=Windows_NT
+ OS_TARGET=WIN95
+elif test "$OS_ARCH" = 'Windows_98'; then
+ OS_ARCH=Windows_NT
+ OS_TARGET=WIN95
+elif test "`echo $OS_ARCH | egrep -c '^(CYGWIN_9|CYGWIN_ME)' 2>/dev/null`" != 0; then
+ OS_ARCH='CYGWIN_NT-4.0'
+ OS_TARGET=WIN95
+elif test "$OS_ARCH" = "OS_2"; then
+ OS_ARCH=OS2
+ OS_TARGET=OS2
+fi
+
+#
+# On WIN32, we also define the variable CPU_ARCH.
+#
+
+if test "$OS_ARCH" = "WINNT"; then
+ CPU_ARCH=`uname -p`
+ if test "$CPU_ARCH" = "I386"; then
+ CPU_ARCH=x86
+ fi
+elif test "$OS_ARCH" = "Windows_NT"; then
+#
+# If uname -s returns "Windows_NT", we assume that we are using
+# the uname.exe in MKS toolkit.
+#
+# The -r option of MKS uname only returns the major version number.
+# So we need to use its -v option to get the minor version number.
+# Moreover, it doesn't have the -p option, so we need to use uname -m.
+#
+ OS_ARCH=WINNT
+ OS_MINOR_RELEASE=`uname -v`
+ if test "$OS_MINOR_RELEASE" = "00"; then
+ OS_MINOR_RELEASE=0
+ fi
+ OS_RELEASE="${OS_RELEASE}.${OS_MINOR_RELEASE}"
+ CPU_ARCH=`uname -m`
+ #
+ # MKS's uname -m returns "586" on a Pentium machine.
+ #
+ if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ fi
+elif echo "$OS_ARCH" | grep -c CYGWIN_NT >/dev/null; then
+#
+# If uname -s returns "CYGWIN_NT-4.0", we assume that we are using
+# the uname.exe in the Cygwin tools.
+#
+ OS_RELEASE=`echo $OS_ARCH | sed 's|^CYGWIN_NT-||'`
+ OS_ARCH=WINNT
+ CPU_ARCH=`uname -m`
+ #
+ # Cygwin's uname -m returns "i686" on a Pentium Pro machine.
+ #
+ if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ fi
+elif test "$OS_ARCH" = "CYGWIN32_NT"; then
+#
+# Prior to the Beta 20 release, Cygwin was called GNU-Win32.
+# If uname -s returns "CYGWIN32/NT", we assume that we are using
+# the uname.exe in the GNU-Win32 tools.
+#
+ OS_ARCH=WINNT
+ CPU_ARCH=`uname -m`
+ #
+ # GNU-Win32's uname -m returns "i686" on a Pentium Pro machine.
+ #
+ if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ fi
+fi
+
+if test -n "$MOZILLA_CLIENT" && test "$OS_ARCH" = "WINNT"; then
+ OS_TARGET=WIN95
+ if test -n "$MOZ_DEBUG"; then
+ USE_DEBUG_RTL=1
+ fi
+fi
+if test -z "$OS_TARGET"; then
+ OS_TARGET=$OS_ARCH
+fi
+if test "$OS_TARGET" = "WIN95"; then
+ OS_RELEASE="4.0"
+fi
+if test "$OS_TARGET" = "WIN16"; then
+ OS_RELEASE=
+fi
+OS_CONFIG="${OS_TARGET}${OS_RELEASE}"
+
+dnl ========================================================
+
+dnl ========================================================
+dnl Override of system specific host options
+dnl ========================================================
+case "$host" in
+*-mingw*|*-cygwin*|*-msvc*|*-mks*)
+ NSINSTALL='$(CYGWIN_WRAPPER) nsinstall'
+ if test `echo "${PATH}" | grep -c \;` = 0; then
+ CYGWIN_WRAPPER='sh $(topsrcdir)/build/cygwin-wrapper'
+ fi
+ ;;
+*-beos*)
+ HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE"
+ ;;
+*os2*)
+ ;;
+*)
+ HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
+ ;;
+esac
+
+dnl ========================================================
+dnl Override of system specific target options
+dnl ========================================================
+case "$target" in
+
+*-aix*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(AIX)
+ AC_DEFINE(SYSV)
+ DSO_LDOPTS='-brtl -bnortllib -bM:SRE -bnoentry -bexpall -blibpath:/usr/lib:/lib'
+ AC_CHECK_HEADER(sys/atomic_op.h, AC_DEFINE(AIX_HAVE_ATOMIC_OP_H))
+ case "${target_os}" in
+ aix3.2*)
+ AC_DEFINE(AIX_RENAME_SELECT)
+ AC_DEFINE(_PR_NO_LARGE_FILES)
+ AIX_LINK_OPTS='-bnso -berok'
+ PR_MD_ASFILES=os_AIX.s
+ ;;
+ aix4.1*)
+ AC_DEFINE(AIX_TIMERS)
+ AC_DEFINE(_PR_NO_LARGE_FILES)
+ AC_DEFINE(AIX4_1)
+ MKSHLIB=
+ DSO_LDOPTS=
+ AIX_LINK_OPTS='-bnso -berok'
+ LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)_shr'
+ LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)_shr'
+ ;;
+ aix4.2*)
+ AC_DEFINE(AIX_TIMERS)
+ AC_DEFINE(_PR_HAVE_OFF64_T)
+ AIX_LINK_OPTS='-brtl -bnso -berok'
+ ;;
+ aix4.3*)
+ AC_DEFINE(AIX_TIMERS)
+ AC_DEFINE(_PR_HAVE_OFF64_T)
+ AC_DEFINE(AIX4_3_PLUS)
+ AC_DEFINE(HAVE_SOCKLEN_T)
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ USE_IPV6=1
+ AIX_LINK_OPTS='-brtl -bnso -berok'
+ ;;
+ *)
+ AC_DEFINE(AIX_TIMERS)
+ AC_DEFINE(_PR_HAVE_OFF64_T)
+ AC_DEFINE(AIX4_3_PLUS)
+ AC_DEFINE(HAVE_SOCKLEN_T)
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ USE_IPV6=1
+ AIX_LINK_OPTS='-brtl -bnso -berok'
+ ;;
+ esac
+ CFLAGS="$CFLAGS -qro -qroconst"
+ AIX_WRAP='$(DIST)/lib/aixwrap.o'
+ AIX_TMP='./_aix_tmp.o'
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_aix64.cfg
+ OBJECT_MODE=64
+ else
+ MDCPUCFG_H=_aix32.cfg
+ fi
+ PR_MD_CSRCS=aix.c
+ RESOLVE_LINK_SYMBOLS=1
+ ;;
+
+*-beos*)
+ AC_DEFINE(XP_BEOS)
+ AC_DEFINE(BeOS)
+ AC_DEFINE(BEOS)
+ AC_DEFINE(_POSIX_SOURCE)
+ DSO_LDOPTS=-nostart
+ MDCPUCFG_H=_beos.cfg
+ USE_BTHREADS=1
+ PR_MD_ARCH_DIR=beos
+ RESOLVE_LINK_SYMBOLS=1
+ case "${target_cpu}" in
+ i*86)
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS='-gdwarf-2 -O0'
+ MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@'
+ AC_CHECK_LIB(bind, gethostbyaddr, [OS_LIBS="$OS_LIBS -lbind -lsocket"])
+ ;;
+ powerpc)
+ CC=mwcc
+ CCC=mwcc
+ LD=mwld
+ DSO_LDOPTS='-xms -export pragma -init _init_routine_ -term _term_routine_ -lroot -lnet /boot/develop/lib/ppc/glue-noinit.a /boot/develop/lib/ppc/init_term_dyn.o /boot/develop/lib/ppc/start_dyn.o'
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS='-g -O0'
+ ;;
+ esac
+ ;;
+
+*-bsdi*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(BSDI)
+ AC_DEFINE(NEED_BSDREGEX)
+
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ CXXFLAGS="$CXXFLAGS -Wall -Wno-format"
+
+ if echo "$OS_TEST" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ elif echo "$OS_TEST" | grep -c sparc >/dev/null; then
+ CPU_ARCH=sparc
+ fi
+
+ MDCPUCFG_H=_bsdi.cfg
+ PR_MD_CSRCS=bsdi.c
+
+ DSO_LDOPTS=-r
+
+ case "$target_os" in
+ bsdi1.1*)
+ AC_DEFINE(_PR_BSDI_JMPBUF_IS_ARRAY)
+ AC_DEFINE(_PR_STAT_HAS_ONLY_ST_ATIME)
+ AC_DEFINE(_PR_NEED_H_ERRNO)
+ MKSHLIB=
+ DSO_CFLAGS=
+ DSO_LDOPTS=
+ ;;
+
+ bsdi2.1*)
+ AC_DEFINE(_PR_TIMESPEC_HAS_TS_SEC)
+ AC_DEFINE(_PR_BSDI_JMPBUF_IS_ARRAY)
+ AC_DEFINE(HAVE_DLL)
+ AC_DEFINE(USE_DLFCN)
+ AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC)
+ PR_MD_ASFILES=os_BSD_OS_386_2.s
+ ;;
+
+ bsdi4.* | bsdi5.*)
+ AC_DEFINE(_PR_SELECT_CONST_TIMEVAL)
+ AC_DEFINE(_PR_BSDI_JMPBUF_IS_STRUCT)
+ AC_DEFINE(HAVE_DLL)
+ AC_DEFINE(USE_DLFCN)
+ AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC)
+ MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS='-shared -Wl,-soname,$(@:$(OBJDIR)/%.so=%.so)'
+ STRIP="$STRIP -d"
+ case "$target_os" in
+ bsdi4.2* | bsdi4.3* | bsdi5.*)
+ AC_DEFINE(_PR_HAVE_GETPROTO_R)
+ AC_DEFINE(_PR_HAVE_GETPROTO_R_POINTER)
+ ;;
+ esac
+ ;;
+ *)
+ AC_DEFINE(_PR_SELECT_CONST_TIMEVAL)
+ AC_DEFINE(_PR_BSDI_JMPBUF_IS_STRUCT)
+ AC_DEFINE(HAVE_DLL)
+ AC_DEFINE(USE_DLFCN)
+ AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC)
+ ;;
+ esac
+
+ ;;
+
+*-darwin*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(DARWIN)
+ AC_DEFINE(HAVE_BSD_FLOCK)
+ CFLAGS="$CFLAGS -Wmost -fno-common"
+ if echo $OS_TEST | grep -c 86 2>/dev/null; then
+ AC_DEFINE(i386)
+ CPU_ARCH=i386
+ else
+ AC_DEFINE(ppc)
+ CPU_ARCH=ppc
+ fi
+ DSO_LDOPTS='-dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name @executable_path/$@ -headerpad_max_install_names'
+ # Use the standard preprocessor (cpp)
+ CFLAGS="$CFLAGS -no-cpp-precomp"
+ MKSHLIB='$(CC) -arch $(CPU_ARCH) $(DSO_LDOPTS) -o $@'
+ STRIP="$STRIP -x -S"
+ DLL_SUFFIX=dylib
+ USE_PTHREADS=1
+ MDCPUCFG_H=_darwin.cfg
+ PR_MD_CSRCS=darwin.c
+ if test "$CPU_ARCH" = "ppc"; then
+ PR_MD_ASFILES=os_Darwin_ppc.s
+ fi
+
+ # Add Mac OS X support for loading CFM & CFBundle plugins
+ if test -f /System/Library/Frameworks/Carbon.framework/Carbon; then
+ AC_DEFINE(XP_MACOSX)
+ OS_TARGET=MacOSX
+
+ dnl The C preprocessor can only handle integers in comparisons, so
+ dnl convert the version to the form AABBCC where AA=major release,
+ dnl BB=minor release, and CC=point/micro release.
+
+ MACOS_VERSION_MAJOR=`echo $MACOS_DEPLOYMENT_TARGET_STR | cut -d . -f 1`
+ MACOS_VERSION_MINOR=`echo $MACOS_DEPLOYMENT_TARGET_STR | cut -d . -f 2`
+ MACOS_VERSION_MICRO=`echo $MACOS_DEPLOYMENT_TARGET_STR | cut -d . -f 3`
+ if test -z "$MACOS_VERSION_MINOR"; then
+ MACOS_VERSION_MINOR=0
+ fi
+ if test -z "$MACOS_VERSION_MICRO"; then
+ MACOS_VERSION_MICRO=0
+ fi
+ MACOS_DEPLOYMENT_TARGET=`printf "%02d%02d%02d" "$MACOS_VERSION_MAJOR" "$MACOS_VERSION_MINOR" "$MACOS_VERSION_MICRO"`
+ AC_DEFINE_UNQUOTED(MACOS_DEPLOYMENT_TARGET, $MACOS_DEPLOYMENT_TARGET)
+ fi
+
+ # do the right thing for panther SDK support
+ if test "$NEXT_ROOT"; then
+ CFLAGS="-I${NEXT_ROOT}/usr/include $CFLAGS"
+ CXXFLAGS="-I${NEXT_ROOT}/usr/include $CXXFLAGS"
+ fi
+ ;;
+
+*-dgux*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(SYSV)
+ AC_DEFINE(DGUX)
+ AC_DEFINE(_DGUX_SOURCE)
+ AC_DEFINE(_POSIX4A_DRAFT6_SOURCE)
+ DSO_LDOPTS=-G
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS=
+ MDCPUCFG_H=_dgux.cfg
+ PR_MD_CSRCS=dgux.c
+ ;;
+
+*-freebsd*)
+ if test -z "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=1
+ fi
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(FREEBSD)
+ AC_DEFINE(HAVE_BSD_FLOCK)
+ AC_DEFINE(HAVE_SOCKLEN_T)
+ CFLAGS="$CFLAGS $(DSO_CFLAGS) -ansi -Wall"
+ MOZ_OBJFORMAT=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ if test "$MOZ_OBJFORMAT" = "elf"; then
+ DLL_SUFFIX=so
+ else
+ DLL_SUFFIX=so.1.0
+ fi
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
+ MDCPUCFG_H=_freebsd.cfg
+ PR_MD_CSRCS=freebsd.c
+ ;;
+
+*-hpux*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(HPUX)
+ AC_DEFINE(_HPUX_SOURCE)
+ AC_DEFINE(hppa)
+ # OSF1 and HPUX report the POLLHUP event for a socket when the
+ # shutdown(SHUT_WR) operation is called for the remote end, even though
+ # the socket is still writeable. Use select(), instead of poll(), to
+ # workaround this problem.
+ AC_DEFINE(_PR_POLL_WITH_SELECT)
+ AC_DEFINE(_USE_BIG_FDS)
+ DLL_SUFFIX=sl
+ DSO_LDOPTS='-b +h $(notdir $@)'
+ PR_MD_CSRCS=hpux.c
+ if test "$OS_TEST" != "ia64"; then
+ PR_MD_ASFILES=os_HPUX.s
+ fi
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_hpux64.cfg
+ else
+ MDCPUCFG_H=_hpux32.cfg
+ fi
+ if test -z "$GNU_CC"; then
+ CC="$CC -Ae"
+ CXX="$CXX -ext"
+ DSO_CFLAGS=+Z
+ else
+ DSO_CFLAGS=-fPIC
+ fi
+
+ if test -n "$MOZILLA_CLIENT"; then
+ DEFAULT_IMPL_STRATEGY=_EMU
+ fi
+
+ if echo "$OS_RELEASE" | grep ^A.09 >/dev/null; then
+ AC_DEFINE(_PR_NEED_H_ERRNO)
+ AC_DEFINE(HPUX9)
+ DEFAULT_IMPL_STRATEGY=_EMU
+ USE_NSPR_THREADS=1
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(A.09|B.10)' >/dev/null; then
+ AC_DEFINE(_PR_NO_LARGE_FILES)
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
+ AC_DEFINE(_PR_NEED_H_ERRNO)
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
+ AC_DEFINE(HAVE_INT_LOCALTIME_R)
+ fi
+
+ if echo "$OS_RELEASE" | egrep '^(B.10.30|B.11)' >/dev/null; then
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ fi
+
+ # HP-UX 11i (B.11.11) or higher
+ changequote(<<,>>)
+ case "$OS_RELEASE" in
+ [C-Z]*|B.[2-9]*|B.1[2-9]*|B.11.[2-9]*|B.11.1[1-9]*)
+ USE_IPV6=1
+ ;;
+ esac
+ changequote([,])
+
+ if test "$OS_RELEASE" = "B.10.01"; then
+ AC_DEFINE(HPUX10)
+ DEFAULT_IMPL_STRATEGY=_EMU
+ fi
+
+ if test "$OS_RELEASE" = "B.10.10"; then
+ AC_DEFINE(HPUX10)
+ AC_DEFINE(HPUX10_10)
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if test "$OS_RELEASE" = "B.10.20"; then
+ AC_DEFINE(HPUX10)
+ AC_DEFINE(HPUX10_20)
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS +DAportable +DS1.1"
+ CXXFLAGS="$CXXFLAGS +DAportable +DS1.1"
+ fi
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if test "$OS_RELEASE" = "B.10.30"; then
+ AC_DEFINE(HPUX10)
+ AC_DEFINE(HPUX10_30)
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS +DAportable +DS1.1"
+ CXXFLAGS="$CXXFLAGS +DAportable +DS1.1"
+ fi
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if echo "$OS_RELEASE" | grep ^B.11 >/dev/null; then
+ AC_DEFINE(HPUX10)
+ AC_DEFINE(HPUX11)
+ AC_DEFINE(_LARGEFILE64_SOURCE)
+ AC_DEFINE(_PR_HAVE_OFF64_T)
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ if test -z "$GNU_CC"; then
+ if test -z "$USE_64"; then
+ if test "$OS_TEST" = "ia64"; then
+ CFLAGS="$CFLAGS +DD32"
+ CXXFLAGS="$CXXFLAGS +DD32"
+ else
+ CFLAGS="$CFLAGS +DAportable +DS2.0"
+ CXXFLAGS="$CXXFLAGS +DAportable +DS2.0"
+ fi
+ else
+ if test "$OS_TEST" = "ia64"; then
+ CFLAGS="$CFLAGS +DD64"
+ CXXFLAGS="$CXXFLAGS +DD64"
+ else
+ CFLAGS="$CFLAGS +DA2.0W +DS2.0"
+ CXXFLAGS="$CXXFLAGS +DA2.0W +DS2.0"
+ fi
+ fi
+ fi
+ DEFAULT_IMPL_STRATEGY=_PTH
+ fi
+
+ if test "$DEFAULT_IMPL_STRATEGY" = "_EMU"; then
+ USE_NSPR_THREADS=1
+ USE_PTHREADS=
+ USE_USER_THREADS=
+ elif test "$DEFAULT_IMPL_STRATEGY" = "_PTH"; then
+ USE_PTHREADS=1
+ if test "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=
+ fi
+ if test "$USE_USER_PTHREADS"; then
+ USE_PTHREADS=
+ fi
+ fi
+ ;;
+
+*-irix*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(IRIX)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(_SGI_MP_SOURCE)
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ PR_MD_CSRCS=irix.c
+ PR_MD_ASFILES=os_Irix.s
+ MKSHLIB='$(LD) $(DSO_LDOPTS) -rdata_shared -shared -soname $(notdir $@) -o $@'
+ STRIP="$STRIP -f"
+ RESOLVE_LINK_SYMBOLS=1
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_irix64.cfg
+ else
+ MDCPUCFG_H=_irix32.cfg
+ fi
+ case "${target_os}" in
+ irix6*)
+ AC_DEFINE(IRIX6)
+ USE_PTHREADS=1
+ USE_N32=1
+ COMPILER_TAG=_n32
+ IMPL_STRATEGY=_PTH
+ ;;
+ irix5*)
+ AC_DEFINE(IRIX5)
+ USE_NSPR_THREADS=1
+ ;;
+ *)
+ USE_PTHREADS=1
+ USE_N32=1
+ ;;
+ esac
+ if test "$GNU_CC"; then
+ dnl
+ dnl If we are using gcc with native binutils, we need to
+ dnl suppress the
+ dnl #lineno "filename" num num
+ dnl lines, which confuse IRIX native as. Add -Wp,-P to the
+ dnl gcc command line, which passes -P to the preprocessor.
+ dnl
+ AS='$(CC) -Wp,-P -x assembler-with-cpp -D_ASM -mips2 $(INCLUDES)'
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ _OPTIMIZE_FLAGS="-O6"
+ else
+ if test -n "$USE_N32"; then
+ AS='as -D_ASM $(INCLUDES) -n32'
+ else
+ AS='as -D_ASM $(INCLUDES)'
+ fi
+ CFLAGS="$CFLAGS -fullwarn -xansi"
+ if test "$USE_N32"; then
+ _OPTIMIZE_FLAGS="-O -OPT:Olimit=4000"
+ else
+ _OPTIMIZE_FLAGS="-O -Olimit 4000"
+ fi
+ if test "$USE_MDUPDATE"; then
+ CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)"
+ fi
+ case "${target}" in
+ *-irix6.*)
+ CFLAGS="$CFLAGS -multigot"
+ DSO_LDOPTS="-no_unresolved"
+ if test "$USE_N32"; then
+ CFLAGS="$CFLAGS -n32 -woff 1209"
+ DSO_LDOPTS="$DSO_LDOPTS -n32"
+ else
+ if test "$USE_64"; then
+ CFLAGS="$CFLAGS -64"
+ else
+ CFLAGS="$CFLAGS -32"
+ fi
+ fi
+ ;;
+ *)
+ CFLAGS="$CFLAGS -xgot"
+ ;;
+ esac
+ fi
+ if test "${target_os}" = "irix5.3"; then
+ AC_DEFINE(IRIX5_3)
+ fi
+ case "${target_os}" in
+ irix6.5)
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS -mips3"
+ fi
+ AC_DEFINE(_PR_HAVE_GETPROTO_R)
+ AC_DEFINE(_PR_HAVE_GETPROTO_R_POINTER)
+ AC_DEFINE(_PR_HAVE_SGI_PRDA_PROCMASK)
+ ;;
+ irix5*)
+ ;;
+ *)
+ AC_DEFINE(_PR_HAVE_SGI_PRDA_PROCMASK)
+ ;;
+ esac
+ ;;
+
+*-linux*)
+ if test -z "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=1
+ IMPL_STRATEGY=_PTH
+ fi
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(_POSIX_SOURCE)
+ AC_DEFINE(_BSD_SOURCE)
+ AC_DEFINE(_SVID_SOURCE)
+ AC_DEFINE(_LARGEFILE64_SOURCE)
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ AC_DEFINE(LINUX)
+ CFLAGS="$CFLAGS -ansi -Wall"
+ CXXFLAGS="$CXXFLAGS -ansi -Wall"
+ MDCPUCFG_H=_linux.cfg
+ PR_MD_CSRCS=linux.c
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)'
+ _OPTIMIZE_FLAGS=-O2
+ _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that
+ # combo is not yet good at debugging inlined
+ # functions (even when using DWARF2 as the
+ # debugging format)
+ COMPILER_TAG=_glibc
+ if echo "$OS_TEST" | grep -c 86 >/dev/null; then
+ CPU_ARCH=x86
+ else
+ CPU_ARCH=$OS_TEST
+ fi
+ CPU_ARCH_TAG=_${CPU_ARCH}
+ case "${target_cpu}" in
+ alpha)
+ AC_DEFINE(_ALPHA_)
+ AC_DEFINE(__alpha)
+ CFLAGS="$CFLAGS -mieee"
+ CXXFLAGS="$CXXFLAGS -mieee"
+ ;;
+ i*86)
+ AC_DEFINE(i386)
+ PR_MD_ASFILES=os_Linux_x86.s
+ ;;
+ ia64)
+ PR_MD_ASFILES=os_Linux_ia64.s
+ ;;
+ x86_64)
+ PR_MD_ASFILES=os_Linux_x86_64.s
+ ;;
+ m68k)
+ CFLAGS="$CFLAGS -m68020-60"
+ CXXFLAGS="$CXXFLAGS -m68020-60"
+ ;;
+ esac
+ ;;
+
+*-mingw*|*-cygwin*|*-msvc*|*-mks*)
+ AC_DEFINE(XP_PC)
+ AC_DEFINE(WIN32)
+ PR_MD_ARCH_DIR=windows
+ RESOLVE_LINK_SYMBOLS=1
+
+ if test -n "$GNU_CC"; then
+ CC="$CC -mno-cygwin"
+ CXX="$CXX -mno-cygwin"
+ DLL_SUFFIX=dll
+ MKSHLIB='$(CC) -shared -Wl,--export-all-symbols -Wl,--out-implib -Wl,$(IMPORT_LIBRARY) $(DLLBASE) -o $(subst $(OBJDIR)/,,$(SHARED_LIBRARY))'
+ RC=$WINDRES
+ # Use temp file for windres (bug 213281)
+ RCFLAGS='-O coff --use-temp-file'
+ else
+ CC=cl
+ CXX=cl
+ LD=link
+ AR='lib -NOLOGO -OUT:"$@"'
+ AR_FLAGS=
+ RANLIB='echo not_ranlib'
+ STRIP='echo not_strip'
+ RC=rc.exe
+ GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb'
+ OBJ_SUFFIX=obj
+ LIB_SUFFIX=lib
+ DLL_SUFFIX=dll
+
+ # Determine compiler version
+ CC_VERSION=`"${CC}" -v 2>&1 | grep Version | sed -e 's|.* Version ||' -e 's| .*||'`
+ _CC_MAJOR_VERSION=`echo $CC_VERSION | awk -F\. '{ print $1 }'`
+ _CC_MINOR_VERSION=`echo $CC_VERSION | awk -F\. '{ print $2 }'`
+ MSC_VER=${_CC_MAJOR_VERSION}${_CC_MINOR_VERSION}
+
+ CFLAGS="$CFLAGS -W3 -nologo -GF -Gy"
+ DLLFLAGS='-OUT:"$@"'
+ _DEBUG_FLAGS=-Z7
+ _OPTIMIZE_FLAGS=-O2
+ if test -z "$MOZ_OPTIMIZE"; then
+ CFLAGS="$CFLAGS -Od"
+ fi
+
+ if test -n "$USE_DEBUG_RTL"; then
+ CFLAGS="$CFLAGS -MDd"
+ else
+ CFLAGS="$CFLAGS -MD"
+ fi
+
+ if test -n "$MOZ_DEBUG"; then
+ AC_DEFINE(_DEBUG)
+ else
+ DEFINES="$DEFINES -U_DEBUG"
+ fi
+
+ if test -n "$MOZ_OPTIMIZE"; then
+ if test -n "$MOZ_PROFILE"; then
+ _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Z7"
+ fi
+ if test -n "$MOZ_DEBUG_SYMBOLS"; then
+ _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Zi"
+ fi
+ if test -n "$MOZ_PROFILE" -o -n "$MOZ_DEBUG_SYMBOLS"; then
+ DLLFLAGS="$DLLFLAGS -DEBUG -OPT:REF"
+ LDFLAGS="$LDFLAGS -DEBUG -OPT:REF"
+ fi
+ fi
+
+ if test -n "$MOZ_DEBUG"; then
+ DLLFLAGS="$DLLFLAGS -DEBUG -DEBUGTYPE:CV"
+ LDFLAGS="$LDFLAGS -DEBUG -DEBUGTYPE:CV"
+ fi
+
+ if test "$OS_TARGET" = "WINNT"; then
+ CFLAGS="$CFLAGS -GT"
+ if test "$CPU_ARCH" = "x86"; then
+ CFLAGS="$CFLAGS -G5"
+ fi
+ LIBNSPR='$(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ LIBPLC='$(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ else
+ LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ fi
+ fi # GNU_CC
+
+ if test -n "$USE_STATIC_TLS"; then
+ AC_DEFINE(_PR_USE_STATIC_TLS)
+ fi
+
+ if test "$OS_TARGET" = "WINNT"; then
+ AC_DEFINE(WINNT)
+ else
+ AC_DEFINE(WIN95)
+ # undefine WINNT as some versions of mingw gcc define it by default
+ DEFINES="$DEFINES -UWINNT"
+ AC_DEFINE(_PR_GLOBAL_THREADS_ONLY)
+ fi
+
+ if test "$CPU_ARCH" = "x86"; then
+ CPU_ARCH_TAG=
+ else
+ CPU_ARCH_TAG=$CPU_ARCH
+ fi
+
+ if test -n "$USE_DEBUG_RTL"; then
+ OBJDIR_SUFFIX=OBJD
+ fi
+
+ OS_DLLFLAGS="-nologo -DLL -SUBSYSTEM:WINDOWS"
+ if test "$MSC_VER" = "1200" -a -z "$MOZ_DEBUG_SYMBOLS"; then
+ OS_DLLFLAGS="$OS_DLLFLAGS -PDB:NONE"
+ fi
+
+ case "$OS_TARGET" in
+ WINNT)
+ MDCPUCFG_H=_winnt.cfg
+ ;;
+ WIN95)
+ MDCPUCFG_H=_win95.cfg
+ ;;
+ WIN16)
+ MDCPUCFG_H=_win16.cfg
+ ;;
+ *)
+ AC_MSG_ERROR([Missing OS_TARGET for ${target}. Use --enable-win32-target to set.])
+ ;;
+ esac
+
+ case "$target_cpu" in
+ i*86)
+ AC_DEFINE(_X86_)
+ ;;
+ alpha)
+ AC_DEFINE(_ALPHA_)
+ ;;
+ mips)
+ AC_DEFINE(_MIPS_)
+ ;;
+ *)
+ AC_DEFINE(_CPU_ARCH_NOT_DEFINED)
+ ;;
+ esac
+
+ ;;
+
+*-ncr-sysv*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(SYSV)
+ AC_DEFINE(NCR)
+ USE_NSPR_THREADS=1
+ if test "$OS_RELEASE" = "2.03"; then
+ AC_DEFINE(_PR_STAT_HAS_ST_ATIM)
+ else
+ AC_DEFINE(_PR_STAT_HAS_ST_ATIM_UNION)
+ fi
+
+ if test -z "$GNU_CC"; then
+ CFLAGS="$CFLAGS -Hnocopyr"
+ CXXFLAGS="$CXXFLAGS -Hnocopyr"
+ else
+ CFLAGS="$CFLAGS -fPIC -Wall"
+ CXXFLAGS="$CXXFLAGS -fPIC -Wall"
+ DSO_LDOPTS=-G
+ fi
+ MDCPUCFG_H=_ncr.cfg
+ PR_MD_CSRCS=ncr.c
+ ;;
+
+mips-nec-sysv*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(__SVR4)
+ AC_DEFINE(NEC)
+ AC_DEFINE(nec_ews)
+ USE_NSPR_THREADS=1
+ if test -z "$GNU_CC"; then
+ CC='$(NSDEPTH)/build/hcc cc -Xa -KGnum=0 -KOlimit=4000'
+ CXX=g++
+ fi
+ OS_LIBS="$OS_LIBS -lsocket -lnsl -ldl"
+ DSO_LDOPTS=-G
+ MDCPUCFG_H=_nec.cfg
+ PR_MD_CSRCS=nec.c
+ ;;
+
+*-netbsd*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(NETBSD)
+ AC_DEFINE(HAVE_BSD_FLOCK)
+ USE_NSPR_THREADS=1
+ MDCPUCFG_H=_netbsd.cfg
+ PR_MD_CSRCS=netbsd.c
+
+ DSO_CFLAGS='-fPIC -DPIC'
+ CFLAGS="$CFLAGS -ansi -Wall"
+ CXXFLAGS="$CXXFLAGS -ansi -Wall"
+ MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)'
+
+ if test -z "$OBJECT_FMT"; then
+ if echo __ELF__ | ${CC-cc} -E - | grep -q __ELF__ 2>/dev/null; then
+ OBJECT_FMT=a.out
+ DLL_SUFFIX=so.1.0
+ DSO_LDOPTS='-shared'
+ else
+ OBJECT_FMT=ELF
+ DLL_SUFFIX=so
+ DSO_LDOPTS='-shared -Wl,-soname,$(notdir $@)'
+ fi
+ fi
+
+ if test "$LIBRUNPATH"; then
+ DSO_LDOPTS="$DSO_LDOPTS -Wl,-R$LIBRUNPATH"
+ fi
+ ;;
+
+mips-sony-newsos*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SONY)
+ AC_DEFINE(SYSV)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(__svr4)
+ AC_DEFINE(__svr4__)
+ AC_DEFINE(HAVE_SVID_GETTOD)
+ USE_NSPR_THREADS=1
+ CFLAGS="$CFLAGS -Xa -fullwarn"
+ CXXFLAGS="$CXXFLAGS -Xa -fullwarn"
+ DSO_LDOPTS=-G
+ MDCPUCFG_H=_sony.cfg
+ PR_MD_CSRCS=sony.c
+ ;;
+
+*-nextstep*|*-openstep*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(NEXTSTEP)
+ AC_DEFINE(HAVE_BSD_FLOCK)
+ AC_DEFINE(_POSIX_SOURCE)
+ CFLAGS="$CFLAGS -Wall -fno-common -traditional-cpp -posix"
+ CXXFLAGS="$CXXFLAGS -Wall -fno-common -traditional-cpp -posix"
+ USE_NSPR_THREADS=1
+ DLL_SUFFIX=dylib
+ MDCPUCFG_H=_nextstep.cfg
+ PR_MD_CSRCS=nextstep.c
+ ;;
+
+
+*-nto*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(NTO)
+ AC_DEFINE(_QNX_SOURCE)
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ MDCPUCFG_H=_nto.cfg
+ PR_MD_CSRCS=nto.c
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -Wl,-soname -Wl,$(notdir $@) -o $@'
+ DSO_CFLAGS=-fPIC
+ DSO_LDOPTS=-shared
+ OS_LIBS="$OS_LIBS -lsocket"
+ _OPTIMIZE_FLAGS="-O1"
+ _DEBUG_FLAGS="-gstabs"
+ ;;
+
+*-openbsd*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(OPENBSD)
+ AC_DEFINE(HAVE_BSD_FLOCK)
+ AC_DEFINE(HAVE_SOCKLEN_T)
+ CFLAGS="$CFLAGS -ansi -Wall"
+ CXXFLAGS="$CXXFLAGS -ansi -Wall"
+ DLL_SUFFIX=so.1.0
+ DSO_CFLAGS=-fPIC
+ MDCPUCFG_H=_openbsd.cfg
+ PR_MD_CSRCS=openbsd.c
+ USE_NSPR_THREADS=1
+ DSO_LDOPTS='-shared -fPIC'
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ ;;
+
+*-openvms*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(VMS)
+ AC_DEFINE(PR_GETIPNODE_NOT_THREADSAFE)
+ RESOLVE_LINK_SYMBOLS=1
+ AR_FLAGS='c $@'
+ MDCPUCFG_H=_openvms.cfg
+ PR_MD_CSRCS=openvms.c
+ DSO_LDOPTS='-shared -auto_symvec $(LDFLAGS)'
+ if test -n "$MOZ_DEBUG"; then
+ DSO_LDOPTS="$DSO_LDOPTS $_DEBUG_FLAGS"
+ else
+ DSO_LDOPTS="$DSO_LDOPTS $_OPTIMIZE_FLAGS"
+ fi
+ ;;
+
+*-osf*)
+ SHELL_OVERRIDE="SHELL = /usr/bin/ksh"
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(OSF1)
+ AC_DEFINE(_REENTRANT)
+ # OSF1 and HPUX report the POLLHUP event for a socket when the
+ # shutdown(SHUT_WR) operation is called for the remote end, even though
+ # the socket is still writeable. Use select(), instead of poll(), to
+ # workaround this problem.
+ AC_DEFINE(_PR_POLL_WITH_SELECT)
+
+ if echo "$OS_RELEASE" | egrep -c '(V2.0|V3.2)' 2>/dev/null ; then
+ USE_NSPR_THREADS=1
+ fi
+
+ if test -z "$GNU_CC"; then
+ CC="$CC -std1 -ieee_with_inexact"
+ if test "$OS_RELEASE" != "V2.0"; then
+ CC="$CC -readonly_strings"
+ fi
+ _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Olimit 4000"
+ AC_CHECK_HEADER(machine/builtins.h, AC_DEFINE(OSF1_HAVE_MACHINE_BUILTINS_H))
+ else
+ CFLAGS="$CFLAGS -mieee"
+ CXXFLAGS="$CXXFLAGS -mieee"
+ fi
+
+ if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then
+ AC_DEFINE(HAVE_INT_LOCALTIME_R)
+ else
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ fi
+ if echo $OS_RELEASE | grep -c V4.0 >/dev/null; then
+ AC_DEFINE(OSF1V4_MAP_PRIVATE_BUG)
+ fi
+ DSO_LDOPTS='-shared -all -expect_unresolved "*" -soname $(notdir $@)'
+ MDCPUCFG_H=_osf1.cfg
+ PR_MD_CSRCS=osf1.c
+ ;;
+
+*-qnx*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(QNX)
+ AC_DEFINE(_PR_NEED_H_ERRNO)
+ USE_NSPR_THREADS=1
+ MDCPUCFG_H=_qnx.cfg
+ PR_MD_CSRCS=qnx.c
+ ;;
+
+*-*-sco*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SCO)
+ AC_DEFINE(sco)
+ AC_DEFINE(SYSV)
+ AC_DEFINE(_SVID3)
+ AC_DEFINE(_PR_NEED_H_ERRNO)
+ CC='cc -b elf -KPIC'
+ CXX='$(NSDEPTH)/build/hcpp CC +.cpp +w'
+ USE_NSPR_THREADS=1
+ CPU_ARCH=x86
+ DSO_LDOPTS='-b elf -G'
+ MDCPUCFG_H=_scoos.cfg
+ PR_MD_SRCS=scoos.c
+ ;;
+
+*-sinix*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(SNI)
+ AC_DEFINE(RELIANTUNIX)
+ AC_DEFINE(sinix)
+ AC_DEFINE(HAVE_SVID_GETTOD)
+ if echo "$OS_TEST" | grep -c 86 2>/dev/null; then
+ AC_DEFINE(i386)
+ CPU_ARCH=x86
+ else
+ CPU_ARCH=mips
+ fi
+
+ if test "$GNU_CC"; then
+ AS='$(CC) -x assembler-with-cpp'
+ if test "$CPU_ARCH" = "mips"; then
+ LD=gld
+ fi
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ else
+ AS='/usr/bin/cc'
+ _OPTIMIZE_FLAGS='-O -F Olimit,4000'
+ fi
+
+ DSO_LDOPTS='-G -z defs -h $(@:$(OBJDIR)/%.so=%.so)'
+
+ if test "$OS_RELEASE" = "5.43"; then
+ AC_DEFINE(IP_MULTICAST)
+ fi
+
+ OS_LIBS="$OS_LIBS -lsocket -lnsl -lresolv -ldl -lc"
+ USE_NSPR_THREADS=1
+ MDCPUCFG_H=_reliantunix.cfg
+ PR_MD_CSRCS=reliantunix.c
+ if test "${OS_ARCH}" = "mips"; then
+ PR_MD_ASFILES=os_ReliantUNIX.s
+ fi
+ ;;
+
+*-sunos*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SUNOS4)
+ CFLAGS="$CFLAGS -Wall -Wno-format"
+ if test "$USE_MDUPDATE"; then
+ CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)"
+ fi
+ CPU_ARCH=sparc
+ DLL_SUFFIX=so.1.0
+ DSO_LDOPTS=
+ DSO_CFLAGS=-fPIC
+ USE_NSPR_THREADS=1
+ if test "$OS_RELEASE" = "4.1.3_U1"; then
+ _OPTIMIZE_FLAGS=
+ OS_LIBS="$OS_LIBS -lm"
+ fi
+ MDCPUCFG_H=_sunos4.cfg
+ PR_MD_CSRCS=sunos4.c
+ ;;
+
+*-solaris*)
+ if test -z "$USE_USER_THREADS" && test -z "$USE_NATIVE_THREADS"; then
+ USE_PTHREADS=1
+ fi
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(SYSV)
+ AC_DEFINE(__svr4)
+ AC_DEFINE(__svr4__)
+ AC_DEFINE(SOLARIS)
+ AC_DEFINE(HAVE_FCNTL_FILE_LOCKING)
+ if test -n "$USE_64"; then
+ MDCPUCFG_H=_solaris64.cfg
+ else
+ MDCPUCFG_H=_solaris32.cfg
+ fi
+ PR_MD_CSRCS=solaris.c
+ LD=/usr/ccs/bin/ld
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ RESOLVE_LINK_SYMBOLS=1
+ if test -n "$GNU_CC"; then
+ DSO_CFLAGS=-fPIC
+ if `$CC -print-prog-name=ld` -v 2>&1 | grep -c GNU >/dev/null; then
+ GCC_USE_GNU_LD=1
+ fi
+ DSO_LDOPTS='-shared -Wl,-h,$(notdir $@),-z,combreloc,-z,defs'
+ else
+ DSO_CFLAGS=-KPIC
+ DSO_LDOPTS='-G -h $(notdir $@) -z combreloc -z defs'
+ fi
+ if test -z "$GNU_AS"; then
+ ASFLAGS="$ASFLAGS -Wa,-P"
+ fi
+ if test -n "$GNU_CC"; then
+ CFLAGS="$CFLAGS -Wall"
+ CXXFLAGS="$CXXFLAGS -Wall"
+ if test -n "$USE_MDUPDATE"; then
+ CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)"
+ CXXFLAGS="$CXXFLAGS -MDupdate \$(DEPENDENCIES)"
+ fi
+ else
+ CFLAGS="$CFLAGS -xstrconst"
+ CXXFLAGS="$CXXFLAGS -Qoption cg -xstrconst -features=tmplife"
+ if test -z "$MOZ_OPTIMIZE"; then
+ CFLAGS="$CFLAGS -xs"
+ CXXFLAGS="$CXXFLAGS -xs"
+ fi
+ _OPTIMIZE_FLAGS=-xO4
+ fi
+ if test -n "$USE_64"; then
+ if test -n "$GNU_CC"; then
+ CC="$CC -m64"
+ CXX="$CXX -m64"
+ else
+ CC="$CC -xarch=v9"
+ CXX="$CXX -xarch=v9"
+ fi
+ fi
+ if test "$OS_TEST" = "i86pc"; then
+ AC_DEFINE(i386)
+ CPU_ARCH_TAG=_$OS_TEST
+ # The default debug format, DWARF (-g), is not supported by gcc
+ # on i386-ANY-sysv4/solaris, but the stabs format is. It is
+ # assumed that the Solaris assembler /usr/ccs/bin/as is used.
+ # If your gcc uses GNU as, you do not need the -Wa,-s option.
+ if test -n "$MOZ_DEBUG" && test -n "$GNU_CC"; then
+ _DEBUG_FLAGS=-gstabs
+ if test -z "$GNU_AS"; then
+ _DEBUG_FLAGS="$_DEBUG_FLAGS -Wa,-s"
+ fi
+ fi
+ fi
+ case "${target_os}" in
+ solaris2.3*)
+ AC_DEFINE(_PR_NO_LARGE_FILES)
+ ;;
+ solaris2.4*)
+ AC_DEFINE(_PR_NO_LARGE_FILES)
+ ;;
+ solaris2.5*)
+ AC_DEFINE(SOLARIS2_5)
+ ;;
+ *)
+ AC_DEFINE(_PR_HAVE_OFF64_T)
+ # The lfcompile64(5) man page on Solaris 2.6 says:
+ # For applications that do not wish to conform to the POSIX or
+ # X/Open specifications, the 64-bit transitional interfaces
+ # are available by default. No compile-time flags need to be
+ # set.
+ # But gcc 2.7.2.x fails to define _LARGEFILE64_SOURCE by default.
+ # The native compiler, gcc 2.8.x, and egcs don't have this problem.
+ if test -n "$GNU_CC"; then
+ AC_DEFINE(_LARGEFILE64_SOURCE)
+ fi
+ ;;
+ esac
+ case "${target_os}" in
+ solaris2.3*)
+ ;;
+ solaris2.4*)
+ ;;
+ solaris2.5*)
+ ;;
+ solaris2.6*)
+ ;;
+ solaris2.7*)
+ ;;
+ *)
+ # Solaris 8 or higher has IPv6.
+ AC_DEFINE(_PR_INET6)
+ ;;
+ esac
+ if test "$OS_TEST" = "sun4u"; then
+ # 64-bit Solaris requires SPARC V9 architecture, so the following
+ # is not needed.
+ if test -z "$USE_64"; then
+ ULTRASPARC_LIBRARY=nspr_flt
+ fi
+ fi
+ # Purify requires that binaries linked against nspr also
+ # be linked against -lrt (or -lposix4) so add it to OS_LIBS
+ _rev=`uname -r`
+ _librt=`echo $_rev 5.6 | awk '{ if ($1 > $2) print "-lrt"; else print "-lposix4" }'`
+ OS_LIBS="$OS_LIBS $_librt"
+ ;;
+
+*-sco-sysv5*)
+ AC_DEFINE(XP_UNIX)
+ AC_DEFINE(UNIXWARE)
+ AC_DEFINE(SVR4)
+ AC_DEFINE(SYSV)
+ USE_NSPR_THREADS=1
+ if echo $OS_RELEASE | grep -c 2.1 2>/dev/null; then
+ AC_DEFINE(_PR_NO_LARGE_FILES)
+ CC='$(NSDEPTH)/build/hcc cc'
+ CXX='$(NSDEPTH)/build/hcpp CC'
+ MDCPUCFG_H=_unixware.cfg
+ else
+ AC_DEFINE(_LARGEFILE64_SOURCE)
+ AC_DEFINE(_PR_HAVE_OFF64_T)
+ AC_DEFINE(_PR_HAVE_SOCKADDR_LEN)
+ MDCPUCFG_H=_unixware7.cfg
+ fi
+ PR_MD_CSRCS=unixware.c
+ DSO_LDOPTS=-G
+ CPU_ARCH=x86
+ ;;
+
+*-os2*)
+ AC_DEFINE(XP_OS2)
+ AC_DEFINE(XP_PC)
+ AC_DEFINE(BSD_SELECT)
+ AC_DEFINE(TCPV40HDRS)
+ LIB_SUFFIX=lib
+ DLL_SUFFIX=dll
+ RC=rc.exe
+ PR_MD_ARCH_DIR=os2
+ PROG_SUFFIX=.exe
+ NSINSTALL=nsinstall
+ MDCPUCFG_H=_os2.cfg
+ RESOLVE_LINK_SYMBOLS=1
+
+ # EMX/GCC build
+ if test -n "$GNU_CC"; then
+ AC_DEFINE(XP_OS2_EMX)
+ AC_DEFINE(OS2)
+ AR=emxomfar
+ AR_FLAGS='r $@'
+ CFLAGS="$CFLAGS -Wall -Zomf"
+ CXXFLAGS="$CFLAGS -Wall -Zomf"
+ MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@'
+ DSO_CFLAGS=
+ DSO_LDOPTS='-Zomf -Zdll -Zmap'
+ LDFLAGS='-Zmap'
+ _OPTIMIZE_FLAGS="-O2 -s"
+ _DEBUG_FLAGS="-g -fno-inline"
+ if test -n "$MOZ_OPTIMIZE"; then
+ DSO_LDOPTS="$DSO_LDOPTS -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA"
+ fi
+ OS_LIBS="-lsocket"
+ IMPLIB='emximp -o'
+ FILTER='emxexp -o'
+
+ # GCC for OS/2 currently predefines these, but we don't want them
+ DEFINES="$DEFINES -Uunix -U__unix -U__unix__"
+
+ # Visual Age C++ build
+ elif test "$VACPP" = "yes"; then
+ AC_DEFINE(XP_OS2_VACPP)
+ AC_DEFINE(OS2,4)
+ AC_DEFINE(_X86_)
+ OBJ_SUFFIX=obj
+ AS=alp
+ ASFLAGS='-Mb'
+ ASM_SUFFIX=asm
+ AR=-ilib
+ AR_FLAGS='/NOL /NOI /O:$(subst /,\\,$@)'
+ CFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ HOST_CFLAGS="$CFLAGS"
+ OS_CFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ OS_EXE_CFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ CXXFLAGS='/Q /qlibansi /Gd+ /Gm+ /Su4 /Mp /Tl9'
+ OS_LIBS='so32dll.lib tcp32dll.lib'
+ LD='-ilink'
+ MKSHLIB='$(LD) $(DSO_LDOPTS)'
+ IMPLIB='implib -nologo -noignorecase'
+ FILTER='cppfilt -q -B -P'
+ _OPTIMIZE_FLAGS='/O+ /Gl+ /qtune=pentium /qarch=pentium'
+ _DEBUG_FLAGS='/Ti+ '
+ LDFLAGS='/NOL /M /L'
+ DLLFLAGS='/O:$@ /DLL /INC:_dllentry /MAP:$(@:.dll=.map) /L /NOL'
+ EXEFLAGS='/OUT:$@ /PMTYPE:VIO /MAP:$(@:.exe=.map) /L /NOL'
+ if test -n "$MOZ_DEBUG"; then
+ LDFLAGS="$LDFLAGS /DE"
+ DLLFLAGS="$DLLFLAGS /DE"
+ EXEFLAGS="$EXEFLAGS /DE"
+ fi
+ if test -n "$MOZ_OPTIMIZE"; then
+ LDFLAGS="$LDFLAGS /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA"
+ DLLFLAGS="$DLLFLAGS /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA"
+ EXEFLAGS="$EXEFLAGS /OPTFUNC /EXEPACK:2 /PACKCODE /PACKDATA"
+ fi
+ LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)'
+ fi
+ ;;
+
+*)
+ AC_DEFINE(XP_UNIX)
+ ;;
+
+esac
+
+if test -z "$SKIP_LIBRARY_CHECKS"; then
+dnl ========================================================
+dnl Check for system libraries
+dnl ========================================================
+dnl AC_CHECK_LIB(C, main)
+dnl AC_CHECK_LIB(C_r, main)
+dnl AC_CHECK_LIB(c, main)
+dnl AC_CHECK_LIB(c_r, main)
+dnl AC_CHECK_LIB(dce, main)
+dnl AC_CHECK_LIB(dl, main)
+dnl AC_CHECK_LIB(dld, main)
+dnl AC_CHECK_LIB(gen, main)
+dnl AC_CHECK_LIB(ip6, main)
+dnl AC_CHECK_LIB(l, main)
+dnl AC_CHECK_LIB(m, main)
+dnl AC_CHECK_LIB(nsl, main)
+dnl AC_CHECK_LIB(posix4, main)
+dnl AC_CHECK_LIB(prstrms, main)
+dnl AC_CHECK_LIB(prstrms_shr, main)
+dnl AC_CHECK_LIB(pthread, main)
+dnl AC_CHECK_LIB(pthreads, main)
+dnl AC_CHECK_LIB(resolv, main)
+dnl AC_CHECK_LIB(rt, main)
+dnl AC_CHECK_LIB(socket, main)
+dnl AC_CHECK_LIB(svld, main)
+dnl AC_CHECK_LIB(thread, main)
+dnl AC_CHECK_LIB(vms_jackets, main)
+
+
+dnl We don't want anything to link with libdl even if it's present on OS X,
+dnl since it's not used and not part of the default installation.
+
+case $target in
+*-darwin*)
+ ;;
+*)
+ AC_CHECK_LIB(dl, dlopen,
+ AC_CHECK_HEADER(dlfcn.h,
+ OS_LIBS="-ldl $OS_LIBS"))
+ ;;
+esac
+
+
+dnl ========================================================
+dnl Check for system header files.
+dnl ========================================================
+dnl AC_HEADER_DIRENT
+dnl AC_HEADER_STDC
+dnl AC_HEADER_SYS_WAIT
+dnl AC_CHECK_HEADERS(fcntl.h limits.h sys/file.h sys/ioctl.h sys/time.h unistd.h)
+
+dnl ========================================================
+dnl Check for typedefs and structs
+dnl ========================================================
+dnl AC_C_CONST
+dnl AC_TYPE_UID_T
+dnl AC_TYPE_MODE_T
+dnl AC_TYPE_OFF_T
+dnl AC_TYPE_PID_T
+dnl AC_TYPE_SIZE_T
+dnl AC_STRUCT_ST_BLKSIZE
+dnl AC_STRUCT_ST_BLOCKS
+dnl AC_STRUCT_ST_RDEV
+dnl AC_HEADER_TIME
+dnl AC_STRUCT_TM
+
+dnl ========================================================
+dnl Checks for library functions.
+dnl ========================================================
+AC_PROG_GCC_TRADITIONAL
+AC_CHECK_FUNCS(lchown strerror)
+
+dnl AC_FUNC_MEMCMP
+dnl AC_FUNC_MMAP
+dnl AC_FUNC_SETVBUF_REVERSED
+dnl AC_FUNC_STRCOLL
+dnl AC_FUNC_STRFTIME
+dnl AC_FUNC_UTIME_NULL
+dnl AC_FUNC_VPRINTF
+dnl AC_CHECK_FUNCS(ftime getcwd gethostname gettimeofday getwd mkdir mktime putenv rmdir select socket strdup strerror strstr strtol strtoul uname)
+
+dnl ========================================================
+dnl Check options
+dnl ========================================================
+
+dnl ========================================================
+dnl =
+dnl = --enable-strip
+dnl =
+dnl = Enable stripping of libs and executables
+dnl =
+dnl ========================================================
+AC_ARG_ENABLE(strip,
+ [ --enable-strip Enable stripping of shared libs and programs],
+ [ if test "$enableval" = "yes"; then
+ ENABLE_STRIP=1
+ fi ])
+
+dnl Check for hpux options
+case "${target_os}" in
+hpux*)
+if test -z "$GNU_CC"; then
+
+ AC_CACHE_CHECK(for +Olit support,
+ ac_cv_hpux_usable_olit_option,
+ dnl since aCC doesn't throw an error on invalid options,
+ dnl we have to test this the hard way
+ [ac_cv_hpux_usable_olit_option=no
+ rm -f conftest*
+ echo 'int main() { return 0; }' | cat > conftest.c
+ ${CC-cc} ${CFLAGS} +Olit=all -o conftest conftest.c > conftest.out 2>&1
+ if test $? -eq 0; then
+ if test -z "`egrep -i '(unrecognize|unknown)' conftest.out`"; then
+ ac_cv_hpux_usable_olit_option=yes
+ fi
+ fi
+ rm -f conftest*
+ ])
+
+ if test "$ac_cv_hpux_usable_olit_option" = "yes"; then
+ CFLAGS="$CFLAGS +Olit=all"
+ CXXFLAGS="$CXXFLAGS +Olit=all"
+ else
+ CFLAGS="$CFLAGS +ESlit"
+ CXXFLAGS="$CXXFLAGS +ESlit"
+ fi
+fi
+;;
+esac
+
+dnl
+dnl Apparently, some systems cannot properly check for the pthread
+dnl library unless <pthread.h> is included so we need to test
+dnl using it
+dnl
+dnl MOZ_CHECK_PTHREADS(lib, success, failure)
+AC_DEFUN(MOZ_CHECK_PTHREADS,
+[
+AC_MSG_CHECKING([for pthread_create in -l$1])
+echo "
+ #include <pthread.h>
+ void *foo(void *v) { return v; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ return 0;
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ AC_MSG_RESULT([yes])
+ [$2]
+ else
+ AC_MSG_RESULT([no])
+ [$3]
+ fi
+])
+
+MOZ_CHECK_PTHREADS(pthreads,
+ _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads",
+ MOZ_CHECK_PTHREADS(pthread,
+ _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread",
+ MOZ_CHECK_PTHREADS(c_r,
+ _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r",
+ MOZ_CHECK_PTHREADS(c,
+ _HAVE_PTHREADS=1
+ )
+ )
+ )
+)
+
+AC_ARG_WITH(pthreads,
+ [ --with-pthreads Use system pthreads library as thread subsystem],
+ [ if test "$withval" = "yes"; then
+ if test -n "$_HAVE_PTHREADS"; then
+ USE_PTHREADS=1
+ USE_USER_PTHREADS=
+ USE_NSPR_THREADS=
+ else
+ AC_MSG_ERROR([ --with-pthreads specified for a system without pthread support ]);
+ fi
+ else
+ USE_PTHREADS=
+ _PTHREAD_LDFLAGS=
+ fi],
+ [ if test -n "$_HAVE_PTHREADS" && test -z "$USE_USER_PTHREADS" && test -z "$USE_NSPR_THREADS"; then
+ USE_PTHREADS=1
+ USE_USER_PTHREADS=
+ USE_NSPR_THREADS=
+ fi])
+
+AC_ARG_ENABLE(user-pthreads,
+ [ --enable-user-pthreads Build using userland pthreads],
+ [ if test "$enableval" = "yes"; then
+ if test -n "$_HAVE_PTHREADS"; then
+ USE_PTHREADS=
+ USE_USER_PTHREADS=1
+ USE_NSPR_THREADS=
+ else
+ AC_MSG_ERROR([ --enable-user-pthreads specified for a system without pthread support ]);
+ fi
+ fi])
+
+AC_ARG_ENABLE(nspr-threads,
+ [ --enable-nspr-threads Build using classic nspr threads],
+ [ if test "$enableval" = "yes"; then
+ USE_PTHREADS=
+ USE_USER_PTHREADS=
+ USE_NSPR_THREADS=1
+ fi])
+
+case "$target" in
+*-beos*)
+ AC_ARG_WITH(bthreads,
+ [ --with-bthreads Use system bthreads library as thread subsystem (BeOS only)],
+ [ if test "$withval" = "yes"; then
+ USE_BTHREADS=1
+ USE_USER_PTHREADS=
+ USE_PTHREADS=
+ fi])
+ ;;
+
+*-solaris*)
+ AC_ARG_WITH(native-threads,
+ [ --with-native-threads Use native system threads as thread subsystem (Solaris only)],
+ [ if test "$withval" = "yes"; then
+ USE_NATIVE_THREADS=1
+ USE_USER_PTHREADS=
+ USE_PTHREADS=
+ fi])
+ ;;
+esac
+
+fi # SKIP_LIBRARY_CHECKS
+
+AC_ARG_ENABLE(cplus,
+ [ --enable-cplus Enable some c++ api routines],
+ [ if test "$enableval" = "yes"; then
+ USE_CPLUS=1
+ fi])
+
+AC_ARG_ENABLE(ipv6,
+ [ --enable-ipv6 Compile ipv6 support],
+ [ if test "$enableval" = "yes"; then
+ USE_IPV6=1
+ else
+ USE_IPV6=
+ fi])
+
+
+AC_ARG_ENABLE(boehm,
+ [ --enable-boehm Enable the Boehm Garbage Collector],
+ [ if test "$enableval" = "yes"; then
+ AC_DEFINE(GC_LEAK_DETECTOR)
+ GC_LEAK_DETECTOR=1
+ fi])
+
+if test -n "$USE_PTHREADS"; then
+ dnl See if -pthread is supported.
+ rm -f conftest*
+ ac_cv_have_dash_pthread=no
+ AC_MSG_CHECKING(whether ${CC-cc} accepts -pthread)
+ echo 'int main() { return 0; }' | cat > conftest.c
+ ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1
+ if test $? -eq 0; then
+ if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
+ ac_cv_have_dash_pthread=yes
+ case "$target_os" in
+ freebsd*)
+# Freebsd doesn't use -pthread for compiles, it uses them for linking
+ ;;
+ *)
+ CFLAGS="$CFLAGS -pthread"
+ CXXFLAGS="$CXXFLAGS -pthread"
+ ;;
+ esac
+ fi
+ fi
+ rm -f conftest*
+ AC_MSG_RESULT($ac_cv_have_dash_pthread)
+
+ dnl
+ dnl See if -pthreads is supported.
+ dnl
+ ac_cv_have_dash_pthreads=no
+ if test "$ac_cv_have_dash_pthread" = "no"; then
+ AC_MSG_CHECKING(whether ${CC-cc} accepts -pthreads)
+ echo 'int main() { return 0; }' | cat > conftest.c
+ ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1
+ if test $? -eq 0; then
+ if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then
+ ac_cv_have_dash_pthreads=yes
+ CFLAGS="$CFLAGS -pthreads"
+ CXXFLAGS="$CXXFLAGS -pthreads"
+ fi
+ fi
+ rm -f conftest*
+ AC_MSG_RESULT($ac_cv_have_dash_pthreads)
+ fi
+
+ case "$target" in
+ *-solaris*)
+ if test "$ac_cv_have_dash_pthreads" = "yes"; then
+ _PTHREAD_LDFLAGS=
+ fi
+ ;;
+ *-freebsd*)
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(_THREAD_SAFE)
+ dnl -pthread links in -lc_r, so don't specify it explicitly.
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS="-pthread"
+ else
+ _PTHREAD_LDFLAGS="-lc_r"
+ fi
+ ;;
+ *-netbsd*)
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS="-pthread"
+ fi
+ ;;
+ *-bsdi*)
+ AC_DEFINE(_THREAD_SAFE)
+ dnl -pthread links in -lc_r, so don't specify it explicitly.
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS=
+ fi
+ ;;
+ *-openbsd*)
+ if test "$ac_cv_have_dash_pthread" = "yes"; then
+ _PTHREAD_LDFLAGS=-pthread
+ fi
+ ;;
+ *-linux*)
+ AC_DEFINE(_REENTRANT)
+ ;;
+ esac
+
+else
+ if test -n "$USE_USER_PTHREADS"; then
+ USE_PTHREADS=
+ USE_NSPR_THREADS=
+ else
+ _PTHREAD_LDFLAGS=
+ fi
+fi
+dnl Special thread exceptions
+
+case "$target" in
+*-aix*)
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ case "$target_os" in
+ aix4.1*)
+ if test -z "$USE_PTHREADS"; then
+ AC_DEFINE(AIX_RENAME_SELECT)
+ fi
+ ;;
+ aix4.2*)
+ if test -z "$USE_NSPR_THREADS"; then
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ fi
+ ;;
+ aix4.3*)
+ if test -z "$USE_NSPR_THREADS"; then
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ fi
+ if test -n "$USE_PTHREADS"; then
+ AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST)
+ fi
+ ;;
+ *)
+ if test -z "$USE_NSPR_THREADS"; then
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ fi
+ if test -n "$USE_PTHREADS"; then
+ AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST)
+ fi
+ ;;
+ esac
+ ;;
+*-bsdi*)
+ if test -n "$USE_PTHREADS"; then
+ AC_DEFINE(_PR_NEED_PTHREAD_INIT)
+ fi
+ ;;
+*-freebsd*)
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ ;;
+*-hpux*)
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ if test "$USE_PTHREADS"; then
+ if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(_PR_DCETHREADS)
+ else
+ AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L)
+ AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST)
+ fi
+ fi
+ if test "$USE_USER_PTHREADS"; then
+ AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L)
+ fi
+ ;;
+*-irix*)
+ if test "${target_os}" = "irix6.5"; then
+ if test -n "$USE_PTHREADS"; then
+ AC_DEFINE(_PR_HAVE_GETHOST_R)
+ AC_DEFINE(_PR_HAVE_GETHOST_R_POINTER)
+ fi
+ fi
+ ;;
+*-linux*)
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ ;;
+*-mingw*|*-cygwin*|*-msvc*|*-mks*)
+ dnl win32 does not use pthreads
+ USE_PTHREADS=
+ _PTHREAD_LDFLAGS=
+ USE_USER_PTHREADS=
+ ;;
+*-netbsd*|*-openbsd*)
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ ;;
+*-osf*)
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ if test -n "$USE_PTHREADS"; then
+ if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then
+ :
+ else
+ AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST)
+ fi
+ fi
+ ;;
+*-solaris*)
+ if test -n "$USE_NATIVE_THREADS"; then
+ AC_DEFINE(_PR_GLOBAL_THREADS_ONLY)
+ else
+ if test -n "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
+ fi
+ fi
+ if test -z "$USE_NSPR_THREADS"; then
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(HAVE_POINTER_LOCALTIME_R)
+ if test "$OS_TEST" = "i86pc"; then
+ PR_MD_ASFILES=os_SunOS_x86.s
+ else
+ PR_MD_ASFILES=os_SunOS.s
+ if test -n "$USE_64"; then
+ PR_MD_ASFILES="$PR_MD_ASFILES os_SunOS_sparcv9.s"
+ fi
+ fi
+ fi
+ ;;
+*-nto*)
+ if test -n "$USE_PTHREADS"; then
+ AC_DEFINE(_PR_HAVE_GETHOST_R)
+ AC_DEFINE(_PR_HAVE_GETHOST_R_POINTER)
+ fi
+ ;;
+esac
+
+OS_LIBS="$_PTHREAD_LDFLAGS $OS_LIBS"
+
+dnl If the user passed in arg to --enable-optimize,
+dnl make sure that we use it.
+if test -n "$_SAVE_OPTIMIZE_FLAGS"; then
+ _OPTIMIZE_FLAGS="$_SAVE_OPTIMIZE_FLAGS"
+fi
+
+if test -n "$MOZ_OPTIMIZE"; then
+ CFLAGS="$CFLAGS $_OPTIMIZE_FLAGS"
+ CXXFLAGS="$CXXFLAGS $_OPTIMIZE_FLAGS"
+fi
+
+if test -n "$MOZ_DEBUG"; then
+ CFLAGS="$CFLAGS $_DEBUG_FLAGS"
+ CXXFLAGS="$CXXFLAGS $_DEBUG_FLAGS"
+fi
+
+if test -n "$MOZ_OPTIMIZE"; then
+ OBJDIR_TAG=_OPT
+else
+ OBJDIR_TAG=_DBG
+fi
+
+if test -n "$USE_64"; then
+ COMPILER_TAG=_64
+fi
+
+RELEASE_OBJDIR_NAME="${OS_CONFIG}${CPU_ARCH_TAG}${COMPILER_TAG}${IMPL_STRATEGY}${OBJDIR_TAG}.${OBJDIR_SUFFIX}"
+
+dnl ========================================================
+dnl Use cygwin wrapper for win32 builds
+dnl ========================================================
+case "$target_os" in
+mingw*|cygwin*|msvc*|mks*)
+ CC="\$(CYGWIN_WRAPPER) $CC"
+ CXX="\$(CYGWIN_WRAPPER) $CXX"
+ RC="\$(CYGWIN_WRAPPER) $RC"
+ ;;
+esac
+
+dnl ========================================================
+dnl Substitution of found variables.
+dnl ========================================================
+AC_SUBST(SHELL_OVERRIDE)
+
+AC_SUBST(MOZILLA_CLIENT)
+AC_SUBST(CC)
+AC_SUBST(CXX)
+AC_SUBST(CFLAGS)
+AC_SUBST(CXXFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(HOST_CC)
+AC_SUBST(HOST_CFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(GNU_CC)
+AC_SUBST(GCC_USE_GNU_LD)
+AC_SUBST(MSC_VER)
+AC_SUBST(CROSS_COMPILE)
+
+AC_SUBST(MOZ_OPTIMIZE)
+
+AC_SUBST(USE_CPLUS)
+AC_SUBST(USE_IPV6)
+AC_SUBST(USE_N32)
+AC_SUBST(USE_64)
+AC_SUBST(OBJECT_MODE)
+AC_SUBST(GC_LEAK_DETECTOR)
+AC_SUBST(ENABLE_STRIP)
+
+AC_SUBST(USE_PTHREADS)
+AC_SUBST(USE_BTHREADS)
+AC_SUBST(USE_USER_PTHREADS)
+AC_SUBST(USE_NATIVE_THREADS)
+AC_SUBST(USE_NSPR_THREADS)
+
+AC_SUBST(LIBNSPR)
+AC_SUBST(LIBPLC)
+
+AC_SUBST(MOD_MAJOR_VERSION)
+AC_SUBST(MOD_MINOR_VERSION)
+AC_SUBST(MOD_PATCH_VERSION)
+AC_SUBST(NSPR_MODNAME)
+AC_SUBST(MDCPUCFG_H)
+AC_SUBST(PR_MD_CSRCS)
+AC_SUBST(PR_MD_ASFILES)
+AC_SUBST(PR_MD_ARCH_DIR)
+AC_SUBST(CPU_ARCH)
+
+AC_SUBST(OBJ_SUFFIX)
+AC_SUBST(LIB_SUFFIX)
+AC_SUBST(DLL_SUFFIX)
+AC_SUBST(ASM_SUFFIX)
+AC_SUBST(MKSHLIB)
+AC_SUBST(DSO_CFLAGS)
+AC_SUBST(DSO_LDOPTS)
+
+AC_SUBST(OS_TARGET)
+AC_SUBST(OS_ARCH)
+AC_SUBST(OS_RELEASE)
+AC_SUBST(OS_TEST)
+AC_SUBST(MACOS_DEPLOYMENT_TARGET)
+
+AC_SUBST(DEFINES)
+AC_SUBST(DEFS)
+AC_SUBST(AR)
+AC_SUBST(AR_FLAGS)
+AC_SUBST(AS)
+AC_SUBST(ASFLAGS)
+AC_SUBST(LD)
+AC_SUBST(RANLIB)
+AC_SUBST(PERL)
+AC_SUBST(STRIP)
+AC_SUBST(FILTER)
+AC_SUBST(IMPLIB)
+
+AC_SUBST(OS_LIBS)
+AC_SUBST(RESOLVE_LINK_SYMBOLS)
+AC_SUBST(AIX_LINK_OPTS)
+AC_SUBST(NOSUCHFILE)
+AC_SUBST(MOZ_OBJFORMAT)
+AC_SUBST(ULTRASPARC_LIBRARY)
+
+AC_SUBST(OBJDIR)
+AC_SUBST(OBJDIR_NAME)
+AC_SUBST(RELEASE_OBJDIR_NAME)
+AC_SUBST(NSINSTALL)
+AC_SUBST(OPTIMIZER)
+AC_SUBST(RC)
+AC_SUBST(RCFLAGS)
+AC_SUBST(DLLFLAGS)
+AC_SUBST(EXEFLAGS)
+AC_SUBST(OS_DLLFLAGS)
+AC_SUBST(CYGWIN_WRAPPER)
+
+dnl ========================================================
+dnl Generate output files.
+dnl ========================================================
+MAKEFILES="
+Makefile
+config/Makefile
+config/autoconf.mk
+config/nsprincl.mk
+config/nsprincl.sh
+config/nspr-config
+lib/Makefile
+lib/ds/Makefile
+lib/libc/Makefile
+lib/libc/include/Makefile
+lib/libc/src/Makefile
+lib/tests/Makefile
+pkg/Makefile
+pkg/linux/Makefile
+pkg/solaris/Makefile
+pkg/solaris/SUNWpr/Makefile
+pkg/solaris/SUNWprx/Makefile
+pr/Makefile
+pr/include/Makefile
+pr/include/md/Makefile
+pr/include/obsolete/Makefile
+pr/include/private/Makefile
+pr/src/Makefile
+pr/src/io/Makefile
+pr/src/linking/Makefile
+pr/src/malloc/Makefile
+pr/src/md/Makefile
+pr/src/md/${PR_MD_ARCH_DIR}/Makefile
+pr/src/memory/Makefile
+pr/src/misc/Makefile
+pr/src/threads/Makefile
+pr/tests/Makefile
+pr/tests/dll/Makefile
+"
+
+dnl lib/tests/Makefile
+dnl pr/tests/w16gui/Makefile
+dnl tools/Makefile
+
+if test -z "$USE_PTHREADS" && test -z "$USE_BTHREADS"; then
+ MAKEFILES="$MAKEFILES pr/src/threads/combined/Makefile"
+elif test -n "$USE_PTHREADS"; then
+ MAKEFILES="$MAKEFILES pr/src/pthreads/Makefile"
+elif test -n "$USE_BTHREADS"; then
+ MAKEFILES="$MAKEFILES pr/src/bthreads/Makefile"
+fi
+
+if test -n "$USE_CPLUS"; then
+ MAKEFILES="$MAKEFILES pr/src/cplus/Makefile pr/src/cplus/tests/Makefile"
+fi
+
+AC_OUTPUT([$MAKEFILES], [chmod +x config/nspr-config])
diff --git a/src/libs/xpcom18a4/nsprpub/gmakefile.win b/src/libs/xpcom18a4/nsprpub/gmakefile.win
new file mode 100644
index 00000000..80e8809a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/gmakefile.win
@@ -0,0 +1,96 @@
+#!gmake
+# -*- Mode: Makefile -*-
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+
+ifndef MOZ_SRC_FLIPPED
+$(error MOZ_SRC_FLIPPED is not set)
+endif
+
+ifndef MOZ_TOP
+MOZ_TOP=mozilla
+endif
+
+MOZ_DIST_FLIPPED = $(MOZ_SRC_FLIPPED)/mozilla/dist
+
+ifdef MOZ_DEBUG
+MOZ_OBJDIR = WIN32_D.OBJ
+else
+MOZ_OBJDIR = WIN32_O.OBJ
+endif
+
+NSPR_CONFIGURE := ../configure \
+ --with-mozilla \
+ --with-dist-prefix=$(MOZ_DIST_FLIPPED) \
+ --with-dist-bindir=$(MOZ_DIST_FLIPPED)/$(MOZ_OBJDIR)/bin \
+ --with-dist-libdir=$(MOZ_DIST_FLIPPED)/$(MOZ_OBJDIR)/lib
+
+ifeq (,$(MOZ_DEBUG)$(MOZ_TRACE_MALLOC))
+NSPR_CONFIGURE := $(NSPR_CONFIGURE) --enable-optimize --disable-debug
+endif
+
+define MAKE_OBJDIR
+if test ! -d $(@D) ; then rm -rf $(@D) ; nsinstall -D $(@D) ; fi
+endef
+
+
+all:: build_all
+
+# Argh. nmake keeps the cwd from cmd to cmd and gmake does not
+# Furthermore, shmsdos doesn't support '&&' so there's a chance the
+# 'cd' could fail and configure would be run in the wrong dir
+#
+$(MOZ_OBJDIR)/config.status: configure configure.in
+ @$(MAKE_OBJDIR)
+ cd $(MOZ_OBJDIR)/ ; \
+ sh $(NSPR_CONFIGURE)
+
+build_all: $(MOZ_OBJDIR)/config.status check_old
+ gmake -C $(MOZ_OBJDIR)
+
+clobber_all: $(MOZ_OBJDIR)/config.status check_old
+ gmake -C $(MOZ_OBJDIR) clobber_all
+
+distclean: check_old
+ rm -rf WIN32_D.OBJ WIN32_O.OBJ
+
+check_old:
+ @if test -f Makefile; then gmake distclean; fi
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/Makefile.in
new file mode 100644
index 00000000..9bdc078e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/Makefile.in
@@ -0,0 +1,56 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+export NSPR20=1
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = ds libc
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/ds/.cvsignore
new file mode 100644
index 00000000..bcab60f5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+_pl_bld.h
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/MANIFEST b/src/libs/xpcom18a4/nsprpub/lib/ds/MANIFEST
new file mode 100644
index 00000000..ceda33b7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/MANIFEST
@@ -0,0 +1,7 @@
+#
+# This is a list of local files which get copied to the mozilla:dist directory
+#
+
+plarenas.h
+plarena.h
+plhash.h
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/ds/Makefile.in
new file mode 100644
index 00000000..516e1a37
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/Makefile.in
@@ -0,0 +1,202 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include
+
+CSRCS = \
+ plarena.c \
+ plhash.c \
+ plvrsion.c \
+ $(NULL)
+
+HEADERS = \
+ plarenas.h \
+ plarena.h \
+ plhash.h \
+ $(NULL)
+
+HEADERS := $(addprefix $(srcdir)/, $(HEADERS))
+
+ifeq ($(OS_ARCH), WINNT)
+ifdef NS_USE_GCC
+DLLBASE=-Wl,--image-base -Wl,0x30000000
+else
+DLLBASE=/BASE:0x30000000
+endif # GCC
+RES=$(OBJDIR)/plds.res
+RESNAME=plds.rc
+endif # WINNT
+
+ifeq ($(OS_ARCH), AIX)
+ifeq ($(CLASSIC_NSPR),1)
+OS_LIBS = -lc
+else
+OS_LIBS = -lc_r
+endif
+endif
+
+ifeq ($(OS_ARCH),IRIX)
+OS_LIBS = -lc
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+OS_LIBS = -lc
+MAPFILE = $(OBJDIR)/pldsmap.sun
+GARBAGE += $(MAPFILE)
+ifdef NS_USE_GCC
+ifdef GCC_USE_GNU_LD
+MKSHLIB += -Wl,--version-script,$(MAPFILE)
+else
+MKSHLIB += -Wl,-M,$(MAPFILE)
+endif
+else
+MKSHLIB += -M $(MAPFILE)
+endif
+# The -R '$ORIGIN' linker option instructs this library to search for its
+# dependencies in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+
+ifeq ($(OS_ARCH),OS2)
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+GARBAGE += $(MAPFILE)
+MKSHLIB += $(MAPFILE)
+endif
+
+EXTRA_LIBS = $(LIBNSPR)
+
+# On NCR and SCOOS, we can't link with extra libraries when
+# we build a shared library. If we do so, the linker doesn't
+# complain, but we would run into weird problems at run-time.
+# Therefore on these platforms, we link just the .o files.
+ifeq ($(OS_ARCH),NCR)
+EXTRA_LIBS =
+endif
+ifeq ($(OS_ARCH),SCOOS)
+EXTRA_LIBS =
+endif
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+LIBRARY_NAME = plds
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+RELEASE_LIBS = $(TARGETS)
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = $(notdir $(SHARED_LIBRARY))
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+GARBAGE += $(TINC)
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ifeq ($(MOZ_OS2_TOOLS), VACPP)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+endif
+#
+# Version information generation (end)
+#
+
+#
+# The Client build wants the shared libraries in $(dist_bindir),
+# so we also install them there.
+#
+
+export:: $(TARGETS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifdef SHARED_LIBRARY
+ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
+endif
+endif
+ifeq ($(MOZ_BITS),16)
+ $(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
+endif
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plarena.c b/src/libs/xpcom18a4/nsprpub/lib/ds/plarena.c
new file mode 100644
index 00000000..e61efbe2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plarena.c
@@ -0,0 +1,442 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. 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 *****
+ */
+
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "plarena.h"
+#include "prmem.h"
+#include "prbit.h"
+#include "prlog.h"
+#include "prlock.h"
+#include "prinit.h"
+
+static PLArena *arena_freelist;
+
+#ifdef PL_ARENAMETER
+static PLArenaStats *arena_stats_list;
+
+#define COUNT(pool,what) (pool)->stats.what++
+#else
+#define COUNT(pool,what) /* nothing */
+#endif
+
+#define PL_ARENA_DEFAULT_ALIGN sizeof(double)
+
+static PRLock *arenaLock;
+static PRCallOnceType once;
+
+/*
+** InitializeArenas() -- Initialize arena operations.
+**
+** InitializeArenas() is called exactly once and only once from
+** LockArena(). This function creates the arena protection
+** lock: arenaLock.
+**
+** Note: If the arenaLock cannot be created, InitializeArenas()
+** fails quietly, returning only PR_FAILURE. This percolates up
+** to the application using the Arena API. He gets no arena
+** from PL_ArenaAllocate(). It's up to him to fail gracefully
+** or recover.
+**
+*/
+static PRStatus InitializeArenas( void )
+{
+ PR_ASSERT( arenaLock == NULL );
+ arenaLock = PR_NewLock();
+ if ( arenaLock == NULL )
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+} /* end ArenaInitialize() */
+
+static PRStatus LockArena( void )
+{
+ PRStatus rc = PR_CallOnce( &once, InitializeArenas );
+
+ if ( PR_FAILURE != rc )
+ PR_Lock( arenaLock );
+ return(rc);
+} /* end LockArena() */
+
+static void UnlockArena( void )
+{
+ PR_Unlock( arenaLock );
+ return;
+} /* end UnlockArena() */
+
+PR_IMPLEMENT(void) PL_InitArenaPool(
+ PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align)
+{
+#if defined(XP_MAC)
+#pragma unused (name)
+#endif
+
+ if (align == 0)
+ align = PL_ARENA_DEFAULT_ALIGN;
+ pool->mask = PR_BITMASK(PR_CeilingLog2(align));
+ pool->first.next = NULL;
+ /* Set all three addresses in pool->first to the same dummy value.
+ * These addresses are only compared with each other, but never
+ * dereferenced. */
+ pool->first.base = pool->first.avail = pool->first.limit =
+ (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ pool->arenasize = size;
+#ifdef PL_ARENAMETER
+ memset(&pool->stats, 0, sizeof pool->stats);
+ pool->stats.name = strdup(name);
+ pool->stats.next = arena_stats_list;
+ arena_stats_list = &pool->stats;
+#endif
+}
+
+
+/*
+** PL_ArenaAllocate() -- allocate space from an arena pool
+**
+** Description: PL_ArenaAllocate() allocates space from an arena
+** pool.
+**
+** First, try to satisfy the request from arenas starting at
+** pool->current.
+**
+** If there is not enough space in the arena pool->current, try
+** to claim an arena, on a first fit basis, from the global
+** freelist (arena_freelist).
+**
+** If no arena in arena_freelist is suitable, then try to
+** allocate a new arena from the heap.
+**
+** Returns: pointer to allocated space or NULL
+**
+** Notes: The original implementation had some difficult to
+** solve bugs; the code was difficult to read. Sometimes it's
+** just easier to rewrite it. I did that. larryh.
+**
+** See also: bugzilla: 45343.
+**
+*/
+
+PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb)
+{
+ PLArena *a;
+ char *rp; /* returned pointer */
+ PRUint32 nbOld;
+
+ PR_ASSERT((nb & pool->mask) == 0);
+
+ nbOld = nb;
+ nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */
+ if (nb < nbOld)
+ return NULL;
+
+ /* attempt to allocate from arenas at pool->current */
+ {
+ a = pool->current;
+ do {
+ if ( a->avail +nb <= a->limit ) {
+ pool->current = a;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ return rp;
+ }
+ } while( NULL != (a = a->next) );
+ }
+
+ /* attempt to allocate from arena_freelist */
+ {
+ PLArena *p; /* previous pointer, for unlinking from freelist */
+
+ /* lock the arena_freelist. Make access to the freelist MT-Safe */
+ if ( PR_FAILURE == LockArena())
+ return(0);
+
+ for ( a = p = arena_freelist; a != NULL ; p = a, a = a->next ) {
+ if ( a->base +nb <= a->limit ) {
+ if ( p == arena_freelist )
+ arena_freelist = a->next;
+ else
+ p->next = a->next;
+ UnlockArena();
+ a->avail = a->base;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( NULL == pool->first.next )
+ pool->first.next = a;
+ return(rp);
+ }
+ }
+ UnlockArena();
+ }
+
+ /* attempt to allocate from the heap */
+ {
+ PRUint32 sz = PR_MAX(pool->arenasize, nb);
+ sz += sizeof *a + pool->mask; /* header and alignment slop */
+ a = (PLArena*)PR_MALLOC(sz);
+ if ( NULL != a ) {
+ a->limit = (PRUword)a + sz;
+ a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1);
+ rp = (char *)a->avail;
+ a->avail += nb;
+ PR_ASSERT(a->avail <= a->limit);
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( NULL == pool->first.next )
+ pool->first.next = a;
+ PL_COUNT_ARENA(pool,++);
+ COUNT(pool, nmallocs);
+ return(rp);
+ }
+ }
+
+ /* we got to here, and there's no memory to allocate */
+ return(NULL);
+} /* --- end PL_ArenaAllocate() --- */
+
+PR_IMPLEMENT(void *) PL_ArenaGrow(
+ PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr)
+{
+ void *newp;
+
+ if (PR_UINT32_MAX - size < incr)
+ return NULL;
+ PL_ARENA_ALLOCATE(newp, pool, size + incr);
+ if (newp)
+ memcpy(newp, p, size);
+ return newp;
+}
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree)
+{
+ PLArena **ap, *a;
+
+ ap = &head->next;
+ a = *ap;
+ if (!a)
+ return;
+
+#ifdef DEBUG
+ do {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ PL_CLEAR_UNUSED(a);
+ } while ((a = a->next) != 0);
+ a = *ap;
+#endif
+
+ if (reallyFree) {
+ do {
+ *ap = a->next;
+ PL_CLEAR_ARENA(a);
+ PL_COUNT_ARENA(pool,--);
+ PR_DELETE(a);
+ } while ((a = *ap) != 0);
+ } else {
+ /* Insert the whole arena chain at the front of the freelist. */
+ do {
+ ap = &(*ap)->next;
+ } while (*ap);
+ LockArena();
+ *ap = arena_freelist;
+ arena_freelist = a;
+ head->next = 0;
+ UnlockArena();
+ }
+
+ pool->current = head;
+}
+
+PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark)
+{
+ PLArena *a;
+
+ for (a = pool->first.next; a; a = a->next) {
+ if (PR_UPTRDIFF(mark, a->base) < PR_UPTRDIFF(a->avail, a->base)) {
+ a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark);
+ FreeArenaList(pool, a, PR_FALSE);
+ return;
+ }
+ }
+}
+
+PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, PR_FALSE);
+ COUNT(pool, ndeallocs);
+}
+
+PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, PR_TRUE);
+#ifdef PL_ARENAMETER
+ {
+ PLArenaStats *stats, **statsp;
+
+ if (pool->stats.name)
+ PR_DELETE(pool->stats.name);
+ for (statsp = &arena_stats_list; (stats = *statsp) != 0;
+ statsp = &stats->next) {
+ if (stats == &pool->stats) {
+ *statsp = stats->next;
+ return;
+ }
+ }
+ }
+#endif
+}
+
+PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap)
+{
+#if XP_MAC
+#pragma unused (ap)
+#if 0
+ PRArena *curr = &(ap->first);
+ while (curr) {
+ reallocSmaller(curr, curr->avail - (uprword_t)curr);
+ curr->limit = curr->avail;
+ curr = curr->next;
+ }
+#endif
+#endif
+}
+
+PR_IMPLEMENT(void) PL_ArenaFinish(void)
+{
+ PLArena *a, *next;
+
+ for (a = arena_freelist; a; a = next) {
+ next = a->next;
+ PR_DELETE(a);
+ }
+ arena_freelist = NULL;
+
+ if (arenaLock) {
+ PR_DestroyLock(arenaLock);
+ arenaLock = NULL;
+ }
+}
+
+#ifdef PL_ARENAMETER
+PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb)
+{
+ pool->stats.nallocs++;
+ pool->stats.nbytes += nb;
+ if (nb > pool->stats.maxalloc)
+ pool->stats.maxalloc = nb;
+ pool->stats.variance += nb * nb;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountInplaceGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr)
+{
+ pool->stats.ninplace++;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr)
+{
+ pool->stats.ngrows++;
+ pool->stats.nbytes += incr;
+ pool->stats.variance -= size * size;
+ size += incr;
+ if (size > pool->stats.maxalloc)
+ pool->stats.maxalloc = size;
+ pool->stats.variance += size * size;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark)
+{
+ pool->stats.nreleases++;
+}
+
+PR_IMPLEMENT(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark)
+{
+ pool->stats.nfastrels++;
+}
+
+#include <math.h>
+#include <stdio.h>
+
+PR_IMPLEMENT(void) PL_DumpArenaStats(FILE *fp)
+{
+ PLArenaStats *stats;
+ double mean, variance;
+
+ for (stats = arena_stats_list; stats; stats = stats->next) {
+ if (stats->nallocs != 0) {
+ mean = (double)stats->nbytes / stats->nallocs;
+ variance = fabs(stats->variance / stats->nallocs - mean * mean);
+ } else {
+ mean = variance = 0;
+ }
+
+ fprintf(fp, "\n%s allocation statistics:\n", stats->name);
+ fprintf(fp, " number of arenas: %u\n", stats->narenas);
+ fprintf(fp, " number of allocations: %u\n", stats->nallocs);
+ fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims);
+ fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
+ fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
+ fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
+ fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
+ fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
+ fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
+ fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
+ fprintf(fp, " mean allocation size: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sqrt(variance));
+ fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
+ }
+}
+#endif /* PL_ARENAMETER */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plarena.h b/src/libs/xpcom18a4/nsprpub/lib/ds/plarena.h
new file mode 100644
index 00000000..174bd975
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plarena.h
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#ifndef plarena_h___
+#define plarena_h___
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ *
+ * Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE).
+ */
+#include "prtypes.h"
+#include "plarenas.h"
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLArena PLArena;
+
+struct PLArena {
+ PLArena *next; /* next arena for this lifetime */
+ PRUword base; /* aligned base address, follows this header */
+ PRUword limit; /* one beyond last byte in arena */
+ PRUword avail; /* points to next available byte */
+};
+
+#ifdef PL_ARENAMETER
+typedef struct PLArenaStats PLArenaStats;
+
+struct PLArenaStats {
+ PLArenaStats *next; /* next in arenaStats list */
+ char *name; /* name for debugging */
+ PRUint32 narenas; /* number of arenas in pool */
+ PRUint32 nallocs; /* number of PL_ARENA_ALLOCATE() calls */
+ PRUint32 nreclaims; /* number of reclaims from freeArenas */
+ PRUint32 nmallocs; /* number of malloc() calls */
+ PRUint32 ndeallocs; /* number of lifetime deallocations */
+ PRUint32 ngrows; /* number of PL_ARENA_GROW() calls */
+ PRUint32 ninplace; /* number of in-place growths */
+ PRUint32 nreleases; /* number of PL_ARENA_RELEASE() calls */
+ PRUint32 nfastrels; /* number of "fast path" releases */
+ PRUint32 nbytes; /* total bytes allocated */
+ PRUint32 maxalloc; /* maximum allocation size in bytes */
+ PRFloat64 variance; /* size variance accumulator */
+};
+#endif
+
+struct PLArenaPool {
+ PLArena first; /* first arena in pool list */
+ PLArena *current; /* arena from which to allocate space */
+ PRUint32 arenasize; /* net exact size of a new arena */
+ PRUword mask; /* alignment mask (power-of-2 - 1) */
+#ifdef PL_ARENAMETER
+ PLArenaStats stats;
+#endif
+};
+
+/*
+ * If the including .c file uses only one power-of-2 alignment, it may define
+ * PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
+ * per ALLOCATE and GROW.
+ */
+#ifdef PL_ARENA_CONST_ALIGN_MASK
+#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \
+ & ~PL_ARENA_CONST_ALIGN_MASK)
+
+#define PL_INIT_ARENA_POOL(pool, name, size) \
+ PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1)
+#else
+#define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask)
+#endif
+
+#define PL_ARENA_ALLOCATE(p, pool, nb) \
+ PR_BEGIN_MACRO \
+ PLArena *_a = (pool)->current; \
+ PRUint32 _nb = PL_ARENA_ALIGN(pool, (PRUint32)nb); \
+ PRUword _p = _a->avail; \
+ if (_nb < (PRUint32)nb) { \
+ _p = 0; \
+ } else if (_nb > (_a->limit - _a->avail)) { \
+ _p = (PRUword)PL_ArenaAllocate(pool, _nb); \
+ } else { \
+ _a->avail += _nb; \
+ } \
+ p = (void *)_p; \
+ if (p) { \
+ PL_ArenaCountAllocation(pool, nb); \
+ } \
+ PR_END_MACRO
+
+#define PL_ARENA_GROW(p, pool, size, incr) \
+ PR_BEGIN_MACRO \
+ PLArena *_a = (pool)->current; \
+ PRUint32 _incr = PL_ARENA_ALIGN(pool, (PRUint32)incr); \
+ if (_incr < (PRUint32)incr) { \
+ p = NULL; \
+ } else if (_a->avail == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \
+ _incr <= (_a->limit - _a->avail)) { \
+ _a->avail = _incr; \
+ PL_ArenaCountInplaceGrowth(pool, size, (RTUint32)incr); \
+ } else { \
+ p = PL_ArenaGrow(pool, p, size, (PRUint32)incr); \
+ } \
+ if (p) { \
+ PL_ArenaCountGrowth(pool, size, (PRUint32)incr); \
+ } \
+ PR_END_MACRO
+
+#define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q))
+
+#ifdef DEBUG
+#define PL_FREE_PATTERN 0xDA
+#define PL_CLEAR_UNUSED(a) (PR_ASSERT((a)->avail <= (a)->limit), \
+ memset((void*)(a)->avail, PL_FREE_PATTERN, \
+ (a)->limit - (a)->avail))
+#define PL_CLEAR_ARENA(a) memset((void*)(a), PL_FREE_PATTERN, \
+ (a)->limit - (PRUword)(a))
+#else
+#define PL_CLEAR_UNUSED(a)
+#define PL_CLEAR_ARENA(a)
+#endif
+
+#define PL_ARENA_RELEASE(pool, mark) \
+ PR_BEGIN_MACRO \
+ char *_m = (char *)(mark); \
+ PLArena *_a = (pool)->current; \
+ if (PR_UPTRDIFF(_m, _a->base) <= PR_UPTRDIFF(_a->avail, _a->base)) { \
+ _a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \
+ PL_CLEAR_UNUSED(_a); \
+ PL_ArenaCountRetract(pool, _m); \
+ } else { \
+ PL_ArenaRelease(pool, _m); \
+ } \
+ PL_ArenaCountRelease(pool, _m); \
+ PR_END_MACRO
+
+#ifdef PL_ARENAMETER
+#define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
+#else
+#define PL_COUNT_ARENA(pool,op)
+#endif
+
+#define PL_ARENA_DESTROY(pool, a, pnext) \
+ PR_BEGIN_MACRO \
+ PL_COUNT_ARENA(pool,--); \
+ if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
+ *(pnext) = (a)->next; \
+ PL_CLEAR_ARENA(a); \
+ free(a); \
+ (a) = 0; \
+ PR_END_MACRO
+
+#ifdef PL_ARENAMETER
+
+#include <stdio.h>
+
+PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb);
+
+PR_EXTERN(void) PL_ArenaCountInplaceGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr);
+
+PR_EXTERN(void) PL_ArenaCountGrowth(
+ PLArenaPool *pool, PRUint32 size, PRUint32 incr);
+
+PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark);
+
+PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark);
+
+PR_EXTERN(void) PL_DumpArenaStats(FILE *fp);
+
+#else /* !PL_ARENAMETER */
+
+#define PL_ArenaCountAllocation(ap, nb) /* nothing */
+#define PL_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
+#define PL_ArenaCountGrowth(ap, size, incr) /* nothing */
+#define PL_ArenaCountRelease(ap, mark) /* nothing */
+#define PL_ArenaCountRetract(ap, mark) /* nothing */
+
+#endif /* !PL_ARENAMETER */
+
+PR_END_EXTERN_C
+
+#endif /* plarena_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plarenas.h b/src/libs/xpcom18a4/nsprpub/lib/ds/plarenas.h
new file mode 100644
index 00000000..8e8a1137
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plarenas.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#if defined(PLARENAS_H)
+#else /* defined(PLARENAS_H) */
+#define PLARENAS_H
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_ArenaAllocate VBoxNsplPL_ArenaAllocate
+#define PL_ArenaFinish VBoxNsplPL_ArenaFinish
+#define PL_ArenaGrow VBoxNsplPL_ArenaGrow
+#define PL_ArenaRelease VBoxNsplPL_ArenaRelease
+#define PL_CompactArenaPool VBoxNsplPL_CompactArenaPool
+#define PL_FinishArenaPool VBoxNsplPL_FinishArenaPool
+#define PL_FreeArenaPool VBoxNsplPL_FreeArenaPool
+#define PL_InitArenaPool VBoxNsplPL_InitArenaPool
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLArenaPool PLArenaPool;
+
+/*
+** Allocate an arena pool as specified by the parameters.
+**
+** This is equivelant to allocating the space yourself and then
+** calling PL_InitArenaPool().
+**
+** This function may fail (and return a NULL) for a variety of
+** reasons. The reason for a particular failure can be discovered
+** by calling PR_GetError().
+*/
+#if 0 /* Not implemented */
+PR_EXTERN(PLArenaPool*) PL_AllocArenaPool(
+ const char *name, PRUint32 size, PRUint32 align);
+#endif
+
+/*
+** Destroy an arena pool previously allocated by PL_AllocArenaPool().
+**
+** This function may fail if the arena is not empty and the caller
+** wishes to check for empty upon descruction.
+*/
+#if 0 /* Not implemented */
+PR_EXTERN(PRStatus) PL_DestroyArenaPool(PLArenaPool *pool, PRBool checkEmpty);
+#endif
+
+
+/*
+** Initialize an arena pool with the given name for debugging and metering,
+** with a minimum size per arena of size bytes.
+**/
+PR_EXTERN(void) PL_InitArenaPool(
+ PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align);
+
+/*
+** Finish using arenas, freeing all memory associated with them.
+**/
+PR_EXTERN(void) PL_ArenaFinish(void);
+
+/*
+** Free the arenas in pool. The user may continue to allocate from pool
+** after calling this function. There is no need to call PL_InitArenaPool()
+** again unless PL_FinishArenaPool(pool) has been called.
+**/
+PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool);
+
+/*
+** Free the arenas in pool and finish using it altogether.
+**/
+PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool);
+
+/*
+** Compact all of the arenas in a pool so that no space is wasted.
+**/
+PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool);
+
+/*
+** Friend functions used by the PL_ARENA_*() macros.
+**/
+PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb);
+
+PR_EXTERN(void *) PL_ArenaGrow(
+ PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr);
+
+PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark);
+
+PR_END_EXTERN_C
+
+#endif /* defined(PLARENAS_H) */
+
+/* plarenas */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plds.def b/src/libs/xpcom18a4/nsprpub/lib/ds/plds.def
new file mode 100644
index 00000000..9e0b505a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plds.def
@@ -0,0 +1,78 @@
+;+#
+;+# 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 Portable Runtime (NSPR).
+;+#
+;+# The Initial Developer of the Original Code is Netscape
+;+# Communications Corporation. Portions created by Netscape are
+;+# Copyright (C) 2002-2003 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.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+NSPR_4.0 {
+;+ global:
+LIBRARY plds4 ;-
+EXPORTS ;-
+PL_ArenaAllocate;
+PL_ArenaFinish;
+PL_ArenaGrow;
+PL_ArenaRelease;
+PL_CompactArenaPool;
+PL_CompareStrings;
+PL_CompareValues;
+PL_FinishArenaPool;
+PL_FreeArenaPool;
+PL_HashString;
+PL_HashTableAdd;
+PL_HashTableDestroy;
+PL_HashTableDump;
+PL_HashTableEnumerateEntries;
+PL_HashTableLookup;
+PL_HashTableRawAdd;
+PL_HashTableRawLookup;
+PL_HashTableRawRemove;
+PL_HashTableRemove;
+PL_InitArenaPool;
+PL_NewHashTable;
+libVersionPoint;
+;+ local: *;
+;+};
+;+
+;+NSPR_4.1 {
+;+ global:
+PL_HashTableLookupConst;
+PL_HashTableRawLookupConst;
+;+} NSPR_4.0;
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plds.rc b/src/libs/xpcom18a4/nsprpub/lib/ds/plds.rc
new file mode 100644
index 00000000..fa64e192
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plds.rc
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "plds"
+#define MY_FILEDESCRIPTION "PLDS Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plds_symvec.opt b/src/libs/xpcom18a4/nsprpub/lib/ds/plds_symvec.opt
new file mode 100644
index 00000000..71784540
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plds_symvec.opt
@@ -0,0 +1,37 @@
+! Fixed section of symbol vector for LIBPLDS4
+!
+GSMATCH=LEQUAL,2,2
+case_sensitive=YES
+!
+! --------------------------------------------------------------------------
+! Ident 2,2 introduced for Mozilla 1.3
+! Previously this was empty. Now we include everything that's specified in
+! plds.def.
+! --------------------------------------------------------------------------
+!
+! NSPR 4.0
+SYMBOL_VECTOR=(PL_ArenaAllocate=PROCEDURE)
+SYMBOL_VECTOR=(PL_ArenaFinish=PROCEDURE)
+SYMBOL_VECTOR=(PL_ArenaGrow=PROCEDURE)
+SYMBOL_VECTOR=(PL_ArenaRelease=PROCEDURE)
+SYMBOL_VECTOR=(PL_CompactArenaPool=PROCEDURE)
+SYMBOL_VECTOR=(PL_CompareStrings=PROCEDURE)
+SYMBOL_VECTOR=(PL_CompareValues=PROCEDURE)
+SYMBOL_VECTOR=(PL_FinishArenaPool=PROCEDURE)
+SYMBOL_VECTOR=(PL_FreeArenaPool=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashString=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableAdd=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableDestroy=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableDump=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableEnumerateEntries=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableLookup=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableRawAdd=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableRawLookup=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableRawRemove=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableRemove=PROCEDURE)
+SYMBOL_VECTOR=(PL_InitArenaPool=PROCEDURE)
+SYMBOL_VECTOR=(PL_NewHashTable=PROCEDURE)
+SYMBOL_VECTOR=(libVersionPoint=PROCEDURE)
+! NSPR 4.1
+SYMBOL_VECTOR=(PL_HashTableLookupConst=PROCEDURE)
+SYMBOL_VECTOR=(PL_HashTableRawLookupConst=PROCEDURE)
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plhash.c b/src/libs/xpcom18a4/nsprpub/lib/ds/plhash.c
new file mode 100644
index 00000000..98ce5959
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plhash.c
@@ -0,0 +1,541 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * PL hash table package.
+ */
+#include "plhash.h"
+#include "prbit.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prtypes.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* Compute the number of buckets in ht */
+#define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift))
+
+/* The smallest table has 16 buckets */
+#define MINBUCKETSLOG2 4
+#define MINBUCKETS (1 << MINBUCKETSLOG2)
+
+/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
+#define OVERLOADED(n) ((n) - ((n) >> 3))
+
+/* Compute the number of entries below which we shrink the table by half */
+#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
+
+/*
+** Stubs for default hash allocator ops.
+*/
+static void * PR_CALLBACK
+DefaultAllocTable(void *pool, PRSize size)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ return PR_MALLOC(size);
+}
+
+static void PR_CALLBACK
+DefaultFreeTable(void *pool, void *item)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ PR_Free(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+DefaultAllocEntry(void *pool, const void *key)
+{
+#if defined(XP_MAC)
+#pragma unused (pool,key)
+#endif
+
+ return PR_NEW(PLHashEntry);
+}
+
+static void PR_CALLBACK
+DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY)
+ PR_Free(he);
+}
+
+static PLHashAllocOps defaultHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, DefaultFreeEntry
+};
+
+PR_IMPLEMENT(PLHashTable *)
+PL_NewHashTable(PRUint32 n, PLHashFunction keyHash,
+ PLHashComparator keyCompare, PLHashComparator valueCompare,
+ const PLHashAllocOps *allocOps, void *allocPriv)
+{
+ PLHashTable *ht;
+ PRSize nb;
+
+ if (n <= MINBUCKETS) {
+ n = MINBUCKETSLOG2;
+ } else {
+ n = PR_CeilingLog2(n);
+ if ((PRInt32)n < 0)
+ return 0;
+ }
+
+ if (!allocOps) allocOps = &defaultHashAllocOps;
+
+ ht = (PLHashTable*)((*allocOps->allocTable)(allocPriv, sizeof *ht));
+ if (!ht)
+ return 0;
+ memset(ht, 0, sizeof *ht);
+ ht->shift = PL_HASH_BITS - n;
+ n = 1 << n;
+#if defined(WIN16)
+ if (n > 16000) {
+ (*allocOps->freeTable)(allocPriv, ht);
+ return 0;
+ }
+#endif /* WIN16 */
+ nb = n * sizeof(PLHashEntry *);
+ ht->buckets = (PLHashEntry**)((*allocOps->allocTable)(allocPriv, nb));
+ if (!ht->buckets) {
+ (*allocOps->freeTable)(allocPriv, ht);
+ return 0;
+ }
+ memset(ht->buckets, 0, nb);
+
+ ht->keyHash = keyHash;
+ ht->keyCompare = keyCompare;
+ ht->valueCompare = valueCompare;
+ ht->allocOps = allocOps;
+ ht->allocPriv = allocPriv;
+ return ht;
+}
+
+PR_IMPLEMENT(void)
+PL_HashTableDestroy(PLHashTable *ht)
+{
+ PRUint32 i, n;
+ PLHashEntry *he, *next;
+ const PLHashAllocOps *allocOps = ht->allocOps;
+ void *allocPriv = ht->allocPriv;
+
+ n = NBUCKETS(ht);
+ for (i = 0; i < n; i++) {
+ for (he = ht->buckets[i]; he; he = next) {
+ next = he->next;
+ (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
+ }
+ }
+#ifdef DEBUG
+ memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
+#endif
+ (*allocOps->freeTable)(allocPriv, ht->buckets);
+#ifdef DEBUG
+ memset(ht, 0xDB, sizeof *ht);
+#endif
+ (*allocOps->freeTable)(allocPriv, ht);
+}
+
+/*
+** Multiplicative hash, from Knuth 6.4.
+*/
+#define GOLDEN_RATIO 0x9E3779B9U /* 2/(1+sqrt(5))*(2^32) */
+
+PR_IMPLEMENT(PLHashEntry **)
+PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key)
+{
+ PLHashEntry *he, **hep, **hep0;
+ PLHashNumber h;
+
+#ifdef HASHMETER
+ ht->nlookups++;
+#endif
+ h = keyHash * GOLDEN_RATIO;
+ h >>= ht->shift;
+ hep = hep0 = &ht->buckets[h];
+ while ((he = *hep) != 0) {
+ if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
+ /* Move to front of chain if not already there */
+ if (hep != hep0) {
+ *hep = he->next;
+ he->next = *hep0;
+ *hep0 = he;
+ }
+ return hep0;
+ }
+ hep = &he->next;
+#ifdef HASHMETER
+ ht->nsteps++;
+#endif
+ }
+ return hep;
+}
+
+/*
+** Same as PL_HashTableRawLookup but doesn't reorder the hash entries.
+*/
+PR_IMPLEMENT(PLHashEntry **)
+PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash,
+ const void *key)
+{
+ PLHashEntry *he, **hep;
+ PLHashNumber h;
+
+#ifdef HASHMETER
+ ht->nlookups++;
+#endif
+ h = keyHash * GOLDEN_RATIO;
+ h >>= ht->shift;
+ hep = &ht->buckets[h];
+ while ((he = *hep) != 0) {
+ if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) {
+ break;
+ }
+ hep = &he->next;
+#ifdef HASHMETER
+ ht->nsteps++;
+#endif
+ }
+ return hep;
+}
+
+PR_IMPLEMENT(PLHashEntry *)
+PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep,
+ PLHashNumber keyHash, const void *key, void *value)
+{
+ PRUint32 i, n;
+ PLHashEntry *he, *next, **oldbuckets;
+ PRSize nb;
+
+ /* Grow the table if it is overloaded */
+ n = NBUCKETS(ht);
+ if (ht->nentries >= OVERLOADED(n)) {
+ oldbuckets = ht->buckets;
+#if defined(WIN16)
+ if (2 * n > 16000)
+ return 0;
+#endif /* WIN16 */
+ nb = 2 * n * sizeof(PLHashEntry *);
+ ht->buckets = (PLHashEntry**)
+ ((*ht->allocOps->allocTable)(ht->allocPriv, nb));
+ if (!ht->buckets) {
+ ht->buckets = oldbuckets;
+ return 0;
+ }
+ memset(ht->buckets, 0, nb);
+#ifdef HASHMETER
+ ht->ngrows++;
+#endif
+ ht->shift--;
+
+ for (i = 0; i < n; i++) {
+ for (he = oldbuckets[i]; he; he = next) {
+ next = he->next;
+ hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
+ PR_ASSERT(*hep == 0);
+ he->next = 0;
+ *hep = he;
+ }
+ }
+#ifdef DEBUG
+ memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
+#endif
+ (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ }
+
+ /* Make a new key value entry */
+ he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
+ if (!he)
+ return 0;
+ he->keyHash = keyHash;
+ he->key = key;
+ he->value = value;
+ he->next = *hep;
+ *hep = he;
+ ht->nentries++;
+ return he;
+}
+
+PR_IMPLEMENT(PLHashEntry *)
+PL_HashTableAdd(PLHashTable *ht, const void *key, void *value)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != 0) {
+ /* Hit; see if values match */
+ if ((*ht->valueCompare)(he->value, value)) {
+ /* key,value pair is already present in table */
+ return he;
+ }
+ if (he->value)
+ (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE);
+ he->value = value;
+ return he;
+ }
+ return PL_HashTableRawAdd(ht, hep, keyHash, key, value);
+}
+
+PR_IMPLEMENT(void)
+PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he)
+{
+ PRUint32 i, n;
+ PLHashEntry *next, **oldbuckets;
+ PRSize nb;
+
+ *hep = he->next;
+ (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);
+
+ /* Shrink table if it's underloaded */
+ n = NBUCKETS(ht);
+ if (--ht->nentries < UNDERLOADED(n)) {
+ oldbuckets = ht->buckets;
+ nb = n * sizeof(PLHashEntry*) / 2;
+ ht->buckets = (PLHashEntry**)(
+ (*ht->allocOps->allocTable)(ht->allocPriv, nb));
+ if (!ht->buckets) {
+ ht->buckets = oldbuckets;
+ return;
+ }
+ memset(ht->buckets, 0, nb);
+#ifdef HASHMETER
+ ht->nshrinks++;
+#endif
+ ht->shift++;
+
+ for (i = 0; i < n; i++) {
+ for (he = oldbuckets[i]; he; he = next) {
+ next = he->next;
+ hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
+ PR_ASSERT(*hep == 0);
+ he->next = 0;
+ *hep = he;
+ }
+ }
+#ifdef DEBUG
+ memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
+#endif
+ (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
+ }
+}
+
+PR_IMPLEMENT(PRBool)
+PL_HashTableRemove(PLHashTable *ht, const void *key)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) == 0)
+ return PR_FALSE;
+
+ /* Hit; remove element */
+ PL_HashTableRawRemove(ht, hep, he);
+ return PR_TRUE;
+}
+
+PR_IMPLEMENT(void *)
+PL_HashTableLookup(PLHashTable *ht, const void *key)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != 0) {
+ return he->value;
+ }
+ return 0;
+}
+
+/*
+** Same as PL_HashTableLookup but doesn't reorder the hash entries.
+*/
+PR_IMPLEMENT(void *)
+PL_HashTableLookupConst(PLHashTable *ht, const void *key)
+{
+ PLHashNumber keyHash;
+ PLHashEntry *he, **hep;
+
+ keyHash = (*ht->keyHash)(key);
+ hep = PL_HashTableRawLookupConst(ht, keyHash, key);
+ if ((he = *hep) != 0) {
+ return he->value;
+ }
+ return 0;
+}
+
+/*
+** Iterate over the entries in the hash table calling func for each
+** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP).
+** Return a count of the number of elements scanned.
+*/
+PR_IMPLEMENT(int)
+PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg)
+{
+ PLHashEntry *he, **hep;
+ PRUint32 i, nbuckets;
+ int rv, n = 0;
+ PLHashEntry *todo = 0;
+
+ nbuckets = NBUCKETS(ht);
+ for (i = 0; i < nbuckets; i++) {
+ hep = &ht->buckets[i];
+ while ((he = *hep) != 0) {
+ rv = (*f)(he, n, arg);
+ n++;
+ if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) {
+ *hep = he->next;
+ if (rv & HT_ENUMERATE_REMOVE) {
+ he->next = todo;
+ todo = he;
+ }
+ } else {
+ hep = &he->next;
+ }
+ if (rv & HT_ENUMERATE_STOP) {
+ goto out;
+ }
+ }
+ }
+
+out:
+ hep = &todo;
+ while ((he = *hep) != 0) {
+ PL_HashTableRawRemove(ht, hep, he);
+ }
+ return n;
+}
+
+#ifdef HASHMETER
+#include <math.h>
+#include <stdio.h>
+
+PR_IMPLEMENT(void)
+PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
+{
+ double mean, variance;
+ PRUint32 nchains, nbuckets;
+ PRUint32 i, n, maxChain, maxChainLen;
+ PLHashEntry *he;
+
+ variance = 0;
+ nchains = 0;
+ maxChainLen = 0;
+ nbuckets = NBUCKETS(ht);
+ for (i = 0; i < nbuckets; i++) {
+ he = ht->buckets[i];
+ if (!he)
+ continue;
+ nchains++;
+ for (n = 0; he; he = he->next)
+ n++;
+ variance += n * n;
+ if (n > maxChainLen) {
+ maxChainLen = n;
+ maxChain = i;
+ }
+ }
+ mean = (double)ht->nentries / nchains;
+ variance = fabs(variance / nchains - mean * mean);
+
+ fprintf(fp, "\nHash table statistics:\n");
+ fprintf(fp, " number of lookups: %u\n", ht->nlookups);
+ fprintf(fp, " number of entries: %u\n", ht->nentries);
+ fprintf(fp, " number of grows: %u\n", ht->ngrows);
+ fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
+ fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
+ / ht->nlookups);
+ fprintf(fp, "mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sqrt(variance));
+ fprintf(fp, " max hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " max hash chain: [%u]\n", maxChain);
+
+ for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
+ if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
+ break;
+}
+#endif /* HASHMETER */
+
+PR_IMPLEMENT(int)
+PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
+{
+ int count;
+
+ count = PL_HashTableEnumerateEntries(ht, dump, fp);
+#ifdef HASHMETER
+ PL_HashTableDumpMeter(ht, dump, fp);
+#endif
+ return count;
+}
+
+PR_IMPLEMENT(PLHashNumber)
+PL_HashString(const void *key)
+{
+ PLHashNumber h;
+ const PRUint8 *s;
+
+ h = 0;
+ for (s = (const PRUint8*)key; *s; s++)
+ h = (h >> 28) ^ (h << 4) ^ *s;
+ return h;
+}
+
+PR_IMPLEMENT(int)
+PL_CompareStrings(const void *v1, const void *v2)
+{
+ return strcmp((const char*)v1, (const char*)v2) == 0;
+}
+
+PR_IMPLEMENT(int)
+PL_CompareValues(const void *v1, const void *v2)
+{
+ return v1 == v2;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plhash.h b/src/libs/xpcom18a4/nsprpub/lib/ds/plhash.h
new file mode 100644
index 00000000..e899c0dc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plhash.h
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef plhash_h___
+#define plhash_h___
+/*
+ * API to portable hash table code.
+ */
+#include <stdio.h>
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_CompareStrings VBoxNsplPL_CompareStrings
+#define PL_CompareValues VBoxNsplPL_CompareValues
+#define PL_HashString VBoxNsplPL_HashString
+#define PL_HashTableAdd VBoxNsplPL_HashTableAdd
+#define PL_HashTableDestroy VBoxNsplPL_HashTableDestroy
+#define PL_HashTableLookup VBoxNsplPL_HashTableLookup
+#define PL_HashTableRemove VBoxNsplPL_HashTableRemove
+#define PL_NewHashTable VBoxNsplPL_NewHashTable
+#define PL_HashTableDump VBoxNsplPL_HashTableDump
+#define PL_HashTableEnumerateEntries VBoxNsplPL_HashTableEnumerateEntries
+#define PL_HashTableLookupConst VBoxNsplPL_HashTableLookupConst
+#define PL_HashTableRawAdd VBoxNsplPL_HashTableRawAdd
+#define PL_HashTableRawLookup VBoxNsplPL_HashTableRawLookup
+#define PL_HashTableRawLookupConst VBoxNsplPL_HashTableRawLookupConst
+#define PL_HashTableRawRemove VBoxNsplPL_HashTableRawRemove
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLHashEntry PLHashEntry;
+typedef struct PLHashTable PLHashTable;
+typedef PRUint32 PLHashNumber;
+#define PL_HASH_BITS 32 /* Number of bits in PLHashNumber */
+typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key);
+typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2);
+
+#if defined(XP_OS2_VACPP) && defined(VACPP_FLIP) /* for nsSpaceManager.cpp */
+PR_END_EXTERN_C /* and nsHTMLDocument.cpp */
+#endif
+typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg);
+
+#if defined(XP_OS2_VACPP) && defined(VACPP_FLIP)
+PR_BEGIN_EXTERN_C
+#endif
+
+/* Flag bits in PLHashEnumerator's return value */
+#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
+#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
+#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
+#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */
+
+typedef struct PLHashAllocOps {
+ void * (PR_CALLBACK *allocTable)(void *pool, PRSize size);
+ void (PR_CALLBACK *freeTable)(void *pool, void *item);
+ PLHashEntry * (PR_CALLBACK *allocEntry)(void *pool, const void *key);
+ void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag);
+} PLHashAllocOps;
+
+#define HT_FREE_VALUE 0 /* just free the entry's value */
+#define HT_FREE_ENTRY 1 /* free value and entire entry */
+
+struct PLHashEntry {
+ PLHashEntry *next; /* hash chain linkage */
+ PLHashNumber keyHash; /* key hash function result */
+ const void *key; /* ptr to opaque key */
+ void *value; /* ptr to opaque value */
+};
+
+struct PLHashTable {
+ PLHashEntry **buckets; /* vector of hash buckets */
+ PRUint32 nentries; /* number of entries in table */
+ PRUint32 shift; /* multiplicative hash shift */
+ PLHashFunction keyHash; /* key hash function */
+ PLHashComparator keyCompare; /* key comparison function */
+ PLHashComparator valueCompare; /* value comparison function */
+ const PLHashAllocOps *allocOps; /* allocation operations */
+ void *allocPriv; /* allocation private data */
+#ifdef HASHMETER
+ PRUint32 nlookups; /* total number of lookups */
+ PRUint32 nsteps; /* number of hash chains traversed */
+ PRUint32 ngrows; /* number of table expansions */
+ PRUint32 nshrinks; /* number of table contractions */
+#endif
+};
+
+/*
+ * Create a new hash table.
+ * If allocOps is null, use default allocator ops built on top of malloc().
+ */
+PR_EXTERN(PLHashTable *)
+PL_NewHashTable(PRUint32 numBuckets, PLHashFunction keyHash,
+ PLHashComparator keyCompare, PLHashComparator valueCompare,
+ const PLHashAllocOps *allocOps, void *allocPriv);
+
+PR_EXTERN(void)
+PL_HashTableDestroy(PLHashTable *ht);
+
+/* Higher level access methods */
+PR_EXTERN(PLHashEntry *)
+PL_HashTableAdd(PLHashTable *ht, const void *key, void *value);
+
+PR_EXTERN(PRBool)
+PL_HashTableRemove(PLHashTable *ht, const void *key);
+
+PR_EXTERN(void *)
+PL_HashTableLookup(PLHashTable *ht, const void *key);
+
+PR_EXTERN(void *)
+PL_HashTableLookupConst(PLHashTable *ht, const void *key);
+
+PR_EXTERN(PRIntn)
+PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg);
+
+/* General-purpose C string hash function. */
+PR_EXTERN(PLHashNumber)
+PL_HashString(const void *key);
+
+/* Compare strings using strcmp(), return true if equal. */
+PR_EXTERN(PRIntn)
+PL_CompareStrings(const void *v1, const void *v2);
+
+/* Stub function just returns v1 == v2 */
+PR_EXTERN(PRIntn)
+PL_CompareValues(const void *v1, const void *v2);
+
+/* Low level access methods */
+PR_EXTERN(PLHashEntry **)
+PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key);
+
+PR_EXTERN(PLHashEntry **)
+PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash,
+ const void *key);
+
+PR_EXTERN(PLHashEntry *)
+PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash,
+ const void *key, void *value);
+
+PR_EXTERN(void)
+PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he);
+
+/* This can be trivially implemented using PL_HashTableEnumerateEntries. */
+PR_EXTERN(PRIntn)
+PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp);
+
+PR_END_EXTERN_C
+
+#endif /* plhash_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/ds/plvrsion.c b/src/libs/xpcom18a4/nsprpub/lib/ds/plvrsion.c
new file mode 100644
index 00000000..486a6cb1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/ds/plvrsion.c
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplds, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
+ /* comment */ "http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+
+/* plvrsion.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/libc/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/libc/Makefile.in
new file mode 100644
index 00000000..9755225a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/Makefile.in
@@ -0,0 +1,56 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+export NSPR20=1
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = include src
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/README b/src/libs/xpcom18a4/nsprpub/lib/libc/README
new file mode 100644
index 00000000..74f24690
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/README
@@ -0,0 +1,20 @@
+NSPR 2.0 libc functions
+-----------------------
+
+Last edited: AOF 04 March 1997
+
+This directory contains various libc-types of functions. All functions in
+this directory are platform independent, thread friendly (both safe and
+efficient). They are contributed from various sources, though the contri-
+butions are monitored by the NSPR group (mailto:freier).
+
+All API items exported by these functions will contain the same three
+character prefix, "PL_" (Portable Library). Internal function names
+that are not exported (static) are of little concern, though some caution
+must be used on those elements that are 'extern' but not really intended
+to be part of the API. Those should all have a prefix of "_PL_" (is that
+legal?).
+
+The responsibility for contributions in this area are distributed among
+all interested parties.
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/libc/include/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/MANIFEST b/src/libs/xpcom18a4/nsprpub/lib/libc/include/MANIFEST
new file mode 100644
index 00000000..63e8861d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/MANIFEST
@@ -0,0 +1,9 @@
+#
+# This is a list of local files which get copied to the mozilla:dist directory
+#
+
+plbase64.h
+plerror.h
+plgetopt.h
+plresolv.h
+plstr.h
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/libc/include/Makefile.in
new file mode 100644
index 00000000..9d5e2e18
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/Makefile.in
@@ -0,0 +1,61 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/config.mk
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(HEADERS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
+ifeq ($(MOZ_BITS),16)
+ $(INSTALL) -m 444 $(HEADERS) $(MOZ_INCL)
+endif
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/README b/src/libs/xpcom18a4/nsprpub/lib/libc/include/README
new file mode 100644
index 00000000..2b852189
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/README
@@ -0,0 +1,7 @@
+NSPR 2.0 libc functions
+-----------------------
+
+Last edited: AOF 04 March 1997
+
+This directory contains the API for various libc-types of functions.
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/plbase64.h b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plbase64.h
new file mode 100644
index 00000000..d6c7ec7b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plbase64.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef _plbase64_h
+#define _plbase64_h
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_Base64Decode VBoxNsplPL_Base64Decode
+#define PL_Base64Encode VBoxNsplPL_Base64Encode
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * PL_Base64Encode
+ *
+ * This routine encodes the data pointed to by the "src" parameter using the
+ * base64 algorithm, and returns a pointer to the result. If the "srclen"
+ * parameter is not zero, it specifies the length of the source data. If it
+ * is zero, the source data is assumed to be null-terminated, and PL_strlen
+ * is used to determine the source length. If the "dest" parameter is not
+ * null, it is assumed to point to a buffer of sufficient size (which may be
+ * calculated: ((srclen + 2)/3)*4) into which the encoded data is placed
+ * (without any termination). If the "dest" parameter is null, a buffer is
+ * allocated from the heap to hold the encoded data, and the result *will*
+ * be terminated with an extra null character. It is the caller's
+ * responsibility to free the result when it is allocated. A null is returned
+ * if the allocation fails.
+ */
+
+PR_EXTERN(char *)
+PL_Base64Encode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+);
+
+/*
+ * PL_Base64Decode
+ *
+ * This routine decodes the data pointed to by the "src" parameter using
+ * the base64 algorithm, and returns a pointer to the result. The source
+ * may either include or exclude any trailing '=' characters. If the
+ * "srclen" parameter is not zero, it specifies the length of the source
+ * data. If it is zero, PL_strlen will be used to determine the source
+ * length. If the "dest" parameter is not null, it is assumed to point to
+ * a buffer of sufficient size (which may be calculated: (srclen * 3)/4
+ * when srclen includes the '=' characters) into which the decoded data
+ * is placed (without any termination). If the "dest" parameter is null,
+ * a buffer is allocated from the heap to hold the decoded data, and the
+ * result *will* be terminated with an extra null character. It is the
+ * caller's responsibility to free the result when it is allocated. A null
+ * is retuned if the allocation fails, or if the source is not well-coded.
+ */
+
+PR_EXTERN(char *)
+PL_Base64Decode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+);
+
+PR_END_EXTERN_C
+
+#endif /* _plbase64_h */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/plerror.h b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plerror.h
new file mode 100644
index 00000000..534acf2a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plerror.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: plerror.h
+** Description: Simple routine to print translate the calling thread's
+** error numbers and print them.
+*/
+
+#if defined(PLERROR_H)
+#else
+#define PLERROR_H
+
+#include "prio.h"
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_FPrintError VBoxNsplPL_FPrintError
+#define PL_PrintError VBoxNsplPL_PrintError
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+/*
+** Print the messages to "syserr" prepending 'msg' if not NULL.
+*/
+PR_EXTERN(void) PL_PrintError(const char *msg);
+
+/*
+** Print the messages to specified output file prepending 'msg' if not NULL.
+*/
+PR_EXTERN(void) PL_FPrintError(PRFileDesc *output, const char *msg);
+
+PR_END_EXTERN_C
+
+#endif /* defined(PLERROR_H) */
+
+/* plerror.h */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/plgetopt.h b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plgetopt.h
new file mode 100644
index 00000000..0f794fb0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plgetopt.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: plgetopt.h
+** Description: utilities to parse argc/argv
+*/
+
+#if defined(PLGETOPT_H_)
+#else
+#define PLGETOPT_H_
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_CreateOptState VBoxNsplPL_CreateOptState
+#define PL_DestroyOptState VBoxNsplPL_DestroyOptState
+#define PL_GetNextOpt VBoxNsplPL_GetNextOpt
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PLOptionInternal PLOptionInternal;
+
+typedef enum
+{
+ PL_OPT_OK, /* all's well with the option */
+ PL_OPT_EOL, /* end of options list */
+ PL_OPT_BAD /* invalid option (and value) */
+} PLOptStatus;
+
+typedef struct PLOptState
+{
+ char option; /* the name of the option */
+ const char *value; /* the value of that option | NULL */
+
+ PLOptionInternal *internal; /* private processing state */
+
+} PLOptState;
+
+PR_EXTERN(PLOptState*) PL_CreateOptState(
+ PRIntn argc, char **argv, const char *options);
+
+PR_EXTERN(void) PL_DestroyOptState(PLOptState *opt);
+
+PR_EXTERN(PLOptStatus) PL_GetNextOpt(PLOptState *opt);
+
+PR_END_EXTERN_C
+
+#endif /* defined(PLGETOPT_H_) */
+
+/* plgetopt.h */
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/plresolv.h b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plresolv.h
new file mode 100644
index 00000000..45d4e5e6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plresolv.h
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * plresolv.h - asynchronous name resolution using DNS
+ */
+
+#ifndef _PLRESOLV_H_
+#define _PLRESOLV_H_
+
+/*
+** THIS IS WORK IN PROGRESS. DO NOT ATTEMPT TO USE ANY PORTION OF THIS
+** API UNTIL THIS MESSAGE NO LONGER EXISTS. IF YOU DO, THEN YOU SURRENDER
+** THE RIGHT TO COMPLAIN ABOUT ANY CONTENT.
+*/
+
+#if defined(XP_UNIX)
+
+#include <prtypes.h>
+#include <prnetdb.h>
+
+NSPR_BEGIN_EXTERN_C
+
+#define PL_RESOLVE_MAXHOSTENTBUF 1024
+#define PL_RESOLVE_DEFAULT_TIMEOUT 0
+
+/* Error return codes */
+#define PL_RESOLVE_OK 0
+#define PL_RESOLVE_EWINIT 1 /* Failed to initialize window */
+#define PL_RESOLVE_EMAKE 2 /* Failed to create request */
+#define PL_RESOLVE_ELAUNCH 3 /* Error launching Async request */
+#define PL_RESOLVE_ETIMEDOUT 4 /* Request timed-out */
+#define PL_RESOLVE_EINVAL 5 /* Invalid argument */
+#define PL_RESOLVE_EOVERFLOW 6 /* Buffer Overflow */
+#define PL_RESOLVE_EUNKNOWN 7 /* berzerk error */
+
+/* ----------- Function Prototypes ----------------*/
+
+PR_EXTERN(PRStatus) PL_ResolveName(
+ const char *name, unsigned char *buf,
+ PRIntn bufsize, PRIntervalTime timeout,
+ PRHostEnt *hostentry, PRIntervalTime *ttl);
+
+PR_EXTERN(PRStatus) PL_ResolveAddr(
+ const PRNetAddr *address, unsigned char *buf,
+ PRIntn bufsize, PRIntervalTime timeout,
+ PRHostEnt *hostentry, PRIntervalTime *ttl);
+
+typedef struct PLResolveStats {
+ int re_errors;
+ int re_nu_look;
+ int re_na_look;
+ int re_replies;
+ int re_requests;
+ int re_resends;
+ int re_sent;
+ int re_timeouts;
+} PLResolveStats;
+
+typedef struct PLResoveInfo {
+ PRBool enabled;
+ PRUint32 numNameLookups;
+ PRUint32 numAddrLookups;
+ PRUint32 numLookupsInProgress;
+ PLResolveStats stats;
+} PLResoveInfo;
+
+PR_EXTERN(void) PL_ResolveInfo(PLResoveInfo *info);
+
+NSPR_END_EXTERN_C
+
+#endif /* defined(XP_UNIX) */
+
+#endif /* _PLRESOLV_H_ */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/include/plstr.h b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plstr.h
new file mode 100644
index 00000000..443da300
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/include/plstr.h
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roland Mainz <roland mainz@informatik.med.uni-giessen.de>
+ *
+ * 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 _plstr_h
+#define _plstr_h
+
+/*
+ * plstr.h
+ *
+ * This header file exports the API to the NSPR portable library or string-
+ * handling functions.
+ *
+ * This API was not designed as an "optimal" or "ideal" string library; it
+ * was based on the good ol' unix string.3 functions, and was written to
+ *
+ * 1) replace the libc functions, for cross-platform consistancy,
+ * 2) complete the API on platforms lacking common functions (e.g.,
+ * strcase*), and
+ * 3) to implement some obvious "closure" functions that I've seen
+ * people hacking around in our code.
+ *
+ * Point number three largely means that most functions have an "strn"
+ * limited-length version, and all comparison routines have a non-case-
+ * sensitive version available.
+ */
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_strlen VBoxNsplPL_strlen
+#define PL_strcmp VBoxNsplPL_strcmp
+#define PL_strncmp VBoxNsplPL_strncmp
+#define PL_strcasecmp VBoxNsplPL_strcasecmp
+#define PL_strncasecmp VBoxNsplPL_strncasecmp
+#define PL_strdup VBoxNsplPL_strdup
+#define PL_strfree VBoxNsplPL_strfree
+#define PL_strncpy VBoxNsplPL_strncpy
+#define PL_strncpyz VBoxNsplPL_strncpyz
+#define PL_strrchr VBoxNsplPL_strrchr
+#define PL_strcaserstr VBoxNsplPL_strcaserstr
+#define PL_strcasestr VBoxNsplPL_strcasestr
+#define PL_strcat VBoxNsplPL_strcat
+#define PL_strcatn VBoxNsplPL_strcatn
+#define PL_strchr VBoxNsplPL_strchr
+#define PL_strcpy VBoxNsplPL_strcpy
+#define PL_strncaserstr VBoxNsplPL_strncaserstr
+#define PL_strncasestr VBoxNsplPL_strncasestr
+#define PL_strncat VBoxNsplPL_strncat
+#define PL_strnchr VBoxNsplPL_strnchr
+#define PL_strndup VBoxNsplPL_strndup
+#define PL_strnlen VBoxNsplPL_strnlen
+#define PL_strnpbrk VBoxNsplPL_strnpbrk
+#define PL_strnprbrk VBoxNsplPL_strnprbrk
+#define PL_strnrchr VBoxNsplPL_strnrchr
+#define PL_strnrstr VBoxNsplPL_strnrstr
+#define PL_strnstr VBoxNsplPL_strnstr
+#define PL_strpbrk VBoxNsplPL_strpbrk
+#define PL_strprbrk VBoxNsplPL_strprbrk
+#define PL_strrstr VBoxNsplPL_strrstr
+#define PL_strstr VBoxNsplPL_strstr
+#define PL_strtok_r VBoxNsplPL_strtok_r
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+/*
+ * PL_strlen
+ *
+ * Returns the length of the provided string, not including the trailing '\0'.
+ */
+
+PR_EXTERN(PRUint32)
+PL_strlen(const char *str);
+
+/*
+ * PL_strnlen
+ *
+ * Returns the length of the provided string, not including the trailing '\0',
+ * up to the indicated maximum. The string will not be examined beyond the
+ * maximum; if no terminating '\0' is found, the maximum will be returned.
+ */
+
+PR_EXTERN(PRUint32)
+PL_strnlen(const char *str, PRUint32 max);
+
+/*
+ * PL_strcpy
+ *
+ * Copies the source string, up to and including the trailing '\0', into the
+ * destination buffer. It does not (can not) verify that the destination
+ * buffer is large enough. It returns the "dest" argument.
+ */
+
+PR_EXTERN(char *)
+PL_strcpy(char *dest, const char *src);
+
+/*
+ * PL_strncpy
+ *
+ * Copies the source string into the destination buffer, up to and including
+ * the trailing '\0' or up to and including the max'th character, whichever
+ * comes first. It does not (can not) verify that the destination buffer is
+ * large enough. If the source string is longer than the maximum length,
+ * the result will *not* be null-terminated (JLRU).
+ */
+
+PR_EXTERN(char *)
+PL_strncpy(char *dest, const char *src, PRUint32 max);
+
+/*
+ * PL_strncpyz
+ *
+ * Copies the source string into the destination buffer, up to and including
+ * the trailing '\0' or up but not including the max'th character, whichever
+ * comes first. It does not (can not) verify that the destination buffer is
+ * large enough. The destination string is always terminated with a '\0',
+ * unlike the traditional libc implementation. It returns the "dest" argument.
+ *
+ * NOTE: If you call this with a source "abcdefg" and a max of 5, the
+ * destination will end up with "abcd\0" (i.e., it's strlen length will be 4)!
+ *
+ * This means you can do this:
+ *
+ * char buffer[ SOME_SIZE ];
+ * PL_strncpyz(buffer, src, sizeof(buffer));
+ *
+ * and the result will be properly terminated.
+ */
+
+PR_EXTERN(char *)
+PL_strncpyz(char *dest, const char *src, PRUint32 max);
+
+/*
+ * PL_strdup
+ *
+ * Returns a pointer to a malloc'd extent of memory containing a duplicate
+ * of the argument string. The size of the allocated extent is one greater
+ * than the length of the argument string, because of the terminator. A
+ * null argument, like a zero-length argument, will result in a pointer to
+ * a one-byte extent containing the null value. This routine returns null
+ * upon malloc failure.
+ */
+
+PR_EXTERN(char *)
+PL_strdup(const char *s);
+
+/*
+ * PL_strfree
+ *
+ * Free memory allocated by PL_strdup
+ */
+
+PR_EXTERN(void)
+PL_strfree(char *s);
+
+/*
+ * PL_strndup
+ *
+ * Returns a pointer to a malloc'd extent of memory containing a duplicate
+ * of the argument string, up to the maximum specified. If the argument
+ * string has a length greater than the value of the specified maximum, the
+ * return value will be a pointer to an extent of memory of length one
+ * greater than the maximum specified. A null string, a zero-length string,
+ * or a zero maximum will all result in a pointer to a one-byte extent
+ * containing the null value. This routine returns null upon malloc failure.
+ */
+
+PR_EXTERN(char *)
+PL_strndup(const char *s, PRUint32 max);
+
+/*
+ * PL_strcat
+ *
+ * Appends a copy of the string pointed to by the second argument to the
+ * end of the string pointed to by the first. The destination buffer is
+ * not (can not be) checked for sufficient size. A null destination
+ * argument returns null; otherwise, the first argument is returned.
+ */
+
+PR_EXTERN(char *)
+PL_strcat(char *dst, const char *src);
+
+/*
+ * PL_strncat
+ *
+ * Appends a copy of the string pointed to by the second argument, up to
+ * the maximum size specified, to the end of the string pointed to by the
+ * first. The destination buffer is not (can not be) checked for sufficient
+ * size. A null destination argument returns null; otherwise, the first
+ * argument is returned. If the maximum size limits the copy, then the
+ * result will *not* be null-terminated (JLRU). A null destination
+ * returns null; otherwise, the destination argument is returned.
+ */
+
+PR_EXTERN(char *)
+PL_strncat(char *dst, const char *src, PRUint32 max);
+
+/*
+ * PL_strcatn
+ *
+ * Appends a copy of the string pointed to by the third argument, to the
+ * end of the string pointed to by the first. The second argument specifies
+ * the maximum size of the destination buffer, including the null termination.
+ * If the existing string in dst is longer than the max, no action is taken.
+ * The resulting string will be null-terminated. A null destination returns
+ * null; otherwise, the destination argument is returned.
+ */
+
+PR_EXTERN(char *)
+PL_strcatn(char *dst, PRUint32 max, const char *src);
+
+/*
+ * PL_strcmp
+ *
+ * Returns an integer, the sign of which -- positive, zero, or negative --
+ * reflects the lexical sorting order of the two strings indicated. The
+ * result is positive if the first string comes after the second. The
+ * NSPR implementation is not i18n.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strcmp(const char *a, const char *b);
+
+/*
+ * PL_strncmp
+ *
+ * Returns an integer, the sign of which -- positive, zero, or negative --
+ * reflects the lexical sorting order of the two strings indicated, up to
+ * the maximum specified. The result is positive if the first string comes
+ * after the second. The NSPR implementation is not i18n. If the maximum
+ * is zero, only the existance or non-existance (pointer is null) of the
+ * strings is compared.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strncmp(const char *a, const char *b, PRUint32 max);
+
+/*
+ * PL_strcasecmp
+ *
+ * Returns an integer, the sign of which -- positive, zero or negative --
+ * reflects the case-insensitive lexical sorting order of the two strings
+ * indicated. The result is positive if the first string comes after the
+ * second. The NSPR implementation is not i18n.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strcasecmp(const char *a, const char *b);
+
+/*
+ * PL_strncasecmp
+ *
+ * Returns an integer, the sign of which -- positive, zero or negative --
+ * reflects the case-insensitive lexical sorting order of the first n characters
+ * of the two strings indicated. The result is positive if the first string comes
+ * after the second. The NSPR implementation is not i18n.
+ */
+
+PR_EXTERN(PRIntn)
+PL_strncasecmp(const char *a, const char *b, PRUint32 max);
+
+/*
+ * PL_strchr
+ *
+ * Returns a pointer to the first instance of the specified character in the
+ * provided string. It returns null if the character is not found, or if the
+ * provided string is null. The character may be the null character.
+ */
+
+PR_EXTERN(char *)
+PL_strchr(const char *s, char c);
+
+/*
+ * PL_strrchr
+ *
+ * Returns a pointer to the last instance of the specified character in the
+ * provided string. It returns null if the character is not found, or if the
+ * provided string is null. The character may be the null character.
+ */
+
+PR_EXTERN(char *)
+PL_strrchr(const char *s, char c);
+
+/*
+ * PL_strnchr
+ *
+ * Returns a pointer to the first instance of the specified character within the
+ * first n characters of the provided string. It returns null if the character
+ * is not found, or if the provided string is null. The character may be the
+ * null character.
+ */
+
+PR_EXTERN(char *)
+PL_strnchr(const char *s, char c, PRUint32 n);
+
+/*
+ * PL_strnrchr
+ *
+ * Returns a pointer to the last instance of the specified character within the
+ * first n characters of the provided string. It returns null if the character is
+ * not found, or if the provided string is null. The character may be the null
+ * character.
+ */
+
+PR_EXTERN(char *)
+PL_strnrchr(const char *s, char c, PRUint32 n);
+
+/*
+ * NOTE: Looking for strcasechr, strcaserchr, strncasechr, or strncaserchr?
+ * Use strpbrk, strprbrk, strnpbrk or strnprbrk.
+ */
+
+/*
+ * PL_strpbrk
+ *
+ * Returns a pointer to the first instance in the first string of any character
+ * (not including the terminating null character) of the second string. It returns
+ * null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strpbrk(const char *s, const char *list);
+
+/*
+ * PL_strprbrk
+ *
+ * Returns a pointer to the last instance in the first string of any character
+ * (not including the terminating null character) of the second string. It returns
+ * null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strprbrk(const char *s, const char *list);
+
+/*
+ * PL_strnpbrk
+ *
+ * Returns a pointer to the first instance (within the first n characters) of any
+ * character (not including the terminating null character) of the second string.
+ * It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strnpbrk(const char *s, const char *list, PRUint32 n);
+
+/*
+ * PL_strnprbrk
+ *
+ * Returns a pointer to the last instance (within the first n characters) of any
+ * character (not including the terminating null character) of the second string.
+ * It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strnprbrk(const char *s, const char *list, PRUint32 n);
+
+/*
+ * PL_strstr
+ *
+ * Returns a pointer to the first instance of the little string within the
+ * big one. It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strstr(const char *big, const char *little);
+
+/*
+ * PL_strrstr
+ *
+ * Returns a pointer to the last instance of the little string within the big one.
+ * It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strrstr(const char *big, const char *little);
+
+/*
+ * PL_strnstr
+ *
+ * Returns a pointer to the first instance of the little string within the first
+ * n characters of the big one. It returns null if either string is null. It
+ * returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strnstr(const char *big, const char *little, PRUint32 n);
+
+/*
+ * PL_strnrstr
+ *
+ * Returns a pointer to the last instance of the little string within the first
+ * n characters of the big one. It returns null if either string is null. It
+ * returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strnrstr(const char *big, const char *little, PRUint32 max);
+
+/*
+ * PL_strcasestr
+ *
+ * Returns a pointer to the first instance of the little string within the big one,
+ * ignoring case. It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strcasestr(const char *big, const char *little);
+
+/*
+ * PL_strcaserstr
+ *
+ * Returns a pointer to the last instance of the little string within the big one,
+ * ignoring case. It returns null if either string is null.
+ */
+
+PR_EXTERN(char *)
+PL_strcaserstr(const char *big, const char *little);
+
+/*
+ * PL_strncasestr
+ *
+ * Returns a pointer to the first instance of the listtle string within the first
+ * n characters of the big one, ignoring case. It returns null if either string is
+ * null. It returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strncasestr(const char *big, const char *little, PRUint32 max);
+
+/*
+ * PL_strncaserstr
+ *
+ * Returns a pointer to the last instance of the little string within the first
+ * n characters of the big one, ignoring case. It returns null if either string is
+ * null. It returns null if the length of the little string is greater than n.
+ */
+
+PR_EXTERN(char *)
+PL_strncaserstr(const char *big, const char *little, PRUint32 max);
+
+/*
+ * PL_strtok_r
+ *
+ * Splits the string s1 into tokens, separated by one or more characters
+ * from the separator string s2. The argument lasts points to a
+ * user-supplied char * pointer in which PL_strtok_r stores information
+ * for it to continue scanning the same string.
+ *
+ * In the first call to PL_strtok_r, s1 points to a string and the value
+ * of *lasts is ignored. PL_strtok_r returns a pointer to the first
+ * token, writes '\0' into the character following the first token, and
+ * updates *lasts.
+ *
+ * In subsequent calls, s1 is null and lasts must stay unchanged from the
+ * previous call. The separator string s2 may be different from call to
+ * call. PL_strtok_r returns a pointer to the next token in s1. When no
+ * token remains in s1, PL_strtok_r returns null.
+ */
+
+PR_EXTERN(char *)
+PL_strtok_r(char *s1, const char *s2, char **lasts);
+
+/*
+ * Things not (yet?) included: strspn/strcspn, strsep.
+ * memchr, memcmp, memcpy, memccpy, index, rindex, bcmp, bcopy, bzero.
+ * Any and all i18n/l10n stuff.
+ */
+
+PR_END_EXTERN_C
+
+#endif /* _plstr_h */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/libc/src/.cvsignore
new file mode 100644
index 00000000..bcab60f5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+_pl_bld.h
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/libc/src/Makefile.in
new file mode 100644
index 00000000..162b3ed9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/Makefile.in
@@ -0,0 +1,202 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+INCLUDES = -I$(dist_includedir)
+
+CSRCS =\
+ plvrsion.c \
+ strlen.c \
+ strcpy.c \
+ strdup.c \
+ strcat.c \
+ strcmp.c \
+ strccmp.c \
+ strchr.c \
+ strpbrk.c \
+ strstr.c \
+ strcstr.c \
+ strtok.c \
+ base64.c \
+ plerror.c \
+ plgetopt.c \
+ $(NULL)
+
+LIBRARY_NAME = plc
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_LIBS = $(TARGETS)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef NS_USE_GCC
+DLLBASE=-Wl,--image-base -Wl,0x30000000
+else
+DLLBASE=/BASE:0x30000000
+endif
+RES=$(OBJDIR)/plc.res
+RESNAME=plc.rc
+endif # WINNT
+
+ifeq ($(OS_ARCH), AIX)
+ifeq ($(CLASSIC_NSPR),1)
+OS_LIBS = -lc
+else
+OS_LIBS = -lc_r
+endif
+endif
+
+ifeq ($(OS_ARCH),IRIX)
+OS_LIBS = -lc
+endif
+
+ifeq ($(OS_ARCH),SunOS)
+OS_LIBS = -lc
+MAPFILE = $(OBJDIR)/plcmap.sun
+GARBAGE += $(MAPFILE)
+ifdef NS_USE_GCC
+ifdef GCC_USE_GNU_LD
+MKSHLIB += -Wl,--version-script,$(MAPFILE)
+else
+MKSHLIB += -Wl,-M,$(MAPFILE)
+endif
+else
+MKSHLIB += -M $(MAPFILE)
+endif
+# The -R '$ORIGIN' linker option instructs this library to search for its
+# dependencies in the same directory where it resides.
+MKSHLIB += -R '$$ORIGIN'
+endif
+
+ifeq ($(OS_ARCH),OS2)
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+GARBAGE += $(MAPFILE)
+MKSHLIB += $(MAPFILE)
+endif
+
+EXTRA_LIBS = $(LIBNSPR)
+
+# On NCR and SCOOS, we can't link with extra libraries when
+# we build a shared library. If we do so, the linker doesn't
+# complain, but we would run into weird problems at run-time.
+# Therefore on these platforms, we link just the .o files.
+ifeq ($(OS_ARCH),NCR)
+EXTRA_LIBS =
+endif
+ifeq ($(OS_ARCH),SCOOS)
+EXTRA_LIBS =
+endif
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = $(notdir $(SHARED_LIBRARY))
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+GARBAGE += $(TINC)
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ifeq ($(MOZ_OS2_TOOLS), VACPP)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+endif
+#
+# Version information generation (end)
+#
+
+#
+# The Client build wants the shared libraries in $(dist_bindir),
+# so we also install them there.
+#
+
+export:: $(TARGETS)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifdef SHARED_LIBRARY
+ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
+endif
+endif
+ifeq ($(MOZ_BITS),16)
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
+endif
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/README b/src/libs/xpcom18a4/nsprpub/lib/libc/src/README
new file mode 100644
index 00000000..74f24690
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/README
@@ -0,0 +1,20 @@
+NSPR 2.0 libc functions
+-----------------------
+
+Last edited: AOF 04 March 1997
+
+This directory contains various libc-types of functions. All functions in
+this directory are platform independent, thread friendly (both safe and
+efficient). They are contributed from various sources, though the contri-
+butions are monitored by the NSPR group (mailto:freier).
+
+All API items exported by these functions will contain the same three
+character prefix, "PL_" (Portable Library). Internal function names
+that are not exported (static) are of little concern, though some caution
+must be used on those elements that are 'extern' but not really intended
+to be part of the API. Those should all have a prefix of "_PL_" (is that
+legal?).
+
+The responsibility for contributions in this area are distributed among
+all interested parties.
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/base64.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/base64.c
new file mode 100644
index 00000000..234d60d8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/base64.c
@@ -0,0 +1,428 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plbase64.h"
+#include "prlog.h" /* For PR_NOT_REACHED */
+#include "prmem.h" /* for malloc / PR_MALLOC */
+#include "plstr.h" /* for PL_strlen */
+
+static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static void
+encode3to4
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32 = (PRUint32)0;
+ PRIntn i, j = 18;
+
+ for( i = 0; i < 3; i++ )
+ {
+ b32 <<= 8;
+ b32 |= (PRUint32)src[i];
+ }
+
+ for( i = 0; i < 4; i++ )
+ {
+ dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
+ j -= 6;
+ }
+
+ return;
+}
+
+static void
+encode2to4
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
+ dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
+ dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
+ dest[3] = (unsigned char)'=';
+ return;
+}
+
+static void
+encode1to4
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
+ dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
+ dest[2] = (unsigned char)'=';
+ dest[3] = (unsigned char)'=';
+ return;
+}
+
+static void
+encode
+(
+ const unsigned char *src,
+ PRUint32 srclen,
+ unsigned char *dest
+)
+{
+ while( srclen >= 3 )
+ {
+ encode3to4(src, dest);
+ src += 3;
+ dest += 4;
+ srclen -= 3;
+ }
+
+ switch( srclen )
+ {
+ case 2:
+ encode2to4(src, dest);
+ break;
+ case 1:
+ encode1to4(src, dest);
+ break;
+ case 0:
+ break;
+ default:
+ PR_NOT_REACHED("coding error");
+ }
+
+ return;
+}
+
+/*
+ * PL_Base64Encode
+ *
+ * If the destination argument is NULL, a return buffer is
+ * allocated, and the data therein will be null-terminated.
+ * If the destination argument is not NULL, it is assumed to
+ * be of sufficient size, and the contents will not be null-
+ * terminated by this routine.
+ *
+ * Returns null if the allocation fails.
+ */
+
+PR_IMPLEMENT(char *)
+PL_Base64Encode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+)
+{
+ if( 0 == srclen )
+ {
+ srclen = PL_strlen(src);
+ }
+
+ if( (char *)0 == dest )
+ {
+ PRUint32 destlen = ((srclen + 2)/3) * 4;
+ dest = (char *)PR_MALLOC(destlen + 1);
+ if( (char *)0 == dest )
+ {
+ return (char *)0;
+ }
+ dest[ destlen ] = (char)0; /* null terminate */
+ }
+
+ encode((const unsigned char *)src, srclen, (unsigned char *)dest);
+ return dest;
+}
+
+static PRInt32
+codetovalue
+(
+ unsigned char c
+)
+{
+ if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
+ {
+ return (PRInt32)(c - (unsigned char)'A');
+ }
+ else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
+ {
+ return ((PRInt32)(c - (unsigned char)'a') +26);
+ }
+ else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
+ {
+ return ((PRInt32)(c - (unsigned char)'0') +52);
+ }
+ else if( (unsigned char)'+' == c )
+ {
+ return (PRInt32)62;
+ }
+ else if( (unsigned char)'/' == c )
+ {
+ return (PRInt32)63;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+static PRStatus
+decode4to3
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32 = (PRUint32)0;
+ PRInt32 bits;
+ PRIntn i;
+
+ for( i = 0; i < 4; i++ )
+ {
+ bits = codetovalue(src[i]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ b32 <<= 6;
+ b32 |= bits;
+ }
+
+ dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
+ dest[1] = (unsigned char)((b32 >> 8) & 0xFF);
+ dest[2] = (unsigned char)((b32 ) & 0xFF);
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decode3to2
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32 = (PRUint32)0;
+ PRInt32 bits;
+ PRUint32 ubits;
+
+ bits = codetovalue(src[0]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ b32 = (PRUint32)bits;
+ b32 <<= 6;
+
+ bits = codetovalue(src[1]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ b32 |= (PRUint32)bits;
+ b32 <<= 4;
+
+ bits = codetovalue(src[2]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ ubits = (PRUint32)bits;
+ b32 |= (ubits >> 2);
+
+ dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
+ dest[1] = (unsigned char)((b32 ) & 0xFF);
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decode2to1
+(
+ const unsigned char *src,
+ unsigned char *dest
+)
+{
+ PRUint32 b32;
+ PRUint32 ubits;
+ PRInt32 bits;
+
+ bits = codetovalue(src[0]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ ubits = (PRUint32)bits;
+ b32 = (ubits << 2);
+
+ bits = codetovalue(src[1]);
+ if( bits < 0 )
+ {
+ return PR_FAILURE;
+ }
+
+ ubits = (PRUint32)bits;
+ b32 |= (ubits >> 4);
+
+ dest[0] = (unsigned char)b32;
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decode
+(
+ const unsigned char *src,
+ PRUint32 srclen,
+ unsigned char *dest
+)
+{
+ PRStatus rv;
+
+ while( srclen >= 4 )
+ {
+ rv = decode4to3(src, dest);
+ if( PR_SUCCESS != rv )
+ {
+ return PR_FAILURE;
+ }
+
+ src += 4;
+ dest += 3;
+ srclen -= 4;
+ }
+
+ switch( srclen )
+ {
+ case 3:
+ rv = decode3to2(src, dest);
+ break;
+ case 2:
+ rv = decode2to1(src, dest);
+ break;
+ case 1:
+ rv = PR_FAILURE;
+ break;
+ case 0:
+ rv = PR_SUCCESS;
+ break;
+ default:
+ PR_NOT_REACHED("coding error");
+ }
+
+ return rv;
+}
+
+/*
+ * PL_Base64Decode
+ *
+ * If the destination argument is NULL, a return buffer is
+ * allocated and the data therein will be null-terminated.
+ * If the destination argument is not null, it is assumed
+ * to be of sufficient size, and the data will not be null-
+ * terminated by this routine.
+ *
+ * Returns null if the allocation fails, or if the source string is
+ * not well-formed.
+ */
+
+PR_IMPLEMENT(char *)
+PL_Base64Decode
+(
+ const char *src,
+ PRUint32 srclen,
+ char *dest
+)
+{
+ PRStatus status;
+ PRBool allocated = PR_FALSE;
+
+ if( (char *)0 == src )
+ {
+ return (char *)0;
+ }
+
+ if( 0 == srclen )
+ {
+ srclen = PL_strlen(src);
+ }
+
+ if( srclen && (0 == (srclen & 3)) )
+ {
+ if( (char)'=' == src[ srclen-1 ] )
+ {
+ if( (char)'=' == src[ srclen-2 ] )
+ {
+ srclen -= 2;
+ }
+ else
+ {
+ srclen -= 1;
+ }
+ }
+ }
+
+ if( (char *)0 == dest )
+ {
+ PRUint32 destlen = ((srclen * 3) / 4);
+ dest = (char *)PR_MALLOC(destlen + 1);
+ if( (char *)0 == dest )
+ {
+ return (char *)0;
+ }
+ dest[ destlen ] = (char)0; /* null terminate */
+ allocated = PR_TRUE;
+ }
+
+ status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
+ if( PR_SUCCESS != status )
+ {
+ if( PR_TRUE == allocated )
+ {
+ PR_DELETE(dest);
+ }
+
+ return (char *)0;
+ }
+
+ return dest;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.def b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.def
new file mode 100644
index 00000000..39eba5b7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.def
@@ -0,0 +1,94 @@
+;+#
+;+# 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 Portable Runtime (NSPR).
+;+#
+;+# The Initial Developer of the Original Code is Netscape
+;+# Communications Corporation. Portions created by Netscape are
+;+# Copyright (C) 2002-2003 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.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+NSPR_4.0 {
+;+ global:
+LIBRARY plc4 ;-
+EXPORTS ;-
+PL_Base64Decode;
+PL_Base64Encode;
+PL_CreateOptState;
+PL_DestroyOptState;
+PL_FPrintError;
+PL_GetNextOpt;
+PL_PrintError;
+PL_strcasecmp;
+PL_strcaserstr;
+PL_strcasestr;
+PL_strcat;
+PL_strcatn;
+PL_strchr;
+PL_strcmp;
+PL_strcpy;
+PL_strdup;
+PL_strfree;
+PL_strlen;
+PL_strncasecmp;
+PL_strncaserstr;
+PL_strncasestr;
+PL_strncat;
+PL_strnchr;
+PL_strncmp;
+PL_strncpy;
+PL_strncpyz;
+PL_strndup;
+PL_strnlen;
+PL_strnpbrk;
+PL_strnprbrk;
+PL_strnrchr;
+PL_strnrstr;
+PL_strnstr;
+PL_strpbrk;
+PL_strprbrk;
+PL_strrchr;
+PL_strrstr;
+PL_strstr;
+libVersionPoint;
+;+ local: *;
+;+};
+;+
+;+NSPR_4.2 {
+;+ global:
+PL_strtok_r;
+;+} NSPR_4.0;
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.rc b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.rc
new file mode 100644
index 00000000..15ca10f2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc.rc
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "plc"
+#define MY_FILEDESCRIPTION "PLC Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc_symvec.opt b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc_symvec.opt
new file mode 100644
index 00000000..8bc769e0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plc_symvec.opt
@@ -0,0 +1,53 @@
+! Fixed section of symbol vector for LIBPLC4
+!
+GSMATCH=LEQUAL,2,2
+case_sensitive=YES
+!
+! --------------------------------------------------------------------------
+! Ident 2,2 introduced for Mozilla 1.3
+! Previously this was empty. Now we include everything that's specified in
+! plc.def.
+! --------------------------------------------------------------------------
+!
+! NSPR 4.0
+SYMBOL_VECTOR=(PL_Base64Decode=PROCEDURE)
+SYMBOL_VECTOR=(PL_Base64Encode=PROCEDURE)
+SYMBOL_VECTOR=(PL_CreateOptState=PROCEDURE)
+SYMBOL_VECTOR=(PL_DestroyOptState=PROCEDURE)
+SYMBOL_VECTOR=(PL_FPrintError=PROCEDURE)
+SYMBOL_VECTOR=(PL_GetNextOpt=PROCEDURE)
+SYMBOL_VECTOR=(PL_PrintError=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcasecmp=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcaserstr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcasestr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcat=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcatn=PROCEDURE)
+SYMBOL_VECTOR=(PL_strchr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcmp=PROCEDURE)
+SYMBOL_VECTOR=(PL_strcpy=PROCEDURE)
+SYMBOL_VECTOR=(PL_strdup=PROCEDURE)
+SYMBOL_VECTOR=(PL_strfree=PROCEDURE)
+SYMBOL_VECTOR=(PL_strlen=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncasecmp=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncaserstr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncasestr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncat=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnchr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncmp=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncpy=PROCEDURE)
+SYMBOL_VECTOR=(PL_strncpyz=PROCEDURE)
+SYMBOL_VECTOR=(PL_strndup=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnlen=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnpbrk=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnprbrk=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnrchr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnrstr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strnstr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strpbrk=PROCEDURE)
+SYMBOL_VECTOR=(PL_strprbrk=PROCEDURE)
+SYMBOL_VECTOR=(PL_strrchr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strrstr=PROCEDURE)
+SYMBOL_VECTOR=(PL_strstr=PROCEDURE)
+SYMBOL_VECTOR=(libVersionPoint=PROCEDURE)
+! NSPR 4.2
+SYMBOL_VECTOR=(PL_strtok_r=PROCEDURE)
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/plerror.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plerror.c
new file mode 100644
index 00000000..4e38ee6d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plerror.c
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File:plerror.c
+** Description: Simple routine to print translate the calling thread's
+** error numbers and print them to "syserr".
+*/
+
+#include "plerror.h"
+
+#include "prprf.h"
+#include "prerror.h"
+
+PR_IMPLEMENT(void) PL_FPrintError(PRFileDesc *fd, const char *msg)
+{
+static const char *tags[] =
+{
+ "PR_OUT_OF_MEMORY_ERROR",
+ "PR_BAD_DESCRIPTOR_ERROR",
+ "PR_WOULD_BLOCK_ERROR",
+ "PR_ACCESS_FAULT_ERROR",
+ "PR_INVALID_METHOD_ERROR",
+ "PR_ILLEGAL_ACCESS_ERROR",
+ "PR_UNKNOWN_ERROR",
+ "PR_PENDING_INTERRUPT_ERROR",
+ "PR_NOT_IMPLEMENTED_ERROR",
+ "PR_IO_ERROR",
+ "PR_IO_TIMEOUT_ERROR",
+ "PR_IO_PENDING_ERROR",
+ "PR_DIRECTORY_OPEN_ERROR",
+ "PR_INVALID_ARGUMENT_ERROR",
+ "PR_ADDRESS_NOT_AVAILABLE_ERROR",
+ "PR_ADDRESS_NOT_SUPPORTED_ERROR",
+ "PR_IS_CONNECTED_ERROR",
+ "PR_BAD_ADDRESS_ERROR",
+ "PR_ADDRESS_IN_USE_ERROR",
+ "PR_CONNECT_REFUSED_ERROR",
+ "PR_NETWORK_UNREACHABLE_ERROR",
+ "PR_CONNECT_TIMEOUT_ERROR",
+ "PR_NOT_CONNECTED_ERROR",
+ "PR_LOAD_LIBRARY_ERROR",
+ "PR_UNLOAD_LIBRARY_ERROR",
+ "PR_FIND_SYMBOL_ERROR",
+ "PR_INSUFFICIENT_RESOURCES_ERROR",
+ "PR_DIRECTORY_LOOKUP_ERROR",
+ "PR_TPD_RANGE_ERROR",
+ "PR_PROC_DESC_TABLE_FULL_ERROR",
+ "PR_SYS_DESC_TABLE_FULL_ERROR",
+ "PR_NOT_SOCKET_ERROR",
+ "PR_NOT_TCP_SOCKET_ERROR",
+ "PR_SOCKET_ADDRESS_IS_BOUND_ERROR",
+ "PR_NO_ACCESS_RIGHTS_ERROR",
+ "PR_OPERATION_NOT_SUPPORTED_ERROR",
+ "PR_PROTOCOL_NOT_SUPPORTED_ERROR",
+ "PR_REMOTE_FILE_ERROR",
+ "PR_BUFFER_OVERFLOW_ERROR",
+ "PR_CONNECT_RESET_ERROR",
+ "PR_RANGE_ERROR",
+ "PR_DEADLOCK_ERROR",
+ "PR_FILE_IS_LOCKED_ERROR",
+ "PR_FILE_TOO_BIG_ERROR",
+ "PR_NO_DEVICE_SPACE_ERROR",
+ "PR_PIPE_ERROR",
+ "PR_NO_SEEK_DEVICE_ERROR",
+ "PR_IS_DIRECTORY_ERROR",
+ "PR_LOOP_ERROR",
+ "PR_NAME_TOO_LONG_ERROR",
+ "PR_FILE_NOT_FOUND_ERROR",
+ "PR_NOT_DIRECTORY_ERROR",
+ "PR_READ_ONLY_FILESYSTEM_ERROR",
+ "PR_DIRECTORY_NOT_EMPTY_ERROR",
+ "PR_FILESYSTEM_MOUNTED_ERROR",
+ "PR_NOT_SAME_DEVICE_ERROR",
+ "PR_DIRECTORY_CORRUPTED_ERROR",
+ "PR_FILE_EXISTS_ERROR",
+ "PR_MAX_DIRECTORY_ENTRIES_ERROR",
+ "PR_INVALID_DEVICE_STATE_ERROR",
+ "PR_DEVICE_IS_LOCKED_ERROR",
+ "PR_NO_MORE_FILES_ERROR",
+ "PR_END_OF_FILE_ERROR",
+ "PR_FILE_SEEK_ERROR",
+ "PR_FILE_IS_BUSY_ERROR",
+ "<unused error code>",
+ "PR_IN_PROGRESS_ERROR",
+ "PR_ALREADY_INITIATED_ERROR",
+ "PR_GROUP_EMPTY_ERROR",
+ "PR_INVALID_STATE_ERROR",
+ "PR_NETWORK_DOWN_ERROR",
+ "PR_SOCKET_SHUTDOWN_ERROR",
+ "PR_CONNECT_ABORTED_ERROR",
+ "PR_HOST_UNREACHABLE_ERROR",
+ "PR_MAX_ERROR"
+};
+
+PRErrorCode error = PR_GetError();
+PRInt32 oserror = PR_GetOSError();
+PRIntn thoseIKnowAbout = sizeof(tags) / sizeof(char*);
+PRIntn lastError = PR_NSPR_ERROR_BASE + thoseIKnowAbout;
+
+ if (NULL != msg) PR_fprintf(fd, "%s: ", msg);
+ if ((error < PR_NSPR_ERROR_BASE) || (error >= lastError))
+ PR_fprintf(
+ fd, " (%d)OUT OF RANGE, oserror = %d\n", error, oserror);
+ else
+ PR_fprintf(
+ fd, "%s(%d), oserror = %d\n",
+ tags[error - PR_NSPR_ERROR_BASE], error, oserror);
+} /* PL_FPrintError */
+
+PR_IMPLEMENT(void) PL_PrintError(const char *msg)
+{
+ static PRFileDesc *fd = NULL;
+ if (NULL == fd) fd = PR_GetSpecialFD(PR_StandardError);
+ PL_FPrintError(fd, msg);
+} /* PL_PrintError */
+
+#if defined(WIN16)
+/*
+** libmain() is a required function for win16
+**
+*/
+int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
+ WORD cbHeapSize, LPSTR lpszCmdLine )
+{
+return TRUE;
+}
+#endif /* WIN16 */
+
+
+
+
+
+/* plerror.c */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/plgetopt.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plgetopt.c
new file mode 100644
index 00000000..e2ccfa1b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plgetopt.c
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: plgetopt.c
+** Description: utilities to parse argc/argv
+*/
+
+#include "prmem.h"
+#include "prlog.h"
+#include "prerror.h"
+#include "plstr.h"
+#include "plgetopt.h"
+
+#include <string.h>
+
+static char static_Nul = 0;
+
+struct PLOptionInternal
+{
+ const char *options; /* client options list specification */
+ PRIntn argc; /* original number of arguments */
+ char **argv; /* vector of pointers to arguments */
+ PRIntn xargc; /* which one we're processing now */
+ const char *xargv; /* where within *argv[xargc] */
+ PRBool minus; /* do we already have the '-'? */
+};
+
+/*
+** Create the state in which to parse the tokens.
+**
+** argc the sum of the number of options and their values
+** argv the options and their values
+** options vector of single character options w/ | w/o ':
+*/
+PR_IMPLEMENT(PLOptState*) PL_CreateOptState(
+ PRIntn argc, char **argv, const char *options)
+{
+ PLOptState *opt = NULL;
+ if (NULL == options)
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ else
+ {
+ opt = PR_NEWZAP(PLOptState);
+ if (NULL == opt)
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ PLOptionInternal *internal = PR_NEW(PLOptionInternal);
+ if (NULL == internal)
+ {
+ PR_DELETE(opt);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+ else
+ {
+ opt->option = 0;
+ opt->value = NULL;
+ opt->internal = internal;
+
+ internal->argc = argc;
+ internal->argv = argv;
+ internal->xargc = 0;
+ internal->xargv = &static_Nul;
+ internal->minus = PR_FALSE;
+ internal->options = options;
+ }
+ }
+ }
+ return opt;
+} /* PL_CreateOptState */
+
+/*
+** Destroy object created by CreateOptState()
+*/
+PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt)
+{
+ PR_DELETE(opt->internal);
+ PR_DELETE(opt);
+} /* PL_DestroyOptState */
+
+PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt)
+{
+ PLOptionInternal *internal = opt->internal;
+ PRIntn cop, eoo = PL_strlen(internal->options);
+
+ /*
+ ** If the current xarg points to nul, advance to the next
+ ** element of the argv vector. If the vector index is equal
+ ** to argc, we're out of arguments, so return an EOL.
+ ** Note whether the first character of the new argument is
+ ** a '-' and skip by it if it is.
+ */
+ while (0 == *internal->xargv)
+ {
+ internal->xargc += 1;
+ if (internal->xargc >= internal->argc)
+ {
+ opt->option = 0;
+ opt->value = NULL;
+ return PL_OPT_EOL;
+ }
+ internal->xargv = internal->argv[internal->xargc];
+ internal->minus = ('-' == *internal->xargv ? PR_TRUE : PR_FALSE); /* not it */
+ if (internal->minus) internal->xargv += 1; /* and consume */
+ }
+
+ /*
+ ** If we already have a '-' in hand, xargv points to the next
+ ** option. See if we can find a match in the list of possible
+ ** options supplied.
+ */
+
+ if (internal->minus)
+ {
+ for (cop = 0; cop < eoo; ++cop)
+ {
+ if (internal->options[cop] == *internal->xargv)
+ {
+ opt->option = *internal->xargv;
+ internal->xargv += 1;
+ /*
+ ** if options indicates that there's an associated
+ ** value, this argv is finished and the next is the
+ ** option's value.
+ */
+ if (':' == internal->options[cop + 1])
+ {
+ if (0 != *internal->xargv) return PL_OPT_BAD;
+ opt->value = internal->argv[++(internal->xargc)];
+ internal->xargv = &static_Nul;
+ internal->minus = PR_FALSE;
+ }
+ else opt->value = NULL;
+ return PL_OPT_OK;
+ }
+ }
+ internal->xargv += 1; /* consume that option */
+ return PL_OPT_BAD;
+ }
+ /*
+ ** No '-', so it must be a standalone value. The option is nul.
+ */
+ opt->value = internal->argv[internal->xargc];
+ internal->xargv = &static_Nul;
+ opt->option = 0;
+ return PL_OPT_OK;
+} /* PL_GetNextOpt */
+
+/* plgetopt.c */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/plvrsion.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plvrsion.c
new file mode 100644
index 00000000..e9903cb7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/plvrsion.c
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplc, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
+ /* comment */ "http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+
+/* plvrsion.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcat.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcat.c
new file mode 100644
index 00000000..f71b0974
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcat.c
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strcat(char *dest, const char *src)
+{
+ if( ((char *)0 == dest) || ((const char *)0 == src) )
+ return dest;
+
+ return strcat(dest, src);
+}
+
+PR_IMPLEMENT(char *)
+PL_strncat(char *dest, const char *src, PRUint32 max)
+{
+ char *rv;
+
+ if( ((char *)0 == dest) || ((const char *)0 == src) || (0 == max) )
+ return dest;
+
+ for( rv = dest; *dest; dest++ )
+ ;
+
+ (void)PL_strncpy(dest, src, max);
+ return rv;
+}
+
+PR_IMPLEMENT(char *)
+PL_strcatn(char *dest, PRUint32 max, const char *src)
+{
+ char *rv;
+ PRUint32 dl;
+
+ if( ((char *)0 == dest) || ((const char *)0 == src) )
+ return dest;
+
+ for( rv = dest, dl = 0; *dest; dest++, dl++ )
+ ;
+
+ if( max <= dl ) return rv;
+ (void)PL_strncpyz(dest, src, max-dl);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strccmp.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strccmp.c
new file mode 100644
index 00000000..ec877484
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strccmp.c
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+
+static const unsigned char uc[] =
+{
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+};
+
+PR_IMPLEMENT(PRIntn)
+PL_strcasecmp(const char *a, const char *b)
+{
+ const unsigned char *ua = (const unsigned char *)a;
+ const unsigned char *ub = (const unsigned char *)b;
+
+ if( ((const char *)0 == a) || (const char *)0 == b )
+ return (PRIntn)(a-b);
+
+ while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
+ {
+ a++;
+ ua++;
+ ub++;
+ }
+
+ return (PRIntn)(uc[*ua] - uc[*ub]);
+}
+
+PR_IMPLEMENT(PRIntn)
+PL_strncasecmp(const char *a, const char *b, PRUint32 max)
+{
+ const unsigned char *ua = (const unsigned char *)a;
+ const unsigned char *ub = (const unsigned char *)b;
+
+ if( ((const char *)0 == a) || (const char *)0 == b )
+ return (PRIntn)(a-b);
+
+ while( max && (uc[*ua] == uc[*ub]) && ('\0' != *a) )
+ {
+ a++;
+ ua++;
+ ub++;
+ max--;
+ }
+
+ if( 0 == max ) return (PRIntn)0;
+
+ return (PRIntn)(uc[*ua] - uc[*ub]);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strchr.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strchr.c
new file mode 100644
index 00000000..35ccedcc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strchr.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strchr(const char *s, char c)
+{
+ if( (const char *)0 == s ) return (char *)0;
+
+ return strchr(s, c);
+}
+
+PR_IMPLEMENT(char *)
+PL_strrchr(const char *s, char c)
+{
+ if( (const char *)0 == s ) return (char *)0;
+
+ return strrchr(s, c);
+}
+
+PR_IMPLEMENT(char *)
+PL_strnchr(const char *s, char c, PRUint32 n)
+{
+ if( (const char *)0 == s ) return (char *)0;
+
+ for( ; n && *s; s++, n-- )
+ if( *s == c )
+ return (char *)s;
+
+ if( ((char)0 == c) && (n > 0) && ((char)0 == *s) ) return (char *)s;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnrchr(const char *s, char c, PRUint32 n)
+{
+ const char *p;
+
+ if( (const char *)0 == s ) return (char *)0;
+
+ for( p = s; n && *p; p++, n-- )
+ ;
+
+ if( ((char)0 == c) && (n > 0) && ((char)0 == *p) ) return (char *)p;
+
+ for( p--; p >= s; p-- )
+ if( *p == c )
+ return (char *)p;
+
+ return (char *)0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcmp.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcmp.c
new file mode 100644
index 00000000..095e1784
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcmp.c
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(PRIntn)
+PL_strcmp(const char *a, const char *b)
+{
+ if( ((const char *)0 == a) || (const char *)0 == b )
+ return (PRIntn)(a-b);
+
+ return (PRIntn)strcmp(a, b);
+}
+
+PR_IMPLEMENT(PRIntn)
+PL_strncmp(const char *a, const char *b, PRUint32 max)
+{
+ if( ((const char *)0 == a) || (const char *)0 == b )
+ return (PRIntn)(a-b);
+
+ return (PRIntn)strncmp(a, b, (size_t)max);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcpy.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcpy.c
new file mode 100644
index 00000000..b576b677
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcpy.c
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strcpy(char *dest, const char *src)
+{
+ if( ((char *)0 == dest) || ((const char *)0 == src) ) return (char *)0;
+
+ return strcpy(dest, src);
+}
+
+PR_IMPLEMENT(char *)
+PL_strncpy(char *dest, const char *src, PRUint32 max)
+{
+ char *rv;
+
+ if( (char *)0 == dest ) return (char *)0;
+ if( (const char *)0 == src ) return (char *)0;
+
+ for( rv = dest; max && ((*dest = *src) != 0); dest++, src++, max-- )
+ ;
+
+#ifdef JLRU
+ /* XXX I (wtc) think the -- and ++ operators should be postfix. */
+ while( --max )
+ *++dest = '\0';
+#endif /* JLRU */
+
+ return rv;
+}
+
+PR_IMPLEMENT(char *)
+PL_strncpyz(char *dest, const char *src, PRUint32 max)
+{
+ char *rv;
+
+ if( (char *)0 == dest ) return (char *)0;
+ if( (const char *)0 == src ) return (char *)0;
+ if( 0 == max ) return (char *)0;
+
+ for( rv = dest, max--; max && ((*dest = *src) != 0); dest++, src++, max-- )
+ ;
+
+ *dest = '\0';
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcstr.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcstr.c
new file mode 100644
index 00000000..cb587788
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strcstr.c
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+
+PR_IMPLEMENT(char *)
+PL_strcasestr(const char *big, const char *little)
+{
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = PL_strlen(little);
+
+ for( ; *big; big++ )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(big, little, ll) )
+ return (char *)big;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strcaserstr(const char *big, const char *little)
+{
+ const char *p;
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = PL_strlen(little);
+ p = &big[ PL_strlen(big) - ll ];
+ if( p < big ) return (char *)0;
+
+ for( ; p >= big; p-- )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(p, little, ll) )
+ return (char *)p;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strncasestr(const char *big, const char *little, PRUint32 max)
+{
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = PL_strlen(little);
+ if( ll > max ) return (char *)0;
+ max -= ll;
+ max++;
+
+ for( ; max && *big; big++, max-- )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(big, little, ll) )
+ return (char *)big;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strncaserstr(const char *big, const char *little, PRUint32 max)
+{
+ const char *p;
+ PRUint32 ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = PL_strlen(little);
+
+ for( p = big; max && *p; p++, max-- )
+ ;
+
+ p -= ll;
+ if( p < big ) return (char *)0;
+
+ for( ; p >= big; p-- )
+ /* obvious improvement available here */
+ if( 0 == PL_strncasecmp(p, little, ll) )
+ return (char *)p;
+
+ return (char *)0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strdup.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strdup.c
new file mode 100644
index 00000000..f5fe61ad
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strdup.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include "prmem.h"
+#include <string.h>
+#ifdef VBOX_USE_IPRT_IN_NSPR
+#include <iprt/mem.h>
+#endif
+
+PR_IMPLEMENT(char *)
+PL_strdup(const char *s)
+{
+ char *rv;
+ size_t n;
+
+ if( (const char *)0 == s )
+ s = "";
+
+ n = strlen(s) + 1;
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ rv = (char *)RTMemAlloc(n);
+#else
+ rv = (char *)malloc(n);
+#endif
+ if( (char *)0 == rv ) return rv;
+
+ (void)memcpy(rv, s, n);
+
+ return rv;
+}
+
+PR_IMPLEMENT(void)
+PL_strfree(char *s)
+{
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(s);
+#else
+ free(s);
+#endif
+}
+
+PR_IMPLEMENT(char *)
+PL_strndup(const char *s, PRUint32 max)
+{
+ char *rv;
+ size_t l;
+
+ if( (const char *)0 == s )
+ s = "";
+
+ l = PL_strnlen(s, max);
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ rv = (char *)RTMemAlloc(l+1);
+#else
+ rv = (char *)malloc(l+1);
+#endif
+ if( (char *)0 == rv ) return rv;
+
+ (void)memcpy(rv, s, l);
+ rv[l] = '\0';
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strlen.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strlen.c
new file mode 100644
index 00000000..6c476777
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strlen.c
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include "prtypes.h"
+#include "prlog.h"
+#include <string.h>
+
+PR_IMPLEMENT(PRUint32)
+PL_strlen(const char *str)
+{
+ size_t l;
+
+ if( (const char *)0 == str ) return 0;
+
+ l = strlen(str);
+
+ /* error checking in case we have a 64-bit platform -- make sure
+ * we don't have ultra long strings that overflow an int32
+ */
+ if( sizeof(PRUint32) < sizeof(size_t) )
+ PR_ASSERT(l < 2147483647);
+
+ return (PRUint32)l;
+}
+
+PR_IMPLEMENT(PRUint32)
+PL_strnlen(const char *str, PRUint32 max)
+{
+ register const char *s;
+
+ if( (const char *)0 == str ) return 0;
+ for( s = str; max && *s; s++, max-- )
+ ;
+
+ return (PRUint32)(s - str);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strpbrk.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strpbrk.c
new file mode 100644
index 00000000..afcb4f51
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strpbrk.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strpbrk(const char *s, const char *list)
+{
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
+
+ return strpbrk(s, list);
+}
+
+PR_IMPLEMENT(char *)
+PL_strprbrk(const char *s, const char *list)
+{
+ const char *p;
+ const char *r;
+
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
+
+ for( r = s; *r; r++ )
+ ;
+
+ for( r--; r >= s; r-- )
+ for( p = list; *p; p++ )
+ if( *r == *p )
+ return (char *)r;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnpbrk(const char *s, const char *list, PRUint32 max)
+{
+ const char *p;
+
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
+
+ for( ; max && *s; s++, max-- )
+ for( p = list; *p; p++ )
+ if( *s == *p )
+ return (char *)s;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnprbrk(const char *s, const char *list, PRUint32 max)
+{
+ const char *p;
+ const char *r;
+
+ if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0;
+
+ for( r = s; max && *r; r++, max-- )
+ ;
+
+ for( r--; r >= s; r-- )
+ for( p = list; *p; p++ )
+ if( *r == *p )
+ return (char *)r;
+
+ return (char *)0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strstr.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strstr.c
new file mode 100644
index 00000000..6bc03d37
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strstr.c
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include <string.h>
+
+PR_IMPLEMENT(char *)
+PL_strstr(const char *big, const char *little)
+{
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ return strstr(big, little);
+}
+
+PR_IMPLEMENT(char *)
+PL_strrstr(const char *big, const char *little)
+{
+ const char *p;
+ size_t ll;
+ size_t bl;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = strlen(little);
+ bl = strlen(big);
+ if( bl < ll ) return (char *)0;
+ p = &big[ bl - ll ];
+
+ for( ; p >= big; p-- )
+ if( *little == *p )
+ if( 0 == strncmp(p, little, ll) )
+ return (char *)p;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnstr(const char *big, const char *little, PRUint32 max)
+{
+ size_t ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = strlen(little);
+ if( ll > (size_t)max ) return (char *)0;
+ max -= (PRUint32)ll;
+ max++;
+
+ for( ; max && *big; big++, max-- )
+ if( *little == *big )
+ if( 0 == strncmp(big, little, ll) )
+ return (char *)big;
+
+ return (char *)0;
+}
+
+PR_IMPLEMENT(char *)
+PL_strnrstr(const char *big, const char *little, PRUint32 max)
+{
+ const char *p;
+ size_t ll;
+
+ if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0;
+ if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0;
+
+ ll = strlen(little);
+
+ for( p = big; max && *p; p++, max-- )
+ ;
+
+ p -= ll;
+ if( p < big ) return (char *)0;
+
+ for( ; p >= big; p-- )
+ if( *little == *p )
+ if( 0 == strncmp(p, little, ll) )
+ return (char *)p;
+
+ return (char *)0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/libc/src/strtok.c b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strtok.c
new file mode 100644
index 00000000..400e9a4c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/libc/src/strtok.c
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roland Mainz <roland mainz@informatik.med.uni-giessen.de>
+ *
+ * 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 "plstr.h"
+
+PR_IMPLEMENT(char *)
+PL_strtok_r(char *s1, const char *s2, char **lasts)
+{
+ const char *sepp;
+ int c, sc;
+ char *tok;
+
+ if( s1 == NULL )
+ {
+ if( *lasts == NULL )
+ return NULL;
+
+ s1 = *lasts;
+ }
+
+ for( ; (c = *s1) != 0; s1++ )
+ {
+ for( sepp = s2 ; (sc = *sepp) != 0 ; sepp++ )
+ {
+ if( c == sc )
+ break;
+ }
+ if( sc == 0 )
+ break;
+ }
+
+ if( c == 0 )
+ {
+ *lasts = NULL;
+ return NULL;
+ }
+
+ tok = s1++;
+
+ for( ; (c = *s1) != 0; s1++ )
+ {
+ for( sepp = s2; (sc = *sepp) != 0; sepp++ )
+ {
+ if( c == sc )
+ {
+ *s1++ = '\0';
+ *lasts = s1;
+ return tok;
+ }
+ }
+ }
+ *lasts = NULL;
+ return tok;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/msgc/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/msgc/Makefile.in
new file mode 100644
index 00000000..d7299b2b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/Makefile.in
@@ -0,0 +1,52 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = include src tests
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/include/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/include/MANIFEST b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/MANIFEST
new file mode 100644
index 00000000..a45ec20e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/MANIFEST
@@ -0,0 +1,5 @@
+#
+# This is a list of local files which get copied to the mozilla:dist directory
+#
+
+prgc.h
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/include/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/Makefile.in
new file mode 100644
index 00000000..60803a02
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/Makefile.in
@@ -0,0 +1,61 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/config.mk
+
+EXPORT_HEADERS = prgc.h
+HEADERS = $(EXPORT_HEADERS) gcint.h
+
+RELEASE_HEADERS = $(EXPORT_HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(EXPORT_HEADERS)
+ $(INSTALL) -m 444 $(EXPORT_HEADERS) $(dist_includedir)
+ifeq ($(MOZ_BITS),16)
+ $(INSTALL) -m 444 $(EXPORT_HEADERS) $(MOZ_INCL)
+endif
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/include/gcint.h b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/gcint.h
new file mode 100644
index 00000000..10048f06
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/gcint.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef gcint_h___
+#define gcint_h___
+
+#include "prmon.h"
+#include "prgc.h"
+
+extern PRLogModuleInfo *_pr_msgc_lm;
+extern GCInfo _pr_gcData;
+
+#if defined(_WIN32) && !defined(DEBUG)
+#undef INLINE_LOCK
+#endif
+
+#ifdef INLINE_LOCK
+#define LOCK_GC() EnterCriticalSection(&_pr_gcData.lock->mutexHandle)
+#define UNLOCK_GC() LeaveCriticalSection(&_pr_gcData.lock->mutexHandle)
+#else
+#define LOCK_GC() PR_EnterMonitor(_pr_gcData.lock)
+#define UNLOCK_GC() PR_ExitMonitor (_pr_gcData.lock)
+#define GC_IS_LOCKED() (PR_GetMonitorEntryCount(_pr_gcData.lock)!=0)
+#endif
+
+#ifdef DEBUG
+#define _GCTRACE(x, y) if (_pr_gcData.flags & x) GCTrace y
+#else
+#define _GCTRACE(x, y)
+#endif
+
+extern GCBeginGCHook *_pr_beginGCHook;
+extern void *_pr_beginGCHookArg;
+extern GCBeginGCHook *_pr_endGCHook;
+extern void *_pr_endGCHookArg;
+
+extern GCBeginFinalizeHook *_pr_beginFinalizeHook;
+extern void *_pr_beginFinalizeHookArg;
+extern GCBeginFinalizeHook *_pr_endFinalizeHook;
+extern void *_pr_endFinalizeHookArg;
+
+extern int _pr_do_a_dump;
+extern FILE *_pr_dump_file;
+
+extern PRLogModuleInfo *_pr_gc_lm;
+
+/*
+** Root finders. Root finders are used by the GC to find pointers into
+** the GC heap that are not contained in the GC heap.
+*/
+typedef struct RootFinderStr RootFinder;
+
+struct RootFinderStr {
+ RootFinder *next;
+ GCRootFinder *func;
+ char *name;
+ void *arg;
+};
+extern RootFinder *_pr_rootFinders;
+
+typedef struct CollectorTypeStr {
+ GCType gctype;
+ PRUint32 flags;
+} CollectorType;
+
+#define GC_MAX_TYPES 256
+extern CollectorType *_pr_collectorTypes;
+
+#define _GC_TYPE_BUSY 0x1
+#define _GC_TYPE_FINAL 0x2
+#define _GC_TYPE_WEAK 0x4
+
+/* Slot in _pr_gcTypes used for free memory */
+#define FREE_MEMORY_TYPEIX 255
+
+extern void _PR_InitGC(PRWord flags);
+extern void _MD_InitGC(void);
+extern void PR_CALLBACK _PR_ScanFinalQueue(void *notused);
+
+/*
+** Grow the GC Heap.
+*/
+extern void *_MD_GrowGCHeap(PRUint32 *sizep);
+
+/*
+** Extend the GC Heap.
+*/
+extern PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize);
+
+/*
+** Free a GC segment.
+*/
+extern void _MD_FreeGCSegment(void *base, PRInt32 len);
+
+#endif /* gcint_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/include/prgc.h b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/prgc.h
new file mode 100644
index 00000000..add30213
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/include/prgc.h
@@ -0,0 +1,419 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prgc_h___
+#define prgc_h___
+
+/*
+** API to NSPR gc memory system.
+*/
+#include "prtypes.h"
+#include "prmon.h"
+#include "prthread.h"
+#include <stdio.h>
+
+#if defined(WIN16)
+#define GCPTR __far
+#else
+#define GCPTR
+#endif
+
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Initialize the garbage collector.
+** "flags" is the trace flags (see below).
+** "initialHeapSize" is the initial size of the heap and may be zero
+** if the default is desired.
+** "segmentSize" is the size of each segment of memory added to the
+** heap when the heap is grown.
+*/
+PR_EXTERN(void) PR_InitGC(
+ PRWord flags, PRInt32 initialHeapSize, PRInt32 segmentSize, PRThreadScope scope);
+
+/*
+** Shuts down gc and frees up all memory associated with it.
+*/
+PR_EXTERN(void) PR_ShutdownGC(PRBool finalizeOnExit);
+
+/*
+** This walk function will be called for every gc object in the
+** heap as it is walked. If it returns non-zero, the walk is terminated.
+*/
+typedef PRInt32 (*PRWalkFun)(void GCPTR* obj, void* data);
+
+/*
+** GC Type record. This defines all of the GC operations used on a
+** particular object type. These structures are passed to
+** PR_RegisterType.
+*/
+typedef struct GCType {
+ /*
+ ** Scan an object that is in the GC heap and call GCInfo.livePointer
+ ** on all of the pointers in it. If this slot is null then the object
+ ** won't be scanned (i.e. it has no embedded pointers).
+ */
+ void (PR_CALLBACK *scan)(void GCPTR *obj);
+
+ /*
+ ** Finalize an object that has no references. This is called by the
+ ** GC after it has determined where the object debris is but before
+ ** it has moved the debris to the logical "free list". The object is
+ ** marked alive for this call and removed from the list of objects
+ ** that need finalization (finalization only happens once for an
+ ** object). If this slot is null then the object doesn't need
+ ** finalization.
+ */
+ void (PR_CALLBACK *finalize)(void GCPTR *obj);
+
+ /*
+ ** Dump out an object during a PR_DumpGCHeap(). This is used as a
+ ** debugging tool.
+ */
+ void (PR_CALLBACK *dump)(FILE *out, void GCPTR *obj, PRBool detailed, PRIntn indentLevel);
+
+ /*
+ ** Add object to summary table.
+ */
+ void (PR_CALLBACK *summarize)(void GCPTR *obj, PRUint32 bytes);
+
+ /*
+ ** Free hook called by GC when the object is being freed.
+ */
+ void (PR_CALLBACK *free)(void *obj);
+
+ /* Weak pointer support: If the object has a weak pointer (Note:
+ at most one), this function is used to get the weak link's
+ offset from the start of the body of a gc object */
+ PRUint32 (PR_CALLBACK *getWeakLinkOffset)(void *obj);
+
+ /* Descriptive character for dumping this GCType */
+ char kindChar;
+
+ /*
+ ** Walker routine. This routine should apply fun(obj->ptr, data)
+ ** for every gc pointer within the object.
+ */
+ PRInt32 (PR_CALLBACK *walk)(void GCPTR *obj, PRWalkFun fun, void* data);
+} GCType;
+
+/*
+** This data structure must be added as the hash table passed to
+** the summarize method of GCType.
+*/
+typedef struct PRSummaryEntry {
+ void* clazz;
+ PRInt32 instancesCount;
+ PRInt32 totalSize;
+} PRSummaryEntry;
+
+/*
+** This function pointer must be registered by users of nspr
+** to produce the finally summary after all object in the
+** heap have been visited.
+*/
+typedef void (PR_CALLBACK *PRSummaryPrinter)(FILE *out, void* closure);
+
+PR_EXTERN(void) PR_CALLBACK PR_RegisterSummaryPrinter(PRSummaryPrinter fun, void* closure);
+
+typedef void PR_CALLBACK GCRootFinder(void *arg);
+typedef void PR_CALLBACK GCBeginFinalizeHook(void *arg);
+typedef void PR_CALLBACK GCEndFinalizeHook(void *arg);
+typedef void PR_CALLBACK GCBeginGCHook(void *arg);
+typedef void PR_CALLBACK GCEndGCHook(void *arg);
+
+typedef enum { PR_GCBEGIN, PR_GCEND } GCLockHookArg;
+
+typedef void PR_CALLBACK GCLockHookFunc(GCLockHookArg arg1, void *arg2);
+
+typedef struct GCLockHook GCLockHook;
+
+struct GCLockHook {
+ GCLockHookFunc* func;
+ void* arg;
+ GCLockHook* next;
+ GCLockHook* prev;
+};
+
+
+/*
+** Hooks which are called at the beginning and end of the GC process.
+** The begin hooks are called before the root finding step. The hooks are
+** called with threading disabled, so it is now allowed to re-enter the
+** kernel. The end hooks are called after the gc has finished but before
+** the finalizer has run.
+*/
+PR_EXTERN(void) PR_CALLBACK PR_SetBeginGCHook(GCBeginGCHook *hook, void *arg);
+PR_EXTERN(void) PR_CALLBACK PR_GetBeginGCHook(GCBeginGCHook **hook, void **arg);
+PR_EXTERN(void) PR_CALLBACK PR_SetEndGCHook(GCBeginGCHook *hook, void *arg);
+PR_EXTERN(void) PR_CALLBACK PR_GetEndGCHook(GCEndGCHook **hook, void **arg);
+
+/*
+** Called before SuspendAll is called by dogc, so that GC thread can hold
+** all the locks before hand to avoid any deadlocks
+*/
+
+/*
+PR_EXTERN(void) PR_SetGCLockHook(GCLockHook *hook, void *arg);
+PR_EXTERN(void) PR_GetGCLockHook(GCLockHook **hook, void **arg);
+*/
+
+PR_EXTERN(int) PR_RegisterGCLockHook(GCLockHookFunc *hook, void *arg);
+
+/*
+** Hooks which are called at the beginning and end of the GC finalization
+** process. After the GC has identified all of the dead objects in the
+** heap, it looks for objects that need finalization. Before it calls the
+** first finalization proc (see the GCType structure above) it calls the
+** begin hook. When it has finalized the last object it calls the end
+** hook.
+*/
+PR_EXTERN(void) PR_SetBeginFinalizeHook(GCBeginFinalizeHook *hook, void *arg);
+PR_EXTERN(void) PR_GetBeginFinalizeHook(GCBeginFinalizeHook **hook, void **arg);
+PR_EXTERN(void) PR_SetEndFinalizeHook(GCBeginFinalizeHook *hook, void *arg);
+PR_EXTERN(void) PR_GetEndFinalizeHook(GCEndFinalizeHook **hook, void **arg);
+
+/*
+** Register a GC type. Return's the index into the GC internal type
+** table. The returned value is passed to PR_AllocMemory. After the call,
+** the "type" memory belongs to the GC (the caller must not free it or
+** change it).
+*/
+PR_EXTERN(PRInt32) PR_RegisterType(GCType *type);
+
+/*
+** Register a root finder with the collector. The collector will call
+** these functions to identify all of the roots before collection
+** proceeds. "arg" is passed to the function when it is called.
+*/
+PR_EXTERN(PRStatus) PR_RegisterRootFinder(GCRootFinder func, char *name, void *arg);
+
+/*
+** Allocate some GC'able memory. The object must be at least bytes in
+** size. The type index function for the object is specified. "flags"
+** specifies some control flags. If PR_ALLOC_CLEAN is set then the memory
+** is zero'd before being returned. If PR_ALLOC_DOUBLE is set then the
+** allocated memory is double aligned.
+**
+** Any memory cell that you store a pointer to something allocated by
+** this call must be findable by the GC. Use the PR_RegisterRootFinder to
+** register new places where the GC will look for pointers into the heap.
+** The GC already knows how to scan any NSPR threads or monitors.
+*/
+PR_EXTERN(PRWord GCPTR *)PR_AllocMemory(
+ PRWord bytes, PRInt32 typeIndex, PRWord flags);
+PR_EXTERN(PRWord GCPTR *)PR_AllocSimpleMemory(
+ PRWord bytes, PRInt32 typeIndex);
+
+/*
+** This function can be used to cause PR_AllocMemory to always return
+** NULL. This may be useful in low memory situations when we're trying to
+** shutdown applets.
+*/
+PR_EXTERN(void) PR_EnableAllocation(PRBool yesOrNo);
+
+/* flags bits */
+#define PR_ALLOC_CLEAN 0x1
+#define PR_ALLOC_DOUBLE 0x2
+#define PR_ALLOC_ZERO_HANDLE 0x4 /* XXX yes, it's a hack */
+
+/*
+** Force a garbage collection right now. Return when it completes.
+*/
+PR_EXTERN(void) PR_GC(void);
+
+/*
+** Force a finalization right now. Return when finalization has
+** completed. Finalization completes when there are no more objects
+** pending finalization. This does not mean there are no objects in the
+** gc heap that will need finalization should a collection be done after
+** this call.
+*/
+PR_EXTERN(void) PR_ForceFinalize(void);
+
+/*
+** Dump the GC heap out to the given file. This will stop the system dead
+** in its tracks while it is occuring.
+*/
+PR_EXTERN(void) PR_DumpGCHeap(FILE *out, PRBool detailed);
+
+/*
+** Wrapper for PR_DumpGCHeap
+*/
+PR_EXTERN(void) PR_DumpMemory(PRBool detailed);
+
+/*
+** Dump summary of objects allocated.
+*/
+PR_EXTERN(void) PR_DumpMemorySummary(void);
+
+/*
+** Dump the application heaps.
+*/
+PR_EXTERN(void) PR_DumpApplicationHeaps(void);
+
+/*
+** Helper function used by dump routines to do the indentation in a
+** consistent fashion.
+*/
+PR_EXTERN(void) PR_DumpIndent(FILE *out, PRIntn indent);
+
+/*
+** The GCInfo structure contains all of the GC state...
+**
+** busyMemory:
+** The amount of GC heap memory that is busy at this instant. Busy
+** doesn't mean alive, it just means that it has been
+** allocated. Immediately after a collection busy means how much is
+** alive.
+**
+** freeMemory:
+** The amount of GC heap memory that is as yet unallocated.
+**
+** allocMemory:
+** The sum of free and busy memory in the GC heap.
+**
+** maxMemory:
+** The maximum size that the GC heap is allowed to grow.
+**
+** lowSeg:
+** The lowest segment currently used in the GC heap.
+**
+** highSeg:
+** The highest segment currently used in the GC heap.
+** The lowSeg and highSeg members are used for a "quick test" of whether
+** a pointer falls within the GC heap. [ see GC_IN_HEAP(...) ]
+**
+** lock:
+** Monitor used for syncronization within the GC.
+**
+** finalizer:
+** Thread in which the GC finalizer is running.
+**
+** liveBlock:
+** Object scanning functions call through this function pointer to
+** register a potential block of pointers with the collector. (This is
+** currently not at all different than processRoot.)
+**
+** livePointer:
+** Object scanning functions call through this function pointer to
+** register a single pointer with the collector.
+**
+** processRootBlock:
+** When a root finder identifies a root it should call through this
+** function pointer so that the GC can process the root. The call takes
+** a base address and count which the gc will examine for valid heap
+** pointers.
+**
+** processRootPointer:
+** When a root finder identifies a root it should call through this
+** function pointer so that the GC can process the root. The call takes
+** a single pointer value.
+*/
+typedef struct GCInfoStr {
+ PRWord flags; /* trace flags (see below) */
+ PRWord busyMemory; /* memory in use right now */
+ PRWord freeMemory; /* memory free right now */
+ PRWord allocMemory; /* sum of busy & free memory */
+ PRWord maxMemory; /* max memory we are allowed to allocate */
+ PRWord *lowSeg; /* lowest segment in the GC heap */
+ PRWord *highSeg; /* higest segment in the GC heap */
+
+ PRMonitor *lock;
+ PRThread *finalizer;
+
+ void (PR_CALLBACK *liveBlock)(void **base, PRInt32 count);
+ void (PR_CALLBACK *livePointer)(void *ptr);
+ void (PR_CALLBACK *processRootBlock)(void **base, PRInt32 count);
+ void (PR_CALLBACK *processRootPointer)(void *ptr);
+ FILE* dumpOutput;
+#ifdef GCTIMINGHOOK
+ void (*gcTimingHook)(int32 gcTime);
+#endif
+} GCInfo;
+
+PR_EXTERN(GCInfo *) PR_GetGCInfo(void);
+PR_EXTERN(PRBool) PR_GC_In_Heap(void GCPTR *object);
+
+/*
+** Simple bounds check to see if a pointer is anywhere near the GC heap.
+** Used to avoid calls to PR_ProcessRoot and GCInfo.livePointer by object
+** scanning code.
+*/
+#if !defined(XP_PC) || defined(_WIN32)
+#define GC_IN_HEAP(_info, _p) (((PRWord*)(_p) >= (_info)->lowSeg) && \
+ ((PRWord*)(_p) < (_info)->highSeg))
+#else
+/*
+** The simple bounds check, above, doesn't work in Win16, because we don't
+** maintain: lowSeg == MIN(all segments) and highSeg == MAX(all segments).
+** So we have to do a little better.
+*/
+#define GC_IN_HEAP(_info, _p) PR_GC_In_Heap(_p)
+#endif
+
+PR_EXTERN(PRWord) PR_GetObjectHeader(void *ptr);
+
+PR_EXTERN(PRWord) PR_SetObjectHeader(void *ptr, PRWord newUserBits);
+
+/************************************************************************/
+
+/* Trace flags (passed to PR_InitGC or in environment GCLOG) */
+#define GC_TRACE 0x0001
+#define GC_ROOTS 0x0002
+#define GC_LIVE 0x0004
+#define GC_ALLOC 0x0008
+#define GC_MARK 0x0010
+#define GC_SWEEP 0x0020
+#define GC_DEBUG 0x0040
+#define GC_FINAL 0x0080
+
+#if defined(DEBUG_kipp) || defined(DEBUG_warren)
+#define GC_CHECK 0x0100
+#endif
+
+#ifdef DEBUG
+#define GCTRACE(x, y) if (PR_GetGCInfo()->flags & x) GCTrace y
+PR_EXTERN(void) GCTrace(char *fmt, ...);
+#else
+#define GCTRACE(x, y)
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* prgc_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/Makefile.in
new file mode 100644
index 00000000..e822fc29
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/Makefile.in
@@ -0,0 +1,103 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+INCLUDES = -I$(dist_includedir) -I../include
+
+CSRCS = prgcapi.c prmsgc.c
+
+ifeq ($(OS_ARCH),WINNT)
+CSRCS += win32gc.c
+else
+ifeq ($(OS_ARCH),OS2)
+CSRCS += os2gc.c
+else
+CSRCS += unixgc.c
+endif
+endif
+
+NSPR_VERSION = $(MOD_MAJOR_VERSION)
+
+EXTRA_LIBS = $(LIBNSPR)
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+ifeq ($(OS_ARCH), WINNT)
+ifdef NS_USE_GCC
+DLLBASE=-Wl,--image-base -Wl,0x30000000
+else
+DLLBASE=/BASE:0x30000000
+endif # GCC
+#RES=$(OBJDIR)/ds.res
+#RESNAME=$(MOD_DEPTH)/pr/src/nspr.rc
+#OS_LIBS = user32.lib
+endif # WINNT
+
+LIBRARY_NAME = msgc
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_LIBS = $(TARGETS)
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# The Client build wants the shared libraries in $(dist_bindir),
+# so we also install them there.
+#
+
+export:: $(TARGETS)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifdef SHARED_LIBRARY
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
+endif
+ifeq ($(MOZ_BITS),16)
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
+endif
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/macgc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/macgc.c
new file mode 100644
index 00000000..eafc28e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/macgc.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include "MacMemAllocator.h"
+
+void _MD_InitGC() {}
+
+void *_MD_GrowGCHeap(size_t *sizep)
+{
+ void *heapPtr = NULL;
+ size_t heapSize = *sizep;
+
+ // In previous versions of this code we tried to allocate GC heaps from the application
+ // heap. In the 4.0 application, we try to keep our app heap allications to a minimum
+ // and instead go through our own memory allocation routines.
+ heapPtr = malloc(heapSize);
+
+ if (heapPtr == NULL) {
+ FreeMemoryStats stats;
+
+ memtotal(heapSize, &stats); // How much can we allcoate?
+
+ if (stats.maxBlockSize < heapSize)
+ heapSize = stats.maxBlockSize;
+
+ heapPtr = malloc(heapSize);
+
+ if (heapPtr == NULL) // Now we're hurting
+ heapSize = 0;
+ }
+
+ *sizep = heapSize;
+ return heapPtr;
+}
+
+
+void _MD_FreeGCSegment(void *base, int32 /* len */)
+{
+ free(base);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/os2gc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/os2gc.c
new file mode 100644
index 00000000..f99bb678
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/os2gc.c
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * GC related routines
+ *
+ */
+#include "prlog.h"
+
+#include <stdlib.h>
+
+/* Leave a bit of room for any malloc header bytes... */
+#define MAX_SEGMENT_SIZE (65536L - 4096L)
+
+/************************************************************************/
+/*
+** Machine dependent GC Heap management routines:
+** _MD_GrowGCHeap
+*/
+/************************************************************************/
+void _MD_InitGC() {}
+
+void *_MD_GrowGCHeap(PRUint32 *sizep)
+{
+ void *addr;
+
+ if ( *sizep > MAX_SEGMENT_SIZE )
+ {
+ *sizep = MAX_SEGMENT_SIZE;
+ }
+
+ addr = malloc((size_t)*sizep);
+ return addr;
+}
+
+
+PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) {
+ /* Not sure about this. Todd? */
+ return PR_FALSE;
+}
+
+
+void _MD_FreeGCSegment(void *base, PRInt32 len)
+{
+ if (base)
+ {
+ free(base);
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/prgcapi.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/prgcapi.c
new file mode 100644
index 00000000..23f7ea51
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/prgcapi.c
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include "prenv.h"
+#include "prmem.h"
+#include "prmon.h"
+#include "prlog.h"
+#include "prthread.h"
+#if defined(XP_MAC)
+#include "pprthred.h"
+#else
+#include "private/pprthred.h"
+#endif
+#include "gcint.h"
+
+/*
+** Generic GC implementation independent code for the NSPR GC
+*/
+
+RootFinder *_pr_rootFinders;
+
+CollectorType *_pr_collectorTypes;
+
+/* GC State information */
+GCInfo _pr_gcData;
+
+GCBeginGCHook *_pr_beginGCHook;
+void *_pr_beginGCHookArg;
+GCBeginGCHook *_pr_endGCHook;
+void *_pr_endGCHookArg;
+
+GCBeginFinalizeHook *_pr_beginFinalizeHook;
+void *_pr_beginFinalizeHookArg;
+GCBeginFinalizeHook *_pr_endFinalizeHook;
+void *_pr_endFinalizeHookArg;
+
+FILE *_pr_dump_file;
+int _pr_do_a_dump;
+GCLockHook *_pr_GCLockHook;
+
+extern PRLogModuleInfo *_pr_msgc_lm;
+
+/************************************************************************/
+
+static PRStatus PR_CALLBACK
+pr_ScanOneThread(PRThread* t, void** addr, PRUword count, void* closure)
+{
+#if defined(XP_MAC)
+#pragma unused (t, closure)
+#endif
+
+ _pr_gcData.processRootBlock(addr, count);
+ return PR_SUCCESS;
+}
+
+/*
+** Scan all of the threads C stack's and registers, looking for "root"
+** pointers into the GC heap. These are the objects that the GC cannot
+** move and are considered "live" by the GC. Caller has stopped all of
+** the threads from running.
+*/
+static void PR_CALLBACK ScanThreads(void *arg)
+{
+ PR_ScanStackPointers(pr_ScanOneThread, arg);
+}
+
+/************************************************************************/
+
+PR_IMPLEMENT(GCInfo *) PR_GetGCInfo(void)
+{
+ return &_pr_gcData;
+}
+
+
+PR_IMPLEMENT(PRInt32) PR_RegisterType(GCType *t)
+{
+ CollectorType *ct, *ect;
+ int rv = -1;
+
+ LOCK_GC();
+ ct = &_pr_collectorTypes[0];
+ ect = &_pr_collectorTypes[FREE_MEMORY_TYPEIX];
+ for (; ct < ect; ct++) {
+ if (ct->flags == 0) {
+ ct->gctype = *t;
+ ct->flags = _GC_TYPE_BUSY;
+ if (0 != ct->gctype.finalize) {
+ ct->flags |= _GC_TYPE_FINAL;
+ }
+ if (0 != ct->gctype.getWeakLinkOffset) {
+ ct->flags |= _GC_TYPE_WEAK;
+ }
+ rv = ct - &_pr_collectorTypes[0];
+ break;
+ }
+ }
+ UNLOCK_GC();
+ return rv;
+}
+
+PR_IMPLEMENT(PRStatus) PR_RegisterRootFinder(
+ GCRootFinder f, char *name, void *arg)
+{
+ RootFinder *rf = PR_NEWZAP(RootFinder);
+ if (rf) {
+ rf->func = f;
+ rf->name = name;
+ rf->arg = arg;
+
+ LOCK_GC();
+ rf->next = _pr_rootFinders;
+ _pr_rootFinders = rf;
+ UNLOCK_GC();
+ return PR_SUCCESS;
+ }
+ return PR_FAILURE;
+}
+
+
+PR_IMPLEMENT(int) PR_RegisterGCLockHook(GCLockHookFunc* f, void *arg)
+{
+
+ GCLockHook *rf = 0;
+
+ rf = (GCLockHook*) calloc(1, sizeof(GCLockHook));
+ if (rf) {
+ rf->func = f;
+ rf->arg = arg;
+
+ LOCK_GC();
+ /* first dummy node */
+ if (! _pr_GCLockHook) {
+ _pr_GCLockHook = (GCLockHook*) calloc(1, sizeof(GCLockHook));
+ _pr_GCLockHook->next = _pr_GCLockHook;
+ _pr_GCLockHook->prev = _pr_GCLockHook;
+ }
+
+ rf->next = _pr_GCLockHook;
+ rf->prev = _pr_GCLockHook->prev;
+ _pr_GCLockHook->prev->next = rf;
+ _pr_GCLockHook->prev = rf;
+ UNLOCK_GC();
+ return 0;
+ }
+ return -1;
+}
+
+/*
+PR_IMPLEMENT(void) PR_SetGCLockHook(GCLockHook *hook, void *arg)
+{
+ LOCK_GC();
+ _pr_GCLockHook = hook;
+ _pr_GCLockHookArg2 = arg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_GetGCLockHook(GCLockHook **hook, void **arg)
+{
+ LOCK_GC();
+ *hook = _pr_GCLockHook;
+ *arg = _pr_GCLockHookArg2;
+ UNLOCK_GC();
+}
+*/
+
+
+PR_IMPLEMENT(void) PR_SetBeginGCHook(GCBeginGCHook *hook, void *arg)
+{
+ LOCK_GC();
+ _pr_beginGCHook = hook;
+ _pr_beginGCHookArg = arg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_GetBeginGCHook(GCBeginGCHook **hook, void **arg)
+{
+ LOCK_GC();
+ *hook = _pr_beginGCHook;
+ *arg = _pr_beginGCHookArg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_SetEndGCHook(GCEndGCHook *hook, void *arg)
+{
+ LOCK_GC();
+ _pr_endGCHook = hook;
+ _pr_endGCHookArg = arg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_GetEndGCHook(GCEndGCHook **hook, void **arg)
+{
+ LOCK_GC();
+ *hook = _pr_endGCHook;
+ *arg = _pr_endGCHookArg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_SetBeginFinalizeHook(GCBeginFinalizeHook *hook, void *arg)
+{
+ LOCK_GC();
+ _pr_beginFinalizeHook = hook;
+ _pr_beginFinalizeHookArg = arg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_GetBeginFinalizeHook(GCBeginFinalizeHook **hook,
+ void **arg)
+{
+ LOCK_GC();
+ *hook = _pr_beginFinalizeHook;
+ *arg = _pr_beginFinalizeHookArg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_SetEndFinalizeHook(GCEndFinalizeHook *hook, void *arg)
+{
+ LOCK_GC();
+ _pr_endFinalizeHook = hook;
+ _pr_endFinalizeHookArg = arg;
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void) PR_GetEndFinalizeHook(GCEndFinalizeHook **hook, void **arg)
+{
+ LOCK_GC();
+ *hook = _pr_endFinalizeHook;
+ *arg = _pr_endFinalizeHookArg;
+ UNLOCK_GC();
+}
+
+#ifdef DEBUG
+#include "prprf.h"
+
+#if defined(WIN16)
+static FILE *tracefile = 0;
+#endif
+
+PR_IMPLEMENT(void) GCTrace(char *fmt, ...)
+{
+ va_list ap;
+ char buf[400];
+
+ va_start(ap, fmt);
+ PR_vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+#if defined(WIN16)
+ if ( tracefile == 0 )
+ {
+ tracefile = fopen( "xxxGCtr", "w" );
+ }
+ fprintf(tracefile, "%s\n", buf );
+ fflush(tracefile);
+#else
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("%s", buf));
+#endif
+}
+#endif
+
+void _PR_InitGC(PRWord flags)
+{
+ static char firstTime = 1;
+
+ if (!firstTime) return;
+ firstTime = 0;
+
+ _MD_InitGC();
+
+ if (flags == 0) {
+ char *ev = PR_GetEnv("GCLOG");
+ if (ev && ev[0]) {
+ flags = atoi(ev);
+ }
+ }
+ _pr_gcData.flags = flags;
+
+ _pr_gcData.lock = PR_NewMonitor();
+
+ _pr_collectorTypes = (CollectorType*) PR_CALLOC(256 * sizeof(CollectorType));
+
+ PR_RegisterRootFinder(ScanThreads, "scan threads", 0);
+ PR_RegisterRootFinder(_PR_ScanFinalQueue, "scan final queue", 0);
+}
+
+extern void pr_FinalizeOnExit(void);
+
+#ifdef DEBUG
+#ifdef GC_STATS
+PR_PUBLIC_API(void) PR_PrintGCAllocStats(void);
+#endif
+#endif
+
+PR_IMPLEMENT(void)
+PR_ShutdownGC(PRBool finalizeOnExit)
+{
+ /* first finalize all the objects in the heap */
+ if (finalizeOnExit) {
+ pr_FinalizeOnExit();
+ }
+
+#ifdef DEBUG
+#ifdef GC_STATS
+ PR_PrintGCAllocStats();
+#endif /* GC_STATS */
+#endif /* DEBUG */
+
+ /* then the chance for any future allocations */
+
+ /* finally delete the gc heap */
+
+ /* write me */
+}
+
+/******************************************************************************/
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/prmsgc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/prmsgc.c
new file mode 100644
index 00000000..ad0566a4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/prmsgc.c
@@ -0,0 +1,3514 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <string.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <time.h>
+
+#ifdef WIN32
+#include <windef.h>
+#include <winbase.h>
+#endif
+
+#include "prclist.h"
+#include "prbit.h"
+
+#include "prtypes.h"
+#include "prenv.h"
+#include "prgc.h"
+#include "prthread.h"
+#include "prlog.h"
+#include "prlong.h"
+#include "prinrval.h"
+#include "prprf.h"
+#include "gcint.h"
+
+#if defined(XP_MAC)
+#include "pprthred.h"
+#else
+#include "private/pprthred.h"
+#endif
+
+typedef void (*PRFileDumper)(FILE *out, PRBool detailed);
+
+PR_EXTERN(void)
+PR_DumpToFile(char* filename, char* msg, PRFileDumper dump, PRBool detailed);
+
+/*
+** Mark&sweep garbage collector. Supports objects that require
+** finalization, objects that can have a single weak link, and special
+** objects that require care during sweeping.
+*/
+
+PRLogModuleInfo *_pr_msgc_lm;
+PRLogModuleInfo* GC;
+
+static PRInt32 _pr_pageShift;
+static PRInt32 _pr_pageSize;
+
+#ifdef DEBUG
+#define GCMETER
+#endif
+#ifdef DEBUG_jwz
+# undef GCMETER
+#endif /* 1 */
+
+#ifdef GCMETER
+#define METER(x) x
+#else
+#define METER(x)
+#endif
+
+/*
+** Make this constant bigger to reduce the amount of recursion during
+** garbage collection.
+*/
+#define MAX_SCAN_Q 100L
+
+#if defined(XP_PC) && !defined(WIN32)
+#define MAX_SEGS 400L
+#define MAX_SEGMENT_SIZE (65536L - 4096L)
+#define SEGMENT_SIZE (65536L - 4096L)
+#define MAX_ALLOC_SIZE (65536L - 4096L)
+#else
+#define MAX_SEGS 400L
+#define MAX_SEGMENT_SIZE (2L * 256L * 1024L)
+#define SEGMENT_SIZE (1L * 256L * 1024L)
+#define MAX_ALLOC_SIZE (4L * 1024L * 1024L)
+#endif
+
+/*
+ * The highest value that can fit into a signed integer. This
+ * is used to prevent overflow of allocation size in alloc routines.
+ */
+
+#define MAX_INT ((1UL << (PR_BITS_PER_INT - 1)) - 1)
+
+/*
+ * On 32-bit machines, only 22 bits are used in the cibx integer to
+ * store size since 8 bits of the integer are used to store type, and
+ * of the remainder, 2 are user defined. Max allocation size = 2^22 -1
+ */
+
+#define MAX_ALLOC ( (1L << (PR_BYTES_PER_WORD_LOG2 + WORDS_BITS )) -1)
+
+/* The minimum percentage of free heap space after a collection. If
+ the amount of free space doesn't meet this criteria then we will
+ attempt to grow the heap */
+#ifdef XP_MAC
+#define MIN_FREE_THRESHOLD_AFTER_GC 10L
+#else
+#define MIN_FREE_THRESHOLD_AFTER_GC 20L
+#endif
+
+static PRInt32 segmentSize = SEGMENT_SIZE;
+
+static PRInt32 collectorCleanupNeeded;
+
+#ifdef GCMETER
+PRUint32 _pr_gcMeter;
+
+#define _GC_METER_STATS 0x01L
+#define _GC_METER_GROWTH 0x02L
+#define _GC_METER_FREE_LIST 0x04L
+#endif
+
+/************************************************************************/
+
+#define LINEAR_BIN_EXPONENT 5
+#define NUM_LINEAR_BINS ((PRUint32)1 << LINEAR_BIN_EXPONENT)
+#define FIRST_LOG_BIN (NUM_LINEAR_BINS - LINEAR_BIN_EXPONENT)
+
+/* Each free list bin holds a chunk of memory sized from
+ 2^n to (2^(n+1))-1 inclusive. */
+#define NUM_BINS (FIRST_LOG_BIN + 32)
+
+/*
+ * Find the bin number for a given size (in bytes). This does not round up as
+ * values from 2^n to (2^(n+1))-1 share the same bin.
+ */
+#define InlineBinNumber(_bin,_bytes) \
+{ \
+ PRUint32 _t, _n = (PRUint32) _bytes / 4; \
+ if (_n < NUM_LINEAR_BINS) { \
+ _bin = _n; \
+ } else { \
+ _bin = FIRST_LOG_BIN; \
+ if ((_t = (_n >> 16)) != 0) { _bin += 16; _n = _t; } \
+ if ((_t = (_n >> 8)) != 0) { _bin += 8; _n = _t; } \
+ if ((_t = (_n >> 4)) != 0) { _bin += 4; _n = _t; } \
+ if ((_t = (_n >> 2)) != 0) { _bin += 2; _n = _t; } \
+ if ((_n >> 1) != 0) _bin++; \
+ } \
+}
+
+#define BIG_ALLOC 16384L
+
+#define MIN_FREE_CHUNK_BYTES ((PRInt32)sizeof(GCFreeChunk))
+
+/* Note: fix code in PR_AllocMemory if you change the size of GCFreeChunk
+ so that it zeros the right number of words */
+typedef struct GCFreeChunk {
+ struct GCFreeChunk *next;
+ struct GCSeg *segment;
+ PRInt32 chunkSize;
+} GCFreeChunk;
+
+typedef struct GCSegInfo {
+ struct GCSegInfo *next;
+ char *base;
+ char *limit;
+ PRWord *hbits;
+ int fromMalloc;
+} GCSegInfo;
+
+typedef struct GCSeg {
+ char *base;
+ char *limit;
+ PRWord *hbits;
+ GCSegInfo *info;
+} GCSeg;
+
+#ifdef GCMETER
+typedef struct GCMeter {
+ PRInt32 allocBytes;
+ PRInt32 wastedBytes;
+ PRInt32 numFreeChunks;
+ PRInt32 skippedFreeChunks;
+} GCMeter;
+static GCMeter meter;
+#endif
+
+/*
+** There is one of these for each segment of GC'able memory.
+*/
+static GCSeg segs[MAX_SEGS];
+static GCSegInfo *freeSegs;
+static GCSeg* lastInHeap;
+static int nsegs;
+
+static GCFreeChunk *bins[NUM_BINS];
+static PRInt32 minBin;
+static PRInt32 maxBin;
+
+/*
+** Scan Q used to avoid deep recursion when scanning live objects for
+** heap pointers
+*/
+typedef struct GCScanQStr {
+ PRWord *q[MAX_SCAN_Q];
+ int queued;
+} GCScanQ;
+
+static GCScanQ *pScanQ;
+
+#ifdef GCMETER
+PRInt32 _pr_maxScanDepth;
+PRInt32 _pr_scanDepth;
+#endif
+
+/*
+** Keeps track of the number of bytes allocated via the BigAlloc()
+** allocator. When the number of bytes allocated, exceeds the
+** BIG_ALLOC_GC_SIZE, then a GC will occur before the next allocation
+** is done...
+*/
+#define BIG_ALLOC_GC_SIZE (4*SEGMENT_SIZE)
+static PRWord bigAllocBytes = 0;
+
+/*
+** There is one GC header word in front of each GC allocated object. We
+** use it to contain information about the object (what TYPEIX to use for
+** scanning it, how big it is, it's mark status, and if it's a root).
+*/
+#define TYPEIX_BITS 8L
+#define WORDS_BITS 20L
+#define MAX_CBS (1L << GC_TYPEIX_BITS)
+#define MAX_WORDS (1L << GC_WORDS_BITS)
+#define TYPEIX_SHIFT 24L
+#define MAX_TYPEIX ((1L << TYPEIX_BITS) - 1L)
+#define TYPEIX_MASK PR_BITMASK(TYPEIX_BITS)
+#define WORDS_SHIFT 2L
+#define WORDS_MASK PR_BITMASK(WORDS_BITS)
+#define MARK_BIT 1L
+#define FINAL_BIT 2L
+
+/* Two bits per object header are reserved for the user of the memory
+ system to store information into. */
+#define GC_USER_BITS_SHIFT 22L
+#define GC_USER_BITS 0x00c00000L
+
+#define MAKE_HEADER(_cbix,_words) \
+ ((PRWord) (((unsigned long)(_cbix) << TYPEIX_SHIFT) \
+ | ((unsigned long)(_words) << WORDS_SHIFT)))
+
+#define GET_TYPEIX(_h) \
+ (((PRUword)(_h) >> TYPEIX_SHIFT) & 0xff)
+
+#define MARK(_sp,_p) \
+ (((PRWord *)(_p))[0] |= MARK_BIT)
+#define IS_MARKED(_sp,_p) \
+ (((PRWord *)(_p))[0] & MARK_BIT)
+#define OBJ_BYTES(_h) \
+ (((PRInt32) (_h) & 0x003ffffcL) << (PR_BYTES_PER_WORD_LOG2-2L))
+
+#define GC_GET_USER_BITS(_h) (((_h) & GC_USER_BITS) >> GC_USER_BITS_SHIFT)
+
+/************************************************************************/
+
+/*
+** Mark the start of an object in a segment. Note that we mark the header
+** word (which we always have), not the data word (which we may not have
+** for empty objects).
+** XXX tune: put subtract of _sp->base into _sp->hbits pointer?
+*/
+#if !defined(WIN16)
+#define SET_HBIT(_sp,_ph) \
+ SET_BIT((_sp)->hbits, (((PRWord*)(_ph)) - ((PRWord*) (_sp)->base)))
+
+#define CLEAR_HBIT(_sp,_ph) \
+ CLEAR_BIT((_sp)->hbits, (((PRWord*)(_ph)) - ((PRWord*) (_sp)->base)))
+
+#define IS_HBIT(_sp,_ph) \
+ TEST_BIT((_sp)->hbits, (((PRWord*)(_ph)) - ((PRWord*) (_sp)->base)))
+#else
+
+#define SET_HBIT(_sp,_ph) set_hbit(_sp,_ph)
+
+#define CLEAR_HBIT(_sp,_ph) clear_hbit(_sp,_ph)
+
+#define IS_HBIT(_sp,_ph) is_hbit(_sp,_ph)
+
+static void
+set_hbit(GCSeg *sp, PRWord *p)
+{
+ unsigned int distance;
+ unsigned int index;
+ PRWord mask;
+
+ PR_ASSERT( SELECTOROF(p) == SELECTOROF(sp->base) );
+ PR_ASSERT( OFFSETOF(p) >= OFFSETOF(sp->base) );
+
+ distance = (OFFSETOF(p) - OFFSETOF(sp->base)) >> 2;
+ index = distance >> PR_BITS_PER_WORD_LOG2;
+ mask = 1L << (distance&(PR_BITS_PER_WORD-1));
+
+ sp->hbits[index] |= mask;
+}
+
+static void
+clear_hbit(GCSeg *sp, PRWord *p)
+{
+ unsigned int distance;
+ unsigned int index;
+ PRWord mask;
+
+ PR_ASSERT( SELECTOROF(p) == SELECTOROF(sp->base) );
+ PR_ASSERT( OFFSETOF(p) >= OFFSETOF(sp->base) );
+
+ distance = (OFFSETOF(p) - OFFSETOF(sp->base)) >> 2;
+ index = distance >> PR_BITS_PER_WORD_LOG2;
+ mask = 1L << (distance&(PR_BITS_PER_WORD-1));
+
+ sp->hbits[index] &= ~mask;
+}
+
+static int
+is_hbit(GCSeg *sp, PRWord *p)
+{
+ unsigned int distance;
+ unsigned int index;
+ PRWord mask;
+
+ PR_ASSERT( SELECTOROF(p) == SELECTOROF(sp->base) );
+ PR_ASSERT( OFFSETOF(p) >= OFFSETOF(sp->base) );
+
+ distance = (OFFSETOF(p) - OFFSETOF(sp->base)) >> 2;
+ index = distance >> PR_BITS_PER_WORD_LOG2;
+ mask = 1L << (distance&(PR_BITS_PER_WORD-1));
+
+ return ((sp->hbits[index] & mask) != 0);
+}
+
+
+#endif /* WIN16 */
+
+/*
+** Given a pointer into this segment, back it up until we are at the
+** start of the object the pointer points into. Each heap segment has a
+** bitmap that has one bit for each word of the objects it contains. The
+** bit's are set for the firstword of an object, and clear for it's other
+** words.
+*/
+static PRWord *FindObject(GCSeg *sp, PRWord *p)
+{
+ PRWord *base;
+
+ /* Align p to it's proper boundary before we start fiddling with it */
+ p = (PRWord*) ((PRWord)p & ~(PR_BYTES_PER_WORD-1L));
+
+ base = (PRWord *) sp->base;
+#if defined(WIN16)
+ PR_ASSERT( SELECTOROF(p) == SELECTOROF(base));
+#endif
+ do {
+ if (IS_HBIT(sp, p)) {
+ return (p);
+ }
+ p--;
+ } while ( p >= base );
+
+ /* Heap is corrupted! */
+ _GCTRACE(GC_TRACE, ("ERROR: The heap is corrupted!!! aborting now!"));
+ abort();
+ return NULL;
+}
+
+/************************************************************************/
+#if !defined(XP_PC) || defined(XP_OS2)
+#define OutputDebugString(msg)
+#endif
+
+#if !defined(WIN16)
+#define IN_SEGMENT(_sp, _p) \
+ ((((char *)(_p)) >= (_sp)->base) && \
+ (((char *)(_p)) < (_sp)->limit))
+#else
+#define IN_SEGMENT(_sp, _p) \
+ ((((PRWord)(_p)) >= ((PRWord)(_sp)->base)) && \
+ (((PRWord)(_p)) < ((PRWord)(_sp)->limit)))
+#endif
+
+static GCSeg *InHeap(void *p)
+{
+ GCSeg *sp, *esp;
+
+ if (lastInHeap && IN_SEGMENT(lastInHeap, p)) {
+ return lastInHeap;
+ }
+
+ sp = segs;
+ esp = segs + nsegs;
+ for (; sp < esp; sp++) {
+ if (IN_SEGMENT(sp, p)) {
+ lastInHeap = sp;
+ return sp;
+ }
+ }
+ return 0;
+}
+
+/*
+** Grow the heap by allocating another segment. Fudge the requestedSize
+** value to try to pre-account for the HBITS.
+*/
+static GCSeg* DoGrowHeap(PRInt32 requestedSize, PRBool exactly)
+{
+ GCSeg *sp;
+ GCSegInfo *segInfo;
+ GCFreeChunk *cp;
+ char *base;
+ PRWord *hbits;
+ PRInt32 nhbytes, nhbits;
+ PRUint32 allocSize;
+
+ if (nsegs == MAX_SEGS) {
+ /* No room for more segments */
+ return 0;
+ }
+
+ segInfo = (GCSegInfo*) PR_MALLOC(sizeof(GCSegInfo));
+#ifdef DEBUG
+ {
+ char str[256];
+ sprintf(str, "[1] Allocated %ld bytes at %p\n",
+ (long) sizeof(GCSegInfo), segInfo);
+ OutputDebugString(str);
+ }
+#endif
+ if (!segInfo) {
+ return 0;
+ }
+
+#if defined(WIN16)
+ if (requestedSize > segmentSize) {
+ PR_DELETE(segInfo);
+ return 0;
+ }
+#endif
+
+ /* Get more memory from the OS */
+ if (exactly) {
+ allocSize = requestedSize;
+ base = (char *) PR_MALLOC(requestedSize);
+ } else {
+ allocSize = requestedSize;
+ allocSize = (allocSize + _pr_pageSize - 1L) >> _pr_pageShift;
+ allocSize <<= _pr_pageShift;
+ base = (char*)_MD_GrowGCHeap(&allocSize);
+ }
+ if (!base) {
+ PR_DELETE(segInfo);
+ return 0;
+ }
+
+ nhbits = (PRInt32)(
+ (allocSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2);
+ nhbytes = ((nhbits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2)
+ * sizeof(PRWord);
+
+ /* Get bitmap memory from malloc heap */
+#if defined(WIN16)
+ PR_ASSERT( nhbytes < MAX_ALLOC_SIZE );
+#endif
+ hbits = (PRWord *) PR_CALLOC((PRUint32)nhbytes);
+ if (!hbits) {
+ /* Loser! */
+ PR_DELETE(segInfo);
+ if (exactly) {
+ PR_DELETE(base);
+ } else {
+ /* XXX do something about this */
+ /* _MD_FreeGCSegment(base, allocSize); */
+ }
+ return 0;
+ }
+
+ /*
+ ** Setup new segment.
+ */
+ sp = &segs[nsegs++];
+ segInfo->base = sp->base = base;
+ segInfo->limit = sp->limit = base + allocSize;
+ segInfo->hbits = sp->hbits = hbits;
+ sp->info = segInfo;
+ segInfo->fromMalloc = exactly;
+ memset(base, 0, allocSize);
+
+#ifdef GCMETER
+ if (_pr_gcMeter & _GC_METER_GROWTH) {
+ fprintf(stderr, "[GC: new segment base=%p size=%ld]\n",
+ sp->base, (long) allocSize);
+ }
+#endif
+
+ _pr_gcData.allocMemory += allocSize;
+ _pr_gcData.freeMemory += allocSize;
+
+ if (!exactly) {
+ PRInt32 bin;
+
+ /* Put free memory into a freelist bin */
+ cp = (GCFreeChunk *) base;
+ cp->segment = sp;
+ cp->chunkSize = allocSize;
+ InlineBinNumber(bin, allocSize)
+ cp->next = bins[bin];
+ bins[bin] = cp;
+ if (bin < minBin) minBin = bin;
+ if (bin > maxBin) maxBin = bin;
+ } else {
+ /*
+ ** When exactly allocating the entire segment is given over to a
+ ** single object to prevent fragmentation
+ */
+ }
+
+ if (!_pr_gcData.lowSeg) {
+ _pr_gcData.lowSeg = (PRWord*) sp->base;
+ _pr_gcData.highSeg = (PRWord*) sp->limit;
+ } else {
+ if ((PRWord*)sp->base < _pr_gcData.lowSeg) {
+ _pr_gcData.lowSeg = (PRWord*) sp->base;
+ }
+ if ((PRWord*)sp->limit > _pr_gcData.highSeg) {
+ _pr_gcData.highSeg = (PRWord*) sp->limit;
+ }
+ }
+
+ /*
+ ** Get rid of the GC pointer in case it shows up in some uninitialized
+ ** local stack variable later (while scanning the C stack looking for
+ ** roots).
+ */
+ memset(&base, 0, sizeof(base)); /* optimizers beware */
+
+ PR_LOG(_pr_msgc_lm, PR_LOG_WARNING, ("grow heap: total gc memory now %d",
+ _pr_gcData.allocMemory));
+
+ return sp;
+}
+
+#ifdef USE_EXTEND_HEAP
+static PRBool ExtendHeap(PRInt32 requestedSize) {
+ GCSeg* sp;
+ PRUint32 allocSize;
+ PRInt32 oldSize, newSize;
+ PRInt32 newHBits, newHBytes;
+ PRInt32 oldHBits, oldHBytes;
+ PRWord* hbits;
+ GCFreeChunk* cp;
+ PRInt32 bin;
+
+ /* Can't extend nothing */
+ if (nsegs == 0) return PR_FALSE;
+
+ /* Round up requested size to the size of a page */
+ allocSize = (PRUint32) requestedSize;
+ allocSize = (allocSize + _pr_pageSize - 1L) >> _pr_pageShift;
+ allocSize <<= _pr_pageShift;
+
+ /* Malloc some memory for the new hbits array */
+ sp = segs;
+ oldSize = sp->limit - sp->base;
+ newSize = oldSize + allocSize;
+ newHBits = (newSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2;
+ newHBytes = ((newHBits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2)
+ * sizeof(PRWord);
+ hbits = (PRWord*) PR_MALLOC(newHBytes);
+ if (0 == hbits) return PR_FALSE;
+
+ /* Attempt to extend the last segment by the desired amount */
+ if (_MD_ExtendGCHeap(sp->base, oldSize, newSize)) {
+ oldHBits = (oldSize + PR_BYTES_PER_WORD - 1L) >> PR_BYTES_PER_WORD_LOG2;
+ oldHBytes = ((oldHBits + PR_BITS_PER_WORD - 1L) >> PR_BITS_PER_WORD_LOG2)
+ * sizeof(PRWord);
+
+ /* Copy hbits from old memory into new memory */
+ memset(hbits, 0, newHBytes);
+ memcpy(hbits, sp->hbits, oldHBytes);
+ PR_DELETE(sp->hbits);
+ memset(sp->base + oldSize, 0, allocSize);
+
+ /* Adjust segment state */
+ sp->limit += allocSize;
+ sp->hbits = hbits;
+ sp->info->limit = sp->limit;
+ sp->info->hbits = hbits;
+
+ /* Put free memory into a freelist bin */
+ cp = (GCFreeChunk *) (sp->base + oldSize);
+ cp->segment = sp;
+ cp->chunkSize = allocSize;
+ InlineBinNumber(bin, allocSize)
+ cp->next = bins[bin];
+ bins[bin] = cp;
+ if (bin < minBin) minBin = bin;
+ if (bin > maxBin) maxBin = bin;
+
+ /* Prevent a pointer that points to the free memory from showing
+ up on the call stack later on */
+ memset(&cp, 0, sizeof(cp));
+
+ /* Update heap brackets and counters */
+ if ((PRWord*)sp->limit > _pr_gcData.highSeg) {
+ _pr_gcData.highSeg = (PRWord*) sp->limit;
+ }
+ _pr_gcData.allocMemory += allocSize;
+ _pr_gcData.freeMemory += allocSize;
+
+ return PR_TRUE;
+ }
+ PR_DELETE(hbits);
+ return PR_FALSE;
+}
+#endif /* USE_EXTEND_HEAP */
+
+static GCSeg *GrowHeapExactly(PRInt32 requestedSize)
+{
+ GCSeg *sp = DoGrowHeap(requestedSize, PR_TRUE);
+ return sp;
+}
+
+static PRBool GrowHeap(PRInt32 requestedSize)
+{
+ void *p;
+#ifdef USE_EXTEND_HEAP
+ if (ExtendHeap(requestedSize)) {
+ return PR_TRUE;
+ }
+#endif
+ p = DoGrowHeap(requestedSize, PR_FALSE);
+ return (p != NULL ? PR_TRUE : PR_FALSE);
+}
+
+/*
+** Release a segment when it is entirely free.
+*/
+static void ShrinkGCHeap(GCSeg *sp)
+{
+#ifdef GCMETER
+ if (_pr_gcMeter & _GC_METER_GROWTH) {
+ fprintf(stderr, "[GC: free segment base=%p size=%ld]\n",
+ sp->base, (long) (sp->limit - sp->base));
+ }
+#endif
+
+ /*
+ * Put segment onto free seginfo list (we can't call free right now
+ * because we have the GC lock and all of the other threads are
+ * suspended; if one of them has the malloc lock we would deadlock)
+ */
+ sp->info->next = freeSegs;
+ freeSegs = sp->info;
+ collectorCleanupNeeded = 1;
+ _pr_gcData.allocMemory -= sp->limit - sp->base;
+ if (sp == lastInHeap) lastInHeap = 0;
+
+ /* Squish out disappearing segment from segment table */
+ --nsegs;
+ if ((sp - segs) != nsegs) {
+ *sp = segs[nsegs];
+ } else {
+ sp->base = 0;
+ sp->limit = 0;
+ sp->hbits = 0;
+ sp->info = 0;
+ }
+
+ /* Recalculate the lowSeg and highSeg values */
+ _pr_gcData.lowSeg = (PRWord*) segs[0].base;
+ _pr_gcData.highSeg = (PRWord*) segs[0].limit;
+ for (sp = segs; sp < &segs[nsegs]; sp++) {
+ if ((PRWord*)sp->base < _pr_gcData.lowSeg) {
+ _pr_gcData.lowSeg = (PRWord*) sp->base;
+ }
+ if ((PRWord*)sp->limit > _pr_gcData.highSeg) {
+ _pr_gcData.highSeg = (PRWord*) sp->limit;
+ }
+ }
+}
+
+static void FreeSegments(void)
+{
+ GCSegInfo *si;
+
+ while (0 != freeSegs) {
+ LOCK_GC();
+ si = freeSegs;
+ if (si) {
+ freeSegs = si->next;
+ }
+ UNLOCK_GC();
+
+ if (!si) {
+ break;
+ }
+ PR_DELETE(si->base);
+ PR_DELETE(si->hbits);
+ PR_DELETE(si);
+ }
+}
+
+/************************************************************************/
+
+void ScanScanQ(GCScanQ *iscan)
+{
+ PRWord *p;
+ PRWord **pp;
+ PRWord **epp;
+ GCScanQ nextQ, *scan, *next, *temp;
+ CollectorType *ct;
+
+ if (!iscan->queued) return;
+
+ _GCTRACE(GC_MARK, ("begin scanQ @ 0x%x (%d)", iscan, iscan->queued));
+ scan = iscan;
+ next = &nextQ;
+ while (scan->queued) {
+ _GCTRACE(GC_MARK, ("continue scanQ @ 0x%x (%d)", scan, scan->queued));
+ /*
+ * Set pointer to current scanQ so that _pr_gcData.livePointer
+ * can find it.
+ */
+ pScanQ = next;
+ next->queued = 0;
+
+ /* Now scan the scan Q */
+ pp = scan->q;
+ epp = &scan->q[scan->queued];
+ scan->queued = 0;
+ while (pp < epp) {
+ p = *pp++;
+ ct = &_pr_collectorTypes[GET_TYPEIX(p[0])];
+ PR_ASSERT(0 != ct->gctype.scan);
+ /* Scan object ... */
+ (*ct->gctype.scan)(p + 1);
+ }
+
+ /* Exchange pointers so that we scan next */
+ temp = scan;
+ scan = next;
+ next = temp;
+ }
+
+ pScanQ = iscan;
+ PR_ASSERT(nextQ.queued == 0);
+ PR_ASSERT(iscan->queued == 0);
+}
+
+/*
+** Called during root finding step to identify "root" pointers into the
+** GC heap. First validate if it is a real heap pointer and then mark the
+** object being pointed to and add it to the scan Q for eventual
+** scanning.
+*/
+static void PR_CALLBACK ProcessRootBlock(void **base, PRInt32 count)
+{
+ GCSeg *sp;
+ PRWord *p0, *p, h, tix, *low, *high, *segBase;
+ CollectorType *ct;
+#ifdef DEBUG
+ void **base0 = base;
+#endif
+
+ low = _pr_gcData.lowSeg;
+ high = _pr_gcData.highSeg;
+ while (--count >= 0) {
+ p0 = (PRWord*) *base++;
+ /*
+ ** XXX:
+ ** Until Win16 maintains lowSeg and highSeg correctly,
+ ** (ie. lowSeg=MIN(all segs) and highSeg = MAX(all segs))
+ ** Allways scan through the segment list
+ */
+#if !defined(WIN16)
+ if (p0 < low) continue; /* below gc heap */
+ if (p0 >= high) continue; /* above gc heap */
+#endif
+ /* NOTE: inline expansion of InHeap */
+ /* Find segment */
+ sp = lastInHeap;
+ if (!sp || !IN_SEGMENT(sp,p0)) {
+ GCSeg *esp;
+ sp = segs;
+ esp = segs + nsegs;
+ for (; sp < esp; sp++) {
+ if (IN_SEGMENT(sp, p0)) {
+ lastInHeap = sp;
+ goto find_object;
+ }
+ }
+ continue;
+ }
+
+ find_object:
+ /* NOTE: Inline expansion of FindObject */
+ /* Align p to it's proper boundary before we start fiddling with it */
+ p = (PRWord*) ((PRWord)p0 & ~(PR_BYTES_PER_WORD-1L));
+ segBase = (PRWord *) sp->base;
+ do {
+ if (IS_HBIT(sp, p)) {
+ goto winner;
+ }
+ p--;
+ } while (p >= segBase);
+
+ /*
+ ** We have a pointer into the heap, but it has no header
+ ** bit. This means that somehow the very first object in the heap
+ ** doesn't have a header. This is impossible so when debugging
+ ** lets abort.
+ */
+#ifdef DEBUG
+ PR_Abort();
+#endif
+
+ winner:
+ h = p[0];
+ if ((h & MARK_BIT) == 0) {
+#ifdef DEBUG
+ _GCTRACE(GC_ROOTS,
+ ("root 0x%p (%d) base0=%p off=%d",
+ p, OBJ_BYTES(h), base0, (base-1) - base0));
+#endif
+
+ /* Mark the root we just found */
+ p[0] = h | MARK_BIT;
+
+ /*
+ * See if object we just found needs scanning. It must
+ * have a scan function to be placed on the scanQ.
+ */
+ tix = (PRWord)GET_TYPEIX(h);
+ ct = &_pr_collectorTypes[tix];
+ if (0 == ct->gctype.scan) {
+ continue;
+ }
+
+ /*
+ ** Put a pointer onto the scan Q. We use the scan Q to avoid
+ ** deep recursion on the C call stack. Objects are added to
+ ** the scan Q until the scan Q fills up. At that point we
+ ** make a call to ScanScanQ which proceeds to scan each of
+ ** the objects in the Q. This limits the recursion level by a
+ ** large amount though the stack frames get larger to hold
+ ** the GCScanQ's.
+ */
+ pScanQ->q[pScanQ->queued++] = p;
+ if (pScanQ->queued == MAX_SCAN_Q) {
+ METER(_pr_scanDepth++);
+ ScanScanQ(pScanQ);
+ }
+ }
+ }
+}
+
+static void PR_CALLBACK ProcessRootPointer(void *ptr)
+{
+ PRWord *p0, *p, h, tix, *segBase;
+ GCSeg* sp;
+ CollectorType *ct;
+
+ p0 = (PRWord*) ptr;
+
+ /*
+ ** XXX:
+ ** Until Win16 maintains lowSeg and highSeg correctly,
+ ** (ie. lowSeg=MIN(all segs) and highSeg = MAX(all segs))
+ ** Allways scan through the segment list
+ */
+#if !defined(WIN16)
+ if (p0 < _pr_gcData.lowSeg) return; /* below gc heap */
+ if (p0 >= _pr_gcData.highSeg) return; /* above gc heap */
+#endif
+
+ /* NOTE: inline expansion of InHeap */
+ /* Find segment */
+ sp = lastInHeap;
+ if (!sp || !IN_SEGMENT(sp,p0)) {
+ GCSeg *esp;
+ sp = segs;
+ esp = segs + nsegs;
+ for (; sp < esp; sp++) {
+ if (IN_SEGMENT(sp, p0)) {
+ lastInHeap = sp;
+ goto find_object;
+ }
+ }
+ return;
+ }
+
+ find_object:
+ /* NOTE: Inline expansion of FindObject */
+ /* Align p to it's proper boundary before we start fiddling with it */
+ p = (PRWord*) ((PRWord)p0 & ~(BYTES_PER_WORD-1L));
+ segBase = (PRWord *) sp->base;
+ do {
+ if (IS_HBIT(sp, p)) {
+ goto winner;
+ }
+ p--;
+ } while (p >= segBase);
+
+ /*
+ ** We have a pointer into the heap, but it has no header
+ ** bit. This means that somehow the very first object in the heap
+ ** doesn't have a header. This is impossible so when debugging
+ ** lets abort.
+ */
+#ifdef DEBUG
+ PR_Abort();
+#endif
+
+ winner:
+ h = p[0];
+ if ((h & MARK_BIT) == 0) {
+#ifdef DEBUG
+ _GCTRACE(GC_ROOTS, ("root 0x%p (%d)", p, OBJ_BYTES(h)));
+#endif
+
+ /* Mark the root we just found */
+ p[0] = h | MARK_BIT;
+
+ /*
+ * See if object we just found needs scanning. It must
+ * have a scan function to be placed on the scanQ.
+ */
+ tix = (PRWord)GET_TYPEIX(h);
+ ct = &_pr_collectorTypes[tix];
+ if (0 == ct->gctype.scan) {
+ return;
+ }
+
+ /*
+ ** Put a pointer onto the scan Q. We use the scan Q to avoid
+ ** deep recursion on the C call stack. Objects are added to
+ ** the scan Q until the scan Q fills up. At that point we
+ ** make a call to ScanScanQ which proceeds to scan each of
+ ** the objects in the Q. This limits the recursion level by a
+ ** large amount though the stack frames get larger to hold
+ ** the GCScanQ's.
+ */
+ pScanQ->q[pScanQ->queued++] = p;
+ if (pScanQ->queued == MAX_SCAN_Q) {
+ METER(_pr_scanDepth++);
+ ScanScanQ(pScanQ);
+ }
+ }
+}
+
+/************************************************************************/
+
+/*
+** Empty the freelist for each segment. This is done to make sure that
+** the root finding step works properly (otherwise, if we had a pointer
+** into a free section, we might not find its header word and abort in
+** FindObject)
+*/
+static void EmptyFreelists(void)
+{
+ GCFreeChunk *cp;
+ GCFreeChunk *next;
+ GCSeg *sp;
+ PRWord *p;
+ PRInt32 chunkSize;
+ PRInt32 bin;
+
+ /*
+ ** Run over the freelist and make all of the free chunks look like
+ ** object debris.
+ */
+ for (bin = 0; bin <= NUM_BINS-1; bin++) {
+ cp = bins[bin];
+ while (cp) {
+ next = cp->next;
+ sp = cp->segment;
+ chunkSize = cp->chunkSize >> BYTES_PER_WORD_LOG2;
+ p = (PRWord*) cp;
+ PR_ASSERT(chunkSize != 0);
+ p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, chunkSize);
+ SET_HBIT(sp, p);
+ cp = next;
+ }
+ bins[bin] = 0;
+ }
+ minBin = NUM_BINS - 1;
+ maxBin = 0;
+}
+
+typedef struct GCBlockEnd {
+ PRInt32 check;
+#ifdef GC_CHECK
+ PRInt32 requestedBytes;
+#endif
+#ifdef GC_STATS
+ PRInt32 bin;
+ PRInt64 allocTime;
+#endif
+#ifdef GC_TRACEROOTS
+ PRInt32 traceGeneration;
+#endif
+} GCBlockEnd;
+
+#define PR_BLOCK_END 0xDEADBEEF
+
+/************************************************************************/
+
+#ifdef GC_STATS
+
+typedef struct GCStat {
+ PRInt32 nallocs;
+ double allocTime;
+ double allocTimeVariance;
+ PRInt32 nfrees;
+ double lifetime;
+ double lifetimeVariance;
+} GCStat;
+
+#define GCSTAT_BINS NUM_BINS
+
+GCStat gcstats[GCSTAT_BINS];
+
+#define GCLTFREQ_BINS NUM_BINS
+
+PRInt32 gcltfreq[GCSTAT_BINS][GCLTFREQ_BINS];
+
+#include <math.h>
+
+static char*
+pr_GetSizeString(PRUint32 size)
+{
+ char* sizeStr;
+ if (size < 1024)
+ sizeStr = PR_smprintf("<= %ld", size);
+ else if (size < 1024 * 1024)
+ sizeStr = PR_smprintf("<= %ldk", size / 1024);
+ else
+ sizeStr = PR_smprintf("<= %ldM", size / (1024 * 1024));
+ return sizeStr;
+}
+
+static void
+pr_FreeSizeString(char *sizestr)
+{
+ PR_smprintf_free(sizestr);
+}
+
+
+static void
+pr_PrintGCAllocStats(FILE* out)
+{
+ PRInt32 i, j;
+ _PR_DebugPrint(out, "\n--Allocation-Stats-----------------------------------------------------------");
+ _PR_DebugPrint(out, "\n--Obj-Size----Count-----Avg-Alloc-Time-----------Avg-Lifetime---------%%Freed-\n");
+ for (i = 0; i < GCSTAT_BINS; i++) {
+ GCStat stat = gcstats[i];
+ double allocTimeMean = 0.0, allocTimeVariance = 0.0, lifetimeMean = 0.0, lifetimeVariance = 0.0;
+ PRUint32 maxSize = (1 << i);
+ char* sizeStr;
+ if (stat.nallocs != 0.0) {
+ allocTimeMean = stat.allocTime / stat.nallocs;
+ allocTimeVariance = fabs(stat.allocTimeVariance / stat.nallocs - allocTimeMean * allocTimeMean);
+ }
+ if (stat.nfrees != 0.0) {
+ lifetimeMean = stat.lifetime / stat.nfrees;
+ lifetimeVariance = fabs(stat.lifetimeVariance / stat.nfrees - lifetimeMean * lifetimeMean);
+ }
+ sizeStr = pr_GetSizeString(maxSize);
+ _PR_DebugPrint(out, "%10s %8lu %10.3f +- %10.3f %10.3f +- %10.3f (%2ld%%)\n",
+ sizeStr, stat.nallocs,
+ allocTimeMean, sqrt(allocTimeVariance),
+ lifetimeMean, sqrt(lifetimeVariance),
+ (stat.nallocs ? (stat.nfrees * 100 / stat.nallocs) : 0));
+ pr_FreeSizeString(sizeStr);
+ }
+ _PR_DebugPrint(out, "--Lifetime-Frequency-Counts----------------------------------------------------\n");
+ _PR_DebugPrint(out, "size\\cnt");
+ for (j = 0; j < GCLTFREQ_BINS; j++) {
+ _PR_DebugPrint(out, "\t%lu", j);
+ }
+ _PR_DebugPrint(out, "\n");
+ for (i = 0; i < GCSTAT_BINS; i++) {
+ PRInt32* freqs = gcltfreq[i];
+ _PR_DebugPrint(out, "%lu", (1 << i));
+ for (j = 0; j < GCLTFREQ_BINS; j++) {
+ _PR_DebugPrint(out, "\t%lu", freqs[j]);
+ }
+ _PR_DebugPrint(out, "\n");
+ }
+ _PR_DebugPrint(out, "-------------------------------------------------------------------------------\n");
+}
+
+PR_PUBLIC_API(void)
+PR_PrintGCAllocStats(void)
+{
+ pr_PrintGCAllocStats(stderr);
+}
+
+#endif /* GC_STATS */
+
+/************************************************************************/
+
+/*
+** Sweep a segment, cleaning up all of the debris. Coallese the debris
+** into GCFreeChunk's which are added to the freelist bins.
+*/
+static PRBool SweepSegment(GCSeg *sp)
+{
+ PRWord h, tix;
+ PRWord *p;
+ PRWord *np;
+ PRWord *limit;
+ GCFreeChunk *cp;
+ PRInt32 bytes, chunkSize, segmentSize, totalFree;
+ CollectorType *ct;
+ PRInt32 bin;
+
+ /*
+ ** Now scan over the segment's memory in memory order, coallescing
+ ** all of the debris into a FreeChunk list.
+ */
+ totalFree = 0;
+ segmentSize = sp->limit - sp->base;
+ p = (PRWord *) sp->base;
+ limit = (PRWord *) sp->limit;
+ PR_ASSERT(segmentSize > 0);
+ while (p < limit) {
+ chunkSize = 0;
+ cp = (GCFreeChunk *) p;
+
+ /* Attempt to coallesce any neighboring free objects */
+ for (;;) {
+ PR_ASSERT(IS_HBIT(sp, p) != 0);
+ h = p[0];
+ bytes = OBJ_BYTES(h);
+ PR_ASSERT(bytes != 0);
+ np = (PRWord *) ((char *)p + bytes);
+ tix = (PRWord)GET_TYPEIX(h);
+ if ((h & MARK_BIT) && (tix != FREE_MEMORY_TYPEIX)) {
+#ifdef DEBUG
+ if (tix != FREE_MEMORY_TYPEIX) {
+ PR_ASSERT(_pr_collectorTypes[tix].flags != 0);
+ }
+#endif
+ p[0] = h & ~(MARK_BIT|FINAL_BIT);
+ _GCTRACE(GC_SWEEP, ("busy 0x%x (%d)", p, bytes));
+ break;
+ }
+ _GCTRACE(GC_SWEEP, ("free 0x%x (%d)", p, bytes));
+
+ /* Found a free object */
+#ifdef GC_STATS
+ {
+ PRInt32 userSize = bytes - sizeof(GCBlockEnd);
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + userSize);
+ if (userSize >= 0 && end->check == PR_BLOCK_END) {
+ PRInt64 now = PR_Now();
+ double nowd, delta;
+ PRInt32 freq;
+ LL_L2D(nowd, now);
+ delta = nowd - end->allocTime;
+ gcstats[end->bin].nfrees++;
+ gcstats[end->bin].lifetime += delta;
+ gcstats[end->bin].lifetimeVariance += delta * delta;
+
+ InlineBinNumber(freq, delta);
+ gcltfreq[end->bin][freq]++;
+
+ end->check = 0;
+ }
+ }
+#endif
+ CLEAR_HBIT(sp, p);
+ ct = &_pr_collectorTypes[tix];
+ if (0 != ct->gctype.free) {
+ (*ct->gctype.free)(p + 1);
+ }
+ chunkSize = chunkSize + bytes;
+ if (np == limit) {
+ /* Found the end of heap */
+ break;
+ }
+ PR_ASSERT(np < limit);
+ p = np;
+ }
+
+ if (chunkSize) {
+ _GCTRACE(GC_SWEEP, ("free chunk 0x%p to 0x%p (%d)",
+ cp, (char*)cp + chunkSize - 1, chunkSize));
+ if (chunkSize < MIN_FREE_CHUNK_BYTES) {
+ /* Lost a tiny fragment until (maybe) next time */
+ METER(meter.wastedBytes += chunkSize);
+ p = (PRWord *) cp;
+ chunkSize >>= BYTES_PER_WORD_LOG2;
+ PR_ASSERT(chunkSize != 0);
+ p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, chunkSize);
+ SET_HBIT(sp, p);
+ } else {
+ /* See if the chunk constitutes the entire segment */
+ if (chunkSize == segmentSize) {
+ /* Free up the segment right now */
+ if (sp->info->fromMalloc) {
+ ShrinkGCHeap(sp);
+ return PR_TRUE;
+ }
+ }
+
+ /* Put free chunk into the appropriate bin */
+ cp->segment = sp;
+ cp->chunkSize = chunkSize;
+ InlineBinNumber(bin, chunkSize)
+ cp->next = bins[bin];
+ bins[bin] = cp;
+ if (bin < minBin) minBin = bin;
+ if (bin > maxBin) maxBin = bin;
+
+ /* Zero swept memory now */
+ memset(cp+1, 0, chunkSize - sizeof(*cp));
+ METER(meter.numFreeChunks++);
+ totalFree += chunkSize;
+ }
+ }
+
+ /* Advance to next object */
+ p = np;
+ }
+
+ PR_ASSERT(totalFree <= segmentSize);
+
+ _pr_gcData.freeMemory += totalFree;
+ _pr_gcData.busyMemory += (sp->limit - sp->base) - totalFree;
+ return PR_FALSE;
+}
+
+/************************************************************************/
+
+/* This is a list of all the objects that are finalizable. This is not
+ the list of objects that are awaiting finalization because they
+ have been collected. */
+PRCList _pr_finalizeableObjects;
+
+/* This is the list of objects that are awaiting finalization because
+ they have been collected. */
+PRCList _pr_finalQueue;
+
+/* Each object that requires finalization has one of these objects
+ allocated as well. The GCFinal objects are put on the
+ _pr_finalizeableObjects list until the object is collected at which
+ point the GCFinal object is moved to the _pr_finalQueue */
+typedef struct GCFinalStr {
+ PRCList links;
+ PRWord *object;
+} GCFinal;
+
+/* Find pointer to GCFinal struct from the list linkaged embedded in it */
+#define FinalPtr(_qp) \
+ ((GCFinal*) ((char*) (_qp) - offsetof(GCFinal,links)))
+
+static GCFinal *AllocFinalNode(void)
+{
+ return PR_NEWZAP(GCFinal);
+}
+
+static void FreeFinalNode(GCFinal *node)
+{
+ PR_DELETE(node);
+}
+
+/*
+** Prepare for finalization. At this point in the GC cycle we have
+** identified all of the live objects. For each object on the
+** _pr_finalizeableObjects list see if the object is alive or dead. If
+** it's dead, resurrect it and move it from the _pr_finalizeableObjects
+** list to the _pr_finalQueue (object's only get finalized once).
+**
+** Once _pr_finalizeableObjects has been processed we can finish the
+** GC and free up memory and release the threading lock. After that we
+** can invoke the finalization procs for each object that is on the
+** _pr_finalQueue.
+*/
+static void PrepareFinalize(void)
+{
+ PRCList *qp;
+ GCFinal *fp;
+ PRWord h;
+ PRWord *p;
+ void (PR_CALLBACK *livePointer)(void *ptr);
+#ifdef DEBUG
+ CollectorType *ct;
+#endif
+
+ /* This must be done under the same lock that the finalizer uses */
+ PR_ASSERT( GC_IS_LOCKED() );
+
+ /* cache this ptr */
+ livePointer = _pr_gcData.livePointer;
+
+ /*
+ * Pass #1: Identify objects that are to be finalized, set their
+ * FINAL_BIT.
+ */
+ qp = _pr_finalizeableObjects.next;
+ while (qp != &_pr_finalizeableObjects) {
+ fp = FinalPtr(qp);
+ qp = qp->next;
+ h = fp->object[0]; /* Grab header word */
+ if (h & MARK_BIT) {
+ /* Object is already alive */
+ continue;
+ }
+
+#ifdef DEBUG
+ ct = &_pr_collectorTypes[GET_TYPEIX(h)];
+ PR_ASSERT((0 != ct->flags) && (0 != ct->gctype.finalize));
+#endif
+ fp->object[0] |= FINAL_BIT;
+ _GCTRACE(GC_FINAL, ("moving %p (%d) to finalQueue",
+ fp->object, OBJ_BYTES(h)));
+ }
+
+ /*
+ * Pass #2: For each object that is going to be finalized, move it to
+ * the finalization queue and resurrect it
+ */
+ qp = _pr_finalizeableObjects.next;
+ while (qp != &_pr_finalizeableObjects) {
+ fp = FinalPtr(qp);
+ qp = qp->next;
+ h = fp->object[0]; /* Grab header word */
+ if ((h & FINAL_BIT) == 0) {
+ continue;
+ }
+
+ /* Resurrect the object and any objects it refers to */
+ p = &fp->object[1];
+ (*livePointer)(p);
+ PR_REMOVE_LINK(&fp->links);
+ PR_APPEND_LINK(&fp->links, &_pr_finalQueue);
+ }
+}
+
+/*
+** Scan the finalQ, marking each and every object on it live. This is
+** necessary because we might do a GC before objects that are on the
+** final queue get finalized. Since there are no other references
+** (otherwise they would be on the final queue), we have to scan them.
+** This really only does work if we call the GC before the finalizer
+** has a chance to do its job.
+*/
+extern void PR_CALLBACK _PR_ScanFinalQueue(void *notused)
+{
+#ifdef XP_MAC
+#pragma unused (notused)
+#endif
+ PRCList *qp;
+ GCFinal *fp;
+ PRWord *p;
+ void ( PR_CALLBACK *livePointer)(void *ptr);
+
+ livePointer = _pr_gcData.livePointer;
+ qp = _pr_finalQueue.next;
+ while (qp != &_pr_finalQueue) {
+ fp = FinalPtr(qp);
+ _GCTRACE(GC_FINAL, ("marking 0x%x (on final queue)", fp->object));
+ p = &fp->object[1];
+ (*livePointer)(p);
+ qp = qp->next;
+ }
+}
+
+void PR_CALLBACK FinalizerLoop(void* unused)
+{
+#ifdef XP_MAC
+#pragma unused (unused)
+#endif
+ GCFinal *fp;
+ PRWord *p;
+ PRWord h, tix;
+ CollectorType *ct;
+
+ LOCK_GC();
+ for (;;) {
+ p = 0; h = 0; /* don't let the gc find these pointers */
+ while (PR_CLIST_IS_EMPTY(&_pr_finalQueue))
+ PR_Wait(_pr_gcData.lock, PR_INTERVAL_NO_TIMEOUT);
+
+ _GCTRACE(GC_FINAL, ("begin finalization"));
+ while (_pr_finalQueue.next != &_pr_finalQueue) {
+ fp = FinalPtr(_pr_finalQueue.next);
+ PR_REMOVE_LINK(&fp->links);
+ p = fp->object;
+
+ h = p[0]; /* Grab header word */
+ tix = (PRWord)GET_TYPEIX(h);
+ ct = &_pr_collectorTypes[tix];
+ _GCTRACE(GC_FINAL, ("finalize 0x%x (%d)", p, OBJ_BYTES(h)));
+
+ /*
+ ** Give up the GC lock so that other threads can allocate memory
+ ** while this finalization method is running. Get it back
+ ** afterwards so that the list remains thread safe.
+ */
+ UNLOCK_GC();
+ FreeFinalNode(fp);
+ PR_ASSERT(ct->gctype.finalize != 0);
+ (*ct->gctype.finalize)(p + 1);
+ LOCK_GC();
+ }
+ _GCTRACE(GC_FINAL, ("end finalization"));
+ PR_Notify(_pr_gcData.lock);
+ }
+}
+
+static void NotifyFinalizer(void)
+{
+ if (!PR_CLIST_IS_EMPTY(&_pr_finalQueue)) {
+ PR_ASSERT( GC_IS_LOCKED() );
+ PR_Notify(_pr_gcData.lock);
+ }
+}
+
+void _PR_CreateFinalizer(PRThreadScope scope)
+{
+ if (!_pr_gcData.finalizer) {
+ _pr_gcData.finalizer = PR_CreateThreadGCAble(PR_SYSTEM_THREAD,
+ FinalizerLoop, 0,
+ PR_PRIORITY_LOW, scope,
+ PR_UNJOINABLE_THREAD, 0);
+
+ if (_pr_gcData.finalizer == NULL)
+ /* We are doomed if we can't start the finalizer */
+ PR_Abort();
+
+ }
+}
+
+void pr_FinalizeOnExit(void)
+{
+#ifdef DEBUG_warren
+ OutputDebugString("### Doing finalize-on-exit pass\n");
+#endif
+ PR_ForceFinalize();
+#ifdef DEBUG_warren
+ OutputDebugString("### Finalize-on-exit complete. Dumping object left to memory.out\n");
+ PR_DumpMemorySummary();
+ PR_DumpMemory(PR_TRUE);
+#endif
+}
+
+PR_IMPLEMENT(void) PR_ForceFinalize()
+{
+ LOCK_GC();
+ NotifyFinalizer();
+ while (!PR_CLIST_IS_EMPTY(&_pr_finalQueue)) {
+ PR_ASSERT( GC_IS_LOCKED() );
+ (void) PR_Wait(_pr_gcData.lock, PR_INTERVAL_NO_TIMEOUT);
+ }
+ UNLOCK_GC();
+
+ /* XXX I don't know how to make it wait (yet) */
+}
+
+/************************************************************************/
+
+typedef struct GCWeakStr {
+ PRCList links;
+ PRWord *object;
+} GCWeak;
+
+/*
+** Find pointer to GCWeak struct from the list linkaged embedded in it
+*/
+#define WeakPtr(_qp) \
+ ((GCWeak*) ((char*) (_qp) - offsetof(GCWeak,links)))
+
+PRCList _pr_weakLinks = PR_INIT_STATIC_CLIST(&_pr_weakLinks);
+PRCList _pr_freeWeakLinks = PR_INIT_STATIC_CLIST(&_pr_freeWeakLinks);
+
+#define WEAK_FREELIST_ISEMPTY() (_pr_freeWeakLinks.next == &_pr_freeWeakLinks)
+
+/*
+ * Keep objects referred to by weak free list alive until they can be
+ * freed
+ */
+static void PR_CALLBACK ScanWeakFreeList(void *notused) {
+#ifdef XP_MAC
+#pragma unused (notused)
+#endif
+ PRCList *qp = _pr_freeWeakLinks.next;
+ while (qp != &_pr_freeWeakLinks) {
+ GCWeak *wp = WeakPtr(qp);
+ qp = qp->next;
+ ProcessRootPointer(wp->object);
+ }
+}
+
+/*
+ * Empty the list of weak objects. Note that we can't call malloc/free
+ * under the cover of the GC's lock (we might deadlock), so transfer the
+ * list of free objects to a local list under the cover of the lock, then
+ * release the lock and free up the memory.
+ */
+static void EmptyWeakFreeList(void) {
+ if (!WEAK_FREELIST_ISEMPTY()) {
+ PRCList *qp, freeLinks;
+
+ PR_INIT_CLIST(&freeLinks);
+
+ /*
+ * Transfer list of free weak links from the global list to a
+ * local list.
+ */
+ LOCK_GC();
+ qp = _pr_freeWeakLinks.next;
+ while (qp != &_pr_freeWeakLinks) {
+ GCWeak *wp = WeakPtr(qp);
+ qp = qp->next;
+ PR_REMOVE_LINK(&wp->links);
+ PR_APPEND_LINK(&wp->links, &freeLinks);
+ }
+ UNLOCK_GC();
+
+ /* Free up storage now */
+ qp = freeLinks.next;
+ while (qp != &freeLinks) {
+ GCWeak *wp = WeakPtr(qp);
+ qp = qp->next;
+ PR_DELETE(wp);
+ }
+ }
+}
+
+/*
+ * Allocate a new weak node in the weak objects list
+ */
+static GCWeak *AllocWeakNode(void)
+{
+ EmptyWeakFreeList();
+ return PR_NEWZAP(GCWeak);
+}
+
+static void FreeWeakNode(GCWeak *node)
+{
+ PR_DELETE(node);
+}
+
+/*
+ * Check the weak links for validity. Note that the list of weak links is
+ * itself weak (otherwise we would keep the objects with weak links in
+ * them alive forever). As we scan the list check the weak link object
+ * itself and if it's not marked then remove it from the weak link list
+ */
+static void CheckWeakLinks(void) {
+ PRCList *qp;
+ GCWeak *wp;
+ PRWord *p, h, tix, **weakPtrAddress;
+ CollectorType *ct;
+ PRUint32 offset;
+
+ qp = _pr_weakLinks.next;
+ while (qp != &_pr_weakLinks) {
+ wp = WeakPtr(qp);
+ qp = qp->next;
+ if ((p = wp->object) != 0) {
+ h = p[0]; /* Grab header word */
+ if ((h & MARK_BIT) == 0) {
+ /*
+ * The object that has a weak link is no longer being
+ * referenced; remove it from the chain and let it get
+ * swept away by the GC. Transfer it to the list of
+ * free weak links for later freeing.
+ */
+ PR_REMOVE_LINK(&wp->links);
+ PR_APPEND_LINK(&wp->links, &_pr_freeWeakLinks);
+ collectorCleanupNeeded = 1;
+ continue;
+ }
+
+ /* Examine a live object that contains weak links */
+ tix = GET_TYPEIX(h);
+ ct = &_pr_collectorTypes[tix];
+ PR_ASSERT((ct->flags != 0) && (ct->gctype.getWeakLinkOffset != 0));
+ if (0 == ct->gctype.getWeakLinkOffset) {
+ /* Heap is probably corrupted */
+ continue;
+ }
+
+ /* Get offset into the object of where the weak pointer is */
+ offset = (*ct->gctype.getWeakLinkOffset)(p + 1);
+
+ /* Check the weak pointer */
+ weakPtrAddress = (PRWord**)((char*)(p + 1) + offset);
+ p = *weakPtrAddress;
+ if (p != 0) {
+ h = p[-1]; /* Grab header word for pointed to object */
+ if (h & MARK_BIT) {
+ /* Object can't be dead */
+ continue;
+ }
+ /* Break weak link to an object that is about to be swept */
+ *weakPtrAddress = 0;
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+/*
+** Perform a complete garbage collection
+*/
+
+extern GCLockHook *_pr_GCLockHook;
+
+static void dogc(void)
+{
+ RootFinder *rf;
+ GCLockHook* lhook;
+
+ GCScanQ scanQ;
+ GCSeg *sp, *esp;
+ PRInt64 start, end, diff;
+
+#if defined(GCMETER) || defined(GCTIMINGHOOK)
+ start = PR_Now();
+#endif
+
+ /*
+ ** Stop all of the other threads. This also promises to capture the
+ ** register state of each and every thread
+ */
+
+ /*
+ ** Get all the locks that will be need during GC after SuspendAll. We
+ ** cannot make any locking/library calls after SuspendAll.
+ */
+ if (_pr_GCLockHook) {
+ for (lhook = _pr_GCLockHook->next; lhook != _pr_GCLockHook;
+ lhook = lhook->next) {
+ (*lhook->func)(PR_GCBEGIN, lhook->arg);
+ }
+ }
+
+ PR_SuspendAll();
+
+#ifdef GCMETER
+ /* Reset meter info */
+ if (_pr_gcMeter & _GC_METER_STATS) {
+ fprintf(stderr,
+ "[GCSTATS: busy:%ld skipped:%ld, alloced:%ld+wasted:%ld+free:%ld = total:%ld]\n",
+ (long) _pr_gcData.busyMemory,
+ (long) meter.skippedFreeChunks,
+ (long) meter.allocBytes,
+ (long) meter.wastedBytes,
+ (long) _pr_gcData.freeMemory,
+ (long) _pr_gcData.allocMemory);
+ }
+ memset(&meter, 0, sizeof(meter));
+#endif
+
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("begin mark phase; busy=%d free=%d total=%d",
+ _pr_gcData.busyMemory, _pr_gcData.freeMemory,
+ _pr_gcData.allocMemory));
+
+ if (_pr_beginGCHook) {
+ (*_pr_beginGCHook)(_pr_beginGCHookArg);
+ }
+
+ /*
+ ** Initialize scanQ to all zero's so that root finder doesn't walk
+ ** over it...
+ */
+ memset(&scanQ, 0, sizeof(scanQ));
+ pScanQ = &scanQ;
+
+ /******************************************/
+ /* MARK PHASE */
+
+ EmptyFreelists();
+
+ /* Find root's */
+ PR_LOG(_pr_msgc_lm, PR_LOG_WARNING,
+ ("begin mark phase; busy=%d free=%d total=%d",
+ _pr_gcData.busyMemory, _pr_gcData.freeMemory,
+ _pr_gcData.allocMemory));
+ METER(_pr_scanDepth = 0);
+ rf = _pr_rootFinders;
+ while (rf) {
+ _GCTRACE(GC_ROOTS, ("finding roots in %s", rf->name));
+ (*rf->func)(rf->arg);
+ rf = rf->next;
+ }
+ _GCTRACE(GC_ROOTS, ("done finding roots"));
+
+ /* Scan remaining object's that need scanning */
+ ScanScanQ(&scanQ);
+ PR_ASSERT(pScanQ == &scanQ);
+ PR_ASSERT(scanQ.queued == 0);
+ METER({
+ if (_pr_scanDepth > _pr_maxScanDepth) {
+ _pr_maxScanDepth = _pr_scanDepth;
+ }
+ });
+
+ /******************************************/
+ /* FINALIZATION PHASE */
+
+ METER(_pr_scanDepth = 0);
+ PrepareFinalize();
+
+ /* Scan any resurrected objects found during finalization */
+ ScanScanQ(&scanQ);
+ PR_ASSERT(pScanQ == &scanQ);
+ PR_ASSERT(scanQ.queued == 0);
+ METER({
+ if (_pr_scanDepth > _pr_maxScanDepth) {
+ _pr_maxScanDepth = _pr_scanDepth;
+ }
+ });
+ pScanQ = 0;
+
+ /******************************************/
+ /* SWEEP PHASE */
+
+ /*
+ ** Sweep each segment clean. While we are at it, figure out which
+ ** segment has the most free space and make that the current segment.
+ */
+ CheckWeakLinks();
+ _GCTRACE(GC_SWEEP, ("begin sweep phase"));
+ _pr_gcData.freeMemory = 0;
+ _pr_gcData.busyMemory = 0;
+ sp = segs;
+ esp = sp + nsegs;
+ while (sp < esp) {
+ if (SweepSegment(sp)) {
+ /*
+ ** Segment is now free and has been replaced with a different
+ ** segment object.
+ */
+ esp--;
+ continue;
+ }
+ sp++;
+ }
+
+#if defined(GCMETER) || defined(GCTIMINGHOOK)
+ end = PR_Now();
+#endif
+#ifdef GCMETER
+ LL_SUB(diff, end, start);
+ PR_LOG(GC, PR_LOG_ALWAYS,
+ ("done; busy=%d free=%d chunks=%d total=%d time=%lldms",
+ _pr_gcData.busyMemory, _pr_gcData.freeMemory,
+ meter.numFreeChunks, _pr_gcData.allocMemory, diff));
+ if (_pr_gcMeter & _GC_METER_FREE_LIST) {
+ PRIntn bin;
+ fprintf(stderr, "Freelist bins:\n");
+ for (bin = 0; bin < NUM_BINS; bin++) {
+ GCFreeChunk *cp = bins[bin];
+ while (cp != NULL) {
+ fprintf(stderr, "%3d: %p %8ld\n",
+ bin, cp, (long) cp->chunkSize);
+ cp = cp->next;
+ }
+ }
+ }
+#endif
+
+ if (_pr_endGCHook) {
+ (*_pr_endGCHook)(_pr_endGCHookArg);
+ }
+
+ /* clear the running total of the bytes allocated via BigAlloc() */
+ bigAllocBytes = 0;
+
+ /* And resume multi-threading */
+ PR_ResumeAll();
+
+ if (_pr_GCLockHook) {
+ for (lhook = _pr_GCLockHook->prev; lhook != _pr_GCLockHook;
+ lhook = lhook->prev) {
+ (*lhook->func)(PR_GCEND, lhook->arg);
+ }
+ }
+
+ /* Kick finalizer */
+ NotifyFinalizer();
+#ifdef GCTIMINGHOOK
+ if (_pr_gcData.gcTimingHook) {
+ PRInt32 time;
+ LL_SUB(diff, end, start);
+ LL_L2I(time, diff);
+ _pr_gcData.gcTimingHook(time);
+ }
+#endif
+}
+
+PR_IMPLEMENT(void) PR_GC(void)
+{
+ LOCK_GC();
+ dogc();
+ UNLOCK_GC();
+
+ EmptyWeakFreeList();
+}
+
+/*******************************************************************************
+ * Heap Walker
+ ******************************************************************************/
+
+/*
+** This is yet another disgusting copy of the body of ProcessRootPointer
+** (the other being ProcessRootBlock), but we're not leveraging a single
+** function in their cases in interest of performance (avoiding the function
+** call).
+*/
+static PRInt32 PR_CALLBACK
+pr_ConservativeWalkPointer(void* ptr, PRWalkFun walkRootPointer, void* data)
+{
+ PRWord *p0, *p, *segBase;
+ GCSeg* sp;
+
+ p0 = (PRWord*) ptr;
+
+ /*
+ ** XXX:
+ ** Until Win16 maintains lowSeg and highSeg correctly,
+ ** (ie. lowSeg=MIN(all segs) and highSeg = MAX(all segs))
+ ** Allways scan through the segment list
+ */
+#if !defined(WIN16)
+ if (p0 < _pr_gcData.lowSeg) return 0; /* below gc heap */
+ if (p0 >= _pr_gcData.highSeg) return 0; /* above gc heap */
+#endif
+
+ /* NOTE: inline expansion of InHeap */
+ /* Find segment */
+ sp = lastInHeap;
+ if (!sp || !IN_SEGMENT(sp,p0)) {
+ GCSeg *esp;
+ sp = segs;
+ esp = segs + nsegs;
+ for (; sp < esp; sp++) {
+ if (IN_SEGMENT(sp, p0)) {
+ lastInHeap = sp;
+ goto find_object;
+ }
+ }
+ return 0;
+ }
+
+ find_object:
+ /* NOTE: Inline expansion of FindObject */
+ /* Align p to it's proper boundary before we start fiddling with it */
+ p = (PRWord*) ((PRWord)p0 & ~(BYTES_PER_WORD-1L));
+ segBase = (PRWord *) sp->base;
+ do {
+ if (IS_HBIT(sp, p)) {
+ goto winner;
+ }
+ p--;
+ } while (p >= segBase);
+
+ /*
+ ** We have a pointer into the heap, but it has no header
+ ** bit. This means that somehow the very first object in the heap
+ ** doesn't have a header. This is impossible so when debugging
+ ** lets abort.
+ */
+#ifdef DEBUG
+ PR_Abort();
+#endif
+ return 0;
+
+ winner:
+ return walkRootPointer(p, data);
+}
+
+static PRInt32 PR_CALLBACK
+pr_ConservativeWalkBlock(void **base, PRInt32 count,
+ PRWalkFun walkRootPointer, void* data)
+{
+ PRWord *p0;
+ while (--count >= 0) {
+ PRInt32 status;
+ p0 = (PRWord*) *base++;
+ status = pr_ConservativeWalkPointer(p0, walkRootPointer, data);
+ if (status) return status;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+typedef void (*WalkObject_t)(FILE *out, GCType* tp, PRWord *obj,
+ size_t bytes, PRBool detailed);
+typedef void (*WalkUnknown_t)(FILE *out, GCType* tp, PRWord tix, PRWord *p,
+ size_t bytes, PRBool detailed);
+typedef void (*WalkFree_t)(FILE *out, PRWord *p, size_t size, PRBool detailed);
+typedef void (*WalkSegment_t)(FILE *out, GCSeg* sp, PRBool detailed);
+
+static void
+pr_WalkSegment(FILE* out, GCSeg* sp, PRBool detailed,
+ char* enterMsg, char* exitMsg,
+ WalkObject_t walkObject, WalkUnknown_t walkUnknown, WalkFree_t walkFree)
+{
+ PRWord *p, *limit;
+
+ p = (PRWord *) sp->base;
+ limit = (PRWord *) sp->limit;
+ if (enterMsg)
+ fprintf(out, enterMsg, p);
+ while (p < limit)
+ {
+ if (IS_HBIT(sp, p)) /* Is this an object header? */
+ {
+ PRWord h = p[0];
+ PRWord tix = GET_TYPEIX(h);
+ size_t bytes = OBJ_BYTES(h);
+ PRWord* np = (PRWord*) ((char*)p + bytes);
+
+ GCType* tp = &_pr_collectorTypes[tix].gctype;
+ if ((0 != tp) && walkObject)
+ walkObject(out, tp, p, bytes, detailed);
+ else if (walkUnknown)
+ walkUnknown(out, tp, tix, p, bytes, detailed);
+ p = np;
+ }
+ else
+ {
+ /* Must be a freelist item */
+ size_t size = ((GCFreeChunk*)p)->chunkSize;
+ if (walkFree)
+ walkFree(out, p, size, detailed);
+ p = (PRWord*)((char*)p + size);
+ }
+ }
+ if (p != limit)
+ fprintf(out, "SEGMENT OVERRUN (end should be at 0x%p)\n", limit);
+ if (exitMsg)
+ fprintf(out, exitMsg, p);
+}
+
+static void
+pr_WalkSegments(FILE *out, WalkSegment_t walkSegment, PRBool detailed)
+{
+ GCSeg *sp = segs;
+ GCSeg *esp;
+
+ LOCK_GC();
+ esp = sp + nsegs;
+ while (sp < esp)
+ {
+ walkSegment(out, sp, detailed);
+ sp++;
+ }
+ fprintf(out, "End of heap\n");
+ UNLOCK_GC();
+}
+
+/*******************************************************************************
+ * Heap Dumper
+ ******************************************************************************/
+
+PR_IMPLEMENT(void)
+PR_DumpIndent(FILE *out, int indent)
+{
+ while (--indent >= 0)
+ fprintf(out, " ");
+}
+
+static void
+PR_DumpHexWords(FILE *out, PRWord *p, int nWords,
+ int indent, int nWordsPerLine)
+{
+ while (nWords > 0)
+ {
+ int i;
+
+ PR_DumpIndent(out, indent);
+ i = nWordsPerLine;
+ if (i > nWords)
+ i = nWords;
+ nWords -= i;
+ while (i--)
+ {
+ fprintf(out, "0x%.8lX", (long) *p++);
+ if (i)
+ fputc(' ', out);
+ }
+ fputc('\n', out);
+ }
+}
+
+static void PR_CALLBACK
+pr_DumpObject(FILE *out, GCType* tp, PRWord *p,
+ size_t bytes, PRBool detailed)
+{
+ char kindChar = tp->kindChar;
+ fprintf(out, "0x%p: 0x%.6lX %c ",
+ p, (long) bytes, kindChar ? kindChar : '?');
+ if (tp->dump)
+ (*tp->dump)(out, (void*) (p + 1), detailed, 0);
+ if (detailed)
+ PR_DumpHexWords(out, p, bytes>>2, 22, 4);
+}
+
+static void PR_CALLBACK
+pr_DumpUnknown(FILE *out, GCType* tp, PRWord tix, PRWord *p,
+ size_t bytes, PRBool detailed)
+{
+ char kindChar = tp->kindChar;
+ fprintf(out, "0x%p: 0x%.6lX %c ",
+ p, (long) bytes, kindChar ? kindChar : '?');
+ fprintf(out, "UNKNOWN KIND %ld\n", (long) tix);
+ if (detailed)
+ PR_DumpHexWords(out, p, bytes>>2, 22, 4);
+}
+
+static void PR_CALLBACK
+pr_DumpFree(FILE *out, PRWord *p, size_t size, PRBool detailed)
+{
+#if defined(XP_MAC) && XP_MAC
+# pragma unused( detailed )
+#endif
+
+ fprintf(out, "0x%p: 0x%.6lX - FREE\n", p, (long) size);
+}
+
+static void PR_CALLBACK
+pr_DumpSegment(FILE* out, GCSeg* sp, PRBool detailed)
+{
+ pr_WalkSegment(out, sp, detailed,
+ "\n Address: Length\n0x%p: Beginning of segment\n",
+ "0x%p: End of segment\n\n",
+ pr_DumpObject, pr_DumpUnknown, pr_DumpFree);
+}
+
+static void pr_DumpRoots(FILE *out);
+
+/*
+** Dump out the GC heap.
+*/
+PR_IMPLEMENT(void)
+PR_DumpGCHeap(FILE *out, PRBool detailed)
+{
+ fprintf(out, "\n"
+ "The kinds are:\n"
+ " U unscanned block\n"
+ " W weak link block\n"
+ " S scanned block\n"
+ " F scanned and final block\n"
+ " C class record\n"
+ " X context record\n"
+ " - free list item\n"
+ " ? other\n");
+ LOCK_GC();
+ pr_WalkSegments(out, pr_DumpSegment, detailed);
+ if (detailed)
+ pr_DumpRoots(out);
+ UNLOCK_GC();
+}
+
+PR_IMPLEMENT(void)
+PR_DumpMemory(PRBool detailed)
+{
+ PR_DumpToFile("memory.out", "Dumping memory", PR_DumpGCHeap, detailed);
+}
+
+/******************************************************************************/
+
+static PRInt32 PR_CALLBACK
+pr_DumpRootPointer(PRWord* p, void* data)
+{
+#ifdef XP_MAC
+#pragma unused(data)
+#endif
+ PRWord h = p[0];
+ PRWord tix = GET_TYPEIX(h);
+ size_t bytes = OBJ_BYTES(h);
+
+ GCType* tp = &_pr_collectorTypes[tix].gctype;
+ if (0 != tp)
+ pr_DumpObject(_pr_gcData.dumpOutput, tp, p, bytes, PR_FALSE);
+ else
+ pr_DumpUnknown(_pr_gcData.dumpOutput, tp, tix, p, bytes, PR_FALSE);
+ return 0;
+}
+
+static void PR_CALLBACK
+pr_ConservativeDumpRootPointer(void* ptr)
+{
+ (void)pr_ConservativeWalkPointer(ptr, (PRWalkFun) pr_DumpRootPointer, NULL);
+}
+
+static void PR_CALLBACK
+pr_ConservativeDumpRootBlock(void **base, PRInt32 count)
+{
+ (void)pr_ConservativeWalkBlock(base, count, (PRWalkFun) pr_DumpRootPointer, NULL);
+}
+
+extern int
+DumpThreadRoots(PRThread *t, int i, void *notused);
+
+static void
+pr_DumpRoots(FILE *out)
+{
+ RootFinder *rf;
+ void (*liveBlock)(void **base, PRInt32 count);
+ void (*livePointer)(void *ptr);
+ void (*processRootBlock)(void **base, PRInt32 count);
+ void (*processRootPointer)(void *ptr);
+
+ LOCK_GC();
+
+ liveBlock = _pr_gcData.liveBlock;
+ livePointer = _pr_gcData.livePointer;
+ processRootBlock = _pr_gcData.processRootBlock;
+ processRootPointer = _pr_gcData.processRootPointer;
+
+ _pr_gcData.liveBlock = pr_ConservativeDumpRootBlock;
+ _pr_gcData.livePointer = pr_ConservativeDumpRootPointer;
+ _pr_gcData.processRootBlock = pr_ConservativeDumpRootBlock;
+ _pr_gcData.processRootPointer = pr_ConservativeDumpRootPointer;
+ _pr_gcData.dumpOutput = out;
+
+ rf = _pr_rootFinders;
+ while (rf) {
+ fprintf(out, "\n===== Roots for %s\n", rf->name);
+ (*rf->func)(rf->arg);
+ rf = rf->next;
+ }
+
+ _pr_gcData.liveBlock = liveBlock;
+ _pr_gcData.livePointer = livePointer;
+ _pr_gcData.processRootBlock = processRootBlock;
+ _pr_gcData.processRootPointer = processRootPointer;
+ _pr_gcData.dumpOutput = NULL;
+
+ UNLOCK_GC();
+}
+
+/*******************************************************************************
+ * Heap Summary Dumper
+ ******************************************************************************/
+
+PRSummaryPrinter summaryPrinter = NULL;
+void* summaryPrinterClosure = NULL;
+
+PR_IMPLEMENT(void)
+PR_RegisterSummaryPrinter(PRSummaryPrinter fun, void* closure)
+{
+ summaryPrinter = fun;
+ summaryPrinterClosure = closure;
+}
+
+static void PR_CALLBACK
+pr_SummarizeObject(FILE *out, GCType* tp, PRWord *p,
+ size_t bytes, PRBool detailed)
+{
+#if defined(XP_MAC) && XP_MAC
+# pragma unused( out, detailed )
+#endif
+
+ if (tp->summarize)
+ (*tp->summarize)((void GCPTR*)(p + 1), bytes);
+}
+
+static void PR_CALLBACK
+pr_DumpSummary(FILE* out, GCSeg* sp, PRBool detailed)
+{
+ pr_WalkSegment(out, sp, detailed, NULL, NULL,
+ pr_SummarizeObject, NULL, NULL);
+}
+
+PR_IMPLEMENT(void)
+PR_DumpGCSummary(FILE *out, PRBool detailed)
+{
+ if (summaryPrinter) {
+ pr_WalkSegments(out, pr_DumpSummary, detailed);
+ summaryPrinter(out, summaryPrinterClosure);
+ }
+#if 0
+ fprintf(out, "\nFinalizable objects:\n");
+ {
+ PRCList *qp;
+ qp = _pr_pendingFinalQueue.next;
+ while (qp != &_pr_pendingFinalQueue) {
+ GCFinal* fp = FinalPtr(qp);
+ PRWord h = fp->object[0]; /* Grab header word */
+ PRWord tix = GET_TYPEIX(h);
+ GCType* tp = _pr_gcTypes[tix];
+ size_t bytes = OBJ_BYTES(h);
+ pr_DumpObject(out, tp, fp->object, bytes, PR_FALSE);
+ qp = qp->next;
+ }
+ }
+#endif
+}
+
+PR_IMPLEMENT(void)
+PR_DumpMemorySummary(void)
+{
+ PR_DumpToFile("memory.out", "Memory Summary", PR_DumpGCSummary, PR_FALSE);
+}
+
+/*******************************************************************************
+ * End Of Heap Walker
+ ******************************************************************************/
+
+#ifdef GC_TRACEROOTS
+
+PRInt32 pr_traceGen = 0;
+
+static PRBool
+pr_IsMarked(PRWord* p)
+{
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+ PR_ASSERT(end->check == PR_BLOCK_END);
+ return end->traceGeneration == pr_traceGen;
+}
+
+static void
+pr_Mark(PRWord* p)
+{
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+ PR_ASSERT(end->check == PR_BLOCK_END);
+ end->traceGeneration = pr_traceGen;
+}
+
+PRWord* pr_traceObj; /* set this in the debugger, then execute PR_TraceRoot() */
+
+static PRInt32 PR_CALLBACK
+pr_TraceRootObject(void* obj, void* data);
+
+static PRInt32 PR_CALLBACK
+pr_TraceRootPointer(PRWord *p, void* data)
+{
+ PRInt32 printTrace = 0;
+ PRWord h = p[0];
+ PRWord tix = GET_TYPEIX(h);
+ GCType* tp = &_pr_collectorTypes[tix].gctype;
+ FILE* out = _pr_gcData.dumpOutput;
+
+ PR_ASSERT(tp);
+ if (pr_IsMarked(p))
+ return printTrace;
+
+ pr_Mark(p);
+ if (p == pr_traceObj) {
+ fprintf(out, "\n### Found path to:\n");
+ printTrace = 1;
+ }
+ else {
+ if (PR_StackSpaceLeft(PR_CurrentThread()) < 512) {
+ fprintf(out, "\n### Path too deep (giving up):\n");
+ printTrace = 1;
+ }
+ else if (tp->walk) {
+ printTrace = tp->walk((void*)(p + 1), pr_TraceRootObject, data);
+ }
+ /* else there's no way to walk this object, so we
+ haven't found what we're looking for */
+ }
+
+ if (printTrace == 1) {
+ PR_ASSERT(tp->dump);
+ fprintf(out, "0x%p: ", p);
+ tp->dump(out, (void*)(p + 1), PR_FALSE, 1);
+ }
+ return printTrace;
+}
+
+static PRInt32 PR_CALLBACK
+pr_TraceRootObject(void* obj, void* data)
+{
+ /* This version of pr_TraceRootPointer takes object
+ pointers, instead of gc header pointers. */
+ return pr_TraceRootPointer((PRWord*)obj - 1, data);
+}
+
+static void PR_CALLBACK
+pr_ConservativeTraceRootPointer(PRWord *p)
+{
+ PRInt32 status;
+ ++pr_traceGen;
+ status = pr_ConservativeWalkPointer(p, pr_TraceRootPointer, NULL);
+ if (status) {
+ FILE* out = _pr_gcData.dumpOutput;
+ fprintf(out, "### from root at 0x%p\n\n", p);
+ }
+}
+
+static void PR_CALLBACK
+pr_ConservativeTraceRootBlock(void **base, PRInt32 count)
+{
+ PRInt32 status;
+ ++pr_traceGen;
+ status = pr_ConservativeWalkBlock(base, count, pr_TraceRootPointer, NULL);
+ if (status) {
+ FILE* out = _pr_gcData.dumpOutput;
+ fprintf(out, "### from root in range 0x%p + 0x%lx\n\n",
+ base, (long) count);
+ }
+}
+
+static void
+PR_TraceRoot1(FILE* out, PRBool detailed)
+{
+ RootFinder *rf;
+ void (*liveBlock)(void **base, PRInt32 count);
+ void (*livePointer)(void *ptr);
+ void (*processRootBlock)(void **base, PRInt32 count);
+ void (*processRootPointer)(void *ptr);
+
+ LOCK_GC();
+
+ liveBlock = _pr_gcData.liveBlock;
+ livePointer = _pr_gcData.livePointer;
+ processRootBlock = _pr_gcData.processRootBlock;
+ processRootPointer = _pr_gcData.processRootPointer;
+
+ _pr_gcData.liveBlock = pr_ConservativeTraceRootBlock;
+ _pr_gcData.livePointer = pr_ConservativeTraceRootPointer;
+ _pr_gcData.processRootBlock = pr_ConservativeTraceRootBlock;
+ _pr_gcData.processRootPointer = pr_ConservativeTraceRootPointer;
+ _pr_gcData.dumpOutput = out;
+
+ fprintf(out, "### Looking for paths to 0x%p\n\n", pr_traceObj);
+
+ rf = _pr_rootFinders;
+ while (rf) {
+ fprintf(out, "\n===== Roots for %s\n", rf->name);
+ (*rf->func)(rf->arg);
+ rf = rf->next;
+ }
+
+ _pr_gcData.liveBlock = liveBlock;
+ _pr_gcData.livePointer = livePointer;
+ _pr_gcData.processRootBlock = processRootBlock;
+ _pr_gcData.processRootPointer = processRootPointer;
+ _pr_gcData.dumpOutput = NULL;
+
+ UNLOCK_GC();
+}
+
+PR_PUBLIC_API(void)
+PR_TraceRoot()
+{
+ /*
+ ** How this works:
+ ** Once you find the object you want to trace the roots of, set the
+ ** global variable pr_traceObj to point to it (the header, not the
+ ** java handle), and then call this routine (on Windows, you can set
+ ** a breakpoint at the end of a function that returns void (e.g. dogc)
+ ** and then do a "set next statement" to point to this routine and go.
+ ** This will dump a list of the paths from the roots to the object in
+ ** question to your memory.out file.
+ */
+ PR_DumpToFile("memory.out", "Tracing Roots", PR_TraceRoot1, PR_FALSE);
+}
+
+#endif /* GC_TRACEROOTS */
+
+/******************************************************************************/
+
+#if defined(DEBUG) && defined(WIN32)
+static void DumpApplicationHeap(FILE *out, HANDLE heap)
+{
+ PROCESS_HEAP_ENTRY entry;
+ DWORD err;
+
+ if (!HeapLock(heap))
+ OutputDebugString("Can't lock the heap.\n");
+ entry.lpData = 0;
+ fprintf(out, " address: size ovhd region\n");
+ while (HeapWalk(heap, &entry))
+ {
+ WORD flags = entry.wFlags;
+
+ fprintf(out, "0x%.8X: 0x%.8X 0x%.2X 0x%.2X ", entry.lpData, entry.cbData,
+ entry.cbOverhead, entry.iRegionIndex);
+ if (flags & PROCESS_HEAP_REGION)
+ fprintf(out, "REGION committedSize=0x%.8X uncommittedSize=0x%.8X firstBlock=0x%.8X lastBlock=0x%.8X",
+ entry.Region.dwCommittedSize, entry.Region.dwUnCommittedSize,
+ entry.Region.lpFirstBlock, entry.Region.lpLastBlock);
+ else if (flags & PROCESS_HEAP_UNCOMMITTED_RANGE)
+ fprintf(out, "UNCOMMITTED");
+ else if (flags & PROCESS_HEAP_ENTRY_BUSY)
+ {
+ if (flags & PROCESS_HEAP_ENTRY_DDESHARE)
+ fprintf(out, "DDEShare ");
+ if (flags & PROCESS_HEAP_ENTRY_MOVEABLE)
+ fprintf(out, "Moveable Block handle=0x%.8X", entry.Block.hMem);
+ else
+ fprintf(out, "Block");
+ }
+ fprintf(out, "\n");
+ }
+ if ((err = GetLastError()) != ERROR_NO_MORE_ITEMS)
+ fprintf(out, "ERROR %d iterating through the heap\n", err);
+ if (!HeapUnlock(heap))
+ OutputDebugString("Can't unlock the heap.\n");
+}
+#endif
+
+#if defined(DEBUG) && defined(WIN32)
+static void DumpApplicationHeaps(FILE *out)
+{
+ HANDLE mainHeap;
+ HANDLE heaps[100];
+ DWORD nHeaps;
+ PRInt32 i;
+
+ mainHeap = GetProcessHeap();
+ nHeaps = GetProcessHeaps(100, heaps);
+ if (nHeaps > 100)
+ nHeaps = 0;
+ fprintf(out, "%ld heaps:\n", (long) nHeaps);
+ for (i = 0; i<nHeaps; i++)
+ {
+ HANDLE heap = heaps[i];
+
+ fprintf(out, "Heap at 0x%.8lX", (long) heap);
+ if (heap == mainHeap)
+ fprintf(out, " (main)");
+ fprintf(out, ":\n");
+ DumpApplicationHeap(out, heap);
+ fprintf(out, "\n");
+ }
+ fprintf(out, "End of heap dump\n\n");
+}
+#endif
+
+#if defined(DEBUG) && defined(WIN32)
+PR_IMPLEMENT(void) PR_DumpApplicationHeaps(void)
+{
+ FILE *out;
+
+ OutputDebugString("Dumping heaps...");
+ out = fopen("heaps.out", "a");
+ if (!out)
+ OutputDebugString("Can't open \"heaps.out\"\n");
+ else
+ {
+ struct tm *newtime;
+ time_t aclock;
+
+ time(&aclock);
+ newtime = localtime(&aclock);
+ fprintf(out, "Heap dump on %s\n", asctime(newtime)); /* Print current time */
+ DumpApplicationHeaps(out);
+ fprintf(out, "\n\n");
+ fclose(out);
+ }
+ OutputDebugString(" done\n");
+}
+#else
+
+PR_IMPLEMENT(void) PR_DumpApplicationHeaps(void)
+{
+ fprintf(stderr, "Native heap dumping is currently implemented only for Windows32.\n");
+}
+#endif
+
+/************************************************************************/
+
+/*
+** Scan the freelist bins looking for a big enough chunk of memory to
+** hold "bytes" worth of allocation. "bytes" already has the
+** per-allocation header added to it. Return a pointer to the object with
+** its per-allocation header already prepared.
+*/
+static PRWord *BinAlloc(int cbix, PRInt32 bytes, int dub)
+{
+ GCFreeChunk **cpp, *cp, *cpNext;
+ GCSeg *sp;
+ PRInt32 chunkSize, remainder;
+ PRWord *p, *np;
+ PRInt32 bin, newbin;
+
+ /* Compute bin that allocation belongs in */
+ InlineBinNumber(bin,bytes)
+ if (bin < minBin) {
+ bin = minBin; /* Start at first filled bin */
+ }
+
+ /* Search in the bin, and larger bins, for a big enough piece */
+ for (; bin <= NUM_BINS-1; bin++) {
+ cpp = &bins[bin];
+ while ((cp = *cpp) != 0) {
+ chunkSize = cp->chunkSize;
+ if (chunkSize < bytes) {
+ /* Too small; skip it */
+ METER(meter.skippedFreeChunks++);
+ cpp = &cp->next;
+ continue;
+ }
+
+ /* We have found a hunk of memory large enough to use */
+ p = (PRWord*) cp;
+ sp = cp->segment;
+ cpNext = cp->next;
+#ifndef IS_64
+ if (dub && (((PRWord)p & (PR_BYTES_PER_DWORD-1)) == 0)) {
+ /*
+ * We are double aligning the memory and the current free
+ * chunk is aligned on an even boundary. Because header
+ * words are one word long we need to discard the first
+ * word of memory.
+ */
+ p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, 1);
+ SET_HBIT(sp, p);
+ p++;
+ chunkSize -= PR_BYTES_PER_WORD;
+ bytes -= PR_BYTES_PER_WORD;
+ PR_ASSERT(((PRWord)p & (PR_BYTES_PER_DWORD-1)) != 0);
+ _pr_gcData.freeMemory -= PR_BYTES_PER_WORD;
+ _pr_gcData.busyMemory += PR_BYTES_PER_WORD;
+ }
+#endif
+ np = (PRWord*) ((char*) p + bytes);
+ remainder = chunkSize - bytes;
+ if (remainder >= MIN_FREE_CHUNK_BYTES) {
+ /* The left over memory is large enough to be freed. */
+ cp = (GCFreeChunk*) np;
+ cp->segment = sp;
+ cp->chunkSize = remainder;
+ InlineBinNumber(newbin, remainder)
+ if (newbin != bin) {
+ *cpp = (GCFreeChunk*) cpNext; /* remove */
+ cp->next = bins[newbin]; /* insert */
+ bins[newbin] = cp;
+ if (newbin < minBin) minBin = newbin;
+ if (newbin > maxBin) maxBin = newbin;
+ } else {
+ /* Leave it on the same list */
+ cp->next = cpNext;
+ *cpp = (GCFreeChunk*) np;
+ }
+ } else {
+ /*
+ * The left over memory is too small to be released. Just
+ * leave it attached to the chunk of memory being
+ * returned.
+ */
+ *cpp = cpNext;
+ bytes = chunkSize;
+ }
+ p[0] = MAKE_HEADER(cbix, (bytes >> PR_BYTES_PER_WORD_LOG2));
+ SET_HBIT(sp, p);
+ _pr_gcData.freeMemory -= bytes;
+ _pr_gcData.busyMemory += bytes;
+ return p;
+ }
+ }
+ return 0;
+}
+
+/*
+** Allocate a piece of memory that is "big" in it's own segment. Make
+** the object consume the entire segment to avoid fragmentation. When
+** the object is no longer referenced, the segment is freed.
+*/
+static PRWord *BigAlloc(int cbix, PRInt32 bytes, int dub)
+{
+ GCSeg *sp;
+ PRWord *p, h;
+ PRInt32 chunkSize;
+
+ /*
+ ** If the number of bytes allocated via BigAlloc() since the last GC
+ ** exceeds BIG_ALLOC_GC_SIZE then do a GC Now...
+ */
+ if (bigAllocBytes >= BIG_ALLOC_GC_SIZE) {
+ dogc();
+ }
+ bigAllocBytes += bytes;
+
+ /* Get a segment to hold this allocation */
+ sp = GrowHeapExactly(bytes);
+
+ if (sp) {
+ p = (PRWord*) sp->base;
+ chunkSize = sp->limit - sp->base;
+
+ /* All memory is double aligned on 64 bit machines... */
+#ifndef IS_64
+ if (dub && (((PRWord)p & (PR_BYTES_PER_DWORD-1)) == 0)) {
+ /*
+ ** Consume the first word of the chunk with a dummy
+ ** unreferenced object.
+ */
+ p[0] = MAKE_HEADER(FREE_MEMORY_TYPEIX, 1);
+ SET_HBIT(sp, p);
+ p++;
+ chunkSize -= PR_BYTES_PER_WORD;
+ _pr_gcData.freeMemory -= PR_BYTES_PER_WORD;
+ _pr_gcData.busyMemory += PR_BYTES_PER_WORD;
+ PR_ASSERT(((PRWord)p & (PR_BYTES_PER_DWORD-1)) != 0);
+ }
+#endif
+
+#if defined(WIN16)
+ /* All memory MUST be aligned on 32bit boundaries */
+ PR_ASSERT( (((PRWord)p) & (PR_BYTES_PER_WORD-1)) == 0 );
+#endif
+
+ /* Consume the *entire* segment with a single allocation */
+ h = MAKE_HEADER(cbix, (chunkSize >> PR_BYTES_PER_WORD_LOG2));
+ p[0] = h;
+ SET_HBIT(sp, p);
+ _pr_gcData.freeMemory -= chunkSize;
+ _pr_gcData.busyMemory += chunkSize;
+ return p;
+ }
+ return 0;
+}
+
+/* we disable gc allocation during low memory conditions */
+static PRBool allocationEnabled = PR_TRUE;
+
+PR_IMPLEMENT(void) PR_EnableAllocation(PRBool yesOrNo)
+{
+ allocationEnabled = yesOrNo;
+}
+
+static void CollectorCleanup(void) {
+ while (collectorCleanupNeeded) {
+ LOCK_GC();
+ collectorCleanupNeeded = 0;
+ UNLOCK_GC();
+ if (freeSegs) {
+ FreeSegments();
+ }
+ if (!WEAK_FREELIST_ISEMPTY()) {
+ EmptyWeakFreeList();
+ }
+ }
+}
+
+/******************************************************************************/
+
+#ifdef GC_CHECK
+static PRInt32 allocationCount;
+
+static void EarthShatteringKaBoom(PRInt32 whichOne) {
+ long* p = 0;
+ *p = 0;
+}
+
+/* Check a segment of heap memory. Verify that the object memory
+ hasn't been overwritten (past the end at least) */
+static void CheckSegment(GCSeg* sp) {
+ PRWord h, tix;
+ PRWord *p, *lastp, *np, *limit;
+
+ lastp = p = (PRWord *) sp->base;
+ limit = (PRWord *) sp->limit;
+ while (p < limit) {
+ if (IS_HBIT(sp, p)) {
+ char *cp, i;
+ GCBlockEnd* end;
+ PRWord bytes, requestedBytes;
+
+ h = p[0];
+ tix = GET_TYPEIX(h);
+ bytes = OBJ_BYTES(h);
+ np = (PRWord *) ((char *)p + bytes);
+ if (tix != FREE_MEMORY_TYPEIX) {
+ PRInt32 test; /* msdev get's fooled without this local */
+ /* A live object is here. The last word in the object will
+ contain the objects requestedSize */
+ end = (GCBlockEnd*)((char*)(p) + bytes - sizeof(GCBlockEnd));
+ test = end->check;
+ if (test != PR_BLOCK_END) {
+ PR_ASSERT(test == PR_BLOCK_END);
+ }
+ requestedBytes = end->requestedBytes;
+ if (requestedBytes >= bytes) EarthShatteringKaBoom(0);
+ cp = (char*)(p + 1) + requestedBytes;
+ i = (char) 0xff;
+ while (cp < (char*)end) {
+ if (*cp != i) EarthShatteringKaBoom(1);
+ cp++;
+ i--;
+ }
+ }
+ lastp = p;
+ p = np;
+ } else {
+ /* Must be a freelist item */
+ GCFreeChunk *cp = (GCFreeChunk*) p;
+ if ((PRInt32)cp->chunkSize < (PRInt32)sizeof(GCFreeChunk)) {
+ EarthShatteringKaBoom(3);
+ }
+ lastp = p;
+ p = (PRWord*) ((char*)p + cp->chunkSize);
+ }
+ }
+}
+
+static void CheckHeap(void) {
+ GCSeg *sp = segs;
+ GCSeg *esp = sp + nsegs;
+ while (sp < esp) {
+ CheckSegment(sp);
+ sp++;
+ }
+}
+
+#endif /* GC_CHECK */
+
+/******************************************************************************/
+
+#ifdef DEBUG
+long gc_thrash = -1L;
+#endif
+
+/*
+** Allocate memory from the GC Heap. Performs garbage collections if
+** memory gets tight and grows the heap as needed. May return NULL if
+** memory cannot be found.
+*/
+PR_IMPLEMENT(PRWord GCPTR *)PR_AllocMemory(
+ PRWord requestedBytes, PRInt32 tix, PRWord flags)
+{
+ PRWord *p;
+ CollectorType *ct;
+ PRInt32 bytes;
+ GCFinal *final = 0;
+ GCWeak *weak = 0;
+ int dub = flags & PR_ALLOC_DOUBLE;
+ PRInt32 objBytes;
+#ifdef GC_STATS
+ PRInt64 allocTime, ldelta;
+#endif
+
+ if (!allocationEnabled) return NULL;
+
+ PR_ASSERT(requestedBytes >= 0);
+ PR_ASSERT(_pr_collectorTypes[tix].flags != 0);
+
+#ifdef DEBUG
+ if (_pr_do_a_dump) {
+ /*
+ ** Collect, pause for a second (lets finalizer run), and then GC
+ ** again.
+ */
+ PR_GC();
+ PR_Sleep(PR_MicrosecondsToInterval(1000000L));
+ PR_GC();
+ PR_DumpGCHeap(_pr_dump_file, PR_TRUE);
+ _pr_do_a_dump = 0;
+ }
+#endif
+
+#ifdef GC_STATS
+ allocTime = PR_Now();
+#endif
+ bytes = (PRInt32) requestedBytes;
+
+ /*
+ ** Align bytes to a multiple of a PRWord, then add in enough space
+ ** to hold the header word.
+ **
+ ** MSVC 1.52 crashed on the ff. code because of the "complex" shifting :-(
+ */
+#if !defined(WIN16)
+ /* Check for possible overflow of bytes before performing add */
+ if ((MAX_INT - PR_BYTES_PER_WORD) < bytes ) return NULL;
+ bytes = (bytes + PR_BYTES_PER_WORD - 1) >> PR_BYTES_PER_WORD_LOG2;
+ bytes <<= PR_BYTES_PER_WORD_LOG2;
+ /* Check for possible overflow of bytes before performing add */
+ if ((MAX_INT - sizeof(PRWord)) < bytes ) return NULL;
+ bytes += sizeof(PRWord);
+#else
+ /*
+ ** For WIN16 the shifts have been broken out into separate statements
+ ** to prevent the compiler from crashing...
+ */
+ {
+ PRWord shiftVal;
+
+ /* Check for possible overflow of bytes before performing add */
+ if ((MAX_INT - PR_BYTES_PER_WORD) < bytes ) return NULL;
+ bytes += PR_BYTES_PER_WORD - 1L;
+ shiftVal = PR_BYTES_PER_WORD_LOG2;
+ bytes >>= shiftVal;
+ bytes <<= shiftVal;
+ /* Check for possible overflow of bytes before performing add */
+ if ((MAX_INT - sizeof(PRWord)) < bytes ) return NULL;
+ bytes += sizeof(PRWord);
+ }
+#endif
+ /*
+ * Add in an extra word of memory for double-aligned memory. Some
+ * percentage of the time this will waste a word of memory (too
+ * bad). Howver, it makes the allocation logic much simpler and
+ * faster.
+ */
+#ifndef IS_64
+ if (dub) {
+ /* Check for possible overflow of bytes before performing add */
+ if ((MAX_INT - PR_BYTES_PER_WORD) < bytes ) return NULL;
+ bytes += PR_BYTES_PER_WORD;
+ }
+#endif
+
+#ifdef GC_CHECK
+ if (_pr_gcData.flags & GC_CHECK) {
+ /* Bloat the allocation a bit so that we can lay down
+ a check pattern that we will validate */
+ /* Check for possible overflow of bytes before performing add */
+ if ((MAX_INT - PR_BYTES_PER_WORD * 3) < bytes ) return NULL;
+ bytes += PR_BYTES_PER_WORD * 3;
+ }
+#endif
+
+#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS)
+ if ((MAX_INT - sizeof(GCBlockEnd)) < bytes ) return NULL;
+ bytes += sizeof(GCBlockEnd);
+#endif
+
+ PR_ASSERT( bytes < MAX_ALLOC_SIZE );
+ /*
+ ** Java can ask for objects bigger than MAX_ALLOC_SIZE,
+ ** but it won't get them.
+ */
+ if (bytes >= MAX_ALLOC_SIZE) return NULL;
+
+#ifdef DEBUG
+ if (gc_thrash == -1L ? (gc_thrash = (long)PR_GetEnv("GC_THRASH")):gc_thrash) PR_GC();
+#endif
+
+ ct = &_pr_collectorTypes[tix];
+ if (ct->flags & (_GC_TYPE_FINAL|_GC_TYPE_WEAK)) {
+ if (0 != ct->gctype.finalize) {
+ /*
+ ** Allocate a GCFinal struct for this object in advance. Don't put
+ ** it on the pending list until we have allocated the object
+ */
+ final = AllocFinalNode();
+ if (!final) {
+ /* XXX THIS IS NOT ACCEPTABLE*/
+ PR_ASSERT(0);
+ return 0;
+ }
+ }
+ if (0 != ct->gctype.getWeakLinkOffset) {
+ /*
+ ** Allocate a GCWeak struct for this object in advance. Don't put
+ ** it on the weak links list until we have allocated the object
+ */
+ weak = AllocWeakNode();
+ if (!weak) {
+ /* XXX THIS IS NOT ACCEPTABLE*/
+ if (0 != final) {
+ FreeFinalNode(final);
+ }
+ PR_ASSERT(0);
+ return 0;
+ }
+ }
+ }
+
+ LOCK_GC();
+#ifdef GC_CHECK
+ if (_pr_gcData.flags & GC_CHECK) CheckHeap();
+ allocationCount++;
+#endif
+
+ /* Check for overflow of maximum size we can handle */
+ if (bytes > MAX_ALLOC) goto lost;
+
+ /* Try default allocation */
+ p = ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) ?
+ BigAlloc(tix, bytes, dub) : BinAlloc(tix, bytes, dub);
+ if (0 == p) {
+#ifdef GC_STATS
+ LL_SUB(ldelta, PR_Now(), allocTime);
+#endif
+ /* Collect some memory */
+ _GCTRACE(GC_ALLOC, ("force GC: want %d", bytes));
+ dogc();
+ PR_ASSERT( GC_IS_LOCKED() );
+
+ /* After a collection we check and see if we should grow the
+ ** heap. We grow the heap when the amount of memory free is less
+ ** than a certain percentage of the heap size. We don't check to
+ ** see if the grow succeeded because our fallback strategy in
+ ** either case is to try one more time to allocate. */
+ if ((_pr_gcData.allocMemory < _pr_gcData.maxMemory)
+ && ((_pr_gcData.freeMemory <
+ ((_pr_gcData.allocMemory * MIN_FREE_THRESHOLD_AFTER_GC) / 100L))
+ || (_pr_gcData.freeMemory < bytes))) {
+ GrowHeap(PR_MAX(bytes, segmentSize));
+ }
+#ifdef GC_STATS
+ LL_ADD(allocTime, PR_Now(), ldelta);
+#endif
+
+ /* Try again */
+ p = ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) ?
+ BigAlloc(tix, bytes, dub) : BinAlloc(tix, bytes, dub);
+ if (0 == p) {
+ /* Well that lost big time. Memory must be pretty well fragmented */
+ if (!GrowHeap(PR_MAX(bytes, segmentSize))) goto lost;
+ p = BinAlloc(tix, bytes, dub);
+ if (0 == p) goto lost;
+ }
+ }
+
+ /* Zero out the portion of the object memory that was used by
+ the GCFreeChunk structure (skip the first word because it
+ was already overwritten by the gc header word) */
+ objBytes = OBJ_BYTES(p[0]);
+ if (objBytes > sizeof(PRWord)) p[1] = 0;
+ if (objBytes > sizeof(PRWord)*2) p[2] = 0;
+
+ if (final) {
+ _GCTRACE(GC_ALLOC, ("alloc 0x%x (%d) final=0x%x",
+ p, bytes, final));
+ final->object = p;
+ PR_APPEND_LINK(&final->links, &_pr_finalizeableObjects);
+ } else {
+ _GCTRACE(GC_ALLOC, ("alloc 0x%x (%d)", p, bytes));
+ }
+ if (weak) {
+ weak->object = p;
+ PR_APPEND_LINK(&weak->links, &_pr_weakLinks);
+ }
+ METER(meter.allocBytes += bytes);
+ METER(meter.wastedBytes += (bytes - requestedBytes));
+ UNLOCK_GC();
+
+ if (collectorCleanupNeeded) {
+ CollectorCleanup();
+ }
+
+#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS)
+ {
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+ end->check = PR_BLOCK_END;
+ }
+#endif
+#ifdef GC_STATS
+ {
+ PRInt64 now = PR_Now();
+ double delta;
+ PRInt32 bin;
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+
+ end->allocTime = allocTime;
+ LL_SUB(ldelta, now, allocTime);
+ LL_L2D(delta, ldelta);
+ InlineBinNumber(bin, requestedBytes);
+ end->bin = bin;
+ gcstats[bin].nallocs++;
+ gcstats[bin].allocTime += delta;
+ gcstats[bin].allocTimeVariance += delta * delta;
+ }
+#endif
+#ifdef GC_CHECK
+ if (_pr_gcData.flags & GC_CHECK) {
+ /* Place a pattern in the memory that was allocated that was not
+ requested. We will check the pattern later. */
+ char* cp = (char*)(p + 1) + requestedBytes;
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+ char i = (char) 0xff;
+ while (cp < (char*)end) {
+ *cp++ = i--;
+ }
+ end->requestedBytes = requestedBytes;
+ CheckHeap();
+ }
+#endif
+ return p + 1;
+
+ lost:
+ /* Out of memory */
+ UNLOCK_GC();
+ if (final) {
+ FreeFinalNode(final);
+ }
+ if (weak) {
+ FreeWeakNode(weak);
+ }
+ if (collectorCleanupNeeded) {
+ CollectorCleanup();
+ }
+ return 0;
+}
+
+/* Shortcut allocator for objects that do not require finalization or
+ are weak objects */
+PR_IMPLEMENT(PRWord GCPTR *)
+PR_AllocSimpleMemory(PRWord requestedBytes, PRInt32 tix)
+{
+ PRWord *p;
+ PRInt32 bytes;
+ PRInt32 objBytes;
+#ifdef GC_STATS
+ PRInt64 allocTime, ldelta;
+#endif
+
+ if (!allocationEnabled) return NULL;
+
+ PR_ASSERT(requestedBytes >= 0);
+ PR_ASSERT(_pr_collectorTypes[tix].flags != 0);
+
+#ifdef DEBUG
+ if (_pr_do_a_dump) {
+ /*
+ ** Collect, pause for a second (lets finalizer run), and then GC
+ ** again.
+ */
+ PR_GC();
+ PR_Sleep(PR_MicrosecondsToInterval(1000000L));
+ PR_GC();
+ PR_DumpGCHeap(_pr_dump_file, PR_TRUE);
+ _pr_do_a_dump = 0;
+ }
+#endif
+
+#ifdef GC_STATS
+ allocTime = PR_NowMS();
+#endif
+ bytes = (PRInt32) requestedBytes;
+
+ /*
+ ** Align bytes to a multiple of a PRWord, then add in enough space
+ ** to hold the header word.
+ **
+ ** MSVC 1.52 crashed on the ff. code because of the "complex" shifting :-(
+ */
+#if !defined(WIN16)
+ bytes = (bytes + PR_BYTES_PER_WORD - 1) >> PR_BYTES_PER_WORD_LOG2;
+ bytes <<= PR_BYTES_PER_WORD_LOG2;
+ bytes += sizeof(PRWord);
+#else
+ /*
+ ** For WIN16 the shifts have been broken out into separate statements
+ ** to prevent the compiler from crashing...
+ */
+ {
+ PRWord shiftVal;
+
+ bytes += PR_BYTES_PER_WORD - 1L;
+ shiftVal = PR_BYTES_PER_WORD_LOG2;
+ bytes >>= shiftVal;
+ bytes <<= shiftVal;
+ bytes += sizeof(PRWord);
+ }
+#endif
+
+ /*
+ * Add in an extra word of memory for double-aligned memory. Some
+ * percentage of the time this will waste a word of memory (too
+ * bad). Howver, it makes the allocation logic much simpler and
+ * faster.
+ */
+#ifndef IS_64
+ bytes += PR_BYTES_PER_WORD;
+#endif
+
+#ifdef GC_CHECK
+ if (_pr_gcData.flags & GC_CHECK) {
+ /* Bloat the allocation a bit so that we can lay down
+ a check pattern that we will validate */
+ bytes += PR_BYTES_PER_WORD * 2;
+ }
+#endif
+
+#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS)
+ bytes += sizeof(GCBlockEnd);
+#endif
+
+#if defined(WIN16)
+ PR_ASSERT( bytes < MAX_ALLOC_SIZE );
+#endif
+ /* Java can ask for objects bigger than 4M, but it won't get them */
+ /*
+ * This check was added because there is a fundamental limit of
+ * the size field maintained by the gc code. Going over the 4M
+ * limit caused some bits to roll over into another bit field,
+ * violating the max segment size and causing a bug.
+ */
+ if (bytes >= MAX_ALLOC_SIZE) {
+ return NULL;
+ }
+#ifdef DEBUG
+ if (gc_thrash == -1L
+ ? (gc_thrash = (long)PR_GetEnv("GC_THRASH"))
+ : gc_thrash) {
+ PR_GC();
+ }
+#endif
+
+ LOCK_GC();
+#ifdef GC_CHECK
+ if (_pr_gcData.flags & GC_CHECK) {
+ CheckHeap();
+ }
+ allocationCount++;
+#endif
+
+ /* Try default allocation */
+ if ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) {
+ p = BigAlloc(tix, bytes, 1);
+ } else {
+ p = BinAlloc(tix, bytes, 1);
+ }
+ if (0 == p) {
+#ifdef GC_STATS
+ LL_SUB(ldelta, PR_Now(), allocTime);
+#endif
+ /* Collect some memory */
+ _GCTRACE(GC_ALLOC, ("force GC: want %d", bytes));
+ dogc();
+ PR_ASSERT( GC_IS_LOCKED() );
+
+ /* After a collection we check and see if we should grow the
+ heap. We grow the heap when the amount of memory free is less
+ than a certain percentage of the heap size. We don't check to
+ see if the grow succeeded because our fallback strategy in
+ either case is to try one more time to allocate. */
+ if ((_pr_gcData.allocMemory < _pr_gcData.maxMemory) &&
+ (_pr_gcData.freeMemory <
+ ((_pr_gcData.allocMemory * MIN_FREE_THRESHOLD_AFTER_GC) / 100L))) {
+ GrowHeap(PR_MAX(bytes, segmentSize));
+ }
+#ifdef GC_STATS
+ LL_ADD(allocTime, PR_Now(), ldelta);
+#endif
+
+ /* Try one last time */
+ if ((bytes >= BIG_ALLOC) && (nsegs < MAX_SEGS)) {
+ p = BigAlloc(tix, bytes, 1);
+ } else {
+ p = BinAlloc(tix, bytes, 1);
+ }
+ if (0 == p) {
+ /* Well that lost big time. Memory must be pretty well fragmented */
+ if (!GrowHeap(PR_MAX(bytes, segmentSize))) {
+ goto lost;
+ }
+ p = BinAlloc(tix, bytes, 1);
+ if (0 == p) goto lost;
+ }
+ }
+
+ /* Zero out the portion of the object memory that was used by
+ the GCFreeChunk structure (skip the first word because it
+ was already overwritten by the gc header word) */
+ objBytes = OBJ_BYTES(p[0]);
+ if (objBytes > sizeof(PRWord)) p[1] = 0;
+ if (objBytes > sizeof(PRWord)*2) p[2] = 0;
+
+ METER(meter.allocBytes += bytes);
+ METER(meter.wastedBytes += (bytes - requestedBytes));
+ UNLOCK_GC();
+
+ if (collectorCleanupNeeded) {
+ CollectorCleanup();
+ }
+
+#if defined(GC_CHECK) || defined(GC_STATS) || defined(GC_TRACEROOTS)
+ {
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+ end->check = PR_BLOCK_END;
+ }
+#endif
+#ifdef GC_STATS
+ {
+ PRInt64 now = PR_Now();
+ double delta;
+ PRInt32 bin;
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+
+ end->allocTime = allocTime;
+ LL_SUB(ldelta, now, allocTime);
+ LL_L2D(delta, ldelta);
+ InlineBinNumber(bin, requestedBytes);
+ end->bin = bin;
+ gcstats[bin].nallocs++;
+ gcstats[bin].allocTime += delta;
+ gcstats[bin].allocTimeVariance += delta * delta;
+ }
+#endif
+#ifdef GC_CHECK
+ if (_pr_gcData.flags & GC_CHECK) {
+ /* Place a pattern in the memory that was allocated that was not
+ requested. We will check the pattern later. */
+ char* cp = (char*)(p + 1) + requestedBytes;
+ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd));
+ char i = (char) 0xff;
+ while (cp < (char*)end) {
+ *cp++ = i--;
+ }
+ end->requestedBytes = requestedBytes;
+ CheckHeap();
+ }
+#endif
+ return p + 1;
+
+ lost:
+ /* Out of memory */
+ UNLOCK_GC();
+ if (collectorCleanupNeeded) {
+ CollectorCleanup();
+ }
+ return 0;
+}
+
+/************************************************************************/
+
+PR_IMPLEMENT(PRWord) PR_GetObjectHeader(void *ptr) {
+ GCSeg *sp;
+ PRWord *h;
+
+ if (ptr == 0) return 0;
+ sp = InHeap(ptr);
+ if (sp == 0) return 0;
+ h = (PRWord*)FindObject(sp, (PRWord*)ptr);
+ return GC_GET_USER_BITS(h[0]);
+}
+
+PR_IMPLEMENT(PRWord) PR_SetObjectHeader(void *ptr, PRWord newUserBits) {
+ GCSeg *sp;
+ PRWord *h, rv;
+
+ if (ptr == 0) return 0;
+ sp = InHeap(ptr);
+ if (sp == 0) return 0;
+ h = (PRWord*)FindObject(sp, (PRWord*)ptr);
+ rv = GC_GET_USER_BITS(h[0]);
+ h[0] = (h[0] & ~GC_USER_BITS) |
+ ((newUserBits << GC_USER_BITS_SHIFT) & GC_USER_BITS);
+ return rv;
+}
+
+PR_IMPLEMENT(void) PR_InitGC(
+ PRWord flags, PRInt32 initialHeapSize, PRInt32 segSize, PRThreadScope scope)
+{
+ static char firstTime = 1;
+
+ if (!firstTime) return;
+ firstTime = 0;
+
+ _pr_msgc_lm = PR_NewLogModule("msgc");
+ _pr_pageShift = PR_GetPageShift();
+ _pr_pageSize = PR_GetPageSize();
+
+#if defined(WIN16)
+ PR_ASSERT( initialHeapSize < MAX_ALLOC_SIZE );
+#endif
+
+ /* Setup initial heap size and initial segment size */
+ if (0 != segSize) segmentSize = segSize;
+#ifdef DEBUG
+ GC = PR_NewLogModule("GC");
+ {
+ char *ev = PR_GetEnv("GC_SEGMENT_SIZE");
+ if (ev && ev[0]) {
+ PRInt32 newSegmentSize = atoi(ev);
+ if (0 != newSegmentSize) segmentSize = newSegmentSize;
+ }
+ ev = PR_GetEnv("GC_INITIAL_HEAP_SIZE");
+ if (ev && ev[0]) {
+ PRInt32 newInitialHeapSize = atoi(ev);
+ if (0 != newInitialHeapSize) initialHeapSize = newInitialHeapSize;
+ }
+ ev = PR_GetEnv("GC_FLAGS");
+ if (ev && ev[0]) {
+ flags |= atoi(ev);
+ }
+#ifdef GCMETER
+ ev = PR_GetEnv("GC_METER");
+ if (ev && ev[0]) {
+ _pr_gcMeter = atoi(ev);
+ }
+#endif
+ }
+#endif
+ if (0 == initialHeapSize) initialHeapSize = segmentSize;
+ if (initialHeapSize < segmentSize) initialHeapSize = segmentSize;
+
+ _pr_gcData.maxMemory = MAX_SEGS * segmentSize;
+ _pr_gcData.liveBlock = ProcessRootBlock;
+ _pr_gcData.livePointer = ProcessRootPointer;
+ _pr_gcData.processRootBlock = ProcessRootBlock;
+ _pr_gcData.processRootPointer = ProcessRootPointer;
+ _pr_gcData.dumpOutput = NULL;
+
+ PR_INIT_CLIST(&_pr_finalizeableObjects);
+ PR_INIT_CLIST(&_pr_finalQueue);
+ _PR_InitGC(flags);
+
+ /* Create finalizer thread */
+ _PR_CreateFinalizer(scope);
+
+ /* Allocate the initial segment for the heap */
+ minBin = 31;
+ maxBin = 0;
+ GrowHeap(initialHeapSize);
+ PR_RegisterRootFinder(ScanWeakFreeList, "scan weak free list", 0);
+}
+
+#if defined(WIN16)
+/*
+** For WIN16 the GC_IN_HEAP() macro must call the private InHeap function.
+** This public wrapper function makes this possible...
+*/
+PR_IMPLEMENT(PRBool)
+PR_GC_In_Heap(void *object)
+{
+ return InHeap( object ) != NULL;
+}
+#endif
+
+
+/** Added by Vishy for sanity checking a few GC structures **/
+/** Can use SanityCheckGC to debug corrupted GC Heap situations **/
+
+#ifdef DEBUG
+
+static int SegmentOverlaps(int i, int j)
+{
+ return
+ (((segs[i].limit > segs[j].base) && (segs[i].base < segs[j].base)) ||
+ ((segs[j].limit > segs[i].base) && (segs[j].base < segs[i].base)));
+}
+
+static void NoSegmentOverlaps(void)
+{
+ int i,j;
+
+ for (i = 0; i < nsegs; i++)
+ for (j = i+1 ; j < nsegs ; j++)
+ PR_ASSERT(!SegmentOverlaps(i,j));
+}
+
+static void SegInfoCheck(void)
+{
+ int i;
+ for (i = 0 ; i < nsegs ; i++)
+ PR_ASSERT((segs[i].info->hbits) &&
+ (segs[i].info->hbits == segs[i].hbits) &&
+ (segs[i].info->base == segs[i].base) &&
+ (segs[i].info->limit == segs[i].limit));
+}
+
+static void SanityCheckGC()
+{
+ NoSegmentOverlaps();
+ SegInfoCheck();
+}
+
+#endif
+
+#if defined(DEBUG) && defined(WIN32)
+
+extern void *baseaddr;
+extern void *lastaddr;
+
+PR_IMPLEMENT(void)
+PR_PrintGCStats(void)
+{
+ long reportedSegSpace = _pr_gcData.busyMemory + _pr_gcData.freeMemory;
+ char* msg;
+ long largeCount = 0, largeSize = 0;
+ long segCount = 0, segSize = 0;
+ long freeCount = 0, freeSize = 0;
+ GCSeg *sp, *esp;
+ GCSegInfo* si;
+
+ LOCK_GC();
+
+ sp = segs;
+ esp = sp + nsegs;
+ while (sp < esp) {
+ long size = sp->info->limit - sp->info->base;
+ segCount++;
+ segSize += size;
+ if (sp->info->fromMalloc) {
+ largeCount++;
+ largeSize += size;
+ }
+ sp++;
+ }
+
+ si = freeSegs;
+ while (si != NULL) {
+ long size = si->limit - si->base;
+ freeCount++;
+ freeSize += size;
+ si = si->next;
+ }
+
+ msg = PR_smprintf("\
+# GC Stats:\n\
+# vm space:\n\
+# range: %ld - %ld\n\
+# size: %ld\n\
+# segments:\n\
+# range: %ld - %ld\n\
+# count: %ld (reported: %ld)\n\
+# size: %ld (reported: %ld)\n\
+# free count: %ld\n\
+# free size: %ld\n\
+# busy objs: %ld (%ld%%)\n\
+# free objs: %ld (%ld%%)\n\
+# large blocks:\n\
+# count: %ld\n\
+# total size: %ld (%ld%%)\n\
+# avg size: %ld\n\
+",
+ /* vm space */
+ (long)baseaddr, (long)lastaddr,
+ (long)lastaddr - (long)baseaddr,
+ /* segments */
+ _pr_gcData.lowSeg, _pr_gcData.highSeg,
+ segCount, nsegs,
+ segSize, reportedSegSpace,
+ freeCount,
+ freeSize,
+ _pr_gcData.busyMemory,
+ (_pr_gcData.busyMemory * 100 / reportedSegSpace),
+ _pr_gcData.freeMemory,
+ (_pr_gcData.freeMemory * 100 / reportedSegSpace),
+ /* large blocks */
+ largeCount,
+ largeSize, (largeSize * 100 / reportedSegSpace),
+ (largeCount ? largeSize / largeCount : 0)
+ );
+ UNLOCK_GC();
+ fprintf(stderr, msg);
+ OutputDebugString(msg);
+ PR_smprintf_free(msg);
+#ifdef GC_STATS
+ PR_PrintGCAllocStats();
+#endif
+}
+#endif
+
+PR_IMPLEMENT(void)
+PR_DumpToFile(char* filename, char* msg, PRFileDumper dump, PRBool detailed)
+{
+ FILE *out;
+ OutputDebugString(msg);
+ out = fopen(filename, "a");
+ if (!out) {
+ char buf[64];
+ PR_ASSERT(strlen(filename) < sizeof(buf) - 16);
+ PR_snprintf(buf, sizeof(buf), "Can't open \"%s\"\n",
+ filename);
+ OutputDebugString(buf);
+ }
+ else
+ {
+ struct tm *newtime;
+ time_t aclock;
+ int i;
+
+ time(&aclock);
+ newtime = localtime(&aclock);
+ fprintf(out, "%s on %s\n", msg, asctime(newtime)); /* Print current time */
+ dump(out, detailed);
+ fprintf(out, "\n\n");
+ for (i = 0; i < 80; i++)
+ fprintf(out, "=");
+ fprintf(out, "\n\n");
+ fclose(out);
+ }
+ OutputDebugString(" done\n");
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/unixgc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/unixgc.c
new file mode 100644
index 00000000..cea4225e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/unixgc.c
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "gcint.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#define _PR_GC_VMBASE 0x40000000
+
+#if defined(SOLARIS)
+#define _MD_MMAP_FLAGS MAP_SHARED
+#elif defined(RELIANTUNIX)
+#define _MD_MMAP_FLAGS MAP_PRIVATE|MAP_FIXED
+#else
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+#endif
+
+static PRInt32 zero_fd = -1;
+static PRLock *zero_fd_lock = NULL;
+
+void _MD_InitGC(void)
+{
+#ifdef DEBUG
+ /*
+ * Disable using mmap(2) if NSPR_NO_MMAP is set
+ */
+ if (getenv("NSPR_NO_MMAP")) {
+ zero_fd = -2;
+ return;
+ }
+#endif
+ zero_fd = open("/dev/zero",O_RDWR , 0);
+ zero_fd_lock = PR_NewLock();
+}
+
+/* This static variable is used by _MD_GrowGCHeap and _MD_ExtendGCHeap */
+static void *lastaddr = (void*) _PR_GC_VMBASE;
+
+void *_MD_GrowGCHeap(PRUint32 *sizep)
+{
+ void *addr;
+ PRUint32 size;
+
+ size = *sizep;
+
+ PR_Lock(zero_fd_lock);
+ if (zero_fd < 0) {
+ goto mmap_loses;
+ }
+
+ /* Extend the mapping */
+ addr = mmap(lastaddr, size, PROT_READ|PROT_WRITE|PROT_EXEC,
+ _MD_MMAP_FLAGS,
+ zero_fd, 0);
+ if (addr == (void*)-1) {
+ zero_fd = -1;
+ goto mmap_loses;
+ }
+ lastaddr = ((char*)addr + size);
+#ifdef DEBUG
+ PR_LOG(_pr_msgc_lm, PR_LOG_WARNING,
+ ("GC: heap extends from %08x to %08x\n",
+ _PR_GC_VMBASE,
+ _PR_GC_VMBASE + (char*)lastaddr - (char*)_PR_GC_VMBASE));
+#endif
+ PR_Unlock(zero_fd_lock);
+ return addr;
+
+mmap_loses:
+ PR_Unlock(zero_fd_lock);
+ return PR_MALLOC(size);
+}
+
+/* XXX - This is disabled. MAP_FIXED just does not work. */
+#if 0
+PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) {
+ PRBool rv = PR_FALSE;
+ void* addr;
+ PRInt32 allocSize = newSize - oldSize;
+
+ PR_Lock(zero_fd_lock);
+ addr = mmap(base + oldSize, allocSize, PROT_READ|PROT_WRITE|PROT_EXEC,
+ _MD_MMAP_FLAGS | MAP_FIXED, zero_fd, 0);
+ if (addr == (void*)-1) {
+ goto loser;
+ }
+ if (addr != (void*) (base + oldSize)) {
+ munmap(base + oldSize, allocSize);
+ goto loser;
+ }
+ lastaddr = ((char*)base + newSize);
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS,
+ ("GC: heap now extends from %p to %p",
+ base, base + newSize));
+ rv = PR_TRUE;
+
+loser:
+ PR_Unlock(zero_fd_lock);
+ return rv;
+}
+#else
+PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) {
+ return PR_FALSE;
+}
+#endif
+
+void _MD_FreeGCSegment(void *base, PRInt32 len)
+{
+ if (zero_fd < 0) {
+ PR_DELETE(base);
+ } else {
+ (void) munmap(base, len);
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/win16gc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/win16gc.c
new file mode 100644
index 00000000..0af0079b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/win16gc.c
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+#if defined(WIN16)
+#include <windows.h>
+#endif
+#include "prtypes.h"
+#include <stdlib.h>
+
+#define MAX_SEGMENT_SIZE (65536l - 4096l)
+
+/************************************************************************/
+/*
+** Machine dependent GC Heap management routines:
+** _MD_GrowGCHeap
+*/
+/************************************************************************/
+
+void _MD_InitGC(void) {}
+
+extern void *
+_MD_GrowGCHeap(PRUint32 *sizep)
+{
+ void *addr;
+
+ if( *sizep > MAX_SEGMENT_SIZE ) {
+ *sizep = MAX_SEGMENT_SIZE;
+ }
+
+ addr = malloc((size_t)*sizep);
+ return addr;
+}
+
+HINSTANCE _pr_hInstance;
+
+int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
+ WORD cbHeapSize, LPSTR lpszCmdLine )
+{
+ _pr_hInstance = hInst;
+ return TRUE;
+}
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/src/win32gc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/win32gc.c
new file mode 100644
index 00000000..eec83774
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/src/win32gc.c
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * GC related routines
+ *
+ */
+#include <windows.h>
+#include "prlog.h"
+
+extern PRLogModuleInfo* _pr_msgc_lm;
+
+#define GC_VMBASE 0x40000000
+#define GC_VMLIMIT 0x00FFFFFF
+
+/************************************************************************/
+/*
+** Machine dependent GC Heap management routines:
+** _MD_GrowGCHeap
+*/
+/************************************************************************/
+
+void *baseaddr = (void*) GC_VMBASE;
+void *lastaddr = (void*) GC_VMBASE;
+
+void _MD_InitGC() {}
+
+void *_MD_GrowGCHeap(PRUint32 *sizep)
+{
+ void *addr;
+ size_t size;
+
+ /* Reserve a block of memory for the GC */
+ if( lastaddr == baseaddr ) {
+ addr = VirtualAlloc( (void *)GC_VMBASE, GC_VMLIMIT, MEM_RESERVE, PAGE_READWRITE );
+
+ /*
+ ** If the GC_VMBASE address is already mapped, then let the OS choose a
+ ** base address that is available...
+ */
+ if (addr == NULL) {
+ addr = VirtualAlloc( NULL, GC_VMLIMIT, MEM_RESERVE, PAGE_READWRITE );
+
+ baseaddr = lastaddr = addr;
+ if (addr == NULL) {
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("GC: unable to allocate heap: LastError=%ld",
+ GetLastError()));
+ return 0;
+ }
+ }
+ }
+ size = *sizep;
+
+ /* Extend the mapping */
+ addr = VirtualAlloc( lastaddr, size, MEM_COMMIT, PAGE_READWRITE );
+ if (addr == NULL) {
+ return 0;
+ }
+
+ lastaddr = ((char*)addr + size);
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS,
+ ("GC: heap extends from %08x to %08x",
+ baseaddr, (long)baseaddr + (char*)lastaddr - (char*)baseaddr));
+
+ return addr;
+}
+
+PRBool _MD_ExtendGCHeap(char *base, PRInt32 oldSize, PRInt32 newSize) {
+ void* addr;
+
+ addr = VirtualAlloc( base + oldSize, newSize - oldSize,
+ MEM_COMMIT, PAGE_READWRITE );
+ if (NULL == addr) {
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("GC: unable to extend heap: LastError=%ld",
+ GetLastError()));
+ return PR_FALSE;
+ }
+ if (base + oldSize != (char*)addr) {
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("GC: segment extension returned %x instead of %x",
+ addr, base + oldSize));
+ VirtualFree(addr, newSize - oldSize, MEM_DECOMMIT);
+ return PR_FALSE;
+ }
+ lastaddr = base + newSize;
+ PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS,
+ ("GC: heap now extends from %p to %p",
+ base, base + newSize));
+ return PR_TRUE;
+}
+
+
+void _MD_FreeGCSegment(void *base, PRInt32 len)
+{
+ (void)VirtualFree(base, 0, MEM_RELEASE);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/Makefile.in
new file mode 100644
index 00000000..23518e15
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/Makefile.in
@@ -0,0 +1,315 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_TARGET), WIN16)
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+W16STDIO = $(MOD_DEPTH)/pr/src/md/windows/$(OBJDIR)/w16stdio.$(OBJ_SUFFIX)
+endif
+
+ifeq ($(OS_TARGET), OS2)
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+endif
+
+CSRCS = gc1.c thrashgc.c
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS) $(OBJS)
+
+INCLUDES = -I$(dist_includedir)
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+NSPR_VERSION = $(MOD_MAJOR_VERSION)
+GC_VERSION = $(MOD_MAJOR_VERSION)
+LIBPR = -lnspr$(NSPR_VERSION)
+LIBPLC = -lplc$(NSPR_VERSION)
+LIBGC = -lmsgc$(GC_VERSION)
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+ LIBPR = $(dist_libdir)/nspr$(NSPR_VERSION).lib
+ LIBPLC = $(dist_libdir)/plc$(NSPR_VERSION).lib
+ LIBGC= $(dist_libdir)/msgc$(GC_VERSION).lib
+else
+ LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+ LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).$(LIB_SUFFIX)
+ LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).$(LIB_SUFFIX)
+ LIBGC= $(dist_libdir)/libmsgc$(GC_VERSION).$(LIB_SUFFIX)
+endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO
+ LIBPR = $(dist_libdir)/nspr$(NSPR_VERSION).lib
+ LIBPLC = $(dist_libdir)/plc$(NSPR_VERSION).lib
+ LIBGC= $(dist_libdir)/msgc$(GC_VERSION).lib
+else
+ LDOPTS += -Zomf -Zlinker /PM:VIO
+endif
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+LDOPTS += -rpath $(PWD)/$(dist_libdir) -rdata_shared
+
+# For 6.x machines, include this flag
+ifeq ($(basename $(OS_RELEASE)),6)
+ifeq ($(USE_N32),1)
+LDOPTS += -n32
+else
+LDOPTS += -32
+endif
+endif
+
+endif
+
+ifeq ($(OS_ARCH), OSF1)
+# I haven't figured out how to pass -rpath to cc on OSF1 V3.2, so
+# we do static linking.
+ifeq ($(OS_RELEASE), V3.2)
+ LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).a
+ LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).a
+ LIBGC = $(dist_libdir)/libmsgc$(GC_VERSION).a
+ EXTRA_LIBS = -lc_r
+else
+ LDOPTS += -rpath $(PWD)/$(dist_libdir)
+endif
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+LDOPTS += -z -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+LIBPR = -lnspr$(NSPR_VERSION)_shr
+LIBPLC = -lplc$(NSPR_VERSION)_shr
+LIBGC = -lmsgc$(GC_VERSION)_shr
+else
+LDOPTS += -brtl
+EXTRA_LIBS = -ldl
+endif
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ifneq ($(OS_RELEASE), 4.1.3_U1)
+ifdef NS_USE_GCC
+LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+else
+LDOPTS += -R $(PWD)/$(dist_libdir)
+endif
+endif
+
+ifneq ($(LOCAL_THREADS_ONLY),1)
+# SunOS 5.4 and 5.5 need to link with -lthread or -lpthread,
+# even though we already linked with these system libraries
+# when we built libnspr.so.
+ifeq ($(OS_RELEASE), 5.4)
+EXTRA_LIBS = -lthread
+endif
+
+ifeq ($(OS_RELEASE), 5.5)
+ifdef USE_PTHREADS
+EXTRA_LIBS = -lpthread
+else
+EXTRA_LIBS = -lthread
+endif
+endif
+endif # LOCAL_THREADS_ONLY
+endif # SunOS
+
+ifeq ($(OS_ARCH),NEC)
+EXTRA_LIBS = $(OS_LIBS)
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), NCR)
+# XXX: We see some strange problems when we link with libnspr.so.
+# So for now we use static libraries on NCR. The shared library
+# stuff below is commented out.
+LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).a
+LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).a
+LIBGC = $(dist_libdir)/libmsgc$(GC_VERSION).a
+EXTRA_LIBS = -lsocket -lnsl -ldl
+
+# NCR needs to link against -lsocket -lnsl (and -lc, which is linked
+# implicitly by $(CC)) again even though we already linked with these
+# system libraries when we built libnspr.so.
+#EXTRA_LIBS = -lsocket -lnsl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+#export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), Linux)
+ifeq ($(OS_RELEASE), 1.2)
+EXTRA_LIBS = -ldl
+endif
+endif
+
+ifeq ($(OS_ARCH), SCOOS)
+# SCO Unix needs to link against -lsocket again even though we
+# already linked with these system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH),SINIX)
+EXTRA_LIBS = -lsocket -lnsl -lresolv -ldl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH),BSD_OS)
+EXTRA_LIBS = -ldl
+endif
+
+ifeq ($(OS_ARCH),DGUX)
+EXTRA_LIBS = -lsocket -lnsl -ldl
+endif
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(NSPR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET),WIN16)
+ echo system windows >w16link
+ echo name $@ >>w16link
+ echo option map >>w16link
+# echo option CASEEXACT >>w16link
+ echo option stack=16K >>w16link
+ echo debug $(DEBUGTYPE) all >>w16link
+ echo file >>w16link
+ echo $< , >>w16link
+ echo $(W16STDIO) >>w16link
+ echo library >>w16link
+ echo $(LIBPR), >>w16link
+ echo $(LIBPLC), >>w16link
+ echo $(LIBGC), >>w16link
+ echo winsock.lib >>w16link
+ wlink @w16link.
+else
+ link $(LDOPTS) $< $(LIBGC) $(LIBPLC) $(LIBPR) wsock32.lib -out:$@
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(LDOPTS) $< $(LIBGC) $(LIBPLC) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS) -o $@
+else
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBGC) $(LIBPLC) $(LIBPR) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+
+export:: $(TARGETS)
+export:: install
+clean::
+ rm -f $(TARGETS)
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/gc1.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/gc1.c
new file mode 100644
index 00000000..d6846235
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/gc1.c
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prgc.h"
+#include "prinit.h"
+#include "prmon.h"
+#include "prinrval.h"
+#ifndef XP_MAC
+#include "private/pprthred.h"
+#else
+#include "pprthred.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+static PRMonitor *mon;
+static PRInt32 threads, waiting, iterations;
+static PRInt32 scanCount, finalizeCount, freeCount;
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+
+typedef struct Array {
+ PRUintn size;
+ void *body[1];
+} Array;
+
+int arrayTypeIndex;
+
+static void PR_CALLBACK ScanArray(void *a)
+{
+/* printf ("In ScanArray a = %X size = %d \n", a, a->size); */
+ scanCount++;
+}
+
+static void PR_CALLBACK FinalizeArray(void *a)
+{
+/* printf ("In FinalizeArray a = %X size = %d \n", a, a->size); */
+ finalizeCount++;
+}
+
+static void PR_CALLBACK FreeArray(void *a)
+{
+/* printf ("In FreeArray\n"); */
+ freeCount++;
+}
+
+static Array *NewArray(PRUintn size)
+{
+ Array *a;
+
+ a = (Array *)PR_AllocMemory(sizeof(Array) + size*sizeof(void*) - 1*sizeof(void*),
+ arrayTypeIndex, PR_ALLOC_CLEAN);
+
+/* printf ("In NewArray a = %X \n", a); */
+
+ if (a)
+ a->size = size;
+ return a;
+}
+
+GCType arrayType = {
+ ScanArray,
+ FinalizeArray,
+ 0,
+ 0,
+ FreeArray,
+ 0
+};
+
+static void Initialize(void)
+{
+ PR_InitGC(0, 0, 0, PR_GLOBAL_THREAD);
+ arrayTypeIndex = PR_RegisterType(&arrayType);
+}
+
+static void PR_CALLBACK AllocateLikeMad(void *arg)
+{
+ Array *prev;
+ PRInt32 i;
+ PRInt32 count;
+
+ count = (PRInt32)arg;
+ prev = 0;
+ for (i = 0; i < count; i++) {
+ Array *leak = NewArray(i & 511);
+ if ((i & 1023) == 0) {
+ prev = 0; /* forget */
+ } else {
+ if (i & 1) {
+ prev = leak; /* remember */
+ }
+ }
+ }
+ PR_EnterMonitor(mon);
+ waiting++;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+}
+
+int main(int argc, char **argv)
+{
+ PRIntervalTime start, stop, usec;
+ double d;
+ PRIntn i, totalIterations;
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
+
+ threads = 10;
+ iterations = 100;
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) {
+ fprintf(stderr, "Invalid command-line option\n");
+ exit(1);
+ }
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 't': /* number of threads */
+ threads = atoi(opt->value);
+ break;
+ case 'c': /* iteration count */
+ iterations = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ fprintf(stderr, "t is %ld, i is %ld\n", (long) threads, (long) iterations);
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 5);
+ PR_STDIO_INIT();
+ Initialize();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("gc1.log");
+ debug_mode = 1;
+#endif
+
+ /* Spin all of the allocator threads and then wait for them to exit */
+ start = PR_IntervalNow();
+ mon = PR_NewMonitor();
+ PR_EnterMonitor(mon);
+ waiting = 0;
+ for (i = 0; i < threads; i++) {
+ (void) PR_CreateThreadGCAble(PR_USER_THREAD,
+ AllocateLikeMad, (void*)iterations,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ }
+ while (waiting != threads) {
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(mon);
+
+ PR_GC();
+ PR_ForceFinalize();
+
+ totalIterations = iterations * threads;
+/*
+ if (scanCount != totalIterations)
+ printf ("scanCount discrepancy scanCount = %d totalIterations = %d \n",
+ scanCount, totalIterations);
+ if (freeCount != totalIterations)
+ printf ("freeCount discrepancy freeCount = %d totalIterations = %d \n",
+ freeCount, totalIterations);
+ if ((finalizeCount != totalIterations) && (finalizeCount != (totalIterations-1)))
+ printf ("finalizeCount discrepancy finalizeCount = %d totalIterations = %d \n",
+ finalizeCount,totalIterations);
+*/
+
+ stop = PR_IntervalNow();
+
+ usec = stop = stop - start;
+ d = (double)usec;
+
+ if (debug_mode) printf("%40s: %6.2f usec\n", "GC allocation", d / (iterations * threads));
+ else {
+ if (d == 0.0) failed_already = PR_TRUE;
+
+ }
+
+ PR_Cleanup();
+ if(failed_already)
+ {
+ printf("FAIL\n");
+ return 1;
+ }
+ else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/thrashgc.c b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/thrashgc.c
new file mode 100644
index 00000000..9d49ec19
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/msgc/tests/thrashgc.c
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** Name: thrashgc
+**
+** Description: test garbace collection functions.
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+#include "prthread.h"
+#include "prgc.h"
+#include "prprf.h"
+#include "prinrval.h"
+#include "prlock.h"
+#include "prinit.h"
+#include "prcvar.h"
+
+#ifndef XP_MAC
+#include "private/pprthred.h"
+#else
+#include "pprthred.h"
+#endif
+
+#include <stdio.h>
+#include <memory.h>
+#include <string.h>
+
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+static char* progname;
+static PRInt32 loops = 1000;
+static int tix1, tix2, tix3;
+static GCInfo* gcInfo;
+static PRLock* stderrLock;
+
+typedef struct Type1 Type1;
+typedef struct Type2 Type2;
+
+struct Type1 {
+ Type2* atwo;
+ Type1* next;
+};
+
+struct Type2 {
+ void* buf;
+};
+
+static void PR_CALLBACK ScanType1(void *obj) {
+ gcInfo->livePointer(((Type1 *)obj)->atwo);
+ gcInfo->livePointer(((Type1 *)obj)->next);
+}
+
+static void PR_CALLBACK ScanType2(void *obj) {
+ gcInfo->livePointer(((Type2 *)obj)->buf);
+}
+
+static GCType type1 = {
+ ScanType1
+};
+
+static GCType type2 = {
+ ScanType2
+/* (void (*)(void*)) ScanType2 */
+};
+
+static GCType type3 = {
+ 0
+};
+
+Type1* NewType1(void) {
+ Type1* p = (Type1*) PR_AllocMemory(sizeof(Type1), tix1, PR_ALLOC_DOUBLE);
+ PR_ASSERT(p != NULL);
+ return p;
+}
+
+Type2* NewType2(void) {
+ Type2* p = (Type2*) PR_AllocMemory(sizeof(Type2), tix2, PR_ALLOC_DOUBLE);
+ PR_ASSERT(p != NULL);
+ return p;
+}
+
+void* NewBuffer(PRInt32 size) {
+ void* p = PR_AllocMemory(size, tix3, PR_ALLOC_DOUBLE);
+ PR_ASSERT(p != NULL);
+ return p;
+}
+
+/* Allocate alot of garbage */
+static void PR_CALLBACK AllocStuff(void *unused) {
+ PRInt32 i;
+ void* danglingRefs[50];
+ PRIntervalTime start, end;
+ char msg[100];
+
+ start = PR_IntervalNow();
+ for (i = 0; i < loops; i++) {
+ void* p;
+ if (i & 1) {
+ Type1* t1 = NewType1();
+ t1->atwo = NewType2();
+ t1->next = NewType1();
+ t1->atwo->buf = NewBuffer(100);
+ p = t1;
+ } else {
+ Type2* t2 = NewType2();
+ t2->buf = NewBuffer(i & 16383);
+ p = t2;
+ }
+ if ((i % 10) == 0) {
+ memmove(&danglingRefs[0], &danglingRefs[1], 49*sizeof(void*));
+ danglingRefs[49] = p;
+ }
+ }
+ end = PR_IntervalNow();
+ if (debug_mode) PR_snprintf(msg, sizeof(msg), "Thread %p: %ld allocations took %ld ms",
+ PR_GetCurrentThread(), loops,
+ PR_IntervalToMilliseconds((PRIntervalTime) (end - start)));
+ PR_Lock(stderrLock);
+#ifndef XP_MAC
+ fprintf(stderr, "%s\n", msg);
+#else
+ if (debug_mode) printf("%s\n", msg);
+#endif
+ PR_Unlock(stderrLock);
+ }
+
+static void usage(char *progname) {
+#ifndef XP_MAC
+ fprintf(stderr, "Usage: %s [-t threads] [-l loops]\n", progname);
+#else
+ printf("Usage: %s [-t threads] [-l loops]\n", progname);
+#endif
+ exit(-1);
+}
+
+static int realMain(int argc, char **argv, char *notused) {
+ int i;
+ int threads = 0;
+
+#ifndef XP_MAC
+ progname = strrchr(argv[0], '/');
+ if (progname == 0) progname = argv[0];
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-t") == 0) {
+ if (i == argc - 1) {
+ usage(progname);
+ }
+ threads = atoi(argv[++i]);
+ if (threads < 0) threads = 0;
+ if (threads > 10000) threads = 10000;
+ continue;
+ }
+ if (strcmp(argv[i], "-l") == 0) {
+ if (i == argc - 1) {
+ usage(progname);
+ }
+ loops = atoi(argv[++i]);
+ continue;
+ }
+ usage(progname);
+ }
+#else
+ threads = 50;
+#endif
+
+ for (i = 0; i < threads; i++) {
+ PRThread* thread;
+
+ /* XXXXX */
+ thread = PR_CreateThreadGCAble(PR_USER_THREAD, /* thread type */
+ AllocStuff, /* start function */
+ NULL, /* arg */
+ PR_PRIORITY_NORMAL, /* priority */
+ PR_LOCAL_THREAD, /* thread scope */
+ PR_UNJOINABLE_THREAD, /* thread state */
+ 0); /* stack size */
+ if (thread == 0) {
+#ifndef XP_MAC
+ fprintf(stderr, "%s: no more threads (only %d were created)\n",
+ progname, i);
+#else
+ printf("%s: no more threads (only %d were created)\n",
+ progname, i);
+#endif
+ break;
+ }
+ }
+ AllocStuff(NULL);
+ return 0;
+}
+
+static int padMain(int argc, char **argv) {
+ char pad[512];
+ return realMain(argc, argv, pad);
+}
+
+int main(int argc, char **argv) {
+ int rv;
+
+ debug_mode = 1;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_SetThreadGCAble();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("thrashgc.log");
+ debug_mode = 1;
+#endif
+
+ PR_InitGC(0, 0, 0, PR_GLOBAL_THREAD);
+ PR_STDIO_INIT();
+ stderrLock = PR_NewLock();
+ tix1 = PR_RegisterType(&type1);
+ tix2 = PR_RegisterType(&type2);
+ tix3 = PR_RegisterType(&type3);
+ gcInfo = PR_GetGCInfo();
+ rv = padMain(argc, argv);
+ printf("PASS\n");
+ PR_Cleanup();
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/prstreams/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/prstreams/Makefile.in
new file mode 100644
index 00000000..5c1311b2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/Makefile.in
@@ -0,0 +1,207 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ ifeq ($(OS_RELEASE),4.1.3_U1)
+ OPTIMIZER =
+ else
+ # The C++ compiler in Workshop 5.0 uses standard
+ # iostreams as default. -library=iostream will
+ # allow Workshop 5.0 to work with classic iostreams.
+ ifndef NS_USE_GCC
+ CCC_VERSION := $(shell $(CCC) -V 2>&1)
+ ifneq (,$(findstring 5.0,$(CCC_VERSION)))
+ CCC_ONLY_FLAGS += -library=iostream
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+ ifneq ($(OS_RELEASE),5.3)
+ CCC_ONLY_FLAGS += -exceptions
+ endif
+endif
+
+ifeq ($(OS_ARCH), BeOS)
+ CFLAGS += -frtti -fexceptions
+endif
+
+INCLUDES = -I$(dist_includedir)
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+CSRCS = \
+ plvrsion.c \
+ $(NULL)
+
+CXXSRCS = \
+ prstrms.cpp \
+ $(NULL)
+
+OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX)) $(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
+
+ifeq ($(OS_ARCH), WINNT)
+ DLLBASE=/BASE:0x30000000
+ RES=$(OBJDIR)/prstrms.res
+ RESNAME=prstrms.rc
+ OS_LIBS = user32.lib
+else
+ ifeq ($(OS_ARCH),OS2)
+ ifneq ($(MOZ_OS2_TOOLS),VACPP)
+ OS_LIBS = -lstdcpp
+ endif
+ else
+ ifeq ($(OS_ARCH), AIX)
+ ifeq ($(OS_RELEASE), 4.1)
+ ifeq ($(CLASSIC_NSPR),1)
+ OS_LIBS += -lC -lc
+ else
+ OS_LIBS += -lC_r -lc_r
+ endif
+ else
+ # makeC++SharedLib(_r) is in either /usr/lpp/xlC/bin
+ # or /usr/ibmcxx/bin.
+ ifeq ($(CLASSIC_NSPR),1)
+ MKSHLIB = makeC++SharedLib -p 0
+ else
+ MKSHLIB = makeC++SharedLib_r -p 0
+ endif
+ OS_LIBS += -ldl
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH),BeOS)
+ OS_LIBS = -lstdc++.r4
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+ OS_LIBS += -lC
+endif
+
+EXTRA_LIBS = $(LIBNSPR)
+
+# On NCR and SCOOS, we can't link with extra libraries when
+# we build a shared library. If we do so, the linker doesn't
+# complain, but we would run into weird problems at run-time.
+# Therefore on these platforms, we link just the object files.
+ifeq ($(OS_ARCH),NCR)
+ EXTRA_LIBS =
+endif
+ifeq ($(OS_ARCH),SCOOS)
+ EXTRA_LIBS =
+endif
+
+ifdef RESOLVE_LINK_SYMBOLS
+EXTRA_LIBS += $(OS_LIBS)
+endif
+
+LIBRARY_NAME = prstrms
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+RELEASE_LIBS = $(TARGETS)
+
+include $(topsrcdir)/config/rules.mk
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+TINC = $(OBJDIR)/_pl_bld.h
+PROD = $(notdir $(SHARED_LIBRARY))
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(OS_ARCH), WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC)
+ifeq ($(OS_ARCH), WINNT)
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ifeq ($(MOZ_OS2_TOOLS), VACPP)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+endif
+#
+# Version information generation (end)
+#
+
+export:: $(TARGETS) $(HEADERS)
+ $(INSTALL) -m 444 $(HEADERS) $(dist_includedir)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifeq ($(OS_ARCH),OS2)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_bindir)
+endif
+ifeq ($(OS_ARCH),HP-UX)
+ifdef SHARED_LIBRARY
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+endif
+endif
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/plvrsion.c b/src/libs/xpcom18a4/nsprpub/lib/prstreams/plvrsion.c
new file mode 100644
index 00000000..87b62e7a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/plvrsion.c
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#include "_pl_bld.h"
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libprstrms, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
+ /* comment */ "http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint()
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+
+/* plvrsion.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.cpp b/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.cpp
new file mode 100644
index 00000000..17b280ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.cpp
@@ -0,0 +1,550 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Robin J. Maxwell 11-22-96
+ */
+
+#include "prstrms.h"
+#include <string.h> // memmove
+
+//
+// Definition of macros _PRSTR_BP, _PRSTR_DELBUF, and _PRSTR_DELBUF_C.
+//
+// _PRSTR_BP is the protected member of class ios that is returned
+// by the public method rdbuf().
+//
+// _PRSTR_DELBUF is the method or data member of class ios, if available,
+// with which we can ensure that the ios destructor does not delete
+// the associated streambuf. If such a method or data member does not
+// exist, define _PRSTR_DELBUF to be empty.
+//
+// _PRSTR_DELBUF_C is just _PRSTR_DELBUF qualified by a base class.
+//
+
+#if defined(__GNUC__)
+#define _PRSTR_BP _strbuf
+#define _PRSTR_DELBUF(x) /* as nothing */
+#define _PRSTR_DELBUF_C(c, x) /* as nothing */
+#elif defined(WIN32)
+#define _PRSTR_BP bp
+#define _PRSTR_DELBUF(x) delbuf(x)
+#define _PRSTR_DELBUF_C(c, x) c::_PRSTR_DELBUF(x)
+#elif defined(VMS)
+#undef _PRSTR_BP
+#define _PRSTR_DELBUF(x) /* as nothing */
+#define _PRSTR_DELBUF_C(c, x) /* as nothing */
+#elif defined(OSF1)
+#define _PRSTR_BP m_psb
+#define _PRSTR_DELBUF(x) /* as nothing */
+#define _PRSTR_DELBUF_C(c, x) /* as nothing */
+#elif defined(QNX)
+#define PRFSTREAMS_BROKEN
+#else
+#define _PRSTR_BP bp
+// Unix compilers don't believe in encapsulation
+// At least on Solaris this is also ignored
+#define _PRSTR_DELBUF(x) delbuf = x
+#define _PRSTR_DELBUF_C(c, x) c::_PRSTR_DELBUF(x)
+#endif
+
+const PRIntn STRM_BUFSIZ = 8192;
+
+#if !defined (PRFSTREAMS_BROKEN)
+
+PRfilebuf::PRfilebuf():
+_fd(0),
+_opened(PR_FALSE),
+_allocated(PR_FALSE)
+{
+}
+
+PRfilebuf::PRfilebuf(PRFileDesc *fd):
+streambuf(),
+_fd(fd),
+_opened(PR_FALSE),
+_allocated(PR_FALSE)
+{
+}
+
+PRfilebuf::PRfilebuf(PRFileDesc *fd, char * buffptr, int bufflen):
+_fd(fd),
+_opened(PR_FALSE),
+_allocated(PR_FALSE)
+{
+ PRfilebuf::setbuf(buffptr, bufflen);
+}
+
+PRfilebuf::~PRfilebuf()
+{
+ if (_opened){
+ close();
+ }else
+ sync();
+ if (_allocated)
+ delete base();
+}
+
+PRfilebuf*
+PRfilebuf::open(const char *name, int mode, int flags)
+{
+ if (_fd != 0)
+ return 0; // error if already open
+ PRIntn PRmode = 0;
+ // translate mode argument
+ if (!(mode & ios::nocreate))
+ PRmode |= PR_CREATE_FILE;
+ //if (mode & ios::noreplace)
+ // PRmode |= O_EXCL;
+ if (mode & ios::app){
+ mode |= ios::out;
+ PRmode |= PR_APPEND;
+ }
+ if (mode & ios::trunc){
+ mode |= ios::out; // IMPLIED
+ PRmode |= PR_TRUNCATE;
+ }
+ if (mode & ios::out){
+ if (mode & ios::in)
+ PRmode |= PR_RDWR;
+ else
+ PRmode |= PR_WRONLY;
+ if (!(mode & (ios::in|ios::app|ios::ate|ios::noreplace))){
+ mode |= ios::trunc; // IMPLIED
+ PRmode |= PR_TRUNCATE;
+ }
+ }else if (mode & ios::in)
+ PRmode |= PR_RDONLY;
+ else
+ return 0; // error if not ios:in or ios::out
+
+
+ //
+ // The usual portable across unix crap...
+ // NT gets a hokey piece of junk layer that prevents
+ // access to the API.
+#ifdef WIN32
+ _fd = PR_Open(name, PRmode, PRmode);
+#else
+ _fd = PR_Open(name, PRmode, flags);
+#endif
+ if (_fd == 0)
+ return 0;
+ _opened = PR_TRUE;
+ if ((!unbuffered()) && (!ebuf())){
+ char * sbuf = new char[STRM_BUFSIZ];
+ if (!sbuf)
+ unbuffered(1);
+ else{
+ _allocated = PR_TRUE;
+ streambuf::setb(sbuf,sbuf+STRM_BUFSIZ,0);
+ }
+ }
+ if (mode & ios::ate){
+ if (seekoff(0,ios::end,mode)==EOF){
+ close();
+ return 0;
+ }
+ }
+ return this;
+}
+
+PRfilebuf*
+PRfilebuf::attach(PRFileDesc *fd)
+{
+ _opened = PR_FALSE;
+ _fd = fd;
+ return this;
+}
+
+int
+PRfilebuf::overflow(int c)
+{
+ if (allocate()==EOF) // make sure there is a reserve area
+ return EOF;
+ if (PRfilebuf::sync()==EOF) // sync before new buffer created below
+ return EOF;
+
+ if (!unbuffered())
+ setp(base(),ebuf());
+
+ if (c!=EOF){
+ if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
+ sputc(c);
+ else{
+ if (PR_Write(_fd, &c, 1)!=1)
+ return(EOF);
+ }
+ }
+ return(1); // return something other than EOF if successful
+}
+
+int
+PRfilebuf::underflow()
+{
+ int count;
+ unsigned char tbuf;
+
+ if (in_avail())
+ return (int)(unsigned char) *gptr();
+
+ if (allocate()==EOF) // make sure there is a reserve area
+ return EOF;
+ if (PRfilebuf::sync()==EOF)
+ return EOF;
+
+ if (unbuffered())
+ {
+ if (PR_Read(_fd,(void *)&tbuf,1)<=0)
+ return EOF;
+ return (int)tbuf;
+ }
+
+ if ((count=PR_Read(_fd,(void *)base(),blen())) <= 0)
+ return EOF; // reached EOF
+ setg(base(),base(),base()+count);
+ return (int)(unsigned char) *gptr();
+}
+
+streambuf*
+PRfilebuf::setbuf(char *buffptr, PRstreambuflen bufflen)
+{
+ if (is_open() && (ebuf()))
+ return 0;
+ if ((!buffptr) || (bufflen <= 0))
+ unbuffered(1);
+ else
+ setb(buffptr, buffptr+bufflen, 0);
+ return this;
+}
+
+streampos
+PRfilebuf::seekoff(streamoff offset, ios::seek_dir dir, int /* mode */)
+{
+ if (PR_GetDescType(_fd) == PR_DESC_FILE){
+ PRSeekWhence fdir;
+ PRInt32 retpos;
+ switch (dir) {
+ case ios::beg :
+ fdir = PR_SEEK_SET;
+ break;
+ case ios::cur :
+ fdir = PR_SEEK_CUR;
+ break;
+ case ios::end :
+ fdir = PR_SEEK_END;
+ break;
+ default:
+ // error
+ return(EOF);
+ }
+
+ if (PRfilebuf::sync()==EOF)
+ return EOF;
+ if ((retpos=PR_Seek(_fd, offset, fdir))==-1L)
+ return (EOF);
+ return((streampos)retpos);
+ }else
+ return (EOF);
+}
+
+
+int
+PRfilebuf::sync()
+{
+ PRInt32 count;
+
+ if (_fd==0)
+ return(EOF);
+
+ if (!unbuffered()){
+ // Sync write area
+ if ((count=out_waiting())!=0){
+ PRInt32 nout;
+ if ((nout =PR_Write(_fd,
+ (void *) pbase(),
+ (unsigned int)count)) != count){
+ if (nout > 0) {
+ // should set _pptr -= nout
+ pbump(-(int)nout);
+ memmove(pbase(), pbase()+nout, (int)(count-nout));
+ }
+ return(EOF);
+ }
+ }
+ setp(0,0); // empty put area
+
+ if (PR_GetDescType(_fd) == PR_DESC_FILE){
+ // Sockets can't seek; don't need this
+ if ((count=in_avail()) > 0){
+ if (PR_Seek(_fd, -count, PR_SEEK_CUR)!=-1L)
+ {
+ return (EOF);
+ }
+ }
+ }
+ setg(0,0,0); // empty get area
+ }
+ return(0);
+}
+
+PRfilebuf *
+PRfilebuf::close()
+{
+ int retval;
+ if (_fd==0)
+ return 0;
+
+ retval = sync();
+
+ if ((PR_Close(_fd)==0) || (retval==EOF))
+ return 0;
+ _fd = 0;
+ return this;
+}
+
+PRifstream::PRifstream():
+istream(new PRfilebuf)
+{
+ _PRSTR_DELBUF(0);
+}
+
+PRifstream::PRifstream(PRFileDesc *fd):
+istream(new PRfilebuf(fd))
+{
+ _PRSTR_DELBUF(0);
+}
+
+PRifstream::PRifstream(PRFileDesc *fd, char *buff, int bufflen):
+istream(new PRfilebuf(fd, buff, bufflen))
+{
+ _PRSTR_DELBUF(0);
+}
+
+PRifstream::PRifstream(const char * name, int mode, int flags):
+istream(new PRfilebuf)
+{
+ _PRSTR_DELBUF(0);
+ if (!rdbuf()->open(name, (mode|ios::in), flags))
+ clear(rdstate() | ios::failbit);
+}
+
+PRifstream::~PRifstream()
+{
+ sync();
+
+ delete rdbuf();
+#ifdef _PRSTR_BP
+ _PRSTR_BP = 0;
+#endif
+}
+
+streambuf *
+PRifstream::setbuf(char * ptr, int len)
+{
+ if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
+ clear(rdstate() | ios::failbit);
+ return 0;
+ }
+ return rdbuf();
+}
+
+void
+PRifstream::attach(PRFileDesc *fd)
+{
+ if (!(rdbuf()->attach(fd)))
+ clear(rdstate() | ios::failbit);
+}
+
+void
+PRifstream::open(const char * name, int mode, int flags)
+{
+ if (is_open() || !(rdbuf()->open(name, (mode|ios::in), flags)))
+ clear(rdstate() | ios::failbit);
+}
+
+void
+PRifstream::close()
+{
+ clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
+}
+
+PRofstream::PRofstream():
+ostream(new PRfilebuf)
+{
+ _PRSTR_DELBUF(0);
+}
+
+PRofstream::PRofstream(PRFileDesc *fd):
+ostream(new PRfilebuf(fd))
+{
+ _PRSTR_DELBUF(0);
+}
+
+PRofstream::PRofstream(PRFileDesc *fd, char *buff, int bufflen):
+ostream(new PRfilebuf(fd, buff, bufflen))
+{
+ _PRSTR_DELBUF(0);
+}
+
+PRofstream::PRofstream(const char *name, int mode, int flags):
+ostream(new PRfilebuf)
+{
+ _PRSTR_DELBUF(0);
+ if (!rdbuf()->open(name, (mode|ios::out), flags))
+ clear(rdstate() | ios::failbit);
+}
+
+PRofstream::~PRofstream()
+{
+ flush();
+
+ delete rdbuf();
+#ifdef _PRSTR_BP
+ _PRSTR_BP = 0;
+#endif
+}
+
+streambuf *
+PRofstream::setbuf(char * ptr, int len)
+{
+ if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
+ clear(rdstate() | ios::failbit);
+ return 0;
+ }
+ return rdbuf();
+}
+
+void
+PRofstream::attach(PRFileDesc *fd)
+{
+ if (!(rdbuf()->attach(fd)))
+ clear(rdstate() | ios::failbit);
+}
+
+void
+PRofstream::open(const char * name, int mode, int flags)
+{
+ if (is_open() || !(rdbuf()->open(name, (mode|ios::out), flags)))
+ clear(rdstate() | ios::failbit);
+}
+
+void
+PRofstream::close()
+{
+ clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
+}
+
+PRfstream::PRfstream():
+iostream(new PRfilebuf)
+{
+ _PRSTR_DELBUF_C(istream, 0);
+ _PRSTR_DELBUF_C(ostream, 0);
+}
+
+PRfstream::PRfstream(PRFileDesc *fd):
+iostream(new PRfilebuf(fd))
+{
+ _PRSTR_DELBUF_C(istream, 0);
+ _PRSTR_DELBUF_C(ostream, 0);
+}
+
+PRfstream::PRfstream(PRFileDesc *fd, char *buff, int bufflen):
+iostream(new PRfilebuf(fd, buff, bufflen))
+{
+ _PRSTR_DELBUF_C(istream, 0);
+ _PRSTR_DELBUF_C(ostream, 0);
+}
+
+PRfstream::PRfstream(const char *name, int mode, int flags):
+iostream(new PRfilebuf)
+{
+ _PRSTR_DELBUF_C(istream, 0);
+ _PRSTR_DELBUF_C(ostream, 0);
+ if (!rdbuf()->open(name, (mode|(ios::in|ios::out)), flags))
+ clear(rdstate() | ios::failbit);
+}
+
+PRfstream::~PRfstream()
+{
+ sync();
+ flush();
+
+ delete rdbuf();
+#ifdef _PRSTR_BP
+ istream::_PRSTR_BP = 0;
+ ostream::_PRSTR_BP = 0;
+#endif
+}
+
+streambuf *
+PRfstream::setbuf(char * ptr, int len)
+{
+ if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
+ clear(rdstate() | ios::failbit);
+ return 0;
+ }
+ return rdbuf();
+}
+
+void
+PRfstream::attach(PRFileDesc *fd)
+{
+ if (!(rdbuf()->attach(fd)))
+ clear(rdstate() | ios::failbit);
+}
+
+void
+PRfstream::open(const char * name, int mode, int flags)
+{
+ if (is_open() || !(rdbuf()->open(name, (mode|(ios::in|ios::out)), flags)))
+ clear(rdstate() | ios::failbit);
+}
+
+void
+PRfstream::close()
+{
+ clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
+}
+
+#else
+
+// fix it sometime
+
+int fix_prfstreams () { return 0; }
+
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.h b/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.h
new file mode 100644
index 00000000..a6752fc4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.h
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Robin J. Maxwell 11-22-96
+ */
+
+#ifndef _PRSTRMS_H
+#define _PRSTRMS_H
+
+#include "prtypes.h"
+#include "prio.h"
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4275)
+#endif
+#include <iostream.h>
+
+#if defined(AIX) && defined(__64BIT__)
+typedef long PRstreambuflen;
+#else
+typedef int PRstreambuflen;
+#endif
+
+#if defined (PRFSTREAMS_BROKEN)
+
+// fix it sometime
+
+#define PRfilebuf streambuf
+#define PRifstream ifstream
+#define PRofstream ofstream
+#define PRfstream fstream
+
+#else
+
+class PR_IMPLEMENT(PRfilebuf): public streambuf
+{
+public:
+ PRfilebuf();
+ PRfilebuf(PRFileDesc *fd);
+ PRfilebuf(PRFileDesc *fd, char * buffptr, int bufflen);
+ ~PRfilebuf();
+ virtual int overflow(int=EOF);
+ virtual int underflow();
+ virtual streambuf *setbuf(char *buff, PRstreambuflen bufflen);
+ virtual streampos seekoff(streamoff, ios::seek_dir, int);
+ virtual int sync();
+ PRfilebuf *open(const char *name, int mode, int flags);
+ PRfilebuf *attach(PRFileDesc *fd);
+ PRfilebuf *close();
+ int is_open() const {return (_fd != 0);}
+ PRFileDesc *fd(){return _fd;}
+
+private:
+ PRFileDesc * _fd;
+ PRBool _opened;
+ PRBool _allocated;
+};
+
+class PR_IMPLEMENT(PRifstream): public istream {
+public:
+ PRifstream();
+ PRifstream(const char *, int mode=ios::in, int flags = 0);
+ PRifstream(PRFileDesc *);
+ PRifstream(PRFileDesc *, char *, int);
+ ~PRifstream();
+
+ streambuf * setbuf(char *, int);
+ PRfilebuf* rdbuf(){return (PRfilebuf*) ios::rdbuf(); }
+
+ void attach(PRFileDesc *fd);
+ PRFileDesc *fd() {return rdbuf()->fd();}
+
+ int is_open(){return rdbuf()->is_open();}
+ void open(const char *, int mode=ios::in, int flags= 0);
+ void close();
+};
+
+class PR_IMPLEMENT(PRofstream) : public ostream {
+public:
+ PRofstream();
+ PRofstream(const char *, int mode=ios::out, int flags = 0);
+ PRofstream(PRFileDesc *);
+ PRofstream(PRFileDesc *, char *, int);
+ ~PRofstream();
+
+ streambuf * setbuf(char *, int);
+ PRfilebuf* rdbuf() { return (PRfilebuf*) ios::rdbuf(); }
+
+ void attach(PRFileDesc *);
+ PRFileDesc *fd() {return rdbuf()->fd();}
+
+ int is_open(){return rdbuf()->is_open();}
+ void open(const char *, int =ios::out, int = 0);
+ void close();
+};
+
+class PR_IMPLEMENT(PRfstream) : public iostream {
+public:
+ PRfstream();
+ PRfstream(const char *name, int mode, int flags= 0);
+ PRfstream(PRFileDesc *fd);
+ PRfstream(PRFileDesc *fd, char *buff, int bufflen);
+ ~PRfstream();
+
+ streambuf * setbuf(char *, int);
+ PRfilebuf* rdbuf(){ return (PRfilebuf*) ostream::rdbuf(); }
+
+ void attach(PRFileDesc *);
+ PRFileDesc *fd() { return rdbuf()->fd(); }
+
+ int is_open() { return rdbuf()->is_open(); }
+ void open(const char *, int, int = 0);
+ void close();
+};
+
+#endif
+
+#endif /* _PRSTRMS_H */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.rc b/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.rc
new file mode 100644
index 00000000..589a64d1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/prstrms.rc
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "prstrms"
+#define MY_FILEDESCRIPTION "PRSTRMS Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in
new file mode 100644
index 00000000..1b682ff8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in
@@ -0,0 +1,254 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_TARGET), WIN16)
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+endif
+
+CXXSRCS = \
+ testprstrm.cpp \
+ $(NULL)
+
+OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CXXSRCS:.cpp=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS) $(OBJS)
+
+INCLUDES = -I$(dist_includedir)
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)
+LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION)
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+ LIBPRSTRMS = $(dist_libdir)/prstrms$(MOD_MAJOR_VERSION).lib
+else
+ LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+ ifeq ($(OS_TARGET), WIN95)
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPRSTRMS = $(dist_libdir)/prstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ else
+ LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPRSTRMS = $(dist_libdir)/libprstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ endif
+endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO /S:32768
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+ LIBPRSTRMS = $(dist_libdir)/prstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ else
+ LDOPTS += -Zomf -Zlinker /PM:VIO -lstdcpp
+ endif
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+LDOPTS += -rpath $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), OSF1)
+LDOPTS += -rpath $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr
+LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION)_shr
+else
+LDOPTS += -brtl
+EXTRA_LIBS = -ldl
+endif
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ifneq ($(OS_RELEASE), 4.1.3_U1)
+ifdef NS_USE_GCC
+LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+else
+LDOPTS += -R $(PWD)/$(dist_libdir)
+# CC on SunOS 5.4 and 5.5.x need to link with -lthread or -lpthread
+# (or use the -mt switch) even though we already linked with these
+# system libraries when we built libnspr.so.
+ifdef USE_PTHREADS
+EXTRA_LIBS = -lpthread
+else
+EXTRA_LIBS = -lthread
+endif # USE_PTHREADS
+endif # NS_USE_GCC
+endif # 4.1.3_U1
+endif # SunOS
+
+ifeq ($(OS_ARCH), NCR)
+# XXX: We see some strange problems when we link with libnspr.so.
+# So for now we use static libraries on NCR. The shared library
+# stuff below is commented out.
+LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+LIBPRSTRMS = $(dist_libdir)/libprstrms$(MOD_MAJOR_VERSION).a
+EXTRA_LIBS = -lsocket -lnsl -ldl
+
+# NCR needs to link against -lsocket -lnsl (and -lc, which is linked
+# implicitly by $(CC)) again even though we already linked with these
+# system libraries when we built libnspr.so.
+#EXTRA_LIBS = -lsocket -lnsl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+#export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), SCOOS)
+# SCO Unix needs to link against -lsocket again even though we
+# already linked with these system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET),WIN16)
+ echo system windows >w16link
+ echo option map >>w16link
+ echo option stack=10K >>w16link
+ echo option heapsize=32K >>w16link
+ echo debug $(DEBUGTYPE) all >>w16link
+ echo name $@ >>w16link
+ echo file >>w16link
+ echo $< >>w16link
+ echo library >>w16link
+ echo $(LIBPR), >>w16link
+ echo $(LIBPRSTRMS), >>w16link
+ echo winsock.lib >>w16link
+ wlink @w16link.
+else
+ link $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) wsock32.lib -out:$@
+endif
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(CCC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPRSTRMS) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
+
+testlinker:
+ echo $(LINK)
diff --git a/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp b/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp
new file mode 100644
index 00000000..6e8b8665
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prstrms.h"
+#include "prio.h"
+#include <string.h>
+#include <stdio.h>
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+const unsigned int MaxCnt = 1;
+
+void threadwork(void *mytag);
+
+
+typedef struct threadarg {
+ void *mytag;
+} threadarg;
+
+void
+#ifdef XP_OS2_VACPP
+_Optlink
+#endif
+threadmain(void *mytag)
+{
+ threadarg arg;
+
+ arg.mytag = mytag;
+
+ threadwork(&arg);
+}
+
+
+void
+threadwork(void *_arg)
+{
+ threadarg *arg = (threadarg *)_arg;
+ unsigned int i;
+
+ char fname1[256];
+ char fname2[256];
+
+ strcpy(fname1, (char *)arg->mytag);
+ strcpy(fname2, (char *)arg->mytag);
+ strcat(fname2, "2");
+ PR_Delete(fname1);
+ PR_Delete(fname2);
+
+ PRfilebuf *fb[MaxCnt];
+ PRifstream *ifs[MaxCnt];
+ PRofstream *ofs[MaxCnt];
+ int mode = 0;
+#ifdef XP_UNIX
+ mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IRGRP|S_IWOTH|S_IROTH;
+#endif
+
+ //
+ // Allocate a bunch
+ cout << "Testing unused filebufs ----------------" << endl;
+ for (i=0; i < MaxCnt; i++){
+ fb[i] = new PRfilebuf;
+ }
+ // Delete them
+ for (i=0; i < MaxCnt; i++){
+ delete fb[i];
+ }
+ cout << "Unused filebufs complete ---------------" << endl;
+
+ //
+ // Allocate a bunch
+ cout << "Testing unused ifstream -----------------" << endl;
+ for (i=0; i < MaxCnt; i++){
+ ifs[i] = new PRifstream;
+ }
+ //
+ // Delete them
+ for (i=0; i < MaxCnt; i++){
+ delete ifs[i];
+ }
+ cout << "Unused ifstream complete ----------------" << endl;
+ //
+ // Allocate a bunch
+ cout << "Testing unused ofstream -----------------" << endl;
+ for (i=0; i < MaxCnt; i++){
+ ofs[i] = new PRofstream;
+ }
+ for (i=0; i < MaxCnt; i++){
+ *(ofs[i]) << "A"; // Write a bit
+ delete ofs[i]; // Delete it.
+ }
+ cout << "Unused ofstream complete ----------------" << endl;
+
+ cout << "Testing use of ofstream 1 (extra filebuf allocated) ---------" << endl;
+ PRofstream *aos = new PRofstream(fname1, ios::out|ios::ate, mode);
+ for (i=0; i < MaxCnt; i++){
+ for (int j=0; j < 8192; j++)
+ *aos << "AaBbCcDdEeFfGg" << endl;
+ fb[i] = new PRfilebuf; // Allocate as we go to hack at the heap
+ }
+ //
+ // Delete the extra foo we allocated
+ for (i=0; i < MaxCnt; i++){
+ delete fb[i];
+ }
+ aos->flush(); // Explicit flush
+ delete aos;
+ cout << "Testing use of ofstream 1 complete (extra filebuf deleted) --" << endl;
+ cout << "Testing use of ofstream 2 (extra filebuf allocated) ---------" << endl;
+ PRofstream *aos2 = new PRofstream(fname2, ios::out, mode);
+
+ for (i=0; i < MaxCnt; i++){
+ *aos2 << "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+ }
+ // Force flushing in the dtor
+ delete aos2;
+ cout << "Testing use of ofstream 2 complete (extra filebuf deleted) --" << endl;
+ char line[1024];
+ cout << "Testing use of ifstream 1 (stack allocation) -------------" << endl;
+ PRifstream ais(fname1);
+ for (i=0; i < MaxCnt; i++){
+ ais >> line;
+ }
+ cout << "Testing use of ifstream 1 complete -----------------------" << endl;
+ cout << "Testing use of ifstream 2 ----------------------" << endl;
+ PRifstream *ais2 = new PRifstream(fname2);
+ char achar;
+ for (i=0; i < MaxCnt*10; i++){
+ *ais2 >> achar;
+ }
+ delete ais2;
+ cout << "Testing use of ifstream 2 complete -------------" << endl;
+}
+
+#define STACKSIZE 1024*1024
+int
+main(int argc, char **argv)
+{
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 256);
+ threadmain("TestFile");
+ PRThread *thr1 = PR_CreateThread(PR_SYSTEM_THREAD,
+ threadmain,
+ (void *)"TestFile1",
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ STACKSIZE);
+ PRThread *thr2 = PR_CreateThread(PR_SYSTEM_THREAD,
+ threadmain,
+ (void *)"TestFile2",
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ STACKSIZE);
+
+ PRThread *thr3 = PR_CreateThread(PR_SYSTEM_THREAD,
+ threadmain,
+ (void *)"TestFile3",
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ STACKSIZE);
+ PR_JoinThread(thr1);
+ PR_JoinThread(thr2);
+ PR_JoinThread(thr3);
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/.cvsignore b/src/libs/xpcom18a4/nsprpub/lib/tests/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/Makefile.in b/src/libs/xpcom18a4/nsprpub/lib/tests/Makefile.in
new file mode 100644
index 00000000..8c3dc9a8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/Makefile.in
@@ -0,0 +1,259 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_ARCH), WINNT)
+# DIRS = windows
+endif
+
+ifeq ($(OS_TARGET), WIN16)
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+endif
+
+CSRCS = \
+ arena.c \
+ string.c \
+ base64t.c
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+CSRCS += arena.c
+endif
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS) $(OBJS)
+
+INCLUDES = -I$(dist_includedir)
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)
+LIBPLC = -lplc$(MOD_MAJOR_VERSION)
+LIBPLDS = -lplds$(MOD_MAJOR_VERSION)
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+ LIBPLC= $(dist_libdir)/plc$(MOD_MAJOR_VERSION).lib
+ LIBPLDS= $(dist_libdir)/plds$(MOD_MAJOR_VERSION).lib
+else
+ LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+ ifeq ($(OS_TARGET), WIN95)
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLC= $(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLDS= $(dist_libdir)/plds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ else
+ LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLC= $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPLDS= $(dist_libdir)/libplds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ endif
+endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO /S:32768
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+ LIBPLC = $(dist_libdir)/plc$(MOD_MAJOR_VERSION).lib
+ LIBPLDS= $(dist_libdir)/plds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ else
+ LDOPTS += -Zomf -Zlinker /PM:VIO
+ endif
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+LDOPTS += -rpath $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), Linux)
+ ifeq ($(OS_RELEASE), 1.2)
+ EXTRA_LIBS = -ldl
+ else
+ LDOPTS += -Xlinker -rpath $(PWD)/$(dist_libdir)
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), OSF1)
+LDOPTS += -rpath $(PWD)/$(dist_libdir) -lpthread
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr
+LIBPLC = -lplc$(MOD_MAJOR_VERSION)_shr
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ifneq ($(OS_RELEASE), 4.1.3_U1)
+ifdef NS_USE_GCC
+LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+else
+LDOPTS += -R $(PWD)/$(dist_libdir)
+endif
+endif
+
+# SunOS 5.4 and 5.5 need to link with -lthread or -lpthread,
+# even though we already linked with these system libraries
+# when we built libnspr.so.
+ifeq ($(OS_RELEASE), 5.4)
+EXTRA_LIBS = -lthread
+endif
+
+ifeq ($(OS_RELEASE), 5.5)
+ifdef USE_PTHREADS
+EXTRA_LIBS = -lpthread
+else
+EXTRA_LIBS = -lthread
+endif
+endif
+endif # SunOS
+
+ifeq ($(OS_ARCH), NCR)
+# NCR needs to link against -lsocket -lnsl (and -lc, which is linked
+# implicitly by $(CC)) again even though we already linked with these
+# system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket -lnsl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET),WIN16)
+ echo system windows >w16link
+ echo option map >>w16link
+ echo option stack=10K >>w16link
+ echo option heapsize=32K >>w16link
+ echo debug $(DEBUGTYPE) all >>w16link
+ echo name $@ >>w16link
+ echo file >>w16link
+ echo $< >>w16link
+ echo library >>w16link
+ echo $(LIBPR), >>w16link
+ echo $(LIBPLC), >>w16link
+ echo winsock.lib >>w16link
+ wlink @w16link.
+else
+ link $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) wsock32.lib -out:$@
+endif
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPLDS) $(LIBPR) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/arena.c b/src/libs/xpcom18a4/nsprpub/lib/tests/arena.c
new file mode 100644
index 00000000..9c74479c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/arena.c
@@ -0,0 +1,401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: arena.c
+** Description: Testing arenas
+**
+*/
+
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include "nspr.h"
+#include "plarena.h"
+#include "plgetopt.h"
+
+PRLogModuleInfo *tLM;
+PRIntn threadCount = 0;
+PRMonitor *tMon;
+PRBool failed_already = PR_FALSE;
+
+/* Arguments from the command line with default values */
+PRIntn debug_mode = 0;
+PRIntn poolMin = 4096;
+PRIntn poolMax = (100 * 4096);
+PRIntn arenaMin = 40;
+PRIntn arenaMax = (100 * 40);
+PRIntn stressIterations = 15;
+PRIntn maxAlloc = (1024 * 1024);
+PRIntn stressThreads = 4;
+
+void DumpAll( void )
+{
+ return;
+}
+
+/*
+** Test Arena allocation.
+*/
+static void ArenaAllocate( void )
+{
+ PLArenaPool ap;
+ void *ptr;
+ PRInt32 i;
+
+ PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double));
+ PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d",
+ &ap, ap.first, ap.current, ap.arenasize ));
+
+ for( i = 0; i < 150; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
+ &ap, ap.first, ap.current, ap.arenasize ));
+ PR_LOG( tLM, PR_LOG_DEBUG,(
+ "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
+ }
+
+ PL_FreeArenaPool( &ap );
+
+ for( i = 0; i < 221; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d",
+ &ap, ap.first, ap.current, ap.arenasize ));
+ PR_LOG( tLM, PR_LOG_DEBUG,(
+ "AA -- Pool: %p. alloc: %p ", &ap, ptr ));
+ }
+
+ PL_FreeArenaPool( &ap );
+
+ return;
+} /* end ArenaGrow() */
+/*
+** Test Arena grow.
+*/
+static void ArenaGrow( void )
+{
+ PLArenaPool ap;
+ void *ptr;
+ PRInt32 i;
+
+ PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr ));
+
+ for( i = 0; i < 10; i++ )
+ {
+ PL_ARENA_GROW( ptr, &ap, 512, 7000 );
+ PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr ));
+ }
+
+
+ return;
+} /* end ArenaGrow() */
+
+
+/*
+** Test arena Mark and Release.
+*/
+static void MarkAndRelease( void )
+{
+ PLArenaPool ap;
+ void *ptr = NULL;
+ void *mark0, *mark1;
+ PRIntn i;
+
+ PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double));
+ mark0 = PL_ARENA_MARK( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 ));
+
+ for( i = 0; i < 201; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+ }
+
+ mark1 = PL_ARENA_MARK( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 ));
+
+
+ for( i = 0; i < 225; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+ }
+
+ PL_ARENA_RELEASE( &ap, mark1 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d",
+ mark1, &ap, ap.first, ap.current, ap.arenasize ));
+
+ for( i = 0; i < 20; i++ )
+ {
+ PL_ARENA_ALLOCATE( ptr, &ap, 512 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+ }
+
+ PL_ARENA_RELEASE( &ap, mark1 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ PL_ARENA_RELEASE( &ap, mark0 );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ PL_FreeArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ PL_FinishArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG,
+ ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p",
+ &ap, ap.first.next, ap.current, ap.arenasize, ptr ));
+
+ return;
+} /* end MarkAndRelease() */
+
+/*
+** RandSize() returns a random number in the range
+** min..max, rounded to the next doubleword
+**
+*/
+static PRIntn RandSize( PRIntn min, PRIntn max )
+{
+ PRIntn sz = (rand() % (max -min)) + min + sizeof(double);
+
+ sz &= ~sizeof(double)-1;
+
+ return(sz);
+}
+
+
+/*
+** StressThread()
+** A bunch of these beat on individual arenas
+** This tests the free_list protection.
+**
+*/
+static void PR_CALLBACK StressThread( void *arg )
+{
+ PLArenaPool ap;
+ PRIntn i;
+ PRIntn sz;
+ void *ptr;
+ PRThread *tp = PR_GetCurrentThread();
+
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread()));
+ PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double));
+
+ for ( i = 0; i < stressIterations; i++ )
+ {
+ PRIntn allocated = 0;
+
+ while ( allocated < maxAlloc )
+ {
+ sz = RandSize( arenaMin, arenaMax );
+ PL_ARENA_ALLOCATE( ptr, &ap, sz );
+ if ( ptr == NULL )
+ {
+ PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated));
+ break;
+ }
+ allocated += sz;
+ }
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp));
+ PL_FreeArenaPool( &ap );
+ }
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp));
+ PL_FinishArenaPool( &ap );
+ PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp));
+
+ /* That's all folks! let's quit */
+ PR_EnterMonitor(tMon);
+ threadCount--;
+ PR_Notify(tMon);
+ PR_ExitMonitor(tMon);
+ return;
+}
+
+/*
+** Stress()
+** Flog the hell out of arenas multi-threaded.
+** Do NOT pass an individual arena to another thread.
+**
+*/
+static void Stress( void )
+{
+ PRThread *tt;
+ PRIntn i;
+
+ tMon = PR_NewMonitor();
+
+ for ( i = 0 ; i < stressThreads ; i++ )
+ {
+ PR_EnterMonitor(tMon);
+ tt = PR_CreateThread(PR_USER_THREAD,
+ StressThread,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ threadCount++;
+ PR_ExitMonitor(tMon);
+ }
+
+ /* Wait for all threads to exit */
+ PR_EnterMonitor(tMon);
+ while ( threadCount != 0 )
+ {
+ PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(tMon);
+ PR_DestroyMonitor(tMon);
+
+ return;
+} /* end Stress() */
+
+/*
+** EvaluateResults()
+** uses failed_already to display results and set program
+** exit code.
+*/
+static PRIntn EvaluateResults(void)
+{
+ PRIntn rc = 0;
+
+ if ( failed_already == PR_TRUE )
+ {
+ PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n"));
+ rc =1;
+ }
+ else
+ {
+ PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n"));
+ }
+ return(rc);
+} /* EvaluateResults() */
+
+void Help( void )
+{
+ printf("arena [options]\n");
+ printf("where options are:\n");
+ printf("-p <n> minimum size of an arena pool. Default(%d)\n", poolMin);
+ printf("-P <n> maximum size of an arena pool. Default(%d)\n", poolMax);
+ printf("-a <n> minimum size of an arena allocation. Default(%d)\n", arenaMin);
+ printf("-A <n> maximum size of an arena allocation. Default(%d)\n", arenaMax);
+ printf("-i <n> number of iterations in a stress thread. Default(%d)\n", stressIterations);
+ printf("-s <n> maximum allocation for a single stress thread. Default(%d)\n", maxAlloc);
+ printf("-t <n> number of stress threads. Default(%d)\n", stressThreads );
+ printf("-d enable debug mode\n");
+ printf("\n");
+ exit(1);
+}
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'a': /* arena Min size */
+ arenaMin = atol( opt->value );
+ break;
+ case 'A': /* arena Max size */
+ arenaMax = atol( opt->value );
+ break;
+ case 'p': /* pool Min size */
+ poolMin = atol( opt->value );
+ break;
+ case 'P': /* pool Max size */
+ poolMax = atol( opt->value );
+ break;
+ case 'i': /* Iterations in stress tests */
+ stressIterations = atol( opt->value );
+ break;
+ case 's': /* storage to get per iteration */
+ maxAlloc = atol( opt->value );
+ break;
+ case 't': /* Number of stress threads to create */
+ stressThreads = atol( opt->value );
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'h': /* help */
+ default:
+ Help();
+ } /* end switch() */
+ } /* end while() */
+ PL_DestroyOptState(opt);
+
+ srand( (unsigned)time( NULL ) ); /* seed random number generator */
+ tLM = PR_NewLogModule("testcase");
+
+
+#if 0
+ ArenaAllocate();
+ ArenaGrow();
+#endif
+
+ MarkAndRelease();
+
+ Stress();
+
+ return(EvaluateResults());
+} /* end main() */
+
+/* arena.c */
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/base64t.c b/src/libs/xpcom18a4/nsprpub/lib/tests/base64t.c
new file mode 100644
index 00000000..c3c48813
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/base64t.c
@@ -0,0 +1,3047 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plbase64.h"
+#include "plstr.h"
+#include "nspr.h"
+
+#include <stdio.h>
+
+static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* PL_Base64Encode, single characters */
+PRBool test_001(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 001 (PL_Base64Encode, single characters) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Encode((char *)plain, 1, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d): return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)cypher, result, 4) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, double characters */
+PRBool test_002(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 002 (PL_Base64Encode, double characters) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Encode((char *)plain, 2, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)cypher, result, 4) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, c, d, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, triple characters */
+PRBool test_003(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 003 (PL_Base64Encode, triple characters) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Encode((char *)plain, 3, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)cypher, result, 4) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, c, d, e, f, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+ static struct
+ {
+ const char *plaintext;
+ const char *cyphertext;
+ } array[] =
+ {
+ /* Cyphertexts generated with uuenview 0.5.13 */
+ { " ", "IA==" },
+ { ".", "Lg==" },
+ { "/", "Lw==" },
+ { "C", "Qw==" },
+ { "H", "SA==" },
+ { "S", "Uw==" },
+ { "^", "Xg==" },
+ { "a", "YQ==" },
+ { "o", "bw==" },
+ { "t", "dA==" },
+
+ { "AB", "QUI=" },
+ { "AH", "QUg=" },
+ { "AQ", "QVE=" },
+ { "BD", "QkQ=" },
+ { "CR", "Q1I=" },
+ { "CS", "Q1M=" },
+ { "DB", "REI=" },
+ { "DC", "REM=" },
+ { "EK", "RUs=" },
+ { "ET", "RVQ=" },
+ { "IM", "SU0=" },
+ { "JR", "SlI=" },
+ { "LO", "TE8=" },
+ { "LW", "TFc=" },
+ { "ML", "TUw=" },
+ { "SB", "U0I=" },
+ { "TO", "VE8=" },
+ { "VS", "VlM=" },
+ { "WP", "V1A=" },
+ /* legitimate two-letter words */
+ { "ad", "YWQ=" },
+ { "ah", "YWg=" },
+ { "am", "YW0=" },
+ { "an", "YW4=" },
+ { "as", "YXM=" },
+ { "at", "YXQ=" },
+ { "ax", "YXg=" },
+ { "be", "YmU=" },
+ { "by", "Ynk=" },
+ { "do", "ZG8=" },
+ { "go", "Z28=" },
+ { "he", "aGU=" },
+ { "hi", "aGk=" },
+ { "if", "aWY=" },
+ { "in", "aW4=" },
+ { "is", "aXM=" },
+ { "it", "aXQ=" },
+ { "me", "bWU=" },
+ { "my", "bXk=" },
+ { "no", "bm8=" },
+ { "of", "b2Y=" },
+ { "on", "b24=" },
+ { "or", "b3I=" },
+ { "ox", "b3g=" },
+ { "so", "c28=" },
+ { "to", "dG8=" },
+ { "up", "dXA=" },
+ { "us", "dXM=" },
+ { "we", "d2U=" },
+ /* all three-letter entries in /usr/dict/words */
+ { "1st", "MXN0" },
+ { "2nd", "Mm5k" },
+ { "3rd", "M3Jk" },
+ { "4th", "NHRo" },
+ { "5th", "NXRo" },
+ { "6th", "NnRo" },
+ { "7th", "N3Ro" },
+ { "8th", "OHRo" },
+ { "9th", "OXRo" },
+ { "AAA", "QUFB" },
+ { "AAU", "QUFV" },
+ { "ABA", "QUJB" },
+ { "abc", "YWJj" },
+ { "Abe", "QWJl" },
+ { "Abo", "QWJv" },
+ { "ace", "YWNl" },
+ { "ACM", "QUNN" },
+ { "ACS", "QUNT" },
+ { "act", "YWN0" },
+ { "Ada", "QWRh" },
+ { "add", "YWRk" },
+ { "ado", "YWRv" },
+ { "aft", "YWZ0" },
+ { "age", "YWdl" },
+ { "ago", "YWdv" },
+ { "aid", "YWlk" },
+ { "ail", "YWls" },
+ { "aim", "YWlt" },
+ { "air", "YWly" },
+ { "ala", "YWxh" },
+ { "alb", "YWxi" },
+ { "ale", "YWxl" },
+ { "Ali", "QWxp" },
+ { "all", "YWxs" },
+ { "alp", "YWxw" },
+ { "A&M", "QSZN" },
+ { "AMA", "QU1B" },
+ { "ami", "YW1p" },
+ { "amp", "YW1w" },
+ { "Amy", "QW15" },
+ { "amy", "YW15" },
+ { "ana", "YW5h" },
+ { "and", "YW5k" },
+ { "ani", "YW5p" },
+ { "Ann", "QW5u" },
+ { "ant", "YW50" },
+ { "any", "YW55" },
+ { "A&P", "QSZQ" },
+ { "ape", "YXBl" },
+ { "Apr", "QXBy" },
+ { "APS", "QVBT" },
+ { "apt", "YXB0" },
+ { "arc", "YXJj" },
+ { "are", "YXJl" },
+ { "ark", "YXJr" },
+ { "arm", "YXJt" },
+ { "art", "YXJ0" },
+ { "a's", "YSdz" },
+ { "ash", "YXNo" },
+ { "ask", "YXNr" },
+ { "ass", "YXNz" },
+ { "ate", "YXRl" },
+ { "Aug", "QXVn" },
+ { "auk", "YXVr" },
+ { "Ave", "QXZl" },
+ { "awe", "YXdl" },
+ { "awl", "YXds" },
+ { "awn", "YXdu" },
+ { "axe", "YXhl" },
+ { "aye", "YXll" },
+ { "bad", "YmFk" },
+ { "bag", "YmFn" },
+ { "bah", "YmFo" },
+ { "bam", "YmFt" },
+ { "ban", "YmFu" },
+ { "bar", "YmFy" },
+ { "bat", "YmF0" },
+ { "bay", "YmF5" },
+ { "bed", "YmVk" },
+ { "bee", "YmVl" },
+ { "beg", "YmVn" },
+ { "bel", "YmVs" },
+ { "Ben", "QmVu" },
+ { "bet", "YmV0" },
+ { "bey", "YmV5" },
+ { "bib", "Ymli" },
+ { "bid", "Ymlk" },
+ { "big", "Ymln" },
+ { "bin", "Ymlu" },
+ { "bit", "Yml0" },
+ { "biz", "Yml6" },
+ { "BMW", "Qk1X" },
+ { "boa", "Ym9h" },
+ { "bob", "Ym9i" },
+ { "bog", "Ym9n" },
+ { "bon", "Ym9u" },
+ { "boo", "Ym9v" },
+ { "bop", "Ym9w" },
+ { "bow", "Ym93" },
+ { "box", "Ym94" },
+ { "boy", "Ym95" },
+ { "b's", "Yidz" },
+ { "BTL", "QlRM" },
+ { "BTU", "QlRV" },
+ { "bub", "YnVi" },
+ { "bud", "YnVk" },
+ { "bug", "YnVn" },
+ { "bum", "YnVt" },
+ { "bun", "YnVu" },
+ { "bus", "YnVz" },
+ { "but", "YnV0" },
+ { "buy", "YnV5" },
+ { "bye", "Ynll" },
+ { "cab", "Y2Fi" },
+ { "Cal", "Q2Fs" },
+ { "cam", "Y2Ft" },
+ { "can", "Y2Fu" },
+ { "cap", "Y2Fw" },
+ { "car", "Y2Fy" },
+ { "cat", "Y2F0" },
+ { "caw", "Y2F3" },
+ { "CBS", "Q0JT" },
+ { "CDC", "Q0RD" },
+ { "CEQ", "Q0VR" },
+ { "chi", "Y2hp" },
+ { "CIA", "Q0lB" },
+ { "cit", "Y2l0" },
+ { "cod", "Y29k" },
+ { "cog", "Y29n" },
+ { "col", "Y29s" },
+ { "con", "Y29u" },
+ { "coo", "Y29v" },
+ { "cop", "Y29w" },
+ { "cos", "Y29z" },
+ { "cot", "Y290" },
+ { "cow", "Y293" },
+ { "cox", "Y294" },
+ { "coy", "Y295" },
+ { "CPA", "Q1BB" },
+ { "cpu", "Y3B1" },
+ { "CRT", "Q1JU" },
+ { "cry", "Y3J5" },
+ { "c's", "Yydz" },
+ { "cub", "Y3Vi" },
+ { "cud", "Y3Vk" },
+ { "cue", "Y3Vl" },
+ { "cup", "Y3Vw" },
+ { "cur", "Y3Vy" },
+ { "cut", "Y3V0" },
+ { "dab", "ZGFi" },
+ { "dad", "ZGFk" },
+ { "dam", "ZGFt" },
+ { "Dan", "RGFu" },
+ { "Dar", "RGFy" },
+ { "day", "ZGF5" },
+ { "Dec", "RGVj" },
+ { "Dee", "RGVl" },
+ { "Del", "RGVs" },
+ { "den", "ZGVu" },
+ { "Des", "RGVz" },
+ { "dew", "ZGV3" },
+ { "dey", "ZGV5" },
+ { "did", "ZGlk" },
+ { "die", "ZGll" },
+ { "dig", "ZGln" },
+ { "dim", "ZGlt" },
+ { "din", "ZGlu" },
+ { "dip", "ZGlw" },
+ { "Dis", "RGlz" },
+ { "DNA", "RE5B" },
+ { "DOD", "RE9E" },
+ { "doe", "ZG9l" },
+ { "dog", "ZG9n" },
+ { "don", "ZG9u" },
+ { "dot", "ZG90" },
+ { "Dow", "RG93" },
+ { "dry", "ZHJ5" },
+ { "d's", "ZCdz" },
+ { "dub", "ZHVi" },
+ { "dud", "ZHVk" },
+ { "due", "ZHVl" },
+ { "dug", "ZHVn" },
+ { "dun", "ZHVu" },
+ { "dye", "ZHll" },
+ { "ear", "ZWFy" },
+ { "eat", "ZWF0" },
+ { "ebb", "ZWJi" },
+ { "EDT", "RURU" },
+ { "eel", "ZWVs" },
+ { "eft", "ZWZ0" },
+ { "e.g", "ZS5n" },
+ { "egg", "ZWdn" },
+ { "ego", "ZWdv" },
+ { "eke", "ZWtl" },
+ { "Eli", "RWxp" },
+ { "elk", "ZWxr" },
+ { "ell", "ZWxs" },
+ { "elm", "ZWxt" },
+ { "Ely", "RWx5" },
+ { "end", "ZW5k" },
+ { "Eng", "RW5n" },
+ { "EPA", "RVBB" },
+ { "era", "ZXJh" },
+ { "ere", "ZXJl" },
+ { "erg", "ZXJn" },
+ { "err", "ZXJy" },
+ { "e's", "ZSdz" },
+ { "EST", "RVNU" },
+ { "eta", "ZXRh" },
+ { "etc", "ZXRj" },
+ { "Eva", "RXZh" },
+ { "eve", "ZXZl" },
+ { "ewe", "ZXdl" },
+ { "eye", "ZXll" },
+ { "FAA", "RkFB" },
+ { "fad", "ZmFk" },
+ { "fag", "ZmFn" },
+ { "fan", "ZmFu" },
+ { "far", "ZmFy" },
+ { "fat", "ZmF0" },
+ { "fay", "ZmF5" },
+ { "FBI", "RkJJ" },
+ { "FCC", "RkND" },
+ { "FDA", "RkRB" },
+ { "Feb", "RmVi" },
+ { "fed", "ZmVk" },
+ { "fee", "ZmVl" },
+ { "few", "ZmV3" },
+ { "fib", "Zmli" },
+ { "fig", "Zmln" },
+ { "fin", "Zmlu" },
+ { "fir", "Zmly" },
+ { "fit", "Zml0" },
+ { "fix", "Zml4" },
+ { "Flo", "Rmxv" },
+ { "flu", "Zmx1" },
+ { "fly", "Zmx5" },
+ { "FMC", "Rk1D" },
+ { "fob", "Zm9i" },
+ { "foe", "Zm9l" },
+ { "fog", "Zm9n" },
+ { "fop", "Zm9w" },
+ { "for", "Zm9y" },
+ { "fox", "Zm94" },
+ { "FPC", "RlBD" },
+ { "fro", "ZnJv" },
+ { "fry", "ZnJ5" },
+ { "f's", "Zidz" },
+ { "FTC", "RlRD" },
+ { "fum", "ZnVt" },
+ { "fun", "ZnVu" },
+ { "fur", "ZnVy" },
+ { "gab", "Z2Fi" },
+ { "gad", "Z2Fk" },
+ { "gag", "Z2Fn" },
+ { "gal", "Z2Fs" },
+ { "gam", "Z2Ft" },
+ { "GAO", "R0FP" },
+ { "gap", "Z2Fw" },
+ { "gar", "Z2Fy" },
+ { "gas", "Z2Fz" },
+ { "gay", "Z2F5" },
+ { "gee", "Z2Vl" },
+ { "gel", "Z2Vs" },
+ { "gem", "Z2Vt" },
+ { "get", "Z2V0" },
+ { "gig", "Z2ln" },
+ { "Gil", "R2ls" },
+ { "gin", "Z2lu" },
+ { "GMT", "R01U" },
+ { "GNP", "R05Q" },
+ { "gnu", "Z251" },
+ { "Goa", "R29h" },
+ { "gob", "Z29i" },
+ { "god", "Z29k" },
+ { "gog", "Z29n" },
+ { "GOP", "R09Q" },
+ { "got", "Z290" },
+ { "GPO", "R1BP" },
+ { "g's", "Zydz" },
+ { "GSA", "R1NB" },
+ { "gum", "Z3Vt" },
+ { "gun", "Z3Vu" },
+ { "Gus", "R3Vz" },
+ { "gut", "Z3V0" },
+ { "guy", "Z3V5" },
+ { "gym", "Z3lt" },
+ { "gyp", "Z3lw" },
+ { "had", "aGFk" },
+ { "Hal", "SGFs" },
+ { "ham", "aGFt" },
+ { "Han", "SGFu" },
+ { "hap", "aGFw" },
+ { "hat", "aGF0" },
+ { "haw", "aGF3" },
+ { "hay", "aGF5" },
+ { "hem", "aGVt" },
+ { "hen", "aGVu" },
+ { "her", "aGVy" },
+ { "hew", "aGV3" },
+ { "hex", "aGV4" },
+ { "hey", "aGV5" },
+ { "hid", "aGlk" },
+ { "him", "aGlt" },
+ { "hip", "aGlw" },
+ { "his", "aGlz" },
+ { "hit", "aGl0" },
+ { "hob", "aG9i" },
+ { "hoc", "aG9j" },
+ { "hoe", "aG9l" },
+ { "hog", "aG9n" },
+ { "hoi", "aG9p" },
+ { "Hom", "SG9t" },
+ { "hop", "aG9w" },
+ { "hot", "aG90" },
+ { "how", "aG93" },
+ { "hoy", "aG95" },
+ { "h's", "aCdz" },
+ { "hub", "aHVi" },
+ { "hue", "aHVl" },
+ { "hug", "aHVn" },
+ { "huh", "aHVo" },
+ { "hum", "aHVt" },
+ { "Hun", "SHVu" },
+ { "hut", "aHV0" },
+ { "Ian", "SWFu" },
+ { "IBM", "SUJN" },
+ { "Ibn", "SWJu" },
+ { "ICC", "SUND" },
+ { "ice", "aWNl" },
+ { "icy", "aWN5" },
+ { "I'd", "SSdk" },
+ { "Ida", "SWRh" },
+ { "i.e", "aS5l" },
+ { "iii", "aWlp" },
+ { "Ike", "SWtl" },
+ { "ill", "aWxs" },
+ { "I'm", "SSdt" },
+ { "imp", "aW1w" },
+ { "Inc", "SW5j" },
+ { "ink", "aW5r" },
+ { "inn", "aW5u" },
+ { "ion", "aW9u" },
+ { "Ira", "SXJh" },
+ { "ire", "aXJl" },
+ { "irk", "aXJr" },
+ { "IRS", "SVJT" },
+ { "i's", "aSdz" },
+ { "Ito", "SXRv" },
+ { "ITT", "SVRU" },
+ { "ivy", "aXZ5" },
+ { "jab", "amFi" },
+ { "jag", "amFn" },
+ { "jam", "amFt" },
+ { "Jan", "SmFu" },
+ { "jar", "amFy" },
+ { "jaw", "amF3" },
+ { "jay", "amF5" },
+ { "Jed", "SmVk" },
+ { "jet", "amV0" },
+ { "Jew", "SmV3" },
+ { "jig", "amln" },
+ { "Jim", "Smlt" },
+ { "job", "am9i" },
+ { "Joe", "Sm9l" },
+ { "jog", "am9n" },
+ { "Jon", "Sm9u" },
+ { "jot", "am90" },
+ { "joy", "am95" },
+ { "j's", "aidz" },
+ { "jug", "anVn" },
+ { "jut", "anV0" },
+ { "Kay", "S2F5" },
+ { "keg", "a2Vn" },
+ { "ken", "a2Vu" },
+ { "key", "a2V5" },
+ { "kid", "a2lk" },
+ { "Kim", "S2lt" },
+ { "kin", "a2lu" },
+ { "kit", "a2l0" },
+ { "k's", "aydz" },
+ { "lab", "bGFi" },
+ { "lac", "bGFj" },
+ { "lad", "bGFk" },
+ { "lag", "bGFn" },
+ { "lam", "bGFt" },
+ { "Lao", "TGFv" },
+ { "lap", "bGFw" },
+ { "law", "bGF3" },
+ { "lax", "bGF4" },
+ { "lay", "bGF5" },
+ { "lea", "bGVh" },
+ { "led", "bGVk" },
+ { "lee", "bGVl" },
+ { "leg", "bGVn" },
+ { "Len", "TGVu" },
+ { "Leo", "TGVv" },
+ { "let", "bGV0" },
+ { "Lev", "TGV2" },
+ { "Lew", "TGV3" },
+ { "lew", "bGV3" },
+ { "lid", "bGlk" },
+ { "lie", "bGll" },
+ { "lim", "bGlt" },
+ { "Lin", "TGlu" },
+ { "lip", "bGlw" },
+ { "lit", "bGl0" },
+ { "Liz", "TGl6" },
+ { "lob", "bG9i" },
+ { "log", "bG9n" },
+ { "lop", "bG9w" },
+ { "Los", "TG9z" },
+ { "lot", "bG90" },
+ { "Lou", "TG91" },
+ { "low", "bG93" },
+ { "loy", "bG95" },
+ { "l's", "bCdz" },
+ { "LSI", "TFNJ" },
+ { "Ltd", "THRk" },
+ { "LTV", "TFRW" },
+ { "lug", "bHVn" },
+ { "lux", "bHV4" },
+ { "lye", "bHll" },
+ { "Mac", "TWFj" },
+ { "mad", "bWFk" },
+ { "Mae", "TWFl" },
+ { "man", "bWFu" },
+ { "Mao", "TWFv" },
+ { "map", "bWFw" },
+ { "mar", "bWFy" },
+ { "mat", "bWF0" },
+ { "maw", "bWF3" },
+ { "Max", "TWF4" },
+ { "max", "bWF4" },
+ { "may", "bWF5" },
+ { "MBA", "TUJB" },
+ { "Meg", "TWVn" },
+ { "Mel", "TWVs" },
+ { "men", "bWVu" },
+ { "met", "bWV0" },
+ { "mew", "bWV3" },
+ { "mid", "bWlk" },
+ { "mig", "bWln" },
+ { "min", "bWlu" },
+ { "MIT", "TUlU" },
+ { "mix", "bWl4" },
+ { "mob", "bW9i" },
+ { "Moe", "TW9l" },
+ { "moo", "bW9v" },
+ { "mop", "bW9w" },
+ { "mot", "bW90" },
+ { "mow", "bW93" },
+ { "MPH", "TVBI" },
+ { "Mrs", "TXJz" },
+ { "m's", "bSdz" },
+ { "mud", "bXVk" },
+ { "mug", "bXVn" },
+ { "mum", "bXVt" },
+ { "nab", "bmFi" },
+ { "nag", "bmFn" },
+ { "Nan", "TmFu" },
+ { "nap", "bmFw" },
+ { "Nat", "TmF0" },
+ { "nay", "bmF5" },
+ { "NBC", "TkJD" },
+ { "NBS", "TkJT" },
+ { "NCO", "TkNP" },
+ { "NCR", "TkNS" },
+ { "Ned", "TmVk" },
+ { "nee", "bmVl" },
+ { "net", "bmV0" },
+ { "new", "bmV3" },
+ { "nib", "bmli" },
+ { "NIH", "TklI" },
+ { "nil", "bmls" },
+ { "nip", "bmlw" },
+ { "nit", "bml0" },
+ { "NNE", "Tk5F" },
+ { "NNW", "Tk5X" },
+ { "nob", "bm9i" },
+ { "nod", "bm9k" },
+ { "non", "bm9u" },
+ { "nor", "bm9y" },
+ { "not", "bm90" },
+ { "Nov", "Tm92" },
+ { "now", "bm93" },
+ { "NRC", "TlJD" },
+ { "n's", "bidz" },
+ { "NSF", "TlNG" },
+ { "nun", "bnVu" },
+ { "nut", "bnV0" },
+ { "NYC", "TllD" },
+ { "NYU", "TllV" },
+ { "oaf", "b2Fm" },
+ { "oak", "b2Fr" },
+ { "oar", "b2Fy" },
+ { "oat", "b2F0" },
+ { "Oct", "T2N0" },
+ { "odd", "b2Rk" },
+ { "ode", "b2Rl" },
+ { "off", "b2Zm" },
+ { "oft", "b2Z0" },
+ { "ohm", "b2ht" },
+ { "oil", "b2ls" },
+ { "old", "b2xk" },
+ { "one", "b25l" },
+ { "opt", "b3B0" },
+ { "orb", "b3Ji" },
+ { "ore", "b3Jl" },
+ { "Orr", "T3Jy" },
+ { "o's", "bydz" },
+ { "Ott", "T3R0" },
+ { "our", "b3Vy" },
+ { "out", "b3V0" },
+ { "ova", "b3Zh" },
+ { "owe", "b3dl" },
+ { "owl", "b3ds" },
+ { "own", "b3du" },
+ { "pad", "cGFk" },
+ { "pal", "cGFs" },
+ { "Pam", "UGFt" },
+ { "pan", "cGFu" },
+ { "pap", "cGFw" },
+ { "par", "cGFy" },
+ { "pat", "cGF0" },
+ { "paw", "cGF3" },
+ { "pax", "cGF4" },
+ { "pay", "cGF5" },
+ { "Paz", "UGF6" },
+ { "PBS", "UEJT" },
+ { "PDP", "UERQ" },
+ { "pea", "cGVh" },
+ { "pee", "cGVl" },
+ { "peg", "cGVn" },
+ { "pen", "cGVu" },
+ { "pep", "cGVw" },
+ { "per", "cGVy" },
+ { "pet", "cGV0" },
+ { "pew", "cGV3" },
+ { "PhD", "UGhE" },
+ { "phi", "cGhp" },
+ { "pie", "cGll" },
+ { "pig", "cGln" },
+ { "pin", "cGlu" },
+ { "pip", "cGlw" },
+ { "pit", "cGl0" },
+ { "ply", "cGx5" },
+ { "pod", "cG9k" },
+ { "Poe", "UG9l" },
+ { "poi", "cG9p" },
+ { "pol", "cG9s" },
+ { "pop", "cG9w" },
+ { "pot", "cG90" },
+ { "pow", "cG93" },
+ { "ppm", "cHBt" },
+ { "pro", "cHJv" },
+ { "pry", "cHJ5" },
+ { "p's", "cCdz" },
+ { "psi", "cHNp" },
+ { "PTA", "UFRB" },
+ { "pub", "cHVi" },
+ { "PUC", "UFVD" },
+ { "pug", "cHVn" },
+ { "pun", "cHVu" },
+ { "pup", "cHVw" },
+ { "pus", "cHVz" },
+ { "put", "cHV0" },
+ { "PVC", "UFZD" },
+ { "QED", "UUVE" },
+ { "q's", "cSdz" },
+ { "qua", "cXVh" },
+ { "quo", "cXVv" },
+ { "Rae", "UmFl" },
+ { "rag", "cmFn" },
+ { "raj", "cmFq" },
+ { "ram", "cmFt" },
+ { "ran", "cmFu" },
+ { "rap", "cmFw" },
+ { "rat", "cmF0" },
+ { "raw", "cmF3" },
+ { "ray", "cmF5" },
+ { "RCA", "UkNB" },
+ { "R&D", "UiZE" },
+ { "reb", "cmVi" },
+ { "red", "cmVk" },
+ { "rep", "cmVw" },
+ { "ret", "cmV0" },
+ { "rev", "cmV2" },
+ { "Rex", "UmV4" },
+ { "rho", "cmhv" },
+ { "rib", "cmli" },
+ { "rid", "cmlk" },
+ { "rig", "cmln" },
+ { "rim", "cmlt" },
+ { "Rio", "Umlv" },
+ { "rip", "cmlw" },
+ { "RNA", "Uk5B" },
+ { "rob", "cm9i" },
+ { "rod", "cm9k" },
+ { "roe", "cm9l" },
+ { "Ron", "Um9u" },
+ { "rot", "cm90" },
+ { "row", "cm93" },
+ { "Roy", "Um95" },
+ { "RPM", "UlBN" },
+ { "r's", "cidz" },
+ { "rub", "cnVi" },
+ { "rue", "cnVl" },
+ { "rug", "cnVn" },
+ { "rum", "cnVt" },
+ { "run", "cnVu" },
+ { "rut", "cnV0" },
+ { "rye", "cnll" },
+ { "sac", "c2Fj" },
+ { "sad", "c2Fk" },
+ { "sag", "c2Fn" },
+ { "Sal", "U2Fs" },
+ { "Sam", "U2Ft" },
+ { "San", "U2Fu" },
+ { "Sao", "U2Fv" },
+ { "sap", "c2Fw" },
+ { "sat", "c2F0" },
+ { "saw", "c2F3" },
+ { "sax", "c2F4" },
+ { "say", "c2F5" },
+ { "Sci", "U2Np" },
+ { "SCM", "U0NN" },
+ { "sea", "c2Vh" },
+ { "sec", "c2Vj" },
+ { "see", "c2Vl" },
+ { "sen", "c2Vu" },
+ { "seq", "c2Vx" },
+ { "set", "c2V0" },
+ { "sew", "c2V3" },
+ { "sex", "c2V4" },
+ { "she", "c2hl" },
+ { "Shu", "U2h1" },
+ { "shy", "c2h5" },
+ { "sib", "c2li" },
+ { "sic", "c2lj" },
+ { "sin", "c2lu" },
+ { "sip", "c2lw" },
+ { "sir", "c2ly" },
+ { "sis", "c2lz" },
+ { "sit", "c2l0" },
+ { "six", "c2l4" },
+ { "ski", "c2tp" },
+ { "sky", "c2t5" },
+ { "sly", "c2x5" },
+ { "sob", "c29i" },
+ { "Soc", "U29j" },
+ { "sod", "c29k" },
+ { "Sol", "U29s" },
+ { "son", "c29u" },
+ { "sop", "c29w" },
+ { "sou", "c291" },
+ { "sow", "c293" },
+ { "soy", "c295" },
+ { "spa", "c3Bh" },
+ { "spy", "c3B5" },
+ { "Sri", "U3Jp" },
+ { "s's", "cydz" },
+ { "SSE", "U1NF" },
+ { "SST", "U1NU" },
+ { "SSW", "U1NX" },
+ { "Stu", "U3R1" },
+ { "sub", "c3Vi" },
+ { "sud", "c3Vk" },
+ { "sue", "c3Vl" },
+ { "sum", "c3Vt" },
+ { "sun", "c3Vu" },
+ { "sup", "c3Vw" },
+ { "Sus", "U3Vz" },
+ { "tab", "dGFi" },
+ { "tad", "dGFk" },
+ { "tag", "dGFn" },
+ { "tam", "dGFt" },
+ { "tan", "dGFu" },
+ { "tao", "dGFv" },
+ { "tap", "dGFw" },
+ { "tar", "dGFy" },
+ { "tat", "dGF0" },
+ { "tau", "dGF1" },
+ { "tax", "dGF4" },
+ { "tea", "dGVh" },
+ { "Ted", "VGVk" },
+ { "ted", "dGVk" },
+ { "tee", "dGVl" },
+ { "Tel", "VGVs" },
+ { "ten", "dGVu" },
+ { "the", "dGhl" },
+ { "thy", "dGh5" },
+ { "tic", "dGlj" },
+ { "tid", "dGlk" },
+ { "tie", "dGll" },
+ { "til", "dGls" },
+ { "Tim", "VGlt" },
+ { "tin", "dGlu" },
+ { "tip", "dGlw" },
+ { "tit", "dGl0" },
+ { "TNT", "VE5U" },
+ { "toe", "dG9l" },
+ { "tog", "dG9n" },
+ { "Tom", "VG9t" },
+ { "ton", "dG9u" },
+ { "too", "dG9v" },
+ { "top", "dG9w" },
+ { "tor", "dG9y" },
+ { "tot", "dG90" },
+ { "tow", "dG93" },
+ { "toy", "dG95" },
+ { "TRW", "VFJX" },
+ { "try", "dHJ5" },
+ { "t's", "dCdz" },
+ { "TTL", "VFRM" },
+ { "TTY", "VFRZ" },
+ { "tub", "dHVi" },
+ { "tug", "dHVn" },
+ { "tum", "dHVt" },
+ { "tun", "dHVu" },
+ { "TVA", "VFZB" },
+ { "TWA", "VFdB" },
+ { "two", "dHdv" },
+ { "TWX", "VFdY" },
+ { "ugh", "dWdo" },
+ { "UHF", "VUhG" },
+ { "Uri", "VXJp" },
+ { "urn", "dXJu" },
+ { "U.S", "VS5T" },
+ { "u's", "dSdz" },
+ { "USA", "VVNB" },
+ { "USC", "VVND" },
+ { "use", "dXNl" },
+ { "USN", "VVNO" },
+ { "van", "dmFu" },
+ { "vat", "dmF0" },
+ { "vee", "dmVl" },
+ { "vet", "dmV0" },
+ { "vex", "dmV4" },
+ { "VHF", "VkhG" },
+ { "via", "dmlh" },
+ { "vie", "dmll" },
+ { "vii", "dmlp" },
+ { "vis", "dmlz" },
+ { "viz", "dml6" },
+ { "von", "dm9u" },
+ { "vow", "dm93" },
+ { "v's", "didz" },
+ { "WAC", "V0FD" },
+ { "wad", "d2Fk" },
+ { "wag", "d2Fn" },
+ { "wah", "d2Fo" },
+ { "wan", "d2Fu" },
+ { "war", "d2Fy" },
+ { "was", "d2Fz" },
+ { "wax", "d2F4" },
+ { "way", "d2F5" },
+ { "web", "d2Vi" },
+ { "wed", "d2Vk" },
+ { "wee", "d2Vl" },
+ { "Wei", "V2Vp" },
+ { "wet", "d2V0" },
+ { "who", "d2hv" },
+ { "why", "d2h5" },
+ { "wig", "d2ln" },
+ { "win", "d2lu" },
+ { "wit", "d2l0" },
+ { "woe", "d29l" },
+ { "wok", "d29r" },
+ { "won", "d29u" },
+ { "woo", "d29v" },
+ { "wop", "d29w" },
+ { "wow", "d293" },
+ { "wry", "d3J5" },
+ { "w's", "dydz" },
+ { "x's", "eCdz" },
+ { "yah", "eWFo" },
+ { "yak", "eWFr" },
+ { "yam", "eWFt" },
+ { "yap", "eWFw" },
+ { "yaw", "eWF3" },
+ { "yea", "eWVh" },
+ { "yen", "eWVu" },
+ { "yet", "eWV0" },
+ { "yin", "eWlu" },
+ { "yip", "eWlw" },
+ { "yon", "eW9u" },
+ { "you", "eW91" },
+ { "yow", "eW93" },
+ { "y's", "eSdz" },
+ { "yuh", "eXVo" },
+ { "zag", "emFn" },
+ { "Zan", "WmFu" },
+ { "zap", "emFw" },
+ { "Zen", "WmVu" },
+ { "zig", "emln" },
+ { "zip", "emlw" },
+ { "Zoe", "Wm9l" },
+ { "zoo", "em9v" },
+ { "z's", "eidz" },
+ /* the false rumors file */
+ { "\"So when I die, the first thing I will see in heaven is a score list?\"",
+ "IlNvIHdoZW4gSSBkaWUsIHRoZSBmaXJzdCB0aGluZyBJIHdpbGwgc2VlIGluIGhlYXZlbiBpcyBhIHNjb3JlIGxpc3Q/Ig==" },
+ { "1st Law of Hacking: leaving is much more difficult than entering.",
+ "MXN0IExhdyBvZiBIYWNraW5nOiBsZWF2aW5nIGlzIG11Y2ggbW9yZSBkaWZmaWN1bHQgdGhhbiBlbnRlcmluZy4=" },
+ { "2nd Law of Hacking: first in, first out.",
+ "Mm5kIExhdyBvZiBIYWNraW5nOiBmaXJzdCBpbiwgZmlyc3Qgb3V0Lg==" },
+ { "3rd Law of Hacking: the last blow counts most.",
+ "M3JkIExhdyBvZiBIYWNraW5nOiB0aGUgbGFzdCBibG93IGNvdW50cyBtb3N0Lg==" },
+ { "4th Law of Hacking: you will find the exit at the entrance.",
+ "NHRoIExhdyBvZiBIYWNraW5nOiB5b3Ugd2lsbCBmaW5kIHRoZSBleGl0IGF0IHRoZSBlbnRyYW5jZS4=" },
+ { "A chameleon imitating a mail daemon often delivers scrolls of fire.",
+ "QSBjaGFtZWxlb24gaW1pdGF0aW5nIGEgbWFpbCBkYWVtb24gb2Z0ZW4gZGVsaXZlcnMgc2Nyb2xscyBvZiBmaXJlLg==" },
+ { "A cockatrice corpse is guaranteed to be untainted!",
+ "QSBjb2NrYXRyaWNlIGNvcnBzZSBpcyBndWFyYW50ZWVkIHRvIGJlIHVudGFpbnRlZCE=" },
+ { "A dead cockatrice is just a dead lizard.",
+ "QSBkZWFkIGNvY2thdHJpY2UgaXMganVzdCBhIGRlYWQgbGl6YXJkLg==" },
+ { "A dragon is just a snake that ate a scroll of fire.",
+ "QSBkcmFnb24gaXMganVzdCBhIHNuYWtlIHRoYXQgYXRlIGEgc2Nyb2xsIG9mIGZpcmUu" },
+ { "A fading corridor enlightens your insight.",
+ "QSBmYWRpbmcgY29ycmlkb3IgZW5saWdodGVucyB5b3VyIGluc2lnaHQu" },
+ { "A glowing potion is too hot to drink.",
+ "QSBnbG93aW5nIHBvdGlvbiBpcyB0b28gaG90IHRvIGRyaW5rLg==" },
+ { "A good amulet may protect you against guards.",
+ "QSBnb29kIGFtdWxldCBtYXkgcHJvdGVjdCB5b3UgYWdhaW5zdCBndWFyZHMu" },
+ { "A lizard corpse is a good thing to turn undead.",
+ "QSBsaXphcmQgY29ycHNlIGlzIGEgZ29vZCB0aGluZyB0byB0dXJuIHVuZGVhZC4=" },
+ { "A long worm can be defined recursively. So how should you attack it?",
+ "QSBsb25nIHdvcm0gY2FuIGJlIGRlZmluZWQgcmVjdXJzaXZlbHkuIFNvIGhvdyBzaG91bGQgeW91IGF0dGFjayBpdD8=" },
+ { "A monstrous mind is a toy forever.",
+ "QSBtb25zdHJvdXMgbWluZCBpcyBhIHRveSBmb3JldmVyLg==" },
+ { "A nymph will be very pleased if you call her by her real name: Lorelei.",
+ "QSBueW1waCB3aWxsIGJlIHZlcnkgcGxlYXNlZCBpZiB5b3UgY2FsbCBoZXIgYnkgaGVyIHJlYWwgbmFtZTogTG9yZWxlaS4=" },
+ { "A ring of dungeon master control is a great find.",
+ "QSByaW5nIG9mIGR1bmdlb24gbWFzdGVyIGNvbnRyb2wgaXMgYSBncmVhdCBmaW5kLg==" },
+ { "A ring of extra ring finger is useless if not enchanted.",
+ "QSByaW5nIG9mIGV4dHJhIHJpbmcgZmluZ2VyIGlzIHVzZWxlc3MgaWYgbm90IGVuY2hhbnRlZC4=" },
+ { "A rope may form a trail in a maze.",
+ "QSByb3BlIG1heSBmb3JtIGEgdHJhaWwgaW4gYSBtYXplLg==" },
+ { "A staff may recharge if you drop it for awhile.",
+ "QSBzdGFmZiBtYXkgcmVjaGFyZ2UgaWYgeW91IGRyb3AgaXQgZm9yIGF3aGlsZS4=" },
+ { "A visit to the Zoo is very educational; you meet interesting animals.",
+ "QSB2aXNpdCB0byB0aGUgWm9vIGlzIHZlcnkgZWR1Y2F0aW9uYWw7IHlvdSBtZWV0IGludGVyZXN0aW5nIGFuaW1hbHMu" },
+ { "A wand of deaf is a more dangerous weapon than a wand of sheep.",
+ "QSB3YW5kIG9mIGRlYWYgaXMgYSBtb3JlIGRhbmdlcm91cyB3ZWFwb24gdGhhbiBhIHdhbmQgb2Ygc2hlZXAu" },
+ { "A wand of vibration might bring the whole cave crashing about your ears.",
+ "QSB3YW5kIG9mIHZpYnJhdGlvbiBtaWdodCBicmluZyB0aGUgd2hvbGUgY2F2ZSBjcmFzaGluZyBhYm91dCB5b3VyIGVhcnMu" },
+ { "A winner never quits. A quitter never wins.",
+ "QSB3aW5uZXIgbmV2ZXIgcXVpdHMuIEEgcXVpdHRlciBuZXZlciB3aW5zLg==" },
+ { "A wish? Okay, make me a fortune cookie!",
+ "QSB3aXNoPyBPa2F5LCBtYWtlIG1lIGEgZm9ydHVuZSBjb29raWUh" },
+ { "Afraid of mimics? Try to wear a ring of true seeing.",
+ "QWZyYWlkIG9mIG1pbWljcz8gVHJ5IHRvIHdlYXIgYSByaW5nIG9mIHRydWUgc2VlaW5nLg==" },
+ { "All monsters are created evil, but some are more evil than others.",
+ "QWxsIG1vbnN0ZXJzIGFyZSBjcmVhdGVkIGV2aWwsIGJ1dCBzb21lIGFyZSBtb3JlIGV2aWwgdGhhbiBvdGhlcnMu" },
+ { "Always attack a floating eye from behind!",
+ "QWx3YXlzIGF0dGFjayBhIGZsb2F0aW5nIGV5ZSBmcm9tIGJlaGluZCE=" },
+ { "An elven cloak is always the height of fashion.",
+ "QW4gZWx2ZW4gY2xvYWsgaXMgYWx3YXlzIHRoZSBoZWlnaHQgb2YgZmFzaGlvbi4=" },
+ { "Any small object that is accidentally dropped will hide under a larger object.",
+ "QW55IHNtYWxsIG9iamVjdCB0aGF0IGlzIGFjY2lkZW50YWxseSBkcm9wcGVkIHdpbGwgaGlkZSB1bmRlciBhIGxhcmdlciBvYmplY3Qu" },
+ { "Balrogs do not appear above level 20.",
+ "QmFscm9ncyBkbyBub3QgYXBwZWFyIGFib3ZlIGxldmVsIDIwLg==" },
+ { "Banana peels work especially well against Keystone Kops.",
+ "QmFuYW5hIHBlZWxzIHdvcmsgZXNwZWNpYWxseSB3ZWxsIGFnYWluc3QgS2V5c3RvbmUgS29wcy4=" },
+ { "Be careful when eating bananas. Monsters might slip on the peels.",
+ "QmUgY2FyZWZ1bCB3aGVuIGVhdGluZyBiYW5hbmFzLiBNb25zdGVycyBtaWdodCBzbGlwIG9uIHRoZSBwZWVscy4=" },
+ { "Better leave the dungeon; otherwise you might get hurt badly.",
+ "QmV0dGVyIGxlYXZlIHRoZSBkdW5nZW9uOyBvdGhlcndpc2UgeW91IG1pZ2h0IGdldCBodXJ0IGJhZGx5Lg==" },
+ { "Beware of the potion of nitroglycerin -- it's not for the weak of heart.",
+ "QmV3YXJlIG9mIHRoZSBwb3Rpb24gb2Ygbml0cm9nbHljZXJpbiAtLSBpdCdzIG5vdCBmb3IgdGhlIHdlYWsgb2YgaGVhcnQu" },
+ { "Beware: there's always a chance that your wand explodes as you try to zap it!",
+ "QmV3YXJlOiB0aGVyZSdzIGFsd2F5cyBhIGNoYW5jZSB0aGF0IHlvdXIgd2FuZCBleHBsb2RlcyBhcyB5b3UgdHJ5IHRvIHphcCBpdCE=" },
+ { "Beyond the 23rd level lies a happy retirement in a room of your own.",
+ "QmV5b25kIHRoZSAyM3JkIGxldmVsIGxpZXMgYSBoYXBweSByZXRpcmVtZW50IGluIGEgcm9vbSBvZiB5b3VyIG93bi4=" },
+ { "Changing your suit without dropping your sword? You must be kidding!",
+ "Q2hhbmdpbmcgeW91ciBzdWl0IHdpdGhvdXQgZHJvcHBpbmcgeW91ciBzd29yZD8gWW91IG11c3QgYmUga2lkZGluZyE=" },
+ { "Cockatrices might turn themselves to stone faced with a mirror.",
+ "Q29ja2F0cmljZXMgbWlnaHQgdHVybiB0aGVtc2VsdmVzIHRvIHN0b25lIGZhY2VkIHdpdGggYSBtaXJyb3Iu" },
+ { "Consumption of home-made food is strictly forbidden in this dungeon.",
+ "Q29uc3VtcHRpb24gb2YgaG9tZS1tYWRlIGZvb2QgaXMgc3RyaWN0bHkgZm9yYmlkZGVuIGluIHRoaXMgZHVuZ2Vvbi4=" },
+ { "Dark room? Your chance to develop your photographs!",
+ "RGFyayByb29tPyBZb3VyIGNoYW5jZSB0byBkZXZlbG9wIHlvdXIgcGhvdG9ncmFwaHMh" },
+ { "Dark rooms are not *completely* dark: just wait and let your eyes adjust...",
+ "RGFyayByb29tcyBhcmUgbm90ICpjb21wbGV0ZWx5KiBkYXJrOiBqdXN0IHdhaXQgYW5kIGxldCB5b3VyIGV5ZXMgYWRqdXN0Li4u" },
+ { "David London sez, \"Hey guys, *WIELD* a lizard corpse against a cockatrice!\"",
+ "RGF2aWQgTG9uZG9uIHNleiwgIkhleSBndXlzLCAqV0lFTEQqIGEgbGl6YXJkIGNvcnBzZSBhZ2FpbnN0IGEgY29ja2F0cmljZSEi" },
+ { "Death is just life's way of telling you you've been fired.",
+ "RGVhdGggaXMganVzdCBsaWZlJ3Mgd2F5IG9mIHRlbGxpbmcgeW91IHlvdSd2ZSBiZWVuIGZpcmVkLg==" },
+ { "Demi-gods don't need any help from the gods.",
+ "RGVtaS1nb2RzIGRvbid0IG5lZWQgYW55IGhlbHAgZnJvbSB0aGUgZ29kcy4=" },
+ { "Demons *HATE* Priests and Priestesses.",
+ "RGVtb25zICpIQVRFKiBQcmllc3RzIGFuZCBQcmllc3Rlc3Nlcy4=" },
+ { "Didn't you forget to pay?",
+ "RGlkbid0IHlvdSBmb3JnZXQgdG8gcGF5Pw==" },
+ { "Didn't your mother tell you not to eat food off the floor?",
+ "RGlkbid0IHlvdXIgbW90aGVyIHRlbGwgeW91IG5vdCB0byBlYXQgZm9vZCBvZmYgdGhlIGZsb29yPw==" },
+ { "Direct a direct hit on your direct opponent, directing in the right direction.",
+ "RGlyZWN0IGEgZGlyZWN0IGhpdCBvbiB5b3VyIGRpcmVjdCBvcHBvbmVudCwgZGlyZWN0aW5nIGluIHRoZSByaWdodCBkaXJlY3Rpb24u" },
+ { "Do you want to make more money? Sure, we all do! Join the Fort Ludios guard!",
+ "RG8geW91IHdhbnQgdG8gbWFrZSBtb3JlIG1vbmV5PyBTdXJlLCB3ZSBhbGwgZG8hIEpvaW4gdGhlIEZvcnQgTHVkaW9zIGd1YXJkIQ==" },
+ { "Don't eat too much: you might start hiccoughing!",
+ "RG9uJ3QgZWF0IHRvbyBtdWNoOiB5b3UgbWlnaHQgc3RhcnQgaGljY291Z2hpbmch" },
+ { "Don't play hack at your work; your boss might hit you!",
+ "RG9uJ3QgcGxheSBoYWNrIGF0IHlvdXIgd29yazsgeW91ciBib3NzIG1pZ2h0IGhpdCB5b3Uh" },
+ { "Don't tell a soul you found a secret door, otherwise it isn't a secret anymore.",
+ "RG9uJ3QgdGVsbCBhIHNvdWwgeW91IGZvdW5kIGEgc2VjcmV0IGRvb3IsIG90aGVyd2lzZSBpdCBpc24ndCBhIHNlY3JldCBhbnltb3JlLg==" },
+ { "Drinking potions of booze may land you in jail if you are under 21.",
+ "RHJpbmtpbmcgcG90aW9ucyBvZiBib296ZSBtYXkgbGFuZCB5b3UgaW4gamFpbCBpZiB5b3UgYXJlIHVuZGVyIDIxLg==" },
+ { "Drop your vanity and get rid of your jewels! Pickpockets about!",
+ "RHJvcCB5b3VyIHZhbml0eSBhbmQgZ2V0IHJpZCBvZiB5b3VyIGpld2VscyEgUGlja3BvY2tldHMgYWJvdXQh" },
+ { "Eat 10 cloves of garlic and keep all humans at a two-square distance.",
+ "RWF0IDEwIGNsb3ZlcyBvZiBnYXJsaWMgYW5kIGtlZXAgYWxsIGh1bWFucyBhdCBhIHR3by1zcXVhcmUgZGlzdGFuY2Uu" },
+ { "Eels hide under mud. Use a unicorn to clear the water and make them visible.",
+ "RWVscyBoaWRlIHVuZGVyIG11ZC4gVXNlIGEgdW5pY29ybiB0byBjbGVhciB0aGUgd2F0ZXIgYW5kIG1ha2UgdGhlbSB2aXNpYmxlLg==" },
+ { "Engrave your wishes with a wand of wishing.",
+ "RW5ncmF2ZSB5b3VyIHdpc2hlcyB3aXRoIGEgd2FuZCBvZiB3aXNoaW5nLg==" },
+ { "Eventually you will come to admire the swift elegance of a retreating nymph.",
+ "RXZlbnR1YWxseSB5b3Ugd2lsbCBjb21lIHRvIGFkbWlyZSB0aGUgc3dpZnQgZWxlZ2FuY2Ugb2YgYSByZXRyZWF0aW5nIG55bXBoLg==" },
+ { "Ever heard hissing outside? I *knew* you hadn't!",
+ "RXZlciBoZWFyZCBoaXNzaW5nIG91dHNpZGU/IEkgKmtuZXcqIHlvdSBoYWRuJ3Qh" },
+ { "Ever lifted a dragon corpse?",
+ "RXZlciBsaWZ0ZWQgYSBkcmFnb24gY29ycHNlPw==" },
+ { "Ever seen a leocrotta dancing the tengu?",
+ "RXZlciBzZWVuIGEgbGVvY3JvdHRhIGRhbmNpbmcgdGhlIHRlbmd1Pw==" },
+ { "Ever seen your weapon glow plaid?",
+ "RXZlciBzZWVuIHlvdXIgd2VhcG9uIGdsb3cgcGxhaWQ/" },
+ { "Ever tamed a shopkeeper?",
+ "RXZlciB0YW1lZCBhIHNob3BrZWVwZXI/" },
+ { "Ever tried digging through a Vault Guard?",
+ "RXZlciB0cmllZCBkaWdnaW5nIHRocm91Z2ggYSBWYXVsdCBHdWFyZD8=" },
+ { "Ever tried enchanting a rope?",
+ "RXZlciB0cmllZCBlbmNoYW50aW5nIGEgcm9wZT8=" },
+ { "Floating eyes can't stand Hawaiian shirts.",
+ "RmxvYXRpbmcgZXllcyBjYW4ndCBzdGFuZCBIYXdhaWlhbiBzaGlydHMu" },
+ { "For any remedy there is a misery.",
+ "Rm9yIGFueSByZW1lZHkgdGhlcmUgaXMgYSBtaXNlcnku" },
+ { "Giant bats turn into giant vampires.",
+ "R2lhbnQgYmF0cyB0dXJuIGludG8gZ2lhbnQgdmFtcGlyZXMu" },
+ { "Good day for overcoming obstacles. Try a steeplechase.",
+ "R29vZCBkYXkgZm9yIG92ZXJjb21pbmcgb2JzdGFjbGVzLiBUcnkgYSBzdGVlcGxlY2hhc2Uu" },
+ { "Half Moon tonight. (At least it's better than no Moon at all.)",
+ "SGFsZiBNb29uIHRvbmlnaHQuIChBdCBsZWFzdCBpdCdzIGJldHRlciB0aGFuIG5vIE1vb24gYXQgYWxsLik=" },
+ { "Help! I'm being held prisoner in a fortune cookie factory!",
+ "SGVscCEgSSdtIGJlaW5nIGhlbGQgcHJpc29uZXIgaW4gYSBmb3J0dW5lIGNvb2tpZSBmYWN0b3J5IQ==" },
+ { "Housecats have nine lives, kittens only one.",
+ "SG91c2VjYXRzIGhhdmUgbmluZSBsaXZlcywga2l0dGVucyBvbmx5IG9uZS4=" },
+ { "How long can you tread water?",
+ "SG93IGxvbmcgY2FuIHlvdSB0cmVhZCB3YXRlcj8=" },
+ { "Hungry? There is an abundance of food on the next level.",
+ "SHVuZ3J5PyBUaGVyZSBpcyBhbiBhYnVuZGFuY2Ugb2YgZm9vZCBvbiB0aGUgbmV4dCBsZXZlbC4=" },
+ { "I guess you've never hit a mail daemon with the Amulet of Yendor...",
+ "SSBndWVzcyB5b3UndmUgbmV2ZXIgaGl0IGEgbWFpbCBkYWVtb24gd2l0aCB0aGUgQW11bGV0IG9mIFllbmRvci4uLg==" },
+ { "If you are the shopkeeper, you can take things for free.",
+ "SWYgeW91IGFyZSB0aGUgc2hvcGtlZXBlciwgeW91IGNhbiB0YWtlIHRoaW5ncyBmb3IgZnJlZS4=" },
+ { "If you can't learn to do it well, learn to enjoy doing it badly.",
+ "SWYgeW91IGNhbid0IGxlYXJuIHRvIGRvIGl0IHdlbGwsIGxlYXJuIHRvIGVuam95IGRvaW5nIGl0IGJhZGx5Lg==" },
+ { "If you thought the Wizard was bad, just wait till you meet the Warlord!",
+ "SWYgeW91IHRob3VnaHQgdGhlIFdpemFyZCB3YXMgYmFkLCBqdXN0IHdhaXQgdGlsbCB5b3UgbWVldCB0aGUgV2FybG9yZCE=" },
+ { "If you turn blind, don't expect your dog to be turned into a seeing-eye dog.",
+ "SWYgeW91IHR1cm4gYmxpbmQsIGRvbid0IGV4cGVjdCB5b3VyIGRvZyB0byBiZSB0dXJuZWQgaW50byBhIHNlZWluZy1leWUgZG9nLg==" },
+ { "If you want to feel great, you must eat something real big.",
+ "SWYgeW91IHdhbnQgdG8gZmVlbCBncmVhdCwgeW91IG11c3QgZWF0IHNvbWV0aGluZyByZWFsIGJpZy4=" },
+ { "If you want to float, you'd better eat a floating eye.",
+ "SWYgeW91IHdhbnQgdG8gZmxvYXQsIHlvdSdkIGJldHRlciBlYXQgYSBmbG9hdGluZyBleWUu" },
+ { "If your ghost kills a player, it increases your score.",
+ "SWYgeW91ciBnaG9zdCBraWxscyBhIHBsYXllciwgaXQgaW5jcmVhc2VzIHlvdXIgc2NvcmUu" },
+ { "Increase mindpower: Tame your own ghost!",
+ "SW5jcmVhc2UgbWluZHBvd2VyOiBUYW1lIHlvdXIgb3duIGdob3N0IQ==" },
+ { "It furthers one to see the great man.",
+ "SXQgZnVydGhlcnMgb25lIHRvIHNlZSB0aGUgZ3JlYXQgbWFuLg==" },
+ { "It's easy to overlook a monster in a wood.",
+ "SXQncyBlYXN5IHRvIG92ZXJsb29rIGEgbW9uc3RlciBpbiBhIHdvb2Qu" },
+ { "Just below any trapdoor there may be another one. Just keep falling!",
+ "SnVzdCBiZWxvdyBhbnkgdHJhcGRvb3IgdGhlcmUgbWF5IGJlIGFub3RoZXIgb25lLiBKdXN0IGtlZXAgZmFsbGluZyE=" },
+ { "Katanas are very sharp; watch you don't cut yourself.",
+ "S2F0YW5hcyBhcmUgdmVyeSBzaGFycDsgd2F0Y2ggeW91IGRvbid0IGN1dCB5b3Vyc2VsZi4=" },
+ { "Keep a clear mind: quaff clear potions.",
+ "S2VlcCBhIGNsZWFyIG1pbmQ6IHF1YWZmIGNsZWFyIHBvdGlvbnMu" },
+ { "Kicking the terminal doesn't hurt the monsters.",
+ "S2lja2luZyB0aGUgdGVybWluYWwgZG9lc24ndCBodXJ0IHRoZSBtb25zdGVycy4=" },
+ { "Killer bees keep appearing till you kill their queen.",
+ "S2lsbGVyIGJlZXMga2VlcCBhcHBlYXJpbmcgdGlsbCB5b3Uga2lsbCB0aGVpciBxdWVlbi4=" },
+ { "Killer bunnies can be tamed with carrots only.",
+ "S2lsbGVyIGJ1bm5pZXMgY2FuIGJlIHRhbWVkIHdpdGggY2Fycm90cyBvbmx5Lg==" },
+ { "Latest news? Put `rec.games.roguelike.nethack' in your .newsrc!",
+ "TGF0ZXN0IG5ld3M/IFB1dCBgcmVjLmdhbWVzLnJvZ3VlbGlrZS5uZXRoYWNrJyBpbiB5b3VyIC5uZXdzcmMh" },
+ { "Learn how to spell. Play NetHack!",
+ "TGVhcm4gaG93IHRvIHNwZWxsLiBQbGF5IE5ldEhhY2sh" },
+ { "Leprechauns hide their gold in a secret room.",
+ "TGVwcmVjaGF1bnMgaGlkZSB0aGVpciBnb2xkIGluIGEgc2VjcmV0IHJvb20u" },
+ { "Let your fingers do the walking on the yulkjhnb keys.",
+ "TGV0IHlvdXIgZmluZ2VycyBkbyB0aGUgd2Fsa2luZyBvbiB0aGUgeXVsa2pobmIga2V5cy4=" },
+ { "Let's face it: this time you're not going to win.",
+ "TGV0J3MgZmFjZSBpdDogdGhpcyB0aW1lIHlvdSdyZSBub3QgZ29pbmcgdG8gd2luLg==" },
+ { "Let's have a party, drink a lot of booze.",
+ "TGV0J3MgaGF2ZSBhIHBhcnR5LCBkcmluayBhIGxvdCBvZiBib296ZS4=" },
+ { "Liquor sellers do not drink; they hate to see you twice.",
+ "TGlxdW9yIHNlbGxlcnMgZG8gbm90IGRyaW5rOyB0aGV5IGhhdGUgdG8gc2VlIHlvdSB0d2ljZS4=" },
+ { "Lunar eclipse tonight. May as well quit now!",
+ "THVuYXIgZWNsaXBzZSB0b25pZ2h0LiBNYXkgYXMgd2VsbCBxdWl0IG5vdyE=" },
+ { "Meeting your own ghost decreases your luck considerably!",
+ "TWVldGluZyB5b3VyIG93biBnaG9zdCBkZWNyZWFzZXMgeW91ciBsdWNrIGNvbnNpZGVyYWJseSE=" },
+ { "Money to invest? Take it to the local branch of the Magic Memory Vault!",
+ "TW9uZXkgdG8gaW52ZXN0PyBUYWtlIGl0IHRvIHRoZSBsb2NhbCBicmFuY2ggb2YgdGhlIE1hZ2ljIE1lbW9yeSBWYXVsdCE=" },
+ { "Monsters come from nowhere to hit you everywhere.",
+ "TW9uc3RlcnMgY29tZSBmcm9tIG5vd2hlcmUgdG8gaGl0IHlvdSBldmVyeXdoZXJlLg==" },
+ { "Monsters sleep because you are boring, not because they ever get tired.",
+ "TW9uc3RlcnMgc2xlZXAgYmVjYXVzZSB5b3UgYXJlIGJvcmluZywgbm90IGJlY2F1c2UgdGhleSBldmVyIGdldCB0aXJlZC4=" },
+ { "Most monsters prefer minced meat. That's why they are hitting you!",
+ "TW9zdCBtb25zdGVycyBwcmVmZXIgbWluY2VkIG1lYXQuIFRoYXQncyB3aHkgdGhleSBhcmUgaGl0dGluZyB5b3Uh" },
+ { "Most of the bugs in NetHack are on the floor.",
+ "TW9zdCBvZiB0aGUgYnVncyBpbiBOZXRIYWNrIGFyZSBvbiB0aGUgZmxvb3Iu" },
+ { "Much ado Nothing Happens.",
+ "TXVjaCBhZG8gTm90aGluZyBIYXBwZW5zLg==" },
+ { "Multi-player NetHack is a myth.",
+ "TXVsdGktcGxheWVyIE5ldEhhY2sgaXMgYSBteXRoLg==" },
+ { "NetHack is addictive. Too late, you're already hooked.",
+ "TmV0SGFjayBpcyBhZGRpY3RpdmUuIFRvbyBsYXRlLCB5b3UncmUgYWxyZWFkeSBob29rZWQu" },
+ { "Never ask a shopkeeper for a price list.",
+ "TmV2ZXIgYXNrIGEgc2hvcGtlZXBlciBmb3IgYSBwcmljZSBsaXN0Lg==" },
+ { "Never burn a tree, unless you like getting whacked with a +5 shovel.",
+ "TmV2ZXIgYnVybiBhIHRyZWUsIHVubGVzcyB5b3UgbGlrZSBnZXR0aW5nIHdoYWNrZWQgd2l0aCBhICs1IHNob3ZlbC4=" },
+ { "Never eat with glowing hands!",
+ "TmV2ZXIgZWF0IHdpdGggZ2xvd2luZyBoYW5kcyE=" },
+ { "Never mind the monsters hitting you: they just replace the charwomen.",
+ "TmV2ZXIgbWluZCB0aGUgbW9uc3RlcnMgaGl0dGluZyB5b3U6IHRoZXkganVzdCByZXBsYWNlIHRoZSBjaGFyd29tZW4u" },
+ { "Never play leapfrog with a unicorn.",
+ "TmV2ZXIgcGxheSBsZWFwZnJvZyB3aXRoIGEgdW5pY29ybi4=" },
+ { "Never step on a cursed engraving.",
+ "TmV2ZXIgc3RlcCBvbiBhIGN1cnNlZCBlbmdyYXZpbmcu" },
+ { "Never swim with a camera: there's nothing to take pictures of.",
+ "TmV2ZXIgc3dpbSB3aXRoIGEgY2FtZXJhOiB0aGVyZSdzIG5vdGhpbmcgdG8gdGFrZSBwaWN0dXJlcyBvZi4=" },
+ { "Never teach your pet rust monster to fetch.",
+ "TmV2ZXIgdGVhY2ggeW91ciBwZXQgcnVzdCBtb25zdGVyIHRvIGZldGNoLg==" },
+ { "Never trust a random generator in magic fields.",
+ "TmV2ZXIgdHJ1c3QgYSByYW5kb20gZ2VuZXJhdG9yIGluIG1hZ2ljIGZpZWxkcy4=" },
+ { "Never use a wand of death.",
+ "TmV2ZXIgdXNlIGEgd2FuZCBvZiBkZWF0aC4=" },
+ { "No level contains two shops. The maze is no level. So...",
+ "Tm8gbGV2ZWwgY29udGFpbnMgdHdvIHNob3BzLiBUaGUgbWF6ZSBpcyBubyBsZXZlbC4gU28uLi4=" },
+ { "No part of this fortune may be reproduced, stored in a retrieval system, ...",
+ "Tm8gcGFydCBvZiB0aGlzIGZvcnR1bmUgbWF5IGJlIHJlcHJvZHVjZWQsIHN0b3JlZCBpbiBhIHJldHJpZXZhbCBzeXN0ZW0sIC4uLg==" },
+ { "Not all rumors are as misleading as this one.",
+ "Tm90IGFsbCBydW1vcnMgYXJlIGFzIG1pc2xlYWRpbmcgYXMgdGhpcyBvbmUu" },
+ { "Nymphs and nurses like beautiful rings.",
+ "TnltcGhzIGFuZCBudXJzZXMgbGlrZSBiZWF1dGlmdWwgcmluZ3Mu" },
+ { "Nymphs are blondes. Are you a gentleman?",
+ "TnltcGhzIGFyZSBibG9uZGVzLiBBcmUgeW91IGEgZ2VudGxlbWFuPw==" },
+ { "Offering a unicorn a worthless piece of glass might prove to be fatal!",
+ "T2ZmZXJpbmcgYSB1bmljb3JuIGEgd29ydGhsZXNzIHBpZWNlIG9mIGdsYXNzIG1pZ2h0IHByb3ZlIHRvIGJlIGZhdGFsIQ==" },
+ { "Old hackers never die: young ones do.",
+ "T2xkIGhhY2tlcnMgbmV2ZXIgZGllOiB5b3VuZyBvbmVzIGRvLg==" },
+ { "One has to leave shops before closing time.",
+ "T25lIGhhcyB0byBsZWF2ZSBzaG9wcyBiZWZvcmUgY2xvc2luZyB0aW1lLg==" },
+ { "One homunculus a day keeps the doctor away.",
+ "T25lIGhvbXVuY3VsdXMgYSBkYXkga2VlcHMgdGhlIGRvY3RvciBhd2F5Lg==" },
+ { "One level further down somebody is getting killed, right now.",
+ "T25lIGxldmVsIGZ1cnRoZXIgZG93biBzb21lYm9keSBpcyBnZXR0aW5nIGtpbGxlZCwgcmlnaHQgbm93Lg==" },
+ { "Only a wizard can use a magic whistle.",
+ "T25seSBhIHdpemFyZCBjYW4gdXNlIGEgbWFnaWMgd2hpc3RsZS4=" },
+ { "Only adventurers of evil alignment think of killing their dog.",
+ "T25seSBhZHZlbnR1cmVycyBvZiBldmlsIGFsaWdubWVudCB0aGluayBvZiBraWxsaW5nIHRoZWlyIGRvZy4=" },
+ { "Only chaotic evils kill sleeping monsters.",
+ "T25seSBjaGFvdGljIGV2aWxzIGtpbGwgc2xlZXBpbmcgbW9uc3RlcnMu" },
+ { "Only real trappers escape traps.",
+ "T25seSByZWFsIHRyYXBwZXJzIGVzY2FwZSB0cmFwcy4=" },
+ { "Only real wizards can write scrolls.",
+ "T25seSByZWFsIHdpemFyZHMgY2FuIHdyaXRlIHNjcm9sbHMu" },
+ { "Operation OVERKILL has started now.",
+ "T3BlcmF0aW9uIE9WRVJLSUxMIGhhcyBzdGFydGVkIG5vdy4=" },
+ { "PLEASE ignore previous rumor.",
+ "UExFQVNFIGlnbm9yZSBwcmV2aW91cyBydW1vci4=" },
+ { "Polymorph into an ettin; meet your opponents face to face to face.",
+ "UG9seW1vcnBoIGludG8gYW4gZXR0aW47IG1lZXQgeW91ciBvcHBvbmVudHMgZmFjZSB0byBmYWNlIHRvIGZhY2Uu" },
+ { "Praying will frighten demons.",
+ "UHJheWluZyB3aWxsIGZyaWdodGVuIGRlbW9ucy4=" },
+ { "Row (3x) that boat gently down the stream, Charon (4x), death is but a dream.",
+ "Um93ICgzeCkgdGhhdCBib2F0IGdlbnRseSBkb3duIHRoZSBzdHJlYW0sIENoYXJvbiAoNHgpLCBkZWF0aCBpcyBidXQgYSBkcmVhbS4=" },
+ { "Running is good for your legs.",
+ "UnVubmluZyBpcyBnb29kIGZvciB5b3VyIGxlZ3Mu" },
+ { "Screw up your courage! You've screwed up everything else.",
+ "U2NyZXcgdXAgeW91ciBjb3VyYWdlISBZb3UndmUgc2NyZXdlZCB1cCBldmVyeXRoaW5nIGVsc2Uu" },
+ { "Seepage? Leaky pipes? Rising damp? Summon the plumber!",
+ "U2VlcGFnZT8gTGVha3kgcGlwZXM/IFJpc2luZyBkYW1wPyBTdW1tb24gdGhlIHBsdW1iZXIh" },
+ { "Segmentation fault (core dumped).",
+ "U2VnbWVudGF0aW9uIGZhdWx0IChjb3JlIGR1bXBlZCku" },
+ { "Shopkeepers sometimes die from old age.",
+ "U2hvcGtlZXBlcnMgc29tZXRpbWVzIGRpZSBmcm9tIG9sZCBhZ2Uu" },
+ { "Some mazes (especially small ones) have no solutions, says man 6 maze.",
+ "U29tZSBtYXplcyAoZXNwZWNpYWxseSBzbWFsbCBvbmVzKSBoYXZlIG5vIHNvbHV0aW9ucywgc2F5cyBtYW4gNiBtYXplLg==" },
+ { "Some questions the Sphynx asks just *don't* have any answers.",
+ "U29tZSBxdWVzdGlvbnMgdGhlIFNwaHlueCBhc2tzIGp1c3QgKmRvbid0KiBoYXZlIGFueSBhbnN3ZXJzLg==" },
+ { "Sometimes \"mu\" is the answer.",
+ "U29tZXRpbWVzICJtdSIgaXMgdGhlIGFuc3dlci4=" },
+ { "Sorry, no fortune this time. Better luck next cookie!",
+ "U29ycnksIG5vIGZvcnR1bmUgdGhpcyB0aW1lLiBCZXR0ZXIgbHVjayBuZXh0IGNvb2tpZSE=" },
+ { "Spare your scrolls of make-edible until it's really necessary!",
+ "U3BhcmUgeW91ciBzY3JvbGxzIG9mIG1ha2UtZWRpYmxlIHVudGlsIGl0J3MgcmVhbGx5IG5lY2Vzc2FyeSE=" },
+ { "Suddenly, the dungeon will collapse...",
+ "U3VkZGVubHksIHRoZSBkdW5nZW9uIHdpbGwgY29sbGFwc2UuLi4=" },
+ { "Taming a mail daemon may cause a system security violation.",
+ "VGFtaW5nIGEgbWFpbCBkYWVtb24gbWF5IGNhdXNlIGEgc3lzdGVtIHNlY3VyaXR5IHZpb2xhdGlvbi4=" },
+ { "The crowd was so tough, the Stooges won't play the Dungeon anymore, nyuk nyuk.",
+ "VGhlIGNyb3dkIHdhcyBzbyB0b3VnaCwgdGhlIFN0b29nZXMgd29uJ3QgcGxheSB0aGUgRHVuZ2VvbiBhbnltb3JlLCBueXVrIG55dWsu" },
+ { "The leprechauns hide their treasure in a small hidden room.",
+ "VGhlIGxlcHJlY2hhdW5zIGhpZGUgdGhlaXIgdHJlYXN1cmUgaW4gYSBzbWFsbCBoaWRkZW4gcm9vbS4=" },
+ { "The longer the wand the better.",
+ "VGhlIGxvbmdlciB0aGUgd2FuZCB0aGUgYmV0dGVyLg==" },
+ { "The magic word is \"XYZZY\".",
+ "VGhlIG1hZ2ljIHdvcmQgaXMgIlhZWlpZIi4=" },
+ { "The meek shall inherit your bones files.",
+ "VGhlIG1lZWsgc2hhbGwgaW5oZXJpdCB5b3VyIGJvbmVzIGZpbGVzLg==" },
+ { "The mines are dark and deep, and I have levels to go before I sleep.",
+ "VGhlIG1pbmVzIGFyZSBkYXJrIGFuZCBkZWVwLCBhbmQgSSBoYXZlIGxldmVscyB0byBnbyBiZWZvcmUgSSBzbGVlcC4=" },
+ { "The use of dynamite is dangerous.",
+ "VGhlIHVzZSBvZiBkeW5hbWl0ZSBpcyBkYW5nZXJvdXMu" },
+ { "There are no worms in the UNIX version.",
+ "VGhlcmUgYXJlIG5vIHdvcm1zIGluIHRoZSBVTklYIHZlcnNpb24u" },
+ { "There is a trap on this level!",
+ "VGhlcmUgaXMgYSB0cmFwIG9uIHRoaXMgbGV2ZWwh" },
+ { "They say that Demogorgon, Asmodeus, Orcus, Yeenoghu & Juiblex is no law firm.",
+ "VGhleSBzYXkgdGhhdCBEZW1vZ29yZ29uLCBBc21vZGV1cywgT3JjdXMsIFllZW5vZ2h1ICYgSnVpYmxleCBpcyBubyBsYXcgZmlybS4=" },
+ { "They say that Geryon has an evil twin, beware!",
+ "VGhleSBzYXkgdGhhdCBHZXJ5b24gaGFzIGFuIGV2aWwgdHdpbiwgYmV3YXJlIQ==" },
+ { "They say that Medusa would make a terrible pet.",
+ "VGhleSBzYXkgdGhhdCBNZWR1c2Egd291bGQgbWFrZSBhIHRlcnJpYmxlIHBldC4=" },
+ { "They say that NetHack bugs are Seldon planned.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGJ1Z3MgYXJlIFNlbGRvbiBwbGFubmVkLg==" },
+ { "They say that NetHack comes in 256 flavors.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGNvbWVzIGluIDI1NiBmbGF2b3JzLg==" },
+ { "They say that NetHack is just a computer game.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIGp1c3QgYSBjb21wdXRlciBnYW1lLg==" },
+ { "They say that NetHack is more than just a computer game.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIG1vcmUgdGhhbiBqdXN0IGEgY29tcHV0ZXIgZ2FtZS4=" },
+ { "They say that NetHack is never what it used to be.",
+ "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIG5ldmVyIHdoYXQgaXQgdXNlZCB0byBiZS4=" },
+ { "They say that a baby dragon is too small to hurt or help you.",
+ "VGhleSBzYXkgdGhhdCBhIGJhYnkgZHJhZ29uIGlzIHRvbyBzbWFsbCB0byBodXJ0IG9yIGhlbHAgeW91Lg==" },
+ { "They say that a black pudding is simply a brown pudding gone bad.",
+ "VGhleSBzYXkgdGhhdCBhIGJsYWNrIHB1ZGRpbmcgaXMgc2ltcGx5IGEgYnJvd24gcHVkZGluZyBnb25lIGJhZC4=" },
+ { "They say that a black sheep has 3 bags full of wool.",
+ "VGhleSBzYXkgdGhhdCBhIGJsYWNrIHNoZWVwIGhhcyAzIGJhZ3MgZnVsbCBvZiB3b29sLg==" },
+ { "They say that a blank scroll is like a blank check.",
+ "VGhleSBzYXkgdGhhdCBhIGJsYW5rIHNjcm9sbCBpcyBsaWtlIGEgYmxhbmsgY2hlY2su" },
+ { "They say that a cat named Morris has nine lives.",
+ "VGhleSBzYXkgdGhhdCBhIGNhdCBuYW1lZCBNb3JyaXMgaGFzIG5pbmUgbGl2ZXMu" },
+ { "They say that a desperate shopper might pay any price in a shop.",
+ "VGhleSBzYXkgdGhhdCBhIGRlc3BlcmF0ZSBzaG9wcGVyIG1pZ2h0IHBheSBhbnkgcHJpY2UgaW4gYSBzaG9wLg==" },
+ { "They say that a diamond dog is everybody's best friend.",
+ "VGhleSBzYXkgdGhhdCBhIGRpYW1vbmQgZG9nIGlzIGV2ZXJ5Ym9keSdzIGJlc3QgZnJpZW5kLg==" },
+ { "They say that a dwarf lord can carry a pick-axe because his armor is light.",
+ "VGhleSBzYXkgdGhhdCBhIGR3YXJmIGxvcmQgY2FuIGNhcnJ5IGEgcGljay1heGUgYmVjYXVzZSBoaXMgYXJtb3IgaXMgbGlnaHQu" },
+ { "They say that a floating eye can defeat Medusa.",
+ "VGhleSBzYXkgdGhhdCBhIGZsb2F0aW5nIGV5ZSBjYW4gZGVmZWF0IE1lZHVzYS4=" },
+ { "They say that a fortune only has 1 line and you can't read between it.",
+ "VGhleSBzYXkgdGhhdCBhIGZvcnR1bmUgb25seSBoYXMgMSBsaW5lIGFuZCB5b3UgY2FuJ3QgcmVhZCBiZXR3ZWVuIGl0Lg==" },
+ { "They say that a fortune only has 1 line, but you can read between it.",
+ "VGhleSBzYXkgdGhhdCBhIGZvcnR1bmUgb25seSBoYXMgMSBsaW5lLCBidXQgeW91IGNhbiByZWFkIGJldHdlZW4gaXQu" },
+ { "They say that a fountain looks nothing like a regularly erupting geyser.",
+ "VGhleSBzYXkgdGhhdCBhIGZvdW50YWluIGxvb2tzIG5vdGhpbmcgbGlrZSBhIHJlZ3VsYXJseSBlcnVwdGluZyBnZXlzZXIu" },
+ { "They say that a gold doubloon is worth more than its weight in gold.",
+ "VGhleSBzYXkgdGhhdCBhIGdvbGQgZG91Ymxvb24gaXMgd29ydGggbW9yZSB0aGFuIGl0cyB3ZWlnaHQgaW4gZ29sZC4=" },
+ { "They say that a grid bug won't pay a shopkeeper for zapping you in a shop.",
+ "VGhleSBzYXkgdGhhdCBhIGdyaWQgYnVnIHdvbid0IHBheSBhIHNob3BrZWVwZXIgZm9yIHphcHBpbmcgeW91IGluIGEgc2hvcC4=" },
+ { "They say that a gypsy could tell your fortune for a price.",
+ "VGhleSBzYXkgdGhhdCBhIGd5cHN5IGNvdWxkIHRlbGwgeW91ciBmb3J0dW5lIGZvciBhIHByaWNlLg==" },
+ { "They say that a hacker named Alice once level teleported by using a mirror.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBBbGljZSBvbmNlIGxldmVsIHRlbGVwb3J0ZWQgYnkgdXNpbmcgYSBtaXJyb3Iu" },
+ { "They say that a hacker named David once slew a giant with a sling and a rock.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBEYXZpZCBvbmNlIHNsZXcgYSBnaWFudCB3aXRoIGEgc2xpbmcgYW5kIGEgcm9jay4=" },
+ { "They say that a hacker named Dorothy once rode a fog cloud to Oz.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBEb3JvdGh5IG9uY2Ugcm9kZSBhIGZvZyBjbG91ZCB0byBPei4=" },
+ { "They say that a hacker named Mary once lost a white sheep in the mazes.",
+ "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBNYXJ5IG9uY2UgbG9zdCBhIHdoaXRlIHNoZWVwIGluIHRoZSBtYXplcy4=" },
+ { "They say that a helm of brilliance is not to be taken lightly.",
+ "VGhleSBzYXkgdGhhdCBhIGhlbG0gb2YgYnJpbGxpYW5jZSBpcyBub3QgdG8gYmUgdGFrZW4gbGlnaHRseS4=" },
+ { "They say that a hot dog and a hell hound are the same thing.",
+ "VGhleSBzYXkgdGhhdCBhIGhvdCBkb2cgYW5kIGEgaGVsbCBob3VuZCBhcmUgdGhlIHNhbWUgdGhpbmcu" },
+ { "They say that a lamp named Aladdin's Lamp contains a djinni with 3 wishes.",
+ "VGhleSBzYXkgdGhhdCBhIGxhbXAgbmFtZWQgQWxhZGRpbidzIExhbXAgY29udGFpbnMgYSBkamlubmkgd2l0aCAzIHdpc2hlcy4=" },
+ { "They say that a large dog named Lassie will lead you to the amulet.",
+ "VGhleSBzYXkgdGhhdCBhIGxhcmdlIGRvZyBuYW1lZCBMYXNzaWUgd2lsbCBsZWFkIHlvdSB0byB0aGUgYW11bGV0Lg==" },
+ { "They say that a long sword is not a light sword.",
+ "VGhleSBzYXkgdGhhdCBhIGxvbmcgc3dvcmQgaXMgbm90IGEgbGlnaHQgc3dvcmQu" },
+ { "They say that a manes won't mince words with you.",
+ "VGhleSBzYXkgdGhhdCBhIG1hbmVzIHdvbid0IG1pbmNlIHdvcmRzIHdpdGggeW91Lg==" },
+ { "They say that a mind is a terrible thing to waste.",
+ "VGhleSBzYXkgdGhhdCBhIG1pbmQgaXMgYSB0ZXJyaWJsZSB0aGluZyB0byB3YXN0ZS4=" },
+ { "They say that a plain nymph will only wear a wire ring in one ear.",
+ "VGhleSBzYXkgdGhhdCBhIHBsYWluIG55bXBoIHdpbGwgb25seSB3ZWFyIGEgd2lyZSByaW5nIGluIG9uZSBlYXIu" },
+ { "They say that a plumed hat could be a previously used crested helmet.",
+ "VGhleSBzYXkgdGhhdCBhIHBsdW1lZCBoYXQgY291bGQgYmUgYSBwcmV2aW91c2x5IHVzZWQgY3Jlc3RlZCBoZWxtZXQu" },
+ { "They say that a potion of oil is difficult to grasp.",
+ "VGhleSBzYXkgdGhhdCBhIHBvdGlvbiBvZiBvaWwgaXMgZGlmZmljdWx0IHRvIGdyYXNwLg==" },
+ { "They say that a potion of yogurt is a cancelled potion of sickness.",
+ "VGhleSBzYXkgdGhhdCBhIHBvdGlvbiBvZiB5b2d1cnQgaXMgYSBjYW5jZWxsZWQgcG90aW9uIG9mIHNpY2tuZXNzLg==" },
+ { "They say that a purple worm is not a baby purple dragon.",
+ "VGhleSBzYXkgdGhhdCBhIHB1cnBsZSB3b3JtIGlzIG5vdCBhIGJhYnkgcHVycGxlIGRyYWdvbi4=" },
+ { "They say that a quivering blob tastes different than a gelatinous cube.",
+ "VGhleSBzYXkgdGhhdCBhIHF1aXZlcmluZyBibG9iIHRhc3RlcyBkaWZmZXJlbnQgdGhhbiBhIGdlbGF0aW5vdXMgY3ViZS4=" },
+ { "They say that a runed broadsword named Stormbringer attracts vortices.",
+ "VGhleSBzYXkgdGhhdCBhIHJ1bmVkIGJyb2Fkc3dvcmQgbmFtZWQgU3Rvcm1icmluZ2VyIGF0dHJhY3RzIHZvcnRpY2VzLg==" },
+ { "They say that a scroll of summoning has other names.",
+ "VGhleSBzYXkgdGhhdCBhIHNjcm9sbCBvZiBzdW1tb25pbmcgaGFzIG90aGVyIG5hbWVzLg==" },
+ { "They say that a shaman can bestow blessings but usually doesn't.",
+ "VGhleSBzYXkgdGhhdCBhIHNoYW1hbiBjYW4gYmVzdG93IGJsZXNzaW5ncyBidXQgdXN1YWxseSBkb2Vzbid0Lg==" },
+ { "They say that a shaman will bless you for an eye of newt and wing of bat.",
+ "VGhleSBzYXkgdGhhdCBhIHNoYW1hbiB3aWxsIGJsZXNzIHlvdSBmb3IgYW4gZXllIG9mIG5ld3QgYW5kIHdpbmcgb2YgYmF0Lg==" },
+ { "They say that a shimmering gold shield is not a polished silver shield.",
+ "VGhleSBzYXkgdGhhdCBhIHNoaW1tZXJpbmcgZ29sZCBzaGllbGQgaXMgbm90IGEgcG9saXNoZWQgc2lsdmVyIHNoaWVsZC4=" },
+ { "They say that a spear will hit a neo-otyugh. (Do YOU know what that is?)",
+ "VGhleSBzYXkgdGhhdCBhIHNwZWFyIHdpbGwgaGl0IGEgbmVvLW90eXVnaC4gKERvIFlPVSBrbm93IHdoYXQgdGhhdCBpcz8p" },
+ { "They say that a spotted dragon is the ultimate shape changer.",
+ "VGhleSBzYXkgdGhhdCBhIHNwb3R0ZWQgZHJhZ29uIGlzIHRoZSB1bHRpbWF0ZSBzaGFwZSBjaGFuZ2VyLg==" },
+ { "They say that a stethoscope is no good if you can only hear your heartbeat.",
+ "VGhleSBzYXkgdGhhdCBhIHN0ZXRob3Njb3BlIGlzIG5vIGdvb2QgaWYgeW91IGNhbiBvbmx5IGhlYXIgeW91ciBoZWFydGJlYXQu" },
+ { "They say that a succubus named Suzy will sometimes warn you of danger.",
+ "VGhleSBzYXkgdGhhdCBhIHN1Y2N1YnVzIG5hbWVkIFN1enkgd2lsbCBzb21ldGltZXMgd2FybiB5b3Ugb2YgZGFuZ2VyLg==" },
+ { "They say that a wand of cancellation is not like a wand of polymorph.",
+ "VGhleSBzYXkgdGhhdCBhIHdhbmQgb2YgY2FuY2VsbGF0aW9uIGlzIG5vdCBsaWtlIGEgd2FuZCBvZiBwb2x5bW9ycGgu" },
+ { "They say that a wood golem named Pinocchio would be easy to control.",
+ "VGhleSBzYXkgdGhhdCBhIHdvb2QgZ29sZW0gbmFtZWQgUGlub2NjaGlvIHdvdWxkIGJlIGVhc3kgdG8gY29udHJvbC4=" },
+ { "They say that after killing a dragon it's time for a change of scenery.",
+ "VGhleSBzYXkgdGhhdCBhZnRlciBraWxsaW5nIGEgZHJhZ29uIGl0J3MgdGltZSBmb3IgYSBjaGFuZ2Ugb2Ygc2NlbmVyeS4=" },
+ { "They say that an amulet of strangulation is worse than ring around the collar.",
+ "VGhleSBzYXkgdGhhdCBhbiBhbXVsZXQgb2Ygc3RyYW5ndWxhdGlvbiBpcyB3b3JzZSB0aGFuIHJpbmcgYXJvdW5kIHRoZSBjb2xsYXIu" },
+ { "They say that an attic is the best place to hide your toys.",
+ "VGhleSBzYXkgdGhhdCBhbiBhdHRpYyBpcyB0aGUgYmVzdCBwbGFjZSB0byBoaWRlIHlvdXIgdG95cy4=" },
+ { "They say that an axe named Cleaver once belonged to a hacker named Beaver.",
+ "VGhleSBzYXkgdGhhdCBhbiBheGUgbmFtZWQgQ2xlYXZlciBvbmNlIGJlbG9uZ2VkIHRvIGEgaGFja2VyIG5hbWVkIEJlYXZlci4=" },
+ { "They say that an eye of newt and a wing of bat are double the trouble.",
+ "VGhleSBzYXkgdGhhdCBhbiBleWUgb2YgbmV3dCBhbmQgYSB3aW5nIG9mIGJhdCBhcmUgZG91YmxlIHRoZSB0cm91YmxlLg==" },
+ { "They say that an incubus named Izzy sometimes makes women feel sensitive.",
+ "VGhleSBzYXkgdGhhdCBhbiBpbmN1YnVzIG5hbWVkIEl6enkgc29tZXRpbWVzIG1ha2VzIHdvbWVuIGZlZWwgc2Vuc2l0aXZlLg==" },
+ { "They say that an opulent throne room is rarely a place to wish you'd be in.",
+ "VGhleSBzYXkgdGhhdCBhbiBvcHVsZW50IHRocm9uZSByb29tIGlzIHJhcmVseSBhIHBsYWNlIHRvIHdpc2ggeW91J2QgYmUgaW4u" },
+ { "They say that an unlucky hacker once had a nose bleed at an altar and died.",
+ "VGhleSBzYXkgdGhhdCBhbiB1bmx1Y2t5IGhhY2tlciBvbmNlIGhhZCBhIG5vc2UgYmxlZWQgYXQgYW4gYWx0YXIgYW5kIGRpZWQu" },
+ { "They say that and they say this but they never say never, never!",
+ "VGhleSBzYXkgdGhhdCBhbmQgdGhleSBzYXkgdGhpcyBidXQgdGhleSBuZXZlciBzYXkgbmV2ZXIsIG5ldmVyIQ==" },
+ { "They say that any quantum mechanic knows that speed kills.",
+ "VGhleSBzYXkgdGhhdCBhbnkgcXVhbnR1bSBtZWNoYW5pYyBrbm93cyB0aGF0IHNwZWVkIGtpbGxzLg==" },
+ { "They say that applying a unicorn horn means you've missed the point.",
+ "VGhleSBzYXkgdGhhdCBhcHBseWluZyBhIHVuaWNvcm4gaG9ybiBtZWFucyB5b3UndmUgbWlzc2VkIHRoZSBwb2ludC4=" },
+ { "They say that blue stones are radioactive, beware.",
+ "VGhleSBzYXkgdGhhdCBibHVlIHN0b25lcyBhcmUgcmFkaW9hY3RpdmUsIGJld2FyZS4=" },
+ { "They say that building a dungeon is a team effort.",
+ "VGhleSBzYXkgdGhhdCBidWlsZGluZyBhIGR1bmdlb24gaXMgYSB0ZWFtIGVmZm9ydC4=" },
+ { "They say that chaotic characters never get a kick out of altars.",
+ "VGhleSBzYXkgdGhhdCBjaGFvdGljIGNoYXJhY3RlcnMgbmV2ZXIgZ2V0IGEga2ljayBvdXQgb2YgYWx0YXJzLg==" },
+ { "They say that collapsing a dungeon often creates a panic.",
+ "VGhleSBzYXkgdGhhdCBjb2xsYXBzaW5nIGEgZHVuZ2VvbiBvZnRlbiBjcmVhdGVzIGEgcGFuaWMu" },
+ { "They say that counting your eggs before they hatch shows that you care.",
+ "VGhleSBzYXkgdGhhdCBjb3VudGluZyB5b3VyIGVnZ3MgYmVmb3JlIHRoZXkgaGF0Y2ggc2hvd3MgdGhhdCB5b3UgY2FyZS4=" },
+ { "They say that dipping a bag of tricks in a fountain won't make it an icebox.",
+ "VGhleSBzYXkgdGhhdCBkaXBwaW5nIGEgYmFnIG9mIHRyaWNrcyBpbiBhIGZvdW50YWluIHdvbid0IG1ha2UgaXQgYW4gaWNlYm94Lg==" },
+ { "They say that dipping an eel and brown mold in hot water makes bouillabaisse.",
+ "VGhleSBzYXkgdGhhdCBkaXBwaW5nIGFuIGVlbCBhbmQgYnJvd24gbW9sZCBpbiBob3Qgd2F0ZXIgbWFrZXMgYm91aWxsYWJhaXNzZS4=" },
+ { "They say that donating a doubloon is extremely pious charity.",
+ "VGhleSBzYXkgdGhhdCBkb25hdGluZyBhIGRvdWJsb29uIGlzIGV4dHJlbWVseSBwaW91cyBjaGFyaXR5Lg==" },
+ { "They say that eating royal jelly attracts grizzly owlbears.",
+ "VGhleSBzYXkgdGhhdCBlYXRpbmcgcm95YWwgamVsbHkgYXR0cmFjdHMgZ3JpenpseSBvd2xiZWFycy4=" },
+ { "They say that eggs, pancakes and juice are just a mundane breakfast.",
+ "VGhleSBzYXkgdGhhdCBlZ2dzLCBwYW5jYWtlcyBhbmQganVpY2UgYXJlIGp1c3QgYSBtdW5kYW5lIGJyZWFrZmFzdC4=" },
+ { "They say that everyone knows why Medusa stands alone in the dark.",
+ "VGhleSBzYXkgdGhhdCBldmVyeW9uZSBrbm93cyB3aHkgTWVkdXNhIHN0YW5kcyBhbG9uZSBpbiB0aGUgZGFyay4=" },
+ { "They say that everyone wanted rec.games.hack to undergo a name change.",
+ "VGhleSBzYXkgdGhhdCBldmVyeW9uZSB3YW50ZWQgcmVjLmdhbWVzLmhhY2sgdG8gdW5kZXJnbyBhIG5hbWUgY2hhbmdlLg==" },
+ { "They say that finding a winning strategy is a deliberate move on your part.",
+ "VGhleSBzYXkgdGhhdCBmaW5kaW5nIGEgd2lubmluZyBzdHJhdGVneSBpcyBhIGRlbGliZXJhdGUgbW92ZSBvbiB5b3VyIHBhcnQu" },
+ { "They say that finding worthless glass is worth something.",
+ "VGhleSBzYXkgdGhhdCBmaW5kaW5nIHdvcnRobGVzcyBnbGFzcyBpcyB3b3J0aCBzb21ldGhpbmcu" },
+ { "They say that fortune cookies are food for thought.",
+ "VGhleSBzYXkgdGhhdCBmb3J0dW5lIGNvb2tpZXMgYXJlIGZvb2QgZm9yIHRob3VnaHQu" },
+ { "They say that gold is only wasted on a pet dragon.",
+ "VGhleSBzYXkgdGhhdCBnb2xkIGlzIG9ubHkgd2FzdGVkIG9uIGEgcGV0IGRyYWdvbi4=" },
+ { "They say that good things come to those that wait.",
+ "VGhleSBzYXkgdGhhdCBnb29kIHRoaW5ncyBjb21lIHRvIHRob3NlIHRoYXQgd2FpdC4=" },
+ { "They say that greased objects will slip out of monsters' hands.",
+ "VGhleSBzYXkgdGhhdCBncmVhc2VkIG9iamVjdHMgd2lsbCBzbGlwIG91dCBvZiBtb25zdGVycycgaGFuZHMu" },
+ { "They say that if you can't spell then you'll wish you had a spell book.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UgY2FuJ3Qgc3BlbGwgdGhlbiB5b3UnbGwgd2lzaCB5b3UgaGFkIGEgc3BlbGwgYm9vay4=" },
+ { "They say that if you live by the sword, you'll die by the sword.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UgbGl2ZSBieSB0aGUgc3dvcmQsIHlvdSdsbCBkaWUgYnkgdGhlIHN3b3JkLg==" },
+ { "They say that if you play like a monster you'll have a better game.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UgcGxheSBsaWtlIGEgbW9uc3RlciB5b3UnbGwgaGF2ZSBhIGJldHRlciBnYW1lLg==" },
+ { "They say that if you sleep with a demon you might awake with a headache.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3Ugc2xlZXAgd2l0aCBhIGRlbW9uIHlvdSBtaWdodCBhd2FrZSB3aXRoIGEgaGVhZGFjaGUu" },
+ { "They say that if you step on a crack you could break your mother's back.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3Ugc3RlcCBvbiBhIGNyYWNrIHlvdSBjb3VsZCBicmVhayB5b3VyIG1vdGhlcidzIGJhY2su" },
+ { "They say that if you're invisible you can still be heard!",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UncmUgaW52aXNpYmxlIHlvdSBjYW4gc3RpbGwgYmUgaGVhcmQh" },
+ { "They say that if you're lucky you can feel the runes on a scroll.",
+ "VGhleSBzYXkgdGhhdCBpZiB5b3UncmUgbHVja3kgeW91IGNhbiBmZWVsIHRoZSBydW5lcyBvbiBhIHNjcm9sbC4=" },
+ { "They say that in the big picture gold is only small change.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgYmlnIHBpY3R1cmUgZ29sZCBpcyBvbmx5IHNtYWxsIGNoYW5nZS4=" },
+ { "They say that in the dungeon it's not what you know that really matters.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiBpdCdzIG5vdCB3aGF0IHlvdSBrbm93IHRoYXQgcmVhbGx5IG1hdHRlcnMu" },
+ { "They say that in the dungeon moon rocks are really dilithium crystals.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiBtb29uIHJvY2tzIGFyZSByZWFsbHkgZGlsaXRoaXVtIGNyeXN0YWxzLg==" },
+ { "They say that in the dungeon the boorish customer is never right.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB0aGUgYm9vcmlzaCBjdXN0b21lciBpcyBuZXZlciByaWdodC4=" },
+ { "They say that in the dungeon you don't need a watch to tell time.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3UgZG9uJ3QgbmVlZCBhIHdhdGNoIHRvIHRlbGwgdGltZS4=" },
+ { "They say that in the dungeon you need something old, new, burrowed and blue.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3UgbmVlZCBzb21ldGhpbmcgb2xkLCBuZXcsIGJ1cnJvd2VkIGFuZCBibHVlLg==" },
+ { "They say that in the dungeon you should always count your blessings.",
+ "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3Ugc2hvdWxkIGFsd2F5cyBjb3VudCB5b3VyIGJsZXNzaW5ncy4=" },
+ { "They say that iron golem plate mail isn't worth wishing for.",
+ "VGhleSBzYXkgdGhhdCBpcm9uIGdvbGVtIHBsYXRlIG1haWwgaXNuJ3Qgd29ydGggd2lzaGluZyBmb3Iu" },
+ { "They say that it takes four quarterstaffs to make one staff.",
+ "VGhleSBzYXkgdGhhdCBpdCB0YWtlcyBmb3VyIHF1YXJ0ZXJzdGFmZnMgdG8gbWFrZSBvbmUgc3RhZmYu" },
+ { "They say that it's not over till the fat ladies sing.",
+ "VGhleSBzYXkgdGhhdCBpdCdzIG5vdCBvdmVyIHRpbGwgdGhlIGZhdCBsYWRpZXMgc2luZy4=" },
+ { "They say that it's not over till the fat lady shouts `Off with its head'.",
+ "VGhleSBzYXkgdGhhdCBpdCdzIG5vdCBvdmVyIHRpbGwgdGhlIGZhdCBsYWR5IHNob3V0cyBgT2ZmIHdpdGggaXRzIGhlYWQnLg==" },
+ { "They say that kicking a heavy statue is really a dumb move.",
+ "VGhleSBzYXkgdGhhdCBraWNraW5nIGEgaGVhdnkgc3RhdHVlIGlzIHJlYWxseSBhIGR1bWIgbW92ZS4=" },
+ { "They say that kicking a valuable gem doesn't seem to make sense.",
+ "VGhleSBzYXkgdGhhdCBraWNraW5nIGEgdmFsdWFibGUgZ2VtIGRvZXNuJ3Qgc2VlbSB0byBtYWtlIHNlbnNlLg==" },
+ { "They say that leprechauns know Latin and you should too.",
+ "VGhleSBzYXkgdGhhdCBsZXByZWNoYXVucyBrbm93IExhdGluIGFuZCB5b3Ugc2hvdWxkIHRvby4=" },
+ { "They say that minotaurs get lost outside of the mazes.",
+ "VGhleSBzYXkgdGhhdCBtaW5vdGF1cnMgZ2V0IGxvc3Qgb3V0c2lkZSBvZiB0aGUgbWF6ZXMu" },
+ { "They say that most trolls are born again.",
+ "VGhleSBzYXkgdGhhdCBtb3N0IHRyb2xscyBhcmUgYm9ybiBhZ2Fpbi4=" },
+ { "They say that naming your cat Garfield will make you more attractive.",
+ "VGhleSBzYXkgdGhhdCBuYW1pbmcgeW91ciBjYXQgR2FyZmllbGQgd2lsbCBtYWtlIHlvdSBtb3JlIGF0dHJhY3RpdmUu" },
+ { "They say that no one knows everything about everything in the dungeon.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUga25vd3MgZXZlcnl0aGluZyBhYm91dCBldmVyeXRoaW5nIGluIHRoZSBkdW5nZW9uLg==" },
+ { "They say that no one plays NetHack just for the fun of it.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUgcGxheXMgTmV0SGFjayBqdXN0IGZvciB0aGUgZnVuIG9mIGl0Lg==" },
+ { "They say that no one really subscribes to rec.games.roguelike.nethack.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUgcmVhbGx5IHN1YnNjcmliZXMgdG8gcmVjLmdhbWVzLnJvZ3VlbGlrZS5uZXRoYWNrLg==" },
+ { "They say that no one will admit to starting a rumor.",
+ "VGhleSBzYXkgdGhhdCBubyBvbmUgd2lsbCBhZG1pdCB0byBzdGFydGluZyBhIHJ1bW9yLg==" },
+ { "They say that nurses sometimes carry scalpels and never use them.",
+ "VGhleSBzYXkgdGhhdCBudXJzZXMgc29tZXRpbWVzIGNhcnJ5IHNjYWxwZWxzIGFuZCBuZXZlciB1c2UgdGhlbS4=" },
+ { "They say that once you've met one wizard you've met them all.",
+ "VGhleSBzYXkgdGhhdCBvbmNlIHlvdSd2ZSBtZXQgb25lIHdpemFyZCB5b3UndmUgbWV0IHRoZW0gYWxsLg==" },
+ { "They say that one troll is worth 10,000 newts.",
+ "VGhleSBzYXkgdGhhdCBvbmUgdHJvbGwgaXMgd29ydGggMTAsMDAwIG5ld3RzLg==" },
+ { "They say that only David can find the zoo!",
+ "VGhleSBzYXkgdGhhdCBvbmx5IERhdmlkIGNhbiBmaW5kIHRoZSB6b28h" },
+ { "They say that only angels play their harps for their pets.",
+ "VGhleSBzYXkgdGhhdCBvbmx5IGFuZ2VscyBwbGF5IHRoZWlyIGhhcnBzIGZvciB0aGVpciBwZXRzLg==" },
+ { "They say that only big spenders carry gold.",
+ "VGhleSBzYXkgdGhhdCBvbmx5IGJpZyBzcGVuZGVycyBjYXJyeSBnb2xkLg==" },
+ { "They say that orc shamans are healthy, wealthy and wise.",
+ "VGhleSBzYXkgdGhhdCBvcmMgc2hhbWFucyBhcmUgaGVhbHRoeSwgd2VhbHRoeSBhbmQgd2lzZS4=" },
+ { "They say that playing NetHack is like walking into a death trap.",
+ "VGhleSBzYXkgdGhhdCBwbGF5aW5nIE5ldEhhY2sgaXMgbGlrZSB3YWxraW5nIGludG8gYSBkZWF0aCB0cmFwLg==" },
+ { "They say that problem breathing is best treated by a proper diet.",
+ "VGhleSBzYXkgdGhhdCBwcm9ibGVtIGJyZWF0aGluZyBpcyBiZXN0IHRyZWF0ZWQgYnkgYSBwcm9wZXIgZGlldC4=" },
+ { "They say that quaffing many potions of levitation can give you a headache.",
+ "VGhleSBzYXkgdGhhdCBxdWFmZmluZyBtYW55IHBvdGlvbnMgb2YgbGV2aXRhdGlvbiBjYW4gZ2l2ZSB5b3UgYSBoZWFkYWNoZS4=" },
+ { "They say that queen bees get that way by eating royal jelly.",
+ "VGhleSBzYXkgdGhhdCBxdWVlbiBiZWVzIGdldCB0aGF0IHdheSBieSBlYXRpbmcgcm95YWwgamVsbHku" },
+ { "They say that reading a scare monster scroll is the same as saying Elbereth.",
+ "VGhleSBzYXkgdGhhdCByZWFkaW5nIGEgc2NhcmUgbW9uc3RlciBzY3JvbGwgaXMgdGhlIHNhbWUgYXMgc2F5aW5nIEVsYmVyZXRoLg==" },
+ { "They say that real hackers always are controlled.",
+ "VGhleSBzYXkgdGhhdCByZWFsIGhhY2tlcnMgYWx3YXlzIGFyZSBjb250cm9sbGVkLg==" },
+ { "They say that real hackers never sleep.",
+ "VGhleSBzYXkgdGhhdCByZWFsIGhhY2tlcnMgbmV2ZXIgc2xlZXAu" },
+ { "They say that shopkeepers are insured by Croesus himself!",
+ "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBhcmUgaW5zdXJlZCBieSBDcm9lc3VzIGhpbXNlbGYh" },
+ { "They say that shopkeepers never carry more than 20 gold pieces, at night.",
+ "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBuZXZlciBjYXJyeSBtb3JlIHRoYW4gMjAgZ29sZCBwaWVjZXMsIGF0IG5pZ2h0Lg==" },
+ { "They say that shopkeepers never sell blessed potions of invisibility.",
+ "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBuZXZlciBzZWxsIGJsZXNzZWQgcG90aW9ucyBvZiBpbnZpc2liaWxpdHku" },
+ { "They say that soldiers wear kid gloves and silly helmets.",
+ "VGhleSBzYXkgdGhhdCBzb2xkaWVycyB3ZWFyIGtpZCBnbG92ZXMgYW5kIHNpbGx5IGhlbG1ldHMu" },
+ { "They say that some Kops are on the take.",
+ "VGhleSBzYXkgdGhhdCBzb21lIEtvcHMgYXJlIG9uIHRoZSB0YWtlLg==" },
+ { "They say that some guards' palms can be greased.",
+ "VGhleSBzYXkgdGhhdCBzb21lIGd1YXJkcycgcGFsbXMgY2FuIGJlIGdyZWFzZWQu" },
+ { "They say that some monsters may kiss your boots to stop your drum playing.",
+ "VGhleSBzYXkgdGhhdCBzb21lIG1vbnN0ZXJzIG1heSBraXNzIHlvdXIgYm9vdHMgdG8gc3RvcCB5b3VyIGRydW0gcGxheWluZy4=" },
+ { "They say that sometimes you can be the hit of the party when playing a horn.",
+ "VGhleSBzYXkgdGhhdCBzb21ldGltZXMgeW91IGNhbiBiZSB0aGUgaGl0IG9mIHRoZSBwYXJ0eSB3aGVuIHBsYXlpbmcgYSBob3JuLg==" },
+ { "They say that the NetHack gods generally welcome your sacrifices.",
+ "VGhleSBzYXkgdGhhdCB0aGUgTmV0SGFjayBnb2RzIGdlbmVyYWxseSB3ZWxjb21lIHlvdXIgc2FjcmlmaWNlcy4=" },
+ { "They say that the Three Rings are named Vilya, Nenya and Narya.",
+ "VGhleSBzYXkgdGhhdCB0aGUgVGhyZWUgUmluZ3MgYXJlIG5hbWVkIFZpbHlhLCBOZW55YSBhbmQgTmFyeWEu" },
+ { "They say that the Wizard of Yendor has a death wish.",
+ "VGhleSBzYXkgdGhhdCB0aGUgV2l6YXJkIG9mIFllbmRvciBoYXMgYSBkZWF0aCB3aXNoLg==" },
+ { "They say that the `hair of the dog' is sometimes an effective remedy.",
+ "VGhleSBzYXkgdGhhdCB0aGUgYGhhaXIgb2YgdGhlIGRvZycgaXMgc29tZXRpbWVzIGFuIGVmZmVjdGl2ZSByZW1lZHku" },
+ { "They say that the best time to save your game is now before its too late.",
+ "VGhleSBzYXkgdGhhdCB0aGUgYmVzdCB0aW1lIHRvIHNhdmUgeW91ciBnYW1lIGlzIG5vdyBiZWZvcmUgaXRzIHRvbyBsYXRlLg==" },
+ { "They say that the biggest obstacle in NetHack is your mind.",
+ "VGhleSBzYXkgdGhhdCB0aGUgYmlnZ2VzdCBvYnN0YWNsZSBpbiBOZXRIYWNrIGlzIHlvdXIgbWluZC4=" },
+ { "They say that the gods are angry when they hit you with objects.",
+ "VGhleSBzYXkgdGhhdCB0aGUgZ29kcyBhcmUgYW5ncnkgd2hlbiB0aGV5IGhpdCB5b3Ugd2l0aCBvYmplY3RzLg==" },
+ { "They say that the priesthood are specially favored by the gods.",
+ "VGhleSBzYXkgdGhhdCB0aGUgcHJpZXN0aG9vZCBhcmUgc3BlY2lhbGx5IGZhdm9yZWQgYnkgdGhlIGdvZHMu" },
+ { "They say that the way to make a unicorn happy is to give it what it wants.",
+ "VGhleSBzYXkgdGhhdCB0aGUgd2F5IHRvIG1ha2UgYSB1bmljb3JuIGhhcHB5IGlzIHRvIGdpdmUgaXQgd2hhdCBpdCB3YW50cy4=" },
+ { "They say that there are no black or white stones, only gray.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBhcmUgbm8gYmxhY2sgb3Igd2hpdGUgc3RvbmVzLCBvbmx5IGdyYXku" },
+ { "They say that there are no skeletons hence there are no skeleton keys.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBhcmUgbm8gc2tlbGV0b25zIGhlbmNlIHRoZXJlIGFyZSBubyBza2VsZXRvbiBrZXlzLg==" },
+ { "They say that there is a clever rogue in every hacker just dying to escape.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBhIGNsZXZlciByb2d1ZSBpbiBldmVyeSBoYWNrZXIganVzdCBkeWluZyB0byBlc2NhcGUu" },
+ { "They say that there is no such thing as free advice.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBubyBzdWNoIHRoaW5nIGFzIGZyZWUgYWR2aWNlLg==" },
+ { "They say that there is only one way to win at NetHack.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBvbmx5IG9uZSB3YXkgdG8gd2luIGF0IE5ldEhhY2su" },
+ { "They say that there once was a fearsome chaotic samurai named Luk No.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSBvbmNlIHdhcyBhIGZlYXJzb21lIGNoYW90aWMgc2FtdXJhaSBuYW1lZCBMdWsgTm8u" },
+ { "They say that there was a time when cursed holy water wasn't water.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSB3YXMgYSB0aW1lIHdoZW4gY3Vyc2VkIGhvbHkgd2F0ZXIgd2Fzbid0IHdhdGVyLg==" },
+ { "They say that there's no point in crying over a gray ooze.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSdzIG5vIHBvaW50IGluIGNyeWluZyBvdmVyIGEgZ3JheSBvb3plLg==" },
+ { "They say that there's only hope left after you've opened Pandora's box.",
+ "VGhleSBzYXkgdGhhdCB0aGVyZSdzIG9ubHkgaG9wZSBsZWZ0IGFmdGVyIHlvdSd2ZSBvcGVuZWQgUGFuZG9yYSdzIGJveC4=" },
+ { "They say that trapdoors should always be marked `Caution: Trap Door'.",
+ "VGhleSBzYXkgdGhhdCB0cmFwZG9vcnMgc2hvdWxkIGFsd2F5cyBiZSBtYXJrZWQgYENhdXRpb246IFRyYXAgRG9vcicu" },
+ { "They say that using an amulet of change isn't a difficult operation.",
+ "VGhleSBzYXkgdGhhdCB1c2luZyBhbiBhbXVsZXQgb2YgY2hhbmdlIGlzbid0IGEgZGlmZmljdWx0IG9wZXJhdGlvbi4=" },
+ { "They say that water walking boots are better if you are fast like Hermes.",
+ "VGhleSBzYXkgdGhhdCB3YXRlciB3YWxraW5nIGJvb3RzIGFyZSBiZXR0ZXIgaWYgeW91IGFyZSBmYXN0IGxpa2UgSGVybWVzLg==" },
+ { "They say that when you wear a circular amulet you might resemble a troll.",
+ "VGhleSBzYXkgdGhhdCB3aGVuIHlvdSB3ZWFyIGEgY2lyY3VsYXIgYW11bGV0IHlvdSBtaWdodCByZXNlbWJsZSBhIHRyb2xsLg==" },
+ { "They say that when you're hungry you can get a pizza in 30 moves or it's free.",
+ "VGhleSBzYXkgdGhhdCB3aGVuIHlvdSdyZSBodW5ncnkgeW91IGNhbiBnZXQgYSBwaXp6YSBpbiAzMCBtb3ZlcyBvciBpdCdzIGZyZWUu" },
+ { "They say that when your god is angry you should try another one.",
+ "VGhleSBzYXkgdGhhdCB3aGVuIHlvdXIgZ29kIGlzIGFuZ3J5IHlvdSBzaG91bGQgdHJ5IGFub3RoZXIgb25lLg==" },
+ { "They say that wielding a unicorn horn takes strength.",
+ "VGhleSBzYXkgdGhhdCB3aWVsZGluZyBhIHVuaWNvcm4gaG9ybiB0YWtlcyBzdHJlbmd0aC4=" },
+ { "They say that with speed boots you never worry about hit and run accidents.",
+ "VGhleSBzYXkgdGhhdCB3aXRoIHNwZWVkIGJvb3RzIHlvdSBuZXZlciB3b3JyeSBhYm91dCBoaXQgYW5kIHJ1biBhY2NpZGVudHMu" },
+ { "They say that you can defeat a killer bee with a unicorn horn.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIGRlZmVhdCBhIGtpbGxlciBiZWUgd2l0aCBhIHVuaWNvcm4gaG9ybi4=" },
+ { "They say that you can only cross the River Styx in Charon's boat.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkgY3Jvc3MgdGhlIFJpdmVyIFN0eXggaW4gQ2hhcm9uJ3MgYm9hdC4=" },
+ { "They say that you can only kill a lich once and then you'd better be careful.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkga2lsbCBhIGxpY2ggb25jZSBhbmQgdGhlbiB5b3UnZCBiZXR0ZXIgYmUgY2FyZWZ1bC4=" },
+ { "They say that you can only wish for things you've already had.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkgd2lzaCBmb3IgdGhpbmdzIHlvdSd2ZSBhbHJlYWR5IGhhZC4=" },
+ { "They say that you can train a cat by talking gently to it.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRyYWluIGEgY2F0IGJ5IHRhbGtpbmcgZ2VudGx5IHRvIGl0Lg==" },
+ { "They say that you can train a dog by talking firmly to it.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRyYWluIGEgZG9nIGJ5IHRhbGtpbmcgZmlybWx5IHRvIGl0Lg==" },
+ { "They say that you can trust your gold with the king.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRydXN0IHlvdXIgZ29sZCB3aXRoIHRoZSBraW5nLg==" },
+ { "They say that you can't wipe your greasy bare hands on a blank scroll.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2FuJ3Qgd2lwZSB5b3VyIGdyZWFzeSBiYXJlIGhhbmRzIG9uIGEgYmxhbmsgc2Nyb2xsLg==" },
+ { "They say that you cannot trust scrolls of rumor.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY2Fubm90IHRydXN0IHNjcm9sbHMgb2YgcnVtb3Iu" },
+ { "They say that you could fall head over heels for an energy vortex.",
+ "VGhleSBzYXkgdGhhdCB5b3UgY291bGQgZmFsbCBoZWFkIG92ZXIgaGVlbHMgZm9yIGFuIGVuZXJneSB2b3J0ZXgu" },
+ { "They say that you need a key in order to open locked doors.",
+ "VGhleSBzYXkgdGhhdCB5b3UgbmVlZCBhIGtleSBpbiBvcmRlciB0byBvcGVuIGxvY2tlZCBkb29ycy4=" },
+ { "They say that you need a mirror to notice a mimic in an antique shop.",
+ "VGhleSBzYXkgdGhhdCB5b3UgbmVlZCBhIG1pcnJvciB0byBub3RpY2UgYSBtaW1pYyBpbiBhbiBhbnRpcXVlIHNob3Au" },
+ { "They say that you really can use a pick-axe unless you really can't.",
+ "VGhleSBzYXkgdGhhdCB5b3UgcmVhbGx5IGNhbiB1c2UgYSBwaWNrLWF4ZSB1bmxlc3MgeW91IHJlYWxseSBjYW4ndC4=" },
+ { "They say that you should always store your tools in the cellar.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGFsd2F5cyBzdG9yZSB5b3VyIHRvb2xzIGluIHRoZSBjZWxsYXIu" },
+ { "They say that you should be careful while climbing the ladder to success.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGJlIGNhcmVmdWwgd2hpbGUgY2xpbWJpbmcgdGhlIGxhZGRlciB0byBzdWNjZXNzLg==" },
+ { "They say that you should call your armor `rustproof'.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGNhbGwgeW91ciBhcm1vciBgcnVzdHByb29mJy4=" },
+ { "They say that you should name your dog Spuds to have a cool pet.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5hbWUgeW91ciBkb2cgU3B1ZHMgdG8gaGF2ZSBhIGNvb2wgcGV0Lg==" },
+ { "They say that you should name your weapon after your first monster kill.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5hbWUgeW91ciB3ZWFwb24gYWZ0ZXIgeW91ciBmaXJzdCBtb25zdGVyIGtpbGwu" },
+ { "They say that you should never introduce a rope golem to a succubus.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIGludHJvZHVjZSBhIHJvcGUgZ29sZW0gdG8gYSBzdWNjdWJ1cy4=" },
+ { "They say that you should never sleep near invisible ring wraiths.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIHNsZWVwIG5lYXIgaW52aXNpYmxlIHJpbmcgd3JhaXRocy4=" },
+ { "They say that you should never try to leave the dungeon with a bag of gems.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIHRyeSB0byBsZWF2ZSB0aGUgZHVuZ2VvbiB3aXRoIGEgYmFnIG9mIGdlbXMu" },
+ { "They say that you should remove your armor before sitting on a throne.",
+ "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIHJlbW92ZSB5b3VyIGFybW9yIGJlZm9yZSBzaXR0aW5nIG9uIGEgdGhyb25lLg==" },
+ { "This fortune cookie is copy protected.",
+ "VGhpcyBmb3J0dW5lIGNvb2tpZSBpcyBjb3B5IHByb3RlY3RlZC4=" },
+ { "This fortune cookie is the property of Fortune Cookies, Inc.",
+ "VGhpcyBmb3J0dW5lIGNvb2tpZSBpcyB0aGUgcHJvcGVydHkgb2YgRm9ydHVuZSBDb29raWVzLCBJbmMu" },
+ { "Tired? Try a scroll of charging on yourself.",
+ "VGlyZWQ/IFRyeSBhIHNjcm9sbCBvZiBjaGFyZ2luZyBvbiB5b3Vyc2VsZi4=" },
+ { "To achieve the next higher rating, you need 3 more points.",
+ "VG8gYWNoaWV2ZSB0aGUgbmV4dCBoaWdoZXIgcmF0aW5nLCB5b3UgbmVlZCAzIG1vcmUgcG9pbnRzLg==" },
+ { "To reach heaven, escape the dungeon while wearing a ring of levitation.",
+ "VG8gcmVhY2ggaGVhdmVuLCBlc2NhcGUgdGhlIGR1bmdlb24gd2hpbGUgd2VhcmluZyBhIHJpbmcgb2YgbGV2aXRhdGlvbi4=" },
+ { "Tourists wear shirts loud enough to wake the dead.",
+ "VG91cmlzdHMgd2VhciBzaGlydHMgbG91ZCBlbm91Z2ggdG8gd2FrZSB0aGUgZGVhZC4=" },
+ { "Try calling your katana Moulinette.",
+ "VHJ5IGNhbGxpbmcgeW91ciBrYXRhbmEgTW91bGluZXR0ZS4=" },
+ { "Ulch! That meat was painted!",
+ "VWxjaCEgVGhhdCBtZWF0IHdhcyBwYWludGVkIQ==" },
+ { "Unfortunately, this message was left intentionally blank.",
+ "VW5mb3J0dW5hdGVseSwgdGhpcyBtZXNzYWdlIHdhcyBsZWZ0IGludGVudGlvbmFsbHkgYmxhbmsu" },
+ { "Using a morning star in the evening has no effect.",
+ "VXNpbmcgYSBtb3JuaW5nIHN0YXIgaW4gdGhlIGV2ZW5pbmcgaGFzIG5vIGVmZmVjdC4=" },
+ { "Want a hint? Zap a wand of make invisible on your weapon!",
+ "V2FudCBhIGhpbnQ/IFphcCBhIHdhbmQgb2YgbWFrZSBpbnZpc2libGUgb24geW91ciB3ZWFwb24h" },
+ { "Want to ascend in a hurry? Apply at Gizmonic Institute.",
+ "V2FudCB0byBhc2NlbmQgaW4gYSBodXJyeT8gQXBwbHkgYXQgR2l6bW9uaWMgSW5zdGl0dXRlLg==" },
+ { "Wanted: shopkeepers. Send a scroll of mail to Mage of Yendor/Level 35/Dungeon.",
+ "V2FudGVkOiBzaG9wa2VlcGVycy4gU2VuZCBhIHNjcm9sbCBvZiBtYWlsIHRvIE1hZ2Ugb2YgWWVuZG9yL0xldmVsIDM1L0R1bmdlb24u" },
+ { "Warning: fortune reading can be hazardous to your health.",
+ "V2FybmluZzogZm9ydHVuZSByZWFkaW5nIGNhbiBiZSBoYXphcmRvdXMgdG8geW91ciBoZWFsdGgu" },
+ { "We have new ways of detecting treachery...",
+ "V2UgaGF2ZSBuZXcgd2F5cyBvZiBkZXRlY3RpbmcgdHJlYWNoZXJ5Li4u" },
+ { "Wet towels make great weapons!",
+ "V2V0IHRvd2VscyBtYWtlIGdyZWF0IHdlYXBvbnMh" },
+ { "What a pity, you cannot read it!",
+ "V2hhdCBhIHBpdHksIHlvdSBjYW5ub3QgcmVhZCBpdCE=" },
+ { "When a piercer drops in on you, you will be tempted to hit the ceiling!",
+ "V2hlbiBhIHBpZXJjZXIgZHJvcHMgaW4gb24geW91LCB5b3Ugd2lsbCBiZSB0ZW1wdGVkIHRvIGhpdCB0aGUgY2VpbGluZyE=" },
+ { "When in a maze follow the right wall and you will never get lost.",
+ "V2hlbiBpbiBhIG1hemUgZm9sbG93IHRoZSByaWdodCB3YWxsIGFuZCB5b3Ugd2lsbCBuZXZlciBnZXQgbG9zdC4=" },
+ { "When you have a key, you don't have to wait for the guard.",
+ "V2hlbiB5b3UgaGF2ZSBhIGtleSwgeW91IGRvbid0IGhhdmUgdG8gd2FpdCBmb3IgdGhlIGd1YXJkLg==" },
+ { "Why are you wasting time reading fortunes?",
+ "V2h5IGFyZSB5b3Ugd2FzdGluZyB0aW1lIHJlYWRpbmcgZm9ydHVuZXM/" },
+ { "Wish for a master key and open the Magic Memory Vault!",
+ "V2lzaCBmb3IgYSBtYXN0ZXIga2V5IGFuZCBvcGVuIHRoZSBNYWdpYyBNZW1vcnkgVmF1bHQh" },
+ { "Wizard expects every monster to do its duty.",
+ "V2l6YXJkIGV4cGVjdHMgZXZlcnkgbW9uc3RlciB0byBkbyBpdHMgZHV0eS4=" },
+ { "Wow! You could've had a potion of fruit juice!",
+ "V293ISBZb3UgY291bGQndmUgaGFkIGEgcG90aW9uIG9mIGZydWl0IGp1aWNlIQ==" },
+ { "Yet Another Silly Message (YASM).",
+ "WWV0IEFub3RoZXIgU2lsbHkgTWVzc2FnZSAoWUFTTSku" },
+ { "You are destined to be misled by a fortune.",
+ "WW91IGFyZSBkZXN0aW5lZCB0byBiZSBtaXNsZWQgYnkgYSBmb3J0dW5lLg==" },
+ { "You can get a genuine Amulet of Yendor by doing the following: --More--",
+ "WW91IGNhbiBnZXQgYSBnZW51aW5lIEFtdWxldCBvZiBZZW5kb3IgYnkgZG9pbmcgdGhlIGZvbGxvd2luZzogLS1Nb3JlLS0=" },
+ { "You can protect yourself from black dragons by doing the following: --More--",
+ "WW91IGNhbiBwcm90ZWN0IHlvdXJzZWxmIGZyb20gYmxhY2sgZHJhZ29ucyBieSBkb2luZyB0aGUgZm9sbG93aW5nOiAtLU1vcmUtLQ==" },
+ { "You can't get by the snake.",
+ "WW91IGNhbid0IGdldCBieSB0aGUgc25ha2Uu" },
+ { "You feel like someone is pulling your leg.",
+ "WW91IGZlZWwgbGlrZSBzb21lb25lIGlzIHB1bGxpbmcgeW91ciBsZWcu" },
+ { "You have to outwit the Sphynx or pay her.",
+ "WW91IGhhdmUgdG8gb3V0d2l0IHRoZSBTcGh5bnggb3IgcGF5IGhlci4=" },
+ { "You hear the fortune cookie's hissing!",
+ "WW91IGhlYXIgdGhlIGZvcnR1bmUgY29va2llJ3MgaGlzc2luZyE=" },
+ { "You may get rich selling letters, but beware of being blackmailed!",
+ "WW91IG1heSBnZXQgcmljaCBzZWxsaW5nIGxldHRlcnMsIGJ1dCBiZXdhcmUgb2YgYmVpbmcgYmxhY2ttYWlsZWQh" },
+ { "You offend Shai-Hulud by sheathing your crysknife without having drawn blood.",
+ "WW91IG9mZmVuZCBTaGFpLUh1bHVkIGJ5IHNoZWF0aGluZyB5b3VyIGNyeXNrbmlmZSB3aXRob3V0IGhhdmluZyBkcmF3biBibG9vZC4=" },
+ { "You swallowed the fortune!",
+ "WW91IHN3YWxsb3dlZCB0aGUgZm9ydHVuZSE=" },
+ { "You want to regain strength? Two levels ahead is a guesthouse!",
+ "WW91IHdhbnQgdG8gcmVnYWluIHN0cmVuZ3RoPyBUd28gbGV2ZWxzIGFoZWFkIGlzIGEgZ3Vlc3Rob3VzZSE=" },
+ { "You will encounter a tall, dark, and gruesome creature...",
+ "WW91IHdpbGwgZW5jb3VudGVyIGEgdGFsbCwgZGFyaywgYW5kIGdydWVzb21lIGNyZWF0dXJlLi4u" },
+
+ { "The End", "VGhlIEVuZA==" }
+ };
+
+/* PL_Base64Encode, random strings */
+PRBool test_004(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 004 (PL_Base64Encode, random strings) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, plen, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].cyphertext, clen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, clen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, single characters, malloc */
+PRBool test_005(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 005 (PL_Base64Encode, single characters, malloc) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Encode((char *)plain, 1, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d): no return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)cypher, rv) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, double characters, malloc */
+PRBool test_006(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 006 (PL_Base64Encode, double characters, malloc) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Encode((char *)plain, 2, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)cypher, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, c, d, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, triple characters, malloc */
+PRBool test_007(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 007 (PL_Base64Encode, triple characters, malloc) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Encode((char *)plain, 3, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): no return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)cypher, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n",
+ a, b, c, d, e, f, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_008(void)
+{
+ int i;
+
+ printf("Test 008 (PL_Base64Encode, random strings, malloc) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, plen, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].cyphertext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters */
+PRBool test_009(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 009 (PL_Base64Decode, single characters, equals) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 4, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d): return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 1) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.1s.\"\n",
+ a, b, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters */
+PRBool test_010(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 010 (PL_Base64Decode, single characters, no equals) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 2, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d): return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 1) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.1s.\"\n",
+ a, b, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters */
+PRBool test_011(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 011 (PL_Base64Decode, double characters, equals) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 4, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 2) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.2s.\"\n",
+ a, b, c, d, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters */
+PRBool test_012(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 012 (PL_Base64Decode, double characters, no equals) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 3, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 2) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.2s.\"\n",
+ a, b, c, d, cypher, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, triple characters */
+PRBool test_013(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char result[ 8 ];
+ char *rv;
+
+ printf("Test 013 (PL_Base64Decode, triple characters) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Decode((char *)cypher, 4, result);
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp((char *)plain, result, 3) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.3s.\"\n",
+ a, b, c, d, e, f, plain, result);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_014(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 014 (PL_Base64Decode, random strings, equals) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+ PRUint32 plen = (clen * 3) / 4;
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, clen, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == array[i].cyphertext[clen-1] )
+ {
+ if( '=' == array[i].cyphertext[clen-2] )
+ {
+ plen -= 2;
+ }
+ else
+ {
+ plen -= 1;
+ }
+ }
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_015(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char result[ 4096 ];
+ char *rv;
+
+ printf("Test 015 (PL_Base64Decode, random strings, no equals) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen, plen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ plen = (clen * 3) / 4;
+
+ rv = PL_Base64Decode(buffer, clen, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters, malloc */
+PRBool test_016(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 016 (PL_Base64Decode, single characters, equals, malloc) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 4, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d): no return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, single characters, malloc */
+PRBool test_017(void)
+{
+ PRUint32 a, b;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 017 (PL_Base64Decode, single characters, no equals, malloc) ..."); fflush(stdout);
+
+ plain[1] = plain[2] = plain[3] = (unsigned char)0;
+ cypher[2] = cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (unsigned char)(a * 4 + b);
+ cypher[1] = base[(b * 16)];
+
+ rv = PL_Base64Decode((char *)cypher, 2, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d): no return value\n", a, b);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters, malloc */
+PRBool test_018(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 018 (PL_Base64Decode, double characters, equals, malloc) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)'=';
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 4, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, c, d, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, double characters, malloc */
+PRBool test_019(void)
+{
+ PRUint32 a, b, c, d;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 019 (PL_Base64Decode, double characters, no equals, malloc) ..."); fflush(stdout);
+
+ plain[2] = plain[3] = (unsigned char)0;
+ cypher[3] = (unsigned char)0;
+ cypher[4] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ cypher[2] = base[d*4];
+
+ rv = PL_Base64Decode((char *)cypher, 3, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n",
+ a, b, c, d, cypher, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, triple characters, malloc */
+PRBool test_020(void)
+{
+ PRUint32 a, b, c, d, e, f;
+ unsigned char plain[ 4 ];
+ unsigned char cypher[ 5 ];
+ char *rv;
+
+ printf("Test 020 (PL_Base64Decode, triple characters, malloc) ..."); fflush(stdout);
+
+ cypher[4] = (unsigned char)0;
+ plain[3] = (unsigned char)0;
+
+ for( a = 0; a < 64; a++ )
+ {
+ cypher[0] = base[a];
+ for( b = 0; b < 4; b++ )
+ {
+ plain[0] = (a*4) + b;
+ for( c = 0; c < 16; c++ )
+ {
+ cypher[1] = base[b*16 + c];
+ for( d = 0; d < 16; d++ )
+ {
+ plain[1] = c*16 + d;
+ for( e = 0; e < 4; e++ )
+ {
+ cypher[2] = base[d*4 + e];
+ for( f = 0; f < 64; f++ )
+ {
+ plain[2] = e * 64 + f;
+ cypher[3] = base[f];
+
+ rv = PL_Base64Decode((char *)cypher, 4, (char *)0);
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): no return value\n", a, b, c, d, e, f);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp((char *)plain, rv) )
+ {
+ printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.3s.\"\n",
+ a, b, c, d, e, f, plain, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings, malloc */
+PRBool test_021(void)
+{
+ int i;
+
+ printf("Test 021 (PL_Base64Decode, random strings, equals, malloc) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, clen, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_022(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char *rv;
+
+ printf("Test 022 (PL_Base64Decode, random strings, no equals, malloc) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ rv = PL_Base64Decode(buffer, clen, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings */
+PRBool test_023(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 023 (PL_Base64Encode, random strings, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, 0, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].cyphertext, clen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, clen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_024(void)
+{
+ int i;
+
+ printf("Test 024 (PL_Base64Encode, random strings, malloc, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 plen = PL_strlen(array[i].plaintext);
+ PRUint32 clen = ((plen + 2)/3)*4;
+
+ char *rv = PL_Base64Encode(array[i].plaintext, 0, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].cyphertext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].plaintext, array[i].cyphertext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_025(void)
+{
+ int i;
+ char result[ 4096 ];
+
+ printf("Test 025 (PL_Base64Decode, random strings, equals, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+ PRUint32 plen = (clen * 3) / 4;
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, 0, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == array[i].cyphertext[clen-1] )
+ {
+ if( '=' == array[i].cyphertext[clen-2] )
+ {
+ plen -= 2;
+ }
+ else
+ {
+ plen -= 1;
+ }
+ }
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings */
+PRBool test_026(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char result[ 4096 ];
+ char *rv;
+
+ printf("Test 026 (PL_Base64Decode, random strings, no equals, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen, plen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ plen = (clen * 3) / 4;
+
+ rv = PL_Base64Decode(buffer, 0, result);
+
+ if( rv != result )
+ {
+ printf("FAIL\n\t(%d): return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strncmp(result, array[i].plaintext, plen) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, plen, result);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Decode, random strings, malloc */
+PRBool test_027(void)
+{
+ int i;
+
+ printf("Test 027 (PL_Base64Decode, random strings, equals, malloc, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen = PL_strlen(array[i].cyphertext);
+
+ char *rv = PL_Base64Decode(array[i].cyphertext, 0, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ PR_DELETE(rv);
+ return PR_FALSE;
+ }
+
+ PR_DELETE(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_Base64Encode, random strings, malloc */
+PRBool test_028(void)
+{
+ int i;
+ char buffer[ 4096 ];
+ char *rv;
+
+ printf("Test 028 (PL_Base64Decode, random strings, no equals, malloc, strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRUint32 clen;
+
+ PL_strcpy(buffer, array[i].cyphertext);
+ clen = PL_strlen(buffer);
+
+ if( 0 == (clen & 3) )
+ {
+ if( '=' == buffer[clen-1] )
+ {
+ if( '=' == buffer[clen-2] )
+ {
+ buffer[clen-2] = buffer[clen-1] = (char)0;
+ clen -= 2;
+ }
+ else
+ {
+ buffer[clen-1] = (char)0;
+ clen -= 1;
+ }
+ }
+ }
+
+ rv = PL_Base64Decode(buffer, 0, (char *)0);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL\n\t(%d): no return value\n", i);
+ return PR_FALSE;
+ }
+
+ if( 0 != PL_strcmp(rv, array[i].plaintext) )
+ {
+ printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n",
+ i, array[i].cyphertext, array[i].plaintext, rv);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+int
+main
+(
+ int argc,
+ char *argv[]
+)
+{
+ printf("Testing the Portable Library base64 functions:\n");
+ printf("(warning: the \"triple characters\" tests are slow)\n");
+
+ if( 1
+ && test_001()
+ && test_002()
+ && test_003()
+ && test_004()
+ && test_005()
+ && test_006()
+ && test_007()
+ && test_008()
+ && test_009()
+ && test_010()
+ && test_011()
+ && test_012()
+ && test_013()
+ && test_014()
+ && test_015()
+ && test_016()
+ && test_017()
+ && test_018()
+ && test_019()
+ && test_020()
+ && test_021()
+ && test_022()
+ && test_023()
+ && test_024()
+ && test_025()
+ && test_026()
+ && test_027()
+ && test_028()
+ )
+ {
+ printf("Suite passed.\n");
+ return 0;
+ }
+ else
+ {
+ printf("Suite failed.\n");
+ return 1;
+ }
+
+ /*NOTREACHED*/
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/string.c b/src/libs/xpcom18a4/nsprpub/lib/tests/string.c
new file mode 100644
index 00000000..482e17b5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/string.c
@@ -0,0 +1,3116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plstr.h"
+#include "nspr.h"
+
+#include <stdio.h>
+
+/* PL_strlen */
+PRBool test_001(void)
+{
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ } array[] =
+ {
+ { (const char *)0, 0 },
+ { "", 0 },
+ { "a", 1 },
+ { "abcdefg", 7 },
+ { "abcdefg\0hijk", 7 }
+ };
+
+ int i;
+
+ printf("Test 001 (PL_strlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ if( PL_strlen(array[i].str) != array[i].len )
+ {
+ printf("FAIL (%d: %s->%d, %d)\n", i,
+ array[i].str ? array[i].str : "(null)",
+ PL_strlen(array[i].str), array[i].len);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnlen */
+PRBool test_002(void)
+{
+ static struct
+ {
+ const char *str;
+ PRUint32 max;
+ PRUint32 len;
+ } array[] =
+ {
+ { (const char *)0, 0, 0 },
+ { (const char *)0, 12, 0 },
+ { "", 0, 0 },
+ { "", 12, 0 },
+ { "a", 0, 0 },
+ { "a", 1, 1 },
+ { "a", 12, 1 },
+ { "abcdefg", 0, 0 },
+ { "abcdefg", 1, 1 },
+ { "abcdefg", 7, 7 },
+ { "abcdefg", 12, 7 },
+ { "abcdefg\0hijk", 0, 0 },
+ { "abcdefg\0hijk", 1, 1 },
+ { "abcdefg\0hijk", 7, 7 },
+ { "abcdefg\0hijk", 12, 7 },
+ };
+
+ int i;
+
+ printf("Test 002 (PL_strnlen) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ if( PL_strnlen(array[i].str, array[i].max) != array[i].len )
+ {
+ printf("FAIL (%d: %s,%d->%d, %d)\n", i,
+ array[i].str ? array[i].str : "(null)", array[i].max,
+ PL_strnlen(array[i].str, array[i].max), array[i].len);
+ return PR_FALSE;
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcpy */
+PRBool test_003(void)
+{
+ static char buffer[ 1024 ];
+
+ static struct
+ {
+ const char *str;
+ char *dest;
+ char *rv;
+ PRBool comp;
+ } array[] =
+ {
+ { (const char *)0, (char *)0, (char *)0, PR_FALSE },
+ { (const char *)0, buffer, (char *)0, PR_FALSE },
+ { "", (char *)0, (char *)0, PR_FALSE },
+ { "", buffer, buffer, PR_TRUE },
+ { "a", (char *)0, (char *)0, PR_FALSE },
+ { "a", buffer, buffer, PR_TRUE },
+ { "abcdefg", (char *)0, (char *)0, PR_FALSE },
+ { "abcdefg", buffer, buffer, PR_TRUE },
+ { "wxyz\0abcdefg", (char *)0, (char *)0, PR_FALSE },
+ { "wxyz\0abcdefg", buffer, buffer, PR_TRUE }
+ };
+
+ int i;
+
+ printf("Test 003 (PL_strcpy) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv;
+ const char *a = array[i].str;
+ const char *b = (const char *)array[i].dest;
+
+ rv = PL_strcpy(array[i].dest, array[i].str);
+ if( array[i].rv != rv )
+ {
+ printf("FAIL %d: (0x%x, %s)->0x%x\n", i, array[i].dest,
+ array[i].str ? array[i].str : "(null)", rv);
+ return PR_FALSE;
+ }
+
+ if( array[i].comp )
+ {
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s->%.32s\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].dest ? array[i].dest : "(null)");
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) break;
+
+ a++;
+ b++;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncpy */
+PRBool test_004(void)
+{
+ static char buffer[ 1024 ];
+
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ char *dest;
+ char *rv;
+ PRBool comp;
+ const char *result;
+ PRBool nulled;
+ } array[] =
+ {
+ { (const char *)0, 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 0, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 1, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { (const char *)0, 7, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "", 1, buffer, buffer, PR_TRUE, "", PR_TRUE },
+ { "", 7, buffer, buffer, PR_TRUE, "", PR_TRUE },
+ { "a", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "b", 1, buffer, buffer, PR_TRUE, "b", PR_FALSE },
+ { "c", 7, buffer, buffer, PR_TRUE, "c", PR_TRUE },
+ { "de", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "fg", 1, buffer, buffer, PR_TRUE, "f", PR_FALSE },
+ { "hi", 7, buffer, buffer, PR_TRUE, "hi", PR_TRUE },
+ { "jklmnopq", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "rstuvwxy", 1, buffer, buffer, PR_TRUE, "r", PR_FALSE },
+ { "zABCDEFG", 7, buffer, buffer, PR_TRUE, "zABCDEF", PR_FALSE },
+ { "a\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "a\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "b\0XXX", 1, buffer, buffer, PR_TRUE, "b", PR_FALSE },
+ { "c\0XXX", 7, buffer, buffer, PR_TRUE, "c", PR_TRUE },
+ { "de\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "de\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "fg\0XXX", 1, buffer, buffer, PR_TRUE, "f", PR_FALSE },
+ { "hi\0XXX", 7, buffer, buffer, PR_TRUE, "hi", PR_TRUE },
+ { "jklmnopq\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "jklmnopq\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE },
+ { "rstuvwxy\0XXX", 1, buffer, buffer, PR_TRUE, "r", PR_FALSE },
+ { "zABCDEFG\0XXX", 7, buffer, buffer, PR_TRUE, "zABCDEF", PR_FALSE },
+ };
+
+ int i;
+
+ printf("Test 004 (PL_strncpy) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv;
+ int j;
+
+ for( j = 0; j < sizeof(buffer); j++ )
+ buffer[j] = '-';
+
+ rv = PL_strncpy(array[i].dest, array[i].str, array[i].len);
+ if( array[i].rv != rv )
+ {
+ printf("FAIL %d: (0x%x, %s, %lu)->0x%x\n", i, array[i].dest,
+ array[i].str ? array[i].str : "(null)", array[i].len, rv);
+ return PR_FALSE;
+ }
+
+ if( array[i].comp )
+ {
+ const char *a = array[i].result;
+ const char *b = array[i].dest;
+
+ while( *a )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i,
+ array[i].result, array[i].dest);
+ return PR_FALSE;
+ }
+
+ a++;
+ b++;
+ }
+
+ if( array[i].nulled )
+ {
+ if( *b != '\0' )
+ {
+ printf("FAIL %d: not terminated\n", i);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( *b != '-' )
+ {
+ printf("FAIL %d: overstepped\n", i);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncpyz */
+PRBool test_005(void)
+{
+ static char buffer[ 1024 ];
+
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ char *dest;
+ char *rv;
+ PRBool comp;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 1, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { (const char *)0, 7, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "", 1, buffer, buffer, PR_TRUE, "" },
+ { "", 7, buffer, buffer, PR_TRUE, "" },
+ { "a", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "a", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "b", 1, buffer, buffer, PR_TRUE, "" },
+ { "c", 7, buffer, buffer, PR_TRUE, "c" },
+ { "de", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "de", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "fg", 1, buffer, buffer, PR_TRUE, "" },
+ { "hi", 7, buffer, buffer, PR_TRUE, "hi" },
+ { "jklmnopq", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "rstuvwxy", 1, buffer, buffer, PR_TRUE, "" },
+ { "zABCDEFG", 7, buffer, buffer, PR_TRUE, "zABCDE" },
+ { "a\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "a\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "a\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "b\0XXX", 1, buffer, buffer, PR_TRUE, "" },
+ { "c\0XXX", 7, buffer, buffer, PR_TRUE, "c" },
+ { "de\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "de\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "de\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "fg\0XXX", 1, buffer, buffer, PR_TRUE, "" },
+ { "hi\0XXX", 7, buffer, buffer, PR_TRUE, "hi" },
+ { "jklmnopq\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "jklmnopq\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 },
+ { "rstuvwxy\0XXX", 1, buffer, buffer, PR_TRUE, "" },
+ { "zABCDEFG\0XXX", 7, buffer, buffer, PR_TRUE, "zABCDE" },
+ };
+
+ int i;
+
+ printf("Test 005 (PL_strncpyz) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv;
+ int j;
+
+ for( j = 0; j < sizeof(buffer); j++ )
+ buffer[j] = '-';
+
+ rv = PL_strncpyz(array[i].dest, array[i].str, array[i].len);
+ if( array[i].rv != rv )
+ {
+ printf("FAIL %d: (0x%x, %s, %lu)->0x%x\n", i, array[i].dest,
+ array[i].str ? array[i].str : "(null)", array[i].len, rv);
+ return PR_FALSE;
+ }
+
+ if( array[i].comp )
+ {
+ const char *a = array[i].result;
+ const char *b = array[i].dest;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i,
+ array[i].result, array[i].dest);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) break;
+
+ a++;
+ b++;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strdup */
+PRBool test_006(void)
+{
+ static const char *array[] =
+ {
+ (const char *)0,
+ "",
+ "a",
+ "abcdefg"
+ };
+
+ int i;
+
+ printf("Test 006 (PL_strdup) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strdup(array[i]);
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: 0x%x -> 0\n", i, array[i]);
+ return PR_FALSE;
+ }
+
+ if( (const char *)0 == array[i] )
+ {
+ if( (char)0 != *rv )
+ {
+ printf("FAIL %d: (const char *)0 -> %.32s\n", i, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ const char *a = array[i];
+ const char *b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i, array[i], rv);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) break;
+
+ a++;
+ b++;
+ }
+
+ }
+ PL_strfree(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strndup */
+PRBool test_007(void)
+{
+ static struct
+ {
+ const char *str;
+ PRUint32 len;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, 0, "" },
+ { (const char *)0, 1, "" },
+ { (const char *)0, 7, "" },
+ { "", 0, "" },
+ { "", 1, "" },
+ { "", 7, "" },
+ { "a", 0, "" },
+ { "a", 1, "a" },
+ { "a", 7, "a" },
+ { "ab", 0, "" },
+ { "ab", 1, "a" },
+ { "ab", 7, "ab" },
+ { "abcdefg", 0, "" },
+ { "abcdefg", 1, "a" },
+ { "abcdefg", 7, "abcdefg" },
+ { "abcdefghijk", 0, "" },
+ { "abcdefghijk", 1, "a" },
+ { "abcdefghijk", 7, "abcdefg" },
+ { "abcdef\0ghijk", 0, "" },
+ { "abcdef\0ghijk", 1, "a" },
+ { "abcdef\0ghijk", 7, "abcdef" }
+ };
+
+ int i;
+
+ printf("Test 007 (PL_strndup) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strndup(array[i].str, array[i].len);
+ const char *a;
+ const char *b;
+
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%lu -> 0\n", i,
+ array[i].str ? array[i].str : "(null)", array[i].len);
+ return PR_FALSE;
+ }
+
+ a = array[i].result;
+ b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s != %.32s\n", i, array[i].result, rv);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) break;
+
+ a++;
+ b++;
+ }
+
+ free(rv);
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcat */
+PRBool test_008(void)
+{
+ static struct
+ {
+ const char *first;
+ const char *second;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, (const char *)0 },
+ { (const char *)0, "xyz", (const char *)0 },
+ { "", (const char *)0, "" },
+ { "", "", "" },
+ { "ab", "", "ab" },
+ { "cd", "ef", "cdef" },
+ { "gh\0X", "", "gh" },
+ { "ij\0X", "kl", "ijkl" },
+ { "mn\0X", "op\0X", "mnop" },
+ { "qr", "st\0X", "qrst" },
+ { "uv\0X", "wx\0X", "uvwx" }
+ };
+
+ int i;
+
+ printf("Test 008 (PL_strcat) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char buffer[ 1024 ];
+ int j;
+ char *rv;
+
+ for( j = 0; j < sizeof(buffer); j++ )
+ buffer[j] = '-';
+
+ if( (const char *)0 != array[i].first )
+ (void)PL_strcpy(buffer, array[i].first);
+
+ rv = PL_strcat(((const char *)0 == array[i].first) ? (char *)0 : buffer,
+ array[i].second);
+
+ if( (const char *)0 == array[i].result )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s+%s -> %.32s, not zero\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s+%s -> null, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].result);
+ return PR_FALSE;
+ }
+ else
+ {
+ const char *a = array[i].result;
+ const char *b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s+%s -> %.32s, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ rv, array[i].result);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) break;
+
+ a++;
+ b++;
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncat */
+PRBool test_009(void)
+{
+ static struct
+ {
+ const char *first;
+ const char *second;
+ PRUint32 length;
+ PRBool nulled;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, PR_FALSE, (const char *)0 },
+ { (const char *)0, (const char *)0, 1, PR_FALSE, (const char *)0 },
+ { (const char *)0, (const char *)0, 7, PR_FALSE, (const char *)0 },
+ { (const char *)0, "", 0, PR_FALSE, (const char *)0 },
+ { (const char *)0, "", 1, PR_FALSE, (const char *)0 },
+ { (const char *)0, "", 7, PR_FALSE, (const char *)0 },
+ { (const char *)0, "stuff", 0, PR_FALSE, (const char *)0 },
+ { (const char *)0, "stuff", 1, PR_FALSE, (const char *)0 },
+ { (const char *)0, "stuff", 7, PR_FALSE, (const char *)0 },
+ { "", (const char *)0, 0, PR_TRUE, "" },
+ { "", (const char *)0, 1, PR_TRUE, "" },
+ { "", (const char *)0, 7, PR_TRUE, "" },
+ { "", "", 0, PR_TRUE, "" },
+ { "", "", 1, PR_TRUE, "" },
+ { "", "", 7, PR_TRUE, "" },
+ { "", "abcdefgh", 0, PR_TRUE, "" },
+ { "", "abcdefgh", 1, PR_FALSE, "a" },
+ { "", "abcdefgh", 7, PR_FALSE, "abcdefg" },
+ { "xyz", (const char *)0, 0, PR_TRUE, "xyz" },
+ { "xyz", (const char *)0, 1, PR_TRUE, "xyz" },
+ { "xyz", (const char *)0, 7, PR_TRUE, "xyz" },
+ { "xyz", "", 0, PR_TRUE, "xyz" },
+ { "xyz", "", 1, PR_TRUE, "xyz" },
+ { "xyz", "", 7, PR_TRUE, "xyz" },
+ { "xyz", "abcdefgh", 0, PR_TRUE, "xyz" },
+ { "xyz", "abcdefgh", 1, PR_FALSE, "xyza" },
+ { "xyz", "abcdefgh", 7, PR_FALSE, "xyzabcdefg" }
+ };
+
+ int i;
+
+ printf("Test 009 (PL_strncat) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char buffer[ 1024 ];
+ int j;
+ char *rv;
+
+ for( j = 0; j < sizeof(buffer); j++ )
+ buffer[j] = '-';
+
+ if( (const char *)0 != array[i].first )
+ (void)PL_strcpy(buffer, array[i].first);
+
+ rv = PL_strncat(((const char *)0 == array[i].first) ? (char *)0 : buffer,
+ array[i].second, array[i].length);
+
+ if( (const char *)0 == array[i].result )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not zero\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> null, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, array[i].result);
+ return PR_FALSE;
+ }
+ else
+ {
+ const char *a = array[i].result;
+ const char *b = (const char *)rv;
+
+ while( *a )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv, array[i].result);
+ return PR_FALSE;
+ }
+
+ a++;
+ b++;
+ }
+
+ if( array[i].nulled )
+ {
+ if( (char)0 != *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> not nulled\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char)0 == *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> overrun\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length);
+ return PR_FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcatn */
+PRBool test_010(void)
+{
+ static struct
+ {
+ const char *first;
+ const char *second;
+ PRUint32 length;
+ const char *result;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, (const char *)0 },
+ { (const char *)0, (const char *)0, 1, (const char *)0 },
+ { (const char *)0, (const char *)0, 7, (const char *)0 },
+ { (const char *)0, "", 0, (const char *)0 },
+ { (const char *)0, "", 1, (const char *)0 },
+ { (const char *)0, "", 7, (const char *)0 },
+ { (const char *)0, "stuff", 0, (const char *)0 },
+ { (const char *)0, "stuff", 1, (const char *)0 },
+ { (const char *)0, "stuff", 7, (const char *)0 },
+ { "", (const char *)0, 0, "" },
+ { "", (const char *)0, 1, "" },
+ { "", (const char *)0, 7, "" },
+ { "", "", 0, "" },
+ { "", "", 1, "" },
+ { "", "", 7, "" },
+ { "", "abcdefgh", 0, "" },
+ { "", "abcdefgh", 1, "" },
+ { "", "abcdefgh", 7, "abcdef" },
+ { "xyz", (const char *)0, 0, "xyz" },
+ { "xyz", (const char *)0, 1, "xyz" },
+ { "xyz", (const char *)0, 7, "xyz" },
+ { "xyz", "", 0, "xyz" },
+ { "xyz", "", 1, "xyz" },
+ { "xyz", "", 7, "xyz" },
+ { "xyz", "abcdefgh", 0, "xyz" },
+ { "xyz", "abcdefgh", 1, "xyz" },
+ { "xyz", "abcdefgh", 7, "xyzabc" }
+ };
+
+ int i;
+
+ printf("Test 010 (PL_strcatn) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char buffer[ 1024 ];
+ int j;
+ char *rv;
+
+ for( j = 0; j < sizeof(buffer); j++ )
+ buffer[j] = '-';
+
+ if( (const char *)0 != array[i].first )
+ (void)PL_strcpy(buffer, array[i].first);
+
+ rv = PL_strcatn(((const char *)0 == array[i].first) ? (char *)0 : buffer,
+ array[i].length, array[i].second);
+
+ if( (const char *)0 == array[i].result )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not zero\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s+%s/%lu -> null, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, array[i].result);
+ return PR_FALSE;
+ }
+ else
+ {
+ const char *a = array[i].result;
+ const char *b = (const char *)rv;
+
+ while( 1 )
+ {
+ if( *a != *b )
+ {
+ printf("FAIL %d: %s+%s/%lu -> %.32s, not %s\n", i,
+ array[i].first ? array[i].first : "(null)",
+ array[i].second ? array[i].second : "(null)",
+ array[i].length, rv, array[i].result);
+ return PR_FALSE;
+ }
+
+ if( (char)0 == *a ) break;
+
+ a++;
+ b++;
+ }
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcmp */
+PRBool test_011(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0 },
+ { (const char *)0, "word", -1 },
+ { "word", (const char *)0, 1 },
+ { "word", "word", 0 },
+ { "aZYXVUT", "bZYXVUT", -1 },
+ { "aZYXVUT", "bAAAAAA", -1 },
+ { "a", "aa", -1 },
+ { "a", "a", 0 },
+ { "a", "A", 1 },
+ { "aaaaa", "baaaa", -1 },
+ { "aaaaa", "abaaa", -1 },
+ { "aaaaa", "aabaa", -1 },
+ { "aaaaa", "aaaba", -1 },
+ { "aaaaa", "aaaab", -1 },
+ { "bZYXVUT", "aZYXVUT", 1 },
+ { "bAAAAAA", "aZYXVUT", 1 },
+ { "aa", "a", 1 },
+ { "A", "a", -1 },
+ { "baaaa", "aaaaa", 1 },
+ { "abaaa", "aaaaa", 1 },
+ { "aabaa", "aaaaa", 1 },
+ { "aaaba", "aaaaa", 1 },
+ { "aaaab", "aaaaa", 1 },
+ { "word", "Word", 1 },
+ { "word", "wOrd", 1 },
+ { "word", "woRd", 1 },
+ { "word", "worD", 1 },
+ { "WORD", "wORD", -1 },
+ { "WORD", "WoRD", -1 },
+ { "WORD", "WOrD", -1 },
+ { "WORD", "WORd", -1 }
+ };
+
+ int i;
+
+ printf("Test 011 (PL_strcmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strcmp(array[i].one, array[i].two);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) continue;
+ break;
+ case 1:
+ if( rv > 0 ) continue;
+ break;
+ case 0:
+ if( 0 == rv ) continue;
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncmp */
+PRBool test_012(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRUint32 max;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, 0 },
+ { (const char *)0, (const char *)0, 1, 0 },
+ { (const char *)0, (const char *)0, 4, 0 },
+ { (const char *)0, "word", 0, -1 },
+ { (const char *)0, "word", 1, -1 },
+ { (const char *)0, "word", 4, -1 },
+ { "word", (const char *)0, 0, 1 },
+ { "word", (const char *)0, 1, 1 },
+ { "word", (const char *)0, 4, 1 },
+ { "word", "word", 0, 0 },
+ { "word", "word", 1, 0 },
+ { "word", "word", 3, 0 },
+ { "word", "word", 5, 0 },
+ { "aZYXVUT", "bZYXVUT", 0, 0 },
+ { "aZYXVUT", "bZYXVUT", 1, -1 },
+ { "aZYXVUT", "bZYXVUT", 4, -1 },
+ { "aZYXVUT", "bZYXVUT", 9, -1 },
+ { "aZYXVUT", "bAAAAAA", 0, 0 },
+ { "aZYXVUT", "bAAAAAA", 1, -1 },
+ { "aZYXVUT", "bAAAAAA", 4, -1 },
+ { "aZYXVUT", "bAAAAAA", 5, -1 },
+ { "a", "aa", 0, 0 },
+ { "a", "aa", 1, 0 },
+ { "a", "aa", 4, -1 },
+ { "a", "a", 0, 0 },
+ { "a", "a", 1, 0 },
+ { "a", "a", 4, 0 },
+ { "a", "A", 0, 0 },
+ { "a", "A", 1, 1 },
+ { "a", "A", 4, 1 },
+ { "aaaaa", "baaaa", 0, 0 },
+ { "aaaaa", "baaaa", 1, -1 },
+ { "aaaaa", "baaaa", 4, -1 },
+ { "aaaaa", "abaaa", 0, 0 },
+ { "aaaaa", "abaaa", 1, 0 },
+ { "aaaaa", "abaaa", 4, -1 },
+ { "aaaaa", "aabaa", 0, 0 },
+ { "aaaaa", "aabaa", 1, 0 },
+ { "aaaaa", "aabaa", 4, -1 },
+ { "aaaaa", "aaaba", 0, 0 },
+ { "aaaaa", "aaaba", 1, 0 },
+ { "aaaaa", "aaaba", 4, -1 },
+ { "aaaaa", "aaaab", 0, 0 },
+ { "aaaaa", "aaaab", 1, 0 },
+ { "aaaaa", "aaaab", 4, 0 },
+ { "bZYXVUT", "aZYXVUT", 0, 0 },
+ { "bZYXVUT", "aZYXVUT", 1, 1 },
+ { "bZYXVUT", "aZYXVUT", 4, 1 },
+ { "bAAAAAA", "aZYXVUT", 0, 0 },
+ { "bAAAAAA", "aZYXVUT", 1, 1 },
+ { "bAAAAAA", "aZYXVUT", 4, 1 },
+ { "aa", "a", 0, 0 },
+ { "aa", "a", 1, 0 },
+ { "aa", "a", 4, 1 },
+ { "A", "a", 0, 0 },
+ { "A", "a", 1, -1 },
+ { "A", "a", 4, -1 },
+ { "baaaa", "aaaaa", 0, 0 },
+ { "baaaa", "aaaaa", 1, 1 },
+ { "baaaa", "aaaaa", 4, 1 },
+ { "abaaa", "aaaaa", 0, 0 },
+ { "abaaa", "aaaaa", 1, 0 },
+ { "abaaa", "aaaaa", 4, 1 },
+ { "aabaa", "aaaaa", 0, 0 },
+ { "aabaa", "aaaaa", 1, 0 },
+ { "aabaa", "aaaaa", 4, 1 },
+ { "aaaba", "aaaaa", 0, 0 },
+ { "aaaba", "aaaaa", 1, 0 },
+ { "aaaba", "aaaaa", 4, 1 },
+ { "aaaab", "aaaaa", 0, 0 },
+ { "aaaab", "aaaaa", 1, 0 },
+ { "aaaab", "aaaaa", 4, 0 },
+ { "word", "Word", 0, 0 },
+ { "word", "Word", 1, 1 },
+ { "word", "Word", 3, 1 },
+ { "word", "wOrd", 0, 0 },
+ { "word", "wOrd", 1, 0 },
+ { "word", "wOrd", 3, 1 },
+ { "word", "woRd", 0, 0 },
+ { "word", "woRd", 1, 0 },
+ { "word", "woRd", 3, 1 },
+ { "word", "worD", 0, 0 },
+ { "word", "worD", 1, 0 },
+ { "word", "worD", 3, 0 },
+ { "WORD", "wORD", 0, 0 },
+ { "WORD", "wORD", 1, -1 },
+ { "WORD", "wORD", 3, -1 },
+ { "WORD", "WoRD", 0, 0 },
+ { "WORD", "WoRD", 1, 0 },
+ { "WORD", "WoRD", 3, -1 },
+ { "WORD", "WOrD", 0, 0 },
+ { "WORD", "WOrD", 1, 0 },
+ { "WORD", "WOrD", 3, -1 },
+ { "WORD", "WORd", 0, 0 },
+ { "WORD", "WORd", 1, 0 },
+ { "WORD", "WORd", 3, 0 }
+
+ };
+
+ int i;
+
+ printf("Test 012 (PL_strncmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strncmp(array[i].one, array[i].two, array[i].max);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) continue;
+ break;
+ case 1:
+ if( rv > 0 ) continue;
+ break;
+ case 0:
+ if( 0 == rv ) continue;
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s/%ld -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ array[i].max, rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcasecmp */
+PRBool test_013(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0 },
+ { (const char *)0, "word", -1 },
+ { "word", (const char *)0, 1 },
+ { "word", "word", 0 },
+ { "aZYXVUT", "bZYXVUT", -1 },
+ { "aZYXVUT", "bAAAAAA", -1 },
+ { "a", "aa", -1 },
+ { "a", "a", 0 },
+ { "a", "A", 0 },
+ { "aaaaa", "baaaa", -1 },
+ { "aaaaa", "abaaa", -1 },
+ { "aaaaa", "aabaa", -1 },
+ { "aaaaa", "aaaba", -1 },
+ { "aaaaa", "aaaab", -1 },
+ { "bZYXVUT", "aZYXVUT", 1 },
+ { "bAAAAAA", "aZYXVUT", 1 },
+ { "aa", "a", 1 },
+ { "A", "a", 0 },
+ { "baaaa", "aaaaa", 1 },
+ { "abaaa", "aaaaa", 1 },
+ { "aabaa", "aaaaa", 1 },
+ { "aaaba", "aaaaa", 1 },
+ { "aaaab", "aaaaa", 1 },
+ { "word", "Word", 0 },
+ { "word", "wOrd", 0 },
+ { "word", "woRd", 0 },
+ { "word", "worD", 0 },
+ { "WORD", "wORD", 0 },
+ { "WORD", "WoRD", 0 },
+ { "WORD", "WOrD", 0 },
+ { "WORD", "WORd", 0 }
+ };
+
+ int i;
+
+ printf("Test 013 (PL_strcasecmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strcasecmp(array[i].one, array[i].two);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) continue;
+ break;
+ case 1:
+ if( rv > 0 ) continue;
+ break;
+ case 0:
+ if( 0 == rv ) continue;
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncasecmp */
+PRBool test_014(void)
+{
+ static struct
+ {
+ const char *one;
+ const char *two;
+ PRUint32 max;
+ PRIntn sign;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 0, 0 },
+ { (const char *)0, (const char *)0, 1, 0 },
+ { (const char *)0, (const char *)0, 4, 0 },
+ { (const char *)0, "word", 0, -1 },
+ { (const char *)0, "word", 1, -1 },
+ { (const char *)0, "word", 4, -1 },
+ { "word", (const char *)0, 0, 1 },
+ { "word", (const char *)0, 1, 1 },
+ { "word", (const char *)0, 4, 1 },
+ { "word", "word", 0, 0 },
+ { "word", "word", 1, 0 },
+ { "word", "word", 3, 0 },
+ { "word", "word", 5, 0 },
+ { "aZYXVUT", "bZYXVUT", 0, 0 },
+ { "aZYXVUT", "bZYXVUT", 1, -1 },
+ { "aZYXVUT", "bZYXVUT", 4, -1 },
+ { "aZYXVUT", "bZYXVUT", 9, -1 },
+ { "aZYXVUT", "bAAAAAA", 0, 0 },
+ { "aZYXVUT", "bAAAAAA", 1, -1 },
+ { "aZYXVUT", "bAAAAAA", 4, -1 },
+ { "aZYXVUT", "bAAAAAA", 5, -1 },
+ { "a", "aa", 0, 0 },
+ { "a", "aa", 1, 0 },
+ { "a", "aa", 4, -1 },
+ { "a", "a", 0, 0 },
+ { "a", "a", 1, 0 },
+ { "a", "a", 4, 0 },
+ { "a", "A", 0, 0 },
+ { "a", "A", 1, 0 },
+ { "a", "A", 4, 0 },
+ { "aaaaa", "baaaa", 0, 0 },
+ { "aaaaa", "baaaa", 1, -1 },
+ { "aaaaa", "baaaa", 4, -1 },
+ { "aaaaa", "abaaa", 0, 0 },
+ { "aaaaa", "abaaa", 1, 0 },
+ { "aaaaa", "abaaa", 4, -1 },
+ { "aaaaa", "aabaa", 0, 0 },
+ { "aaaaa", "aabaa", 1, 0 },
+ { "aaaaa", "aabaa", 4, -1 },
+ { "aaaaa", "aaaba", 0, 0 },
+ { "aaaaa", "aaaba", 1, 0 },
+ { "aaaaa", "aaaba", 4, -1 },
+ { "aaaaa", "aaaab", 0, 0 },
+ { "aaaaa", "aaaab", 1, 0 },
+ { "aaaaa", "aaaab", 4, 0 },
+ { "bZYXVUT", "aZYXVUT", 0, 0 },
+ { "bZYXVUT", "aZYXVUT", 1, 1 },
+ { "bZYXVUT", "aZYXVUT", 4, 1 },
+ { "bAAAAAA", "aZYXVUT", 0, 0 },
+ { "bAAAAAA", "aZYXVUT", 1, 1 },
+ { "bAAAAAA", "aZYXVUT", 4, 1 },
+ { "aa", "a", 0, 0 },
+ { "aa", "a", 1, 0 },
+ { "aa", "a", 4, 1 },
+ { "A", "a", 0, 0 },
+ { "A", "a", 1, 0 },
+ { "A", "a", 4, 0 },
+ { "baaaa", "aaaaa", 0, 0 },
+ { "baaaa", "aaaaa", 1, 1 },
+ { "baaaa", "aaaaa", 4, 1 },
+ { "abaaa", "aaaaa", 0, 0 },
+ { "abaaa", "aaaaa", 1, 0 },
+ { "abaaa", "aaaaa", 4, 1 },
+ { "aabaa", "aaaaa", 0, 0 },
+ { "aabaa", "aaaaa", 1, 0 },
+ { "aabaa", "aaaaa", 4, 1 },
+ { "aaaba", "aaaaa", 0, 0 },
+ { "aaaba", "aaaaa", 1, 0 },
+ { "aaaba", "aaaaa", 4, 1 },
+ { "aaaab", "aaaaa", 0, 0 },
+ { "aaaab", "aaaaa", 1, 0 },
+ { "aaaab", "aaaaa", 4, 0 },
+ { "word", "Word", 0, 0 },
+ { "word", "Word", 1, 0 },
+ { "word", "Word", 3, 0 },
+ { "word", "wOrd", 0, 0 },
+ { "word", "wOrd", 1, 0 },
+ { "word", "wOrd", 3, 0 },
+ { "word", "woRd", 0, 0 },
+ { "word", "woRd", 1, 0 },
+ { "word", "woRd", 3, 0 },
+ { "word", "worD", 0, 0 },
+ { "word", "worD", 1, 0 },
+ { "word", "worD", 3, 0 },
+ { "WORD", "wORD", 0, 0 },
+ { "WORD", "wORD", 1, 0 },
+ { "WORD", "wORD", 3, 0 },
+ { "WORD", "WoRD", 0, 0 },
+ { "WORD", "WoRD", 1, 0 },
+ { "WORD", "WoRD", 3, 0 },
+ { "WORD", "WOrD", 0, 0 },
+ { "WORD", "WOrD", 1, 0 },
+ { "WORD", "WOrD", 3, 0 },
+ { "WORD", "WORd", 0, 0 },
+ { "WORD", "WORd", 1, 0 },
+ { "WORD", "WORd", 3, 0 }
+ };
+
+ int i;
+
+ printf("Test 014 (PL_strncasecmp) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ PRIntn rv = PL_strncasecmp(array[i].one, array[i].two, array[i].max);
+
+ switch( array[i].sign )
+ {
+ case -1:
+ if( rv < 0 ) continue;
+ break;
+ case 1:
+ if( rv > 0 ) continue;
+ break;
+ case 0:
+ if( 0 == rv ) continue;
+ break;
+ default:
+ PR_NOT_REACHED("static data inconsistancy");
+ break;
+ }
+
+ printf("FAIL %d: %s-%s/%ld -> %d, not %d\n", i,
+ array[i].one ? array[i].one : "(null)",
+ array[i].two ? array[i].two : "(null)",
+ array[i].max, rv, array[i].sign);
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strchr */
+PRBool test_015(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', PR_FALSE, 0 },
+ { (const char *)0, '\0', PR_FALSE, 0 },
+ { "abcdefg", 'a', PR_TRUE, 0 },
+ { "abcdefg", 'b', PR_TRUE, 1 },
+ { "abcdefg", 'c', PR_TRUE, 2 },
+ { "abcdefg", 'd', PR_TRUE, 3 },
+ { "abcdefg", 'e', PR_TRUE, 4 },
+ { "abcdefg", 'f', PR_TRUE, 5 },
+ { "abcdefg", 'g', PR_TRUE, 6 },
+ { "abcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefg", '\0', PR_TRUE, 7 },
+ { "abcdefg", 'A', PR_FALSE, 0 },
+ { "abcdefg", 'B', PR_FALSE, 0 },
+ { "abcdefg", 'C', PR_FALSE, 0 },
+ { "abcdefg", 'D', PR_FALSE, 0 },
+ { "abcdefg", 'E', PR_FALSE, 0 },
+ { "abcdefg", 'F', PR_FALSE, 0 },
+ { "abcdefg", 'G', PR_FALSE, 0 },
+ { "abcdefg", 'H', PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', PR_TRUE, 0 },
+ { "abcdefgabcdefg", 'b', PR_TRUE, 1 },
+ { "abcdefgabcdefg", 'c', PR_TRUE, 2 },
+ { "abcdefgabcdefg", 'd', PR_TRUE, 3 },
+ { "abcdefgabcdefg", 'e', PR_TRUE, 4 },
+ { "abcdefgabcdefg", 'f', PR_TRUE, 5 },
+ { "abcdefgabcdefg", 'g', PR_TRUE, 6 },
+ { "abcdefgabcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 015 (PL_strchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strchr(array[i].str, array[i].chr);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strrchr */
+PRBool test_016(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', PR_FALSE, 0 },
+ { (const char *)0, '\0', PR_FALSE, 0 },
+ { "abcdefg", 'a', PR_TRUE, 0 },
+ { "abcdefg", 'b', PR_TRUE, 1 },
+ { "abcdefg", 'c', PR_TRUE, 2 },
+ { "abcdefg", 'd', PR_TRUE, 3 },
+ { "abcdefg", 'e', PR_TRUE, 4 },
+ { "abcdefg", 'f', PR_TRUE, 5 },
+ { "abcdefg", 'g', PR_TRUE, 6 },
+ { "abcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefg", '\0', PR_TRUE, 7 },
+ { "abcdefg", 'A', PR_FALSE, 0 },
+ { "abcdefg", 'B', PR_FALSE, 0 },
+ { "abcdefg", 'C', PR_FALSE, 0 },
+ { "abcdefg", 'D', PR_FALSE, 0 },
+ { "abcdefg", 'E', PR_FALSE, 0 },
+ { "abcdefg", 'F', PR_FALSE, 0 },
+ { "abcdefg", 'G', PR_FALSE, 0 },
+ { "abcdefg", 'H', PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', PR_TRUE, 7 },
+ { "abcdefgabcdefg", 'b', PR_TRUE, 8 },
+ { "abcdefgabcdefg", 'c', PR_TRUE, 9 },
+ { "abcdefgabcdefg", 'd', PR_TRUE, 10 },
+ { "abcdefgabcdefg", 'e', PR_TRUE, 11 },
+ { "abcdefgabcdefg", 'f', PR_TRUE, 12 },
+ { "abcdefgabcdefg", 'g', PR_TRUE, 13 },
+ { "abcdefgabcdefg", 'h', PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 016 (PL_strrchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strrchr(array[i].str, array[i].chr);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnchr */
+PRBool test_017(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', 2, PR_FALSE, 0 },
+ { (const char *)0, '\0', 2, PR_FALSE, 0 },
+ { "abcdefg", 'a', 5, PR_TRUE, 0 },
+ { "abcdefg", 'b', 5, PR_TRUE, 1 },
+ { "abcdefg", 'c', 5, PR_TRUE, 2 },
+ { "abcdefg", 'd', 5, PR_TRUE, 3 },
+ { "abcdefg", 'e', 5, PR_TRUE, 4 },
+ { "abcdefg", 'f', 5, PR_FALSE, 0 },
+ { "abcdefg", 'g', 5, PR_FALSE, 0 },
+ { "abcdefg", 'h', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 15, PR_TRUE, 7 },
+ { "abcdefg", 'A', 5, PR_FALSE, 0 },
+ { "abcdefg", 'B', 5, PR_FALSE, 0 },
+ { "abcdefg", 'C', 5, PR_FALSE, 0 },
+ { "abcdefg", 'D', 5, PR_FALSE, 0 },
+ { "abcdefg", 'E', 5, PR_FALSE, 0 },
+ { "abcdefg", 'F', 5, PR_FALSE, 0 },
+ { "abcdefg", 'G', 5, PR_FALSE, 0 },
+ { "abcdefg", 'H', 5, PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', 10, PR_TRUE, 0 },
+ { "abcdefgabcdefg", 'b', 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", 'c', 10, PR_TRUE, 2 },
+ { "abcdefgabcdefg", 'd', 10, PR_TRUE, 3 },
+ { "abcdefgabcdefg", 'e', 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", 'f', 10, PR_TRUE, 5 },
+ { "abcdefgabcdefg", 'g', 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", 'h', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 14, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 15, PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 017 (PL_strnchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnchr(array[i].str, array[i].chr, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnrchr */
+PRBool test_018(void)
+{
+ static struct
+ {
+ const char *str;
+ char chr;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, 'a', 2, PR_FALSE, 0 },
+ { (const char *)0, '\0', 2, PR_FALSE, 0 },
+ { "abcdefg", 'a', 5, PR_TRUE, 0 },
+ { "abcdefg", 'b', 5, PR_TRUE, 1 },
+ { "abcdefg", 'c', 5, PR_TRUE, 2 },
+ { "abcdefg", 'd', 5, PR_TRUE, 3 },
+ { "abcdefg", 'e', 5, PR_TRUE, 4 },
+ { "abcdefg", 'f', 5, PR_FALSE, 0 },
+ { "abcdefg", 'g', 5, PR_FALSE, 0 },
+ { "abcdefg", 'h', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 5, PR_FALSE, 0 },
+ { "abcdefg", '\0', 15, PR_TRUE, 7 },
+ { "abcdefg", 'A', 5, PR_FALSE, 0 },
+ { "abcdefg", 'B', 5, PR_FALSE, 0 },
+ { "abcdefg", 'C', 5, PR_FALSE, 0 },
+ { "abcdefg", 'D', 5, PR_FALSE, 0 },
+ { "abcdefg", 'E', 5, PR_FALSE, 0 },
+ { "abcdefg", 'F', 5, PR_FALSE, 0 },
+ { "abcdefg", 'G', 5, PR_FALSE, 0 },
+ { "abcdefg", 'H', 5, PR_FALSE, 0 },
+ { "abcdefgabcdefg", 'a', 10, PR_TRUE, 7 },
+ { "abcdefgabcdefg", 'b', 10, PR_TRUE, 8 },
+ { "abcdefgabcdefg", 'c', 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", 'd', 10, PR_TRUE, 3 },
+ { "abcdefgabcdefg", 'e', 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", 'f', 10, PR_TRUE, 5 },
+ { "abcdefgabcdefg", 'g', 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", 'h', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 14, PR_FALSE, 0 },
+ { "abcdefgabcdefg", '\0', 15, PR_TRUE, 14 }
+ };
+
+ int i;
+
+ printf("Test 018 (PL_strnrchr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnrchr(array[i].str, array[i].chr, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> %.32s, not zero\n", i, array[i].str,
+ array[i].chr, array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> null, not +%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%c/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str,
+ array[i].chr, array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strpbrk */
+PRBool test_019(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "abc", PR_FALSE, 0 },
+ { "abc", (const char *)0, PR_FALSE, 0 },
+ { "abcdefg", "", PR_FALSE, 0 },
+ { "", "aeiou", PR_FALSE, 0 },
+ { "abcdefg", "ae", PR_TRUE, 0 },
+ { "abcdefg", "ei", PR_TRUE, 4 },
+ { "abcdefg", "io", PR_FALSE, 0 },
+ { "abcdefg", "bcd", PR_TRUE, 1 },
+ { "abcdefg", "cbd", PR_TRUE, 1 },
+ { "abcdefg", "dbc", PR_TRUE, 1 },
+ { "abcdefg", "ghi", PR_TRUE, 6 },
+ { "abcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefg", "GHI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "ei", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "io", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "cbd", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "dbc", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "ghi", PR_TRUE, 6 },
+ { "abcdefgabcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 019 (PL_strpbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strpbrk(array[i].str, array[i].chrs);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strprbrk */
+PRBool test_020(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "abc", PR_FALSE, 0 },
+ { "abc", (const char *)0, PR_FALSE, 0 },
+ { "abcdefg", "", PR_FALSE, 0 },
+ { "", "aeiou", PR_FALSE, 0 },
+ { "abcdefg", "ae", PR_TRUE, 4 },
+ { "abcdefg", "ei", PR_TRUE, 4 },
+ { "abcdefg", "io", PR_FALSE, 0 },
+ { "abcdefg", "bcd", PR_TRUE, 3 },
+ { "abcdefg", "cbd", PR_TRUE, 3 },
+ { "abcdefg", "dbc", PR_TRUE, 3 },
+ { "abcdefg", "ghi", PR_TRUE, 6 },
+ { "abcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefg", "GHI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "ei", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "io", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", PR_TRUE, 10 },
+ { "abcdefgabcdefg", "cbd", PR_TRUE, 10 },
+ { "abcdefgabcdefg", "dbc", PR_TRUE, 10 },
+ { "abcdefgabcdefg", "ghi", PR_TRUE, 13 },
+ { "abcdefgabcdefg", "AE", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 020 (PL_strprbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strprbrk(array[i].str, array[i].chrs);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnpbrk */
+PRBool test_021(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 3, PR_FALSE, 0 },
+ { (const char *)0, "abc", 3, PR_FALSE, 0 },
+ { "abc", (const char *)0, 3, PR_FALSE, 0 },
+ { "abcdefg", "", 3, PR_FALSE, 0 },
+ { "", "aeiou", 3, PR_FALSE, 0 },
+ { "abcdefg", "ae", 0, PR_FALSE, 0 },
+ { "abcdefg", "ae", 1, PR_TRUE, 0 },
+ { "abcdefg", "ae", 4, PR_TRUE, 0 },
+ { "abcdefg", "ae", 5, PR_TRUE, 0 },
+ { "abcdefg", "ae", 6, PR_TRUE, 0 },
+ { "abcdefg", "ei", 4, PR_FALSE, 0 },
+ { "abcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefg", "bcd", 2, PR_TRUE, 1 },
+ { "abcdefg", "cbd", 2, PR_TRUE, 1 },
+ { "abcdefg", "dbc", 2, PR_TRUE, 1 },
+ { "abcdefg", "ghi", 6, PR_FALSE, 0 },
+ { "abcdefg", "ghi", 7, PR_TRUE, 6 },
+ { "abcdefg", "AE", 9, PR_FALSE, 0 },
+ { "abcdefg", "EI", 9, PR_FALSE, 0 },
+ { "abcdefg", "IO", 9, PR_FALSE, 0 },
+ { "abcdefg", "BCD", 9, PR_FALSE, 0 },
+ { "abcdefg", "CBD", 9, PR_FALSE, 0 },
+ { "abcdefg", "DBC", 9, PR_FALSE, 0 },
+ { "abcdefg", "GHI", 9, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", 10, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "ei", 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "cbd", 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "dbc", 10, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "ghi", 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "AE", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", 10, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 021 (PL_strnpbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnpbrk(array[i].str, array[i].chrs, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnprbrk */
+PRBool test_022(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *chrs;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 3, PR_FALSE, 0 },
+ { (const char *)0, "abc", 3, PR_FALSE, 0 },
+ { "abc", (const char *)0, 3, PR_FALSE, 0 },
+ { "abcdefg", "", 3, PR_FALSE, 0 },
+ { "", "aeiou", 3, PR_FALSE, 0 },
+ { "abcdefg", "ae", 0, PR_FALSE, 0 },
+ { "abcdefg", "ae", 1, PR_TRUE, 0 },
+ { "abcdefg", "ae", 4, PR_TRUE, 0 },
+ { "abcdefg", "ae", 5, PR_TRUE, 4 },
+ { "abcdefg", "ae", 6, PR_TRUE, 4 },
+ { "abcdefg", "ei", 4, PR_FALSE, 0 },
+ { "abcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefg", "bcd", 2, PR_TRUE, 1 },
+ { "abcdefg", "cbd", 2, PR_TRUE, 1 },
+ { "abcdefg", "dbc", 2, PR_TRUE, 1 },
+ { "abcdefg", "bcd", 3, PR_TRUE, 2 },
+ { "abcdefg", "cbd", 3, PR_TRUE, 2 },
+ { "abcdefg", "dbc", 3, PR_TRUE, 2 },
+ { "abcdefg", "bcd", 5, PR_TRUE, 3 },
+ { "abcdefg", "cbd", 5, PR_TRUE, 3 },
+ { "abcdefg", "dbc", 5, PR_TRUE, 3 },
+ { "abcdefg", "bcd", 15, PR_TRUE, 3 },
+ { "abcdefg", "cbd", 15, PR_TRUE, 3 },
+ { "abcdefg", "dbc", 15, PR_TRUE, 3 },
+ { "abcdefg", "ghi", 6, PR_FALSE, 0 },
+ { "abcdefg", "ghi", 7, PR_TRUE, 6 },
+ { "abcdefg", "AE", 9, PR_FALSE, 0 },
+ { "abcdefg", "EI", 9, PR_FALSE, 0 },
+ { "abcdefg", "IO", 9, PR_FALSE, 0 },
+ { "abcdefg", "BCD", 9, PR_FALSE, 0 },
+ { "abcdefg", "CBD", 9, PR_FALSE, 0 },
+ { "abcdefg", "DBC", 9, PR_FALSE, 0 },
+ { "abcdefg", "GHI", 9, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ae", 10, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "ei", 10, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "io", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "bcd", 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "cbd", 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "dbc", 10, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ghi", 10, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "AE", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "EI", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "IO", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "BCD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "CBD", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "DBC", 10, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "GHI", 10, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 022 (PL_strnprbrk) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnprbrk(array[i].str, array[i].chrs, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not +%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].chrs ? array[i].chrs : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strstr */
+PRBool test_023(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 0 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 023 (PL_strstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strstr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strrstr */
+PRBool test_024(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 8 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 13 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 7 },
+ { "ABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 024 (PL_strrstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strrstr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnstr */
+PRBool test_025(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 0 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFG", "a", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "c", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "e", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "cd", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 6, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 5, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 6, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 7, PR_FALSE, },
+ { "ABCDEFGABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 7, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 8, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 025 (PL_strnstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnstr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strnrstr */
+PRBool test_026(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 11, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 8 },
+ { "blah-de-blah", "blah", 13, PR_TRUE, 8 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 12, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 13, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 14, PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", 13, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 14, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "abcdefg", 15, PR_TRUE, 7 },
+ { "ABCDEFG", "a", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "c", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "e", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "cd", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 6, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 13, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 14, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 13, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 14, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 15, PR_FALSE, 0 }
+ };
+
+ int i;
+
+ printf("Test 026 (PL_strnrstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strnrstr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcasestr */
+PRBool test_027(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 0 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFG", "a", PR_TRUE, 0 },
+ { "ABCDEFG", "c", PR_TRUE, 2 },
+ { "ABCDEFG", "e", PR_TRUE, 4 },
+ { "ABCDEFG", "g", PR_TRUE, 6 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_TRUE, 0 },
+ { "ABCDEFG", "cd", PR_TRUE, 2 },
+ { "ABCDEFG", "ef", PR_TRUE, 4 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_TRUE, 1 },
+ { "ABCDEFG", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "c", PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "e", PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "g", PR_TRUE, 6 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "cd", PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "ef", PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_TRUE, 1 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_TRUE, 0 }
+ };
+
+ int i;
+
+ printf("Test 027 (PL_strcasestr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strcasestr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strcaserstr */
+PRBool test_028(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, PR_FALSE, 0 },
+ { (const char *)0, "blah", PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", PR_TRUE, 8 },
+ { "", "blah", PR_FALSE, 0 },
+ { "blah-de-blah", "", PR_FALSE, 0 },
+ { "abcdefg", "a", PR_TRUE, 0 },
+ { "abcdefg", "c", PR_TRUE, 2 },
+ { "abcdefg", "e", PR_TRUE, 4 },
+ { "abcdefg", "g", PR_TRUE, 6 },
+ { "abcdefg", "i", PR_FALSE, 0 },
+ { "abcdefg", "ab", PR_TRUE, 0 },
+ { "abcdefg", "cd", PR_TRUE, 2 },
+ { "abcdefg", "ef", PR_TRUE, 4 },
+ { "abcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabc", "bc", PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", PR_TRUE, 13 },
+ { "abcdefgabcdefg", "i", PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", PR_TRUE, 11 },
+ { "abcdefgabcdefg", "gh", PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", PR_TRUE, 7 },
+ { "ABCDEFG", "a", PR_TRUE, 0 },
+ { "ABCDEFG", "c", PR_TRUE, 2 },
+ { "ABCDEFG", "e", PR_TRUE, 4 },
+ { "ABCDEFG", "g", PR_TRUE, 6 },
+ { "ABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFG", "ab", PR_TRUE, 0 },
+ { "ABCDEFG", "cd", PR_TRUE, 2 },
+ { "ABCDEFG", "ef", PR_TRUE, 4 },
+ { "ABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABC", "bc", PR_TRUE, 5 },
+ { "ABCDEFG", "abcdefg", PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "c", PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "e", PR_TRUE, 11 },
+ { "ABCDEFGABCDEFG", "g", PR_TRUE, 13 },
+ { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "cd", PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "ef", PR_TRUE, 11 },
+ { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", PR_TRUE, 12 },
+ { "ABCDEFGABCDEFG", "abcdefg", PR_TRUE, 7 }
+ };
+
+ int i;
+
+ printf("Test 028 (PL_strcaserstr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strcaserstr(array[i].str, array[i].sub);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncasestr */
+PRBool test_029(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 0 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 2 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabcabcdabc", "bc", 7, PR_TRUE, 1 },
+ { "abcdefgabcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFG", "a", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "c", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "e", 5, PR_TRUE, 4 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "cd", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 6, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 7, PR_TRUE, 1 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_TRUE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_TRUE, 6 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_TRUE, 2 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 5, PR_TRUE, 1 },
+ { "ABCDABCABCDABC", "bc", 6, PR_TRUE, 1 },
+ { "ABCDABCABCDABC", "bc", 7, PR_TRUE, 1 },
+ { "ABCDEFGABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 7, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 8, PR_TRUE, 0 }
+ };
+
+ int i;
+
+ printf("Test 029 (PL_strncasestr) ..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strncasestr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strncaserstr */
+PRBool test_030(void)
+{
+ static struct
+ {
+ const char *str;
+ const char *sub;
+ PRUint32 max;
+ PRBool ret;
+ PRUint32 off;
+ } array[] =
+ {
+ { (const char *)0, (const char *)0, 12, PR_FALSE, 0 },
+ { (const char *)0, "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 0, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 2, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 3, PR_FALSE, 0 },
+ { "blah-de-blah", "blah", 4, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 5, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 11, PR_TRUE, 0 },
+ { "blah-de-blah", "blah", 12, PR_TRUE, 8 },
+ { "blah-de-blah", "blah", 13, PR_TRUE, 8 },
+ { "", "blah", 12, PR_FALSE, 0 },
+ { "blah-de-blah", "", 12, PR_FALSE, 0 },
+ { "abcdefg", "a", 5, PR_TRUE, 0 },
+ { "abcdefg", "c", 5, PR_TRUE, 2 },
+ { "abcdefg", "e", 5, PR_TRUE, 4 },
+ { "abcdefg", "g", 5, PR_FALSE, 0 },
+ { "abcdefg", "i", 5, PR_FALSE, 0 },
+ { "abcdefg", "ab", 5, PR_TRUE, 0 },
+ { "abcdefg", "cd", 5, PR_TRUE, 2 },
+ { "abcdefg", "ef", 5, PR_FALSE, 0 },
+ { "abcdefg", "gh", 5, PR_FALSE, 0 },
+ { "abcdabc", "bc", 5, PR_TRUE, 1 },
+ { "abcdabc", "bc", 6, PR_TRUE, 1 },
+ { "abcdabc", "bc", 7, PR_TRUE, 5 },
+ { "abcdefg", "abcdefg", 6, PR_FALSE, 0 },
+ { "abcdefg", "abcdefg", 7, PR_TRUE, 0 },
+ { "abcdefg", "abcdefg", 8, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "a", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "c", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "e", 12, PR_TRUE, 11 },
+ { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 },
+ { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 },
+ { "abcdefgabcdefg", "ab", 12, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "cd", 12, PR_TRUE, 9 },
+ { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 },
+ { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 },
+ { "abcdabcabcdabc", "bc", 12, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 13, PR_TRUE, 8 },
+ { "abcdabcabcdabc", "bc", 14, PR_TRUE, 12 },
+ { "abcdefgabcdefg", "abcdefg", 13, PR_TRUE, 0 },
+ { "abcdefgabcdefg", "abcdefg", 14, PR_TRUE, 7 },
+ { "abcdefgabcdefg", "abcdefg", 15, PR_TRUE, 7 },
+ { "ABCDEFG", "a", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "c", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "e", 5, PR_TRUE, 4 },
+ { "ABCDEFG", "g", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "i", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "ab", 5, PR_TRUE, 0 },
+ { "ABCDEFG", "cd", 5, PR_TRUE, 2 },
+ { "ABCDEFG", "ef", 5, PR_FALSE, 0 },
+ { "ABCDEFG", "gh", 5, PR_FALSE, 0 },
+ { "ABCDABC", "bc", 5, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 6, PR_TRUE, 1 },
+ { "ABCDABC", "bc", 7, PR_TRUE, 5 },
+ { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 },
+ { "ABCDEFG", "abcdefg", 7, PR_TRUE, 0 },
+ { "ABCDEFG", "abcdefg", 8, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "a", 12, PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "c", 12, PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "e", 12, PR_TRUE, 11 },
+ { "ABCDEFGABCDEFG", "g", 12, PR_TRUE, 6 },
+ { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 },
+ { "ABCDEFGABCDEFG", "ab", 12, PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "cd", 12, PR_TRUE, 9 },
+ { "ABCDEFGABCDEFG", "ef", 12, PR_TRUE, 4 },
+ { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 },
+ { "ABCDABCABCDABC", "bc", 12, PR_TRUE, 8 },
+ { "ABCDABCABCDABC", "bc", 13, PR_TRUE, 8 },
+ { "ABCDABCABCDABC", "bc", 14, PR_TRUE, 12 },
+ { "ABCDEFGABCDEFG", "abcdefg", 13, PR_TRUE, 0 },
+ { "ABCDEFGABCDEFG", "abcdefg", 14, PR_TRUE, 7 },
+ { "ABCDEFGABCDEFG", "abcdefg", 15, PR_TRUE, 7 }
+ };
+
+ int i;
+
+ printf("Test 030 (PL_strncaserstr)..."); fflush(stdout);
+
+ for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ )
+ {
+ char *rv = PL_strncaserstr(array[i].str, array[i].sub, array[i].max);
+
+ if( PR_FALSE == array[i].ret )
+ {
+ if( (char *)0 != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv);
+ return PR_FALSE;
+ }
+ }
+ else
+ {
+ if( (char *)0 == rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+
+ if( &array[i].str[ array[i].off ] != rv )
+ {
+ printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i,
+ array[i].str ? array[i].str : "(null)",
+ array[i].sub ? array[i].sub : "(null)",
+ array[i].max, rv, array[i].str, array[i].off);
+ return PR_FALSE;
+ }
+ }
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+/* PL_strtok_r */
+PRBool test_031(void)
+{
+ static const char *tokens[] = {
+ "wtc", "relyea", "nelsonb", "jpierre", "nicolson",
+ "ian.mcgreer", "kirk.erickson", "sonja.mirtitsch", "mhein"
+ };
+
+ static const char *seps[] = {
+ ", ", ",", " ", "\t", ",,,", " ,", " ", " \t\t", ","
+ };
+
+ static const char s2[] = ", \t";
+
+ char string[ 1024 ];
+ char *s1;
+ char *token;
+ char *lasts;
+ unsigned int i;
+
+ printf("Test 031 (PL_strtok_r) ..."); fflush(stdout);
+
+ /* Build the string. */
+ string[0] = '\0';
+ for( i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++ )
+ {
+ PL_strcat(string, tokens[i]);
+ PL_strcat(string, seps[i]);
+ }
+
+ /* Scan the string for tokens. */
+ i = 0;
+ s1 = string;
+ while( (token = PL_strtok_r(s1, s2, &lasts)) != NULL)
+ {
+ if( PL_strcmp(token, tokens[i]) != 0 )
+ {
+ printf("FAIL wrong token scanned\n");
+ return PR_FALSE;
+ }
+ i++;
+ s1 = NULL;
+ }
+ if( i != sizeof(tokens)/sizeof(tokens[0]) )
+ {
+ printf("FAIL wrong number of tokens scanned\n");
+ return PR_FALSE;
+ }
+
+ printf("PASS\n");
+ return PR_TRUE;
+}
+
+int
+main
+(
+ int argc,
+ char *argv[]
+)
+{
+ printf("Testing the Portable Library string functions:\n");
+
+ if( 1
+ && test_001()
+ && test_001()
+ && test_002()
+ && test_003()
+ && test_004()
+ && test_005()
+ && test_006()
+ && test_007()
+ && test_008()
+ && test_009()
+ && test_010()
+ && test_011()
+ && test_012()
+ && test_013()
+ && test_014()
+ && test_015()
+ && test_016()
+ && test_017()
+ && test_018()
+ && test_019()
+ && test_020()
+ && test_021()
+ && test_022()
+ && test_023()
+ && test_024()
+ && test_025()
+ && test_026()
+ && test_027()
+ && test_028()
+ && test_029()
+ && test_030()
+ && test_031()
+ )
+ {
+ printf("Suite passed.\n");
+ return 0;
+ }
+ else
+ {
+ printf("Suite failed.\n");
+ return 1;
+ }
+
+ /*NOTREACHED*/
+}
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/windows/makefile b/src/libs/xpcom18a4/nsprpub/lib/tests/windows/makefile
new file mode 100644
index 00000000..1cf2c079
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/windows/makefile
@@ -0,0 +1,82 @@
+#
+# 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998-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.
+#
+
+#! gmake
+
+
+
+MOD_DEPTH = ../../..
+
+include $(MOD_DEPTH)/config/config.mk
+
+INCLUDES = -I$(DIST)/include
+
+CSRCS = winevent.c
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+ LIBPR = $(DIST)/lib/nspr$(MOD_VERSION).lib
+ LIBPLC= $(DIST)/lib/plc$(MOD_VERSION).lib
+ LIBPLDS= $(DIST)/lib/plds$(MOD_VERSION).lib
+else
+ LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+ ifeq ($(OS_TARGET), WIN95)
+ LIBPR = $(DIST)/lib/nspr$(MOD_VERSION).$(LIB_SUFFIX)
+ LIBPLC= $(DIST)/lib/plc$(MOD_VERSION).$(LIB_SUFFIX)
+ LIBPLDS= $(DIST)/lib/plds$(MOD_VERSION).lib
+ else
+ LIBPR = $(DIST)/lib/libnspr$(MOD_VERSION).$(LIB_SUFFIX)
+ LIBPLC= $(DIST)/lib/libplc$(MOD_VERSION).$(LIB_SUFFIX)
+ LIBPLDS= $(DIST)/lib/libplds$(MOD_VERSION).lib
+ endif
+endif
+endif
+
+TARGETS = $(OBJDIR)/winevent.exe
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+LDFLAGS += -DEBUG
+LIBPR += $(LIBPLDS)
+LIBPR += kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
+
+include $(MOD_DEPTH)/config/rules.mk
+
+$(OBJDIR)/winevent.exe: $(OBJS)
+ link $(LDOPTS) $< $(LIBPLC) $(LIBPR) wsock32.lib -out:$@
+
+export:: $(TARGETS)
+
+install:: export
+
+clean::
+ rm -rf $(TARGETS)
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/windows/readme.1st b/src/libs/xpcom18a4/nsprpub/lib/tests/windows/readme.1st
new file mode 100644
index 00000000..2b756823
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/windows/readme.1st
@@ -0,0 +1,37 @@
+readme.1st.
+
+The files in the lib/tests/WinGUI directory are taken
+from "Programming Windows 3.1" by Charles Petzold,
+specifically, the programs in chapter 14 related
+to the "poppad4" sample application.
+
+These programs are compiled with nspr20 to test nspr 2.0
+and to demostrate the use of nspr in a gui application.
+
+Library (DLL) PLDSxx.lib PLDSxx.dll is required to be
+linked with this test case. Functions in this dll are
+in the source ns/nspr20/lib/ds/plevent.* files.
+
+Permission to use.
+
+The source for poppad.c are used under license from
+Petzold. The license to use is stated in the book.
+The following paragraph of the license grants that
+use.
+
+ 5. SAMPLE CODE. If the SOFTWARE includes Sample Code, then
+ Microsoft grants you a royalty-free right to reproduce and
+ distribute the sample code of the SOFTWARE provided that you:
+ (a) distribute the sample code only in conjunction with and
+ as part of your software product; (b) do not use Microsoft's
+ or its authors' names, logos, or trademarks to market your
+ software product; (c) include the copyright notice that appears
+ on the SOFTWARE on your product label and as a part of the
+ sign-on message for your software product; and (d) agree to
+ idemnify, hold harmless, and defend Microsoft and its authors
+ from and against any claims or lawsuits, including attorneys'
+ fees, that arise or result from the use or distribution of
+ your software product.
+
+lth. 9/24/97.
+
diff --git a/src/libs/xpcom18a4/nsprpub/lib/tests/windows/winevent.c b/src/libs/xpcom18a4/nsprpub/lib/tests/windows/winevent.c
new file mode 100644
index 00000000..d571aed7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/lib/tests/windows/winevent.c
@@ -0,0 +1,348 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: winevent.c
+** Description: Test functions in plevent.c using Windows
+**
+** The winevent test exercises the PLEvent library in a maner
+** similar to how the Mozilla (or NGLayout) Client will use
+** it in a Windows environment.
+**
+** This test is based on ideas taken from Charles Petzold's
+** book "Programming Windows 3.1". License to use is in the
+** book. It has been ported to Win32.
+**
+** Operation:
+** The initialization is a standard Windows GUI application
+** setup. When the main window receives its WM_CREATE
+** message, a child window is created, a edit control is
+** instantiated in that window.
+**
+** A thread is created; this thread runs in the function:
+** TimerThread(). The new thread sends a message every second
+** via the PL_PostEvent() function. The event handler
+** HandlePadEvent() sends a windows message to the edit
+** control window; these messages are WM_CHAR messages that
+** cause the edit control to place a single '.' character in
+** the edit control.
+**
+** After a deterministic number of '.' characters, the
+** TimerThread() function is notified via a global variable
+** that it's quitting time.
+**
+** TimerThread() callse TestEvents(), an external function
+** that tests additional function of PLEvent.
+**
+*/
+
+#include "nspr.h"
+#include "plevent.h"
+
+#include <windows.h>
+#include <commdlg.h>
+
+#define ID_EDIT 1
+
+/*
+** Declarations for NSPR customization
+**
+*/
+typedef struct PadEvent
+{
+ PLEvent plEvent;
+ int unused;
+} PadEvent;
+
+static void PR_CALLBACK TimerThread( void *arg);
+static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent );
+static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent );
+
+static PRThread *tThread;
+static PLEventQueue *padQueue;
+static long ThreadSleepTime = 1000; /* in milli-seconds */
+static long timerCount = 0;
+static HWND hDlgModeless ;
+static HWND hwndEdit ;
+static PRBool testFinished = PR_FALSE;
+static HWND hwnd ;
+
+LRESULT CALLBACK WinProc (HWND, UINT, WPARAM, LPARAM);
+
+TCHAR appName[] = TEXT ("WinEvent") ;
+
+int WINAPI WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ PSTR szCmdLine,
+ int iCmdShow
+ )
+{
+ MSG msg ;
+ WNDCLASS wndclass ;
+ HANDLE hAccel ;
+
+ PR_Init(0, 0, 0);
+
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = WinProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = appName;
+
+ if ( !RegisterClass( &wndclass ))
+ {
+ MessageBox( NULL,
+ TEXT( "This program needs Win32" ),
+ appName,
+ MB_ICONERROR );
+ return 0;
+ }
+
+ hwnd = CreateWindow( appName,
+ appName,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ hInstance,
+ NULL);
+
+ ShowWindow( hwnd, iCmdShow );
+ UpdateWindow( hwnd );
+
+ for(;;)
+ {
+ if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
+ {
+ if ( GetMessage( &msg, NULL, 0, 0 ))
+ {
+ if ( hDlgModeless == NULL || !IsDialogMessage( hDlgModeless, &msg ))
+ {
+ if ( !TranslateAccelerator( hwnd, hAccel, &msg ))
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ } /* end if !TranslateAccelerator */
+ }
+ }
+ else
+ {
+ break;
+ } /* end if GetMessage() */
+ }
+ else /* !PeekMessage */
+ {
+ PR_Sleep(50);
+ }/* end if PeekMessage() */
+ } /* end for() */
+
+ PR_JoinThread( tThread );
+ PL_DestroyEventQueue( padQueue );
+ PR_Cleanup();
+ return msg.wParam ;
+}
+
+LRESULT CALLBACK WinProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ switch (message)
+ {
+ case WM_CREATE :
+ hwndEdit = CreateWindow(
+ TEXT( "edit" ),
+ NULL,
+ WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
+ WS_BORDER | ES_LEFT | ES_MULTILINE |
+ ES_AUTOHSCROLL | ES_AUTOVSCROLL,
+ 0, 0, 0, 0,
+ hwnd,
+ (HMENU)ID_EDIT,
+ ((LPCREATESTRUCT)lParam)->hInstance,
+ NULL);
+
+ /* Initialize Event Processing for NSPR
+ ** Retrieve the event queue just created
+ ** Create the TimerThread
+ */
+
+/*
+ PL_InitializeEventsLib( "someName" );
+ padQueue = PL_GetMainEventQueue();
+*/
+ padQueue = PL_CreateEventQueue("MainQueue", PR_GetCurrentThread());
+ PR_ASSERT( padQueue != NULL );
+ tThread = PR_CreateThread( PR_USER_THREAD,
+ TimerThread,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+ return 0 ;
+
+ case WM_SETFOCUS :
+ SetFocus( hwndEdit );
+ return 0;
+
+ case WM_SIZE :
+ MoveWindow( hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE );
+ return 0 ;
+
+ case WM_COMMAND :
+ if ( LOWORD(wParam) == ID_EDIT )
+ if ( HIWORD(wParam ) == EN_ERRSPACE ||
+ HIWORD( wParam ) == EN_MAXTEXT )
+
+ MessageBox( hwnd, TEXT( "Edit control out of space." ),
+ appName, MB_OK | MB_ICONSTOP );
+ return 0;
+
+ case WM_DESTROY :
+ PostQuitMessage(0);
+ return 0;
+ }
+ return DefWindowProc( hwnd, message, wParam, lParam );
+}
+
+
+
+/*
+** TimerThread() -- The Main function of the timer pop thread
+**
+*/
+static void PR_CALLBACK TimerThread( void *arg )
+{
+ PRIntn rc;
+
+ do {
+ PadEvent *ev;
+
+ /*
+ ** Create and Post the event the event
+ */
+ PL_ENTER_EVENT_QUEUE_MONITOR( padQueue );
+ ev = (PadEvent *) PR_NEW( PadEvent );
+ PL_InitEvent( &ev->plEvent, NULL,
+ (PLHandleEventProc)HandlePadEvent,
+ (PLDestroyEventProc)DestroyPadEvent );
+ PL_PostEvent( padQueue, &ev->plEvent );
+ PL_EXIT_EVENT_QUEUE_MONITOR( padQueue );
+
+ PR_Sleep( PR_MillisecondsToInterval(ThreadSleepTime) );
+ } while( testFinished == PR_FALSE );
+
+ PR_Sleep( PR_SecondsToInterval(4) );
+
+ /*
+ ** All done now. This thread can kill the main thread by sending
+ ** WM_DESTROY message to the main window.
+ */
+ SendMessage( hwnd, WM_DESTROY, 0, 0 );
+ return;
+}
+
+static char *startMessage = "Poppad: NSPR Windows GUI and event test program.\n"
+ "Every 1 second gets a '.'.\n"
+ "The test self terminates in less than a minute\n"
+ "You should be able to type in the window.\n\n";
+
+static char *stopMessage = "\n\nIf you saw a series of dots being emitted in the window\n"
+ " at one second intervals, the test worked.\n\n";
+
+/*
+** HandlePadEvent() -- gets called because of PostEvent
+*/
+static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent )
+{
+ char *cp;
+ static const long lineLimit = 10; /* limit on number of '.' per line */
+ static const long timerLimit = 25; /* limit on timer pop iterations */
+
+ if ( timerCount++ == 0 )
+ {
+
+ for ( cp = startMessage; *cp != 0 ; cp++ )
+ {
+ SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
+ }
+ }
+ /*
+ ** Send a WM_CHAR event the edit Window
+ */
+ SendMessage( hwndEdit, WM_CHAR, '.', 1 );
+
+ /*
+ ** Limit the number of characters sent via timer pop to lineLimit
+ */
+ if ( (timerCount % lineLimit) == 0)
+ {
+ SendMessage( hwndEdit, WM_CHAR, '\n', 1 );
+ }
+
+ if ( timerCount >= timerLimit )
+ {
+ for ( cp = stopMessage; *cp != 0 ; cp++ )
+ {
+ SendMessage( hwndEdit, WM_CHAR, *cp, 1 );
+ }
+ testFinished = PR_TRUE;
+ }
+
+ return;
+}
+
+/*
+** DestroyPadEvent() -- Called after HandlePadEvent()
+*/
+static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent )
+{
+ PR_Free( padevent );
+ return;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/makefile.win b/src/libs/xpcom18a4/nsprpub/makefile.win
new file mode 100644
index 00000000..97beeabe
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/makefile.win
@@ -0,0 +1,127 @@
+
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#
+# An NMAKE file to set up and adjust NSPR20's build system for
+# Client build. Client build should invoke NMAKE on this file
+# instead of invoking gmake directly.
+#
+
+DEPTH = ..
+include <$(DEPTH)\config\config.mak>
+
+#
+# Backslashes are escape characters to gmake, so flip all backslashes
+# in $(MOZ_TOOLS) to forward slashes and pass that to gmake.
+#
+
+GMAKE = $(MOZ_TOOLS)\bin\gmake.exe
+
+GMAKE_FLAGS = MOZ_TOOLS_FLIPPED=$(MOZ_TOOLS:\=/) PR_CLIENT_BUILD=1 PR_CLIENT_BUILD_WINDOWS=1
+
+#
+# The Client's debug build uses MSVC's debug runtime library (/MDd).
+#
+
+!ifdef MOZ_DEBUG
+!else
+GMAKE_FLAGS = $(GMAKE_FLAGS) BUILD_OPT=1
+!endif
+
+!if "$(MOZ_BITS)" == "16"
+GMAKE_FLAGS = $(GMAKE_FLAGS) OS_TARGET=WIN16
+!else
+
+GMAKE_FLAGS = $(GMAKE_FLAGS) OS_TARGET=WIN95
+!ifdef MOZ_DEBUG
+!ifdef MOZ_NO_DEBUG_RTL
+!IF "$(CPU)" == "ALPHA"
+PR_OBJDIR = WIN954.0ALPHA_DBG.OBJ
+!else
+PR_OBJDIR = WIN954.0_DBG.OBJ
+!endif
+!else
+GMAKE_FLAGS = $(GMAKE_FLAGS) USE_DEBUG_RTL=1
+!IF "$(CPU)" == "ALPHA"
+PR_OBJDIR = WIN954.0ALPHA_DBG.OBJD
+!else
+PR_OBJDIR = WIN954.0_DBG.OBJD
+!endif
+!endif
+!else
+!IF "$(CPU)" == "ALPHA"
+PR_OBJDIR = WIN954.0ALPHA_OPT.OBJ
+!else
+PR_OBJDIR = WIN954.0_OPT.OBJ
+!endif
+!endif
+
+!endif
+
+
+#
+# The rules. Simply invoke gmake with the same target.
+# The default target is 'all'. For Win16, set up the
+# environment to use the Watcom compiler, Watcom headers,
+# and Watcom libs.
+#
+
+all:: export libs install
+
+export libs install clobber clobber_all clean depend::
+!if "$(MOZ_BITS)" == "16"
+ set PATH=%WATCPATH%
+ set INCLUDE=%WATC_INC%
+ set LIB=%WATC_LIB%
+!endif
+ $(GMAKE) $(GMAKE_FLAGS) $@
+!if "$(MOZ_BITS)" == "16"
+ set PATH=%MSVCPATH%
+ set INCLUDE=%MSVC_INC%
+ set LIB=%MSVC_LIB%
+!endif
+
+!if "$(MOZ_BITS)" != "16"
+export::
+ $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\include\*.h $(DIST)\include
+ $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\include\obsolete\*.h $(DIST)\include\obsolete
+ $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\include\private\*.h $(DIST)\include\private
+ $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\lib\*.lib $(DIST)\lib
+ $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\lib\*.dll $(DIST)\bin
+!endif
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/Makefile.in b/src/libs/xpcom18a4/nsprpub/pkg/Makefile.in
new file mode 100644
index 00000000..b21d7741
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/Makefile.in
@@ -0,0 +1,58 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+DIRS =
+ifeq ($(OS_TARGET),Linux)
+DIRS = linux
+endif
+ifeq ($(OS_TARGET),SunOS)
+DIRS = solaris
+endif
+
+publish::
+ +$(LOOP_OVER_DIRS)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/linux/Makefile.in b/src/libs/xpcom18a4/nsprpub/pkg/linux/Makefile.in
new file mode 100644
index 00000000..630af186
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/linux/Makefile.in
@@ -0,0 +1,44 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: Makefile.in $"
+#
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+NAME = sun-nspr
+RELEASE = 1
+TOPDIR = /usr/src/redhat
+VERSION = `grep PR_VERSION $(dist_includedir)/prinit.h \
+ | sed -e 's/"$$//' -e 's/.*"//' -e 's/ .*//'`
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+publish:
+ $(MAKE) clean
+ mkdir -p usr/lib/mps
+ cp -L $(MOD_DEPTH)/dist/lib/* usr/lib/mps
+ mkdir -p usr/include/mps
+ cp -Lr $(MOD_DEPTH)/dist/include/* usr/include/mps
+ tar czvf $(NAME)-$(VERSION).tar.gz usr
+ echo "%define name $(NAME)" >$(NAME).spec
+ echo "%define version $(VERSION)" >>$(NAME).spec
+ echo "%define release $(RELEASE)" >>$(NAME).spec
+
+ cat $(srcdir)/$(NAME).spec >>$(NAME).spec
+ cp $(NAME)-$(VERSION).tar.gz $(TOPDIR)/SOURCES
+ rpm -ba $(NAME).spec
+ if [ ! -d RPMS ] ; then mkdir -p RPMS ; fi
+ if [ ! -d SRPMS ] ; then mkdir -p SRPMS ; fi
+ cp -v $(TOPDIR)/RPMS/i386/$(NAME)-$(VERSION)-* RPMS
+ cp -v $(TOPDIR)/RPMS/i386/$(NAME)-devel-$(VERSION)-* RPMS
+ cp -v $(TOPDIR)/SRPMS/$(NAME)-$(VERSION)-* SRPMS
+
+clean:
+ rm -rf $(TOPDIR)/BUILD/$(NAME)
+ rm -rf RPMS SRPMS usr
+ rm -f $(NAME)-$(VERSION).tar.gz
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/linux/sun-nspr.spec b/src/libs/xpcom18a4/nsprpub/pkg/linux/sun-nspr.spec
new file mode 100644
index 00000000..1fed5048
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/linux/sun-nspr.spec
@@ -0,0 +1,122 @@
+Summary: Netscape Portable Runtime
+Name: %{name}
+Vendor: Sun Microsystems
+Version: %{version}
+Release: %{release}
+Copyright: MPL/GPL
+Group: System Environment/Base
+Source: %{name}-%{version}.tar.gz
+ExclusiveOS: Linux
+BuildRoot: /var/tmp/%{name}-root
+
+%description
+
+NSPR provides platform independence for non-GUI operating system
+facilities. These facilities include threads, thread synchronization,
+normal file and network I/O, interval timing and calendar time, basic
+memory management (malloc and free) and shared library linking.
+
+See: http://www.mozilla.org/projects/nspr/about-nspr.html
+
+%package devel
+Summary: Development Libraries for the Netscape Portable Runtime
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Header files for doing development with the Netscape Portable Runtime.
+
+%prep
+%setup -c
+
+%build
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir $RPM_BUILD_ROOT
+cd $RPM_BUILD_ROOT
+tar xvzf $RPM_SOURCE_DIR/%{name}-%{version}.tar.gz
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%dir /usr
+%dir /usr/lib
+%dir /usr/lib/mps
+/usr/lib/mps/libnspr4.so
+/usr/lib/mps/libplc4.so
+/usr/lib/mps/libplds4.so
+
+%files devel
+%defattr(-,root,root)
+/usr/lib/mps/libnspr4.a
+/usr/lib/mps/libplc4.a
+/usr/lib/mps/libplds4.a
+%dir /usr
+%dir /usr/include
+%dir /usr/include/mps
+%dir /usr/include/mps/nspr
+%dir /usr/include/mps/nspr/obsolete
+%dir /usr/include/mps/nspr/private
+/usr/include/mps/nspr/private/pprio.h
+/usr/include/mps/nspr/private/pprthred.h
+/usr/include/mps/nspr/private/prpriv.h
+/usr/include/mps/nspr/prcpucfg.h
+/usr/include/mps/nspr/obsolete/pralarm.h
+/usr/include/mps/nspr/obsolete/probslet.h
+/usr/include/mps/nspr/obsolete/protypes.h
+/usr/include/mps/nspr/obsolete/prsem.h
+/usr/include/mps/nspr/nspr.h
+/usr/include/mps/nspr/pratom.h
+/usr/include/mps/nspr/prbit.h
+/usr/include/mps/nspr/prclist.h
+/usr/include/mps/nspr/prcmon.h
+/usr/include/mps/nspr/prcountr.h
+/usr/include/mps/nspr/prcvar.h
+/usr/include/mps/nspr/prdtoa.h
+/usr/include/mps/nspr/prenv.h
+/usr/include/mps/nspr/prerr.h
+/usr/include/mps/nspr/prerror.h
+/usr/include/mps/nspr/prinet.h
+/usr/include/mps/nspr/prinit.h
+/usr/include/mps/nspr/prinrval.h
+/usr/include/mps/nspr/prio.h
+/usr/include/mps/nspr/pripcsem.h
+/usr/include/mps/nspr/prlink.h
+/usr/include/mps/nspr/prlock.h
+/usr/include/mps/nspr/prlog.h
+/usr/include/mps/nspr/prlong.h
+/usr/include/mps/nspr/prmem.h
+/usr/include/mps/nspr/prmon.h
+/usr/include/mps/nspr/prmwait.h
+/usr/include/mps/nspr/prnetdb.h
+/usr/include/mps/nspr/prolock.h
+/usr/include/mps/nspr/prpdce.h
+/usr/include/mps/nspr/prprf.h
+/usr/include/mps/nspr/prproces.h
+/usr/include/mps/nspr/prrng.h
+/usr/include/mps/nspr/prrwlock.h
+/usr/include/mps/nspr/prshma.h
+/usr/include/mps/nspr/prshm.h
+/usr/include/mps/nspr/prsystem.h
+/usr/include/mps/nspr/prthread.h
+/usr/include/mps/nspr/prtime.h
+/usr/include/mps/nspr/prtpool.h
+/usr/include/mps/nspr/prtrace.h
+/usr/include/mps/nspr/prtypes.h
+/usr/include/mps/nspr/prvrsion.h
+/usr/include/mps/nspr/prwin16.h
+/usr/include/mps/nspr/plarenas.h
+/usr/include/mps/nspr/plarena.h
+/usr/include/mps/nspr/plhash.h
+/usr/include/mps/nspr/plbase64.h
+/usr/include/mps/nspr/plerror.h
+/usr/include/mps/nspr/plgetopt.h
+/usr/include/mps/nspr/plresolv.h
+/usr/include/mps/nspr/plstr.h
+
+%changelog
+* Sat Jan 18 2003 Kirk Erickson <kirk.erickson@sun.com>
+- http://bugzilla.mozilla.org/show_bug.cgi?id=189501
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.com b/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.com
new file mode 100644
index 00000000..32de8a9b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.com
@@ -0,0 +1,32 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: Makefile.com $"
+#
+
+MACH = $(shell mach)
+
+PUBLISH_ROOT = $(DIST)
+ifeq ($(MOD_DEPTH),../..)
+ROOT = ROOT
+else
+ROOT = $(subst ../../,,$(MOD_DEPTH))/ROOT
+endif
+
+PKGARCHIVE = $(dist_libdir)/pkgarchive
+DATAFILES = copyright
+FILES = $(DATAFILES) pkginfo prototype
+
+PACKAGE = $(shell basename `pwd`)
+
+PRODUCT_VERSION = $(shell grep PR_VERSION $(dist_includedir)/prinit.h \
+ | sed -e 's/"$$//' -e 's/.*"//' -e 's/ .*//')
+
+LN = /usr/bin/ln
+
+CLOBBERFILES = $(FILES)
+
+include $(topsrcdir)/config/rules.mk
+
+# vim: ft=make
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.in b/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.in
new file mode 100644
index 00000000..0c2d2e31
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.in
@@ -0,0 +1,60 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: Makefile.in $"
+#
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+%: %.ksh
+ $(RM) $@
+ cp $< $@
+ chmod +x $@
+
+ifeq ($(USE_64), 1)
+DIRS = \
+ SUNWprx
+else
+DIRS = \
+ SUNWpr
+endif
+
+PROTO = \
+ $(ROOT) \
+ $(ROOT)/usr \
+ $(ROOT)/usr/lib \
+ $(ROOT)/usr/lib/mps
+
+ifdef USE_64
+PROTO += $(ROOT)/usr/lib/mps/sparcv9
+endif
+
+include $(srcdir)/Makefile.com
+
+awk_pkginfo: bld_awk_pkginfo
+ ./bld_awk_pkginfo -m $(MACH) -p "$(PRODUCT_VERSION)" -o $@ -v $(PRODUCT_VERSION)
+
+all:: awk_pkginfo $(PROTO)
+publish: awk_pkginfo $(PROTO)
+ +$(LOOP_OVER_DIRS)
+
+clean clobber::
+ $(RM) awk_pkginfo bld_awk_pkginfo
+ $(RM) -r $(ROOT)
+
+$(ROOT) $(ROOT)/%:
+ mkdir -p $@
+
+ifdef USE_64
+$(ROOT)/usr/lib/mps/sparcv9:
+ $(LN) -sf ../../../../$(dist_libdir) $@
+else
+$(ROOT)/usr/lib/mps:
+ $(LN) -sf ../../../$(dist_libdir) $@
+endif
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.targ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.targ
new file mode 100644
index 00000000..9c49cf20
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/Makefile.targ
@@ -0,0 +1,40 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: Makefile.targ $"
+#
+
+pkginfo: pkginfo.tmpl ../awk_pkginfo
+ $(RM) $@; nawk -f ../awk_pkginfo $< > $@
+
+# we need to copy prototype_sparc to current too find copyright in current
+prototype: $(srcdir)/prototype_com $(srcdir)/prototype_$(MACH)
+ cat $(srcdir)/prototype_$(MACH) | sed -e \
+'/^!include[ ][ ]*prototype_com/ r ./prototype_com' \
+-e 's/^!include[ ][ ]*prototype_com//g' >prototype
+
+
+
+pkg: $(PKGARCHIVE) prototype
+ cp $(srcdir)/prototype_com .
+ cp $(srcdir)/prototype_$(MACH) .
+ cp $(srcdir)/depend .
+ pkgmk -f prototype_$(MACH) -d $(PKGARCHIVE) -r $(ROOT) -o $(PACKAGE)
+
+$(PKGARCHIVE):
+ [ -d $(PKGARCHIVE) ] || mkdir -p $(PKGARCHIVE)
+
+$(DATAFILES): %: $(srcdir)/../common_files/%
+ $(RM) $@; cp $(srcdir)/../common_files/$@ $@
+
+#$(MACHDATAFILES): %: $(srcdir)/../common_files/%_$(MACH)
+# $(RM) $@; cp $(srcdir)/../common_files/$@_$(MACH) $@
+#
+#$(MACHDATAFILES): %: $(srcdir)/%_$(MACH)
+# $(RM) $@; cp $(srcdir)/$@_$(MACH) $@
+
+clobber clean::
+ -$(RM) $(CLOBBERFILES) $(CLEANFILES)
+
+.PHONY: pkg
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/Makefile.in b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/Makefile.in
new file mode 100644
index 00000000..ab54db6f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/Makefile.in
@@ -0,0 +1,22 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: Makefile.in $"
+#
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(srcdir)/../Makefile.com
+
+DATAFILES +=
+
+all:: $(FILES)
+publish:: all pkg
+
+include $(srcdir)/../Makefile.targ
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/depend b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/depend
new file mode 100644
index 00000000..57bc554e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/depend
@@ -0,0 +1,27 @@
+# Copyright 2002 Microsystems, Inc. All Rights Reserved.
+# Use is subject to license terms.
+#
+# $Id: depend $
+#
+# This package information file defines software dependencies associated
+# with the pkg. You can define three types of pkg dependencies with this file:
+# P indicates a prerequisite for installation
+# I indicates an incompatible package
+# R indicates a reverse dependency
+# <pkg.abbr> see pkginfo(4), PKG parameter
+# <name> see pkginfo(4), NAME parameter
+# <version> see pkginfo(4), VERSION parameter
+# <arch> see pkginfo(4), ARCH parameter
+# <type> <pkg.abbr> <name>
+# (<arch>)<version>
+# (<arch>)<version>
+# ...
+# <type> <pkg.abbr> <name>
+# ...
+
+P SUNWcar Core Architecture, (Root)
+P SUNWkvm Core Architecture, (Kvm)
+P SUNWcsr Core Solaris, (Root)
+P SUNWcsu Core Solaris, (Usr)
+P SUNWcsd Core Solaris Devices
+P SUNWcsl Core Solaris Libraries
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/pkginfo.tmpl b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/pkginfo.tmpl
new file mode 100644
index 00000000..431ef37a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/pkginfo.tmpl
@@ -0,0 +1,34 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: pkginfo.tmpl $"
+#
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWpr"
+NAME="Netscape Portable Runtime"
+ARCH="ISA"
+VERSION="NSPRVERS,REV=0.0.0"
+SUNW_PRODNAME="Netscape Portable Runtime"
+SUNW_PRODVERS="NSPRVERS"
+SUNW_PKGTYPE="usr"
+MAXINST="1000"
+CATEGORY="system"
+DESC="Netscape Portable Runtime Interface"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+#VSTOCK="<reserved by Release Engineering for package part #>"
+#ISTATES="<developer defined>"
+#RSTATES='<developer defined>'
+#ULIMIT="<developer defined>"
+#ORDER="<developer defined>"
+#PSTAMP="<developer defined>"
+#INTONLY="<developer defined>"
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_com b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_com
new file mode 100644
index 00000000..e92c4e51
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_com
@@ -0,0 +1,31 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: prototype_com $"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i copyright
+i pkginfo
+i depend
+#
+# source locations relative to the prototype file
+#
+# SUNWpr
+#
+d none usr 755 root sys
+d none usr/lib 755 root bin
+d none usr/lib/mps 755 root bin
+f none usr/lib/mps/libnspr4.so 755 root bin
+f none usr/lib/mps/libplc4.so 755 root bin
+f none usr/lib/mps/libplds4.so 755 root bin
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_i386 b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_i386
new file mode 100644
index 00000000..76b92016
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_i386
@@ -0,0 +1,30 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: prototype_i386 $"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+#
+#
+# List files which are i386 specific here
+#
+# source locations relative to the prototype file
+#
+#
+# SUNWpr
+#
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_sparc b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_sparc
new file mode 100644
index 00000000..4da58b01
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWpr/prototype_sparc
@@ -0,0 +1,33 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: prototype_sparc $"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+#
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+#
+# SUNWpr
+#
+d none usr/lib/mps/cpu 755 root bin
+d none usr/lib/mps/cpu/sparcv8plus 755 root bin
+f none usr/lib/mps/cpu/sparcv8plus/libnspr_flt4.so 755 root bin
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/Makefile.in b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/Makefile.in
new file mode 100644
index 00000000..ab54db6f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/Makefile.in
@@ -0,0 +1,22 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: Makefile.in $"
+#
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(srcdir)/../Makefile.com
+
+DATAFILES +=
+
+all:: $(FILES)
+publish:: all pkg
+
+include $(srcdir)/../Makefile.targ
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/depend b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/depend
new file mode 100644
index 00000000..5be1ecd9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/depend
@@ -0,0 +1,30 @@
+# Copyright 2002 Microsystems, Inc. All Rights Reserved.
+# Use is subject to license terms.
+#
+# $Id: depend $
+#
+# This package information file defines software dependencies associated
+# with the pkg. You can define three types of pkg dependencies with this file:
+# P indicates a prerequisite for installation
+# I indicates an incompatible package
+# R indicates a reverse dependency
+# <pkg.abbr> see pkginfo(4), PKG parameter
+# <name> see pkginfo(4), NAME parameter
+# <version> see pkginfo(4), VERSION parameter
+# <arch> see pkginfo(4), ARCH parameter
+# <type> <pkg.abbr> <name>
+# (<arch>)<version>
+# (<arch>)<version>
+# ...
+# <type> <pkg.abbr> <name>
+# ...
+
+P SUNWcar Core Architecture, (Root)
+P SUNWkvm Core Architecture, (Kvm)
+P SUNWcsr Core Solaris, (Root)
+P SUNWcsu Core Solaris, (Usr)
+P SUNWcsd Core Solaris Devices
+P SUNWcsl Core Solaris Libraries
+P SUNWcarx Core Architecture, (Root) (64-bit)
+P SUNWcsxu Core Solaris (Usr) (64-bit)
+P SUNWcslx Core Solaris Libraries (64-bit)
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/pkginfo.tmpl b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/pkginfo.tmpl
new file mode 100644
index 00000000..0b13c5be
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/pkginfo.tmpl
@@ -0,0 +1,35 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: pkginfo.tmpl $"
+#
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWprx"
+NAME="Netscape Portable Runtime (64-bit)"
+ARCH="ISA"
+SUNW_ISA="sparcv9"
+VERSION="NSPRVERS,REV=0.0.0"
+SUNW_PRODNAME="Netscape Portable Runtime"
+SUNW_PRODVERS="NSPRVERS"
+SUNW_PKGTYPE="usr"
+MAXINST="1000"
+CATEGORY="system"
+DESC="Netscape Portable Runtime Interface (64-bit)"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+#VSTOCK="<reserved by Release Engineering for package part #>"
+#ISTATES="<developer defined>"
+#RSTATES='<developer defined>'
+#ULIMIT="<developer defined>"
+#ORDER="<developer defined>"
+#PSTAMP="<developer defined>"
+#INTONLY="<developer defined>"
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_com b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_com
new file mode 100644
index 00000000..700d61ca
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_com
@@ -0,0 +1,28 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: prototype_com $"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+# packaging files
+i copyright
+i pkginfo
+i depend
+#
+# source locations relative to the prototype file
+#
+# SUNWprx
+#
+d none usr 755 root sys
+d none usr/lib 755 root bin
+d none usr/lib/mps 755 root bin
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_sparc b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_sparc
new file mode 100644
index 00000000..cd3da121
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/SUNWprx/prototype_sparc
@@ -0,0 +1,35 @@
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "$Id: prototype_sparc $"
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...> # where to find pkg objects
+#!include <filename> # include another 'prototype' file
+#!default <mode> <owner> <group> # default used if not specified on entry
+#!<param>=<value> # puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+#
+#
+# List files which are SPARC specific here
+#
+# source locations relative to the prototype file
+#
+#
+# SUNWprx
+#
+s none usr/lib/mps/64=sparcv9
+d none usr/lib/mps/sparcv9 755 root bin
+f none usr/lib/mps/sparcv9/libnspr4.so 755 root bin
+f none usr/lib/mps/sparcv9/libplc4.so 755 root bin
+f none usr/lib/mps/sparcv9/libplds4.so 755 root bin
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/bld_awk_pkginfo.ksh b/src/libs/xpcom18a4/nsprpub/pkg/solaris/bld_awk_pkginfo.ksh
new file mode 100755
index 00000000..b01645e4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/bld_awk_pkginfo.ksh
@@ -0,0 +1,105 @@
+#!/usr/bin/ksh -p
+#
+#ident "$Id: bld_awk_pkginfo.ksh $"
+#
+# Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Simple script which builds the awk_pkginfo awk script. This awk script
+# is used to convert the pkginfo.tmpl files into pkginfo files
+# for the build.
+#
+
+usage()
+{
+ cat <<-EOF
+usage: bld_awk_pkginfo -p <prodver> -m <mach> -o <awk_script> [-v <version>]
+EOF
+}
+
+#
+# Awk strings
+#
+# two VERSION patterns: one for Dewey decimal, one for Dewey plus ,REV=n
+# the first has one '=' the second has two or more '='
+#
+VERSION1="VERSION=[^=]*$"
+VERSION2="VERSION=[^=]*=.*$"
+PRODVERS="^SUNW_PRODVERS="
+ARCH='ARCH=\"ISA\"'
+
+#
+# parse command line
+#
+mach=""
+prodver=""
+awk_script=""
+version="NSPRVERS"
+
+while getopts o:p:m:v: c
+do
+ case $c in
+ o)
+ awk_script=$OPTARG
+ ;;
+ m)
+ mach=$OPTARG
+ ;;
+ p)
+ prodver=$OPTARG
+ ;;
+ v)
+ version=$OPTARG
+ ;;
+ \?)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+if [[ ( -z $prodver ) || ( -z $mach ) || ( -z $awk_script ) ]]
+then
+ usage
+ exit 1
+fi
+
+if [[ -f $awk_script ]]
+then
+ rm -f $awk_script
+fi
+
+#
+# Build REV= field based on date
+#
+rev=$(date "+%Y.%m.%d.%H.%M")
+
+#
+# Build awk script which will process all the
+# pkginfo.tmpl files.
+#
+# the first VERSION pattern is replaced with a leading quotation mark
+#
+rm -f $awk_script
+cat << EOF > $awk_script
+/$VERSION1/ {
+ sub(/\=[^=]*$/,"=\"$rev\"")
+ print
+ next
+ }
+/$VERSION2/ {
+ sub(/\=[^=]*$/,"=$rev\"")
+ sub(/NSPRVERS/,"$version")
+ print
+ next
+ }
+/$PRODVERS/ {
+ printf "SUNW_PRODVERS=\"%s\"\n", "$prodver"
+ next
+ }
+/$ARCH/ {
+ printf "ARCH=\"%s\"\n", "$mach"
+ next
+ }
+{ print }
+EOF
diff --git a/src/libs/xpcom18a4/nsprpub/pkg/solaris/common_files/copyright b/src/libs/xpcom18a4/nsprpub/pkg/solaris/common_files/copyright
new file mode 100644
index 00000000..1e0f6ce3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pkg/solaris/common_files/copyright
@@ -0,0 +1,28 @@
+The contents of this package are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this package 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 Portable Runtime (NSPR).
+
+The Initial Developer of the Original Code is Netscape Communications
+Corporation. Portions created by Netscape are Copyright (C) 1998-2000
+Netscape Communications Corporation. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this package 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 package only
+under the terms of the GPL and not to allow others to use your version
+of this package 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 package under either the MPL or
+the GPL.
diff --git a/src/libs/xpcom18a4/nsprpub/pr/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/Makefile.in
new file mode 100644
index 00000000..e060f195
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+DIRS = include src
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/include/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/MANIFEST b/src/libs/xpcom18a4/nsprpub/pr/include/MANIFEST
new file mode 100644
index 00000000..634968ef
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/MANIFEST
@@ -0,0 +1,52 @@
+#
+# This is a list of local files which get copied to the mozilla:dist directory
+#
+
+nspr.h
+pratom.h
+prbit.h
+prclist.h
+prcmon.h
+prcountr.h
+prcvar.h
+prdtoa.h
+prenv.h
+prerr.h
+prerror.h
+prinet.h
+prinit.h
+prinrval.h
+prio.h
+pripcsem.h
+prlink.h
+prlock.h
+prlog.h
+prlong.h
+prmem.h
+prmon.h
+prmwait.h
+prnetdb.h
+prolock.h
+prpdce.h
+prprf.h
+prproces.h
+prrng.h
+prrwlock.h
+prshm.h
+prshma.h
+prsystem.h
+prthread.h
+prtime.h
+prtpool.h
+prtrace.h
+prtypes.h
+prvrsion.h
+prwin16.h
+
+obsolete/protypes.h
+obsolete/prsem.h
+obsolete/probslet.h
+
+private/prpriv.h
+private/pprio.h
+private/pprthred.h
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/include/Makefile.in
new file mode 100644
index 00000000..5dc9686d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/Makefile.in
@@ -0,0 +1,59 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+DIRS = md private obsolete
+
+include $(topsrcdir)/config/config.mk
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(RELEASE_HEADERS)
+ $(INSTALL) -m 444 $(RELEASE_HEADERS) $(dist_includedir)
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/gencfg.c b/src/libs/xpcom18a4/nsprpub/pr/include/gencfg.c
new file mode 100644
index 00000000..e67c1309
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/gencfg.c
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <stdio.h>
+
+#if defined(sgi)
+#ifndef IRIX
+ error - IRIX is not defined
+#endif
+#endif
+
+#if defined(__sun)
+#if defined(__svr4) || defined(__svr4__) || defined(__SVR4)
+#ifndef SOLARIS
+ error - SOLARIS is not defined
+#endif
+#else
+#ifndef SUNOS4
+ error - SUNOS4 is not defined
+#endif
+#endif
+#endif
+
+#if defined(__hpux)
+#ifndef HPUX
+ error - HPUX is not defined
+#endif
+#endif
+
+#if defined(__alpha)
+#if !(defined(_WIN32)) && !(defined(OSF1)) && !(defined(__linux)) && !(defined(__FreeBSD__))
+ error - None of OSF1, _WIN32, __linux, or __FreeBSD__ is defined
+#endif
+#endif
+
+#if defined(_IBMR2)
+#ifndef AIX
+ error - AIX is not defined
+#endif
+#endif
+
+#if defined(linux)
+#ifndef LINUX
+ error - LINUX is not defined
+#endif
+#endif
+
+#if defined(bsdi)
+#ifndef BSDI
+ error - BSDI is not defined
+#endif
+#endif
+
+#if defined(M_UNIX)
+#ifndef SCO
+ error - SCO is not defined
+#endif
+#endif
+#if !defined(M_UNIX) && defined(_USLC_)
+#ifndef UNIXWARE
+ error - UNIXWARE is not defined
+#endif
+#endif
+
+#if defined(__APPLE__)
+#ifndef DARWIN
+ error - DARWIN is not defined
+#endif
+#endif
+
+#if defined(__NeXT__)
+#ifndef NEXTSTEP
+ error - NEXTSTEP is not defined
+#endif
+#endif
+
+/************************************************************************/
+
+/* Generate cpucfg.h */
+
+#ifdef XP_PC
+#ifdef WIN32
+#define INT64 _PRInt64
+#else
+#define INT64 long
+#endif
+#else
+#if defined(HPUX) || defined(NECSVR4) || defined(SCO) || defined(UNIXWARE) || defined (NCR)
+#define INT64 long
+#else
+#define INT64 long long
+#endif
+#endif
+
+struct align_short {
+ char c;
+ short a;
+};
+struct align_int {
+ char c;
+ int a;
+};
+struct align_long {
+ char c;
+ long a;
+};
+struct align_PRInt64 {
+ char c;
+ INT64 a;
+};
+struct align_fakelonglong {
+ char c;
+ struct {
+ long hi, lo;
+ } a;
+};
+struct align_float {
+ char c;
+ float a;
+};
+struct align_double {
+ char c;
+ double a;
+};
+struct align_pointer {
+ char c;
+ void *a;
+};
+
+#define ALIGN_OF(type) \
+ (((char*)&(((struct align_##type *)0)->a)) - ((char*)0))
+
+int bpb;
+
+/* Used if shell doesn't support redirection. By default, assume it does. */
+FILE *stream;
+
+static int Log2(int n)
+{
+ int log2 = 0;
+
+ if (n & (n-1))
+ log2++;
+ if (n >> 16)
+ log2 += 16, n >>= 16;
+ if (n >> 8)
+ log2 += 8, n >>= 8;
+ if (n >> 4)
+ log2 += 4, n >>= 4;
+ if (n >> 2)
+ log2 += 2, n >>= 2;
+ if (n >> 1)
+ log2++;
+ return log2;
+}
+
+/* We assume that int's are 32 bits */
+static void do64(void)
+{
+ union {
+ int i;
+ char c[4];
+ } u;
+
+ u.i = 0x01020304;
+ if (u.c[0] == 0x01) {
+ fprintf(stream, "#undef IS_LITTLE_ENDIAN\n");
+ fprintf(stream, "#define IS_BIG_ENDIAN 1\n\n");
+ } else {
+ fprintf(stream, "#define IS_LITTLE_ENDIAN 1\n");
+ fprintf(stream, "#undef IS_BIG_ENDIAN\n\n");
+ }
+}
+
+static void do32(void)
+{
+ union {
+ long i;
+ char c[4];
+ } u;
+
+ u.i = 0x01020304;
+ if (u.c[0] == 0x01) {
+ fprintf(stream, "#undef IS_LITTLE_ENDIAN\n");
+ fprintf(stream, "#define IS_BIG_ENDIAN 1\n\n");
+ } else {
+ fprintf(stream, "#define IS_LITTLE_ENDIAN 1\n");
+ fprintf(stream, "#undef IS_BIG_ENDIAN\n\n");
+ }
+}
+
+/*
+** Concievably this could actually be used; but there is lots of code out
+** there with and's and shift's in it that assumes a byte is 8 bits, so
+** forget about porting THIS code to those non 8 bit byte machines.
+*/
+static void BitsPerByte(void)
+{
+ bpb = 8;
+}
+
+int main(int argc, char **argv)
+{
+ BitsPerByte();
+
+ /* If we got a command line argument, try to use it as the stream. */
+ ++argv;
+ if(*argv) {
+ if(!(stream = fopen ( *argv, "wt" ))) {
+ fprintf(stderr, "Could not write to output file %s.\n", *argv);
+ return 1;
+ }
+ } else {
+ stream = stdout;
+ }
+
+ fprintf(stream, "#ifndef nspr_cpucfg___\n");
+ fprintf(stream, "#define nspr_cpucfg___\n\n");
+
+ fprintf(stream, "/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
+
+ if (sizeof(long) == 8) {
+ do64();
+ } else {
+ do32();
+ }
+ fprintf(stream, "#define PR_BYTES_PER_BYTE %d\n", sizeof(char));
+ fprintf(stream, "#define PR_BYTES_PER_SHORT %d\n", sizeof(short));
+ fprintf(stream, "#define PR_BYTES_PER_INT %d\n", sizeof(int));
+ fprintf(stream, "#define PR_BYTES_PER_INT64 %d\n", 8);
+ fprintf(stream, "#define PR_BYTES_PER_LONG %d\n", sizeof(long));
+ fprintf(stream, "#define PR_BYTES_PER_FLOAT %d\n", sizeof(float));
+ fprintf(stream, "#define PR_BYTES_PER_DOUBLE %d\n\n", sizeof(double));
+
+ fprintf(stream, "#define PR_BITS_PER_BYTE %d\n", bpb);
+ fprintf(stream, "#define PR_BITS_PER_SHORT %d\n", bpb * sizeof(short));
+ fprintf(stream, "#define PR_BITS_PER_INT %d\n", bpb * sizeof(int));
+ fprintf(stream, "#define PR_BITS_PER_INT64 %d\n", bpb * 8);
+ fprintf(stream, "#define PR_BITS_PER_LONG %d\n", bpb * sizeof(long));
+ fprintf(stream, "#define PR_BITS_PER_FLOAT %d\n", bpb * sizeof(float));
+ fprintf(stream, "#define PR_BITS_PER_DOUBLE %d\n\n",
+ bpb * sizeof(double));
+
+ fprintf(stream, "#define PR_BITS_PER_BYTE_LOG2 %d\n", Log2(bpb));
+ fprintf(stream, "#define PR_BITS_PER_SHORT_LOG2 %d\n",
+ Log2(bpb * sizeof(short)));
+ fprintf(stream, "#define PR_BITS_PER_INT_LOG2 %d\n",
+ Log2(bpb * sizeof(int)));
+ fprintf(stream, "#define PR_BITS_PER_INT64_LOG2 %d\n", 6);
+ fprintf(stream, "#define PR_BITS_PER_LONG_LOG2 %d\n",
+ Log2(bpb * sizeof(long)));
+ fprintf(stream, "#define PR_BITS_PER_FLOAT_LOG2 %d\n",
+ Log2(bpb * sizeof(float)));
+ fprintf(stream, "#define PR_BITS_PER_DOUBLE_LOG2 %d\n\n",
+ Log2(bpb * sizeof(double)));
+
+ fprintf(stream, "#define PR_ALIGN_OF_SHORT %d\n", ALIGN_OF(short));
+ fprintf(stream, "#define PR_ALIGN_OF_INT %d\n", ALIGN_OF(int));
+ fprintf(stream, "#define PR_ALIGN_OF_LONG %d\n", ALIGN_OF(long));
+ if (sizeof(INT64) < 8) {
+ /* this machine doesn't actually support PRInt64's */
+ fprintf(stream, "#define PR_ALIGN_OF_INT64 %d\n",
+ ALIGN_OF(fakelonglong));
+ } else {
+ fprintf(stream, "#define PR_ALIGN_OF_INT64 %d\n", ALIGN_OF(PRInt64));
+ }
+ fprintf(stream, "#define PR_ALIGN_OF_FLOAT %d\n", ALIGN_OF(float));
+ fprintf(stream, "#define PR_ALIGN_OF_DOUBLE %d\n", ALIGN_OF(double));
+ fprintf(stream, "#define PR_ALIGN_OF_POINTER %d\n\n", ALIGN_OF(pointer));
+
+ fprintf(stream, "#endif /* nspr_cpucfg___ */\n");
+ fclose(stream);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/include/md/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/include/md/Makefile.in
new file mode 100644
index 00000000..3f3c08bc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/Makefile.in
@@ -0,0 +1,80 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+CONFIGS = $(wildcard $(srcdir)/*.cfg)
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(MDCPUCFG_H)
+ $(INSTALL) -m 444 $(CONFIGS) $(HEADERS) $(dist_includedir)/md
+ $(INSTALL) -m 444 $(srcdir)/$(MDCPUCFG_H) $(dist_includedir)
+ifeq ($(OS_ARCH),OpenVMS)
+# On OpenVMS mv updates the file's modified time, so we create a hard link.
+ cd $(dist_includedir); \
+ if test ! -f prcpucfg.h; then \
+ dcl set file /enter=prcpucfg.h $(MDCPUCFG_H); \
+ fi
+else
+ mv -f $(dist_includedir)/$(MDCPUCFG_H) $(dist_includedir)/prcpucfg.h
+endif
+
+real_install::
+ $(NSINSTALL) -D $(DESTDIR)$(includedir)/md
+ cp $(srcdir)/$(MDCPUCFG_H) $(DESTDIR)$(includedir)/prcpucfg.h
+ $(NSINSTALL) -t -m 644 $(HEADERS) $(DESTDIR)$(includedir)/md
+
+release:: export
+ @echo "Copying machine-dependent prcpucfg.h"
+ @if test -z "$(BUILD_NUMBER)"; then \
+ echo "BUILD_NUMBER must be defined"; \
+ false; \
+ fi
+ @if test ! -d $(RELEASE_INCLUDE_DIR); then \
+ rm -rf $(RELEASE_INCLUDE_DIR); \
+ $(NSINSTALL) -D $(RELEASE_INCLUDE_DIR);\
+ fi
+ cp $(srcdir)/$(MDCPUCFG_H) $(RELEASE_INCLUDE_DIR)/prcpucfg.h
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix.h
new file mode 100644
index 00000000..855cb247
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix.h
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_aix_defs_h___
+#define nspr_aix_defs_h___
+
+#include <sys/types.h>
+#if defined(_PR_PTHREADS) || defined(PTHREADS_USER)
+#include <pthread.h>
+#endif
+
+/*
+ * To pick up fd_set and the poll events.
+ */
+#include <sys/select.h>
+#include <sys/poll.h>
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "aix"
+#define _PR_SI_SYSNAME "AIX"
+#define _PR_SI_ARCHITECTURE "rs6000"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE (2*65536L)
+#define _MD_MINIMUM_STACK_SIZE (2*65536L)
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#define NEED_TIME_R
+#undef HAVE_STACK_GROWING_UP
+#undef HAVE_WEAK_IO_SYMBOLS
+#undef HAVE_WEAK_MALLOC_SYMBOLS
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#ifdef _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
+#endif
+#define _PR_HAVE_SYSV_SEMAPHORES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+#define _PR_ACCEPT_INHERIT_NONBLOCK
+
+/* Timer operations */
+#if defined(AIX_TIMERS)
+extern PRIntervalTime _MD_AixGetInterval(void);
+#define _MD_GET_INTERVAL _MD_AixGetInterval
+
+extern PRIntervalTime _MD_AixIntervalPerSec(void);
+#define _MD_INTERVAL_PER_SEC _MD_AixIntervalPerSec
+
+#else /* defined(AIX_TIMERS) */
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#endif /* defined(AIX_TIMERS) */
+
+#ifdef AIX_HAVE_ATOMIC_OP_H
+/* The atomic operations */
+#include <sys/atomic_op.h>
+#define _PR_HAVE_ATOMIC_OPS
+#ifndef IS_64
+#define _PR_HAVE_ATOMIC_CAS
+#endif
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(val) ((PRInt32)fetch_and_add((atomic_p)val, 1) + 1)
+#define _MD_ATOMIC_ADD(ptr, val) ((PRInt32)fetch_and_add((atomic_p)ptr, val) + val)
+#define _MD_ATOMIC_DECREMENT(val) ((PRInt32)fetch_and_add((atomic_p)val, -1) - 1)
+#define _MD_ATOMIC_SET(val, newval) _AIX_AtomicSet(val, newval)
+#endif /* AIX_HAVE_ATOMIC_OP_H */
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _MD_GET_SP(_t) (_t)->md.jb[3]
+#define _MD_SET_THR_SP(_t, _sp) ((_t)->md.jb[3] = (int) (_sp - 2 * 64))
+#define PR_NUM_GCREGS _JBLEN
+
+#define CONTEXT(_th) ((_th)->md.jb)
+#define SAVE_CONTEXT(_th) _setjmp(CONTEXT(_th))
+#define GOTO_CONTEXT(_th) _longjmp(CONTEXT(_th), 1)
+
+#ifdef PTHREADS_USER
+#include "_nspr_pthread.h"
+#else
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ (*_main)(); \
+ } \
+ _MD_GET_SP(_thread) = (int) (_sp - 2 * 64); \
+ PR_END_MACRO
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ jmp_buf jb;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#if !defined(_PR_PTHREADS)
+#define _MD_INIT_LOCKS()
+#endif
+
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+#endif /* PTHREADS_USER */
+
+#ifdef AIX_RENAME_SELECT
+#define _MD_SELECT select
+#define _MD_POLL poll
+#endif
+
+extern void _MD_aix_map_sendfile_error(int err);
+
+#endif /* nspr_aix_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix32.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix32.cfg
new file mode 100644
index 00000000..1949862a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix32.cfg
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef AIX
+#define AIX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+/* used by protypes.h only */
+#define _PR_AIX_HAVE_BSD_INT_TYPES
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix64.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix64.cfg
new file mode 100644
index 00000000..e2c9dc42
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_aix64.cfg
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef AIX
+#define AIX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 8
+
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+/* used by protypes.h only */
+#define _PR_AIX_HAVE_BSD_INT_TYPES
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.cfg
new file mode 100644
index 00000000..d15cf044
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.cfg
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-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.
+ */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_BEOS
+#define XP_BEOS
+#undef XP_UNIX
+#endif
+
+#ifndef BEOS
+#define BEOS
+#endif
+
+#define PR_AF_INET6 5 /* same as AF_INET6 */
+
+#ifdef __powerpc__
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#else
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#endif
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define HAVE_LONG_LONG
+/*
+ * XXX These two macros need to be investigated for different architectures.
+ */
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.h
new file mode 100644
index 00000000..40fa86d7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_beos.h
@@ -0,0 +1,612 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_beos_defs_h___
+#define nspr_beos_defs_h___
+
+#include "prtypes.h"
+#include "prio.h"
+#include "prthread.h"
+#include "prproces.h"
+#include "prmem.h"
+#include "obsolete/prsem.h"
+#include <errno.h>
+
+#include <support/SupportDefs.h>
+#include <kernel/OS.h>
+#include <dirent.h>
+
+/*
+ * Internal configuration macros
+ */
+
+#ifdef BONE_VERSION
+#define _PR_HAVE_SOCKADDR_LEN
+#endif
+
+#define PR_LINKER_ARCH "beos"
+#define _PR_SI_SYSNAME "BEOS"
+#ifdef __powerpc__
+#define _PR_SI_ARCHITECTURE "ppc"
+#else
+#define _PR_SI_ARCHITECTURE "x86"
+#endif
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define _PR_NO_CLOCK_TIMER
+
+/*
+ * The Atomic operations
+ */
+
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC _MD_AtomicInit
+#define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement
+#define _MD_ATOMIC_ADD _MD_AtomicAdd
+#define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement
+#define _MD_ATOMIC_SET _MD_AtomicSet
+
+#define HAVE_CVAR_BUILT_ON_SEM
+#define _PR_GLOBAL_THREADS_ONLY
+#define _PR_BTHREADS
+#define _PR_NEED_FAKE_POLL
+#define _PR_HAVE_PEEK_BUFFER
+#define _PR_PEEK_BUFFER_MAX (16 * 1024)
+#define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) 1
+#define _PR_CONNECT_DOES_NOT_BIND
+
+/* Define threading functions and objects as native BeOS */
+struct _MDThread {
+ thread_id tid; /* BeOS thread handle */
+ sem_id joinSem; /* sems used to synchronzie joining */
+ PRBool is_joining; /* TRUE if someone is currently waiting to
+ join this thread */
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+/*
+ * Lock and Semaphore related definitions
+ */
+
+struct _MDLock {
+ sem_id semaphoreID;
+ int32 benaphoreCount;
+};
+
+struct _MDCVar {
+ sem_id sem1;
+ sem_id sem2;
+ int16 count;
+};
+
+struct _MDSemaphore {
+ sem_id sid;
+};
+
+/*
+** CPU-related definitions
+*/
+struct _MDCPU {
+ int8 unused;
+};
+
+/*
+** Process-related definitions
+*/
+struct _MDProcess {
+ pid_t pid;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+** File- and directory-related definitions
+*/
+
+#ifndef BONE_VERSION
+#define BE_SOCK_SHUTDOWN_READ 0x01
+#define BE_SOCK_SHUTDOWN_WRITE 0x02
+#endif
+
+struct _MDFileDesc {
+ PRInt32 osfd;
+ PRInt32 sock_state;
+ PRBool accepted_socket;
+ PRNetAddr peer_addr;
+#ifndef BONE_VERSION
+ PRBool connectValueValid;
+ int connectReturnValue;
+ int connectReturnError;
+#endif
+};
+
+struct _MDDir {
+ DIR *d;
+};
+
+#define PR_DIRECTORY_SEPARATOR '/'
+#define PR_DIRECTORY_SEPARATOR_STR "/"
+#define PR_PATH_SEPARATOR ':'
+#define PR_PATH_SEPARATOR_STR ":"
+
+#define GETTIMEOFDAY(tp) gettimeofday((tp), NULL)
+
+/* --- Memory-mapped files stuff --- not implemented on BeOS */
+
+struct _MDFileMap {
+ PRInt8 unused;
+};
+
+/*
+ * Network related definitions.
+ */
+
+#ifndef BONE_VERSION
+#define IPPROTO_IP 0
+#define AF_UNIX 2
+#define TCP_NODELAY SO_NONBLOCK
+#define SO_LINGER -1
+#define SO_ERROR 4
+#endif
+
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+
+#ifndef BONE_VERSION
+/* these aren't actually used. if they are, we're screwed */
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+struct protoent* getprotobyname(const char* name);
+struct protoent* getprotobynumber(int number);
+#endif
+
+/*
+ * malloc() related definitions.
+ */
+
+#undef _PR_OVERRIDE_MALLOC
+
+/* Miscellaneous */
+
+#define _MD_ERRNO() (errno)
+
+#define _MD_CLEANUP_BEFORE_EXIT _MD_cleanup_before_exit
+#define _MD_EXIT _MD_exit
+
+#define _MD_GET_ENV getenv
+#define _MD_PUT_ENV putenv
+
+#define _MD_EARLY_INIT _MD_early_init
+#define _MD_FINAL_INIT _MD_final_init
+
+/* CPU Stuff */
+
+#define _MD_INIT_CPUS _MD_init_cpus
+#define _MD_WAKEUP_CPUS _MD_wakeup_cpus
+#define _MD_START_INTERRUPTS _MD_start_interrupts
+#define _MD_STOP_INTERRUPTS _MD_stop_interrupts
+#define _MD_DISABLE_CLOCK_INTERRUPTS _MD_disable_clock_interrupts
+#define _MD_BLOCK_CLOCK_INTERRUPTS _MD_block_clock_interrupts
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS _MD_unblock_clock_interrupts
+#define _MD_CLOCK_INTERRUPT _MD_clock_interrupt
+#define _MD_INIT_STACK _MD_init_stack
+#define _MD_CLEAR_STACK _MD_clear_stack
+// #define _MD_GET_INTSOFF _MD_get_intsoff
+// #define _MD_SET_INTSOFF _MD_set_intsoff
+#define _MD_CURRENT_CPU _MD_current_cpu
+#define _MD_SET_CURRENT_CPU _MD_set_current_cpu
+#define _MD_INIT_RUNNING_CPU _MD_init_running_cpu
+#define _MD_PAUSE_CPU _MD_pause_cpu
+
+/* Thread stuff */
+
+#define _MD_CURRENT_THREAD() PR_GetCurrentThread()
+// #define _MD_GET_ATTACHED_THREAD _MD_get_attached_thread
+#define _MD_LAST_THREAD _MD_last_thread
+#define _MD_SET_CURRENT_THREAD _MD_set_current_THREAD
+#define _MD_SET_LAST_THREAD _MD_set_last_thread
+#define _MD_INIT_THREAD _MD_init_thread
+#define _MD_EXIT_THREAD _MD_exit_thread
+#define _MD_INIT_ATTACHED_THREAD _MD_init_attached_thread
+
+#define _MD_SUSPEND_THREAD _MD_suspend_thread
+#define _MD_RESUME_THREAD _MD_resume_thread
+#define _MD_SUSPEND_CPU _MD_suspend_cpu
+#define _MD_RESUME_CPU _MD_resume_cpu
+#define _MD_BEGIN_SUSPEND_ALL _MD_begin_suspend_all
+#define _MD_END_SUSPEND_ALL _MD_end_suspend_all
+#define _MD_BEGIN_RESUME_ALL _MD_begin_resume_all
+#define _MD_END_RESUME_ALL _MD_end_resume_all
+
+#define _MD_GET_SP _MD_get_sp
+
+#define _MD_CLEAN_THREAD _MD_clean_thread
+#define _MD_CREATE_PRIMORDIAL_USER_THREAD _MD_create_primordial_user_thread
+#define _MD_CREATE_USER_THREAD _MD_create_user_thread
+#define _MD_INIT_PRIMORDIAL_THREAD _MD_init_primordial_thread
+#define _MD_CREATE_THREAD _MD_create_thread
+#define _MD_YIELD _MD_yield
+#define _MD_SET_PRIORITY _MD_set_priority
+
+#define _MD_SUSPENDALL _MD_suspendall
+#define _MD_RESUMEALL _MD_resumeall
+
+#define _MD_SWITCH_CONTEXT _MD_switch_context
+#define _MD_RESTORE_CONTEXT _MD_restore_context
+
+#define _MD_WAIT _MD_wait
+#define _MD_WAKEUP_WAITER _MD_wakeup_waiter
+
+#define _MD_SETTHREADAFFINITYMASK _MD_setthreadaffinitymask
+#define _MD_GETTHREADAFFINITYMASK _MD_getthreadaffinitymask
+
+/* Thread Synchronization */
+
+#define _MD_INIT_LOCKS _MD_init_locks
+#define _MD_NEW_LOCK _MD_new_lock
+#define _MD_FREE_LOCK _MD_free_lock
+#define _MD_LOCK _MD_lock
+#define _MD_TEST_AND_LOCK _MD_test_and_lock
+#define _MD_UNLOCK _MD_unlock
+#define _MD_IOQ_LOCK _MD_ioq_lock
+#define _MD_IOQ_UNLOCK _MD_ioq_unlock
+#define _MD_NEW_SEM _MD_new_sem
+#define _MD_DESTROY_SEM _MD_destroy_sem
+#define _MD_TIMED_WAIT_SEM _MD_timed_wait_sem
+#define _MD_WAIT_SEM _MD_wait_sem
+#define _MD_POST_SEM _MD_post_sem
+// #define _MD_NEW_CV _MD_new_cv
+// #define _MD_FREE_CV _MD_free_cv
+// #define _MD_WAIT_CV _MD_wait_cv
+// #define _MD_NOTIFY_CV _MD_notify_cv
+// #define _MD_NOTIFYALL_CV _MD_notifyall_cv
+
+/* File I/O */
+
+/* don't need any I/O initializations */
+#define _MD_INIT_IO()
+#define _MD_INIT_FILEDESC(fd)
+
+#define _MD_OPEN_DIR _MD_open_dir
+#define _MD_READ_DIR _MD_read_dir
+#define _MD_CLOSE_DIR _MD_close_dir
+#define _MD_MAKE_NONBLOCK _MD_make_nonblock
+#define _MD_SET_FD_INHERITABLE _MD_set_fd_inheritable
+#define _MD_INIT_FD_INHERITABLE _MD_init_fd_inheritable
+#define _MD_QUERY_FD_INHERITABLE _MD_query_fd_inheritable
+#define _MD_OPEN _MD_open
+#define _MD_OPEN_FILE _MD_open
+#define _MD_CLOSE_FILE _MD_close_file
+#define _MD_READ _MD_read
+#define _MD_WRITE _MD_write
+#define _MD_WRITEV _MD_writev
+#define _MD_LSEEK _MD_lseek
+#define _MD_LSEEK64 _MD_lseek64
+#define _MD_FSYNC _MD_fsync
+#define _MD_DELETE _MD_delete
+#define _MD_GETFILEINFO _MD_getfileinfo
+#define _MD_GETFILEINFO64 _MD_getfileinfo64
+#define _MD_GETOPENFILEINFO _MD_getopenfileinfo
+#define _MD_GETOPENFILEINFO64 _MD_getopenfileinfo64
+#define _MD_RENAME _MD_rename
+#define _MD_ACCESS _MD_access
+#define _MD_STAT stat
+#define _MD_MKDIR _MD_mkdir
+#define _MD_MAKE_DIR _MD_mkdir
+#define _MD_RMDIR _MD_rmdir
+#define _MD_PR_POLL _MD_pr_poll
+
+/* Network I/O */
+
+#define _MD_CLOSE_SOCKET _MD_close_socket
+#define _MD_CONNECT _MD_connect
+#define _MD_ACCEPT _MD_accept
+#define _MD_BIND _MD_bind
+#define _MD_LISTEN _MD_listen
+#define _MD_SHUTDOWN _MD_shutdown
+#define _MD_RECV _MD_recv
+#define _MD_SEND _MD_send
+#define _MD_ACCEPT_READ _MD_accept_read
+#define _MD_GETSOCKNAME _MD_getsockname
+#define _MD_GETPEERNAME _MD_getpeername
+#define _MD_GETSOCKOPT _MD_getsockopt
+#define _MD_SETSOCKOPT _MD_setsockopt
+#define _MD_RECVFROM _MD_recvfrom
+#define _MD_SENDTO _MD_sendto
+#define _MD_SOCKETPAIR _MD_socketpair
+#define _MD_SOCKET _MD_socket
+#define _MD_SOCKETAVAILABLE _MD_socketavailable
+#define _MD_PIPEAVAILABLE _MD_socketavailable
+
+#define _MD_GET_SOCKET_ERROR() (errno)
+#define _MD_GETHOSTNAME _MD_gethostname
+
+#define _MD_SELECT select
+
+/* Process management */
+
+#define _MD_CREATE_PROCESS _MD_create_process
+#define _MD_DETACH_PROCESS _MD_detach_process
+#define _MD_WAIT_PROCESS _MD_wait_process
+#define _MD_KILL_PROCESS _MD_kill_process
+
+/* Atomic data operations */
+
+// #define _MD_INIT_ATOMIC _MD_init_atomic
+// #define _MD_ATOMIC_INCREMENT _MD_atomic_increment
+// #define _MD_ATOMIC_DECREMENT _MD_atomic_decrement
+// #define _MD_ATOMIC_SET _MD_atomic_set
+
+/* memory management */
+
+#define _MD_INIT_SEGS _MD_init_segs
+#define _MD_ALLOC_SEGMENT _MD_alloc_segment
+#define _MD_FREE_SEGMENT _MD_free_segment
+
+/* Memory mapped file I/O */
+
+#define _MD_CREATE_FILE_MAP _MD_create_file_map
+#define _MD_GET_MEM_MAP_ALIGNMENT _MD_get_mem_map_alignment
+#define _MD_MEM_MAP _MD_mem_map
+#define _MD_MEM_UNMAP _MD_mem_unmap
+#define _MD_CLOSE_FILE_MAP _MD_close_file_map
+
+/* Time related */
+
+#define _MD_NOW _MD_now
+#define _MD_INTERVAL_INIT _MD_interval_init
+#define _MD_GET_INTERVAL _MD_get_interval
+#define _MD_INTERVAL_PER_SEC _MD_interval_per_sec
+
+/* File locking */
+
+#define _MD_LOCKFILE _MD_lockfile
+#define _MD_TLOCKFILE _MD_tlockfile
+#define _MD_UNLOCKFILE _MD_unlockfile
+
+/**
+ * Prototypes for machine dependent function implementations. (Too bad
+ * NSPR's MD system blows so much that we have to reiterate every stinking
+ * thing we implement here in our MD header file.)
+ */
+
+/* Miscellaneous */
+
+NSPR_API(void) _MD_cleanup_before_exit(void);
+NSPR_API(void) _MD_exit(PRIntn status);
+
+NSPR_API(char*) _MD_get_env(const char *name);
+NSPR_API(PRIntn) _MD_put_env(const char *name);
+
+NSPR_API(void) _MD_early_init(void);
+NSPR_API(void) _MD_final_init(void);
+
+/* CPU Stuff */
+
+NSPR_API(void) _MD_init_cpus();
+NSPR_API(void) _MD_wakeup_cpus();
+NSPR_API(void) _MD_start_interrupts(void);
+NSPR_API(void) _MD_stop_interrupts(void);
+NSPR_API(void) _MD_disable_clock_interrupts(void);
+NSPR_API(void) _MD_block_clock_interrupts(void);
+NSPR_API(void) _MD_unblock_clock_interrupts(void);
+NSPR_API(void) _MD_clock_interrupt(void);
+// NSPR_API(void) _MD_init_stack(PRThreadStack *ts, PRIntn redzone);
+// NSPR_API(void) _MD_clear_stack(PRThreadStack* ts);
+// NSPR_API(PRInt32) _MD_get_intsoff(void);
+// NSPR_API(void) _MD_set_intsoff(PRInt32 _val);
+// NSPR_API(_PRCPU*) _MD_current_cpu(void);
+// NSPR_API(void) _MD_set_current_cpu(_PRCPU *cpu);
+// NSPR_API(void) _MD_init_running_cpu(_PRCPU *cpu);
+NSPR_API(PRInt32) _MD_pause_cpu(PRIntervalTime timeout);
+
+/* Thread stuff */
+
+// NSPR_API(PRThread*) _MD_current_thread(void);
+NSPR_API(PRThread*) _MD_get_attached_thread(void);
+NSPR_API(PRThread*) _MD_last_thread(void);
+NSPR_API(void) _MD_set_current_thread(PRThread *thread);
+NSPR_API(void) _MD_set_last_thread(PRThread *thread);
+NSPR_API(PRStatus) _MD_init_thread(PRThread *thread);
+NSPR_API(void) _MD_exit_thread(PRThread *thread);
+NSPR_API(PRStatus) _MD_init_attached_thread(PRThread *thread);
+
+NSPR_API(void) _MD_suspend_thread(PRThread *thread);
+NSPR_API(void) _MD_resume_thread(PRThread *thread);
+// NSPR_API(void) _MD_suspend_cpu(_PRCPU *cpu);
+// NSPR_API(void) _MD_resume_cpu(_PRCPU *cpu);
+NSPR_API(void) _MD_begin_suspend_all(void);
+NSPR_API(void) _MD_end_suspend_all(void);
+NSPR_API(void) _MD_begin_resume_all(void);
+NSPR_API(void) _MD_end_resume_all(void);
+
+NSPR_API(void *) _MD_get_sp(PRThread *thread);
+
+NSPR_API(void) _MD_clean_thread(PRThread *thread);
+NSPR_API(void) _MD_create_primordial_user_thread(PRThread *);
+NSPR_API(PRThread*) _MD_create_user_thread(PRUint32 stacksize, void (*start)(void *), void *arg);
+NSPR_API(void) _MD_init_primordial_thread(PRThread *thread);
+NSPR_API(PRStatus) _MD_create_thread(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize);
+NSPR_API(void) _MD_yield(void);
+NSPR_API(void) _MD_set_priority(struct _MDThread *md, PRThreadPriority newPri);
+
+NSPR_API(void) _MD_suspendall(void);
+NSPR_API(void) _MD_resumeall(void);
+
+NSPR_API(void) _MD_init_context(PRThread *thread, char *top, void (*start) (void), PRBool *status);
+NSPR_API(void) _MD_switch_context(PRThread *thread);
+NSPR_API(void) _MD_restore_context(PRThread *thread);
+
+NSPR_API(PRStatus) _MD_wait(PRThread *, PRIntervalTime timeout);
+NSPR_API(PRStatus) _MD_wakeup_waiter(PRThread *);
+
+NSPR_API(PRInt32) _MD_setthreadaffinitymask(PRThread *thread, PRUint32 mask );
+NSPR_API(PRInt32) _MD_getthreadaffinitymask(PRThread *thread, PRUint32 *mask);
+
+/* Thread Synchronization */
+
+NSPR_API(void) _MD_init_locks(void);
+NSPR_API(PRStatus) _MD_new_lock(struct _MDLock *md);
+NSPR_API(void) _MD_free_lock(struct _MDLock *md);
+NSPR_API(void) _MD_lock(struct _MDLock *md);
+NSPR_API(PRIntn) _MD_test_and_lock(struct _MDLock *md);
+NSPR_API(void) _MD_unlock(struct _MDLock *md);
+NSPR_API(void) _MD_ioq_lock(void);
+NSPR_API(void) _MD_ioq_unlock(void);
+NSPR_API(void) _MD_new_sem(struct _MDSemaphore *md, PRUintn value);
+NSPR_API(void) _MD_destroy_sem(struct _MDSemaphore *md);
+NSPR_API(PRStatus) _MD_timed_wait_sem(struct _MDSemaphore *md, PRIntervalTime timeout);
+NSPR_API(PRStatus) _MD_wait_sem(struct _MDSemaphore *md);
+NSPR_API(void) _MD_post_sem(struct _MDSemaphore *md);
+// NSPR_API(PRInt32) _MD_new_cv(struct _MDCVar *md);
+// NSPR_API(void) _MD_free_cv(struct _MDCVar *md);
+// NSPR_API(void) _MD_wait_cv(struct _MDCVar *mdCVar, struct _MDLock *mdLock, PRIntervalTime timeout);
+// NSPR_API(void) _MD_notify_cv(struct _MDCVar *md, struct _MDLock *lock);
+// NSPR_API(void) _MD_notifyall_cv(struct _MDCVar *md, struct _MDLock *lock);
+
+/* File I/O */
+
+// NSPR_API(void) _MD_init_io(void);
+NSPR_API(PRStatus) _MD_open_dir(struct _MDDir *md,const char *name);
+NSPR_API(char *) _MD_read_dir(struct _MDDir *md, PRIntn flags);
+NSPR_API(PRInt32) _MD_close_dir(struct _MDDir *md);
+NSPR_API(void) _MD_make_nonblock(PRFileDesc *fd);
+NSPR_API(void) _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported);
+NSPR_API(void) _MD_query_fd_inheritable(PRFileDesc *fd);
+NSPR_API(PRInt32) _MD_open(const char *name, PRIntn osflags, PRIntn mode);
+NSPR_API(PRInt32) _MD_close_file(PRInt32 osfd);
+NSPR_API(PRInt32) _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount);
+NSPR_API(PRInt32) _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount);
+NSPR_API(PRInt32) _MD_writev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_lseek(PRFileDesc *fd, PRInt32 offset, int whence);
+NSPR_API(PRInt64) _MD_lseek64(PRFileDesc *fd, PRInt64 offset, int whence);
+NSPR_API(PRInt32) _MD_fsync(PRFileDesc *fd);
+NSPR_API(PRInt32) _MD_delete(const char *name);
+NSPR_API(PRInt32) _MD_getfileinfo(const char *fn, PRFileInfo *info);
+NSPR_API(PRInt32) _MD_getfileinfo64(const char *fn, PRFileInfo64 *info);
+NSPR_API(PRInt32) _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info);
+NSPR_API(PRInt32) _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info);
+NSPR_API(PRInt32) _MD_rename(const char *from, const char *to);
+NSPR_API(PRInt32) _MD_access(const char *name, PRIntn how);
+NSPR_API(PRInt32) _MD_stat(const char *name, struct stat *buf);
+NSPR_API(PRInt32) _MD_mkdir(const char *name, PRIntn mode);
+NSPR_API(PRInt32) _MD_rmdir(const char *name);
+NSPR_API(PRInt32) _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout);
+
+/* Network I/O */
+NSPR_API(PRInt32) _MD_close_socket(PRInt32 osfd);
+NSPR_API(PRInt32) _MD_connect(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen);
+NSPR_API(PRInt32) _MD_listen(PRFileDesc *fd, PRIntn backlog);
+NSPR_API(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how);
+NSPR_API(PRInt32) _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_accept_read(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout);
+// NSPR_API(PRInt32) _MD_fast_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg);
+// NSPR_API(PRInt32) _MD_fast_accept_read(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg);
+// NSPR_API(void) _MD_update_accept_context(PRInt32 s, PRInt32 ls);
+NSPR_API(PRStatus) _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen);
+NSPR_API(PRStatus) _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen);
+NSPR_API(PRStatus) _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen);
+NSPR_API(PRStatus) _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen);
+NSPR_API(PRInt32) _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout);
+NSPR_API(PRInt32) _MD_socketpair(int af, int type, int flags, PRInt32 *osfd);
+NSPR_API(PRInt32) _MD_socket(int af, int type, int flags);
+NSPR_API(PRInt32) _MD_socketavailable(PRFileDesc *fd);
+
+// NSPR_API(PRInt32) _MD_get_socket_error(void);
+NSPR_API(PRStatus) _MD_gethostname(char *name, PRUint32 namelen);
+
+/* Process management */
+
+NSPR_API(PRProcess *) _MD_create_process(const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr);
+NSPR_API(PRStatus) _MD_detach_process(PRProcess *process);
+NSPR_API(PRStatus) _MD_wait_process(PRProcess *process, PRInt32 *exitCode);
+NSPR_API(PRStatus) _MD_kill_process(PRProcess *process);
+
+/* Atomic data operations */
+
+// NSPR_API(void) _MD_init_atomic(void);
+// NSPR_API(PRInt32) _MD_atomic_increment(PRInt32 *);
+// NSPR_API(PRInt32) _MD_atomic_decrement(PRInt32 *);
+// NSPR_API(PRInt32) _MD_atomic_set(PRInt32 *, PRInt32);
+
+/* Memory management */
+
+NSPR_API(void) _MD_init_segs(void);
+NSPR_API(PRStatus) _MD_alloc_segment(PRSegment *seg, PRUint32 size, void *vaddr);
+NSPR_API(void) _MD_free_segment(PRSegment *seg);
+
+/* Memory mapped file I/O */
+
+NSPR_API(PRStatus) _MD_create_file_map(PRFileMap *fmap, PRInt64 size);
+NSPR_API(PRInt32) _MD_get_mem_map_alignment(void);
+NSPR_API(void *) _MD_mem_map(PRFileMap *fmap, PRInt64 offset, PRUint32 len);
+NSPR_API(PRStatus) _MD_mem_unmap(void *addr, PRUint32 size);
+NSPR_API(PRStatus) _MD_close_file_map(PRFileMap *fmap);
+
+/* Time related */
+
+NSPR_API(PRTime) _MD_now(void);
+NSPR_API(void) _MD_interval_init(void);
+NSPR_API(PRIntervalTime) _MD_get_interval(void);
+NSPR_API(PRIntervalTime) _MD_interval_per_sec(void);
+
+/* File locking */
+
+NSPR_API(PRStatus) _MD_lockfile(PRInt32 osfd);
+NSPR_API(PRStatus) _MD_tlockfile(PRInt32 osfd);
+NSPR_API(PRStatus) _MD_unlockfile(PRInt32 osfd);
+
+#endif /* _nspr_beos_defs_h___*/
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.cfg
new file mode 100644
index 00000000..843f35f6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.cfg
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef BSDI
+#define BSDI
+#endif
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#if defined(__i386__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__sparc__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#else
+
+#error "Unknown CPU architecture"
+
+#endif
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.h
new file mode 100644
index 00000000..b59c9b0f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_bsdi.h
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_bsdi_defs_h___
+#define nspr_bsdi_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#include <sys/param.h> /* for _BSDI_VERSION */
+
+#define PR_LINKER_ARCH "bsdi"
+#define _PR_SI_SYSNAME "BSDI"
+#if defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#else
+#error "Unknown CPU architecture"
+#endif
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#define HAVE_BSD_FLOCK
+#define NEED_TIME_R
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_NO_LARGE_FILES
+
+#define USE_SETJMP
+
+/* BSD/OS 4.3 and newer all have IPv6 support */
+#if _BSDI_VERSION >= 200105
+#define _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETIPNODEBYNAME
+#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#endif
+
+#ifndef _PR_PTHREADS
+
+#include <setjmp.h>
+
+#if defined(_PR_BSDI_JMPBUF_IS_ARRAY)
+#define _MD_GET_SP(_t) (_t)->md.context[2]
+#elif defined(_PR_BSDI_JMPBUF_IS_STRUCT)
+#define _MD_GET_SP(_t) (_t)->md.context[0].jb_esp
+#else
+#error "Unknown BSDI jmp_buf type"
+#endif
+
+#define PR_NUM_GCREGS _JBLEN
+#define PR_CONTEXT_TYPE jmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (int) (_sp - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+#endif /* ! _PR_PTHREADS */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+
+#include <sys/syscall.h>
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#endif /* nspr_bsdi_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg
new file mode 100644
index 00000000..b2965802
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.cfg
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef DARWIN /*bird*/
+#define DARWIN /*bird*/
+#endif /*bird*/
+
+#define PR_AF_INET6 30 /* same as AF_INET6 */
+
+#if defined(i386) || defined(__i386__) || defined(__amd64__) || defined(__arm64__) || defined(__arm__)
+#undef IS_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#else
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#endif
+
+#define HAVE_LONG_LONG
+#if defined(__amd64__)
+#define HAVE_ALIGNED_DOUBLES
+#else
+#undef HAVE_ALIGNED_DOUBLES
+#endif
+#define HAVE_ALIGNED_LONGLONGS 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#if defined(__amd64__)
+#define PR_BYTES_PER_LONG 8
+#else
+#define PR_BYTES_PER_LONG 4
+#endif
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#if defined(__amd64__)
+#define PR_BITS_PER_LONG 64
+#else
+#define PR_BITS_PER_LONG 32
+#endif
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#if defined(__amd64__)
+#define PR_BITS_PER_LONG_LOG2 6
+#else
+#define PR_BITS_PER_LONG_LOG2 5
+#endif
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#if defined(__amd64__)
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 8
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#else
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+#endif
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h
new file mode 100644
index 00000000..0640a924
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_darwin.h
@@ -0,0 +1,306 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_darwin_defs_h___
+#define nspr_darwin_defs_h___
+
+#include "prthread.h"
+
+#include <sys/syscall.h>
+
+#ifdef XP_MACOSX
+#include <AvailabilityMacros.h>
+#endif
+
+#define PR_LINKER_ARCH "darwin"
+#define _PR_SI_SYSNAME "DARWIN"
+#ifdef __i386__
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__ppc__)
+#define _PR_SI_ARCHITECTURE "ppc"
+#elif defined(__amd64__)
+#define _PR_SI_ARCHITECTURE "amd64"
+#elif defined(__arm__)
+#define _PR_SI_ARCHITECTURE "arm"
+#elif defined(__arm64__)
+#define _PR_SI_ARCHITECTURE "arm64"
+#else
+#error "unknown architecture."
+#endif
+#define PR_DLL_SUFFIX ".dylib"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_MACH_DYLD
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_HAVE_LARGE_OFF_T
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 /* Mac OS X 10.6 has poll(). */
+# if 0 /* ... but we don't use it because it performs worse on Mt. Lion - WEIRD! */
+# define _PR_POLL_AVAILABLE 1
+# define _PR_USE_POLL 1
+# endif
+#endif
+
+#define _PR_INET6
+/*
+ * I'd prefer to use getipnodebyname and getipnodebyaddr but the
+ * getipnodebyname(3) man page on Mac OS X 10.2 says they are not
+ * thread-safe. AI_V4MAPPED|AI_ADDRCONFIG doesn't work either.
+ */
+#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
+/*
+ * On Mac OS X 10.2, gethostbyaddr fails with h_errno=NO_RECOVERY
+ * if you pass an IPv4-mapped IPv6 address to it.
+ */
+#define _PR_GHBA_DISALLOW_V4MAPPED
+#ifdef XP_MACOSX
+#if !defined(MAC_OS_X_VERSION_10_3) || \
+ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3
+/*
+ * socket(AF_INET6) fails with EPROTONOSUPPORT on Mac OS X 10.1.
+ * IPv6 under OS X 10.2 and below is not complete (see bug 222031).
+ */
+#define _PR_INET6_PROBE
+#endif /* DT < 10.3 */
+#if defined(MAC_OS_X_VERSION_10_2) && \
+ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+/* Mac OS X 10.2 has inet_ntop and inet_pton. */
+#define _PR_HAVE_INET_NTOP
+#endif /* DT >= 10.2 */
+#endif /* XP_MACOSX */
+#define _PR_IPV6_V6ONLY_PROBE
+/* The IPV6_V6ONLY socket option is not defined on Mac OS X 10.1. */
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 27
+#endif
+
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+# include "_iprt_atomic.h"
+#else /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+#if defined(__ppc__)
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+extern PRInt32 _PR_DarwinPPC_AtomicIncrement(PRInt32 *val);
+#define _MD_ATOMIC_INCREMENT(val) _PR_DarwinPPC_AtomicIncrement(val)
+extern PRInt32 _PR_DarwinPPC_AtomicDecrement(PRInt32 *val);
+#define _MD_ATOMIC_DECREMENT(val) _PR_DarwinPPC_AtomicDecrement(val)
+extern PRInt32 _PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval);
+#define _MD_ATOMIC_SET(val, newval) _PR_DarwinPPC_AtomicSet(val, newval)
+extern PRInt32 _PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD(ptr, val) _PR_DarwinPPC_AtomicAdd(ptr, val)
+#elif defined(__i386__)
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+extern PRInt32 _PR_Darwin_x86_AtomicIncrement(PRInt32 *val);
+#define _MD_ATOMIC_INCREMENT(val) _PR_Darwin_x86_AtomicIncrement(val)
+extern PRInt32 _PR_Darwin_x86_AtomicDecrement(PRInt32 *val);
+#define _MD_ATOMIC_DECREMENT(val) _PR_Darwin_x86_AtomicDecrement(val)
+extern PRInt32 _PR_Darwin_x86_AtomicSet(PRInt32 *val, PRInt32 newval);
+#define _MD_ATOMIC_SET(val, newval) _PR_Darwin_x86_AtomicSet(val, newval)
+extern PRInt32 _PR_Darwin_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD(ptr, val) _PR_Darwin_x86_AtomicAdd(ptr, val)
+#endif /* __i386__ */
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+#define USE_SETJMP
+
+#if !defined(_PR_PTHREADS)
+
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE jmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+#define _MD_GET_SP(_th) (((struct sigcontext *) (_th)->md.context)->sc_onstack)
+#define PR_NUM_GCREGS _JBLEN
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+extern PRStatus _MD_InitializeThread(PRThread *thread);
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+extern PRStatus _MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
+extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
+extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
+extern void _MD_YIELD(void);
+
+#endif /* ! _PR_PTHREADS */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+
+/* For writev() */
+#include <sys/uio.h>
+
+#endif /* nspr_darwin_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.cfg
new file mode 100644
index 00000000..ed6b93f8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.cfg
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef DGUX
+#define DGUX
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.h
new file mode 100644
index 00000000..f3f02e82
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_dgux.h
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_dgux_defs_h___
+#define nspr_dgux_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "dgux"
+#define _PR_SI_SYSNAME "DGUX"
+#define _PR_SI_ARCHITECTURE "x86"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_NETCONFIG
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define _PR_NEED_STRCASECMP
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _SETJMP setjmp
+#define _LONGJMP longjmp
+#define _PR_CONTEXT_TYPE jmp_buf
+#define _MD_GET_SP(_t) (_t)->md.context[4]
+#define _PR_NUM_GCREGS _JBLEN
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!_SETJMP(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _LONGJMP(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures.
+ * Don't use SVR4 native threads (yet).
+ */
+
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+ * The following are copied from _sunos.h, _aix.h. This means
+ * some of them should probably be moved into _unixos.h. But
+ * _irix.h seems to be quite different in regard to these macros.
+ */
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *execptfds, struct timeval *timeout);
+#define _MD_SELECT _select
+
+#define _MD_POLL _poll
+#include <poll.h>
+#include <stropts.h>
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+
+#endif /* nspr_dgux_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.cfg
new file mode 100644
index 00000000..76d35420
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.cfg
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef FREEBSD
+#define FREEBSD
+#endif
+
+#define PR_AF_INET6 28 /* same as AF_INET6 */
+
+#ifndef HAVE_LONG_LONG
+#define HAVE_LONG_LONG
+#endif
+
+#if defined(__i386__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__alpha__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#elif defined(__sparc__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#elif defined(__ia64__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#elif defined(__amd64__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#else
+
+#error "Unknown CPU architecture"
+
+#endif
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.h
new file mode 100644
index 00000000..7ec7c894
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_freebsd.h
@@ -0,0 +1,290 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_freebsd_defs_h___
+#define nspr_freebsd_defs_h___
+
+#include "prthread.h"
+
+#if __FreeBSD__ >= 2
+#include <osreldate.h> /* for __FreeBSD_version */
+#endif
+#include <sys/syscall.h>
+
+#define PR_LINKER_ARCH "freebsd"
+#define _PR_SI_SYSNAME "FREEBSD"
+#if defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__alpha__)
+#define _PR_SI_ARCHITECTURE "alpha"
+#elif defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#elif defined(__ia64__)
+#define _PR_SI_ARCHITECTURE "ia64"
+#elif defined(__amd64__)
+#define _PR_SI_ARCHITECTURE "amd64"
+#else
+#error "Unknown CPU architecture"
+#endif
+#if defined(__ELF__)
+#define PR_DLL_SUFFIX ".so"
+#else
+#define PR_DLL_SUFFIX ".so.1.0"
+#endif
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_NO_LARGE_FILES
+
+#if defined(_PR_PTHREADS)
+#if __FreeBSD_version >= 400008
+/*
+ * libc_r before this version of FreeBSD doesn't have poll().
+ * Although libc has poll(), it is not thread-safe so we can't
+ * use it in the pthreads version.
+ */
+#define _PR_POLL_AVAILABLE
+#endif
+#else
+#if __FreeBSD_version >= 300000
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#endif
+#endif
+
+#define _PR_HAVE_SYSV_SEMAPHORES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+
+#if __FreeBSD_version >= 400014
+#define _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#define _PR_IPV6_V6ONLY_PROBE
+#endif
+
+/* VBOX - START (expect somthing similar to arrive in the mozilla tree) */
+#if (__FreeBSD_version >= 700016) || (__FreeBSD_version < 700000 && __FreeBSD_version >= 601103)
+#if defined(_PR_PTHREADS)
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_5_ARG_GETPROTO_R
+#define _PR_HAVE_GETHOST_R
+#define _PR_HAVE_GETHOST_R_INT
+#define _PR_HAVE_THREADSAFE_GETHOST
+#endif
+#endif
+/* VBOX - END */
+
+#define USE_SETJMP
+
+#ifndef _PR_PTHREADS
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE sigjmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+#define _MD_GET_SP(_th) (_th)->md.context[0]._sjb[2]
+#define PR_NUM_GCREGS _JBLEN
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (sigsetjmp(CONTEXT(_thread), 1)) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!sigsetjmp(CONTEXT(_thread), 1)) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ siglongjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+extern PRStatus _MD_InitializeThread(PRThread *thread);
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+extern PRStatus _MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
+extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
+extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
+extern void _MD_YIELD(void);
+
+#endif /* ! _PR_PTHREADS */
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+
+#if defined(_PR_POLL_AVAILABLE)
+#include <poll.h>
+#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
+#endif
+
+/* freebsd has INADDR_LOOPBACK defined, but in /usr/include/rpc/types.h, and I didn't
+ want to be including that.. */
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (u_long)0x7F000001
+#endif
+
+/* For writev() */
+#include <sys/uio.h>
+
+#endif /* nspr_freebsd_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux.h
new file mode 100644
index 00000000..73928313
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux.h
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_xhppa_defs_h___
+#define nspr_xhppa_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "hpux"
+#define _PR_SI_SYSNAME "HPUX"
+#define _PR_SI_ARCHITECTURE "hppa1.1"
+#define PR_DLL_SUFFIX ".sl"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+/*
+ * _USE_BIG_FDS increases the size of fd_set from 256 bytes to
+ * about 7500 bytes. PR_Poll allocates three fd_sets on the
+ * stack, so it is safer to also increase the default thread
+ * stack size.
+ */
+#define _MD_DEFAULT_STACK_SIZE (2*65536L)
+#define _MD_MINIMUM_STACK_SIZE (2*65536L)
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#define NEED_TIME_R
+
+#define HAVE_STACK_GROWING_UP
+#undef HAVE_WEAK_IO_SYMBOLS
+#undef HAVE_WEAK_MALLOC_SYMBOLS
+#define HAVE_DLL
+#ifdef IS_64
+#define USE_DLFCN
+#else
+#define USE_HPSHL
+#endif
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR
+#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#define _PR_HAVE_POSIX_SEMAPHORES
+#define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+#define _PR_ACCEPT_INHERIT_NONBLOCK
+
+#undef _PR_HAVE_ATOMIC_OPS
+
+#ifdef _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETIPNODEBYNAME
+#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#endif
+
+#if !defined(_PR_PTHREADS)
+
+#include <syscall.h>
+#include <setjmp.h>
+
+#define USE_SETJMP
+
+#define _MD_GET_SP(_t) (*((int *)((_t)->md.jb) + 1))
+#define PR_NUM_GCREGS _JBLEN
+/* Caveat: This makes jmp_buf full of doubles. */
+#define CONTEXT(_th) ((_th)->md.jb)
+
+ /* Stack needs two frames (64 bytes) at the bottom */ \
+#define _MD_SET_THR_SP(_t, _sp) ((_MD_GET_SP(_t)) = (int) (_sp + 64 *2))
+#define SAVE_CONTEXT(_th) _setjmp(CONTEXT(_th))
+#define GOTO_CONTEXT(_th) _longjmp(CONTEXT(_th), 1)
+
+#if !defined(PTHREADS_USER)
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *(status) = PR_TRUE; \
+ if (_setjmp(CONTEXT(_thread))) (*_main)(); \
+ /* Stack needs two frames (64 bytes) at the bottom */ \
+ (_MD_GET_SP(_thread)) = (int) ((_sp) + 64*2); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!_setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures. HP-UX has no native threads. */
+
+struct _MDThread {
+ jmp_buf jb;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+#else /* PTHREADS_USER */
+
+#include "_nspr_pthread.h"
+
+#endif /* PTHREADS_USER */
+
+#endif /* !defined(_PR_PTHREADS) */
+
+#if !defined(PTHREADS_USER)
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#endif
+
+#if defined(HPUX_LW_TIMER)
+extern void _PR_HPUX_LW_IntervalInit(void);
+extern PRIntervalTime _PR_HPUX_LW_GetInterval(void);
+#define _MD_INTERVAL_INIT _PR_HPUX_LW_IntervalInit
+#define _MD_GET_INTERVAL _PR_HPUX_LW_GetInterval
+#define _MD_INTERVAL_PER_SEC() 1000
+#else
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#endif
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+
+#include <poll.h>
+#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
+
+#ifdef HPUX11
+extern void _MD_hpux_map_sendfile_error(int err);
+#endif /* HPUX11 */
+
+#endif /* nspr_xhppa_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux32.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux32.cfg
new file mode 100644
index 00000000..1213802d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux32.cfg
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef HPUX
+#define HPUX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_AF_INET6 22 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux64.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux64.cfg
new file mode 100644
index 00000000..17574ade
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_hpux64.cfg
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef HPUX
+#define HPUX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define IS_64
+
+#define PR_AF_INET6 22 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_iprt_atomic.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_iprt_atomic.h
new file mode 100644
index 00000000..daf929b6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_iprt_atomic.h
@@ -0,0 +1,64 @@
+/* $Id: _iprt_atomic.h $ */
+/** @file
+ * IPRT Atomic Operation, for including into a system config header.
+ */
+
+/*
+ * Copyright (C) 2009-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_md__iprt_atomic_h
+#define VBOX_INCLUDED_SRC_md__iprt_atomic_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Note! Do not copy this around, put it in a header of its own if reused anywhere! */
+#include <iprt/asm.h>
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC() do {} while (0)
+
+DECLINLINE(PRInt32) _PR_IPRT_AtomicIncrement(PRInt32 *pVal)
+{
+ return ASMAtomicIncS32(pVal);
+}
+#define _MD_ATOMIC_INCREMENT(pVal) _PR_IPRT_AtomicIncrement(pVal)
+
+DECLINLINE(PRInt32) _PR_IPRT_AtomicDecrement(PRInt32 *pVal)
+{
+ return ASMAtomicDecS32(pVal);
+}
+#define _MD_ATOMIC_DECREMENT(pVal) _PR_IPRT_AtomicDecrement(pVal)
+
+DECLINLINE(PRInt32) _PR_IPRT_AtomicSet(PRInt32 *pVal, PRInt32 NewVal)
+{
+ return ASMAtomicXchgS32(pVal, NewVal);
+}
+#define _MD_ATOMIC_SET(pVal, NewVal) _PR_IPRT_AtomicSet(pVal, NewVal)
+
+DECLINLINE(PRInt32) _PR_IPRT_AtomicAdd(PRInt32 *pVal, PRInt32 ToAdd)
+{
+ return ASMAtomicAddS32(pVal, ToAdd) + ToAdd;
+}
+#define _MD_ATOMIC_ADD(pVal, ToAdd) _PR_IPRT_AtomicAdd(pVal, ToAdd)
+
+#endif /* !VBOX_INCLUDED_SRC_md__iprt_atomic_h */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix.h
new file mode 100644
index 00000000..c38bb4bc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix.h
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_irix_defs_h___
+#define nspr_irix_defs_h___
+
+#define _PR_HAVE_ATOMIC_CAS
+
+/*
+ * MipsPro assembler defines _LANGUAGE_ASSEMBLY
+ */
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include "prclist.h"
+#include "prthread.h"
+#include <sys/ucontext.h>
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "irix"
+#define _PR_SI_SYSNAME "IRIX"
+#define _PR_SI_ARCHITECTURE "mips"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _PR_NUM_GCREGS 9
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MIN_STACK_SIZE 16384L
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_MALLOC_SYMBOLS
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_HAVE_ATOMIC_OPS
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ST_ATIM
+#define _PR_HAVE_OFF64_T
+#define HAVE_POINTER_LOCALTIME_R
+#define _PR_HAVE_POSIX_SEMAPHORES
+#define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+#define _PR_ACCEPT_INHERIT_NONBLOCK
+
+#ifdef _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETIPNODEBYNAME
+#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
+#endif
+
+/* Initialization entry points */
+NSPR_API(void) _MD_EarlyInit(void);
+#define _MD_EARLY_INIT _MD_EarlyInit
+
+NSPR_API(void) _MD_IrixInit(void);
+#define _MD_FINAL_INIT _MD_IrixInit
+
+#define _MD_INIT_IO()
+
+/* Timer operations */
+NSPR_API(PRIntervalTime) _MD_IrixGetInterval(void);
+#define _MD_GET_INTERVAL _MD_IrixGetInterval
+
+NSPR_API(PRIntervalTime) _MD_IrixIntervalPerSec(void);
+#define _MD_INTERVAL_PER_SEC _MD_IrixIntervalPerSec
+
+/* GC operations */
+NSPR_API(void *) _MD_GetSP(PRThread *thread);
+#define _MD_GET_SP _MD_GetSP
+
+/* The atomic operations */
+#include <mutex.h>
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(val) add_then_test((unsigned long*)val, 1)
+#define _MD_ATOMIC_ADD(ptr, val) add_then_test((unsigned long*)ptr, (unsigned long)val)
+#define _MD_ATOMIC_DECREMENT(val) add_then_test((unsigned long*)val, 0xffffffff)
+#define _MD_ATOMIC_SET(val, newval) test_and_set((unsigned long*)val, newval)
+
+#if defined(_PR_PTHREADS)
+#else /* defined(_PR_PTHREADS) */
+
+/************************************************************************/
+
+#include <setjmp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <bstring.h>
+#include <sys/time.h>
+#include <ulocks.h>
+#include <sys/prctl.h>
+
+
+/*
+ * Data region private to each sproc. This region is setup by calling
+ * mmap(...,MAP_LOCAL,...). The private data is mapped at the same
+ * address in every sproc, but every sproc gets a private mapping.
+ *
+ * Just make sure that this structure fits in a page, as only one page
+ * is allocated for the private region.
+ */
+struct sproc_private_data {
+ struct PRThread *me;
+ struct _PRCPU *cpu;
+ struct PRThread *last;
+ PRUintn intsOff;
+ int sproc_pid;
+};
+
+extern char *_nspr_sproc_private;
+
+#define _PR_PRDA() ((struct sproc_private_data *) _nspr_sproc_private)
+#define _MD_SET_CURRENT_THREAD(_thread) _PR_PRDA()->me = (_thread)
+#define _MD_THIS_THREAD() (_PR_PRDA()->me)
+#define _MD_LAST_THREAD() (_PR_PRDA()->last)
+#define _MD_SET_LAST_THREAD(_thread) _PR_PRDA()->last = (_thread)
+#define _MD_CURRENT_CPU() (_PR_PRDA()->cpu)
+#define _MD_SET_CURRENT_CPU(_cpu) _PR_PRDA()->cpu = (_cpu)
+#define _MD_SET_INTSOFF(_val) (_PR_PRDA()->intsOff = _val)
+#define _MD_GET_INTSOFF() (_PR_PRDA()->intsOff)
+
+#define _MD_SET_SPROC_PID(_val) (_PR_PRDA()->sproc_pid = _val)
+#define _MD_GET_SPROC_PID() (_PR_PRDA()->sproc_pid)
+
+NSPR_API(struct PRThread*) _MD_get_attached_thread(void);
+NSPR_API(struct PRThread*) _MD_get_current_thread(void);
+#define _MD_GET_ATTACHED_THREAD() _MD_get_attached_thread()
+#define _MD_CURRENT_THREAD() _MD_get_current_thread()
+
+#define _MD_CHECK_FOR_EXIT() { \
+ if (_pr_irix_exit_now) { \
+ _PR_POST_SEM(_pr_irix_exit_sem); \
+ _MD_Wakeup_CPUs(); \
+ _exit(0); \
+ } \
+ }
+
+#define _MD_ATTACH_THREAD(threadp)
+
+#define _MD_SAVE_ERRNO(_thread) (_thread)->md.errcode = errno;
+#define _MD_RESTORE_ERRNO(_thread) errno = (_thread)->md.errcode;
+
+extern struct _PRCPU *_pr_primordialCPU;
+extern usema_t *_pr_irix_exit_sem;
+extern PRInt32 _pr_irix_exit_now;
+extern int _pr_irix_primoridal_cpu_fd[];
+extern PRInt32 _pr_irix_process_exit;
+extern PRInt32 _pr_irix_process_exit_code;
+
+/* Thread operations */
+#define _PR_LOCK_HEAP() { \
+ PRIntn _is; \
+ if (_pr_primordialCPU) { \
+ if (_MD_GET_ATTACHED_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _MD_GET_ATTACHED_THREAD())) \
+ _PR_INTSOFF(_is); \
+ _PR_LOCK(_pr_heapLock); \
+ }
+
+#define _PR_UNLOCK_HEAP() if (_pr_primordialCPU) { \
+ _PR_UNLOCK(_pr_heapLock); \
+ if (_MD_GET_ATTACHED_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _MD_GET_ATTACHED_THREAD())) \
+ _PR_INTSON(_is); \
+ } \
+ }
+
+#define _PR_OPEN_POLL_SEM(_sem) usopenpollsema(_sem, 0666)
+#define _PR_WAIT_SEM(_sem) uspsema(_sem)
+#define _PR_POST_SEM(_sem) usvsema(_sem)
+
+#define _MD_CVAR_POST_SEM(threadp) usvsema((threadp)->md.cvar_pollsem)
+
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+struct _MDLock {
+ ulock_t lock;
+ usptr_t *arena;
+};
+
+/*
+ * disable pre-emption for the LOCAL threads when calling the arena lock
+ * routines
+ */
+
+#define _PR_LOCK(lock) { \
+ PRIntn _is; \
+ PRThread *me = _MD_GET_ATTACHED_THREAD(); \
+ if (me && !_PR_IS_NATIVE_THREAD(me)) \
+ _PR_INTSOFF(_is); \
+ ussetlock(lock); \
+ if (me && !_PR_IS_NATIVE_THREAD(me)) \
+ _PR_FAST_INTSON(_is); \
+ }
+
+#define _PR_UNLOCK(lock) { \
+ PRIntn _is; \
+ PRThread *me = _MD_GET_ATTACHED_THREAD(); \
+ if (me && !_PR_IS_NATIVE_THREAD(me)) \
+ _PR_INTSOFF(_is); \
+ usunsetlock(lock); \
+ if (me && !_PR_IS_NATIVE_THREAD(me)) \
+ _PR_FAST_INTSON(_is); \
+ }
+
+NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md);
+NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp);
+
+#define _MD_LOCK(_lockp) _PR_LOCK((_lockp)->lock)
+#define _MD_UNLOCK(_lockp) _PR_UNLOCK((_lockp)->lock)
+#define _MD_TEST_AND_LOCK(_lockp) (uscsetlock((_lockp)->lock, 1) == 0)
+
+extern ulock_t _pr_heapLock;
+
+struct _MDThread {
+ jmp_buf jb;
+ usptr_t *pollsem_arena;
+ usema_t *cvar_pollsem;
+ PRInt32 cvar_pollsemfd;
+ PRInt32 cvar_pollsem_select; /* acquire sem by calling select */
+ PRInt32 cvar_wait; /* if 1, thread is waiting on cvar Q */
+ PRInt32 id;
+ PRInt32 suspending_id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ usema_t *sem;
+};
+
+struct _MDCVar {
+ ulock_t mdcvar_lock;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+
+struct _MDCPU {
+ PRInt32 id;
+ PRInt32 suspending_id;
+ struct _MDCPU_Unix md_unix;
+};
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ int *jb = (_thread)->md.jb; \
+ *status = PR_TRUE; \
+ (void) setjmp(jb); \
+ (_thread)->md.jb[JB_SP] = (int) ((_sp) - 64); \
+ (_thread)->md.jb[JB_PC] = (int) _main; \
+ _thread->no_sched = 0; \
+ PR_END_MACRO
+
+/*
+** Switch away from the current thread context by saving its state and
+** calling the thread scheduler. Reload cpu when we come back from the
+** context switch because it might have changed.
+*
+* XXX RUNQ lock needed before clearing _PR_NO_SCHED flag, because the
+* thread may be unr RUNQ?
+*/
+#define _MD_SWITCH_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ PR_ASSERT(_thread->no_sched); \
+ if (!setjmp(_thread->md.jb)) { \
+ _MD_SAVE_ERRNO(_thread) \
+ _MD_SET_LAST_THREAD(_thread); \
+ _PR_Schedule(); \
+ } else { \
+ PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
+ _MD_LAST_THREAD()->no_sched = 0; \
+ } \
+ PR_END_MACRO
+
+/*
+** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
+** initialized by _MD_INIT_CONTEXT.
+*/
+#define _MD_RESTORE_CONTEXT(_newThread) \
+ PR_BEGIN_MACRO \
+ int *jb = (_newThread)->md.jb; \
+ _MD_RESTORE_ERRNO(_newThread) \
+ _MD_SET_CURRENT_THREAD(_newThread); \
+ _newThread->no_sched = 1; \
+ longjmp(jb, 1); \
+ PR_END_MACRO
+
+NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread,
+ PRBool wakeup_parent);
+NSPR_API(PRStatus) _MD_InitAttachedThread(struct PRThread *thread,
+ PRBool wakeup_parent);
+#define _MD_INIT_THREAD(thread) _MD_InitThread(thread, PR_TRUE)
+#define _MD_INIT_ATTACHED_THREAD(thread) \
+ _MD_InitAttachedThread(thread, PR_FALSE)
+
+NSPR_API(void) _MD_ExitThread(struct PRThread *thread);
+#define _MD_EXIT_THREAD _MD_ExitThread
+
+NSPR_API(void) _MD_SuspendThread(struct PRThread *thread);
+#define _MD_SUSPEND_THREAD _MD_SuspendThread
+
+NSPR_API(void) _MD_ResumeThread(struct PRThread *thread);
+#define _MD_RESUME_THREAD _MD_ResumeThread
+
+NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread);
+#define _MD_SUSPEND_CPU _MD_SuspendCPU
+
+NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread);
+#define _MD_RESUME_CPU _MD_ResumeCPU
+
+#define _MD_BEGIN_SUSPEND_ALL()
+#define _MD_END_SUSPEND_ALL()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_RESUME_ALL()
+
+NSPR_API(void) _MD_InitLocks(void);
+#define _MD_INIT_LOCKS _MD_InitLocks
+
+NSPR_API(void) _MD_CleanThread(struct PRThread *thread);
+#define _MD_CLEAN_THREAD _MD_CleanThread
+
+#define _MD_YIELD() sginap(0)
+
+/* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and
+ * awaken a thread which is waiting on a lock or cvar.
+ */
+NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout);
+#define _MD_WAIT _MD_wait
+
+NSPR_API(void) _PR_MD_primordial_cpu();
+NSPR_API(void) _PR_MD_WAKEUP_PRIMORDIAL_CPU();
+
+NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *);
+#define _MD_WAKEUP_WAITER _MD_WakeupWaiter
+
+NSPR_API(void ) _MD_exit(PRIntn status);
+#define _MD_EXIT _MD_exit
+
+#include "prthread.h"
+
+NSPR_API(void) _MD_SetPriority(struct _MDThread *thread,
+ PRThreadPriority newPri);
+#define _MD_SET_PRIORITY _MD_SetPriority
+
+NSPR_API(PRStatus) _MD_CreateThread(
+ struct PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+#define _MD_CREATE_THREAD _MD_CreateThread
+
+extern void _MD_CleanupBeforeExit(void);
+#define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit
+
+NSPR_API(void) _PR_MD_PRE_CLEANUP(PRThread *me);
+
+
+/* The following defines the unwrapped versions of select() and poll(). */
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout);
+#define _MD_SELECT _select
+
+#include <stropts.h>
+#include <poll.h>
+#define _MD_POLL _poll
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+
+
+#define HAVE_THREAD_AFFINITY 1
+
+NSPR_API(PRInt32) _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask);
+#define _MD_GETTHREADAFFINITYMASK _MD_GetThreadAffinityMask
+
+NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu);
+#define _MD_INIT_RUNNING_CPU _MD_InitRunningCPU
+
+#endif /* defined(_PR_PTHREADS) */
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#endif /* nspr_irix_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix32.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix32.cfg
new file mode 100644
index 00000000..db6ca446
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix32.cfg
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef _SGI_MP_SOURCE
+#define _SGI_MP_SOURCE
+#endif
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef IRIX
+#define IRIX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix64.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix64.cfg
new file mode 100644
index 00000000..305317ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_irix64.cfg
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef _SGI_MP_SOURCE
+#define _SGI_MP_SOURCE
+#endif
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef IRIX
+#define IRIX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define IS_64
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.cfg
new file mode 100644
index 00000000..f1d89314
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.cfg
@@ -0,0 +1,661 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef LINUX
+#define LINUX
+#endif
+
+#define PR_AF_INET6 10 /* same as AF_INET6 */
+
+#ifdef __powerpc__
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__alpha)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__ia64__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__x86_64__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__mc68000__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 2
+#define PR_ALIGN_OF_LONG 2
+#define PR_ALIGN_OF_INT64 2
+#define PR_ALIGN_OF_FLOAT 2
+#define PR_ALIGN_OF_DOUBLE 2
+#define PR_ALIGN_OF_POINTER 2
+#define PR_ALIGN_OF_WORD 2
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__sparc__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__i386__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__mips__)
+
+#ifdef __MIPSEB__
+#define IS_BIG_ENDIAN 1
+#undef IS_LITTLE_ENDIAN
+#elif defined(__MIPSEL__)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#else
+#error "Unknown MIPS endianness."
+#endif
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__arm__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__hppa__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__s390__)
+
+#define IS_BIG_ENDIAN 1
+#undef IS_LITTLE_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__s390x__)
+
+#define IS_BIG_ENDIAN 1
+#undef IS_LITTLE_ENDIAN
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#else
+
+#error "Unknown CPU architecture"
+
+#endif
+
+#define HAVE_LONG_LONG
+#if PR_ALIGN_OF_DOUBLE == 8
+#define HAVE_ALIGNED_DOUBLES
+#endif
+#if PR_ALIGN_OF_INT64 == 8
+#define HAVE_ALIGNED_LONGLONGS
+#endif
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.h
new file mode 100644
index 00000000..f68dfff1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_linux.h
@@ -0,0 +1,501 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_linux_defs_h___
+#define nspr_linux_defs_h___
+
+#include "prthread.h"
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "linux"
+#define _PR_SI_SYSNAME "LINUX"
+#ifdef __powerpc__
+#define _PR_SI_ARCHITECTURE "ppc"
+#elif defined(__alpha)
+#define _PR_SI_ARCHITECTURE "alpha"
+#elif defined(__ia64__)
+#define _PR_SI_ARCHITECTURE "ia64"
+#elif defined(__x86_64__)
+#define _PR_SI_ARCHITECTURE "x86-64"
+#elif defined(__mc68000__)
+#define _PR_SI_ARCHITECTURE "m68k"
+#elif defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#elif defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__mips__)
+#define _PR_SI_ARCHITECTURE "mips"
+#elif defined(__arm__)
+#define _PR_SI_ARCHITECTURE "arm"
+#elif defined(__hppa__)
+#define _PR_SI_ARCHITECTURE "hppa"
+#elif defined(__s390__)
+#define _PR_SI_ARCHITECTURE "s390"
+#elif defined(__s390x__)
+#define _PR_SI_ARCHITECTURE "s390x"
+#else
+#error "Unknown CPU architecture"
+#endif
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+
+/*
+ * Elf linux supports dl* functions
+ */
+#define HAVE_DLL
+#define USE_DLFCN
+
+#if defined(__i386__)
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+extern PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val);
+#define _MD_ATOMIC_INCREMENT _PR_x86_AtomicIncrement
+extern PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val);
+#define _MD_ATOMIC_DECREMENT _PR_x86_AtomicDecrement
+extern PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD _PR_x86_AtomicAdd
+extern PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval);
+#define _MD_ATOMIC_SET _PR_x86_AtomicSet
+#endif
+
+#if defined(__ia64__)
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+extern PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val);
+#define _MD_ATOMIC_INCREMENT _PR_ia64_AtomicIncrement
+extern PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val);
+#define _MD_ATOMIC_DECREMENT _PR_ia64_AtomicDecrement
+extern PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD _PR_ia64_AtomicAdd
+extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval);
+#define _MD_ATOMIC_SET _PR_ia64_AtomicSet
+#endif
+
+#if defined(__x86_64__)
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+extern PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val);
+#define _MD_ATOMIC_INCREMENT _PR_x86_64_AtomicIncrement
+extern PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val);
+#define _MD_ATOMIC_DECREMENT _PR_x86_64_AtomicDecrement
+extern PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD _PR_x86_64_AtomicAdd
+extern PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval);
+#define _MD_ATOMIC_SET _PR_x86_64_AtomicSet
+#endif
+
+#define USE_SETJMP
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _PR_POLL_AVAILABLE
+#endif
+#undef _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#if defined(__alpha) || defined(__ia64__)
+#define _PR_HAVE_LARGE_OFF_T
+#elif (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
+#define _PR_HAVE_OFF64_T
+#else
+#define _PR_NO_LARGE_FILES
+#endif
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
+#define _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#endif
+#define _PR_HAVE_SYSV_SEMAPHORES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+#if (__GLIBC__ >= 2) && defined(_PR_PTHREADS)
+#define _PR_HAVE_GETHOST_R
+#define _PR_HAVE_GETHOST_R_INT
+#endif
+
+#ifdef _PR_PTHREADS
+
+extern void _MD_CleanupBeforeExit(void);
+#define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit
+
+#else /* ! _PR_PTHREADS */
+
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE sigjmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+#ifdef __powerpc__
+/*
+ * PowerPC based MkLinux
+ *
+ * On the PowerPC, the new style jmp_buf isn't used until glibc
+ * 2.1.
+ */
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_GPR1]
+#else
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__misc[0]
+#endif /* glibc 2.1 or later */
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+/* aix = 64, macos = 70 */
+#define PR_NUM_GCREGS 64
+
+#elif defined(__alpha)
+/* Alpha based Linux */
+
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_SP]
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+#define _MD_SP_TYPE long int
+#else
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+#define _MD_SP_TYPE __ptr_t
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+
+/* XXX not sure if this is correct, or maybe it should be 17? */
+#define PR_NUM_GCREGS 9
+
+#elif defined(__ia64__)
+
+#define _MD_GET_SP(_t) ((long *)((_t)->md.context[0].__jmpbuf)[0])
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+#define _MD_SP_TYPE long int
+
+#define PR_NUM_GCREGS _JBLEN
+
+#elif defined(__mc68000__)
+/* m68k based Linux */
+
+/*
+ * On the m68k, glibc still uses the old style sigjmp_buf, even
+ * in glibc 2.0.7.
+ */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+#define _MD_SP_TYPE int
+#else
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+#define _MD_SP_TYPE __ptr_t
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+
+/* XXX not sure if this is correct, or maybe it should be 17? */
+#define PR_NUM_GCREGS 9
+
+#elif defined(__sparc__)
+/* Sparc */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+/*
+ * You need glibc2-2.0.7-25 or later. The libraries that came with
+ * Red Hat 5.1 are not new enough, but they are in 5.2.
+ */
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_SP]
+#define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[JB_FP] = val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[JB_FP])
+#define _MD_SP_TYPE int
+#else
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__fp
+#define _MD_SET_FP(_t, val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) ((void *) 0)
+#define _MD_SP_TYPE __ptr_t
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+
+#elif defined(__i386__)
+/* Intel based Linux */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_SP]
+#define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[JB_BP] = val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[JB_BP])
+#define _MD_SP_TYPE int
+#else
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp
+#define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[0].__bp = val)
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) &((_t)->md.context[0].__jmpbuf[0].__bp)
+#define _MD_SP_TYPE __ptr_t
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+#define PR_NUM_GCREGS 6
+
+#elif defined(__mips__)
+/* Linux/MIPS */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp
+#define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[0].__fp = (val))
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[0].__fp)
+#define _MD_SP_TYPE __ptr_t
+#else
+#error "Linux/MIPS pre-glibc2 not supported yet"
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+
+#elif defined(__arm__)
+/* ARM/Linux */
+#if defined(__GLIBC__) && __GLIBC__ >= 2
+#define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[20]
+#define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[19] = (val))
+#define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t))
+#define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[19])
+#define _MD_SP_TYPE __ptr_t
+#else
+#error "ARM/Linux pre-glibc2 not supported yet"
+#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
+
+#else
+
+#error "Unknown CPU architecture"
+
+#endif /*__powerpc__*/
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#ifdef __powerpc__
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (sigsetjmp(CONTEXT(_thread), 1)) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 128); \
+ _thread->md.sp = _MD_GET_SP_PTR(_thread); \
+ _thread->md.fp = _MD_GET_FP_PTR(_thread); \
+ _MD_SET_FP(_thread, 0); \
+}
+
+#elif defined(__mips__)
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ (void) sigsetjmp(CONTEXT(_thread), 1); \
+ _thread->md.context[0].__jmpbuf[0].__pc = (__ptr_t) _main; \
+ _MD_GET_SP(_thread) = (_MD_SP_TYPE) ((_sp) - 64); \
+ _thread->md.sp = _MD_GET_SP_PTR(_thread); \
+ _thread->md.fp = _MD_GET_FP_PTR(_thread); \
+ _MD_SET_FP(_thread, 0); \
+}
+
+#else
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (sigsetjmp(CONTEXT(_thread), 1)) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (_MD_SP_TYPE) ((_sp) - 64); \
+ _thread->md.sp = _MD_GET_SP_PTR(_thread); \
+ _thread->md.fp = _MD_GET_FP_PTR(_thread); \
+ _MD_SET_FP(_thread, 0); \
+}
+
+#endif /*__powerpc__*/
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!sigsetjmp(CONTEXT(_thread), 1)) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ siglongjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ void *sp;
+ void *fp;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#include <sys/time.h> /* for FD_SETSIZE */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+extern PRStatus _MD_InitializeThread(PRThread *thread);
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+extern PRStatus _MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
+extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
+extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
+extern void _MD_YIELD(void);
+
+#endif /* ! _PR_PTHREADS */
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT __select
+
+#ifdef _PR_POLL_AVAILABLE
+#include <sys/poll.h>
+extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds,
+ int timeout);
+#define _MD_POLL __syscall_poll
+#endif
+
+/* For writev() */
+#include <sys/uio.h>
+
+extern void _MD_linux_map_sendfile_error(int err);
+
+#endif /* nspr_linux_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_macos.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_macos.h
new file mode 100644
index 00000000..dbcab409
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_macos.h
@@ -0,0 +1,725 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prmacos_h___
+#define prmacos_h___
+
+//
+// This file contains all changes and additions which need to be made to the NSPR runtime
+// for the Macintosh platform (specifically the Metrowerks environment). This file should
+// only be incluced in Macintosh builds.
+//
+
+#define PR_DLL_SUFFIX ""
+#define _PR_LOCAL_THREADS_ONLY
+#define _PR_NO_PREEMPT 1
+#define _PR_HAVE_ATOMIC_OPS 1
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlong.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prsem.h"
+#include "prthread.h"
+#include "prtime.h"
+#include "prproces.h"
+
+#if !defined(MAC_NSPR_STANDALONE)
+#include "macstdlibextras.h"
+#endif
+
+#include <stddef.h>
+#include <setjmp.h>
+
+#include <Errors.h>
+#include <OpenTransport.h>
+#include <DriverServices.h>
+
+#define _PR_HAVE_PEEK_BUFFER
+#define _PR_PEEK_BUFFER_MAX (16 * 1024)
+#define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) 1
+
+struct _MDProcess {
+ PRInt8 notused;
+};
+
+struct _MDThread {
+ jmp_buf jb;
+ int osErrCode;
+ PRLock * asyncIOLock;
+ PRCondVar * asyncIOCVar;
+ PRBool missedIONotify;
+ PRBool missedAsyncNotify;
+ PRBool asyncNotifyPending;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+struct _MDCPU {
+ AbsoluteTime lastThreadSwitch;
+ AbsoluteTime lastWakeUpProcess;
+ PRBool trackScheduling;
+};
+
+typedef struct _MDSocketCallerInfo {
+ PRThread * thread;
+ void * cookie;
+} _MDSocketCallerInfo;
+
+struct _MDFileDesc {
+ PRInt32 osfd;
+ PRPackedBool orderlyDisconnect;
+ PRPackedBool readReady;
+ PRPackedBool writeReady;
+ PRPackedBool exceptReady;
+ PRLock * miscLock;
+
+ /* Server sockets: listen bit tells the notifier func what to do */
+ PRBool doListen;
+
+ /* stored error for non-blocking connects, as a Unix-style error code */
+ OTReason disconnectError;
+
+ _MDSocketCallerInfo misc;
+ _MDSocketCallerInfo read;
+ _MDSocketCallerInfo write;
+};
+
+/*
+** Iinitialization Related definitions
+*/
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _MD_FinalInit
+
+/*
+** Interrupts Related definitions
+*/
+
+#define _MD_GET_INTSOFF() (_pr_intsOff)
+
+#define _MD_INTSOFF(_is) \
+ PR_BEGIN_MACRO \
+ ENTER_CRITICAL_REGION(); \
+ (_is) = _PR_MD_GET_INTSOFF(); \
+ _PR_MD_SET_INTSOFF(1); \
+ LEAVE_CRITICAL_REGION(); \
+ PR_END_MACRO
+
+#if TARGET_CARBON
+extern void _MD_SetIntsOff(PRInt32 ints);
+#define _MD_SET_INTSOFF(_val) _MD_SetIntsOff(_val)
+#else /* not TARGET_CARBON */
+#define _MD_SET_INTSOFF(_val) (_pr_intsOff = _val)
+#endif /* TARGET_CARBON */
+
+#define _MD_START_INTERRUPTS _MD_StartInterrupts
+#define _MD_STOP_INTERRUPTS _MD_StopInterrupts
+#define _MD_BLOCK_CLOCK_INTERRUPTS()
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
+#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
+
+/*
+** CPU Related definitions
+*/
+
+#define _MD_PAUSE_CPU _MD_PauseCPU
+#define _MD_CLEANUP_BEFORE_EXIT()
+#define _MD_EXIT(status) exit(status)
+#define _MD_INIT_CPUS()
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_InitRunningCPU(cpu)
+
+/*
+** Process Related definitions
+*/
+
+extern struct PRProcess * _MD_CreateProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr);
+#define _MD_CREATE_PROCESS _MD_CreateProcess
+
+extern PRStatus _MD_DetachProcess(PRProcess *process);
+#define _MD_DETACH_PROCESS _MD_DetachProcess
+
+extern PRStatus _MD_WaitProcess(PRProcess *process, PRInt32 *exitCode);
+#define _MD_WAIT_PROCESS _MD_WaitProcess
+
+extern PRStatus _MD_KillProcess(PRProcess *process);
+#define _MD_KILL_PROCESS _MD_KillProcess
+
+/*
+** Memory Segments Related definitions
+*/
+
+#define _MD_INIT_SEGS()
+
+/*
+** Thread Stacks Debugging Related definitions
+*/
+
+#define _MD_INIT_STACK _MD_InitStack
+#define _MD_CLEAR_STACK _MD_ClearStack
+
+/*
+** Locks Related definitions
+*/
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) (PR_SUCCESS)
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+
+/*
+** Thread Related definitions
+*/
+
+NSPR_API(PRThread *) PR_GetPrimaryThread();
+
+#if defined(powerc) || defined(__powerc)
+#define _MD_GET_PC(_t) (*((PRUint32 *)((_t)->md.jb)))
+#define _MD_GET_SP(_t) (*((PRUint32 *)((_t)->md.jb) + 2))
+#define _MD_GET_TOC(_t) (*((PRUint32 *)((_t)->md.jb) + 3))
+#define INIT_STACKPTR(stackTop) ((unsigned char*)stackTop - 128)
+#define PR_NUM_GCREGS 70
+#else
+#define _MD_GET_PC(_t) (*((PRUint32 *)((_t)->md.jb) + 6))
+#define _MD_GET_SP(_t) (*((PRUint32 *)((_t)->md.jb) + 12))
+#define INIT_STACKPTR(stackTop) ((unsigned char*)stackTop - 4)
+#define PR_NUM_GCREGS 13
+#endif
+
+#define _MD_DEFAULT_STACK_SIZE (58 * 1024)
+#define _MD_MINIMUM_STACK_SIZE (58 * 1024)
+
+/*
+** Initialize the thread machine dependent data structure
+*/
+extern PRStatus _MD_InitThread(PRThread *thread);
+#define _MD_INIT_THREAD _MD_InitThread
+
+/*
+** Clean-up the thread machine dependent data structure
+*/
+#define _MD_CLEAN_THREAD(_thread) \
+ PR_BEGIN_MACRO \
+ PR_DestroyCondVar(_thread->md.asyncIOCVar); \
+ PR_DestroyLock(_thread->md.asyncIOLock); \
+ PR_END_MACRO
+
+
+/*
+** Initialize the thread context preparing it to execute _main.
+** *sp = 0 zeros out the sp for the first stack frame so that
+** stack walking code can find the top of the stack.
+*/
+#if defined(powerc) || defined(__powerc)
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, _status) \
+ PR_BEGIN_MACRO \
+ unsigned char *sp; \
+ unsigned long *tvect; \
+ long **jb = (_thread)->md.jb; \
+ *((PRBool *)_status) = PR_TRUE; \
+ (void) setjmp(jb); \
+ sp = INIT_STACKPTR(_sp); \
+ *sp = 0; \
+ (_MD_GET_SP(_thread)) = (long) sp; \
+ tvect = (unsigned long *)_main; \
+ (_MD_GET_PC(_thread)) = (int) *tvect; \
+ (_MD_GET_TOC(_thread)) = (int) *(tvect+1); \
+ _thread->no_sched = 0; \
+ PR_END_MACRO
+#else
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, _status) \
+ PR_BEGIN_MACRO \
+ unsigned char *sp; \
+ long **jb = (_thread)->md.jb; \
+ *((PRBool *)_status) = PR_TRUE; \
+ (void) setjmp(jb); \
+ sp = INIT_STACKPTR(_sp); \
+ (_MD_GET_SP(_thread)) = (long) sp; \
+ (_MD_GET_PC(_thread)) = (int) _main; \
+ _thread->no_sched = 0; \
+ PR_END_MACRO
+#endif
+
+/*
+** Switch away from the current thread context by saving its state and
+** calling the thread scheduler. Reload cpu when we come back from the
+** context switch because it might have changed.
+*/
+/* ResetTimer(); before _PR_Schedule() */
+
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ PR_ASSERT(_thread->no_sched); \
+ if (!setjmp(_thread->md.jb)) { \
+ _MD_SET_LAST_THREAD(_thread); \
+ if (_PR_MD_CURRENT_CPU()->md.trackScheduling) \
+ _PR_MD_CURRENT_CPU()->md.lastThreadSwitch = UpTime(); \
+ _PR_Schedule(); \
+ } else { \
+ PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
+ _MD_LAST_THREAD()->no_sched = 0; \
+ } \
+ PR_END_MACRO
+
+/*
+** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
+** initialized by _MD_INIT_CONTEXT.
+*/
+#define _MD_RESTORE_CONTEXT(_newThread) \
+ PR_BEGIN_MACRO \
+ long **jb = (_newThread)->md.jb; \
+ _MD_SET_CURRENT_THREAD(_newThread); \
+ _newThread->no_sched = 1; \
+ longjmp(jb, 1); \
+ PR_END_MACRO
+
+
+#define _MD_ERRNO() _MD_CURRENT_THREAD()->md.osErrCode
+
+extern PRStatus _MD_wait(PRThread *thread, PRIntervalTime timeout);
+#define _MD_WAIT _MD_wait
+
+/*
+** Combined thread model related definitions
+*/
+
+#define _MD_CREATE_THREAD(a,b,c,d,e,f) (PR_SUCCESS)
+#define _MD_WAKEUP_WAITER(a)
+#define _MD_SET_PRIORITY(a,b)
+
+/*
+** File I/O Related definitions
+*/
+
+extern PRInt32 _PR_MD_WRITE_SYNC(PRFileDesc *fd, void *buf, PRInt32 amount);
+#define _PR_MD_WRITE_SYNC _MD_WRITE_SYNC
+
+struct _MDDir {
+ short ioVRefNum;
+ long ioDirID;
+ short ioFDirIndex;
+ char *currentEntryName;
+};
+
+#define PR_DIRECTORY_SEPARATOR '/'
+#define PR_DIRECTORY_SEPARATOR_STR "/"
+#define PR_PATH_SEPARATOR ':'
+#define PR_PATH_SEPARATOR_STR ":"
+
+typedef enum IOOperation {
+ READ_ASYNC,
+ WRITE_ASYNC
+} IOOperation;
+
+
+#define _MD_INIT_IO()
+
+#define _MD_OPEN _MD_Open
+#define _MD_OPEN_FILE _MD_Open
+#define _MD_CLOSE_FILE FSClose
+#define _MD_READ(fd,buf,amount) ReadWriteProc(fd,buf,amount,READ_ASYNC)
+#define _MD_WRITE(fd,buf,amount) ReadWriteProc(fd,buf,amount,WRITE_ASYNC)
+#define _MD_WRITE_SYNC(fd,buf,amount) WriteSyncProc(fd,buf,amount)
+#define _MD_GET_FILE_ERROR() _PR_MD_CURRENT_THREAD()->md.osErrCode
+#define _MD_LSEEK _MD_LSeek
+#define _MD_FSYNC _MD_FSync
+
+/* to be implemented */
+#define _MD_LSEEK64(a,b,c) LL_ZERO
+#define _MD_GETOPENFILEINFO64(fd,info) -1
+#define _MD_GETFILEINFO64(fd,info) -1
+
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+** File Manipulation definitions
+*/
+
+#define _MD_RENAME _MD_Rename
+#define _MD_ACCESS _MD_Access
+
+#define _MD_GETFILEINFO _MD_GetFileInfo
+#define _MD_GETOPENFILEINFO _MD_GetOpenFileInfo
+
+#define _MD_STAT _MD_Stat
+
+#define _MD_DELETE _MD_Delete
+
+extern PRStatus _MD_LockFile(PRInt32 osfd);
+#define _MD_LOCKFILE _MD_LockFile
+extern PRStatus _MD_TLockFile(PRInt32 osfd);
+#define _MD_TLOCKFILE _MD_TLockFile
+extern PRStatus _MD_UnlockFile(PRInt32 osfd);
+#define _MD_UNLOCKFILE _MD_UnlockFile
+
+/*
+** Directory enumeration related definitions
+*/
+
+extern PRStatus _MD_OpenDir(struct _MDDir *md,const char *name);
+#define _MD_OPEN_DIR _MD_OpenDir
+
+extern char* _MD_ReadDir(struct _MDDir *md,PRIntn flags);
+#define _MD_READ_DIR _MD_ReadDir
+
+#define _MD_CLOSE_DIR _MD_CloseDir
+
+#define _MD_MKDIR _MD_MkDir
+#define _MD_MAKE_DIR _MD_MkDir
+#define _MD_RMDIR _MD_Delete
+
+/*
+** Pipe I/O Related definitions (not implemented)
+*/
+
+#define _MD_PIPEAVAILABLE(fd) -1
+
+/*
+** Socket I/O Related definitions
+*/
+
+#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
+/* In Universal Interfaces 3.3 and later, these are enums. */
+#define IP_TTL IP_TTL
+#define IP_TOS IP_TOS
+#define IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP
+#define IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP
+#define IP_MULTICAST_IF IP_MULTICAST_IF
+#define IP_MULTICAST_TTL IP_MULTICAST_TTL
+#define IP_MULTICAST_LOOP IP_MULTICAST_LOOP
+#define TCP_NODELAY TCP_NODELAY
+#define TCP_MAXSEG TCP_MAXSEG
+#endif
+
+#define _MD_SOCKET _MD_socket
+#define _MD_BIND _MD_bind
+#define _MD_LISTEN _MD_listen
+#define _MD_GETSOCKNAME _MD_getsockname
+
+extern PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen);
+#define _MD_GETSOCKOPT _MD_getsockopt
+
+extern PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen);
+#define _MD_SETSOCKOPT _MD_setsockopt
+
+#define _MD_SOCKETAVAILABLE _MD_socketavailable
+#define _MD_ACCEPT _MD_accept
+#define _MD_CONNECT _MD_connect
+#define _MD_SEND _MD_send
+#define _MD_RECV _MD_recv
+#define _MD_CLOSE_SOCKET _MD_closesocket
+#define _MD_SENDTO _MD_sendto
+#define _MD_RECVFROM _MD_recvfrom
+#define _MD_PR_POLL _MD_poll
+#define _MD_INIT_FILEDESC _MD_initfiledesc
+#define _MD_FREE_FILEDESC _MD_freefiledesc
+#define _MD_MAKE_NONBLOCK _MD_makenonblock
+#define _MD_INIT_FD_INHERITABLE _MD_initfdinheritable
+#define _MD_QUERY_FD_INHERITABLE _MD_queryfdinheritable
+
+#define _MD_GET_SOCKET_ERROR() _PR_MD_CURRENT_THREAD()->md.osErrCode
+
+#define _PR_MD_MAP_SELECT_ERROR(x) (x)
+/*
+** Netdb Related definitions
+*/
+extern PRStatus _MD_gethostname(char *name, int namelen);
+#define _MD_GETHOSTNAME _MD_gethostname
+#define _PR_GET_HOST_ADDR_AS_NAME
+
+/*
+ XXX _MD_WRITEV, _MD_SHUTDOWN & _MD_GETPEERNAME not done yet!!!
+*/
+#define _MD_WRITEV _MD_writev
+#define _MD_SHUTDOWN _MD_shutdown
+#define _MD_GETPEERNAME _MD_getpeername
+
+
+#ifdef OLD_MACSOCK_LIBRARY
+#define _MD_SOCKET macsock_socket
+#define _MD_LISTEN macsock_listen
+#define _MD_SEND(fd,buf,amount,flags,timeout) macsock_send(fd->secret->md.osfd,buf,amount,flags)
+#define _MD_SENDTO(fd,buf,amount,flags,addr,addrlen,timeout) macsock_sendto(fd->secret->md.osfd,buf,amount,flags,(struct sockaddr *)addr,addrlen)
+#define _MD_RECV(fd,buf,amount,flags,timeout) macsock_recv(fd->secret->md.osfd,buf,amount,flags)
+#define _MD_RECVFROM(fd,buf,amount,flags,addr,addrlen,timeout) macsock_recvfrom(fd->secret->md.osfd,buf,amount,flags,(struct sockaddr *)addr,addrlen)
+#define _MD_CLOSE_SOCKET macsock_close
+#define _MD_SHUTDOWN(a,b) (0)
+
+#define _MD_ACCEPT(fd,addr,addrlen,timeout) macsock_accept(fd->secret->md.osfd,(struct sockaddr *)addr,addrlen)
+#define _MD_CONNECT(fd,name,namelen,timeout) macsock_connect(fd->secret->md.osfd,(struct sockaddr *)name,namelen)
+#define _MD_BIND(fd,name,namelen) macsock_bind(fd->secret->md.osfd,(struct sockaddr *)name,namelen)
+#define _MD_GETSOCKNAME(fd,name,namelen) macsock_getsockname(fd->secret->md.osfd,(struct sockaddr *)name,namelen)
+#define _MD_GETPEERNAME(fd,name,namelen) macsock_getpeername(fd->secret->md.osfd,(struct sockaddr *)name,namelen)
+#define _MD_GETSOCKOPT(fd,level,optname,optval,optlen) macsock_getsockopt(fd->secret->md.osfd,level,optname,optval,optlen)
+#define _MD_SETSOCKOPT(fd,level,optname,optval,optlen) macsock_setsockopt(fd->secret->md.osfd,level,optname,optval,optlen)
+#define _MD_SOCKETAVAILABLE(fd,bytes) macsock_socketavailable(fd->secret->md.osfd,bytes)
+#endif
+
+/*
+** Memory Segements Related definitions
+*/
+
+#define _MD_INIT_SEGS()
+#define _MD_ALLOC_SEGMENT _MD_AllocSegment
+#define _MD_FREE_SEGMENT _MD_FreeSegment
+
+/*
+** Time Related definitions
+*/
+
+#define _MD_GET_INTERVAL _MD_GetInterval
+#define _MD_INTERVAL_PER_SEC() PR_MSEC_PER_SEC
+#define _MD_INTERVAL_INIT()
+
+/*
+** Environemnt Related definitions
+*/
+
+extern char *_MD_GetEnv(const char *name);
+#define _MD_GET_ENV _MD_GetEnv
+
+extern int _MD_PutEnv(const char *variableCopy);
+#define _MD_PUT_ENV _MD_PutEnv
+
+/*
+** Following is old stuff to be looked at.
+*/
+
+#define GCPTR
+#define CALLBACK
+typedef int (*FARPROC)();
+
+
+#define MAX_NON_PRIMARY_TIME_SLICES 6
+
+extern long gTimeSlicesOnNonPrimaryThread;
+extern struct PRThread *gPrimaryThread;
+
+// Errors not found in the Mac StdCLib
+#define EACCES 13 // Permission denied
+#define ENOENT -43 // No such file or directory
+#define _OS_INVALID_FD_VALUE -1
+
+#define STDERR_FILENO 2
+
+#if !defined(MAC_NSPR_STANDALONE)
+#define PATH_SEPARATOR ':'
+#define PATH_SEPARATOR_STR ":"
+#define DIRECTORY_SEPARATOR '/'
+#define DIRECTORY_SEPARATOR_STR "/"
+#endif
+
+#define UNIX_THIS_DIRECTORY_STR "./"
+#define UNIX_PARENT_DIRECTORY_STR "../"
+
+
+// Alias a few names
+#define getenv PR_GetEnv
+#define putenv _MD_PutEnv
+
+#if defined(MAC_NSPR_STANDALONE)
+typedef unsigned char (*MemoryCacheFlusherProc)(size_t size);
+typedef void (*PreAllocationHookProc)(void);
+
+extern char *strdup(const char *source);
+
+extern void InstallPreAllocationHook(PreAllocationHookProc newHook);
+extern void InstallMemoryCacheFlusher(MemoryCacheFlusherProc newFlusher);
+#endif
+
+extern char *PR_GetDLLSearchPath(void);
+
+#if defined(MAC_NSPR_STANDALONE)
+extern int strcmp(const char *str1, const char *str2);
+extern int strcasecmp(const char *str1, const char *str2);
+#endif
+
+extern void MapFullToPartialMacFile(char *);
+extern char *MapPartialToFullMacFile(const char *);
+
+extern void ResetTimer(void);
+extern void PR_PeriodicIdle(void);
+extern void ActivateTimer(void);
+extern void DeactivateTimer(void);
+extern void PR_InitMemory(void);
+
+extern struct hostent *gethostbyaddr(const void *addr, int addrlen, int type);
+
+extern short GetVolumeRefNumFromName(const char *);
+
+#include <stdio.h> // Needed to get FILE typedef
+extern FILE *_OS_FOPEN(const char *filename, const char *mode);
+//
+// Macintosh only private parts.
+//
+
+#define dprintTrace ";dprintf;doTrace"
+#define dprintNoTrace ";dprintf"
+extern void dprintf(const char *format, ...);
+
+
+// Entry into the memory system's cache flushing
+#if defined(MAC_NSPR_STANDALONE)
+extern PRUint8 CallCacheFlushers(size_t blockSize);
+#endif
+
+#if defined(MAC_NSPR_STANDALONE)
+extern void* reallocSmaller(void* block, size_t newSize);
+#endif
+
+
+/*
+** PR_GetSystemInfo related definitions
+*/
+#define _PR_SI_SYSNAME "MacOS"
+#define _PR_SI_ARCHITECTURE "PowerPC"
+
+/*
+ * Memory-mapped files
+ */
+
+struct _MDFileMap {
+ PRInt8 unused;
+};
+
+extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
+#define _MD_CREATE_FILE_MAP _MD_CreateFileMap
+
+extern PRInt32 _MD_GetMemMapAlignment(void);
+#define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment
+
+extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
+ PRUint32 len);
+#define _MD_MEM_MAP _MD_MemMap
+
+extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
+#define _MD_MEM_UNMAP _MD_MemUnmap
+
+extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
+#define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
+
+extern void SetLogFileTypeCreator(const char *logFile);
+extern int _MD_mac_get_nonblocking_connect_error(PRFileDesc* fd);
+
+
+/*
+ * Critical section support
+ */
+
+#define MAC_CRITICAL_REGIONS TARGET_CARBON
+
+#if MAC_CRITICAL_REGIONS
+
+extern void InitCriticalRegion();
+extern void TermCriticalRegion();
+
+extern void EnterCritialRegion();
+extern void LeaveCritialRegion();
+
+#define INIT_CRITICAL_REGION() InitCriticalRegion()
+#define TERM_CRITICAL_REGION() TermCriticalRegion()
+
+#define ENTER_CRITICAL_REGION() EnterCritialRegion()
+#define LEAVE_CRITICAL_REGION() LeaveCritialRegion()
+
+#else
+
+#define INIT_CRITICAL_REGION()
+#define TERM_CRITICAL_REGION()
+
+#define ENTER_CRITICAL_REGION()
+#define LEAVE_CRITICAL_REGION()
+
+#endif
+
+
+
+/*
+ * CPU Idle support
+ */
+
+extern void InitIdleSemaphore();
+extern void TermIdleSemaphore();
+
+extern void WaitOnIdleSemaphore();
+extern void SignalIdleSemaphore();
+
+
+/*
+ * Atomic operations
+ */
+#ifdef _PR_HAVE_ATOMIC_OPS
+
+extern PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval);
+
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(val) OTAtomicAdd32(1, (SInt32 *)val)
+#define _MD_ATOMIC_ADD(ptr, val) OTAtomicAdd32(val, (SInt32 *)ptr)
+#define _MD_ATOMIC_DECREMENT(val) OTAtomicAdd32(-1, (SInt32 *)val)
+#define _MD_ATOMIC_SET(val, newval) _MD_AtomicSet(val, newval)
+
+#endif /* _PR_HAVE_ATOMIC_OPS */
+
+
+#endif /* prmacos_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.cfg
new file mode 100644
index 00000000..c8a32bfb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.cfg
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef NCR
+#define NCR
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.h
new file mode 100644
index 00000000..d094c2ee
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_ncr.h
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_unixware_defs_h___
+#define nspr_unixware_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "ncr"
+#define _PR_SI_SYSNAME "NCR"
+#define _PR_SI_ARCHITECTURE "x86"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_RECV_BROKEN /* recv doesn't work on Unix Domain Sockets */
+
+#if !defined (HAVE_STRERROR)
+#define HAVE_STRERROR
+#endif
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_NO_LARGE_FILES
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_NETCONFIG
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define NEED_LOCALTIME_R
+#define NEED_GMTIME_R
+#define NEED_ASCTIME_R
+#define NEED_STRTOK_R
+#define NEED_CTIME_R
+#define _PR_NEED_STRCASECMP
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _SETJMP setjmp
+#define _LONGJMP longjmp
+#define _PR_CONTEXT_TYPE jmp_buf
+#define _MD_GET_SP(_t) (_t)->md.context[4]
+#define _PR_NUM_GCREGS _JBLEN
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!_SETJMP(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _LONGJMP(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures.
+ * Don't use SVR4 native threads (yet).
+ */
+
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+ * The following are copied from _sunos.h, _aix.h. This means
+ * some of them should probably be moved into _unixos.h. But
+ * _irix.h seems to be quite different in regard to these macros.
+ */
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *execptfds, struct timeval *timeout);
+#define _MD_SELECT _select
+
+#define _MD_POLL _poll
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+
+#endif /* nspr_ncr_defs_h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.cfg
new file mode 100644
index 00000000..558a5251
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.cfg
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef NEC
+#define NEC
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.h
new file mode 100644
index 00000000..ed7e8a36
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nec.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_nec_defs_h___
+#define nspr_nec_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "nec"
+#define _PR_SI_SYSNAME "NEC"
+#define _PR_SI_ARCHITECTURE "mips"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_TIME_R
+#define NEED_STRFTIME_LOCK
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ST_ATIM_UNION
+
+#include <ucontext.h>
+#include <sys/regset.h>
+
+#define PR_NUM_GCREGS NGREG
+#define PR_CONTEXT_TYPE ucontext_t
+
+#define CONTEXT(_thread) (&(_thread)->md.context)
+
+#define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gregs[CXT_SP]
+
+/*
+** Initialize the thread context preparing it to execute "e(o,a)"
+*/
+#define _MD_INIT_CONTEXT(thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ getcontext(CONTEXT(thread)); \
+ CONTEXT(thread)->uc_stack.ss_sp = (char*) (thread)->stack->stackBottom; \
+ CONTEXT(thread)->uc_stack.ss_size = (thread)->stack->stackSize; \
+ _MD_GET_SP(thread) = (greg_t) _sp - 64; \
+ makecontext(CONTEXT(thread), _main, 0); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!getcontext(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ ucontext_t *uc = CONTEXT(_thread); \
+ uc->uc_mcontext.gregs[CXT_V0] = 1; \
+ uc->uc_mcontext.gregs[CXT_A3] = 0; \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ setcontext(uc); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+#define _MD_SELECT _select
+#define _MD_POLL _poll
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#endif /* nspr_nec_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.cfg
new file mode 100644
index 00000000..09457192
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.cfg
@@ -0,0 +1,289 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef NETBSD
+#define NETBSD
+#endif
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#if defined(__i386__) || defined(__arm32__) || defined(__MIPSEL__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__sparc__) || defined(__MIPSEB__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__alpha__) || defined(__x86_64__)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__powerpc__) || defined(__m68k__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#else
+
+#error Must define constants for type sizes here.
+
+#endif
+
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.h
new file mode 100644
index 00000000..cc16f105
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_netbsd.h
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-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.
+ */
+
+#ifndef nspr_netbsd_defs_h___
+#define nspr_netbsd_defs_h___
+
+#include <sys/syscall.h>
+#include <sys/param.h> /* for __NetBSD_Version__ */
+
+#define PR_LINKER_ARCH "netbsd"
+#define _PR_SI_SYSNAME "NetBSD"
+#if defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__alpha__)
+#define _PR_SI_ARCHITECTURE "alpha"
+#elif defined(__m68k__)
+#define _PR_SI_ARCHITECTURE "m68k"
+#elif defined(__powerpc__)
+#define _PR_SI_ARCHITECTURE "powerpc"
+#elif defined(__sparc_v9__)
+#define _PR_SI_ARCHITECTURE "sparc64"
+#elif defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#elif defined(__mips__)
+#define _PR_SI_ARCHITECTURE "mips"
+#elif defined(__arm32__) || defined(__arm__) || defined(__armel__) \
+ || defined(__armeb__)
+#define _PR_SI_ARCHITECTURE "arm"
+#endif
+
+#if defined(__ELF__)
+#define PR_DLL_SUFFIX ".so"
+#else
+#define PR_DLL_SUFFIX ".so.1.0"
+#endif
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_HAVE_SYSV_SEMAPHORES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+
+#if __NetBSD_Version__ >= 105000000
+#define _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#endif
+
+#if __NetBSD_Version__ >= 106370000
+/* NetBSD 1.6ZK */
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_GETPROTO_R_INT
+#endif
+
+#define USE_SETJMP
+
+#ifndef _PR_PTHREADS
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE sigjmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#ifdef __i386__
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[2] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[0] = (int) _main; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[2]
+#endif
+#ifdef __sparc_v9__
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[1] = (unsigned char*) ((_sp) - 176 - 0x7ff); \
+ CONTEXT(_thread)[2] = (long) _main; \
+ CONTEXT(_thread)[3] = (long) _main + 4; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) (CONTEXT(_thread)[2]+0x7ff)
+#elif defined(__sparc__)
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[2] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[3] = (int) _main; \
+ CONTEXT(_thread)[4] = (int) _main + 4; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[2]
+#endif
+#ifdef __powerpc__
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[3] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[4] = (int) _main; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[3]
+#endif
+#ifdef __m68k__
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[2] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[5] = (int) _main; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[2]
+#endif
+#ifdef __mips__
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[32] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[2] = (int) _main; \
+ CONTEXT(_thread)[28] = (int) _main; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[32]
+#endif
+#if defined(__arm32__) || defined(__arm__) || defined(__armel__) \
+ || defined(__armeb__)
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[23] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[24] = (int) _main; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[23]
+#endif
+#ifdef __alpha__
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ sigsetjmp(CONTEXT(_thread), 1); \
+ CONTEXT(_thread)[34] = (unsigned char*) ((_sp) - 128); \
+ CONTEXT(_thread)[2] = (long) _main; \
+ CONTEXT(_thread)[30] = (long) _main; \
+ CONTEXT(_thread)[31] = (long) _main; \
+ *status = PR_TRUE; \
+}
+#define _MD_GET_SP(_thread) CONTEXT(_thread)[34]
+#endif
+#ifndef _MD_INIT_CONTEXT
+#error "Need to define _MD_INIT_CONTEXT for this platform"
+#endif
+
+#define PR_NUM_GCREGS _JBLEN
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!sigsetjmp(CONTEXT(_thread), 1)) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ siglongjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+#endif /* ! _PR_PTHREADS */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+#if defined(_PR_POLL_AVAILABLE)
+#include <poll.h>
+#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
+#endif
+
+#if NetBSD1_3 == 1L
+typedef unsigned int nfds_t;
+#endif
+
+#endif /* nspr_netbsd_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.cfg
new file mode 100644
index 00000000..ce623cb9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.cfg
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef NEXTSTEP
+#define NEXTSTEP
+#endif
+
+/* Platform specific
+*/
+#if defined(__sparc__)
+
+/* Check these
+*/
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+/* Taken from _solaris.cfg
+*/
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+/* Taken from _solaris.cfg
+*/
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+/* Taken from _solaris.cfg
+*/
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_WORDS_PER_DWORD_LOG2 1
+
+#elif defined(__m68k__)
+
+/* Check these
+*/
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 2
+#define PR_ALIGN_OF_LONG 2
+#define PR_ALIGN_OF_INT64 2
+#define PR_ALIGN_OF_FLOAT 2
+#define PR_ALIGN_OF_DOUBLE 2
+#define PR_ALIGN_OF_POINTER 2
+
+#define PR_WORDS_PER_DWORD_LOG2 1
+
+#elif defined(__i386__)
+
+/* Check these
+*/
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+#define PR_WORDS_PER_DWORD_LOG2 1
+#endif /* defined(__somearch__) */
+
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.h
new file mode 100644
index 00000000..e7e4c055
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nextstep.h
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_nextstep_defs_h___
+#define nspr_nextstep_defs_h___
+
+#include "prthread.h"
+
+#include <bsd/libc.h>
+#include <bsd/syscall.h>
+
+/* syscall() is not declared in NEXTSTEP's syscall.h ...
+*/
+extern int syscall(int number, ...);
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "nextstep"
+#define _PR_SI_SYSNAME "NEXTSTEP"
+#if defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#elif defined(__m68k__)
+#define _PR_SI_ARCHITECTURE "m68k"
+#elif defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#else
+error Unknown NEXTSTEP architecture
+#endif
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+
+#define HAVE_WEAK_MALLOC_SYMBOLS
+
+#define HAVE_DLL
+#define USE_MACH_DYLD
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#define _PR_NO_LARGE_FILES
+
+#define USE_SETJMP
+
+#ifndef _PR_PTHREADS
+
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE jmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/* balazs.pataki@sztaki.hu:
+** __sparc__ is checked
+** __m68k__ is checked
+** __i386__ is a guess (one of the two defines should work)
+*/
+#if defined(__sparc__)
+#define _MD_GET_SP(_th) (_th)->md.context[2]
+#elif defined(__m68k__)
+#define _MD_GET_SP(_th) (_th)->md.context[2]
+#elif defined(__i386__)
+/* One of this two must be OK ... try using sc_onstack
+*/
+#define _MD_GET_SP(_th) (((struct sigcontext *) (_th)->md.context)->sc_onstack)
+//#define _MD_GET_SP(_th) (_th)->md.context[0].sc_esp
+#else
+error Unknown NEXTSTEP architecture
+#endif
+
+#define PR_NUM_GCREGS _JBLEN
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+extern PRStatus _MD_InitializeThread(PRThread *thread);
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+extern PRStatus _MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
+extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
+extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
+extern void _MD_YIELD(void);
+
+#endif /* ! _PR_PTHREADS */
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+
+/* For writev() */
+#include <sys/uio.h>
+
+/* signal.h */
+/* balazs.pataki@sztaki.hu: this is stolen from sunos4.h. The things is that
+** NEXTSTEP doesn't support these flags for `struct sigaction's sa_flags, so
+** I have to fake them ...
+*/
+#define SA_RESTART 0
+
+/* mmap */
+/* balazs.pataki@sztaki.hu: NEXTSTEP doesn't have mmap, at least not
+** publically. We have sys/mman.h, but it doesn't declare mmap(), and
+** PROT_NONE is also missing. syscall.h has entries for mmap, munmap, and
+** mprotect so I wrap these in nextstep.c as mmap(), munmap() and mprotect()
+** and pray for it to work.
+**
+*/
+caddr_t mmap(caddr_t addr, size_t len, int prot, int flags,
+ int fildes, off_t off);
+int munmap(caddr_t addr, size_t len);
+int mprotect(caddr_t addr, size_t len, int prot);
+
+/* my_mmap() is implemented in nextstep.c and is based on map_fd() of mach.
+*/
+caddr_t my_mmap(caddr_t addr, size_t len, int prot, int flags,
+ int fildes, off_t off);
+int my_munmap(caddr_t addr, size_t len);
+
+
+/* string.h
+*/
+/* balazs.pataki@sztaki.hu: this is missing so implemenetd in nextstep.c ...
+*/
+char *strdup(const char *s1);
+
+/* unistd.h
+*/
+/* balazs.pataki@sztaki.hu: these functions are hidden, though correctly
+** implemented in NEXTSTEP. Here I give the declaration for them to be used
+** by prmalloc.c, and I have a wrapped syscall() version of them in nextstep.c
+*/
+int brk(void *endds);
+void *sbrk(int incr);
+
+#endif /* nspr_nextstep_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nspr_pthread.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nspr_pthread.h
new file mode 100644
index 00000000..b7a0481e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nspr_pthread.h
@@ -0,0 +1,283 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_pthread_defs_h___
+#define nspr_pthread_defs_h___
+
+#include <pthread.h>
+#include "prthread.h"
+
+#if defined(PTHREADS_USER)
+/*
+** Thread Local Storage
+*/
+extern pthread_key_t current_thread_key;
+extern pthread_key_t current_cpu_key;
+extern pthread_key_t last_thread_key;
+extern pthread_key_t intsoff_key;
+
+#define _MD_CURRENT_THREAD() \
+ ((struct PRThread *) pthread_getspecific(current_thread_key))
+#define _MD_CURRENT_CPU() \
+ ((struct _PRCPU *) pthread_getspecific(current_cpu_key))
+#define _MD_LAST_THREAD() \
+ ((struct PRThread *) pthread_getspecific(last_thread_key))
+
+#define _MD_SET_CURRENT_THREAD(newval) \
+ pthread_setspecific(current_thread_key, (void *)newval)
+
+#define _MD_SET_CURRENT_CPU(newval) \
+ pthread_setspecific(current_cpu_key, (void *)newval)
+
+#define _MD_SET_LAST_THREAD(newval) \
+ pthread_setspecific(last_thread_key, (void *)newval)
+
+#define _MD_SET_INTSOFF(_val)
+#define _MD_GET_INTSOFF() 1
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ if (SAVE_CONTEXT(_thread)) { \
+ (*_main)(); \
+ } \
+ _MD_SET_THR_SP(_thread, _sp); \
+ _thread->no_sched = 0; \
+ PR_END_MACRO
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ PR_ASSERT(_thread->no_sched); \
+ if (!SAVE_CONTEXT(_thread)) { \
+ (_thread)->md.errcode = errno; \
+ _MD_SET_LAST_THREAD(_thread); \
+ _PR_Schedule(); \
+ } else { \
+ (_MD_LAST_THREAD())->no_sched = 0; \
+ } \
+ PR_END_MACRO
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _thread->no_sched = 1; \
+ GOTO_CONTEXT(_thread); \
+ PR_END_MACRO
+
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ jmp_buf jb;
+ int id;
+ int errcode;
+ pthread_t pthread;
+ pthread_mutex_t pthread_mutex;
+ pthread_cond_t pthread_cond;
+ int wait;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ pthread_mutex_t mutex;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ pthread_mutex_t mutex;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ jmp_buf jb;
+ pthread_t pthread;
+ struct _MDCPU_Unix md_unix;
+};
+
+/*
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+*/
+
+extern pthread_mutex_t _pr_heapLock;
+
+#define _PR_LOCK(lock) pthread_mutex_lock(lock)
+
+#define _PR_UNLOCK(lock) pthread_mutex_unlock(lock)
+
+
+#define _PR_LOCK_HEAP() { \
+ if (_pr_primordialCPU) { \
+ _PR_LOCK(_pr_heapLock); \
+ }
+
+#define _PR_UNLOCK_HEAP() if (_pr_primordialCPU) { \
+ _PR_UNLOCK(_pr_heapLock); \
+ } \
+ }
+
+NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md);
+NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp);
+
+#define _MD_LOCK(_lockp) _PR_LOCK(&(_lockp)->mutex)
+#define _MD_UNLOCK(_lockp) _PR_UNLOCK(&(_lockp)->mutex)
+
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+#define _MD_CHECK_FOR_EXIT()
+
+NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread);
+#define _MD_INIT_THREAD _MD_InitThread
+#define _MD_INIT_ATTACHED_THREAD _MD_InitThread
+
+NSPR_API(void) _MD_ExitThread(struct PRThread *thread);
+#define _MD_EXIT_THREAD _MD_ExitThread
+
+NSPR_API(void) _MD_SuspendThread(struct PRThread *thread);
+#define _MD_SUSPEND_THREAD _MD_SuspendThread
+
+NSPR_API(void) _MD_ResumeThread(struct PRThread *thread);
+#define _MD_RESUME_THREAD _MD_ResumeThread
+
+NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread);
+#define _MD_SUSPEND_CPU _MD_SuspendCPU
+
+NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread);
+#define _MD_RESUME_CPU _MD_ResumeCPU
+
+#define _MD_BEGIN_SUSPEND_ALL()
+#define _MD_END_SUSPEND_ALL()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_RESUME_ALL()
+
+NSPR_API(void) _MD_EarlyInit(void);
+#define _MD_EARLY_INIT _MD_EarlyInit
+
+#define _MD_FINAL_INIT _PR_UnixInit
+
+NSPR_API(void) _MD_InitLocks(void);
+#define _MD_INIT_LOCKS _MD_InitLocks
+
+NSPR_API(void) _MD_CleanThread(struct PRThread *thread);
+#define _MD_CLEAN_THREAD _MD_CleanThread
+
+NSPR_API(PRStatus) _MD_CreateThread(
+ struct PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+#define _MD_CREATE_THREAD _MD_CreateThread
+
+extern void _MD_CleanupBeforeExit(void);
+#define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit
+
+NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu);
+#define _MD_INIT_RUNNING_CPU _MD_InitRunningCPU
+
+/* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and
+ * awaken a thread which is waiting on a lock or cvar.
+ */
+NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout);
+#define _MD_WAIT _MD_wait
+
+NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *);
+#define _MD_WAKEUP_WAITER _MD_WakeupWaiter
+
+NSPR_API(void) _MD_SetPriority(struct _MDThread *thread,
+ PRThreadPriority newPri);
+#define _MD_SET_PRIORITY _MD_SetPriority
+
+#endif /* PTHREADS_USER */
+
+#endif /* nspr_pthread_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.cfg
new file mode 100644
index 00000000..76635729
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.cfg
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef NTO
+#define NTO
+#endif
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#ifdef __i386__
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1L
+#define PR_BYTES_PER_SHORT 2L
+#define PR_BYTES_PER_INT 4L
+#define PR_BYTES_PER_INT64 8L
+#define PR_BYTES_PER_LONG 4L
+#define PR_BYTES_PER_FLOAT 4L
+#define PR_BYTES_PER_DOUBLE 8L
+#define PR_BYTES_PER_WORD 4L
+#define PR_BYTES_PER_DWORD 8L
+
+#define PR_BITS_PER_BYTE 8L
+#define PR_BITS_PER_SHORT 16L
+#define PR_BITS_PER_INT 32L
+#define PR_BITS_PER_INT64 64L
+#define PR_BITS_PER_LONG 32L
+#define PR_BITS_PER_FLOAT 32L
+#define PR_BITS_PER_DOUBLE 64L
+#define PR_BITS_PER_WORD 32L
+
+#define PR_BITS_PER_BYTE_LOG2 3L
+#define PR_BITS_PER_SHORT_LOG2 4L
+#define PR_BITS_PER_INT_LOG2 5L
+#define PR_BITS_PER_INT64_LOG2 6L
+#define PR_BITS_PER_LONG_LOG2 5L
+#define PR_BITS_PER_FLOAT_LOG2 5L
+#define PR_BITS_PER_DOUBLE_LOG2 6L
+#define PR_BITS_PER_WORD_LOG2 5L
+
+#define PR_ALIGN_OF_SHORT 2L
+#define PR_ALIGN_OF_INT 4L
+#define PR_ALIGN_OF_LONG 4L
+#define PR_ALIGN_OF_INT64 4L
+#define PR_ALIGN_OF_FLOAT 4L
+#define PR_ALIGN_OF_DOUBLE 4L
+#define PR_ALIGN_OF_POINTER 4L
+#define PR_ALIGN_OF_WORD 4L
+
+#define PR_BYTES_PER_WORD_LOG2 2L
+#define PR_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 1L
+
+#else
+
+#error Undefined CPU Architecture
+
+#endif
+
+#define HAVE_LONG_LONG
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.h
new file mode 100644
index 00000000..97f4d38f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_nto.h
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_nto_defs_h___
+#define nspr_nto_defs_h___
+
+/*
+** Internal configuration macros
+*/
+#define PR_LINKER_ARCH "nto"
+#define _PR_SI_SYSNAME "NTO"
+#define _PR_SI_ARCHITECTURE "x86"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MINIMUM_STACK_SIZE 131072L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+
+#undef _PR_POLL_AVAILABLE
+#undef _PR_USE_POLL
+#define _PR_HAVE_SOCKADDR_LEN
+#undef HAVE_BSD_FLOCK
+#define HAVE_FCNTL_FILE_LOCKING
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+#define _PR_HAVE_POSIX_SEMAPHORES
+
+#undef FD_SETSIZE
+#define FD_SETSIZE 4096
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define _PR_NEED_STRCASECMP
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR
+#endif
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _SETJMP setjmp
+#define _LONGJMP longjmp
+#define _PR_CONTEXT_TYPE jmp_buf
+#define _PR_NUM_GCREGS _JBLEN
+#define _MD_GET_SP(_t) (_t)->md.context[7]
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!_SETJMP(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _LONGJMP(CONTEXT(_thread), 1); \
+}
+
+/*
+** Machine-dependent (MD) data structures.
+*/
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+** md-specific cpu structure field
+*/
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD], fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/*
+** We wrapped the select() call. _MD_SELECT refers to the built-in,
+** unwrapped version.
+*/
+#define _MD_SELECT select
+
+#define SA_RESTART 0
+
+#endif /* nspr_nto_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.cfg
new file mode 100644
index 00000000..0041a242
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.cfg
@@ -0,0 +1,387 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef OPENBSD
+#define OPENBSD
+#endif
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#if defined(__i386__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__amd64__)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#elif defined(__sparc_v9__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__sparc__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#elif defined(__alpha__)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#define IS_64
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__powerpc__) || defined(__m68k__)
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#else
+
+#error Must define constants for type sizes here.
+
+#endif
+
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.h
new file mode 100644
index 00000000..ccd75306
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openbsd.h
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_openbsd_defs_h___
+#define nspr_openbsd_defs_h___
+
+#include <sys/syscall.h>
+
+#define PR_LINKER_ARCH "openbsd"
+#define _PR_SI_SYSNAME "OPENBSD"
+#if defined(__i386__)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__alpha__)
+#define _PR_SI_ARCHITECTURE "alpha"
+#elif defined(__amd64__)
+#define _PR_SI_ARCHITECTURE "amd64"
+#elif defined(__m68k__)
+#define _PR_SI_ARCHITECTURE "m68k"
+#elif defined(__powerpc__)
+#define _PR_SI_ARCHITECTURE "powerpc"
+#elif defined(__sparc__)
+#define _PR_SI_ARCHITECTURE "sparc"
+#endif
+
+#define PR_DLL_SUFFIX ".so.1.0"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_HAVE_SYSV_SEMAPHORES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+
+#define _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#define _PR_HAVE_GETHOSTBYNAME2
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+
+#define USE_SETJMP
+
+#ifndef _PR_PTHREADS
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE sigjmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+#if defined(__i386__) || defined(__sparc__) || defined(__m68k__)
+#define JB_SP_INDEX 2
+#elif defined(__powerpc__)
+#define JB_SP_INDEX 1
+#elif defined(__alpha__)
+#define JB_SP_INDEX 34
+#elif defined(__amd64__)
+#define JB_SP_INDEX 6
+#else
+#error "Need to define SP index in jmp_buf here"
+#endif
+#define _MD_GET_SP(_th) (_th)->md.context[JB_SP_INDEX]
+
+#define PR_NUM_GCREGS _JBLEN
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (sigsetjmp(CONTEXT(_thread), 1)) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!sigsetjmp(CONTEXT(_thread), 1)) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ siglongjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+#endif /* ! _PR_PTHREADS */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+#include <poll.h>
+#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
+
+#if OpenBSD1_3 == 1L
+typedef unsigned int nfds_t;
+#endif
+
+#endif /* nspr_openbsd_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.cfg
new file mode 100644
index 00000000..84c2a9d4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.cfg
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef VMS
+#define VMS
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#ifdef IS_64
+#undef IS_64
+#endif
+
+#define PR_AF_INET6 26 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.h
new file mode 100644
index 00000000..1ee7e428
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_openvms.h
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** This is the OpenVMS machine dependant configuration file. It is based
+** on the OSF/1 machine dependant file.
+*/
+
+#ifndef nspr_openvms_defs_h___
+#define nspr_openvms_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "OpenVMS"
+#define _PR_SI_SYSNAME "OpenVMS"
+#ifdef __alpha
+#define _PR_SI_ARCHITECTURE "alpha"
+#else
+#define _PR_SI_ARCHITECTURE "vax"
+#endif
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 131072L
+#define _MD_MINIMUM_STACK_SIZE 131072L
+
+/*
+** This is not defined on OpenVMS. I believe its only used in GC code, and
+** isn't that only used in Java? Anyway, for now, let's keep the compiler
+** happy.
+*/
+#define SA_RESTART 0
+
+/*
+** OpenVMS doesn't have these in socket.h.
+** Does in later versions!
+*/
+#if 0
+struct ip_mreq {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+#endif
+
+/*
+ * OSF1 needs the MAP_FIXED flag to ensure that mmap returns a pointer
+ * with the upper 32 bits zero. This is because Java sticks a pointer
+ * into an int.
+ */
+#define _MD_MMAP_FLAGS MAP_PRIVATE|MAP_FIXED
+
+#undef HAVE_STACK_GROWING_UP
+#undef HAVE_WEAK_IO_SYMBOLS
+#undef HAVE_WEAK_MALLOC_SYMBOLS
+#undef HAVE_BSD_FLOCK
+
+#define NEED_TIME_R
+
+#define HAVE_DLL
+#define USE_DLFCN
+
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#define _PR_NO_LARGE_FILES
+#define _PR_STRICT_ADDR_LEN
+
+/* IPv6 support */
+#ifdef _SOCKADDR_LEN
+#define _PR_HAVE_SOCKADDR_LEN
+#endif
+#define _PR_HAVE_GETIPNODEBYNAME
+#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#ifdef _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#else
+#define AF_INET6 26
+#ifndef AI_CANONNAME
+#define AI_CANONNAME 0x00000002
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#endif
+#define AI_V4MAPPED 0x00000010
+#define AI_ALL 0x00000008
+#define AI_ADDRCONFIG 0x00000020
+#endif
+
+#define _PR_HAVE_MD_SOCKADDR_IN6
+/* if we have a quadword field defined in the structure, then its length */
+/* will be a multiple of 8, and connect() won't accept 32 (it wants 28) */
+struct _md_in6_addr {
+ union {
+ PRUint8 _S6_u8[16];
+ PRUint16 _S6_u16[8];
+ PRUint32 _S6_u32[4];
+ } _S6_un;
+};
+struct _md_sockaddr_in6 {
+ PRUint16 sin6_family;
+ PRUint16 sin6_port;
+ PRUint32 sin6_flowinfo;
+ struct _md_in6_addr sin6_addr;
+ PRUint32 sin6_scope_id;
+};
+
+#undef USE_SETJMP
+
+#include <setjmp.h>
+
+/*
+ * A jmp_buf is actually a struct sigcontext. The sc_sp field of
+ * struct sigcontext is the stack pointer.
+ */
+#define _MD_GET_SP(_t) (((struct sigcontext *) (_t)->md.context)->sc_sp)
+#define PR_NUM_GCREGS _JBLEN
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** I am ifdef'ing these out because that's the way they are in FT.
+*/
+#ifndef __VMS
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ (*_main)(); \
+ } \
+ _MD_GET_SP(_thread) = (long) ((_sp) - 64); \
+ _MD_GET_SP(_thread) &= ~15; \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+#endif /* __VMS */
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ jmp_buf context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#ifndef _PR_PTHREADS
+#define _MD_INIT_LOCKS()
+#endif
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+ * The following are copied from _sunos.h, _aix.h. This means
+ * some of them should probably be moved into _unixos.h. But
+ * _irix.h seems to be quite different in regard to these macros.
+ */
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+void _MD_EarlyInit(void);
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#ifdef _VMS_NOT_YET
+NSPR_API(void) _PR_InitThreads(
+ PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs);
+#endif
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/* The following defines unwrapped versions of select() and poll(). */
+extern int __select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
+#define _MD_SELECT __select
+
+#ifndef __VMS
+#define _MD_POLL __poll
+extern int __poll(struct pollfd filedes[], unsigned int nfds, int timeout);
+#endif
+
+#ifdef __VMS
+NSPR_API(void) _PR_InitCPUs(void);
+NSPR_API(void) _PR_MD_START_INTERRUPTS(void);
+#endif
+
+/*
+ * Atomic operations
+ */
+#include <machine/builtins.h>
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_ADD(ptr,val) (__ATOMIC_ADD_LONG(ptr,val) + val)
+#define _MD_ATOMIC_INCREMENT(val) (__ATOMIC_INCREMENT_LONG(val) + 1)
+#define _MD_ATOMIC_DECREMENT(val) (__ATOMIC_DECREMENT_LONG(val) - 1)
+#define _MD_ATOMIC_SET(val, newval) __ATOMIC_EXCH_LONG(val, newval)
+
+extern int thread_suspend(PRThread *thr_id);
+extern int thread_resume(PRThread *thr_id);
+
+#endif /* nspr_openvms_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.cfg
new file mode 100644
index 00000000..55bcf93b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.cfg
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_PC
+#define XP_PC
+#endif
+
+#ifndef XP_OS2
+#define XP_OS2
+#endif
+
+#ifndef OS2
+#define OS2
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#ifdef NO_LONG_LONG
+#undef HAVE_LONG_LONG
+#else
+#define HAVE_LONG_LONG 1
+#endif
+
+#define PR_AF_INET6 24 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+#define PR_BITS_PER_DOUBLE 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_WORD_LOG2 5
+#define PR_BITS_PER_DWORD_LOG2 6
+#define PR_BITS_PER_DOUBLE_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_WORD 4
+#define PR_ALIGN_OF_DWORD 8
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 2
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.h
new file mode 100644
index 00000000..d72af0e5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2.h
@@ -0,0 +1,601 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_os2_defs_h___
+#define nspr_os2_defs_h___
+
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#define INCL_WPS
+#include <os2.h>
+#include <sys/select.h>
+
+#include "prio.h"
+
+#include <errno.h>
+
+#ifdef XP_OS2_VACPP
+/* TODO RAMSEMs need to be written for GCC/EMX */
+#define USE_RAMSEM
+#endif
+
+#ifdef USE_RAMSEM
+#pragma pack(4)
+
+#pragma pack(2)
+typedef struct _RAMSEM
+{
+ ULONG ulTIDPID;
+ ULONG hevSem;
+ ULONG cLocks;
+ USHORT cWaiting;
+ USHORT cPosts;
+} RAMSEM, *PRAMSEM;
+
+typedef struct _CRITICAL_SECTION
+{
+ ULONG ulReserved[4]; /* Same size as RAMSEM */
+} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION;
+#pragma pack(4)
+
+APIRET _Optlink SemRequest486(PRAMSEM, ULONG);
+APIRET _Optlink SemReleasex86(PRAMSEM, ULONG);
+#endif
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "os2"
+#define _PR_SI_SYSNAME "OS2"
+#define _PR_SI_ARCHITECTURE "x86" /* XXXMB hardcode for now */
+
+#define HAVE_DLL
+#define _PR_GLOBAL_THREADS_ONLY
+#undef HAVE_THREAD_AFFINITY
+#define _PR_HAVE_THREADSAFE_GETHOST
+#define _PR_HAVE_ATOMIC_OPS
+#ifndef TCPV40HDRS /* bird */
+#define _PR_HAVE_SOCKADDR_LEN /* bird */
+#endif /* bird */
+
+#define HANDLE unsigned long
+#define HINSTANCE HMODULE
+
+/* --- Common User-Thread/Native-Thread Definitions --------------------- */
+
+/* --- Globals --- */
+extern struct PRLock *_pr_schedLock;
+
+/* --- Typedefs --- */
+typedef void (*FiberFunc)(void *);
+
+#define PR_NUM_GCREGS 8
+typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS];
+#define GC_VMBASE 0x40000000
+#define GC_VMLIMIT 0x00FFFFFF
+typedef int (*FARPROC)();
+
+#define _MD_MAGIC_THREAD 0x22222222
+#define _MD_MAGIC_THREADSTACK 0x33333333
+#define _MD_MAGIC_SEGMENT 0x44444444
+#define _MD_MAGIC_DIR 0x55555555
+#define _MD_MAGIC_CV 0x66666666
+
+struct _MDSemaphore {
+ HEV sem;
+};
+
+struct _MDCPU {
+ int unused;
+};
+
+struct _MDThread {
+ HEV blocked_sema; /* Threads block on this when waiting
+ * for IO or CondVar.
+ */
+ PRBool inCVWaitQueue; /* PR_TRUE if the thread is in the
+ * wait queue of some cond var.
+ * PR_FALSE otherwise. */
+ TID handle; /* OS/2 thread handle */
+ void *sp; /* only valid when suspended */
+ PRUint32 magic; /* for debugging */
+ PR_CONTEXT_TYPE gcContext; /* Thread context for GC */
+ struct PRThread *prev, *next; /* used by the cvar wait queue to
+ * chain the PRThread structures
+ * together */
+};
+
+struct _MDThreadStack {
+ PRUint32 magic; /* for debugging */
+};
+
+struct _MDSegment {
+ PRUint32 magic; /* for debugging */
+};
+
+#undef PROFILE_LOCKS
+
+struct _MDDir {
+ HDIR d_hdl;
+ FILEFINDBUF3 d_entry;
+ PRBool firstEntry; /* Is this the entry returned
+ * by FindFirstFile()? */
+ PRUint32 magic; /* for debugging */
+};
+
+struct _MDCVar {
+ PRUint32 magic;
+ struct PRThread *waitHead, *waitTail; /* the wait queue: a doubly-
+ * linked list of threads
+ * waiting on this condition
+ * variable */
+ PRIntn nwait; /* number of threads in the
+ * wait queue */
+};
+
+#define _MD_CV_NOTIFIED_LENGTH 6
+typedef struct _MDNotified _MDNotified;
+struct _MDNotified {
+ PRIntn length; /* # of used entries in this
+ * structure */
+ struct {
+ struct _MDCVar *cv; /* the condition variable notified */
+ PRIntn times; /* and the number of times notified */
+ struct PRThread *notifyHead; /* list of threads to wake up */
+ } cv[_MD_CV_NOTIFIED_LENGTH];
+ _MDNotified *link; /* link to another of these, or NULL */
+};
+
+struct _MDLock {
+#ifdef USE_RAMSEM
+ CRITICAL_SECTION mutex; /* this is recursive on NT */
+#else
+ HMTX mutex; /* this is recursive on NT */
+#endif
+
+ /*
+ * When notifying cvars, there is no point in actually
+ * waking up the threads waiting on the cvars until we've
+ * released the lock. So, we temporarily record the cvars.
+ * When doing an unlock, we'll then wake up the waiting threads.
+ */
+ struct _MDNotified notified; /* array of conditions notified */
+#ifdef PROFILE_LOCKS
+ PRInt32 hitcount;
+ PRInt32 misscount;
+#endif
+};
+
+struct _MDFileDesc {
+ PRInt32 osfd; /* The osfd can come from one of three spaces:
+ * - For stdin, stdout, and stderr, we are using
+ * the libc file handle (0, 1, 2), which is an int.
+ * - For files and pipes, we are using OS/2 handles,
+ * which is a void*.
+ * - For sockets, we are using int
+ */
+};
+
+struct _MDProcess {
+ PID pid;
+};
+
+/* --- Misc stuff --- */
+#define _MD_GET_SP(thread) (thread)->md.gcContext[6]
+
+/* --- IO stuff --- */
+
+#define _MD_OPEN (_PR_MD_OPEN)
+#define _MD_OPEN_FILE (_PR_MD_OPEN)
+#define _MD_READ (_PR_MD_READ)
+#define _MD_WRITE (_PR_MD_WRITE)
+#define _MD_WRITEV (_PR_MD_WRITEV)
+#define _MD_LSEEK (_PR_MD_LSEEK)
+#define _MD_LSEEK64 (_PR_MD_LSEEK64)
+extern PRInt32 _MD_CloseFile(PRInt32 osfd);
+#define _MD_CLOSE_FILE _MD_CloseFile
+#define _MD_GETFILEINFO (_PR_MD_GETFILEINFO)
+#define _MD_GETFILEINFO64 (_PR_MD_GETFILEINFO64)
+#define _MD_GETOPENFILEINFO (_PR_MD_GETOPENFILEINFO)
+#define _MD_GETOPENFILEINFO64 (_PR_MD_GETOPENFILEINFO64)
+#define _MD_STAT (_PR_MD_STAT)
+#define _MD_RENAME (_PR_MD_RENAME)
+#define _MD_ACCESS (_PR_MD_ACCESS)
+#define _MD_DELETE (_PR_MD_DELETE)
+#define _MD_MKDIR (_PR_MD_MKDIR)
+#define _MD_MAKE_DIR (_PR_MD_MKDIR)
+#define _MD_RMDIR (_PR_MD_RMDIR)
+#define _MD_LOCKFILE (_PR_MD_LOCKFILE)
+#define _MD_TLOCKFILE (_PR_MD_TLOCKFILE)
+#define _MD_UNLOCKFILE (_PR_MD_UNLOCKFILE)
+
+/* --- Socket IO stuff --- */
+
+/* The ones that don't map directly may need to be re-visited... */
+#ifdef XP_OS2_VACPP
+#define EPIPE EBADF
+#define EIO ECONNREFUSED
+#endif
+#define _MD_EACCES EACCES
+#define _MD_EADDRINUSE EADDRINUSE
+#define _MD_EADDRNOTAVAIL EADDRNOTAVAIL
+#define _MD_EAFNOSUPPORT EAFNOSUPPORT
+#define _MD_EAGAIN EWOULDBLOCK
+#define _MD_EALREADY EALREADY
+#define _MD_EBADF EBADF
+#define _MD_ECONNREFUSED ECONNREFUSED
+#define _MD_ECONNRESET ECONNRESET
+#define _MD_EFAULT SOCEFAULT
+#define _MD_EINPROGRESS EINPROGRESS
+#define _MD_EINTR EINTR
+#define _MD_EINVAL EINVAL
+#define _MD_EISCONN EISCONN
+#define _MD_ENETUNREACH ENETUNREACH
+#define _MD_ENOENT ENOENT
+#define _MD_ENOTCONN ENOTCONN
+#define _MD_ENOTSOCK ENOTSOCK
+#define _MD_EOPNOTSUPP EOPNOTSUPP
+#define _MD_EWOULDBLOCK EWOULDBLOCK
+#define _MD_GET_SOCKET_ERROR() sock_errno()
+#ifndef INADDR_LOOPBACK /* For some reason this is not defined in OS2 tcpip */
+/* #define INADDR_LOOPBACK INADDR_ANY */
+#endif
+
+#define _MD_INIT_FILEDESC(fd)
+extern void _MD_MakeNonblock(PRFileDesc *f);
+#define _MD_MAKE_NONBLOCK _MD_MakeNonblock
+#define _MD_INIT_FD_INHERITABLE (_PR_MD_INIT_FD_INHERITABLE)
+#define _MD_QUERY_FD_INHERITABLE (_PR_MD_QUERY_FD_INHERITABLE)
+#define _MD_SHUTDOWN (_PR_MD_SHUTDOWN)
+#define _MD_LISTEN _PR_MD_LISTEN
+extern PRInt32 _MD_CloseSocket(PRInt32 osfd);
+#define _MD_CLOSE_SOCKET _MD_CloseSocket
+#define _MD_SENDTO (_PR_MD_SENDTO)
+#define _MD_RECVFROM (_PR_MD_RECVFROM)
+#ifdef XP_OS2_VACPP
+#define _MD_SOCKETPAIR(s, type, proto, sv) -1
+#else
+#define _MD_SOCKETPAIR (_PR_MD_SOCKETPAIR)
+#endif
+#define _MD_GETSOCKNAME (_PR_MD_GETSOCKNAME)
+#define _MD_GETPEERNAME (_PR_MD_GETPEERNAME)
+#define _MD_GETSOCKOPT (_PR_MD_GETSOCKOPT)
+#define _MD_SETSOCKOPT (_PR_MD_SETSOCKOPT)
+
+#define _MD_FSYNC _PR_MD_FSYNC
+#define _MD_SET_FD_INHERITABLE (_PR_MD_SET_FD_INHERITABLE)
+
+#ifdef _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD
+#define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT
+#define _MD_ATOMIC_SET _PR_MD_ATOMIC_SET
+#endif
+
+#define _MD_INIT_IO (_PR_MD_INIT_IO)
+#define _MD_PR_POLL (_PR_MD_PR_POLL)
+
+#define _MD_SOCKET (_PR_MD_SOCKET)
+extern PRInt32 _MD_SocketAvailable(PRFileDesc *fd);
+#define _MD_SOCKETAVAILABLE _MD_SocketAvailable
+#define _MD_PIPEAVAILABLE _MD_SocketAvailable
+#define _MD_CONNECT (_PR_MD_CONNECT)
+extern PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
+ PRIntervalTime timeout);
+#define _MD_ACCEPT _MD_Accept
+#define _MD_BIND (_PR_MD_BIND)
+#define _MD_RECV (_PR_MD_RECV)
+#define _MD_SEND (_PR_MD_SEND)
+
+/* --- Scheduler stuff --- */
+/* #define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU */
+#define _MD_PAUSE_CPU
+
+/* --- DIR stuff --- */
+#define PR_DIRECTORY_SEPARATOR '\\'
+#define PR_DIRECTORY_SEPARATOR_STR "\\"
+#define PR_PATH_SEPARATOR ';'
+#define PR_PATH_SEPARATOR_STR ";"
+#define _MD_ERRNO() errno
+#define _MD_OPEN_DIR (_PR_MD_OPEN_DIR)
+#define _MD_CLOSE_DIR (_PR_MD_CLOSE_DIR)
+#define _MD_READ_DIR (_PR_MD_READ_DIR)
+
+/* --- Segment stuff --- */
+#define _MD_INIT_SEGS()
+#define _MD_ALLOC_SEGMENT(seg, size, vaddr) 0
+#define _MD_FREE_SEGMENT(seg)
+
+/* --- Environment Stuff --- */
+#define _MD_GET_ENV (_PR_MD_GET_ENV)
+#define _MD_PUT_ENV (_PR_MD_PUT_ENV)
+
+/* --- Threading Stuff --- */
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_INIT_THREAD (_PR_MD_INIT_THREAD)
+#define _MD_INIT_ATTACHED_THREAD (_PR_MD_INIT_THREAD)
+#define _MD_CREATE_THREAD (_PR_MD_CREATE_THREAD)
+#define _MD_YIELD (_PR_MD_YIELD)
+#define _MD_SET_PRIORITY (_PR_MD_SET_PRIORITY)
+#define _MD_CLEAN_THREAD (_PR_MD_CLEAN_THREAD)
+#define _MD_SETTHREADAFFINITYMASK (_PR_MD_SETTHREADAFFINITYMASK)
+#define _MD_GETTHREADAFFINITYMASK (_PR_MD_GETTHREADAFFINITYMASK)
+#define _MD_EXIT_THREAD (_PR_MD_EXIT_THREAD)
+#define _MD_SUSPEND_THREAD (_PR_MD_SUSPEND_THREAD)
+#define _MD_RESUME_THREAD (_PR_MD_RESUME_THREAD)
+#define _MD_SUSPEND_CPU (_PR_MD_SUSPEND_CPU)
+#define _MD_RESUME_CPU (_PR_MD_RESUME_CPU)
+#define _MD_WAKEUP_CPUS (_PR_MD_WAKEUP_CPUS)
+#define _MD_BEGIN_SUSPEND_ALL()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_SUSPEND_ALL()
+#define _MD_END_RESUME_ALL()
+
+/* --- Lock stuff --- */
+#define _PR_LOCK _MD_LOCK
+#define _PR_UNLOCK _MD_UNLOCK
+extern void
+md_UnlockAndPostNotifies(struct _MDLock *lock, PRThread *waitThred, struct _MDCVar *waitCV);
+#ifdef USE_RAMSEM
+#define _MD_NEW_LOCK (_PR_MD_NEW_LOCK)
+#define _MD_FREE_LOCK(lock) (DosCloseEventSem(((PRAMSEM)(&((lock)->mutex)))->hevSem))
+#define _MD_LOCK(lock) (SemRequest486(&((lock)->mutex), -1))
+#define _MD_TEST_AND_LOCK(lock) (SemRequest486(&((lock)->mutex), -1),0)
+#define _MD_UNLOCK(lock) \
+ PR_BEGIN_MACRO \
+ if (0 != (lock)->notified.length) { \
+ md_UnlockAndPostNotifies((lock), NULL, NULL); \
+ } else { \
+ SemReleasex86( &(lock)->mutex, 0 ); \
+ } \
+ PR_END_MACRO
+#else
+#define _MD_NEW_LOCK (_PR_MD_NEW_LOCK)
+#define _MD_FREE_LOCK(lock) (DosCloseMutexSem((lock)->mutex))
+#define _MD_LOCK(lock) (DosRequestMutexSem((lock)->mutex, SEM_INDEFINITE_WAIT))
+#define _MD_TEST_AND_LOCK(lock) (DosRequestMutexSem((lock)->mutex, SEM_INDEFINITE_WAIT),0)
+#define _MD_UNLOCK(lock) \
+ PR_BEGIN_MACRO \
+ if (0 != (lock)->notified.length) { \
+ md_UnlockAndPostNotifies((lock), NULL, NULL); \
+ } else { \
+ DosReleaseMutexSem((lock)->mutex); \
+ } \
+ PR_END_MACRO
+#endif
+
+/* --- lock and cv waiting --- */
+#define _MD_WAIT (_PR_MD_WAIT)
+#define _MD_WAKEUP_WAITER (_PR_MD_WAKEUP_WAITER)
+
+/* --- CVar ------------------- */
+#define _MD_WAIT_CV (_PR_MD_WAIT_CV)
+#define _MD_NEW_CV (_PR_MD_NEW_CV)
+#define _MD_FREE_CV (_PR_MD_FREE_CV)
+#define _MD_NOTIFY_CV (_PR_MD_NOTIFY_CV )
+#define _MD_NOTIFYALL_CV (_PR_MD_NOTIFYALL_CV)
+
+ /* XXXMB- the IOQ stuff is certainly not working correctly yet. */
+/* extern struct _MDLock _pr_ioq_lock; */
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+
+/* --- Initialization stuff --- */
+#define _MD_START_INTERRUPTS()
+#define _MD_STOP_INTERRUPTS()
+#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
+#define _MD_BLOCK_CLOCK_INTERRUPTS()
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
+#define _MD_EARLY_INIT (_PR_MD_EARLY_INIT)
+#define _MD_FINAL_INIT()
+#define _MD_INIT_CPUS()
+#define _MD_INIT_RUNNING_CPU(cpu)
+
+struct PRProcess;
+struct PRProcessAttr;
+
+extern struct PRProcess * _PR_CreateOS2ProcessEx(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr,
+ PRBool detached
+);
+
+#define _MD_CREATE_PROCESS _PR_CreateOS2Process
+extern struct PRProcess * _PR_CreateOS2Process(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr
+);
+
+#define _MD_DETACH_PROCESS _PR_DetachOS2Process
+extern PRStatus _PR_DetachOS2Process(struct PRProcess *process);
+
+/* --- Wait for a child process to terminate --- */
+#define _MD_WAIT_PROCESS _PR_WaitOS2Process
+extern PRStatus _PR_WaitOS2Process(struct PRProcess *process,
+ PRInt32 *exitCode);
+
+#define _MD_KILL_PROCESS _PR_KillOS2Process
+extern PRStatus _PR_KillOS2Process(struct PRProcess *process);
+
+#define _MD_CLEANUP_BEFORE_EXIT()
+#define _MD_EXIT (_PR_MD_EXIT)
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ PR_END_MACRO
+#define _MD_SWITCH_CONTEXT
+#define _MD_RESTORE_CONTEXT
+
+/* --- Intervals --- */
+#define _MD_INTERVAL_INIT (_PR_MD_INTERVAL_INIT)
+#define _MD_GET_INTERVAL (_PR_MD_GET_INTERVAL)
+#define _MD_INTERVAL_PER_SEC (_PR_MD_INTERVAL_PER_SEC)
+#define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
+#define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
+
+/* --- Native-Thread Specific Definitions ------------------------------- */
+
+typedef struct __NSPR_TLS
+{
+ struct PRThread *_pr_thread_last_run;
+ struct PRThread *_pr_currentThread;
+ struct _PRCPU *_pr_currentCPU;
+} _NSPR_TLS;
+
+extern _NSPR_TLS* pThreadLocalStorage;
+NSPR_API(void) _PR_MD_ENSURE_TLS(void);
+
+#define _MD_GET_ATTACHED_THREAD() pThreadLocalStorage->_pr_currentThread
+extern struct PRThread * _MD_CURRENT_THREAD(void);
+#define _MD_SET_CURRENT_THREAD(_thread) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_currentThread = (_thread)
+
+#define _MD_LAST_THREAD() pThreadLocalStorage->_pr_thread_last_run
+#define _MD_SET_LAST_THREAD(_thread) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_thread_last_run = (_thread)
+
+#define _MD_CURRENT_CPU() pThreadLocalStorage->_pr_currentCPU
+#define _MD_SET_CURRENT_CPU(_cpu) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_currentCPU = (_cpu)
+
+/* lth. #define _MD_SET_INTSOFF(_val) (_pr_ints_off = (_val)) */
+/* lth. #define _MD_GET_INTSOFF() _pr_ints_off */
+/* lth. #define _MD_INCREMENT_INTSOFF() (_pr_ints_off++) */
+/* lth. #define _MD_DECREMENT_INTSOFF() (_pr_ints_off--) */
+
+/* --- Scheduler stuff --- */
+#define LOCK_SCHEDULER() 0
+#define UNLOCK_SCHEDULER() 0
+#define _PR_LockSched() 0
+#define _PR_UnlockSched() 0
+
+/* --- Initialization stuff --- */
+#define _MD_INIT_LOCKS()
+
+/* --- Stack stuff --- */
+#define _MD_INIT_STACK(stack, redzone)
+#define _MD_CLEAR_STACK(stack)
+
+/* --- Memory-mapped files stuff --- not implemented on OS/2 */
+
+struct _MDFileMap {
+ PRInt8 unused;
+};
+
+extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
+#define _MD_CREATE_FILE_MAP _MD_CreateFileMap
+
+extern PRInt32 _MD_GetMemMapAlignment(void);
+#define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment
+
+extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
+ PRUint32 len);
+#define _MD_MEM_MAP _MD_MemMap
+
+extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
+#define _MD_MEM_UNMAP _MD_MemUnmap
+
+extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
+#define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
+
+/* Some stuff for setting up thread contexts */
+typedef ULONG DWORD, *PDWORD;
+
+/* The following definitions and two structures are new in OS/2 Warp 4.0.
+ */
+#ifndef CONTEXT_CONTROL
+#define CONTEXT_CONTROL 0x00000001
+#define CONTEXT_INTEGER 0x00000002
+#define CONTEXT_SEGMENTS 0x00000004
+#define CONTEXT_FLOATING_POINT 0x00000008
+#define CONTEXT_FULL 0x0000000F
+
+#pragma pack(2)
+typedef struct _FPREG {
+ ULONG losig; /* Low 32-bits of the significand. */
+ ULONG hisig; /* High 32-bits of the significand. */
+ USHORT signexp; /* Sign and exponent. */
+} FPREG;
+typedef struct _CONTEXTRECORD {
+ ULONG ContextFlags;
+ ULONG ctx_env[7];
+ FPREG ctx_stack[8];
+ ULONG ctx_SegGs; /* GS register. */
+ ULONG ctx_SegFs; /* FS register. */
+ ULONG ctx_SegEs; /* ES register. */
+ ULONG ctx_SegDs; /* DS register. */
+ ULONG ctx_RegEdi; /* EDI register. */
+ ULONG ctx_RegEsi; /* ESI register. */
+ ULONG ctx_RegEax; /* EAX register. */
+ ULONG ctx_RegEbx; /* EBX register. */
+ ULONG ctx_RegEcx; /* ECX register. */
+ ULONG ctx_RegEdx; /* EDX register. */
+ ULONG ctx_RegEbp; /* EBP register. */
+ ULONG ctx_RegEip; /* EIP register. */
+ ULONG ctx_SegCs; /* CS register. */
+ ULONG ctx_EFlags; /* EFLAGS register. */
+ ULONG ctx_RegEsp; /* ESP register. */
+ ULONG ctx_SegSs; /* SS register. */
+} CONTEXTRECORD, *PCONTEXTRECORD;
+#pragma pack()
+#endif
+
+extern APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD);
+unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long flag);
+
+/*
+#define _pr_tid (((PTIB2)_getTIBvalue(offsetof(TIB, tib_ptib2)))->tib2_ultid)
+#define _pr_current_Thread (_system_tls[_pr_tid-1].__pr_current_thread)
+*/
+
+/* Some simple mappings of Windows API's to OS/2 API's to make our lives a
+ * little bit easier. Only add one here if it is a DIRECT mapping. We are
+ * not emulating anything. Just mapping.
+ */
+#define FreeLibrary(x) DosFreeModule((HMODULE)x)
+#define OutputDebugString(x)
+
+extern int _MD_os2_get_nonblocking_connect_error(int osfd);
+
+#endif /* nspr_os2_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2_errors.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2_errors.h
new file mode 100644
index 00000000..628b058a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_os2_errors.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_os2_errors_h___
+#define nspr_os2_errors_h___
+
+#include "md/_os2.h"
+#ifndef assert
+ #include <assert.h>
+#endif
+
+NSPR_API(void) _MD_os2_map_default_error(PRInt32 err);
+#define _PR_MD_MAP_DEFAULT_ERROR _MD_os2_map_default_error
+
+NSPR_API(void) _MD_os2_map_opendir_error(PRInt32 err);
+#define _PR_MD_MAP_OPENDIR_ERROR _MD_os2_map_opendir_error
+
+NSPR_API(void) _MD_os2_map_closedir_error(PRInt32 err);
+#define _PR_MD_MAP_CLOSEDIR_ERROR _MD_os2_map_closedir_error
+
+NSPR_API(void) _MD_os2_readdir_error(PRInt32 err);
+#define _PR_MD_MAP_READDIR_ERROR _MD_os2_readdir_error
+
+NSPR_API(void) _MD_os2_map_delete_error(PRInt32 err);
+#define _PR_MD_MAP_DELETE_ERROR _MD_os2_map_delete_error
+
+NSPR_API(void) _MD_os2_map_stat_error(PRInt32 err);
+#define _PR_MD_MAP_STAT_ERROR _MD_os2_map_stat_error
+
+NSPR_API(void) _MD_os2_map_fstat_error(PRInt32 err);
+#define _PR_MD_MAP_FSTAT_ERROR _MD_os2_map_fstat_error
+
+NSPR_API(void) _MD_os2_map_rename_error(PRInt32 err);
+#define _PR_MD_MAP_RENAME_ERROR _MD_os2_map_rename_error
+
+NSPR_API(void) _MD_os2_map_access_error(PRInt32 err);
+#define _PR_MD_MAP_ACCESS_ERROR _MD_os2_map_access_error
+
+NSPR_API(void) _MD_os2_map_mkdir_error(PRInt32 err);
+#define _PR_MD_MAP_MKDIR_ERROR _MD_os2_map_mkdir_error
+
+NSPR_API(void) _MD_os2_map_rmdir_error(PRInt32 err);
+#define _PR_MD_MAP_RMDIR_ERROR _MD_os2_map_rmdir_error
+
+NSPR_API(void) _MD_os2_map_read_error(PRInt32 err);
+#define _PR_MD_MAP_READ_ERROR _MD_os2_map_read_error
+
+NSPR_API(void) _MD_os2_map_transmitfile_error(PRInt32 err);
+#define _PR_MD_MAP_TRANSMITFILE_ERROR _MD_os2_map_transmitfile_error
+
+NSPR_API(void) _MD_os2_map_write_error(PRInt32 err);
+#define _PR_MD_MAP_WRITE_ERROR _MD_os2_map_write_error
+
+NSPR_API(void) _MD_os2_map_lseek_error(PRInt32 err);
+#define _PR_MD_MAP_LSEEK_ERROR _MD_os2_map_lseek_error
+
+NSPR_API(void) _MD_os2_map_fsync_error(PRInt32 err);
+#define _PR_MD_MAP_FSYNC_ERROR _MD_os2_map_fsync_error
+
+NSPR_API(void) _MD_os2_map_close_error(PRInt32 err);
+#define _PR_MD_MAP_CLOSE_ERROR _MD_os2_map_close_error
+
+NSPR_API(void) _MD_os2_map_socket_error(PRInt32 err);
+#define _PR_MD_MAP_SOCKET_ERROR _MD_os2_map_socket_error
+
+NSPR_API(void) _MD_os2_map_recv_error(PRInt32 err);
+#define _PR_MD_MAP_RECV_ERROR _MD_os2_map_recv_error
+
+NSPR_API(void) _MD_os2_map_recvfrom_error(PRInt32 err);
+#define _PR_MD_MAP_RECVFROM_ERROR _MD_os2_map_recvfrom_error
+
+NSPR_API(void) _MD_os2_map_send_error(PRInt32 err);
+#define _PR_MD_MAP_SEND_ERROR _MD_os2_map_send_error
+
+NSPR_API(void) _MD_os2_map_sendto_error(PRInt32 err);
+#define _PR_MD_MAP_SENDTO_ERROR _MD_os2_map_sendto_error
+
+NSPR_API(void) _MD_os2_map_writev_error(int err);
+#define _PR_MD_MAP_WRITEV_ERROR _MD_os2_map_writev_error
+
+NSPR_API(void) _MD_os2_map_accept_error(PRInt32 err);
+#define _PR_MD_MAP_ACCEPT_ERROR _MD_os2_map_accept_error
+
+NSPR_API(void) _MD_os2_map_acceptex_error(PRInt32 err);
+#define _PR_MD_MAP_ACCEPTEX_ERROR _MD_os2_map_acceptex_error
+
+NSPR_API(void) _MD_os2_map_connect_error(PRInt32 err);
+#define _PR_MD_MAP_CONNECT_ERROR _MD_os2_map_connect_error
+
+NSPR_API(void) _MD_os2_map_bind_error(PRInt32 err);
+#define _PR_MD_MAP_BIND_ERROR _MD_os2_map_bind_error
+
+NSPR_API(void) _MD_os2_map_listen_error(PRInt32 err);
+#define _PR_MD_MAP_LISTEN_ERROR _MD_os2_map_listen_error
+
+NSPR_API(void) _MD_os2_map_shutdown_error(PRInt32 err);
+#define _PR_MD_MAP_SHUTDOWN_ERROR _MD_os2_map_shutdown_error
+
+#ifndef XP_OS2_VACPP
+NSPR_API(void) _MD_os2_map_socketpair_error(int err);
+#define _PR_MD_MAP_SOCKETPAIR_ERROR _MD_os2_map_socketpair_error
+#endif
+
+NSPR_API(void) _MD_os2_map_getsockname_error(PRInt32 err);
+#define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_os2_map_getsockname_error
+
+NSPR_API(void) _MD_os2_map_getpeername_error(PRInt32 err);
+#define _PR_MD_MAP_GETPEERNAME_ERROR _MD_os2_map_getpeername_error
+
+NSPR_API(void) _MD_os2_map_getsockopt_error(PRInt32 err);
+#define _PR_MD_MAP_GETSOCKOPT_ERROR _MD_os2_map_getsockopt_error
+
+NSPR_API(void) _MD_os2_map_setsockopt_error(PRInt32 err);
+#define _PR_MD_MAP_SETSOCKOPT_ERROR _MD_os2_map_setsockopt_error
+
+NSPR_API(void) _MD_os2_map_open_error(PRInt32 err);
+#define _PR_MD_MAP_OPEN_ERROR _MD_os2_map_open_error
+
+NSPR_API(void) _MD_os2_map_gethostname_error(PRInt32 err);
+#define _PR_MD_MAP_GETHOSTNAME_ERROR _MD_os2_map_gethostname_error
+
+NSPR_API(void) _MD_os2_map_select_error(PRInt32 err);
+#define _PR_MD_MAP_SELECT_ERROR _MD_os2_map_select_error
+
+NSPR_API(void) _MD_os2_map_lockf_error(int err);
+#define _PR_MD_MAP_LOCKF_ERROR _MD_os2_map_lockf_error
+
+#endif /* nspr_os2_errors_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.cfg
new file mode 100644
index 00000000..ac07b57c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.cfg
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef OSF1
+#define OSF1
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+#ifndef IS_64
+#define IS_64
+#endif
+
+#define PR_AF_INET6 26 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 8
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.h
new file mode 100644
index 00000000..9767b873
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_osf1.h
@@ -0,0 +1,255 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_osf1_defs_h___
+#define nspr_osf1_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "osf"
+#define _PR_SI_SYSNAME "OSF"
+#define _PR_SI_ARCHITECTURE "alpha"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 131072L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#undef HAVE_WEAK_IO_SYMBOLS
+#undef HAVE_WEAK_MALLOC_SYMBOLS
+#define HAVE_DLL
+#define HAVE_BSD_FLOCK
+
+#define NEED_TIME_R
+#define USE_DLFCN
+
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+#define _PR_HAVE_LARGE_OFF_T
+#define _PR_HAVE_GETIPNODEBYNAME
+#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#ifdef _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#else
+#define AF_INET6 26
+#ifndef AI_CANONNAME
+#define AI_CANONNAME 0x00000002
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#endif
+#define AI_V4MAPPED 0x00000010
+#define AI_ALL 0x00000008
+#define AI_ADDRCONFIG 0x00000020
+#endif
+#define _PR_HAVE_POSIX_SEMAPHORES
+#define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+/*
+ * A jmp_buf is actually a struct sigcontext. The sc_sp field of
+ * struct sigcontext is the stack pointer.
+ */
+#define _MD_GET_SP(_t) (((struct sigcontext *) (_t)->md.context)->sc_sp)
+#define PR_NUM_GCREGS _JBLEN
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ (*_main)(); \
+ } \
+ _MD_GET_SP(_thread) = (long) ((_sp) - 64); \
+ _MD_GET_SP(_thread) &= ~15; \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ jmp_buf context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#ifndef _PR_PTHREADS
+#define _MD_INIT_LOCKS()
+#endif
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+ * The following are copied from _sunos.h, _aix.h. This means
+ * some of them should probably be moved into _unixos.h. But
+ * _irix.h seems to be quite different in regard to these macros.
+ */
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/* The following defines unwrapped versions of select() and poll(). */
+#include <sys/time.h>
+extern int __select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
+#define _MD_SELECT __select
+
+#include <sys/poll.h>
+#define _MD_POLL __poll
+extern int __poll(struct pollfd filedes[], unsigned int nfds, int timeout);
+
+/*
+ * Atomic operations
+ */
+#ifdef OSF1_HAVE_MACHINE_BUILTINS_H
+#include <machine/builtins.h>
+#define _PR_HAVE_ATOMIC_OPS
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(val) (__ATOMIC_INCREMENT_LONG(val) + 1)
+#define _MD_ATOMIC_ADD(ptr, val) (__ATOMIC_ADD_LONG(ptr, val) + val)
+#define _MD_ATOMIC_DECREMENT(val) (__ATOMIC_DECREMENT_LONG(val) - 1)
+#define _MD_ATOMIC_SET(val, newval) __ATOMIC_EXCH_LONG(val, newval)
+#endif /* OSF1_HAVE_MACHINE_BUILTINS_H */
+
+#endif /* nspr_osf1_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_pcos.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_pcos.h
new file mode 100644
index 00000000..64bd8405
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_pcos.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prpcos_h___
+#define prpcos_h___
+
+#define PR_DLL_SUFFIX ".dll"
+
+#include <stdlib.h>
+
+#define DIRECTORY_SEPARATOR '\\'
+#define DIRECTORY_SEPARATOR_STR "\\"
+#define PATH_SEPARATOR ';'
+
+#ifdef WIN16
+#define GCPTR __far
+#else
+#define GCPTR
+#endif
+
+/*
+** Routines for processing command line arguments
+*/
+PR_BEGIN_EXTERN_C
+#ifndef XP_OS2_EMX
+extern char *optarg;
+extern int optind;
+extern int getopt(int argc, char **argv, char *spec);
+#endif
+PR_END_EXTERN_C
+
+
+/*
+** Definitions of directory structures amd functions
+** These definitions are from:
+** <dirent.h>
+*/
+#ifdef XP_OS2_EMX
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#include <io.h>
+#include <fcntl.h> /* O_BINARY */
+
+#ifdef OS2
+extern PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen);
+#define _MD_GETHOSTNAME _MD_OS2GetHostName
+#else
+extern PRStatus _MD_WindowsGetHostName(char *name, PRUint32 namelen);
+#define _MD_GETHOSTNAME _MD_WindowsGetHostName
+extern PRStatus _MD_WindowsGetSysInfo(PRSysInfo cmd, char *name, PRUint32 namelen);
+#define _MD_GETSYSINFO _MD_WindowsGetSysInfo
+#endif
+
+#endif /* prpcos_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_pth.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_pth.h
new file mode 100644
index 00000000..34ccf713
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_pth.h
@@ -0,0 +1,298 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_pth_defs_h_
+#define nspr_pth_defs_h_
+
+/*
+** Appropriate definitions of entry points not used in a pthreads world
+*/
+#define _PR_MD_BLOCK_CLOCK_INTERRUPTS()
+#define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS()
+#define _PR_MD_DISABLE_CLOCK_INTERRUPTS()
+#define _PR_MD_ENABLE_CLOCK_INTERRUPTS()
+
+/* In good standards fashion, the DCE threads (based on posix-4) are not
+ * quite the same as newer posix implementations. These are mostly name
+ * changes and small differences, so macros usually do the trick
+ */
+#ifdef _PR_DCETHREADS
+#define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_create
+#define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_delete
+#define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), a)
+#define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (0 == pthread_mutex_trylock(&(m)))
+#define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_create
+#define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), a)
+#define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_delete
+
+/* Notes about differences between DCE threads and pthreads 10:
+ * 1. pthread_mutex_trylock returns 1 when it locks the mutex
+ * 0 when it does not. The latest pthreads has a set of errno-like
+ * return values.
+ * 2. return values from pthread_cond_timedwait are different.
+ *
+ *
+ *
+ */
+#elif defined(BSDI)
+/*
+ * Mutex and condition attributes are not supported. The attr
+ * argument to pthread_mutex_init() and pthread_cond_init() must
+ * be passed as NULL.
+ *
+ * The memset calls in _PT_PTHREAD_MUTEX_INIT and _PT_PTHREAD_COND_INIT
+ * are to work around BSDI's using a single bit to indicate a mutex
+ * or condition variable is initialized. This entire BSDI section
+ * will go away when BSDI releases updated threads libraries for
+ * BSD/OS 3.1 and 4.0.
+ */
+#define _PT_PTHREAD_MUTEXATTR_INIT(x) 0
+#define _PT_PTHREAD_MUTEXATTR_DESTROY(x) /* */
+#define _PT_PTHREAD_MUTEX_INIT(m, a) (memset(&(m), 0, sizeof(m)), \
+ pthread_mutex_init(&(m), NULL))
+#define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m)))
+#define _PT_PTHREAD_CONDATTR_INIT(x) 0
+#define _PT_PTHREAD_CONDATTR_DESTROY(x) /* */
+#define _PT_PTHREAD_COND_INIT(m, a) (memset(&(m), 0, sizeof(m)), \
+ pthread_cond_init(&(m), NULL))
+#else
+#define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_init
+#define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_destroy
+#define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), &(a))
+#define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m)))
+#if defined(DARWIN)
+#define _PT_PTHREAD_CONDATTR_INIT(x) 0
+#else
+#define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_init
+#endif
+#define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_destroy
+#define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), &(a))
+#endif
+
+/* The pthreads standard does not specify an invalid value for the
+ * pthread_t handle. (0 is usually an invalid pthread identifier
+ * but there are exceptions, for example, DG/UX.) These macros
+ * define a way to set the handle to or compare the handle with an
+ * invalid identifier. These macros are not portable and may be
+ * more of a problem as we adapt to more pthreads implementations.
+ * They are only used in the PRMonitor functions. Do not use them
+ * in new code.
+ *
+ * Unfortunately some of our clients depend on certain properties
+ * of our PRMonitor implementation, preventing us from replacing
+ * it by a portable implementation.
+ * - High-performance servers like the fact that PR_EnterMonitor
+ * only calls PR_Lock and PR_ExitMonitor only calls PR_Unlock.
+ * (A portable implementation would use a PRLock and a PRCondVar
+ * to implement the recursive lock in a monitor and call both
+ * PR_Lock and PR_Unlock in PR_EnterMonitor and PR_ExitMonitor.)
+ * Unfortunately this forces us to read the monitor owner field
+ * without holding a lock.
+ * - One way to make it safe to read the monitor owner field
+ * without holding a lock is to make that field a PRThread*
+ * (one should be able to read a pointer with a single machine
+ * instruction). However, PR_GetCurrentThread calls calloc if
+ * it is called by a thread that was not created by NSPR. The
+ * malloc tracing tools in the Mozilla client use PRMonitor for
+ * locking in their malloc, calloc, and free functions. If
+ * PR_EnterMonitor calls any of these functions, infinite
+ * recursion ensues.
+ */
+#if defined(_PR_DCETHREADS)
+#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \
+ memset(&(t), 0, sizeof(pthread_t))
+#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \
+ (!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
+#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
+#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
+ || defined(HPUX) || defined(LINUX) || defined(FREEBSD) \
+ || defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
+ || defined(VMS) || defined(NTO) || defined(DARWIN) \
+ || defined(UNIXWARE)
+#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) (t) = 0
+#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) (t) == 0
+#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
+#else
+#error "pthreads is not supported for this architecture"
+#endif
+
+#if defined(_PR_DCETHREADS)
+#define _PT_PTHREAD_ATTR_INIT pthread_attr_create
+#define _PT_PTHREAD_ATTR_DESTROY pthread_attr_delete
+#define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, a, f, r)
+#define _PT_PTHREAD_KEY_CREATE pthread_keycreate
+#define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setsched
+#define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \
+ (*(s) = pthread_attr_getstacksize(*(a)), 0)
+#define _PT_PTHREAD_GETSPECIFIC(k, r) \
+ pthread_getspecific((k), (pthread_addr_t *) &(r))
+#elif defined(_PR_PTHREADS)
+#define _PT_PTHREAD_ATTR_INIT pthread_attr_init
+#define _PT_PTHREAD_ATTR_DESTROY pthread_attr_destroy
+#define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, &a, f, r)
+#define _PT_PTHREAD_KEY_CREATE pthread_key_create
+#define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setschedpolicy
+#define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) pthread_attr_getstacksize(a, s)
+#define _PT_PTHREAD_GETSPECIFIC(k, r) (r) = pthread_getspecific(k)
+#else
+#error "Cannot determine pthread strategy"
+#endif
+
+#if defined(_PR_DCETHREADS)
+#define _PT_PTHREAD_EXPLICIT_SCHED _PT_PTHREAD_DEFAULT_SCHED
+#endif
+
+/*
+ * pthread_mutex_trylock returns different values in DCE threads and
+ * pthreads.
+ */
+#if defined(_PR_DCETHREADS)
+#define PT_TRYLOCK_SUCCESS 1
+#define PT_TRYLOCK_BUSY 0
+#else
+#define PT_TRYLOCK_SUCCESS 0
+#define PT_TRYLOCK_BUSY EBUSY
+#endif
+
+/*
+ * These platforms don't have sigtimedwait()
+ */
+#if (defined(AIX) && !defined(AIX4_3_PLUS)) || defined(LINUX) \
+ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
+ || defined(BSDI) || defined(VMS) || defined(UNIXWARE) \
+ || defined(DARWIN)
+#define PT_NO_SIGTIMEDWAIT
+#endif
+
+/*
+ * These platforms don't have pthread_kill()
+ */
+#if defined(DARWIN) && !defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)
+#define pthread_kill(thread, sig) ENOSYS
+#endif
+
+#if defined(OSF1) || defined(VMS)
+#define PT_PRIO_MIN PRI_OTHER_MIN
+#define PT_PRIO_MAX PRI_OTHER_MAX
+#elif defined(IRIX)
+#include <sys/sched.h>
+#define PT_PRIO_MIN PX_PRIO_MIN
+#define PT_PRIO_MAX PX_PRIO_MAX
+#elif defined(AIX)
+#include <sys/priv.h>
+#include <sys/sched.h>
+#ifndef PTHREAD_CREATE_JOINABLE
+#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
+#endif
+#define PT_PRIO_MIN DEFAULT_PRIO
+#define PT_PRIO_MAX DEFAULT_PRIO
+#elif defined(HPUX)
+
+#if defined(_PR_DCETHREADS)
+#define PT_PRIO_MIN PRI_OTHER_MIN
+#define PT_PRIO_MAX PRI_OTHER_MAX
+#else /* defined(_PR_DCETHREADS) */
+#include <sys/sched.h>
+#define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
+#define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
+#endif /* defined(_PR_DCETHREADS) */
+
+#elif defined(LINUX) || defined(FREEBSD)
+#define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
+#define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
+#elif defined(NTO)
+/*
+ * Neutrino has functions that return the priority range but
+ * they return invalid numbers, so I just hard coded these here
+ * for now. Jerry.Kirk@Nexarecorp.com
+ */
+#define PT_PRIO_MIN 0
+#define PT_PRIO_MAX 30
+#elif defined(SOLARIS)
+/*
+ * Solaris doesn't seem to have macros for the min/max priorities.
+ * The range of 0-127 is mentioned in the pthread_setschedparam(3T)
+ * man pages, and pthread_setschedparam indeed allows 0-127. However,
+ * pthread_attr_setschedparam does not allow 0; it allows 1-127.
+ */
+#define PT_PRIO_MIN 1
+#define PT_PRIO_MAX 127
+#elif defined(OPENBSD)
+#define PT_PRIO_MIN 0
+#define PT_PRIO_MAX 31
+#elif defined(NETBSD) \
+ || defined(BSDI) || defined(DARWIN) || defined(UNIXWARE) /* XXX */
+#define PT_PRIO_MIN 0
+#define PT_PRIO_MAX 126
+#else
+#error "pthreads is not supported for this architecture"
+#endif
+
+/*
+ * The _PT_PTHREAD_YIELD function is called from a signal handler.
+ * Needed for garbage collection -- Look at PR_Suspend/PR_Resume
+ * implementation.
+ */
+#if defined(_PR_DCETHREADS)
+#define _PT_PTHREAD_YIELD() pthread_yield()
+#elif defined(OSF1) || defined(VMS)
+/*
+ * sched_yield can't be called from a signal handler. Must use
+ * the _np version.
+ */
+#define _PT_PTHREAD_YIELD() pthread_yield_np()
+#elif defined(AIX)
+extern int (*_PT_aix_yield_fcn)();
+#define _PT_PTHREAD_YIELD() (*_PT_aix_yield_fcn)()
+#elif defined(IRIX)
+#include <time.h>
+#define _PT_PTHREAD_YIELD() \
+ PR_BEGIN_MACRO \
+ struct timespec onemillisec = {0}; \
+ onemillisec.tv_nsec = 1000000L; \
+ nanosleep(&onemillisec,NULL); \
+ PR_END_MACRO
+#elif defined(HPUX) || defined(LINUX) || defined(SOLARIS) \
+ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
+ || defined(BSDI) || defined(NTO) || defined(DARWIN) \
+ || defined(UNIXWARE)
+#define _PT_PTHREAD_YIELD() sched_yield()
+#else
+#error "Need to define _PT_PTHREAD_YIELD for this platform"
+#endif
+
+#endif /* nspr_pth_defs_h_ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.cfg
new file mode 100644
index 00000000..7c5fc3e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.cfg
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef QNX
+#define QNX
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 1
+#define PR_ALIGN_OF_INT 1
+#define PR_ALIGN_OF_LONG 1
+#define PR_ALIGN_OF_INT64 1
+#define PR_ALIGN_OF_FLOAT 1
+#define PR_ALIGN_OF_DOUBLE 1
+#define PR_ALIGN_OF_POINTER 1
+#define PR_ALIGN_OF_WORD 1
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+#define PR_WORDS_PER_DWORD_LOG2 1
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.h
new file mode 100644
index 00000000..f7593c6a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_qnx.h
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_qnx_defs_h___
+#define nspr_qnx_defs_h___
+
+/*
+** Internal configuration macros
+*/
+#define PR_LINKER_ARCH "qnx"
+#define _PR_SI_SYSNAME "QNX"
+#define _PR_SI_ARCHITECTURE "x86"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+
+#undef _PR_POLL_AVAILABLE
+#undef _PR_USE_POLL
+#define _PR_HAVE_SOCKADDR_LEN
+#define HAVE_BSD_FLOCK
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+
+#include <sys/select.h>
+
+#undef HAVE_STACK_GROWING_UP
+#undef HAVE_DLL
+#undef USE_DLFCN
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define _PR_NEED_STRCASECMP
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR
+#endif
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _SETJMP setjmp
+#define _LONGJMP longjmp
+#define _PR_CONTEXT_TYPE jmp_buf
+#define _PR_NUM_GCREGS _JBLEN
+#define _MD_GET_SP(_t) (_t)->md.context[7]
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!_SETJMP(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _LONGJMP(CONTEXT(_thread), 1); \
+}
+
+/*
+** Machine-dependent (MD) data structures.
+*/
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+** md-specific cpu structure field
+*/
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD], fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/*
+** We wrapped the select() call. _MD_SELECT refers to the built-in,
+** unwrapped version.
+*/
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#define _MD_SELECT select
+
+#define SA_RESTART 0
+
+#endif /* nspr_qnx_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.cfg
new file mode 100644
index 00000000..f2913d18
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.cfg
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef RELIANTUNIX
+#define RELIANTUNIX
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_DOUBLE 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+#define PR_BITS_PER_DOUBLE 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_WORD_LOG2 5
+#define PR_BITS_PER_DWORD_LOG2 6
+#define PR_BITS_PER_DOUBLE_LOG2 6
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+#define PR_WORDS_PER_DWORD_LOG2 1
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_WORD 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.h
new file mode 100644
index 00000000..a924e2f9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_reliantunix.h
@@ -0,0 +1,270 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * reliantunix.h
+ * 5/18/96 Taken from nec.h -- chrisk@netscape.com
+ * 3/14/97 Modified for nspr20 -- chrisk@netscape.com
+ */
+#ifndef nspr_reliantunix_defs_h___
+#define nspr_reliantunix_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "sinix"
+#define _PR_SI_SYSNAME "SINIX"
+#define _PR_SI_ARCHITECTURE "mips"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE (2*65536L)
+#define _MD_MMAP_FLAGS MAP_PRIVATE|MAP_FIXED
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define HAVE_NETCONFIG
+#define HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_MALLOC_SYMBOLS
+#define _PR_RECV_BROKEN /* recv doesn't work on Unix Domain Sockets */
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ST_ATIM
+#define _PR_NO_LARGE_FILES
+
+/*
+ * Mike Patnode indicated that it is possibly safe now to use context-switching
+ * calls that do not change the signal mask, like setjmp vs. sigsetjmp.
+ * So we'll use our homegrown, getcontext/setcontext-compatible stuff which
+ * will save us the getcontext/setcontext system calls at each context switch.
+ * It already works in FastTrack 2.01, so it should do it here :-)
+ * - chrisk 040497
+ */
+#define USE_SETCXT /* temporarily disabled... */
+
+#include <ucontext.h>
+
+#ifdef USE_SETCXT
+/* use non-syscall machine language replacement */
+#define _GETCONTEXT getcxt
+#define _SETCONTEXT setcxt
+/* defined in os_ReliantUNIX.s */
+extern int getcxt(ucontext_t *);
+extern int setcxt(ucontext_t *);
+#else
+#define _GETCONTEXT getcontext
+#define _SETCONTEXT setcontext
+#endif
+
+#define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gpregs[CXT_SP]
+#define _PR_CONTEXT_TYPE ucontext_t
+#define _PR_NUM_GCREGS NGREG
+
+#define CONTEXT(_thread) (&(_thread)->md.context)
+
+#define _PR_IS_NATIVE_THREAD_SUPPORTED() 0
+
+/*
+** Machine-dependent (MD) data structures.
+*/
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+** Initialize the thread context preparing it to execute "_main()"
+** - get a nice, fresh context
+** - set its SP to the stack we allcoated for it
+** - set it to start things at "e"
+*/
+#define _MD_INIT_CONTEXT(thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ _GETCONTEXT(CONTEXT(thread)); \
+ /* this is supposed to point to the stack BASE, not to SP */ \
+ CONTEXT(thread)->uc_stack.ss_sp = thread->stack->stackBottom; \
+ CONTEXT(thread)->uc_stack.ss_size = thread->stack->stackSize; \
+ CONTEXT(thread)->uc_mcontext.gpregs[CXT_SP] = ((unsigned long)_sp - 128) & 0xfffffff8; \
+ CONTEXT(thread)->uc_mcontext.gpregs[CXT_T9] = _main; \
+ CONTEXT(thread)->uc_mcontext.gpregs[CXT_EPC] = _main; \
+ CONTEXT(thread)->uc_mcontext.gpregs[CXT_RA] = 0; \
+ thread->no_sched = 0; \
+ PR_END_MACRO
+
+/*
+** Save current context as it is scheduled away
+*/
+#define _MD_SWITCH_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ if (!_GETCONTEXT(CONTEXT(_thread))) { \
+ _MD_SAVE_ERRNO(_thread); \
+ _MD_SET_LAST_THREAD(_thread); \
+ _PR_Schedule(); \
+ } \
+ PR_END_MACRO
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT or set up
+** by _MD_INIT_CONTEXT
+** CXT_V0 is the register that holds the return value.
+** We must set it to 1 so that we can see if the return from
+** getcontext() is the result of calling getcontext() or
+** setcontext()...
+** setting a context got with getcontext() appears to
+** return from getcontext(), too!
+** CXT_A3 is the register that holds status when returning
+** from a syscall. It is set to 0 to indicate success,
+** because we want getcontext() on the other side of the magic
+** door to be ok.
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ ucontext_t *uc = CONTEXT(_thread); \
+ uc->uc_mcontext.gpregs[CXT_V0] = 1;\
+ uc->uc_mcontext.gpregs[CXT_A3] = 0;\
+ _MD_RESTORE_ERRNO(_thread); \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _SETCONTEXT(uc); \
+ PR_END_MACRO
+
+#define _MD_SAVE_ERRNO(t) (t)->md.errcode = errno;
+#define _MD_RESTORE_ERRNO(t) errno = (t)->md.errcode;
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+#define S_ISSOCK(mode) ((mode&0xF000) == 0xC000)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(mode) ((mode&0xA000) == 0xC000)
+#endif
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *execptfds, struct timeval *timeout);
+#define _MD_SELECT(nfds,r,w,e,tv) _select(nfds,r,w,e,tv)
+#define _MD_POLL _poll
+
+#endif /* nspr_reliantunix_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.cfg
new file mode 100644
index 00000000..b79e2503
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.cfg
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef RHAPOSDY
+#define RHAPOSDY
+#endif
+
+#define PR_AF_INET6 30 /* same as AF_INET6 */
+
+#if defined(i386)
+#undef IS_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#else
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#endif
+
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.h
new file mode 100644
index 00000000..fa9903ed
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_rhapsody.h
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_rhapsody_defs_h___
+#define nspr_rhapsody_defs_h___
+
+#include "prthread.h"
+
+#include <sys/syscall.h>
+
+#define PR_LINKER_ARCH "rhapsody"
+#define _PR_SI_SYSNAME "RHAPSODY"
+#ifdef i386
+#define _PR_SI_ARCHITECTURE "x86"
+#else
+#define _PR_SI_ARCHITECTURE "ppc"
+#endif
+#define PR_DLL_SUFFIX ".dylib"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_MACH_DYLD
+#define _PR_HAVE_SOCKADDR_LEN
+#define _PR_STAT_HAS_ST_ATIMESPEC
+#define _PR_NO_LARGE_FILES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+
+#define USE_SETJMP
+
+#if !defined(_PR_PTHREADS)
+
+#include <setjmp.h>
+
+#define PR_CONTEXT_TYPE jmp_buf
+
+#define CONTEXT(_th) ((_th)->md.context)
+#define _MD_GET_SP(_th) (((struct sigcontext *) (_th)->md.context)->sc_onstack)
+#define PR_NUM_GCREGS _JBLEN
+
+/*
+** Initialize a thread context to run "_main()" when started
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) { \
+ _main(); \
+ } \
+ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+extern PRStatus _MD_InitializeThread(PRThread *thread);
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread
+#define _MD_RESUME_THREAD(thread) _MD_resume_thread
+#define _MD_CLEAN_THREAD(_thread)
+
+extern PRStatus _MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
+extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
+extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
+extern void _MD_YIELD(void);
+
+#endif /* ! _PR_PTHREADS */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+extern void _MD_EarlyInit(void);
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+
+/* For writev() */
+#include <sys/uio.h>
+
+#endif /* nspr_rhapsody_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.cfg
new file mode 100644
index 00000000..d7c461ff
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.cfg
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef SCO
+#define SCO
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.h
new file mode 100644
index 00000000..6efaa7ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_scoos.h
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_scoos5_defs_h___
+#define nspr_scoos5_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "scoos5"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_SI_SYSNAME "SCO"
+#define _PR_SI_ARCHITECTURE "x86"
+#define _PR_STACK_VMBASE 0x50000000
+
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+
+#if !defined (HAVE_STRERROR)
+#define HAVE_STRERROR
+#endif
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define _PR_RECV_BROKEN /* recv doesn't work on Unix Domain Sockets */
+
+#define USE_SETJMP
+
+#ifdef _PR_LOCAL_THREADS_ONLY
+#include <setjmp.h>
+
+#define _MD_GET_SP(_t) (_t)->md.jb[4]
+#define PR_NUM_GCREGS _SIGJBLEN
+#define PR_CONTEXT_TYPE sigjmp_buf
+
+#define CONTEXT(_th) ((_th)->md.jb)
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if (sigsetjmp(CONTEXT(_thread),1)) { \
+ (*_main)(); \
+ } \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!sigsetjmp(CONTEXT(_thread), 1)) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->osErrorCode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ siglongjmp(CONTEXT(_thread), 1); \
+}
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+struct _MDThread {
+ jmp_buf jb;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define _MD_SELECT _select
+#define _MD_POLL _poll
+
+#endif /* nspr_scoos5_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris.h
new file mode 100644
index 00000000..8f9d121e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris.h
@@ -0,0 +1,832 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_solaris_defs_h___
+#define nspr_solaris_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "solaris"
+#define _PR_SI_SYSNAME "SOLARIS"
+#ifdef sparc
+#define _PR_SI_ARCHITECTURE "sparc"
+#elif defined(i386)
+#define _PR_SI_ARCHITECTURE "x86"
+#elif defined(__x86_64)
+#define _PR_SI_ARCHITECTURE "x86-64"
+#else
+#error unknown processor
+#endif
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE (2*65536L)
+#define _MD_MMAP_FLAGS MAP_SHARED
+
+#undef HAVE_STACK_GROWING_UP
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+
+#undef HAVE_WEAK_MALLOC_SYMBOLS
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_STRFTIME_LOCK
+
+#if defined(_LARGEFILE64_SOURCE) /* vbox */
+#define _PR_HAVE_OFF64_T /* vbox */
+#elif defined(_LP64) || _FILE_OFFSET_BITS == 32 /* vbox */
+#define _PR_HAVE_LARGE_OFF_T /* vbox */
+#else /* vbox */
+#define _PR_NO_LARGE_FILES /* vbox */
+#endif /* vbox */
+
+
+/*
+ * Intel x86 has atomic instructions.
+ *
+ * Sparc v8 does not have instructions to efficiently implement
+ * atomic increment/decrement operations. In the local threads
+ * only and pthreads versions, we use the default atomic routine
+ * implementation in pratom.c. The obsolete global threads only
+ * version uses a global mutex_t to implement the atomic routines
+ * in solaris.c, which is actually equivalent to the default
+ * implementation.
+ *
+ * 64-bit Solaris requires sparc v9, which has atomic instructions.
+ */
+#if defined(i386) || defined(_PR_GLOBAL_THREADS_ONLY) || defined(IS_64)
+#define _PR_HAVE_ATOMIC_OPS
+#endif
+
+#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS)
+/*
+ * We have assembly language implementation of atomic
+ * stacks for the 32-bit sparc and x86 architectures only.
+ *
+ * Note: We ran into thread starvation problem with the
+ * 32-bit sparc assembly language implementation of atomic
+ * stacks, so we do not use it now. (Bugzilla bug 113740)
+ */
+#if !defined(sparc) && !defined(__x86_64)
+#define _PR_HAVE_ATOMIC_CAS
+#endif
+#endif
+
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ST_ATIM
+#ifdef SOLARIS2_5
+#define _PR_HAVE_SYSV_SEMAPHORES
+#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+#else
+#define _PR_HAVE_POSIX_SEMAPHORES
+#define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+#endif
+#define _PR_HAVE_GETIPNODEBYNAME
+#define _PR_HAVE_GETIPNODEBYADDR
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#define _PR_ACCEPT_INHERIT_NONBLOCK
+#if !defined(_XPG4_2) || defined(_XPG6) || defined(__EXTENSIONS__) /* vbox */
+#define _PR_INET6 /* vbox */
+#endif /* vbox */
+#ifdef _PR_INET6
+#define _PR_HAVE_INET_NTOP
+#else
+#define AF_INET6 26
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#define AI_CANONNAME 0x0010
+#define AI_V4MAPPED 0x0001
+#define AI_ALL 0x0002
+#define AI_ADDRCONFIG 0x0004
+#define _PR_HAVE_MD_SOCKADDR_IN6
+/* isomorphic to struct in6_addr on Solaris 8 */
+struct _md_in6_addr {
+ union {
+ PRUint8 _S6_u8[16];
+ PRUint32 _S6_u32[4];
+ PRUint32 __S6_align;
+ } _S6_un;
+};
+/* isomorphic to struct sockaddr_in6 on Solaris 8 */
+struct _md_sockaddr_in6 {
+ PRUint16 sin6_family;
+ PRUint16 sin6_port;
+ PRUint32 sin6_flowinfo;
+ struct _md_in6_addr sin6_addr;
+ PRUint32 sin6_scope_id;
+ PRUint32 __sin6_src_id;
+};
+#endif
+#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS)
+#define _PR_HAVE_GETHOST_R
+#define _PR_HAVE_GETHOST_R_POINTER
+#endif
+
+#include "prinrval.h"
+NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void);
+#define _MD_GET_INTERVAL _MD_Solaris_GetInterval
+NSPR_API(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
+#define _MD_INTERVAL_PER_SEC _MD_Solaris_TicksPerSecond
+
+#if defined(_PR_HAVE_ATOMIC_OPS)
+/*
+** Atomic Operations
+*/
+#define _MD_INIT_ATOMIC()
+
+NSPR_API(PRInt32) _MD_AtomicIncrement(PRInt32 *val);
+#define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement
+
+NSPR_API(PRInt32) _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#define _MD_ATOMIC_ADD _MD_AtomicAdd
+
+NSPR_API(PRInt32) _MD_AtomicDecrement(PRInt32 *val);
+#define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement
+
+NSPR_API(PRInt32) _MD_AtomicSet(PRInt32 *val, PRInt32 newval);
+#define _MD_ATOMIC_SET _MD_AtomicSet
+#endif /* _PR_HAVE_ATOMIC_OPS */
+
+#if defined(_PR_PTHREADS)
+
+NSPR_API(void) _MD_EarlyInit(void);
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+
+#elif defined(_PR_GLOBAL_THREADS_ONLY)
+
+#include "prthread.h"
+
+#include <ucontext.h>
+
+/*
+** Iinitialization Related definitions
+*/
+
+NSPR_API(void) _MD_EarlyInit(void);
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+
+#define _MD_GET_SP(threadp) threadp->md.sp
+
+/*
+** Clean-up the thread machine dependent data structure
+*/
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_INIT_ATTACHED_THREAD _MD_InitializeThread
+
+NSPR_API(PRStatus) _MD_CreateThread(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+#define _MD_CREATE_THREAD _MD_CreateThread
+
+#define _PR_CONTEXT_TYPE ucontext_t
+
+#define CONTEXT(_thread) (&(_thread)->md.context)
+
+#include <thread.h>
+#include <sys/lwp.h>
+#include <synch.h>
+
+extern struct PRLock *_pr_schedLock;
+
+/*
+** Thread Local Storage
+*/
+
+#define THREAD_KEY_T thread_key_t
+
+extern struct PRThread *_pr_attached_thread_tls();
+extern struct PRThread *_pr_current_thread_tls();
+extern struct _PRCPU *_pr_current_cpu_tls();
+extern struct PRThread *_pr_last_thread_tls();
+
+extern THREAD_KEY_T threadid_key;
+extern THREAD_KEY_T cpuid_key;
+extern THREAD_KEY_T last_thread_key;
+
+#define _MD_GET_ATTACHED_THREAD() _pr_attached_thread_tls()
+#define _MD_CURRENT_THREAD() _pr_current_thread_tls()
+#define _MD_CURRENT_CPU() _pr_current_cpu_tls()
+#define _MD_LAST_THREAD() _pr_last_thread_tls()
+
+#define _MD_SET_CURRENT_THREAD(newval) \
+ PR_BEGIN_MACRO \
+ thr_setspecific(threadid_key, (void *)newval); \
+ PR_END_MACRO
+
+#define _MD_SET_CURRENT_CPU(newval) \
+ PR_BEGIN_MACRO \
+ thr_setspecific(cpuid_key, (void *)newval); \
+ PR_END_MACRO
+
+#define _MD_SET_LAST_THREAD(newval) \
+ PR_BEGIN_MACRO \
+ thr_setspecific(last_thread_key, (void *)newval); \
+ PR_END_MACRO
+
+#define _MD_CLEAN_THREAD(_thread) _MD_cleanup_thread(_thread)
+extern void _MD_exit_thread(PRThread *thread);
+#define _MD_EXIT_THREAD(thread) _MD_exit_thread(thread)
+
+#define _MD_SUSPEND_THREAD(thread) _MD_Suspend(thread)
+#define _MD_RESUME_THREAD(thread) thr_continue((thread)->md.handle)
+
+/* XXXX Needs to be defined - Prashant */
+#define _MD_SUSPEND_CPU(cpu)
+#define _MD_RESUME_CPU(cpu)
+
+extern void _MD_Begin_SuspendAll(void);
+extern void _MD_End_SuspendAll(void);
+extern void _MD_End_ResumeAll(void);
+#define _MD_BEGIN_SUSPEND_ALL() _MD_Begin_SuspendAll()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_SUSPEND_ALL() _MD_End_SuspendAll()
+#define _MD_END_RESUME_ALL() _MD_End_ResumeAll()
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(md_lockp) (mutex_init(&((md_lockp)->lock),USYNC_THREAD,NULL) ? PR_FAILURE : PR_SUCCESS)
+#define _MD_FREE_LOCK(md_lockp) mutex_destroy(&((md_lockp)->lock))
+#define _MD_UNLOCK(md_lockp) mutex_unlock(&((md_lockp)->lock))
+#define _MD_TEST_AND_LOCK(md_lockp) mutex_trylock(&((md_lockp)->lock))
+struct _MDLock;
+NSPR_API(void) _MD_lock(struct _MDLock *md_lock);
+#undef PROFILE_LOCKS
+#ifndef PROFILE_LOCKS
+#define _MD_LOCK(md_lockp) _MD_lock(md_lockp)
+#else
+#define _MD_LOCK(md_lockp) \
+ PR_BEGIN_MACRO \
+ int rv = _MD_TEST_AND_LOCK(md_lockp); \
+ if (rv == 0) { \
+ (md_lockp)->hitcount++; \
+ } else { \
+ (md_lockp)->misscount++; \
+ _MD_lock(md_lockp); \
+ } \
+ PR_END_MACRO
+#endif
+
+#define _PR_LOCK_HEAP() if (_pr_heapLock) _MD_LOCK(&_pr_heapLock->md)
+#define _PR_UNLOCK_HEAP() if (_pr_heapLock) _MD_UNLOCK(&_pr_heapLock->md)
+
+#define _MD_ATTACH_THREAD(threadp)
+
+
+#define THR_KEYCREATE thr_keycreate
+#define THR_SELF thr_self
+#define _MD_NEW_CV(condp) cond_init(&((condp)->cv), USYNC_THREAD, 0)
+#define COND_WAIT(condp, mutexp) cond_wait(condp, mutexp)
+#define COND_TIMEDWAIT(condp, mutexp, tspec) \
+ cond_timedwait(condp, mutexp, tspec)
+#define _MD_NOTIFY_CV(condp, lockp) cond_signal(&((condp)->cv))
+#define _MD_NOTIFYALL_CV(condp,unused) cond_broadcast(&((condp)->cv))
+#define _MD_FREE_CV(condp) cond_destroy(&((condp)->cv))
+#define _MD_YIELD() thr_yield()
+#include <time.h>
+/*
+ * Because clock_gettime() on Solaris/x86 2.4 always generates a
+ * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
+ * which is implemented using gettimeofday().
+ */
+#if defined(i386) && defined(SOLARIS2_4)
+extern int _pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp);
+#define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
+#else
+#define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
+#endif /* i386 && SOLARIS2_4 */
+
+#define MUTEX_T mutex_t
+#define COND_T cond_t
+
+#define _MD_NEW_SEM(md_semp,_val) sema_init(&((md_semp)->sem),_val,USYNC_THREAD,NULL)
+#define _MD_DESTROY_SEM(md_semp) sema_destroy(&((md_semp)->sem))
+#define _MD_WAIT_SEM(md_semp) sema_wait(&((md_semp)->sem))
+#define _MD_POST_SEM(md_semp) sema_post(&((md_semp)->sem))
+
+#define _MD_SAVE_ERRNO(_thread)
+#define _MD_RESTORE_ERRNO(_thread)
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+
+extern struct _MDLock _pr_ioq_lock;
+#define _MD_IOQ_LOCK() _MD_LOCK(&_pr_ioq_lock)
+#define _MD_IOQ_UNLOCK() _MD_UNLOCK(&_pr_ioq_lock)
+
+extern PRStatus _MD_wait(struct PRThread *, PRIntervalTime timeout);
+#define _MD_WAIT _MD_wait
+
+extern PRStatus _MD_WakeupWaiter(struct PRThread *);
+#define _MD_WAKEUP_WAITER _MD_WakeupWaiter
+
+NSPR_API(void) _MD_InitIO(void);
+#define _MD_INIT_IO _MD_InitIO
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ PR_END_MACRO
+#define _MD_SWITCH_CONTEXT(_thread)
+#define _MD_RESTORE_CONTEXT(_newThread)
+
+struct _MDLock {
+ MUTEX_T lock;
+#ifdef PROFILE_LOCKS
+ PRInt32 hitcount;
+ PRInt32 misscount;
+#endif
+};
+
+struct _MDCVar {
+ COND_T cv;
+};
+
+struct _MDSemaphore {
+ sema_t sem;
+};
+
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ thread_t handle;
+ lwpid_t lwpid;
+ uint_t sp; /* stack pointer */
+ uint_t threadID; /* ptr to solaris-internal thread id structures */
+ struct _MDSemaphore waiter_sem;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field, common to all Unix platforms
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+/* The following defines the unwrapped versions of select() and poll(). */
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout);
+#define _MD_SELECT _select
+
+#include <poll.h>
+#define _MD_POLL _poll
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Missing function prototypes
+*/
+extern int gethostname (char *name, int namelen);
+
+PR_END_EXTERN_C
+
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+/*
+ * LOCAL_THREADS_ONLY implementation on Solaris
+ */
+
+#include "prthread.h"
+
+#include <errno.h>
+#include <ucontext.h>
+#include <sys/stack.h>
+#include <synch.h>
+
+/*
+** Iinitialization Related definitions
+*/
+
+NSPR_API(void) _MD_EarlyInit(void);
+NSPR_API(void) _MD_SolarisInit();
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _MD_SolarisInit
+#define _MD_INIT_THREAD _MD_InitializeThread
+
+#ifdef USE_SETJMP
+
+#include <setjmp.h>
+
+#define _PR_CONTEXT_TYPE jmp_buf
+
+#ifdef sparc
+#define _MD_GET_SP(_t) (_t)->md.context[2]
+#else
+#define _MD_GET_SP(_t) (_t)->md.context[4]
+#endif
+
+#define PR_NUM_GCREGS _JBLEN
+#define CONTEXT(_thread) (_thread)->md.context
+
+#else /* ! USE_SETJMP */
+
+#ifdef sparc
+#define _PR_CONTEXT_TYPE ucontext_t
+#define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gregs[REG_SP]
+/*
+** Sparc's use register windows. the _MD_GetRegisters for the sparc's
+** doesn't actually store anything into the argument buffer; instead the
+** register windows are homed to the stack. I assume that the stack
+** always has room for the registers to spill to...
+*/
+#define PR_NUM_GCREGS 0
+#else
+#define _PR_CONTEXT_TYPE unsigned int edi; sigset_t oldMask, blockMask; ucontext_t
+#define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gregs[USP]
+#define PR_NUM_GCREGS _JBLEN
+#endif
+
+#define CONTEXT(_thread) (&(_thread)->md.context)
+
+#endif /* ! USE_SETJMP */
+
+#include <time.h>
+/*
+ * Because clock_gettime() on Solaris/x86 always generates a
+ * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
+ * which is implemented using gettimeofday().
+ */
+#ifdef i386
+#define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
+#else
+#define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
+#endif /* i386 */
+
+#define _MD_SAVE_ERRNO(_thread) (_thread)->md.errcode = errno;
+#define _MD_RESTORE_ERRNO(_thread) errno = (_thread)->md.errcode;
+
+#ifdef sparc
+
+#ifdef USE_SETJMP
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ int *context = (_thread)->md.context; \
+ *status = PR_TRUE; \
+ (void) setjmp(context); \
+ (_thread)->md.context[1] = (int) ((_sp) - 64); \
+ (_thread)->md.context[2] = (int) _main; \
+ (_thread)->md.context[3] = (int) _main + 4; \
+ _thread->no_sched = 0; \
+ PR_END_MACRO
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ _MD_SAVE_ERRNO(_thread) \
+ _MD_SET_LAST_THREAD(_thread); \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _PR_Schedule(); \
+ }
+
+#define _MD_RESTORE_CONTEXT(_newThread) \
+{ \
+ _MD_RESTORE_ERRNO(_newThread) \
+ _MD_SET_CURRENT_THREAD(_newThread); \
+ longjmp(CONTEXT(_newThread), 1); \
+}
+
+#else
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ ucontext_t *uc = CONTEXT(_thread); \
+ *status = PR_TRUE; \
+ getcontext(uc); \
+ uc->uc_stack.ss_sp = (char *) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8); \
+ uc->uc_stack.ss_size = _thread->stack->stackSize; \
+ uc->uc_stack.ss_flags = 0; /* ? */ \
+ uc->uc_mcontext.gregs[REG_SP] = (unsigned int) uc->uc_stack.ss_sp; \
+ uc->uc_mcontext.gregs[REG_PC] = (unsigned int) _main; \
+ uc->uc_mcontext.gregs[REG_nPC] = (unsigned int) ((char*)_main)+4; \
+ uc->uc_flags = UC_ALL; \
+ _thread->no_sched = 0; \
+ PR_END_MACRO
+
+/*
+** Switch away from the current thread context by saving its state and
+** calling the thread scheduler. Reload cpu when we come back from the
+** context switch because it might have changed.
+*/
+#define _MD_SWITCH_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ if (!getcontext(CONTEXT(_thread))) { \
+ _MD_SAVE_ERRNO(_thread); \
+ _MD_SET_LAST_THREAD(_thread); \
+ _PR_Schedule(); \
+ } \
+ PR_END_MACRO
+
+/*
+** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
+** initialized by _MD_INIT_CONTEXT.
+*/
+#define _MD_RESTORE_CONTEXT(_newThread) \
+ PR_BEGIN_MACRO \
+ ucontext_t *uc = CONTEXT(_newThread); \
+ uc->uc_mcontext.gregs[11] = 1; \
+ _MD_RESTORE_ERRNO(_newThread); \
+ _MD_SET_CURRENT_THREAD(_newThread); \
+ setcontext(uc); \
+ PR_END_MACRO
+#endif
+
+#else /* x86 solaris */
+
+#ifdef USE_SETJMP
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ if (setjmp(CONTEXT(_thread))) _main(); \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
+ PR_END_MACRO
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!setjmp(CONTEXT(_thread))) { \
+ _MD_SAVE_ERRNO(_thread) \
+ _PR_Schedule(); \
+ }
+
+#define _MD_RESTORE_CONTEXT(_newThread) \
+{ \
+ _MD_RESTORE_ERRNO(_newThread) \
+ _MD_SET_CURRENT_THREAD(_newThread); \
+ longjmp(CONTEXT(_newThread), 1); \
+}
+
+#else /* USE_SETJMP */
+
+#define WINDOWSIZE 0
+
+int getedi(void);
+void setedi(int);
+
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ ucontext_t *uc = CONTEXT(_thread); \
+ *status = PR_TRUE; \
+ getcontext(uc); \
+ /* Force sp to be double aligned! */ \
+ uc->uc_mcontext.gregs[USP] = (int) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8); \
+ uc->uc_mcontext.gregs[PC] = (int) _main; \
+ (_thread)->no_sched = 0; \
+ PR_END_MACRO
+
+/* getcontext() may return 1, contrary to what the man page says */
+#define _MD_SWITCH_CONTEXT(_thread) \
+ PR_BEGIN_MACRO \
+ ucontext_t *uc = CONTEXT(_thread); \
+ PR_ASSERT(_thread->no_sched); \
+ sigfillset(&((_thread)->md.blockMask)); \
+ sigprocmask(SIG_BLOCK, &((_thread)->md.blockMask), \
+ &((_thread)->md.oldMask)); \
+ (_thread)->md.edi = getedi(); \
+ if (! getcontext(uc)) { \
+ sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
+ uc->uc_mcontext.gregs[EDI] = (_thread)->md.edi; \
+ _MD_SAVE_ERRNO(_thread) \
+ _MD_SET_LAST_THREAD(_thread); \
+ _PR_Schedule(); \
+ } else { \
+ sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
+ setedi((_thread)->md.edi); \
+ PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
+ _MD_LAST_THREAD()->no_sched = 0; \
+ } \
+ PR_END_MACRO
+
+/*
+** Restore a thread context, saved by _PR_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_newthread) \
+ PR_BEGIN_MACRO \
+ ucontext_t *uc = CONTEXT(_newthread); \
+ uc->uc_mcontext.gregs[EAX] = 1; \
+ _MD_RESTORE_ERRNO(_newthread) \
+ _MD_SET_CURRENT_THREAD(_newthread); \
+ (_newthread)->no_sched = 1; \
+ setcontext(uc); \
+ PR_END_MACRO
+#endif /* USE_SETJMP */
+
+#endif /* sparc */
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int errcode;
+ int id;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#ifndef _PR_PTHREADS
+#define _MD_INIT_LOCKS()
+#endif
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+extern PRStatus _MD_WAIT(struct PRThread *, PRIntervalTime timeout);
+extern PRStatus _MD_WAKEUP_WAITER(struct PRThread *);
+extern void _MD_YIELD(void);
+extern PRStatus _MD_InitializeThread(PRThread *thread);
+extern void _MD_SET_PRIORITY(struct _MDThread *thread,
+ PRThreadPriority newPri);
+extern PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start) (void *),
+ PRThreadPriority priority, PRThreadScope scope, PRThreadState state,
+ PRUint32 stackSize);
+
+NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void);
+#define _MD_GET_INTERVAL _MD_Solaris_GetInterval
+NSPR_API(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
+#define _MD_INTERVAL_PER_SEC _MD_Solaris_TicksPerSecond
+
+/* The following defines the unwrapped versions of select() and poll(). */
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout);
+#define _MD_SELECT _select
+
+#include <stropts.h>
+#include <poll.h>
+#define _MD_POLL _poll
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Missing function prototypes
+*/
+extern int gethostname (char *name, int namelen);
+
+PR_END_EXTERN_C
+
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+
+extern void _MD_solaris_map_sendfile_error(int err);
+
+#endif /* nspr_solaris_defs_h___ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris32.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris32.cfg
new file mode 100644
index 00000000..3902e09c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris32.cfg
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef SOLARIS
+#define SOLARIS
+#endif
+
+#if defined(sparc) || defined(__sparc)
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_DOUBLE 8
+#elif defined(i386) || defined(__i386)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_DOUBLE 4
+#else
+#error unknown processor
+#endif
+
+#define PR_AF_INET6 26 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* ifndef nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris64.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris64.cfg
new file mode 100644
index 00000000..9d5b6069
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris64.cfg
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef SOLARIS
+#define SOLARIS
+#endif
+
+#if defined(sparc) || defined(__sparc)
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_DOUBLE 8
+#elif defined(__x86_64) || defined(__AMD64)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_DOUBLE 8
+#else
+#error unknown processor
+#endif
+#define IS_64
+
+#define PR_AF_INET6 26 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 8
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 8
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_POINTER 8
+
+#define HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#define HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* ifndef nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.cfg
new file mode 100644
index 00000000..4b8fbff9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.cfg
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef SONY
+#define SONY
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.h
new file mode 100644
index 00000000..3d17e04d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sony.h
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_sony_defs_h___
+#define nspr_sony_defs_h___
+
+#define PR_LINKER_ARCH "sony"
+#define _PR_SI_SYSNAME "SONY"
+#define _PR_SI_ARCHITECTURE "mips"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#if defined(_PR_LOCAL_THREADS_ONLY)
+#include <ucontext.h>
+#include <sys/regset.h>
+
+#define PR_NUM_GCREGS NGREG
+#define PR_CONTEXT_TYPE ucontext_t
+
+#define CONTEXT(_thread) (&(_thread)->md.context)
+
+#define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gregs[CXT_SP]
+
+/*
+** Initialize the thread context preparing it to execute _main()
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ getcontext(CONTEXT(_thread)); \
+ CONTEXT(_thread)->uc_stack.ss_sp = (char*) (_thread)->stack->stackBottom; \
+ CONTEXT(_thread)->uc_stack.ss_size = (_thread)->stack->stackSize; \
+ _MD_GET_SP(_thread) = (greg_t) (_sp) - 64; \
+ makecontext(CONTEXT(_thread), _main, 0); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!getcontext(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ ucontext_t *uc = CONTEXT(_thread); \
+ uc->uc_mcontext.gregs[CXT_V0] = 1; \
+ uc->uc_mcontext.gregs[CXT_A3] = 0; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ errno = (_thread)->md.errcode; \
+ setcontext(uc); \
+}
+
+/* Machine-dependent (MD) data structures */
+
+struct _MDThread {
+ PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/* The following defines unwrapped versions of select() and poll(). */
+extern int _select (int, fd_set *, fd_set *, fd_set *, struct timeval *);
+#define _MD_SELECT _select
+
+#include <sys/poll.h>
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+#define _MD_POLL _poll
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_TIME_R
+#define NEED_STRFTIME_LOCK
+
+/*
+** Missing function prototypes
+*/
+extern int gethostname(char *name, int namelen);
+
+#endif /* nspr_sony_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.cfg
new file mode 100644
index 00000000..581d4834
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.cfg
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef SUNOS4
+#define SUNOS4
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#undef HAVE_LONG_LONG
+#define HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* ifndef nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.h
new file mode 100644
index 00000000..0d62892e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_sunos4.h
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_sunos_defs_h___
+#define nspr_sunos_defs_h___
+
+#include "md/sunos4.h"
+
+/* On SunOS 4, memset is declared in memory.h */
+#include <memory.h>
+#include <errno.h>
+#include <sys/syscall.h>
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "sunos"
+#define _PR_SI_SYSNAME "SUNOS"
+#define _PR_SI_ARCHITECTURE "sparc"
+#define PR_DLL_SUFFIX ".so.1.0"
+
+/*
+** For sunos type machines, don't specify an address because the
+** NetBSD/SPARC O.S. does the wrong thing.
+*/
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#undef HAVE_STACK_GROWING_UP
+#undef HAVE_WEAK_IO_SYMBOLS
+#undef HAVE_WEAK_MALLOC_SYMBOLS
+#define HAVE_DLL
+#define USE_DLFCN
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define HAVE_BSD_FLOCK
+#define _PR_NO_LARGE_FILES
+#define _PR_STAT_HAS_ONLY_ST_ATIME
+
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _MD_GET_SP(_t) (_t)->md.context[2]
+
+#define PR_NUM_GCREGS _JBLEN
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ int *context = (_thread)->md.context; \
+ *status = PR_TRUE; \
+ asm("ta 3"); \
+ (void) setjmp(context); \
+ (_thread)->md.context[2] = (int) ((_sp) - 64); \
+ (_thread)->md.context[2] &= ~7; \
+ (_thread)->md.context[3] = (int) _main; \
+ (_thread)->md.context[4] = (int) _main + 4; \
+ PR_END_MACRO
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ asm("ta 3"); \
+ if (!setjmp(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ longjmp(CONTEXT(_thread), 1); \
+}
+
+#pragma unknown_control_flow(longjmp)
+#pragma unknown_control_flow(setjmp)
+#pragma unknown_control_flow(_PR_Schedule)
+
+/*
+** Missing function prototypes
+*/
+
+extern int socket (int domain, int type, int protocol);
+extern int getsockname (int s, struct sockaddr *name, int *namelen);
+extern int getpeername (int s, struct sockaddr *name, int *namelen);
+extern int getsockopt (int s, int level, int optname, char* optval, int* optlen);
+extern int setsockopt (int s, int level, int optname, const char* optval, int optlen);
+extern int accept (int s, struct sockaddr *addr, int *addrlen);
+extern int listen (int s, int backlog);
+extern int brk(void *);
+extern void *sbrk(int);
+
+
+/* Machine-dependent (MD) data structures. SunOS 4 has no native threads. */
+
+struct _MDThread {
+ jmp_buf context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/* These are copied from _solaris.h */
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
+#define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
+
+#endif /* nspr_sparc_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_unix_errors.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unix_errors.h
new file mode 100644
index 00000000..28cfc35f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unix_errors.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prunixerrors_h___
+#define prunixerrors_h___
+
+#include <unistd.h>
+#include <stddef.h>
+
+PR_BEGIN_EXTERN_C
+
+NSPR_API(void) _MD_unix_map_default_error(int err);
+#define _PR_MD_MAP_DEFAULT_ERROR _MD_unix_map_default_error
+
+NSPR_API(void) _MD_unix_map_opendir_error(int err);
+#define _PR_MD_MAP_OPENDIR_ERROR _MD_unix_map_opendir_error
+
+NSPR_API(void) _MD_unix_map_closedir_error(int err);
+#define _PR_MD_MAP_CLOSEDIR_ERROR _MD_unix_map_closedir_error
+
+NSPR_API(void) _MD_unix_readdir_error(int err);
+#define _PR_MD_MAP_READDIR_ERROR _MD_unix_readdir_error
+
+NSPR_API(void) _MD_unix_map_unlink_error(int err);
+#define _PR_MD_MAP_UNLINK_ERROR _MD_unix_map_unlink_error
+
+NSPR_API(void) _MD_unix_map_stat_error(int err);
+#define _PR_MD_MAP_STAT_ERROR _MD_unix_map_stat_error
+
+NSPR_API(void) _MD_unix_map_fstat_error(int err);
+#define _PR_MD_MAP_FSTAT_ERROR _MD_unix_map_fstat_error
+
+NSPR_API(void) _MD_unix_map_rename_error(int err);
+#define _PR_MD_MAP_RENAME_ERROR _MD_unix_map_rename_error
+
+NSPR_API(void) _MD_unix_map_access_error(int err);
+#define _PR_MD_MAP_ACCESS_ERROR _MD_unix_map_access_error
+
+NSPR_API(void) _MD_unix_map_mkdir_error(int err);
+#define _PR_MD_MAP_MKDIR_ERROR _MD_unix_map_mkdir_error
+
+NSPR_API(void) _MD_unix_map_rmdir_error(int err);
+#define _PR_MD_MAP_RMDIR_ERROR _MD_unix_map_rmdir_error
+
+NSPR_API(void) _MD_unix_map_read_error(int err);
+#define _PR_MD_MAP_READ_ERROR _MD_unix_map_read_error
+
+NSPR_API(void) _MD_unix_map_write_error(int err);
+#define _PR_MD_MAP_WRITE_ERROR _MD_unix_map_write_error
+
+NSPR_API(void) _MD_unix_map_lseek_error(int err);
+#define _PR_MD_MAP_LSEEK_ERROR _MD_unix_map_lseek_error
+
+NSPR_API(void) _MD_unix_map_fsync_error(int err);
+#define _PR_MD_MAP_FSYNC_ERROR _MD_unix_map_fsync_error
+
+NSPR_API(void) _MD_unix_map_close_error(int err);
+#define _PR_MD_MAP_CLOSE_ERROR _MD_unix_map_close_error
+
+NSPR_API(void) _MD_unix_map_socket_error(int err);
+#define _PR_MD_MAP_SOCKET_ERROR _MD_unix_map_socket_error
+
+NSPR_API(void) _MD_unix_map_socketavailable_error(int err);
+#define _PR_MD_MAP_SOCKETAVAILABLE_ERROR _MD_unix_map_socketavailable_error
+
+NSPR_API(void) _MD_unix_map_recv_error(int err);
+#define _PR_MD_MAP_RECV_ERROR _MD_unix_map_recv_error
+
+NSPR_API(void) _MD_unix_map_recvfrom_error(int err);
+#define _PR_MD_MAP_RECVFROM_ERROR _MD_unix_map_recvfrom_error
+
+NSPR_API(void) _MD_unix_map_send_error(int err);
+#define _PR_MD_MAP_SEND_ERROR _MD_unix_map_send_error
+
+NSPR_API(void) _MD_unix_map_sendto_error(int err);
+#define _PR_MD_MAP_SENDTO_ERROR _MD_unix_map_sendto_error
+
+NSPR_API(void) _MD_unix_map_writev_error(int err);
+#define _PR_MD_MAP_WRITEV_ERROR _MD_unix_map_writev_error
+
+NSPR_API(void) _MD_unix_map_accept_error(int err);
+#define _PR_MD_MAP_ACCEPT_ERROR _MD_unix_map_accept_error
+
+NSPR_API(void) _MD_unix_map_connect_error(int err);
+#define _PR_MD_MAP_CONNECT_ERROR _MD_unix_map_connect_error
+
+NSPR_API(void) _MD_unix_map_bind_error(int err);
+#define _PR_MD_MAP_BIND_ERROR _MD_unix_map_bind_error
+
+NSPR_API(void) _MD_unix_map_listen_error(int err);
+#define _PR_MD_MAP_LISTEN_ERROR _MD_unix_map_listen_error
+
+NSPR_API(void) _MD_unix_map_shutdown_error(int err);
+#define _PR_MD_MAP_SHUTDOWN_ERROR _MD_unix_map_shutdown_error
+
+NSPR_API(void) _MD_unix_map_socketpair_error(int err);
+#define _PR_MD_MAP_SOCKETPAIR_ERROR _MD_unix_map_socketpair_error
+
+NSPR_API(void) _MD_unix_map_getsockname_error(int err);
+#define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_unix_map_getsockname_error
+
+NSPR_API(void) _MD_unix_map_getpeername_error(int err);
+#define _PR_MD_MAP_GETPEERNAME_ERROR _MD_unix_map_getpeername_error
+
+NSPR_API(void) _MD_unix_map_getsockopt_error(int err);
+#define _PR_MD_MAP_GETSOCKOPT_ERROR _MD_unix_map_getsockopt_error
+
+NSPR_API(void) _MD_unix_map_setsockopt_error(int err);
+#define _PR_MD_MAP_SETSOCKOPT_ERROR _MD_unix_map_setsockopt_error
+
+NSPR_API(void) _MD_unix_map_open_error(int err);
+#define _PR_MD_MAP_OPEN_ERROR _MD_unix_map_open_error
+
+NSPR_API(void) _MD_unix_map_mmap_error(int err);
+#define _PR_MD_MAP_MMAP_ERROR _MD_unix_map_mmap_error
+
+NSPR_API(void) _MD_unix_map_gethostname_error(int err);
+#define _PR_MD_MAP_GETHOSTNAME_ERROR _MD_unix_map_gethostname_error
+
+NSPR_API(void) _MD_unix_map_select_error(int err);
+#define _PR_MD_MAP_SELECT_ERROR _MD_unix_map_select_error
+
+NSPR_API(void) _MD_unix_map_poll_error(int err);
+#define _PR_MD_MAP_POLL_ERROR _MD_unix_map_poll_error
+
+NSPR_API(void) _MD_unix_map_poll_revents_error(int err);
+#define _PR_MD_MAP_POLL_REVENTS_ERROR _MD_unix_map_poll_revents_error
+
+NSPR_API(void) _MD_unix_map_flock_error(int err);
+#define _PR_MD_MAP_FLOCK_ERROR _MD_unix_map_flock_error
+
+NSPR_API(void) _MD_unix_map_lockf_error(int err);
+#define _PR_MD_MAP_LOCKF_ERROR _MD_unix_map_lockf_error
+
+PR_END_EXTERN_C
+
+#endif /* prunixerrors_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixos.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixos.h
new file mode 100644
index 00000000..60793de1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixos.h
@@ -0,0 +1,641 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prunixos_h___
+#define prunixos_h___
+
+/*
+ * If FD_SETSIZE is not defined on the command line, set the default value
+ * before include select.h
+ */
+/*
+ * Linux: FD_SETSIZE is defined in /usr/include/sys/select.h and should
+ * not be redefined.
+ */
+#if !defined(LINUX) && !defined(DARWIN) && !defined(NEXTSTEP)
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 4096
+#endif
+#endif
+
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include "prio.h"
+#include "prmem.h"
+#include "prclist.h"
+
+/*
+ * For select(), fd_set, and struct timeval.
+ *
+ * In The Single UNIX(R) Specification, Version 2,
+ * the header file for select() is <sys/time.h>.
+ *
+ * fd_set is defined in <sys/types.h>. Usually
+ * <sys/time.h> includes <sys/types.h>, but on some
+ * older systems <sys/time.h> does not include
+ * <sys/types.h>, so we include it explicitly.
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#if defined(AIX) /* Only pre-4.2 AIX needs it, but for simplicity... */
+#include <sys/select.h>
+#endif
+
+#define PR_DIRECTORY_SEPARATOR '/'
+#define PR_DIRECTORY_SEPARATOR_STR "/"
+#define PR_PATH_SEPARATOR ':'
+#define PR_PATH_SEPARATOR_STR ":"
+#define GCPTR
+typedef int (*FARPROC)();
+
+/*
+ * intervals at which GLOBAL threads wakeup to check for pending interrupt
+ */
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+extern PRIntervalTime intr_timeout_ticks;
+
+/*
+ * The bit flags for the in_flags and out_flags fields
+ * of _PR_UnixPollDesc
+ */
+#ifdef _PR_USE_POLL
+#define _PR_UNIX_POLL_READ POLLIN
+#define _PR_UNIX_POLL_WRITE POLLOUT
+#define _PR_UNIX_POLL_EXCEPT POLLPRI
+#define _PR_UNIX_POLL_ERR POLLERR
+#define _PR_UNIX_POLL_NVAL POLLNVAL
+#define _PR_UNIX_POLL_HUP POLLHUP
+#else /* _PR_USE_POLL */
+#define _PR_UNIX_POLL_READ 0x1
+#define _PR_UNIX_POLL_WRITE 0x2
+#define _PR_UNIX_POLL_EXCEPT 0x4
+#define _PR_UNIX_POLL_ERR 0x8
+#define _PR_UNIX_POLL_NVAL 0x10
+#define _PR_UNIX_POLL_HUP 0x20
+#endif /* _PR_USE_POLL */
+
+typedef struct _PRUnixPollDesc {
+ PRInt32 osfd;
+ PRInt16 in_flags;
+ PRInt16 out_flags;
+} _PRUnixPollDesc;
+
+typedef struct PRPollQueue {
+ PRCList links; /* for linking PRPollQueue's together */
+ _PRUnixPollDesc *pds; /* array of poll descriptors */
+ PRUintn npds; /* length of the array */
+ PRPackedBool on_ioq; /* is this on the async i/o work q? */
+ PRIntervalTime timeout; /* timeout, in ticks */
+ struct PRThread *thr;
+} PRPollQueue;
+
+#define _PR_POLLQUEUE_PTR(_qp) \
+ ((PRPollQueue*) ((char*) (_qp) - offsetof(PRPollQueue,links)))
+
+
+extern PRInt32 _PR_WaitForMultipleFDs(
+ _PRUnixPollDesc *unixpds,
+ PRInt32 pdcnt,
+ PRIntervalTime timeout);
+extern void _PR_Unblock_IO_Wait(struct PRThread *thr);
+
+#if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY)
+#define _MD_CHECK_FOR_EXIT()
+#endif
+
+extern fd_set _pr_md_read_set, _pr_md_write_set, _pr_md_exception_set;
+extern PRInt16 _pr_md_read_cnt[], _pr_md_write_cnt[], _pr_md_exception_cnt[];
+extern PRInt32 _pr_md_ioq_max_osfd;
+extern PRUint32 _pr_md_ioq_timeout;
+
+struct _MDFileDesc {
+ int osfd;
+#if defined(LINUX) && defined(_PR_PTHREADS)
+ int tcp_nodelay; /* used by pt_LinuxSendFile */
+#endif
+};
+
+struct _MDDir {
+ DIR *d;
+};
+
+struct _PRCPU;
+extern void _MD_unix_init_running_cpu(struct _PRCPU *cpu);
+
+/*
+** Make a redzone at both ends of the stack segment. Disallow access
+** to those pages of memory. It's ok if the mprotect call's don't
+** work - it just means that we don't really have a functional
+** redzone.
+*/
+#include <sys/mman.h>
+#ifndef PROT_NONE
+#define PROT_NONE 0x0
+#endif
+
+#if defined(DEBUG) && !defined(DARWIN) && !defined(NEXTSTEP)
+#if !defined(SOLARIS)
+#include <string.h> /* for memset() */
+#define _MD_INIT_STACK(ts,REDZONE) \
+ PR_BEGIN_MACRO \
+ (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_NONE); \
+ (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\
+ REDZONE, PROT_NONE); \
+ /* \
+ ** Fill stack memory with something that turns into an illegal \
+ ** pointer value. This will sometimes find runtime references to \
+ ** uninitialized pointers. We don't do this for solaris because we \
+ ** can use purify instead. \
+ */ \
+ if (_pr_debugStacks) { \
+ memset(ts->allocBase + REDZONE, 0xf7, ts->stackSize); \
+ } \
+ PR_END_MACRO
+#else /* !SOLARIS */
+#define _MD_INIT_STACK(ts,REDZONE) \
+ PR_BEGIN_MACRO \
+ (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_NONE); \
+ (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\
+ REDZONE, PROT_NONE); \
+ PR_END_MACRO
+#endif /* !SOLARIS */
+
+/*
+ * _MD_CLEAR_STACK
+ * Allow access to the redzone pages; the access was turned off in
+ * _MD_INIT_STACK.
+ */
+#define _MD_CLEAR_STACK(ts) \
+ PR_BEGIN_MACRO \
+ (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_READ|PROT_WRITE);\
+ (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\
+ REDZONE, PROT_READ|PROT_WRITE); \
+ PR_END_MACRO
+
+#else /* DEBUG */
+
+#define _MD_INIT_STACK(ts,REDZONE)
+#define _MD_CLEAR_STACK(ts)
+
+#endif /* DEBUG */
+
+#if !defined(SOLARIS)
+
+#define PR_SET_INTSOFF(newval)
+
+#endif
+
+/************************************************************************/
+
+extern void _PR_UnixInit(void);
+
+/************************************************************************/
+
+struct _MDProcess {
+ pid_t pid;
+};
+
+struct PRProcess;
+struct PRProcessAttr;
+
+/* Create a new process (fork() + exec()) */
+#define _MD_CREATE_PROCESS _MD_CreateUnixProcess
+extern struct PRProcess * _MD_CreateUnixProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr
+);
+
+#ifdef VBOX
+/* Create a new detached process (fork() + exec()) */
+#define _MD_CREATE_PROCESS_DETACHED _MD_CreateUnixProcessDetached
+extern PRStatus _MD_CreateUnixProcessDetached(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr
+);
+#endif /* VBOX */
+
+#define _MD_DETACH_PROCESS _MD_DetachUnixProcess
+extern PRStatus _MD_DetachUnixProcess(struct PRProcess *process);
+
+/* Wait for a child process to terminate */
+#define _MD_WAIT_PROCESS _MD_WaitUnixProcess
+extern PRStatus _MD_WaitUnixProcess(struct PRProcess *process,
+ PRInt32 *exitCode);
+
+#define _MD_KILL_PROCESS _MD_KillUnixProcess
+extern PRStatus _MD_KillUnixProcess(struct PRProcess *process);
+
+/************************************************************************/
+
+extern void _MD_EnableClockInterrupts(void);
+extern void _MD_DisableClockInterrupts(void);
+
+#define _MD_START_INTERRUPTS _MD_StartInterrupts
+#define _MD_STOP_INTERRUPTS _MD_StopInterrupts
+#define _MD_DISABLE_CLOCK_INTERRUPTS _MD_DisableClockInterrupts
+#define _MD_ENABLE_CLOCK_INTERRUPTS _MD_EnableClockInterrupts
+#define _MD_BLOCK_CLOCK_INTERRUPTS _MD_BlockClockInterrupts
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UnblockClockInterrupts
+
+/************************************************************************/
+
+extern void _MD_InitCPUS(void);
+#define _MD_INIT_CPUS _MD_InitCPUS
+
+extern void _MD_Wakeup_CPUs(void);
+#define _MD_WAKEUP_CPUS _MD_Wakeup_CPUs
+
+#define _MD_PAUSE_CPU _MD_PauseCPU
+
+#if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY)
+#define _MD_CLEANUP_BEFORE_EXIT()
+#endif
+
+#ifndef IRIX
+#define _MD_EXIT(status) _exit(status)
+#endif
+
+/************************************************************************/
+
+#define _MD_GET_ENV getenv
+#define _MD_PUT_ENV putenv
+
+/************************************************************************/
+
+#define _MD_INIT_FILEDESC(fd)
+
+extern void _MD_MakeNonblock(PRFileDesc *fd);
+#define _MD_MAKE_NONBLOCK _MD_MakeNonblock
+
+/************************************************************************/
+
+#if !defined(_PR_PTHREADS)
+
+extern void _MD_InitSegs(void);
+extern PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size,
+ void *vaddr);
+extern void _MD_FreeSegment(PRSegment *seg);
+
+#define _MD_INIT_SEGS _MD_InitSegs
+#define _MD_ALLOC_SEGMENT _MD_AllocSegment
+#define _MD_FREE_SEGMENT _MD_FreeSegment
+
+#endif /* !defined(_PR_PTHREADS) */
+
+/************************************************************************/
+
+#if !defined(HPUX_LW_TIMER)
+#define _MD_INTERVAL_INIT()
+#endif
+#define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
+#define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
+
+/************************************************************************/
+
+#define _MD_ERRNO() (errno)
+#define _MD_GET_SOCKET_ERROR() (errno)
+
+/************************************************************************/
+
+extern PRInt32 _MD_AvailableSocket(PRInt32 osfd);
+
+extern void _MD_StartInterrupts(void);
+extern void _MD_StopInterrupts(void);
+extern void _MD_DisableClockInterrupts(void);
+extern void _MD_BlockClockInterrupts(void);
+extern void _MD_UnblockClockInterrupts(void);
+extern void _MD_PauseCPU(PRIntervalTime timeout);
+
+extern PRStatus _MD_open_dir(struct _MDDir *, const char *);
+extern PRInt32 _MD_close_dir(struct _MDDir *);
+extern char * _MD_read_dir(struct _MDDir *, PRIntn);
+extern PRInt32 _MD_open(const char *name, PRIntn osflags, PRIntn mode);
+extern PRInt32 _MD_delete(const char *name);
+extern PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info);
+extern PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info);
+extern PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info);
+extern PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info);
+extern PRInt32 _MD_rename(const char *from, const char *to);
+extern PRInt32 _MD_access(const char *name, PRAccessHow how);
+extern PRInt32 _MD_mkdir(const char *name, PRIntn mode);
+extern PRInt32 _MD_rmdir(const char *name);
+extern PRInt32 _MD_accept_read(PRInt32 sock, PRInt32 *newSock,
+ PRNetAddr **raddr, void *buf, PRInt32 amount);
+extern PRInt32 _PR_UnixSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout);
+
+extern PRStatus _MD_LockFile(PRInt32 osfd);
+extern PRStatus _MD_TLockFile(PRInt32 osfd);
+extern PRStatus _MD_UnlockFile(PRInt32 osfd);
+
+#define _MD_OPEN_DIR(dir, name) _MD_open_dir(dir, name)
+#define _MD_CLOSE_DIR(dir) _MD_close_dir(dir)
+#define _MD_READ_DIR(dir, flags) _MD_read_dir(dir, flags)
+#define _MD_OPEN(name, osflags, mode) _MD_open(name, osflags, mode)
+#define _MD_OPEN_FILE(name, osflags, mode) _MD_open(name, osflags, mode)
+extern PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount);
+#define _MD_READ(fd,buf,amount) _MD_read(fd,buf,amount)
+extern PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount);
+#define _MD_WRITE(fd,buf,amount) _MD_write(fd,buf,amount)
+#define _MD_DELETE(name) _MD_delete(name)
+#define _MD_GETFILEINFO(fn, info) _MD_getfileinfo(fn, info)
+#define _MD_GETFILEINFO64(fn, info) _MD_getfileinfo64(fn, info)
+#define _MD_GETOPENFILEINFO(fd, info) _MD_getopenfileinfo(fd, info)
+#define _MD_GETOPENFILEINFO64(fd, info) _MD_getopenfileinfo64(fd, info)
+#define _MD_RENAME(from, to) _MD_rename(from, to)
+#define _MD_ACCESS(name, how) _MD_access(name, how)
+#define _MD_MKDIR(name, mode) _MD_mkdir(name, mode)
+#define _MD_MAKE_DIR(name, mode) _MD_mkdir(name, mode)
+#define _MD_RMDIR(name) _MD_rmdir(name)
+#define _MD_ACCEPT_READ(sock, newSock, raddr, buf, amount) _MD_accept_read(sock, newSock, raddr, buf, amount)
+
+#define _MD_LOCKFILE _MD_LockFile
+#define _MD_TLOCKFILE _MD_TLockFile
+#define _MD_UNLOCKFILE _MD_UnlockFile
+
+
+extern PRInt32 _MD_socket(int af, int type, int flags);
+#define _MD_SOCKET _MD_socket
+extern PRInt32 _MD_connect(PRFileDesc *fd, const PRNetAddr *addr,
+ PRUint32 addrlen, PRIntervalTime timeout);
+#define _MD_CONNECT _MD_connect
+extern PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout);
+#define _MD_ACCEPT _MD_accept
+extern PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen);
+#define _MD_BIND _MD_bind
+extern PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog);
+#define _MD_LISTEN _MD_listen
+extern PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how);
+#define _MD_SHUTDOWN _MD_shutdown
+
+extern PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+#define _MD_RECV _MD_recv
+extern PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+#define _MD_SEND _MD_send
+extern PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout);
+#define _MD_RECVFROM _MD_recvfrom
+extern PRInt32 _MD_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout);
+#define _MD_SENDTO _MD_sendto
+extern PRInt32 _MD_writev(PRFileDesc *fd, const struct PRIOVec *iov,
+ PRInt32 iov_size, PRIntervalTime timeout);
+#define _MD_WRITEV _MD_writev
+
+extern PRInt32 _MD_socketavailable(PRFileDesc *fd);
+#define _MD_SOCKETAVAILABLE _MD_socketavailable
+extern PRInt64 _MD_socketavailable64(PRFileDesc *fd);
+#define _MD_SOCKETAVAILABLE64 _MD_socketavailable64
+
+#define _MD_PIPEAVAILABLE _MD_socketavailable
+
+extern PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds,
+ PRIntervalTime timeout);
+#define _MD_PR_POLL _MD_pr_poll
+
+extern PRInt32 _MD_close(PRInt32 osfd);
+#define _MD_CLOSE_FILE _MD_close
+extern PRInt32 _MD_lseek(PRFileDesc*, PRInt32, PRSeekWhence);
+#define _MD_LSEEK _MD_lseek
+extern PRInt64 _MD_lseek64(PRFileDesc*, PRInt64, PRSeekWhence);
+#define _MD_LSEEK64 _MD_lseek64
+extern PRInt32 _MD_fsync(PRFileDesc *fd);
+#define _MD_FSYNC _MD_fsync
+
+extern PRInt32 _MD_socketpair(int af, int type, int flags, PRInt32 *osfd);
+#define _MD_SOCKETPAIR _MD_socketpair
+
+#define _MD_CLOSE_SOCKET _MD_close
+
+#ifndef NO_NSPR_10_SUPPORT
+#define _MD_STAT stat
+#endif
+
+extern PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen);
+#define _MD_GETPEERNAME _MD_getpeername
+extern PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen);
+#define _MD_GETSOCKNAME _MD_getsockname
+
+extern PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, char* optval, PRInt32* optlen);
+#define _MD_GETSOCKOPT _MD_getsockopt
+extern PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, const char* optval, PRInt32 optlen);
+#define _MD_SETSOCKOPT _MD_setsockopt
+
+extern PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable);
+#define _MD_SET_FD_INHERITABLE _MD_set_fd_inheritable
+
+extern void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported);
+#define _MD_INIT_FD_INHERITABLE _MD_init_fd_inheritable
+
+extern void _MD_query_fd_inheritable(PRFileDesc *fd);
+#define _MD_QUERY_FD_INHERITABLE _MD_query_fd_inheritable
+
+extern PRStatus _MD_gethostname(char *name, PRUint32 namelen);
+#define _MD_GETHOSTNAME _MD_gethostname
+
+extern PRStatus _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen);
+#define _MD_GETSYSINFO _MD_getsysinfo
+
+extern int _MD_unix_get_nonblocking_connect_error(int osfd);
+
+/* Memory-mapped files */
+
+struct _MDFileMap {
+ PRIntn prot;
+ PRIntn flags;
+ PRBool isAnonFM; /* when true, PR_CloseFileMap() must close the related fd */
+};
+
+extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
+#define _MD_CREATE_FILE_MAP _MD_CreateFileMap
+
+#define _MD_GET_MEM_MAP_ALIGNMENT() PR_GetPageSize()
+
+extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
+ PRUint32 len);
+#define _MD_MEM_MAP _MD_MemMap
+
+extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
+#define _MD_MEM_UNMAP _MD_MemUnmap
+
+extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
+#define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
+
+/*
+ * The standard (XPG4) gettimeofday() (from BSD) takes two arguments.
+ * On some SVR4 derivatives, gettimeofday() takes only one argument.
+ * The GETTIMEOFDAY macro is intended to hide this difference.
+ */
+#ifdef HAVE_SVID_GETTOD
+#define GETTIMEOFDAY(tp) gettimeofday(tp)
+#else
+#define GETTIMEOFDAY(tp) gettimeofday((tp), NULL)
+#endif
+
+#if defined(_PR_PTHREADS) && !defined(_PR_POLL_AVAILABLE)
+#define _PR_NEED_FAKE_POLL
+#endif
+
+#if defined(_PR_NEED_FAKE_POLL)
+
+/*
+ * Some platforms don't have poll(), but our pthreads code calls poll().
+ * As a temporary measure, I implemented a fake poll() using select().
+ * Here are the struct and macro definitions copied from sys/poll.h
+ * on Solaris 2.5.
+ */
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+/* poll events */
+
+#define POLLIN 0x0001 /* fd is readable */
+#define POLLPRI 0x0002 /* high priority info at fd */
+#define POLLOUT 0x0004 /* fd is writeable (won't block) */
+#define POLLRDNORM 0x0040 /* normal data is readable */
+#define POLLWRNORM POLLOUT
+#define POLLRDBAND 0x0080 /* out-of-band data is readable */
+#define POLLWRBAND 0x0100 /* out-of-band data is writeable */
+
+#define POLLNORM POLLRDNORM
+
+#define POLLERR 0x0008 /* fd has error condition */
+#define POLLHUP 0x0010 /* fd has been hung up on */
+#define POLLNVAL 0x0020 /* invalid pollfd entry */
+
+extern int poll(struct pollfd *, unsigned long, int);
+
+#endif /* _PR_NEED_FAKE_POLL */
+
+/*
+** A vector of the UNIX I/O calls we use. These are here to smooth over
+** the rough edges needed for large files. All of NSPR's implmentaions
+** go through this vector using syntax of the form
+** result = _md_iovector.xxx64(args);
+*/
+
+#if defined(SOLARIS2_5)
+/*
+** Special case: Solaris 2.5.1
+** Solaris starts to have 64-bit file I/O in 2.6. We build on Solaris
+** 2.5.1 so that we can use the same binaries on both Solaris 2.5.1 and
+** 2.6. At run time, we detect whether 64-bit file I/O is available by
+** looking up the 64-bit file function symbols in libc. At build time,
+** we need to define the 64-bit file I/O datatypes that are compatible
+** with their definitions on Solaris 2.6.
+*/
+typedef PRInt64 off64_t;
+typedef PRUint64 ino64_t;
+typedef PRInt64 blkcnt64_t;
+struct stat64 {
+ dev_t st_dev;
+ long st_pad1[3];
+ ino64_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ long t_pad2[2];
+ off64_t st_size;
+ timestruc_t st_atim;
+ timestruc_t st_mtim;
+ timestruc_t st_ctim;
+ long st_blksize;
+ blkcnt64_t st_blocks;
+ char st_fstype[_ST_FSTYPSZ];
+ long st_pad4[8];
+};
+typedef struct stat64 _MDStat64;
+typedef off64_t _MDOff64_t;
+
+#elif defined(_PR_HAVE_OFF64_T)
+typedef struct stat64 _MDStat64;
+typedef off64_t _MDOff64_t;
+#elif defined(_PR_HAVE_LARGE_OFF_T)
+typedef struct stat _MDStat64;
+typedef off_t _MDOff64_t;
+#elif defined(_PR_NO_LARGE_FILES)
+typedef struct stat _MDStat64;
+typedef PRInt64 _MDOff64_t;
+#else
+#error "I don't know yet"
+#endif
+
+typedef PRIntn (*_MD_Fstat64)(PRIntn osfd, _MDStat64 *buf);
+typedef PRIntn (*_MD_Open64)(const char *path, int oflag, ...);
+#if defined(VMS)
+typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf, ...);
+#else
+typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf);
+#endif
+typedef _MDOff64_t (*_MD_Lseek64)(PRIntn osfd, _MDOff64_t, PRIntn whence);
+typedef void* (*_MD_Mmap64)(
+ void *addr, PRSize len, PRIntn prot, PRIntn flags,
+ PRIntn fildes, _MDOff64_t offset);
+struct _MD_IOVector
+{
+ _MD_Open64 _open64;
+ _MD_Mmap64 _mmap64;
+ _MD_Stat64 _stat64;
+ _MD_Fstat64 _fstat64;
+ _MD_Lseek64 _lseek64;
+};
+extern struct _MD_IOVector _md_iovector;
+
+#endif /* prunixos_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.cfg
new file mode 100644
index 00000000..796e748d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.cfg
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef UNIXWARE
+#define UNIXWARE
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#undef HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.h
new file mode 100644
index 00000000..bdc084f2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware.h
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_unixware_defs_h___
+#define nspr_unixware_defs_h___
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "unixware"
+#define _PR_SI_SYSNAME "UnixWare"
+#define _PR_SI_ARCHITECTURE "x86"
+#define PR_DLL_SUFFIX ".so"
+
+#define _PR_VMBASE 0x30000000
+#define _PR_STACK_VMBASE 0x50000000
+#define _MD_DEFAULT_STACK_SIZE 65536L
+#define _MD_MMAP_FLAGS MAP_PRIVATE
+
+#ifndef HAVE_WEAK_IO_SYMBOLS
+#define HAVE_WEAK_IO_SYMBOLS
+#endif
+#define _PR_POLL_AVAILABLE
+#define _PR_USE_POLL
+#define _PR_STAT_HAS_ST_ATIM_UNION
+
+#undef HAVE_STACK_GROWING_UP
+#define HAVE_NETCONFIG
+#define HAVE_DLL
+#define USE_DLFCN
+#define HAVE_STRERROR
+#define NEED_STRFTIME_LOCK
+#define NEED_TIME_R
+#define _PR_NEED_STRCASECMP
+
+#define USE_SETJMP
+
+#include <setjmp.h>
+
+#define _SETJMP setjmp
+#define _LONGJMP longjmp
+#define _PR_CONTEXT_TYPE jmp_buf
+#define _MD_GET_SP(_t) (_t)->md.context[4]
+#define _PR_NUM_GCREGS _JBLEN
+
+#define CONTEXT(_th) ((_th)->md.context)
+
+/*
+** Initialize the thread context preparing it to execute _main.
+*/
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+{ \
+ *status = PR_TRUE; \
+ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \
+ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \
+}
+
+#define _MD_SWITCH_CONTEXT(_thread) \
+ if (!_SETJMP(CONTEXT(_thread))) { \
+ (_thread)->md.errcode = errno; \
+ _PR_Schedule(); \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _MD_RESTORE_CONTEXT(_thread) \
+{ \
+ errno = (_thread)->md.errcode; \
+ _MD_SET_CURRENT_THREAD(_thread); \
+ _LONGJMP(CONTEXT(_thread), 1); \
+}
+
+/* Machine-dependent (MD) data structures.
+ * Don't use SVR4 native threads (yet).
+ */
+
+struct _MDThread {
+ _PR_CONTEXT_TYPE context;
+ int id;
+ int errcode;
+};
+
+struct _MDThreadStack {
+ PRInt8 notused;
+};
+
+struct _MDLock {
+ PRInt8 notused;
+};
+
+struct _MDSemaphore {
+ PRInt8 notused;
+};
+
+struct _MDCVar {
+ PRInt8 notused;
+};
+
+struct _MDSegment {
+ PRInt8 notused;
+};
+
+/*
+ * md-specific cpu structure field
+ */
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+
+struct _MDCPU_Unix {
+ PRCList ioQ;
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+ PRInt32 ioq_osfd_cnt;
+#ifndef _PR_USE_POLL
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+#else
+ struct pollfd *ioq_pollfds;
+ int ioq_pollfds_size;
+#endif /* _PR_USE_POLL */
+};
+
+#define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd)
+#define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt)
+#define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds)
+#define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
+
+#define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32
+
+struct _MDCPU {
+ struct _MDCPU_Unix md_unix;
+};
+
+#define _MD_INIT_LOCKS()
+#define _MD_NEW_LOCK(lock) PR_SUCCESS
+#define _MD_FREE_LOCK(lock)
+#define _MD_LOCK(lock)
+#define _MD_UNLOCK(lock)
+#define _MD_INIT_IO()
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+/*
+ * The following are copied from _sunos.h, _aix.h. This means
+ * some of them should probably be moved into _unixos.h. But
+ * _irix.h seems to be quite different in regard to these macros.
+ */
+#define _MD_GET_INTERVAL _PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond
+
+#define _MD_EARLY_INIT _MD_EarlyInit
+#define _MD_FINAL_INIT _PR_UnixInit
+#define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
+#define _MD_INIT_THREAD _MD_InitializeThread
+#define _MD_EXIT_THREAD(thread)
+#define _MD_SUSPEND_THREAD(thread)
+#define _MD_RESUME_THREAD(thread)
+#define _MD_CLEAN_THREAD(_thread)
+
+/*
+ * We wrapped the select() call. _MD_SELECT refers to the built-in,
+ * unwrapped version.
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *execptfds, struct timeval *timeout);
+#define _MD_SELECT _select
+
+#define _MD_POLL _poll
+extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
+
+#endif /* nspr_unixware_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware7.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware7.cfg
new file mode 100644
index 00000000..c37bd3c9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_unixware7.cfg
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+
+#ifndef UNIXWARE
+#define UNIXWARE
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+#define HAVE_LONG_LONG
+#undef HAVE_ALIGNED_DOUBLES
+#undef HAVE_ALIGNED_LONGLONGS
+
+#define PR_AF_INET6 27 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 4
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define _PR_POLL_BACKCOMPAT
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_vbox.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_vbox.cfg
new file mode 100644
index 00000000..ce3c1dde
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_vbox.cfg
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * innotek
+ *
+ * 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 nspr_vboxcfg___
+#define nspr_vboxcfg___
+
+#ifdef RT_OS_DARWIN
+# include <md/_darwin.cfg>
+#elif defined(RT_OS_FREEBSD)
+# include <md/_freebsd.cfg>
+#elif defined(RT_OS_L4)
+# include <md/_l4v2.cfg>
+#elif defined(RT_OS_LINUX)
+# include <md/_linux.cfg>
+#elif defined(RT_OS_NETBSD)
+# include <md/_netbsd.cfg>
+#elif defined(RT_OS_OPENBSD)
+# include <md/_openbsd.cfg>
+#elif defined(RT_OS_SOLARIS)
+# if defined(RT_ARCH_X86)
+# include <md/_solaris32.cfg>
+# else
+# include <md/_solaris64.cfg>
+# endif
+#elif defined(RT_OS_OS2)
+# include <md/_os2.cfg>
+#else
+# error "Define the correct platform identifier / Port me."
+#endif
+
+#endif /* !nspr_vboxcfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.cfg
new file mode 100644
index 00000000..330db386
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.cfg
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** _win16.cfg -- prcpucfg.h for win16
+**
+**
+** lth. 14-Apr-1997. New. Made from _win95.cfg
+*/
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_PC
+#define XP_PC
+#endif
+
+#ifndef WIN16
+#define WIN16
+#undef WIN32
+#endif
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 2
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_DOUBLE 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 16
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+#define PR_BITS_PER_DOUBLE 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 4
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_WORD_LOG2 4
+#define PR_BITS_PER_DWORD_LOG2 6
+#define PR_BITS_PER_DOUBLE_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 2
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_WORD 2
+#define PR_ALIGN_OF_DWORD 8
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 2
+
+#else /* defined(_M_IX86) || defined(_X86_) */
+
+#error unknown processor architecture
+
+#endif /* defined(_M_IX86) || defined(_X86_) */
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#undef HAVE_LONG_LONG
+
+/*
+** HAVE_WATCOM_BUG_1
+** When HAVE_WATCOM_BUG_1 is defined, special case code is
+** used to circumvent the bug.
+** Functions declared __cdecl in DLLs returning floating point types
+** generate bad return code and will not return the intended result.
+*/
+#define HAVE_WATCOM_BUG_1
+
+/*
+** HAVE_WATCOM_BUG_2
+** When HAVE_WATCOM_BUG_2 is defined, special case code is
+** used to circumvent the bug.
+** Functions declared __cdecl in DLLs returning a structure by value
+** generate bad return values.
+** Yes, similar to Watcom Bug 1.
+*/
+#define HAVE_WATCOM_BUG_2
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.h
new file mode 100644
index 00000000..d7e79c22
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win16.h
@@ -0,0 +1,568 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_win16_defs_h___
+#define nspr_win16_defs_h___
+
+#include <windows.h>
+#include <winsock.h>
+#include <errno.h>
+#include <direct.h>
+
+#include "nspr.h"
+/* $$ fix this */
+#define Remind(x)
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "win16"
+#define _PR_SI_SYSNAME "WIN16"
+#define _PR_SI_ARCHITECTURE "x86" /* XXXMB hardcode for now */
+
+#define HAVE_DLL
+#define _PR_NO_PREEMPT
+#define _PR_LOCAL_THREADS_ONLY
+#undef _PR_GLOBAL_THREADS_ONLY
+#undef HAVE_THREAD_AFFINITY
+#define _PR_HAVE_ATOMIC_OPS
+
+/* --- Common User-Thread/Native-Thread Definitions --------------------- */
+
+extern struct PRLock *_pr_schedLock;
+extern char * _pr_top_of_task_stack;
+
+
+/* --- Typedefs --- */
+
+#define PR_NUM_GCREGS 9
+typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS];
+
+#define _MD_MAGIC_THREAD 0x22222222
+#define _MD_MAGIC_THREADSTACK 0x33333333
+#define _MD_MAGIC_SEGMENT 0x44444444
+#define _MD_MAGIC_DIR 0x55555555
+#define _MD_MAGIC_CV 0x66666666
+
+
+typedef struct _PRWin16PollDesc
+{
+ PRInt32 osfd;
+ PRInt16 in_flags;
+ PRInt16 out_flags;
+} _PRWin16PollDesc;
+
+typedef struct PRPollQueue
+{
+ PRCList links; /* for linking PRPollQueue's together */
+ _PRWin16PollDesc *pds; /* array of poll descriptors */
+ PRUintn npds; /* length of the array */
+ PRPackedBool on_ioq; /* is this on the async i/o work q? */
+ PRIntervalTime timeout; /* timeout, in ticks */
+ struct PRThread *thr;
+} PRPollQueue;
+
+#define _PR_POLLQUEUE_PTR(_qp) \
+ ((PRPollQueue *) ((char*) (_qp) - offsetof(PRPollQueue,links)))
+
+NSPR_API(PRInt32) _PR_WaitForFD(PRInt32 osfd, PRUintn how,
+ PRIntervalTime timeout);
+NSPR_API(void) _PR_Unblock_IO_Wait(struct PRThread *thr);
+
+#define _PR_MD_MAX_OSFD FD_SETSIZE
+#define _PR_IOQ(_cpu) ((_cpu)->md.ioQ)
+#define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
+#define _PR_FD_READ_SET(_cpu) ((_cpu)->md.fd_read_set)
+#define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.fd_read_cnt)
+#define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.fd_write_set)
+#define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.fd_write_cnt)
+#define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.fd_exception_set)
+#define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.fd_exception_cnt)
+#define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.ioq_timeout)
+#define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.ioq_max_osfd)
+
+struct _MDCPU {
+ PRCList ioQ;
+ fd_set fd_read_set, fd_write_set, fd_exception_set;
+ PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
+ fd_exception_cnt[_PR_MD_MAX_OSFD];
+ PRUint32 ioq_timeout;
+ PRInt32 ioq_max_osfd;
+};
+
+struct _MDThread {
+ /* The overlapped structure must be first! */
+ HANDLE blocked_sema; /* Threads block on this when waiting
+ * for IO or CondVar.
+ */
+ PRInt32 errcode; /* preserved errno for this thread */
+ CATCHBUF context; /* thread context for Throw() */
+ void *SP; /* Stack pointer, used only by GarbColl */
+ int threadNumber; /* instrumentation: order of creation */
+ _PRWin16PollDesc thr_pd; /* poll descriptor for i/o */
+ PRPollQueue thr_pq; /* i/o parameters */
+ void *exceptionContext; /* mfc exception context */
+ char guardBand[24]; /* don't overwrite this */
+ PRUint32 magic; /* self identifier, for debug */
+};
+
+struct _MDThreadStack {
+ PRUint32 magic; /* for debugging */
+ PRIntn cxByteCount; /* number of stack bytes to move */
+ char * stackTop; /* high address on stack */
+};
+
+struct _MDSegment {
+ PRUint32 magic; /* for debugging */
+};
+
+
+struct _MDLock {
+ PRUint32 magic; /* for debugging */
+ PRUint32 mutex;
+};
+
+struct _MDDir {
+ PRUint32 magic; /* for debugging */
+ struct dirent *dir;
+};
+
+struct _MDCVar {
+ PRUint32 magic;
+};
+
+struct _MDSemaphore {
+ PRInt32 unused;
+};
+
+struct _MDFileDesc {
+ PRInt32 osfd;
+};
+
+struct _MDProcess {
+ HANDLE handle;
+ DWORD id;
+};
+
+/*
+** Microsoft 'struct _stat'
+** ... taken directly from msvc 1.52c's header file sys/stat.h
+** see PR_Stat() implemented in w16io.c
+** See BugSplat: 98516
+*/
+#pragma pack(push)
+#pragma pack(2)
+
+typedef unsigned short _ino_t;
+typedef short _dev_t;
+typedef long _off_t;
+
+typedef struct _MDMSStat {
+ _dev_t st_dev;
+ _ino_t st_ino;
+ unsigned short st_mode;
+ short st_nlink;
+ short st_uid;
+ short st_gid;
+ _dev_t st_rdev;
+ _off_t st_size;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+} _MDMSStat;
+#pragma pack(pop)
+
+/* --- Errors --- */
+ /* These are NSPR generated error codes which need to be unique from
+ * OS error codes.
+ */
+#define _MD_UNIQUEBASE 50000
+#define _MD_EINTERRUPTED _MD_UNIQUEBASE + 1
+#define _MD_ETIMEDOUT _MD_UNIQUEBASE + 2
+#define _MD_EIO _MD_UNIQUEBASE + 3
+
+struct PRProcess;
+struct PRProcessAttr;
+
+/* --- Create a new process --- */
+#define _MD_CREATE_PROCESS _PR_CreateWindowsProcess
+extern struct PRProcess * _PR_CreateWindowsProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr
+);
+
+#define _MD_DETACH_PROCESS _PR_DetachWindowsProcess
+extern PRStatus _PR_DetachWindowsProcess(struct PRProcess *process);
+
+/* --- Wait for a child process to terminate --- */
+#define _MD_WAIT_PROCESS _PR_WaitWindowsProcess
+extern PRStatus _PR_WaitWindowsProcess(struct PRProcess *process,
+ PRInt32 *exitCode);
+
+#define _MD_KILL_PROCESS _PR_KillWindowsProcess
+extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
+
+
+/* --- Misc stuff --- */
+
+#define MD_ASSERTINT( x ) PR_ASSERT( (x) < 65535 )
+
+/* --- IO stuff --- */
+#define MAX_PATH 256
+#define _MD_ERRNO() errno
+#define GetLastError() errno
+
+#define _MD_GET_FILE_ERROR() errno
+#define _MD_SET_FILE_ERROR(_err) errno = (_err)
+
+#define _MD_OPEN _PR_MD_OPEN
+#define _MD_READ _PR_MD_READ
+#define _MD_WRITE _PR_MD_WRITE
+#define _MD_WRITEV _PR_MD_WRITEV
+#define _MD_LSEEK _PR_MD_LSEEK
+#define _MD_LSEEK64 _PR_MD_LSEEK64
+#define _MD_CLOSE_FILE _PR_MD_CLOSE_FILE
+#define _MD_GETFILEINFO _PR_MD_GETFILEINFO
+#define _MD_GETOPENFILEINFO _PR_MD_GETOPENFILEINFO
+#define _MD_STAT _PR_MD_STAT
+#define _MD_RENAME _PR_MD_RENAME
+#define _MD_ACCESS _PR_MD_ACCESS
+#define _MD_DELETE _PR_MD_DELETE
+#define _MD_MKDIR _PR_MD_MKDIR
+#define _MD_RMDIR _PR_MD_RMDIR
+#define _MD_LOCKFILE _PR_MD_LOCKFILE
+#define _MD_TLOCKFILE _PR_MD_TLOCKFILE
+#define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE
+
+
+/* --- Socket IO stuff --- */
+#define _MD_EACCES WSAEACCES
+#define _MD_EADDRINUSE WSAEADDRINUSE
+#define _MD_EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define _MD_EAFNOSUPPORT WSAEAFNOSUPPORT
+#define _MD_EAGAIN WSAEWOULDBLOCK
+#define _MD_EALREADY WSAEALREADY
+#define _MD_EBADF WSAEBADF
+#define _MD_ECONNREFUSED WSAECONNREFUSED
+#define _MD_ECONNRESET WSAECONNRESET
+#define _MD_EFAULT WSAEFAULT
+#define _MD_EINPROGRESS WSAEINPROGRESS
+#define _MD_EINTR WSAEINTR
+#define _MD_EINVAL EINVAL
+#define _MD_EISCONN WSAEISCONN
+#define _MD_ENETUNREACH WSAENETUNREACH
+#define _MD_ENOENT ENOENT
+#define _MD_ENOTCONN WSAENOTCONN
+#define _MD_ENOTSOCK WSAENOTSOCK
+#define _MD_EOPNOTSUPP WSAEOPNOTSUPP
+#define _MD_EWOULDBLOCK WSAEWOULDBLOCK
+#define _MD_GET_SOCKET_ERROR() WSAGetLastError()
+#define _MD_SET_SOCKET_ERROR(_err) WSASetLastError(_err)
+
+#define _MD_INIT_FILEDESC(fd)
+#define _MD_MAKE_NONBLOCK _PR_MD_MAKE_NONBLOCK
+#define _MD_SHUTDOWN _PR_MD_SHUTDOWN
+#define _MD_LISTEN _PR_MD_LISTEN
+#define _MD_CLOSE_SOCKET _PR_MD_CLOSE_SOCKET
+#define _MD_SENDTO _PR_MD_SENDTO
+#define _MD_RECVFROM _PR_MD_RECVFROM
+#define _MD_SOCKETPAIR(s, type, proto, sv) -1
+#define _MD_GETSOCKNAME _PR_MD_GETSOCKNAME
+#define _MD_GETPEERNAME _PR_MD_GETPEERNAME
+#define _MD_GETSOCKOPT _PR_MD_GETSOCKOPT
+#define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT
+#define _MD_SELECT select
+#define _MD_FSYNC _PR_MD_FSYNC
+#define _MD_SOCKETAVAILABLE _PR_MD_SOCKETAVAILABLE
+
+#define _MD_INIT_ATOMIC()
+#define _MD_ATOMIC_INCREMENT(x) (*x++)
+#define _MD_ATOMIC_ADD(ptr, val) ((*x) += val)
+#define _MD_ATOMIC_DECREMENT(x) (*x--)
+#define _MD_ATOMIC_SET(x,y) (*x, y)
+
+#define _MD_INIT_IO _PR_MD_INIT_IO
+
+/* win95 doesn't have async IO */
+#define _MD_SOCKET _PR_MD_SOCKET
+#define _MD_CONNECT _PR_MD_CONNECT
+#define _MD_ACCEPT _PR_MD_ACCEPT
+#define _MD_BIND _PR_MD_BIND
+#define _MD_RECV _PR_MD_RECV
+#define _MD_SEND _PR_MD_SEND
+
+#define _MD_CHECK_FOR_EXIT()
+
+/* --- Scheduler stuff --- */
+#define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU
+
+/* --- DIR stuff --- */
+#define PR_DIRECTORY_SEPARATOR '\\'
+#define PR_DIRECTORY_SEPARATOR_STR "\\"
+#define PR_PATH_SEPARATOR ';'
+#define PR_PATH_SEPARATOR_STR ";"
+#define _MD_OPEN_DIR _PR_MD_OPEN_DIR
+#define _MD_CLOSE_DIR _PR_MD_CLOSE_DIR
+#define _MD_READ_DIR _PR_MD_READ_DIR
+
+/* --- Segment stuff --- */
+#define _MD_INIT_SEGS()
+#define _MD_ALLOC_SEGMENT _MD_AllocSegment
+#define _MD_FREE_SEGMENT _MD_FreeSegment
+
+/* --- Environment Stuff --- */
+#define _MD_GET_ENV _PR_MD_GET_ENV
+#define _MD_PUT_ENV _PR_MD_PUT_ENV
+
+/* --- Threading Stuff --- */
+#define _MD_DEFAULT_STACK_SIZE 32767L
+#define _MD_INIT_THREAD _PR_MD_INIT_THREAD
+#define _MD_CREATE_THREAD(t,f,p,sc,st,stsiz) (PR_SUCCESS)
+#define _MD_YIELD _PR_MD_YIELD
+#define _MD_SET_PRIORITY(t,p)
+#define _MD_CLEAN_THREAD(t)
+#define _MD_SETTHREADAFFINITYMASK _PR_MD_SETTHREADAFFINITYMASK
+#define _MD_GETTHREADAFFINITYMASK _PR_MD_GETTHREADAFFINITYMASK
+#define _MD_EXIT_THREAD
+#define _MD_SUSPEND_THREAD _PR_MD_SUSPEND_THREAD
+#define _MD_RESUME_THREAD _PR_MD_RESUME_THREAD
+#define _MD_SUSPEND_CPU _PR_MD_SUSPEND_CPU
+#define _MD_RESUME_CPU _PR_MD_RESUME_CPU
+#define _MD_BEGIN_SUSPEND_ALL()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_SUSPEND_ALL()
+#define _MD_END_RESUME_ALL()
+
+/* --- Lock stuff --- */
+/*
+** Win16 does not need MD locks.
+*/
+#define _PR_LOCK _MD_LOCK
+#define _PR_UNLOCK _MD_UNLOCK
+
+#define _MD_NEW_LOCK(l) (PR_SUCCESS)
+#define _MD_FREE_LOCK(l)
+#define _MD_LOCK(l)
+#define _MD_TEST_AND_LOCK(l) (-1)
+#define _MD_UNLOCK(l)
+
+/* --- lock and cv waiting --- */
+#define _MD_WAIT _PR_MD_WAIT
+#define _MD_WAKEUP_WAITER(a)
+#define _MD_WAKEUP_CPUS _PR_MD_WAKEUP_CPUS
+
+/* --- CVar ------------------- */
+#define _MD_WAIT_CV _PR_MD_WAIT_CV
+#define _MD_NEW_CV _PR_MD_NEW_CV
+#define _MD_FREE_CV _PR_MD_FREE_CV
+#define _MD_NOTIFY_CV _PR_MD_NOTIFY_CV
+#define _MD_NOTIFYALL_CV _PR_MD_NOTIFYALL_CV
+
+ /* XXXMB- the IOQ stuff is certainly not working correctly yet. */
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+
+/* --- Initialization stuff --- */
+NSPR_API(void) _MD_INIT_RUNNING_CPU(struct _PRCPU *cpu );
+#define _MD_START_INTERRUPTS()
+#define _MD_STOP_INTERRUPTS()
+#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
+#define _MD_BLOCK_CLOCK_INTERRUPTS()
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
+#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
+#define _MD_FINAL_INIT _PR_MD_FINAL_INIT
+#define _MD_INIT_CPUS()
+
+/* --- User Threading stuff --- */
+#define _MD_EXIT
+
+#define _MD_CLEANUP_BEFORE_EXIT _PR_MD_CLEANUP_BEFORE_EXIT
+
+/* --- Intervals --- */
+#define _MD_INTERVAL_INIT _PR_MD_INTERVAL_INIT
+#define _MD_GET_INTERVAL _PR_MD_GET_INTERVAL
+#define _MD_INTERVAL_PER_SEC _PR_MD_INTERVAL_PER_SEC
+#define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
+#define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
+
+/* --- Scheduler stuff --- */
+#define LOCK_SCHEDULER() 0
+#define UNLOCK_SCHEDULER() 0
+#define _PR_LockSched() 0
+#define _PR_UnlockSched() 0
+
+/* --- Initialization stuff --- */
+#define _MD_INIT_LOCKS()
+
+/* --- Stack stuff --- */
+#define _MD_INIT_STACK _PR_MD_INIT_STACK
+#define _MD_CLEAR_STACK(stack)
+
+/*
+** Watcom needs to see this to make the linker work.
+**
+*/
+NSPR_API(void) _PR_NativeDestroyThread(PRThread *thread);
+NSPR_API(void) _PR_UserDestroyThread(PRThread *thread);
+
+
+/*
+** If thread emulation is used, then setjmp/longjmp stores the register
+** state of each thread.
+**
+** CatchBuf layout:
+** context[0] - IP
+** context[1] - CS
+** context[2] - SP
+** context[3] - BP
+** context[4] - SI
+** context[5] - DI
+** context[6] - DS
+** context[7] - ?? (maybe flags)
+** context[8] - SS
+*/
+#define PR_CONTEXT_TYPE CATCHBUF
+#define PR_NUM_GCREGS 9
+
+#define _MD_GET_SP(thread) ((thread)->md.SP)
+#define CONTEXT(_t) ((_t)->md.context)
+
+/*
+** Initialize a thread context to run "e(o,a)" when started
+*/
+#define _MD_INIT_CONTEXT(_t, sp, epa, stat ) \
+{ \
+ *(stat) = PR_TRUE; \
+ Catch((_t)->md.context ); \
+ (_t)->md.context[0] = OFFSETOF(epa); \
+ (_t)->md.context[1] = SELECTOROF(epa); \
+ (_t)->md.context[2] = OFFSETOF(_pr_top_of_task_stack - 64); \
+ (_t)->md.context[3] = 0; \
+}
+
+#define _MD_SWITCH_CONTEXT(_t) \
+ if (!Catch((_t)->md.context)) { \
+ int garbCollPlaceHolder; \
+ (_t)->md.errcode = errno; \
+ (_t)->md.SP = &garbCollPlaceHolder; \
+ _PR_Schedule(); \
+ }
+
+#define _MD_SAVE_CONTEXT(_t) \
+ { \
+ int garbCollPlaceHolder; \
+ Catch((_t)->md.context); \
+ (_t)->md.errcode = errno; \
+ (_t)->md.SP = &garbCollPlaceHolder; \
+ }
+
+/*
+** Restore a thread context, saved by _MD_SWITCH_CONTEXT
+*/
+#define _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT
+
+/*
+ * Memory-mapped files
+ */
+
+struct _MDFileMap {
+ PRInt8 unused;
+};
+
+extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
+#define _MD_CREATE_FILE_MAP _MD_CreateFileMap
+
+extern PRInt32 _MD_GetMemMapAlignment(void);
+#define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment
+
+extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
+ PRUint32 len);
+#define _MD_MEM_MAP _MD_MemMap
+
+extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
+#define _MD_MEM_UNMAP _MD_MemUnmap
+
+extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
+#define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
+
+
+/* --- Error mapping ----------------------------------- */
+extern void _PR_MD_map_error( int err );
+
+#define _PR_MD_MAP_OPENDIR_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_CLOSEDIR_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_READDIR_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_DELETE_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_STAT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_FSTAT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_RENAME_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_ACCESS_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_MKDIR_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_RMDIR_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_READ_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_TRANSMITFILE_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_WRITE_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_LSEEK_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_FSYNC_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_CLOSE_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_SOCKET_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_RECV_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_RECVFROM_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_SEND_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_SENDTO_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_ACCEPT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_ACCEPTEX_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_CONNECT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_BIND_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_LISTEN_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_SHUTDOWN_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_GETSOCKNAME_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_GETPEERNAME_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_GETSOCKOPT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_SETSOCKOPT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_OPEN_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_GETHOSTNAME_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_SELECT_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_LOCKF_ERROR _PR_MD_map_error
+#define _PR_MD_MAP_WSASTARTUP_ERROR _PR_MD_map_error
+
+#endif /* nspr_win16_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_win32_errors.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win32_errors.h
new file mode 100644
index 00000000..d5d8b714
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win32_errors.h
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_win32_errors_h___
+#define nspr_win32_errors_h___
+
+#include <windows.h>
+#include <winsock.h>
+#include <errno.h>
+
+
+extern void _MD_win32_map_default_error(PRInt32 err);
+#define _PR_MD_MAP_DEFAULT_ERROR _MD_win32_map_default_error
+
+extern void _MD_win32_map_opendir_error(PRInt32 err);
+#define _PR_MD_MAP_OPENDIR_ERROR _MD_win32_map_opendir_error
+
+extern void _MD_win32_map_closedir_error(PRInt32 err);
+#define _PR_MD_MAP_CLOSEDIR_ERROR _MD_win32_map_closedir_error
+
+extern void _MD_unix_readdir_error(PRInt32 err);
+#define _PR_MD_MAP_READDIR_ERROR _MD_unix_readdir_error
+
+extern void _MD_win32_map_delete_error(PRInt32 err);
+#define _PR_MD_MAP_DELETE_ERROR _MD_win32_map_delete_error
+
+extern void _MD_win32_map_stat_error(PRInt32 err);
+#define _PR_MD_MAP_STAT_ERROR _MD_win32_map_stat_error
+
+extern void _MD_win32_map_fstat_error(PRInt32 err);
+#define _PR_MD_MAP_FSTAT_ERROR _MD_win32_map_fstat_error
+
+extern void _MD_win32_map_rename_error(PRInt32 err);
+#define _PR_MD_MAP_RENAME_ERROR _MD_win32_map_rename_error
+
+extern void _MD_win32_map_access_error(PRInt32 err);
+#define _PR_MD_MAP_ACCESS_ERROR _MD_win32_map_access_error
+
+extern void _MD_win32_map_mkdir_error(PRInt32 err);
+#define _PR_MD_MAP_MKDIR_ERROR _MD_win32_map_mkdir_error
+
+extern void _MD_win32_map_rmdir_error(PRInt32 err);
+#define _PR_MD_MAP_RMDIR_ERROR _MD_win32_map_rmdir_error
+
+extern void _MD_win32_map_read_error(PRInt32 err);
+#define _PR_MD_MAP_READ_ERROR _MD_win32_map_read_error
+
+extern void _MD_win32_map_transmitfile_error(PRInt32 err);
+#define _PR_MD_MAP_TRANSMITFILE_ERROR _MD_win32_map_transmitfile_error
+
+extern void _MD_win32_map_write_error(PRInt32 err);
+#define _PR_MD_MAP_WRITE_ERROR _MD_win32_map_write_error
+
+extern void _MD_win32_map_lseek_error(PRInt32 err);
+#define _PR_MD_MAP_LSEEK_ERROR _MD_win32_map_lseek_error
+
+extern void _MD_win32_map_fsync_error(PRInt32 err);
+#define _PR_MD_MAP_FSYNC_ERROR _MD_win32_map_fsync_error
+
+extern void _MD_win32_map_close_error(PRInt32 err);
+#define _PR_MD_MAP_CLOSE_ERROR _MD_win32_map_close_error
+
+extern void _MD_win32_map_socket_error(PRInt32 err);
+#define _PR_MD_MAP_SOCKET_ERROR _MD_win32_map_socket_error
+
+extern void _MD_win32_map_recv_error(PRInt32 err);
+#define _PR_MD_MAP_RECV_ERROR _MD_win32_map_recv_error
+
+extern void _MD_win32_map_recvfrom_error(PRInt32 err);
+#define _PR_MD_MAP_RECVFROM_ERROR _MD_win32_map_recvfrom_error
+
+extern void _MD_win32_map_send_error(PRInt32 err);
+#define _PR_MD_MAP_SEND_ERROR _MD_win32_map_send_error
+
+extern void _MD_win32_map_sendto_error(PRInt32 err);
+#define _PR_MD_MAP_SENDTO_ERROR _MD_win32_map_sendto_error
+
+extern void _MD_win32_map_accept_error(PRInt32 err);
+#define _PR_MD_MAP_ACCEPT_ERROR _MD_win32_map_accept_error
+
+extern void _MD_win32_map_acceptex_error(PRInt32 err);
+#define _PR_MD_MAP_ACCEPTEX_ERROR _MD_win32_map_acceptex_error
+
+extern PRInt32 _MD_win32_map_connect_error(PRInt32 err);
+#define _PR_MD_MAP_CONNECT_ERROR _MD_win32_map_connect_error
+
+extern void _MD_win32_map_bind_error(PRInt32 err);
+#define _PR_MD_MAP_BIND_ERROR _MD_win32_map_bind_error
+
+extern void _MD_win32_map_listen_error(PRInt32 err);
+#define _PR_MD_MAP_LISTEN_ERROR _MD_win32_map_listen_error
+
+extern void _MD_win32_map_shutdown_error(PRInt32 err);
+#define _PR_MD_MAP_SHUTDOWN_ERROR _MD_win32_map_shutdown_error
+
+extern void _MD_win32_map_getsockname_error(PRInt32 err);
+#define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_win32_map_getsockname_error
+
+extern void _MD_win32_map_getpeername_error(PRInt32 err);
+#define _PR_MD_MAP_GETPEERNAME_ERROR _MD_win32_map_getpeername_error
+
+extern void _MD_win32_map_getsockopt_error(PRInt32 err);
+#define _PR_MD_MAP_GETSOCKOPT_ERROR _MD_win32_map_getsockopt_error
+
+extern void _MD_win32_map_setsockopt_error(PRInt32 err);
+#define _PR_MD_MAP_SETSOCKOPT_ERROR _MD_win32_map_setsockopt_error
+
+extern void _MD_win32_map_open_error(PRInt32 err);
+#define _PR_MD_MAP_OPEN_ERROR _MD_win32_map_open_error
+
+extern void _MD_win32_map_gethostname_error(PRInt32 err);
+#define _PR_MD_MAP_GETHOSTNAME_ERROR _MD_win32_map_gethostname_error
+
+extern void _MD_win32_map_select_error(PRInt32 err);
+#define _PR_MD_MAP_SELECT_ERROR _MD_win32_map_select_error
+
+extern void _MD_win32_map_lockf_error(int err);
+#define _PR_MD_MAP_LOCKF_ERROR _MD_win32_map_lockf_error
+
+#endif /* nspr_win32_errors_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.cfg
new file mode 100644
index 00000000..310fff89
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.cfg
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_PC
+#define XP_PC
+#endif
+
+#ifndef WIN32
+#define WIN32
+#endif
+
+#ifndef WIN95
+#define WIN95
+#endif
+
+#define PR_AF_INET6 23 /* same as AF_INET6 */
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_DOUBLE 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+#define PR_BITS_PER_DOUBLE 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_WORD_LOG2 5
+#define PR_BITS_PER_DWORD_LOG2 6
+#define PR_BITS_PER_DOUBLE_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_WORD 4
+#define PR_ALIGN_OF_DWORD 8
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 2
+
+#elif defined(_ALPHA_)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#else /* defined(_M_IX86) || defined(_X86_) */
+
+#error unknown processor architecture
+
+#endif /* defined(_M_IX86) || defined(_X86_) */
+
+#define HAVE_LONG_LONG
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.h
new file mode 100644
index 00000000..4e61fdf3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_win95.h
@@ -0,0 +1,533 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_win95_defs_h___
+#define nspr_win95_defs_h___
+
+#include "prio.h"
+
+#include <windows.h>
+#include <winsock.h>
+#include <errno.h>
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "win32"
+#define _PR_SI_SYSNAME "WIN95"
+#define _PR_SI_ARCHITECTURE "x86" /* XXXMB hardcode for now */
+
+#define HAVE_DLL
+#undef HAVE_THREAD_AFFINITY
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#ifndef _PR_INET6
+#define AF_INET6 23
+/* newer ws2tcpip.h provides these */
+#ifndef AI_CANONNAME
+#define AI_CANONNAME 0x2
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#endif
+#endif
+#define _PR_HAVE_THREADSAFE_GETHOST
+#define _PR_HAVE_ATOMIC_OPS
+#define PR_HAVE_WIN32_NAMED_SHARED_MEMORY
+
+/* --- Common User-Thread/Native-Thread Definitions --------------------- */
+
+/* --- Globals --- */
+extern struct PRLock *_pr_schedLock;
+
+/* --- Typedefs --- */
+typedef void (*FiberFunc)(void *);
+
+#define PR_NUM_GCREGS 8
+typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS];
+#define GC_VMBASE 0x40000000
+#define GC_VMLIMIT 0x00FFFFFF
+
+#define _MD_MAGIC_THREAD 0x22222222
+#define _MD_MAGIC_THREADSTACK 0x33333333
+#define _MD_MAGIC_SEGMENT 0x44444444
+#define _MD_MAGIC_DIR 0x55555555
+#define _MD_MAGIC_CV 0x66666666
+
+struct _MDCPU {
+ int unused;
+};
+
+struct _MDThread {
+ HANDLE blocked_sema; /* Threads block on this when waiting
+ * for IO or CondVar.
+ */
+ PRBool inCVWaitQueue; /* PR_TRUE if the thread is in the
+ * wait queue of some cond var.
+ * PR_FALSE otherwise. */
+ HANDLE handle; /* Win32 thread handle */
+ PRUint32 id;
+ void *sp; /* only valid when suspended */
+ PRUint32 magic; /* for debugging */
+ PR_CONTEXT_TYPE gcContext; /* Thread context for GC */
+ struct PRThread *prev, *next; /* used by the cvar wait queue to
+ * chain the PRThread structures
+ * together */
+ void (*start)(void *); /* used by _PR_MD_CREATE_THREAD to
+ * pass its 'start' argument to
+ * pr_root. */
+};
+
+struct _MDThreadStack {
+ PRUint32 magic; /* for debugging */
+};
+
+struct _MDSegment {
+ PRUint32 magic; /* for debugging */
+};
+
+#undef PROFILE_LOCKS
+
+struct _MDDir {
+ HANDLE d_hdl;
+ WIN32_FIND_DATA d_entry;
+ PRBool firstEntry; /* Is this the entry returned
+ * by FindFirstFile()? */
+ PRUint32 magic; /* for debugging */
+};
+
+#ifdef MOZ_UNICODE
+struct _MDDirUTF16 {
+ HANDLE d_hdl;
+ WIN32_FIND_DATAW d_entry;
+ PRBool firstEntry; /* Is this the entry returned
+ * by FindFirstFileW()? */
+ PRUint32 magic; /* for debugging */
+};
+#endif /* MOZ_UNICODE */
+
+struct _MDCVar {
+ PRUint32 magic;
+ struct PRThread *waitHead, *waitTail; /* the wait queue: a doubly-
+ * linked list of threads
+ * waiting on this condition
+ * variable */
+ PRIntn nwait; /* number of threads in the
+ * wait queue */
+};
+
+#define _MD_CV_NOTIFIED_LENGTH 6
+typedef struct _MDNotified _MDNotified;
+struct _MDNotified {
+ PRIntn length; /* # of used entries in this
+ * structure */
+ struct {
+ struct _MDCVar *cv; /* the condition variable notified */
+ PRIntn times; /* and the number of times notified */
+ struct PRThread *notifyHead; /* list of threads to wake up */
+ } cv[_MD_CV_NOTIFIED_LENGTH];
+ _MDNotified *link; /* link to another of these, or NULL */
+};
+
+struct _MDLock {
+ CRITICAL_SECTION mutex; /* this is recursive on NT */
+
+ /*
+ * When notifying cvars, there is no point in actually
+ * waking up the threads waiting on the cvars until we've
+ * released the lock. So, we temporarily record the cvars.
+ * When doing an unlock, we'll then wake up the waiting threads.
+ */
+ struct _MDNotified notified; /* array of conditions notified */
+#ifdef PROFILE_LOCKS
+ PRInt32 hitcount;
+ PRInt32 misscount;
+#endif
+};
+
+struct _MDSemaphore {
+ HANDLE sem;
+};
+
+struct _MDFileDesc {
+ PRInt32 osfd; /* The osfd can come from one of three spaces:
+ * - For stdin, stdout, and stderr, we are using
+ * the libc file handle (0, 1, 2), which is an int.
+ * - For files and pipes, we are using Win32 HANDLE,
+ * which is a void*.
+ * - For sockets, we are using Winsock SOCKET, which
+ * is a u_int.
+ */
+};
+
+struct _MDProcess {
+ HANDLE handle;
+ DWORD id;
+};
+
+/* --- Misc stuff --- */
+#define _MD_GET_SP(thread) (thread)->md.gcContext[6]
+
+/* --- NT security stuff --- */
+
+extern void _PR_NT_InitSids(void);
+extern void _PR_NT_FreeSids(void);
+extern PRStatus _PR_NT_MakeSecurityDescriptorACL(
+ PRIntn mode,
+ DWORD accessTable[],
+ PSECURITY_DESCRIPTOR *resultSD,
+ PACL *resultACL
+);
+extern void _PR_NT_FreeSecurityDescriptorACL(
+ PSECURITY_DESCRIPTOR pSD, PACL pACL);
+
+/* --- IO stuff --- */
+
+#define _MD_OPEN _PR_MD_OPEN
+#define _MD_OPEN_FILE _PR_MD_OPEN_FILE
+#define _MD_READ _PR_MD_READ
+#define _MD_WRITE _PR_MD_WRITE
+#define _MD_WRITEV _PR_MD_WRITEV
+#define _MD_LSEEK _PR_MD_LSEEK
+#define _MD_LSEEK64 _PR_MD_LSEEK64
+extern PRInt32 _MD_CloseFile(PRInt32 osfd);
+#define _MD_CLOSE_FILE _MD_CloseFile
+#define _MD_GETFILEINFO _PR_MD_GETFILEINFO
+#define _MD_GETFILEINFO64 _PR_MD_GETFILEINFO64
+#define _MD_GETOPENFILEINFO _PR_MD_GETOPENFILEINFO
+#define _MD_GETOPENFILEINFO64 _PR_MD_GETOPENFILEINFO64
+#define _MD_STAT _PR_MD_STAT
+#define _MD_RENAME _PR_MD_RENAME
+#define _MD_ACCESS _PR_MD_ACCESS
+#define _MD_DELETE _PR_MD_DELETE
+#define _MD_MKDIR _PR_MD_MKDIR
+#define _MD_MAKE_DIR _PR_MD_MAKE_DIR
+#define _MD_RMDIR _PR_MD_RMDIR
+#define _MD_LOCKFILE _PR_MD_LOCKFILE
+#define _MD_TLOCKFILE _PR_MD_TLOCKFILE
+#define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE
+
+#ifdef MOZ_UNICODE
+/* --- UTF16 IO stuff --- */
+#define _MD_OPEN_FILE_UTF16 _PR_MD_OPEN_FILE_UTF16
+#define _MD_OPEN_DIR_UTF16 _PR_MD_OPEN_DIR_UTF16
+#define _MD_READ_DIR_UTF16 _PR_MD_READ_DIR_UTF16
+#define _MD_CLOSE_DIR_UTF16 _PR_MD_CLOSE_DIR_UTF16
+#define _MD_GETFILEINFO64_UTF16 _PR_MD_GETFILEINFO64_UTF16
+#endif /* MOZ_UNICODE */
+
+/* --- Socket IO stuff --- */
+#define _MD_EACCES WSAEACCES
+#define _MD_EADDRINUSE WSAEADDRINUSE
+#define _MD_EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define _MD_EAFNOSUPPORT WSAEAFNOSUPPORT
+#define _MD_EAGAIN WSAEWOULDBLOCK
+#define _MD_EALREADY WSAEALREADY
+#define _MD_EBADF WSAEBADF
+#define _MD_ECONNREFUSED WSAECONNREFUSED
+#define _MD_ECONNRESET WSAECONNRESET
+#define _MD_EFAULT WSAEFAULT
+#define _MD_EINPROGRESS WSAEINPROGRESS
+#define _MD_EINTR WSAEINTR
+#define _MD_EINVAL EINVAL
+#define _MD_EISCONN WSAEISCONN
+#define _MD_ENETUNREACH WSAENETUNREACH
+#define _MD_ENOENT ENOENT
+#define _MD_ENOTCONN WSAENOTCONN
+#define _MD_ENOTSOCK WSAENOTSOCK
+#define _MD_EOPNOTSUPP WSAEOPNOTSUPP
+#define _MD_EWOULDBLOCK WSAEWOULDBLOCK
+#define _MD_GET_SOCKET_ERROR() WSAGetLastError()
+#define _MD_SET_SOCKET_ERROR(_err) WSASetLastError(_err)
+
+#define _MD_INIT_FILEDESC(fd)
+extern void _MD_MakeNonblock(PRFileDesc *f);
+#define _MD_MAKE_NONBLOCK _MD_MakeNonblock
+#define _MD_INIT_FD_INHERITABLE _PR_MD_INIT_FD_INHERITABLE
+#define _MD_QUERY_FD_INHERITABLE _PR_MD_QUERY_FD_INHERITABLE
+#define _MD_SHUTDOWN _PR_MD_SHUTDOWN
+#define _MD_LISTEN _PR_MD_LISTEN
+extern PRInt32 _MD_CloseSocket(PRInt32 osfd);
+#define _MD_CLOSE_SOCKET _MD_CloseSocket
+#define _MD_SENDTO _PR_MD_SENDTO
+#define _MD_RECVFROM _PR_MD_RECVFROM
+#define _MD_SOCKETPAIR(s, type, proto, sv) -1
+#define _MD_GETSOCKNAME _PR_MD_GETSOCKNAME
+#define _MD_GETPEERNAME _PR_MD_GETPEERNAME
+#define _MD_GETSOCKOPT _PR_MD_GETSOCKOPT
+#define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT
+#define _MD_SET_FD_INHERITABLE _PR_MD_SET_FD_INHERITABLE
+#define _MD_SELECT select
+#define _MD_FSYNC _PR_MD_FSYNC
+#define READ_FD 1
+#define WRITE_FD 2
+
+#define _MD_INIT_ATOMIC()
+#if defined(_M_IX86) || defined(_X86_)
+#define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD
+#define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT
+#else /* non-x86 processors */
+#define _MD_ATOMIC_INCREMENT(x) InterlockedIncrement((PLONG)x)
+#define _MD_ATOMIC_ADD(ptr,val) (InterlockedExchangeAdd((PLONG)ptr, (LONG)val) + val)
+#define _MD_ATOMIC_DECREMENT(x) InterlockedDecrement((PLONG)x)
+#endif /* x86 */
+#define _MD_ATOMIC_SET(x,y) InterlockedExchange((PLONG)x, (LONG)y)
+
+#define _MD_INIT_IO _PR_MD_INIT_IO
+
+
+/* win95 doesn't have async IO */
+#define _MD_SOCKET _PR_MD_SOCKET
+extern PRInt32 _MD_SocketAvailable(PRFileDesc *fd);
+#define _MD_SOCKETAVAILABLE _MD_SocketAvailable
+#define _MD_PIPEAVAILABLE _PR_MD_PIPEAVAILABLE
+#define _MD_CONNECT _PR_MD_CONNECT
+extern PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
+ PRIntervalTime timeout);
+#define _MD_ACCEPT _MD_Accept
+#define _MD_BIND _PR_MD_BIND
+#define _MD_RECV _PR_MD_RECV
+#define _MD_SEND _PR_MD_SEND
+#define _MD_PR_POLL _PR_MD_PR_POLL
+
+/* --- Scheduler stuff --- */
+// #define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU
+#define _MD_PAUSE_CPU
+
+/* --- DIR stuff --- */
+#define PR_DIRECTORY_SEPARATOR '\\'
+#define PR_DIRECTORY_SEPARATOR_STR "\\"
+#define PR_PATH_SEPARATOR ';'
+#define PR_PATH_SEPARATOR_STR ";"
+#define _MD_ERRNO() GetLastError()
+#define _MD_OPEN_DIR _PR_MD_OPEN_DIR
+#define _MD_CLOSE_DIR _PR_MD_CLOSE_DIR
+#define _MD_READ_DIR _PR_MD_READ_DIR
+
+/* --- Segment stuff --- */
+#define _MD_INIT_SEGS()
+#define _MD_ALLOC_SEGMENT(seg, size, vaddr) 0
+#define _MD_FREE_SEGMENT(seg)
+
+/* --- Environment Stuff --- */
+#define _MD_GET_ENV _PR_MD_GET_ENV
+#define _MD_PUT_ENV _PR_MD_PUT_ENV
+
+/* --- Threading Stuff --- */
+#define _MD_DEFAULT_STACK_SIZE 0
+#define _MD_INIT_THREAD _PR_MD_INIT_THREAD
+#define _MD_INIT_ATTACHED_THREAD _PR_MD_INIT_THREAD
+#define _MD_CREATE_THREAD _PR_MD_CREATE_THREAD
+#define _MD_YIELD _PR_MD_YIELD
+#define _MD_SET_PRIORITY _PR_MD_SET_PRIORITY
+#define _MD_CLEAN_THREAD _PR_MD_CLEAN_THREAD
+#define _MD_SETTHREADAFFINITYMASK _PR_MD_SETTHREADAFFINITYMASK
+#define _MD_GETTHREADAFFINITYMASK _PR_MD_GETTHREADAFFINITYMASK
+#define _MD_EXIT_THREAD _PR_MD_EXIT_THREAD
+#define _MD_EXIT _PR_MD_EXIT
+#define _MD_SUSPEND_THREAD _PR_MD_SUSPEND_THREAD
+#define _MD_RESUME_THREAD _PR_MD_RESUME_THREAD
+#define _MD_SUSPEND_CPU _PR_MD_SUSPEND_CPU
+#define _MD_RESUME_CPU _PR_MD_RESUME_CPU
+#define _MD_BEGIN_SUSPEND_ALL()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_SUSPEND_ALL()
+#define _MD_END_RESUME_ALL()
+
+/* --- Lock stuff --- */
+#define _PR_LOCK _MD_LOCK
+#define _PR_UNLOCK _MD_UNLOCK
+
+#define _MD_NEW_LOCK(lock) (InitializeCriticalSection(&((lock)->mutex)),(lock)->notified.length=0,(lock)->notified.link=NULL,PR_SUCCESS)
+#define _MD_FREE_LOCK(lock) DeleteCriticalSection(&((lock)->mutex))
+#define _MD_LOCK(lock) EnterCriticalSection(&((lock)->mutex))
+#define _MD_TEST_AND_LOCK(lock) (EnterCriticalSection(&((lock)->mutex)),0)
+#define _MD_UNLOCK _PR_MD_UNLOCK
+
+/* --- lock and cv waiting --- */
+#define _MD_WAIT _PR_MD_WAIT
+#define _MD_WAKEUP_WAITER _PR_MD_WAKEUP_WAITER
+
+/* --- CVar ------------------- */
+#define _MD_WAIT_CV _PR_MD_WAIT_CV
+#define _MD_NEW_CV _PR_MD_NEW_CV
+#define _MD_FREE_CV _PR_MD_FREE_CV
+#define _MD_NOTIFY_CV _PR_MD_NOTIFY_CV
+#define _MD_NOTIFYALL_CV _PR_MD_NOTIFYALL_CV
+
+ /* XXXMB- the IOQ stuff is certainly not working correctly yet. */
+// extern struct _MDLock _pr_ioq_lock;
+#define _MD_IOQ_LOCK()
+#define _MD_IOQ_UNLOCK()
+
+
+/* --- Initialization stuff --- */
+#define _MD_START_INTERRUPTS()
+#define _MD_STOP_INTERRUPTS()
+#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
+#define _MD_BLOCK_CLOCK_INTERRUPTS()
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
+#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
+#define _MD_FINAL_INIT()
+#define _MD_INIT_CPUS()
+#define _MD_INIT_RUNNING_CPU(cpu)
+
+struct PRProcess;
+struct PRProcessAttr;
+
+#define _MD_CREATE_PROCESS _PR_CreateWindowsProcess
+extern struct PRProcess * _PR_CreateWindowsProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr
+);
+
+#define _MD_DETACH_PROCESS _PR_DetachWindowsProcess
+extern PRStatus _PR_DetachWindowsProcess(struct PRProcess *process);
+
+/* --- Wait for a child process to terminate --- */
+#define _MD_WAIT_PROCESS _PR_WaitWindowsProcess
+extern PRStatus _PR_WaitWindowsProcess(struct PRProcess *process,
+ PRInt32 *exitCode);
+
+#define _MD_KILL_PROCESS _PR_KillWindowsProcess
+extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
+
+#define _MD_CLEANUP_BEFORE_EXIT _PR_MD_CLEANUP_BEFORE_EXIT
+#define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
+ PR_BEGIN_MACRO \
+ *status = PR_TRUE; \
+ PR_END_MACRO
+#define _MD_SWITCH_CONTEXT
+#define _MD_RESTORE_CONTEXT
+
+/* --- Intervals --- */
+#define _MD_INTERVAL_INIT _PR_MD_INTERVAL_INIT
+#define _MD_GET_INTERVAL _PR_MD_GET_INTERVAL
+#define _MD_INTERVAL_PER_SEC _PR_MD_INTERVAL_PER_SEC
+#define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
+#define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
+
+/* --- Time --- */
+extern void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm);
+
+/* --- Native-Thread Specific Definitions ------------------------------- */
+
+extern struct PRThread * _MD_CURRENT_THREAD(void);
+
+#ifdef _PR_USE_STATIC_TLS
+extern __declspec(thread) struct PRThread *_pr_currentThread;
+#define _MD_GET_ATTACHED_THREAD() _pr_currentThread
+#define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))
+
+extern __declspec(thread) struct PRThread *_pr_thread_last_run;
+#define _MD_LAST_THREAD() _pr_thread_last_run
+#define _MD_SET_LAST_THREAD(_thread) (_pr_thread_last_run = 0)
+
+extern __declspec(thread) struct _PRCPU *_pr_currentCPU;
+#define _MD_CURRENT_CPU() _pr_currentCPU
+#define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = 0)
+#else /* _PR_USE_STATIC_TLS */
+extern DWORD _pr_currentThreadIndex;
+#define _MD_GET_ATTACHED_THREAD() ((PRThread *) TlsGetValue(_pr_currentThreadIndex))
+#define _MD_SET_CURRENT_THREAD(_thread) TlsSetValue(_pr_currentThreadIndex, (_thread))
+
+extern DWORD _pr_lastThreadIndex;
+#define _MD_LAST_THREAD() ((PRThread *) TlsGetValue(_pr_lastThreadIndex))
+#define _MD_SET_LAST_THREAD(_thread) TlsSetValue(_pr_lastThreadIndex, 0)
+
+extern DWORD _pr_currentCPUIndex;
+#define _MD_CURRENT_CPU() ((struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
+#define _MD_SET_CURRENT_CPU(_cpu) TlsSetValue(_pr_currentCPUIndex, 0)
+#endif /* _PR_USE_STATIC_TLS */
+
+/* --- Scheduler stuff --- */
+#define LOCK_SCHEDULER() 0
+#define UNLOCK_SCHEDULER() 0
+#define _PR_LockSched() 0
+#define _PR_UnlockSched() 0
+
+/* --- Initialization stuff --- */
+#define _MD_INIT_LOCKS()
+
+/* --- Stack stuff --- */
+#define _MD_INIT_STACK(stack, redzone)
+#define _MD_CLEAR_STACK(stack)
+
+/* --- Memory-mapped files stuff --- */
+
+struct _MDFileMap {
+ HANDLE hFileMap;
+ DWORD dwAccess;
+};
+
+extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
+#define _MD_CREATE_FILE_MAP _MD_CreateFileMap
+
+extern PRInt32 _MD_GetMemMapAlignment(void);
+#define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment
+
+extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
+ PRUint32 len);
+#define _MD_MEM_MAP _MD_MemMap
+
+extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
+#define _MD_MEM_UNMAP _MD_MemUnmap
+
+extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
+#define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
+
+/* --- Named semaphores stuff --- */
+#define _PR_HAVE_NAMED_SEMAPHORES
+#define _MD_OPEN_SEMAPHORE _PR_MD_OPEN_SEMAPHORE
+#define _MD_WAIT_SEMAPHORE _PR_MD_WAIT_SEMAPHORE
+#define _MD_POST_SEMAPHORE _PR_MD_POST_SEMAPHORE
+#define _MD_CLOSE_SEMAPHORE _PR_MD_CLOSE_SEMAPHORE
+#define _MD_DELETE_SEMAPHORE(name) PR_SUCCESS /* no op */
+
+#endif /* nspr_win32_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.cfg b/src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.cfg
new file mode 100644
index 00000000..ce077d33
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.cfg
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_PC
+#define XP_PC
+#endif
+
+#ifndef WIN32
+#define WIN32
+#endif
+
+#ifndef WINNT
+#define WINNT
+#endif
+
+#define PR_AF_INET6 23 /* same as AF_INET6 */
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+#define PR_BYTES_PER_DOUBLE 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_WORD 32
+#define PR_BITS_PER_DWORD 64
+#define PR_BITS_PER_DOUBLE 64
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_WORD_LOG2 5
+#define PR_BITS_PER_DWORD_LOG2 6
+#define PR_BITS_PER_DOUBLE_LOG2 6
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_WORD 4
+#define PR_ALIGN_OF_DWORD 8
+#define PR_ALIGN_OF_DOUBLE 4
+#define PR_ALIGN_OF_POINTER 4
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 2
+
+#elif defined(_ALPHA_)
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define PR_BYTES_PER_BYTE 1
+#define PR_BYTES_PER_SHORT 2
+#define PR_BYTES_PER_INT 4
+#define PR_BYTES_PER_INT64 8
+#define PR_BYTES_PER_LONG 4
+#define PR_BYTES_PER_FLOAT 4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD 4
+#define PR_BYTES_PER_DWORD 8
+
+#define PR_BITS_PER_BYTE 8
+#define PR_BITS_PER_SHORT 16
+#define PR_BITS_PER_INT 32
+#define PR_BITS_PER_INT64 64
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_FLOAT 32
+#define PR_BITS_PER_DOUBLE 64
+#define PR_BITS_PER_WORD 32
+
+#define PR_BITS_PER_BYTE_LOG2 3
+#define PR_BITS_PER_SHORT_LOG2 4
+#define PR_BITS_PER_INT_LOG2 5
+#define PR_BITS_PER_INT64_LOG2 6
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_BITS_PER_FLOAT_LOG2 5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2 5
+
+#define PR_BYTES_PER_WORD_LOG2 2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#define PR_ALIGN_OF_SHORT 2
+#define PR_ALIGN_OF_INT 4
+#define PR_ALIGN_OF_LONG 4
+#define PR_ALIGN_OF_INT64 8
+#define PR_ALIGN_OF_FLOAT 4
+#define PR_ALIGN_OF_DOUBLE 8
+#define PR_ALIGN_OF_POINTER 4
+
+#else /* defined(_M_IX86) || defined(_X86_) */
+
+#error unknown processor architecture
+
+#endif /* defined(_M_IX86) || defined(_X86_) */
+
+#define HAVE_LONG_LONG
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.h
new file mode 100644
index 00000000..36cbcfae
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/_winnt.h
@@ -0,0 +1,594 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_win32_defs_h___
+#define nspr_win32_defs_h___
+
+/* Need to force service-pack 3 extensions to be defined by
+** setting _WIN32_WINNT to NT 4.0 for winsock.h, winbase.h, winnt.h.
+*/
+#ifndef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0400
+#elif (_WIN32_WINNT < 0x0400)
+ #undef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0400
+#endif /* _WIN32_WINNT */
+
+#include <windows.h>
+#include <winsock.h>
+#ifdef __MINGW32__
+#include <mswsock.h>
+#endif
+#include <errno.h>
+
+#include "prio.h"
+#include "prclist.h"
+
+/*
+ * Internal configuration macros
+ */
+
+#define PR_LINKER_ARCH "win32"
+#define _PR_SI_SYSNAME "WINNT"
+#define _PR_SI_ARCHITECTURE "x86" /* XXXMB hardcode for now */
+
+#define HAVE_DLL
+#define HAVE_CUSTOM_USER_THREADS
+#define HAVE_THREAD_AFFINITY
+#define _PR_HAVE_GETADDRINFO
+#define _PR_INET6_PROBE
+#ifndef _PR_INET6
+#define AF_INET6 23
+/* newer ws2tcpip.h provides these */
+#ifndef AI_CANONNAME
+#define AI_CANONNAME 0x2
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#endif
+#endif
+#define _PR_HAVE_THREADSAFE_GETHOST
+#define _PR_HAVE_ATOMIC_OPS
+#define _PR_HAVE_ATOMIC_CAS
+#define PR_HAVE_WIN32_NAMED_SHARED_MEMORY
+#define _PR_HAVE_PEEK_BUFFER
+#define _PR_PEEK_BUFFER_MAX (32 * 1024)
+#define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) \
+ (!(fd)->secret->nonblocking && (fd)->secret->inheritable != _PR_TRI_TRUE)
+
+/* --- Common User-Thread/Native-Thread Definitions --------------------- */
+
+/* --- Globals --- */
+extern struct PRLock *_pr_schedLock;
+
+/* --- Typedefs --- */
+typedef void (*FiberFunc)(void *);
+
+#define PR_NUM_GCREGS 8
+typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS];
+#define GC_VMBASE 0x40000000
+#define GC_VMLIMIT 0x00FFFFFF
+
+#define _MD_MAGIC_THREAD 0x22222222
+#define _MD_MAGIC_THREADSTACK 0x33333333
+#define _MD_MAGIC_SEGMENT 0x44444444
+#define _MD_MAGIC_DIR 0x55555555
+
+struct _MDCPU {
+ int unused;
+};
+
+enum _MDIOModel {
+ _MD_BlockingIO = 0x38,
+ _MD_MultiWaitIO = 0x49
+};
+
+typedef struct _MDOverlapped {
+ OVERLAPPED overlapped; /* Used for async I/O */
+
+ enum _MDIOModel ioModel; /* The I/O model to implement
+ * using overlapped I/O.
+ */
+ union {
+ struct _MDThread *mdThread; /* For blocking I/O, this structure
+ * is embedded in the _MDThread
+ * structure.
+ */
+ struct {
+ PRCList links; /* for group->io_ready list */
+ struct PRRecvWait *desc; /* For multiwait I/O, this structure
+ * is associated with a PRRecvWait
+ * structure.
+ */
+ struct PRWaitGroup *group;
+ struct TimerEvent *timer;
+ DWORD error;
+ } mw;
+ } data;
+} _MDOverlapped;
+
+struct _MDThread {
+ /* The overlapped structure must be first! */
+ struct _MDOverlapped overlapped; /* Used for async IO for this thread */
+ void *acceptex_buf; /* Used for AcceptEx() */
+ TRANSMIT_FILE_BUFFERS *xmit_bufs; /* Used for TransmitFile() */
+ HANDLE blocked_sema; /* Threads block on this when waiting
+ * for IO or CondVar.
+ */
+ PRInt32 blocked_io_status; /* Status of the completed IO */
+ PRInt32 blocked_io_bytes; /* Bytes transferred for completed IO */
+ PRInt32 blocked_io_error; /* Save error if status is FALSE */
+ HANDLE handle;
+ PRUint32 id;
+ void *sp; /* only valid when suspended */
+ PRUint32 magic; /* for debugging */
+ PR_CONTEXT_TYPE gcContext; /* Thread context for GC */
+ struct _PRCPU *thr_bound_cpu; /* thread bound to cpu */
+ PRBool interrupt_disabled;/* thread cannot be interrupted */
+ HANDLE thr_event; /* For native-threads-only support,
+ thread blocks on this event */
+
+ /* The following are used only if this is a fiber */
+ void *fiber_id; /* flag whether or not this is a fiber*/
+ FiberFunc fiber_fn; /* main fiber routine */
+ void *fiber_arg; /* arg to main fiber routine */
+ PRUint32 fiber_stacksize; /* stacksize for fiber */
+ PRInt32 fiber_last_error; /* last error for the fiber */
+ void (*start)(void *); /* used by _PR_MD_CREATE_THREAD to
+ * pass its 'start' argument to
+ * pr_root. */
+};
+
+struct _MDThreadStack {
+ PRUint32 magic; /* for debugging */
+};
+
+struct _MDSegment {
+ PRUint32 magic; /* for debugging */
+};
+
+#undef PROFILE_LOCKS
+
+struct _MDLock {
+ CRITICAL_SECTION mutex; /* this is recursive on NT */
+#ifdef PROFILE_LOCKS
+ PRInt32 hitcount;
+ PRInt32 misscount;
+#endif
+};
+
+struct _MDDir {
+ HANDLE d_hdl;
+ WIN32_FIND_DATA d_entry;
+ PRBool firstEntry; /* Is this the entry returned
+ * by FindFirstFile()? */
+ PRUint32 magic; /* for debugging */
+};
+
+struct _MDCVar {
+ PRUint32 unused;
+};
+
+struct _MDSemaphore {
+ HANDLE sem;
+};
+
+struct _MDFileDesc {
+ PRInt32 osfd; /* The osfd can come from one of three spaces:
+ * - For stdin, stdout, and stderr, we are using
+ * the libc file handle (0, 1, 2), which is an int.
+ * - For files and pipes, we are using Win32 HANDLE,
+ * which is a void*.
+ * - For sockets, we are using Winsock SOCKET, which
+ * is a u_int.
+ */
+ PRBool io_model_committed; /* The io model (blocking or nonblocking)
+ * for this osfd has been committed and
+ * cannot be changed. The osfd has been
+ * either associated with the io
+ * completion port or made nonblocking. */
+ PRBool sync_file_io; /* Use synchronous file I/O on the osfd
+ * (a file handle) */
+ PRBool accepted_socket; /* Is this an accepted socket (on the
+ * server side)? */
+ PRNetAddr peer_addr; /* If this is an accepted socket, cache
+ * the peer's address returned by
+ * AcceptEx(). This is to work around
+ * the bug that getpeername() on an
+ * socket accepted by AcceptEx() returns
+ * an all-zero net address. */
+};
+
+struct _MDProcess {
+ HANDLE handle;
+ DWORD id;
+};
+
+
+/* --- Misc stuff --- */
+#define _MD_GET_SP(thread) (thread)->md.gcContext[6]
+
+/* --- NT security stuff --- */
+
+extern void _PR_NT_InitSids(void);
+extern void _PR_NT_FreeSids(void);
+extern PRStatus _PR_NT_MakeSecurityDescriptorACL(
+ PRIntn mode,
+ DWORD accessTable[],
+ PSECURITY_DESCRIPTOR *resultSD,
+ PACL *resultACL
+);
+extern void _PR_NT_FreeSecurityDescriptorACL(
+ PSECURITY_DESCRIPTOR pSD, PACL pACL);
+
+/* --- IO stuff --- */
+
+extern PRInt32 _md_Associate(HANDLE);
+extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket);
+
+#define _MD_OPEN _PR_MD_OPEN
+#define _MD_OPEN_FILE _PR_MD_OPEN_FILE
+#define _MD_READ _PR_MD_READ
+#define _MD_WRITE _PR_MD_WRITE
+#define _MD_WRITEV _PR_MD_WRITEV
+#define _MD_LSEEK _PR_MD_LSEEK
+#define _MD_LSEEK64 _PR_MD_LSEEK64
+#define _MD_CLOSE_FILE(f) _PR_MD_CLOSE(f, PR_FALSE)
+#define _MD_GETFILEINFO _PR_MD_GETFILEINFO
+#define _MD_GETFILEINFO64 _PR_MD_GETFILEINFO64
+#define _MD_GETOPENFILEINFO _PR_MD_GETOPENFILEINFO
+#define _MD_GETOPENFILEINFO64 _PR_MD_GETOPENFILEINFO64
+#define _MD_STAT _PR_MD_STAT
+#define _MD_RENAME _PR_MD_RENAME
+#define _MD_ACCESS _PR_MD_ACCESS
+#define _MD_DELETE _PR_MD_DELETE
+#define _MD_MKDIR _PR_MD_MKDIR
+#define _MD_MAKE_DIR _PR_MD_MAKE_DIR
+#define _MD_RMDIR _PR_MD_RMDIR
+#define _MD_LOCKFILE _PR_MD_LOCKFILE
+#define _MD_TLOCKFILE _PR_MD_TLOCKFILE
+#define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE
+
+/* --- Socket IO stuff --- */
+#define _MD_GET_SOCKET_ERROR() WSAGetLastError()
+#define _MD_SET_SOCKET_ERROR(_err) WSASetLastError(_err)
+
+#define _MD_INIT_FILEDESC(fd)
+#define _MD_MAKE_NONBLOCK _PR_MD_MAKE_NONBLOCK
+#define _MD_INIT_FD_INHERITABLE _PR_MD_INIT_FD_INHERITABLE
+#define _MD_QUERY_FD_INHERITABLE _PR_MD_QUERY_FD_INHERITABLE
+#define _MD_SHUTDOWN _PR_MD_SHUTDOWN
+#define _MD_LISTEN _PR_MD_LISTEN
+#define _MD_CLOSE_SOCKET(s) _PR_MD_CLOSE(s, PR_TRUE)
+#define _MD_SENDTO _PR_MD_SENDTO
+#define _MD_RECVFROM _PR_MD_RECVFROM
+#define _MD_SOCKETPAIR(s, type, proto, sv) -1
+#define _MD_GETSOCKNAME _PR_MD_GETSOCKNAME
+#define _MD_GETPEERNAME _PR_MD_GETPEERNAME
+#define _MD_GETSOCKOPT _PR_MD_GETSOCKOPT
+#define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT
+#define _MD_SELECT select
+extern int _PR_NTFiberSafeSelect(int, fd_set *, fd_set *, fd_set *,
+ const struct timeval *);
+#define _MD_FSYNC _PR_MD_FSYNC
+#define _MD_SOCKETAVAILABLE _PR_MD_SOCKETAVAILABLE
+#define _MD_PIPEAVAILABLE _PR_MD_PIPEAVAILABLE
+#define _MD_SET_FD_INHERITABLE _PR_MD_SET_FD_INHERITABLE
+
+#define _MD_INIT_ATOMIC()
+#if defined(_M_IX86) || defined(_X86_)
+#define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT
+#define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD
+#define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT
+#else /* non-x86 processors */
+#define _MD_ATOMIC_INCREMENT(x) InterlockedIncrement((PLONG)x)
+#define _MD_ATOMIC_ADD(ptr,val) (InterlockedExchangeAdd((PLONG)ptr, (LONG)val) + val)
+#define _MD_ATOMIC_DECREMENT(x) InterlockedDecrement((PLONG)x)
+#endif /* x86 */
+#define _MD_ATOMIC_SET(x,y) InterlockedExchange((PLONG)x, (LONG)y)
+
+#define _MD_INIT_IO _PR_MD_INIT_IO
+#define _MD_SOCKET _PR_MD_SOCKET
+#define _MD_CONNECT _PR_MD_CONNECT
+
+#define _MD_ACCEPT(s, a, l, to) \
+ _MD_FAST_ACCEPT(s, a, l, to, PR_FALSE, NULL, NULL)
+#define _MD_FAST_ACCEPT(s, a, l, to, fast, cb, cba) \
+ _PR_MD_FAST_ACCEPT(s, a, l, to, fast, cb, cba)
+#define _MD_ACCEPT_READ(s, ns, ra, buf, l, t) \
+ _MD_FAST_ACCEPT_READ(s, ns, ra, buf, l, t, PR_FALSE, NULL, NULL)
+#define _MD_FAST_ACCEPT_READ(s, ns, ra, buf, l, t, fast, cb, cba) \
+ _PR_MD_FAST_ACCEPT_READ(s, ns, ra, buf, l, t, fast, cb, cba)
+#define _MD_UPDATE_ACCEPT_CONTEXT _PR_MD_UPDATE_ACCEPT_CONTEXT
+
+#define _MD_BIND _PR_MD_BIND
+#define _MD_RECV _PR_MD_RECV
+#define _MD_SEND _PR_MD_SEND
+#define _MD_SENDFILE _PR_MD_SENDFILE
+#define _MD_PR_POLL _PR_MD_PR_POLL
+
+/* --- Scheduler stuff --- */
+#define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU
+
+/* --- DIR stuff --- */
+#define PR_DIRECTORY_SEPARATOR '\\'
+#define PR_DIRECTORY_SEPARATOR_STR "\\"
+#define PR_PATH_SEPARATOR ';'
+#define PR_PATH_SEPARATOR_STR ";"
+#define _MD_ERRNO() GetLastError()
+#define _MD_OPEN_DIR _PR_MD_OPEN_DIR
+#define _MD_CLOSE_DIR _PR_MD_CLOSE_DIR
+#define _MD_READ_DIR _PR_MD_READ_DIR
+
+/* --- Segment stuff --- */
+#define _MD_INIT_SEGS()
+#define _MD_ALLOC_SEGMENT(seg, size, vaddr) 0
+#define _MD_FREE_SEGMENT(seg)
+
+/* --- Environment Stuff --- */
+#define _MD_GET_ENV _PR_MD_GET_ENV
+#define _MD_PUT_ENV _PR_MD_PUT_ENV
+
+/* --- Threading Stuff --- */
+#define _MD_DEFAULT_STACK_SIZE 0
+#define _MD_INIT_THREAD _PR_MD_INIT_THREAD
+#define _MD_INIT_ATTACHED_THREAD _PR_MD_INIT_THREAD
+#define _MD_CREATE_THREAD _PR_MD_CREATE_THREAD
+#define _MD_JOIN_THREAD _PR_MD_JOIN_THREAD
+#define _MD_END_THREAD _PR_MD_END_THREAD
+#define _MD_YIELD _PR_MD_YIELD
+#define _MD_SET_PRIORITY _PR_MD_SET_PRIORITY
+#define _MD_CLEAN_THREAD _PR_MD_CLEAN_THREAD
+#define _MD_SETTHREADAFFINITYMASK _PR_MD_SETTHREADAFFINITYMASK
+#define _MD_GETTHREADAFFINITYMASK _PR_MD_GETTHREADAFFINITYMASK
+#define _MD_EXIT_THREAD _PR_MD_EXIT_THREAD
+#define _MD_SUSPEND_THREAD _PR_MD_SUSPEND_THREAD
+#define _MD_RESUME_THREAD _PR_MD_RESUME_THREAD
+#define _MD_SUSPEND_CPU _PR_MD_SUSPEND_CPU
+#define _MD_RESUME_CPU _PR_MD_RESUME_CPU
+#define _MD_BEGIN_SUSPEND_ALL()
+#define _MD_BEGIN_RESUME_ALL()
+#define _MD_END_SUSPEND_ALL()
+#define _MD_END_RESUME_ALL()
+
+extern void _PR_Unblock_IO_Wait(PRThread *thr);
+
+/* --- Lock stuff --- */
+#define _MD_NEW_LOCK(lock) (InitializeCriticalSection(&((lock)->mutex)),PR_SUCCESS)
+#define _MD_FREE_LOCK(lock) DeleteCriticalSection(&((lock)->mutex))
+#ifndef PROFILE_LOCKS
+#define _MD_LOCK(lock) EnterCriticalSection(&((lock)->mutex))
+#define _MD_TEST_AND_LOCK(lock) (TryEnterCriticalSection(&((lock)->mutex))== FALSE)
+#define _MD_UNLOCK(lock) LeaveCriticalSection(&((lock)->mutex))
+#else
+#define _MD_LOCK(lock) \
+ PR_BEGIN_MACRO \
+ BOOL rv = TryEnterCriticalSection(&((lock)->mutex)); \
+ if (rv == TRUE) { \
+ InterlockedIncrement(&((lock)->hitcount)); \
+ } else { \
+ InterlockedIncrement(&((lock)->misscount)); \
+ EnterCriticalSection(&((lock)->mutex)); \
+ } \
+ PR_END_MACRO
+#define _MD_TEST_AND_LOCK(lock) 0 /* XXXMB */
+#define _MD_UNLOCK(lock) LeaveCriticalSection(&((lock)->mutex))
+#endif
+#define _PR_LOCK _MD_LOCK
+#define _PR_UNLOCK _MD_UNLOCK
+
+/* --- lock and cv waiting --- */
+#define _MD_WAIT _PR_MD_WAIT
+#define _MD_WAKEUP_WAITER _PR_MD_WAKEUP_WAITER
+
+ /* XXXMB- the IOQ stuff is certainly not working correctly yet. */
+extern struct _MDLock _pr_ioq_lock;
+#define _MD_IOQ_LOCK() _MD_LOCK(&_pr_ioq_lock)
+#define _MD_IOQ_UNLOCK() _MD_UNLOCK(&_pr_ioq_lock)
+
+
+/* --- Initialization stuff --- */
+#define _MD_START_INTERRUPTS()
+#define _MD_STOP_INTERRUPTS()
+#define _MD_DISABLE_CLOCK_INTERRUPTS()
+#define _MD_ENABLE_CLOCK_INTERRUPTS()
+#define _MD_BLOCK_CLOCK_INTERRUPTS()
+#define _MD_UNBLOCK_CLOCK_INTERRUPTS()
+#define _MD_EARLY_INIT _PR_MD_EARLY_INIT
+#define _MD_FINAL_INIT()
+#define _MD_INIT_CPUS()
+#define _MD_INIT_RUNNING_CPU(cpu)
+
+struct PRProcess;
+struct PRProcessAttr;
+
+/* --- Create a new process --- */
+#define _MD_CREATE_PROCESS _PR_CreateWindowsProcess
+extern struct PRProcess * _PR_CreateWindowsProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const struct PRProcessAttr *attr
+);
+
+#define _MD_DETACH_PROCESS _PR_DetachWindowsProcess
+extern PRStatus _PR_DetachWindowsProcess(struct PRProcess *process);
+
+/* --- Wait for a child process to terminate --- */
+#define _MD_WAIT_PROCESS _PR_WaitWindowsProcess
+extern PRStatus _PR_WaitWindowsProcess(struct PRProcess *process,
+ PRInt32 *exitCode);
+
+#define _MD_KILL_PROCESS _PR_KillWindowsProcess
+extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process);
+
+/* --- User Threading stuff --- */
+#define HAVE_FIBERS
+#define _MD_CREATE_USER_THREAD _PR_MD_CREATE_USER_THREAD
+#define _MD_CREATE_PRIMORDIAL_USER_THREAD _PR_MD_CREATE_PRIMORDIAL_USER_THREAD
+#define _MD_CLEANUP_BEFORE_EXIT _PR_MD_CLEANUP_BEFORE_EXIT
+#define _MD_EXIT _PR_MD_EXIT
+#define _MD_INIT_CONTEXT _PR_MD_INIT_CONTEXT
+#define _MD_SWITCH_CONTEXT _PR_MD_SWITCH_CONTEXT
+#define _MD_RESTORE_CONTEXT _PR_MD_RESTORE_CONTEXT
+
+/* --- Intervals --- */
+#define _MD_INTERVAL_INIT _PR_MD_INTERVAL_INIT
+#define _MD_GET_INTERVAL _PR_MD_GET_INTERVAL
+#define _MD_INTERVAL_PER_SEC _PR_MD_INTERVAL_PER_SEC
+#define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000)
+#define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000)
+
+/* --- Time --- */
+extern void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm);
+
+/* --- Native-Thread Specific Definitions ------------------------------- */
+
+extern BOOL _pr_use_static_tls;
+
+extern __declspec(thread) struct PRThread *_pr_current_fiber;
+extern DWORD _pr_currentFiberIndex;
+
+#define _MD_GET_ATTACHED_THREAD() \
+ (_pr_use_static_tls ? _pr_current_fiber \
+ : (PRThread *) TlsGetValue(_pr_currentFiberIndex))
+
+extern struct PRThread * _MD_CURRENT_THREAD(void);
+
+#define _MD_SET_CURRENT_THREAD(_thread) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_current_fiber = (_thread); \
+ } else { \
+ TlsSetValue(_pr_currentFiberIndex, (_thread)); \
+ } \
+ PR_END_MACRO
+
+extern __declspec(thread) struct PRThread *_pr_fiber_last_run;
+extern DWORD _pr_lastFiberIndex;
+
+#define _MD_LAST_THREAD() \
+ (_pr_use_static_tls ? _pr_fiber_last_run \
+ : (PRThread *) TlsGetValue(_pr_lastFiberIndex))
+
+#define _MD_SET_LAST_THREAD(_thread) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_fiber_last_run = (_thread); \
+ } else { \
+ TlsSetValue(_pr_lastFiberIndex, (_thread)); \
+ } \
+ PR_END_MACRO
+
+extern __declspec(thread) struct _PRCPU *_pr_current_cpu;
+extern DWORD _pr_currentCPUIndex;
+
+#define _MD_CURRENT_CPU() \
+ (_pr_use_static_tls ? _pr_current_cpu \
+ : (struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex))
+
+#define _MD_SET_CURRENT_CPU(_cpu) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_current_cpu = (_cpu); \
+ } else { \
+ TlsSetValue(_pr_currentCPUIndex, (_cpu)); \
+ } \
+ PR_END_MACRO
+
+extern __declspec(thread) PRUintn _pr_ints_off;
+extern DWORD _pr_intsOffIndex;
+
+#define _MD_GET_INTSOFF() \
+ (_pr_use_static_tls ? _pr_ints_off \
+ : (PRUintn) TlsGetValue(_pr_intsOffIndex))
+
+#define _MD_SET_INTSOFF(_val) \
+ PR_BEGIN_MACRO \
+ if (_pr_use_static_tls) { \
+ _pr_ints_off = (_val); \
+ } else { \
+ TlsSetValue(_pr_intsOffIndex, (LPVOID) (_val)); \
+ } \
+ PR_END_MACRO
+
+/* --- Initialization stuff --- */
+#define _MD_INIT_LOCKS()
+
+/* --- Stack stuff --- */
+#define _MD_INIT_STACK(stack, redzone)
+#define _MD_CLEAR_STACK(stack)
+
+/* --- Memory-mapped files stuff --- */
+
+struct _MDFileMap {
+ HANDLE hFileMap;
+ DWORD dwAccess;
+};
+
+extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size);
+#define _MD_CREATE_FILE_MAP _MD_CreateFileMap
+
+extern PRInt32 _MD_GetMemMapAlignment(void);
+#define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment
+
+extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset,
+ PRUint32 len);
+#define _MD_MEM_MAP _MD_MemMap
+
+extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size);
+#define _MD_MEM_UNMAP _MD_MemUnmap
+
+extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap);
+#define _MD_CLOSE_FILE_MAP _MD_CloseFileMap
+
+/* --- Named semaphores stuff --- */
+#define _PR_HAVE_NAMED_SEMAPHORES
+#define _MD_OPEN_SEMAPHORE _PR_MD_OPEN_SEMAPHORE
+#define _MD_WAIT_SEMAPHORE _PR_MD_WAIT_SEMAPHORE
+#define _MD_POST_SEMAPHORE _PR_MD_POST_SEMAPHORE
+#define _MD_CLOSE_SEMAPHORE _PR_MD_CLOSE_SEMAPHORE
+#define _MD_DELETE_SEMAPHORE(name) PR_SUCCESS /* no op */
+
+#endif /* nspr_win32_defs_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/prosdep.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/prosdep.h
new file mode 100644
index 00000000..93496520
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/prosdep.h
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prosdep_h___
+#define prosdep_h___
+
+/*
+** Get OS specific header information
+*/
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+#ifdef XP_PC
+
+#include "md/_pcos.h"
+#ifdef WINNT
+#include "md/_winnt.h"
+#include "md/_win32_errors.h"
+#elif defined(WIN95)
+#include "md/_win95.h"
+#include "md/_win32_errors.h"
+#elif defined(WIN16)
+#include "md/_win16.h"
+#elif defined(OS2)
+#include "md/_os2.h"
+#include "md/_os2_errors.h"
+#else
+#error unknown Windows platform
+#endif
+
+#elif defined XP_MAC
+
+#include "_macos.h"
+
+#elif defined(XP_UNIX)
+
+#if defined(AIX)
+#include "md/_aix.h"
+
+#elif defined(FREEBSD)
+#include "md/_freebsd.h"
+
+#elif defined(NETBSD)
+#include "md/_netbsd.h"
+
+#elif defined(OPENBSD)
+#include "md/_openbsd.h"
+
+#elif defined(BSDI)
+#include "md/_bsdi.h"
+
+#elif defined(HPUX)
+#include "md/_hpux.h"
+
+#elif defined(IRIX)
+#include "md/_irix.h"
+
+#elif defined(LINUX)
+#include "md/_linux.h"
+
+#elif defined(OSF1)
+#include "md/_osf1.h"
+
+#elif defined(DARWIN)
+#include "md/_darwin.h"
+
+#elif defined(NEXTSTEP)
+#include "md/_nextstep.h"
+
+#elif defined(SOLARIS)
+#include "md/_solaris.h"
+
+#elif defined(SUNOS4)
+#include "md/_sunos4.h"
+
+#elif defined(SNI)
+#include "md/_reliantunix.h"
+
+#elif defined(SONY)
+#include "md/_sony.h"
+
+#elif defined(NEC)
+#include "md/_nec.h"
+
+#elif defined(SCO)
+#include "md/_scoos.h"
+
+#elif defined(UNIXWARE)
+#include "md/_unixware.h"
+
+#elif defined(NCR)
+#include "md/_ncr.h"
+
+#elif defined(DGUX)
+#include "md/_dgux.h"
+
+#elif defined(QNX)
+#include "md/_qnx.h"
+
+#elif defined(VMS)
+#include "md/_openvms.h"
+
+#elif defined(NTO)
+#include "md/_nto.h"
+
+#else
+#error unknown Unix flavor
+
+#endif
+
+#include "md/_unixos.h"
+#include "md/_unix_errors.h"
+
+#elif defined(XP_BEOS)
+
+#include "md/_beos.h"
+#include "md/_unix_errors.h"
+
+#else
+
+#error "The platform is not BeOS, Unix, Windows, or Mac"
+
+#endif
+
+#ifdef _PR_PTHREADS
+#include "md/_pth.h"
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* prosdep_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/md/sunos4.h b/src/libs/xpcom18a4/nsprpub/pr/include/md/sunos4.h
new file mode 100644
index 00000000..0a8f36d4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/md/sunos4.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef pr_sunos4_h___
+#define pr_sunos4_h___
+
+#ifndef SVR4
+
+/*
+** Hodge podge of random missing prototypes for the Sunos4 system
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <limits.h>
+#include <sys/types.h>
+
+#define PATH_MAX _POSIX_PATH_MAX
+
+struct timeval;
+struct timezone;
+struct itimerval;
+struct sockaddr;
+struct stat;
+struct tm;
+
+/* ctype.h */
+extern int tolower(int);
+extern int toupper(int);
+
+/* errno.h */
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+#define strerror(e) sys_errlist[((unsigned)(e) < sys_nerr) ? e : 0]
+
+extern void perror(const char *);
+
+/* getopt */
+extern char *optarg;
+extern int optind;
+extern int getopt(int argc, char **argv, char *spec);
+
+/* math.h */
+extern int srandom(long val);
+extern long random(void);
+
+/* memory.h */
+#define memmove(to,from,len) bcopy((char*)(from),(char*)(to),len)
+
+extern void bcopy(const char *, char *, int);
+
+/* signal.h */
+/*
+** SunOS4 sigaction hides interrupts by default, so we can safely define
+** SA_RESTART to 0.
+*/
+#define SA_RESTART 0
+
+/* stdio.h */
+extern int printf(const char *, ...);
+extern int fprintf(FILE *, const char *, ...);
+extern int vprintf(const char *, va_list);
+extern int vfprintf(FILE *, const char *, va_list);
+extern char *vsprintf(char *, const char *, va_list);
+extern int scanf(const char *, ...);
+extern int sscanf(const char *, const char *, ...);
+extern int fscanf(FILE *, const char *, ...);
+extern int fgetc(FILE *);
+extern int fputc(int, FILE *);
+extern int fputs(const char *, FILE *);
+extern int puts(const char *);
+extern int fread(void *, size_t, size_t, FILE *);
+extern int fwrite(const char *, int, int, FILE *);
+extern int fseek(FILE *, long, int);
+extern long ftell(FILE *);
+extern int rewind(FILE *);
+extern int fflush(FILE *);
+extern int _flsbuf(unsigned char, FILE *);
+extern int fclose(FILE *);
+extern int remove(const char *);
+extern int setvbuf(FILE *, char *, int, size_t);
+extern int system(const char *);
+extern FILE *popen(const char *, const char *);
+extern int pclose(FILE *);
+
+/* stdlib.h */
+#define strtoul strtol
+
+extern int isatty(int fildes);
+extern long strtol(const char *, char **, int);
+extern int putenv(const char *);
+extern void srand48(long);
+extern long lrand48(void);
+extern double drand48(void);
+
+/* string.h */
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, size_t);
+extern int strcoll(const char *, const char *);
+
+/* time.h */
+extern time_t mktime(struct tm *);
+extern size_t strftime(char *, size_t, const char *, const struct tm *);
+extern int gettimeofday(struct timeval *, struct timezone *);
+extern int setitimer(int, struct itimerval *, struct itimerval *);
+extern time_t time(time_t *);
+extern time_t timegm(struct tm *);
+extern struct tm *localtime(const time_t *);
+extern struct tm *gmtime(const time_t *);
+
+/* unistd.h */
+extern int rename(const char *, const char *);
+extern int ioctl(int, int, int *arg);
+extern int connect(int, struct sockaddr *, int);
+extern int readlink(const char *, char *, int);
+extern int symlink(const char *, const char *);
+extern int ftruncate(int, off_t);
+extern int fchmod(int, mode_t);
+extern int fchown(int, uid_t, gid_t);
+extern int lstat(const char *, struct stat *);
+extern int fstat(int, struct stat *);
+extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+extern int gethostname(char *, int);
+extern char *getwd(char *);
+extern int getpagesize(void);
+
+#endif /* SVR4 */
+
+#endif /* pr_sunos4_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/nspr.h b/src/libs/xpcom18a4/nsprpub/pr/include/nspr.h
new file mode 100644
index 00000000..cf3bfad7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/nspr.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_h___
+#define nspr_h___
+
+#include "pratom.h"
+#include "prbit.h"
+#include "prclist.h"
+#include "prcmon.h"
+#include "prcvar.h"
+#include "prdtoa.h"
+#include "prenv.h"
+#include "prerror.h"
+#include "prinet.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "pripcsem.h"
+#include "prlink.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prlong.h"
+#include "prmem.h"
+#include "prmon.h"
+#include "prmwait.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prproces.h"
+#include "prrng.h"
+#include "prrwlock.h"
+#include "prshm.h"
+#include "prshma.h"
+#include "prsystem.h"
+#include "prthread.h"
+#include "prtime.h"
+#include "prtpool.h"
+#include "prtrace.h"
+#include "prtypes.h"
+
+#endif /* nspr_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/Makefile.in
new file mode 100644
index 00000000..1add4844
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+RELEASE_HEADERS = $(HEADERS)
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/obsolete
+
+include_subdir = obsolete
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(RELEASE_HEADERS)
+ $(INSTALL) -m 444 $(RELEASE_HEADERS) $(dist_includedir)/obsolete
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/pralarm.h b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/pralarm.h
new file mode 100644
index 00000000..8d34a905
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/pralarm.h
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: pralarm.h
+** Description: API to periodic alarms.
+**
+**
+** Alarms are defined to invoke some client specified function at
+** a time in the future. The notification may be a one time event
+** or repeated at a fixed interval. The interval at which the next
+** notification takes place may be modified by the client code only
+** during the respective notification.
+**
+** The notification is delivered on a thread that is part of the
+** alarm context (PRAlarm). The thread will inherit the priority
+** of the Alarm creator.
+**
+** Any number of periodic alarms (PRAlarmID) may be created within
+** the context of a single alarm (PRAlarm). The notifications will be
+** scheduled as close to the desired time as possible.
+**
+** Repeating periodic notifies are expected to run at a fixed rate.
+** That rate is expressed as some number of notifies per period where
+** the period is much larger than a PRIntervalTime (see prinrval.h).
+*/
+
+#if !defined(pralarm_h)
+#define pralarm_h
+
+#include "prtypes.h"
+#include "prinrval.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateAlarm VBoxNsprPR_CreateAlarm
+#define PR_DestroyAlarm VBoxNsprPR_DestroyAlarm
+#define PR_SetAlarm VBoxNsprPR_SetAlarm
+#define PR_ResetAlarm VBoxNsprPR_ResetAlarm
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+typedef struct PRAlarm PRAlarm;
+typedef struct PRAlarmID PRAlarmID;
+
+typedef PRBool (PR_CALLBACK *PRPeriodicAlarmFn)(
+ PRAlarmID *id, void *clientData, PRUint32 late);
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION: PR_CreateAlarm
+** DESCRIPTION:
+** Create an alarm context.
+** INPUTS: void
+** OUTPUTS: None
+** RETURN: PRAlarm*
+**
+** SIDE EFFECTS:
+** This creates an alarm context, which is an object used for subsequent
+** notification creations. It also creates a thread that will be used to
+** deliver the notifications that are expected to be defined. The client
+** is resposible for destroying the context when appropriate.
+** RESTRICTIONS:
+** None.
+** MEMORY: The object (PRAlarm) and a thread to support notifications.
+** ALGORITHM: N/A
+***********************************************************************/
+NSPR_API(PRAlarm*) PR_CreateAlarm(void);
+
+/***********************************************************************
+** FUNCTION: PR_DestroyAlarm
+** DESCRIPTION:
+** Destroys the context created by PR_CreateAlarm().
+** INPUTS: PRAlarm*
+** OUTPUTS: None
+** RETURN: PRStatus
+**
+** SIDE EFFECTS:
+** This destroys the context that was created by PR_CreateAlarm().
+** If there are any active alarms (PRAlarmID), they will be cancelled.
+** Once that is done, the thread that was used to deliver the alarms
+** will be joined.
+** RESTRICTIONS:
+** None.
+** MEMORY: N/A
+** ALGORITHM: N/A
+***********************************************************************/
+NSPR_API(PRStatus) PR_DestroyAlarm(PRAlarm *alarm);
+
+/***********************************************************************
+** FUNCTION: PR_SetAlarm
+** DESCRIPTION:
+** Creates a periodic notifier that is to be delivered to a specified
+** function at some fixed interval.
+** INPUTS: PRAlarm *alarm Parent alarm context
+** PRIntervalTime period Interval over which the notifies
+** are delivered.
+** PRUint32 rate The rate within the interval that
+** the notifies will be delivered.
+** PRPeriodicAlarmFn function Entry point where the notifies
+** will be delivered.
+** OUTPUTS: None
+** RETURN: PRAlarmID* Handle to the notifier just created
+** or NULL if the request failed.
+**
+** SIDE EFFECTS:
+** A periodic notifier is created. The notifications will be delivered
+** by the alarm's internal thread at a fixed interval whose rate is the
+** number of interrupts per interval specified. The first notification
+** will be delivered as soon as possible, and they will continue until
+** the notifier routine indicates that they should cease of the alarm
+** context is destroyed (PR_DestroyAlarm).
+** RESTRICTIONS:
+** None.
+** MEMORY: Memory for the notifier object.
+** ALGORITHM: The rate at which notifications are delivered are stated
+** to be "'rate' notifies per 'interval'". The exact time of
+** the notification is computed based on a epoch established
+** when the notifier was set. Each notification is delivered
+** not ealier than the epoch plus the fixed rate times the
+** notification sequence number. Such notifications have the
+** potential to be late by not more than 'interval'/'rate'.
+** The amount of lateness of one notification is taken into
+** account on the next in an attempt to avoid long term slew.
+***********************************************************************/
+NSPR_API(PRAlarmID*) PR_SetAlarm(
+ PRAlarm *alarm, PRIntervalTime period, PRUint32 rate,
+ PRPeriodicAlarmFn function, void *clientData);
+
+/***********************************************************************
+** FUNCTION: PR_ResetAlarm
+** DESCRIPTION:
+** Resets an existing alarm.
+** INPUTS: PRAlarmID *id Identify of the notifier.
+** PRIntervalTime period Interval over which the notifies
+** are delivered.
+** PRUint32 rate The rate within the interval that
+** the notifies will be delivered.
+** OUTPUTS: None
+** RETURN: PRStatus Indication of completion.
+**
+** SIDE EFFECTS:
+** An existing alarm may have its period and rate redefined. The
+** additional side effect is that the notifier's epoch is recomputed.
+** The first notification delivered by the newly refreshed alarm is
+** defined to be 'interval'/'rate' from the time of the reset.
+** RESTRICTIONS:
+** This function may only be called in the notifier for that alarm.
+** MEMORY: N/A.
+** ALGORITHM: See PR_SetAlarm().
+***********************************************************************/
+NSPR_API(PRStatus) PR_ResetAlarm(
+ PRAlarmID *id, PRIntervalTime period, PRUint32 rate);
+
+PR_END_EXTERN_C
+
+#endif /* !defined(pralarm_h) */
+
+/* prinrval.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/probslet.h b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/probslet.h
new file mode 100644
index 00000000..ad346391
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/probslet.h
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** A collection of things thought to be obsolete
+*/
+
+#if defined(PROBSLET_H)
+#else
+#define PROBSLET_H
+
+#include "prio.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_Yield VBoxNsprPR_Yield
+#define PR_Select VBoxNsprPR_Select
+#define PR_FD_ZERO VBoxNsprPR_FD_ZERO
+#define PR_FD_SET VBoxNsprPR_FD_SET
+#define PR_FD_CLR VBoxNsprPR_FD_CLR
+#define PR_FD_ISSET VBoxNsprPR_FD_ISSET
+#define PR_FD_NSET VBoxNsprPR_FD_NSET
+#define PR_FD_NCLR VBoxNsprPR_FD_NCLR
+#define PR_FD_NISSET VBoxNsprPR_FD_NISSET
+#define PR_Stat VBoxNsprPR_Stat
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Yield the current thread. The proper function to use in place of
+** PR_Yield() is PR_Sleep() with an argument of PR_INTERVAL_NO_WAIT.
+*/
+NSPR_API(PRStatus) PR_Yield(void);
+
+/************************************************************************/
+/************* The following definitions are for select *****************/
+/************************************************************************/
+
+/*
+** The following is obsolete and will be deleted in the next release!
+** These are provided for compatibility, but are GUARANTEED to be slow.
+**
+** Override PR_MAX_SELECT_DESC if you need more space in the select set.
+*/
+#ifndef PR_MAX_SELECT_DESC
+#define PR_MAX_SELECT_DESC 1024
+#endif
+typedef struct PR_fd_set {
+ PRUint32 hsize;
+ PRFileDesc *harray[PR_MAX_SELECT_DESC];
+ PRUint32 nsize;
+ PRInt32 narray[PR_MAX_SELECT_DESC];
+} PR_fd_set;
+
+/*
+*************************************************************************
+** FUNCTION: PR_Select
+** DESCRIPTION:
+**
+** The call returns as soon as I/O is ready on one or more of the underlying
+** file/socket descriptors or an exceptional condition is pending. A count of the
+** number of ready descriptors is returned unless a timeout occurs in which case
+** zero is returned. On return, PR_Select replaces the given descriptor sets with
+** subsets consisting of those descriptors that are ready for the requested condition.
+** The total number of ready descriptors in all the sets is the return value.
+**
+** INPUTS:
+** PRInt32 num
+** This argument is unused but is provided for select(unix) interface
+** compatability. All input PR_fd_set arguments are self-describing
+** with its own maximum number of elements in the set.
+**
+** PR_fd_set *readfds
+** A set describing the io descriptors for which ready for reading
+** condition is of interest.
+**
+** PR_fd_set *writefds
+** A set describing the io descriptors for which ready for writing
+** condition is of interest.
+**
+** PR_fd_set *exceptfds
+** A set describing the io descriptors for which exception pending
+** condition is of interest.
+**
+** Any of the above readfds, writefds or exceptfds may be given as NULL
+** pointers if no descriptors are of interest for that particular condition.
+**
+** PRIntervalTime timeout
+** Amount of time the call will block waiting for I/O to become ready.
+** If this time expires without any I/O becoming ready, the result will
+** be zero.
+**
+** OUTPUTS:
+** PR_fd_set *readfds
+** A set describing the io descriptors which are ready for reading.
+**
+** PR_fd_set *writefds
+** A set describing the io descriptors which are ready for writing.
+**
+** PR_fd_set *exceptfds
+** A set describing the io descriptors which have pending exception.
+**
+** RETURN:PRInt32
+** Number of io descriptors with asked for conditions or zero if the function
+** timed out or -1 on failure. The reason for the failure is obtained by
+** calling PR_GetError().
+** XXX can we implement this on windoze and mac?
+**************************************************************************
+*/
+NSPR_API(PRInt32) PR_Select(
+ PRInt32 num, PR_fd_set *readfds, PR_fd_set *writefds,
+ PR_fd_set *exceptfds, PRIntervalTime timeout);
+
+/*
+** The following are not thread safe for two threads operating on them at the
+** same time.
+**
+** The following routines are provided for manipulating io descriptor sets.
+** PR_FD_ZERO(&fdset) initializes a descriptor set fdset to the null set.
+** PR_FD_SET(fd, &fdset) includes a particular file descriptor fd in fdset.
+** PR_FD_CLR(fd, &fdset) removes a file descriptor fd from fdset.
+** PR_FD_ISSET(fd, &fdset) is nonzero if file descriptor fd is a member of
+** fdset, zero otherwise.
+**
+** PR_FD_NSET(osfd, &fdset) includes a particular native file descriptor osfd
+** in fdset.
+** PR_FD_NCLR(osfd, &fdset) removes a native file descriptor osfd from fdset.
+** PR_FD_NISSET(osfd, &fdset) is nonzero if native file descriptor osfd is a member of
+** fdset, zero otherwise.
+*/
+
+NSPR_API(void) PR_FD_ZERO(PR_fd_set *set);
+NSPR_API(void) PR_FD_SET(PRFileDesc *fd, PR_fd_set *set);
+NSPR_API(void) PR_FD_CLR(PRFileDesc *fd, PR_fd_set *set);
+NSPR_API(PRInt32) PR_FD_ISSET(PRFileDesc *fd, PR_fd_set *set);
+NSPR_API(void) PR_FD_NSET(PRInt32 osfd, PR_fd_set *set);
+NSPR_API(void) PR_FD_NCLR(PRInt32 osfd, PR_fd_set *set);
+NSPR_API(PRInt32) PR_FD_NISSET(PRInt32 osfd, PR_fd_set *set);
+
+#ifndef NO_NSPR_10_SUPPORT
+#ifdef XP_MAC
+#include <stat.h>
+#else
+#include <sys/stat.h>
+#endif
+
+NSPR_API(PRInt32) PR_Stat(const char *path, struct stat *buf);
+#endif /* NO_NSPR_10_SUPPORT */
+
+PR_END_EXTERN_C
+
+#endif /* defined(PROBSLET_H) */
+
+/* probslet.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/protypes.h b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/protypes.h
new file mode 100644
index 00000000..0912e497
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/protypes.h
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This header typedefs the old 'native' types to the new PR<type>s.
+ * These definitions are scheduled to be eliminated at the earliest
+ * possible time. The NSPR API is implemented and documented using
+ * the new definitions.
+ */
+
+#if !defined(PROTYPES_H)
+#define PROTYPES_H
+
+typedef PRUintn uintn;
+#ifndef _XP_Core_
+typedef PRIntn intn;
+#endif
+
+/*
+ * It is trickier to define uint, int8, uint8, int16, uint16,
+ * int32, uint32, int64, and uint64 because some of these int
+ * types are defined by standard header files on some platforms.
+ * Our strategy here is to include all such standard headers
+ * first, and then define these int types only if they are not
+ * defined by those standard headers.
+ */
+
+/*
+ * BeOS defines all the int types below in its standard header
+ * file SupportDefs.h.
+ */
+#ifdef XP_BEOS
+#include <support/SupportDefs.h>
+#endif
+
+/*
+ * OpenVMS defines all the int types below in its standard
+ * header files ints.h and types.h.
+ */
+#ifdef VMS
+#include <ints.h>
+#include <types.h>
+#endif
+
+/*
+ * SVR4 typedef of uint is commonly found on UNIX machines.
+ *
+ * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h)
+ * defines the types int8, int16, int32, and int64.
+ */
+#ifdef XP_UNIX
+#include <sys/types.h>
+#endif
+
+/* model.h on HP-UX defines int8, int16, and int32. */
+#ifdef HPUX
+#include <model.h>
+#endif
+
+/*
+ * uint
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS) \
+ && !defined(XP_OS2_EMX) \
+ && !defined(XP_UNIX) || defined(NTO)
+typedef PRUintn uint;
+#endif
+
+/*
+ * uint64
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS) \
+ && (!defined(__APPLE__) || !defined(_UINT64))
+/* bird: ^^^ cssmconfig.h conflicts on 10.6/amd64; XP_MACOSX isn't always set so check for the compiler. */
+typedef PRUint64 uint64;
+# if defined(__APPLE__) /* bird */
+# define _UINT64 /* bird */
+# endif /* bird */
+#endif
+
+/*
+ * uint32
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS)
+#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO)
+typedef PRUint32 uint32;
+#else
+typedef unsigned long uint32;
+#endif
+#endif
+
+/*
+ * uint16
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS)
+typedef PRUint16 uint16;
+#endif
+
+/*
+ * uint8
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS)
+typedef PRUint8 uint8;
+#endif
+
+/*
+ * int64
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS) \
+ && !defined(_PR_AIX_HAVE_BSD_INT_TYPES)
+typedef PRInt64 int64;
+#endif
+
+/*
+ * int32
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS) \
+ && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \
+ && !defined(HPUX)
+#if !defined(WIN32) || !defined(_WINSOCK2API_) /* defines its own "int32" */
+#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO)
+typedef PRInt32 int32;
+#else
+typedef long int32;
+#endif
+#endif
+#endif
+
+/*
+ * int16
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS) \
+ && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \
+ && !defined(HPUX)
+typedef PRInt16 int16;
+#endif
+
+/*
+ * int8
+ */
+
+#if !defined(XP_BEOS) && !defined(VMS) \
+ && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \
+ && !defined(HPUX)
+typedef PRInt8 int8;
+#endif
+
+typedef PRFloat64 float64;
+typedef PRUptrdiff uptrdiff_t;
+typedef PRUword uprword_t;
+typedef PRWord prword_t;
+
+
+/* Re: prbit.h */
+#define TEST_BIT PR_TEST_BIT
+#define SET_BIT PR_SET_BIT
+#define CLEAR_BIT PR_CLEAR_BIT
+
+/* Re: prarena.h->plarena.h */
+#define PRArena PLArena
+#define PRArenaPool PLArenaPool
+#define PRArenaStats PLArenaStats
+#define PR_ARENA_ALIGN PL_ARENA_ALIGN
+#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL
+#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE
+#define PR_ARENA_GROW PL_ARENA_GROW
+#define PR_ARENA_MARK PL_ARENA_MARK
+#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED
+#define PR_CLEAR_ARENA PL_CLEAR_ARENA
+#define PR_ARENA_RELEASE PL_ARENA_RELEASE
+#define PR_COUNT_ARENA PL_COUNT_ARENA
+#define PR_ARENA_DESTROY PL_ARENA_DESTROY
+#define PR_InitArenaPool PL_InitArenaPool
+#define PR_FreeArenaPool PL_FreeArenaPool
+#define PR_FinishArenaPool PL_FinishArenaPool
+#define PR_CompactArenaPool PL_CompactArenaPool
+#define PR_ArenaFinish PL_ArenaFinish
+#define PR_ArenaAllocate PL_ArenaAllocate
+#define PR_ArenaGrow PL_ArenaGrow
+#define PR_ArenaRelease PL_ArenaRelease
+#define PR_ArenaCountAllocation PL_ArenaCountAllocation
+#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth
+#define PR_ArenaCountGrowth PL_ArenaCountGrowth
+#define PR_ArenaCountRelease PL_ArenaCountRelease
+#define PR_ArenaCountRetract PL_ArenaCountRetract
+
+/* Re: prhash.h->plhash.h */
+#define PRHashEntry PLHashEntry
+#define PRHashTable PLHashTable
+#define PRHashNumber PLHashNumber
+#define PRHashFunction PLHashFunction
+#define PRHashComparator PLHashComparator
+#define PRHashEnumerator PLHashEnumerator
+#define PRHashAllocOps PLHashAllocOps
+#define PR_NewHashTable PL_NewHashTable
+#define PR_HashTableDestroy PL_HashTableDestroy
+#define PR_HashTableRawLookup PL_HashTableRawLookup
+#define PR_HashTableRawAdd PL_HashTableRawAdd
+#define PR_HashTableRawRemove PL_HashTableRawRemove
+#define PR_HashTableAdd PL_HashTableAdd
+#define PR_HashTableRemove PL_HashTableRemove
+#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries
+#define PR_HashTableLookup PL_HashTableLookup
+#define PR_HashTableDump PL_HashTableDump
+#define PR_HashString PL_HashString
+#define PR_CompareStrings PL_CompareStrings
+#define PR_CompareValues PL_CompareValues
+
+#if defined(XP_MAC)
+#ifndef TRUE /* Mac standard is lower case true */
+ #define TRUE 1
+#endif
+#ifndef FALSE /* Mac standard is lower case false */
+ #define FALSE 0
+#endif
+#endif
+
+#endif /* !defined(PROTYPES_H) */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/prsem.h b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/prsem.h
new file mode 100644
index 00000000..447027a6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/obsolete/prsem.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prsem_h___
+#define prsem_h___
+
+/*
+** API for counting semaphores. Semaphores are counting synchronizing
+** variables based on a lock and a condition variable. They are lightweight
+** contention control for a given count of resources.
+*/
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_NewSem VBoxNsprPR_NewSem
+#define PR_DestroySem VBoxNsprPR_DestroySem
+#define PR_WaitSem VBoxNsprPR_WaitSem
+#define PR_PostSem VBoxNsprPR_PostSem
+#define PR_GetValueSem VBoxNsprPR_GetValueSem
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PRSemaphore PRSemaphore;
+
+/*
+** Create a new semaphore object.
+*/
+NSPR_API(PRSemaphore*) PR_NewSem(PRUintn value);
+
+/*
+** Destroy the given semaphore object.
+**
+*/
+NSPR_API(void) PR_DestroySem(PRSemaphore *sem);
+
+/*
+** Wait on a Semaphore.
+**
+** This routine allows a calling thread to wait or proceed depending upon the
+** state of the semahore sem. The thread can proceed only if the counter value
+** of the semaphore sem is currently greater than 0. If the value of semaphore
+** sem is positive, it is decremented by one and the routine returns immediately
+** allowing the calling thread to continue. If the value of semaphore sem is 0,
+** the calling thread blocks awaiting the semaphore to be released by another
+** thread.
+**
+** This routine can return PR_PENDING_INTERRUPT if the waiting thread
+** has been interrupted.
+*/
+NSPR_API(PRStatus) PR_WaitSem(PRSemaphore *sem);
+
+/*
+** This routine increments the counter value of the semaphore. If other threads
+** are blocked for the semaphore, then the scheduler will determine which ONE
+** thread will be unblocked.
+*/
+NSPR_API(void) PR_PostSem(PRSemaphore *sem);
+
+/*
+** Returns the value of the semaphore referenced by sem without affecting
+** the state of the semaphore. The value represents the semaphore vaule
+F** at the time of the call, but may not be the actual value when the
+** caller inspects it.
+*/
+NSPR_API(PRUintn) PR_GetValueSem(PRSemaphore *sem);
+
+PR_END_EXTERN_C
+
+#endif /* prsem_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/pratom.h b/src/libs/xpcom18a4/nsprpub/pr/include/pratom.h
new file mode 100644
index 00000000..9ea92c36
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/pratom.h
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* GLOBAL FUNCTIONS:
+** DESCRIPTION:
+** PR Atomic operations
+*/
+
+#ifndef pratom_h___
+#define pratom_h___
+
+#include "prtypes.h"
+#include "prlock.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_AtomicDecrement VBoxNsprPR_AtomicDecrement
+#define PR_AtomicIncrement VBoxNsprPR_AtomicIncrement
+#define PR_AtomicAdd VBoxNsprPR_AtomicAdd
+#define PR_AtomicSet VBoxNsprPR_AtomicSet
+#define PR_CreateStack VBoxNsprPR_CreateStack
+#define PR_StackPush VBoxNsprPR_StackPush
+#define PR_StackPop VBoxNsprPR_StackPop
+#define PR_DestroyStack VBoxNsprPR_DestroyStack
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** FUNCTION: PR_AtomicIncrement
+** DESCRIPTION:
+** Atomically increment a 32 bit value.
+** INPUTS:
+** val: a pointer to the value to increment
+** RETURN:
+** the returned value is the result of the increment
+*/
+NSPR_API(PRInt32) PR_AtomicIncrement(PRInt32 *val);
+
+/*
+** FUNCTION: PR_AtomicDecrement
+** DESCRIPTION:
+** Atomically decrement a 32 bit value.
+** INPUTS:
+** val: a pointer to the value to decrement
+** RETURN:
+** the returned value is the result of the decrement
+*/
+NSPR_API(PRInt32) PR_AtomicDecrement(PRInt32 *val);
+
+/*
+** FUNCTION: PR_AtomicSet
+** DESCRIPTION:
+** Atomically set a 32 bit value.
+** INPUTS:
+** val: A pointer to a 32 bit value to be set
+** newval: The newvalue to assign to val
+** RETURN:
+** Returns the prior value
+*/
+NSPR_API(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval);
+
+/*
+** FUNCTION: PR_AtomicAdd
+** DESCRIPTION:
+** Atomically add a 32 bit value.
+** INPUTS:
+** ptr: a pointer to the value to increment
+** val: value to be added
+** RETURN:
+** the returned value is the result of the addition
+*/
+NSPR_API(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+
+/*
+** LIFO linked-list (stack)
+*/
+typedef struct PRStackElemStr PRStackElem;
+
+struct PRStackElemStr {
+ PRStackElem *prstk_elem_next; /* next pointer MUST be at offset 0;
+ assembly language code relies on this */
+};
+
+typedef struct PRStackStr PRStack;
+
+/*
+** FUNCTION: PR_CreateStack
+** DESCRIPTION:
+** Create a stack, a LIFO linked list
+** INPUTS:
+** stack_name: a pointer to string containing the name of the stack
+** RETURN:
+** A pointer to the created stack, if successful, else NULL.
+*/
+NSPR_API(PRStack *) PR_CreateStack(const char *stack_name);
+
+/*
+** FUNCTION: PR_StackPush
+** DESCRIPTION:
+** Push an element on the top of the stack
+** INPUTS:
+** stack: pointer to the stack
+** stack_elem: pointer to the stack element
+** RETURN:
+** None
+*/
+NSPR_API(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem);
+
+/*
+** FUNCTION: PR_StackPop
+** DESCRIPTION:
+** Remove the element on the top of the stack
+** INPUTS:
+** stack: pointer to the stack
+** RETURN:
+** A pointer to the stack element removed from the top of the stack,
+** if non-empty,
+** else NULL
+*/
+NSPR_API(PRStackElem *) PR_StackPop(PRStack *stack);
+
+/*
+** FUNCTION: PR_DestroyStack
+** DESCRIPTION:
+** Destroy the stack
+** INPUTS:
+** stack: pointer to the stack
+** RETURN:
+** PR_SUCCESS - if successfully deleted
+** PR_FAILURE - if the stack is not empty
+** PR_GetError will return
+** PR_INVALID_STATE_ERROR - stack is not empty
+*/
+NSPR_API(PRStatus) PR_DestroyStack(PRStack *stack);
+
+PR_END_EXTERN_C
+
+#endif /* pratom_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prbit.h b/src/libs/xpcom18a4/nsprpub/pr/include/prbit.h
new file mode 100644
index 00000000..4b112271
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prbit.h
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prbit_h___
+#define prbit_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CeilingLog2 VBoxNsprPR_CeilingLog2
+#define PR_FloorLog2 VBoxNsprPR_FloorLog2
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** A prbitmap_t is a long integer that can be used for bitmaps
+*/
+typedef unsigned long prbitmap_t;
+
+#define PR_TEST_BIT(_map,_bit) \
+ ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] & (1L << ((_bit) & (PR_BITS_PER_LONG-1))))
+#define PR_SET_BIT(_map,_bit) \
+ ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] |= (1L << ((_bit) & (PR_BITS_PER_LONG-1))))
+#define PR_CLEAR_BIT(_map,_bit) \
+ ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] &= ~(1L << ((_bit) & (PR_BITS_PER_LONG-1))))
+
+/*
+** Compute the log of the least power of 2 greater than or equal to n
+*/
+NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i);
+
+/*
+** Compute the log of the greatest power of 2 less than or equal to n
+*/
+NSPR_API(PRIntn) PR_FloorLog2(PRUint32 i);
+
+/*
+** Macro version of PR_CeilingLog2: Compute the log of the least power of
+** 2 greater than or equal to _n. The result is returned in _log2.
+*/
+#define PR_CEILING_LOG2(_log2,_n) \
+ PR_BEGIN_MACRO \
+ PRUint32 j_ = (PRUint32)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1; \
+ PR_END_MACRO
+
+/*
+** Macro version of PR_FloorLog2: Compute the log of the greatest power of
+** 2 less than or equal to _n. The result is returned in _log2.
+**
+** This is equivalent to finding the highest set bit in the word.
+*/
+#define PR_FLOOR_LOG2(_log2,_n) \
+ PR_BEGIN_MACRO \
+ PRUint32 j_ = (PRUint32)(_n); \
+ (_log2) = 0; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1; \
+ PR_END_MACRO
+
+PR_END_EXTERN_C
+#endif /* prbit_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prclist.h b/src/libs/xpcom18a4/nsprpub/pr/include/prclist.h
new file mode 100644
index 00000000..1680ac17
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prclist.h
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prclist_h___
+#define prclist_h___
+
+#include "prtypes.h"
+
+typedef struct PRCListStr PRCList;
+
+/*
+** Circular linked list
+*/
+struct PRCListStr {
+ PRCList *next;
+ PRCList *prev;
+};
+
+/*
+** Insert element "_e" into the list, before "_l".
+*/
+#define PR_INSERT_BEFORE(_e,_l) \
+ PR_BEGIN_MACRO \
+ (_e)->next = (_l); \
+ (_e)->prev = (_l)->prev; \
+ (_l)->prev->next = (_e); \
+ (_l)->prev = (_e); \
+ PR_END_MACRO
+
+/*
+** Insert element "_e" into the list, after "_l".
+*/
+#define PR_INSERT_AFTER(_e,_l) \
+ PR_BEGIN_MACRO \
+ (_e)->next = (_l)->next; \
+ (_e)->prev = (_l); \
+ (_l)->next->prev = (_e); \
+ (_l)->next = (_e); \
+ PR_END_MACRO
+
+/*
+** Return the element following element "_e"
+*/
+#define PR_NEXT_LINK(_e) \
+ ((_e)->next)
+/*
+** Return the element preceding element "_e"
+*/
+#define PR_PREV_LINK(_e) \
+ ((_e)->prev)
+
+/*
+** Append an element "_e" to the end of the list "_l"
+*/
+#define PR_APPEND_LINK(_e,_l) PR_INSERT_BEFORE(_e,_l)
+
+/*
+** Insert an element "_e" at the head of the list "_l"
+*/
+#define PR_INSERT_LINK(_e,_l) PR_INSERT_AFTER(_e,_l)
+
+/* Return the head/tail of the list */
+#define PR_LIST_HEAD(_l) (_l)->next
+#define PR_LIST_TAIL(_l) (_l)->prev
+
+/*
+** Remove the element "_e" from it's circular list.
+*/
+#define PR_REMOVE_LINK(_e) \
+ PR_BEGIN_MACRO \
+ (_e)->prev->next = (_e)->next; \
+ (_e)->next->prev = (_e)->prev; \
+ PR_END_MACRO
+
+/*
+** Remove the element "_e" from it's circular list. Also initializes the
+** linkage.
+*/
+#define PR_REMOVE_AND_INIT_LINK(_e) \
+ PR_BEGIN_MACRO \
+ (_e)->prev->next = (_e)->next; \
+ (_e)->next->prev = (_e)->prev; \
+ (_e)->next = (_e); \
+ (_e)->prev = (_e); \
+ PR_END_MACRO
+
+/*
+** Return non-zero if the given circular list "_l" is empty, zero if the
+** circular list is not empty
+*/
+#define PR_CLIST_IS_EMPTY(_l) \
+ ((_l)->next == (_l))
+
+/*
+** Initialize a circular list
+*/
+#define PR_INIT_CLIST(_l) \
+ PR_BEGIN_MACRO \
+ (_l)->next = (_l); \
+ (_l)->prev = (_l); \
+ PR_END_MACRO
+
+#define PR_INIT_STATIC_CLIST(_l) \
+ {(_l), (_l)}
+
+#endif /* prclist_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prcmon.h b/src/libs/xpcom18a4/nsprpub/pr/include/prcmon.h
new file mode 100644
index 00000000..d470da38
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prcmon.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prcmon_h___
+#define prcmon_h___
+
+/*
+** Interface to cached monitors. Cached monitors use an address to find a
+** given PR monitor. In this way a monitor can be associated with another
+** object without preallocating a monitor for all objects.
+**
+** A hash table is used to quickly map addresses to individual monitors
+** and the system automatically grows the hash table as needed.
+**
+** Cache monitors are about 5 times slower to use than uncached monitors.
+*/
+#include "prmon.h"
+#include "prinrval.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CEnterMonitor VBoxNsprPR_CEnterMonitor
+#define PR_CExitMonitor VBoxNsprPR_CExitMonitor
+#define PR_CNotify VBoxNsprPR_CNotify
+#define PR_CWait VBoxNsprPR_CWait
+#define PR_CNotifyAll VBoxNsprPR_CNotifyAll
+#define PR_CSetOnMonitorRecycle VBoxNsprPR_CSetOnMonitorRecycle
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**
+** Like PR_EnterMonitor except use the "address" to find a monitor in the
+** monitor cache. If successful, returns the PRMonitor now associated
+** with "address". Note that you must PR_CExitMonitor the address to
+** release the monitor cache entry (otherwise the monitor cache will fill
+** up). This call will return NULL if the monitor cache needs to be
+** expanded and the system is out of memory.
+*/
+NSPR_API(PRMonitor*) PR_CEnterMonitor(void *address);
+
+/*
+** Like PR_ExitMonitor except use the "address" to find a monitor in the
+** monitor cache.
+*/
+NSPR_API(PRStatus) PR_CExitMonitor(void *address);
+
+/*
+** Like PR_Wait except use the "address" to find a monitor in the
+** monitor cache.
+*/
+NSPR_API(PRStatus) PR_CWait(void *address, PRIntervalTime timeout);
+
+/*
+** Like PR_Notify except use the "address" to find a monitor in the
+** monitor cache.
+*/
+NSPR_API(PRStatus) PR_CNotify(void *address);
+
+/*
+** Like PR_NotifyAll except use the "address" to find a monitor in the
+** monitor cache.
+*/
+NSPR_API(PRStatus) PR_CNotifyAll(void *address);
+
+/*
+** Set a callback to be invoked each time a monitor is recycled from the cache
+** freelist, with the monitor's cache-key passed in address.
+*/
+NSPR_API(void) PR_CSetOnMonitorRecycle(void (PR_CALLBACK *callback)(void *address));
+
+PR_END_EXTERN_C
+
+#endif /* prcmon_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prcountr.h b/src/libs/xpcom18a4/nsprpub/pr/include/prcountr.h
new file mode 100644
index 00000000..016200a4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prcountr.h
@@ -0,0 +1,572 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prcountr_h___
+#define prcountr_h___
+
+/*----------------------------------------------------------------------------
+** prcountr.h -- NSPR Instrumentation counters
+**
+** The NSPR Counter Feature provides a means to "count
+** something." Counters can be dynamically defined, incremented,
+** decremented, set, and deleted under application program
+** control.
+**
+** The Counter Feature is intended to be used as instrumentation,
+** not as operational data. If you need a counter for operational
+** data, use native integral types.
+**
+** Counters are 32bit unsigned intergers. On overflow, a counter
+** will wrap. No exception is recognized or reported.
+**
+** A counter can be dynamically created using a two level naming
+** convention. A "handle" is returned when the counter is
+** created. The counter can subsequently be addressed by its
+** handle. An API is provided to get an existing counter's handle
+** given the names with which it was originally created.
+** Similarly, a counter's name can be retrieved given its handle.
+**
+** The counter naming convention is a two-level hierarchy. The
+** QName is the higher level of the hierarchy; RName is the
+** lower level. RNames can be thought of as existing within a
+** QName. The same RName can exist within multiple QNames. QNames
+** are unique. The NSPR Counter is not a near-zero overhead
+** feature. Application designers should be aware of
+** serialization issues when using the Counter API. Creating a
+** counter locks a large asset, potentially causing a stall. This
+** suggest that applications should create counters at component
+** initialization, for example, and not create and destroy them
+** willy-nilly. ... You have been warned.
+**
+** Incrementing and Adding to counters uses atomic operations.
+** The performance of these operations will vary from platform
+** to platform. On platforms where atomic operations are not
+** supported the overhead may be substantial.
+**
+** When traversing the counter database with FindNext functions,
+** the instantaneous values of any given counter is that at the
+** moment of extraction. The state of the entire counter database
+** may not be viewed as atomic.
+**
+** The counter interface may be disabled (No-Op'd) at compile
+** time. When DEBUG is defined at compile time, the Counter
+** Feature is compiled into NSPR and applications invoking it.
+** When DEBUG is not defined, the counter macros compile to
+** nothing. To force the Counter Feature to be compiled into an
+** optimized build, define FORCE_NSPR_COUNTERS at compile time
+** for both NSPR and the application intending to use it.
+**
+** Application designers should use the macro form of the Counter
+** Feature methods to minimize performance impact in optimized
+** builds. The macros normally compile to nothing on optimized
+** builds.
+**
+** Application designers should be aware of the effects of
+** debug and optimized build differences when using result of the
+** Counter Feature macros in expressions.
+**
+** The Counter Feature is thread-safe and SMP safe.
+**
+** /lth. 09-Jun-1998.
+*/
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateCounter VBoxNsprPR_CreateCounter
+#define PR_DestroyCounter VBoxNsprPR_DestroyCounter
+#define PR_GetCounterHandleFromName VBoxNsprPR_GetCounterHandleFromName
+#define PR_GetCounterNameFromHandle VBoxNsprPR_GetCounterNameFromHandle
+#define PR_IncrementCounter VBoxNsprPR_IncrementCounter
+#define PR_DecrementCounter VBoxNsprPR_DecrementCounter
+#define PR_AddToCounter VBoxNsprPR_AddToCounter
+#define PR_SubtractFromCounter VBoxNsprPR_SubtractFromCounter
+#define PR_GetCounter VBoxNsprPR_GetCounter
+#define PR_SetCounter VBoxNsprPR_SetCounter
+#define PR_FindNextCounterQname VBoxNsprPR_FindNextCounterQname
+#define PR_FindNextCounterRname VBoxNsprPR_FindNextCounterRname
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Opaque counter handle type.
+** ... don't even think of looking in here.
+**
+*/
+typedef void * PRCounterHandle;
+
+#define PRCOUNTER_NAME_MAX 31
+#define PRCOUNTER_DESC_MAX 255
+
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DEFINE_COUNTER() -- Define a PRCounterHandle
+**
+** DESCRIPTION: PR_DEFINE_COUNTER() is used to define a counter
+** handle.
+**
+*/
+#define PR_DEFINE_COUNTER(name) PRCounterHandle name
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_INIT_COUNTER_HANDLE() -- Set the value of a PRCounterHandle
+**
+** DESCRIPTION:
+** PR_INIT_COUNTER_HANDLE() sets the value of a PRCounterHandle
+** to value.
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_INIT_COUNTER_HANDLE(handle,value)\
+ (handle) = (PRCounterHandle)(value)
+#else
+#define PR_INIT_COUNTER_HANDLE(handle,value)
+#endif
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_CreateCounter() -- Create a counter
+**
+** DESCRIPTION: PR_CreateCounter() creates a counter object and
+** initializes it to zero.
+**
+** The macro form takes as its first argument the name of the
+** PRCounterHandle to receive the handle returned from
+** PR_CreateCounter().
+**
+** INPUTS:
+** qName: The QName for the counter object. The maximum length
+** of qName is defined by PRCOUNTER_NAME_MAX
+**
+** rName: The RName for the counter object. The maximum length
+** of qName is defined by PRCOUNTER_NAME_MAX
+**
+** descrioption: The description of the counter object. The
+** maximum length of description is defined by
+** PRCOUNTER_DESC_MAX.
+**
+** OUTPUTS:
+**
+** RETURNS:
+** PRCounterHandle.
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_CREATE_COUNTER(handle,qName,rName,description)\
+ (handle) = PR_CreateCounter((qName),(rName),(description))
+#else
+#define PR_CREATE_COUNTER(handle,qName,rName,description)
+#endif
+
+NSPR_API(PRCounterHandle)
+ PR_CreateCounter(
+ const char *qName,
+ const char *rName,
+ const char *description
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DestroyCounter() -- Destroy a counter object.
+**
+** DESCRIPTION: PR_DestroyCounter() removes a counter and
+** unregisters its handle from the counter database.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter to be destroyed.
+**
+** OUTPUTS:
+** The counter is destroyed.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_DESTROY_COUNTER(handle) PR_DestroyCounter((handle))
+#else
+#define PR_DESTROY_COUNTER(handle)
+#endif
+
+NSPR_API(void)
+ PR_DestroyCounter(
+ PRCounterHandle handle
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetCounterHandleFromName() -- Retreive a
+** counter's handle give its name.
+**
+** DESCRIPTION: PR_GetCounterHandleFromName() retreives a
+** counter's handle from the counter database, given the name
+** the counter was originally created with.
+**
+** INPUTS:
+** qName: Counter's original QName.
+** rName: Counter's original RName.
+**
+** OUTPUTS:
+**
+** RETURNS:
+** PRCounterHandle or PRCounterError.
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName)\
+ (handle) = PR_GetCounterHandleFromName((qName),(rName))
+#else
+#define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName)
+#endif
+
+NSPR_API(PRCounterHandle)
+ PR_GetCounterHandleFromName(
+ const char *qName,
+ const char *rName
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetCounterNameFromHandle() -- Retreive a
+** counter's name, given its handle.
+**
+** DESCRIPTION: PR_GetCounterNameFromHandle() retreives a
+** counter's name given its handle.
+**
+** INPUTS:
+** qName: Where to store a pointer to qName.
+** rName: Where to store a pointer to rName.
+** description: Where to store a pointer to description.
+**
+** OUTPUTS: Pointers to the Counter Feature's copies of the names
+** used when the counters were created.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description)\
+ PR_GetCounterNameFromHandle((handle),(qName),(rName),(description))
+#else
+#define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description )
+#endif
+
+NSPR_API(void)
+ PR_GetCounterNameFromHandle(
+ PRCounterHandle handle,
+ const char **qName,
+ const char **rName,
+ const char **description
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_IncrementCounter() -- Add one to the referenced
+** counter.
+**
+** DESCRIPTION: Add one to the referenced counter.
+**
+** INPUTS:
+** handle: The PRCounterHandle of the counter to be incremented
+**
+** OUTPUTS: The counter is incrementd.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_INCREMENT_COUNTER(handle) PR_IncrementCounter(handle)
+#else
+#define PR_INCREMENT_COUNTER(handle)
+#endif
+
+NSPR_API(void)
+ PR_IncrementCounter(
+ PRCounterHandle handle
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DecrementCounter() -- Subtract one from the
+** referenced counter
+**
+** DESCRIPTION: Subtract one from the referenced counter.
+**
+** INPUTS:
+** handle: The PRCounterHandle of the coutner to be
+** decremented.
+**
+** OUTPUTS: the counter is decremented.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_DECREMENT_COUNTER(handle) PR_DecrementCounter(handle)
+#else
+#define PR_DECREMENT_COUNTER(handle)
+#endif
+
+NSPR_API(void)
+ PR_DecrementCounter(
+ PRCounterHandle handle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_AddToCounter() -- Add a value to a counter.
+**
+** DESCRIPTION: Add value to the counter referenced by handle.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter to be added to.
+**
+** value: the value to be added to the counter.
+**
+** OUTPUTS: new value for counter.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_ADD_TO_COUNTER(handle,value)\
+ PR_AddToCounter((handle),(value))
+#else
+#define PR_ADD_TO_COUNTER(handle,value)
+#endif
+
+NSPR_API(void)
+ PR_AddToCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_SubtractFromCounter() -- A value is subtracted
+** from a counter.
+**
+** DESCRIPTION:
+** Subtract a value from a counter.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter to be subtracted
+** from.
+**
+** value: the value to be subtracted from the counter.
+**
+** OUTPUTS: new value for counter
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_SUBTRACT_FROM_COUNTER(handle,value)\
+ PR_SubtractFromCounter((handle),(value))
+#else
+#define PR_SUBTRACT_FROM_COUNTER(handle,value)
+#endif
+
+NSPR_API(void)
+ PR_SubtractFromCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetCounter() -- Retreive the value of a counter
+**
+** DESCRIPTION:
+** Retreive the value of a counter.
+**
+** INPUTS:
+** handle: the PR_CounterHandle of the counter to be retreived
+**
+** OUTPUTS:
+**
+** RETURNS: The value of the referenced counter
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_GET_COUNTER(counter,handle)\
+ (counter) = PR_GetCounter((handle))
+#else
+#define PR_GET_COUNTER(counter,handle) 0
+#endif
+
+NSPR_API(PRUint32)
+ PR_GetCounter(
+ PRCounterHandle handle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_SetCounter() -- Replace the content of counter
+** with value.
+**
+** DESCRIPTION: The contents of the referenced counter are
+** replaced by value.
+**
+** INPUTS:
+** handle: the PRCounterHandle of the counter whose contents
+** are to be replaced.
+**
+** value: the new value of the counter.
+**
+** OUTPUTS:
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_SET_COUNTER(handle,value) PR_SetCounter((handle),(value))
+#else
+#define PR_SET_COUNTER(handle,value)
+#endif
+
+NSPR_API(void)
+ PR_SetCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextCounterQname() -- Retreive the next QName counter
+** handle iterator
+**
+** DESCRIPTION:
+** PR_FindNextCounterQname() retreives the first or next Qname
+** the counter data base, depending on the value of handle. When
+** handle is NULL, the function attempts to retreive the first
+** QName handle in the database. When handle is a handle previosly
+** retreived QName handle, then the function attempts to retreive
+** the next QName handle.
+**
+** INPUTS:
+** handle: PRCounterHandle or NULL.
+**
+** OUTPUTS: returned
+**
+** RETURNS: PRCounterHandle or NULL when no more QName counter
+** handles are present.
+**
+** RESTRICTIONS:
+** A concurrent PR_CreateCounter() or PR_DestroyCounter() may
+** cause unpredictable results.
+**
+** A PRCounterHandle returned from this function may only be used
+** in another PR_FindNextCounterQname() function call; other
+** operations may cause unpredictable results.
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_FIND_NEXT_COUNTER_QNAME(next,handle)\
+ (next) = PR_FindNextCounterQname((handle))
+#else
+#define PR_FIND_NEXT_COUNTER_QNAME(next,handle) NULL
+#endif
+
+NSPR_API(PRCounterHandle)
+ PR_FindNextCounterQname(
+ PRCounterHandle handle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextCounterRname() -- Retreive the next RName counter
+** handle iterator
+**
+** DESCRIPTION:
+** PR_FindNextCounterRname() retreives the first or next RNname
+** handle from the counter data base, depending on the
+** value of handle. When handle is NULL, the function attempts to
+** retreive the first RName handle in the database. When handle is
+** a handle previosly retreived RName handle, then the function
+** attempts to retreive the next RName handle.
+**
+** INPUTS:
+** handle: PRCounterHandle or NULL.
+** qhandle: PRCounterHandle of a previously aquired via
+** PR_FIND_NEXT_QNAME_HANDLE()
+**
+** OUTPUTS: returned
+**
+** RETURNS: PRCounterHandle or NULL when no more RName counter
+** handles are present.
+**
+** RESTRICTIONS:
+** A concurrent PR_CreateCounter() or PR_DestroyCounter() may
+** cause unpredictable results.
+**
+** A PRCounterHandle returned from this function may only be used
+** in another PR_FindNextCounterRname() function call; other
+** operations may cause unpredictable results.
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS)
+#define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle)\
+ (next) = PR_FindNextCounterRname((rhandle),(qhandle))
+#else
+#define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle)
+#endif
+
+NSPR_API(PRCounterHandle)
+ PR_FindNextCounterRname(
+ PRCounterHandle rhandle,
+ PRCounterHandle qhandle
+);
+
+PR_END_EXTERN_C
+
+#endif /* prcountr_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prcvar.h b/src/libs/xpcom18a4/nsprpub/pr/include/prcvar.h
new file mode 100644
index 00000000..a094bb6e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prcvar.h
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prcvar_h___
+#define prcvar_h___
+
+#include "prlock.h"
+#include "prinrval.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_NewCondVar VBoxNsprPR_NewCondVar
+#define PR_DestroyCondVar VBoxNsprPR_DestroyCondVar
+#define PR_WaitCondVar VBoxNsprPR_WaitCondVar
+#define PR_NotifyCondVar VBoxNsprPR_NotifyCondVar
+#define PR_NotifyAllCondVar VBoxNsprPR_NotifyAllCondVar
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PRCondVar PRCondVar;
+
+/*
+** Create a new condition variable.
+**
+** "lock" is the lock used to protect the condition variable.
+**
+** Condition variables are synchronization objects that threads can use
+** to wait for some condition to occur.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low. In such cases, a NULL will be returned.
+*/
+NSPR_API(PRCondVar*) PR_NewCondVar(PRLock *lock);
+
+/*
+** Destroy a condition variable. There must be no thread
+** waiting on the condvar. The caller is responsible for guaranteeing
+** that the condvar is no longer in use.
+**
+*/
+NSPR_API(void) PR_DestroyCondVar(PRCondVar *cvar);
+
+/*
+** The thread that waits on a condition is blocked in a "waiting on
+** condition" state until another thread notifies the condition or a
+** caller specified amount of time expires. The lock associated with
+** the condition variable will be released, which must have be held
+** prior to the call to wait.
+**
+** Logically a notified thread is moved from the "waiting on condition"
+** state and made "ready." When scheduled, it will attempt to reacquire
+** the lock that it held when wait was called.
+**
+** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and
+** PR_INTERVAL_NO_WAIT. The former value requires that a condition be
+** notified (or the thread interrupted) before it will resume from the
+** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect
+** is to release the lock, possibly causing a rescheduling within the
+** runtime, then immediately attempting to reacquire the lock and resume.
+**
+** Any other value for timeout will cause the thread to be rescheduled
+** either due to explicit notification or an expired interval. The latter
+** must be determined by treating time as one part of the monitored data
+** being protected by the lock and tested explicitly for an expired
+** interval.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable or the thread was interrupted (PR_Interrupt()).
+** The particular reason can be extracted with PR_GetError().
+*/
+NSPR_API(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout);
+
+/*
+** Notify ONE thread that is currently waiting on 'cvar'. Which thread is
+** dependent on the implementation of the runtime. Common sense would dictate
+** that all threads waiting on a single condition have identical semantics,
+** therefore which one gets notified is not significant.
+**
+** The calling thead must hold the lock that protects the condition, as
+** well as the invariants that are tightly bound to the condition, when
+** notify is called.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+*/
+NSPR_API(PRStatus) PR_NotifyCondVar(PRCondVar *cvar);
+
+/*
+** Notify all of the threads waiting on the condition variable. The order
+** that the threads are notified is indeterminant. The lock that protects
+** the condition must be held.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+*/
+NSPR_API(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar);
+
+PR_END_EXTERN_C
+
+#endif /* prcvar_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prdtoa.h b/src/libs/xpcom18a4/nsprpub/pr/include/prdtoa.h
new file mode 100644
index 00000000..8e21d2b5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prdtoa.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prdtoa_h___
+#define prdtoa_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_cnvtf VBoxNsprPR_cnvtf
+#define PR_dtoa VBoxNsprPR_dtoa
+#define PR_strtod VBoxNsprPR_strtod
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** PR_strtod() returns as a double-precision floating-point number
+** the value represented by the character string pointed to by
+** s00. The string is scanned up to the first unrecognized
+** character.
+**a
+** If the value of se is not (char **)NULL, a pointer to
+** the character terminating the scan is returned in the location pointed
+** to by se. If no number can be formed, se is set to s00, and
+** zero is returned.
+*/
+#if defined(HAVE_WATCOM_BUG_1)
+/* this is a hack to circumvent a bug in the Watcom C/C++ 11.0 compiler
+** When Watcom fixes the bug, remove the special case for Win16
+*/
+PRFloat64 __pascal __loadds __export
+#else
+NSPR_API(PRFloat64)
+#endif
+PR_strtod(const char *s00, char **se);
+
+/*
+** PR_cnvtf()
+** conversion routines for floating point
+** prcsn - number of digits of precision to generate floating
+** point value.
+*/
+NSPR_API(void) PR_cnvtf(char *buf, PRIntn bufsz, PRIntn prcsn, PRFloat64 fval);
+
+/*
+** PR_dtoa() converts double to a string.
+**
+** ARGUMENTS:
+** If rve is not null, *rve is set to point to the end of the return value.
+** If d is +-Infinity or NaN, then *decpt is set to 9999.
+**
+** mode:
+** 0 ==> shortest string that yields d when read in
+** and rounded to nearest.
+*/
+NSPR_API(PRStatus) PR_dtoa(PRFloat64 d, PRIntn mode, PRIntn ndigits,
+ PRIntn *decpt, PRIntn *sign, char **rve, char *buf, PRSize bufsize);
+
+PR_END_EXTERN_C
+
+#endif /* prdtoa_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prenv.h b/src/libs/xpcom18a4/nsprpub/pr/include/prenv.h
new file mode 100644
index 00000000..581d5a51
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prenv.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prenv_h___
+#define prenv_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_GetEnv VBoxNsprPR_GetEnv
+#define PR_SetEnv VBoxNsprPR_SetEnv
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*******************************************************************************/
+/*******************************************************************************/
+/****************** THESE FUNCTIONS MAY NOT BE THREAD SAFE *********************/
+/*******************************************************************************/
+/*******************************************************************************/
+
+PR_BEGIN_EXTERN_C
+
+/*
+** PR_GetEnv() -- Retrieve value of environment variable
+**
+** Description:
+** PR_GetEnv() is modeled on Unix getenv().
+**
+**
+** Inputs:
+** var -- The name of the environment variable
+**
+** Returns:
+** The value of the environment variable 'var' or NULL if
+** the variable is undefined.
+**
+** Restrictions:
+** You'd think that a POSIX getenv(), putenv() would be
+** consistently implemented everywhere. Surprise! It is not. On
+** some platforms, a putenv() where the argument is of
+** the form "name" causes the named environment variable to
+** be un-set; that is: a subsequent getenv() returns NULL. On
+** other platforms, the putenv() fails, on others, it is a
+** no-op. Similarly, a putenv() where the argument is of the
+** form "name=" causes the named environment variable to be
+** un-set; a subsequent call to getenv() returns NULL. On
+** other platforms, a subsequent call to getenv() returns a
+** pointer to a null-string (a byte of zero).
+**
+** PR_GetEnv(), PR_SetEnv() provide a consistent behavior
+** across all supported platforms. There are, however, some
+** restrictions and some practices you must use to achieve
+** consistent results everywhere.
+**
+** When manipulating the environment there is no way to un-set
+** an environment variable across all platforms. We suggest
+** you interpret the return of a pointer to null-string to
+** mean the same as a return of NULL from PR_GetEnv().
+**
+** A call to PR_SetEnv() where the parameter is of the form
+** "name" will return PR_FAILURE; the environment remains
+** unchanged. A call to PR_SetEnv() where the parameter is
+** of the form "name=" may un-set the envrionment variable on
+** some platforms; on others it may set the value of the
+** environment variable to the null-string.
+**
+** For example, to test for NULL return or return of the
+** null-string from PR_GetEnv(), use the following code
+** fragment:
+**
+** char *val = PR_GetEnv("foo");
+** if ((NULL == val) || ('\0' == *val)) {
+** ... interpret this as un-set ...
+** }
+**
+** The caller must ensure that the string passed
+** to PR_SetEnv() is persistent. That is: The string should
+** not be on the stack, where it can be overwritten
+** on return from the function calling PR_SetEnv().
+** Similarly, the string passed to PR_SetEnv() must not be
+** overwritten by other actions of the process. ... Some
+** platforms use the string by reference rather than copying
+** it into the environment space. ... You have been warned!
+**
+** Use of platform-native functions that manipulate the
+** environment (getenv(), putenv(),
+** SetEnvironmentVariable(), etc.) must not be used with
+** NSPR's similar functions. The platform-native functions
+** may not be thread safe and/or may operate on different
+** conceptual environment space than that operated upon by
+** NSPR's functions or other environment manipulating
+** functions on the same platform. (!)
+**
+*/
+NSPR_API(char*) PR_GetEnv(const char *var);
+
+/*
+** PR_SetEnv() -- set, unset or change an environment variable
+**
+** Description:
+** PR_SetEnv() is modeled on the Unix putenv() function.
+**
+** Inputs:
+** string -- pointer to a caller supplied
+** constant, persistent string of the form name=value. Where
+** name is the name of the environment variable to be set or
+** changed; value is the value assigned to the variable.
+**
+** Returns:
+** PRStatus.
+**
+** Restrictions:
+** See the Restrictions documented in the description of
+** PR_GetEnv() in this header file.
+**
+**
+*/
+NSPR_API(PRStatus) PR_SetEnv(const char *string);
+
+/*
+** DEPRECATED. Use PR_SetEnv() instead.
+*/
+#ifdef XP_MAC
+NSPR_API(PRIntn) PR_PutEnv(const char *string);
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* prenv_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prerr.h b/src/libs/xpcom18a4/nsprpub/pr/include/prerr.h
new file mode 100644
index 00000000..79294847
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prerr.h
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prerr_h___
+#define prerr_h___
+
+/*
+ *
+ * prerr.h
+ * This file is automatically generated; please do not edit it.
+ */
+
+/* Memory allocation attempt failed */
+#define PR_OUT_OF_MEMORY_ERROR (-6000L)
+
+/* Invalid file descriptor */
+#define PR_BAD_DESCRIPTOR_ERROR (-5999L)
+
+/* The operation would have blocked */
+#define PR_WOULD_BLOCK_ERROR (-5998L)
+
+/* Invalid memory address argument */
+#define PR_ACCESS_FAULT_ERROR (-5997L)
+
+/* Invalid function for file type */
+#define PR_INVALID_METHOD_ERROR (-5996L)
+
+/* Invalid memory address argument */
+#define PR_ILLEGAL_ACCESS_ERROR (-5995L)
+
+/* Some unknown error has occurred */
+#define PR_UNKNOWN_ERROR (-5994L)
+
+/* Operation interrupted by another thread */
+#define PR_PENDING_INTERRUPT_ERROR (-5993L)
+
+/* function not implemented */
+#define PR_NOT_IMPLEMENTED_ERROR (-5992L)
+
+/* I/O function error */
+#define PR_IO_ERROR (-5991L)
+
+/* I/O operation timed out */
+#define PR_IO_TIMEOUT_ERROR (-5990L)
+
+/* I/O operation on busy file descriptor */
+#define PR_IO_PENDING_ERROR (-5989L)
+
+/* The directory could not be opened */
+#define PR_DIRECTORY_OPEN_ERROR (-5988L)
+
+/* Invalid function argument */
+#define PR_INVALID_ARGUMENT_ERROR (-5987L)
+
+/* Network address not available (in use?) */
+#define PR_ADDRESS_NOT_AVAILABLE_ERROR (-5986L)
+
+/* Network address type not supported */
+#define PR_ADDRESS_NOT_SUPPORTED_ERROR (-5985L)
+
+/* Already connected */
+#define PR_IS_CONNECTED_ERROR (-5984L)
+
+/* Network address is invalid */
+#define PR_BAD_ADDRESS_ERROR (-5983L)
+
+/* Local Network address is in use */
+#define PR_ADDRESS_IN_USE_ERROR (-5982L)
+
+/* Connection refused by peer */
+#define PR_CONNECT_REFUSED_ERROR (-5981L)
+
+/* Network address is presently unreachable */
+#define PR_NETWORK_UNREACHABLE_ERROR (-5980L)
+
+/* Connection attempt timed out */
+#define PR_CONNECT_TIMEOUT_ERROR (-5979L)
+
+/* Network file descriptor is not connected */
+#define PR_NOT_CONNECTED_ERROR (-5978L)
+
+/* Failure to load dynamic library */
+#define PR_LOAD_LIBRARY_ERROR (-5977L)
+
+/* Failure to unload dynamic library */
+#define PR_UNLOAD_LIBRARY_ERROR (-5976L)
+
+/* Symbol not found in any of the loaded dynamic libraries */
+#define PR_FIND_SYMBOL_ERROR (-5975L)
+
+/* Insufficient system resources */
+#define PR_INSUFFICIENT_RESOURCES_ERROR (-5974L)
+
+/* A directory lookup on a network address has failed */
+#define PR_DIRECTORY_LOOKUP_ERROR (-5973L)
+
+/* Attempt to access a TPD key that is out of range */
+#define PR_TPD_RANGE_ERROR (-5972L)
+
+/* Process open FD table is full */
+#define PR_PROC_DESC_TABLE_FULL_ERROR (-5971L)
+
+/* System open FD table is full */
+#define PR_SYS_DESC_TABLE_FULL_ERROR (-5970L)
+
+/* Network operation attempted on non-network file descriptor */
+#define PR_NOT_SOCKET_ERROR (-5969L)
+
+/* TCP-specific function attempted on a non-TCP file descriptor */
+#define PR_NOT_TCP_SOCKET_ERROR (-5968L)
+
+/* TCP file descriptor is already bound */
+#define PR_SOCKET_ADDRESS_IS_BOUND_ERROR (-5967L)
+
+/* Access Denied */
+#define PR_NO_ACCESS_RIGHTS_ERROR (-5966L)
+
+/* The requested operation is not supported by the platform */
+#define PR_OPERATION_NOT_SUPPORTED_ERROR (-5965L)
+
+/* The host operating system does not support the protocol requested */
+#define PR_PROTOCOL_NOT_SUPPORTED_ERROR (-5964L)
+
+/* Access to the remote file has been severed */
+#define PR_REMOTE_FILE_ERROR (-5963L)
+
+/* The value requested is too large to be stored in the data buffer provided */
+#define PR_BUFFER_OVERFLOW_ERROR (-5962L)
+
+/* TCP connection reset by peer */
+#define PR_CONNECT_RESET_ERROR (-5961L)
+
+/* Unused */
+#define PR_RANGE_ERROR (-5960L)
+
+/* The operation would have deadlocked */
+#define PR_DEADLOCK_ERROR (-5959L)
+
+/* The file is already locked */
+#define PR_FILE_IS_LOCKED_ERROR (-5958L)
+
+/* Write would result in file larger than the system allows */
+#define PR_FILE_TOO_BIG_ERROR (-5957L)
+
+/* The device for storing the file is full */
+#define PR_NO_DEVICE_SPACE_ERROR (-5956L)
+
+/* Unused */
+#define PR_PIPE_ERROR (-5955L)
+
+/* Unused */
+#define PR_NO_SEEK_DEVICE_ERROR (-5954L)
+
+/* Cannot perform a normal file operation on a directory */
+#define PR_IS_DIRECTORY_ERROR (-5953L)
+
+/* Symbolic link loop */
+#define PR_LOOP_ERROR (-5952L)
+
+/* File name is too long */
+#define PR_NAME_TOO_LONG_ERROR (-5951L)
+
+/* File not found */
+#define PR_FILE_NOT_FOUND_ERROR (-5950L)
+
+/* Cannot perform directory operation on a normal file */
+#define PR_NOT_DIRECTORY_ERROR (-5949L)
+
+/* Cannot write to a read-only file system */
+#define PR_READ_ONLY_FILESYSTEM_ERROR (-5948L)
+
+/* Cannot delete a directory that is not empty */
+#define PR_DIRECTORY_NOT_EMPTY_ERROR (-5947L)
+
+/* Cannot delete or rename a file object while the file system is busy */
+#define PR_FILESYSTEM_MOUNTED_ERROR (-5946L)
+
+/* Cannot rename a file to a file system on another device */
+#define PR_NOT_SAME_DEVICE_ERROR (-5945L)
+
+/* The directory object in the file system is corrupted */
+#define PR_DIRECTORY_CORRUPTED_ERROR (-5944L)
+
+/* Cannot create or rename a filename that already exists */
+#define PR_FILE_EXISTS_ERROR (-5943L)
+
+/* Directory is full. No additional filenames may be added */
+#define PR_MAX_DIRECTORY_ENTRIES_ERROR (-5942L)
+
+/* The required device was in an invalid state */
+#define PR_INVALID_DEVICE_STATE_ERROR (-5941L)
+
+/* The device is locked */
+#define PR_DEVICE_IS_LOCKED_ERROR (-5940L)
+
+/* No more entries in the directory */
+#define PR_NO_MORE_FILES_ERROR (-5939L)
+
+/* Encountered end of file */
+#define PR_END_OF_FILE_ERROR (-5938L)
+
+/* Seek error */
+#define PR_FILE_SEEK_ERROR (-5937L)
+
+/* The file is busy */
+#define PR_FILE_IS_BUSY_ERROR (-5936L)
+
+/* The I/O operation was aborted */
+#define PR_OPERATION_ABORTED_ERROR (-5935L)
+
+/* Operation is still in progress (probably a non-blocking connect) */
+#define PR_IN_PROGRESS_ERROR (-5934L)
+
+/* Operation has already been initiated (probably a non-blocking connect) */
+#define PR_ALREADY_INITIATED_ERROR (-5933L)
+
+/* The wait group is empty */
+#define PR_GROUP_EMPTY_ERROR (-5932L)
+
+/* Object state improper for request */
+#define PR_INVALID_STATE_ERROR (-5931L)
+
+/* Network is down */
+#define PR_NETWORK_DOWN_ERROR (-5930L)
+
+/* Socket shutdown */
+#define PR_SOCKET_SHUTDOWN_ERROR (-5929L)
+
+/* Connection aborted */
+#define PR_CONNECT_ABORTED_ERROR (-5928L)
+
+/* Host is unreachable */
+#define PR_HOST_UNREACHABLE_ERROR (-5927L)
+
+/* The library is not loaded */
+#define PR_LIBRARY_NOT_LOADED_ERROR (-5926L)
+
+/* Placeholder for the end of the list */
+#define PR_MAX_ERROR (-5925L)
+
+extern void nspr_InitializePRErrorTable(void);
+#define ERROR_TABLE_BASE_nspr (-6000L)
+
+#endif /* prerr_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prerror.h b/src/libs/xpcom18a4/nsprpub/pr/include/prerror.h
new file mode 100644
index 00000000..29e69dde
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prerror.h
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prerror_h___
+#define prerror_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_SetError VBoxNsprPR_SetError
+#define PR_SetErrorText VBoxNsprPR_SetErrorText
+#define PR_GetError VBoxNsprPR_GetError
+#define PR_GetOSError VBoxNsprPR_GetOSError
+#define PR_GetErrorTextLength VBoxNsprPR_GetErrorTextLength
+#define PR_GetErrorText VBoxNsprPR_GetErrorText
+#define PR_ErrorToString VBoxNsprPR_ErrorToString
+#define PR_ErrorToName VBoxNsprPR_ErrorToName
+#define PR_ErrorLanguages VBoxNsprPR_ErrorLanguages
+#define PR_ErrorInstallTable VBoxNsprPR_ErrorInstallTable
+#define PR_ErrorInstallCallback VBoxNsprPR_ErrorInstallCallback
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PR_BEGIN_EXTERN_C
+
+typedef PRInt32 PRErrorCode;
+
+#define PR_NSPR_ERROR_BASE -6000
+
+#include "prerr.h"
+
+/*
+** Set error will preserve an error condition within a thread context.
+** The values stored are the NSPR (platform independent) translation of
+** the error. Also, if available, the platform specific oserror is stored.
+** If there is no appropriate OS error number, a zero my be supplied.
+*/
+NSPR_API(void) PR_SetError(PRErrorCode errorCode, PRInt32 oserr);
+
+/*
+** The text value specified may be NULL. If it is not NULL and the text length
+** is zero, the string is assumed to be a null terminated C string. Otherwise
+** the text is assumed to be the length specified and possibly include NULL
+** characters (e.g., a multi-national string).
+**
+** The text will be copied into to thread structure and remain there
+** until the next call to PR_SetError.
+*/
+NSPR_API(void) PR_SetErrorText(
+ PRIntn textLength, const char *text);
+
+/*
+** Return the current threads last set error code.
+*/
+NSPR_API(PRErrorCode) PR_GetError(void);
+
+/*
+** Return the current threads last set os error code. This is used for
+** machine specific code that desires the underlying os error.
+*/
+NSPR_API(PRInt32) PR_GetOSError(void);
+
+/*
+** Get the length of the error text. If a zero is returned, then there
+** is no text. Otherwise, the value returned is sufficient to contain
+** the error text currently available.
+*/
+NSPR_API(PRInt32) PR_GetErrorTextLength(void);
+
+/*
+** Copy the current threads current error text. Then actual number of bytes
+** copied is returned as the result. If the result is zero, the 'text' area
+** is unaffected.
+*/
+NSPR_API(PRInt32) PR_GetErrorText(char *text);
+
+
+/*
+Copyright (C) 1987, 1988 Student Information Processing Board of the
+Massachusetts Institute of Technology.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
+make no representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+*/
+
+
+/*
+ * NOTE:
+ * The interfaces for error-code-translation described in the rest of
+ * this file are preliminary in the 3.1 release of nspr and are subject
+ * to change in future releases.
+ */
+
+/*
+** Description: Localizable error code to string function.
+**
+**
+** NSPR provides a mechanism for converting an error code to a
+** descriptive string, in a caller-specified language.
+**
+** Error codes themselves are 32 bit (signed) integers. Typically,
+** the high order 24 bits are an identifier of which error table the
+** error code is from, and the low order 8 bits are a sequential error
+** number within the table. NSPR supports error tables whose first
+** error code is not a multiple of 256, such error code assignments
+** should be avoided when possible.
+**
+** Error table 0 is defined to match the UNIX system call error table
+** (sys_errlist); this allows errno values to be used directly in the
+** library. Other error table numbers are typically formed by
+** compacting together the first four characters of the error table
+** name. The mapping between characters in the name and numeric
+** values in the error code are defined in a system-independent
+** fashion, so that two systems that can pass integral values between
+** them can reliably pass error codes without loss of meaning; this
+** should work even if the character sets used are not the
+** same. (However, if this is to be done, error table 0 should be
+** avoided, since the local system call error tables may differ.)
+**
+** Libraries defining error codes need only provide a table mapping
+** error code numbers to names and default English descriptions,
+** calling a routine to install the table, making it ``known'' to NSPR
+** library. Once installed, a table may not be removed. Any error
+** code the library generates can be converted to the corresponding
+** error message. There is also a default format for error codes
+** accidentally returned before making the table known, which is of
+** the form "unknown code foo 32", where "foo" would be the name of
+** the table.
+**
+** Normally, the error code conversion routine only supports the
+** languages "i-default" and "en", returning the error-table-provided
+** English description for both languages. The application may
+** provide a localization plugin, allowing support for additional
+** languages.
+**
+**/
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+/*
+ * PRLanguageCode --
+ *
+ * NSPR represents a language code as a non-negative integer.
+ * Languages 0 is always "i-default" the language you get without
+ * explicit negotiation. Language 1 is always "en", English
+ * which has been explicitly negotiated. Additional language
+ * codes are defined by an application-provided localization plugin.
+ */
+typedef PRUint32 PRLanguageCode;
+#define PR_LANGUAGE_I_DEFAULT 0 /* i-default, the default language */
+#define PR_LANGUAGE_EN 1 /* English, explicitly negotiated */
+
+/*
+ * struct PRErrorMessage --
+ *
+ * An error message in an error table.
+ */
+struct PRErrorMessage {
+ const char * name; /* Macro name for error */
+ const char * en_text; /* Default English text */
+};
+
+/*
+ * struct PRErrorTable --
+ *
+ * An error table, provided by a library.
+ */
+struct PRErrorTable {
+ const struct PRErrorMessage * msgs; /* Array of error information */
+ const char *name; /* Name of error table source */
+ PRErrorCode base; /* Error code for first error in table */
+ int n_msgs; /* Number of codes in table */
+};
+
+/*
+ * struct PRErrorCallbackPrivate --
+ *
+ * A private structure for the localization plugin
+ */
+struct PRErrorCallbackPrivate;
+
+/*
+ * struct PRErrorCallbackTablePrivate --
+ *
+ * A data structure under which the localization plugin may store information,
+ * associated with an error table, that is private to itself.
+ */
+struct PRErrorCallbackTablePrivate;
+
+/*
+ * PRErrorCallbackLookupFn --
+ *
+ * A function of PRErrorCallbackLookupFn type is a localization
+ * plugin callback which converts an error code into a description
+ * in the requested language. The callback is provided the
+ * appropriate error table, private data for the plugin and the table.
+ * The callback returns the appropriate UTF-8 encoded description, or NULL
+ * if no description can be found.
+ */
+typedef const char *
+PRErrorCallbackLookupFn(PRErrorCode code, PRLanguageCode language,
+ const struct PRErrorTable *table,
+ struct PRErrorCallbackPrivate *cb_private,
+ struct PRErrorCallbackTablePrivate *table_private);
+
+/*
+ * PRErrorCallbackNewTableFn --
+ *
+ * A function PRErrorCallbackNewTableFn type is a localization plugin
+ * callback which is called once with each error table registered
+ * with NSPR. The callback is provided with the error table and
+ * the plugin's private structure. The callback returns any table private
+ * data it wishes to associate with the error table. Does not need to be thread
+ * safe.
+ */
+typedef struct PRErrorCallbackTablePrivate *
+PRErrorCallbackNewTableFn(const struct PRErrorTable *table,
+ struct PRErrorCallbackPrivate *cb_private);
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION: PR_ErrorToString
+** DESCRIPTION:
+** Returns the UTF-8 message for an error code in
+** the requested language. May return the message
+** in the default language if a translation in the requested
+** language is not available. The returned string is
+** valid for the duration of the process. Never returns NULL.
+**
+***********************************************************************/
+NSPR_API(const char *) PR_ErrorToString(PRErrorCode code,
+ PRLanguageCode language);
+
+
+/***********************************************************************
+** FUNCTION: PR_ErrorToName
+** DESCRIPTION:
+** Returns the macro name for an error code, or NULL
+** if the error code is not known. The returned string is
+** valid for the duration of the process.
+**
+** Does not work for error table 0, the system error codes.
+**
+***********************************************************************/
+NSPR_API(const char *) PR_ErrorToName(PRErrorCode code);
+
+
+/***********************************************************************
+** FUNCTION: PR_ErrorLanguages
+** DESCRIPTION:
+** Returns the RFC 1766 language tags for the language
+** codes PR_ErrorToString() supports. The returned array is valid
+** for the duration of the process. Never returns NULL. The first
+** item in the returned array is the language tag for PRLanguageCode 0,
+** the second is for PRLanguageCode 1, and so on. The array is terminated
+** with a null pointer.
+**
+***********************************************************************/
+NSPR_API(const char * const *) PR_ErrorLanguages(void);
+
+
+/***********************************************************************
+** FUNCTION: PR_ErrorInstallTable
+** DESCRIPTION:
+** Registers an error table with NSPR. Must be done exactly once per
+** table. Memory pointed to by `table' must remain valid for the life
+** of the process.
+**
+** NOT THREAD SAFE!
+**
+***********************************************************************/
+NSPR_API(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table);
+
+
+/***********************************************************************
+** FUNCTION: PR_ErrorInstallCallback
+** DESCRIPTION:
+** Registers an error localization plugin with NSPR. May be called
+** at most one time. `languages' contains the language codes supported
+** by this plugin. Languages 0 and 1 must be "i-default" and "en"
+** respectively. `lookup' and `newtable' contain pointers to
+** the plugin callback functions. `cb_private' contains any information
+** private to the plugin functions.
+**
+** NOT THREAD SAFE!
+**
+***********************************************************************/
+NSPR_API(void) PR_ErrorInstallCallback(const char * const * languages,
+ PRErrorCallbackLookupFn *lookup,
+ PRErrorCallbackNewTableFn *newtable,
+ struct PRErrorCallbackPrivate *cb_private);
+
+PR_END_EXTERN_C
+
+#endif /* prerror_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prinet.h b/src/libs/xpcom18a4/nsprpub/pr/include/prinet.h
new file mode 100644
index 00000000..2c733b0b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prinet.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: prinet.h
+ * Description:
+ * Header file used to find the system header files for socket support.
+ * This file serves the following purposes:
+ * - A cross-platform, "get-everything" socket header file. On
+ * Unix, socket support is scattered in several header files,
+ * while Windows and Mac have a "get-everything" socket header
+ * file.
+ * - NSPR needs the following macro definitions and function
+ * prototype declarations from these header files:
+ * AF_INET
+ * INADDR_ANY, INADDR_LOOPBACK, INADDR_BROADCAST
+ * ntohl(), ntohs(), htonl(), ntons().
+ * NSPR does not define its own versions of these macros and
+ * functions. It simply uses the native versions, which have
+ * the same names on all supported platforms.
+ * This file is intended to be included by nspr20 public header
+ * files, such as prio.h. One should not include this file directly.
+ */
+
+#ifndef prinet_h__
+#define prinet_h__
+
+#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+#ifdef LINUX
+#undef __STRICT_ANSI__
+#define __STRICT_ANSI__
+#endif
+#include <sys/types.h>
+#include <sys/socket.h> /* AF_INET */
+#include <netinet/in.h> /* INADDR_ANY, ..., ntohl(), ... */
+#ifdef XP_OS2
+#include <sys/ioctl.h>
+#endif
+#ifdef XP_UNIX
+#ifdef AIX
+/*
+ * On AIX 4.3, the header <arpa/inet.h> refers to struct
+ * ether_addr and struct sockaddr_dl that are not declared.
+ * The following struct declarations eliminate the compiler
+ * warnings.
+ */
+struct ether_addr;
+struct sockaddr_dl;
+#endif /* AIX */
+#include <arpa/inet.h>
+#endif /* XP_UNIX */
+#include <netdb.h>
+
+#if defined(FREEBSD) || defined(BSDI) || defined(QNX)
+#include <rpc/types.h> /* the only place that defines INADDR_LOOPBACK */
+#endif
+
+/*
+ * OS/2 hack. For some reason INADDR_LOOPBACK is not defined in the
+ * socket headers.
+ */
+#if defined(OS2) && !defined(INADDR_LOOPBACK)
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+/*
+ * Prototypes of ntohl() etc. are declared in <machine/endian.h>
+ * on these platforms.
+ */
+#if defined(BSDI) || defined(OSF1)
+#include <machine/endian.h>
+#endif
+
+#elif defined(WIN32)
+
+/* Do not include any system header files. */
+
+#elif defined(WIN16)
+
+#include <winsock.h>
+
+#elif defined(XP_MAC)
+
+#include "macsocket.h"
+
+#else
+
+#error Unknown platform
+
+#endif
+
+#endif /* prinet_h__ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prinit.h b/src/libs/xpcom18a4/nsprpub/pr/include/prinit.h
new file mode 100644
index 00000000..1f6718ba
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prinit.h
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prinit_h___
+#define prinit_h___
+
+#include "prthread.h"
+#include "prtypes.h"
+#include "prwin16.h"
+#include <stdio.h>
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_Abort VBoxNsprPR_Abort
+#define PR_Cleanup VBoxNsprPR_Cleanup
+#define PR_DisableClockInterrupts VBoxNsprPR_DisableClockInterrupts
+#define PR_EnableClockInterrupts VBoxNsprPR_EnableClockInterrupts
+#define PR_BlockClockInterrupts VBoxNsprPR_BlockClockInterrupts
+#define PR_UnblockClockInterrupts VBoxNsprPR_UnblockClockInterrupts
+#define PR_Init VBoxNsprPR_Init
+#define PR_Initialize VBoxNsprPR_Initialize
+#define PR_Initialized VBoxNsprPR_Initialized
+#define PR_VersionCheck VBoxNsprPR_VersionCheck
+#define PR_SetConcurrency VBoxNsprPR_SetConcurrency
+#define PR_SetFDCacheSize VBoxNsprPR_SetFDCacheSize
+#define PR_ProcessExit VBoxNsprPR_ProcessExit
+#define PR_CallOnce VBoxNsprPR_CallOnce
+#define PR_CallOnceWithArg VBoxNsprPR_CallOnceWithArg
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+
+/*
+** NSPR's name, this should persist until at least the turn of the
+** century.
+*/
+#define PR_NAME "NSPR"
+
+/*
+** NSPR's version is used to determine the likelihood that the version you
+** used to build your component is anywhere close to being compatible with
+** what is in the underlying library.
+**
+** The format of the version string is
+** "<major version>.<minor version>[.<patch level>] [<Beta>]"
+*/
+#define PR_VERSION "4.6 Beta"
+#define PR_VMAJOR 4
+#define PR_VMINOR 6
+#define PR_VPATCH 0
+#define PR_BETA PR_TRUE
+
+/*
+** PRVersionCheck
+**
+** The basic signature of the function that is called to provide version
+** checking. The result will be a boolean that indicates the likelihood
+** that the underling library will perform as the caller expects.
+**
+** The only argument is a string, which should be the verson identifier
+** of the library in question. That string will be compared against an
+** equivalent string that represents the actual build version of the
+** exporting library.
+**
+** The result will be the logical union of the directly called library
+** and all dependent libraries.
+*/
+
+typedef PRBool (*PRVersionCheck)(const char*);
+
+/*
+** PR_VersionCheck
+**
+** NSPR's existance proof of the version check function.
+**
+** Note that NSPR has no cooperating dependencies.
+*/
+
+NSPR_API(PRBool) PR_VersionCheck(const char *importedVersion);
+
+
+/************************************************************************/
+/*******************************INITIALIZATION***************************/
+/************************************************************************/
+
+/*
+** Initialize the runtime. Attach a thread object to the currently
+** executing native thread of type "type".
+**
+** The specificaiton of 'maxPTDs' is ignored.
+*/
+NSPR_API(void) PR_Init(
+ PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs);
+
+/*
+** And alternate form of initialization, one that may become the default if
+** not the only mechanism, provides a method to get the NSPR runtime init-
+** ialized and place NSPR between the caller and the runtime library. This
+** allows main() to be treated as any other thread root function, signalling
+** its compeletion by returning and allowing the runtime to coordinate the
+** completion of the other threads of the runtime.
+**
+** The priority of the main (or primordial) thread will be PR_PRIORITY_NORMAL.
+** The thread may adjust its own priority by using PR_SetPriority(), though
+** at this time the support for priorities is somewhat weak.
+**
+** The specificaiton of 'maxPTDs' is ignored.
+**
+** The value returned by PR_Initialize is the value returned from the root
+** function, 'prmain'.
+*/
+
+typedef PRIntn (PR_CALLBACK *PRPrimordialFn)(PRIntn argc, char **argv);
+
+NSPR_API(PRIntn) PR_Initialize(
+ PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs);
+
+/*
+** Return PR_TRUE if PR_Init has already been called.
+*/
+NSPR_API(PRBool) PR_Initialized(void);
+
+/*
+ * Perform a graceful shutdown of NSPR. PR_Cleanup() may be called by
+ * the primordial thread near the end of the main() function.
+ *
+ * PR_Cleanup() attempts to synchronize the natural termination of
+ * process. It does that by blocking the caller, if and only if it is
+ * the primordial thread, until the number of user threads has dropped
+ * to zero. When the primordial thread returns from main(), the process
+ * will immediately and silently exit. That is, it will (if necessary)
+ * forcibly terminate any existing threads and exit without significant
+ * blocking and there will be no error messages or core files.
+ *
+ * PR_Cleanup() returns PR_SUCCESS if NSPR is successfully shutdown,
+ * or PR_FAILURE if the calling thread of this function is not the
+ * primordial thread.
+ */
+NSPR_API(PRStatus) PR_Cleanup(void);
+
+/*
+** Disable Interrupts
+** Disables timer signals used for pre-emptive scheduling.
+*/
+NSPR_API(void) PR_DisableClockInterrupts(void);
+
+/*
+** Enables Interrupts
+** Enables timer signals used for pre-emptive scheduling.
+*/
+NSPR_API(void) PR_EnableClockInterrupts(void);
+
+/*
+** Block Interrupts
+** Blocks the timer signal used for pre-emptive scheduling
+*/
+NSPR_API(void) PR_BlockClockInterrupts(void);
+
+/*
+** Unblock Interrupts
+** Unblocks the timer signal used for pre-emptive scheduling
+*/
+NSPR_API(void) PR_UnblockClockInterrupts(void);
+
+/*
+** Create extra virtual processor threads. Generally used with MP systems.
+*/
+NSPR_API(void) PR_SetConcurrency(PRUintn numCPUs);
+
+/*
+** Control the method and size of the file descriptor (PRFileDesc*)
+** cache used by the runtime. Setting 'high' to zero is for performance,
+** any other value probably for debugging (see memo on FD caching).
+*/
+NSPR_API(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high);
+
+/*
+ * Cause an immediate, nongraceful, forced termination of the process.
+ * It takes a PRIntn argument, which is the exit status code of the
+ * process.
+ */
+NSPR_API(void) PR_ProcessExit(PRIntn status);
+
+/*
+** Abort the process in a non-graceful manner. This will cause a core file,
+** call to the debugger or other moral equivalent as well as causing the
+** entire process to stop.
+*/
+NSPR_API(void) PR_Abort(void);
+
+/*
+ ****************************************************************
+ *
+ * Module initialization:
+ *
+ ****************************************************************
+ */
+
+typedef struct PRCallOnceType {
+ PRIntn initialized;
+ PRInt32 inProgress;
+ PRStatus status;
+} PRCallOnceType;
+
+typedef PRStatus (PR_CALLBACK *PRCallOnceFN)(void);
+
+typedef PRStatus (PR_CALLBACK *PRCallOnceWithArgFN)(void *arg);
+
+NSPR_API(PRStatus) PR_CallOnce(
+ PRCallOnceType *once,
+ PRCallOnceFN func
+);
+
+NSPR_API(PRStatus) PR_CallOnceWithArg(
+ PRCallOnceType *once,
+ PRCallOnceWithArgFN func,
+ void *arg
+);
+
+
+PR_END_EXTERN_C
+
+#endif /* prinit_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prinrval.h b/src/libs/xpcom18a4/nsprpub/pr/include/prinrval.h
new file mode 100644
index 00000000..83efdfa7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prinrval.h
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prinrval.h
+** Description: API to interval timing functions of NSPR.
+**
+**
+** NSPR provides interval times that are independent of network time
+** of day values. Interval times are (in theory) accurate regardless
+** of host processing requirements and also very cheap to acquire. It
+** is expected that getting an interval time while in a synchronized
+** function (holding one's lock).
+**/
+
+#if !defined(prinrval_h)
+#define prinrval_h
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_IntervalNow VBoxNsprPR_IntervalNow
+#define PR_TicksPerSecond VBoxNsprPR_TicksPerSecond
+#define PR_SecondsToInterval VBoxNsprPR_SecondsToInterval
+#define PR_MillisecondsToInterval VBoxNsprPR_MillisecondsToInterval
+#define PR_MicrosecondsToInterval VBoxNsprPR_MicrosecondsToInterval
+#define PR_IntervalToSeconds VBoxNsprPR_IntervalToSeconds
+#define PR_IntervalToMilliseconds VBoxNsprPR_IntervalToMilliseconds
+#define PR_IntervalToMicroseconds VBoxNsprPR_IntervalToMicroseconds
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+typedef PRUint32 PRIntervalTime;
+
+/***********************************************************************
+** DEFINES: PR_INTERVAL_MIN
+** PR_INTERVAL_MAX
+** DESCRIPTION:
+** These two constants define the range (in ticks / second) of the
+** platform dependent type, PRIntervalTime. These constants bound both
+** the period and the resolution of a PRIntervalTime.
+***********************************************************************/
+#define PR_INTERVAL_MIN 1000UL
+#define PR_INTERVAL_MAX 100000UL
+
+/***********************************************************************
+** DEFINES: PR_INTERVAL_NO_WAIT
+** PR_INTERVAL_NO_TIMEOUT
+** DESCRIPTION:
+** Two reserved constants are defined in the PRIntervalTime namespace.
+** They are used to indicate that the process should wait no time (return
+** immediately) or wait forever (never time out), respectively.
+***********************************************************************/
+#define PR_INTERVAL_NO_WAIT 0UL
+#define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION: PR_IntervalNow
+** DESCRIPTION:
+** Return the value of NSPR's free running interval timer. That timer
+** can be used to establish epochs and determine intervals (be computing
+** the difference between two times).
+** INPUTS: void
+** OUTPUTS: void
+** RETURN: PRIntervalTime
+**
+** SIDE EFFECTS:
+** None
+** RESTRICTIONS:
+** The units of PRIntervalTime are platform dependent. They are chosen
+** such that they are appropriate for the host OS, yet provide sufficient
+** resolution and period to be useful to clients.
+** MEMORY: N/A
+** ALGORITHM: Platform dependent
+***********************************************************************/
+NSPR_API(PRIntervalTime) PR_IntervalNow(void);
+
+/***********************************************************************
+** FUNCTION: PR_TicksPerSecond
+** DESCRIPTION:
+** Return the number of ticks per second for PR_IntervalNow's clock.
+** The value will be in the range [PR_INTERVAL_MIN..PR_INTERVAL_MAX].
+** INPUTS: void
+** OUTPUTS: void
+** RETURN: PRUint32
+**
+** SIDE EFFECTS:
+** None
+** RESTRICTIONS:
+** None
+** MEMORY: N/A
+** ALGORITHM: N/A
+***********************************************************************/
+NSPR_API(PRUint32) PR_TicksPerSecond(void);
+
+/***********************************************************************
+** FUNCTION: PR_SecondsToInterval
+** PR_MillisecondsToInterval
+** PR_MicrosecondsToInterval
+** DESCRIPTION:
+** Convert standard clock units to platform dependent intervals.
+** INPUTS: PRUint32
+** OUTPUTS: void
+** RETURN: PRIntervalTime
+**
+** SIDE EFFECTS:
+** None
+** RESTRICTIONS:
+** Conversion may cause overflow, which is not reported.
+** MEMORY: N/A
+** ALGORITHM: N/A
+***********************************************************************/
+NSPR_API(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds);
+NSPR_API(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli);
+NSPR_API(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro);
+
+/***********************************************************************
+** FUNCTION: PR_IntervalToSeconds
+** PR_IntervalToMilliseconds
+** PR_IntervalToMicroseconds
+** DESCRIPTION:
+** Convert platform dependent intervals to standard clock units.
+** INPUTS: PRIntervalTime
+** OUTPUTS: void
+** RETURN: PRUint32
+**
+** SIDE EFFECTS:
+** None
+** RESTRICTIONS:
+** Conversion may cause overflow, which is not reported.
+** MEMORY: N/A
+** ALGORITHM: N/A
+***********************************************************************/
+NSPR_API(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks);
+NSPR_API(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks);
+NSPR_API(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks);
+
+PR_END_EXTERN_C
+
+
+#endif /* !defined(prinrval_h) */
+
+/* prinrval.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prio.h b/src/libs/xpcom18a4/nsprpub/pr/include/prio.h
new file mode 100644
index 00000000..908a88d3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prio.h
@@ -0,0 +1,2107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: prio.h
+ *
+ * Description: PR i/o related stuff, such as file system access, file
+ * i/o, socket i/o, etc.
+ */
+
+#ifndef prio_h___
+#define prio_h___
+
+#include "prlong.h"
+#include "prtime.h"
+#include "prinrval.h"
+#include "prinet.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_GetInheritedFD VBoxNsprPR_GetInheritedFD
+#define PR_SetFDInheritable VBoxNsprPR_SetFDInheritable
+#define PR_Access VBoxNsprPR_Access
+#define PR_Open VBoxNsprPR_Open
+#define PR_Read VBoxNsprPR_Read
+#define PR_Write VBoxNsprPR_Write
+#define PR_Seek VBoxNsprPR_Seek
+#define PR_Seek64 VBoxNsprPR_Seek64
+#define PR_Poll VBoxNsprPR_Poll
+#define PR_NewPollableEvent VBoxNsprPR_NewPollableEvent
+#define PR_SetPollableEvent VBoxNsprPR_SetPollableEvent
+#define PR_WaitForPollableEvent VBoxNsprPR_WaitForPollableEvent
+#define PR_DestroyPollableEvent VBoxNsprPR_DestroyPollableEvent
+#define PR_Close VBoxNsprPR_Close
+#define PR_GetSpecialFD VBoxNsprPR_GetSpecialFD
+#define PR_Connect VBoxNsprPR_Connect
+#define PR_OpenTCPSocket VBoxNsprPR_OpenTCPSocket
+#define PR_SetSocketOption VBoxNsprPR_SetSocketOption
+#define PR_Bind VBoxNsprPR_Bind
+#define PR_Listen VBoxNsprPR_Listen
+#define PR_Accept VBoxNsprPR_Accept
+#define PR_AcceptRead VBoxNsprPR_AcceptRead
+#define PR_OpenDir VBoxNsprPR_OpenDir
+#define PR_ReadDir VBoxNsprPR_ReadDir
+#define PR_CloseDir VBoxNsprPR_CloseDir
+#define PR_CreatePipe VBoxNsprPR_CreatePipe
+#define PR_GetDescType VBoxNsprPR_GetDescType
+#define PR_GetSpecialFD VBoxNsprPR_GetSpecialFD
+#define PR_GetUniqueIdentity VBoxNsprPR_GetUniqueIdentity
+#define PR_GetNameForIdentity VBoxNsprPR_GetNameForIdentity
+#define PR_GetLayersIdentity VBoxNsprPR_GetLayersIdentity
+#define PR_GetIdentitiesLayer VBoxNsprPR_GetIdentitiesLayer
+#define PR_GetDefaultIOMethods VBoxNsprPR_GetDefaultIOMethods
+#define PR_CreateIOLayerStub VBoxNsprPR_CreateIOLayerStub
+#define PR_CreateIOLayer VBoxNsprPR_CreateIOLayer
+#define PR_PushIOLayer VBoxNsprPR_PushIOLayer
+#define PR_PopIOLayer VBoxNsprPR_PopIOLayer
+#define PR_OpenFile VBoxNsprPR_OpenFile
+#define PR_Writev VBoxNsprPR_Writev
+#define PR_Delete VBoxNsprPR_Delete
+#define PR_Rename VBoxNsprPR_Rename
+#define PR_GetFileInfo VBoxNsprPR_GetFileInfo
+#define PR_GetFileInfo64 VBoxNsprPR_GetFileInfo64
+#define PR_GetOpenFileInfo VBoxNsprPR_GetOpenFileInfo
+#define PR_GetOpenFileInfo64 VBoxNsprPR_GetOpenFileInfo64
+#define PR_Available VBoxNsprPR_Available
+#define PR_Available64 VBoxNsprPR_Available64
+#define PR_Sync VBoxNsprPR_Sync
+#define PR_MkDir VBoxNsprPR_MkDir
+#define PR_MakeDir VBoxNsprPR_MakeDir
+#define PR_RmDir VBoxNsprPR_RmDir
+#define PR_NewUDPSocket VBoxNsprPR_NewUDPSocket
+#define PR_NewTCPSocket VBoxNsprPR_NewTCPSocket
+#define PR_OpenUDPSocket VBoxNsprPR_OpenUDPSocket
+#define PR_OpenTCPSocket VBoxNsprPR_OpenTCPSocket
+#define PR_ConnectContinue VBoxNsprPR_ConnectContinue
+#define PR_GetConnectStatus VBoxNsprPR_GetConnectStatus
+#define PR_Shutdown VBoxNsprPR_Shutdown
+#define PR_Recv VBoxNsprPR_Recv
+#define PR_Send VBoxNsprPR_Send
+#define PR_RecvFrom VBoxNsprPR_RecvFrom
+#define PR_SendTo VBoxNsprPR_SendTo
+#define PR_TransmitFile VBoxNsprPR_TransmitFile
+#define PR_SendFile VBoxNsprPR_SendFile
+#define PR_NewTCPSocketPair VBoxNsprPR_NewTCPSocketPair
+#define PR_GetSockName VBoxNsprPR_GetSockName
+#define PR_GetPeerName VBoxNsprPR_GetPeerName
+#define PR_GetSocketOption VBoxNsprPR_GetSocketOption
+#define PR_CreateFileMap VBoxNsprPR_CreateFileMap
+#define PR_GetMemMapAlignment VBoxNsprPR_GetMemMapAlignment
+#define PR_MemMap VBoxNsprPR_MemMap
+#define PR_MemUnmap VBoxNsprPR_MemUnmap
+#define PR_CloseFileMap VBoxNsprPR_CloseFileMap
+#define PR_CreatePipe VBoxNsprPR_CreatePipe
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/* Typedefs */
+typedef struct PRDir PRDir;
+typedef struct PRDirEntry PRDirEntry;
+#ifdef MOZ_UNICODE
+typedef struct PRDirUTF16 PRDirUTF16;
+typedef struct PRDirEntryUTF16 PRDirEntryUTF16;
+#endif /* MOZ_UNICODE */
+typedef struct PRFileDesc PRFileDesc;
+typedef struct PRFileInfo PRFileInfo;
+typedef struct PRFileInfo64 PRFileInfo64;
+typedef union PRNetAddr PRNetAddr;
+typedef struct PRIOMethods PRIOMethods;
+typedef struct PRPollDesc PRPollDesc;
+typedef struct PRFilePrivate PRFilePrivate;
+typedef struct PRSendFileData PRSendFileData;
+
+/*
+***************************************************************************
+** The file descriptor.
+** This is the primary structure to represent any active open socket,
+** whether it be a normal file or a network connection. Such objects
+** are stackable (or layerable). Each layer may have its own set of
+** method pointers and context private to that layer. All each layer
+** knows about its neighbors is how to get to their method table.
+***************************************************************************
+*/
+
+typedef PRIntn PRDescIdentity; /* see: Layering file descriptors */
+
+struct PRFileDesc {
+ const PRIOMethods *methods; /* the I/O methods table */
+ PRFilePrivate *secret; /* layer dependent data */
+ PRFileDesc *lower, *higher; /* pointers to adjacent layers */
+ void (PR_CALLBACK *dtor)(PRFileDesc *fd);
+ /* A destructor function for layer */
+ PRDescIdentity identity; /* Identity of this particular layer */
+};
+
+/*
+***************************************************************************
+** PRTransmitFileFlags
+**
+** Flags for PR_TransmitFile. Pass PR_TRANSMITFILE_CLOSE_SOCKET to
+** PR_TransmitFile if the connection should be closed after the file
+** is transmitted.
+***************************************************************************
+*/
+typedef enum PRTransmitFileFlags {
+ PR_TRANSMITFILE_KEEP_OPEN = 0, /* socket is left open after file
+ * is transmitted. */
+ PR_TRANSMITFILE_CLOSE_SOCKET = 1 /* socket is closed after file
+ * is transmitted. */
+} PRTransmitFileFlags;
+
+/*
+**************************************************************************
+** Macros for PRNetAddr
+**
+** Address families: PR_AF_INET, PR_AF_INET6, PR_AF_LOCAL
+** IP addresses: PR_INADDR_ANY, PR_INADDR_LOOPBACK, PR_INADDR_BROADCAST
+**************************************************************************
+*/
+
+#ifdef WIN32
+
+#define PR_AF_INET 2
+#define PR_AF_LOCAL 1
+#define PR_INADDR_ANY (unsigned long)0x00000000
+#define PR_INADDR_LOOPBACK 0x7f000001
+#define PR_INADDR_BROADCAST (unsigned long)0xffffffff
+
+#else /* WIN32 */
+
+#define PR_AF_INET AF_INET
+#define PR_AF_LOCAL AF_UNIX
+#define PR_INADDR_ANY INADDR_ANY
+#define PR_INADDR_LOOPBACK INADDR_LOOPBACK
+#define PR_INADDR_BROADCAST INADDR_BROADCAST
+
+#endif /* WIN32 */
+
+/*
+** Define PR_AF_INET6 in prcpucfg.h with the same
+** value as AF_INET6 on platforms with IPv6 support.
+** Otherwise define it here.
+*/
+#ifndef PR_AF_INET6
+#define PR_AF_INET6 100
+#endif
+
+#ifndef PR_AF_UNSPEC
+#define PR_AF_UNSPEC 0
+#endif
+
+/*
+**************************************************************************
+** A network address
+**
+** Only Internet Protocol (IPv4 and IPv6) addresses are supported.
+** The address family must always represent IPv4 (AF_INET, probably == 2)
+** or IPv6 (AF_INET6).
+**************************************************************************
+*************************************************************************/
+
+struct PRIPv6Addr {
+ union {
+ PRUint8 _S6_u8[16];
+ PRUint16 _S6_u16[8];
+ PRUint32 _S6_u32[4];
+ PRUint64 _S6_u64[2];
+ } _S6_un;
+};
+#define pr_s6_addr _S6_un._S6_u8
+#define pr_s6_addr16 _S6_un._S6_u16
+#define pr_s6_addr32 _S6_un._S6_u32
+#define pr_s6_addr64 _S6_un._S6_u64
+
+typedef struct PRIPv6Addr PRIPv6Addr;
+
+union PRNetAddr {
+ struct {
+ PRUint16 family; /* address family (0x00ff maskable) */
+#ifdef XP_BEOS
+ char data[10]; /* Be has a smaller structure */
+#else
+ char data[14]; /* raw address data */
+#endif
+ } raw;
+ struct {
+ PRUint16 family; /* address family (AF_INET) */
+ PRUint16 port; /* port number */
+ PRUint32 ip; /* The actual 32 bits of address */
+#ifdef XP_BEOS
+ char pad[4]; /* Be has a smaller structure */
+#else
+ char pad[8];
+#endif
+ } inet;
+ struct {
+ PRUint16 family; /* address family (AF_INET6) */
+ PRUint16 port; /* port number */
+ PRUint32 flowinfo; /* routing information */
+ PRIPv6Addr ip; /* the actual 128 bits of address */
+ PRUint32 scope_id; /* set of interfaces for a scope */
+ } ipv6;
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ struct { /* Unix domain socket address */
+ PRUint16 family; /* address family (AF_UNIX) */
+#ifdef XP_OS2
+ char path[108]; /* null-terminated pathname */
+ /* bind fails if size is not 108. */
+#else
+ char path[104]; /* null-terminated pathname */
+#endif
+ } local;
+#endif
+};
+
+/*
+***************************************************************************
+** PRSockOption
+**
+** The file descriptors can have predefined options set after they file
+** descriptor is created to change their behavior. Only the options in
+** the following enumeration are supported.
+***************************************************************************
+*/
+typedef enum PRSockOption
+{
+ PR_SockOpt_Nonblocking, /* nonblocking io */
+ PR_SockOpt_Linger, /* linger on close if data present */
+ PR_SockOpt_Reuseaddr, /* allow local address reuse */
+ PR_SockOpt_Keepalive, /* keep connections alive */
+ PR_SockOpt_RecvBufferSize, /* send buffer size */
+ PR_SockOpt_SendBufferSize, /* receive buffer size */
+
+ PR_SockOpt_IpTimeToLive, /* time to live */
+ PR_SockOpt_IpTypeOfService, /* type of service and precedence */
+
+ PR_SockOpt_AddMember, /* add an IP group membership */
+ PR_SockOpt_DropMember, /* drop an IP group membership */
+ PR_SockOpt_McastInterface, /* multicast interface address */
+ PR_SockOpt_McastTimeToLive, /* multicast timetolive */
+ PR_SockOpt_McastLoopback, /* multicast loopback */
+
+ PR_SockOpt_NoDelay, /* don't delay send to coalesce packets */
+ PR_SockOpt_MaxSegment, /* maximum segment size */
+ PR_SockOpt_Broadcast, /* enable broadcast */
+ PR_SockOpt_Last
+} PRSockOption;
+
+typedef struct PRLinger {
+ PRBool polarity; /* Polarity of the option's setting */
+ PRIntervalTime linger; /* Time to linger before closing */
+} PRLinger;
+
+typedef struct PRMcastRequest {
+ PRNetAddr mcaddr; /* IP multicast address of group */
+ PRNetAddr ifaddr; /* local IP address of interface */
+} PRMcastRequest;
+
+typedef struct PRSocketOptionData
+{
+ PRSockOption option;
+ union
+ {
+ PRUintn ip_ttl; /* IP time to live */
+ PRUintn mcast_ttl; /* IP multicast time to live */
+ PRUintn tos; /* IP type of service and precedence */
+ PRBool non_blocking; /* Non-blocking (network) I/O */
+ PRBool reuse_addr; /* Allow local address reuse */
+ PRBool keep_alive; /* Keep connections alive */
+ PRBool mcast_loopback; /* IP multicast loopback */
+ PRBool no_delay; /* Don't delay send to coalesce packets */
+ PRBool broadcast; /* Enable broadcast */
+ PRSize max_segment; /* Maximum segment size */
+ PRSize recv_buffer_size; /* Receive buffer size */
+ PRSize send_buffer_size; /* Send buffer size */
+ PRLinger linger; /* Time to linger on close if data present */
+ PRMcastRequest add_member; /* add an IP group membership */
+ PRMcastRequest drop_member; /* Drop an IP group membership */
+ PRNetAddr mcast_if; /* multicast interface address */
+ } value;
+} PRSocketOptionData;
+
+/*
+***************************************************************************
+** PRIOVec
+**
+** The I/O vector is used by the write vector method to describe the areas
+** that are affected by the ouput operation.
+***************************************************************************
+*/
+typedef struct PRIOVec {
+ char *iov_base;
+ int iov_len;
+} PRIOVec;
+
+/*
+***************************************************************************
+** Discover what type of socket is being described by the file descriptor.
+***************************************************************************
+*/
+typedef enum PRDescType
+{
+ PR_DESC_FILE = 1,
+ PR_DESC_SOCKET_TCP = 2,
+ PR_DESC_SOCKET_UDP = 3,
+ PR_DESC_LAYERED = 4,
+ PR_DESC_PIPE = 5
+} PRDescType;
+
+typedef enum PRSeekWhence {
+ PR_SEEK_SET = 0,
+ PR_SEEK_CUR = 1,
+ PR_SEEK_END = 2
+} PRSeekWhence;
+
+NSPR_API(PRDescType) PR_GetDescType(PRFileDesc *file);
+
+/*
+***************************************************************************
+** PRIOMethods
+**
+** The I/O methods table provides procedural access to the functions of
+** the file descriptor. It is the responsibility of a layer implementor
+** to provide suitable functions at every entry point. If a layer provides
+** no functionality, it should call the next lower(higher) function of the
+** same name (e.g., return fd->lower->method->close(fd->lower));
+**
+** Not all functions are implemented for all types of files. In cases where
+** that is true, the function will return a error indication with an error
+** code of PR_INVALID_METHOD_ERROR.
+***************************************************************************
+*/
+
+typedef PRStatus (PR_CALLBACK *PRCloseFN)(PRFileDesc *fd);
+typedef PRInt32 (PR_CALLBACK *PRReadFN)(PRFileDesc *fd, void *buf, PRInt32 amount);
+typedef PRInt32 (PR_CALLBACK *PRWriteFN)(PRFileDesc *fd, const void *buf, PRInt32 amount);
+typedef PRInt32 (PR_CALLBACK *PRAvailableFN)(PRFileDesc *fd);
+typedef PRInt64 (PR_CALLBACK *PRAvailable64FN)(PRFileDesc *fd);
+typedef PRStatus (PR_CALLBACK *PRFsyncFN)(PRFileDesc *fd);
+typedef PROffset32 (PR_CALLBACK *PRSeekFN)(PRFileDesc *fd, PROffset32 offset, PRSeekWhence how);
+typedef PROffset64 (PR_CALLBACK *PRSeek64FN)(PRFileDesc *fd, PROffset64 offset, PRSeekWhence how);
+typedef PRStatus (PR_CALLBACK *PRFileInfoFN)(PRFileDesc *fd, PRFileInfo *info);
+typedef PRStatus (PR_CALLBACK *PRFileInfo64FN)(PRFileDesc *fd, PRFileInfo64 *info);
+typedef PRInt32 (PR_CALLBACK *PRWritevFN)(
+ PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout);
+typedef PRStatus (PR_CALLBACK *PRConnectFN)(
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout);
+typedef PRFileDesc* (PR_CALLBACK *PRAcceptFN) (
+ PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout);
+typedef PRStatus (PR_CALLBACK *PRBindFN)(PRFileDesc *fd, const PRNetAddr *addr);
+typedef PRStatus (PR_CALLBACK *PRListenFN)(PRFileDesc *fd, PRIntn backlog);
+typedef PRStatus (PR_CALLBACK *PRShutdownFN)(PRFileDesc *fd, PRIntn how);
+typedef PRInt32 (PR_CALLBACK *PRRecvFN)(
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+typedef PRInt32 (PR_CALLBACK *PRSendFN) (
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+typedef PRInt32 (PR_CALLBACK *PRRecvfromFN)(
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout);
+typedef PRInt32 (PR_CALLBACK *PRSendtoFN)(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout);
+typedef PRInt16 (PR_CALLBACK *PRPollFN)(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
+typedef PRInt32 (PR_CALLBACK *PRAcceptreadFN)(
+ PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime t);
+typedef PRInt32 (PR_CALLBACK *PRTransmitfileFN)(
+ PRFileDesc *sd, PRFileDesc *fd, const void *headers,
+ PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime t);
+typedef PRStatus (PR_CALLBACK *PRGetsocknameFN)(PRFileDesc *fd, PRNetAddr *addr);
+typedef PRStatus (PR_CALLBACK *PRGetpeernameFN)(PRFileDesc *fd, PRNetAddr *addr);
+typedef PRStatus (PR_CALLBACK *PRGetsocketoptionFN)(
+ PRFileDesc *fd, PRSocketOptionData *data);
+typedef PRStatus (PR_CALLBACK *PRSetsocketoptionFN)(
+ PRFileDesc *fd, const PRSocketOptionData *data);
+typedef PRInt32 (PR_CALLBACK *PRSendfileFN)(
+ PRFileDesc *networkSocket, PRSendFileData *sendData,
+ PRTransmitFileFlags flags, PRIntervalTime timeout);
+typedef PRStatus (PR_CALLBACK *PRConnectcontinueFN)(
+ PRFileDesc *fd, PRInt16 out_flags);
+typedef PRIntn (PR_CALLBACK *PRReservedFN)(PRFileDesc *fd);
+
+struct PRIOMethods {
+ PRDescType file_type; /* Type of file represented (tos) */
+ PRCloseFN close; /* close file and destroy descriptor */
+ PRReadFN read; /* read up to specified bytes into buffer */
+ PRWriteFN write; /* write specified bytes from buffer */
+ PRAvailableFN available; /* determine number of bytes available */
+ PRAvailable64FN available64; /* ditto, 64 bit */
+ PRFsyncFN fsync; /* flush all buffers to permanent store */
+ PRSeekFN seek; /* position the file to the desired place */
+ PRSeek64FN seek64; /* ditto, 64 bit */
+ PRFileInfoFN fileInfo; /* Get information about an open file */
+ PRFileInfo64FN fileInfo64; /* ditto, 64 bit */
+ PRWritevFN writev; /* Write segments as described by iovector */
+ PRConnectFN connect; /* Connect to the specified (net) address */
+ PRAcceptFN accept; /* Accept a connection for a (net) peer */
+ PRBindFN bind; /* Associate a (net) address with the fd */
+ PRListenFN listen; /* Prepare to listen for (net) connections */
+ PRShutdownFN shutdown; /* Shutdown a (net) connection */
+ PRRecvFN recv; /* Solicit up the the specified bytes */
+ PRSendFN send; /* Send all the bytes specified */
+ PRRecvfromFN recvfrom; /* Solicit (net) bytes and report source */
+ PRSendtoFN sendto; /* Send bytes to (net) address specified */
+ PRPollFN poll; /* Test the fd to see if it is ready */
+ PRAcceptreadFN acceptread; /* Accept and read on a new (net) fd */
+ PRTransmitfileFN transmitfile; /* Transmit at entire file */
+ PRGetsocknameFN getsockname; /* Get (net) address associated with fd */
+ PRGetpeernameFN getpeername; /* Get peer's (net) address */
+ PRReservedFN reserved_fn_6; /* reserved for future use */
+ PRReservedFN reserved_fn_5; /* reserved for future use */
+ PRGetsocketoptionFN getsocketoption;
+ /* Get current setting of specified option */
+ PRSetsocketoptionFN setsocketoption;
+ /* Set value of specified option */
+ PRSendfileFN sendfile; /* Send a (partial) file with header/trailer*/
+ PRConnectcontinueFN connectcontinue;
+ /* Continue a nonblocking connect */
+ PRReservedFN reserved_fn_3; /* reserved for future use */
+ PRReservedFN reserved_fn_2; /* reserved for future use */
+ PRReservedFN reserved_fn_1; /* reserved for future use */
+ PRReservedFN reserved_fn_0; /* reserved for future use */
+};
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_GetSpecialFD
+ * DESCRIPTION: Get the file descriptor that represents the standard input,
+ * output, or error stream.
+ * INPUTS:
+ * PRSpecialFD id
+ * A value indicating the type of stream desired:
+ * PR_StandardInput: standard input
+ * PR_StandardOuput: standard output
+ * PR_StandardError: standard error
+ * OUTPUTS: none
+ * RETURNS: PRFileDesc *
+ * If the argument is valid, PR_GetSpecialFD returns a file descriptor
+ * that represents the corresponding standard I/O stream. Otherwise,
+ * PR_GetSpecialFD returns NULL and sets error PR_INVALID_ARGUMENT_ERROR.
+ **************************************************************************
+ */
+
+typedef enum PRSpecialFD
+{
+ PR_StandardInput, /* standard input */
+ PR_StandardOutput, /* standard output */
+ PR_StandardError /* standard error */
+} PRSpecialFD;
+
+NSPR_API(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD id);
+
+#define PR_STDIN PR_GetSpecialFD(PR_StandardInput)
+#define PR_STDOUT PR_GetSpecialFD(PR_StandardOutput)
+#define PR_STDERR PR_GetSpecialFD(PR_StandardError)
+
+/*
+ **************************************************************************
+ * Layering file descriptors
+ *
+ * File descriptors may be layered. Each layer has it's own identity.
+ * Identities are allocated by the runtime and are to be associated
+ * (by the layer implementor) with all layers that are of that type.
+ * It is then possible to scan the chain of layers and find a layer
+ * that one recongizes and therefore predict that it will implement
+ * a desired protocol.
+ *
+ * There are three well-known identities:
+ * PR_INVALID_IO_LAYER => an invalid layer identity, for error return
+ * PR_TOP_IO_LAYER => the identity of the top of the stack
+ * PR_NSPR_IO_LAYER => the identity used by NSPR proper
+ * PR_TOP_IO_LAYER may be used as a shorthand for identifying the topmost
+ * layer of an existing stack. Ie., the following two constructs are
+ * equivalent.
+ *
+ * rv = PR_PushIOLayer(stack, PR_TOP_IO_LAYER, my_layer);
+ * rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), my_layer)
+ *
+ * A string may be associated with the creation of the identity. It
+ * will be copied by the runtime. If queried the runtime will return
+ * a reference to that copied string (not yet another copy). There
+ * is no facility for deleting an identity.
+ **************************************************************************
+ */
+
+#define PR_IO_LAYER_HEAD (PRDescIdentity)-3
+#define PR_INVALID_IO_LAYER (PRDescIdentity)-1
+#define PR_TOP_IO_LAYER (PRDescIdentity)-2
+#define PR_NSPR_IO_LAYER (PRDescIdentity)0
+
+NSPR_API(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name);
+NSPR_API(const char*) PR_GetNameForIdentity(PRDescIdentity ident);
+NSPR_API(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd);
+NSPR_API(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd_stack, PRDescIdentity id);
+
+/*
+ **************************************************************************
+ * PR_GetDefaultIOMethods: Accessing the default methods table.
+ * You may get a pointer to the default methods table by calling this function.
+ * You may then select any elements from that table with which to build your
+ * layer's methods table. You may NOT modify the table directly.
+ **************************************************************************
+ */
+NSPR_API(const PRIOMethods *) PR_GetDefaultIOMethods(void);
+
+/*
+ **************************************************************************
+ * Creating a layer
+ *
+ * A new layer may be allocated by calling PR_CreateIOLayerStub(). The
+ * file descriptor returned will contain the pointer to the methods table
+ * provided. The runtime will not modify the table nor test its correctness.
+ **************************************************************************
+ */
+NSPR_API(PRFileDesc*) PR_CreateIOLayerStub(
+ PRDescIdentity ident, const PRIOMethods *methods);
+
+/*
+ **************************************************************************
+ * Creating a layer
+ *
+ * A new stack may be created by calling PR_CreateIOLayer(). The
+ * file descriptor returned will point to the top of the stack, which has
+ * the layer 'fd' as the topmost layer.
+ *
+ * NOTE: This function creates a new style stack, which has a fixed, dummy
+ * header. The old style stack, created by a call to PR_PushIOLayer,
+ * results in modifying contents of the top layer of the stack, when
+ * pushing and popping layers of the stack.
+ **************************************************************************
+ */
+NSPR_API(PRFileDesc*) PR_CreateIOLayer(PRFileDesc* fd);
+
+/*
+ **************************************************************************
+ * Pushing a layer
+ *
+ * A file descriptor (perhaps allocated using PR_CreateIOLayerStub()) may
+ * be pushed into an existing stack of file descriptors at any point the
+ * caller deems appropriate. The new layer will be inserted into the stack
+ * just above the layer with the indicated identity.
+ *
+ * Note: Even if the identity parameter indicates the top-most layer of
+ * the stack, the value of the file descriptor describing the original
+ * stack will not change.
+ **************************************************************************
+ */
+NSPR_API(PRStatus) PR_PushIOLayer(
+ PRFileDesc *fd_stack, PRDescIdentity id, PRFileDesc *layer);
+
+/*
+ **************************************************************************
+ * Popping a layer
+ *
+ * A layer may be popped from a stack by indicating the identity of the
+ * layer to be removed. If found, a pointer to the removed object will
+ * be returned to the caller. The object then becomes the responsibility
+ * of the caller.
+ *
+ * Note: Even if the identity indicates the top layer of the stack, the
+ * reference returned will not be the file descriptor for the stack and
+ * that file descriptor will remain valid.
+ **************************************************************************
+ */
+NSPR_API(PRFileDesc*) PR_PopIOLayer(PRFileDesc *fd_stack, PRDescIdentity id);
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_Open
+ * DESCRIPTION: Open a file for reading, writing, or both.
+ * INPUTS:
+ * const char *name
+ * The path name of the file to be opened
+ * PRIntn flags
+ * The file status flags.
+ * It is a bitwise OR of the following bit flags (only one of
+ * the first three flags below may be used):
+ * PR_RDONLY Open for reading only.
+ * PR_WRONLY Open for writing only.
+ * PR_RDWR Open for reading and writing.
+ * PR_CREATE_FILE If the file does not exist, the file is created
+ * If the file exists, this flag has no effect.
+ * PR_SYNC If set, each write will wait for both the file data
+ * and file status to be physically updated.
+ * PR_APPEND The file pointer is set to the end of
+ * the file prior to each write.
+ * PR_TRUNCATE If the file exists, its length is truncated to 0.
+ * PR_EXCL With PR_CREATE_FILE, if the file does not exist,
+ * the file is created. If the file already
+ * exists, no action and NULL is returned
+ *
+ * PRIntn mode
+ * The access permission bits of the file mode, if the file is
+ * created when PR_CREATE_FILE is on.
+ * OUTPUTS: None
+ * RETURNS: PRFileDesc *
+ * If the file is successfully opened,
+ * returns a pointer to the PRFileDesc
+ * created for the newly opened file.
+ * Returns a NULL pointer if the open
+ * failed.
+ * SIDE EFFECTS:
+ * RESTRICTIONS:
+ * MEMORY:
+ * The return value, if not NULL, points to a dynamically allocated
+ * PRFileDesc object.
+ * ALGORITHM:
+ **************************************************************************
+ */
+
+/* Open flags */
+#define PR_RDONLY 0x01
+#define PR_WRONLY 0x02
+#define PR_RDWR 0x04
+#define PR_CREATE_FILE 0x08
+#define PR_APPEND 0x10
+#define PR_TRUNCATE 0x20
+#define PR_SYNC 0x40
+#define PR_EXCL 0x80
+
+/*
+** File modes ....
+**
+** CAVEAT: 'mode' is currently only applicable on UNIX platforms.
+** The 'mode' argument may be ignored by PR_Open on other platforms.
+**
+** 00400 Read by owner.
+** 00200 Write by owner.
+** 00100 Execute (search if a directory) by owner.
+** 00040 Read by group.
+** 00020 Write by group.
+** 00010 Execute by group.
+** 00004 Read by others.
+** 00002 Write by others
+** 00001 Execute by others.
+**
+*/
+
+NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode);
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_OpenFile
+ * DESCRIPTION:
+ * Open a file for reading, writing, or both.
+ * PR_OpenFile has the same prototype as PR_Open but implements
+ * the specified file mode where possible.
+ **************************************************************************
+ */
+
+/* File mode bits */
+#define PR_IRWXU 00700 /* read, write, execute/search by owner */
+#define PR_IRUSR 00400 /* read permission, owner */
+#define PR_IWUSR 00200 /* write permission, owner */
+#define PR_IXUSR 00100 /* execute/search permission, owner */
+#define PR_IRWXG 00070 /* read, write, execute/search by group */
+#define PR_IRGRP 00040 /* read permission, group */
+#define PR_IWGRP 00020 /* write permission, group */
+#define PR_IXGRP 00010 /* execute/search permission, group */
+#define PR_IRWXO 00007 /* read, write, execute/search by others */
+#define PR_IROTH 00004 /* read permission, others */
+#define PR_IWOTH 00002 /* write permission, others */
+#define PR_IXOTH 00001 /* execute/search permission, others */
+
+NSPR_API(PRFileDesc*) PR_OpenFile(
+ const char *name, PRIntn flags, PRIntn mode);
+
+#ifdef MOZ_UNICODE
+/*
+ * EXPERIMENTAL: This function may be removed in a future release.
+ */
+NSPR_API(PRFileDesc*) PR_OpenFileUTF16(
+ const PRUnichar *name, PRIntn flags, PRIntn mode);
+#endif /* MOZ_UNICODE */
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_Close
+ * DESCRIPTION:
+ * Close a file or socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * a pointer to a PRFileDesc.
+ * OUTPUTS:
+ * None.
+ * RETURN:
+ * PRStatus
+ * SIDE EFFECTS:
+ * RESTRICTIONS:
+ * None.
+ * MEMORY:
+ * The dynamic memory pointed to by the argument fd is freed.
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Close(PRFileDesc *fd);
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_Read
+ * DESCRIPTION:
+ * Read bytes from a file or socket.
+ * The operation will block until either an end of stream indication is
+ * encountered, some positive number of bytes are transferred, or there
+ * is an error. No more than 'amount' bytes will be transferred.
+ * INPUTS:
+ * PRFileDesc *fd
+ * pointer to the PRFileDesc object for the file or socket
+ * void *buf
+ * pointer to a buffer to hold the data read in.
+ * PRInt32 amount
+ * the size of 'buf' (in bytes)
+ * OUTPUTS:
+ * RETURN:
+ * PRInt32
+ * a positive number indicates the number of bytes actually read in.
+ * 0 means end of file is reached or the network connection is closed.
+ * -1 indicates a failure. The reason for the failure is obtained
+ * by calling PR_GetError().
+ * SIDE EFFECTS:
+ * data is written into the buffer pointed to by 'buf'.
+ * RESTRICTIONS:
+ * None.
+ * MEMORY:
+ * N/A
+ * ALGORITHM:
+ * N/A
+ **************************************************************************
+ */
+
+NSPR_API(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount);
+
+/*
+ ***************************************************************************
+ * FUNCTION: PR_Write
+ * DESCRIPTION:
+ * Write a specified number of bytes to a file or socket. The thread
+ * invoking this function blocks until all the data is written.
+ * INPUTS:
+ * PRFileDesc *fd
+ * pointer to a PRFileDesc object that refers to a file or socket
+ * const void *buf
+ * pointer to the buffer holding the data
+ * PRInt32 amount
+ * amount of data in bytes to be written from the buffer
+ * OUTPUTS:
+ * None.
+ * RETURN: PRInt32
+ * A positive number indicates the number of bytes successfully written.
+ * A -1 is an indication that the operation failed. The reason
+ * for the failure is obtained by calling PR_GetError().
+ ***************************************************************************
+ */
+
+NSPR_API(PRInt32) PR_Write(PRFileDesc *fd,const void *buf,PRInt32 amount);
+
+/*
+ ***************************************************************************
+ * FUNCTION: PR_Writev
+ * DESCRIPTION:
+ * Write data to a socket. The data is organized in a PRIOVec array. The
+ * operation will block until all the data is written or the operation
+ * fails.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Pointer that points to a PRFileDesc object for a socket.
+ * const PRIOVec *iov
+ * An array of PRIOVec. PRIOVec is a struct with the following
+ * two fields:
+ * char *iov_base;
+ * int iov_len;
+ * PRInt32 iov_size
+ * Number of elements in the iov array. The value of this
+ * argument must not be greater than PR_MAX_IOVECTOR_SIZE.
+ * If it is, the method will fail (PR_BUFFER_OVERFLOW_ERROR).
+ * PRIntervalTime timeout
+ * Time limit for completion of the entire write operation.
+ * OUTPUTS:
+ * None
+ * RETURN:
+ * A positive number indicates the number of bytes successfully written.
+ * A -1 is an indication that the operation failed. The reason
+ * for the failure is obtained by calling PR_GetError().
+ ***************************************************************************
+ */
+
+#define PR_MAX_IOVECTOR_SIZE 16 /* 'iov_size' must be <= */
+
+NSPR_API(PRInt32) PR_Writev(
+ PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout);
+
+/*
+ ***************************************************************************
+ * FUNCTION: PR_Delete
+ * DESCRIPTION:
+ * Delete a file from the filesystem. The operation may fail if the
+ * file is open.
+ * INPUTS:
+ * const char *name
+ * Path name of the file to be deleted.
+ * OUTPUTS:
+ * None.
+ * RETURN: PRStatus
+ * The function returns PR_SUCCESS if the file is successfully
+ * deleted, otherwise it returns PR_FAILURE.
+ ***************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Delete(const char *name);
+
+/**************************************************************************/
+
+typedef enum PRFileType
+{
+ PR_FILE_FILE = 1,
+ PR_FILE_DIRECTORY = 2,
+ PR_FILE_OTHER = 3
+} PRFileType;
+
+struct PRFileInfo {
+ PRFileType type; /* Type of file */
+ PROffset32 size; /* Size, in bytes, of file's contents */
+ PRTime creationTime; /* Creation time per definition of PRTime */
+ PRTime modifyTime; /* Last modification time per definition of PRTime */
+};
+
+struct PRFileInfo64 {
+ PRFileType type; /* Type of file */
+ PROffset64 size; /* Size, in bytes, of file's contents */
+ PRTime creationTime; /* Creation time per definition of PRTime */
+ PRTime modifyTime; /* Last modification time per definition of PRTime */
+};
+
+/****************************************************************************
+ * FUNCTION: PR_GetFileInfo, PR_GetFileInfo64
+ * DESCRIPTION:
+ * Get the information about the file with the given path name. This is
+ * applicable only to NSFileDesc describing 'file' types (see
+ * INPUTS:
+ * const char *fn
+ * path name of the file
+ * OUTPUTS:
+ * PRFileInfo *info
+ * Information about the given file is written into the file
+ * information object pointer to by 'info'.
+ * RETURN: PRStatus
+ * PR_GetFileInfo returns PR_SUCCESS if file information is successfully
+ * obtained, otherwise it returns PR_FAILURE.
+ ***************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info);
+NSPR_API(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info);
+
+#ifdef MOZ_UNICODE
+/*
+ * EXPERIMENTAL: This function may be removed in a future release.
+ */
+NSPR_API(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info);
+#endif /* MOZ_UNICODE */
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_GetOpenFileInfo, PR_GetOpenFileInfo64
+ * DESCRIPTION:
+ * Get information about an open file referred to by the
+ * given PRFileDesc object.
+ * INPUTS:
+ * const PRFileDesc *fd
+ * A reference to a valid, open file.
+ * OUTPUTS:
+ * Same as PR_GetFileInfo, PR_GetFileInfo64
+ * RETURN: PRStatus
+ * PR_GetFileInfo returns PR_SUCCESS if file information is successfully
+ * obtained, otherwise it returns PR_FAILURE.
+ ***************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info);
+NSPR_API(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info);
+
+/*
+ **************************************************************************
+ * FUNCTION: PR_Rename
+ * DESCRIPTION:
+ * Rename a file from the old name 'from' to the new name 'to'.
+ * INPUTS:
+ * const char *from
+ * The old name of the file to be renamed.
+ * const char *to
+ * The new name of the file.
+ * OUTPUTS:
+ * None.
+ * RETURN: PRStatus
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Rename(const char *from, const char *to);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Access
+ * DESCRIPTION:
+ * Determine accessibility of a file.
+ * INPUTS:
+ * const char *name
+ * path name of the file
+ * PRAccessHow how
+ * specifies which access permission to check for.
+ * It can be one of the following values:
+ * PR_ACCESS_READ_OK Test for read permission
+ * PR_ACCESS_WRITE_OK Test for write permission
+ * PR_ACCESS_EXISTS Check existence of file
+ * OUTPUTS:
+ * None.
+ * RETURN: PRStatus
+ * PR_SUCCESS is returned if the requested access is permitted.
+ * Otherwise, PR_FAILURE is returned. Additional information
+ * regarding the reason for the failure may be retrieved from
+ * PR_GetError().
+ *************************************************************************
+ */
+
+typedef enum PRAccessHow {
+ PR_ACCESS_EXISTS = 1,
+ PR_ACCESS_WRITE_OK = 2,
+ PR_ACCESS_READ_OK = 3
+} PRAccessHow;
+
+NSPR_API(PRStatus) PR_Access(const char *name, PRAccessHow how);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Seek, PR_Seek64
+ * DESCRIPTION:
+ * Moves read-write file offset
+ * INPUTS:
+ * PRFileDesc *fd
+ * Pointer to a PRFileDesc object.
+ * PROffset32, PROffset64 offset
+ * Specifies a value, in bytes, that is used in conjunction
+ * with the 'whence' parameter to set the file pointer. A
+ * negative value causes seeking in the reverse direction.
+ * PRSeekWhence whence
+ * Specifies how to interpret the 'offset' parameter in setting
+ * the file pointer associated with the 'fd' parameter.
+ * Values for the 'whence' parameter are:
+ * PR_SEEK_SET Sets the file pointer to the value of the
+ * 'offset' parameter
+ * PR_SEEK_CUR Sets the file pointer to its current location
+ * plus the value of the offset parameter.
+ * PR_SEEK_END Sets the file pointer to the size of the
+ * file plus the value of the offset parameter.
+ * OUTPUTS:
+ * None.
+ * RETURN: PROffset32, PROffset64
+ * Upon successful completion, the resulting pointer location,
+ * measured in bytes from the beginning of the file, is returned.
+ * If the PR_Seek() function fails, the file offset remains
+ * unchanged, and the returned value is -1. The error code can
+ * then be retrieved via PR_GetError().
+ *************************************************************************
+ */
+
+NSPR_API(PROffset32) PR_Seek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence);
+NSPR_API(PROffset64) PR_Seek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence);
+
+/*
+ ************************************************************************
+ * FUNCTION: PR_Available
+ * DESCRIPTION:
+ * Determine the amount of data in bytes available for reading
+ * in the given file or socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Pointer to a PRFileDesc object that refers to a file or
+ * socket.
+ * OUTPUTS:
+ * None
+ * RETURN: PRInt32, PRInt64
+ * Upon successful completion, PR_Available returns the number of
+ * bytes beyond the current read pointer that is available for
+ * reading. Otherwise, it returns a -1 and the reason for the
+ * failure can be retrieved via PR_GetError().
+ ************************************************************************
+ */
+
+NSPR_API(PRInt32) PR_Available(PRFileDesc *fd);
+NSPR_API(PRInt64) PR_Available64(PRFileDesc *fd);
+
+/*
+ ************************************************************************
+ * FUNCTION: PR_Sync
+ * DESCRIPTION:
+ * Sync any buffered data for a fd to its backing device (disk).
+ * INPUTS:
+ * PRFileDesc *fd
+ * Pointer to a PRFileDesc object that refers to a file or
+ * socket
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * PR_SUCCESS is returned if the requested access is permitted.
+ * Otherwise, PR_FAILURE is returned.
+ ************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Sync(PRFileDesc *fd);
+
+/************************************************************************/
+
+struct PRDirEntry {
+ const char *name; /* name of entry, relative to directory name */
+};
+
+#ifdef MOZ_UNICODE
+struct PRDirEntryUTF16 {
+ const PRUnichar *name; /* name of entry in UTF16, relative to
+ * directory name */
+};
+#endif /* MOZ_UNICODE */
+
+#if !defined(NO_NSPR_10_SUPPORT)
+#define PR_DirName(dirEntry) (dirEntry->name)
+#endif
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_OpenDir
+ * DESCRIPTION:
+ * Open the directory by the given name
+ * INPUTS:
+ * const char *name
+ * path name of the directory to be opened
+ * OUTPUTS:
+ * None
+ * RETURN: PRDir *
+ * If the directory is sucessfully opened, a PRDir object is
+ * dynamically allocated and a pointer to it is returned.
+ * If the directory cannot be opened, a NULL pointer is returned.
+ * MEMORY:
+ * Upon successful completion, the return value points to
+ * dynamically allocated memory.
+ *************************************************************************
+ */
+
+NSPR_API(PRDir*) PR_OpenDir(const char *name);
+
+#ifdef MOZ_UNICODE
+/*
+ * EXPERIMENTAL: This function may be removed in a future release.
+ */
+NSPR_API(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name);
+#endif /* MOZ_UNICODE */
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_ReadDir
+ * DESCRIPTION:
+ * INPUTS:
+ * PRDir *dir
+ * pointer to a PRDir object that designates an open directory
+ * PRDirFlags flags
+ * PR_SKIP_NONE Do not skip any files
+ * PR_SKIP_DOT Skip the directory entry "." that
+ * represents the current directory
+ * PR_SKIP_DOT_DOT Skip the directory entry ".." that
+ * represents the parent directory.
+ * PR_SKIP_BOTH Skip both '.' and '..'
+ * PR_SKIP_HIDDEN Skip hidden files
+ * OUTPUTS:
+ * RETURN: PRDirEntry*
+ * Returns a pointer to the next entry in the directory. Returns
+ * a NULL pointer upon reaching the end of the directory or when an
+ * error occurs. The actual reason can be retrieved via PR_GetError().
+ *************************************************************************
+ */
+
+typedef enum PRDirFlags {
+ PR_SKIP_NONE = 0x0,
+ PR_SKIP_DOT = 0x1,
+ PR_SKIP_DOT_DOT = 0x2,
+ PR_SKIP_BOTH = 0x3,
+ PR_SKIP_HIDDEN = 0x4
+} PRDirFlags;
+
+NSPR_API(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags);
+
+#ifdef MOZ_UNICODE
+/*
+ * EXPERIMENTAL: This function may be removed in a future release.
+ */
+NSPR_API(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags);
+#endif /* MOZ_UNICODE */
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_CloseDir
+ * DESCRIPTION:
+ * Close the specified directory.
+ * INPUTS:
+ * PRDir *dir
+ * The directory to be closed.
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * If successful, will return a status of PR_SUCCESS. Otherwise
+ * a value of PR_FAILURE. The reason for the failure may be re-
+ * trieved using PR_GetError().
+ *************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_CloseDir(PRDir *dir);
+
+#ifdef MOZ_UNICODE
+/*
+ * EXPERIMENTAL: This function may be removed in a future release.
+ */
+NSPR_API(PRStatus) PR_CloseDirUTF16(PRDirUTF16 *dir);
+#endif /* MOZ_UNICODE */
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_MkDir
+ * DESCRIPTION:
+ * Create a new directory with the given name and access mode.
+ * INPUTS:
+ * const char *name
+ * The name of the directory to be created. All the path components
+ * up to but not including the leaf component must already exist.
+ * PRIntn mode
+ * See 'mode' definiton in PR_Open().
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * If successful, will return a status of PR_SUCCESS. Otherwise
+ * a value of PR_FAILURE. The reason for the failure may be re-
+ * trieved using PR_GetError().
+ *************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_MkDir(const char *name, PRIntn mode);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_MakeDir
+ * DESCRIPTION:
+ * Create a new directory with the given name and access mode.
+ * PR_MakeDir has the same prototype as PR_MkDir but implements
+ * the specified access mode where possible.
+ *************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_MakeDir(const char *name, PRIntn mode);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_RmDir
+ * DESCRIPTION:
+ * Remove a directory by the given name.
+ * INPUTS:
+ * const char *name
+ * The name of the directory to be removed. All the path components
+ * must already exist. Only the leaf component will be removed.
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * If successful, will return a status of PR_SUCCESS. Otherwise
+ * a value of PR_FAILURE. The reason for the failure may be re-
+ * trieved using PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_RmDir(const char *name);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_NewUDPSocket
+ * DESCRIPTION:
+ * Create a new UDP socket.
+ * INPUTS:
+ * None
+ * OUTPUTS:
+ * None
+ * RETURN: PRFileDesc*
+ * Upon successful completion, PR_NewUDPSocket returns a pointer
+ * to the PRFileDesc created for the newly opened UDP socket.
+ * Returns a NULL pointer if the creation of a new UDP socket failed.
+ *
+ **************************************************************************
+ */
+
+NSPR_API(PRFileDesc*) PR_NewUDPSocket(void);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_NewTCPSocket
+ * DESCRIPTION:
+ * Create a new TCP socket.
+ * INPUTS:
+ * None
+ * OUTPUTS:
+ * None
+ * RETURN: PRFileDesc*
+ * Upon successful completion, PR_NewTCPSocket returns a pointer
+ * to the PRFileDesc created for the newly opened TCP socket.
+ * Returns a NULL pointer if the creation of a new TCP socket failed.
+ *
+ **************************************************************************
+ */
+
+NSPR_API(PRFileDesc*) PR_NewTCPSocket(void);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_OpenUDPSocket
+ * DESCRIPTION:
+ * Create a new UDP socket of the specified address family.
+ * INPUTS:
+ * PRIntn af
+ * Address family
+ * OUTPUTS:
+ * None
+ * RETURN: PRFileDesc*
+ * Upon successful completion, PR_OpenUDPSocket returns a pointer
+ * to the PRFileDesc created for the newly opened UDP socket.
+ * Returns a NULL pointer if the creation of a new UDP socket failed.
+ *
+ **************************************************************************
+ */
+
+NSPR_API(PRFileDesc*) PR_OpenUDPSocket(PRIntn af);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_OpenTCPSocket
+ * DESCRIPTION:
+ * Create a new TCP socket of the specified address family.
+ * INPUTS:
+ * PRIntn af
+ * Address family
+ * OUTPUTS:
+ * None
+ * RETURN: PRFileDesc*
+ * Upon successful completion, PR_NewTCPSocket returns a pointer
+ * to the PRFileDesc created for the newly opened TCP socket.
+ * Returns a NULL pointer if the creation of a new TCP socket failed.
+ *
+ **************************************************************************
+ */
+
+NSPR_API(PRFileDesc*) PR_OpenTCPSocket(PRIntn af);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Connect
+ * DESCRIPTION:
+ * Initiate a connection on a socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Points to a PRFileDesc object representing a socket
+ * PRNetAddr *addr
+ * Specifies the address of the socket in its own communication
+ * space.
+ * PRIntervalTime timeout
+ * Time limit for completion of the connect operation.
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * Upon successful completion of connection initiation, PR_Connect
+ * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further
+ * failure information can be obtained by calling PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Connect(
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_ConnectContinue
+ * DESCRIPTION:
+ * Continue a nonblocking connect. After a nonblocking connect
+ * is initiated with PR_Connect() (which fails with
+ * PR_IN_PROGRESS_ERROR), one should call PR_Poll() on the socket,
+ * with the in_flags PR_POLL_WRITE | PR_POLL_EXCEPT. When
+ * PR_Poll() returns, one calls PR_ConnectContinue() on the
+ * socket to determine whether the nonblocking connect has
+ * completed or is still in progress. Repeat the PR_Poll(),
+ * PR_ConnectContinue() sequence until the nonblocking connect
+ * has completed.
+ * INPUTS:
+ * PRFileDesc *fd
+ * the file descriptor representing a socket
+ * PRInt16 out_flags
+ * the out_flags field of the poll descriptor returned by
+ * PR_Poll()
+ * RETURN: PRStatus
+ * If the nonblocking connect has successfully completed,
+ * PR_ConnectContinue returns PR_SUCCESS. If PR_ConnectContinue()
+ * returns PR_FAILURE, call PR_GetError():
+ * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in
+ * progress and has not completed yet. The caller should poll
+ * on the file descriptor for the in_flags
+ * PR_POLL_WRITE|PR_POLL_EXCEPT and retry PR_ConnectContinue
+ * later when PR_Poll() returns.
+ * - Other errors: the nonblocking connect has failed with this
+ * error code.
+ */
+
+NSPR_API(PRStatus) PR_ConnectContinue(PRFileDesc *fd, PRInt16 out_flags);
+
+/*
+ *************************************************************************
+ * THIS FUNCTION IS DEPRECATED. USE PR_ConnectContinue INSTEAD.
+ *
+ * FUNCTION: PR_GetConnectStatus
+ * DESCRIPTION:
+ * Get the completion status of a nonblocking connect. After
+ * a nonblocking connect is initiated with PR_Connect() (which
+ * fails with PR_IN_PROGRESS_ERROR), one should call PR_Poll()
+ * on the socket, with the in_flags PR_POLL_WRITE | PR_POLL_EXCEPT.
+ * When PR_Poll() returns, one calls PR_GetConnectStatus on the
+ * PRPollDesc structure to determine whether the nonblocking
+ * connect has succeeded or failed.
+ * INPUTS:
+ * const PRPollDesc *pd
+ * Pointer to a PRPollDesc whose fd member is the socket,
+ * and in_flags must contain PR_POLL_WRITE and PR_POLL_EXCEPT.
+ * PR_Poll() should have been called and set the out_flags.
+ * RETURN: PRStatus
+ * If the nonblocking connect has successfully completed,
+ * PR_GetConnectStatus returns PR_SUCCESS. If PR_GetConnectStatus()
+ * returns PR_FAILURE, call PR_GetError():
+ * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in
+ * progress and has not completed yet.
+ * - Other errors: the nonblocking connect has failed with this
+ * error code.
+ */
+
+NSPR_API(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Accept
+ * DESCRIPTION:
+ * Accept a connection on a socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Points to a PRFileDesc object representing the rendezvous socket
+ * on which the caller is willing to accept new connections.
+ * PRIntervalTime timeout
+ * Time limit for completion of the accept operation.
+ * OUTPUTS:
+ * PRNetAddr *addr
+ * Returns the address of the connecting entity in its own
+ * communication space. It may be NULL.
+ * RETURN: PRFileDesc*
+ * Upon successful acceptance of a connection, PR_Accept
+ * returns a valid file descriptor. Otherwise, it returns NULL.
+ * Further failure information can be obtained by calling PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRFileDesc*) PR_Accept(
+ PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Bind
+ * DESCRIPTION:
+ * Bind an address to a socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Points to a PRFileDesc object representing a socket.
+ * PRNetAddr *addr
+ * Specifies the address to which the socket will be bound.
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * Upon successful binding of an address to a socket, PR_Bind
+ * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further
+ * failure information can be obtained by calling PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Listen
+ * DESCRIPTION:
+ * Listen for connections on a socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Points to a PRFileDesc object representing a socket that will be
+ * used to listen for new connections.
+ * PRIntn backlog
+ * Specifies the maximum length of the queue of pending connections.
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * Upon successful completion of listen request, PR_Listen
+ * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further
+ * failure information can be obtained by calling PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Shutdown
+ * DESCRIPTION:
+ * Shut down part of a full-duplex connection on a socket.
+ * INPUTS:
+ * PRFileDesc *fd
+ * Points to a PRFileDesc object representing a connected socket.
+ * PRIntn how
+ * Specifies the kind of disallowed operations on the socket.
+ * PR_SHUTDOWN_RCV - Further receives will be disallowed
+ * PR_SHUTDOWN_SEND - Further sends will be disallowed
+ * PR_SHUTDOWN_BOTH - Further sends and receives will be disallowed
+ * OUTPUTS:
+ * None
+ * RETURN: PRStatus
+ * Upon successful completion of shutdown request, PR_Shutdown
+ * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further
+ * failure information can be obtained by calling PR_GetError().
+ **************************************************************************
+ */
+
+typedef enum PRShutdownHow
+{
+ PR_SHUTDOWN_RCV = 0, /* disallow further receives */
+ PR_SHUTDOWN_SEND = 1, /* disallow further sends */
+ PR_SHUTDOWN_BOTH = 2 /* disallow further receives and sends */
+} PRShutdownHow;
+
+NSPR_API(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Recv
+ * DESCRIPTION:
+ * Receive a specified number of bytes from a connected socket.
+ * The operation will block until some positive number of bytes are
+ * transferred, a time out has occurred, or there is an error.
+ * No more than 'amount' bytes will be transferred.
+ * INPUTS:
+ * PRFileDesc *fd
+ * points to a PRFileDesc object representing a socket.
+ * void *buf
+ * pointer to a buffer to hold the data received.
+ * PRInt32 amount
+ * the size of 'buf' (in bytes)
+ * PRIntn flags
+ * must be zero or PR_MSG_PEEK.
+ * PRIntervalTime timeout
+ * Time limit for completion of the receive operation.
+ * OUTPUTS:
+ * None
+ * RETURN: PRInt32
+ * a positive number indicates the number of bytes actually received.
+ * 0 means the network connection is closed.
+ * -1 indicates a failure. The reason for the failure is obtained
+ * by calling PR_GetError().
+ **************************************************************************
+ */
+
+#define PR_MSG_PEEK 0x2
+
+NSPR_API(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_Send
+ * DESCRIPTION:
+ * Send a specified number of bytes from a connected socket.
+ * The operation will block until all bytes are
+ * processed, a time out has occurred, or there is an error.
+ * INPUTS:
+ * PRFileDesc *fd
+ * points to a PRFileDesc object representing a socket.
+ * void *buf
+ * pointer to a buffer from where the data is sent.
+ * PRInt32 amount
+ * the size of 'buf' (in bytes)
+ * PRIntn flags
+ * (OBSOLETE - must always be zero)
+ * PRIntervalTime timeout
+ * Time limit for completion of the send operation.
+ * OUTPUTS:
+ * None
+ * RETURN: PRInt32
+ * A positive number indicates the number of bytes successfully processed.
+ * This number must always equal 'amount'. A -1 is an indication that the
+ * operation failed. The reason for the failure is obtained by calling
+ * PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_RecvFrom
+ * DESCRIPTION:
+ * Receive up to a specified number of bytes from socket which may
+ * or may not be connected.
+ * The operation will block until one or more bytes are
+ * transferred, a time out has occurred, or there is an error.
+ * No more than 'amount' bytes will be transferred.
+ * INPUTS:
+ * PRFileDesc *fd
+ * points to a PRFileDesc object representing a socket.
+ * void *buf
+ * pointer to a buffer to hold the data received.
+ * PRInt32 amount
+ * the size of 'buf' (in bytes)
+ * PRIntn flags
+ * (OBSOLETE - must always be zero)
+ * PRNetAddr *addr
+ * Specifies the address of the sending peer. It may be NULL.
+ * PRIntervalTime timeout
+ * Time limit for completion of the receive operation.
+ * OUTPUTS:
+ * None
+ * RETURN: PRInt32
+ * a positive number indicates the number of bytes actually received.
+ * 0 means the network connection is closed.
+ * -1 indicates a failure. The reason for the failure is obtained
+ * by calling PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRInt32) PR_RecvFrom(
+ PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRIntervalTime timeout);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_SendTo
+ * DESCRIPTION:
+ * Send a specified number of bytes from an unconnected socket.
+ * The operation will block until all bytes are
+ * sent, a time out has occurred, or there is an error.
+ * INPUTS:
+ * PRFileDesc *fd
+ * points to a PRFileDesc object representing an unconnected socket.
+ * void *buf
+ * pointer to a buffer from where the data is sent.
+ * PRInt32 amount
+ * the size of 'buf' (in bytes)
+ * PRIntn flags
+ * (OBSOLETE - must always be zero)
+ * PRNetAddr *addr
+ * Specifies the address of the peer.
+.* PRIntervalTime timeout
+ * Time limit for completion of the send operation.
+ * OUTPUTS:
+ * None
+ * RETURN: PRInt32
+ * A positive number indicates the number of bytes successfully sent.
+ * -1 indicates a failure. The reason for the failure is obtained
+ * by calling PR_GetError().
+ **************************************************************************
+ */
+
+NSPR_API(PRInt32) PR_SendTo(
+ PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRIntervalTime timeout);
+
+/*
+*************************************************************************
+** FUNCTION: PR_TransmitFile
+** DESCRIPTION:
+** Transmitfile sends a complete file (sourceFile) across a socket
+** (networkSocket). If headers is non-NULL, the headers will be sent across
+** the socket prior to sending the file.
+**
+** Optionally, the PR_TRANSMITFILE_CLOSE_SOCKET flag may be passed to
+** transmitfile. This flag specifies that transmitfile should close the
+** socket after sending the data.
+**
+** INPUTS:
+** PRFileDesc *networkSocket
+** The socket to send data over
+** PRFileDesc *sourceFile
+** The file to send
+** const void *headers
+** A pointer to headers to be sent before sending data
+** PRInt32 hlen
+** length of header buffers in bytes.
+** PRTransmitFileFlags flags
+** If the flags indicate that the connection should be closed,
+** it will be done immediately after transferring the file, unless
+** the operation is unsuccessful.
+.* PRIntervalTime timeout
+ * Time limit for completion of the transmit operation.
+**
+** RETURNS:
+** Returns the number of bytes written or -1 if the operation failed.
+** If an error occurs while sending the file, the PR_TRANSMITFILE_CLOSE_
+** SOCKET flag is ignored. The reason for the failure is obtained
+** by calling PR_GetError().
+**************************************************************************
+*/
+
+NSPR_API(PRInt32) PR_TransmitFile(
+ PRFileDesc *networkSocket, PRFileDesc *sourceFile,
+ const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
+ PRIntervalTime timeout);
+
+/*
+*************************************************************************
+** FUNCTION: PR_SendFile
+** DESCRIPTION:
+** PR_SendFile sends data from a file (sendData->fd) across a socket
+** (networkSocket). If specified, a header and/or trailer buffer are sent
+** before and after the file, respectively. The file offset, number of bytes
+** of file data to send, the header and trailer buffers are specified in the
+** sendData argument.
+**
+** Optionally, if the PR_TRANSMITFILE_CLOSE_SOCKET flag is passed, the
+** socket is closed after successfully sending the data.
+**
+** INPUTS:
+** PRFileDesc *networkSocket
+** The socket to send data over
+** PRSendFileData *sendData
+** Contains the FD, file offset and length, header and trailer
+** buffer specifications.
+** PRTransmitFileFlags flags
+** If the flags indicate that the connection should be closed,
+** it will be done immediately after transferring the file, unless
+** the operation is unsuccessful.
+.* PRIntervalTime timeout
+ * Time limit for completion of the send operation.
+**
+** RETURNS:
+** Returns the number of bytes written or -1 if the operation failed.
+** If an error occurs while sending the file, the PR_TRANSMITFILE_CLOSE_
+** SOCKET flag is ignored. The reason for the failure is obtained
+** by calling PR_GetError().
+**************************************************************************
+*/
+
+struct PRSendFileData {
+ PRFileDesc *fd; /* file to send */
+ PRUint32 file_offset; /* file offset */
+ PRSize file_nbytes; /* number of bytes of file data to send */
+ /* if 0, send data from file_offset to */
+ /* end-of-file. */
+ const void *header; /* header buffer */
+ PRInt32 hlen; /* header len */
+ const void *trailer; /* trailer buffer */
+ PRInt32 tlen; /* trailer len */
+};
+
+
+NSPR_API(PRInt32) PR_SendFile(
+ PRFileDesc *networkSocket, PRSendFileData *sendData,
+ PRTransmitFileFlags flags, PRIntervalTime timeout);
+
+/*
+*************************************************************************
+** FUNCTION: PR_AcceptRead
+** DESCRIPTION:
+** AcceptRead accepts a new connection, returns the newly created
+** socket's descriptor and also returns the connecting peer's address.
+** AcceptRead, as its name suggests, also receives the first block of data
+** sent by the peer.
+**
+** INPUTS:
+** PRFileDesc *listenSock
+** A socket descriptor that has been called with the PR_Listen()
+** function, also known as the rendezvous socket.
+** void *buf
+** A pointer to a buffer to receive data sent by the client. This
+** buffer must be large enough to receive <amount> bytes of data
+** and two PRNetAddr structures, plus an extra 32 bytes. See:
+** PR_ACCEPT_READ_BUF_OVERHEAD.
+** PRInt32 amount
+** The number of bytes of client data to receive. Does not include
+** the size of the PRNetAddr structures. If 0, no data will be read
+** from the client.
+** PRIntervalTime timeout
+** The timeout interval only applies to the read portion of the
+** operation. PR_AcceptRead will block indefinitely until the
+** connection is accepted; the read will timeout after the timeout
+** interval elapses.
+** OUTPUTS:
+** PRFileDesc **acceptedSock
+** The file descriptor for the newly connected socket. This parameter
+** will only be valid if the function return does not indicate failure.
+** PRNetAddr **peerAddr,
+** The address of the remote socket. This parameter will only be
+** valid if the function return does not indicate failure. The
+** returned address is not guaranteed to be properly aligned.
+**
+** RETURNS:
+** The number of bytes read from the client or -1 on failure. The reason
+** for the failure is obtained by calling PR_GetError().
+**************************************************************************
+**/
+/* define buffer overhead constant. Add this value to the user's
+** data length when allocating a buffer to accept data.
+** Example:
+** #define USER_DATA_SIZE 10
+** char buf[USER_DATA_SIZE + PR_ACCEPT_READ_BUF_OVERHEAD];
+** bytesRead = PR_AcceptRead( s, fd, &a, &p, USER_DATA_SIZE, ...);
+*/
+#define PR_ACCEPT_READ_BUF_OVERHEAD (32+(2*sizeof(PRNetAddr)))
+
+NSPR_API(PRInt32) PR_AcceptRead(
+ PRFileDesc *listenSock, PRFileDesc **acceptedSock,
+ PRNetAddr **peerAddr, void *buf, PRInt32 amount, PRIntervalTime timeout);
+
+/*
+*************************************************************************
+** FUNCTION: PR_NewTCPSocketPair
+** DESCRIPTION:
+** Create a new TCP socket pair. The returned descriptors can be used
+** interchangeably; they are interconnected full-duplex descriptors: data
+** written to one can be read from the other and vice-versa.
+**
+** INPUTS:
+** None
+** OUTPUTS:
+** PRFileDesc *fds[2]
+** The file descriptor pair for the newly created TCP sockets.
+** RETURN: PRStatus
+** Upon successful completion of TCP socket pair, PR_NewTCPSocketPair
+** returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further
+** failure information can be obtained by calling PR_GetError().
+** XXX can we implement this on windoze and mac?
+**************************************************************************
+**/
+NSPR_API(PRStatus) PR_NewTCPSocketPair(PRFileDesc *fds[2]);
+
+/*
+*************************************************************************
+** FUNCTION: PR_GetSockName
+** DESCRIPTION:
+** Get socket name. Return the network address for this socket.
+**
+** INPUTS:
+** PRFileDesc *fd
+** Points to a PRFileDesc object representing the socket.
+** OUTPUTS:
+** PRNetAddr *addr
+** Returns the address of the socket in its own communication space.
+** RETURN: PRStatus
+** Upon successful completion, PR_GetSockName returns PR_SUCCESS.
+** Otherwise, it returns PR_FAILURE. Further failure information can
+** be obtained by calling PR_GetError().
+**************************************************************************
+**/
+NSPR_API(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr);
+
+/*
+*************************************************************************
+** FUNCTION: PR_GetPeerName
+** DESCRIPTION:
+** Get name of the connected peer. Return the network address for the
+** connected peer socket.
+**
+** INPUTS:
+** PRFileDesc *fd
+** Points to a PRFileDesc object representing the connected peer.
+** OUTPUTS:
+** PRNetAddr *addr
+** Returns the address of the connected peer in its own communication
+** space.
+** RETURN: PRStatus
+** Upon successful completion, PR_GetPeerName returns PR_SUCCESS.
+** Otherwise, it returns PR_FAILURE. Further failure information can
+** be obtained by calling PR_GetError().
+**************************************************************************
+**/
+NSPR_API(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr);
+
+NSPR_API(PRStatus) PR_GetSocketOption(
+ PRFileDesc *fd, PRSocketOptionData *data);
+
+NSPR_API(PRStatus) PR_SetSocketOption(
+ PRFileDesc *fd, const PRSocketOptionData *data);
+
+/*
+ *********************************************************************
+ *
+ * File descriptor inheritance
+ *
+ *********************************************************************
+ */
+
+/*
+ ************************************************************************
+ * FUNCTION: PR_SetFDInheritable
+ * DESCRIPTION:
+ * Set the inheritance attribute of a file descriptor.
+ *
+ * INPUTS:
+ * PRFileDesc *fd
+ * Points to a PRFileDesc object.
+ * PRBool inheritable
+ * If PR_TRUE, the file descriptor fd is set to be inheritable
+ * by a child process. If PR_FALSE, the file descriptor is set
+ * to be not inheritable by a child process.
+ * RETURN: PRStatus
+ * Upon successful completion, PR_SetFDInheritable returns PR_SUCCESS.
+ * Otherwise, it returns PR_FAILURE. Further failure information can
+ * be obtained by calling PR_GetError().
+ *************************************************************************
+ */
+NSPR_API(PRStatus) PR_SetFDInheritable(
+ PRFileDesc *fd,
+ PRBool inheritable);
+
+/*
+ ************************************************************************
+ * FUNCTION: PR_GetInheritedFD
+ * DESCRIPTION:
+ * Get an inherited file descriptor with the specified name.
+ *
+ * INPUTS:
+ * const char *name
+ * The name of the inherited file descriptor.
+ * RETURN: PRFileDesc *
+ * Upon successful completion, PR_GetInheritedFD returns the
+ * inherited file descriptor with the specified name. Otherwise,
+ * it returns NULL. Further failure information can be obtained
+ * by calling PR_GetError().
+ *************************************************************************
+ */
+NSPR_API(PRFileDesc *) PR_GetInheritedFD(const char *name);
+
+/*
+ *********************************************************************
+ *
+ * Memory-mapped files
+ *
+ *********************************************************************
+ */
+
+typedef struct PRFileMap PRFileMap;
+
+/*
+ * protection options for read and write accesses of a file mapping
+ */
+typedef enum PRFileMapProtect {
+ PR_PROT_READONLY, /* read only */
+ PR_PROT_READWRITE, /* readable, and write is shared */
+ PR_PROT_WRITECOPY /* readable, and write is private (copy-on-write) */
+} PRFileMapProtect;
+
+NSPR_API(PRFileMap *) PR_CreateFileMap(
+ PRFileDesc *fd,
+ PRInt64 size,
+ PRFileMapProtect prot);
+
+/*
+ * return the alignment (in bytes) of the offset argument to PR_MemMap
+ */
+NSPR_API(PRInt32) PR_GetMemMapAlignment(void);
+
+NSPR_API(void *) PR_MemMap(
+ PRFileMap *fmap,
+ PROffset64 offset, /* must be aligned and sized according to the
+ * return value of PR_GetMemMapAlignment() */
+ PRUint32 len);
+
+NSPR_API(PRStatus) PR_MemUnmap(void *addr, PRUint32 len);
+
+NSPR_API(PRStatus) PR_CloseFileMap(PRFileMap *fmap);
+
+/*
+ ******************************************************************
+ *
+ * Interprocess communication
+ *
+ ******************************************************************
+ */
+
+/*
+ * Creates an anonymous pipe and returns file descriptors for the
+ * read and write ends of the pipe.
+ */
+
+NSPR_API(PRStatus) PR_CreatePipe(
+ PRFileDesc **readPipe,
+ PRFileDesc **writePipe
+);
+
+/************************************************************************/
+/************** The following definitions are for poll ******************/
+/************************************************************************/
+
+struct PRPollDesc {
+ PRFileDesc* fd;
+ PRInt16 in_flags;
+ PRInt16 out_flags;
+};
+
+/*
+** Bit values for PRPollDesc.in_flags or PRPollDesc.out_flags. Binary-or
+** these together to produce the desired poll request.
+*/
+
+#if defined(_PR_POLL_BACKCOMPAT)
+
+#include <poll.h>
+#define PR_POLL_READ POLLIN
+#define PR_POLL_WRITE POLLOUT
+#define PR_POLL_EXCEPT POLLPRI
+#define PR_POLL_ERR POLLERR /* only in out_flags */
+#define PR_POLL_NVAL POLLNVAL /* only in out_flags when fd is bad */
+#define PR_POLL_HUP POLLHUP /* only in out_flags */
+
+#else /* _PR_POLL_BACKCOMPAT */
+
+#define PR_POLL_READ 0x1
+#define PR_POLL_WRITE 0x2
+#define PR_POLL_EXCEPT 0x4
+#define PR_POLL_ERR 0x8 /* only in out_flags */
+#define PR_POLL_NVAL 0x10 /* only in out_flags when fd is bad */
+#define PR_POLL_HUP 0x20 /* only in out_flags */
+
+#endif /* _PR_POLL_BACKCOMPAT */
+
+/*
+*************************************************************************
+** FUNCTION: PR_Poll
+** DESCRIPTION:
+**
+** The call returns as soon as I/O is ready on one or more of the underlying
+** socket objects. A count of the number of ready descriptors is
+** returned unless a timeout occurs in which case zero is returned.
+**
+** PRPollDesc.fd should be set to a pointer to a PRFileDesc object
+** representing a socket. This field can be set to NULL to indicate to
+** PR_Poll that this PRFileDesc object should be ignored.
+** PRPollDesc.in_flags should be set to the desired request
+** (read/write/except or some combination). Upon successful return from
+** this call PRPollDesc.out_flags will be set to indicate what kind of
+** i/o can be performed on the respective descriptor. PR_Poll() uses the
+** out_flags fields as scratch variables during the call. If PR_Poll()
+** returns 0 or -1, the out_flags fields do not contain meaningful values
+** and must not be used.
+**
+** INPUTS:
+** PRPollDesc *pds A pointer to an array of PRPollDesc
+**
+** PRIntn npds The number of elements in the array
+** If this argument is zero PR_Poll is
+** equivalent to a PR_Sleep(timeout).
+**
+** PRIntervalTime timeout Amount of time the call will block waiting
+** for I/O to become ready. If this time expires
+** w/o any I/O becoming ready, the result will
+** be zero.
+**
+** OUTPUTS: None
+** RETURN:
+** PRInt32 Number of PRPollDesc's with events or zero
+** if the function timed out or -1 on failure.
+** The reason for the failure is obtained by
+** calling PR_GetError().
+**************************************************************************
+*/
+NSPR_API(PRInt32) PR_Poll(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout);
+
+/*
+**************************************************************************
+**
+** Pollable events
+**
+** A pollable event is a special kind of file descriptor.
+** The only I/O operation you can perform on a pollable event
+** is to poll it with the PR_POLL_READ flag. You can't
+** read from or write to a pollable event.
+**
+** The purpose of a pollable event is to combine event waiting
+** with I/O waiting in a single PR_Poll call. Pollable events
+** are implemented using a pipe or a pair of TCP sockets
+** connected via the loopback address, therefore setting and
+** waiting for pollable events are expensive operating system
+** calls. Do not use pollable events for general thread
+** synchronization. Use condition variables instead.
+**
+** A pollable event has two states: set and unset. Events
+** are not queued, so there is no notion of an event count.
+** A pollable event is either set or unset.
+**
+** A new pollable event is created by a PR_NewPollableEvent
+** call and is initially in the unset state.
+**
+** PR_WaitForPollableEvent blocks the calling thread until
+** the pollable event is set, and then it atomically unsets
+** the pollable event before it returns.
+**
+** To set a pollable event, call PR_SetPollableEvent.
+**
+** One can call PR_Poll with the PR_POLL_READ flag on a pollable
+** event. When the pollable event is set, PR_Poll returns with
+** the PR_POLL_READ flag set in the out_flags.
+**
+** To close a pollable event, call PR_DestroyPollableEvent
+** (not PR_Close).
+**
+**************************************************************************
+*/
+
+NSPR_API(PRFileDesc *) PR_NewPollableEvent(void);
+
+NSPR_API(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event);
+
+NSPR_API(PRStatus) PR_SetPollableEvent(PRFileDesc *event);
+
+NSPR_API(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event);
+
+PR_END_EXTERN_C
+
+#endif /* prio_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/pripcsem.h b/src/libs/xpcom18a4/nsprpub/pr/include/pripcsem.h
new file mode 100644
index 00000000..c7450f3a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/pripcsem.h
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: pripcsem.h
+ *
+ * Description: named semaphores for interprocess
+ * synchronization
+ *
+ * Unrelated processes obtain access to a shared semaphore
+ * by specifying its name.
+ *
+ * Our goal is to support named semaphores on at least
+ * Unix and Win32 platforms. The implementation will use
+ * one of the three native semaphore APIs: POSIX, System V,
+ * and Win32.
+ *
+ * Because POSIX named semaphores have kernel persistence,
+ * we are forced to have a delete function in this API.
+ */
+
+#ifndef pripcsem_h___
+#define pripcsem_h___
+
+#include "prtypes.h"
+#include "prio.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_OpenSemaphore VBoxNsprPR_OpenSemaphore
+#define PR_WaitSemaphore VBoxNsprPR_WaitSemaphore
+#define PR_PostSemaphore VBoxNsprPR_PostSemaphore
+#define PR_CloseSemaphore VBoxNsprPR_CloseSemaphore
+#define PR_DeleteSemaphore VBoxNsprPR_DeleteSemaphore
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * PRSem is an opaque structure that represents a named
+ * semaphore.
+ */
+typedef struct PRSem PRSem;
+
+/*
+ * PR_OpenSemaphore --
+ *
+ * Create or open a named semaphore with the specified name.
+ * A handle to the semaphore is returned.
+ *
+ * If the named semaphore doesn't exist and the PR_SEM_CREATE
+ * flag is specified, the named semaphore is created. The
+ * created semaphore needs to be removed from the system with
+ * a PR_DeleteSemaphore call.
+ *
+ * If PR_SEM_CREATE is specified, the third argument is the
+ * access permission bits of the new semaphore (same
+ * interpretation as the mode argument to PR_Open) and the
+ * fourth argument is the initial value of the new semaphore.
+ * If PR_SEM_CREATE is not specified, the third and fourth
+ * arguments are ignored.
+ */
+
+#define PR_SEM_CREATE 0x1 /* create if not exist */
+#define PR_SEM_EXCL 0x2 /* fail if already exists */
+
+NSPR_API(PRSem *) PR_OpenSemaphore(
+ const char *name, PRIntn flags, PRIntn mode, PRUintn value);
+
+/*
+ * PR_WaitSemaphore --
+ *
+ * If the value of the semaphore is > 0, decrement the value and return.
+ * If the value is 0, sleep until the value becomes > 0, then decrement
+ * the value and return.
+ *
+ * The "test and decrement" operation is performed atomically.
+ */
+
+NSPR_API(PRStatus) PR_WaitSemaphore(PRSem *sem);
+
+/*
+ * PR_PostSemaphore --
+ *
+ * Increment the value of the named semaphore by 1.
+ */
+
+NSPR_API(PRStatus) PR_PostSemaphore(PRSem *sem);
+
+/*
+ * PR_CloseSemaphore --
+ *
+ * Close a named semaphore handle.
+ */
+
+NSPR_API(PRStatus) PR_CloseSemaphore(PRSem *sem);
+
+/*
+ * PR_DeleteSemaphore --
+ *
+ * Remove a named semaphore from the system.
+ */
+
+NSPR_API(PRStatus) PR_DeleteSemaphore(const char *name);
+
+PR_END_EXTERN_C
+
+#endif /* pripcsem_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/include/private/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/include/private/Makefile.in
new file mode 100644
index 00000000..180393b1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/Makefile.in
@@ -0,0 +1,61 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+RELEASE_HEADERS = pprio.h pprthred.h prpriv.h
+RELEASE_HEADERS := $(addprefix $(srcdir)/, $(RELEASE_HEADERS))
+RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/private
+
+HEADERS = $(RELEASE_HEADERS) $(srcdir)/pprmwait.h $(srcdir)/primpl.h
+
+include_subdir = private
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(RELEASE_HEADERS)
+ $(INSTALL) -m 444 $(RELEASE_HEADERS) $(dist_includedir)/private
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/pprio.h b/src/libs/xpcom18a4/nsprpub/pr/include/private/pprio.h
new file mode 100644
index 00000000..f1d11360
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/pprio.h
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: pprio.h
+**
+** Description: Private definitions for I/O related structures
+*/
+
+#ifndef pprio_h___
+#define pprio_h___
+
+#include "prtypes.h"
+#include "prio.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_GetFileMethods VBoxNsprPR_GetFileMethods
+#define PR_GetTCPMethods VBoxNsprPR_GetTCPMethods
+#define PR_GetUDPMethods VBoxNsprPR_GetUDPMethods
+#define PR_GetPipeMethods VBoxNsprPR_GetPipeMethods
+#define PR_FileDesc2NativeHandle VBoxNsprPR_FileDesc2NativeHandle
+#define PR_ChangeFileDescNativeHandle VBoxNsprPR_ChangeFileDescNativeHandle
+#define PR_AllocFileDesc VBoxNsprPR_AllocFileDesc
+#define PR_FreeFileDesc VBoxNsprPR_FreeFileDesc
+#define PR_ImportFile VBoxNsprPR_ImportFile
+#define PR_ImportPipe VBoxNsprPR_ImportPipe
+#define PR_ImportTCPSocket VBoxNsprPR_ImportTCPSocket
+#define PR_ImportUDPSocket VBoxNsprPR_ImportUDPSocket
+#define PR_CreateSocketPollFd VBoxNsprPR_CreateSocketPollFd
+#define PR_DestroySocketPollFd VBoxNsprPR_DestroySocketPollFd
+#define PR_Socket VBoxNsprPR_Socket
+#define PR_LockFile VBoxNsprPR_LockFile
+#define PR_TLockFile VBoxNsprPR_TLockFile
+#define PR_UnlockFile VBoxNsprPR_UnlockFile
+#define PR_EmulateAcceptRead VBoxNsprPR_EmulateAcceptRead
+#define PR_EmulateSendFile VBoxNsprPR_EmulateSendFile
+#define PR_NTFast_AcceptRead VBoxNsprPR_NTFast_AcceptRead
+#define PR_NTFast_AcceptRead_WithTimeoutCallback VBoxNsprPR_NTFast_AcceptRead_WithTimeoutCallback
+#define PR_NTFast_Accept VBoxNsprPR_NTFast_Accept
+#define PR_NTFast_UpdateAcceptContext VBoxNsprPR_NTFast_UpdateAcceptContext
+#define PR_NT_CancelIo VBoxNsprPR_NT_CancelIo
+#define PR_Init_Log VBoxNsprPR_Init_Log
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/************************************************************************/
+/************************************************************************/
+
+/* Return the method tables for files, tcp sockets and udp sockets */
+NSPR_API(const PRIOMethods*) PR_GetFileMethods(void);
+NSPR_API(const PRIOMethods*) PR_GetTCPMethods(void);
+NSPR_API(const PRIOMethods*) PR_GetUDPMethods(void);
+NSPR_API(const PRIOMethods*) PR_GetPipeMethods(void);
+
+/*
+** Convert a NSPR Socket Handle to a Native Socket handle.
+** This function will be obsoleted with the next release; avoid using it.
+*/
+NSPR_API(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *);
+NSPR_API(void) PR_ChangeFileDescNativeHandle(PRFileDesc *, PRInt32);
+NSPR_API(PRFileDesc*) PR_AllocFileDesc(PRInt32 osfd,
+ const PRIOMethods *methods);
+NSPR_API(void) PR_FreeFileDesc(PRFileDesc *fd);
+/*
+** Import an existing OS file to NSPR.
+*/
+NSPR_API(PRFileDesc*) PR_ImportFile(PRInt32 osfd);
+NSPR_API(PRFileDesc*) PR_ImportPipe(PRInt32 osfd);
+NSPR_API(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd);
+NSPR_API(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd);
+
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_CreateSocketPollFd
+ * DESCRIPTION:
+ * Create a PRFileDesc wrapper for a native socket handle, for use with
+ * PR_Poll only
+ * INPUTS:
+ * None
+ * OUTPUTS:
+ * None
+ * RETURN: PRFileDesc*
+ * Upon successful completion, PR_CreateSocketPollFd returns a pointer
+ * to the PRFileDesc created for the native socket handle
+ * Returns a NULL pointer if the create of a new PRFileDesc failed
+ *
+ **************************************************************************
+ */
+
+NSPR_API(PRFileDesc*) PR_CreateSocketPollFd(PRInt32 osfd);
+
+/*
+ *************************************************************************
+ * FUNCTION: PR_DestroySocketPollFd
+ * DESCRIPTION:
+ * Destroy the PRFileDesc wrapper created by PR_CreateSocketPollFd
+ * INPUTS:
+ * None
+ * OUTPUTS:
+ * None
+ * RETURN: PRFileDesc*
+ * Upon successful completion, PR_DestroySocketPollFd returns
+ * PR_SUCCESS, else PR_FAILURE
+ *
+ **************************************************************************
+ */
+
+NSPR_API(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd);
+
+
+/*
+** Macros for PR_Socket
+**
+** Socket types: PR_SOCK_STREAM, PR_SOCK_DGRAM
+*/
+
+#ifdef WIN32
+
+#define PR_SOCK_STREAM 1
+#define PR_SOCK_DGRAM 2
+
+#else /* WIN32 */
+
+#define PR_SOCK_STREAM SOCK_STREAM
+#define PR_SOCK_DGRAM SOCK_DGRAM
+
+#endif /* WIN32 */
+
+/*
+** Create a new Socket; this function is obsolete.
+*/
+NSPR_API(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto);
+
+/* FUNCTION: PR_LockFile
+** DESCRIPTION:
+** Lock a file for exclusive access.
+** RETURNS:
+** PR_SUCCESS when the lock is held
+** PR_FAILURE otherwise
+*/
+NSPR_API(PRStatus) PR_LockFile(PRFileDesc *fd);
+
+/* FUNCTION: PR_TLockFile
+** DESCRIPTION:
+** Test and Lock a file for exclusive access. Do not block if the
+** file cannot be locked immediately.
+** RETURNS:
+** PR_SUCCESS when the lock is held
+** PR_FAILURE otherwise
+*/
+NSPR_API(PRStatus) PR_TLockFile(PRFileDesc *fd);
+
+/* FUNCTION: PR_UnlockFile
+** DESCRIPTION:
+** Unlock a file which has been previously locked successfully by this
+** process.
+** RETURNS:
+** PR_SUCCESS when the lock is released
+** PR_FAILURE otherwise
+*/
+NSPR_API(PRStatus) PR_UnlockFile(PRFileDesc *fd);
+
+/*
+** Emulate acceptread by accept and recv.
+*/
+NSPR_API(PRInt32) PR_EmulateAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
+ PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout);
+
+/*
+** Emulate sendfile by reading from the file and writing to the socket.
+** The file is memory-mapped if memory-mapped files are supported.
+*/
+NSPR_API(PRInt32) PR_EmulateSendFile(
+ PRFileDesc *networkSocket, PRSendFileData *sendData,
+ PRTransmitFileFlags flags, PRIntervalTime timeout);
+
+#ifdef WIN32
+/* FUNCTION: PR_NTFast_AcceptRead
+** DESCRIPTION:
+** NT has the notion of an "accept context", which is only needed in
+** order to make certain calls. By default, a socket connected via
+** AcceptEx can only do a limited number of things without updating
+** the acceptcontext. The generic version of PR_AcceptRead always
+** updates the accept context. This version does not.
+**/
+NSPR_API(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
+ PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime t);
+
+typedef void (*_PR_AcceptTimeoutCallback)(void *);
+
+/* FUNCTION: PR_NTFast_AcceptRead_WithTimeoutCallback
+** DESCRIPTION:
+** The AcceptEx call combines the accept with the read function. However,
+** our daemon threads need to be able to wakeup and reliably flush their
+** log buffers if the Accept times out. However, with the current blocking
+** interface to AcceptRead, there is no way for us to timeout the Accept;
+** this is because when we timeout the Read, we can close the newly
+** socket and continue; but when we timeout the accept itself, there is no
+** new socket to timeout. So instead, this version of the function is
+** provided. After the initial timeout period elapses on the accept()
+** portion of the function, it will call the callback routine and then
+** continue the accept. If the timeout occurs on the read, it will
+** close the connection and return error.
+*/
+NSPR_API(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback(
+ PRFileDesc *sd,
+ PRFileDesc **nd,
+ PRNetAddr **raddr,
+ void *buf,
+ PRInt32 amount,
+ PRIntervalTime t,
+ _PR_AcceptTimeoutCallback callback,
+ void *callback_arg);
+
+/* FUNCTION: PR_NTFast_Accept
+** DESCRIPTION:
+** NT has the notion of an "accept context", which is only needed in
+** order to make certain calls. By default, a socket connected via
+** AcceptEx can only do a limited number of things without updating
+** the acceptcontext. The generic version of PR_Accept always
+** updates the accept context. This version does not.
+**/
+NSPR_API(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr,
+ PRIntervalTime timeout);
+
+/* FUNCTION: PR_NTFast_Update
+** DESCRIPTION:
+** For sockets accepted with PR_NTFast_Accept or PR_NTFastAcceptRead,
+** this function will update the accept context for those sockets,
+** so that the socket can make general purpose socket calls.
+** Without calling this, the only operations supported on the socket
+** Are PR_Read, PR_Write, PR_Transmitfile, and PR_Close.
+*/
+NSPR_API(void) PR_NTFast_UpdateAcceptContext(PRFileDesc *acceptSock,
+ PRFileDesc *listenSock);
+
+
+/* FUNCTION: PR_NT_CancelIo
+** DESCRIPTION:
+** Cancel IO operations on fd.
+*/
+NSPR_API(PRStatus) PR_NT_CancelIo(PRFileDesc *fd);
+
+
+#endif /* WIN32 */
+
+/*
+** Need external access to this on Mac so we can first set up our faux
+** environment vars
+*/
+#ifdef XP_MAC
+NSPR_API(void) PR_Init_Log(void);
+#endif
+
+
+PR_END_EXTERN_C
+
+#endif /* pprio_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/pprmwait.h b/src/libs/xpcom18a4/nsprpub/pr/include/private/pprmwait.h
new file mode 100644
index 00000000..e677f137
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/pprmwait.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#if defined(_PPRMWAIT_H)
+#else
+#define _PPRMWAIT_H
+
+#include "prlock.h"
+#include "prcvar.h"
+#include "prclist.h"
+#include "prthread.h"
+
+#define MAX_POLLING_INTERVAL 100
+#define _PR_POLL_COUNT_FUDGE 64
+#define MAX_POLLING_INTERVAL 100
+#define _PR_DEFAULT_HASH_LENGTH 59
+
+/*
+ * Our hash table resolves collisions by open addressing with
+ * double hashing. See Cormen, Leiserson, and Rivest,
+ * Introduction to Algorithms, p. 232, The MIT Press, 1990.
+ */
+
+#define _MW_HASH(a, m) ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m))
+#define _MW_HASH2(a, m) (1 + ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m - 2)))
+#define _MW_ABORTED(_rv) \
+ ((PR_FAILURE == (_rv)) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
+
+typedef enum {_prmw_success, _prmw_rehash, _prmw_error} _PR_HashStory;
+
+typedef struct _PRWaiterHash
+{
+ PRUint16 count; /* current number in hash table */
+ PRUint16 length; /* current size of the hash table */
+ PRRecvWait *recv_wait; /* hash table of receive wait objects */
+} _PRWaiterHash;
+
+typedef enum {_prmw_running, _prmw_stopping, _prmw_stopped} PRMWGroupState;
+
+struct PRWaitGroup
+{
+ PRCList group_link; /* all groups are linked to each other */
+ PRCList io_ready; /* list of I/O requests that are ready */
+ PRMWGroupState state; /* state of this group (so we can shut down) */
+
+ PRLock *ml; /* lock for synchronizing this wait group */
+ PRCondVar *io_taken; /* calling threads notify when they take I/O */
+ PRCondVar *io_complete; /* calling threads wait here for completions */
+ PRCondVar *new_business; /* polling thread waits here more work */
+ PRCondVar *mw_manage; /* used to manage group lists */
+ PRThread* poller; /* thread that's actually doing the poll() */
+ PRUint16 waiting_threads; /* number of threads waiting for recv */
+ PRUint16 polling_count; /* number of elements in the polling list */
+ PRUint32 p_timestamp; /* pseudo-time group had element removed */
+ PRPollDesc *polling_list; /* list poller builds for polling */
+ PRIntervalTime last_poll; /* last time we polled */
+ _PRWaiterHash *waiter; /* pointer to hash table of wait receive objects */
+
+#ifdef WINNT
+ /*
+ * On NT, idle threads are responsible for getting completed i/o.
+ * They need to add completed i/o to the io_ready list. Since
+ * idle threads cannot use nspr locks, we have to use an md lock
+ * to protect the io_ready list.
+ */
+ _MDLock mdlock; /* protect io_ready, waiter, and wait_list */
+ PRCList wait_list; /* used in place of io_complete. reuse
+ * waitQLinks in the PRThread structure. */
+#endif /* WINNT */
+};
+
+/**********************************************************************
+***********************************************************************
+******************** Wait group enumerations **************************
+***********************************************************************
+**********************************************************************/
+typedef struct _PRGlobalState
+{
+ PRCList group_list; /* master of the group list */
+ PRWaitGroup *group; /* the default (NULL) group */
+} _PRGlobalState;
+
+#ifdef WINNT
+extern PRStatus NT_HashRemoveInternal(PRWaitGroup *group, PRFileDesc *fd);
+#endif
+
+typedef enum {_PR_ENUM_UNSEALED=0, _PR_ENUM_SEALED=0x0eadface} _PREnumSeal;
+
+struct PRMWaitEnumerator
+{
+ PRWaitGroup *group; /* group this enumerator is bound to */
+ PRThread *thread; /* thread in midst of an enumeration */
+ _PREnumSeal seal; /* trying to detect deleted objects */
+ PRUint32 p_timestamp; /* when enumeration was (re)started */
+ PRRecvWait **waiter; /* pointer into hash table */
+ PRUintn index; /* position in hash table */
+ void *pad[4]; /* some room to grow */
+};
+
+#endif /* defined(_PPRMWAIT_H) */
+
+/* pprmwait.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/pprthred.h b/src/libs/xpcom18a4/nsprpub/pr/include/private/pprthred.h
new file mode 100644
index 00000000..fe6b0529
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/pprthred.h
@@ -0,0 +1,414 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef pprthred_h___
+#define pprthred_h___
+
+/*
+** API for PR private functions. These calls are to be used by internal
+** developers only.
+*/
+#include "nspr.h"
+
+#if defined(XP_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#include <os2.h>
+#endif
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_AttachThread VBoxNsprPR_AttachThread
+#define PR_DetachThread VBoxNsprPR_DetachThread
+#define PR_GetThreadID VBoxNsprPR_GetThreadID
+#define PR_SetThreadDumpProc VBoxNsprPR_SetThreadDumpProc
+#define PR_GetThreadAffinityMask VBoxNsprPR_GetThreadAffinityMask
+#define PR_SetThreadAffinityMask VBoxNsprPR_SetThreadAffinityMask
+#define PR_SetCPUAffinityMask VBoxNsprPR_SetCPUAffinityMask
+#define PR_ShowStatus VBoxNsprPR_ShowStatus
+#define PR_SetThreadRecycleMode VBoxNsprPR_SetThreadRecycleMode
+#define PR_CreateThreadGCAble VBoxNsprPR_CreateThreadGCAble
+#define PR_AttachThreadGCAble VBoxNsprPR_AttachThreadGCAble
+#define PR_SetThreadGCAble VBoxNsprPR_SetThreadGCAble
+#define PR_ClearThreadGCAble VBoxNsprPR_ClearThreadGCAble
+#define PR_SuspendAll VBoxNsprPR_SuspendAll
+#define PR_ResumeAll VBoxNsprPR_ResumeAll
+#define PR_GetSP VBoxNsprPR_GetSP
+#define PR_GetGCRegisters VBoxNsprPR_GetGCRegisters
+#define GetExecutionEnvironment VBoxNsprGetExecutionEnvironment
+#define SetExecutionEnvironment VBoxNsprSetExecutionEnvironment
+#define PR_EnumerateThreads VBoxNsprPR_EnumerateThreads
+#define PR_ThreadScanStackPointers VBoxNsprPR_ThreadScanStackPointers
+#define PR_ScanStackPointers VBoxNsprPR_ScanStackPointers
+#define PR_GetStackSpaceLeft VBoxNsprPR_GetStackSpaceLeft
+#define PR_NewNamedMonitor VBoxNsprPR_NewNamedMonitor
+#define PR_TestAndLock VBoxNsprPR_TestAndLock
+#define PR_TestAndEnterMonitor VBoxNsprPR_TestAndEnterMonitor
+#define PR_GetMonitorEntryCount VBoxNsprPR_GetMonitorEntryCount
+#define PR_CTestAndEnterMonitor VBoxNsprPR_CTestAndEnterMonitor
+#define PR_Mac_WaitForAsyncNotify VBoxNsprPR_Mac_WaitForAsyncNotify
+#define PR_Mac_PostAsyncNotify VBoxNsprPR_Mac_PostAsyncNotify
+#define PR_OS2_SetFloatExcpHandler VBoxNsprPR_OS2_SetFloatExcpHandler
+#define PR_OS2_UnsetFloatExcpHandler VBoxNsprPR_OS2_UnsetFloatExcpHandler
+#define PR_XLock VBoxNsprPR_XLock
+#define PR_XUnlock VBoxNsprPR_XUnlock
+#define PR_XIsLocked VBoxNsprPR_XIsLocked
+#define PR_XWait VBoxNsprPR_XWait
+#define PR_XNotify VBoxNsprPR_XNotify
+#define PR_XNotifyAll VBoxNsprPR_XNotifyAll
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*---------------------------------------------------------------------------
+** THREAD PRIVATE FUNCTIONS
+---------------------------------------------------------------------------*/
+
+/*
+** Associate a thread object with an existing native thread.
+** "type" is the type of thread object to attach
+** "priority" is the priority to assign to the thread
+** "stack" defines the shape of the threads stack
+**
+** This can return NULL if some kind of error occurs, or if memory is
+** tight. This call invokes "start(obj,arg)" and returns when the
+** function returns. The thread object is automatically destroyed.
+**
+** This call is not normally needed unless you create your own native
+** thread. PR_Init does this automatically for the primordial thread.
+*/
+NSPR_API(PRThread*) PR_AttachThread(PRThreadType type,
+ PRThreadPriority priority,
+ PRThreadStack *stack);
+
+/*
+** Detach the nspr thread from the currently executing native thread.
+** The thread object will be destroyed and all related data attached
+** to it. The exit procs will be invoked.
+**
+** This call is not normally needed unless you create your own native
+** thread. PR_Exit will automatially detach the nspr thread object
+** created by PR_Init for the primordial thread.
+**
+** This call returns after the nspr thread object is destroyed.
+*/
+NSPR_API(void) PR_DetachThread(void);
+
+/*
+** Get the id of the named thread. Each thread is assigned a unique id
+** when it is created or attached.
+*/
+NSPR_API(PRUint32) PR_GetThreadID(PRThread *thread);
+
+/*
+** Set the procedure that is called when a thread is dumped. The procedure
+** will be applied to the argument, arg, when called. Setting the procedure
+** to NULL effectively removes it.
+*/
+typedef void (*PRThreadDumpProc)(PRFileDesc *fd, PRThread *t, void *arg);
+NSPR_API(void) PR_SetThreadDumpProc(
+ PRThread* thread, PRThreadDumpProc dump, void *arg);
+
+/*
+** Get this thread's affinity mask. The affinity mask is a 32 bit quantity
+** marking a bit for each processor this process is allowed to run on.
+** The processor mask is returned in the mask argument.
+** The least-significant-bit represents processor 0.
+**
+** Returns 0 on success, -1 on failure.
+*/
+NSPR_API(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask);
+
+/*
+** Set this thread's affinity mask.
+**
+** Returns 0 on success, -1 on failure.
+*/
+NSPR_API(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask );
+
+/*
+** Set the default CPU Affinity mask.
+**
+*/
+NSPR_API(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask);
+
+/*
+** Show status of all threads to standard error output.
+*/
+NSPR_API(void) PR_ShowStatus(void);
+
+/*
+** Set thread recycle mode to on (1) or off (0)
+*/
+NSPR_API(void) PR_SetThreadRecycleMode(PRUint32 flag);
+
+
+/*---------------------------------------------------------------------------
+** THREAD PRIVATE FUNCTIONS FOR GARBAGE COLLECTIBLE THREADS
+---------------------------------------------------------------------------*/
+
+/*
+** Only Garbage collectible threads participate in resume all, suspend all and
+** enumeration operations. They are also different during creation when
+** platform specific action may be needed (For example, all Solaris GC able
+** threads are bound threads).
+*/
+
+/*
+** Same as PR_CreateThread except that the thread is marked as garbage
+** collectible.
+*/
+NSPR_API(PRThread*) PR_CreateThreadGCAble(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+
+/*
+** Same as PR_AttachThread except that the thread being attached is marked as
+** garbage collectible.
+*/
+NSPR_API(PRThread*) PR_AttachThreadGCAble(PRThreadType type,
+ PRThreadPriority priority,
+ PRThreadStack *stack);
+
+/*
+** Mark the thread as garbage collectible.
+*/
+NSPR_API(void) PR_SetThreadGCAble(void);
+
+/*
+** Unmark the thread as garbage collectible.
+*/
+NSPR_API(void) PR_ClearThreadGCAble(void);
+
+/*
+** This routine prevents all other GC able threads from running. This call is needed by
+** the garbage collector.
+*/
+NSPR_API(void) PR_SuspendAll(void);
+
+/*
+** This routine unblocks all other GC able threads that were suspended from running by
+** PR_SuspendAll(). This call is needed by the garbage collector.
+*/
+NSPR_API(void) PR_ResumeAll(void);
+
+/*
+** Return the thread stack pointer of the given thread.
+** Needed by the garbage collector.
+*/
+NSPR_API(void *) PR_GetSP(PRThread *thread);
+
+/*
+** Save the registers that the GC would find interesting into the thread
+** "t". isCurrent will be non-zero if the thread state that is being
+** saved is the currently executing thread. Return the address of the
+** first register to be scanned as well as the number of registers to
+** scan in "np".
+**
+** If "isCurrent" is non-zero then it is allowed for the thread context
+** area to be used as scratch storage to hold just the registers
+** necessary for scanning.
+**
+** This function simply calls the internal function _MD_HomeGCRegisters().
+*/
+NSPR_API(PRWord *) PR_GetGCRegisters(PRThread *t, int isCurrent, int *np);
+
+/*
+** (Get|Set)ExecutionEnvironent
+**
+** Used by Java to associate it's execution environment so garbage collector
+** can find it. If return is NULL, then it's probably not a collectable thread.
+**
+** There's no locking required around these calls.
+*/
+NSPR_API(void*) GetExecutionEnvironment(PRThread *thread);
+NSPR_API(void) SetExecutionEnvironment(PRThread* thread, void *environment);
+
+/*
+** Enumeration function that applies "func(thread,i,arg)" to each active
+** thread in the process. The enumerator returns PR_SUCCESS if the enumeration
+** should continue, any other value is considered failure, and enumeration
+** stops, returning the failure value from PR_EnumerateThreads.
+** Needed by the garbage collector.
+*/
+typedef PRStatus (PR_CALLBACK *PREnumerator)(PRThread *t, int i, void *arg);
+NSPR_API(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg);
+
+/*
+** Signature of a thread stack scanning function. It is applied to every
+** contiguous group of potential pointers within a thread. Count denotes the
+** number of pointers.
+*/
+typedef PRStatus
+(PR_CALLBACK *PRScanStackFun)(PRThread* t,
+ void** baseAddr, PRUword count, void* closure);
+
+/*
+** Applies scanFun to all contiguous groups of potential pointers
+** within a thread. This includes the stack, registers, and thread-local
+** data. If scanFun returns a status value other than PR_SUCCESS the scan
+** is aborted, and the status value is returned.
+*/
+NSPR_API(PRStatus)
+PR_ThreadScanStackPointers(PRThread* t,
+ PRScanStackFun scanFun, void* scanClosure);
+
+/*
+** Calls PR_ThreadScanStackPointers for every thread.
+*/
+NSPR_API(PRStatus)
+PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure);
+
+/*
+** Returns a conservative estimate on the amount of stack space left
+** on a thread in bytes, sufficient for making decisions about whether
+** to continue recursing or not.
+*/
+NSPR_API(PRUword)
+PR_GetStackSpaceLeft(PRThread* t);
+
+/*---------------------------------------------------------------------------
+** THREAD CPU PRIVATE FUNCTIONS
+---------------------------------------------------------------------------*/
+
+/*
+** Get a pointer to the primordial CPU.
+*/
+NSPR_API(struct _PRCPU *) _PR_GetPrimordialCPU(void);
+
+/*---------------------------------------------------------------------------
+** THREAD SYNCHRONIZATION PRIVATE FUNCTIONS
+---------------------------------------------------------------------------*/
+
+/*
+** Create a new named monitor (named for debugging purposes).
+** Monitors are re-entrant locks with a built-in condition variable.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low.
+*/
+NSPR_API(PRMonitor*) PR_NewNamedMonitor(const char* name);
+
+/*
+** Test and then lock the lock if it's not already locked by some other
+** thread. Return PR_FALSE if some other thread owned the lock at the
+** time of the call.
+*/
+NSPR_API(PRBool) PR_TestAndLock(PRLock *lock);
+
+/*
+** Test and then enter the mutex associated with the monitor if it's not
+** already entered by some other thread. Return PR_FALSE if some other
+** thread owned the mutex at the time of the call.
+*/
+NSPR_API(PRBool) PR_TestAndEnterMonitor(PRMonitor *mon);
+
+/*
+** Return the number of times that the current thread has entered the
+** mutex. Returns zero if the current thread has not entered the mutex.
+*/
+NSPR_API(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon);
+
+/*
+** Just like PR_CEnterMonitor except that if the monitor is owned by
+** another thread NULL is returned.
+*/
+NSPR_API(PRMonitor*) PR_CTestAndEnterMonitor(void *address);
+
+/*---------------------------------------------------------------------------
+** PLATFORM-SPECIFIC THREAD SYNCHRONIZATION FUNCTIONS
+---------------------------------------------------------------------------*/
+#if defined(XP_MAC)
+
+NSPR_API(void) PR_Mac_WaitForAsyncNotify(PRIntervalTime timeout);
+NSPR_API(void) PR_Mac_PostAsyncNotify(PRThread *thread);
+
+#endif /* XP_MAC */
+
+/*---------------------------------------------------------------------------
+** PLATFORM-SPECIFIC INITIALIZATION FUNCTIONS
+---------------------------------------------------------------------------*/
+#if defined(IRIX)
+/*
+** Irix specific initialization funtion to be called before PR_Init
+** is called by the application. Sets the CONF_INITUSERS and CONF_INITSIZE
+** attributes of the shared arena set up by nspr.
+**
+** The environment variables _NSPR_IRIX_INITUSERS and _NSPR_IRIX_INITSIZE
+** can also be used to set these arena attributes. If _NSPR_IRIX_INITUSERS
+** is set, but not _NSPR_IRIX_INITSIZE, the value of the CONF_INITSIZE
+** attribute of the nspr arena is scaled as a function of the
+** _NSPR_IRIX_INITUSERS value.
+**
+** If the _PR_Irix_Set_Arena_Params() is called in addition to setting the
+** environment variables, the values of the environment variables are used.
+**
+*/
+NSPR_API(void) _PR_Irix_Set_Arena_Params(PRInt32 initusers, PRInt32 initsize);
+
+#endif /* IRIX */
+
+#if defined(XP_OS2)
+/*
+** These functions need to be called at the start and end of a thread.
+** An EXCEPTIONREGISTRATIONRECORD must be declared on the stack and its
+** address passed to the two functions.
+*/
+NSPR_API(void) PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* e);
+NSPR_API(void) PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* e);
+#endif /* XP_OS2 */
+
+/* I think PR_GetMonitorEntryCount is useless. All you really want is this... */
+#define PR_InMonitor(m) (PR_GetMonitorEntryCount(m) > 0)
+
+/*---------------------------------------------------------------------------
+** Special X-Lock hack for client
+---------------------------------------------------------------------------*/
+
+#ifdef XP_UNIX
+extern void PR_XLock(void);
+extern void PR_XUnlock(void);
+extern PRBool PR_XIsLocked(void);
+#endif /* XP_UNIX */
+
+PR_END_EXTERN_C
+
+#endif /* pprthred_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/primpl.h b/src/libs/xpcom18a4/nsprpub/pr/include/private/primpl.h
new file mode 100644
index 00000000..cd8e46c4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/primpl.h
@@ -0,0 +1,2141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef primpl_h___
+#define primpl_h___
+
+/*
+ * HP-UX 10.10's pthread.h (DCE threads) includes dce/cma.h, which
+ * has:
+ * #define sigaction _sigaction_sys
+ * This macro causes chaos if signal.h gets included before pthread.h.
+ * To be safe, we include pthread.h first.
+ */
+
+#if defined(_PR_PTHREADS)
+#include <pthread.h>
+#endif
+
+#if defined(_PR_BTHREADS)
+#include <kernel/OS.h>
+#endif
+
+#ifdef WINNT
+/* Need to force service-pack 3 extensions to be defined by
+** setting _WIN32_WINNT to NT 4.0 for winsock.h, winbase.h, winnt.h.
+*/
+#ifndef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0400
+#elif (_WIN32_WINNT < 0x0400)
+ #undef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0400
+#endif /* _WIN32_WINNT */
+#endif /* WINNT */
+
+#include "nspr.h"
+#include "prpriv.h"
+
+typedef struct PRSegment PRSegment;
+
+#ifdef XP_MAC
+#include "prosdep.h"
+#include "probslet.h"
+#else
+#include "md/prosdep.h"
+#include "obsolete/probslet.h"
+#endif /* XP_MAC */
+
+#ifdef _PR_HAVE_POSIX_SEMAPHORES
+#include <semaphore.h>
+#elif defined(_PR_HAVE_SYSV_SEMAPHORES)
+#include <sys/sem.h>
+#endif
+
+/*************************************************************************
+***** A Word about Model Dependent Function Naming Convention ***********
+*************************************************************************/
+
+/*
+NSPR 2.0 must implement its function across a range of platforms
+including: MAC, Windows/16, Windows/95, Windows/NT, and several
+variants of Unix. Each implementation shares common code as well
+as having platform dependent portions. This standard describes how
+the model dependent portions are to be implemented.
+
+In header file pr/include/primpl.h, each publicly declared
+platform dependent function is declared as:
+
+NSPR_API void _PR_MD_FUNCTION( long arg1, long arg2 );
+#define _PR_MD_FUNCTION _MD_FUNCTION
+
+In header file pr/include/md/<platform>/_<platform>.h,
+each #define'd macro is redefined as one of:
+
+#define _MD_FUNCTION <blanks>
+#define _MD_FUNCTION <expanded macro>
+#define _MD_FUNCTION <osFunction>
+#define _MD_FUNCTION <_MD_Function>
+
+Where:
+
+<blanks> is no definition at all. In this case, the function is not implemented
+and is never called for this platform.
+For example:
+#define _MD_INIT_CPUS()
+
+<expanded macro> is a C language macro expansion.
+For example:
+#define _MD_CLEAN_THREAD(_thread) \
+ PR_BEGIN_MACRO \
+ PR_DestroyCondVar(_thread->md.asyncIOCVar); \
+ PR_DestroyLock(_thread->md.asyncIOLock); \
+ PR_END_MACRO
+
+<osFunction> is some function implemented by the host operating system.
+For example:
+#define _MD_EXIT exit
+
+<_MD_function> is the name of a function implemented for this platform in
+pr/src/md/<platform>/<soruce>.c file.
+For example:
+#define _MD_GETFILEINFO _MD_GetFileInfo
+
+In <source>.c, the implementation is:
+PR_IMPLEMENT(PRInt32) _MD_GetFileInfo(const char *fn, PRFileInfo *info);
+*/
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PT_FPrintStats VBoxNsprPT_FPrintStats
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct _MDLock _MDLock;
+typedef struct _MDCVar _MDCVar;
+typedef struct _MDSegment _MDSegment;
+typedef struct _MDThread _MDThread;
+typedef struct _MDThreadStack _MDThreadStack;
+typedef struct _MDSemaphore _MDSemaphore;
+typedef struct _MDDir _MDDir;
+#ifdef MOZ_UNICODE
+typedef struct _MDDirUTF16 _MDDirUTF16;
+#endif /* MOZ_UNICODE */
+typedef struct _MDFileDesc _MDFileDesc;
+typedef struct _MDProcess _MDProcess;
+typedef struct _MDFileMap _MDFileMap;
+
+#if defined(_PR_PTHREADS)
+
+/*
+** The following definitions are unique to implementing NSPR using pthreads.
+** Since pthreads defines most of the thread and thread synchronization
+** stuff, this is a pretty small set.
+*/
+
+#define PT_CV_NOTIFIED_LENGTH 6
+typedef struct _PT_Notified _PT_Notified;
+struct _PT_Notified
+{
+ PRIntn length; /* # of used entries in this structure */
+ struct
+ {
+ PRCondVar *cv; /* the condition variable notified */
+ PRIntn times; /* and the number of times notified */
+ } cv[PT_CV_NOTIFIED_LENGTH];
+ _PT_Notified *link; /* link to another of these | NULL */
+};
+
+/*
+ * bits defined for pthreads 'state' field
+ */
+#define PT_THREAD_DETACHED 0x01 /* thread can't be joined */
+#define PT_THREAD_GLOBAL 0x02 /* a global thread (unlikely) */
+#define PT_THREAD_SYSTEM 0x04 /* system (not user) thread */
+#define PT_THREAD_PRIMORD 0x08 /* this is the primordial thread */
+#define PT_THREAD_ABORTED 0x10 /* thread has been interrupted */
+#define PT_THREAD_GCABLE 0x20 /* thread is garbage collectible */
+#define PT_THREAD_SUSPENDED 0x40 /* thread has been suspended */
+#define PT_THREAD_FOREIGN 0x80 /* thread is not one of ours */
+#define PT_THREAD_BOUND 0x100 /* a bound-global thread */
+
+#define _PT_THREAD_INTERRUPTED(thr) \
+ (!(thr->interrupt_blocked) && (thr->state & PT_THREAD_ABORTED))
+#define _PT_THREAD_BLOCK_INTERRUPT(thr) \
+ (thr->interrupt_blocked = 1)
+#define _PT_THREAD_UNBLOCK_INTERRUPT(thr) \
+ (thr->interrupt_blocked = 0)
+
+#ifdef GC_LEAK_DETECTOR
+/* All threads are GCable. */
+#define _PT_IS_GCABLE_THREAD(thr) 1
+#else
+#define _PT_IS_GCABLE_THREAD(thr) ((thr)->state & PT_THREAD_GCABLE)
+#endif /* GC_LEAK_DETECTOR */
+
+/*
+** Possible values for thread's suspend field
+** Note that the first two can be the same as they are really mutually exclusive,
+** i.e. both cannot be happening at the same time. We have two symbolic names
+** just as a mnemonic.
+**/
+#define PT_THREAD_RESUMED 0x80 /* thread has been resumed */
+#define PT_THREAD_SETGCABLE 0x100 /* set the GCAble flag */
+
+#if defined(DEBUG)
+
+typedef struct PTDebug
+{
+ PRTime timeStarted;
+ PRUintn locks_created, locks_destroyed;
+ PRUintn locks_acquired, locks_released;
+ PRUintn cvars_created, cvars_destroyed;
+ PRUintn cvars_notified, delayed_cv_deletes;
+} PTDebug;
+
+#endif /* defined(DEBUG) */
+
+NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);
+
+#else /* defined(_PR_PTHREADS) */
+
+NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg);
+
+/*
+** This section is contains those parts needed to implement NSPR on
+** platforms in general. One would assume that the pthreads implementation
+** included lots of the same types, at least conceptually.
+*/
+
+/*
+ * Local threads only. No multiple CPU support and hence all the
+ * following routines are no-op.
+ */
+#ifdef _PR_LOCAL_THREADS_ONLY
+
+#define _PR_MD_SUSPEND_THREAD(thread)
+#define _PR_MD_RESUME_THREAD(thread)
+#define _PR_MD_SUSPEND_CPU(cpu)
+#define _PR_MD_RESUME_CPU(cpu)
+#define _PR_MD_BEGIN_SUSPEND_ALL()
+#define _PR_MD_END_SUSPEND_ALL()
+#define _PR_MD_BEGIN_RESUME_ALL()
+#define _PR_MD_END_RESUME_ALL()
+#define _PR_MD_INIT_ATTACHED_THREAD(thread) PR_FAILURE
+
+#endif
+
+typedef struct _PRCPUQueue _PRCPUQueue;
+typedef struct _PRCPU _PRCPU;
+typedef struct _MDCPU _MDCPU;
+
+struct _PRCPUQueue {
+ _MDLock runQLock; /* lock for the run + wait queues */
+ _MDLock sleepQLock; /* lock for the run + wait queues */
+ _MDLock miscQLock; /* lock for the run + wait queues */
+
+ PRCList runQ[PR_PRIORITY_LAST + 1]; /* run queue for this CPU */
+ PRUint32 runQReadyMask;
+ PRCList sleepQ;
+ PRIntervalTime sleepQmax;
+ PRCList pauseQ;
+ PRCList suspendQ;
+ PRCList waitingToJoinQ;
+
+ PRUintn numCPUs; /* number of CPUs using this Q */
+};
+
+struct _PRCPU {
+ PRCList links; /* link list of CPUs */
+ PRUint32 id; /* id for this CPU */
+
+ union {
+ PRInt32 bits;
+ PRUint8 missed[4];
+ } u;
+ PRIntn where; /* index into u.missed */
+ PRPackedBool paused; /* cpu is paused */
+ PRPackedBool exit; /* cpu should exit */
+
+ PRThread *thread; /* native thread for this CPUThread */
+ PRThread *idle_thread; /* user-level idle thread for this CPUThread */
+
+ PRIntervalTime last_clock; /* the last time we went into
+ * _PR_ClockInterrupt() on this CPU
+ */
+
+ _PRCPUQueue *queue;
+
+ _MDCPU md;
+};
+
+typedef struct _PRInterruptTable {
+ const char *name;
+ PRUintn missed_bit;
+ void (*handler)(void);
+} _PRInterruptTable;
+
+#define _PR_CPU_PTR(_qp) \
+ ((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links)))
+
+#if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2) \
+ && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY))
+#define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD())
+#endif
+
+#ifdef _PR_LOCAL_THREADS_ONLY
+
+NSPR_API(struct _PRCPU *) _pr_currentCPU;
+NSPR_API(PRThread *) _pr_currentThread;
+NSPR_API(PRThread *) _pr_lastThread;
+NSPR_API(PRInt32) _pr_intsOff;
+
+#define _MD_CURRENT_CPU() (_pr_currentCPU)
+#define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = (_cpu))
+#define _MD_CURRENT_THREAD() (_pr_currentThread)
+#define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread))
+#define _MD_LAST_THREAD() (_pr_lastThread)
+#define _MD_SET_LAST_THREAD(t) (_pr_lastThread = t)
+
+#ifndef XP_MAC
+#define _MD_GET_INTSOFF() (_pr_intsOff)
+#define _MD_SET_INTSOFF(_val) (_pr_intsOff = _val)
+#endif
+
+
+/* The unbalanced curly braces in these two macros are intentional */
+#define _PR_LOCK_HEAP() { PRIntn _is; if (_pr_currentCPU) _PR_INTSOFF(_is);
+#define _PR_UNLOCK_HEAP() if (_pr_currentCPU) _PR_INTSON(_is); }
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+extern PRInt32 _native_threads_only;
+
+#if defined(_PR_GLOBAL_THREADS_ONLY)
+
+#define _MD_GET_INTSOFF() 0
+#define _MD_SET_INTSOFF(_val)
+#define _PR_INTSOFF(_is)
+#define _PR_FAST_INTSON(_is)
+#define _PR_INTSON(_is)
+#define _PR_THREAD_LOCK(_thread)
+#define _PR_THREAD_UNLOCK(_thread)
+#define _PR_RUNQ_LOCK(cpu)
+#define _PR_RUNQ_UNLOCK(cpu)
+#define _PR_SLEEPQ_LOCK(thread)
+#define _PR_SLEEPQ_UNLOCK(thread)
+#define _PR_MISCQ_LOCK(thread)
+#define _PR_MISCQ_UNLOCK(thread)
+#define _PR_CPU_LIST_LOCK()
+#define _PR_CPU_LIST_UNLOCK()
+
+#define _PR_ADD_RUNQ(_thread, _cpu, _pri)
+#define _PR_DEL_RUNQ(_thread)
+#define _PR_ADD_SLEEPQ(_thread, _timeout)
+#define _PR_DEL_SLEEPQ(_thread, _propogate)
+#define _PR_ADD_JOINQ(_thread, _cpu)
+#define _PR_DEL_JOINQ(_thread)
+#define _PR_ADD_SUSPENDQ(_thread, _cpu)
+#define _PR_DEL_SUSPENDQ(_thread)
+
+#define _PR_THREAD_SWITCH_CPU(_thread, _newCPU)
+
+#define _PR_IS_NATIVE_THREAD(thread) 1
+#define _PR_IS_NATIVE_THREAD_SUPPORTED() 1
+
+#else
+
+#ifdef XP_MAC
+
+#define _PR_INTSOFF(_is) _MD_INTSOFF(_is)
+
+#else /* XP_MAC */
+
+#define _PR_INTSOFF(_is) \
+ PR_BEGIN_MACRO \
+ (_is) = _PR_MD_GET_INTSOFF(); \
+ _PR_MD_SET_INTSOFF(1); \
+ PR_END_MACRO
+
+#endif /* XP_MAC */
+
+#define _PR_FAST_INTSON(_is) \
+ PR_BEGIN_MACRO \
+ _PR_MD_SET_INTSOFF(_is); \
+ PR_END_MACRO
+
+#define _PR_INTSON(_is) \
+ PR_BEGIN_MACRO \
+ if ((_is == 0) && (_PR_MD_CURRENT_CPU())->u.bits) \
+ _PR_IntsOn((_PR_MD_CURRENT_CPU())); \
+ _PR_MD_SET_INTSOFF(_is); \
+ PR_END_MACRO
+
+#ifdef _PR_LOCAL_THREADS_ONLY
+
+#define _PR_IS_NATIVE_THREAD(thread) 0
+#define _PR_THREAD_LOCK(_thread)
+#define _PR_THREAD_UNLOCK(_thread)
+#define _PR_RUNQ_LOCK(cpu)
+#define _PR_RUNQ_UNLOCK(cpu)
+#define _PR_SLEEPQ_LOCK(thread)
+#define _PR_SLEEPQ_UNLOCK(thread)
+#define _PR_MISCQ_LOCK(thread)
+#define _PR_MISCQ_UNLOCK(thread)
+#define _PR_CPU_LIST_LOCK()
+#define _PR_CPU_LIST_UNLOCK()
+
+#define _PR_ADD_RUNQ(_thread, _cpu, _pri) \
+ PR_BEGIN_MACRO \
+ PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \
+ _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \
+ PR_END_MACRO
+
+#define _PR_DEL_RUNQ(_thread) \
+ PR_BEGIN_MACRO \
+ _PRCPU *_cpu = _thread->cpu; \
+ PRInt32 _pri = _thread->priority; \
+ PR_REMOVE_LINK(&(_thread)->links); \
+ if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \
+ _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \
+ PR_END_MACRO
+
+#define _PR_ADD_SLEEPQ(_thread, _timeout) \
+ _PR_AddSleepQ(_thread, _timeout);
+
+#define _PR_DEL_SLEEPQ(_thread, _propogate) \
+ _PR_DelSleepQ(_thread, _propogate);
+
+#define _PR_ADD_JOINQ(_thread, _cpu) \
+ PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu));
+
+#define _PR_DEL_JOINQ(_thread) \
+ PR_REMOVE_LINK(&(_thread)->links);
+
+#define _PR_ADD_SUSPENDQ(_thread, _cpu) \
+ PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu));
+
+#define _PR_DEL_SUSPENDQ(_thread) \
+ PR_REMOVE_LINK(&(_thread)->links);
+
+#define _PR_THREAD_SWITCH_CPU(_thread, _newCPU)
+
+#define _PR_IS_NATIVE_THREAD_SUPPORTED() 0
+
+#else /* _PR_LOCAL_THREADS_ONLY */
+
+/* These are for the "combined" thread model */
+
+#define _PR_THREAD_LOCK(_thread) \
+ _PR_MD_LOCK(&(_thread)->threadLock);
+
+#define _PR_THREAD_UNLOCK(_thread) \
+ _PR_MD_UNLOCK(&(_thread)->threadLock);
+
+#define _PR_RUNQ_LOCK(_cpu) \
+ PR_BEGIN_MACRO \
+ _PR_MD_LOCK(&(_cpu)->queue->runQLock );\
+ PR_END_MACRO
+
+#define _PR_RUNQ_UNLOCK(_cpu) \
+ PR_BEGIN_MACRO \
+ _PR_MD_UNLOCK(&(_cpu)->queue->runQLock );\
+ PR_END_MACRO
+
+#define _PR_SLEEPQ_LOCK(_cpu) \
+ _PR_MD_LOCK(&(_cpu)->queue->sleepQLock );
+
+#define _PR_SLEEPQ_UNLOCK(_cpu) \
+ _PR_MD_UNLOCK(&(_cpu)->queue->sleepQLock );
+
+#define _PR_MISCQ_LOCK(_cpu) \
+ _PR_MD_LOCK(&(_cpu)->queue->miscQLock );
+
+#define _PR_MISCQ_UNLOCK(_cpu) \
+ _PR_MD_UNLOCK(&(_cpu)->queue->miscQLock );
+
+#define _PR_CPU_LIST_LOCK() _PR_MD_LOCK(&_pr_cpuLock)
+#define _PR_CPU_LIST_UNLOCK() _PR_MD_UNLOCK(&_pr_cpuLock)
+
+#define QUEUE_RUN 0x1
+#define QUEUE_SLEEP 0x2
+#define QUEUE_JOIN 0x4
+#define QUEUE_SUSPEND 0x8
+#define QUEUE_LOCK 0x10
+
+#define _PR_ADD_RUNQ(_thread, _cpu, _pri) \
+ PR_BEGIN_MACRO \
+ PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \
+ _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \
+ PR_ASSERT((_thread)->queueCount == 0); \
+ (_thread)->queueCount = QUEUE_RUN; \
+ PR_END_MACRO
+
+#define _PR_DEL_RUNQ(_thread) \
+ PR_BEGIN_MACRO \
+ _PRCPU *_cpu = _thread->cpu; \
+ PRInt32 _pri = _thread->priority; \
+ PR_REMOVE_LINK(&(_thread)->links); \
+ if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \
+ _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \
+ PR_ASSERT((_thread)->queueCount == QUEUE_RUN);\
+ (_thread)->queueCount = 0; \
+ PR_END_MACRO
+
+#define _PR_ADD_SLEEPQ(_thread, _timeout) \
+ PR_ASSERT((_thread)->queueCount == 0); \
+ (_thread)->queueCount = QUEUE_SLEEP; \
+ _PR_AddSleepQ(_thread, _timeout);
+
+#define _PR_DEL_SLEEPQ(_thread, _propogate) \
+ PR_ASSERT((_thread)->queueCount == QUEUE_SLEEP);\
+ (_thread)->queueCount = 0; \
+ _PR_DelSleepQ(_thread, _propogate);
+
+#define _PR_ADD_JOINQ(_thread, _cpu) \
+ PR_ASSERT((_thread)->queueCount == 0); \
+ (_thread)->queueCount = QUEUE_JOIN; \
+ PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu));
+
+#define _PR_DEL_JOINQ(_thread) \
+ PR_ASSERT((_thread)->queueCount == QUEUE_JOIN);\
+ (_thread)->queueCount = 0; \
+ PR_REMOVE_LINK(&(_thread)->links);
+
+#define _PR_ADD_SUSPENDQ(_thread, _cpu) \
+ PR_ASSERT((_thread)->queueCount == 0); \
+ (_thread)->queueCount = QUEUE_SUSPEND; \
+ PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu));
+
+#define _PR_DEL_SUSPENDQ(_thread) \
+ PR_ASSERT((_thread)->queueCount == QUEUE_SUSPEND);\
+ (_thread)->queueCount = 0; \
+ PR_REMOVE_LINK(&(_thread)->links);
+
+#define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) \
+ (_thread)->cpu = (_newCPU);
+
+#define _PR_IS_NATIVE_THREAD(thread) (thread->flags & _PR_GLOBAL_SCOPE)
+#define _PR_IS_NATIVE_THREAD_SUPPORTED() 1
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+
+#define _PR_SET_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 1
+#define _PR_CLEAR_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 0
+
+extern _PRInterruptTable _pr_interruptTable[];
+
+/* Bits for _pr_interruptState.u.missed[0,1] */
+#define _PR_MISSED_CLOCK 0x1
+#define _PR_MISSED_IO 0x2
+#define _PR_MISSED_CHILD 0x4
+
+extern void _PR_IntsOn(_PRCPU *cpu);
+
+NSPR_API(void) _PR_WakeupCPU(void);
+NSPR_API(void) _PR_PauseCPU(void);
+
+/************************************************************************/
+
+#define _PR_LOCK_LOCK(_lock) \
+ _PR_MD_LOCK(&(_lock)->ilock);
+#define _PR_LOCK_UNLOCK(_lock) \
+ _PR_MD_UNLOCK(&(_lock)->ilock);
+
+extern void _PR_UnblockLockWaiter(PRLock *lock);
+
+#define _PR_LOCK_PTR(_qp) \
+ ((PRLock*) ((char*) (_qp) - offsetof(PRLock,links)))
+
+/************************************************************************/
+
+#define _PR_CVAR_LOCK(_cvar) \
+ _PR_MD_LOCK(&(_cvar)->ilock);
+#define _PR_CVAR_UNLOCK(_cvar) \
+ _PR_MD_UNLOCK(&(_cvar)->ilock);
+
+extern PRStatus _PR_WaitCondVar(
+ PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout);
+extern PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen);
+
+NSPR_API(void) _PR_Notify(PRMonitor *mon, PRBool all, PRBool sticky);
+
+/* PRThread.flags */
+#define _PR_SYSTEM 0x01
+#define _PR_INTERRUPT 0x02
+#define _PR_ATTACHED 0x04 /* created via PR_AttachThread */
+#define _PR_PRIMORDIAL 0x08 /* the thread that called PR_Init */
+#define _PR_ON_SLEEPQ 0x10 /* thread is on the sleepQ */
+#define _PR_ON_PAUSEQ 0x20 /* thread is on the pauseQ */
+#define _PR_SUSPENDING 0x40 /* thread wants to suspend */
+#define _PR_GLOBAL_SCOPE 0x80 /* thread is global scope */
+#define _PR_IDLE_THREAD 0x200 /* this is an idle thread */
+#define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */
+#define _PR_BOUND_THREAD 0x800 /* a bound thread */
+#define _PR_INTERRUPT_BLOCKED 0x1000 /* interrupts blocked */
+
+/* PRThread.state */
+#define _PR_UNBORN 0
+#define _PR_RUNNABLE 1
+#define _PR_RUNNING 2
+#define _PR_LOCK_WAIT 3
+#define _PR_COND_WAIT 4
+#define _PR_JOIN_WAIT 5
+#define _PR_IO_WAIT 6
+#define _PR_SUSPENDED 7
+#define _PR_DEAD_STATE 8 /* for debugging */
+
+/* PRThreadStack.flags */
+#define _PR_STACK_VM 0x1 /* using vm instead of malloc */
+#define _PR_STACK_MAPPED 0x2 /* vm is mapped */
+#define _PR_STACK_PRIMORDIAL 0x4 /* stack for primordial thread */
+
+/*
+** If the default stcksize from the client is zero, we need to pick a machine
+** dependent value. This is only for standard user threads. For custom threads,
+** 0 has a special meaning.
+** Adjust stackSize. Round up to a page boundary.
+*/
+
+#ifndef _MD_MINIMUM_STACK_SIZE
+#define _MD_MINIMUM_STACK_SIZE 0
+#endif
+
+#if (!defined(HAVE_CUSTOM_USER_THREADS))
+#define _PR_ADJUST_STACKSIZE(stackSize) \
+ PR_BEGIN_MACRO \
+ if (stackSize == 0) \
+ stackSize = _MD_DEFAULT_STACK_SIZE; \
+ if (stackSize < _MD_MINIMUM_STACK_SIZE) \
+ stackSize = _MD_MINIMUM_STACK_SIZE; \
+ stackSize = (stackSize + (1 << _pr_pageShift) - 1) >> _pr_pageShift; \
+ stackSize <<= _pr_pageShift; \
+ PR_END_MACRO
+#else
+#define _PR_ADJUST_STACKSIZE(stackSize)
+#endif
+
+#ifdef GC_LEAK_DETECTOR
+/* All threads are GCable. */
+#define _PR_IS_GCABLE_THREAD(thr) 1
+#else
+#define _PR_IS_GCABLE_THREAD(thr) ((thr)->flags & _PR_GCABLE_THREAD)
+#endif /* GC_LEAK_DETECTOR */
+
+#define _PR_PENDING_INTERRUPT(thr) \
+ (!((thr)->flags & _PR_INTERRUPT_BLOCKED) && ((thr)->flags & _PR_INTERRUPT))
+#define _PR_THREAD_BLOCK_INTERRUPT(thr) \
+ (thr->flags |= _PR_INTERRUPT_BLOCKED)
+#define _PR_THREAD_UNBLOCK_INTERRUPT(thr) \
+ (thr->flags &= ~_PR_INTERRUPT_BLOCKED)
+
+#define _PR_THREAD_PTR(_qp) \
+ ((PRThread*) ((char*) (_qp) - offsetof(PRThread,links)))
+
+#define _PR_ACTIVE_THREAD_PTR(_qp) \
+ ((PRThread*) ((char*) (_qp) - offsetof(PRThread,active)))
+
+#define _PR_THREAD_CONDQ_PTR(_qp) \
+ ((PRThread*) ((char*) (_qp) - offsetof(PRThread,waitQLinks)))
+
+#define _PR_THREAD_MD_TO_PTR(_md) \
+ ((PRThread*) ((char*) (_md) - offsetof(PRThread,md)))
+
+#define _PR_THREAD_STACK_TO_PTR(_stack) \
+ ((PRThread*) (_stack->thr))
+
+extern PRCList _pr_active_local_threadQ;
+extern PRCList _pr_active_global_threadQ;
+extern PRCList _pr_cpuQ;
+extern _MDLock _pr_cpuLock;
+extern PRInt32 _pr_md_idle_cpus;
+
+#define _PR_ACTIVE_LOCAL_THREADQ() _pr_active_local_threadQ
+#define _PR_ACTIVE_GLOBAL_THREADQ() _pr_active_global_threadQ
+#define _PR_CPUQ() _pr_cpuQ
+#define _PR_RUNQ(_cpu) ((_cpu)->queue->runQ)
+#define _PR_RUNQREADYMASK(_cpu) ((_cpu)->queue->runQReadyMask)
+#define _PR_SLEEPQ(_cpu) ((_cpu)->queue->sleepQ)
+#define _PR_SLEEPQMAX(_cpu) ((_cpu)->queue->sleepQmax)
+#define _PR_PAUSEQ(_cpu) ((_cpu)->queue->pauseQ)
+#define _PR_SUSPENDQ(_cpu) ((_cpu)->queue->suspendQ)
+#define _PR_WAITINGTOJOINQ(_cpu) ((_cpu)->queue->waitingToJoinQ)
+
+extern PRUint32 _pr_recycleThreads; /* Flag for behavior on thread cleanup */
+extern PRLock *_pr_deadQLock;
+extern PRUint32 _pr_numNativeDead;
+extern PRUint32 _pr_numUserDead;
+extern PRCList _pr_deadNativeQ;
+extern PRCList _pr_deadUserQ;
+#define _PR_DEADNATIVEQ _pr_deadNativeQ
+#define _PR_DEADUSERQ _pr_deadUserQ
+#define _PR_DEADQ_LOCK PR_Lock(_pr_deadQLock);
+#define _PR_DEADQ_UNLOCK PR_Unlock(_pr_deadQLock);
+#define _PR_INC_DEADNATIVE (_pr_numNativeDead++)
+#define _PR_DEC_DEADNATIVE (_pr_numNativeDead--)
+#define _PR_NUM_DEADNATIVE (_pr_numNativeDead)
+#define _PR_INC_DEADUSER (_pr_numUserDead++)
+#define _PR_DEC_DEADUSER (_pr_numUserDead--)
+#define _PR_NUM_DEADUSER (_pr_numUserDead)
+
+extern PRUint32 _pr_utid;
+
+extern struct _PRCPU *_pr_primordialCPU;
+
+extern PRLock *_pr_activeLock; /* lock for userActive and systemActive */
+extern PRInt32 _pr_userActive; /* number of active user threads */
+extern PRInt32 _pr_systemActive; /* number of active system threads */
+extern PRInt32 _pr_primordialExitCount; /* number of user threads left
+ * before the primordial thread
+ * can exit. */
+extern PRCondVar *_pr_primordialExitCVar; /* the condition variable for
+ * notifying the primordial thread
+ * when all other user threads
+ * have terminated. */
+
+extern PRUintn _pr_maxPTDs;
+
+extern PRLock *_pr_terminationCVLock;
+
+/*************************************************************************
+* Internal routines either called by PR itself or from machine-dependent *
+* code. *
+*************************************************************************/
+
+extern void _PR_ClockInterrupt(void);
+
+extern void _PR_Schedule(void);
+extern void _PR_SetThreadPriority(
+ PRThread* thread, PRThreadPriority priority);
+
+/***********************************************************************
+** FUNCTION: _PR_NewSegment()
+** DESCRIPTION:
+** Allocate a memory segment. The "size" value is rounded up to the
+** native system page size and a page aligned portion of memory is
+** returned. This memory is not part of the malloc heap. If "vaddr" is
+** not NULL then PR tries to allocate the segment at the desired virtual
+** address.
+** INPUTS: size: size of the desired memory segment
+** vaddr: address at which the newly aquired segment is to be
+** mapped into memory.
+** OUTPUTS: a memory segment is allocated, a PRSegment is allocated
+** RETURN: pointer to PRSegment
+***********************************************************************/
+extern PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr);
+
+/***********************************************************************
+** FUNCTION: _PR_DestroySegment()
+** DESCRIPTION:
+** The memory segment and the PRSegment are freed
+** INPUTS: seg: pointer to PRSegment to be freed
+** OUTPUTS: the the PRSegment and its associated memory segment are freed
+** RETURN: void
+***********************************************************************/
+extern void _PR_DestroySegment(PRSegment *seg);
+
+extern PRThreadStack * _PR_NewStack(PRUint32 stackSize);
+extern void _PR_FreeStack(PRThreadStack *stack);
+extern PRBool _PR_NotifyThread (PRThread *thread, PRThread *me);
+extern void _PR_NotifyLockedThread (PRThread *thread);
+
+NSPR_API(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout);
+NSPR_API(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time);
+
+extern void _PR_AddThreadToRunQ(PRThread *me, PRThread *thread);
+
+NSPR_API(PRThread*) _PR_CreateThread(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize,
+ PRUint32 flags);
+
+extern void _PR_NativeDestroyThread(PRThread *thread);
+extern void _PR_UserDestroyThread(PRThread *thread);
+
+extern PRThread* _PRI_AttachThread(
+ PRThreadType type, PRThreadPriority priority,
+ PRThreadStack *stack, PRUint32 flags);
+
+extern void _PRI_DetachThread(void);
+
+
+#define _PR_IO_PENDING(_thread) ((_thread)->io_pending)
+
+NSPR_API(void) _PR_MD_INIT_CPUS();
+#define _PR_MD_INIT_CPUS _MD_INIT_CPUS
+
+NSPR_API(void) _PR_MD_WAKEUP_CPUS();
+#define _PR_MD_WAKEUP_CPUS _MD_WAKEUP_CPUS
+
+/* Interrupts related */
+
+NSPR_API(void) _PR_MD_START_INTERRUPTS(void);
+#define _PR_MD_START_INTERRUPTS _MD_START_INTERRUPTS
+
+NSPR_API(void) _PR_MD_STOP_INTERRUPTS(void);
+#define _PR_MD_STOP_INTERRUPTS _MD_STOP_INTERRUPTS
+
+NSPR_API(void) _PR_MD_ENABLE_CLOCK_INTERRUPTS(void);
+#define _PR_MD_ENABLE_CLOCK_INTERRUPTS _MD_ENABLE_CLOCK_INTERRUPTS
+
+NSPR_API(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);
+#define _PR_MD_DISABLE_CLOCK_INTERRUPTS _MD_DISABLE_CLOCK_INTERRUPTS
+
+NSPR_API(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void);
+#define _PR_MD_BLOCK_CLOCK_INTERRUPTS _MD_BLOCK_CLOCK_INTERRUPTS
+
+NSPR_API(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);
+#define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UNBLOCK_CLOCK_INTERRUPTS
+
+/* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and
+ * awaken a thread which is waiting on a lock or cvar.
+ */
+extern PRStatus _PR_MD_WAIT(PRThread *, PRIntervalTime timeout);
+#define _PR_MD_WAIT _MD_WAIT
+
+extern PRStatus _PR_MD_WAKEUP_WAITER(PRThread *);
+#define _PR_MD_WAKEUP_WAITER _MD_WAKEUP_WAITER
+
+#ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */
+NSPR_API(void) _PR_MD_CLOCK_INTERRUPT(void);
+#define _PR_MD_CLOCK_INTERRUPT _MD_CLOCK_INTERRUPT
+#endif
+
+/* Stack debugging */
+NSPR_API(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone);
+#define _PR_MD_INIT_STACK _MD_INIT_STACK
+
+NSPR_API(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts);
+#define _PR_MD_CLEAR_STACK _MD_CLEAR_STACK
+
+/* CPU related */
+NSPR_API(PRInt32) _PR_MD_GET_INTSOFF(void);
+#define _PR_MD_GET_INTSOFF _MD_GET_INTSOFF
+
+NSPR_API(void) _PR_MD_SET_INTSOFF(PRInt32 _val);
+#define _PR_MD_SET_INTSOFF _MD_SET_INTSOFF
+
+NSPR_API(_PRCPU*) _PR_MD_CURRENT_CPU(void);
+#define _PR_MD_CURRENT_CPU _MD_CURRENT_CPU
+
+NSPR_API(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu);
+#define _PR_MD_SET_CURRENT_CPU _MD_SET_CURRENT_CPU
+
+NSPR_API(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);
+#define _PR_MD_INIT_RUNNING_CPU _MD_INIT_RUNNING_CPU
+
+/*
+ * Returns the number of threads awoken or 0 if a timeout occurred;
+ */
+extern PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
+#define _PR_MD_PAUSE_CPU _MD_PAUSE_CPU
+
+extern void _PR_MD_CLEANUP_BEFORE_EXIT(void);
+#define _PR_MD_CLEANUP_BEFORE_EXIT _MD_CLEANUP_BEFORE_EXIT
+
+extern void _PR_MD_EXIT(PRIntn status);
+#define _PR_MD_EXIT _MD_EXIT
+
+/* Locks related */
+
+NSPR_API(void) _PR_MD_INIT_LOCKS(void);
+#define _PR_MD_INIT_LOCKS _MD_INIT_LOCKS
+
+NSPR_API(PRStatus) _PR_MD_NEW_LOCK(_MDLock *md);
+#define _PR_MD_NEW_LOCK _MD_NEW_LOCK
+
+NSPR_API(void) _PR_MD_FREE_LOCK(_MDLock *md);
+#define _PR_MD_FREE_LOCK _MD_FREE_LOCK
+
+NSPR_API(void) _PR_MD_LOCK(_MDLock *md);
+#define _PR_MD_LOCK _MD_LOCK
+
+/* Return 0 on success, a nonzero value on failure. */
+NSPR_API(PRIntn) _PR_MD_TEST_AND_LOCK(_MDLock *md);
+#define _PR_MD_TEST_AND_LOCK _MD_TEST_AND_LOCK
+
+NSPR_API(void) _PR_MD_UNLOCK(_MDLock *md);
+#define _PR_MD_UNLOCK _MD_UNLOCK
+
+NSPR_API(void) _PR_MD_IOQ_LOCK(void);
+#define _PR_MD_IOQ_LOCK _MD_IOQ_LOCK
+
+NSPR_API(void) _PR_MD_IOQ_UNLOCK(void);
+#define _PR_MD_IOQ_UNLOCK _MD_IOQ_UNLOCK
+
+#ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */
+/* Semaphore related -- only for native threads */
+#ifdef HAVE_CVAR_BUILT_ON_SEM
+NSPR_API(void) _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value);
+#define _PR_MD_NEW_SEM _MD_NEW_SEM
+
+NSPR_API(void) _PR_MD_DESTROY_SEM(_MDSemaphore *md);
+#define _PR_MD_DESTROY_SEM _MD_DESTROY_SEM
+
+NSPR_API(PRStatus) _PR_MD_TIMED_WAIT_SEM(
+ _MDSemaphore *md, PRIntervalTime timeout);
+#define _PR_MD_TIMED_WAIT_SEM _MD_TIMED_WAIT_SEM
+
+NSPR_API(PRStatus) _PR_MD_WAIT_SEM(_MDSemaphore *md);
+#define _PR_MD_WAIT_SEM _MD_WAIT_SEM
+
+NSPR_API(void) _PR_MD_POST_SEM(_MDSemaphore *md);
+#define _PR_MD_POST_SEM _MD_POST_SEM
+#endif /* HAVE_CVAR_BUILT_ON_SEM */
+
+#endif
+
+/* Condition Variables related -- only for native threads */
+
+#ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */
+NSPR_API(PRInt32) _PR_MD_NEW_CV(_MDCVar *md);
+#define _PR_MD_NEW_CV _MD_NEW_CV
+
+NSPR_API(void) _PR_MD_FREE_CV(_MDCVar *md);
+#define _PR_MD_FREE_CV _MD_FREE_CV
+
+NSPR_API(void) _PR_MD_WAIT_CV(
+ _MDCVar *mdCVar,_MDLock *mdLock,PRIntervalTime timeout);
+#define _PR_MD_WAIT_CV _MD_WAIT_CV
+
+NSPR_API(void) _PR_MD_NOTIFY_CV(_MDCVar *md, _MDLock *lock);
+#define _PR_MD_NOTIFY_CV _MD_NOTIFY_CV
+
+NSPR_API(void) _PR_MD_NOTIFYALL_CV(_MDCVar *md, _MDLock *lock);
+#define _PR_MD_NOTIFYALL_CV _MD_NOTIFYALL_CV
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+/* Threads related */
+NSPR_API(PRThread*) _PR_MD_CURRENT_THREAD(void);
+#define _PR_MD_CURRENT_THREAD _MD_CURRENT_THREAD
+
+NSPR_API(PRThread*) _PR_MD_GET_ATTACHED_THREAD(void);
+#define _PR_MD_GET_ATTACHED_THREAD _MD_GET_ATTACHED_THREAD
+
+NSPR_API(PRThread*) _PR_MD_LAST_THREAD(void);
+#define _PR_MD_LAST_THREAD _MD_LAST_THREAD
+
+NSPR_API(void) _PR_MD_SET_CURRENT_THREAD(PRThread *thread);
+#define _PR_MD_SET_CURRENT_THREAD _MD_SET_CURRENT_THREAD
+
+NSPR_API(void) _PR_MD_SET_LAST_THREAD(PRThread *thread);
+#define _PR_MD_SET_LAST_THREAD _MD_SET_LAST_THREAD
+
+extern PRStatus _PR_MD_INIT_THREAD(PRThread *thread);
+#define _PR_MD_INIT_THREAD _MD_INIT_THREAD
+
+extern void _PR_MD_EXIT_THREAD(PRThread *thread);
+#define _PR_MD_EXIT_THREAD _MD_EXIT_THREAD
+
+#ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */
+
+NSPR_API(PRStatus) _PR_MD_INIT_ATTACHED_THREAD(PRThread *thread);
+#define _PR_MD_INIT_ATTACHED_THREAD _MD_INIT_ATTACHED_THREAD
+
+extern void _PR_MD_SUSPEND_THREAD(PRThread *thread);
+#define _PR_MD_SUSPEND_THREAD _MD_SUSPEND_THREAD
+
+extern void _PR_MD_RESUME_THREAD(PRThread *thread);
+#define _PR_MD_RESUME_THREAD _MD_RESUME_THREAD
+
+extern void _PR_MD_SUSPEND_CPU(_PRCPU *cpu);
+#define _PR_MD_SUSPEND_CPU _MD_SUSPEND_CPU
+
+extern void _PR_MD_RESUME_CPU(_PRCPU *cpu);
+#define _PR_MD_RESUME_CPU _MD_RESUME_CPU
+
+extern void _PR_MD_BEGIN_SUSPEND_ALL(void);
+#define _PR_MD_BEGIN_SUSPEND_ALL _MD_BEGIN_SUSPEND_ALL
+
+extern void _PR_MD_END_SUSPEND_ALL(void);
+#define _PR_MD_END_SUSPEND_ALL _MD_END_SUSPEND_ALL
+
+extern void _PR_MD_BEGIN_RESUME_ALL(void);
+#define _PR_MD_BEGIN_RESUME_ALL _MD_BEGIN_RESUME_ALL
+
+extern void _PR_MD_END_RESUME_ALL(void);
+#define _PR_MD_END_RESUME_ALL _MD_END_RESUME_ALL
+
+#if defined(IRIX)
+NSPR_API(void) _PR_IRIX_CHILD_PROCESS(void);
+#endif /* IRIX */
+
+#endif /* !_PR_LOCAL_THREADS_ONLY */
+
+extern void _PR_MD_CLEAN_THREAD(PRThread *thread);
+#define _PR_MD_CLEAN_THREAD _MD_CLEAN_THREAD
+
+#ifdef HAVE_CUSTOM_USER_THREADS
+extern void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *);
+#define _PR_MD_CREATE_PRIMORDIAL_USER_THREAD _MD_CREATE_PRIMORDIAL_USER_THREAD
+
+extern PRThread* _PR_MD_CREATE_USER_THREAD(
+ PRUint32 stacksize,
+ void (*start)(void *),
+ void *arg);
+#define _PR_MD_CREATE_USER_THREAD _MD_CREATE_USER_THREAD
+#endif
+
+extern PRStatus _PR_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+#define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD
+
+extern void _PR_MD_JOIN_THREAD(_MDThread *md);
+#define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD
+
+extern void _PR_MD_END_THREAD(void);
+#define _PR_MD_END_THREAD _MD_END_THREAD
+
+extern void _PR_MD_YIELD(void);
+#define _PR_MD_YIELD _MD_YIELD
+
+extern void _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri);
+#define _PR_MD_SET_PRIORITY _MD_SET_PRIORITY
+
+NSPR_API(void) _PR_MD_SUSPENDALL(void);
+#define _PR_MD_SUSPENDALL _MD_SUSPENDALL
+
+NSPR_API(void) _PR_MD_RESUMEALL(void);
+#define _PR_MD_RESUMEALL _MD_RESUMEALL
+
+extern void _PR_MD_INIT_CONTEXT(
+ PRThread *thread, char *top, void (*start) (void), PRBool *status);
+#define _PR_MD_INIT_CONTEXT _MD_INIT_CONTEXT
+
+extern void _PR_MD_SWITCH_CONTEXT(PRThread *thread);
+#define _PR_MD_SWITCH_CONTEXT _MD_SWITCH_CONTEXT
+
+extern void _PR_MD_RESTORE_CONTEXT(PRThread *thread);
+#define _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT
+
+/* Segment related */
+extern void _PR_MD_INIT_SEGS(void);
+#define _PR_MD_INIT_SEGS _MD_INIT_SEGS
+
+extern PRStatus _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);
+#define _PR_MD_ALLOC_SEGMENT _MD_ALLOC_SEGMENT
+
+extern void _PR_MD_FREE_SEGMENT(PRSegment *seg);
+#define _PR_MD_FREE_SEGMENT _MD_FREE_SEGMENT
+
+/* Directory enumeration related */
+extern PRStatus _PR_MD_OPEN_DIR(_MDDir *md,const char *name);
+#define _PR_MD_OPEN_DIR _MD_OPEN_DIR
+
+extern char * _PR_MD_READ_DIR(_MDDir *md, PRIntn flags);
+#define _PR_MD_READ_DIR _MD_READ_DIR
+
+extern PRInt32 _PR_MD_CLOSE_DIR(_MDDir *md);
+#define _PR_MD_CLOSE_DIR _MD_CLOSE_DIR
+
+/* Named semaphores related */
+extern PRSem * _PR_MD_OPEN_SEMAPHORE(
+ const char *osname, PRIntn flags, PRIntn mode, PRUintn value);
+#define _PR_MD_OPEN_SEMAPHORE _MD_OPEN_SEMAPHORE
+
+extern PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem);
+#define _PR_MD_WAIT_SEMAPHORE _MD_WAIT_SEMAPHORE
+
+extern PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem);
+#define _PR_MD_POST_SEMAPHORE _MD_POST_SEMAPHORE
+
+extern PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem);
+#define _PR_MD_CLOSE_SEMAPHORE _MD_CLOSE_SEMAPHORE
+
+extern PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname);
+#define _PR_MD_DELETE_SEMAPHORE _MD_DELETE_SEMAPHORE
+
+/* I/O related */
+extern void _PR_MD_INIT_FILEDESC(PRFileDesc *fd);
+#define _PR_MD_INIT_FILEDESC _MD_INIT_FILEDESC
+
+#ifdef XP_MAC
+extern void _PR_MD_FREE_FILEDESC(PRFileDesc *fd);
+#define _PR_MD_FREE_FILEDESC _MD_FREE_FILEDESC
+#endif
+
+extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd);
+#define _PR_MD_MAKE_NONBLOCK _MD_MAKE_NONBLOCK
+
+/* File I/O related */
+extern PRInt32 _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode);
+#define _PR_MD_OPEN _MD_OPEN
+
+extern PRInt32 _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode);
+#define _PR_MD_OPEN_FILE _MD_OPEN_FILE
+
+extern PRInt32 _PR_MD_CLOSE_FILE(PRInt32 osfd);
+#define _PR_MD_CLOSE_FILE _MD_CLOSE_FILE
+
+extern PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 amount);
+#define _PR_MD_READ _MD_READ
+
+extern PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 amount);
+#define _PR_MD_WRITE _MD_WRITE
+
+extern PRInt32 _PR_MD_WRITEV(
+ PRFileDesc *fd, const struct PRIOVec *iov,
+ PRInt32 iov_size, PRIntervalTime timeout);
+#define _PR_MD_WRITEV _MD_WRITEV
+
+extern PRInt32 _PR_MD_FSYNC(PRFileDesc *fd);
+#define _PR_MD_FSYNC _MD_FSYNC
+
+extern PRInt32 _PR_MD_DELETE(const char *name);
+#define _PR_MD_DELETE _MD_DELETE
+
+extern PRInt32 _PR_MD_RENAME(const char *from, const char *to);
+#define _PR_MD_RENAME _MD_RENAME
+
+extern PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how);
+#define _PR_MD_ACCESS _MD_ACCESS
+
+extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf);
+#define _PR_MD_STAT _MD_STAT
+
+extern PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode);
+#define _PR_MD_MKDIR _MD_MKDIR
+
+extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode);
+#define _PR_MD_MAKE_DIR _MD_MAKE_DIR
+
+extern PRInt32 _PR_MD_RMDIR(const char *name);
+#define _PR_MD_RMDIR _MD_RMDIR
+
+#ifdef MOZ_UNICODE
+/* UTF16 File I/O related */
+extern PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *md, const PRUnichar *name);
+#define _PR_MD_OPEN_DIR_UTF16 _MD_OPEN_DIR_UTF16
+
+extern PRInt32 _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, PRIntn mode);
+#define _PR_MD_OPEN_FILE_UTF16 _MD_OPEN_FILE_UTF16
+
+extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags);
+#define _PR_MD_READ_DIR_UTF16 _MD_READ_DIR_UTF16
+
+extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md);
+#define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF16
+
+extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info);
+#define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF16
+#endif /* MOZ_UNICODE */
+
+/* Socket I/O related */
+extern void _PR_MD_INIT_IO(void);
+#define _PR_MD_INIT_IO _MD_INIT_IO
+
+extern PRInt32 _PR_MD_CLOSE_SOCKET(PRInt32 osfd);
+#define _PR_MD_CLOSE_SOCKET _MD_CLOSE_SOCKET
+
+extern PRInt32 _PR_MD_CONNECT(
+ PRFileDesc *fd, const PRNetAddr *addr,
+ PRUint32 addrlen, PRIntervalTime timeout);
+#define _PR_MD_CONNECT _MD_CONNECT
+
+extern PRInt32 _PR_MD_ACCEPT(
+ PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen, PRIntervalTime timeout);
+#define _PR_MD_ACCEPT _MD_ACCEPT
+
+extern PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen);
+#define _PR_MD_BIND _MD_BIND
+
+extern PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog);
+#define _PR_MD_LISTEN _MD_LISTEN
+
+extern PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how);
+#define _PR_MD_SHUTDOWN _MD_SHUTDOWN
+
+extern PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout);
+#define _PR_MD_RECV _MD_RECV
+
+extern PRInt32 _PR_MD_SEND(
+ PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout);
+#define _PR_MD_SEND _MD_SEND
+
+extern PRInt32 _PR_MD_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock,
+ PRNetAddr **raddr, void *buf, PRInt32 amount,
+ PRIntervalTime timeout);
+#define _PR_MD_ACCEPT_READ _MD_ACCEPT_READ
+
+#ifdef WIN32
+extern PRInt32 _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen, PRIntervalTime timeout,
+ PRBool fast,
+ _PR_AcceptTimeoutCallback callback,
+ void *callbackArg);
+
+extern PRInt32 _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock,
+ PRNetAddr **raddr, void *buf, PRInt32 amount,
+ PRIntervalTime timeout, PRBool fast,
+ _PR_AcceptTimeoutCallback callback,
+ void *callbackArg);
+
+extern void _PR_MD_UPDATE_ACCEPT_CONTEXT(PRInt32 s, PRInt32 ls);
+#define _PR_MD_UPDATE_ACCEPT_CONTEXT _MD_UPDATE_ACCEPT_CONTEXT
+#endif /* WIN32 */
+
+extern PRInt32 _PR_MD_SENDFILE(
+ PRFileDesc *sock, PRSendFileData *sfd,
+ PRInt32 flags, PRIntervalTime timeout);
+#define _PR_MD_SENDFILE _MD_SENDFILE
+
+extern PRStatus _PR_MD_GETSOCKNAME(
+ PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen);
+#define _PR_MD_GETSOCKNAME _MD_GETSOCKNAME
+
+extern PRStatus _PR_MD_GETPEERNAME(
+ PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen);
+#define _PR_MD_GETPEERNAME _MD_GETPEERNAME
+
+extern PRStatus _PR_MD_GETSOCKOPT(
+ PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen);
+#define _PR_MD_GETSOCKOPT _MD_GETSOCKOPT
+
+extern PRStatus _PR_MD_SETSOCKOPT(
+ PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ const char* optval, PRInt32 optlen);
+#define _PR_MD_SETSOCKOPT _MD_SETSOCKOPT
+
+extern PRStatus PR_CALLBACK _PR_SocketGetSocketOption(
+ PRFileDesc *fd, PRSocketOptionData *data);
+
+extern PRStatus PR_CALLBACK _PR_SocketSetSocketOption(
+ PRFileDesc *fd, const PRSocketOptionData *data);
+
+extern PRInt32 _PR_MD_RECVFROM(
+ PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout);
+#define _PR_MD_RECVFROM _MD_RECVFROM
+
+extern PRInt32 _PR_MD_SENDTO(
+ PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout);
+#define _PR_MD_SENDTO _MD_SENDTO
+
+extern PRInt32 _PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd);
+#define _PR_MD_SOCKETPAIR _MD_SOCKETPAIR
+
+extern PRInt32 _PR_MD_SOCKET(int af, int type, int flags);
+#define _PR_MD_SOCKET _MD_SOCKET
+
+extern PRInt32 _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd);
+#define _PR_MD_SOCKETAVAILABLE _MD_SOCKETAVAILABLE
+
+extern PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd);
+#define _PR_MD_PIPEAVAILABLE _MD_PIPEAVAILABLE
+
+extern PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds,
+ PRIntervalTime timeout);
+#define _PR_MD_PR_POLL _MD_PR_POLL
+
+/*
+ * Initialize fd->secret->inheritable for a newly created fd.
+ * If 'imported' is false, the osfd (i.e., fd->secret->md.osfd)
+ * was created by NSPR and hence has the OS-dependent default
+ * inheritable attribute. If 'imported' is true, the osfd was
+ * not created by NSPR and hence a system call is required to
+ * query its inheritable attribute. Since we may never need to
+ * know the inheritable attribute of a fd, a platform may choose
+ * to initialize fd->secret->inheritable of an imported fd to
+ * _PR_TRI_UNKNOWN and only pay the cost of the system call
+ * (in _PR_MD_QUERY_FD_INHERITABLE) when necessary.
+ */
+extern void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported);
+#define _PR_MD_INIT_FD_INHERITABLE _MD_INIT_FD_INHERITABLE
+
+extern PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable);
+#define _PR_MD_SET_FD_INHERITABLE _MD_SET_FD_INHERITABLE
+
+
+#define _PR_PROCESS_TIMEOUT_INTERRUPT_ERRORS(me) \
+ if (_PR_PENDING_INTERRUPT(me)) { \
+ me->flags &= ~_PR_INTERRUPT; \
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); \
+ } else { \
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0); \
+ }
+
+extern void *_PR_MD_GET_SP(PRThread *thread);
+#define _PR_MD_GET_SP _MD_GET_SP
+
+#endif /* defined(_PR_PTHREADS) */
+
+/************************************************************************/
+/*************************************************************************
+** The remainder of the definitions are shared by pthreads and the classic
+** NSPR code. These too may be conditionalized.
+*************************************************************************/
+/************************************************************************/
+
+extern PROffset32 _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence);
+#define _PR_MD_LSEEK _MD_LSEEK
+
+extern PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence);
+#define _PR_MD_LSEEK64 _MD_LSEEK64
+
+extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info);
+#define _PR_MD_GETFILEINFO _MD_GETFILEINFO
+
+extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info);
+#define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64
+
+extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info);
+#define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO
+
+extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info);
+#define _PR_MD_GETOPENFILEINFO64 _MD_GETOPENFILEINFO64
+
+
+/*****************************************************************************/
+/************************** File descriptor caching **************************/
+/*****************************************************************************/
+extern void _PR_InitFdCache(void);
+extern void _PR_CleanupFdCache(void);
+extern PRFileDesc *_PR_Getfd(void);
+extern void _PR_Putfd(PRFileDesc *fd);
+
+/*
+ * These flags are used by NSPR temporarily in the poll
+ * descriptor's out_flags field to record the mapping of
+ * NSPR's poll flags to the system poll flags.
+ *
+ * If _PR_POLL_READ_SYS_WRITE bit is set, it means the
+ * PR_POLL_READ flag specified by the topmost layer is
+ * mapped to the WRITE flag at the system layer. Similarly
+ * for the other three _PR_POLL_XXX_SYS_YYY flags. It is
+ * assumed that the PR_POLL_EXCEPT flag doesn't get mapped
+ * to other flags.
+ */
+#define _PR_POLL_READ_SYS_READ 0x1
+#define _PR_POLL_READ_SYS_WRITE 0x2
+#define _PR_POLL_WRITE_SYS_READ 0x4
+#define _PR_POLL_WRITE_SYS_WRITE 0x8
+
+/*
+** These methods are coerced into file descriptor methods table
+** when the intended service is inappropriate for the particular
+** type of file descriptor.
+*/
+extern PRIntn _PR_InvalidInt(void);
+extern PRInt16 _PR_InvalidInt16(void);
+extern PRInt64 _PR_InvalidInt64(void);
+extern PRStatus _PR_InvalidStatus(void);
+extern PRFileDesc *_PR_InvalidDesc(void);
+
+extern PRIOMethods _pr_faulty_methods;
+
+/*
+** The PR_NETADDR_SIZE macro can only be called on a PRNetAddr union
+** whose 'family' field is set. It returns the size of the union
+** member corresponding to the specified address family.
+*/
+
+extern PRUintn _PR_NetAddrSize(const PRNetAddr* addr);
+
+#if defined(_PR_INET6)
+
+#define PR_NETADDR_SIZE(_addr) _PR_NetAddrSize(_addr)
+
+#elif defined(_PR_HAVE_MD_SOCKADDR_IN6)
+
+/*
+** Under the following conditions:
+** 1. _PR_INET6 is not defined;
+** 2. _PR_INET6_PROBE is defined;
+** 3. struct sockaddr_in6 has nonstandard fields at the end
+** (e.g., on Solaris 8),
+** (_addr)->ipv6 is smaller than struct sockaddr_in6, and
+** hence we can't pass sizeof((_addr)->ipv6) to socket
+** functions such as connect because they would fail with
+** EINVAL.
+**
+** To pass the correct socket address length to socket
+** functions, define the macro _PR_HAVE_MD_SOCKADDR_IN6 and
+** define struct _md_sockaddr_in6 to be isomorphic to
+** struct sockaddr_in6.
+*/
+
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+#define PR_NETADDR_SIZE(_addr) \
+ ((_addr)->raw.family == PR_AF_INET \
+ ? sizeof((_addr)->inet) \
+ : ((_addr)->raw.family == PR_AF_INET6 \
+ ? sizeof(struct _md_sockaddr_in6) \
+ : sizeof((_addr)->local)))
+#else
+#define PR_NETADDR_SIZE(_addr) \
+ ((_addr)->raw.family == PR_AF_INET \
+ ? sizeof((_addr)->inet) \
+ : sizeof(struct _md_sockaddr_in6)
+#endif /* defined(XP_UNIX) */
+
+#else
+
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+#define PR_NETADDR_SIZE(_addr) \
+ ((_addr)->raw.family == PR_AF_INET \
+ ? sizeof((_addr)->inet) \
+ : ((_addr)->raw.family == PR_AF_INET6 \
+ ? sizeof((_addr)->ipv6) \
+ : sizeof((_addr)->local)))
+#else
+#define PR_NETADDR_SIZE(_addr) \
+ ((_addr)->raw.family == PR_AF_INET \
+ ? sizeof((_addr)->inet) \
+ : sizeof((_addr)->ipv6))
+#endif /* defined(XP_UNIX) */
+
+#endif /* defined(_PR_INET6) */
+
+extern PRStatus _PR_MapOptionName(
+ PRSockOption optname, PRInt32 *level, PRInt32 *name);
+extern void _PR_InitThreads(
+ PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs);
+
+struct PRLock {
+#if defined(_PR_PTHREADS)
+ pthread_mutex_t mutex; /* the underlying lock */
+ _PT_Notified notified; /* array of conditions notified */
+ PRBool locked; /* whether the mutex is locked */
+ pthread_t owner; /* if locked, current lock owner */
+#elif defined(_PR_BTHREADS)
+ sem_id semaphoreID; /* the underlying lock */
+ int32 benaphoreCount; /* number of people in lock */
+ thread_id owner; /* current lock owner */
+#else /* not pthreads or Be threads */
+ PRCList links; /* linkage for PRThread.lockList */
+ struct PRThread *owner; /* current lock owner */
+ PRCList waitQ; /* list of threads waiting for lock */
+ PRThreadPriority priority; /* priority of lock */
+ PRThreadPriority boostPriority; /* boosted priority of lock owner */
+ _MDLock ilock; /* Internal Lock to protect user-level fields */
+#endif
+};
+
+extern void _PR_InitLocks(void);
+
+struct PRCondVar {
+ PRLock *lock; /* associated lock that protects the condition */
+#if defined(_PR_PTHREADS)
+ pthread_cond_t cv; /* underlying pthreads condition */
+ PRInt32 notify_pending; /* CV has destroy pending notification */
+#elif defined(_PR_BTHREADS)
+ sem_id sem; /* the underlying lock */
+ sem_id handshakeSem; /* the lock for 'notify'-threads waiting for confirmation */
+ sem_id signalSem; /* the lock for threads waiting for someone to notify */
+ volatile int32 nw; /* the number waiting */
+ volatile int32 ns; /* the number signalling */
+ long signalBenCount; /* the number waiting on the underlying sem */
+#else /* not pthreads or Be threads */
+ PRCList condQ; /* Condition variable wait Q */
+ _MDLock ilock; /* Internal Lock to protect condQ */
+ _MDCVar md;
+#endif
+};
+
+/************************************************************************/
+
+struct PRMonitor {
+ const char* name; /* monitor name for debugging */
+#if defined(_PR_PTHREADS)
+ PRLock lock; /* the lock structure */
+ pthread_t owner; /* the owner of the lock or invalid */
+ PRCondVar *cvar; /* condition variable queue */
+#else /* defined(_PR_PTHREADS) */
+ PRCondVar *cvar; /* associated lock and condition variable queue */
+#endif /* defined(_PR_PTHREADS) */
+ PRUint32 entryCount; /* # of times re-entered */
+};
+
+/************************************************************************/
+
+struct PRSemaphore {
+#if defined(_PR_BTHREADS)
+ sem_id sem;
+ int32 benaphoreCount;
+#else
+ PRCondVar *cvar; /* associated lock and condition variable queue */
+ PRUintn count; /* the value of the counting semaphore */
+ PRUint32 waiters; /* threads waiting on the semaphore */
+#if defined(_PR_PTHREADS)
+#else /* defined(_PR_PTHREADS) */
+ _MDSemaphore md;
+#endif /* defined(_PR_PTHREADS) */
+#endif /* defined(_PR_BTHREADS) */
+};
+
+NSPR_API(void) _PR_InitSem(void);
+
+/*************************************************************************/
+
+struct PRSem {
+#ifdef _PR_HAVE_POSIX_SEMAPHORES
+ sem_t *sem;
+#elif defined(_PR_HAVE_SYSV_SEMAPHORES)
+ int semid;
+#elif defined(WIN32)
+ HANDLE sem;
+#else
+ PRInt8 notused;
+#endif
+};
+
+/*************************************************************************/
+
+struct PRStackStr {
+ /* head MUST be at offset 0; assembly language code relies on this */
+#if defined(AIX)
+ volatile PRStackElem prstk_head;
+#else
+ PRStackElem prstk_head;
+#endif
+
+ PRLock *prstk_lock;
+ char *prstk_name;
+};
+
+/************************************************************************/
+
+/* XXX this needs to be exported (sigh) */
+struct PRThreadStack {
+ PRCList links;
+ PRUintn flags;
+
+ char *allocBase; /* base of stack's allocated memory */
+ PRUint32 allocSize; /* size of stack's allocated memory */
+ char *stackBottom; /* bottom of stack from C's point of view */
+ char *stackTop; /* top of stack from C's point of view */
+ PRUint32 stackSize; /* size of usable portion of the stack */
+
+ PRSegment *seg;
+ PRThread* thr; /* back pointer to thread owning this stack */
+
+#if defined(_PR_PTHREADS)
+#else /* defined(_PR_PTHREADS) */
+ _MDThreadStack md;
+#endif /* defined(_PR_PTHREADS) */
+};
+
+extern void _PR_DestroyThreadPrivate(PRThread*);
+
+typedef void (PR_CALLBACK *_PRStartFn)(void *);
+
+struct PRThread {
+ PRUint32 state; /* thread's creation state */
+ PRThreadPriority priority; /* apparent priority, loosly defined */
+
+ void *arg; /* argument to the client's entry point */
+ _PRStartFn startFunc; /* the root of the client's thread */
+
+ PRThreadStack *stack; /* info about thread's stack (for GC) */
+ void *environment; /* pointer to execution environment */
+
+ PRThreadDumpProc dump; /* dump thread info out */
+ void *dumpArg; /* argument for the dump function */
+
+ /*
+ ** Per thread private data
+ */
+ PRUint32 tpdLength; /* thread's current vector length */
+ void **privateData; /* private data vector or NULL */
+ PRErrorCode errorCode; /* current NSPR error code | zero */
+ PRInt32 osErrorCode; /* mapping of errorCode | zero */
+ PRIntn errorStringLength; /* textLength from last call to PR_SetErrorText() */
+ PRInt32 errorStringSize; /* malloc()'d size of buffer | zero */
+ char *errorString; /* current error string | NULL */
+
+#if defined(_PR_PTHREADS)
+ pthread_t id; /* pthread identifier for the thread */
+ PRBool okToDelete; /* ok to delete the PRThread struct? */
+ PRCondVar *waiting; /* where the thread is waiting | NULL */
+ void *sp; /* recorded sp for garbage collection */
+ PRThread *next, *prev; /* simple linked list of all threads */
+ PRUint32 suspend; /* used to store suspend and resume flags */
+#ifdef PT_NO_SIGTIMEDWAIT
+ pthread_mutex_t suspendResumeMutex;
+ pthread_cond_t suspendResumeCV;
+#endif
+ PRUint32 interrupt_blocked; /* interrupt blocked */
+ struct pollfd *syspoll_list; /* Unix polling list used by PR_Poll */
+ PRUint32 syspoll_count; /* number of elements in syspoll_list */
+#if defined(_PR_POLL_WITH_SELECT)
+ int *selectfd_list; /* Unix fd's that PR_Poll selects on */
+ PRUint32 selectfd_count; /* number of elements in selectfd_list */
+#endif
+#elif defined(_PR_BTHREADS)
+ PRUint32 flags;
+ _MDThread md;
+ PRBool io_pending;
+ PRInt32 io_fd;
+ PRBool io_suspended;
+#else /* not pthreads or Be threads */
+ _MDLock threadLock; /* Lock to protect thread state variables.
+ * Protects the following fields:
+ * state
+ * priority
+ * links
+ * wait
+ * cpu
+ */
+ PRUint32 queueCount;
+ PRUint32 waitCount;
+
+ PRCList active; /* on list of all active threads */
+ PRCList links;
+ PRCList waitQLinks; /* when thread is PR_Wait'ing */
+ PRCList lockList; /* list of locks currently holding */
+ PRIntervalTime sleep; /* sleep time when thread is sleeping */
+ struct _wait {
+ struct PRLock *lock;
+ struct PRCondVar *cvar;
+ } wait;
+
+ PRUint32 id;
+ PRUint32 flags;
+ PRUint32 no_sched; /* Don't schedule the thread to run.
+ * This flag has relevance only when
+ * multiple NSPR CPUs are created.
+ * When a thread is de-scheduled, there
+ * is a narrow window of time in which
+ * the thread is put on the run queue
+ * but the scheduler is actually using
+ * the stack of this thread. It is safe
+ * to run this thread on a different CPU
+ * only when its stack is not in use on
+ * any other CPU. The no_sched flag is
+ * set during this interval to prevent
+ * the thread from being scheduled on a
+ * different CPU.
+ */
+
+ /* thread termination condition variable for join */
+ PRCondVar *term;
+
+ _PRCPU *cpu; /* cpu to which this thread is bound */
+ PRUint32 threadAllocatedOnStack;/* boolean */
+
+ /* When an async IO is in progress and a second async IO cannot be
+ * initiated, the io_pending flag is set to true. Some platforms will
+ * not use the io_pending flag. If the io_pending flag is true, then
+ * io_fd is the OS-file descriptor on which IO is pending.
+ */
+ PRBool io_pending;
+ PRInt32 io_fd;
+
+ /* If a timeout occurs or if an outstanding IO is interrupted and the
+ * OS doesn't support a real cancellation (NT or MAC), then the
+ * io_suspended flag will be set to true. The thread will be resumed
+ * but may run into trouble issuing additional IOs until the io_pending
+ * flag can be cleared
+ */
+ PRBool io_suspended;
+
+ _MDThread md;
+#endif
+};
+
+struct PRProcessAttr {
+ PRFileDesc *stdinFd;
+ PRFileDesc *stdoutFd;
+ PRFileDesc *stderrFd;
+ char *currentDirectory;
+ char *fdInheritBuffer;
+ PRSize fdInheritBufferSize;
+ PRSize fdInheritBufferUsed;
+};
+
+struct PRProcess {
+ _MDProcess md;
+};
+
+struct PRFileMap {
+ PRFileDesc *fd;
+ PRFileMapProtect prot;
+ _MDFileMap md;
+};
+
+/************************************************************************/
+
+/*
+** File descriptors of the NSPR layer can be in one of the
+** following states (stored in the 'state' field of struct
+** PRFilePrivate):
+** - _PR_FILEDESC_OPEN: The OS fd is open.
+** - _PR_FILEDESC_CLOSED: The OS fd is closed. The PRFileDesc
+** is still open but is unusable. The only operation allowed
+** on the PRFileDesc is PR_Close().
+** - _PR_FILEDESC_FREED: The OS fd is closed and the PRFileDesc
+** structure is freed.
+*/
+
+#define _PR_FILEDESC_OPEN 0xaaaaaaaa /* 1010101... */
+#define _PR_FILEDESC_CLOSED 0x55555555 /* 0101010... */
+#define _PR_FILEDESC_FREED 0x11111111
+
+/*
+** A boolean type with an additional "unknown" state
+*/
+
+typedef enum {
+ _PR_TRI_TRUE = 1,
+ _PR_TRI_FALSE = 0,
+ _PR_TRI_UNKNOWN = -1
+} _PRTriStateBool;
+
+struct PRFilePrivate {
+ PRInt32 state;
+ PRBool nonblocking;
+ _PRTriStateBool inheritable;
+ PRFileDesc *next;
+ PRIntn lockCount; /* 0: not locked
+ * -1: a native lockfile call is in progress
+ * > 0: # times the file is locked */
+#ifdef _PR_HAVE_PEEK_BUFFER
+ char *peekBuffer;
+ PRInt32 peekBufSize;
+ PRInt32 peekBytes;
+#endif
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ PRBool appendMode;
+#endif
+ _MDFileDesc md;
+#ifdef _PR_STRICT_ADDR_LEN
+ PRUint16 af; /* If the platform requires passing the exact
+ * length of the sockaddr structure for the
+ * address family of the socket to socket
+ * functions like accept(), we need to save
+ * the address family of the socket. */
+#endif
+};
+
+struct PRDir {
+ PRDirEntry d;
+ _MDDir md;
+};
+
+#ifdef MOZ_UNICODE
+struct PRDirUTF16 {
+ PRDirEntry d;
+ _MDDirUTF16 md;
+};
+#endif /* MOZ_UNICODE */
+
+extern void _PR_InitSegs(void);
+extern void _PR_InitStacks(void);
+extern void _PR_InitTPD(void);
+extern void _PR_InitMem(void);
+extern void _PR_InitEnv(void);
+extern void _PR_InitCMon(void);
+extern void _PR_InitIO(void);
+extern void _PR_InitLog(void);
+extern void _PR_InitNet(void);
+extern void _PR_InitClock(void);
+extern void _PR_InitLinker(void);
+extern void _PR_InitAtomic(void);
+extern void _PR_InitCPUs(void);
+extern void _PR_InitDtoa(void);
+extern void _PR_InitMW(void);
+extern void _PR_InitRWLocks(void);
+extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me);
+extern void _PR_CleanupThread(PRThread *thread);
+extern void _PR_CleanupCallOnce(void);
+extern void _PR_CleanupMW(void);
+extern void _PR_CleanupDtoa(void);
+extern void _PR_ShutdownLinker(void);
+extern void _PR_CleanupEnv(void);
+extern void _PR_CleanupIO(void);
+extern void _PR_CleanupNet(void);
+extern void _PR_CleanupLayerCache(void);
+extern void _PR_CleanupStacks(void);
+#ifdef WINNT
+extern void _PR_CleanupCPUs(void);
+#endif
+extern void _PR_CleanupThreads(void);
+extern void _PR_CleanupTPD(void);
+extern void _PR_Cleanup(void);
+extern void _PR_LogCleanup(void);
+extern void _PR_InitLayerCache(void);
+#ifdef GC_LEAK_DETECTOR
+extern void _PR_InitGarbageCollector(void);
+#endif
+
+extern PRBool _pr_initialized;
+extern void _PR_ImplicitInitialization(void);
+extern PRBool _PR_Obsolete(const char *obsolete, const char *preferred);
+
+/************************************************************************/
+
+struct PRSegment {
+ void *vaddr;
+ PRUint32 size;
+ PRUintn flags;
+#if defined(_PR_PTHREADS)
+#else /* defined(_PR_PTHREADS) */
+ _MDSegment md;
+#endif /* defined(_PR_PTHREADS) */
+};
+
+/* PRSegment.flags */
+#define _PR_SEG_VM 0x1
+
+/************************************************************************/
+
+extern PRInt32 _pr_pageSize;
+extern PRInt32 _pr_pageShift;
+
+extern PRLogModuleInfo *_pr_clock_lm;
+extern PRLogModuleInfo *_pr_cmon_lm;
+extern PRLogModuleInfo *_pr_io_lm;
+extern PRLogModuleInfo *_pr_cvar_lm;
+extern PRLogModuleInfo *_pr_mon_lm;
+extern PRLogModuleInfo *_pr_linker_lm;
+extern PRLogModuleInfo *_pr_sched_lm;
+extern PRLogModuleInfo *_pr_thread_lm;
+extern PRLogModuleInfo *_pr_gc_lm;
+
+extern PRFileDesc *_pr_stdin;
+extern PRFileDesc *_pr_stdout;
+extern PRFileDesc *_pr_stderr;
+
+/* Zone allocator */
+/*
+** The zone allocator code has hardcoded pthread types and
+** functions, so it can only be used in the pthreads version.
+** This can be fixed by replacing the hardcoded pthread types
+** and functions with macros that expand to the native thread
+** types and functions on each platform.
+*/
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#define _PR_ZONE_ALLOCATOR
+#endif
+
+#ifdef _PR_ZONE_ALLOCATOR
+extern void _PR_InitZones(void);
+extern void _PR_DestroyZones(void);
+#endif
+
+/* Overriding malloc, free, etc. */
+#if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \
+ && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \
+ && !defined(PURIFY) \
+ && !defined(DARWIN) \
+ && !defined(NEXTSTEP) \
+ && !defined(QNX) \
+ && !(defined (UNIXWARE) && defined (USE_SVR4_THREADS))
+#define _PR_OVERRIDE_MALLOC
+#endif
+
+/*************************************************************************
+* External machine-dependent code provided by each OS. * *
+*************************************************************************/
+
+/* Initialization related */
+extern void _PR_MD_EARLY_INIT(void);
+#define _PR_MD_EARLY_INIT _MD_EARLY_INIT
+
+extern void _PR_MD_INTERVAL_INIT(void);
+#define _PR_MD_INTERVAL_INIT _MD_INTERVAL_INIT
+
+NSPR_API(void) _PR_MD_FINAL_INIT(void);
+#define _PR_MD_FINAL_INIT _MD_FINAL_INIT
+
+/* Process control */
+
+extern PRProcess * _PR_MD_CREATE_PROCESS(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr);
+#define _PR_MD_CREATE_PROCESS _MD_CREATE_PROCESS
+
+#ifdef _MD_CREATE_PROCESS_DETACHED
+# define _PR_MD_CREATE_PROCESS_DETACHED _MD_CREATE_PROCESS_DETACHED
+#endif
+
+extern PRStatus _PR_MD_DETACH_PROCESS(PRProcess *process);
+#define _PR_MD_DETACH_PROCESS _MD_DETACH_PROCESS
+
+extern PRStatus _PR_MD_WAIT_PROCESS(PRProcess *process, PRInt32 *exitCode);
+#define _PR_MD_WAIT_PROCESS _MD_WAIT_PROCESS
+
+extern PRStatus _PR_MD_KILL_PROCESS(PRProcess *process);
+#define _PR_MD_KILL_PROCESS _MD_KILL_PROCESS
+
+/* Current Time */
+NSPR_API(PRTime) _PR_MD_NOW(void);
+#define _PR_MD_NOW _MD_NOW
+
+/* Environment related */
+extern char* _PR_MD_GET_ENV(const char *name);
+#define _PR_MD_GET_ENV _MD_GET_ENV
+
+extern PRIntn _PR_MD_PUT_ENV(const char *name);
+#define _PR_MD_PUT_ENV _MD_PUT_ENV
+
+/* Atomic operations */
+
+extern void _PR_MD_INIT_ATOMIC(void);
+#define _PR_MD_INIT_ATOMIC _MD_INIT_ATOMIC
+
+extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *);
+#define _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT
+
+extern PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *, PRInt32);
+#define _PR_MD_ATOMIC_ADD _MD_ATOMIC_ADD
+
+extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *);
+#define _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT
+
+extern PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32);
+#define _PR_MD_ATOMIC_SET _MD_ATOMIC_SET
+
+/* Garbage collection */
+
+/*
+** Save the registers that the GC would find interesting into the thread
+** "t". isCurrent will be non-zero if the thread state that is being
+** saved is the currently executing thread. Return the address of the
+** first register to be scanned as well as the number of registers to
+** scan in "np".
+**
+** If "isCurrent" is non-zero then it is allowed for the thread context
+** area to be used as scratch storage to hold just the registers
+** necessary for scanning.
+*/
+extern PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np);
+
+/* Time intervals */
+
+extern PRIntervalTime _PR_MD_GET_INTERVAL(void);
+#define _PR_MD_GET_INTERVAL _MD_GET_INTERVAL
+
+extern PRIntervalTime _PR_MD_INTERVAL_PER_SEC(void);
+#define _PR_MD_INTERVAL_PER_SEC _MD_INTERVAL_PER_SEC
+
+/* Affinity masks */
+
+extern PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask );
+#define _PR_MD_SETTHREADAFFINITYMASK _MD_SETTHREADAFFINITYMASK
+
+extern PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask);
+#define _PR_MD_GETTHREADAFFINITYMASK _MD_GETTHREADAFFINITYMASK
+
+/* File locking */
+
+extern PRStatus _PR_MD_LOCKFILE(PRInt32 osfd);
+#define _PR_MD_LOCKFILE _MD_LOCKFILE
+
+extern PRStatus _PR_MD_TLOCKFILE(PRInt32 osfd);
+#define _PR_MD_TLOCKFILE _MD_TLOCKFILE
+
+extern PRStatus _PR_MD_UNLOCKFILE(PRInt32 osfd);
+#define _PR_MD_UNLOCKFILE _MD_UNLOCKFILE
+
+/* Memory-mapped files */
+
+extern PRStatus _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size);
+#define _PR_MD_CREATE_FILE_MAP _MD_CREATE_FILE_MAP
+
+extern PRInt32 _PR_MD_GET_MEM_MAP_ALIGNMENT(void);
+#define _PR_MD_GET_MEM_MAP_ALIGNMENT _MD_GET_MEM_MAP_ALIGNMENT
+
+extern void * _PR_MD_MEM_MAP(
+ PRFileMap *fmap,
+ PROffset64 offset,
+ PRUint32 len);
+#define _PR_MD_MEM_MAP _MD_MEM_MAP
+
+extern PRStatus _PR_MD_MEM_UNMAP(void *addr, PRUint32 size);
+#define _PR_MD_MEM_UNMAP _MD_MEM_UNMAP
+
+extern PRStatus _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap);
+#define _PR_MD_CLOSE_FILE_MAP _MD_CLOSE_FILE_MAP
+
+/* Named Shared Memory */
+
+/*
+** Declare PRSharedMemory.
+*/
+struct PRSharedMemory
+{
+ char *ipcname; /* after conversion to native */
+ PRSize size; /* from open */
+ PRIntn mode; /* from open */
+ PRIntn flags; /* from open */
+#if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY)
+ int id;
+#elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY)
+ int id;
+#elif defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY)
+ HANDLE handle;
+#else
+ PRUint32 nothing; /* placeholder, nothing behind here */
+#endif
+ PRUint32 ident; /* guard word at end of struct */
+#define _PR_SHM_IDENT 0xdeadbad
+};
+
+extern PRSharedMemory * _MD_OpenSharedMemory(
+ const char *name,
+ PRSize size,
+ PRIntn flags,
+ PRIntn mode
+);
+#define _PR_MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory
+
+extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags );
+#define _PR_MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory
+
+extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr );
+#define _PR_MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory
+
+extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm );
+#define _PR_MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory
+
+extern PRStatus _MD_DeleteSharedMemory( const char *name );
+#define _PR_MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory
+
+extern PRFileMap* _md_OpenAnonFileMap(
+ const char *dirName,
+ PRSize size,
+ PRFileMapProtect prot
+);
+#define _PR_MD_OPEN_ANON_FILE_MAP _md_OpenAnonFileMap
+
+extern PRStatus _md_ExportFileMapAsString(
+ PRFileMap *fm,
+ PRSize bufSize,
+ char *buf
+);
+#define _PR_MD_EXPORT_FILE_MAP_AS_STRING _md_ExportFileMapAsString
+
+extern PRFileMap * _md_ImportFileMapFromString(
+ const char *fmstring
+);
+#define _PR_MD_IMPORT_FILE_MAP_FROM_STRING _md_ImportFileMapFromString
+
+
+
+/* Interprocess communications (IPC) */
+
+/*
+ * The maximum length of an NSPR IPC name, including the
+ * terminating null byte.
+ */
+#define PR_IPC_NAME_SIZE 1024
+
+/*
+ * Types of NSPR IPC objects
+ */
+typedef enum {
+ _PRIPCSem, /* semaphores */
+ _PRIPCShm /* shared memory segments */
+} _PRIPCType;
+
+/*
+ * Make a native IPC name from an NSPR IPC name.
+ */
+extern PRStatus _PR_MakeNativeIPCName(
+ const char *name, /* NSPR IPC name */
+ char *result, /* result buffer */
+ PRIntn size, /* size of result buffer */
+ _PRIPCType type /* type of IPC object */
+);
+
+/* Socket call error code */
+
+NSPR_API(PRInt32) _PR_MD_GET_SOCKET_ERROR(void);
+#define _PR_MD_GET_SOCKET_ERROR _MD_GET_SOCKET_ERROR
+
+/* Get name of current host */
+extern PRStatus _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen);
+#define _PR_MD_GETHOSTNAME _MD_GETHOSTNAME
+
+extern PRStatus _PR_MD_GETSYSINFO(PRSysInfo cmd, char *name, PRUint32 namelen);
+#define _PR_MD_GETSYSINFO _MD_GETSYSINFO
+
+/* File descriptor inheritance */
+
+/*
+ * If fd->secret->inheritable is _PR_TRI_UNKNOWN and we need to
+ * know the inheritable attribute of the fd, call this function
+ * to find that out. This typically requires a system call.
+ */
+extern void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd);
+#define _PR_MD_QUERY_FD_INHERITABLE _MD_QUERY_FD_INHERITABLE
+
+/* --- PR_GetRandomNoise() related things --- */
+
+extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size );
+#define _PR_MD_GET_RANDOM_NOISE(buf,size) _PR_MD_GetRandomNoise((buf),(size))
+extern PRSize _pr_CopyLowBits( void *dest, PRSize dstlen, void *src, PRSize srclen );
+
+/* end PR_GetRandomNoise() related */
+
+#ifdef XP_BEOS
+
+extern PRLock *_connectLock;
+
+typedef struct _ConnectListNode {
+ PRInt32 osfd;
+ PRNetAddr addr;
+ PRUint32 addrlen;
+ PRIntervalTime timeout;
+} ConnectListNode;
+
+extern ConnectListNode connectList[64];
+
+extern PRUint32 connectCount;
+
+#endif /* XP_BEOS */
+
+PR_END_EXTERN_C
+
+#endif /* primpl_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/private/prpriv.h b/src/libs/xpcom18a4/nsprpub/pr/include/private/prpriv.h
new file mode 100644
index 00000000..780376e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/private/prpriv.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prpriv_h___
+#define prpriv_h___
+
+/*
+ * NSPR 2.0 Private API
+ */
+
+#ifndef XP_MAC
+#include "private/pprio.h"
+#include "private/pprthred.h"
+#else
+#include "pprio.h"
+#include "pprthred.h"
+#endif
+
+#endif /* prpriv_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prlink.h b/src/libs/xpcom18a4/nsprpub/pr/include/prlink.h
new file mode 100644
index 00000000..5bdafec9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prlink.h
@@ -0,0 +1,271 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prlink_h___
+#define prlink_h___
+
+/*
+** API to static and dynamic linking.
+*/
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_SetLibraryPath VBoxNsprPR_SetLibraryPath
+#define PR_GetLibraryPath VBoxNsprPR_GetLibraryPath
+#define PR_GetLibraryName VBoxNsprPR_GetLibraryName
+#define PR_FreeLibraryName VBoxNsprPR_FreeLibraryName
+#define PR_LoadLibrary VBoxNsprPR_LoadLibrary
+#define PR_LoadLibraryWithFlags VBoxNsprPR_LoadLibraryWithFlags
+#define PR_UnloadLibrary VBoxNsprPR_UnloadLibrary
+#define PR_FindSymbol VBoxNsprPR_FindSymbol
+#define PR_FindFunctionSymbol VBoxNsprPR_FindFunctionSymbol
+#define PR_FindSymbolAndLibrary VBoxNsprPR_FindSymbolAndLibrary
+#define PR_FindFunctionSymbolAndLibrary VBoxNsprPR_FindFunctionSymbolAndLibrary
+#define PR_LoadStaticLibrary VBoxNsprPR_LoadStaticLibrary
+#define PR_GetLibraryFilePathname VBoxNsprPR_GetLibraryFilePathname
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PRLibrary PRLibrary;
+
+typedef struct PRStaticLinkTable {
+ const char *name;
+ void (*fp)();
+} PRStaticLinkTable;
+
+/*
+** Change the default library path to the given string. The string is
+** copied. This call will fail if it runs out of memory.
+**
+** The string provided as 'path' is copied. The caller can do whatever is
+** convenient with the argument when the function is complete.
+*/
+NSPR_API(PRStatus) PR_SetLibraryPath(const char *path);
+
+/*
+** Return a character string which contains the path used to search for
+** dynamically loadable libraries.
+**
+** The returned value is basically a copy of a PR_SetLibraryPath().
+** The storage is allocated by the runtime and becomes the responsibilty
+** of the caller.
+*/
+NSPR_API(char*) PR_GetLibraryPath(void);
+
+/*
+** Given a directory name "dir" and a library name "lib" construct a full
+** path name that will refer to the actual dynamically loaded
+** library. This does not test for existance of said file, it just
+** constructs the full filename. The name constructed is system dependent
+** and prepared for PR_LoadLibrary. The result must be free'd when the
+** caller is done with it.
+**
+** The storage for the result is allocated by the runtime and becomes the
+** responsibility of the caller.
+*/
+NSPR_API(char*) PR_GetLibraryName(const char *dir, const char *lib);
+
+/*
+**
+** Free the memory allocated, for the caller, by PR_GetLibraryName
+*/
+NSPR_API(void) PR_FreeLibraryName(char *mem);
+
+/*
+** Given a library "name" try to load the library. The argument "name"
+** is a machine-dependent name for the library, such as the full pathname
+** returned by PR_GetLibraryName. If the library is already loaded,
+** this function will avoid loading the library twice.
+**
+** If the library is loaded successfully, then a pointer to the PRLibrary
+** structure representing the library is returned. Otherwise, NULL is
+** returned.
+**
+** This increments the reference count of the library.
+*/
+NSPR_API(PRLibrary*) PR_LoadLibrary(const char *name);
+
+/*
+** Each operating system has its preferred way of specifying
+** a file in the file system. Most operating systems use
+** a pathname. Mac OS, on the other hand, uses the FSSpec
+** structure to specify a file. PRLibSpec allows NSPR clients
+** to use the type of file specification that is most efficient
+** for a particular platform.
+**
+** On some operating systems such as Mac OS, a shared library may
+** contain code fragments that can be individually loaded.
+** PRLibSpec also allows NSPR clients to identify a code fragment
+** in a library, if code fragments are supported by the OS.
+** A code fragment can be specified by name or by an integer index.
+**
+** Right now PRLibSpec supports three types of library specification:
+** a pathname, a Mac code fragment by name, and a Mac code fragment
+** by index.
+*/
+
+typedef enum PRLibSpecType {
+ PR_LibSpec_Pathname,
+ PR_LibSpec_MacNamedFragment,
+ PR_LibSpec_MacIndexedFragment
+} PRLibSpecType;
+
+struct FSSpec; /* Mac OS FSSpec */
+
+typedef struct PRLibSpec {
+ PRLibSpecType type;
+ union {
+ /* if type is PR_LibSpec_Pathname */
+ const char *pathname;
+
+ /* if type is PR_LibSpec_MacNamedFragment */
+ struct {
+ const struct FSSpec *fsspec;
+ const char *name;
+ } mac_named_fragment;
+
+ /* if type is PR_LibSpec_MacIndexedFragment */
+ struct {
+ const struct FSSpec *fsspec;
+ PRUint32 index;
+ } mac_indexed_fragment;
+ } value;
+} PRLibSpec;
+
+/*
+** The following bit flags may be or'd together and passed
+** as the 'flags' argument to PR_LoadLibraryWithFlags.
+** Flags not supported by the underlying OS are ignored.
+*/
+
+#define PR_LD_LAZY 0x1 /* equivalent to RTLD_LAZY on Unix */
+#define PR_LD_NOW 0x2 /* equivalent to RTLD_NOW on Unix */
+#define PR_LD_GLOBAL 0x4 /* equivalent to RTLD_GLOBAL on Unix */
+#define PR_LD_LOCAL 0x8 /* equivalent to RTLD_LOCAL on Unix */
+
+/*
+** Load the specified library, in the manner specified by 'flags'.
+*/
+
+NSPR_API(PRLibrary *)
+PR_LoadLibraryWithFlags(
+ PRLibSpec libSpec, /* the shared library */
+ PRIntn flags /* flags that affect the loading */
+);
+
+/*
+** Unload a previously loaded library. If the library was a static
+** library then the static link table will no longer be referenced. The
+** associated PRLibrary object is freed.
+**
+** PR_FAILURE is returned if the library cannot be unloaded.
+**
+** This function decrements the reference count of the library.
+*/
+NSPR_API(PRStatus) PR_UnloadLibrary(PRLibrary *lib);
+
+/*
+** Given the name of a procedure, return the address of the function that
+** implements the procedure, or NULL if no such function can be
+** found. This does not find symbols in the main program (the ".exe");
+** use PR_LoadStaticLibrary to register symbols in the main program.
+**
+** This function does not modify the reference count of the library.
+*/
+NSPR_API(void*) PR_FindSymbol(PRLibrary *lib, const char *name);
+
+/*
+** Similar to PR_FindSymbol, except that the return value is a pointer to
+** a function, and not a pointer to void. Casting between a data pointer
+** and a function pointer is not portable according to the C standard.
+** Any function pointer can be cast to any other function pointer.
+**
+** This function does not modify the reference count of the library.
+*/
+typedef void (*PRFuncPtr)();
+NSPR_API(PRFuncPtr) PR_FindFunctionSymbol(PRLibrary *lib, const char *name);
+
+/*
+** Finds a symbol in one of the currently loaded libraries. Given the
+** name of a procedure, return the address of the function that
+** implements the procedure, and return the library that contains that
+** symbol, or NULL if no such function can be found. This does not find
+** symbols in the main program (the ".exe"); use PR_AddStaticLibrary to
+** register symbols in the main program.
+**
+** This increments the reference count of the library.
+*/
+NSPR_API(void*) PR_FindSymbolAndLibrary(const char *name,
+ PRLibrary* *lib);
+
+/*
+** Similar to PR_FindSymbolAndLibrary, except that the return value is
+** a pointer to a function, and not a pointer to void. Casting between a
+** data pointer and a function pointer is not portable according to the C
+** standard. Any function pointer can be cast to any other function pointer.
+**
+** This increments the reference count of the library.
+*/
+NSPR_API(PRFuncPtr) PR_FindFunctionSymbolAndLibrary(const char *name,
+ PRLibrary* *lib);
+
+/*
+** Register a static link table with the runtime under the name
+** "name". The symbols present in the static link table will be made
+** available to PR_FindSymbol. If "name" is null then the symbols will be
+** made available to the library which represents the executable. The
+** tables are not copied.
+**
+** Returns the library object if successful, null otherwise.
+**
+** This increments the reference count of the library.
+*/
+NSPR_API(PRLibrary*) PR_LoadStaticLibrary(
+ const char *name, const PRStaticLinkTable *table);
+
+/*
+** Return the pathname of the file that the library "name" was loaded
+** from. "addr" is the address of a function defined in the library.
+**
+** The caller is responsible for freeing the result with PR_Free.
+*/
+NSPR_API(char *) PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr);
+
+PR_END_EXTERN_C
+
+#endif /* prlink_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prlock.h b/src/libs/xpcom18a4/nsprpub/pr/include/prlock.h
new file mode 100644
index 00000000..0cf5aa55
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prlock.h
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prlock.h
+** Description: API to basic locking functions of NSPR.
+**
+**
+** NSPR provides basic locking mechanisms for thread synchronization. Locks
+** are lightweight resource contention controls that prevent multiple threads
+** from accessing something (code/data) simultaneously.
+**/
+
+#ifndef prlock_h___
+#define prlock_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_DestroyLock VBoxNsprPR_DestroyLock
+#define PR_Lock VBoxNsprPR_Lock
+#define PR_NewLock VBoxNsprPR_NewLock
+#define PR_Unlock VBoxNsprPR_Unlock
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+/*
+ * PRLock --
+ *
+ * NSPR represents the lock as an opaque entity to the client of the
+ * API. All routines operate on a pointer to this opaque entity.
+ */
+
+typedef struct PRLock PRLock;
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/***********************************************************************
+** FUNCTION: PR_NewLock
+** DESCRIPTION:
+** Returns a pointer to a newly created opaque lock object.
+** INPUTS: void
+** OUTPUTS: void
+** RETURN: PRLock*
+** If the lock can not be created because of resource constraints, NULL
+** is returned.
+**
+***********************************************************************/
+NSPR_API(PRLock*) PR_NewLock(void);
+
+/***********************************************************************
+** FUNCTION: PR_DestroyLock
+** DESCRIPTION:
+** Destroys a given opaque lock object.
+** INPUTS: PRLock *lock
+** Lock to be freed.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+NSPR_API(void) PR_DestroyLock(PRLock *lock);
+
+/***********************************************************************
+** FUNCTION: PR_Lock
+** DESCRIPTION:
+** Lock a lock.
+** INPUTS: PRLock *lock
+** Lock to locked.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+NSPR_API(void) PR_Lock(PRLock *lock);
+
+/***********************************************************************
+** FUNCTION: PR_Unlock
+** DESCRIPTION:
+** Unlock a lock. Unlocking an unlocked lock has undefined results.
+** INPUTS: PRLock *lock
+** Lock to unlocked.
+** OUTPUTS: void
+** RETURN: PR_STATUS
+** Returns PR_FAILURE if the caller does not own the lock.
+***********************************************************************/
+NSPR_API(PRStatus) PR_Unlock(PRLock *lock);
+
+PR_END_EXTERN_C
+
+#endif /* prlock_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prlog.h b/src/libs/xpcom18a4/nsprpub/pr/include/prlog.h
new file mode 100644
index 00000000..7f3369c6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prlog.h
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prlog_h___
+#define prlog_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_NewLogModule VBoxNsprPR_NewLogModule
+#define PR_SetLogFile VBoxNsprPR_SetLogFile
+#define PR_SetLogBuffering VBoxNsprPR_SetLogBuffering
+#define PR_LogPrint VBoxNsprPR_LogPrint
+#define PR_LogFlush VBoxNsprPR_LogFlush
+#define PR_Assert VBoxNsprPR_Assert
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** prlog.h -- Declare interfaces to NSPR's Logging service
+**
+** NSPR provides a logging service that is used by NSPR itself and is
+** available to client programs.
+**
+** To use the service from a client program, you should create a
+** PRLogModuleInfo structure by calling PR_NewLogModule(). After
+** creating the LogModule, you can write to the log using the PR_LOG()
+** macro.
+**
+** Initialization of the log service is handled by NSPR initialization.
+**
+** At execution time, you must enable the log service. To enable the
+** log service, set the environment variable: NSPR_LOG_MODULES
+** variable.
+**
+** NSPR_LOG_MODULES variable has the form:
+**
+** <moduleName>:<value>[, <moduleName>:<value>]*
+**
+** Where:
+** <moduleName> is the name passed to PR_NewLogModule().
+** <value> is a numeric constant, e.g. 5. This value is the maximum
+** value of a log event, enumerated by PRLogModuleLevel, that you want
+** written to the log.
+**
+** For example: to record all events of greater value than or equal to
+** PR_LOG_ERROR for a LogModule names "gizmo", say:
+**
+** set NSPR_LOG_MODULES=gizmo:2
+**
+** Note that you must specify the numeric value of PR_LOG_ERROR.
+**
+** Special LogModule names are provided for controlling NSPR's log
+** service at execution time. These controls should be set in the
+** NSPR_LOG_MODULES environment variable at execution time to affect
+** NSPR's log service for your application.
+**
+** The special LogModule "all" enables all LogModules. To enable all
+** LogModule calls to PR_LOG(), say:
+**
+** set NSPR_LOG_MODULES=all:5
+**
+** The special LogModule name "sync" tells the NSPR log service to do
+** unbuffered logging.
+**
+** The special LogModule name "bufsize:<size>" tells NSPR to set the
+** log buffer to <size>.
+**
+** The environment variable NSPR_LOG_FILE specifies the log file to use
+** unless the default of "stderr" is acceptable. For MS Windows
+** systems, NSPR_LOG_FILE can be set to a special value: "WinDebug"
+** (case sensitive). This value causes PR_LOG() output to be written
+** using the Windows API OutputDebugString(). OutputDebugString()
+** writes to the debugger window; some people find this helpful.
+**
+**
+** To put log messages in your programs, use the PR_LOG macro:
+**
+** PR_LOG(<module>, <level>, (<printfString>, <args>*));
+**
+** Where <module> is the address of a PRLogModuleInfo structure, and
+** <level> is one of the levels defined by the enumeration:
+** PRLogModuleLevel. <args> is a printf() style of argument list. That
+** is: (fmtstring, ...).
+**
+** Example:
+**
+** main() {
+** PRIntn one = 1;
+** PRLogModuleInfo * myLm = PR_NewLogModule("gizmo");
+** PR_LOG( myLm, PR_LOG_ALWAYS, ("Log this! %d\n", one));
+** return;
+** }
+**
+** Note the use of printf() style arguments as the third agrument(s) to
+** PR_LOG().
+**
+** After compiling and linking you application, set the environment:
+**
+** set NSPR_LOG_MODULES=gizmo:5
+** set NSPR_LOG_FILE=logfile.txt
+**
+** When you execute your application, the string "Log this! 1" will be
+** written to the file "logfile.txt".
+**
+** Note to NSPR engineers: a number of PRLogModuleInfo structures are
+** defined and initialized in prinit.c. See this module for ideas on
+** what to log where.
+**
+*/
+
+typedef enum PRLogModuleLevel {
+ PR_LOG_NONE = 0, /* nothing */
+ PR_LOG_ALWAYS = 1, /* always printed */
+ PR_LOG_ERROR = 2, /* error messages */
+ PR_LOG_WARNING = 3, /* warning messages */
+ PR_LOG_DEBUG = 4, /* debug messages */
+
+ PR_LOG_NOTICE = PR_LOG_DEBUG, /* notice messages */
+ PR_LOG_WARN = PR_LOG_WARNING, /* warning messages */
+ PR_LOG_MIN = PR_LOG_DEBUG, /* minimal debugging messages */
+ PR_LOG_MAX = PR_LOG_DEBUG /* maximal debugging messages */
+} PRLogModuleLevel;
+
+/*
+** One of these structures is created for each module that uses logging.
+** "name" is the name of the module
+** "level" is the debugging level selected for that module
+*/
+typedef struct PRLogModuleInfo {
+ const char *name;
+ PRLogModuleLevel level;
+ struct PRLogModuleInfo *next;
+} PRLogModuleInfo;
+
+/*
+** Create a new log module.
+*/
+NSPR_API(PRLogModuleInfo*) PR_NewLogModule(const char *name);
+
+/*
+** Set the file to use for logging. Returns PR_FALSE if the file cannot
+** be created
+*/
+NSPR_API(PRBool) PR_SetLogFile(const char *name);
+
+/*
+** Set the size of the logging buffer. If "buffer_size" is zero then the
+** logging becomes "synchronous" (or unbuffered).
+*/
+NSPR_API(void) PR_SetLogBuffering(PRIntn buffer_size);
+
+/*
+** Print a string to the log. "fmt" is a PR_snprintf format type. All
+** messages printed to the log are preceeded by the name of the thread
+** and a time stamp. Also, the routine provides a missing newline if one
+** is not provided.
+*/
+NSPR_API(void) PR_LogPrint(const char *fmt, ...);
+
+/*
+** Flush the log to its file.
+*/
+NSPR_API(void) PR_LogFlush(void);
+
+/*
+** Windoze 16 can't support a large static string space for all of the
+** various debugging strings so logging is not enabled for it.
+*/
+#if (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16)
+#define PR_LOGGING 1
+
+#define PR_LOG_TEST(_module,_level) \
+ ((_module)->level >= (_level))
+
+/*
+** Log something.
+** "module" is the address of a PRLogModuleInfo structure
+** "level" is the desired logging level
+** "args" is a variable length list of arguments to print, in the following
+** format: ("printf style format string", ...)
+*/
+#define PR_LOG(_module,_level,_args) \
+ PR_BEGIN_MACRO \
+ if (PR_LOG_TEST(_module,_level)) { \
+ PR_LogPrint _args; \
+ } \
+ PR_END_MACRO
+
+#else /* (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16) */
+
+#undef PR_LOGGING
+#define PR_LOG_TEST(module,level) 0
+#define PR_LOG(module,level,args)
+
+#endif /* (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16) */
+
+#ifndef NO_NSPR_10_SUPPORT
+
+#ifdef PR_LOGGING
+#define PR_LOG_BEGIN PR_LOG
+#define PR_LOG_END PR_LOG
+#define PR_LOG_DEFINE PR_NewLogModule
+#else
+#define PR_LOG_BEGIN(module,level,args)
+#define PR_LOG_END(module,level,args)
+#define PR_LOG_DEFINE(_name) NULL
+#endif /* PR_LOGGING */
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
+
+NSPR_API(void) PR_Assert(const char *s, const char *file, PRIntn ln);
+#define PR_ASSERT(_expr) \
+ ((_expr)?((void)0):PR_Assert(# _expr,__FILE__,__LINE__))
+
+#define PR_NOT_REACHED(_reasonStr) \
+ PR_Assert(_reasonStr,__FILE__,__LINE__)
+
+#else
+
+#define PR_ASSERT(expr) ((void) 0)
+#define PR_NOT_REACHED(reasonStr)
+
+#endif /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */
+
+PR_END_EXTERN_C
+
+#endif /* prlog_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prlong.h b/src/libs/xpcom18a4/nsprpub/pr/include/prlong.h
new file mode 100644
index 00000000..b99dd247
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prlong.h
@@ -0,0 +1,440 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prlong.h
+** Description: Portable access to 64 bit numerics
+**
+** Long-long (64-bit signed integer type) support. Some C compilers
+** don't support 64 bit integers yet, so we use these macros to
+** support both machines that do and don't.
+**/
+#ifndef prlong_h___
+#define prlong_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define LL_MaxInt VBoxNsllLL_MaxInt
+#define LL_MaxUint VBoxNsllLL_MaxUint
+#define LL_MinInt VBoxNsllLL_MinInt
+#define LL_Zero VBoxNsllLL_Zero
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/***********************************************************************
+** DEFINES: LL_MaxInt
+** LL_MinInt
+** LL_Zero
+** LL_MaxUint
+** DESCRIPTION:
+** Various interesting constants and static variable
+** initializer
+***********************************************************************/
+#if defined(HAVE_WATCOM_BUG_2)
+PRInt64 __pascal __loadds __export
+ LL_MaxInt(void);
+PRInt64 __pascal __loadds __export
+ LL_MinInt(void);
+PRInt64 __pascal __loadds __export
+ LL_Zero(void);
+PRUint64 __pascal __loadds __export
+ LL_MaxUint(void);
+#else
+NSPR_API(PRInt64) LL_MaxInt(void);
+NSPR_API(PRInt64) LL_MinInt(void);
+NSPR_API(PRInt64) LL_Zero(void);
+NSPR_API(PRUint64) LL_MaxUint(void);
+#endif
+
+#define LL_MAXINT LL_MaxInt()
+#define LL_MININT LL_MinInt()
+#define LL_ZERO LL_Zero()
+#define LL_MAXUINT LL_MaxUint()
+
+#if defined(HAVE_LONG_LONG)
+
+#if PR_BYTES_PER_LONG == 8
+#define LL_INIT(hi, lo) ((hi ## L << 32) + lo ## L)
+#elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__)
+#define LL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64)
+#else
+#define LL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL)
+#endif
+
+/***********************************************************************
+** MACROS: LL_*
+** DESCRIPTION:
+** The following macros define portable access to the 64 bit
+** math facilities.
+**
+***********************************************************************/
+
+/***********************************************************************
+** MACROS: LL_<relational operators>
+**
+** LL_IS_ZERO Test for zero
+** LL_EQ Test for equality
+** LL_NE Test for inequality
+** LL_GE_ZERO Test for zero or positive
+** LL_CMP Compare two values
+***********************************************************************/
+#define LL_IS_ZERO(a) ((a) == 0)
+#define LL_EQ(a, b) ((a) == (b))
+#define LL_NE(a, b) ((a) != (b))
+#define LL_GE_ZERO(a) ((a) >= 0)
+#define LL_CMP(a, op, b) ((PRInt64)(a) op (PRInt64)(b))
+#define LL_UCMP(a, op, b) ((PRUint64)(a) op (PRUint64)(b))
+
+/***********************************************************************
+** MACROS: LL_<logical operators>
+**
+** LL_AND Logical and
+** LL_OR Logical or
+** LL_XOR Logical exclusion
+** LL_OR2 A disgusting deviation
+** LL_NOT Negation (one's complement)
+***********************************************************************/
+#define LL_AND(r, a, b) ((r) = (a) & (b))
+#define LL_OR(r, a, b) ((r) = (a) | (b))
+#define LL_XOR(r, a, b) ((r) = (a) ^ (b))
+#define LL_OR2(r, a) ((r) = (r) | (a))
+#define LL_NOT(r, a) ((r) = ~(a))
+
+/***********************************************************************
+** MACROS: LL_<mathematical operators>
+**
+** LL_NEG Negation (two's complement)
+** LL_ADD Summation (two's complement)
+** LL_SUB Difference (two's complement)
+***********************************************************************/
+#define LL_NEG(r, a) ((r) = -(a))
+#define LL_ADD(r, a, b) ((r) = (a) + (b))
+#define LL_SUB(r, a, b) ((r) = (a) - (b))
+
+/***********************************************************************
+** MACROS: LL_<mathematical operators>
+**
+** LL_MUL Product (two's complement)
+** LL_DIV Quotient (two's complement)
+** LL_MOD Modulus (two's complement)
+***********************************************************************/
+#define LL_MUL(r, a, b) ((r) = (a) * (b))
+#define LL_DIV(r, a, b) ((r) = (a) / (b))
+#define LL_MOD(r, a, b) ((r) = (a) % (b))
+
+/***********************************************************************
+** MACROS: LL_<shifting operators>
+**
+** LL_SHL Shift left [0..64] bits
+** LL_SHR Shift right [0..64] bits with sign extension
+** LL_USHR Unsigned shift right [0..64] bits
+** LL_ISHL Signed shift left [0..64] bits
+***********************************************************************/
+#define LL_SHL(r, a, b) ((r) = (PRInt64)(a) << (b))
+#define LL_SHR(r, a, b) ((r) = (PRInt64)(a) >> (b))
+#define LL_USHR(r, a, b) ((r) = (PRUint64)(a) >> (b))
+#define LL_ISHL(r, a, b) ((r) = (PRInt64)(a) << (b))
+
+/***********************************************************************
+** MACROS: LL_<conversion operators>
+**
+** LL_L2I Convert to signed 32 bit
+** LL_L2UI Convert to unsigned 32 bit
+** LL_L2F Convert to floating point
+** LL_L2D Convert to floating point
+** LL_I2L Convert signed to 64 bit
+** LL_UI2L Convert unsigned to 64 bit
+** LL_F2L Convert float to 64 bit
+** LL_D2L Convert float to 64 bit
+***********************************************************************/
+#define LL_L2I(i, l) ((i) = (PRInt32)(l))
+#define LL_L2UI(ui, l) ((ui) = (PRUint32)(l))
+#define LL_L2F(f, l) ((f) = (PRFloat64)(l))
+#define LL_L2D(d, l) ((d) = (PRFloat64)(l))
+
+#define LL_I2L(l, i) ((l) = (PRInt64)(i))
+#define LL_UI2L(l, ui) ((l) = (PRInt64)(ui))
+#define LL_F2L(l, f) ((l) = (PRInt64)(f))
+#define LL_D2L(l, d) ((l) = (PRInt64)(d))
+
+/***********************************************************************
+** MACROS: LL_UDIVMOD
+** DESCRIPTION:
+** Produce both a quotient and a remainder given an unsigned
+** INPUTS: PRUint64 a: The dividend of the operation
+** PRUint64 b: The quotient of the operation
+** OUTPUTS: PRUint64 *qp: pointer to quotient
+** PRUint64 *rp: pointer to remainder
+***********************************************************************/
+#define LL_UDIVMOD(qp, rp, a, b) \
+ (*(qp) = ((PRUint64)(a) / (b)), \
+ *(rp) = ((PRUint64)(a) % (b)))
+
+#else /* !HAVE_LONG_LONG */
+
+#ifdef IS_LITTLE_ENDIAN
+#define LL_INIT(hi, lo) {PR_UINT32(lo), PR_UINT32(hi)}
+#else
+#define LL_INIT(hi, lo) {PR_UINT32(hi), PR_UINT32(lo)}
+#endif
+
+#define LL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0))
+#define LL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo))
+#define LL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo))
+#define LL_GE_ZERO(a) (((a).hi >> 31) == 0)
+
+#define LL_CMP(a, op, b) (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \
+ ((PRInt32)(a).hi op (PRInt32)(b).hi))
+#define LL_UCMP(a, op, b) (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \
+ ((a).hi op (b).hi))
+
+#define LL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \
+ (r).hi = (a).hi & (b).hi)
+#define LL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \
+ (r).hi = (a).hi | (b).hi)
+#define LL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \
+ (r).hi = (a).hi ^ (b).hi)
+#define LL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \
+ (r).hi = (r).hi | (a).hi)
+#define LL_NOT(r, a) ((r).lo = ~(a).lo, \
+ (r).hi = ~(a).hi)
+
+#define LL_NEG(r, a) ((r).lo = -(PRInt32)(a).lo, \
+ (r).hi = -(PRInt32)(a).hi - ((r).lo != 0))
+#define LL_ADD(r, a, b) { \
+ PRInt64 _a, _b; \
+ _a = a; _b = b; \
+ (r).lo = _a.lo + _b.lo; \
+ (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \
+}
+
+#define LL_SUB(r, a, b) { \
+ PRInt64 _a, _b; \
+ _a = a; _b = b; \
+ (r).lo = _a.lo - _b.lo; \
+ (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \
+}
+
+#define LL_MUL(r, a, b) { \
+ PRInt64 _a, _b; \
+ _a = a; _b = b; \
+ LL_MUL32(r, _a.lo, _b.lo); \
+ (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \
+}
+
+#define _lo16(a) ((a) & PR_BITMASK(16))
+#define _hi16(a) ((a) >> 16)
+
+#define LL_MUL32(r, a, b) { \
+ PRUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \
+ _a1 = _hi16(a), _a0 = _lo16(a); \
+ _b1 = _hi16(b), _b0 = _lo16(b); \
+ _y0 = _a0 * _b0; \
+ _y1 = _a0 * _b1; \
+ _y2 = _a1 * _b0; \
+ _y3 = _a1 * _b1; \
+ _y1 += _hi16(_y0); /* can't carry */ \
+ _y1 += _y2; /* might carry */ \
+ if (_y1 < _y2) \
+ _y3 += (PRUint32)(PR_BIT(16)); /* propagate */ \
+ (r).lo = (_lo16(_y1) << 16) + _lo16(_y0); \
+ (r).hi = _y3 + _hi16(_y1); \
+}
+
+#define LL_UDIVMOD(qp, rp, a, b) ll_udivmod(qp, rp, a, b)
+
+NSPR_API(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b);
+
+#define LL_DIV(r, a, b) { \
+ PRInt64 _a, _b; \
+ PRUint32 _negative = (PRInt32)(a).hi < 0; \
+ if (_negative) { \
+ LL_NEG(_a, a); \
+ } else { \
+ _a = a; \
+ } \
+ if ((PRInt32)(b).hi < 0) { \
+ _negative ^= 1; \
+ LL_NEG(_b, b); \
+ } else { \
+ _b = b; \
+ } \
+ LL_UDIVMOD(&(r), 0, _a, _b); \
+ if (_negative) \
+ LL_NEG(r, r); \
+}
+
+#define LL_MOD(r, a, b) { \
+ PRInt64 _a, _b; \
+ PRUint32 _negative = (PRInt32)(a).hi < 0; \
+ if (_negative) { \
+ LL_NEG(_a, a); \
+ } else { \
+ _a = a; \
+ } \
+ if ((PRInt32)(b).hi < 0) { \
+ LL_NEG(_b, b); \
+ } else { \
+ _b = b; \
+ } \
+ LL_UDIVMOD(0, &(r), _a, _b); \
+ if (_negative) \
+ LL_NEG(r, r); \
+}
+
+#define LL_SHL(r, a, b) { \
+ if (b) { \
+ PRInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = _a.lo << ((b) & 31); \
+ (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \
+ } else { \
+ (r).lo = 0; \
+ (r).hi = _a.lo << ((b) & 31); \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+/* a is an PRInt32, b is PRInt32, r is PRInt64 */
+#define LL_ISHL(r, a, b) { \
+ if (b) { \
+ PRInt64 _a; \
+ _a.lo = (a); \
+ _a.hi = 0; \
+ if ((b) < 32) { \
+ (r).lo = (a) << ((b) & 31); \
+ (r).hi = ((a) >> (32 - (b))); \
+ } else { \
+ (r).lo = 0; \
+ (r).hi = (a) << ((b) & 31); \
+ } \
+ } else { \
+ (r).lo = (a); \
+ (r).hi = 0; \
+ } \
+}
+
+#define LL_SHR(r, a, b) { \
+ if (b) { \
+ PRInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
+ (r).hi = (PRInt32)_a.hi >> ((b) & 31); \
+ } else { \
+ (r).lo = (PRInt32)_a.hi >> ((b) & 31); \
+ (r).hi = (PRInt32)_a.hi >> 31; \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+#define LL_USHR(r, a, b) { \
+ if (b) { \
+ PRInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
+ (r).hi = _a.hi >> ((b) & 31); \
+ } else { \
+ (r).lo = _a.hi >> ((b) & 31); \
+ (r).hi = 0; \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+#define LL_L2I(i, l) ((i) = (l).lo)
+#define LL_L2UI(ui, l) ((ui) = (l).lo)
+#define LL_L2F(f, l) { double _d; LL_L2D(_d, l); (f) = (PRFloat64)_d; }
+
+#define LL_L2D(d, l) { \
+ int _negative; \
+ PRInt64 _absval; \
+ \
+ _negative = (l).hi >> 31; \
+ if (_negative) { \
+ LL_NEG(_absval, l); \
+ } else { \
+ _absval = l; \
+ } \
+ (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \
+ if (_negative) \
+ (d) = -(d); \
+}
+
+#define LL_I2L(l, i) { PRInt32 _i = ((PRInt32)(i)) >> 31; (l).lo = (i); (l).hi = _i; }
+#define LL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0)
+#define LL_F2L(l, f) { double _d = (double)f; LL_D2L(l, _d); }
+
+#define LL_D2L(l, d) { \
+ int _negative; \
+ double _absval, _d_hi; \
+ PRInt64 _lo_d; \
+ \
+ _negative = ((d) < 0); \
+ _absval = _negative ? -(d) : (d); \
+ \
+ (l).hi = _absval / 4.294967296e9; \
+ (l).lo = 0; \
+ LL_L2D(_d_hi, l); \
+ _absval -= _d_hi; \
+ _lo_d.hi = 0; \
+ if (_absval < 0) { \
+ _lo_d.lo = -_absval; \
+ LL_SUB(l, l, _lo_d); \
+ } else { \
+ _lo_d.lo = _absval; \
+ LL_ADD(l, l, _lo_d); \
+ } \
+ \
+ if (_negative) \
+ LL_NEG(l, l); \
+}
+
+#endif /* !HAVE_LONG_LONG */
+
+PR_END_EXTERN_C
+
+#endif /* prlong_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prmem.h b/src/libs/xpcom18a4/nsprpub/pr/include/prmem.h
new file mode 100644
index 00000000..de4d15fd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prmem.h
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prmem.h
+** Description: API to NSPR 2.0 memory management functions
+**
+*/
+#ifndef prmem_h___
+#define prmem_h___
+
+#include "prtypes.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_Malloc VBoxNsprPR_Malloc
+#define PR_Calloc VBoxNsprPR_Calloc
+#define PR_Realloc VBoxNsprPR_Realloc
+#define PR_Free VBoxNsprPR_Free
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Thread safe memory allocation.
+**
+** NOTE: pr wraps up malloc, free, calloc, realloc so they are already
+** thread safe (and are not declared here - look in stdlib.h).
+*/
+
+/*
+** PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free have the same signatures
+** as their libc equivalent malloc, calloc, realloc, and free, and have
+** the same semantics. (Note that the argument type size_t is replaced
+** by PRUint32.) Memory allocated by PR_Malloc, PR_Calloc, or PR_Realloc
+** must be freed by PR_Free.
+*/
+
+NSPR_API(void *) PR_Malloc(PRUint32 size);
+
+NSPR_API(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize);
+
+NSPR_API(void *) PR_Realloc(void *ptr, PRUint32 size);
+
+NSPR_API(void) PR_Free(void *ptr);
+
+/*
+** The following are some convenience macros defined in terms of
+** PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free.
+*/
+
+/***********************************************************************
+** FUNCTION: PR_MALLOC()
+** DESCRIPTION:
+** PR_NEW() allocates an untyped item of size _size from the heap.
+** INPUTS: _size: size in bytes of item to be allocated
+** OUTPUTS: untyped pointer to the node allocated
+** RETURN: pointer to node or error returned from malloc().
+***********************************************************************/
+#define PR_MALLOC(_bytes) (PR_Malloc((_bytes)))
+
+/***********************************************************************
+** FUNCTION: PR_NEW()
+** DESCRIPTION:
+** PR_NEW() allocates an item of type _struct from the heap.
+** INPUTS: _struct: a data type
+** OUTPUTS: pointer to _struct
+** RETURN: pointer to _struct or error returns from malloc().
+***********************************************************************/
+#define PR_NEW(_struct) ((_struct *) PR_MALLOC(sizeof(_struct)))
+
+/***********************************************************************
+** FUNCTION: PR_REALLOC()
+** DESCRIPTION:
+** PR_REALLOC() re-allocates _ptr bytes from the heap as a _size
+** untyped item.
+** INPUTS: _ptr: pointer to node to reallocate
+** _size: size of node to allocate
+** OUTPUTS: pointer to node allocated
+** RETURN: pointer to node allocated
+***********************************************************************/
+#define PR_REALLOC(_ptr, _size) (PR_Realloc((_ptr), (_size)))
+
+/***********************************************************************
+** FUNCTION: PR_CALLOC()
+** DESCRIPTION:
+** PR_CALLOC() allocates a _size bytes untyped item from the heap
+** and sets the allocated memory to all 0x00.
+** INPUTS: _size: size of node to allocate
+** OUTPUTS: pointer to node allocated
+** RETURN: pointer to node allocated
+***********************************************************************/
+#define PR_CALLOC(_size) (PR_Calloc(1, (_size)))
+
+/***********************************************************************
+** FUNCTION: PR_NEWZAP()
+** DESCRIPTION:
+** PR_NEWZAP() allocates an item of type _struct from the heap
+** and sets the allocated memory to all 0x00.
+** INPUTS: _struct: a data type
+** OUTPUTS: pointer to _struct
+** RETURN: pointer to _struct
+***********************************************************************/
+#define PR_NEWZAP(_struct) ((_struct*)PR_Calloc(1, sizeof(_struct)))
+
+/***********************************************************************
+** FUNCTION: PR_DELETE()
+** DESCRIPTION:
+** PR_DELETE() unallocates an object previosly allocated via PR_NEW()
+** or PR_NEWZAP() to the heap.
+** INPUTS: pointer to previously allocated object
+** OUTPUTS: the referenced object is returned to the heap
+** RETURN: void
+***********************************************************************/
+#define PR_DELETE(_ptr) { PR_Free(_ptr); (_ptr) = NULL; }
+
+/***********************************************************************
+** FUNCTION: PR_FREEIF()
+** DESCRIPTION:
+** PR_FREEIF() conditionally unallocates an object previously allocated
+** vial PR_NEW() or PR_NEWZAP(). If the pointer to the object is
+** equal to zero (0), the object is not released.
+** INPUTS: pointer to previously allocated object
+** OUTPUTS: the referenced object is conditionally returned to the heap
+** RETURN: void
+***********************************************************************/
+#define PR_FREEIF(_ptr) if (_ptr) PR_DELETE(_ptr)
+
+PR_END_EXTERN_C
+
+#endif /* prmem_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prmon.h b/src/libs/xpcom18a4/nsprpub/pr/include/prmon.h
new file mode 100644
index 00000000..ac317708
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prmon.h
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prmon_h___
+#define prmon_h___
+
+#include "prtypes.h"
+#include "prinrval.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_EnterMonitor VBoxNsprPR_EnterMonitor
+#define PR_ExitMonitor VBoxNsprPR_ExitMonitor
+#define PR_Notify VBoxNsprPR_Notify
+#define PR_NotifyAll VBoxNsprPR_NotifyAll
+#define PR_Wait VBoxNsprPR_Wait
+#define PR_NewMonitor VBoxNsprPR_NewMonitor
+#define PR_DestroyMonitor VBoxNsprPR_DestroyMonitor
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PRMonitor PRMonitor;
+
+/*
+** Create a new monitor. Monitors are re-entrant locks with a single built-in
+** condition variable.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low.
+*/
+NSPR_API(PRMonitor*) PR_NewMonitor(void);
+
+/*
+** Destroy a monitor. The caller is responsible for guaranteeing that the
+** monitor is no longer in use. There must be no thread waiting on the monitor's
+** condition variable and that the lock is not held.
+**
+*/
+NSPR_API(void) PR_DestroyMonitor(PRMonitor *mon);
+
+/*
+** Enter the lock associated with the monitor. If the calling thread currently
+** is in the monitor, the call to enter will silently succeed. In either case,
+** it will increment the entry count by one.
+*/
+NSPR_API(void) PR_EnterMonitor(PRMonitor *mon);
+
+/*
+** Decrement the entry count associated with the monitor. If the decremented
+** entry count is zero, the monitor is exited. Returns PR_FAILURE if the
+** calling thread has not entered the monitor.
+*/
+NSPR_API(PRStatus) PR_ExitMonitor(PRMonitor *mon);
+
+/*
+** Wait for a notify on the monitor's condition variable. Sleep for "ticks"
+** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is
+** indefinite).
+**
+** While the thread is waiting it exits the monitor (as if it called
+** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When
+** the wait has finished the thread regains control of the monitors lock
+** with the same entry count as before the wait began.
+**
+** The thread waiting on the monitor will be resumed when the monitor is
+** notified (assuming the thread is the next in line to receive the
+** notify) or when the "ticks" timeout elapses.
+**
+** Returns PR_FAILURE if the caller has not entered the monitor.
+*/
+NSPR_API(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks);
+
+/*
+** Notify a thread waiting on the monitor's condition variable. If a thread
+** is waiting on the condition variable (using PR_Wait) then it is awakened
+** and attempts to reenter the monitor.
+*/
+NSPR_API(PRStatus) PR_Notify(PRMonitor *mon);
+
+/*
+** Notify all of the threads waiting on the monitor's condition variable.
+** All of threads waiting on the condition are scheduled to reenter the
+** monitor.
+*/
+NSPR_API(PRStatus) PR_NotifyAll(PRMonitor *mon);
+
+PR_END_EXTERN_C
+
+#endif /* prmon_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prmwait.h b/src/libs/xpcom18a4/nsprpub/pr/include/prmwait.h
new file mode 100644
index 00000000..e116b17a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prmwait.h
@@ -0,0 +1,424 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#if defined(_PRMWAIT_H)
+#else
+#define _PRMWAIT_H
+
+#include "prio.h"
+#include "prtypes.h"
+#include "prclist.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_AddWaitFileDesc VBoxNsprPR_AddWaitFileDesc
+#define PR_CancelWaitFileDesc VBoxNsprPR_CancelWaitFileDesc
+#define PR_CancelWaitGroup VBoxNsprPR_CancelWaitGroup
+#define PR_CreateWaitGroup VBoxNsprPR_CreateWaitGroup
+#define PR_CreateMWaitEnumerator VBoxNsprPR_CreateMWaitEnumerator
+#define PR_DestroyWaitGroup VBoxNsprPR_DestroyWaitGroup
+#define PR_DestroyMWaitEnumerator VBoxNsprPR_DestroyMWaitEnumerator
+#define PR_EnumerateWaitGroup VBoxNsprPR_EnumerateWaitGroup
+#define PR_WaitRecvReady VBoxNsprPR_WaitRecvReady
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/********************************************************************************/
+/********************************************************************************/
+/********************************************************************************/
+/****************************** WARNING ****************************/
+/********************************************************************************/
+/**************************** This is work in progress. *************************/
+/************************** Do not make any assumptions *************************/
+/************************** about the stability of this *************************/
+/************************** API or the underlying imple- ************************/
+/************************** mentation. ************************/
+/********************************************************************************/
+/********************************************************************************/
+
+/*
+** STRUCTURE: PRWaitGroup
+** DESCRIPTION:
+** The client may define several wait groups in order to semantically
+** tie a collection of file descriptors for a single purpose. This allows
+** easier dispatching of threads that returned with active file descriptors
+** from the wait function.
+*/
+typedef struct PRWaitGroup PRWaitGroup;
+
+/*
+** ENUMERATION: PRMWStatus
+** DESCRIPTION:
+** This enumeration is used to indicate the completion status of
+** a receive wait object. Generally stated, a positive value indicates
+** that the operation is not yet complete. A zero value indicates
+** success (similar to PR_SUCCESS) and any negative value is an
+** indication of failure. The reason for the failure can be retrieved
+** by calling PR_GetError().
+**
+** PR_MW_PENDING The operation is still pending. None of the other
+** fields of the object are currently valid.
+** PR_MW_SUCCESS The operation is complete and it was successful.
+** PR_MW_FAILURE The operation failed. The reason for the failure
+** can be retrieved by calling PR_GetError().
+** PR_MW_TIMEOUT The amount of time allowed for by the object's
+** 'timeout' field has expired w/o the operation
+** otherwise coming to closure.
+** PR_MW_INTERRUPT The operation was cancelled, either by the client
+** calling PR_CancelWaitFileDesc() or destroying the
+** entire wait group (PR_DestroyWaitGroup()).
+*/
+typedef enum PRMWStatus
+{
+ PR_MW_PENDING = 1,
+ PR_MW_SUCCESS = 0,
+ PR_MW_FAILURE = -1,
+ PR_MW_TIMEOUT = -2,
+ PR_MW_INTERRUPT = -3
+} PRMWStatus;
+
+/*
+** STRUCTURE: PRMemoryDescriptor
+** DESCRIPTION:
+** THis is a descriptor for an interval of memory. It contains a
+** pointer to the first byte of that memory and the length (in
+** bytes) of the interval.
+*/
+typedef struct PRMemoryDescriptor
+{
+ void *start; /* pointer to first byte of memory */
+ PRSize length; /* length (in bytes) of memory interval */
+} PRMemoryDescriptor;
+
+/*
+** STRUCTURE: PRMWaitClientData
+** DESCRIPTION:
+** An opague stucture for which a client MAY give provide a concrete
+** definition and associate with a receive descriptor. The NSPR runtime
+** does not manage this field. It is completely up to the client.
+*/
+typedef struct PRMWaitClientData PRMWaitClientData;
+
+/*
+** STRUCTURE: PRRecvWait
+** DESCRIPTION:
+** A receive wait object contains the file descriptor that is subject
+** to the wait and the amount of time (beginning epoch established
+** when the object is presented to the runtime) the the channel should
+** block before abandoning the process.
+**
+** The success of the wait operation will be noted in the object's
+** 'outcome' field. The fields are not valid when the NSPR runtime
+** is in possession of the object.
+**
+** The memory descriptor describes an interval of writable memory
+** in the caller's address space where data from an initial read
+** can be placed. The description may indicate a null interval.
+*/
+typedef struct PRRecvWait
+{
+ PRCList internal; /* internal runtime linkages */
+
+ PRFileDesc *fd; /* file descriptor associated w/ object */
+ PRMWStatus outcome; /* outcome of the current/last operation */
+ PRIntervalTime timeout; /* time allowed for entire operation */
+
+ PRInt32 bytesRecv; /* number of bytes transferred into buffer */
+ PRMemoryDescriptor buffer; /* where to store first segment of input data */
+ PRMWaitClientData *client; /* pointer to arbitrary client defined data */
+} PRRecvWait;
+
+/*
+** STRUCTURE: PRMWaitEnumerator
+** DESCRIPTION:
+** An enumeration object is used to store the state of an existing
+** enumeration over a wait group. The opaque object must be allocated
+** by the client and the reference presented on each call to the
+** pseudo-stateless enumerator. The enumeration objects are sharable
+** only in serial fashion.
+*/
+typedef struct PRMWaitEnumerator PRMWaitEnumerator;
+
+
+/*
+** FUNCTION: PR_AddWaitFileDesc
+** DESCRIPTION:
+** This function will effectively add a file descriptor to the
+** list of those waiting for network receive. The new descriptor
+** will be semantically tied to the wait group specified.
+**
+** The ownership for the storage pointed to by 'desc' is temporarily
+** passed over the the NSPR runtime. It will be handed back by the
+** function PR_WaitRecvReady().
+**
+** INPUTS
+** group A reference to a PRWaitGroup or NULL. Wait groups are
+** created by calling PR_CreateWaitGroup() and are used
+** to semantically group various file descriptors by the
+** client's application.
+** desc A reference to a valid PRRecvWait. The object of the
+** reference must be preserved and not be modified
+** until its ownership is returned to the client.
+** RETURN
+** PRStatus An indication of success. If equal to PR_FAILUE details
+** of the failure are avaiable via PR_GetError().
+**
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** Invalid 'group' identifier or duplicate 'desc' object.
+** PR_OUT_OF_MEMORY_ERROR
+** Insuffient memory for internal data structures.
+** PR_INVALID_STATE_ERROR
+** The group is being destroyed.
+*/
+NSPR_API(PRStatus) PR_AddWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc);
+
+/*
+** FUNCTION: PR_WaitRecvReady
+** DESCRIPTION:
+** PR_WaitRecvReady will block the calling thread until one of the
+** file descriptors that have been added via PR_AddWaitFileDesc is
+** available for input I/O.
+** INPUT
+** group A pointer to a valid PRWaitGroup or NULL (the null
+** group. The function will block the caller until a
+** channel from the wait group becomes ready for receive
+** or there is some sort of error.
+** RETURN
+** PRReciveWait
+** When the caller is resumed it is either returned a
+** valid pointer to a previously added receive wait or
+** a NULL. If the latter, the function has terminated
+** for a reason that can be determined by calling
+** PR_GetError().
+** If a valid pointer is returned, the reference is to the
+** file descriptor contained in the receive wait object.
+** The outcome of the wait operation may still fail, and
+** if it has, that fact will be noted in the object's
+** outcome field. Details can be retrieved from PR_GetError().
+**
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** The 'group' is not known by the runtime.
+** PR_PENDING_INTERRUPT_ERROR
+ The thread was interrupted.
+** PR_INVALID_STATE_ERROR
+** The group is being destroyed.
+*/
+NSPR_API(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group);
+
+/*
+** FUNCTION: PR_CancelWaitFileDesc
+** DESCRIPTION:
+** PR_CancelWaitFileDesc is provided as a means for cancelling operations
+** on objects previously submitted by use of PR_AddWaitFileDesc(). If
+** the runtime knows of the object, it will be marked as having failed
+** because it was interrupted (similar to PR_Interrupt()). The first
+** available thread waiting on the group will be made to return the
+** PRRecvWait object with the outcome noted.
+**
+** INPUTS
+** group The wait group under which the wait receive object was
+** added.
+** desc A pointer to the wait receive object that is to be
+** cancelled.
+** RETURN
+** PRStatus If the wait receive object was located and associated
+** with the specified wait group, the status returned will
+** be PR_SUCCESS. There is still a race condition that would
+** permit the offected object to complete normally, but it
+** is assured that it will complete in the near future.
+** If the receive object or wait group are invalid, the
+** function will return with a status of PR_FAILURE.
+**
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** The 'group' argument is not recognized as a valid group.
+** PR_COLLECTION_EMPTY_ERROR
+** There are no more receive wait objects in the group's
+** collection.
+** PR_INVALID_STATE_ERROR
+** The group is being destroyed.
+*/
+NSPR_API(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc);
+
+/*
+** FUNCTION: PR_CancelWaitGroup
+** DESCRIPTION:
+** PR_CancelWaitGroup is provided as a means for cancelling operations
+** on objects previously submitted by use of PR_AddWaitFileDesc(). Each
+** successive call will return a pointer to a PRRecvWait object that
+** was previously registered via PR_AddWaitFileDesc(). If no wait
+** objects are associated with the wait group, a NULL will be returned.
+** This function should be called in a loop until a NULL is returned
+** to reclaim all the wait objects prior to calling PR_DestroyWaitGroup().
+**
+** INPUTS
+** group The wait group under which the wait receive object was
+** added.
+** RETURN
+** PRRecvWait* If the wait group is valid and at least one receive wait
+** object is present in the group, that object will be
+** marked as PR_MW_INTERRUPT'd and removed from the group's
+** queues. Otherwise a NULL will be returned and the reason
+** for the NULL may be retrieved by calling PR_GetError().
+**
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** PR_GROUP_EMPTY_ERROR
+*/
+NSPR_API(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group);
+
+/*
+** FUNCTION: PR_CreateWaitGroup
+** DESCRIPTION:
+** A wait group is an opaque object that a client may create in order
+** to semantically group various wait requests. Each wait group is
+** unique, including the default wait group (NULL). A wait request
+** that was added under a wait group will only be serviced by a caller
+** that specified the same wait group.
+**
+** INPUT
+** size The size of the hash table to be used to contain the
+** receive wait objects. This is just the initial size.
+** It will grow as it needs to, but to avoid that hassle
+** one can suggest a suitable size initially. It should
+** be ~30% larger than the maximum number of receive wait
+** objects expected.
+** RETURN
+** PRWaitGroup If successful, the function will return a pointer to an
+** object that was allocated by and owned by the runtime.
+** The reference remains valid until it is explicitly destroyed
+** by calling PR_DestroyWaitGroup().
+**
+** ERRORS
+** PR_OUT_OF_MEMORY_ERROR
+*/
+NSPR_API(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size);
+
+/*
+** FUNCTION: PR_DestroyWaitGroup
+** DESCRIPTION:
+** Undo the effects of PR_CreateWaitGroup(). Any receive wait operations
+** on the group will be treated as if the each had been the target of a
+** PR_CancelWaitFileDesc().
+**
+** INPUT
+** group Reference to a wait group previously allocated using
+** PR_CreateWaitGroup().
+** RETURN
+** PRStatus Will be PR_SUCCESS if the wait group was valid and there
+** are no receive wait objects in that group. Otherwise
+** will indicate PR_FAILURE.
+**
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** The 'group' argument does not reference a known object.
+** PR_INVALID_STATE_ERROR
+** The group still contains receive wait objects.
+*/
+NSPR_API(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group);
+
+/*
+** FUNCTION: PR_CreateMWaitEnumerator
+** DESCRIPTION:
+** The PR_CreateMWaitEnumerator() function returns a reference to an
+** opaque PRMWaitEnumerator object. The enumerator object is required
+** as an argument for each successive call in the stateless enumeration
+** of the indicated wait group.
+**
+** group The wait group that the enumeration is intended to
+** process. It may be be the default wait group (NULL).
+** RETURN
+** PRMWaitEnumerator* group
+** A reference to an object that will be used to store
+** intermediate state of enumerations.
+** ERRORS
+** Errors are indicated by the function returning a NULL.
+** PR_INVALID_ARGUMENT_ERROR
+** The 'group' argument does not reference a known object.
+** PR_OUT_OF_MEMORY_ERROR
+*/
+NSPR_API(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group);
+
+/*
+** FUNCTION: PR_DestroyMWaitEnumerator
+** DESCRIPTION:
+** Destroys the object created by PR_CreateMWaitEnumerator(). The reference
+** used as an argument becomes invalid.
+**
+** INPUT
+** PRMWaitEnumerator* enumerator
+** The PRMWaitEnumerator object to destroy.
+** RETURN
+** PRStatus
+** PR_SUCCESS if successful, PR_FAILURE otherwise.
+** ERRORS
+** PR_INVALID_ARGUMENT_ERROR
+** The enumerator is invalid.
+*/
+NSPR_API(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator);
+
+/*
+** FUNCTION: PR_EnumerateWaitGroup
+** DESCRIPTION:
+** PR_EnumerateWaitGroup is a thread safe enumerator over a wait group.
+** Each call to the enumerator must present a valid PRMWaitEnumerator
+** rererence and a pointer to the "previous" element returned from the
+** enumeration process or a NULL.
+**
+** An enumeration is started by passing a NULL as the "previous" value.
+** Subsequent calls to the enumerator must pass in the result of the
+** previous call. The enumeration end is signaled by the runtime returning
+** a NULL as the result.
+**
+** Modifications to the content of the wait group are allowed during
+** an enumeration. The effect is that the enumeration may have to be
+** "reset" and that may result in duplicates being returned from the
+** enumeration.
+**
+** An enumeration may be abandoned at any time. The runtime is not
+** keeping any state, so there are no issues in that regard.
+*/
+NSPR_API(PRRecvWait*) PR_EnumerateWaitGroup(
+ PRMWaitEnumerator *enumerator, const PRRecvWait *previous);
+
+PR_END_EXTERN_C
+
+#endif /* defined(_PRMWAIT_H) */
+
+/* prmwait.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prnetdb.h b/src/libs/xpcom18a4/nsprpub/pr/include/prnetdb.h
new file mode 100644
index 00000000..bd9a9eff
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prnetdb.h
@@ -0,0 +1,524 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prnetdb_h___
+#define prnetdb_h___
+
+#include "prtypes.h"
+#include "prio.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_StringToNetAddr VBoxNsprPR_StringToNetAddr
+#define PR_NetAddrToString VBoxNsprPR_NetAddrToString
+#define PR_GetHostByName VBoxNsprPR_GetHostByName
+#define PR_GetIPNodeByName VBoxNsprPR_GetIPNodeByName
+#define PR_GetHostByAddr VBoxNsprPR_GetHostByAddr
+#define PR_EnumerateHostEnt VBoxNsprPR_EnumerateHostEnt
+#define PR_InitializeNetAddr VBoxNsprPR_InitializeNetAddr
+#define PR_SetNetAddr VBoxNsprPR_SetNetAddr
+#define PR_IsNetAddrType VBoxNsprPR_IsNetAddrType
+#define PR_ConvertIPv4AddrToIPv6 VBoxNsprPR_ConvertIPv4AddrToIPv6
+#define PR_GetProtoByName VBoxNsprPR_GetProtoByName
+#define PR_GetProtoByNumber VBoxNsprPR_GetProtoByNumber
+#define PR_GetAddrInfoByName VBoxNsprPR_GetAddrInfoByName
+#define PR_FreeAddrInfo VBoxNsprPR_FreeAddrInfo
+#define PR_EnumerateAddrInfo VBoxNsprPR_EnumerateAddrInfo
+#define PR_GetCanonNameFromAddrInfo VBoxNsprPR_GetCanonNameFromAddrInfo
+#define PR_htonl VBoxNsprPR_htonl
+#define PR_htonll VBoxNsprPR_htonll
+#define PR_htons VBoxNsprPR_htons
+#define PR_ntohl VBoxNsprPR_ntohl
+#define PR_ntohll VBoxNsprPR_ntohll
+#define PR_ntohs VBoxNsprPR_ntohs
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+
+/*
+ *********************************************************************
+ * Translate an Internet address to/from a character string
+ *********************************************************************
+ */
+NSPR_API(PRStatus) PR_StringToNetAddr(
+ const char *string, PRNetAddr *addr);
+
+NSPR_API(PRStatus) PR_NetAddrToString(
+ const PRNetAddr *addr, char *string, PRUint32 size);
+
+/*
+** Structures returned by network data base library. All addresses are
+** supplied in host order, and returned in network order (suitable for
+** use in system calls).
+*/
+/*
+** Beware that WINSOCK.H defines h_addrtype and h_length as short.
+** Client code does direct struct copies of hostent to PRHostEnt and
+** hence the ifdef.
+*/
+typedef struct PRHostEnt {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+#if defined(WIN32) || defined(WIN16)
+ PRInt16 h_addrtype; /* host address type */
+ PRInt16 h_length; /* length of address */
+#else
+ PRInt32 h_addrtype; /* host address type */
+ PRInt32 h_length; /* length of address */
+#endif
+ char **h_addr_list; /* list of addresses from name server */
+} PRHostEnt;
+
+/* A safe size to use that will mostly work... */
+#if (defined(AIX) && defined(_THREAD_SAFE)) || defined(OSF1)
+#define PR_NETDB_BUF_SIZE sizeof(struct protoent_data)
+#else
+#define PR_NETDB_BUF_SIZE 1024
+#endif
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetHostByName()
+** Lookup a host by name.
+**
+** INPUTS:
+** char *hostname Character string defining the host name of interest
+** char *buf A scratch buffer for the runtime to return result.
+** This buffer is allocated by the caller.
+** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to
+** use is PR_NETDB_BUF_SIZE.
+** OUTPUTS:
+** PRHostEnt *hostentry
+** This structure is filled in by the runtime if
+** the function returns PR_SUCCESS. This structure
+** is allocated by the caller.
+** RETURN:
+** PRStatus PR_SUCCESS if the lookup succeeds. If it fails
+** the result will be PR_FAILURE and the reason
+** for the failure can be retrieved by PR_GetError().
+***********************************************************************/
+NSPR_API(PRStatus) PR_GetHostByName(
+ const char *hostname, char *buf, PRIntn bufsize, PRHostEnt *hostentry);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetIPNodeByName()
+** Lookup a host by name. Equivalent to getipnodebyname(AI_DEFAULT)
+** of RFC 2553.
+**
+** INPUTS:
+** char *hostname Character string defining the host name of interest
+** PRUint16 af Address family (either PR_AF_INET or PR_AF_INET6)
+** PRIntn flags Specifies the types of addresses that are searched
+** for and the types of addresses that are returned.
+** The only supported flag is PR_AI_DEFAULT.
+** char *buf A scratch buffer for the runtime to return result.
+** This buffer is allocated by the caller.
+** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to
+** use is PR_NETDB_BUF_SIZE.
+** OUTPUTS:
+** PRHostEnt *hostentry
+** This structure is filled in by the runtime if
+** the function returns PR_SUCCESS. This structure
+** is allocated by the caller.
+** RETURN:
+** PRStatus PR_SUCCESS if the lookup succeeds. If it fails
+** the result will be PR_FAILURE and the reason
+** for the failure can be retrieved by PR_GetError().
+***********************************************************************/
+
+
+#define PR_AI_ALL 0x08
+#define PR_AI_V4MAPPED 0x10
+#define PR_AI_ADDRCONFIG 0x20
+#define PR_AI_NOCANONNAME 0x8000
+#define PR_AI_DEFAULT (PR_AI_V4MAPPED | PR_AI_ADDRCONFIG)
+
+NSPR_API(PRStatus) PR_GetIPNodeByName(
+ const char *hostname,
+ PRUint16 af,
+ PRIntn flags,
+ char *buf,
+ PRIntn bufsize,
+ PRHostEnt *hostentry);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetHostByAddr()
+** Lookup a host entry by its network address.
+**
+** INPUTS:
+** char *hostaddr IP address of host in question
+** char *buf A scratch buffer for the runtime to return result.
+** This buffer is allocated by the caller.
+** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to
+** use is PR_NETDB_BUF_SIZE.
+** OUTPUTS:
+** PRHostEnt *hostentry
+** This structure is filled in by the runtime if
+** the function returns PR_SUCCESS. This structure
+** is allocated by the caller.
+** RETURN:
+** PRStatus PR_SUCCESS if the lookup succeeds. If it fails
+** the result will be PR_FAILURE and the reason
+** for the failure can be retrieved by PR_GetError().
+***********************************************************************/
+NSPR_API(PRStatus) PR_GetHostByAddr(
+ const PRNetAddr *hostaddr, char *buf, PRIntn bufsize, PRHostEnt *hostentry);
+
+/***********************************************************************
+** FUNCTION: PR_EnumerateHostEnt()
+** DESCRIPTION:
+** A stateless enumerator over a PRHostEnt structure acquired from
+** PR_GetHostByName() PR_GetHostByAddr() to evaluate the possible
+** network addresses.
+**
+** INPUTS:
+** PRIntn enumIndex Index of the enumeration. The enumeration starts
+** and ends with a value of zero.
+**
+** PRHostEnt *hostEnt A pointer to a host entry struct that was
+** previously returned by PR_GetHostByName() or
+** PR_GetHostByAddr().
+**
+** PRUint16 port The port number to be assigned as part of the
+** PRNetAddr.
+**
+** OUTPUTS:
+** PRNetAddr *address A pointer to an address structure that will be
+** filled in by the call to the enumeration if the
+** result of the call is greater than zero.
+**
+** RETURN:
+** PRIntn The value that should be used for the next call
+** of the enumerator ('enumIndex'). The enumeration
+** is ended if this value is returned zero.
+** If a value of -1 is returned, the enumeration
+** has failed. The reason for the failure can be
+** retrieved by calling PR_GetError().
+***********************************************************************/
+NSPR_API(PRIntn) PR_EnumerateHostEnt(
+ PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address);
+
+/***********************************************************************
+** FUNCTION: PR_InitializeNetAddr(),
+** DESCRIPTION:
+** Initialize the fields of a PRNetAddr, assigning well known values as
+** appropriate.
+**
+** INPUTS
+** PRNetAddrValue val The value to be assigned to the IP Address portion
+** of the network address. This can only specify the
+** special well known values that are equivalent to
+** INADDR_ANY and INADDR_LOOPBACK.
+**
+** PRUint16 port The port number to be assigned in the structure.
+**
+** OUTPUTS:
+** PRNetAddr *addr The address to be manipulated.
+**
+** RETURN:
+** PRStatus To indicate success or failure. If the latter, the
+** reason for the failure can be retrieved by calling
+** PR_GetError();
+***********************************************************************/
+typedef enum PRNetAddrValue
+{
+ PR_IpAddrNull, /* do NOT overwrite the IP address */
+ PR_IpAddrAny, /* assign logical INADDR_ANY to IP address */
+ PR_IpAddrLoopback, /* assign logical INADDR_LOOPBACK */
+ PR_IpAddrV4Mapped /* IPv4 mapped address */
+} PRNetAddrValue;
+
+NSPR_API(PRStatus) PR_InitializeNetAddr(
+ PRNetAddrValue val, PRUint16 port, PRNetAddr *addr);
+
+/***********************************************************************
+** FUNCTION: PR_SetNetAddr(),
+** DESCRIPTION:
+** Set the fields of a PRNetAddr, assigning well known values as
+** appropriate. This function is similar to PR_InitializeNetAddr
+** but differs in that the address family is specified.
+**
+** INPUTS
+** PRNetAddrValue val The value to be assigned to the IP Address portion
+** of the network address. This can only specify the
+** special well known values that are equivalent to
+** INADDR_ANY and INADDR_LOOPBACK.
+**
+** PRUint16 af The address family (either PR_AF_INET or PR_AF_INET6)
+**
+** PRUint16 port The port number to be assigned in the structure.
+**
+** OUTPUTS:
+** PRNetAddr *addr The address to be manipulated.
+**
+** RETURN:
+** PRStatus To indicate success or failure. If the latter, the
+** reason for the failure can be retrieved by calling
+** PR_GetError();
+***********************************************************************/
+NSPR_API(PRStatus) PR_SetNetAddr(
+ PRNetAddrValue val, PRUint16 af, PRUint16 port, PRNetAddr *addr);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_IsNetAddrType()
+** Determine if the network address is of the specified type.
+**
+** INPUTS:
+** const PRNetAddr *addr A network address.
+** PRNetAddrValue The type of network address
+**
+** RETURN:
+** PRBool PR_TRUE if the network address is of the
+** specified type, else PR_FALSE.
+***********************************************************************/
+NSPR_API(PRBool) PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_ConvertIPv4AddrToIPv6()
+** Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr
+**
+** INPUTS:
+** PRUint32 v4addr IPv4 address
+**
+** OUTPUTS:
+** PRIPv6Addr *v6addr The converted IPv6 address
+**
+** RETURN:
+** void
+**
+***********************************************************************/
+NSPR_API(void) PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr *v6addr);
+
+/***********************************************************************
+** MACRO:
+** DESCRIPTION: PR_NetAddrFamily()
+** Get the 'family' field of a PRNetAddr union.
+**
+** INPUTS:
+** const PRNetAddr *addr A network address.
+**
+** RETURN:
+** PRUint16 The 'family' field of 'addr'.
+***********************************************************************/
+#define PR_NetAddrFamily(addr) ((addr)->raw.family)
+
+/***********************************************************************
+** MACRO:
+** DESCRIPTION: PR_NetAddrInetPort()
+** Get the 'port' field of a PRNetAddr union.
+**
+** INPUTS:
+** const PRNetAddr *addr A network address.
+**
+** RETURN:
+** PRUint16 The 'port' field of 'addr'.
+***********************************************************************/
+#define PR_NetAddrInetPort(addr) \
+ ((addr)->raw.family == PR_AF_INET6 ? (addr)->ipv6.port : (addr)->inet.port)
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetProtoByName()
+** Lookup a protocol entry based on protocol's name
+**
+** INPUTS:
+** char *protocolname Character string of the protocol's name.
+** char *buf A scratch buffer for the runtime to return result.
+** This buffer is allocated by the caller.
+** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to
+** use is PR_NETDB_BUF_SIZE.
+** OUTPUTS:
+** PRHostEnt *PRProtoEnt
+** This structure is filled in by the runtime if
+** the function returns PR_SUCCESS. This structure
+** is allocated by the caller.
+** RETURN:
+** PRStatus PR_SUCCESS if the lookup succeeds. If it fails
+** the result will be PR_FAILURE and the reason
+** for the failure can be retrieved by PR_GetError().
+***********************************************************************/
+
+typedef struct PRProtoEnt {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+#if defined(WIN32) || defined(WIN16)
+ PRInt16 p_num; /* protocol # */
+#else
+ PRInt32 p_num; /* protocol # */
+#endif
+} PRProtoEnt;
+
+NSPR_API(PRStatus) PR_GetProtoByName(
+ const char* protocolname, char* buffer, PRInt32 bufsize, PRProtoEnt* result);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetProtoByNumber()
+** Lookup a protocol entry based on protocol's number
+**
+** INPUTS:
+** PRInt32 protocolnumber
+** Number assigned to the protocol.
+** char *buf A scratch buffer for the runtime to return result.
+** This buffer is allocated by the caller.
+** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to
+** use is PR_NETDB_BUF_SIZE.
+** OUTPUTS:
+** PRHostEnt *PRProtoEnt
+** This structure is filled in by the runtime if
+** the function returns PR_SUCCESS. This structure
+** is allocated by the caller.
+** RETURN:
+** PRStatus PR_SUCCESS if the lookup succeeds. If it fails
+** the result will be PR_FAILURE and the reason
+** for the failure can be retrieved by PR_GetError().
+***********************************************************************/
+NSPR_API(PRStatus) PR_GetProtoByNumber(
+ PRInt32 protocolnumber, char* buffer, PRInt32 bufsize, PRProtoEnt* result);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetAddrInfoByName()
+** Lookup a host by name. Equivalent to getaddrinfo(host, NULL, ...) of
+** RFC 3493.
+**
+** INPUTS:
+** char *hostname Character string defining the host name of interest
+** PRUint16 af May be PR_AF_UNSPEC or PR_AF_INET.
+** PRIntn flags May be either PR_AI_ADDRCONFIG or
+** PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME. Include
+** PR_AI_NOCANONNAME to suppress the determination of
+** the canonical name corresponding to hostname.
+** RETURN:
+** PRAddrInfo* Handle to a data structure containing the results
+** of the host lookup. Use PR_EnumerateAddrInfo to
+** inspect the PRNetAddr values stored in this object.
+** When no longer needed, this handle must be destroyed
+** with a call to PR_FreeAddrInfo. If a lookup error
+** occurs, then NULL will be returned.
+***********************************************************************/
+typedef struct PRAddrInfo PRAddrInfo;
+
+NSPR_API(PRAddrInfo*) PR_GetAddrInfoByName(
+ const char *hostname, PRUint16 af, PRIntn flags);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_FreeAddrInfo()
+** Destroy the PRAddrInfo handle allocated by PR_GetAddrInfoByName().
+**
+** INPUTS:
+** PRAddrInfo *addrInfo
+** The handle resulting from a successful call to
+** PR_GetAddrInfoByName().
+** RETURN:
+** void
+***********************************************************************/
+NSPR_API(void) PR_FreeAddrInfo(PRAddrInfo *addrInfo);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_EnumerateAddrInfo()
+** A stateless enumerator over a PRAddrInfo handle acquired from
+** PR_GetAddrInfoByName() to inspect the possible network addresses.
+**
+** INPUTS:
+** void *enumPtr Index pointer of the enumeration. The enumeration
+** starts and ends with a value of NULL.
+** PRAddrInfo *addrInfo
+** The PRAddrInfo handle returned by a successful
+** call to PR_GetAddrInfoByName().
+** PRUint16 port The port number to be assigned as part of the
+** PRNetAddr.
+** OUTPUTS:
+** PRNetAddr *result A pointer to an address structure that will be
+** filled in by the call to the enumeration if the
+** result of the call is greater than zero.
+** RETURN:
+** void* The value that should be used for the next call
+** of the enumerator ('enumPtr'). The enumeration
+** is ended if this value is returned NULL.
+***********************************************************************/
+NSPR_API(void *) PR_EnumerateAddrInfo(
+ void *enumPtr, const PRAddrInfo *addrInfo, PRUint16 port, PRNetAddr *result);
+
+/***********************************************************************
+** FUNCTION:
+** DESCRIPTION: PR_GetCanonNameFromAddrInfo()
+** Extracts the canonical name of the hostname passed to
+** PR_GetAddrInfoByName().
+**
+** INPUTS:
+** PRAddrInfo *addrInfo
+** The PRAddrInfo handle returned by a successful
+** call to PR_GetAddrInfoByName().
+** RETURN:
+** const char * A const pointer to the canonical hostname stored
+** in the given PRAddrInfo handle. This pointer is
+** invalidated once the PRAddrInfo handle is destroyed
+** by a call to PR_FreeAddrInfo().
+***********************************************************************/
+NSPR_API(const char *) PR_GetCanonNameFromAddrInfo(
+ const PRAddrInfo *addrInfo);
+
+/***********************************************************************
+** FUNCTIONS: PR_ntohs, PR_ntohl, PR_ntohll, PR_htons, PR_htonl, PR_htonll
+**
+** DESCRIPTION: API entries for the common byte ordering routines.
+**
+** PR_ntohs 16 bit conversion from network to host
+** PR_ntohl 32 bit conversion from network to host
+** PR_ntohll 64 bit conversion from network to host
+** PR_htons 16 bit conversion from host to network
+** PR_htonl 32 bit conversion from host to network
+** PR_ntonll 64 bit conversion from host to network
+**
+***********************************************************************/
+NSPR_API(PRUint16) PR_ntohs(PRUint16);
+NSPR_API(PRUint32) PR_ntohl(PRUint32);
+NSPR_API(PRUint64) PR_ntohll(PRUint64);
+NSPR_API(PRUint16) PR_htons(PRUint16);
+NSPR_API(PRUint32) PR_htonl(PRUint32);
+NSPR_API(PRUint64) PR_htonll(PRUint64);
+
+PR_END_EXTERN_C
+
+#endif /* prnetdb_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prolock.h b/src/libs/xpcom18a4/nsprpub/pr/include/prolock.h
new file mode 100644
index 00000000..bdb57f88
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prolock.h
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prolock_h___
+#define prolock_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateOrderedLock VBoxNsprPR_CreateOrderedLock
+#define PR_DestroyOrderedLock VBoxNsprPR_DestroyOrderedLock
+#define PR_LockOrderedLock VBoxNsprPR_LockOrderedLock
+#define PR_UnlockOrderedLock VBoxNsprPR_UnlockOrderedLock
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** A locking mechanism, built on the existing PRLock definiion,
+** is provided that will permit applications to define a Lock
+** Hierarchy (or Lock Ordering) schema. An application designed
+** using the Ordered Lock functions will terminate with a
+** diagnostic message when a lock inversion condition is
+** detected.
+**
+** The lock ordering detection is complile-time enabled only. in
+** optimized builds of NSPR, the Ordered Lock functions map
+** directly to PRLock functions, providing no lock order
+** detection.
+**
+** The Ordered Lock Facility is compiled in when DEBUG is defined at
+** compile time. Ordered Lock can be forced on in optimized builds by
+** defining FORCE_NSPR_ORDERED_LOCK at compile time. Both the
+** application using Ordered Lock and NSPR must be compiled with the
+** facility enabled to achieve the desired results.
+**
+** Application designers should use the macro interfaces to the Ordered
+** Lock facility to ensure that it is compiled out in optimized builds.
+**
+** Application designers are responsible for defining their own
+** lock hierarchy.
+**
+** Ordered Lock is thread-safe and SMP safe.
+**
+** See Also: prlock.h
+**
+** /lth. 10-Jun-1998.
+**
+*/
+
+/*
+** Opaque type for ordered lock.
+** ... Don't even think of looking in here.
+**
+*/
+
+#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)
+typedef void * PROrderedLock;
+#else
+/*
+** Map PROrderedLock and methods onto PRLock when ordered locking
+** is not compiled in.
+**
+*/
+#include "prlock.h"
+
+typedef PRLock PROrderedLock;
+#endif
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_CreateOrderedLock() -- Create an Ordered Lock
+**
+** DESCRIPTION: PR_CreateOrderedLock() creates an ordered lock.
+**
+** INPUTS:
+** order: user defined order of this lock.
+** name: name of the lock. For debugging purposes.
+**
+** OUTPUTS: returned
+**
+** RETURNS: PR_OrderedLock pointer
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)
+#define PR_CREATE_ORDERED_LOCK(order,name)\
+ PR_CreateOrderedLock((order),(name))
+#else
+#define PR_CREATE_ORDERED_LOCK(order) PR_NewLock()
+#endif
+
+NSPR_API(PROrderedLock *)
+ PR_CreateOrderedLock(
+ PRInt32 order,
+ const char *name
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DestroyOrderedLock() -- Destroy an Ordered Lock
+**
+** DESCRIPTION: PR_DestroyOrderedLock() destroys the ordered lock
+** referenced by lock.
+**
+** INPUTS: lock: pointer to a PROrderedLock
+**
+** OUTPUTS: the lock is destroyed
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)
+#define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyOrderedLock((lock))
+#else
+#define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyLock((lock))
+#endif
+
+NSPR_API(void)
+ PR_DestroyOrderedLock(
+ PROrderedLock *lock
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_LockOrderedLock() -- Lock an ordered lock
+**
+** DESCRIPTION: PR_LockOrderedLock() locks the ordered lock
+** referenced by lock. If the order of lock is less than or equal
+** to the order of the highest lock held by the locking thread,
+** the function asserts.
+**
+** INPUTS: lock: a pointer to a PROrderedLock
+**
+** OUTPUTS: The lock is held or the fucntion asserts.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)
+#define PR_LOCK_ORDERED_LOCK(lock) PR_LockOrderedLock((lock))
+#else
+#define PR_LOCK_ORDERED_LOCK(lock) PR_Lock((lock))
+#endif
+
+NSPR_API(void)
+ PR_LockOrderedLock(
+ PROrderedLock *lock
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_UnlockOrderedLock() -- unlock and Ordered Lock
+**
+** DESCRIPTION: PR_UnlockOrderedLock() unlocks the lock referenced
+** by lock.
+**
+** INPUTS: lock: a pointer to a PROrderedLock
+**
+** OUTPUTS: the lock is unlocked
+**
+** RETURNS:
+** PR_SUCCESS
+** PR_FAILURE
+**
+** RESTRICTIONS:
+**
+*/
+#if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS)
+#define PR_UNLOCK_ORDERED_LOCK(lock) PR_UnlockOrderedLock((lock))
+#else
+#define PR_UNLOCK_ORDERED_LOCK(lock) PR_Unlock((lock))
+#endif
+
+NSPR_API(PRStatus)
+ PR_UnlockOrderedLock(
+ PROrderedLock *lock
+);
+
+PR_END_EXTERN_C
+
+#endif /* prolock_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prpdce.h b/src/libs/xpcom18a4/nsprpub/pr/include/prpdce.h
new file mode 100644
index 00000000..434f1ec2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prpdce.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: prpdce.h
+ * Description: This file is the API defined to allow for DCE (aka POSIX)
+ * thread emulation in an NSPR environment. It is not the
+ * intent that this be a fully supported API.
+ */
+
+#if !defined(PRPDCE_H)
+#define PRPDCE_H
+
+#include "prlock.h"
+#include "prcvar.h"
+#include "prtypes.h"
+#include "prinrval.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PRP_DestroyNakedCondVar VBoxNsprPRP_DestroyNakedCondVar
+#define PRP_NakedBroadcast VBoxNsprPRP_NakedBroadcast
+#define PRP_NakedNotify VBoxNsprPRP_NakedNotify
+#define PRP_NakedWait VBoxNsprPRP_NakedWait
+#define PRP_NewNakedCondVar VBoxNsprPRP_NewNakedCondVar
+#define PRP_TryLock VBoxNsprPRP_TryLock
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+#define _PR_NAKED_CV_LOCK (PRLock*)0xdce1dce1
+
+/*
+** Test and acquire a lock.
+**
+** If the lock is acquired by the calling thread, the
+** return value will be PR_SUCCESS. If the lock is
+** already held, by another thread or this thread, the
+** result will be PR_FAILURE.
+*/
+NSPR_API(PRStatus) PRP_TryLock(PRLock *lock);
+
+/*
+** Create a naked condition variable
+**
+** A "naked" condition variable is one that is not created bound
+** to a lock. The CV created with this function is the only type
+** that may be used in the subsequent "naked" condition variable
+** operations (see PRP_NakedWait, PRP_NakedNotify, PRP_NakedBroadcast);
+*/
+NSPR_API(PRCondVar*) PRP_NewNakedCondVar(void);
+
+/*
+** Destroy a naked condition variable
+**
+** Destroy the condition variable created by PR_NewNakedCondVar.
+*/
+NSPR_API(void) PRP_DestroyNakedCondVar(PRCondVar *cvar);
+
+/*
+** Wait on a condition
+**
+** Wait on the condition variable 'cvar'. It is asserted that
+** the lock protecting the condition 'lock' is held by the
+** calling thread. If more time expires than that declared in
+** 'timeout' the condition will be notified. Waits can be
+** interrupted by another thread.
+**
+** NB: The CV ('cvar') must be one created using PR_NewNakedCondVar.
+*/
+NSPR_API(PRStatus) PRP_NakedWait(
+ PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout);
+
+/*
+** Notify a thread waiting on a condition
+**
+** Notify the condition specified 'cvar'.
+**
+** NB: The CV ('cvar') must be one created using PR_NewNakedCondVar.
+*/
+NSPR_API(PRStatus) PRP_NakedNotify(PRCondVar *cvar);
+
+/*
+** Notify all threads waiting on a condition
+**
+** Notify the condition specified 'cvar'.
+**
+** NB: The CV ('cvar') must be one created using PR_NewNakedCondVar.
+*/
+NSPR_API(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar);
+
+PR_END_EXTERN_C
+
+#endif /* PRPDCE_H */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prprf.h b/src/libs/xpcom18a4/nsprpub/pr/include/prprf.h
new file mode 100644
index 00000000..69a27b34
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prprf.h
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prprf_h___
+#define prprf_h___
+
+/*
+** API for PR printf like routines. Supports the following formats
+** %d - decimal
+** %u - unsigned decimal
+** %x - unsigned hex
+** %X - unsigned uppercase hex
+** %o - unsigned octal
+** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
+** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
+** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
+** %s - string
+** %c - character
+** %p - pointer (deals with machine dependent pointer size)
+** %f - float
+** %g - float
+*/
+#include "prtypes.h"
+#include "prio.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_snprintf VBoxNsprPR_snprintf
+#define PR_vsnprintf VBoxNsprPR_vsnprintf
+#define PR_smprintf VBoxNsprPR_smprintf
+#define PR_smprintf_free VBoxNsprPR_smprintf_free
+#define PR_sprintf_append VBoxNsprPR_sprintf_append
+#define PR_sxprintf VBoxNsprPR_sxprintf
+#define PR_fprintf VBoxNsprPR_fprintf
+#define PR_vsmprintf VBoxNsprPR_vsmprintf
+#define PR_vsprintf_append VBoxNsprPR_vsprintf_append
+#define PR_vsxprintf VBoxNsprPR_vsxprintf
+#define PR_vfprintf VBoxNsprPR_vfprintf
+#define PR_sscanf VBoxNsprPR_sscanf
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
+** of the buffer. Returns the length of the written output, NOT including
+** the NUL, or (PRUint32)-1 if an error occurs.
+*/
+NSPR_API(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...);
+
+/*
+** sprintf into a PR_MALLOC'd buffer. Return a pointer to the malloc'd
+** buffer on success, NULL on failure. Call "PR_smprintf_free" to release
+** the memory returned.
+*/
+NSPR_API(char*) PR_smprintf(const char *fmt, ...);
+
+/*
+** Free the memory allocated, for the caller, by PR_smprintf
+*/
+NSPR_API(void) PR_smprintf_free(char *mem);
+
+/*
+** "append" sprintf into a PR_MALLOC'd buffer. "last" is the last value of
+** the PR_MALLOC'd buffer. sprintf will append data to the end of last,
+** growing it as necessary using realloc. If last is NULL, PR_sprintf_append
+** will allocate the initial string. The return value is the new value of
+** last for subsequent calls, or NULL if there is a malloc failure.
+*/
+NSPR_API(char*) PR_sprintf_append(char *last, const char *fmt, ...);
+
+/*
+** sprintf into a function. The function "f" is called with a string to
+** place into the output. "arg" is an opaque pointer used by the stuff
+** function to hold any state needed to do the storage of the output
+** data. The return value is a count of the number of characters fed to
+** the stuff function, or (PRUint32)-1 if an error occurs.
+*/
+typedef PRIntn (*PRStuffFunc)(void *arg, const char *s, PRUint32 slen);
+
+NSPR_API(PRUint32) PR_sxprintf(PRStuffFunc f, void *arg, const char *fmt, ...);
+
+/*
+** fprintf to a PRFileDesc
+*/
+NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...);
+
+/*
+** va_list forms of the above.
+*/
+NSPR_API(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen, const char *fmt, va_list ap);
+NSPR_API(char*) PR_vsmprintf(const char *fmt, va_list ap);
+NSPR_API(char*) PR_vsprintf_append(char *last, const char *fmt, va_list ap);
+NSPR_API(PRUint32) PR_vsxprintf(PRStuffFunc f, void *arg, const char *fmt, va_list ap);
+NSPR_API(PRUint32) PR_vfprintf(struct PRFileDesc* fd, const char *fmt, va_list ap);
+
+/*
+***************************************************************************
+** FUNCTION: PR_sscanf
+** DESCRIPTION:
+** PR_sscanf() scans the input character string, performs data
+** conversions, and stores the converted values in the data objects
+** pointed to by its arguments according to the format control
+** string.
+**
+** PR_sscanf() behaves the same way as the sscanf() function in the
+** Standard C Library (stdio.h), with the following exceptions:
+** - PR_sscanf() handles the NSPR integer and floating point types,
+** such as PRInt16, PRInt32, PRInt64, and PRFloat64, whereas
+** sscanf() handles the standard C types like short, int, long,
+** and double.
+** - PR_sscanf() has no multibyte character support, while sscanf()
+** does.
+** INPUTS:
+** const char *buf
+** a character string holding the input to scan
+** const char *fmt
+** the format control string for the conversions
+** ...
+** variable number of arguments, each of them is a pointer to
+** a data object in which the converted value will be stored
+** OUTPUTS: none
+** RETURNS: PRInt32
+** The number of values converted and stored.
+** RESTRICTIONS:
+** Multibyte characters in 'buf' or 'fmt' are not allowed.
+***************************************************************************
+*/
+
+NSPR_API(PRInt32) PR_sscanf(const char *buf, const char *fmt, ...);
+
+PR_END_EXTERN_C
+
+#endif /* prprf_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prproces.h b/src/libs/xpcom18a4/nsprpub/pr/include/prproces.h
new file mode 100644
index 00000000..27999799
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prproces.h
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prproces_h___
+#define prproces_h___
+
+#include "prtypes.h"
+#include "prio.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateProcessDetached VBoxNsprPR_CreateProcessDetached
+#define PR_ProcessAttrSetInheritableFD VBoxNsprPR_ProcessAttrSetInheritableFD
+#define PR_DestroyProcessAttr VBoxNsprPR_DestroyProcessAttr
+#define PR_NewProcessAttr VBoxNsprPR_NewProcessAttr
+#define PR_ResetProcessAttr VBoxNsprPR_ResetProcessAttr
+#define PR_ProcessAttrSetStdioRedirect VBoxNsprPR_ProcessAttrSetStdioRedirect
+#define PR_SetStdioRedirect VBoxNsprPR_SetStdioRedirect
+#define PR_ProcessAttrSetCurrentDirectory VBoxNsprPR_ProcessAttrSetCurrentDirectory
+#define PR_CreateProcess VBoxNsprPR_CreateProcess
+#define PR_DetachProcess VBoxNsprPR_DetachProcess
+#define PR_WaitProcess VBoxNsprPR_WaitProcess
+#define PR_KillProcess VBoxNsprPR_KillProcess
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/************************************************************************/
+/*****************************PROCESS OPERATIONS*************************/
+/************************************************************************/
+
+typedef struct PRProcess PRProcess;
+typedef struct PRProcessAttr PRProcessAttr;
+
+NSPR_API(PRProcessAttr *) PR_NewProcessAttr(void);
+
+NSPR_API(void) PR_ResetProcessAttr(PRProcessAttr *attr);
+
+NSPR_API(void) PR_DestroyProcessAttr(PRProcessAttr *attr);
+
+NSPR_API(void) PR_ProcessAttrSetStdioRedirect(
+ PRProcessAttr *attr,
+ PRSpecialFD stdioFd,
+ PRFileDesc *redirectFd
+);
+
+/*
+ * OBSOLETE -- use PR_ProcessAttrSetStdioRedirect instead.
+ */
+NSPR_API(void) PR_SetStdioRedirect(
+ PRProcessAttr *attr,
+ PRSpecialFD stdioFd,
+ PRFileDesc *redirectFd
+);
+
+NSPR_API(PRStatus) PR_ProcessAttrSetCurrentDirectory(
+ PRProcessAttr *attr,
+ const char *dir
+);
+
+NSPR_API(PRStatus) PR_ProcessAttrSetInheritableFD(
+ PRProcessAttr *attr,
+ PRFileDesc *fd,
+ const char *name
+);
+
+/*
+** Create a new process
+**
+** Create a new process executing the file specified as 'path' and with
+** the supplied arguments and environment.
+**
+** This function may fail because of illegal access (permissions),
+** invalid arguments or insufficient resources.
+**
+** A process may be created such that the creator can later synchronize its
+** termination using PR_WaitProcess().
+*/
+
+NSPR_API(PRProcess*) PR_CreateProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr);
+
+NSPR_API(PRStatus) PR_CreateProcessDetached(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr);
+
+NSPR_API(PRStatus) PR_DetachProcess(PRProcess *process);
+
+NSPR_API(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode);
+
+NSPR_API(PRStatus) PR_KillProcess(PRProcess *process);
+
+PR_END_EXTERN_C
+
+#endif /* prproces_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prrng.h b/src/libs/xpcom18a4/nsprpub/pr/include/prrng.h
new file mode 100644
index 00000000..90d1a385
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prrng.h
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/*
+** prrng.h -- NSPR Random Number Generator
+**
+**
+** lth. 29-Oct-1999.
+*/
+
+#ifndef prrng_h___
+#define prrng_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_GetRandomNoise VBoxNsprPR_GetRandomNoise
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** PR_GetRandomNoise() -- Get random noise from the host platform
+**
+** Description:
+** PR_GetRandomNoise() provides, depending on platform, a random value.
+** The length of the random value is dependent on platform and the
+** platform's ability to provide a random value at that moment.
+**
+** The intent of PR_GetRandomNoise() is to provide a "seed" value for a
+** another random number generator that may be suitable for
+** cryptographic operations. This implies that the random value
+** provided may not be, by itself, cryptographically secure. The value
+** generated by PR_GetRandomNoise() is at best, extremely difficult to
+** predict and is as non-deterministic as the underlying platfrom can
+** provide.
+**
+** Inputs:
+** buf -- pointer to a caller supplied buffer to contain the
+** generated random number. buf must be at least as large as
+** is specified in the 'size' argument.
+**
+** size -- the requested size of the generated random number
+**
+** Outputs:
+** a random number provided in 'buf'.
+**
+** Returns:
+** PRSize value equal to the size of the random number actually
+** generated, or zero. The generated size may be less than the size
+** requested. A return value of zero means that PR_GetRandomNoise() is
+** not implemented on this platform, or there is no available noise
+** available to be returned at the time of the call.
+**
+** Restrictions:
+** Calls to PR_GetRandomNoise() may use a lot of CPU on some platforms.
+** Some platforms may block for up to a few seconds while they
+** accumulate some noise. Busy machines generate lots of noise, but
+** care is advised when using PR_GetRandomNoise() frequently in your
+** application.
+**
+** History:
+** Parts of the model dependent implementation for PR_GetRandomNoise()
+** were taken in whole or part from code previously in Netscape's NSS
+** component.
+**
+*/
+NSPR_API(PRSize) PR_GetRandomNoise(
+ void *buf,
+ PRSize size
+);
+
+PR_END_EXTERN_C
+
+#endif /* prrng_h___ */
+/* end prrng.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prrwlock.h b/src/libs/xpcom18a4/nsprpub/pr/include/prrwlock.h
new file mode 100644
index 00000000..718bbb12
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prrwlock.h
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prrwlock.h
+** Description: API to basic reader-writer lock functions of NSPR.
+**
+**/
+
+#ifndef prrwlock_h___
+#define prrwlock_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_NewRWLock VBoxNsprPR_NewRWLock
+#define PR_DestroyRWLock VBoxNsprPR_DestroyRWLock
+#define PR_RWLock_Rlock VBoxNsprPR_RWLock_Rlock
+#define PR_RWLock_Wlock VBoxNsprPR_RWLock_Wlock
+#define PR_RWLock_Unlock VBoxNsprPR_RWLock_Unlock
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * PRRWLock --
+ *
+ * The reader writer lock, PRRWLock, is an opaque object to the clients
+ * of NSPR. All routines operate on a pointer to this opaque entity.
+ */
+
+
+typedef struct PRRWLock PRRWLock;
+
+#define PR_RWLOCK_RANK_NONE 0
+
+
+/***********************************************************************
+** FUNCTION: PR_NewRWLock
+** DESCRIPTION:
+** Returns a pointer to a newly created reader-writer lock object.
+** INPUTS: Lock rank
+** Lock name
+** OUTPUTS: void
+** RETURN: PRRWLock*
+** If the lock cannot be created because of resource constraints, NULL
+** is returned.
+**
+***********************************************************************/
+NSPR_API(PRRWLock*) PR_NewRWLock(PRUint32 lock_rank, const char *lock_name);
+
+/***********************************************************************
+** FUNCTION: PR_DestroyRWLock
+** DESCRIPTION:
+** Destroys a given RW lock object.
+** INPUTS: PRRWLock *lock - Lock to be freed.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+NSPR_API(void) PR_DestroyRWLock(PRRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: PR_RWLock_Rlock
+** DESCRIPTION:
+** Apply a read lock (non-exclusive) on a RWLock
+** INPUTS: PRRWLock *lock - Lock to be read-locked.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+NSPR_API(void) PR_RWLock_Rlock(PRRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: PR_RWLock_Wlock
+** DESCRIPTION:
+** Apply a write lock (exclusive) on a RWLock
+** INPUTS: PRRWLock *lock - Lock to write-locked.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+NSPR_API(void) PR_RWLock_Wlock(PRRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: PR_RWLock_Unlock
+** DESCRIPTION:
+** Release a RW lock. Unlocking an unlocked lock has undefined results.
+** INPUTS: PRRWLock *lock - Lock to unlocked.
+** OUTPUTS: void
+** RETURN: void
+***********************************************************************/
+NSPR_API(void) PR_RWLock_Unlock(PRRWLock *lock);
+
+PR_END_EXTERN_C
+
+#endif /* prrwlock_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prshm.h b/src/libs/xpcom18a4/nsprpub/pr/include/prshm.h
new file mode 100644
index 00000000..f474d306
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prshm.h
@@ -0,0 +1,297 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prshm.h -- NSPR Shared Memory
+**
+** NSPR Named Shared Memory API provides a cross-platform named
+** shared-memory interface. NSPR Named Shared Memory is modeled on
+** similar constructs in Unix and Windows operating systems. Shared
+** memory allows multiple processes to access one or more common shared
+** memory regions, using it as an inter-process communication channel.
+**
+** Notes on Platform Independence:
+** NSPR Named Shared Memory is built on the native services offered
+** by most platforms. The NSPR Named Shared Memory API tries to
+** provide a least common denominator interface so that it works
+** across all supported platforms. To ensure that it works everywhere,
+** some platform considerations must be accomodated and the protocol
+** for using NSPR Shared Memory API must be observed.
+**
+** Protocol:
+** Multiple shared memories can be created using NSPR's Shared Memory
+** feature. For each named shared memory, as defined by the name
+** given in the PR_OpenSharedMemory() call, a protocol for using the
+** shared memory API is required to ensure desired behavior. Failing
+** to follow the protocol may yield unpredictable results.
+**
+** PR_OpenSharedMemory() will create the shared memory segment, if it
+** does not already exist, or open a connection that the existing
+** shared memory segment if it already exists.
+**
+** PR_AttachSharedMemory() should be called following
+** PR_OpenSharedMemory() to map the memory segment to an address in
+** the application's address space.
+**
+** PR_AttachSharedMemory() may be called to re-map a shared memory
+** segment after detaching the same PRSharedMemory object. Be
+** sure to detach it when done.
+**
+** PR_DetachSharedMemory() should be called to un-map the shared
+** memory segment from the application's address space.
+**
+** PR_CloseSharedMemory() should be called when no further use of the
+** PRSharedMemory object is required within a process. Following a
+** call to PR_CloseSharedMemory() the PRSharedMemory object is
+** invalid and cannot be reused.
+**
+** PR_DeleteSharedMemory() should be called before process
+** termination. After calling PR_DeleteSharedMemory() any further use
+** of the shared memory associated with the name may cause
+** unpredictable results.
+**
+** Files:
+** The name passed to PR_OpenSharedMemory() should be a valid filename
+** for a unix platform. PR_OpenSharedMemory() creates file using the
+** name passed in. Some platforms may mangle the name before creating
+** the file and the shared memory.
+**
+** The unix implementation may use SysV IPC shared memory, Posix
+** shared memory, or memory mapped files; the filename may used to
+** define the namespace. On Windows, the name is significant, but
+** there is no file associated with name.
+**
+** No assumptions about the persistence of data in the named file
+** should be made. Depending on platform, the shared memory may be
+** mapped onto system paging space and be discarded at process
+** termination.
+**
+** All names provided to PR_OpenSharedMemory() should be valid
+** filename syntax or name syntax for shared memory for the target
+** platform. Referenced directories should have permissions
+** appropriate for writing.
+**
+** Limits:
+** Different platforms have limits on both the number and size of
+** shared memory resources. The default system limits on some
+** platforms may be smaller than your requirements. These limits may
+** be adjusted on some platforms either via boot-time options or by
+** setting the size of the system paging space to accomodate more
+** and/or larger shared memory segment(s).
+**
+** Security:
+** On unix platforms, depending on implementation, contents of the
+** backing store for the shared memory can be exposed via the file
+** system. Set permissions and or access controls at create and attach
+** time to ensure you get the desired security.
+**
+** On windows platforms, no special security measures are provided.
+**
+** Example:
+** The test case pr/tests/nameshm1.c provides an example of use as
+** well as testing the operation of NSPR's Named Shared Memory.
+**
+** lth. 18-Aug-1999.
+*/
+
+#ifndef prshm_h___
+#define prshm_h___
+
+#include "prtypes.h"
+#include "prio.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_OpenSharedMemory VBoxNsprPR_OpenSharedMemory
+#define PR_AttachSharedMemory VBoxNsprPR_AttachSharedMemory
+#define PR_DetachSharedMemory VBoxNsprPR_DetachSharedMemory
+#define PR_CloseSharedMemory VBoxNsprPR_CloseSharedMemory
+#define PR_DeleteSharedMemory VBoxNsprPR_DeleteSharedMemory
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Declare opaque type PRSharedMemory.
+*/
+typedef struct PRSharedMemory PRSharedMemory;
+
+/*
+** FUNCTION: PR_OpenSharedMemory()
+**
+** DESCRIPTION:
+** PR_OpenSharedMemory() creates a new shared-memory segment or
+** associates a previously created memory segment with name.
+**
+** When parameter create is (PR_SHM_EXCL | PR_SHM_CREATE) and the
+** shared memory already exists, the function returns NULL with the
+** error set to PR_FILE_EXISTS_ERROR.
+**
+** When parameter create is PR_SHM_CREATE and the shared memory
+** already exists, a handle to that memory segment is returned. If
+** the segment does not exist, it is created and a pointer to the
+** related PRSharedMemory structure is returned.
+**
+** When parameter create is 0, and the shared memory exists, a
+** pointer to a PRSharedMemory is returned. If the shared memory does
+** not exist, NULL is returned with the error set to
+** PR_FILE_NOT_FOUND_ERROR.
+**
+** INPUTS:
+** name -- the name the shared-memory segment is known as.
+** size -- the size of the shared memory segment.
+** flags -- Options for creating the shared memory
+** mode -- Same as is passed to PR_Open()
+**
+** OUTPUTS:
+** The shared memory is allocated.
+**
+** RETURNS: Pointer to opaque structure PRSharedMemory or NULL.
+** NULL is returned on error. The reason for the error can be
+** retrieved via PR_GetError() and PR_GetOSError();
+**
+*/
+NSPR_API( PRSharedMemory * )
+ PR_OpenSharedMemory(
+ const char *name,
+ PRSize size,
+ PRIntn flags,
+ PRIntn mode
+);
+/* Define values for PR_OpenShareMemory(...,create) */
+#define PR_SHM_CREATE 0x1 /* create if not exist */
+#define PR_SHM_EXCL 0x2 /* fail if already exists */
+
+/*
+** FUNCTION: PR_AttachSharedMemory()
+**
+** DESCRIPTION:
+** PR_AttachSharedMemory() maps the shared-memory described by
+** shm to the current process.
+**
+** INPUTS:
+** shm -- The handle returned from PR_OpenSharedMemory().
+** flags -- options for mapping the shared memory.
+** PR_SHM_READONLY causes the memory to be attached
+** read-only.
+**
+** OUTPUTS:
+** On success, the shared memory segment represented by shm is mapped
+** into the process' address space.
+**
+** RETURNS: Address where shared memory is mapped, or NULL.
+** NULL is returned on error. The reason for the error can be
+** retrieved via PR_GetError() and PR_GetOSError();
+**
+**
+*/
+NSPR_API( void * )
+ PR_AttachSharedMemory(
+ PRSharedMemory *shm,
+ PRIntn flags
+);
+/* Define values for PR_AttachSharedMemory(...,flags) */
+#define PR_SHM_READONLY 0x01
+
+/*
+** FUNCTION: PR_DetachSharedMemory()
+**
+** DESCRIPTION:
+** PR_DetachSharedMemory() detaches the shared-memory described
+** by shm.
+**
+** INPUTS:
+** shm -- The handle returned from PR_OpenSharedMemory().
+** addr -- The address at which the memory was attached.
+**
+** OUTPUTS:
+** The shared memory mapped to an address via a previous call to
+** PR_AttachSharedMemory() is unmapped.
+**
+** RETURNS: PRStatus
+**
+*/
+NSPR_API( PRStatus )
+ PR_DetachSharedMemory(
+ PRSharedMemory *shm,
+ void *addr
+);
+
+/*
+** FUNCTION: PR_CloseSharedMemory()
+**
+** DESCRIPTION:
+** PR_CloseSharedMemory() closes the shared-memory described by
+** shm.
+**
+** INPUTS:
+** shm -- The handle returned from PR_OpenSharedMemory().
+**
+** OUTPUTS:
+** the shared memory represented by shm is closed
+**
+** RETURNS: PRStatus
+**
+*/
+NSPR_API( PRStatus )
+ PR_CloseSharedMemory(
+ PRSharedMemory *shm
+);
+
+/*
+** FUNCTION: PR_DeleteSharedMemory()
+**
+** DESCRIPTION:
+** The shared memory resource represented by name is released.
+**
+** INPUTS:
+** name -- the name the shared-memory segment
+**
+** OUTPUTS:
+** depending on platform, resources may be returned to the underlying
+** operating system.
+**
+** RETURNS: PRStatus
+**
+*/
+NSPR_API( PRStatus )
+ PR_DeleteSharedMemory(
+ const char *name
+);
+
+PR_END_EXTERN_C
+
+#endif /* prshm_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prshma.h b/src/libs/xpcom18a4/nsprpub/pr/include/prshma.h
new file mode 100644
index 00000000..0214e0aa
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prshma.h
@@ -0,0 +1,279 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prshma.h -- NSPR Anonymous Shared Memory
+**
+** NSPR provides an anonymous shared memory based on NSPR's PRFileMap
+** type. The anonymous file-mapped shared memory provides an inheritable
+** shared memory, as in: the child process inherits the shared memory.
+** Compare the file-mapped anonymous shared memory to to a named shared
+** memory described in prshm.h. The intent is to provide a shared
+** memory that is accessable only by parent and child processes. ...
+** It's a security thing.
+**
+** Depending on the underlying platform, the file-mapped shared memory
+** may be backed by a file. ... surprise! ... On some platforms, no
+** real file backs the shared memory. On platforms where the shared
+** memory is backed by a file, the file's name in the filesystem is
+** visible to other processes for only the duration of the creation of
+** the file, hopefully a very short time. This restricts processess
+** that do not inherit the shared memory from opening the file and
+** reading or writing its contents. Further, when all processes
+** using an anonymous shared memory terminate, the backing file is
+** deleted. ... If you are not paranoid, you're not paying attention.
+**
+** The file-mapped shared memory requires a protocol for the parent
+** process and child process to share the memory. NSPR provides two
+** protocols. Use one or the other; don't mix and match.
+**
+** In the first protocol, the job of passing the inheritable shared
+** memory is done via helper-functions with PR_CreateProcess(). In the
+** second protocol, the parent process is responsible for creating the
+** child process; the parent and child are mutually responsible for
+** passing a FileMap string. NSPR provides helper functions for
+** extracting data from the PRFileMap object. ... See the examples
+** below.
+**
+** Both sides should adhere strictly to the protocol for proper
+** operation. The pseudo-code below shows the use of a file-mapped
+** shared memory by a parent and child processes. In the examples, the
+** server creates the file-mapped shared memory, the client attaches to
+** it.
+**
+** First protocol.
+** Server:
+**
+** fm = PR_OpenAnonFileMap(dirName, size, FilemapProt);
+** addr = PR_MemMap(fm);
+** attr = PR_NewProcessAttr();
+** PR_ProcessAttrSetInheritableFileMap( attr, fm, shmname );
+** PR_CreateProcess(Client);
+** PR_DestroyProcessAttr(attr);
+** ... yadda ...
+** PR_MemUnmap( addr );
+** PR_CloseFileMap(fm);
+**
+**
+** Client:
+** ... started by server via PR_CreateProcess()
+** fm = PR_GetInheritedFileMap( shmname );
+** addr = PR_MemMap(fm);
+** ... yadda ...
+** PR_MemUnmap(addr);
+** PR_CloseFileMap(fm);
+**
+**
+** Second Protocol:
+** Server:
+**
+** fm = PR_OpenAnonFileMap(dirName, size, FilemapProt);
+** fmstring = PR_ExportFileMapAsString( fm );
+** addr = PR_MemMap(fm);
+** ... application specific technique to pass fmstring to child
+** ... yadda ... Server uses his own magic to create child
+** PR_MemUnmap( addr );
+** PR_CloseFileMap(fm);
+**
+**
+** Client:
+** ... started by server via his own magic
+** ... application specific technique to find fmstring from parent
+** fm = PR_ImportFileMapFromString( fmstring )
+** addr = PR_MemMap(fm);
+** ... yadda ...
+** PR_MemUnmap(addr);
+** PR_CloseFileMap(fm);
+**
+**
+** lth. 2-Jul-1999.
+**
+** Note: The second protocol was requested by NelsonB (7/1999); this is
+** to accomodate servers which already create their own child processes
+** using platform native methods.
+**
+*/
+
+#ifndef prshma_h___
+#define prshma_h___
+
+#include "prtypes.h"
+#include "prio.h"
+#include "prproces.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_OpenAnonFileMap VBoxNsprPR_OpenAnonFileMap
+#define PR_ProcessAttrSetInheritableFileMap VBoxNsprPR_ProcessAttrSetInheritableFileMap
+#define PR_GetInheritedFileMap VBoxNsprPR_GetInheritedFileMap
+#define PR_ExportFileMapAsString VBoxNsprPR_ExportFileMapAsString
+#define PR_ImportFileMapFromString VBoxNsprPR_ImportFileMapFromString
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** PR_OpenAnonFileMap() -- Creates an anonymous file-mapped shared memory
+**
+** Description:
+** PR_OpenAnonFileMap() creates an anonymous shared memory. If the
+** shared memory already exists, a handle is returned to that shared
+** memory object.
+**
+** On Unix platforms, PR_OpenAnonFileMap() uses 'dirName' as a
+** directory name, without the trailing '/', to contain the anonymous
+** file. A filename is generated for the name.
+**
+** On Windows platforms, dirName is ignored.
+**
+** Inputs:
+** dirName -- A directory name to contain the anonymous file.
+** size -- The size of the shared memory
+** prot -- How the shared memory is mapped. See prio.h
+**
+** Outputs:
+** PRFileMap *
+**
+** Returns:
+** Pointer to PRFileMap or NULL on error.
+**
+*/
+NSPR_API( PRFileMap *)
+PR_OpenAnonFileMap(
+ const char *dirName,
+ PRSize size,
+ PRFileMapProtect prot
+);
+
+/*
+** PR_ProcessAttrSetInheritableFileMap() -- Prepare FileMap for export
+** to my children processes via PR_CreateProcess()
+**
+** Description:
+** PR_ProcessAttrSetInheritableFileMap() connects the PRFileMap to
+** PRProcessAttr with shmname. A subsequent call to PR_CreateProcess()
+** makes the PRFileMap importable by the child process.
+**
+** Inputs:
+** attr -- PRProcessAttr, used to pass data to PR_CreateProcess()
+** fm -- PRFileMap structure to be passed to the child process
+** shmname -- The name for the PRFileMap; used by child.
+**
+** Outputs:
+** PRFileMap *
+**
+** Returns:
+** PRStatus
+**
+*/
+NSPR_API(PRStatus)
+PR_ProcessAttrSetInheritableFileMap(
+ PRProcessAttr *attr,
+ PRFileMap *fm,
+ const char *shmname
+);
+
+/*
+** PR_GetInheritedFileMap() -- Import a PRFileMap previously exported
+** by my parent process via PR_CreateProcess()
+**
+** Description:
+** PR_GetInheritedFileMap() retrieves a PRFileMap object exported from
+** its parent process via PR_CreateProcess().
+**
+** Inputs:
+** shmname -- The name provided to PR_ProcessAttrSetInheritableFileMap()
+**
+** Outputs:
+** PRFileMap *
+**
+** Returns:
+** PRFileMap pointer or NULL.
+**
+*/
+NSPR_API( PRFileMap *)
+PR_GetInheritedFileMap(
+ const char *shmname
+);
+
+/*
+** PR_ExportFileMapAsString() -- Creates a string identifying a PRFileMap
+**
+** Description:
+** Creates an identifier, as a string, from a PRFileMap object
+** previously created with PR_OpenAnonFileMap().
+**
+** Inputs:
+** fm -- PRFileMap pointer to be represented as a string.
+** bufsize -- sizeof(buf)
+** buf -- a buffer of length PR_FILEMAP_STRING_BUFSIZE
+**
+** Outputs:
+** buf contains the stringized PRFileMap identifier
+**
+** Returns:
+** PRStatus
+**
+*/
+NSPR_API( PRStatus )
+PR_ExportFileMapAsString(
+ PRFileMap *fm,
+ PRSize bufsize,
+ char *buf
+);
+#define PR_FILEMAP_STRING_BUFSIZE 128
+
+/*
+** PR_ImportFileMapFromString() -- Creates a PRFileMap from the identifying string
+**
+** Description:
+** PR_ImportFileMapFromString() creates a PRFileMap object from a
+** string previously created by PR_ExportFileMapAsString().
+**
+** Inputs:
+** fmstring -- string created by PR_ExportFileMapAsString()
+**
+** Returns:
+** PRFileMap pointer or NULL.
+**
+*/
+NSPR_API( PRFileMap * )
+PR_ImportFileMapFromString(
+ const char *fmstring
+);
+
+PR_END_EXTERN_C
+#endif /* prshma_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prsystem.h b/src/libs/xpcom18a4/nsprpub/pr/include/prsystem.h
new file mode 100644
index 00000000..2028b709
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prsystem.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prsystem_h___
+#define prsystem_h___
+
+/*
+** API to NSPR functions returning system info.
+*/
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_GetDirectorySeparator VBoxNsprPR_GetDirectorySeparator
+#define PR_GetDirectorySepartor VBoxNsprPR_GetDirectorySepartor
+#define PR_GetPathSeparator VBoxNsprPR_GetPathSeparator
+#define PR_GetSystemInfo VBoxNsprPR_GetSystemInfo
+#define PR_GetPageSize VBoxNsprPR_GetPageSize
+#define PR_GetPageShift VBoxNsprPR_GetPageShift
+#define PR_GetNumberOfProcessors VBoxNsprPR_GetNumberOfProcessors
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Get the host' directory separator.
+** Pathnames are then assumed to be of the form:
+** [<sep><root_component><sep>]*(<component><sep>)<leaf_name>
+*/
+
+NSPR_API(char) PR_GetDirectorySeparator(void);
+
+/*
+** OBSOLETE -- the function name is misspelled.
+** Use PR_GetDirectorySeparator instead.
+*/
+
+NSPR_API(char) PR_GetDirectorySepartor(void);
+
+/*
+** Get the host' path separator.
+** Paths are assumed to be of the form:
+** <directory>[<sep><directory>]*
+*/
+
+NSPR_API(char) PR_GetPathSeparator(void);
+
+/* Types of information available via PR_GetSystemInfo(...) */
+typedef enum {
+ PR_SI_HOSTNAME,
+ PR_SI_SYSNAME,
+ PR_SI_RELEASE,
+ PR_SI_ARCHITECTURE
+} PRSysInfo;
+
+
+/*
+** If successful returns a null termintated string in 'buf' for
+** the information indicated in 'cmd'. If unseccussful the reason for
+** the failure can be retrieved from PR_GetError().
+**
+** The buffer is allocated by the caller and should be at least
+** SYS_INFO_BUFFER_LENGTH bytes in length.
+*/
+
+#define SYS_INFO_BUFFER_LENGTH 256
+
+NSPR_API(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen);
+
+/*
+** Return the number of bytes in a page
+*/
+NSPR_API(PRInt32) PR_GetPageSize(void);
+
+/*
+** Return log2 of the size of a page
+*/
+NSPR_API(PRInt32) PR_GetPageShift(void);
+
+/*
+** PR_GetNumberOfProcessors() -- returns the number of CPUs
+**
+** Description:
+** PR_GetNumberOfProcessors() extracts the number of processors
+** (CPUs available in an SMP system) and returns the number.
+**
+** Parameters:
+** none
+**
+** Returns:
+** The number of available processors or -1 on error
+**
+*/
+NSPR_API(PRInt32) PR_GetNumberOfProcessors( void );
+
+PR_END_EXTERN_C
+
+#endif /* prsystem_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prthread.h b/src/libs/xpcom18a4/nsprpub/pr/include/prthread.h
new file mode 100644
index 00000000..bc2be5e1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prthread.h
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prthread_h___
+#define prthread_h___
+
+/*
+** API for NSPR threads. On some architectures (MAC and WIN16
+** notably) pre-emptibility is not guaranteed. Hard priority scheduling
+** is not guaranteed, so programming using priority based synchronization
+** is a no-no.
+**
+** NSPR threads are scheduled based loosly on their client set priority.
+** In general, a thread of a higher priority has a statistically better
+** chance of running relative to threads of lower priority. However,
+** NSPR uses multiple strategies to provide execution vehicles for thread
+** abstraction of various host platforms. As it turns out, there is little
+** NSPR can do to affect the scheduling attributes of "GLOBAL" threads.
+** However, a semblance of GLOBAL threads is used to implement "LOCAL"
+** threads. An arbitrary number of such LOCAL threads can be assigned to
+** a single GLOBAL thread.
+**
+** For scheduling, NSPR will attempt to run the highest priority LOCAL
+** thread associated with a given GLOBAL thread. It is further assumed
+** that the host OS will apply some form of "fair" scheduling on the
+** GLOBAL threads.
+**
+** Threads have a "system flag" which when set indicates the thread
+** doesn't count for determining when the process should exit (the
+** process exits when the last user thread exits).
+**
+** Threads also have a "scope flag" which controls whether the threads
+** are scheduled in the local scope or scheduled by the OS globally. This
+** indicates whether a thread is permanently bound to a native OS thread.
+** An unbound thread competes for scheduling resources in the same process.
+**
+** Another flag is "state flag" which control whether the thread is joinable.
+** It allows other threads to wait for the created thread to reach completion.
+**
+** Threads can have "per-thread-data" attached to them. Each thread has a
+** per-thread error number and error string which are updated when NSPR
+** operations fail.
+*/
+#include "prtypes.h"
+#include "prinrval.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateThread VBoxNsprPR_CreateThread
+#define PR_JoinThread VBoxNsprPR_JoinThread
+#define PR_Sleep VBoxNsprPR_Sleep
+#define PR_GetCurrentThread VBoxNsprPR_GetCurrentThread
+#define PR_GetThreadState VBoxNsprPR_GetThreadState
+#define PR_SetThreadPrivate VBoxNsprPR_SetThreadPrivate
+#define PR_GetThreadPrivate VBoxNsprPR_GetThreadPrivate
+#define PR_NewThreadPrivateIndex VBoxNsprPR_NewThreadPrivateIndex
+#define PR_GetThreadPriority VBoxNsprPR_GetThreadPriority
+#define PR_SetThreadPriority VBoxNsprPR_SetThreadPriority
+#define PR_Interrupt VBoxNsprPR_Interrupt
+#define PR_ClearInterrupt VBoxNsprPR_ClearInterrupt
+#define PR_BlockInterrupt VBoxNsprPR_BlockInterrupt
+#define PR_UnblockInterrupt VBoxNsprPR_UnblockInterrupt
+#define PR_GetThreadScope VBoxNsprPR_GetThreadScope
+#define PR_GetThreadType VBoxNsprPR_GetThreadType
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PRThread PRThread;
+typedef struct PRThreadStack PRThreadStack;
+
+typedef enum PRThreadType {
+ PR_USER_THREAD,
+ PR_SYSTEM_THREAD
+} PRThreadType;
+
+typedef enum PRThreadScope {
+ PR_LOCAL_THREAD,
+ PR_GLOBAL_THREAD,
+ PR_GLOBAL_BOUND_THREAD
+} PRThreadScope;
+
+typedef enum PRThreadState {
+ PR_JOINABLE_THREAD,
+ PR_UNJOINABLE_THREAD
+} PRThreadState;
+
+typedef enum PRThreadPriority
+{
+ PR_PRIORITY_FIRST = 0, /* just a placeholder */
+ PR_PRIORITY_LOW = 0, /* the lowest possible priority */
+ PR_PRIORITY_NORMAL = 1, /* most common expected priority */
+ PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */
+ PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */
+ PR_PRIORITY_LAST = 3 /* this is just a placeholder */
+} PRThreadPriority;
+
+/*
+** Create a new thread:
+** "type" is the type of thread to create
+** "start(arg)" will be invoked as the threads "main"
+** "priority" will be created thread's priority
+** "scope" will specify whether the thread is local or global
+** "state" will specify whether the thread is joinable or not
+** "stackSize" the size of the stack, in bytes. The value can be zero
+** and then a machine specific stack size will be chosen.
+**
+** This can return NULL if some kind of error occurs, such as if memory is
+** tight.
+**
+** If you want the thread to start up waiting for the creator to do
+** something, enter a lock before creating the thread and then have the
+** threads start routine enter and exit the same lock. When you are ready
+** for the thread to run, exit the lock.
+**
+** If you want to detect the completion of the created thread, the thread
+** should be created joinable. Then, use PR_JoinThread to synchrnoize the
+** termination of another thread.
+**
+** When the start function returns the thread exits. If it is the last
+** PR_USER_THREAD to exit then the process exits.
+*/
+NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
+ void (PR_CALLBACK *start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+
+/*
+** Wait for thread termination:
+** "thread" is the target thread
+**
+** This can return PR_FAILURE if no joinable thread could be found
+** corresponding to the specified target thread.
+**
+** The calling thread is blocked until the target thread completes.
+** Several threads cannot wait for the same thread to complete; one thread
+** will operate successfully and others will terminate with an error PR_FAILURE.
+** The calling thread will not be blocked if the target thread has already
+** terminated.
+*/
+NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);
+
+/*
+** Return the current thread object for the currently running code.
+** Never returns NULL.
+*/
+NSPR_API(PRThread*) PR_GetCurrentThread(void);
+#ifndef NO_NSPR_10_SUPPORT
+#define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
+#endif /* NO_NSPR_10_SUPPORT */
+
+/*
+** Get the priority of "thread".
+*/
+NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);
+
+/*
+** Change the priority of the "thread" to "priority".
+*/
+NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);
+
+/*
+** This routine returns a new index for per-thread-private data table.
+** The index is visible to all threads within a process. This index can
+** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines
+** to save and retrieve data associated with the index for a thread.
+**
+** Each index is associationed with a destructor function ('dtor'). The function
+** may be specified as NULL when the index is created. If it is not NULL, the
+** function will be called when:
+** - the thread exits and the private data for the associated index
+** is not NULL,
+** - new thread private data is set and the current private data is
+** not NULL.
+**
+** The index independently maintains specific values for each binding thread.
+** A thread can only get access to its own thread-specific-data.
+**
+** Upon a new index return the value associated with the index for all threads
+** is NULL, and upon thread creation the value associated with all indices for
+** that thread is NULL.
+**
+** Returns PR_FAILURE if the total number of indices will exceed the maximun
+** allowed.
+*/
+typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
+
+NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
+ PRUintn *newIndex, PRThreadPrivateDTOR destructor);
+
+/*
+** Define some per-thread-private data.
+** "tpdIndex" is an index into the per-thread private data table
+** "priv" is the per-thread-private data
+**
+** If the per-thread private data table has a previously registered
+** destructor function and a non-NULL per-thread-private data value,
+** the destructor function is invoked.
+**
+** This can return PR_FAILURE if the index is invalid.
+*/
+NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);
+
+/*
+** Recover the per-thread-private data for the current thread. "tpdIndex" is
+** the index into the per-thread private data table.
+**
+** The returned value may be NULL which is indistinguishable from an error
+** condition.
+**
+** A thread can only get access to its own thread-specific-data.
+*/
+NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);
+
+/*
+** This routine sets the interrupt request for a target thread. The interrupt
+** request remains in the thread's state until it is delivered exactly once
+** or explicitly canceled.
+**
+** A thread that has been interrupted will fail all NSPR blocking operations
+** that return a PRStatus (I/O, waiting on a condition, etc).
+**
+** PR_Interrupt may itself fail if the target thread is invalid.
+*/
+NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);
+
+/*
+** Clear the interrupt request for the calling thread. If no such request
+** is pending, this operation is a noop.
+*/
+NSPR_API(void) PR_ClearInterrupt(void);
+
+/*
+** Block the interrupt for the calling thread.
+*/
+NSPR_API(void) PR_BlockInterrupt(void);
+
+/*
+** Unblock the interrupt for the calling thread.
+*/
+NSPR_API(void) PR_UnblockInterrupt(void);
+
+/*
+** Make the current thread sleep until "ticks" time amount of time
+** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is
+** equivalent to calling PR_Yield. Calling PR_Sleep with an argument
+** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result
+** in a PR_FAILURE error return.
+*/
+NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);
+
+/*
+** Get the scoping of this thread.
+*/
+NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);
+
+/*
+** Get the type of this thread.
+*/
+NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);
+
+/*
+** Get the join state of this thread.
+*/
+NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);
+
+PR_END_EXTERN_C
+
+#endif /* prthread_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prtime.h b/src/libs/xpcom18a4/nsprpub/pr/include/prtime.h
new file mode 100644
index 00000000..fe86d365
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prtime.h
@@ -0,0 +1,311 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * prtime.h --
+ *
+ * NSPR date and time functions
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#ifndef prtime_h___
+#define prtime_h___
+
+#include "prlong.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_Now VBoxNsprPR_Now
+#define PR_ExplodeTime VBoxNsprPR_ExplodeTime
+#define PR_ImplodeTime VBoxNsprPR_ImplodeTime
+#define PR_NormalizeTime VBoxNsprPR_NormalizeTime
+#define PR_LocalTimeParameters VBoxNsprPR_LocalTimeParameters
+#define PR_GMTParameters VBoxNsprPR_GMTParameters
+#define PR_USPacificTimeParameters VBoxNsprPR_USPacificTimeParameters
+#define PR_ParseTimeString VBoxNsprPR_ParseTimeString
+#define PR_FormatTime VBoxNsprPR_FormatTime
+#define PR_FormatTimeUSEnglish VBoxNsprPR_FormatTimeUSEnglish
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**********************************************************************/
+/************************* TYPES AND CONSTANTS ************************/
+/**********************************************************************/
+
+#define PR_MSEC_PER_SEC 1000UL
+#define PR_USEC_PER_SEC 1000000UL
+#define PR_NSEC_PER_SEC 1000000000UL
+#define PR_USEC_PER_MSEC 1000UL
+#define PR_NSEC_PER_MSEC 1000000UL
+
+/*
+ * PRTime --
+ *
+ * NSPR represents basic time as 64-bit signed integers relative
+ * to midnight (00:00:00), January 1, 1970 Greenwich Mean Time (GMT).
+ * (GMT is also known as Coordinated Universal Time, UTC.)
+ * The units of time are in microseconds. Negative times are allowed
+ * to represent times prior to the January 1970 epoch. Such values are
+ * intended to be exported to other systems or converted to human
+ * readable form.
+ *
+ * Notes on porting: PRTime corresponds to time_t in ANSI C. NSPR 1.0
+ * simply uses PRInt64.
+ */
+
+typedef PRInt64 PRTime;
+
+/*
+ * Time zone and daylight saving time corrections applied to GMT to
+ * obtain the local time of some geographic location
+ */
+
+typedef struct PRTimeParameters {
+ PRInt32 tp_gmt_offset; /* the offset from GMT in seconds */
+ PRInt32 tp_dst_offset; /* contribution of DST in seconds */
+} PRTimeParameters;
+
+/*
+ * PRExplodedTime --
+ *
+ * Time broken down into human-readable components such as year, month,
+ * day, hour, minute, second, and microsecond. Time zone and daylight
+ * saving time corrections may be applied. If they are applied, the
+ * offsets from the GMT must be saved in the 'tm_params' field so that
+ * all the information is available to reconstruct GMT.
+ *
+ * Notes on porting: PRExplodedTime corrresponds to struct tm in
+ * ANSI C, with the following differences:
+ * - an additional field tm_usec;
+ * - replacing tm_isdst by tm_params;
+ * - the month field is spelled tm_month, not tm_mon;
+ * - we use absolute year, AD, not the year since 1900.
+ * The corresponding type in NSPR 1.0 is called PRTime. Below is
+ * a table of date/time type correspondence in the three APIs:
+ * API time since epoch time in components
+ * ANSI C time_t struct tm
+ * NSPR 1.0 PRInt64 PRTime
+ * NSPR 2.0 PRTime PRExplodedTime
+ */
+
+typedef struct PRExplodedTime {
+ PRInt32 tm_usec; /* microseconds past tm_sec (0-99999) */
+ PRInt32 tm_sec; /* seconds past tm_min (0-61, accomodating
+ up to two leap seconds) */
+ PRInt32 tm_min; /* minutes past tm_hour (0-59) */
+ PRInt32 tm_hour; /* hours past tm_day (0-23) */
+ PRInt32 tm_mday; /* days past tm_mon (1-31, note that it
+ starts from 1) */
+ PRInt32 tm_month; /* months past tm_year (0-11, Jan = 0) */
+ PRInt16 tm_year; /* absolute year, AD (note that we do not
+ count from 1900) */
+
+ PRInt8 tm_wday; /* calculated day of the week
+ (0-6, Sun = 0) */
+ PRInt16 tm_yday; /* calculated day of the year
+ (0-365, Jan 1 = 0) */
+
+ PRTimeParameters tm_params; /* time parameters used by conversion */
+} PRExplodedTime;
+
+/*
+ * PRTimeParamFn --
+ *
+ * A function of PRTimeParamFn type returns the time zone and
+ * daylight saving time corrections for some geographic location,
+ * given the current time in GMT. The input argument gmt should
+ * point to a PRExplodedTime that is in GMT, i.e., whose
+ * tm_params contains all 0's.
+ *
+ * For any time zone other than GMT, the computation is intended to
+ * consist of two steps:
+ * - Figure out the time zone correction, tp_gmt_offset. This number
+ * usually depends on the geographic location only. But it may
+ * also depend on the current time. For example, all of China
+ * is one time zone right now. But this situation may change
+ * in the future.
+ * - Figure out the daylight saving time correction, tp_dst_offset.
+ * This number depends on both the geographic location and the
+ * current time. Most of the DST rules are expressed in local
+ * current time. If so, one should apply the time zone correction
+ * to GMT before applying the DST rules.
+ */
+
+typedef PRTimeParameters (PR_CALLBACK *PRTimeParamFn)(const PRExplodedTime *gmt);
+
+/**********************************************************************/
+/****************************** FUNCTIONS *****************************/
+/**********************************************************************/
+
+/*
+ * The PR_Now routine returns the current time relative to the
+ * epoch, midnight, January 1, 1970 UTC. The units of the returned
+ * value are microseconds since the epoch.
+ *
+ * The values returned are not guaranteed to advance in a linear fashion
+ * due to the application of time correction protocols which synchronize
+ * computer clocks to some external time source. Consequently it should
+ * not be depended on for interval timing.
+ *
+ * The implementation is machine dependent.
+ * Cf. time_t time(time_t *tp) in ANSI C.
+ */
+#if defined(HAVE_WATCOM_BUG_2)
+PRTime __pascal __export __loadds
+#else
+NSPR_API(PRTime)
+#endif
+PR_Now(void);
+
+/*
+ * Expand time binding it to time parameters provided by PRTimeParamFn.
+ * The calculation is envisoned to proceed in the following steps:
+ * - From given PRTime, calculate PRExplodedTime in GMT
+ * - Apply the given PRTimeParamFn to the GMT that we just calculated
+ * to obtain PRTimeParameters.
+ * - Add the PRTimeParameters offsets to GMT to get the local time
+ * as PRExplodedTime.
+ */
+
+NSPR_API(void) PR_ExplodeTime(
+ PRTime usecs, PRTimeParamFn params, PRExplodedTime *exploded);
+
+/* Reverse operation of PR_ExplodeTime */
+#if defined(HAVE_WATCOM_BUG_2)
+PRTime __pascal __export __loadds
+#else
+NSPR_API(PRTime)
+#endif
+PR_ImplodeTime(const PRExplodedTime *exploded);
+
+/*
+ * Adjust exploded time to normalize field overflows after manipulation.
+ * Note that the following fields of PRExplodedTime should not be
+ * manipulated:
+ * - tm_month and tm_year: because the number of days in a month and
+ * number of days in a year are not constant, it is ambiguous to
+ * manipulate the month and year fields, although one may be tempted
+ * to. For example, what does "a month from January 31st" mean?
+ * - tm_wday and tm_yday: these fields are calculated by NSPR. Users
+ * should treat them as "read-only".
+ */
+
+NSPR_API(void) PR_NormalizeTime(
+ PRExplodedTime *exploded, PRTimeParamFn params);
+
+/**********************************************************************/
+/*********************** TIME PARAMETER FUNCTIONS *********************/
+/**********************************************************************/
+
+/* Time parameters that suit current host machine */
+NSPR_API(PRTimeParameters) PR_LocalTimeParameters(const PRExplodedTime *gmt);
+
+/* Time parameters that represent Greenwich Mean Time */
+NSPR_API(PRTimeParameters) PR_GMTParameters(const PRExplodedTime *gmt);
+
+/*
+ * Time parameters that represent the US Pacific Time Zone, with the
+ * current daylight saving time rules (for testing only)
+ */
+NSPR_API(PRTimeParameters) PR_USPacificTimeParameters(const PRExplodedTime *gmt);
+
+/*
+ * This parses a time/date string into a PRTime
+ * (microseconds after "1-Jan-1970 00:00:00 GMT").
+ * It returns PR_SUCCESS on success, and PR_FAILURE
+ * if the time/date string can't be parsed.
+ *
+ * Many formats are handled, including:
+ *
+ * 14 Apr 89 03:20:12
+ * 14 Apr 89 03:20 GMT
+ * Fri, 17 Mar 89 4:01:33
+ * Fri, 17 Mar 89 4:01 GMT
+ * Mon Jan 16 16:12 PDT 1989
+ * Mon Jan 16 16:12 +0130 1989
+ * 6 May 1992 16:41-JST (Wednesday)
+ * 22-AUG-1993 10:59:12.82
+ * 22-AUG-1993 10:59pm
+ * 22-AUG-1993 12:59am
+ * 22-AUG-1993 12:59 PM
+ * Friday, August 04, 1995 3:54 PM
+ * 06/21/95 04:24:34 PM
+ * 20/06/95 21:07
+ * 95-06-08 19:32:48 EDT
+ *
+ * If the input string doesn't contain a description of the timezone,
+ * we consult the `default_to_gmt' to decide whether the string should
+ * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE).
+ * The correct value for this argument depends on what standard specified
+ * the time string which you are parsing.
+ */
+
+NSPR_API(PRStatus) PR_ParseTimeString (
+ const char *string,
+ PRBool default_to_gmt,
+ PRTime *result);
+
+/*
+ * FIXME: should we also have a formatting function, such as asctime, ctime,
+ * and strftime in standard C library? But this would involve
+ * internationalization issues. Might want to provide a US English version.
+ */
+
+/**********************************************************************/
+/*********************** OLD COMPATIBILITYFUNCTIONS *******************/
+/**********************************************************************/
+#ifndef NO_NSPR_10_SUPPORT
+
+/* Format a time value into a buffer. Same semantics as strftime() */
+NSPR_API(PRUint32) PR_FormatTime(char *buf, int buflen, const char *fmt,
+ const PRExplodedTime *tm);
+
+/* Format a time value into a buffer. Time is always in US English format, regardless
+ * of locale setting.
+ */
+NSPR_API(PRUint32)
+PR_FormatTimeUSEnglish( char* buf, PRUint32 bufSize,
+ const char* format, const PRExplodedTime* tm );
+
+#endif /* NO_NSPR_10_SUPPORT */
+
+PR_END_EXTERN_C
+
+#endif /* prtime_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prtpool.h b/src/libs/xpcom18a4/nsprpub/pr/include/prtpool.h
new file mode 100644
index 00000000..bf083ccb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prtpool.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prtpool_h___
+#define prtpool_h___
+
+#include "prtypes.h"
+#include "prthread.h"
+#include "prio.h"
+#include "prerror.h"
+
+/*
+ * NOTE:
+ * THIS API IS A PRELIMINARY VERSION IN NSPR 4.0 AND IS SUBJECT TO
+ * CHANGE
+ */
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateThreadPool VBoxNsprPR_CreateThreadPool
+#define PR_QueueJobPR_QueueJob_Read VBoxNsprPR_QueueJobPR_QueueJob_Read
+#define PR_QueueJob VBoxNsprPR_QueueJob
+#define PR_QueueJob_Read VBoxNsprPR_QueueJob_Read
+#define PR_QueueJob_Write VBoxNsprPR_QueueJob_Write
+#define PR_QueueJob_Accept VBoxNsprPR_QueueJob_Accept
+#define PR_QueueJob_Connect VBoxNsprPR_QueueJob_Connect
+#define PR_QueueJob_Timer VBoxNsprPR_QueueJob_Timer
+#define PR_CancelJob VBoxNsprPR_CancelJob
+#define PR_JoinJob VBoxNsprPR_JoinJob
+#define PR_ShutdownThreadPool VBoxNsprPR_ShutdownThreadPool
+#define PR_JoinThreadPool VBoxNsprPR_JoinThreadPool
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct PRJobIoDesc {
+ PRFileDesc *socket;
+ PRErrorCode error;
+ PRIntervalTime timeout;
+} PRJobIoDesc;
+
+typedef struct PRThreadPool PRThreadPool;
+typedef struct PRJob PRJob;
+typedef void (PR_CALLBACK *PRJobFn) (void *arg);
+
+/* Create thread pool */
+NSPR_API(PRThreadPool *)
+PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads,
+ PRUint32 stacksize);
+
+/* queue a job */
+NSPR_API(PRJob *)
+PR_QueueJob(PRThreadPool *tpool, PRJobFn fn, void *arg, PRBool joinable);
+
+/* queue a job, when a socket is readable */
+NSPR_API(PRJob *)
+PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod,
+ PRJobFn fn, void * arg, PRBool joinable);
+
+/* queue a job, when a socket is writeable */
+NSPR_API(PRJob *)
+PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod,
+ PRJobFn fn, void * arg, PRBool joinable);
+
+/* queue a job, when a socket has a pending connection */
+NSPR_API(PRJob *)
+PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod,
+ PRJobFn fn, void * arg, PRBool joinable);
+
+/* queue a job, when the socket connection to addr succeeds or fails */
+NSPR_API(PRJob *)
+PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod,
+ const PRNetAddr *addr, PRJobFn fn, void * arg, PRBool joinable);
+
+/* queue a job, when a timer exipres */
+NSPR_API(PRJob *)
+PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout,
+ PRJobFn fn, void * arg, PRBool joinable);
+/* cancel a job */
+NSPR_API(PRStatus)
+PR_CancelJob(PRJob *job);
+
+/* join a job */
+NSPR_API(PRStatus)
+PR_JoinJob(PRJob *job);
+
+/* shutdown pool */
+NSPR_API(PRStatus)
+PR_ShutdownThreadPool(PRThreadPool *tpool);
+
+/* join pool, wait for exit of all threads */
+NSPR_API(PRStatus)
+PR_JoinThreadPool(PRThreadPool *tpool);
+
+PR_END_EXTERN_C
+
+#endif /* prtpool_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prtrace.h b/src/libs/xpcom18a4/nsprpub/pr/include/prtrace.h
new file mode 100644
index 00000000..4e8a6a5f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prtrace.h
@@ -0,0 +1,692 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prtrace_h___
+#define prtrace_h___
+/*
+** prtrace.h -- NSPR's Trace Facility.
+**
+** The Trace Facility provides a means to trace application
+** program events within a process. When implementing an
+** application program an engineer may insert a "Trace" function
+** call, passing arguments to be traced. The "Trace" function
+** combines the user trace data with identifying data and
+** writes this data in time ordered sequence into a circular
+** in-memory buffer; when the buffer fills, it wraps.
+**
+** Functions are provided to set and/or re-configure the size of
+** the trace buffer, control what events are recorded in the
+** buffer, enable and disable tracing based on specific user
+** supplied data and other control functions. Methods are provided
+** to record the trace entries in the in-memory trace buffer to
+** a file.
+**
+** Tracing may cause a performance degredation to the application
+** depending on the number and placement of calls to the tracing
+** facility. When tracing is compiled in and all tracing is
+** disabled via the runtime controls, the overhead should be
+** minimal. ... Famous last words, eh?
+**
+** When DEBUG is defined at compile time, the Trace Facility is
+** compiled as part of NSPR and any application using NSPR's
+** header files will have tracing compiled in. When DEBUG is not
+** defined, the Trace Facility is not compiled into NSPR nor
+** exported in its header files. If the Trace Facility is
+** desired in a non-debug build, then FORCE_NSPR_TRACE may be
+** defined at compile time for both the optimized build of NSPR
+** and the application. NSPR and any application using NSPR's
+** Trace Facility must be compiled with the same level of trace
+** conditioning or unresolved references may be realized at link
+** time.
+**
+** For any of the Trace Facility methods that requires a trace
+** handle as an input argument, the caller must ensure that the
+** trace handle argument is valid. An invalid trace handle
+** argument may cause unpredictable results.
+**
+** Trace Facility methods are thread-safe and SMP safe.
+**
+** Users of the Trace Facility should use the defined macros to
+** invoke trace methods, not the function calls directly. e.g.
+** PR_TRACE( h1,0,1,2, ...); not PR_Trace(h1,0,1,2, ...);
+**
+** Application designers should be aware of the effects of
+** debug and optimized build differences when using result of the
+** Trace Facility macros in expressions.
+**
+** See Also: prcountr.h
+**
+** /lth. 08-Jun-1998.
+*/
+
+#include "prtypes.h"
+#include "prthread.h"
+#include "prtime.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_CreateTrace VBoxNsprPR_CreateTrace
+#define PR_DestroyTrace VBoxNsprPR_DestroyTrace
+#define PR_Trace VBoxNsprPR_Trace
+#define PR_SetTraceOption VBoxNsprPR_SetTraceOption
+#define PR_GetTraceOption VBoxNsprPR_GetTraceOption
+#define PR_GetTraceHandleFromName VBoxNsprPR_GetTraceHandleFromName
+#define PR_GetTraceNameFromHandle VBoxNsprPR_GetTraceNameFromHandle
+#define PR_FindNextTraceQname VBoxNsprPR_FindNextTraceQname
+#define PR_FindNextTraceRname VBoxNsprPR_FindNextTraceRname
+#define PR_RecordTraceEntries VBoxNsprPR_RecordTraceEntries
+#define PR_GetTraceEntries VBoxNsprPR_GetTraceEntries
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+** Opaque type for the trace handle
+** ... Don't even think about looking in here.
+**
+*/
+typedef void * PRTraceHandle;
+
+/*
+** PRTraceEntry -- A trace entry in the in-memory trace buffer
+** looks like this.
+**
+*/
+typedef struct PRTraceEntry
+{
+ PRThread *thread; /* The thread creating the trace entry */
+ PRTraceHandle handle; /* PRTraceHandle creating the trace entry */
+ PRTime time; /* Value of PR_Now() at time of trace entry */
+ PRUint32 userData[8]; /* user supplied trace data */
+} PRTraceEntry;
+
+/*
+** PRTraceOption -- command operands to
+** PR_[Set|Get]TraceOption(). See descriptive meanings there.
+**
+*/
+typedef enum PRTraceOption
+{
+ PRTraceBufSize,
+ PRTraceEnable,
+ PRTraceDisable,
+ PRTraceSuspend,
+ PRTraceResume,
+ PRTraceSuspendRecording,
+ PRTraceResumeRecording,
+ PRTraceLockHandles,
+ PRTraceUnLockHandles,
+ PRTraceStopRecording
+} PRTraceOption;
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DEFINE_TRACE() -- Define a PRTraceHandle
+**
+** DESCRIPTION: PR_DEFINE_TRACE() is used to define a trace
+** handle.
+**
+*/
+#define PR_DEFINE_TRACE(name) PRTraceHandle name
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_INIT_TRACE_HANDLE() -- Set the value of a PRTraceHandle
+**
+** DESCRIPTION:
+** PR_INIT_TRACE_HANDLE() sets the value of a PRTraceHandle
+** to value. e.g. PR_INIT_TRACE_HANDLE( myHandle, NULL );
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_INIT_TRACE_HANDLE(handle,value)\
+ (handle) = (PRCounterHandle)(value)
+#else
+#define PR_INIT_TRACE_HANDLE(handle,value)
+#endif
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_CreateTrace() -- Create a trace handle
+**
+** DESCRIPTION:
+** PR_CreateTrace() creates a new trace handle. Tracing is
+** enabled for this handle when it is created. The trace handle
+** is intended for use in other Trace Facility calls.
+**
+** PR_CreateTrace() registers the QName, RName and description
+** data so that this data can be retrieved later.
+**
+** INPUTS:
+** qName: pointer to string. QName for this trace handle.
+**
+** rName: pointer to string. RName for this trace handle.
+**
+** description: pointer to string. Descriptive data about this
+** trace handle.
+**
+** OUTPUTS:
+** Creates the trace handle.
+** Registers the QName and RName with the trace facility.
+**
+** RETURNS:
+** PRTraceHandle
+**
+** RESTRICTIONS:
+** qName is limited to 31 characters.
+** rName is limited to 31 characters.
+** description is limited to 255 characters.
+**
+*/
+#define PRTRACE_NAME_MAX 31
+#define PRTRACE_DESC_MAX 255
+
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_CREATE_TRACE(handle,qName,rName,description)\
+ (handle) = PR_CreateTrace((qName),(rName),(description))
+#else
+#define PR_CREATE_TRACE(handle,qName,rName,description)
+#endif
+
+NSPR_API(PRTraceHandle)
+ PR_CreateTrace(
+ const char *qName, /* QName for this trace handle */
+ const char *rName, /* RName for this trace handle */
+ const char *description /* description for this trace handle */
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_DestroyTrace() -- Destroy a trace handle
+**
+** DESCRIPTION:
+** PR_DestroyTrace() removes the referenced trace handle and
+** associated QName, RName and description data from the Trace
+** Facility.
+**
+** INPUTS: handle. A PRTraceHandle
+**
+** OUTPUTS:
+** The trace handle is unregistered.
+** The QName, RName and description are removed.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_DESTROY_TRACE(handle)\
+ PR_DestroyTrace((handle))
+#else
+#define PR_DESTROY_TRACE(handle)
+#endif
+
+NSPR_API(void)
+ PR_DestroyTrace(
+ PRTraceHandle handle /* Handle to be destroyed */
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_Trace() -- Make a trace entry in the in-memory trace
+**
+** DESCRIPTION:
+** PR_Trace() makes an entry in the in-memory trace buffer for
+** the referenced trace handle. The next logically available
+** PRTraceEntry is used; when the next trace entry would overflow
+** the trace table, the table wraps.
+**
+** PR_Trace() for a specific trace handle may be disabled by
+** calling PR_SetTraceOption() specifying PRTraceDisable for the
+** trace handle to be disabled.
+**
+** INPUTS:
+** handle: PRTraceHandle. The trace handle for this trace.
+**
+** userData[0..7]: unsigned 32bit integers. user supplied data
+** that is copied into the PRTraceEntry
+**
+** OUTPUTS:
+** A PRTraceEntry is (conditionally) formatted in the in-memory
+** trace buffer.
+**
+** RETURNS: void.
+**
+** RESTRICTIONS:
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7)\
+ PR_Trace((handle),(ud0),(ud1),(ud2),(ud3),(ud4),(ud5),(ud6),(ud7))
+#else
+#define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7)
+#endif
+
+NSPR_API(void)
+ PR_Trace(
+ PRTraceHandle handle, /* use this trace handle */
+ PRUint32 userData0, /* User supplied data word 0 */
+ PRUint32 userData1, /* User supplied data word 1 */
+ PRUint32 userData2, /* User supplied data word 2 */
+ PRUint32 userData3, /* User supplied data word 3 */
+ PRUint32 userData4, /* User supplied data word 4 */
+ PRUint32 userData5, /* User supplied data word 5 */
+ PRUint32 userData6, /* User supplied data word 6 */
+ PRUint32 userData7 /* User supplied data word 7 */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_SetTraceOption() -- Control the Trace Facility
+**
+** DESCRIPTION:
+** PR_SetTraceOption() controls the Trace Facility. Depending on
+** command and value, attributes of the Trace Facility may be
+** changed.
+**
+** INPUTS:
+** command: An enumerated value in the set of PRTraceOption.
+** value: pointer to the data to be set. Type of the data is
+** dependent on command; for each value of command, the type
+** and meaning of dereferenced value is shown.
+**
+** PRTraceBufSize: unsigned long: the size of the trace buffer,
+** in bytes.
+**
+** PRTraceEnable: PRTraceHandle. The trace handle to be
+** enabled.
+**
+** PRTraceDisable: PRTraceHandle. The trace handle to be
+** disabled.
+**
+** PRTraceSuspend: void. value must be NULL. All tracing is
+** suspended.
+**
+** PRTraceResume: void. value must be NULL. Tracing for all
+** previously enabled, prior to a PRTraceSuspend, is resumed.
+**
+** PRTraceStopRecording: void. value must be NULL. If recording
+** (see: ** PR_RecordTraceEntries()) is being done,
+** PRTraceStopRecording causes PR_RecordTraceEntries() to return
+** to its caller. If recording is not being done, this function
+** has no effect.
+**
+** PRTraceSuspendRecording: void. Must be NULL. If recording is
+** being done, PRTraceSuspendRecording causes further writes to
+** the trace file to be suspended. Data in the in-memory
+** trace buffer that would ordinarily be written to the
+** trace file will not be written. Trace entries will continue
+** to be entered in the in-memory buffer. If the Trace Facility
+** recording is already in a suspended state, the call has no
+** effect.
+**
+** PRTraceResumeRecording: void. value must be NULL. If
+** recording for the Trace Facility has been previously been
+** suspended, this causes recording to resume. Recording resumes
+** with the next in-memory buffer segment that would be written
+** if trace recording had not been suspended. If recording is
+** not currently suspended, the call has no effect.
+**
+** PRTraceLockHandles: void. value must be NULL. Locks the
+** trace handle lock. While the trace handle lock is held,
+** calls to PR_CreateTrace() will block until the lock is
+** released.
+**
+** PRTraceUnlockHandles: void. value must be NULL. Unlocks the
+** trace handle lock.
+**
+** OUTPUTS:
+** The operation of the Trace Facility may be changed.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_SET_TRACE_OPTION(command,value)\
+ PR_SetTraceOption((command),(value))
+#else
+#define PR_SET_TRACE_OPTION(command,value)
+#endif
+
+NSPR_API(void)
+ PR_SetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceOption() -- Retrieve settings from the Trace Facility
+**
+** DESCRIPTION:
+** PR_GetTraceOption() retrieves the current setting of the
+** Trace Facility control depending on command.
+**
+**
+** PRTraceBufSize: unsigned long: the size of the trace buffer,
+** in bytes.
+**
+**
+** INPUTS:
+** command: one of the enumerated values in PRTraceOptions
+** valid for PR_GetTraceOption().
+**
+** OUTPUTS:
+** dependent on command.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_GET_TRACE_OPTION(command,value)\
+ PR_GetTraceOption((command),(value))
+#else
+#define PR_GET_TRACE_OPTION(command,value)
+#endif
+
+NSPR_API(void)
+ PR_GetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceHandleFromName() -- Retrieve an existing
+** handle by name.
+**
+** DESCRIPTION:
+** PR_GetTraceHandleFromName() retreives an existing tracehandle
+** using the name specified by qName and rName.
+**
+** INPUTS:
+** qName: pointer to string. QName for this trace handle.
+**
+** rName: pointer to string. RName for this trace handle.
+**
+**
+** OUTPUTS: returned.
+**
+** RETURNS:
+** PRTraceHandle associated with qName and rName or NULL when
+** there is no match.
+**
+** RESTRICTIONS:
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName)\
+ (handle) = PR_GetTraceHandleFromName((qName),(rName))
+#else
+#define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName)
+#endif
+
+NSPR_API(PRTraceHandle)
+ PR_GetTraceHandleFromName(
+ const char *qName, /* QName search argument */
+ const char *rName /* RName search argument */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceNameFromHandle() -- Retreive trace name
+** by bandle.
+**
+** DESCRIPTION:
+** PR_GetTraceNameFromHandle() retreives the existing qName,
+** rName, and description for the referenced trace handle.
+**
+** INPUTS: handle: PRTraceHandle.
+**
+** OUTPUTS: pointers to the Trace Facility's copy of qName,
+** rName and description. ... Don't mess with these values.
+** They're mine.
+**
+** RETURNS: void
+**
+** RESTRICTIONS:
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description)\
+ PR_GetTraceNameFromHandle((handle),(qName),(rName),(description))
+#else
+#define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description)
+#endif
+
+NSPR_API(void)
+ PR_GetTraceNameFromHandle(
+ PRTraceHandle handle, /* handle as search argument */
+ const char **qName, /* pointer to associated QName */
+ const char **rName, /* pointer to associated RName */
+ const char **description /* pointer to associated description */
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextTraceQname() -- Retrieive a QName handle
+** iterator.
+**
+** DESCRIPTION:
+** PR_FindNextTraceQname() retreives the first or next trace
+** QName handle, depending on the value of handle, from the trace
+** database. The PRTraceHandle returned can be used as an
+** iterator to traverse the QName handles in the Trace database.
+**
+** INPUTS:
+** handle: When NULL, PR_FindNextQname() returns the first QName
+** handle. When a handle is a valid PRTraceHandle previously
+** retreived using PR_FindNextQname() the next QName handle is
+** retreived.
+**
+** OUTPUTS: returned.
+**
+** RETURNS:
+** PRTraceHandle or NULL when there are no trace handles.
+**
+** RESTRICTIONS:
+** Iterating thru the trace handles via FindFirst/FindNext
+** should be done under protection of the trace handle lock.
+** See: PR_SetTraceOption( PRLockTraceHandles ).
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_FIND_NEXT_TRACE_QNAME(next,handle)\
+ (next) = PR_FindNextTraceQname((handle))
+#else
+#define PR_FIND_NEXT_TRACE_QNAME(next,handle)
+#endif
+
+NSPR_API(PRTraceHandle)
+ PR_FindNextTraceQname(
+ PRTraceHandle handle
+);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_FindNextTraceRname() -- Retrieive an RName handle
+** iterator.
+**
+** DESCRIPTION:
+** PR_FindNextTraceRname() retreives the first or next trace
+** RName handle, depending on the value of handle, from the trace
+** database. The PRTraceHandle returned can be used as an
+** iterator to traverse the RName handles in the Trace database.
+**
+** INPUTS:
+** rhandle: When NULL, PR_FindNextRname() returns the first
+** RName handle. When a handle is a valid PRTraceHandle
+** previously retreived using PR_FindNextRname() the next RName
+** handle is retreived.
+** qhandle: A valid PRTraceHandle retruned from a previous call
+** to PR_FIND_NEXT_TRACE_QNAME().
+**
+** OUTPUTS: returned.
+**
+** RETURNS:
+** PRTraceHandle or NULL when there are no trace handles.
+**
+** RESTRICTIONS:
+** Iterating thru the trace handles via FindNext should be done
+** under protection of the trace handle lock. See: (
+** PR_SetTraceOption( PRLockTraceHandles ).
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle)\
+ (next) = PR_FindNextTraceRname((rhandle),(qhandle))
+#else
+#define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle)
+#endif
+
+NSPR_API(PRTraceHandle)
+ PR_FindNextTraceRname(
+ PRTraceHandle rhandle,
+ PRTraceHandle qhandle
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_RecordTraceEntries() -- Write trace entries to external media
+**
+** DESCRIPTION:
+** PR_RecordTraceEntries() causes entries in the in-memory trace
+** buffer to be written to external media.
+**
+** When PR_RecordTraceEntries() is called from an application
+** thread, the function appears to block until another thread
+** calls PR_SetTraceOption() with the PRTraceStopRecording
+** option. This suggests that PR_RecordTraceEntries() should be
+** called from a user supplied thread whose only job is to
+** record trace entries.
+**
+** The environment variable NSPR_TRACE_LOG controls the operation
+** of this function. When NSPR_TRACE_LOG is not defined in the
+** environment, no recording of trace entries occurs. When
+** NSPR_TRACE_LOG is defined, the value of its definition must be
+** the filename of the file to receive the trace entry buffer.
+**
+** PR_RecordTraceEntries() attempts to record the in-memory
+** buffer to a file, subject to the setting of the environment
+** variable NSPR_TRACE_LOG. It is possible because of system
+** load, the thread priority of the recording thread, number of
+** active trace records being written over time, and other
+** variables that some trace records can be lost. ... In other
+** words: don't bet the farm on getting everything.
+**
+** INPUTS: none
+**
+** OUTPUTS: none
+**
+** RETURNS: PR_STATUS
+** PR_SUCCESS no errors were found.
+** PR_FAILURE errors were found.
+**
+** RESTRICTIONS:
+** Only one thread can call PR_RecordTraceEntries() within a
+** process.
+**
+** On error, PR_RecordTraceEntries() may return prematurely.
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_RECORD_TRACE_ENTRIES()\
+ PR_RecordTraceEntries()
+#else
+#define PR_RECORD_TRACE_ENTRIES()
+#endif
+
+NSPR_API(void)
+ PR_RecordTraceEntries(
+ void
+);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PR_GetTraceEntries() -- Retreive trace entries from
+** the Trace Facility
+**
+** DESCRIPTION:
+** PR_GetTraceEntries() retreives trace entries from the Trace
+** Facility. Up to count trace entries are copied from the Trace
+** Facility into buffer. Only those trace entries that have not
+** been copied via a previous call to PR_GetTraceEntries() are
+** copied. The actual number copied is placed in the PRInt32
+** variable pointed to by found.
+**
+** If more than count trace entries have entered the Trace
+** Facility since the last call to PR_GetTraceEntries()
+** a lost data condition is returned. In this case, the most
+** recent count trace entries are copied into buffer and found is
+** set to count.
+**
+** INPUTS:
+** count. The number of trace entries to be copied into buffer.
+**
+**
+** OUTPUTS:
+** buffer. An array of PRTraceEntries. The buffer is supplied
+** by the caller.
+**
+** found: 32bit signed integer. The number of PRTraceEntries
+** actually copied. found is always less than or equal to count.
+**
+** RETURNS:
+** zero when there is no lost data.
+** non-zero when some PRTraceEntries have been lost.
+**
+** RESTRICTIONS:
+** This is a real performance pig. The copy out operation is bad
+** enough, but depending on then frequency of calls to the
+** function, serious performance impact to the operating
+** application may be realized. ... YMMV.
+**
+*/
+#if defined (DEBUG) || defined (FORCE_NSPR_TRACE)
+#define PR_GET_TRACE_ENTRIES(buffer,count,found)\
+ PR_GetTraceEntries((buffer),(count),(found))
+#else
+#define PR_GET_TRACE_ENTRIES(buffer,count,found)
+#endif
+
+NSPR_API(PRIntn)
+ PR_GetTraceEntries(
+ PRTraceEntry *buffer, /* where to write output */
+ PRInt32 count, /* number to get */
+ PRInt32 *found /* number you got */
+);
+
+PR_END_EXTERN_C
+
+#endif /* prtrace_h___ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prtypes.h b/src/libs/xpcom18a4/nsprpub/pr/include/prtypes.h
new file mode 100644
index 00000000..32218fd4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prtypes.h
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prtypes.h
+** Description: Definitions of NSPR's basic types
+**
+** Prototypes and macros used to make up for deficiencies in ANSI environments
+** that we have found.
+**
+** Since we do not wrap <stdlib.h> and all the other standard headers, authors
+** of portable code will not know in general that they need these definitions.
+** Instead of requiring these authors to find the dependent uses in their code
+** and take the following steps only in those C files, we take steps once here
+** for all C files.
+**/
+
+#ifndef prtypes_h___
+#define prtypes_h___
+
+#ifdef MDCPUCFG
+#include MDCPUCFG
+#else
+#include "prcpucfg.h"
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+/***********************************************************************
+** MACROS: PR_EXTERN
+** PR_IMPLEMENT
+** DESCRIPTION:
+** These are only for externally visible routines and globals. For
+** internal routines, just use "extern" for type checking and that
+** will not export internal cross-file or forward-declared symbols.
+** Define a macro for declaring procedures return types. We use this to
+** deal with windoze specific type hackery for DLL definitions. Use
+** PR_EXTERN when the prototype for the method is declared. Use
+** PR_IMPLEMENT for the implementation of the method.
+**
+** Example:
+** in dowhim.h
+** PR_EXTERN( void ) DoWhatIMean( void );
+** in dowhim.c
+** PR_IMPLEMENT( void ) DoWhatIMean( void ) { return; }
+**
+**
+***********************************************************************/
+#if defined(WIN32)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) __declspec(dllimport) __type
+#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_BEOS)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(WIN16)
+
+#define PR_CALLBACK_DECL __cdecl
+
+#if defined(_WINDLL)
+#define PR_EXPORT(__type) extern __type _cdecl _export _loadds
+#define PR_IMPORT(__type) extern __type _cdecl _export _loadds
+#define PR_EXPORT_DATA(__type) extern __type _export
+#define PR_IMPORT_DATA(__type) extern __type _export
+
+#define PR_EXTERN(__type) extern __type _cdecl _export _loadds
+#define PR_IMPLEMENT(__type) __type _cdecl _export _loadds
+#define PR_EXTERN_DATA(__type) extern __type _export
+#define PR_IMPLEMENT_DATA(__type) __type _export
+
+#define PR_CALLBACK __cdecl __loadds
+#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK
+
+#else /* this must be .EXE */
+#define PR_EXPORT(__type) extern __type _cdecl _export
+#define PR_IMPORT(__type) extern __type _cdecl _export
+#define PR_EXPORT_DATA(__type) extern __type _export
+#define PR_IMPORT_DATA(__type) extern __type _export
+
+#define PR_EXTERN(__type) extern __type _cdecl _export
+#define PR_IMPLEMENT(__type) __type _cdecl _export
+#define PR_EXTERN_DATA(__type) extern __type _export
+#define PR_IMPLEMENT_DATA(__type) __type _export
+
+#define PR_CALLBACK __cdecl __loadds
+#define PR_STATIC_CALLBACK(__x) __x PR_CALLBACK
+#endif /* _WINDLL */
+
+#elif defined(XP_MAC)
+
+#define PR_EXPORT(__type) extern __declspec(export) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(export) __type
+#define PR_IMPORT(__type) extern __declspec(export) __type
+#define PR_IMPORT_DATA(__type) extern __declspec(export) __type
+
+#define PR_EXTERN(__type) extern __declspec(export) __type
+#define PR_IMPLEMENT(__type) __declspec(export) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(export) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(export) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_OS2) && defined(__declspec)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) __declspec(dllimport) __type
+#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_OS2_VACPP)
+
+#define PR_EXPORT(__type) extern __type
+#define PR_EXPORT_DATA(__type) extern __type
+#define PR_IMPORT(__type) extern __type
+#define PR_IMPORT_DATA(__type) extern __type
+
+#define PR_EXTERN(__type) extern __type
+#define PR_IMPLEMENT(__type) __type
+#define PR_EXTERN_DATA(__type) extern __type
+#define PR_IMPLEMENT_DATA(__type) __type
+#define PR_CALLBACK _Optlink
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK
+
+#else /* Unix */
+
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define PR_EXPORT(__type) __attribute__((visibility("default"))) extern __type
+# define PR_EXPORT_DATA(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPORT(__type) extern __type
+# define PR_IMPORT_DATA(__type) extern __type
+# define PR_EXTERN(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPLEMENT(__type) __attribute__((visibility("default"))) __type
+# define PR_EXTERN_DATA(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPLEMENT_DATA(__type) __attribute__((visibility("default"))) __type
+# define PR_CALLBACK
+# define PR_CALLBACK_DECL
+# define PR_STATIC_CALLBACK(__x) static __x
+# else
+# define PR_EXPORT(__type) extern __type
+# define PR_EXPORT_DATA(__type) extern __type
+# define PR_IMPORT(__type) extern __type
+# define PR_IMPORT_DATA(__type) extern __type
+# define PR_EXTERN(__type) extern __type
+# define PR_IMPLEMENT(__type) __type
+# define PR_EXTERN_DATA(__type) extern __type
+# define PR_IMPLEMENT_DATA(__type) __type
+# define PR_CALLBACK
+# define PR_CALLBACK_DECL
+# define PR_STATIC_CALLBACK(__x) static __x
+# endif
+#endif
+
+#if defined(_NSPR_BUILD_)
+#define NSPR_API(__type) PR_EXPORT(__type)
+#define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type)
+#else
+#define NSPR_API(__type) PR_IMPORT(__type)
+#define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type)
+#endif
+
+/***********************************************************************
+** MACROS: PR_BEGIN_MACRO
+** PR_END_MACRO
+** DESCRIPTION:
+** Macro body brackets so that macros with compound statement definitions
+** behave syntactically more like functions when called.
+***********************************************************************/
+#define PR_BEGIN_MACRO do {
+#define PR_END_MACRO } while (0)
+
+/***********************************************************************
+** MACROS: PR_BEGIN_EXTERN_C
+** PR_END_EXTERN_C
+** DESCRIPTION:
+** Macro shorthands for conditional C++ extern block delimiters.
+***********************************************************************/
+#ifdef __cplusplus
+#define PR_BEGIN_EXTERN_C extern "C" {
+#define PR_END_EXTERN_C }
+#else
+#define PR_BEGIN_EXTERN_C
+#define PR_END_EXTERN_C
+#endif
+
+/***********************************************************************
+** MACROS: PR_BIT
+** PR_BITMASK
+** DESCRIPTION:
+** Bit masking macros. XXX n must be <= 31 to be portable
+***********************************************************************/
+#define PR_BIT(n) ((PRUint32)1 << (n))
+#define PR_BITMASK(n) (PR_BIT(n) - 1)
+
+/***********************************************************************
+** MACROS: PR_ROUNDUP
+** PR_MIN
+** PR_MAX
+** PR_ABS
+** DESCRIPTION:
+** Commonly used macros for operations on compatible types.
+***********************************************************************/
+#define PR_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+#define PR_MIN(x,y) ((x)<(y)?(x):(y))
+#define PR_MAX(x,y) ((x)>(y)?(x):(y))
+#define PR_ABS(x) ((x)<0?-(x):(x))
+
+PR_BEGIN_EXTERN_C
+
+/************************************************************************
+** TYPES: PRUint8
+** PRInt8
+** DESCRIPTION:
+** The int8 types are known to be 8 bits each. There is no type that
+** is equivalent to a plain "char".
+************************************************************************/
+#if PR_BYTES_PER_BYTE == 1
+typedef unsigned char PRUint8;
+/*
+** Some cfront-based C++ compilers do not like 'signed char' and
+** issue the warning message:
+** warning: "signed" not implemented (ignored)
+** For these compilers, we have to define PRInt8 as plain 'char'.
+** Make sure that plain 'char' is indeed signed under these compilers.
+*/
+#if (defined(HPUX) && defined(__cplusplus) \
+ && !defined(__GNUC__) && __cplusplus < 199707L) \
+ || (defined(SCO) && defined(__cplusplus) \
+ && !defined(__GNUC__) && __cplusplus == 1L)
+typedef char PRInt8;
+#else
+typedef signed char PRInt8;
+#endif
+#else
+#error No suitable type for PRInt8/PRUint8
+#endif
+
+/************************************************************************
+ * MACROS: PR_INT8_MAX
+ * PR_INT8_MIN
+ * PR_UINT8_MAX
+ * DESCRIPTION:
+ * The maximum and minimum values of a PRInt8 or PRUint8.
+************************************************************************/
+
+#define PR_INT8_MAX 127
+#define PR_INT8_MIN (-128)
+#define PR_UINT8_MAX 255U
+
+/************************************************************************
+** TYPES: PRUint16
+** PRInt16
+** DESCRIPTION:
+** The int16 types are known to be 16 bits each.
+************************************************************************/
+#if PR_BYTES_PER_SHORT == 2
+typedef unsigned short PRUint16;
+typedef short PRInt16;
+#else
+#error No suitable type for PRInt16/PRUint16
+#endif
+
+/************************************************************************
+ * MACROS: PR_INT16_MAX
+ * PR_INT16_MIN
+ * PR_UINT16_MAX
+ * DESCRIPTION:
+ * The maximum and minimum values of a PRInt16 or PRUint16.
+************************************************************************/
+
+#define PR_INT16_MAX 32767
+#define PR_INT16_MIN (-32768)
+#define PR_UINT16_MAX 65535U
+
+/************************************************************************
+** TYPES: PRUint32
+** PRInt32
+** DESCRIPTION:
+** The int32 types are known to be 32 bits each.
+************************************************************************/
+#if PR_BYTES_PER_INT == 4
+typedef unsigned int PRUint32;
+typedef int PRInt32;
+#define PR_INT32(x) x
+#define PR_UINT32(x) x ## U
+#elif PR_BYTES_PER_LONG == 4
+typedef unsigned long PRUint32;
+typedef long PRInt32;
+#define PR_INT32(x) x ## L
+#define PR_UINT32(x) x ## UL
+#else
+#error No suitable type for PRInt32/PRUint32
+#endif
+
+/************************************************************************
+ * MACROS: PR_INT32_MAX
+ * PR_INT32_MIN
+ * PR_UINT32_MAX
+ * DESCRIPTION:
+ * The maximum and minimum values of a PRInt32 or PRUint32.
+************************************************************************/
+
+#define PR_INT32_MAX PR_INT32(2147483647)
+#define PR_INT32_MIN (-PR_INT32_MAX - 1)
+#define PR_UINT32_MAX PR_UINT32(4294967295)
+
+/************************************************************************
+** TYPES: PRUint64
+** PRInt64
+** DESCRIPTION:
+** The int64 types are known to be 64 bits each. Care must be used when
+** declaring variables of type PRUint64 or PRInt64. Different hardware
+** architectures and even different compilers have varying support for
+** 64 bit values. The only guaranteed portability requires the use of
+** the LL_ macros (see prlong.h).
+************************************************************************/
+#ifdef HAVE_LONG_LONG
+#if PR_BYTES_PER_LONG == 8
+typedef long PRInt64;
+typedef unsigned long PRUint64;
+#elif defined(WIN16)
+typedef __int64 PRInt64;
+typedef unsigned __int64 PRUint64;
+#elif defined(WIN32) && !defined(__GNUC__)
+typedef __int64 PRInt64;
+typedef unsigned __int64 PRUint64;
+#else
+typedef long long PRInt64;
+typedef unsigned long long PRUint64;
+#endif /* PR_BYTES_PER_LONG == 8 */
+#else /* !HAVE_LONG_LONG */
+typedef struct {
+#ifdef IS_LITTLE_ENDIAN
+ PRUint32 lo, hi;
+#else
+ PRUint32 hi, lo;
+#endif
+} PRInt64;
+typedef PRInt64 PRUint64;
+#endif /* !HAVE_LONG_LONG */
+
+/************************************************************************
+** TYPES: PRUintn
+** PRIntn
+** DESCRIPTION:
+** The PRIntn types are most appropriate for automatic variables. They are
+** guaranteed to be at least 16 bits, though various architectures may
+** define them to be wider (e.g., 32 or even 64 bits). These types are
+** never valid for fields of a structure.
+************************************************************************/
+#if PR_BYTES_PER_INT >= 2
+typedef int PRIntn;
+typedef unsigned int PRUintn;
+#else
+#error 'sizeof(int)' not sufficient for platform use
+#endif
+
+/************************************************************************
+** TYPES: PRFloat64
+** DESCRIPTION:
+** NSPR's floating point type is always 64 bits.
+************************************************************************/
+typedef double PRFloat64;
+
+/************************************************************************
+** TYPES: PRSize
+** DESCRIPTION:
+** A type for representing the size of objects.
+************************************************************************/
+typedef size_t PRSize;
+
+
+/************************************************************************
+** TYPES: PROffset32, PROffset64
+** DESCRIPTION:
+** A type for representing byte offsets from some location.
+************************************************************************/
+typedef PRInt32 PROffset32;
+typedef PRInt64 PROffset64;
+
+/************************************************************************
+** TYPES: PRPtrDiff
+** DESCRIPTION:
+** A type for pointer difference. Variables of this type are suitable
+** for storing a pointer or pointer sutraction.
+************************************************************************/
+typedef ptrdiff_t PRPtrdiff;
+
+/************************************************************************
+** TYPES: PRUptrdiff
+** DESCRIPTION:
+** A type for pointer difference. Variables of this type are suitable
+** for storing a pointer or pointer sutraction.
+************************************************************************/
+typedef unsigned long PRUptrdiff;
+
+/************************************************************************
+** TYPES: PRBool
+** DESCRIPTION:
+** Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE
+** for clarity of target type in assignments and actual arguments. Use
+** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
+** juast as you would C int-valued conditions.
+************************************************************************/
+typedef PRIntn PRBool;
+#define PR_TRUE 1
+#define PR_FALSE 0
+
+/************************************************************************
+** TYPES: PRPackedBool
+** DESCRIPTION:
+** Use PRPackedBOol within structs where bitfields are not desireable
+** but minimum and consistant overhead matters.
+************************************************************************/
+typedef PRUint8 PRPackedBool;
+
+/*
+** Status code used by some routines that have a single point of failure or
+** special status return.
+*/
+typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
+
+#ifdef MOZ_UNICODE
+/*
+ * EXPERIMENTAL: This type may be removed in a future release.
+ */
+#ifndef __PRUNICHAR__
+#define __PRUNICHAR__
+#if defined(WIN32) || defined(XP_MAC)
+typedef wchar_t PRUnichar;
+#else
+typedef PRUint16 PRUnichar;
+#endif
+#endif
+#endif /* MOZ_UNICODE */
+
+/*
+** WARNING: The undocumented data types PRWord and PRUword are
+** only used in the garbage collection and arena code. Do not
+** use PRWord and PRUword in new code.
+**
+** A PRWord is an integer that is the same size as a void*.
+** It implements the notion of a "word" in the Java Virtual
+** Machine. (See Sec. 3.4 "Words", The Java Virtual Machine
+** Specification, Addison-Wesley, September 1996.
+** http://java.sun.com/docs/books/vmspec/index.html.)
+*/
+typedef long PRWord;
+typedef unsigned long PRUword;
+
+#if defined(NO_NSPR_10_SUPPORT)
+#else
+/********* ???????????????? FIX ME ??????????????????????????? *****/
+/********************** Some old definitions until pr=>ds transition is done ***/
+/********************** Also, we are still using NSPR 1.0. GC ******************/
+/*
+** Fundamental NSPR macros, used nearly everywhere.
+*/
+
+#define PR_PUBLIC_API PR_IMPLEMENT
+
+/*
+** Macro body brackets so that macros with compound statement definitions
+** behave syntactically more like functions when called.
+*/
+#define NSPR_BEGIN_MACRO do {
+#define NSPR_END_MACRO } while (0)
+
+/*
+** Macro shorthands for conditional C++ extern block delimiters.
+*/
+#ifdef NSPR_BEGIN_EXTERN_C
+#undef NSPR_BEGIN_EXTERN_C
+#endif
+#ifdef NSPR_END_EXTERN_C
+#undef NSPR_END_EXTERN_C
+#endif
+
+#ifdef __cplusplus
+#define NSPR_BEGIN_EXTERN_C extern "C" {
+#define NSPR_END_EXTERN_C }
+#else
+#define NSPR_BEGIN_EXTERN_C
+#define NSPR_END_EXTERN_C
+#endif
+
+#ifdef XP_MAC
+#include "protypes.h"
+#else
+#include "obsolete/protypes.h"
+#endif
+
+/********* ????????????? End Fix me ?????????????????????????????? *****/
+#endif /* NO_NSPR_10_SUPPORT */
+
+PR_END_EXTERN_C
+
+#endif /* prtypes_h___ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prvrsion.h b/src/libs/xpcom18a4/nsprpub/pr/include/prvrsion.h
new file mode 100644
index 00000000..eb8e1e61
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prvrsion.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/* author: jstewart */
+
+#if defined(_PRVERSION_H)
+#else
+#define _PRVERSION_H
+
+#include "prtypes.h"
+
+PR_BEGIN_EXTERN_C
+
+/* All components participating in the PR version protocol must expose
+ * a structure and a function. The structure is defined below and named
+ * according to the naming conventions outlined further below. The function
+ * is called libVersionPoint and returns a pointer to this structure.
+ */
+
+/* on NT, always pack the structure the same. */
+#ifdef _WIN32
+#pragma pack(push, 8)
+#endif
+
+typedef struct {
+ /*
+ * The first field defines which version of this structure is in use.
+ * At this time, only version 2 is specified. If this value is not
+ * 2, you must read no further into the structure.
+ */
+ PRInt32 version;
+
+ /* for Version 2, this is the body format. */
+ PRInt64 buildTime; /* 64 bits - usecs since midnight, 1/1/1970 */
+ char * buildTimeString;/* a human readable version of the time */
+
+ PRUint8 vMajor; /* Major version of this component */
+ PRUint8 vMinor; /* Minor version of this component */
+ PRUint8 vPatch; /* Patch level of this component */
+
+ PRBool beta; /* true if this is a beta component */
+ PRBool debug; /* true if this is a debug component */
+ PRBool special; /* true if this component is a special build */
+
+ char * filename; /* The original filename */
+ char * description; /* description of this component */
+ char * security; /* level of security in this component */
+ char * copyright; /* The copyright for this file */
+ char * comment; /* free form field for misc usage */
+ char * specialString; /* the special variant for this build */
+} PRVersionDescription;
+
+/* on NT, restore the previous packing */
+#ifdef _WIN32
+#pragma pack(pop)
+#endif
+
+/*
+ * All components must define an entrypoint named libVersionPoint which
+ * is of type versionEntryPointType.
+ *
+ * For example, for a library named libfoo, we would have:
+ *
+ * PRVersionDescription prVersionDescription_libfoo =
+ * {
+ * ...
+ * };
+ *
+ * PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void)
+ * {
+ * return &prVersionDescription_libfoo;
+ * }
+ */
+typedef const PRVersionDescription *(*versionEntryPointType)(void);
+
+/*
+ * Where you declare your libVersionPoint, do it like this:
+ * PR_IMPLEMENT(const PRVersionDescription *) libVersionPoint(void) {
+ * fill it in...
+ * }
+ */
+
+/*
+ * NAMING CONVENTION FOR struct
+ *
+ * all components should also expose a static PRVersionDescription
+ * The name of the struct should be calculated as follows:
+ * Take the value of filename. (If filename is not specified, calculate
+ * a short, unique string.) Convert all non-alphanumeric characters
+ * to '_'. To this, prepend "PRVersionDescription_". Thus for libfoo.so,
+ * the symbol name is "PRVersionDescription_libfoo_so".
+ * so the file should have
+ * PRVersionDescription PRVersionDescription_libfoo_so { fill it in };
+ * on NT, this file should be declspec export.
+ */
+
+PR_END_EXTERN_C
+
+#endif /* defined(_PRVERSION_H) */
+
+/* prvrsion.h */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/include/prwin16.h b/src/libs/xpcom18a4/nsprpub/pr/include/prwin16.h
new file mode 100644
index 00000000..215b0514
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/include/prwin16.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef prwin16_h___
+#define prwin16_h___
+
+/*
+** Condition use of this header on platform.
+*/
+#if (defined(XP_PC) && !defined(_WIN32) && !defined(XP_OS2) && defined(MOZILLA_CLIENT)) || defined(WIN16)
+#include <stdio.h>
+
+PR_BEGIN_EXTERN_C
+/*
+** Win16 stdio special case.
+** To get stdio to work for Win16, all calls to printf() and related
+** things must be called from the environment of the .EXE; calls to
+** printf() from the .DLL send output to the bit-bucket.
+**
+** To make sure that PR_fprintf(), and related functions, work correctly,
+** the actual stream I/O to stdout, stderr, stdin must be done in the
+** .EXE. To do this, a hack is placed in _MD_Write() such that the
+** fd for stdio handles results in a call to the .EXE.
+**
+** file w16stdio.c contains the functions that get called from NSPR
+** to do the actual I/O. w16stdio.o must be statically linked with
+** any application needing stdio for Win16.
+**
+** The address of these functions must be made available to the .DLL
+** so he can call back to the .EXE. To do this, function
+** PR_MD_RegisterW16StdioCallbacks() is called from the .EXE.
+** The arguments are the functions defined in w16stdio.c
+** At runtime, MD_Write() calls the registered functions, if any
+** were registered.
+**
+** prinit.h contains a macro PR_STDIO_INIT() that calls the registration
+** function for Win16; For other platforms, the macro is a No-Op.
+**
+** Note that stdio is not operational at all on Win16 GUI applications.
+** This special case exists to provide stdio capability from the NSPR
+** .DLL for command line applications only. NSPR's test cases are
+** almost exclusively command line applications.
+**
+** See also: w16io.c, w16stdio.c
+*/
+typedef PRInt32 (PR_CALLBACK *PRStdinRead)( void *buf, PRInt32 amount);
+typedef PRInt32 (PR_CALLBACK *PRStdoutWrite)( void *buf, PRInt32 amount);
+typedef PRInt32 (PR_CALLBACK *PRStderrWrite)( void *buf, PRInt32 amount);
+
+NSPR_API(PRStatus)
+PR_MD_RegisterW16StdioCallbacks(
+ PRStdinRead inReadf, /* i: function pointer for stdin read */
+ PRStdoutWrite outWritef, /* i: function pointer for stdout write */
+ PRStderrWrite errWritef /* i: function pointer for stderr write */
+ );
+
+NSPR_API(PRInt32)
+_PL_W16StdioWrite( void *buf, PRInt32 amount );
+
+NSPR_API(PRInt32)
+_PL_W16StdioRead( void *buf, PRInt32 amount );
+
+#define PR_STDIO_INIT() PR_MD_RegisterW16StdioCallbacks( \
+ _PL_W16StdioRead, _PL_W16StdioWrite, _PL_W16StdioWrite ); \
+ PR_INIT_CALLBACKS();
+
+/*
+** Win16 hackery.
+**
+*/
+struct PRMethodCallbackStr {
+ int (PR_CALLBACK *auxOutput)(const char *outputString);
+ size_t (PR_CALLBACK *strftime)(char *s, size_t len, const char *fmt, const struct tm *p);
+ void * (PR_CALLBACK *malloc)( size_t size );
+ void * (PR_CALLBACK *calloc)(size_t n, size_t size );
+ void * (PR_CALLBACK *realloc)( void* old_blk, size_t size );
+ void (PR_CALLBACK *free)( void *ptr );
+ void * (PR_CALLBACK *getenv)( const char *name);
+ int (PR_CALLBACK *putenv)( const char *assoc);
+/* void * (PR_CALLBACK *perror)( const char *prefix ); */
+};
+
+NSPR_API(void) PR_MDRegisterCallbacks(struct PRMethodCallbackStr *);
+
+int PR_CALLBACK _PL_W16CallBackPuts( const char *outputString );
+size_t PR_CALLBACK _PL_W16CallBackStrftime(
+ char *s,
+ size_t len,
+ const char *fmt,
+ const struct tm *p );
+void * PR_CALLBACK _PL_W16CallBackMalloc( size_t size );
+void * PR_CALLBACK _PL_W16CallBackCalloc( size_t n, size_t size );
+void * PR_CALLBACK _PL_W16CallBackRealloc(
+ void *old_blk,
+ size_t size );
+void PR_CALLBACK _PL_W16CallBackFree( void *ptr );
+void * PR_CALLBACK _PL_W16CallBackGetenv( const char *name );
+int PR_CALLBACK _PL_W16CallBackPutenv( const char *assoc );
+
+/*
+** Hackery!
+**
+** These functions are provided as static link points.
+** This is to satisfy the quick port of Gromit to NSPR 2.0
+** ... Don't do this! ... alas, It may never go away.
+**
+*/
+NSPR_API(int) PR_MD_printf(const char *, ...);
+NSPR_API(void) PR_MD_exit(int);
+NSPR_API(size_t) PR_MD_strftime(char *, size_t, const char *, const struct tm *);
+NSPR_API(int) PR_MD_sscanf(const char *, const char *, ...);
+NSPR_API(void*) PR_MD_malloc( size_t size );
+NSPR_API(void*) PR_MD_calloc( size_t n, size_t size );
+NSPR_API(void*) PR_MD_realloc( void* old_blk, size_t size );
+NSPR_API(void) PR_MD_free( void *ptr );
+NSPR_API(char*) PR_MD_getenv( const char *name );
+NSPR_API(int) PR_MD_putenv( const char *assoc );
+NSPR_API(int) PR_MD_fprintf(FILE *fPtr, const char *fmt, ...);
+
+#define PR_INIT_CALLBACKS() \
+ { \
+ static struct PRMethodCallbackStr cbf = { \
+ _PL_W16CallBackPuts, \
+ _PL_W16CallBackStrftime, \
+ _PL_W16CallBackMalloc, \
+ _PL_W16CallBackCalloc, \
+ _PL_W16CallBackRealloc, \
+ _PL_W16CallBackFree, \
+ _PL_W16CallBackGetenv, \
+ _PL_W16CallBackPutenv, \
+ }; \
+ PR_MDRegisterCallbacks( &cbf ); \
+ }
+
+
+/*
+** Get the exception context for Win16 MFC applications threads
+*/
+NSPR_API(void *) PR_W16GetExceptionContext(void);
+/*
+** Set the exception context for Win16 MFC applications threads
+*/
+NSPR_API(void) PR_W16SetExceptionContext(void *context);
+
+PR_END_EXTERN_C
+#else
+/*
+** For platforms other than Win16, define
+** PR_STDIO_INIT() as a No-Op.
+*/
+#define PR_STDIO_INIT()
+#endif /* WIN16 || MOZILLA_CLIENT */
+
+#endif /* prwin16_h___ */
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/.cvsignore
new file mode 100644
index 00000000..41a1bd2b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+_pr_bld.h
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/Makefile.in
new file mode 100644
index 00000000..c15e2153
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/Makefile.in
@@ -0,0 +1,422 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = io linking malloc md memory misc threads
+
+# For VAC++ 4 geticcdata rule in config/OS2.mk
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+CSRCS = prvrsion.c
+endif
+
+ifeq ($(USE_PTHREADS), 1)
+ DIRS += pthreads
+endif
+
+ifeq ($(USE_BTHREADS), 1)
+ DIRS += bthreads
+endif
+
+ifeq ($(USE_CPLUS), 1)
+ DIRS += cplus
+endif
+
+#
+# Define platform-dependent OS_LIBS
+#
+
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OS_LIBS = -lm
+else # 4.1.3_U1
+MAPFILE = $(OBJDIR)/nsprmap.sun
+GARBAGE += $(MAPFILE)
+ifdef NS_USE_GCC
+ifdef GCC_USE_GNU_LD
+MKSHLIB += -Wl,--version-script,$(MAPFILE)
+else
+MKSHLIB += -Wl,-M,$(MAPFILE)
+endif
+else
+MKSHLIB += -M $(MAPFILE)
+endif
+#
+# In Solaris 2.6 or earlier, -lrt is called -lposix4.
+#
+LIBRT_TEST=$(firstword $(sort 5.7 $(OS_RELEASE)))
+ifeq (5.7, $(LIBRT_TEST))
+LIBRT=-lrt
+else
+LIBRT=-lposix4
+endif
+
+ifdef USE_PTHREADS
+OS_LIBS = -lpthread -lthread ${LIBRT} -lsocket -lnsl -ldl -lc
+else
+ifdef LOCAL_THREADS_ONLY
+OS_LIBS = -lsocket -lnsl -ldl -lc
+else
+OS_LIBS = -lthread ${LIBRT} -lsocket -lnsl -ldl -lc
+endif # LOCAL_THREADS_ONLY
+endif # USE_PTHREADS
+ifeq ($(OS_TEST),sun4u)
+ifndef USE_64
+DSO_LDOPTS += -Wl,-f,\$$ORIGIN/cpu/\$$ISALIST/lib$(ULTRASPARC_LIBRARY)$(LIBRARY_VERSION).so
+endif
+endif # sun4u
+endif # 4.1.3_U1
+endif # SunOS
+
+ifeq ($(OS_ARCH), IRIX)
+ifeq ($(USE_PTHREADS), 1)
+OS_LIBS = -lpthread
+endif
+OS_LIBS += -lc
+endif
+
+ifeq ($(OS_ARCH),AIX)
+ifeq ($(CLASSIC_NSPR),1)
+ifeq ($(OS_RELEASE),4.1)
+OS_LIBS = -lsvld -lc
+else
+OS_LIBS = -ldl -lc
+endif
+else
+ifeq ($(OS_RELEASE),4.1)
+OS_LIBS = -lpthreads -lsvld -lC_r -lC -lc_r -lm /usr/lib/libc.a
+else
+OS_LIBS = -lpthreads -ldl -lC_r -lC -lc_r -lm /usr/lib/libc.a
+endif
+endif
+endif
+
+# On AIX, we override malloc in non-pthread versions. On AIX 4.2 or
+# above, this requires that we use the rtl-enabled version of libc.a.
+ifeq ($(OS_ARCH),AIX)
+ifneq (,$(filter-out 3.2 4.1,$(OS_RELEASE)))
+ifneq ($(USE_PTHREADS),1)
+BUILD_AIX_RTL_LIBC = 1
+AIX_RTL_LIBC = $(OBJDIR)/libc.a
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def
+ADD_TO_DEF_FILE = cat $(srcdir)/os2extra.def >> $(MAPFILE)
+GARBAGE += $(MAPFILE)
+MKSHLIB += $(MAPFILE)
+endif
+
+ifeq ($(OS_ARCH),OSF1)
+ifeq ($(USE_PTHREADS), 1)
+OS_LIBS = -lpthread -lrt
+endif
+ifneq ($(OS_RELEASE),V2.0)
+OS_LIBS += -lc_r
+endif
+endif
+
+ifeq ($(OS_ARCH),Linux)
+ifeq ($(USE_PTHREADS), 1)
+OS_LIBS = -lpthread -ldl
+else
+OS_LIBS = -ldl
+endif
+endif
+
+ifeq ($(OS_ARCH),HP-UX)
+ifeq ($(USE_PTHREADS), 1)
+ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
+OS_LIBS = -ldce
+else
+OS_LIBS = -lpthread -lrt
+endif
+endif
+ifeq ($(PTHREADS_USER), 1)
+OS_LIBS = -lpthread
+endif
+ifeq ($(basename $(OS_RELEASE)),A.09)
+OS_LIBS += -ldld -L/lib/pa1.1 -lm
+else
+OS_LIBS += -ldld -lm -lc
+endif
+endif
+
+ifeq ($(OS_ARCH),UNIXWARE)
+OS_LIBS = -lsocket -lc
+endif
+
+ifeq ($(OS_ARCH),NEWS-OS)
+OS_LIBS = -lsocket -lnsl -lgen -lresolv
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef NS_USE_GCC
+OS_LIBS = -ladvapi32 -lwsock32
+else
+OS_LIBS = advapi32.lib wsock32.lib
+endif
+endif
+
+ifeq ($(OS_TARGET),MacOSX)
+OS_LIBS = -framework CoreServices -framework CoreFoundation
+endif
+
+ifdef GC_LEAK_DETECTOR
+EXTRA_LIBS = -L$(dist_libdir) -lboehm
+endif
+
+EXTRA_LIBS += $(OS_LIBS)
+
+#
+# Define platform-dependent OBJS
+#
+
+OBJS = \
+ $(OBJDIR)/prvrsion.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prfdcach.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prmwait.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prmapopt.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/priometh.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prlayer.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prlog.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prmmap.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prpolevt.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prprf.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prscanf.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prstdio.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prcmon.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prrwlock.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prtpd.$(OBJ_SUFFIX) \
+ linking/$(OBJDIR)/prlink.$(OBJ_SUFFIX) \
+ malloc/$(OBJDIR)/prmem.$(OBJ_SUFFIX) \
+ md/$(OBJDIR)/prosdep.$(OBJ_SUFFIX) \
+ memory/$(OBJDIR)/prshm.$(OBJ_SUFFIX) \
+ memory/$(OBJDIR)/prshma.$(OBJ_SUFFIX) \
+ memory/$(OBJDIR)/prseg.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/pralarm.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/pratom.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prcountr.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prdtoa.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prenv.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prerr.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prerror.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prerrortable.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prinit.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prinrval.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/pripc.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prlog2.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prlong.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prnetdb.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prolock.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prrng.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prsystem.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prthinfo.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prtpool.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prtrace.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/prtime.$(OBJ_SUFFIX)
+
+# ilib now rejects empty objects
+ifneq ($(MOZ_OS2_TOOLS),VACPP)
+OBJS += malloc/$(OBJDIR)/prmalloc.$(OBJ_SUFFIX)
+endif
+
+ifdef USE_PTHREADS
+OBJS += \
+ pthreads/$(OBJDIR)/ptsynch.$(OBJ_SUFFIX) \
+ pthreads/$(OBJDIR)/ptio.$(OBJ_SUFFIX) \
+ pthreads/$(OBJDIR)/ptthread.$(OBJ_SUFFIX) \
+ pthreads/$(OBJDIR)/ptmisc.$(OBJ_SUFFIX)
+else
+OBJS += \
+ io/$(OBJDIR)/prdir.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prfile.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prio.$(OBJ_SUFFIX) \
+ io/$(OBJDIR)/prsocket.$(OBJ_SUFFIX) \
+ misc/$(OBJDIR)/pripcsem.$(OBJ_SUFFIX)
+
+ifndef USE_BTHREADS
+OBJS += \
+ threads/$(OBJDIR)/prcthr.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prdump.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prmon.$(OBJ_SUFFIX) \
+ threads/$(OBJDIR)/prsem.$(OBJ_SUFFIX) \
+ threads/combined/$(OBJDIR)/prucpu.$(OBJ_SUFFIX) \
+ threads/combined/$(OBJDIR)/prucv.$(OBJ_SUFFIX) \
+ threads/combined/$(OBJDIR)/prulock.$(OBJ_SUFFIX) \
+ threads/combined/$(OBJDIR)/prustack.$(OBJ_SUFFIX) \
+ threads/combined/$(OBJDIR)/pruthr.$(OBJ_SUFFIX)
+endif
+
+endif
+
+ifeq ($(USE_CPLUS), 1)
+OBJS += \
+ cplus/$(OBJDIR)/rcbase.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rccv.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rcfileio.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rcinrval.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rcio.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rclock.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rcnetdb.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rcnetio.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rcthread.$(OBJ_SUFFIX) \
+ cplus/$(OBJDIR)/rctime.$(OBJ_SUFFIX)
+endif
+
+ifdef GC_LEAK_DETECTOR
+OBJS += memory/$(OBJDIR)/prgcleak.$(OBJ_SUFFIX)
+endif
+
+ifeq ($(OS_ARCH), WINNT)
+ifdef NS_USE_GCC
+DLLBASE=-Wl,--image-base -Wl,0x30000000
+else
+DLLBASE=/BASE:0x30000000
+endif # GCC
+RES=$(OBJDIR)/nspr.res
+RESNAME=nspr.rc
+endif # WINNT
+
+include $(srcdir)/md/$(PR_MD_ARCH_DIR)/objs.mk
+ifdef USE_BTHREADS
+include $(srcdir)/bthreads/objs.mk
+endif
+
+LIBRARY_NAME = nspr
+LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+
+RELEASE_LIBS = $(TARGETS)
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(BUILD_AIX_RTL_LIBC),1)
+TARGETS += $(AIX_RTL_LIBC)
+# XXX is this a shared library?
+endif
+
+#
+# Version information generation (begin)
+#
+ECHO = echo
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+TINC = $(OBJDIR)/_pr_bld.h
+
+ifeq ($(OS_TARGET),OS2)
+PROD = nspr$(MOD_MAJOR_VERSION).$(DLL_SUFFIX)
+else
+PROD = $(notdir $(SHARED_LIBRARY))
+endif
+
+NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now
+SH_DATE = $(shell date "+%Y-%m-%d %T")
+SH_NOW = $(shell $(NOW))
+
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ SUF = i64
+else
+ SUF = LL
+endif
+
+DEFINES += -D_NSPR_BUILD_
+
+GARBAGE += $(TINC)
+
+$(TINC):
+ @$(MAKE_OBJDIR)
+ @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC)
+ @if test ! -z "$(SH_NOW)"; then \
+ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \
+ else \
+ true; \
+ fi
+ @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC)
+
+
+$(OBJDIR)/prvrsion.$(OBJ_SUFFIX): prvrsion.c $(TINC)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ifeq ($(MOZ_OS2_TOOLS), VACPP)
+ $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $<
+else
+ $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $<
+endif
+endif
+#
+# Version information generation (end)
+#
+
+
+#
+# The Client build wants the shared libraries in $(dist_bindir)
+# so we also install them there.
+#
+
+export:: $(TARGETS)
+ $(INSTALL) -m 444 $(TARGETS) $(dist_libdir)
+ifdef SHARED_LIBRARY
+ifeq ($(OS_ARCH),HP-UX)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir)
+ $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir)
+else
+ $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir)
+endif
+endif
+ifeq ($(MOZ_BITS),16)
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/lib
+ $(INSTALL) -m 444 $(TARGETS) $(MOZ_DIST)/bin
+endif
+
+ifeq ($(BUILD_AIX_RTL_LIBC),1)
+$(AIX_RTL_LIBC): /usr/ccs/lib/libc.a
+ rtl_enable -o $@ $<
+endif
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/Makefile.in
new file mode 100644
index 00000000..285f217d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/Makefile.in
@@ -0,0 +1,63 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+include $(srcdir)/bsrcs.mk
+CSRCS += $(BTCSRCS)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_NSPR_BUILD_
+
+export:: $(TARGETS)
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/bsrcs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/bsrcs.mk
new file mode 100644
index 00000000..af01bb7d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/bsrcs.mk
@@ -0,0 +1,49 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+# this file lists the source files to be compiled (used in Makefile) and
+# then enumerated as object files (in objs.mk) for inclusion in the NSPR
+# shared library
+
+BTCSRCS = \
+ btthread.c \
+ btlocks.c \
+ btcvar.c \
+ btmon.c \
+ btsem.c \
+ btmisc.c \
+ $(NULL)
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btcvar.c b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btcvar.c
new file mode 100644
index 00000000..841ec960
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btcvar.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Create a new condition variable.
+**
+** "lock" is the lock used to protect the condition variable.
+**
+** Condition variables are synchronization objects that threads can use
+** to wait for some condition to occur.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low. In such cases, a NULL will be returned.
+*/
+PR_IMPLEMENT(PRCondVar*)
+ PR_NewCondVar (PRLock *lock)
+{
+ PRCondVar *cv = PR_NEW( PRCondVar );
+ PR_ASSERT( NULL != lock );
+ if( NULL != cv )
+ {
+ cv->lock = lock;
+ cv->sem = create_sem(0, "CVSem");
+ cv->handshakeSem = create_sem(0, "CVHandshake");
+ cv->signalSem = create_sem( 0, "CVSignal");
+ cv->signalBenCount = 0;
+ cv->ns = cv->nw = 0;
+ PR_ASSERT( cv->sem >= B_NO_ERROR );
+ PR_ASSERT( cv->handshakeSem >= B_NO_ERROR );
+ PR_ASSERT( cv->signalSem >= B_NO_ERROR );
+ }
+ return cv;
+} /* PR_NewCondVar */
+
+/*
+** Destroy a condition variable. There must be no thread
+** waiting on the condvar. The caller is responsible for guaranteeing
+** that the condvar is no longer in use.
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyCondVar (PRCondVar *cvar)
+{
+ status_t result = delete_sem( cvar->sem );
+ PR_ASSERT( result == B_NO_ERROR );
+
+ result = delete_sem( cvar->handshakeSem );
+ PR_ASSERT( result == B_NO_ERROR );
+
+ result = delete_sem( cvar->signalSem );
+ PR_ASSERT( result == B_NO_ERROR );
+
+ PR_DELETE( cvar );
+}
+
+/*
+** The thread that waits on a condition is blocked in a "waiting on
+** condition" state until another thread notifies the condition or a
+** caller specified amount of time expires. The lock associated with
+** the condition variable will be released, which must have be held
+** prior to the call to wait.
+**
+** Logically a notified thread is moved from the "waiting on condition"
+** state and made "ready." When scheduled, it will attempt to reacquire
+** the lock that it held when wait was called.
+**
+** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and
+** PR_INTERVAL_NO_WAIT. The former value requires that a condition be
+** notified (or the thread interrupted) before it will resume from the
+** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect
+** is to release the lock, possibly causing a rescheduling within the
+** runtime, then immediately attempting to reacquire the lock and resume.
+**
+** Any other value for timeout will cause the thread to be rescheduled
+** either due to explicit notification or an expired interval. The latter
+** must be determined by treating time as one part of the monitored data
+** being protected by the lock and tested explicitly for an expired
+** interval.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable or the thread was interrupted (PR_Interrupt()).
+** The particular reason can be extracted with PR_GetError().
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout)
+{
+ status_t err;
+ if( timeout == PR_INTERVAL_NO_WAIT )
+ {
+ PR_Unlock( cvar->lock );
+ PR_Lock( cvar->lock );
+ return PR_SUCCESS;
+ }
+
+ if( atomic_add( &cvar->signalBenCount, 1 ) > 0 )
+ {
+ if (acquire_sem(cvar->signalSem) == B_INTERRUPTED)
+ {
+ atomic_add( &cvar->signalBenCount, -1 );
+ return PR_FAILURE;
+ }
+ }
+ cvar->nw += 1;
+ if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
+ {
+ release_sem(cvar->signalSem);
+ }
+
+ PR_Unlock( cvar->lock );
+ if( timeout==PR_INTERVAL_NO_TIMEOUT )
+ {
+ err = acquire_sem(cvar->sem);
+ }
+ else
+ {
+ err = acquire_sem_etc(cvar->sem, 1, B_RELATIVE_TIMEOUT, PR_IntervalToMicroseconds(timeout) );
+ }
+
+ if( atomic_add( &cvar->signalBenCount, 1 ) > 0 )
+ {
+ while (acquire_sem(cvar->signalSem) == B_INTERRUPTED);
+ }
+
+ if (cvar->ns > 0)
+ {
+ release_sem(cvar->handshakeSem);
+ cvar->ns -= 1;
+ }
+ cvar->nw -= 1;
+ if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
+ {
+ release_sem(cvar->signalSem);
+ }
+
+ PR_Lock( cvar->lock );
+ if(err!=B_NO_ERROR)
+ {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+/*
+** Notify ONE thread that is currently waiting on 'cvar'. Which thread is
+** dependent on the implementation of the runtime. Common sense would dictate
+** that all threads waiting on a single condition have identical semantics,
+** therefore which one gets notified is not significant.
+**
+** The calling thead must hold the lock that protects the condition, as
+** well as the invariants that are tightly bound to the condition, when
+** notify is called.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_NotifyCondVar (PRCondVar *cvar)
+{
+ status_t err ;
+ if( atomic_add( &cvar->signalBenCount, 1 ) > 0 )
+ {
+ if (acquire_sem(cvar->signalSem) == B_INTERRUPTED)
+ {
+ atomic_add( &cvar->signalBenCount, -1 );
+ return PR_FAILURE;
+ }
+ }
+ if (cvar->nw > cvar->ns)
+ {
+ cvar->ns += 1;
+ release_sem(cvar->sem);
+ if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
+ {
+ release_sem(cvar->signalSem);
+ }
+
+ while (acquire_sem(cvar->handshakeSem) == B_INTERRUPTED)
+ {
+ err = B_INTERRUPTED;
+ }
+ }
+ else
+ {
+ if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
+ {
+ release_sem(cvar->signalSem);
+ }
+ }
+ return PR_SUCCESS;
+}
+
+/*
+** Notify all of the threads waiting on the condition variable. The order
+** that the threads are notified is indeterminant. The lock that protects
+** the condition must be held.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_NotifyAllCondVar (PRCondVar *cvar)
+{
+ int32 handshakes;
+ status_t err = B_OK;
+
+ if( atomic_add( &cvar->signalBenCount, 1 ) > 0 )
+ {
+ if (acquire_sem(cvar->signalSem) == B_INTERRUPTED)
+ {
+ atomic_add( &cvar->signalBenCount, -1 );
+ return PR_FAILURE;
+ }
+ }
+
+ if (cvar->nw > cvar->ns)
+ {
+ handshakes = cvar->nw - cvar->ns;
+ cvar->ns = cvar->nw;
+ release_sem_etc(cvar->sem, handshakes, 0);
+ if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
+ {
+ release_sem(cvar->signalSem);
+ }
+
+ while (acquire_sem_etc(cvar->handshakeSem, handshakes, 0, 0) == B_INTERRUPTED)
+ {
+ err = B_INTERRUPTED;
+ }
+ }
+ else
+ {
+ if( atomic_add( &cvar->signalBenCount, -1 ) > 1 )
+ {
+ release_sem(cvar->signalSem);
+ }
+ }
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btlocks.c b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btlocks.c
new file mode 100644
index 00000000..c5b62860
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btlocks.c
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: btlocks.c
+** Description: Implemenation for thread locks using bthreads
+** Exports: prlock.h
+*/
+
+#include "primpl.h"
+
+#include <string.h>
+#include <sys/time.h>
+
+void
+_PR_InitLocks (void)
+{
+}
+
+PR_IMPLEMENT(PRLock*)
+ PR_NewLock (void)
+{
+ PRLock *lock;
+ status_t semresult;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ lock = PR_NEWZAP(PRLock);
+ if (lock != NULL) {
+
+ lock->benaphoreCount = 0;
+ lock->semaphoreID = create_sem( 0, "nsprLockSem" );
+ if( lock->semaphoreID < B_NO_ERROR ) {
+
+ PR_DELETE( lock );
+ lock = NULL;
+ }
+ }
+
+ return lock;
+}
+
+PR_IMPLEMENT(void)
+ PR_DestroyLock (PRLock* lock)
+{
+ status_t result;
+
+ PR_ASSERT(NULL != lock);
+ result = delete_sem(lock->semaphoreID);
+ PR_ASSERT(result == B_NO_ERROR);
+ PR_DELETE(lock);
+}
+
+PR_IMPLEMENT(void)
+ PR_Lock (PRLock* lock)
+{
+ PR_ASSERT(lock != NULL);
+
+ if( atomic_add( &lock->benaphoreCount, 1 ) > 0 ) {
+
+ if( acquire_sem(lock->semaphoreID ) != B_NO_ERROR ) {
+
+ atomic_add( &lock->benaphoreCount, -1 );
+ return;
+ }
+ }
+
+ lock->owner = find_thread( NULL );
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_Unlock (PRLock* lock)
+{
+ PR_ASSERT(lock != NULL);
+ lock->owner = NULL;
+ if( atomic_add( &lock->benaphoreCount, -1 ) > 1 ) {
+
+ release_sem( lock->semaphoreID );
+ }
+
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmisc.c b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmisc.c
new file mode 100644
index 00000000..2d678a9d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmisc.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <stdio.h>
+
+// void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
+// void _MD_StartInterrupts(void) {PT_LOG("_MD_StartInterrupts")}
+
+/* this is a total hack.. */
+
+struct protoent* getprotobyname(const char* name)
+{
+ return 0;
+}
+
+struct protoent* getprotobynumber(int number)
+{
+ return 0;
+}
+
+/* this is needed by prinit for some reason */
+void
+_PR_InitStacks (void)
+{
+}
+
+/* this is needed by prinit for some reason */
+void
+_PR_InitTPD (void)
+{
+}
+
+/*
+** Create extra virtual processor threads. Generally used with MP systems.
+*/
+PR_IMPLEMENT(void)
+ PR_SetConcurrency (PRUintn numCPUs)
+{
+}
+
+/*
+** Set thread recycle mode to on (1) or off (0)
+*/
+PR_IMPLEMENT(void)
+ PR_SetThreadRecycleMode (PRUint32 flag)
+{
+}
+
+/*
+** Get context registers, return with error for now.
+*/
+
+PR_IMPLEMENT(PRWord *)
+_MD_HomeGCRegisters( PRThread *t, int isCurrent, int *np )
+{
+ return 0;
+}
+
+PR_IMPLEMENT(void *)
+PR_GetSP( PRThread *t )
+{
+ return 0;
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_EnumerateThreads( PREnumerator func, void *arg )
+{
+ return PR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmon.c b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmon.c
new file mode 100644
index 00000000..f14d1379
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btmon.c
@@ -0,0 +1,219 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Create a new monitor. Monitors are re-entrant locks with a single built-in
+** condition variable.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low.
+*/
+PR_IMPLEMENT(PRMonitor*)
+ PR_NewMonitor (void)
+{
+ PRMonitor *mon;
+ PRCondVar *cvar;
+ PRLock *lock;
+
+ mon = PR_NEWZAP( PRMonitor );
+ if( mon )
+ {
+ lock = PR_NewLock();
+ if( !lock )
+ {
+ PR_DELETE( mon );
+ return( 0 );
+ }
+
+ cvar = PR_NewCondVar( lock );
+ if( !cvar )
+ {
+ PR_DestroyLock( lock );
+ PR_DELETE( mon );
+ return( 0 );
+ }
+
+ mon->cvar = cvar;
+ mon->name = NULL;
+ }
+
+ return( mon );
+}
+
+PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
+{
+ PRMonitor* mon = PR_NewMonitor();
+ if( mon )
+ {
+ mon->name = name;
+ }
+ return mon;
+}
+
+/*
+** Destroy a monitor. The caller is responsible for guaranteeing that the
+** monitor is no longer in use. There must be no thread waiting on the
+** monitor's condition variable and that the lock is not held.
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyMonitor (PRMonitor *mon)
+{
+ PR_DestroyLock( mon->cvar->lock );
+ PR_DestroyCondVar( mon->cvar );
+ PR_DELETE( mon );
+}
+
+/*
+** Enter the lock associated with the monitor. If the calling thread currently
+** is in the monitor, the call to enter will silently succeed. In either case,
+** it will increment the entry count by one.
+*/
+PR_IMPLEMENT(void)
+ PR_EnterMonitor (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner == find_thread( NULL ) )
+ {
+ mon->entryCount++;
+
+ } else
+ {
+ PR_Lock( mon->cvar->lock );
+ mon->entryCount = 1;
+ }
+}
+
+/*
+** Decrement the entry count associated with the monitor. If the decremented
+** entry count is zero, the monitor is exited. Returns PR_FAILURE if the
+** calling thread has not entered the monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_ExitMonitor (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner != find_thread( NULL ) )
+ {
+ return( PR_FAILURE );
+ }
+ if( --mon->entryCount == 0 )
+ {
+ return( PR_Unlock( mon->cvar->lock ) );
+ }
+ return( PR_SUCCESS );
+}
+
+/*
+** Wait for a notify on the monitor's condition variable. Sleep for "ticks"
+** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is
+** indefinite).
+**
+** While the thread is waiting it exits the monitor (as if it called
+** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When
+** the wait has finished the thread regains control of the monitors lock
+** with the same entry count as before the wait began.
+**
+** The thread waiting on the monitor will be resumed when the monitor is
+** notified (assuming the thread is the next in line to receive the
+** notify) or when the "ticks" timeout elapses.
+**
+** Returns PR_FAILURE if the caller has not entered the monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_Wait (PRMonitor *mon, PRIntervalTime ticks)
+{
+ PRUint32 entryCount;
+ PRUintn status;
+ PRThread *meThread;
+ thread_id me = find_thread( NULL );
+ meThread = PR_GetCurrentThread();
+
+ if( mon->cvar->lock->owner != me ) return( PR_FAILURE );
+
+ entryCount = mon->entryCount;
+ mon->entryCount = 0;
+
+ status = PR_WaitCondVar( mon->cvar, ticks );
+
+ mon->entryCount = entryCount;
+
+ return( status );
+}
+
+/*
+** Notify a thread waiting on the monitor's condition variable. If a thread
+** is waiting on the condition variable (using PR_Wait) then it is awakened
+** and attempts to reenter the monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_Notify (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner != find_thread( NULL ) )
+ {
+ return( PR_FAILURE );
+ }
+
+ PR_NotifyCondVar( mon->cvar );
+ return( PR_SUCCESS );
+}
+
+/*
+** Notify all of the threads waiting on the monitor's condition variable.
+** All of threads waiting on the condition are scheduled to reenter the
+** monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_NotifyAll (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner != find_thread( NULL ) )
+ {
+ return( PR_FAILURE );
+ }
+
+ PR_NotifyAllCondVar( mon->cvar );
+ return( PR_SUCCESS );
+}
+
+PR_IMPLEMENT(PRIntn)
+ PR_GetMonitorEntryCount(PRMonitor *mon)
+{
+ return( mon->entryCount );
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btsem.c b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btsem.c
new file mode 100644
index 00000000..c9f2e641
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btsem.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Create a new semaphore object.
+*/
+PR_IMPLEMENT(PRSemaphore*)
+ PR_NewSem (PRUintn value)
+{
+ PRSemaphore *semaphore;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ semaphore = PR_NEWZAP(PRSemaphore);
+ if (NULL != semaphore) {
+ if ((semaphore->sem = create_sem(value, "nspr_sem")) < B_NO_ERROR)
+ return NULL;
+ else
+ return semaphore;
+ }
+ return NULL;
+}
+
+/*
+** Destroy the given semaphore object.
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroySem (PRSemaphore *sem)
+{
+ status_t result;
+
+ PR_ASSERT(sem != NULL);
+ result = delete_sem(sem->sem);
+ PR_ASSERT(result == B_NO_ERROR);
+ PR_DELETE(sem);
+}
+
+/*
+** Wait on a Semaphore.
+**
+** This routine allows a calling thread to wait or proceed depending upon
+** the state of the semahore sem. The thread can proceed only if the
+** counter value of the semaphore sem is currently greater than 0. If the
+** value of semaphore sem is positive, it is decremented by one and the
+** routine returns immediately allowing the calling thread to continue. If
+** the value of semaphore sem is 0, the calling thread blocks awaiting the
+** semaphore to be released by another thread.
+**
+** This routine can return PR_PENDING_INTERRUPT if the waiting thread
+** has been interrupted.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_WaitSem (PRSemaphore *sem)
+{
+ PR_ASSERT(sem != NULL);
+ if (acquire_sem(sem->sem) == B_NO_ERROR)
+ return PR_SUCCESS;
+ else
+ return PR_FAILURE;
+}
+
+/*
+** This routine increments the counter value of the semaphore. If other
+** threads are blocked for the semaphore, then the scheduler will
+** determine which ONE thread will be unblocked.
+*/
+PR_IMPLEMENT(void)
+ PR_PostSem (PRSemaphore *sem)
+{
+ status_t result;
+
+ PR_ASSERT(sem != NULL);
+ result = release_sem(sem->sem);
+ PR_ASSERT(result == B_NO_ERROR);
+}
+
+/*
+** Returns the value of the semaphore referenced by sem without affecting
+** the state of the semaphore. The value represents the semaphore value
+** at the time of the call, but may not be the actual value when the
+** caller inspects it.
+*/
+PR_IMPLEMENT(PRUintn)
+ PR_GetValueSem (PRSemaphore *sem)
+{
+ sem_info info;
+
+ PR_ASSERT(sem != NULL);
+ get_sem_info(sem->sem, &info);
+ return info.count;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btthread.c b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btthread.c
new file mode 100644
index 00000000..814ede29
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/btthread.c
@@ -0,0 +1,694 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <kernel/OS.h>
+#include <support/TLS.h>
+
+#include "prlog.h"
+#include "primpl.h"
+#include "prcvar.h"
+#include "prpdce.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+/* values for PRThread.state */
+#define BT_THREAD_PRIMORD 0x01 /* this is the primordial thread */
+#define BT_THREAD_SYSTEM 0x02 /* this is a system thread */
+#define BT_THREAD_JOINABLE 0x04 /* this is a joinable thread */
+
+struct _BT_Bookeeping
+{
+ PRLock *ml; /* a lock to protect ourselves */
+ sem_id cleanUpSem; /* the primoridal thread will block on this
+ sem while waiting for the user threads */
+ PRInt32 threadCount; /* user thred count */
+
+} bt_book = { NULL, B_ERROR, 0 };
+
+
+#define BT_TPD_LIMIT 128 /* number of TPD slots we'll provide (arbitrary) */
+
+/* these will be used to map an index returned by PR_NewThreadPrivateIndex()
+ to the corresponding beos native TLS slot number, and to the destructor
+ for that slot - note that, because it is allocated globally, this data
+ will be automatically zeroed for us when the program begins */
+static int32 tpd_beosTLSSlots[BT_TPD_LIMIT];
+static PRThreadPrivateDTOR tpd_dtors[BT_TPD_LIMIT];
+
+static vint32 tpd_slotsUsed=0; /* number of currently-allocated TPD slots */
+static int32 tls_prThreadSlot; /* TLS slot in which PRThread will be stored */
+
+/* this mutex will be used to synchronize access to every
+ PRThread.md.joinSem and PRThread.md.is_joining (we could
+ actually allocate one per thread, but that seems a bit excessive,
+ especially considering that there will probably be little
+ contention, PR_JoinThread() is allowed to block anyway, and the code
+ protected by the mutex is short/fast) */
+static PRLock *joinSemLock;
+
+static PRUint32 _bt_MapNSPRToNativePriority( PRThreadPriority priority );
+static PRThreadPriority _bt_MapNativeToNSPRPriority( PRUint32 priority );
+static void _bt_CleanupThread(void *arg);
+static PRThread *_bt_AttachThread();
+
+void
+_PR_InitThreads (PRThreadType type, PRThreadPriority priority,
+ PRUintn maxPTDs)
+{
+ PRThread *primordialThread;
+ PRUint32 beThreadPriority;
+
+ /* allocate joinSem mutex */
+ joinSemLock = PR_NewLock();
+ if (joinSemLock == NULL)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return;
+ }
+
+ /*
+ ** Create and initialize NSPR structure for our primordial thread.
+ */
+
+ primordialThread = PR_NEWZAP(PRThread);
+ if( NULL == primordialThread )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ primordialThread->md.joinSem = B_ERROR;
+
+ /*
+ ** Set the priority to the desired level.
+ */
+
+ beThreadPriority = _bt_MapNSPRToNativePriority( priority );
+
+ set_thread_priority( find_thread( NULL ), beThreadPriority );
+
+ primordialThread->priority = priority;
+
+
+ /* set the thread's state - note that the thread is not joinable */
+ primordialThread->state |= BT_THREAD_PRIMORD;
+ if (type == PR_SYSTEM_THREAD)
+ primordialThread->state |= BT_THREAD_SYSTEM;
+
+ /*
+ ** Allocate a TLS slot for the PRThread structure (just using
+ ** native TLS, as opposed to NSPR TPD, will make PR_GetCurrentThread()
+ ** somewhat faster, and will leave one more TPD slot for our client)
+ */
+
+ tls_prThreadSlot = tls_allocate();
+
+ /*
+ ** Stuff our new PRThread structure into our thread specific
+ ** slot.
+ */
+
+ tls_set(tls_prThreadSlot, primordialThread);
+
+ /* allocate lock for bt_book */
+ bt_book.ml = PR_NewLock();
+ if( NULL == bt_book.ml )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+}
+
+PRUint32
+_bt_MapNSPRToNativePriority( PRThreadPriority priority )
+ {
+ switch( priority )
+ {
+ case PR_PRIORITY_LOW: return( B_LOW_PRIORITY );
+ case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );
+ case PR_PRIORITY_HIGH: return( B_DISPLAY_PRIORITY );
+ case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );
+ default: return( B_NORMAL_PRIORITY );
+ }
+}
+
+PRThreadPriority
+_bt_MapNativeToNSPRPriority(PRUint32 priority)
+ {
+ if (priority < B_NORMAL_PRIORITY)
+ return PR_PRIORITY_LOW;
+ if (priority < B_DISPLAY_PRIORITY)
+ return PR_PRIORITY_NORMAL;
+ if (priority < B_URGENT_DISPLAY_PRIORITY)
+ return PR_PRIORITY_HIGH;
+ return PR_PRIORITY_URGENT;
+}
+
+PRUint32
+_bt_mapNativeToNSPRPriority( int32 priority )
+{
+ switch( priority )
+ {
+ case PR_PRIORITY_LOW: return( B_LOW_PRIORITY );
+ case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );
+ case PR_PRIORITY_HIGH: return( B_DISPLAY_PRIORITY );
+ case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );
+ default: return( B_NORMAL_PRIORITY );
+ }
+}
+
+/* This method is called by all NSPR threads as they exit */
+void _bt_CleanupThread(void *arg)
+{
+ PRThread *me = PR_GetCurrentThread();
+ int32 i;
+
+ /* first, clean up all thread-private data */
+ for (i = 0; i < tpd_slotsUsed; i++)
+ {
+ void *oldValue = tls_get(tpd_beosTLSSlots[i]);
+ if ( oldValue != NULL && tpd_dtors[i] != NULL )
+ (*tpd_dtors[i])(oldValue);
+ }
+
+ /* if this thread is joinable, wait for someone to join it */
+ if (me->state & BT_THREAD_JOINABLE)
+ {
+ /* protect access to our joinSem */
+ PR_Lock(joinSemLock);
+
+ if (me->md.is_joining)
+ {
+ /* someone is already waiting to join us (they've
+ allocated a joinSem for us) - let them know we're
+ ready */
+ delete_sem(me->md.joinSem);
+
+ PR_Unlock(joinSemLock);
+
+ }
+ else
+ {
+ /* noone is currently waiting for our demise - it
+ is our responsibility to allocate the joinSem
+ and block on it */
+ me->md.joinSem = create_sem(0, "join sem");
+
+ /* we're done accessing our joinSem */
+ PR_Unlock(joinSemLock);
+
+ /* wait for someone to join us */
+ while (acquire_sem(me->md.joinSem) == B_INTERRUPTED);
+ }
+ }
+
+ /* if this is a user thread, we must update our books */
+ if ((me->state & BT_THREAD_SYSTEM) == 0)
+ {
+ /* synchronize access to bt_book */
+ PR_Lock( bt_book.ml );
+
+ /* decrement the number of currently-alive user threads */
+ bt_book.threadCount--;
+
+ if (bt_book.threadCount == 0 && bt_book.cleanUpSem != B_ERROR) {
+ /* we are the last user thread, and the primordial thread is
+ blocked in PR_Cleanup() waiting for us to finish - notify
+ it */
+ delete_sem(bt_book.cleanUpSem);
+ }
+
+ PR_Unlock( bt_book.ml );
+ }
+
+ /* finally, delete this thread's PRThread */
+ PR_DELETE(me);
+}
+
+/**
+ * This is a wrapper that all threads invoke that allows us to set some
+ * things up prior to a thread's invocation and clean up after a thread has
+ * exited.
+ */
+static void*
+_bt_root (void* arg)
+ {
+ PRThread *thred = (PRThread*)arg;
+ PRIntn rv;
+ void *privData;
+ status_t result;
+ int i;
+
+ /* save our PRThread object into our TLS */
+ tls_set(tls_prThreadSlot, thred);
+
+ thred->startFunc(thred->arg); /* run the dang thing */
+
+ /* clean up */
+ _bt_CleanupThread(NULL);
+
+ return 0;
+}
+
+PR_IMPLEMENT(PRThread*)
+ PR_CreateThread (PRThreadType type, void (*start)(void* arg), void* arg,
+ PRThreadPriority priority, PRThreadScope scope,
+ PRThreadState state, PRUint32 stackSize)
+{
+ PRUint32 bePriority;
+
+ PRThread* thred;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ thred = PR_NEWZAP(PRThread);
+ if (thred == NULL)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ thred->md.joinSem = B_ERROR;
+
+ thred->arg = arg;
+ thred->startFunc = start;
+ thred->priority = priority;
+
+ if( state == PR_JOINABLE_THREAD )
+ {
+ thred->state |= BT_THREAD_JOINABLE;
+ }
+
+ /* keep some books */
+
+ PR_Lock( bt_book.ml );
+
+ if (type == PR_USER_THREAD)
+ {
+ bt_book.threadCount++;
+ }
+
+ PR_Unlock( bt_book.ml );
+
+ bePriority = _bt_MapNSPRToNativePriority( priority );
+
+ thred->md.tid = spawn_thread((thread_func)_bt_root, "moz-thread",
+ bePriority, thred);
+ if (thred->md.tid < B_OK) {
+ PR_SetError(PR_UNKNOWN_ERROR, thred->md.tid);
+ PR_DELETE(thred);
+ return NULL;
+ }
+
+ if (resume_thread(thred->md.tid) < B_OK) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ PR_DELETE(thred);
+ return NULL;
+ }
+
+ return thred;
+ }
+
+PR_IMPLEMENT(PRThread*)
+ PR_AttachThread(PRThreadType type, PRThreadPriority priority,
+ PRThreadStack *stack)
+{
+ /* PR_GetCurrentThread() will attach a thread if necessary */
+ return PR_GetCurrentThread();
+}
+
+PR_IMPLEMENT(void)
+ PR_DetachThread()
+{
+ /* we don't support detaching */
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_JoinThread (PRThread* thred)
+{
+ status_t eval, status;
+
+ PR_ASSERT(thred != NULL);
+
+ if ((thred->state & BT_THREAD_JOINABLE) == 0)
+ {
+ PR_SetError( PR_INVALID_ARGUMENT_ERROR, 0 );
+ return( PR_FAILURE );
+ }
+
+ /* synchronize access to the thread's joinSem */
+ PR_Lock(joinSemLock);
+
+ if (thred->md.is_joining)
+ {
+ /* another thread is already waiting to join the specified
+ thread - we must fail */
+ PR_Unlock(joinSemLock);
+ return PR_FAILURE;
+ }
+
+ /* let others know we are waiting to join */
+ thred->md.is_joining = PR_TRUE;
+
+ if (thred->md.joinSem == B_ERROR)
+ {
+ /* the thread hasn't finished yet - it is our responsibility to
+ allocate a joinSem and wait on it */
+ thred->md.joinSem = create_sem(0, "join sem");
+
+ /* we're done changing the joinSem now */
+ PR_Unlock(joinSemLock);
+
+ /* wait for the thread to finish */
+ while (acquire_sem(thred->md.joinSem) == B_INTERRUPTED);
+
+ }
+ else
+ {
+ /* the thread has already finished, and has allocated the
+ joinSem itself - let it know it can finally die */
+ delete_sem(thred->md.joinSem);
+
+ PR_Unlock(joinSemLock);
+ }
+
+ /* make sure the thread is dead */
+ wait_for_thread(thred->md.tid, &eval);
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRThread*)
+ PR_GetCurrentThread ()
+{
+ PRThread* thred;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ thred = (PRThread *)tls_get( tls_prThreadSlot);
+ if (thred == NULL)
+ {
+ /* this thread doesn't have a PRThread structure (it must be
+ a native thread not created by the NSPR) - assimilate it */
+ thred = _bt_AttachThread();
+ }
+ PR_ASSERT(NULL != thred);
+
+ return thred;
+}
+
+PR_IMPLEMENT(PRThreadScope)
+ PR_GetThreadScope (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return PR_GLOBAL_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadType)
+ PR_GetThreadType (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return (thred->state & BT_THREAD_SYSTEM) ?
+ PR_SYSTEM_THREAD : PR_USER_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadState)
+ PR_GetThreadState (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return (thred->state & BT_THREAD_JOINABLE)?
+ PR_JOINABLE_THREAD: PR_UNJOINABLE_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadPriority)
+ PR_GetThreadPriority (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return thred->priority;
+} /* PR_GetThreadPriority */
+
+PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred,
+ PRThreadPriority newPri)
+{
+ PRUint32 bePriority;
+
+ PR_ASSERT( thred != NULL );
+
+ thred->priority = newPri;
+ bePriority = _bt_MapNSPRToNativePriority( newPri );
+ set_thread_priority( thred->md.tid, bePriority );
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_NewThreadPrivateIndex (PRUintn* newIndex,
+ PRThreadPrivateDTOR destructor)
+{
+ int32 index;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* reserve the next available tpd slot */
+ index = atomic_add( &tpd_slotsUsed, 1 );
+ if (index >= BT_TPD_LIMIT)
+ {
+ /* no slots left - decrement value, then fail */
+ atomic_add( &tpd_slotsUsed, -1 );
+ PR_SetError( PR_TPD_RANGE_ERROR, 0 );
+ return( PR_FAILURE );
+ }
+
+ /* allocate a beos-native TLS slot for this index (the new slot
+ automatically contains NULL) */
+ tpd_beosTLSSlots[index] = tls_allocate();
+
+ /* remember the destructor */
+ tpd_dtors[index] = destructor;
+
+ *newIndex = (PRUintn)index;
+
+ return( PR_SUCCESS );
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_SetThreadPrivate (PRUintn index, void* priv)
+{
+ void *oldValue;
+
+ /*
+ ** Sanity checking
+ */
+
+ if(index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT)
+ {
+ PR_SetError( PR_TPD_RANGE_ERROR, 0 );
+ return( PR_FAILURE );
+ }
+
+ /* if the old value isn't NULL, and the dtor for this slot isn't
+ NULL, we must destroy the data */
+ oldValue = tls_get(tpd_beosTLSSlots[index]);
+ if (oldValue != NULL && tpd_dtors[index] != NULL)
+ (*tpd_dtors[index])(oldValue);
+
+ /* save new value */
+ tls_set(tpd_beosTLSSlots[index], priv);
+
+ return( PR_SUCCESS );
+ }
+
+PR_IMPLEMENT(void*)
+ PR_GetThreadPrivate (PRUintn index)
+{
+ /* make sure the index is valid */
+ if (index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT)
+ {
+ PR_SetError( PR_TPD_RANGE_ERROR, 0 );
+ return NULL;
+ }
+
+ /* return the value */
+ return tls_get( tpd_beosTLSSlots[index] );
+ }
+
+
+PR_IMPLEMENT(PRStatus)
+ PR_Interrupt (PRThread* thred)
+{
+ PRIntn rv;
+
+ PR_ASSERT(thred != NULL);
+
+ /*
+ ** there seems to be a bug in beos R5 in which calling
+ ** resume_thread() on a blocked thread returns B_OK instead
+ ** of B_BAD_THREAD_STATE (beos bug #20000422-19095). as such,
+ ** to interrupt a thread, we will simply suspend then resume it
+ ** (no longer call resume_thread(), check for B_BAD_THREAD_STATE,
+ ** the suspend/resume to wake up a blocked thread). this wakes
+ ** up blocked threads properly, and doesn't hurt unblocked threads
+ ** (they simply get stopped then re-started immediately)
+ */
+
+ rv = suspend_thread( thred->md.tid );
+ if( rv != B_NO_ERROR )
+ {
+ /* this doesn't appear to be a valid thread_id */
+ PR_SetError( PR_UNKNOWN_ERROR, rv );
+ return PR_FAILURE;
+ }
+
+ rv = resume_thread( thred->md.tid );
+ if( rv != B_NO_ERROR )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR, rv );
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(void)
+ PR_ClearInterrupt ()
+{
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_Yield ()
+{
+ /* we just sleep for long enough to cause a reschedule (100
+ microseconds) */
+ snooze(100);
+}
+
+#define BT_MILLION 1000000UL
+
+PR_IMPLEMENT(PRStatus)
+ PR_Sleep (PRIntervalTime ticks)
+{
+ bigtime_t tps;
+ status_t status;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ tps = PR_IntervalToMicroseconds( ticks );
+
+ status = snooze(tps);
+ if (status == B_NO_ERROR) return PR_SUCCESS;
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, status);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_Cleanup ()
+{
+ PRThread *me = PR_CurrentThread();
+
+ PR_ASSERT(me->state & BT_THREAD_PRIMORD);
+ if ((me->state & BT_THREAD_PRIMORD) == 0) {
+ return PR_FAILURE;
+ }
+
+ PR_Lock( bt_book.ml );
+
+ if (bt_book.threadCount != 0)
+ {
+ /* we'll have to wait for some threads to finish - create a
+ sem to block on */
+ bt_book.cleanUpSem = create_sem(0, "cleanup sem");
+ }
+
+ PR_Unlock( bt_book.ml );
+
+ /* note that, if all the user threads were already dead, we
+ wouldn't have created a sem above, so this acquire_sem()
+ will fail immediately */
+ while (acquire_sem(bt_book.cleanUpSem) == B_INTERRUPTED);
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(void)
+ PR_ProcessExit (PRIntn status)
+{
+ exit(status);
+}
+
+PRThread *_bt_AttachThread()
+{
+ PRThread *thread;
+ thread_info tInfo;
+
+ /* make sure this thread doesn't already have a PRThread structure */
+ PR_ASSERT(tls_get(tls_prThreadSlot) == NULL);
+
+ /* allocate a PRThread structure for this thread */
+ thread = PR_NEWZAP(PRThread);
+ if (thread == NULL)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ /* get the native thread's current state */
+ get_thread_info(find_thread(NULL), &tInfo);
+
+ /* initialize new PRThread */
+ thread->md.tid = tInfo.thread;
+ thread->md.joinSem = B_ERROR;
+ thread->priority = _bt_MapNativeToNSPRPriority(tInfo.priority);
+
+ /* attached threads are always non-joinable user threads */
+ thread->state = 0;
+
+ /* increment user thread count */
+ PR_Lock(bt_book.ml);
+ bt_book.threadCount++;
+ PR_Unlock(bt_book.ml);
+
+ /* store this thread's PRThread */
+ tls_set(tls_prThreadSlot, thread);
+
+ /* the thread must call _bt_CleanupThread() before it dies, in order
+ to clean up its PRThread, synchronize with the primordial thread,
+ etc. */
+ on_exit_thread(_bt_CleanupThread, NULL);
+
+ return thread;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/objs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/objs.mk
new file mode 100644
index 00000000..60455a37
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/bthreads/objs.mk
@@ -0,0 +1,43 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+# This makefile appends to the variable OBJS the bthread object modules
+# that will be part of the nspr20 library.
+
+include $(srcdir)/bthreads/bsrcs.mk
+
+OBJS += $(BTCSRCS:%.c=bthreads/$(OBJDIR)/%.$(OBJ_SUFFIX))
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/Makefile.in
new file mode 100644
index 00000000..46e62e75
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/Makefile.in
@@ -0,0 +1,75 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+CXXSRCS = \
+ rcbase.cpp \
+ rccv.cpp \
+ rcfileio.cpp \
+ rcinrval.cpp \
+ rcio.cpp \
+ rclock.cpp \
+ rcnetdb.cpp \
+ rcnetio.cpp \
+ rcthread.cpp \
+ rctime.cpp \
+ $(NULL)
+
+OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir)
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+HEADERS = $(wildcard $(srcdir)/*.h)
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcascii.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcascii.h
new file mode 100644
index 00000000..8476fc49
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcascii.h
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Class definitions to format ASCII data.
+*/
+
+#if defined(_RCASCII_H)
+#else
+#define _RCASCII_H
+
+/*
+** RCFormatStuff
+** This class maintains no state - that is the responsibility of
+** the class' client. For each call to Sx_printf(), the StuffFunction
+** will be called for each embedded "%" in the 'fmt' string and once
+** for each interveaning literal.
+*/
+class PR_IMPLEMENT(RCFormatStuff)
+{
+public:
+ RCFormatStuff();
+ virtual ~RCFormatStuff();
+
+ /*
+ ** Process the arbitrary argument list using as indicated by
+ ** the 'fmt' string. Each segment of the processing the stuff
+ ** function is called with the relavent translation.
+ */
+ virtual PRInt32 Sx_printf(void *state, const char *fmt, ...);
+
+ /*
+ ** The 'state' argument is not processed by the runtime. It
+ ** is merely passed from the Sx_printf() call. It is intended
+ ** to be used by the client to figure out what to do with the
+ ** new string.
+ **
+ ** The new string ('stuff') is ASCII translation driven by the
+ ** Sx_printf()'s 'fmt' string. It is not guaranteed to be a null
+ ** terminated string.
+ **
+ ** The return value is the number of bytes copied from the 'stuff'
+ ** string. It is accumulated for each of the calls to the stuff
+ ** function and returned from the original caller of Sx_printf().
+ */
+ virtual PRSize StuffFunction(
+ void *state, const char *stuff, PRSize stufflen) = 0;
+}; /* RCFormatStuff */
+
+
+/*
+** RCFormatBuffer
+** The caller is supplying the buffer, the runtime is doing all
+** the conversion. The object contains no state, so is reusable
+** and reentrant.
+*/
+class PR_IMPLEMENT(RCFormatBuffer): public RCFormatStuff
+{
+public:
+ RCFormatBuffer();
+ virtual ~RCFormatBuffer();
+
+ /*
+ ** Format the trailing arguments as indicated by the 'fmt'
+ ** string. Put the result in 'buffer'. Return the number
+ ** of bytes moved into 'buffer'. 'buffer' will always be
+ ** a properly terminated string even if the convresion fails.
+ */
+ virtual PRSize Sn_printf(
+ char *buffer, PRSize length, const char *fmt, ...);
+
+ virtual char *Sm_append(char *buffer, const char *fmt, ...);
+
+private:
+ /*
+ ** This class overrides the stuff function, does not preserve
+ ** its virtual-ness and no longer allows the clients to call
+ ** it in the clear. In other words, it is now the implementation
+ ** for this class.
+ */
+ PRSize StuffFunction(void*, const char*, PRSize);
+
+}; /* RCFormatBuffer */
+
+/*
+** RCFormat
+** The runtime is supplying the buffer. The object has state - the
+** buffer. Each operation must run to completion before the object
+** can be reused. When it is, the buffer is reset (whatever that
+** means). The result of a conversion is available via the extractor.
+** After extracted, the memory still belongs to the class - if the
+** caller wants to retain or modify, it must first be copied.
+*/
+class PR_IMPLEMENT(RCFormat): pubic RCFormatBuffer
+{
+public:
+ RCFormat();
+ virtual ~RCFormat();
+
+ /*
+ ** Translate the trailing arguments according to the 'fmt'
+ ** string and store the results in the object.
+ */
+ virtual PRSize Sm_printf(const char *fmt, ...);
+
+ /*
+ ** Extract the latest translation.
+ ** The object does not surrender the memory occupied by
+ ** the string. If the caller wishes to modify the data,
+ ** it must first be copied.
+ */
+ const char*();
+
+private:
+ char *buffer;
+
+ RCFormat(const RCFormat&);
+ RCFormat& operator=(const RCFormat&);
+}; /* RCFormat */
+
+/*
+** RCPrint
+** The output is formatted and then written to an associated file
+** descriptor. The client can provide a suitable file descriptor
+** or can indicate that the output should be directed to one of
+** the well-known "console" devices.
+*/
+class PR_IMPLEMENT(RCPrint): public RCFormat
+{
+ virtual ~RCPrint();
+ RCPrint(RCIO* output);
+ RCPrint(RCFileIO::SpecialFile output);
+
+ virtual PRSize Printf(const char *fmt, ...);
+private:
+ RCPrint();
+}; /* RCPrint */
+
+#endif /* defined(_RCASCII_H) */
+
+/* RCAscii.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.cpp
new file mode 100644
index 00000000..84662d9a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.cpp
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** RCBase.cpp - Mixin class for NSPR C++ wrappers
+*/
+
+#include "rcbase.h"
+
+RCBase::~RCBase() { }
+
+PRSize RCBase::GetErrorTextLength() { return PR_GetErrorTextLength(); }
+PRSize RCBase::CopyErrorText(char *text) { return PR_GetErrorText(text); }
+
+void RCBase::SetError(PRErrorCode error, PRInt32 oserror)
+ { PR_SetError(error, oserror); }
+
+void RCBase::SetErrorText(PRSize text_length, const char *text)
+ { PR_SetErrorText(text_length, text); }
+
+/* rcbase.cpp */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.h
new file mode 100644
index 00000000..0910a158
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcbase.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** RCBase.h - Mixin class for NSPR C++ wrappers
+*/
+
+#if defined(_RCRUNTIME_H)
+#else
+#define _RCRUNTIME_H
+
+#include <prerror.h>
+
+/*
+** Class: RCBase (mixin)
+**
+** Generally mixed into every base class. The functions in this class are all
+** static. Therefore this entire class is just syntatic sugar. It gives the
+** illusion that errors (in particular) are retrieved via the same object
+** that just reported a failure. It also (unfortunately) might lead one to
+** believe that the errors are persistent in that object. They're not.
+*/
+
+class PR_IMPLEMENT(RCBase)
+{
+public:
+ virtual ~RCBase();
+
+ static void AbortSelf();
+
+ static PRErrorCode GetError();
+ static PRInt32 GetOSError();
+
+ static PRSize GetErrorTextLength();
+ static PRSize CopyErrorText(char *text);
+
+ static void SetError(PRErrorCode error, PRInt32 oserror);
+ static void SetErrorText(PRSize textLength, const char *text);
+
+protected:
+ RCBase() { }
+}; /* RCObject */
+
+inline PRErrorCode RCBase::GetError() { return PR_GetError(); }
+inline PRInt32 RCBase::GetOSError() { return PR_GetOSError(); }
+
+#endif /* defined(_RCRUNTIME_H) */
+
+/* rcbase.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.cpp
new file mode 100644
index 00000000..5e03ae75
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** RCCondition - C++ wrapper around NSPR's PRCondVar
+*/
+
+#include "rccv.h"
+
+#include <prlog.h>
+#include <prerror.h>
+#include <prcvar.h>
+
+RCCondition::RCCondition(class RCLock *lock): RCBase()
+{
+ cv = PR_NewCondVar(lock->lock);
+ PR_ASSERT(NULL != cv);
+ timeout = PR_INTERVAL_NO_TIMEOUT;
+} /* RCCondition::RCCondition */
+
+RCCondition::~RCCondition()
+{
+ if (NULL != cv) PR_DestroyCondVar(cv);
+} /* RCCondition::~RCCondition */
+
+PRStatus RCCondition::Wait()
+{
+ PRStatus rv;
+ PR_ASSERT(NULL != cv);
+ if (NULL == cv)
+ {
+ SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ else
+ rv = PR_WaitCondVar(cv, timeout.interval);
+ return rv;
+} /* RCCondition::Wait */
+
+PRStatus RCCondition::Notify()
+{
+ return PR_NotifyCondVar(cv);
+} /* RCCondition::Notify */
+
+PRStatus RCCondition::Broadcast()
+{
+ return PR_NotifyAllCondVar(cv);
+} /* RCCondition::Broadcast */
+
+PRStatus RCCondition::SetTimeout(const RCInterval& tmo)
+{
+ if (NULL == cv)
+ {
+ SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ timeout = tmo;
+ return PR_SUCCESS;
+} /* RCCondition::SetTimeout */
+
+RCInterval RCCondition::GetTimeout() const { return timeout; }
+
+/* rccv.cpp */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.h
new file mode 100644
index 00000000..56923af1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rccv.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** RCCondition - C++ wrapper around NSPR's PRCondVar
+**
+** Conditions have a notion of timeouts. A thread that waits on a condition
+** will resume execution when the condition is notified OR when a specified
+** interval of time has expired.
+**
+** Most applications don't adjust the timeouts on conditions. The literature
+** would argue that all threads waiting on a single condition must have the
+** same semantics. But if an application wishes to modify the timeout with
+** (perhaps) each wait call, that modification should be done consistantly
+** and under protection of the condition's associated lock.
+**
+** The default timeout is infinity.
+*/
+
+#if defined(_RCCOND_H)
+#else
+#define _RCCOND_H
+
+#include "rclock.h"
+#include "rcbase.h"
+#include "rcinrval.h"
+
+struct PRCondVar;
+
+class PR_IMPLEMENT(RCCondition): public RCBase
+{
+public:
+ RCCondition(RCLock*); /* associates CV with a lock and infinite tmo */
+ virtual ~RCCondition();
+
+ virtual PRStatus Wait(); /* applies object's current timeout */
+
+ virtual PRStatus Notify(); /* perhaps ready one thread */
+ virtual PRStatus Broadcast(); /* perhaps ready many threads */
+
+ virtual PRStatus SetTimeout(const RCInterval&);
+ /* set object's current timeout value */
+
+private:
+ PRCondVar *cv;
+ RCInterval timeout;
+
+ RCCondition();
+ RCCondition(const RCCondition&);
+ void operator=(const RCCondition&);
+
+public:
+ RCInterval GetTimeout() const;
+}; /* RCCondition */
+
+inline RCCondition::RCCondition(): RCBase() { }
+inline RCCondition::RCCondition(const RCCondition&): RCBase() { }
+inline void RCCondition::operator=(const RCCondition&) { }
+
+#endif /* defined(_RCCOND_H) */
+
+/* RCCond.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.cpp
new file mode 100644
index 00000000..7646c894
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.cpp
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Class implementation for normal and special file I/O (ref: prio.h)
+*/
+
+#include "rcfileio.h"
+
+#include <string.h>
+
+RCFileIO::RCFileIO(): RCIO(RCIO::file) { }
+
+RCFileIO::~RCFileIO() { if (NULL != fd) (void)Close(); }
+
+PRInt64 RCFileIO::Available()
+ { return fd->methods->available(fd); }
+
+PRStatus RCFileIO::Close()
+ { PRStatus rv = fd->methods->close(fd); fd = NULL; return rv; }
+
+PRStatus RCFileIO::Delete(const char* filename) { return PR_Delete(filename); }
+
+PRStatus RCFileIO::FileInfo(RCFileInfo* info) const
+ { return fd->methods->fileInfo64(fd, &info->info); }
+
+PRStatus RCFileIO::FileInfo(const char *name, RCFileInfo* info)
+ { return PR_GetFileInfo64(name, &info->info); }
+
+PRStatus RCFileIO::Fsync()
+ { return fd->methods->fsync(fd); }
+
+PRStatus RCFileIO::Open(const char *filename, PRIntn flags, PRIntn mode)
+{
+ fd = PR_Open(filename, flags, mode);
+ return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;
+} /* RCFileIO::Open */
+
+PRInt32 RCFileIO::Read(void *buf, PRSize amount)
+ { return fd->methods->read(fd, buf, amount); }
+
+PRInt64 RCFileIO::Seek(PRInt64 offset, RCIO::Whence how)
+{
+ PRSeekWhence whence;
+ switch (how)
+ {
+ case RCFileIO::set: whence = PR_SEEK_SET; break;
+ case RCFileIO::current: whence = PR_SEEK_CUR; break;
+ case RCFileIO::end: whence = PR_SEEK_END; break;
+ default: whence = (PRSeekWhence)-1;
+ }
+ return fd->methods->seek64(fd, offset, whence);
+} /* RCFileIO::Seek */
+
+PRInt32 RCFileIO::Write(const void *buf, PRSize amount)
+ { return fd->methods->write(fd, buf, amount); }
+
+PRInt32 RCFileIO::Writev(
+ const PRIOVec *iov, PRSize size, const RCInterval& timeout)
+ { return fd->methods->writev(fd, iov, size, timeout); }
+
+RCIO *RCFileIO::GetSpecialFile(RCFileIO::SpecialFile special)
+{
+ PRFileDesc* fd;
+ PRSpecialFD which;
+ RCFileIO* spec = NULL;
+
+ switch (special)
+ {
+ case RCFileIO::input: which = PR_StandardInput; break;
+ case RCFileIO::output: which = PR_StandardOutput; break;
+ case RCFileIO::error: which = PR_StandardError; break;
+ default: which = (PRSpecialFD)-1;
+ }
+ fd = PR_GetSpecialFD(which);
+ if (NULL != fd)
+ {
+ spec = new RCFileIO();
+ if (NULL != spec) spec->fd = fd;
+ }
+ return spec;
+} /* RCFileIO::GetSpecialFile */
+
+
+/*
+** The following methods have been made non-virtual and private. These
+** default implementations are intended to NEVER be called. They
+** are not valid for this type of I/O class (normal and special file).
+*/
+PRStatus RCFileIO::Connect(const RCNetAddr&, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCFileIO::GetLocalName(RCNetAddr*) const
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCFileIO::GetPeerName(RCNetAddr*) const
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCFileIO::GetSocketOption(PRSocketOptionData*) const
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCFileIO::Listen(PRIntn)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRInt16 RCFileIO::Poll(PRInt16, PRInt16*)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return 0; }
+
+PRInt32 RCFileIO::Recv(void*, PRSize, PRIntn, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; }
+
+PRInt32 RCFileIO::Recvfrom(void*, PRSize, PRIntn, RCNetAddr*, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; }
+
+PRInt32 RCFileIO::Send(
+ const void*, PRSize, PRIntn, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; }
+
+PRInt32 RCFileIO::Sendto(
+ const void*, PRSize, PRIntn, const RCNetAddr&, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; }
+
+RCIO* RCFileIO::Accept(RCNetAddr*, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return NULL; }
+
+PRStatus RCFileIO::Bind(const RCNetAddr&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRInt32 RCFileIO::AcceptRead(
+ RCIO**, RCNetAddr**, void*, PRSize, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; }
+
+PRStatus RCFileIO::SetSocketOption(const PRSocketOptionData*)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCFileIO::Shutdown(RCIO::ShutdownHow)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRInt32 RCFileIO::TransmitFile(
+ RCIO*, const void*, PRSize, RCIO::FileDisposition, const RCInterval&)
+{ PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; }
+
+/*
+** Class implementation for file information object (ref: prio.h)
+*/
+
+RCFileInfo::~RCFileInfo() { }
+
+RCFileInfo::RCFileInfo(const RCFileInfo& her): RCBase()
+ { info = her.info; } /* RCFileInfo::RCFileInfo */
+
+RCTime RCFileInfo::CreationTime() const { return RCTime(info.creationTime); }
+
+RCTime RCFileInfo::ModifyTime() const { return RCTime(info.modifyTime); }
+
+RCFileInfo::FileType RCFileInfo::Type() const
+{
+ RCFileInfo::FileType type;
+ switch (info.type)
+ {
+ case PR_FILE_FILE: type = RCFileInfo::file; break;
+ case PR_FILE_DIRECTORY: type = RCFileInfo::directory; break;
+ default: type = RCFileInfo::other;
+ }
+ return type;
+} /* RCFileInfo::Type */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.h
new file mode 100644
index 00000000..576b37df
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcfileio.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Class definitions for normal and special file I/O (ref: prio.h)
+*/
+
+#if defined(_RCFILEIO_H)
+#else
+#define _RCFILEIO_H
+
+#include "rcio.h"
+#include "rctime.h"
+
+/*
+** One would normally create a concrete class, such as RCFileIO, but then
+** pass around more generic references, ie., RCIO.
+**
+** This subclass of RCIO hides (makes private) the methods that are not
+** applicable to normal files.
+*/
+
+class RCFileInfo;
+
+class PR_IMPLEMENT(RCFileIO): public RCIO
+{
+public:
+ RCFileIO();
+ virtual ~RCFileIO();
+
+ virtual PRInt64 Available();
+ virtual PRStatus Close();
+ static PRStatus Delete(const char *name);
+ virtual PRStatus FileInfo(RCFileInfo* info) const;
+ static PRStatus FileInfo(const char *name, RCFileInfo* info);
+ virtual PRStatus Fsync();
+ virtual PRStatus Open(const char *name, PRIntn flags, PRIntn mode);
+ virtual PRInt32 Read(void *buf, PRSize amount);
+ virtual PRInt64 Seek(PRInt64 offset, RCIO::Whence how);
+ virtual PRInt32 Write(const void *buf, PRSize amount);
+ virtual PRInt32 Writev(
+ const PRIOVec *iov, PRSize size,
+ const RCInterval& timeout);
+
+private:
+
+ /* These methods made private are unavailable for this object */
+ RCFileIO(const RCFileIO&);
+ void operator=(const RCFileIO&);
+
+ RCIO* Accept(RCNetAddr* addr, const RCInterval& timeout);
+ PRInt32 AcceptRead(
+ RCIO **newfd, RCNetAddr **address, void *buffer,
+ PRSize amount, const RCInterval& timeout);
+ PRStatus Bind(const RCNetAddr& addr);
+ PRStatus Connect(const RCNetAddr& addr, const RCInterval& timeout);
+ PRStatus GetLocalName(RCNetAddr *addr) const;
+ PRStatus GetPeerName(RCNetAddr *addr) const;
+ PRStatus GetSocketOption(PRSocketOptionData *data) const;
+ PRStatus Listen(PRIntn backlog);
+ PRInt16 Poll(PRInt16 in_flags, PRInt16 *out_flags);
+ PRInt32 Recv(
+ void *buf, PRSize amount, PRIntn flags,
+ const RCInterval& timeout);
+ PRInt32 Recvfrom(
+ void *buf, PRSize amount, PRIntn flags,
+ RCNetAddr* addr, const RCInterval& timeout);
+ PRInt32 Send(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCInterval& timeout);
+ PRInt32 Sendto(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCNetAddr& addr,
+ const RCInterval& timeout);
+ PRStatus SetSocketOption(const PRSocketOptionData *data);
+ PRStatus Shutdown(RCIO::ShutdownHow how);
+ PRInt32 TransmitFile(
+ RCIO *source, const void *headers,
+ PRSize hlen, RCIO::FileDisposition flags,
+ const RCInterval& timeout);
+public:
+
+ /*
+ ** The following function return a valid normal file object,
+ ** Such objects can be used for scanned input and console output.
+ */
+ typedef enum {
+ input = PR_StandardInput,
+ output = PR_StandardOutput,
+ error = PR_StandardError
+ } SpecialFile;
+
+ static RCIO *GetSpecialFile(RCFileIO::SpecialFile special);
+
+}; /* RCFileIO */
+
+class PR_IMPLEMENT(RCFileInfo): public RCBase
+{
+public:
+ typedef enum {
+ file = PR_FILE_FILE,
+ directory = PR_FILE_DIRECTORY,
+ other = PR_FILE_OTHER
+ } FileType;
+
+public:
+ RCFileInfo();
+ RCFileInfo(const RCFileInfo&);
+
+ virtual ~RCFileInfo();
+
+ PRInt64 Size() const;
+ RCTime CreationTime() const;
+ RCTime ModifyTime() const;
+ RCFileInfo::FileType Type() const;
+
+friend PRStatus RCFileIO::FileInfo(RCFileInfo*) const;
+friend PRStatus RCFileIO::FileInfo(const char *name, RCFileInfo*);
+
+private:
+ PRFileInfo64 info;
+}; /* RCFileInfo */
+
+inline RCFileInfo::RCFileInfo(): RCBase() { }
+inline PRInt64 RCFileInfo::Size() const { return info.size; }
+
+#endif /* defined(_RCFILEIO_H) */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.cpp
new file mode 100644
index 00000000..ff075a3a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** C++ interval times (ref: prinrval.h)
+**
+** An interval is a period of time. The start of the interval (epoch)
+** must be defined by the application. The unit of time of an interval
+** is platform dependent, therefore so is the maximum interval that is
+** representable. However, that interval is never less that ~12 hours.
+*/
+
+#include "rcinrval.h"
+
+RCInterval::~RCInterval() { }
+
+RCInterval::RCInterval(RCInterval::RCReservedInterval special): RCBase()
+{
+ switch (special)
+ {
+ case RCInterval::now:
+ interval = PR_IntervalNow();
+ break;
+ case RCInterval::no_timeout:
+ interval = PR_INTERVAL_NO_TIMEOUT;
+ break;
+ case RCInterval::no_wait:
+ interval = PR_INTERVAL_NO_WAIT;
+ break;
+ default:
+ break;
+ }
+} /* RCInterval::RCInterval */
+
+/* rcinrval.cpp */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.h
new file mode 100644
index 00000000..2dc24987
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcinrval.h
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** C++ interval times (ref: prinrval.h)
+**
+** An interval is a period of time. The start of the interval (epoch)
+** must be defined by the application. The unit of time of an interval
+** is platform dependent, therefore so is the maximum interval that is
+** representable. However, that interval is never less than ~6 hours.
+*/
+#if defined(_RCINTERVAL_H)
+#else
+#define _RCINTERVAL_H
+
+#include "rcbase.h"
+#include <prinrval.h>
+
+class PR_IMPLEMENT(RCInterval): public RCBase
+{
+public:
+ typedef enum {now, no_timeout, no_wait} RCReservedInterval;
+
+ virtual ~RCInterval();
+
+ RCInterval();
+
+ RCInterval(PRIntervalTime interval);
+ RCInterval(const RCInterval& copy);
+ RCInterval(RCReservedInterval special);
+
+ void SetToNow();
+
+ void operator=(const RCInterval&);
+ void operator=(PRIntervalTime interval);
+
+ PRBool operator<(const RCInterval&);
+ PRBool operator>(const RCInterval&);
+ PRBool operator==(const RCInterval&);
+ PRBool operator>=(const RCInterval&);
+ PRBool operator<=(const RCInterval&);
+
+ RCInterval operator+(const RCInterval&);
+ RCInterval operator-(const RCInterval&);
+ RCInterval& operator+=(const RCInterval&);
+ RCInterval& operator-=(const RCInterval&);
+
+ RCInterval operator/(PRUint32);
+ RCInterval operator*(PRUint32);
+ RCInterval& operator/=(PRUint32);
+ RCInterval& operator*=(PRUint32);
+
+
+ PRUint32 ToSeconds() const;
+ PRUint32 ToMilliseconds() const;
+ PRUint32 ToMicroseconds() const;
+ operator PRIntervalTime() const;
+
+ static PRIntervalTime FromSeconds(PRUint32 seconds);
+ static PRIntervalTime FromMilliseconds(PRUint32 milli);
+ static PRIntervalTime FromMicroseconds(PRUint32 micro);
+
+ friend class RCCondition;
+
+private:
+ PRIntervalTime interval;
+
+}; /* RCInterval */
+
+
+inline RCInterval::RCInterval(): RCBase() { }
+
+inline RCInterval::RCInterval(const RCInterval& his): RCBase()
+ { interval = his.interval; }
+
+inline RCInterval::RCInterval(PRIntervalTime ticks): RCBase()
+ { interval = ticks; }
+
+inline void RCInterval::SetToNow() { interval = PR_IntervalNow(); }
+
+inline void RCInterval::operator=(const RCInterval& his)
+ { interval = his.interval; }
+
+inline void RCInterval::operator=(PRIntervalTime his)
+ { interval = his; }
+
+inline PRBool RCInterval::operator==(const RCInterval& his)
+ { return (interval == his.interval) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCInterval::operator<(const RCInterval& his)
+ { return (interval < his.interval)? PR_TRUE : PR_FALSE; }
+inline PRBool RCInterval::operator>(const RCInterval& his)
+ { return (interval > his.interval) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCInterval::operator<=(const RCInterval& his)
+ { return (interval <= his.interval) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCInterval::operator>=(const RCInterval& his)
+ { return (interval <= his.interval) ? PR_TRUE : PR_FALSE; }
+
+inline RCInterval RCInterval::operator+(const RCInterval& his)
+ { return RCInterval((PRIntervalTime)(interval + his.interval)); }
+inline RCInterval RCInterval::operator-(const RCInterval& his)
+ { return RCInterval((PRIntervalTime)(interval - his.interval)); }
+inline RCInterval& RCInterval::operator+=(const RCInterval& his)
+ { interval += his.interval; return *this; }
+inline RCInterval& RCInterval::operator-=(const RCInterval& his)
+ { interval -= his.interval; return *this; }
+
+inline RCInterval RCInterval::operator/(PRUint32 him)
+ { return RCInterval((PRIntervalTime)(interval / him)); }
+inline RCInterval RCInterval::operator*(PRUint32 him)
+ { return RCInterval((PRIntervalTime)(interval * him)); }
+
+inline RCInterval& RCInterval::operator/=(PRUint32 him)
+ { interval /= him; return *this; }
+
+inline RCInterval& RCInterval::operator*=(PRUint32 him)
+ { interval *= him; return *this; }
+
+inline PRUint32 RCInterval::ToSeconds() const
+ { return PR_IntervalToSeconds(interval); }
+inline PRUint32 RCInterval::ToMilliseconds() const
+ { return PR_IntervalToMilliseconds(interval); }
+inline PRUint32 RCInterval::ToMicroseconds() const
+ { return PR_IntervalToMicroseconds(interval); }
+inline RCInterval::operator PRIntervalTime() const { return interval; }
+
+inline PRIntervalTime RCInterval::FromSeconds(PRUint32 seconds)
+ { return PR_SecondsToInterval(seconds); }
+inline PRIntervalTime RCInterval::FromMilliseconds(PRUint32 milli)
+ { return PR_MillisecondsToInterval(milli); }
+inline PRIntervalTime RCInterval::FromMicroseconds(PRUint32 micro)
+ { return PR_MicrosecondsToInterval(micro); }
+
+#endif /* defined(_RCINTERVAL_H) */
+
+/* RCInterval.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.cpp
new file mode 100644
index 00000000..27f9e788
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Base class implmenation for I/O (ref: prio.h)
+*/
+
+#include "rcio.h"
+
+RCIO::~RCIO() { }
+
+RCIO::RCIO(RCIO::RCIOType): RCBase() { }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.h
new file mode 100644
index 00000000..5550a881
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcio.h
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Base class definitions for I/O (ref: prio.h)
+**
+** This class is a virtual base class. Construction must be done by a
+** subclass, but the I/O operations can be done on a RCIO object reference.
+*/
+
+#if defined(_RCIO_H)
+#else
+#define _RCIO_H
+
+#include "rcbase.h"
+#include "rcnetdb.h"
+#include "rcinrval.h"
+
+#include "prio.h"
+
+class RCFileInfo;
+
+class PR_IMPLEMENT(RCIO): public RCBase
+{
+public:
+ typedef enum {
+ open = PR_TRANSMITFILE_KEEP_OPEN, /* socket is left open after file
+ * is transmitted. */
+ close = PR_TRANSMITFILE_CLOSE_SOCKET/* socket is closed after file
+ * is transmitted. */
+ } FileDisposition;
+
+ typedef enum {
+ set = PR_SEEK_SET, /* Set to value specified */
+ current = PR_SEEK_CUR, /* Seek relative to current position */
+ end = PR_SEEK_END /* seek past end of current eof */
+ } Whence;
+
+ typedef enum {
+ recv = PR_SHUTDOWN_RCV, /* receives will be disallowed */
+ send = PR_SHUTDOWN_SEND, /* sends will be disallowed */
+ both = PR_SHUTDOWN_BOTH /* sends & receives will be disallowed */
+ } ShutdownHow;
+
+public:
+ virtual ~RCIO();
+
+ virtual RCIO* Accept(RCNetAddr* addr, const RCInterval& timeout) = 0;
+ virtual PRInt32 AcceptRead(
+ RCIO **nd, RCNetAddr **raddr, void *buf,
+ PRSize amount, const RCInterval& timeout) = 0;
+ virtual PRInt64 Available() = 0;
+ virtual PRStatus Bind(const RCNetAddr& addr) = 0;
+ virtual PRStatus Close() = 0;
+ virtual PRStatus Connect(
+ const RCNetAddr& addr,
+ const RCInterval& timeout) = 0;
+ virtual PRStatus FileInfo(RCFileInfo *info) const = 0;
+ virtual PRStatus Fsync() = 0;
+ virtual PRStatus GetLocalName(RCNetAddr *addr) const = 0;
+ virtual PRStatus GetPeerName(RCNetAddr *addr) const = 0;
+ virtual PRStatus GetSocketOption(PRSocketOptionData *data) const = 0;
+ virtual PRStatus Listen(PRIntn backlog) = 0;
+ virtual PRStatus Open(const char *name, PRIntn flags, PRIntn mode) = 0;
+ virtual PRInt16 Poll(PRInt16 in_flags, PRInt16 *out_flags) = 0;
+ virtual PRInt32 Read(void *buf, PRSize amount) = 0;
+ virtual PRInt32 Recv(
+ void *buf, PRSize amount, PRIntn flags,
+ const RCInterval& timeout) = 0;
+ virtual PRInt32 Recvfrom(
+ void *buf, PRSize amount, PRIntn flags,
+ RCNetAddr* addr, const RCInterval& timeout) = 0;
+ virtual PRInt64 Seek(PRInt64 offset, Whence how) = 0;
+ virtual PRInt32 Send(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCInterval& timeout) = 0;
+ virtual PRInt32 Sendto(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCNetAddr& addr,
+ const RCInterval& timeout) = 0;
+ virtual PRStatus SetSocketOption(const PRSocketOptionData *data) = 0;
+ virtual PRStatus Shutdown(ShutdownHow how) = 0;
+ virtual PRInt32 TransmitFile(
+ RCIO *source, const void *headers,
+ PRSize hlen, RCIO::FileDisposition flags,
+ const RCInterval& timeout) = 0;
+ virtual PRInt32 Write(const void *buf, PRSize amount) = 0;
+ virtual PRInt32 Writev(
+ const PRIOVec *iov, PRSize size,
+ const RCInterval& timeout) = 0;
+
+protected:
+ typedef enum {
+ file = PR_DESC_FILE,
+ tcp = PR_DESC_SOCKET_TCP,
+ udp = PR_DESC_SOCKET_UDP,
+ layered = PR_DESC_LAYERED} RCIOType;
+
+ RCIO(RCIOType);
+
+ PRFileDesc *fd; /* where the real code hides */
+
+private:
+ /* no default construction and no copies allowed */
+ RCIO();
+ RCIO(const RCIO&);
+
+}; /* RCIO */
+
+#endif /* defined(_RCIO_H) */
+
+/* RCIO.h */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.cpp
new file mode 100644
index 00000000..87b326bc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+/*
+** C++ access to NSPR locks (PRLock)
+*/
+
+#include "rclock.h"
+#include <prlog.h>
+
+RCLock::RCLock()
+{
+ lock = PR_NewLock(); /* it might be NULL */
+ PR_ASSERT(NULL != lock);
+} /* RCLock::RCLock */
+
+RCLock::~RCLock()
+{
+ if (NULL != lock) PR_DestroyLock(lock);
+ lock = NULL;
+} /* RCLock::~RCLock */
+
+void RCLock::Acquire()
+{
+ PR_ASSERT(NULL != lock);
+ PR_Lock(lock);
+} /* RCLock::Acquire */
+
+void RCLock::Release()
+{
+ PRStatus rv;
+ PR_ASSERT(NULL != lock);
+ rv = PR_Unlock(lock);
+ PR_ASSERT(PR_SUCCESS == rv);
+} /* RCLock::Release */
+
+/* RCLock.cpp */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.h
new file mode 100644
index 00000000..9e20ef04
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rclock.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** C++ access to NSPR locks (PRLock)
+*/
+
+#if defined(_RCLOCK_H)
+#else
+#define _RCLOCK_H
+
+#include "rcbase.h"
+
+#include <prlock.h>
+
+class PR_IMPLEMENT(RCLock): public RCBase
+{
+public:
+ RCLock();
+ virtual ~RCLock();
+
+ void Acquire(); /* non-reentrant */
+ void Release(); /* should be by owning thread */
+
+ friend class RCCondition;
+
+private:
+ RCLock(const RCLock&); /* can't do that */
+ void operator=(const RCLock&); /* nor that */
+
+ PRLock *lock;
+}; /* RCLock */
+
+/*
+** Class: RCEnter
+**
+** In scope locks. You can only allocate them on the stack. The language
+** will insure that they get released (by calling the destructor) when
+** the thread leaves scope, even if via an exception.
+*/
+class PR_IMPLEMENT(RCEnter)
+{
+public:
+ ~RCEnter(); /* releases the lock */
+ RCEnter(RCLock*); /* acquires the lock */
+
+private:
+ RCLock *lock;
+
+ RCEnter();
+ RCEnter(const RCEnter&);
+ void operator=(const RCEnter&);
+
+ void *operator new(PRSize) { return NULL; }
+ void operator delete(void*) { }
+}; /* RCEnter */
+
+
+inline RCEnter::RCEnter(RCLock* ml) { lock = ml; lock->Acquire(); }
+inline RCEnter::~RCEnter() { lock->Release(); lock = NULL; }
+
+#endif /* defined(_RCLOCK_H) */
+
+/* RCLock.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcmon.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcmon.h
new file mode 100644
index 00000000..75b8ca3e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcmon.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Class: RCMonitor (ref prmonitor.h)
+**
+** RCMonitor.h - C++ wrapper around NSPR's monitors
+*/
+#if defined(_RCMONITOR_H)
+#else
+#define _RCMONITOR_H
+
+#include "rcbase.h"
+#include "rcinrval.h"
+
+struct PRMonitor;
+
+class PR_IMPLEMENT(RCMonitor): public RCBase
+{
+public:
+ RCMonitor(); /* timeout is infinity */
+ virtual ~RCMonitor();
+
+ virtual void Enter(); /* reentrant entry */
+ virtual void Exit();
+
+ virtual void Notify(); /* possibly enable one thread */
+ virtual void NotifyAll(); /* enable all waiters */
+
+ virtual void Wait(); /* applies object's timeout */
+
+ virtual void SetTimeout(const RCInterval& timeout);
+
+private:
+ PRMonitor *monitor;
+ RCInterval timeout;
+
+public:
+ RCInterval GetTimeout() const; /* get the current value */
+
+}; /* RCMonitor */
+
+#endif /* defined(_RCMONITOR_H) */
+
+/* RCMonitor.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.cpp
new file mode 100644
index 00000000..9890c9ae
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.cpp
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Base class implementation for network access functions (ref: prnetdb.h)
+*/
+
+#include "rclock.h"
+#include "rcnetdb.h"
+
+#include <prmem.h>
+#include <prlog.h>
+#include <string.h>
+
+RCNetAddr::RCNetAddr(const RCNetAddr& his): RCBase()
+ { address = his.address; }
+
+RCNetAddr::RCNetAddr(const RCNetAddr& his, PRUint16 port): RCBase()
+{
+ address = his.address;
+ switch (address.raw.family)
+ {
+ case PR_AF_INET: address.inet.port = port; break;
+ case PR_AF_INET6: address.ipv6.port = port; break;
+ default: break;
+ }
+} /* RCNetAddr::RCNetAddr */
+
+RCNetAddr::RCNetAddr(RCNetAddr::HostValue host, PRUint16 port): RCBase()
+{
+ PRNetAddrValue how;
+ switch (host)
+ {
+ case RCNetAddr::any: how = PR_IpAddrAny; break;
+ case RCNetAddr::loopback: how = PR_IpAddrLoopback; break;
+ default: PR_ASSERT(!"This can't happen -- and did!");
+ }
+ (void)PR_InitializeNetAddr(how, port, &address);
+} /* RCNetAddr::RCNetAddr */
+
+RCNetAddr::~RCNetAddr() { }
+
+void RCNetAddr::operator=(const RCNetAddr& his) { address = his.address; }
+
+PRStatus RCNetAddr::FromString(const char* string)
+ { return PR_StringToNetAddr(string, &address); }
+
+void RCNetAddr::operator=(const PRNetAddr* addr) { address = *addr; }
+
+PRBool RCNetAddr::operator==(const RCNetAddr& his) const
+{
+ PRBool rv = EqualHost(his);
+ if (rv)
+ {
+ switch (address.raw.family)
+ {
+ case PR_AF_INET:
+ rv = (address.inet.port == his.address.inet.port); break;
+ case PR_AF_INET6:
+ rv = (address.ipv6.port == his.address.ipv6.port); break;
+ case PR_AF_LOCAL:
+ default: break;
+ }
+ }
+ return rv;
+} /* RCNetAddr::operator== */
+
+PRBool RCNetAddr::EqualHost(const RCNetAddr& his) const
+{
+ PRBool rv;
+ switch (address.raw.family)
+ {
+ case PR_AF_INET:
+ rv = (address.inet.ip == his.address.inet.ip); break;
+ case PR_AF_INET6:
+ rv = (0 == memcmp(
+ &address.ipv6.ip, &his.address.ipv6.ip,
+ sizeof(address.ipv6.ip)));
+ break;
+#if defined(XP_UNIX)
+ case PR_AF_LOCAL:
+ rv = (0 == strncmp(
+ address.local.path, his.address.local.path,
+ sizeof(address.local.path)));
+ break;
+#endif
+ default: break;
+ }
+ return rv;
+} /* RCNetAddr::operator== */
+
+PRStatus RCNetAddr::ToString(char *string, PRSize size) const
+ { return PR_NetAddrToString(&address, string, size); }
+
+/*
+** RCHostLookup
+*/
+
+RCHostLookup::~RCHostLookup()
+{
+ if (NULL != address) delete [] address;
+} /* RCHostLookup::~RCHostLookup */
+
+RCHostLookup::RCHostLookup(): RCBase()
+{
+ address = NULL;
+ max_index = 0;
+} /* RCHostLookup::RCHostLookup */
+
+PRStatus RCHostLookup::ByName(const char* name)
+{
+ PRStatus rv;
+ PRNetAddr addr;
+ PRHostEnt hostentry;
+ PRIntn index = 0, max;
+ RCNetAddr* vector = NULL;
+ RCNetAddr* old_vector = NULL;
+ void* buffer = PR_Malloc(PR_NETDB_BUF_SIZE);
+ if (NULL == buffer) return PR_FAILURE;
+ rv = PR_GetHostByName(name, (char*)buffer, PR_NETDB_BUF_SIZE, &hostentry);
+ if (PR_SUCCESS == rv)
+ {
+ for (max = 0, index = 0;; ++max)
+ {
+ index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr);
+ if (0 == index) break;
+ }
+ if (max > 0)
+ {
+ vector = new RCNetAddr[max];
+ while (--max > 0)
+ {
+ index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr);
+ if (0 == index) break;
+ vector[index] = &addr;
+ }
+ {
+ RCEnter entry(&ml);
+ old_vector = address;
+ address = vector;
+ max_index = max;
+ }
+ if (NULL != old_vector) delete [] old_vector;
+ }
+ }
+ if (NULL != buffer) PR_DELETE(buffer);
+ return PR_SUCCESS;
+} /* RCHostLookup::ByName */
+
+PRStatus RCHostLookup::ByAddress(const RCNetAddr& host_addr)
+{
+ PRStatus rv;
+ PRNetAddr addr;
+ PRHostEnt hostentry;
+ PRIntn index = 0, max;
+ RCNetAddr* vector = NULL;
+ RCNetAddr* old_vector = NULL;
+ char *buffer = (char*)PR_Malloc(PR_NETDB_BUF_SIZE);
+ if (NULL == buffer) return PR_FAILURE;
+ rv = PR_GetHostByAddr(host_addr, buffer, PR_NETDB_BUF_SIZE, &hostentry);
+ if (PR_SUCCESS == rv)
+ {
+ for (max = 0, index = 0;; ++max)
+ {
+ index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr);
+ if (0 == index) break;
+ }
+ if (max > 0)
+ {
+ vector = new RCNetAddr[max];
+ while (--max > 0)
+ {
+ index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr);
+ if (0 == index) break;
+ vector[index] = &addr;
+ }
+ {
+ RCEnter entry(&ml);
+ old_vector = address;
+ address = vector;
+ max_index = max;
+ }
+ if (NULL != old_vector) delete [] old_vector;
+ }
+ }
+ if (NULL != buffer) PR_DELETE(buffer);
+ return PR_SUCCESS;
+} /* RCHostLookup::ByAddress */
+
+const RCNetAddr* RCHostLookup::operator[](PRUintn which)
+{
+ RCNetAddr* addr = NULL;
+ if (which < max_index)
+ addr = &address[which];
+ return addr;
+} /* RCHostLookup::operator[] */
+
+/* RCNetdb.cpp */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.h
new file mode 100644
index 00000000..03f5b4f0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetdb.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Base class definitions for network access functions (ref: prnetdb.h)
+*/
+
+#if defined(_RCNETDB_H)
+#else
+#define _RCNETDB_H
+
+#include "rclock.h"
+#include "rcbase.h"
+
+#include <prnetdb.h>
+
+class PR_IMPLEMENT(RCNetAddr): public RCBase
+{
+public:
+ typedef enum {
+ any = PR_IpAddrAny, /* assign logical INADDR_ANY */
+ loopback = PR_IpAddrLoopback /* assign logical INADDR_LOOPBACK */
+ } HostValue;
+
+ RCNetAddr(); /* default constructor is unit'd object */
+ RCNetAddr(const RCNetAddr&); /* copy constructor */
+ RCNetAddr(HostValue, PRUint16 port);/* init'd w/ 'special' assignments */
+ RCNetAddr(const RCNetAddr&, PRUint16 port);
+ /* copy w/ port reassigment */
+
+ virtual ~RCNetAddr();
+
+ void operator=(const RCNetAddr&);
+
+ virtual PRBool operator==(const RCNetAddr&) const;
+ /* compare of all relavent fields */
+ virtual PRBool EqualHost(const RCNetAddr&) const;
+ /* compare of just host field */
+
+
+public:
+
+ void operator=(const PRNetAddr*); /* construction from more primitive data */
+ operator const PRNetAddr*() const; /* extraction of underlying representation */
+ virtual PRStatus FromString(const char* string);
+ /* initialization from an ASCII string */
+ virtual PRStatus ToString(char *string, PRSize size) const;
+ /* convert internal fromat to a string */
+
+private:
+
+ PRNetAddr address;
+
+}; /* RCNetAddr */
+
+/*
+** Class: RCHostLookup
+**
+** Abstractions to look up host names and addresses.
+**
+** This is a stateful class. One looks up the host by name or by
+** address, then enumerates over a possibly empty array of network
+** addresses. The storage for the addresses is owned by the class.
+*/
+
+class RCHostLookup: public RCBase
+{
+public:
+ virtual ~RCHostLookup();
+
+ RCHostLookup();
+
+ virtual PRStatus ByName(const char* name);
+ virtual PRStatus ByAddress(const RCNetAddr&);
+
+ virtual const RCNetAddr* operator[](PRUintn);
+
+private:
+ RCLock ml;
+ PRIntn max_index;
+ RCNetAddr* address;
+
+ RCHostLookup(const RCHostLookup&);
+ RCHostLookup& operator=(const RCHostLookup&);
+};
+
+inline RCNetAddr::RCNetAddr(): RCBase() { }
+inline RCNetAddr::operator const PRNetAddr*() const { return &address; }
+
+
+#endif /* defined(_RCNETDB_H) */
+
+/* RCNetdb.h */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.cpp
new file mode 100644
index 00000000..bdc94309
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.cpp
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Subclass implementation for streamed network I/O (ref: prio.h)
+*/
+
+#include "rcnetio.h"
+
+#include <private/pprio.h>
+
+RCNetStreamIO::~RCNetStreamIO()
+ { PRStatus rv = (fd->methods->close)(fd); fd = NULL; }
+
+RCNetStreamIO::RCNetStreamIO(): RCIO(RCIO::tcp)
+ { fd = PR_NewTCPSocket(); }
+
+RCNetStreamIO::RCNetStreamIO(PRIntn protocol): RCIO(RCIO::tcp)
+ { fd = PR_Socket(PR_AF_INET, PR_SOCK_STREAM, protocol); }
+
+RCIO* RCNetStreamIO::Accept(RCNetAddr* addr, const RCInterval& timeout)
+{
+ PRNetAddr peer;
+ RCNetStreamIO* rcio = NULL;
+ PRFileDesc* newfd = fd->methods->accept(fd, &peer, timeout);
+ if (NULL != newfd)
+ {
+ rcio = new RCNetStreamIO();
+ if (NULL != rcio)
+ {
+ *addr = &peer;
+ rcio->fd = newfd;
+ }
+ else
+ (void)(newfd->methods->close)(newfd);
+ }
+ return rcio;
+} /* RCNetStreamIO::Accept */
+
+PRInt32 RCNetStreamIO::AcceptRead(
+ RCIO **nd, RCNetAddr **raddr, void *buf,
+ PRSize amount, const RCInterval& timeout)
+{
+ PRNetAddr *from;
+ PRFileDesc *accepted;
+ PRInt32 rv = (fd->methods->acceptread)(
+ fd, &accepted, &from, buf, amount, timeout);
+ if (rv >= 0)
+ {
+ RCNetStreamIO *ns = new RCNetStreamIO();
+ if (NULL != *nd) ns->fd = accepted;
+ else {PR_Close(accepted); rv = -1; }
+ *nd = ns;
+ }
+ return rv;
+} /* RCNetStreamIO::AcceptRead */
+
+PRInt64 RCNetStreamIO::Available()
+ { return (fd->methods->available64)(fd); }
+
+PRStatus RCNetStreamIO::Bind(const RCNetAddr& addr)
+ { return (fd->methods->bind)(fd, addr); }
+
+PRStatus RCNetStreamIO::Connect(const RCNetAddr& addr, const RCInterval& timeout)
+ { return (fd->methods->connect)(fd, addr, timeout); }
+
+PRStatus RCNetStreamIO::GetLocalName(RCNetAddr *addr) const
+{
+ PRNetAddr local;
+ PRStatus rv = (fd->methods->getsockname)(fd, &local);
+ if (PR_SUCCESS == rv) *addr = &local;
+ return rv;
+} /* RCNetStreamIO::GetLocalName */
+
+PRStatus RCNetStreamIO::GetPeerName(RCNetAddr *addr) const
+{
+ PRNetAddr peer;
+ PRStatus rv = (fd->methods->getpeername)(fd, &peer);
+ if (PR_SUCCESS == rv) *addr = &peer;
+ return rv;
+} /* RCNetStreamIO::GetPeerName */
+
+PRStatus RCNetStreamIO::GetSocketOption(PRSocketOptionData *data) const
+ { return (fd->methods->getsocketoption)(fd, data); }
+
+PRStatus RCNetStreamIO::Listen(PRIntn backlog)
+ { return (fd->methods->listen)(fd, backlog); }
+
+PRInt16 RCNetStreamIO::Poll(PRInt16 in_flags, PRInt16 *out_flags)
+ { return (fd->methods->poll)(fd, in_flags, out_flags); }
+
+PRInt32 RCNetStreamIO::Read(void *buf, PRSize amount)
+ { return (fd->methods->read)(fd, buf, amount); }
+
+PRInt32 RCNetStreamIO::Recv(
+ void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout)
+ { return (fd->methods->recv)(fd, buf, amount, flags, timeout); }
+
+PRInt32 RCNetStreamIO::Recvfrom(
+ void *buf, PRSize amount, PRIntn flags,
+ RCNetAddr* addr, const RCInterval& timeout)
+{
+ PRNetAddr peer;
+ PRInt32 rv = (fd->methods->recvfrom)(
+ fd, buf, amount, flags, &peer, timeout);
+ if (-1 != rv) *addr = &peer;
+ return rv;
+} /* RCNetStreamIO::Recvfrom */
+
+PRInt32 RCNetStreamIO::Send(
+ const void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout)
+ { return (fd->methods->send)(fd, buf, amount, flags, timeout); }
+
+PRInt32 RCNetStreamIO::Sendto(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCNetAddr& addr, const RCInterval& timeout)
+ { return (fd->methods->sendto)(fd, buf, amount, flags, addr, timeout); }
+
+PRStatus RCNetStreamIO::SetSocketOption(const PRSocketOptionData *data)
+ { return (fd->methods->setsocketoption)(fd, data); }
+
+PRStatus RCNetStreamIO::Shutdown(RCIO::ShutdownHow how)
+ { return (fd->methods->shutdown)(fd, (PRIntn)how); }
+
+PRInt32 RCNetStreamIO::TransmitFile(
+ RCIO *source, const void *headers, PRSize hlen,
+ RCIO::FileDisposition flags, const RCInterval& timeout)
+{
+ RCNetStreamIO *src = (RCNetStreamIO*)source;
+ return (fd->methods->transmitfile)(
+ fd, src->fd, headers, hlen, (PRTransmitFileFlags)flags, timeout); }
+
+PRInt32 RCNetStreamIO::Write(const void *buf, PRSize amount)
+ { return (fd->methods->write)(fd, buf, amount); }
+
+PRInt32 RCNetStreamIO::Writev(
+ const PRIOVec *iov, PRSize size, const RCInterval& timeout)
+ { return (fd->methods->writev)(fd, iov, size, timeout); }
+
+/*
+** Invalid functions
+*/
+
+PRStatus RCNetStreamIO::Close()
+ { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCNetStreamIO::FileInfo(RCFileInfo*) const
+ { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRStatus RCNetStreamIO::Fsync()
+ { return (fd->methods->fsync)(fd); }
+
+PRStatus RCNetStreamIO::Open(const char*, PRIntn, PRIntn)
+ { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+PRInt64 RCNetStreamIO::Seek(PRInt64, RCIO::Whence)
+ { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; }
+
+/* RCNetStreamIO.cpp */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.h
new file mode 100644
index 00000000..54ce695f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcnetio.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Subclass definitions for network I/O (ref: prio.h)
+*/
+
+#if defined(_RCNETIO_H)
+#else
+#define _RCNETIO_H
+
+#include "rcbase.h"
+#include "rcinrval.h"
+#include "rcio.h"
+#include "rcnetdb.h"
+
+#include "prio.h"
+
+class RCFileInfo;
+
+/*
+** Class: RCNetStreamIO (ref prio.h)
+**
+** Streamed (reliable) network I/O (e.g., TCP).
+** This class hides (makes private) the functions that are not applicable
+** to network I/O (i.e., those for file I/O).
+*/
+
+class PR_IMPLEMENT(RCNetStreamIO): public RCIO
+{
+
+public:
+ RCNetStreamIO();
+ virtual ~RCNetStreamIO();
+
+ virtual RCIO* Accept(RCNetAddr* addr, const RCInterval& timeout);
+ virtual PRInt32 AcceptRead(
+ RCIO **nd, RCNetAddr **raddr, void *buf,
+ PRSize amount, const RCInterval& timeout);
+ virtual PRInt64 Available();
+ virtual PRStatus Bind(const RCNetAddr& addr);
+ virtual PRStatus Connect(
+ const RCNetAddr& addr, const RCInterval& timeout);
+ virtual PRStatus GetLocalName(RCNetAddr *addr) const;
+ virtual PRStatus GetPeerName(RCNetAddr *addr) const;
+ virtual PRStatus GetSocketOption(PRSocketOptionData *data) const;
+ virtual PRStatus Listen(PRIntn backlog);
+ virtual PRInt16 Poll(PRInt16 in_flags, PRInt16 *out_flags);
+ virtual PRInt32 Read(void *buf, PRSize amount);
+ virtual PRInt32 Recv(
+ void *buf, PRSize amount, PRIntn flags,
+ const RCInterval& timeout);
+ virtual PRInt32 Recvfrom(
+ void *buf, PRSize amount, PRIntn flags,
+ RCNetAddr* addr, const RCInterval& timeout);
+ virtual PRInt32 Send(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCInterval& timeout);
+ virtual PRInt32 Sendto(
+ const void *buf, PRSize amount, PRIntn flags,
+ const RCNetAddr& addr,
+ const RCInterval& timeout);
+ virtual PRStatus SetSocketOption(const PRSocketOptionData *data);
+ virtual PRStatus Shutdown(ShutdownHow how);
+ virtual PRInt32 TransmitFile(
+ RCIO *source, const void *headers,
+ PRSize hlen, RCIO::FileDisposition flags,
+ const RCInterval& timeout);
+ virtual PRInt32 Write(const void *buf, PRSize amount);
+ virtual PRInt32 Writev(
+ const PRIOVec *iov, PRSize size,
+ const RCInterval& timeout);
+
+private:
+ /* functions unavailable to this clients of this class */
+ RCNetStreamIO(const RCNetStreamIO&);
+
+ PRStatus Close();
+ PRStatus Open(const char *name, PRIntn flags, PRIntn mode);
+ PRStatus FileInfo(RCFileInfo *info) const;
+ PRStatus Fsync();
+ PRInt64 Seek(PRInt64 offset, RCIO::Whence how);
+
+public:
+ RCNetStreamIO(PRIntn protocol);
+}; /* RCNetIO */
+
+#endif /* defined(_RCNETIO_H) */
+
+/* RCNetStreamIO.h */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.cpp
new file mode 100644
index 00000000..10a7ce92
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.cpp
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* RCThread.cpp - C++ wrapper on NSPR */
+
+#include "rcthread.h"
+#include "rcinrval.h"
+
+#include <prmem.h>
+#include <prlog.h>
+#include <stdio.h>
+#include <prinit.h>
+
+static RCPrimordialThread *primordial = NULL;
+
+void nas_Root(void *arg)
+{
+ RCThread *him = (RCThread*)arg;
+ while (RCThread::ex_unstarted == him->execution)
+ (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT); /* wait for Start() */
+ him->RootFunction(); /* he gets a self reference */
+ if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity))
+ delete him;
+} /* nas_Root */
+
+RCThread::~RCThread() { }
+
+RCThread::RCThread(): RCBase() { }
+
+RCThread::RCThread(const RCThread&): RCBase()
+{
+ PR_NOT_REACHED("Cannot call thread copy constructor");
+} /* RCThread::RCThread */
+
+RCThread::RCThread(
+ RCThread::Scope scope, RCThread::State join, PRUint32 stackSize):
+ RCBase()
+{
+ execution = ex_unstarted;
+ identity = PR_CreateThread(
+ PR_USER_THREAD, nas_Root, this,
+ PR_GetThreadPriority(PR_CurrentThread()),
+ (PRThreadScope)scope, (PRThreadState)join, stackSize);
+} /* RCThread::RCThread */
+
+void RCThread::operator=(const RCThread&)
+{
+ PR_NOT_REACHED("Cannot call thread assignment operator");
+} /* RCThread::operator= */
+
+
+PRStatus RCThread::Start()
+{
+ PRStatus rv;
+ /* This is an unsafe check, but not too critical */
+ if (RCThread::ex_unstarted == execution)
+ {
+ execution = RCThread::ex_started;
+ rv = PR_Interrupt(identity);
+ PR_ASSERT(PR_SUCCESS == rv);
+ }
+ else
+ {
+ rv = PR_FAILURE;
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ }
+ return rv;
+} /* RCThread::Start */
+
+PRStatus RCThread::Join()
+{
+ PRStatus rv;
+ if (RCThread::ex_unstarted == execution)
+ {
+ rv = PR_FAILURE;
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ }
+ else rv = PR_JoinThread(identity);
+ if (PR_SUCCESS == rv) delete this;
+ return rv;
+} /* RCThread::Join */
+
+PRStatus RCThread::Interrupt()
+{
+ PRStatus rv;
+ if (RCThread::ex_unstarted == execution)
+ {
+ rv = PR_FAILURE;
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ }
+ else rv = PR_Interrupt(identity);
+ return rv;
+} /* RCThread::Interrupt */
+
+void RCThread::ClearInterrupt() { PR_ClearInterrupt(); }
+
+void RCThread::SetPriority(RCThread::Priority new_priority)
+ { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); }
+
+PRThread *RCThread::Self()
+ { return PR_CurrentThread(); }
+
+RCThread::Scope RCThread::GetScope() const
+ { return (RCThread::Scope)PR_GetThreadScope(identity); }
+
+RCThread::State RCThread::GetState() const
+ { return (RCThread::State)PR_GetThreadState(identity); }
+
+RCThread::Priority RCThread::GetPriority() const
+ { return (RCThread::Priority)PR_GetThreadPriority(identity); }
+
+static void _rc_PDDestructor(RCThreadPrivateData* privateData)
+{
+ PR_ASSERT(NULL != privateData);
+ privateData->Release();
+}
+
+static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor;
+
+PRStatus RCThread::NewPrivateIndex(PRUintn* index)
+ { return PR_NewThreadPrivateIndex(index, _tpd_dtor); }
+
+PRStatus RCThread::SetPrivateData(PRUintn index)
+ { return PR_SetThreadPrivate(index, NULL); }
+
+PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data)
+{
+ return PR_SetThreadPrivate(index, data);
+}
+
+RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index)
+ { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); }
+
+PRStatus RCThread::Sleep(const RCInterval& ticks)
+ { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); }
+
+RCPrimordialThread *RCThread::WrapPrimordialThread()
+{
+ /*
+ ** This needs to take more care in insuring that the thread
+ ** being wrapped is really the primordial thread. This code
+ ** is assuming that the caller is the primordial thread, and
+ ** there's nothing to insure that.
+ */
+ if (NULL == primordial)
+ {
+ /* it doesn't have to be perfect */
+ RCPrimordialThread *me = new RCPrimordialThread();
+ PR_ASSERT(NULL != me);
+ if (NULL == primordial)
+ {
+ primordial = me;
+ me->execution = RCThread::ex_started;
+ me->identity = PR_GetCurrentThread();
+ }
+ else delete me; /* somebody beat us to it */
+ }
+ return primordial;
+} /* RCThread::WrapPrimordialThread */
+
+RCPrimordialThread::RCPrimordialThread(): RCThread() { }
+
+RCPrimordialThread::~RCPrimordialThread() { }
+
+void RCPrimordialThread::RootFunction()
+{
+ PR_NOT_REACHED("Primordial thread calling root function");
+} /* RCPrimordialThread::RootFunction */
+
+PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); }
+
+PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count)
+{
+ PR_SetConcurrency(count);
+ return PR_SUCCESS;
+} /* SetVirutalProcessors */
+
+RCThreadPrivateData::RCThreadPrivateData() { }
+
+RCThreadPrivateData::RCThreadPrivateData(
+ const RCThreadPrivateData& him) { }
+
+RCThreadPrivateData::~RCThreadPrivateData() { }
+
+/* RCThread.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.h
new file mode 100644
index 00000000..2b000564
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rcthread.h
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* RCThread.h */
+
+#if defined(_RCTHREAD_H)
+#else
+#define _RCTHREAD_H
+
+#include "rcbase.h"
+
+#include <prthread.h>
+
+class RCInterval;
+
+class PR_IMPLEMENT(RCThreadPrivateData)
+{
+public:
+ RCThreadPrivateData();
+ RCThreadPrivateData(const RCThreadPrivateData&);
+
+ virtual ~RCThreadPrivateData();
+
+ virtual void Release() = 0;
+
+}; /* RCThreadPrivateData */
+
+class PR_IMPLEMENT(RCThread): public RCBase
+{
+public:
+
+ typedef enum
+ {
+ local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD
+ } Scope;
+
+ typedef enum
+ {
+ joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD
+ } State;
+
+ typedef enum
+ {
+ first = PR_PRIORITY_FIRST,
+ low = PR_PRIORITY_LOW,
+ normal = PR_PRIORITY_NORMAL,
+ high = PR_PRIORITY_HIGH,
+ urgent = PR_PRIORITY_URGENT,
+ last = PR_PRIORITY_LAST
+ } Priority;
+
+ /*
+ * Create a new thread, providing scope and joinability state.
+ */
+ RCThread(Scope scope, State state, PRUint32 stackSize=0);
+
+ /*
+ * New threads are created in a suspended state. It must be 'started"
+ * before it begins execution in the class' defined 'RootFunction()'.
+ */
+ virtual PRStatus Start();
+
+ /*
+ * If a thread is created joinable, then the thread's object exists
+ * until join is called. The thread that calls join will block until
+ * the target thread returns from it's root function.
+ */
+ virtual PRStatus Join();
+
+ /*
+ * The priority of a newly created thread is the same as the creator.
+ * The priority may be changed either by the new thread itself, by
+ * the creator or any other arbitrary thread.
+ */
+ virtual void SetPriority(Priority newPriority);
+
+
+ /*
+ * Interrupt another thread, causing it to stop what it
+ * is doing and return with a well known error code.
+ */
+ virtual PRStatus Interrupt();
+
+ /*
+ * And in case a thread was interrupted and didn't get a chance
+ * to have the notification delivered, a way to cancel the pending
+ * status.
+ */
+ static void ClearInterrupt();
+
+ /*
+ * Methods to discover the attributes of an existing thread.
+ */
+ static PRThread *Self();
+ Scope GetScope() const;
+ State GetState() const;
+ Priority GetPriority() const;
+
+ /*
+ * Thread private data
+ */
+ static PRStatus NewPrivateIndex(PRUintn* index);
+
+ /*
+ * Getting it - if you want to modify, make a copy
+ */
+ static RCThreadPrivateData* GetPrivateData(PRUintn index);
+
+ /*
+ * Setting it to <empty> - deletes existing data
+ */
+ static PRStatus SetPrivateData(PRUintn index);
+
+ /*
+ * Setting it - runtime will make a copy, freeing old iff necessary
+ */
+ static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data);
+
+ /*
+ * Scheduling control
+ */
+ static PRStatus Sleep(const RCInterval& ticks);
+
+ friend void nas_Root(void*);
+ friend class RCPrimordialThread;
+protected:
+
+ /*
+ * The instantiator of a class must not call the destructor. The base
+ * implementation of Join will, and if the thread is created unjoinable,
+ * then the code that called the RootFunction will call the desctructor.
+ */
+ virtual ~RCThread();
+
+private:
+
+ /*
+ * This is where a newly created thread begins execution. Returning
+ * from this function is equivalent to terminating the thread.
+ */
+ virtual void RootFunction() = 0;
+
+ PRThread *identity;
+
+ /* Threads are unstarted until started - pretty startling */
+ enum {ex_unstarted, ex_started} execution;
+
+ /* There is no public default constructor or copy constructor */
+ RCThread();
+ RCThread(const RCThread&);
+
+ /* And there is no assignment operator */
+ void operator=(const RCThread&);
+
+public:
+ static RCPrimordialThread *WrapPrimordialThread();
+
+ };
+
+/*
+** class RCPrimordialThread
+*/
+class PR_IMPLEMENT(RCPrimordialThread): public RCThread
+{
+public:
+ /*
+ ** The primordial thread can (optionally) wait for all created
+ ** threads to terminate before allowing the process to exit.
+ ** Not calling Cleanup() before returning from main() will cause
+ ** the immediate termination of the entire process, including
+ ** any running threads.
+ */
+ static PRStatus Cleanup();
+
+ /*
+ ** Only the primordial thread is allowed to adjust the number of
+ ** virtual processors of the runtime. It's a lame security thing.
+ */
+ static PRStatus SetVirtualProcessors(PRIntn count=10);
+
+friend class RCThread;
+private:
+ /*
+ ** None other than the runtime can create of destruct
+ ** a primordial thread. It is fabricated by the runtime
+ ** to wrap the thread that initiated the application.
+ */
+ RCPrimordialThread();
+ ~RCPrimordialThread();
+ void RootFunction();
+}; /* RCPrimordialThread */
+
+ #endif /* defined(_RCTHREAD_H) */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.cpp
new file mode 100644
index 00000000..6f02b413
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.cpp
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Class implementation for calendar time routines (ref: prtime.h)
+*/
+
+#include "rctime.h"
+
+RCTime::~RCTime() { }
+
+RCTime::RCTime(PRTime time): RCBase() { gmt = time; }
+RCTime::RCTime(const RCTime& his): RCBase() { gmt = his.gmt; }
+RCTime::RCTime(RCTime::Current): RCBase() { gmt = PR_Now(); }
+RCTime::RCTime(const PRExplodedTime& time): RCBase()
+{ gmt = PR_ImplodeTime(&time); }
+
+void RCTime::operator=(const PRExplodedTime& time)
+{ gmt = PR_ImplodeTime(&time); }
+
+RCTime RCTime::operator+(const RCTime& his)
+{ RCTime sum(gmt + his.gmt); return sum; }
+
+RCTime RCTime::operator-(const RCTime& his)
+{ RCTime difference(gmt - his.gmt); return difference; }
+
+RCTime RCTime::operator/(PRUint64 his)
+{ RCTime quotient(gmt / his); return quotient; }
+
+RCTime RCTime::operator*(PRUint64 his)
+{ RCTime product(gmt * his); return product; }
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.h b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.h
new file mode 100644
index 00000000..f0b900a2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/rctime.h
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Class definitions for calendar time routines (ref: prtime.h)
+*/
+
+#if defined(_RCTIME_H)
+#else
+#define _RCTIME_H
+
+#include "rcbase.h"
+
+#include <prtime.h>
+
+/*
+** Class: RCTime (ref: prtime.h)
+**
+** RCTimes are objects that are intended to be used to represent calendar
+** times. They maintain units internally as microseconds since the defined
+** epoch (midnight, January 1, 1970, GMT). Conversions to and from external
+** formats (PRExplodedTime) are available.
+**
+** In general, NCTimes possess normal algebretic capabilities.
+*/
+
+class PR_IMPLEMENT(RCTime): public RCBase
+{
+public:
+ typedef enum {now} Current;
+
+ RCTime(); /* leaves the object unitialized */
+ RCTime(Current); /* initializes to current system time */
+ RCTime(const RCTime&); /* copy constructor */
+ RCTime(const PRExplodedTime&); /* construction from exploded representation */
+
+ virtual ~RCTime();
+
+ /* assignment operators */
+ void operator=(const RCTime&);
+ void operator=(const PRExplodedTime&);
+
+ /* comparitive operators */
+ PRBool operator<(const RCTime&);
+ PRBool operator>(const RCTime&);
+ PRBool operator<=(const RCTime&);
+ PRBool operator>=(const RCTime&);
+ PRBool operator==(const RCTime&);
+
+ /* associative operators */
+ RCTime operator+(const RCTime&);
+ RCTime operator-(const RCTime&);
+ RCTime& operator+=(const RCTime&);
+ RCTime& operator-=(const RCTime&);
+
+ /* multiply and divide operators */
+ RCTime operator/(PRUint64);
+ RCTime operator*(PRUint64);
+ RCTime& operator/=(PRUint64);
+ RCTime& operator*=(PRUint64);
+
+ void Now(); /* assign current time to object */
+
+private:
+ PRTime gmt;
+
+public:
+
+ RCTime(PRTime); /* construct from raw PRTime */
+ void operator=(PRTime); /* assign from raw PRTime */
+ operator PRTime() const; /* extract internal representation */
+}; /* RCTime */
+
+inline RCTime::RCTime(): RCBase() { }
+
+inline void RCTime::Now() { gmt = PR_Now(); }
+inline RCTime::operator PRTime() const { return gmt; }
+
+inline void RCTime::operator=(PRTime his) { gmt = his; }
+inline void RCTime::operator=(const RCTime& his) { gmt = his.gmt; }
+
+inline PRBool RCTime::operator<(const RCTime& his)
+ { return (gmt < his.gmt) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCTime::operator>(const RCTime& his)
+ { return (gmt > his.gmt) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCTime::operator<=(const RCTime& his)
+ { return (gmt <= his.gmt) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCTime::operator>=(const RCTime& his)
+ { return (gmt >= his.gmt) ? PR_TRUE : PR_FALSE; }
+inline PRBool RCTime::operator==(const RCTime& his)
+ { return (gmt == his.gmt) ? PR_TRUE : PR_FALSE; }
+
+inline RCTime& RCTime::operator+=(const RCTime& his)
+ { gmt += his.gmt; return *this; }
+inline RCTime& RCTime::operator-=(const RCTime& his)
+ { gmt -= his.gmt; return *this; }
+inline RCTime& RCTime::operator/=(PRUint64 his)
+ { gmt /= his; return *this; }
+inline RCTime& RCTime::operator*=(PRUint64 his)
+ { gmt *= his; return *this; }
+
+#endif /* defined(_RCTIME_H) */
+
+/* RCTime.h */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/Makefile.in
new file mode 100644
index 00000000..e786d585
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/Makefile.in
@@ -0,0 +1,288 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_TARGET), WIN16)
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+endif
+
+CXXSRCS = \
+ ranfile.cpp \
+ thread.cpp \
+ interval.cpp \
+ time.cpp \
+ fileio.cpp \
+ switch.cpp \
+ tpd.cpp \
+ $(NULL)
+
+OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX)))
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CXXSRCS:.cpp=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS) $(OBJS)
+
+INCLUDES = -I.. -I$(dist_includedir)
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+LIBPR = -lnspr$(MOD_MAJOR_VERSION)
+LIBPL = -lplc$(MOD_MAJOR_VERSION)
+
+ifeq ($(OS_ARCH), IRIX)
+ LDOPTS += -rpath $(PWD)/$(dist_libdir) -rdata_shared
+ # For 6.x machines, include this flag
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ifeq ($(USE_N32),1)
+ LDOPTS += -n32
+ else
+ LDOPTS += -32
+ endif
+
+ ifeq ($(USE_PTHREADS), 1)
+ ifeq ($(OS_RELEASE), 6.2)
+ LDOPTS += -Wl,-woff,85
+ endif
+ endif
+ endif
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ ifneq ($(OS_RELEASE), 4.1.3_U1)
+ ifdef NS_USE_GCC
+ LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+ else
+ LDOPTS += -R $(PWD)/$(dist_libdir)
+ endif
+ endif
+
+ ifneq ($(LOCAL_THREADS_ONLY),1)
+# SunOS 5.4 and 5.5 need to link with -lthread or -lpthread,
+# even though we already linked with these system libraries
+# when we built libnspr.so.
+ ifeq ($(OS_RELEASE), 5.4)
+ EXTRA_LIBS = -lthread
+ endif
+
+ ifeq ($(OS_RELEASE), 5.5)
+ ifdef USE_PTHREADS
+ EXTRA_LIBS = -lpthread
+ else
+ EXTRA_LIBS = -lthread
+ endif
+ endif
+ endif # LOCAL_THREADS_ONLY
+endif # SunOS
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+ LIBPL = $(dist_libdir)/plc$(MOD_MAJOR_VERSION).lib
+else
+ LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+ LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+ LIBPL = $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)
+endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO
+ LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+ LIBPLC = $(dist_libdir)/plc$(MOD_MAJOR_VERSION).lib
+ else
+ LDOPTS += -Zomf -Zlinker /PM:VIO -lstdcpp
+ endif
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), OSF1)
+LDOPTS += -rpath $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+ LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+ LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+ ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+ LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr
+ LIBPLC = -lplc$(MOD_MAJOR_VERSION)_shr
+ else
+ LDOPTS += -brtl
+ EXTRA_LIBS = -ldl
+ endif
+endif
+
+ifeq ($(OS_ARCH), Linux)
+ ifeq ($(OS_RELEASE), 1.2)
+ EXTRA_LIBS = -ldl
+ else
+ LDOPTS += -Xlinker -rpath $(PWD)/$(dist_libdir)
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), NCR)
+# XXX: We see some strange problems when we link with libnspr.so.
+# So for now we use static libraries on NCR. The shared library
+# stuff below is commented out.
+LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+LIBPL = $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).a
+EXTRA_LIBS = -lsocket -lnsl -ldl
+
+# NCR needs to link against -lsocket -lnsl (and -lc, which is linked
+# implicitly by $(CC)) again even though we already linked with these
+# system libraries when we built libnspr.so.
+#EXTRA_LIBS = -lsocket -lnsl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+#export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), SCO_SV)
+# SCO Unix needs to link against -lsocket again even though we
+# already linked with these system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET),WIN16)
+ echo system windows >w16link
+ echo option map >>w16link
+ echo option stack=10K >>w16link
+ echo option heapsize=32K >>w16link
+ echo debug $(DEBUGTYPE) all >>w16link
+ echo name $@ >>w16link
+ echo file >>w16link
+ echo $< >>w16link
+ echo library >>w16link
+ echo $(LIBPR), >>w16link
+ echo $(LIBPL), >>w16link
+ echo winsock.lib >>w16link
+ wlink @w16link.
+else
+ link $(LDOPTS) $< $(LIBPR) $(LIBPL) wsock32.lib -out:$@
+endif
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(LDOPTS) $< $(LIBGC) $(LIBPLC) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS) -o $@
+else
+ $(CCC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPL) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/fileio.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/fileio.cpp
new file mode 100644
index 00000000..a01ea5eb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/fileio.cpp
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* fileio.cpp - a test program */
+
+#include "rcfileio.h"
+
+#include <prlog.h>
+#include <prprf.h>
+
+#define DEFAULT_ITERATIONS 100
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ RCFileIO fd;
+ RCFileInfo info;
+ rv = fd.Open("filio.dat", PR_CREATE_FILE, 0666);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = fd.FileInfo(&info);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = fd.Delete("filio.dat");
+ PR_ASSERT(PR_SUCCESS == rv);
+ fd.Close();
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ return 0;
+} /* main */
+
+/* interval.cpp */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/interval.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/interval.cpp
new file mode 100644
index 00000000..1223d67a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/interval.cpp
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* interval.cpp - a test program */
+
+#include "rclock.h"
+#include "rcthread.h"
+#include "rcinrval.h"
+#include "rccv.h"
+
+#include <prio.h>
+#include <prlog.h>
+#include <prprf.h>
+
+#define DEFAULT_ITERATIONS 100
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ RCLock ml;
+ PRStatus rv;
+ RCCondition cv(&ml);
+
+ RCInterval now, timeout, epoch, elapsed;
+ PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput);
+ PRIntn msecs, seconds, loops, iterations = DEFAULT_ITERATIONS;
+
+ /* slow, agonizing waits */
+ for (seconds = 0; seconds < 10; ++seconds)
+ {
+ timeout = RCInterval::FromSeconds(seconds);
+ cv.SetTimeout(timeout);
+ {
+ RCEnter lock(&ml);
+
+ epoch.SetToNow();
+
+ rv = cv.Wait();
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ now = RCInterval(RCInterval::now);
+ elapsed = now - epoch;
+ }
+
+ PR_fprintf(
+ output, "Waiting %u seconds took %s%u milliseconds\n",
+ seconds, ((elapsed < timeout)? "**" : ""),
+ elapsed.ToMilliseconds());
+ }
+
+ /* more slow, agonizing sleeps */
+ for (seconds = 0; seconds < 10; ++seconds)
+ {
+ timeout = RCInterval::FromSeconds(seconds);
+ {
+ epoch.SetToNow();
+
+ rv = RCThread::Sleep(timeout);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ now = RCInterval(RCInterval::now);
+ elapsed = now - epoch;
+ }
+
+ PR_fprintf(
+ output, "Sleeping %u seconds took %s%u milliseconds\n",
+ seconds, ((elapsed < timeout)? "**" : ""),
+ elapsed.ToMilliseconds());
+ }
+
+ /* fast, spritely little devils */
+ for (msecs = 10; msecs < 100; msecs += 10)
+ {
+ timeout = RCInterval::FromMilliseconds(msecs);
+ cv.SetTimeout(timeout);
+ {
+ RCEnter lock(&ml);
+
+ epoch.SetToNow();
+
+ for (loops = 0; loops < iterations; ++loops)
+ {
+ rv = cv.Wait();
+ PR_ASSERT(PR_SUCCESS == rv);
+ }
+
+ now = RCInterval(RCInterval::now);
+ elapsed = now - epoch;
+ }
+ elapsed /= iterations;
+
+ PR_fprintf(
+ output, "Waiting %u msecs took %s%u milliseconds average\n",
+ msecs, ((elapsed < timeout)? "**" : ""), elapsed.ToMilliseconds());
+ }
+ return 0;
+} /* main */
+
+/* interval.cpp */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/ranfile.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/ranfile.cpp
new file mode 100644
index 00000000..b745b15c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/ranfile.cpp
@@ -0,0 +1,432 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Contact: AOF<mailto:freier@netscape.com>
+**
+** Name: ranfile.c
+**
+** Description: Test to hammer on various components of NSPR
+** Modification History:
+** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include <plgetopt.h>
+#include <prprf.h>
+#include <prio.h>
+
+#include "rccv.h"
+#include "rcthread.h"
+#include "rcfileio.h"
+#include "rclock.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static PRFileDesc *output;
+static PRIntn debug_mode = 0;
+static PRIntn failed_already = 0;
+
+class HammerData
+{
+public:
+ typedef enum {
+ sg_go, sg_stop, sg_done} Action;
+ typedef enum {
+ sg_okay, sg_open, sg_close, sg_delete, sg_write, sg_seek} Problem;
+
+ virtual ~HammerData();
+ HammerData(RCLock* lock, RCCondition *cond, PRUint32 clip);
+ virtual PRUint32 Random();
+
+ Action action;
+ Problem problem;
+ PRUint32 writes;
+ RCInterval timein;
+friend class Hammer;
+private:
+ RCLock *ml;
+ RCCondition *cv;
+ PRUint32 limit;
+
+ PRFloat64 seed;
+}; /* HammerData */
+
+class Hammer: public HammerData, public RCThread
+{
+public:
+ virtual ~Hammer();
+ Hammer(RCThread::Scope scope, RCLock* lock, RCCondition *cond, PRUint32 clip);
+
+private:
+ void RootFunction();
+
+};
+
+static PRInt32 pageSize = 1024;
+static const char* baseName = "./";
+static const char *programName = "Random File";
+
+/***********************************************************************
+** PRIVATE FUNCTION: Random
+** DESCRIPTION:
+** Generate a pseudo-random number
+** INPUTS: None
+** OUTPUTS: None
+** RETURN: A pseudo-random unsigned number, 32-bits wide
+** SIDE EFFECTS:
+** Updates random seed (a static)
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM:
+** Uses the current interval timer value, promoted to a 64 bit
+** float as a multiplier for a static residue (which begins
+** as an uninitialized variable). The result is bits [16..48)
+** of the product. Seed is then updated with the return value
+** promoted to a float-64.
+***********************************************************************/
+PRUint32 HammerData::Random()
+{
+ PRUint32 rv;
+ PRUint64 shift;
+ RCInterval now = RCInterval(RCInterval::now);
+ PRFloat64 random = seed * (PRFloat64)((PRIntervalTime)now);
+ LL_USHR(shift, *((PRUint64*)&random), 16);
+ LL_L2UI(rv, shift);
+ seed = (PRFloat64)rv;
+ return rv;
+} /* HammerData::Random */
+
+Hammer::~Hammer() { }
+
+Hammer::Hammer(
+ RCThread::Scope scope, RCLock* lock, RCCondition *cond, PRUint32 clip):
+ HammerData(lock, cond, clip), RCThread(scope, RCThread::joinable, 0) { }
+
+HammerData::~HammerData() { }
+
+HammerData::HammerData(RCLock* lock, RCCondition *cond, PRUint32 clip)
+{
+ ml = lock;
+ cv = cond;
+ writes = 0;
+ limit = clip;
+ seed = 0x58a9382;
+ action = HammerData::sg_go;
+ problem = HammerData::sg_okay;
+ timein = RCInterval(RCInterval::now);
+} /* HammerData::HammerData */
+
+
+/***********************************************************************
+** PRIVATE FUNCTION: Hammer::RootFunction
+** DESCRIPTION:
+** Hammer on the file I/O system
+** INPUTS: A pointer to the thread's private data
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+** Creates, accesses and deletes a file
+** RESTRICTIONS:
+** (Currently) must have file create permission in "/usr/tmp".
+** MEMORY: NA
+** ALGORITHM:
+** This function is a root of a thread
+** 1) Creates a (hopefully) unique file in /usr/tmp/
+** 2) Writes a zero to a random number of sequential pages
+** 3) Closes the file
+** 4) Reopens the file
+** 5) Seeks to a random page within the file
+** 6) Writes a one byte on that page
+** 7) Repeat steps [5..6] for each page in the file
+** 8) Close and delete the file
+** 9) Repeat steps [1..8] until told to stop
+** 10) Notify complete and return
+***********************************************************************/
+void Hammer::RootFunction()
+{
+ PRUint32 index;
+ RCFileIO file;
+ char filename[30];
+ const char zero = 0;
+ PRStatus rv = PR_SUCCESS;
+
+ limit = (Random() % limit) + 1;
+
+ (void)sprintf(filename, "%ssg%04p.dat", baseName, this);
+
+ if (debug_mode) PR_fprintf(output, "Starting work on %s\n", filename);
+
+ while (PR_TRUE)
+ {
+ PRUint64 bytes;
+ PRUint32 minor = (Random() % limit) + 1;
+ PRUint32 random = (Random() % limit) + 1;
+ PRUint32 pages = (Random() % limit) + 10;
+ while (minor-- > 0)
+ {
+ problem = sg_okay;
+ if (action != sg_go) goto finished;
+ problem = sg_open;
+ rv = file.Open(filename, PR_RDWR|PR_CREATE_FILE, 0666);
+ if (PR_FAILURE == rv) goto finished;
+ for (index = 0; index < pages; index++)
+ {
+ problem = sg_okay;
+ if (action != sg_go) goto close;
+ problem = sg_seek;
+ bytes = file.Seek(pageSize * index, RCFileIO::set);
+ if (bytes != pageSize * index) goto close;
+ problem = sg_write;
+ bytes = file.Write(&zero, sizeof(zero));
+ if (bytes <= 0) goto close;
+ writes += 1;
+ }
+ problem = sg_close;
+ rv = file.Close();
+ if (rv != PR_SUCCESS) goto purge;
+
+ problem = sg_okay;
+ if (action != sg_go) goto purge;
+
+ problem = sg_open;
+ rv = file.Open(filename, PR_RDWR, 0666);
+ if (PR_FAILURE == rv) goto finished;
+ for (index = 0; index < pages; index++)
+ {
+ problem = sg_okay;
+ if (action != sg_go) goto close;
+ problem = sg_seek;
+ bytes = file.Seek(pageSize * index, RCFileIO::set);
+ if (bytes != pageSize * index) goto close;
+ problem = sg_write;
+ bytes = file.Write(&zero, sizeof(zero));
+ if (bytes <= 0) goto close;
+ writes += 1;
+ random = (random + 511) % pages;
+ }
+ problem = sg_close;
+ rv = file.Close();
+ if (rv != PR_SUCCESS) goto purge;
+ problem = sg_delete;
+ rv = file.Delete(filename);
+ if (rv != PR_SUCCESS) goto finished;
+ }
+ }
+
+close:
+ (void)file.Close();
+purge:
+ (void)file.Delete(filename);
+finished:
+ RCEnter scope(ml);
+ action = HammerData::sg_done;
+ cv->Notify();
+
+ if (debug_mode) PR_fprintf(output, "Ending work on %s\n", filename);
+
+ return;
+} /* Hammer::RootFunction */
+
+static Hammer* hammer[100];
+/***********************************************************************
+** PRIVATE FUNCTION: main
+** DESCRIPTION:
+** Hammer on the file I/O system
+** INPUTS: The usual argc and argv
+** argv[0] - program name (not used)
+** argv[1] - the number of virtual_procs to execute the major loop
+** argv[2] - the number of threads to toss into the batch
+** argv[3] - the clipping number applied to randoms
+** default values: max_virtual_procs = 2, threads = 10, limit = 57
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+** Creates, accesses and deletes lots of files
+** RESTRICTIONS:
+** (Currently) must have file create permission in "/usr/tmp".
+** MEMORY: NA
+** ALGORITHM:
+** 1) Fork a "Thread()"
+** 2) Wait for 'interleave' seconds
+** 3) For [0..'threads') repeat [1..2]
+** 4) Mark all objects to stop
+** 5) Collect the threads, accumulating the results
+** 6) For [0..'max_virtual_procs') repeat [1..5]
+** 7) Print accumulated results and exit
+**
+** Characteristic output (from IRIX)
+** Random File: Using max_virtual_procs = 2, threads = 10, limit = 57
+** Random File: [min [avg] max] writes/sec average
+***********************************************************************/
+PRIntn main (PRIntn argc, char *argv[])
+{
+ RCLock ml;
+ PLOptStatus os;
+ RCCondition cv(&ml);
+ PRUint32 writesMax = 0, durationTot = 0;
+ RCThread::Scope thread_scope = RCThread::local;
+ PRUint32 writes, writesMin = 0x7fffffff, writesTot = 0;
+ PRIntn active, poll, limit = 0, max_virtual_procs = 0, threads = 0, virtual_procs;
+ RCInterval interleave(RCInterval::FromMilliseconds(10000)), duration(0);
+
+ const char *where[] = {"okay", "open", "close", "delete", "write", "seek"};
+
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:t:i:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0:
+ baseName = opt->value;
+ break;
+ case 'G': /* global threads */
+ thread_scope = RCThread::global;
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'l': /* limiting number */
+ limit = atoi(opt->value);
+ break;
+ case 't': /* number of threads */
+ threads = atoi(opt->value);
+ break;
+ case 'i': /* iteration counter */
+ max_virtual_procs = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ output = PR_GetSpecialFD(PR_StandardOutput);
+
+ /* main test */
+
+ cv.SetTimeout(interleave);
+
+ if (max_virtual_procs == 0) max_virtual_procs = 2;
+ if (limit == 0) limit = 57;
+ if (threads == 0) threads = 10;
+
+ if (debug_mode) PR_fprintf(output,
+ "%s: Using %d virtual processors, %d threads, limit = %d and %s threads\n",
+ programName, max_virtual_procs, threads, limit,
+ (thread_scope == RCThread::local) ? "LOCAL" : "GLOBAL");
+
+ for (virtual_procs = 0; virtual_procs < max_virtual_procs; ++virtual_procs)
+ {
+ if (debug_mode)
+ PR_fprintf(output,
+ "%s: Setting number of virtual processors to %d\n",
+ programName, virtual_procs + 1);
+ RCPrimordialThread::SetVirtualProcessors(virtual_procs + 1);
+ for (active = 0; active < threads; active++)
+ {
+ hammer[active] = new Hammer(thread_scope, &ml, &cv, limit);
+ hammer[active]->Start(); /* then make it roll */
+ RCThread::Sleep(interleave); /* start them slowly */
+ }
+
+ /*
+ * The last thread started has had the opportunity to run for
+ * 'interleave' seconds. Now gather them all back in.
+ */
+ {
+ RCEnter scope(&ml);
+ for (poll = 0; poll < threads; poll++)
+ {
+ if (hammer[poll]->action == HammerData::sg_go) /* don't overwrite done */
+ hammer[poll]->action = HammerData::sg_stop; /* ask him to stop */
+ }
+ }
+
+ while (active > 0)
+ {
+ for (poll = 0; poll < threads; poll++)
+ {
+ ml.Acquire();
+ while (hammer[poll]->action < HammerData::sg_done) cv.Wait();
+ ml.Release();
+
+ if (hammer[poll]->problem == HammerData::sg_okay)
+ {
+ duration = RCInterval(RCInterval::now) - hammer[poll]->timein;
+ writes = hammer[poll]->writes * 1000 / duration;
+ if (writes < writesMin) writesMin = writes;
+ if (writes > writesMax) writesMax = writes;
+ writesTot += hammer[poll]->writes;
+ durationTot += duration;
+ }
+ else
+ {
+ if (debug_mode) PR_fprintf(output,
+ "%s: test failed %s after %ld seconds\n",
+ programName, where[hammer[poll]->problem], duration);
+ else failed_already=1;
+ }
+ active -= 1; /* this is another one down */
+ (void)hammer[poll]->Join();
+ hammer[poll] = NULL;
+ }
+ }
+ if (debug_mode) PR_fprintf(output,
+ "%s: [%ld [%ld] %ld] writes/sec average\n",
+ programName, writesMin,
+ writesTot * 1000 / durationTot, writesMax);
+ }
+
+ failed_already |= (PR_FAILURE == RCPrimordialThread::Cleanup());
+ PR_fprintf(output, "%s\n", (failed_already) ? "FAIL\n" : "PASS\n");
+ return failed_already;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/switch.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/switch.cpp
new file mode 100644
index 00000000..fddc5808
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/switch.cpp
@@ -0,0 +1,266 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: switch.cpp
+** Description: trying to time context switches
+*/
+
+#include "rccv.h"
+#include "rcinrval.h"
+#include "rclock.h"
+#include "rcthread.h"
+
+#include <prio.h>
+#include <prlog.h>
+#include <prprf.h>
+#include <plerror.h>
+#include <plgetopt.h>
+
+#include <stdlib.h>
+
+#define INNER_LOOPS 100
+#define DEFAULT_LOOPS 100
+#define DEFAULT_THREADS 10
+
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE, verbosity = PR_FALSE, failed = PR_FALSE;
+
+class Home: public RCCondition
+{
+public:
+ virtual ~Home();
+ Home(Home *link, RCLock* ml);
+
+public:
+ Home *next;
+ RCLock* ml;
+ PRBool twiddle;
+}; /* Home */
+
+Home::~Home() { }
+
+Home::Home(Home *link, RCLock* lock): RCCondition(lock)
+{
+ ml = lock;
+ next = link;
+ twiddle = PR_FALSE;
+} /* Home::Home */
+
+class Shared: public Home, public RCThread
+{
+public:
+ Shared(RCThread::Scope scope, Home* link, RCLock* ml);
+
+private:
+ ~Shared();
+ void RootFunction();
+}; /* Shared */
+
+Shared::Shared(RCThread::Scope scope, Home* link, RCLock* lock):
+ Home(link, lock), RCThread(scope, RCThread::joinable) { }
+
+Shared::~Shared() { }
+
+void Shared::RootFunction()
+{
+ PRStatus status = PR_SUCCESS;
+ while (PR_SUCCESS == status)
+ {
+ RCEnter entry(ml);
+ while (twiddle && (PR_SUCCESS == status)) status = Wait();
+ if (verbosity) PR_fprintf(debug_out, "+");
+ twiddle = PR_TRUE;
+ next->twiddle = PR_FALSE;
+ next->Notify();
+ }
+} /* Shared::RootFunction */
+
+static void Help(void)
+{
+ debug_out = PR_STDOUT;
+
+ PR_fprintf(
+ debug_out, "Usage: >./switch [-d] [-c n] [-t n] [-T n] [-G]\n");
+ PR_fprintf(
+ debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
+ PR_fprintf(
+ debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
+ PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G n\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
+} /* Help */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ PRStatus status;
+ PRBool help = PR_FALSE;
+ PRUintn concurrency = 1;
+ RCThread::Scope thread_scope = RCThread::local;
+ PRUintn thread_count, inner_count, loop_count, average;
+ PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* verbose mode */
+ verbosity = PR_TRUE;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop counter */
+ loop_limit = atoi(opt->value);
+ break;
+ case 't': /* thread limit */
+ thread_limit = atoi(opt->value);
+ break;
+ case 'C': /* Concurrency limit */
+ concurrency = atoi(opt->value);
+ break;
+ case 'G': /* global threads only */
+ thread_scope = RCThread::global;
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (help) return -1;
+
+ if (PR_TRUE == debug_mode)
+ {
+ debug_out = PR_STDOUT;
+ PR_fprintf(debug_out, "Test parameters\n");
+ PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit);
+ PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit);
+ PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
+ PR_fprintf(
+ debug_out, "\tThread type: %s\n",
+ (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
+ }
+
+ /*
+ ** The interesting part starts here
+ */
+ RCLock lock;
+ Shared* shared;
+ Home home(NULL, &lock);
+ Home* link = &home;
+ RCInterval timein, timeout = 0;
+
+ /* Build up the string of objects */
+ for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
+ {
+ shared = new Shared(thread_scope, link, &lock);
+ shared->Start(); /* make it run */
+ link = (Home*)shared;
+ }
+
+ /* Pass the message around the horn a few times */
+ for (loop_count = 1; loop_count <= loop_limit; ++loop_count)
+ {
+ timein.SetToNow();
+ for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count)
+ {
+ RCEnter entry(&lock);
+ home.twiddle = PR_TRUE;
+ shared->twiddle = PR_FALSE;
+ shared->Notify();
+ while (home.twiddle)
+ {
+ failed = (PR_FAILURE == home.Wait()) ? PR_TRUE : PR_FALSE;
+ }
+ }
+ timeout += (RCInterval(RCInterval::now) - timein);
+ }
+
+ /* Figure out how well we did */
+ if (debug_mode)
+ {
+ average = timeout.ToMicroseconds()
+ / (INNER_LOOPS * loop_limit * thread_count);
+ PR_fprintf(
+ debug_out, "Average switch times %d usecs for %d threads\n",
+ average, thread_limit);
+ }
+
+ /* Start reclamation process */
+ link = shared;
+ for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
+ {
+ if (&home == link) break;
+ status = ((Shared*)link)->Interrupt();
+ if (PR_SUCCESS != status)
+ {
+ failed = PR_TRUE;
+ if (debug_mode)
+ PL_FPrintError(debug_out, "Failed to interrupt");
+ }
+ link = link->next;
+ }
+
+ for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
+ {
+ link = shared->next;
+ status = shared->Join();
+ if (PR_SUCCESS != status)
+ {
+ failed = PR_TRUE;
+ if (debug_mode)
+ PL_FPrintError(debug_out, "Failed to join");
+ }
+ if (&home == link) break;
+ shared = (Shared*)link;
+ }
+
+ PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n"));
+
+ failed |= (PR_SUCCESS == RCPrimordialThread::Cleanup());
+
+ return ((failed) ? 1 : 0);
+} /* main */
+
+/* switch.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/thread.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/thread.cpp
new file mode 100644
index 00000000..801eee0d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/thread.cpp
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* thread.cpp - a test program */
+
+#include "rcthread.h"
+
+#include <prlog.h>
+
+#include <stdio.h>
+
+class TestThread: public RCThread
+{
+public:
+ TestThread(RCThread::State state, PRIntn count);
+
+ virtual void RootFunction();
+
+protected:
+ virtual ~TestThread();
+
+private:
+ PRUint32 mydata;
+};
+
+TestThread::~TestThread() { }
+
+TestThread::TestThread(RCThread::State state, PRIntn count):
+ RCThread(RCThread::global, state, 0) { mydata = count; }
+
+void TestThread::RootFunction()
+{
+ SetPriority(RCThread::high);
+ printf("TestThread::RootFunction %d did it\n", mydata);
+} /* TestThread::RootFunction */
+
+class Foo1
+{
+public:
+ Foo1();
+ virtual ~Foo1();
+
+ TestThread *thread;
+ PRIntn data;
+};
+
+Foo1::Foo1()
+{
+ data = 0xafaf;
+ thread = new TestThread(RCThread::joinable, 0xafaf);
+ thread->Start();
+}
+
+Foo1::~Foo1()
+{
+ PRStatus rv = thread->Join();
+ PR_ASSERT(PR_SUCCESS == rv);
+} /* Foo1::~Foo1 */
+
+PRIntn main(PRIntn argc, char **agrv)
+{
+ PRStatus status;
+ PRIntn count = 100;
+ RCThread *thread[10];
+ while (--count > 0)
+ {
+ TestThread *thread = new TestThread(RCThread::joinable, count);
+ status = thread->Start(); /* have to remember to start it */
+ PR_ASSERT(PR_SUCCESS == status);
+ status = thread->Join(); /* this should work */
+ PR_ASSERT(PR_SUCCESS == status);
+ }
+ while (++count < 100)
+ {
+ TestThread *thread = new TestThread(RCThread::unjoinable, count);
+ status = thread->Start(); /* have to remember to start it */
+ PR_ASSERT(PR_SUCCESS == status);
+ }
+
+ {
+ Foo1 *foo1 = new Foo1();
+ PR_ASSERT(NULL != foo1);
+ delete foo1;
+ }
+
+ {
+ for (count = 0; count < 10; ++count)
+ {
+ thread[count] = new TestThread( RCThread::joinable, count);
+ status = thread[count]->Start(); /* have to remember to start it */
+ PR_ASSERT(PR_SUCCESS == status);
+ }
+ for (count = 0; count < 10; ++count)
+ {
+ PRStatus rv = thread[count]->Join();
+ PR_ASSERT(PR_SUCCESS == rv);
+ }
+ }
+
+ (void)RCPrimordialThread::Cleanup();
+
+ return 0;
+} /* main */
+
+/* thread.cpp */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/time.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/time.cpp
new file mode 100644
index 00000000..c0a9c3e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/time.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* time.cpp - a test program */
+
+#include "rctime.h"
+
+#include <prlog.h>
+#include <prprf.h>
+
+#define DEFAULT_ITERATIONS 100
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ RCTime unitialized;
+ RCTime now(PR_Now());
+ RCTime current(RCTime::now);
+ PRTime time = current;
+
+ unitialized = now;
+ now.Now();
+
+ return 0;
+} /* main */
+
+/* time.cpp */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/tpd.cpp b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/tpd.cpp
new file mode 100644
index 00000000..6e3dd953
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/cplus/tests/tpd.cpp
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: tpd.cpp
+** Description: Exercising the thread private data bailywick.
+*/
+
+#include "prlog.h"
+#include "prprf.h"
+#include "rcthread.h"
+
+#include <string.h>
+
+#include "plgetopt.h"
+
+/*
+** class MyThread
+*/
+class MyThread: public RCThread
+{
+public:
+ MyThread();
+
+private:
+ ~MyThread();
+ void RootFunction();
+}; /* MyThread */
+
+/*
+** class MyPrivateData
+*/
+class MyPrivateData: public RCThreadPrivateData
+{
+public:
+ virtual ~MyPrivateData();
+
+ MyPrivateData();
+ MyPrivateData(char*);
+ MyPrivateData(const MyPrivateData&);
+
+ void Release();
+
+private:
+ char *string;
+}; /* MyPrivateData */
+
+static PRUintn key[128];
+static PRIntn debug = 0;
+static PRBool failed = PR_FALSE;
+static PRBool should = PR_TRUE;
+static PRBool did = PR_TRUE;
+static PRFileDesc *fout = NULL;
+
+static void PrintProgress(PRIntn line)
+{
+ failed = failed || (should && !did);
+ failed = failed || (!should && did);
+ if (debug > 0)
+ {
+ PR_fprintf(
+ fout, "@ line %d destructor should %shave been called and was%s\n",
+ line, ((should) ? "" : "NOT "), ((did) ? "" : " NOT"));
+ }
+} /* PrintProgress */
+
+static void MyAssert(const char *expr, const char *file, PRIntn line)
+{
+ if (debug > 0)
+ (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line);
+} /* MyAssert */
+
+#define MY_ASSERT(_expr) \
+ ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__))
+
+int main(PRIntn argc, char *argv[])
+{
+ PRStatus rv;
+ PRUintn keys;
+ MyThread *thread;
+ const RCThreadPrivateData *pd;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ RCThread *primordial = RCThread::WrapPrimordialThread();
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ fout = PR_STDOUT;
+
+ MyPrivateData extension = MyPrivateData("EXTENSION");
+ MyPrivateData key_string[] = {
+ "Key #0", "Key #1", "Key #2", "Key #3",
+ "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
+
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = RCThread::NewPrivateIndex(&key[keys]);
+ key[keys + 4] = key[keys] + 4;
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ /* the first four should be bu null, the last four undefined and null */
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 8; ++keys)
+ {
+ pd = RCThread::GetPrivateData(key[keys]);
+ MY_ASSERT(NULL == pd);
+ }
+ PrintProgress(__LINE__);
+
+ /* initially set private data for new keys */
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ /* re-assign the private data, albeit the same content */
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ pd = RCThread::GetPrivateData(key[keys]);
+ PR_ASSERT(NULL != pd);
+ rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ /* set private to <empty> */
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = RCThread::SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ /* should all be null now */
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ pd = RCThread::GetPrivateData(key[keys]);
+ PR_ASSERT(NULL == pd);
+ }
+ PrintProgress(__LINE__);
+
+ /* allocate another batch of keys and assign data to them */
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = RCThread::NewPrivateIndex(&key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ rv = RCThread::SetPrivateData(key[keys], &extension);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ /* set all the extended slots to <empty> */
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = RCThread::SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ /* set all the extended slots to <empty> again (noop) */
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = RCThread::SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+
+ if (debug) PR_fprintf(fout, "Creating thread\n");
+ thread = new MyThread();
+ if (debug) PR_fprintf(fout, "Starting thread\n");
+ thread->Start();
+ if (debug) PR_fprintf(fout, "Joining thread\n");
+ (void)thread->Join();
+ if (debug) PR_fprintf(fout, "Joined thread\n");
+
+ failed |= (PR_FAILURE == RCPrimordialThread::Cleanup());
+
+ (void)PR_fprintf(
+ fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
+
+ return (failed) ? 1 : 0;
+
+} /* main */
+
+/*
+** class MyPrivateData
+*/
+MyPrivateData::~MyPrivateData()
+{
+ PR_fprintf(
+ fout, "MyPrivateData::~MyPrivateData[%s]\n",
+ (NULL != string) ? string : "NULL");
+} /* MyPrivateData::~MyPrivateData */
+
+MyPrivateData::MyPrivateData(): RCThreadPrivateData()
+{
+ PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n");
+ string = NULL;
+} /* MyPrivateData::MyPrivateData */
+
+MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData()
+{
+ PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n");
+ string = data;
+} /* MyPrivateData:: MyPrivateData */
+
+MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him)
+{
+ PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n");
+ string = him.string;
+} /* MyPrivateData:: MyPrivateData */
+
+void MyPrivateData::Release()
+{
+ if (should) did = PR_TRUE;
+ else failed = PR_TRUE;
+} /* MyPrivateData::operator= */
+
+/*
+** class MyThread
+*/
+MyThread::~MyThread() { }
+MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { }
+
+
+void MyThread::RootFunction()
+{
+ PRStatus rv;
+ PRUintn keys;
+ const RCThreadPrivateData *pd;
+
+ MyPrivateData extension = MyPrivateData("EXTENSION");
+ MyPrivateData key_string[] = {
+ "Key #0", "Key #1", "Key #2", "Key #3",
+ "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 8; ++keys)
+ {
+ pd = GetPrivateData(key[keys]);
+ MY_ASSERT(NULL == pd);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = SetPrivateData(keys, &key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+#if !defined(DEBUG)
+ did = should = PR_FALSE;
+ for (keys = 4; keys < 8; ++keys)
+ {
+ rv = SetPrivateData(keys, &key_string[keys]);
+ MY_ASSERT(PR_FAILURE == rv);
+ }
+ PrintProgress(__LINE__);
+#endif
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = SetPrivateData(key[keys], &key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = SetPrivateData(key[keys], &extension);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = SetPrivateData(key[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+} /* MyThread::RootFunction */
+
+/* tpd.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/io/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/io/Makefile.in
new file mode 100644
index 00000000..40dc6ded
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/Makefile.in
@@ -0,0 +1,97 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OPTIMIZER =
+endif
+endif
+
+CSRCS = \
+ prfdcach.c \
+ prmwait.c \
+ priometh.c \
+ pripv6.c \
+ prmapopt.c \
+ prlayer.c \
+ prlog.c \
+ prmmap.c \
+ prpolevt.c \
+ prprf.c \
+ prscanf.c \
+ prstdio.c \
+ $(NULL)
+
+ifndef USE_PTHREADS
+ CSRCS += \
+ prdir.c \
+ prfile.c \
+ prio.c \
+ prsocket.c \
+ $(NULL)
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+# An OS/2 Optimization bug causes PR_snprintf() to produce wrong result.
+# This suppresses optimization for this single compilation unit.
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+$(OBJDIR)/prprf.obj: prprf.c
+ @$(MAKE_OBJDIR)
+ $(CC) -Fo$@ -c $(filter-out /O+, $(CFLAGS)) $<
+endif
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prdir.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prdir.c
new file mode 100644
index 00000000..8679c9d5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prdir.c
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roy Yokoyama <yokoyama@netscape.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 "primpl.h"
+
+PR_IMPLEMENT(PRDir*) PR_OpenDir(const char *name)
+{
+ PRDir *dir;
+ PRStatus sts;
+
+ dir = PR_NEW(PRDir);
+ if (dir) {
+ sts = _PR_MD_OPEN_DIR(&dir->md,name);
+ if (sts != PR_SUCCESS) {
+ PR_DELETE(dir);
+ return NULL;
+ }
+ } else {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+ return dir;
+}
+
+PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags)
+{
+ /* _MD_READ_DIR return a char* to the name; allocation in machine-dependent code */
+ char* name = _PR_MD_READ_DIR(&dir->md, flags);
+ dir->d.name = name;
+ return name ? &dir->d : NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir)
+{
+PRInt32 rv;
+
+ if (dir) {
+ rv = _PR_MD_CLOSE_DIR(&dir->md);
+ PR_DELETE(dir);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode)
+{
+PRInt32 rv;
+
+ rv = _PR_MD_MKDIR(name, mode);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode)
+{
+PRInt32 rv;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ rv = _PR_MD_MAKE_DIR(name, mode);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name)
+{
+PRInt32 rv;
+
+ rv = _PR_MD_RMDIR(name);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+#ifdef MOZ_UNICODE
+/*
+ * UTF16 Interface
+ */
+PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name)
+{
+ PRDirUTF16 *dir;
+ PRStatus sts;
+
+ dir = PR_NEW(PRDirUTF16);
+ if (dir) {
+ sts = _PR_MD_OPEN_DIR_UTF16(&dir->md,name);
+ if (sts != PR_SUCCESS) {
+ PR_DELETE(dir);
+ return NULL;
+ }
+ } else {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+ return dir;
+}
+
+PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags)
+{
+ /*
+ * _MD_READ_DIR_UTF16 return a PRUnichar* to the name; allocation in
+ * machine-dependent code
+ */
+ PRUnichar* name = _PR_MD_READ_DIR_UTF16(&dir->md, flags);
+ dir->d.name = name;
+ return name ? &dir->d : NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDirUTF16 *dir)
+{
+ PRInt32 rv;
+
+ if (dir) {
+ rv = _PR_MD_CLOSE_DIR_UTF16(&dir->md);
+ PR_DELETE(dir);
+ if (rv < 0)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+ }
+ return PR_SUCCESS;
+}
+
+#endif /* MOZ_UNICODE */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prfdcach.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prfdcach.c
new file mode 100644
index 00000000..aea19dff
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prfdcach.c
@@ -0,0 +1,311 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+
+/*****************************************************************************/
+/*****************************************************************************/
+/************************** File descriptor caching **************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+/*
+** This code is built into debuggable versions of NSPR to assist in
+** finding misused file descriptors. Since file descritors (PRFileDesc)
+** are identified by a pointer to their structure, they can be the
+** target of dangling references. Furthermore, NSPR caches and tries
+** to aggressively reuse file descriptors, leading to more ambiguity.
+** The following code will allow a debugging client to set environment
+** variables and control the number of file descriptors that will be
+** preserved before they are recycled. The environment variables are
+** NSPR_FD_CACHE_SIZE_LOW and NSPR_FD_CACHE_SIZE_HIGH. The former sets
+** the number of descriptors NSPR will allocate before beginning to
+** recycle. The latter is the maximum number permitted in the cache
+** (exclusive of those in use) at a time.
+*/
+typedef struct _PR_Fd_Cache
+{
+ PRLock *ml;
+ PRIntn count;
+ PRStack *stack;
+ PRFileDesc *head, *tail;
+ PRIntn limit_low, limit_high;
+} _PR_Fd_Cache;
+
+static _PR_Fd_Cache _pr_fd_cache;
+static PRFileDesc **stack2fd = &(((PRFileDesc*)NULL)->higher);
+
+
+/*
+** Get a FileDescriptor from the cache if one exists. If not allocate
+** a new one from the heap.
+*/
+PRFileDesc *_PR_Getfd(void)
+{
+ PRFileDesc *fd;
+ /*
+ ** $$$
+ ** This may look a little wasteful. We'll see. Right now I want to
+ ** be able to toggle between caching and not at runtime to measure
+ ** the differences. If it isn't too annoying, I'll leave it in.
+ ** $$$$
+ **
+ ** The test is against _pr_fd_cache.limit_high. If that's zero,
+ ** we're not doing the extended cache but going for performance.
+ */
+ if (0 == _pr_fd_cache.limit_high)
+ {
+ PRStackElem *pop;
+ PR_ASSERT(NULL != _pr_fd_cache.stack);
+ pop = PR_StackPop(_pr_fd_cache.stack);
+ if (NULL == pop) goto allocate;
+ fd = (PRFileDesc*)((PRPtrdiff)pop - (PRPtrdiff)stack2fd);
+ }
+ else
+ {
+ do
+ {
+ if (NULL == _pr_fd_cache.head) goto allocate; /* nothing there */
+ if (_pr_fd_cache.count < _pr_fd_cache.limit_low) goto allocate;
+
+ /* we "should" be able to extract an fd from the cache */
+ PR_Lock(_pr_fd_cache.ml); /* need the lock to do this safely */
+ fd = _pr_fd_cache.head; /* protected extraction */
+ if (NULL == fd) /* unexpected, but not fatal */
+ {
+ PR_ASSERT(0 == _pr_fd_cache.count);
+ PR_ASSERT(NULL == _pr_fd_cache.tail);
+ }
+ else
+ {
+ _pr_fd_cache.count -= 1;
+ _pr_fd_cache.head = fd->higher;
+ if (NULL == _pr_fd_cache.head)
+ {
+ PR_ASSERT(0 == _pr_fd_cache.count);
+ _pr_fd_cache.tail = NULL;
+ }
+ PR_ASSERT(&_pr_faulty_methods == fd->methods);
+ PR_ASSERT(PR_INVALID_IO_LAYER == fd->identity);
+ PR_ASSERT(_PR_FILEDESC_FREED == fd->secret->state);
+ }
+ PR_Unlock(_pr_fd_cache.ml);
+
+ } while (NULL == fd); /* then go around and allocate a new one */
+ }
+
+finished:
+ fd->dtor = NULL;
+ fd->lower = fd->higher = NULL;
+ fd->identity = PR_NSPR_IO_LAYER;
+ memset(fd->secret, 0, sizeof(PRFilePrivate));
+ return fd;
+
+allocate:
+ fd = PR_NEW(PRFileDesc);
+ if (NULL != fd)
+ {
+ fd->secret = PR_NEW(PRFilePrivate);
+ if (NULL == fd->secret) PR_DELETE(fd);
+ }
+ if (NULL != fd) goto finished;
+ else return NULL;
+
+} /* _PR_Getfd */
+
+/*
+** Return a file descriptor to the cache unless there are too many in
+** there already. If put in cache, clear the fields first.
+*/
+void _PR_Putfd(PRFileDesc *fd)
+{
+ PR_ASSERT(PR_NSPR_IO_LAYER == fd->identity);
+ fd->methods = &_pr_faulty_methods;
+ fd->identity = PR_INVALID_IO_LAYER;
+ fd->secret->state = _PR_FILEDESC_FREED;
+
+ if (0 == _pr_fd_cache.limit_high)
+ {
+ PR_StackPush(_pr_fd_cache.stack, (PRStackElem*)(&fd->higher));
+ }
+ else
+ {
+ if (_pr_fd_cache.count > _pr_fd_cache.limit_high)
+ {
+ PR_Free(fd->secret);
+ PR_Free(fd);
+ }
+ else
+ {
+ PR_Lock(_pr_fd_cache.ml);
+ if (NULL == _pr_fd_cache.tail)
+ {
+ PR_ASSERT(0 == _pr_fd_cache.count);
+ PR_ASSERT(NULL == _pr_fd_cache.head);
+ _pr_fd_cache.head = _pr_fd_cache.tail = fd;
+ }
+ else
+ {
+ PR_ASSERT(NULL == _pr_fd_cache.tail->higher);
+ _pr_fd_cache.tail->higher = fd;
+ _pr_fd_cache.tail = fd; /* new value */
+ }
+ fd->higher = NULL; /* always so */
+ _pr_fd_cache.count += 1; /* count the new entry */
+ PR_Unlock(_pr_fd_cache.ml);
+ }
+ }
+} /* _PR_Putfd */
+
+PR_IMPLEMENT(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high)
+{
+ /*
+ ** This can be called at any time, may adjust the cache sizes,
+ ** turn the caches off, or turn them on. It is not dependent
+ ** on the compilation setting of DEBUG.
+ */
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (low > high) low = high; /* sanity check the params */
+
+ PR_Lock(_pr_fd_cache.ml);
+ if (0 == high) /* shutting down or staying down */
+ {
+ if (0 != _pr_fd_cache.limit_high) /* shutting down */
+ {
+ _pr_fd_cache.limit_high = 0; /* stop use */
+ /*
+ ** Hold the lock throughout - nobody's going to want it
+ ** other than another caller to this routine. Just don't
+ ** let that happen.
+ **
+ ** Put all the cached fds onto the new cache.
+ */
+ while (NULL != _pr_fd_cache.head)
+ {
+ PRFileDesc *fd = _pr_fd_cache.head;
+ _pr_fd_cache.head = fd->higher;
+ PR_StackPush(_pr_fd_cache.stack, (PRStackElem*)(&fd->higher));
+ }
+ _pr_fd_cache.limit_low = 0;
+ _pr_fd_cache.tail = NULL;
+ _pr_fd_cache.count = 0;
+ }
+ }
+ else /* starting up or just adjusting parameters */
+ {
+ PRBool was_using_stack = (0 == _pr_fd_cache.limit_high);
+ _pr_fd_cache.limit_low = low;
+ _pr_fd_cache.limit_high = high;
+ if (was_using_stack) /* was using stack - feed into cache */
+ {
+ PRStackElem *pop;
+ while (NULL != (pop = PR_StackPop(_pr_fd_cache.stack)))
+ {
+ PRFileDesc *fd = (PRFileDesc*)
+ ((PRPtrdiff)pop - (PRPtrdiff)stack2fd);
+ if (NULL == _pr_fd_cache.tail) _pr_fd_cache.tail = fd;
+ fd->higher = _pr_fd_cache.head;
+ _pr_fd_cache.head = fd;
+ _pr_fd_cache.count += 1;
+ }
+ }
+ }
+ PR_Unlock(_pr_fd_cache.ml);
+ return PR_SUCCESS;
+} /* PR_SetFDCacheSize */
+
+void _PR_InitFdCache(void)
+{
+ /*
+ ** The fd caching is enabled by default for DEBUG builds,
+ ** disabled by default for OPT builds. That default can
+ ** be overridden at runtime using environment variables
+ ** or a super-wiz-bang API.
+ */
+ const char *low = PR_GetEnv("NSPR_FD_CACHE_SIZE_LOW");
+ const char *high = PR_GetEnv("NSPR_FD_CACHE_SIZE_HIGH");
+
+ /*
+ ** _low is allowed to be zero, _high is not.
+ ** If _high is zero, we're not doing the caching.
+ */
+
+ _pr_fd_cache.limit_low = 0;
+#if defined(DEBUG)
+ _pr_fd_cache.limit_high = FD_SETSIZE;
+#else
+ _pr_fd_cache.limit_high = 0;
+#endif /* defined(DEBUG) */
+
+ if (NULL != low) _pr_fd_cache.limit_low = atoi(low);
+ if (NULL != high) _pr_fd_cache.limit_high = atoi(high);
+
+ if (_pr_fd_cache.limit_high < _pr_fd_cache.limit_low)
+ _pr_fd_cache.limit_high = _pr_fd_cache.limit_low;
+
+ _pr_fd_cache.ml = PR_NewLock();
+ PR_ASSERT(NULL != _pr_fd_cache.ml);
+ _pr_fd_cache.stack = PR_CreateStack("FD");
+ PR_ASSERT(NULL != _pr_fd_cache.stack);
+
+} /* _PR_InitFdCache */
+
+void _PR_CleanupFdCache(void)
+{
+ PRFileDesc *fd, *next;
+ PRStackElem *pop;
+
+ for (fd = _pr_fd_cache.head; fd != NULL; fd = next)
+ {
+ next = fd->higher;
+ PR_DELETE(fd->secret);
+ PR_DELETE(fd);
+ }
+ PR_DestroyLock(_pr_fd_cache.ml);
+ while ((pop = PR_StackPop(_pr_fd_cache.stack)) != NULL)
+ {
+ fd = (PRFileDesc*)((PRPtrdiff)pop - (PRPtrdiff)stack2fd);
+ PR_DELETE(fd->secret);
+ PR_DELETE(fd);
+ }
+ PR_DestroyStack(_pr_fd_cache.stack);
+} /* _PR_CleanupFdCache */
+
+/* prfdcach.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prfile.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prfile.c
new file mode 100644
index 00000000..caf1bb88
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prfile.c
@@ -0,0 +1,861 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+#include <fcntl.h>
+
+#ifdef XP_UNIX
+#if defined(AIX) || defined(QNX)
+/* To pick up sysconf */
+#include <unistd.h>
+#else
+/* To pick up getrlimit, setrlimit */
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#endif /* XP_UNIX */
+
+extern PRLock *_pr_flock_lock;
+extern PRCondVar *_pr_flock_cv;
+
+static PRInt32 PR_CALLBACK FileRead(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ PRInt32 rv = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ rv = -1;
+ }
+ if (rv == -1)
+ return rv;
+
+ PR_LOG(_pr_io_lm, PR_LOG_MAX,
+ ("read: fd=%p osfd=%d buf=%p amount=%d",
+ fd, fd ? fd->secret->md.osfd : 0, buf, amount));
+
+ rv = _PR_MD_READ(fd, buf, amount);
+ if (rv < 0) {
+ PR_ASSERT(rv == -1);
+ }
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("read -> %d", rv));
+ return rv;
+}
+
+static PRInt32 PR_CALLBACK FileWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ PRInt32 rv = 0;
+ PRInt32 temp, count;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ rv = -1;
+ }
+ if (rv != 0)
+ return rv;
+
+ count = 0;
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ if ( PR_TRUE == fd->secret->appendMode ) {
+ rv = PR_Seek(fd, 0, PR_SEEK_END );
+ if ( -1 == rv ) {
+ return rv;
+ }
+ } /* if (fd->secret->appendMode...) */
+#endif /* XP_UNIX */
+ while (amount > 0) {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX,
+ ("write: fd=%p osfd=%d buf=%p amount=%d",
+ fd, fd ? fd->secret->md.osfd : 0, buf, amount));
+ temp = _PR_MD_WRITE(fd, buf, amount);
+ if (temp < 0) {
+ count = -1;
+ break;
+ }
+ count += temp;
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ buf = (const void*) ((const char*)buf + temp);
+ amount -= temp;
+ }
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("write -> %d", count));
+ return count;
+}
+
+static PROffset32 PR_CALLBACK FileSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
+{
+ PROffset32 result;
+
+ result = _PR_MD_LSEEK(fd, offset, whence);
+ return result;
+}
+
+static PROffset64 PR_CALLBACK FileSeek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
+{
+#ifdef XP_MAC
+#pragma unused( fd, offset, whence )
+#endif
+ PROffset64 result;
+
+ result = _PR_MD_LSEEK64(fd, offset, whence);
+ return result;
+}
+
+static PRInt32 PR_CALLBACK FileAvailable(PRFileDesc *fd)
+{
+ PRInt32 result, cur, end;
+
+ cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);
+
+ if (cur >= 0)
+ end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);
+
+ if ((cur < 0) || (end < 0)) {
+ return -1;
+ }
+
+ result = end - cur;
+ _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);
+
+ return result;
+}
+
+static PRInt64 PR_CALLBACK FileAvailable64(PRFileDesc *fd)
+{
+#ifdef XP_MAC
+#pragma unused( fd )
+#endif
+ PRInt64 result, cur, end;
+ PRInt64 minus_one;
+
+ LL_I2L(minus_one, -1);
+ cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);
+
+ if (LL_GE_ZERO(cur))
+ end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);
+
+ if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;
+
+ LL_SUB(result, end, cur);
+ (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);
+
+ return result;
+}
+
+static PRInt32 PR_CALLBACK PipeAvailable(PRFileDesc *fd)
+{
+ PRInt32 rv;
+ rv = _PR_MD_PIPEAVAILABLE(fd);
+ return rv;
+}
+
+static PRInt64 PR_CALLBACK PipeAvailable64(PRFileDesc *fd)
+{
+ PRInt64 rv;
+ LL_I2L(rv, _PR_MD_PIPEAVAILABLE(fd));
+ return rv;
+}
+
+static PRStatus PR_CALLBACK PipeSync(PRFileDesc *fd)
+{
+#if defined(XP_MAC)
+#pragma unused (fd)
+#endif
+
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK FileGetInfo(PRFileDesc *fd, PRFileInfo *info)
+{
+ PRInt32 rv;
+
+ rv = _PR_MD_GETOPENFILEINFO(fd, info);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK FileGetInfo64(PRFileDesc *fd, PRFileInfo64 *info)
+{
+#ifdef XP_MAC
+#pragma unused( fd, info )
+#endif
+ /* $$$$ NOT YET IMPLEMENTED */
+ PRInt32 rv;
+
+ rv = _PR_MD_GETOPENFILEINFO64(fd, info);
+ if (rv < 0) return PR_FAILURE;
+ else return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK FileSync(PRFileDesc *fd)
+{
+ PRInt32 result;
+ result = _PR_MD_FSYNC(fd);
+ if (result < 0) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK FileClose(PRFileDesc *fd)
+{
+ if (!fd || !fd->secret
+ || (fd->secret->state != _PR_FILEDESC_OPEN
+ && fd->secret->state != _PR_FILEDESC_CLOSED)) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (fd->secret->state == _PR_FILEDESC_OPEN) {
+ if (_PR_MD_CLOSE_FILE(fd->secret->md.osfd) < 0) {
+ return PR_FAILURE;
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
+ }
+ PR_FreeFileDesc(fd);
+ return PR_SUCCESS;
+}
+
+static PRInt16 PR_CALLBACK FilePoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+#ifdef XP_MAC
+#pragma unused( fd, in_flags )
+#endif
+ *out_flags = 0;
+ return in_flags;
+} /* FilePoll */
+
+static PRIOMethods _pr_fileMethods = {
+ PR_DESC_FILE,
+ FileClose,
+ FileRead,
+ FileWrite,
+ FileAvailable,
+ FileAvailable64,
+ FileSync,
+ FileSeek,
+ FileSeek64,
+ FileGetInfo,
+ FileGetInfo64,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ FilePoll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
+{
+ return &_pr_fileMethods;
+}
+
+static PRIOMethods _pr_pipeMethods = {
+ PR_DESC_PIPE,
+ FileClose,
+ FileRead,
+ FileWrite,
+ PipeAvailable,
+ PipeAvailable64,
+ PipeSync,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ FilePoll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)
+{
+ return &_pr_pipeMethods;
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
+{
+ PRInt32 osfd;
+ PRFileDesc *fd = 0;
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* Map pr open flags and mode to os specific flags */
+
+ osfd = _PR_MD_OPEN(name, flags, mode);
+ if (osfd != -1) {
+ fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
+ if (!fd) {
+ (void) _PR_MD_CLOSE_FILE(osfd);
+ } else {
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ fd->secret->appendMode = appendMode;
+#endif
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
+ }
+ }
+ return fd;
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_OpenFile(
+ const char *name, PRIntn flags, PRIntn mode)
+{
+ PRInt32 osfd;
+ PRFileDesc *fd = 0;
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* Map pr open flags and mode to os specific flags */
+
+ osfd = _PR_MD_OPEN_FILE(name, flags, mode);
+ if (osfd != -1) {
+ fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
+ if (!fd) {
+ (void) _PR_MD_CLOSE_FILE(osfd);
+ } else {
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ fd->secret->appendMode = appendMode;
+#endif
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
+ }
+ }
+ return fd;
+}
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+static PRInt32 PR_GetSysfdTableMax(void)
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PRInt32 PR_GetSysfdTableMax(void)
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+{
+#if defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX)
+ struct rlimit rlim;
+
+ if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+ /* XXX need to call PR_SetError() */
+ return -1;
+ }
+
+ return rlim.rlim_max;
+#elif defined(AIX) || defined(NEXTSTEP) || defined(QNX)
+ return sysconf(_SC_OPEN_MAX);
+#elif defined(WIN32)
+ /*
+ * There is a systemwide limit of 65536 user handles.
+ */
+ return 16384;
+#elif defined (WIN16)
+ return FOPEN_MAX;
+#elif defined(XP_OS2)
+ ULONG ulReqCount = 0;
+ ULONG ulCurMaxFH = 0;
+ DosSetRelMaxFH(&ulReqCount, &ulCurMaxFH);
+ return ulCurMaxFH;
+#elif defined (XP_MAC) || defined(XP_BEOS)
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+#else
+ write me;
+#endif
+}
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+static PRInt32 PR_SetSysfdTableSize(int table_size)
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PRInt32 PR_SetSysfdTableSize(int table_size)
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+{
+#if defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX)
+ struct rlimit rlim;
+ PRInt32 tableMax = PR_GetSysfdTableMax();
+
+ if (tableMax < 0)
+ return -1;
+
+ if (tableMax > FD_SETSIZE)
+ tableMax = FD_SETSIZE;
+
+ rlim.rlim_max = tableMax;
+
+ /* Grow as much as we can; even if too big */
+ if ( rlim.rlim_max < table_size )
+ rlim.rlim_cur = rlim.rlim_max;
+ else
+ rlim.rlim_cur = table_size;
+
+ if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+ /* XXX need to call PR_SetError() */
+ return -1;
+ }
+
+ return rlim.rlim_cur;
+#elif defined(XP_OS2)
+ PRInt32 tableMax = PR_GetSysfdTableMax();
+ if (table_size > tableMax) {
+ APIRET rc = NO_ERROR;
+ rc = DosSetMaxFH(table_size);
+ if (rc == NO_ERROR)
+ return table_size;
+ else
+ return -1;
+ }
+ return tableMax;
+#elif defined(AIX) || defined(NEXTSTEP) || defined(QNX) \
+ || defined(WIN32) || defined(WIN16) || defined(XP_BEOS)
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+#elif defined (XP_MAC)
+#pragma unused (table_size)
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+#else
+ write me;
+#endif
+}
+
+PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)
+{
+ PRInt32 rv;
+
+ rv = _PR_MD_DELETE(name);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
+{
+ PRInt32 rv;
+
+ rv = _PR_MD_GETFILEINFO(fn, info);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
+{
+#ifdef XP_MAC
+#pragma unused (fn, info)
+#endif
+ PRInt32 rv;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ rv = _PR_MD_GETFILEINFO64(fn, info);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else {
+ return PR_SUCCESS;
+ }
+}
+
+PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
+{
+ PRInt32 rv;
+
+ rv = _PR_MD_RENAME(from, to);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
+{
+PRInt32 rv;
+
+ rv = _PR_MD_ACCESS(name, how);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+}
+
+/*
+** Import an existing OS file to NSPR
+*/
+PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd)
+{
+ PRFileDesc *fd = NULL;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
+ if( !fd ) {
+ (void) _PR_MD_CLOSE_FILE(osfd);
+ } else {
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
+ }
+
+ return fd;
+}
+
+/*
+** Import an existing OS pipe to NSPR
+*/
+PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PRInt32 osfd)
+{
+ PRFileDesc *fd = NULL;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ fd = PR_AllocFileDesc(osfd, &_pr_pipeMethods);
+ if( !fd ) {
+ (void) _PR_MD_CLOSE_FILE(osfd);
+ } else {
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
+#ifdef WINNT
+ fd->secret->md.sync_file_io = PR_TRUE;
+#endif
+ }
+
+ return fd;
+}
+
+#ifndef NO_NSPR_10_SUPPORT
+/*
+** PR_Stat() for Win16 is defined in w16io.c
+** it is a hack to circumvent problems in Gromit and Java
+** See also: BugSplat: 98516.
+*/
+#if !defined(WIN16)
+/*
+ * This function is supposed to be for backward compatibility with
+ * nspr 1.0. Therefore, it still uses the nspr 1.0 error-reporting
+ * mechanism -- returns a PRInt32, which is the error code when the call
+ * fails.
+ *
+ * If we need this function in nspr 2.0, it should be changed to
+ * return PRStatus, as follows:
+ *
+ * PR_IMPLEMENT(PRStatus) PR_Stat(const char *name, struct stat *buf)
+ * {
+ * PRInt32 rv;
+ *
+ * rv = _PR_MD_STAT(name, buf);
+ * if (rv < 0)
+ * return PR_FAILURE;
+ * else
+ * return PR_SUCCESS;
+ * }
+ *
+ * -- wtc, 2/14/97.
+ */
+PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
+{
+ PRInt32 rv;
+
+ rv = _PR_MD_STAT(name, buf);
+ return rv;
+}
+
+#endif /* !defined(WIN16) */
+#endif /* ! NO_NSPR_10_SUPPORT */
+
+PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
+{
+ PRStatus status = PR_SUCCESS;
+
+#ifdef WINNT
+ if (!fd->secret->md.io_model_committed) {
+ PRInt32 rv;
+ rv = _md_Associate((HANDLE)fd->secret->md.osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+#endif
+
+ PR_Lock(_pr_flock_lock);
+ while (fd->secret->lockCount == -1)
+ PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT);
+ if (fd->secret->lockCount == 0) {
+ fd->secret->lockCount = -1;
+ PR_Unlock(_pr_flock_lock);
+ status = _PR_MD_LOCKFILE(fd->secret->md.osfd);
+ PR_Lock(_pr_flock_lock);
+ fd->secret->lockCount = (status == PR_SUCCESS) ? 1 : 0;
+ PR_NotifyAllCondVar(_pr_flock_cv);
+ } else {
+ fd->secret->lockCount++;
+ }
+ PR_Unlock(_pr_flock_lock);
+
+ return status;
+}
+
+PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
+{
+ PRStatus status = PR_SUCCESS;
+
+#ifdef WINNT
+ if (!fd->secret->md.io_model_committed) {
+ PRInt32 rv;
+ rv = _md_Associate((HANDLE)fd->secret->md.osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+#endif
+
+ PR_Lock(_pr_flock_lock);
+ if (fd->secret->lockCount == 0) {
+ status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
+ PR_ASSERT(status == PR_SUCCESS || fd->secret->lockCount == 0);
+ if (status == PR_SUCCESS)
+ fd->secret->lockCount = 1;
+ } else {
+ fd->secret->lockCount++;
+ }
+ PR_Unlock(_pr_flock_lock);
+
+ return status;
+}
+
+PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
+{
+ PRStatus rv = PR_SUCCESS;
+
+ PR_Lock(_pr_flock_lock);
+ if (fd->secret->lockCount == 1) {
+ rv = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);
+ if (rv == PR_SUCCESS)
+ fd->secret->lockCount = 0;
+ } else {
+ fd->secret->lockCount--;
+ }
+ PR_Unlock(_pr_flock_lock);
+
+ return rv;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CreatePipe(
+ PRFileDesc **readPipe,
+ PRFileDesc **writePipe
+)
+{
+#if defined(XP_MAC)
+#pragma unused (readPipe, writePipe)
+#endif
+
+#ifdef WIN32
+ HANDLE readEnd, writeEnd;
+ SECURITY_ATTRIBUTES pipeAttributes;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ ZeroMemory(&pipeAttributes, sizeof(pipeAttributes));
+ pipeAttributes.nLength = sizeof(pipeAttributes);
+ pipeAttributes.bInheritHandle = TRUE;
+ if (CreatePipe(&readEnd, &writeEnd, &pipeAttributes, 0) == 0) {
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ *readPipe = PR_AllocFileDesc((PRInt32)readEnd, &_pr_pipeMethods);
+ if (NULL == *readPipe) {
+ CloseHandle(readEnd);
+ CloseHandle(writeEnd);
+ return PR_FAILURE;
+ }
+ *writePipe = PR_AllocFileDesc((PRInt32)writeEnd, &_pr_pipeMethods);
+ if (NULL == *writePipe) {
+ PR_Close(*readPipe);
+ CloseHandle(writeEnd);
+ return PR_FAILURE;
+ }
+#ifdef WINNT
+ (*readPipe)->secret->md.sync_file_io = PR_TRUE;
+ (*writePipe)->secret->md.sync_file_io = PR_TRUE;
+#endif
+ (*readPipe)->secret->inheritable = _PR_TRI_TRUE;
+ (*writePipe)->secret->inheritable = _PR_TRI_TRUE;
+ return PR_SUCCESS;
+#elif defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+#ifdef XP_OS2
+ HFILE pipefd[2];
+#else
+ int pipefd[2];
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#ifdef XP_OS2
+ if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) {
+#else
+ if (pipe(pipefd) == -1) {
+#endif
+ /* XXX map pipe error */
+ PR_SetError(PR_UNKNOWN_ERROR, errno);
+ return PR_FAILURE;
+ }
+ *readPipe = PR_AllocFileDesc(pipefd[0], &_pr_pipeMethods);
+ if (NULL == *readPipe) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return PR_FAILURE;
+ }
+ *writePipe = PR_AllocFileDesc(pipefd[1], &_pr_pipeMethods);
+ if (NULL == *writePipe) {
+ PR_Close(*readPipe);
+ close(pipefd[1]);
+ return PR_FAILURE;
+ }
+#ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
+ _PR_MD_MAKE_NONBLOCK(*readPipe);
+#endif
+ _PR_MD_INIT_FD_INHERITABLE(*readPipe, PR_FALSE);
+#ifndef XP_BEOS /* Pipes are nonblocking on BeOS */
+ _PR_MD_MAKE_NONBLOCK(*writePipe);
+#endif
+ _PR_MD_INIT_FD_INHERITABLE(*writePipe, PR_FALSE);
+ return PR_SUCCESS;
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+#endif
+}
+
+#ifdef MOZ_UNICODE
+/* ================ UTF16 Interfaces ================================ */
+PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16(
+ const PRUnichar *name, PRIntn flags, PRIntn mode)
+{
+ PRInt32 osfd;
+ PRFileDesc *fd = 0;
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* Map pr open flags and mode to os specific flags */
+ osfd = _PR_MD_OPEN_FILE_UTF16(name, flags, mode);
+ if (osfd != -1) {
+ fd = PR_AllocFileDesc(osfd, &_pr_fileMethods);
+ if (!fd) {
+ (void) _PR_MD_CLOSE_FILE(osfd);
+ } else {
+#if !defined(XP_UNIX) /* BugZilla: 4090 */
+ fd->secret->appendMode = appendMode;
+#endif
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
+ }
+ }
+ return fd;
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info)
+{
+#ifdef XP_MAC
+#pragma unused (fn, info)
+#endif
+ PRInt32 rv;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ rv = _PR_MD_GETFILEINFO64_UTF16(fn, info);
+ if (rv < 0) {
+ return PR_FAILURE;
+ } else {
+ return PR_SUCCESS;
+ }
+}
+
+/* ================ UTF16 Interfaces ================================ */
+#endif /* MOZ_UNICODE */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prio.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prio.c
new file mode 100644
index 00000000..908bfd61
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prio.c
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h> /* for memset() */
+
+
+/************************************************************************/
+
+PRLock *_pr_flock_lock;
+PRCondVar *_pr_flock_cv;
+
+void _PR_InitIO(void)
+{
+ const PRIOMethods *methods = PR_GetFileMethods();
+
+ _PR_InitFdCache();
+
+ _pr_flock_lock = PR_NewLock();
+ _pr_flock_cv = PR_NewCondVar(_pr_flock_lock);
+
+#ifdef WIN32
+ _pr_stdin = PR_AllocFileDesc((PRInt32)GetStdHandle(STD_INPUT_HANDLE),
+ methods);
+ _pr_stdout = PR_AllocFileDesc((PRInt32)GetStdHandle(STD_OUTPUT_HANDLE),
+ methods);
+ _pr_stderr = PR_AllocFileDesc((PRInt32)GetStdHandle(STD_ERROR_HANDLE),
+ methods);
+#ifdef WINNT
+ _pr_stdin->secret->md.sync_file_io = PR_TRUE;
+ _pr_stdout->secret->md.sync_file_io = PR_TRUE;
+ _pr_stderr->secret->md.sync_file_io = PR_TRUE;
+#endif
+#else
+ _pr_stdin = PR_AllocFileDesc(0, methods);
+ _pr_stdout = PR_AllocFileDesc(1, methods);
+ _pr_stderr = PR_AllocFileDesc(2, methods);
+#endif
+ _PR_MD_INIT_FD_INHERITABLE(_pr_stdin, PR_TRUE);
+ _PR_MD_INIT_FD_INHERITABLE(_pr_stdout, PR_TRUE);
+ _PR_MD_INIT_FD_INHERITABLE(_pr_stderr, PR_TRUE);
+
+ _PR_MD_INIT_IO();
+}
+
+void _PR_CleanupIO(void)
+{
+ PR_FreeFileDesc(_pr_stdin);
+ _pr_stdin = NULL;
+ PR_FreeFileDesc(_pr_stdout);
+ _pr_stdout = NULL;
+ PR_FreeFileDesc(_pr_stderr);
+ _pr_stderr = NULL;
+
+ if (_pr_flock_cv) {
+ PR_DestroyCondVar(_pr_flock_cv);
+ _pr_flock_cv = NULL;
+ }
+ if (_pr_flock_lock) {
+ PR_DestroyLock(_pr_flock_lock);
+ _pr_flock_lock = NULL;
+ }
+
+ _PR_CleanupFdCache();
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
+{
+ PRFileDesc *result = NULL;
+ PR_ASSERT((int) osfd >= PR_StandardInput && osfd <= PR_StandardError);
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ switch (osfd)
+ {
+ case PR_StandardInput: result = _pr_stdin; break;
+ case PR_StandardOutput: result = _pr_stdout; break;
+ case PR_StandardError: result = _pr_stderr; break;
+ default:
+ (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ }
+ return result;
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
+ PRInt32 osfd, const PRIOMethods *methods)
+{
+ PRFileDesc *fd;
+
+#ifdef XP_UNIX
+ /*
+ * Assert that the file descriptor is small enough to fit in the
+ * fd_set passed to select
+ */
+ PR_ASSERT(osfd < FD_SETSIZE);
+#endif
+ fd = _PR_Getfd();
+ if (fd) {
+ /* Initialize the members of PRFileDesc and PRFilePrivate */
+ fd->methods = methods;
+ fd->secret->state = _PR_FILEDESC_OPEN;
+ fd->secret->md.osfd = osfd;
+ _PR_MD_INIT_FILEDESC(fd);
+ } else {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+
+ return fd;
+}
+
+PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc *fd)
+{
+ PR_ASSERT(fd);
+#ifdef XP_MAC
+ _PR_MD_FREE_FILEDESC(fd);
+#endif
+ _PR_Putfd(fd);
+}
+
+/*
+** Wait for some i/o to finish on one or more more poll descriptors.
+*/
+PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ return(_PR_MD_PR_POLL(pds, npds, timeout));
+}
+
+/*
+** Set the inheritance attribute of a file descriptor.
+*/
+PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(
+ PRFileDesc *fd,
+ PRBool inheritable)
+{
+#if defined(XP_UNIX) || defined(WIN32) || defined(XP_OS2) || defined(XP_BEOS)
+ /*
+ * Only a non-layered, NSPR file descriptor can be inherited
+ * by a child process.
+ */
+ if (fd->identity != PR_NSPR_IO_LAYER) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (fd->secret->inheritable != inheritable) {
+ if (_PR_MD_SET_FD_INHERITABLE(fd, inheritable) == PR_FAILURE) {
+ return PR_FAILURE;
+ }
+ fd->secret->inheritable = inheritable;
+ }
+ return PR_SUCCESS;
+#else
+#ifdef XP_MAC
+#pragma unused (fd, inheritable)
+#endif
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+#endif
+}
+
+/*
+** This function only has a useful implementation in the debug build of
+** the pthreads version.
+*/
+PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
+{
+ /* do nothing */
+} /* PT_FPrintStats */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/priometh.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/priometh.c
new file mode 100644
index 00000000..1ca474f0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/priometh.c
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+#include "primpl.h"
+
+#include <string.h>
+
+/*****************************************************************************/
+/************************** Invalid I/O method object ************************/
+/*****************************************************************************/
+PRIOMethods _pr_faulty_methods = {
+ (PRDescType)0,
+ (PRCloseFN)_PR_InvalidStatus,
+ (PRReadFN)_PR_InvalidInt,
+ (PRWriteFN)_PR_InvalidInt,
+ (PRAvailableFN)_PR_InvalidInt,
+ (PRAvailable64FN)_PR_InvalidInt64,
+ (PRFsyncFN)_PR_InvalidStatus,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ (PRPollFN)_PR_InvalidInt16,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+PRIntn _PR_InvalidInt(void)
+{
+ PR_ASSERT(!"I/O method is invalid");
+ PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+ return -1;
+} /* _PR_InvalidInt */
+
+PRInt16 _PR_InvalidInt16(void)
+{
+ PR_ASSERT(!"I/O method is invalid");
+ PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+ return -1;
+} /* _PR_InvalidInt */
+
+PRInt64 _PR_InvalidInt64(void)
+{
+ PRInt64 rv;
+ LL_I2L(rv, -1);
+ PR_ASSERT(!"I/O method is invalid");
+ PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+ return rv;
+} /* _PR_InvalidInt */
+
+/*
+ * An invalid method that returns PRStatus
+ */
+
+PRStatus _PR_InvalidStatus(void)
+{
+ PR_ASSERT(!"I/O method is invalid");
+ PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+ return PR_FAILURE;
+} /* _PR_InvalidDesc */
+
+/*
+ * An invalid method that returns a pointer
+ */
+
+PRFileDesc *_PR_InvalidDesc(void)
+{
+ PR_ASSERT(!"I/O method is invalid");
+ PR_SetError(PR_INVALID_METHOD_ERROR, 0);
+ return NULL;
+} /* _PR_InvalidDesc */
+
+PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file)
+{
+ return file->methods->file_type;
+}
+
+PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd)
+{
+ return (fd->methods->close)(fd);
+}
+
+PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ return((fd->methods->read)(fd,buf,amount));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ return((fd->methods->write)(fd,buf,amount));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
+{
+ return((fd->methods->seek)(fd, offset, whence));
+}
+
+PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
+{
+ return((fd->methods->seek64)(fd, offset, whence));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd)
+{
+ return((fd->methods->available)(fd));
+}
+
+PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd)
+{
+ return((fd->methods->available64)(fd));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info)
+{
+ return((fd->methods->fileInfo)(fd, info));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
+{
+ return((fd->methods->fileInfo64)(fd, info));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd)
+{
+ return((fd->methods->fsync)(fd));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Connect(
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ return((fd->methods->connect)(fd,addr,timeout));
+}
+
+PR_IMPLEMENT(PRStatus) PR_ConnectContinue(
+ PRFileDesc *fd, PRInt16 out_flags)
+{
+ return((fd->methods->connectcontinue)(fd,out_flags));
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr,
+PRIntervalTime timeout)
+{
+ return((fd->methods->accept)(fd,addr,timeout));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr)
+{
+ return((fd->methods->bind)(fd,addr));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
+{
+ return((fd->methods->shutdown)(fd,how));
+}
+
+PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog)
+{
+ return((fd->methods->listen)(fd,backlog));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+PRIntn flags, PRIntervalTime timeout)
+{
+ return((fd->methods->recv)(fd,buf,amount,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+PRIntn flags, PRIntervalTime timeout)
+{
+ return((fd->methods->send)(fd,buf,amount,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov,
+PRInt32 iov_size, PRIntervalTime timeout)
+{
+ if (iov_size > PR_MAX_IOVECTOR_SIZE)
+ {
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ return -1;
+ }
+ return((fd->methods->writev)(fd,iov,iov_size,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ return((fd->methods->recvfrom)(fd,buf,amount,flags,addr,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_SendTo(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ return((fd->methods->sendto)(fd,buf,amount,flags,addr,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_TransmitFile(
+ PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_AcceptRead(
+ PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
+{
+ return((fd->methods->getsockname)(fd,addr));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
+{
+ return((fd->methods->getpeername)(fd,addr));
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetSocketOption(
+ PRFileDesc *fd, PRSocketOptionData *data)
+{
+ return((fd->methods->getsocketoption)(fd, data));
+}
+
+PR_IMPLEMENT(PRStatus) PR_SetSocketOption(
+ PRFileDesc *fd, const PRSocketOptionData *data)
+{
+ return((fd->methods->setsocketoption)(fd, data));
+}
+
+PR_IMPLEMENT(PRInt32) PR_SendFile(
+ PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ return((sd->methods->sendfile)(sd,sfd,flags,timeout));
+}
+
+PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead(
+ PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+ PRNetAddr remote;
+ PRFileDesc *accepted = NULL;
+
+ /*
+ ** The timeout does not apply to the accept portion of the
+ ** operation - it waits indefinitely.
+ */
+ accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == accepted) return rv;
+
+ rv = PR_Recv(accepted, buf, amount, 0, timeout);
+ if (rv >= 0)
+ {
+ /* copy the new info out where caller can see it */
+#define AMASK ((PRPtrdiff)7) /* mask for alignment of PRNetAddr */
+ PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK;
+ *raddr = (PRNetAddr*)(aligned & ~AMASK);
+ memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote));
+ *nd = accepted;
+ return rv;
+ }
+
+ PR_Close(accepted);
+ return rv;
+}
+
+/*
+ * PR_EmulateSendFile
+ *
+ * Send file sfd->fd across socket sd. If header/trailer are specified
+ * they are sent before and after the file, respectively.
+ *
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
+ *
+ */
+
+#if defined(XP_UNIX) || defined(WIN32)
+
+/*
+ * An implementation based on memory-mapped files
+ */
+
+#define SENDFILE_MMAP_CHUNK (256 * 1024)
+
+PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
+ PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ PRInt32 rv, count = 0;
+ PRInt32 len, file_bytes, index = 0;
+ PRFileInfo info;
+ PRIOVec iov[3];
+ PRFileMap *mapHandle = NULL;
+ void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */
+ PRUint32 file_mmap_offset, alignment;
+ PRInt64 zero64;
+ PROffset64 file_mmap_offset64;
+ PRUint32 addr_offset, mmap_len;
+
+ /* Get file size */
+ if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) {
+ count = -1;
+ goto done;
+ }
+ if (sfd->file_nbytes &&
+ (info.size < (sfd->file_offset + sfd->file_nbytes))) {
+ /*
+ * there are fewer bytes in file to send than specified
+ */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ count = -1;
+ goto done;
+ }
+ if (sfd->file_nbytes)
+ file_bytes = sfd->file_nbytes;
+ else
+ file_bytes = info.size - sfd->file_offset;
+
+ alignment = PR_GetMemMapAlignment();
+
+ /* number of initial bytes to skip in mmap'd segment */
+ addr_offset = sfd->file_offset % alignment;
+
+ /* find previous mmap alignment boundary */
+ file_mmap_offset = sfd->file_offset - addr_offset;
+
+ /*
+ * If the file is large, mmap and send the file in chunks so as
+ * to not consume too much virtual address space
+ */
+ mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK);
+ len = mmap_len - addr_offset;
+
+ /*
+ * Map in (part of) file. Take care of zero-length files.
+ */
+ if (len) {
+ LL_I2L(zero64, 0);
+ mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY);
+ if (!mapHandle) {
+ count = -1;
+ goto done;
+ }
+ LL_I2L(file_mmap_offset64, file_mmap_offset);
+ addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len);
+ if (!addr) {
+ count = -1;
+ goto done;
+ }
+ }
+ /*
+ * send headers first, followed by the file
+ */
+ if (sfd->hlen) {
+ iov[index].iov_base = (char *) sfd->header;
+ iov[index].iov_len = sfd->hlen;
+ index++;
+ }
+ if (len) {
+ iov[index].iov_base = (char*)addr + addr_offset;
+ iov[index].iov_len = len;
+ index++;
+ }
+ if ((file_bytes == len) && (sfd->tlen)) {
+ /*
+ * all file data is mapped in; send the trailer too
+ */
+ iov[index].iov_base = (char *) sfd->trailer;
+ iov[index].iov_len = sfd->tlen;
+ index++;
+ }
+ rv = PR_Writev(sd, iov, index, timeout);
+ if (len)
+ PR_MemUnmap(addr, mmap_len);
+ if (rv < 0) {
+ count = -1;
+ goto done;
+ }
+
+ PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0));
+
+ file_bytes -= len;
+ count += rv;
+ if (!file_bytes) /* header, file and trailer are sent */
+ goto done;
+
+ /*
+ * send remaining bytes of the file, if any
+ */
+ len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
+ while (len > 0) {
+ /*
+ * Map in (part of) file
+ */
+ file_mmap_offset = sfd->file_offset + count - sfd->hlen;
+ PR_ASSERT((file_mmap_offset % alignment) == 0);
+
+ LL_I2L(file_mmap_offset64, file_mmap_offset);
+ addr = PR_MemMap(mapHandle, file_mmap_offset64, len);
+ if (!addr) {
+ count = -1;
+ goto done;
+ }
+ rv = PR_Send(sd, addr, len, 0, timeout);
+ PR_MemUnmap(addr, len);
+ if (rv < 0) {
+ count = -1;
+ goto done;
+ }
+
+ PR_ASSERT(rv == len);
+ file_bytes -= rv;
+ count += rv;
+ len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK);
+ }
+ PR_ASSERT(0 == file_bytes);
+ if (sfd->tlen) {
+ rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
+ if (rv >= 0) {
+ PR_ASSERT(rv == sfd->tlen);
+ count += rv;
+ } else
+ count = -1;
+ }
+done:
+ if (mapHandle)
+ PR_CloseFileMap(mapHandle);
+ if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
+ PR_Close(sd);
+ return count;
+}
+
+#else
+
+PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
+ PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ PRInt32 rv, count = 0;
+ PRInt32 rlen;
+ const void * buffer;
+ PRInt32 buflen;
+ PRInt32 sendbytes, readbytes;
+ char *buf;
+
+#define _SENDFILE_BUFSIZE (16 * 1024)
+
+ buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE);
+ if (buf == NULL) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ * send header first
+ */
+ buflen = sfd->hlen;
+ buffer = sfd->header;
+ while (buflen) {
+ rv = PR_Send(sd, buffer, buflen, 0, timeout);
+ if (rv < 0) {
+ /* PR_Send() has invoked PR_SetError(). */
+ rv = -1;
+ goto done;
+ } else {
+ count += rv;
+ buffer = (const void*) ((const char*)buffer + rv);
+ buflen -= rv;
+ }
+ }
+
+ /*
+ * send file next
+ */
+ if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) {
+ rv = -1;
+ goto done;
+ }
+ sendbytes = sfd->file_nbytes;
+ if (sendbytes == 0) {
+ /* send entire file */
+ while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) {
+ while (rlen) {
+ char *bufptr = buf;
+
+ rv = PR_Send(sd, bufptr, rlen, 0, timeout);
+ if (rv < 0) {
+ /* PR_Send() has invoked PR_SetError(). */
+ rv = -1;
+ goto done;
+ } else {
+ count += rv;
+ bufptr = ((char*)bufptr + rv);
+ rlen -= rv;
+ }
+ }
+ }
+ if (rlen < 0) {
+ /* PR_Read() has invoked PR_SetError(). */
+ rv = -1;
+ goto done;
+ }
+ } else {
+ readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);
+ while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) {
+ while (rlen) {
+ char *bufptr = buf;
+
+ rv = PR_Send(sd, bufptr, rlen, 0, timeout);
+ if (rv < 0) {
+ /* PR_Send() has invoked PR_SetError(). */
+ rv = -1;
+ goto done;
+ } else {
+ count += rv;
+ sendbytes -= rv;
+ bufptr = ((char*)bufptr + rv);
+ rlen -= rv;
+ }
+ }
+ readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);
+ }
+ if (rlen < 0) {
+ /* PR_Read() has invoked PR_SetError(). */
+ rv = -1;
+ goto done;
+ } else if (sendbytes != 0) {
+ /*
+ * there are fewer bytes in file to send than specified
+ */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ }
+
+ /*
+ * send trailer last
+ */
+ buflen = sfd->tlen;
+ buffer = sfd->trailer;
+ while (buflen) {
+ rv = PR_Send(sd, buffer, buflen, 0, timeout);
+ if (rv < 0) {
+ /* PR_Send() has invoked PR_SetError(). */
+ rv = -1;
+ goto done;
+ } else {
+ count += rv;
+ buffer = (const void*) ((const char*)buffer + rv);
+ buflen -= rv;
+ }
+ }
+ rv = count;
+
+done:
+ if (buf)
+ PR_DELETE(buf);
+ if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
+ PR_Close(sd);
+ return rv;
+}
+
+#endif
+
+/* priometh.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/pripv6.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/pripv6.c
new file mode 100644
index 00000000..9f953534
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/pripv6.c
@@ -0,0 +1,382 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: pripv6.c
+** Description: Support for various functions unique to IPv6
+*/
+#include "primpl.h"
+#include <string.h>
+
+#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+
+static PRIOMethods ipv6_to_v4_tcpMethods;
+static PRIOMethods ipv6_to_v4_udpMethods;
+static PRDescIdentity _pr_ipv6_to_ipv4_id;
+extern PRBool IsValidNetAddr(const PRNetAddr *addr);
+extern PRIPv6Addr _pr_in6addr_any;
+extern PRIPv6Addr _pr_in6addr_loopback;
+
+/*
+ * convert an IPv4-mapped IPv6 addr to an IPv4 addr
+ */
+static void _PR_ConvertToIpv4NetAddr(const PRNetAddr *src_v6addr,
+ PRNetAddr *dst_v4addr)
+{
+const PRUint8 *srcp;
+
+ PR_ASSERT(PR_AF_INET6 == src_v6addr->ipv6.family);
+
+ if (PR_IsNetAddrType(src_v6addr, PR_IpAddrV4Mapped)) {
+ srcp = src_v6addr->ipv6.ip.pr_s6_addr;
+ memcpy((char *) &dst_v4addr->inet.ip, srcp + 12, 4);
+ } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrAny)) {
+ dst_v4addr->inet.ip = htonl(INADDR_ANY);
+ } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrLoopback)) {
+ dst_v4addr->inet.ip = htonl(INADDR_LOOPBACK);
+ }
+ dst_v4addr->inet.family = PR_AF_INET;
+ dst_v4addr->inet.port = src_v6addr->ipv6.port;
+}
+
+/*
+ * convert an IPv4 addr to an IPv4-mapped IPv6 addr
+ */
+static void _PR_ConvertToIpv6NetAddr(const PRNetAddr *src_v4addr,
+ PRNetAddr *dst_v6addr)
+{
+PRUint8 *dstp;
+
+ PR_ASSERT(PR_AF_INET == src_v4addr->inet.family);
+ dst_v6addr->ipv6.family = PR_AF_INET6;
+ dst_v6addr->ipv6.port = src_v4addr->inet.port;
+
+ if (htonl(INADDR_ANY) == src_v4addr->inet.ip) {
+ dst_v6addr->ipv6.ip = _pr_in6addr_any;
+ } else {
+ dstp = dst_v6addr->ipv6.ip.pr_s6_addr;
+ memset(dstp, 0, 10);
+ memset(dstp + 10, 0xff, 2);
+ memcpy(dstp + 12,(char *) &src_v4addr->inet.ip, 4);
+ }
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketBind(PRFileDesc *fd,
+ const PRNetAddr *addr)
+{
+ PRNetAddr tmp_ipv4addr;
+ const PRNetAddr *tmp_addrp;
+ PRFileDesc *lo = fd->lower;
+
+ if (PR_AF_INET6 != addr->raw.family) {
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) ||
+ PR_IsNetAddrType(addr, PR_IpAddrAny)) {
+ _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
+ tmp_addrp = &tmp_ipv4addr;
+ } else {
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return((lo->methods->bind)(lo,tmp_addrp));
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketConnect(
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRNetAddr tmp_ipv4addr;
+ const PRNetAddr *tmp_addrp;
+
+ if (PR_AF_INET6 != addr->raw.family) {
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) ||
+ PR_IsNetAddrType(addr, PR_IpAddrLoopback)) {
+ _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
+ tmp_addrp = &tmp_ipv4addr;
+ } else {
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return (fd->lower->methods->connect)(fd->lower, tmp_addrp, timeout);
+}
+
+static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketSendTo(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRNetAddr tmp_ipv4addr;
+ const PRNetAddr *tmp_addrp;
+
+ if (PR_AF_INET6 != addr->raw.family) {
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) ||
+ PR_IsNetAddrType(addr, PR_IpAddrLoopback)) {
+ _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
+ tmp_addrp = &tmp_ipv4addr;
+ } else {
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return (fd->lower->methods->sendto)(
+ fd->lower, buf, amount, flags, tmp_addrp, timeout);
+}
+
+static PRFileDesc* PR_CALLBACK Ipv6ToIpv4SocketAccept (
+ PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRStatus rv;
+ PRFileDesc *newfd;
+ PRFileDesc *newstack;
+ PRNetAddr tmp_ipv4addr;
+ PRNetAddr *addrlower = NULL;
+
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ newstack = PR_NEW(PRFileDesc);
+ if (NULL == newstack)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ *newstack = *fd; /* make a copy of the accepting layer */
+
+ if (addr)
+ addrlower = &tmp_ipv4addr;
+ newfd = (fd->lower->methods->accept)(fd->lower, addrlower, timeout);
+ if (NULL == newfd)
+ {
+ PR_DELETE(newstack);
+ return NULL;
+ }
+ if (addr)
+ _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, addr);
+
+ rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return newfd; /* that's it */
+}
+
+static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketAcceptRead(PRFileDesc *sd,
+ PRFileDesc **nd, PRNetAddr **ipv6_raddr, void *buf, PRInt32 amount,
+ PRIntervalTime timeout)
+{
+ PRInt32 nbytes;
+ PRStatus rv;
+ PRNetAddr tmp_ipv4addr;
+ PRFileDesc *newstack;
+
+ PR_ASSERT(sd != NULL);
+ PR_ASSERT(sd->lower != NULL);
+
+ newstack = PR_NEW(PRFileDesc);
+ if (NULL == newstack)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ *newstack = *sd; /* make a copy of the accepting layer */
+
+ nbytes = sd->lower->methods->acceptread(
+ sd->lower, nd, ipv6_raddr, buf, amount, timeout);
+ if (-1 == nbytes)
+ {
+ PR_DELETE(newstack);
+ return nbytes;
+ }
+ tmp_ipv4addr = **ipv6_raddr; /* copy */
+ _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, *ipv6_raddr);
+
+ /* this PR_PushIOLayer call cannot fail */
+ rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return nbytes;
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetName(PRFileDesc *fd,
+ PRNetAddr *ipv6addr)
+{
+ PRStatus result;
+ PRNetAddr tmp_ipv4addr;
+
+ result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr);
+ if (PR_SUCCESS == result) {
+ _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr);
+ PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE);
+ }
+ return result;
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetPeerName(PRFileDesc *fd,
+ PRNetAddr *ipv6addr)
+{
+ PRStatus result;
+ PRNetAddr tmp_ipv4addr;
+
+ result = (fd->lower->methods->getpeername)(fd->lower, &tmp_ipv4addr);
+ if (PR_SUCCESS == result) {
+ _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr);
+ PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE);
+ }
+ return result;
+}
+
+static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf,
+ PRInt32 amount, PRIntn flags, PRNetAddr *ipv6addr,
+ PRIntervalTime timeout)
+{
+ PRNetAddr tmp_ipv4addr;
+ PRInt32 result;
+
+ result = (fd->lower->methods->recvfrom)(
+ fd->lower, buf, amount, flags, &tmp_ipv4addr, timeout);
+ if (-1 != result) {
+ _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr);
+ PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE);
+ }
+ return result;
+}
+
+#if defined(_PR_INET6_PROBE)
+PRBool _pr_ipv6_is_present;
+extern PRBool _pr_test_ipv6_socket(void);
+
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
+extern PRStatus _pr_find_getipnodebyname(void);
+#endif
+
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO)
+extern PRStatus _pr_find_getaddrinfo(void);
+#endif
+
+static PRBool
+_pr_probe_ipv6_presence(void)
+{
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ if (_pr_find_getipnodebyname() != PR_SUCCESS)
+ return PR_FALSE;
+#endif
+
+#if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO)
+ if (_pr_find_getaddrinfo() != PR_SUCCESS)
+ return PR_FALSE;
+#endif
+
+ return _pr_test_ipv6_socket();
+}
+#endif /* _PR_INET6_PROBE */
+
+PRStatus _pr_init_ipv6()
+{
+ const PRIOMethods *stubMethods;
+
+#if defined(_PR_INET6_PROBE)
+ _pr_ipv6_is_present = _pr_probe_ipv6_presence();
+ if (PR_TRUE == _pr_ipv6_is_present)
+ return PR_SUCCESS;
+#endif
+
+ _pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer");
+ PR_ASSERT(PR_INVALID_IO_LAYER != _pr_ipv6_to_ipv4_id);
+
+ stubMethods = PR_GetDefaultIOMethods();
+
+ ipv6_to_v4_tcpMethods = *stubMethods; /* first get the entire batch */
+ /* then override the ones we care about */
+ ipv6_to_v4_tcpMethods.connect = Ipv6ToIpv4SocketConnect;
+ ipv6_to_v4_tcpMethods.bind = Ipv6ToIpv4SocketBind;
+ ipv6_to_v4_tcpMethods.accept = Ipv6ToIpv4SocketAccept;
+ ipv6_to_v4_tcpMethods.acceptread = Ipv6ToIpv4SocketAcceptRead;
+ ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName;
+ ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName;
+/*
+ ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption;
+ ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption;
+*/
+ ipv6_to_v4_udpMethods = *stubMethods; /* first get the entire batch */
+ /* then override the ones we care about */
+ ipv6_to_v4_udpMethods.connect = Ipv6ToIpv4SocketConnect;
+ ipv6_to_v4_udpMethods.bind = Ipv6ToIpv4SocketBind;
+ ipv6_to_v4_udpMethods.sendto = Ipv6ToIpv4SocketSendTo;
+ ipv6_to_v4_udpMethods.recvfrom = Ipv6ToIpv4SocketRecvFrom;
+ ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName;
+ ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName;
+/*
+ ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption;
+ ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption;
+*/
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd)
+{
+ PRFileDesc *ipv6_fd = NULL;
+
+ /*
+ * For platforms with no support for IPv6
+ * create layered socket for IPv4-mapped IPv6 addresses
+ */
+ if (fd->methods->file_type == PR_DESC_SOCKET_TCP)
+ ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id,
+ &ipv6_to_v4_tcpMethods);
+ else
+ ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id,
+ &ipv6_to_v4_udpMethods);
+ if (NULL == ipv6_fd) {
+ goto errorExit;
+ }
+ ipv6_fd->secret = NULL;
+
+ if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, ipv6_fd) == PR_FAILURE) {
+ goto errorExit;
+ }
+
+ return PR_SUCCESS;
+errorExit:
+
+ if (ipv6_fd)
+ ipv6_fd->dtor(ipv6_fd);
+ return PR_FAILURE;
+}
+
+#endif /* !defined(_PR_INET6) || defined(_PR_INET6_PROBE) */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prlayer.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prlayer.c
new file mode 100644
index 00000000..65b67a09
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prlayer.c
@@ -0,0 +1,769 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prlayer.c
+** Description: Routines for handling pushable protocol modules on sockets.
+*/
+
+#include "primpl.h"
+#include "prerror.h"
+#include "prmem.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prio.h"
+
+#include <string.h> /* for memset() */
+static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack);
+
+void PR_CALLBACK pl_FDDestructor(PRFileDesc *fd)
+{
+ PR_ASSERT(fd != NULL);
+ if (NULL != fd->lower) fd->lower->higher = fd->higher;
+ if (NULL != fd->higher) fd->higher->lower = fd->lower;
+ PR_DELETE(fd);
+}
+
+/*
+** Default methods that just call down to the next fd.
+*/
+static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd)
+{
+ PRFileDesc *top, *lower;
+ PRStatus rv;
+
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+ PR_ASSERT(fd->secret == NULL);
+ PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED);
+
+ if (PR_IO_LAYER_HEAD == fd->identity) {
+ /*
+ * new style stack; close all the layers, before deleting the
+ * stack head
+ */
+ rv = fd->lower->methods->close(fd->lower);
+ _PR_DestroyIOLayer(fd);
+ return rv;
+ } else if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) {
+ /*
+ * lower layers of new style stack
+ */
+ lower = fd->lower;
+ /*
+ * pop and cleanup current layer
+ */
+ top = PR_PopIOLayer(fd->higher, PR_TOP_IO_LAYER);
+ top->dtor(top);
+ /*
+ * then call lower layer
+ */
+ return (lower->methods->close(lower));
+ } else {
+ /* old style stack */
+ top = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
+ top->dtor(top);
+ return (fd->methods->close)(fd);
+ }
+}
+
+static PRInt32 PR_CALLBACK pl_DefRead (PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->read)(fd->lower, buf, amount);
+}
+
+static PRInt32 PR_CALLBACK pl_DefWrite (
+ PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->write)(fd->lower, buf, amount);
+}
+
+static PRInt32 PR_CALLBACK pl_DefAvailable (PRFileDesc *fd)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->available)(fd->lower);
+}
+
+static PRInt64 PR_CALLBACK pl_DefAvailable64 (PRFileDesc *fd)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->available64)(fd->lower);
+}
+
+static PRStatus PR_CALLBACK pl_DefFsync (PRFileDesc *fd)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->fsync)(fd->lower);
+}
+
+static PRInt32 PR_CALLBACK pl_DefSeek (
+ PRFileDesc *fd, PRInt32 offset, PRSeekWhence how)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->seek)(fd->lower, offset, how);
+}
+
+static PRInt64 PR_CALLBACK pl_DefSeek64 (
+ PRFileDesc *fd, PRInt64 offset, PRSeekWhence how)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->seek64)(fd->lower, offset, how);
+}
+
+static PRStatus PR_CALLBACK pl_DefFileInfo (PRFileDesc *fd, PRFileInfo *info)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->fileInfo)(fd->lower, info);
+}
+
+static PRStatus PR_CALLBACK pl_DefFileInfo64 (PRFileDesc *fd, PRFileInfo64 *info)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->fileInfo64)(fd->lower, info);
+}
+
+static PRInt32 PR_CALLBACK pl_DefWritev (PRFileDesc *fd, const PRIOVec *iov,
+ PRInt32 size, PRIntervalTime timeout)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->writev)(fd->lower, iov, size, timeout);
+}
+
+static PRStatus PR_CALLBACK pl_DefConnect (
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->connect)(fd->lower, addr, timeout);
+}
+
+static PRStatus PR_CALLBACK pl_DefConnectcontinue (
+ PRFileDesc *fd, PRInt16 out_flags)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->connectcontinue)(fd->lower, out_flags);
+}
+
+static PRFileDesc* PR_CALLBACK pl_TopAccept (
+ PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRStatus rv;
+ PRFileDesc *newfd, *layer = fd;
+ PRFileDesc *newstack;
+ PRBool newstyle_stack = PR_FALSE;
+
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ /* test for new style stack */
+ while (NULL != layer->higher)
+ layer = layer->higher;
+ newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
+ newstack = PR_NEW(PRFileDesc);
+ if (NULL == newstack)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ *newstack = *fd; /* make a copy of the accepting layer */
+
+ newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
+ if (NULL == newfd)
+ {
+ PR_DELETE(newstack);
+ return NULL;
+ }
+
+ if (newstyle_stack) {
+ newstack->lower = newfd;
+ newfd->higher = newstack;
+ return newstack;
+ } else {
+ /* this PR_PushIOLayer call cannot fail */
+ rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return newfd; /* that's it */
+ }
+}
+
+static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->bind)(fd->lower, addr);
+}
+
+static PRStatus PR_CALLBACK pl_DefListen (PRFileDesc *fd, PRIntn backlog)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->listen)(fd->lower, backlog);
+}
+
+static PRStatus PR_CALLBACK pl_DefShutdown (PRFileDesc *fd, PRIntn how)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->shutdown)(fd->lower, how);
+}
+
+static PRInt32 PR_CALLBACK pl_DefRecv (
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->recv)(
+ fd->lower, buf, amount, flags, timeout);
+}
+
+static PRInt32 PR_CALLBACK pl_DefSend (
+ PRFileDesc *fd, const void *buf,
+ PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout);
+}
+
+static PRInt32 PR_CALLBACK pl_DefRecvfrom (
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->recvfrom)(
+ fd->lower, buf, amount, flags, addr, timeout);
+}
+
+static PRInt32 PR_CALLBACK pl_DefSendto (
+ PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->sendto)(
+ fd->lower, buf, amount, flags, addr, timeout);
+}
+
+static PRInt16 PR_CALLBACK pl_DefPoll (
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
+}
+
+static PRInt32 PR_CALLBACK pl_DefAcceptread (
+ PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf,
+ PRInt32 amount, PRIntervalTime t)
+{
+ PRInt32 nbytes;
+ PRStatus rv;
+ PRFileDesc *newstack;
+ PRFileDesc *layer = sd;
+ PRBool newstyle_stack = PR_FALSE;
+
+ PR_ASSERT(sd != NULL);
+ PR_ASSERT(sd->lower != NULL);
+
+ /* test for new style stack */
+ while (NULL != layer->higher)
+ layer = layer->higher;
+ newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
+ newstack = PR_NEW(PRFileDesc);
+ if (NULL == newstack)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ *newstack = *sd; /* make a copy of the accepting layer */
+
+ nbytes = sd->lower->methods->acceptread(
+ sd->lower, nd, raddr, buf, amount, t);
+ if (-1 == nbytes)
+ {
+ PR_DELETE(newstack);
+ return nbytes;
+ }
+ if (newstyle_stack) {
+ newstack->lower = *nd;
+ (*nd)->higher = newstack;
+ *nd = newstack;
+ return nbytes;
+ } else {
+ /* this PR_PushIOLayer call cannot fail */
+ rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return nbytes;
+ }
+}
+
+static PRInt32 PR_CALLBACK pl_DefTransmitfile (
+ PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen,
+ PRTransmitFileFlags flags, PRIntervalTime t)
+{
+ PR_ASSERT(sd != NULL);
+ PR_ASSERT(sd->lower != NULL);
+
+ return sd->lower->methods->transmitfile(
+ sd->lower, fd, headers, hlen, flags, t);
+}
+
+static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->getsockname)(fd->lower, addr);
+}
+
+static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->getpeername)(fd->lower, addr);
+}
+
+static PRStatus PR_CALLBACK pl_DefGetsocketoption (
+ PRFileDesc *fd, PRSocketOptionData *data)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->getsocketoption)(fd->lower, data);
+}
+
+static PRStatus PR_CALLBACK pl_DefSetsocketoption (
+ PRFileDesc *fd, const PRSocketOptionData *data)
+{
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ return (fd->lower->methods->setsocketoption)(fd->lower, data);
+}
+
+static PRInt32 PR_CALLBACK pl_DefSendfile (
+ PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ PR_ASSERT(sd != NULL);
+ PR_ASSERT(sd->lower != NULL);
+
+ return sd->lower->methods->sendfile(
+ sd->lower, sfd, flags, timeout);
+}
+
+/* Methods for the top of the stack. Just call down to the next fd. */
+static PRIOMethods pl_methods = {
+ PR_DESC_LAYERED,
+ pl_TopClose,
+ pl_DefRead,
+ pl_DefWrite,
+ pl_DefAvailable,
+ pl_DefAvailable64,
+ pl_DefFsync,
+ pl_DefSeek,
+ pl_DefSeek64,
+ pl_DefFileInfo,
+ pl_DefFileInfo64,
+ pl_DefWritev,
+ pl_DefConnect,
+ pl_TopAccept,
+ pl_DefBind,
+ pl_DefListen,
+ pl_DefShutdown,
+ pl_DefRecv,
+ pl_DefSend,
+ pl_DefRecvfrom,
+ pl_DefSendto,
+ pl_DefPoll,
+ pl_DefAcceptread,
+ pl_DefTransmitfile,
+ pl_DefGetsockname,
+ pl_DefGetpeername,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ pl_DefGetsocketoption,
+ pl_DefSetsocketoption,
+ pl_DefSendfile,
+ pl_DefConnectcontinue,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void)
+{
+ return &pl_methods;
+} /* PR_GetDefaultIOMethods */
+
+PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub(
+ PRDescIdentity ident, const PRIOMethods *methods)
+{
+ PRFileDesc *fd = NULL;
+ PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident));
+ if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident))
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ else
+ {
+ fd = PR_NEWZAP(PRFileDesc);
+ if (NULL == fd)
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ fd->methods = methods;
+ fd->dtor = pl_FDDestructor;
+ fd->identity = ident;
+ }
+ }
+ return fd;
+} /* PR_CreateIOLayerStub */
+
+/*
+ * PR_CreateIOLayer
+ * Create a new style stack, where the stack top is a dummy header.
+ * Unlike the old style stacks, the contents of the stack head
+ * are not modified when a layer is pushed onto or popped from a new
+ * style stack.
+ */
+
+PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayer(PRFileDesc *top)
+{
+ PRFileDesc *fd = NULL;
+
+ fd = PR_NEWZAP(PRFileDesc);
+ if (NULL == fd)
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ fd->methods = &pl_methods;
+ fd->dtor = pl_FDDestructor;
+ fd->identity = PR_IO_LAYER_HEAD;
+ fd->higher = NULL;
+ fd->lower = top;
+ top->higher = fd;
+ top->lower = NULL;
+ }
+ return fd;
+} /* PR_CreateIOLayer */
+
+/*
+ * _PR_DestroyIOLayer
+ * Delete the stack head of a new style stack.
+ */
+
+static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack)
+{
+ if (NULL == stack)
+ return PR_FAILURE;
+ else {
+ PR_DELETE(stack);
+ return PR_SUCCESS;
+ }
+} /* _PR_DestroyIOLayer */
+
+PR_IMPLEMENT(PRStatus) PR_PushIOLayer(
+ PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd)
+{
+ PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id);
+
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(stack != NULL);
+ PR_ASSERT(insert != NULL);
+ PR_ASSERT(PR_IO_LAYER_HEAD != id);
+ if ((NULL == stack) || (NULL == fd) || (NULL == insert))
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (stack == insert)
+ {
+ /* going on top of the stack */
+ /* old-style stack */
+ PRFileDesc copy = *stack;
+ *stack = *fd;
+ *fd = copy;
+ fd->higher = stack;
+ stack->lower = fd;
+ stack->higher = NULL;
+ } else {
+ /*
+ * going somewhere in the middle of the stack for both old and new
+ * style stacks, or going on top of stack for new style stack
+ */
+ fd->lower = insert;
+ fd->higher = insert->higher;
+
+ insert->higher->lower = fd;
+ insert->higher = fd;
+ }
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id)
+{
+ PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id);
+
+ PR_ASSERT(0 != id);
+ PR_ASSERT(NULL != stack);
+ PR_ASSERT(NULL != extract);
+ if ((NULL == stack) || (0 == id) || (NULL == extract))
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ if (extract == stack) {
+ /* popping top layer of the stack */
+ /* old style stack */
+ PRFileDesc copy = *stack;
+ extract = stack->lower;
+ *stack = *extract;
+ *extract = copy;
+ stack->higher = NULL;
+ } else if ((PR_IO_LAYER_HEAD == stack->identity) &&
+ (extract == stack->lower) && (extract->lower == NULL)) {
+ /*
+ * new style stack
+ * popping the only layer in the stack; delete the stack too
+ */
+ stack->lower = NULL;
+ _PR_DestroyIOLayer(stack);
+ } else {
+ /* for both kinds of stacks */
+ extract->lower->higher = extract->higher;
+ extract->higher->lower = extract->lower;
+ }
+ extract->higher = extract->lower = NULL;
+ return extract;
+} /* PR_PopIOLayer */
+
+#define ID_CACHE_INCREMENT 16
+typedef struct _PRIdentity_cache
+{
+ PRLock *ml;
+ char **name;
+ PRIntn length;
+ PRDescIdentity ident;
+} _PRIdentity_cache;
+
+static _PRIdentity_cache identity_cache;
+
+PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name)
+{
+ PRDescIdentity identity, length;
+ char **names = NULL, *name = NULL, **old = NULL;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident);
+
+ if (NULL != layer_name)
+ {
+ name = (char*)PR_Malloc(strlen(layer_name) + 1);
+ if (NULL == name)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return PR_INVALID_IO_LAYER;
+ }
+ strcpy(name, layer_name);
+ }
+
+ /* this initial code runs unsafe */
+retry:
+ PR_ASSERT(NULL == names);
+ length = identity_cache.length;
+ if (length < (identity_cache.ident + 1))
+ {
+ length += ID_CACHE_INCREMENT;
+ names = (char**)PR_CALLOC(length * sizeof(char*));
+ if (NULL == names)
+ {
+ if (NULL != name) PR_DELETE(name);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return PR_INVALID_IO_LAYER;
+ }
+ }
+
+ /* now we get serious about thread safety */
+ PR_Lock(identity_cache.ml);
+ PR_ASSERT(identity_cache.ident <= identity_cache.length);
+ identity = identity_cache.ident + 1;
+ if (identity > identity_cache.length) /* there's no room */
+ {
+ /* we have to do something - hopefully it's already done */
+ if ((NULL != names) && (length >= identity))
+ {
+ /* what we did is still okay */
+ if (identity_cache.length)
+ memcpy(
+ names, identity_cache.name,
+ identity_cache.length * sizeof(char*));
+ old = identity_cache.name;
+ identity_cache.name = names;
+ identity_cache.length = length;
+ names = NULL;
+ }
+ else
+ {
+ PR_ASSERT(identity_cache.ident <= identity_cache.length);
+ PR_Unlock(identity_cache.ml);
+ if (NULL != names) PR_DELETE(names);
+ goto retry;
+ }
+ }
+ if (NULL != name) /* there's a name to be stored */
+ {
+ identity_cache.name[identity] = name;
+ }
+ identity_cache.ident = identity;
+ PR_ASSERT(identity_cache.ident <= identity_cache.length);
+ PR_Unlock(identity_cache.ml);
+
+ if (NULL != old) PR_DELETE(old);
+ if (NULL != names) PR_DELETE(names);
+
+ return identity;
+} /* PR_GetUniqueIdentity */
+
+PR_IMPLEMENT(const char*) PR_GetNameForIdentity(PRDescIdentity ident)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (PR_TOP_IO_LAYER == ident) return NULL;
+
+ PR_ASSERT(ident <= identity_cache.ident);
+ return (ident > identity_cache.ident) ? NULL : identity_cache.name[ident];
+} /* PR_GetNameForIdentity */
+
+PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd)
+{
+ PR_ASSERT(NULL != fd);
+ if (PR_IO_LAYER_HEAD == fd->identity) {
+ PR_ASSERT(NULL != fd->lower);
+ return fd->lower->identity;
+ } else
+ return fd->identity;
+} /* PR_GetLayersIdentity */
+
+PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id)
+{
+ PRFileDesc *layer = fd;
+
+ if (PR_TOP_IO_LAYER == id) {
+ if (PR_IO_LAYER_HEAD == fd->identity)
+ return fd->lower;
+ else
+ return fd;
+ }
+
+ for (layer = fd; layer != NULL; layer = layer->lower)
+ {
+ if (id == layer->identity) return layer;
+ }
+ for (layer = fd; layer != NULL; layer = layer->higher)
+ {
+ if (id == layer->identity) return layer;
+ }
+ return NULL;
+} /* PR_GetIdentitiesLayer */
+
+void _PR_InitLayerCache(void)
+{
+ memset(&identity_cache, 0, sizeof(identity_cache));
+ identity_cache.ml = PR_NewLock();
+ PR_ASSERT(NULL != identity_cache.ml);
+} /* _PR_InitLayerCache */
+
+void _PR_CleanupLayerCache(void)
+{
+ if (identity_cache.ml)
+ {
+ PR_DestroyLock(identity_cache.ml);
+ identity_cache.ml = NULL;
+ }
+
+ if (identity_cache.name)
+ {
+ PRDescIdentity ident;
+
+ for (ident = 0; ident <= identity_cache.ident; ident++)
+ PR_DELETE(identity_cache.name[ident]);
+
+ PR_DELETE(identity_cache.name);
+ }
+} /* _PR_CleanupLayerCache */
+
+/* prlayer.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prlog.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prlog.c
new file mode 100644
index 00000000..faac606a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prlog.c
@@ -0,0 +1,617 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Contributors:
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines Corporation, 2000.
+ * Modifications to Mozilla code or documentation identified per
+ * MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/10/2000 IBM Corp. Added DebugBreak() definitions for OS/2
+ */
+
+#if defined(VBOX) && defined(DEBUG)
+# include <iprt/initterm.h> /* for RTR3InitDll */
+# include <iprt/log.h>
+#endif
+#ifdef VBOX_USE_IPRT_IN_NSPR
+# include <iprt/string.h>
+#endif
+
+#include "primpl.h"
+#include "prenv.h"
+#include "prprf.h"
+#include <string.h>
+
+/*
+ * Lock used to lock the log.
+ *
+ * We can't define _PR_LOCK_LOG simply as PR_Lock because PR_Lock may
+ * contain assertions. We have to avoid assertions in _PR_LOCK_LOG
+ * because PR_ASSERT calls PR_LogPrint, which in turn calls _PR_LOCK_LOG.
+ * This can lead to infinite recursion.
+ */
+static PRLock *_pr_logLock;
+#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
+#define _PR_LOCK_LOG() PR_Lock(_pr_logLock);
+#define _PR_UNLOCK_LOG() PR_Unlock(_pr_logLock);
+#elif defined(_PR_GLOBAL_THREADS_ONLY)
+#define _PR_LOCK_LOG() { _PR_LOCK_LOCK(_pr_logLock)
+#define _PR_UNLOCK_LOG() _PR_LOCK_UNLOCK(_pr_logLock); }
+#else
+
+#define _PR_LOCK_LOG() \
+{ \
+ PRIntn _is; \
+ PRThread *_me = _PR_MD_CURRENT_THREAD(); \
+ if (!_PR_IS_NATIVE_THREAD(_me)) \
+ _PR_INTSOFF(_is); \
+ _PR_LOCK_LOCK(_pr_logLock)
+
+#define _PR_UNLOCK_LOG() \
+ _PR_LOCK_UNLOCK(_pr_logLock); \
+ PR_ASSERT(_me == _PR_MD_CURRENT_THREAD()); \
+ if (!_PR_IS_NATIVE_THREAD(_me)) \
+ _PR_INTSON(_is); \
+}
+
+#endif
+
+#if defined(XP_PC)
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#endif
+
+/*
+ * On NT, we can't define _PUT_LOG as PR_Write or _PR_MD_WRITE,
+ * because every asynchronous file io operation leads to a fiber context
+ * switch. So we define _PUT_LOG as fputs (from stdio.h). A side
+ * benefit is that fputs handles the LF->CRLF translation. This
+ * code can also be used on other platforms with file stream io.
+ */
+#if defined(WIN32) || defined(XP_OS2)
+#define _PR_USE_STDIO_FOR_LOGGING
+#endif
+
+/*
+** Coerce Win32 log output to use OutputDebugString() when
+** NSPR_LOG_FILE is set to "WinDebug".
+*/
+#if defined(XP_PC)
+#define WIN32_DEBUG_FILE (FILE*)-2
+#endif
+
+/*
+** Use the IPRT logging facility when
+** NSPR_LOG_FILE is set to "WinDebug". The default IPRT log instance
+** and the "default" log group will be used for logging.
+*/
+#if defined(VBOX) && defined(DEBUG)
+#if defined(_PR_USE_STDIO_FOR_LOGGING)
+#define IPRT_DEBUG_FILE (FILE*)-3
+#else
+#define IPRT_DEBUG_FILE (PRFileDesc*)-3
+#endif
+#endif
+
+/* Macros used to reduce #ifdef pollution */
+
+#if defined(_PR_USE_STDIO_FOR_LOGGING) && defined(XP_PC)
+#define __PUT_LOG(fd, buf, nb) \
+ PR_BEGIN_MACRO \
+ if (fd == WIN32_DEBUG_FILE) { \
+ char savebyte = buf[nb]; \
+ buf[nb] = '\0'; \
+ OutputDebugString(buf); \
+ buf[nb] = savebyte; \
+ } else { \
+ fwrite(buf, 1, nb, fd); \
+ fflush(fd); \
+ } \
+ PR_END_MACRO
+#elif defined(_PR_USE_STDIO_FOR_LOGGING)
+#define __PUT_LOG(fd, buf, nb) {fwrite(buf, 1, nb, fd); fflush(fd);}
+#elif defined(_PR_PTHREADS)
+#define __PUT_LOG(fd, buf, nb) PR_Write(fd, buf, nb)
+#elif defined(XP_MAC)
+#define __PUT_LOG(fd, buf, nb) _PR_MD_WRITE_SYNC(fd, buf, nb)
+#else
+#define __PUT_LOG(fd, buf, nb) _PR_MD_WRITE(fd, buf, nb)
+#endif
+
+#if defined(VBOX) && defined(DEBUG)
+#define _PUT_LOG(fd, buf, nb) \
+ PR_BEGIN_MACRO \
+ if (fd == IPRT_DEBUG_FILE) { \
+ Log(("%*.*S", nb, nb, buf)); \
+ } else { \
+ __PUT_LOG(fd, buf, nb); \
+ } \
+ PR_END_MACRO
+#else
+#define _PUT_LOG(fd, buf, nb) __PUT_LOG(fd, buf, nb)
+#endif
+
+/************************************************************************/
+
+static PRLogModuleInfo *logModules;
+
+static char *logBuf = NULL;
+static char *logp;
+static char *logEndp;
+#ifdef _PR_USE_STDIO_FOR_LOGGING
+static FILE *logFile = NULL;
+#else
+static PRFileDesc *logFile = 0;
+#endif
+
+#define LINE_BUF_SIZE 512
+#define DEFAULT_BUF_SIZE 16384
+
+#ifdef _PR_NEED_STRCASECMP
+
+/*
+ * strcasecmp is defined in /usr/ucblib/libucb.a on some platforms
+ * such as NCR and Unixware. Linking with both libc and libucb
+ * may cause some problem, so I just provide our own implementation
+ * of strcasecmp here.
+ */
+
+static const unsigned char uc[] =
+{
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', '\177'
+};
+
+PRIntn strcasecmp(const char *a, const char *b)
+{
+ const unsigned char *ua = (const unsigned char *)a;
+ const unsigned char *ub = (const unsigned char *)b;
+
+ if( ((const char *)0 == a) || (const char *)0 == b )
+ return (PRIntn)(a-b);
+
+ while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
+ {
+ a++;
+ ua++;
+ ub++;
+ }
+
+ return (PRIntn)(uc[*ua] - uc[*ub]);
+}
+
+#endif /* _PR_NEED_STRCASECMP */
+
+void _PR_InitLog(void)
+{
+ char *ev;
+
+ _pr_logLock = PR_NewLock();
+
+ ev = PR_GetEnv("NSPR_LOG_MODULES");
+ if (ev && ev[0]) {
+ char module[64]; /* Security-Critical: If you change this
+ * size, you must also change the sscanf
+ * format string to be size-1.
+ */
+ PRBool isSync = PR_FALSE;
+ PRIntn evlen = strlen(ev), pos = 0;
+ PRInt32 bufSize = DEFAULT_BUF_SIZE;
+ while (pos < evlen) {
+ PRIntn level = 1, count = 0, delta = 0;
+ count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]%n:%d%n",
+ module, &delta, &level, &delta);
+ pos += delta;
+ if (count == 0) break;
+
+ /*
+ ** If count == 2, then we got module and level. If count
+ ** == 1, then level defaults to 1 (module enabled).
+ */
+ if (strcasecmp(module, "sync") == 0) {
+ isSync = PR_TRUE;
+ } else if (strcasecmp(module, "bufsize") == 0) {
+ if (level >= LINE_BUF_SIZE) {
+ bufSize = level;
+ }
+ } else {
+ PRLogModuleInfo *lm = logModules;
+ PRBool skip_modcheck =
+ (0 == strcasecmp (module, "all")) ? PR_TRUE : PR_FALSE;
+
+ while (lm != NULL) {
+ if (skip_modcheck) lm -> level = (PRLogModuleLevel)level;
+ else if (strcasecmp(module, lm->name) == 0) {
+ lm->level = (PRLogModuleLevel)level;
+ break;
+ }
+ lm = lm->next;
+ }
+ }
+ /*found:*/
+ count = sscanf(&ev[pos], " , %n", &delta);
+ pos += delta;
+ if (count == EOF) break;
+ }
+ PR_SetLogBuffering(isSync ? bufSize : 0);
+
+ ev = PR_GetEnv("NSPR_LOG_FILE");
+ if (ev && ev[0]) {
+ if (!PR_SetLogFile(ev)) {
+#ifdef XP_PC
+ char* str = PR_smprintf("Unable to create nspr log file '%s'\n", ev);
+ if (str) {
+ OutputDebugString(str);
+ PR_smprintf_free(str);
+ }
+#else
+ fprintf(stderr, "Unable to create nspr log file '%s'\n", ev);
+#endif
+ }
+ } else {
+#ifdef _PR_USE_STDIO_FOR_LOGGING
+ logFile = stderr;
+#else
+ logFile = _pr_stderr;
+#endif
+ }
+ }
+}
+
+void _PR_LogCleanup(void)
+{
+ PRLogModuleInfo *lm = logModules;
+
+ PR_LogFlush();
+
+#ifdef _PR_USE_STDIO_FOR_LOGGING
+ if (logFile
+ && logFile != stdout
+ && logFile != stderr
+#if defined(VBOX) && defined(DEBUG)
+ && logFile != IPRT_DEBUG_FILE
+#endif
+#ifdef XP_PC
+ && logFile != WIN32_DEBUG_FILE
+#endif
+ ) {
+ fclose(logFile);
+ }
+#else
+ if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
+ PR_Close(logFile);
+ }
+#endif
+
+ while (lm != NULL) {
+ PRLogModuleInfo *next = lm->next;
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTStrFree((/*const*/ char *)lm->name);
+#else
+ free((/*const*/ char *)lm->name);
+#endif
+ PR_Free(lm);
+ lm = next;
+ }
+ logModules = NULL;
+
+ if (_pr_logLock) {
+ PR_DestroyLock(_pr_logLock);
+ _pr_logLock = NULL;
+ }
+}
+
+static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm )
+{
+ char *ev;
+
+ ev = PR_GetEnv("NSPR_LOG_MODULES");
+ if (ev && ev[0]) {
+ char module[64]; /* Security-Critical: If you change this
+ * size, you must also change the sscanf
+ * format string to be size-1.
+ */
+ PRIntn evlen = strlen(ev), pos = 0;
+ while (pos < evlen) {
+ PRIntn level = 1, count = 0, delta = 0;
+
+ count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]%n:%d%n",
+ module, &delta, &level, &delta);
+ pos += delta;
+ if (count == 0) break;
+
+ /*
+ ** If count == 2, then we got module and level. If count
+ ** == 1, then level defaults to 1 (module enabled).
+ */
+ if (lm != NULL)
+ {
+ if ((strcasecmp(module, "all") == 0)
+ || (strcasecmp(module, lm->name) == 0))
+ {
+ lm->level = (PRLogModuleLevel)level;
+ }
+ }
+ count = sscanf(&ev[pos], " , %n", &delta);
+ pos += delta;
+ if (count == EOF) break;
+ }
+ }
+} /* end _PR_SetLogModuleLevel() */
+
+PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char *name)
+{
+ PRLogModuleInfo *lm;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ lm = PR_NEWZAP(PRLogModuleInfo);
+ if (lm) {
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ lm->name = RTStrDup(name);
+#else
+ lm->name = strdup(name);
+#endif
+ lm->level = PR_LOG_NONE;
+ lm->next = logModules;
+ logModules = lm;
+ _PR_SetLogModuleLevel(lm);
+ }
+ return lm;
+}
+
+PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
+{
+#ifdef _PR_USE_STDIO_FOR_LOGGING
+
+ FILE *newLogFile;
+
+#if defined(VBOX) && defined(DEBUG)
+ if (strcmp(file, "IPRT") == 0) {
+ /* initialize VBox Runtime */
+ RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ newLogFile = IPRT_DEBUG_FILE;
+ }
+ else
+#endif
+#ifdef XP_PC
+ if (strcmp(file, "WinDebug") == 0) {
+ newLogFile = WIN32_DEBUG_FILE;
+ }
+ else
+#endif
+ {
+ newLogFile = fopen(file, "w");
+ if (!newLogFile)
+ return PR_FALSE;
+
+ /* We do buffering ourselves. */
+ setvbuf(newLogFile, NULL, _IONBF, 0);
+ }
+ if (logFile
+ && logFile != stdout
+ && logFile != stderr
+#if defined(VBOX) && defined(DEBUG)
+ && logFile != IPRT_DEBUG_FILE
+#endif
+#ifdef XP_PC
+ && logFile != WIN32_DEBUG_FILE
+#endif
+ ) {
+ fclose(logFile);
+ }
+ logFile = newLogFile;
+ return PR_TRUE;
+
+#else /* _PR_USE_STDIO_FOR_LOGGING */
+
+ PRFileDesc *newLogFile;
+
+#if defined(VBOX) && defined(DEBUG)
+ if (strcmp(file, "IPRT") == 0) {
+ /* initialize VBox Runtime */
+ RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ logFile = IPRT_DEBUG_FILE;
+ return PR_TRUE;
+ }
+#endif
+
+ newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0666);
+ if (newLogFile) {
+ if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
+ PR_Close(logFile);
+ }
+ logFile = newLogFile;
+#if defined(XP_MAC)
+ SetLogFileTypeCreator(file);
+#endif
+ }
+ return (PRBool) (newLogFile != 0);
+
+#endif /* _PR_USE_STDIO_FOR_LOGGING */
+}
+
+PR_IMPLEMENT(void) PR_SetLogBuffering(PRIntn buffer_size)
+{
+ PR_LogFlush();
+
+ if (logBuf)
+ PR_DELETE(logBuf);
+
+ if (buffer_size >= LINE_BUF_SIZE) {
+ logp = logBuf = (char*) PR_MALLOC(buffer_size);
+ logEndp = logp + buffer_size;
+ }
+}
+
+PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...)
+{
+ va_list ap;
+ char line[LINE_BUF_SIZE];
+ PRUint32 nb;
+ PRThread *me;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (!logFile) {
+ return;
+ }
+
+ va_start(ap, fmt);
+ me = PR_GetCurrentThread();
+ nb = PR_snprintf(line, sizeof(line)-1, "%ld[%p]: ",
+#if defined(_PR_DCETHREADS)
+ /* The problem is that for _PR_DCETHREADS, pthread_t is not a
+ * pointer, but a structure; so you can't easily print it...
+ */
+ me ? &(me->id): 0L, me);
+#elif defined(_PR_BTHREADS)
+ me, me);
+#else
+ me ? me->id : 0L, me);
+#endif
+
+ nb += PR_vsnprintf(line+nb, sizeof(line)-nb-1, fmt, ap);
+ if (nb > 0) {
+ if (line[nb-1] != '\n') {
+#ifndef XP_MAC
+ line[nb++] = '\n';
+#else
+ line[nb++] = '\015';
+#endif
+ line[nb] = '\0';
+ } else {
+#ifdef XP_MAC
+ line[nb-1] = '\015';
+#endif
+ }
+ }
+ va_end(ap);
+
+ _PR_LOCK_LOG();
+ if (logBuf == 0) {
+ _PUT_LOG(logFile, line, nb);
+ } else {
+ if (logp + nb > logEndp) {
+ _PUT_LOG(logFile, logBuf, logp - logBuf);
+ logp = logBuf;
+ }
+ memcpy(logp, line, nb);
+ logp += nb;
+ }
+ _PR_UNLOCK_LOG();
+ PR_LogFlush();
+}
+
+PR_IMPLEMENT(void) PR_LogFlush(void)
+{
+ if (logBuf && logFile) {
+ _PR_LOCK_LOG();
+ if (logp > logBuf) {
+ _PUT_LOG(logFile, logBuf, logp - logBuf);
+ logp = logBuf;
+ }
+ _PR_UNLOCK_LOG();
+ }
+}
+
+PR_IMPLEMENT(void) PR_Abort(void)
+{
+ PR_LogPrint("Aborting");
+ abort();
+}
+
+#if defined(XP_OS2)
+/*
+ * Added definitions for DebugBreak() for 2 different OS/2 compilers.
+ * Doing the int3 on purpose for Visual Age so that a developer can
+ * step over the instruction if so desired. Not always possible if
+ * trapping due to exception handling IBM-AKR
+ */
+#if defined(XP_OS2_VACPP)
+#include <builtin.h>
+static void DebugBreak(void) { _interrupt(3); }
+#elif defined(XP_OS2_EMX)
+static void DebugBreak(void) { asm("int $3"); }
+#else
+static void DebugBreak(void) { }
+#endif
+#endif /* XP_OS2 */
+
+PR_IMPLEMENT(void) PR_Assert(const char *s, const char *file, PRIntn ln)
+{
+ PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln);
+#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+ fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
+#endif
+#ifdef XP_MAC
+ dprintf("Assertion failure: %s, at %s:%d\n", s, file, ln);
+#endif
+#if defined(WIN32) || defined(XP_OS2)
+ DebugBreak();
+#endif
+#ifndef XP_MAC
+ abort();
+#endif
+}
+
+#ifdef XP_MAC
+PR_IMPLEMENT(void) PR_Init_Log(void)
+{
+ _PR_InitLog();
+}
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prmapopt.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prmapopt.c
new file mode 100644
index 00000000..e4811e57
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prmapopt.c
@@ -0,0 +1,517 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This file defines _PR_MapOptionName(). The purpose of putting
+ * _PR_MapOptionName() in a separate file is to work around a Winsock
+ * header file problem on Windows NT.
+ *
+ * On Windows NT, if we define _WIN32_WINNT to be 0x0400 (in order
+ * to use Service Pack 3 extensions), windows.h includes winsock2.h
+ * (instead of winsock.h), which doesn't define many socket options
+ * defined in winsock.h.
+ *
+ * We need the socket options defined in winsock.h. So this file
+ * includes winsock.h, with _WIN32_WINNT undefined.
+ */
+
+#if defined(WINNT) || defined(__MINGW32__)
+#include <winsock.h>
+#endif
+
+/* MinGW doesn't define these in its winsock.h. */
+#ifdef __MINGW32__
+#ifndef IP_TTL
+#define IP_TTL 7
+#endif
+#ifndef IP_TOS
+#define IP_TOS 8
+#endif
+#endif
+
+#include "primpl.h"
+
+#if defined(NEXTSTEP)
+/* NEXTSTEP is special: this must come before netinet/tcp.h. */
+#include <netinet/in_systm.h> /* n_short, n_long, n_time */
+#endif
+
+#if defined(XP_UNIX) || defined(OS2) || (defined(XP_BEOS) && defined(BONE_VERSION))
+#include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */
+#endif
+
+#ifndef _PR_PTHREADS
+
+PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
+{
+ PRStatus rv;
+ PRInt32 length;
+ PRInt32 level, name;
+
+ /*
+ * PR_SockOpt_Nonblocking is a special case that does not
+ * translate to a getsockopt() call
+ */
+ if (PR_SockOpt_Nonblocking == data->option)
+ {
+ data->value.non_blocking = fd->secret->nonblocking;
+ return PR_SUCCESS;
+ }
+
+ rv = _PR_MapOptionName(data->option, &level, &name);
+ if (PR_SUCCESS == rv)
+ {
+ switch (data->option)
+ {
+ case PR_SockOpt_Linger:
+ {
+#if !defined(XP_BEOS) || defined(BONE_VERSION)
+ struct linger linger;
+ length = sizeof(linger);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char *) &linger, &length);
+ if (PR_SUCCESS == rv)
+ {
+ PR_ASSERT(sizeof(linger) == length);
+ data->value.linger.polarity =
+ (linger.l_onoff) ? PR_TRUE : PR_FALSE;
+ data->value.linger.linger =
+ PR_SecondsToInterval(linger.l_linger);
+ }
+ break;
+#else
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return PR_FAILURE;
+#endif
+ }
+ case PR_SockOpt_Reuseaddr:
+ case PR_SockOpt_Keepalive:
+ case PR_SockOpt_NoDelay:
+ case PR_SockOpt_Broadcast:
+ {
+#ifdef WIN32 /* Winsock */
+ BOOL value;
+#else
+ PRIntn value;
+#endif
+ length = sizeof(value);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char*)&value, &length);
+ if (PR_SUCCESS == rv)
+ data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;
+ break;
+ }
+ case PR_SockOpt_McastLoopback:
+ {
+#ifdef WIN32 /* Winsock */
+ BOOL bool;
+#else
+ PRUint8 bool;
+#endif
+ length = sizeof(bool);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char*)&bool, &length);
+ if (PR_SUCCESS == rv)
+ data->value.mcast_loopback = (0 == bool) ? PR_FALSE : PR_TRUE;
+ break;
+ }
+ case PR_SockOpt_RecvBufferSize:
+ case PR_SockOpt_SendBufferSize:
+ case PR_SockOpt_MaxSegment:
+ {
+ PRIntn value;
+ length = sizeof(value);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char*)&value, &length);
+ if (PR_SUCCESS == rv)
+ data->value.recv_buffer_size = value;
+ break;
+ }
+ case PR_SockOpt_IpTimeToLive:
+ case PR_SockOpt_IpTypeOfService:
+ {
+ /* These options should really be an int (or PRIntn). */
+ length = sizeof(PRUintn);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char*)&data->value.ip_ttl, &length);
+ break;
+ }
+ case PR_SockOpt_McastTimeToLive:
+ {
+#ifdef WIN32 /* Winsock */
+ int ttl;
+#else
+ PRUint8 ttl;
+#endif
+ length = sizeof(ttl);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char*)&ttl, &length);
+ if (PR_SUCCESS == rv)
+ data->value.mcast_ttl = ttl;
+ break;
+ }
+#ifdef IP_ADD_MEMBERSHIP
+ case PR_SockOpt_AddMember:
+ case PR_SockOpt_DropMember:
+ {
+ struct ip_mreq mreq;
+ length = sizeof(mreq);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name, (char*)&mreq, &length);
+ if (PR_SUCCESS == rv)
+ {
+ data->value.add_member.mcaddr.inet.ip =
+ mreq.imr_multiaddr.s_addr;
+ data->value.add_member.ifaddr.inet.ip =
+ mreq.imr_interface.s_addr;
+ }
+ break;
+ }
+#endif /* IP_ADD_MEMBERSHIP */
+ case PR_SockOpt_McastInterface:
+ {
+ /* This option is a struct in_addr. */
+ length = sizeof(data->value.mcast_if.inet.ip);
+ rv = _PR_MD_GETSOCKOPT(
+ fd, level, name,
+ (char*)&data->value.mcast_if.inet.ip, &length);
+ break;
+ }
+ default:
+ PR_NOT_REACHED("Unknown socket option");
+ break;
+ }
+ }
+ return rv;
+} /* _PR_SocketGetSocketOption */
+
+PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)
+{
+ PRStatus rv;
+ PRInt32 level, name;
+
+ /*
+ * PR_SockOpt_Nonblocking is a special case that does not
+ * translate to a setsockopt call.
+ */
+ if (PR_SockOpt_Nonblocking == data->option)
+ {
+#ifdef WINNT
+ PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE)
+ || (fd->secret->nonblocking == data->value.non_blocking));
+ if (fd->secret->md.io_model_committed
+ && (fd->secret->nonblocking != data->value.non_blocking))
+ {
+ /*
+ * On NT, once we have associated a socket with the io
+ * completion port, we can't disassociate it. So we
+ * can't change the nonblocking option of the socket
+ * afterwards.
+ */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+#endif
+ fd->secret->nonblocking = data->value.non_blocking;
+ return PR_SUCCESS;
+ }
+
+ rv = _PR_MapOptionName(data->option, &level, &name);
+ if (PR_SUCCESS == rv)
+ {
+ switch (data->option)
+ {
+ case PR_SockOpt_Linger:
+ {
+#if !defined(XP_BEOS) || defined(BONE_VERSION)
+ struct linger linger;
+ linger.l_onoff = data->value.linger.polarity;
+ linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&linger, sizeof(linger));
+ break;
+#else
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return PR_FAILURE;
+#endif
+ }
+ case PR_SockOpt_Reuseaddr:
+ case PR_SockOpt_Keepalive:
+ case PR_SockOpt_NoDelay:
+ case PR_SockOpt_Broadcast:
+ {
+#ifdef WIN32 /* Winsock */
+ BOOL value;
+#else
+ PRIntn value;
+#endif
+ value = (data->value.reuse_addr) ? 1 : 0;
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&value, sizeof(value));
+ break;
+ }
+ case PR_SockOpt_McastLoopback:
+ {
+#ifdef WIN32 /* Winsock */
+ BOOL bool;
+#else
+ PRUint8 bool;
+#endif
+ bool = data->value.mcast_loopback ? 1 : 0;
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&bool, sizeof(bool));
+ break;
+ }
+ case PR_SockOpt_RecvBufferSize:
+ case PR_SockOpt_SendBufferSize:
+ case PR_SockOpt_MaxSegment:
+ {
+ PRIntn value = data->value.recv_buffer_size;
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&value, sizeof(value));
+ break;
+ }
+ case PR_SockOpt_IpTimeToLive:
+ case PR_SockOpt_IpTypeOfService:
+ {
+ /* These options should really be an int (or PRIntn). */
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn));
+ break;
+ }
+ case PR_SockOpt_McastTimeToLive:
+ {
+#ifdef WIN32 /* Winsock */
+ int ttl;
+#else
+ PRUint8 ttl;
+#endif
+ ttl = data->value.mcast_ttl;
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&ttl, sizeof(ttl));
+ break;
+ }
+#ifdef IP_ADD_MEMBERSHIP
+ case PR_SockOpt_AddMember:
+ case PR_SockOpt_DropMember:
+ {
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr =
+ data->value.add_member.mcaddr.inet.ip;
+ mreq.imr_interface.s_addr =
+ data->value.add_member.ifaddr.inet.ip;
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&mreq, sizeof(mreq));
+ break;
+ }
+#endif /* IP_ADD_MEMBERSHIP */
+ case PR_SockOpt_McastInterface:
+ {
+ /* This option is a struct in_addr. */
+ rv = _PR_MD_SETSOCKOPT(
+ fd, level, name, (char*)&data->value.mcast_if.inet.ip,
+ sizeof(data->value.mcast_if.inet.ip));
+ break;
+ }
+ default:
+ PR_NOT_REACHED("Unknown socket option");
+ break;
+ }
+ }
+ return rv;
+} /* _PR_SocketSetSocketOption */
+
+#endif /* ! _PR_PTHREADS */
+
+/*
+ *********************************************************************
+ *********************************************************************
+ **
+ ** Make sure that the following is at the end of this file,
+ ** because we will be playing with macro redefines.
+ **
+ *********************************************************************
+ *********************************************************************
+ */
+
+#if defined(VMS)
+/*
+** Sad but true. The DEC C header files define the following socket options
+** differently to what UCX is expecting. The values that UCX expects are
+** defined in SYS$LIBRARY:UCX$INETDEF.H. We redefine them here to the values
+** that UCX expects. Note that UCX V4.x will only accept these values while
+** UCX V5.x will accept either. So in theory this hack can be removed once
+** UCX V5 is the minimum.
+*/
+#undef IP_MULTICAST_IF
+#undef IP_MULTICAST_TTL
+#undef IP_MULTICAST_LOOP
+#undef IP_ADD_MEMBERSHIP
+#undef IP_DROP_MEMBERSHIP
+#include <ucx$inetdef.h>
+#define IP_MULTICAST_IF UCX$C_IP_MULTICAST_IF
+#define IP_MULTICAST_TTL UCX$C_IP_MULTICAST_TTL
+#define IP_MULTICAST_LOOP UCX$C_IP_MULTICAST_LOOP
+#define IP_ADD_MEMBERSHIP UCX$C_IP_ADD_MEMBERSHIP
+#define IP_DROP_MEMBERSHIP UCX$C_IP_DROP_MEMBERSHIP
+#endif
+
+/*
+ * Not every platform has all the socket options we want to
+ * support. Some older operating systems such as SunOS 4.1.3
+ * don't have the IP multicast socket options. Win32 doesn't
+ * have TCP_MAXSEG.
+ *
+ * To deal with this problem, we define the missing socket
+ * options as _PR_NO_SUCH_SOCKOPT. _PR_MapOptionName() fails with
+ * PR_OPERATION_NOT_SUPPORTED_ERROR if a socket option not
+ * available on the platform is requested.
+ */
+
+/*
+ * Sanity check. SO_LINGER and TCP_NODELAY should be available
+ * on all platforms. Just to make sure we have included the
+ * appropriate header files. Then any undefined socket options
+ * are really missing.
+ */
+
+#if !defined(SO_LINGER)
+#error "SO_LINGER is not defined"
+#endif
+
+/*
+ * Some platforms, such as NCR 2.03, don't have TCP_NODELAY defined
+ * in <netinet/tcp.h>
+ */
+#if !defined(NCR)
+#if !defined(TCP_NODELAY)
+#error "TCP_NODELAY is not defined"
+#endif
+#endif
+
+/*
+ * Make sure the value of _PR_NO_SUCH_SOCKOPT is not
+ * a valid socket option.
+ */
+#define _PR_NO_SUCH_SOCKOPT -1
+
+#ifndef SO_KEEPALIVE
+#define SO_KEEPALIVE _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef SO_SNDBUF
+#define SO_SNDBUF _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef SO_RCVBUF
+#define SO_RCVBUF _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_MULTICAST_IF /* set/get IP multicast interface */
+#define IP_MULTICAST_IF _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_MULTICAST_TTL /* set/get IP multicast timetolive */
+#define IP_MULTICAST_TTL _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_MULTICAST_LOOP /* set/get IP multicast loopback */
+#define IP_MULTICAST_LOOP _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_ADD_MEMBERSHIP /* add an IP group membership */
+#define IP_ADD_MEMBERSHIP _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_DROP_MEMBERSHIP /* drop an IP group membership */
+#define IP_DROP_MEMBERSHIP _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_TTL /* set/get IP Time To Live */
+#define IP_TTL _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef IP_TOS /* set/get IP Type Of Service */
+#define IP_TOS _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef TCP_NODELAY /* don't delay to coalesce data */
+#define TCP_NODELAY _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef TCP_MAXSEG /* maxumum segment size for tcp */
+#define TCP_MAXSEG _PR_NO_SUCH_SOCKOPT
+#endif
+
+#ifndef SO_BROADCAST /* enable broadcast on udp sockets */
+#define SO_BROADCAST _PR_NO_SUCH_SOCKOPT
+#endif
+
+PRStatus _PR_MapOptionName(
+ PRSockOption optname, PRInt32 *level, PRInt32 *name)
+{
+ static PRInt32 socketOptions[PR_SockOpt_Last] =
+ {
+ 0, SO_LINGER, SO_REUSEADDR, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF,
+ IP_TTL, IP_TOS, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP,
+ IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP,
+ TCP_NODELAY, TCP_MAXSEG, SO_BROADCAST
+ };
+ static PRInt32 socketLevels[PR_SockOpt_Last] =
+ {
+ 0, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET,
+ IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
+ IPPROTO_IP, IPPROTO_IP, IPPROTO_IP,
+ IPPROTO_TCP, IPPROTO_TCP, SOL_SOCKET
+ };
+
+ if ((optname < PR_SockOpt_Linger)
+ || (optname >= PR_SockOpt_Last))
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (socketOptions[optname] == _PR_NO_SUCH_SOCKOPT)
+ {
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ *name = socketOptions[optname];
+ *level = socketLevels[optname];
+ return PR_SUCCESS;
+} /* _PR_MapOptionName */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prmmap.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prmmap.c
new file mode 100644
index 00000000..e5c1e5dc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prmmap.c
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *********************************************************************
+ *
+ * Memory-mapped files
+ *
+ *********************************************************************
+ */
+
+#include "primpl.h"
+
+PR_IMPLEMENT(PRFileMap *) PR_CreateFileMap(
+ PRFileDesc *fd,
+ PRInt64 size,
+ PRFileMapProtect prot)
+{
+ PRFileMap *fmap;
+
+ PR_ASSERT(prot == PR_PROT_READONLY || prot == PR_PROT_READWRITE
+ || prot == PR_PROT_WRITECOPY);
+ fmap = PR_NEWZAP(PRFileMap);
+ if (NULL == fmap) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ fmap->fd = fd;
+ fmap->prot = prot;
+ if (_PR_MD_CREATE_FILE_MAP(fmap, size) == PR_SUCCESS) {
+ return fmap;
+ } else {
+ PR_DELETE(fmap);
+ return NULL;
+ }
+}
+
+PR_IMPLEMENT(PRInt32) PR_GetMemMapAlignment(void)
+{
+ return _PR_MD_GET_MEM_MAP_ALIGNMENT();
+}
+
+PR_IMPLEMENT(void *) PR_MemMap(
+ PRFileMap *fmap,
+ PROffset64 offset,
+ PRUint32 len)
+{
+ return _PR_MD_MEM_MAP(fmap, offset, len);
+}
+
+PR_IMPLEMENT(PRStatus) PR_MemUnmap(void *addr, PRUint32 len)
+{
+ return _PR_MD_MEM_UNMAP(addr, len);
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseFileMap(PRFileMap *fmap)
+{
+ return _PR_MD_CLOSE_FILE_MAP(fmap);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prmwait.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prmwait.c
new file mode 100644
index 00000000..8c2e5f98
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prmwait.c
@@ -0,0 +1,1491 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include "pprmwait.h"
+
+#define _MW_REHASH_MAX 11
+
+static PRLock *mw_lock = NULL;
+static _PRGlobalState *mw_state = NULL;
+
+static PRIntervalTime max_polling_interval;
+
+#ifdef WINNT
+
+typedef struct TimerEvent {
+ PRIntervalTime absolute;
+ void (*func)(void *);
+ void *arg;
+ LONG ref_count;
+ PRCList links;
+} TimerEvent;
+
+#define TIMER_EVENT_PTR(_qp) \
+ ((TimerEvent *) ((char *) (_qp) - offsetof(TimerEvent, links)))
+
+struct {
+ PRLock *ml;
+ PRCondVar *new_timer;
+ PRCondVar *cancel_timer;
+ PRThread *manager_thread;
+ PRCList timer_queue;
+} tm_vars;
+
+static PRStatus TimerInit(void);
+static void TimerManager(void *arg);
+static TimerEvent *CreateTimer(PRIntervalTime timeout,
+ void (*func)(void *), void *arg);
+static PRBool CancelTimer(TimerEvent *timer);
+
+static void TimerManager(void *arg)
+{
+ PRIntervalTime now;
+ PRIntervalTime timeout;
+ PRCList *head;
+ TimerEvent *timer;
+
+ PR_Lock(tm_vars.ml);
+ while (1)
+ {
+ if (PR_CLIST_IS_EMPTY(&tm_vars.timer_queue))
+ {
+ PR_WaitCondVar(tm_vars.new_timer, PR_INTERVAL_NO_TIMEOUT);
+ }
+ else
+ {
+ now = PR_IntervalNow();
+ head = PR_LIST_HEAD(&tm_vars.timer_queue);
+ timer = TIMER_EVENT_PTR(head);
+ if ((PRInt32) (now - timer->absolute) >= 0)
+ {
+ PR_REMOVE_LINK(head);
+ /*
+ * make its prev and next point to itself so that
+ * it's obvious that it's not on the timer_queue.
+ */
+ PR_INIT_CLIST(head);
+ PR_ASSERT(2 == timer->ref_count);
+ PR_Unlock(tm_vars.ml);
+ timer->func(timer->arg);
+ PR_Lock(tm_vars.ml);
+ timer->ref_count -= 1;
+ if (0 == timer->ref_count)
+ {
+ PR_NotifyAllCondVar(tm_vars.cancel_timer);
+ }
+ }
+ else
+ {
+ timeout = (PRIntervalTime)(timer->absolute - now);
+ PR_WaitCondVar(tm_vars.new_timer, timeout);
+ }
+ }
+ }
+ PR_Unlock(tm_vars.ml);
+}
+
+static TimerEvent *CreateTimer(
+ PRIntervalTime timeout,
+ void (*func)(void *),
+ void *arg)
+{
+ TimerEvent *timer;
+ PRCList *links, *tail;
+ TimerEvent *elem;
+
+ timer = PR_NEW(TimerEvent);
+ if (NULL == timer)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return timer;
+ }
+ timer->absolute = PR_IntervalNow() + timeout;
+ timer->func = func;
+ timer->arg = arg;
+ timer->ref_count = 2;
+ PR_Lock(tm_vars.ml);
+ tail = links = PR_LIST_TAIL(&tm_vars.timer_queue);
+ while (links->prev != tail)
+ {
+ elem = TIMER_EVENT_PTR(links);
+ if ((PRInt32)(timer->absolute - elem->absolute) >= 0)
+ {
+ break;
+ }
+ links = links->prev;
+ }
+ PR_INSERT_AFTER(&timer->links, links);
+ PR_NotifyCondVar(tm_vars.new_timer);
+ PR_Unlock(tm_vars.ml);
+ return timer;
+}
+
+static PRBool CancelTimer(TimerEvent *timer)
+{
+ PRBool canceled = PR_FALSE;
+
+ PR_Lock(tm_vars.ml);
+ timer->ref_count -= 1;
+ if (timer->links.prev == &timer->links)
+ {
+ while (timer->ref_count == 1)
+ {
+ PR_WaitCondVar(tm_vars.cancel_timer, PR_INTERVAL_NO_TIMEOUT);
+ }
+ }
+ else
+ {
+ PR_REMOVE_LINK(&timer->links);
+ canceled = PR_TRUE;
+ }
+ PR_Unlock(tm_vars.ml);
+ PR_DELETE(timer);
+ return canceled;
+}
+
+static PRStatus TimerInit(void)
+{
+ tm_vars.ml = PR_NewLock();
+ if (NULL == tm_vars.ml)
+ {
+ goto failed;
+ }
+ tm_vars.new_timer = PR_NewCondVar(tm_vars.ml);
+ if (NULL == tm_vars.new_timer)
+ {
+ goto failed;
+ }
+ tm_vars.cancel_timer = PR_NewCondVar(tm_vars.ml);
+ if (NULL == tm_vars.cancel_timer)
+ {
+ goto failed;
+ }
+ PR_INIT_CLIST(&tm_vars.timer_queue);
+ tm_vars.manager_thread = PR_CreateThread(
+ PR_SYSTEM_THREAD, TimerManager, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+ if (NULL == tm_vars.manager_thread)
+ {
+ goto failed;
+ }
+ return PR_SUCCESS;
+
+failed:
+ if (NULL != tm_vars.cancel_timer)
+ {
+ PR_DestroyCondVar(tm_vars.cancel_timer);
+ }
+ if (NULL != tm_vars.new_timer)
+ {
+ PR_DestroyCondVar(tm_vars.new_timer);
+ }
+ if (NULL != tm_vars.ml)
+ {
+ PR_DestroyLock(tm_vars.ml);
+ }
+ return PR_FAILURE;
+}
+
+#endif /* WINNT */
+
+/******************************************************************/
+/******************************************************************/
+/************************ The private portion *********************/
+/******************************************************************/
+/******************************************************************/
+void _PR_InitMW(void)
+{
+#ifdef WINNT
+ /*
+ * We use NT 4's InterlockedCompareExchange() to operate
+ * on PRMWStatus variables.
+ */
+ PR_ASSERT(sizeof(PVOID) == sizeof(PRMWStatus));
+ TimerInit();
+#endif
+ mw_lock = PR_NewLock();
+ PR_ASSERT(NULL != mw_lock);
+ mw_state = PR_NEWZAP(_PRGlobalState);
+ PR_ASSERT(NULL != mw_state);
+ PR_INIT_CLIST(&mw_state->group_list);
+ max_polling_interval = PR_MillisecondsToInterval(MAX_POLLING_INTERVAL);
+} /* _PR_InitMW */
+
+void _PR_CleanupMW(void)
+{
+ PR_DestroyLock(mw_lock);
+ mw_lock = NULL;
+ if (mw_state->group) {
+ PR_DestroyWaitGroup(mw_state->group);
+ /* mw_state->group is set to NULL as a side effect. */
+ }
+ PR_DELETE(mw_state);
+} /* _PR_CleanupMW */
+
+static PRWaitGroup *MW_Init2(void)
+{
+ PRWaitGroup *group = mw_state->group; /* it's the null group */
+ if (NULL == group) /* there is this special case */
+ {
+ group = PR_CreateWaitGroup(_PR_DEFAULT_HASH_LENGTH);
+ if (NULL == group) goto failed_alloc;
+ PR_Lock(mw_lock);
+ if (NULL == mw_state->group)
+ {
+ mw_state->group = group;
+ group = NULL;
+ }
+ PR_Unlock(mw_lock);
+ if (group != NULL) (void)PR_DestroyWaitGroup(group);
+ group = mw_state->group; /* somebody beat us to it */
+ }
+failed_alloc:
+ return group; /* whatever */
+} /* MW_Init2 */
+
+static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash)
+{
+ /*
+ ** The entries are put in the table using the fd (PRFileDesc*) of
+ ** the receive descriptor as the key. This allows us to locate
+ ** the appropriate entry aqain when the poll operation finishes.
+ **
+ ** The pointer to the file descriptor object is first divided by
+ ** the natural alignment of a pointer in the belief that object
+ ** will have at least that many zeros in the low order bits.
+ ** This may not be a good assuption.
+ **
+ ** We try to put the entry in by rehashing _MW_REHASH_MAX times. After
+ ** that we declare defeat and force the table to be reconstructed.
+ ** Since some fds might be added more than once, won't that cause
+ ** collisions even in an empty table?
+ */
+ PRIntn rehash = _MW_REHASH_MAX;
+ PRRecvWait **waiter;
+ PRUintn hidx = _MW_HASH(desc->fd, hash->length);
+ PRUintn hoffset = 0;
+
+ while (rehash-- > 0)
+ {
+ waiter = &hash->recv_wait;
+ if (NULL == waiter[hidx])
+ {
+ waiter[hidx] = desc;
+ hash->count += 1;
+#if 0
+ printf("Adding 0x%x->0x%x ", desc, desc->fd);
+ printf(
+ "table[%u:%u:*%u]: 0x%x->0x%x\n",
+ hidx, hash->count, hash->length, waiter[hidx], waiter[hidx]->fd);
+#endif
+ return _prmw_success;
+ }
+ if (desc == waiter[hidx])
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); /* desc already in table */
+ return _prmw_error;
+ }
+#if 0
+ printf("Failing 0x%x->0x%x ", desc, desc->fd);
+ printf(
+ "table[*%u:%u:%u]: 0x%x->0x%x\n",
+ hidx, hash->count, hash->length, waiter[hidx], waiter[hidx]->fd);
+#endif
+ if (0 == hoffset)
+ {
+ hoffset = _MW_HASH2(desc->fd, hash->length);
+ PR_ASSERT(0 != hoffset);
+ }
+ hidx = (hidx + hoffset) % (hash->length);
+ }
+ return _prmw_rehash;
+} /* MW_AddHashInternal */
+
+static _PR_HashStory MW_ExpandHashInternal(PRWaitGroup *group)
+{
+ PRRecvWait **desc;
+ PRUint32 pidx, length;
+ _PRWaiterHash *newHash, *oldHash = group->waiter;
+ PRBool retry;
+ _PR_HashStory hrv;
+
+ static const PRInt32 prime_number[] = {
+ _PR_DEFAULT_HASH_LENGTH, 179, 521, 907, 1427,
+ 2711, 3917, 5021, 8219, 11549, 18911, 26711, 33749, 44771};
+ PRUintn primes = (sizeof(prime_number) / sizeof(PRInt32));
+
+ /* look up the next size we'd like to use for the hash table */
+ for (pidx = 0; pidx < primes; ++pidx)
+ {
+ if (prime_number[pidx] == oldHash->length)
+ {
+ break;
+ }
+ }
+ /* table size must be one of the prime numbers */
+ PR_ASSERT(pidx < primes);
+
+ /* if pidx == primes - 1, we can't expand the table any more */
+ while (pidx < primes - 1)
+ {
+ /* next size */
+ ++pidx;
+ length = prime_number[pidx];
+
+ /* allocate the new hash table and fill it in with the old */
+ newHash = (_PRWaiterHash*)PR_CALLOC(
+ sizeof(_PRWaiterHash) + (length * sizeof(PRRecvWait*)));
+ if (NULL == newHash)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return _prmw_error;
+ }
+
+ newHash->length = length;
+ retry = PR_FALSE;
+ for (desc = &oldHash->recv_wait;
+ newHash->count < oldHash->count; ++desc)
+ {
+ PR_ASSERT(desc < &oldHash->recv_wait + oldHash->length);
+ if (NULL != *desc)
+ {
+ hrv = MW_AddHashInternal(*desc, newHash);
+ PR_ASSERT(_prmw_error != hrv);
+ if (_prmw_success != hrv)
+ {
+ PR_DELETE(newHash);
+ retry = PR_TRUE;
+ break;
+ }
+ }
+ }
+ if (retry) continue;
+
+ PR_DELETE(group->waiter);
+ group->waiter = newHash;
+ group->p_timestamp += 1;
+ return _prmw_success;
+ }
+
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return _prmw_error; /* we're hosed */
+} /* MW_ExpandHashInternal */
+
+#ifndef WINNT
+static void _MW_DoneInternal(
+ PRWaitGroup *group, PRRecvWait **waiter, PRMWStatus outcome)
+{
+ /*
+ ** Add this receive wait object to the list of finished I/O
+ ** operations for this particular group. If there are other
+ ** threads waiting on the group, notify one. If not, arrange
+ ** for this thread to return.
+ */
+
+#if 0
+ printf("Removing 0x%x->0x%x\n", *waiter, (*waiter)->fd);
+#endif
+ (*waiter)->outcome = outcome;
+ PR_APPEND_LINK(&((*waiter)->internal), &group->io_ready);
+ PR_NotifyCondVar(group->io_complete);
+ PR_ASSERT(0 != group->waiter->count);
+ group->waiter->count -= 1;
+ *waiter = NULL;
+} /* _MW_DoneInternal */
+#endif /* WINNT */
+
+static PRRecvWait **_MW_LookupInternal(PRWaitGroup *group, PRFileDesc *fd)
+{
+ /*
+ ** Find the receive wait object corresponding to the file descriptor.
+ ** Only search the wait group specified.
+ */
+ PRRecvWait **desc;
+ PRIntn rehash = _MW_REHASH_MAX;
+ _PRWaiterHash *hash = group->waiter;
+ PRUintn hidx = _MW_HASH(fd, hash->length);
+ PRUintn hoffset = 0;
+
+ while (rehash-- > 0)
+ {
+ desc = (&hash->recv_wait) + hidx;
+ if ((*desc != NULL) && ((*desc)->fd == fd)) return desc;
+ if (0 == hoffset)
+ {
+ hoffset = _MW_HASH2(fd, hash->length);
+ PR_ASSERT(0 != hoffset);
+ }
+ hidx = (hidx + hoffset) % (hash->length);
+ }
+ return NULL;
+} /* _MW_LookupInternal */
+
+#ifndef WINNT
+static PRStatus _MW_PollInternal(PRWaitGroup *group)
+{
+ PRRecvWait **waiter;
+ PRStatus rv = PR_FAILURE;
+ PRInt32 count, count_ready;
+ PRIntervalTime polling_interval;
+
+ group->poller = PR_GetCurrentThread();
+
+ while (PR_TRUE)
+ {
+ PRIntervalTime now, since_last_poll;
+ PRPollDesc *poll_list;
+
+ while (0 == group->waiter->count)
+ {
+ PRStatus st;
+ st = PR_WaitCondVar(group->new_business, PR_INTERVAL_NO_TIMEOUT);
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ if (_MW_ABORTED(st)) goto aborted;
+ }
+
+ /*
+ ** There's something to do. See if our existing polling list
+ ** is large enough for what we have to do?
+ */
+
+ while (group->polling_count < group->waiter->count)
+ {
+ PRUint32 old_count = group->waiter->count;
+ PRUint32 new_count = PR_ROUNDUP(old_count, _PR_POLL_COUNT_FUDGE);
+ PRSize new_size = sizeof(PRPollDesc) * new_count;
+ PRPollDesc *old_polling_list = group->polling_list;
+
+ PR_Unlock(group->ml);
+ poll_list = (PRPollDesc*)PR_CALLOC(new_size);
+ if (NULL == poll_list)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ PR_Lock(group->ml);
+ goto failed_alloc;
+ }
+ if (NULL != old_polling_list)
+ PR_DELETE(old_polling_list);
+ PR_Lock(group->ml);
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ group->polling_list = poll_list;
+ group->polling_count = new_count;
+ }
+
+ now = PR_IntervalNow();
+ polling_interval = max_polling_interval;
+ since_last_poll = now - group->last_poll;
+
+ waiter = &group->waiter->recv_wait;
+ poll_list = group->polling_list;
+ for (count = 0; count < group->waiter->count; ++waiter)
+ {
+ PR_ASSERT(waiter < &group->waiter->recv_wait
+ + group->waiter->length);
+ if (NULL != *waiter) /* a live one! */
+ {
+ if ((PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout)
+ && (since_last_poll >= (*waiter)->timeout))
+ _MW_DoneInternal(group, waiter, PR_MW_TIMEOUT);
+ else
+ {
+ if (PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout)
+ {
+ (*waiter)->timeout -= since_last_poll;
+ if ((*waiter)->timeout < polling_interval)
+ polling_interval = (*waiter)->timeout;
+ }
+ PR_ASSERT(poll_list < group->polling_list
+ + group->polling_count);
+ poll_list->fd = (*waiter)->fd;
+ poll_list->in_flags = PR_POLL_READ;
+ poll_list->out_flags = 0;
+#if 0
+ printf(
+ "Polling 0x%x[%d]: [fd: 0x%x, tmo: %u]\n",
+ poll_list, count, poll_list->fd, (*waiter)->timeout);
+#endif
+ poll_list += 1;
+ count += 1;
+ }
+ }
+ }
+
+ PR_ASSERT(count == group->waiter->count);
+
+ /*
+ ** If there are no more threads waiting for completion,
+ ** we need to return.
+ */
+ if ((!PR_CLIST_IS_EMPTY(&group->io_ready))
+ && (1 == group->waiting_threads)) break;
+
+ if (0 == count) continue; /* wait for new business */
+
+ group->last_poll = now;
+
+ PR_Unlock(group->ml);
+
+ count_ready = PR_Poll(group->polling_list, count, polling_interval);
+
+ PR_Lock(group->ml);
+
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ if (-1 == count_ready)
+ {
+ goto failed_poll; /* that's a shame */
+ }
+ else if (0 < count_ready)
+ {
+ for (poll_list = group->polling_list; count > 0;
+ poll_list++, count--)
+ {
+ PR_ASSERT(
+ poll_list < group->polling_list + group->polling_count);
+ if (poll_list->out_flags != 0)
+ {
+ waiter = _MW_LookupInternal(group, poll_list->fd);
+ /*
+ ** If 'waiter' is NULL, that means the wait receive
+ ** descriptor has been canceled.
+ */
+ if (NULL != waiter)
+ _MW_DoneInternal(group, waiter, PR_MW_SUCCESS);
+ }
+ }
+ }
+ /*
+ ** If there are no more threads waiting for completion,
+ ** we need to return.
+ ** This thread was "borrowed" to do the polling, but it really
+ ** belongs to the client.
+ */
+ if ((!PR_CLIST_IS_EMPTY(&group->io_ready))
+ && (1 == group->waiting_threads)) break;
+ }
+
+ rv = PR_SUCCESS;
+
+aborted:
+failed_poll:
+failed_alloc:
+ group->poller = NULL; /* we were that, not we ain't */
+ if ((_prmw_running == group->state) && (group->waiting_threads > 1))
+ {
+ /* Wake up one thread to become the new poller. */
+ PR_NotifyCondVar(group->io_complete);
+ }
+ return rv; /* we return with the lock held */
+} /* _MW_PollInternal */
+#endif /* !WINNT */
+
+static PRMWGroupState MW_TestForShutdownInternal(PRWaitGroup *group)
+{
+ PRMWGroupState rv = group->state;
+ /*
+ ** Looking at the group's fields is safe because
+ ** once the group's state is no longer running, it
+ ** cannot revert and there is a safe check on entry
+ ** to make sure no more threads are made to wait.
+ */
+ if ((_prmw_stopping == rv)
+ && (0 == group->waiting_threads))
+ {
+ rv = group->state = _prmw_stopped;
+ PR_NotifyCondVar(group->mw_manage);
+ }
+ return rv;
+} /* MW_TestForShutdownInternal */
+
+#ifndef WINNT
+static void _MW_InitialRecv(PRCList *io_ready)
+{
+ PRRecvWait *desc = (PRRecvWait*)io_ready;
+ if ((NULL == desc->buffer.start)
+ || (0 == desc->buffer.length))
+ desc->bytesRecv = 0;
+ else
+ {
+ desc->bytesRecv = desc->fd->methods->recv(
+ desc->fd, desc->buffer.start,
+ desc->buffer.length, 0, desc->timeout);
+ if (desc->bytesRecv < 0) /* SetError should already be there */
+ desc->outcome = PR_MW_FAILURE;
+ }
+} /* _MW_InitialRecv */
+#endif
+
+#ifdef WINNT
+static void NT_TimeProc(void *arg)
+{
+ _MDOverlapped *overlapped = (_MDOverlapped *)arg;
+ PRRecvWait *desc = overlapped->data.mw.desc;
+ PRFileDesc *bottom;
+
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)PR_MW_TIMEOUT, (PVOID)PR_MW_PENDING) != (PVOID)PR_MW_PENDING)
+ {
+ /* This wait recv descriptor has already completed. */
+ return;
+ }
+
+ /* close the osfd to abort the outstanding async io request */
+ /* $$$$
+ ** Little late to be checking if NSPR's on the bottom of stack,
+ ** but if we don't check, we can't assert that the private data
+ ** is what we think it is.
+ ** $$$$
+ */
+ bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL != bottom) /* now what!?!?! */
+ {
+ bottom->secret->state = _PR_FILEDESC_CLOSED;
+ if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR)
+ {
+ fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError());
+ PR_ASSERT(!"What shall I do?");
+ }
+ }
+ return;
+} /* NT_TimeProc */
+
+static PRStatus NT_HashRemove(PRWaitGroup *group, PRFileDesc *fd)
+{
+ PRRecvWait **waiter;
+
+ _PR_MD_LOCK(&group->mdlock);
+ waiter = _MW_LookupInternal(group, fd);
+ if (NULL != waiter)
+ {
+ group->waiter->count -= 1;
+ *waiter = NULL;
+ }
+ _PR_MD_UNLOCK(&group->mdlock);
+ return (NULL != waiter) ? PR_SUCCESS : PR_FAILURE;
+}
+
+PRStatus NT_HashRemoveInternal(PRWaitGroup *group, PRFileDesc *fd)
+{
+ PRRecvWait **waiter;
+
+ waiter = _MW_LookupInternal(group, fd);
+ if (NULL != waiter)
+ {
+ group->waiter->count -= 1;
+ *waiter = NULL;
+ }
+ return (NULL != waiter) ? PR_SUCCESS : PR_FAILURE;
+}
+#endif /* WINNT */
+
+/******************************************************************/
+/******************************************************************/
+/********************** The public API portion ********************/
+/******************************************************************/
+/******************************************************************/
+PR_IMPLEMENT(PRStatus) PR_AddWaitFileDesc(
+ PRWaitGroup *group, PRRecvWait *desc)
+{
+ _PR_HashStory hrv;
+ PRStatus rv = PR_FAILURE;
+#ifdef WINNT
+ _MDOverlapped *overlapped;
+ HANDLE hFile;
+ BOOL bResult;
+ DWORD dwError;
+ PRFileDesc *bottom;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ if ((NULL == group) && (NULL == (group = MW_Init2())))
+ {
+ return rv;
+ }
+
+ PR_ASSERT(NULL != desc->fd);
+
+ desc->outcome = PR_MW_PENDING; /* nice, well known value */
+ desc->bytesRecv = 0; /* likewise, though this value is ambiguious */
+
+ PR_Lock(group->ml);
+
+ if (_prmw_running != group->state)
+ {
+ /* Not allowed to add after cancelling the group */
+ desc->outcome = PR_MW_INTERRUPT;
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ PR_Unlock(group->ml);
+ return rv;
+ }
+
+#ifdef WINNT
+ _PR_MD_LOCK(&group->mdlock);
+#endif
+
+ /*
+ ** If the waiter count is zero at this point, there's no telling
+ ** how long we've been idle. Therefore, initialize the beginning
+ ** of the timing interval. As long as the list doesn't go empty,
+ ** it will maintain itself.
+ */
+ if (0 == group->waiter->count)
+ group->last_poll = PR_IntervalNow();
+
+ do
+ {
+ hrv = MW_AddHashInternal(desc, group->waiter);
+ if (_prmw_rehash != hrv) break;
+ hrv = MW_ExpandHashInternal(group); /* gruesome */
+ if (_prmw_success != hrv) break;
+ } while (PR_TRUE);
+
+#ifdef WINNT
+ _PR_MD_UNLOCK(&group->mdlock);
+#endif
+
+ PR_NotifyCondVar(group->new_business); /* tell the world */
+ rv = (_prmw_success == hrv) ? PR_SUCCESS : PR_FAILURE;
+ PR_Unlock(group->ml);
+
+#ifdef WINNT
+ overlapped = PR_NEWZAP(_MDOverlapped);
+ if (NULL == overlapped)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ NT_HashRemove(group, desc->fd);
+ return rv;
+ }
+ overlapped->ioModel = _MD_MultiWaitIO;
+ overlapped->data.mw.desc = desc;
+ overlapped->data.mw.group = group;
+ if (desc->timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ overlapped->data.mw.timer = CreateTimer(
+ desc->timeout,
+ NT_TimeProc,
+ overlapped);
+ if (0 == overlapped->data.mw.timer)
+ {
+ NT_HashRemove(group, desc->fd);
+ PR_DELETE(overlapped);
+ /*
+ * XXX It appears that a maximum of 16 timer events can
+ * be outstanding. GetLastError() returns 0 when I try it.
+ */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ }
+
+ /* Reach to the bottom layer to get the OS fd */
+ bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ hFile = (HANDLE)bottom->secret->md.osfd;
+ if (!bottom->secret->md.io_model_committed)
+ {
+ PRInt32 st;
+ st = _md_Associate(hFile);
+ PR_ASSERT(0 != st);
+ bottom->secret->md.io_model_committed = PR_TRUE;
+ }
+ bResult = ReadFile(hFile,
+ desc->buffer.start,
+ (DWORD)desc->buffer.length,
+ NULL,
+ &overlapped->overlapped);
+ if (FALSE == bResult && (dwError = GetLastError()) != ERROR_IO_PENDING)
+ {
+ if (desc->timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)PR_MW_FAILURE, (PVOID)PR_MW_PENDING)
+ == (PVOID)PR_MW_PENDING)
+ {
+ CancelTimer(overlapped->data.mw.timer);
+ }
+ NT_HashRemove(group, desc->fd);
+ PR_DELETE(overlapped);
+ }
+ _PR_MD_MAP_READ_ERROR(dwError);
+ rv = PR_FAILURE;
+ }
+#endif
+
+ return rv;
+} /* PR_AddWaitFileDesc */
+
+PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group)
+{
+ PRCList *io_ready = NULL;
+#ifdef WINNT
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ _MDOverlapped *overlapped;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ if ((NULL == group) && (NULL == (group = MW_Init2()))) goto failed_init;
+
+ PR_Lock(group->ml);
+
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto invalid_state;
+ }
+
+ group->waiting_threads += 1; /* the polling thread is counted */
+
+#ifdef WINNT
+ _PR_MD_LOCK(&group->mdlock);
+ while (PR_CLIST_IS_EMPTY(&group->io_ready))
+ {
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_IO_WAIT;
+ PR_APPEND_LINK(&me->waitQLinks, &group->wait_list);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ {
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, PR_INTERVAL_NO_TIMEOUT);
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ }
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_UNLOCK(&group->mdlock);
+ PR_Unlock(group->ml);
+ _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ me->state = _PR_RUNNING;
+ PR_Lock(group->ml);
+ _PR_MD_LOCK(&group->mdlock);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ PR_REMOVE_LINK(&me->waitQLinks);
+ _PR_MD_UNLOCK(&group->mdlock);
+ me->flags &= ~_PR_INTERRUPT;
+ me->io_suspended = PR_FALSE;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ goto aborted;
+ }
+ }
+ io_ready = PR_LIST_HEAD(&group->io_ready);
+ PR_ASSERT(io_ready != NULL);
+ PR_REMOVE_LINK(io_ready);
+ _PR_MD_UNLOCK(&group->mdlock);
+ overlapped = (_MDOverlapped *)
+ ((char *)io_ready - offsetof(_MDOverlapped, data));
+ io_ready = &overlapped->data.mw.desc->internal;
+#else
+ do
+ {
+ /*
+ ** If the I/O ready list isn't empty, have this thread
+ ** return with the first receive wait object that's available.
+ */
+ if (PR_CLIST_IS_EMPTY(&group->io_ready))
+ {
+ /*
+ ** Is there a polling thread yet? If not, grab this thread
+ ** and use it.
+ */
+ if (NULL == group->poller)
+ {
+ /*
+ ** This thread will stay do polling until it becomes the only one
+ ** left to service a completion. Then it will return and there will
+ ** be none left to actually poll or to run completions.
+ **
+ ** The polling function should only return w/ failure or
+ ** with some I/O ready.
+ */
+ if (PR_FAILURE == _MW_PollInternal(group)) goto failed_poll;
+ }
+ else
+ {
+ /*
+ ** There are four reasons a thread can be awakened from
+ ** a wait on the io_complete condition variable.
+ ** 1. Some I/O has completed, i.e., the io_ready list
+ ** is nonempty.
+ ** 2. The wait group is canceled.
+ ** 3. The thread is interrupted.
+ ** 4. The current polling thread has to leave and needs
+ ** a replacement.
+ ** The logic to find a new polling thread is made more
+ ** complicated by all the other possible events.
+ ** I tried my best to write the logic clearly, but
+ ** it is still full of if's with continue and goto.
+ */
+ PRStatus st;
+ do
+ {
+ st = PR_WaitCondVar(group->io_complete, PR_INTERVAL_NO_TIMEOUT);
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ goto aborted;
+ }
+ if (_MW_ABORTED(st) || (NULL == group->poller)) break;
+ } while (PR_CLIST_IS_EMPTY(&group->io_ready));
+
+ /*
+ ** The thread is interrupted and has to leave. It might
+ ** have also been awakened to process ready i/o or be the
+ ** new poller. To be safe, if either condition is true,
+ ** we awaken another thread to take its place.
+ */
+ if (_MW_ABORTED(st))
+ {
+ if ((NULL == group->poller
+ || !PR_CLIST_IS_EMPTY(&group->io_ready))
+ && group->waiting_threads > 1)
+ PR_NotifyCondVar(group->io_complete);
+ goto aborted;
+ }
+
+ /*
+ ** A new poller is needed, but can I be the new poller?
+ ** If there is no i/o ready, sure. But if there is any
+ ** i/o ready, it has a higher priority. I want to
+ ** process the ready i/o first and wake up another
+ ** thread to be the new poller.
+ */
+ if (NULL == group->poller)
+ {
+ if (PR_CLIST_IS_EMPTY(&group->io_ready))
+ continue;
+ if (group->waiting_threads > 1)
+ PR_NotifyCondVar(group->io_complete);
+ }
+ }
+ PR_ASSERT(!PR_CLIST_IS_EMPTY(&group->io_ready));
+ }
+ io_ready = PR_LIST_HEAD(&group->io_ready);
+ PR_NotifyCondVar(group->io_taken);
+ PR_ASSERT(io_ready != NULL);
+ PR_REMOVE_LINK(io_ready);
+ } while (NULL == io_ready);
+
+failed_poll:
+
+#endif
+
+aborted:
+
+ group->waiting_threads -= 1;
+invalid_state:
+ (void)MW_TestForShutdownInternal(group);
+ PR_Unlock(group->ml);
+
+failed_init:
+ if (NULL != io_ready)
+ {
+ /* If the operation failed, record the reason why */
+ switch (((PRRecvWait*)io_ready)->outcome)
+ {
+ case PR_MW_PENDING:
+ PR_ASSERT(0);
+ break;
+ case PR_MW_SUCCESS:
+#ifndef WINNT
+ _MW_InitialRecv(io_ready);
+#endif
+ break;
+#ifdef WINNT
+ case PR_MW_FAILURE:
+ _PR_MD_MAP_READ_ERROR(overlapped->data.mw.error);
+ break;
+#endif
+ case PR_MW_TIMEOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_MW_INTERRUPT:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ break;
+ default: break;
+ }
+#ifdef WINNT
+ if (NULL != overlapped->data.mw.timer)
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ != overlapped->data.mw.desc->timeout);
+ CancelTimer(overlapped->data.mw.timer);
+ }
+ else
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ == overlapped->data.mw.desc->timeout);
+ }
+ PR_DELETE(overlapped);
+#endif
+ }
+ return (PRRecvWait*)io_ready;
+} /* PR_WaitRecvReady */
+
+PR_IMPLEMENT(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc)
+{
+#if !defined(WINNT)
+ PRRecvWait **recv_wait;
+#endif
+ PRStatus rv = PR_SUCCESS;
+ if (NULL == group) group = mw_state->group;
+ PR_ASSERT(NULL != group);
+ if (NULL == group)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ PR_Lock(group->ml);
+
+ if (_prmw_running != group->state)
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ rv = PR_FAILURE;
+ goto unlock;
+ }
+
+#ifdef WINNT
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)PR_MW_INTERRUPT, (PVOID)PR_MW_PENDING) == (PVOID)PR_MW_PENDING)
+ {
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ goto unlock;
+ }
+ bottom->secret->state = _PR_FILEDESC_CLOSED;
+#if 0
+ fprintf(stderr, "cancel wait recv: closing socket\n");
+#endif
+ if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR)
+ {
+ fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError());
+ exit(1);
+ }
+ }
+#else
+ if (NULL != (recv_wait = _MW_LookupInternal(group, desc->fd)))
+ {
+ /* it was in the wait table */
+ _MW_DoneInternal(group, recv_wait, PR_MW_INTERRUPT);
+ goto unlock;
+ }
+ if (!PR_CLIST_IS_EMPTY(&group->io_ready))
+ {
+ /* is it already complete? */
+ PRCList *head = PR_LIST_HEAD(&group->io_ready);
+ do
+ {
+ PRRecvWait *done = (PRRecvWait*)head;
+ if (done == desc) goto unlock;
+ head = PR_NEXT_LINK(head);
+ } while (head != &group->io_ready);
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+
+#endif
+unlock:
+ PR_Unlock(group->ml);
+ return rv;
+} /* PR_CancelWaitFileDesc */
+
+PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group)
+{
+ PRRecvWait **desc;
+ PRRecvWait *recv_wait = NULL;
+#ifdef WINNT
+ _MDOverlapped *overlapped;
+ PRRecvWait **end;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#endif
+
+ if (NULL == group) group = mw_state->group;
+ PR_ASSERT(NULL != group);
+ if (NULL == group)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ PR_Lock(group->ml);
+ if (_prmw_stopped != group->state)
+ {
+ if (_prmw_running == group->state)
+ group->state = _prmw_stopping; /* so nothing new comes in */
+ if (0 == group->waiting_threads) /* is there anybody else? */
+ group->state = _prmw_stopped; /* we can stop right now */
+ else
+ {
+ PR_NotifyAllCondVar(group->new_business);
+ PR_NotifyAllCondVar(group->io_complete);
+ }
+ while (_prmw_stopped != group->state)
+ (void)PR_WaitCondVar(group->mw_manage, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+#ifdef WINNT
+ _PR_MD_LOCK(&group->mdlock);
+#endif
+ /* make all the existing descriptors look done/interrupted */
+#ifdef WINNT
+ end = &group->waiter->recv_wait + group->waiter->length;
+ for (desc = &group->waiter->recv_wait; desc < end; ++desc)
+ {
+ if (NULL != *desc)
+ {
+ if (InterlockedCompareExchange((PVOID *)&(*desc)->outcome,
+ (PVOID)PR_MW_INTERRUPT, (PVOID)PR_MW_PENDING)
+ == (PVOID)PR_MW_PENDING)
+ {
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(
+ (*desc)->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ goto invalid_arg;
+ }
+ bottom->secret->state = _PR_FILEDESC_CLOSED;
+#if 0
+ fprintf(stderr, "cancel wait group: closing socket\n");
+#endif
+ if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR)
+ {
+ fprintf(stderr, "closesocket failed: %d\n",
+ WSAGetLastError());
+ exit(1);
+ }
+ }
+ }
+ }
+ while (group->waiter->count > 0)
+ {
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_IO_WAIT;
+ PR_APPEND_LINK(&me->waitQLinks, &group->wait_list);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ {
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, PR_INTERVAL_NO_TIMEOUT);
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ }
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_UNLOCK(&group->mdlock);
+ PR_Unlock(group->ml);
+ _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ me->state = _PR_RUNNING;
+ PR_Lock(group->ml);
+ _PR_MD_LOCK(&group->mdlock);
+ }
+#else
+ for (desc = &group->waiter->recv_wait; group->waiter->count > 0; ++desc)
+ {
+ PR_ASSERT(desc < &group->waiter->recv_wait + group->waiter->length);
+ if (NULL != *desc)
+ _MW_DoneInternal(group, desc, PR_MW_INTERRUPT);
+ }
+#endif
+
+ /* take first element of finished list and return it or NULL */
+ if (PR_CLIST_IS_EMPTY(&group->io_ready))
+ PR_SetError(PR_GROUP_EMPTY_ERROR, 0);
+ else
+ {
+ PRCList *head = PR_LIST_HEAD(&group->io_ready);
+ PR_REMOVE_AND_INIT_LINK(head);
+#ifdef WINNT
+ overlapped = (_MDOverlapped *)
+ ((char *)head - offsetof(_MDOverlapped, data));
+ head = &overlapped->data.mw.desc->internal;
+ if (NULL != overlapped->data.mw.timer)
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ != overlapped->data.mw.desc->timeout);
+ CancelTimer(overlapped->data.mw.timer);
+ }
+ else
+ {
+ PR_ASSERT(PR_INTERVAL_NO_TIMEOUT
+ == overlapped->data.mw.desc->timeout);
+ }
+ PR_DELETE(overlapped);
+#endif
+ recv_wait = (PRRecvWait*)head;
+ }
+#ifdef WINNT
+invalid_arg:
+ _PR_MD_UNLOCK(&group->mdlock);
+#endif
+ PR_Unlock(group->ml);
+
+ return recv_wait;
+} /* PR_CancelWaitGroup */
+
+PR_IMPLEMENT(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size /* ignored */)
+{
+#ifdef XP_MAC
+#pragma unused (size)
+#endif
+ PRWaitGroup *wg;
+
+ if (NULL == (wg = PR_NEWZAP(PRWaitGroup)))
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto failed;
+ }
+ /* the wait group itself */
+ wg->ml = PR_NewLock();
+ if (NULL == wg->ml) goto failed_lock;
+ wg->io_taken = PR_NewCondVar(wg->ml);
+ if (NULL == wg->io_taken) goto failed_cvar0;
+ wg->io_complete = PR_NewCondVar(wg->ml);
+ if (NULL == wg->io_complete) goto failed_cvar1;
+ wg->new_business = PR_NewCondVar(wg->ml);
+ if (NULL == wg->new_business) goto failed_cvar2;
+ wg->mw_manage = PR_NewCondVar(wg->ml);
+ if (NULL == wg->mw_manage) goto failed_cvar3;
+
+ PR_INIT_CLIST(&wg->group_link);
+ PR_INIT_CLIST(&wg->io_ready);
+
+ /* the waiters sequence */
+ wg->waiter = (_PRWaiterHash*)PR_CALLOC(
+ sizeof(_PRWaiterHash) +
+ (_PR_DEFAULT_HASH_LENGTH * sizeof(PRRecvWait*)));
+ if (NULL == wg->waiter)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto failed_waiter;
+ }
+ wg->waiter->count = 0;
+ wg->waiter->length = _PR_DEFAULT_HASH_LENGTH;
+
+#ifdef WINNT
+ _PR_MD_NEW_LOCK(&wg->mdlock);
+ PR_INIT_CLIST(&wg->wait_list);
+#endif /* WINNT */
+
+ PR_Lock(mw_lock);
+ PR_APPEND_LINK(&wg->group_link, &mw_state->group_list);
+ PR_Unlock(mw_lock);
+ return wg;
+
+failed_waiter:
+ PR_DestroyCondVar(wg->mw_manage);
+failed_cvar3:
+ PR_DestroyCondVar(wg->new_business);
+failed_cvar2:
+ PR_DestroyCondVar(wg->io_complete);
+failed_cvar1:
+ PR_DestroyCondVar(wg->io_taken);
+failed_cvar0:
+ PR_DestroyLock(wg->ml);
+failed_lock:
+ PR_DELETE(wg);
+ wg = NULL;
+
+failed:
+ return wg;
+} /* MW_CreateWaitGroup */
+
+PR_IMPLEMENT(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group)
+{
+ PRStatus rv = PR_SUCCESS;
+ if (NULL == group) group = mw_state->group;
+ PR_ASSERT(NULL != group);
+ if (NULL != group)
+ {
+ PR_Lock(group->ml);
+ if ((group->waiting_threads == 0)
+ && (group->waiter->count == 0)
+ && PR_CLIST_IS_EMPTY(&group->io_ready))
+ {
+ group->state = _prmw_stopped;
+ }
+ else
+ {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ PR_Unlock(group->ml);
+ if (PR_FAILURE == rv) return rv;
+
+ PR_Lock(mw_lock);
+ PR_REMOVE_LINK(&group->group_link);
+ PR_Unlock(mw_lock);
+
+#ifdef WINNT
+ /*
+ * XXX make sure wait_list is empty and waiter is empty.
+ * These must be checked while holding mdlock.
+ */
+ _PR_MD_FREE_LOCK(&group->mdlock);
+#endif
+
+ PR_DELETE(group->waiter);
+ PR_DELETE(group->polling_list);
+ PR_DestroyCondVar(group->mw_manage);
+ PR_DestroyCondVar(group->new_business);
+ PR_DestroyCondVar(group->io_complete);
+ PR_DestroyCondVar(group->io_taken);
+ PR_DestroyLock(group->ml);
+ if (group == mw_state->group) mw_state->group = NULL;
+ PR_DELETE(group);
+ }
+ else
+ {
+ /* The default wait group is not created yet. */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* PR_DestroyWaitGroup */
+
+/**********************************************************************
+***********************************************************************
+******************** Wait group enumerations **************************
+***********************************************************************
+**********************************************************************/
+
+PR_IMPLEMENT(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group)
+{
+ PRMWaitEnumerator *enumerator = PR_NEWZAP(PRMWaitEnumerator);
+ if (NULL == enumerator) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ enumerator->group = group;
+ enumerator->seal = _PR_ENUM_SEALED;
+ }
+ return enumerator;
+} /* PR_CreateMWaitEnumerator */
+
+PR_IMPLEMENT(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator)
+{
+ PR_ASSERT(NULL != enumerator);
+ PR_ASSERT(_PR_ENUM_SEALED == enumerator->seal);
+ if ((NULL == enumerator) || (_PR_ENUM_SEALED != enumerator->seal))
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ enumerator->seal = _PR_ENUM_UNSEALED;
+ PR_Free(enumerator);
+ return PR_SUCCESS;
+} /* PR_DestroyMWaitEnumerator */
+
+PR_IMPLEMENT(PRRecvWait*) PR_EnumerateWaitGroup(
+ PRMWaitEnumerator *enumerator, const PRRecvWait *previous)
+{
+ PRRecvWait *result = NULL;
+
+ /* entry point sanity checking */
+ PR_ASSERT(NULL != enumerator);
+ PR_ASSERT(_PR_ENUM_SEALED == enumerator->seal);
+ if ((NULL == enumerator)
+ || (_PR_ENUM_SEALED != enumerator->seal)) goto bad_argument;
+
+ /* beginning of enumeration */
+ if (NULL == previous)
+ {
+ if (NULL == enumerator->group)
+ {
+ enumerator->group = mw_state->group;
+ if (NULL == enumerator->group)
+ {
+ PR_SetError(PR_GROUP_EMPTY_ERROR, 0);
+ return NULL;
+ }
+ }
+ enumerator->waiter = &enumerator->group->waiter->recv_wait;
+ enumerator->p_timestamp = enumerator->group->p_timestamp;
+ enumerator->thread = PR_GetCurrentThread();
+ enumerator->index = 0;
+ }
+ /* continuing an enumeration */
+ else
+ {
+ PRThread *me = PR_GetCurrentThread();
+ PR_ASSERT(me == enumerator->thread);
+ if (me != enumerator->thread) goto bad_argument;
+
+ /* need to restart the enumeration */
+ if (enumerator->p_timestamp != enumerator->group->p_timestamp)
+ return PR_EnumerateWaitGroup(enumerator, NULL);
+ }
+
+ /* actually progress the enumeration */
+#if defined(WINNT)
+ _PR_MD_LOCK(&enumerator->group->mdlock);
+#else
+ PR_Lock(enumerator->group->ml);
+#endif
+ while (enumerator->index++ < enumerator->group->waiter->length)
+ {
+ if (NULL != (result = *(enumerator->waiter)++)) break;
+ }
+#if defined(WINNT)
+ _PR_MD_UNLOCK(&enumerator->group->mdlock);
+#else
+ PR_Unlock(enumerator->group->ml);
+#endif
+
+ return result; /* what we live for */
+
+bad_argument:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL; /* probably ambiguous */
+} /* PR_EnumerateWaitGroup */
+
+/* prmwait.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prpolevt.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prpolevt.c
new file mode 100644
index 00000000..de5f991c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prpolevt.c
@@ -0,0 +1,530 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *********************************************************************
+ *
+ * Pollable events
+ *
+ * Pollable events are implemented using layered I/O. The only
+ * I/O methods that are implemented for pollable events are poll
+ * and close. No other methods can be invoked on a pollable
+ * event.
+ *
+ * A pipe or socket pair is created and the pollable event layer
+ * is pushed onto the read end. A pointer to the write end is
+ * saved in the PRFilePrivate structure of the pollable event.
+ *
+ *********************************************************************
+ */
+
+#include "prinit.h"
+#include "prio.h"
+#include "prmem.h"
+#include "prerror.h"
+#include "prlog.h"
+
+#ifdef VMS
+
+/*
+ * On OpenVMS we use an event flag instead of a pipe or a socket since
+ * event flags are much more efficient on OpenVMS.
+ */
+#include "pprio.h"
+#include <lib$routines.h>
+#include <starlet.h>
+#include <stsdef.h>
+
+PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
+{
+ unsigned int status;
+ int flag = -1;
+ PRFileDesc *event;
+
+ /*
+ ** Allocate an event flag and clear it.
+ */
+ status = lib$get_ef(&flag);
+ if ((!$VMS_STATUS_SUCCESS(status)) || (flag == -1)) {
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, status);
+ return NULL;
+ }
+ sys$clref(flag);
+
+ /*
+ ** Give NSPR the event flag's negative value. We do this because our
+ ** select interprets a negative fd as an event flag rather than a
+ ** regular file fd.
+ */
+ event = PR_CreateSocketPollFd(-flag);
+ if (NULL == event) {
+ lib$free_ef(&flag);
+ return NULL;
+ }
+
+ return event;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
+{
+ int flag = -PR_FileDesc2NativeHandle(event);
+ PR_DestroySocketPollFd(event);
+ lib$free_ef(&flag);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
+{
+ /*
+ ** Just set the event flag.
+ */
+ unsigned int status;
+ status = sys$setef(-PR_FileDesc2NativeHandle(event));
+ if (!$VMS_STATUS_SUCCESS(status)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, status);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
+{
+ /*
+ ** Just clear the event flag.
+ */
+ unsigned int status;
+ status = sys$clref(-PR_FileDesc2NativeHandle(event));
+ if (!$VMS_STATUS_SUCCESS(status)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, status);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+#elif defined (XP_MAC)
+
+#include "primpl.h"
+
+/*
+ * On Mac, local sockets cannot be used, because the networking stack
+ * closes them when the machine goes to sleep. Instead, we'll use a simple
+ * flag.
+ */
+
+
+/*
+ * PRFilePrivate structure for the NSPR pollable events layer
+ */
+typedef struct PRPollableDesc {
+ PRBool gotEvent;
+ PRThread *pollingThread;
+} PRPollableDesc;
+
+static PRStatus PR_CALLBACK _pr_MacPolEvtClose(PRFileDesc *fd);
+
+static PRInt16 PR_CALLBACK _pr_MacPolEvtPoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
+
+static PRIOMethods _pr_mac_polevt_methods = {
+ PR_DESC_LAYERED,
+ _pr_MacPolEvtClose,
+ (PRReadFN)_PR_InvalidInt,
+ (PRWriteFN)_PR_InvalidInt,
+ (PRAvailableFN)_PR_InvalidInt,
+ (PRAvailable64FN)_PR_InvalidInt64,
+ (PRFsyncFN)_PR_InvalidStatus,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ _pr_MacPolEvtPoll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRDescIdentity _pr_mac_polevt_id;
+static PRCallOnceType _pr_mac_polevt_once_control;
+static PRStatus PR_CALLBACK _pr_MacPolEvtInit(void);
+
+static PRInt16 PR_CALLBACK _pr_MacPolEvtPoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+ PRPollableDesc *pollDesc = (PRPollableDesc *)fd->secret;
+ PR_ASSERT(pollDesc);
+
+ // set the current thread so that we can wake up the poll thread
+ pollDesc->pollingThread = PR_GetCurrentThread();
+
+ if ((in_flags & PR_POLL_READ) && pollDesc->gotEvent)
+ *out_flags = PR_POLL_READ;
+ else
+ *out_flags = 0;
+ return pollDesc->gotEvent ? 1 : 0;
+}
+
+static PRStatus PR_CALLBACK _pr_MacPolEvtInit(void)
+{
+ _pr_mac_polevt_id = PR_GetUniqueIdentity("NSPR pollable events");
+ if (PR_INVALID_IO_LAYER == _pr_mac_polevt_id) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK _pr_MacPolEvtClose(PRFileDesc *fd)
+{
+ PRPollableDesc *pollDesc = (PRPollableDesc *)fd->secret;
+ PR_ASSERT(NULL == fd->higher && NULL == fd->lower);
+ PR_ASSERT(pollDesc);
+ PR_DELETE(pollDesc);
+ fd->dtor(fd);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
+{
+ PRFileDesc *event;
+ PRPollableDesc *pollDesc;
+
+ if (PR_CallOnce(&_pr_mac_polevt_once_control, _pr_MacPolEvtInit) == PR_FAILURE) {
+ return NULL;
+ }
+
+ event = PR_CreateIOLayerStub(_pr_mac_polevt_id, &_pr_mac_polevt_methods);
+ if (NULL == event) {
+ return NULL;
+ }
+
+ /*
+ ** Allocate an event flag and clear it.
+ */
+ pollDesc = PR_NEW(PRPollableDesc);
+ if (!pollDesc) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ pollDesc->gotEvent = PR_FALSE;
+ pollDesc->pollingThread = NULL;
+
+ event->secret = (PRFilePrivate*)pollDesc;
+ return event;
+
+errorExit:
+
+ if (event) {
+ PR_DELETE(event->secret);
+ event->dtor(event);
+ }
+ return NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
+{
+ return PR_Close(event);
+}
+
+/* from macsockotpt.c. I wish there was a cleaner way */
+extern void WakeUpNotifiedThread(PRThread *thread, OTResult result);
+
+PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
+{
+ PRPollableDesc *pollDesc = (PRPollableDesc *)event->secret;
+ PR_ASSERT(pollDesc);
+ PR_ASSERT(pollDesc->pollingThread->state != _PR_DEAD_STATE);
+
+ if (pollDesc->pollingThread->state == _PR_DEAD_STATE)
+ return PR_FAILURE;
+
+ pollDesc->gotEvent = PR_TRUE;
+
+ if (pollDesc->pollingThread)
+ WakeUpNotifiedThread(pollDesc->pollingThread, noErr);
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
+{
+ PRPollableDesc *pollDesc = (PRPollableDesc *)event->secret;
+ PRStatus status;
+ PR_ASSERT(pollDesc);
+
+ /*
+ FIXME: Danger Will Robinson!
+
+ The current implementation of PR_WaitForPollableEvent is somewhat
+ bogus; it makes the assumption that, in Mozilla, this will only
+ ever be called when PR_Poll has returned, telling us that an
+ event has been set.
+ */
+
+ PR_ASSERT(pollDesc->gotEvent);
+
+ status = (pollDesc->gotEvent) ? PR_SUCCESS : PR_FAILURE;
+ pollDesc->gotEvent = PR_FALSE;
+ return status;
+}
+
+#else /* VMS */
+
+/*
+ * These internal functions are declared in primpl.h,
+ * but we can't include primpl.h because the definition
+ * of struct PRFilePrivate in this file (for the pollable
+ * event layer) will conflict with the definition of
+ * struct PRFilePrivate in primpl.h (for the NSPR layer).
+ */
+extern PRIntn _PR_InvalidInt(void);
+extern PRInt64 _PR_InvalidInt64(void);
+extern PRStatus _PR_InvalidStatus(void);
+extern PRFileDesc *_PR_InvalidDesc(void);
+
+/*
+ * PRFilePrivate structure for the NSPR pollable events layer
+ */
+struct PRFilePrivate {
+ PRFileDesc *writeEnd; /* the write end of the pipe/socketpair */
+};
+
+static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd);
+
+static PRInt16 PR_CALLBACK _pr_PolEvtPoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags);
+
+static PRIOMethods _pr_polevt_methods = {
+ PR_DESC_LAYERED,
+ _pr_PolEvtClose,
+ (PRReadFN)_PR_InvalidInt,
+ (PRWriteFN)_PR_InvalidInt,
+ (PRAvailableFN)_PR_InvalidInt,
+ (PRAvailable64FN)_PR_InvalidInt64,
+ (PRFsyncFN)_PR_InvalidStatus,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ _pr_PolEvtPoll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRDescIdentity _pr_polevt_id;
+static PRCallOnceType _pr_polevt_once_control;
+static PRStatus PR_CALLBACK _pr_PolEvtInit(void);
+
+static PRInt16 PR_CALLBACK _pr_PolEvtPoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+ return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags);
+}
+
+static PRStatus PR_CALLBACK _pr_PolEvtInit(void)
+{
+ _pr_polevt_id = PR_GetUniqueIdentity("NSPR pollable events");
+ if (PR_INVALID_IO_LAYER == _pr_polevt_id) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+#if !defined(XP_UNIX)
+#define USE_TCP_SOCKETPAIR
+#endif
+
+PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void)
+{
+ PRFileDesc *event;
+ PRFileDesc *fd[2]; /* fd[0] is the read end; fd[1] is the write end */
+#ifdef USE_TCP_SOCKETPAIR
+ PRSocketOptionData socket_opt;
+ PRStatus rv;
+#endif
+
+ fd[0] = fd[1] = NULL;
+
+ if (PR_CallOnce(&_pr_polevt_once_control, _pr_PolEvtInit) == PR_FAILURE) {
+ return NULL;
+ }
+
+ event = PR_CreateIOLayerStub(_pr_polevt_id, &_pr_polevt_methods);
+ if (NULL == event) {
+ goto errorExit;
+ }
+ event->secret = PR_NEW(PRFilePrivate);
+ if (event->secret == NULL) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+#ifndef USE_TCP_SOCKETPAIR
+ if (PR_CreatePipe(&fd[0], &fd[1]) == PR_FAILURE) {
+ fd[0] = fd[1] = NULL;
+ goto errorExit;
+ }
+#else
+ if (PR_NewTCPSocketPair(fd) == PR_FAILURE) {
+ fd[0] = fd[1] = NULL;
+ goto errorExit;
+ }
+ /*
+ * set the TCP_NODELAY option to reduce notification latency
+ */
+ socket_opt.option = PR_SockOpt_NoDelay;
+ socket_opt.value.no_delay = PR_TRUE;
+ rv = PR_SetSocketOption(fd[1], &socket_opt);
+ PR_ASSERT(PR_SUCCESS == rv);
+#endif
+
+ event->secret->writeEnd = fd[1];
+ if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, event) == PR_FAILURE) {
+ goto errorExit;
+ }
+
+ return fd[0];
+
+errorExit:
+ if (fd[0]) {
+ PR_Close(fd[0]);
+ PR_Close(fd[1]);
+ }
+ if (event) {
+ PR_DELETE(event->secret);
+ event->dtor(event);
+ }
+ return NULL;
+}
+
+static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd)
+{
+ PRFileDesc *event;
+
+ event = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
+ PR_ASSERT(NULL == event->higher && NULL == event->lower);
+ PR_Close(fd);
+ PR_Close(event->secret->writeEnd);
+ PR_DELETE(event->secret);
+ event->dtor(event);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event)
+{
+ return PR_Close(event);
+}
+
+static const char magicChar = '\x38';
+
+PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event)
+{
+ if (PR_Write(event->secret->writeEnd, &magicChar, 1) != 1) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event)
+{
+ char buf[1024];
+ PRInt32 nBytes;
+#ifdef DEBUG
+ PRIntn i;
+#endif
+
+ nBytes = PR_Read(event->lower, buf, sizeof(buf));
+ if (nBytes == -1) {
+ return PR_FAILURE;
+ }
+
+#ifdef DEBUG
+ /*
+ * Make sure people do not write to the pollable event fd
+ * directly.
+ */
+ for (i = 0; i < nBytes; i++) {
+ PR_ASSERT(buf[i] == magicChar);
+ }
+#endif
+
+ return PR_SUCCESS;
+}
+
+#endif /* VMS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prprf.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prprf.c
new file mode 100644
index 00000000..c68e7382
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prprf.c
@@ -0,0 +1,1229 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Portable safe sprintf code.
+**
+** Author: Kipp E.B. Hickman
+*/
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "primpl.h"
+#include "prprf.h"
+#include "prlong.h"
+#include "prlog.h"
+#include "prmem.h"
+
+/*
+** WARNING: This code may *NOT* call PR_LOG (because PR_LOG calls it)
+*/
+
+/*
+** XXX This needs to be internationalized!
+*/
+
+typedef struct SprintfStateStr SprintfState;
+
+struct SprintfStateStr {
+ int (*stuff)(SprintfState *ss, const char *sp, PRUint32 len);
+
+ char *base;
+ char *cur;
+ PRUint32 maxlen;
+
+ int (*func)(void *arg, const char *sp, PRUint32 len);
+ void *arg;
+};
+
+/*
+** Numbered Argument
+*/
+struct NumArg {
+ int type; /* type of the numbered argument */
+ union { /* the numbered argument */
+ int i;
+ unsigned int ui;
+ PRInt32 i32;
+ PRUint32 ui32;
+ PRInt64 ll;
+ PRUint64 ull;
+ double d;
+ const char *s;
+ int *ip;
+ } u;
+};
+
+#define NAS_DEFAULT_NUM 20 /* default number of NumberedArgument array */
+
+
+#define TYPE_INT16 0
+#define TYPE_UINT16 1
+#define TYPE_INTN 2
+#define TYPE_UINTN 3
+#define TYPE_INT32 4
+#define TYPE_UINT32 5
+#define TYPE_INT64 6
+#define TYPE_UINT64 7
+#define TYPE_STRING 8
+#define TYPE_DOUBLE 9
+#define TYPE_INTSTR 10
+#define TYPE_UNKNOWN 20
+
+#define FLAG_LEFT 0x1
+#define FLAG_SIGNED 0x2
+#define FLAG_SPACED 0x4
+#define FLAG_ZEROS 0x8
+#define FLAG_NEG 0x10
+
+/*
+** Fill into the buffer using the data in src
+*/
+static int fill2(SprintfState *ss, const char *src, int srclen, int width,
+ int flags)
+{
+ char space = ' ';
+ int rv;
+
+ width -= srclen;
+ if ((width > 0) && ((flags & FLAG_LEFT) == 0)) { /* Right adjusting */
+ if (flags & FLAG_ZEROS) {
+ space = '0';
+ }
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Copy out the source data */
+ rv = (*ss->stuff)(ss, src, srclen);
+ if (rv < 0) {
+ return rv;
+ }
+
+ if ((width > 0) && ((flags & FLAG_LEFT) != 0)) { /* Left adjusting */
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Fill a number. The order is: optional-sign zero-filling conversion-digits
+*/
+static int fill_n(SprintfState *ss, const char *src, int srclen, int width,
+ int prec, int type, int flags)
+{
+ int zerowidth = 0;
+ int precwidth = 0;
+ int signwidth = 0;
+ int leftspaces = 0;
+ int rightspaces = 0;
+ int cvtwidth;
+ int rv;
+ char sign;
+
+ if ((type & 1) == 0) {
+ if (flags & FLAG_NEG) {
+ sign = '-';
+ signwidth = 1;
+ } else if (flags & FLAG_SIGNED) {
+ sign = '+';
+ signwidth = 1;
+ } else if (flags & FLAG_SPACED) {
+ sign = ' ';
+ signwidth = 1;
+ }
+ }
+ cvtwidth = signwidth + srclen;
+
+ if (prec > 0) {
+ if (prec > srclen) {
+ precwidth = prec - srclen; /* Need zero filling */
+ cvtwidth += precwidth;
+ }
+ }
+
+ if ((flags & FLAG_ZEROS) && (prec < 0)) {
+ if (width > cvtwidth) {
+ zerowidth = width - cvtwidth; /* Zero filling */
+ cvtwidth += zerowidth;
+ }
+ }
+
+ if (flags & FLAG_LEFT) {
+ if (width > cvtwidth) {
+ /* Space filling on the right (i.e. left adjusting) */
+ rightspaces = width - cvtwidth;
+ }
+ } else {
+ if (width > cvtwidth) {
+ /* Space filling on the left (i.e. right adjusting) */
+ leftspaces = width - cvtwidth;
+ }
+ }
+ while (--leftspaces >= 0) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ if (signwidth) {
+ rv = (*ss->stuff)(ss, &sign, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--precwidth >= 0) {
+ rv = (*ss->stuff)(ss, "0", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--zerowidth >= 0) {
+ rv = (*ss->stuff)(ss, "0", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ rv = (*ss->stuff)(ss, src, srclen);
+ if (rv < 0) {
+ return rv;
+ }
+ while (--rightspaces >= 0) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*
+** Convert a long into its printable form
+*/
+static int cvt_l(SprintfState *ss, long num, int width, int prec, int radix,
+ int type, int flags, const char *hexp)
+{
+ char cvtbuf[100];
+ char *cvt;
+ int digits;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (num == 0)) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ cvt = cvtbuf + sizeof(cvtbuf);
+ digits = 0;
+ while (num) {
+ int digit = (((unsigned long)num) % radix) & 0xF;
+ *--cvt = hexp[digit];
+ digits++;
+ num = (long)(((unsigned long)num) / radix);
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a 64-bit integer into its printable form
+*/
+static int cvt_ll(SprintfState *ss, PRInt64 num, int width, int prec, int radix,
+ int type, int flags, const char *hexp)
+{
+ char cvtbuf[100];
+ char *cvt;
+ int digits;
+ PRInt64 rad;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (LL_IS_ZERO(num))) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ LL_I2L(rad, radix);
+ cvt = cvtbuf + sizeof(cvtbuf);
+ digits = 0;
+ while (!LL_IS_ZERO(num)) {
+ PRInt32 digit;
+ PRInt64 quot, rem;
+ LL_UDIVMOD(&quot, &rem, num, rad);
+ LL_L2I(digit, rem);
+ *--cvt = hexp[digit & 0xf];
+ digits++;
+ num = quot;
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a double precision floating point number into its printable
+** form.
+**
+** XXX stop using snprintf to convert floating point
+*/
+static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1)
+{
+ char fin[20];
+ char fout[300];
+ int amount = fmt1 - fmt0;
+
+ if (amount <= 0 || amount >= sizeof(fin)) {
+ /* Totally bogus % command to snprintf. Just ignore it */
+ return 0;
+ }
+ memcpy(fin, fmt0, amount);
+ fin[amount] = 0;
+
+ /* Convert floating point using the native snprintf code */
+#ifdef DEBUG
+ {
+ const char *p = fin;
+ while (*p) {
+ PR_ASSERT(*p != 'L');
+ p++;
+ }
+ }
+#endif
+ memset(fout, 0, sizeof(fout));
+ snprintf(fout, sizeof(fout), fin, d);
+ /* Explicitly null-terminate fout because on Windows snprintf doesn't
+ * append a null-terminator if the buffer is too small. */
+ fout[sizeof(fout) - 1] = '\0';
+
+ return (*ss->stuff)(ss, fout, strlen(fout));
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_s(SprintfState *ss, const char *s, int width, int prec,
+ int flags)
+{
+ int slen;
+
+ if (prec == 0)
+ return 0;
+
+ /* Limit string length by precision value */
+ slen = s ? strlen(s) : 6;
+ if (prec > 0) {
+ if (prec < slen) {
+ slen = prec;
+ }
+ }
+
+ /* and away we go */
+ return fill2(ss, s ? s : "(null)", slen, width, flags);
+}
+
+/*
+** BiuldArgArray stands for Numbered Argument list Sprintf
+** for example,
+** fmp = "%4$i, %2$d, %3s, %1d";
+** the number must start from 1, and no gap among them
+*/
+
+static struct NumArg* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArg* nasArray )
+{
+ int number = 0, cn = 0, i;
+ const char* p;
+ char c;
+ struct NumArg* nas;
+
+
+ /*
+ ** first pass:
+ ** detemine how many legal % I have got, then allocate space
+ */
+
+ p = fmt;
+ *rv = 0;
+ i = 0;
+ while( ( c = *p++ ) != 0 ){
+ if( c != '%' )
+ continue;
+ if( ( c = *p++ ) == '%' ) /* skip %% case */
+ continue;
+
+ while( c != 0 ){
+ if( c > '9' || c < '0' ){
+ if( c == '$' ){ /* numbered argument case */
+ if( i > 0 ){
+ *rv = -1;
+ return NULL;
+ }
+ number++;
+ } else{ /* non-numbered argument case */
+ if( number > 0 ){
+ *rv = -1;
+ return NULL;
+ }
+ i = 1;
+ }
+ break;
+ }
+
+ c = *p++;
+ }
+ }
+
+ if( number == 0 ){
+ return NULL;
+ }
+
+
+ if( number > NAS_DEFAULT_NUM ){
+ nas = (struct NumArg*)PR_MALLOC( number * sizeof( struct NumArg ) );
+ if( !nas ){
+ *rv = -1;
+ return NULL;
+ }
+ } else {
+ nas = nasArray;
+ }
+
+ for( i = 0; i < number; i++ ){
+ nas[i].type = TYPE_UNKNOWN;
+ }
+
+
+ /*
+ ** second pass:
+ ** set nas[].type
+ */
+
+ p = fmt;
+ while( ( c = *p++ ) != 0 ){
+ if( c != '%' ) continue;
+ c = *p++;
+ if( c == '%' ) continue;
+
+ cn = 0;
+ while( c && c != '$' ){ /* should imporve error check later */
+ cn = cn*10 + c - '0';
+ c = *p++;
+ }
+
+ if( !c || cn < 1 || cn > number ){
+ *rv = -1;
+ break;
+ }
+
+ /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */
+ cn--;
+ if( nas[cn].type != TYPE_UNKNOWN )
+ continue;
+
+ c = *p++;
+
+ /* width */
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ }
+
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ c = *p++;
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ }
+
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+
+ /* size */
+ nas[cn].type = TYPE_INTN;
+ if (c == 'h') {
+ nas[cn].type = TYPE_INT16;
+ c = *p++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ } else if (c == 'l') {
+ nas[cn].type = TYPE_INT32;
+ c = *p++;
+ if (c == 'l') {
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ }
+ }
+
+ /* format */
+ switch (c) {
+ case 'd':
+ case 'c':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ nas[ cn ].type = TYPE_DOUBLE;
+ break;
+
+ case 'p':
+ /* XXX should use cpp */
+ if (sizeof(void *) == sizeof(PRInt32)) {
+ nas[ cn ].type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(PRInt64)) {
+ nas[ cn ].type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(PRIntn)) {
+ nas[ cn ].type = TYPE_UINTN;
+ } else {
+ nas[ cn ].type = TYPE_UNKNOWN;
+ }
+ break;
+
+ case 'C':
+ case 'S':
+ case 'E':
+ case 'G':
+ /* XXX not supported I suppose */
+ PR_ASSERT(0);
+ nas[ cn ].type = TYPE_UNKNOWN;
+ break;
+
+ case 's':
+ nas[ cn ].type = TYPE_STRING;
+ break;
+
+ case 'n':
+ nas[ cn ].type = TYPE_INTSTR;
+ break;
+
+ default:
+ PR_ASSERT(0);
+ nas[ cn ].type = TYPE_UNKNOWN;
+ break;
+ }
+
+ /* get a legal para. */
+ if( nas[ cn ].type == TYPE_UNKNOWN ){
+ *rv = -1;
+ break;
+ }
+ }
+
+
+ /*
+ ** third pass
+ ** fill the nas[cn].ap
+ */
+
+ if( *rv < 0 ){
+ if( nas != nasArray )
+ PR_DELETE( nas );
+ return NULL;
+ }
+
+ cn = 0;
+ while( cn < number ){
+ if( nas[cn].type == TYPE_UNKNOWN ){
+ cn++;
+ continue;
+ }
+
+ switch( nas[cn].type ){
+ case TYPE_INT16:
+ case TYPE_UINT16:
+ case TYPE_INTN:
+ nas[cn].u.i = va_arg( ap, int );
+ break;
+
+ case TYPE_UINTN:
+ nas[cn].u.ui = va_arg( ap, unsigned int );
+ break;
+
+ case TYPE_INT32:
+ nas[cn].u.i32 = va_arg( ap, PRInt32 );
+ break;
+
+ case TYPE_UINT32:
+ nas[cn].u.ui32 = va_arg( ap, PRUint32 );
+ break;
+
+ case TYPE_INT64:
+ nas[cn].u.ll = va_arg( ap, PRInt64 );
+ break;
+
+ case TYPE_UINT64:
+ nas[cn].u.ull = va_arg( ap, PRUint64 );
+ break;
+
+ case TYPE_STRING:
+ nas[cn].u.s = va_arg( ap, char* );
+ break;
+
+ case TYPE_INTSTR:
+ nas[cn].u.ip = va_arg( ap, int* );
+ break;
+
+ case TYPE_DOUBLE:
+ nas[cn].u.d = va_arg( ap, double );
+ break;
+
+ default:
+ if( nas != nasArray )
+ PR_DELETE( nas );
+ *rv = -1;
+ return NULL;
+ }
+
+ cn++;
+ }
+
+
+ return nas;
+}
+
+/*
+** The workhorse sprintf code.
+*/
+static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
+{
+ char c;
+ int flags, width, prec, radix, type;
+ union {
+ char ch;
+ int i;
+ long l;
+ PRInt64 ll;
+ double d;
+ const char *s;
+ int *ip;
+ } u;
+ const char *fmt0;
+ static char *hex = "0123456789abcdef";
+ static char *HEX = "0123456789ABCDEF";
+ char *hexp;
+ int rv, i;
+ struct NumArg* nas = NULL;
+ struct NumArg* nap;
+ struct NumArg nasArray[ NAS_DEFAULT_NUM ];
+ char pattern[20];
+ const char* dolPt = NULL; /* in "%4$.2f", dolPt will point to . */
+
+
+ /*
+ ** build an argument array, IF the fmt is numbered argument
+ ** list style, to contain the Numbered Argument list pointers
+ */
+
+ nas = BuildArgArray( fmt, ap, &rv, nasArray );
+ if( rv < 0 ){
+ /* the fmt contains error Numbered Argument format, jliu@netscape.com */
+ PR_ASSERT(0);
+ return rv;
+ }
+
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+ fmt0 = fmt - 1;
+
+ /*
+ ** Gobble up the % format string. Hopefully we have handled all
+ ** of the strange cases!
+ */
+ flags = 0;
+ c = *fmt++;
+ if (c == '%') {
+ /* quoting a % with %% */
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ if( nas != NULL ){
+ /* the fmt contains the Numbered Arguments feature */
+ i = 0;
+ while( c && c != '$' ){ /* should imporve error check later */
+ i = ( i * 10 ) + ( c - '0' );
+ c = *fmt++;
+ }
+
+ if( nas[i-1].type == TYPE_UNKNOWN ){
+ if( nas && ( nas != nasArray ) )
+ PR_DELETE( nas );
+ return -1;
+ }
+
+ nap = &nas[i-1];
+ dolPt = fmt;
+ c = *fmt++;
+ }
+
+ /*
+ * Examine optional flags. Note that we do not implement the
+ * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is
+ * somewhat ambiguous and not ideal, which is perhaps why
+ * the various sprintf() implementations are inconsistent
+ * on this feature.
+ */
+#ifdef VBOX
+ /* this is not expected so just ignore this flags */
+ while (c == '#')
+ c = *fmt++;
+#endif
+ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
+ if (c == '-') flags |= FLAG_LEFT;
+ if (c == '+') flags |= FLAG_SIGNED;
+ if (c == ' ') flags |= FLAG_SPACED;
+ if (c == '0') flags |= FLAG_ZEROS;
+ c = *fmt++;
+ }
+ if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED;
+ if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS;
+
+ /* width */
+ if (c == '*') {
+ c = *fmt++;
+ width = va_arg(ap, int);
+ } else {
+ width = 0;
+ while ((c >= '0') && (c <= '9')) {
+ width = (width * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+
+ /* precision */
+ prec = -1;
+ if (c == '.') {
+ c = *fmt++;
+ if (c == '*') {
+ c = *fmt++;
+ prec = va_arg(ap, int);
+ } else {
+ prec = 0;
+ while ((c >= '0') && (c <= '9')) {
+ prec = (prec * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+ }
+
+ /* size */
+ type = TYPE_INTN;
+ if (c == 'h') {
+ type = TYPE_INT16;
+ c = *fmt++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ type = TYPE_INT64;
+ c = *fmt++;
+ } else if (c == 'l') {
+ type = TYPE_INT32;
+ c = *fmt++;
+ if (c == 'l') {
+ type = TYPE_INT64;
+ c = *fmt++;
+ }
+ }
+
+ /* format */
+ hexp = hex;
+ switch (c) {
+ case 'd': case 'i': /* decimal/integer */
+ radix = 10;
+ goto fetch_and_convert;
+
+ case 'o': /* octal */
+ radix = 8;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'u': /* unsigned decimal */
+ radix = 10;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'x': /* unsigned hex */
+ radix = 16;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'X': /* unsigned HEX */
+ radix = 16;
+ hexp = HEX;
+ type |= 1;
+ goto fetch_and_convert;
+
+ fetch_and_convert:
+ switch (type) {
+ case TYPE_INT16:
+ u.l = nas ? nap->u.i : va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINT16:
+ u.l = (nas ? nap->u.i : va_arg(ap, int)) & 0xffff;
+ goto do_long;
+ case TYPE_INTN:
+ u.l = nas ? nap->u.i : va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINTN:
+ u.l = (long)(nas ? nap->u.ui : va_arg(ap, unsigned int));
+ goto do_long;
+
+ case TYPE_INT32:
+ u.l = nas ? nap->u.i32 : va_arg(ap, PRInt32);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINT32:
+ u.l = (long)(nas ? nap->u.ui32 : va_arg(ap, PRUint32));
+ do_long:
+ rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case TYPE_INT64:
+ u.ll = nas ? nap->u.ll : va_arg(ap, PRInt64);
+ if (!LL_GE_ZERO(u.ll)) {
+ LL_NEG(u.ll, u.ll);
+ flags |= FLAG_NEG;
+ }
+ goto do_longlong;
+ case TYPE_UINT64:
+ u.ll = nas ? nap->u.ull : va_arg(ap, PRUint64);
+ do_longlong:
+ rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ u.d = nas ? nap->u.d : va_arg(ap, double);
+ if( nas != NULL ){
+ i = fmt - dolPt;
+ if( i < sizeof( pattern ) ){
+ pattern[0] = '%';
+ memcpy( &pattern[1], dolPt, i );
+ rv = cvt_f(ss, u.d, pattern, &pattern[i+1] );
+ }
+ } else
+ rv = cvt_f(ss, u.d, fmt0, fmt);
+
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'c':
+ u.ch = nas ? nap->u.i : va_arg(ap, int);
+ if ((flags & FLAG_LEFT) == 0) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ rv = (*ss->stuff)(ss, &u.ch, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ if (flags & FLAG_LEFT) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ break;
+
+ case 'p':
+ if (sizeof(void *) == sizeof(PRInt32)) {
+ type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(PRInt64)) {
+ type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(int)) {
+ type = TYPE_UINTN;
+ } else {
+ PR_ASSERT(0);
+ break;
+ }
+ radix = 16;
+ goto fetch_and_convert;
+
+#if 0
+ case 'C':
+ case 'S':
+ case 'E':
+ case 'G':
+ /* XXX not supported I suppose */
+ PR_ASSERT(0);
+ break;
+#endif
+
+ case 's':
+ u.s = nas ? nap->u.s : va_arg(ap, const char*);
+ rv = cvt_s(ss, u.s, width, prec, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'n':
+ u.ip = nas ? nap->u.ip : va_arg(ap, int*);
+ if (u.ip) {
+ *u.ip = ss->cur - ss->base;
+ }
+ break;
+
+ default:
+ /* Not a % token after all... skip it */
+#if 0
+ PR_ASSERT(0);
+#endif
+ rv = (*ss->stuff)(ss, "%", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Stuff trailing NUL */
+ rv = (*ss->stuff)(ss, "\0", 1);
+
+ if( nas && ( nas != nasArray ) ){
+ PR_DELETE( nas );
+ }
+
+ return rv;
+}
+
+/************************************************************************/
+
+static int FuncStuff(SprintfState *ss, const char *sp, PRUint32 len)
+{
+ int rv;
+
+ rv = (*ss->func)(ss->arg, sp, len);
+ if (rv < 0) {
+ return rv;
+ }
+ ss->maxlen += len;
+ return 0;
+}
+
+PR_IMPLEMENT(PRUint32) PR_sxprintf(PRStuffFunc func, void *arg,
+ const char *fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ va_start(ap, fmt);
+ rv = PR_vsxprintf(func, arg, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PR_IMPLEMENT(PRUint32) PR_vsxprintf(PRStuffFunc func, void *arg,
+ const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = FuncStuff;
+ ss.func = func;
+ ss.arg = arg;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ return (rv < 0) ? (PRUint32)-1 : ss.maxlen;
+}
+
+/*
+** Stuff routine that automatically grows the malloc'd output buffer
+** before it overflows.
+*/
+static int GrowStuff(SprintfState *ss, const char *sp, PRUint32 len)
+{
+ ptrdiff_t off;
+ char *newbase;
+ PRUint32 newlen;
+
+ off = ss->cur - ss->base;
+ if (off + len >= ss->maxlen) {
+ /* Grow the buffer */
+ newlen = ss->maxlen + ((len > 32) ? len : 32);
+ if (ss->base) {
+ newbase = (char*) PR_REALLOC(ss->base, newlen);
+ } else {
+ newbase = (char*) PR_MALLOC(newlen);
+ }
+ if (!newbase) {
+ /* Ran out of memory */
+ return -1;
+ }
+ ss->base = newbase;
+ ss->maxlen = newlen;
+ ss->cur = ss->base + off;
+ }
+
+ /* Copy data */
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ PR_ASSERT((PRUint32)(ss->cur - ss->base) <= ss->maxlen);
+ return 0;
+}
+
+/*
+** sprintf into a malloc'd buffer
+*/
+PR_IMPLEMENT(char *) PR_smprintf(const char *fmt, ...)
+{
+ va_list ap;
+ char *rv;
+
+ va_start(ap, fmt);
+ rv = PR_vsmprintf(fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+/*
+** Free memory allocated, for the caller, by PR_smprintf
+*/
+PR_IMPLEMENT(void) PR_smprintf_free(char *mem)
+{
+ PR_DELETE(mem);
+}
+
+PR_IMPLEMENT(char *) PR_vsmprintf(const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ PR_DELETE(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
+/*
+** Stuff routine that discards overflow data
+*/
+static int LimitStuff(SprintfState *ss, const char *sp, PRUint32 len)
+{
+ PRUint32 limit = ss->maxlen - (ss->cur - ss->base);
+
+ if (len > limit) {
+ len = limit;
+ }
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ return 0;
+}
+
+/*
+** sprintf into a fixed size buffer. Make sure there is a NUL at the end
+** when finished.
+*/
+PR_IMPLEMENT(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ PR_ASSERT((PRInt32)outlen > 0);
+ if ((PRInt32)outlen <= 0) {
+ return 0;
+ }
+
+ va_start(ap, fmt);
+ rv = PR_vsnprintf(out, outlen, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PR_IMPLEMENT(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen,const char *fmt,
+ va_list ap)
+{
+ SprintfState ss;
+ PRUint32 n;
+
+ PR_ASSERT((PRInt32)outlen > 0);
+ if ((PRInt32)outlen <= 0) {
+ return 0;
+ }
+
+ ss.stuff = LimitStuff;
+ ss.base = out;
+ ss.cur = out;
+ ss.maxlen = outlen;
+ (void) dosprintf(&ss, fmt, ap);
+
+ /* If we added chars, and we didn't append a null, do it now. */
+ if( (ss.cur != ss.base) && (*(ss.cur - 1) != '\0') )
+ *(ss.cur - 1) = '\0';
+
+ n = ss.cur - ss.base;
+ return n ? n - 1 : n;
+}
+
+PR_IMPLEMENT(char *) PR_sprintf_append(char *last, const char *fmt, ...)
+{
+ va_list ap;
+ char *rv;
+
+ va_start(ap, fmt);
+ rv = PR_vsprintf_append(last, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PR_IMPLEMENT(char *) PR_vsprintf_append(char *last, const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ if (last) {
+ int lastlen = strlen(last);
+ ss.base = last;
+ ss.cur = last + lastlen;
+ ss.maxlen = lastlen;
+ } else {
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ }
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ PR_DELETE(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prscanf.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prscanf.c
new file mode 100644
index 00000000..6fad0f70
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prscanf.c
@@ -0,0 +1,669 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Scan functions for NSPR types
+ *
+ * Author: Wan-Teh Chang
+ *
+ * Acknowledgment: The implementation is inspired by the source code
+ * in P.J. Plauger's "The Standard C Library," Prentice-Hall, 1992.
+ */
+
+#include <limits.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef SUNOS4
+#include "md/sunos4.h" /* for strtoul */
+#endif
+#include "prprf.h"
+#include "prdtoa.h"
+#include "prlog.h"
+#include "prerror.h"
+
+/*
+ * A function that reads a character from 'stream'.
+ * Returns the character read, or EOF if end of stream is reached.
+ */
+typedef int (*_PRGetCharFN)(void *stream);
+
+/*
+ * A function that pushes the character 'ch' back to 'stream'.
+ */
+typedef void (*_PRUngetCharFN)(void *stream, int ch);
+
+/*
+ * The size specifier for the integer and floating point number
+ * conversions in format control strings.
+ */
+typedef enum {
+ _PR_size_none, /* No size specifier is given */
+ _PR_size_h, /* The 'h' specifier, suggesting "short" */
+ _PR_size_l, /* The 'l' specifier, suggesting "long" */
+ _PR_size_L, /* The 'L' specifier, meaning a 'long double' */
+ _PR_size_ll /* The 'll' specifier, suggesting "long long" */
+} _PRSizeSpec;
+
+/*
+ * The collection of data that is passed between the scan function
+ * and its subordinate functions. The fields of this structure
+ * serve as the input or output arguments for these functions.
+ */
+typedef struct {
+ _PRGetCharFN get; /* get a character from input stream */
+ _PRUngetCharFN unget; /* unget (push back) a character */
+ void *stream; /* argument for get and unget */
+ va_list ap; /* the variable argument list */
+ int nChar; /* number of characters read from 'stream' */
+
+ PRBool assign; /* assign, or suppress assignment? */
+ int width; /* field width */
+ _PRSizeSpec sizeSpec; /* 'h', 'l', 'L', or 'll' */
+
+ PRBool converted; /* is the value actually converted? */
+} ScanfState;
+
+#define GET(state) ((state)->nChar++, (state)->get((state)->stream))
+#define UNGET(state, ch) \
+ ((state)->nChar--, (state)->unget((state)->stream, ch))
+
+/*
+ * The following two macros, GET_IF_WITHIN_WIDTH and WITHIN_WIDTH,
+ * are always used together.
+ *
+ * GET_IF_WITHIN_WIDTH calls the GET macro and assigns its return
+ * value to 'ch' only if we have not exceeded the field width of
+ * 'state'. Therefore, after GET_IF_WITHIN_WIDTH, the value of
+ * 'ch' is valid only if the macro WITHIN_WIDTH evaluates to true.
+ */
+
+#define GET_IF_WITHIN_WIDTH(state, ch) \
+ if (--(state)->width >= 0) { \
+ (ch) = GET(state); \
+ }
+#define WITHIN_WIDTH(state) ((state)->width >= 0)
+
+/*
+ * _pr_strtoull:
+ * Convert a string to an unsigned 64-bit integer. The string
+ * 'str' is assumed to be a representation of the integer in
+ * base 'base'.
+ *
+ * Warning:
+ * - Only handle base 8, 10, and 16.
+ * - No overflow checking.
+ */
+
+static PRUint64
+_pr_strtoull(const char *str, char **endptr, int base)
+{
+ static const int BASE_MAX = 16;
+ static const char digits[] = "0123456789abcdef";
+ char *digitPtr;
+ PRUint64 x; /* return value */
+ PRInt64 base64;
+ const char *cPtr;
+ PRBool negative;
+ const char *digitStart;
+
+ PR_ASSERT(base == 0 || base == 8 || base == 10 || base == 16);
+ if (base < 0 || base == 1 || base > BASE_MAX) {
+ if (endptr) {
+ *endptr = (char *) str;
+ return LL_ZERO;
+ }
+ }
+
+ cPtr = str;
+ while (isspace(*cPtr)) {
+ ++cPtr;
+ }
+
+ negative = PR_FALSE;
+ if (*cPtr == '-') {
+ negative = PR_TRUE;
+ cPtr++;
+ } else if (*cPtr == '+') {
+ cPtr++;
+ }
+
+ if (base == 16) {
+ if (*cPtr == '0' && (cPtr[1] == 'x' || cPtr[1] == 'X')) {
+ cPtr += 2;
+ }
+ } else if (base == 0) {
+ if (*cPtr != '0') {
+ base = 10;
+ } else if (cPtr[1] == 'x' || cPtr[1] == 'X') {
+ base = 16;
+ cPtr += 2;
+ } else {
+ base = 8;
+ }
+ }
+ PR_ASSERT(base != 0);
+ LL_I2L(base64, base);
+ digitStart = cPtr;
+
+ /* Skip leading zeros */
+ while (*cPtr == '0') {
+ cPtr++;
+ }
+
+ LL_I2L(x, 0);
+ while ((digitPtr = (char*)memchr(digits, tolower(*cPtr), base)) != NULL) {
+ PRUint64 d;
+
+ LL_I2L(d, (digitPtr - digits));
+ LL_MUL(x, x, base64);
+ LL_ADD(x, x, d);
+ cPtr++;
+ }
+
+ if (cPtr == digitStart) {
+ if (endptr) {
+ *endptr = (char *) str;
+ }
+ return LL_ZERO;
+ }
+
+ if (negative) {
+#ifdef HAVE_LONG_LONG
+ /* The cast to a signed type is to avoid a compiler warning */
+ x = -(PRInt64)x;
+#else
+ LL_NEG(x, x);
+#endif
+ }
+
+ if (endptr) {
+ *endptr = (char *) cPtr;
+ }
+ return x;
+}
+
+/*
+ * The maximum field width (in number of characters) that is enough
+ * (may be more than necessary) to represent a 64-bit integer or
+ * floating point number.
+ */
+#define FMAX 31
+#define DECIMAL_POINT '.'
+
+static PRStatus
+GetInt(ScanfState *state, int code)
+{
+ char buf[FMAX + 1], *p;
+ int ch;
+ static const char digits[] = "0123456789abcdefABCDEF";
+ PRBool seenDigit = PR_FALSE;
+ int base;
+ int dlen;
+
+ switch (code) {
+ case 'd': case 'u':
+ base = 10;
+ break;
+ case 'i':
+ base = 0;
+ break;
+ case 'x': case 'X': case 'p':
+ base = 16;
+ break;
+ case 'o':
+ base = 8;
+ break;
+ default:
+ return PR_FAILURE;
+ }
+ if (state->width == 0 || state->width > FMAX) {
+ state->width = FMAX;
+ }
+ p = buf;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ }
+ if (WITHIN_WIDTH(state) && ch == '0') {
+ seenDigit = PR_TRUE;
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ if (WITHIN_WIDTH(state)
+ && (ch == 'x' || ch == 'X')
+ && (base == 0 || base == 16)) {
+ base = 16;
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ } else if (base == 0) {
+ base = 8;
+ }
+ }
+ if (base == 0 || base == 10) {
+ dlen = 10;
+ } else if (base == 8) {
+ dlen = 8;
+ } else {
+ PR_ASSERT(base == 16);
+ dlen = 16 + 6; /* 16 digits, plus 6 in uppercase */
+ }
+ while (WITHIN_WIDTH(state) && memchr(digits, ch, dlen)) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ seenDigit = PR_TRUE;
+ }
+ if (WITHIN_WIDTH(state)) {
+ UNGET(state, ch);
+ }
+ if (!seenDigit) {
+ return PR_FAILURE;
+ }
+ *p = '\0';
+ if (state->assign) {
+ if (code == 'd' || code == 'i') {
+ if (state->sizeSpec == _PR_size_ll) {
+ PRInt64 llval = _pr_strtoull(buf, NULL, base);
+ *va_arg(state->ap, PRInt64 *) = llval;
+ } else {
+ long lval = strtol(buf, NULL, base);
+
+ if (state->sizeSpec == _PR_size_none) {
+ *va_arg(state->ap, PRIntn *) = lval;
+ } else if (state->sizeSpec == _PR_size_h) {
+ *va_arg(state->ap, PRInt16 *) = (PRInt16)lval;
+ } else if (state->sizeSpec == _PR_size_l) {
+ *va_arg(state->ap, PRInt32 *) = lval;
+ } else {
+ return PR_FAILURE;
+ }
+ }
+ } else {
+ if (state->sizeSpec == _PR_size_ll) {
+ PRUint64 llval = _pr_strtoull(buf, NULL, base);
+ *va_arg(state->ap, PRUint64 *) = llval;
+ } else {
+ unsigned long lval = strtoul(buf, NULL, base);
+
+ if (state->sizeSpec == _PR_size_none) {
+ *va_arg(state->ap, PRUintn *) = lval;
+ } else if (state->sizeSpec == _PR_size_h) {
+ *va_arg(state->ap, PRUint16 *) = (PRUint16)lval;
+ } else if (state->sizeSpec == _PR_size_l) {
+ *va_arg(state->ap, PRUint32 *) = lval;
+ } else {
+ return PR_FAILURE;
+ }
+ }
+ }
+ state->converted = PR_TRUE;
+ }
+ return PR_SUCCESS;
+}
+
+static PRStatus
+GetFloat(ScanfState *state)
+{
+ char buf[FMAX + 1], *p;
+ int ch;
+ PRBool seenDigit = PR_FALSE;
+
+ if (state->width == 0 || state->width > FMAX) {
+ state->width = FMAX;
+ }
+ p = buf;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ }
+ while (WITHIN_WIDTH(state) && isdigit(ch)) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ seenDigit = PR_TRUE;
+ }
+ if (WITHIN_WIDTH(state) && ch == DECIMAL_POINT) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ while (WITHIN_WIDTH(state) && isdigit(ch)) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ seenDigit = PR_TRUE;
+ }
+ }
+
+ /*
+ * This is not robust. For example, "1.2e+" would confuse
+ * the code below to read 'e' and '+', only to realize that
+ * it should have stopped at "1.2". But we can't push back
+ * more than one character, so there is nothing I can do.
+ */
+
+ /* Parse exponent */
+ if (WITHIN_WIDTH(state) && (ch == 'e' || ch == 'E') && seenDigit) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ }
+ while (WITHIN_WIDTH(state) && isdigit(ch)) {
+ *p++ = ch;
+ GET_IF_WITHIN_WIDTH(state, ch);
+ }
+ }
+ if (WITHIN_WIDTH(state)) {
+ UNGET(state, ch);
+ }
+ if (!seenDigit) {
+ return PR_FAILURE;
+ }
+ *p = '\0';
+ if (state->assign) {
+ PRFloat64 dval = PR_strtod(buf, NULL);
+
+ state->converted = PR_TRUE;
+ if (state->sizeSpec == _PR_size_l) {
+ *va_arg(state->ap, PRFloat64 *) = dval;
+ } else if (state->sizeSpec == _PR_size_L) {
+#if defined(OSF1) || defined(IRIX)
+ *va_arg(state->ap, double *) = dval;
+#else
+ *va_arg(state->ap, long double *) = dval;
+#endif
+ } else {
+ *va_arg(state->ap, float *) = (float) dval;
+ }
+ }
+ return PR_SUCCESS;
+}
+
+/*
+ * Convert, and return the end of the conversion spec.
+ * Return NULL on error.
+ */
+
+static const char *
+Convert(ScanfState *state, const char *fmt)
+{
+ const char *cPtr;
+ int ch;
+ char *cArg = NULL;
+
+ state->converted = PR_FALSE;
+ cPtr = fmt;
+ if (*cPtr != 'c' && *cPtr != 'n' && *cPtr != '[') {
+ do {
+ ch = GET(state);
+ } while (isspace(ch));
+ UNGET(state, ch);
+ }
+ switch (*cPtr) {
+ case 'c':
+ if (state->assign) {
+ cArg = va_arg(state->ap, char *);
+ }
+ if (state->width == 0) {
+ state->width = 1;
+ }
+ for (; state->width > 0; state->width--) {
+ ch = GET(state);
+ if (ch == EOF) {
+ return NULL;
+ } else if (state->assign) {
+ *cArg++ = ch;
+ }
+ }
+ if (state->assign) {
+ state->converted = PR_TRUE;
+ }
+ break;
+ case 'p':
+ case 'd': case 'i': case 'o':
+ case 'u': case 'x': case 'X':
+ if (GetInt(state, *cPtr) == PR_FAILURE) {
+ return NULL;
+ }
+ break;
+ case 'e': case 'E': case 'f':
+ case 'g': case 'G':
+ if (GetFloat(state) == PR_FAILURE) {
+ return NULL;
+ }
+ break;
+ case 'n':
+ /* do not consume any input */
+ if (state->assign) {
+ switch (state->sizeSpec) {
+ case _PR_size_none:
+ *va_arg(state->ap, PRIntn *) = state->nChar;
+ break;
+ case _PR_size_h:
+ *va_arg(state->ap, PRInt16 *) = state->nChar;
+ break;
+ case _PR_size_l:
+ *va_arg(state->ap, PRInt32 *) = state->nChar;
+ break;
+ case _PR_size_ll:
+ LL_I2L(*va_arg(state->ap, PRInt64 *), state->nChar);
+ break;
+ default:
+ PR_ASSERT(0);
+ }
+ }
+ break;
+ case 's':
+ if (state->width == 0) {
+ state->width = INT_MAX;
+ }
+ if (state->assign) {
+ cArg = va_arg(state->ap, char *);
+ }
+ for (; state->width > 0; state->width--) {
+ ch = GET(state);
+ if ((ch == EOF) || isspace(ch)) {
+ UNGET(state, ch);
+ break;
+ }
+ if (state->assign) {
+ *cArg++ = ch;
+ }
+ }
+ if (state->assign) {
+ *cArg = '\0';
+ state->converted = PR_TRUE;
+ }
+ break;
+ case '%':
+ ch = GET(state);
+ if (ch != '%') {
+ UNGET(state, ch);
+ return NULL;
+ }
+ break;
+ case '[':
+ {
+ PRBool complement = PR_FALSE;
+ const char *closeBracket;
+ size_t n;
+
+ if (*++cPtr == '^') {
+ complement = PR_TRUE;
+ cPtr++;
+ }
+ closeBracket = strchr(*cPtr == ']' ? cPtr + 1 : cPtr, ']');
+ if (closeBracket == NULL) {
+ return NULL;
+ }
+ n = closeBracket - cPtr;
+ if (state->width == 0) {
+ state->width = INT_MAX;
+ }
+ if (state->assign) {
+ cArg = va_arg(state->ap, char *);
+ }
+ for (; state->width > 0; state->width--) {
+ ch = GET(state);
+ if ((ch == EOF)
+ || (!complement && !memchr(cPtr, ch, n))
+ || (complement && memchr(cPtr, ch, n))) {
+ UNGET(state, ch);
+ break;
+ }
+ if (state->assign) {
+ *cArg++ = ch;
+ }
+ }
+ if (state->assign) {
+ *cArg = '\0';
+ state->converted = PR_TRUE;
+ }
+ cPtr = closeBracket;
+ }
+ break;
+ default:
+ return NULL;
+ }
+ return cPtr;
+}
+
+static PRInt32
+DoScanf(ScanfState *state, const char *fmt)
+{
+ PRInt32 nConverted = 0;
+ const char *cPtr;
+ int ch;
+
+ state->nChar = 0;
+ cPtr = fmt;
+ while (1) {
+ if (isspace(*cPtr)) {
+ /* white space: skip */
+ do {
+ cPtr++;
+ } while (isspace(*cPtr));
+ do {
+ ch = GET(state);
+ } while (isspace(ch));
+ UNGET(state, ch);
+ } else if (*cPtr == '%') {
+ /* format spec: convert */
+ cPtr++;
+ state->assign = PR_TRUE;
+ if (*cPtr == '*') {
+ cPtr++;
+ state->assign = PR_FALSE;
+ }
+ for (state->width = 0; isdigit(*cPtr); cPtr++) {
+ state->width = state->width * 10 + *cPtr - '0';
+ }
+ state->sizeSpec = _PR_size_none;
+ if (*cPtr == 'h') {
+ cPtr++;
+ state->sizeSpec = _PR_size_h;
+ } else if (*cPtr == 'l') {
+ cPtr++;
+ if (*cPtr == 'l') {
+ cPtr++;
+ state->sizeSpec = _PR_size_ll;
+ } else {
+ state->sizeSpec = _PR_size_l;
+ }
+ } else if (*cPtr == 'L') {
+ cPtr++;
+ state->sizeSpec = _PR_size_L;
+ }
+ cPtr = Convert(state, cPtr);
+ if (cPtr == NULL) {
+ return (nConverted > 0 ? nConverted : EOF);
+ }
+ if (state->converted) {
+ nConverted++;
+ }
+ cPtr++;
+ } else {
+ /* others: must match */
+ if (*cPtr == '\0') {
+ return nConverted;
+ }
+ ch = GET(state);
+ if (ch != *cPtr) {
+ UNGET(state, ch);
+ return nConverted;
+ }
+ cPtr++;
+ }
+ }
+}
+
+static int
+StringGetChar(void *stream)
+{
+ char *cPtr = *((char **) stream);
+
+ if (*cPtr == '\0') {
+ return EOF;
+ } else {
+ *((char **) stream) = cPtr + 1;
+ return *cPtr;
+ }
+}
+
+static void
+StringUngetChar(void *stream, int ch)
+{
+ char *cPtr = *((char **) stream);
+
+ if (ch != EOF) {
+ *((char **) stream) = cPtr - 1;
+ }
+}
+
+PR_IMPLEMENT(PRInt32)
+PR_sscanf(const char *buf, const char *fmt, ...)
+{
+ PRInt32 rv;
+ ScanfState state;
+
+ state.get = &StringGetChar;
+ state.unget = &StringUngetChar;
+ state.stream = (void *) &buf;
+ va_start(state.ap, fmt);
+ rv = DoScanf(&state, fmt);
+ va_end(state.ap);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prsocket.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prsocket.c
new file mode 100644
index 00000000..8be198fa
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prsocket.c
@@ -0,0 +1,1842 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+
+/************************************************************************/
+
+/* These two functions are only used in assertions. */
+#if defined(DEBUG)
+
+PRBool IsValidNetAddr(const PRNetAddr *addr)
+{
+ if ((addr != NULL)
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ && (addr->raw.family != PR_AF_LOCAL)
+#endif
+ && (addr->raw.family != PR_AF_INET6)
+ && (addr->raw.family != PR_AF_INET)) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
+{
+ /*
+ * The definition of the length of a Unix domain socket address
+ * is not uniform, so we don't check it.
+ */
+ if ((addr != NULL)
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ && (addr->raw.family != AF_UNIX)
+#endif
+ && (PR_NETADDR_SIZE(addr) != addr_len)) {
+#if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
+ /*
+ * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2
+ * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
+ * field and is 28 bytes. It is possible for socket functions
+ * to return an addr_len greater than sizeof(struct sockaddr_in6).
+ * We need to allow that. (Bugzilla bug #77264)
+ */
+ if ((PR_AF_INET6 == addr->raw.family)
+ && (sizeof(addr->ipv6) == addr_len)) {
+ return PR_TRUE;
+ }
+#endif
+ /*
+ * The accept(), getsockname(), etc. calls on some platforms
+ * do not set the actual socket address length on return.
+ * In this case, we verifiy addr_len is still the value we
+ * passed in (i.e., sizeof(PRNetAddr)).
+ */
+#if defined(QNX)
+ if (sizeof(PRNetAddr) == addr_len) {
+ return PR_TRUE;
+ }
+#endif
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+#endif /* DEBUG */
+
+static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov,
+PRInt32 iov_size, PRIntervalTime timeout)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ int w = 0;
+ const PRIOVec *tmp_iov;
+#define LOCAL_MAXIOV 8
+ PRIOVec local_iov[LOCAL_MAXIOV];
+ PRIOVec *iov_copy = NULL;
+ int tmp_out;
+ int index, iov_cnt;
+ int count=0, sz = 0; /* 'count' is the return value. */
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ * Assume the first writev will succeed. Copy iov's only on
+ * failure.
+ */
+ tmp_iov = iov;
+ for (index = 0; index < iov_size; index++)
+ sz += iov[index].iov_len;
+
+ iov_cnt = iov_size;
+
+ while (sz > 0) {
+
+ w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout);
+ if (w < 0) {
+ count = -1;
+ break;
+ }
+ count += w;
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ sz -= w;
+
+ if (sz > 0) {
+ /* find the next unwritten vector */
+ for ( index = 0, tmp_out = count;
+ tmp_out >= iov[index].iov_len;
+ tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */
+
+ if (tmp_iov == iov) {
+ /*
+ * The first writev failed so we
+ * must copy iov's around.
+ * Avoid calloc/free if there
+ * are few enough iov's.
+ */
+ if (iov_size - index <= LOCAL_MAXIOV)
+ iov_copy = local_iov;
+ else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_size - index) *
+ sizeof *iov_copy)) == NULL) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ tmp_iov = iov_copy;
+ }
+
+ PR_ASSERT(tmp_iov == iov_copy);
+
+ /* fill in the first partial read */
+ iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]);
+ iov_copy[0].iov_len = iov[index].iov_len - tmp_out;
+ index++;
+
+ /* copy the remaining vectors */
+ for (iov_cnt=1; index<iov_size; iov_cnt++, index++) {
+ iov_copy[iov_cnt].iov_base = iov[index].iov_base;
+ iov_copy[iov_cnt].iov_len = iov[index].iov_len;
+ }
+ }
+ }
+
+ if (iov_copy != local_iov)
+ PR_DELETE(iov_copy);
+ return count;
+}
+
+/************************************************************************/
+
+PR_IMPLEMENT(PRFileDesc *) PR_ImportTCPSocket(PRInt32 osfd)
+{
+PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
+ if (fd != NULL) {
+ _PR_MD_MAKE_NONBLOCK(fd);
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
+ } else
+ _PR_MD_CLOSE_SOCKET(osfd);
+ return(fd);
+}
+
+PR_IMPLEMENT(PRFileDesc *) PR_ImportUDPSocket(PRInt32 osfd)
+{
+PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
+ if (fd != NULL) {
+ _PR_MD_MAKE_NONBLOCK(fd);
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE);
+ } else
+ _PR_MD_CLOSE_SOCKET(osfd);
+ return(fd);
+}
+
+
+static const PRIOMethods* PR_GetSocketPollFdMethods(void);
+
+PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PRInt32 osfd)
+{
+ PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ fd = _PR_Getfd();
+
+ if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ fd->secret->md.osfd = osfd;
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ fd->secret->state = _PR_FILEDESC_OPEN;
+ fd->methods = PR_GetSocketPollFdMethods();
+ }
+
+ return fd;
+} /* PR_CreateSocketPollFD */
+
+PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd)
+{
+ if (NULL == fd)
+ {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
+ _PR_Putfd(fd);
+ return PR_SUCCESS;
+} /* PR_DestroySocketPollFd */
+
+static PRStatus PR_CALLBACK SocketConnect(
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRInt32 rv; /* Return value of _PR_MD_CONNECT */
+ const PRNetAddr *addrp = addr;
+#if defined(_PR_INET6)
+ PRNetAddr addrCopy;
+#endif
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return PR_FAILURE;
+ }
+#if defined(_PR_INET6)
+ if (addr->raw.family == PR_AF_INET6) {
+ addrCopy = *addr;
+ addrCopy.raw.family = AF_INET6;
+ addrp = &addrCopy;
+ }
+#endif
+
+ rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout);
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv));
+ if (rv == 0)
+ return PR_SUCCESS;
+ else
+ return PR_FAILURE;
+}
+
+static PRStatus PR_CALLBACK SocketConnectContinue(
+ PRFileDesc *fd, PRInt16 out_flags)
+{
+ PRInt32 osfd;
+ int err;
+
+ if (out_flags & PR_POLL_NVAL) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) {
+ PR_ASSERT(out_flags == 0);
+ PR_SetError(PR_IN_PROGRESS_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ osfd = fd->secret->md.osfd;
+
+#if defined(XP_UNIX)
+
+ err = _MD_unix_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+
+#elif defined(WIN32) || defined(WIN16)
+
+#if defined(WIN32)
+ /*
+ * The sleep circumvents a bug in Win32 WinSock.
+ * See Microsoft Knowledge Base article ID: Q165989.
+ */
+ Sleep(0);
+#endif /* WIN32 */
+
+ if (out_flags & PR_POLL_EXCEPT) {
+ int len = sizeof(err);
+ if (getsockopt(osfd, (int)SOL_SOCKET, SO_ERROR, (char *) &err, &len)
+ == SOCKET_ERROR) {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ }
+ return PR_FAILURE;
+ }
+
+ PR_ASSERT(out_flags & PR_POLL_WRITE);
+ return PR_SUCCESS;
+
+#elif defined(XP_OS2)
+
+ err = _MD_os2_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+
+#elif defined(XP_MAC)
+
+ err = _MD_mac_get_nonblocking_connect_error(fd);
+ if (err == -1)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+
+#elif defined(XP_BEOS)
+
+#ifdef BONE_VERSION /* bug 122364 */
+ /* temporary workaround until getsockopt(SO_ERROR) works in BONE */
+ if (out_flags & PR_POLL_EXCEPT) {
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ PR_ASSERT(out_flags & PR_POLL_WRITE);
+ return PR_SUCCESS;
+#else
+ err = _MD_beos_get_nonblocking_connect_error(fd);
+ if( err != 0 ) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return PR_FAILURE;
+ }
+ else
+ return PR_SUCCESS;
+#endif /* BONE_VERSION */
+
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+#endif
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
+{
+ /* Find the NSPR layer and invoke its connectcontinue method */
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+
+ if (NULL == bottom) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return SocketConnectContinue(bottom, pd->out_flags);
+}
+
+static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr,
+PRIntervalTime timeout)
+{
+ PRInt32 osfd;
+ PRFileDesc *fd2;
+ PRUint32 al;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifdef WINNT
+ PRNetAddr addrCopy;
+#endif
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return 0;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return 0;
+ }
+
+#ifdef WINNT
+ if (addr == NULL) {
+ addr = &addrCopy;
+ }
+#endif
+ al = sizeof(PRNetAddr);
+ osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout);
+ if (osfd == -1)
+ return 0;
+
+ fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
+ if (!fd2) {
+ _PR_MD_CLOSE_SOCKET(osfd);
+ return NULL;
+ }
+
+ fd2->secret->nonblocking = fd->secret->nonblocking;
+ fd2->secret->inheritable = fd->secret->inheritable;
+#ifdef WINNT
+ if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRUE) {
+ /*
+ * The new socket has been associated with an I/O
+ * completion port. There is no going back.
+ */
+ fd2->secret->md.io_model_committed = PR_TRUE;
+ }
+ PR_ASSERT(al == PR_NETADDR_SIZE(addr));
+ fd2->secret->md.accepted_socket = PR_TRUE;
+ memcpy(&fd2->secret->md.peer_addr, addr, al);
+#endif
+
+ /*
+ * On some platforms, the new socket created by accept()
+ * inherits the nonblocking (or overlapped io) attribute
+ * of the listening socket. As an optimization, these
+ * platforms can skip the following _PR_MD_MAKE_NONBLOCK
+ * call.
+ *
+ * On Mac, we MUST make this call, because _PR_MD_MAKE_NONBLOCK
+ * (which maps to _MD_makenonblock, see macsockotpt.c)
+ * installs the async notifier routine needed to make blocking
+ * I/O work properly.
+ */
+#if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT)
+ _PR_MD_MAKE_NONBLOCK(fd2);
+#endif
+
+#ifdef _PR_INET6
+ if (addr && (AF_INET6 == addr->raw.family))
+ addr->raw.family = PR_AF_INET6;
+#endif
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE);
+
+ return fd2;
+}
+
+#ifdef WINNT
+PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr,
+PRIntervalTime timeout)
+{
+ PRInt32 osfd;
+ PRFileDesc *fd2;
+ PRIntn al;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRNetAddr addrCopy;
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return 0;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return 0;
+ }
+
+ if (addr == NULL) {
+ addr = &addrCopy;
+ }
+ al = PR_NETADDR_SIZE(addr);
+ osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL);
+ if (osfd == -1) {
+ return 0;
+ }
+
+ fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
+ if (!fd2) {
+ _PR_MD_CLOSE_SOCKET(osfd);
+ } else {
+ fd2->secret->nonblocking = fd->secret->nonblocking;
+ fd2->secret->md.io_model_committed = PR_TRUE;
+ PR_ASSERT(al == PR_NETADDR_SIZE(addr));
+ fd2->secret->md.accepted_socket = PR_TRUE;
+ memcpy(&fd2->secret->md.peer_addr, addr, al);
+#ifdef _PR_INET6
+ if (AF_INET6 == addr->raw.family)
+ addr->raw.family = PR_AF_INET6;
+#endif
+ }
+ return fd2;
+}
+#endif /* WINNT */
+
+
+static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr)
+{
+ PRInt32 result;
+ const PRNetAddr *addrp = addr;
+#if defined(_PR_INET6)
+ PRNetAddr addrCopy;
+#endif
+
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+
+#ifdef XP_UNIX
+ if (addr->raw.family == AF_UNIX) {
+ /* Disallow relative pathnames */
+ if (addr->local.path[0] != '/') {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ }
+#endif /* XP_UNIX */
+
+#if defined(_PR_INET6)
+ if (addr->raw.family == PR_AF_INET6) {
+ addrCopy = *addr;
+ addrCopy.raw.family = AF_INET6;
+ addrp = &addrCopy;
+ }
+#endif
+ result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr));
+ if (result < 0) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 result;
+
+ result = _PR_MD_LISTEN(fd, backlog);
+ if (result < 0) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK SocketShutdown(PRFileDesc *fd, PRIntn how)
+{
+ PRInt32 result;
+
+ result = _PR_MD_SHUTDOWN(fd, how);
+ if (result < 0) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+PRIntervalTime timeout)
+{
+ PRInt32 rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if ((flags != 0) && (flags != PR_MSG_PEEK)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv: fd=%p osfd=%d buf=%p amount=%d flags=%d",
+ fd, fd->secret->md.osfd, buf, amount, flags));
+
+#ifdef _PR_HAVE_PEEK_BUFFER
+ if (fd->secret->peekBytes != 0) {
+ rv = (amount < fd->secret->peekBytes) ?
+ amount : fd->secret->peekBytes;
+ memcpy(buf, fd->secret->peekBuffer, rv);
+ if (flags == 0) {
+ /* consume the bytes in the peek buffer */
+ fd->secret->peekBytes -= rv;
+ if (fd->secret->peekBytes != 0) {
+ memmove(fd->secret->peekBuffer,
+ fd->secret->peekBuffer + rv,
+ fd->secret->peekBytes);
+ }
+ }
+ return rv;
+ }
+
+ /* allocate peek buffer, if necessary */
+ if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) {
+ PR_ASSERT(0 == fd->secret->peekBytes);
+ /* impose a max size on the peek buffer */
+ if (amount > _PR_PEEK_BUFFER_MAX) {
+ amount = _PR_PEEK_BUFFER_MAX;
+ }
+ if (fd->secret->peekBufSize < amount) {
+ if (fd->secret->peekBuffer) {
+ PR_Free(fd->secret->peekBuffer);
+ }
+ fd->secret->peekBufSize = amount;
+ fd->secret->peekBuffer = PR_Malloc(amount);
+ if (NULL == fd->secret->peekBuffer) {
+ fd->secret->peekBufSize = 0;
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ }
+ }
+#endif
+
+ rv = _PR_MD_RECV(fd, buf, amount, flags, timeout);
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d",
+ rv, PR_GetError(), PR_GetOSError()));
+
+#ifdef _PR_HAVE_PEEK_BUFFER
+ if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) {
+ if (rv > 0) {
+ memcpy(fd->secret->peekBuffer, buf, rv);
+ fd->secret->peekBytes = rv;
+ }
+ }
+#endif
+
+ return rv;
+}
+
+static PRInt32 PR_CALLBACK SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ return SocketRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
+}
+
+static PRInt32 PR_CALLBACK SocketSend(PRFileDesc *fd, const void *buf, PRInt32 amount,
+PRIntn flags, PRIntervalTime timeout)
+{
+ PRInt32 temp, count;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+
+ count = 0;
+ while (amount > 0) {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX,
+ ("send: fd=%p osfd=%d buf=%p amount=%d",
+ fd, fd->secret->md.osfd, buf, amount));
+ temp = _PR_MD_SEND(fd, buf, amount, flags, timeout);
+ if (temp < 0) {
+ count = -1;
+ break;
+ }
+
+ count += temp;
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ buf = (const void*) ((const char*)buf + temp);
+
+ amount -= temp;
+ }
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send -> %d", count));
+ return count;
+}
+
+static PRInt32 PR_CALLBACK SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ return SocketSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
+}
+
+static PRStatus PR_CALLBACK SocketClose(PRFileDesc *fd)
+{
+ if (!fd || !fd->secret
+ || (fd->secret->state != _PR_FILEDESC_OPEN
+ && fd->secret->state != _PR_FILEDESC_CLOSED)) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (fd->secret->state == _PR_FILEDESC_OPEN) {
+ if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) {
+ return PR_FAILURE;
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
+ }
+
+#ifdef _PR_HAVE_PEEK_BUFFER
+ if (fd->secret->peekBuffer) {
+ PR_ASSERT(fd->secret->peekBufSize > 0);
+ PR_DELETE(fd->secret->peekBuffer);
+ fd->secret->peekBufSize = 0;
+ fd->secret->peekBytes = 0;
+ }
+#endif
+
+ PR_FreeFileDesc(fd);
+ return PR_SUCCESS;
+}
+
+static PRInt32 PR_CALLBACK SocketAvailable(PRFileDesc *fd)
+{
+ PRInt32 rv;
+#ifdef _PR_HAVE_PEEK_BUFFER
+ if (fd->secret->peekBytes != 0) {
+ return fd->secret->peekBytes;
+ }
+#endif
+ rv = _PR_MD_SOCKETAVAILABLE(fd);
+ return rv;
+}
+
+static PRInt64 PR_CALLBACK SocketAvailable64(PRFileDesc *fd)
+{
+ PRInt64 rv;
+#ifdef _PR_HAVE_PEEK_BUFFER
+ if (fd->secret->peekBytes != 0) {
+ LL_I2L(rv, fd->secret->peekBytes);
+ return rv;
+ }
+#endif
+ LL_I2L(rv, _PR_MD_SOCKETAVAILABLE(fd));
+ return rv;
+}
+
+static PRStatus PR_CALLBACK SocketSync(PRFileDesc *fd)
+{
+#if defined(XP_MAC)
+#pragma unused (fd)
+#endif
+
+ return PR_SUCCESS;
+}
+
+static PRInt32 PR_CALLBACK SocketSendTo(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRInt32 temp, count;
+ const PRNetAddr *addrp = addr;
+#if defined(_PR_INET6)
+ PRNetAddr addrCopy;
+#endif
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+#if defined(_PR_INET6)
+ if (addr->raw.family == PR_AF_INET6) {
+ addrCopy = *addr;
+ addrCopy.raw.family = AF_INET6;
+ addrp = &addrCopy;
+ }
+#endif
+
+ count = 0;
+ while (amount > 0) {
+ temp = _PR_MD_SENDTO(fd, buf, amount, flags,
+ addrp, PR_NETADDR_SIZE(addr), timeout);
+ if (temp < 0) {
+ count = -1;
+ break;
+ }
+ count += temp;
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ buf = (const void*) ((const char*)buf + temp);
+ amount -= temp;
+ }
+ return count;
+}
+
+static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRInt32 rv;
+ PRUint32 al;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+
+ al = sizeof(PRNetAddr);
+ rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout);
+#ifdef _PR_INET6
+ if (addr && (AF_INET6 == addr->raw.family))
+ addr->raw.family = PR_AF_INET6;
+#endif
+ return rv;
+}
+
+static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
+PRNetAddr **raddr, void *buf, PRInt32 amount,
+PRIntervalTime timeout)
+{
+ PRInt32 rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ *nd = NULL;
+
+#if defined(WINNT)
+ {
+ PRInt32 newSock;
+ PRNetAddr *raddrCopy;
+
+ if (raddr == NULL) {
+ raddr = &raddrCopy;
+ }
+ rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout);
+ if (rv < 0) {
+ rv = -1;
+ } else {
+ /* Successfully accepted and read; create the new PRFileDesc */
+ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
+ if (*nd == 0) {
+ _PR_MD_CLOSE_SOCKET(newSock);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ rv = -1;
+ } else {
+ (*nd)->secret->md.io_model_committed = PR_TRUE;
+ (*nd)->secret->md.accepted_socket = PR_TRUE;
+ memcpy(&(*nd)->secret->md.peer_addr, *raddr,
+ PR_NETADDR_SIZE(*raddr));
+#ifdef _PR_INET6
+ if (AF_INET6 == *raddr->raw.family)
+ *raddr->raw.family = PR_AF_INET6;
+#endif
+ }
+ }
+ }
+#else
+ rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
+#endif
+ return rv;
+}
+
+#ifdef WINNT
+PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
+PRNetAddr **raddr, void *buf, PRInt32 amount,
+PRIntervalTime timeout)
+{
+ PRInt32 rv;
+ PRInt32 newSock;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRNetAddr *raddrCopy;
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+ *nd = NULL;
+
+ if (raddr == NULL) {
+ raddr = &raddrCopy;
+ }
+ rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount,
+ timeout, PR_TRUE, NULL, NULL);
+ if (rv < 0) {
+ rv = -1;
+ } else {
+ /* Successfully accepted and read; create the new PRFileDesc */
+ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
+ if (*nd == 0) {
+ _PR_MD_CLOSE_SOCKET(newSock);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ rv = -1;
+ } else {
+ (*nd)->secret->md.io_model_committed = PR_TRUE;
+ (*nd)->secret->md.accepted_socket = PR_TRUE;
+ memcpy(&(*nd)->secret->md.peer_addr, *raddr,
+ PR_NETADDR_SIZE(*raddr));
+#ifdef _PR_INET6
+ if (AF_INET6 == *raddr->raw.family)
+ *raddr->raw.family = PR_AF_INET6;
+#endif
+ }
+ }
+ return rv;
+}
+
+PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback(
+PRFileDesc *sd, PRFileDesc **nd,
+PRNetAddr **raddr, void *buf, PRInt32 amount,
+PRIntervalTime timeout,
+_PR_AcceptTimeoutCallback callback,
+void *callbackArg)
+{
+ PRInt32 rv;
+ PRInt32 newSock;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRNetAddr *raddrCopy;
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+ *nd = NULL;
+
+ if (raddr == NULL) {
+ raddr = &raddrCopy;
+ }
+ rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount,
+ timeout, PR_TRUE, callback, callbackArg);
+ if (rv < 0) {
+ rv = -1;
+ } else {
+ /* Successfully accepted and read; create the new PRFileDesc */
+ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods());
+ if (*nd == 0) {
+ _PR_MD_CLOSE_SOCKET(newSock);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ rv = -1;
+ } else {
+ (*nd)->secret->md.io_model_committed = PR_TRUE;
+ (*nd)->secret->md.accepted_socket = PR_TRUE;
+ memcpy(&(*nd)->secret->md.peer_addr, *raddr,
+ PR_NETADDR_SIZE(*raddr));
+#ifdef _PR_INET6
+ if (AF_INET6 == *raddr->raw.family)
+ *raddr->raw.family = PR_AF_INET6;
+#endif
+ }
+ }
+ return rv;
+}
+#endif /* WINNT */
+
+#ifdef WINNT
+PR_IMPLEMENT(void)
+PR_NTFast_UpdateAcceptContext(PRFileDesc *socket, PRFileDesc *acceptSocket)
+{
+ _PR_MD_UPDATE_ACCEPT_CONTEXT(
+ socket->secret->md.osfd, acceptSocket->secret->md.osfd);
+}
+#endif /* WINNT */
+
+static PRInt32 PR_CALLBACK SocketSendFile(
+ PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ PRInt32 rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (_PR_IO_PENDING(me)) {
+ PR_SetError(PR_IO_PENDING_ERROR, 0);
+ return -1;
+ }
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+#if defined(WINNT)
+ rv = _PR_MD_SENDFILE(sd, sfd, flags, timeout);
+ if ((rv >= 0) && (flags == PR_TRANSMITFILE_CLOSE_SOCKET)) {
+ /*
+ * This should be kept the same as SocketClose, except
+ * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should
+ * not be called because the socket will be recycled.
+ */
+ PR_FreeFileDesc(sd);
+ }
+#else
+ rv = PR_EmulateSendFile(sd, sfd, flags, timeout);
+#endif /* WINNT */
+
+ return rv;
+}
+
+static PRInt32 PR_CALLBACK SocketTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
+const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
+PRIntervalTime timeout)
+{
+ PRSendFileData sfd;
+
+ sfd.fd = fd;
+ sfd.file_offset = 0;
+ sfd.file_nbytes = 0;
+ sfd.header = headers;
+ sfd.hlen = hlen;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+
+ return(SocketSendFile(sd, &sfd, flags, timeout));
+}
+
+static PRStatus PR_CALLBACK SocketGetName(PRFileDesc *fd, PRNetAddr *addr)
+{
+ PRInt32 result;
+ PRUint32 addrlen;
+
+ addrlen = sizeof(PRNetAddr);
+ result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen);
+ if (result < 0) {
+ return PR_FAILURE;
+ }
+#ifdef _PR_INET6
+ if (AF_INET6 == addr->raw.family)
+ addr->raw.family = PR_AF_INET6;
+#endif
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
+ return PR_SUCCESS;
+}
+
+static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr)
+{
+ PRInt32 result;
+ PRUint32 addrlen;
+
+ addrlen = sizeof(PRNetAddr);
+ result = _PR_MD_GETPEERNAME(fd, addr, &addrlen);
+ if (result < 0) {
+ return PR_FAILURE;
+ }
+#ifdef _PR_INET6
+ if (AF_INET6 == addr->raw.family)
+ addr->raw.family = PR_AF_INET6;
+#endif
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
+ return PR_SUCCESS;
+}
+
+static PRInt16 PR_CALLBACK SocketPoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+#ifdef XP_MAC
+#pragma unused( fd, in_flags )
+#endif
+ *out_flags = 0;
+ return in_flags;
+} /* SocketPoll */
+
+static PRIOMethods tcpMethods = {
+ PR_DESC_SOCKET_TCP,
+ SocketClose,
+ SocketRead,
+ SocketWrite,
+ SocketAvailable,
+ SocketAvailable64,
+ SocketSync,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ SocketWritev,
+ SocketConnect,
+ SocketAccept,
+ SocketBind,
+ SocketListen,
+ SocketShutdown,
+ SocketRecv,
+ SocketSend,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ SocketPoll,
+ SocketAcceptRead,
+ SocketTransmitFile,
+ SocketGetName,
+ SocketGetPeerName,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ _PR_SocketGetSocketOption,
+ _PR_SocketSetSocketOption,
+ SocketSendFile,
+ SocketConnectContinue,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRIOMethods udpMethods = {
+ PR_DESC_SOCKET_UDP,
+ SocketClose,
+ SocketRead,
+ SocketWrite,
+ SocketAvailable,
+ SocketAvailable64,
+ SocketSync,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ SocketWritev,
+ SocketConnect,
+ (PRAcceptFN)_PR_InvalidDesc,
+ SocketBind,
+ SocketListen,
+ SocketShutdown,
+ SocketRecv,
+ SocketSend,
+ SocketRecvFrom,
+ SocketSendTo,
+ SocketPoll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ SocketGetName,
+ SocketGetPeerName,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ _PR_SocketGetSocketOption,
+ _PR_SocketSetSocketOption,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+
+static PRIOMethods socketpollfdMethods = {
+ (PRDescType) 0,
+ (PRCloseFN)_PR_InvalidStatus,
+ (PRReadFN)_PR_InvalidInt,
+ (PRWriteFN)_PR_InvalidInt,
+ (PRAvailableFN)_PR_InvalidInt,
+ (PRAvailable64FN)_PR_InvalidInt64,
+ (PRFsyncFN)_PR_InvalidStatus,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ SocketPoll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods()
+{
+ return &tcpMethods;
+}
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods()
+{
+ return &udpMethods;
+}
+
+static const PRIOMethods* PR_GetSocketPollFdMethods()
+{
+ return &socketpollfdMethods;
+} /* PR_GetSocketPollFdMethods */
+
+#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
+
+#if defined(_PR_INET6_PROBE)
+
+PR_EXTERN(PRBool) _pr_ipv6_is_present;
+
+PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket()
+{
+PRInt32 osfd;
+
+ osfd = _PR_MD_SOCKET(AF_INET6, SOCK_STREAM, 0);
+ if (osfd != -1) {
+ _PR_MD_CLOSE_SOCKET(osfd);
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+#endif /* _PR_INET6_PROBE */
+
+#endif
+
+PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
+{
+ PRInt32 osfd;
+ PRFileDesc *fd;
+ PRInt32 tmp_domain = domain;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ if (PR_AF_INET != domain
+ && PR_AF_INET6 != domain
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ && PR_AF_LOCAL != domain
+#endif
+ ) {
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+ return NULL;
+ }
+
+#if defined(_PR_INET6_PROBE)
+ if (PR_AF_INET6 == domain) {
+ if (_pr_ipv6_is_present == PR_FALSE)
+ domain = AF_INET;
+ else
+ domain = AF_INET6;
+ }
+#elif defined(_PR_INET6)
+ if (PR_AF_INET6 == domain)
+ domain = AF_INET6;
+#else
+ if (PR_AF_INET6 == domain)
+ domain = AF_INET;
+#endif /* _PR_INET6 */
+ osfd = _PR_MD_SOCKET(domain, type, proto);
+ if (osfd == -1) {
+ return 0;
+ }
+ if (type == SOCK_STREAM)
+ fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
+ else
+ fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
+ /*
+ * Make the sockets non-blocking
+ */
+ if (fd != NULL) {
+ _PR_MD_MAKE_NONBLOCK(fd);
+ _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE);
+#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
+ /*
+ * For platforms with no support for IPv6
+ * create layered socket for IPv4-mapped IPv6 addresses
+ */
+ if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) {
+ if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
+ PR_Close(fd);
+ fd = NULL;
+ }
+ }
+#endif
+ } else
+ _PR_MD_CLOSE_SOCKET(osfd);
+
+ return fd;
+}
+
+PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void)
+{
+ PRInt32 domain = AF_INET;
+
+ return PR_Socket(domain, SOCK_STREAM, 0);
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void)
+{
+ PRInt32 domain = AF_INET;
+
+ return PR_Socket(domain, SOCK_DGRAM, 0);
+}
+
+PR_IMPLEMENT(PRFileDesc *) PR_OpenTCPSocket(PRIntn af)
+{
+ return PR_Socket(af, SOCK_STREAM, 0);
+}
+
+PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af)
+{
+ return PR_Socket(af, SOCK_DGRAM, 0);
+}
+
+PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[])
+{
+#ifdef XP_UNIX
+ PRInt32 rv, osfd[2];
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd);
+ if (rv == -1) {
+ return PR_FAILURE;
+ }
+
+ f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
+ if (!f[0]) {
+ _PR_MD_CLOSE_SOCKET(osfd[0]);
+ _PR_MD_CLOSE_SOCKET(osfd[1]);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ return PR_FAILURE;
+ }
+ f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods());
+ if (!f[1]) {
+ PR_Close(f[0]);
+ _PR_MD_CLOSE_SOCKET(osfd[1]);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ return PR_FAILURE;
+ }
+ _PR_MD_MAKE_NONBLOCK(f[0]);
+ _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE);
+ _PR_MD_MAKE_NONBLOCK(f[1]);
+ _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE);
+ return PR_SUCCESS;
+#elif defined(WINNT)
+ /*
+ * A socket pair is often used for interprocess communication,
+ * so we need to make sure neither socket is associated with
+ * the I/O completion port; otherwise it can't be used by a
+ * child process.
+ *
+ * The default implementation below cannot be used for NT
+ * because PR_Accept would have associated the I/O completion
+ * port with the listening and accepted sockets.
+ */
+ SOCKET listenSock;
+ SOCKET osfd[2];
+ struct sockaddr_in selfAddr, peerAddr;
+ int addrLen;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ osfd[0] = osfd[1] = INVALID_SOCKET;
+ listenSock = socket(AF_INET, SOCK_STREAM, 0);
+ if (listenSock == INVALID_SOCKET) {
+ goto failed;
+ }
+ selfAddr.sin_family = AF_INET;
+ selfAddr.sin_port = 0;
+ selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */
+ addrLen = sizeof(selfAddr);
+ if (bind(listenSock, (struct sockaddr *) &selfAddr,
+ addrLen) == SOCKET_ERROR) {
+ goto failed;
+ }
+ if (getsockname(listenSock, (struct sockaddr *) &selfAddr,
+ &addrLen) == SOCKET_ERROR) {
+ goto failed;
+ }
+ if (listen(listenSock, 5) == SOCKET_ERROR) {
+ goto failed;
+ }
+ osfd[0] = socket(AF_INET, SOCK_STREAM, 0);
+ if (osfd[0] == INVALID_SOCKET) {
+ goto failed;
+ }
+ selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ /*
+ * Only a thread is used to do the connect and accept.
+ * I am relying on the fact that connect returns
+ * successfully as soon as the connect request is put
+ * into the listen queue (but before accept is called).
+ * This is the behavior of the BSD socket code. If
+ * connect does not return until accept is called, we
+ * will need to create another thread to call connect.
+ */
+ if (connect(osfd[0], (struct sockaddr *) &selfAddr,
+ addrLen) == SOCKET_ERROR) {
+ goto failed;
+ }
+ /*
+ * A malicious local process may connect to the listening
+ * socket, so we need to verify that the accepted connection
+ * is made from our own socket osfd[0].
+ */
+ if (getsockname(osfd[0], (struct sockaddr *) &selfAddr,
+ &addrLen) == SOCKET_ERROR) {
+ goto failed;
+ }
+ osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen);
+ if (osfd[1] == INVALID_SOCKET) {
+ goto failed;
+ }
+ if (peerAddr.sin_port != selfAddr.sin_port) {
+ /* the connection we accepted is not from osfd[0] */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ goto failed;
+ }
+ closesocket(listenSock);
+
+ f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
+ if (!f[0]) {
+ closesocket(osfd[0]);
+ closesocket(osfd[1]);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ return PR_FAILURE;
+ }
+ f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods());
+ if (!f[1]) {
+ PR_Close(f[0]);
+ closesocket(osfd[1]);
+ /* PR_AllocFileDesc() has invoked PR_SetError(). */
+ return PR_FAILURE;
+ }
+ _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE);
+ _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE);
+ return PR_SUCCESS;
+
+failed:
+ if (listenSock != INVALID_SOCKET) {
+ closesocket(listenSock);
+ }
+ if (osfd[0] != INVALID_SOCKET) {
+ closesocket(osfd[0]);
+ }
+ if (osfd[1] != INVALID_SOCKET) {
+ closesocket(osfd[1]);
+ }
+ return PR_FAILURE;
+#else /* not Unix or NT */
+ /*
+ * default implementation
+ */
+ PRFileDesc *listenSock;
+ PRNetAddr selfAddr, peerAddr;
+ PRUint16 port;
+
+ f[0] = f[1] = NULL;
+ listenSock = PR_NewTCPSocket();
+ if (listenSock == NULL) {
+ goto failed;
+ }
+ PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */
+ if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+ if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+ port = ntohs(selfAddr.inet.port);
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ goto failed;
+ }
+ f[0] = PR_NewTCPSocket();
+ if (f[0] == NULL) {
+ goto failed;
+ }
+#ifdef _PR_CONNECT_DOES_NOT_BIND
+ /*
+ * If connect does not implicitly bind the socket (e.g., on
+ * BeOS), we have to bind the socket so that we can get its
+ * port with getsockname later.
+ */
+ PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr);
+ if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+#endif
+ PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr);
+
+ /*
+ * Only a thread is used to do the connect and accept.
+ * I am relying on the fact that PR_Connect returns
+ * successfully as soon as the connect request is put
+ * into the listen queue (but before PR_Accept is called).
+ * This is the behavior of the BSD socket code. If
+ * connect does not return until accept is called, we
+ * will need to create another thread to call connect.
+ */
+ if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT)
+ == PR_FAILURE) {
+ goto failed;
+ }
+ /*
+ * A malicious local process may connect to the listening
+ * socket, so we need to verify that the accepted connection
+ * is made from our own socket f[0].
+ */
+ if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) {
+ goto failed;
+ }
+ f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT);
+ if (f[1] == NULL) {
+ goto failed;
+ }
+ if (peerAddr.inet.port != selfAddr.inet.port) {
+ /* the connection we accepted is not from f[0] */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ goto failed;
+ }
+ PR_Close(listenSock);
+ return PR_SUCCESS;
+
+failed:
+ if (listenSock) {
+ PR_Close(listenSock);
+ }
+ if (f[0]) {
+ PR_Close(f[0]);
+ }
+ if (f[1]) {
+ PR_Close(f[1]);
+ }
+ return PR_FAILURE;
+#endif
+}
+
+PR_IMPLEMENT(PRInt32)
+PR_FileDesc2NativeHandle(PRFileDesc *fd)
+{
+ if (fd) {
+ fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
+ }
+ if (!fd) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ return fd->secret->md.osfd;
+}
+
+PR_IMPLEMENT(void)
+PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PRInt32 handle)
+{
+ if (fd)
+ fd->secret->md.osfd = handle;
+}
+
+/*
+** Select compatibility
+**
+*/
+
+PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)
+{
+ memset(set, 0, sizeof(PR_fd_set));
+}
+
+PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set)
+{
+ PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC );
+
+ set->harray[set->hsize++] = fh;
+}
+
+PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set)
+{
+ PRUint32 index, index2;
+
+ for (index = 0; index<set->hsize; index++)
+ if (set->harray[index] == fh) {
+ for (index2=index; index2 < (set->hsize-1); index2++) {
+ set->harray[index2] = set->harray[index2+1];
+ }
+ set->hsize--;
+ break;
+ }
+}
+
+PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set)
+{
+ PRUint32 index;
+ for (index = 0; index<set->hsize; index++)
+ if (set->harray[index] == fh) {
+ return 1;
+ }
+ return 0;
+}
+
+PR_IMPLEMENT(void) PR_FD_NSET(PRInt32 fd, PR_fd_set *set)
+{
+ PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC );
+
+ set->narray[set->nsize++] = fd;
+}
+
+PR_IMPLEMENT(void) PR_FD_NCLR(PRInt32 fd, PR_fd_set *set)
+{
+ PRUint32 index, index2;
+
+ for (index = 0; index<set->nsize; index++)
+ if (set->narray[index] == fd) {
+ for (index2=index; index2 < (set->nsize-1); index2++) {
+ set->narray[index2] = set->narray[index2+1];
+ }
+ set->nsize--;
+ break;
+ }
+}
+
+PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PRInt32 fd, PR_fd_set *set)
+{
+ PRUint32 index;
+ for (index = 0; index<set->nsize; index++)
+ if (set->narray[index] == fd) {
+ return 1;
+ }
+ return 0;
+}
+
+
+#if !defined(NEED_SELECT)
+#if !defined(XP_MAC)
+#include "obsolete/probslet.h"
+#else
+#include "probslet.h"
+#endif
+
+#define PD_INCR 20
+
+static PRPollDesc *_pr_setfd(
+ PR_fd_set *set, PRInt16 flags, PRPollDesc *polldesc)
+{
+ PRUintn fsidx, pdidx;
+ PRPollDesc *poll = polldesc;
+
+ if (NULL == set) return poll;
+
+ /* First set the pr file handle osfds */
+ for (fsidx = 0; fsidx < set->hsize; fsidx++)
+ {
+ for (pdidx = 0; 1; pdidx++)
+ {
+ if ((PRFileDesc*)-1 == poll[pdidx].fd)
+ {
+ /* our vector is full - extend and condition it */
+ poll = (PRPollDesc*)PR_Realloc(
+ poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc));
+ if (NULL == poll) goto out_of_memory;
+ memset(
+ poll + pdidx * sizeof(PRPollDesc),
+ 0, PD_INCR * sizeof(PRPollDesc));
+ poll[pdidx + PD_INCR].fd = (PRFileDesc*)-1;
+ }
+ if ((NULL == poll[pdidx].fd)
+ || (poll[pdidx].fd == set->harray[fsidx]))
+ {
+ /* PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); */
+ /* either empty or prevously defined */
+ poll[pdidx].fd = set->harray[fsidx]; /* possibly redundant */
+ poll[pdidx].in_flags |= flags; /* possibly redundant */
+ break;
+ }
+ }
+ }
+
+#if 0
+ /* Second set the native osfds */
+ for (fsidx = 0; fsidx < set->nsize; fsidx++)
+ {
+ for (pdidx = 0; ((PRFileDesc*)-1 != poll[pdidx].fd); pdidx++)
+ {
+ if ((PRFileDesc*)-1 == poll[pdidx].fd)
+ {
+ /* our vector is full - extend and condition it */
+ poll = PR_Realloc(
+ poll, (pdidx + PD_INCR) * sizeof(PRPollDesc));
+ if (NULL == poll) goto out_of_memory;
+ memset(
+ poll + pdidx * sizeof(PRPollDesc),
+ 0, PD_INCR * sizeof(PRPollDesc));
+ poll[(pdidx + PD_INCR)].fd = (PRFileDesc*)-1;
+ }
+ if ((NULL == poll[pdidx].fd)
+ || (poll[pdidx].fd == set->narray[fsidx]))
+ {
+ /* either empty or prevously defined */
+ poll[pdidx].fd = set->narray[fsidx];
+ PR_ASSERT(0 == (poll[pdidx].in_flags & flags));
+ poll[pdidx].in_flags |= flags;
+ break;
+ }
+ }
+ }
+#endif /* 0 */
+
+ return poll;
+
+out_of_memory:
+ if (NULL != polldesc) PR_DELETE(polldesc);
+ return NULL;
+} /* _pr_setfd */
+
+#endif /* !defined(NEED_SELECT) */
+
+PR_IMPLEMENT(PRInt32) PR_Select(
+ PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr,
+ PR_fd_set *pr_ex, PRIntervalTime timeout)
+{
+
+#if !defined(NEED_SELECT)
+ PRInt32 npds = 0;
+ /*
+ ** Find out how many fds are represented in the three lists.
+ ** Then allocate a polling descriptor for the logical union
+ ** (there can't be any overlapping) and call PR_Poll().
+ */
+
+ PRPollDesc *copy, *poll;
+
+ static PRBool warning = PR_TRUE;
+ if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()");
+
+ /* try to get an initial guesss at how much space we need */
+ npds = 0;
+ if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0))
+ npds = pr_rd->hsize + pr_rd->nsize;
+ if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0))
+ npds = pr_wr->hsize + pr_wr->nsize;
+ if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0))
+ npds = pr_ex->hsize + pr_ex->nsize;
+
+ if (0 == npds)
+ {
+ PR_Sleep(timeout);
+ return 0;
+ }
+
+ copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc));
+ if (NULL == poll) goto out_of_memory;
+ poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1;
+
+ poll = _pr_setfd(pr_rd, PR_POLL_READ, poll);
+ if (NULL == poll) goto out_of_memory;
+ poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll);
+ if (NULL == poll) goto out_of_memory;
+ poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll);
+ if (NULL == poll) goto out_of_memory;
+ unused = 0;
+ while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd)
+ {
+ ++unused;
+ }
+
+ PR_ASSERT(unused > 0);
+ npds = PR_Poll(poll, unused, timeout);
+
+ if (npds > 0)
+ {
+ /* Copy the results back into the fd sets */
+ if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0;
+ if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0;
+ if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0;
+ for (copy = &poll[unused - 1]; copy >= poll; --copy)
+ {
+ if (copy->out_flags & PR_POLL_NVAL)
+ {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ npds = -1;
+ break;
+ }
+ if (copy->out_flags & PR_POLL_READ)
+ if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd;
+ if (copy->out_flags & PR_POLL_WRITE)
+ if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd;
+ if (copy->out_flags & PR_POLL_EXCEPT)
+ if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd;
+ }
+ }
+ PR_DELETE(poll);
+
+ return npds;
+out_of_memory:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+
+#endif /* !defined(NEED_SELECT) */
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/io/prstdio.c b/src/libs/xpcom18a4/nsprpub/pr/src/io/prstdio.c
new file mode 100644
index 00000000..0b7ecd89
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/io/prstdio.c
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+
+/*
+** fprintf to a PRFileDesc
+*/
+PR_IMPLEMENT(PRUint32) PR_fprintf(PRFileDesc* fd, const char *fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ va_start(ap, fmt);
+ rv = PR_vfprintf(fd, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PR_IMPLEMENT(PRUint32) PR_vfprintf(PRFileDesc* fd, const char *fmt, va_list ap)
+{
+ /* XXX this could be better */
+ PRUint32 rv, len;
+ char* msg = PR_vsmprintf(fmt, ap);
+ len = strlen(msg);
+#ifdef XP_OS2
+ /*
+ * OS/2 really needs a \r for every \n.
+ * In the future we should try to use scatter-gather instead of a
+ * succession of PR_Write.
+ */
+ if (isatty(PR_FileDesc2NativeHandle(fd))) {
+ PRUint32 last = 0, idx;
+ PRInt32 tmp;
+ rv = 0;
+ for (idx = 0; idx < len+1; idx++) {
+ if ((idx - last > 0) && (('\n' == msg[idx]) || (idx == len))) {
+ tmp = PR_Write(fd, msg + last, idx - last);
+ if (tmp >= 0) {
+ rv += tmp;
+ }
+ last = idx;
+ }
+ /*
+ * if current character is \n, and
+ * previous character isn't \r, and
+ * next character isn't \r
+ */
+ if (('\n' == msg[idx]) &&
+ ((0 == idx) || ('\r' != msg[idx-1])) &&
+ ('\r' != msg[idx+1])) {
+ /* add extra \r */
+ tmp = PR_Write(fd, "\r", 1);
+ if (tmp >= 0) {
+ rv += tmp;
+ }
+ }
+ }
+ } else {
+ rv = PR_Write(fd, msg, len);
+ }
+#else
+ rv = PR_Write(fd, msg, len);
+#endif
+ PR_DELETE(msg);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/linking/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/linking/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/linking/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/linking/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/linking/Makefile.in
new file mode 100644
index 00000000..71fbf571
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/linking/Makefile.in
@@ -0,0 +1,80 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OPTIMIZER =
+endif
+endif
+
+CSRCS = \
+ prlink.c \
+ $(NULL)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+# For Dl_info and dladdr.
+ifeq ($(OS_TARGET),Linux)
+DEFINES += -D_GNU_SOURCE
+endif
+
+# On Mac OS X use flat #includes.
+ifeq ($(OS_TARGET),MacOSX)
+INCLUDES += -I$(NEXT_ROOT)/Developer/Headers/FlatCarbon
+endif
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/linking/prlink.c b/src/libs/xpcom18a4/nsprpub/pr/src/linking/prlink.c
new file mode 100644
index 00000000..faad8af2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/linking/prlink.c
@@ -0,0 +1,2147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s): Steve Streeter (Hewlett-Packard Company)
+ *
+ * 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.
+ */
+
+#include "primpl.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_FindLibrary VBoxNsprPR_FindLibrary
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+#include <string.h>
+
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+# include <iprt/ldr.h>
+# include <iprt/path.h>
+# include <iprt/err.h>
+
+# if defined(XP_MACOSX) /** @todo Add some equivalent to PR_GetLibraryFilePathname. */
+# include <mach-o/dyld.h>
+# endif
+
+# ifdef XP_MAC
+# error "Misconfiguration: XP_MAC && VBOX_USE_MORE_IPRT_IN_NSPR are not intended to work together"
+# endif
+
+#else /* ! VBOX_USE_MORE_IPRT_IN_NSPR */
+
+#ifdef XP_BEOS
+#include <image.h>
+#endif
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#include <CodeFragments.h>
+#include <TextUtils.h>
+#include <Types.h>
+#include <Aliases.h>
+
+#if TARGET_CARBON
+#include <CFURL.h>
+#include <CFBundle.h>
+#include <CFString.h>
+#include <CFDictionary.h>
+#include <CFData.h>
+#endif
+
+#if defined(XP_MACOSX)
+#define PStrFromCStr(src, dst) c2pstrcpy(dst, src)
+#else
+#include "macdll.h"
+#include "mdmac.h"
+#endif /* XP_MACOSX */
+#endif
+
+#ifdef XP_UNIX
+#ifdef USE_DLFCN
+#include <dlfcn.h>
+/* Define these on systems that don't have them. */
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#ifndef RTLD_LAZY
+#define RTLD_LAZY RTLD_NOW
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
+#ifdef AIX
+#include <sys/ldr.h>
+#endif
+#ifdef OSF1
+#include <loader.h>
+#include <rld_interface.h>
+#endif
+#elif defined(USE_HPSHL)
+#include <dl.h>
+#elif defined(USE_MACH_DYLD)
+#include <mach-o/dyld.h>
+#endif
+#endif /* XP_UNIX */
+
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+#ifdef VBOX_USE_IPRT_IN_NSPR
+# include <iprt/mem.h>
+# include <iprt/string.h>
+# undef strdup
+# define strdup(str) RTStrDup(str)
+#endif
+
+#define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY
+
+#ifdef VMS
+/* These are all require for the PR_GetLibraryFilePathname implementation */
+#include <descrip.h>
+#include <dvidef.h>
+#include <fibdef.h>
+#include <iodef.h>
+#include <lib$routines.h>
+#include <ssdef.h>
+#include <starlet.h>
+#include <stsdef.h>
+#include <unixlib.h>
+
+#pragma __nostandard
+#pragma __member_alignment __save
+#pragma __nomember_alignment
+#ifdef __INITIAL_POINTER_SIZE
+#pragma __required_pointer_size __save
+#pragma __required_pointer_size __short
+#endif
+
+typedef struct _imcb {
+ struct _imcb *imcb$l_flink;
+ struct _imcb *imcb$l_blink;
+ unsigned short int imcb$w_size;
+ unsigned char imcb$b_type;
+ char imcb$b_resv_1;
+ unsigned char imcb$b_access_mode;
+ unsigned char imcb$b_act_code;
+ unsigned short int imcb$w_chan;
+ unsigned int imcb$l_flags;
+ char imcb$t_image_name [40];
+ unsigned int imcb$l_symvec_size;
+ unsigned __int64 imcb$q_ident;
+ void *imcb$l_starting_address;
+ void *imcb$l_end_address;
+} IMCB;
+
+#pragma __member_alignment __restore
+#ifdef __INITIAL_POINTER_SIZE
+#pragma __required_pointer_size __restore
+#endif
+#pragma __standard
+
+typedef struct {
+ short buflen;
+ short itmcode;
+ void *buffer;
+ void *retlen;
+} ITMLST;
+
+typedef struct {
+ short cond;
+ short count;
+ int rest;
+} IOSB;
+
+typedef unsigned long int ulong_t;
+
+struct _imcb *IAC$GL_IMAGE_LIST = NULL;
+
+#define MAX_DEVNAM 64
+#define MAX_FILNAM 255
+#endif /* VMS */
+
+/*
+ * On these platforms, symbols have a leading '_'.
+ */
+#ifndef VBOX_USE_MORE_IPRT_IN_NSPR /* RTLdr hides this. */
+#if defined(SUNOS4) || defined(DARWIN) || defined(NEXTSTEP) \
+ || defined(WIN16) || defined(XP_OS2) \
+ || ((defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__))
+#define NEED_LEADING_UNDERSCORE
+#endif
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+#ifdef XP_PC
+typedef PRStaticLinkTable *NODL_PROC(void);
+#endif
+
+/************************************************************************/
+
+struct PRLibrary {
+ char* name; /* Our own copy of the name string */
+ PRLibrary* next;
+ int refCount;
+ const PRStaticLinkTable* staticTable;
+
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+ RTLDRMOD dlh;
+#else /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+#ifdef XP_PC
+#ifdef XP_OS2
+ HMODULE dlh;
+#else
+ HINSTANCE dlh;
+#endif
+#endif
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+ CFragConnectionID connection;
+
+#if TARGET_CARBON
+ CFBundleRef bundle;
+#endif
+
+ Ptr main;
+
+#if defined(XP_MACOSX)
+ CFMutableDictionaryRef wrappers;
+ const struct mach_header* image;
+#endif /* XP_MACOSX */
+#endif
+
+#ifdef XP_UNIX
+#if defined(USE_HPSHL)
+ shl_t dlh;
+#elif defined(USE_MACH_DYLD)
+ NSModule dlh;
+#else
+ void* dlh;
+#endif
+#endif
+
+#ifdef XP_BEOS
+ void* dlh;
+ void* stub_dlh;
+#endif
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+};
+
+static PRLibrary *pr_loadmap;
+static PRLibrary *pr_exe_loadmap;
+static PRMonitor *pr_linker_lock;
+static char* _pr_currentLibPath = NULL;
+
+static PRLibrary *pr_LoadLibraryByPathname(const char *name, PRIntn flags);
+#ifdef XP_MAC
+static PRLibrary *pr_Mac_LoadNamedFragment(const FSSpec *fileSpec,
+ const char* fragmentName);
+static PRLibrary *pr_Mac_LoadIndexedFragment(const FSSpec *fileSpec,
+ PRUint32 fragIndex);
+#endif /* XP_MAC */
+
+/************************************************************************/
+
+#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) && !defined(VBOX_USE_MORE_IPRT_IN_NSPR)
+static char* errStrBuf = NULL;
+#define ERR_STR_BUF_LENGTH 20
+static char* errno_string(PRIntn oserr)
+{
+ if (errStrBuf == NULL)
+ errStrBuf = PR_MALLOC(ERR_STR_BUF_LENGTH);
+ PR_snprintf(errStrBuf, ERR_STR_BUF_LENGTH, "error %d", oserr);
+ return errStrBuf;
+}
+#endif
+
+static void DLLErrorInternal(PRIntn oserr)
+/*
+** This whole function, and most of the code in this file, are run
+** with a big hairy lock wrapped around it. Not the best of situations,
+** but will eventually come up with the right answer.
+*/
+{
+ const char *error = NULL;
+#ifdef USE_DLFCN
+ error = dlerror(); /* $$$ That'll be wrong some of the time - AOF */
+#elif defined(HAVE_STRERROR)
+ error = strerror(oserr); /* this should be okay */
+#else
+ error = errno_string(oserr);
+#endif
+ if (NULL != error)
+ PR_SetErrorText(strlen(error), error);
+} /* DLLErrorInternal */
+
+void _PR_InitLinker(void)
+{
+#if (!defined(XP_MAC) && !defined(XP_BEOS)) || defined(VBOX_USE_MORE_IPRT_IN_NSPR)
+ PRLibrary *lm;
+#endif
+#ifdef XP_UNIX
+ void *h;
+#endif
+
+ if (!pr_linker_lock) {
+ pr_linker_lock = PR_NewNamedMonitor("linker-lock");
+ }
+ PR_EnterMonitor(pr_linker_lock);
+
+#if defined(XP_PC) || defined(VBOX_USE_MORE_IPRT_IN_NSPR)
+ lm = PR_NEWZAP(PRLibrary);
+ lm->name = strdup("Executable");
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+ lm->dlh = NIL_RTLDRMOD;
+#else /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+ /*
+ ** In WIN32, GetProcAddress(...) expects a module handle in order to
+ ** get exported symbols from the executable...
+ **
+ ** However, in WIN16 this is accomplished by passing NULL to
+ ** GetProcAddress(...)
+ */
+#if defined(_WIN32)
+ lm->dlh = GetModuleHandle(NULL);
+#else
+ lm->dlh = (HINSTANCE)NULL;
+#endif /* ! _WIN32 */
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+ lm->refCount = 1;
+ lm->staticTable = NULL;
+ pr_exe_loadmap = lm;
+ pr_loadmap = lm;
+
+#elif defined(XP_UNIX)
+#ifdef HAVE_DLL
+#ifdef USE_DLFCN
+ h = dlopen(0, RTLD_LAZY);
+ if (!h) {
+ char *error;
+
+ DLLErrorInternal(_MD_ERRNO());
+ error = (char*)PR_MALLOC(PR_GetErrorTextLength());
+ (void) PR_GetErrorText(error);
+ fprintf(stderr, "failed to initialize shared libraries [%s]\n",
+ error);
+ PR_DELETE(error);
+ abort();/* XXX */
+ }
+#elif defined(USE_HPSHL)
+ h = NULL;
+ /* don't abort with this NULL */
+#elif defined(USE_MACH_DYLD)
+ h = NULL; /* XXXX toshok */
+#else
+#error no dll strategy
+#endif /* USE_DLFCN */
+
+ lm = PR_NEWZAP(PRLibrary);
+ if (lm) {
+ lm->name = strdup("a.out");
+ lm->refCount = 1;
+ lm->dlh = h;
+ lm->staticTable = NULL;
+ }
+ pr_exe_loadmap = lm;
+ pr_loadmap = lm;
+#endif /* HAVE_DLL */
+#endif /* XP_UNIX */
+
+#if !defined(XP_MAC) && !defined(XP_BEOS) || defined(VBOX_USE_MORE_IPRT_IN_NSPR)
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (init)", lm?lm->name:"NULL"));
+#endif
+
+ PR_ExitMonitor(pr_linker_lock);
+}
+
+#if defined(WIN16)
+/*
+ * _PR_ShutdownLinker unloads all dlls loaded by the application via
+ * calls to PR_LoadLibrary
+ */
+void _PR_ShutdownLinker(void)
+{
+ PR_EnterMonitor(pr_linker_lock);
+
+ while (pr_loadmap) {
+ if (pr_loadmap->refCount > 1) {
+#ifdef DEBUG
+ fprintf(stderr, "# Forcing library to unload: %s (%d outstanding references)\n",
+ pr_loadmap->name, pr_loadmap->refCount);
+#endif
+ pr_loadmap->refCount = 1;
+ }
+ PR_UnloadLibrary(pr_loadmap);
+ }
+
+ PR_ExitMonitor(pr_linker_lock);
+
+ PR_DestroyMonitor(pr_linker_lock);
+ pr_linker_lock = NULL;
+}
+#else
+/*
+ * _PR_ShutdownLinker was originally only used on WIN16 (see above),
+ * but I think it should also be used on other platforms. However,
+ * I disagree with the original implementation's unloading the dlls
+ * for the application. Any dlls that still remain on the pr_loadmap
+ * list when NSPR shuts down are application programming errors. The
+ * only exception is pr_exe_loadmap, which was added to the list by
+ * NSPR and hence should be cleaned up by NSPR.
+ */
+void _PR_ShutdownLinker(void)
+{
+ /* FIXME: pr_exe_loadmap should be destroyed. */
+
+ PR_DestroyMonitor(pr_linker_lock);
+ pr_linker_lock = NULL;
+
+ if (_pr_currentLibPath) {
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTStrFree(_pr_currentLibPath);
+#else
+ free(_pr_currentLibPath);
+#endif
+ _pr_currentLibPath = NULL;
+ }
+
+#if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) && !defined(VBOX_USE_MORE_IPRT_IN_NSPR)
+ PR_DELETE(errStrBuf);
+#endif
+}
+#endif
+
+/******************************************************************************/
+
+PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path)
+{
+ PRStatus rv = PR_SUCCESS;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ PR_EnterMonitor(pr_linker_lock);
+ if (_pr_currentLibPath) {
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTStrFree(_pr_currentLibPath);
+#else
+ free(_pr_currentLibPath);
+#endif
+ }
+ if (path) {
+ _pr_currentLibPath = strdup(path);
+ if (!_pr_currentLibPath) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ } else {
+ _pr_currentLibPath = 0;
+ }
+ PR_ExitMonitor(pr_linker_lock);
+ return rv;
+}
+
+/*
+** Return the library path for finding shared libraries.
+*/
+PR_IMPLEMENT(char *)
+PR_GetLibraryPath(void)
+{
+ char *ev;
+ char *copy = NULL; /* a copy of _pr_currentLibPath */
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ PR_EnterMonitor(pr_linker_lock);
+ if (_pr_currentLibPath != NULL) {
+ goto exit;
+ }
+
+ /* initialize pr_currentLibPath */
+
+#ifdef XP_PC
+ ev = getenv("LD_LIBRARY_PATH");
+ if (!ev) {
+ ev = ".;\\lib";
+ }
+ ev = strdup(ev);
+#endif
+
+#ifdef XP_MAC
+ {
+ char *p;
+ int len;
+
+ ev = getenv("LD_LIBRARY_PATH");
+
+ if (!ev)
+ ev = "";
+
+ len = strlen(ev) + 1; /* +1 for the null */
+# ifdef VBOX_USE_IPRT_IN_NSPR
+ p = (char*) RTStrAlloc(len);
+# else
+ p = (char*) malloc(len);
+# endif
+ if (p) {
+ strcpy(p, ev);
+ }
+ ev = p;
+ }
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#if defined(USE_DLFCN) || defined(USE_MACH_DYLD) || defined(XP_BEOS)
+ {
+ char *p=NULL;
+ int len;
+
+#ifdef XP_BEOS
+ ev = getenv("LIBRARY_PATH");
+ if (!ev) {
+ ev = "%A/lib:/boot/home/config/lib:/boot/beos/system/lib";
+ }
+#else
+# if defined(VBOX) && defined(XP_MACOSX)
+ ev = getenv("DYLD_LIBRARY_PATH");
+# else
+ ev = getenv("LD_LIBRARY_PATH");
+# endif
+ if (!ev) {
+ ev = "/usr/lib:/lib";
+ }
+#endif
+ len = strlen(ev) + 1; /* +1 for the null */
+
+# ifdef VBOX_USE_IPRT_IN_NSPR
+ p = (char*) RTStrAlloc(len);
+# else
+ p = (char*) malloc(len);
+# endif
+ if (p) {
+ strcpy(p, ev);
+ } /* if (p) */
+ ev = p;
+ PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev));
+
+ }
+#else
+ /* AFAIK there isn't a library path with the HP SHL interface --Rob */
+ ev = strdup("");
+# endif
+#endif
+
+ /*
+ * If ev is NULL, we have run out of memory
+ */
+ _pr_currentLibPath = ev;
+
+ exit:
+ if (_pr_currentLibPath) {
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ copy = RTMemDup(_pr_currentLibPath, strlen(_pr_currentLibPath) + 1);
+#else
+ copy = strdup(_pr_currentLibPath);
+#endif
+ }
+ PR_ExitMonitor(pr_linker_lock);
+ if (!copy) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+ return copy;
+}
+
+/*
+** Build library name from path, lib and extensions
+*/
+PR_IMPLEMENT(char*)
+PR_GetLibraryName(const char *path, const char *lib)
+{
+ char *fullname;
+
+#ifdef XP_PC
+ if (strstr(lib, PR_DLL_SUFFIX) == NULL)
+ {
+ if (path) {
+ fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX);
+ } else {
+ fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX);
+ }
+ } else {
+ if (path) {
+ fullname = PR_smprintf("%s\\%s", path, lib);
+ } else {
+ fullname = PR_smprintf("%s", lib);
+ }
+ }
+#endif /* XP_PC */
+#ifdef XP_MAC
+ if (path) {
+ fullname = PR_smprintf("%s%s", path, lib);
+ } else {
+ fullname = PR_smprintf("%s", lib);
+ }
+#endif
+#if defined(XP_UNIX) || defined(XP_BEOS)
+ if (strstr(lib, PR_DLL_SUFFIX) == NULL)
+ {
+ if (path) {
+ fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX);
+ } else {
+ fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX);
+ }
+ } else {
+ if (path) {
+ fullname = PR_smprintf("%s/%s", path, lib);
+ } else {
+ fullname = PR_smprintf("%s", lib);
+ }
+ }
+#endif /* XP_UNIX || XP_BEOS */
+ return fullname;
+}
+
+/*
+** Free the memory allocated, for the caller, by PR_GetLibraryName
+*/
+PR_IMPLEMENT(void)
+PR_FreeLibraryName(char *mem)
+{
+ PR_smprintf_free(mem);
+}
+
+static PRLibrary*
+pr_UnlockedFindLibrary(const char *name)
+{
+ PRLibrary* lm = pr_loadmap;
+ const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR);
+ np = np ? np + 1 : name;
+ while (lm) {
+ const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR);
+ cp = cp ? cp + 1 : lm->name;
+#ifdef WIN32
+ /* Windows DLL names are case insensitive... */
+ if (strcmpi(np, cp) == 0)
+#elif defined(XP_OS2)
+ if (stricmp(np, cp) == 0)
+#else
+ if (strcmp(np, cp) == 0)
+#endif
+ {
+ /* found */
+ lm->refCount++;
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN,
+ ("%s incr => %d (find lib)",
+ lm->name, lm->refCount));
+ return lm;
+ }
+ lm = lm->next;
+ }
+ return NULL;
+}
+
+PR_IMPLEMENT(PRLibrary*)
+PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags)
+{
+ if (flags == 0) {
+ flags = _PR_DEFAULT_LD_FLAGS;
+ }
+ switch (libSpec.type) {
+ case PR_LibSpec_Pathname:
+ return pr_LoadLibraryByPathname(libSpec.value.pathname, flags);
+#ifdef XP_MAC
+ case PR_LibSpec_MacNamedFragment:
+ return pr_Mac_LoadNamedFragment(
+ libSpec.value.mac_named_fragment.fsspec,
+ libSpec.value.mac_named_fragment.name);
+ case PR_LibSpec_MacIndexedFragment:
+ return pr_Mac_LoadIndexedFragment(
+ libSpec.value.mac_indexed_fragment.fsspec,
+ libSpec.value.mac_indexed_fragment.index);
+#endif /* XP_MAC */
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+}
+
+PR_IMPLEMENT(PRLibrary*)
+PR_LoadLibrary(const char *name)
+{
+ PRLibSpec libSpec;
+
+ libSpec.type = PR_LibSpec_Pathname;
+ libSpec.value.pathname = name;
+ return PR_LoadLibraryWithFlags(libSpec, 0);
+}
+
+#ifndef VBOX_USE_MORE_IPRT_IN_NSPR /* exclude big chunk */
+#if defined(USE_MACH_DYLD)
+static NSModule
+pr_LoadMachDyldModule(const char *name)
+{
+ NSObjectFileImage ofi;
+ NSModule h = NULL;
+ if (NSCreateObjectFileImageFromFile(name, &ofi)
+ == NSObjectFileImageSuccess) {
+ h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE
+ | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ /*
+ * TODO: If NSLinkModule fails, use NSLinkEditError to retrieve
+ * error information.
+ */
+ if (NSDestroyObjectFileImage(ofi) == FALSE) {
+ if (h) {
+ (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE);
+ h = NULL;
+ }
+ }
+ }
+ return h;
+}
+#endif
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+
+#ifdef XP_MACOSX
+static void* TV2FP(CFMutableDictionaryRef dict, const char* name, void *tvp)
+{
+ static uint32 glue[6] = { 0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420 };
+ uint32* newGlue = NULL;
+
+ if (tvp != NULL) {
+ CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII);
+ if (nameRef) {
+ CFMutableDataRef glueData = (CFMutableDataRef) CFDictionaryGetValue(dict, nameRef);
+ if (glueData == NULL) {
+ glueData = CFDataCreateMutable(NULL, sizeof(glue));
+ if (glueData != NULL) {
+ newGlue = (uint32*) CFDataGetMutableBytePtr(glueData);
+ memcpy(newGlue, glue, sizeof(glue));
+ newGlue[0] |= ((UInt32)tvp >> 16);
+ newGlue[1] |= ((UInt32)tvp & 0xFFFF);
+ MakeDataExecutable(newGlue, sizeof(glue));
+ CFDictionaryAddValue(dict, nameRef, glueData);
+ CFRelease(glueData);
+
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: created wrapper for CFM function %s().", name));
+ }
+ } else {
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: found wrapper for CFM function %s().", name));
+
+ newGlue = (uint32*) CFDataGetMutableBytePtr(glueData);
+ }
+ CFRelease(nameRef);
+ }
+ }
+
+ return newGlue;
+}
+#endif
+
+/*
+** macLibraryLoadProc is a function definition for a Mac shared library
+** loading method. The "name" param is the same full or partial pathname
+** that was passed to pr_LoadLibraryByPathName. The function must fill
+** in the fields of "lm" which apply to its library type. Returns
+** PR_SUCCESS if successful.
+*/
+
+typedef PRStatus (*macLibraryLoadProc)(const char *name, PRLibrary *lm);
+
+static PRStatus
+pr_LoadViaCFM(const char *name, PRLibrary *lm)
+{
+ OSErr err;
+ char cName[64];
+ Str255 errName;
+
+#if !defined(XP_MACOSX)
+ Str255 pName;
+ /*
+ * Algorithm: The "name" passed in could be either a shared
+ * library name that we should look for in the normal library
+ * search paths, or a full path name to a specific library on
+ * disk. Since the full path will always contain a ":"
+ * (shortest possible path is "Volume:File"), and since a
+ * library name can not contain a ":", we can test for the
+ * presence of a ":" to see which type of library we should load.
+ * or its a full UNIX path which we for now assume is Java
+ * enumerating all the paths (see below)
+ */
+ if (strchr(name, PR_PATH_SEPARATOR) == NULL) {
+ if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) {
+ /*
+ * The name did not contain a ":", so it must be a
+ * library name. Convert the name to a Pascal string
+ * and try to find the library.
+ */
+ } else {
+ /*
+ * name contained a "/" which means we need to suck off
+ * the last part of the path and pass that on the
+ * NSGetSharedLibrary. this may not be what we really
+ * want to do .. because Java could be iterating through
+ * the whole LD path, and we'll find it if it's anywhere
+ * on that path -- it appears that's what UNIX and the
+ * PC do too...so we'll emulate but it could be wrong.
+ */
+ name = strrchr(name, PR_DIRECTORY_SEPARATOR) + 1;
+ }
+
+ PStrFromCStr(name, pName);
+
+ /*
+ * beard: NSGetSharedLibrary was so broken that I just decided to
+ * use GetSharedLibrary for now. This will need to change for
+ * plugins, but those should go in the Extensions folder anyhow.
+ */
+ err = GetSharedLibrary(pName, kCompiledCFragArch, kReferenceCFrag,
+ &lm->connection, &lm->main, errName);
+ if (err != noErr)
+ return PR_FAILURE;
+ }
+ else
+#endif
+ {
+ /*
+ * The name did contain a ":", so it must be a full path name.
+ * Now we have to do a lot of work to convert the path name to
+ * an FSSpec (silly, since we were probably just called from the
+ * MacFE plug-in code that already knew the FSSpec and converted
+ * it to a full path just to pass to us). Make an FSSpec from
+ * the full path and call GetDiskFragment.
+ */
+ FSSpec fileSpec;
+ Boolean tempUnusedBool;
+
+#if defined(XP_MACOSX)
+ {
+ /* Use direct conversion of POSIX path to FSRef to FSSpec. */
+ FSRef ref;
+ err = FSPathMakeRef((const UInt8*)name, &ref, NULL);
+ if (err == noErr)
+ err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL,
+ &fileSpec, NULL);
+ }
+#else
+ PStrFromCStr(name, pName);
+ err = FSMakeFSSpec(0, 0, pName, &fileSpec);
+#endif
+ if (err != noErr)
+ return PR_FAILURE;
+
+ /* Resolve an alias if this was one */
+ err = ResolveAliasFile(&fileSpec, true, &tempUnusedBool,
+ &tempUnusedBool);
+ if (err != noErr)
+ return PR_FAILURE;
+
+ /* Finally, try to load the library */
+ err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name,
+ kLoadCFrag, &lm->connection, &lm->main, errName);
+
+#if TARGET_CARBON
+ p2cstrcpy(cName, fileSpec.name);
+#else
+ memcpy(cName, fileSpec.name + 1, fileSpec.name[0]);
+ cName[fileSpec.name[0]] = '\0';
+#endif
+
+#ifdef XP_MACOSX
+ if (err == noErr && lm->connection) {
+ /*
+ * if we're a mach-o binary, need to wrap all CFM function
+ * pointers. need a hash-table of already seen function
+ * pointers, etc.
+ */
+ lm->wrappers = CFDictionaryCreateMutable(NULL, 16,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (lm->wrappers) {
+ lm->main = TV2FP(lm->wrappers, "main", lm->main);
+ } else
+ err = memFullErr;
+ }
+#endif
+ }
+ return (err == noErr) ? PR_SUCCESS : PR_FAILURE;
+}
+
+/*
+** Creates a CFBundleRef if the pathname refers to a Mac OS X bundle
+** directory. The caller is responsible for calling CFRelease() to
+** deallocate.
+*/
+
+#if TARGET_CARBON
+static PRStatus
+pr_LoadCFBundle(const char *name, PRLibrary *lm)
+{
+ CFURLRef bundleURL;
+ CFBundleRef bundle = NULL;
+
+#ifdef XP_MACOSX
+ char pathBuf[PATH_MAX];
+ const char *resolvedPath;
+ CFStringRef pathRef;
+
+ /* Takes care of relative paths and symlinks */
+ resolvedPath = realpath(name, pathBuf);
+ if (!resolvedPath)
+ return PR_FAILURE;
+
+ pathRef = CFStringCreateWithCString(NULL, pathBuf, kCFStringEncodingUTF8);
+ if (pathRef) {
+ bundleURL = CFURLCreateWithFileSystemPath(NULL, pathRef,
+ kCFURLPOSIXPathStyle, true);
+ if (bundleURL) {
+ bundle = CFBundleCreate(NULL, bundleURL);
+ CFRelease(bundleURL);
+ }
+ CFRelease(pathRef);
+ }
+#else
+ OSErr err;
+ Str255 pName;
+ FSSpec fsSpec;
+ FSRef fsRef;
+
+ if ((UInt32)(CFURLCreateFromFSRef) == kUnresolvedCFragSymbolAddress)
+ return PR_FAILURE;
+ PStrFromCStr(name, pName);
+ err = FSMakeFSSpec(0, 0, pName, &fsSpec);
+ if (err != noErr)
+ return PR_FAILURE;
+ err = FSpMakeFSRef(&fsSpec, &fsRef);
+ if (err != noErr)
+ return PR_FAILURE;
+ bundleURL = CFURLCreateFromFSRef(NULL, &fsRef);
+ if (bundleURL) {
+ bundle = CFBundleCreate(NULL, bundleURL);
+ CFRelease(bundleURL);
+ }
+#endif
+
+ lm->bundle = bundle;
+ return (bundle != NULL) ? PR_SUCCESS : PR_FAILURE;
+}
+#endif
+
+#ifdef XP_MACOSX
+static PRStatus
+pr_LoadViaDyld(const char *name, PRLibrary *lm)
+{
+ lm->dlh = pr_LoadMachDyldModule(name);
+ if (lm->dlh == NULL) {
+ lm->image = NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR
+ | NSADDIMAGE_OPTION_WITH_SEARCHING);
+ /*
+ * TODO: If NSAddImage fails, use NSLinkEditError to retrieve
+ * error information.
+ */
+ }
+ return (lm->dlh != NULL || lm->image != NULL) ? PR_SUCCESS : PR_FAILURE;
+}
+#endif
+
+#endif /* defined(XP_MAC) || defined(XP_MACOSX) */
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+/*
+** Dynamically load a library. Only load libraries once, so scan the load
+** map first.
+*/
+static PRLibrary*
+pr_LoadLibraryByPathname(const char *name, PRIntn flags)
+{
+ PRLibrary *lm;
+ PRLibrary* result;
+ PRInt32 oserr;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* See if library is already loaded */
+ PR_EnterMonitor(pr_linker_lock);
+
+ result = pr_UnlockedFindLibrary(name);
+ if (result != NULL) goto unlock;
+
+ lm = PR_NEWZAP(PRLibrary);
+ if (lm == NULL) {
+ oserr = _MD_ERRNO();
+ goto unlock;
+ }
+ lm->staticTable = NULL;
+
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+ oserr = RTLdrLoad(name, &lm->dlh);
+ if (RT_FAILURE(oserr))
+ goto unlock;
+ lm->name = strdup(name);
+ lm->refCount = 1;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+
+#else /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+#ifdef XP_OS2 /* Why isn't all this stuff in MD code?! */
+ {
+ HMODULE h;
+ UCHAR pszError[_MAX_PATH];
+ ULONG ulRc = NO_ERROR;
+
+ ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h);
+ if (ulRc != NO_ERROR) {
+ oserr = ulRc;
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = h;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+ }
+#endif /* XP_OS2 */
+
+#if defined(WIN32) || defined(WIN16)
+ {
+ HINSTANCE h;
+ NODL_PROC *pfn;
+
+ h = LoadLibrary(name);
+ if (h < (HINSTANCE)HINSTANCE_ERROR) {
+ oserr = _MD_ERRNO();
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = h;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+
+ /*
+ ** Try to load a table of "static functions" provided by the DLL
+ */
+
+ pfn = (NODL_PROC *)GetProcAddress(h, "NODL_TABLE");
+ if (pfn != NULL) {
+ lm->staticTable = (*pfn)();
+ }
+ }
+#endif /* WIN32 || WIN16 */
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+ {
+ int i;
+ PRStatus status;
+
+ static const macLibraryLoadProc loadProcs[] = {
+#if defined(XP_MACOSX)
+ pr_LoadViaDyld, pr_LoadCFBundle, pr_LoadViaCFM
+#elif TARGET_CARBON
+ pr_LoadViaCFM, pr_LoadCFBundle
+#else
+ pr_LoadViaCFM
+#endif
+ };
+
+ for (i = 0; i < sizeof(loadProcs) / sizeof(loadProcs[0]); i++) {
+ if ((status = loadProcs[i](name, lm)) == PR_SUCCESS)
+ break;
+ }
+ if (status != PR_SUCCESS) {
+ oserr = cfragNoLibraryErr;
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+ }
+#endif
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+#ifdef HAVE_DLL
+ {
+#if defined(USE_DLFCN)
+#ifdef NTO
+ /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */
+ int dl_flags = RTLD_GROUP;
+#elif defined(AIX)
+ /* AIX needs RTLD_MEMBER to load an archive member. (bug 228899) */
+ int dl_flags = RTLD_MEMBER;
+#else
+ int dl_flags = 0;
+#endif
+ void *h;
+
+ if (flags & PR_LD_LAZY) {
+ dl_flags |= RTLD_LAZY;
+ }
+ if (flags & PR_LD_NOW) {
+ dl_flags |= RTLD_NOW;
+ }
+ if (flags & PR_LD_GLOBAL) {
+ dl_flags |= RTLD_GLOBAL;
+ }
+ if (flags & PR_LD_LOCAL) {
+ dl_flags |= RTLD_LOCAL;
+ }
+ h = dlopen(name, dl_flags);
+#elif defined(USE_HPSHL)
+ int shl_flags = 0;
+ shl_t h;
+
+ /*
+ * Use the DYNAMIC_PATH flag only if 'name' is a plain file
+ * name (containing no directory) to match the behavior of
+ * dlopen().
+ */
+ if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) {
+ shl_flags |= DYNAMIC_PATH;
+ }
+ if (flags & PR_LD_LAZY) {
+ shl_flags |= BIND_DEFERRED;
+ }
+ if (flags & PR_LD_NOW) {
+ shl_flags |= BIND_IMMEDIATE;
+ }
+ /* No equivalent of PR_LD_GLOBAL and PR_LD_LOCAL. */
+ h = shl_load(name, shl_flags, 0L);
+#elif defined(USE_MACH_DYLD)
+ NSModule h = pr_LoadMachDyldModule(name);
+#else
+#error Configuration error
+#endif
+ if (!h) {
+ oserr = _MD_ERRNO();
+#ifdef DEBUG
+ fprintf(stderr, "pr_LoadLibraryByPathname(): Failed to load '%s'\n", name);
+#endif
+ PR_DELETE(lm);
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = h;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+ }
+#endif /* HAVE_DLL */
+#endif /* XP_UNIX */
+
+ lm->refCount = 1;
+
+#ifdef XP_BEOS
+ {
+ image_info info;
+ int32 cookie = 0;
+ image_id imageid = B_ERROR;
+ image_id stubid = B_ERROR;
+ PRLibrary *p;
+
+ for (p = pr_loadmap; p != NULL; p = p->next) {
+ /* hopefully, our caller will always use the same string
+ to refer to the same library */
+ if (strcmp(name, p->name) == 0) {
+ /* we've already loaded this library */
+ imageid = info.id;
+ lm->refCount++;
+ break;
+ }
+ }
+
+ if(imageid == B_ERROR) {
+ /* it appears the library isn't yet loaded - load it now */
+ char stubName [B_PATH_NAME_LENGTH + 1];
+
+ /* the following is a work-around to a "bug" in the beos -
+ the beos system loader allows only 32M (system-wide)
+ to be used by code loaded as "add-ons" (code loaded
+ through the 'load_add_on()' system call, which includes
+ mozilla components), but allows 256M to be used by
+ shared libraries.
+
+ unfortunately, mozilla is too large to fit into the
+ "add-on" space, so we must trick the loader into
+ loading some of the components as shared libraries. this
+ is accomplished by creating a "stub" add-on (an empty
+ shared object), and linking it with the component
+ (the actual .so file generated by the build process,
+ without any modifications). when this stub is loaded
+ by load_add_on(), the loader will automatically load the
+ component into the shared library space.
+ */
+
+ strcpy(stubName, name);
+ strcat(stubName, ".stub");
+
+ /* first, attempt to load the stub (thereby loading the
+ component as a shared library */
+ if ((stubid = load_add_on(stubName)) > B_ERROR) {
+ /* the stub was loaded successfully. */
+ imageid = B_FILE_NOT_FOUND;
+
+ cookie = 0;
+ while (get_next_image_info(0, &cookie, &info) == B_OK) {
+ const char *endOfSystemName = strrchr(info.name, '/');
+ const char *endOfPassedName = strrchr(name, '/');
+ if( 0 == endOfSystemName )
+ endOfSystemName = info.name;
+ else
+ endOfSystemName++;
+ if( 0 == endOfPassedName )
+ endOfPassedName = name;
+ else
+ endOfPassedName++;
+ if (strcmp(endOfSystemName, endOfPassedName) == 0) {
+ /* this is the actual component - remember it */
+ imageid = info.id;
+ break;
+ }
+ }
+
+ } else {
+ /* we failed to load the "stub" - try to load the
+ component directly as an add-on */
+ stubid = B_ERROR;
+ imageid = load_add_on(name);
+ }
+ }
+
+ if (imageid <= B_ERROR) {
+ oserr = imageid;
+ PR_DELETE( lm );
+ goto unlock;
+ }
+ lm->name = strdup(name);
+ lm->dlh = (void*)imageid;
+ lm->stub_dlh = (void*)stubid;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+ }
+#endif
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+ result = lm; /* success */
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name));
+
+ unlock:
+ if (result == NULL) {
+ PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr);
+ DLLErrorInternal(oserr); /* sets error text */
+ }
+ PR_ExitMonitor(pr_linker_lock);
+ return result;
+}
+
+PR_IMPLEMENT(PRLibrary*)
+PR_FindLibrary(const char *name)
+{
+ PRLibrary* result;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ PR_EnterMonitor(pr_linker_lock);
+ result = pr_UnlockedFindLibrary(name);
+ PR_ExitMonitor(pr_linker_lock);
+ return result;
+}
+
+
+#ifdef XP_MAC
+
+static PRLibrary*
+pr_Mac_LoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName)
+{
+ PRLibrary* newLib = NULL;
+ PRLibrary* result;
+ FSSpec resolvedSpec = *fileSpec;
+ CFragConnectionID connectionID = 0;
+ Boolean isFolder, wasAlias;
+ OSErr err = noErr;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* See if library is already loaded */
+ PR_EnterMonitor(pr_linker_lock);
+
+ result = pr_UnlockedFindLibrary(fragmentName);
+ if (result != NULL) goto unlock;
+
+ newLib = PR_NEWZAP(PRLibrary);
+ if (newLib == NULL) goto unlock;
+ newLib->staticTable = NULL;
+
+
+ /* Resolve an alias if this was one */
+ err = ResolveAliasFile(&resolvedSpec, true, &isFolder, &wasAlias);
+ if (err != noErr)
+ goto unlock;
+
+ if (isFolder)
+ {
+ err = fnfErr;
+ goto unlock;
+ }
+
+ /* Finally, try to load the library */
+ err = NSLoadNamedFragment(&resolvedSpec, fragmentName, &connectionID);
+ if (err != noErr)
+ goto unlock;
+
+ newLib->name = strdup(fragmentName);
+ newLib->connection = connectionID;
+ newLib->next = pr_loadmap;
+ pr_loadmap = newLib;
+
+ result = newLib; /* success */
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", newLib->name));
+
+unlock:
+ if (result == NULL) {
+ if (newLib != NULL)
+ PR_DELETE(newLib);
+ PR_SetError(PR_LOAD_LIBRARY_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO()); /* sets error text */
+ }
+ PR_ExitMonitor(pr_linker_lock);
+ return result;
+}
+
+
+static PRLibrary*
+pr_Mac_LoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragIndex)
+{
+ PRLibrary* newLib = NULL;
+ PRLibrary* result;
+ FSSpec resolvedSpec = *fileSpec;
+ char* fragmentName = NULL;
+ UInt32 fragOffset, fragLength;
+ CFragConnectionID connectionID = 0;
+ Boolean isFolder, wasAlias;
+ OSErr err = noErr;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* See if library is already loaded */
+ PR_EnterMonitor(pr_linker_lock);
+
+ /* Resolve an alias if this was one */
+ err = ResolveAliasFile(&resolvedSpec, true, &isFolder, &wasAlias);
+ if (err != noErr)
+ goto unlock;
+
+ if (isFolder)
+ {
+ err = fnfErr;
+ goto unlock;
+ }
+ err = GetIndexedFragmentOffsets(&resolvedSpec, fragIndex, &fragOffset, &fragLength, &fragmentName);
+ if (err != noErr) goto unlock;
+
+ result = pr_UnlockedFindLibrary(fragmentName);
+ free(fragmentName);
+ fragmentName = NULL;
+ if (result != NULL) goto unlock;
+
+ newLib = PR_NEWZAP(PRLibrary);
+ if (newLib == NULL) goto unlock;
+ newLib->staticTable = NULL;
+
+ /* Finally, try to load the library */
+ err = NSLoadIndexedFragment(&resolvedSpec, fragIndex, &fragmentName, &connectionID);
+ if (err != noErr) {
+ PR_DELETE(newLib);
+ goto unlock;
+ }
+
+ newLib->name = fragmentName; /* was malloced in NSLoadIndexedFragment */
+ newLib->connection = connectionID;
+ newLib->next = pr_loadmap;
+ pr_loadmap = newLib;
+
+ result = newLib; /* success */
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", newLib->name));
+
+unlock:
+ if (result == NULL) {
+ if (newLib != NULL)
+ PR_DELETE(newLib);
+ PR_SetError(PR_LOAD_LIBRARY_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO()); /* sets error text */
+ }
+ PR_ExitMonitor(pr_linker_lock);
+ return result;
+}
+
+
+#endif
+
+/*
+** Unload a shared library which was loaded via PR_LoadLibrary
+*/
+PR_IMPLEMENT(PRStatus)
+PR_UnloadLibrary(PRLibrary *lib)
+{
+ int result = 0;
+ PRStatus status = PR_SUCCESS;
+
+ if ((lib == 0) || (lib->refCount <= 0)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ PR_EnterMonitor(pr_linker_lock);
+ if (--lib->refCount > 0) {
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN,
+ ("%s decr => %d",
+ lib->name, lib->refCount));
+ goto done;
+ }
+
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+ result = RTLdrClose(lib->dlh);
+ lib->dlh = NIL_RTLDRMOD;
+
+#else /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+#ifdef XP_BEOS
+ if(((image_id)lib->stub_dlh) == B_ERROR)
+ unload_add_on( (image_id) lib->dlh );
+ else
+ unload_add_on( (image_id) lib->stub_dlh);
+#endif
+
+#ifdef XP_UNIX
+#ifdef HAVE_DLL
+#ifdef USE_DLFCN
+ result = dlclose(lib->dlh);
+#elif defined(USE_HPSHL)
+ result = shl_unload(lib->dlh);
+#elif defined(USE_MACH_DYLD)
+ result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1;
+#else
+#error Configuration error
+#endif
+#endif /* HAVE_DLL */
+#endif /* XP_UNIX */
+#ifdef XP_PC
+ if (lib->dlh) {
+ FreeLibrary((HINSTANCE)(lib->dlh));
+ lib->dlh = (HINSTANCE)NULL;
+ }
+#endif /* XP_PC */
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+ /* Close the connection */
+ if (lib->connection)
+ CloseConnection(&(lib->connection));
+#if TARGET_CARBON
+ if (lib->bundle)
+ CFRelease(lib->bundle);
+#endif
+#if defined(XP_MACOSX)
+ if (lib->wrappers)
+ CFRelease(lib->wrappers);
+ /* No way to unload an image (lib->image) */
+#endif
+#endif
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+
+ /* unlink from library search list */
+ if (pr_loadmap == lib)
+ pr_loadmap = pr_loadmap->next;
+ else if (pr_loadmap != NULL) {
+ PRLibrary* prev = pr_loadmap;
+ PRLibrary* next = pr_loadmap->next;
+ while (next != NULL) {
+ if (next == lib) {
+ prev->next = next->next;
+ goto freeLib;
+ }
+ prev = next;
+ next = next->next;
+ }
+ /*
+ * fail (the library is not on the _pr_loadmap list),
+ * but don't wipe out an error from dlclose/shl_unload.
+ */
+ PR_ASSERT(!"_pr_loadmap and lib->refCount inconsistent");
+ if (result == 0) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ status = PR_FAILURE;
+ }
+ }
+ /*
+ * We free the PRLibrary structure whether dlclose/shl_unload
+ * succeeds or not.
+ */
+
+ freeLib:
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTStrFree(lib->name);
+#else
+ free(lib->name);
+#endif
+ lib->name = NULL;
+ PR_DELETE(lib);
+ if (result != 0) {
+ PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ status = PR_FAILURE;
+ }
+
+done:
+ PR_ExitMonitor(pr_linker_lock);
+ return status;
+}
+
+static void*
+pr_FindSymbolInLib(PRLibrary *lm, const char *name)
+{
+ void *f = NULL;
+#ifdef XP_OS2
+ int rc;
+#endif
+
+ if (lm->staticTable != NULL) {
+ const PRStaticLinkTable* tp;
+ for (tp = lm->staticTable; tp->name; tp++) {
+ if (strcmp(name, tp->name) == 0) {
+ return (void*) tp->fp;
+ }
+ }
+ /*
+ ** If the symbol was not found in the static table then check if
+ ** the symbol was exported in the DLL... Win16 only!!
+ */
+#if !defined(WIN16) && !defined(XP_BEOS)
+ PR_SetError(PR_FIND_SYMBOL_ERROR, 0);
+ return (void*)NULL;
+#endif
+ }
+
+#ifdef VBOX_USE_MORE_IPRT_IN_NSPR
+ if (RT_FAILURE(RTLdrGetSymbol(lm->dlh, name, &f)))
+ f = NULL;
+
+#else /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+#ifdef XP_OS2
+ rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
+#if defined(NEED_LEADING_UNDERSCORE)
+ /*
+ * Older plugins (not built using GCC) will have symbols that are not
+ * underscore prefixed. We check for that here.
+ */
+ if (rc != NO_ERROR) {
+ name++;
+ DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f);
+ }
+#endif
+#endif /* XP_OS2 */
+
+#if defined(WIN32) || defined(WIN16)
+ f = GetProcAddress(lm->dlh, name);
+#endif /* WIN32 || WIN16 */
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#if defined(NEED_LEADING_UNDERSCORE)
+#define SYM_OFFSET 1
+#else
+#define SYM_OFFSET 0
+#endif
+#if TARGET_CARBON
+ if (lm->bundle) {
+ CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII);
+ if (nameRef) {
+ f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef);
+ CFRelease(nameRef);
+ }
+ }
+#endif
+ if (lm->connection) {
+ Ptr symAddr;
+ CFragSymbolClass symClass;
+ Str255 pName;
+
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_OFFSET));
+
+ PStrFromCStr(name + SYM_OFFSET, pName);
+
+#if defined(XP_MACOSX)
+ f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
+#else
+ f = (NSFindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL;
+#endif
+
+#if defined(XP_MACOSX)
+ /* callers expect mach-o function pointers, so must wrap tvectors with glue. */
+ if (f && symClass == kTVectorCFragSymbol) {
+ f = TV2FP(lm->wrappers, name + SYM_OFFSET, f);
+ }
+#endif
+
+ if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main;
+ }
+#if defined(XP_MACOSX)
+ if (lm->image) {
+ NSSymbol symbol;
+ symbol = NSLookupSymbolInImage(lm->image, name,
+ NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+ | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+ if (symbol != NULL)
+ f = NSAddressOfSymbol(symbol);
+ else
+ f = NULL;
+ }
+#endif
+#undef SYM_OFFSET
+#endif /* XP_MAC */
+
+#ifdef XP_BEOS
+ if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_TEXT, &f ) ) {
+ f = NULL;
+ }
+#endif
+
+#ifdef XP_UNIX
+#ifdef HAVE_DLL
+#ifdef USE_DLFCN
+ f = dlsym(lm->dlh, name);
+#elif defined(USE_HPSHL)
+ if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) {
+ f = NULL;
+ }
+#elif defined(USE_MACH_DYLD)
+ if (lm->dlh) {
+ NSSymbol symbol;
+ symbol = NSLookupSymbolInModule(lm->dlh, name);
+ if (symbol != NULL)
+ f = NSAddressOfSymbol(symbol);
+ else
+ f = NULL;
+ }
+#endif
+#endif /* HAVE_DLL */
+#endif /* XP_UNIX */
+#endif /* !VBOX_USE_MORE_IPRT_IN_NSPR */
+ if (f == NULL) {
+ PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ }
+ return f;
+}
+
+/*
+** Called by class loader to resolve missing native's
+*/
+PR_IMPLEMENT(void*)
+PR_FindSymbol(PRLibrary *lib, const char *raw_name)
+{
+ void *f = NULL;
+#if defined(NEED_LEADING_UNDERSCORE)
+ char *name;
+#else
+ const char *name;
+#endif
+ /*
+ ** Mangle the raw symbol name in any way that is platform specific.
+ */
+#if defined(NEED_LEADING_UNDERSCORE)
+ /* Need a leading _ */
+ name = PR_smprintf("_%s", raw_name);
+#elif defined(AIX)
+ /*
+ ** AIX with the normal linker put's a "." in front of the symbol
+ ** name. When use "svcc" and "svld" then the "." disappears. Go
+ ** figure.
+ */
+ name = raw_name;
+#else
+ name = raw_name;
+#endif
+
+ PR_EnterMonitor(pr_linker_lock);
+ PR_ASSERT(lib != NULL);
+ f = pr_FindSymbolInLib(lib, name);
+
+#if defined(NEED_LEADING_UNDERSCORE)
+ PR_smprintf_free(name);
+#endif
+
+ PR_ExitMonitor(pr_linker_lock);
+ return f;
+}
+
+/*
+** Return the address of the function 'raw_name' in the library 'lib'
+*/
+PR_IMPLEMENT(PRFuncPtr)
+PR_FindFunctionSymbol(PRLibrary *lib, const char *raw_name)
+{
+ return ((PRFuncPtr) PR_FindSymbol(lib, raw_name));
+}
+
+PR_IMPLEMENT(void*)
+PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
+{
+ void *f = NULL;
+#if defined(NEED_LEADING_UNDERSCORE)
+ char *name;
+#else
+ const char *name;
+#endif
+ PRLibrary* lm;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ /*
+ ** Mangle the raw symbol name in any way that is platform specific.
+ */
+#if defined(NEED_LEADING_UNDERSCORE)
+ /* Need a leading _ */
+ name = PR_smprintf("_%s", raw_name);
+#elif defined(AIX)
+ /*
+ ** AIX with the normal linker put's a "." in front of the symbol
+ ** name. When use "svcc" and "svld" then the "." disappears. Go
+ ** figure.
+ */
+ name = raw_name;
+#else
+ name = raw_name;
+#endif
+
+ PR_EnterMonitor(pr_linker_lock);
+
+ /* search all libraries */
+ for (lm = pr_loadmap; lm != NULL; lm = lm->next) {
+ f = pr_FindSymbolInLib(lm, name);
+ if (f != NULL) {
+ *lib = lm;
+ lm->refCount++;
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN,
+ ("%s incr => %d (for %s)",
+ lm->name, lm->refCount, name));
+ break;
+ }
+ }
+#if defined(NEED_LEADING_UNDERSCORE)
+ PR_smprintf_free(name);
+#endif
+
+ PR_ExitMonitor(pr_linker_lock);
+ return f;
+}
+
+PR_IMPLEMENT(PRFuncPtr)
+PR_FindFunctionSymbolAndLibrary(const char *raw_name, PRLibrary* *lib)
+{
+ return ((PRFuncPtr) PR_FindSymbolAndLibrary(raw_name, lib));
+}
+
+/*
+** Add a static library to the list of loaded libraries. If LoadLibrary
+** is called with the name then we will pretend it was already loaded
+*/
+PR_IMPLEMENT(PRLibrary*)
+PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt)
+{
+ PRLibrary *lm=NULL;
+ PRLibrary* result = NULL;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /* See if library is already loaded */
+ PR_EnterMonitor(pr_linker_lock);
+
+ /* If the lbrary is already loaded, then add the static table information... */
+ result = pr_UnlockedFindLibrary(name);
+ if (result != NULL) {
+ PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) );
+ result->staticTable = slt;
+ goto unlock;
+ }
+
+ /* Add library to list...Mark it static */
+ lm = PR_NEWZAP(PRLibrary);
+ if (lm == NULL) goto unlock;
+
+ lm->name = strdup(name);
+ lm->refCount = 1;
+#if defined(XP_MAC) && !defined(VBOX_USE_MORE_IPRT_IN_NSPR)
+ lm->connection = pr_exe_loadmap ? pr_exe_loadmap->connection : 0;
+#else
+ lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0;
+#endif
+ lm->staticTable = slt;
+ lm->next = pr_loadmap;
+ pr_loadmap = lm;
+
+ result = lm; /* success */
+ PR_ASSERT(lm->refCount == 1);
+ unlock:
+ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->name));
+ PR_ExitMonitor(pr_linker_lock);
+ return result;
+}
+
+PR_IMPLEMENT(char *)
+PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr)
+{
+#if defined(SOLARIS) || defined(LINUX) || defined(FREEBSD)
+ Dl_info dli;
+ char *result;
+
+ if (dladdr((void *)addr, &dli) == 0) {
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ return NULL;
+ }
+ result = PR_Malloc(strlen(dli.dli_fname)+1);
+ if (result != NULL) {
+ strcpy(result, dli.dli_fname);
+ }
+ return result;
+#elif defined(USE_MACH_DYLD)
+ char *result;
+ char const *image_name;
+ int i, count = _dyld_image_count();
+
+ for (i = 0; i < count; i++) {
+ image_name = _dyld_get_image_name(i);
+ if (strstr(image_name, name) != NULL) {
+ result = PR_Malloc(strlen(image_name)+1);
+ if (result != NULL) {
+ strcpy(result, image_name);
+ }
+ return result;
+ }
+ }
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
+ return NULL;
+#elif defined(AIX)
+ char *result;
+#define LD_INFO_INCREMENT 64
+ struct ld_info *info;
+ unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info);
+ struct ld_info *infop;
+
+ for (;;) {
+ info = PR_Malloc(info_length);
+ if (info == NULL) {
+ return NULL;
+ }
+ /* If buffer is too small, loadquery fails with ENOMEM. */
+ if (loadquery(L_GETINFO, info, info_length) != -1) {
+ break;
+ }
+ PR_Free(info);
+ if (errno != ENOMEM) {
+ /* should not happen */
+ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
+ return NULL;
+ }
+ /* retry with a larger buffer */
+ info_length += LD_INFO_INCREMENT * sizeof(struct ld_info);
+ }
+
+ for (infop = info;
+ ;
+ infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) {
+ if (strstr(infop->ldinfo_filename, name) != NULL) {
+ result = PR_Malloc(strlen(infop->ldinfo_filename)+1);
+ if (result != NULL) {
+ strcpy(result, infop->ldinfo_filename);
+ }
+ break;
+ }
+ if (!infop->ldinfo_next) {
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
+ result = NULL;
+ break;
+ }
+ }
+ PR_Free(info);
+ return result;
+#elif defined(OSF1)
+ /* Contributed by Steve Streeter of HP */
+ ldr_process_t process, ldr_my_process();
+ ldr_module_t mod_id;
+ ldr_module_info_t info;
+ ldr_region_t regno;
+ ldr_region_info_t reginfo;
+ size_t retsize;
+ int rv;
+ char *result;
+
+ /* Get process for which dynamic modules will be listed */
+
+ process = ldr_my_process();
+
+ /* Attach to process */
+
+ rv = ldr_xattach(process);
+ if (rv) {
+ /* should not happen */
+ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
+ return NULL;
+ }
+
+ /* Print information for list of modules */
+
+ mod_id = LDR_NULL_MODULE;
+
+ for (;;) {
+
+ /* Get information for the next module in the module list. */
+
+ ldr_next_module(process, &mod_id);
+ if (ldr_inq_module(process, mod_id, &info, sizeof(info),
+ &retsize) != 0) {
+ /* No more modules */
+ break;
+ }
+ if (retsize < sizeof(info)) {
+ continue;
+ }
+
+ /*
+ * Get information for each region in the module and check if any
+ * contain the address of this function.
+ */
+
+ for (regno = 0; ; regno++) {
+ if (ldr_inq_region(process, mod_id, regno, &reginfo,
+ sizeof(reginfo), &retsize) != 0) {
+ /* No more regions */
+ break;
+ }
+ if (((unsigned long)reginfo.lri_mapaddr <=
+ (unsigned long)addr) &&
+ (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) >
+ (unsigned long)addr)) {
+ /* Found it. */
+ result = PR_Malloc(strlen(info.lmi_name)+1);
+ if (result != NULL) {
+ strcpy(result, info.lmi_name);
+ }
+ return result;
+ }
+ }
+ }
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
+ return NULL;
+#elif defined(VMS)
+ /* Contributed by Colin Blake of HP */
+ struct _imcb *icb;
+ ulong_t status;
+ char device_name[MAX_DEVNAM];
+ int device_name_len;
+ $DESCRIPTOR (device_name_desc, device_name);
+ struct fibdef fib;
+ struct dsc$descriptor_s fib_desc =
+ { sizeof(struct fibdef), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *)&fib } ;
+ IOSB iosb;
+ ITMLST devlst[2] = {
+ {MAX_DEVNAM, DVI$_ALLDEVNAM, device_name, &device_name_len},
+ {0,0,0,0}};
+ short file_name_len;
+ char file_name[MAX_FILNAM+1];
+ char *result = NULL;
+ struct dsc$descriptor_s file_name_desc =
+ { MAX_FILNAM, DSC$K_DTYPE_T, DSC$K_CLASS_S, (char *) &file_name[0] } ;
+
+ /*
+ ** The address for the process image list could change in future versions
+ ** of the operating system. 7FFD0688 is valid for V7.2 and V7.3 releases,
+ ** so we use that for the default, but allow an environment variable
+ ** (logical name) to override.
+ */
+ if (IAC$GL_IMAGE_LIST == NULL) {
+ char *p = getenv("MOZILLA_IAC_GL_IMAGE_LIST");
+ if (p)
+ IAC$GL_IMAGE_LIST = (struct _imcb *) strtol(p,NULL,0);
+ else
+ IAC$GL_IMAGE_LIST = (struct _imcb *) 0x7FFD0688;
+ }
+
+ for (icb = IAC$GL_IMAGE_LIST->imcb$l_flink;
+ icb != IAC$GL_IMAGE_LIST;
+ icb = icb->imcb$l_flink) {
+ if (((void *)addr >= icb->imcb$l_starting_address) &&
+ ((void *)addr <= icb->imcb$l_end_address)) {
+ /*
+ ** This is the correct image.
+ ** Get the device name.
+ */
+ status = sys$getdviw(0,icb->imcb$w_chan,0,&devlst,0,0,0,0);
+ if ($VMS_STATUS_SUCCESS(status))
+ device_name_desc.dsc$w_length = device_name_len;
+
+ /*
+ ** Get the FID.
+ */
+ memset(&fib,0,sizeof(struct fibdef));
+ status = sys$qiow(0,icb->imcb$w_chan,IO$_ACCESS,&iosb,
+ 0,0,&fib_desc,0,0,0,0,0);
+
+ /*
+ ** If we got the FID, now look up its name (if for some reason
+ ** we didn't get the device name, this call will fail).
+ */
+ if (($VMS_STATUS_SUCCESS(status)) && ($VMS_STATUS_SUCCESS(iosb.cond))) {
+ status = lib$fid_to_name (
+ &device_name_desc,
+ &fib.fib$w_fid,
+ &file_name_desc,
+ &file_name_len,
+ 0, 0);
+
+ /*
+ ** If we succeeded then remove the version number and
+ ** return a copy of the UNIX format version of the file name.
+ */
+ if ($VMS_STATUS_SUCCESS(status)) {
+ char *p, *result;
+ file_name[file_name_len] = 0;
+ p = strrchr(file_name,';');
+ if (p) *p = 0;
+ p = decc$translate_vms(&file_name[0]);
+ result = PR_Malloc(strlen(p)+1);
+ if (result != NULL) {
+ strcpy(result, p);
+ }
+ return result;
+ }
+ }
+ }
+ }
+
+ /* Didn't find it */
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
+ return NULL;
+
+#elif defined(HPUX) && defined(USE_HPSHL)
+ int index;
+ struct shl_descriptor desc;
+ char *result;
+
+ for (index = 0; shl_get_r(index, &desc) == 0; index++) {
+ if (strstr(desc.filename, name) != NULL) {
+ result = PR_Malloc(strlen(desc.filename)+1);
+ if (result != NULL) {
+ strcpy(result, desc.filename);
+ }
+ return result;
+ }
+ }
+ /*
+ * Since the index value of a library is decremented if
+ * a library preceding it in the shared library search
+ * list was unloaded, it is possible that we missed some
+ * libraries as we went up the list. So we should go
+ * down the list to be sure that we not miss anything.
+ */
+ for (index--; index >= 0; index--) {
+ if ((shl_get_r(index, &desc) == 0)
+ && (strstr(desc.filename, name) != NULL)) {
+ result = PR_Malloc(strlen(desc.filename)+1);
+ if (result != NULL) {
+ strcpy(result, desc.filename);
+ }
+ return result;
+ }
+ }
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0);
+ return NULL;
+#elif defined(HPUX) && defined(USE_DLFCN)
+ struct load_module_desc desc;
+ char *result;
+ const char *module_name;
+
+ if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) {
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ return NULL;
+ }
+ module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0);
+ if (module_name == NULL) {
+ /* should not happen */
+ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ return NULL;
+ }
+ result = PR_Malloc(strlen(module_name)+1);
+ if (result != NULL) {
+ strcpy(result, module_name);
+ }
+ return result;
+#elif defined(WIN32)
+ HMODULE handle;
+ char module_name[MAX_PATH];
+ char *result;
+
+ handle = GetModuleHandle(name);
+ if (handle == NULL) {
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ return NULL;
+ }
+ if (GetModuleFileName(handle, module_name, sizeof module_name) == 0) {
+ /* should not happen */
+ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
+ return NULL;
+ }
+ result = PR_Malloc(strlen(module_name)+1);
+ if (result != NULL) {
+ strcpy(result, module_name);
+ }
+ return result;
+#elif defined(XP_OS2)
+ HMODULE module = NULL;
+ char module_name[_MAX_PATH];
+ char *result;
+ APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr);
+ if ((NO_ERROR != ulrc) || (NULL == module) ) {
+ PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO());
+ DLLErrorInternal(_MD_ERRNO());
+ return NULL;
+ }
+ ulrc = DosQueryModuleName(module, sizeof module_name, module_name);
+ if (NO_ERROR != ulrc) {
+ /* should not happen */
+ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
+ return NULL;
+ }
+ result = PR_Malloc(strlen(module_name)+1);
+ if (result != NULL) {
+ strcpy(result, module_name);
+ }
+ return result;
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+#endif
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/malloc/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/malloc/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/Makefile.in
new file mode 100644
index 00000000..981ec462
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/Makefile.in
@@ -0,0 +1,67 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OPTIMIZER =
+endif
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+CSRCS = prmalloc.c prmem.c
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmalloc.c b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmalloc.c
new file mode 100644
index 00000000..10e9cf78
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmalloc.c
@@ -0,0 +1,1174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/*
+** We override malloc etc. on any platform which has preemption +
+** nspr20 user level threads. When we're debugging, we can make our
+** version of malloc fail occasionally.
+*/
+#ifdef _PR_OVERRIDE_MALLOC
+
+/*
+** Thread safe version of malloc, calloc, realloc, free
+*/
+#include <stdarg.h>
+
+#ifdef DEBUG
+#define SANITY
+#define EXTRA_SANITY
+#else
+#undef SANITY
+#undef EXTRA_SANITY
+#endif
+
+/* Forward decls */
+void *_PR_UnlockedMalloc(size_t size);
+void _PR_UnlockedFree(void *ptr);
+void *_PR_UnlockedRealloc(void *ptr, size_t size);
+void *_PR_UnlockedCalloc(size_t n, size_t elsize);
+
+/************************************************************************/
+
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+/*
+ * Defining SANITY will enable some checks which will tell you if the users
+ * program did botch something
+ */
+
+/*
+ * Defining EXTRA_SANITY will enable some checks which are mostly related
+ * to internal conditions in malloc.c
+ */
+
+/*
+ * Very verbose progress on stdout...
+ */
+#if 0
+# define TRACE(foo) printf foo
+static int malloc_event;
+#else
+# define TRACE(foo)
+#endif
+
+/* XXX Pick a number, any number */
+# define malloc_pagesize 4096UL
+# define malloc_pageshift 12UL
+
+#ifdef XP_UNIX
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#endif
+
+/*
+ * This structure describes a page's worth of chunks.
+ */
+
+struct pginfo {
+ struct pginfo *next; /* next on the free list */
+ char *page; /* Pointer to the page */
+ u_short size; /* size of this page's chunks */
+ u_short shift; /* How far to shift for this size chunks */
+ u_short free; /* How many free chunks */
+ u_short total; /* How many chunk */
+ u_long bits[1]; /* Which chunks are free */
+};
+
+struct pgfree {
+ struct pgfree *next; /* next run of free pages */
+ struct pgfree *prev; /* prev run of free pages */
+ char *page; /* pointer to free pages */
+ char *end; /* pointer to end of free pages */
+ u_long size; /* number of bytes free */
+};
+
+/*
+ * How many bits per u_long in the bitmap.
+ * Change only if not 8 bits/byte
+ */
+#define MALLOC_BITS (8*sizeof(u_long))
+
+/*
+ * Magic values to put in the page_directory
+ */
+#define MALLOC_NOT_MINE ((struct pginfo*) 0)
+#define MALLOC_FREE ((struct pginfo*) 1)
+#define MALLOC_FIRST ((struct pginfo*) 2)
+#define MALLOC_FOLLOW ((struct pginfo*) 3)
+#define MALLOC_MAGIC ((struct pginfo*) 4)
+
+/*
+ * Set to one when malloc_init has been called
+ */
+static unsigned initialized;
+
+/*
+ * The size of a page.
+ * Must be a integral multiplum of the granularity of mmap(2).
+ * Your toes will curl if it isn't a power of two
+ */
+#define malloc_pagemask ((malloc_pagesize)-1)
+
+/*
+ * The size of the largest chunk.
+ * Half a page.
+ */
+#define malloc_maxsize ((malloc_pagesize)>>1)
+
+/*
+ * malloc_pagesize == 1 << malloc_pageshift
+ */
+#ifndef malloc_pageshift
+static unsigned malloc_pageshift;
+#endif /* malloc_pageshift */
+
+/*
+ * The smallest allocation we bother about.
+ * Must be power of two
+ */
+#ifndef malloc_minsize
+static unsigned malloc_minsize;
+#endif /* malloc_minsize */
+
+/*
+ * The largest chunk we care about.
+ * Must be smaller than pagesize
+ * Must be power of two
+ */
+#ifndef malloc_maxsize
+static unsigned malloc_maxsize;
+#endif /* malloc_maxsize */
+
+#ifndef malloc_cache
+static unsigned malloc_cache;
+#endif /* malloc_cache */
+
+/*
+ * The offset from pagenumber to index into the page directory
+ */
+static u_long malloc_origo;
+
+/*
+ * The last index in the page directory we care about
+ */
+static u_long last_index;
+
+/*
+ * Pointer to page directory.
+ * Allocated "as if with" malloc
+ */
+static struct pginfo **page_dir;
+
+/*
+ * How many slots in the page directory
+ */
+static unsigned malloc_ninfo;
+
+/*
+ * Free pages line up here
+ */
+static struct pgfree free_list;
+
+/*
+ * Abort() if we fail to get VM ?
+ */
+static int malloc_abort;
+
+#ifdef SANITY
+/*
+ * Are we trying to die ?
+ */
+static int suicide;
+#endif
+
+/*
+ * dump statistics
+ */
+static int malloc_stats;
+
+/*
+ * always realloc ?
+ */
+static int malloc_realloc;
+
+/*
+ * my last break.
+ */
+static void *malloc_brk;
+
+/*
+ * one location cache for free-list holders
+ */
+static struct pgfree *px;
+
+static int set_pgdir(void *ptr, struct pginfo *info);
+static int extend_page_directory(u_long index);
+
+#ifdef SANITY
+void
+malloc_dump(FILE *fd)
+{
+ struct pginfo **pd;
+ struct pgfree *pf;
+ int j;
+
+ pd = page_dir;
+
+ /* print out all the pages */
+ for(j=0;j<=last_index;j++) {
+ fprintf(fd,"%08lx %5d ",(j+malloc_origo) << malloc_pageshift,j);
+ if (pd[j] == MALLOC_NOT_MINE) {
+ for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
+ ;
+ j--;
+ fprintf(fd,".. %5d not mine\n", j);
+ } else if (pd[j] == MALLOC_FREE) {
+ for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
+ ;
+ j--;
+ fprintf(fd,".. %5d free\n", j);
+ } else if (pd[j] == MALLOC_FIRST) {
+ for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
+ ;
+ j--;
+ fprintf(fd,".. %5d in use\n", j);
+ } else if (pd[j] < MALLOC_MAGIC) {
+ fprintf(fd,"(%p)\n", pd[j]);
+ } else {
+ fprintf(fd,"%p %d (of %d) x %d @ %p --> %p\n",
+ pd[j],pd[j]->free, pd[j]->total,
+ pd[j]->size, pd[j]->page, pd[j]->next);
+ }
+ }
+
+ for(pf=free_list.next; pf; pf=pf->next) {
+ fprintf(fd,"Free: @%p [%p...%p[ %ld ->%p <-%p\n",
+ pf,pf->page,pf->end,pf->size,pf->prev,pf->next);
+ if (pf == pf->next) {
+ fprintf(fd,"Free_list loops.\n");
+ break;
+ }
+ }
+
+ /* print out various info */
+ fprintf(fd,"Minsize\t%d\n",malloc_minsize);
+ fprintf(fd,"Maxsize\t%ld\n",malloc_maxsize);
+ fprintf(fd,"Pagesize\t%ld\n",malloc_pagesize);
+ fprintf(fd,"Pageshift\t%ld\n",malloc_pageshift);
+ fprintf(fd,"FirstPage\t%ld\n",malloc_origo);
+ fprintf(fd,"LastPage\t%ld %lx\n",last_index+malloc_pageshift,
+ (last_index + malloc_pageshift) << malloc_pageshift);
+ fprintf(fd,"Break\t%ld\n",(u_long)sbrk(0) >> malloc_pageshift);
+}
+
+static void wrterror(char *fmt, ...)
+{
+ char *q = "malloc() error: ";
+ char buf[100];
+ va_list ap;
+
+ suicide = 1;
+
+ va_start(ap, fmt);
+ PR_vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ fputs(q, stderr);
+ fputs(buf, stderr);
+
+ malloc_dump(stderr);
+ PR_Abort();
+}
+
+static void wrtwarning(char *fmt, ...)
+{
+ char *q = "malloc() warning: ";
+ char buf[100];
+ va_list ap;
+
+ va_start(ap, fmt);
+ PR_vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ fputs(q, stderr);
+ fputs(buf, stderr);
+}
+#endif /* SANITY */
+
+
+/*
+ * Allocate a number of pages from the OS
+ */
+static caddr_t
+map_pages(int pages, int update)
+{
+ caddr_t result,tail;
+
+ result = ((caddr_t)sbrk(0)) + malloc_pagemask - 1;
+ result = (caddr_t) ((u_long)result & ~malloc_pagemask);
+ tail = result + (pages << malloc_pageshift);
+ if (!brk(tail)) {
+ last_index = ((u_long)tail >> malloc_pageshift) - malloc_origo -1;
+ malloc_brk = tail;
+ TRACE(("%6d S %p .. %p\n",malloc_event++, result, tail));
+ if (!update || last_index < malloc_ninfo ||
+ extend_page_directory(last_index))
+ return result;
+ }
+ TRACE(("%6d s %d %p %d\n",malloc_event++,pages,sbrk(0),errno));
+#ifdef EXTRA_SANITY
+ wrterror("map_pages fails\n");
+#endif
+ return 0;
+}
+
+#define set_bit(_pi,_bit) \
+ (_pi)->bits[(_bit)/MALLOC_BITS] |= 1L<<((_bit)%MALLOC_BITS)
+
+#define clr_bit(_pi,_bit) \
+ (_pi)->bits[(_bit)/MALLOC_BITS] &= ~(1L<<((_bit)%MALLOC_BITS));
+
+#define tst_bit(_pi,_bit) \
+ ((_pi)->bits[(_bit)/MALLOC_BITS] & (1L<<((_bit)%MALLOC_BITS)))
+
+/*
+ * Extend page directory
+ */
+static int
+extend_page_directory(u_long index)
+{
+ struct pginfo **young, **old;
+ int i;
+
+ TRACE(("%6d E %lu\n",malloc_event++,index));
+
+ /* Make it this many pages */
+ i = index * sizeof *page_dir;
+ i /= malloc_pagesize;
+ i += 2;
+
+ /* Get new pages, if you used this much mem you don't care :-) */
+ young = (struct pginfo**) map_pages(i,0);
+ if (!young)
+ return 0;
+
+ /* Copy the old stuff */
+ memset(young, 0, i * malloc_pagesize);
+ memcpy(young, page_dir,
+ malloc_ninfo * sizeof *page_dir);
+
+ /* register the new size */
+ malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
+
+ /* swap the pointers */
+ old = page_dir;
+ page_dir = young;
+
+ /* Mark the pages */
+ index = ((u_long)young >> malloc_pageshift) - malloc_origo;
+ page_dir[index] = MALLOC_FIRST;
+ while (--i) {
+ page_dir[++index] = MALLOC_FOLLOW;
+ }
+
+ /* Now free the old stuff */
+ _PR_UnlockedFree(old);
+ return 1;
+}
+
+/*
+ * Set entry in page directory.
+ * Extend page directory if need be.
+ */
+static int
+set_pgdir(void *ptr, struct pginfo *info)
+{
+ u_long index = ((u_long)ptr >> malloc_pageshift) - malloc_origo;
+
+ if (index >= malloc_ninfo && !extend_page_directory(index))
+ return 0;
+ page_dir[index] = info;
+ return 1;
+}
+
+/*
+ * Initialize the world
+ */
+static void
+malloc_init (void)
+{
+ int i;
+ char *p;
+
+ TRACE(("%6d I\n",malloc_event++));
+#ifdef DEBUG
+ for (p=getenv("MALLOC_OPTIONS"); p && *p; p++) {
+ switch (*p) {
+ case 'a': malloc_abort = 0; break;
+ case 'A': malloc_abort = 1; break;
+ case 'd': malloc_stats = 0; break;
+ case 'D': malloc_stats = 1; break;
+ case 'r': malloc_realloc = 0; break;
+ case 'R': malloc_realloc = 1; break;
+ default:
+ wrtwarning("Unknown chars in MALLOC_OPTIONS\n");
+ break;
+ }
+ }
+#endif
+
+#ifndef malloc_pagesize
+ /* determine our pagesize */
+ malloc_pagesize = getpagesize();
+#endif /* malloc_pagesize */
+
+#ifndef malloc_pageshift
+ /* determine how much we shift by to get there */
+ for (i = malloc_pagesize; i > 1; i >>= 1)
+ malloc_pageshift++;
+#endif /* malloc_pageshift */
+
+#ifndef malloc_cache
+ malloc_cache = 50 << malloc_pageshift;
+#endif /* malloc_cache */
+
+#ifndef malloc_minsize
+ /*
+ * find the smallest size allocation we will bother about.
+ * this is determined as the smallest allocation that can hold
+ * it's own pginfo;
+ */
+ i = 2;
+ for(;;) {
+ int j;
+
+ /* Figure out the size of the bits */
+ j = malloc_pagesize/i;
+ j /= 8;
+ if (j < sizeof(u_long))
+ j = sizeof (u_long);
+ if (sizeof(struct pginfo) + j - sizeof (u_long) <= i)
+ break;
+ i += i;
+ }
+ malloc_minsize = i;
+#endif /* malloc_minsize */
+
+
+ /* Allocate one page for the page directory */
+ page_dir = (struct pginfo **) map_pages(1,0);
+#ifdef SANITY
+ if (!page_dir)
+ wrterror("fatal: my first mmap failed. (check limits ?)\n");
+#endif
+
+ /*
+ * We need a maximum of malloc_pageshift buckets, steal these from the
+ * front of the page_directory;
+ */
+ malloc_origo = (u_long) page_dir >> malloc_pageshift;
+ malloc_origo -= malloc_pageshift;
+
+ /* Clear it */
+ memset(page_dir,0,malloc_pagesize);
+
+ /* Find out how much it tells us */
+ malloc_ninfo = malloc_pagesize / sizeof *page_dir;
+
+ /* Plug the page directory into itself */
+ i = set_pgdir(page_dir,MALLOC_FIRST);
+#ifdef SANITY
+ if (!i)
+ wrterror("fatal: couldn't set myself in the page directory\n");
+#endif
+
+ /* Been here, done that */
+ initialized++;
+}
+
+/*
+ * Allocate a number of complete pages
+ */
+static void *malloc_pages(size_t size)
+{
+ void *p,*delay_free = 0;
+ int i;
+ struct pgfree *pf;
+ u_long index;
+
+ /* How many pages ? */
+ size += (malloc_pagesize-1);
+ size &= ~malloc_pagemask;
+
+ p = 0;
+ /* Look for free pages before asking for more */
+ for(pf = free_list.next; pf; pf = pf->next) {
+#ifdef EXTRA_SANITY
+ if (pf->page == pf->end)
+ wrterror("zero entry on free_list\n");
+ if (pf->page > pf->end) {
+ TRACE(("%6d !s %p %p %p <%d>\n",malloc_event++,
+ pf,pf->page,pf->end,__LINE__));
+ wrterror("sick entry on free_list\n");
+ }
+ if ((void*)pf->page >= (void*)sbrk(0))
+ wrterror("entry on free_list past brk\n");
+ if (page_dir[((u_long)pf->page >> malloc_pageshift) - malloc_origo]
+ != MALLOC_FREE) {
+ TRACE(("%6d !f %p %p %p <%d>\n",malloc_event++,
+ pf,pf->page,pf->end,__LINE__));
+ wrterror("non-free first page on free-list\n");
+ }
+ if (page_dir[((u_long)pf->end >> malloc_pageshift) - 1 - malloc_origo]
+ != MALLOC_FREE)
+ wrterror("non-free last page on free-list\n");
+#endif /* EXTRA_SANITY */
+ if (pf->size < size)
+ continue;
+ else if (pf->size == size) {
+ p = pf->page;
+ if (pf->next)
+ pf->next->prev = pf->prev;
+ pf->prev->next = pf->next;
+ delay_free = pf;
+ break;
+ } else {
+ p = pf->page;
+ pf->page += size;
+ pf->size -= size;
+ break;
+ }
+ }
+#ifdef EXTRA_SANITY
+ if (p && page_dir[((u_long)p >> malloc_pageshift) - malloc_origo]
+ != MALLOC_FREE) {
+ wrterror("allocated non-free page on free-list\n");
+ }
+#endif /* EXTRA_SANITY */
+
+ size >>= malloc_pageshift;
+
+ /* Map new pages */
+ if (!p)
+ p = map_pages(size,1);
+
+ if (p) {
+ /* Mark the pages in the directory */
+ index = ((u_long)p >> malloc_pageshift) - malloc_origo;
+ page_dir[index] = MALLOC_FIRST;
+ for (i=1;i<size;i++)
+ page_dir[index+i] = MALLOC_FOLLOW;
+ }
+ if (delay_free) {
+ if (!px)
+ px = (struct pgfree*)delay_free;
+ else
+ _PR_UnlockedFree(delay_free);
+ }
+ return p;
+}
+
+/*
+ * Allocate a page of fragments
+ */
+
+static int
+malloc_make_chunks(int bits)
+{
+ struct pginfo *bp;
+ void *pp;
+ int i,k,l;
+
+ /* Allocate a new bucket */
+ pp = malloc_pages(malloc_pagesize);
+ if (!pp)
+ return 0;
+ l = sizeof *bp - sizeof(u_long);
+ l += sizeof(u_long) *
+ (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
+ if ((1<<(bits)) <= l+l) {
+ bp = (struct pginfo *)pp;
+ } else {
+ bp = (struct pginfo *)_PR_UnlockedMalloc(l);
+ }
+ if (!bp)
+ return 0;
+ bp->size = (1<<bits);
+ bp->shift = bits;
+ bp->total = bp->free = malloc_pagesize >> bits;
+ bp->next = page_dir[bits];
+ bp->page = (char*)pp;
+ i = set_pgdir(pp,bp);
+ if (!i)
+ return 0;
+
+ /* We can safely assume that there is nobody in this chain */
+ page_dir[bits] = bp;
+
+ /* set all valid bits in the bits */
+ k = bp->total;
+ i = 0;
+/*
+ for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
+ bp->bits[i / MALLOC_BITS] = ~0;
+*/
+ for(; i < k; i++)
+ set_bit(bp,i);
+
+ if (bp != pp)
+ return 1;
+
+ /* We may have used the first ones already */
+ for(i=0;l > 0;i++) {
+ clr_bit(bp,i);
+ bp->free--;
+ bp->total--;
+ l -= (1 << bits);
+ }
+ return 1;
+}
+
+/*
+ * Allocate a fragment
+ */
+static void *malloc_bytes(size_t size)
+{
+ size_t s;
+ int j;
+ struct pginfo *bp;
+ int k;
+ u_long *lp, bf;
+
+ /* Don't bother with anything less than this */
+ if (size < malloc_minsize) {
+ size = malloc_minsize;
+ }
+
+ /* Find the right bucket */
+ j = 1;
+ s = size - 1;
+ while (s >>= 1) {
+ j++;
+ }
+
+ /* If it's empty, make a page more of that size chunks */
+ if (!page_dir[j] && !malloc_make_chunks(j))
+ return 0;
+
+ /* Find first word of bitmap which isn't empty */
+ bp = page_dir[j];
+ for (lp = bp->bits; !*lp; lp++)
+ ;
+
+ /* Find that bit */
+ bf = *lp;
+ k = 0;
+ while ((bf & 1) == 0) {
+ bf >>= 1;
+ k++;
+ }
+
+ *lp ^= 1L<<k; /* clear it */
+ bp->free--;
+ if (!bp->free) {
+ page_dir[j] = bp->next;
+ bp->next = 0;
+ }
+ k += (lp - bp->bits)*MALLOC_BITS;
+ return bp->page + (k << bp->shift);
+}
+
+void *_PR_UnlockedMalloc(size_t size)
+{
+ void *result;
+
+ /* Round up to a multiple of 8 bytes */
+ if (size & 7) {
+ size = size + 8 - (size & 7);
+ }
+
+ if (!initialized)
+ malloc_init();
+
+#ifdef SANITY
+ if (suicide)
+ PR_Abort();
+#endif
+
+ if (size <= malloc_maxsize)
+ result = malloc_bytes(size);
+ else
+ result = malloc_pages(size);
+#ifdef SANITY
+ if (malloc_abort && !result)
+ wrterror("malloc() returns NULL\n");
+#endif
+ TRACE(("%6d M %p %d\n",malloc_event++,result,size));
+
+ return result;
+}
+
+void *_PR_UnlockedMemalign(size_t alignment, size_t size)
+{
+ void *result;
+
+ /*
+ * alignment has to be a power of 2
+ */
+
+ if ((size <= alignment) && (alignment <= malloc_maxsize))
+ size = alignment;
+ else
+ size += alignment - 1;
+
+ /* Round up to a multiple of 8 bytes */
+ if (size & 7) {
+ size = size + 8 - (size & 7);
+ }
+
+ if (!initialized)
+ malloc_init();
+
+#ifdef SANITY
+ if (suicide)
+ abort();
+#endif
+
+ if (size <= malloc_maxsize)
+ result = malloc_bytes(size);
+ else
+ result = malloc_pages(size);
+#ifdef SANITY
+ if (malloc_abort && !result)
+ wrterror("malloc() returns NULL\n");
+#endif
+ TRACE(("%6d A %p %d\n",malloc_event++,result,size));
+
+ if ((u_long)result & (alignment - 1))
+ return ((void *)(((u_long)result + alignment) & ~(alignment - 1)));
+ else
+ return result;
+}
+
+void *_PR_UnlockedCalloc(size_t n, size_t nelem)
+{
+ void *p;
+
+ /* Compute total size and then round up to a double word amount */
+ n *= nelem;
+ if (n & 7) {
+ n = n + 8 - (n & 7);
+ }
+
+ /* Get the memory */
+ p = _PR_UnlockedMalloc(n);
+ if (p) {
+ /* Zero it */
+ memset(p, 0, n);
+ }
+ return p;
+}
+
+/*
+ * Change an allocation's size
+ */
+void *_PR_UnlockedRealloc(void *ptr, size_t size)
+{
+ void *p;
+ u_long osize,page,index,tmp_index;
+ struct pginfo **mp;
+
+ if (!initialized)
+ malloc_init();
+
+#ifdef SANITY
+ if (suicide)
+ PR_Abort();
+#endif
+
+ /* used as free() */
+ TRACE(("%6d R %p %d\n",malloc_event++, ptr, size));
+ if (ptr && !size) {
+ _PR_UnlockedFree(ptr);
+ return _PR_UnlockedMalloc (1);
+ }
+
+ /* used as malloc() */
+ if (!ptr) {
+ p = _PR_UnlockedMalloc(size);
+ return p;
+ }
+
+ /* Find the page directory entry for the page in question */
+ page = (u_long)ptr >> malloc_pageshift;
+ index = page - malloc_origo;
+
+ /*
+ * check if memory was allocated by memalign
+ */
+ tmp_index = index;
+ while (page_dir[tmp_index] == MALLOC_FOLLOW)
+ tmp_index--;
+ if (tmp_index != index) {
+ /*
+ * memalign-allocated memory
+ */
+ index = tmp_index;
+ page = index + malloc_origo;
+ ptr = (void *) (page << malloc_pageshift);
+ }
+ TRACE(("%6d R2 %p %d\n",malloc_event++, ptr, size));
+
+ /* make sure it makes sense in some fashion */
+ if (index < malloc_pageshift || index > last_index) {
+#ifdef SANITY
+ wrtwarning("junk pointer passed to realloc()\n");
+#endif
+ return 0;
+ }
+
+ /* find the size of that allocation, and see if we need to relocate */
+ mp = &page_dir[index];
+ if (*mp == MALLOC_FIRST) {
+ osize = malloc_pagesize;
+ while (mp[1] == MALLOC_FOLLOW) {
+ osize += malloc_pagesize;
+ mp++;
+ }
+ if (!malloc_realloc &&
+ size < osize &&
+ size > malloc_maxsize &&
+ size > (osize - malloc_pagesize)) {
+ return ptr;
+ }
+ } else if (*mp >= MALLOC_MAGIC) {
+ osize = (*mp)->size;
+ if (!malloc_realloc &&
+ size < osize &&
+ (size > (*mp)->size/2 || (*mp)->size == malloc_minsize)) {
+ return ptr;
+ }
+ } else {
+#ifdef SANITY
+ wrterror("realloc() of wrong page.\n");
+#endif
+ }
+
+ /* try to reallocate */
+ p = _PR_UnlockedMalloc(size);
+
+ if (p) {
+ /* copy the lesser of the two sizes */
+ if (osize < size)
+ memcpy(p,ptr,osize);
+ else
+ memcpy(p,ptr,size);
+ _PR_UnlockedFree(ptr);
+ }
+#ifdef DEBUG
+ else if (malloc_abort)
+ wrterror("realloc() returns NULL\n");
+#endif
+
+ return p;
+}
+
+/*
+ * Free a sequence of pages
+ */
+
+static void
+free_pages(char *ptr, u_long page, int index, struct pginfo *info)
+{
+ int i;
+ struct pgfree *pf,*pt;
+ u_long l;
+ char *tail;
+
+ TRACE(("%6d FP %p %d\n",malloc_event++, ptr, page));
+ /* Is it free already ? */
+ if (info == MALLOC_FREE) {
+#ifdef SANITY
+ wrtwarning("freeing free page at %p.\n", ptr);
+#endif
+ return;
+ }
+
+#ifdef SANITY
+ /* Is it not the right place to begin ? */
+ if (info != MALLOC_FIRST)
+ wrterror("freeing wrong page.\n");
+
+ /* Is this really a pointer to a page ? */
+ if ((u_long)ptr & malloc_pagemask)
+ wrterror("freeing messed up page pointer.\n");
+#endif
+
+ /* Count how many pages it is anyway */
+ page_dir[index] = MALLOC_FREE;
+ for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
+ page_dir[index + i] = MALLOC_FREE;
+
+ l = i << malloc_pageshift;
+
+ tail = ptr+l;
+
+ /* add to free-list */
+ if (!px)
+ px = (struct pgfree*)_PR_UnlockedMalloc(sizeof *pt);
+ /* XXX check success */
+ px->page = ptr;
+ px->end = tail;
+ px->size = l;
+ if (!free_list.next) {
+ px->next = free_list.next;
+ px->prev = &free_list;
+ free_list.next = px;
+ pf = px;
+ px = 0;
+ } else {
+ tail = ptr+l;
+ for(pf = free_list.next; pf->next && pf->end < ptr; pf = pf->next)
+ ;
+ for(; pf; pf = pf->next) {
+ if (pf->end == ptr ) {
+ /* append to entry */
+ pf->end += l;
+ pf->size += l;
+ if (pf->next && pf->end == pf->next->page ) {
+ pt = pf->next;
+ pf->end = pt->end;
+ pf->size += pt->size;
+ pf->next = pt->next;
+ if (pf->next)
+ pf->next->prev = pf;
+ _PR_UnlockedFree(pt);
+ }
+ } else if (pf->page == tail) {
+ /* prepend to entry */
+ pf->size += l;
+ pf->page = ptr;
+ } else if (pf->page > ptr) {
+ px->next = pf;
+ px->prev = pf->prev;
+ pf->prev = px;
+ px->prev->next = px;
+ pf = px;
+ px = 0;
+ } else if (!pf->next) {
+ px->next = 0;
+ px->prev = pf;
+ pf->next = px;
+ pf = px;
+ px = 0;
+ } else {
+ continue;
+ }
+ break;
+ }
+ }
+ if (!pf->next &&
+ pf->size > malloc_cache &&
+ pf->end == malloc_brk &&
+ malloc_brk == (void*)sbrk(0)) {
+ pf->end = pf->page + malloc_cache;
+ pf->size = malloc_cache;
+ TRACE(("%6d U %p %d\n",malloc_event++,pf->end,pf->end - pf->page));
+ brk(pf->end);
+ malloc_brk = pf->end;
+ /* Find the page directory entry for the page in question */
+ page = (u_long)pf->end >> malloc_pageshift;
+ index = page - malloc_origo;
+ /* Now update the directory */
+ for(i=index;i <= last_index;)
+ page_dir[i++] = MALLOC_NOT_MINE;
+ last_index = index - 1;
+ }
+}
+
+/*
+ * Free a chunk, and possibly the page it's on, if the page becomes empty.
+ */
+
+static void
+free_bytes(void *ptr, u_long page, int index, struct pginfo *info)
+{
+ int i;
+ struct pginfo **mp;
+ void *vp;
+
+ /* Make sure that pointer is multiplum of chunk-size */
+#ifdef SANITY
+ if ((u_long)ptr & (info->size - 1))
+ wrterror("freeing messed up chunk pointer\n");
+#endif
+
+ /* Find the chunk number on the page */
+ i = ((u_long)ptr & malloc_pagemask) >> info->shift;
+
+ /* See if it's free already */
+ if (tst_bit(info,i)) {
+#ifdef SANITY
+ wrtwarning("freeing free chunk at %p\n", ptr);
+#endif
+ return;
+ }
+
+ /* Mark it free */
+ set_bit(info,i);
+ info->free++;
+
+ /* If the page was full before, we need to put it on the queue now */
+ if (info->free == 1) {
+ mp = page_dir + info->shift;
+ while (*mp && (*mp)->next && (*mp)->next->page < info->page)
+ mp = &(*mp)->next;
+ info->next = *mp;
+ *mp = info;
+ return;
+ }
+
+ /* If this page isn't empty, don't do anything. */
+ if (info->free != info->total)
+ return;
+
+ /* We may want to keep at least one page of each size chunks around. */
+ mp = page_dir + info->shift;
+ if (0 && (*mp == info) && !info->next)
+ return;
+
+ /* Find & remove this page in the queue */
+ while (*mp != info) {
+ mp = &((*mp)->next);
+#ifdef EXTRA_SANITY
+ if (!*mp) {
+ TRACE(("%6d !q %p\n",malloc_event++,info));
+ wrterror("Not on queue\n");
+ }
+#endif
+ }
+ *mp = info->next;
+
+ /* Free the page & the info structure if need be */
+ set_pgdir(info->page,MALLOC_FIRST);
+ if((void*)info->page == (void*)info) {
+ _PR_UnlockedFree(info->page);
+ } else {
+ vp = info->page;
+ _PR_UnlockedFree(info);
+ _PR_UnlockedFree(vp);
+ }
+}
+
+void _PR_UnlockedFree(void *ptr)
+{
+ u_long page;
+ struct pginfo *info;
+ int index, tmp_index;
+
+ TRACE(("%6d F %p\n",malloc_event++,ptr));
+ /* This is legal */
+ if (!ptr)
+ return;
+
+#ifdef SANITY
+ /* There wouldn't be anything to free */
+ if (!initialized) {
+ wrtwarning("free() called before malloc() ever got called\n");
+ return;
+ }
+#endif
+
+#ifdef SANITY
+ if (suicide)
+ PR_Abort();
+#endif
+
+ /* Find the page directory entry for the page in question */
+ page = (u_long)ptr >> malloc_pageshift;
+ index = page - malloc_origo;
+
+ /*
+ * check if memory was allocated by memalign
+ */
+ tmp_index = index;
+ while (page_dir[tmp_index] == MALLOC_FOLLOW)
+ tmp_index--;
+ if (tmp_index != index) {
+ /*
+ * memalign-allocated memory
+ */
+ index = tmp_index;
+ page = index + malloc_origo;
+ ptr = (void *) (page << malloc_pageshift);
+ }
+ /* make sure it makes sense in some fashion */
+ if (index < malloc_pageshift) {
+#ifdef SANITY
+ wrtwarning("junk pointer %p (low) passed to free()\n", ptr);
+#endif
+ return;
+ }
+ if (index > last_index) {
+#ifdef SANITY
+ wrtwarning("junk pointer %p (high) passed to free()\n", ptr);
+#endif
+ return;
+ }
+
+ /* handle as page-allocation or chunk allocation */
+ info = page_dir[index];
+ if (info < MALLOC_MAGIC)
+ free_pages((char*)ptr, page, index, info);
+ else
+ free_bytes(ptr,page,index,info);
+ return;
+}
+#endif /* _PR_OVERRIDE_MALLOC */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmem.c b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmem.c
new file mode 100644
index 00000000..d29bc1fb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/malloc/prmem.c
@@ -0,0 +1,762 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Thread safe versions of malloc, free, realloc, calloc and cfree.
+*/
+
+#include "primpl.h"
+#ifdef VBOX_USE_IPRT_IN_NSPR
+# include <iprt/mem.h>
+#endif
+
+#ifdef _PR_ZONE_ALLOCATOR
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PR_FPrintZoneStats VBoxNsprPR_FPrintZoneStats
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*
+** The zone allocator code must use native mutexes and cannot
+** use PRLocks because PR_NewLock calls PR_Calloc, resulting
+** in cyclic dependency of initialization.
+*/
+
+#include <string.h>
+
+union memBlkHdrUn;
+
+typedef struct MemoryZoneStr {
+ union memBlkHdrUn *head; /* free list */
+ pthread_mutex_t lock;
+ size_t blockSize; /* size of blocks on this free list */
+ PRUint32 locked; /* current state of lock */
+ PRUint32 contention; /* counter: had to wait for lock */
+ PRUint32 hits; /* allocated from free list */
+ PRUint32 misses; /* had to call malloc */
+ PRUint32 elements; /* on free list */
+} MemoryZone;
+
+typedef union memBlkHdrUn {
+ unsigned char filler[48]; /* fix the size of this beast */
+ struct memBlkHdrStr {
+ union memBlkHdrUn *next;
+ MemoryZone *zone;
+ size_t blockSize;
+ size_t requestedSize;
+ PRUint32 magic;
+ } s;
+} MemBlockHdr;
+
+#define MEM_ZONES 7
+#define THREAD_POOLS 11 /* prime number for modulus */
+#define ZONE_MAGIC 0x0BADC0DE
+
+static MemoryZone zones[MEM_ZONES][THREAD_POOLS];
+
+static PRBool use_zone_allocator = PR_FALSE;
+
+static void pr_ZoneFree(void *ptr);
+
+void
+_PR_DestroyZones(void)
+{
+ int i, j;
+
+ if (!use_zone_allocator)
+ return;
+
+ for (j = 0; j < THREAD_POOLS; j++) {
+ for (i = 0; i < MEM_ZONES; i++) {
+ MemoryZone *mz = &zones[i][j];
+ pthread_mutex_destroy(&mz->lock);
+ while (mz->head) {
+ MemBlockHdr *hdr = mz->head;
+ mz->head = hdr->s.next; /* unlink it */
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(hdr);
+#else
+ free(hdr);
+#endif
+ mz->elements--;
+ }
+ }
+ }
+ use_zone_allocator = PR_FALSE;
+}
+
+/*
+** pr_FindSymbolInProg
+**
+** Find the specified data symbol in the program and return
+** its address.
+*/
+
+#ifdef USE_DLFCN
+
+#include <dlfcn.h>
+
+static void *
+pr_FindSymbolInProg(const char *name)
+{
+ void *h;
+ void *sym;
+
+ h = dlopen(0, RTLD_LAZY);
+ if (h == NULL)
+ return NULL;
+ sym = dlsym(h, name);
+ (void)dlclose(h);
+ return sym;
+}
+
+#elif defined(USE_HPSHL)
+
+#include <dl.h>
+
+static void *
+pr_FindSymbolInProg(const char *name)
+{
+ shl_t h = NULL;
+ void *sym;
+
+ if (shl_findsym(&h, name, TYPE_DATA, &sym) == -1)
+ return NULL;
+ return sym;
+}
+
+#elif defined(USE_MACH_DYLD)
+
+static void *
+pr_FindSymbolInProg(const char *name)
+{
+ /* FIXME: not implemented */
+ return NULL;
+}
+
+#else
+
+#error "The zone allocator is not supported on this platform"
+
+#endif
+
+void
+_PR_InitZones(void)
+{
+ int i, j;
+ char *envp;
+ PRBool *sym;
+
+ if ((sym = (PRBool *)pr_FindSymbolInProg("nspr_use_zone_allocator")) != NULL) {
+ use_zone_allocator = *sym;
+ } else if ((envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) != NULL) {
+ use_zone_allocator = (atoi(envp) == 1);
+ }
+
+ if (!use_zone_allocator)
+ return;
+
+ for (j = 0; j < THREAD_POOLS; j++) {
+ for (i = 0; i < MEM_ZONES; i++) {
+ MemoryZone *mz = &zones[i][j];
+ int rv = pthread_mutex_init(&mz->lock, NULL);
+ PR_ASSERT(0 == rv);
+ if (rv != 0) {
+ goto loser;
+ }
+ mz->blockSize = 16 << ( 2 * i);
+ }
+ }
+ return;
+
+loser:
+ _PR_DestroyZones();
+ return;
+}
+
+PR_IMPLEMENT(void)
+PR_FPrintZoneStats(PRFileDesc *debug_out)
+{
+ int i, j;
+
+ for (j = 0; j < THREAD_POOLS; j++) {
+ for (i = 0; i < MEM_ZONES; i++) {
+ MemoryZone *mz = &zones[i][j];
+ MemoryZone zone = *mz;
+ if (zone.elements || zone.misses || zone.hits) {
+ PR_fprintf(debug_out,
+"pool: %d, zone: %d, size: %d, free: %d, hit: %d, miss: %d, contend: %d\n",
+ j, i, zone.blockSize, zone.elements,
+ zone.hits, zone.misses, zone.contention);
+ }
+ }
+ }
+}
+
+static void *
+pr_ZoneMalloc(PRUint32 size)
+{
+ void *rv;
+ unsigned int zone;
+ size_t blockSize;
+ MemBlockHdr *mb, *mt;
+ MemoryZone *mz;
+
+ /* Always allocate a non-zero amount of bytes */
+ if (size < 1) {
+ size = 1;
+ }
+ for (zone = 0, blockSize = 16; zone < MEM_ZONES; ++zone, blockSize <<= 2) {
+ if (size <= blockSize) {
+ break;
+ }
+ }
+ if (zone < MEM_ZONES) {
+ pthread_t me = pthread_self();
+ unsigned int pool = (PRUptrdiff)me % THREAD_POOLS;
+ PRUint32 wasLocked;
+ mz = &zones[zone][pool];
+ wasLocked = mz->locked;
+ pthread_mutex_lock(&mz->lock);
+ mz->locked = 1;
+ if (wasLocked)
+ mz->contention++;
+ if (mz->head) {
+ mb = mz->head;
+ PR_ASSERT(mb->s.magic == ZONE_MAGIC);
+ PR_ASSERT(mb->s.zone == mz);
+ PR_ASSERT(mb->s.blockSize == blockSize);
+ PR_ASSERT(mz->blockSize == blockSize);
+
+ mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
+ PR_ASSERT(mt->s.magic == ZONE_MAGIC);
+ PR_ASSERT(mt->s.zone == mz);
+ PR_ASSERT(mt->s.blockSize == blockSize);
+
+ mz->hits++;
+ mz->elements--;
+ mz->head = mb->s.next; /* take off free list */
+ mz->locked = 0;
+ pthread_mutex_unlock(&mz->lock);
+
+ mt->s.next = mb->s.next = NULL;
+ mt->s.requestedSize = mb->s.requestedSize = size;
+
+ rv = (void *)(mb + 1);
+ return rv;
+ }
+
+ mz->misses++;
+ mz->locked = 0;
+ pthread_mutex_unlock(&mz->lock);
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ mb = (MemBlockHdr *)RTMemAlloc(blockSize + 2 * (sizeof *mb));
+#else
+ mb = (MemBlockHdr *)malloc(blockSize + 2 * (sizeof *mb));
+#endif
+ if (!mb) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ mb->s.next = NULL;
+ mb->s.zone = mz;
+ mb->s.magic = ZONE_MAGIC;
+ mb->s.blockSize = blockSize;
+ mb->s.requestedSize = size;
+
+ mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
+ memcpy(mt, mb, sizeof *mb);
+
+ rv = (void *)(mb + 1);
+ return rv;
+ }
+
+ /* size was too big. Create a block with no zone */
+ blockSize = (size & 15) ? size + 16 - (size & 15) : size;
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ mb = (MemBlockHdr *)RTMemAlloc(blockSize + 2 * (sizeof *mb));
+#else
+ mb = (MemBlockHdr *)malloc(blockSize + 2 * (sizeof *mb));
+#endif
+ if (!mb) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ mb->s.next = NULL;
+ mb->s.zone = NULL;
+ mb->s.magic = ZONE_MAGIC;
+ mb->s.blockSize = blockSize;
+ mb->s.requestedSize = size;
+
+ mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
+ memcpy(mt, mb, sizeof *mb);
+
+ rv = (void *)(mb + 1);
+ return rv;
+}
+
+
+static void *
+pr_ZoneCalloc(PRUint32 nelem, PRUint32 elsize)
+{
+ PRUint32 size = nelem * elsize;
+ void *p = pr_ZoneMalloc(size);
+ if (p) {
+ memset(p, 0, size);
+ }
+ return p;
+}
+
+static void *
+pr_ZoneRealloc(void *oldptr, PRUint32 bytes)
+{
+ void *rv;
+ MemBlockHdr *mb;
+ int ours;
+ MemBlockHdr phony;
+
+ if (!oldptr)
+ return pr_ZoneMalloc(bytes);
+ mb = (MemBlockHdr *)((char *)oldptr - (sizeof *mb));
+ PR_ASSERT(mb->s.magic == ZONE_MAGIC);
+ if (mb->s.magic != ZONE_MAGIC) {
+ /* Maybe this just came from ordinary malloc */
+#ifdef DEBUG
+ fprintf(stderr,
+ "Warning: reallocing memory block %p from ordinary malloc\n",
+ oldptr);
+#endif
+ /* We don't know how big it is. But we can fix that. */
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ oldptr = RTMemRealloc(oldptr, bytes);
+#else
+ oldptr = realloc(oldptr, bytes);
+#endif
+ if (!oldptr) {
+ if (bytes) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return oldptr;
+ }
+ }
+ phony.s.requestedSize = bytes;
+ mb = &phony;
+ ours = 0;
+ } else {
+ size_t blockSize = mb->s.blockSize;
+ MemBlockHdr *mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
+
+ PR_ASSERT(mt->s.magic == ZONE_MAGIC);
+ PR_ASSERT(mt->s.zone == mb->s.zone);
+ PR_ASSERT(mt->s.blockSize == blockSize);
+
+ if (bytes <= blockSize) {
+ /* The block is already big enough. */
+ mt->s.requestedSize = mb->s.requestedSize = bytes;
+ return oldptr;
+ }
+ ours = 1;
+ }
+
+ rv = pr_ZoneMalloc(bytes);
+ if (rv) {
+ if (oldptr && mb->s.requestedSize)
+ memcpy(rv, oldptr, mb->s.requestedSize);
+ if (ours)
+ pr_ZoneFree(oldptr);
+ else if (oldptr)
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(oldptr);
+#else
+ free(oldptr);
+#endif
+ }
+ return rv;
+}
+
+static void
+pr_ZoneFree(void *ptr)
+{
+ MemBlockHdr *mb, *mt;
+ MemoryZone *mz;
+ size_t blockSize;
+ PRUint32 wasLocked;
+
+ if (!ptr)
+ return;
+
+ mb = (MemBlockHdr *)((char *)ptr - (sizeof *mb));
+
+ if (mb->s.magic != ZONE_MAGIC) {
+ /* maybe this came from ordinary malloc */
+#ifdef DEBUG
+ fprintf(stderr,
+ "Warning: freeing memory block %p from ordinary malloc\n", ptr);
+#endif
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(ptr);
+#else
+ free(ptr);
+#endif
+ return;
+ }
+
+ blockSize = mb->s.blockSize;
+ mz = mb->s.zone;
+ mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize);
+ PR_ASSERT(mt->s.magic == ZONE_MAGIC);
+ PR_ASSERT(mt->s.zone == mz);
+ PR_ASSERT(mt->s.blockSize == blockSize);
+ if (!mz) {
+ PR_ASSERT(blockSize > 65536);
+ /* This block was not in any zone. Just free it. */
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(mb);
+#else
+ free(mb);
+#endif
+ return;
+ }
+ PR_ASSERT(mz->blockSize == blockSize);
+ wasLocked = mz->locked;
+ pthread_mutex_lock(&mz->lock);
+ mz->locked = 1;
+ if (wasLocked)
+ mz->contention++;
+ mt->s.next = mb->s.next = mz->head; /* put on head of list */
+ mz->head = mb;
+ mz->elements++;
+ mz->locked = 0;
+ pthread_mutex_unlock(&mz->lock);
+}
+
+PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ return use_zone_allocator ? pr_ZoneMalloc(size) : RTMemAlloc(RT_MAX(size, 1));
+#else
+ return use_zone_allocator ? pr_ZoneMalloc(size) : malloc(size);
+#endif
+}
+
+PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ return use_zone_allocator ?
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ pr_ZoneCalloc(nelem, elsize) : RTMemAllocZ(RT_MAX(nelem * (size_t)elsize, 1));
+#else
+ pr_ZoneCalloc(nelem, elsize) : calloc(nelem, elsize);
+#endif
+}
+
+PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ return use_zone_allocator ? pr_ZoneRealloc(ptr, size) : RTMemRealloc(ptr, size);
+#else
+ return use_zone_allocator ? pr_ZoneRealloc(ptr, size) : realloc(ptr, size);
+#endif
+}
+
+PR_IMPLEMENT(void) PR_Free(void *ptr)
+{
+ if (use_zone_allocator)
+ pr_ZoneFree(ptr);
+ else
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+#else /* !defined(_PR_ZONE_ALLOCATOR) */
+
+/*
+** The PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free functions simply
+** call their libc equivalents now. This may seem redundant, but it
+** ensures that we are calling into the same runtime library. On
+** Win32, it is possible to have multiple runtime libraries (e.g.,
+** objects compiled with /MD and /MDd) in the same process, and
+** they maintain separate heaps, which cannot be mixed.
+*/
+PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size)
+{
+#if defined (WIN16)
+ return PR_MD_malloc( (size_t) size);
+#else
+# ifdef VBOX_USE_IPRT_IN_NSPR
+ return RTMemAlloc(RT_MAX(size, 1));
+# else
+ return malloc(size);
+# endif
+#endif
+}
+
+PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize)
+{
+#if defined (WIN16)
+ return PR_MD_calloc( (size_t)nelem, (size_t)elsize );
+
+#else
+# ifdef VBOX_USE_IPRT_IN_NSPR
+ return RTMemAllocZ(RT_MAX(nelem * (size_t)elsize, 1));
+# else
+ return calloc(nelem, elsize);
+# endif
+#endif
+}
+
+PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size)
+{
+#if defined (WIN16)
+ return PR_MD_realloc( ptr, (size_t) size);
+#else
+# ifdef VBOX_USE_IPRT_IN_NSPR
+ return RTMemRealloc(ptr, size);
+# else
+ return realloc(ptr, size);
+# endif
+#endif
+}
+
+PR_IMPLEMENT(void) PR_Free(void *ptr)
+{
+#if defined (WIN16)
+ PR_MD_free( ptr );
+#else
+# ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMemFree(ptr);
+# else
+ free(ptr);
+# endif
+#endif
+}
+
+#endif /* _PR_ZONE_ALLOCATOR */
+
+/*
+** Complexity alert!
+**
+** If malloc/calloc/free (etc.) were implemented to use pr lock's then
+** the entry points could block when called if some other thread had the
+** lock.
+**
+** Most of the time this isn't a problem. However, in the case that we
+** are using the thread safe malloc code after PR_Init but before
+** PR_AttachThread has been called (on a native thread that nspr has yet
+** to be told about) we could get royally screwed if the lock was busy
+** and we tried to context switch the thread away. In this scenario
+** PR_CURRENT_THREAD() == NULL
+**
+** To avoid this unfortunate case, we use the low level locking
+** facilities for malloc protection instead of the slightly higher level
+** locking. This makes malloc somewhat faster so maybe it's a good thing
+** anyway.
+*/
+#ifdef _PR_OVERRIDE_MALLOC
+
+/* Imports */
+extern void *_PR_UnlockedMalloc(size_t size);
+extern void *_PR_UnlockedMemalign(size_t alignment, size_t size);
+extern void _PR_UnlockedFree(void *ptr);
+extern void *_PR_UnlockedRealloc(void *ptr, size_t size);
+extern void *_PR_UnlockedCalloc(size_t n, size_t elsize);
+
+static PRBool _PR_malloc_initialised = PR_FALSE;
+
+#ifdef _PR_PTHREADS
+static pthread_mutex_t _PR_MD_malloc_crustylock;
+
+#define _PR_Lock_Malloc() { \
+ if(PR_TRUE == _PR_malloc_initialised) { \
+ PRStatus rv; \
+ rv = pthread_mutex_lock(&_PR_MD_malloc_crustylock); \
+ PR_ASSERT(0 == rv); \
+ }
+
+#define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \
+ PRStatus rv; \
+ rv = pthread_mutex_unlock(&_PR_MD_malloc_crustylock); \
+ PR_ASSERT(0 == rv); \
+ } \
+ }
+#else /* _PR_PTHREADS */
+static _MDLock _PR_MD_malloc_crustylock;
+
+#ifdef IRIX
+#define _PR_Lock_Malloc() { \
+ PRIntn _is; \
+ if(PR_TRUE == _PR_malloc_initialised) { \
+ if (_PR_MD_GET_ATTACHED_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _PR_MD_GET_ATTACHED_THREAD())) \
+ _PR_INTSOFF(_is); \
+ _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \
+ }
+
+#define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \
+ _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \
+ if (_PR_MD_GET_ATTACHED_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _PR_MD_GET_ATTACHED_THREAD())) \
+ _PR_INTSON(_is); \
+ } \
+ }
+#else /* IRIX */
+#define _PR_Lock_Malloc() { \
+ PRIntn _is; \
+ if(PR_TRUE == _PR_malloc_initialised) { \
+ if (_PR_MD_CURRENT_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _PR_MD_CURRENT_THREAD())) \
+ _PR_INTSOFF(_is); \
+ _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \
+ }
+
+#define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \
+ _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \
+ if (_PR_MD_CURRENT_THREAD() && \
+ !_PR_IS_NATIVE_THREAD( \
+ _PR_MD_CURRENT_THREAD())) \
+ _PR_INTSON(_is); \
+ } \
+ }
+#endif /* IRIX */
+#endif /* _PR_PTHREADS */
+
+PR_IMPLEMENT(PRStatus) _PR_MallocInit(void)
+{
+ PRStatus rv = PR_SUCCESS;
+
+ if( PR_TRUE == _PR_malloc_initialised ) return PR_SUCCESS;
+
+#ifdef _PR_PTHREADS
+ {
+ int status;
+ pthread_mutexattr_t mattr;
+
+ status = _PT_PTHREAD_MUTEXATTR_INIT(&mattr);
+ PR_ASSERT(0 == status);
+ status = _PT_PTHREAD_MUTEX_INIT(_PR_MD_malloc_crustylock, mattr);
+ PR_ASSERT(0 == status);
+ status = _PT_PTHREAD_MUTEXATTR_DESTROY(&mattr);
+ PR_ASSERT(0 == status);
+ }
+#else /* _PR_PTHREADS */
+ _MD_NEW_LOCK(&_PR_MD_malloc_crustylock);
+#endif /* _PR_PTHREADS */
+
+ if( PR_SUCCESS == rv )
+ {
+ _PR_malloc_initialised = PR_TRUE;
+ }
+
+ return rv;
+}
+
+void *malloc(size_t size)
+{
+ void *p;
+ _PR_Lock_Malloc();
+ p = _PR_UnlockedMalloc(size);
+ _PR_Unlock_Malloc();
+ return p;
+}
+
+#if defined(IRIX)
+void *memalign(size_t alignment, size_t size)
+{
+ void *p;
+ _PR_Lock_Malloc();
+ p = _PR_UnlockedMemalign(alignment, size);
+ _PR_Unlock_Malloc();
+ return p;
+}
+
+void *valloc(size_t size)
+{
+ return(memalign(sysconf(_SC_PAGESIZE),size));
+}
+#endif /* IRIX */
+
+void free(void *ptr)
+{
+ _PR_Lock_Malloc();
+ _PR_UnlockedFree(ptr);
+ _PR_Unlock_Malloc();
+}
+
+void *realloc(void *ptr, size_t size)
+{
+ void *p;
+ _PR_Lock_Malloc();
+ p = _PR_UnlockedRealloc(ptr, size);
+ _PR_Unlock_Malloc();
+ return p;
+}
+
+void *calloc(size_t n, size_t elsize)
+{
+ void *p;
+ _PR_Lock_Malloc();
+ p = _PR_UnlockedCalloc(n, elsize);
+ _PR_Unlock_Malloc();
+ return p;
+}
+
+void cfree(void *p)
+{
+ _PR_Lock_Malloc();
+ _PR_UnlockedFree(p);
+ _PR_Unlock_Malloc();
+}
+
+void _PR_InitMem(void)
+{
+ PRStatus rv;
+ rv = _PR_MallocInit();
+ PR_ASSERT(PR_SUCCESS == rv);
+}
+
+#endif /* _PR_OVERRIDE_MALLOC */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/md/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/md/Makefile.in
new file mode 100644
index 00000000..2b8d4778
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/Makefile.in
@@ -0,0 +1,64 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = $(PR_MD_ARCH_DIR)
+
+CSRCS = \
+ prosdep.c \
+ $(NULL)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/Makefile.in
new file mode 100644
index 00000000..fca5cf2c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+include $(srcdir)/bsrcs.mk
+CSRCS += $(MDCSRCS)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bcpu.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bcpu.c
new file mode 100644
index 00000000..548df8c2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bcpu.c
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+PR_EXTERN(void) _PR_MD_INIT_CPUS();
+PR_EXTERN(void) _PR_MD_WAKEUP_CPUS();
+PR_EXTERN(void) _PR_MD_START_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_STOP_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_CLOCK_INTERRUPT(void);
+PR_EXTERN(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone);
+PR_EXTERN(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts);
+PR_EXTERN(PRInt32) _PR_MD_GET_INTSOFF(void);
+PR_EXTERN(void) _PR_MD_SET_INTSOFF(PRInt32 _val);
+PR_EXTERN(_PRCPU*) _PR_MD_CURRENT_CPU(void);
+PR_EXTERN(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu);
+PR_EXTERN(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);
+PR_EXTERN(PRInt32) _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos.c
new file mode 100644
index 00000000..dba9ae24
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos.c
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+/*
+ * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
+ * PRInt32* pointer to a _PRSockLen_t* pointer.
+ */
+#define _PRSockLen_t int
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+static PRMonitor *_pr_Xfe_mon = NULL;
+
+/*
+ * Variables used by the GC code, initialized in _MD_InitSegs().
+ * _pr_zero_fd should be a static variable. Unfortunately, there is
+ * still some Unix-specific code left in function PR_GrowSegment()
+ * in file memory/prseg.c that references it, so it needs
+ * to be a global variable for now.
+ */
+PRInt32 _pr_zero_fd = -1;
+static PRLock *_pr_md_lock = NULL;
+
+sigset_t timer_set;
+
+void _PR_UnixInit()
+{
+ struct sigaction sigact;
+ int rv;
+
+ sigemptyset(&timer_set);
+
+ sigact.sa_handler = SIG_IGN;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ rv = sigaction(SIGPIPE, &sigact, 0);
+ PR_ASSERT(0 == rv);
+
+ _pr_rename_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_rename_lock);
+ _pr_Xfe_mon = PR_NewMonitor();
+ PR_ASSERT(NULL != _pr_Xfe_mon);
+}
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the Unix
+ * implementation.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTime)
+PR_Now(void)
+{
+ struct timeval tv;
+ PRInt64 s, us, s2us;
+
+ GETTIMEOFDAY(&tv);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, tv.tv_sec);
+ LL_I2L(us, tv.tv_usec);
+ LL_MUL(s, s, s2us);
+ LL_ADD(s, s, us);
+ return s;
+}
+
+PRIntervalTime
+_PR_UNIX_GetInterval()
+{
+ struct timeval time;
+ PRIntervalTime ticks;
+
+ (void)GETTIMEOFDAY(&time); /* fallicy of course */
+ ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
+ ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
+ return ticks;
+} /* _PR_SUNOS_GetInterval */
+
+PRIntervalTime _PR_UNIX_TicksPerSecond()
+{
+ return 1000; /* this needs some work :) */
+}
+
+/************************************************************************/
+
+/*
+** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
+** safe. Unfortunately, neither is mozilla. To make these programs work
+** in a pre-emptive threaded environment, we need to use a lock.
+*/
+
+void PR_XLock()
+{
+ PR_EnterMonitor(_pr_Xfe_mon);
+}
+
+void PR_XUnlock()
+{
+ PR_ExitMonitor(_pr_Xfe_mon);
+}
+
+PRBool PR_XIsLocked()
+{
+ return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
+}
+
+void PR_XWait(int ms)
+{
+ PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
+}
+
+void PR_XNotify(void)
+{
+ PR_Notify(_pr_Xfe_mon);
+}
+
+void PR_XNotifyAll(void)
+{
+ PR_NotifyAll(_pr_Xfe_mon);
+}
+
+#if !defined(BEOS)
+#ifdef HAVE_BSD_FLOCK
+
+#include <sys/file.h>
+
+PR_IMPLEMENT(PRStatus)
+_MD_LOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX|LOCK_NB);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UNLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_UN);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+#else
+
+PR_IMPLEMENT(PRStatus)
+_MD_LOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_LOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_TLOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UNLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_ULOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+#endif
+
+PR_IMPLEMENT(PRStatus)
+ _MD_GETHOSTNAME (char *name, PRUint32 namelen)
+{
+ PRIntn rv;
+
+ rv = gethostname(name, namelen);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ }
+ _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos_errors.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos_errors.c
new file mode 100644
index 00000000..4882594b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/beos_errors.c
@@ -0,0 +1,1525 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prtypes.h"
+#include "md/_unix_errors.h"
+#include "prerror.h"
+#include <errno.h>
+
+void _MD_unix_map_opendir_error(int err)
+{
+ switch (err) {
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_closedir_error(int err)
+{
+ switch (err) {
+ case EINVAL:
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_readdir_error(int err)
+{
+
+ switch (err) {
+ case ENOENT:
+ PR_SetError(PR_NO_MORE_FILES_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#ifdef IRIX
+#ifdef IRIX5_3
+#else
+ case EDIRCORRUPTED:
+ PR_SetError(PR_DIRECTORY_CORRUPTED_ERROR, err);
+ break;
+#endif
+#endif
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ case EINVAL:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#ifdef EBADMSG
+ case EBADMSG:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ case EDEADLK:
+ PR_SetError(PR_DEADLOCK_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOLCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ case ENXIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_unlink_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EPERM:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_stat_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_fstat_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ETIMEDOUT:
+#ifdef ENOLINK
+ case ENOLINK:
+#endif
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_rename_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err);
+ break;
+#ifdef EDQUOT
+ case EDQUOT:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#endif
+ case EEXIST:
+ PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EISDIR:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ case EXDEV:
+ PR_SetError(PR_NOT_SAME_DEVICE_ERROR, err);
+ break;
+ case EMLINK:
+ PR_SetError(PR_MAX_DIRECTORY_ENTRIES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_access_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_mkdir_error(int err)
+{
+ switch (err) {
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EEXIST:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case EMLINK:
+ PR_SetError(PR_MAX_DIRECTORY_ENTRIES_ERROR, err);
+ break;
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#ifdef EDQUOT
+ case EDQUOT:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#endif
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_rmdir_error(int err)
+{
+
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err);
+ break;
+ case EEXIST:
+ PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_read_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#ifdef EBADMSG
+ case EBADMSG:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ case EDEADLK:
+ PR_SetError(PR_DEADLOCK_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOLCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ENXIO:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EISDIR:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_write_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EDEADLK:
+ PR_SetError(PR_DEADLOCK_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EFBIG:
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOLCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ENXIO:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case ERANGE:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+#ifdef EDQUOT
+ case EDQUOT:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#endif
+#ifdef ENOLINK
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_lseek_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ESPIPE:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_fsync_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+#endif
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_close_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+#endif
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_socket_error(int err)
+{
+ switch (err) {
+ case EPROTONOSUPPORT:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+#endif /* !defined(SCO) */
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_socketavailable_error(int err)
+{
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+}
+
+void _MD_unix_map_recv_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_recvfrom_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ECONNRESET:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_send_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EMSGSIZE:
+#endif
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif /* !defined(SCO) */
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_sendto_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EMSGSIZE:
+#endif
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif /* !defined(SCO) */
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_writev_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_accept_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EOPNOTSUPP:
+#endif
+ case ENODEV:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+#ifdef EPROTO
+ case EPROTO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_connect_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EINPROGRESS:
+ PR_SetError(PR_IN_PROGRESS_ERROR, err);
+ break;
+ case EALREADY:
+ PR_SetError(PR_ALREADY_INITIATED_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case ENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ /*
+ * UNIX domain sockets are not supported in NSPR
+ */
+ case EACCES:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+#if defined(UNIXWARE) || defined(SNI) || defined(NEC)
+ /*
+ * On some platforms, if we connect to a port on
+ * the local host (the loopback address) that no
+ * process is listening on, we get EIO instead
+ * of ECONNREFUSED.
+ */
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+#else
+ PR_SetError(PR_IO_ERROR, err);
+#endif
+ break;
+ case ELOOP:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ENXIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EPROTOTYPE:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_bind_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_SOCKET_ADDRESS_IS_BOUND_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ /*
+ * UNIX domain sockets are not supported in NSPR
+ */
+ case EIO:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EROFS:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_listen_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EOPNOTSUPP:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_shutdown_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_socketpair_error(int err)
+{
+ switch (err) {
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EAFNOSUPPORT:
+ case EPROTONOSUPPORT:
+#if !defined(BEOS)
+ case EOPNOTSUPP:
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_getsockname_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+#endif /* !defined(SCO) */
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_getpeername_error(int err)
+{
+
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+#endif /* !defined(SCO) */
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_getsockopt_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOPROTOOPT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_setsockopt_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOPROTOOPT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_open_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EAGAIN:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EEXIST:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EISDIR:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENODEV:
+ case ENOENT:
+ case ENXIO:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EPERM:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_mmap_error(int err)
+{
+
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EAGAIN:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_gethostname_error(int err)
+{
+ switch (err) {
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_select_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_poll_error(int err)
+{
+ PRErrorCode prerror;
+ switch (err) {
+ case EAGAIN:
+ prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EINVAL:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case EFAULT:
+ prerror = PR_ACCESS_FAULT_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, err);
+}
+
+void _MD_unix_map_flock_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ case EINVAL:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EWOULDBLOCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_lockf_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case EDEADLK:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+#ifdef HPUX11
+void _MD_hpux_map_sendfile_error(int oserror)
+{
+ PRErrorCode prerror;
+
+ switch (oserror) {
+ case ENOTSOCK:
+ prerror = PR_NOT_SOCKET_ERROR;
+ break;
+ case EFAULT:
+ prerror = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ENOBUFS:
+ prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EINVAL:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ENOTCONN:
+ prerror = PR_NOT_CONNECTED_ERROR;
+ break;
+ case EPIPE:
+ prerror = PR_CONNECT_RESET_ERROR;
+ break;
+ case ENOMEM:
+ prerror = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case EOPNOTSUPP:
+ prerror = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ }
+ PR_SetError(prerror, oserror);
+}
+#endif /* HPUX11 */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bfile.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bfile.c
new file mode 100644
index 00000000..95206f30
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bfile.c
@@ -0,0 +1,892 @@
+/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-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.
+ */
+
+#include "primpl.h"
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+
+void
+_MD_InitIO (void)
+{
+}
+
+PRStatus
+_MD_open_dir (_MDDir *md,const char *name)
+{
+int err;
+
+ md->d = opendir(name);
+ if (!md->d) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPENDIR_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+char*
+_MD_read_dir (_MDDir *md, PRIntn flags)
+{
+struct dirent *de;
+int err;
+
+ for (;;) {
+ /*
+ * XXX: readdir() is not MT-safe
+ */
+ de = readdir(md->d);
+
+ if (!de) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return 0;
+ }
+
+ if ((flags & PR_SKIP_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == 0))
+ continue;
+
+ if ((flags & PR_SKIP_DOT_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
+ (de->d_name[2] == 0))
+ continue;
+
+ if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
+ continue;
+
+ break;
+ }
+ return de->d_name;
+}
+
+
+PRInt32
+_MD_close_dir (_MDDir *md)
+{
+int rv = 0, err;
+
+ if (md->d) {
+ rv = closedir(md->d);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSEDIR_ERROR(err);
+ }
+ }
+ return(rv);
+}
+
+void
+_MD_make_nonblock (PRFileDesc *fd)
+{
+ int blocking = 1;
+ setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
+
+}
+
+PRStatus
+_MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable)
+{
+ int rv;
+
+ rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
+ if (-1 == rv) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+void
+_MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported)
+{
+ if (imported) {
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ } else {
+ int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ if (flags == -1) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return;
+ }
+ fd->secret->inheritable = (flags & FD_CLOEXEC) ?
+ _PR_TRI_TRUE : _PR_TRI_FALSE;
+ }
+}
+
+void
+_MD_query_fd_inheritable (PRFileDesc *fd)
+{
+ int flags;
+
+ PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
+ flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ PR_ASSERT(-1 != flags);
+ fd->secret->inheritable = (flags & FD_CLOEXEC) ?
+ _PR_TRI_FALSE : _PR_TRI_TRUE;
+}
+
+PRInt32
+_MD_open (const char *name, PRIntn flags, PRIntn mode)
+{
+ PRInt32 osflags;
+ PRInt32 rv, err;
+
+ if (flags & PR_RDWR) {
+ osflags = O_RDWR;
+ } else if (flags & PR_WRONLY) {
+ osflags = O_WRONLY;
+ } else {
+ osflags = O_RDONLY;
+ }
+
+ if (flags & PR_APPEND)
+ osflags |= O_APPEND;
+ if (flags & PR_TRUNCATE)
+ osflags |= O_TRUNC;
+ if (flags & PR_SYNC) {
+/* Ummmm. BeOS doesn't appear to
+ support sync in any way shape or
+ form. */
+ return PR_NOT_IMPLEMENTED_ERROR;
+ }
+
+ /*
+ ** On creations we hold the 'create' lock in order to enforce
+ ** the semantics of PR_Rename. (see the latter for more details)
+ */
+ if (flags & PR_CREATE_FILE)
+ {
+ osflags |= O_CREAT ;
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ }
+
+ rv = open(name, osflags, mode);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPEN_ERROR(err);
+ }
+
+ if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32
+_MD_close_file (PRInt32 osfd)
+{
+PRInt32 rv, err;
+
+ rv = close(osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ PRInt32 rv, err;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ rv = read( osfd, buf, amount );
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_READ_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ PRInt32 rv, err;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ rv = write( osfd, buf, amount );
+
+ if( rv < 0 ) {
+
+ err = _MD_ERRNO();
+ _PR_MD_MAP_WRITE_ERROR(err);
+ }
+ return( rv );
+}
+
+#ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */
+PRInt32
+_MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+#endif
+
+PRInt32
+_MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
+{
+PRInt32 rv, err;
+
+ rv = lseek (fd->secret->md.osfd, offset, whence);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(err);
+ }
+ return( rv );
+}
+
+PRInt64
+_MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
+{
+PRInt32 rv, err;
+
+/* According to the BeOS headers, lseek accepts a
+ * variable of type off_t for the offset, and off_t
+ * is defined to be a 64-bit value. So no special
+ * cracking needs to be done on "offset".
+ */
+
+ rv = lseek (fd->secret->md.osfd, offset, whence);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(err);
+ }
+ return( rv );
+}
+
+PRInt32
+_MD_fsync (PRFileDesc *fd)
+{
+PRInt32 rv, err;
+
+ rv = fsync(fd->secret->md.osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSYNC_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_delete (const char *name)
+{
+PRInt32 rv, err;
+
+ rv = unlink(name);
+ if (rv == -1)
+ {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_UNLINK_ERROR(err);
+ }
+ return (rv);
+}
+
+PRInt32
+_MD_getfileinfo (const char *fn, PRFileInfo *info)
+{
+struct stat sb;
+PRInt32 rv, err;
+PRInt64 s, s2us;
+
+ rv = stat(fn, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_STAT_ERROR(err);
+ } else if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+ /* Must truncate file size for the 32 bit
+ version */
+ info->size = (sb.st_size & 0xffffffff);
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ return rv;
+}
+
+PRInt32
+_MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
+{
+struct stat sb;
+PRInt32 rv, err;
+PRInt64 s, s2us;
+
+ rv = stat(fn, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_STAT_ERROR(err);
+ } else if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+ /* For the 64 bit version we can use
+ * the native st_size without modification
+ */
+ info->size = sb.st_size;
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ return rv;
+}
+
+PRInt32
+_MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
+{
+ struct stat sb;
+ PRInt64 s, s2us;
+ PRInt32 rv, err;
+
+ rv = fstat(fd->secret->md.osfd, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSTAT_ERROR(err);
+ } else if (info) {
+ if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE ;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ /* Use lower 32 bits of file size */
+ info->size = ( sb.st_size & 0xffffffff);
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ struct stat sb;
+ PRInt64 s, s2us;
+ PRInt32 rv, err;
+
+ rv = fstat(fd->secret->md.osfd, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSTAT_ERROR(err);
+ } else if (info) {
+ if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE ;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ info->size = sb.st_size;
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_MD_rename (const char *from, const char *to)
+{
+ PRInt32 rv = -1, err;
+
+ /*
+ ** This is trying to enforce the semantics of WINDOZE' rename
+ ** operation. That means one is not allowed to rename over top
+ ** of an existing file. Holding a lock across these two function
+ ** and the open function is known to be a bad idea, but ....
+ */
+ if (NULL != _pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ if (0 == access(to, F_OK))
+ PR_SetError(PR_FILE_EXISTS_ERROR, 0);
+ else
+ {
+ rv = rename(from, to);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RENAME_ERROR(err);
+ }
+ }
+ if (NULL != _pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32
+_MD_access (const char *name, PRIntn how)
+{
+PRInt32 rv, err;
+int amode;
+
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ amode = W_OK;
+ break;
+ case PR_ACCESS_READ_OK:
+ amode = R_OK;
+ break;
+ case PR_ACCESS_EXISTS:
+ amode = F_OK;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ rv = access(name, amode);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_ACCESS_ERROR(err);
+ }
+
+done:
+ return(rv);
+}
+
+PRInt32
+_MD_stat (const char *name, struct stat *buf)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_mkdir (const char *name, PRIntn mode)
+{
+ status_t rv;
+ int err;
+
+ /*
+ ** This lock is used to enforce rename semantics as described
+ ** in PR_Rename. Look there for more fun details.
+ */
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+
+ rv = mkdir(name, mode);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_MKDIR_ERROR(err);
+ }
+ if (NULL !=_pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32
+_MD_rmdir (const char *name)
+{
+int rv, err;
+
+ rv = rmdir(name);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RMDIR_ERROR(err);
+ }
+ return rv;
+}
+
+PRInt32
+_MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRInt32 rv = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ /*
+ * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
+ */
+ fd_set rd, wt, ex;
+ PRFileDesc *bottom;
+ PRPollDesc *pd, *epd;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
+
+ struct timeval tv, *tvp = NULL;
+
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ if (0 == npds) {
+ PR_Sleep(timeout);
+ return rv;
+ }
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd) maxfd = osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ pd->out_flags = 0;
+ }
+ }
+
+ if (0 != ready) return ready; /* no need to block */
+
+ remaining = timeout;
+ start = PR_IntervalNow();
+
+ retry:
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = remaining / ticksPerSecond;
+ tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
+ tvp = &tv;
+ }
+
+ ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
+
+ if (ready == -1 && errno == EINTR)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ goto retry;
+ }
+ }
+ }
+
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ PRInt32 osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = bottom->secret->md.osfd;
+
+ if (FD_ISSET(osfd, &rd))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &wt))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
+
+/* Workaround for nonblocking connects under net_server */
+#ifndef BONE_VERSION
+ if (out_flags)
+ {
+ /* check if it is a pending connect */
+ int i = 0, j = 0;
+ PR_Lock( _connectLock );
+ for( i = 0; i < connectCount; i++ )
+ {
+ if(connectList[i].osfd == osfd)
+ {
+ int connectError;
+ int connectResult;
+
+ connectResult = connect(connectList[i].osfd,
+ &connectList[i].addr,
+ connectList[i].addrlen);
+ connectError = errno;
+
+ if(connectResult < 0 )
+ {
+ if(connectError == EINTR || connectError == EWOULDBLOCK ||
+ connectError == EINPROGRESS || connectError == EALREADY)
+ {
+ break;
+ }
+ }
+
+ if(i == (connectCount - 1))
+ {
+ connectList[i].osfd = -1;
+ } else {
+ for(j = i; j < connectCount; j++ )
+ {
+ memcpy( &connectList[j], &connectList[j+1],
+ sizeof(connectList[j]));
+ }
+ }
+ connectCount--;
+
+ bottom->secret->md.connectReturnValue = connectResult;
+ bottom->secret->md.connectReturnError = connectError;
+ bottom->secret->md.connectValueValid = PR_TRUE;
+ break;
+ }
+ }
+ PR_Unlock( _connectLock );
+ }
+#endif
+ }
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready < 0)
+ {
+ err = _MD_ERRNO();
+ if (err == EBADF)
+ {
+ /* Find the bad fds */
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+ return ready;
+} /* _MD_pr_poll */
+
+/*
+ * File locking.
+ */
+
+PRStatus
+_MD_lockfile (PRInt32 osfd)
+{
+ PRInt32 rv;
+ struct flock linfo;
+
+ linfo.l_type =
+ linfo.l_whence = SEEK_SET;
+ linfo.l_start = 0;
+ linfo.l_len = 0;
+
+ rv = fcntl(osfd, F_SETLKW, &linfo);
+ if (rv == 0)
+ return PR_SUCCESS;
+
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PRStatus
+_MD_tlockfile (PRInt32 osfd)
+{
+ PRInt32 rv;
+ struct flock linfo;
+
+ linfo.l_type =
+ linfo.l_whence = SEEK_SET;
+ linfo.l_start = 0;
+ linfo.l_len = 0;
+
+ rv = fcntl(osfd, F_SETLK, &linfo);
+ if (rv == 0)
+ return PR_SUCCESS;
+
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PRStatus
+_MD_unlockfile (PRInt32 osfd)
+{
+ PRInt32 rv;
+ struct flock linfo;
+
+ linfo.l_type =
+ linfo.l_whence = SEEK_SET;
+ linfo.l_start = 0;
+ linfo.l_len = 0;
+
+ rv = fcntl(osfd, F_UNLCK, &linfo);
+
+ if (rv == 0)
+ return PR_SUCCESS;
+
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmemory.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmemory.c
new file mode 100644
index 00000000..17c73325
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmemory.c
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+PR_EXTERN(void) _PR_MD_INIT_SEGS(void);
+PR_EXTERN(PRStatus) _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);
+PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSegment *seg);
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmisc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmisc.c
new file mode 100644
index 00000000..429cd7be
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmisc.c
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <stdlib.h>
+
+PRLock *_connectLock = NULL;
+
+#ifndef BONE_VERSION
+/* Workaround for nonblocking connects under net_server */
+PRUint32 connectCount = 0;
+ConnectListNode connectList[64];
+#endif
+
+void
+_MD_cleanup_before_exit (void)
+{
+}
+
+void
+_MD_exit (PRIntn status)
+{
+ exit(status);
+}
+
+void
+_MD_early_init (void)
+{
+}
+
+static PRLock *monitor = NULL;
+
+void
+_MD_final_init (void)
+{
+ _connectLock = PR_NewLock();
+ PR_ASSERT(NULL != _connectLock);
+#ifndef BONE_VERSION
+ /* Workaround for nonblocking connects under net_server */
+ connectCount = 0;
+#endif
+}
+
+void
+_MD_AtomicInit (void)
+{
+ if (monitor == NULL) {
+ monitor = PR_NewLock();
+ }
+}
+
+/*
+** This is exceedingly messy. atomic_add returns the last value, NSPR expects the new value.
+** We just add or subtract 1 from the result. The actual memory update is atomic.
+*/
+
+PRInt32
+_MD_AtomicAdd( PRInt32 *ptr, PRInt32 val )
+{
+ return( ( atomic_add( (long *)ptr, val ) ) + val );
+}
+
+PRInt32
+_MD_AtomicIncrement( PRInt32 *val )
+{
+ return( ( atomic_add( (long *)val, 1 ) ) + 1 );
+}
+
+PRInt32
+_MD_AtomicDecrement( PRInt32 *val )
+{
+ return( ( atomic_add( (long *)val, -1 ) ) - 1 );
+}
+
+PRInt32
+_MD_AtomicSet( PRInt32 *val, PRInt32 newval )
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(monitor);
+ rv = *val;
+ *val = newval;
+ PR_Unlock(monitor);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmmap.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmmap.c
new file mode 100644
index 00000000..9edd0673
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bmmap.c
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+PR_EXTERN(PRStatus)
+_PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return PR_FAILURE;
+}
+
+PR_EXTERN(PRInt32)
+_PR_MD_GET_MEM_MAP_ALIGNMENT(void)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return -1;
+}
+
+PR_EXTERN(void *)
+_PR_MD_MEM_MAP(PRFileMap *fmap, PRInt64 offset, PRUint32 len)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return 0;
+}
+
+PR_EXTERN(PRStatus)
+_PR_MD_MEM_UNMAP(void *addr, PRUint32 size)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return PR_FAILURE;
+}
+
+PR_EXTERN(PRStatus)
+_PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return PR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bnet.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bnet.c
new file mode 100644
index 00000000..9b10509e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bnet.c
@@ -0,0 +1,929 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+/*
+ * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
+ * PRInt32* pointer to a _PRSockLen_t* pointer.
+ */
+#define _PRSockLen_t int
+
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+static PRMonitor *_pr_Xfe_mon = NULL;
+
+#define READ_FD 1
+#define WRITE_FD 2
+
+/*
+** This is a support routine to handle "deferred" i/o on sockets.
+** It uses "select", so it is subject to all of the BeOS limitations
+** (only READ notification, only sockets)
+*/
+
+/*
+ * socket_io_wait --
+ *
+ * wait for socket i/o, periodically checking for interrupt
+ *
+ */
+
+static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+ struct timeval tv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRInt32 syserror;
+ fd_set rd_wr;
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+#ifdef BONE_VERSION
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+#else
+ if (syserror == EBADF) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, syserror);
+ }
+#endif
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ FD_ZERO(&rd_wr);
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+ wait_for_remaining = PR_TRUE;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+#ifdef BONE_VERSION
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+#else
+ if (syserror == EBADF) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, syserror);
+ }
+#endif
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+ /*
+ * If _MD_SELECT timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ }
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+#ifndef BONE_VERSION
+ if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
+ _PR_MD_MAP_RECV_ERROR(EPIPE);
+ return -1;
+ }
+#endif
+
+#ifdef BONE_VERSION
+ /*
+ ** Gah, stupid hack. If reading a zero amount, instantly return success.
+ ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of
+ ** mozilla use to check for socket availability.
+ */
+
+ if( 0 == amount ) return(0);
+#endif
+
+ while ((rv = recv(osfd, buf, amount, flags)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ /* If socket was supposed to be blocking,
+ wait a while for the condition to be
+ satisfied. */
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+
+ } else
+ break;
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+
+done:
+ return(rv);
+}
+
+PRInt32
+_MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1)) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv != -1) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+PRInt32
+_MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+#ifndef BONE_VERSION
+ if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
+ {
+ _PR_MD_MAP_SEND_ERROR(EPIPE);
+ return -1;
+ }
+#endif
+
+ while ((rv = send(osfd, buf, amount, flags)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+
+#ifndef BONE_VERSION
+ if( _PR_PENDING_INTERRUPT(me)) {
+
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ /* in UNIX implementations, you could do a socket_io_wait here.
+ * but since BeOS doesn't yet support WRITE notification in select,
+ * you're spanked.
+ */
+ snooze( 10000L );
+ continue;
+#else /* BONE_VERSION */
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+#endif
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+#ifdef BONE_VERSION
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next writev() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+#endif /* BONE_VERSION */
+
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+
+#ifdef BONE_VERSION
+done:
+#endif
+ return(rv);
+}
+
+PRInt32
+_MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) &addrCopy, addrlen)) == -1) {
+#else
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1) {
+#endif
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+
+#ifdef BONE_VERSION
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+#endif
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+
+#ifdef BONE_VERSION
+done:
+#endif
+ return(rv);
+}
+
+#ifdef BONE_VERSION
+
+PRInt32 _MD_writev(
+ PRFileDesc *fd, const PRIOVec *iov,
+ PRInt32 iov_size, PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ /*
+ * Calculate the total number of bytes to be sent; needed for
+ * optimization later.
+ * We could avoid this if this number was passed in; but it is
+ * probably not a big deal because iov_size is usually small (less than
+ * 3)
+ */
+ if (!fd->secret->nonblocking) {
+ for (index=0; index<iov_size; index++) {
+ amount += iov[index].iov_len;
+ }
+ }
+
+ while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next writev() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+
+
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+#endif /* BONE_VERSION */
+
+PRInt32
+_MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = accept(osfd, (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ /* If it's SUPPOSED to be a blocking thread, wait
+ * a while to see if the triggering condition gets
+ * satisfied.
+ */
+ /* Assume that we're always using a native thread */
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ } else if (addr != NULL) {
+ /* bug 134099 */
+ err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+ }
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv != -1) {
+ /* Mask off the first byte of struct sockaddr (the length field) */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+PRInt32
+_MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+
+#ifndef BONE_VERSION
+ fd->secret->md.connectValueValid = PR_FALSE;
+#endif
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+#endif
+
+ /* (Copied from unix.c)
+ * We initiate the connection setup by making a nonblocking connect()
+ * call. If the connect() call fails, there are two cases we handle
+ * specially:
+ * 1. The connect() call was interrupted by a signal. In this case
+ * we simply retry connect().
+ * 2. The NSPR socket is nonblocking and connect() fails with
+ * EINPROGRESS. We first wait until the socket becomes writable.
+ * Then we try to find out whether the connection setup succeeded
+ * or failed.
+ */
+
+retry:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
+#else
+ if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
+#endif
+ err = _MD_ERRNO();
+#ifndef BONE_VERSION
+ fd->secret->md.connectReturnValue = rv;
+ fd->secret->md.connectReturnError = err;
+ fd->secret->md.connectValueValid = PR_TRUE;
+#endif
+ if( err == EINTR ) {
+
+ if( _PR_PENDING_INTERRUPT(me)) {
+
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+#ifndef BONE_VERSION
+ snooze( 100000L );
+#endif
+ goto retry;
+ }
+
+#ifndef BONE_VERSION
+ if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
+
+ /*
+ ** There's no timeout on this connect, but that's not
+ ** a big deal, since the connect times out anyways
+ ** after 30 seconds. Just sleep for 1/10th of a second
+ ** and retry until we go through or die.
+ */
+
+ if( _PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ goto retry;
+ }
+
+ if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
+ PR_Lock(_connectLock);
+ if (connectCount < sizeof(connectList)/sizeof(connectList[0])) {
+ connectList[connectCount].osfd = osfd;
+ memcpy(&connectList[connectCount].addr, addr, addrlen);
+ connectList[connectCount].addrlen = addrlen;
+ connectList[connectCount].timeout = timeout;
+ connectCount++;
+ PR_Unlock(_connectLock);
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ } else {
+ PR_Unlock(_connectLock);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+ return rv;
+ }
+#else /* BONE_VERSION */
+ if(!fd->secret->nonblocking && (err == EINTR)) {
+
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv == -1) {
+ return -1;
+ }
+
+ PR_ASSERT(rv == 1);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ err = _MD_beos_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ }
+ return 0;
+ }
+#endif
+
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+
+ return rv;
+}
+
+PRInt32
+_MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv, err;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
+#else
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+#endif
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+
+ return(rv);
+}
+
+PRInt32
+_MD_listen (PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv, err;
+
+#ifndef BONE_VERSION
+ /* Bug workaround! Setting listen to 0 on Be accepts no connections.
+ ** On most UN*Xes this sets the default.
+ */
+
+ if( backlog == 0 ) backlog = 5;
+#endif
+
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LISTEN_ERROR(err);
+ }
+
+ return(rv);
+}
+
+PRInt32
+_MD_shutdown (PRFileDesc *fd, PRIntn how)
+{
+ PRInt32 rv, err;
+
+#ifndef BONE_VERSION
+ if (how == PR_SHUTDOWN_SEND)
+ fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
+ else if (how == PR_SHUTDOWN_RCV)
+ fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
+ else if (how == PR_SHUTDOWN_BOTH) {
+ fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
+ }
+
+ return 0;
+#else /* BONE_VERSION */
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SHUTDOWN_ERROR(err);
+ }
+ return(rv);
+#endif
+}
+
+PRInt32
+_MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_close_socket (PRInt32 osfd)
+{
+#ifdef BONE_VERSION
+ close( osfd );
+#else
+ closesocket( osfd );
+#endif
+}
+
+PRStatus
+_MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockname(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv == 0) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKNAME_ERROR(err);
+ }
+
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getpeername(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv == 0) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETPEERNAME_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_MD_getsockopt (PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockopt(fd->secret->md.osfd, level, optname,
+ optval, (_PRSockLen_t *)optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
+ }
+
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_MD_setsockopt (PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv, err;
+
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRInt32
+_MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+#ifndef BONE_VERSION
+PRInt32
+_MD_socket (int af, int type, int flags)
+{
+ PRInt32 osfd, err;
+
+ osfd = socket( af, type, 0 );
+
+ if( -1 == osfd ) {
+
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR( err );
+ }
+
+ return( osfd );
+}
+#else
+PRInt32
+_MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
+{
+ PRInt32 osfd, err;
+
+ osfd = socket(domain, type, proto);
+
+ if (osfd == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ }
+
+ return(osfd);
+}
+#endif
+
+PRInt32
+_MD_socketavailable (PRFileDesc *fd)
+{
+#ifdef BONE_VERSION
+ PRInt32 result;
+
+ if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
+ return -1;
+ }
+ return result;
+#else
+ return PR_NOT_IMPLEMENTED_ERROR;
+#endif
+}
+
+PRInt32
+_MD_get_socket_error (void)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRStatus
+_MD_gethostname (char *name, PRUint32 namelen)
+{
+ PRInt32 rv, err;
+
+ rv = gethostname(name, namelen);
+ if (rv == 0)
+ {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETHOSTNAME_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+#ifndef BONE_VERSION
+PRInt32
+_MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
+{
+ int rv;
+ int flags = 0;
+
+ rv = recv(fd->secret->md.osfd, NULL, 0, flags);
+ PR_ASSERT(-1 == rv || 0 == rv);
+ if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
+ return errno;
+ }
+ return 0; /* no error */
+}
+#else
+PRInt32
+_MD_beos_get_nonblocking_connect_error(int osfd)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+ // int err;
+ // _PRSockLen_t optlen = sizeof(err);
+ // if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
+ // return errno;
+ // } else {
+ // return err;
+ // }
+}
+#endif /* BONE_VERSION */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bproc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bproc.c
new file mode 100644
index 00000000..f21e9465
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bproc.c
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <stdio.h>
+#include <signal.h>
+
+#define _PR_SIGNALED_EXITSTATUS 256
+
+PRProcess*
+_MD_create_process (const char *path, char *const *argv,
+ char *const *envp, const PRProcessAttr *attr)
+{
+ PRProcess *process;
+ int nEnv, idx;
+ char *const *childEnvp;
+ char **newEnvp = NULL;
+ int flags;
+
+ process = PR_NEW(PRProcess);
+ if (!process) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ childEnvp = envp;
+ if (attr && attr->fdInheritBuffer) {
+ if (NULL == childEnvp) {
+ childEnvp = environ;
+ }
+ for (nEnv = 0; childEnvp[nEnv]; nEnv++) {
+ }
+ newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *));
+ if (NULL == newEnvp) {
+ PR_DELETE(process);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ for (idx = 0; idx < nEnv; idx++) {
+ newEnvp[idx] = childEnvp[idx];
+ }
+ newEnvp[idx++] = attr->fdInheritBuffer;
+ newEnvp[idx] = NULL;
+ childEnvp = newEnvp;
+ }
+
+ process->md.pid = fork();
+
+ if ((pid_t) -1 == process->md.pid) {
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
+ PR_DELETE(process);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ return NULL;
+ } else if (0 == process->md.pid) { /* the child process */
+ /*
+ * If the child process needs to exit, it must call _exit().
+ * Do not call exit(), because exit() will flush and close
+ * the standard I/O file descriptors, and hence corrupt
+ * the parent process's standard I/O data structures.
+ */
+
+ if (attr) {
+ /* the osfd's to redirect stdin, stdout, and stderr to */
+ int in_osfd = -1, out_osfd = -1, err_osfd = -1;
+
+ if (attr->stdinFd
+ && attr->stdinFd->secret->md.osfd != 0) {
+ in_osfd = attr->stdinFd->secret->md.osfd;
+ if (dup2(in_osfd, 0) != 0) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(0, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (attr->stdoutFd
+ && attr->stdoutFd->secret->md.osfd != 1) {
+ out_osfd = attr->stdoutFd->secret->md.osfd;
+ if (dup2(out_osfd, 1) != 1) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(1, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (attr->stderrFd
+ && attr->stderrFd->secret->md.osfd != 2) {
+ err_osfd = attr->stderrFd->secret->md.osfd;
+ if (dup2(err_osfd, 2) != 2) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(2, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(2, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (in_osfd != -1) {
+ close(in_osfd);
+ }
+ if (out_osfd != -1 && out_osfd != in_osfd) {
+ close(out_osfd);
+ }
+ if (err_osfd != -1 && err_osfd != in_osfd
+ && err_osfd != out_osfd) {
+ close(err_osfd);
+ }
+ if (attr->currentDirectory) {
+ if (chdir(attr->currentDirectory) < 0) {
+ _exit(1); /* failed */
+ }
+ }
+ }
+
+ if (childEnvp) {
+ (void)execve(path, argv, childEnvp);
+ } else {
+ /* Inherit the environment of the parent. */
+ (void)execv(path, argv);
+ }
+ /* Whoops! It returned. That's a bad sign. */
+ _exit(1);
+ }
+
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+
+ return process;
+}
+
+PRStatus
+_MD_detach_process (PRProcess *process)
+{
+ /* If we kept a process table like unix does,
+ * we'd remove the entry here.
+ * Since we dont', just delete the process variable
+ */
+ PR_DELETE(process);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_wait_process (PRProcess *process, PRInt32 *exitCode)
+{
+ PRStatus retVal = PR_SUCCESS;
+ int ret, status;
+
+ /* Ignore interruptions */
+ do {
+ ret = waitpid(process->md.pid, &status, 0);
+ } while (ret == -1 && errno == EINTR);
+
+ /*
+ * waitpid() cannot return 0 because we did not invoke it
+ * with the WNOHANG option.
+ */
+ PR_ASSERT(0 != ret);
+
+ if (ret < 0) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+
+ /* If child process exited normally, return child exit code */
+ if (WIFEXITED(status)) {
+ *exitCode = WEXITSTATUS(status);
+ } else {
+ PR_ASSERT(WIFSIGNALED(status));
+ *exitCode = _PR_SIGNALED_EXITSTATUS;
+ }
+
+ PR_DELETE(process);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_kill_process (PRProcess *process)
+{
+ PRErrorCode prerror;
+ PRInt32 oserror;
+
+ if (kill(process->md.pid, SIGKILL) == 0) {
+ return PR_SUCCESS;
+ }
+ oserror = errno;
+ switch (oserror) {
+ case EPERM:
+ prerror = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ESRCH:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, oserror);
+ return PR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/brng.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/brng.c
new file mode 100644
index 00000000..0aba8da3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/brng.c
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1999-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.
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <time.h>
+#include "primpl.h"
+
+extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
+{
+ struct timeval tv;
+ int n = 0;
+ int s;
+
+ GETTIMEOFDAY(&tv);
+
+ if ( size >= 0 ) {
+ s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec));
+ size -= s;
+ n += s;
+ }
+ if ( size >= 0 ) {
+ s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec));
+ size -= s;
+ n += s;
+ }
+
+ return n;
+} /* end _PR_MD_GetRandomNoise() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bseg.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bseg.c
new file mode 100644
index 00000000..b6b3b67b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bseg.c
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+PR_IMPLEMENT(void)
+ _MD_init_segs (void)
+{
+}
+
+PR_IMPLEMENT(PRStatus)
+ _MD_alloc_segment (PRSegment *seg, PRUint32 size, void *vaddr)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PR_IMPLEMENT(void)
+ _MD_free_segment (PRSegment *seg)
+{
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bsrcs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bsrcs.mk
new file mode 100644
index 00000000..c6eb6fe1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/bsrcs.mk
@@ -0,0 +1,54 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+# this file lists the source files to be compiled (used in Makefile) and
+# then enumerated as object files (in objs.mk) for inclusion in the NSPR
+# shared library
+
+MDCSRCS = \
+ beos.c \
+ beos_errors.c \
+ bfile.c \
+ bmisc.c \
+ bnet.c \
+ bproc.c \
+ brng.c \
+ bseg.c \
+ btime.c \
+ bmmap.c \
+ $(NULL)
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/btime.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/btime.c
new file mode 100644
index 00000000..aaaa9d27
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/btime.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <kernel/OS.h>
+
+static bigtime_t start;
+
+PRTime
+_MD_now (void)
+{
+ return (PRTime)real_time_clock_usecs();
+}
+
+void
+_MD_interval_init (void)
+{
+ /* grab the base interval time */
+ start = real_time_clock_usecs();
+}
+
+PRIntervalTime
+_MD_get_interval (void)
+{
+ return( (PRIntervalTime) real_time_clock_usecs() / 10 );
+
+#if 0
+ /* return the number of tens of microseconds that have elapsed since
+ we were initialized */
+ bigtime_t now = real_time_clock_usecs();
+ now -= start;
+ now /= 10;
+ return (PRIntervalTime)now;
+#endif
+}
+
+PRIntervalTime
+_MD_interval_per_sec (void)
+{
+ return 100000L;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/objs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/objs.mk
new file mode 100644
index 00000000..163c5d9c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/beos/objs.mk
@@ -0,0 +1,43 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+# This makefile appends to the variable OBJS the platform-dependent
+# object modules that will be part of the nspr20 library.
+
+include $(srcdir)/md/beos/bsrcs.mk
+
+OBJS += $(MDCSRCS:%.c=md/beos/$(OBJDIR)/%.$(OBJ_SUFFIX))
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MANIFEST b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MANIFEST
new file mode 100644
index 00000000..c51cbd5a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MANIFEST
@@ -0,0 +1,7 @@
+#
+# This is a list of local files which get copied to the mozilla:dist directory
+#
+
+MacErrorHandling.h
+macsocket.h
+prcpucfg.h
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MacErrorHandling.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MacErrorHandling.h
new file mode 100644
index 00000000..b0e03900
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/MacErrorHandling.h
@@ -0,0 +1,668 @@
+/* ***** 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*********************************************************************
+
+FILENAME
+ Exceptions.h
+
+DESCRIPTION
+ A collection of routines and macros to handle assertions and
+ exceptions.
+
+COPYRIGHT
+ Copyright © Apple Computer, Inc. 1989-1991
+ All rights reserved.
+
+ROUTINES
+ EXTERNALS
+ dprintf
+ check_dprintf
+ checkpos_dprintf
+
+MACROS
+ EXTERNALS
+ check
+ ncheck
+ check_action
+ ncheck_action
+ require
+ nrequire
+ require_action
+ nrequire_action
+ resume
+
+MODIFICATION HISTORY
+ Nov 12 95 BKJ Moved to MetroWerks environment & the NSPR
+
+NOTE
+ To keep code size down, use these routines and macros with the C
+ compiler option -b2 or -b3. This will eliminate duplicate strings
+ within a procedure.
+
+*********************************************************************/
+
+#ifndef __MACERRORHANDLING__
+#define __MACERRORHANDLING__
+
+/*********************************************************************
+
+INCLUDES
+
+*********************************************************************/
+
+#include <Types.h>
+
+/*<FF>*/
+/*********************************************************************
+
+CONSTANTS AND CONTROL
+
+*********************************************************************/
+
+/*
+ These defines are used to control the amount of information
+ displayed when an assertion fails. DEBUGOFF and WARN will run
+ silently. MIN will simply break into the debugger. ON will break
+ and display the assertion that failed and the exception (for
+ require statements). FULL will also display the source file name
+ and line number. SYM does a SysBreak and is usefull when using a
+ symbolic debugger like SourceBug or SADE. They should be set into
+ DEBUGLEVEL. The default LEVEL is OFF.
+*/
+
+#define DEBUGOFF 0
+#define DEBUGWARN 1
+#define DEBUGMIN 2
+#define DEBUGON 3
+#define DEBUGFULL 4
+#define DEBUGSYM 6
+
+#ifndef DEBUGLEVEL
+#define DEBUGLEVEL DEBUGOFF
+#endif DEBUGLEVEL
+
+/*
+ resumeLabel is used to control the insertion of labels for use with
+ the resume macro. If you do not use the resume macro and you wish
+ to have multible exceptions per label then you can add the
+ following define to you source code.
+
+*/
+#define resumeLabel(exception) // Multiple exceptions per label
+// #define resumeLabel(exception) resume_ ## exception: // Single exception per label
+
+
+/*
+ traceon and debugon are used to test for options
+*/
+
+#define traceon ((DEBUGLEVEL > DEBUGWARN) && defined(TRACEON))
+#define debugon (DEBUGLEVEL > DEBUGWARN)
+
+/*
+ Add some macros for DEBUGMIN and DEBUGSYM to keep the size down.
+*/
+
+#define __DEBUGSMALL ((DEBUGLEVEL == DEBUGMIN) || \
+ (DEBUGLEVEL == DEBUGSYM))
+
+#if DEBUGLEVEL == DEBUGMIN
+#define __DebuggerBreak Debugger()
+#elif DEBUGLEVEL == DEBUGSYM
+#define __DebuggerBreak SysBreak()
+#endif
+
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ check(assertion)
+
+DESCRIPTION
+ If debugging is on then check will test assertion and if it fails
+ break into the debugger. Otherwise check does nothing.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define check(assertion) \
+ do { \
+ if (assertion) ; \
+ else __DebuggerBreak; \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define check(assertion) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed", #assertion); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define check(assertion) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, __FILE__, __LINE__); \
+ } \
+ } while (false)
+
+#else
+
+#define check(assertion)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ ncheck(assertion)
+
+DESCRIPTION
+ If debugging is on then ncheck will test !assertion and if it fails
+ break into the debugger. Otherwise ncheck does nothing.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define ncheck(assertion) \
+ do { \
+ if (assertion) __DebuggerBreak; \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define ncheck(assertion) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed", \
+ #assertion, __privateAssertion); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define ncheck(assertion) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, __privateAssertion, __FILE__, __LINE__); \
+ } \
+ } while (false)
+
+#else
+
+#define ncheck(assertion)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ check_action(assertion, action)
+
+DESCRIPTION
+ If debugging is on then check_action will test assertion and if it
+ fails break into the debugger then execute action. Otherwise
+ check_action does nothing.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define check_action(assertion, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ __DebuggerBreak; \
+ { action } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define check_action(assertion, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed", #assertion); \
+ { action } \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define check_action(assertion, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, __FILE__, __LINE__); \
+ { action } \
+ } \
+ } while (false)
+
+#else
+
+#define check_action(assertion, action)
+
+#endif
+
+/*<FF>*/
+/**************************************************************************************
+
+MACRO
+ ncheck_action(assertion, action)
+
+DESCRIPTION
+ If debugging is on then ncheck_action will test !assertion and if
+ it fails break into the debugger then execute action. Otherwise
+ ncheck_action does nothing.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define ncheck_action(assertion, action) \
+ do { \
+ if (assertion) { \
+ __DebuggerBreak; \
+ { action } \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define ncheck_action(assertion, action) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed", \
+ #assertion, __privateAssertion); \
+ { action } \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define ncheck_action(assertion, action) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, __privateAssertion, __FILE__, __LINE__); \
+ { action } \
+ } \
+ } while (false)
+
+#else
+
+#define ncheck_action(assertion, action)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ require(assertion, exception)
+
+DESCRIPTION
+ require will test assertion and if it fails:
+ break into the debugger if debugging is on.
+ goto exception.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define require(assertion, exception) \
+ do { \
+ if (assertion) ; \
+ else { \
+ __DebuggerBreak; \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define require(assertion, exception) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed\n" \
+ "Exception \"%s\" Raised", \
+ #assertion, #exception); \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define require(assertion, exception) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed\n" \
+ "Exception \"%s\" Raised\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, #exception, __FILE__, __LINE__); \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#else
+
+#define require(assertion, exception) \
+ do { \
+ if (assertion) ; \
+ else { \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ nrequire(assertion, exception)
+
+DESCRIPTION
+ nrequire will test !assertion and if it fails:
+ break into the debugger if debugging is on.
+ goto exception.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define nrequire(assertion, exception) \
+ do { \
+ if (assertion) { \
+ DebugStr(); \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define nrequire(assertion, exception) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
+ "Exception \"%s\" Raised", \
+ #assertion, __privateAssertion, #exception); \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define nrequire(assertion, exception) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
+ "Exception \"%s\" Raised\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, __privateAssertion, #exception, __FILE__, \
+ __LINE__); \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#else
+
+#define nrequire(assertion, exception) \
+ do { \
+ if (assertion) { \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ require_action(assertion, exception, action)
+
+DESCRIPTION
+ require_action will test assertion and if it fails:
+ break into the debugger if debugging is on.
+ execute action.
+ goto exception.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define require_action(assertion, exception, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ __DebuggerBreak; \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define require_action(assertion, exception, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed\n" \
+ "Exception \"%s\" Raised", \
+ #assertion, #exception); \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define require_action(assertion, exception, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ dprintf(notrace, "Assertion \"%s\" Failed\n" \
+ "Exception \"%s\" Raised\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, #exception, __FILE__, __LINE__); \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#else
+
+#define require_action(assertion, exception, action) \
+ do { \
+ if (assertion) ; \
+ else { \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ nrequire_action(assertion, exception, action)
+
+DESCRIPTION
+ nrequire_action will test !assertion and if it fails:
+ break into the debugger if debugging is on.
+ execute action.
+ goto exception.
+
+*********************************************************************/
+
+#if __DEBUGSMALL
+
+#define nrequire_action(assertion, exception, action) \
+ do { \
+ if (assertion) { \
+ __DebuggerBreak; \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGON
+
+#define nrequire_action(assertion, exception, action) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
+ "Exception \"%s\" Raised", \
+ #assertion, __privateAssertion, #exception); \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#elif DEBUGLEVEL == DEBUGFULL
+
+#define nrequire_action(assertion, exception, action) \
+ do { \
+ void* __privateAssertion = (void*)(assertion); \
+ \
+ if (__privateAssertion) { \
+ dprintf(notrace, "Assertion \"!(%s [= %#08X])\" Failed\n" \
+ "Exception \"%s\" Raised\n" \
+ "File: %s\n" \
+ "Line: %d", \
+ #assertion, __privateAssertion, #exception, __FILE__, \
+ __LINE__); \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#else
+
+#define nrequire_action(assertion, exception, action) \
+ do { \
+ if (assertion) { \
+ { action } \
+ goto exception; \
+ resumeLabel(exception); \
+ } \
+ } while (false)
+
+#endif
+
+/*<FF>*/
+/*********************************************************************
+
+MACRO
+ resume(exception)
+
+DESCRIPTION
+ resume will resume execution after the n/require/_action statement
+ specified by exception. Resume lables must be on (the default) in
+ order to use resume. If an action form of require was used then the
+ action will not be re-executed.
+
+*********************************************************************/
+
+
+#define resume(exception) \
+ do { \
+ goto resume_ ## exception; \
+ } while (false)
+
+
+/*<FF>*/
+/********************************************************************/
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c
new file mode 100644
index 00000000..a5ecce78
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c
@@ -0,0 +1,587 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <string.h>
+
+#include <Files.h>
+#include <Errors.h>
+#include <Folders.h>
+#include <CodeFragments.h>
+#include <Aliases.h>
+#include <Resources.h>
+
+#include "IterateDirectory.h" /* MoreFiles */
+
+#include "MacErrorHandling.h"
+#include "macdll.h"
+#include "mdmac.h"
+#include "macio.h"
+
+#include "primpl.h"
+#include "plstr.h"
+
+/*
+ turds used to iterate through the directories looking
+ for the desired library.
+*/
+
+struct GetSharedLibraryFilterProcData
+{
+ Boolean inRecursive;
+ StringPtr inName;
+
+ Boolean outFound;
+ CFragConnectionID outID;
+ Ptr outAddress;
+ OSErr outError;
+};
+typedef struct GetSharedLibraryFilterProcData GetSharedLibraryFilterProcData;
+
+static pascal void
+GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData);
+
+
+/*
+ NSGetSharedLibrary
+
+ Unfortunately CFM doesn't support user specified loader paths,
+ so we emulate the behavior. Effectively this is a GetSharedLibrary
+ where the loader path is user defined.
+*/
+
+OSErr
+NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr)
+{
+ char* curLibPath;
+ char* freeCurLibPath;
+ OSErr tempErr;
+ Boolean recursive;
+ FSSpec curFolder;
+ GetSharedLibraryFilterProcData filterData;
+ char *endCurLibPath;
+ Boolean done;
+
+ filterData.outFound = false;
+ filterData.outID = (CFragConnectionID)(-1);
+ filterData.outAddress = NULL;
+ filterData.inName = inLibName;
+
+ freeCurLibPath = curLibPath = PR_GetLibraryPath();
+
+ if (curLibPath == NULL)
+ return (cfragNoLibraryErr);
+
+ tempErr = cfragNoLibraryErr;
+
+ do
+ {
+ endCurLibPath = PL_strchr(curLibPath, PR_PATH_SEPARATOR);
+ done = (endCurLibPath == NULL);
+
+#if 0
+ // we overload the first character of a path if it's :
+ // then we want to recursively search that path
+ // see if path should be recursive
+ if (*curLibPath == ':')
+ {
+ // ':' is an illegal character in the name of a file
+ // if we start any path with this, we want to allow
+ // search recursively
+ curLibPath++;
+ recursive = true;
+ }
+ else
+#endif
+ {
+ recursive = false;
+ }
+
+ if (!done)
+ *endCurLibPath = '\0'; // NULL terminate the string
+
+ // convert to FSSpec
+ tempErr = ConvertUnixPathToFSSpec(curLibPath, &curFolder);
+
+ // now look in this directory
+ if (noErr == tempErr)
+ {
+ filterData.inRecursive = recursive;
+ FSpIterateDirectory(&curFolder, recursive ? 0 : 1, &GetSharedLibraryFilterProc, &filterData);
+
+ if (filterData.outFound)
+ {
+ *outID = filterData.outID;
+ *outMainAddr = filterData.outAddress;
+ tempErr = noErr;
+ break;
+ }
+ else
+ {
+ tempErr = cfragNoLibraryErr;
+ }
+ }
+
+ curLibPath = endCurLibPath + 1; // skip to next path (past the '\0');
+ } while (!done);
+
+ free(freeCurLibPath);
+ return (tempErr);
+}
+
+
+static Boolean
+LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength);
+
+
+/*
+ GetSharedLibraryFilterProc
+
+ Callback to FSpIterateDirectory, finds a library with the name matching the
+ data in inFilterData (of type GetSharedLibraryFilterProcData). Forces a quit
+ when a match is found.
+*/
+
+static pascal void
+GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData)
+{
+ GetSharedLibraryFilterProcData* pFilterData = (GetSharedLibraryFilterProcData*) inFilterData;
+
+ if ((inCpb->hFileInfo.ioFlAttrib & (1 << ioDirFlg)) == 0)
+ {
+ FSSpec fragSpec;
+ OSErr tempErr;
+ Str255 errName;
+ Boolean crap;
+ UInt32 codeOffset;
+ UInt32 codeLength;
+
+ // it's a file
+
+ // ¥ fix-me do we really want to allow all 'APPL's' for in which to find this library?
+ switch (inCpb->hFileInfo.ioFlFndrInfo.fdType)
+ {
+ case kCFragLibraryFileType:
+ case 'APPL':
+ tempErr = FSMakeFSSpec(inCpb->hFileInfo.ioVRefNum, inCpb->hFileInfo.ioFlParID, inCpb->hFileInfo.ioNamePtr, &fragSpec);
+
+ // this shouldn't fail
+ if (noErr != tempErr)
+ {
+ return;
+ }
+
+ // resolve an alias if this was one
+ tempErr = ResolveAliasFile(&fragSpec, true, &crap, &crap);
+
+ // if got here we have a shlb (or app-like shlb)
+ if (noErr != tempErr)
+ {
+ // probably couldn't resolve an alias
+ return;
+ }
+
+ break;
+ default:
+ return;
+ }
+
+ // see if this symbol is in this fragment
+ if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength))
+ tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, fragSpec.name, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName);
+ else
+ return;
+
+ // stop if we found a library by that name
+ if (noErr == tempErr)
+ {
+ *inWantQuit = true;
+ pFilterData->outFound = true;
+ pFilterData->outError = tempErr;
+ }
+ }
+ // FSpIterateDirectory will automagically call us for subsequent sub-dirs if necessary
+}
+
+
+/*
+ LibInPefContainer
+
+ Tell whether library inName is contained it the file pointed to by inSpec.
+ Return the codeOffset and codeLength information, for a subsequent
+ call to GetDiskFragment.
+*/
+
+static Boolean
+LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength)
+{
+ short refNum;
+ CFragResourceHandle hCfrg;
+ CFragResourceMember* pCurItem;
+ UInt32 curLibIndex;
+ Boolean found;
+
+ // asume we didn't find it
+ found = false;
+
+ // open the resource fork, if we can't bail
+ refNum = FSpOpenResFile(inSpec, fsRdPerm);
+ require(-1 != refNum, Exit);
+
+ // grab out the alias record, if it's not there bail
+ hCfrg = (CFragResourceHandle) Get1Resource(kCFragResourceType, kCFragResourceID);
+ require(NULL != hCfrg, CloseResourceAndExit);
+
+ HLock((Handle)hCfrg);
+
+ // get ptr to first item
+ pCurItem = &(*hCfrg)->firstMember;
+ for (curLibIndex = 0; curLibIndex < (*hCfrg)->memberCount; curLibIndex++)
+ {
+ // is this our library?
+ if ((pCurItem->name[0] == inName[0]) &&
+ (strncmp((char*) inName + 1, (char*) pCurItem->name + 1, PR_MIN(pCurItem->name[0], inName[0])) == 0))
+ {
+ *outCodeOffset = pCurItem->offset;
+ *outCodeLength = pCurItem->length;
+ found = true;
+ }
+
+ // skip to next one
+ pCurItem = (CFragResourceMember*) ((char*) pCurItem + pCurItem->memberSize);
+ }
+
+ HUnlock((Handle)hCfrg);
+
+CloseResourceAndExit:
+ CloseResFile(refNum);
+Exit:
+ return (found);
+
+}
+
+
+/*
+ NSFindSymbol
+
+ Workaround bug in CFM FindSymbol (in at least 7.5.5) where symbols with lengths
+ greater than 63 chars cause a "paramErr". We iterate through all symbols
+ in the library to find the desired symbol.
+*/
+
+OSErr
+NSFindSymbol(CFragConnectionID inID, Str255 inSymName, Ptr* outMainAddr, CFragSymbolClass *outSymClass)
+{
+ OSErr err;
+
+ if (inSymName[0] > 63)
+ {
+ /*
+ if there are greater than 63 characters in the
+ name, CFM FindSymbol fails, so let's iterate through all
+ of the symbols in the fragment and grab it
+ that way.
+ */
+ long symbolCount;
+ Str255 curSymName;
+ long curIndex;
+ Boolean found;
+
+ found = false;
+ err = CountSymbols(inID, &symbolCount);
+ if (noErr == err)
+ {
+ /* now iterate through all the symbols in the library */
+ /* per DTS the indices apparently go 0 to n-1 */
+ for (curIndex = 0; (curIndex <= symbolCount - 1 && !found); curIndex++)
+ {
+ err = GetIndSymbol(inID, curIndex, curSymName, outMainAddr, outSymClass);
+ if (noErr == err && curSymName[0] == inSymName[0] && !strncmp((char*)curSymName + 1, (char*)inSymName + 1, curSymName[0]))
+ {
+ /* found our symbol */
+ found = true;
+ }
+ }
+
+ /* if we didn't find it set the error code so below it won't take this symbol */
+ if (!found)
+ err = cfragNoSymbolErr;
+ }
+ }
+ else
+ {
+ err = FindSymbol(inID, inSymName, outMainAddr, outSymClass);
+ }
+
+ return (err);
+}
+
+
+#pragma mark -
+
+
+/*-----------------------------------------------------------------
+
+ GetNamedFragmentOffsets
+
+ Get the offsets into the data fork of the named fragment,
+ by reading the 'cfrg' resoruce.
+
+-----------------------------------------------------------------*/
+OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
+ UInt32 *outOffset, UInt32 *outLength)
+{
+ CFragResourceHandle cFragHandle;
+ short fileRefNum;
+ OSErr err = noErr;
+
+ fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
+ err = ResError();
+ if (err != noErr) return err;
+
+ cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
+ if (!cFragHandle)
+ {
+ err = resNotFound;
+ goto done;
+ }
+
+ /* nothing here moves memory, so no need to lock the handle */
+
+ err = cfragNoLibraryErr; /* in case of failure */
+ *outOffset = 0;
+ *outLength = 0;
+
+ /* Now look for the named fragment */
+ if ((**cFragHandle).memberCount > 0)
+ {
+ CFragResourceMemberPtr memberPtr;
+ UInt16 i;
+
+ for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
+ i < (**cFragHandle).memberCount;
+ i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
+ {
+ char memberName[256];
+ UInt16 nameLen = PR_MIN(memberPtr->name[0], 255);
+
+ // avoid malloc here for speed
+ strncpy(memberName, (char *)&memberPtr->name[1], nameLen);
+ memberName[nameLen] = '\0';
+
+ // fragment names are case insensitive, so act like the system
+ if (PL_strcasecmp(memberName, fragmentName) == 0)
+ {
+ *outOffset = memberPtr->offset;
+ *outLength = memberPtr->length;
+ err = noErr;
+ break;
+ }
+ }
+ }
+
+ /* Resource handle will go away when the res fork is closed */
+
+done:
+ CloseResFile(fileRefNum);
+ return err;
+}
+
+
+/*-----------------------------------------------------------------
+
+ GetIndexedFragmentOffsets
+
+ Get the offsets into the data fork of the indexed fragment,
+ by reading the 'cfrg' resoruce.
+
+-----------------------------------------------------------------*/
+OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
+ UInt32 *outOffset, UInt32 *outLength, char **outFragmentName)
+{
+ CFragResourceHandle cFragHandle;
+ short fileRefNum;
+ OSErr err = noErr;
+
+ fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
+ err = ResError();
+ if (err != noErr) return err;
+
+ cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
+ if (!cFragHandle)
+ {
+ err = resNotFound;
+ goto done;
+ }
+
+ err = cfragNoLibraryErr; /* in case of failure */
+ *outOffset = 0;
+ *outLength = 0;
+ *outFragmentName = NULL;
+
+ /* the CStrFromPStr mallocs, so might move memory */
+ HLock((Handle)cFragHandle);
+
+ /* Now look for the named fragment */
+ if ((**cFragHandle).memberCount > 0)
+ {
+ CFragResourceMemberPtr memberPtr;
+ UInt16 i;
+
+ for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
+ i < (**cFragHandle).memberCount;
+ i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
+ {
+
+ if (i == fragmentIndex)
+ {
+ char *fragmentStr;
+ CStrFromPStr(memberPtr->name, &fragmentStr);
+ if (!fragmentStr) /* test for allocation failure */
+ {
+ err = memFullErr;
+ break;
+ }
+
+ *outFragmentName = fragmentStr;
+ *outOffset = memberPtr->offset;
+ *outLength = memberPtr->length;
+ err = noErr;
+ break;
+ }
+ }
+ }
+
+ HUnlock((Handle)cFragHandle);
+
+ /* Resource handle will go away when the res fork is closed */
+
+done:
+ CloseResFile(fileRefNum);
+ return err;
+}
+
+
+/*-----------------------------------------------------------------
+
+ NSLoadNamedFragment
+
+ Load the named fragment from the specified file. Aliases must
+ have been resolved by this point.
+
+-----------------------------------------------------------------*/
+
+OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID)
+{
+ UInt32 fragOffset, fragLength;
+ short fragNameLength;
+ Ptr main;
+ Str255 fragName;
+ Str255 errName;
+ OSErr err;
+
+ err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
+ if (err != noErr) return err;
+
+ // convert fragment name to pascal string
+ fragNameLength = strlen(fragmentName);
+ if (fragNameLength > 255)
+ fragNameLength = 255;
+ BlockMoveData(fragmentName, &fragName[1], fragNameLength);
+ fragName[0] = fragNameLength;
+
+ // Note that we pass the fragment name as the 4th param to GetDiskFragment.
+ // This value affects the ability of debuggers, and the Talkback system,
+ // to match code fragments with symbol files
+ err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
+ kLoadCFrag, outConnectionID, &main, errName);
+
+ return err;
+}
+
+
+/*-----------------------------------------------------------------
+
+ NSLoadIndexedFragment
+
+ Load the indexed fragment from the specified file. Aliases must
+ have been resolved by this point.
+
+ *outFragName is a malloc'd block containing the fragment name,
+ if returning noErr.
+
+-----------------------------------------------------------------*/
+
+OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
+ char** outFragName, CFragConnectionID *outConnectionID)
+{
+ UInt32 fragOffset, fragLength;
+ char *fragNameBlock = NULL;
+ Ptr main;
+ Str255 fragName = "\p";
+ Str255 errName;
+ OSErr err;
+
+ *outFragName = NULL;
+
+ err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
+ if (err != noErr) return err;
+
+ if (fragNameBlock)
+ {
+ UInt32 nameLen = strlen(fragNameBlock);
+ if (nameLen > 63)
+ nameLen = 63;
+ BlockMoveData(fragNameBlock, &fragName[1], nameLen);
+ fragName[0] = nameLen;
+ }
+
+ // Note that we pass the fragment name as the 4th param to GetDiskFragment.
+ // This value affects the ability of debuggers, and the Talkback system,
+ // to match code fragments with symbol files
+ err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
+ kLoadCFrag, outConnectionID, &main, errName);
+ if (err != noErr)
+ {
+ free(fragNameBlock);
+ return err;
+ }
+
+ *outFragName = fragNameBlock;
+ return noErr;
+}
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.h
new file mode 100644
index 00000000..a34890cd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef macdll_h__
+#define macdll_h__
+
+#include "prtypes.h"
+
+OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
+ UInt32 *outOffset, UInt32 *outLength);
+OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
+ UInt32 *outOffset, UInt32 *outLength, char **outFragmentName);
+
+OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID);
+OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
+ char** outFragName, CFragConnectionID *outConnectionID);
+
+
+OSErr NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr);
+OSErr NSFindSymbol(CFragConnectionID inID, Str255 inSymName,
+ Ptr* outMainAddr, CFragSymbolClass *outSymClass);
+
+#endif /* macdll_h__ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.c
new file mode 100644
index 00000000..ae3516de
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.c
@@ -0,0 +1,1949 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <string.h>
+
+#include <Types.h>
+#include <Files.h>
+#include <Devices.h>
+#include <Folders.h>
+#include <Errors.h>
+#include <Resources.h>
+#include <Processes.h>
+#include <TextUtils.h>
+
+#include <fcntl.h>
+
+#include "FullPath.h" /* MoreFiles */
+
+#include "primpl.h"
+#include "MacErrorHandling.h"
+#include "mdmac.h"
+
+#include "macio.h"
+
+/* forward declarations */
+extern unsigned long gJanuaryFirst1970Seconds;
+
+extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);
+extern void DoneWaitingOnThisThread(PRThread *thread);
+extern void AsyncNotify(PRThread *thread);
+
+
+/* PB for Read and Write */
+struct ExtendedParamBlock {
+ /* PB must be first so that the file system can get the right data. */
+ ParamBlockRec pb;
+ PRThread *thread;
+};
+typedef struct ExtendedParamBlock ExtendedParamBlock;
+
+
+/* XXX Not done yet for 68K */
+/* I/O completion routne for _MD_READ and _MD_WRITE */
+static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr)
+{
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+ PRThread *thread = pbAsyncPtr->thread;
+ PRIntn is;
+
+ if (_PR_MD_GET_INTSOFF()) {
+ thread->md.missedIONotify = PR_TRUE;
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ } else {
+ _PR_INTSOFF(is);
+
+ thread->md.osErrCode = noErr;
+ DoneWaitingOnThisThread(thread);
+
+ _PR_FAST_INTSON(is);
+ }
+
+ SignalIdleSemaphore();
+}
+
+void _MD_SetError(OSErr oserror)
+{
+ PRErrorCode code;
+
+ switch (oserror) {
+ case memFullErr:
+ code = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case fnfErr:
+ code = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case dupFNErr:
+ code = PR_FILE_EXISTS_ERROR;
+ break;
+ case ioErr:
+ code = PR_IO_ERROR;
+ break;
+ case nsvErr:
+ case wrgVolTypErr:
+ code = PR_INVALID_DEVICE_STATE_ERROR;
+ break;
+ case bdNamErr:
+ case fsRnErr:
+ code = PR_NAME_TOO_LONG_ERROR;
+ break;
+ case tmfoErr:
+ code = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case opWrErr:
+ case wrPermErr:
+ case permErr:
+ case afpAccessDenied:
+ code = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case afpObjectTypeErr:
+ code = PR_DIRECTORY_LOOKUP_ERROR;
+ break;
+ case wPrErr:
+ case vLckdErr:
+ code = PR_DEVICE_IS_LOCKED_ERROR;
+ break;
+ case fLckdErr:
+ code = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case dirNFErr:
+ code = PR_NOT_DIRECTORY_ERROR;
+ break;
+ case dirFulErr:
+ code = PR_MAX_DIRECTORY_ENTRIES_ERROR;
+ break;
+ case dskFulErr:
+ code = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+ case rfNumErr:
+ case fnOpnErr:
+ code = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case eofErr:
+ code = PR_END_OF_FILE_ERROR;
+ break;
+ case posErr:
+ case gfpErr:
+ code = PR_FILE_SEEK_ERROR;
+ break;
+ case fBsyErr:
+ code = PR_FILE_IS_BUSY_ERROR;
+ break;
+ case extFSErr:
+ code = PR_REMOTE_FILE_ERROR;
+ break;
+ case abortErr:
+ code = PR_PENDING_INTERRUPT_ERROR;
+ break;
+ case paramErr:
+ code = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case unimpErr:
+ code = PR_NOT_IMPLEMENTED_ERROR;
+ break;
+ }
+
+ PR_SetError(code, oserror);
+}
+
+void _MD_IOInterrupt(void)
+{
+ PRCList *qp;
+ PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
+
+ _PR_SLEEPQ_LOCK(me->cpu);
+ qp = _PR_PAUSEQ(me->cpu).next;
+ while (qp != &_PR_PAUSEQ(me->cpu)) {
+
+ thread = _PR_THREAD_PTR(qp);
+ PR_ASSERT(thread->flags & _PR_ON_PAUSEQ);
+
+ qp = qp->next;
+
+ if (thread->md.missedIONotify) {
+ thread->md.missedIONotify = PR_FALSE;
+ DoneWaitingOnThisThread(thread);
+ }
+
+ if (thread->md.missedAsyncNotify) {
+ thread->md.missedAsyncNotify = PR_FALSE;
+ AsyncNotify(thread);
+ }
+ }
+ qp = _PR_SLEEPQ(me->cpu).next;
+ while (qp != &_PR_SLEEPQ(me->cpu)) {
+
+ thread = _PR_THREAD_PTR(qp);
+ PR_ASSERT(thread->flags & _PR_ON_SLEEPQ);
+
+ qp = qp->next;
+
+ if (thread->md.missedIONotify) {
+ thread->md.missedIONotify = PR_FALSE;
+ DoneWaitingOnThisThread(thread);
+ }
+
+ if (thread->md.missedAsyncNotify) {
+ thread->md.missedAsyncNotify = PR_FALSE;
+ AsyncNotify(thread);
+ }
+ }
+ _PR_SLEEPQ_UNLOCK(thread->cpu);
+}
+
+/*
+** All PR_read and PR_Write calls are synchronous from caller's perspective.
+** They are internally made asynchronous calls. This gives cpu to other
+** user threads while the async io is in progress.
+*/
+PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
+{
+ PRInt32 refNum = fd->secret->md.osfd;
+ OSErr err;
+ ExtendedParamBlock pbAsync;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+
+ /* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */
+ /* note, if a user chooses "seek" or the like as an operation in another function */
+ /* this will not work */
+ if (refNum >= 0 && refNum < 3)
+ {
+ switch (refNum)
+ {
+ case 0:
+ /* stdin - not on a Mac for now */
+ err = paramErr;
+ goto ErrorExit;
+ break;
+ case 1: /* stdout */
+ case 2: /* stderr */
+ puts(buf);
+ break;
+ }
+
+ return (bytes);
+ }
+ else
+ {
+ static IOCompletionUPP sCompletionUPP = NULL;
+
+ PRBool doingAsync = PR_FALSE;
+
+ /* allocate the callback Universal Procedure Pointer (UPP). This actually allocates
+ a 32 byte Ptr in the heap, so only do this once
+ */
+ if (!sCompletionUPP)
+ sCompletionUPP = NewIOCompletionUPP((IOCompletionProcPtr)&AsyncIOCompletion);
+
+ /* grab the thread so we know which one to post to at completion */
+ pbAsync.thread = me;
+
+ pbAsync.pb.ioParam.ioCompletion = sCompletionUPP;
+ pbAsync.pb.ioParam.ioResult = noErr;
+ pbAsync.pb.ioParam.ioRefNum = refNum;
+ pbAsync.pb.ioParam.ioBuffer = buf;
+ pbAsync.pb.ioParam.ioReqCount = bytes;
+ pbAsync.pb.ioParam.ioPosMode = fsAtMark;
+ pbAsync.pb.ioParam.ioPosOffset = 0;
+
+ /*
+ ** Issue the async read call and wait for the io semaphore associated
+ ** with this thread.
+ ** Async file system calls *never* return error values, so ignore their
+ ** results (see <http://developer.apple.com/technotes/fl/fl_515.html>);
+ ** the completion routine is always called.
+ */
+ me->io_fd = refNum;
+ me->md.osErrCode = noErr;
+ if (op == READ_ASYNC)
+ {
+ /*
+ ** Skanky optimization so that reads < 20K are actually done synchronously
+ ** to optimize performance on small reads (e.g. registry reads on startup)
+ */
+ if ( bytes > 20480L )
+ {
+ doingAsync = PR_TRUE;
+ me->io_pending = PR_TRUE;
+
+ (void)PBReadAsync(&pbAsync.pb);
+ }
+ else
+ {
+ pbAsync.pb.ioParam.ioCompletion = NULL;
+ me->io_pending = PR_FALSE;
+
+ err = PBReadSync(&pbAsync.pb);
+ if (err != noErr && err != eofErr)
+ goto ErrorExit;
+ }
+ }
+ else
+ {
+ doingAsync = PR_TRUE;
+ me->io_pending = PR_TRUE;
+
+ /* writes are currently always async */
+ (void)PBWriteAsync(&pbAsync.pb);
+ }
+
+ if (doingAsync) {
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ }
+ }
+
+ err = me->md.osErrCode;
+ if (err != noErr)
+ goto ErrorExit;
+
+ err = pbAsync.pb.ioParam.ioResult;
+ if (err != noErr && err != eofErr)
+ goto ErrorExit;
+
+ return pbAsync.pb.ioParam.ioActCount;
+
+ErrorExit:
+ me->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+/*
+Special WriteSyncProc for logging only. IO occurs synchronously. Otherwise,
+logging internal to NSPR causes ReadWriteProc above to recurse on PR_WaitSem logging.
+*/
+PRInt32 WriteSyncProc(PRFileDesc *fd, void *buf, PRUint32 bytes)
+{
+ PRInt32 refNum = fd->secret->md.osfd;
+ OSErr err;
+ ParamBlockRec pb;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (refNum >= 0 && refNum < 3)
+ {
+ PR_ASSERT(FALSE); /* writing to these is hazardous to a Mac's health (refNum 2 is the system file) */
+ err = paramErr;
+ goto ErrorExit;
+ }
+
+ pb.ioParam.ioCompletion = NULL;
+ pb.ioParam.ioResult = noErr;
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioBuffer = buf;
+ pb.ioParam.ioReqCount = bytes;
+ pb.ioParam.ioPosMode = fsAtMark;
+ pb.ioParam.ioPosOffset = 0;
+
+ err = PBWriteSync(&pb);
+
+ if (err != noErr)
+ goto ErrorExit;
+ else
+ return pb.ioParam.ioActCount;
+
+ErrorExit:
+ me->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+/* File I/O functions called by PR I/O routines */
+PRInt32 _MD_Open(const char *path, PRIntn flags, int mode)
+{
+// Macintosh doesn't really have mode bits, just drop them
+#pragma unused (mode)
+
+ OSErr err;
+ HParamBlockRec hpb;
+ ParamBlockRec pb;
+ char *macFileName = NULL;
+ Str255 pascalName;
+ PRInt8 perm;
+
+ err = ConvertUnixPathToMacPath(path, &macFileName);
+
+ if (err != noErr)
+ goto ErrorExit;
+
+ hpb.ioParam.ioCompletion = NULL;
+ PStrFromCStr(macFileName, pascalName);
+ PR_DELETE(macFileName);
+ hpb.ioParam.ioNamePtr = pascalName;
+ hpb.ioParam.ioVRefNum = 0;
+ hpb.ioParam.ioVersNum = 0;
+ hpb.fileParam.ioDirID = 0;
+
+ if (flags & PR_RDWR)
+ perm = fsRdWrPerm;
+ else if (flags & PR_WRONLY)
+ perm = fsWrPerm;
+ else
+ perm = fsRdPerm;
+ hpb.ioParam.ioPermssn = perm;
+
+
+ if (flags & PR_CREATE_FILE) {
+ err = PBHCreateSync(&hpb);
+
+ /* If opening with the PR_EXCL flag the existence of the file prior to opening is an error */
+ if ((flags & PR_EXCL) && (err == dupFNErr)) {
+ err = PR_FILE_EXISTS_ERROR;
+ goto ErrorExit;
+ }
+
+ if ((err != noErr) && (err != dupFNErr))
+ goto ErrorExit;
+ }
+
+ err = PBHOpenDFSync(&hpb);
+
+ if (err != noErr)
+ goto ErrorExit;
+
+ if (flags & PR_TRUNCATE) {
+ pb.ioParam.ioCompletion = NULL;
+ pb.ioParam.ioRefNum = hpb.ioParam.ioRefNum;
+ pb.ioParam.ioMisc = NULL;
+ err = PBSetEOFSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+ } else if (flags & PR_APPEND) {
+ pb.ioParam.ioCompletion = NULL;
+ pb.ioParam.ioRefNum = hpb.ioParam.ioRefNum;
+ pb.ioParam.ioPosMode = fsFromLEOF;
+ pb.ioParam.ioPosOffset = 0;
+ err = PBSetFPosSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+ }
+ return hpb.ioParam.ioRefNum;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+/* _MD_CLOSE_FILE, _MD_READ, _MD_WRITE, _MD_GET_FILE_ERROR are defined in _macos.h */
+
+PROffset32 _MD_LSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence how)
+{
+ PRInt32 refNum = fd->secret->md.osfd;
+ OSErr err = noErr;
+ long curPos, endPos;
+
+ /* compute new mark */
+ switch (how) {
+ case PR_SEEK_SET:
+ endPos = offset;
+ break;
+
+ case PR_SEEK_CUR:
+ err = GetFPos(refNum, &curPos);
+ endPos = curPos + offset;
+ break;
+
+ case PR_SEEK_END:
+ err = GetEOF(refNum, &curPos);
+ endPos = curPos + offset;
+ break;
+
+ default:
+ err = paramErr;
+ break;
+ }
+
+ /* set the new mark and extend the file if seeking beyond current EOF */
+ /* making sure to set the mark after any required extend */
+ if (err == noErr) {
+ err = SetFPos(refNum, fsFromStart, endPos);
+ if (err == eofErr) {
+ err = SetEOF(refNum, endPos);
+ if (err == noErr) {
+ err = SetFPos(refNum, fsFromStart, endPos);
+ }
+ }
+ }
+
+ if (err == noErr) {
+ return endPos;
+ } else {
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+ }
+}
+
+PRInt32 _MD_FSync(PRFileDesc *fd)
+{
+ PRInt32 refNum = fd->secret->md.osfd;
+ OSErr err;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioCompletion = NULL;
+ pb.ioParam.ioRefNum = refNum;
+
+ err = PBFlushFileSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+#include "plstr.h"
+
+PRStatus _MD_OpenDir(_MDDir *mdDir,const char *name)
+{
+ // Emulate the Unix opendir() routine.
+
+ OSErr err;
+ CInfoPBRec pb;
+ char *macDirName = NULL;
+ char *position = NULL;
+ char volumeName[32];
+ Str255 pascalName;
+
+ // Get the Macintosh path
+ err = ConvertUnixPathToMacPath(name, &macDirName);
+ if (err != noErr)
+ goto ErrorExit;
+
+ // Get the vRefNum
+ position = PL_strchr(macDirName, PR_PATH_SEPARATOR);
+ if ((position == macDirName) || (position == NULL))
+ mdDir->ioVRefNum = 0; // Use application relative searching
+ else {
+ memset(volumeName, 0, sizeof(volumeName));
+ strncpy(volumeName, macDirName, position-macDirName);
+ mdDir->ioVRefNum = GetVolumeRefNumFromName(volumeName);
+ }
+
+ // Get info about the object.
+ PStrFromCStr(macDirName, pascalName);
+ PR_DELETE(macDirName);
+
+ pb.dirInfo.ioNamePtr = pascalName;
+ pb.dirInfo.ioVRefNum = mdDir->ioVRefNum;
+ pb.dirInfo.ioDrDirID = 0;
+ pb.dirInfo.ioFDirIndex = 0;
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ // Are we dealing with a directory?
+ if ((pb.dirInfo.ioFlAttrib & ioDirMask) == 0) {
+ err = dirNFErr;
+ goto ErrorExit;
+ }
+
+ /* This is a directory, store away the pertinent information.
+ ** We post increment. I.e. index is always the nth. item we
+ ** should get on the next call
+ */
+ mdDir->ioDirID = pb.dirInfo.ioDrDirID;
+ mdDir->currentEntryName = NULL;
+ mdDir->ioFDirIndex = 1;
+ return PR_SUCCESS;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return PR_FAILURE;
+}
+
+char *_MD_ReadDir(_MDDir *mdDir, PRIntn flags)
+{
+ // Emulate the Unix readdir() routine.
+
+ // Mac doesnÕt have the concept of .(PR_SKIP_DOT) & ..(PR_SKIP_DOT_DOT)
+
+ OSErr err;
+ CInfoPBRec pb;
+ char *returnedCStr;
+ Str255 pascalName = "\p";
+ PRBool foundEntry;
+
+ PR_ASSERT(mdDir != NULL);
+
+ do {
+
+ // Release the last name read.
+ PR_DELETE(mdDir->currentEntryName);
+ mdDir->currentEntryName = NULL;
+
+ // WeÕve got all the info we need, just get info about this guy.
+ pb.hFileInfo.ioNamePtr = pascalName;
+ pb.hFileInfo.ioVRefNum = mdDir->ioVRefNum;
+ pb.hFileInfo.ioFDirIndex = mdDir->ioFDirIndex;
+ pb.hFileInfo.ioDirID = mdDir->ioDirID;
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ // Convert the Pascal string to a C string (actual allocation occurs in CStrFromPStr)
+ CStrFromPStr(pascalName, &returnedCStr);
+
+ mdDir->currentEntryName = returnedCStr;
+ mdDir->ioFDirIndex++;
+
+ // If it is not a hidden file and the flags did not specify skipping, we are done.
+ if ((flags & PR_SKIP_HIDDEN) && (pb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible))
+ foundEntry = PR_FALSE;
+ else
+ foundEntry = PR_TRUE;
+
+ } while (!foundEntry);
+
+ return (mdDir->currentEntryName);
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return NULL;
+}
+
+
+void _MD_CloseDir(_MDDir *mdDir)
+{
+ // Emulate the Unix closedir() routine
+
+ PR_DELETE(mdDir->currentEntryName);
+}
+
+PRInt32 _MD_MkDir(char *unixPath, PRIntn mode)
+{
+ HFileParam fpb;
+ Str255 pascalName = "\p";
+ char *cMacPath = NULL;
+ OSErr err;
+
+ #pragma unused (mode) // Mode is ignored on the Mac
+
+ if (unixPath) {
+ err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
+ if (err != noErr)
+ goto ErrorExit;
+
+ PStrFromCStr(cMacPath, pascalName);
+ PR_DELETE(cMacPath);
+ fpb.ioNamePtr = pascalName;
+ fpb.ioVRefNum = 0;
+ fpb.ioDirID = 0L;
+
+ err = PBDirCreateSync((HParmBlkPtr)&fpb);
+ if (err != noErr)
+ goto ErrorExit;
+ }
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+PRInt32 _MD_Delete(char *unixPath)
+{
+ HFileParam fpb;
+ Str255 pascalName = "\p";
+ char *cMacPath = NULL;
+ OSErr err;
+
+ if (unixPath) {
+ err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
+ if (err != noErr)
+ goto ErrorExit;
+
+ PStrFromCStr(cMacPath, pascalName);
+ PR_DELETE(cMacPath);
+ fpb.ioNamePtr = pascalName;
+ fpb.ioVRefNum = 0;
+ fpb.ioDirID = 0L;
+
+ err = PBHDeleteSync((HParmBlkPtr)&fpb);
+ if (err != noErr)
+ goto ErrorExit;
+ }
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+PRInt32 _MD_Rename(char *fromUnixPath, char *toUnixPath)
+{
+ OSErr err;
+ FSSpec fromSpec;
+ FSSpec toSpec;
+ FSSpec destDirSpec;
+ FSSpec beforeRenameSpec;
+
+ if (fromUnixPath && toUnixPath) {
+ err = ConvertUnixPathToFSSpec(fromUnixPath, &fromSpec);
+ if (err != noErr)
+ goto ErrorExit;
+
+ err = ConvertUnixPathToFSSpec(toUnixPath, &toSpec);
+ if (err != noErr && err != fnfErr)
+ goto ErrorExit;
+
+ /* make an FSSpec for the destination directory */
+ err = FSMakeFSSpec(toSpec.vRefNum, toSpec.parID, nil, &destDirSpec);
+ if (err != noErr) /* parent directory must exist */
+ goto ErrorExit;
+
+ // move it to the directory specified
+ err = FSpCatMove(&fromSpec, &destDirSpec);
+ if (err != noErr)
+ goto ErrorExit;
+
+ // make a new FSSpec for the file or directory in its new location
+ err = FSMakeFSSpec(toSpec.vRefNum, toSpec.parID, fromSpec.name, &beforeRenameSpec);
+ if (err != noErr)
+ goto ErrorExit;
+
+ // rename the file or directory
+ err = FSpRename(&beforeRenameSpec, toSpec.name);
+ if (err != noErr)
+ goto ErrorExit;
+
+ } else {
+ err = paramErr;
+ goto ErrorExit;
+ }
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+#define kWriteAccessAllowed (0x100)
+PRInt32 _MD_Access(char *unixPath, int amode)
+{
+ //
+ // Emulate the Unix access routine
+ //
+
+ OSErr err;
+ CInfoPBRec pb;
+ FCBPBRec fcbpb;
+ char *cMacPath = NULL;
+ Str255 pascalMacPath;
+ struct stat info;
+
+ // Convert to a Mac style path
+ err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
+ if (err != noErr)
+ goto ErrorExit;
+
+ err = stat(cMacPath, &info);
+ if (err != noErr)
+ goto ErrorExit;
+
+
+ // If all weÕre doing is checking for the existence of the file, weÕre out of here.
+ // On the Mac, if a file exists, you can read from it.
+ // This doesnÕt handle remote AppleShare volumes. Does it need to?
+ if ((amode == PR_ACCESS_EXISTS) || (amode == PR_ACCESS_READ_OK)) {
+ goto success;
+ }
+
+ PStrFromCStr(cMacPath, pascalMacPath);
+
+ pb.hFileInfo.ioNamePtr = pascalMacPath;
+ pb.hFileInfo.ioVRefNum = info.st_dev;
+ pb.hFileInfo.ioDirID = 0;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+ // Check out all the access permissions.
+
+ if (amode == PR_ACCESS_WRITE_OK) {
+ fcbpb.ioNamePtr = NULL;
+ fcbpb.ioVRefNum = pb.hFileInfo.ioVRefNum;
+ fcbpb.ioRefNum = pb.hFileInfo.ioFRefNum;
+ fcbpb.ioFCBIndx = 0;
+
+ err = PBGetFCBInfoSync(&fcbpb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ /* Look at Inside Mac IV-180 */
+ if ((fcbpb.ioFCBFlags & kWriteAccessAllowed) == 0) {
+ err = permErr;
+ goto ErrorExit;
+ }
+ }
+
+success:
+ PR_DELETE(cMacPath);
+ return 0;
+
+ErrorExit:
+ if (cMacPath != NULL)
+ PR_DELETE(cMacPath);
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+PRInt32 _MD_GetFileInfo(char *unixPath, PRFileInfo *info)
+{
+ CInfoPBRec pb;
+ OSErr err;
+ char *cMacPath = NULL;
+ Str255 pascalMacPath;
+ PRTime oneMillion, dateInMicroSeconds;
+
+ // Convert to a Mac style path
+ err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
+ if (err != noErr)
+ goto ErrorExit;
+
+ PStrFromCStr(cMacPath, pascalMacPath);
+ PR_DELETE(cMacPath);
+
+ pb.hFileInfo.ioNamePtr = pascalMacPath;
+ pb.hFileInfo.ioVRefNum = 0;
+ pb.hFileInfo.ioDirID = 0;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ if (pb.hFileInfo.ioFlAttrib & ioDirMask) {
+ info->type = PR_FILE_DIRECTORY;
+ info->size = 0;
+ } else {
+ info->type = PR_FILE_FILE;
+ info->size = pb.hFileInfo.ioFlLgLen + pb.hFileInfo.ioFlRLgLen;
+ }
+
+ pb.hFileInfo.ioFlCrDat -= gJanuaryFirst1970Seconds;
+ LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlCrDat);
+ LL_I2L(oneMillion, PR_USEC_PER_SEC);
+ LL_MUL(info->creationTime, oneMillion, dateInMicroSeconds);
+
+ pb.hFileInfo.ioFlMdDat -= gJanuaryFirst1970Seconds;
+ LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlMdDat);
+ LL_MUL(info->modifyTime, oneMillion, dateInMicroSeconds);
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+PRInt32 _MD_GetOpenFileInfo(const PRFileDesc *fd, PRFileInfo *info)
+{
+ OSErr err;
+ FCBPBRec fcbpb;
+ CInfoPBRec pb;
+ Str255 pascalMacPath;
+ PRTime oneMillion, dateInMicroSeconds;
+
+ fcbpb.ioNamePtr = pascalMacPath;
+ fcbpb.ioVRefNum = 0;
+ fcbpb.ioRefNum = fd->secret->md.osfd;
+ fcbpb.ioFCBIndx = 0;
+
+ err = PBGetFCBInfoSync(&fcbpb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ info->type = PR_FILE_FILE;
+ info->size = fcbpb.ioFCBEOF;
+
+ pb.hFileInfo.ioNamePtr = pascalMacPath;
+ pb.hFileInfo.ioVRefNum = fcbpb.ioFCBVRefNum;
+ pb.hFileInfo.ioDirID = fcbpb.ioFCBParID;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ pb.hFileInfo.ioFlCrDat -= gJanuaryFirst1970Seconds;
+ LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlCrDat);
+ LL_I2L(oneMillion, PR_USEC_PER_SEC);
+ LL_MUL(info->creationTime, oneMillion, dateInMicroSeconds);
+
+ pb.hFileInfo.ioFlMdDat -= gJanuaryFirst1970Seconds;
+ LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlMdDat);
+ LL_MUL(info->modifyTime, oneMillion, dateInMicroSeconds);
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+PRInt32 _MD_Stat(const char *path, struct stat *buf)
+{
+ OSErr err;
+ char *macFileName = NULL;
+
+ err = ConvertUnixPathToMacPath(path, &macFileName);
+ if (err != noErr)
+ goto ErrorExit;
+
+ err = stat(macFileName, buf);
+ if (err != noErr)
+ goto ErrorExit;
+
+ PR_DELETE(macFileName);
+
+ return 0;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return -1;
+}
+
+PRStatus _MD_LockFile(PRInt32 fd)
+{
+ OSErr err;
+ FCBPBRec fcbpb;
+ HFileParam fpb;
+ Str255 pascalName;
+
+ fcbpb.ioNamePtr = pascalName;
+ fcbpb.ioVRefNum = 0;
+ fcbpb.ioRefNum = fd;
+ fcbpb.ioFCBIndx = 0;
+
+ err = PBGetFCBInfoSync(&fcbpb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ fpb.ioCompletion = NULL;
+ fpb.ioNamePtr = pascalName;
+ fpb.ioVRefNum = fcbpb.ioFCBVRefNum;
+ fpb.ioDirID = fcbpb.ioFCBParID;
+
+ err = PBHSetFLockSync((HParmBlkPtr)&fpb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ return PR_SUCCESS;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_TLockFile(PRInt32 fd)
+{
+ return (_MD_LockFile(fd));
+}
+
+PRStatus _MD_UnlockFile(PRInt32 fd)
+{
+ OSErr err;
+ FCBPBRec fcbpb;
+ HFileParam fpb;
+ Str255 pascalName;
+
+ fcbpb.ioNamePtr = pascalName;
+ fcbpb.ioVRefNum = 0;
+ fcbpb.ioRefNum = fd;
+ fcbpb.ioFCBIndx = 0;
+
+ err = PBGetFCBInfoSync(&fcbpb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ fpb.ioCompletion = NULL;
+ fpb.ioNamePtr = pascalName;
+ fpb.ioVRefNum = fcbpb.ioFCBVRefNum;
+ fpb.ioDirID = fcbpb.ioFCBParID;
+
+ err = PBHRstFLockSync((HParmBlkPtr)&fpb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ return PR_SUCCESS;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return PR_FAILURE;
+}
+
+void SetLogFileTypeCreator(const char *logFile)
+{
+ HParamBlockRec pb;
+ OSErr err;
+ Str31 pName;
+
+ PStrFromCStr(logFile, pName);
+ pb.fileParam.ioCompletion = nil;
+ pb.fileParam.ioNamePtr = pName;
+ pb.fileParam.ioVRefNum = 0;
+ pb.fileParam.ioFDirIndex = 0;
+ pb.fileParam.ioDirID = 0;
+ err = PBHGetFInfoSync(&pb);
+ PR_ASSERT(err == noErr);
+
+ pb.fileParam.ioDirID = 0;
+ pb.fileParam.ioFlFndrInfo.fdType = 'TEXT';
+ pb.fileParam.ioFlFndrInfo.fdCreator = 'ttxt';
+ err = PBHSetFInfoSync(&pb);
+ PR_ASSERT(err == noErr);
+}
+
+#if DEVELOPER_DEBUG
+PR_IMPLEMENT (void)
+SetupMacPrintfLog(char *logFile)
+{
+ /*
+ * We do _PR_InitLog() twice. The first to force the implicit initialization which
+ * will set logging to highest levels in _MD_EARLY_INIT. Then, change the env variable
+ * to disable kernel logging and call _PR_InitLog() again to make it effective. Since
+ * we are using logging to log test program output, we disable kernel logging to avoid
+ * all Kernel logging output.
+ */
+#ifdef PR_INTERNAL_LOGGING
+ _PR_InitLog();
+ _MD_PutEnv("NSPR_LOG_MODULES=clock:0,cmon:0,io:0,mon:0,linker:0,cvar:0,sched:0,thread:0");
+ _PR_InitLog();
+#endif
+ PR_ASSERT(PR_SetLogFile(logFile) == PR_TRUE);
+
+ SetLogFileTypeCreator(logFile);
+}
+#endif
+
+
+/*
+********************** Old name related stuff that is unchanged. **********************
+*/
+
+#if !defined(MAC_NSPR_STANDALONE)
+
+short GetVolumeRefNumFromName(const char *cTgtVolName)
+{
+ OSErr err;
+ Str32 pVolName;
+ char *cVolName = NULL;
+ HParamBlockRec hPB;
+ short refNum = 0;
+
+ hPB.volumeParam.ioVolIndex = 0;
+ hPB.volumeParam.ioNamePtr = pVolName;
+ do {
+ hPB.volumeParam.ioVolIndex++;
+ err = PBHGetVInfoSync(&hPB);
+ CStrFromPStr(pVolName, &cVolName);
+ if (strcmp(cTgtVolName, cVolName) == 0) {
+ refNum = hPB.volumeParam.ioVRefNum;
+ PR_DELETE(cVolName);
+ break;
+ }
+ PR_DELETE(cVolName);
+ } while (err == noErr);
+
+ return refNum;
+}
+
+static OSErr CreateMacPathFromUnixPath(const char *unixPath, char **macPath)
+{
+ // Given a Unix style path with '/' directory separators, this allocates
+ // a path with Mac style directory separators in the path.
+ //
+ // It does not do any special directory translation; use ConvertUnixPathToMacPath
+ // for that.
+
+ const char *src;
+ char *tgt;
+ OSErr err = noErr;
+
+ PR_ASSERT(unixPath != nil);
+ if (nil == unixPath) {
+ err = paramErr;
+ goto exit;
+ }
+
+ // If unixPath is a zero-length string, we copy ":" into
+ // macPath, so we need a minimum of two bytes to handle
+ // the case of ":".
+ *macPath = malloc(strlen(unixPath) + 2); // Will be enough extra space.
+ require_action (*macPath != NULL, exit, err = memFullErr;);
+
+ src = unixPath;
+ tgt = *macPath;
+
+ if (PL_strchr(src, PR_DIRECTORY_SEPARATOR) == src) // If weÕre dealing with an absolute
+ src++; // path, skip the separator
+ else
+ *(tgt++) = PR_PATH_SEPARATOR;
+
+ if (PL_strstr(src, UNIX_THIS_DIRECTORY_STR) == src) // If it starts with /
+ src += 2; // skip it.
+
+ while (*src)
+ { // deal with the rest of the path
+ if (PL_strstr(src, UNIX_PARENT_DIRECTORY_STR) == src) { // Going up?
+ *(tgt++) = PR_PATH_SEPARATOR; // simply add an extra colon.
+ src +=3;
+ }
+ else if (*src == PR_DIRECTORY_SEPARATOR) { // Change the separator
+ *(tgt++) = PR_PATH_SEPARATOR;
+ src++;
+ }
+ else
+ *(tgt++) = *(src++);
+ }
+
+ *tgt = NULL; // make sure itÕs null terminated.
+
+exit:
+ return err;
+}
+
+
+static ProcessInfoRec gNavigatorProcInfo;
+static FSSpec gGutsFolder;
+static FSSpec gNetscapeFolder;
+
+static OSErr SetupRequiredFSSpecs(void)
+{
+ OSErr err;
+ CInfoPBRec pb;
+ ProcessSerialNumber curPSN = {0, kCurrentProcess};
+
+ gNavigatorProcInfo.processInfoLength = sizeof(ProcessInfoRec);
+ gNavigatorProcInfo.processName = NULL;
+ gNavigatorProcInfo.processAppSpec = &gNetscapeFolder;
+
+ err = GetProcessInformation (&curPSN, &gNavigatorProcInfo);
+ if (err != noErr)
+ goto ErrorExit;
+
+ /* guts folder resides at the same place as the app file itself */
+ gGutsFolder = gNetscapeFolder;
+ /* How else do we do this hack???
+ * Should NSPR have a string resource for this ?
+ */
+ GetIndString( gGutsFolder.name, 300, 34);
+
+ /*
+ * vRefNum and parentDirID are now set up correctly for the app file itself.
+ * parentDirID is the Netscape Folder's ID. Then Find it's parent ID to
+ * set up the FSSpec and its own name.
+ */
+
+ pb.dirInfo.ioCompletion = NULL;
+ pb.dirInfo.ioNamePtr = gNetscapeFolder.name;
+ pb.dirInfo.ioVRefNum = gNetscapeFolder.vRefNum;
+ pb.dirInfo.ioFDirIndex = -1;
+ pb.dirInfo.ioDrDirID = gNetscapeFolder.parID;
+
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr)
+ goto ErrorExit;
+
+ gNetscapeFolder.parID = pb.dirInfo.ioDrParID;
+
+ return noErr;
+
+ErrorExit:
+ return err;
+}
+
+static OSErr FindGutsFolder(FSSpec *foundSpec)
+{
+ OSErr err;
+
+ if (gNavigatorProcInfo.processInfoLength == 0) { /* Uninitialized? */
+ err = SetupRequiredFSSpecs();
+ if (err != noErr)
+ goto ErrorExit;
+ }
+
+ *foundSpec = gGutsFolder;
+
+ return noErr;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ return err;
+}
+
+static OSErr FindNetscapeFolder(FSSpec *foundSpec)
+{
+ OSErr err;
+
+ if (gNavigatorProcInfo.processInfoLength == 0) { /* Uninitialized? */
+ err = SetupRequiredFSSpecs();
+ if (err != noErr)
+ goto ErrorExit;
+ }
+
+ *foundSpec = gNetscapeFolder;
+
+ return noErr;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ return err;
+}
+
+
+PR_IMPLEMENT (OSErr)
+ConvertUnixPathToMacPath(const char *unixPath, char **macPath)
+{
+ OSErr err = noErr;
+
+ // ******** HACK ALERT ********
+ //
+ // Java really wants long file names (>31 chars). We truncate file names
+ // greater than 31 characters long. Truncation is from the middle.
+ //
+ // Convert UNIX style path names (with . and / separators) into a Macintosh
+ // style path (with :).
+ //
+ // There are also a couple of special paths that need to be dealt with
+ // by translating them to the appropriate Mac special folders. These include:
+ //
+ // /usr/tmp/file => {TempFolder}file
+ //
+ // The file conversions we need to do are as follows:
+ //
+ // file => file
+ // dir/file => :dir:file
+ // ./file => file
+ // ../file => ::file
+ // ../dir/file => ::dir:file
+ // /file => ::BootDrive:file
+ // /dir/file => ::BootDrive:dir:file
+
+
+ if (!strcmp(unixPath, "."))
+ {
+ *macPath = malloc(sizeof(":"));
+ if (*macPath == NULL)
+ err = memFullErr;
+ (*macPath)[0] = ':';
+ (*macPath)[1] = '\0';
+ }
+ else
+
+ if (*unixPath != PR_DIRECTORY_SEPARATOR) { // Not root relative, just convert it.
+ err = CreateMacPathFromUnixPath(unixPath, macPath);
+ }
+
+ else {
+ // WeÕre root-relative. This is either a special Unix directory, or a
+ // full path (which weÕll support on the Mac since they might be generated).
+ // This is not condoning the use of full-paths on the Macintosh for file
+ // specification.
+
+ FSSpec foundSpec;
+ short pathBufferSize;
+#if DEBUG
+ char *temp;
+#endif
+ int tempLen;
+
+ // Are we dealing with the temp folder?
+ if ((strncmp(unixPath, "/usr/tmp", strlen("/usr/tmp")) == 0) ||
+ ((strncmp(unixPath, "/tmp", strlen("/tmp")) == 0))) {
+ CInfoPBRec pb;
+
+ unixPath = PL_strchr(unixPath, PR_DIRECTORY_SEPARATOR);
+ if (strncmp(unixPath, "/tmp", strlen("/tmp")) == 0) // skip past temp spec
+ unixPath += 5;
+ else
+ unixPath += 9;
+
+ err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, // Create if needed
+ &foundSpec.vRefNum, &foundSpec.parID);
+ if (err == noErr) {
+ pb.dirInfo.ioCompletion = NULL;
+ pb.dirInfo.ioNamePtr = foundSpec.name;
+ pb.dirInfo.ioVRefNum = foundSpec.vRefNum;
+ pb.dirInfo.ioFDirIndex = -1;
+ pb.dirInfo.ioDrDirID = foundSpec.parID;
+
+ err = PBGetCatInfoSync(&pb);
+ foundSpec.parID = pb.dirInfo.ioDrParID;
+ }
+ }
+
+ else if (!strncmp(unixPath, "/usr/local/netscape/", (tempLen = strlen("/usr/local/netscape/")))) {
+
+ unixPath += tempLen;
+
+ if (!strncmp(unixPath, "RequiredGuts/", (tempLen = strlen("RequiredGuts/"))))
+ {
+ unixPath += tempLen;
+ err = FindGutsFolder(&foundSpec);
+ }
+ else if (!strncmp(unixPath, "bin/", (tempLen = strlen("bin/"))))
+ {
+ unixPath += tempLen;
+ err = FindNetscapeFolder(&foundSpec);
+ }
+ else if (*unixPath == '\0')
+ {
+ // it's /usr/local/netscape
+ err = FindGutsFolder(&foundSpec);
+ }
+
+ }
+
+ else {
+ // This is a root relative directory, weÕll just convert the whole thing.
+ err = CreateMacPathFromUnixPath(unixPath, macPath);
+ goto Exit_ConvertUnixPathToMacPath;
+ }
+
+
+
+ // WeÕre dealing with a special folder
+ if (err == noErr)
+ {
+ Handle hPathStr;
+ // Get the path to the root-relative directory
+ err = FSpGetFullPath(&foundSpec, &pathBufferSize, &hPathStr); // NewHandle's hPathStr
+
+ if (noErr == err)
+ {
+ // convert handle to c-string
+ // add one for NULL termination
+ // pathBufferSize is now one greater than the length of the string
+ pathBufferSize++;
+
+ *macPath = (char*) malloc(sizeof(char) * pathBufferSize);
+ (*macPath)[pathBufferSize - 1] = '\0';
+ BlockMoveData(*hPathStr, *macPath, pathBufferSize - 1);
+
+ DisposeHandle(hPathStr);
+ }
+ }
+
+ if (err == noErr)
+ {
+ UInt32 unixPathLeft;
+ UInt32 macPathLen;
+
+ unixPathLeft = strlen(unixPath);
+ macPathLen = strlen(*macPath);
+
+
+ // copy over the remaining file name, converting
+ if (pathBufferSize - 1 < macPathLen + unixPathLeft)
+ {
+ // need to grow string
+ *macPath = realloc(*macPath, macPathLen + unixPathLeft + 1);
+ err = (*macPath == NULL ? memFullErr : noErr);
+ }
+
+ if (err == noErr)
+ {
+ // carefully remove the '/''s out of the unix path. If we see an "escaped" /
+ // we will leave it in there, otherwise we take it out and replace it with a :
+ // we have to do this before we convert to a mac-path, so we can tell what is
+ // really a path separator and what is in the name of a file or directory
+ // Make sure that all of the /Õs are :Õs in the final pathname
+ // effectively we do a
+ // strcat(*macPath, unixPath); while replace all occurrences of / with : in unixPath
+ char* dp;
+ const char* sp;
+
+ sp = unixPath;
+ dp = *macPath + macPathLen;
+
+ for (;*sp != '\0'; sp++, dp++)
+ {
+ if (*sp == PR_DIRECTORY_SEPARATOR)
+ {
+ // if we can look at the previous character
+ if (sp > unixPath)
+ {
+ // check to see if previous character is an escape
+ if (sp[-1] == '\\')
+ {
+ // leave it in, and cycle
+ continue;
+ }
+ else
+ {
+ *dp = PR_PATH_SEPARATOR;
+ }
+ }
+ else
+ *dp = PR_PATH_SEPARATOR;
+ }
+ else
+ {
+ // just copy;
+ *dp = *sp;
+ }
+ }
+
+ *dp = '\0'; // NULL terminate *macPath
+ }
+#if DEBUG
+ // we used to check here, now we check above, we leave this in
+ // the debug build to make sure we didn't screw up
+ // Make sure that all of the /Õs are :Õs in the final pathname
+ for (temp = *macPath + strlen(*macPath) - strlen(unixPath); *temp != '\0'; temp++) {
+
+ if (*temp == PR_DIRECTORY_SEPARATOR)
+ {
+ DebugStr("\pFound a slash");
+ *temp = PR_PATH_SEPARATOR;
+ }
+ }
+#endif
+ }
+ }
+
+
+Exit_ConvertUnixPathToMacPath:
+
+ return err;
+}
+
+// Hey! Before you delete this "hack" you should look at how it's being
+// used by sun-java/netscape/applet/appletStubs.c.
+PR_IMPLEMENT (OSErr)
+ConvertMacPathToUnixPath(const char *macPath, char **unixPath)
+{
+ // *** HACK ***
+ // Get minimal version working
+
+ char *unixPathPtr;
+
+ *unixPath = malloc(strlen(macPath) + 2); // Add one for the front slash, one for null
+ if (*unixPath == NULL)
+ return (memFullErr);
+
+ unixPathPtr = *unixPath;
+
+ *unixPathPtr++ = PR_DIRECTORY_SEPARATOR;
+
+ do {
+ // Translate all colons to slashes
+ if (*macPath == PR_PATH_SEPARATOR)
+ *unixPathPtr = PR_DIRECTORY_SEPARATOR;
+ else
+ *unixPathPtr = *macPath;
+
+ unixPathPtr++;
+ macPath++;
+ } while (*macPath != NULL);
+
+ // Terminate the string
+ *unixPathPtr = '\0';
+
+ return (noErr);
+}
+
+OSErr
+ConvertUnixPathToFSSpec(const char *unixPath, FSSpec *fileSpec)
+{
+ char* macPath;
+ OSErr convertError;
+ int len;
+
+ convertError = ConvertUnixPathToMacPath(unixPath, &macPath);
+ if (convertError != noErr)
+ return convertError;
+
+ len = strlen(macPath);
+
+ if (*macPath == PR_PATH_SEPARATOR)
+ {
+ if (len < sizeof(Str255))
+ {
+ short vRefNum;
+ long dirID;
+ Str255 pascalMacPath;
+
+ convertError = HGetVol(NULL, &vRefNum, &dirID);
+ if (convertError == noErr)
+ {
+ PStrFromCStr(macPath, pascalMacPath);
+ convertError = FSMakeFSSpec(vRefNum, dirID, pascalMacPath, fileSpec);
+ }
+ }
+ else
+ convertError = paramErr;
+ }
+ else
+ {
+ convertError = FSpLocationFromFullPath(len, macPath, fileSpec);
+ if (convertError == fnfErr)
+ {
+ CInfoPBRec pb;
+ Str255 pascalMacPath;
+ OSErr err;
+
+ PStrFromCStr(macPath, pascalMacPath);
+ /*
+ FSpLocationFromFullPath does not work for directories unless there is
+ a ":" at the end. We will make sure of an existence of a directory.
+ If so, the returned fileSpec is valid from FSpLocationFromFullPath eventhough
+ it returned an error.
+ */
+ pb.hFileInfo.ioNamePtr = pascalMacPath;
+ pb.hFileInfo.ioVRefNum = 0;
+ pb.hFileInfo.ioDirID = 0;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&pb);
+ if (err == noErr)
+ convertError = noErr;
+ }
+ }
+
+ free(macPath);
+
+ return (convertError);
+}
+
+
+FILE *_OS_FOPEN(const char *filename, const char *mode)
+{
+ OSErr err = noErr;
+ char *macFileName = NULL;
+ FILE *result;
+
+ err = ConvertUnixPathToMacPath(filename, &macFileName);
+ if (err != noErr)
+ goto ErrorExit;
+
+ result = fopen(macFileName, mode);
+
+ PR_DELETE(macFileName);
+
+ return result;
+
+ErrorExit:
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+ _MD_SetError(err);
+ return NULL;
+}
+
+#else
+
+short GetVolumeRefNumFromName(const char *cTgtVolName)
+{
+ OSErr err;
+ Str32 pVolName;
+ char *cVolName = NULL;
+ HParamBlockRec hPB;
+ short refNum = 0;
+
+ hPB.volumeParam.ioVolIndex = 0;
+ hPB.volumeParam.ioNamePtr = pVolName;
+ do {
+ hPB.volumeParam.ioVolIndex++;
+ err = PBHGetVInfoSync(&hPB);
+ CStrFromPStr(pVolName, &cVolName);
+ if (strcmp(cTgtVolName, cVolName) == 0) {
+ refNum = hPB.volumeParam.ioVRefNum;
+ PR_DELETE(cVolName);
+ break;
+ }
+ PR_DELETE(cVolName);
+ } while (err == noErr);
+
+ return refNum;
+}
+
+
+
+static OSErr GetFullPath(short vRefNum, long dirID, char **fullPath, int *strSize)
+{
+ Str255 pascalDirName;
+ char cDirName[256];
+ char *tmpPath = NULL; // needed since sprintf isnÕt safe
+ CInfoPBRec myPB;
+ OSErr err = noErr;
+
+
+ // get the full path of the temp folder.
+ *strSize = 256;
+ *fullPath = NULL;
+ *fullPath = malloc(*strSize); // How big should this thing be?
+ require_action (*fullPath != NULL, errorExit, err = memFullErr;);
+
+ tmpPath = malloc(*strSize);
+ require_action (tmpPath != NULL, errorExit, err = memFullErr;);
+
+ strcpy(*fullPath, ""); // Clear C result
+ strcpy(tmpPath, "");
+ pascalDirName[0] = 0; // Clear Pascal intermediate string
+
+ myPB.dirInfo.ioNamePtr = &pascalDirName[0];
+ myPB.dirInfo.ioVRefNum = vRefNum;
+ myPB.dirInfo.ioDrParID = dirID;
+ myPB.dirInfo.ioFDirIndex = -1; // Getting info about
+
+ do {
+ myPB.dirInfo.ioDrDirID = myPB.dirInfo.ioDrParID;
+
+ err = PBGetCatInfoSync(&myPB);
+ require(err == noErr, errorExit);
+
+ // Move the name into C domain
+ memcpy(&cDirName, &pascalDirName, 256);
+ p2cstr((unsigned char *)&cDirName); // Changes in place!
+
+ if ((strlen(cDirName) + strlen(*fullPath)) > *strSize) {
+ // We need to grow the string, do it in 256 byte chunks
+ (*strSize) += 256;
+ *fullPath = PR_REALLOC(*fullPath, *strSize);
+ require_action (*fullPath != NULL, errorExit, err = memFullErr;);
+
+ tmpPath = PR_REALLOC(tmpPath, *strSize);
+ require_action (tmpPath != NULL, errorExit, err = memFullErr;);
+ }
+ sprintf(tmpPath, "%s:%s", cDirName, *fullPath);
+ strcpy(*fullPath, tmpPath);
+ } while (myPB.dirInfo.ioDrDirID != fsRtDirID);
+
+ PR_DELETE(tmpPath);
+
+ return noErr;
+
+
+errorExit:
+ PR_DELETE(*fullPath);
+ PR_DELETE(tmpPath);
+
+ return err;
+
+}
+
+static OSErr CreateMacPathFromUnixPath(const char *unixPath, char **macPath)
+{
+ // Given a Unix style path with '/' directory separators, this allocates
+ // a path with Mac style directory separators in the path.
+ //
+ // It does not do any special directory translation; use ConvertUnixPathToMacPath
+ // for that.
+
+ const char *src;
+ char *tgt;
+ OSErr err = noErr;
+
+ PR_ASSERT(unixPath != nil);
+ if (nil == unixPath) {
+ err = paramErr;
+ goto exit;
+ }
+
+ // If unixPath is a zero-length string, we copy ":" into
+ // macPath, so we need a minimum of two bytes to handle
+ // the case of ":".
+ *macPath = malloc(strlen(unixPath) + 2); // Will be enough extra space.
+ require_action (*macPath != NULL, exit, err = memFullErr;);
+
+ src = unixPath;
+ tgt = *macPath;
+
+ if (PL_strchr(src, PR_DIRECTORY_SEPARATOR) == src) // If weÕre dealing with an absolute
+ src++; // path, skip the separator
+ else
+ *(tgt++) = PR_PATH_SEPARATOR;
+
+ if (PL_strstr(src, UNIX_THIS_DIRECTORY_STR) == src) // If it starts with ./
+ src += 2; // skip it.
+
+ while (*src)
+ { // deal with the rest of the path
+ if (PL_strstr(src, UNIX_PARENT_DIRECTORY_STR) == src) { // Going up?
+ *(tgt++) = PR_PATH_SEPARATOR; // simply add an extra colon.
+ src +=3;
+ }
+ else if (*src == PR_DIRECTORY_SEPARATOR) { // Change the separator
+ *(tgt++) = PR_PATH_SEPARATOR;
+ src++;
+ }
+ else
+ *(tgt++) = *(src++);
+ }
+
+ *tgt = NULL; // make sure itÕs null terminated.
+
+exit:
+ return err;
+}
+
+static OSErr ConvertUnixPathToMacPath(const char *unixPath, char **macPath)
+{
+ OSErr err = noErr;
+
+
+ //
+ // Convert UNIX style path names (with . and / separators) into a Macintosh
+ // style path (with :).
+ //
+ // There are also a couple of special paths that need to be dealt with
+ // by translating them to the appropriate Mac special folders. These include:
+ //
+ // /usr/tmp/file => {TempFolder}file
+ //
+ // The file conversions we need to do are as follows:
+ //
+ // file => file
+ // dir/file => :dir:file
+ // ./file => file
+ // ../file => ::file
+ // ../dir/file => ::dir:file
+ // /file => ::BootDrive:file
+ // /dir/file => ::BootDrive:dir:file
+
+
+ if (*unixPath != PR_DIRECTORY_SEPARATOR) { // Not root relative, just convert it.
+ err = CreateMacPathFromUnixPath(unixPath, macPath);
+ }
+
+ else {
+ // WeÕre root-relative. This is either a special Unix directory, or a
+ // full path (which weÕll support on the Mac since they might be generated).
+ // This is not condoning the use of full-paths on the Macintosh for file
+ // specification.
+
+ short foundVRefNum;
+ long foundDirID;
+ int pathBufferSize;
+ char *temp;
+ char isNetscapeDir = false;
+
+ // Are we dealing with the temp folder?
+ if (strncmp(unixPath, "/usr/tmp", strlen("/usr/tmp")) == 0){
+ unixPath += 8;
+ if (*unixPath == PR_DIRECTORY_SEPARATOR)
+ unixPath++; // Skip the slash
+ err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, // Create if needed
+ &foundVRefNum, &foundDirID);
+ }
+
+ if (strncmp(unixPath, "/tmp", strlen("/tmp")) == 0) {
+ unixPath += 4; // Skip the slash
+ if (*unixPath == PR_DIRECTORY_SEPARATOR)
+ unixPath++; // Skip the slash
+ err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, // Create if needed
+ &foundVRefNum, &foundDirID);
+ }
+
+ else if (strncmp(unixPath, "/usr", strlen("/usr")) == 0) {
+
+ int usrNetscapePathLen;
+
+ usrNetscapePathLen = strlen("/usr/local/netscape/");
+
+ if (strncmp(unixPath, "/usr/local/netscape/", usrNetscapePathLen) == 0) {
+ unixPath += usrNetscapePathLen;
+// err = FindPreferencesFolder(&foundVRefNum, &foundDirID);
+ err = paramErr;
+ isNetscapeDir = true;
+ }
+
+ else {
+ dprintf("Unable to translate Unix file path %s to Mac path\n", unixPath);
+ err = -1;
+ goto Exit_ConvertUnixPathToMacPath;
+ }
+
+ }
+
+ else {
+ // This is a root relative directory, weÕll just convert the whole thing.
+ err = CreateMacPathFromUnixPath(unixPath, macPath);
+ goto Exit_ConvertUnixPathToMacPath;
+ }
+
+ // WeÕre dealing with a special folder
+ if (err == noErr)
+ // Get the path to the root-relative directory
+ err = GetFullPath(foundVRefNum, foundDirID, macPath, &pathBufferSize); // mallocs macPath
+
+ if (err == noErr){
+
+ // copy over the remaining file name, converting
+ if (pathBufferSize < (strlen(*macPath) + strlen(unixPath))) {
+ // need to grow string
+ *macPath = PR_REALLOC(*macPath, (strlen(*macPath) + strlen(unixPath) +
+ (isNetscapeDir ? strlen("Netscape Ä:") : 0)));
+ err = (*macPath == NULL ? memFullErr : noErr);
+ }
+
+ if (isNetscapeDir)
+ strcat(*macPath, "Netscape Ä:");
+
+ if (err == noErr)
+ strcat(*macPath, unixPath);
+
+ // Make sure that all of the /Õs are :Õs in the final pathname
+
+ for (temp = *macPath + strlen(*macPath) - strlen(unixPath); *temp != '\0'; temp++) {
+ if (*temp == PR_DIRECTORY_SEPARATOR)
+ *temp = PR_PATH_SEPARATOR;
+ }
+
+ }
+ }
+
+
+Exit_ConvertUnixPathToMacPath:
+
+ return err;
+}
+
+OSErr
+ConvertUnixPathToFSSpec(const char *unixPath, FSSpec *fileSpec)
+{
+ char* macPath;
+ OSErr convertError;
+ int len;
+
+ convertError = ConvertUnixPathToMacPath(unixPath, &macPath);
+ if (convertError != noErr)
+ return convertError;
+
+ len = strlen(macPath);
+
+ if (*macPath == PR_PATH_SEPARATOR)
+ {
+ if (len < sizeof(Str255))
+ {
+ short vRefNum;
+ long dirID;
+ Str255 pascalMacPath;
+
+ convertError = HGetVol(NULL, &vRefNum, &dirID);
+ if (convertError == noErr)
+ {
+ PStrFromCStr(macPath, pascalMacPath);
+ convertError = FSMakeFSSpec(vRefNum, dirID, pascalMacPath, fileSpec);
+ }
+ }
+ else
+ convertError = paramErr;
+ }
+ else
+ {
+ convertError = FSpLocationFromFullPath(len, macPath, fileSpec);
+ }
+
+ free(macPath);
+
+ return (convertError);
+}
+
+
+#endif
+
+/*
+ **********************************************************************
+ *
+ * Memory-mapped files are not implementable on the Mac.
+ *
+ **********************************************************************
+ */
+
+PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
+{
+#pragma unused (fmap, size)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRInt32 _MD_GetMemMapAlignment(void)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+}
+
+void * _MD_MemMap(
+ PRFileMap *fmap,
+ PROffset64 offset,
+ PRUint32 len)
+{
+#pragma unused (fmap, offset, len)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
+{
+#pragma unused (addr, len)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_CloseFileMap(PRFileMap *fmap)
+{
+#pragma unused (fmap)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.h
new file mode 100644
index 00000000..06b85a9a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macio.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef macio_h__
+#define macio_h__
+
+
+PR_BEGIN_EXTERN_C
+
+OSErr ConvertUnixPathToMacPath(const char *, char **);
+OSErr ConvertUnixPathToFSSpec(const char *unixPath, FSSpec *fileSpec);
+
+PR_END_EXTERN_C
+
+
+#endif /* macio_h__ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macrng.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macrng.c
new file mode 100644
index 00000000..c869cc3d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macrng.c
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/* XXX are all these headers required for a call to TickCount()? */
+#include <Events.h>
+#include <OSUtils.h>
+#include <QDOffscreen.h>
+#include <PPCToolbox.h>
+#include <Processes.h>
+#include <LowMem.h>
+#include "primpl.h"
+
+extern PRSize _PR_MD_GetRandomNoise( buf, size )
+{
+ uint32 c = TickCount();
+ return _pr_CopyLowBits((void *)buf, size, &c, sizeof(c));
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsocket.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsocket.h
new file mode 100644
index 00000000..7e99faf2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsocket.h
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef macksocket_h___
+#define macksocket_h___
+
+// macsock.h
+// Interface visible to xp code
+// C socket type definitions and routines
+// from sys/socket.h
+#include <Files.h>
+#include <OpenTptInternet.h> // All the internet typedefs
+#include <utime.h> // For timeval
+/*
+ * sleep and delay conflict with the same in unistd.h from Metrowerks. OT
+ * defines them as
+ *
+ * extern pascal void OTDelay(UInt32 seconds);
+ * extern pascal void OTIdle(void);
+ *
+ * #define sleep(x) OTDelay(x)
+ * #define delay(x) OTDelay(x)
+ */
+
+#undef sleep
+#undef delay
+
+#pragma once
+
+#include "prio.h"
+
+struct sockaddr {
+ unsigned char sa_len; /* total length */
+ unsigned char sa_family; /* address family */
+ char sa_data[14]; /* actually longer; address value */
+};
+
+// from netinet/in.h
+struct in_addr {
+ unsigned long s_addr;
+};
+
+struct sockaddr_in {
+ unsigned char sin_len;
+ unsigned char sin_family; // AF_INET
+ unsigned short sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatiblity */
+};
+
+// Necessary network defines, found by grepping unix headers when XP code would not compile
+#define FIONBIO 1
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+#define IPPROTO_TCP INET_TCP // Default TCP protocol
+#define IPPROTO_UDP INET_UDP // Default UDP protocol
+#define INADDR_ANY kOTAnyInetAddress
+#define SOL_SOCKET XTI_GENERIC // Any type of socket
+#define SO_REUSEADDR IP_REUSEADDR
+#define SO_BROADCAST IP_BROADCAST
+#define MSG_PEEK 0x2 // Just look at a message waiting, donÕt actually read it.
+
+typedef unsigned long u_long;
+
+/* ldap.h has its own definition of fd_set */
+/* select support */
+#if !defined(FD_SET)
+#define NBBY 8
+typedef long fd_mask;
+#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
+
+#ifndef howmany
+#define howmany(x, y) (((x)+((y)-1))/(y))
+#endif
+#define FD_SETSIZE 64
+typedef struct fd_set{
+ fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
+} fd_set;
+
+#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p) memset (p, 0, sizeof(*(p)))
+#endif /* !FD_SET */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned long inet_addr(const char *cp);
+extern char *inet_ntoa(struct in_addr in);
+
+inline unsigned long htonl(unsigned long hostlong) {return hostlong;}
+inline unsigned long ntohl(unsigned long netlong) {return netlong;}
+inline unsigned short ntohs(unsigned short netshort) {return netshort;}
+inline unsigned short htons(unsigned short hostshort) {return hostshort;}
+
+
+// UNIX look-alike routines
+// They make sure that the arguments passed in are valid, and then
+//
+extern struct hostent *macsock_gethostbyaddr(const void *addr, int addrlen, int type);
+
+extern int macsock_socket(int domain, int type, int protocol);
+extern int macsock_ioctl(int sID, unsigned int request, void *value);
+extern int macsock_connect(int sID, struct sockaddr *name, int namelen);
+extern int macsock_write(int sID, const void *buffer, unsigned buflen);
+extern int macsock_read(int sID, void *buf, unsigned nbyte);
+extern int macsock_close(int sID);
+
+extern int macsock_accept(int sID, struct sockaddr *addr, int *addrlen);
+extern int macsock_bind(int sID, const struct sockaddr *name, int namelen);
+extern int macsock_listen(int sID, int backlog);
+
+extern int macsock_shutdown(int sID, int how);
+extern int macsock_getpeername(int sID, struct sockaddr *name, int *namelen);
+extern int macsock_getsockname(int sID, struct sockaddr *name, int *namelen);
+extern int macsock_getsockopt(int sID, int level, int optname, void *optval,int *optlen);
+extern int macsock_setsockopt(int sID, int level, int optname, const void *optval,int optlen);
+extern int macsock_socketavailable(int sID, size_t *bytesAvailable);
+extern int macsock_dup(int sID);
+
+extern int macsock_send(int sID, const void *msg, int len, int flags);
+extern int macsock_sendto(int sID, const void *msg, int len, int flags, struct sockaddr *toAddr, int toLen);
+extern int macsock_recvfrom(int sID, void *buf, int len, int flags, struct sockaddr *from, int *fromLen);
+extern int macsock_recv(int sID, void *buf, int len, int flags);
+
+extern int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+
+
+#define macsock_gethostbyaddr PR_GetHostByAddr
+#define macsock_socket PR_Socket
+#define macsock_connect PR_Connect
+#define macsock_write PR_Write
+#define macsock_read PR_Read
+#define macsock_close PR_Close
+#define macsock_accept PR_Accept
+#define macsock_bind PR_Bind
+#define macsock_listen PR_Listen
+#define macsock_shutdown PR_Shutdown
+#define macsock_getpeername PR_GetPeerName
+#define macsock_getsockname PR_GetSockName
+#define macsock_socketavailable PR_SocketAvailable
+#define macsock_send PR_Send
+#define macsock_sendto PR_SendTo
+#define macsock_recvfrom PR_RecvFrom
+#define macsock_recv PR_Recv
+
+#ifdef __cplusplus
+}
+#endif
+//extern int errno;
+
+/*
+macsock_sendmsg
+macsock_readv
+macsock_writev
+*/
+
+/* New definitions that are not defined in macsock.h in macsock library */
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+extern struct protoent *getprotobyname(const char * name);
+extern struct protoent *getprotobynumber(int number);
+
+extern int gethostname (char *name, int namelen);
+extern struct hostent *gethostbyname(const char * name);
+extern struct hostent *gethostbyaddr(const void *addr, int addrlen, int type);
+
+#define INADDR_LOOPBACK 0x7F000001
+
+#define SO_KEEPALIVE TCP_KEEPALIVE
+#define SO_RCVBUF XTI_RCVBUF
+#define SO_SNDBUF XTI_SNDBUF
+#define SO_LINGER XTI_LINGER /* linger on close if data present */
+
+#define IPPROTO_IP INET_IP
+
+/* Get/Set sock opt until fixed in NSPR 2.0 */
+struct linger {
+ int l_onoff; /* option on/off */
+ int l_linger; /* linger time */
+};
+
+struct ip_mreq {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+#endif /* macksocket_h___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsockotpt.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsockotpt.c
new file mode 100644
index 00000000..b357eea6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macsockotpt.c
@@ -0,0 +1,2321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* This turns on UNIX style errors in OT 1.1 headers */
+#define OTUNIXERRORS 1
+
+#include <string.h>
+
+#include <Gestalt.h>
+#include <Files.h>
+#include <OpenTransport.h>
+#include <OSUtils.h>
+
+#define GESTALT_OPEN_TPT_PRESENT gestaltOpenTptPresentMask
+#define GESTALT_OPEN_TPT_TCP_PRESENT gestaltOpenTptTCPPresentMask
+
+#include <OpenTptInternet.h> // All the internet typedefs
+
+#if (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
+// for some reason Apple removed this typedef.
+typedef struct OTConfiguration OTConfiguration;
+#endif
+
+#include "primpl.h"
+
+typedef enum SndRcvOpCode {
+ kSTREAM_SEND,
+ kSTREAM_RECEIVE,
+ kDGRAM_SEND,
+ kDGRAM_RECEIVE
+} SndRcvOpCode;
+
+static struct {
+ PRLock * lock;
+ InetSvcRef serviceRef;
+ PRThread * thread;
+ void * cookie;
+} dnsContext;
+
+
+static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);
+static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);
+static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);
+
+static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);
+
+void
+WakeUpNotifiedThread(PRThread *thread, OTResult result);
+
+extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);
+extern void DoneWaitingOnThisThread(PRThread *thread);
+
+#if TARGET_CARBON
+OTClientContextPtr clientContext = NULL;
+
+#define INIT_OPEN_TRANSPORT() InitOpenTransportInContext(kInitOTForExtensionMask, &clientContext)
+#define OT_OPEN_INTERNET_SERVICES(config, flags, err) OTOpenInternetServicesInContext(config, flags, err, clientContext)
+#define OT_OPEN_ENDPOINT(config, flags, info, err) OTOpenEndpointInContext(config, flags, info, err, clientContext)
+
+#else
+
+#define INIT_OPEN_TRANSPORT() InitOpenTransport()
+#define OT_OPEN_INTERNET_SERVICES(config, flags, err) OTOpenInternetServices(config, flags, err)
+#define OT_OPEN_ENDPOINT(config, flags, info, err) OTOpenEndpoint(config, flags, info, err)
+#endif /* TARGET_CARBON */
+
+static OTNotifyUPP DNSNotifierRoutineUPP;
+static OTNotifyUPP NotifierRoutineUPP;
+static OTNotifyUPP RawEndpointNotifierRoutineUPP;
+
+void _MD_InitNetAccess()
+{
+ OSErr err;
+ OSStatus errOT;
+ PRBool hasOTTCPIP = PR_FALSE;
+ PRBool hasOT = PR_FALSE;
+ long gestaltResult;
+
+ err = Gestalt(gestaltOpenTpt, &gestaltResult);
+ if (err == noErr)
+ if (gestaltResult & GESTALT_OPEN_TPT_PRESENT)
+ hasOT = PR_TRUE;
+
+ if (hasOT)
+ if (gestaltResult & GESTALT_OPEN_TPT_TCP_PRESENT)
+ hasOTTCPIP = PR_TRUE;
+
+ PR_ASSERT(hasOTTCPIP == PR_TRUE);
+
+ DNSNotifierRoutineUPP = NewOTNotifyUPP(DNSNotifierRoutine);
+ NotifierRoutineUPP = NewOTNotifyUPP(NotifierRoutine);
+ RawEndpointNotifierRoutineUPP = NewOTNotifyUPP(RawEndpointNotifierRoutine);
+
+ errOT = INIT_OPEN_TRANSPORT();
+ PR_ASSERT(err == kOTNoError);
+
+ dnsContext.serviceRef = NULL;
+ dnsContext.lock = PR_NewLock();
+ PR_ASSERT(dnsContext.lock != NULL);
+
+ dnsContext.thread = _PR_MD_CURRENT_THREAD();
+ dnsContext.cookie = NULL;
+
+/* XXX Does not handle absence of open tpt and tcp yet! */
+}
+
+static void _MD_FinishInitNetAccess()
+{
+ OSStatus errOT;
+
+ if (dnsContext.serviceRef)
+ return;
+
+ dnsContext.serviceRef = OT_OPEN_INTERNET_SERVICES(kDefaultInternetServicesPath, NULL, &errOT);
+ if (errOT != kOTNoError) {
+ dnsContext.serviceRef = NULL;
+ return; /* no network -- oh well */
+ }
+
+ PR_ASSERT((dnsContext.serviceRef != NULL) && (errOT == kOTNoError));
+
+ /* Install notify function for DNR Address To String completion */
+ errOT = OTInstallNotifier(dnsContext.serviceRef, DNSNotifierRoutineUPP, &dnsContext);
+ PR_ASSERT(errOT == kOTNoError);
+
+ /* Put us into async mode */
+ errOT = OTSetAsynchronous(dnsContext.serviceRef);
+ PR_ASSERT(errOT == kOTNoError);
+}
+
+
+static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, OTResult result, void * cookie)
+{
+#pragma unused(contextPtr)
+ _PRCPU * cpu = _PR_MD_CURRENT_CPU();
+ OSStatus errOT;
+
+ dnsContext.thread->md.osErrCode = result;
+ dnsContext.cookie = cookie;
+
+ switch (otEvent) {
+ case T_DNRSTRINGTOADDRCOMPLETE:
+ if (_PR_MD_GET_INTSOFF()) {
+ dnsContext.thread->md.missedIONotify = PR_TRUE;
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ } else {
+ DoneWaitingOnThisThread(dnsContext.thread);
+ }
+ break;
+
+ case kOTProviderWillClose:
+ errOT = OTSetSynchronous(dnsContext.serviceRef);
+ // fall through to kOTProviderIsClosed case
+
+ case kOTProviderIsClosed:
+ errOT = OTCloseProvider((ProviderRef)dnsContext.serviceRef);
+ dnsContext.serviceRef = nil;
+
+ if (_PR_MD_GET_INTSOFF()) {
+ dnsContext.thread->md.missedIONotify = PR_TRUE;
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ } else {
+ DoneWaitingOnThisThread(dnsContext.thread);
+ }
+ break;
+
+ default: // or else we don't handle the event
+ PR_ASSERT(otEvent==NULL);
+
+ }
+ // or else we don't handle the event
+
+ SignalIdleSemaphore();
+}
+
+
+static void macsock_map_error(OSStatus err)
+{
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
+
+ if (IsEError(err) || (err >= EPERM && err <= ELASTERRNO)) {
+ switch (IsEError(err) ? OSStatus2E(err) : err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EINPROGRESS:
+ PR_SetError(PR_IN_PROGRESS_ERROR, err);
+ break;
+ case EWOULDBLOCK:
+ case EAGAIN:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case ENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case ENXIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EPROTOTYPE:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EOPNOTSUPP:
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+ } else {
+ PR_ASSERT(IsXTIError(err));
+ switch (err) {
+ case kOTNoDataErr:
+ case kOTFlowErr:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+ }
+}
+
+static void PrepareForAsyncCompletion(PRThread * thread, PRInt32 osfd)
+{
+ thread->io_pending = PR_TRUE;
+ thread->io_fd = osfd;
+ thread->md.osErrCode = noErr;
+}
+
+
+void
+WakeUpNotifiedThread(PRThread *thread, OTResult result)
+{
+ _PRCPU * cpu = _PR_MD_CURRENT_CPU();
+
+ if (thread) {
+ thread->md.osErrCode = result;
+ if (_PR_MD_GET_INTSOFF()) {
+ thread->md.missedIONotify = PR_TRUE;
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ } else {
+ DoneWaitingOnThisThread(thread);
+ }
+ }
+
+ SignalIdleSemaphore();
+}
+
+// Notification routine
+// Async callback routine.
+// A5 is OK. Cannot allocate memory here
+// Ref: http://gemma.apple.com/techpubs/mac/NetworkingOT/NetworkingWOT-100.html
+//
+static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
+{
+ PRFilePrivate *secret = (PRFilePrivate *) contextPtr;
+ _MDFileDesc * md = &(secret->md);
+ EndpointRef endpoint = (EndpointRef)secret->md.osfd;
+ PRThread * readThread = NULL; // also used for 'misc'
+ PRThread * writeThread = NULL;
+ OSStatus err;
+ OTResult resultOT;
+ TDiscon discon;
+
+ switch (code)
+ {
+// OTLook Events -
+ case T_LISTEN: // A connection request is available
+ // If md->doListen is true, then PR_Listen has been
+ // called on this endpoint; therefore, we're ready to
+ // accept connections. But we'll do that with PR_Accept
+ // (which calls OTListen, OTAccept, etc) instead of
+ // doing it here.
+ if (md->doListen) {
+ readThread = secret->md.misc.thread;
+ secret->md.misc.thread = NULL;
+ secret->md.misc.cookie = cookie;
+ break;
+ } else {
+ // Reject the connection, we're not listening
+ OTSndDisconnect(endpoint, NULL);
+ }
+ break;
+
+ case T_CONNECT: // Confirmation of a connect request
+ // cookie = sndCall parameter from OTConnect()
+ err = OTRcvConnect(endpoint, NULL);
+ PR_ASSERT(err == kOTNoError);
+
+ // wake up waiting thread, if any.
+ writeThread = secret->md.write.thread;
+ secret->md.write.thread = NULL;
+ secret->md.write.cookie = cookie;
+ break;
+
+ case T_DATA: // Standard data is available
+ // Mark this socket as readable.
+ secret->md.readReady = PR_TRUE;
+
+ // wake up waiting thread, if any
+ readThread = secret->md.read.thread;
+ secret->md.read.thread = NULL;
+ secret->md.read.cookie = cookie;
+ break;
+
+ case T_EXDATA: // Expedited data is available
+ PR_ASSERT(!"T_EXDATA Not implemented");
+ return;
+
+ case T_DISCONNECT: // A disconnect is available
+ discon.udata.len = 0;
+ err = OTRcvDisconnect(endpoint, &discon);
+ PR_ASSERT(err == kOTNoError);
+ secret->md.exceptReady = PR_TRUE; // XXX Check this
+
+ md->disconnectError = discon.reason; // save for _MD_mac_get_nonblocking_connect_error
+
+ // wake up waiting threads, if any
+ result = -3199 - discon.reason; // obtain the negative error code
+ if ((readThread = secret->md.read.thread) != NULL) {
+ secret->md.read.thread = NULL;
+ secret->md.read.cookie = cookie;
+ }
+
+ if ((writeThread = secret->md.write.thread) != NULL) {
+ secret->md.write.thread = NULL;
+ secret->md.write.cookie = cookie;
+ }
+ break;
+
+ case T_ERROR: // obsolete/unused in library
+ PR_ASSERT(!"T_ERROR Not implemented");
+ return;
+
+ case T_UDERR: // UDP Send error; clear the error
+ (void) OTRcvUDErr((EndpointRef) cookie, NULL);
+ break;
+
+ case T_ORDREL: // An orderly release is available
+ err = OTRcvOrderlyDisconnect(endpoint);
+ PR_ASSERT(err == kOTNoError);
+ secret->md.readReady = PR_TRUE; // mark readable (to emulate bsd sockets)
+ // remember connection is closed, so we can return 0 on read or receive
+ secret->md.orderlyDisconnect = PR_TRUE;
+
+ readThread = secret->md.read.thread;
+ secret->md.read.thread = NULL;
+ secret->md.read.cookie = cookie;
+ break;
+
+ case T_GODATA: // Flow control lifted on standard data
+ secret->md.writeReady = PR_TRUE;
+ resultOT = OTLook(endpoint); // clear T_GODATA event
+ PR_ASSERT(resultOT == T_GODATA);
+
+ // wake up waiting thread, if any
+ writeThread = secret->md.write.thread;
+ secret->md.write.thread = NULL;
+ secret->md.write.cookie = cookie;
+ break;
+
+ case T_GOEXDATA: // Flow control lifted on expedited data
+ PR_ASSERT(!"T_GOEXDATA Not implemented");
+ return;
+
+ case T_REQUEST: // An Incoming request is available
+ PR_ASSERT(!"T_REQUEST Not implemented");
+ return;
+
+ case T_REPLY: // An Incoming reply is available
+ PR_ASSERT(!"T_REPLY Not implemented");
+ return;
+
+ case T_PASSCON: // State is now T_DATAXFER
+ // OTAccept() complete, receiving endpoint in T_DATAXFER state
+ // cookie = OTAccept() resRef parameter
+ break;
+
+ case T_RESET: // Protocol has been reset
+ PR_ASSERT(!"T_RESET Not implemented");
+ return;
+
+// Async Completion Events
+ case T_BINDCOMPLETE:
+ case T_UNBINDCOMPLETE:
+ case T_ACCEPTCOMPLETE:
+ case T_OPTMGMTCOMPLETE:
+ case T_GETPROTADDRCOMPLETE:
+ readThread = secret->md.misc.thread;
+ secret->md.misc.thread = NULL;
+ secret->md.misc.cookie = cookie;
+ break;
+
+// case T_OPENCOMPLETE: // we open endpoints in synchronous mode
+// case T_REPLYCOMPLETE:
+// case T_DISCONNECTCOMPLETE: // we don't call OTSndDisconnect()
+// case T_RESOLVEADDRCOMPLETE:
+// case T_GETINFOCOMPLETE:
+// case T_SYNCCOMPLETE:
+// case T_MEMORYRELEASED: // only if OTAckSends() called on endpoint
+// case T_REGNAMECOMPLETE:
+// case T_DELNAMECOMPLETE:
+// case T_LKUPNAMECOMPLETE:
+// case T_LKUPNAMERESULT:
+ // OpenTptInternet.h
+// case T_DNRSTRINGTOADDRCOMPLETE: // DNS is handled by dnsContext in DNSNotifierRoutine()
+// case T_DNRADDRTONAMECOMPLETE:
+// case T_DNRSYSINFOCOMPLETE:
+// case T_DNRMAILEXCHANGECOMPLETE:
+// case T_DNRQUERYCOMPLETE:
+ default:
+ // we should probably have a bit more sophisticated handling of kOTSystemSleep, etc.
+ // PR_ASSERT(code != 0);
+ return;
+ }
+
+ if (readThread)
+ WakeUpNotifiedThread(readThread, result);
+
+ if (writeThread && (writeThread != readThread))
+ WakeUpNotifiedThread(writeThread, result);
+}
+
+
+static OSErr CreateSocket(int type, EndpointRef *endpoint)
+{
+ OSStatus err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ char * configName;
+ OTConfiguration *config;
+ EndpointRef ep;
+
+ // for now we just create the endpoint
+ // we'll make it asynchronous and give it a notifier routine in _MD_makenonblock()
+
+ switch (type){
+ case SOCK_STREAM: configName = kTCPName; break;
+ case SOCK_DGRAM: configName = kUDPName; break;
+ }
+ config = OTCreateConfiguration(configName);
+ ep = OT_OPEN_ENDPOINT(config, 0, NULL, &err);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ *endpoint = ep;
+ PR_ASSERT(*endpoint != NULL);
+
+ return kOTNoError;
+
+ErrorExit:
+ return err;
+}
+
+
+// Errors returned:
+// kOTXXXX - OT returned error
+// EPROTONOSUPPORT - bad socket type/protocol
+// ENOBUFS - not enough space for another socket, or failure in socket creation routine
+PRInt32 _MD_socket(int domain, int type, int protocol)
+{
+ OSStatus err;
+ EndpointRef endpoint;
+
+ _MD_FinishInitNetAccess();
+
+ // We only deal with internet domain
+ if (domain != AF_INET) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // We only know about tcp & udp
+ if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // Convert default types to specific types.
+ if (protocol == 0) {
+ if (type == SOCK_DGRAM)
+ protocol = IPPROTO_UDP;
+ else if (type == SOCK_STREAM)
+ protocol = IPPROTO_TCP;
+ }
+
+ // Only support default protocol for tcp
+ if ((type == SOCK_STREAM) && (protocol != IPPROTO_TCP)) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // Only support default protocol for udp
+ if ((type == SOCK_DGRAM) && (protocol != IPPROTO_UDP)) {
+ err = kEPROTONOSUPPORTErr;
+ goto ErrorExit;
+ }
+
+ // Create a socket, we might run out of memory
+ err = CreateSocket(type, &endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PR_ASSERT((PRInt32)endpoint != -1);
+
+ return ((PRInt32)endpoint);
+
+ErrorExit:
+ macsock_map_error(err);
+ return -1;
+}
+
+
+// Errors:
+// EBADF -- bad socket id
+// EFAULT -- bad address format
+PRInt32 _MD_bind(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ TBind bindReq;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRUint32 retryCount = 0;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+/*
+ * There seems to be a bug with OT related to OTBind failing with kOTNoAddressErr even though
+ * a proper legal address was supplied. This happens very rarely and just retrying the
+ * operation after a certain time (less than 1 sec. does not work) seems to succeed.
+ */
+
+TryAgain:
+ // setup our request
+ bindReq.addr.len = addrlen;
+
+ bindReq.addr.maxlen = addrlen;
+ bindReq.addr.buf = (UInt8*) addr;
+ bindReq.qlen = 1;
+
+ PR_Lock(fd->secret->md.miscLock);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me;
+
+ err = OTBind(endpoint, &bindReq, NULL);
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ PR_Unlock(fd->secret->md.miscLock);
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(fd->secret->md.miscLock);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ return kOTNoError;
+
+ErrorExit:
+ if ((err == kOTNoAddressErr) && (++retryCount <= 4)) {
+ unsigned long finalTicks;
+
+ Delay(100,&finalTicks);
+ goto TryAgain;
+ }
+ macsock_map_error(err);
+ return -1;
+}
+
+
+// Errors:
+// EBADF -- bad socket id
+PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err = 0;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ TBind bindReq;
+ PRNetAddr addr;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if ((fd == NULL) || (endpoint == NULL)) {
+ err = EBADF;
+ goto ErrorExit;
+ }
+
+ if (backlog == 0)
+ backlog = 1;
+
+ if (endpoint == NULL) {
+ err = EBADF;
+ goto ErrorExit;
+ }
+
+ addr.inet.family = AF_INET;
+ addr.inet.port = addr.inet.ip = 0;
+
+ bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr);
+ bindReq.addr.len = 0;
+ bindReq.addr.buf = (UInt8*) &addr;
+ bindReq.qlen = 0;
+
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me; // tell notifier routine what to wake up
+
+ err = OTGetProtAddress(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me; // tell notifier routine what to wake up
+
+ err = OTUnbind(endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ /* tell the notifier func that we are interested in pending connections */
+ fd->secret->md.doListen = PR_TRUE;
+ /* accept up to (backlog) pending connections at any one time */
+ bindReq.qlen = backlog;
+
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me; // tell notifier routine what to wake up
+
+ err = OTBind(endpoint, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ {
+ // If OTBind failed, we're really not ready to listen after all.
+ fd->secret->md.doListen = PR_FALSE;
+ goto ErrorExit;
+ }
+
+ return kOTNoError;
+
+ErrorExit:
+ me->io_pending = PR_FALSE; // clear pending wait state if any
+ macsock_map_error(err);
+ return -1;
+}
+
+
+// Errors:
+// EBADF -- bad socket id
+PRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ TBind bindReq;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ bindReq.addr.len = *addrlen;
+ bindReq.addr.maxlen = *addrlen;
+ bindReq.addr.buf = (UInt8*) addr;
+ bindReq.qlen = 0;
+
+ PR_Lock(fd->secret->md.miscLock);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me;
+
+ err = OTGetProtAddress(endpoint, &bindReq, NULL);
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ PR_Unlock(fd->secret->md.miscLock);
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(fd->secret->md.miscLock);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ *addrlen = PR_NETADDR_SIZE(addr);
+ return kOTNoError;
+
+ErrorExit:
+ macsock_map_error(err);
+ return -1;
+}
+
+
+PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ TOptMgmt cmd;
+ TOption *opt;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ /*
+ OT wants IPPROTO_IP for level and not XTI_GENERIC. SO_REUSEADDR and SO_KEEPALIVE
+ are equated to IP level and TCP level options respectively and hence we need to set
+ the level correctly.
+ */
+ if (level == SOL_SOCKET) {
+ if (optname == SO_REUSEADDR)
+ level = IPPROTO_IP;
+ else if (optname == SO_KEEPALIVE)
+ level = INET_TCP;
+ }
+
+ opt = (TOption *)&optionBuffer[0];
+ opt->len = sizeof(TOption);
+ opt->level = level;
+ opt->name = optname;
+ opt->status = 0;
+
+ cmd.opt.len = sizeof(TOption);
+ cmd.opt.maxlen = sizeof(optionBuffer);
+ cmd.opt.buf = (UInt8*)optionBuffer;
+ cmd.flags = T_CURRENT;
+
+ PR_Lock(fd->secret->md.miscLock);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me;
+
+ err = OTOptionManagement(endpoint, &cmd, &cmd);
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ PR_Unlock(fd->secret->md.miscLock);
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(fd->secret->md.miscLock);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
+ err = kEOPNOTSUPPErr;
+ goto ErrorExit;
+ }
+
+ PR_ASSERT(opt->status == T_SUCCESS);
+
+ switch (optname) {
+ case SO_LINGER:
+ *((t_linger*)optval) = *((t_linger*)&opt->value);
+ *optlen = sizeof(t_linger);
+ break;
+ case SO_REUSEADDR:
+ case TCP_NODELAY:
+ case SO_KEEPALIVE:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ *((PRIntn*)optval) = *((PRIntn*)&opt->value);
+ *optlen = sizeof(PRIntn);
+ break;
+ case IP_MULTICAST_LOOP:
+ *((PRUint8*)optval) = *((PRIntn*)&opt->value);
+ *optlen = sizeof(PRUint8);
+ break;
+ case IP_TTL:
+ *((PRUintn*)optval) = *((PRUint8*)&opt->value);
+ *optlen = sizeof(PRUintn);
+ break;
+ case IP_MULTICAST_TTL:
+ *((PRUint8*)optval) = *((PRUint8*)&opt->value);
+ *optlen = sizeof(PRUint8);
+ break;
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ {
+ /* struct ip_mreq and TIPAddMulticast are the same size and optval
+ is pointing to struct ip_mreq */
+ *((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);
+ *optlen = sizeof(struct ip_mreq);
+ break;
+ }
+ case IP_MULTICAST_IF:
+ {
+ *((PRUint32*)optval) = *((PRUint32*)&opt->value);
+ *optlen = sizeof(PRUint32);
+ break;
+ }
+ /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
+ case TCP_MAXSEG:
+ if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
+ *((PRIntn*)optval) = *((PRIntn*)&opt->value);
+ *optlen = sizeof(PRIntn);
+ } else { /* it is IP_TOS */
+ *((PRUintn*)optval) = *((PRUint8*)&opt->value);
+ *optlen = sizeof(PRUintn);
+ }
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ }
+
+ return PR_SUCCESS;
+
+ErrorExit:
+ macsock_map_error(err);
+ return PR_FAILURE;
+}
+
+
+PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ TOptMgmt cmd;
+ TOption *opt;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ /*
+ OT wants IPPROTO_IP for level and not XTI_GENERIC. SO_REUSEADDR and SO_KEEPALIVE
+ are equated to IP level and TCP level options respectively and hence we need to set
+ the level correctly.
+ */
+ if (level == SOL_SOCKET) {
+ if (optname == SO_REUSEADDR)
+ level = IPPROTO_IP;
+ else if (optname == SO_KEEPALIVE)
+ level = INET_TCP;
+ }
+
+ opt = (TOption *)&optionBuffer[0];
+ opt->len = kOTOptionHeaderSize + optlen;
+
+ /* special case adjustments for length follow */
+ if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */
+ opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);
+ if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */
+ opt->len = kOTOneByteOptionSize;
+ if (optname == IP_TOS && level == IPPROTO_IP)
+ opt->len = kOTOneByteOptionSize;
+
+ opt->level = level;
+ opt->name = optname;
+ opt->status = 0;
+
+ cmd.opt.len = opt->len;
+ cmd.opt.maxlen = sizeof(optionBuffer);
+ cmd.opt.buf = (UInt8*)optionBuffer;
+
+ optionBuffer[opt->len] = 0;
+
+ cmd.flags = T_NEGOTIATE;
+
+ switch (optname) {
+ case SO_LINGER:
+ *((t_linger*)&opt->value) = *((t_linger*)optval);
+ break;
+ case SO_REUSEADDR:
+ case TCP_NODELAY:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ *((PRIntn*)&opt->value) = *((PRIntn*)optval);
+ break;
+ case IP_MULTICAST_LOOP:
+ if (*optval != 0)
+ opt->value[0] = T_YES;
+ else
+ opt->value[0] = T_NO;
+ break;
+ case SO_KEEPALIVE:
+ {
+ t_kpalive *kpalive = (t_kpalive *)&opt->value;
+
+ kpalive->kp_onoff = *((long*)optval);
+ kpalive->kp_timeout = 10; /* timeout in minutes */
+ break;
+ }
+ case IP_TTL:
+ *((unsigned char*)&opt->value) = *((PRUintn*)optval);
+ break;
+ case IP_MULTICAST_TTL:
+ *((unsigned char*)&opt->value) = *optval;
+ break;
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ {
+ /* struct ip_mreq and TIPAddMulticast are the same size and optval
+ is pointing to struct ip_mreq */
+ *((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);
+ break;
+ }
+ case IP_MULTICAST_IF:
+ {
+ *((PRUint32*)&opt->value) = *((PRUint32*)optval);
+ break;
+ }
+ /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
+ case TCP_MAXSEG:
+ if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
+ *((PRIntn*)&opt->value) = *((PRIntn*)optval);
+ } else { /* it is IP_TOS */
+ *((unsigned char*)&opt->value) = *((PRUintn*)optval);
+ }
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ }
+
+ PR_Lock(fd->secret->md.miscLock);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me;
+
+ err = OTOptionManagement(endpoint, &cmd, &cmd);
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ PR_Unlock(fd->secret->md.miscLock);
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(fd->secret->md.miscLock);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
+ err = kEOPNOTSUPPErr;
+ goto ErrorExit;
+ }
+
+ if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {
+ err = kEOPNOTSUPPErr;
+ goto ErrorExit;
+ }
+
+ PR_ASSERT(opt->status == T_SUCCESS);
+
+ return PR_SUCCESS;
+
+ErrorExit:
+ macsock_map_error(err);
+ return PR_FAILURE;
+}
+
+
+PRInt32 _MD_socketavailable(PRFileDesc *fd)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ size_t bytes;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ bytes = 0;
+
+ err = OTCountDataBytes(endpoint, &bytes);
+ if ((err == kOTLookErr) || // Not really errors, we just need to do a read,
+ (err == kOTNoDataErr)) // or there's nothing there.
+ err = kOTNoError;
+
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ return bytes;
+
+ErrorExit:
+ macsock_map_error(err);
+ return -1;
+}
+
+
+typedef struct RawEndpointAndThread
+{
+ PRThread * thread;
+ EndpointRef endpoint;
+} RawEndpointAndThread;
+
+// Notification routine for raw endpoints not yet attached to a PRFileDesc.
+// Async callback routine.
+// A5 is OK. Cannot allocate memory here
+static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
+{
+ RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr;
+ PRThread * thread = endthr->thread;
+ EndpointRef * endpoint = endthr->endpoint;
+ _PRCPU * cpu = _PR_MD_CURRENT_CPU();
+ OSStatus err;
+ OTResult resultOT;
+
+ switch (code)
+ {
+// OTLook Events -
+ case T_LISTEN: // A connection request is available
+ PR_ASSERT(!"T_EXDATA not implemented for raw endpoints");
+ break;
+
+ case T_CONNECT: // Confirmation of a connect request
+ // cookie = sndCall parameter from OTConnect()
+ err = OTRcvConnect(endpoint, NULL);
+ PR_ASSERT(err == kOTNoError);
+
+ // wake up waiting thread
+ break;
+
+ case T_DATA: // Standard data is available
+ break;
+
+ case T_EXDATA: // Expedited data is available
+ PR_ASSERT(!"T_EXDATA Not implemented for raw endpoints");
+ return;
+
+ case T_DISCONNECT: // A disconnect is available
+ err = OTRcvDisconnect(endpoint, NULL);
+ PR_ASSERT(err == kOTNoError);
+ break;
+
+ case T_ERROR: // obsolete/unused in library
+ PR_ASSERT(!"T_ERROR Not implemented for raw endpoints");
+ return;
+
+ case T_UDERR: // UDP Send error; clear the error
+ (void) OTRcvUDErr((EndpointRef) cookie, NULL);
+ break;
+
+ case T_ORDREL: // An orderly release is available
+ err = OTRcvOrderlyDisconnect(endpoint);
+ PR_ASSERT(err == kOTNoError);
+ break;
+
+ case T_GODATA: // Flow control lifted on standard data
+ resultOT = OTLook(endpoint); // clear T_GODATA event
+ PR_ASSERT(resultOT == T_GODATA);
+
+ // wake up waiting thread, if any
+ break;
+
+ case T_GOEXDATA: // Flow control lifted on expedited data
+ PR_ASSERT(!"T_GOEXDATA Not implemented");
+ return;
+
+ case T_REQUEST: // An Incoming request is available
+ PR_ASSERT(!"T_REQUEST Not implemented");
+ return;
+
+ case T_REPLY: // An Incoming reply is available
+ PR_ASSERT(!"T_REPLY Not implemented");
+ return;
+
+ case T_PASSCON: // State is now T_DATAXFER
+ // OTAccept() complete, receiving endpoint in T_DATAXFER state
+ // cookie = OTAccept() resRef parameter
+ break;
+
+// Async Completion Events
+ case T_BINDCOMPLETE:
+ case T_UNBINDCOMPLETE:
+ case T_ACCEPTCOMPLETE:
+ case T_OPTMGMTCOMPLETE:
+ case T_GETPROTADDRCOMPLETE:
+ break;
+
+ // for other OT events, see NotifierRoutine above
+ default:
+ return;
+ }
+
+ if (thread) {
+ thread->md.osErrCode = result;
+ if (_PR_MD_GET_INTSOFF()) {
+ thread->md.asyncNotifyPending = PR_TRUE;
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ } else {
+ DoneWaitingOnThisThread(thread);
+ }
+ }
+
+ SignalIdleSemaphore();
+}
+
+PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ TBind bindReq;
+ PRNetAddr bindAddr;
+ PRInt32 newosfd = -1;
+ TCall call;
+ PRNetAddr callAddr;
+ RawEndpointAndThread *endthr = NULL;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ memset(&call, 0 , sizeof(call));
+
+ if (addr != NULL) {
+ call.addr.maxlen = *addrlen;
+ call.addr.len = *addrlen;
+ call.addr.buf = (UInt8*) addr;
+ } else {
+ call.addr.maxlen = sizeof(callAddr);
+ call.addr.len = sizeof(callAddr);
+ call.addr.buf = (UInt8*) &callAddr;
+ }
+
+ do {
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me;
+
+ // Perform the listen.
+ err = OTListen (endpoint, &call);
+ if (err == kOTNoError)
+ break; // got the call information
+ else if ((!fd->secret->nonblocking) && (err == kOTNoDataErr)) {
+ WaitOnThisThread(me, timeout);
+ err = me->md.osErrCode;
+ if ((err != kOTNoError) && (err != kOTNoDataErr))
+ goto ErrorExit;
+ // we can get kOTNoError here, but still need
+ // to loop back to call OTListen, in order
+ // to get call info for OTAccept
+ } else {
+ goto ErrorExit; // we're nonblocking, and/or we got an error
+ }
+ }
+ while(1);
+
+ newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0);
+ if (newosfd == -1)
+ return -1;
+
+ // Attach the raw endpoint handler to this endpoint for now.
+ endthr = (RawEndpointAndThread *) PR_Malloc(sizeof(RawEndpointAndThread));
+ endthr->thread = me;
+ endthr->endpoint = (EndpointRef) newosfd;
+
+ err = OTInstallNotifier((ProviderRef) newosfd, RawEndpointNotifierRoutineUPP, endthr);
+ PR_ASSERT(err == kOTNoError);
+
+ err = OTSetAsynchronous((EndpointRef) newosfd);
+ PR_ASSERT(err == kOTNoError);
+
+ // Bind to a local port; let the system assign it.
+ bindAddr.inet.family = AF_INET;
+ bindAddr.inet.port = bindAddr.inet.ip = 0;
+
+ bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
+ bindReq.addr.len = 0;
+ bindReq.addr.buf = (UInt8*) &bindAddr;
+ bindReq.qlen = 0;
+
+ PrepareForAsyncCompletion(me, newosfd);
+ err = OTBind((EndpointRef) newosfd, &bindReq, NULL);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, timeout);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ PrepareForAsyncCompletion(me, newosfd);
+
+ err = OTAccept (endpoint, (EndpointRef) newosfd, &call);
+ if ((err != kOTNoError) && (err != kOTNoDataErr))
+ goto ErrorExit;
+
+ WaitOnThisThread(me, timeout);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ if (addrlen != NULL)
+ *addrlen = call.addr.len;
+
+ // Remove the temporary notifier we installed to set up the new endpoint.
+ OTRemoveNotifier((EndpointRef) newosfd);
+ PR_Free(endthr); // free the temporary context we set up for this endpoint
+
+ return newosfd;
+
+ErrorExit:
+ me->io_pending = PR_FALSE; // clear pending wait state if any
+ if (newosfd != -1)
+ _MD_closesocket(newosfd);
+ macsock_map_error(err);
+ return -1;
+}
+
+
+PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ TCall sndCall;
+ TBind bindReq;
+ PRNetAddr bindAddr;
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ // Bind to a local port; let the system assign it.
+
+ bindAddr.inet.family = AF_INET;
+ bindAddr.inet.port = bindAddr.inet.ip = 0;
+
+ bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
+ bindReq.addr.len = 0;
+ bindReq.addr.buf = (UInt8*) &bindAddr;
+ bindReq.qlen = 0;
+
+ PR_Lock(fd->secret->md.miscLock);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me;
+
+ err = OTBind(endpoint, &bindReq, NULL);
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ PR_Unlock(fd->secret->md.miscLock);
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(fd->secret->md.miscLock);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ memset(&sndCall, 0 , sizeof(sndCall));
+
+ sndCall.addr.maxlen = addrlen;
+ sndCall.addr.len = addrlen;
+ sndCall.addr.buf = (UInt8*) addr;
+
+ if (!fd->secret->nonblocking) {
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ PR_ASSERT(fd->secret->md.write.thread == NULL);
+ fd->secret->md.write.thread = me;
+ }
+
+ err = OTConnect (endpoint, &sndCall, NULL);
+ if (err == kOTNoError) {
+ PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!");
+ }
+ if (fd->secret->nonblocking) {
+ if (err == kOTNoDataErr)
+ err = EINPROGRESS;
+ goto ErrorExit;
+ } else {
+ if (err != kOTNoError && err != kOTNoDataErr) {
+ me->io_pending = PR_FALSE;
+ goto ErrorExit;
+ }
+ }
+
+ WaitOnThisThread(me, timeout);
+
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ return kOTNoError;
+
+ErrorExit:
+ macsock_map_error(err);
+ return -1;
+}
+
+
+// Errors:
+// EBADF -- bad socket id
+// EFAULT -- bad buffer
+static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout, SndRcvOpCode opCode)
+{
+ OSStatus err;
+ OTResult result;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 bytesLeft = amount;
+
+ PR_ASSERT(flags == 0 ||
+ (opCode == kSTREAM_RECEIVE && flags == PR_MSG_PEEK));
+ PR_ASSERT(opCode == kSTREAM_SEND || opCode == kSTREAM_RECEIVE);
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (buf == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
+ fd->secret->md.read.thread == NULL);
+
+ while (bytesLeft > 0)
+ {
+ Boolean disabledNotifications = OTEnterNotifier(endpoint);
+
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+
+ if (opCode == kSTREAM_SEND) {
+ do {
+ fd->secret->md.write.thread = me;
+ fd->secret->md.writeReady = PR_FALSE; // expect the worst
+ result = OTSnd(endpoint, buf, bytesLeft, NULL);
+ fd->secret->md.writeReady = (result != kOTFlowErr);
+ if (fd->secret->nonblocking) // hope for the best
+ break;
+ else {
+
+ // We drop through on anything other than a blocking write.
+ if (result != kOTFlowErr)
+ break;
+
+ // Blocking write, but the pipe is full. Turn notifications on and
+ // wait for an event, hoping that it's a T_GODATA event.
+ if (disabledNotifications) {
+ OTLeaveNotifier(endpoint);
+ disabledNotifications = false;
+ }
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ result = me->md.osErrCode;
+ if (result != kOTNoError) // got interrupted, or some other error
+ break;
+
+ // Prepare to loop back and try again
+ disabledNotifications = OTEnterNotifier(endpoint);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ }
+ }
+ while(1);
+ } else {
+ do {
+ fd->secret->md.read.thread = me;
+ fd->secret->md.readReady = PR_FALSE; // expect the worst
+ result = OTRcv(endpoint, buf, bytesLeft, NULL);
+ if (fd->secret->nonblocking) {
+ fd->secret->md.readReady = (result != kOTNoDataErr);
+ break;
+ } else {
+ if (result != kOTNoDataErr) {
+ // If we successfully read a blocking socket, check for more data.
+ // According to IM:OT, we should be able to rely on OTCountDataBytes
+ // to tell us whether there is a nonzero amount of data pending.
+ size_t count;
+ OSErr tmpResult;
+ tmpResult = OTCountDataBytes(endpoint, &count);
+ fd->secret->md.readReady = ((tmpResult == kOTNoError) && (count > 0));
+ break;
+ }
+
+ // Blocking read, but no data available. Turn notifications on and
+ // wait for an event on this endpoint, and hope that we get a T_DATA event.
+ if (disabledNotifications) {
+ OTLeaveNotifier(endpoint);
+ disabledNotifications = false;
+ }
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ result = me->md.osErrCode;
+ if (result != kOTNoError) // interrupted thread, etc.
+ break;
+
+ // Prepare to loop back and try again
+ disabledNotifications = OTEnterNotifier(endpoint);
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ }
+ }
+ // Retry read if we had to wait for data to show up.
+ while(1);
+ }
+
+ me->io_pending = PR_FALSE;
+
+ if (opCode == kSTREAM_SEND)
+ fd->secret->md.write.thread = NULL;
+ else
+ fd->secret->md.read.thread = NULL;
+
+ // turn notifications back on
+ if (disabledNotifications)
+ OTLeaveNotifier(endpoint);
+
+ if (result > 0) {
+ buf = (void *) ( (UInt32) buf + (UInt32)result );
+ bytesLeft -= result;
+ if (opCode == kSTREAM_RECEIVE) {
+ amount = result;
+ goto NormalExit;
+ }
+ } else {
+ switch (result) {
+ case kOTLookErr:
+ PR_ASSERT(!"call to OTLook() required after all.");
+ break;
+
+ case kOTFlowErr:
+ case kOTNoDataErr:
+ case kEAGAINErr:
+ case kEWOULDBLOCKErr:
+ if (fd->secret->nonblocking) {
+
+ if (bytesLeft == amount) { // no data was sent
+ err = result;
+ goto ErrorExit;
+ }
+
+ // some data was sent
+ amount -= bytesLeft;
+ goto NormalExit;
+ }
+
+ WaitOnThisThread(me, timeout);
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+ break;
+
+ case kOTOutStateErr: // if provider already closed, fall through to handle error
+ if (fd->secret->md.orderlyDisconnect) {
+ amount = 0;
+ goto NormalExit;
+ }
+ // else fall through
+ default:
+ err = result;
+ goto ErrorExit;
+ }
+ }
+ }
+
+NormalExit:
+ PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
+ fd->secret->md.read.thread == NULL);
+ return amount;
+
+ErrorExit:
+ PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
+ fd->secret->md.read.thread == NULL);
+ macsock_map_error(err);
+ return -1;
+}
+
+
+PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ return (SendReceiveStream(fd, buf, amount, flags, timeout, kSTREAM_RECEIVE));
+}
+
+
+PRInt32 _MD_send(PRFileDesc *fd,const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ return (SendReceiveStream(fd, (void *)buf, amount, flags, timeout, kSTREAM_SEND));
+}
+
+
+// Errors:
+// EBADF -- bad socket id
+// EFAULT -- bad buffer
+static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout, SndRcvOpCode opCode)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 bytesLeft = amount;
+ TUnitData dgram;
+
+ PR_ASSERT(flags == 0);
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (buf == NULL || addr == NULL) {
+ err = kEFAULTErr;
+ goto ErrorExit;
+ }
+
+ if (opCode != kDGRAM_SEND && opCode != kDGRAM_RECEIVE) {
+ err = kEINVALErr;
+ goto ErrorExit;
+ }
+
+ memset(&dgram, 0 , sizeof(dgram));
+ dgram.addr.maxlen = *addrlen;
+ dgram.addr.len = *addrlen;
+ dgram.addr.buf = (UInt8*) addr;
+ dgram.udata.maxlen = amount;
+ dgram.udata.len = amount;
+ dgram.udata.buf = (UInt8*) buf;
+
+ while (bytesLeft > 0) {
+
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+
+ if (opCode == kDGRAM_SEND) {
+ fd->secret->md.write.thread = me;
+ fd->secret->md.writeReady = PR_FALSE; // expect the worst
+ err = OTSndUData(endpoint, &dgram);
+ if (err != kOTFlowErr) // hope for the best
+ fd->secret->md.writeReady = PR_TRUE;
+ } else {
+ fd->secret->md.read.thread = me;
+ fd->secret->md.readReady = PR_FALSE; // expect the worst
+ err = OTRcvUData(endpoint, &dgram, NULL);
+ if (err != kOTNoDataErr) // hope for the best
+ fd->secret->md.readReady = PR_TRUE;
+ }
+
+ if (err == kOTNoError) {
+ buf = (void *) ( (UInt32) buf + (UInt32)dgram.udata.len );
+ bytesLeft -= dgram.udata.len;
+ dgram.udata.buf = (UInt8*) buf;
+ me->io_pending = PR_FALSE;
+ } else {
+ PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
+ WaitOnThisThread(me, timeout);
+ err = me->md.osErrCode;
+ if (err != kOTNoError)
+ goto ErrorExit;
+ }
+ }
+
+ if (opCode == kDGRAM_RECEIVE)
+ *addrlen = dgram.addr.len;
+
+ return amount;
+
+ErrorExit:
+ macsock_map_error(err);
+ return -1;
+}
+
+
+PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout)
+{
+ return (SendReceiveDgram(fd, buf, amount, flags, addr, addrlen,
+ timeout, kDGRAM_RECEIVE));
+}
+
+
+PRInt32 _MD_sendto(PRFileDesc *fd,const void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ return (SendReceiveDgram(fd, (void *)buf, amount, flags, addr, &addrlen,
+ timeout, kDGRAM_SEND));
+}
+
+
+PRInt32 _MD_closesocket(PRInt32 osfd)
+{
+ OSStatus err;
+ EndpointRef endpoint = (EndpointRef) osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (endpoint == NULL) {
+ err = kEBADFErr;
+ goto ErrorExit;
+ }
+
+ if (me->io_pending && me->io_fd == osfd)
+ me->io_pending = PR_FALSE;
+
+ (void) OTSndOrderlyDisconnect(endpoint);
+ err = OTCloseProvider(endpoint);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ return kOTNoError;
+
+ErrorExit:
+ macsock_map_error(err);
+ return -1;
+}
+
+
+PRInt32 _MD_writev(PRFileDesc *fd, const struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
+{
+#pragma unused (fd, iov, iov_size, timeout)
+
+ PR_ASSERT(0);
+ _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
+ return -1;
+}
+
+// OT endpoint states are documented here:
+// http://gemma.apple.com/techpubs/mac/NetworkingOT/NetworkingWOT-27.html#MARKER-9-65
+//
+static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady)
+{
+ OTResult resultOT;
+ // hack to emulate BSD sockets; say that a socket that has disconnected
+ // is still readable.
+ size_t availableData = 1;
+ if (!fd->secret->md.orderlyDisconnect)
+ OTCountDataBytes((EndpointRef)fd->secret->md.osfd, &availableData);
+
+ *readReady = fd->secret->md.readReady && (availableData > 0);
+ *exceptReady = fd->secret->md.exceptReady;
+
+ resultOT = OTGetEndpointState((EndpointRef)fd->secret->md.osfd);
+ switch (resultOT) {
+ case T_IDLE:
+ case T_UNBND:
+ // the socket is not connected. Emulating BSD sockets,
+ // we mark it readable and writable. The next PR_Read
+ // or PR_Write will then fail. Usually, in this situation,
+ // fd->secret->md.exceptReady is also set, and returned if
+ // anyone is polling for it.
+ *readReady = PR_FALSE;
+ *writeReady = PR_FALSE;
+ break;
+
+ case T_DATAXFER: // data transfer
+ *writeReady = fd->secret->md.writeReady;
+ break;
+
+ case T_INREL: // incoming orderly release
+ *writeReady = fd->secret->md.writeReady;
+ break;
+
+ case T_OUTCON: // outgoing connection pending
+ case T_INCON: // incoming connection pending
+ case T_OUTREL: // outgoing orderly release
+ default:
+ *writeReady = PR_FALSE;
+ }
+
+ return *readReady || *writeReady || *exceptReady;
+}
+
+// check to see if any of the poll descriptors have data available
+// for reading or writing, by calling their poll methods (layered IO).
+static PRInt32 CheckPollDescMethods(PRPollDesc *pds, PRIntn npds, PRInt16 *outReadFlags, PRInt16 *outWriteFlags)
+{
+ PRInt32 ready = 0;
+ PRPollDesc *pd, *epd;
+ PRInt16 *readFlag, *writeFlag;
+
+ for (pd = pds, epd = pd + npds, readFlag = outReadFlags, writeFlag = outWriteFlags;
+ pd < epd;
+ pd++, readFlag++, writeFlag++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ pd->out_flags = 0;
+
+ if (NULL == pd->fd || pd->in_flags == 0) continue;
+
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+
+ if ((0 != (in_flags_read & out_flags_read)) ||
+ (0 != (in_flags_write & out_flags_write)))
+ {
+ ready += 1; /* some layer has buffer input */
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+
+ *readFlag = in_flags_read;
+ *writeFlag = in_flags_write;
+ }
+
+ return ready;
+}
+
+// check to see if any of OT endpoints of the poll descriptors have data available
+// for reading or writing.
+static PRInt32 CheckPollDescEndpoints(PRPollDesc *pds, PRIntn npds, const PRInt16 *inReadFlags, const PRInt16 *inWriteFlags)
+{
+ PRInt32 ready = 0;
+ PRPollDesc *pd, *epd;
+ const PRInt16 *readFlag, *writeFlag;
+
+ for (pd = pds, epd = pd + npds, readFlag = inReadFlags, writeFlag = inWriteFlags;
+ pd < epd;
+ pd++, readFlag++, writeFlag++)
+ {
+ PRFileDesc *bottomFD;
+ PRBool readReady, writeReady, exceptReady;
+ PRInt16 in_flags_read = *readFlag;
+ PRInt16 in_flags_write = *writeFlag;
+
+ if (NULL == pd->fd || pd->in_flags == 0) continue;
+
+ if ((pd->in_flags & ~pd->out_flags) == 0) {
+ ready++;
+ continue;
+ }
+
+ bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ /* bottomFD can be NULL for pollable sockets */
+ if (bottomFD)
+ {
+ if (_PR_FILEDESC_OPEN == bottomFD->secret->state)
+ {
+ if (GetState(bottomFD, &readReady, &writeReady, &exceptReady))
+ {
+ if (readReady)
+ {
+ if (in_flags_read & PR_POLL_READ)
+ pd->out_flags |= PR_POLL_READ;
+ if (in_flags_write & PR_POLL_READ)
+ pd->out_flags |= PR_POLL_WRITE;
+ }
+ if (writeReady)
+ {
+ if (in_flags_read & PR_POLL_WRITE)
+ pd->out_flags |= PR_POLL_READ;
+ if (in_flags_write & PR_POLL_WRITE)
+ pd->out_flags |= PR_POLL_WRITE;
+ }
+ if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT))
+ {
+ pd->out_flags |= PR_POLL_EXCEPT;
+ }
+ }
+ if (0 != pd->out_flags) ready++;
+ }
+ else /* bad state */
+ {
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+
+ return ready;
+}
+
+
+// see how many of the poll descriptors are ready
+static PRInt32 CountReadyPollDescs(PRPollDesc *pds, PRIntn npds)
+{
+ PRInt32 ready = 0;
+ PRPollDesc *pd, *epd;
+
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ if (pd->out_flags)
+ ready ++;
+ }
+
+ return ready;
+}
+
+// set or clear the poll thread on the poll descriptors
+static void SetDescPollThread(PRPollDesc *pds, PRIntn npds, PRThread* thread)
+{
+ PRInt32 ready = 0;
+ PRPollDesc *pd, *epd;
+
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ if (pd->fd)
+ {
+ PRFileDesc *bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (bottomFD && (_PR_FILEDESC_OPEN == bottomFD->secret->state))
+ {
+ if (pd->in_flags & PR_POLL_READ) {
+ PR_ASSERT(thread == NULL || bottomFD->secret->md.read.thread == NULL);
+ bottomFD->secret->md.read.thread = thread;
+ }
+
+ if (pd->in_flags & PR_POLL_WRITE) {
+ // it's possible for the writing thread to be non-null during
+ // a non-blocking connect, so we assert that we're on
+ // the same thread, or the thread is null.
+ // Note that it's strictly possible for the connect and poll
+ // to be on different threads, so ideally we need to assert
+ // that if md.write.thread is non-null, there is a non-blocking
+ // connect in progress.
+ PR_ASSERT(thread == NULL ||
+ (bottomFD->secret->md.write.thread == NULL ||
+ bottomFD->secret->md.write.thread == thread));
+ bottomFD->secret->md.write.thread = thread;
+ }
+ }
+ }
+ }
+}
+
+
+#define DESCRIPTOR_FLAGS_ARRAY_SIZE 32
+
+PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRInt16 readFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE];
+ PRInt16 writeFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE];
+
+ PRInt16 *readFlags = readFlagsArray;
+ PRInt16 *writeFlags = writeFlagsArray;
+
+ PRInt16 *ioFlags = NULL;
+
+ PRThread *thread = _PR_MD_CURRENT_THREAD();
+ PRInt32 ready;
+
+ if (npds > DESCRIPTOR_FLAGS_ARRAY_SIZE)
+ {
+ // we allocate a single double-size array. The first half is used
+ // for read flags, and the second half for write flags.
+ ioFlags = (PRInt16*)PR_Malloc(sizeof(PRInt16) * npds * 2);
+ if (!ioFlags)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+
+ readFlags = ioFlags;
+ writeFlags = &ioFlags[npds];
+ }
+
+ // we have to be outside the lock when calling this, since
+ // it can call arbitrary user code (including other socket
+ // entry points)
+ ready = CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+
+ if (!ready && timeout != PR_INTERVAL_NO_WAIT) {
+ intn is;
+
+
+ _PR_INTSOFF(is);
+ PR_Lock(thread->md.asyncIOLock);
+ PrepareForAsyncCompletion(thread, 0);
+
+ SetDescPollThread(pds, npds, thread);
+
+ (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+
+ PR_Unlock(thread->md.asyncIOLock);
+ _PR_FAST_INTSON(is);
+
+ ready = CountReadyPollDescs(pds, npds);
+
+ if (ready == 0) {
+ WaitOnThisThread(thread, timeout);
+
+ // since we may have been woken by a pollable event firing,
+ // we have to check both poll methods and endpoints.
+ (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
+ ready = CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+ }
+
+ thread->io_pending = PR_FALSE;
+ SetDescPollThread(pds, npds, NULL);
+ }
+ else {
+ ready = CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
+ }
+
+ if (readFlags != readFlagsArray)
+ PR_Free(ioFlags);
+
+ return ready;
+}
+
+
+void _MD_initfiledesc(PRFileDesc *fd)
+{
+ // Allocate a PR_Lock to arbitrate miscellaneous OT calls for this endpoint between threads
+ // We presume that only one thread will be making Read calls (Recv/Accept) and that only
+ // one thread will be making Write calls (Send/Connect) on the endpoint at a time.
+ if (fd->methods->file_type == PR_DESC_SOCKET_TCP ||
+ fd->methods->file_type == PR_DESC_SOCKET_UDP )
+ {
+ PR_ASSERT(fd->secret->md.miscLock == NULL);
+ fd->secret->md.miscLock = PR_NewLock();
+ PR_ASSERT(fd->secret->md.miscLock != NULL);
+ fd->secret->md.orderlyDisconnect = PR_FALSE;
+ fd->secret->md.readReady = PR_FALSE; // let's not presume we have data ready to read
+ fd->secret->md.writeReady = PR_TRUE; // let's presume we can write unless we hear otherwise
+ fd->secret->md.exceptReady = PR_FALSE;
+ }
+}
+
+
+void _MD_freefiledesc(PRFileDesc *fd)
+{
+ if (fd->secret->md.miscLock)
+ {
+ PR_ASSERT(fd->methods->file_type == PR_DESC_SOCKET_TCP || fd->methods->file_type == PR_DESC_SOCKET_UDP);
+ PR_DestroyLock(fd->secret->md.miscLock);
+ fd->secret->md.miscLock = NULL;
+ } else {
+ PR_ASSERT(fd->methods->file_type != PR_DESC_SOCKET_TCP && PR_DESC_SOCKET_TCP != PR_DESC_SOCKET_UDP);
+ }
+}
+
+// _MD_makenonblock is also used for sockets meant to be used for blocking I/O,
+// in order to install the notifier routine for async completion.
+void _MD_makenonblock(PRFileDesc *fd)
+{
+ // We simulate non-blocking mode using async mode rather
+ // than put the endpoint in non-blocking mode.
+ // We need to install the PRFileDesc as the contextPtr for the NotifierRoutine, but it
+ // didn't exist at the time the endpoint was created. It does now though...
+ ProviderRef endpointRef = (ProviderRef)fd->secret->md.osfd;
+ OSStatus err;
+
+ // Install fd->secret as the contextPtr for the Notifier function associated with this
+ // endpoint. We use this instead of the fd itself because:
+ // (a) in cases where you import I/O layers, the containing
+ // fd changes, but the secret structure does not;
+ // (b) the notifier func refers only to the secret data structure
+ // anyway.
+ err = OTInstallNotifier(endpointRef, NotifierRoutineUPP, fd->secret);
+ PR_ASSERT(err == kOTNoError);
+
+ // Now that we have a NotifierRoutine installed, we can make the endpoint asynchronous
+ err = OTSetAsynchronous(endpointRef);
+ PR_ASSERT(err == kOTNoError);
+}
+
+
+void _MD_initfdinheritable(PRFileDesc *fd, PRBool imported)
+{
+ /* XXX this function needs to be implemented */
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+}
+
+
+void _MD_queryfdinheritable(PRFileDesc *fd)
+{
+ /* XXX this function needs to be implemented */
+ PR_ASSERT(0);
+}
+
+
+PR_IMPLEMENT(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how)
+{
+#pragma unused (fd, how)
+
+/* Just succeed silently!!! */
+return (0);
+}
+
+
+PR_IMPLEMENT(PRStatus)
+_MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ EndpointRef ep = (EndpointRef) fd->secret->md.osfd;
+ InetAddress inetAddr;
+ TBind peerAddr;
+ OSErr err;
+
+ if (*addrlen < sizeof(InetAddress)) {
+
+ err = (OSErr) kEINVALErr;
+ goto ErrorExit;
+ }
+
+ peerAddr.addr.maxlen = sizeof(InetAddress);
+ peerAddr.addr.len = 0;
+ peerAddr.addr.buf = (UInt8*) &inetAddr;
+ peerAddr.qlen = 0;
+
+ PrepareForAsyncCompletion(me, fd->secret->md.osfd);
+ fd->secret->md.misc.thread = me; // tell notifier routine what to wake up
+
+ err = OTGetProtAddress(ep, NULL, &peerAddr);
+
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+ err = me->md.osErrCode;
+ if ((err == kOTNoError) && (peerAddr.addr.len < sizeof(InetAddress)))
+ err = kEBADFErr; // we don't understand the address we got
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ // Translate the OT peer information into an NSPR address.
+ addr->inet.family = AF_INET;
+ addr->inet.port = (PRUint16) inetAddr.fPort;
+ addr->inet.ip = (PRUint32) inetAddr.fHost;
+
+ *addrlen = PR_NETADDR_SIZE(addr); // return the amount of data obtained
+ return PR_SUCCESS;
+
+ErrorExit:
+ macsock_map_error(err);
+ return PR_FAILURE;
+}
+
+
+PR_IMPLEMENT(unsigned long) inet_addr(const char *cp)
+{
+ OSStatus err;
+ InetHost host;
+
+ _MD_FinishInitNetAccess();
+
+ err = OTInetStringToHost((char*) cp, &host);
+ if (err != kOTNoError)
+ return -1;
+
+ return host;
+}
+
+
+static char *sAliases[1] = {NULL};
+static struct hostent sHostEnt = {NULL, &sAliases[0], AF_INET, sizeof (long), NULL};
+static InetHostInfo sHostInfo;
+static InetHost *sAddresses[kMaxHostAddrs+1];
+
+
+PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name)
+{
+ OSStatus err;
+ PRUint32 index;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ _MD_FinishInitNetAccess();
+
+ me->io_pending = PR_TRUE;
+ me->io_fd = NULL;
+ me->md.osErrCode = noErr;
+
+ PR_Lock(dnsContext.lock); // so we can safely store our thread ptr in dnsContext
+ dnsContext.thread = me; // so we know what thread to wake up when OTInetStringToAddress completes
+
+ err = OTInetStringToAddress(dnsContext.serviceRef, (char *)name, &sHostInfo);
+ if (err != kOTNoError) {
+ me->io_pending = PR_FALSE;
+ me->md.osErrCode = err;
+ goto ErrorExit;
+ }
+
+ WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(dnsContext.lock);
+
+ if (me->md.osErrCode != kOTNoError)
+ goto ErrorExit;
+
+ sHostEnt.h_name = sHostInfo.name;
+ for (index=0; index<kMaxHostAddrs && sHostInfo.addrs[index] != NULL; index++)
+ sAddresses[index] = &sHostInfo.addrs[index];
+ sAddresses[index] = NULL;
+ sHostEnt.h_addr_list = (char **)sAddresses;
+
+ return (&sHostEnt);
+
+ErrorExit:
+ return NULL;
+}
+
+
+PR_IMPLEMENT(struct hostent *) gethostbyaddr(const void *addr, int addrlen, int type)
+{
+ PR_ASSERT(type == AF_INET);
+ PR_ASSERT(addrlen == sizeof(struct in_addr));
+
+ _MD_FinishInitNetAccess();
+
+ OTInetHostToString((InetHost)addr, sHostInfo.name);
+
+ return (gethostbyname(sHostInfo.name));
+}
+
+
+PR_IMPLEMENT(char *) inet_ntoa(struct in_addr addr)
+{
+ _MD_FinishInitNetAccess();
+
+ OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
+
+ return sHostInfo.name;
+}
+
+
+PRStatus _MD_gethostname(char *name, int namelen)
+{
+ OSStatus err;
+ InetInterfaceInfo info;
+
+ _MD_FinishInitNetAccess();
+
+ /*
+ * On a Macintosh, we don't have the concept of a local host name.
+ * We do though have an IP address & everyone should be happy with
+ * a string version of that for a name.
+ * The alternative here is to ping a local DNS for our name, they
+ * will often know it. This is the cheap, easiest, and safest way out.
+ */
+
+ /* Make sure the string is as long as the longest possible address */
+ if (namelen < strlen("123.123.123.123")) {
+ err = kEINVALErr;
+ goto ErrorExit;
+ }
+
+ err = OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
+ if (err != kOTNoError)
+ goto ErrorExit;
+
+ OTInetHostToString(info.fAddress, name);
+
+ return PR_SUCCESS;
+
+ErrorExit:
+ macsock_map_error(err);
+ return PR_FAILURE;
+}
+
+
+#define kIPName "ip"
+static struct protoent sIPProto = {kIPName, NULL, INET_IP};
+static struct protoent sTCPProto = {kTCPName, NULL, INET_TCP};
+static struct protoent sUDPProto = {kUDPName, NULL, INET_UDP};
+
+PR_IMPLEMENT(struct protoent *) getprotobyname(const char * name)
+{
+ if (strcmp(name, kIPName) == 0)
+ return (&sIPProto);
+
+ if (strcmp(name, kTCPName) == 0)
+ return (&sTCPProto);
+
+ if (strcmp(name, kUDPName) == 0)
+ return (&sUDPProto);
+
+ErrorExit:
+ macsock_map_error(kEINVALErr);
+ return NULL;
+}
+
+
+PR_IMPLEMENT(struct protoent *) getprotobynumber(int number)
+{
+ if (number == INET_IP)
+ return (&sIPProto);
+
+ if (number == INET_TCP)
+ return (&sTCPProto);
+
+ if (number == INET_UDP)
+ return (&sUDPProto);
+
+ErrorExit:
+ macsock_map_error(kEINVALErr);
+ return NULL;
+}
+
+
+int _MD_mac_get_nonblocking_connect_error(PRFileDesc* fd)
+{
+ EndpointRef endpoint = (EndpointRef)fd->secret->md.osfd;
+ OTResult resultOT = OTGetEndpointState(endpoint);
+
+ switch (resultOT) {
+ case T_OUTCON:
+ macsock_map_error(EINPROGRESS);
+ return -1;
+
+ case T_DATAXFER:
+ return 0;
+
+ case T_IDLE:
+ macsock_map_error(fd->secret->md.disconnectError);
+ fd->secret->md.disconnectError = 0;
+ return -1;
+
+ case T_INREL:
+ macsock_map_error(ENOTCONN);
+ return -1;
+
+ default:
+ PR_ASSERT(0);
+ return -1;
+ }
+
+ return -1; // not reached
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macthr.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macthr.c
new file mode 100644
index 00000000..292389ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macthr.c
@@ -0,0 +1,721 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+
+#include <MacTypes.h>
+#include <Timer.h>
+#include <OSUtils.h>
+#include <Math64.h>
+#include <LowMem.h>
+#include <Multiprocessing.h>
+#include <Gestalt.h>
+
+#include "mdcriticalregion.h"
+
+TimerUPP gTimerCallbackUPP = NULL;
+PRThread * gPrimaryThread = NULL;
+
+ProcessSerialNumber gApplicationProcess;
+
+PR_IMPLEMENT(PRThread *) PR_GetPrimaryThread()
+{
+ return gPrimaryThread;
+}
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark CREATING MACINTOSH THREAD STACKS
+
+#if defined(GC_LEAK_DETECTOR)
+extern void* GC_malloc_atomic(PRUint32 size);
+#endif
+
+/*
+** Allocate a new memory segment. We allocate it from our figment heap. Currently,
+** it is being used for per thread stack space.
+**
+** Return the segment's access rights and size. vaddr is used on Unix platforms to
+** map an existing address for the segment.
+*/
+PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
+{
+ PR_ASSERT(seg != 0);
+ PR_ASSERT(size != 0);
+ PR_ASSERT(vaddr == 0);
+
+ /*
+ ** Take the actual memory for the segment out of our Figment heap.
+ */
+
+#if defined(GC_LEAK_DETECTOR)
+ seg->vaddr = (char *)GC_malloc_atomic(size);
+#else
+ seg->vaddr = (char *)malloc(size);
+#endif
+
+ if (seg->vaddr == NULL) {
+
+#if DEBUG
+ DebugStr("\p_MD_AllocSegment failed.");
+#endif
+
+ return PR_FAILURE;
+ }
+
+ seg->size = size;
+
+ return PR_SUCCESS;
+}
+
+
+/*
+** Free previously allocated memory segment.
+*/
+void _MD_FreeSegment(PRSegment *seg)
+{
+ PR_ASSERT((seg->flags & _PR_SEG_VM) == 0);
+
+ if (seg->vaddr != NULL)
+ free(seg->vaddr);
+}
+
+
+/*
+** The thread's stack has been allocated and its fields are already properly filled
+** in by PR. Perform any debugging related initialization here.
+**
+** Put a recognizable pattern so that we can find it from Macsbug.
+** Put a cookie at the top of the stack so that we can find it from Macsbug.
+*/
+void _MD_InitStack(PRThreadStack *ts, int redZoneBytes)
+ {
+#pragma unused (redZoneBytes)
+#if DEVELOPER_DEBUG
+ // Put a cookie at the top of the stack so that we can find
+ // it from Macsbug.
+
+ memset(ts->allocBase, 0xDC, ts->stackSize);
+
+ ((UInt32 *)ts->stackTop)[-1] = 0xBEEFCAFE;
+ ((UInt32 *)ts->stackTop)[-2] = (UInt32)gPrimaryThread;
+ ((UInt32 *)ts->stackTop)[-3] = (UInt32)(ts);
+ ((UInt32 *)ts->stackBottom)[0] = 0xCAFEBEEF;
+#else
+#pragma unused (ts)
+#endif
+ }
+
+extern void _MD_ClearStack(PRThreadStack *ts)
+ {
+#if DEVELOPER_DEBUG
+ // Clear out our cookies.
+
+ memset(ts->allocBase, 0xEF, ts->allocSize);
+ ((UInt32 *)ts->stackTop)[-1] = 0;
+ ((UInt32 *)ts->stackTop)[-2] = 0;
+ ((UInt32 *)ts->stackTop)[-3] = 0;
+ ((UInt32 *)ts->stackBottom)[0] = 0;
+#else
+#pragma unused (ts)
+#endif
+ }
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark TIME MANAGER-BASED CLOCK
+
+// On Mac OS X, it's possible for the application to spend lots of time
+// in WaitNextEvent, yielding to other applications. Since NSPR threads are
+// cooperative here, this means that NSPR threads will also get very little
+// time to run. To kick ourselves out of a WaitNextEvent call when we have
+// determined that it's time to schedule another thread, the Timer Task
+// (which fires every 8ms, even when other apps have the CPU) calls WakeUpProcess.
+// We only want to do this on Mac OS X; the gTimeManagerTaskDoesWUP variable
+// indicates when we're running on that OS.
+//
+// Note that the TimerCallback makes use of gApplicationProcess. We need to
+// have set this up before the first possible run of the timer task; we do
+// so in _MD_EarlyInit().
+static Boolean gTimeManagerTaskDoesWUP;
+
+static TMTask gTimeManagerTaskElem;
+
+extern void _MD_IOInterrupt(void);
+_PRInterruptTable _pr_interruptTable[] = {
+ { "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },
+ { "i/o", _PR_MISSED_IO, _MD_IOInterrupt, },
+ { 0 }
+};
+
+#define kMacTimerInMiliSecs 8L
+
+pascal void TimerCallback(TMTaskPtr tmTaskPtr)
+{
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+ PRIntn is;
+
+ if (_PR_MD_GET_INTSOFF()) {
+ cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
+ PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
+ return;
+ }
+
+ _PR_INTSOFF(is);
+
+ // And tell nspr that a clock interrupt occured.
+ _PR_ClockInterrupt();
+
+ if ((_PR_RUNQREADYMASK(cpu)) >> ((_PR_MD_CURRENT_THREAD()->priority))) {
+ if (gTimeManagerTaskDoesWUP) {
+ // We only want to call WakeUpProcess if we know that NSPR has managed to switch threads
+ // since the last call, otherwise we end up spewing out WakeUpProcess() calls while the
+ // application is blocking somewhere. This can interfere with events loops other than
+ // our own (see bug 158927).
+ if (UnsignedWideToUInt64(cpu->md.lastThreadSwitch) > UnsignedWideToUInt64(cpu->md.lastWakeUpProcess))
+ {
+ WakeUpProcess(&gApplicationProcess);
+ cpu->md.lastWakeUpProcess = UpTime();
+ }
+ }
+ _PR_SET_RESCHED_FLAG();
+ }
+
+ _PR_FAST_INTSON(is);
+
+ // Reset the clock timer so that we fire again.
+ PrimeTime((QElemPtr)tmTaskPtr, kMacTimerInMiliSecs);
+}
+
+
+void _MD_StartInterrupts(void)
+{
+ gPrimaryThread = _PR_MD_CURRENT_THREAD();
+
+ gTimeManagerTaskDoesWUP = RunningOnOSX();
+
+ if ( !gTimerCallbackUPP )
+ gTimerCallbackUPP = NewTimerUPP(TimerCallback);
+
+ // Fill in the Time Manager queue element
+
+ gTimeManagerTaskElem.tmAddr = (TimerUPP)gTimerCallbackUPP;
+ gTimeManagerTaskElem.tmCount = 0;
+ gTimeManagerTaskElem.tmWakeUp = 0;
+ gTimeManagerTaskElem.tmReserved = 0;
+
+ // Make sure that our time manager task is ready to go.
+ InsTime((QElemPtr)&gTimeManagerTaskElem);
+
+ PrimeTime((QElemPtr)&gTimeManagerTaskElem, kMacTimerInMiliSecs);
+}
+
+void _MD_StopInterrupts(void)
+{
+ if (gTimeManagerTaskElem.tmAddr != NULL) {
+ RmvTime((QElemPtr)&gTimeManagerTaskElem);
+ gTimeManagerTaskElem.tmAddr = NULL;
+ }
+}
+
+
+#define MAX_PAUSE_TIMEOUT_MS 500
+
+void _MD_PauseCPU(PRIntervalTime timeout)
+{
+ if (timeout != PR_INTERVAL_NO_WAIT)
+ {
+ // There is a race condition entering the critical section
+ // in AsyncIOCompletion (and probably elsewhere) that can
+ // causes deadlock for the duration of this timeout. To
+ // work around this, use a max 500ms timeout for now.
+ // See bug 99561 for details.
+ if (PR_IntervalToMilliseconds(timeout) > MAX_PAUSE_TIMEOUT_MS)
+ timeout = PR_MillisecondsToInterval(MAX_PAUSE_TIMEOUT_MS);
+
+ WaitOnIdleSemaphore(timeout);
+ (void) _MD_IOInterrupt();
+ }
+}
+
+void _MD_InitRunningCPU(_PRCPU* cpu)
+{
+ cpu->md.trackScheduling = RunningOnOSX();
+ if (cpu->md.trackScheduling) {
+ AbsoluteTime zeroTime = {0, 0};
+ cpu->md.lastThreadSwitch = UpTime();
+ cpu->md.lastWakeUpProcess = zeroTime;
+ }
+}
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark THREAD SUPPORT FUNCTIONS
+
+#include <OpenTransport.h> /* for error codes */
+
+PRStatus _MD_InitThread(PRThread *thread)
+{
+ thread->md.asyncIOLock = PR_NewLock();
+ PR_ASSERT(thread->md.asyncIOLock != NULL);
+ thread->md.asyncIOCVar = PR_NewCondVar(thread->md.asyncIOLock);
+ PR_ASSERT(thread->md.asyncIOCVar != NULL);
+
+ if (thread->md.asyncIOLock == NULL || thread->md.asyncIOCVar == NULL)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+}
+
+PRStatus _MD_wait(PRThread *thread, PRIntervalTime timeout)
+{
+#pragma unused (timeout)
+
+ _MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+
+void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout)
+{
+ intn is;
+ PRIntervalTime timein = PR_IntervalNow();
+ PRStatus status = PR_SUCCESS;
+
+ // Turn interrupts off to avoid a race over lock ownership with the callback
+ // (which can fire at any time). Interrupts may stay off until we leave
+ // this function, or another NSPR thread turns them back on. They certainly
+ // stay off until PR_WaitCondVar() relinquishes the asyncIOLock lock, which
+ // is what we care about.
+ _PR_INTSOFF(is);
+ PR_Lock(thread->md.asyncIOLock);
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ while ((thread->io_pending) && (status == PR_SUCCESS))
+ status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
+ } else {
+ while ((thread->io_pending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
+ status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
+ }
+ if ((status == PR_FAILURE) && (PR_GetError() == PR_PENDING_INTERRUPT_ERROR)) {
+ thread->md.osErrCode = kEINTRErr;
+ } else if (thread->io_pending) {
+ thread->md.osErrCode = kETIMEDOUTErr;
+ PR_SetError(PR_IO_TIMEOUT_ERROR, kETIMEDOUTErr);
+ }
+
+ thread->io_pending = PR_FALSE;
+ PR_Unlock(thread->md.asyncIOLock);
+ _PR_FAST_INTSON(is);
+}
+
+
+void DoneWaitingOnThisThread(PRThread *thread)
+{
+ intn is;
+
+ PR_ASSERT(thread->md.asyncIOLock->owner == NULL);
+
+ // DoneWaitingOnThisThread() is called from OT notifiers and async file I/O
+ // callbacks that can run at "interrupt" time (Classic Mac OS) or on pthreads
+ // that may run concurrently with the main threads (Mac OS X). They can thus
+ // be called when any NSPR thread is running, or even while NSPR is in a
+ // thread context switch. It is therefore vital that we can guarantee to
+ // be able to get the asyncIOLock without blocking (thus avoiding code
+ // that makes assumptions about the current NSPR thread etc). To achieve
+ // this, we use NSPR interrrupts as a semaphore on the lock; all code
+ // that grabs the lock also disables interrupts for the time the lock
+ // is held. Callers of DoneWaitingOnThisThread() thus have to check whether
+ // interrupts are already off, and, if so, simply set the missed_IO flag on
+ // the CPU rather than calling this function.
+
+ _PR_INTSOFF(is);
+ PR_Lock(thread->md.asyncIOLock);
+ thread->io_pending = PR_FALSE;
+ /* let the waiting thread know that async IO completed */
+ PR_NotifyCondVar(thread->md.asyncIOCVar);
+ PR_Unlock(thread->md.asyncIOLock);
+ _PR_FAST_INTSON(is);
+}
+
+
+PR_IMPLEMENT(void) PR_Mac_WaitForAsyncNotify(PRIntervalTime timeout)
+{
+ intn is;
+ PRIntervalTime timein = PR_IntervalNow();
+ PRStatus status = PR_SUCCESS;
+ PRThread *thread = _PR_MD_CURRENT_THREAD();
+
+ // See commments in WaitOnThisThread()
+ _PR_INTSOFF(is);
+ PR_Lock(thread->md.asyncIOLock);
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ while ((!thread->md.asyncNotifyPending) && (status == PR_SUCCESS))
+ status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
+ } else {
+ while ((!thread->md.asyncNotifyPending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
+ status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
+ }
+ if ((status == PR_FAILURE) && (PR_GetError() == PR_PENDING_INTERRUPT_ERROR)) {
+ thread->md.osErrCode = kEINTRErr;
+ } else if (!thread->md.asyncNotifyPending) {
+ thread->md.osErrCode = kETIMEDOUTErr;
+ PR_SetError(PR_IO_TIMEOUT_ERROR, kETIMEDOUTErr);
+ }
+ thread->md.asyncNotifyPending = PR_FALSE;
+ PR_Unlock(thread->md.asyncIOLock);
+ _PR_FAST_INTSON(is);
+}
+
+
+void AsyncNotify(PRThread *thread)
+{
+ intn is;
+
+ PR_ASSERT(thread->md.asyncIOLock->owner == NULL);
+
+ // See commments in DoneWaitingOnThisThread()
+ _PR_INTSOFF(is);
+ PR_Lock(thread->md.asyncIOLock);
+ thread->md.asyncNotifyPending = PR_TRUE;
+ /* let the waiting thread know that async IO completed */
+ PR_NotifyCondVar(thread->md.asyncIOCVar);
+ PR_Unlock(thread->md.asyncIOLock);
+ _PR_FAST_INTSON(is);
+}
+
+
+PR_IMPLEMENT(void) PR_Mac_PostAsyncNotify(PRThread *thread)
+{
+ _PRCPU * cpu = _PR_MD_CURRENT_CPU();
+
+ if (_PR_MD_GET_INTSOFF()) {
+ thread->md.missedAsyncNotify = PR_TRUE;
+ cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+ } else {
+ AsyncNotify(thread);
+ }
+}
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark PROCESS SUPPORT FUNCTIONS
+
+PRProcess * _MD_CreateProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+#pragma unused (path, argv, envp, attr)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
+ return NULL;
+}
+
+PRStatus _MD_DetachProcess(PRProcess *process)
+{
+#pragma unused (process)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_WaitProcess(PRProcess *process, PRInt32 *exitCode)
+{
+#pragma unused (process, exitCode)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_KillProcess(PRProcess *process)
+{
+#pragma unused (process)
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, unimpErr);
+ return PR_FAILURE;
+}
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark ATOMIC OPERATIONS
+
+#ifdef _PR_HAVE_ATOMIC_OPS
+PRInt32
+_MD_AtomicSet(PRInt32 *val, PRInt32 newval)
+{
+ PRInt32 rv;
+ do {
+ rv = *val;
+ } while (!OTCompareAndSwap32(rv, newval, (UInt32*)val));
+
+ return rv;
+}
+
+#endif // _PR_HAVE_ATOMIC_OPS
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark INTERRUPT SUPPORT
+
+#if TARGET_CARBON
+
+/*
+ This critical region support is required for Mac NSPR to work correctly on dual CPU
+ machines on Mac OS X. This note explains why.
+
+ NSPR uses a timer task, and has callbacks for async file I/O and Open Transport
+ whose runtime behaviour differs depending on environment. On "Classic" Mac OS
+ these run at "interrupt" time (OS-level interrupts, that is, not NSPR interrupts),
+ and can thus preempt other code, but they always run to completion.
+
+ On Mac OS X, these are all emulated using MP tasks, which sit atop pthreads. Thus,
+ they can be preempted at any time (and not necessarily run to completion), and can
+ also run *concurrently* with eachother, and with application code, on multiple
+ CPU machines. Note that all NSPR threads are emulated, and all run on the main
+ application MP task.
+
+ We thus have to use MP critical sections to protect data that is shared between
+ the various callbacks and the main MP thread. It so happens that NSPR has this
+ concept of software interrupts, and making interrupt-off times be critical
+ sections works.
+
+*/
+
+
+/*
+ Whether to use critical regions. True if running on Mac OS X and later
+*/
+
+PRBool gUseCriticalRegions;
+
+/*
+ Count of the number of times we've entered the critical region.
+ We need this because ENTER_CRITICAL_REGION() will *not* block when
+ called from different NSPR threads (which all run on one MP thread),
+ and we need to ensure that when code turns interrupts back on (by
+ settings _pr_intsOff to 0) we exit the critical section enough times
+ to leave it.
+*/
+
+PRInt32 gCriticalRegionEntryCount;
+
+
+void _MD_SetIntsOff(PRInt32 ints)
+{
+ ENTER_CRITICAL_REGION();
+ gCriticalRegionEntryCount ++;
+
+ _pr_intsOff = ints;
+
+ if (!ints)
+ {
+ PRInt32 i = gCriticalRegionEntryCount;
+
+ gCriticalRegionEntryCount = 0;
+ for ( ;i > 0; i --) {
+ LEAVE_CRITICAL_REGION();
+ }
+ }
+}
+
+
+#endif /* TARGET_CARBON */
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark CRITICAL REGION SUPPORT
+
+
+static PRBool RunningOnOSX()
+{
+ long systemVersion;
+ OSErr err = Gestalt(gestaltSystemVersion, &systemVersion);
+ return (err == noErr) && (systemVersion >= 0x00001000);
+}
+
+
+#if MAC_CRITICAL_REGIONS
+
+MDCriticalRegionID gCriticalRegion;
+
+void InitCriticalRegion()
+{
+ OSStatus err;
+
+ // we only need to do critical region stuff on Mac OS X
+ gUseCriticalRegions = RunningOnOSX();
+ if (!gUseCriticalRegions) return;
+
+ err = MD_CriticalRegionCreate(&gCriticalRegion);
+ PR_ASSERT(err == noErr);
+}
+
+void TermCriticalRegion()
+{
+ OSStatus err;
+
+ if (!gUseCriticalRegions) return;
+
+ err = MD_CriticalRegionDelete(gCriticalRegion);
+ PR_ASSERT(err == noErr);
+}
+
+
+void EnterCritialRegion()
+{
+ OSStatus err;
+
+ if (!gUseCriticalRegions) return;
+
+ PR_ASSERT(gCriticalRegion != kInvalidID);
+
+ /* Change to a non-infinite timeout for debugging purposes */
+ err = MD_CriticalRegionEnter(gCriticalRegion, kDurationForever /* 10000 * kDurationMillisecond */ );
+ PR_ASSERT(err == noErr);
+}
+
+void LeaveCritialRegion()
+{
+ OSStatus err;
+
+ if (!gUseCriticalRegions) return;
+
+ PR_ASSERT(gCriticalRegion != kInvalidID);
+
+ err = MD_CriticalRegionExit(gCriticalRegion);
+ PR_ASSERT(err == noErr);
+}
+
+
+#endif // MAC_CRITICAL_REGIONS
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark IDLE SEMAPHORE SUPPORT
+
+/*
+ Since the WaitNextEvent() in _MD_PauseCPU() is causing all sorts of
+ headache under Mac OS X we're going to switch to MPWaitOnSemaphore()
+ which should do what we want
+*/
+
+#if TARGET_CARBON
+PRBool gUseIdleSemaphore = PR_FALSE;
+MPSemaphoreID gIdleSemaphore = NULL;
+#endif
+
+void InitIdleSemaphore()
+{
+ // we only need to do idle semaphore stuff on Mac OS X
+#if TARGET_CARBON
+ gUseIdleSemaphore = RunningOnOSX();
+ if (gUseIdleSemaphore)
+ {
+ OSStatus err = MPCreateSemaphore(1 /* max value */, 0 /* initial value */, &gIdleSemaphore);
+ PR_ASSERT(err == noErr);
+ }
+#endif
+}
+
+void TermIdleSemaphore()
+{
+#if TARGET_CARBON
+ if (gUseIdleSemaphore)
+ {
+ OSStatus err = MPDeleteSemaphore(gIdleSemaphore);
+ PR_ASSERT(err == noErr);
+ gUseIdleSemaphore = NULL;
+ }
+#endif
+}
+
+
+void WaitOnIdleSemaphore(PRIntervalTime timeout)
+{
+#if TARGET_CARBON
+ if (gUseIdleSemaphore)
+ {
+ OSStatus err = MPWaitOnSemaphore(gIdleSemaphore, kDurationMillisecond * PR_IntervalToMilliseconds(timeout));
+ PR_ASSERT(err == noErr);
+ }
+ else
+#endif
+ {
+ EventRecord theEvent;
+ /*
+ ** Calling WaitNextEvent() here is suboptimal. This routine should
+ ** pause the process until IO or the timeout occur, yielding time to
+ ** other processes on operating systems that require this (Mac OS classic).
+ ** WaitNextEvent() may incur too much latency, and has other problems,
+ ** such as the potential to drop suspend/resume events.
+ */
+ (void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);
+ }
+}
+
+
+void SignalIdleSemaphore()
+{
+#if TARGET_CARBON
+ if (gUseIdleSemaphore)
+ {
+ // often we won't be waiting on the semaphore here, so ignore any errors
+ (void)MPSignalSemaphore(gIdleSemaphore);
+ }
+ else
+#endif
+ {
+ WakeUpProcess(&gApplicationProcess);
+ }
+}
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.c
new file mode 100644
index 00000000..1e7d2a22
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.c
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <OSUtils.h>
+#include <Timer.h>
+
+#include "primpl.h"
+
+#include "mactime.h"
+
+unsigned long gJanuaryFirst1970Seconds;
+
+/*
+ * The geographic location and time zone information of a Mac
+ * are stored in extended parameter RAM. The ReadLocation
+ * produdure uses the geographic location record, MachineLocation,
+ * to read the geographic location and time zone information in
+ * extended parameter RAM.
+ *
+ * Because serial port and SLIP conflict with ReadXPram calls,
+ * we cache the call here.
+ *
+ * Caveat: this caching will give the wrong result if a session
+ * extend across the DST changeover time.
+ */
+
+static void MyReadLocation(MachineLocation *loc)
+{
+ static MachineLocation storedLoc;
+ static Boolean didReadLocation = false;
+
+ if (!didReadLocation) {
+ ReadLocation(&storedLoc);
+ didReadLocation = true;
+ }
+ *loc = storedLoc;
+}
+
+static long GMTDelta(void)
+{
+ MachineLocation loc;
+ long gmtDelta;
+
+ MyReadLocation(&loc);
+ gmtDelta = loc.u.gmtDelta & 0x00ffffff;
+ if (gmtDelta & 0x00800000) { /* test sign extend bit */
+ gmtDelta |= 0xff000000;
+ }
+ return gmtDelta;
+}
+
+void MacintoshInitializeTime(void)
+{
+ /*
+ * The NSPR epoch is midnight, Jan. 1, 1970 GMT.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ * midnight Jan. 1, 1970 + GMTDelta().
+ *
+ * Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
+ * = 2082844800 seconds since the Mac epoch.
+ * (There were 17 leap years from 1904 to 1970.)
+ *
+ * So the NSPR epoch is 2082844800 + GMTDelta() seconds since
+ * the Mac epoch. Whew! :-)
+ */
+ gJanuaryFirst1970Seconds = 2082844800 + GMTDelta();
+}
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the Mac
+ * Implementation.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PRTime PR_Now(void)
+{
+ unsigned long currentTime; /* unsigned 32-bit integer, ranging
+ from midnight Jan. 1, 1904 to
+ 6:28:15 AM Feb. 6, 2040 */
+ PRTime retVal;
+ int64 usecPerSec;
+
+ /*
+ * Get the current time expressed as the number of seconds
+ * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
+ * On a Mac, current time accuracy is up to a second.
+ */
+ GetDateTime(&currentTime);
+
+ /*
+ * Express the current time relative to the NSPR epoch,
+ * midnight, Jan. 1, 1970 GMT.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ * midnight Jan. 1, 1970 + GMTDelta().
+ *
+ * Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
+ * = 2082844800 seconds since the Mac epoch.
+ * (There were 17 leap years from 1904 to 1970.)
+ *
+ * So the NSPR epoch is 2082844800 + GMTDelta() seconds since
+ * the Mac epoch. Whew! :-)
+ */
+ currentTime = currentTime - 2082844800 - GMTDelta();
+
+ /* Convert seconds to microseconds */
+ LL_I2L(usecPerSec, PR_USEC_PER_SEC);
+ LL_I2L(retVal, currentTime);
+ LL_MUL(retVal, retVal, usecPerSec);
+
+ return retVal;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * PR_LocalTimeParameters --
+ *
+ * returns the time parameters for the local time zone
+ *
+ * This is the machine-dependent implementation for Mac.
+ *
+ * Caveat: On a Mac, we only know the GMT and DST offsets for
+ * the current time, not for the time in question.
+ * Mac has no support for DST handling.
+ * DST changeover is all manually set by the user.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+PRTimeParameters PR_LocalTimeParameters(const PRExplodedTime *gmt)
+{
+#pragma unused (gmt)
+
+ PRTimeParameters retVal;
+ MachineLocation loc;
+
+ MyReadLocation(&loc);
+
+ /*
+ * On a Mac, the GMT value is in seconds east of GMT. For example,
+ * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
+ * east of GMT. The gmtDelta field is a 3-byte value contained in a
+ * long word, so you must take care to get it properly.
+ */
+
+ retVal.tp_gmt_offset = loc.u.gmtDelta & 0x00ffffff;
+ if (retVal.tp_gmt_offset & 0x00800000) { /* test sign extend bit */
+ retVal.tp_gmt_offset |= 0xff000000;
+ }
+
+ /*
+ * The daylight saving time value, dlsDelta, is a signed byte
+ * value representing the offset for the hour field -- whether
+ * to add 1 hour, subtract 1 hour, or make no change at all.
+ */
+
+ if (loc.u.dlsDelta) {
+ retVal.tp_gmt_offset -= 3600;
+ retVal.tp_dst_offset = 3600;
+ } else {
+ retVal.tp_dst_offset = 0;
+ }
+ return retVal;
+}
+
+PRIntervalTime _MD_GetInterval(void)
+{
+ PRIntervalTime retVal;
+ PRUint64 upTime, microtomilli;
+
+ /*
+ * Use the Microseconds procedure to obtain the number of
+ * microseconds elapsed since system startup time.
+ */
+ Microseconds((UnsignedWide *)&upTime);
+ LL_I2L(microtomilli, PR_USEC_PER_MSEC);
+ LL_DIV(upTime, upTime, microtomilli);
+ LL_L2I(retVal, upTime);
+
+ return retVal;
+}
+
+struct tm *Maclocaltime(const time_t * t)
+{
+ DateTimeRec dtr;
+ MachineLocation loc;
+ time_t macLocal = *t + gJanuaryFirst1970Seconds; /* GMT Mac */
+ static struct tm statictime;
+ static const short monthday[12] =
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ SecondsToDate(macLocal, &dtr);
+ statictime.tm_sec = dtr.second;
+ statictime.tm_min = dtr.minute;
+ statictime.tm_hour = dtr.hour;
+ statictime.tm_mday = dtr.day;
+ statictime.tm_mon = dtr.month - 1;
+ statictime.tm_year = dtr.year - 1900;
+ statictime.tm_wday = dtr.dayOfWeek - 1;
+ statictime.tm_yday = monthday[statictime.tm_mon]
+ + statictime.tm_mday - 1;
+ if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
+ ++statictime.tm_yday;
+ MyReadLocation(&loc);
+ statictime.tm_isdst = loc.u.dlsDelta;
+ return(&statictime);
+}
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.h
new file mode 100644
index 00000000..a78424df
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mactime.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#ifndef mactime_h__
+#define mactime_h__
+
+
+PR_BEGIN_EXTERN_C
+
+void MacintoshInitializeTime(void);
+
+
+PR_END_EXTERN_C
+
+
+#endif /* mactime_h__ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.c
new file mode 100644
index 00000000..15eea19a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.c
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: NULL; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * George Warner, Apple Computer Inc.
+ * Simon Fraser <sfraser@netscape.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 "mdcriticalregion.h"
+#include <MacErrors.h>
+
+/*
+ This code is a replacement for MPEnterCriticalRegion/MPLeaveCriticalRegion,
+ which is broken on Mac OS 10.0.x builds, but fixed in 10.1. This code works
+ everywhere.
+*/
+
+
+typedef struct MDCriticalRegionData_struct {
+ MPTaskID mMPTaskID; /* Who's in the critical region? */
+ UInt32 mDepthCount; /* How deep? */
+ MPSemaphoreID mMPSemaphoreID; /* ready semaphore */
+} MDCriticalRegionData, *MDCriticalRegionDataPtr;
+
+
+OSStatus
+MD_CriticalRegionCreate(MDCriticalRegionID * outCriticalRegionID)
+{
+ MDCriticalRegionDataPtr newCriticalRegionPtr;
+ MPSemaphoreID mpSemaphoreID;
+ OSStatus err = noErr;
+
+ if (outCriticalRegionID == NULL)
+ return paramErr;
+
+ *outCriticalRegionID = NULL;
+
+ newCriticalRegionPtr = (MDCriticalRegionDataPtr)MPAllocateAligned(sizeof(MDCriticalRegionData),
+ kMPAllocateDefaultAligned, kMPAllocateClearMask);
+ if (newCriticalRegionPtr == NULL)
+ return memFullErr;
+
+ // Note: this semaphore is pre-fired (ready!)
+ err = MPCreateBinarySemaphore(&mpSemaphoreID);
+ if (err == noErr)
+ {
+ newCriticalRegionPtr->mMPTaskID = kInvalidID;
+ newCriticalRegionPtr->mDepthCount = 0;
+ newCriticalRegionPtr->mMPSemaphoreID = mpSemaphoreID;
+
+ *outCriticalRegionID = (MDCriticalRegionID)newCriticalRegionPtr;
+ }
+ else
+ {
+ MPFree((LogicalAddress)newCriticalRegionPtr);
+ }
+
+ return err;
+}
+
+OSStatus
+MD_CriticalRegionDelete(MDCriticalRegionID inCriticalRegionID)
+{
+ MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
+ OSStatus err = noErr;
+
+ if (criticalRegion == NULL)
+ return paramErr;
+
+ if ((criticalRegion->mMPTaskID != kInvalidID) && (criticalRegion->mDepthCount > 0))
+ return kMPInsufficientResourcesErr;
+
+ if (criticalRegion->mMPSemaphoreID != kInvalidID)
+ err = MPDeleteSemaphore(criticalRegion->mMPSemaphoreID);
+ if (noErr != err) return err;
+
+ criticalRegion->mMPSemaphoreID = kInvalidID;
+ MPFree((LogicalAddress) criticalRegion);
+
+ return noErr;
+}
+
+OSStatus
+MD_CriticalRegionEnter(MDCriticalRegionID inCriticalRegionID, Duration inTimeout)
+{
+ MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
+ MPTaskID currentTaskID = MPCurrentTaskID();
+ OSStatus err = noErr;
+
+ if (criticalRegion == NULL)
+ return paramErr;
+
+ // if I'm inside the critical region...
+ if (currentTaskID == criticalRegion->mMPTaskID)
+ {
+ // bump my depth
+ criticalRegion->mDepthCount++;
+ // and continue
+ return noErr;
+ }
+
+ // wait for the ready semaphore
+ err = MPWaitOnSemaphore(criticalRegion->mMPSemaphoreID, inTimeout);
+ // we didn't get it. return the error
+ if (noErr != err) return err;
+
+ // we got it!
+ criticalRegion->mMPTaskID = currentTaskID;
+ criticalRegion->mDepthCount = 1;
+
+ return noErr;
+}
+
+OSStatus
+MD_CriticalRegionExit(MDCriticalRegionID inCriticalRegionID)
+{
+ MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID;
+ MPTaskID currentTaskID = MPCurrentTaskID();
+ OSStatus err = noErr;
+
+ // if we don't own the critical region...
+ if (currentTaskID != criticalRegion->mMPTaskID)
+ return kMPInsufficientResourcesErr;
+
+ // if we aren't at a depth...
+ if (criticalRegion->mDepthCount == 0)
+ return kMPInsufficientResourcesErr;
+
+ // un-bump my depth
+ criticalRegion->mDepthCount--;
+
+ // if we just bottomed out...
+ if (criticalRegion->mDepthCount == 0)
+ {
+ // release ownership of the structure
+ criticalRegion->mMPTaskID = kInvalidID;
+ // and signal the ready semaphore
+ err = MPSignalSemaphore(criticalRegion->mMPSemaphoreID);
+ }
+ return err;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.h
new file mode 100644
index 00000000..abcd20e3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdcriticalregion.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * George Warner, Apple Computer Inc.
+ * Simon Fraser <sfraser@netscape.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 ***** */
+
+#ifndef mdcriticalregion_h___
+#define mdcriticalregion_h___
+
+
+#ifndef __MULTIPROCESSING__
+#include <Multiprocessing.h>
+#endif
+
+typedef struct OpaqueMDCriticalRegionID* MDCriticalRegionID;
+
+OSStatus MD_CriticalRegionCreate(MDCriticalRegionID * pMDCriticalRegionID);
+
+OSStatus MD_CriticalRegionDelete(MDCriticalRegionID pMDCriticalRegionID);
+
+OSStatus MD_CriticalRegionEnter(MDCriticalRegionID pMDCriticalRegionID, Duration pTimeout);
+
+OSStatus MD_CriticalRegionExit(MDCriticalRegionID pMDCriticalRegionID);
+
+#endif /* mdcriticalregion_h___ */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.c
new file mode 100644
index 00000000..bcbb3f82
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.c
@@ -0,0 +1,776 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <Types.h>
+#include <Timer.h>
+#include <Files.h>
+#include <Errors.h>
+#include <Folders.h>
+#include <Gestalt.h>
+#include <Events.h>
+#include <Processes.h>
+#include <TextUtils.h>
+#include <MixedMode.h>
+#include <LowMem.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stat.h>
+#include <stdarg.h>
+#include <unix.h>
+
+#include "MacErrorHandling.h"
+
+#include "primpl.h"
+#include "prgc.h"
+
+#include "mactime.h"
+
+#include "mdmac.h"
+
+// undefine getenv, so that _MD_GetEnv can call the version in NSStdLib::nsEnvironment.cpp.
+#undef getenv
+
+//
+// Local routines
+//
+unsigned char GarbageCollectorCacheFlusher(PRUint32 size);
+
+extern PRThread *gPrimaryThread;
+extern ProcessSerialNumber gApplicationProcess; // in macthr.c
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark CREATING MACINTOSH THREAD STACKS
+
+
+enum {
+ uppExitToShellProcInfo = kPascalStackBased,
+ uppStackSpaceProcInfo = kRegisterBased
+ | RESULT_SIZE(SIZE_CODE(sizeof(long)))
+ | REGISTER_RESULT_LOCATION(kRegisterD0)
+ | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(UInt16)))
+};
+
+typedef CALLBACK_API( long , StackSpacePatchPtr )(UInt16 trapNo);
+typedef REGISTER_UPP_TYPE(StackSpacePatchPtr) StackSpacePatchUPP;
+
+StackSpacePatchUPP gStackSpacePatchUPP = NULL;
+UniversalProcPtr gStackSpacePatchCallThru = NULL;
+long (*gCallOSTrapUniversalProc)(UniversalProcPtr,ProcInfoType,...) = NULL;
+
+
+pascal long StackSpacePatch(UInt16 trapNo)
+{
+ char tos;
+ PRThread *thisThread;
+
+ thisThread = PR_CurrentThread();
+
+ // If we are the primary thread, then call through to the
+ // good ol' fashion stack space implementation. Otherwise,
+ // compute it by hand.
+ if ((thisThread == gPrimaryThread) ||
+ (&tos < thisThread->stack->stackBottom) ||
+ (&tos > thisThread->stack->stackTop)) {
+ return gCallOSTrapUniversalProc(gStackSpacePatchCallThru, uppStackSpaceProcInfo, trapNo);
+ }
+ else {
+ return &tos - thisThread->stack->stackBottom;
+ }
+}
+
+
+static void InstallStackSpacePatch(void)
+{
+ long systemVersion;
+ OSErr err;
+ CFragConnectionID connID;
+ Str255 errMessage;
+ Ptr interfaceLibAddr;
+ CFragSymbolClass symClass;
+ UniversalProcPtr (*getOSTrapAddressProc)(UInt16);
+ void (*setOSTrapAddressProc)(StackSpacePatchUPP, UInt16);
+ UniversalProcPtr (*newRoutineDescriptorProc)(ProcPtr,ProcInfoType,ISAType);
+
+
+ err = Gestalt(gestaltSystemVersion,&systemVersion);
+ if (systemVersion >= 0x00000A00) // we don't need to patch StackSpace()
+ return;
+
+ // open connection to "InterfaceLib"
+ err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag,
+ &connID, &interfaceLibAddr, errMessage);
+ PR_ASSERT(err == noErr);
+ if (err != noErr)
+ return;
+
+ // get symbol GetOSTrapAddress
+ err = FindSymbol(connID, "\pGetOSTrapAddress", &(Ptr)getOSTrapAddressProc, &symClass);
+ if (err != noErr)
+ return;
+
+ // get symbol SetOSTrapAddress
+ err = FindSymbol(connID, "\pSetOSTrapAddress", &(Ptr)setOSTrapAddressProc, &symClass);
+ if (err != noErr)
+ return;
+
+ // get symbol NewRoutineDescriptor
+ err = FindSymbol(connID, "\pNewRoutineDescriptor", &(Ptr)newRoutineDescriptorProc, &symClass);
+ if (err != noErr)
+ return;
+
+ // get symbol CallOSTrapUniversalProc
+ err = FindSymbol(connID, "\pCallOSTrapUniversalProc", &(Ptr)gCallOSTrapUniversalProc, &symClass);
+ if (err != noErr)
+ return;
+
+ // get and set trap address for StackSpace (A065)
+ gStackSpacePatchCallThru = getOSTrapAddressProc(0x0065);
+ if (gStackSpacePatchCallThru)
+ {
+ gStackSpacePatchUPP =
+ (StackSpacePatchUPP)newRoutineDescriptorProc((ProcPtr)(StackSpacePatch), uppStackSpaceProcInfo, GetCurrentArchitecture());
+ setOSTrapAddressProc(gStackSpacePatchUPP, 0x0065);
+ }
+
+#if DEBUG
+ StackSpace();
+#endif
+}
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark ENVIRONMENT VARIABLES
+
+
+typedef struct EnvVariable EnvVariable;
+
+struct EnvVariable {
+ char *variable;
+ char *value;
+ EnvVariable *next;
+};
+
+EnvVariable *gEnvironmentVariables = NULL;
+
+char *_MD_GetEnv(const char *name)
+{
+ EnvVariable *currentVariable = gEnvironmentVariables;
+
+ while (currentVariable) {
+ if (!strcmp(currentVariable->variable, name))
+ return currentVariable->value;
+
+ currentVariable = currentVariable->next;
+ }
+
+ return getenv(name);
+}
+
+PR_IMPLEMENT(int)
+_MD_PutEnv(const char *string)
+{
+ EnvVariable *currentVariable = gEnvironmentVariables;
+ char *variableCopy,
+ *value,
+ *current;
+
+ variableCopy = strdup(string);
+ PR_ASSERT(variableCopy != NULL);
+
+ current = variableCopy;
+ while (*current != '=')
+ current++;
+
+ *current = 0;
+ current++;
+
+ value = current;
+
+ while (currentVariable) {
+ if (!strcmp(currentVariable->variable, variableCopy))
+ break;
+
+ currentVariable = currentVariable->next;
+ }
+
+ if (currentVariable == NULL) {
+ currentVariable = PR_NEW(EnvVariable);
+
+ if (currentVariable == NULL) {
+ PR_DELETE(variableCopy);
+ return -1;
+ }
+
+ currentVariable->variable = strdup(variableCopy);
+ currentVariable->value = strdup(value);
+ currentVariable->next = gEnvironmentVariables;
+ gEnvironmentVariables = currentVariable;
+ }
+
+ else {
+ PR_DELETE(currentVariable->value);
+ currentVariable->value = strdup(current);
+
+ /* This is a temporary hack. Working on a real fix, remove this when done. */
+ /* OK, there are two ways to access the */
+ /* library path, getenv() and PR_GetLibraryPath(). Take a look at PR_GetLibraryPath(). */
+ /* You'll see that we keep the path in a global which is intialized at startup from */
+ /* a call to getenv(). From then on, they have nothing in common. */
+ /* We need to keep them in synch. */
+ if (strcmp(currentVariable->variable, "LD_LIBRARY_PATH") == 0)
+ PR_SetLibraryPath(currentVariable->value);
+ }
+
+ PR_DELETE(variableCopy);
+ return 0;
+}
+
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark MISCELLANEOUS
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(t->md.jb);
+ }
+ *np = sizeof(t->md.jb) / sizeof(PRUint32);
+ return (PRWord*) (t->md.jb);
+}
+
+void _MD_GetRegisters(PRUint32 *to)
+{
+ (void) setjmp((void*) to);
+}
+
+void _MD_EarlyInit()
+{
+ Handle environmentVariables;
+
+ GetCurrentProcess(&gApplicationProcess);
+
+ INIT_CRITICAL_REGION();
+ InitIdleSemaphore();
+
+#if !defined(MAC_NSPR_STANDALONE)
+ // MacintoshInitializeMemory(); Moved to mdmacmem.c: AllocateRawMemory(Size blockSize)
+#else
+ MacintoshInitializeMemory();
+#endif
+ MacintoshInitializeTime();
+
+ // Install resource-controlled environment variables.
+
+ environmentVariables = GetResource('Envi', 128);
+ if (environmentVariables != NULL) {
+
+ Size resourceSize;
+ char *currentPutEnvString = (char *)*environmentVariables,
+ *currentScanChar = currentPutEnvString;
+
+ resourceSize = GetHandleSize(environmentVariables);
+ DetachResource(environmentVariables);
+ HLock(environmentVariables);
+
+ while (resourceSize--) {
+
+ if ((*currentScanChar == '\n') || (*currentScanChar == '\r')) {
+ *currentScanChar = 0;
+ _MD_PutEnv (currentPutEnvString);
+ currentPutEnvString = currentScanChar + 1;
+ }
+
+ currentScanChar++;
+
+ }
+
+ DisposeHandle(environmentVariables);
+
+ }
+
+#ifdef PR_INTERNAL_LOGGING
+ _MD_PutEnv ("NSPR_LOG_MODULES=clock:6,cmon:6,io:6,mon:6,linker:6,cvar:6,sched:6,thread:6");
+#endif
+
+ InstallStackSpacePatch();
+}
+
+void _MD_FinalInit()
+{
+ _MD_InitNetAccess();
+}
+
+void PR_InitMemory(void) {
+#ifndef NSPR_AS_SHARED_LIB
+ // Needed for Mac browsers without Java. We don't want them calling PR_INIT, since it
+ // brings in all of the thread support. But we do need to allow them to initialize
+ // the NSPR memory package.
+ // This should go away when all clients of the NSPR want threads AND memory.
+ MacintoshInitializeMemory();
+#endif
+}
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark TERMINATION
+
+
+// THIS IS *** VERY *** IMPORTANT... our CFM Termination proc.
+// This allows us to deactivate our Time Mananger task even
+// if we are not totally gracefully exited. If this is not
+// done then we will randomly crash at later times when the
+// task is called after the app heap is gone.
+
+#if TARGET_CARBON
+extern OTClientContextPtr clientContext;
+#define CLOSE_OPEN_TRANSPORT() CloseOpenTransportInContext(clientContext)
+
+#else
+
+#define CLOSE_OPEN_TRANSPORT() CloseOpenTransport()
+#endif /* TARGET_CARBON */
+
+extern pascal void __NSTerminate(void);
+
+void CleanupTermProc(void)
+{
+ _MD_StopInterrupts(); // deactive Time Manager task
+
+ CLOSE_OPEN_TRANSPORT();
+ TermIdleSemaphore();
+ TERM_CRITICAL_REGION();
+
+ __NSTerminate();
+}
+
+
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark STRING OPERATIONS
+
+#if !defined(MAC_NSPR_STANDALONE)
+
+// PStrFromCStr converts the source C string to a destination
+// pascal string as it copies. The dest string will
+// be truncated to fit into an Str255 if necessary.
+// If the C String pointer is NULL, the pascal string's length is set to zero
+//
+void
+PStrFromCStr(const char* src, Str255 dst)
+{
+ short length = 0;
+
+ // handle case of overlapping strings
+ if ( (void*)src == (void*)dst )
+ {
+ unsigned char* curdst = &dst[1];
+ unsigned char thisChar;
+
+ thisChar = *(const unsigned char*)src++;
+ while ( thisChar != '\0' )
+ {
+ unsigned char nextChar;
+
+ // use nextChar so we don't overwrite what we are about to read
+ nextChar = *(const unsigned char*)src++;
+ *curdst++ = thisChar;
+ thisChar = nextChar;
+
+ if ( ++length >= 255 )
+ break;
+ }
+ }
+ else if ( src != NULL )
+ {
+ unsigned char* curdst = &dst[1];
+ short overflow = 255; // count down so test it loop is faster
+ register char temp;
+
+ // Can't do the K&R C thing of "while (*s++ = *t++)" because it will copy trailing zero
+ // which might overrun pascal buffer. Instead we use a temp variable.
+ while ( (temp = *src++) != 0 )
+ {
+ *(char*)curdst++ = temp;
+
+ if ( --overflow <= 0 )
+ break;
+ }
+ length = 255 - overflow;
+ }
+ dst[0] = length;
+}
+
+
+void CStrFromPStr(ConstStr255Param pString, char **cString)
+{
+ // Allocates a cString and copies a Pascal string into it.
+ unsigned int len;
+
+ len = pString[0];
+ *cString = malloc(len+1);
+
+ if (*cString != NULL) {
+ strncpy(*cString, (char *)&pString[1], len);
+ (*cString)[len] = NULL;
+ }
+}
+
+
+void dprintf(const char *format, ...)
+{
+#if DEBUG
+ va_list ap;
+ Str255 buffer;
+
+ va_start(ap, format);
+ buffer[0] = PR_vsnprintf((char *)buffer + 1, sizeof(buffer) - 1, format, ap);
+ va_end(ap);
+
+ DebugStr(buffer);
+#endif /* DEBUG */
+}
+
+#else
+
+void debugstr(const char *debuggerMsg)
+{
+ Str255 pStr;
+
+ PStrFromCStr(debuggerMsg, pStr);
+ DebugStr(pStr);
+}
+
+
+char *strdup(const char *source)
+{
+ char *newAllocation;
+ size_t stringLength;
+
+ PR_ASSERT(source);
+
+ stringLength = strlen(source) + 1;
+
+ newAllocation = (char *)PR_MALLOC(stringLength);
+ if (newAllocation == NULL)
+ return NULL;
+ BlockMoveData(source, newAllocation, stringLength);
+ return newAllocation;
+}
+
+// PStrFromCStr converts the source C string to a destination
+// pascal string as it copies. The dest string will
+// be truncated to fit into an Str255 if necessary.
+// If the C String pointer is NULL, the pascal string's length is set to zero
+//
+void PStrFromCStr(const char* src, Str255 dst)
+{
+ short length = 0;
+
+ // handle case of overlapping strings
+ if ( (void*)src == (void*)dst )
+ {
+ unsigned char* curdst = &dst[1];
+ unsigned char thisChar;
+
+ thisChar = *(const unsigned char*)src++;
+ while ( thisChar != '\0' )
+ {
+ unsigned char nextChar;
+
+ // use nextChar so we don't overwrite what we are about to read
+ nextChar = *(const unsigned char*)src++;
+ *curdst++ = thisChar;
+ thisChar = nextChar;
+
+ if ( ++length >= 255 )
+ break;
+ }
+ }
+ else if ( src != NULL )
+ {
+ unsigned char* curdst = &dst[1];
+ short overflow = 255; // count down so test it loop is faster
+ register char temp;
+
+ // Can't do the K&R C thing of "while (*s++ = *t++)" because it will copy trailing zero
+ // which might overrun pascal buffer. Instead we use a temp variable.
+ while ( (temp = *src++) != 0 )
+ {
+ *(char*)curdst++ = temp;
+
+ if ( --overflow <= 0 )
+ break;
+ }
+ length = 255 - overflow;
+ }
+ dst[0] = length;
+}
+
+
+void CStrFromPStr(ConstStr255Param pString, char **cString)
+{
+ // Allocates a cString and copies a Pascal string into it.
+ unsigned int len;
+
+ len = pString[0];
+ *cString = PR_MALLOC(len+1);
+
+ if (*cString != NULL) {
+ strncpy(*cString, (char *)&pString[1], len);
+ (*cString)[len] = NULL;
+ }
+}
+
+
+size_t strlen(const char *source)
+{
+ size_t currentLength = 0;
+
+ if (source == NULL)
+ return currentLength;
+
+ while (*source++ != '\0')
+ currentLength++;
+
+ return currentLength;
+}
+
+int strcmpcore(const char *str1, const char *str2, int caseSensitive)
+{
+ char currentChar1, currentChar2;
+
+ while (1) {
+
+ currentChar1 = *str1;
+ currentChar2 = *str2;
+
+ if (!caseSensitive) {
+
+ if ((currentChar1 >= 'a') && (currentChar1 <= 'z'))
+ currentChar1 += ('A' - 'a');
+
+ if ((currentChar2 >= 'a') && (currentChar2 <= 'z'))
+ currentChar2 += ('A' - 'a');
+
+ }
+
+ if (currentChar1 == '\0')
+ break;
+
+ if (currentChar1 != currentChar2)
+ return currentChar1 - currentChar2;
+
+ str1++;
+ str2++;
+
+ }
+
+ return currentChar1 - currentChar2;
+}
+
+int strcmp(const char *str1, const char *str2)
+{
+ return strcmpcore(str1, str2, true);
+}
+
+int strcasecmp(const char *str1, const char *str2)
+{
+ return strcmpcore(str1, str2, false);
+}
+
+
+void *memcpy(void *to, const void *from, size_t size)
+{
+ if (size != 0) {
+#if DEBUG
+ if ((UInt32)to < 0x1000)
+ DebugStr("\pmemcpy has illegal to argument");
+ if ((UInt32)from < 0x1000)
+ DebugStr("\pmemcpy has illegal from argument");
+#endif
+ BlockMoveData(from, to, size);
+ }
+ return to;
+}
+
+void dprintf(const char *format, ...)
+{
+ va_list ap;
+ char *buffer;
+
+ va_start(ap, format);
+ buffer = (char *)PR_vsmprintf(format, ap);
+ va_end(ap);
+
+ debugstr(buffer);
+ PR_DELETE(buffer);
+}
+
+void
+exit(int result)
+{
+#pragma unused (result)
+
+ ExitToShell();
+}
+
+void abort(void)
+{
+ exit(-1);
+}
+
+#endif
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark FLUSHING THE GARBAGE COLLECTOR
+
+#if !defined(MAC_NSPR_STANDALONE)
+
+unsigned char GarbageCollectorCacheFlusher(PRUint32)
+{
+
+ PRIntn is;
+
+ UInt32 oldPriority;
+
+ // If java wasn't completely initialized, then bail
+ // harmlessly.
+
+ if (PR_GetGCInfo()->lock == NULL)
+ return false;
+
+#if DEBUG
+ if (_MD_GET_INTSOFF() == 1)
+ DebugStr("\pGarbageCollectorCacheFlusher at interrupt time!");
+#endif
+
+ // The synchronization here is very tricky. We really
+ // don't want any other threads to run while we are
+ // cleaning up the gc heap... they could call malloc,
+ // and then we would be in trouble in a big way. So,
+ // we jack up our priority and that of the finalizer
+ // so that we won't yield to other threads.
+ // dkc 5/17/96
+
+ oldPriority = PR_GetThreadPriority(PR_GetCurrentThread());
+ _PR_INTSOFF(is);
+ _PR_SetThreadPriority(PR_GetCurrentThread(), (PRThreadPriority)30);
+ _PR_INTSON(is);
+
+ // Garbage collect twice. This will finalize any
+ // dangling AWT resources (images, components), and
+ // then free up their GC space, too.
+ // dkc 2/15/96
+ // interrupts must be on during PR_GC
+
+ PR_GC();
+
+ // By setting the finalizer priority to 31, then we
+ // ensure it will run before us. When it finishes
+ // its list of finalizations, it returns to us
+ // for the second garbage collection.
+
+ PR_Yield();
+
+ PR_GC();
+
+ // Restore our old priorities.
+
+ _PR_INTSOFF(is);
+ _PR_SetThreadPriority(PR_GetCurrentThread(), (PRThreadPriority)oldPriority);
+ _PR_INTSON(is);
+
+ return false;
+}
+
+#endif
+
+//##############################################################################
+//##############################################################################
+#pragma mark -
+#pragma mark MISCELLANEOUS-HACKS
+
+
+//
+// ***** HACK FIX THESE ****
+//
+extern long _MD_GetOSName(char *buf, long count)
+{
+ long len;
+
+ len = PR_snprintf(buf, count, "Mac OS");
+
+ return 0;
+}
+
+extern long _MD_GetOSVersion(char *buf, long count)
+{
+ long len;
+
+ len = PR_snprintf(buf, count, "7.5");
+
+ return 0;
+}
+
+extern long _MD_GetArchitecture(char *buf, long count)
+{
+ long len;
+
+#if defined(TARGET_CPU_PPC) && TARGET_CPU_PPC
+ len = PR_snprintf(buf, count, "PowerPC");
+#else
+ len = PR_snprintf(buf, count, "Motorola68k");
+#endif
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.h
new file mode 100644
index 00000000..ad8c3c4d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/mdmac.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#ifndef mdmac_h__
+#define mdmac_h__
+
+
+PR_BEGIN_EXTERN_C
+
+void PStrFromCStr(const char* src, Str255 dst);
+void CStrFromPStr(ConstStr255Param pString, char **cString);
+
+PR_END_EXTERN_C
+
+
+#endif /* mdmac_h__ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/prcpucfg.h b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/prcpucfg.h
new file mode 100644
index 00000000..17d665c6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/prcpucfg.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifndef nspr_cpucfg___
+#define nspr_cpucfg___
+
+#ifndef XP_MAC
+#define XP_MAC
+#endif
+
+#undef IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+
+#define HAVE_LONG_LONG
+
+#define PR_AF_INET6 30 /* same as AF_INET6 */
+
+#define PR_BYTES_PER_BYTE 1L
+#define PR_BYTES_PER_SHORT 2L
+#define PR_BYTES_PER_INT 4L
+#define PR_BYTES_PER_INT64 8L
+#define PR_BYTES_PER_LONG 4L
+#define PR_BYTES_PER_FLOAT 4L
+#define PR_BYTES_PER_DOUBLE 8L
+#define PR_BYTES_PER_WORD 4L
+#define PR_BYTES_PER_DWORD 8L
+
+#define PR_BITS_PER_BYTE 8L
+#define PR_BITS_PER_SHORT 16L
+#define PR_BITS_PER_INT 32L
+#define PR_BITS_PER_INT64 64L
+#define PR_BITS_PER_LONG 32L
+#define PR_BITS_PER_FLOAT 32L
+#define PR_BITS_PER_DOUBLE 64L
+#define PR_BITS_PER_WORD 32L
+
+#define PR_BITS_PER_BYTE_LOG2 3L
+#define PR_BITS_PER_SHORT_LOG2 4L
+#define PR_BITS_PER_INT_LOG2 5L
+#define PR_BITS_PER_INT64_LOG2 6L
+#define PR_BITS_PER_LONG_LOG2 5L
+#define PR_BITS_PER_FLOAT_LOG2 5L
+#define PR_BITS_PER_DOUBLE_LOG2 6L
+#define PR_BITS_PER_WORD_LOG2 5L
+
+#define PR_ALIGN_OF_SHORT 2L
+#define PR_ALIGN_OF_INT 4L
+#define PR_ALIGN_OF_LONG 4L
+#define PR_ALIGN_OF_INT64 2L
+#define PR_ALIGN_OF_FLOAT 4L
+#define PR_ALIGN_OF_DOUBLE 4L
+#define PR_ALIGN_OF_POINTER 4L
+#define PR_ALIGN_OF_WORD 4L
+
+#define PR_BYTES_PER_WORD_LOG2 2L
+#define PR_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 1L
+
+#ifndef NO_NSPR_10_SUPPORT
+#define BYTES_PER_BYTE PR_BYTES_PER_BYTE
+#define BYTES_PER_SHORT PR_BYTES_PER_SHORT
+#define BYTES_PER_INT PR_BYTES_PER_INT
+#define BYTES_PER_INT64 PR_BYTES_PER_INT64
+#define BYTES_PER_LONG PR_BYTES_PER_LONG
+#define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT
+#define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE
+#define BYTES_PER_WORD PR_BYTES_PER_WORD
+#define BYTES_PER_DWORD PR_BYTES_PER_DWORD
+
+#define BITS_PER_BYTE PR_BITS_PER_BYTE
+#define BITS_PER_SHORT PR_BITS_PER_SHORT
+#define BITS_PER_INT PR_BITS_PER_INT
+#define BITS_PER_INT64 PR_BITS_PER_INT64
+#define BITS_PER_LONG PR_BITS_PER_LONG
+#define BITS_PER_FLOAT PR_BITS_PER_FLOAT
+#define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE
+#define BITS_PER_WORD PR_BITS_PER_WORD
+
+#define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2
+#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
+#define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2
+#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
+#define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2
+#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
+#define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2
+#define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2
+
+#define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT
+#define ALIGN_OF_INT PR_ALIGN_OF_INT
+#define ALIGN_OF_LONG PR_ALIGN_OF_LONG
+#define ALIGN_OF_INT64 PR_ALIGN_OF_INT64
+#define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT
+#define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE
+#define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER
+#define ALIGN_OF_WORD PR_ALIGN_OF_WORD
+
+#define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2
+#define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2
+#define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2
+#endif /* NO_NSPR_10_SUPPORT */
+
+#endif /* nspr_cpucfg___ */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/Makefile.in
new file mode 100644
index 00000000..299cf662
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/Makefile.in
@@ -0,0 +1,85 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_TARGET), OS2)
+CSRCS = \
+ os2misc.c \
+ os2sem.c \
+ os2inrval.c \
+ os2gc.c \
+ os2thred.c \
+ os2io.c \
+ os2cv.c \
+ os2sock.c \
+ os2_errors.c \
+ os2poll.c \
+ os2rng.c \
+ $(NULL)
+endif
+
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ASFILES = os2vacpp.asm
+endif
+
+ifeq ($(MOZ_OS2_TOOLS),EMX)
+ASFILES = os2emx.s os2vaclegacy.s
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/objs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/objs.mk
new file mode 100644
index 00000000..008c2525
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/objs.mk
@@ -0,0 +1,65 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+# This makefile appends to the variable OBJS the platform-dependent
+# object modules that will be part of the nspr20 library.
+
+CSRCS = \
+ os2io.c \
+ os2sock.c \
+ os2thred.c \
+ os2cv.c \
+ os2gc.c \
+ os2misc.c \
+ os2inrval.c \
+ os2sem.c \
+ os2_errors.c \
+ os2poll.c \
+ os2rng.c \
+ $(NULL)
+
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ASFILES = os2vacpp.asm
+endif
+
+ifeq ($(MOZ_OS2_TOOLS),EMX)
+ASFILES = os2emx.s os2vaclegacy.s
+endif
+
+OBJS += $(addprefix md/os2/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
+ $(addprefix md/os2/$(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX)))
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2_errors.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2_errors.c
new file mode 100644
index 00000000..59784d0c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2_errors.c
@@ -0,0 +1,1129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prerror.h"
+#include "primpl.h"
+
+void _MD_os2_map_default_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EMSGSIZE:
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+void _MD_os2_map_opendir_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ case ERROR_INVALID_ACCESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_INVALID_NAME:
+ case ERROR_INVALID_PARAMETER:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ case ERROR_NOT_DOS_DISK:
+ case ERROR_NOT_READY:
+ case ERROR_OPEN_FAILED:
+ case ERROR_PATH_BUSY:
+ case ERROR_CANNOT_MAKE:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_DEVICE_IN_USE:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_closedir_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_ACCESS_DENIED:
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_readdir_error(PRInt32 err)
+{
+
+ switch (err) {
+ case ERROR_NO_MORE_FILES:
+ PR_SetError(PR_NO_MORE_FILES_ERROR, err);
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_NOT_DOS_DISK:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_BROKEN_PIPE:
+ case ERROR_NOT_READY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_delete_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_WRITE_PROTECT:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_LOCKED:
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+/* The error code for stat() is in errno. */
+void _MD_os2_map_stat_error(PRInt32 err)
+{
+ switch (err) {
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ }
+}
+
+void _MD_os2_map_fstat_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_LOCKED:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_rename_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_INVALID_NAME:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_FILE_EXISTS:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+/* The error code for access() is in errno. */
+void _MD_os2_map_access_error(PRInt32 err)
+{
+ switch (err) {
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ }
+}
+
+void _MD_os2_map_mkdir_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_FILE_EXISTS:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_INVALID_NAME:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_DISK_FULL:
+ case ERROR_HANDLE_DISK_FULL:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ERROR_WRITE_PROTECT:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_rmdir_error(PRInt32 err)
+{
+
+ switch (err) {
+ case ERROR_FILE_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_INVALID_NAME:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_WRITE_PROTECT:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_read_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_LOCKED:
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_transmitfile_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_LOCKED:
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_write_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ case ERROR_WRITE_PROTECT:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_LOCKED:
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ case ERROR_DISK_FULL:
+ case ERROR_HANDLE_DISK_FULL:
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EMSGSIZE:
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_lseek_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_SEEK_ON_DEVICE:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_fsync_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ case ERROR_WRITE_PROTECT:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_DISK_FULL:
+ case ERROR_HANDLE_DISK_FULL:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_close_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_INVALID_HANDLE:
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_socket_error(PRInt32 err)
+{
+ switch (err) {
+ case EPROTONOSUPPORT:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_recv_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_recvfrom_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_send_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EMSGSIZE:
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ERROR_NETNAME_DELETED:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_sendto_error(PRInt32 err)
+{
+ _MD_os2_map_default_error(err);
+}
+
+void _MD_os2_map_writev_error(int err)
+{
+ _MD_os2_map_default_error(err);
+}
+
+void _MD_os2_map_accept_error(PRInt32 err)
+{
+ _MD_os2_map_default_error(err);
+}
+
+void _MD_os2_map_acceptex_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+/*
+ * An error code of 0 means that the nonblocking connect succeeded.
+ */
+
+int _MD_os2_get_nonblocking_connect_error(int osfd)
+{
+ int err;
+ int len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == -1) {
+ return sock_errno();
+ } else {
+ return err;
+ }
+}
+
+void _MD_os2_map_connect_error(PRInt32 err)
+{
+ switch (err) {
+ case EWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EINPROGRESS:
+ PR_SetError(PR_IN_PROGRESS_ERROR, err);
+ break;
+ case EALREADY:
+ case EINVAL:
+ PR_SetError(PR_ALREADY_INITIATED_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case ENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_bind_error(PRInt32 err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_SOCKET_ADDRESS_IS_BOUND_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_listen_error(PRInt32 err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case EOPNOTSUPP:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_shutdown_error(PRInt32 err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case ENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+#ifndef XP_OS2_VACPP
+void _MD_os2_map_socketpair_error(PRInt32 err)
+{
+ switch (err) {
+ case ENOMEM:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EPROTONOSUPPORT:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EOPNOTSUPP:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+ case EPROTOTYPE:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ _MD_os2_map_default_error(err);
+ return;
+ }
+}
+#endif
+
+void _MD_os2_map_getsockname_error(PRInt32 err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_getpeername_error(PRInt32 err)
+{
+
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case ENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_getsockopt_error(PRInt32 err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case ENOPROTOOPT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case EINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_setsockopt_error(PRInt32 err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case ENOPROTOOPT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case EINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_open_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_FILE_EXISTS:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_INVALID_NAME:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ERROR_NOT_READY:
+ case ERROR_OPEN_FAILED:
+ case ERROR_PATH_BUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ERROR_DISK_FULL:
+ case ERROR_HANDLE_DISK_FULL:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ERROR_WRITE_PROTECT:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_gethostname_error(PRInt32 err)
+{
+ switch (err) {
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#endif
+ case ENETDOWN:
+ case EINPROGRESS:
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_os2_map_select_error(PRInt32 err)
+{
+ PRErrorCode prerror;
+
+ switch (err) {
+ /*
+ * OS/2 select() only works on sockets. So in this
+ * context, ENOTSOCK is equivalent to EBADF on Unix.
+ */
+ case ENOTSOCK:
+ prerror = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case EINVAL:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+#ifdef SOCEFAULT
+ case SOCEFAULT:
+ prerror = PR_ACCESS_FAULT_ERROR;
+ break;
+#endif
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ }
+ PR_SetError(prerror, err);
+}
+
+void _MD_os2_map_lockf_error(PRInt32 err)
+{
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ERROR_INVALID_HANDLE:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ERROR_INVALID_ADDRESS:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_LOCKED:
+ case ERROR_SHARING_VIOLATION:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_MORE_DATA:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2cv.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2cv.c
new file mode 100644
index 00000000..7e80993b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2cv.c
@@ -0,0 +1,432 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * os2cv.c -- OS/2 Machine-Dependent Code for Condition Variables
+ *
+ * We implement our own condition variable wait queue. Each thread
+ * has a semaphore object (thread->md.blocked_sema) to block on while
+ * waiting on a condition variable.
+ *
+ * We use a deferred condition notify algorithm. When PR_NotifyCondVar
+ * or PR_NotifyAllCondVar is called, the condition notifies are simply
+ * recorded in the _MDLock structure. We defer the condition notifies
+ * until right after we unlock the lock. This way the awakened threads
+ * have a better chance to reaquire the lock.
+ */
+
+#include "primpl.h"
+
+#ifdef USE_RAMSEM
+ULONG _Far16 _Pascal Dos16GetInfoSeg(PSEL pselGlobal, PSEL pselLocal);
+
+#ifdef XP_OS2_EMX
+typedef unsigned short BOOL16;
+#endif
+
+typedef struct _LINFOSEG
+{
+ USHORT pidCurrent;
+ USHORT pidParent;
+ USHORT prtyCurrent;
+ USHORT tidCurrent;
+ USHORT sgCurrent;
+ UCHAR rfProcStatus;
+ UCHAR dummy1;
+ BOOL16 fForeground;
+ UCHAR typProcess;
+ UCHAR dummy2;
+ SEL selEnvironment;
+ USHORT offCmdLine;
+ USHORT cbDataSegment;
+ USHORT cbStack;
+ USHORT cbHeap;
+ USHORT hmod;
+ SEL selDS;
+ SEL selPack;
+ SEL selPackShr;
+ SEL selPackPck;
+ ULONG ulReserved;
+} LINFOSEG;
+typedef LINFOSEG FAR *PLINFOSEG;
+
+PLINFOSEG plisCurrent = NULL;
+#endif
+
+/*
+ * AddThreadToCVWaitQueueInternal --
+ *
+ * Add the thread to the end of the condition variable's wait queue.
+ * The CV's lock must be locked when this function is called.
+ */
+
+static void
+AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv)
+{
+ PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
+ || (cv->waitTail == NULL && cv->waitHead == NULL));
+ cv->nwait += 1;
+ thred->md.inCVWaitQueue = PR_TRUE;
+ thred->md.next = NULL;
+ thred->md.prev = cv->waitTail;
+ if (cv->waitHead == NULL) {
+ cv->waitHead = thred;
+ } else {
+ cv->waitTail->md.next = thred;
+ }
+ cv->waitTail = thred;
+}
+
+/*
+ * md_UnlockAndPostNotifies --
+ *
+ * Unlock the lock, and then do the deferred condition notifies.
+ * If waitThred and waitCV are not NULL, waitThred is added to
+ * the wait queue of waitCV before the lock is unlocked.
+ *
+ * This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK,
+ * the two places where a lock is unlocked.
+ */
+void
+md_UnlockAndPostNotifies(
+ _MDLock *lock,
+ PRThread *waitThred,
+ _MDCVar *waitCV)
+{
+ PRIntn index;
+ _MDNotified post;
+ _MDNotified *notified, *prev = NULL;
+
+ /*
+ * Time to actually notify any conditions that were affected
+ * while the lock was held. Get a copy of the list that's in
+ * the lock structure and then zero the original. If it's
+ * linked to other such structures, we own that storage.
+ */
+ post = lock->notified; /* a safe copy; we own the lock */
+
+#if defined(DEBUG)
+ memset(&lock->notified, 0, sizeof(_MDNotified)); /* reset */
+#else
+ lock->notified.length = 0; /* these are really sufficient */
+ lock->notified.link = NULL;
+#endif
+
+ /*
+ * Figure out how many threads we need to wake up.
+ */
+ notified = &post; /* this is where we start */
+ do {
+ for (index = 0; index < notified->length; ++index) {
+ _MDCVar *cv = notified->cv[index].cv;
+ PRThread *thred;
+ int i;
+
+ /* Fast special case: no waiting threads */
+ if (cv->waitHead == NULL) {
+ notified->cv[index].notifyHead = NULL;
+ continue;
+ }
+
+ /* General case */
+ if (-1 == notified->cv[index].times) {
+ /* broadcast */
+ thred = cv->waitHead;
+ while (thred != NULL) {
+ thred->md.inCVWaitQueue = PR_FALSE;
+ thred = thred->md.next;
+ }
+ notified->cv[index].notifyHead = cv->waitHead;
+ cv->waitHead = cv->waitTail = NULL;
+ cv->nwait = 0;
+ } else {
+ thred = cv->waitHead;
+ i = notified->cv[index].times;
+ while (thred != NULL && i > 0) {
+ thred->md.inCVWaitQueue = PR_FALSE;
+ thred = thred->md.next;
+ i--;
+ }
+ notified->cv[index].notifyHead = cv->waitHead;
+ cv->waitHead = thred;
+ if (cv->waitHead == NULL) {
+ cv->waitTail = NULL;
+ } else {
+ if (cv->waitHead->md.prev != NULL) {
+ cv->waitHead->md.prev->md.next = NULL;
+ cv->waitHead->md.prev = NULL;
+ }
+ }
+ cv->nwait -= notified->cv[index].times - i;
+ }
+ }
+ notified = notified->link;
+ } while (NULL != notified);
+
+ if (waitThred) {
+ AddThreadToCVWaitQueueInternal(waitThred, waitCV);
+ }
+
+ /* Release the lock before notifying */
+#ifdef USE_RAMSEM
+ SemReleasex86(&lock->mutex, 0);
+#else
+ DosReleaseMutexSem(lock->mutex);
+#endif
+
+ notified = &post; /* this is where we start */
+ do {
+ for (index = 0; index < notified->length; ++index) {
+ PRThread *thred;
+ PRThread *next;
+
+ thred = notified->cv[index].notifyHead;
+ while (thred != NULL) {
+ BOOL rv;
+
+ next = thred->md.next;
+ thred->md.prev = thred->md.next = NULL;
+ rv = DosPostEventSem(thred->md.blocked_sema);
+ PR_ASSERT(rv == NO_ERROR);
+ thred = next;
+ }
+ }
+ prev = notified;
+ notified = notified->link;
+ if (&post != prev) PR_DELETE(prev);
+ } while (NULL != notified);
+}
+
+/*
+ * Notifies just get posted to the protecting mutex. The
+ * actual notification is done when the lock is released so that
+ * MP systems don't contend for a lock that they can't have.
+ */
+static void md_PostNotifyToCvar(_MDCVar *cvar, _MDLock *lock,
+ PRBool broadcast)
+{
+ PRIntn index = 0;
+ _MDNotified *notified = &lock->notified;
+
+ while (1) {
+ for (index = 0; index < notified->length; ++index) {
+ if (notified->cv[index].cv == cvar) {
+ if (broadcast) {
+ notified->cv[index].times = -1;
+ } else if (-1 != notified->cv[index].times) {
+ notified->cv[index].times += 1;
+ }
+ return;
+ }
+ }
+ /* if not full, enter new CV in this array */
+ if (notified->length < _MD_CV_NOTIFIED_LENGTH) break;
+
+ /* if there's no link, create an empty array and link it */
+ if (NULL == notified->link) {
+ notified->link = PR_NEWZAP(_MDNotified);
+ }
+
+ notified = notified->link;
+ }
+
+ /* A brand new entry in the array */
+ notified->cv[index].times = (broadcast) ? -1 : 1;
+ notified->cv[index].cv = cvar;
+ notified->length += 1;
+}
+
+/*
+ * _PR_MD_NEW_CV() -- Creating new condition variable
+ * ... Solaris uses cond_init() in similar function.
+ *
+ * returns: -1 on failure
+ * 0 when it succeeds.
+ *
+ */
+PRInt32
+_PR_MD_NEW_CV(_MDCVar *cv)
+{
+ cv->magic = _MD_MAGIC_CV;
+ /*
+ * The waitHead, waitTail, and nwait fields are zeroed
+ * when the PRCondVar structure is created.
+ */
+ return 0;
+}
+
+void _PR_MD_FREE_CV(_MDCVar *cv)
+{
+ cv->magic = (PRUint32)-1;
+ return;
+}
+
+/*
+ * _PR_MD_WAIT_CV() -- Wait on condition variable
+ */
+void
+_PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
+{
+ PRThread *thred = _PR_MD_CURRENT_THREAD();
+ ULONG rv, count;
+ ULONG msecs = (timeout == PR_INTERVAL_NO_TIMEOUT) ?
+ SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(timeout);
+
+ /*
+ * If we have pending notifies, post them now.
+ */
+ if (0 != lock->notified.length) {
+ md_UnlockAndPostNotifies(lock, thred, cv);
+ } else {
+ AddThreadToCVWaitQueueInternal(thred, cv);
+#ifdef USE_RAMSEM
+ SemReleasex86( &lock->mutex, 0 );
+#else
+ DosReleaseMutexSem(lock->mutex);
+#endif
+ }
+
+ /* Wait for notification or timeout; don't really care which */
+ rv = DosWaitEventSem(thred->md.blocked_sema, msecs);
+ if (rv == NO_ERROR) {
+ DosResetEventSem(thred->md.blocked_sema, &count);
+ }
+
+#ifdef USE_RAMSEM
+ SemRequest486(&(lock->mutex), -1);
+#else
+ DosRequestMutexSem((lock->mutex), SEM_INDEFINITE_WAIT);
+#endif
+
+ PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT || rv == ERROR_INTERRUPT);
+
+ if(rv == ERROR_TIMEOUT || rv == ERROR_INTERRUPT)
+ {
+ if (thred->md.inCVWaitQueue) {
+ PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
+ || (cv->waitTail == NULL && cv->waitHead == NULL));
+ cv->nwait -= 1;
+ thred->md.inCVWaitQueue = PR_FALSE;
+ if (cv->waitHead == thred) {
+ cv->waitHead = thred->md.next;
+ if (cv->waitHead == NULL) {
+ cv->waitTail = NULL;
+ } else {
+ cv->waitHead->md.prev = NULL;
+ }
+ } else {
+ PR_ASSERT(thred->md.prev != NULL);
+ thred->md.prev->md.next = thred->md.next;
+ if (thred->md.next != NULL) {
+ thred->md.next->md.prev = thred->md.prev;
+ } else {
+ PR_ASSERT(cv->waitTail == thred);
+ cv->waitTail = thred->md.prev;
+ }
+ }
+ thred->md.next = thred->md.prev = NULL;
+ } else {
+ /*
+ * This thread must have been notified, but the
+ * SemRelease call happens after SemRequest
+ * times out. Wait on the semaphore again to make it
+ * non-signaled. We assume this wait won't take long.
+ */
+ rv = DosWaitEventSem(thred->md.blocked_sema, SEM_INDEFINITE_WAIT);
+ if (rv == NO_ERROR) {
+ DosResetEventSem(thred->md.blocked_sema, &count);
+ }
+ PR_ASSERT(rv == NO_ERROR);
+ }
+ }
+ PR_ASSERT(thred->md.inCVWaitQueue == PR_FALSE);
+ return;
+} /* --- end _PR_MD_WAIT_CV() --- */
+
+void
+_PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock)
+{
+ md_PostNotifyToCvar(cv, lock, PR_FALSE);
+ return;
+}
+
+PRStatus
+_PR_MD_NEW_LOCK(_MDLock *lock)
+{
+#ifdef USE_RAMSEM
+ // It's better if this API traps when pCriticalSect is not a valid
+ // pointer, because we can't return an error code and if we just return
+ // the API caller will have nasty bugs that are hard to find.
+
+ PRAMSEM pramsem = (PRAMSEM)(&(lock->mutex));
+ /* First time, set up addresses of processor specific functions
+ */
+ if (plisCurrent == NULL)
+ {
+ SEL selGlobal = 0, selLocal = 0;
+
+ /* Convert 16 bit global information segment to 32 bit address
+ * by performing CRMA on the 16 bit address: "shift" operation
+ * to convert sel to flat, "and" operation to mask the address
+ * to 32-bit
+ */
+ Dos16GetInfoSeg(&selGlobal, &selLocal);
+ plisCurrent = (PLINFOSEG)(((ULONG)selLocal << 13) &
+ (ULONG)0x1fff0000);
+
+ }
+
+ memset(pramsem, 0, sizeof(pramsem));
+ DosCreateEventSem(0, &pramsem->hevSem, DC_SEM_SHARED, 0);
+
+ lock->notified.length=0;
+ lock->notified.link=NULL;
+ return PR_SUCCESS;
+#else
+ DosCreateMutexSem(0, &(lock->mutex), 0, 0);
+ (lock)->notified.length=0;
+ (lock)->notified.link=NULL;
+ return PR_SUCCESS;
+#endif
+}
+
+void
+_PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock)
+{
+ md_PostNotifyToCvar(cv, lock, PR_TRUE);
+ return;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2emx.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2emx.s
new file mode 100644
index 00000000..4dd81e39
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2emx.s
@@ -0,0 +1,111 @@
+/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/
+/ 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 Portable Runtime (NSPR).
+/
+/ 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.
+/
+
+/ PRInt32 __PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
+/
+/ Atomically increment the integer pointed to by 'val' and return
+/ the result of the increment.
+/
+ .text
+ .globl __PR_MD_ATOMIC_INCREMENT
+ .align 4
+__PR_MD_ATOMIC_INCREMENT:
+ movl 4(%esp), %ecx
+ movl $1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ incl %eax
+ ret
+
+/ PRInt32 __PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
+/
+/ Atomically decrement the integer pointed to by 'val' and return
+/ the result of the decrement.
+/
+ .text
+ .globl __PR_MD_ATOMIC_DECREMENT
+ .align 4
+__PR_MD_ATOMIC_DECREMENT:
+ movl 4(%esp), %ecx
+ movl $-1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ decl %eax
+ ret
+
+/ PRInt32 __PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+/
+/ Atomically set the integer pointed to by 'val' to the new
+/ value 'newval' and return the old value.
+/
+/ An alternative implementation:
+/ .text
+/ .globl __PR_MD_ATOMIC_SET
+/ .align 4
+/__PR_MD_ATOMIC_SET:
+/ movl 4(%esp), %ecx
+/ movl 8(%esp), %edx
+/ movl (%ecx), %eax
+/retry:
+/ lock
+/ cmpxchgl %edx, (%ecx)
+/ jne retry
+/ ret
+/
+ .text
+ .globl __PR_MD_ATOMIC_SET
+ .align 4
+__PR_MD_ATOMIC_SET:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ lock
+ xchgl %eax, (%ecx)
+ ret
+
+/ PRInt32 __PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+/
+/ Atomically add 'val' to the integer pointed to by 'ptr'
+/ and return the result of the addition.
+/
+ .text
+ .globl __PR_MD_ATOMIC_ADD
+ .align 4
+__PR_MD_ATOMIC_ADD:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ movl %eax, %edx
+ lock
+ xaddl %eax, (%ecx)
+ addl %edx, %eax
+ ret
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2gc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2gc.c
new file mode 100644
index 00000000..d9f76466
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2gc.c
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * GC related routines
+ *
+ */
+#include "primpl.h"
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ CONTEXTRECORD context;
+ context.ContextFlags = CONTEXT_INTEGER;
+
+ if (_PR_IS_NATIVE_THREAD(t)) {
+ context.ContextFlags |= CONTEXT_CONTROL;
+ if (QueryThreadContext(t->md.handle, CONTEXT_CONTROL, &context)) {
+ t->md.gcContext[0] = context.ctx_RegEax;
+ t->md.gcContext[1] = context.ctx_RegEbx;
+ t->md.gcContext[2] = context.ctx_RegEcx;
+ t->md.gcContext[3] = context.ctx_RegEdx;
+ t->md.gcContext[4] = context.ctx_RegEsi;
+ t->md.gcContext[5] = context.ctx_RegEdi;
+ t->md.gcContext[6] = context.ctx_RegEsp;
+ t->md.gcContext[7] = context.ctx_RegEbp;
+ *np = PR_NUM_GCREGS;
+ } else {
+ PR_ASSERT(0);/* XXX */
+ }
+ }
+ return (PRWord *)&t->md.gcContext;
+}
+
+/* This function is not used right now, but is left as a reference.
+ * If you ever need to get the fiberID from the currently running fiber,
+ * this is it.
+ */
+void *
+GetMyFiberID()
+{
+ void *fiberData = 0;
+
+ /* A pointer to our tib entry is found at FS:[18]
+ * At offset 10h is the fiberData pointer. The context of the
+ * fiber is stored in there.
+ */
+#ifdef HAVE_ASM
+ __asm {
+ mov EDX, FS:[18h]
+ mov EAX, DWORD PTR [EDX+10h]
+ mov [fiberData], EAX
+ }
+#endif
+
+ return fiberData;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2inrval.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2inrval.c
new file mode 100644
index 00000000..aa928ed3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2inrval.c
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * OS/2 interval timers
+ *
+ */
+
+#include "primpl.h"
+
+static PRBool useHighResTimer = PR_FALSE;
+PRIntervalTime _os2_ticksPerSec = -1;
+PRIntn _os2_bitShift = 0;
+PRInt32 _os2_highMask = 0;
+
+void
+_PR_MD_INTERVAL_INIT()
+{
+ ULONG timerFreq = 0; /* OS/2 high-resolution timer frequency in Hz */
+ APIRET rc = DosTmrQueryFreq(&timerFreq);
+ if (NO_ERROR == rc) {
+ useHighResTimer = PR_TRUE;
+ PR_ASSERT(timerFreq != 0);
+ while (timerFreq > PR_INTERVAL_MAX) {
+ timerFreq >>= 1;
+ _os2_bitShift++;
+ _os2_highMask = (_os2_highMask << 1)+1;
+ }
+
+ _os2_ticksPerSec = timerFreq;
+ PR_ASSERT(_os2_ticksPerSec > PR_INTERVAL_MIN);
+ }
+}
+
+PRIntervalTime
+_PR_MD_GET_INTERVAL()
+{
+ if (useHighResTimer) {
+ QWORD timestamp;
+ PRInt32 top;
+ APIRET rc = DosTmrQueryTime(&timestamp);
+ if (NO_ERROR != rc) {
+ return -1;
+ }
+ /* Sadly, nspr requires the interval to range from 1000 ticks per
+ * second to only 100000 ticks per second. DosTmrQueryTime is too
+ * high resolution...
+ */
+ top = timestamp.ulHi & _os2_highMask;
+ top = top << (32 - _os2_bitShift);
+ timestamp.ulLo = timestamp.ulLo >> _os2_bitShift;
+ timestamp.ulLo = timestamp.ulLo + top;
+ return (PRUint32)timestamp.ulLo;
+ } else {
+ ULONG msCount = -1;
+ DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount));
+ return msCount;
+ }
+}
+
+PRIntervalTime
+_PR_MD_INTERVAL_PER_SEC()
+{
+ if (useHighResTimer) {
+ return _os2_ticksPerSec;
+ } else {
+ return 1000;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2io.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2io.c
new file mode 100644
index 00000000..6a90ed51
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2io.c
@@ -0,0 +1,907 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/*
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 03/23/2000 IBM Corp. Changed write() to DosWrite(). EMX i/o
+ * calls cannot be intermixed with DosXXX
+ * calls since EMX remaps file/socket
+ * handles.
+ * 04/27/2000 IBM Corp. Changed open file to be more like NT and
+ * better handle PR_TRUNCATE | PR_CREATE_FILE
+ * and also fixed _PR_MD_SET_FD_INHERITABLE
+ */
+
+/* OS2 IO module
+ *
+ * Assumes synchronous I/O.
+ *
+ */
+
+#include "primpl.h"
+#include "prio.h"
+#include <ctype.h>
+#include <string.h>
+#ifdef XP_OS2_VACPP
+#include <direct.h>
+#else
+#include <limits.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+struct _MDLock _pr_ioq_lock;
+
+PRStatus
+_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PRInt32 rv;
+ ULONG count;
+
+ PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
+ SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks);
+ rv = DosWaitEventSem(thread->md.blocked_sema, msecs);
+ DosResetEventSem(thread->md.blocked_sema, &count);
+ switch(rv)
+ {
+ case NO_ERROR:
+ return PR_SUCCESS;
+ break;
+ case ERROR_TIMEOUT:
+ _PR_THREAD_LOCK(thread);
+ if (thread->state == _PR_IO_WAIT) {
+ ;
+ } else {
+ if (thread->wait.cvar != NULL) {
+ thread->wait.cvar = NULL;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The CVAR was notified just as the timeout
+ * occurred. This led to us being notified twice.
+ * call SemRequest() to clear the semaphore.
+ */
+ _PR_THREAD_UNLOCK(thread);
+ rv = DosWaitEventSem(thread->md.blocked_sema, 0);
+ DosResetEventSem(thread->md.blocked_sema, &count);
+ PR_ASSERT(rv == NO_ERROR);
+ }
+ }
+ return PR_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ return PR_FAILURE;
+}
+PRStatus
+_PR_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if ( _PR_IS_NATIVE_THREAD(thread) )
+ {
+ if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+ }
+}
+
+
+/* --- FILE IO ----------------------------------------------------------- */
+/*
+ * _PR_MD_OPEN() -- Open a file
+ *
+ * returns: a fileHandle
+ *
+ * The NSPR open flags (osflags) are translated into flags for OS/2
+ *
+ * Mode seems to be passed in as a unix style file permissions argument
+ * as in 0666, in the case of opening the logFile.
+ *
+ */
+PRInt32
+_PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
+{
+ HFILE file;
+ PRInt32 access = OPEN_SHARE_DENYNONE;
+ PRInt32 flags = 0L;
+ APIRET rc = 0;
+ PRUword actionTaken;
+
+ ULONG fattr;
+
+ if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH;
+
+ /* we don't want to let children inherit file handles by default */
+ access |= OPEN_FLAGS_NOINHERIT;
+
+ if (osflags & PR_RDONLY)
+ access |= OPEN_ACCESS_READONLY;
+ else if (osflags & PR_WRONLY)
+ access |= OPEN_ACCESS_WRITEONLY;
+ else if(osflags & PR_RDWR)
+ access |= OPEN_ACCESS_READWRITE;
+
+ if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
+ {
+ flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
+ }
+ else if (osflags & PR_CREATE_FILE)
+ {
+ if (osflags & PR_TRUNCATE)
+ flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
+ else
+ flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ }
+ else
+ {
+ if (osflags & PR_TRUNCATE)
+ flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
+ else
+ flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ }
+
+ if (isxdigit(mode) == 0) /* file attribs are hex, UNIX modes octal */
+ fattr = ((ULONG)mode == FILE_HIDDEN) ? FILE_HIDDEN : FILE_NORMAL;
+ else fattr = FILE_NORMAL;
+
+ do {
+ rc = DosOpen((char*)name,
+ &file, /* file handle if successful */
+ &actionTaken, /* reason for failure */
+ 0, /* initial size of new file */
+ fattr, /* file system attributes */
+ flags, /* Open flags */
+ access, /* Open mode and rights */
+ 0); /* OS/2 Extended Attributes */
+ if (rc == ERROR_TOO_MANY_OPEN_FILES) {
+ ULONG CurMaxFH = 0;
+ LONG ReqCount = 20;
+ APIRET rc2;
+ rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
+ if (rc2 != NO_ERROR) {
+ break;
+ }
+ }
+ } while (rc == ERROR_TOO_MANY_OPEN_FILES);
+
+ if (rc != NO_ERROR) {
+ _PR_MD_MAP_OPEN_ERROR(rc);
+ return -1;
+ }
+
+ return (PRInt32)file;
+}
+
+PRInt32
+_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
+{
+ ULONG bytes;
+ int rv;
+
+ rv = DosRead((HFILE)fd->secret->md.osfd,
+ (PVOID)buf,
+ len,
+ &bytes);
+
+ if (rv != NO_ERROR)
+ {
+ /* ERROR_HANDLE_EOF can only be returned by async io */
+ PR_ASSERT(rv != ERROR_HANDLE_EOF);
+ if (rv == ERROR_BROKEN_PIPE)
+ return 0;
+ else {
+ _PR_MD_MAP_READ_ERROR(rv);
+ return -1;
+ }
+ }
+ return (PRInt32)bytes;
+}
+
+PRInt32
+_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
+{
+ PRInt32 bytes;
+ int rv;
+
+ rv = DosWrite((HFILE)fd->secret->md.osfd,
+ (PVOID)buf,
+ len,
+ (PULONG)&bytes);
+
+ if (rv != NO_ERROR)
+ {
+ _PR_MD_MAP_WRITE_ERROR(rv);
+ return -1;
+ }
+
+ if (len != bytes) {
+ rv = ERROR_DISK_FULL;
+ _PR_MD_MAP_WRITE_ERROR(rv);
+ return -1;
+ }
+
+ return bytes;
+} /* --- end _PR_MD_WRITE() --- */
+
+PRInt32
+_PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
+{
+ PRInt32 rv;
+ PRUword newLocation;
+
+ rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation);
+
+ if (rv != NO_ERROR) {
+ _PR_MD_MAP_LSEEK_ERROR(rv);
+ return -1;
+ } else
+ return newLocation;
+}
+
+PRInt64
+_PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
+{
+#ifdef NO_LONG_LONG
+ PRInt64 result;
+ PRInt32 rv, low = offset.lo, hi = offset.hi;
+ PRUword newLocation;
+
+ rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation);
+ rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation);
+
+ if (rv != NO_ERROR) {
+ _PR_MD_MAP_LSEEK_ERROR(rv);
+ hi = newLocation = -1;
+ }
+
+ result.lo = newLocation;
+ result.hi = hi;
+ return result;
+
+#else
+ PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32);
+ PRUint64 rv;
+ PRUint32 newLocation, uhi;
+
+ switch (whence)
+ {
+ case PR_SEEK_SET:
+ where = FILE_BEGIN;
+ break;
+ case PR_SEEK_CUR:
+ where = FILE_CURRENT;
+ break;
+ case PR_SEEK_END:
+ where = FILE_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+}
+
+ rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation);
+
+ if (rc != NO_ERROR) {
+ _PR_MD_MAP_LSEEK_ERROR(rc);
+ return -1;
+ }
+
+ uhi = (PRUint32)hi;
+ PR_ASSERT((PRInt32)uhi >= 0);
+ rv = uhi;
+ PR_ASSERT((PRInt64)rv >= 0);
+ rv = (rv << 32);
+ PR_ASSERT((PRInt64)rv >= 0);
+ rv += newLocation;
+ PR_ASSERT((PRInt64)rv >= 0);
+ return (PRInt64)rv;
+#endif
+}
+
+PRInt32
+_PR_MD_FSYNC(PRFileDesc *fd)
+{
+ PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd);
+
+ if (rc != NO_ERROR) {
+ if (rc != ERROR_ACCESS_DENIED) {
+ _PR_MD_MAP_FSYNC_ERROR(rc);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+PRInt32
+_MD_CloseFile(PRInt32 osfd)
+{
+ PRInt32 rv;
+
+ rv = DosClose((HFILE)osfd);
+ if (rv != NO_ERROR)
+ _PR_MD_MAP_CLOSE_ERROR(rv);
+ return rv;
+}
+
+
+/* --- DIR IO ------------------------------------------------------------ */
+#define GetFileFromDIR(d) (d)->d_entry.achName
+#define GetFileAttr(d) (d)->d_entry.attrFile
+
+void FlipSlashes(char *cp, int len)
+{
+ while (--len >= 0) {
+ if (cp[0] == '/') {
+ cp[0] = PR_DIRECTORY_SEPARATOR;
+ }
+ cp++;
+ }
+}
+
+/*
+**
+** Local implementations of standard Unix RTL functions which are not provided
+** by the VAC RTL.
+**
+*/
+
+PRInt32
+_PR_MD_CLOSE_DIR(_MDDir *d)
+{
+ PRInt32 rc;
+
+ if ( d ) {
+ rc = DosFindClose(d->d_hdl);
+ if(rc == NO_ERROR){
+ d->magic = (PRUint32)-1;
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_CLOSEDIR_ERROR(rc);
+ return PR_FAILURE;
+ }
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+}
+
+
+PRStatus
+_PR_MD_OPEN_DIR(_MDDir *d, const char *name)
+{
+ char filename[ CCHMAXPATH ];
+ PRUword numEntries, rc;
+
+ numEntries = 1;
+
+ PR_snprintf(filename, CCHMAXPATH, "%s%s%s",
+ name, PR_DIRECTORY_SEPARATOR_STR, "*.*");
+ FlipSlashes( filename, strlen(filename) );
+
+ d->d_hdl = HDIR_CREATE;
+
+ rc = DosFindFirst( filename,
+ &d->d_hdl,
+ FILE_DIRECTORY | FILE_HIDDEN,
+ &(d->d_entry),
+ sizeof(d->d_entry),
+ &numEntries,
+ FIL_STANDARD);
+ if ( rc != NO_ERROR ) {
+ _PR_MD_MAP_OPENDIR_ERROR(rc);
+ return PR_FAILURE;
+ }
+ d->firstEntry = PR_TRUE;
+ d->magic = _MD_MAGIC_DIR;
+ return PR_SUCCESS;
+}
+
+char *
+_PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
+{
+ PRUword numFiles = 1;
+ BOOL rv;
+ char *fileName;
+ USHORT fileAttr;
+
+ if ( d ) {
+ while (1) {
+ if (d->firstEntry) {
+ d->firstEntry = PR_FALSE;
+ rv = NO_ERROR;
+ } else {
+ rv = DosFindNext(d->d_hdl,
+ &(d->d_entry),
+ sizeof(d->d_entry),
+ &numFiles);
+ }
+ if (rv != NO_ERROR) {
+ break;
+ }
+ fileName = GetFileFromDIR(d);
+ fileAttr = GetFileAttr(d);
+ if ( (flags & PR_SKIP_DOT) &&
+ (fileName[0] == '.') && (fileName[1] == '\0'))
+ continue;
+ if ( (flags & PR_SKIP_DOT_DOT) &&
+ (fileName[0] == '.') && (fileName[1] == '.') &&
+ (fileName[2] == '\0'))
+ continue;
+ /*
+ * XXX
+ * Is this the correct definition of a hidden file on OS/2?
+ */
+ if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN))
+ return fileName;
+ else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN))
+ continue;
+ return fileName;
+ }
+ PR_ASSERT(NO_ERROR != rv);
+ _PR_MD_MAP_READDIR_ERROR(rv);
+ return NULL;
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+}
+
+PRInt32
+_PR_MD_DELETE(const char *name)
+{
+ PRInt32 rc = DosDelete((char*)name);
+ if(rc == NO_ERROR) {
+ return 0;
+ } else {
+ _PR_MD_MAP_DELETE_ERROR(rc);
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_STAT(const char *fn, struct stat *info)
+{
+ PRInt32 rv;
+ char filename[CCHMAXPATH];
+
+ PR_snprintf(filename, CCHMAXPATH, "%s", fn);
+ FlipSlashes(filename, strlen(filename));
+
+ rv = _stat((char*)filename, info);
+ if (-1 == rv) {
+ /*
+ * Check for MSVC runtime library _stat() bug.
+ * (It's really a bug in FindFirstFile().)
+ * If a pathname ends in a backslash or slash,
+ * e.g., c:\temp\ or c:/temp/, _stat() will fail.
+ * Note: a pathname ending in a slash (e.g., c:/temp/)
+ * can be handled by _stat() on NT but not on Win95.
+ *
+ * We remove the backslash or slash at the end and
+ * try again.
+ *
+ * Not sure if this happens on OS/2 or not,
+ * but it doesn't hurt to be careful.
+ */
+
+ int len = strlen(fn);
+ if (len > 0 && len <= _MAX_PATH
+ && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
+ char newfn[_MAX_PATH + 1];
+
+ strcpy(newfn, fn);
+ newfn[len - 1] = '\0';
+ rv = _stat(newfn, info);
+ }
+ }
+
+ if (-1 == rv) {
+ _PR_MD_MAP_STAT_ERROR(errno);
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
+{
+ struct stat sb;
+ PRInt32 rv;
+ PRInt64 s, s2us;
+
+ if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) {
+ if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE ;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ info->size = sb.st_size;
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, sb.st_mtime);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
+{
+ PRFileInfo info32;
+ PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
+ if (0 == rv)
+ {
+ info->type = info32.type;
+ LL_UI2L(info->size,info32.size);
+ info->modifyTime = info32.modifyTime;
+ info->creationTime = info32.creationTime;
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
+{
+ /* For once, the VAC compiler/library did a nice thing.
+ * The file handle used by the C runtime is the same one
+ * returned by the OS when you call DosOpen(). This means
+ * that you can take an OS HFILE and use it with C file
+ * functions. The only caveat is that you have to call
+ * _setmode() first to initialize some junk. This is
+ * immensely useful because I did not have a clue how to
+ * implement this function otherwise. The windows folks
+ * took the source from the Microsoft C library source, but
+ * IBM wasn't kind enough to ship the source with VAC.
+ * On second thought, the needed function could probably
+ * be gotten from the OS/2 GNU library source, but the
+ * point is now moot.
+ */
+ struct stat hinfo;
+ PRInt64 s, s2us;
+
+ _setmode(fd->secret->md.osfd, O_BINARY);
+ if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) {
+ _PR_MD_MAP_FSTAT_ERROR(errno);
+ return -1;
+ }
+
+ if (hinfo.st_mode & S_IFDIR)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_FILE;
+
+ info->size = hinfo.st_size;
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, hinfo.st_mtime);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, hinfo.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ PRFileInfo info32;
+ PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
+ if (0 == rv)
+ {
+ info->type = info32.type;
+ LL_UI2L(info->size,info32.size);
+
+ info->modifyTime = info32.modifyTime;
+ info->creationTime = info32.creationTime;
+ }
+ return rv;
+}
+
+
+PRInt32
+_PR_MD_RENAME(const char *from, const char *to)
+{
+ PRInt32 rc;
+ /* Does this work with dot-relative pathnames? */
+ if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) {
+ return 0;
+ } else {
+ _PR_MD_MAP_RENAME_ERROR(rc);
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_ACCESS(const char *name, PRAccessHow how)
+{
+ PRInt32 rv;
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ rv = access(name, 02);
+ break;
+ case PR_ACCESS_READ_OK:
+ rv = access(name, 04);
+ break;
+ case PR_ACCESS_EXISTS:
+ return access(name, 00);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ if (rv < 0)
+ _PR_MD_MAP_ACCESS_ERROR(errno);
+ return rv;
+}
+
+PRInt32
+_PR_MD_MKDIR(const char *name, PRIntn mode)
+{
+ PRInt32 rc;
+ /* XXXMB - how to translate the "mode"??? */
+ if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) {
+ return 0;
+ } else {
+ _PR_MD_MAP_MKDIR_ERROR(rc);
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_RMDIR(const char *name)
+{
+ PRInt32 rc;
+ if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) {
+ return 0;
+ } else {
+ _PR_MD_MAP_RMDIR_ERROR(rc);
+ return -1;
+ }
+}
+
+PRStatus
+_PR_MD_LOCKFILE(PRInt32 f)
+{
+ PRInt32 rv;
+ FILELOCK lock, unlock;
+
+ lock.lOffset = 0;
+ lock.lRange = 0xffffffff;
+ unlock.lOffset = 0;
+ unlock.lRange = 0;
+
+ /*
+ * loop trying to DosSetFileLocks(),
+ * pause for a few miliseconds when can't get the lock
+ * and try again
+ */
+ for( rv = FALSE; rv == FALSE; /* do nothing */ )
+ {
+
+ rv = DosSetFileLocks( (HFILE) f,
+ &unlock, &lock,
+ 0, 0);
+ if ( rv != NO_ERROR )
+ {
+ DosSleep( 50 ); /* Sleep() a few milisecs and try again. */
+ }
+ } /* end for() */
+ return PR_SUCCESS;
+} /* end _PR_MD_LOCKFILE() */
+
+PRStatus
+_PR_MD_TLOCKFILE(PRInt32 f)
+{
+ return _PR_MD_LOCKFILE(f);
+} /* end _PR_MD_TLOCKFILE() */
+
+
+PRStatus
+_PR_MD_UNLOCKFILE(PRInt32 f)
+{
+ PRInt32 rv;
+ FILELOCK lock, unlock;
+
+ lock.lOffset = 0;
+ lock.lRange = 0;
+ unlock.lOffset = 0;
+ unlock.lRange = 0xffffffff;
+
+ rv = DosSetFileLocks( (HFILE) f,
+ &unlock, &lock,
+ 0, 0);
+
+ if ( rv != NO_ERROR )
+ {
+ return PR_SUCCESS;
+ }
+ else
+ {
+ return PR_FAILURE;
+ }
+} /* end _PR_MD_UNLOCKFILE() */
+
+PRStatus
+_PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
+{
+ APIRET rc = 0;
+ ULONG flags;
+ switch (fd->methods->file_type)
+ {
+ case PR_DESC_PIPE:
+ case PR_DESC_FILE:
+ rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags);
+ if (rc != NO_ERROR) {
+ PR_SetError(PR_UNKNOWN_ERROR, rc);
+ return PR_FAILURE;
+ }
+
+ if (inheritable)
+ flags &= ~OPEN_FLAGS_NOINHERIT;
+ else
+ flags |= OPEN_FLAGS_NOINHERIT;
+
+ /* Mask off flags DosSetFHState don't want. */
+ flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
+ rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags);
+ if (rc != NO_ERROR) {
+ PR_SetError(PR_UNKNOWN_ERROR, rc);
+ return PR_FAILURE;
+ }
+ break;
+
+ case PR_DESC_LAYERED:
+ /* XXX what to do here? */
+ PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/);
+ return PR_FAILURE;
+
+ case PR_DESC_SOCKET_TCP:
+ case PR_DESC_SOCKET_UDP:
+ {
+#ifdef XP_OS2_EMX
+ int rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
+ if (-1 == rv) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+#else
+ /* In VAC, socket() FDs are global. */
+#endif
+ break;
+ }
+ }
+
+ return PR_SUCCESS;
+}
+
+void
+_PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported)
+{
+ if (imported) {
+ /* for imported handles, we'll determine the inheritance state later
+ * in _PR_MD_QUERY_FD_INHERITABLE */
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ } else {
+ switch (fd->methods->file_type)
+ {
+ case PR_DESC_PIPE:
+ /* On OS/2, pipe handles created by NPSR (PR_CreatePipe) are
+ * inheritable by default */
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ break;
+ case PR_DESC_FILE:
+ /* On OS/2, file handles created by NPSR (_MD_OPEN) are
+ * made non-inheritable by default */
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ break;
+
+ case PR_DESC_LAYERED:
+ /* XXX what to do here? */
+ break;
+
+ case PR_DESC_SOCKET_TCP:
+ case PR_DESC_SOCKET_UDP:
+#ifdef XP_OS2_EMX
+ /* In EMX/GCC, sockets opened by NSPR (_PR_MD_SOCKET) are
+ * made non-inheritedable by default */
+ fd->secret->inheritable = _PR_TRI_FALSE;
+#else
+ /* In VAC, socket() FDs are global. */
+ fd->secret->inheritable = _PR_TRI_TRUE;
+#endif
+ break;
+ }
+ }
+}
+
+void
+_PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd)
+{
+ PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
+
+ switch (fd->methods->file_type)
+ {
+ case PR_DESC_PIPE:
+ case PR_DESC_FILE:
+ {
+ ULONG flags;
+ if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) {
+ if (flags & OPEN_FLAGS_NOINHERIT) {
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ } else {
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ }
+ }
+ break;
+ }
+
+ case PR_DESC_LAYERED:
+ /* XXX what to do here? */
+ break;
+
+ case PR_DESC_SOCKET_TCP:
+ case PR_DESC_SOCKET_UDP:
+ {
+#ifdef XP_OS2_EMX
+ /* In EMX/GCC, socket() FDs are inherited by default. */
+ int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ if (FD_CLOEXEC == flags) {
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ } else {
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ }
+#else
+ /* In VAC, socket() FDs are global. */
+#endif
+ break;
+ }
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2misc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2misc.c
new file mode 100644
index 00000000..9ea8df74
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2misc.c
@@ -0,0 +1,666 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * os2misc.c
+ *
+ */
+#include <string.h>
+#include "primpl.h"
+
+extern int _CRT_init(void);
+extern void _CRT_term(void);
+extern void __ctordtorInit(int flag);
+extern void __ctordtorTerm(int flag);
+
+char *
+_PR_MD_GET_ENV(const char *name)
+{
+ return getenv(name);
+}
+
+PRIntn
+_PR_MD_PUT_ENV(const char *name)
+{
+ return putenv(name);
+}
+
+
+/* see assembleEnvBlock() below */
+#define USE_DOSALLOCMEM
+
+
+/*
+ **************************************************************************
+ **************************************************************************
+ **
+ ** Date and time routines
+ **
+ **************************************************************************
+ **************************************************************************
+ */
+
+#include <sys/timeb.h>
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the
+ * implementation for OS/2.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTime)
+PR_Now(void)
+{
+ PRInt64 s, ms, ms2us, s2us;
+ struct timeb b;
+
+ ftime(&b);
+ LL_I2L(ms2us, PR_USEC_PER_MSEC);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, b.time);
+ LL_I2L(ms, b.millitm);
+ LL_MUL(ms, ms, ms2us);
+ LL_MUL(s, s, s2us);
+ LL_ADD(s, s, ms);
+ return s;
+}
+
+
+/*
+ ***********************************************************************
+ ***********************************************************************
+ *
+ * Process creation routines
+ *
+ ***********************************************************************
+ ***********************************************************************
+ */
+
+/*
+ * Assemble the command line by concatenating the argv array.
+ * On success, this function returns 0 and the resulting command
+ * line is returned in *cmdLine. On failure, it returns -1.
+ */
+static int assembleCmdLine(char *const *argv, char **cmdLine)
+{
+ char *const *arg;
+ int cmdLineSize;
+
+ /*
+ * Find out how large the command line buffer should be.
+ */
+ cmdLineSize = 1; /* final null */
+ for (arg = argv+1; *arg; arg++) {
+ cmdLineSize += strlen(*arg) + 1; /* space in between */
+ }
+ *cmdLine = PR_MALLOC(cmdLineSize);
+ if (*cmdLine == NULL) {
+ return -1;
+ }
+
+ (*cmdLine)[0] = '\0';
+
+ for (arg = argv+1; *arg; arg++) {
+ if (arg > argv +1) {
+ strcat(*cmdLine, " ");
+ }
+ strcat(*cmdLine, *arg);
+ }
+ return 0;
+}
+
+/*
+ * Assemble the environment block by concatenating the envp array
+ * (preserving the terminating null byte in each array element)
+ * and adding a null byte at the end.
+ *
+ * Returns 0 on success. The resulting environment block is returned
+ * in *envBlock. Note that if envp is NULL, a NULL pointer is returned
+ * in *envBlock. Returns -1 on failure.
+ */
+static int assembleEnvBlock(char **envp, char **envBlock)
+{
+ char *p;
+ char *q;
+ char **env;
+ char *curEnv;
+ char *cwdStart, *cwdEnd;
+ int envBlockSize;
+
+ PPIB ppib = NULL;
+ PTIB ptib = NULL;
+
+ if (envp == NULL) {
+ *envBlock = NULL;
+ return 0;
+ }
+
+ if(DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR)
+ return -1;
+
+ curEnv = ppib->pib_pchenv;
+
+ cwdStart = curEnv;
+ while (*cwdStart) {
+ if (cwdStart[0] == '=' && cwdStart[1] != '\0'
+ && cwdStart[2] == ':' && cwdStart[3] == '=') {
+ break;
+ }
+ cwdStart += strlen(cwdStart) + 1;
+ }
+ cwdEnd = cwdStart;
+ if (*cwdEnd) {
+ cwdEnd += strlen(cwdEnd) + 1;
+ while (*cwdEnd) {
+ if (cwdEnd[0] != '=' || cwdEnd[1] == '\0'
+ || cwdEnd[2] != ':' || cwdEnd[3] != '=') {
+ break;
+ }
+ cwdEnd += strlen(cwdEnd) + 1;
+ }
+ }
+ envBlockSize = cwdEnd - cwdStart;
+
+ for (env = envp; *env; env++) {
+ envBlockSize += strlen(*env) + 1;
+ }
+ envBlockSize++;
+
+ /* It seems that the Environment parameter of DosStartSession() and/or
+ * DosExecPgm() wants a memory block that is completely within the 64K
+ * memory object; otherwise we will get the environment truncated on the
+ * 64K boundary in the child process. PR_MALLOC() cannot guarantee this,
+ * so use DosAllocMem directly. */
+#ifdef USE_DOSALLOCMEM
+ DosAllocMem((PPVOID) envBlock, envBlockSize, PAG_COMMIT | PAG_READ | PAG_WRITE);
+ p = *envBlock;
+#else
+ p = *envBlock = PR_MALLOC(envBlockSize);
+#endif
+ if (p == NULL) {
+ return -1;
+ }
+
+ q = cwdStart;
+ while (q < cwdEnd) {
+ *p++ = *q++;
+ }
+
+ for (env = envp; *env; env++) {
+ q = *env;
+ while (*q) {
+ *p++ = *q++;
+ }
+ *p++ = '\0';
+ }
+ *p = '\0';
+ return 0;
+}
+
+/*
+ * For qsort. We sort (case-insensitive) the environment strings
+ * before generating the environment block.
+ */
+static int compare(const void *arg1, const void *arg2)
+{
+ return stricmp(* (char**)arg1, * (char**)arg2);
+}
+
+/*
+ * On OS/2, a process can be detached only when it is started -- you cannot
+ * make it detached afterwards. This is why _PR_CreateOS2ProcessEx() is
+ * necessary. This function is called directly from
+ * PR_CreateProcessDetached(). */
+PRProcess * _PR_CreateOS2ProcessEx(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr,
+ PRBool detached)
+{
+ PRProcess *proc = NULL;
+ char *cmdLine = NULL;
+ char **newEnvp = NULL;
+ char *envBlock = NULL;
+
+ APIRET rc;
+ ULONG ulAppType = 0;
+ PID pid = 0;
+ char *pEnvWPS = NULL;
+ char *pszComSpec;
+ char pszEXEName[CCHMAXPATH] = "";
+ char pszFormatString[CCHMAXPATH];
+ char pszObjectBuffer[CCHMAXPATH];
+ char *pszFormatResult = NULL;
+ char *pszArg0 = NULL;
+
+ proc = PR_NEW(PRProcess);
+ if (!proc) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ if (assembleCmdLine(argv, &cmdLine) == -1) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ /* the 0th argument to the program (by convention, the program name, as
+ * entered by user) */
+ pszArg0 = argv[0];
+
+ /*
+ * If attr->fdInheritBuffer is not NULL, we need to insert
+ * it into the envp array, so envp cannot be NULL.
+ */
+ if (envp == NULL && attr && attr->fdInheritBuffer) {
+ envp = environ;
+ }
+
+ if (envp != NULL) {
+ int idx;
+ int numEnv;
+ int newEnvpSize;
+
+ numEnv = 0;
+ while (envp[numEnv]) {
+ numEnv++;
+ }
+ newEnvpSize = numEnv + 1; /* terminating null pointer */
+ if (attr && attr->fdInheritBuffer) {
+ newEnvpSize++;
+ }
+ newEnvp = (char **) PR_MALLOC(newEnvpSize * sizeof(char *));
+ for (idx = 0; idx < numEnv; idx++) {
+ newEnvp[idx] = envp[idx];
+ }
+ if (attr && attr->fdInheritBuffer) {
+ newEnvp[idx++] = attr->fdInheritBuffer;
+ }
+ newEnvp[idx] = NULL;
+ qsort((void *) newEnvp, (size_t) (newEnvpSize - 1),
+ sizeof(char *), compare);
+ }
+ if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ if (attr) {
+ if (attr->stdinFd || attr->stdoutFd || attr->stderrFd)
+ PR_ASSERT(!"Stdin/stdout redirection is not implemented");
+ if (attr->currentDirectory)
+ PR_ASSERT(!"Setting current directory is not implemented");
+ }
+
+ rc = DosQueryAppType(path, &ulAppType);
+ if (rc != NO_ERROR) {
+ char *pszDot = strrchr(path, '.');
+ if (pszDot) {
+ /* If it is a CMD file, launch the users command processor */
+ if (!stricmp(pszDot, ".cmd")) {
+ rc = DosScanEnv("COMSPEC", &pszComSpec);
+ if (!rc) {
+ strcpy(pszFormatString, "/C %s %s");
+ strcpy(pszEXEName, pszComSpec);
+ pszArg0 = pszEXEName;
+ ulAppType = FAPPTYP_WINDOWCOMPAT;
+ }
+ }
+ }
+ }
+ if (ulAppType == 0) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ goto errorExit;
+ }
+
+ /* We don't want to use DosExecPgm for detached processes because
+ * they won't have stdin/stderr/stdout by default which will hang up
+ * the child process if it tries to write/read from there. Instead,
+ * we will detach console processes by starting them using the PM session
+ * (yes, it requires PM, but the whole XPCOM does so too).
+ */
+#if 0
+ if (detached) {
+ /* we don't care about parent/child process type matching,
+ * DosExecPgm() should complain if there is a mismatch. */
+
+ size_t cbArg0 = strlen(pszArg0);
+ char *pszArgs = NULL;
+
+ if (pszEXEName[0]) {
+ pszFormatResult = PR_MALLOC(cbArg0 + 1 +
+ strlen(pszFormatString) +
+ strlen(path) + strlen(cmdLine) + 1 + 1);
+ if (!pszFormatResult) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+ pszArgs = pszFormatResult + cbArg0 + 1;
+ sprintf(pszArgs, pszFormatString, path, cmdLine);
+ } else {
+ strcpy(pszEXEName, path);
+ pszFormatResult = PR_MALLOC(cbArg0 + 1 +
+ strlen(cmdLine) + 1 + 1);
+ if (!pszFormatResult) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+ pszArgs = pszFormatResult + cbArg0 + 1;
+ strcpy(pszArgs, cmdLine);
+ }
+
+ strcpy(pszFormatResult, pszArg0);
+ /* add final NULL */
+ pszArgs[strlen(pszArgs) + 1] = '\0';
+
+ RESULTCODES res = {0};
+ rc = DosExecPgm(pszObjectBuffer, CCHMAXPATH, EXEC_BACKGROUND,
+ pszFormatResult, envBlock, &res, pszEXEName);
+
+ if (rc != NO_ERROR) {
+ PR_SetError(PR_UNKNOWN_ERROR, rc);
+ goto errorExit;
+ }
+
+ /* use 0 to indicate the detached process in the internal
+ * process structure (I believe no process may have pid of 0) */
+ proc->md.pid = 0 /* res.codeTerminate */;
+ }
+ else
+#endif
+ {
+ STARTDATA startData = {0};
+
+ if ((ulAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) {
+ startData.SessionType = SSF_TYPE_PM;
+ }
+ else if (ulAppType & FAPPTYP_WINDOWCOMPAT) {
+ startData.SessionType = detached ? SSF_TYPE_PM
+ : SSF_TYPE_WINDOWABLEVIO;
+ }
+ else if (ulAppType & FAPPTYP_NOTWINDOWCOMPAT) {
+ startData.SessionType = detached ? SSF_TYPE_PM
+ : SSF_TYPE_DEFAULT;
+ }
+ else {
+ startData.SessionType = SSF_TYPE_DEFAULT;
+ }
+
+ if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL))
+ {
+ strcpy(pszEXEName, "WINOS2.COM");
+ startData.SessionType = PROG_31_STDSEAMLESSVDM;
+ strcpy(pszFormatString, "/3 %s %s");
+ }
+
+ startData.InheritOpt = SSF_INHERTOPT_PARENT;
+
+ if (pszEXEName[0]) {
+ pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine));
+ sprintf(pszFormatResult, pszFormatString, path, cmdLine);
+ startData.PgmInputs = pszFormatResult;
+ } else {
+ strcpy(pszEXEName, path);
+ startData.PgmInputs = cmdLine;
+ }
+ startData.PgmName = pszEXEName;
+
+ startData.Related = detached ? SSF_RELATED_INDEPENDENT : SSF_RELATED_CHILD;
+
+ startData.Length = sizeof(startData);
+ startData.ObjectBuffer = pszObjectBuffer;
+ startData.ObjectBuffLen = CCHMAXPATH;
+ startData.Environment = envBlock;
+
+ rc = DosStartSession(&startData, &ulAppType, &pid);
+
+ if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) {
+ PR_SetError(PR_UNKNOWN_ERROR, rc);
+ goto errorExit;
+ }
+
+ /* if Related is SSF_RELATED_INDEPENDENT, we don't get pid of the started
+ * process and use 0 to indicate the detached process in the internal
+ * process structure (I believe no process may have pid of 0).
+ */
+ proc->md.pid = detached ? 0 : pid;
+ }
+
+ if (pszFormatResult) {
+ PR_DELETE(pszFormatResult);
+ }
+ if (cmdLine) {
+ PR_DELETE(cmdLine);
+ }
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (envBlock) {
+#ifdef USE_DOSALLOCMEM
+ DosFreeMem(envBlock);
+#else
+ PR_DELETE(envBlock);
+#endif
+ }
+ return proc;
+
+errorExit:
+ if (pszFormatResult) {
+ PR_DELETE(pszFormatResult);
+ }
+ if (cmdLine) {
+ PR_DELETE(cmdLine);
+ }
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (envBlock) {
+#ifdef USE_DOSALLOCMEM
+ DosFreeMem(envBlock);
+#else
+ PR_DELETE(envBlock);
+#endif
+ }
+ if (proc) {
+ PR_DELETE(proc);
+ }
+ return NULL;
+} /* _PR_CreateOS2ProcessEx */
+
+PRProcess * _PR_CreateOS2Process(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+ return _PR_CreateOS2ProcessEx(path, argv, envp, attr, PR_FALSE);
+}
+
+PRStatus _PR_DetachOS2Process(PRProcess *process)
+{
+ /* On OS/2, a process is either created as a child or not.
+ * You can't 'detach' it later on.
+ */
+ if (process->md.pid == 0) {
+ /* this is a detached process, just free memory */
+ PR_DELETE(process);
+ return PR_SUCCESS;
+ }
+ /* For a normal child process, we can't complete the request. Note that
+ * terminating the parent process w/o calling PR_WaitProcess() on the
+ * child will terminate the child as well (since it is not detached).
+ */
+ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+/*
+ * XXX: This will currently only work on a child process.
+ */
+PRStatus _PR_WaitOS2Process(PRProcess *process,
+ PRInt32 *exitCode)
+{
+ ULONG ulRetVal;
+ RESULTCODES results;
+ PID pidEnded = 0;
+
+ ulRetVal = DosWaitChild(DCWA_PROCESS, DCWW_WAIT,
+ &results,
+ &pidEnded, process->md.pid);
+
+ if (ulRetVal != NO_ERROR) {
+ printf("\nDosWaitChild rc = %lu\n", ulRetVal);
+ PR_SetError(PR_UNKNOWN_ERROR, ulRetVal);
+ return PR_FAILURE;
+ }
+ PR_DELETE(process);
+ return PR_SUCCESS;
+}
+
+PRStatus _PR_KillOS2Process(PRProcess *process)
+{
+ ULONG ulRetVal;
+ if ((ulRetVal = DosKillProcess(DKP_PROCESS, process->md.pid)) == NO_ERROR) {
+ return PR_SUCCESS;
+ }
+ PR_SetError(PR_UNKNOWN_ERROR, ulRetVal);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen)
+{
+ PRIntn rv;
+
+ rv = gethostname(name, (PRInt32) namelen);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ }
+ _PR_MD_MAP_GETHOSTNAME_ERROR(sock_errno());
+ return PR_FAILURE;
+}
+
+void
+_PR_MD_WAKEUP_CPUS( void )
+{
+ return;
+}
+
+
+/*
+ **********************************************************************
+ *
+ * Memory-mapped files are not supported on OS/2 (or Win16).
+ *
+ **********************************************************************
+ */
+
+PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRInt32 _MD_GetMemMapAlignment(void)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+}
+
+void * _MD_MemMap(
+ PRFileMap *fmap,
+ PROffset64 offset,
+ PRUint32 len)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_CloseFileMap(PRFileMap *fmap)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+/*
+ * Automatically set apptype switch for interactive and other
+ * tests that create an invisible plevent window.
+ */
+unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long flag)
+{
+ unsigned long rc = 0; /* failure */
+
+ if( !flag)
+ {
+ /* init */
+ if( _CRT_init() == 0)
+ {
+ PPIB pPib;
+ PTIB pTib;
+
+ /* probably superfluous, but can't hurt */
+ __ctordtorInit(0);
+
+ DosGetInfoBlocks( &pTib, &pPib);
+ pPib->pib_ultype = 3; /* PM */
+
+ rc = 1;
+ }
+ }
+ else
+ {
+ __ctordtorTerm(0);
+ _CRT_term();
+ rc = 1;
+ }
+
+ return rc;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2poll.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2poll.c
new file mode 100644
index 00000000..ff87491b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2poll.c
@@ -0,0 +1,382 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This file implements _PR_MD_PR_POLL for OS/2.
+ */
+
+#ifdef XP_OS2_EMX
+ #include <sys/time.h> /* For timeval. */
+#endif
+
+#include "primpl.h"
+
+#ifndef BSD_SELECT
+/* Utility functions called when using OS/2 select */
+
+PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count )
+{
+ int i;
+ PRBool isSet = PR_FALSE;
+
+ for( i = start; i < start+count; i++ )
+ {
+ if( socks[i] == osfd )
+ isSet = PR_TRUE;
+ }
+
+ return isSet;
+}
+#endif
+
+PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+#ifdef BSD_SELECT
+ fd_set rd, wt, ex;
+#else
+ int rd, wt, ex;
+ int* socks;
+ unsigned long msecs;
+ int i, j;
+#endif
+ PRFileDesc *bottom;
+ PRPollDesc *pd, *epd;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
+
+#ifdef BSD_SELECT
+ struct timeval tv, *tvp = NULL;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+#else
+ rd = 0;
+ wt = 0;
+ ex = 0;
+ socks = (int *) PR_MALLOC( npds * 3 * sizeof(int) );
+
+ if (!socks)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+#endif
+
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read)) ||
+ (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom) &&
+ (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd)
+ maxfd = osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+#ifdef BSD_SELECT
+ FD_SET(osfd, &rd);
+#else
+ socks[rd] = osfd;
+ rd++;
+#endif
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+#ifdef BSD_SELECT
+ FD_SET(osfd, &wt);
+#else
+ socks[npds+wt] = osfd;
+ wt++;
+#endif
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+#ifdef BSD_SELECT
+ FD_SET(osfd, &rd);
+#else
+ socks[rd] = osfd;
+ rd++;
+#endif
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+#ifdef BSD_SELECT
+ FD_SET(osfd, &wt);
+#else
+ socks[npds+wt] = osfd;
+ wt++;
+#endif
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT)
+ {
+#ifdef BSD_SELECT
+ FD_SET(osfd, &ex);
+#else
+ socks[npds*2+ex] = osfd;
+ ex++;
+#endif
+ }
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ pd->out_flags = 0;
+ }
+ }
+
+ if (0 != ready)
+ {
+#ifndef BSD_SELECT
+ PR_Free(socks);
+#endif
+ return ready; /* no need to block */
+ }
+
+ remaining = timeout;
+ start = PR_IntervalNow();
+
+retry:
+#ifdef BSD_SELECT
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = remaining / ticksPerSecond;
+ tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
+ tvp = &tv;
+ }
+
+ ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp);
+#else
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT:
+ msecs = 0;
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ msecs = -1;
+ break;
+ default:
+ msecs = PR_IntervalToMilliseconds(remaining);
+ }
+
+ /* compact array */
+ for( i = rd, j = npds; j < npds+wt; i++,j++ )
+ socks[i] = socks[j];
+ for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ )
+ socks[i] = socks[j];
+
+ ready = os2_select(socks, rd, wt, ex, msecs);
+#endif
+
+ if (ready == -1 && errno == EINTR)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ goto retry;
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout)
+ ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ goto retry;
+ }
+ }
+ }
+
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ PRInt32 osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = bottom->secret->md.osfd;
+
+#ifdef BSD_SELECT
+ if (FD_ISSET(osfd, &rd))
+#else
+ if( IsSocketSet(osfd, socks, 0, rd) )
+#endif
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+
+#ifdef BSD_SELECT
+ if (FD_ISSET(osfd, &wt))
+#else
+ if( IsSocketSet(osfd, socks, rd, wt) )
+#endif
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+
+#ifdef BSD_SELECT
+ if (FD_ISSET(osfd, &ex))
+#else
+ if( IsSocketSet(osfd, socks, rd+wt, ex) )
+#endif
+ {
+ out_flags |= PR_POLL_EXCEPT;
+ }
+ }
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready < 0)
+ {
+ err = _MD_ERRNO();
+ if (err == EBADF)
+ {
+ /* Find the bad fds */
+ int optval;
+ int optlen = sizeof(optval);
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1)
+ {
+ PR_ASSERT(sock_errno() == ENOTSOCK);
+ if (sock_errno() == ENOTSOCK)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else
+ _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+#ifndef BSD_SELECT
+ PR_Free(socks);
+#endif
+ return ready;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2rng.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2rng.c
new file mode 100644
index 00000000..ae0c66cf
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2rng.c
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <time.h>
+#include "primpl.h"
+
+static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow)
+{
+ APIRET rc = NO_ERROR;
+ QWORD qword = {0,0};
+
+ rc = DosTmrQueryTime(&qword);
+ if (rc != NO_ERROR)
+ return FALSE;
+
+ *phigh = qword.ulHi;
+ *plow = qword.ulLo;
+
+ return TRUE;
+}
+
+extern PRSize _PR_MD_GetRandomNoise(void *buf, PRSize size )
+{
+ unsigned long high = 0;
+ unsigned long low = 0;
+ clock_t val = 0;
+ int n = 0;
+ int nBytes = 0;
+ time_t sTime;
+
+ if (size <= 0)
+ return 0;
+
+ clockTickTime(&high, &low);
+
+ /* get the maximally changing bits first */
+ nBytes = sizeof(low) > size ? size : sizeof(low);
+ memcpy(buf, &low, nBytes);
+ n += nBytes;
+ size -= nBytes;
+
+ if (size <= 0)
+ return n;
+
+ nBytes = sizeof(high) > size ? size : sizeof(high);
+ memcpy(((char *)buf) + n, &high, nBytes);
+ n += nBytes;
+ size -= nBytes;
+
+ if (size <= 0)
+ return n;
+
+ /* get the number of milliseconds that have elapsed since application started */
+ val = clock();
+
+ nBytes = sizeof(val) > size ? size : sizeof(val);
+ memcpy(((char *)buf) + n, &val, nBytes);
+ n += nBytes;
+ size -= nBytes;
+
+ if (size <= 0)
+ return n;
+
+ /* get the time in seconds since midnight Jan 1, 1970 */
+ time(&sTime);
+ nBytes = sizeof(sTime) > size ? size : sizeof(sTime);
+ memcpy(((char *)buf) + n, &sTime, nBytes);
+ n += nBytes;
+
+ return n;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sem.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sem.c
new file mode 100644
index 00000000..20b57a82
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sem.c
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * OS/2-specific semaphore handling code.
+ *
+ */
+
+#include "primpl.h"
+
+
+void
+_PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value)
+{
+ int rv;
+
+ /* Our Sems don't support a value > 1 */
+ PR_ASSERT(value <= 1);
+
+ rv = DosCreateEventSem(NULL, &md->sem, 0, 0);
+ PR_ASSERT(rv == NO_ERROR);
+}
+
+void
+_PR_MD_DESTROY_SEM(_MDSemaphore *md)
+{
+ int rv;
+ rv = DosCloseEventSem(md->sem);
+ PR_ASSERT(rv == NO_ERROR);
+
+}
+
+PRStatus
+_PR_MD_TIMED_WAIT_SEM(_MDSemaphore *md, PRIntervalTime ticks)
+{
+ int rv;
+ rv = DosWaitEventSem(md->sem, PR_IntervalToMilliseconds(ticks));
+
+ if (rv == NO_ERROR)
+ return PR_SUCCESS;
+ else
+ return PR_FAILURE;
+}
+
+PRStatus
+_PR_MD_WAIT_SEM(_MDSemaphore *md)
+{
+ return _PR_MD_TIMED_WAIT_SEM(md, PR_INTERVAL_NO_TIMEOUT);
+}
+
+void
+_PR_MD_POST_SEM(_MDSemaphore *md)
+{
+ int rv;
+ rv = DosPostEventSem(md->sem);
+ PR_ASSERT(rv == NO_ERROR);
+}
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sock.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sock.c
new file mode 100644
index 00000000..c0ada2a4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2sock.c
@@ -0,0 +1,733 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* OS/2 Sockets module
+ *
+ */
+
+/*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2 */
+/*There is standard BSD (which is kind of slow) and a new flavor of select() that takes */
+/*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */
+/*a millisecond count for timeout. In the interest of performance I have choosen the OS/2 */
+/*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info. */
+
+#include "primpl.h"
+
+#ifdef XP_OS2_EMX
+ #include <sys/time.h> /* For timeval. */
+#endif
+
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+#define READ_FD 1
+#define WRITE_FD 2
+
+#ifdef XP_OS2_VACPP
+#define _OS2_WRITEV writev
+#define _OS2_IOCTL ioctl
+#define _OS2_const const
+#else
+#define _OS2_WRITEV so_writev
+#define _OS2_IOCTL so_ioctl
+#define _OS2_const
+#endif
+
+void
+_PR_MD_INIT_IO()
+{
+ sock_init();
+}
+
+/* --- SOCKET IO --------------------------------------------------------- */
+
+
+PRInt32
+_PR_MD_SOCKET(int domain, int type, int flags)
+{
+ PRInt32 osfd, err;
+
+ osfd = socket(domain, type, flags);
+
+ if (osfd == -1)
+ {
+ err = sock_errno();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ }
+
+#ifdef XP_OS2_EMX
+ /* Disable inheritance of socket FDs by default to avoid side effects */
+ err = fcntl(osfd, F_SETFD, FD_CLOEXEC);
+ if (-1 == err) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ soclose(osfd);
+ return -1;
+ }
+#endif
+
+ return(osfd);
+}
+
+/*
+** _MD_CloseSocket() -- Close a socket
+**
+*/
+PRInt32
+_MD_CloseSocket(PRInt32 osfd)
+{
+ PRInt32 rv, err;
+
+ rv = soclose(osfd);
+ if (rv == -1) {
+ err = sock_errno();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
+ return rv;
+}
+
+PRInt32
+_MD_SocketAvailable(PRFileDesc *fd)
+{
+ PRInt32 result;
+
+ if (_OS2_IOCTL(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno());
+ return -1;
+ }
+ return result;
+}
+
+static PRInt32
+socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout )
+{
+ PRInt32 rv = -1;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRInt32 syserror;
+#ifdef BSD_SELECT
+ struct timeval tv;
+ fd_set rd_wr;
+#else
+ int socks[1];
+ long lTimeout;
+#endif
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+#ifdef BSD_SELECT
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
+#else
+ lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ do {
+ socks[0] = osfd;
+ if (fd_type == READ_FD)
+ rv = os2_select(socks, 1, 0, 0, lTimeout);
+ else
+ rv = os2_select(socks, 0, 1, 0, lTimeout);
+#endif
+ if (rv == -1 && (syserror = sock_errno()) != EINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+#ifdef BSD_SELECT
+ FD_ZERO(&rd_wr);
+#endif
+ do {
+ /*
+ * We block in select for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+#ifdef BSD_SELECT
+ wait_for_remaining = PR_TRUE;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv);
+#else
+ wait_for_remaining = PR_TRUE;
+ lTimeout = PR_IntervalToMilliseconds(remaining);
+ if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+ wait_for_remaining = PR_FALSE;
+ lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ }
+ socks[0] = osfd;
+ if (fd_type == READ_FD)
+ rv = os2_select(socks, 1, 0, 0, lTimeout);
+ else
+ rv = os2_select(socks, 0, 1, 0, lTimeout);
+#endif
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = sock_errno()) != EINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if select timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+ /*
+ * If select timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+#ifdef BSD_SELECT
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+#else
+ now += PR_MillisecondsToInterval(lTimeout);
+#endif
+ }
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_Accept(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1)
+ {
+ err = sock_errno();
+ if ((err == EWOULDBLOCK) || (err == ECONNABORTED))
+ {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ if (rv != -1 && addr) /* ignore the sa_len field of struct sockaddr */
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+PRInt32
+_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ PRNetAddr addrCopy = *addr;
+ ((struct sockaddr *)&addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *)&addrCopy)->sa_family = addr->raw.family;
+ addr = &addrCopy;
+#endif
+
+ /*
+ * We initiate the connection setup by making a nonblocking connect()
+ * call. If the connect() call fails, there are two cases we handle
+ * specially:
+ * 1. The connect() call was interrupted by a signal. In this case
+ * we simply retry connect().
+ * 2. The NSPR socket is nonblocking and connect() fails with
+ * EINPROGRESS. We first wait until the socket becomes writable.
+ * Then we try to find out whether the connection setup succeeded
+ * or failed.
+ */
+
+retry:
+ if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1)
+ {
+ err = sock_errno();
+
+ if (err == EINTR) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ goto retry;
+ }
+
+ if (!fd->secret->nonblocking && (err == EINPROGRESS))
+ {
+ /*
+ * socket_io_wait() may return -1 or 1.
+ */
+
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv == -1) {
+ return -1;
+ }
+
+ PR_ASSERT(rv == 1);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ err = _MD_os2_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ }
+ return 0;
+ }
+
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+
+ return rv;
+} /* _MD_connect */
+
+PRInt32
+_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv, err;
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ PRNetAddr addrCopy = *addr;
+ ((struct sockaddr *)&addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *)&addrCopy)->sa_family = addr->raw.family;
+ addr = &addrCopy;
+#endif
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+ return(rv);
+}
+
+
+PRInt32
+_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv, err;
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_DEFAULT_ERROR(err);
+ }
+ return(rv);
+}
+
+
+PRInt32
+_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = recv(osfd,buf,amount,flags)) == -1)
+ {
+ err = sock_errno();
+ if ((err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32
+_PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = send(osfd,buf,amount,flags)) == -1)
+ {
+ err = sock_errno();
+ if ((err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next send() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT))
+ {
+ if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32
+_PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ PRNetAddr addrCopy = *addr;
+ ((struct sockaddr *)&addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *)&addrCopy)->sa_family = addr->raw.family;
+ addr = &addrCopy;
+#endif
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1)
+ {
+ err = sock_errno();
+ if ((err == EWOULDBLOCK))
+ {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32
+_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while( (*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, (int *)addrlen)) == -1))
+ {
+ err = sock_errno();
+ if ((err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ if (rv != -1 && addr) /* ignore the sa_len field of struct sockaddr */
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+PRInt32
+_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ /*
+ * Calculate the total number of bytes to be sent; needed for
+ * optimization later.
+ * We could avoid this if this number was passed in; but it is
+ * probably not a big deal because iov_size is usually small (less than
+ * 3)
+ */
+ if (!fd->secret->nonblocking) {
+ for (index=0; index<iov_size; index++) {
+ amount += iov[index].iov_len;
+ }
+ }
+
+ while ((rv = _OS2_WRITEV(osfd, (_OS2_const struct iovec*)iov, iov_size)) == -1) {
+ err = sock_errno();
+ if ((err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next writev() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32
+_PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
+{
+ PRInt32 rv;
+
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0)
+ _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno());
+ return rv;
+}
+
+#ifndef XP_OS2_VACPP
+PRInt32
+_PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd)
+{
+ PRInt32 rv, err;
+
+ rv = socketpair(af, type, flags, osfd);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKETPAIR_ERROR(err);
+ }
+ return rv;
+}
+#endif
+
+PRStatus
+_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockname(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (int *)addrlen);
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ if (rv == 0 && addr) /* ignore the sa_len field of struct sockaddr */
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETSOCKNAME_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getpeername(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (int *)addrlen);
+#ifdef _PR_HAVE_SOCKADDR_LEN /* bird - !TCPV40HDRS */
+ if (rv == 0 && addr) /* ignore the sa_len field of struct sockaddr */
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETPEERNAME_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ char* optval, PRInt32* optlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname,
+ const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv, err;
+
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = sock_errno();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+void
+_MD_MakeNonblock(PRFileDesc *fd)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 err;
+ PRUint32 one = 1;
+
+ if (osfd <= 2) {
+ /* Don't mess around with stdin, stdout or stderr */
+ return;
+ }
+
+ err = _OS2_IOCTL( osfd, FIONBIO, (char *) &one, sizeof(one));
+ if ( err != 0 )
+ {
+ err = sock_errno();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2thred.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2thred.c
new file mode 100644
index 00000000..69f06aa0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2thred.c
@@ -0,0 +1,407 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <process.h> /* for _beginthread() */
+
+#ifdef XP_OS2_VACPP
+#include <time.h> /* for _tzset() */
+#endif
+
+#ifdef XP_OS2_EMX
+#include <signal.h>
+#endif
+
+#include <float.h>
+
+/* --- globals ------------------------------------------------ */
+_NSPR_TLS* pThreadLocalStorage = 0;
+_PRInterruptTable _pr_interruptTable[] = { { 0 } };
+APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD);
+
+void
+_PR_MD_ENSURE_TLS(void)
+{
+ if(!pThreadLocalStorage)
+ {
+ /* Allocate thread local storage (TLS). Note, that only 32 bytes can
+ * be allocated at a time.
+ */
+ int rc = DosAllocThreadLocalMemory(sizeof(_NSPR_TLS) / 4, (PULONG*)&pThreadLocalStorage);
+ PR_ASSERT(rc == NO_ERROR);
+ memset(pThreadLocalStorage, 0, sizeof(_NSPR_TLS));
+ }
+}
+
+void
+_PR_MD_EARLY_INIT()
+{
+ HMODULE hmod;
+
+ if (DosLoadModule(NULL, 0, "DOSCALL1", &hmod) == 0)
+ DosQueryProcAddr(hmod, 877, "DOSQUERYTHREADCONTEXT",
+ (PFN *)&QueryThreadContext);
+
+#ifdef XP_OS2_VACPP
+ _tzset();
+#endif
+}
+
+static void
+_pr_SetThreadMDHandle(PRThread *thread)
+{
+ PTIB ptib;
+ PPIB ppib;
+ PRUword rc;
+
+ rc = DosGetInfoBlocks(&ptib, &ppib);
+
+ thread->md.handle = ptib->tib_ptib2->tib2_ultid;
+}
+
+/* On OS/2, some system function calls seem to change the FPU control word,
+ * such that we crash with a floating underflow exception. The FIX_FPU() call
+ * in jsnum.c does not always work, as sometimes FIX_FPU() is called BEFORE the
+ * OS/2 system call that horks the FPU control word. So, we set an exception
+ * handler that covers any floating point exceptions and resets the FPU CW to
+ * the required value.
+ */
+static ULONG
+_System OS2_FloatExcpHandler(PEXCEPTIONREPORTRECORD p1,
+ PEXCEPTIONREGISTRATIONRECORD p2,
+ PCONTEXTRECORD p3,
+ PVOID pv)
+{
+#ifdef DEBUG_pedemonte
+ printf("Entering exception handler; ExceptionNum = %x\n", p1->ExceptionNum);
+ switch(p1->ExceptionNum) {
+ case XCPT_FLOAT_DENORMAL_OPERAND:
+ printf("got XCPT_FLOAT_DENORMAL_OPERAND\n");
+ break;
+ case XCPT_FLOAT_DIVIDE_BY_ZERO:
+ printf("got XCPT_FLOAT_DIVIDE_BY_ZERO\n");
+ break;
+ case XCPT_FLOAT_INEXACT_RESULT:
+ printf("got XCPT_FLOAT_INEXACT_RESULT\n");
+ break;
+ case XCPT_FLOAT_INVALID_OPERATION:
+ printf("got XCPT_FLOAT_INVALID_OPERATION\n");
+ break;
+ case XCPT_FLOAT_OVERFLOW:
+ printf("got XCPT_FLOAT_OVERFLOW\n");
+ break;
+ case XCPT_FLOAT_STACK_CHECK:
+ printf("got XCPT_FLOAT_STACK_CHECK\n");
+ break;
+ case XCPT_FLOAT_UNDERFLOW:
+ printf("got XCPT_FLOAT_UNDERFLOW\n");
+ break;
+ }
+#endif
+
+ switch(p1->ExceptionNum) {
+ case XCPT_FLOAT_DENORMAL_OPERAND:
+ case XCPT_FLOAT_DIVIDE_BY_ZERO:
+ case XCPT_FLOAT_INEXACT_RESULT:
+ case XCPT_FLOAT_INVALID_OPERATION:
+ case XCPT_FLOAT_OVERFLOW:
+ case XCPT_FLOAT_STACK_CHECK:
+ case XCPT_FLOAT_UNDERFLOW:
+ {
+ unsigned cw = p3->ctx_env[0];
+ if ((cw & MCW_EM) != MCW_EM) {
+ /* Mask out all floating point exceptions */
+ p3->ctx_env[0] |= MCW_EM;
+ /* Following two lines set precision to 53 bit mantissa. See jsnum.c */
+ p3->ctx_env[0] &= ~MCW_PC;
+ p3->ctx_env[0] |= PC_53;
+ return XCPT_CONTINUE_EXECUTION;
+ }
+ }
+ }
+ return XCPT_CONTINUE_SEARCH;
+}
+
+PR_IMPLEMENT(void)
+PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg)
+{
+ /* setup the exception handler for the thread */
+ APIRET rv;
+ excpreg->ExceptionHandler = OS2_FloatExcpHandler;
+ excpreg->prev_structure = NULL;
+ rv = DosSetExceptionHandler(excpreg);
+ PR_ASSERT(rv == NO_ERROR);
+}
+
+PR_IMPLEMENT(void)
+PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg)
+{
+ /* unset exception handler */
+ APIRET rv = DosUnsetExceptionHandler(excpreg);
+ PR_ASSERT(rv == NO_ERROR);
+}
+
+PRStatus
+_PR_MD_INIT_THREAD(PRThread *thread)
+{
+ APIRET rv;
+
+ if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
+ _pr_SetThreadMDHandle(thread);
+ }
+
+ /* Create the blocking IO semaphore */
+ rv = DosCreateEventSem(NULL, &(thread->md.blocked_sema), 0, 0);
+ return (rv == NO_ERROR) ? PR_SUCCESS : PR_FAILURE;
+}
+
+typedef struct param_store
+{
+ void (*start)(void *);
+ PRThread* thread;
+} PARAMSTORE;
+
+/* This is a small intermediate function that sets/unsets the exception
+ handler before calling the initial thread function */
+static void
+ExcpStartFunc(void* arg)
+{
+ EXCEPTIONREGISTRATIONRECORD excpreg;
+ PARAMSTORE params, *pParams = arg;
+
+ PR_OS2_SetFloatExcpHandler(&excpreg);
+
+ params = *pParams;
+ PR_Free(pParams);
+ params.start(params.thread);
+
+ PR_OS2_UnsetFloatExcpHandler(&excpreg);
+}
+
+PRStatus
+_PR_MD_CREATE_THREAD(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PARAMSTORE* params = PR_Malloc(sizeof(PARAMSTORE));
+ params->start = start;
+ params->thread = thread;
+#ifdef XP_OS2_VACPP /* No exception handler for VACPP */
+ thread->md.handle = thread->id = (TID) _beginthread(
+ (void(* _Optlink)(void*))start,
+ NULL,
+ thread->stack->stackSize,
+ thread);
+#else
+ thread->md.handle = thread->id = (TID) _beginthread(ExcpStartFunc,
+ NULL,
+ thread->stack->stackSize,
+ params);
+#endif
+ if(thread->md.handle == -1) {
+ return PR_FAILURE;
+ }
+
+ /*
+ * On OS/2, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL
+ */
+
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
+
+ return PR_SUCCESS;
+}
+
+void
+_PR_MD_YIELD(void)
+{
+ /* Isn't there some problem with DosSleep(0) on OS/2? */
+ DosSleep(0);
+}
+
+void
+_PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
+{
+ int nativePri;
+ BOOL rv;
+
+ if (newPri < PR_PRIORITY_FIRST) {
+ newPri = PR_PRIORITY_FIRST;
+ } else if (newPri > PR_PRIORITY_LAST) {
+ newPri = PR_PRIORITY_LAST;
+ }
+ switch (newPri) {
+ case PR_PRIORITY_LOW:
+ nativePri = PRTYC_IDLETIME;
+ break;
+ case PR_PRIORITY_NORMAL:
+ nativePri = PRTYC_REGULAR;
+ break;
+ case PR_PRIORITY_HIGH:
+ nativePri = PRTYC_FOREGROUNDSERVER;
+ break;
+ case PR_PRIORITY_URGENT:
+ nativePri = PRTYC_TIMECRITICAL;
+ }
+ rv = DosSetPriority(PRTYS_THREAD, nativePri, 0, thread->handle);
+ PR_ASSERT(rv == NO_ERROR);
+ if (rv != NO_ERROR) {
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("PR_SetThreadPriority: can't set thread priority\n"));
+ }
+ return;
+}
+
+void
+_PR_MD_CLEAN_THREAD(PRThread *thread)
+{
+ APIRET rv;
+
+ if (thread->md.blocked_sema) {
+ rv = DosCloseEventSem(thread->md.blocked_sema);
+ PR_ASSERT(rv == NO_ERROR);
+ thread->md.blocked_sema = 0;
+ }
+
+ if (thread->md.handle) {
+ thread->md.handle = 0;
+ }
+}
+
+void
+_PR_MD_EXIT_THREAD(PRThread *thread)
+{
+ _PR_MD_CLEAN_THREAD(thread);
+ _PR_MD_SET_CURRENT_THREAD(NULL);
+}
+
+
+void
+_PR_MD_EXIT(PRIntn status)
+{
+ _exit(status);
+}
+
+#ifdef HAVE_THREAD_AFFINITY
+PR_EXTERN(PRInt32)
+_PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
+{
+ /* Can we do this on OS/2? Only on SMP versions? */
+ PR_ASSERT(!"Not implemented");
+ return 0;
+
+ /* This is what windows does:
+ int rv;
+
+ rv = SetThreadAffinityMask(thread->md.handle, mask);
+
+ return rv?0:-1;
+ */
+}
+
+PR_EXTERN(PRInt32)
+_PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
+{
+ /* Can we do this on OS/2? Only on SMP versions? */
+ PR_ASSERT(!"Not implemented");
+ return 0;
+
+ /* This is what windows does:
+ PRInt32 rv, system_mask;
+
+ rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);
+
+ return rv?0:-1;
+ */
+}
+#endif /* HAVE_THREAD_AFFINITY */
+
+void
+_PR_MD_SUSPEND_CPU(_PRCPU *cpu)
+{
+ _PR_MD_SUSPEND_THREAD(cpu->thread);
+}
+
+void
+_PR_MD_RESUME_CPU(_PRCPU *cpu)
+{
+ _PR_MD_RESUME_THREAD(cpu->thread);
+}
+
+void
+_PR_MD_SUSPEND_THREAD(PRThread *thread)
+{
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ APIRET rc;
+
+ /* XXXMB - DosSuspendThread() is not a blocking call; how do we
+ * know when the thread is *REALLY* suspended?
+ */
+ rc = DosSuspendThread(thread->md.handle);
+ PR_ASSERT(rc == NO_ERROR);
+ }
+}
+
+void
+_PR_MD_RESUME_THREAD(PRThread *thread)
+{
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ DosResumeThread(thread->md.handle);
+ }
+}
+
+
+PRThread*
+_MD_CURRENT_THREAD(void)
+{
+ PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+
+ PR_ASSERT(thread != NULL);
+ return thread;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vaclegacy.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vaclegacy.s
new file mode 100644
index 00000000..05310f91
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vaclegacy.s
@@ -0,0 +1,73 @@
+/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/
+/ 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 Portable Runtime (NSPR).
+/
+/ The Initial Developer of the Original Code is innotek.
+/ Portions created by the Initial Developer are Copyright (C) 2003
+/ the Initial Developer. All Rights Reserved.
+/
+/ Contributor(s):
+/ innotek GmbH / Knut St. Osmundsen
+/
+/ 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.
+/
+
+ .text
+ .align 4
+ .globl PR_NewMonitor
+PR_NewMonitor:
+ jmp _PR_NewMonitor
+
+ .align 4
+ .globl PR_EnterMonitor
+PR_EnterMonitor:
+ mov %eax, 4(%esp)
+ jmp _PR_EnterMonitor
+
+ .align 4
+ .globl PR_ExitMonitor
+PR_ExitMonitor:
+ mov %eax, 4(%esp)
+ jmp _PR_ExitMonitor
+
+
+
+ .align 4
+ .globl PR_AttachThread
+PR_AttachThread:
+ mov %eax, 4(%esp)
+ mov %edx, 8(%esp)
+ mov %ecx, 12(%esp)
+ jmp _PR_AttachThread
+
+ .align 4
+ .globl PR_DetachThread
+PR_DetachThread:
+ jmp _PR_DetachThread
+
+ .align 4
+ .globl PR_GetCurrentThread
+PR_GetCurrentThread:
+ jmp _PR_GetCurrentThread
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vacpp.asm b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vacpp.asm
new file mode 100644
index 00000000..0f07f2f6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/os2/os2vacpp.asm
@@ -0,0 +1,293 @@
+COMMENT | -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
+ ***** BEGIN LICENSE BLOCK *****
+ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+ The contents of this file are subject to the Mozilla Public License Version
+ 1.1 (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the
+ License.
+
+ The Original Code is mozilla.org Code.
+
+ The Initial Developer of the Original Code is
+ Netscape Communications Corporation.
+ Portions created by the Initial Developer are Copyright (C) 2001
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+
+ Alternatively, the contents of this file may be used under the terms of
+ either the GNU General Public License Version 2 or later (the "GPL"), or
+ the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ in which case the provisions of the GPL or the LGPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of either the GPL or the LGPL, and not to allow others to
+ use your version of this file under the terms of the MPL, indicate your
+ decision by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL or the LGPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the MPL, the GPL or the LGPL.
+
+ ***** END LICENSE BLOCK *****
+ 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 Portable Runtime (NSPR).
+
+ The Initial Developer of the Original Code is IBM Corporation.
+ Portions created by IBM are Copyright (C) 2001 IBM 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.
+
+ Windows uses inline assembly for their atomic functions, so we have
+ created an assembly file for VACPP on OS/2.
+
+ This assembly file also contains an implementation of RAM semaphores.
+
+ Notes:
+ The ulTIDPID element of the RAMSEM structure is overloaded in the 386
+ implementation to hold the TID:PID in the lower 31 bits and the lock
+ bit in the high bit
+ |
+ page ,132
+
+ .486P
+ ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:FLAT
+
+ EXTRN Dos32PostEventSem:PROC
+ EXTRN Dos32WaitEventSem:PROC
+ EXTRN Dos32ResetEventSem:PROC
+
+ramsem STRUC
+ ramsem_ulTIDPID DD ?
+ ramsem_hevSem DD ?
+ ramsem_cLocks DD ?
+ ramsem_cWaiting DW ?
+ ramsem_cPosts DW ?
+ramsem ENDS
+
+ERROR_SEM_TIMEOUT equ 121
+ERROR_NOT_OWNER equ 288
+SEM_RELEASE_UNOWNED equ 1
+SEM_RELEASE_ALL equ 2
+TS_LOCKBIT equ 31
+
+
+DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
+
+ EXTRN plisCurrent:DWORD
+
+DATA ENDS
+
+CODE32 SEGMENT USE32 PUBLIC 'CODE'
+
+ PUBLIC SemRequest486
+ PUBLIC SemReleasex86
+
+ PUBLIC _PR_MD_ATOMIC_SET
+ PUBLIC _PR_MD_ATOMIC_ADD
+ PUBLIC _PR_MD_ATOMIC_INCREMENT
+ PUBLIC _PR_MD_ATOMIC_DECREMENT
+
+;;;---------------------------------------------------------------------------
+;;; APIRET _Optlink SemRequest(PRAMSEM pramsem, ULONG ulTimeout);
+;;;
+;;; Registers:
+;;; EAX - packed TID:PID word
+;;; ECX - address of RAMSEM structure
+;;; EDX - length of timeout in milli-seconds
+;;;---------------------------------------------------------------------------
+
+ ALIGN 10H
+SemRequest486 PROC
+ push ebx ; Save ebx (volatile)
+ mov ecx, eax ; PRAMSEM must be in ecx,
+ ; not eax, for cmpxchg
+
+ mov ebx, dword ptr [plisCurrent]
+ mov eax, dword ptr [ebx+4] ; Place thread id in high
+ ; word, process id in low
+ mov ax, word ptr [ebx] ; word
+ mov ebx,eax
+
+req486_test:
+ xor eax,eax
+ cmp (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx ; If we own the sem, just
+ jz short req486_inc_exit ; increment the use count
+
+ lock inc (ramsem PTR [ecx]).ramsem_cWaiting ; inc waiting flag
+
+; lock ; Uncomment for SMP
+ DB 0F0h
+; cmpxchg (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx
+; (byte 3 is the offset of ulProcessThread into the RAMSEM structure)
+ DB 00Fh
+ DB 0B1h
+ DB 019h
+ jnz short req486_sleep
+
+req486_inc_exit:
+ lock inc (ramsem PTR [ecx]).ramsem_cLocks
+
+req486_exit:
+ pop ebx ; Restore ebx
+ ret
+
+req486_sleep:
+ push ecx ; Save ecx (volatile)
+ push edx ; Save edx (volatile)
+ push edx ; timeout
+ push (ramsem PTR [ecx]).ramsem_hevSem
+ call Dos32WaitEventSem
+ add esp, 8
+ pop edx ; restore edx
+ pop ecx ; restore ecx
+ or eax, eax
+ jne req486_exit ; Exit, if error
+
+ push ecx ; Save ecx (volatile)
+ push edx ; Save edx (volatile)
+ sub esp, 4 ; Use stack space for
+ push esp ; dummy pulPostCt
+ push (ramsem PTR [ecx]).ramsem_hevSem
+ call Dos32ResetEventSem
+ add esp, 12
+ pop edx ; restore edx
+ pop ecx ; restore ecx
+ jmp req486_test ; Retry the semaphore
+
+SemRequest486 ENDP
+
+;;;---------------------------------------------------------------------
+;;; APIRET _Optlink SemReleasex86(PRAMSEM pramsem, ULONG flFlags);
+;;;
+;;; Registers:
+;;; EAX - address of RAMSEM structure
+;;; ECX - temporary variable
+;;; EDX - flags
+;;;---------------------------------------------------------------------
+
+ ALIGN 10H
+SemReleasex86 PROC
+ test edx, SEM_RELEASE_UNOWNED ; If set, don't bother
+ jnz short rel_ownerok ; getting/checking PID/TID
+
+ push ebx ; Save ebx (volatile)
+ mov ebx, dword ptr [plisCurrent]
+ mov ecx, dword ptr [ebx+4] ; Place thread id in high
+ ; word, process id in low
+ mov cx, word ptr [ebx] ; word
+ pop ebx ; Restore ebx
+
+ sub ecx, (ramsem PTR [eax]).ramsem_ulTIDPID ; This thread the owner?
+ shl ecx,1 ; Don't compare top bit
+ jnz short rel_notowner
+
+rel_ownerok:
+ test edx, SEM_RELEASE_ALL
+ jnz short rel_clear
+
+ lock dec (ramsem PTR [eax]).ramsem_cLocks
+ jnz short rel_exit
+
+rel_disown:
+ mov (ramsem PTR [eax]).ramsem_ulTIDPID, 0
+
+ lock inc (ramsem PTR [eax]).ramsem_cPosts
+ mov cx, (ramsem PTR [eax]).ramsem_cWaiting
+ cmp (ramsem PTR [eax]).ramsem_cPosts, cx
+ jne short rel_post
+
+rel_exit:
+ xor eax, eax
+ ret
+
+rel_clear:
+ lock mov (ramsem PTR [eax]).ramsem_cLocks,0
+ jmp rel_disown
+
+rel_notowner:
+ mov eax, ERROR_NOT_OWNER
+ ret
+
+rel_post:
+ mov (ramsem PTR [eax]).ramsem_cPosts, cx
+ push (ramsem PTR [eax]).ramsem_hevSem
+ call Dos32PostEventSem
+ add esp,4
+ xor eax,eax
+ ret
+SemReleasex86 ENDP
+
+;;;---------------------------------------------------------------------
+;;; PRInt32 _Optlink _PR_MD_ATOMIC_SET(PRInt32* val, PRInt32 newval)
+;;;---------------------------------------------------------------------
+ ALIGN 10H
+_PR_MD_ATOMIC_SET proc
+ lock xchg dword ptr [eax],edx
+ mov eax, edx;
+ ret
+_PR_MD_ATOMIC_SET endp
+
+;;;---------------------------------------------------------------------
+;;; PRInt32 _Optlink _PR_MD_ATOMIC_ADD(PRInt32* ptr, PRInt32 val)
+;;;---------------------------------------------------------------------
+ ALIGN 10H
+_PR_MD_ATOMIC_ADD proc
+ mov ecx, edx
+ lock xadd dword ptr [eax], edx
+ mov eax, edx
+ add eax, ecx
+ ret
+_PR_MD_ATOMIC_ADD endp
+
+;;;---------------------------------------------------------------------
+;;; PRInt32 _Optlink _PR_MD_ATOMIC_INCREMENT(PRInt32* val)
+;;;---------------------------------------------------------------------
+ ALIGN 10H
+_PR_MD_ATOMIC_INCREMENT proc
+ mov edx, 1
+ lock xadd dword ptr [eax], edx
+ mov eax, edx
+ inc eax
+ ret
+_PR_MD_ATOMIC_INCREMENT endp
+
+;;;---------------------------------------------------------------------
+;;; PRInt32 _Optlink _PR_MD_ATOMIC_DECREMENT(PRInt32* val)
+;;;---------------------------------------------------------------------
+ ALIGN 10H
+_PR_MD_ATOMIC_DECREMENT proc
+ mov edx, 0ffffffffh
+ lock xadd dword ptr [eax], edx
+ mov eax, edx
+ dec eax
+ ret
+_PR_MD_ATOMIC_DECREMENT endp
+
+CODE32 ENDS
+END
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/prosdep.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/prosdep.c
new file mode 100644
index 00000000..9ae80965
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/prosdep.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prbit.h"
+#include "prsystem.h"
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+#ifdef SUNOS4
+#include "md/sunos4.h"
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#ifdef XP_BEOS
+#include <OS.h>
+#endif
+
+PRInt32 _pr_pageShift;
+PRInt32 _pr_pageSize;
+
+/*
+** Get system page size
+*/
+static void GetPageSize(void)
+{
+ PRInt32 pageSize;
+
+ /* Get page size */
+#ifdef XP_UNIX
+#if defined SUNOS4 || defined LINUX || defined BSDI || defined AIX \
+ || defined FREEBSD || defined NETBSD || defined OPENBSD \
+ || defined DARWIN || defined NEXTSTEP
+ _pr_pageSize = getpagesize();
+#elif defined(HPUX)
+ /* I have no idea. Don't get me started. --Rob */
+ _pr_pageSize = sysconf(_SC_PAGE_SIZE);
+#else
+ _pr_pageSize = sysconf(_SC_PAGESIZE);
+#endif
+#endif /* XP_UNIX */
+
+#ifdef XP_MAC
+ _pr_pageSize = 4096;
+#endif /* XP_MAC */
+
+#ifdef XP_BEOS
+ _pr_pageSize = B_PAGE_SIZE;
+#endif
+
+#ifdef XP_PC
+#ifdef _WIN32
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ _pr_pageSize = info.dwPageSize;
+#else
+ _pr_pageSize = 4096;
+#endif
+#endif /* XP_PC */
+
+ pageSize = _pr_pageSize;
+ PR_CEILING_LOG2(_pr_pageShift, pageSize);
+}
+
+PR_IMPLEMENT(PRInt32) PR_GetPageShift(void)
+{
+ if (!_pr_pageSize) {
+ GetPageSize();
+ }
+ return _pr_pageShift;
+}
+
+PR_IMPLEMENT(PRInt32) PR_GetPageSize(void)
+{
+ if (!_pr_pageSize) {
+ GetPageSize();
+ }
+ return _pr_pageSize;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/Makefile.in
new file mode 100644
index 00000000..1c4c071c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/Makefile.in
@@ -0,0 +1,135 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+CSRCS = \
+ unix.c \
+ unix_errors.c \
+ uxproces.c \
+ uxrng.c \
+ uxshm.c \
+ uxwrap.c \
+ $(NULL)
+
+ifneq ($(USE_PTHREADS),1)
+CSRCS += uxpoll.c
+endif
+
+ifeq ($(PTHREADS_USER),1)
+CSRCS += pthreads_user.c
+endif
+
+CSRCS += $(PR_MD_CSRCS)
+ASFILES += $(PR_MD_ASFILES)
+
+TARGETS = $(OBJS)
+
+ifeq ($(OS_ARCH),SunOS)
+ ifneq ($(OS_RELEASE),4.1.3_U1)
+ ifeq ($(OS_TEST),sun4u)
+ ifdef USE_64
+ ULTRASPARC_ASFILES = os_SunOS_sparcv9.s
+ ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX)))
+ else
+ LIBRARY_NAME = $(ULTRASPARC_LIBRARY)
+ LIBRARY_VERSION = $(MOD_MAJOR_VERSION)
+ ULTRASPARC_ASFILES = os_SunOS_ultrasparc.s
+ ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX)))
+ TARGETS += $(ULTRASPARC_ASOBJS) $(SHARED_LIBRARY)
+ RELEASE_LIBS = $(SHARED_LIBRARY)
+ RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR)/cpu/sparcv8plus
+ lib_subdir = cpu/sparcv8plus
+ endif
+ endif
+ endif
+endif
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
+ifeq ($(OS_ARCH),SunOS)
+ifneq ($(OS_RELEASE),4.1.3_U1)
+ifeq ($(OS_TEST),sun4u)
+
+ifdef USE_64
+$(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES)
+ /usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v9 $<
+else
+$(SHARED_LIBRARY): $(ULTRASPARC_ASOBJS)
+ $(LD) -G -z text -z endfiltee -o $@ $(ULTRASPARC_ASOBJS)
+ $(INSTALL) -m 444 $@ $(dist_libdir)/cpu/sparcv8plus
+ $(INSTALL) -m 444 $@ $(dist_bindir)/cpu/sparcv8plus
+#
+# The -f $(ORIGIN)/... linker flag uses the real file, after symbolic links
+# are resolved, as the origin. If NSDISTMODE is not "copy", libnspr4.so
+# will be installed as a symbolic link in $(dist_libdir), pointing to the
+# real libnspr4.so file in pr/src. Therefore we need to install an
+# additional copy of libnspr_flt4.so in pr/src/cpu/sparcv8plus.
+#
+ifneq ($(NSDISTMODE),copy)
+ $(INSTALL) -m 444 $@ ../../cpu/sparcv8plus
+endif
+
+ifneq ($(NSDISTMODE),copy)
+clobber realclean clobber_all distclean::
+ rm -rf ../../cpu
+endif
+
+$(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES)
+ /usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v8plus $<
+
+clean::
+ rm -rf $(ULTRASPARC_ASOBJS)
+endif
+
+endif
+endif
+endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aix.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aix.c
new file mode 100644
index 00000000..ae945b1b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aix.c
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#ifdef AIX_HAVE_ATOMIC_OP_H
+#include <sys/atomic_op.h>
+
+PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
+{
+ PRIntn oldval;
+ boolean_t stored;
+ oldval = fetch_and_add((atomic_p)val, 0);
+ do
+ {
+ stored = compare_and_swap((atomic_p)val, &oldval, newval);
+ } while (!stored);
+ return oldval;
+} /* _AIX_AtomicSet */
+#endif /* AIX_HAVE_ATOMIC_OP_H */
+
+#if defined(AIX_TIMERS)
+
+#include <sys/time.h>
+
+static PRUint32 _aix_baseline_epoch;
+
+static void _MD_AixIntervalInit(void)
+{
+ timebasestruct_t real_time;
+ read_real_time(&real_time, TIMEBASE_SZ);
+ (void)time_base_to_time(&real_time, TIMEBASE_SZ);
+ _aix_baseline_epoch = real_time.tb_high;
+} /* _MD_AixIntervalInit */
+
+PRIntervalTime _MD_AixGetInterval(void)
+{
+ PRIntn rv;
+ PRUint64 temp;
+ timebasestruct_t real_time;
+ read_real_time(&real_time, TIMEBASE_SZ);
+ (void)time_base_to_time(&real_time, TIMEBASE_SZ);
+ /* tb_high is in seconds, tb_low in 10(-9)seconds */
+ temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch);
+ temp += (PRUint64)real_time.tb_low; /* everything's 10(-9) seconds */
+ temp >>= 16; /* now it's something way different */
+ return (PRIntervalTime)temp;
+} /* _MD_AixGetInterval */
+
+PRIntervalTime _MD_AixIntervalPerSec(void)
+{
+ return 1000000000ULL >> 16; /* that's 15258, I think */
+} /* _MD_AixIntervalPerSec */
+
+#endif /* defined(AIX_TIMERS) */
+
+#if !defined(PTHREADS_USER)
+
+#if defined(_PR_PTHREADS)
+
+/*
+ * AIX 4.3 has sched_yield(). AIX 4.2 has pthread_yield().
+ * So we look up the appropriate function pointer at run time.
+ */
+
+#include <dlfcn.h>
+
+int (*_PT_aix_yield_fcn)() = NULL;
+int _pr_aix_send_file_use_disabled = 0;
+
+void _MD_EarlyInit(void)
+{
+ void *main_app_handle;
+ char *evp;
+
+ main_app_handle = dlopen(NULL, RTLD_NOW);
+ PR_ASSERT(NULL != main_app_handle);
+
+ _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield");
+ if (!_PT_aix_yield_fcn) {
+ _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield");
+ PR_ASSERT(NULL != _PT_aix_yield_fcn);
+ }
+ dlclose(main_app_handle);
+
+ if (evp = getenv("NSPR_AIX_SEND_FILE_USE_DISABLED")) {
+ if (1 == atoi(evp))
+ _pr_aix_send_file_use_disabled = 1;
+ }
+
+#if defined(AIX_TIMERS)
+ _MD_AixIntervalInit();
+#endif
+}
+
+#else /* _PR_PTHREADS */
+
+void _MD_EarlyInit(void)
+{
+#if defined(AIX_TIMERS)
+ _MD_AixIntervalInit();
+#endif
+}
+
+#endif /* _PR_PTHREADS */
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+PR_IMPLEMENT(void)
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for AIX */
+PR_IMPLEMENT(void)
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for AIX.");
+}
+#endif /* _PR_PTHREADS */
+#endif /* PTHREADS_USER */
+
+/*
+ * NSPR 2.0 overrides the system select() and poll() functions.
+ * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
+ * at the original system select() and poll() functions.
+ */
+
+#if !defined(AIX_RENAME_SELECT)
+
+#include <sys/select.h>
+#include <sys/poll.h>
+#include <dlfcn.h>
+
+static int (*aix_select_fcn)() = NULL;
+static int (*aix_poll_fcn)() = NULL;
+
+int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
+{
+ int rv;
+
+ if (!aix_select_fcn) {
+ void *aix_handle;
+
+ aix_handle = dlopen("/unix", RTLD_NOW);
+ if (!aix_handle) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
+ dlclose(aix_handle);
+ if (!aix_select_fcn) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ }
+ rv = (*aix_select_fcn)(width, r, w, e, t);
+ return rv;
+}
+
+int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
+{
+ int rv;
+
+ if (!aix_poll_fcn) {
+ void *aix_handle;
+
+ aix_handle = dlopen("/unix", RTLD_NOW);
+ if (!aix_handle) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
+ dlclose(aix_handle);
+ if (!aix_poll_fcn) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ }
+ rv = (*aix_poll_fcn)(listptr, nfds, timeout);
+ return rv;
+}
+
+#else
+
+/*
+ * In AIX versions prior to 4.2, we use the two-step rename/link trick.
+ * The binary must contain at least one "poll" symbol for linker's rename
+ * to work. So we must have this dummy function that references poll().
+ */
+#include <sys/poll.h>
+void _pr_aix_dummy()
+{
+ poll(0,0,0);
+}
+
+#endif /* !defined(AIX_RENAME_SELECT) */
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include "pratom.h"
+
+#define _PR_AIX_ATOMIC_LOCK -1
+
+PR_IMPLEMENT(void)
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+PRStackElem *addr;
+boolean_t locked = TRUE;
+
+ /* Is it safe to cast a pointer to an int? */
+ PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
+ do {
+ while ((addr = stack->prstk_head.prstk_elem_next) ==
+ (PRStackElem *)_PR_AIX_ATOMIC_LOCK)
+ ;
+ locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
+ (int) addr, _PR_AIX_ATOMIC_LOCK);
+ } while (locked == TRUE);
+ stack_elem->prstk_elem_next = addr;
+ _clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem);
+ return;
+}
+
+PR_IMPLEMENT(PRStackElem *)
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+boolean_t locked = TRUE;
+
+ /* Is it safe to cast a pointer to an int? */
+ PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
+ do {
+ while ((element = stack->prstk_head.prstk_elem_next) ==
+ (PRStackElem *) _PR_AIX_ATOMIC_LOCK)
+ ;
+ locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
+ (int)element, _PR_AIX_ATOMIC_LOCK);
+ } while (locked == TRUE);
+
+ if (element == NULL) {
+ _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL);
+ } else {
+ _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
+ (int) element->prstk_elem_next);
+ }
+ return element;
+}
+
+#endif /* _PR_HAVE_ATOMIC_CAS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aixwrap.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aixwrap.c
new file mode 100644
index 00000000..d829710a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/aixwrap.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: aixwrap.c
+ * Description:
+ * This file contains a single function, _MD_SELECT(), which simply
+ * invokes the select() function. This file is used in an ugly
+ * hack to override the system select() function on AIX releases
+ * prior to 4.2. (On AIX 4.2, we use a different mechanism to
+ * override select().)
+ */
+
+#ifndef AIX_RENAME_SELECT
+#error aixwrap.c should only be used on AIX 3.2 or 4.1
+#else
+
+#include <sys/select.h>
+#include <sys/poll.h>
+
+int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
+{
+ return select(width, r, w, e, t);
+}
+
+int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
+{
+ return poll(listptr, nfds, timeout);
+}
+
+#endif /* AIX_RENAME_SELECT */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/bsdi.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/bsdi.c
new file mode 100644
index 00000000..64676633
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/bsdi.c
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+
+void _MD_EarlyInit(void)
+{
+ /*
+ * Ignore FPE because coercion of a NaN to an int causes SIGFPE
+ * to be raised.
+ */
+ struct sigaction act;
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGFPE, &act, 0);
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for BSDI */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for BSDI.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for BSDI.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/darwin.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/darwin.c
new file mode 100644
index 00000000..3a1329e7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/darwin.c
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#if !defined(_PR_PTHREADS)
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#if !defined(_PR_PTHREADS)
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Darwin */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Darwin.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Darwin.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
+
+/* darwin.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/dgux.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/dgux.c
new file mode 100644
index 00000000..2874d9ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/dgux.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/*
+ * using only NSPR threads here
+ *
+ * Copied from the UnixWare implementation. Should be kept in sync
+ * with ../../../include/md/_dgux.h.
+ */
+
+#include <setjmp.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for DG/UX */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for DG/UX.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for DG/UX.");
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/freebsd.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/freebsd.c
new file mode 100644
index 00000000..dce244a3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/freebsd.c
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+
+void _MD_EarlyInit(void)
+{
+ /*
+ * Ignore FPE because coercion of a NaN to an int causes SIGFPE
+ * to be raised.
+ */
+ struct sigaction act;
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGFPE, &act, 0);
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) sigsetjmp(CONTEXT(t), 1);
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for FreeBSD */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for FreeBSD.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for FreeBSD.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/hpux.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/hpux.c
new file mode 100644
index 00000000..cf43e05e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/hpux.c
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <setjmp.h>
+
+#if defined(HPUX_LW_TIMER)
+
+#include <machine/inline.h>
+#include <machine/clock.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/pstat.h>
+
+int __lw_get_thread_times(int which, int64_t *sample, int64_t *time);
+
+static double msecond_per_itick;
+
+void _PR_HPUX_LW_IntervalInit(void)
+{
+ struct pst_processor psp;
+ int iticksperclktick, clk_tck;
+ int rv;
+
+ rv = pstat_getprocessor(&psp, sizeof(psp), 1, 0);
+ PR_ASSERT(rv != -1);
+
+ iticksperclktick = psp.psp_iticksperclktick;
+ clk_tck = sysconf(_SC_CLK_TCK);
+ msecond_per_itick = (1000.0)/(double)(iticksperclktick * clk_tck);
+}
+
+PRIntervalTime _PR_HPUX_LW_GetInterval(void)
+{
+ int64_t time, sample;
+
+ __lw_get_thread_times(1, &sample, &time);
+ /*
+ * Division is slower than float multiplication.
+ * return (time / iticks_per_msecond);
+ */
+ return (time * msecond_per_itick);
+}
+#endif /* HPUX_LW_TIMER */
+
+#if !defined(PTHREADS_USER)
+
+void _MD_EarlyInit(void)
+{
+#ifndef _PR_PTHREADS
+ /*
+ * The following piece of code is taken from ns/nspr/src/md_HP-UX.c.
+ * In the comment for revision 1.6, dated 1995/09/11 23:33:34,
+ * robm says:
+ * This version has some problems which need to be addressed.
+ * First, intercept all system calls and prevent them from
+ * executing the library code which performs stack switches
+ * before normal system call invocation. In order for library
+ * calls which make system calls to work (like stdio), however,
+ * we must also allocate our own stack and switch the primordial
+ * stack to use it. This isn't so bad, except that I fudged the
+ * backtrace length when copying the old stack to the new one.
+ *
+ * This is the original comment of robm in the code:
+ * XXXrobm Horrific. To avoid a problem with HP's system call
+ * code, we allocate a new stack for the primordial thread and
+ * use it. However, we don't know how far back the original stack
+ * goes. We should create a routine that performs a backtrace and
+ * finds out just how much we need to copy. As a temporary measure,
+ * I just copy an arbitrary guess.
+ *
+ * In an email to servereng dated 2 Jan 1997, Mike Patnode (mikep)
+ * suggests that this only needs to be done for HP-UX 9.
+ */
+#ifdef HPUX9
+#define PIDOOMA_STACK_SIZE 524288
+#define BACKTRACE_SIZE 8192
+ {
+ jmp_buf jb;
+ char *newstack;
+ char *oldstack;
+
+ if(!setjmp(jb)) {
+ newstack = (char *) PR_MALLOC(PIDOOMA_STACK_SIZE);
+ oldstack = (char *) (*(((int *) jb) + 1) - BACKTRACE_SIZE);
+ memcpy(newstack, oldstack, BACKTRACE_SIZE);
+ *(((int *) jb) + 1) = (int) (newstack + BACKTRACE_SIZE);
+ longjmp(jb, 1);
+ }
+ }
+#endif /* HPUX9 */
+#endif /* !_PR_PTHREADS */
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for HP-UX */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for HP-UX.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for HP-UX.");
+}
+#endif /* _PR_PTHREADS */
+
+void
+_MD_suspend_thread(PRThread *thread)
+{
+#ifdef _PR_PTHREADS
+#endif
+}
+
+void
+_MD_resume_thread(PRThread *thread)
+{
+#ifdef _PR_PTHREADS
+#endif
+}
+#endif /* PTHREADS_USER */
+
+/*
+ * The HP version of strchr is buggy. It looks past the end of the
+ * string and causes a segmentation fault when our (NSPR) version
+ * of malloc is used.
+ *
+ * A better solution might be to put a cushion in our malloc just in
+ * case HP's version of strchr somehow gets used instead of this one.
+ */
+char *
+strchr(const char *s, int c)
+{
+ char ch;
+
+ if (!s) {
+ return NULL;
+ }
+
+ ch = (char) c;
+
+ while ((*s) && ((*s) != ch)) {
+ s++;
+ }
+
+ if ((*s) == ch) {
+ return (char *) s;
+ }
+
+ return NULL;
+}
+
+/*
+ * Implemementation of memcmp in HP-UX (verified on releases A.09.03,
+ * A.09.07, and B.10.10) dumps core if called with:
+ * 1. First operand with address = 1(mod 4).
+ * 2. Size = 1(mod 4)
+ * 3. Last byte of the second operand is the last byte of the page and
+ * next page is not accessible(not mapped or protected)
+ * Thus, using the following naive version (tons of optimizations are
+ * possible;^)
+ */
+
+int memcmp(const void *s1, const void *s2, size_t n)
+{
+ register unsigned char *p1 = (unsigned char *) s1,
+ *p2 = (unsigned char *) s2;
+
+ while (n-- > 0) {
+ register int r = ((int) ((unsigned int) *p1))
+ - ((int) ((unsigned int) *p2));
+ if (r) return r;
+ p1++; p2++;
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/irix.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/irix.c
new file mode 100644
index 00000000..758e54d2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/irix.c
@@ -0,0 +1,1680 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/syssgi.h>
+#include <sys/time.h>
+#include <sys/immu.h>
+#include <sys/utsname.h>
+#include <sys/sysmp.h>
+#include <sys/pda.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/procfs.h>
+#include <task.h>
+#include <dlfcn.h>
+
+static void _MD_IrixIntervalInit(void);
+
+#if defined(_PR_PTHREADS)
+/*
+ * for compatibility with classic nspr
+ */
+void _PR_IRIX_CHILD_PROCESS()
+{
+}
+#else /* defined(_PR_PTHREADS) */
+
+static void irix_detach_sproc(void);
+char *_nspr_sproc_private; /* ptr. to private region in every sproc */
+
+extern PRUintn _pr_numCPU;
+
+typedef struct nspr_arena {
+ PRCList links;
+ usptr_t *usarena;
+} nspr_arena;
+
+#define ARENA_PTR(qp) \
+ ((nspr_arena *) ((char*) (qp) - offsetof(nspr_arena , links)))
+
+static usptr_t *alloc_new_arena(void);
+
+PRCList arena_list = PR_INIT_STATIC_CLIST(&arena_list);
+ulock_t arena_list_lock;
+nspr_arena first_arena;
+int _nspr_irix_arena_cnt = 1;
+
+PRCList sproc_list = PR_INIT_STATIC_CLIST(&sproc_list);
+ulock_t sproc_list_lock;
+
+typedef struct sproc_data {
+ void (*entry) (void *, size_t);
+ unsigned inh;
+ void *arg;
+ caddr_t sp;
+ size_t len;
+ int *pid;
+ int creator_pid;
+} sproc_data;
+
+typedef struct sproc_params {
+ PRCList links;
+ sproc_data sd;
+} sproc_params;
+
+#define SPROC_PARAMS_PTR(qp) \
+ ((sproc_params *) ((char*) (qp) - offsetof(sproc_params , links)))
+
+long _nspr_irix_lock_cnt = 0;
+long _nspr_irix_sem_cnt = 0;
+long _nspr_irix_pollsem_cnt = 0;
+
+usptr_t *_pr_usArena;
+ulock_t _pr_heapLock;
+
+usema_t *_pr_irix_exit_sem;
+PRInt32 _pr_irix_exit_now = 0;
+PRInt32 _pr_irix_process_exit_code = 0; /* exit code for PR_ProcessExit */
+PRInt32 _pr_irix_process_exit = 0; /* process exiting due to call to
+ PR_ProcessExit */
+
+int _pr_irix_primoridal_cpu_fd[2] = { -1, -1 };
+static void (*libc_exit)(int) = NULL;
+static void *libc_handle = NULL;
+
+#define _NSPR_DEF_INITUSERS 100 /* default value of CONF_INITUSERS */
+#define _NSPR_DEF_INITSIZE (4 * 1024 * 1024) /* 4 MB */
+
+int _irix_initusers = _NSPR_DEF_INITUSERS;
+int _irix_initsize = _NSPR_DEF_INITSIZE;
+
+PRIntn _pr_io_in_progress, _pr_clock_in_progress;
+
+PRInt32 _pr_md_irix_sprocs_created, _pr_md_irix_sprocs_failed;
+PRInt32 _pr_md_irix_sprocs = 1;
+PRCList _pr_md_irix_sproc_list =
+PR_INIT_STATIC_CLIST(&_pr_md_irix_sproc_list);
+
+sigset_t ints_off;
+extern sigset_t timer_set;
+
+#if !defined(PR_SETABORTSIG)
+#define PR_SETABORTSIG 18
+#endif
+/*
+ * terminate the entire application if any sproc exits abnormally
+ */
+PRBool _nspr_terminate_on_error = PR_TRUE;
+
+/*
+ * exported interface to set the shared arena parameters
+ */
+void _PR_Irix_Set_Arena_Params(PRInt32 initusers, PRInt32 initsize)
+{
+ _irix_initusers = initusers;
+ _irix_initsize = initsize;
+}
+
+static usptr_t *alloc_new_arena()
+{
+ return(usinit("/dev/zero"));
+}
+
+static PRStatus new_poll_sem(struct _MDThread *mdthr, int val)
+{
+PRIntn _is;
+PRStatus rv = PR_SUCCESS;
+usema_t *sem = NULL;
+PRCList *qp;
+nspr_arena *arena;
+usptr_t *irix_arena;
+PRThread *me = _MD_GET_ATTACHED_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(_is);
+ _PR_LOCK(arena_list_lock);
+ for (qp = arena_list.next; qp != &arena_list; qp = qp->next) {
+ arena = ARENA_PTR(qp);
+ sem = usnewpollsema(arena->usarena, val);
+ if (sem != NULL) {
+ mdthr->cvar_pollsem = sem;
+ mdthr->pollsem_arena = arena->usarena;
+ break;
+ }
+ }
+ if (sem == NULL) {
+ /*
+ * If no space left in the arena allocate a new one.
+ */
+ if (errno == ENOMEM) {
+ arena = PR_NEWZAP(nspr_arena);
+ if (arena != NULL) {
+ irix_arena = alloc_new_arena();
+ if (irix_arena) {
+ PR_APPEND_LINK(&arena->links, &arena_list);
+ _nspr_irix_arena_cnt++;
+ arena->usarena = irix_arena;
+ sem = usnewpollsema(arena->usarena, val);
+ if (sem != NULL) {
+ mdthr->cvar_pollsem = sem;
+ mdthr->pollsem_arena = arena->usarena;
+ } else
+ rv = PR_FAILURE;
+ } else {
+ PR_DELETE(arena);
+ rv = PR_FAILURE;
+ }
+
+ } else
+ rv = PR_FAILURE;
+ } else
+ rv = PR_FAILURE;
+ }
+ _PR_UNLOCK(arena_list_lock);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(_is);
+ if (rv == PR_SUCCESS)
+ _MD_ATOMIC_INCREMENT(&_nspr_irix_pollsem_cnt);
+ return rv;
+}
+
+static void free_poll_sem(struct _MDThread *mdthr)
+{
+PRIntn _is;
+PRThread *me = _MD_GET_ATTACHED_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(_is);
+ usfreepollsema(mdthr->cvar_pollsem, mdthr->pollsem_arena);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(_is);
+ _MD_ATOMIC_DECREMENT(&_nspr_irix_pollsem_cnt);
+}
+
+static PRStatus new_lock(struct _MDLock *lockp)
+{
+PRIntn _is;
+PRStatus rv = PR_SUCCESS;
+ulock_t lock = NULL;
+PRCList *qp;
+nspr_arena *arena;
+usptr_t *irix_arena;
+PRThread *me = _MD_GET_ATTACHED_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(_is);
+ _PR_LOCK(arena_list_lock);
+ for (qp = arena_list.next; qp != &arena_list; qp = qp->next) {
+ arena = ARENA_PTR(qp);
+ lock = usnewlock(arena->usarena);
+ if (lock != NULL) {
+ lockp->lock = lock;
+ lockp->arena = arena->usarena;
+ break;
+ }
+ }
+ if (lock == NULL) {
+ /*
+ * If no space left in the arena allocate a new one.
+ */
+ if (errno == ENOMEM) {
+ arena = PR_NEWZAP(nspr_arena);
+ if (arena != NULL) {
+ irix_arena = alloc_new_arena();
+ if (irix_arena) {
+ PR_APPEND_LINK(&arena->links, &arena_list);
+ _nspr_irix_arena_cnt++;
+ arena->usarena = irix_arena;
+ lock = usnewlock(irix_arena);
+ if (lock != NULL) {
+ lockp->lock = lock;
+ lockp->arena = arena->usarena;
+ } else
+ rv = PR_FAILURE;
+ } else {
+ PR_DELETE(arena);
+ rv = PR_FAILURE;
+ }
+
+ } else
+ rv = PR_FAILURE;
+ } else
+ rv = PR_FAILURE;
+ }
+ _PR_UNLOCK(arena_list_lock);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(_is);
+ if (rv == PR_SUCCESS)
+ _MD_ATOMIC_INCREMENT(&_nspr_irix_lock_cnt);
+ return rv;
+}
+
+static void free_lock(struct _MDLock *lockp)
+{
+PRIntn _is;
+PRThread *me = _MD_GET_ATTACHED_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(_is);
+ usfreelock(lockp->lock, lockp->arena);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(_is);
+ _MD_ATOMIC_DECREMENT(&_nspr_irix_lock_cnt);
+}
+
+void _MD_FREE_LOCK(struct _MDLock *lockp)
+{
+ PRIntn _is;
+ PRThread *me = _MD_GET_ATTACHED_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(_is);
+ free_lock(lockp);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(_is);
+}
+
+/*
+ * _MD_get_attached_thread
+ * Return the thread pointer of the current thread if it is attached.
+ *
+ * This function is needed for Irix because the thread-local-storage is
+ * implemented by mmapin'g a page with the MAP_LOCAL flag. This causes the
+ * sproc-private page to inherit contents of the page of the caller of sproc().
+ */
+PRThread *_MD_get_attached_thread(void)
+{
+
+ if (_MD_GET_SPROC_PID() == get_pid())
+ return _MD_THIS_THREAD();
+ else
+ return 0;
+}
+
+/*
+ * _MD_get_current_thread
+ * Return the thread pointer of the current thread (attaching it if
+ * necessary)
+ */
+PRThread *_MD_get_current_thread(void)
+{
+PRThread *me;
+
+ me = _MD_GET_ATTACHED_THREAD();
+ if (NULL == me) {
+ me = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(me != NULL);
+ return(me);
+}
+
+/*
+ * irix_detach_sproc
+ * auto-detach a sproc when it exits
+ */
+void irix_detach_sproc(void)
+{
+PRThread *me;
+
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED)) {
+ _PRI_DetachThread();
+ }
+}
+
+
+PRStatus _MD_NEW_LOCK(struct _MDLock *lockp)
+{
+ PRStatus rv;
+ PRIntn is;
+ PRThread *me = _MD_GET_ATTACHED_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ rv = new_lock(lockp);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return rv;
+}
+
+static void
+sigchld_handler(int sig)
+{
+ pid_t pid;
+ int status;
+
+ /*
+ * If an sproc exited abnormally send a SIGKILL signal to all the
+ * sprocs in the process to terminate the application
+ */
+ while ((pid = waitpid(0, &status, WNOHANG)) > 0) {
+ if (WIFSIGNALED(status) && ((WTERMSIG(status) == SIGSEGV) ||
+ (WTERMSIG(status) == SIGBUS) ||
+ (WTERMSIG(status) == SIGABRT) ||
+ (WTERMSIG(status) == SIGILL))) {
+
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(status);
+ }
+ }
+}
+
+static void save_context_and_block(int sig)
+{
+PRThread *me = _PR_MD_CURRENT_THREAD();
+_PRCPU *cpu = _PR_MD_CURRENT_CPU();
+
+ /*
+ * save context
+ */
+ (void) setjmp(me->md.jb);
+ /*
+ * unblock the suspending thread
+ */
+ if (me->cpu) {
+ /*
+ * I am a cpu thread, not a user-created GLOBAL thread
+ */
+ unblockproc(cpu->md.suspending_id);
+ } else {
+ unblockproc(me->md.suspending_id);
+ }
+ /*
+ * now, block current thread
+ */
+ blockproc(getpid());
+}
+
+/*
+** The irix kernel has a bug in it which causes async connect's which are
+** interrupted by a signal to fail terribly (EADDRINUSE is returned).
+** We work around the bug by blocking signals during the async connect
+** attempt.
+*/
+PRInt32 _MD_irix_connect(
+ PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 rv;
+ sigset_t oldset;
+
+ sigprocmask(SIG_BLOCK, &ints_off, &oldset);
+ rv = connect(osfd, addr, addrlen);
+ sigprocmask(SIG_SETMASK, &oldset, 0);
+
+ return(rv);
+}
+
+#include "prprf.h"
+
+/********************************************************************/
+/********************************************************************/
+/*************** Various thread like things for IRIX ****************/
+/********************************************************************/
+/********************************************************************/
+
+void *_MD_GetSP(PRThread *t)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ void *sp;
+
+ if (me == t)
+ (void) setjmp(t->md.jb);
+
+ sp = (void *)(t->md.jb[JB_SP]);
+ PR_ASSERT((sp >= (void *) t->stack->stackBottom) &&
+ (sp <= (void *) (t->stack->stackBottom + t->stack->stackSize)));
+ return(sp);
+}
+
+void _MD_InitLocks()
+{
+ char buf[200];
+ char *init_users, *init_size;
+
+ PR_snprintf(buf, sizeof(buf), "/dev/zero");
+
+ if (init_users = getenv("_NSPR_IRIX_INITUSERS"))
+ _irix_initusers = atoi(init_users);
+
+ if (init_size = getenv("_NSPR_IRIX_INITSIZE"))
+ _irix_initsize = atoi(init_size);
+
+ usconfig(CONF_INITUSERS, _irix_initusers);
+ usconfig(CONF_INITSIZE, _irix_initsize);
+ usconfig(CONF_AUTOGROW, 1);
+ usconfig(CONF_AUTORESV, 1);
+ if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) {
+ perror("PR_Init: unable to config mutex arena");
+ exit(-1);
+ }
+
+ _pr_usArena = usinit(buf);
+ if (!_pr_usArena) {
+ fprintf(stderr,
+ "PR_Init: Error - unable to create lock/monitor arena\n");
+ exit(-1);
+ }
+ _pr_heapLock = usnewlock(_pr_usArena);
+ _nspr_irix_lock_cnt++;
+
+ arena_list_lock = usnewlock(_pr_usArena);
+ _nspr_irix_lock_cnt++;
+
+ sproc_list_lock = usnewlock(_pr_usArena);
+ _nspr_irix_lock_cnt++;
+
+ _pr_irix_exit_sem = usnewsema(_pr_usArena, 0);
+ _nspr_irix_sem_cnt = 1;
+
+ first_arena.usarena = _pr_usArena;
+ PR_INIT_CLIST(&first_arena.links);
+ PR_APPEND_LINK(&first_arena.links, &arena_list);
+}
+
+/* _PR_IRIX_CHILD_PROCESS is a private API for Server group */
+void _PR_IRIX_CHILD_PROCESS()
+{
+extern PRUint32 _pr_global_threads;
+
+ PR_ASSERT(_PR_MD_CURRENT_CPU() == _pr_primordialCPU);
+ PR_ASSERT(_pr_numCPU == 1);
+ PR_ASSERT(_pr_global_threads == 0);
+ /*
+ * save the new pid
+ */
+ _pr_primordialCPU->md.id = getpid();
+ _MD_SET_SPROC_PID(getpid());
+}
+
+static PRStatus pr_cvar_wait_sem(PRThread *thread, PRIntervalTime timeout)
+{
+ int rv;
+
+#ifdef _PR_USE_POLL
+ struct pollfd pfd;
+ int msecs;
+
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ msecs = -1;
+ else
+ msecs = PR_IntervalToMilliseconds(timeout);
+#else
+ struct timeval tv, *tvp;
+ fd_set rd;
+
+ if(timeout == PR_INTERVAL_NO_TIMEOUT)
+ tvp = NULL;
+ else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&rd);
+ FD_SET(thread->md.cvar_pollsemfd, &rd);
+#endif
+
+ /*
+ * call uspsema only if a previous select call on this semaphore
+ * did not timeout
+ */
+ if (!thread->md.cvar_pollsem_select) {
+ rv = _PR_WAIT_SEM(thread->md.cvar_pollsem);
+ PR_ASSERT(rv >= 0);
+ } else
+ rv = 0;
+again:
+ if(!rv) {
+#ifdef _PR_USE_POLL
+ pfd.events = POLLIN;
+ pfd.fd = thread->md.cvar_pollsemfd;
+ rv = _MD_POLL(&pfd, 1, msecs);
+#else
+ rv = _MD_SELECT(thread->md.cvar_pollsemfd + 1, &rd, NULL,NULL,tvp);
+#endif
+ if ((rv == -1) && (errno == EINTR)) {
+ rv = 0;
+ goto again;
+ }
+ PR_ASSERT(rv >= 0);
+ }
+
+ if (rv > 0) {
+ /*
+ * acquired the semaphore, call uspsema next time
+ */
+ thread->md.cvar_pollsem_select = 0;
+ return PR_SUCCESS;
+ } else {
+ /*
+ * select timed out; must call select, not uspsema, when trying
+ * to acquire the semaphore the next time
+ */
+ thread->md.cvar_pollsem_select = 1;
+ return PR_FAILURE;
+ }
+}
+
+PRStatus _MD_wait(PRThread *thread, PRIntervalTime ticks)
+{
+ if ( thread->flags & _PR_GLOBAL_SCOPE ) {
+ _MD_CHECK_FOR_EXIT();
+ if (pr_cvar_wait_sem(thread, ticks) == PR_FAILURE) {
+ _MD_CHECK_FOR_EXIT();
+ /*
+ * wait timed out
+ */
+ _PR_THREAD_LOCK(thread);
+ if (thread->wait.cvar) {
+ /*
+ * The thread will remove itself from the waitQ
+ * of the cvar in _PR_WaitCondVar
+ */
+ thread->wait.cvar = NULL;
+ thread->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ _PR_THREAD_UNLOCK(thread);
+ /*
+ * This thread was woken up by a notifying thread
+ * at the same time as a timeout; so, consume the
+ * extra post operation on the semaphore
+ */
+ _MD_CHECK_FOR_EXIT();
+ pr_cvar_wait_sem(thread, PR_INTERVAL_NO_TIMEOUT);
+ }
+ _MD_CHECK_FOR_EXIT();
+ }
+ } else {
+ _PR_MD_SWITCH_CONTEXT(thread);
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus _MD_WakeupWaiter(PRThread *thread)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntn is;
+
+ PR_ASSERT(_pr_md_idle_cpus >= 0);
+ if (thread == NULL) {
+ if (_pr_md_idle_cpus)
+ _MD_Wakeup_CPUs();
+ } else if (!_PR_IS_NATIVE_THREAD(thread)) {
+ if (_pr_md_idle_cpus)
+ _MD_Wakeup_CPUs();
+ } else {
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(thread));
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ _MD_CVAR_POST_SEM(thread);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ }
+ return PR_SUCCESS;
+}
+
+void create_sproc (void (*entry) (void *, size_t), unsigned inh,
+ void *arg, caddr_t sp, size_t len, int *pid)
+{
+sproc_params sparams;
+char data;
+int rv;
+PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) {
+ *pid = sprocsp(entry, /* startup func */
+ inh, /* attribute flags */
+ arg, /* thread param */
+ sp, /* stack address */
+ len); /* stack size */
+ } else {
+ sparams.sd.entry = entry;
+ sparams.sd.inh = inh;
+ sparams.sd.arg = arg;
+ sparams.sd.sp = sp;
+ sparams.sd.len = len;
+ sparams.sd.pid = pid;
+ sparams.sd.creator_pid = getpid();
+ _PR_LOCK(sproc_list_lock);
+ PR_APPEND_LINK(&sparams.links, &sproc_list);
+ rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);
+ PR_ASSERT(rv == 1);
+ _PR_UNLOCK(sproc_list_lock);
+ blockproc(getpid());
+ }
+}
+
+/*
+ * _PR_MD_WAKEUP_PRIMORDIAL_CPU
+ *
+ * wakeup cpu 0
+ */
+
+void _PR_MD_WAKEUP_PRIMORDIAL_CPU()
+{
+char data = '0';
+int rv;
+
+ rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);
+ PR_ASSERT(rv == 1);
+}
+
+/*
+ * _PR_MD_primordial_cpu
+ *
+ * process events that need to executed by the primordial cpu on each
+ * iteration through the idle loop
+ */
+
+void _PR_MD_primordial_cpu()
+{
+PRCList *qp;
+sproc_params *sp;
+int pid;
+
+ _PR_LOCK(sproc_list_lock);
+ while ((qp = sproc_list.next) != &sproc_list) {
+ sp = SPROC_PARAMS_PTR(qp);
+ PR_REMOVE_LINK(&sp->links);
+ pid = sp->sd.creator_pid;
+ (*(sp->sd.pid)) = sprocsp(sp->sd.entry, /* startup func */
+ sp->sd.inh, /* attribute flags */
+ sp->sd.arg, /* thread param */
+ sp->sd.sp, /* stack address */
+ sp->sd.len); /* stack size */
+ unblockproc(pid);
+ }
+ _PR_UNLOCK(sproc_list_lock);
+}
+
+PRStatus _MD_CreateThread(PRThread *thread,
+void (*start)(void *),
+PRThreadPriority priority,
+PRThreadScope scope,
+PRThreadState state,
+PRUint32 stackSize)
+{
+ typedef void (*SprocEntry) (void *, size_t);
+ SprocEntry spentry = (SprocEntry)start;
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 pid;
+ PRStatus rv;
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ thread->md.cvar_pollsem_select = 0;
+ thread->flags |= _PR_GLOBAL_SCOPE;
+
+ thread->md.cvar_pollsemfd = -1;
+ if (new_poll_sem(&thread->md,0) == PR_FAILURE) {
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+ thread->md.cvar_pollsemfd =
+ _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);
+ if ((thread->md.cvar_pollsemfd < 0)) {
+ free_poll_sem(&thread->md);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+
+ create_sproc(spentry, /* startup func */
+ PR_SALL, /* attribute flags */
+ (void *)thread, /* thread param */
+ NULL, /* stack address */
+ stackSize, &pid); /* stack size */
+ if (pid > 0) {
+ _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created);
+ _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs);
+ rv = PR_SUCCESS;
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return rv;
+ } else {
+ close(thread->md.cvar_pollsemfd);
+ thread->md.cvar_pollsemfd = -1;
+ free_poll_sem(&thread->md);
+ thread->md.cvar_pollsem = NULL;
+ _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+}
+
+void _MD_CleanThread(PRThread *thread)
+{
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ close(thread->md.cvar_pollsemfd);
+ thread->md.cvar_pollsemfd = -1;
+ free_poll_sem(&thread->md);
+ thread->md.cvar_pollsem = NULL;
+ }
+}
+
+void _MD_SetPriority(_MDThread *thread, PRThreadPriority newPri)
+{
+ return;
+}
+
+extern void _MD_unix_terminate_waitpid_daemon(void);
+
+void
+_MD_CleanupBeforeExit(void)
+{
+ extern PRInt32 _pr_cpus_exit;
+
+ _MD_unix_terminate_waitpid_daemon();
+
+ _pr_irix_exit_now = 1;
+ if (_pr_numCPU > 1) {
+ /*
+ * Set a global flag, and wakeup all cpus which will notice the flag
+ * and exit.
+ */
+ _pr_cpus_exit = getpid();
+ _MD_Wakeup_CPUs();
+ while(_pr_numCPU > 1) {
+ _PR_WAIT_SEM(_pr_irix_exit_sem);
+ _pr_numCPU--;
+ }
+ }
+ /*
+ * cause global threads on the recycle list to exit
+ */
+ _PR_DEADQ_LOCK;
+ if (_PR_NUM_DEADNATIVE != 0) {
+ PRThread *thread;
+ PRCList *ptr;
+
+ ptr = _PR_DEADNATIVEQ.next;
+ while( ptr != &_PR_DEADNATIVEQ ) {
+ thread = _PR_THREAD_PTR(ptr);
+ _MD_CVAR_POST_SEM(thread);
+ ptr = ptr->next;
+ }
+ }
+ _PR_DEADQ_UNLOCK;
+ while(_PR_NUM_DEADNATIVE > 1) {
+ _PR_WAIT_SEM(_pr_irix_exit_sem);
+ _PR_DEC_DEADNATIVE;
+ }
+}
+
+#ifdef _PR_HAVE_SGI_PRDA_PROCMASK
+extern void __sgi_prda_procmask(int);
+#endif
+
+PRStatus
+_MD_InitAttachedThread(PRThread *thread, PRBool wakeup_parent)
+{
+ PRStatus rv = PR_SUCCESS;
+
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ if (new_poll_sem(&thread->md,0) == PR_FAILURE) {
+ return PR_FAILURE;
+ }
+ thread->md.cvar_pollsemfd =
+ _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem);
+ if ((thread->md.cvar_pollsemfd < 0)) {
+ free_poll_sem(&thread->md);
+ return PR_FAILURE;
+ }
+ if (_MD_InitThread(thread, PR_FALSE) == PR_FAILURE) {
+ close(thread->md.cvar_pollsemfd);
+ thread->md.cvar_pollsemfd = -1;
+ free_poll_sem(&thread->md);
+ thread->md.cvar_pollsem = NULL;
+ return PR_FAILURE;
+ }
+ }
+ return rv;
+}
+
+PRStatus
+_MD_InitThread(PRThread *thread, PRBool wakeup_parent)
+{
+ struct sigaction sigact;
+ PRStatus rv = PR_SUCCESS;
+
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ thread->md.id = getpid();
+ setblockproccnt(thread->md.id, 0);
+ _MD_SET_SPROC_PID(getpid());
+#ifdef _PR_HAVE_SGI_PRDA_PROCMASK
+ /*
+ * enable user-level processing of sigprocmask(); this is an
+ * undocumented feature available in Irix 6.2, 6.3, 6.4 and 6.5
+ */
+ __sgi_prda_procmask(USER_LEVEL);
+#endif
+ /*
+ * set up SIGUSR1 handler; this is used to save state
+ */
+ sigact.sa_handler = save_context_and_block;
+ sigact.sa_flags = SA_RESTART;
+ /*
+ * Must mask clock interrupts
+ */
+ sigact.sa_mask = timer_set;
+ sigaction(SIGUSR1, &sigact, 0);
+
+
+ /*
+ * PR_SETABORTSIG is a new command implemented in a patch to
+ * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all
+ * sprocs in the process when one of them terminates abnormally
+ *
+ */
+ if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {
+ /*
+ * if (errno == EINVAL)
+ *
+ * PR_SETABORTSIG not supported under this OS.
+ * You may want to get a recent kernel rollup patch that
+ * supports this feature.
+ */
+ }
+ /*
+ * SIGCLD handler for detecting abormally-terminating
+ * sprocs and for reaping sprocs
+ */
+ sigact.sa_handler = sigchld_handler;
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_mask = ints_off;
+ sigaction(SIGCLD, &sigact, NULL);
+ }
+ return rv;
+}
+
+/*
+ * PR_Cleanup should be executed on the primordial sproc; migrate the thread
+ * to the primordial cpu
+ */
+
+void _PR_MD_PRE_CLEANUP(PRThread *me)
+{
+PRIntn is;
+_PRCPU *cpu = _pr_primordialCPU;
+
+ PR_ASSERT(cpu);
+
+ me->flags |= _PR_BOUND_THREAD;
+
+ if (me->cpu->id != 0) {
+ _PR_INTSOFF(is);
+ _PR_RUNQ_LOCK(cpu);
+ me->cpu = cpu;
+ me->state = _PR_RUNNABLE;
+ _PR_ADD_RUNQ(me, cpu, me->priority);
+ _PR_RUNQ_UNLOCK(cpu);
+ _MD_Wakeup_CPUs();
+
+ _PR_MD_SWITCH_CONTEXT(me);
+
+ _PR_FAST_INTSON(is);
+ PR_ASSERT(me->cpu->id == 0);
+ }
+}
+
+/*
+ * process exiting
+ */
+PR_EXTERN(void ) _MD_exit(PRIntn status)
+{
+PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ /*
+ * the exit code of the process is the exit code of the primordial
+ * sproc
+ */
+ if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) {
+ /*
+ * primordial sproc case: call _exit directly
+ * Cause SIGKILL to be sent to other sprocs
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(status);
+ } else {
+ int rv;
+ char data;
+ sigset_t set;
+
+ /*
+ * non-primordial sproc case: cause the primordial sproc, cpu 0,
+ * to wakeup and call _exit
+ */
+ _pr_irix_process_exit = 1;
+ _pr_irix_process_exit_code = status;
+ rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1);
+ PR_ASSERT(rv == 1);
+ /*
+ * block all signals and wait for SIGKILL to terminate this sproc
+ */
+ sigfillset(&set);
+ sigsuspend(&set);
+ /*
+ * this code doesn't (shouldn't) execute
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(status);
+ }
+}
+
+/*
+ * Override the exit() function in libc to cause the process to exit
+ * when the primodial/main nspr thread calls exit. Calls to exit by any
+ * other thread simply result in a call to the exit function in libc.
+ * The exit code of the process is the exit code of the primordial
+ * sproc.
+ */
+
+void exit(int status)
+{
+PRThread *me, *thr;
+PRCList *qp;
+
+ if (!_pr_initialized) {
+ if (!libc_exit) {
+
+ if (!libc_handle)
+ libc_handle = dlopen("libc.so",RTLD_NOW);
+ if (libc_handle)
+ libc_exit = (void (*)(int)) dlsym(libc_handle, "exit");
+ }
+ if (libc_exit)
+ (*libc_exit)(status);
+ else
+ _exit(status);
+ }
+
+ me = _PR_MD_CURRENT_THREAD();
+
+ if (me == NULL) /* detached thread */
+ (*libc_exit)(status);
+
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) ||
+ (_PR_MD_CURRENT_CPU())->id == me->cpu->id);
+
+ if (me->flags & _PR_PRIMORDIAL) {
+
+ me->flags |= _PR_BOUND_THREAD;
+
+ PR_ASSERT((_PR_MD_CURRENT_CPU())->id == me->cpu->id);
+ if (me->cpu->id != 0) {
+ _PRCPU *cpu = _pr_primordialCPU;
+ PRIntn is;
+
+ _PR_INTSOFF(is);
+ _PR_RUNQ_LOCK(cpu);
+ me->cpu = cpu;
+ me->state = _PR_RUNNABLE;
+ _PR_ADD_RUNQ(me, cpu, me->priority);
+ _PR_RUNQ_UNLOCK(cpu);
+ _MD_Wakeup_CPUs();
+
+ _PR_MD_SWITCH_CONTEXT(me);
+
+ _PR_FAST_INTSON(is);
+ }
+
+ PR_ASSERT((_PR_MD_CURRENT_CPU())->id == 0);
+
+ if (prctl(PR_GETNSHARE) > 1) {
+#define SPROC_EXIT_WAIT_TIME 5
+ int sleep_cnt = SPROC_EXIT_WAIT_TIME;
+
+ /*
+ * sprocs still running; caue cpus and recycled global threads
+ * to exit
+ */
+ _pr_irix_exit_now = 1;
+ if (_pr_numCPU > 1) {
+ _MD_Wakeup_CPUs();
+ }
+ _PR_DEADQ_LOCK;
+ if (_PR_NUM_DEADNATIVE != 0) {
+ PRThread *thread;
+ PRCList *ptr;
+
+ ptr = _PR_DEADNATIVEQ.next;
+ while( ptr != &_PR_DEADNATIVEQ ) {
+ thread = _PR_THREAD_PTR(ptr);
+ _MD_CVAR_POST_SEM(thread);
+ ptr = ptr->next;
+ }
+ }
+
+ while (sleep_cnt-- > 0) {
+ if (waitpid(0, NULL, WNOHANG) >= 0)
+ sleep(1);
+ else
+ break;
+ }
+ prctl(PR_SETEXITSIG, SIGKILL);
+ }
+ (*libc_exit)(status);
+ } else {
+ /*
+ * non-primordial thread; simply call exit in libc.
+ */
+ (*libc_exit)(status);
+ }
+}
+
+
+void
+_MD_InitRunningCPU(_PRCPU *cpu)
+{
+ extern int _pr_md_pipefd[2];
+
+ _MD_unix_init_running_cpu(cpu);
+ cpu->md.id = getpid();
+ _MD_SET_SPROC_PID(getpid());
+ if (_pr_md_pipefd[0] >= 0) {
+ _PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0];
+#ifndef _PR_USE_POLL
+ FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu));
+#endif
+ }
+}
+
+void
+_MD_ExitThread(PRThread *thread)
+{
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ _MD_ATOMIC_DECREMENT(&_pr_md_irix_sprocs);
+ _MD_CLEAN_THREAD(thread);
+ _MD_SET_CURRENT_THREAD(NULL);
+ }
+}
+
+void
+_MD_SuspendCPU(_PRCPU *cpu)
+{
+ PRInt32 rv;
+
+ cpu->md.suspending_id = getpid();
+ rv = kill(cpu->md.id, SIGUSR1);
+ PR_ASSERT(rv == 0);
+ /*
+ * now, block the current thread/cpu until woken up by the suspended
+ * thread from it's SIGUSR1 signal handler
+ */
+ blockproc(getpid());
+
+}
+
+void
+_MD_ResumeCPU(_PRCPU *cpu)
+{
+ unblockproc(cpu->md.id);
+}
+
+#if 0
+/*
+ * save the register context of a suspended sproc
+ */
+void get_context(PRThread *thr)
+{
+ int len, fd;
+ char pidstr[24];
+ char path[24];
+
+ /*
+ * open the file corresponding to this process in procfs
+ */
+ sprintf(path,"/proc/%s","00000");
+ len = strlen(path);
+ sprintf(pidstr,"%d",thr->md.id);
+ len -= strlen(pidstr);
+ sprintf(path + len,"%s",pidstr);
+ fd = open(path,O_RDONLY);
+ if (fd >= 0) {
+ (void) ioctl(fd, PIOCGREG, thr->md.gregs);
+ close(fd);
+ }
+ return;
+}
+#endif /* 0 */
+
+void
+_MD_SuspendThread(PRThread *thread)
+{
+ PRInt32 rv;
+
+ PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
+ _PR_IS_GCABLE_THREAD(thread));
+
+ thread->md.suspending_id = getpid();
+ rv = kill(thread->md.id, SIGUSR1);
+ PR_ASSERT(rv == 0);
+ /*
+ * now, block the current thread/cpu until woken up by the suspended
+ * thread from it's SIGUSR1 signal handler
+ */
+ blockproc(getpid());
+}
+
+void
+_MD_ResumeThread(PRThread *thread)
+{
+ PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
+ _PR_IS_GCABLE_THREAD(thread));
+ (void)unblockproc(thread->md.id);
+}
+
+/*
+ * return the set of processors available for scheduling procs in the
+ * "mask" argument
+ */
+PRInt32 _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask)
+{
+ PRInt32 nprocs, rv;
+ struct pda_stat *pstat;
+#define MAX_PROCESSORS 32
+
+ nprocs = sysmp(MP_NPROCS);
+ if (nprocs < 0)
+ return(-1);
+ pstat = (struct pda_stat*)PR_MALLOC(sizeof(struct pda_stat) * nprocs);
+ if (pstat == NULL)
+ return(-1);
+ rv = sysmp(MP_STAT, pstat);
+ if (rv < 0) {
+ PR_DELETE(pstat);
+ return(-1);
+ }
+ /*
+ * look at the first 32 cpus
+ */
+ nprocs = (nprocs > MAX_PROCESSORS) ? MAX_PROCESSORS : nprocs;
+ *mask = 0;
+ while (nprocs) {
+ if ((pstat->p_flags & PDAF_ENABLED) &&
+ !(pstat->p_flags & PDAF_ISOLATED)) {
+ *mask |= (1 << pstat->p_cpuid);
+ }
+ nprocs--;
+ pstat++;
+ }
+ return 0;
+}
+
+static char *_thr_state[] = {
+ "UNBORN",
+ "RUNNABLE",
+ "RUNNING",
+ "LOCK_WAIT",
+ "COND_WAIT",
+ "JOIN_WAIT",
+ "IO_WAIT",
+ "SUSPENDED",
+ "DEAD"
+};
+
+void _PR_List_Threads()
+{
+ PRThread *thr;
+ void *handle;
+ struct _PRCPU *cpu;
+ PRCList *qp;
+ int len, fd;
+ char pidstr[24];
+ char path[24];
+ prpsinfo_t pinfo;
+
+
+ printf("\n%s %-s\n"," ","LOCAL Threads");
+ printf("%s %-s\n"," ","----- -------");
+ printf("%s %-14s %-10s %-12s %-3s %-10s %-10s %-12s\n\n"," ",
+ "Thread", "State", "Wait-Handle",
+ "Cpu","Stk-Base","Stk-Sz","SP");
+ for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
+ qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
+ thr = _PR_ACTIVE_THREAD_PTR(qp);
+ printf("%s 0x%-12x %-10s "," ",thr,_thr_state[thr->state]);
+ if (thr->state == _PR_LOCK_WAIT)
+ handle = thr->wait.lock;
+ else if (thr->state == _PR_COND_WAIT)
+ handle = thr->wait.cvar;
+ else
+ handle = NULL;
+ if (handle)
+ printf("0x%-10x ",handle);
+ else
+ printf("%-12s "," ");
+ printf("%-3d ",thr->cpu->id);
+ printf("0x%-8x ",thr->stack->stackBottom);
+ printf("0x%-8x ",thr->stack->stackSize);
+ printf("0x%-10x\n",thr->md.jb[JB_SP]);
+ }
+
+ printf("\n%s %-s\n"," ","GLOBAL Threads");
+ printf("%s %-s\n"," ","------ -------");
+ printf("%s %-14s %-6s %-12s %-12s %-12s %-12s\n\n"," ","Thread",
+ "Pid","State","Wait-Handle",
+ "Stk-Base","Stk-Sz");
+
+ for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
+ qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
+ thr = _PR_ACTIVE_THREAD_PTR(qp);
+ if (thr->cpu != NULL)
+ continue; /* it is a cpu thread */
+ printf("%s 0x%-12x %-6d "," ",thr,thr->md.id);
+ /*
+ * check if the sproc is still running
+ * first call prctl(PR_GETSHMASK,pid) to check if
+ * the process is part of the share group (the pid
+ * could have been recycled by the OS)
+ */
+ if (prctl(PR_GETSHMASK,thr->md.id) < 0) {
+ printf("%-12s\n","TERMINATED");
+ continue;
+ }
+ /*
+ * Now, check if the sproc terminated and is in zombie
+ * state
+ */
+ sprintf(path,"/proc/pinfo/%s","00000");
+ len = strlen(path);
+ sprintf(pidstr,"%d",thr->md.id);
+ len -= strlen(pidstr);
+ sprintf(path + len,"%s",pidstr);
+ fd = open(path,O_RDONLY);
+ if (fd >= 0) {
+ if (ioctl(fd, PIOCPSINFO, &pinfo) < 0)
+ printf("%-12s ","TERMINATED");
+ else if (pinfo.pr_zomb)
+ printf("%-12s ","TERMINATED");
+ else
+ printf("%-12s ",_thr_state[thr->state]);
+ close(fd);
+ } else {
+ printf("%-12s ","TERMINATED");
+ }
+
+ if (thr->state == _PR_LOCK_WAIT)
+ handle = thr->wait.lock;
+ else if (thr->state == _PR_COND_WAIT)
+ handle = thr->wait.cvar;
+ else
+ handle = NULL;
+ if (handle)
+ printf("%-12x ",handle);
+ else
+ printf("%-12s "," ");
+ printf("0x%-10x ",thr->stack->stackBottom);
+ printf("0x%-10x\n",thr->stack->stackSize);
+ }
+
+ printf("\n%s %-s\n"," ","CPUs");
+ printf("%s %-s\n"," ","----");
+ printf("%s %-14s %-6s %-12s \n\n"," ","Id","Pid","State");
+
+
+ for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
+ cpu = _PR_CPU_PTR(qp);
+ printf("%s %-14d %-6d "," ",cpu->id,cpu->md.id);
+ /*
+ * check if the sproc is still running
+ * first call prctl(PR_GETSHMASK,pid) to check if
+ * the process is part of the share group (the pid
+ * could have been recycled by the OS)
+ */
+ if (prctl(PR_GETSHMASK,cpu->md.id) < 0) {
+ printf("%-12s\n","TERMINATED");
+ continue;
+ }
+ /*
+ * Now, check if the sproc terminated and is in zombie
+ * state
+ */
+ sprintf(path,"/proc/pinfo/%s","00000");
+ len = strlen(path);
+ sprintf(pidstr,"%d",cpu->md.id);
+ len -= strlen(pidstr);
+ sprintf(path + len,"%s",pidstr);
+ fd = open(path,O_RDONLY);
+ if (fd >= 0) {
+ if (ioctl(fd, PIOCPSINFO, &pinfo) < 0)
+ printf("%-12s\n","TERMINATED");
+ else if (pinfo.pr_zomb)
+ printf("%-12s\n","TERMINATED");
+ else
+ printf("%-12s\n","RUNNING");
+ close(fd);
+ } else {
+ printf("%-12s\n","TERMINATED");
+ }
+
+ }
+ fflush(stdout);
+}
+#endif /* defined(_PR_PTHREADS) */
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#if !defined(_PR_PTHREADS)
+ if (isCurrent) {
+ (void) setjmp(t->md.jb);
+ }
+ *np = sizeof(t->md.jb) / sizeof(PRWord);
+ return (PRWord *) (t->md.jb);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+void _MD_EarlyInit(void)
+{
+#if !defined(_PR_PTHREADS)
+ char *eval;
+ int fd;
+ extern int __ateachexit(void (*func)(void));
+
+ sigemptyset(&ints_off);
+ sigaddset(&ints_off, SIGALRM);
+ sigaddset(&ints_off, SIGIO);
+ sigaddset(&ints_off, SIGCLD);
+
+ if (eval = getenv("_NSPR_TERMINATE_ON_ERROR"))
+ _nspr_terminate_on_error = (0 == atoi(eval) == 0) ? PR_FALSE : PR_TRUE;
+
+ fd = open("/dev/zero",O_RDWR , 0);
+ if (fd < 0) {
+ perror("open /dev/zero failed");
+ exit(1);
+ }
+ /*
+ * Set up the sproc private data area.
+ * This region exists at the same address, _nspr_sproc_private, for
+ * every sproc, but each sproc gets a private copy of the region.
+ */
+ _nspr_sproc_private = (char*)mmap(0, _pr_pageSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE| MAP_LOCAL, fd, 0);
+ if (_nspr_sproc_private == (void*)-1) {
+ perror("mmap /dev/zero failed");
+ exit(1);
+ }
+ _MD_SET_SPROC_PID(getpid());
+ close(fd);
+ __ateachexit(irix_detach_sproc);
+#endif
+ _MD_IrixIntervalInit();
+} /* _MD_EarlyInit */
+
+void _MD_IrixInit(void)
+{
+#if !defined(_PR_PTHREADS)
+ struct sigaction sigact;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ int rv;
+
+#ifdef _PR_HAVE_SGI_PRDA_PROCMASK
+ /*
+ * enable user-level processing of sigprocmask(); this is an undocumented
+ * feature available in Irix 6.2, 6.3, 6.4 and 6.5
+ */
+ __sgi_prda_procmask(USER_LEVEL);
+#endif
+
+ /*
+ * set up SIGUSR1 handler; this is used to save state
+ * during PR_SuspendAll
+ */
+ sigact.sa_handler = save_context_and_block;
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_mask = ints_off;
+ sigaction(SIGUSR1, &sigact, 0);
+
+ /*
+ * Change the name of the core file from core to core.pid,
+ * This is inherited by the sprocs created by this process
+ */
+#ifdef PR_COREPID
+ prctl(PR_COREPID, 0, 1);
+#endif
+ /*
+ * Irix-specific terminate on error processing
+ */
+ /*
+ * PR_SETABORTSIG is a new command implemented in a patch to
+ * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all
+ * sprocs in the process when one of them terminates abnormally
+ *
+ */
+ if (prctl(PR_SETABORTSIG, SIGKILL) < 0) {
+ /*
+ * if (errno == EINVAL)
+ *
+ * PR_SETABORTSIG not supported under this OS.
+ * You may want to get a recent kernel rollup patch that
+ * supports this feature.
+ *
+ */
+ }
+ /*
+ * PR_SETEXITSIG - send the SIGCLD signal to the parent
+ * sproc when any sproc terminates
+ *
+ * This is used to cause the entire application to
+ * terminate when any sproc terminates abnormally by
+ * receipt of a SIGSEGV, SIGBUS or SIGABRT signal.
+ * If this is not done, the application may seem
+ * "hung" to the user because the other sprocs may be
+ * waiting for resources held by the
+ * abnormally-terminating sproc.
+ */
+ prctl(PR_SETEXITSIG, 0);
+
+ sigact.sa_handler = sigchld_handler;
+ sigact.sa_flags = SA_RESTART;
+ sigact.sa_mask = ints_off;
+ sigaction(SIGCLD, &sigact, NULL);
+
+ /*
+ * setup stack fields for the primordial thread
+ */
+ me->stack->stackSize = prctl(PR_GETSTACKSIZE);
+ me->stack->stackBottom = me->stack->stackTop - me->stack->stackSize;
+
+ rv = pipe(_pr_irix_primoridal_cpu_fd);
+ PR_ASSERT(rv == 0);
+#ifndef _PR_USE_POLL
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0];
+ FD_SET(_pr_irix_primoridal_cpu_fd[0], &_PR_FD_READ_SET(me->cpu));
+#endif
+
+ libc_handle = dlopen("libc.so",RTLD_NOW);
+ PR_ASSERT(libc_handle != NULL);
+ libc_exit = (void (*)(int)) dlsym(libc_handle, "exit");
+ PR_ASSERT(libc_exit != NULL);
+ /* dlclose(libc_handle); */
+
+#endif /* _PR_PTHREADS */
+
+ _PR_UnixInit();
+}
+
+/**************************************************************************/
+/************** code and such for NSPR 2.0's interval times ***************/
+/**************************************************************************/
+
+#define PR_PSEC_PER_SEC 1000000000000ULL /* 10^12 */
+
+#ifndef SGI_CYCLECNTR_SIZE
+#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */
+#endif
+
+static PRIntn mmem_fd = -1;
+static PRIntn clock_width = 0;
+static void *iotimer_addr = NULL;
+static PRUint32 pr_clock_mask = 0;
+static PRUint32 pr_clock_shift = 0;
+static PRIntervalTime pr_ticks = 0;
+static PRUint32 pr_clock_granularity = 1;
+static PRUint32 pr_previous = 0, pr_residual = 0;
+static PRUint32 pr_ticks_per_second = 0;
+
+extern PRIntervalTime _PR_UNIX_GetInterval(void);
+extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
+
+static void _MD_IrixIntervalInit(void)
+{
+ /*
+ * As much as I would like, the service available through this
+ * interface on R3000's (aka, IP12) just isn't going to make it.
+ * The register is only 24 bits wide, and rolls over at a verocious
+ * rate.
+ */
+ PRUint32 one_tick = 0;
+ struct utsname utsinfo;
+ uname(&utsinfo);
+ if ((strncmp("IP12", utsinfo.machine, 4) != 0)
+ && ((mmem_fd = open("/dev/mmem", O_RDONLY)) != -1))
+ {
+ int poffmask = getpagesize() - 1;
+ __psunsigned_t phys_addr, raddr, cycleval;
+
+ phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
+ raddr = phys_addr & ~poffmask;
+ iotimer_addr = mmap(
+ 0, poffmask, PROT_READ, MAP_PRIVATE, mmem_fd, (__psint_t)raddr);
+
+ clock_width = syssgi(SGI_CYCLECNTR_SIZE);
+ if (clock_width < 0)
+ {
+ /*
+ * We must be executing on a 6.0 or earlier system, since the
+ * SGI_CYCLECNTR_SIZE call is not supported.
+ *
+ * The only pre-6.1 platforms with 64-bit counters are
+ * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
+ */
+ if (!strncmp(utsinfo.machine, "IP19", 4) ||
+ !strncmp(utsinfo.machine, "IP21", 4))
+ clock_width = 64;
+ else
+ clock_width = 32;
+ }
+
+ /*
+ * 'cycleval' is picoseconds / increment of the counter.
+ * I'm pushing for a tick to be 100 microseconds, 10^(-4).
+ * That leaves 10^(-8) left over, or 10^8 / cycleval.
+ * Did I do that right?
+ */
+
+ one_tick = 100000000UL / cycleval ; /* 100 microseconds */
+
+ while (0 != one_tick)
+ {
+ pr_clock_shift += 1;
+ one_tick = one_tick >> 1;
+ pr_clock_granularity = pr_clock_granularity << 1;
+ }
+ pr_clock_mask = pr_clock_granularity - 1; /* to make a mask out of it */
+ pr_ticks_per_second = PR_PSEC_PER_SEC
+ / ((PRUint64)pr_clock_granularity * (PRUint64)cycleval);
+
+ iotimer_addr = (void*)
+ ((__psunsigned_t)iotimer_addr + (phys_addr & poffmask));
+ }
+ else
+ {
+ pr_ticks_per_second = _PR_UNIX_TicksPerSecond();
+ }
+} /* _MD_IrixIntervalInit */
+
+PRIntervalTime _MD_IrixIntervalPerSec(void)
+{
+ return pr_ticks_per_second;
+}
+
+PRIntervalTime _MD_IrixGetInterval(void)
+{
+ if (mmem_fd != -1)
+ {
+ if (64 == clock_width)
+ {
+ PRUint64 temp = *(PRUint64*)iotimer_addr;
+ pr_ticks = (PRIntervalTime)(temp >> pr_clock_shift);
+ }
+ else
+ {
+ PRIntervalTime ticks = pr_ticks;
+ PRUint32 now = *(PRUint32*)iotimer_addr, temp;
+ PRUint32 residual = pr_residual, previous = pr_previous;
+
+ temp = now - previous + residual;
+ residual = temp & pr_clock_mask;
+ ticks += temp >> pr_clock_shift;
+
+ pr_previous = now;
+ pr_residual = residual;
+ pr_ticks = ticks;
+ }
+ }
+ else
+ {
+ /*
+ * No fast access. Use the time of day clock. This isn't the
+ * right answer since this clock can get set back, tick at odd
+ * rates, and it's expensive to acqurie.
+ */
+ pr_ticks = _PR_UNIX_GetInterval();
+ }
+ return pr_ticks;
+} /* _MD_IrixGetInterval */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/linux.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/linux.c
new file mode 100644
index 00000000..c22618d7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/linux.c
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifdef _PR_PTHREADS
+
+extern void _MD_unix_terminate_waitpid_daemon(void);
+
+void _MD_CleanupBeforeExit(void)
+{
+ _MD_unix_terminate_waitpid_daemon();
+}
+
+#else /* ! _PR_PTHREADS */
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ /*
+ * set the pointers to the stack-pointer and frame-pointer words in the
+ * context structure; this is for debugging use.
+ */
+ thread->md.sp = _MD_GET_SP_PTR(thread);
+ thread->md.fp = _MD_GET_FP_PTR(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Linux */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Linux.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Linux.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/ncr.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/ncr.c
new file mode 100644
index 00000000..909b09e6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/ncr.c
@@ -0,0 +1,395 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * NCR 3.0 - cloned from UnixWare by ruslan
+ */
+#include "primpl.h"
+
+#include <setjmp.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+#ifdef ALARMS_BREAK_TCP /* I don't think they do */
+
+PRInt32 _MD_connect(PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _connect(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+}
+
+PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _accept(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+ return(rv);
+}
+#endif
+
+/*
+ * These are also implemented in pratom.c using NSPR locks. Any reason
+ * this might be better or worse? If you like this better, define
+ * _PR_HAVE_ATOMIC_OPS in include/md/unixware.h
+ */
+#ifdef _PR_HAVE_ATOMIC_OPS
+/* Atomic operations */
+#include <stdio.h>
+static FILE *_uw_semf;
+
+void
+_MD_INIT_ATOMIC(void)
+{
+ /* Sigh. Sure wish SYSV semaphores weren't such a pain to use */
+ if ((_uw_semf = tmpfile()) == NULL)
+ PR_ASSERT(0);
+
+ return;
+}
+
+void
+_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+ flockfile(_uw_semf);
+ (*val)++;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ flockfile(_uw_semf);
+ (*ptr) += val;
+ unflockfile(_uw_semf);
+}
+
+
+void
+_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+ flockfile(_uw_semf);
+ (*val)--;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+{
+ flockfile(_uw_semf);
+ *val = newval;
+ unflockfile(_uw_semf);
+}
+#endif
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Unixware */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Unixware.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRUintn priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Unixware.");
+ return PR_FAILURE;
+}
+
+/*
+ This is temp. replacement for localtime_r. Normally PR_ExplodeTime should
+ be used as to my understanding
+*/
+
+/*
+** $$$$$ THEN WHY ARE WE DOING THIS? - AOF $$$$$
+*/
+
+#define NEED_LOCALTIME_R
+#define NEED_GMTIME_R
+#define NEED_ASCTIME_R
+#define NEED_STRTOK_R
+#define NEED_CTIME_R
+
+#if defined (NEED_LOCALTIME_R) || defined (NEED_CTIME_R) || defined (NEED_ASCTIME_R) || defined (NEED_GMTIME_R) || defined (NEED_STRTOK_R)
+#include "prlock.h"
+#endif
+
+#if defined (NEED_LOCALTIME_R)
+
+static PRLock *localtime_r_monitor = NULL;
+
+struct tm *localtime_r (const time_t *clock, struct tm *result)
+{
+ struct tm *tmPtr;
+ int needLock = PR_Initialized(); /* We need to use a lock to protect
+ * against NSPR threads only when the
+ * NSPR thread system is activated. */
+
+ if (needLock) {
+ if (localtime_r_monitor == NULL) {
+
+ localtime_r_monitor = PR_NewLock();
+ }
+ PR_Lock(localtime_r_monitor);
+ }
+
+ /*
+ * On Windows, localtime() returns a NULL pointer if 'clock'
+ * represents a time before midnight January 1, 1970. In
+ * that case, we also return a NULL pointer and the struct tm
+ * object pointed to by 'result' is not modified.
+ */
+
+ tmPtr = localtime(clock);
+ if (tmPtr) {
+ *result = *tmPtr;
+ } else {
+ result = NULL;
+ }
+
+ if (needLock) PR_Unlock(localtime_r_monitor);
+
+ return result;
+}
+
+#endif
+
+#if defined (NEED_GMTIME_R)
+
+static PRLock *gmtime_r_monitor = NULL;
+
+struct tm *gmtime_r (const time_t *clock, struct tm *result)
+{
+ struct tm *tmPtr;
+ int needLock = PR_Initialized(); /* We need to use a lock to protect
+ * against NSPR threads only when the
+ * NSPR thread system is activated. */
+
+ if (needLock) {
+ if (gmtime_r_monitor == NULL) {
+ gmtime_r_monitor = PR_NewLock();
+ }
+ PR_Lock(gmtime_r_monitor);
+ }
+
+ tmPtr = gmtime(clock);
+ if (tmPtr) {
+ *result = *tmPtr;
+ } else {
+ result = NULL;
+ }
+
+ if (needLock) PR_Unlock(gmtime_r_monitor);
+
+ return result;
+}
+
+#endif
+
+#if defined (NEED_CTIME_R)
+
+static PRLock *ctime_r_monitor = NULL;
+
+char *ctime_r (const time_t *clock, char *buf, int buflen)
+{
+ char *cbuf;
+ int needLock = PR_Initialized(); /* We need to use a lock to protect
+ * against NSPR threads only when the
+ * NSPR thread system is activated. */
+
+ if (needLock) {
+
+ if (ctime_r_monitor == NULL) {
+ ctime_r_monitor = PR_NewLock();
+ }
+ PR_Lock(ctime_r_monitor);
+ }
+
+ cbuf = ctime (clock);
+ if (cbuf) {
+ strncpy (buf, cbuf, buflen - 1);
+ buf[buflen - 1] = 0;
+ }
+
+ if (needLock) PR_Unlock(ctime_r_monitor);
+
+ return cbuf;
+}
+
+#endif
+
+#if defined (NEED_ASCTIME_R)
+
+static PRLock *asctime_r_monitor = NULL;
+
+
+char *asctime_r (const struct tm *tm, char *buf, int buflen)
+{
+ char *cbuf;
+ int needLock = PR_Initialized(); /* We need to use a lock to protect
+ * against NSPR threads only when the
+ * NSPR thread system is activated. */
+
+ if (needLock) {
+ if (asctime_r_monitor == NULL) {
+ asctime_r_monitor = PR_NewLock();
+ }
+ PR_Lock(asctime_r_monitor);
+ }
+
+ cbuf = asctime (tm);
+ if (cbuf) {
+ strncpy (buf, cbuf, buflen - 1);
+ buf[buflen - 1] = 0;
+ }
+
+ if (needLock) PR_Unlock(asctime_r_monitor);
+
+ return cbuf;
+
+}
+#endif
+
+#if defined (NEED_STRTOK_R)
+
+char *
+strtok_r (s, delim, last)
+ register char *s;
+ register const char *delim;
+ register char **last;
+{
+ register char *spanp;
+ register int c, sc;
+ char *tok;
+
+
+ if (s == NULL && (s = *last) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ *last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+
+ else
+ s[-1] = 0;
+ *last = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nec.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nec.c
new file mode 100644
index 00000000..8c97b757
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nec.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for NEC */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for NEC.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for NEC.");
+ return PR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/netbsd.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/netbsd.c
new file mode 100644
index 00000000..fdef8d7b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/netbsd.c
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <poll.h>
+#include <sys/syscall.h>
+
+void _MD_EarlyInit(void)
+{
+ /*
+ * Ignore FPE because coercion of a NaN to an int causes SIGFPE
+ * to be raised.
+ */
+ struct sigaction act;
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGFPE, &act, 0);
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) sigsetjmp(CONTEXT(t), 1);
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for NetBSD */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for NetBSD.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for NetBSD.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nextstep.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nextstep.c
new file mode 100644
index 00000000..3f87815a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nextstep.c
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#import <mach/mach.h>
+#import <mach/mach_error.h>
+#import <mach-o/dyld.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <syscall.h>
+
+
+
+/* These functions are hidden in NEXTSTEP, but beacuse they have syscall()
+** entries I can wrap these into their corresponding missing function.
+*/
+caddr_t
+mmap(caddr_t addr, size_t len, int prot, int flags,
+ int fildes, off_t off)
+{
+ return (caddr_t) syscall (SYS_mmap, addr, len, prot, flags, fildes, off);
+}
+
+int
+munmap(caddr_t addr, size_t len)
+{
+ return syscall (SYS_munmap, addr, len);
+}
+
+int
+mprotect(caddr_t addr, size_t len, int prot)
+{
+ return syscall (SYS_mprotect, addr, len, prot);
+}
+
+
+/* If found the brk() symbol in the sahred libraries but no syscall() entry ...
+** I don't know whether it will work ...
+int brk(void *endds)
+{
+ return syscall ();
+}
+*/
+
+void *sbrk(int incr)
+{
+ return (void *) syscall (SYS_sbrk, incr);
+}
+
+/* These are my mach based versions, untested and probably bad ...
+*/
+caddr_t my_mmap(caddr_t addr, size_t len, int prot, int flags,
+ int fildes, off_t off)
+{
+ kern_return_t ret_val;
+
+ /* First map ...
+ */
+ ret_val = map_fd ( fildes, /* fd */
+ (vm_offset_t) off, /* offset */
+ (vm_offset_t*)&addr, /* address */
+ TRUE, /* find_space */
+ (vm_size_t) len); /* size */
+
+ if (ret_val != KERN_SUCCESS) {
+ mach_error("Error calling map_fd() in mmap", ret_val );
+ return (caddr_t)0;
+ }
+
+ /* ... then protect (this is probably bad)
+ */
+ ret_val = vm_protect( task_self(), /* target_task */
+ (vm_address_t)addr, /* address */
+ (vm_size_t) len, /* size */
+ FALSE, /* set_maximum */
+ (vm_prot_t) prot); /* new_protection */
+ if (ret_val != KERN_SUCCESS) {
+ mach_error("vm_protect in mmap()", ret_val );
+ return (caddr_t)0;
+ }
+
+ return addr;
+}
+
+int my_munmap(caddr_t addr, size_t len)
+{
+ kern_return_t ret_val;
+
+ ret_val = vm_deallocate(task_self(),
+ (vm_address_t) addr,
+ (vm_size_t) len);
+
+ if (ret_val != KERN_SUCCESS) {
+ mach_error("vm_deallocate in munmap()", ret_val);
+ return -1;
+ }
+
+ return 0;
+}
+
+int my_mprotect(caddr_t addr, size_t len, int prot)
+{
+ vm_prot_t mach_prot;
+ kern_return_t ret_val;
+
+ switch (prot) {
+ case PROT_READ: mach_prot = VM_PROT_READ; break;
+ case PROT_WRITE: mach_prot = VM_PROT_WRITE; break;
+ case PROT_EXEC: mach_prot = VM_PROT_EXECUTE; break;
+ case PROT_NONE: mach_prot = VM_PROT_NONE; break;
+ }
+
+ ret_val = vm_protect(task_self(), /* target_task */
+ (vm_address_t)addr, /* address */
+ (vm_size_t) len, /* size */
+ FALSE, /* set_maximum */
+ (vm_prot_t) prot); /* new_protection */
+
+ if (ret_val != KERN_SUCCESS) {
+ mach_error("vm_protect in mprotect()", ret_val);
+ return -1;
+ }
+
+ return 0;
+}
+
+char *strdup(const char *s1)
+{
+ int len = strlen (s1);
+ char *copy = (char*) malloc (len+1);
+
+ if (copy == (char*)0)
+ return (char*)0;
+
+ strcpy (copy, s1);
+
+ return copy;
+}
+
+/* Stub rld functions
+*/
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(
+ const char *pathName,
+ NSObjectFileImage *objectFileImage)
+{
+ return NSObjectFileImageFailure;
+}
+
+extern void * NSAddressOfSymbol(
+ NSSymbol symbol)
+{
+ return NULL;
+}
+
+extern NSModule NSLinkModule(
+ NSObjectFileImage objectFileImage,
+ const char *moduleName, /* can be NULL */
+ enum bool bindNow)
+{
+ return NULL;
+}
+
+extern NSSymbol NSLookupAndBindSymbol(
+ const char *symbolName)
+{
+ return NULL;
+}
+
+extern enum bool NSUnLinkModule(
+ NSModule module,
+ enum bool keepMemoryMapped)
+{
+ return 0;
+}
+
+
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) sigsetjmp(CONTEXT(t), 1);
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for NEXTSTEP */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for NEXTSTEP.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for NEXTSTEP.");
+ return PR_FAILURE;
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nto.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nto.c
new file mode 100644
index 00000000..352d93e9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/nto.c
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <setjmp.h>
+
+/* Fake this out */
+int socketpair (int foo, int foo2, int foo3, int sv[2])
+{
+ printf("error in socketpair\n");
+ exit (-1);
+}
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/objs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/objs.mk
new file mode 100644
index 00000000..13f2d7d2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/objs.mk
@@ -0,0 +1,63 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+# This makefile appends to the variable OBJS the platform-dependent
+# object modules that will be part of the nspr20 library.
+
+CSRCS = \
+ unix.c \
+ unix_errors.c \
+ uxproces.c \
+ uxrng.c \
+ uxshm.c \
+ uxwrap.c \
+ $(NULL)
+
+ifneq ($(USE_PTHREADS),1)
+CSRCS += uxpoll.c
+endif
+
+ifeq ($(PTHREADS_USER),1)
+CSRCS += pthreads_user.c
+endif
+
+CSRCS += $(PR_MD_CSRCS)
+ASFILES += $(PR_MD_ASFILES)
+
+OBJS += $(addprefix md/unix/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
+ $(addprefix md/unix/$(OBJDIR)/,$(ASFILES:.s=.$(OBJ_SUFFIX)))
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openbsd.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openbsd.c
new file mode 100644
index 00000000..1103377f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openbsd.c
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <poll.h>
+#include <sys/syscall.h>
+
+void _MD_EarlyInit(void)
+{
+ /*
+ * Ignore FPE because coercion of a NaN to an int causes SIGFPE
+ * to be raised.
+ */
+ struct sigaction act;
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGFPE, &act, 0);
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) sigsetjmp(CONTEXT(t), 1);
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for OpenBSD */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for OpenBSD.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OpenBSD.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openvms.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openvms.c
new file mode 100644
index 00000000..20b4f708
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/openvms.c
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for OSF1 */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for OSF1.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OSF1.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include <c_asm.h>
+
+#define _PR_OSF_ATOMIC_LOCK 1
+
+void
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+long locked;
+
+ do {
+ while ((long) stack->prstk_head.prstk_elem_next ==
+ _PR_OSF_ATOMIC_LOCK)
+ ;
+ locked = __ATOMIC_EXCH_QUAD(&stack->prstk_head.prstk_elem_next,
+ _PR_OSF_ATOMIC_LOCK);
+
+ } while (locked == _PR_OSF_ATOMIC_LOCK);
+ stack_elem->prstk_elem_next = (PRStackElem *) locked;
+ /*
+ * memory-barrier instruction
+ */
+ asm("mb");
+ stack->prstk_head.prstk_elem_next = stack_elem;
+}
+
+PRStackElem *
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+long locked;
+
+ do {
+ while ((long)stack->prstk_head.prstk_elem_next == _PR_OSF_ATOMIC_LOCK)
+ ;
+ locked = __ATOMIC_EXCH_QUAD(&stack->prstk_head.prstk_elem_next,
+ _PR_OSF_ATOMIC_LOCK);
+
+ } while (locked == _PR_OSF_ATOMIC_LOCK);
+
+ element = (PRStackElem *) locked;
+
+ if (element == NULL) {
+ stack->prstk_head.prstk_elem_next = NULL;
+ } else {
+ stack->prstk_head.prstk_elem_next =
+ element->prstk_elem_next;
+ }
+ /*
+ * memory-barrier instruction
+ */
+ asm("mb");
+ return element;
+}
+#endif /* _PR_HAVE_ATOMIC_CAS */
+
+
+/*
+** thread_suspend and thread_resume are used by the gc code
+** in nsprpub/pr/src/pthreads/ptthread.c
+**
+** These routines are never called for the current thread, and
+** there is no check for that - so beware!
+*/
+int thread_suspend(PRThread *thr_id) {
+
+ extern int pthread_suspend_np (
+ pthread_t thread,
+ __pthreadLongUint_t *regs,
+ void *spare);
+
+ __pthreadLongUint_t regs[34];
+ int res;
+
+ /*
+ ** A return res < 0 indicates that the thread was suspended
+ ** but register information could not be obtained
+ */
+
+ res = pthread_suspend_np(thr_id->id,&regs[0],0);
+ if (res==0)
+ thr_id->sp = (void *) regs[30];
+
+ thr_id->suspend |= PT_THREAD_SUSPENDED;
+
+ /* Always succeeds */
+ return 0;
+}
+
+int thread_resume(PRThread *thr_id) {
+ extern int pthread_resume_np(pthread_t thread);
+ int res;
+
+ res = pthread_resume_np (thr_id->id);
+
+ thr_id->suspend |= PT_THREAD_RESUMED;
+
+ return 0;
+}
+
+/*
+** Stubs for nspr_symvec.opt
+**
+** PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended
+** (defined in ptthread.c) used to be exported by mistake
+** (because they look like public functions). They have been
+** converted into static functions.
+**
+** There is an existing third-party binary that uses NSPR: the
+** Java plugin for Mozilla. Because it is part of the Java
+** SDK, we have no control over its releases. So we need these
+** stub functions to occupy the slots that used to be occupied
+** by PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended
+** in the symbol vector so that LIBNSPR4 is backward compatible.
+**
+** The Java plugin was also using PR_CreateThread which we didn't
+** realise and hadn't "nailed down". So we now need to nail it down
+** to its Mozilla 1.1 position and have to insert 51 additional stubs
+** in order to achive this (stubs 4-54).
+**
+** Over time some of these stubs will get reused by new symbols.
+** - Stub54 is replaced by LL_MaxUint
+*/
+
+void PR_VMS_Stub1(void) { }
+void PR_VMS_Stub2(void) { }
+void PR_VMS_Stub3(void) { }
+void PR_VMS_Stub4(void) { }
+void PR_VMS_Stub5(void) { }
+void PR_VMS_Stub6(void) { }
+void PR_VMS_Stub7(void) { }
+void PR_VMS_Stub8(void) { }
+void PR_VMS_Stub9(void) { }
+void PR_VMS_Stub10(void) { }
+void PR_VMS_Stub11(void) { }
+void PR_VMS_Stub12(void) { }
+void PR_VMS_Stub13(void) { }
+void PR_VMS_Stub14(void) { }
+void PR_VMS_Stub15(void) { }
+void PR_VMS_Stub16(void) { }
+void PR_VMS_Stub17(void) { }
+void PR_VMS_Stub18(void) { }
+void PR_VMS_Stub19(void) { }
+void PR_VMS_Stub20(void) { }
+void PR_VMS_Stub21(void) { }
+void PR_VMS_Stub22(void) { }
+void PR_VMS_Stub23(void) { }
+void PR_VMS_Stub24(void) { }
+void PR_VMS_Stub25(void) { }
+void PR_VMS_Stub26(void) { }
+void PR_VMS_Stub27(void) { }
+void PR_VMS_Stub28(void) { }
+void PR_VMS_Stub29(void) { }
+void PR_VMS_Stub30(void) { }
+void PR_VMS_Stub31(void) { }
+void PR_VMS_Stub32(void) { }
+void PR_VMS_Stub33(void) { }
+void PR_VMS_Stub34(void) { }
+void PR_VMS_Stub35(void) { }
+void PR_VMS_Stub36(void) { }
+void PR_VMS_Stub37(void) { }
+void PR_VMS_Stub38(void) { }
+void PR_VMS_Stub39(void) { }
+void PR_VMS_Stub40(void) { }
+void PR_VMS_Stub41(void) { }
+void PR_VMS_Stub42(void) { }
+void PR_VMS_Stub43(void) { }
+void PR_VMS_Stub44(void) { }
+void PR_VMS_Stub45(void) { }
+void PR_VMS_Stub46(void) { }
+void PR_VMS_Stub47(void) { }
+void PR_VMS_Stub48(void) { }
+void PR_VMS_Stub49(void) { }
+void PR_VMS_Stub50(void) { }
+void PR_VMS_Stub51(void) { }
+void PR_VMS_Stub52(void) { }
+void PR_VMS_Stub53(void) { }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_AIX.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_AIX.s
new file mode 100644
index 00000000..8911a75e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_AIX.s
@@ -0,0 +1,119 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+#
+# 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998-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.
+#
+
+.set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.longjmp{TC},"longjmp"
+
+ .lglobl H.10.NO_SYMBOL{PR}
+ .globl .longjmp
+ .globl longjmp{DS}
+ .extern .sigcleanup
+ .extern .jmprestfpr
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+.longjmp:
+ mr r13,r3
+ mr r14,r4
+ stu SP,-56(SP)
+ bl .sigcleanup
+ l RTOC,0x14(SP)
+ cal SP,0x38(SP)
+ mr r3,r13
+ mr r4,r14
+ l r5,0x8(r3)
+ l SP,0xc(r3)
+ l r7,0xf8(r3)
+ st r7,0x0(SP)
+ l RTOC,0x10(r3)
+ bl .jmprestfpr
+# 1 == cr0 in disassembly
+ cmpi 1,r4,0x0
+ mtlr r5
+ lm r13,0x14(r3)
+ l r5,0x60(r3)
+ mtcrf 0x38,r5
+ mr r3,r4
+ bne __L1
+ lil r3,0x1
+__L1:
+ br
+
+# traceback table
+ .long 0x00000000
+ .byte 0x00 # VERSION=0
+ .byte 0x00 # LANG=TB_C
+ .byte 0x20 # IS_GL=0,IS_EPROL=0,HAS_TBOFF=1
+ # INT_PROC=0,HAS_CTL=0,TOCLESS=0
+ # FP_PRESENT=0,LOG_ABORT=0
+ .byte 0x40 # INT_HNDL=0,NAME_PRESENT=1
+ # USES_ALLOCA=0,CL_DIS_INV=WALK_ONCOND
+ # SAVES_CR=0,SAVES_LR=0
+ .byte 0x80 # STORES_BC=1,FPR_SAVED=0
+ .byte 0x00 # GPR_SAVED=0
+ .byte 0x02 # FIXEDPARMS=2
+ .byte 0x01 # FLOATPARMS=0,PARMSONSTK=1
+ .long 0x00000000 #
+ .long 0x00000014 # TB_OFFSET
+ .short 7 # NAME_LEN
+ .byte "longjmp"
+ .byte 0 # padding
+ .byte 0 # padding
+ .byte 0 # padding
+# End of traceback table
+ .long 0x00000000 # "\0\0\0\0"
+
+# .data section
+
+ .toc # 0x00000038
+T.18.longjmp:
+ .tc H.18.longjmp{TC},longjmp{DS}
+
+ .csect longjmp{DS}
+ .long .longjmp # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect longjmp{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_BSD_386_2.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_BSD_386_2.s
new file mode 100644
index 00000000..aadf0df2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_BSD_386_2.s
@@ -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 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 Portable Runtime (NSPR).
+*
+* The Initial Developer of the Original Code is Netscape
+* Communications Corporation. Portions created by Netscape are
+* Copyright (C) 1998-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.
+*/
+
+/*
+ * os_BSD_386_2.s
+ * We need to define our own setjmp/longjmp on BSDI 2.x because libc's
+ * implementation does some sanity checking that defeats user level threads.
+ * This should no longer be necessary in BSDI 3.0.
+ */
+
+.globl _setjmp
+.align 2
+_setjmp:
+ movl 4(%esp),%eax
+ movl 0(%esp),%edx
+ movl %edx, 0(%eax) /* rta */
+ movl %ebx, 4(%eax)
+ movl %esp, 8(%eax)
+ movl %ebp,12(%eax)
+ movl %esi,16(%eax)
+ movl %edi,20(%eax)
+ movl $0,%eax
+ ret
+
+.globl _longjmp
+.align 2
+_longjmp:
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ movl 0(%edx),%ecx
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ cmpl $0,%eax
+ jne 1f
+ movl $1,%eax
+1: movl %ecx,0(%esp)
+ ret
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_ppc.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_ppc.s
new file mode 100644
index 00000000..f38ac644
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_ppc.s
@@ -0,0 +1,92 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+#
+# 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 2003 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.
+#
+
+#
+# Based on the programming examples in The PowerPC Architecture:
+# A Specification for A New Family of RISC Processors, 2nd Ed.,
+# Book I, Section E.1, "Synchronization," pp. 249-256, May 1994.
+#
+
+.text
+
+#
+# PRInt32 __PR_DarwinPPC_AtomicIncrement(PRInt32 *val);
+#
+ .align 2
+ .globl __PR_DarwinPPC_AtomicIncrement
+__PR_DarwinPPC_AtomicIncrement:
+ lwarx r4,0,r3
+ addi r0,r4,1
+ stwcx. r0,0,r3
+ bne- __PR_DarwinPPC_AtomicIncrement
+ mr r3,r0
+ blr
+
+#
+# PRInt32 __PR_DarwinPPC_AtomicDecrement(PRInt32 *val);
+#
+ .align 2
+ .globl __PR_DarwinPPC_AtomicDecrement
+__PR_DarwinPPC_AtomicDecrement:
+ lwarx r4,0,r3
+ addi r0,r4,-1
+ stwcx. r0,0,r3
+ bne- __PR_DarwinPPC_AtomicDecrement
+ mr r3,r0
+ blr
+
+#
+# PRInt32 __PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval);
+#
+ .align 2
+ .globl __PR_DarwinPPC_AtomicSet
+__PR_DarwinPPC_AtomicSet:
+ lwarx r5,0,r3
+ stwcx. r4,0,r3
+ bne- __PR_DarwinPPC_AtomicSet
+ mr r3,r5
+ blr
+
+#
+# PRInt32 __PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#
+ .align 2
+ .globl __PR_DarwinPPC_AtomicAdd
+__PR_DarwinPPC_AtomicAdd:
+ lwarx r5,0,r3
+ add r0,r4,r5
+ stwcx. r0,0,r3
+ bne- __PR_DarwinPPC_AtomicAdd
+ mr r3,r0
+ blr
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_x86.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_x86.s
new file mode 100644
index 00000000..276b16e0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Darwin_x86.s
@@ -0,0 +1,109 @@
+# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2003
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Josh Aas <josh@mozilla.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 *****
+
+#
+# Based on os_Linux_x86.s
+#
+
+#
+# PRInt32 __PR_Darwin_x86_AtomicIncrement(PRInt32 *val);
+#
+# Atomically increment the integer pointed to by 'val' and return
+# the result of the increment.
+#
+ .text
+ .globl __PR_Darwin_x86_AtomicIncrement
+ .align 4
+__PR_Darwin_x86_AtomicIncrement:
+ movl 4(%esp), %ecx
+ movl $1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ incl %eax
+ ret
+
+#
+# PRInt32 __PR_Darwin_x86_AtomicDecrement(PRInt32 *val);
+#
+# Atomically decrement the integer pointed to by 'val' and return
+# the result of the decrement.
+#
+ .text
+ .globl __PR_Darwin_x86_AtomicDecrement
+ .align 4
+__PR_Darwin_x86_AtomicDecrement:
+ movl 4(%esp), %ecx
+ movl $-1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ decl %eax
+ ret
+
+#
+# PRInt32 __PR_Darwin_x86_AtomicSet(PRInt32 *val, PRInt32 newval);
+#
+# Atomically set the integer pointed to by 'val' to the new
+# value 'newval' and return the old value.
+#
+ .text
+ .globl __PR_Darwin_x86_AtomicSet
+ .align 4
+__PR_Darwin_x86_AtomicSet:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ xchgl %eax, (%ecx)
+ ret
+
+#
+# PRInt32 __PR_Darwin_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val);
+#
+# Atomically add 'val' to the integer pointed to by 'ptr'
+# and return the result of the addition.
+#
+ .text
+ .globl __PR_Darwin_x86_AtomicAdd
+ .align 4
+__PR_Darwin_x86_AtomicAdd:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ movl %eax, %edx
+ lock
+ xaddl %eax, (%ecx)
+ addl %edx, %eax
+ ret
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_HPUX.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_HPUX.s
new file mode 100644
index 00000000..375cb256
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_HPUX.s
@@ -0,0 +1,54 @@
+;
+; 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 Portable Runtime (NSPR).
+;
+; The Initial Developer of the Original Code is Netscape
+; Communications Corporation. Portions created by Netscape are
+; Copyright (C) 1998-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.
+;
+
+#ifdef __LP64__
+ .LEVEL 2.0W
+#else
+ .LEVEL 1.1
+#endif
+
+ .CODE ; equivalent to the following two lines
+; .SPACE $TEXT$,SORT=8
+; .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+
+ret_cr16
+ .PROC
+ .CALLINFO FRAME=0, NO_CALLS
+ .EXPORT ret_cr16,ENTRY
+ .ENTER
+; BV %r0(%rp)
+ BV 0(%rp)
+ MFCTL %cr16,%ret0
+ .LEAVE
+ .PROCEND
+ .END
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Irix.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Irix.s
new file mode 100644
index 00000000..7a4b186f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Irix.s
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+* 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 Portable Runtime (NSPR).
+*
+* The Initial Developer of the Original Code is Netscape
+* Communications Corporation. Portions created by Netscape are
+* Copyright (C) 1998-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.
+*/
+
+/*
+ * Atomically add a new element to the top of the stack
+ *
+ * usage : PR_StackPush(listp, elementp);
+ * -----------------------
+ */
+
+#include "md/_irix.h"
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#include <sys/asm.h>
+#include <sys/regdef.h>
+
+LEAF(PR_StackPush)
+
+retry_push:
+.set noreorder
+ lw v0,0(a0)
+ li t1,1
+ beq v0,t1,retry_push
+ move t0,a1
+
+ ll v0,0(a0)
+ beq v0,t1,retry_push
+ nop
+ sc t1,0(a0)
+ beq t1,0,retry_push
+ nop
+ sw v0,0(a1)
+ sync
+ sw t0,0(a0)
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ jr ra
+ nop
+
+END(PR_StackPush)
+
+/*
+ *
+ * Atomically remove the element at the top of the stack
+ *
+ * usage : elemep = PR_StackPop(listp);
+ *
+ */
+
+LEAF(PR_StackPop)
+retry_pop:
+.set noreorder
+
+
+ lw v0,0(a0)
+ li t1,1
+ beq v0,0,done
+ nop
+ beq v0,t1,retry_pop
+ nop
+
+ ll v0,0(a0)
+ beq v0,0,done
+ nop
+ beq v0,t1,retry_pop
+ nop
+ sc t1,0(a0)
+ beq t1,0,retry_pop
+ nop
+ lw t0,0(v0)
+ sw t0,0(a0)
+done:
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ jr ra
+ nop
+
+END(PR_StackPop)
+
+#endif /* _PR_HAVE_ATOMIC_CAS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_ia64.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_ia64.s
new file mode 100644
index 00000000..bf5b03fc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_ia64.s
@@ -0,0 +1,80 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+//
+// 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 Portable Runtime (NSPR).
+//
+// 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.
+//
+
+.text
+ .align 16
+ .global _PR_ia64_AtomicIncrement#
+ .proc _PR_ia64_AtomicIncrement#
+_PR_ia64_AtomicIncrement:
+ fetchadd4.acq r8 = [r32], 1
+ ;;
+ adds r8 = 1, r8
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicIncrement#
+//
+ .align 16
+ .global _PR_ia64_AtomicDecrement#
+ .proc _PR_ia64_AtomicDecrement#
+_PR_ia64_AtomicDecrement:
+ fetchadd4.rel r8 = [r32], -1
+ ;;
+ adds r8 = -1, r8
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicDecrement#
+//
+ .align 16
+ .global _PR_ia64_AtomicAdd#
+ .proc _PR_ia64_AtomicAdd#
+_PR_ia64_AtomicAdd:
+ ld4 r15 = [r32]
+ ;;
+.L3:
+ mov r14 = r15
+ mov ar.ccv = r15
+ add r8 = r15, r33
+ ;;
+ cmpxchg4.acq r15 = [r32], r8, ar.ccv
+ ;;
+ cmp4.ne p6, p7 = r15, r14
+ (p6) br.cond.dptk .L3
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicAdd#
+//
+ .align 16
+ .global _PR_ia64_AtomicSet#
+ .proc _PR_ia64_AtomicSet#
+_PR_ia64_AtomicSet:
+ xchg4 r8 = [r32], r33
+ br.ret.sptk.many b0
+ .endp _PR_ia64_AtomicSet#
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86.s
new file mode 100644
index 00000000..d691badd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86.s
@@ -0,0 +1,114 @@
+/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/
+/ 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 Portable Runtime (NSPR).
+/
+/ 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.
+/
+
+/ PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val)
+/
+/ Atomically increment the integer pointed to by 'val' and return
+/ the result of the increment.
+/
+ .text
+ .globl _PR_x86_AtomicIncrement
+ .align 4
+_PR_x86_AtomicIncrement:
+ movl 4(%esp), %ecx
+ movl $1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ incl %eax
+ ret
+
+/ PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val)
+/
+/ Atomically decrement the integer pointed to by 'val' and return
+/ the result of the decrement.
+/
+ .text
+ .globl _PR_x86_AtomicDecrement
+ .align 4
+_PR_x86_AtomicDecrement:
+ movl 4(%esp), %ecx
+ movl $-1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ decl %eax
+ ret
+
+/ PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval)
+/
+/ Atomically set the integer pointed to by 'val' to the new
+/ value 'newval' and return the old value.
+/
+/ An alternative implementation:
+/ .text
+/ .globl _PR_x86_AtomicSet
+/ .align 4
+/_PR_x86_AtomicSet:
+/ movl 4(%esp), %ecx
+/ movl 8(%esp), %edx
+/ movl (%ecx), %eax
+/retry:
+/ lock
+/ cmpxchgl %edx, (%ecx)
+/ jne retry
+/ ret
+/
+ .text
+ .globl _PR_x86_AtomicSet
+ .align 4
+_PR_x86_AtomicSet:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ lock
+ xchgl %eax, (%ecx)
+ ret
+
+/ PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+/
+/ Atomically add 'val' to the integer pointed to by 'ptr'
+/ and return the result of the addition.
+/
+ .text
+ .globl _PR_x86_AtomicAdd
+ .align 4
+_PR_x86_AtomicAdd:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ movl %eax, %edx
+ lock
+ xaddl %eax, (%ecx)
+ addl %edx, %eax
+ ret
+
+/ Magic indicating no need for an executable stack
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86_64.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86_64.s
new file mode 100644
index 00000000..567ae12d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_Linux_x86_64.s
@@ -0,0 +1,95 @@
+/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/
+/ 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 Portable Runtime (NSPR).
+/
+/ The Initial Developer of the Original Code is Netscape
+/ Communications Corporation. Portions created by Netscape are
+/ Copyright (C) 2004 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.
+/
+
+/ PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val)
+/
+/ Atomically increment the integer pointed to by 'val' and return
+/ the result of the increment.
+/
+ .text
+ .globl _PR_x86_64_AtomicIncrement
+ .align 4
+_PR_x86_64_AtomicIncrement:
+ movl $1, %eax
+ lock
+ xaddl %eax, (%rdi)
+ incl %eax
+ ret
+
+/ PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val)
+/
+/ Atomically decrement the integer pointed to by 'val' and return
+/ the result of the decrement.
+/
+ .text
+ .globl _PR_x86_64_AtomicDecrement
+ .align 4
+_PR_x86_64_AtomicDecrement:
+ movl $-1, %eax
+ lock
+ xaddl %eax, (%rdi)
+ decl %eax
+ ret
+
+/ PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval)
+/
+/ Atomically set the integer pointed to by 'val' to the new
+/ value 'newval' and return the old value.
+/
+ .text
+ .globl _PR_x86_64_AtomicSet
+ .align 4
+_PR_x86_64_AtomicSet:
+ movl %esi, %eax
+ lock
+ xchgl %eax, (%rdi)
+ ret
+
+/ PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+/
+/ Atomically add 'val' to the integer pointed to by 'ptr'
+/ and return the result of the addition.
+/
+ .text
+ .globl _PR_x86_64_AtomicAdd
+ .align 4
+_PR_x86_64_AtomicAdd:
+ movl %esi, %eax
+ lock
+ xaddl %eax, (%rdi)
+ addl %esi, %eax
+ ret
+
+/ Magic indicating no need for an executable stack
+.section .note.GNU-stack, "", @progbits ; .previous
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_ReliantUNIX.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_ReliantUNIX.s
new file mode 100644
index 00000000..769160bf
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_ReliantUNIX.s
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+* 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 Portable Runtime (NSPR).
+*
+* The Initial Developer of the Original Code is Netscape
+* Communications Corporation. Portions created by Netscape are
+* Copyright (C) 1998-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.
+*/
+
+/* We want position independent code */
+#define PIC
+
+#include <sys/asm.h>
+#include <sys/regdef.h>
+#include <sys/syscall.h>
+
+ .file 1 "os_ReliantUNIX.s"
+ .option pic2
+ .text
+
+ .align 2
+ .globl getcxt
+ .ent getcxt
+getcxt:
+ .frame sp,0,$31 # vars= 0, regs= 0/0, args= 0, extra= 0
+ # saved integer regs
+ sw ra,180(a0) # gpregs[CXT_EPC]
+ sw gp,152(a0) # gpregs[CXT_GP]
+ sw sp,156(a0) # gpregs[CXT_SP]
+ sw s8,160(a0) # gpregs[CXT_S8]
+ sw s0,104(a0) # gpregs[CXT_S0]
+ sw s1,108(a0) # gpregs[CXT_S1]
+ sw s2,112(a0) # gpregs[CXT_S2]
+ sw s3,116(a0) # gpregs[CXT_S3]
+ sw s4,120(a0) # gpregs[CXT_S4]
+ sw s5,124(a0) # gpregs[CXT_S5]
+ sw s6,128(a0) # gpregs[CXT_S6]
+ sw s7,132(a0) # gpregs[CXT_S7]
+ # csr
+ cfc1 v0,$31
+ # saved float regs
+ s.d $f20,264(a0) # fpregs.fp_r.fp_dregs[10]
+ s.d $f22,272(a0) # fpregs.fp_r.fp_dregs[11]
+ s.d $f24,280(a0) # fpregs.fp_r.fp_dregs[12]
+ s.d $f26,288(a0) # fpregs.fp_r.fp_dregs[13]
+ s.d $f28,296(a0) # fpregs.fp_r.fp_dregs[14]
+ s.d $f30,304(a0) # fpregs.fp_r.fp_dregs[15]
+ sw v0,312(a0) # fpregs.fp_csr
+
+ # give no illusions about the contents
+ li v0,0x0c # UC_CPU | UC_MAU
+ sw v0,0(a0) # uc_flags
+
+ move v0,zero
+ j ra
+ .end getcxt
+
+ .align 2
+ .globl setcxt
+ .ent setcxt
+setcxt:
+ .frame sp,0,$31 # vars= 0, regs= 0/0, args= 0, extra= 0
+ lw v0,312(a0) # fpregs.fp_csr
+ li v1,0xfffc0fff # mask out exception cause bits
+ and v0,v0,v1
+ # saved integer regs
+ lw t9,180(a0) # gpregs[CXT_EPC]
+ lw ra,180(a0) # gpregs[CXT_EPC]
+ lw gp,152(a0) # gpregs[CXT_GP]
+ lw sp,156(a0) # gpregs[CXT_SP]
+ ctc1 v0,$31 # fp_csr
+ lw s8,160(a0) # gpregs[CXT_S8]
+ lw s0,104(a0) # gpregs[CXT_S0]
+ lw s1,108(a0) # gpregs[CXT_S1]
+ lw s2,112(a0) # gpregs[CXT_S2]
+ lw s3,116(a0) # gpregs[CXT_S3]
+ lw s4,120(a0) # gpregs[CXT_S4]
+ lw s5,124(a0) # gpregs[CXT_S5]
+ lw s6,128(a0) # gpregs[CXT_S6]
+ lw s7,132(a0) # gpregs[CXT_S7]
+ # saved float regs
+ l.d $f20,264(a0) # fpregs.fp_r.fp_dregs[10]
+ l.d $f22,272(a0) # fpregs.fp_r.fp_dregs[11]
+ l.d $f24,280(a0) # fpregs.fp_r.fp_dregs[12]
+ l.d $f26,288(a0) # fpregs.fp_r.fp_dregs[13]
+ l.d $f28,296(a0) # fpregs.fp_r.fp_dregs[14]
+ l.d $f30,304(a0) # fpregs.fp_r.fp_dregs[15]
+
+ # load these, too
+ # they were not saved, but maybe the user modified them...
+ lw v0,48(a0)
+ lw v1,52(a0)
+ lw a1,60(a0)
+ lw a2,64(a0)
+ lw a3,68(a0)
+ lw a0,56(a0) # there is no way back
+
+ j ra
+
+ .end setcxt
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS.s
new file mode 100644
index 00000000..49306862
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS.s
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+* 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 Portable Runtime (NSPR).
+*
+* The Initial Developer of the Original Code is Netscape
+* Communications Corporation. Portions created by Netscape are
+* Copyright (C) 1998-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.
+*/
+
+ .text
+
+/*
+ * sol_getsp()
+ *
+ * Return the current sp (for debugging)
+ */
+ .global sol_getsp
+sol_getsp:
+ retl
+ mov %sp, %o0
+
+
+/*
+ * sol_curthread()
+ *
+ * Return a unique identifier for the currently active thread.
+ */
+ .global sol_curthread
+sol_curthread:
+ retl
+ mov %g7, %o0
+
+
+ .global __MD_FlushRegisterWindows
+ .global _MD_FlushRegisterWindows
+
+__MD_FlushRegisterWindows:
+_MD_FlushRegisterWindows:
+
+ ta 3
+ ret
+ restore
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_32.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_32.s
new file mode 100644
index 00000000..dd8bdd4b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_32.s
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+* 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 Portable Runtime (NSPR).
+*
+* The Initial Developer of the Original Code is Netscape
+* Communications Corporation. Portions created by Netscape are
+* Copyright (C) 1998-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.
+*/
+
+! ======================================================================
+!
+! Atomically add a new element to the top of the stack
+!
+! usage : PR_StackPush(listp, elementp);
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the stack
+! %o1 [input] - the address of the element to be added to the stack
+! -----------------------
+
+ .section ".text"
+ .global PR_StackPush
+
+PR_StackPush:
+
+pulock: ld [%o0],%o3 !
+ cmp %o3,-1 ! check if stack is locked
+ be pulock ! loop, if locked
+ mov -1,%o3 ! use delay-slot
+ swap [%o0],%o3 ! atomically lock the stack and get
+ ! the pointer to stack head
+ cmp %o3,-1 ! check, if the stack is locked
+ be pulock ! loop, if so
+ nop
+ st %o3,[%o1]
+ retl ! return back to the caller
+ st %o1,[%o0] !
+
+ .size PR_StackPush,(.-PR_StackPush)
+
+
+! end
+! ======================================================================
+
+! ======================================================================
+!
+! Atomically remove the element at the top of the stack
+!
+! usage : elemep = PR_StackPop(listp);
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the stack
+! %o1 [input] - work register (top element)
+! -----------------------
+
+ .section ".text"
+ .global PR_StackPop
+
+PR_StackPop:
+
+polock: ld [%o0],%o1 !
+ cmp %o1,-1 ! check if stack is locked
+ be polock ! loop, if locked
+ mov -1,%o1 ! use delay-slot
+ swap [%o0],%o1 ! atomically lock the stack and get
+ ! the pointer to stack head
+ cmp %o1,-1 ! check, if the stack is locked
+ be polock ! loop, if so
+ nop
+ tst %o1 ! test for empty stack
+ be,a empty ! is empty
+ st %g0,[%o0]
+ ld [%o1], %o2 ! load the second element
+ st %o2,[%o0] ! set stack head to second
+ st %g0,[%o1] ! reset the next pointer; for
+ ! debugging
+empty:
+ retl ! return back to the caller
+ mov %o1, %o0 ! return the first element
+
+ .size PR_StackPop,(.-PR_StackPop)
+
+! end
+! ======================================================================
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_sparcv9.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_sparcv9.s
new file mode 100644
index 00000000..a4bb3b79
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_sparcv9.s
@@ -0,0 +1,201 @@
+! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+!
+! 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 Portable Runtime (NSPR).
+!
+! The Initial Developer of the Original Code is Netscape
+! Communications Corporation. Portions created by Netscape are
+! Copyright (C) 1998-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.
+!
+
+!
+! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc)
+! using CAS (compare-and-swap) atomic instructions
+!
+! this MUST be compiled with an ultrasparc-aware assembler
+!
+! standard asm linkage macros; this module must be compiled
+! with the -P option (use C preprocessor)
+
+#include <sys/asm_linkage.h>
+
+! ======================================================================
+!
+! Perform the sequence a = a + 1 atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : val = PR_AtomicIncrement(address)
+! return: current value (you'd think this would be old val)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [local] - work register
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(_MD_AtomicIncrement) ! standard assembler/ELF prologue
+
+retryAI:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, 0x1, %o3 ! calc the new value
+ mov %o3, %o1 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAI ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o1, %o0 ! set the return code to the new value
+
+ SET_SIZE(_MD_AtomicIncrement) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = a - 1 atomically with respect to other
+! fetch-and-decs to location a in a wait-free fashion.
+!
+! usage : val = PR_AtomicDecrement(address)
+! return: current value (you'd think this would be old val)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [local] - work register
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(_MD_AtomicDecrement) ! standard assembler/ELF prologue
+
+retryAD:
+ ld [%o0], %o2 ! set o2 to the current value
+ sub %o2, 0x1, %o3 ! calc the new value
+ mov %o3, %o1 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAD ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o1, %o0 ! set the return code to the new value
+
+ SET_SIZE(_MD_AtomicDecrement) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = b atomically with respect to other
+! fetch-and-stores to location a in a wait-free fashion.
+!
+! usage : old_val = PR_AtomicSet(address, newval)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [input] - the new value to set for [%o0]
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(_MD_AtomicSet) ! standard assembler/ELF prologue
+
+retryAS:
+ ld [%o0], %o2 ! set o2 to the current value
+ mov %o1, %o3 ! set up the new value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAS ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o3, %o0 ! set the return code to the prev value
+
+ SET_SIZE(_MD_AtomicSet) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = a + b atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : newval = PR_AtomicAdd(address, val)
+! return: the value after addition
+!
+ ENTRY(_MD_AtomicAdd) ! standard assembler/ELF prologue
+
+retryAA:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, %o1, %o3 ! calc the new value
+ mov %o3, %o4 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAA ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o4, %o0 ! set the return code to the new value
+
+ SET_SIZE(_MD_AtomicAdd) ! standard assembler/ELF epilogue
+
+!
+! end
+!
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_ultrasparc.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_ultrasparc.s
new file mode 100644
index 00000000..03776f5b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_ultrasparc.s
@@ -0,0 +1,201 @@
+! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+!
+! 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 Portable Runtime (NSPR).
+!
+! The Initial Developer of the Original Code is Netscape
+! Communications Corporation. Portions created by Netscape are
+! Copyright (C) 1998-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.
+!
+
+!
+! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc)
+! using CAS (compare-and-swap) atomic instructions
+!
+! this MUST be compiled with an ultrasparc-aware assembler
+!
+! standard asm linkage macros; this module must be compiled
+! with the -P option (use C preprocessor)
+
+#include <sys/asm_linkage.h>
+
+! ======================================================================
+!
+! Perform the sequence a = a + 1 atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : val = PR_AtomicIncrement(address)
+! return: current value (you'd think this would be old val)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [local] - work register
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(PR_AtomicIncrement) ! standard assembler/ELF prologue
+
+retryAI:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, 0x1, %o3 ! calc the new value
+ mov %o3, %o1 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAI ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o1, %o0 ! set the return code to the new value
+
+ SET_SIZE(PR_AtomicIncrement) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = a - 1 atomically with respect to other
+! fetch-and-decs to location a in a wait-free fashion.
+!
+! usage : val = PR_AtomicDecrement(address)
+! return: current value (you'd think this would be old val)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [local] - work register
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(PR_AtomicDecrement) ! standard assembler/ELF prologue
+
+retryAD:
+ ld [%o0], %o2 ! set o2 to the current value
+ sub %o2, 0x1, %o3 ! calc the new value
+ mov %o3, %o1 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAD ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o1, %o0 ! set the return code to the new value
+
+ SET_SIZE(PR_AtomicDecrement) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = b atomically with respect to other
+! fetch-and-stores to location a in a wait-free fashion.
+!
+! usage : old_val = PR_AtomicSet(address, newval)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller's stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [input] - the new value to set for [%o0]
+! %o2 [local] - work register
+! %o3 [local] - work register
+! -----------------------
+
+ ENTRY(PR_AtomicSet) ! standard assembler/ELF prologue
+
+retryAS:
+ ld [%o0], %o2 ! set o2 to the current value
+ mov %o1, %o3 ! set up the new value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAS ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o3, %o0 ! set the return code to the prev value
+
+ SET_SIZE(PR_AtomicSet) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+
+! ======================================================================
+!
+! Perform the sequence a = a + b atomically with respect to other
+! fetch-and-adds to location a in a wait-free fashion.
+!
+! usage : newval = PR_AtomicAdd(address, val)
+! return: the value after addition
+!
+ ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue
+
+retryAA:
+ ld [%o0], %o2 ! set o2 to the current value
+ add %o2, %o1, %o3 ! calc the new value
+ mov %o3, %o4 ! save the return value
+ cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
+ cmp %o2, %o3 ! see if we set the value
+ bne retryAA ! if not, try again
+ nop ! empty out the branch pipeline
+ retl ! return back to the caller
+ mov %o4, %o0 ! set the return code to the new value
+
+ SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue
+
+!
+! end
+!
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86.s
new file mode 100644
index 00000000..a64c4d5a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86.s
@@ -0,0 +1,249 @@
+/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/
+/ 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 Portable Runtime (NSPR).
+/
+/ The Initial Developer of the Original Code is Netscape
+/ Communications Corporation. Portions created by Netscape are
+/ Copyright (C) 1998-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.
+/
+
+ .text
+
+ .globl getedi
+getedi:
+ movl %edi,%eax
+ ret
+ .type getedi,@function
+ .size getedi,.-getedi
+
+ .globl setedi
+setedi:
+ movl 4(%esp),%edi
+ ret
+ .type setedi,@function
+ .size setedi,.-setedi
+
+ .globl __MD_FlushRegisterWindows
+ .globl _MD_FlushRegisterWindows
+
+__MD_FlushRegisterWindows:
+_MD_FlushRegisterWindows:
+
+ ret
+
+/
+/ sol_getsp()
+/
+/ Return the current sp (for debugging)
+/
+ .globl sol_getsp
+sol_getsp:
+ movl %esp, %eax
+ ret
+
+/
+/ sol_curthread()
+/
+/ Return a unique identifier for the currently active thread.
+/
+ .globl sol_curthread
+sol_curthread:
+ movl %ecx, %eax
+ ret
+
+/ PRInt32 _MD_AtomicIncrement(PRInt32 *val)
+/
+/ Atomically increment the integer pointed to by 'val' and return
+/ the result of the increment.
+/
+ .text
+ .globl _MD_AtomicIncrement
+ .align 4
+_MD_AtomicIncrement:
+ movl 4(%esp), %ecx
+ movl $1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ incl %eax
+ ret
+
+/ PRInt32 _MD_AtomicDecrement(PRInt32 *val)
+/
+/ Atomically decrement the integer pointed to by 'val' and return
+/ the result of the decrement.
+/
+ .text
+ .globl _MD_AtomicDecrement
+ .align 4
+_MD_AtomicDecrement:
+ movl 4(%esp), %ecx
+ movl $-1, %eax
+ lock
+ xaddl %eax, (%ecx)
+ decl %eax
+ ret
+
+/ PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
+/
+/ Atomically set the integer pointed to by 'val' to the new
+/ value 'newval' and return the old value.
+/
+/ An alternative implementation:
+/ .text
+/ .globl _MD_AtomicSet
+/ .align 4
+/_MD_AtomicSet:
+/ movl 4(%esp), %ecx
+/ movl 8(%esp), %edx
+/ movl (%ecx), %eax
+/retry:
+/ lock
+/ cmpxchgl %edx, (%ecx)
+/ jne retry
+/ ret
+/
+ .text
+ .globl _MD_AtomicSet
+ .align 4
+_MD_AtomicSet:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ lock
+ xchgl %eax, (%ecx)
+ ret
+
+/ PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+/
+/ Atomically add 'val' to the integer pointed to by 'ptr'
+/ and return the result of the addition.
+/
+ .text
+ .globl _MD_AtomicAdd
+ .align 4
+_MD_AtomicAdd:
+ movl 4(%esp), %ecx
+ movl 8(%esp), %eax
+ movl %eax, %edx
+ lock
+ xaddl %eax, (%ecx)
+ addl %edx, %eax
+ ret
+
+/
+/ PR_StackPush(listp, elementp)
+/
+/ Atomically push ElementP onto linked list ListP.
+/
+ .text
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ .globl VBoxNsprPR_StackPush
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ .globl PR_StackPush
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ .align 4
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+VBoxNsprPR_StackPush:
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PR_StackPush:
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ movl 4(%esp), %ecx
+ movl $-1,%eax
+pulock:
+/ Already locked?
+ cmpl %eax,(%ecx)
+ je pulock
+
+/ Attempt to lock it
+ lock
+ xchgl %eax, (%ecx)
+
+/ Did we set the lock?
+ cmpl $-1, %eax
+ je pulock
+
+/ We now have the lock. Update pointers
+ movl 8(%esp), %edx
+ movl %eax, (%edx)
+ movl %edx, (%ecx)
+
+/ Done
+ ret
+
+
+/
+/ elementp = PR_StackPop(listp)
+/
+/ Atomically pop ElementP off linked list ListP
+/
+ .text
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ .globl VBoxNsprPR_StackPop
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ .globl PR_StackPop
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ .align 4
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+VBoxNsprPR_StackPop:
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PR_StackPop:
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ movl 4(%esp), %ecx
+ movl $-1, %eax
+polock:
+/ Already locked?
+ cmpl %eax, (%ecx)
+ je polock
+
+/ Attempt to lock it
+ lock
+ xchgl %eax, (%ecx)
+
+/ Did we set the lock?
+ cmpl $-1, %eax
+ je polock
+
+/ We set the lock so now update pointers
+
+/ Was it empty?
+ movl $0, %edx
+ cmpl %eax,%edx
+ je empty
+
+/ Get element "next" pointer
+ movl (%eax), %edx
+
+/ Write NULL to the element "next" pointer
+ movl $0, (%eax)
+
+empty:
+/ Put elements previous "next" value into listp
+/ NOTE: This also unlocks the listp
+ movl %edx, (%ecx)
+
+/ Return previous listp value (already in eax)
+ ret
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86_64.s b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86_64.s
new file mode 100644
index 00000000..3c5ac393
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/os_SunOS_x86_64.s
@@ -0,0 +1,95 @@
+/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/
+/ ***** BEGIN LICENSE BLOCK *****
+/ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+/
+/ The contents of this file are subject to the Mozilla Public License Version
+/ 1.1 (the "License"); you may not use this file except in compliance with
+/ the License. You may obtain a copy of the License at
+/ http://www.mozilla.org/MPL/
+/
+/ Software distributed under the License is distributed on an "AS IS" basis,
+/ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+/ for the specific language governing rights and limitations under the
+/ License.
+/
+/ The Original Code is the Netscape Portable Runtime (NSPR).
+/
+/ The Initial Developer of the Original Code is
+/ Netscape Communications Corporation.
+/ Portions created by the Initial Developer are Copyright (C) 2004
+/ 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 *****
+
+/ PRInt32 _MD_AtomicIncrement(PRInt32 *val)
+/
+/ Atomically increment the integer pointed to by 'val' and return
+/ the result of the increment.
+/
+ .text
+ .globl _MD_AtomicIncrement
+ .align 4
+_MD_AtomicIncrement:
+ movl $1, %eax
+ lock
+ xaddl %eax, (%rdi)
+ incl %eax
+ ret
+
+/ PRInt32 _MD_AtomicDecrement(PRInt32 *val)
+/
+/ Atomically decrement the integer pointed to by 'val' and return
+/ the result of the decrement.
+/
+ .text
+ .globl _MD_AtomicDecrement
+ .align 4
+_MD_AtomicDecrement:
+ movl $-1, %eax
+ lock
+ xaddl %eax, (%rdi)
+ decl %eax
+ ret
+
+/ PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval)
+/
+/ Atomically set the integer pointed to by 'val' to the new
+/ value 'newval' and return the old value.
+/
+ .text
+ .globl _MD_AtomicSet
+ .align 4
+_MD_AtomicSet:
+ movl %esi, %eax
+ xchgl %eax, (%rdi)
+ ret
+
+/ PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+/
+/ Atomically add 'val' to the integer pointed to by 'ptr'
+/ and return the result of the addition.
+/
+ .text
+ .globl _MD_AtomicAdd
+ .align 4
+_MD_AtomicAdd:
+ movl %esi, %eax
+ lock
+ xaddl %eax, (%rdi)
+ addl %esi, %eax
+ ret
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/osf1.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/osf1.c
new file mode 100644
index 00000000..a4cd6a51
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/osf1.c
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for OSF1 */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for OSF1.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OSF1.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/pthreads_user.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/pthreads_user.c
new file mode 100644
index 00000000..21e5f0b8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/pthreads_user.c
@@ -0,0 +1,480 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+
+
+sigset_t ints_off;
+pthread_mutex_t _pr_heapLock;
+pthread_key_t current_thread_key;
+pthread_key_t current_cpu_key;
+pthread_key_t last_thread_key;
+pthread_key_t intsoff_key;
+
+
+PRInt32 _pr_md_pthreads_created, _pr_md_pthreads_failed;
+PRInt32 _pr_md_pthreads = 1;
+
+void _MD_EarlyInit(void)
+{
+extern PRInt32 _nspr_noclock;
+
+ if (pthread_key_create(&current_thread_key, NULL) != 0) {
+ perror("pthread_key_create failed");
+ exit(1);
+ }
+ if (pthread_key_create(&current_cpu_key, NULL) != 0) {
+ perror("pthread_key_create failed");
+ exit(1);
+ }
+ if (pthread_key_create(&last_thread_key, NULL) != 0) {
+ perror("pthread_key_create failed");
+ exit(1);
+ }
+ if (pthread_key_create(&intsoff_key, NULL) != 0) {
+ perror("pthread_key_create failed");
+ exit(1);
+ }
+
+ sigemptyset(&ints_off);
+ sigaddset(&ints_off, SIGALRM);
+ sigaddset(&ints_off, SIGIO);
+ sigaddset(&ints_off, SIGCLD);
+
+ /*
+ * disable clock interrupts
+ */
+ _nspr_noclock = 1;
+
+}
+
+void _MD_InitLocks()
+{
+ if (pthread_mutex_init(&_pr_heapLock, NULL) != 0) {
+ perror("pthread_mutex_init failed");
+ exit(1);
+ }
+}
+
+PR_IMPLEMENT(void) _MD_FREE_LOCK(struct _MDLock *lockp)
+{
+ PRIntn _is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(_is);
+ pthread_mutex_destroy(&lockp->mutex);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(_is);
+}
+
+
+
+PR_IMPLEMENT(PRStatus) _MD_NEW_LOCK(struct _MDLock *lockp)
+{
+ PRStatus rv;
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ rv = pthread_mutex_init(&lockp->mutex, NULL);
+ if (me && !_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
+}
+
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+PR_IMPLEMENT(void)
+_MD_SetPriority(_MDThread *thread, PRThreadPriority newPri)
+{
+ /*
+ * XXX - to be implemented
+ */
+ return;
+}
+
+PR_IMPLEMENT(PRStatus) _MD_InitThread(struct PRThread *thread)
+{
+ struct sigaction sigact;
+
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ thread->md.pthread = pthread_self();
+#if 0
+ /*
+ * set up SIGUSR1 handler; this is used to save state
+ * during PR_SuspendAll
+ */
+ sigact.sa_handler = save_context_and_block;
+ sigact.sa_flags = SA_RESTART;
+ /*
+ * Must mask clock interrupts
+ */
+ sigact.sa_mask = timer_set;
+ sigaction(SIGUSR1, &sigact, 0);
+#endif
+ }
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(void) _MD_ExitThread(struct PRThread *thread)
+{
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ _MD_CLEAN_THREAD(thread);
+ _MD_SET_CURRENT_THREAD(NULL);
+ }
+}
+
+PR_IMPLEMENT(void) _MD_CleanThread(struct PRThread *thread)
+{
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ pthread_mutex_destroy(&thread->md.pthread_mutex);
+ pthread_cond_destroy(&thread->md.pthread_cond);
+ }
+}
+
+PR_IMPLEMENT(void) _MD_SuspendThread(struct PRThread *thread)
+{
+ PRInt32 rv;
+
+ PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
+ _PR_IS_GCABLE_THREAD(thread));
+#if 0
+ thread->md.suspending_id = getpid();
+ rv = kill(thread->md.id, SIGUSR1);
+ PR_ASSERT(rv == 0);
+ /*
+ * now, block the current thread/cpu until woken up by the suspended
+ * thread from it's SIGUSR1 signal handler
+ */
+ blockproc(getpid());
+#endif
+}
+
+PR_IMPLEMENT(void) _MD_ResumeThread(struct PRThread *thread)
+{
+ PRInt32 rv;
+
+ PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) &&
+ _PR_IS_GCABLE_THREAD(thread));
+#if 0
+ rv = unblockproc(thread->md.id);
+#endif
+}
+
+PR_IMPLEMENT(void) _MD_SuspendCPU(struct _PRCPU *thread)
+{
+ PRInt32 rv;
+
+#if 0
+ cpu->md.suspending_id = getpid();
+ rv = kill(cpu->md.id, SIGUSR1);
+ PR_ASSERT(rv == 0);
+ /*
+ * now, block the current thread/cpu until woken up by the suspended
+ * thread from it's SIGUSR1 signal handler
+ */
+ blockproc(getpid());
+#endif
+}
+
+PR_IMPLEMENT(void) _MD_ResumeCPU(struct _PRCPU *thread)
+{
+#if 0
+ unblockproc(cpu->md.id);
+#endif
+}
+
+
+#define PT_NANOPERMICRO 1000UL
+#define PT_BILLION 1000000000UL
+
+PR_IMPLEMENT(PRStatus)
+_pt_wait(PRThread *thread, PRIntervalTime timeout)
+{
+int rv;
+struct timeval now;
+struct timespec tmo;
+PRUint32 ticks = PR_TicksPerSecond();
+
+
+ if (timeout != PR_INTERVAL_NO_TIMEOUT) {
+ tmo.tv_sec = timeout / ticks;
+ tmo.tv_nsec = timeout - (tmo.tv_sec * ticks);
+ tmo.tv_nsec = PR_IntervalToMicroseconds(PT_NANOPERMICRO *
+ tmo.tv_nsec);
+
+ /* pthreads wants this in absolute time, off we go ... */
+ (void)GETTIMEOFDAY(&now);
+ /* that one's usecs, this one's nsecs - grrrr! */
+ tmo.tv_sec += now.tv_sec;
+ tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
+ tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
+ tmo.tv_nsec %= PT_BILLION;
+ }
+
+ pthread_mutex_lock(&thread->md.pthread_mutex);
+ thread->md.wait--;
+ if (thread->md.wait < 0) {
+ if (timeout != PR_INTERVAL_NO_TIMEOUT) {
+ rv = pthread_cond_timedwait(&thread->md.pthread_cond,
+ &thread->md.pthread_mutex, &tmo);
+ }
+ else
+ rv = pthread_cond_wait(&thread->md.pthread_cond,
+ &thread->md.pthread_mutex);
+ if (rv != 0) {
+ thread->md.wait++;
+ }
+ } else
+ rv = 0;
+ pthread_mutex_unlock(&thread->md.pthread_mutex);
+
+ return (rv == 0) ? PR_SUCCESS : PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_wait(PRThread *thread, PRIntervalTime ticks)
+{
+ if ( thread->flags & _PR_GLOBAL_SCOPE ) {
+ _MD_CHECK_FOR_EXIT();
+ if (_pt_wait(thread, ticks) == PR_FAILURE) {
+ _MD_CHECK_FOR_EXIT();
+ /*
+ * wait timed out
+ */
+ _PR_THREAD_LOCK(thread);
+ if (thread->wait.cvar) {
+ /*
+ * The thread will remove itself from the waitQ
+ * of the cvar in _PR_WaitCondVar
+ */
+ thread->wait.cvar = NULL;
+ thread->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ _pt_wait(thread, PR_INTERVAL_NO_TIMEOUT);
+ _PR_THREAD_UNLOCK(thread);
+ }
+ }
+ } else {
+ _PR_MD_SWITCH_CONTEXT(thread);
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_WakeupWaiter(PRThread *thread)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 pid, rv;
+ PRIntn is;
+
+ PR_ASSERT(_pr_md_idle_cpus >= 0);
+ if (thread == NULL) {
+ if (_pr_md_idle_cpus)
+ _MD_Wakeup_CPUs();
+ } else if (!_PR_IS_NATIVE_THREAD(thread)) {
+ /*
+ * If the thread is on my cpu's runq there is no need to
+ * wakeup any cpus
+ */
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if (me->cpu != thread->cpu) {
+ if (_pr_md_idle_cpus)
+ _MD_Wakeup_CPUs();
+ }
+ } else {
+ if (_pr_md_idle_cpus)
+ _MD_Wakeup_CPUs();
+ }
+ } else {
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(thread));
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+
+ pthread_mutex_lock(&thread->md.pthread_mutex);
+ thread->md.wait++;
+ rv = pthread_cond_signal(&thread->md.pthread_cond);
+ PR_ASSERT(rv == 0);
+ pthread_mutex_unlock(&thread->md.pthread_mutex);
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for AIX */
+PR_IMPLEMENT(void)
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_CreateThread(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PRIntn is;
+ int rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ pthread_attr_t attr;
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+
+ if (pthread_mutex_init(&thread->md.pthread_mutex, NULL) != 0) {
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+
+ if (pthread_cond_init(&thread->md.pthread_cond, NULL) != 0) {
+ pthread_mutex_destroy(&thread->md.pthread_mutex);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+ thread->flags |= _PR_GLOBAL_SCOPE;
+
+ pthread_attr_init(&attr); /* initialize attr with default attributes */
+ if (pthread_attr_setstacksize(&attr, (size_t) stackSize) != 0) {
+ pthread_mutex_destroy(&thread->md.pthread_mutex);
+ pthread_cond_destroy(&thread->md.pthread_cond);
+ pthread_attr_destroy(&attr);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_FAILURE;
+ }
+
+ thread->md.wait = 0;
+ rv = pthread_create(&thread->md.pthread, &attr, start, (void *)thread);
+ if (0 == rv) {
+ _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_created);
+ _MD_ATOMIC_INCREMENT(&_pr_md_pthreads);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return PR_SUCCESS;
+ } else {
+ pthread_mutex_destroy(&thread->md.pthread_mutex);
+ pthread_cond_destroy(&thread->md.pthread_cond);
+ pthread_attr_destroy(&attr);
+ _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_failed);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, rv);
+ return PR_FAILURE;
+ }
+}
+
+PR_IMPLEMENT(void)
+_MD_InitRunningCPU(struct _PRCPU *cpu)
+{
+ extern int _pr_md_pipefd[2];
+
+ _MD_unix_init_running_cpu(cpu);
+ cpu->md.pthread = pthread_self();
+ if (_pr_md_pipefd[0] >= 0) {
+ _PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0];
+#ifndef _PR_USE_POLL
+ FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu));
+#endif
+ }
+}
+
+
+void
+_MD_CleanupBeforeExit(void)
+{
+#if 0
+ extern PRInt32 _pr_cpus_exit;
+
+ _pr_irix_exit_now = 1;
+ if (_pr_numCPU > 1) {
+ /*
+ * Set a global flag, and wakeup all cpus which will notice the flag
+ * and exit.
+ */
+ _pr_cpus_exit = getpid();
+ _MD_Wakeup_CPUs();
+ while(_pr_numCPU > 1) {
+ _PR_WAIT_SEM(_pr_irix_exit_sem);
+ _pr_numCPU--;
+ }
+ }
+ /*
+ * cause global threads on the recycle list to exit
+ */
+ _PR_DEADQ_LOCK;
+ if (_PR_NUM_DEADNATIVE != 0) {
+ PRThread *thread;
+ PRCList *ptr;
+
+ ptr = _PR_DEADNATIVEQ.next;
+ while( ptr != &_PR_DEADNATIVEQ ) {
+ thread = _PR_THREAD_PTR(ptr);
+ _MD_CVAR_POST_SEM(thread);
+ ptr = ptr->next;
+ }
+ }
+ _PR_DEADQ_UNLOCK;
+ while(_PR_NUM_DEADNATIVE > 1) {
+ _PR_WAIT_SEM(_pr_irix_exit_sem);
+ _PR_DEC_DEADNATIVE;
+ }
+#endif
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/qnx.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/qnx.c
new file mode 100644
index 00000000..be86e5b9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/qnx.c
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <setjmp.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Unixware */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Unixware.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRUintn priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Unixware.");
+ return PR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/reliantunix.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/reliantunix.c
new file mode 100644
index 00000000..efe21086
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/reliantunix.c
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * SINIX (ReliantUNIX) 5.4 - copied from unixware.c by chrisk 040497
+ */
+#include "primpl.h"
+
+#include <ucontext.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) _GETCONTEXT(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+#ifdef ALARMS_BREAK_TCP /* I don't think they do */
+
+PRInt32 _MD_connect(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _connect(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+}
+
+PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _accept(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+ return(rv);
+}
+#endif
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for SINIX */
+/* Why? Just copied it from UNIXWARE... flying-by-night, chrisk 040497 */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for SINIX.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRUintn priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SINIX.");
+#if defined(SNI) && !defined(__GNUC__)
+ /* make compiler happy */
+ return (PRStatus)NULL;
+#endif
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/rhapsody.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/rhapsody.c
new file mode 100644
index 00000000..5df3c199
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/rhapsody.c
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#if !defined(_PR_PTHREADS)
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#if !defined(_PR_PTHREADS)
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Rhapsody */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Rhapsody.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Rhapsody.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
+
+#if defined(_PR_PTHREADS)
+
+/*
+** Stubs for unimplemented functions
+*/
+
+int pthread_condattr_init(pthread_condattr_t *attr)
+{
+ return 0;
+}
+
+int pthread_kill(pthread_t thread, int sig)
+{
+ return ENOSYS;
+}
+
+typedef struct siginfo_t siginfo_t;
+
+int sigtimedwait(const sigset_t *set, siginfo_t *info,
+ const struct timespec *timeout)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif /* _PR_PTHREADS */
+
+/* rhapsody.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/scoos.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/scoos.c
new file mode 100644
index 00000000..766bf917
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/scoos.c
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * SCO ODT 5.0 - originally created by mikep
+ */
+#include "primpl.h"
+
+#include <setjmp.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+#ifdef ALARMS_BREAK_TCP /* I don't think they do */
+
+PRInt32 _MD_connect(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _connect(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+}
+
+PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _accept(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+ return(rv);
+}
+#endif
+
+/*
+ * These are also implemented in pratom.c using NSPR locks. Any reason
+ * this might be better or worse? If you like this better, define
+ * _PR_HAVE_ATOMIC_OPS in include/md/unixware.h
+ */
+#ifdef _PR_HAVE_ATOMIC_OPS
+/* Atomic operations */
+#include <stdio.h>
+static FILE *_uw_semf;
+
+void
+_MD_INIT_ATOMIC(void)
+{
+ /* Sigh. Sure wish SYSV semaphores weren't such a pain to use */
+ if ((_uw_semf = tmpfile()) == NULL)
+ PR_ASSERT(0);
+
+ return;
+}
+
+void
+_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+ flockfile(_uw_semf);
+ (*val)++;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ flockfile(_uw_semf);
+ (*ptr) += val;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+ flockfile(_uw_semf);
+ (*val)--;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+{
+ flockfile(_uw_semf);
+ *val = newval;
+ unflockfile(_uw_semf);
+}
+#endif
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for SCO */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for SCO.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SCO.");
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/solaris.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/solaris.c
new file mode 100644
index 00000000..2ec3bd1e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/solaris.c
@@ -0,0 +1,889 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+
+extern PRBool suspendAllOn;
+extern PRThread *suspendAllThread;
+
+extern void _MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri);
+
+PRIntervalTime _MD_Solaris_TicksPerSecond(void)
+{
+ /*
+ * Ticks have a 10-microsecond resolution. So there are
+ * 100000 ticks per second.
+ */
+ return 100000UL;
+}
+
+/* Interval timers, implemented using gethrtime() */
+
+PRIntervalTime _MD_Solaris_GetInterval(void)
+{
+ union {
+ hrtime_t hrt; /* hrtime_t is a 64-bit (long long) integer */
+ PRInt64 pr64;
+ } time;
+ PRInt64 resolution;
+ PRIntervalTime ticks;
+
+ time.hrt = gethrtime(); /* in nanoseconds */
+ /*
+ * Convert from nanoseconds to ticks. A tick's resolution is
+ * 10 microseconds, or 10000 nanoseconds.
+ */
+ LL_I2L(resolution, 10000);
+ LL_DIV(time.pr64, time.pr64, resolution);
+ LL_L2UI(ticks, time.pr64);
+ return ticks;
+}
+
+#ifdef _PR_PTHREADS
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np)
+{
+ *np = 0;
+ return NULL;
+}
+#endif /* _PR_PTHREADS */
+
+#if !defined(i386) && !defined(IS_64)
+#if defined(_PR_HAVE_ATOMIC_OPS)
+/* NOTE:
+ * SPARC v9 (Ultras) do have an atomic test-and-set operation. But
+ * SPARC v8 doesn't. We should detect in the init if we are running on
+ * v8 or v9, and then use assembly where we can.
+ *
+ * This code uses the Solaris threads API. It can be used in both the
+ * pthreads and Solaris threads versions of nspr20 because "POSIX threads
+ * and Solaris threads are fully compatible even within the same process",
+ * to quote from pthread_create(3T).
+ */
+
+#include <thread.h>
+#include <synch.h>
+
+static mutex_t _solaris_atomic = DEFAULTMUTEX;
+
+PRInt32
+_MD_AtomicIncrement(PRInt32 *val)
+{
+ PRInt32 rv;
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
+
+ rv = ++(*val);
+
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+
+ return rv;
+}
+
+PRInt32
+_MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+{
+ PRInt32 rv;
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
+
+ rv = ((*ptr) += val);
+
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+
+ return rv;
+}
+
+PRInt32
+_MD_AtomicDecrement(PRInt32 *val)
+{
+ PRInt32 rv;
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
+
+ rv = --(*val);
+
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+
+ return rv;
+}
+
+PRInt32
+_MD_AtomicSet(PRInt32 *val, PRInt32 newval)
+{
+ PRInt32 rv;
+ if (mutex_lock(&_solaris_atomic) != 0)
+ PR_ASSERT(0);
+
+ rv = *val;
+ *val = newval;
+
+ if (mutex_unlock(&_solaris_atomic) != 0)\
+ PR_ASSERT(0);
+
+ return rv;
+}
+#endif /* _PR_HAVE_ATOMIC_OPS */
+#endif /* !defined(i386) */
+
+#if defined(_PR_GLOBAL_THREADS_ONLY)
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <thread.h>
+
+#include <sys/lwp.h>
+#include <sys/procfs.h>
+#include <sys/syscall.h>
+extern int syscall(); /* not declared in sys/syscall.h */
+
+static sigset_t old_mask; /* store away original gc thread sigmask */
+static PRIntn gcprio; /* store away original gc thread priority */
+
+THREAD_KEY_T threadid_key;
+THREAD_KEY_T cpuid_key;
+THREAD_KEY_T last_thread_key;
+static sigset_t set, oldset;
+
+static void
+threadid_key_destructor(void *value)
+{
+ PRThread *me = (PRThread *)value;
+ PR_ASSERT(me != NULL);
+ /* the thread could be PRIMORDIAL (thus not ATTACHED) */
+ if (me->flags & _PR_ATTACHED) {
+ /*
+ * The Solaris thread library sets the thread specific
+ * data (the current thread) to NULL before invoking
+ * the destructor. We need to restore it to prevent the
+ * _PR_MD_CURRENT_THREAD() call in _PRI_DetachThread()
+ * from attaching the thread again.
+ */
+ _PR_MD_SET_CURRENT_THREAD(me);
+ _PRI_DetachThread();
+ }
+}
+
+void _MD_EarlyInit(void)
+{
+ THR_KEYCREATE(&threadid_key, threadid_key_destructor);
+ THR_KEYCREATE(&cpuid_key, NULL);
+ THR_KEYCREATE(&last_thread_key, NULL);
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+}
+
+PRStatus _MD_CreateThread(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PRInt32 flags;
+
+ /* mask out SIGALRM for native thread creation */
+ thr_sigsetmask(SIG_BLOCK, &set, &oldset);
+
+ /*
+ * Note that we create joinable threads with the THR_DETACHED
+ * flag. The reasons why we don't use thr_join to implement
+ * PR_JoinThread are:
+ * - We use a termination condition variable in the PRThread
+ * structure to implement PR_JoinThread across all classic
+ * nspr implementation strategies.
+ * - The native threads may be recycled by NSPR to run other
+ * new NSPR threads, so the native threads may not terminate
+ * when the corresponding NSPR threads terminate.
+ */
+ flags = THR_SUSPENDED|THR_DETACHED;
+ if (_PR_IS_GCABLE_THREAD(thread) || (thread->flags & _PR_BOUND_THREAD) ||
+ (scope == PR_GLOBAL_BOUND_THREAD))
+ flags |= THR_BOUND;
+
+ if (thr_create(NULL, thread->stack->stackSize,
+ (void *(*)(void *)) start, (void *) thread,
+ flags,
+ &thread->md.handle)) {
+ thr_sigsetmask(SIG_SETMASK, &oldset, NULL);
+ return PR_FAILURE;
+ }
+
+ /* When the thread starts running, then the lwpid is set to the right
+ * value. Until then we want to mark this as 'uninit' so that
+ * its register state is initialized properly for GC */
+
+ thread->md.lwpid = -1;
+ thr_sigsetmask(SIG_SETMASK, &oldset, NULL);
+ _MD_NEW_SEM(&thread->md.waiter_sem, 0);
+
+ if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) {
+ thread->flags |= _PR_GLOBAL_SCOPE;
+ }
+
+ _MD_SET_PRIORITY(&(thread->md), priority);
+
+ /* Activate the thread */
+ if (thr_continue( thread->md.handle ) ) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+void _MD_cleanup_thread(PRThread *thread)
+{
+ thread_t hdl;
+
+ hdl = thread->md.handle;
+
+ /*
+ ** First, suspend the thread (unless it's the active one)
+ ** Because we suspend it first, we don't have to use LOCK_SCHEDULER to
+ ** prevent both of us modifying the thread structure at the same time.
+ */
+ if ( thread != _PR_MD_CURRENT_THREAD() ) {
+ thr_suspend(hdl);
+ }
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("(0X%x)[DestroyThread]\n", thread));
+
+ _MD_DESTROY_SEM(&thread->md.waiter_sem);
+}
+
+void _MD_exit_thread(PRThread *thread)
+{
+ _MD_CLEAN_THREAD(thread);
+ _MD_SET_CURRENT_THREAD(NULL);
+}
+
+void _MD_SET_PRIORITY(_MDThread *md_thread,
+ PRThreadPriority newPri)
+{
+ PRIntn nativePri;
+
+ if (newPri < PR_PRIORITY_FIRST) {
+ newPri = PR_PRIORITY_FIRST;
+ } else if (newPri > PR_PRIORITY_LAST) {
+ newPri = PR_PRIORITY_LAST;
+ }
+ /* Solaris priorities are from 0 to 127 */
+ nativePri = newPri * 127 / PR_PRIORITY_LAST;
+ if(thr_setprio((thread_t)md_thread->handle, nativePri)) {
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("_PR_SetThreadPriority: can't set thread priority\n"));
+ }
+}
+
+void _MD_WAIT_CV(
+ struct _MDCVar *md_cv, struct _MDLock *md_lock, PRIntervalTime timeout)
+{
+ struct timespec tt;
+ PRUint32 msec;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT((!suspendAllOn) || (suspendAllThread != me));
+
+ if (PR_INTERVAL_NO_TIMEOUT == timeout) {
+ COND_WAIT(&md_cv->cv, &md_lock->lock);
+ } else {
+ msec = PR_IntervalToMilliseconds(timeout);
+
+ GETTIME(&tt);
+ tt.tv_sec += msec / PR_MSEC_PER_SEC;
+ tt.tv_nsec += (msec % PR_MSEC_PER_SEC) * PR_NSEC_PER_MSEC;
+ /* Check for nsec overflow - otherwise we'll get an EINVAL */
+ if (tt.tv_nsec >= PR_NSEC_PER_SEC) {
+ tt.tv_sec++;
+ tt.tv_nsec -= PR_NSEC_PER_SEC;
+ }
+ COND_TIMEDWAIT(&md_cv->cv, &md_lock->lock, &tt);
+ }
+}
+
+void _MD_lock(struct _MDLock *md_lock)
+{
+#ifdef DEBUG
+ /* This code was used for GC testing to make sure that we didn't attempt
+ * to grab any locks while threads are suspended.
+ */
+ PRLock *lock;
+
+ if ((suspendAllOn) && (suspendAllThread == _PR_MD_CURRENT_THREAD())) {
+ lock = ((PRLock *) ((char*) (md_lock) - offsetof(PRLock,ilock)));
+ PR_ASSERT(lock->owner == NULL);
+ return;
+ }
+#endif /* DEBUG */
+
+ mutex_lock(&md_lock->lock);
+}
+
+PRThread *_pr_attached_thread_tls()
+{
+ PRThread *ret;
+
+ thr_getspecific(threadid_key, (void **)&ret);
+ return ret;
+}
+
+PRThread *_pr_current_thread_tls()
+{
+ PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(thread != NULL);
+
+ return thread;
+}
+
+PRStatus
+_MD_wait(PRThread *thread, PRIntervalTime ticks)
+{
+ _MD_WAIT_SEM(&thread->md.waiter_sem);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WakeupWaiter(PRThread *thread)
+{
+ if (thread == NULL) {
+ return PR_SUCCESS;
+ }
+ _MD_POST_SEM(&thread->md.waiter_sem);
+ return PR_SUCCESS;
+}
+
+_PRCPU *_pr_current_cpu_tls()
+{
+ _PRCPU *ret;
+
+ thr_getspecific(cpuid_key, (void **)&ret);
+ return ret;
+}
+
+PRThread *_pr_last_thread_tls()
+{
+ PRThread *ret;
+
+ thr_getspecific(last_thread_key, (void **)&ret);
+ return ret;
+}
+
+_MDLock _pr_ioq_lock;
+
+void
+_MD_InitIO(void)
+{
+ _MD_NEW_LOCK(&_pr_ioq_lock);
+}
+
+PRStatus _MD_InitializeThread(PRThread *thread)
+{
+ if (!_PR_IS_NATIVE_THREAD(thread))
+ return PR_SUCCESS;
+ /* sol_curthread is an asm routine which grabs GR7; GR7 stores an internal
+ * thread structure ptr used by solaris. We'll use this ptr later
+ * with suspend/resume to find which threads are running on LWPs.
+ */
+ thread->md.threadID = sol_curthread();
+ /* prime the sp; substract 4 so we don't hit the assert that
+ * curr sp > base_stack
+ */
+ thread->md.sp = (uint_t) thread->stack->allocBase - sizeof(long);
+ thread->md.lwpid = _lwp_self();
+ thread->md.handle = THR_SELF();
+
+ /* all threads on Solaris are global threads from NSPR's perspective
+ * since all of them are mapped to Solaris threads.
+ */
+ thread->flags |= _PR_GLOBAL_SCOPE;
+
+ /* For primordial/attached thread, we don't create an underlying native thread.
+ * So, _MD_CREATE_THREAD() does not get called. We need to do initialization
+ * like allocating thread's synchronization variables and set the underlying
+ * native thread's priority.
+ */
+ if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
+ _MD_NEW_SEM(&thread->md.waiter_sem, 0);
+ _MD_SET_PRIORITY(&(thread->md), thread->priority);
+ }
+ return PR_SUCCESS;
+}
+
+/* Sleep for n milliseconds, n < 1000 */
+void solaris_msec_sleep(int n)
+{
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000*n;
+ if (syscall(SYS_nanosleep, &ts, 0, 0) < 0) {
+ PR_ASSERT(0);
+ }
+}
+
+#define VALID_SP(sp, bottom, top) \
+ (((uint_t)(sp)) > ((uint_t)(bottom)) && ((uint_t)(sp)) < ((uint_t)(top)))
+
+void solaris_record_regs(PRThread *t, prstatus_t *lwpstatus)
+{
+#ifdef sparc
+ long *regs = (long *)&t->md.context.uc_mcontext.gregs[0];
+
+ PR_ASSERT(_PR_IS_GCABLE_THREAD(t));
+ PR_ASSERT(t->md.threadID == lwpstatus->pr_reg[REG_G7]);
+
+ t->md.sp = lwpstatus->pr_reg[REG_SP];
+ PR_ASSERT(VALID_SP(t->md.sp, t->stack->stackBottom, t->stack->stackTop));
+
+ regs[0] = lwpstatus->pr_reg[R_G1];
+ regs[1] = lwpstatus->pr_reg[R_G2];
+ regs[2] = lwpstatus->pr_reg[R_G3];
+ regs[3] = lwpstatus->pr_reg[R_G4];
+ regs[4] = lwpstatus->pr_reg[R_O0];
+ regs[5] = lwpstatus->pr_reg[R_O1];
+ regs[6] = lwpstatus->pr_reg[R_O2];
+ regs[7] = lwpstatus->pr_reg[R_O3];
+ regs[8] = lwpstatus->pr_reg[R_O4];
+ regs[9] = lwpstatus->pr_reg[R_O5];
+ regs[10] = lwpstatus->pr_reg[R_O6];
+ regs[11] = lwpstatus->pr_reg[R_O7];
+#elif defined(i386)
+ /*
+ * To be implemented and tested
+ */
+ PR_ASSERT(0);
+ PR_ASSERT(t->md.threadID == lwpstatus->pr_reg[GS]);
+ t->md.sp = lwpstatus->pr_reg[UESP];
+#endif
+}
+
+void solaris_preempt_off()
+{
+ sigset_t set;
+
+ (void)sigfillset(&set);
+ syscall(SYS_sigprocmask, SIG_SETMASK, &set, &old_mask);
+}
+
+void solaris_preempt_on()
+{
+ syscall(SYS_sigprocmask, SIG_SETMASK, &old_mask, NULL);
+}
+
+int solaris_open_main_proc_fd()
+{
+ char buf[30];
+ int fd;
+
+ /* Not locked, so must be created while threads coming up */
+ PR_snprintf(buf, sizeof(buf), "/proc/%ld", getpid());
+ if ( (fd = syscall(SYS_open, buf, O_RDONLY)) < 0) {
+ return -1;
+ }
+ return fd;
+}
+
+/* Return a file descriptor for the /proc entry corresponding to the
+ * given lwp.
+ */
+int solaris_open_lwp(lwpid_t id, int lwp_main_proc_fd)
+{
+ int result;
+
+ if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCOPENLWP, &id)) <0)
+ return -1; /* exited??? */
+
+ return result;
+}
+void _MD_Begin_SuspendAll()
+{
+ solaris_preempt_off();
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin_SuspendAll\n"));
+ /* run at highest prio so I cannot be preempted */
+ thr_getprio(thr_self(), &gcprio);
+ thr_setprio(thr_self(), 0x7fffffff);
+ suspendAllOn = PR_TRUE;
+ suspendAllThread = _PR_MD_CURRENT_THREAD();
+}
+
+void _MD_End_SuspendAll()
+{
+}
+
+void _MD_End_ResumeAll()
+{
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End_ResumeAll\n"));
+ thr_setprio(thr_self(), gcprio);
+ solaris_preempt_on();
+ suspendAllThread = NULL;
+ suspendAllOn = PR_FALSE;
+}
+
+void _MD_Suspend(PRThread *thr)
+{
+ int lwp_fd, result;
+ prstatus_t lwpstatus;
+ int lwp_main_proc_fd = 0;
+
+ if (!_PR_IS_GCABLE_THREAD(thr) || !suspendAllOn){
+ /*XXX When the suspendAllOn is set, we will be trying to do lwp_suspend
+ * during that time we can't call any thread lib or libc calls. Hence
+ * make sure that no suspension is requested for Non gcable thread
+ * during suspendAllOn */
+ PR_ASSERT(!suspendAllOn);
+ thr_suspend(thr->md.handle);
+ return;
+ }
+
+ /* XXX Primordial thread can't be bound to an lwp, hence there is no
+ * way we can assume that we can get the lwp status for primordial
+ * thread reliably. Hence we skip this for primordial thread, hoping
+ * that the SP is saved during lock and cond. wait.
+ * XXX - Again this is concern only for java interpreter, not for the
+ * server, 'cause primordial thread in the server does not do java work
+ */
+ if (thr->flags & _PR_PRIMORDIAL)
+ return;
+
+ /* XXX Important Note: If the start function of a thread is not called,
+ * lwpid is -1. Then, skip this thread. This thread will get caught
+ * in PR_NativeRunThread before calling the start function, because
+ * we hold the pr_activeLock during suspend/resume */
+
+ /* if the thread is not started yet then don't do anything */
+ if (!suspendAllOn || thr->md.lwpid == -1)
+ return;
+
+ if (_lwp_suspend(thr->md.lwpid) < 0) {
+ PR_ASSERT(0);
+ return;
+ }
+
+ if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) {
+ PR_ASSERT(0);
+ return; /* XXXMB ARGH, we're hosed! */
+ }
+
+ if ( (lwp_fd = solaris_open_lwp(thr->md.lwpid, lwp_main_proc_fd)) < 0) {
+ PR_ASSERT(0);
+ close(lwp_main_proc_fd);
+ return;
+ }
+ if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
+ /* Hopefully the thread just died... */
+ close(lwp_fd);
+ close(lwp_main_proc_fd);
+ return;
+ }
+ while ( !(lwpstatus.pr_flags & PR_STOPPED) ) {
+ if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
+ PR_ASSERT(0); /* ARGH SOMETHING WRONG! */
+ break;
+ }
+ solaris_msec_sleep(1);
+ }
+ solaris_record_regs(thr, &lwpstatus);
+ close(lwp_fd);
+ close(lwp_main_proc_fd);
+}
+
+#ifdef OLD_CODE
+
+void _MD_SuspendAll()
+{
+ /* On solaris there are threads, and there are LWPs.
+ * Calling _PR_DoSingleThread would freeze all of the threads bound to LWPs
+ * but not necessarily stop all LWPs (for example if someone did
+ * an attachthread of a thread which was not bound to an LWP).
+ * So now go through all the LWPs for this process and freeze them.
+ *
+ * Note that if any thread which is capable of having the GC run on it must
+ * had better be a LWP with a single bound thread on it. Otherwise, this
+ * might not stop that thread from being run.
+ */
+ PRThread *current = _PR_MD_CURRENT_THREAD();
+ prstatus_t status, lwpstatus;
+ int result, index, lwp_fd;
+ lwpid_t me = _lwp_self();
+ int err;
+ int lwp_main_proc_fd;
+
+ solaris_preempt_off();
+
+ /* run at highest prio so I cannot be preempted */
+ thr_getprio(thr_self(), &gcprio);
+ thr_setprio(thr_self(), 0x7fffffff);
+
+ current->md.sp = (uint_t)&me; /* set my own stack pointer */
+
+ if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) {
+ PR_ASSERT(0);
+ solaris_preempt_on();
+ return; /* XXXMB ARGH, we're hosed! */
+ }
+
+ if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCSTATUS, &status)) < 0) {
+ err = errno;
+ PR_ASSERT(0);
+ goto failure; /* XXXMB ARGH, we're hosed! */
+ }
+
+ num_lwps = status.pr_nlwp;
+
+ if ( (all_lwps = (lwpid_t *)PR_MALLOC((num_lwps+1) * sizeof(lwpid_t)))==NULL) {
+ PR_ASSERT(0);
+ goto failure; /* XXXMB ARGH, we're hosed! */
+ }
+
+ if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCLWPIDS, all_lwps)) < 0) {
+ PR_ASSERT(0);
+ PR_DELETE(all_lwps);
+ goto failure; /* XXXMB ARGH, we're hosed! */
+ }
+
+ for (index=0; index< num_lwps; index++) {
+ if (all_lwps[index] != me) {
+ if (_lwp_suspend(all_lwps[index]) < 0) {
+ /* could happen if lwp exited */
+ all_lwps[index] = me; /* dummy it up */
+ }
+ }
+ }
+
+ /* Turns out that lwp_suspend is not a blocking call.
+ * Go through the list and make sure they are all stopped.
+ */
+ for (index=0; index< num_lwps; index++) {
+ if (all_lwps[index] != me) {
+ if ( (lwp_fd = solaris_open_lwp(all_lwps[index], lwp_main_proc_fd)) < 0) {
+ PR_ASSERT(0);
+ PR_DELETE(all_lwps);
+ all_lwps = NULL;
+ goto failure; /* XXXMB ARGH, we're hosed! */
+ }
+
+ if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
+ /* Hopefully the thread just died... */
+ close(lwp_fd);
+ continue;
+ }
+ while ( !(lwpstatus.pr_flags & PR_STOPPED) ) {
+ if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
+ PR_ASSERT(0); /* ARGH SOMETHING WRONG! */
+ break;
+ }
+ solaris_msec_sleep(1);
+ }
+ solaris_record_regs(&lwpstatus);
+ close(lwp_fd);
+ }
+ }
+
+ close(lwp_main_proc_fd);
+
+ return;
+failure:
+ solaris_preempt_on();
+ thr_setprio(thr_self(), gcprio);
+ close(lwp_main_proc_fd);
+ return;
+}
+
+void _MD_ResumeAll()
+{
+ int i;
+ lwpid_t me = _lwp_self();
+
+ for (i=0; i < num_lwps; i++) {
+ if (all_lwps[i] == me)
+ continue;
+ if ( _lwp_continue(all_lwps[i]) < 0) {
+ PR_ASSERT(0); /* ARGH, we are hosed! */
+ }
+ }
+
+ /* restore priority and sigmask */
+ thr_setprio(thr_self(), gcprio);
+ solaris_preempt_on();
+ PR_DELETE(all_lwps);
+ all_lwps = NULL;
+}
+#endif /* OLD_CODE */
+
+#ifdef USE_SETJMP
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+#else
+PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np)
+{
+ if (isCurrent) {
+ (void) getcontext(CONTEXT(t));
+ }
+ *np = NGREG;
+ return (PRWord*) &t->md.context.uc_mcontext.gregs[0];
+}
+#endif /* USE_SETJMP */
+
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+#if defined(_PR_LOCAL_THREADS_ONLY)
+
+void _MD_EarlyInit(void)
+{
+}
+
+void _MD_SolarisInit()
+{
+ _PR_UnixInit();
+}
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ PR_ASSERT((thread == NULL) || (!(thread->flags & _PR_GLOBAL_SCOPE)));
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Solaris */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Solaris");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Solaris");
+ return(PR_FAILURE);
+}
+
+#ifdef USE_SETJMP
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+#else
+PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np)
+{
+ if (isCurrent) {
+ (void) getcontext(CONTEXT(t));
+ }
+ *np = NGREG;
+ return (PRWord*) &t->md.context.uc_mcontext.gregs[0];
+}
+#endif /* USE_SETJMP */
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+
+#ifndef _PR_PTHREADS
+#if defined(i386) && defined(SOLARIS2_4)
+/*
+ * Because clock_gettime() on Solaris/x86 2.4 always generates a
+ * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
+ * which is implemented using gettimeofday().
+ */
+
+int
+_pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+ struct timeval tv;
+
+ if (clock_id != CLOCK_REALTIME) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ gettimeofday(&tv, NULL);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = tv.tv_usec * 1000;
+ return 0;
+}
+#endif /* i386 && SOLARIS2_4 */
+#endif /* _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sony.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sony.c
new file mode 100644
index 00000000..dacb4fd5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sony.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <signal.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#ifndef _PR_PTHREADS
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t), 1);
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+#else
+ *np = 0;
+ return NULL;
+#endif
+}
+
+#ifndef _PR_PTHREADS
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Sony */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for SONY.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SONY.");
+ return PR_FAILURE;
+}
+#endif /* ! _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sunos4.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sunos4.c
new file mode 100644
index 00000000..d3b40c15
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/sunos4.c
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <setjmp.h>
+#include "primpl.h"
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRStatus _MD_CREATE_THREAD(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SunOS 4.1.3.");
+ return PR_FAILURE;
+}
+
+void _MD_SET_PRIORITY(_MDThread *md_thread, PRUintn newPri)
+{
+ PR_NOT_REACHED("_MD_SET_PRIORITY should not be called for user-level threads.");
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus _MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for SunOS 4.1.3.");
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix.c
new file mode 100644
index 00000000..5901a476
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix.c
@@ -0,0 +1,3738 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-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.
+ */
+
+#include "primpl.h"
+
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#ifdef _PR_POLL_AVAILABLE
+#include <poll.h>
+#endif
+
+/* To get FIONREAD */
+#if defined(NCR) || defined(UNIXWARE) || defined(NEC) || defined(SNI) \
+ || defined(SONY)
+#include <sys/filio.h>
+#endif
+
+#if defined(NTO)
+#include <sys/statvfs.h>
+#endif
+
+#ifdef VBOX
+# include <iprt/mem.h>
+#endif
+
+/*
+ * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
+ * PRInt32* pointer to a _PRSockLen_t* pointer.
+ */
+#if defined(HAVE_SOCKLEN_T) \
+ || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)
+#define _PRSockLen_t socklen_t
+#elif defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \
+ || defined(AIX4_1) || defined(LINUX) || defined(SONY) \
+ || defined(BSDI) || defined(SCO) || defined(NEC) || defined(SNI) \
+ || defined(SUNOS4) || defined(NCR) || defined(DARWIN) \
+ || defined(NEXTSTEP) || defined(QNX)
+#define _PRSockLen_t int
+#elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \
+ || defined(NETBSD) || defined(OPENBSD) || defined(UNIXWARE) \
+ || defined(DGUX) || defined(VMS) || defined(NTO)
+#define _PRSockLen_t size_t
+#else
+#error "Cannot determine architecture"
+#endif
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+static PRMonitor *_pr_Xfe_mon = NULL;
+
+static PRInt64 minus_one;
+
+sigset_t timer_set;
+
+#if !defined(_PR_PTHREADS)
+
+static sigset_t empty_set;
+
+#ifdef SOLARIS
+#include <sys/file.h>
+#include <sys/filio.h>
+#endif
+
+#ifndef PIPE_BUF
+#define PIPE_BUF 512
+#endif
+
+/*
+ * _nspr_noclock - if set clock interrupts are disabled
+ */
+int _nspr_noclock = 1;
+
+#ifdef IRIX
+extern PRInt32 _nspr_terminate_on_error;
+#endif
+
+/*
+ * There is an assertion in this code that NSPR's definition of PRIOVec
+ * is bit compatible with UNIX' definition of a struct iovec. This is
+ * applicable to the 'writev()' operations where the types are casually
+ * cast to avoid warnings.
+ */
+
+int _pr_md_pipefd[2] = { -1, -1 };
+static char _pr_md_pipebuf[PIPE_BUF];
+static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag,
+ PRIntervalTime timeout);
+
+_PRInterruptTable _pr_interruptTable[] = {
+ {
+ "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, },
+ {
+ 0 }
+};
+
+PR_IMPLEMENT(void) _MD_unix_init_running_cpu(_PRCPU *cpu)
+{
+ PR_INIT_CLIST(&(cpu->md.md_unix.ioQ));
+ cpu->md.md_unix.ioq_max_osfd = -1;
+ cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;
+}
+
+PRStatus _MD_open_dir(_MDDir *d, const char *name)
+{
+int err;
+
+ d->d = opendir(name);
+ if (!d->d) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPENDIR_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PRInt32 _MD_close_dir(_MDDir *d)
+{
+int rv = 0, err;
+
+ if (d->d) {
+ rv = closedir(d->d);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSEDIR_ERROR(err);
+ }
+ }
+ return rv;
+}
+
+char * _MD_read_dir(_MDDir *d, PRIntn flags)
+{
+struct dirent *de;
+int err;
+
+ for (;;) {
+ /*
+ * XXX: readdir() is not MT-safe. There is an MT-safe version
+ * readdir_r() on some systems.
+ */
+ de = readdir(d->d);
+ if (!de) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return 0;
+ }
+ if ((flags & PR_SKIP_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == 0))
+ continue;
+ if ((flags & PR_SKIP_DOT_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
+ (de->d_name[2] == 0))
+ continue;
+ if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.'))
+ continue;
+ break;
+ }
+ return de->d_name;
+}
+
+PRInt32 _MD_delete(const char *name)
+{
+PRInt32 rv, err;
+#ifdef UNIXWARE
+ sigset_t set, oset;
+#endif
+
+#ifdef UNIXWARE
+ sigfillset(&set);
+ sigprocmask(SIG_SETMASK, &set, &oset);
+#endif
+ rv = unlink(name);
+#ifdef UNIXWARE
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+#endif
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_UNLINK_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32 _MD_rename(const char *from, const char *to)
+{
+ PRInt32 rv = -1, err;
+
+ /*
+ ** This is trying to enforce the semantics of WINDOZE' rename
+ ** operation. That means one is not allowed to rename over top
+ ** of an existing file. Holding a lock across these two function
+ ** and the open function is known to be a bad idea, but ....
+ */
+ if (NULL != _pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ if (0 == access(to, F_OK))
+ PR_SetError(PR_FILE_EXISTS_ERROR, 0);
+ else
+ {
+ rv = rename(from, to);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RENAME_ERROR(err);
+ }
+ }
+ if (NULL != _pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32 _MD_access(const char *name, PRAccessHow how)
+{
+PRInt32 rv, err;
+int amode;
+
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ amode = W_OK;
+ break;
+ case PR_ACCESS_READ_OK:
+ amode = R_OK;
+ break;
+ case PR_ACCESS_EXISTS:
+ amode = F_OK;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ rv = access(name, amode);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_ACCESS_ERROR(err);
+ }
+
+done:
+ return(rv);
+}
+
+PRInt32 _MD_mkdir(const char *name, PRIntn mode)
+{
+int rv, err;
+
+ /*
+ ** This lock is used to enforce rename semantics as described
+ ** in PR_Rename. Look there for more fun details.
+ */
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ rv = mkdir(name, mode);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_MKDIR_ERROR(err);
+ }
+ if (NULL !=_pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32 _MD_rmdir(const char *name)
+{
+int rv, err;
+
+ rv = rmdir(name);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RMDIR_ERROR(err);
+ }
+ return rv;
+}
+
+PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+PRThread *me = _PR_MD_CURRENT_THREAD();
+PRInt32 rv, err;
+#ifndef _PR_USE_POLL
+fd_set rd;
+#else
+struct pollfd pfd;
+#endif /* _PR_USE_POLL */
+PRInt32 osfd = fd->secret->md.osfd;
+
+#ifndef _PR_USE_POLL
+ FD_ZERO(&rd);
+ FD_SET(osfd, &rd);
+#else
+ pfd.fd = osfd;
+ pfd.events = POLLIN;
+#endif /* _PR_USE_POLL */
+ while ((rv = read(osfd,buf,amount)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ,
+ PR_INTERVAL_NO_TIMEOUT)) < 0)
+ goto done;
+ } else {
+#ifndef _PR_USE_POLL
+ while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_SELECT() if it is interrupted */
+ }
+#else /* _PR_USE_POLL */
+ while ((rv = _MD_POLL(&pfd, 1, -1))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_POLL() if it is interrupted */
+ }
+#endif /* _PR_USE_POLL */
+ if (rv == -1) {
+ break;
+ }
+ }
+ if (_PR_PENDING_INTERRUPT(me))
+ break;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ _PR_MD_MAP_READ_ERROR(err);
+ }
+ }
+done:
+ return(rv);
+}
+
+PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+PRThread *me = _PR_MD_CURRENT_THREAD();
+PRInt32 rv, err;
+#ifndef _PR_USE_POLL
+fd_set wd;
+#else
+struct pollfd pfd;
+#endif /* _PR_USE_POLL */
+PRInt32 osfd = fd->secret->md.osfd;
+
+#ifndef _PR_USE_POLL
+ FD_ZERO(&wd);
+ FD_SET(osfd, &wd);
+#else
+ pfd.fd = osfd;
+ pfd.events = POLLOUT;
+#endif /* _PR_USE_POLL */
+ while ((rv = write(osfd,buf,amount)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE,
+ PR_INTERVAL_NO_TIMEOUT)) < 0)
+ goto done;
+ } else {
+#ifndef _PR_USE_POLL
+ while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_SELECT() if it is interrupted */
+ }
+#else /* _PR_USE_POLL */
+ while ((rv = _MD_POLL(&pfd, 1, -1))
+ == -1 && (err = _MD_ERRNO()) == EINTR) {
+ /* retry _MD_POLL() if it is interrupted */
+ }
+#endif /* _PR_USE_POLL */
+ if (rv == -1) {
+ break;
+ }
+ }
+ if (_PR_PENDING_INTERRUPT(me))
+ break;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ _PR_MD_MAP_WRITE_ERROR(err);
+ }
+ }
+done:
+ return(rv);
+}
+
+PRInt32 _MD_fsync(PRFileDesc *fd)
+{
+PRInt32 rv, err;
+
+ rv = fsync(fd->secret->md.osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSYNC_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32 _MD_close(PRInt32 osfd)
+{
+PRInt32 rv, err;
+
+ rv = close(osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
+{
+ PRInt32 osfd, err;
+
+ osfd = socket(domain, type, proto);
+
+ if (osfd == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR(err);
+ return(osfd);
+ }
+
+ return(osfd);
+}
+
+PRInt32 _MD_socketavailable(PRFileDesc *fd)
+{
+ PRInt32 result;
+
+ if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO());
+ return -1;
+ }
+ return result;
+}
+
+PRInt64 _MD_socketavailable64(PRFileDesc *fd)
+{
+ PRInt64 result;
+ LL_I2L(result, _MD_socketavailable(fd));
+ return result;
+} /* _MD_socketavailable64 */
+
+#define READ_FD 1
+#define WRITE_FD 2
+
+/*
+ * socket_io_wait --
+ *
+ * wait for socket i/o, periodically checking for interrupt
+ *
+ * The first implementation uses select(), for platforms without
+ * poll(). The second (preferred) implementation uses poll().
+ */
+
+#ifndef _PR_USE_POLL
+
+static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+ struct timeval tv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRInt32 syserror;
+ fd_set rd_wr;
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ FD_ZERO(&rd_wr);
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+ wait_for_remaining = PR_TRUE;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_SELECT_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+ /*
+ * If _MD_SELECT timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ }
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
+}
+
+#else /* _PR_USE_POLL */
+
+static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+ int msecs;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRInt32 syserror;
+ struct pollfd pfd;
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ pfd.fd = osfd;
+ if (fd_type == READ_FD) {
+ pfd.events = POLLIN;
+ } else {
+ pfd.events = POLLOUT;
+ }
+ do {
+ rv = _MD_POLL(&pfd, 1, msecs);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_POLL_ERROR(syserror);
+ break;
+ }
+ /*
+ * If POLLERR is set, don't process it; retry the operation
+ */
+ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {
+ rv = -1;
+ _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ pfd.fd = osfd;
+ if (fd_type == READ_FD) {
+ pfd.events = POLLIN;
+ } else {
+ pfd.events = POLLOUT;
+ }
+ do {
+ /*
+ * We block in _MD_POLL for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+ wait_for_remaining = PR_TRUE;
+ msecs = PR_IntervalToMilliseconds(remaining);
+ if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) {
+ wait_for_remaining = PR_FALSE;
+ msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000;
+ }
+ rv = _MD_POLL(&pfd, 1, msecs);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ _PR_MD_MAP_POLL_ERROR(syserror);
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * If POLLERR is set, don't process it; retry the operation
+ */
+ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) {
+ rv = -1;
+ _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents);
+ break;
+ }
+ /*
+ * We loop again if _MD_POLL timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+ /*
+ * If _MD_POLL timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ if (wait_for_remaining) {
+ now += remaining;
+ } else {
+ now += PR_MillisecondsToInterval(msecs);
+ }
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
+}
+
+#endif /* _PR_USE_POLL */
+
+static PRInt32 local_io_wait(
+ PRInt32 osfd,
+ PRInt32 wait_flag,
+ PRIntervalTime timeout)
+{
+ _PRUnixPollDesc pd;
+ PRInt32 rv;
+
+ PR_LOG(_pr_io_lm, PR_LOG_MIN,
+ ("waiting to %s on osfd=%d",
+ (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write",
+ osfd));
+
+ if (timeout == PR_INTERVAL_NO_WAIT) return 0;
+
+ pd.osfd = osfd;
+ pd.in_flags = wait_flag;
+ pd.out_flags = 0;
+
+ rv = _PR_WaitForMultipleFDs(&pd, 1, timeout);
+
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ }
+ return rv;
+}
+
+
+PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRInt32 flags, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+/*
+ * Many OS's (Solaris, Unixware) have a broken recv which won't read
+ * from socketpairs. As long as we don't use flags on socketpairs, this
+ * is a decent fix. - mikep
+ */
+#if defined(UNIXWARE) || defined(SOLARIS) || defined(NCR)
+ while ((rv = read(osfd,buf,amount)) == -1) {
+#else
+ while ((rv = recv(osfd,buf,amount,flags)) == -1) {
+#endif
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd,_PR_UNIX_POLL_READ,timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv != -1) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRInt32 flags, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#if defined(SOLARIS)
+ PRInt32 tmp_amount = amount;
+#endif
+
+ /*
+ * On pre-2.6 Solaris, send() is much slower than write().
+ * On 2.6 and beyond, with in-kernel sockets, send() and
+ * write() are fairly equivalent in performance.
+ */
+#if defined(SOLARIS)
+ PR_ASSERT(0 == flags);
+ while ((rv = write(osfd,buf,tmp_amount)) == -1) {
+#else
+ while ((rv = send(osfd,buf,amount,flags)) == -1) {
+#endif
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+#if defined(SOLARIS)
+ /*
+ * The write system call has been reported to return the ERANGE
+ * error on occasion. Try to write in smaller chunks to workaround
+ * this bug.
+ */
+ if (err == ERANGE) {
+ if (tmp_amount > 1) {
+ tmp_amount = tmp_amount/2; /* half the bytes */
+ continue;
+ }
+ }
+#endif
+ break;
+ }
+ }
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next send() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) {
+ rv = -1;
+ goto done;
+ }
+ } else {
+ if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32 _MD_sendto(
+ PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) &addrCopy, addrlen)) == -1) {
+#else
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1) {
+#endif
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32 _MD_writev(
+ PRFileDesc *fd, const PRIOVec *iov,
+ PRInt32 iov_size, PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 index, amount = 0;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ /*
+ * Calculate the total number of bytes to be sent; needed for
+ * optimization later.
+ * We could avoid this if this number was passed in; but it is
+ * probably not a big deal because iov_size is usually small (less than
+ * 3)
+ */
+ if (!fd->secret->nonblocking) {
+ for (index=0; index<iov_size; index++) {
+ amount += iov[index].iov_len;
+ }
+ }
+
+ while ((rv = writev(osfd, (const struct iovec*)iov, iov_size)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ /*
+ * optimization; if bytes sent is less than "amount" call
+ * select before returning. This is because it is likely that
+ * the next writev() call will return EWOULDBLOCK.
+ */
+ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount)
+ && (timeout != PR_INTERVAL_NO_WAIT)) {
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ } else {
+ if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) {
+ rv = -1;
+ goto done;
+ }
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_WRITEV_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = accept(osfd, (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1) {
+ err = _MD_ERRNO();
+ if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == ECONNABORTED)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0)
+ goto done;
+ } else {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ }
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv != -1) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+extern int _connect (int s, const struct sockaddr *name, int namelen);
+PRInt32 _MD_connect(
+ PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 osfd = fd->secret->md.osfd;
+#ifdef IRIX
+extern PRInt32 _MD_irix_connect(
+ PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout);
+#endif
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+#endif
+
+ /*
+ * We initiate the connection setup by making a nonblocking connect()
+ * call. If the connect() call fails, there are two cases we handle
+ * specially:
+ * 1. The connect() call was interrupted by a signal. In this case
+ * we simply retry connect().
+ * 2. The NSPR socket is nonblocking and connect() fails with
+ * EINPROGRESS. We first wait until the socket becomes writable.
+ * Then we try to find out whether the connection setup succeeded
+ * or failed.
+ */
+
+retry:
+#ifdef IRIX
+ if ((rv = _MD_irix_connect(osfd, addr, addrlen, timeout)) == -1) {
+#else
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) {
+#else
+ if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
+#endif
+#endif
+ err = _MD_ERRNO();
+
+ if (err == EINTR) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ goto retry;
+ }
+
+ if (!fd->secret->nonblocking && (err == EINPROGRESS)) {
+ if (!_PR_IS_NATIVE_THREAD(me)) {
+
+ if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0)
+ return -1;
+ } else {
+ /*
+ * socket_io_wait() may return -1 or 1.
+ */
+
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv == -1) {
+ return -1;
+ }
+ }
+
+ PR_ASSERT(rv == 1);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ err = _MD_unix_get_nonblocking_connect_error(osfd);
+ if (err != 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ }
+ return 0;
+ }
+
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+
+ return rv;
+} /* _MD_connect */
+
+PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv, err;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ PRNetAddr addrCopy;
+
+ addrCopy = *addr;
+ ((struct sockaddr *) &addrCopy)->sa_len = addrlen;
+ ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family;
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen);
+#else
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+#endif
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv, err;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LISTEN_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how)
+{
+ PRInt32 rv, err;
+
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SHUTDOWN_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32 _MD_socketpair(int af, int type, int flags,
+ PRInt32 *osfd)
+{
+ PRInt32 rv, err;
+
+ rv = socketpair(af, type, flags, osfd);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKETPAIR_ERROR(err);
+ }
+ return rv;
+}
+
+PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockname(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv == 0) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKNAME_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr,
+ PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getpeername(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv == 0) {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr) {
+ addr->raw.family = ((struct sockaddr *) addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETPEERNAME_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv, err;
+
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable)
+{
+ int rv;
+
+ rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
+ if (-1 == rv) {
+ PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported)
+{
+ if (imported) {
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ } else {
+ /* By default, a Unix fd is not closed on exec. */
+#ifdef DEBUG
+ {
+ int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ PR_ASSERT(0 == flags);
+ }
+#endif
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ }
+}
+
+/************************************************************************/
+#if !defined(_PR_USE_POLL)
+
+/*
+** Scan through io queue and find any bad fd's that triggered the error
+** from _MD_SELECT
+*/
+static void FindBadFDs(void)
+{
+ PRCList *q;
+ PRThread *me = _MD_CURRENT_THREAD();
+
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
+ q = (_PR_IOQ(me->cpu)).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ pds->out_flags = 0;
+ PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
+ if (pds->in_flags == 0) {
+ continue; /* skip this fd */
+ }
+ if (fcntl(osfd, F_GETFL, 0) == -1) {
+ /* Found a bad descriptor, remove it from the fd_sets. */
+ PR_LOG(_pr_io_lm, PR_LOG_MAX,
+ ("file descriptor %d is bad", osfd));
+ pds->out_flags = _PR_UNIX_POLL_NVAL;
+ notify = PR_TRUE;
+ }
+ if (osfd > pq_max_osfd) {
+ pq_max_osfd = osfd;
+ }
+ }
+
+ if (notify) {
+ PRIntn pri;
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
+
+ /*
+ * Decrement the count of descriptors for each desciptor/event
+ * because this I/O request is being removed from the
+ * ioq
+ */
+ pds = pq->pds;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & _PR_UNIX_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+
+ _PR_THREAD_LOCK(pq->thr);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = pq->thr->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ if (pq->thr->flags & _PR_SUSPENDING) {
+ /*
+ * set thread state to SUSPENDED;
+ * a Resume operation on the thread
+ * will move it to the runQ
+ */
+ pq->thr->state = _PR_SUSPENDED;
+ _PR_MISCQ_LOCK(pq->thr->cpu);
+ _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);
+ _PR_MISCQ_UNLOCK(pq->thr->cpu);
+ } else {
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ }
+ }
+ _PR_THREAD_UNLOCK(pq->thr);
+ } else {
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ }
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+ }
+}
+#endif /* !defined(_PR_USE_POLL) */
+
+/************************************************************************/
+
+/*
+** Called by the scheduler when there is nothing to do. This means that
+** all threads are blocked on some monitor somewhere.
+**
+** Note: this code doesn't release the scheduler lock.
+*/
+/*
+** Pause the current CPU. longjmp to the cpu's pause stack
+**
+** This must be called with the scheduler locked
+*/
+void _MD_PauseCPU(PRIntervalTime ticks)
+{
+ PRThread *me = _MD_CURRENT_THREAD();
+#ifdef _PR_USE_POLL
+ int timeout;
+ struct pollfd *pollfds; /* an array of pollfd structures */
+ struct pollfd *pollfdPtr; /* a pointer that steps through the array */
+ unsigned long npollfds; /* number of pollfd structures in array */
+ unsigned long pollfds_size;
+ int nfd; /* to hold the return value of poll() */
+#else
+ struct timeval timeout, *tvp;
+ fd_set r, w, e;
+ fd_set *rp, *wp, *ep;
+ PRInt32 max_osfd, nfd;
+#endif /* _PR_USE_POLL */
+ PRInt32 rv;
+ PRCList *q;
+ PRUint32 min_timeout;
+ sigset_t oldset;
+#ifdef IRIX
+extern sigset_t ints_off;
+#endif
+
+ PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
+
+ _PR_MD_IOQ_LOCK();
+
+#ifdef _PR_USE_POLL
+ /* Build up the pollfd structure array to wait on */
+
+ /* Find out how many pollfd structures are needed */
+ npollfds = _PR_IOQ_OSFD_CNT(me->cpu);
+ PR_ASSERT(npollfds >= 0);
+
+ /*
+ * We use a pipe to wake up a native thread. An fd is needed
+ * for the pipe and we poll it for reading.
+ */
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ npollfds++;
+#ifdef IRIX
+ /*
+ * On Irix, a second pipe is used to cause the primordial cpu to
+ * wakeup and exit, when the process is exiting because of a call
+ * to exit/PR_ProcessExit.
+ */
+ if (me->cpu->id == 0) {
+ npollfds++;
+ }
+#endif
+ }
+
+ /*
+ * if the cpu's pollfd array is not big enough, release it and allocate a new one
+ */
+ if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) {
+ if (_PR_IOQ_POLLFDS(me->cpu) != NULL)
+ PR_DELETE(_PR_IOQ_POLLFDS(me->cpu));
+ pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds);
+ pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd));
+ _PR_IOQ_POLLFDS(me->cpu) = pollfds;
+ _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size;
+ } else {
+ pollfds = _PR_IOQ_POLLFDS(me->cpu);
+ }
+ pollfdPtr = pollfds;
+
+ /*
+ * If we need to poll the pipe for waking up a native thread,
+ * the pipe's fd is the first element in the pollfds array.
+ */
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ pollfdPtr->fd = _pr_md_pipefd[0];
+ pollfdPtr->events = POLLIN;
+ pollfdPtr++;
+#ifdef IRIX
+ /*
+ * On Irix, the second element is the exit pipe
+ */
+ if (me->cpu->id == 0) {
+ pollfdPtr->fd = _pr_irix_primoridal_cpu_fd[0];
+ pollfdPtr->events = POLLIN;
+ pollfdPtr++;
+ }
+#endif
+ }
+
+ min_timeout = PR_INTERVAL_NO_TIMEOUT;
+ for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+
+ if (pq->timeout < min_timeout) {
+ min_timeout = pq->timeout;
+ }
+ for (; pds < epds; pds++, pollfdPtr++) {
+ /*
+ * Assert that the pollfdPtr pointer does not go
+ * beyond the end of the pollfds array
+ */
+ PR_ASSERT(pollfdPtr < pollfds + npollfds);
+ pollfdPtr->fd = pds->osfd;
+ /* direct copy of poll flags */
+ pollfdPtr->events = pds->in_flags;
+ }
+ }
+ _PR_IOQ_TIMEOUT(me->cpu) = min_timeout;
+#else
+ /*
+ * assigment of fd_sets
+ */
+ r = _PR_FD_READ_SET(me->cpu);
+ w = _PR_FD_WRITE_SET(me->cpu);
+ e = _PR_FD_EXCEPTION_SET(me->cpu);
+
+ rp = &r;
+ wp = &w;
+ ep = &e;
+
+ max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
+ min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
+#endif /* _PR_USE_POLL */
+ /*
+ ** Compute the minimum timeout value: make it the smaller of the
+ ** timeouts specified by the i/o pollers or the timeout of the first
+ ** sleeping thread.
+ */
+ q = _PR_SLEEPQ(me->cpu).next;
+
+ if (q != &_PR_SLEEPQ(me->cpu)) {
+ PRThread *t = _PR_THREAD_PTR(q);
+
+ if (t->sleep < min_timeout) {
+ min_timeout = t->sleep;
+ }
+ }
+ if (min_timeout > ticks) {
+ min_timeout = ticks;
+ }
+
+#ifdef _PR_USE_POLL
+ if (min_timeout == PR_INTERVAL_NO_TIMEOUT)
+ timeout = -1;
+ else
+ timeout = PR_IntervalToMilliseconds(min_timeout);
+#else
+ if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
+ tvp = NULL;
+ } else {
+ timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
+ timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
+ % PR_USEC_PER_SEC;
+ tvp = &timeout;
+ }
+#endif /* _PR_USE_POLL */
+
+ _PR_MD_IOQ_UNLOCK();
+ _MD_CHECK_FOR_EXIT();
+ /*
+ * check for i/o operations
+ */
+#ifndef _PR_NO_CLOCK_TIMER
+ /*
+ * Disable the clock interrupts while we are in select, if clock interrupts
+ * are enabled. Otherwise, when the select/poll calls are interrupted, the
+ * timer value starts ticking from zero again when the system call is restarted.
+ */
+#ifdef IRIX
+ /*
+ * SIGCHLD signal is used on Irix to detect he termination of an
+ * sproc by SIGSEGV, SIGBUS or SIGABRT signals when
+ * _nspr_terminate_on_error is set.
+ */
+ if ((!_nspr_noclock) || (_nspr_terminate_on_error))
+#else
+ if (!_nspr_noclock)
+#endif /* IRIX */
+#ifdef IRIX
+ sigprocmask(SIG_BLOCK, &ints_off, &oldset);
+#else
+ PR_ASSERT(sigismember(&timer_set, SIGALRM));
+ sigprocmask(SIG_BLOCK, &timer_set, &oldset);
+#endif /* IRIX */
+#endif /* !_PR_NO_CLOCK_TIMER */
+
+#ifndef _PR_USE_POLL
+ PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp));
+ nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
+#else
+ nfd = _MD_POLL(pollfds, npollfds, timeout);
+#endif /* !_PR_USE_POLL */
+
+#ifndef _PR_NO_CLOCK_TIMER
+#ifdef IRIX
+ if ((!_nspr_noclock) || (_nspr_terminate_on_error))
+#else
+ if (!_nspr_noclock)
+#endif /* IRIX */
+ sigprocmask(SIG_SETMASK, &oldset, 0);
+#endif /* !_PR_NO_CLOCK_TIMER */
+
+ _MD_CHECK_FOR_EXIT();
+
+#ifdef IRIX
+ _PR_MD_primordial_cpu();
+#endif
+
+ _PR_MD_IOQ_LOCK();
+ /*
+ ** Notify monitors that are associated with the selected descriptors.
+ */
+#ifdef _PR_USE_POLL
+ if (nfd > 0) {
+ pollfdPtr = pollfds;
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ /*
+ * Assert that the pipe is the first element in the
+ * pollfds array.
+ */
+ PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]);
+ if ((pollfds[0].revents & POLLIN) && (nfd == 1)) {
+ /*
+ * woken up by another thread; read all the data
+ * in the pipe to empty the pipe
+ */
+ while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf,
+ PIPE_BUF)) == PIPE_BUF){
+ }
+ PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN)));
+ }
+ pollfdPtr++;
+#ifdef IRIX
+ /*
+ * On Irix, check to see if the primordial cpu needs to exit
+ * to cause the process to terminate
+ */
+ if (me->cpu->id == 0) {
+ PR_ASSERT(pollfds[1].fd == _pr_irix_primoridal_cpu_fd[0]);
+ if (pollfdPtr->revents & POLLIN) {
+ if (_pr_irix_process_exit) {
+ /*
+ * process exit due to a call to PR_ProcessExit
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(_pr_irix_process_exit_code);
+ } else {
+ while ((rv = read(_pr_irix_primoridal_cpu_fd[0],
+ _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {
+ }
+ PR_ASSERT(rv > 0);
+ }
+ }
+ pollfdPtr++;
+ }
+#endif
+ }
+ for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+
+ for (; pds < epds; pds++, pollfdPtr++) {
+ /*
+ * Assert that the pollfdPtr pointer does not go beyond
+ * the end of the pollfds array.
+ */
+ PR_ASSERT(pollfdPtr < pollfds + npollfds);
+ /*
+ * Assert that the fd's in the pollfds array (stepped
+ * through by pollfdPtr) are in the same order as
+ * the fd's in _PR_IOQ() (stepped through by q and pds).
+ * This is how the pollfds array was created earlier.
+ */
+ PR_ASSERT(pollfdPtr->fd == pds->osfd);
+ pds->out_flags = pollfdPtr->revents;
+ /* Negative fd's are ignored by poll() */
+ if (pds->osfd >= 0 && pds->out_flags) {
+ notify = PR_TRUE;
+ }
+ }
+ if (notify) {
+ PRIntn pri;
+ PRThread *thred;
+
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
+
+ thred = pq->thr;
+ _PR_THREAD_LOCK(thred);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = pq->thr->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ if (pq->thr->flags & _PR_SUSPENDING) {
+ /*
+ * set thread state to SUSPENDED;
+ * a Resume operation on the thread
+ * will move it to the runQ
+ */
+ pq->thr->state = _PR_SUSPENDED;
+ _PR_MISCQ_LOCK(pq->thr->cpu);
+ _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);
+ _PR_MISCQ_UNLOCK(pq->thr->cpu);
+ } else {
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ if (_pr_md_idle_cpus > 1)
+ _PR_MD_WAKEUP_WAITER(thred);
+ }
+ }
+ _PR_THREAD_UNLOCK(thred);
+ _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds;
+ PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
+ }
+ }
+ } else if (nfd == -1) {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno));
+ }
+
+#else
+ if (nfd > 0) {
+ q = _PR_IOQ(me->cpu).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PRInt16 out_flags = 0;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) {
+ out_flags |= _PR_UNIX_POLL_READ;
+ }
+ if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) {
+ out_flags |= _PR_UNIX_POLL_WRITE;
+ }
+ if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
+ out_flags |= _PR_UNIX_POLL_EXCEPT;
+ }
+ pds->out_flags = out_flags;
+ if (out_flags) {
+ notify = PR_TRUE;
+ }
+ if (osfd > pq_max_osfd) {
+ pq_max_osfd = osfd;
+ }
+ }
+ if (notify == PR_TRUE) {
+ PRIntn pri;
+ PRThread *thred;
+
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
+
+ /*
+ * Decrement the count of descriptors for each desciptor/event
+ * because this I/O request is being removed from the
+ * ioq
+ */
+ pds = pq->pds;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & _PR_UNIX_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+
+ /*
+ * Because this thread can run on a different cpu right
+ * after being added to the run queue, do not dereference
+ * pq
+ */
+ thred = pq->thr;
+ _PR_THREAD_LOCK(thred);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = thred->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ if (pq->thr->flags & _PR_SUSPENDING) {
+ /*
+ * set thread state to SUSPENDED;
+ * a Resume operation on the thread
+ * will move it to the runQ
+ */
+ pq->thr->state = _PR_SUSPENDED;
+ _PR_MISCQ_LOCK(pq->thr->cpu);
+ _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu);
+ _PR_MISCQ_UNLOCK(pq->thr->cpu);
+ } else {
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ pq->thr->cpu = cpu;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ if (_pr_md_idle_cpus > 1)
+ _PR_MD_WAKEUP_WAITER(thred);
+ }
+ }
+ _PR_THREAD_UNLOCK(thred);
+ } else {
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ }
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) {
+ /*
+ * woken up by another thread; read all the data
+ * in the pipe to empty the pipe
+ */
+ while ((rv =
+ read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
+ == PIPE_BUF){
+ }
+ PR_ASSERT((rv > 0) ||
+ ((rv == -1) && (errno == EAGAIN)));
+ }
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+#ifdef IRIX
+ if ((me->cpu->id == 0) &&
+ (FD_ISSET(_pr_irix_primoridal_cpu_fd[0], rp))) {
+ if (_pr_irix_process_exit) {
+ /*
+ * process exit due to a call to PR_ProcessExit
+ */
+ prctl(PR_SETEXITSIG, SIGKILL);
+ _exit(_pr_irix_process_exit_code);
+ } else {
+ while ((rv = read(_pr_irix_primoridal_cpu_fd[0],
+ _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) {
+ }
+ PR_ASSERT(rv > 0);
+ }
+ }
+ if (me->cpu->id == 0) {
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_irix_primoridal_cpu_fd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0];
+ }
+#endif
+ }
+ } else if (nfd < 0) {
+ if (errno == EBADF) {
+ FindBadFDs();
+ } else {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
+ errno));
+ }
+ } else {
+ PR_ASSERT(nfd == 0);
+ /*
+ * compute the new value of _PR_IOQ_TIMEOUT
+ */
+ q = _PR_IOQ(me->cpu).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ _PRUnixPollDesc *pds = pq->pds;
+ _PRUnixPollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ if (pds->osfd > pq_max_osfd) {
+ pq_max_osfd = pds->osfd;
+ }
+ }
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) {
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0])
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+ }
+ }
+#endif /* _PR_USE_POLL */
+ _PR_MD_IOQ_UNLOCK();
+}
+
+void _MD_Wakeup_CPUs()
+{
+ PRInt32 rv, data;
+
+ data = 0;
+ rv = write(_pr_md_pipefd[1], &data, 1);
+
+ while ((rv < 0) && (errno == EAGAIN)) {
+ /*
+ * pipe full, read all data in pipe to empty it
+ */
+ while ((rv =
+ read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF))
+ == PIPE_BUF) {
+ }
+ PR_ASSERT((rv > 0) ||
+ ((rv == -1) && (errno == EAGAIN)));
+ rv = write(_pr_md_pipefd[1], &data, 1);
+ }
+}
+
+
+void _MD_InitCPUS()
+{
+ PRInt32 rv, flags;
+ PRThread *me = _MD_CURRENT_THREAD();
+
+ rv = pipe(_pr_md_pipefd);
+ PR_ASSERT(rv == 0);
+ _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0];
+#ifndef _PR_USE_POLL
+ FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu));
+#endif
+
+ flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0);
+ fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0);
+ fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK);
+}
+
+/*
+** Unix SIGALRM (clock) signal handler
+*/
+static void ClockInterruptHandler()
+{
+ int olderrno;
+ PRUintn pri;
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+ PRThread *me = _MD_CURRENT_THREAD();
+
+#ifdef SOLARIS
+ if (!me || _PR_IS_NATIVE_THREAD(me)) {
+ _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK;
+ return;
+ }
+#endif
+
+ if (_PR_MD_GET_INTSOFF() != 0) {
+ cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK;
+ return;
+ }
+ _PR_MD_SET_INTSOFF(1);
+
+ olderrno = errno;
+ _PR_ClockInterrupt();
+ errno = olderrno;
+
+ /*
+ ** If the interrupt wants a resched or if some other thread at
+ ** the same priority needs the cpu, reschedule.
+ */
+ pri = me->priority;
+ if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) {
+#ifdef _PR_NO_PREEMPT
+ cpu->resched = PR_TRUE;
+ if (pr_interruptSwitchHook) {
+ (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg);
+ }
+#else /* _PR_NO_PREEMPT */
+ /*
+ ** Re-enable unix interrupts (so that we can use
+ ** setjmp/longjmp for context switching without having to
+ ** worry about the signal state)
+ */
+ sigprocmask(SIG_SETMASK, &empty_set, 0);
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch"));
+
+ if(!(me->flags & _PR_IDLE_THREAD)) {
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_RUNNABLE;
+ me->cpu = cpu;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(me, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ _PR_THREAD_UNLOCK(me);
+ } else
+ me->state = _PR_RUNNABLE;
+ _MD_SWITCH_CONTEXT(me);
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch"));
+#endif /* _PR_NO_PREEMPT */
+ }
+ /*
+ * Because this thread could be running on a different cpu after
+ * a context switch the current cpu should be accessed and the
+ * value of the 'cpu' variable should not be used.
+ */
+ _PR_MD_SET_INTSOFF(0);
+}
+
+/*
+ * On HP-UX 9, we have to use the sigvector() interface to restart
+ * interrupted system calls, because sigaction() does not have the
+ * SA_RESTART flag.
+ */
+
+#ifdef HPUX9
+static void HPUX9_ClockInterruptHandler(
+ int sig,
+ int code,
+ struct sigcontext *scp)
+{
+ ClockInterruptHandler();
+ scp->sc_syscall_action = SIG_RESTART;
+}
+#endif /* HPUX9 */
+
+/* # of milliseconds per clock tick that we will use */
+#define MSEC_PER_TICK 50
+
+
+void _MD_StartInterrupts()
+{
+ char *eval;
+
+ if ((eval = getenv("NSPR_NOCLOCK")) != NULL) {
+ if (atoi(eval) == 0)
+ _nspr_noclock = 0;
+ else
+ _nspr_noclock = 1;
+ }
+
+#ifndef _PR_NO_CLOCK_TIMER
+ if (!_nspr_noclock) {
+ _MD_EnableClockInterrupts();
+ }
+#endif
+}
+
+void _MD_StopInterrupts()
+{
+ sigprocmask(SIG_BLOCK, &timer_set, 0);
+}
+
+void _MD_EnableClockInterrupts()
+{
+ struct itimerval itval;
+ extern PRUintn _pr_numCPU;
+#ifdef HPUX9
+ struct sigvec vec;
+
+ vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler;
+ vec.sv_mask = 0;
+ vec.sv_flags = 0;
+ sigvector(SIGALRM, &vec, 0);
+#else
+ struct sigaction vtact;
+
+ vtact.sa_handler = (void (*)()) ClockInterruptHandler;
+ sigemptyset(&vtact.sa_mask);
+ vtact.sa_flags = SA_RESTART;
+ sigaction(SIGALRM, &vtact, 0);
+#endif /* HPUX9 */
+
+ PR_ASSERT(_pr_numCPU == 1);
+ itval.it_interval.tv_sec = 0;
+ itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC;
+ itval.it_value = itval.it_interval;
+ setitimer(ITIMER_REAL, &itval, 0);
+}
+
+void _MD_DisableClockInterrupts()
+{
+ struct itimerval itval;
+ extern PRUintn _pr_numCPU;
+
+ PR_ASSERT(_pr_numCPU == 1);
+ itval.it_interval.tv_sec = 0;
+ itval.it_interval.tv_usec = 0;
+ itval.it_value = itval.it_interval;
+ setitimer(ITIMER_REAL, &itval, 0);
+}
+
+void _MD_BlockClockInterrupts()
+{
+ sigprocmask(SIG_BLOCK, &timer_set, 0);
+}
+
+void _MD_UnblockClockInterrupts()
+{
+ sigprocmask(SIG_UNBLOCK, &timer_set, 0);
+}
+
+void _MD_MakeNonblock(PRFileDesc *fd)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ int flags;
+
+ if (osfd <= 2) {
+ /* Don't mess around with stdin, stdout or stderr */
+ return;
+ }
+ flags = fcntl(osfd, F_GETFL, 0);
+
+ /*
+ * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible.
+ * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O),
+ * otherwise connect() still blocks and can be interrupted by SIGALRM.
+ */
+
+#ifdef SUNOS4
+ fcntl(osfd, F_SETFL, flags | FNDELAY);
+#else
+ fcntl(osfd, F_SETFL, flags | O_NONBLOCK);
+#endif
+ }
+
+PRInt32 _MD_open(const char *name, PRIntn flags, PRIntn mode)
+{
+ PRInt32 osflags;
+ PRInt32 rv, err;
+
+ if (flags & PR_RDWR) {
+ osflags = O_RDWR;
+ } else if (flags & PR_WRONLY) {
+ osflags = O_WRONLY;
+ } else {
+ osflags = O_RDONLY;
+ }
+
+ if (flags & PR_EXCL)
+ osflags |= O_EXCL;
+ if (flags & PR_APPEND)
+ osflags |= O_APPEND;
+ if (flags & PR_TRUNCATE)
+ osflags |= O_TRUNC;
+ if (flags & PR_SYNC) {
+#if defined(O_SYNC)
+ osflags |= O_SYNC;
+#elif defined(O_FSYNC)
+ osflags |= O_FSYNC;
+#else
+#error "Neither O_SYNC nor O_FSYNC is defined on this platform"
+#endif
+ }
+
+ /*
+ ** On creations we hold the 'create' lock in order to enforce
+ ** the semantics of PR_Rename. (see the latter for more details)
+ */
+ if (flags & PR_CREATE_FILE)
+ {
+ osflags |= O_CREAT;
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ }
+
+ rv = _md_iovector._open64(name, osflags, mode);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPEN_ERROR(err);
+ }
+
+ if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRIntervalTime intr_timeout_ticks;
+
+#if defined(SOLARIS) || defined(IRIX)
+static void sigsegvhandler() {
+ fprintf(stderr,"Received SIGSEGV\n");
+ fflush(stderr);
+ pause();
+}
+
+static void sigaborthandler() {
+ fprintf(stderr,"Received SIGABRT\n");
+ fflush(stderr);
+ pause();
+}
+
+static void sigbushandler() {
+ fprintf(stderr,"Received SIGBUS\n");
+ fflush(stderr);
+ pause();
+}
+#endif /* SOLARIS, IRIX */
+
+#endif /* !defined(_PR_PTHREADS) */
+
+void _MD_query_fd_inheritable(PRFileDesc *fd)
+{
+ int flags;
+
+ PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
+ flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
+ PR_ASSERT(-1 != flags);
+ fd->secret->inheritable = (flags & FD_CLOEXEC) ?
+ _PR_TRI_FALSE : _PR_TRI_TRUE;
+}
+
+PROffset32 _MD_lseek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
+{
+ PROffset32 rv, where;
+
+ switch (whence) {
+ case PR_SEEK_SET:
+ where = SEEK_SET;
+ break;
+ case PR_SEEK_CUR:
+ where = SEEK_CUR;
+ break;
+ case PR_SEEK_END:
+ where = SEEK_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ rv = lseek(fd->secret->md.osfd,offset,where);
+ if (rv == -1)
+ {
+ PRInt32 syserr = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(syserr);
+ }
+done:
+ return(rv);
+}
+
+PROffset64 _MD_lseek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
+{
+ PRInt32 where;
+ PROffset64 rv;
+
+ switch (whence)
+ {
+ case PR_SEEK_SET:
+ where = SEEK_SET;
+ break;
+ case PR_SEEK_CUR:
+ where = SEEK_CUR;
+ break;
+ case PR_SEEK_END:
+ where = SEEK_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = minus_one;
+ goto done;
+ }
+ rv = _md_iovector._lseek64(fd->secret->md.osfd, offset, where);
+ if (LL_EQ(rv, minus_one))
+ {
+ PRInt32 syserr = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(syserr);
+ }
+done:
+ return rv;
+} /* _MD_lseek64 */
+
+/*
+** _MD_set_fileinfo_times --
+** Set the modifyTime and creationTime of the PRFileInfo
+** structure using the values in struct stat.
+**
+** _MD_set_fileinfo64_times --
+** Set the modifyTime and creationTime of the PRFileInfo64
+** structure using the values in _MDStat64.
+*/
+
+#if defined(_PR_STAT_HAS_ST_ATIM)
+/*
+** struct stat has st_atim, st_mtim, and st_ctim fields of
+** type timestruc_t.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtim.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtim.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctim.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctim.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtim.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtim.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctim.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctim.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+#elif defined(_PR_STAT_HAS_ST_ATIM_UNION)
+/*
+** The st_atim, st_mtim, and st_ctim fields in struct stat are
+** unions with a st__tim union member of type timestruc_t.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+#elif defined(_PR_STAT_HAS_ST_ATIMESPEC)
+/*
+** struct stat has st_atimespec, st_mtimespec, and st_ctimespec
+** fields of type struct timespec.
+*/
+#if defined(_PR_TIMESPEC_HAS_TS_SEC)
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+#else /* _PR_TIMESPEC_HAS_TS_SEC */
+/*
+** The POSIX timespec structure has tv_sec and tv_nsec.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 us, s2us;
+
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec);
+ LL_MUL(info->modifyTime, info->modifyTime, s2us);
+ LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000);
+ LL_ADD(info->modifyTime, info->modifyTime, us);
+ LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec);
+ LL_MUL(info->creationTime, info->creationTime, s2us);
+ LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000);
+ LL_ADD(info->creationTime, info->creationTime, us);
+}
+#endif /* _PR_TIMESPEC_HAS_TS_SEC */
+#elif defined(_PR_STAT_HAS_ONLY_ST_ATIME)
+/*
+** struct stat only has st_atime, st_mtime, and st_ctime fields
+** of type time_t.
+*/
+static void _MD_set_fileinfo_times(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ PRInt64 s, s2us;
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, sb->st_mtime);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb->st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+}
+
+static void _MD_set_fileinfo64_times(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ PRInt64 s, s2us;
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, sb->st_mtime);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb->st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+}
+#else
+#error "I don't know yet"
+#endif
+
+static int _MD_convert_stat_to_fileinfo(
+ const struct stat *sb,
+ PRFileInfo *info)
+{
+ if (S_IFREG & sb->st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb->st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+#if defined(_PR_HAVE_LARGE_OFF_T)
+ if (0x7fffffffL < sb->st_size)
+ {
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
+ return -1;
+ }
+#endif /* defined(_PR_HAVE_LARGE_OFF_T) */
+ info->size = sb->st_size;
+
+ _MD_set_fileinfo_times(sb, info);
+ return 0;
+} /* _MD_convert_stat_to_fileinfo */
+
+static int _MD_convert_stat64_to_fileinfo64(
+ const _MDStat64 *sb,
+ PRFileInfo64 *info)
+{
+ if (S_IFREG & sb->st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb->st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+ LL_I2L(info->size, sb->st_size);
+
+ _MD_set_fileinfo64_times(sb, info);
+ return 0;
+} /* _MD_convert_stat64_to_fileinfo64 */
+
+PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info)
+{
+ PRInt32 rv;
+ struct stat sb;
+
+ rv = stat(fn, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat_to_fileinfo(&sb, info);
+ return rv;
+}
+
+PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info)
+{
+ _MDStat64 sb;
+ PRInt32 rv = _md_iovector._stat64(fn, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_STAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
+ return rv;
+}
+
+PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info)
+{
+ struct stat sb;
+ PRInt32 rv = fstat(fd->secret->md.osfd, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat_to_fileinfo(&sb, info);
+ return rv;
+}
+
+PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ _MDStat64 sb;
+ PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb);
+ if (rv < 0)
+ _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO());
+ else if (NULL != info)
+ rv = _MD_convert_stat64_to_fileinfo64(&sb, info);
+ return rv;
+}
+
+struct _MD_IOVector _md_iovector = { open };
+
+/*
+** These implementations are to emulate large file routines on systems that
+** don't have them. Their goal is to check in case overflow occurs. Otherwise
+** they will just operate as normal using 32-bit file routines.
+**
+** The checking might be pre- or post-op, depending on the semantics.
+*/
+
+#if defined(SOLARIS2_5)
+
+static PRIntn _MD_solaris25_fstat64(PRIntn osfd, _MDStat64 *buf)
+{
+ PRInt32 rv;
+ struct stat sb;
+
+ rv = fstat(osfd, &sb);
+ if (rv >= 0)
+ {
+ /*
+ ** I'm only copying the fields that are immediately needed.
+ ** If somebody else calls this function, some of the fields
+ ** may not be defined.
+ */
+ (void)memset(buf, 0, sizeof(_MDStat64));
+ buf->st_mode = sb.st_mode;
+ buf->st_ctim = sb.st_ctim;
+ buf->st_mtim = sb.st_mtim;
+ buf->st_size = sb.st_size;
+ }
+ return rv;
+} /* _MD_solaris25_fstat64 */
+
+static PRIntn _MD_solaris25_stat64(const char *fn, _MDStat64 *buf)
+{
+ PRInt32 rv;
+ struct stat sb;
+
+ rv = stat(fn, &sb);
+ if (rv >= 0)
+ {
+ /*
+ ** I'm only copying the fields that are immediately needed.
+ ** If somebody else calls this function, some of the fields
+ ** may not be defined.
+ */
+ (void)memset(buf, 0, sizeof(_MDStat64));
+ buf->st_mode = sb.st_mode;
+ buf->st_ctim = sb.st_ctim;
+ buf->st_mtim = sb.st_mtim;
+ buf->st_size = sb.st_size;
+ }
+ return rv;
+} /* _MD_solaris25_stat64 */
+#endif /* defined(SOLARIS2_5) */
+
+#if defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5)
+
+static PROffset64 _MD_Unix_lseek64(PRIntn osfd, PROffset64 offset, PRIntn whence)
+{
+ PRUint64 maxoff;
+ PROffset64 rv = minus_one;
+ LL_I2L(maxoff, 0x7fffffff);
+ if (LL_CMP(offset, <=, maxoff))
+ {
+ off_t off;
+ LL_L2I(off, offset);
+ LL_I2L(rv, lseek(osfd, off, whence));
+ }
+ else errno = EFBIG; /* we can't go there */
+ return rv;
+} /* _MD_Unix_lseek64 */
+
+static void* _MD_Unix_mmap64(
+ void *addr, PRSize len, PRIntn prot, PRIntn flags,
+ PRIntn fildes, PRInt64 offset)
+{
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
+ return NULL;
+} /* _MD_Unix_mmap64 */
+#endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */
+
+#if defined(OSF1) && defined(__GNUC__)
+
+/*
+ * On OSF1 V5.0A, <sys/stat.h> defines stat and fstat as
+ * macros when compiled under gcc, so it is rather tricky to
+ * take the addresses of the real functions the macros expend
+ * to. A simple solution is to define forwarder functions
+ * and take the addresses of the forwarder functions instead.
+ */
+
+static int stat_forwarder(const char *path, struct stat *buffer)
+{
+ return stat(path, buffer);
+}
+
+static int fstat_forwarder(int filedes, struct stat *buffer)
+{
+ return fstat(filedes, buffer);
+}
+
+#endif
+
+static void _PR_InitIOV(void)
+{
+#if defined(SOLARIS2_5)
+ PRLibrary *lib;
+ void *open64_func;
+
+ open64_func = PR_FindSymbolAndLibrary("open64", &lib);
+ if (NULL != open64_func)
+ {
+ PR_ASSERT(NULL != lib);
+ _md_iovector._open64 = (_MD_Open64)open64_func;
+ _md_iovector._mmap64 = (_MD_Mmap64)PR_FindSymbol(lib, "mmap64");
+ _md_iovector._fstat64 = (_MD_Fstat64)PR_FindSymbol(lib, "fstat64");
+ _md_iovector._stat64 = (_MD_Stat64)PR_FindSymbol(lib, "stat64");
+ _md_iovector._lseek64 = (_MD_Lseek64)PR_FindSymbol(lib, "lseek64");
+ (void)PR_UnloadLibrary(lib);
+ }
+ else
+ {
+ _md_iovector._open64 = open;
+ _md_iovector._mmap64 = _MD_Unix_mmap64;
+ _md_iovector._fstat64 = _MD_solaris25_fstat64;
+ _md_iovector._stat64 = _MD_solaris25_stat64;
+ _md_iovector._lseek64 = _MD_Unix_lseek64;
+ }
+#elif defined(_PR_NO_LARGE_FILES)
+ _md_iovector._open64 = open;
+ _md_iovector._mmap64 = _MD_Unix_mmap64;
+ _md_iovector._fstat64 = fstat;
+ _md_iovector._stat64 = stat;
+ _md_iovector._lseek64 = _MD_Unix_lseek64;
+#elif defined(_PR_HAVE_OFF64_T)
+#if defined(IRIX5_3)
+ _md_iovector._open64 = open;
+#else
+ _md_iovector._open64 = open64;
+#endif
+ _md_iovector._mmap64 = mmap64;
+ _md_iovector._fstat64 = fstat64;
+ _md_iovector._stat64 = stat64;
+ _md_iovector._lseek64 = lseek64;
+#elif defined(_PR_HAVE_LARGE_OFF_T)
+ _md_iovector._open64 = open;
+ _md_iovector._mmap64 = mmap;
+#if defined(OSF1) && defined(__GNUC__)
+ _md_iovector._fstat64 = fstat_forwarder;
+ _md_iovector._stat64 = stat_forwarder;
+#else
+ _md_iovector._fstat64 = fstat;
+ _md_iovector._stat64 = stat;
+#endif
+ _md_iovector._lseek64 = lseek;
+#else
+#error "I don't know yet"
+#endif
+ LL_I2L(minus_one, -1);
+} /* _PR_InitIOV */
+
+void _PR_UnixInit(void)
+{
+ struct sigaction sigact;
+ int rv;
+
+ sigemptyset(&timer_set);
+
+#if !defined(_PR_PTHREADS)
+
+ sigaddset(&timer_set, SIGALRM);
+ sigemptyset(&empty_set);
+ intr_timeout_ticks =
+ PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS);
+
+#if defined(SOLARIS) || defined(IRIX)
+
+ if (getenv("NSPR_SIGSEGV_HANDLE")) {
+ sigact.sa_handler = sigsegvhandler;
+ sigact.sa_flags = 0;
+ sigact.sa_mask = timer_set;
+ sigaction(SIGSEGV, &sigact, 0);
+ }
+
+ if (getenv("NSPR_SIGABRT_HANDLE")) {
+ sigact.sa_handler = sigaborthandler;
+ sigact.sa_flags = 0;
+ sigact.sa_mask = timer_set;
+ sigaction(SIGABRT, &sigact, 0);
+ }
+
+ if (getenv("NSPR_SIGBUS_HANDLE")) {
+ sigact.sa_handler = sigbushandler;
+ sigact.sa_flags = 0;
+ sigact.sa_mask = timer_set;
+ sigaction(SIGBUS, &sigact, 0);
+ }
+
+#endif
+#endif /* !defined(_PR_PTHREADS) */
+
+ /*
+ * Under HP-UX DCE threads, sigaction() installs a per-thread
+ * handler, so we use sigvector() to install a process-wide
+ * handler.
+ */
+#if defined(HPUX) && defined(_PR_DCETHREADS)
+ {
+ struct sigvec vec;
+
+ vec.sv_handler = SIG_IGN;
+ vec.sv_mask = 0;
+ vec.sv_flags = 0;
+ rv = sigvector(SIGPIPE, &vec, NULL);
+ PR_ASSERT(0 == rv);
+ }
+#else
+ sigact.sa_handler = SIG_IGN;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ rv = sigaction(SIGPIPE, &sigact, 0);
+ PR_ASSERT(0 == rv);
+#endif /* HPUX && _PR_DCETHREADS */
+
+ _pr_rename_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_rename_lock);
+ _pr_Xfe_mon = PR_NewMonitor();
+ PR_ASSERT(NULL != _pr_Xfe_mon);
+#ifdef VBOX
+ RTMEM_MAY_LEAK(_pr_rename_lock);
+ RTMEM_MAY_LEAK(_pr_Xfe_mon);
+#endif
+
+ _PR_InitIOV(); /* one last hack */
+}
+
+#if !defined(_PR_PTHREADS)
+
+/*
+ * Variables used by the GC code, initialized in _MD_InitSegs().
+ */
+static PRInt32 _pr_zero_fd = -1;
+static PRLock *_pr_md_lock = NULL;
+
+/*
+ * _MD_InitSegs --
+ *
+ * This is Unix's version of _PR_MD_INIT_SEGS(), which is
+ * called by _PR_InitSegs(), which in turn is called by
+ * PR_Init().
+ */
+void _MD_InitSegs(void)
+{
+#ifdef DEBUG
+ /*
+ ** Disable using mmap(2) if NSPR_NO_MMAP is set
+ */
+ if (getenv("NSPR_NO_MMAP")) {
+ _pr_zero_fd = -2;
+ return;
+ }
+#endif
+ _pr_zero_fd = open("/dev/zero",O_RDWR , 0);
+ /* Prevent the fd from being inherited by child processes */
+ fcntl(_pr_zero_fd, F_SETFD, FD_CLOEXEC);
+ _pr_md_lock = PR_NewLock();
+}
+
+PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
+{
+ static char *lastaddr = (char*) _PR_STACK_VMBASE;
+ PRStatus retval = PR_SUCCESS;
+ int prot;
+ void *rv;
+
+ PR_ASSERT(seg != 0);
+ PR_ASSERT(size != 0);
+
+ PR_Lock(_pr_md_lock);
+ if (_pr_zero_fd < 0) {
+from_heap:
+ seg->vaddr = PR_MALLOC(size);
+ if (!seg->vaddr) {
+ retval = PR_FAILURE;
+ }
+ else {
+ seg->size = size;
+ }
+ goto exit;
+ }
+
+ prot = PROT_READ|PROT_WRITE;
+ /*
+ * On Alpha Linux, the user-level thread stack needs
+ * to be made executable because longjmp/signal seem
+ * to put machine instructions on the stack.
+ */
+#if defined(LINUX) && defined(__alpha)
+ prot |= PROT_EXEC;
+#endif
+ rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot,
+ _MD_MMAP_FLAGS,
+ _pr_zero_fd, 0);
+ if (rv == (void*)-1) {
+ goto from_heap;
+ }
+ lastaddr += size;
+ seg->vaddr = rv;
+ seg->size = size;
+ seg->flags = _PR_SEG_VM;
+
+exit:
+ PR_Unlock(_pr_md_lock);
+ return retval;
+}
+
+void _MD_FreeSegment(PRSegment *seg)
+{
+ if (seg->flags & _PR_SEG_VM)
+ (void) munmap(seg->vaddr, seg->size);
+ else
+ PR_DELETE(seg->vaddr);
+}
+
+#endif /* _PR_PTHREADS */
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the Unix
+ * implementation.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTime)
+PR_Now(void)
+{
+ struct timeval tv;
+ PRInt64 s, us, s2us;
+
+ GETTIMEOFDAY(&tv);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, tv.tv_sec);
+ LL_I2L(us, tv.tv_usec);
+ LL_MUL(s, s, s2us);
+ LL_ADD(s, s, us);
+ return s;
+}
+
+PRIntervalTime _PR_UNIX_GetInterval()
+{
+ struct timeval time;
+ PRIntervalTime ticks;
+
+ (void)GETTIMEOFDAY(&time); /* fallicy of course */
+ ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
+ ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
+ return ticks;
+} /* _PR_SUNOS_GetInterval */
+
+PRIntervalTime _PR_UNIX_TicksPerSecond()
+{
+ return 1000; /* this needs some work :) */
+}
+
+#if !defined(_PR_PTHREADS)
+/*
+ * Wait for I/O on multiple descriptors.
+ *
+ * Return 0 if timed out, return -1 if interrupted,
+ * else return the number of ready descriptors.
+ */
+PRInt32 _PR_WaitForMultipleFDs(
+ _PRUnixPollDesc *unixpds,
+ PRInt32 pdcnt,
+ PRIntervalTime timeout)
+{
+ PRPollQueue pq;
+ PRIntn is;
+ PRInt32 rv;
+ _PRCPU *io_cpu;
+ _PRUnixPollDesc *unixpd, *eunixpd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ pq.pds = unixpds;
+ pq.npds = pdcnt;
+
+ _PR_INTSOFF(is);
+ _PR_MD_IOQ_LOCK();
+ _PR_THREAD_LOCK(me);
+
+ pq.thr = me;
+ io_cpu = me->cpu;
+ pq.on_ioq = PR_TRUE;
+ pq.timeout = timeout;
+ _PR_ADD_TO_IOQ(pq, me->cpu);
+
+#if !defined(_PR_USE_POLL)
+ eunixpd = unixpds + pdcnt;
+ for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
+ PRInt32 osfd = unixpd->osfd;
+ if (unixpd->in_flags & _PR_UNIX_POLL_READ) {
+ FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
+ _PR_FD_READ_CNT(me->cpu)[osfd]++;
+ }
+ if (unixpd->in_flags & _PR_UNIX_POLL_WRITE) {
+ FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
+ }
+ if (unixpd->in_flags & _PR_UNIX_POLL_EXCEPT) {
+ FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
+ }
+ if (osfd > _PR_IOQ_MAX_OSFD(me->cpu)) {
+ _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
+ }
+ }
+#endif /* !defined(_PR_USE_POLL) */
+
+ if (_PR_IOQ_TIMEOUT(me->cpu) > timeout) {
+ _PR_IOQ_TIMEOUT(me->cpu) = timeout;
+ }
+
+ _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt;
+
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, timeout);
+ me->state = _PR_IO_WAIT;
+ me->io_pending = PR_TRUE;
+ me->io_suspended = PR_FALSE;
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_IOQ_UNLOCK();
+
+ _PR_MD_WAIT(me, timeout);
+
+ me->io_pending = PR_FALSE;
+ me->io_suspended = PR_FALSE;
+
+ /*
+ * This thread should run on the same cpu on which it was blocked; when
+ * the IO request times out the fd sets and fd counts for the
+ * cpu are updated below.
+ */
+ PR_ASSERT(me->cpu == io_cpu);
+
+ /*
+ ** If we timed out the pollq might still be on the ioq. Remove it
+ ** before continuing.
+ */
+ if (pq.on_ioq) {
+ _PR_MD_IOQ_LOCK();
+ /*
+ * Need to check pq.on_ioq again
+ */
+ if (pq.on_ioq) {
+ PR_REMOVE_LINK(&pq.links);
+#ifndef _PR_USE_POLL
+ eunixpd = unixpds + pdcnt;
+ for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
+ PRInt32 osfd = unixpd->osfd;
+ PRInt16 in_flags = unixpd->in_flags;
+
+ if (in_flags & _PR_UNIX_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+#endif /* _PR_USE_POLL */
+ PR_ASSERT(pq.npds == pdcnt);
+ _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt;
+ PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0);
+ }
+ _PR_MD_IOQ_UNLOCK();
+ }
+ /* XXX Should we use _PR_FAST_INTSON or _PR_INTSON? */
+ if (1 == pdcnt) {
+ _PR_FAST_INTSON(is);
+ } else {
+ _PR_INTSON(is);
+ }
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ rv = 0;
+ if (pq.on_ioq == PR_FALSE) {
+ /* Count the number of ready descriptors */
+ while (--pdcnt >= 0) {
+ if (unixpds->out_flags != 0) {
+ rv++;
+ }
+ unixpds++;
+ }
+ }
+
+ return rv;
+}
+
+/*
+ * Unblock threads waiting for I/O
+ * used when interrupting threads
+ *
+ * NOTE: The thread lock should held when this function is called.
+ * On return, the thread lock is released.
+ */
+void _PR_Unblock_IO_Wait(PRThread *thr)
+{
+ int pri = thr->priority;
+ _PRCPU *cpu = thr->cpu;
+
+ /*
+ * GLOBAL threads wakeup periodically to check for interrupt
+ */
+ if (_PR_IS_NATIVE_THREAD(thr)) {
+ _PR_THREAD_UNLOCK(thr);
+ return;
+ }
+
+ PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
+ _PR_SLEEPQ_LOCK(cpu);
+ _PR_DEL_SLEEPQ(thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(cpu);
+
+ PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
+ thr->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ _PR_THREAD_UNLOCK(thr);
+ _PR_MD_WAKEUP_WAITER(thr);
+}
+#endif /* !defined(_PR_PTHREADS) */
+
+/*
+ * When a nonblocking connect has completed, determine whether it
+ * succeeded or failed, and if it failed, what the error code is.
+ *
+ * The function returns the error code. An error code of 0 means
+ * that the nonblocking connect succeeded.
+ */
+
+int _MD_unix_get_nonblocking_connect_error(int osfd)
+{
+#if defined(NTO)
+ /* Neutrino does not support the SO_ERROR socket option */
+ PRInt32 rv;
+ PRNetAddr addr;
+ _PRSockLen_t addrlen = sizeof(addr);
+
+ /* Test to see if we are using the Tiny TCP/IP Stack or the Full one. */
+ struct statvfs superblock;
+ rv = fstatvfs(osfd, &superblock);
+ if (rv == 0) {
+ if (strcmp(superblock.f_basetype, "ttcpip") == 0) {
+ /* Using the Tiny Stack! */
+ rv = getpeername(osfd, (struct sockaddr *) &addr,
+ (_PRSockLen_t *) &addrlen);
+ if (rv == -1) {
+ int errno_copy = errno; /* make a copy so I don't
+ * accidentally reset */
+
+ if (errno_copy == ENOTCONN) {
+ struct stat StatInfo;
+ rv = fstat(osfd, &StatInfo);
+ if (rv == 0) {
+ time_t current_time = time(NULL);
+
+ /*
+ * this is a real hack, can't explain why it
+ * works it just does
+ */
+ if (abs(current_time - StatInfo.st_atime) < 5) {
+ return ECONNREFUSED;
+ } else {
+ return ETIMEDOUT;
+ }
+ } else {
+ return ECONNREFUSED;
+ }
+ } else {
+ return errno_copy;
+ }
+ } else {
+ /* No Error */
+ return 0;
+ }
+ } else {
+ /* Have the FULL Stack which supports SO_ERROR */
+ /* Hasn't been written yet, never been tested! */
+ /* Jerry.Kirk@Nexwarecorp.com */
+
+ int err;
+ _PRSockLen_t optlen = sizeof(err);
+
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
+ (char *) &err, &optlen) == -1) {
+ return errno;
+ } else {
+ return err;
+ }
+ }
+ } else {
+ return ECONNREFUSED;
+ }
+#elif defined(NCR) || defined(UNIXWARE) || defined(SNI) || defined(NEC)
+ /*
+ * getsockopt() fails with EPIPE, so use getmsg() instead.
+ */
+
+ int rv;
+ int flags = 0;
+ rv = getmsg(osfd, NULL, NULL, &flags);
+ PR_ASSERT(-1 == rv || 0 == rv);
+ if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
+ return errno;
+ }
+ return 0; /* no error */
+#else
+ int err;
+ _PRSockLen_t optlen = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) {
+ return errno;
+ } else {
+ return err;
+ }
+#endif
+}
+
+/************************************************************************/
+
+/*
+** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
+** safe. Unfortunately, neither is mozilla. To make these programs work
+** in a pre-emptive threaded environment, we need to use a lock.
+*/
+
+void PR_XLock(void)
+{
+ PR_EnterMonitor(_pr_Xfe_mon);
+}
+
+void PR_XUnlock(void)
+{
+ PR_ExitMonitor(_pr_Xfe_mon);
+}
+
+PRBool PR_XIsLocked(void)
+{
+ return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
+}
+
+void PR_XWait(int ms)
+{
+ PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
+}
+
+void PR_XNotify(void)
+{
+ PR_Notify(_pr_Xfe_mon);
+}
+
+void PR_XNotifyAll(void)
+{
+ PR_NotifyAll(_pr_Xfe_mon);
+}
+
+#if defined(HAVE_FCNTL_FILE_LOCKING)
+
+PR_IMPLEMENT(PRStatus)
+_MD_LockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ struct flock arg;
+
+ arg.l_type = F_WRLCK;
+ arg.l_whence = SEEK_SET;
+ arg.l_start = 0;
+ arg.l_len = 0; /* until EOF */
+ rv = fcntl(f, F_SETLKW, &arg);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ struct flock arg;
+
+ arg.l_type = F_WRLCK;
+ arg.l_whence = SEEK_SET;
+ arg.l_start = 0;
+ arg.l_len = 0; /* until EOF */
+ rv = fcntl(f, F_SETLK, &arg);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UnlockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ struct flock arg;
+
+ arg.l_type = F_UNLCK;
+ arg.l_whence = SEEK_SET;
+ arg.l_start = 0;
+ arg.l_len = 0; /* until EOF */
+ rv = fcntl(f, F_SETLK, &arg);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+#elif defined(HAVE_BSD_FLOCK)
+
+#include <sys/file.h>
+
+PR_IMPLEMENT(PRStatus)
+_MD_LockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX|LOCK_NB);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UnlockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_UN);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+#else
+
+PR_IMPLEMENT(PRStatus)
+_MD_LockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_LOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_TLOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UnlockFile(PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_ULOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+#endif
+
+PR_IMPLEMENT(PRStatus) _MD_gethostname(char *name, PRUint32 namelen)
+{
+ PRIntn rv;
+
+ rv = gethostname(name, namelen);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ }
+ _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus) _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen)
+{
+ struct utsname info;
+
+ PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE));
+
+ if (uname(&info) == -1) {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ if (PR_SI_SYSNAME == cmd)
+ (void)PR_snprintf(name, namelen, info.sysname);
+ else if (PR_SI_RELEASE == cmd)
+ (void)PR_snprintf(name, namelen, info.release);
+ else
+ return PR_FAILURE;
+ return PR_SUCCESS;
+}
+
+/*
+ *******************************************************************
+ *
+ * Memory-mapped files
+ *
+ *******************************************************************
+ */
+
+PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
+{
+ PRFileInfo info;
+ PRUint32 sz;
+
+ LL_L2UI(sz, size);
+ if (sz) {
+ if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) {
+ return PR_FAILURE;
+ }
+ if (sz > info.size) {
+ /*
+ * Need to extend the file
+ */
+ if (fmap->prot != PR_PROT_READWRITE) {
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (PR_Seek(fmap->fd, sz - 1, PR_SEEK_SET) == -1) {
+ return PR_FAILURE;
+ }
+ if (PR_Write(fmap->fd, "", 1) != 1) {
+ return PR_FAILURE;
+ }
+ }
+ }
+ if (fmap->prot == PR_PROT_READONLY) {
+ fmap->md.prot = PROT_READ;
+#ifdef OSF1V4_MAP_PRIVATE_BUG
+ /*
+ * Use MAP_SHARED to work around a bug in OSF1 V4.0D
+ * (QAR 70220 in the OSF_QAR database) that results in
+ * corrupted data in the memory-mapped region. This
+ * bug is fixed in V5.0.
+ */
+ fmap->md.flags = MAP_SHARED;
+#else
+ fmap->md.flags = MAP_PRIVATE;
+#endif
+ } else if (fmap->prot == PR_PROT_READWRITE) {
+ fmap->md.prot = PROT_READ | PROT_WRITE;
+ fmap->md.flags = MAP_SHARED;
+ } else {
+ PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
+ fmap->md.prot = PROT_READ | PROT_WRITE;
+ fmap->md.flags = MAP_PRIVATE;
+ }
+ return PR_SUCCESS;
+}
+
+void * _MD_MemMap(
+ PRFileMap *fmap,
+ PRInt64 offset,
+ PRUint32 len)
+{
+ PRInt32 off;
+ void *addr;
+
+ LL_L2I(off, offset);
+ if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags,
+ fmap->fd->secret->md.osfd, off)) == (void *) -1) {
+ _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO());
+ addr = NULL;
+ }
+ return addr;
+}
+
+PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
+{
+ if (munmap(addr, len) == 0) {
+ return PR_SUCCESS;
+ } else {
+ if (errno == EINVAL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, errno);
+ }
+ return PR_FAILURE;
+ }
+}
+
+PRStatus _MD_CloseFileMap(PRFileMap *fmap)
+{
+ if ( PR_TRUE == fmap->md.isAnonFM ) {
+ PRStatus rc = PR_Close( fmap->fd );
+ if ( PR_FAILURE == rc ) {
+ PR_LOG( _pr_io_lm, PR_LOG_DEBUG,
+ ("_MD_CloseFileMap(): error closing anonymnous file map osfd"));
+ return PR_FAILURE;
+ }
+ }
+ PR_DELETE(fmap);
+ return PR_SUCCESS;
+}
+
+#if defined(_PR_NEED_FAKE_POLL)
+
+/*
+ * Some platforms don't have poll(). For easier porting of code
+ * that calls poll(), we emulate poll() using select().
+ */
+
+int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
+{
+ int i;
+ int rv;
+ int maxfd;
+ fd_set rd, wr, ex;
+ struct timeval tv, *tvp;
+
+ if (timeout < 0 && timeout != -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (timeout == -1) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tvp = &tv;
+ }
+
+ maxfd = -1;
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+
+ for (i = 0; i < nfds; i++) {
+ int osfd = filedes[i].fd;
+ int events = filedes[i].events;
+ PRBool fdHasEvent = PR_FALSE;
+
+ if (osfd < 0) {
+ continue; /* Skip this osfd. */
+ }
+
+ /*
+ * Map the poll events to the select fd_sets.
+ * POLLIN, POLLRDNORM ===> readable
+ * POLLOUT, POLLWRNORM ===> writable
+ * POLLPRI, POLLRDBAND ===> exception
+ * POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
+ * are ignored.
+ *
+ * The output events POLLERR and POLLHUP are never turned on.
+ * POLLNVAL may be turned on.
+ */
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ FD_SET(osfd, &rd);
+ fdHasEvent = PR_TRUE;
+ }
+ if (events & (POLLOUT | POLLWRNORM)) {
+ FD_SET(osfd, &wr);
+ fdHasEvent = PR_TRUE;
+ }
+ if (events & (POLLPRI | POLLRDBAND)) {
+ FD_SET(osfd, &ex);
+ fdHasEvent = PR_TRUE;
+ }
+ if (fdHasEvent && osfd > maxfd) {
+ maxfd = osfd;
+ }
+ }
+
+ rv = select(maxfd + 1, &rd, &wr, &ex, tvp);
+
+ /* Compute poll results */
+ if (rv > 0) {
+ rv = 0;
+ for (i = 0; i < nfds; i++) {
+ PRBool fdHasEvent = PR_FALSE;
+
+ filedes[i].revents = 0;
+ if (filedes[i].fd < 0) {
+ continue;
+ }
+ if (FD_ISSET(filedes[i].fd, &rd)) {
+ if (filedes[i].events & POLLIN) {
+ filedes[i].revents |= POLLIN;
+ }
+ if (filedes[i].events & POLLRDNORM) {
+ filedes[i].revents |= POLLRDNORM;
+ }
+ fdHasEvent = PR_TRUE;
+ }
+ if (FD_ISSET(filedes[i].fd, &wr)) {
+ if (filedes[i].events & POLLOUT) {
+ filedes[i].revents |= POLLOUT;
+ }
+ if (filedes[i].events & POLLWRNORM) {
+ filedes[i].revents |= POLLWRNORM;
+ }
+ fdHasEvent = PR_TRUE;
+ }
+ if (FD_ISSET(filedes[i].fd, &ex)) {
+ if (filedes[i].events & POLLPRI) {
+ filedes[i].revents |= POLLPRI;
+ }
+ if (filedes[i].events & POLLRDBAND) {
+ filedes[i].revents |= POLLRDBAND;
+ }
+ fdHasEvent = PR_TRUE;
+ }
+ if (fdHasEvent) {
+ rv++;
+ }
+ }
+ PR_ASSERT(rv > 0);
+ } else if (rv == -1 && errno == EBADF) {
+ rv = 0;
+ for (i = 0; i < nfds; i++) {
+ filedes[i].revents = 0;
+ if (filedes[i].fd < 0) {
+ continue;
+ }
+ if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) {
+ filedes[i].revents = POLLNVAL;
+ rv++;
+ }
+ }
+ PR_ASSERT(rv > 0);
+ }
+ PR_ASSERT(-1 != timeout || rv != 0);
+
+ return rv;
+}
+#endif /* _PR_NEED_FAKE_POLL */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix_errors.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix_errors.c
new file mode 100644
index 00000000..0facbae5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unix_errors.c
@@ -0,0 +1,862 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#if defined(_PR_POLL_AVAILABLE)
+#include <poll.h>
+#endif
+#include <errno.h>
+
+void _MD_unix_map_default_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err ) {
+ case EACCES:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case EADDRINUSE:
+ prError = PR_ADDRESS_IN_USE_ERROR;
+ break;
+ case EADDRNOTAVAIL:
+ prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
+ break;
+ case EAFNOSUPPORT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case EAGAIN:
+ prError = PR_WOULD_BLOCK_ERROR;
+ break;
+ /*
+ * On QNX and Neutrino, EALREADY is defined as EBUSY.
+ */
+#if EALREADY != EBUSY
+ case EALREADY:
+ prError = PR_ALREADY_INITIATED_ERROR;
+ break;
+#endif
+ case EBADF:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+#ifdef EBADMSG
+ case EBADMSG:
+ prError = PR_IO_ERROR;
+ break;
+#endif
+ case EBUSY:
+ prError = PR_FILESYSTEM_MOUNTED_ERROR;
+ break;
+ case ECONNABORTED:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case ECONNREFUSED:
+ prError = PR_CONNECT_REFUSED_ERROR;
+ break;
+ case ECONNRESET:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+ case EDEADLK:
+ prError = PR_DEADLOCK_ERROR;
+ break;
+#ifdef EDIRCORRUPTED
+ case EDIRCORRUPTED:
+ prError = PR_DIRECTORY_CORRUPTED_ERROR;
+ break;
+#endif
+#ifdef EDQUOT
+ case EDQUOT:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+#endif
+ case EEXIST:
+ prError = PR_FILE_EXISTS_ERROR;
+ break;
+ case EFAULT:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case EFBIG:
+ prError = PR_FILE_TOO_BIG_ERROR;
+ break;
+ case EHOSTUNREACH:
+ prError = PR_HOST_UNREACHABLE_ERROR;
+ break;
+ case EINPROGRESS:
+ prError = PR_IN_PROGRESS_ERROR;
+ break;
+ case EINTR:
+ prError = PR_PENDING_INTERRUPT_ERROR;
+ break;
+ case EINVAL:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case EIO:
+ prError = PR_IO_ERROR;
+ break;
+ case EISCONN:
+ prError = PR_IS_CONNECTED_ERROR;
+ break;
+ case EISDIR:
+ prError = PR_IS_DIRECTORY_ERROR;
+ break;
+ case ELOOP:
+ prError = PR_LOOP_ERROR;
+ break;
+ case EMFILE:
+ prError = PR_PROC_DESC_TABLE_FULL_ERROR;
+ break;
+ case EMLINK:
+ prError = PR_MAX_DIRECTORY_ENTRIES_ERROR;
+ break;
+ case EMSGSIZE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+#ifdef EMULTIHOP
+ case EMULTIHOP:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+#endif
+ case ENAMETOOLONG:
+ prError = PR_NAME_TOO_LONG_ERROR;
+ break;
+ case ENETUNREACH:
+ prError = PR_NETWORK_UNREACHABLE_ERROR;
+ break;
+ case ENFILE:
+ prError = PR_SYS_DESC_TABLE_FULL_ERROR;
+ break;
+ /*
+ * On SCO OpenServer 5, ENOBUFS is defined as ENOSR.
+ */
+#if defined(ENOBUFS) && (ENOBUFS != ENOSR)
+ case ENOBUFS:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+#endif
+ case ENODEV:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ENOLCK:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+#endif
+ case ENOMEM:
+ prError = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case ENOPROTOOPT:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ENOSPC:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+#endif
+ case ENOTCONN:
+ prError = PR_NOT_CONNECTED_ERROR;
+ break;
+ case ENOTDIR:
+ prError = PR_NOT_DIRECTORY_ERROR;
+ break;
+ case ENOTSOCK:
+ prError = PR_NOT_SOCKET_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case EOPNOTSUPP:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+#endif
+ case EPERM:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case EPIPE:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+#ifdef EPROTO
+ case EPROTO:
+ prError = PR_IO_ERROR;
+ break;
+#endif
+ case EPROTONOSUPPORT:
+ prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
+ break;
+ case EPROTOTYPE:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ERANGE:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case EROFS:
+ prError = PR_READ_ONLY_FILESYSTEM_ERROR;
+ break;
+ case ESPIPE:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_IO_TIMEOUT_ERROR;
+ break;
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+ prError = PR_WOULD_BLOCK_ERROR;
+ break;
+#endif
+ case EXDEV:
+ prError = PR_NOT_SAME_DEVICE_ERROR;
+ break;
+ default:
+ prError = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_opendir_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_closedir_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_readdir_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ENOENT:
+ prError = PR_NO_MORE_FILES_ERROR;
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ prError = PR_IO_ERROR;
+ break;
+#endif
+ case EINVAL:
+ prError = PR_IO_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_IO_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_unlink_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EPERM:
+ prError = PR_IS_DIRECTORY_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_stat_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_fstat_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_rename_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EEXIST:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_access_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_mkdir_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_rmdir_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ /*
+ * On AIX 4.3, ENOTEMPTY is defined as EEXIST.
+ */
+#if ENOTEMPTY != EEXIST
+ case ENOTEMPTY:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+#endif
+ case EEXIST:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+ case EINVAL:
+ prError = PR_DIRECTORY_NOT_EMPTY_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_read_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_write_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_lseek_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_fsync_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ case EINVAL:
+ prError = PR_INVALID_METHOD_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_close_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_socket_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_socketavailable_error(int err)
+{
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+}
+
+void _MD_unix_map_recv_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_recvfrom_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_send_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_sendto_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_writev_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_accept_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ENODEV:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_connect_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EACCES:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+#if defined(UNIXWARE) || defined(SNI) || defined(NEC)
+ /*
+ * On some platforms, if we connect to a port on the local host
+ * (the loopback address) that no process is listening on, we get
+ * EIO instead of ECONNREFUSED.
+ */
+ case EIO:
+ prError = PR_CONNECT_REFUSED_ERROR;
+ break;
+#endif
+ case ELOOP:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_IO_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_bind_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
+ break;
+ /*
+ * UNIX domain sockets are not supported in NSPR
+ */
+ case EIO:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EROFS:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_listen_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_shutdown_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_socketpair_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_getsockname_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_getpeername_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_getsockopt_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_setsockopt_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_open_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EAGAIN:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EBUSY:
+ prError = PR_IO_ERROR;
+ break;
+ case ENODEV:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ENOMEM:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ prError = PR_FILE_TOO_BIG_ERROR;
+ break;
+#endif
+ case ETIMEDOUT:
+ prError = PR_REMOTE_FILE_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_mmap_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EAGAIN:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EMFILE:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ENODEV:
+ prError = PR_OPERATION_NOT_SUPPORTED_ERROR;
+ break;
+ case ENXIO:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_gethostname_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+void _MD_unix_map_select_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+
+#if defined(_PR_POLL_AVAILABLE) || defined(_PR_NEED_FAKE_POLL)
+void _MD_unix_map_poll_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EAGAIN:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_poll_revents_error(int err)
+{
+ if (err & POLLNVAL)
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ else if (err & POLLHUP)
+ PR_SetError(PR_CONNECT_RESET_ERROR, EPIPE);
+ else if (err & POLLERR)
+ PR_SetError(PR_IO_ERROR, EIO);
+ else
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+}
+#endif /* _PR_POLL_AVAILABLE || _PR_NEED_FAKE_POLL */
+
+
+void _MD_unix_map_flock_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EINVAL:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case EWOULDBLOCK:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_unix_map_lockf_error(int err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EACCES:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case EDEADLK:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ default:
+ _MD_unix_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+#ifdef AIX
+void _MD_aix_map_sendfile_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+#endif /* AIX */
+
+#ifdef HPUX11
+void _MD_hpux_map_sendfile_error(int err)
+{
+ _MD_unix_map_default_error(err);
+}
+#endif /* HPUX11 */
+
+#ifdef SOLARIS
+void _MD_solaris_map_sendfile_error(int err)
+{
+ _MD_unix_map_default_error(err) ;
+}
+#endif /* SOLARIS */
+
+#ifdef LINUX
+void _MD_linux_map_sendfile_error(int err)
+{
+ _MD_unix_map_default_error(err) ;
+}
+#endif /* LINUX */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unixware.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unixware.c
new file mode 100644
index 00000000..cbcbb3eb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/unixware.c
@@ -0,0 +1,583 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#if !defined (USE_SVR4_THREADS)
+
+/*
+ * using only NSPR threads here
+ */
+
+#include <setjmp.h>
+
+void _MD_EarlyInit(void)
+{
+}
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) setjmp(CONTEXT(t));
+ }
+ *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
+ return (PRWord *) CONTEXT(t);
+}
+
+#ifdef ALARMS_BREAK_TCP /* I don't think they do */
+
+PRInt32 _MD_connect(PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _connect(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+}
+
+PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv;
+
+ _MD_BLOCK_CLOCK_INTERRUPTS();
+ rv = _accept(osfd,addr,addrlen);
+ _MD_UNBLOCK_CLOCK_INTERRUPTS();
+ return(rv);
+}
+#endif
+
+/*
+ * These are also implemented in pratom.c using NSPR locks. Any reason
+ * this might be better or worse? If you like this better, define
+ * _PR_HAVE_ATOMIC_OPS in include/md/unixware.h
+ */
+#ifdef _PR_HAVE_ATOMIC_OPS
+/* Atomic operations */
+#include <stdio.h>
+static FILE *_uw_semf;
+
+void
+_MD_INIT_ATOMIC(void)
+{
+ /* Sigh. Sure wish SYSV semaphores weren't such a pain to use */
+ if ((_uw_semf = tmpfile()) == NULL)
+ PR_ASSERT(0);
+
+ return;
+}
+
+void
+_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+ flockfile(_uw_semf);
+ (*val)++;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ flockfile(_uw_semf);
+ (*ptr) += val;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+ flockfile(_uw_semf);
+ (*val)--;
+ unflockfile(_uw_semf);
+}
+
+void
+_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+{
+ flockfile(_uw_semf);
+ *val = newval;
+ unflockfile(_uw_semf);
+}
+#endif
+
+void
+_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
+{
+ return;
+}
+
+PRStatus
+_MD_InitializeThread(PRThread *thread)
+{
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ _PR_MD_SWITCH_CONTEXT(thread);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread) {
+ PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
+ }
+ return PR_SUCCESS;
+}
+
+/* These functions should not be called for Unixware */
+void
+_MD_YIELD(void)
+{
+ PR_NOT_REACHED("_MD_YIELD should not be called for Unixware.");
+}
+
+PRStatus
+_MD_CREATE_THREAD(
+ PRThread *thread,
+ void (*start) (void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Unixware.");
+}
+
+#else /* USE_SVR4_THREADS */
+
+/* NOTE:
+ * SPARC v9 (Ultras) do have an atomic test-and-set operation. But
+ * SPARC v8 doesn't. We should detect in the init if we are running on
+ * v8 or v9, and then use assembly where we can.
+ */
+
+#include <thread.h>
+#include <synch.h>
+
+static mutex_t _unixware_atomic = DEFAULTMUTEX;
+
+#define TEST_THEN_ADD(where, inc) \
+ if (mutex_lock(&_unixware_atomic) != 0)\
+ PR_ASSERT(0);\
+ *where += inc;\
+ if (mutex_unlock(&_unixware_atomic) != 0)\
+ PR_ASSERT(0);
+
+#define TEST_THEN_SET(where, val) \
+ if (mutex_lock(&_unixware_atomic) != 0)\
+ PR_ASSERT(0);\
+ *where = val;\
+ if (mutex_unlock(&_unixware_atomic) != 0)\
+ PR_ASSERT(0);
+
+void
+_MD_INIT_ATOMIC(void)
+{
+}
+
+void
+_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+ TEST_THEN_ADD(val, 1);
+}
+
+void
+_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ TEST_THEN_ADD(ptr, val);
+}
+
+void
+_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+ TEST_THEN_ADD(val, 0xffffffff);
+}
+
+void
+_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+{
+ TEST_THEN_SET(val, newval);
+}
+
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/lwp.h>
+#include <sys/procfs.h>
+#include <sys/syscall.h>
+
+
+THREAD_KEY_T threadid_key;
+THREAD_KEY_T cpuid_key;
+THREAD_KEY_T last_thread_key;
+static sigset_t set, oldset;
+
+void _MD_EarlyInit(void)
+{
+ THR_KEYCREATE(&threadid_key, NULL);
+ THR_KEYCREATE(&cpuid_key, NULL);
+ THR_KEYCREATE(&last_thread_key, NULL);
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+}
+
+PRStatus _MD_CREATE_THREAD(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ long flags;
+
+ /* mask out SIGALRM for native thread creation */
+ thr_sigsetmask(SIG_BLOCK, &set, &oldset);
+
+ flags = (state == PR_JOINABLE_THREAD ? THR_SUSPENDED/*|THR_NEW_LWP*/
+ : THR_SUSPENDED|THR_DETACHED/*|THR_NEW_LWP*/);
+ if (_PR_IS_GCABLE_THREAD(thread) ||
+ (scope == PR_GLOBAL_BOUND_THREAD))
+ flags |= THR_BOUND;
+
+ if (thr_create(NULL, thread->stack->stackSize,
+ (void *(*)(void *)) start, (void *) thread,
+ flags,
+ &thread->md.handle)) {
+ thr_sigsetmask(SIG_SETMASK, &oldset, NULL);
+ return PR_FAILURE;
+ }
+
+
+ /* When the thread starts running, then the lwpid is set to the right
+ * value. Until then we want to mark this as 'uninit' so that
+ * its register state is initialized properly for GC */
+
+ thread->md.lwpid = -1;
+ thr_sigsetmask(SIG_SETMASK, &oldset, NULL);
+ _MD_NEW_SEM(&thread->md.waiter_sem, 0);
+
+ if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) {
+ thread->flags |= _PR_GLOBAL_SCOPE;
+ }
+
+ /*
+ ** Set the thread priority. This will also place the thread on
+ ** the runQ.
+ **
+ ** Force PR_SetThreadPriority to set the priority by
+ ** setting thread->priority to 100.
+ */
+ {
+ int pri;
+ pri = thread->priority;
+ thread->priority = 100;
+ PR_SetThreadPriority( thread, pri );
+
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("(0X%x)[Start]: on to runq at priority %d",
+ thread, thread->priority));
+ }
+
+ /* Activate the thread */
+ if (thr_continue( thread->md.handle ) ) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+void _MD_cleanup_thread(PRThread *thread)
+{
+ thread_t hdl;
+ PRMonitor *mon;
+
+ hdl = thread->md.handle;
+
+ /*
+ ** First, suspend the thread (unless it's the active one)
+ ** Because we suspend it first, we don't have to use LOCK_SCHEDULER to
+ ** prevent both of us modifying the thread structure at the same time.
+ */
+ if ( thread != _PR_MD_CURRENT_THREAD() ) {
+ thr_suspend(hdl);
+ }
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("(0X%x)[DestroyThread]\n", thread));
+
+ _MD_DESTROY_SEM(&thread->md.waiter_sem);
+}
+
+void _MD_SET_PRIORITY(_MDThread *md_thread, PRUintn newPri)
+{
+ if(thr_setprio((thread_t)md_thread->handle, newPri)) {
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("_PR_SetThreadPriority: can't set thread priority\n"));
+ }
+}
+
+void _MD_WAIT_CV(
+ struct _MDCVar *md_cv, struct _MDLock *md_lock, PRIntervalTime timeout)
+{
+ struct timespec tt;
+ PRUint32 msec;
+ int rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ msec = PR_IntervalToMilliseconds(timeout);
+
+ GETTIME (&tt);
+
+ tt.tv_sec += msec / PR_MSEC_PER_SEC;
+ tt.tv_nsec += (msec % PR_MSEC_PER_SEC) * PR_NSEC_PER_MSEC;
+ /* Check for nsec overflow - otherwise we'll get an EINVAL */
+ if (tt.tv_nsec >= PR_NSEC_PER_SEC) {
+ tt.tv_sec++;
+ tt.tv_nsec -= PR_NSEC_PER_SEC;
+ }
+ me->md.sp = unixware_getsp();
+
+
+ /* XXX Solaris 2.5.x gives back EINTR occasionally for no reason
+ * hence ignore EINTR for now */
+
+ COND_TIMEDWAIT(&md_cv->cv, &md_lock->lock, &tt);
+}
+
+void _MD_lock(struct _MDLock *md_lock)
+{
+ mutex_lock(&md_lock->lock);
+}
+
+void _MD_unlock(struct _MDLock *md_lock)
+{
+ mutex_unlock(&((md_lock)->lock));
+}
+
+
+PRThread *_pr_current_thread_tls()
+{
+ PRThread *ret;
+
+ thr_getspecific(threadid_key, (void **)&ret);
+ return ret;
+}
+
+PRStatus
+_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ _MD_WAIT_SEM(&thread->md.waiter_sem);
+ return PR_SUCCESS;
+}
+
+PRStatus
+_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread == NULL) {
+ return PR_SUCCESS;
+ }
+ _MD_POST_SEM(&thread->md.waiter_sem);
+ return PR_SUCCESS;
+}
+
+_PRCPU *_pr_current_cpu_tls()
+{
+ _PRCPU *ret;
+
+ thr_getspecific(cpuid_key, (void **)&ret);
+ return ret;
+}
+
+PRThread *_pr_last_thread_tls()
+{
+ PRThread *ret;
+
+ thr_getspecific(last_thread_key, (void **)&ret);
+ return ret;
+}
+
+_MDLock _pr_ioq_lock;
+
+void _MD_INIT_IO (void)
+{
+ _MD_NEW_LOCK(&_pr_ioq_lock);
+}
+
+PRStatus _MD_InitializeThread(PRThread *thread)
+{
+ if (!_PR_IS_NATIVE_THREAD(thread))
+ return;
+ /* prime the sp; substract 4 so we don't hit the assert that
+ * curr sp > base_stack
+ */
+ thread->md.sp = (uint_t) thread->stack->allocBase - sizeof(long);
+ thread->md.lwpid = _lwp_self();
+ thread->md.handle = THR_SELF();
+
+ /* all threads on Solaris are global threads from NSPR's perspective
+ * since all of them are mapped to Solaris threads.
+ */
+ thread->flags |= _PR_GLOBAL_SCOPE;
+
+ /* For primordial/attached thread, we don't create an underlying native thread.
+ * So, _MD_CREATE_THREAD() does not get called. We need to do initialization
+ * like allocating thread's synchronization variables and set the underlying
+ * native thread's priority.
+ */
+ if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
+ _MD_NEW_SEM(&thread->md.waiter_sem, 0);
+ _MD_SET_PRIORITY(&(thread->md), thread->priority);
+ }
+ return PR_SUCCESS;
+}
+
+static sigset_t old_mask; /* store away original gc thread sigmask */
+static int gcprio; /* store away original gc thread priority */
+static lwpid_t *all_lwps=NULL; /* list of lwps that we suspended */
+static int num_lwps ;
+static int suspendAllOn = 0;
+
+#define VALID_SP(sp, bottom, top) \
+ (((uint_t)(sp)) > ((uint_t)(bottom)) && ((uint_t)(sp)) < ((uint_t)(top)))
+
+void unixware_preempt_off()
+{
+ sigset_t set;
+ (void)sigfillset(&set);
+ sigprocmask (SIG_SETMASK, &set, &old_mask);
+}
+
+void unixware_preempt_on()
+{
+ sigprocmask (SIG_SETMASK, &old_mask, NULL);
+}
+
+void _MD_Begin_SuspendAll()
+{
+ unixware_preempt_off();
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin_SuspendAll\n"));
+ /* run at highest prio so I cannot be preempted */
+ thr_getprio(thr_self(), &gcprio);
+ thr_setprio(thr_self(), 0x7fffffff);
+ suspendAllOn = 1;
+}
+
+void _MD_End_SuspendAll()
+{
+}
+
+void _MD_End_ResumeAll()
+{
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End_ResumeAll\n"));
+ thr_setprio(thr_self(), gcprio);
+ unixware_preempt_on();
+ suspendAllOn = 0;
+}
+
+void _MD_Suspend(PRThread *thr)
+{
+ int lwp_fd, result;
+ int lwp_main_proc_fd = 0;
+
+ thr_suspend(thr->md.handle);
+ if (!_PR_IS_GCABLE_THREAD(thr))
+ return;
+ /* XXX Primordial thread can't be bound to an lwp, hence there is no
+ * way we can assume that we can get the lwp status for primordial
+ * thread reliably. Hence we skip this for primordial thread, hoping
+ * that the SP is saved during lock and cond. wait.
+ * XXX - Again this is concern only for java interpreter, not for the
+ * server, 'cause primordial thread in the server does not do java work
+ */
+ if (thr->flags & _PR_PRIMORDIAL)
+ return;
+
+ /* if the thread is not started yet then don't do anything */
+ if (!suspendAllOn || thr->md.lwpid == -1)
+ return;
+
+}
+void _MD_Resume(PRThread *thr)
+{
+ if (!_PR_IS_GCABLE_THREAD(thr) || !suspendAllOn){
+ /*XXX When the suspendAllOn is set, we will be trying to do lwp_suspend
+ * during that time we can't call any thread lib or libc calls. Hence
+ * make sure that no resume is requested for Non gcable thread
+ * during suspendAllOn */
+ PR_ASSERT(!suspendAllOn);
+ thr_continue(thr->md.handle);
+ return;
+ }
+ if (thr->md.lwpid == -1)
+ return;
+
+ if ( _lwp_continue(thr->md.lwpid) < 0) {
+ PR_ASSERT(0); /* ARGH, we are hosed! */
+ }
+}
+
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent) {
+ (void) getcontext(CONTEXT(t)); /* XXX tune me: set md_IRIX.c */
+ }
+ *np = NGREG;
+ if (t->md.lwpid == -1)
+ memset(&t->md.context.uc_mcontext.gregs[0], 0, NGREG * sizeof(PRWord));
+ return (PRWord*) &t->md.context.uc_mcontext.gregs[0];
+}
+
+int
+_pr_unixware_clock_gettime (struct timespec *tp)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = tv.tv_usec * 1000;
+ return 0;
+}
+
+
+#endif /* USE_SVR4_THREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxpoll.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxpoll.c
new file mode 100644
index 00000000..aa026568
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxpoll.c
@@ -0,0 +1,708 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#if defined(_PR_PTHREADS)
+
+#error "This file should not be compiled"
+
+#else /* defined(_PR_PTHREADS) */
+
+#include "primpl.h"
+
+#include <sys/time.h>
+
+#include <fcntl.h>
+#ifdef _PR_USE_POLL
+#include <poll.h>
+#endif
+
+#if defined(_PR_USE_POLL)
+static PRInt32 NativeThreadPoll(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ /*
+ * This function is mostly duplicated from ptio.s's PR_Poll().
+ */
+ PRInt32 ready = 0;
+ /*
+ * For restarting poll() if it is interrupted by a signal.
+ * We use these variables to figure out how much time has
+ * elapsed and how much of the timeout still remains.
+ */
+ PRIntn index, msecs;
+ struct pollfd *syspoll = NULL;
+ PRIntervalTime start, elapsed, remaining;
+
+ syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
+ if (NULL == syspoll)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ for (index = 0; index < npds; ++index)
+ {
+ PRFileDesc *bottom;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (pds[index].in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_WRITE,
+ &out_flags_read);
+ }
+ if (pds[index].in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_READ,
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one is ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will return without calling the system
+ * poll function. So zero the out_flags
+ * fields of all the poll descriptors before
+ * this one.
+ */
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1;
+ pds[index].out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pds[index].out_flags = 0; /* pre-condition */
+ /* now locate the NSPR layer at the bottom of the stack */
+ bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ syspoll[index].fd = bottom->secret->md.osfd;
+ syspoll[index].events = 0; /* pre-condition */
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (pds[index].in_flags & PR_POLL_EXCEPT)
+ syspoll[index].events |= POLLPRI;
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pds[index].out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ /* make poll() ignore this entry */
+ syspoll[index].fd = -1;
+ syspoll[index].events = 0;
+ pds[index].out_flags = 0;
+ }
+ }
+
+ if (0 == ready)
+ {
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT: msecs = 0; break;
+ case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;
+ default:
+ msecs = PR_IntervalToMilliseconds(timeout);
+ start = PR_IntervalNow();
+ }
+
+retry:
+ ready = _MD_POLL(syspoll, npds, msecs);
+ if (-1 == ready)
+ {
+ PRIntn oserror = errno;
+
+ if (EINTR == oserror)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0;
+ else
+ {
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ msecs = PR_IntervalToMilliseconds(remaining);
+ goto retry;
+ }
+ }
+ }
+ else _PR_MD_MAP_POLL_ERROR(oserror);
+ }
+ else if (ready > 0)
+ {
+ for (index = 0; index < npds; ++index)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (0 != syspoll[index].revents)
+ {
+ /*
+ ** Set up the out_flags so that it contains the
+ ** bits that the highest layer thinks are nice
+ ** to have. Then the client of that layer will
+ ** call the appropriate I/O function and maybe
+ ** the protocol will make progress.
+ */
+ if (syspoll[index].revents & POLLIN)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_READ)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_READ)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLOUT)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLPRI)
+ out_flags |= PR_POLL_EXCEPT;
+ if (syspoll[index].revents & POLLERR)
+ out_flags |= PR_POLL_ERR;
+ if (syspoll[index].revents & POLLNVAL)
+ out_flags |= PR_POLL_NVAL;
+ if (syspoll[index].revents & POLLHUP)
+ out_flags |= PR_POLL_HUP;
+ }
+ }
+ pds[index].out_flags = out_flags;
+ }
+ }
+ }
+
+ PR_DELETE(syspoll);
+ return ready;
+
+} /* NativeThreadPoll */
+#endif /* defined(_PR_USE_POLL) */
+
+#if !defined(_PR_USE_POLL)
+static PRInt32 NativeThreadSelect(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ /*
+ * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
+ */
+ fd_set rd, wt, ex;
+ PRFileDesc *bottom;
+ PRPollDesc *pd, *epd;
+ PRInt32 maxfd = -1, ready, err;
+ PRIntervalTime remaining, elapsed, start;
+
+ struct timeval tv, *tvp = NULL;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ PRInt32 osfd = bottom->secret->md.osfd;
+ if (osfd > maxfd) maxfd = osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ pd->out_flags = 0;
+ }
+ }
+
+ if (0 != ready) return ready; /* no need to block */
+
+ remaining = timeout;
+ start = PR_IntervalNow();
+
+retry:
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = remaining / ticksPerSecond;
+ tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
+ tvp = &tv;
+ }
+
+ ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
+
+ if (ready == -1 && errno == EINTR)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout) ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ goto retry;
+ }
+ }
+ }
+
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ PRInt32 osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = bottom->secret->md.osfd;
+
+ if (FD_ISSET(osfd, &rd))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &wt))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
+ }
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready < 0)
+ {
+ err = _MD_ERRNO();
+ if (err == EBADF)
+ {
+ /* Find the bad fds */
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+ return ready;
+} /* NativeThreadSelect */
+#endif /* !defined(_PR_USE_POLL) */
+
+static PRInt32 LocalThreads(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRPollDesc *pd, *epd;
+ PRInt32 ready, pdcnt;
+ _PRUnixPollDesc *unixpds, *unixpd;
+
+ /*
+ * XXX
+ * PRPollDesc has a PRFileDesc field, fd, while the IOQ
+ * is a list of PRPollQueue structures, each of which contains
+ * a _PRUnixPollDesc. A _PRUnixPollDesc struct contains
+ * the OS file descriptor, osfd, and not a PRFileDesc.
+ * So, we have allocate memory for _PRUnixPollDesc structures,
+ * copy the flags information from the pds list and have pq
+ * point to this list of _PRUnixPollDesc structures.
+ *
+ * It would be better if the memory allocation can be avoided.
+ */
+
+ unixpd = unixpds = (_PRUnixPollDesc*)
+ PR_MALLOC(npds * sizeof(_PRUnixPollDesc));
+ if (NULL == unixpds)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+
+ ready = 0;
+ for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRFileDesc *bottom;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ unixpd->osfd = bottom->secret->md.osfd;
+ unixpd->in_flags = 0;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_READ;
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_READ;
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ }
+ if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT)
+ {
+ unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT;
+ }
+ unixpd++; pdcnt++;
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ }
+
+ if (0 != ready)
+ {
+ /* no need to block */
+ PR_DELETE(unixpds);
+ return ready;
+ }
+
+ ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);
+
+ /*
+ * Copy the out_flags from the _PRUnixPollDesc structures to the
+ * user's PRPollDesc structures and free the allocated memory
+ */
+ unixpd = unixpds;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ /*
+ * take errors from the poll operation,
+ * the R/W bits from the request
+ */
+ if (0 != unixpd->out_flags)
+ {
+ if (unixpd->out_flags & _PR_UNIX_POLL_READ)
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_WRITE)
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT)
+ out_flags |= PR_POLL_EXCEPT;
+ if (unixpd->out_flags & _PR_UNIX_POLL_ERR)
+ out_flags |= PR_POLL_ERR;
+ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL)
+ out_flags |= PR_POLL_NVAL;
+ if (unixpd->out_flags & _PR_UNIX_POLL_HUP)
+ out_flags |= PR_POLL_HUP;
+ }
+ unixpd++;
+ }
+ pd->out_flags = out_flags;
+ }
+
+ PR_DELETE(unixpds);
+
+ return ready;
+} /* LocalThreads */
+
+#if defined(_PR_USE_POLL)
+#define NativeThreads NativeThreadPoll
+#else
+#define NativeThreads NativeThreadSelect
+#endif
+
+PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRInt32 rv = 0;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ if (0 == npds) PR_Sleep(timeout);
+ else if (_PR_IS_NATIVE_THREAD(me))
+ rv = NativeThreads(pds, npds, timeout);
+ else rv = LocalThreads(pds, npds, timeout);
+
+ return rv;
+} /* _MD_pr_poll */
+
+#endif /* defined(_PR_PTHREADS) */
+
+/* uxpoll.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxproces.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxproces.c
new file mode 100644
index 00000000..ff825772
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxproces.c
@@ -0,0 +1,1118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+#if defined(AIX)
+#include <dlfcn.h> /* For dlopen, dlsym, dlclose */
+#endif
+
+#if defined(DARWIN)
+#include <crt_externs.h>
+#else
+extern char **environ;
+#endif
+
+/*
+ * HP-UX 9 doesn't have the SA_RESTART flag.
+ */
+#ifndef SA_RESTART
+#define SA_RESTART 0
+#endif
+
+#if defined(VMS)
+static PRLock *_pr_vms_fork_lock = NULL;
+#endif
+
+#ifdef VBOX
+#include <iprt/err.h>
+#include <iprt/env.h>
+#include <iprt/file.h>
+#include <iprt/process.h>
+#endif
+
+/*
+ **********************************************************************
+ *
+ * The Unix process routines
+ *
+ **********************************************************************
+ */
+
+#define _PR_SIGNALED_EXITSTATUS 256
+
+typedef enum pr_PidState {
+ _PR_PID_DETACHED,
+ _PR_PID_REAPED,
+ _PR_PID_WAITING
+} pr_PidState;
+
+typedef struct pr_PidRecord {
+ pid_t pid;
+ int exitStatus;
+ pr_PidState state;
+ PRCondVar *reapedCV;
+ struct pr_PidRecord *next;
+} pr_PidRecord;
+
+/*
+ * Irix sprocs and LinuxThreads are actually a kind of processes
+ * that can share the virtual address space and file descriptors.
+ */
+#if (defined(IRIX) && !defined(_PR_PTHREADS)) \
+ || (defined(LINUX) && defined(_PR_PTHREADS))
+#define _PR_SHARE_CLONES
+#endif
+
+/*
+ * The macro _PR_NATIVE_THREADS indicates that we are
+ * using native threads only, so waitpid() blocks just the
+ * calling thread, not the process. In this case, the waitpid
+ * daemon thread can safely block in waitpid(). So we don't
+ * need to catch SIGCHLD, and the pipe to unblock PR_Poll() is
+ * also not necessary.
+ */
+
+#if defined(_PR_GLOBAL_THREADS_ONLY) \
+ || (defined(_PR_PTHREADS) && !defined(LINUX))
+#define _PR_NATIVE_THREADS
+#endif
+
+/*
+ * All the static variables used by the Unix process routines are
+ * collected in this structure.
+ */
+
+static struct {
+ PRCallOnceType once;
+ PRThread *thread;
+ PRLock *ml;
+#if defined(_PR_NATIVE_THREADS)
+ PRInt32 numProcs;
+ PRCondVar *cv;
+#else
+ int pipefd[2];
+#endif
+ pr_PidRecord **pidTable;
+
+#ifdef _PR_SHARE_CLONES
+ struct pr_CreateProcOp *opHead, *opTail;
+#endif
+
+#ifdef AIX
+ pid_t (*forkptr)(void); /* Newer versions of AIX (starting in 4.3.2)
+ * have f_fork, which is faster than the
+ * regular fork in a multithreaded process
+ * because it skips calling the fork handlers.
+ * So we look up the f_fork symbol to see if
+ * it's available and fall back on fork.
+ */
+#endif /* AIX */
+} pr_wp;
+
+#ifdef _PR_SHARE_CLONES
+static int pr_waitpid_daemon_exit;
+
+void
+_MD_unix_terminate_waitpid_daemon(void)
+{
+ if (pr_wp.thread) {
+ pr_waitpid_daemon_exit = 1;
+ write(pr_wp.pipefd[1], "", 1);
+ PR_JoinThread(pr_wp.thread);
+ }
+}
+#endif
+
+static PRStatus _MD_InitProcesses(void);
+#if !defined(_PR_NATIVE_THREADS)
+static void pr_InstallSigchldHandler(void);
+#ifdef VBOX
+static void (*old_sig_handler)(int) = NULL;
+#endif /* VBOX */
+#endif
+
+static PRProcess *
+ForkAndExec(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+ PRProcess *process;
+ int nEnv, idx;
+ char *const *childEnvp;
+ char **newEnvp = NULL;
+ int flags;
+#ifdef VMS
+ char VMScurdir[FILENAME_MAX+1] = { '\0' } ;
+#endif
+
+ process = PR_NEW(PRProcess);
+ if (!process) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ childEnvp = envp;
+ if (attr && attr->fdInheritBuffer) {
+ if (NULL == childEnvp) {
+#ifdef DARWIN
+ childEnvp = *(_NSGetEnviron());
+#else
+ childEnvp = environ;
+#endif
+ }
+ for (nEnv = 0; childEnvp[nEnv]; nEnv++) {
+ }
+ newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *));
+ if (NULL == newEnvp) {
+ PR_DELETE(process);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ for (idx = 0; idx < nEnv; idx++) {
+ newEnvp[idx] = childEnvp[idx];
+ }
+ newEnvp[idx++] = attr->fdInheritBuffer;
+ newEnvp[idx] = NULL;
+ childEnvp = newEnvp;
+ }
+
+#ifdef VMS
+/*
+** Since vfork/exec is implemented VERY differently on OpenVMS, we have to
+** handle the setting up of the standard streams very differently. And since
+** none of this code can ever execute in the context of the child, we have
+** to perform the chdir in the parent so the child is born into the correct
+** directory (and then switch the parent back again).
+*/
+{
+ int decc$set_child_standard_streams(int,int,int);
+ int n, fd_stdin=0, fd_stdout=1, fd_stderr=2;
+
+ /* Set up any standard streams we are given, assuming defaults */
+ if (attr) {
+ if (attr->stdinFd)
+ fd_stdin = attr->stdinFd->secret->md.osfd;
+ if (attr->stdoutFd)
+ fd_stdout = attr->stdoutFd->secret->md.osfd;
+ if (attr->stderrFd)
+ fd_stderr = attr->stderrFd->secret->md.osfd;
+ }
+
+ /*
+ ** Put a lock around anything that isn't going to be thread-safe.
+ */
+ PR_Lock(_pr_vms_fork_lock);
+
+ /*
+ ** Prepare the child's streams. We always do this in case a previous fork
+ ** has left the stream assignments in some non-standard way.
+ */
+ n = decc$set_child_standard_streams(fd_stdin,fd_stdout,fd_stderr);
+ if (n == -1) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, errno);
+ PR_DELETE(process);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ PR_Unlock(_pr_vms_fork_lock);
+ return NULL;
+ }
+
+ /* Switch directory if we have to */
+ if (attr) {
+ if (attr->currentDirectory) {
+ if ( (getcwd(VMScurdir,sizeof(VMScurdir)) == NULL) ||
+ (chdir(attr->currentDirectory) < 0) ) {
+ PR_SetError(PR_DIRECTORY_OPEN_ERROR, errno);
+ PR_DELETE(process);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ PR_Unlock(_pr_vms_fork_lock);
+ return NULL;
+ }
+ }
+ }
+}
+#endif /* VMS */
+
+#ifdef AIX
+ process->md.pid = (*pr_wp.forkptr)();
+#elif defined(NTO)
+ /*
+ * fork() & exec() does not work in a multithreaded process.
+ * Use spawn() instead.
+ */
+ {
+ int fd_map[3] = { 0, 1, 2 };
+
+ if (attr) {
+ if (attr->stdinFd && attr->stdinFd->secret->md.osfd != 0) {
+ fd_map[0] = dup(attr->stdinFd->secret->md.osfd);
+ flags = fcntl(fd_map[0], F_GETFL, 0);
+ if (flags & O_NONBLOCK)
+ fcntl(fd_map[0], F_SETFL, flags & ~O_NONBLOCK);
+ }
+ if (attr->stdoutFd && attr->stdoutFd->secret->md.osfd != 1) {
+ fd_map[1] = dup(attr->stdoutFd->secret->md.osfd);
+ flags = fcntl(fd_map[1], F_GETFL, 0);
+ if (flags & O_NONBLOCK)
+ fcntl(fd_map[1], F_SETFL, flags & ~O_NONBLOCK);
+ }
+ if (attr->stderrFd && attr->stderrFd->secret->md.osfd != 2) {
+ fd_map[2] = dup(attr->stderrFd->secret->md.osfd);
+ flags = fcntl(fd_map[2], F_GETFL, 0);
+ if (flags & O_NONBLOCK)
+ fcntl(fd_map[2], F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ PR_ASSERT(attr->currentDirectory == NULL); /* not implemented */
+ }
+
+ process->md.pid = spawn(path, 3, fd_map, NULL, argv, childEnvp);
+
+ if (fd_map[0] != 0)
+ close(fd_map[0]);
+ if (fd_map[1] != 1)
+ close(fd_map[1]);
+ if (fd_map[2] != 2)
+ close(fd_map[2]);
+ }
+#else
+ process->md.pid = fork();
+#endif
+ if ((pid_t) -1 == process->md.pid) {
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
+ PR_DELETE(process);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ return NULL;
+ } else if (0 == process->md.pid) { /* the child process */
+ /*
+ * If the child process needs to exit, it must call _exit().
+ * Do not call exit(), because exit() will flush and close
+ * the standard I/O file descriptors, and hence corrupt
+ * the parent process's standard I/O data structures.
+ */
+
+#if !defined(NTO)
+#ifdef VMS
+ /* OpenVMS has already handled all this above */
+#else
+ if (attr) {
+ /* the osfd's to redirect stdin, stdout, and stderr to */
+ int in_osfd = -1, out_osfd = -1, err_osfd = -1;
+
+ if (attr->stdinFd
+ && attr->stdinFd->secret->md.osfd != 0) {
+ in_osfd = attr->stdinFd->secret->md.osfd;
+ if (dup2(in_osfd, 0) != 0) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(0, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (attr->stdoutFd
+ && attr->stdoutFd->secret->md.osfd != 1) {
+ out_osfd = attr->stdoutFd->secret->md.osfd;
+ if (dup2(out_osfd, 1) != 1) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(1, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (attr->stderrFd
+ && attr->stderrFd->secret->md.osfd != 2) {
+ err_osfd = attr->stderrFd->secret->md.osfd;
+ if (dup2(err_osfd, 2) != 2) {
+ _exit(1); /* failed */
+ }
+ flags = fcntl(2, F_GETFL, 0);
+ if (flags & O_NONBLOCK) {
+ fcntl(2, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+ if (in_osfd != -1) {
+ close(in_osfd);
+ }
+ if (out_osfd != -1 && out_osfd != in_osfd) {
+ close(out_osfd);
+ }
+ if (err_osfd != -1 && err_osfd != in_osfd
+ && err_osfd != out_osfd) {
+ close(err_osfd);
+ }
+ if (attr->currentDirectory) {
+ if (chdir(attr->currentDirectory) < 0) {
+ _exit(1); /* failed */
+ }
+ }
+ }
+#endif /* !VMS */
+
+ if (childEnvp) {
+ (void)execve(path, argv, childEnvp);
+ } else {
+ /* Inherit the environment of the parent. */
+ (void)execv(path, argv);
+ }
+ /* Whoops! It returned. That's a bad sign. */
+#ifdef VMS
+ /*
+ ** On OpenVMS we are still in the context of the parent, and so we
+ ** can (and should!) perform normal error handling.
+ */
+ PR_SetError(PR_UNKNOWN_ERROR, errno);
+ PR_DELETE(process);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (VMScurdir[0] != '\0')
+ chdir(VMScurdir);
+ PR_Unlock(_pr_vms_fork_lock);
+ return NULL;
+#else
+ _exit(1);
+#endif /* VMS */
+#endif /* !NTO */
+ }
+
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+#ifdef VMS
+ /* If we switched directories, then remember to switch back */
+ if (VMScurdir[0] != '\0') {
+ chdir(VMScurdir); /* can't do much if it fails */
+ }
+ PR_Unlock(_pr_vms_fork_lock);
+#endif /* VMS */
+
+#if defined(_PR_NATIVE_THREADS)
+ PR_Lock(pr_wp.ml);
+ if (0 == pr_wp.numProcs++) {
+ PR_NotifyCondVar(pr_wp.cv);
+ }
+ PR_Unlock(pr_wp.ml);
+#endif
+ return process;
+}
+
+#ifdef _PR_SHARE_CLONES
+
+struct pr_CreateProcOp {
+ const char *path;
+ char *const *argv;
+ char *const *envp;
+ const PRProcessAttr *attr;
+ PRProcess *process;
+ PRErrorCode prerror;
+ PRInt32 oserror;
+ PRBool done;
+ PRCondVar *doneCV;
+ struct pr_CreateProcOp *next;
+};
+
+PRProcess *
+_MD_CreateUnixProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+#ifdef VBOX
+ /* 2010-10-11 Block this for good. */
+ return NULL;
+#endif
+ struct pr_CreateProcOp *op;
+ PRProcess *proc;
+ int rv;
+
+ if (PR_CallOnce(&pr_wp.once, _MD_InitProcesses) == PR_FAILURE) {
+ return NULL;
+ }
+
+ op = PR_NEW(struct pr_CreateProcOp);
+ if (NULL == op) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ op->path = path;
+ op->argv = argv;
+ op->envp = envp;
+ op->attr = attr;
+ op->done = PR_FALSE;
+ op->doneCV = PR_NewCondVar(pr_wp.ml);
+ if (NULL == op->doneCV) {
+ PR_DELETE(op);
+ return NULL;
+ }
+ PR_Lock(pr_wp.ml);
+
+ /* add to the tail of op queue */
+ op->next = NULL;
+ if (pr_wp.opTail) {
+ pr_wp.opTail->next = op;
+ pr_wp.opTail = op;
+ } else {
+ PR_ASSERT(NULL == pr_wp.opHead);
+ pr_wp.opHead = pr_wp.opTail = op;
+ }
+
+ /* wake up the daemon thread */
+ do {
+ rv = write(pr_wp.pipefd[1], "", 1);
+ } while (-1 == rv && EINTR == errno);
+
+ while (op->done == PR_FALSE) {
+ PR_WaitCondVar(op->doneCV, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(pr_wp.ml);
+ PR_DestroyCondVar(op->doneCV);
+ proc = op->process;
+ if (!proc) {
+ PR_SetError(op->prerror, op->oserror);
+ }
+ PR_DELETE(op);
+ return proc;
+}
+
+#else /* ! _PR_SHARE_CLONES */
+
+PRProcess *
+_MD_CreateUnixProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+#ifdef VBOX
+ /* 2010-10-11 Block this for good. */
+ return NULL;
+#endif
+ if (PR_CallOnce(&pr_wp.once, _MD_InitProcesses) == PR_FAILURE) {
+ return NULL;
+ }
+ return ForkAndExec(path, argv, envp, attr);
+} /* _MD_CreateUnixProcess */
+
+#endif /* _PR_SHARE_CLONES */
+
+#ifdef VBOX
+PRStatus
+_MD_CreateUnixProcessDetached(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+ int vrc;
+ int nEnv, idx;
+ RTENV childEnv;
+ RTENV newEnv = RTENV_DEFAULT;
+
+ /* this code doesn't support all attributes */
+ PR_ASSERT(!attr || !attr->currentDirectory);
+ /* no custom environment, please */
+ PR_ASSERT(!envp);
+
+ childEnv = RTENV_DEFAULT;
+ if (attr && attr->fdInheritBuffer) {
+ vrc = RTEnvClone(&newEnv, childEnv);
+ if (RT_FAILURE(vrc))
+ return PR_FAILURE;
+ vrc = RTEnvPutEx(newEnv, attr->fdInheritBuffer);
+ if (RT_FAILURE(vrc))
+ {
+ RTEnvDestroy(newEnv);
+ return PR_FAILURE;
+ }
+ childEnv = newEnv;
+ }
+
+ PRTHANDLE pStdIn = NULL, pStdOut = NULL, pStdErr = NULL;
+ RTHANDLE hStdIn, hStdOut, hStdErr;
+ if (attr && attr->stdinFd)
+ {
+ hStdIn.enmType = RTHANDLETYPE_FILE;
+ RTFileFromNative(&hStdIn.u.hFile, attr->stdinFd->secret->md.osfd);
+ pStdIn = &hStdIn;
+ }
+ if (attr && attr->stdoutFd)
+ {
+ hStdOut.enmType = RTHANDLETYPE_FILE;
+ RTFileFromNative(&hStdOut.u.hFile, attr->stdoutFd->secret->md.osfd);
+ pStdOut = &hStdOut;
+ }
+ if (attr && attr->stderrFd)
+ {
+ hStdErr.enmType = RTHANDLETYPE_FILE;
+ RTFileFromNative(&hStdErr.u.hFile, attr->stderrFd->secret->md.osfd);
+ pStdErr = &hStdErr;
+ }
+
+ vrc = RTProcCreateEx(path, (const char **)argv, childEnv,
+ RTPROC_FLAGS_DETACHED, pStdIn, pStdOut, pStdErr,
+ NULL /* pszAsUser */, NULL /* pszPassword */, NULL /* pExtraData */,
+ NULL /* phProcess */);
+ if (newEnv != RTENV_DEFAULT) {
+ RTEnvDestroy(newEnv);
+ }
+ if (RT_SUCCESS(vrc))
+ return PR_SUCCESS;
+ else
+ return PR_FAILURE;
+} /* _MD_CreateUnixProcessDetached */
+#endif
+
+/*
+ * The pid table is a hashtable.
+ *
+ * The number of buckets in the hashtable (NBUCKETS) must be a power of 2.
+ */
+#define NBUCKETS_LOG2 6
+#define NBUCKETS (1 << NBUCKETS_LOG2)
+#define PID_HASH_MASK ((pid_t) (NBUCKETS - 1))
+
+static pr_PidRecord *
+FindPidTable(pid_t pid)
+{
+ pr_PidRecord *pRec;
+ int keyHash = (int) (pid & PID_HASH_MASK);
+
+ pRec = pr_wp.pidTable[keyHash];
+ while (pRec) {
+ if (pRec->pid == pid) {
+ break;
+ }
+ pRec = pRec->next;
+ }
+ return pRec;
+}
+
+static void
+InsertPidTable(pr_PidRecord *pRec)
+{
+ int keyHash = (int) (pRec->pid & PID_HASH_MASK);
+
+ pRec->next = pr_wp.pidTable[keyHash];
+ pr_wp.pidTable[keyHash] = pRec;
+}
+
+static void
+DeletePidTable(pr_PidRecord *pRec)
+{
+ int keyHash = (int) (pRec->pid & PID_HASH_MASK);
+
+ if (pr_wp.pidTable[keyHash] == pRec) {
+ pr_wp.pidTable[keyHash] = pRec->next;
+ } else {
+ pr_PidRecord *pred, *cur; /* predecessor and current */
+
+ pred = pr_wp.pidTable[keyHash];
+ cur = pred->next;
+ while (cur) {
+ if (cur == pRec) {
+ pred->next = cur->next;
+ break;
+ }
+ pred = cur;
+ cur = cur->next;
+ }
+ PR_ASSERT(cur != NULL);
+ }
+}
+
+static int
+ExtractExitStatus(int rawExitStatus)
+{
+ /*
+ * We did not specify the WCONTINUED and WUNTRACED options
+ * for waitpid, so these two events should not be reported.
+ */
+ PR_ASSERT(!WIFSTOPPED(rawExitStatus));
+#ifdef WIFCONTINUED
+ PR_ASSERT(!WIFCONTINUED(rawExitStatus));
+#endif
+ if (WIFEXITED(rawExitStatus)) {
+ return WEXITSTATUS(rawExitStatus);
+ } else {
+ PR_ASSERT(WIFSIGNALED(rawExitStatus));
+ return _PR_SIGNALED_EXITSTATUS;
+ }
+}
+
+static void
+ProcessReapedChildInternal(pid_t pid, int status)
+{
+ pr_PidRecord *pRec;
+
+ pRec = FindPidTable(pid);
+ if (NULL == pRec) {
+ pRec = PR_NEW(pr_PidRecord);
+ pRec->pid = pid;
+ pRec->state = _PR_PID_REAPED;
+ pRec->exitStatus = ExtractExitStatus(status);
+ pRec->reapedCV = NULL;
+ InsertPidTable(pRec);
+ } else {
+#ifdef VBOX
+ /* In the context of VirtualBox processes get created (right now
+ * exclusively via Machine::openRemoteSession) which xpcom doesn't know
+ * about, and thus would trigger assertions or (even worse) could
+ * crash VBoxSVC as the code below would notify a NULL condition
+ * variable. Treat it like a detached process. The proper fix would be
+ * to port the NSPR to use IPRT, as currently this races with getting
+ * the exit code, but that's pretty harmless. */
+ /* Since 2010-10-11 this code cannot be reached as IPRT took over
+ * what we need, and the rest is blocked. */
+ if (_PR_PID_REAPED == pRec->state) {
+ DeletePidTable(pRec);
+ PR_DELETE(pRec);
+ } else
+#else /* !VBOX */
+ PR_ASSERT(pRec->state != _PR_PID_REAPED);
+#endif /* !VBOX */
+ if (_PR_PID_DETACHED == pRec->state) {
+ PR_ASSERT(NULL == pRec->reapedCV);
+ DeletePidTable(pRec);
+ PR_DELETE(pRec);
+ } else {
+ PR_ASSERT(_PR_PID_WAITING == pRec->state);
+ PR_ASSERT(NULL != pRec->reapedCV);
+ pRec->exitStatus = ExtractExitStatus(status);
+ pRec->state = _PR_PID_REAPED;
+ PR_NotifyCondVar(pRec->reapedCV);
+ }
+ }
+}
+
+#if defined(_PR_NATIVE_THREADS)
+
+/*
+ * If all the threads are native threads, the daemon thread is
+ * simpler. We don't need to catch the SIGCHLD signal. We can
+ * just have the daemon thread block in waitpid().
+ */
+
+static void WaitPidDaemonThread(void *unused)
+{
+ pid_t pid;
+ int status;
+
+ while (1) {
+ PR_Lock(pr_wp.ml);
+ while (0 == pr_wp.numProcs) {
+ PR_WaitCondVar(pr_wp.cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(pr_wp.ml);
+
+ while (1) {
+ do {
+#ifdef VBOX
+ /*
+ * make sure we wait only for child of our group
+ * to ensure we do not interfere with RT
+ */
+ /* Since 2010-10-11 this code cannot be reached as IPRT took over
+ * what we need, and the rest is blocked. */
+ pid = waitpid((pid_t) 0, &status, 0);
+#else
+ pid = waitpid((pid_t) -1, &status, 0);
+#endif
+ } while ((pid_t) -1 == pid && EINTR == errno);
+
+ /*
+ * waitpid() cannot return 0 because we did not invoke it
+ * with the WNOHANG option.
+ */
+ PR_ASSERT(0 != pid);
+
+ /*
+ * The only possible error code is ECHILD. But if we do
+ * our accounting correctly, we should only call waitpid()
+ * when there is a child process to wait for.
+ */
+ PR_ASSERT((pid_t) -1 != pid);
+ if ((pid_t) -1 == pid) {
+ break;
+ }
+
+ PR_Lock(pr_wp.ml);
+ ProcessReapedChildInternal(pid, status);
+ pr_wp.numProcs--;
+ while (0 == pr_wp.numProcs) {
+ PR_WaitCondVar(pr_wp.cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(pr_wp.ml);
+ }
+ }
+}
+
+#else /* _PR_NATIVE_THREADS */
+
+static void WaitPidDaemonThread(void *unused)
+{
+ PRPollDesc pd;
+ PRFileDesc *fd;
+ int rv;
+ char buf[128];
+ pid_t pid;
+ int status;
+#ifdef _PR_SHARE_CLONES
+ struct pr_CreateProcOp *op;
+#endif
+
+#ifdef _PR_SHARE_CLONES
+ pr_InstallSigchldHandler();
+#endif
+
+ fd = PR_ImportFile(pr_wp.pipefd[0]);
+ PR_ASSERT(NULL != fd);
+ pd.fd = fd;
+ pd.in_flags = PR_POLL_READ;
+
+ while (1) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(1 == rv);
+
+#ifdef _PR_SHARE_CLONES
+ if (pr_waitpid_daemon_exit) {
+ return;
+ }
+ PR_Lock(pr_wp.ml);
+#endif
+
+ do {
+ rv = read(pr_wp.pipefd[0], buf, sizeof(buf));
+ } while (sizeof(buf) == rv || (-1 == rv && EINTR == errno));
+
+#ifdef _PR_SHARE_CLONES
+ PR_Unlock(pr_wp.ml);
+ while ((op = pr_wp.opHead) != NULL) {
+ op->process = ForkAndExec(op->path, op->argv,
+ op->envp, op->attr);
+ if (NULL == op->process) {
+ op->prerror = PR_GetError();
+ op->oserror = PR_GetOSError();
+ }
+ PR_Lock(pr_wp.ml);
+ pr_wp.opHead = op->next;
+ if (NULL == pr_wp.opHead) {
+ pr_wp.opTail = NULL;
+ }
+ op->done = PR_TRUE;
+ PR_NotifyCondVar(op->doneCV);
+ PR_Unlock(pr_wp.ml);
+ }
+#endif
+
+ while (1) {
+ do {
+#ifdef VBOX
+ /*
+ * make sure we wait only for child of our group
+ * to ensure we do not interfere with RT
+ */
+ /* Since 2010-10-11 this code cannot be reached as IPRT took over
+ * what we need, and the rest is blocked. */
+ pid = waitpid((pid_t) 0, &status, WNOHANG);
+#else
+ pid = waitpid((pid_t) -1, &status, WNOHANG);
+#endif
+ } while ((pid_t) -1 == pid && EINTR == errno);
+ if (0 == pid) break;
+ if ((pid_t) -1 == pid) {
+ /* must be because we have no child processes */
+ PR_ASSERT(ECHILD == errno);
+ break;
+ }
+
+ PR_Lock(pr_wp.ml);
+ ProcessReapedChildInternal(pid, status);
+ PR_Unlock(pr_wp.ml);
+ }
+ }
+}
+
+static void pr_SigchldHandler(int sig)
+{
+ int errnoCopy;
+ int rv;
+
+ errnoCopy = errno;
+
+ do {
+ rv = write(pr_wp.pipefd[1], "", 1);
+ } while (-1 == rv && EINTR == errno);
+
+#ifdef DEBUG
+ if (-1 == rv && EAGAIN != errno && EWOULDBLOCK != errno) {
+ char *msg = "cannot write to pipe\n";
+ write(2, msg, strlen(msg) + 1);
+ _exit(1);
+ }
+#endif
+
+ errno = errnoCopy;
+#ifdef VBOX
+ /** @todo: check if the sig handler fix is proper here */
+ if(old_sig_handler && old_sig_handler != SIG_IGN)
+ old_sig_handler(sig);
+#endif /* VBOX */
+}
+
+static void pr_InstallSigchldHandler()
+{
+#if defined(HPUX) && defined(_PR_DCETHREADS)
+#error "HP-UX DCE threads have their own SIGCHLD handler"
+#endif
+
+ struct sigaction act, oact;
+ int rv;
+
+ act.sa_handler = pr_SigchldHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ rv = sigaction(SIGCHLD, &act, &oact);
+ PR_ASSERT(0 == rv);
+#ifdef VBOX
+ old_sig_handler = oact.sa_handler;
+#endif /* VBOX */
+ /* Make sure we are not overriding someone else's SIGCHLD handler */
+#ifndef _PR_SHARE_CLONES
+ PR_ASSERT(oact.sa_handler == SIG_DFL);
+#endif
+}
+
+#endif /* !defined(_PR_NATIVE_THREADS) */
+
+static PRStatus _MD_InitProcesses(void)
+{
+#if !defined(_PR_NATIVE_THREADS)
+ int rv;
+ int flags;
+#endif
+#ifdef SUNOS4
+#define _PR_NBIO_FLAG FNDELAY
+#else
+#define _PR_NBIO_FLAG O_NONBLOCK
+#endif
+
+#ifdef AIX
+ {
+ void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
+ pr_wp.forkptr = (pid_t (*)(void)) dlsym(handle, "f_fork");
+ if (!pr_wp.forkptr) {
+ pr_wp.forkptr = fork;
+ }
+ dlclose(handle);
+ }
+#endif /* AIX */
+
+ pr_wp.ml = PR_NewLock();
+ PR_ASSERT(NULL != pr_wp.ml);
+
+#if defined(VMS)
+ _pr_vms_fork_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_vms_fork_lock);
+#endif
+
+#if defined(_PR_NATIVE_THREADS)
+ pr_wp.numProcs = 0;
+ pr_wp.cv = PR_NewCondVar(pr_wp.ml);
+ PR_ASSERT(NULL != pr_wp.cv);
+#else
+ rv = pipe(pr_wp.pipefd);
+ PR_ASSERT(0 == rv);
+ flags = fcntl(pr_wp.pipefd[0], F_GETFL, 0);
+ fcntl(pr_wp.pipefd[0], F_SETFL, flags | _PR_NBIO_FLAG);
+ flags = fcntl(pr_wp.pipefd[1], F_GETFL, 0);
+ fcntl(pr_wp.pipefd[1], F_SETFL, flags | _PR_NBIO_FLAG);
+
+#ifndef _PR_SHARE_CLONES
+ pr_InstallSigchldHandler();
+#endif
+#endif /* !_PR_NATIVE_THREADS */
+
+ pr_wp.thread = PR_CreateThread(PR_SYSTEM_THREAD,
+ WaitPidDaemonThread, NULL, PR_PRIORITY_NORMAL,
+#ifdef _PR_SHARE_CLONES
+ PR_GLOBAL_THREAD,
+#else
+ PR_LOCAL_THREAD,
+#endif
+ PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(NULL != pr_wp.thread);
+
+ pr_wp.pidTable = (pr_PidRecord**)PR_CALLOC(NBUCKETS * sizeof(pr_PidRecord *));
+ PR_ASSERT(NULL != pr_wp.pidTable);
+ return PR_SUCCESS;
+}
+
+PRStatus _MD_DetachUnixProcess(PRProcess *process)
+{
+ PRStatus retVal = PR_SUCCESS;
+ pr_PidRecord *pRec;
+
+ PR_Lock(pr_wp.ml);
+ pRec = FindPidTable(process->md.pid);
+ if (NULL == pRec) {
+ pRec = PR_NEW(pr_PidRecord);
+ if (NULL == pRec) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ retVal = PR_FAILURE;
+ goto done;
+ }
+ pRec->pid = process->md.pid;
+ pRec->state = _PR_PID_DETACHED;
+ pRec->reapedCV = NULL;
+ InsertPidTable(pRec);
+ } else {
+ PR_ASSERT(_PR_PID_REAPED == pRec->state);
+ if (_PR_PID_REAPED != pRec->state) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ retVal = PR_FAILURE;
+ } else {
+ DeletePidTable(pRec);
+ PR_ASSERT(NULL == pRec->reapedCV);
+ PR_DELETE(pRec);
+ }
+ }
+ PR_DELETE(process);
+
+done:
+ PR_Unlock(pr_wp.ml);
+ return retVal;
+}
+
+PRStatus _MD_WaitUnixProcess(
+ PRProcess *process,
+ PRInt32 *exitCode)
+{
+ pr_PidRecord *pRec;
+ PRStatus retVal = PR_SUCCESS;
+ PRBool interrupted = PR_FALSE;
+
+ PR_Lock(pr_wp.ml);
+ pRec = FindPidTable(process->md.pid);
+ if (NULL == pRec) {
+ pRec = PR_NEW(pr_PidRecord);
+ if (NULL == pRec) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ retVal = PR_FAILURE;
+ goto done;
+ }
+ pRec->pid = process->md.pid;
+ pRec->state = _PR_PID_WAITING;
+ pRec->reapedCV = PR_NewCondVar(pr_wp.ml);
+ if (NULL == pRec->reapedCV) {
+ PR_DELETE(pRec);
+ retVal = PR_FAILURE;
+ goto done;
+ }
+ InsertPidTable(pRec);
+ while (!interrupted && _PR_PID_REAPED != pRec->state) {
+ if (PR_WaitCondVar(pRec->reapedCV,
+ PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE
+ && PR_GetError() == PR_PENDING_INTERRUPT_ERROR) {
+ interrupted = PR_TRUE;
+ }
+ }
+ if (_PR_PID_REAPED == pRec->state) {
+ if (exitCode) {
+ *exitCode = pRec->exitStatus;
+ }
+ } else {
+ PR_ASSERT(interrupted);
+ retVal = PR_FAILURE;
+ }
+ DeletePidTable(pRec);
+ PR_DestroyCondVar(pRec->reapedCV);
+ PR_DELETE(pRec);
+ } else {
+ PR_ASSERT(_PR_PID_REAPED == pRec->state);
+ PR_ASSERT(NULL == pRec->reapedCV);
+ DeletePidTable(pRec);
+ if (exitCode) {
+ *exitCode = pRec->exitStatus;
+ }
+ PR_DELETE(pRec);
+ }
+ PR_DELETE(process);
+
+done:
+ PR_Unlock(pr_wp.ml);
+ return retVal;
+} /* _MD_WaitUnixProcess */
+
+PRStatus _MD_KillUnixProcess(PRProcess *process)
+{
+ PRErrorCode prerror;
+ PRInt32 oserror;
+
+ if (kill(process->md.pid, SIGKILL) == 0) {
+ return PR_SUCCESS;
+ }
+ oserror = errno;
+ switch (oserror) {
+ case EPERM:
+ prerror = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ESRCH:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, oserror);
+ return PR_FAILURE;
+} /* _MD_KillUnixProcess */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxrng.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxrng.c
new file mode 100644
index 00000000..9099c5ff
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxrng.c
@@ -0,0 +1,340 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#include "primpl.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+
+
+#if defined(SOLARIS)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ hrtime_t t;
+ t = gethrtime();
+ if (t) {
+ return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
+ }
+ return 0;
+}
+
+#elif defined(SUNOS4)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+#elif defined(HPUX)
+
+#ifdef __ia64
+#include <ia64/sys/inline.h>
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ PRUint64 t;
+
+ t = _Asm_mov_from_ar(_AREG44);
+ return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
+}
+#else
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ extern int ret_cr16();
+ int cr16val;
+
+ cr16val = ret_cr16();
+ return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val)));
+}
+#endif
+
+#elif defined(OSF1)
+
+#include <c_asm.h>
+
+/*
+ * Use the "get the cycle counter" instruction on the alpha.
+ * The low 32 bits completely turn over in less than a minute.
+ * The high 32 bits are some non-counter gunk that changes sometimes.
+ */
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ unsigned long t;
+
+#ifdef __GNUC__
+ __asm__("rpcc %0" : "=r" (t));
+#else
+ t = asm("rpcc %v0");
+#endif
+ return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
+}
+
+#elif defined(VMS)
+
+#include <ints.h>
+
+/*
+ * Use the "get the cycle counter" instruction on the alpha.
+ * The low 32 bits completely turn over in less than a minute.
+ * The high 32 bits are some non-counter gunk that changes sometimes.
+ */
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ uint64 t;
+
+ t = __RPCC();
+ return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
+}
+
+#elif defined(AIX)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+#elif (defined(LINUX) || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD))
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static int fdDevRandom;
+static PRCallOnceType coOpenDevRandom;
+
+static PRStatus OpenDevRandom( void )
+{
+ fdDevRandom = open( "/dev/random", O_RDONLY );
+ return((-1 == fdDevRandom)? PR_FAILURE : PR_SUCCESS );
+} /* end OpenDevRandom() */
+
+static size_t GetDevRandom( void *buf, size_t size )
+{
+ int bytesIn;
+ int rc;
+
+ rc = PR_CallOnce( &coOpenDevRandom, OpenDevRandom );
+ if ( PR_FAILURE == rc ) {
+ _PR_MD_MAP_OPEN_ERROR( errno );
+ return(0);
+ }
+
+ bytesIn = read( fdDevRandom, buf, size );
+ if ( -1 == bytesIn ) {
+ _PR_MD_MAP_READ_ERROR( errno );
+ return(0);
+ }
+
+ return( bytesIn );
+} /* end GetDevRandom() */
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return(GetDevRandom( buf, maxbytes ));
+}
+
+#elif defined(NCR)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+#elif defined(IRIX)
+#include <fcntl.h>
+#undef PRIVATE
+#include <sys/mman.h>
+#include <sys/syssgi.h>
+#include <sys/immu.h>
+#include <sys/systeminfo.h>
+#include <sys/utsname.h>
+
+static size_t GetHighResClock(void *buf, size_t maxbuf)
+{
+ unsigned phys_addr, raddr, cycleval;
+ static volatile unsigned *iotimer_addr = NULL;
+ static int tries = 0;
+ static int cntr_size;
+ int mfd;
+ unsigned s0[2];
+
+#ifndef SGI_CYCLECNTR_SIZE
+#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */
+#endif
+
+ if (iotimer_addr == NULL) {
+ if (tries++ > 1) {
+ /* Don't keep trying if it didn't work */
+ return 0;
+ }
+
+ /*
+ ** For SGI machines we can use the cycle counter, if it has one,
+ ** to generate some truly random numbers
+ */
+ phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
+ if (phys_addr) {
+ int pgsz = getpagesize();
+ int pgoffmask = pgsz - 1;
+
+ raddr = phys_addr & ~pgoffmask;
+ mfd = open("/dev/mmem", O_RDONLY);
+ if (mfd < 0) {
+ return 0;
+ }
+ iotimer_addr = (unsigned *)
+ mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
+ if (iotimer_addr == (unsigned*)-1) {
+ close(mfd);
+ iotimer_addr = NULL;
+ return 0;
+ }
+ iotimer_addr = (unsigned*)
+ ((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
+ /*
+ * The file 'mfd' is purposefully not closed.
+ */
+ cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
+ if (cntr_size < 0) {
+ struct utsname utsinfo;
+
+ /*
+ * We must be executing on a 6.0 or earlier system, since the
+ * SGI_CYCLECNTR_SIZE call is not supported.
+ *
+ * The only pre-6.1 platforms with 64-bit counters are
+ * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
+ */
+ uname(&utsinfo);
+ if (!strncmp(utsinfo.machine, "IP19", 4) ||
+ !strncmp(utsinfo.machine, "IP21", 4))
+ cntr_size = 64;
+ else
+ cntr_size = 32;
+ }
+ cntr_size /= 8; /* Convert from bits to bytes */
+ }
+ }
+
+ s0[0] = *iotimer_addr;
+ if (cntr_size > 4)
+ s0[1] = *(iotimer_addr + 1);
+ memcpy(buf, (char *)&s0[0], cntr_size);
+ return _pr_CopyLowBits(buf, maxbuf, &s0, cntr_size);
+}
+
+#elif defined(SONY)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+
+#elif defined(SNI)
+#include <sys/times.h>
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ int ticks;
+ struct tms buffer;
+
+ ticks=times(&buffer);
+ return _pr_CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
+}
+
+#elif defined(NEC)
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ return 0;
+}
+#elif defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(NTO) \
+ || defined(QNX) || defined(DARWIN)
+#include <sys/times.h>
+
+static size_t
+GetHighResClock(void *buf, size_t maxbytes)
+{
+ int ticks;
+ struct tms buffer;
+
+ ticks=times(&buffer);
+ return _pr_CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
+}
+#else
+#error! Platform undefined
+#endif /* defined(SOLARIS) */
+
+extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
+{
+ struct timeval tv;
+ int n = 0;
+ int s;
+
+ n += GetHighResClock(buf, size);
+ size -= n;
+
+ GETTIMEOFDAY(&tv);
+
+ if ( size > 0 ) {
+ s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec));
+ size -= s;
+ n += s;
+ }
+ if ( size > 0 ) {
+ s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec));
+ size -= s;
+ n += s;
+ }
+
+ return n;
+} /* end _PR_MD_GetRandomNoise() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxshm.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxshm.c
new file mode 100644
index 00000000..6f3192fd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxshm.c
@@ -0,0 +1,658 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** uxshm.c -- Unix Implementations NSPR Named Shared Memory
+**
+**
+** lth. Jul-1999.
+**
+*/
+#include <string.h>
+#include <prshm.h>
+#include <prerr.h>
+#include <prmem.h>
+#include "primpl.h"
+#include <fcntl.h>
+
+extern PRLogModuleInfo *_pr_shm_lm;
+
+
+#define NSPR_IPC_SHM_KEY 'b'
+/*
+** Implementation for System V
+*/
+#if defined PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define _MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory
+#define _MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory
+#define _MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory
+#define _MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory
+#define _MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory
+
+extern PRSharedMemory * _MD_OpenSharedMemory(
+ const char *name,
+ PRSize size,
+ PRIntn flags,
+ PRIntn mode
+)
+{
+ PRStatus rc = PR_SUCCESS;
+ key_t key;
+ PRSharedMemory *shm;
+ char ipcname[PR_IPC_NAME_SIZE];
+
+ rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
+ if ( PR_FAILURE == rc )
+ {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name ));
+ return( NULL );
+ }
+
+ shm = PR_NEWZAP( PRSharedMemory );
+ if ( NULL == shm )
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory"));
+ return( NULL );
+ }
+
+ shm->ipcname = (char*)PR_MALLOC( strlen( ipcname ) + 1 );
+ if ( NULL == shm->ipcname )
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory"));
+ return( NULL );
+ }
+
+ /* copy args to struct */
+ strcpy( shm->ipcname, ipcname );
+ shm->size = size;
+ shm->mode = mode;
+ shm->flags = flags;
+ shm->ident = _PR_SHM_IDENT;
+
+ /* create the file first */
+ if ( flags & PR_SHM_CREATE ) {
+ int osfd = open( shm->ipcname, (O_RDWR | O_CREAT), shm->mode );
+ if ( -1 == osfd ) {
+ _PR_MD_MAP_OPEN_ERROR( errno );
+ PR_FREEIF( shm->ipcname );
+ PR_DELETE( shm );
+ return( NULL );
+ }
+ if ( close(osfd) == -1 ) {
+ _PR_MD_MAP_CLOSE_ERROR( errno );
+ PR_FREEIF( shm->ipcname );
+ PR_DELETE( shm );
+ return( NULL );
+ }
+ }
+
+ /* hash the shm.name to an ID */
+ key = ftok( shm->ipcname, NSPR_IPC_SHM_KEY );
+ if ( -1 == key )
+ {
+ rc = PR_FAILURE;
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): ftok() failed on name: %s", shm->ipcname));
+ PR_FREEIF( shm->ipcname );
+ PR_DELETE( shm );
+ return( NULL );
+ }
+
+ /* get the shared memory */
+ if ( flags & PR_SHM_CREATE ) {
+ shm->id = shmget( key, shm->size, ( shm->mode | IPC_CREAT|IPC_EXCL));
+ if ( shm->id >= 0 ) {
+ return( shm );
+ }
+ if ((errno == EEXIST) && (flags & PR_SHM_EXCL)) {
+ PR_SetError( PR_FILE_EXISTS_ERROR, errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): shmget() exclusive failed, errno: %d", errno));
+ PR_FREEIF(shm->ipcname);
+ PR_DELETE(shm);
+ return(NULL);
+ }
+ }
+
+ shm->id = shmget( key, shm->size, shm->mode );
+ if ( -1 == shm->id ) {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): shmget() failed, errno: %d", errno));
+ PR_FREEIF(shm->ipcname);
+ PR_DELETE(shm);
+ return(NULL);
+ }
+
+ return( shm );
+} /* end _MD_OpenSharedMemory() */
+
+extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags )
+{
+ void *addr;
+ PRUint32 aFlags = shm->mode;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ aFlags |= (flags & PR_SHM_READONLY )? SHM_RDONLY : 0;
+
+ addr = shmat( shm->id, NULL, aFlags );
+ if ( (void*)-1 == addr )
+ {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_AttachSharedMemory(): shmat() failed on name: %s, OsError: %d",
+ shm->ipcname, PR_GetOSError() ));
+ addr = NULL;
+ }
+
+ return addr;
+}
+
+extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr )
+{
+ PRStatus rc = PR_SUCCESS;
+ PRIntn urc;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ urc = shmdt( addr );
+ if ( -1 == urc )
+ {
+ rc = PR_FAILURE;
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DetachSharedMemory(): shmdt() failed on name: %s", shm->ipcname ));
+ }
+
+ return rc;
+}
+
+extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm )
+{
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ PR_FREEIF(shm->ipcname);
+ PR_DELETE(shm);
+
+ return PR_SUCCESS;
+}
+
+extern PRStatus _MD_DeleteSharedMemory( const char *name )
+{
+ PRStatus rc = PR_SUCCESS;
+ key_t key;
+ int id;
+ PRIntn urc;
+ char ipcname[PR_IPC_NAME_SIZE];
+
+ rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR , errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name ));
+ return(PR_FAILURE);
+ }
+
+ /* create the file first */
+ {
+ int osfd = open( ipcname, (O_RDWR | O_CREAT), 0666 );
+ if ( -1 == osfd ) {
+ _PR_MD_MAP_OPEN_ERROR( errno );
+ return( PR_FAILURE );
+ }
+ if ( close(osfd) == -1 ) {
+ _PR_MD_MAP_CLOSE_ERROR( errno );
+ return( PR_FAILURE );
+ }
+ }
+
+ /* hash the shm.name to an ID */
+ key = ftok( ipcname, NSPR_IPC_SHM_KEY );
+ if ( -1 == key )
+ {
+ rc = PR_FAILURE;
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): ftok() failed on name: %s", ipcname));
+ }
+
+ id = shmget( key, 0, 0 );
+ if ( -1 == id ) {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): shmget() failed, errno: %d", errno));
+ return(PR_FAILURE);
+ }
+
+ urc = shmctl( id, IPC_RMID, NULL );
+ if ( -1 == urc )
+ {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): shmctl() failed on name: %s", ipcname ));
+ return(PR_FAILURE);
+ }
+
+ urc = unlink( ipcname );
+ if ( -1 == urc ) {
+ _PR_MD_MAP_UNLINK_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): unlink() failed: %s", ipcname ));
+ return(PR_FAILURE);
+ }
+
+ return rc;
+} /* end _MD_DeleteSharedMemory() */
+
+/*
+** Implementation for Posix
+*/
+#elif defined PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+#include <sys/mman.h>
+
+#define _MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory
+#define _MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory
+#define _MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory
+#define _MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory
+#define _MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory
+
+struct _MDSharedMemory {
+ int handle;
+};
+
+extern PRSharedMemory * _MD_OpenSharedMemory(
+ const char *name,
+ PRSize size,
+ PRIntn flags,
+ PRIntn mode
+)
+{
+ PRStatus rc = PR_SUCCESS;
+ PRInt32 end;
+ PRSharedMemory *shm;
+ char ipcname[PR_IPC_NAME_SIZE];
+
+ rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR , errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name ));
+ return( NULL );
+ }
+
+ shm = PR_NEWZAP( PRSharedMemory );
+ if ( NULL == shm )
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory"));
+ return( NULL );
+ }
+
+ shm->ipcname = PR_MALLOC( strlen( ipcname ) + 1 );
+ if ( NULL == shm->ipcname )
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory"));
+ return( NULL );
+ }
+
+ /* copy args to struct */
+ strcpy( shm->ipcname, ipcname );
+ shm->size = size;
+ shm->mode = mode;
+ shm->flags = flags;
+ shm->ident = _PR_SHM_IDENT;
+
+ /*
+ ** Create the shared memory
+ */
+ if ( flags & PR_SHM_CREATE ) {
+ int oflag = (O_CREAT | O_RDWR);
+
+ if ( flags & PR_SHM_EXCL )
+ oflag |= O_EXCL;
+ shm->id = shm_open( shm->ipcname, oflag, shm->mode );
+ } else {
+ shm->id = shm_open( shm->ipcname, O_RDWR, shm->mode );
+ }
+
+ if ( -1 == shm->id ) {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): shm_open failed: %s, OSError: %d",
+ shm->ipcname, PR_GetOSError()));
+ PR_DELETE( shm->ipcname );
+ PR_DELETE( shm );
+ return(NULL);
+ }
+
+ end = ftruncate( shm->id, shm->size );
+ if ( -1 == end ) {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): ftruncate failed, OSError: %d",
+ PR_GetOSError()));
+ PR_DELETE( shm->ipcname );
+ PR_DELETE( shm );
+ return(NULL);
+ }
+
+ return(shm);
+} /* end _MD_OpenSharedMemory() */
+
+extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags )
+{
+ void *addr;
+ PRIntn prot = (PROT_READ | PROT_WRITE);
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ if ( PR_SHM_READONLY == flags)
+ prot ^= PROT_WRITE;
+
+ addr = mmap( (void*)0, shm->size, prot, MAP_SHARED, shm->id, 0 );
+ if ((void*)-1 == addr )
+ {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_AttachSharedMemory(): mmap failed: %s, errno: %d",
+ shm->ipcname, PR_GetOSError()));
+ addr = NULL;
+ } else {
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_AttachSharedMemory(): name: %s, attached at: %p", shm->ipcname, addr));
+ }
+
+ return addr;
+}
+
+extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr )
+{
+ PRStatus rc = PR_SUCCESS;
+ PRIntn urc;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ urc = munmap( addr, shm->size );
+ if ( -1 == urc )
+ {
+ rc = PR_FAILURE;
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DetachSharedMemory(): munmap failed: %s, errno: %d",
+ shm->ipcname, PR_GetOSError()));
+ }
+ return rc;
+}
+
+extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm )
+{
+ int urc;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ urc = close( shm->id );
+ if ( -1 == urc ) {
+ _PR_MD_MAP_CLOSE_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_CloseSharedMemory(): close() failed, error: %d", PR_GetOSError()));
+ return(PR_FAILURE);
+ }
+ PR_DELETE( shm->ipcname );
+ PR_DELETE( shm );
+ return PR_SUCCESS;
+}
+
+extern PRStatus _MD_DeleteSharedMemory( const char *name )
+{
+ PRStatus rc = PR_SUCCESS;
+ PRUintn urc;
+ char ipcname[PR_IPC_NAME_SIZE];
+
+ rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR , errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name ));
+ return rc;
+ }
+
+ urc = shm_unlink( ipcname );
+ if ( -1 == urc ) {
+ rc = PR_FAILURE;
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): shm_unlink failed: %s, errno: %d",
+ ipcname, PR_GetOSError()));
+ } else {
+ PR_LOG( _pr_shm_lm, PR_LOG_DEBUG,
+ ("_MD_DeleteSharedMemory(): %s, success", ipcname));
+ }
+
+ return rc;
+} /* end _MD_DeleteSharedMemory() */
+#endif
+
+
+
+/*
+** Unix implementation for anonymous memory (file) mapping
+*/
+extern PRLogModuleInfo *_pr_shma_lm;
+
+#include <unistd.h>
+
+extern PRFileMap* _md_OpenAnonFileMap(
+ const char *dirName,
+ PRSize size,
+ PRFileMapProtect prot
+)
+{
+ PRFileMap *fm = NULL;
+ PRFileDesc *fd;
+ int osfd;
+ PRIntn urc;
+ PRIntn mode = 0600;
+ char *genName;
+ pid_t pid = getpid(); /* for generating filename */
+ PRThread *tid = PR_GetCurrentThread(); /* for generating filename */
+ int incr; /* for generating filename */
+ const int maxTries = 20; /* maximum # attempts at a unique filename */
+ PRInt64 size64; /* 64-bit version of 'size' */
+
+ /*
+ ** generate a filename from input and runtime environment
+ ** open the file, unlink the file.
+ ** make maxTries number of attempts at uniqueness in the filename
+ */
+ for ( incr = 0; incr < maxTries ; incr++ ) {
+ genName = PR_smprintf( "%s/.NSPR-AFM-%d-%p.%d",
+ dirName, (int) pid, tid, incr );
+ if ( NULL == genName ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): PR_snprintf(): failed, generating filename"));
+ goto Finished;
+ }
+
+ /* create the file */
+ osfd = open( genName, (O_CREAT | O_EXCL | O_RDWR), mode );
+ if ( -1 == osfd ) {
+ if ( EEXIST == errno ) {
+ PR_smprintf_free( genName );
+ continue; /* name exists, try again */
+ } else {
+ _PR_MD_MAP_OPEN_ERROR( errno );
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): open(): failed, filename: %s, errno: %d",
+ genName, PR_GetOSError()));
+ PR_smprintf_free( genName );
+ goto Finished;
+ }
+ }
+ break; /* name generation and open successful, break; */
+ } /* end for() */
+
+ if ( incr == maxTries ) {
+ PR_ASSERT( -1 == osfd );
+ PR_ASSERT( EEXIST == errno );
+ _PR_MD_MAP_OPEN_ERROR( errno );
+ goto Finished;
+ }
+
+ urc = unlink( genName );
+ if ( -1 == urc ) {
+ _PR_MD_MAP_UNLINK_ERROR( errno );
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): failed on unlink(), errno: %d", errno));
+ PR_smprintf_free( genName );
+ close( osfd );
+ goto Finished;
+ }
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): unlink(): %s", genName ));
+
+ PR_smprintf_free( genName );
+
+ fd = PR_ImportFile( osfd );
+ if ( NULL == fd ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): PR_ImportFile(): failed"));
+ goto Finished;
+ }
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): fd: %p", fd ));
+
+ urc = ftruncate( fd->secret->md.osfd, size );
+ if ( -1 == urc ) {
+ _PR_MD_MAP_DEFAULT_ERROR( errno );
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): failed on ftruncate(), errno: %d", errno));
+ PR_Close( fd );
+ goto Finished;
+ }
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): ftruncate(): size: %d", size ));
+
+ LL_UI2L(size64, size); /* PRSize (size_t) is unsigned */
+ fm = PR_CreateFileMap( fd, size64, prot );
+ if ( NULL == fm ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("PR_OpenAnonFileMap(): failed"));
+ PR_Close( fd );
+ goto Finished;
+ }
+ fm->md.isAnonFM = PR_TRUE; /* set fd close */
+
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): PR_CreateFileMap(): fm: %p", fm ));
+
+Finished:
+ return(fm);
+} /* end md_OpenAnonFileMap() */
+
+/*
+** _md_ExportFileMapAsString()
+**
+**
+*/
+extern PRStatus _md_ExportFileMapAsString(
+ PRFileMap *fm,
+ PRSize bufSize,
+ char *buf
+)
+{
+ PRIntn written;
+ PRIntn prot = (PRIntn)fm->prot;
+
+ written = PR_snprintf( buf, bufSize, "%ld:%d",
+ fm->fd->secret->md.osfd, prot );
+
+ return((written == -1)? PR_FAILURE : PR_SUCCESS);
+} /* end _md_ExportFileMapAsString() */
+
+
+extern PRFileMap * _md_ImportFileMapFromString(
+ const char *fmstring
+)
+{
+ PRStatus rc;
+ PRInt32 osfd;
+ PRIntn prot; /* really: a PRFileMapProtect */
+ PRFileDesc *fd;
+ PRFileMap *fm = NULL; /* default return value */
+ PRFileInfo64 info;
+
+ PR_sscanf( fmstring, "%ld:%d", &osfd, &prot );
+
+ /* import the os file descriptor */
+ fd = PR_ImportFile( osfd );
+ if ( NULL == fd ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_ImportFileMapFromString(): PR_ImportFile() failed"));
+ goto Finished;
+ }
+
+ rc = PR_GetOpenFileInfo64( fd, &info );
+ if ( PR_FAILURE == rc ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_ImportFileMapFromString(): PR_GetOpenFileInfo64() failed"));
+ goto Finished;
+ }
+
+ fm = PR_CreateFileMap( fd, info.size, (PRFileMapProtect)prot );
+ if ( NULL == fm ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_ImportFileMapFromString(): PR_CreateFileMap() failed"));
+ }
+
+Finished:
+ return(fm);
+} /* end _md_ImportFileMapFromString() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxwrap.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxwrap.c
new file mode 100644
index 00000000..8f69de86
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/unix/uxwrap.c
@@ -0,0 +1,548 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *------------------------------------------------------------------------
+ * File: uxwrap.c
+ *
+ * Our wrapped versions of the Unix select() and poll() system calls.
+ *
+ *------------------------------------------------------------------------
+ */
+
+#include "primpl.h"
+
+#if defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) || defined(QNX)
+/* Do not wrap select() and poll(). */
+#else /* defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) */
+/* The include files for select() */
+#ifdef IRIX
+#include <unistd.h>
+#include <bstring.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#define ZAP_SET(_to, _width) \
+ PR_BEGIN_MACRO \
+ memset(_to, 0, \
+ ((_width + 8*sizeof(int)-1) / (8*sizeof(int))) \
+ * sizeof(int) \
+ ); \
+ PR_END_MACRO
+
+/* see comments in ns/cmd/xfe/mozilla.c (look for "PR_XGetXtHackFD") */
+static int _pr_xt_hack_fd = -1;
+
+int PR_XGetXtHackFD(void)
+{
+ int fds[2];
+
+ if (_pr_xt_hack_fd == -1) {
+ if (!pipe(fds)) {
+ _pr_xt_hack_fd = fds[0];
+ }
+ }
+ return _pr_xt_hack_fd;
+}
+
+static int (*_pr_xt_hack_okayToReleaseXLock)(void) = 0;
+
+void PR_SetXtHackOkayToReleaseXLockFn(int (*fn)(void))
+{
+ _pr_xt_hack_okayToReleaseXLock = fn;
+}
+
+
+/*
+ *-----------------------------------------------------------------------
+ * select() --
+ *
+ * Wrap up the select system call so that we can deschedule
+ * a thread that tries to wait for i/o.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#if defined(HPUX9)
+int select(size_t width, int *rl, int *wl, int *el, const struct timeval *tv)
+#elif defined(NEXTSTEP)
+int wrap_select(int width, fd_set *rd, fd_set *wr, fd_set *ex,
+ const struct timeval *tv)
+#elif defined(AIX_RENAME_SELECT)
+int wrap_select(unsigned long width, void *rl, void *wl, void *el,
+ struct timeval *tv)
+#elif defined(_PR_SELECT_CONST_TIMEVAL)
+int select(int width, fd_set *rd, fd_set *wr, fd_set *ex,
+ const struct timeval *tv)
+#else
+int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
+#endif
+{
+ int osfd;
+ _PRUnixPollDesc *unixpds, *unixpd, *eunixpd;
+ PRInt32 pdcnt;
+ PRIntervalTime timeout;
+ int retVal;
+#if defined(HPUX9) || defined(AIX_RENAME_SELECT)
+ fd_set *rd = (fd_set*) rl;
+ fd_set *wr = (fd_set*) wl;
+ fd_set *ex = (fd_set*) el;
+#endif
+
+#if 0
+ /*
+ * Easy special case: zero timeout. Simply call the native
+ * select() with no fear of blocking.
+ */
+ if (tv != NULL && tv->tv_sec == 0 && tv->tv_usec == 0) {
+#if defined(HPUX9) || defined(AIX_RENAME_SELECT)
+ return _MD_SELECT(width, rl, wl, el, tv);
+#else
+ return _MD_SELECT(width, rd, wr, ex, tv);
+#endif
+ }
+#endif
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+
+#ifndef _PR_LOCAL_THREADS_ONLY
+ if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) {
+ return _MD_SELECT(width, rd, wr, ex, tv);
+ }
+#endif
+
+ if (width < 0 || width > FD_SETSIZE) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Compute timeout */
+ if (tv) {
+ /*
+ * These acceptable ranges for t_sec and t_usec are taken
+ * from the select() man pages.
+ */
+ if (tv->tv_sec < 0 || tv->tv_sec > 100000000
+ || tv->tv_usec < 0 || tv->tv_usec >= 1000000) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Convert microseconds to ticks */
+ timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec);
+ } else {
+ /* tv being a NULL pointer means blocking indefinitely */
+ timeout = PR_INTERVAL_NO_TIMEOUT;
+ }
+
+ /* Check for no descriptors case (just doing a timeout) */
+ if ((!rd && !wr && !ex) || !width) {
+ PR_Sleep(timeout);
+ return 0;
+ }
+
+ /*
+ * Set up for PR_Poll(). The PRPollDesc array is allocated
+ * dynamically. If this turns out to have high performance
+ * penalty, one can change to use a large PRPollDesc array
+ * on the stack, and allocate dynamically only when it turns
+ * out to be not large enough.
+ *
+ * I allocate an array of size 'width', which is the maximum
+ * number of fds we may need to poll.
+ */
+ unixpds = (_PRUnixPollDesc *) PR_CALLOC(width * sizeof(_PRUnixPollDesc));
+ if (!unixpds) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ pdcnt = 0;
+ unixpd = unixpds;
+ for (osfd = 0; osfd < width; osfd++) {
+ int in_flags = 0;
+ if (rd && FD_ISSET(osfd, rd)) {
+ in_flags |= _PR_UNIX_POLL_READ;
+ }
+ if (wr && FD_ISSET(osfd, wr)) {
+ in_flags |= _PR_UNIX_POLL_WRITE;
+ }
+ if (ex && FD_ISSET(osfd, ex)) {
+ in_flags |= _PR_UNIX_POLL_EXCEPT;
+ }
+ if (in_flags) {
+ unixpd->osfd = osfd;
+ unixpd->in_flags = in_flags;
+ unixpd->out_flags = 0;
+ unixpd++;
+ pdcnt++;
+ }
+ }
+
+ /*
+ * see comments in mozilla/cmd/xfe/mozilla.c (look for
+ * "PR_XGetXtHackFD")
+ */
+ {
+ int needToLockXAgain;
+
+ needToLockXAgain = 0;
+ if (rd && (_pr_xt_hack_fd != -1)
+ && FD_ISSET(_pr_xt_hack_fd, rd) && PR_XIsLocked()
+ && (!_pr_xt_hack_okayToReleaseXLock
+ || _pr_xt_hack_okayToReleaseXLock())) {
+ PR_XUnlock();
+ needToLockXAgain = 1;
+ }
+
+ /* This is the potentially blocking step */
+ retVal = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);
+
+ if (needToLockXAgain) {
+ PR_XLock();
+ }
+ }
+
+ if (retVal > 0) {
+ /* Compute select results */
+ if (rd) ZAP_SET(rd, width);
+ if (wr) ZAP_SET(wr, width);
+ if (ex) ZAP_SET(ex, width);
+
+ /*
+ * The return value can be either the number of ready file
+ * descriptors or the number of set bits in the three fd_set's.
+ */
+ retVal = 0; /* we're going to recompute */
+ eunixpd = unixpds + pdcnt;
+ for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
+ if (unixpd->out_flags) {
+ int nbits = 0; /* The number of set bits on for this fd */
+
+ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
+ errno = EBADF;
+ PR_LOG(_pr_io_lm, PR_LOG_ERROR,
+ ("select returns EBADF for %d", unixpd->osfd));
+ retVal = -1;
+ break;
+ }
+ /*
+ * If a socket has a pending error, it is considered
+ * both readable and writable. (See W. Richard Stevens,
+ * Unix Network Programming, Vol. 1, 2nd Ed., Section 6.3,
+ * pp. 153-154.) We also consider a socket readable if
+ * it has a hangup condition.
+ */
+ if (rd && (unixpd->in_flags & _PR_UNIX_POLL_READ)
+ && (unixpd->out_flags & (_PR_UNIX_POLL_READ
+ | _PR_UNIX_POLL_ERR | _PR_UNIX_POLL_HUP))) {
+ FD_SET(unixpd->osfd, rd);
+ nbits++;
+ }
+ if (wr && (unixpd->in_flags & _PR_UNIX_POLL_WRITE)
+ && (unixpd->out_flags & (_PR_UNIX_POLL_WRITE
+ | _PR_UNIX_POLL_ERR))) {
+ FD_SET(unixpd->osfd, wr);
+ nbits++;
+ }
+ if (ex && (unixpd->in_flags & _PR_UNIX_POLL_WRITE)
+ && (unixpd->out_flags & PR_POLL_EXCEPT)) {
+ FD_SET(unixpd->osfd, ex);
+ nbits++;
+ }
+ PR_ASSERT(nbits > 0);
+#if defined(HPUX) || defined(SOLARIS) || defined(SUNOS4) || defined(OSF1) || defined(AIX)
+ retVal += nbits;
+#else /* IRIX */
+ retVal += 1;
+#endif
+ }
+ }
+ }
+
+ PR_ASSERT(tv || retVal != 0);
+ PR_LOG(_pr_io_lm, PR_LOG_MIN, ("select returns %d", retVal));
+ PR_DELETE(unixpds);
+
+ return retVal;
+}
+
+/*
+ * Redefine poll, when supported on platforms, for local threads
+ */
+
+/*
+ * I am commenting out the poll() wrapper for Linux for now
+ * because it is difficult to define _MD_POLL that works on all
+ * Linux varieties. People reported that glibc 2.0.7 on Debian
+ * 2.0 Linux machines doesn't have the __syscall_poll symbol
+ * defined. (WTC 30 Nov. 1998)
+ */
+#if defined(_PR_POLL_AVAILABLE) && !defined(LINUX)
+
+/*
+ *-----------------------------------------------------------------------
+ * poll() --
+ *
+ * RETURN VALUES:
+ * -1: fails, errno indicates the error.
+ * 0: timed out, the revents bitmasks are not set.
+ * positive value: the number of file descriptors for which poll()
+ * has set the revents bitmask.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#include <poll.h>
+
+#if defined(AIX_RENAME_SELECT)
+int wrap_poll(void *listptr, unsigned long nfds, long timeout)
+#elif (defined(AIX) && !defined(AIX_RENAME_SELECT))
+int poll(void *listptr, unsigned long nfds, long timeout)
+#elif defined(OSF1) || (defined(HPUX) && !defined(HPUX9))
+int poll(struct pollfd filedes[], unsigned int nfds, int timeout)
+#elif defined(HPUX9)
+int poll(struct pollfd filedes[], int nfds, int timeout)
+#elif defined(NETBSD)
+int poll(struct pollfd *filedes, nfds_t nfds, int timeout)
+#elif defined(OPENBSD)
+int poll(struct pollfd *filedes, int nfds, int timeout)
+#elif defined(FREEBSD)
+int poll(struct pollfd *filedes, unsigned nfds, int timeout)
+#else
+int poll(struct pollfd *filedes, unsigned long nfds, int timeout)
+#endif
+{
+#ifdef AIX
+ struct pollfd *filedes = (struct pollfd *) listptr;
+#endif
+ struct pollfd *pfd, *epfd;
+ _PRUnixPollDesc *unixpds, *unixpd, *eunixpd;
+ PRIntervalTime ticks;
+ PRInt32 pdcnt;
+ int ready;
+
+ /*
+ * Easy special case: zero timeout. Simply call the native
+ * poll() with no fear of blocking.
+ */
+ if (timeout == 0) {
+#if defined(AIX)
+ return _MD_POLL(listptr, nfds, timeout);
+#else
+ return _MD_POLL(filedes, nfds, timeout);
+#endif
+ }
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+
+#ifndef _PR_LOCAL_THREADS_ONLY
+ if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) {
+ return _MD_POLL(filedes, nfds, timeout);
+ }
+#endif
+
+ /* We do not support the pollmsg structures on AIX */
+#ifdef AIX
+ PR_ASSERT((nfds & 0xff00) == 0);
+#endif
+
+ if (timeout < 0 && timeout != -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Convert timeout from miliseconds to ticks */
+ if (timeout == -1) {
+ ticks = PR_INTERVAL_NO_TIMEOUT;
+ } else {
+ ticks = PR_MillisecondsToInterval(timeout);
+ }
+
+ /* Check for no descriptor case (just do a timeout) */
+ if (nfds == 0) {
+ PR_Sleep(ticks);
+ return 0;
+ }
+
+ unixpds = (_PRUnixPollDesc *)
+ PR_MALLOC(nfds * sizeof(_PRUnixPollDesc));
+ if (NULL == unixpds) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ pdcnt = 0;
+ epfd = filedes + nfds;
+ unixpd = unixpds;
+ for (pfd = filedes; pfd < epfd; pfd++) {
+ /*
+ * poll() ignores negative fd's.
+ */
+ if (pfd->fd >= 0) {
+ unixpd->osfd = pfd->fd;
+#ifdef _PR_USE_POLL
+ unixpd->in_flags = pfd->events;
+#else
+ /*
+ * Map the poll events to one of the three that can be
+ * represented by the select fd_sets:
+ * POLLIN, POLLRDNORM ===> readable
+ * POLLOUT, POLLWRNORM ===> writable
+ * POLLPRI, POLLRDBAND ===> exception
+ * POLLNORM, POLLWRBAND (and POLLMSG on some platforms)
+ * are ignored.
+ *
+ * The output events POLLERR and POLLHUP are never turned on.
+ * POLLNVAL may be turned on.
+ */
+ unixpd->in_flags = 0;
+ if (pfd->events & (POLLIN
+#ifdef POLLRDNORM
+ | POLLRDNORM
+#endif
+ )) {
+ unixpd->in_flags |= _PR_UNIX_POLL_READ;
+ }
+ if (pfd->events & (POLLOUT
+#ifdef POLLWRNORM
+ | POLLWRNORM
+#endif
+ )) {
+ unixpd->in_flags |= _PR_UNIX_POLL_WRITE;
+ }
+ if (pfd->events & (POLLPRI
+#ifdef POLLRDBAND
+ | POLLRDBAND
+#endif
+ )) {
+ unixpd->in_flags |= PR_POLL_EXCEPT;
+ }
+#endif /* _PR_USE_POLL */
+ unixpd->out_flags = 0;
+ unixpd++;
+ pdcnt++;
+ }
+ }
+
+ ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, ticks);
+ if (-1 == ready) {
+ if (PR_GetError() == PR_PENDING_INTERRUPT_ERROR) {
+ errno = EINTR; /* XXX we aren't interrupted by a signal, but... */
+ } else {
+ errno = PR_GetOSError();
+ }
+ }
+ if (ready <= 0) {
+ goto done;
+ }
+
+ /*
+ * Copy the out_flags from the _PRUnixPollDesc structures to the
+ * user's pollfd structures and free the allocated memory
+ */
+ unixpd = unixpds;
+ for (pfd = filedes; pfd < epfd; pfd++) {
+ pfd->revents = 0;
+ if (pfd->fd >= 0) {
+#ifdef _PR_USE_POLL
+ pfd->revents = unixpd->out_flags;
+#else
+ if (0 != unixpd->out_flags) {
+ if (unixpd->out_flags & _PR_UNIX_POLL_READ) {
+ if (pfd->events & POLLIN) {
+ pfd->revents |= POLLIN;
+ }
+#ifdef POLLRDNORM
+ if (pfd->events & POLLRDNORM) {
+ pfd->revents |= POLLRDNORM;
+ }
+#endif
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) {
+ if (pfd->events & POLLOUT) {
+ pfd->revents |= POLLOUT;
+ }
+#ifdef POLLWRNORM
+ if (pfd->events & POLLWRNORM) {
+ pfd->revents |= POLLWRNORM;
+ }
+#endif
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) {
+ if (pfd->events & POLLPRI) {
+ pfd->revents |= POLLPRI;
+ }
+#ifdef POLLRDBAND
+ if (pfd->events & POLLRDBAND) {
+ pfd->revents |= POLLRDBAND;
+ }
+#endif
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_ERR) {
+ pfd->revents |= POLLERR;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
+ pfd->revents |= POLLNVAL;
+ }
+ if (unixpd->out_flags & _PR_UNIX_POLL_HUP) {
+ pfd->revents |= POLLHUP;
+ }
+ }
+#endif /* _PR_USE_POLL */
+ unixpd++;
+ }
+ }
+
+done:
+ PR_DELETE(unixpds);
+ return ready;
+}
+
+#endif /* !defined(LINUX) */
+
+#endif /* defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) */
+
+/* uxwrap.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/Makefile.in
new file mode 100644
index 00000000..c97c9821
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/Makefile.in
@@ -0,0 +1,121 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_TARGET), WIN16)
+CSRCS = \
+ w16null.c \
+ w16thred.c \
+ w16proc.c \
+ w16fmem.c \
+ w16sock.c \
+ w16mem.c \
+ w16io.c \
+ w16gc.c \
+ w16error.c \
+ w16stdio.c \
+ w16callb.c \
+ ntinrval.c \
+ $(NULL)
+else
+ifeq ($(OS_TARGET), WIN95)
+CSRCS = \
+ ntmisc.c \
+ ntsec.c \
+ ntsem.c \
+ ntinrval.c \
+ ntgc.c \
+ w95thred.c \
+ w95io.c \
+ w95cv.c \
+ w32rng.c \
+ w95sock.c \
+ win32_errors.c \
+ w32ipcsem.c \
+ w32poll.c \
+ w32shm.c \
+ w95dllmain.c \
+ $(NULL)
+else
+CSRCS = \
+ ntdllmn.c \
+ ntmisc.c \
+ ntsec.c \
+ ntsem.c \
+ ntinrval.c \
+ ntgc.c \
+ ntthread.c \
+ ntio.c \
+ win32_errors.c \
+ w32ipcsem.c \
+ w32poll.c \
+ w32rng.c \
+ w32shm.c \
+ $(NULL)
+endif
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
+# Bug 122433 workaround: disable global optimization (-Og-) on ntio.c.
+ifdef BUILD_OPT
+ifeq ($(OS_TARGET), WINNT)
+ifndef NS_USE_GCC
+$(OBJDIR)/ntio.$(OBJ_SUFFIX): ntio.c
+ @$(MAKE_OBJDIR)
+ $(CC) -Fo$@ -c $(CFLAGS) -Og- $<
+endif
+endif
+endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntdllmn.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntdllmn.c
new file mode 100644
index 00000000..fa8d25f6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntdllmn.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * The DLL entry point (DllMain) for NSPR.
+ *
+ * The only reason we use DLLMain() now is to find out whether
+ * the NSPR DLL is statically or dynamically loaded. When
+ * dynamically loaded, we cannot use static thread-local storage.
+ * However, static TLS is faster than the TlsXXX() functions.
+ * So we want to use static TLS whenever we can. A global
+ * variable _pr_use_static_tls is set in DllMain() during process
+ * attachment to indicate whether it is safe to use static TLS
+ * or not.
+ */
+
+#include <windows.h>
+#include <primpl.h>
+
+extern BOOL _pr_use_static_tls; /* defined in ntthread.c */
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+PRThread *me;
+
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ /*
+ * If lpvReserved is NULL, we are dynamically loaded
+ * and therefore can't use static thread-local storage.
+ */
+ if (lpvReserved == NULL) {
+ _pr_use_static_tls = FALSE;
+ } else {
+ _pr_use_static_tls = TRUE;
+ }
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ if (_pr_initialized) {
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ }
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntgc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntgc.c
new file mode 100644
index 00000000..12af4846
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntgc.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * GC related routines
+ *
+ */
+#include <windows.h>
+#include "primpl.h"
+
+PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+#if defined(_X86_)
+ CONTEXT context;
+ context.ContextFlags = CONTEXT_INTEGER;
+
+ if (_PR_IS_NATIVE_THREAD(t)) {
+ context.ContextFlags |= CONTEXT_CONTROL;
+ if (GetThreadContext(t->md.handle, &context)) {
+ t->md.gcContext[0] = context.Eax;
+ t->md.gcContext[1] = context.Ebx;
+ t->md.gcContext[2] = context.Ecx;
+ t->md.gcContext[3] = context.Edx;
+ t->md.gcContext[4] = context.Esi;
+ t->md.gcContext[5] = context.Edi;
+ t->md.gcContext[6] = context.Esp;
+ t->md.gcContext[7] = context.Ebp;
+ *np = PR_NUM_GCREGS;
+ } else {
+ PR_ASSERT(0);/* XXX */
+ }
+ } else {
+ /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * This code is extremely machine dependant and completely
+ * undocumented by MS. Its only known to work experimentally.
+ * Ready for a walk on the wild * side?
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
+
+#if !defined WIN95 // Win95 does not have fibers
+ int *fiberData = t->md.fiber_id;
+
+ /* I found these offsets by disassembling SwitchToFiber().
+ * Are your palms sweating yet?
+ */
+
+ /*
+ ** EAX is on the stack (ESP+0)
+ ** EDX is on the stack (ESP+4)
+ ** ECX is on the stack (ESP+8)
+ */
+ t->md.gcContext[0] = 0; /* context.Eax */
+ t->md.gcContext[1] = fiberData[0x2e]; /* context.Ebx */
+ t->md.gcContext[2] = 0; /* context.Ecx */
+ t->md.gcContext[2] = 0; /* context.Edx */
+ t->md.gcContext[4] = fiberData[0x2d]; /* context.Esi */
+ t->md.gcContext[5] = fiberData[0x2c]; /* context.Edi */
+ t->md.gcContext[6] = fiberData[0x36]; /* context.Esp */
+ t->md.gcContext[7] = fiberData[0x32]; /* context.Ebp */
+ *np = PR_NUM_GCREGS;
+#endif
+ }
+ return (PRWord *)&t->md.gcContext;
+#elif defined(_ALPHA_)
+#endif /* defined(_X86_) */
+}
+
+/* This function is not used right now, but is left as a reference.
+ * If you ever need to get the fiberID from the currently running fiber,
+ * this is it.
+ */
+void *
+GetMyFiberID()
+{
+#if defined(_X86_) && !defined(__MINGW32__)
+ void *fiberData;
+
+ /* A pointer to our tib entry is found at FS:[18]
+ * At offset 10h is the fiberData pointer. The context of the
+ * fiber is stored in there.
+ */
+ __asm {
+ mov EDX, FS:[18h]
+ mov EAX, DWORD PTR [EDX+10h]
+ mov [fiberData], EAX
+ }
+
+ return fiberData;
+#elif defined(_ALPHA_)
+#endif /* defined(_X86_) */
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntinrval.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntinrval.c
new file mode 100644
index 00000000..494f6e83
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntinrval.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * NT interval timers
+ *
+ */
+
+#include "primpl.h"
+
+#if defined(WIN16)
+#include <win/compobj.h>
+#define QueryPerformanceFrequency(x) FALSE
+#define QueryPerformanceCounter(x) FALSE
+#endif
+
+static PRIntn _nt_bitShift = 0;
+static PRInt32 _nt_ticksPerSec = -1;
+
+void
+_PR_MD_INTERVAL_INIT()
+{
+ LARGE_INTEGER count;
+
+ if (QueryPerformanceFrequency(&count)) {
+ /*
+ * HighPart is signed (LONG). Assert that its sign bit is 0
+ * because we will be right shifting it. LowPart is unsigned
+ * (DWORD).
+ */
+ PR_ASSERT(count.HighPart >= 0);
+ while(count.HighPart) {
+ count.LowPart = (count.HighPart << 31) + (count.LowPart >> 1);
+ count.HighPart >>= 1;
+ _nt_bitShift++;
+ }
+ while(count.LowPart > PR_INTERVAL_MAX) {
+ count.LowPart >>= 1;
+ _nt_bitShift++;
+ }
+
+ /*
+ * We can't use the performance counter if after
+ * normalization we are left with fewer than 32 bits.
+ */
+ if (_nt_bitShift <= 32) {
+ _nt_ticksPerSec = count.LowPart;
+ PR_ASSERT(_nt_ticksPerSec > PR_INTERVAL_MIN);
+ return;
+ }
+ }
+ _nt_ticksPerSec = -1;
+}
+
+PRIntervalTime
+_PR_MD_GET_INTERVAL()
+{
+ LARGE_INTEGER count;
+
+ /* Sadly; nspr requires the interval to range from 1000 ticks per second
+ * to only 100000 ticks per second; QueryPerformanceCounter is too high
+ * resolution...
+ */
+ if (_nt_ticksPerSec != -1) {
+ (void)QueryPerformanceCounter(&count);
+ PR_ASSERT(_nt_bitShift <= 32);
+ if (_nt_bitShift == 32) {
+ return (PRUint32)count.HighPart;
+ } else {
+ return (PRUint32)((count.HighPart << (32 - _nt_bitShift))
+ + (count.LowPart >> _nt_bitShift));
+ }
+ } else
+#if defined(__MINGW32__)
+ return time();
+#elif defined(WIN16)
+ return clock(); /* milliseconds since application start */
+#else
+ return GetTickCount(); /* milliseconds since system start */
+#endif
+}
+
+PRIntervalTime
+_PR_MD_INTERVAL_PER_SEC()
+{
+ if (_nt_ticksPerSec != -1)
+ return _nt_ticksPerSec;
+ else
+ return 1000;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntio.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntio.c
new file mode 100644
index 00000000..defaae4d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntio.c
@@ -0,0 +1,4684 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* Windows NT IO module
+ *
+ * This module handles IO for LOCAL_SCOPE and GLOBAL_SCOPE threads.
+ * For LOCAL_SCOPE threads, we're using NT fibers. For GLOBAL_SCOPE threads
+ * we're using NT-native threads.
+ *
+ * When doing IO, we want to use completion ports for optimal performance
+ * with fibers. But if we use completion ports for all IO, it is difficult
+ * to project a blocking model with GLOBAL_SCOPE threads. To handle this
+ * we create an extra thread for completing IO for GLOBAL_SCOPE threads.
+ * We don't really want to complete IO on a separate thread for LOCAL_SCOPE
+ * threads because it means extra context switches, which are really slow
+ * on NT... Since we're using a single completion port, some IO will
+ * be incorrectly completed on the GLOBAL_SCOPE IO thread; this will mean
+ * extra context switching; but I don't think there is anything I can do
+ * about it.
+ */
+
+#include "primpl.h"
+#include "pprmwait.h"
+#include <direct.h>
+#include <mbstring.h>
+
+static HANDLE _pr_completion_port;
+static PRThread *_pr_io_completion_thread;
+
+#define RECYCLE_SIZE 512
+static struct _MDLock _pr_recycle_lock;
+static PRInt32 _pr_recycle_array[RECYCLE_SIZE];
+static PRInt32 _pr_recycle_tail = 0;
+
+__declspec(thread) PRThread *_pr_io_restarted_io = NULL;
+DWORD _pr_io_restartedIOIndex; /* The thread local storage slot for each
+ * thread is initialized to NULL. */
+
+PRBool _nt_version_gets_lockfile_completion;
+
+struct _MDLock _pr_ioq_lock;
+extern _MDLock _nt_idleLock;
+extern PRCList _nt_idleList;
+extern PRUint32 _nt_idleCount;
+
+#define CLOSE_TIMEOUT PR_SecondsToInterval(5)
+
+/*
+ * NSPR-to-NT access right mapping table for files.
+ */
+static DWORD fileAccessTable[] = {
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE
+};
+
+/*
+ * NSPR-to-NT access right mapping table for directories.
+ */
+static DWORD dirAccessTable[] = {
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE|FILE_DELETE_CHILD,
+ FILE_GENERIC_EXECUTE
+};
+
+/*
+ * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME.
+ * We store the value in a PRTime variable for convenience.
+ * This constant is used by _PR_FileTimeToPRTime().
+ */
+#ifdef __GNUC__
+static const PRTime _pr_filetime_offset = 116444736000000000LL;
+#else
+static const PRTime _pr_filetime_offset = 116444736000000000i64;
+#endif
+
+#define _NEED_351_FILE_LOCKING_HACK
+#ifdef _NEED_351_FILE_LOCKING_HACK
+#define _PR_LOCAL_FILE 1
+#define _PR_REMOTE_FILE 2
+PRBool IsFileLocalInit();
+PRInt32 IsFileLocal(HANDLE hFile);
+#endif /* _NEED_351_FILE_LOCKING_HACK */
+
+static PRInt32 _md_MakeNonblock(HANDLE);
+
+static PRInt32 _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr *addr, int *addrlen, PRIntervalTime);
+static PRInt32 _nt_nonblock_connect(PRFileDesc *fd, struct sockaddr *addr, int addrlen, PRIntervalTime);
+static PRInt32 _nt_nonblock_recv(PRFileDesc *fd, char *buf, int len, int flags, PRIntervalTime);
+static PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime);
+static PRInt32 _nt_nonblock_writev(PRFileDesc *fd, const PRIOVec *iov, int size, PRIntervalTime);
+static PRInt32 _nt_nonblock_sendto(PRFileDesc *, const char *, int, const struct sockaddr *, int, PRIntervalTime);
+static PRInt32 _nt_nonblock_recvfrom(PRFileDesc *, char *, int, struct sockaddr *, int *, PRIntervalTime);
+
+/*
+ * We cannot associate a fd (a socket) with an I/O completion port
+ * if the fd is nonblocking or inheritable.
+ *
+ * Nonblocking socket I/O won't work if the socket is associated with
+ * an I/O completion port.
+ *
+ * An inheritable fd cannot be associated with an I/O completion port
+ * because the completion notification of async I/O initiated by the
+ * child process is still posted to the I/O completion port in the
+ * parent process.
+ */
+#define _NT_USE_NB_IO(fd) \
+ ((fd)->secret->nonblocking || (fd)->secret->inheritable == _PR_TRI_TRUE)
+
+/*
+ * UDP support
+ *
+ * UDP is supported on NT by the continuation thread mechanism.
+ * The code is borrowed from ptio.c in pthreads nspr, hence the
+ * PT and pt prefixes. This mechanism is in fact general and
+ * not limited to UDP. For now, only UDP's recvfrom and sendto
+ * go through the continuation thread if they get WSAEWOULDBLOCK
+ * on first try. Recv and send on a connected UDP socket still
+ * goes through asychronous io.
+ */
+
+#define PT_DEFAULT_SELECT_MSEC 100
+
+typedef struct pt_Continuation pt_Continuation;
+typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revent);
+
+typedef enum pr_ContuationStatus
+{
+ pt_continuation_sumbitted,
+ pt_continuation_inprogress,
+ pt_continuation_abort,
+ pt_continuation_done
+} pr_ContuationStatus;
+
+struct pt_Continuation
+{
+ /* These objects are linked in ascending timeout order */
+ pt_Continuation *next, *prev; /* self linked list of these things */
+
+ /* The building of the continuation operation */
+ ContinuationFn function; /* what function to continue */
+ union { SOCKET osfd; } arg1; /* #1 - the op's fd */
+ union { void* buffer; } arg2; /* #2 - primary transfer buffer */
+ union { PRIntn amount; } arg3; /* #3 - size of 'buffer' */
+ union { PRIntn flags; } arg4; /* #4 - read/write flags */
+ union { PRNetAddr *addr; } arg5; /* #5 - send/recv address */
+
+ PRIntervalTime timeout; /* representation of the timeout */
+
+ PRIntn event; /* flags for select()'s events */
+
+ /*
+ ** The representation and notification of the results of the operation.
+ ** These function can either return an int return code or a pointer to
+ ** some object.
+ */
+ union { PRIntn code; void *object; } result;
+
+ PRIntn syserrno; /* in case it failed, why (errno) */
+ pr_ContuationStatus status; /* the status of the operation */
+ PRCondVar *complete; /* to notify the initiating thread */
+};
+
+static struct pt_TimedQueue
+{
+ PRLock *ml; /* a little protection */
+ PRThread *thread; /* internal thread's identification */
+ PRCondVar *new_op; /* new operation supplied */
+ PRCondVar *finish_op; /* an existing operation finished */
+ PRUintn op_count; /* number of operations in the list */
+ pt_Continuation *head, *tail; /* head/tail of list of operations */
+
+ pt_Continuation *op; /* timed operation furthest in future */
+ PRIntervalTime epoch; /* the epoch of 'timed' */
+} pt_tq;
+
+#if defined(DEBUG)
+static struct pt_debug_s
+{
+ PRIntn predictionsFoiled;
+ PRIntn pollingListMax;
+ PRIntn continuationsServed;
+} pt_debug;
+#endif /* DEBUG */
+
+static void ContinuationThread(void *arg);
+static PRInt32 pt_SendTo(
+ SOCKET osfd, const void *buf,
+ PRInt32 amount, PRInt32 flags, const PRNetAddr *addr,
+ PRIntn addrlen, PRIntervalTime timeout);
+static PRInt32 pt_RecvFrom(SOCKET osfd, void *buf, PRInt32 amount,
+ PRInt32 flags, PRNetAddr *addr, PRIntn *addr_len, PRIntervalTime timeout);
+
+
+/* The key returned from GetQueuedCompletionStatus() is used to determine what
+ * type of completion we have. We differentiate between IO completions and
+ * CVAR completions.
+ */
+#define KEY_IO 0xaaaaaaaa
+#define KEY_CVAR 0xbbbbbbbb
+
+PRInt32
+_PR_MD_PAUSE_CPU(PRIntervalTime ticks)
+{
+ int awoken = 0;
+ unsigned long bytes, key;
+ int rv;
+ LPOVERLAPPED olp;
+ _MDOverlapped *mdOlp;
+ PRUint32 timeout;
+
+ if (_nt_idleCount > 0) {
+ PRThread *deadThread;
+
+ _MD_LOCK(&_nt_idleLock);
+ while( !PR_CLIST_IS_EMPTY(&_nt_idleList) ) {
+ deadThread = _PR_THREAD_PTR(PR_LIST_HEAD(&_nt_idleList));
+ PR_REMOVE_LINK(&deadThread->links);
+
+ PR_ASSERT(deadThread->state == _PR_DEAD_STATE);
+
+ /* XXXMB - cleanup to do here? */
+ if ( !_PR_IS_NATIVE_THREAD(deadThread) ){
+ /* Spinlock while user thread is still running.
+ * There is no way to use a condition variable here. The thread
+ * is dead, and we have to wait until we switch off the dead
+ * thread before we can kill the fiber completely.
+ */
+ while ( deadThread->no_sched)
+ ;
+
+ DeleteFiber(deadThread->md.fiber_id);
+ }
+ memset(deadThread, 0xa, sizeof(PRThread)); /* debugging */
+ if (!deadThread->threadAllocatedOnStack)
+ PR_DELETE(deadThread);
+ _nt_idleCount--;
+ }
+ _MD_UNLOCK(&_nt_idleLock);
+ }
+
+ if (ticks == PR_INTERVAL_NO_TIMEOUT)
+#if 0
+ timeout = INFINITE;
+#else
+ /*
+ * temporary hack to poll the runq every 5 seconds because of bug in
+ * native threads creating user threads and not poking the right cpu.
+ *
+ * A local thread that was interrupted is bound to its current
+ * cpu but there is no easy way for the interrupter to poke the
+ * right cpu. This is a hack to poll the runq every 5 seconds.
+ */
+ timeout = 5000;
+#endif
+ else
+ timeout = PR_IntervalToMilliseconds(ticks);
+
+ /*
+ * The idea of looping here is to complete as many IOs as possible before
+ * returning. This should minimize trips to the idle thread.
+ */
+ while(1) {
+ rv = GetQueuedCompletionStatus(
+ _pr_completion_port,
+ &bytes,
+ &key,
+ &olp,
+ timeout);
+ if (rv == 0 && olp == NULL) {
+ /* Error in GetQueuedCompetionStatus */
+ if (GetLastError() != WAIT_TIMEOUT) {
+ /* ARGH - what can we do here? Log an error? XXXMB */
+ return -1;
+ } else {
+ /* If awoken == 0, then we just had a timeout */
+ return awoken;
+ }
+ }
+
+ if (olp == NULL)
+ return 0;
+
+ mdOlp = (_MDOverlapped *)olp;
+
+ if (mdOlp->ioModel == _MD_MultiWaitIO) {
+ PRRecvWait *desc;
+ PRWaitGroup *group;
+ PRThread *thred = NULL;
+ PRMWStatus mwstatus;
+
+ desc = mdOlp->data.mw.desc;
+ PR_ASSERT(desc != NULL);
+ mwstatus = rv ? PR_MW_SUCCESS : PR_MW_FAILURE;
+ if (InterlockedCompareExchange((PVOID *)&desc->outcome,
+ (PVOID)mwstatus, (PVOID)PR_MW_PENDING)
+ == (PVOID)PR_MW_PENDING) {
+ if (mwstatus == PR_MW_SUCCESS) {
+ desc->bytesRecv = bytes;
+ } else {
+ mdOlp->data.mw.error = GetLastError();
+ }
+ }
+ group = mdOlp->data.mw.group;
+ PR_ASSERT(group != NULL);
+
+ _PR_MD_LOCK(&group->mdlock);
+ PR_APPEND_LINK(&mdOlp->data.mw.links, &group->io_ready);
+ PR_ASSERT(desc->fd != NULL);
+ NT_HashRemoveInternal(group, desc->fd);
+ if (!PR_CLIST_IS_EMPTY(&group->wait_list)) {
+ thred = _PR_THREAD_CONDQ_PTR(PR_LIST_HEAD(&group->wait_list));
+ PR_REMOVE_LINK(&thred->waitQLinks);
+ }
+ _PR_MD_UNLOCK(&group->mdlock);
+
+ if (thred) {
+ if (!_PR_IS_NATIVE_THREAD(thred)) {
+ int pri = thred->priority;
+ _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();
+ _PR_THREAD_LOCK(thred);
+ if (thred->flags & _PR_ON_PAUSEQ) {
+ _PR_SLEEPQ_LOCK(thred->cpu);
+ _PR_DEL_SLEEPQ(thred, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(thred->cpu);
+ _PR_THREAD_UNLOCK(thred);
+ thred->cpu = lockedCPU;
+ thred->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(lockedCPU);
+ _PR_ADD_RUNQ(thred, lockedCPU, pri);
+ _PR_RUNQ_UNLOCK(lockedCPU);
+ } else {
+ /*
+ * The thread was just interrupted and moved
+ * from the pause queue to the run queue.
+ */
+ _PR_THREAD_UNLOCK(thred);
+ }
+ } else {
+ _PR_THREAD_LOCK(thred);
+ thred->state = _PR_RUNNABLE;
+ _PR_THREAD_UNLOCK(thred);
+ ReleaseSemaphore(thred->md.blocked_sema, 1, NULL);
+ }
+ }
+ } else {
+ PRThread *completed_io;
+
+ PR_ASSERT(mdOlp->ioModel == _MD_BlockingIO);
+ completed_io = _PR_THREAD_MD_TO_PTR(mdOlp->data.mdThread);
+ completed_io->md.blocked_io_status = rv;
+ if (rv == 0)
+ completed_io->md.blocked_io_error = GetLastError();
+ completed_io->md.blocked_io_bytes = bytes;
+
+ if ( !_PR_IS_NATIVE_THREAD(completed_io) ) {
+ int pri = completed_io->priority;
+ _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU();
+
+ /* The KEY_CVAR notification only occurs when a native thread
+ * is notifying a user thread. For user-user notifications
+ * the wakeup occurs by having the notifier place the thread
+ * on the runq directly; for native-native notifications the
+ * wakeup occurs by calling ReleaseSemaphore.
+ */
+ if ( key == KEY_CVAR ) {
+ PR_ASSERT(completed_io->io_pending == PR_FALSE);
+ PR_ASSERT(completed_io->io_suspended == PR_FALSE);
+ PR_ASSERT(completed_io->md.thr_bound_cpu == NULL);
+
+ /* Thread has already been deleted from sleepQ */
+
+ /* Switch CPU and add to runQ */
+ completed_io->cpu = lockedCPU;
+ completed_io->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(lockedCPU);
+ _PR_ADD_RUNQ(completed_io, lockedCPU, pri);
+ _PR_RUNQ_UNLOCK(lockedCPU);
+ } else {
+ PR_ASSERT(key == KEY_IO);
+ PR_ASSERT(completed_io->io_pending == PR_TRUE);
+
+ _PR_THREAD_LOCK(completed_io);
+
+ completed_io->io_pending = PR_FALSE;
+
+ /* If io_suspended is true, then this IO has already resumed.
+ * We don't need to do anything; because the thread is
+ * already running.
+ */
+ if (completed_io->io_suspended == PR_FALSE) {
+ if (completed_io->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) {
+ _PR_SLEEPQ_LOCK(completed_io->cpu);
+ _PR_DEL_SLEEPQ(completed_io, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(completed_io->cpu);
+
+ _PR_THREAD_UNLOCK(completed_io);
+
+ /*
+ * If an I/O operation is suspended, the thread
+ * must be running on the same cpu on which the
+ * I/O operation was issued.
+ */
+ PR_ASSERT(!completed_io->md.thr_bound_cpu ||
+ (completed_io->cpu == completed_io->md.thr_bound_cpu));
+
+ if (!completed_io->md.thr_bound_cpu)
+ completed_io->cpu = lockedCPU;
+ completed_io->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(completed_io->cpu);
+ _PR_ADD_RUNQ(completed_io, completed_io->cpu, pri);
+ _PR_RUNQ_UNLOCK(completed_io->cpu);
+ } else {
+ _PR_THREAD_UNLOCK(completed_io);
+ }
+ } else {
+ _PR_THREAD_UNLOCK(completed_io);
+ }
+ }
+ } else {
+ /* For native threads, they are only notified through this loop
+ * when completing IO. So, don't worry about this being a CVAR
+ * notification, because that is not possible.
+ */
+ _PR_THREAD_LOCK(completed_io);
+ completed_io->io_pending = PR_FALSE;
+ if (completed_io->io_suspended == PR_FALSE) {
+ completed_io->state = _PR_RUNNABLE;
+ _PR_THREAD_UNLOCK(completed_io);
+ rv = ReleaseSemaphore(completed_io->md.blocked_sema,
+ 1, NULL);
+ PR_ASSERT(0 != rv);
+ } else {
+ _PR_THREAD_UNLOCK(completed_io);
+ }
+ }
+ }
+
+ awoken++;
+ timeout = 0; /* Don't block on subsequent trips through the loop */
+ }
+
+ /* never reached */
+ return 0;
+}
+
+static PRStatus
+_native_thread_md_wait(PRThread *thread, PRIntervalTime ticks)
+{
+ DWORD rv;
+ PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
+ INFINITE : PR_IntervalToMilliseconds(ticks);
+
+ /*
+ * thread waiting for a cvar or a joining thread
+ */
+ rv = WaitForSingleObject(thread->md.blocked_sema, msecs);
+ switch(rv) {
+ case WAIT_OBJECT_0:
+ return PR_SUCCESS;
+ break;
+ case WAIT_TIMEOUT:
+ _PR_THREAD_LOCK(thread);
+ PR_ASSERT (thread->state != _PR_IO_WAIT);
+ if (thread->wait.cvar != NULL) {
+ PR_ASSERT(thread->state == _PR_COND_WAIT);
+ thread->wait.cvar = NULL;
+ thread->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The CVAR was notified just as the timeout
+ * occurred. This left the semaphore in the
+ * signaled state. Call WaitForSingleObject()
+ * to clear the semaphore.
+ */
+ _PR_THREAD_UNLOCK(thread);
+ rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+ return PR_SUCCESS;
+ break;
+ default:
+ return PR_FAILURE;
+ break;
+ }
+
+ return PR_SUCCESS;
+}
+
+PRStatus
+_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ DWORD rv;
+
+ if (_native_threads_only) {
+ return(_native_thread_md_wait(thread, ticks));
+ }
+ if ( thread->flags & _PR_GLOBAL_SCOPE ) {
+ PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
+ INFINITE : PR_IntervalToMilliseconds(ticks);
+ rv = WaitForSingleObject(thread->md.blocked_sema, msecs);
+ switch(rv) {
+ case WAIT_OBJECT_0:
+ return PR_SUCCESS;
+ break;
+ case WAIT_TIMEOUT:
+ _PR_THREAD_LOCK(thread);
+ if (thread->state == _PR_IO_WAIT) {
+ if (thread->io_pending == PR_TRUE) {
+ thread->state = _PR_RUNNING;
+ thread->io_suspended = PR_TRUE;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The IO completed just at the same time the timeout
+ * occurred. This left the semaphore in the signaled
+ * state. Call WaitForSingleObject() to clear the
+ * semaphore.
+ */
+ _PR_THREAD_UNLOCK(thread);
+ rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+ } else {
+ if (thread->wait.cvar != NULL) {
+ PR_ASSERT(thread->state == _PR_COND_WAIT);
+ thread->wait.cvar = NULL;
+ thread->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The CVAR was notified just as the timeout
+ * occurred. This left the semaphore in the
+ * signaled state. Call WaitForSingleObject()
+ * to clear the semaphore.
+ */
+ _PR_THREAD_UNLOCK(thread);
+ rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+ }
+ return PR_SUCCESS;
+ break;
+ default:
+ return PR_FAILURE;
+ break;
+ }
+ } else {
+ PRInt32 is;
+
+ _PR_INTSOFF(is);
+ _PR_MD_SWITCH_CONTEXT(thread);
+ }
+
+ return PR_SUCCESS;
+}
+
+static void
+_native_thread_io_nowait(
+ PRThread *thread,
+ int rv,
+ int bytes)
+{
+ int rc;
+
+ PR_ASSERT(rv != 0);
+ _PR_THREAD_LOCK(thread);
+ if (thread->state == _PR_IO_WAIT) {
+ PR_ASSERT(thread->io_suspended == PR_FALSE);
+ PR_ASSERT(thread->io_pending == PR_TRUE);
+ thread->state = _PR_RUNNING;
+ thread->io_pending = PR_FALSE;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The IO completed just at the same time the
+ * thread was interrupted. This left the semaphore
+ * in the signaled state. Call WaitForSingleObject()
+ * to clear the semaphore.
+ */
+ PR_ASSERT(thread->io_suspended == PR_TRUE);
+ PR_ASSERT(thread->io_pending == PR_TRUE);
+ thread->io_pending = PR_FALSE;
+ _PR_THREAD_UNLOCK(thread);
+ rc = WaitForSingleObject(thread->md.blocked_sema, INFINITE);
+ PR_ASSERT(rc == WAIT_OBJECT_0);
+ }
+
+ thread->md.blocked_io_status = rv;
+ thread->md.blocked_io_bytes = bytes;
+ rc = ResetEvent(thread->md.thr_event);
+ PR_ASSERT(rc != 0);
+ return;
+}
+
+static PRStatus
+_native_thread_io_wait(PRThread *thread, PRIntervalTime ticks)
+{
+ DWORD rv, bytes;
+#define _NATIVE_IO_WAIT_HANDLES 2
+#define _NATIVE_WAKEUP_EVENT_INDEX 0
+#define _NATIVE_IO_EVENT_INDEX 1
+
+ HANDLE wait_handles[_NATIVE_IO_WAIT_HANDLES];
+
+ PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
+ INFINITE : PR_IntervalToMilliseconds(ticks);
+
+ PR_ASSERT(thread->flags & _PR_GLOBAL_SCOPE);
+
+ wait_handles[0] = thread->md.blocked_sema;
+ wait_handles[1] = thread->md.thr_event;
+ rv = WaitForMultipleObjects(_NATIVE_IO_WAIT_HANDLES, wait_handles,
+ FALSE, msecs);
+
+ switch(rv) {
+ case WAIT_OBJECT_0 + _NATIVE_IO_EVENT_INDEX:
+ /*
+ * I/O op completed
+ */
+ _PR_THREAD_LOCK(thread);
+ if (thread->state == _PR_IO_WAIT) {
+
+ PR_ASSERT(thread->io_suspended == PR_FALSE);
+ PR_ASSERT(thread->io_pending == PR_TRUE);
+ thread->state = _PR_RUNNING;
+ thread->io_pending = PR_FALSE;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The IO completed just at the same time the
+ * thread was interrupted. This led to us being
+ * notified twice. Call WaitForSingleObject()
+ * to clear the semaphore.
+ */
+ PR_ASSERT(thread->io_suspended == PR_TRUE);
+ PR_ASSERT(thread->io_pending == PR_TRUE);
+ thread->io_pending = PR_FALSE;
+ _PR_THREAD_UNLOCK(thread);
+ rv = WaitForSingleObject(thread->md.blocked_sema,
+ INFINITE);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+
+ rv = GetOverlappedResult((HANDLE) thread->io_fd,
+ &thread->md.overlapped.overlapped, &bytes, FALSE);
+
+ thread->md.blocked_io_status = rv;
+ if (rv != 0) {
+ thread->md.blocked_io_bytes = bytes;
+ } else {
+ thread->md.blocked_io_error = GetLastError();
+ PR_ASSERT(ERROR_IO_PENDING != thread->md.blocked_io_error);
+ }
+ rv = ResetEvent(thread->md.thr_event);
+ PR_ASSERT(rv != 0);
+ break;
+ case WAIT_OBJECT_0 + _NATIVE_WAKEUP_EVENT_INDEX:
+ /*
+ * I/O interrupted;
+ */
+#ifdef DEBUG
+ _PR_THREAD_LOCK(thread);
+ PR_ASSERT(thread->io_suspended == PR_TRUE);
+ _PR_THREAD_UNLOCK(thread);
+#endif
+ break;
+ case WAIT_TIMEOUT:
+ _PR_THREAD_LOCK(thread);
+ if (thread->state == _PR_IO_WAIT) {
+ thread->state = _PR_RUNNING;
+ thread->io_suspended = PR_TRUE;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /*
+ * The thread was interrupted just as the timeout
+ * occurred. This left the semaphore in the signaled
+ * state. Call WaitForSingleObject() to clear the
+ * semaphore.
+ */
+ PR_ASSERT(thread->io_suspended == PR_TRUE);
+ _PR_THREAD_UNLOCK(thread);
+ rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+ break;
+ default:
+ return PR_FAILURE;
+ break;
+ }
+
+ return PR_SUCCESS;
+}
+
+
+static PRStatus
+_NT_IO_WAIT(PRThread *thread, PRIntervalTime timeout)
+{
+ PRBool fWait = PR_TRUE;
+
+ if (_native_threads_only) {
+ return(_native_thread_io_wait(thread, timeout));
+ }
+ if (!_PR_IS_NATIVE_THREAD(thread)) {
+
+ _PR_THREAD_LOCK(thread);
+
+ /* The IO may have already completed; if so, don't add to sleepQ,
+ * since we are already on the runQ!
+ */
+ if (thread->io_pending == PR_TRUE) {
+ _PR_SLEEPQ_LOCK(thread->cpu);
+ _PR_ADD_SLEEPQ(thread, timeout);
+ _PR_SLEEPQ_UNLOCK(thread->cpu);
+ } else
+ fWait = PR_FALSE;
+ _PR_THREAD_UNLOCK(thread);
+ }
+ if (fWait)
+ return _PR_MD_WAIT(thread, timeout);
+ else
+ return PR_SUCCESS;
+}
+
+/*
+ * Unblock threads waiting for I/O
+ * used when interrupting threads
+ *
+ * NOTE: The thread lock should held when this function is called.
+ * On return, the thread lock is released.
+ */
+void _PR_Unblock_IO_Wait(PRThread *thr)
+{
+ PRStatus rv;
+ _PRCPU *cpu = thr->cpu;
+
+ PR_ASSERT(thr->state == _PR_IO_WAIT);
+ /*
+ * A thread for which an I/O timed out or was interrupted cannot be
+ * in an IO_WAIT state except as a result of calling PR_Close or
+ * PR_NT_CancelIo for the FD. For these two cases, _PR_IO_WAIT state
+ * is not interruptible
+ */
+ if (thr->md.interrupt_disabled == PR_TRUE) {
+ _PR_THREAD_UNLOCK(thr);
+ return;
+ }
+ thr->io_suspended = PR_TRUE;
+ thr->state = _PR_RUNNABLE;
+
+ if (!_PR_IS_NATIVE_THREAD(thr)) {
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
+ _PR_SLEEPQ_LOCK(cpu);
+ _PR_DEL_SLEEPQ(thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(cpu);
+ /*
+ * this thread will continue to run on the same cpu until the
+ * I/O is aborted by closing the FD or calling CancelIO
+ */
+ thr->md.thr_bound_cpu = cpu;
+
+ PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
+ _PR_AddThreadToRunQ(me, thr);
+ }
+ _PR_THREAD_UNLOCK(thr);
+ rv = _PR_MD_WAKEUP_WAITER(thr);
+ PR_ASSERT(PR_SUCCESS == rv);
+}
+
+/* Resume an outstanding IO; requires that after the switch, we disable */
+static PRStatus
+_NT_ResumeIO(PRThread *thread, PRIntervalTime ticks)
+{
+ PRBool fWait = PR_TRUE;
+
+ if (!_PR_IS_NATIVE_THREAD(thread)) {
+ if (_pr_use_static_tls) {
+ _pr_io_restarted_io = thread;
+ } else {
+ TlsSetValue(_pr_io_restartedIOIndex, thread);
+ }
+ } else {
+ _PR_THREAD_LOCK(thread);
+ if (!thread->io_pending)
+ fWait = PR_FALSE;
+ thread->io_suspended = PR_FALSE;
+
+ _PR_THREAD_UNLOCK(thread);
+ }
+ /* We don't put ourselves back on the sleepQ yet; until we
+ * set the suspended bit to false, we can't do that. Just save
+ * the sleep time here, and then continue. The restarted_io handler
+ * will add us to the sleepQ if needed.
+ */
+ thread->sleep = ticks;
+
+ if (fWait) {
+ if (!_PR_IS_NATIVE_THREAD(thread))
+ return _PR_MD_WAIT(thread, ticks);
+ else
+ return _NT_IO_WAIT(thread, ticks);
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus
+_PR_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if (thread == NULL) {
+ /* If thread is NULL, we aren't waking a thread, we're just poking
+ * idle thread
+ */
+ if ( PostQueuedCompletionStatus(_pr_completion_port, 0,
+ KEY_CVAR, NULL) == FALSE)
+ return PR_FAILURE;
+ return PR_SUCCESS;
+ }
+
+ if ( _PR_IS_NATIVE_THREAD(thread) ) {
+ if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+ } else {
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ /* When a Native thread has to awaken a user thread, it has to poke
+ * the completion port because all user threads might be idle, and
+ * thus the CPUs are just waiting for a completion.
+ *
+ * XXXMB - can we know when we are truely idle (and not checking
+ * the runq)?
+ */
+ if ((_PR_IS_NATIVE_THREAD(me) || (thread->cpu != me->cpu)) &&
+ (!thread->md.thr_bound_cpu)) {
+ /* The thread should not be in any queue */
+ PR_ASSERT(thread->queueCount == 0);
+ if ( PostQueuedCompletionStatus(_pr_completion_port, 0,
+ KEY_CVAR, &(thread->md.overlapped.overlapped)) == FALSE)
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+ }
+}
+
+void
+_PR_MD_INIT_IO()
+{
+ WORD WSAVersion = 0x0101;
+ WSADATA WSAData;
+ int err;
+ OSVERSIONINFO OSversion;
+
+ err = WSAStartup( WSAVersion, &WSAData );
+ PR_ASSERT(0 == err);
+
+ _pr_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
+ NULL,
+ 0,
+ 0);
+
+ _MD_NEW_LOCK(&_pr_recycle_lock);
+ _MD_NEW_LOCK(&_pr_ioq_lock);
+
+ OSversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx(&OSversion)) {
+ _nt_version_gets_lockfile_completion = PR_FALSE;
+ if (OSversion.dwMajorVersion >= 4) {
+ _nt_version_gets_lockfile_completion = PR_TRUE;
+ }
+ } else
+ PR_ASSERT(0);
+
+ IsFileLocalInit();
+
+ /*
+ * UDP support: start up the continuation thread
+ */
+
+ pt_tq.op_count = 0;
+ pt_tq.head = pt_tq.tail = NULL;
+ pt_tq.ml = PR_NewLock();
+ PR_ASSERT(NULL != pt_tq.ml);
+ pt_tq.new_op = PR_NewCondVar(pt_tq.ml);
+ PR_ASSERT(NULL != pt_tq.new_op);
+#if defined(DEBUG)
+ memset(&pt_debug, 0, sizeof(struct pt_debug_s));
+#endif
+
+ pt_tq.thread = PR_CreateThread(
+ PR_SYSTEM_THREAD, ContinuationThread, NULL,
+ PR_PRIORITY_URGENT, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ PR_ASSERT(NULL != pt_tq.thread);
+
+#ifdef DEBUG
+ /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */
+ {
+ SYSTEMTIME systime;
+ union {
+ PRTime prt;
+ FILETIME ft;
+ } filetime;
+ BOOL rv;
+
+ systime.wYear = 1970;
+ systime.wMonth = 1;
+ /* wDayOfWeek is ignored */
+ systime.wDay = 1;
+ systime.wHour = 0;
+ systime.wMinute = 0;
+ systime.wSecond = 0;
+ systime.wMilliseconds = 0;
+
+ rv = SystemTimeToFileTime(&systime, &filetime.ft);
+ PR_ASSERT(0 != rv);
+ PR_ASSERT(filetime.prt == _pr_filetime_offset);
+ }
+#endif /* DEBUG */
+
+ _PR_NT_InitSids();
+}
+
+/* --- SOCKET IO --------------------------------------------------------- */
+
+/* _md_get_recycled_socket()
+ * Get a socket from the recycle bin; if no sockets are in the bin,
+ * create one. The socket will be passed to AcceptEx() as the
+ * second argument.
+ */
+static SOCKET
+_md_get_recycled_socket()
+{
+ SOCKET rv;
+ int af = AF_INET;
+
+ _MD_LOCK(&_pr_recycle_lock);
+ if (_pr_recycle_tail) {
+ _pr_recycle_tail--;
+ rv = _pr_recycle_array[_pr_recycle_tail];
+ _MD_UNLOCK(&_pr_recycle_lock);
+ return rv;
+ }
+ _MD_UNLOCK(&_pr_recycle_lock);
+
+ rv = _PR_MD_SOCKET(af, SOCK_STREAM, 0);
+ if (rv != INVALID_SOCKET && _md_Associate((HANDLE)rv) == 0) {
+ closesocket(rv);
+ return INVALID_SOCKET;
+ }
+ return rv;
+}
+
+/* _md_put_recycled_socket()
+ * Add a socket to the recycle bin.
+ */
+static void
+_md_put_recycled_socket(SOCKET newsock)
+{
+ PR_ASSERT(_pr_recycle_tail >= 0);
+
+ _MD_LOCK(&_pr_recycle_lock);
+ if (_pr_recycle_tail < RECYCLE_SIZE) {
+ _pr_recycle_array[_pr_recycle_tail] = newsock;
+ _pr_recycle_tail++;
+ _MD_UNLOCK(&_pr_recycle_lock);
+ } else {
+ _MD_UNLOCK(&_pr_recycle_lock);
+ closesocket(newsock);
+ }
+
+ return;
+}
+
+/* _md_Associate()
+ * Associates a file with the completion port.
+ * Returns 0 on failure, 1 on success.
+ */
+PRInt32
+_md_Associate(HANDLE file)
+{
+ HANDLE port;
+
+ if (!_native_threads_only) {
+ port = CreateIoCompletionPort((HANDLE)file,
+ _pr_completion_port,
+ KEY_IO,
+ 0);
+
+ /* XXX should map error codes on failures */
+ return (port == _pr_completion_port);
+ } else {
+ return 1;
+ }
+}
+
+/*
+ * _md_MakeNonblock()
+ * Make a socket nonblocking.
+ * Returns 0 on failure, 1 on success.
+ */
+static PRInt32
+_md_MakeNonblock(HANDLE file)
+{
+ int rv;
+ u_long one = 1;
+
+ rv = ioctlsocket((SOCKET)file, FIONBIO, &one);
+ /* XXX should map error codes on failures */
+ return (rv == 0);
+}
+
+static int missing_completions = 0;
+static int max_wait_loops = 0;
+
+static PRInt32
+_NT_IO_ABORT(PRInt32 sock)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRBool fWait;
+ PRInt32 rv;
+ int loop_count;
+
+ /* This is a clumsy way to abort the IO, but it is all we can do.
+ * It looks a bit racy, but we handle all the cases.
+ * case 1: IO completes before calling closesocket
+ * case 1a: fWait is set to PR_FALSE
+ * This should e the most likely case. We'll properly
+ * not wait call _NT_IO_WAIT, since the closesocket()
+ * won't be forcing a completion.
+ * case 1b: fWait is set to PR_TRUE
+ * This hopefully won't happen much. When it does, this
+ * thread will timeout in _NT_IO_WAIT for CLOSE_INTERVAL
+ * before cleaning up.
+ * case 2: IO does not complete before calling closesocket
+ * case 2a: IO never completes
+ * This is the likely case. We'll close it and wait
+ * for the completion forced by the close. Return should
+ * be immediate.
+ * case 2b: IO completes just after calling closesocket
+ * Since the closesocket is issued, we'll either get a
+ * completion back for the real IO or for the close. We
+ * don't really care. It may not even be possible to get
+ * a real completion here. In any event, we'll awaken
+ * from NT_IO_WAIT immediately.
+ */
+
+ _PR_THREAD_LOCK(me);
+ fWait = me->io_pending;
+ if (fWait) {
+ /*
+ * If there's still I/O pending, it should have already timed
+ * out once before this function is called.
+ */
+ PR_ASSERT(me->io_suspended == PR_TRUE);
+
+ /* Set up to wait for I/O completion again */
+ me->state = _PR_IO_WAIT;
+ me->io_suspended = PR_FALSE;
+ me->md.interrupt_disabled = PR_TRUE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ /* Close the socket if there is one */
+ if (sock != INVALID_SOCKET) {
+ rv = closesocket((SOCKET)sock);
+ }
+
+ /* If there was I/O pending before the close, wait for it to complete */
+ if (fWait) {
+
+ /* Wait and wait for the I/O to complete */
+ for (loop_count = 0; fWait; ++loop_count) {
+
+ _NT_IO_WAIT(me, CLOSE_TIMEOUT);
+
+ _PR_THREAD_LOCK(me);
+ fWait = me->io_pending;
+ if (fWait) {
+ PR_ASSERT(me->io_suspended == PR_TRUE);
+ me->state = _PR_IO_WAIT;
+ me->io_suspended = PR_FALSE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ if (loop_count > max_wait_loops) {
+ max_wait_loops = loop_count;
+ }
+ }
+
+ if (loop_count > 1) {
+ ++missing_completions;
+ }
+
+ me->md.interrupt_disabled = PR_FALSE;
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+ me->md.thr_bound_cpu = NULL;
+ me->io_suspended = PR_FALSE;
+
+ return rv;
+}
+
+
+PRInt32
+_PR_MD_SOCKET(int af, int type, int flags)
+{
+ SOCKET sock;
+
+ sock = socket(af, type, flags);
+
+ if (sock == INVALID_SOCKET) {
+ _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
+ }
+
+ return (PRInt32)sock;
+}
+
+struct connect_data_s {
+ PRInt32 status;
+ PRInt32 error;
+ PRInt32 osfd;
+ struct sockaddr *addr;
+ PRUint32 addrlen;
+ PRIntervalTime timeout;
+};
+
+void
+_PR_MD_connect_thread(void *cdata)
+{
+ struct connect_data_s *cd = (struct connect_data_s *)cdata;
+
+ cd->status = connect(cd->osfd, cd->addr, cd->addrlen);
+
+ if (cd->status == SOCKET_ERROR)
+ cd->error = WSAGetLastError();
+
+ return;
+}
+
+
+PRInt32
+_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ u_long nbio;
+ PRInt32 rc;
+
+ if (fd->secret->nonblocking) {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+
+ if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) {
+ err = WSAGetLastError();
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+ return rv;
+ }
+
+ /*
+ * Temporarily make the socket non-blocking so that we can
+ * initiate a non-blocking connect and wait for its completion
+ * (with a timeout) in select.
+ */
+ PR_ASSERT(!fd->secret->md.io_model_committed);
+ nbio = 1;
+ rv = ioctlsocket((SOCKET)osfd, FIONBIO, &nbio);
+ PR_ASSERT(0 == rv);
+
+ rc = _nt_nonblock_connect(fd, (struct sockaddr *) addr, addrlen, timeout);
+
+ /* Set the socket back to blocking. */
+ nbio = 0;
+ rv = ioctlsocket((SOCKET)osfd, FIONBIO, &nbio);
+ PR_ASSERT(0 == rv);
+
+ return rc;
+}
+
+PRInt32
+_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv;
+#if 0
+ int one = 1;
+#endif
+
+ rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
+
+ if (rv == SOCKET_ERROR) {
+ _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
+ return -1;
+ }
+
+#if 0
+ /* Disable nagle- so far unknown if this is good or not...
+ */
+ rv = setsockopt(fd->secret->md.osfd,
+ SOL_SOCKET,
+ TCP_NODELAY,
+ (const char *)&one,
+ sizeof(one));
+ PR_ASSERT(rv == 0);
+#endif
+
+ return 0;
+}
+
+void _PR_MD_UPDATE_ACCEPT_CONTEXT(PRInt32 accept_sock, PRInt32 listen_sock)
+{
+ /* Sockets accept()'d with AcceptEx need to call this setsockopt before
+ * calling anything other than ReadFile(), WriteFile(), send(), recv(),
+ * Transmitfile(), and closesocket(). In order to call any other
+ * winsock functions, we have to make this setsockopt call.
+ *
+ * XXXMB - For the server, we *NEVER* need this in
+ * the "normal" code path. But now we have to call it. This is a waste
+ * of a system call. We'd like to only call it before calling the
+ * obscure socket calls, but since we don't know at that point what the
+ * original socket was (or even if it is still alive) we can't do it
+ * at that point...
+ */
+ setsockopt((SOCKET)accept_sock,
+ SOL_SOCKET,
+ SO_UPDATE_ACCEPT_CONTEXT,
+ (char *)&listen_sock,
+ sizeof(listen_sock));
+
+}
+
+#define INET_ADDR_PADDED (sizeof(PRNetAddr) + 16)
+PRInt32
+_PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
+ PRIntervalTime timeout, PRBool fast,
+ _PR_AcceptTimeoutCallback callback, void *callbackArg)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ SOCKET accept_sock;
+ int bytes;
+ PRNetAddr *Laddr;
+ PRNetAddr *Raddr;
+ PRUint32 llen, err;
+ int rv;
+
+ if (_NT_USE_NB_IO(fd)) {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ /*
+ * The accepted socket inherits the nonblocking and
+ * inheritable (HANDLE_FLAG_INHERIT) attributes of
+ * the listening socket.
+ */
+ accept_sock = _nt_nonblock_accept(fd, (struct sockaddr *)raddr, rlen, timeout);
+ if (!fd->secret->nonblocking) {
+ u_long zero = 0;
+
+ rv = ioctlsocket(accept_sock, FIONBIO, &zero);
+ PR_ASSERT(0 == rv);
+ }
+ return accept_sock;
+ }
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+
+ if (!me->md.acceptex_buf) {
+ me->md.acceptex_buf = PR_MALLOC(2*INET_ADDR_PADDED);
+ if (!me->md.acceptex_buf) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ }
+
+ accept_sock = _md_get_recycled_socket();
+ if (accept_sock == INVALID_SOCKET)
+ return -1;
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ closesocket(accept_sock);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = osfd;
+
+ rv = AcceptEx((SOCKET)osfd,
+ accept_sock,
+ me->md.acceptex_buf,
+ 0,
+ INET_ADDR_PADDED,
+ INET_ADDR_PADDED,
+ &bytes,
+ &(me->md.overlapped.overlapped));
+
+ if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) {
+ /* Argh! The IO failed */
+ closesocket(accept_sock);
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_ACCEPTEX_ERROR(err);
+ return -1;
+ }
+
+ if (_native_threads_only && rv) {
+ _native_thread_io_nowait(me, rv, bytes);
+ } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) {
+ PR_ASSERT(0);
+ closesocket(accept_sock);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
+
+ if (me->io_suspended) {
+ closesocket(accept_sock);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ return -1;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ closesocket(accept_sock);
+ _PR_MD_MAP_ACCEPTEX_ERROR(me->md.blocked_io_error);
+ return -1;
+ }
+
+ if (!fast)
+ _PR_MD_UPDATE_ACCEPT_CONTEXT((SOCKET)accept_sock, (SOCKET)osfd);
+
+ /* IO is done */
+ GetAcceptExSockaddrs(
+ me->md.acceptex_buf,
+ 0,
+ INET_ADDR_PADDED,
+ INET_ADDR_PADDED,
+ (LPSOCKADDR *)&(Laddr),
+ &llen,
+ (LPSOCKADDR *)&(Raddr),
+ (unsigned int *)rlen);
+
+ if (raddr != NULL)
+ memcpy((char *)raddr, (char *)&Raddr->inet, *rlen);
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ return accept_sock;
+}
+
+PRInt32
+_PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout,
+ PRBool fast, _PR_AcceptTimeoutCallback callback,
+ void *callbackArg)
+{
+ PRInt32 sock = sd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ int bytes;
+ PRNetAddr *Laddr;
+ PRUint32 llen, rlen, err;
+ int rv;
+ PRBool isConnected;
+ PRBool madeCallback = PR_FALSE;
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ if (!sd->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)sock);
+ PR_ASSERT(0 != rv);
+ sd->secret->md.io_model_committed = PR_TRUE;
+ }
+
+ *newSock = _md_get_recycled_socket();
+ if (*newSock == INVALID_SOCKET)
+ return -1;
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ closesocket(*newSock);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = sock;
+
+ rv = AcceptEx((SOCKET)sock,
+ *newSock,
+ buf,
+ amount,
+ INET_ADDR_PADDED,
+ INET_ADDR_PADDED,
+ &bytes,
+ &(me->md.overlapped.overlapped));
+
+ if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) {
+ closesocket(*newSock);
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_ACCEPTEX_ERROR(err);
+ return -1;
+ }
+
+ if (_native_threads_only && rv) {
+ _native_thread_io_nowait(me, rv, bytes);
+ } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) {
+ PR_ASSERT(0);
+ closesocket(*newSock);
+ return -1;
+ }
+
+retry:
+ if (me->io_suspended) {
+ PRInt32 err;
+ INT seconds;
+ INT bytes = sizeof(seconds);
+
+ PR_ASSERT(timeout != PR_INTERVAL_NO_TIMEOUT);
+
+ err = getsockopt(*newSock,
+ SOL_SOCKET,
+ SO_CONNECT_TIME,
+ (char *)&seconds,
+ (PINT)&bytes);
+ if ( err == NO_ERROR ) {
+ PRIntervalTime elapsed = PR_SecondsToInterval(seconds);
+
+ if (seconds == 0xffffffff)
+ isConnected = PR_FALSE;
+ else
+ isConnected = PR_TRUE;
+
+ if (!isConnected) {
+ if (madeCallback == PR_FALSE && callback)
+ callback(callbackArg);
+ madeCallback = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ if (_NT_ResumeIO(me, timeout) == PR_FAILURE) {
+ closesocket(*newSock);
+ return -1;
+ }
+ goto retry;
+ }
+
+ if (elapsed < timeout) {
+ /* Socket is connected but time not elapsed, RESUME IO */
+ timeout -= elapsed;
+ me->state = _PR_IO_WAIT;
+ if (_NT_ResumeIO(me, timeout) == PR_FAILURE) {
+ closesocket(*newSock);
+ return -1;
+ }
+ goto retry;
+ }
+ } else {
+ /* What to do here? Assume socket not open?*/
+ PR_ASSERT(0);
+ isConnected = PR_FALSE;
+ }
+
+ rv = _NT_IO_ABORT(*newSock);
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+ PR_ASSERT(me->io_suspended == PR_FALSE);
+ PR_ASSERT(me->md.thr_bound_cpu == NULL);
+ /* If the IO is still suspended, it means we didn't get any
+ * completion from NT_IO_WAIT. This is not disasterous, I hope,
+ * but it may mean we still have an IO outstanding... Try to
+ * recover by just allowing ourselves to continue.
+ */
+ me->io_suspended = PR_FALSE;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ me->state = _PR_RUNNING;
+ closesocket(*newSock);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+ PR_ASSERT(me->io_suspended == PR_FALSE);
+ PR_ASSERT(me->md.thr_bound_cpu == NULL);
+
+ if (me->md.blocked_io_status == 0) {
+ _PR_MD_MAP_ACCEPTEX_ERROR(me->md.blocked_io_error);
+ closesocket(*newSock);
+ return -1;
+ }
+
+ if (!fast)
+ _PR_MD_UPDATE_ACCEPT_CONTEXT((SOCKET)*newSock, (SOCKET)sock);
+
+ /* IO is done */
+ GetAcceptExSockaddrs(
+ buf,
+ amount,
+ INET_ADDR_PADDED,
+ INET_ADDR_PADDED,
+ (LPSOCKADDR *)&(Laddr),
+ &llen,
+ (LPSOCKADDR *)(raddr),
+ (unsigned int *)&rlen);
+
+ return me->md.blocked_io_bytes;
+}
+
+PRInt32
+_PR_MD_SENDFILE(PRFileDesc *sock, PRSendFileData *sfd,
+ PRInt32 flags, PRIntervalTime timeout)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 tflags;
+ int rv, err;
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ if (!sock->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)sock->secret->md.osfd);
+ PR_ASSERT(0 != rv);
+ sock->secret->md.io_model_committed = PR_TRUE;
+ }
+ if (!me->md.xmit_bufs) {
+ me->md.xmit_bufs = PR_NEW(TRANSMIT_FILE_BUFFERS);
+ if (!me->md.xmit_bufs) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ }
+ me->md.xmit_bufs->Head = (void *)sfd->header;
+ me->md.xmit_bufs->HeadLength = sfd->hlen;
+ me->md.xmit_bufs->Tail = (void *)sfd->trailer;
+ me->md.xmit_bufs->TailLength = sfd->tlen;
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+ me->md.overlapped.overlapped.Offset = sfd->file_offset;
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ tflags = 0;
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET)
+ tflags = TF_DISCONNECT | TF_REUSE_SOCKET;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = sock->secret->md.osfd;
+
+ rv = TransmitFile((SOCKET)sock->secret->md.osfd,
+ (HANDLE)sfd->fd->secret->md.osfd,
+ (DWORD)sfd->file_nbytes,
+ (DWORD)0,
+ (LPOVERLAPPED)&(me->md.overlapped.overlapped),
+ (TRANSMIT_FILE_BUFFERS *)me->md.xmit_bufs,
+ (DWORD)tflags);
+ if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_TRANSMITFILE_ERROR(err);
+ return -1;
+ }
+
+ if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) {
+ PR_ASSERT(0);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
+
+ if (me->io_suspended) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ return -1;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ _PR_MD_MAP_TRANSMITFILE_ERROR(me->md.blocked_io_error);
+ return -1;
+ }
+
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+ _md_put_recycled_socket(sock->secret->md.osfd);
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ return me->md.blocked_io_bytes;
+}
+
+PRInt32
+_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ int bytes;
+ int rv, err;
+
+ if (_NT_USE_NB_IO(fd)) {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ return _nt_nonblock_recv(fd, buf, amount, flags, timeout);
+ }
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = osfd;
+
+ rv = ReadFile((HANDLE)osfd,
+ buf,
+ amount,
+ &bytes,
+ &(me->md.overlapped.overlapped));
+ if ( (rv == 0) && (GetLastError() != ERROR_IO_PENDING) ) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ if ((err = GetLastError()) == ERROR_HANDLE_EOF)
+ return 0;
+ _PR_MD_MAP_READ_ERROR(err);
+ return -1;
+ }
+
+ if (_native_threads_only && rv) {
+ _native_thread_io_nowait(me, rv, bytes);
+ } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) {
+ PR_ASSERT(0);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
+
+ if (me->io_suspended) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ return -1;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ if (me->md.blocked_io_error == ERROR_HANDLE_EOF)
+ return 0;
+ _PR_MD_MAP_READ_ERROR(me->md.blocked_io_error);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ return me->md.blocked_io_bytes;
+}
+
+PRInt32
+_PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ int bytes;
+ int rv, err;
+
+ if (_NT_USE_NB_IO(fd)) {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ return _nt_nonblock_send(fd, (char *)buf, amount, timeout);
+ }
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = osfd;
+
+ rv = WriteFile((HANDLE)osfd,
+ buf,
+ amount,
+ &bytes,
+ &(me->md.overlapped.overlapped));
+ if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_WRITE_ERROR(err);
+ return -1;
+ }
+
+ if (_native_threads_only && rv) {
+ _native_thread_io_nowait(me, rv, bytes);
+ } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) {
+ PR_ASSERT(0);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
+
+ if (me->io_suspended) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ return -1;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ _PR_MD_MAP_WRITE_ERROR(me->md.blocked_io_error);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ return me->md.blocked_io_bytes;
+}
+
+PRInt32
+_PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv;
+
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ if (_NT_USE_NB_IO(fd))
+ return _nt_nonblock_sendto(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout);
+ else
+ return pt_SendTo(osfd, buf, amount, flags, addr, addrlen, timeout);
+}
+
+PRInt32
+_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv;
+
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ if (_NT_USE_NB_IO(fd))
+ return _nt_nonblock_recvfrom(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout);
+ else
+ return pt_RecvFrom(osfd, buf, amount, flags, addr, addrlen, timeout);
+}
+
+/* XXXMB - for now this is a sockets call only */
+PRInt32
+_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ int index;
+ int sent = 0;
+ int rv;
+
+ if (_NT_USE_NB_IO(fd)) {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_MakeNonblock((HANDLE)osfd);
+ PR_ASSERT(0 != rv);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ return _nt_nonblock_writev(fd, iov, iov_size, timeout);
+ }
+
+ for (index=0; index<iov_size; index++) {
+ rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0,
+ timeout);
+ if (rv > 0)
+ sent += rv;
+ if ( rv != iov[index].iov_len ) {
+ if (sent <= 0)
+ return -1;
+ return -1;
+ }
+ }
+
+ return sent;
+}
+
+PRInt32
+_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0)
+ _PR_MD_MAP_LISTEN_ERROR(WSAGetLastError());
+ return(rv);
+}
+
+PRInt32
+_PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
+{
+ PRInt32 rv;
+
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0)
+ _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
+ return(rv);
+}
+
+PRStatus
+_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+{
+ PRInt32 rv;
+
+ rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+{
+ PRInt32 rv;
+
+ /*
+ * NT has a bug that, when invoked on a socket accepted by
+ * AcceptEx(), getpeername() returns an all-zero peer address.
+ * To work around this bug, we store the peer's address (returned
+ * by AcceptEx()) with the socket fd and use the cached peer
+ * address if the socket is an accepted socket.
+ */
+
+ if (fd->secret->md.accepted_socket) {
+ INT seconds;
+ INT bytes = sizeof(seconds);
+
+ /*
+ * Determine if the socket is connected.
+ */
+
+ rv = getsockopt(fd->secret->md.osfd,
+ SOL_SOCKET,
+ SO_CONNECT_TIME,
+ (char *) &seconds,
+ (PINT) &bytes);
+ if (rv == NO_ERROR) {
+ if (seconds == 0xffffffff) {
+ PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+ *len = PR_NETADDR_SIZE(&fd->secret->md.peer_addr);
+ memcpy(addr, &fd->secret->md.peer_addr, *len);
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+ } else {
+ rv = getpeername((SOCKET)fd->secret->md.osfd,
+ (struct sockaddr *) addr, len);
+ if (rv == 0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+ }
+}
+
+PRStatus
+_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ PRInt32 rv;
+
+ rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv;
+
+ rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+/* --- FILE IO ----------------------------------------------------------- */
+
+PRInt32
+_PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode)
+{
+ HANDLE file;
+ PRInt32 access = 0;
+ PRInt32 flags = 0;
+ PRInt32 flag6 = 0;
+
+ if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH;
+
+ if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ;
+ if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE;
+
+ if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
+ flags = CREATE_NEW;
+ else if (osflags & PR_CREATE_FILE)
+ flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS;
+ else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING;
+ else flags = OPEN_EXISTING;
+
+
+ flag6 |= FILE_FLAG_OVERLAPPED;
+
+ file = CreateFile(name,
+ access,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ flags,
+ flag6,
+ NULL);
+ if (file == INVALID_HANDLE_VALUE) {
+ _PR_MD_MAP_OPEN_ERROR(GetLastError());
+ return -1;
+ }
+
+ if (osflags & PR_APPEND) {
+ if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) {
+ _PR_MD_MAP_LSEEK_ERROR(GetLastError());
+ CloseHandle(file);
+ return -1;
+ }
+ }
+
+ return (PRInt32)file;
+}
+
+PRInt32
+_PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode)
+{
+ HANDLE file;
+ PRInt32 access = 0;
+ PRInt32 flags = 0;
+ PRInt32 flag6 = 0;
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH;
+
+ if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ;
+ if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE;
+
+ if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
+ flags = CREATE_NEW;
+ else if (osflags & PR_CREATE_FILE)
+ flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS;
+ else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING;
+ else flags = OPEN_EXISTING;
+
+
+ flag6 |= FILE_FLAG_OVERLAPPED;
+
+ if (osflags & PR_CREATE_FILE) {
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ }
+ file = CreateFile(name,
+ access,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ lpSA,
+ flags,
+ flag6,
+ NULL);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+ if (file == INVALID_HANDLE_VALUE) {
+ _PR_MD_MAP_OPEN_ERROR(GetLastError());
+ return -1;
+ }
+
+ if (osflags & PR_APPEND) {
+ if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) {
+ _PR_MD_MAP_LSEEK_ERROR(GetLastError());
+ CloseHandle(file);
+ return -1;
+ }
+ }
+
+ return (PRInt32)file;
+}
+
+PRInt32
+_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
+{
+ PRInt32 f = fd->secret->md.osfd;
+ PRUint32 bytes;
+ int rv, err;
+ LONG hiOffset = 0;
+ LONG loOffset;
+
+ if (!fd->secret->md.sync_file_io) {
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+
+ me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, &me->md.overlapped.overlapped.OffsetHigh, FILE_CURRENT);
+ PR_ASSERT((me->md.overlapped.overlapped.Offset != 0xffffffff) || (GetLastError() == NO_ERROR));
+
+ if (fd->secret->inheritable == _PR_TRI_TRUE) {
+ rv = ReadFile((HANDLE)f,
+ (LPVOID)buf,
+ len,
+ &bytes,
+ &me->md.overlapped.overlapped);
+ if (rv != 0) {
+ loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT);
+ PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR));
+ return bytes;
+ }
+ err = GetLastError();
+ if (err == ERROR_IO_PENDING) {
+ rv = GetOverlappedResult((HANDLE)f,
+ &me->md.overlapped.overlapped, &bytes, TRUE);
+ if (rv != 0) {
+ loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT);
+ PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR));
+ return bytes;
+ }
+ err = GetLastError();
+ }
+ if (err == ERROR_HANDLE_EOF) {
+ return 0;
+ } else {
+ _PR_MD_MAP_READ_ERROR(err);
+ return -1;
+ }
+ } else {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)f);
+ PR_ASSERT(rv != 0);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = f;
+
+ rv = ReadFile((HANDLE)f,
+ (LPVOID)buf,
+ len,
+ &bytes,
+ &me->md.overlapped.overlapped);
+ if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ if (err == ERROR_HANDLE_EOF) {
+ return 0;
+ }
+ _PR_MD_MAP_READ_ERROR(err);
+ return -1;
+ }
+
+ if (_native_threads_only && rv) {
+ _native_thread_io_nowait(me, rv, bytes);
+ } else if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ PR_ASSERT(0);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
+
+ if (me->io_suspended) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ return -1;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ if (me->md.blocked_io_error == ERROR_HANDLE_EOF) {
+ return 0;
+ }
+ _PR_MD_MAP_READ_ERROR(me->md.blocked_io_error);
+ return -1;
+ }
+
+ SetFilePointer((HANDLE)f, me->md.blocked_io_bytes, 0, FILE_CURRENT);
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ return me->md.blocked_io_bytes;
+ }
+ } else {
+
+ rv = ReadFile((HANDLE)f,
+ (LPVOID)buf,
+ len,
+ &bytes,
+ NULL);
+ if (rv == 0) {
+ err = GetLastError();
+ /* ERROR_HANDLE_EOF can only be returned by async io */
+ PR_ASSERT(err != ERROR_HANDLE_EOF);
+ if (err == ERROR_BROKEN_PIPE) {
+ /* The write end of the pipe has been closed. */
+ return 0;
+ }
+ _PR_MD_MAP_READ_ERROR(err);
+ return -1;
+ }
+ return bytes;
+ }
+}
+
+PRInt32
+_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
+{
+ PRInt32 f = fd->secret->md.osfd;
+ PRInt32 bytes;
+ int rv, err;
+ LONG hiOffset = 0;
+ LONG loOffset;
+ LARGE_INTEGER offset; /* use for the calculation of the new offset */
+
+ if (!fd->secret->md.sync_file_io) {
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return -1;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+
+ me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, &me->md.overlapped.overlapped.OffsetHigh, FILE_CURRENT);
+ PR_ASSERT((me->md.overlapped.overlapped.Offset != 0xffffffff) || (GetLastError() == NO_ERROR));
+
+ if (fd->secret->inheritable == _PR_TRI_TRUE) {
+ rv = WriteFile((HANDLE)f,
+ (LPVOID)buf,
+ len,
+ &bytes,
+ &me->md.overlapped.overlapped);
+ if (rv != 0) {
+ loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT);
+ PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR));
+ return bytes;
+ }
+ err = GetLastError();
+ if (err == ERROR_IO_PENDING) {
+ rv = GetOverlappedResult((HANDLE)f,
+ &me->md.overlapped.overlapped, &bytes, TRUE);
+ if (rv != 0) {
+ loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT);
+ PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR));
+ return bytes;
+ }
+ err = GetLastError();
+ }
+ _PR_MD_MAP_READ_ERROR(err);
+ return -1;
+ } else {
+ if (!fd->secret->md.io_model_committed) {
+ rv = _md_Associate((HANDLE)f);
+ PR_ASSERT(rv != 0);
+ fd->secret->md.io_model_committed = PR_TRUE;
+ }
+ if (_native_threads_only)
+ me->md.overlapped.overlapped.hEvent = me->md.thr_event;
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+ me->io_fd = f;
+
+ rv = WriteFile((HANDLE)f,
+ buf,
+ len,
+ &bytes,
+ &(me->md.overlapped.overlapped));
+ if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_WRITE_ERROR(err);
+ return -1;
+ }
+
+ if (_native_threads_only && rv) {
+ _native_thread_io_nowait(me, rv, bytes);
+ } else if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ PR_ASSERT(0);
+ return -1;
+ }
+
+ PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
+
+ if (me->io_suspended) {
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ } else {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ return -1;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ _PR_MD_MAP_WRITE_ERROR(me->md.blocked_io_error);
+ return -1;
+ }
+
+ /*
+ * Moving the file pointer by a relative offset (FILE_CURRENT)
+ * does not work with a file on a network drive exported by a
+ * Win2K system. We still don't know why. A workaround is to
+ * move the file pointer by an absolute offset (FILE_BEGIN).
+ * (Bugzilla bug 70765)
+ */
+ offset.LowPart = me->md.overlapped.overlapped.Offset;
+ offset.HighPart = me->md.overlapped.overlapped.OffsetHigh;
+ offset.QuadPart += me->md.blocked_io_bytes;
+
+ SetFilePointer((HANDLE)f, offset.LowPart, &offset.HighPart, FILE_BEGIN);
+
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ return me->md.blocked_io_bytes;
+ }
+ } else {
+ rv = WriteFile((HANDLE)f,
+ buf,
+ len,
+ &bytes,
+ NULL);
+ if (rv == 0) {
+ _PR_MD_MAP_WRITE_ERROR(GetLastError());
+ return -1;
+ }
+ return bytes;
+ }
+}
+
+PRInt32
+_PR_MD_SOCKETAVAILABLE(PRFileDesc *fd)
+{
+ PRInt32 result;
+
+ if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
+ return -1;
+ }
+ return result;
+}
+
+PRInt32
+_PR_MD_PIPEAVAILABLE(PRFileDesc *fd)
+{
+ if (NULL == fd)
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+}
+
+PROffset32
+_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
+{
+ DWORD moveMethod;
+ PROffset32 rv;
+
+ switch (whence) {
+ case PR_SEEK_SET:
+ moveMethod = FILE_BEGIN;
+ break;
+ case PR_SEEK_CUR:
+ moveMethod = FILE_CURRENT;
+ break;
+ case PR_SEEK_END:
+ moveMethod = FILE_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ rv = SetFilePointer((HANDLE)fd->secret->md.osfd, offset, NULL, moveMethod);
+
+ /*
+ * If the lpDistanceToMoveHigh argument (third argument) is
+ * NULL, SetFilePointer returns 0xffffffff on failure.
+ */
+ if (-1 == rv) {
+ _PR_MD_MAP_LSEEK_ERROR(GetLastError());
+ }
+ return rv;
+}
+
+PROffset64
+_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
+{
+ DWORD moveMethod;
+ LARGE_INTEGER li;
+ DWORD err;
+
+ switch (whence) {
+ case PR_SEEK_SET:
+ moveMethod = FILE_BEGIN;
+ break;
+ case PR_SEEK_CUR:
+ moveMethod = FILE_CURRENT;
+ break;
+ case PR_SEEK_END:
+ moveMethod = FILE_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ li.QuadPart = offset;
+ li.LowPart = SetFilePointer((HANDLE)fd->secret->md.osfd,
+ li.LowPart, &li.HighPart, moveMethod);
+
+ if (0xffffffff == li.LowPart && (err = GetLastError()) != NO_ERROR) {
+ _PR_MD_MAP_LSEEK_ERROR(err);
+ li.QuadPart = -1;
+ }
+ return li.QuadPart;
+}
+
+/*
+ * This is documented to succeed on read-only files, but Win32's
+ * FlushFileBuffers functions fails with "access denied" in such a
+ * case. So we only signal an error if the error is *not* "access
+ * denied".
+ */
+PRInt32
+_PR_MD_FSYNC(PRFileDesc *fd)
+{
+ /*
+ * From the documentation:
+ *
+ * On Windows NT, the function FlushFileBuffers fails if hFile
+ * is a handle to console output. That is because console
+ * output is not buffered. The function returns FALSE, and
+ * GetLastError returns ERROR_INVALID_HANDLE.
+ *
+ * On the other hand, on Win95, it returns without error. I cannot
+ * assume that 0, 1, and 2 are console, because if someone closes
+ * System.out and then opens a file, they might get file descriptor
+ * 1. An error on *that* version of 1 should be reported, whereas
+ * an error on System.out (which was the original 1) should be
+ * ignored. So I use isatty() to ensure that such an error was
+ * because of this, and if it was, I ignore the error.
+ */
+
+ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd);
+
+ if (!ok) {
+ DWORD err = GetLastError();
+
+ if (err != ERROR_ACCESS_DENIED) { /* from winerror.h */
+ _PR_MD_MAP_FSYNC_ERROR(err);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+PRInt32
+_PR_MD_CLOSE(PRInt32 osfd, PRBool socket)
+{
+ PRInt32 rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (socket) {
+ rv = closesocket((SOCKET)osfd);
+ if (rv < 0)
+ _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
+ } else {
+ rv = CloseHandle((HANDLE)osfd)?0:-1;
+ if (rv < 0)
+ _PR_MD_MAP_CLOSE_ERROR(GetLastError());
+ }
+
+ if (rv == 0 && me->io_suspended) {
+ if (me->io_fd == osfd) {
+ PRBool fWait;
+
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_IO_WAIT;
+ /* The IO could have completed on another thread just after
+ * calling closesocket while the io_suspended flag was true.
+ * So we now grab the lock to do a safe check on io_pending to
+ * see if we need to wait or not.
+ */
+ fWait = me->io_pending;
+ me->io_suspended = PR_FALSE;
+ me->md.interrupt_disabled = PR_TRUE;
+ _PR_THREAD_UNLOCK(me);
+
+ if (fWait)
+ _NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(me->io_suspended == PR_FALSE);
+ PR_ASSERT(me->io_pending == PR_FALSE);
+ /*
+ * I/O operation is no longer pending; the thread can now
+ * run on any cpu
+ */
+ _PR_THREAD_LOCK(me);
+ me->md.interrupt_disabled = PR_FALSE;
+ me->md.thr_bound_cpu = NULL;
+ me->io_suspended = PR_FALSE;
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(me);
+ }
+ }
+ return rv;
+}
+
+PRStatus
+_PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
+{
+ BOOL rv;
+
+ if (fd->secret->md.io_model_committed) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ rv = SetHandleInformation(
+ (HANDLE)fd->secret->md.osfd,
+ HANDLE_FLAG_INHERIT,
+ inheritable ? HANDLE_FLAG_INHERIT : 0);
+ if (0 == rv) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+void
+_PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported)
+{
+ if (imported) {
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ } else {
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ }
+}
+
+void
+_PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd)
+{
+ DWORD flags;
+
+ PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
+ if (fd->secret->md.io_model_committed) {
+ return;
+ }
+ if (GetHandleInformation((HANDLE)fd->secret->md.osfd, &flags)) {
+ if (flags & HANDLE_FLAG_INHERIT) {
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ } else {
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ }
+ }
+}
+
+
+/* --- DIR IO ------------------------------------------------------------ */
+#define GetFileFromDIR(d) (d)->d_entry.cFileName
+#define FileIsHidden(d) ((d)->d_entry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
+
+void FlipSlashes(char *cp, int len)
+{
+ while (--len >= 0) {
+ if (cp[0] == '/') {
+ cp[0] = PR_DIRECTORY_SEPARATOR;
+ }
+ cp = _mbsinc(cp);
+ }
+} /* end FlipSlashes() */
+
+/*
+**
+** Local implementations of standard Unix RTL functions which are not provided
+** by the VC RTL.
+**
+*/
+
+PRStatus
+_PR_MD_CLOSE_DIR(_MDDir *d)
+{
+ if ( d ) {
+ if (FindClose( d->d_hdl )) {
+ d->magic = (PRUint32)-1;
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+}
+
+
+PRStatus
+_PR_MD_OPEN_DIR(_MDDir *d, const char *name)
+{
+ char filename[ MAX_PATH ];
+ int len;
+
+ len = strlen(name);
+ /* Need 5 bytes for \*.* and the trailing null byte. */
+ if (len + 5 > MAX_PATH) {
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
+ return PR_FAILURE;
+ }
+ strcpy(filename, name);
+
+ /*
+ * If 'name' ends in a slash or backslash, do not append
+ * another backslash.
+ */
+ if (filename[len - 1] == '/' || filename[len - 1] == '\\') {
+ len--;
+ }
+ strcpy(&filename[len], "\\*.*");
+ FlipSlashes( filename, strlen(filename) );
+
+ d->d_hdl = FindFirstFile( filename, &(d->d_entry) );
+ if ( d->d_hdl == INVALID_HANDLE_VALUE ) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ d->firstEntry = PR_TRUE;
+ d->magic = _MD_MAGIC_DIR;
+ return PR_SUCCESS;
+}
+
+char *
+_PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
+{
+ PRInt32 err;
+ BOOL rv;
+ char *fileName;
+
+ if ( d ) {
+ while (1) {
+ if (d->firstEntry) {
+ d->firstEntry = PR_FALSE;
+ rv = 1;
+ } else {
+ rv = FindNextFile(d->d_hdl, &(d->d_entry));
+ }
+ if (rv == 0) {
+ break;
+ }
+ fileName = GetFileFromDIR(d);
+ if ( (flags & PR_SKIP_DOT) &&
+ (fileName[0] == '.') && (fileName[1] == '\0'))
+ continue;
+ if ( (flags & PR_SKIP_DOT_DOT) &&
+ (fileName[0] == '.') && (fileName[1] == '.') &&
+ (fileName[2] == '\0'))
+ continue;
+ if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d))
+ continue;
+ return fileName;
+ }
+ err = GetLastError();
+ PR_ASSERT(NO_ERROR != err);
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return NULL;
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+}
+
+PRInt32
+_PR_MD_DELETE(const char *name)
+{
+ if (DeleteFile(name)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_DELETE_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+void
+_PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm)
+{
+ PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime));
+ CopyMemory(prtm, filetime, sizeof(PRTime));
+#ifdef __GNUC__
+ *prtm = (*prtm - _pr_filetime_offset) / 10LL;
+#else
+ *prtm = (*prtm - _pr_filetime_offset) / 10i64;
+#endif
+
+#ifdef DEBUG
+ /* Doublecheck our calculation. */
+ {
+ SYSTEMTIME systime;
+ PRExplodedTime etm;
+ PRTime cmp; /* for comparison */
+ BOOL rv;
+
+ rv = FileTimeToSystemTime(filetime, &systime);
+ PR_ASSERT(0 != rv);
+
+ /*
+ * PR_ImplodeTime ignores wday and yday.
+ */
+ etm.tm_usec = systime.wMilliseconds * PR_USEC_PER_MSEC;
+ etm.tm_sec = systime.wSecond;
+ etm.tm_min = systime.wMinute;
+ etm.tm_hour = systime.wHour;
+ etm.tm_mday = systime.wDay;
+ etm.tm_month = systime.wMonth - 1;
+ etm.tm_year = systime.wYear;
+ /*
+ * It is not well-documented what time zone the FILETIME's
+ * are in. WIN32_FIND_DATA is documented to be in UTC (GMT).
+ * But BY_HANDLE_FILE_INFORMATION is unclear about this.
+ * By our best judgement, we assume that FILETIME is in UTC.
+ */
+ etm.tm_params.tp_gmt_offset = 0;
+ etm.tm_params.tp_dst_offset = 0;
+ cmp = PR_ImplodeTime(&etm);
+
+ /*
+ * SYSTEMTIME is in milliseconds precision, so we convert PRTime's
+ * microseconds to milliseconds before doing the comparison.
+ */
+ PR_ASSERT((cmp / PR_USEC_PER_MSEC) == (*prtm / PR_USEC_PER_MSEC));
+ }
+#endif /* DEBUG */
+}
+
+PRInt32
+_PR_MD_STAT(const char *fn, struct stat *info)
+{
+ PRInt32 rv;
+
+ rv = _stat(fn, (struct _stat *)info);
+ if (-1 == rv) {
+ /*
+ * Check for MSVC runtime library _stat() bug.
+ * (It's really a bug in FindFirstFile().)
+ * If a pathname ends in a backslash or slash,
+ * e.g., c:\temp\ or c:/temp/, _stat() will fail.
+ * Note: a pathname ending in a slash (e.g., c:/temp/)
+ * can be handled by _stat() on NT but not on Win95.
+ *
+ * We remove the backslash or slash at the end and
+ * try again.
+ */
+
+ int len = strlen(fn);
+ if (len > 0 && len <= _MAX_PATH
+ && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
+ char newfn[_MAX_PATH + 1];
+
+ strcpy(newfn, fn);
+ newfn[len - 1] = '\0';
+ rv = _stat(newfn, (struct _stat *)info);
+ }
+ }
+
+ if (-1 == rv) {
+ _PR_MD_MAP_STAT_ERROR(errno);
+ }
+ return rv;
+}
+
+#define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\')
+
+/*
+ * IsRootDirectory --
+ *
+ * Return PR_TRUE if the pathname 'fn' is a valid root directory,
+ * else return PR_FALSE. The char buffer pointed to by 'fn' must
+ * be writable. During the execution of this function, the contents
+ * of the buffer pointed to by 'fn' may be modified, but on return
+ * the original contents will be restored. 'buflen' is the size of
+ * the buffer pointed to by 'fn'.
+ *
+ * Root directories come in three formats:
+ * 1. / or \, meaning the root directory of the current drive.
+ * 2. C:/ or C:\, where C is a drive letter.
+ * 3. \\<server name>\<share point name>\ or
+ * \\<server name>\<share point name>, meaning the root directory
+ * of a UNC (Universal Naming Convention) name.
+ */
+
+static PRBool
+IsRootDirectory(char *fn, size_t buflen)
+{
+ char *p;
+ PRBool slashAdded = PR_FALSE;
+ PRBool rv = PR_FALSE;
+
+ if (_PR_IS_SLASH(fn[0]) && fn[1] == '\0') {
+ return PR_TRUE;
+ }
+
+ if (isalpha(fn[0]) && fn[1] == ':' && _PR_IS_SLASH(fn[2])
+ && fn[3] == '\0') {
+ rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE;
+ return rv;
+ }
+
+ /* The UNC root directory */
+
+ if (_PR_IS_SLASH(fn[0]) && _PR_IS_SLASH(fn[1])) {
+ /* The 'server' part should have at least one character. */
+ p = &fn[2];
+ if (*p == '\0' || _PR_IS_SLASH(*p)) {
+ return PR_FALSE;
+ }
+
+ /* look for the next slash */
+ do {
+ p++;
+ } while (*p != '\0' && !_PR_IS_SLASH(*p));
+ if (*p == '\0') {
+ return PR_FALSE;
+ }
+
+ /* The 'share' part should have at least one character. */
+ p++;
+ if (*p == '\0' || _PR_IS_SLASH(*p)) {
+ return PR_FALSE;
+ }
+
+ /* look for the final slash */
+ do {
+ p++;
+ } while (*p != '\0' && !_PR_IS_SLASH(*p));
+ if (_PR_IS_SLASH(*p) && p[1] != '\0') {
+ return PR_FALSE;
+ }
+ if (*p == '\0') {
+ /*
+ * GetDriveType() doesn't work correctly if the
+ * path is of the form \\server\share, so we add
+ * a final slash temporarily.
+ */
+ if ((p + 1) < (fn + buflen)) {
+ *p++ = '\\';
+ *p = '\0';
+ slashAdded = PR_TRUE;
+ } else {
+ return PR_FALSE; /* name too long */
+ }
+ }
+ rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE;
+ /* restore the 'fn' buffer */
+ if (slashAdded) {
+ *--p = '\0';
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
+{
+ HANDLE hFindFile;
+ WIN32_FIND_DATA findFileData;
+ char pathbuf[MAX_PATH + 1];
+
+ if (NULL == fn || '\0' == *fn) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ * FindFirstFile() expands wildcard characters. So
+ * we make sure the pathname contains no wildcard.
+ */
+ if (NULL != _mbspbrk(fn, "?*")) {
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0);
+ return -1;
+ }
+
+ hFindFile = FindFirstFile(fn, &findFileData);
+ if (INVALID_HANDLE_VALUE == hFindFile) {
+ DWORD len;
+ char *filePart;
+
+ /*
+ * FindFirstFile() does not work correctly on root directories.
+ * It also doesn't work correctly on a pathname that ends in a
+ * slash. So we first check to see if the pathname specifies a
+ * root directory. If not, and if the pathname ends in a slash,
+ * we remove the final slash and try again.
+ */
+
+ /*
+ * If the pathname does not contain ., \, and /, it cannot be
+ * a root directory or a pathname that ends in a slash.
+ */
+ if (NULL == _mbspbrk(fn, ".\\/")) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ len = GetFullPathName(fn, sizeof(pathbuf), pathbuf,
+ &filePart);
+ if (0 == len) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ if (len > sizeof(pathbuf)) {
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
+ return -1;
+ }
+ if (IsRootDirectory(pathbuf, sizeof(pathbuf))) {
+ info->type = PR_FILE_DIRECTORY;
+ info->size = 0;
+ /*
+ * These timestamps don't make sense for root directories.
+ */
+ info->modifyTime = 0;
+ info->creationTime = 0;
+ return 0;
+ }
+ if (!_PR_IS_SLASH(pathbuf[len - 1])) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ } else {
+ pathbuf[len - 1] = '\0';
+ hFindFile = FindFirstFile(pathbuf, &findFileData);
+ if (INVALID_HANDLE_VALUE == hFindFile) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ }
+ }
+
+ FindClose(hFindFile);
+
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ info->type = PR_FILE_DIRECTORY;
+ } else {
+ info->type = PR_FILE_FILE;
+ }
+
+ info->size = findFileData.nFileSizeHigh;
+ info->size = (info->size << 32) + findFileData.nFileSizeLow;
+
+ _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime);
+
+ if (0 == findFileData.ftCreationTime.dwLowDateTime &&
+ 0 == findFileData.ftCreationTime.dwHighDateTime) {
+ info->creationTime = info->modifyTime;
+ } else {
+ _PR_FileTimeToPRTime(&findFileData.ftCreationTime,
+ &info->creationTime);
+ }
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
+{
+ PRFileInfo64 info64;
+ PRInt32 rv = _PR_MD_GETFILEINFO64(fn, &info64);
+ if (0 == rv)
+ {
+ info->type = info64.type;
+ info->size = (PRUint32) info64.size;
+ info->modifyTime = info64.modifyTime;
+ info->creationTime = info64.creationTime;
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ int rv;
+
+ BY_HANDLE_FILE_INFORMATION hinfo;
+
+ rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo);
+ if (rv == FALSE) {
+ _PR_MD_MAP_FSTAT_ERROR(GetLastError());
+ return -1;
+ }
+
+ if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_FILE;
+
+ info->size = hinfo.nFileSizeHigh;
+ info->size = (info->size << 32) + hinfo.nFileSizeLow;
+
+ _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime) );
+ _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime) );
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
+{
+ int rv;
+
+ BY_HANDLE_FILE_INFORMATION hinfo;
+
+ rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo);
+ if (rv == FALSE) {
+ _PR_MD_MAP_FSTAT_ERROR(GetLastError());
+ return -1;
+ }
+
+ if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_FILE;
+
+ info->size = hinfo.nFileSizeLow;
+
+ _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime) );
+ _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime) );
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_RENAME(const char *from, const char *to)
+{
+ /* Does this work with dot-relative pathnames? */
+ if (MoveFile(from, to)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_RENAME_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_ACCESS(const char *name, PRAccessHow how)
+{
+ PRInt32 rv;
+
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ rv = _access(name, 02);
+ break;
+ case PR_ACCESS_READ_OK:
+ rv = _access(name, 04);
+ break;
+ case PR_ACCESS_EXISTS:
+ rv = _access(name, 00);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCESS_ERROR(errno);
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_MKDIR(const char *name, PRIntn mode)
+{
+ /* XXXMB - how to translate the "mode"??? */
+ if (CreateDirectory(name, NULL)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_MKDIR_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_MAKE_DIR(const char *name, PRIntn mode)
+{
+ BOOL rv;
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ rv = CreateDirectory(name, lpSA);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+ if (rv) {
+ return 0;
+ } else {
+ _PR_MD_MAP_MKDIR_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_RMDIR(const char *name)
+{
+ if (RemoveDirectory(name)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_RMDIR_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRStatus
+_PR_MD_LOCKFILE(PRInt32 f)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+
+ rv = LockFileEx((HANDLE)f,
+ LOCKFILE_EXCLUSIVE_LOCK,
+ 0,
+ 0x7fffffff,
+ 0,
+ &me->md.overlapped.overlapped);
+
+ if (_native_threads_only) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ if (rv == FALSE) {
+ err = GetLastError();
+ PR_ASSERT(err != ERROR_IO_PENDING);
+ _PR_MD_MAP_LOCKF_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+ }
+
+ /* HACK AROUND NT BUG
+ * NT 3.51 has a bug. In NT 3.51, if LockFileEx returns true, you
+ * don't get any completion on the completion port. This is a bug.
+ *
+ * They fixed it on NT4.0 so that you do get a completion.
+ *
+ * If we pretend we won't get a completion, NSPR gets confused later
+ * when the unexpected completion arrives. If we assume we do get
+ * a completion, we hang on 3.51. Worse, Microsoft informs me that the
+ * behavior varies on 3.51 depending on if you are using a network
+ * file system or a local disk!
+ *
+ * Solution: For now, _nt_version_gets_lockfile_completion is set
+ * depending on whether or not this system is EITHER
+ * - running NT 4.0
+ * - running NT 3.51 with a service pack greater than 5.
+ *
+ * In the meantime, this code may not work on network file systems.
+ *
+ */
+
+ if ( rv == FALSE && ((err = GetLastError()) != ERROR_IO_PENDING)) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_LOCKF_ERROR(err);
+ return PR_FAILURE;
+ }
+#ifdef _NEED_351_FILE_LOCKING_HACK
+ else if (rv) {
+ /* If this is NT 3.51 and the file is local, then we won't get a
+ * completion back from LockFile when it succeeded.
+ */
+ if (_nt_version_gets_lockfile_completion == PR_FALSE) {
+ if ( IsFileLocal((HANDLE)f) == _PR_LOCAL_FILE) {
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ return PR_SUCCESS;
+ }
+ }
+ }
+#endif /* _NEED_351_FILE_LOCKING_HACK */
+
+ if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ _PR_MD_MAP_LOCKF_ERROR(me->md.blocked_io_error);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+PRStatus
+_PR_MD_TLOCKFILE(PRInt32 f)
+{
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+
+ _PR_THREAD_LOCK(me);
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return -1;
+ }
+ me->io_pending = PR_TRUE;
+ me->state = _PR_IO_WAIT;
+ _PR_THREAD_UNLOCK(me);
+
+ rv = LockFileEx((HANDLE)f,
+ LOCKFILE_FAIL_IMMEDIATELY|LOCKFILE_EXCLUSIVE_LOCK,
+ 0,
+ 0x7fffffff,
+ 0,
+ &me->md.overlapped.overlapped);
+ if (_native_threads_only) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ if (rv == FALSE) {
+ err = GetLastError();
+ PR_ASSERT(err != ERROR_IO_PENDING);
+ _PR_MD_MAP_LOCKF_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+ }
+ if ( rv == FALSE && ((err = GetLastError()) != ERROR_IO_PENDING)) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_MD_MAP_LOCKF_ERROR(err);
+ return PR_FAILURE;
+ }
+#ifdef _NEED_351_FILE_LOCKING_HACK
+ else if (rv) {
+ /* If this is NT 3.51 and the file is local, then we won't get a
+ * completion back from LockFile when it succeeded.
+ */
+ if (_nt_version_gets_lockfile_completion == PR_FALSE) {
+ if ( IsFileLocal((HANDLE)f) == _PR_LOCAL_FILE) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ return PR_SUCCESS;
+ }
+ }
+ }
+#endif /* _NEED_351_FILE_LOCKING_HACK */
+
+ if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ _PR_THREAD_LOCK(me);
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ return PR_FAILURE;
+ }
+ _PR_THREAD_UNLOCK(me);
+
+ return PR_FAILURE;
+ }
+
+ if (me->md.blocked_io_status == 0) {
+ _PR_MD_MAP_LOCKF_ERROR(me->md.blocked_io_error);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+
+PRStatus
+_PR_MD_UNLOCKFILE(PRInt32 f)
+{
+ PRInt32 rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->io_suspended) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED));
+
+ rv = UnlockFileEx((HANDLE)f,
+ 0,
+ 0x7fffffff,
+ 0,
+ &me->md.overlapped.overlapped);
+
+ if (rv)
+ return PR_SUCCESS;
+ else {
+ int err = GetLastError();
+ _PR_MD_MAP_LOCKF_ERROR(err);
+ return PR_FAILURE;
+ }
+}
+
+void
+_PR_MD_MAKE_NONBLOCK(PRFileDesc *f)
+{
+ /*
+ * On NT, we either call _md_Associate() or _md_MakeNonblock(),
+ * depending on whether the socket is blocking or not.
+ *
+ * Once we associate a socket with the io completion port,
+ * there is no way to disassociate it from the io completion
+ * port. So we have to call _md_Associate/_md_MakeNonblock
+ * lazily.
+ */
+}
+
+#ifdef _NEED_351_FILE_LOCKING_HACK
+/***************
+**
+** Lockfile hacks
+**
+** The following code is a hack to work around a microsoft bug with lockfile.
+** The problem is that on NT 3.51, if LockFileEx() succeeds, you never
+** get a completion back for files that are on local disks. So, we need to
+** know if a file is local or remote so we can tell if we should expect
+** a completion.
+**
+** The only way to check if a file is local or remote based on the handle is
+** to get the serial number for the volume it is mounted on and then to
+** compare that with mounted drives. This code caches the volume numbers of
+** fixed disks and does a relatively quick check.
+**
+** Locking: Since the only thing we ever do when multithreaded is a 32bit
+** assignment, we probably don't need locking. It is included just
+** case anyway.
+**
+** Limitations: Does not work on floppies because they are too slow
+** Unknown if it will work on wierdo 3rd party file systems
+**
+****************
+*/
+
+/* There can only be 26 drive letters on NT */
+#define _PR_MAX_DRIVES 26
+
+_MDLock cachedVolumeLock;
+DWORD dwCachedVolumeSerialNumbers[_PR_MAX_DRIVES] = {0};
+DWORD dwLastCachedDrive = 0;
+DWORD dwRemoveableDrivesToCheck = 0; /* bitmask for removeable drives */
+
+PRBool IsFileLocalInit()
+{
+ TCHAR lpBuffer[_PR_MAX_DRIVES*5];
+ DWORD nBufferLength = _PR_MAX_DRIVES*5;
+ DWORD nBufferNeeded = GetLogicalDriveStrings(0, NULL);
+ DWORD dwIndex = 0;
+ DWORD dwDriveType;
+ DWORD dwVolumeSerialNumber;
+ DWORD dwDriveIndex = 0;
+ DWORD oldmode = (DWORD) -1;
+
+ _MD_NEW_LOCK(&cachedVolumeLock);
+
+ nBufferNeeded = GetLogicalDriveStrings(nBufferLength, lpBuffer);
+ if (nBufferNeeded == 0 || nBufferNeeded > nBufferLength)
+ return PR_FALSE;
+
+ // Calling GetVolumeInformation on a removeable drive where the
+ // disk is currently removed will cause a dialog box to the
+ // console. This is not good.
+ // Temporarily disable the SEM_FAILCRITICALERRORS to avoid the
+ // damn dialog.
+
+ dwCachedVolumeSerialNumbers[dwDriveIndex] = 0;
+ oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ // now loop through the logical drives
+ while(lpBuffer[dwIndex] != TEXT('\0'))
+ {
+ // skip the floppy drives. This is *SLOW*
+ if ((lpBuffer[dwIndex] == TEXT('A')) || (lpBuffer[dwIndex] == TEXT('B')))
+ /* Skip over floppies */;
+ else
+ {
+ dwDriveIndex = (lpBuffer[dwIndex] - TEXT('A'));
+
+ dwDriveType = GetDriveType(&lpBuffer[dwIndex]);
+
+ switch(dwDriveType)
+ {
+ // Ignore these drive types
+ case 0:
+ case 1:
+ case DRIVE_REMOTE:
+ default: // If the drive type is unknown, ignore it.
+ break;
+
+ // Removable media drives can have different serial numbers
+ // at different times, so cache the current serial number
+ // but keep track of them so they can be rechecked if necessary.
+ case DRIVE_REMOVABLE:
+
+ // CDROM is a removable media
+ case DRIVE_CDROM:
+
+ // no idea if ramdisks can change serial numbers or not
+ // but it doesn't hurt to treat them as removable.
+
+ case DRIVE_RAMDISK:
+
+
+ // Here is where we keep track of removable drives.
+ dwRemoveableDrivesToCheck |= 1 << dwDriveIndex;
+
+ // removable drives fall through to fixed drives and get cached.
+
+ case DRIVE_FIXED:
+
+ // cache volume serial numbers.
+ if (GetVolumeInformation(
+ &lpBuffer[dwIndex],
+ NULL, 0,
+ &dwVolumeSerialNumber,
+ NULL, NULL, NULL, 0)
+ )
+ {
+ if (dwLastCachedDrive < dwDriveIndex)
+ dwLastCachedDrive = dwDriveIndex;
+ dwCachedVolumeSerialNumbers[dwDriveIndex] = dwVolumeSerialNumber;
+ }
+
+ break;
+ }
+ }
+
+ dwIndex += lstrlen(&lpBuffer[dwIndex]) +1;
+ }
+
+ if (oldmode != (DWORD) -1) {
+ SetErrorMode(oldmode);
+ oldmode = (DWORD) -1;
+ }
+
+ return PR_TRUE;
+}
+
+PRInt32 IsFileLocal(HANDLE hFile)
+{
+ DWORD dwIndex = 0, dwMask;
+ BY_HANDLE_FILE_INFORMATION Info;
+ TCHAR szDrive[4] = TEXT("C:\\");
+ DWORD dwVolumeSerialNumber;
+ DWORD oldmode = (DWORD) -1;
+ int rv = _PR_REMOTE_FILE;
+
+ if (!GetFileInformationByHandle(hFile, &Info))
+ return -1;
+
+ // look to see if the volume serial number has been cached.
+ _MD_LOCK(&cachedVolumeLock);
+ while(dwIndex <= dwLastCachedDrive)
+ if (dwCachedVolumeSerialNumbers[dwIndex++] == Info.dwVolumeSerialNumber)
+ return _PR_LOCAL_FILE;
+ _MD_UNLOCK(&cachedVolumeLock);
+
+ // volume serial number not found in the cache. Check removable files.
+ // removable drives are noted as a bitmask. If the bit associated with
+ // a specific drive is set, then we should query its volume serial number
+ // as its possible it has changed.
+ dwMask = dwRemoveableDrivesToCheck;
+ dwIndex = 0;
+
+ while(dwMask)
+ {
+ while(!(dwMask & 1))
+ {
+ dwIndex++;
+ dwMask = dwMask >> 1;
+ }
+
+ szDrive[0] = TEXT('A')+ (TCHAR) dwIndex;
+
+ // Calling GetVolumeInformation on a removeable drive where the
+ // disk is currently removed will cause a dialog box to the
+ // console. This is not good.
+ // Temporarily disable the SEM_FAILCRITICALERRORS to avoid the
+ // dialog.
+
+ oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ if (GetVolumeInformation(
+ szDrive,
+ NULL, 0,
+ &dwVolumeSerialNumber,
+ NULL, NULL, NULL, 0)
+ )
+ {
+ if (dwVolumeSerialNumber == Info.dwVolumeSerialNumber)
+ {
+ _MD_LOCK(&cachedVolumeLock);
+ if (dwLastCachedDrive < dwIndex)
+ dwLastCachedDrive = dwIndex;
+ dwCachedVolumeSerialNumbers[dwIndex] = dwVolumeSerialNumber;
+ _MD_UNLOCK(&cachedVolumeLock);
+ rv = _PR_LOCAL_FILE;
+ }
+ }
+ if (oldmode != (DWORD) -1) {
+ SetErrorMode(oldmode);
+ oldmode = (DWORD) -1;
+ }
+
+ if (rv == _PR_LOCAL_FILE)
+ return _PR_LOCAL_FILE;
+
+ dwIndex++;
+ dwMask = dwMask >> 1;
+ }
+
+ return _PR_REMOTE_FILE;
+}
+#endif /* _NEED_351_FILE_LOCKING_HACK */
+
+PR_IMPLEMENT(PRStatus) PR_NT_CancelIo(PRFileDesc *fd)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRBool fWait;
+ PRFileDesc *bottom;
+
+ bottom = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
+ if (!me->io_suspended || (NULL == bottom) ||
+ (me->io_fd != bottom->secret->md.osfd)) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
+ /*
+ * The CancelIO operation has to be issued by the same NT thread that
+ * issued the I/O operation
+ */
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || (me->cpu == me->md.thr_bound_cpu));
+ if (me->io_pending) {
+ if (!CancelIo((HANDLE)bottom->secret->md.osfd)) {
+ PR_SetError(PR_INVALID_STATE_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ }
+ _PR_THREAD_LOCK(me);
+ fWait = me->io_pending;
+ me->io_suspended = PR_FALSE;
+ me->state = _PR_IO_WAIT;
+ me->md.interrupt_disabled = PR_TRUE;
+ _PR_THREAD_UNLOCK(me);
+ if (fWait)
+ _NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(me->io_suspended == PR_FALSE);
+ PR_ASSERT(me->io_pending == PR_FALSE);
+
+ _PR_THREAD_LOCK(me);
+ me->md.interrupt_disabled = PR_FALSE;
+ me->md.thr_bound_cpu = NULL;
+ me->io_suspended = PR_FALSE;
+ me->io_pending = PR_FALSE;
+ me->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(me);
+ return PR_SUCCESS;
+}
+
+static PRInt32 _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr *addr, int *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ fd_set rd;
+ struct timeval tv, *tvp;
+
+ FD_ZERO(&rd);
+ FD_SET((SOCKET)osfd, &rd);
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ while ((rv = accept(osfd, addr, addrlen)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL,
+ NULL)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ }
+ } else {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ break;
+ }
+ }
+ } else if (timeout == PR_INTERVAL_NO_WAIT) {
+ if ((rv = accept(osfd, addr, addrlen)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ } else {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+ }
+ } else {
+retry:
+ if ((rv = accept(osfd, addr, addrlen)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+
+ rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL, tvp);
+ if (rv > 0) {
+ goto retry;
+ } else if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ } else {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ }
+ } else {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+ }
+ }
+ return(rv);
+}
+
+static PRInt32 _nt_nonblock_connect(PRFileDesc *fd, struct sockaddr *addr, int addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv;
+ int err;
+ fd_set wr, ex;
+ struct timeval tv, *tvp;
+ int len;
+
+ if ((rv = connect(osfd, addr, addrlen)) == -1) {
+ if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) {
+ if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+ FD_SET((SOCKET)osfd, &wr);
+ FD_SET((SOCKET)osfd, &ex);
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wr, &ex,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ return rv;
+ }
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ return -1;
+ }
+ /* Call Sleep(0) to work around a Winsock timeing bug. */
+ Sleep(0);
+ if (FD_ISSET((SOCKET)osfd, &ex)) {
+ len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
+ (char *) &err, &len) == SOCKET_ERROR) {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return -1;
+ }
+ PR_ASSERT(FD_ISSET((SOCKET)osfd, &wr));
+ rv = 0;
+ } else {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+ }
+ return rv;
+}
+
+static PRInt32 _nt_nonblock_recv(PRFileDesc *fd, char *buf, int len, int flags, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ struct timeval tv, *tvp;
+ fd_set rd;
+ int osflags;
+
+ if (0 == flags) {
+ osflags = 0;
+ } else {
+ PR_ASSERT(PR_MSG_PEEK == flags);
+ osflags = MSG_PEEK;
+ }
+ while ((rv = recv(osfd,buf,len,osflags)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ FD_ZERO(&rd);
+ FD_SET((SOCKET)osfd, &rd);
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ } else if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } else {
+ _PR_MD_MAP_RECV_ERROR(err);
+ break;
+ }
+ }
+ return(rv);
+}
+
+static PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ struct timeval tv, *tvp;
+ fd_set wd;
+ PRInt32 bytesSent = 0;
+
+ while(bytesSent < len) {
+ while ((rv = send(osfd,buf,len,0)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&wd);
+ FD_SET((SOCKET)osfd, &wd);
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ return -1;
+ }
+ } else {
+ _PR_MD_MAP_SEND_ERROR(err);
+ return -1;
+ }
+ }
+ bytesSent += rv;
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (bytesSent < len) {
+ if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&wd);
+ FD_SET((SOCKET)osfd, &wd);
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ return -1;
+ }
+ }
+ }
+ return bytesSent;
+}
+
+static PRInt32 _nt_nonblock_writev(PRFileDesc *fd, const PRIOVec *iov, int size, PRIntervalTime timeout)
+{
+ int index;
+ int sent = 0;
+ int rv;
+
+ for (index=0; index<size; index++) {
+ rv = _nt_nonblock_send(fd, iov[index].iov_base, iov[index].iov_len, timeout);
+ if (rv > 0)
+ sent += rv;
+ if ( rv != iov[index].iov_len ) {
+ if (rv < 0) {
+ if (fd->secret->nonblocking
+ && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
+ && (sent > 0)) {
+ return sent;
+ } else {
+ return -1;
+ }
+ }
+ /* Only a nonblocking socket can have partial sends */
+ PR_ASSERT(fd->secret->nonblocking);
+ return sent;
+ }
+ }
+
+ return sent;
+}
+
+static PRInt32 _nt_nonblock_sendto(
+ PRFileDesc *fd, const char *buf, int len,
+ const struct sockaddr *addr, int addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ struct timeval tv, *tvp;
+ fd_set wd;
+ PRInt32 bytesSent = 0;
+
+ while(bytesSent < len) {
+ while ((rv = sendto(osfd,buf,len,0, addr, addrlen)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&wd);
+ FD_SET((SOCKET)osfd, &wd);
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ return -1;
+ }
+ } else {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ return -1;
+ }
+ }
+ bytesSent += rv;
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (bytesSent < len) {
+ if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&wd);
+ FD_SET((SOCKET)osfd, &wd);
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ return -1;
+ }
+ }
+ }
+ return bytesSent;
+}
+
+static PRInt32 _nt_nonblock_recvfrom(PRFileDesc *fd, char *buf, int len, struct sockaddr *addr, int *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ struct timeval tv, *tvp;
+ fd_set rd;
+
+ while ((rv = recvfrom(osfd,buf,len,0,addr, addrlen)) == -1) {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking)) {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ }
+ FD_ZERO(&rd);
+ FD_SET((SOCKET)osfd, &rd);
+ if ((rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL,
+ tvp)) == -1) {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ } else if (rv == 0) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } else {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ break;
+ }
+ }
+ return(rv);
+}
+
+/*
+ * UDP support: the continuation thread functions and recvfrom and sendto.
+ */
+
+static void pt_InsertTimedInternal(pt_Continuation *op)
+{
+ PRInt32 delta = 0;
+ pt_Continuation *t_op = NULL;
+ PRIntervalTime now = PR_IntervalNow(), op_tmo, qd_tmo;
+
+ /*
+ * If this element operation isn't timed, it gets queued at the
+ * end of the list (just after pt_tq.tail) and we're
+ * finishd early.
+ */
+ if (PR_INTERVAL_NO_TIMEOUT == op->timeout)
+ {
+ t_op = pt_tq.tail; /* put it at the end */
+ goto done;
+ }
+
+ /*
+ * The rest of this routine actaully deals with timed ops.
+ */
+
+ if (NULL != pt_tq.op)
+ {
+ /*
+ * To find where in the list to put the new operation, form
+ * the absolute time the operations in question will expire.
+ *
+ * The new operation ('op') will expire at now() + op->timeout.
+ *
+ * The operation that will time out furthest in the future will
+ * do so at pt_tq.epoch + pt_tq.op->timeout.
+ *
+ * Subsequently earlier timeouts are computed based on the latter
+ * knowledge by subracting the timeout deltas that are stored in
+ * the operation list. There are operation[n]->timeout ticks
+ * between the expiration of operation[n-1] and operation[n].e e
+ *
+ * Therefore, the operation[n-1] will expire operation[n]->timeout
+ * ticks prior to operation[n].
+ *
+ * This should be easy!
+ */
+ t_op = pt_tq.op; /* running pointer to queued op */
+ op_tmo = now + op->timeout; /* that's in absolute ticks */
+ qd_tmo = pt_tq.epoch + t_op->timeout; /* likewise */
+
+ do
+ {
+ /*
+ * If 'op' expires later than t_op, then insert 'op' just
+ * ahead of t_op. Otherwise, compute when operation[n-1]
+ * expires and try again.
+ *
+ * The actual different between the expiriation of 'op'
+ * and the current operation what becomes the new operaton's
+ * timeout interval. That interval is also subtracted from
+ * the interval of the operation immediately following where
+ * we stick 'op' (unless the next one isn't timed). The new
+ * timeout assigned to 'op' takes into account the values of
+ * now() and when the previous intervals were compured.
+ */
+ delta = op_tmo - qd_tmo;
+ if (delta >= 0)
+ {
+ op->timeout += (now - pt_tq.epoch);
+ goto done;
+ }
+
+ qd_tmo -= t_op->timeout; /* previous operaton expiration */
+ t_op = t_op->prev; /* point to previous operation */
+ if (NULL != t_op) qd_tmo += t_op->timeout;
+ } while (NULL != t_op);
+
+ /*
+ * If we got here we backed off the head of the list. That means that
+ * this timed entry has to go at the head of the list. This is just
+ * about like having an empty timer list.
+ */
+ delta = op->timeout; /* $$$ is this right? */
+ }
+
+done:
+
+ /*
+ * Insert 'op' into the queue just after t_op or if t_op is null,
+ * at the head of the list.
+ *
+ * If t_op is NULL, the list is currently empty and this is pretty
+ * easy.
+ */
+ if (NULL == t_op)
+ {
+ op->prev = NULL;
+ op->next = pt_tq.head;
+ pt_tq.head = op;
+ if (NULL == pt_tq.tail) pt_tq.tail = op;
+ else op->next->prev = op;
+ }
+ else
+ {
+ op->prev = t_op;
+ op->next = t_op->next;
+ if (NULL != op->prev)
+ op->prev->next = op;
+ if (NULL != op->next)
+ op->next->prev = op;
+ if (t_op == pt_tq.tail)
+ pt_tq.tail = op;
+ }
+
+ /*
+ * Are we adjusting our epoch, etc? Are we replacing
+ * what was previously the element due to expire furthest
+ * out in the future? Is this even a timed operation?
+ */
+ if (PR_INTERVAL_NO_TIMEOUT != op->timeout)
+ {
+ if ((NULL == pt_tq.op) /* we're the one and only */
+ || (t_op == pt_tq.op)) /* we're replacing */
+ {
+ pt_tq.op = op;
+ pt_tq.epoch = now;
+ }
+ }
+
+ pt_tq.op_count += 1;
+
+} /* pt_InsertTimedInternal */
+
+/*
+ * function: pt_FinishTimed
+ *
+ * Takes the finished operation out of the timed queue. It
+ * notifies the initiating thread that the opertions is
+ * complete and returns to the caller the value of the next
+ * operation in the list (or NULL).
+ */
+static pt_Continuation *pt_FinishTimedInternal(pt_Continuation *op)
+{
+ pt_Continuation *next;
+
+ /* remove this one from the list */
+ if (NULL == op->prev) pt_tq.head = op->next;
+ else op->prev->next = op->next;
+ if (NULL == op->next) pt_tq.tail = op->prev;
+ else op->next->prev = op->prev;
+
+ /* did we happen to hit the timed op? */
+ if (op == pt_tq.op) pt_tq.op = op->prev;
+
+ next = op->next;
+ op->next = op->prev = NULL;
+ op->status = pt_continuation_done;
+
+ pt_tq.op_count -= 1;
+#if defined(DEBUG)
+ pt_debug.continuationsServed += 1;
+#endif
+ PR_NotifyCondVar(op->complete);
+
+ return next;
+} /* pt_FinishTimedInternal */
+
+static void ContinuationThread(void *arg)
+{
+ /* initialization */
+ fd_set readSet, writeSet, exceptSet;
+ struct timeval tv;
+ SOCKET *pollingList = 0; /* list built for polling */
+ PRIntn pollingListUsed; /* # entries used in the list */
+ PRIntn pollingListNeeded; /* # entries needed this time */
+ PRIntn pollingSlotsAllocated = 0; /* # entries available in list */
+ PRIntervalTime mx_select_ticks = PR_MillisecondsToInterval(PT_DEFAULT_SELECT_MSEC);
+
+ /* do some real work */
+ while (1)
+ {
+ PRIntn rv;
+ PRStatus status;
+ PRIntn pollIndex;
+ pt_Continuation *op;
+ PRIntervalTime now = PR_IntervalNow();
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
+
+ PR_Lock(pt_tq.ml);
+ while (NULL == pt_tq.head)
+ {
+ status = PR_WaitCondVar(pt_tq.new_op, PR_INTERVAL_NO_TIMEOUT);
+ if ((PR_FAILURE == status)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
+ }
+ pollingListNeeded = pt_tq.op_count;
+ PR_Unlock(pt_tq.ml);
+
+ /* Okay. We're history */
+ if ((PR_FAILURE == status)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
+
+ /*
+ * We are not holding the pt_tq.ml lock now, so more items may
+ * get added to pt_tq during this window of time. We hope
+ * that 10 more spaces in the polling list should be enough.
+ */
+
+ FD_ZERO(&readSet);
+ FD_ZERO(&writeSet);
+ FD_ZERO(&exceptSet);
+ pollingListNeeded += 10;
+ if (pollingListNeeded > pollingSlotsAllocated)
+ {
+ if (NULL != pollingList) PR_DELETE(pollingList);
+ pollingList = PR_MALLOC(pollingListNeeded * sizeof(PRPollDesc));
+ PR_ASSERT(NULL != pollingList);
+ pollingSlotsAllocated = pollingListNeeded;
+ }
+
+#if defined(DEBUG)
+ if (pollingListNeeded > pt_debug.pollingListMax)
+ pt_debug.pollingListMax = pollingListUsed;
+#endif
+
+ /*
+ * Build up a polling list.
+ * This list is sorted on time. Operations that have been
+ * interrupted are completed and not included in the list.
+ * There is an assertion that the operation is in progress.
+ */
+ pollingListUsed = 0;
+ PR_Lock(pt_tq.ml);
+
+ for (op = pt_tq.head; NULL != op;)
+ {
+ if (pt_continuation_abort == op->status)
+ {
+ op->result.code = -1;
+ op->syserrno = WSAEINTR;
+ op = pt_FinishTimedInternal(op);
+ }
+ else
+ {
+ PR_ASSERT(pt_continuation_done != op->status);
+ op->status = pt_continuation_inprogress;
+ if (op->event & PR_POLL_READ) {
+ FD_SET(op->arg1.osfd, &readSet);
+ }
+ if (op->event & PR_POLL_WRITE) {
+ FD_SET(op->arg1.osfd, &writeSet);
+ }
+ if (op->event & PR_POLL_EXCEPT) {
+ FD_SET(op->arg1.osfd, &exceptSet);
+ }
+ pollingList[pollingListUsed] = op->arg1.osfd;
+ pollingListUsed += 1;
+ if (pollingListUsed == pollingSlotsAllocated) break;
+ op = op->next;
+ }
+ }
+
+ PR_Unlock(pt_tq.ml);
+
+ /*
+ * If 'op' isn't NULL at this point, then we didn't get to
+ * the end of the list. That means that more items got added
+ * to the list than we anticipated. So, forget this iteration,
+ * go around the horn again.
+ * One would hope this doesn't happen all that often.
+ */
+ if (NULL != op)
+ {
+#if defined(DEBUG)
+ pt_debug.predictionsFoiled += 1; /* keep track */
+#endif
+ continue; /* make it rethink things */
+ }
+
+ /* there's a chance that all ops got blown away */
+ if (NULL == pt_tq.head) continue;
+ /* if not, we know this is the shortest timeout */
+ timeout = pt_tq.head->timeout;
+
+ /*
+ * We don't want to wait forever on this poll. So keep
+ * the interval down. The operations, if they are timed,
+ * still have to timeout, while those that are not timed
+ * should persist forever. But they may be aborted. That's
+ * what this anxiety is all about.
+ */
+ if (timeout > mx_select_ticks) timeout = mx_select_ticks;
+
+ if (PR_INTERVAL_NO_TIMEOUT != pt_tq.head->timeout)
+ pt_tq.head->timeout -= timeout;
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
+
+ rv = select(0, &readSet, &writeSet, &exceptSet, &tv);
+
+ if (0 == rv) /* poll timed out - what about leading op? */
+ {
+ if (0 == pt_tq.head->timeout)
+ {
+ /*
+ * The leading element of the timed queue has timed
+ * out. Get rid of it. In any case go around the
+ * loop again, computing the polling list, checking
+ * for interrupted operations.
+ */
+ PR_Lock(pt_tq.ml);
+ do
+ {
+ pt_tq.head->result.code = -1;
+ pt_tq.head->syserrno = WSAETIMEDOUT;
+ op = pt_FinishTimedInternal(pt_tq.head);
+ } while ((NULL != op) && (0 == op->timeout));
+ PR_Unlock(pt_tq.ml);
+ }
+ continue;
+ }
+
+ if (-1 == rv && (WSAGetLastError() == WSAEINTR
+ || WSAGetLastError() == WSAEINPROGRESS))
+ {
+ continue; /* go around the loop again */
+ }
+
+ /*
+ * select() says that something in our list is ready for some more
+ * action or is an invalid fd. Find it, load up the operation and
+ * see what happens.
+ */
+
+ PR_ASSERT(rv > 0 || WSAGetLastError() == WSAENOTSOCK);
+
+
+ /*
+ * $$$ There's a problem here. I'm running the operations list
+ * and I'm not holding any locks. I don't want to hold the lock
+ * and do the operation, so this is really messed up..
+ *
+ * This may work out okay. The rule is that only this thread,
+ * the continuation thread, can remove elements from the list.
+ * Therefore, the list is at worst, longer than when we built
+ * the polling list.
+ */
+ op = pt_tq.head;
+ for (pollIndex = 0; pollIndex < pollingListUsed; ++pollIndex)
+ {
+ PRInt16 revents = 0;
+
+ PR_ASSERT(NULL != op);
+
+ /*
+ * This one wants attention. Redo the operation.
+ * We know that there can only be more elements
+ * in the op list than we knew about when we created
+ * the poll list. Therefore, we might have to skip
+ * a few ops to find the right one to operation on.
+ */
+ while (pollingList[pollIndex] != op->arg1.osfd )
+ {
+ op = op->next;
+ PR_ASSERT(NULL != op);
+ }
+
+ if (FD_ISSET(op->arg1.osfd, &readSet)) {
+ revents |= PR_POLL_READ;
+ }
+ if (FD_ISSET(op->arg1.osfd, &writeSet)) {
+ revents |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(op->arg1.osfd, &exceptSet)) {
+ revents |= PR_POLL_EXCEPT;
+ }
+
+ /*
+ * Sip over all those not in progress. They'll be
+ * pruned next time we build a polling list. Call
+ * the continuation function. If it reports completion,
+ * finish off the operation.
+ */
+ if (revents && (pt_continuation_inprogress == op->status)
+ && (op->function(op, revents)))
+ {
+ PR_Lock(pt_tq.ml);
+ op = pt_FinishTimedInternal(op);
+ PR_Unlock(pt_tq.ml);
+ }
+ }
+ }
+ if (NULL != pollingList) PR_DELETE(pollingList);
+} /* ContinuationThread */
+
+static int pt_Continue(pt_Continuation *op)
+{
+ PRStatus rv;
+ /* Finish filling in the blank slots */
+ op->status = pt_continuation_sumbitted;
+ op->complete = PR_NewCondVar(pt_tq.ml);
+
+ PR_Lock(pt_tq.ml); /* we provide the locking */
+
+ pt_InsertTimedInternal(op); /* insert in the structure */
+
+ PR_NotifyCondVar(pt_tq.new_op); /* notify the continuation thread */
+
+ while (pt_continuation_done != op->status) /* wait for completion */
+ {
+ rv = PR_WaitCondVar(op->complete, PR_INTERVAL_NO_TIMEOUT);
+ /*
+ * If we get interrupted, we set state the continuation thread will
+ * see and allow it to finish the I/O operation w/ error. That way
+ * the rule that only the continuation thread is removing elements
+ * from the list is still valid.
+ *
+ * Don't call interrupt on the continuation thread. That'll just
+ * piss him off. He's cycling around at least every mx_select_ticks
+ * anyhow and should notice the request in there.
+ */
+ if ((PR_FAILURE == rv)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError()))
+ op->status = pt_continuation_abort; /* our status */
+ }
+
+ PR_Unlock(pt_tq.ml); /* we provide the locking */
+
+ PR_DestroyCondVar(op->complete);
+
+ return op->result.code; /* and the primary answer */
+} /* pt_Continue */
+
+static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents)
+{
+ PRIntn bytes = sendto(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags,
+ (struct sockaddr*)op->arg5.addr, sizeof(*(op->arg5.addr)));
+ op->syserrno = WSAGetLastError();
+ if (bytes > 0) /* this is progress */
+ {
+ char *bp = op->arg2.buffer;
+ bp += bytes; /* adjust the buffer pointer */
+ op->arg2.buffer = bp;
+ op->result.code += bytes; /* accumulate the number sent */
+ op->arg3.amount -= bytes; /* and reduce the required count */
+ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
+ }
+ else return ((-1 == bytes) && (WSAEWOULDBLOCK == op->syserrno)) ?
+ PR_FALSE : PR_TRUE;
+} /* pt_sendto_cont */
+
+static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents)
+{
+ PRIntn addr_len = sizeof(*(op->arg5.addr));
+ op->result.code = recvfrom(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount,
+ op->arg4.flags, (struct sockaddr*)op->arg5.addr, &addr_len);
+ op->syserrno = WSAGetLastError();
+ return ((-1 == op->result.code) && (WSAEWOULDBLOCK == op->syserrno)) ?
+ PR_FALSE : PR_TRUE;
+} /* pt_recvfrom_cont */
+
+static PRInt32 pt_SendTo(
+ SOCKET osfd, const void *buf,
+ PRInt32 amount, PRInt32 flags, const PRNetAddr *addr,
+ PRIntn addrlen, PRIntervalTime timeout)
+{
+ PRInt32 bytes = -1, err;
+ PRBool fNeedContinue = PR_FALSE;
+
+ bytes = sendto(
+ osfd, buf, amount, flags,
+ (struct sockaddr*)addr, PR_NETADDR_SIZE(addr));
+ if (bytes == -1) {
+ if ((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ fNeedContinue = PR_TRUE;
+ else
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+ op.arg1.osfd = osfd;
+ op.arg2.buffer = (void*)buf;
+ op.arg3.amount = amount;
+ op.arg4.flags = flags;
+ op.arg5.addr = (PRNetAddr*)addr;
+ op.timeout = timeout;
+ op.result.code = 0; /* initialize the number sent */
+ op.function = pt_sendto_cont;
+ op.event = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ bytes = pt_Continue(&op);
+ if (bytes < 0) {
+ WSASetLastError(op.syserrno);
+ _PR_MD_MAP_SENDTO_ERROR(op.syserrno);
+ }
+ }
+ return bytes;
+} /* pt_SendTo */
+
+static PRInt32 pt_RecvFrom(SOCKET osfd, void *buf, PRInt32 amount,
+ PRInt32 flags, PRNetAddr *addr, PRIntn *addr_len, PRIntervalTime timeout)
+{
+ PRInt32 bytes = -1, err;
+ PRBool fNeedContinue = PR_FALSE;
+
+ bytes = recvfrom(
+ osfd, buf, amount, flags,
+ (struct sockaddr*)addr, addr_len);
+ if (bytes == -1) {
+ if ((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ fNeedContinue = PR_TRUE;
+ else
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+ op.arg1.osfd = osfd;
+ op.arg2.buffer = buf;
+ op.arg3.amount = amount;
+ op.arg4.flags = flags;
+ op.arg5.addr = addr;
+ op.timeout = timeout;
+ op.function = pt_recvfrom_cont;
+ op.event = PR_POLL_READ | PR_POLL_EXCEPT;
+ bytes = pt_Continue(&op);
+ if (bytes < 0) {
+ WSASetLastError(op.syserrno);
+ _PR_MD_MAP_RECVFROM_ERROR(op.syserrno);
+ }
+ }
+ return bytes;
+} /* pt_RecvFrom */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntmisc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntmisc.c
new file mode 100644
index 00000000..849bbbe0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntmisc.c
@@ -0,0 +1,929 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * ntmisc.c
+ *
+ */
+
+#include "primpl.h"
+
+char *_PR_MD_GET_ENV(const char *name)
+{
+ return getenv(name);
+}
+
+/*
+** _PR_MD_PUT_ENV() -- add or change environment variable
+**
+**
+*/
+PRIntn _PR_MD_PUT_ENV(const char *name)
+{
+ return(putenv(name));
+}
+
+
+/*
+ **************************************************************************
+ **************************************************************************
+ **
+ ** Date and time routines
+ **
+ **************************************************************************
+ **************************************************************************
+ */
+
+#include <sys/timeb.h>
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the
+ * implementation for Windows.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTime)
+PR_Now(void)
+{
+ PRTime prt;
+ FILETIME ft;
+
+ GetSystemTimeAsFileTime(&ft);
+ _PR_FileTimeToPRTime(&ft, &prt);
+ return prt;
+}
+
+/*
+ * The following code works around a bug in NT (Netscape Bugsplat
+ * Defect ID 47942).
+ *
+ * In Windows NT 3.51 and 4.0, if the local time zone does not practice
+ * daylight savings time, e.g., Arizona, Taiwan, and Japan, the global
+ * variables that _ftime() and localtime() depend on have the wrong
+ * default values:
+ * _tzname[0] "PST"
+ * _tzname[1] "PDT"
+ * _daylight 1
+ * _timezone 28800
+ *
+ * So at startup time, we need to invoke _PR_Win32InitTimeZone(), which
+ * on NT sets these global variables to the correct values (obtained by
+ * calling GetTimeZoneInformation().
+ */
+
+#include <time.h> /* for _tzname, _daylight, _timezone */
+
+void
+_PR_Win32InitTimeZone(void)
+{
+ OSVERSIONINFO version;
+ TIME_ZONE_INFORMATION tzinfo;
+
+ version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx(&version) != FALSE) {
+ /* Only Windows NT needs this hack */
+ if (version.dwPlatformId != VER_PLATFORM_WIN32_NT) {
+ return;
+ }
+ }
+
+ if (GetTimeZoneInformation(&tzinfo) == 0xffffffff) {
+ return; /* not much we can do if this failed */
+ }
+
+ /*
+ * I feel nervous about modifying these globals. I hope that no
+ * other thread is reading or modifying these globals simultaneously
+ * during nspr initialization.
+ *
+ * I am assuming that _tzname[0] and _tzname[1] point to static buffers
+ * and that the buffers are at least 32 byte long. My experiments show
+ * this is true, but of course this is undocumented. --wtc
+ *
+ * Convert time zone names from WCHAR to CHAR and copy them to
+ * the static buffers pointed to by _tzname[0] and _tzname[1].
+ * Ignore conversion errors, because it is _timezone and _daylight
+ * that _ftime() and localtime() really depend on.
+ */
+
+ WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1, _tzname[0],
+ 32, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1, _tzname[1],
+ 32, NULL, NULL);
+
+ /* _timezone is in seconds. tzinfo.Bias is in minutes. */
+
+ _timezone = tzinfo.Bias * 60;
+ _daylight = tzinfo.DaylightBias ? 1 : 0;
+ return;
+}
+
+/*
+ ***********************************************************************
+ ***********************************************************************
+ *
+ * Process creation routines
+ *
+ ***********************************************************************
+ ***********************************************************************
+ */
+
+/*
+ * Assemble the command line by concatenating the argv array.
+ * On success, this function returns 0 and the resulting command
+ * line is returned in *cmdLine. On failure, it returns -1.
+ */
+static int assembleCmdLine(char *const *argv, char **cmdLine)
+{
+ char *const *arg;
+ char *p, *q;
+ int cmdLineSize;
+ int numBackslashes;
+ int i;
+ int argNeedQuotes;
+
+ /*
+ * Find out how large the command line buffer should be.
+ */
+ cmdLineSize = 0;
+ for (arg = argv; *arg; arg++) {
+ /*
+ * \ and " need to be escaped by a \. In the worst case,
+ * every character is a \ or ", so the string of length
+ * may double. If we quote an argument, that needs two ".
+ * Finally, we need a space between arguments, and
+ * a null byte at the end of command line.
+ */
+ cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
+ + 2 /* we quote every argument */
+ + 1; /* space in between, or final null */
+ }
+ p = *cmdLine = PR_MALLOC(cmdLineSize);
+ if (p == NULL) {
+ return -1;
+ }
+
+ for (arg = argv; *arg; arg++) {
+ /* Add a space to separates the arguments */
+ if (arg != argv) {
+ *p++ = ' ';
+ }
+ q = *arg;
+ numBackslashes = 0;
+ argNeedQuotes = 0;
+
+ /* If the argument contains white space, it needs to be quoted. */
+ if (strpbrk(*arg, " \f\n\r\t\v")) {
+ argNeedQuotes = 1;
+ }
+
+ if (argNeedQuotes) {
+ *p++ = '"';
+ }
+ while (*q) {
+ if (*q == '\\') {
+ numBackslashes++;
+ q++;
+ } else if (*q == '"') {
+ if (numBackslashes) {
+ /*
+ * Double the backslashes since they are followed
+ * by a quote
+ */
+ for (i = 0; i < 2 * numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ numBackslashes = 0;
+ }
+ /* To escape the quote */
+ *p++ = '\\';
+ *p++ = *q++;
+ } else {
+ if (numBackslashes) {
+ /*
+ * Backslashes are not followed by a quote, so
+ * don't need to double the backslashes.
+ */
+ for (i = 0; i < numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ numBackslashes = 0;
+ }
+ *p++ = *q++;
+ }
+ }
+
+ /* Now we are at the end of this argument */
+ if (numBackslashes) {
+ /*
+ * Double the backslashes if we have a quote string
+ * delimiter at the end.
+ */
+ if (argNeedQuotes) {
+ numBackslashes *= 2;
+ }
+ for (i = 0; i < numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ }
+ if (argNeedQuotes) {
+ *p++ = '"';
+ }
+ }
+
+ *p = '\0';
+ return 0;
+}
+
+/*
+ * Assemble the environment block by concatenating the envp array
+ * (preserving the terminating null byte in each array element)
+ * and adding a null byte at the end.
+ *
+ * Returns 0 on success. The resulting environment block is returned
+ * in *envBlock. Note that if envp is NULL, a NULL pointer is returned
+ * in *envBlock. Returns -1 on failure.
+ */
+static int assembleEnvBlock(char **envp, char **envBlock)
+{
+ char *p;
+ char *q;
+ char **env;
+ char *curEnv;
+ char *cwdStart, *cwdEnd;
+ int envBlockSize;
+
+ if (envp == NULL) {
+ *envBlock = NULL;
+ return 0;
+ }
+
+ curEnv = GetEnvironmentStrings();
+
+ cwdStart = curEnv;
+ while (*cwdStart) {
+ if (cwdStart[0] == '=' && cwdStart[1] != '\0'
+ && cwdStart[2] == ':' && cwdStart[3] == '=') {
+ break;
+ }
+ cwdStart += strlen(cwdStart) + 1;
+ }
+ cwdEnd = cwdStart;
+ if (*cwdEnd) {
+ cwdEnd += strlen(cwdEnd) + 1;
+ while (*cwdEnd) {
+ if (cwdEnd[0] != '=' || cwdEnd[1] == '\0'
+ || cwdEnd[2] != ':' || cwdEnd[3] != '=') {
+ break;
+ }
+ cwdEnd += strlen(cwdEnd) + 1;
+ }
+ }
+ envBlockSize = cwdEnd - cwdStart;
+
+ for (env = envp; *env; env++) {
+ envBlockSize += strlen(*env) + 1;
+ }
+ envBlockSize++;
+
+ p = *envBlock = PR_MALLOC(envBlockSize);
+ if (p == NULL) {
+ FreeEnvironmentStrings(curEnv);
+ return -1;
+ }
+
+ q = cwdStart;
+ while (q < cwdEnd) {
+ *p++ = *q++;
+ }
+ FreeEnvironmentStrings(curEnv);
+
+ for (env = envp; *env; env++) {
+ q = *env;
+ while (*q) {
+ *p++ = *q++;
+ }
+ *p++ = '\0';
+ }
+ *p = '\0';
+ return 0;
+}
+
+/*
+ * For qsort. We sort (case-insensitive) the environment strings
+ * before generating the environment block.
+ */
+static int compare(const void *arg1, const void *arg2)
+{
+ return _stricmp(* (char**)arg1, * (char**)arg2);
+}
+
+PRProcess * _PR_CreateWindowsProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+ STARTUPINFO startupInfo;
+ PROCESS_INFORMATION procInfo;
+ BOOL retVal;
+ char *cmdLine = NULL;
+ char *envBlock = NULL;
+ char **newEnvp = NULL;
+ const char *cwd = NULL; /* current working directory */
+ PRProcess *proc = NULL;
+
+ proc = PR_NEW(PRProcess);
+ if (!proc) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ if (assembleCmdLine(argv, &cmdLine) == -1) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ /*
+ * If attr->fdInheritBuffer is not NULL, we need to insert
+ * it into the envp array, so envp cannot be NULL.
+ */
+ if ((envp == NULL) && attr && attr->fdInheritBuffer) {
+ envp = environ;
+ }
+
+ if (envp != NULL) {
+ int idx;
+ int numEnv;
+ int newEnvpSize;
+
+ numEnv = 0;
+ while (envp[numEnv]) {
+ numEnv++;
+ }
+ newEnvpSize = numEnv + 1; /* terminating null pointer */
+ if (attr && attr->fdInheritBuffer) {
+ newEnvpSize++;
+ }
+ newEnvp = (char **) PR_MALLOC(newEnvpSize * sizeof(char *));
+ for (idx = 0; idx < numEnv; idx++) {
+ newEnvp[idx] = envp[idx];
+ }
+ if (attr && attr->fdInheritBuffer) {
+ newEnvp[idx++] = attr->fdInheritBuffer;
+ }
+ newEnvp[idx] = NULL;
+ qsort((void *) newEnvp, (size_t) (newEnvpSize - 1),
+ sizeof(char *), compare);
+ }
+ if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto errorExit;
+ }
+
+ ZeroMemory(&startupInfo, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+
+ if (attr) {
+ PRBool redirected = PR_FALSE;
+
+ /*
+ * XXX the default value for stdin, stdout, and stderr
+ * should probably be the console input and output, not
+ * those of the parent process.
+ */
+ startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ if (attr->stdinFd) {
+ startupInfo.hStdInput = (HANDLE) attr->stdinFd->secret->md.osfd;
+ redirected = PR_TRUE;
+ }
+ if (attr->stdoutFd) {
+ startupInfo.hStdOutput = (HANDLE) attr->stdoutFd->secret->md.osfd;
+ redirected = PR_TRUE;
+ }
+ if (attr->stderrFd) {
+ startupInfo.hStdError = (HANDLE) attr->stderrFd->secret->md.osfd;
+ redirected = PR_TRUE;
+ }
+ if (redirected) {
+ startupInfo.dwFlags |= STARTF_USESTDHANDLES;
+ }
+ cwd = attr->currentDirectory;
+ }
+
+ retVal = CreateProcess(NULL,
+ cmdLine,
+ NULL, /* security attributes for the new
+ * process */
+ NULL, /* security attributes for the primary
+ * thread in the new process */
+ TRUE, /* inherit handles */
+ 0, /* creation flags */
+ envBlock, /* an environment block, consisting
+ * of a null-terminated block of
+ * null-terminated strings. Each
+ * string is in the form:
+ * name=value
+ * XXX: usually NULL */
+ cwd, /* current drive and directory */
+ &startupInfo,
+ &procInfo
+ );
+ if (retVal == FALSE) {
+ /* XXX what error code? */
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ goto errorExit;
+ }
+
+ CloseHandle(procInfo.hThread);
+ proc->md.handle = procInfo.hProcess;
+ proc->md.id = procInfo.dwProcessId;
+
+ PR_DELETE(cmdLine);
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (envBlock) {
+ PR_DELETE(envBlock);
+ }
+ return proc;
+
+errorExit:
+ if (cmdLine) {
+ PR_DELETE(cmdLine);
+ }
+ if (newEnvp) {
+ PR_DELETE(newEnvp);
+ }
+ if (envBlock) {
+ PR_DELETE(envBlock);
+ }
+ if (proc) {
+ PR_DELETE(proc);
+ }
+ return NULL;
+} /* _PR_CreateWindowsProcess */
+
+PRStatus _PR_DetachWindowsProcess(PRProcess *process)
+{
+ CloseHandle(process->md.handle);
+ PR_DELETE(process);
+ return PR_SUCCESS;
+}
+
+/*
+ * XXX: This implementation is a temporary quick solution.
+ * It can be called by native threads only (not by fibers).
+ */
+PRStatus _PR_WaitWindowsProcess(PRProcess *process,
+ PRInt32 *exitCode)
+{
+ DWORD dwRetVal;
+
+ dwRetVal = WaitForSingleObject(process->md.handle, INFINITE);
+ if (dwRetVal == WAIT_FAILED) {
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ PR_ASSERT(dwRetVal == WAIT_OBJECT_0);
+ if (exitCode != NULL &&
+ GetExitCodeProcess(process->md.handle, exitCode) == FALSE) {
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ CloseHandle(process->md.handle);
+ PR_DELETE(process);
+ return PR_SUCCESS;
+}
+
+PRStatus _PR_KillWindowsProcess(PRProcess *process)
+{
+ /*
+ * On Unix, if a process terminates normally, its exit code is
+ * between 0 and 255. So here on Windows, we use the exit code
+ * 256 to indicate that the process is killed.
+ */
+ if (TerminateProcess(process->md.handle, 256)) {
+ return PR_SUCCESS;
+ }
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+}
+
+PRStatus _MD_WindowsGetHostName(char *name, PRUint32 namelen)
+{
+ PRIntn rv;
+ PRInt32 syserror;
+
+ rv = gethostname(name, (PRInt32) namelen);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ }
+ syserror = WSAGetLastError();
+ PR_ASSERT(WSANOTINITIALISED != syserror);
+ _PR_MD_MAP_GETHOSTNAME_ERROR(syserror);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_WindowsGetSysInfo(PRSysInfo cmd, char *name, PRUint32 namelen)
+{
+ OSVERSIONINFO osvi;
+
+ PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE));
+
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ if (! GetVersionEx (&osvi) ) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+
+ switch (osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_NT:
+ if (PR_SI_SYSNAME == cmd)
+ (void)PR_snprintf(name, namelen, "Windows_NT");
+ else if (PR_SI_RELEASE == cmd)
+ (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion,
+ osvi.dwMinorVersion);
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ if (PR_SI_SYSNAME == cmd) {
+ if ((osvi.dwMajorVersion > 4) ||
+ ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0)))
+ (void)PR_snprintf(name, namelen, "Windows_98");
+ else
+ (void)PR_snprintf(name, namelen, "Windows_95");
+ } else if (PR_SI_RELEASE == cmd) {
+ (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion,
+ osvi.dwMinorVersion);
+ }
+ break;
+ default:
+ if (PR_SI_SYSNAME == cmd)
+ (void)PR_snprintf(name, namelen, "Windows_Unknown");
+ else if (PR_SI_RELEASE == cmd)
+ (void)PR_snprintf(name, namelen, "%d.%d",0,0);
+ break;
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus _MD_WindowsGetReleaseName(char *name, PRUint32 namelen)
+{
+ OSVERSIONINFO osvi;
+
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ if (! GetVersionEx (&osvi) ) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+
+ switch (osvi.dwPlatformId) {
+ case VER_PLATFORM_WIN32_NT:
+ case VER_PLATFORM_WIN32_WINDOWS:
+ (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion,
+ osvi.dwMinorVersion);
+ break;
+ default:
+ (void)PR_snprintf(name, namelen, "%d.%d",0,0);
+ break;
+ }
+ return PR_SUCCESS;
+}
+
+/*
+ **********************************************************************
+ *
+ * Memory-mapped files
+ *
+ **********************************************************************
+ */
+
+PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
+{
+ DWORD dwHi, dwLo;
+ DWORD flProtect;
+ PRUint32 osfd;
+
+ osfd = ( fmap->fd == (PRFileDesc*)-1 )? -1 : fmap->fd->secret->md.osfd;
+
+ dwLo = (DWORD) (size & 0xffffffff);
+ dwHi = (DWORD) (((PRUint64) size >> 32) & 0xffffffff);
+
+ if (fmap->prot == PR_PROT_READONLY) {
+ flProtect = PAGE_READONLY;
+ fmap->md.dwAccess = FILE_MAP_READ;
+ } else if (fmap->prot == PR_PROT_READWRITE) {
+ flProtect = PAGE_READWRITE;
+ fmap->md.dwAccess = FILE_MAP_WRITE;
+ } else {
+ PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
+ flProtect = PAGE_WRITECOPY;
+ fmap->md.dwAccess = FILE_MAP_COPY;
+ }
+
+ fmap->md.hFileMap = CreateFileMapping(
+ (HANDLE) osfd,
+ NULL,
+ flProtect,
+ dwHi,
+ dwLo,
+ NULL);
+
+ if (fmap->md.hFileMap == NULL) {
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PRInt32 _MD_GetMemMapAlignment(void)
+{
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ return info.dwAllocationGranularity;
+}
+
+#include "prlog.h"
+extern PRLogModuleInfo *_pr_shma_lm;
+void * _MD_MemMap(
+ PRFileMap *fmap,
+ PROffset64 offset,
+ PRUint32 len)
+{
+ DWORD dwHi, dwLo;
+ void *addr;
+
+ dwLo = (DWORD) (offset & 0xffffffff);
+ dwHi = (DWORD) (((PRUint64) offset >> 32) & 0xffffffff);
+ if ((addr = MapViewOfFile(fmap->md.hFileMap, fmap->md.dwAccess,
+ dwHi, dwLo, len)) == NULL) {
+ {
+ LPVOID lpMsgBuf;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("md_memmap(): %s", lpMsgBuf ));
+ }
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ }
+ return addr;
+}
+
+PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
+{
+ if (UnmapViewOfFile(addr)) {
+ return PR_SUCCESS;
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus _MD_CloseFileMap(PRFileMap *fmap)
+{
+ CloseHandle(fmap->md.hFileMap);
+ PR_DELETE(fmap);
+ return PR_SUCCESS;
+}
+
+/*
+ ***********************************************************************
+ *
+ * Atomic increment and decrement operations for x86 processors
+ *
+ * We don't use InterlockedIncrement and InterlockedDecrement
+ * because on NT 3.51 and Win95, they return a number with
+ * the same sign as the incremented/decremented result, rather
+ * than the result itself. On NT 4.0 these functions do return
+ * the incremented/decremented result.
+ *
+ * The result is returned in the eax register by the inline
+ * assembly code. We disable the harmless "no return value"
+ * warning (4035) for these two functions.
+ *
+ ***********************************************************************
+ */
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#pragma warning(disable: 4035)
+PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+#if defined(__GNUC__)
+ PRInt32 result;
+ asm volatile ("lock ; xadd %0, %1"
+ : "=r"(result), "=m"(*val)
+ : "0"(1), "m"(*val));
+ return result + 1;
+#else
+ __asm
+ {
+ mov ecx, val
+ mov eax, 1
+ lock xadd dword ptr [ecx], eax
+ inc eax
+ }
+#endif /* __GNUC__ */
+}
+#pragma warning(default: 4035)
+
+#pragma warning(disable: 4035)
+PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+#if defined(__GNUC__)
+ PRInt32 result;
+ asm volatile ("lock ; xadd %0, %1"
+ : "=r"(result), "=m"(*val)
+ : "0"(-1), "m"(*val));
+ //asm volatile("lock ; xadd %0, %1" : "=m" (val), "=a" (result) : "-1" (1));
+ return result - 1;
+#else
+ __asm
+ {
+ mov ecx, val
+ mov eax, 0ffffffffh
+ lock xadd dword ptr [ecx], eax
+ dec eax
+ }
+#endif /* __GNUC__ */
+}
+#pragma warning(default: 4035)
+
+#pragma warning(disable: 4035)
+PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val)
+{
+#if defined(__GNUC__)
+ PRInt32 result;
+ //asm volatile("lock ; xadd %1, %0" : "=m" (intp), "=a" (result) : "1" (val));
+ asm volatile ("lock ; xadd %0, %1"
+ : "=r"(result), "=m"(*intp)
+ : "0"(val), "m"(*intp));
+ return result + val;
+#else
+ __asm
+ {
+ mov ecx, intp
+ mov eax, val
+ mov edx, eax
+ lock xadd dword ptr [ecx], eax
+ add eax, edx
+ }
+#endif /* __GNUC__ */
+}
+#pragma warning(default: 4035)
+
+#ifdef _PR_HAVE_ATOMIC_CAS
+
+#pragma warning(disable: 4035)
+void
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+#if defined(__GNUC__)
+ void **tos = (void **) stack;
+ void *tmp;
+
+ retry:
+ if (*tos == (void *) -1)
+ goto retry;
+
+ __asm__("lock xchg %0,%1"
+ : "=r" (tmp), "=m"(*tos)
+ : "0" (-1), "m"(*tos));
+
+ if (tmp == (void *) -1)
+ goto retry;
+
+ *(void **)stack_elem = tmp;
+ __asm__("" : : : "memory");
+ *tos = stack_elem;
+#else
+ __asm
+ {
+ mov ebx, stack
+ mov ecx, stack_elem
+retry: mov eax,[ebx]
+ cmp eax,-1
+ je retry
+ mov eax,-1
+ xchg dword ptr [ebx], eax
+ cmp eax,-1
+ je retry
+ mov [ecx],eax
+ mov [ebx],ecx
+ }
+#endif /* __GNUC__ */
+}
+#pragma warning(default: 4035)
+
+#pragma warning(disable: 4035)
+PRStackElem *
+PR_StackPop(PRStack *stack)
+{
+#if defined(__GNUC__)
+ void **tos = (void **) stack;
+ void *tmp;
+
+ retry:
+ if (*tos == (void *) -1)
+ goto retry;
+
+ __asm__("lock xchg %0,%1"
+ : "=r" (tmp), "=m"(*tos)
+ : "0" (-1), "m"(*tos));
+
+ if (tmp == (void *) -1)
+ goto retry;
+
+ if (tmp != (void *) 0)
+ {
+ void *next = *(void **)tmp;
+ *tos = next;
+ *(void **)tmp = 0;
+ }
+ else
+ *tos = tmp;
+
+ return tmp;
+#else
+ __asm
+ {
+ mov ebx, stack
+retry: mov eax,[ebx]
+ cmp eax,-1
+ je retry
+ mov eax,-1
+ xchg dword ptr [ebx], eax
+ cmp eax,-1
+ je retry
+ cmp eax,0
+ je empty
+ mov ecx,[eax]
+ mov [ebx],ecx
+ mov [eax],0
+ jmp done
+empty:
+ mov [ebx],eax
+done:
+ }
+#endif /* __GNUC__ */
+}
+#pragma warning(default: 4035)
+
+#endif /* _PR_HAVE_ATOMIC_CAS */
+
+#endif /* x86 processors */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsec.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsec.c
new file mode 100644
index 00000000..89ac1dfb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsec.c
@@ -0,0 +1,279 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 "primpl.h"
+
+/*
+ * ntsec.c
+ *
+ * Implement the POSIX-style mode bits (access permissions) for
+ * files and other securable objects in Windows NT using Windows
+ * NT's security descriptors with appropriate discretionary
+ * access-control lists.
+ */
+
+/*
+ * The security identifiers (SIDs) for owner, primary group,
+ * and the Everyone (World) group.
+ *
+ * These SIDs are looked up during NSPR initialization and
+ * saved in this global structure (see _PR_NT_InitSids) so
+ * that _PR_NT_MakeSecurityDescriptorACL doesn't need to
+ * look them up every time.
+ */
+static struct {
+ PSID owner;
+ PSID group;
+ PSID everyone;
+} _pr_nt_sids;
+
+/*
+ * Initialize the SIDs for owner, primary group, and the Everyone
+ * group in the _pr_nt_sids structure.
+ *
+ * This function needs to be called by NSPR initialization.
+ */
+void _PR_NT_InitSids(void)
+{
+ SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
+ HANDLE hToken = NULL; /* initialized to an arbitrary value to
+ * silence a Purify UMR warning */
+ UCHAR infoBuffer[1024];
+ PTOKEN_OWNER pTokenOwner = (PTOKEN_OWNER) infoBuffer;
+ PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup
+ = (PTOKEN_PRIMARY_GROUP) infoBuffer;
+ DWORD dwLength;
+ BOOL rv;
+
+ /*
+ * Look up and make a copy of the owner and primary group
+ * SIDs in the access token of the calling process.
+ */
+ rv = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
+ if (rv == 0) {
+ /*
+ * On non-NT systems, this function is not implemented
+ * (error code ERROR_CALL_NOT_IMPLEMENTED), and neither are
+ * the other security functions. There is no point in
+ * going further.
+ *
+ * A process with insufficient access permissions may fail
+ * with the error code ERROR_ACCESS_DENIED.
+ */
+ PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
+ ("_PR_NT_InitSids: OpenProcessToken() failed. Error: %d",
+ GetLastError()));
+ return;
+ }
+
+ rv = GetTokenInformation(hToken, TokenOwner, infoBuffer,
+ sizeof(infoBuffer), &dwLength);
+ PR_ASSERT(rv != 0);
+ dwLength = GetLengthSid(pTokenOwner->Owner);
+ _pr_nt_sids.owner = (PSID) PR_Malloc(dwLength);
+ PR_ASSERT(_pr_nt_sids.owner != NULL);
+ rv = CopySid(dwLength, _pr_nt_sids.owner, pTokenOwner->Owner);
+ PR_ASSERT(rv != 0);
+
+ rv = GetTokenInformation(hToken, TokenPrimaryGroup, infoBuffer,
+ sizeof(infoBuffer), &dwLength);
+ PR_ASSERT(rv != 0);
+ dwLength = GetLengthSid(pTokenPrimaryGroup->PrimaryGroup);
+ _pr_nt_sids.group = (PSID) PR_Malloc(dwLength);
+ PR_ASSERT(_pr_nt_sids.group != NULL);
+ rv = CopySid(dwLength, _pr_nt_sids.group,
+ pTokenPrimaryGroup->PrimaryGroup);
+ PR_ASSERT(rv != 0);
+
+ rv = CloseHandle(hToken);
+ PR_ASSERT(rv != 0);
+
+ /* Create a well-known SID for the Everyone group. */
+ rv = AllocateAndInitializeSid(&SIDAuthWorld, 1,
+ SECURITY_WORLD_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &_pr_nt_sids.everyone);
+ PR_ASSERT(rv != 0);
+}
+
+/*
+ * Free the SIDs for owner, primary group, and the Everyone group
+ * in the _pr_nt_sids structure.
+ *
+ * This function needs to be called by NSPR cleanup.
+ */
+void
+_PR_NT_FreeSids(void)
+{
+ if (_pr_nt_sids.owner) {
+ PR_Free(_pr_nt_sids.owner);
+ }
+ if (_pr_nt_sids.group) {
+ PR_Free(_pr_nt_sids.group);
+ }
+ if (_pr_nt_sids.everyone) {
+ FreeSid(_pr_nt_sids.everyone);
+ }
+}
+
+/*
+ * Construct a security descriptor whose discretionary access-control
+ * list implements the specified mode bits. The SIDs for owner, group,
+ * and everyone are obtained from the global _pr_nt_sids structure.
+ * Both the security descriptor and access-control list are returned
+ * and should be freed by a _PR_NT_FreeSecurityDescriptorACL call.
+ *
+ * The accessTable array maps NSPR's read, write, and execute access
+ * rights to the corresponding NT access rights for the securable
+ * object.
+ */
+PRStatus
+_PR_NT_MakeSecurityDescriptorACL(
+ PRIntn mode,
+ DWORD accessTable[],
+ PSECURITY_DESCRIPTOR *resultSD,
+ PACL *resultACL)
+{
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+ DWORD cbACL; /* size of ACL */
+ DWORD accessMask;
+
+ if (_pr_nt_sids.owner == NULL) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ pSD = (PSECURITY_DESCRIPTOR) PR_Malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (pSD == NULL) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ if (!SetSecurityDescriptorOwner(pSD, _pr_nt_sids.owner, FALSE)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ if (!SetSecurityDescriptorGroup(pSD, _pr_nt_sids.group, FALSE)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+
+ /*
+ * Construct a discretionary access-control list with three
+ * access-control entries, one each for owner, primary group,
+ * and Everyone.
+ */
+
+ cbACL = sizeof(ACL)
+ + 3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD))
+ + GetLengthSid(_pr_nt_sids.owner)
+ + GetLengthSid(_pr_nt_sids.group)
+ + GetLengthSid(_pr_nt_sids.everyone);
+ pACL = (PACL) PR_Malloc(cbACL);
+ if (pACL == NULL) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ accessMask = 0;
+ if (mode & 00400) accessMask |= accessTable[0];
+ if (mode & 00200) accessMask |= accessTable[1];
+ if (mode & 00100) accessMask |= accessTable[2];
+ if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask,
+ _pr_nt_sids.owner)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ accessMask = 0;
+ if (mode & 00040) accessMask |= accessTable[0];
+ if (mode & 00020) accessMask |= accessTable[1];
+ if (mode & 00010) accessMask |= accessTable[2];
+ if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask,
+ _pr_nt_sids.group)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+ accessMask = 0;
+ if (mode & 00004) accessMask |= accessTable[0];
+ if (mode & 00002) accessMask |= accessTable[1];
+ if (mode & 00001) accessMask |= accessTable[2];
+ if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask,
+ _pr_nt_sids.everyone)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+
+ if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ goto failed;
+ }
+
+ *resultSD = pSD;
+ *resultACL = pACL;
+ return PR_SUCCESS;
+
+failed:
+ if (pSD) {
+ PR_Free(pSD);
+ }
+ if (pACL) {
+ PR_Free(pACL);
+ }
+ return PR_FAILURE;
+}
+
+/*
+ * Free the specified security descriptor and access-control list
+ * previously created by _PR_NT_MakeSecurityDescriptorACL.
+ */
+void
+_PR_NT_FreeSecurityDescriptorACL(PSECURITY_DESCRIPTOR pSD, PACL pACL)
+{
+ if (pSD) {
+ PR_Free(pSD);
+ }
+ if (pACL) {
+ PR_Free(pACL);
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsem.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsem.c
new file mode 100644
index 00000000..b25fac62
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntsem.c
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * NT-specific semaphore handling code.
+ *
+ */
+
+
+#include "primpl.h"
+
+
+void
+_PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value)
+{
+ md->sem = CreateSemaphore(NULL, value, 0x7fffffff, NULL);
+}
+
+void
+_PR_MD_DESTROY_SEM(_MDSemaphore *md)
+{
+ CloseHandle(md->sem);
+}
+
+PRStatus
+_PR_MD_TIMED_WAIT_SEM(_MDSemaphore *md, PRIntervalTime ticks)
+{
+ int rv;
+
+ rv = WaitForSingleObject(md->sem, PR_IntervalToMilliseconds(ticks));
+
+ if (rv == WAIT_OBJECT_0)
+ return PR_SUCCESS;
+ else
+ return PR_FAILURE;
+}
+
+PRStatus
+_PR_MD_WAIT_SEM(_MDSemaphore *md)
+{
+ return _PR_MD_TIMED_WAIT_SEM(md, PR_INTERVAL_NO_TIMEOUT);
+}
+
+void
+_PR_MD_POST_SEM(_MDSemaphore *md)
+{
+ int old_count;
+
+ ReleaseSemaphore(md->sem, 1, &old_count);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntthread.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntthread.c
new file mode 100644
index 00000000..e53b3ab9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/ntthread.c
@@ -0,0 +1,563 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <process.h> /* for _beginthreadex() */
+
+extern void _PR_Win32InitTimeZone(void); /* defined in ntmisc.c */
+
+/* --- globals ------------------------------------------------ */
+PRLock *_pr_schedLock = NULL;
+_PRInterruptTable _pr_interruptTable[] = { { 0 } };
+
+BOOL _pr_use_static_tls = TRUE;
+__declspec(thread) PRThread *_pr_current_fiber;
+__declspec(thread) PRThread *_pr_fiber_last_run;
+__declspec(thread) _PRCPU *_pr_current_cpu;
+__declspec(thread) PRUintn _pr_ints_off;
+DWORD _pr_currentFiberIndex;
+DWORD _pr_lastFiberIndex;
+DWORD _pr_currentCPUIndex;
+DWORD _pr_intsOffIndex;
+
+_MDLock _nt_idleLock;
+PRCList _nt_idleList;
+PRUint32 _nt_idleCount;
+
+extern __declspec(thread) PRThread *_pr_io_restarted_io;
+extern DWORD _pr_io_restartedIOIndex;
+
+/* Must check the restarted_io *before* decrementing no_sched to 0 */
+#define POST_SWITCH_WORK() \
+ PR_BEGIN_MACRO \
+ PRThread *restarted_io = \
+ (_pr_use_static_tls ? _pr_io_restarted_io \
+ : (PRThread *) TlsGetValue(_pr_io_restartedIOIndex)); \
+ if (restarted_io) { \
+ _nt_handle_restarted_io(restarted_io); \
+ } \
+ _PR_MD_LAST_THREAD()->no_sched = 0; \
+ PR_END_MACRO
+
+void
+_nt_handle_restarted_io(PRThread *restarted_io)
+{
+ /* After the switch we can resume an IO if needed.
+ * XXXMB - this needs to be done in create thread, since that could
+ * be the result for a context switch too..
+ */
+ PR_ASSERT(restarted_io->io_suspended == PR_TRUE);
+ PR_ASSERT(restarted_io->md.thr_bound_cpu == restarted_io->cpu);
+
+ _PR_THREAD_LOCK(restarted_io);
+ if (restarted_io->io_pending == PR_FALSE) {
+
+ /* The IO already completed, put us back on the runq. */
+ int pri = restarted_io->priority;
+
+ restarted_io->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(restarted_io->cpu);
+ _PR_ADD_RUNQ(restarted_io, restarted_io->cpu, pri);
+ _PR_RUNQ_UNLOCK(restarted_io->cpu);
+ } else {
+ _PR_SLEEPQ_LOCK(restarted_io->cpu);
+ _PR_ADD_SLEEPQ(restarted_io, restarted_io->sleep);
+ _PR_SLEEPQ_UNLOCK(restarted_io->cpu);
+ }
+ restarted_io->io_suspended = PR_FALSE;
+ restarted_io->md.thr_bound_cpu = NULL;
+
+ _PR_THREAD_UNLOCK(restarted_io);
+
+ if (_pr_use_static_tls) {
+ _pr_io_restarted_io = NULL;
+ } else {
+ TlsSetValue(_pr_io_restartedIOIndex, NULL);
+ }
+}
+
+void
+_PR_MD_EARLY_INIT()
+{
+ _MD_NEW_LOCK( &_nt_idleLock );
+ _nt_idleCount = 0;
+ PR_INIT_CLIST(&_nt_idleList);
+ _PR_Win32InitTimeZone();
+
+#if 0
+ /* Make the clock tick at least once per millisecond */
+ if ( timeBeginPeriod(1) == TIMERR_NOCANDO) {
+ /* deep yoghurt; clock doesn't tick fast enough! */
+ PR_ASSERT(0);
+ }
+#endif
+
+ if (!_pr_use_static_tls) {
+ _pr_currentFiberIndex = TlsAlloc();
+ _pr_lastFiberIndex = TlsAlloc();
+ _pr_currentCPUIndex = TlsAlloc();
+ _pr_intsOffIndex = TlsAlloc();
+ _pr_io_restartedIOIndex = TlsAlloc();
+ }
+}
+
+void _PR_MD_CLEANUP_BEFORE_EXIT(void)
+{
+ _PR_NT_FreeSids();
+
+ WSACleanup();
+
+ if (!_pr_use_static_tls) {
+ TlsFree(_pr_currentFiberIndex);
+ TlsFree(_pr_lastFiberIndex);
+ TlsFree(_pr_currentCPUIndex);
+ TlsFree(_pr_intsOffIndex);
+ TlsFree(_pr_io_restartedIOIndex);
+ }
+}
+
+PRStatus
+_PR_MD_INIT_THREAD(PRThread *thread)
+{
+ thread->md.overlapped.ioModel = _MD_BlockingIO;
+ thread->md.overlapped.data.mdThread = &thread->md;
+
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
+ /*
+ ** Warning:
+ ** --------
+ ** NSPR requires a real handle to every thread.
+ ** GetCurrentThread() returns a pseudo-handle which
+ ** is not suitable for some thread operations (e.g.,
+ ** suspending). Therefore, get a real handle from
+ ** the pseudo handle via DuplicateHandle(...)
+ */
+ DuplicateHandle(
+ GetCurrentProcess(), /* Process of source handle */
+ GetCurrentThread(), /* Pseudo Handle to dup */
+ GetCurrentProcess(), /* Process of handle */
+ &(thread->md.handle), /* resulting handle */
+ 0L, /* access flags */
+ FALSE, /* Inheritable */
+ DUPLICATE_SAME_ACCESS); /* Options */
+ }
+
+ /* Create the blocking IO semaphore */
+ thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL);
+ if (thread->md.blocked_sema == NULL) {
+ return PR_FAILURE;
+ }
+ if (_native_threads_only) {
+ /* Create the blocking IO semaphore */
+ thread->md.thr_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (thread->md.thr_event == NULL) {
+ return PR_FAILURE;
+ }
+ }
+ }
+
+ return PR_SUCCESS;
+}
+
+static unsigned __stdcall
+pr_root(void *arg)
+{
+ PRThread *thread = (PRThread *)arg;
+ thread->md.start(thread);
+ return 0;
+}
+
+PRStatus
+_PR_MD_CREATE_THREAD(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+
+ thread->md.start = start;
+ thread->md.handle = (HANDLE) _beginthreadex(
+ NULL,
+ thread->stack->stackSize,
+ pr_root,
+ (void *)thread,
+ CREATE_SUSPENDED,
+ &(thread->id));
+ if(!thread->md.handle) {
+ PRErrorCode prerror;
+ thread->md.fiber_last_error = GetLastError();
+ switch (errno) {
+ case ENOMEM:
+ prerror = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case EAGAIN:
+ prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EINVAL:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ }
+ PR_SetError(prerror, errno);
+ return PR_FAILURE;
+ }
+
+ thread->md.id = thread->id;
+ /*
+ * On windows, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL.
+ */
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
+
+ /* Activate the thread */
+ if ( ResumeThread( thread->md.handle ) != -1)
+ return PR_SUCCESS;
+
+ PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
+ return PR_FAILURE;
+}
+
+void
+_PR_MD_JOIN_THREAD(_MDThread *md)
+{
+ DWORD rv;
+
+ rv = WaitForSingleObject(md->handle, INFINITE);
+ PR_ASSERT(WAIT_OBJECT_0 == rv);
+}
+
+void
+_PR_MD_END_THREAD(void)
+{
+ _endthreadex(0);
+}
+
+void
+_PR_MD_YIELD(void)
+{
+ /* Can NT really yield at all? */
+ Sleep(0);
+}
+
+void
+_PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
+{
+ int nativePri;
+ BOOL rv;
+
+ if (newPri < PR_PRIORITY_FIRST) {
+ newPri = PR_PRIORITY_FIRST;
+ } else if (newPri > PR_PRIORITY_LAST) {
+ newPri = PR_PRIORITY_LAST;
+ }
+ switch (newPri) {
+ case PR_PRIORITY_LOW:
+ nativePri = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+ case PR_PRIORITY_NORMAL:
+ nativePri = THREAD_PRIORITY_NORMAL;
+ break;
+ case PR_PRIORITY_HIGH:
+ nativePri = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case PR_PRIORITY_URGENT:
+ nativePri = THREAD_PRIORITY_HIGHEST;
+ }
+ rv = SetThreadPriority(thread->handle, nativePri);
+ PR_ASSERT(rv);
+ if (!rv) {
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("PR_SetThreadPriority: can't set thread priority\n"));
+ }
+ return;
+}
+
+void
+_PR_MD_CLEAN_THREAD(PRThread *thread)
+{
+ BOOL rv;
+
+ if (thread->md.acceptex_buf) {
+ PR_DELETE(thread->md.acceptex_buf);
+ }
+
+ if (thread->md.xmit_bufs) {
+ PR_DELETE(thread->md.xmit_bufs);
+ }
+
+ if (thread->md.blocked_sema) {
+ rv = CloseHandle(thread->md.blocked_sema);
+ PR_ASSERT(rv);
+ thread->md.blocked_sema = 0;
+ }
+ if (_native_threads_only) {
+ if (thread->md.thr_event) {
+ rv = CloseHandle(thread->md.thr_event);
+ PR_ASSERT(rv);
+ thread->md.thr_event = 0;
+ }
+ }
+
+ if (thread->md.handle) {
+ rv = CloseHandle(thread->md.handle);
+ PR_ASSERT(rv);
+ thread->md.handle = 0;
+ }
+
+ /* Don't call DeleteFiber on current fiber or we'll kill the whole thread.
+ * Don't call free(thread) until we've switched off the thread.
+ * So put this fiber (or thread) on a list to be deleted by the idle
+ * fiber next time we have a chance.
+ */
+ if (!(thread->flags & (_PR_ATTACHED|_PR_GLOBAL_SCOPE))) {
+ _MD_LOCK(&_nt_idleLock);
+ _nt_idleCount++;
+ PR_APPEND_LINK(&thread->links, &_nt_idleList);
+ _MD_UNLOCK(&_nt_idleLock);
+ }
+}
+
+void
+_PR_MD_EXIT_THREAD(PRThread *thread)
+{
+ BOOL rv;
+
+ if (thread->md.acceptex_buf) {
+ PR_DELETE(thread->md.acceptex_buf);
+ }
+
+ if (thread->md.xmit_bufs) {
+ PR_DELETE(thread->md.xmit_bufs);
+ }
+
+ if (thread->md.blocked_sema) {
+ rv = CloseHandle(thread->md.blocked_sema);
+ PR_ASSERT(rv);
+ thread->md.blocked_sema = 0;
+ }
+
+ if (_native_threads_only) {
+ if (thread->md.thr_event) {
+ rv = CloseHandle(thread->md.thr_event);
+ PR_ASSERT(rv);
+ thread->md.thr_event = 0;
+ }
+ }
+
+ if (thread->md.handle) {
+ rv = CloseHandle(thread->md.handle);
+ PR_ASSERT(rv);
+ thread->md.handle = 0;
+ }
+
+ if (thread->flags & _PR_GLOBAL_SCOPE) {
+ _MD_SET_CURRENT_THREAD(NULL);
+ }
+}
+
+
+void
+_PR_MD_EXIT(PRIntn status)
+{
+ _exit(status);
+}
+
+#ifdef HAVE_FIBERS
+
+void
+_pr_fiber_mainline(void *unused)
+{
+ PRThread *fiber = _PR_MD_CURRENT_THREAD();
+
+ POST_SWITCH_WORK();
+
+ fiber->md.fiber_fn(fiber->md.fiber_arg);
+}
+
+PRThread *_PR_MD_CREATE_USER_THREAD(
+ PRUint32 stacksize, void (*start)(void *), void *arg)
+{
+ PRThread *thread;
+
+ if ( (thread = PR_NEW(PRThread)) == NULL ) {
+ return NULL;
+ }
+
+ memset(thread, 0, sizeof(PRThread));
+ thread->md.fiber_fn = start;
+ thread->md.fiber_arg = arg;
+ thread->md.fiber_stacksize = stacksize;
+ return thread;
+}
+
+void
+_PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *thread)
+{
+ thread->md.fiber_id = ConvertThreadToFiber(NULL);
+ PR_ASSERT(thread->md.fiber_id);
+ _MD_SET_CURRENT_THREAD(thread);
+ _MD_SET_LAST_THREAD(thread);
+ thread->no_sched = 1;
+ return;
+}
+
+void
+_PR_MD_INIT_CONTEXT(PRThread *thread, char *top, void (*start) (void), PRBool *status)
+{
+ thread->md.fiber_fn = (void (*)(void *))start;
+ thread->md.fiber_id = CreateFiber(thread->md.fiber_stacksize,
+ (LPFIBER_START_ROUTINE)_pr_fiber_mainline, NULL);
+ if (thread->md.fiber_id != 0)
+ *status = PR_TRUE;
+ else {
+ DWORD oserror = GetLastError();
+ PRErrorCode prerror;
+ if (oserror == ERROR_NOT_ENOUGH_MEMORY) {
+ prerror = PR_OUT_OF_MEMORY_ERROR;
+ } else {
+ prerror = PR_UNKNOWN_ERROR;
+ }
+ PR_SetError(prerror, oserror);
+ *status = PR_FALSE;
+ }
+}
+
+void
+_PR_MD_SWITCH_CONTEXT(PRThread *thread)
+{
+ PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );
+
+ thread->md.fiber_last_error = GetLastError();
+ _PR_Schedule();
+}
+
+void
+_PR_MD_RESTORE_CONTEXT(PRThread *thread)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );
+
+ /* The user-level code for yielding will happily add ourselves to the runq
+ * and then switch to ourselves; the NT fibers can't handle switching to
+ * ourselves.
+ */
+ if (thread != me) {
+ SetLastError(thread->md.fiber_last_error);
+ _MD_SET_CURRENT_THREAD(thread);
+ _PR_MD_SET_LAST_THREAD(me);
+ thread->no_sched = 1;
+ SwitchToFiber(thread->md.fiber_id);
+ POST_SWITCH_WORK();
+ }
+}
+
+
+#endif /* HAVE_FIBERS */
+
+PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
+{
+ int rv;
+
+ rv = SetThreadAffinityMask(thread->md.handle, mask);
+
+ return rv?0:-1;
+}
+
+PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
+{
+ PRInt32 rv, system_mask;
+
+ rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);
+
+ return rv?0:-1;
+}
+
+void
+_PR_MD_SUSPEND_CPU(_PRCPU *cpu)
+{
+ _PR_MD_SUSPEND_THREAD(cpu->thread);
+}
+
+void
+_PR_MD_RESUME_CPU(_PRCPU *cpu)
+{
+ _PR_MD_RESUME_THREAD(cpu->thread);
+}
+
+void
+_PR_MD_SUSPEND_THREAD(PRThread *thread)
+{
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ /*
+ ** There seems to be some doubt about whether or not SuspendThread
+ ** is a synchronous function. The test afterwards is to help veriry
+ ** that it is, which is what Microsoft says it is.
+ */
+ PRUintn rv = SuspendThread(thread->md.handle);
+ PR_ASSERT(0xffffffffUL != rv);
+ }
+}
+
+void
+_PR_MD_RESUME_THREAD(PRThread *thread)
+{
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ ResumeThread(thread->md.handle);
+ }
+}
+
+PRThread*
+_MD_CURRENT_THREAD(void)
+{
+PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(thread != NULL);
+ return thread;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/objs.mk b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/objs.mk
new file mode 100644
index 00000000..36f21a44
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/objs.mk
@@ -0,0 +1,94 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+ifeq ($(OS_TARGET),WINNT)
+CSRCS = ntmisc.c \
+ ntsec.c \
+ ntsem.c \
+ ntinrval.c \
+ ntgc.c \
+ ntio.c \
+ ntthread.c \
+ ntdllmn.c \
+ win32_errors.c \
+ w32ipcsem.c \
+ w32poll.c \
+ w32rng.c \
+ w32shm.c
+else
+ifeq ($(OS_TARGET),WIN95)
+CSRCS = ntmisc.c \
+ ntsec.c \
+ ntsem.c \
+ ntinrval.c \
+ ntgc.c \
+ w95thred.c \
+ w95io.c \
+ w95cv.c \
+ w95sock.c \
+ win32_errors.c \
+ w32ipcsem.c \
+ w32poll.c \
+ w32rng.c \
+ w32shm.c \
+ w95dllmain.c
+else
+ifeq ($(OS_TARGET),WIN16)
+CSRCS = w16null.c \
+ w16thred.c \
+ w16proc.c \
+ w16fmem.c \
+ w16sock.c \
+ w16mem.c \
+ w16io.c \
+ w16gc.c \
+ w16error.c \
+ w16stdio.c \
+ w16callb.c \
+ ntinrval.c
+endif # win16
+endif # win95
+endif # winnt
+
+CSRCS += $(PR_MD_CSRCS)
+ASFILES += $(PR_MD_ASFILES)
+
+OBJS += $(addprefix md/windows/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \
+ $(addprefix md/windows/$(OBJDIR)/,$(ASFILES:.s=.$(OBJ_SUFFIX)))
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16callb.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16callb.c
new file mode 100644
index 00000000..3f7b4eea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16callb.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** w16callb.c -- Implement Win16 Callback functions
+**
+** Functions here are to replace functions normally in
+** LIBC which are not implemented in MSVC's LIBC.
+** Some clients of NSPR expect to statically link
+** to NSPR and get these functions.
+**
+** Some are implemented as callbacks to the .EXE
+** some are implemented directly in this module.
+**
+*/
+
+#include "primpl.h"
+#include "windowsx.h"
+
+/*
+** _pr_callback_funcs -- This is where clients register the
+** callback function structure.
+*/
+struct PRMethodCallbackStr * _pr_callback_funcs;
+
+/*
+** PR_MDInitWin16() -- Register the PRMethodCallback table pointer
+**
+*/
+void PR_MDRegisterCallbacks(struct PRMethodCallbackStr *f)
+{
+ _pr_callback_funcs = f;
+}
+
+/*
+** NSPR re-implenentations of various C runtime functions:
+*/
+
+/*
+** PR_MD_printf() -- exported as printf()
+**
+*/
+int PR_MD_printf(const char *fmt, ...)
+{
+ char buffer[1024];
+ int ret = 0;
+ va_list args;
+
+ va_start(args, fmt);
+
+#ifdef DEBUG
+ PR_vsnprintf(buffer, sizeof(buffer), fmt, args);
+ {
+ if (_pr_callback_funcs != NULL && _pr_callback_funcs->auxOutput != NULL) {
+ (* _pr_callback_funcs->auxOutput)(buffer);
+ } else {
+ OutputDebugString(buffer);
+ }
+ }
+#endif
+
+ va_end(args);
+ return ret;
+}
+
+/*
+** PR_MD_sscanf() -- exported as sscanf()
+**
+*/
+int PR_MD_sscanf(const char *buf, const char *fmt, ...)
+{
+ int retval;
+ va_list arglist;
+
+ va_start(arglist, fmt);
+ retval = vsscanf((const unsigned char *)buf, (const unsigned char *)fmt, arglist);
+ va_end(arglist);
+ return retval;
+}
+
+/*
+** PR_MD_strftime() -- exported as strftime
+**
+*/
+size_t PR_MD_strftime(char *s, size_t len, const char *fmt, const struct tm *p)
+{
+ if( _pr_callback_funcs ) {
+ return (*_pr_callback_funcs->strftime)(s, len, fmt, p);
+ } else {
+ PR_ASSERT(0);
+ return 0;
+ }
+}
+
+
+/*
+** PR_MD_malloc() -- exported as malloc()
+**
+*/
+void *PR_MD_malloc( size_t size )
+{
+ if( _pr_callback_funcs ) {
+ return (*_pr_callback_funcs->malloc)( size );
+ } else {
+ return GlobalAllocPtr(GPTR, (DWORD)size);
+ }
+} /* end malloc() */
+
+/*
+** PR_MD_calloc() -- exported as calloc()
+**
+*/
+void *PR_MD_calloc( size_t n, size_t size )
+{
+ void *p;
+ size_t sz;
+
+ if( _pr_callback_funcs ) {
+ return (*_pr_callback_funcs->calloc)( n, size );
+ } else {
+ sz = n * size;
+ p = GlobalAllocPtr(GPTR, (DWORD)sz );
+ memset( p, 0x00, sz );
+ return p;
+ }
+} /* end calloc() */
+
+/*
+** PR_MD_realloc() -- exported as realloc()
+**
+*/
+void *PR_MD_realloc( void* old_blk, size_t size )
+{
+ if( _pr_callback_funcs ) {
+ return (*_pr_callback_funcs->realloc)( old_blk, size );
+ } else {
+ return GlobalReAllocPtr( old_blk, (DWORD)size, GPTR);
+ }
+} /* end realloc */
+
+/*
+** PR_MD_free() -- exported as free()
+**
+*/
+void PR_MD_free( void *ptr )
+{
+ if( _pr_callback_funcs ) {
+ (*_pr_callback_funcs->free)( ptr );
+ return;
+ } else {
+ GlobalFreePtr( ptr );
+ return;
+ }
+} /* end free() */
+
+/*
+** PR_MD_getenv() -- exported as getenv()
+**
+*/
+char *PR_MD_getenv( const char *name )
+{
+ if( _pr_callback_funcs ) {
+ return (*_pr_callback_funcs->getenv)( name );
+ } else {
+ return 0;
+ }
+} /* end getenv() */
+
+
+/*
+** PR_MD_perror() -- exported as perror()
+**
+** well, not really (lth. 12/5/97).
+** XXX hold this thought.
+**
+*/
+void PR_MD_perror( const char *prefix )
+{
+ return;
+} /* end perror() */
+
+/*
+** PR_MD_putenv() -- exported as putenv()
+**
+*/
+int PR_MD_putenv(const char *assoc)
+{
+ if( _pr_callback_funcs ) {
+ return (*_pr_callback_funcs->putenv)(assoc);
+ } else {
+ PR_ASSERT(0);
+ return NULL;
+ }
+}
+
+/*
+** PR_MD_fprintf() -- exported as fprintf()
+**
+*/
+int PR_MD_fprintf(FILE *fPtr, const char *fmt, ...)
+{
+ char buffer[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ PR_vsnprintf(buffer, sizeof(buffer), fmt, args);
+
+ if (fPtr == NULL)
+ {
+ if (_pr_callback_funcs != NULL && _pr_callback_funcs->auxOutput != NULL)
+ {
+ (* _pr_callback_funcs->auxOutput)(buffer);
+ }
+ else
+ {
+ OutputDebugString(buffer);
+ }
+ }
+ else
+ {
+ fwrite(buffer, 1, strlen(buffer), fPtr); /* XXX Is this a sec. hole? */
+ }
+
+ va_end(args);
+ return 0;
+}
+
+/* end w16callb.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16error.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16error.c
new file mode 100644
index 00000000..72d1725b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16error.c
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Note: A single error mapping function is provided.
+**
+*/
+#include "prerror.h"
+#include <errno.h>
+#include <winsock.h>
+
+
+void _PR_MD_map_error( int err )
+{
+
+ switch ( err )
+ {
+ case ENOENT: /* No such file or directory */
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case E2BIG: /* Argument list too big */
+ PR_SetError( PR_INVALID_ARGUMENT_ERROR, err );
+ break;
+ case ENOEXEC: /* Exec format error */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EBADF: /* Bad file number */
+ PR_SetError( PR_BAD_DESCRIPTOR_ERROR, err );
+ break;
+ case ENOMEM: /* Not enough Memory */
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, err );
+ break;
+ case EACCES: /* Permission denied */
+ PR_SetError( PR_NO_ACCESS_RIGHTS_ERROR, err );
+ break;
+ case EEXIST: /* File exists */
+
+ /* RESTART here */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EXDEV: /* Cross device link */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EINVAL: /* Invalid argument */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENFILE: /* File table overflow */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EMFILE: /* Too many open files */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOSPC: /* No space left on device */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ /* math errors */
+ case EDOM: /* Argument too large */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ERANGE: /* Result too large */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ /* file locking error */
+ case EDEADLK: /* Resource deadlock would occur */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EINTR: /* Interrupt */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ECHILD: /* Child does not exist */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ /* POSIX errors */
+ case EAGAIN: /* Resource unavailable, try again */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EBUSY: /* Device or Resource is busy */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EFBIG: /* File too large */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EIO: /* I/O error */
+ PR_SetError( PR_IO_ERROR, err );
+ break;
+ case EISDIR: /* Is a directory */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOTDIR: /* Not a directory */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EMLINK: /* Too many links */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOTBLK: /* Block device required */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOTTY: /* Not a character device */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENXIO: /* No such device or address */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EPERM: /* Not owner */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EPIPE: /* Broken pipe */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EROFS: /* Read only file system */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ESPIPE: /* Illegal seek */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ESRCH: /* No such process */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ETXTBSY: /* Text file busy */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case EFAULT: /* Bad address */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENAMETOOLONG: /* Name too long */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENODEV: /* No such device */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOLCK: /* No locks available on system */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOSYS: /* Unknown system call */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ case ENOTEMPTY: /* Directory not empty */
+ /* Normative Addendum error */
+ case EILSEQ: /* Multibyte/widw character encoding error */
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+
+ /* WinSock errors */
+ case WSAEACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case WSAEADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case WSAEADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case WSAEAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAEBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case WSAECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case WSAEFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case WSAEINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case WSAEISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case WSAEMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case WSAENETDOWN:
+ case WSAENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case WSAENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case WSAENOPROTOOPT:
+ case WSAEMSGSIZE:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case WSAENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ case WSAENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+ case WSAEOPNOTSUPP:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+ case WSAEPROTONOSUPPORT:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, err);
+ break;
+ case WSAEINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err );
+ break;
+ case WSASYSNOTREADY:
+ case WSAVERNOTSUPPORTED:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case WSAEWOULDBLOCK:
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+
+ default:
+ PR_SetError( PR_UNKNOWN_ERROR, err );
+ break;
+ }
+ return;
+} /* end _MD_map_win16_error() */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16fmem.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16fmem.c
new file mode 100644
index 00000000..55df5128
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16fmem.c
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/*
+ **********************************************************************
+ *
+ * Memory-mapped files are not implemented on Win16.
+ *
+ **********************************************************************
+ */
+
+PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRInt32 _MD_GetMemMapAlignment(void)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+}
+
+void * _MD_MemMap(
+ PRFileMap *fmap,
+ PRInt64 offset,
+ PRUint32 len)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _MD_CloseFileMap(PRFileMap *fmap)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16gc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16gc.c
new file mode 100644
index 00000000..cd3a6528
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16gc.c
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <sys/timeb.h>
+
+PRWord *
+_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ if (isCurrent)
+ {
+ _MD_SAVE_CONTEXT(t);
+ }
+ /*
+ ** In Win16 because the premption is "cooperative" it can never be the
+ ** case that a register holds the sole reference to an object. It
+ ** will always have been pushed onto the stack before the thread
+ ** switch... So don't bother to scan the registers...
+ */
+ *np = 0;
+
+ return (PRWord *) CONTEXT(t);
+}
+
+#if 0
+#ifndef SPORT_MODEL
+
+#define MAX_SEGMENT_SIZE (65536l - 4096l)
+
+/************************************************************************/
+/*
+** Machine dependent GC Heap management routines:
+** _MD_GrowGCHeap
+*/
+/************************************************************************/
+
+extern void *
+_MD_GrowGCHeap(uint32 *sizep)
+{
+ void *addr;
+
+ if( *sizep > MAX_SEGMENT_SIZE ) {
+ *sizep = MAX_SEGMENT_SIZE;
+ }
+
+ addr = malloc((size_t)*sizep);
+ return addr;
+}
+
+#endif /* SPORT_MODEL */
+#endif /* 0 */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16io.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16io.c
new file mode 100644
index 00000000..6089d399
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16io.c
@@ -0,0 +1,855 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <share.h>
+#include <sys/locking.h>
+
+
+/*
+** Sleep this many milliseconds on each I/O operation
+** to cause an intentional thread switch.
+*/
+#define _PR_MD_WIN16_DELAY 1
+
+
+/*
+** PR_MD_RegisterW16StdioCallbacks() -- Register Win16 stdio callback functions
+**
+** This public function call is unique to Win16.
+** ... Sigh ... So much for platform independence.
+**
+** To get stdio to work from a command line executable, the stdio stream
+** calls must be issued from the .EXE file; calling them from the .DLL
+** sends the output to the bit-bucket. Therefore, the .EXE wanting to
+** do stdio to the console window (must be built as a "quickwin" application)
+** must have the wrapper functions defined in this module statically linked
+** into the .EXE.
+**
+** There appears to be nothing you can do to get stdio to work from a
+** Win16 GUI application. Oh Well!
+**
+*/
+PRStdinRead _pr_md_read_stdin = 0;
+PRStdoutWrite _pr_md_write_stdout = 0;
+PRStderrWrite _pr_md_write_stderr = 0;
+
+PRStatus
+PR_MD_RegisterW16StdioCallbacks( PRStdinRead inReadf, PRStdoutWrite outWritef, PRStderrWrite errWritef )
+{
+ _pr_md_write_stdout = outWritef;
+ _pr_md_write_stderr = errWritef;
+ _pr_md_read_stdin = inReadf;
+
+ return(PR_SUCCESS);
+} /* end PR_MD_RegisterW16StdioCallbacks() */
+
+
+/*
+** _PR_MD_OPEN() -- Open a file
+**
+** Returns: a fileHandle or -1
+**
+**
+*/
+PRInt32
+_PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
+{
+ PRInt32 file;
+ int access = O_BINARY;
+ int rights = 0;
+
+
+ /*
+ ** Map NSPR open flags to os open flags
+ */
+ if (osflags & PR_RDONLY )
+ access |= O_RDONLY;
+ if (osflags & PR_WRONLY )
+ access |= O_WRONLY;
+ if (osflags & PR_RDWR )
+ access |= O_RDWR;
+ if (osflags & PR_CREATE_FILE )
+ {
+ access |= O_CREAT;
+ rights |= S_IRWXU;
+ }
+ if (osflags & PR_TRUNCATE)
+ access |= O_TRUNC;
+ if (osflags & PR_APPEND)
+ access |= O_APPEND;
+ else
+ access |= O_RDONLY;
+
+ /*
+ ** Open the file
+ */
+ file = (PRInt32) sopen( name, access, SH_DENYNO, rights );
+ if ( -1 == (PRInt32)file )
+ {
+ _PR_MD_MAP_OPEN_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return file;
+}
+
+/*
+** _PR_MD_READ() - Read something
+**
+** Returns: bytes read or -1
+**
+*/
+PRInt32
+_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
+{
+ PRInt32 rv;
+
+ if ( (PR_GetDescType(fd) == PR_DESC_FILE) &&
+ ( fd->secret->md.osfd == PR_StandardInput ) &&
+ ( _pr_md_write_stdout ))
+ {
+ rv = (*_pr_md_read_stdin)( buf, len);
+ }
+ else
+ {
+ rv = read( fd->secret->md.osfd, buf, len );
+ }
+
+ if ( rv == -1)
+ {
+ _PR_MD_MAP_READ_ERROR( errno );
+ }
+
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return rv;
+}
+
+/*
+** _PR_MD_WRITE() - Write something
+**
+** Returns: bytes written or -1
+**
+** Note: for file handles 1 and 2 (stdout and stderr)
+** call the Win16 NSPR stdio callback functions, if they are
+** registered.
+**
+*/
+PRInt32
+_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
+{
+ PRInt32 rv;
+
+ if ( (PR_GetDescType(fd) == PR_DESC_FILE))
+ {
+ switch ( fd->secret->md.osfd )
+ {
+ case PR_StandardOutput :
+ if ( _pr_md_write_stdout )
+ rv = (*_pr_md_write_stdout)( (void *)buf, len);
+ else
+ rv = len; /* fake success */
+ break;
+
+ case PR_StandardError :
+ if ( _pr_md_write_stderr )
+ rv = (*_pr_md_write_stderr)( (void *)buf, len);
+ else
+ rv = len; /* fake success */
+ break;
+
+ default:
+ rv = write( fd->secret->md.osfd, buf, len );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_WRITE_ERROR( errno );
+ }
+ break;
+ }
+ }
+ else
+ {
+ rv = write( fd->secret->md.osfd, buf, len );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_WRITE_ERROR( errno );
+ }
+ }
+
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return rv;
+} /* --- end _PR_MD_WRITE() --- */
+
+/*
+** _PR_MD_LSEEK() - Seek to position in a file
+**
+** Note: 'whence' maps directly to PR_...
+**
+** Returns:
+**
+*/
+PRInt32
+_PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, int whence)
+{
+ PRInt32 rv;
+
+ rv = lseek( fd->secret->md.osfd, offset, whence );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return( rv );
+}
+
+/*
+** _PR_MD_LSEEK64() -- Seek to position in file, 64bit offset.
+**
+*/
+PRInt64
+_PR_MD_LSEEK64( PRFileDesc *fd, PRInt64 offset, int whence )
+{
+ PRInt64 test;
+ PRInt32 rv, off;
+ LL_SHR(test, offset, 32);
+ if (!LL_IS_ZERO(test))
+ {
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
+ LL_I2L(test, -1);
+ return test;
+ }
+ LL_L2I(off, offset);
+ rv = _PR_MD_LSEEK(fd, off, whence);
+ LL_I2L(test, rv);
+ return test;
+} /* end _PR_MD_LSEEK64() */
+
+/*
+** _PR_MD_FSYNC() - Flush file buffers.
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_FSYNC(PRFileDesc *fd)
+{
+ PRInt32 rv;
+
+ rv = (PRInt32) fsync( fd->secret->md.osfd );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_FSYNC_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return(rv);
+}
+
+/*
+** _PR_MD_CLOSE() - Close an open file handle
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_CLOSE_FILE(PRInt32 osfd)
+{
+ PRInt32 rv;
+
+ rv = (PRInt32) close( osfd );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_CLOSE_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return(rv);
+} /* --- end _MD_CloseFile() --- */
+
+
+/* --- DIR IO ------------------------------------------------------------ */
+#define GetFileFromDIR(d) (d)->d_entry.cFileName
+
+/*
+** FlipSlashes() - Make forward slashes ('/') into backslashes
+**
+** Returns: void
+**
+**
+*/
+void FlipSlashes(char *cp, int len)
+{
+ while (--len >= 0) {
+ if (cp[0] == '/') {
+ cp[0] = PR_DIRECTORY_SEPARATOR;
+ }
+ cp++;
+ }
+}
+
+
+/*
+** _PR_MD_OPEN_DIR() - Open a Directory.
+**
+** Returns:
+**
+**
+*/
+PRStatus
+_PR_MD_OPEN_DIR(_MDDir *d, const char *name)
+{
+ d->dir = opendir( name );
+
+ if ( d->dir == NULL )
+ {
+ _PR_MD_MAP_OPENDIR_ERROR( errno );
+ return( PR_FAILURE );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return( PR_SUCCESS );
+}
+
+
+/*
+** _PR_MD_READ_DIR() - read next directory entry
+**
+**
+*/
+char *
+_PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
+{
+ struct dirent *de;
+ int err;
+
+ for (;;)
+ {
+ de = readdir( d->dir );
+ if ( de == NULL ) {
+ _PR_MD_MAP_READDIR_ERROR( errno);
+ return 0;
+ }
+ if ((flags & PR_SKIP_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == 0))
+ continue;
+ if ((flags & PR_SKIP_DOT_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
+ (de->d_name[2] == 0))
+ continue;
+ break;
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return de->d_name;
+}
+
+/*
+** _PR_MD_CLOSE_DIR() - Close a directory.
+**
+**
+*/
+PRInt32
+_PR_MD_CLOSE_DIR(_MDDir *d)
+{
+ PRInt32 rv;
+
+ if ( d->dir )
+ {
+ rv = closedir( d->dir );
+ if (rv != 0)
+ {
+ _PR_MD_MAP_CLOSEDIR_ERROR( errno );
+ }
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return rv;
+}
+
+
+/*
+** _PR_MD_DELETE() - Delete a file.
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_DELETE(const char *name)
+{
+ PRInt32 rv;
+
+ rv = (PRInt32) remove( name );
+ if ( rv != 0 )
+ {
+ _PR_MD_MAP_DELETE_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return(rv);
+}
+
+
+/*
+** _PR_MD_STAT() - Get file attributes by filename
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_STAT(const char *fn, struct stat *info)
+{
+ PRInt32 rv;
+
+ rv = _stat(fn, (struct _stat *)info);
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_STAT_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return( rv );
+}
+
+/*
+** _PR_MD_GETFILEINFO() - Get file attributes by filename
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
+{
+ struct _stat sb;
+ PRInt32 rv;
+
+ if ( (rv = _stat(fn, &sb)) == 0 ) {
+ if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE ;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ info->size = sb.st_size;
+ LL_I2L(info->modifyTime, sb.st_mtime);
+ LL_I2L(info->creationTime, sb.st_ctime);
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_STAT_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
+{
+ PRFileInfo info32;
+
+ PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
+ if (0 == rv)
+ {
+ info->type = info32.type;
+ info->modifyTime = info32.modifyTime;
+ info->creationTime = info32.creationTime;
+ LL_I2L(info->size, info32.size);
+ }
+ return(rv);
+}
+
+/*
+** _PR_MD_GETOPENFILEINFO() - Get file attributes from an open file handle
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
+{
+ struct stat statBuf;
+ PRInt32 rv = PR_SUCCESS;
+
+ rv = fstat( fd->secret->md.osfd, &statBuf );
+ if ( rv == 0)
+ {
+ if (statBuf.st_mode & S_IFREG )
+ info->type = PR_FILE_FILE;
+ else if ( statBuf.st_mode & S_IFDIR )
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ info->size = statBuf.st_size;
+ LL_I2L(info->modifyTime, statBuf.st_mtime);
+ LL_I2L(info->creationTime, statBuf.st_ctime);
+
+ }
+ else
+ {
+ _PR_MD_MAP_FSTAT_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return(rv);
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ PRFileInfo info32;
+
+ PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
+ if (0 == rv)
+ {
+ info->type = info32.type;
+ info->modifyTime = info32.modifyTime;
+ info->creationTime = info32.creationTime;
+ LL_I2L(info->size, info32.size);
+ }
+ return(rv);
+}
+
+/*
+** _PR_MD_RENAME() - Rename a file
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_RENAME(const char *from, const char *to)
+{
+ PRInt32 rv;
+
+ rv = rename( from, to );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_RENAME_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return( rv );
+}
+
+/*
+** _PR_MD_ACCESS() - Return file acesss attribute.
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_ACCESS(const char *name, PRIntn how)
+{
+ PRInt32 rv;
+ int mode = 0;
+
+ if ( how & PR_ACCESS_WRITE_OK )
+ mode |= W_OK;
+ if ( how & PR_ACCESS_READ_OK )
+ mode |= R_OK;
+
+ rv = (PRInt32) access( name, mode );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_ACCESS_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return(rv);
+}
+
+/*
+** _PR_MD_MKDIR() - Make a directory
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_MKDIR(const char *name, PRIntn mode)
+{
+ PRInt32 rv;
+
+ rv = mkdir( name );
+ if ( rv == 0 )
+ {
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return PR_SUCCESS;
+ }
+ else
+ {
+ _PR_MD_MAP_MKDIR_ERROR( errno );
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return PR_FAILURE;
+ }
+}
+
+/*
+** _PR_MD_RMDIR() - Delete a directory
+**
+** Returns:
+**
+**
+*/
+PRInt32
+_PR_MD_RMDIR(const char *name)
+{
+ PRInt32 rv;
+
+ rv = (PRInt32) rmdir( name );
+ if ( rv == -1 )
+ {
+ _PR_MD_MAP_RMDIR_ERROR( errno );
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return(rv);
+}
+
+/*
+** _PR_MD_LOCKFILE() - Lock a file.
+**
+** The _locking() call locks relative to the current file pointer.
+** This function is required to lock all of the file, so,
+** 1. Seek to the beginning of the file, preserving the original position.
+** 2. Lock the file, pausing if it is locked by someone else, and
+** try again.
+** 3. Re-position to the original position in the file.
+**
+** For unlocking, a similar protocol of positioning is required.
+**
+*/
+PRStatus
+_PR_MD_LOCKFILE(PRInt32 f)
+{
+ PRInt32 rv = PR_SUCCESS; /* What we return to our caller */
+ long seekOrigin; /* original position in file */
+ PRInt32 rc; /* what the system call returns to us */
+
+ /*
+ ** Seek to beginning of file, saving original position.
+ */
+ seekOrigin = lseek( f, 0l, SEEK_SET );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+ return( PR_FAILURE );
+ }
+
+ /*
+ ** Attempt to lock the file.
+ ** If someone else has it, Sleep-a-while and try again.
+ */
+ for( rc = -1; rc != 0; )
+ {
+ rc = _locking( f, _LK_NBLCK , 0x7fffffff );
+ if ( rc == -1 )
+ {
+ if ( errno == EACCES )
+ {
+ PR_Sleep( 100 );
+ continue;
+ }
+ else
+ {
+ _PR_MD_MAP_LOCKF_ERROR( errno );
+ rv = PR_FAILURE;
+ break;
+ }
+ }
+ } /* end for() */
+
+ /*
+ ** Now that the file is locked, re-position to
+ ** the original file position.
+ **
+ */
+ rc = lseek( f, seekOrigin, SEEK_SET );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+ rv = PR_FAILURE;
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return PR_SUCCESS;
+} /* end _PR_MD_LOCKFILE() */
+
+/*
+** _PR_MD_TLOCKFILE() - Test and Lock file.
+**
+** The _locking() call locks relative to the current file pointer.
+** This function is required to lock all of the file, so,
+** 1. Seek to the beginning of the file, preserving the original position.
+** 2. Attempt to Lock the file.
+** If the file is locked by someone else, try NO MORE.
+** 3. Re-position to the original position in the file.
+**
+** See the discussion of _PR_MD_LOCKFILE
+**
+**
+*/
+PRStatus
+_PR_MD_TLOCKFILE(PRInt32 f)
+{
+ PRInt32 rv = PR_SUCCESS; /* What we return */
+ long seekOrigin; /* original position in file */
+ PRInt32 rc; /* return value from system call */
+
+ /*
+ ** Seek to beginning of file, saving original position.
+ */
+ seekOrigin = lseek( f, 0l, SEEK_SET );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+ return( PR_FAILURE );
+ }
+
+ /*
+ ** Attempt to lock the file. One ping; one ping only, Vasily.
+ ** If someone else has it, Reposition and return failure.
+ */
+ rc = _locking( f, _LK_NBLCK , 0x7fffffff );
+ if ( rc == -1 )
+ {
+ if ( errno != EACCES )
+ _PR_MD_MAP_LOCKF_ERROR( errno );
+ rv = PR_FAILURE;
+ }
+
+ /*
+ ** Now that the file is locked, maybe, re-position to
+ ** the original file position.
+ */
+ rc = lseek( f, seekOrigin, SEEK_SET );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+ rv = PR_FAILURE;
+ }
+
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return rv;
+} /* end _PR_MD_TLOCKFILE() */
+
+
+/*
+** _PR_MD_UNLOCKFILE() - Unlock a file.
+**
+** See the discussion of _PR_MD_LOCKFILE
+**
+*/
+PRStatus
+_PR_MD_UNLOCKFILE(PRInt32 f)
+{
+ PRInt32 rv = PR_SUCCESS; /* What we return */
+ long seekOrigin; /* original position in file */
+ PRInt32 rc; /* return value from system call */
+
+ /*
+ ** Seek to beginning of file, saving original position.
+ */
+ seekOrigin = lseek( f, 0l, SEEK_SET );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+ return( PR_FAILURE );
+ }
+
+ /*
+ ** Unlock the file.
+ */
+ rc = _locking( f, _LK_UNLCK , 0x7fffffff );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LOCKF_ERROR( errno );
+ rv = PR_FAILURE;
+ }
+
+ /*
+ ** Now that the file is unlocked, re-position to
+ ** the original file position.
+ */
+ rc = lseek( f, seekOrigin, SEEK_SET );
+ if ( rc == -1 )
+ {
+ _PR_MD_MAP_LSEEK_ERROR( errno );
+ rv = PR_FAILURE;
+ }
+ PR_Sleep( _PR_MD_WIN16_DELAY );
+ return rv;
+} /* end _PR_MD_UNLOCKFILE() */
+
+/*
+** PR_Stat() -- Return status on a file
+**
+** This is a hack! ... See BugSplat: 98516
+** Basically, this hack takes a name and stat buffer as input.
+** The input stat buffer is presumed to be a Microsoft stat buffer.
+** The functions does a Watcom stat() then maps the result to
+** the MS stat buffer. ...
+**
+*/
+PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
+{
+ PRInt32 rv;
+ _MDMSStat *mssb = (_MDMSStat*) buf; /* this is Microsoft's stat buffer */
+ struct stat statBuf; /* this is Watcom's stat buffer */
+
+ /* First, get Watcom's idea of stat
+ ** then reformat it into a Microsoft idea of stat
+ */
+ rv = (PRInt32) _stat( name, &statBuf);
+ if (rv == 0l )
+ {
+ mssb->st_dev = statBuf.st_dev;
+ mssb->st_ino = statBuf.st_ino; /* not used, really */
+ mssb->st_mode = statBuf.st_mode;
+ mssb->st_nlink = 1; /* always 1, says MS */
+ mssb->st_uid = statBuf.st_uid;
+ mssb->st_gid = statBuf.st_gid;
+ mssb->st_rdev = statBuf.st_rdev; /* please Gh0d! Let these be the same */
+ mssb->st_size = statBuf.st_size;
+ mssb->st_atime = statBuf.st_atime;
+ mssb->st_mtime = statBuf.st_mtime;
+ mssb->st_ctime = statBuf.st_ctime;
+ }
+ return rv;
+} /* end PR_Stat() */
+
+
+
+/* $$ end W16io.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16mem.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16mem.c
new file mode 100644
index 00000000..1c07099d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16mem.c
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*******************************************************************
+** w16mem.c -- Implement memory segment functions.
+**
+**
+********************************************************************
+*/
+#include "primpl.h"
+
+
+/*
+** Allocate a new memory segment.
+**
+** Return the segment's access rights and size.
+*/
+PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr)
+{
+ PR_ASSERT(seg != 0);
+ PR_ASSERT(size != 0);
+ PR_ASSERT(vaddr == 0);
+
+ /*
+ ** Take the actual memory for the segment out of our Figment heap.
+ */
+
+ seg->vaddr = (char *)malloc(size);
+
+ if (seg->vaddr == NULL) {
+ return PR_FAILURE;
+ }
+
+ seg->size = size;
+
+ return PR_SUCCESS;
+} /* --- end _MD_AllocSegment() --- */
+
+
+/*
+** Free previously allocated memory segment.
+*/
+void _MD_FreeSegment(PRSegment *seg)
+{
+ PR_ASSERT((seg->flags & _PR_SEG_VM) == 0);
+
+ if (seg->vaddr != NULL)
+ free( seg->vaddr );
+ return;
+} /* --- end _MD_FreeSegment() --- */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16null.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16null.c
new file mode 100644
index 00000000..7f4c5fc1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16null.c
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <sys/timeb.h>
+
+
+struct _MDLock _pr_ioq_lock;
+HINSTANCE _pr_hInstance = NULL;
+char * _pr_top_of_task_stack;
+_PRInterruptTable _pr_interruptTable[] = { { 0 } };
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the
+ * implementation for Windows.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#if defined(HAVE_WATCOM_BUG_2)
+PRTime __pascal __export __loadds
+#else
+PR_IMPLEMENT(PRTime)
+#endif
+PR_Now(void)
+{
+ PRInt64 s, ms, ms2us, s2us;
+ struct timeb b;
+
+ ftime(&b);
+ LL_I2L(ms2us, PR_USEC_PER_MSEC);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, b.time);
+ LL_I2L(ms, (PRInt32)b.millitm);
+ LL_MUL(ms, ms, ms2us);
+ LL_MUL(s, s, s2us);
+ LL_ADD(s, s, ms);
+ return s;
+}
+
+
+
+char *_PR_MD_GET_ENV(const char *name)
+{
+ return NULL;
+}
+
+PRIntn
+_PR_MD_PUT_ENV(const char *name)
+{
+ return NULL;
+}
+
+int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
+ WORD cbHeapSize, LPSTR lpszCmdLine )
+{
+ _pr_hInstance = hInst;
+ return TRUE;
+}
+
+
+
+void
+_PR_MD_EARLY_INIT()
+{
+ _tzset();
+ return;
+}
+
+void
+_PR_MD_WAKEUP_CPUS( void )
+{
+ return;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16proc.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16proc.c
new file mode 100644
index 00000000..f1a9eab8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16proc.c
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <sys/timeb.h>
+
+
+/*
+** Create Process.
+*/
+PRProcess * _PR_CreateWindowsProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PRStatus _PR_DetachWindowsProcess(PRProcess *process)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _PR_WaitWindowsProcess(PRProcess *process,
+ PRInt32 *exitCode)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _PR_KillWindowsProcess(PRProcess *process)
+{
+ PR_ASSERT(!"Not implemented");
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16sock.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16sock.c
new file mode 100644
index 00000000..78e95906
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16sock.c
@@ -0,0 +1,1170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+static int winsockNotPresent = 0;
+
+void
+_PR_MD_INIT_IO()
+{
+ int rv;
+
+ WORD WSAVersion = 0x0101;
+ WSADATA WSAData;
+
+ rv = WSAStartup( WSAVersion, &WSAData );
+ if ( rv != 0 )
+ {
+ _PR_MD_MAP_WSASTARTUP_ERROR(WSAGetLastError());
+ winsockNotPresent = 1;
+ }
+ return;
+}
+
+void
+_PR_MD_CLEANUP_BEFORE_EXIT(void)
+{
+ int rv;
+ int err;
+
+ rv = WSACleanup();
+ if ( rv == SOCKET_ERROR )
+ {
+ err = WSAGetLastError();
+ PR_ASSERT(0);
+ }
+ return;
+} /* end _PR_MD_CLEANUP_BEFORE_EXIT() */
+
+/* --- SOCKET IO --------------------------------------------------------- */
+
+PRStatus
+_MD_WindowsGetHostName(char *name, PRUint32 namelen)
+{
+ PRIntn rv;
+ PRInt32 syserror;
+
+ rv = gethostname(name, (PRInt32) namelen);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ }
+ syserror = WSAGetLastError();
+ PR_ASSERT(WSANOTINITIALISED != syserror);
+ _PR_MD_MAP_GETHOSTNAME_ERROR(syserror);
+ return PR_FAILURE;
+}
+
+
+PRInt32
+_PR_MD_SOCKET(int af, int type, int flags)
+{
+ SOCKET sock;
+ PRUint32 one = 1;
+ PRInt32 rv;
+ PRInt32 err;
+
+ if ( winsockNotPresent )
+ return( (PRInt32)INVALID_SOCKET );
+
+ sock = socket(af, type, flags);
+
+ if (sock == INVALID_SOCKET )
+ {
+ int rv = GetLastError();
+ closesocket(sock);
+ _PR_MD_MAP_SOCKET_ERROR(rv);
+ return (PRInt32)INVALID_SOCKET;
+ }
+
+ /*
+ ** Make the socket Non-Blocking
+ */
+ rv = ioctlsocket( sock, FIONBIO, &one);
+ if ( rv != 0 )
+ {
+ err = WSAGetLastError();
+ return -1;
+ }
+
+ return (PRInt32)sock;
+}
+
+
+PRInt32
+_PR_MD_SOCKETAVAILABLE(PRFileDesc *fd)
+{
+ PRUint32 result;
+
+ if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
+ return -1;
+ }
+ return result;
+}
+
+
+/*
+** _MD_CloseSocket() -- Close a socket
+**
+*/
+PRInt32
+_PR_MD_CLOSE_SOCKET(PRInt32 osfd)
+{
+ PRInt32 rv;
+
+ rv = closesocket((SOCKET) osfd );
+ if (rv < 0)
+ _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
+
+ return rv;
+}
+
+PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
+{
+ int rv, err;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+ if ( rv == SOCKET_ERROR ) {
+ _PR_MD_MAP_LISTEN_ERROR(WSAGetLastError());
+ return(-1);
+ }
+ return(rv);
+}
+
+PRInt32
+_PR_MD_ACCEPT(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout )
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 err;
+ PRIntn rv;
+
+ MD_ASSERTINT( *addrlen );
+
+ while ((rv = (SOCKET)accept(osfd, (struct sockaddr *) addr,
+ (int *)addrlen)) == INVALID_SOCKET ) {
+ err = WSAGetLastError();
+ if ( err == WSAEWOULDBLOCK ) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
+ if ( _PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ } else
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ rv = -1;
+ goto done;
+ } else if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+done:
+ if ( rv == INVALID_SOCKET )
+ return(-1 );
+ else
+ return(rv);
+} /* end _MD_Accept() */
+
+
+PRInt32
+_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 rv, err;
+
+ while ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
+ err = WSAGetLastError();
+ if (err == WSAEISCONN) {
+ rv = 0;
+ break;
+ }
+ /* for winsock1.1, it reports EALREADY as EINVAL */
+ if ((err == WSAEWOULDBLOCK)
+ ||(err == WSAEALREADY)
+ || (err = WSAEINVAL)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
+ if ( _PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ } else
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ rv = -1;
+ goto done;
+ } else if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+done:
+ return rv;
+}
+
+PRInt32
+_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv;
+ int one = 1;
+
+ rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
+
+ if (rv == SOCKET_ERROR) {
+ _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
+
+
+PRInt32
+_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 rv, err;
+
+ while ((rv = recv(osfd,buf,amount,flags)) == -1) {
+ err = WSAGetLastError();
+ if ( err == WSAEWOULDBLOCK ) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
+ if ( _PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ } else
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ rv = -1;
+ goto done;
+ } else if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32
+_PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 rv, err;
+
+ while ((rv = send(osfd,buf,amount,flags)) == -1) {
+ err = WSAGetLastError();
+ if ( err == WSAEWOULDBLOCK ) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
+ if ( _PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ } else
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ rv = -1;
+ goto done;
+ } else if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+done:
+ return rv;
+}
+
+PRInt32
+_PR_MD_SENDTO(PRFileDesc*fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 rv, err;
+
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1) {
+ err = WSAGetLastError();
+ if ( err == WSAEWOULDBLOCK ) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (_PR_WaitForFD(osfd, PR_POLL_WRITE, timeout) == 0) {
+ if ( _PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ } else
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ rv = -1;
+ goto done;
+ } else if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+done:
+ return rv;
+}
+
+PRInt32
+_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRInt32 rv, err;
+
+ while ((*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr FAR *) addr,(int FAR *)addrlen)) == -1)) {
+ err = WSAGetLastError();
+ if ( err == WSAEWOULDBLOCK ) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if (_PR_WaitForFD(osfd, PR_POLL_READ, timeout) == 0) {
+ if ( _PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ } else
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ }
+ rv = -1;
+ goto done;
+ } else if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ } else if ((err == WSAEINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+done:
+ return(rv);
+}
+
+PRInt32
+_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
+{
+ int index;
+ int sent = 0;
+ int rv;
+
+ for (index=0; index < iov_size; index++)
+ {
+
+/*
+ * XXX To be fixed
+ * should call PR_Send
+ */
+
+ rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
+ if (rv > 0)
+ sent += rv;
+ if ( rv != iov[index].iov_len )
+ {
+ if (sent <= 0)
+ return -1;
+ return -1;
+ }
+ }
+ return sent;
+}
+
+PRInt32
+_PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
+{
+PRInt32 rv;
+
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0)
+ _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
+ return rv;
+}
+
+PRStatus
+_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+{
+ PRInt32 rv;
+
+ rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, (int *)len);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+{
+ PRInt32 rv;
+
+ rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, (int*)len);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ PRInt32 rv;
+
+ rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, (int*)optlen);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv;
+
+ rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv==0)
+ return PR_SUCCESS;
+ else {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+void
+_PR_MD_MAKE_NONBLOCK(PRFileDesc *f)
+{
+ return; // do nothing!
+}
+
+/*
+** Wait for I/O on a single descriptor.
+ *
+ * return 0, if timed-out, else return 1
+*/
+PRInt32
+_PR_WaitForFD(PRInt32 osfd, PRUintn how, PRIntervalTime timeout)
+{
+ _PRWin16PollDesc *pd;
+ PRPollQueue *pq;
+ PRIntn is;
+ PRInt32 rv = 1;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
+
+ pd = &me->md.thr_pd;
+ pq = &me->md.thr_pq;
+ if (timeout == PR_INTERVAL_NO_WAIT) return 0;
+
+ pd->osfd = osfd;
+ pd->in_flags = how;
+ pd->out_flags = 0;
+
+ pq->pds = pd;
+ pq->npds = 1;
+
+ _PR_INTSOFF(is);
+ _PR_MD_IOQ_LOCK();
+ _PR_THREAD_LOCK(me);
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_IOQ_UNLOCK();
+ return 0;
+ }
+
+ pq->thr = me;
+ pq->on_ioq = PR_TRUE;
+ pq->timeout = timeout;
+ _PR_ADD_TO_IOQ((*pq), me->cpu);
+ if (how == PR_POLL_READ) {
+ FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
+ (_PR_FD_READ_CNT(me->cpu))[osfd]++;
+ } else if (how == PR_POLL_WRITE) {
+ FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
+ } else {
+ FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
+ }
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
+ if (_PR_IOQ_TIMEOUT(me->cpu) > timeout)
+ _PR_IOQ_TIMEOUT(me->cpu) = timeout;
+
+ _PR_THREAD_LOCK(me);
+
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, timeout);
+ me->state = _PR_IO_WAIT;
+ me->io_pending = PR_TRUE;
+ me->io_suspended = PR_FALSE;
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_IOQ_UNLOCK();
+
+ _PR_MD_WAIT(me, timeout);
+ me->io_pending = PR_FALSE;
+ me->io_suspended = PR_FALSE;
+
+ /*
+ ** If we timed out the pollq might still be on the ioq. Remove it
+ ** before continuing.
+ */
+ if (pq->on_ioq) {
+ _PR_INTSOFF(is);
+ _PR_MD_IOQ_LOCK();
+ /*
+ * Need to check pq.on_ioq again
+ */
+ if (pq->on_ioq) {
+ PR_REMOVE_LINK(&pq->links);
+ if (how == PR_POLL_READ) {
+ if ((--(_PR_FD_READ_CNT(me->cpu))[osfd]) == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+
+ } else if (how == PR_POLL_WRITE) {
+ if ((--(_PR_FD_WRITE_CNT(me->cpu))[osfd]) == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ } else {
+ if ((--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]) == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+ _PR_MD_IOQ_UNLOCK();
+ rv = 0;
+ }
+ _PR_FAST_INTSON(is);
+ return(rv);
+}
+
+/*
+ * Unblock threads waiting for I/O
+ * used when interrupting threads
+ *
+ * NOTE: The thread lock should held when this function is called.
+ * On return, the thread lock is released.
+ */
+void _PR_Unblock_IO_Wait(PRThread *thr)
+{
+ int pri = thr->priority;
+ _PRCPU *cpu = thr->cpu;
+
+ PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ));
+ _PR_SLEEPQ_LOCK(cpu);
+ _PR_DEL_SLEEPQ(thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(cpu);
+
+ PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD));
+ thr->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ _PR_THREAD_UNLOCK(thr);
+ _PR_MD_WAKEUP_WAITER(thr);
+}
+
+/*
+** Scan through io queue and find any bad fd's that triggered the error
+** from _MD_SELECT
+*/
+static void FindBadFDs(void)
+{
+ PRCList *q;
+ PRThread *me = _MD_CURRENT_THREAD();
+ int sockOpt;
+ int sockOptLen = sizeof(sockOpt);
+
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(me));
+ q = (_PR_IOQ(me->cpu)).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRWin16PollDesc *pds = pq->pds;
+ _PRWin16PollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ pds->out_flags = 0;
+ PR_ASSERT(osfd >= 0 || pds->in_flags == 0);
+ if (pds->in_flags == 0) {
+ continue; /* skip this fd */
+ }
+ if ( getsockopt(osfd,
+ (int)SOL_SOCKET,
+ SO_TYPE,
+ (char*)&sockOpt,
+ &sockOptLen) == SOCKET_ERROR )
+ {
+ if ( WSAGetLastError() == WSAENOTSOCK )
+ {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX,
+ ("file descriptor %d is bad", osfd));
+ pds->out_flags = PR_POLL_NVAL;
+ notify = PR_TRUE;
+ }
+ }
+ if (osfd > pq_max_osfd) {
+ pq_max_osfd = osfd;
+ }
+ }
+
+ if (notify) {
+ PRIntn pri;
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
+
+ /*
+ * Decrement the count of descriptors for each desciptor/event
+ * because this I/O request is being removed from the
+ * ioq
+ */
+ pds = pq->pds;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & PR_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & PR_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & PR_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+
+ _PR_THREAD_LOCK(pq->thr);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = pq->thr->cpu;
+
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ }
+ _PR_THREAD_UNLOCK(pq->thr);
+ } else {
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ }
+} /* end FindBadFDs() */
+
+/*
+** Called by the scheduler when there is nothing to do. This means that
+** all threads are blocked on some monitor somewhere.
+**
+** Pause the current CPU. longjmp to the cpu's pause stack
+*/
+PRInt32 _PR_MD_PAUSE_CPU( PRIntervalTime ticks)
+{
+ PRThread *me = _MD_CURRENT_THREAD();
+ struct timeval timeout, *tvp;
+ fd_set r, w, e;
+ fd_set *rp, *wp, *ep;
+ PRInt32 max_osfd, nfd;
+ PRInt32 rv;
+ PRCList *q;
+ PRUint32 min_timeout;
+
+ PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
+
+ /*
+ * assigment of fd_sets
+ */
+ r = _PR_FD_READ_SET(me->cpu);
+ w = _PR_FD_WRITE_SET(me->cpu);
+ e = _PR_FD_EXCEPTION_SET(me->cpu);
+
+ rp = &r;
+ wp = &w;
+ ep = &e;
+
+ max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1;
+ min_timeout = _PR_IOQ_TIMEOUT(me->cpu);
+ /*
+ ** Compute the minimum timeout value: make it the smaller of the
+ ** timeouts specified by the i/o pollers or the timeout of the first
+ ** sleeping thread.
+ */
+ q = _PR_SLEEPQ(me->cpu).next;
+
+ if (q != &_PR_SLEEPQ(me->cpu)) {
+ PRThread *t = _PR_THREAD_PTR(q);
+
+ if (t->sleep < min_timeout) {
+ min_timeout = t->sleep;
+ }
+ }
+ if (min_timeout > ticks) {
+ min_timeout = ticks;
+ }
+
+ if (min_timeout == PR_INTERVAL_NO_TIMEOUT) {
+ tvp = NULL;
+ } else {
+ timeout.tv_sec = PR_IntervalToSeconds(min_timeout);
+ timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout)
+ % PR_USEC_PER_SEC;
+ tvp = &timeout;
+ }
+
+ _PR_MD_IOQ_UNLOCK();
+ _MD_CHECK_FOR_EXIT();
+ /*
+ * check for i/o operations
+ */
+
+ nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp);
+
+ _MD_CHECK_FOR_EXIT();
+ _PR_MD_IOQ_LOCK();
+ /*
+ ** Notify monitors that are associated with the selected descriptors.
+ */
+ if (nfd > 0) {
+ q = _PR_IOQ(me->cpu).next;
+ _PR_IOQ_MAX_OSFD(me->cpu) = -1;
+ _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT;
+ while (q != &_PR_IOQ(me->cpu)) {
+ PRPollQueue *pq = _PR_POLLQUEUE_PTR(q);
+ PRBool notify = PR_FALSE;
+ _PRWin16PollDesc *pds = pq->pds;
+ _PRWin16PollDesc *epds = pds + pq->npds;
+ PRInt32 pq_max_osfd = -1;
+
+ q = q->next;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PRInt16 out_flags = 0;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, rp)) {
+ out_flags |= PR_POLL_READ;
+ }
+ if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, wp)) {
+ out_flags |= PR_POLL_WRITE;
+ }
+ if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, ep)) {
+ out_flags |= PR_POLL_EXCEPT;
+ }
+ pds->out_flags = out_flags;
+ if (out_flags) {
+ notify = PR_TRUE;
+ }
+ if (osfd > pq_max_osfd) {
+ pq_max_osfd = osfd;
+ }
+ }
+ if (notify == PR_TRUE) {
+ PRIntn pri;
+ PRThread *thred;
+
+ PR_REMOVE_LINK(&pq->links);
+ pq->on_ioq = PR_FALSE;
+
+ /*
+ * Decrement the count of descriptors for each desciptor/event
+ * because this I/O request is being removed from the
+ * ioq
+ */
+ pds = pq->pds;
+ for (; pds < epds; pds++) {
+ PRInt32 osfd = pds->osfd;
+ PRInt16 in_flags = pds->in_flags;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & PR_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & PR_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & PR_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+ thred = pq->thr;
+ _PR_THREAD_LOCK(thred);
+ if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ _PRCPU *cpu = thred->cpu;
+ _PR_SLEEPQ_LOCK(pq->thr->cpu);
+ _PR_DEL_SLEEPQ(pq->thr, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(pq->thr->cpu);
+
+ pri = pq->thr->priority;
+ pq->thr->state = _PR_RUNNABLE;
+
+ pq->thr->cpu = cpu;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(pq->thr, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ if (_pr_md_idle_cpus > 1)
+ _PR_MD_WAKEUP_WAITER(thred);
+ }
+ _PR_THREAD_UNLOCK(thred);
+ } else {
+ if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout;
+ if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd)
+ _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd;
+ }
+ }
+ } else if (nfd < 0) {
+ if ( WSAGetLastError() == WSAENOTSOCK )
+ {
+ FindBadFDs();
+ } else {
+ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d",
+ errno));
+ }
+ }
+ _PR_MD_IOQ_UNLOCK();
+ return(0);
+
+} /* end _PR_MD_PAUSE_CPU() */
+
+
+/*
+** _MD_pr_poll() -- Implement MD polling
+**
+** The function was snatched (re-used) from the unix implementation.
+**
+** The native thread stuff was deleted.
+** The pollqueue is instantiated on the mdthread structure
+** to keep the stack frame from being corrupted when this
+** thread is waiting on the poll.
+**
+*/
+extern PRInt32
+_MD_PR_POLL(PRPollDesc *pds, PRIntn npds,
+ PRIntervalTime timeout)
+{
+ PRPollDesc *pd, *epd;
+ PRInt32 n, err, pdcnt;
+ PRIntn is;
+ _PRWin16PollDesc *spds, *spd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRPollQueue *pq;
+
+ pq = &me->md.thr_pq;
+
+ /*
+ * XXX
+ * PRPollDesc has a PRFileDesc field, fd, while the IOQ
+ * is a list of PRPollQueue structures, each of which contains
+ * a _PRWin16PollDesc. A _PRWin16PollDesc struct contains
+ * the OS file descriptor, osfd, and not a PRFileDesc.
+ * So, we have allocate memory for _PRWin16PollDesc structures,
+ * copy the flags information from the pds list and have pq
+ * point to this list of _PRWin16PollDesc structures.
+ *
+ * It would be better if the memory allocation can be avoided.
+ */
+
+ spds = (_PRWin16PollDesc*) PR_MALLOC(npds * sizeof(_PRWin16PollDesc));
+ if (!spds) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ spd = spds;
+
+ _PR_INTSOFF(is);
+ _PR_MD_IOQ_LOCK();
+ _PR_THREAD_LOCK(me);
+
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_IOQ_UNLOCK();
+ PR_DELETE(spds);
+ return -1;
+ }
+
+ pdcnt = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ PRInt32 osfd;
+ PRInt16 in_flags = pd->in_flags;
+ PRFileDesc *bottom = pd->fd;
+
+ if ((NULL == bottom) || (in_flags == 0)) {
+ continue;
+ }
+ while (bottom->lower != NULL) {
+ bottom = bottom->lower;
+ }
+ osfd = bottom->secret->md.osfd;
+
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+
+ spd->osfd = osfd;
+ spd->in_flags = pd->in_flags;
+ spd++;
+ pdcnt++;
+
+ if (in_flags & PR_POLL_READ) {
+ FD_SET(osfd, &_PR_FD_READ_SET(me->cpu));
+ _PR_FD_READ_CNT(me->cpu)[osfd]++;
+ }
+ if (in_flags & PR_POLL_WRITE) {
+ FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ (_PR_FD_WRITE_CNT(me->cpu))[osfd]++;
+ }
+ if (in_flags & PR_POLL_EXCEPT) {
+ FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++;
+ }
+ if (osfd > _PR_IOQ_MAX_OSFD(me->cpu))
+ _PR_IOQ_MAX_OSFD(me->cpu) = osfd;
+ }
+ if (timeout < _PR_IOQ_TIMEOUT(me->cpu))
+ _PR_IOQ_TIMEOUT(me->cpu) = timeout;
+
+
+ pq->pds = spds;
+ pq->npds = pdcnt;
+
+ pq->thr = me;
+ pq->on_ioq = PR_TRUE;
+ pq->timeout = timeout;
+ _PR_ADD_TO_IOQ((*pq), me->cpu);
+ _PR_SLEEPQ_LOCK(me->cpu);
+ _PR_ADD_SLEEPQ(me, timeout);
+ me->state = _PR_IO_WAIT;
+ me->io_pending = PR_TRUE;
+ me->io_suspended = PR_FALSE;
+ _PR_SLEEPQ_UNLOCK(me->cpu);
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_IOQ_UNLOCK();
+
+ _PR_MD_WAIT(me, timeout);
+
+ me->io_pending = PR_FALSE;
+ me->io_suspended = PR_FALSE;
+
+ /*
+ * Copy the out_flags from the _PRWin16PollDesc structures to the
+ * user's PRPollDesc structures and free the allocated memory
+ */
+ spd = spds;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ if ((NULL == pd->fd) || (pd->in_flags == 0)) {
+ pd->out_flags = 0;
+ continue;
+ }
+ pd->out_flags = spd->out_flags;
+ spd++;
+ }
+ PR_DELETE(spds);
+
+ /*
+ ** If we timed out the pollq might still be on the ioq. Remove it
+ ** before continuing.
+ */
+ if (pq->on_ioq) {
+ _PR_INTSOFF(is);
+ _PR_MD_IOQ_LOCK();
+ /*
+ * Need to check pq.on_ioq again
+ */
+ if (pq->on_ioq == PR_TRUE) {
+ PR_REMOVE_LINK(&pq->links);
+ for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ PRInt32 osfd;
+ PRInt16 in_flags = pd->in_flags;
+ PRFileDesc *bottom = pd->fd;
+
+ if ((NULL == bottom) || (in_flags == 0)) {
+ continue;
+ }
+ while (bottom->lower != NULL) {
+ bottom = bottom->lower;
+ }
+ osfd = bottom->secret->md.osfd;
+ PR_ASSERT(osfd >= 0 || in_flags == 0);
+ if (in_flags & PR_POLL_READ) {
+ if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu));
+ }
+ if (in_flags & PR_POLL_WRITE) {
+ if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu));
+ }
+ if (in_flags & PR_POLL_EXCEPT) {
+ if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0)
+ FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu));
+ }
+ }
+ }
+ _PR_MD_IOQ_UNLOCK();
+ _PR_INTSON(is);
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ } else {
+ n = 0;
+ if (pq->on_ioq == PR_FALSE) {
+ /* Count the number of ready descriptors */
+ while (--npds >= 0) {
+ if (pds->out_flags) {
+ n++;
+ }
+ pds++;
+ }
+ }
+ return n;
+ }
+} /* end _MD_pr_poll() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16stdio.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16stdio.c
new file mode 100644
index 00000000..52d34cfe
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16stdio.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** w16stdio.c -- Callback functions for Win16 stdio read/write.
+**
+**
+*/
+#include "primpl.h"
+
+/*
+** _PL_MDStdioWrite() -- Win16 hackery to get console output
+**
+** Returns: number of bytes written.
+**
+*/
+PRInt32
+_PL_W16StdioWrite( void *buf, PRInt32 amount )
+{
+ int rc;
+
+ rc = fputs( buf, stdout );
+ if ( rc == EOF )
+ {
+ // something about errno
+ return(PR_FAILURE);
+ }
+ return( strlen(buf));
+} /* end _PL_fputs() */
+
+/*
+** _PL_W16StdioRead() -- Win16 hackery to get console input
+**
+*/
+PRInt32
+_PL_W16StdioRead( void *buf, PRInt32 amount )
+{
+ char *bp;
+
+ bp = fgets( buf, (int) amount, stdin );
+ if ( bp == NULL )
+ {
+ // something about errno
+ return(PR_FAILURE);
+ }
+
+ return( strlen(buf));
+} /* end _PL_fgets() */
+/* --- end w16stdio.c --- */
+
+/*
+** Wrappers, linked into the client, that call
+** functions in LibC
+**
+*/
+
+/*
+** _PL_W16CallBackPuts() -- Wrapper for puts()
+**
+*/
+int PR_CALLBACK _PL_W16CallBackPuts( const char *outputString )
+{
+ return( puts( outputString ));
+} /* end _PL_W16CallBackPuts() */
+
+/*
+** _PL_W16CallBackStrftime() -- Wrapper for strftime()
+**
+*/
+size_t PR_CALLBACK _PL_W16CallBackStrftime(
+ char *s,
+ size_t len,
+ const char *fmt,
+ const struct tm *p )
+{
+ return( strftime( s, len, fmt, p ));
+} /* end _PL_W16CallBackStrftime() */
+
+/*
+** _PL_W16CallBackMalloc() -- Wrapper for malloc()
+**
+*/
+void * PR_CALLBACK _PL_W16CallBackMalloc( size_t size )
+{
+ return( malloc( size ));
+} /* end _PL_W16CallBackMalloc() */
+
+/*
+** _PL_W16CallBackCalloc() -- Wrapper for calloc()
+**
+*/
+void * PR_CALLBACK _PL_W16CallBackCalloc( size_t n, size_t size )
+{
+ return( calloc( n, size ));
+} /* end _PL_W16CallBackCalloc() */
+
+/*
+** _PL_W16CallBackRealloc() -- Wrapper for realloc()
+**
+*/
+void * PR_CALLBACK _PL_W16CallBackRealloc(
+ void *old_blk,
+ size_t size )
+{
+ return( realloc( old_blk, size ));
+} /* end _PL_W16CallBackRealloc() */
+
+/*
+** _PL_W16CallBackFree() -- Wrapper for free()
+**
+*/
+void PR_CALLBACK _PL_W16CallBackFree( void *ptr )
+{
+ free( ptr );
+ return;
+} /* end _PL_W16CallBackFree() */
+
+/*
+** _PL_W16CallBackGetenv() -- Wrapper for getenv()
+**
+*/
+void * PR_CALLBACK _PL_W16CallBackGetenv( const char *name )
+{
+ return( getenv( name ));
+} /* end _PL_W16CallBackGetenv */
+
+
+/*
+** _PL_W16CallBackPutenv() -- Wrapper for putenv()
+**
+*/
+int PR_CALLBACK _PL_W16CallBackPutenv( const char *assoc )
+{
+ return( putenv( assoc ));
+} /* end _PL_W16CallBackGetenv */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16thred.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16thred.c
new file mode 100644
index 00000000..85531318
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w16thred.c
@@ -0,0 +1,426 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <sys/timeb.h>
+#include <stdio.h>
+
+/*
+** DispatchTrace -- define a thread dispatch trace entry
+**
+** The DispatchTrace oject(s) are instantiated in a single
+** array. Think of the array as a push-down stack; entry
+** zero is the most recent, entry one the next most recent, etc.
+** For each time PR_MD_RESTORE_CONTEXT() is called, the array
+** is Pushed down and entry zero is overwritten with data
+** for the newly dispatched thread.
+**
+** Function TraceDispatch() manages the DispatchTrace array.
+**
+*/
+typedef struct DispatchTrace
+{
+ PRThread * thread;
+ PRUint32 state;
+ PRInt16 mdThreadNumber;
+ PRInt16 unused;
+ PRThreadPriority priority;
+
+} DispatchTrace, *DispatchTracePtr ;
+
+static void TraceDispatch( PRThread *thread );
+
+
+PRThread *_pr_primordialThread;
+
+/*
+** Note: the static variables must be on the data-segment because
+** the stack is destroyed during shadow-stack copy operations.
+**
+*/
+static char * pSource; /* ptr to sourc of a "shadow-stack" copy */
+static char * pTarget; /* ptr to target of a "shadow-stack" copy */
+static int cxByteCount; /* number of bytes for "shadow-stack" copy */
+static int bytesMoved; /* instrumentation: WRT "shadow-stack" copy */
+static FILE * file1 = 0; /* instrumentation: WRT debug */
+
+#define NUM_DISPATCHTRACE_OBJECTS 24
+static DispatchTrace dt[NUM_DISPATCHTRACE_OBJECTS] = {0}; /* instrumentation: WRT dispatch */
+static PRUint32 dispatchCount = 0; /* instrumentation: number of thread dispatches */
+
+static int OldPriorityOfPrimaryThread = -1;
+static int TimeSlicesOnNonPrimaryThread = 0;
+static PRUint32 threadNumber = 1; /* Instrumentation: monotonically increasing number */
+
+
+
+/*
+** _PR_MD_FINAL_INIT() -- Final MD Initialization
+**
+** Poultry Problems! ... The stack, as allocated by PR_NewStack()
+** is called from here, late in initialization, because PR_NewStack()
+** requires lots of things working. When some elements of the
+** primordial thread are created, early in initialization, the
+** shadow stack is not one of these things. The "shadow stack" is
+** created here, late in initiailization using PR_NewStack(), to
+** ensure consistency in creation of the related objects.
+**
+** A new ThreadStack, and all its affiliated structures, is allocated
+** via the call to PR_NewStack(). The PRThread structure in the
+** new stack is ignored; the old PRThread structure is used (why?).
+** The old PRThreadStack structure is abandoned.
+**
+*/
+void
+_PR_MD_FINAL_INIT()
+{
+ PRThreadStack * stack = 0;
+ PRInt32 stacksize = 0;
+ PRThread * me = _PR_MD_CURRENT_THREAD();
+
+ _PR_ADJUST_STACKSIZE( stacksize );
+ stack = _PR_NewStack( stacksize );
+
+ me->stack = stack;
+ stack->thr = me;
+
+ return;
+} /* --- end _PR_MD_FINAL_INIT() --- */
+
+
+void
+_MD_INIT_RUNNING_CPU( struct _PRCPU *cpu )
+{
+ PR_INIT_CLIST(&(cpu->md.ioQ));
+ cpu->md.ioq_max_osfd = -1;
+ cpu->md.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;
+}
+
+
+void
+_PR_MD_YIELD( void )
+{
+ PR_ASSERT(0);
+}
+
+/*
+** _PR_MD_INIT_STACK() -- Win16 specific Stack initialization.
+**
+**
+*/
+
+void
+_PR_MD_INIT_STACK( PRThreadStack *ts, PRIntn redzone )
+{
+ ts->md.stackTop = ts->stackTop - sizeof(PRThread);
+ ts->md.cxByteCount = 0;
+
+ return;
+} /* --- end _PR_MD_INIT_STACK() --- */
+
+/*
+** _PR_MD_INIT_THREAD() -- Win16 specific Thread initialization.
+**
+*/
+PRStatus
+_PR_MD_INIT_THREAD(PRThread *thread)
+{
+ if ( thread->flags & _PR_PRIMORDIAL)
+ {
+ _pr_primordialThread = thread;
+ thread->md.threadNumber = 1;
+ }
+ else
+ {
+ thread->md.threadNumber = ++threadNumber;
+ }
+
+ thread->md.magic = _MD_MAGIC_THREAD;
+ strcpy( thread->md.guardBand, "GuardBand" );
+
+ return PR_SUCCESS;
+}
+
+
+PRStatus
+_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ _MD_SWITCH_CONTEXT( thread );
+
+ return( PR_SUCCESS );
+}
+
+void *PR_W16GetExceptionContext(void)
+{
+ return _MD_CURRENT_THREAD()->md.exceptionContext;
+}
+
+void
+PR_W16SetExceptionContext(void *context)
+{
+ _MD_CURRENT_THREAD()->md.exceptionContext = context;
+}
+
+
+
+
+/*
+** _MD_RESTORE_CONTEXT() -- Resume execution of thread 't'.
+**
+** Win16 threading is based on the NSPR 2.0 general model of
+** user threads. It differs from the general model in that a
+** single "real" stack segment is used for execution of all
+** threads. The context of the suspended threads is preserved
+** in the md.context [and related members] of the PRThread
+** structure. The stack context of the suspended thread is
+** preserved in a "shadow stack" object.
+**
+** _MD_RESTORE_CONTEXT() implements most of the thread switching
+** for NSPR's implementation of Win16 theads.
+**
+** Operations Notes:
+**
+** Function PR_NewStack() in prustack.c allocates a new
+** PRThreadStack, PRStack, PRSegment, and a "shadow" stack
+** for a thread. These structures are wired together to
+** form the basis of Win16 threads. The thread and shadow
+** stack structures are created as part of PR_CreateThread().
+**
+** Note! Some special "magic" is applied to the "primordial"
+** thread. The physical layout of the PRThread, PRThreadStack,
+** shadow stack, ... is somewhat different. Watch yourself when
+** mucking around with it. ... See _PR_MD_FINAL_INIT() for most
+** of the special treatment of the primordial thread.
+**
+** Function _PR_MD_INIT_STACK() initializes the value of
+** PRThreadStack member md.cxByteCount to zero; there
+** is no context to be restored for a thread's initial
+** dispatch. The value of member md.stackTop is set to
+** point to the highest usable address on the shadow stack.
+** This point corresponds to _pr_top_of_task_stack on the
+** system's operating stack.
+**
+** _pr_top_of_task_stack points to a place on the system stack
+** considered to be "close to the top". Stack context is preserved
+** relative to this point.
+**
+** Reminder: In x86 architecture, the stack grows "down".
+** That is: the stack pointer (SP register) is decremented
+** to push objects onto the stack or when a call is made.
+**
+** Function _PR_MD_WAIT() invokes macro _MD_SWITCH_CONTEXT();
+** this causes the hardware registers to be preserved in a
+** CATCHBUF structure using function Catch() [see _win16.h],
+** then calls PR_Schedule() to select a new thread for dispatch.
+** PR_Schedule() calls _MD_RESTORE_CONTEXT() to cause the thread
+** being suspended's stack to be preserved, to restore the
+** stack of the to-be-dispactched thread, and to restore the
+** to-be-dispactched thread's hardware registers.
+**
+** At the moment _PR_MD_RESTORE_CONTEXT() is called, the stack
+** pointer (SP) is less than the reference pointer
+** _pr_top_of_task_stack. The distance difference between the SP and
+** _pr_top_of_task_stack is the amount of stack that must be preserved.
+** This value, cxByteCount, is calculated then preserved in the
+** PRThreadStack.md.cxByteCount for later use (size of stack
+** context to restore) when this thread is dispatched again.
+**
+** A C language for() loop is used to copy, byte-by-byte, the
+** stack data being preserved starting at the "address of t"
+** [Note: 't' is the argument passed to _PR_MD_RESTORE_CONTEXT()]
+** for the length of cxByteCount.
+**
+** variables pSource and pTarget are the calculated source and
+** destination pointers for the stack copy operation. These
+** variables are static scope because they cannot be instantiated
+** on the stack itself, since the stack is clobbered by restoring
+** the to-be-dispatched thread's stack context.
+**
+** After preserving the suspended thread's stack and architectural
+** context, the to-be-dispatched thread's stack context is copied
+** from its shadow stack to the system operational stack. The copy
+** is done in a small fragment of in-line assembly language. Note:
+** In NSPR 1.0, a while() loop was used to do the copy; when compiled
+** with the MS C 1.52c compiler, the short while loop used no
+** stack variables. The Watcom compiler, specified for use on NSPR 2.0,
+** uses stack variables to implement the same while loop. This is
+** a no-no! The copy operation clobbers these variables making the
+** results of the copy ... unpredictable ... So, a short piece of
+** inline assembly language is used to effect the copy.
+**
+** Following the restoration of the to-be-dispatched thread's
+** stack context, another short inline piece of assemble language
+** is used to set the SP register to correspond to what it was
+** when the to-be-dispatched thread was suspended. This value
+** uses the thread's stack->md.cxByteCount as a negative offset
+** from _pr_top_of_task_stack as the new value of SP.
+**
+** Finally, Function Throw() is called to restore the architectural
+** context of the to-be-dispatched thread.
+**
+** At this point, the newly dispatched thread appears to resume
+** execution following the _PR_MD_SWITCH_CONTEXT() macro.
+**
+** OK, this ain't rocket-science, but it can confuse you easily.
+** If you have to work on this stuff, please take the time to
+** draw, on paper, the structures (PRThread, PRThreadStack,
+** PRSegment, the "shadow stack", the system stack and the related
+** global variables). Hand step it thru the debugger to make sure
+** you understand it very well before making any changes. ...
+** YMMV.
+**
+*/
+void _MD_RESTORE_CONTEXT(PRThread *t)
+{
+ dispatchCount++;
+ TraceDispatch( t );
+ /*
+ ** This is a good opportunity to make sure that the main
+ ** mozilla thread actually gets some time. If interrupts
+ ** are on, then we know it is safe to check if the main
+ ** thread is being starved. If moz has not been scheduled
+ ** for a long time, then then temporarily bump the fe priority
+ ** up so that it gets to run at least one.
+ */
+// #if 0 // lth. condition off for debug.
+ if (_pr_primordialThread == t) {
+ if (OldPriorityOfPrimaryThread != -1) {
+ PR_SetThreadPriority(_pr_primordialThread, OldPriorityOfPrimaryThread);
+ OldPriorityOfPrimaryThread = -1;
+ }
+ TimeSlicesOnNonPrimaryThread = 0;
+ } else {
+ TimeSlicesOnNonPrimaryThread++;
+ }
+
+ if ((TimeSlicesOnNonPrimaryThread >= 20) && (OldPriorityOfPrimaryThread == -1)) {
+ OldPriorityOfPrimaryThread = PR_GetThreadPriority(_pr_primordialThread);
+ PR_SetThreadPriority(_pr_primordialThread, 31);
+ TimeSlicesOnNonPrimaryThread = 0;
+ }
+// #endif
+ /*
+ ** Save the Task Stack into the "shadow stack" of the current thread
+ */
+ cxByteCount = (int) ((PRUint32) _pr_top_of_task_stack - (PRUint32) &t );
+ pSource = (char *) &t;
+ pTarget = (char *)((PRUint32)_pr_currentThread->stack->md.stackTop
+ - (PRUint32)cxByteCount );
+ _pr_currentThread->stack->md.cxByteCount = cxByteCount;
+
+ for( bytesMoved = 0; bytesMoved < cxByteCount; bytesMoved++ )
+ *(pTarget + bytesMoved ) = *(pSource + bytesMoved );
+
+ /* Mark the new thread as the current thread */
+ _pr_currentThread = t;
+
+ /*
+ ** Now copy the "shadow stack" of the new thread into the Task Stack
+ **
+ ** REMEMBER:
+ ** After the stack has been copied, ALL local variables in this function
+ ** are invalid !!
+ */
+ cxByteCount = t->stack->md.cxByteCount;
+ pSource = t->stack->md.stackTop - cxByteCount;
+ pTarget = _pr_top_of_task_stack - cxByteCount;
+
+ errno = (_pr_currentThread)->md.errcode;
+
+ __asm
+ {
+ mov cx, cxByteCount
+ mov si, WORD PTR [pSource]
+ mov di, WORD PTR [pTarget]
+ mov ax, WORD PTR [pTarget + 2]
+ mov es, ax
+ mov ax, WORD PTR [pSource + 2]
+ mov bx, ds
+ mov ds, ax
+ rep movsb
+ mov ds, bx
+ }
+
+ /*
+ ** IMPORTANT:
+ ** ----------
+ ** SS:SP is now invalid :-( This means that all local variables and
+ ** function arguments are invalid and NO function calls can be
+ ** made !!! We must fix up SS:SP so that function calls can safely
+ ** be made...
+ */
+
+ __asm {
+ mov ax, WORD PTR [_pr_top_of_task_stack]
+ sub ax, cxByteCount
+ mov sp, ax
+ };
+
+ /*
+ ** Resume execution of thread: t by restoring the thread's context.
+ **
+ */
+ Throw((_pr_currentThread)->md.context, 1);
+} /* --- end MD_RESTORE_CONTEXT() --- */
+
+
+static void TraceDispatch( PRThread *thread )
+{
+ int i;
+
+ /*
+ ** push all DispatchTrace objects to down one slot.
+ ** Note: the last entry is lost; last-1 becomes last, etc.
+ */
+ for( i = NUM_DISPATCHTRACE_OBJECTS -2; i >= 0; i-- )
+ {
+ dt[i +1] = dt[i];
+ }
+
+ /*
+ ** Build dt[0] from t
+ */
+ dt->thread = thread;
+ dt->state = thread->state;
+ dt->mdThreadNumber = thread->md.threadNumber;
+ dt->priority = thread->priority;
+
+ return;
+} /* --- end TraceDispatch() --- */
+
+
+/* $$ end W16thred.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32ipcsem.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32ipcsem.c
new file mode 100644
index 00000000..82201a80
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32ipcsem.c
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: w32ipcsem.c
+ * Description: implements named semaphores for NT and WIN95.
+ */
+
+#include "primpl.h"
+
+/*
+ * NSPR-to-NT access right mapping table for semaphore objects.
+ *
+ * The SYNCHRONIZE access is required by WaitForSingleObject.
+ * The SEMAPHORE_MODIFY_STATE access is required by ReleaseSemaphore.
+ * The OR of these three access masks must equal SEMAPHORE_ALL_ACCESS.
+ * This is because if a semaphore object with the specified name
+ * exists, CreateSemaphore requests SEMAPHORE_ALL_ACCESS access to
+ * the existing object.
+ */
+static DWORD semAccessTable[] = {
+ STANDARD_RIGHTS_REQUIRED|0x1, /* read (0x1 is "query state") */
+ STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, /* write */
+ 0 /* execute */
+};
+
+#ifndef _PR_GLOBAL_THREADS_ONLY
+
+/*
+ * A fiber cannot call WaitForSingleObject because that
+ * will block the other fibers running on the same thread.
+ * If a fiber needs to wait on a (semaphore) handle, we
+ * create a native thread to call WaitForSingleObject and
+ * have the fiber join the native thread.
+ */
+
+/*
+ * Arguments, return value, and error code for WaitForSingleObject
+ */
+struct WaitSingleArg {
+ HANDLE handle;
+ DWORD timeout;
+ DWORD rv;
+ DWORD error;
+};
+
+static void WaitSingleThread(void *arg)
+{
+ struct WaitSingleArg *warg = (struct WaitSingleArg *) arg;
+
+ warg->rv = WaitForSingleObject(warg->handle, warg->timeout);
+ if (warg->rv == WAIT_FAILED) {
+ warg->error = GetLastError();
+ }
+}
+
+static DWORD FiberSafeWaitForSingleObject(
+ HANDLE hHandle,
+ DWORD dwMilliseconds
+)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ return WaitForSingleObject(hHandle, dwMilliseconds);
+ } else {
+ PRThread *waitThread;
+ struct WaitSingleArg warg;
+ PRStatus rv;
+
+ warg.handle = hHandle;
+ warg.timeout = dwMilliseconds;
+ waitThread = PR_CreateThread(
+ PR_USER_THREAD, WaitSingleThread, &warg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (waitThread == NULL) {
+ return WAIT_FAILED;
+ }
+
+ rv = PR_JoinThread(waitThread);
+ PR_ASSERT(rv == PR_SUCCESS);
+ if (rv == PR_FAILURE) {
+ return WAIT_FAILED;
+ }
+ if (warg.rv == WAIT_FAILED) {
+ SetLastError(warg.error);
+ }
+ return warg.rv;
+ }
+}
+
+#endif /* !_PR_GLOBAL_THREADS_ONLY */
+
+PRSem *_PR_MD_OPEN_SEMAPHORE(
+ const char *osname, PRIntn flags, PRIntn mode, PRUintn value)
+{
+ PRSem *sem;
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ sem = PR_NEW(PRSem);
+ if (sem == NULL) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ if (flags & PR_SEM_CREATE) {
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, semAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ sem->sem = CreateSemaphore(lpSA, value, 0x7fffffff, osname);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+ if (sem->sem == NULL) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ PR_DELETE(sem);
+ return NULL;
+ }
+ if ((flags & PR_SEM_EXCL) && (GetLastError() == ERROR_ALREADY_EXISTS)) {
+ PR_SetError(PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS);
+ CloseHandle(sem->sem);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ } else {
+ sem->sem = OpenSemaphore(
+ SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, FALSE, osname);
+ if (sem->sem == NULL) {
+ DWORD err = GetLastError();
+
+ /*
+ * If we open a nonexistent named semaphore, NT
+ * returns ERROR_FILE_NOT_FOUND, while Win95
+ * returns ERROR_INVALID_NAME
+ */
+ if (err == ERROR_INVALID_NAME) {
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ } else {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ }
+ PR_DELETE(sem);
+ return NULL;
+ }
+ }
+ return sem;
+}
+
+PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem)
+{
+ DWORD rv;
+
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ rv = WaitForSingleObject(sem->sem, INFINITE);
+#else
+ rv = FiberSafeWaitForSingleObject(sem->sem, INFINITE);
+#endif
+ PR_ASSERT(rv == WAIT_FAILED || rv == WAIT_OBJECT_0);
+ if (rv == WAIT_FAILED) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ if (rv != WAIT_OBJECT_0) {
+ /* Should not happen */
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem)
+{
+ if (ReleaseSemaphore(sem->sem, 1, NULL) == FALSE) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem)
+{
+ if (CloseHandle(sem->sem) == FALSE) {
+ _PR_MD_MAP_CLOSE_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ PR_DELETE(sem);
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32poll.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32poll.c
new file mode 100644
index 00000000..0bf5203a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32poll.c
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This file implements _PR_MD_PR_POLL for Win32.
+ */
+
+/* The default value of FD_SETSIZE is 64. */
+#define FD_SETSIZE 1024
+
+#include "primpl.h"
+
+#if !defined(_PR_GLOBAL_THREADS_ONLY)
+
+struct select_data_s {
+ PRInt32 status;
+ PRInt32 error;
+ fd_set *rd, *wt, *ex;
+ const struct timeval *tv;
+};
+
+static void
+_PR_MD_select_thread(void *cdata)
+{
+ struct select_data_s *cd = (struct select_data_s *)cdata;
+
+ cd->status = select(0, cd->rd, cd->wt, cd->ex, cd->tv);
+
+ if (cd->status == SOCKET_ERROR) {
+ cd->error = WSAGetLastError();
+ }
+}
+
+int _PR_NTFiberSafeSelect(
+ int nfds,
+ fd_set *readfds,
+ fd_set *writefds,
+ fd_set *exceptfds,
+ const struct timeval *timeout)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ int ready;
+
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ ready = _MD_SELECT(nfds, readfds, writefds, exceptfds, timeout);
+ }
+ else
+ {
+ /*
+ ** Creating a new thread on each call!!
+ ** I guess web server doesn't use non-block I/O.
+ */
+ PRThread *selectThread;
+ struct select_data_s data;
+ data.status = 0;
+ data.error = 0;
+ data.rd = readfds;
+ data.wt = writefds;
+ data.ex = exceptfds;
+ data.tv = timeout;
+
+ selectThread = PR_CreateThread(
+ PR_USER_THREAD, _PR_MD_select_thread, &data,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (selectThread == NULL) return -1;
+
+ PR_JoinThread(selectThread);
+ ready = data.status;
+ if (ready == SOCKET_ERROR) WSASetLastError(data.error);
+ }
+ return ready;
+}
+
+#endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */
+
+PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ int ready, err;
+ fd_set rd, wt, ex;
+ fd_set *rdp, *wtp, *exp;
+ int nrd, nwt, nex;
+ PRFileDesc *bottom;
+ PRPollDesc *pd, *epd;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ struct timeval tv, *tvp = NULL;
+
+ if (_PR_PENDING_INTERRUPT(me))
+ {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ ** Is it an empty set? If so, just sleep for the timeout and return
+ */
+ if (0 == npds)
+ {
+ PR_Sleep(timeout);
+ return 0;
+ }
+
+ nrd = nwt = nex = 0;
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ SOCKET osfd;
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ if (pd->in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pd->fd->methods->poll)(
+ pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE),
+ &out_flags_read);
+ }
+ if (pd->in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pd->fd->methods->poll)(
+ pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ),
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one's ready right now (buffered input) */
+ if (0 == ready)
+ {
+ /*
+ * We will have to return without calling the
+ * system poll/select function. So zero the
+ * out_flags fields of all the poll descriptors
+ * before this one.
+ */
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1;
+ pd->out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ pd->out_flags = 0; /* pre-condition */
+ /* make sure this is an NSPR supported stack */
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ osfd = (SOCKET) bottom->secret->md.osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_READ;
+ FD_SET(osfd, &rd);
+ nrd++;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ nwt++;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
+ FD_SET(osfd, &rd);
+ nrd++;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
+ FD_SET(osfd, &wt);
+ nwt++;
+ }
+ if (pd->in_flags & PR_POLL_EXCEPT) {
+ FD_SET(osfd, &ex);
+ nex++;
+ }
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ PRPollDesc *prev;
+ for (prev = pds; prev < pd; prev++)
+ {
+ prev->out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pd->out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ pd->out_flags = 0;
+ }
+ }
+
+ if (0 != ready) return ready; /* no need to block */
+
+ if ((nrd > FD_SETSIZE) || (nwt > FD_SETSIZE) || (nex > FD_SETSIZE)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ rdp = (0 == nrd) ? NULL : &rd;
+ wtp = (0 == nwt) ? NULL : &wt;
+ exp = (0 == nex) ? NULL : &ex;
+
+ if ((NULL == rdp) && (NULL == wtp) && (NULL == exp)) {
+ PR_Sleep(timeout);
+ return 0;
+ }
+
+ if (timeout != PR_INTERVAL_NO_TIMEOUT)
+ {
+ PRInt32 ticksPerSecond = PR_TicksPerSecond();
+ tv.tv_sec = timeout / ticksPerSecond;
+ tv.tv_usec = PR_IntervalToMicroseconds( timeout % ticksPerSecond );
+ tvp = &tv;
+ }
+
+#if defined(_PR_GLOBAL_THREADS_ONLY)
+ ready = _MD_SELECT(0, rdp, wtp, exp, tvp);
+#else
+ ready = _PR_NTFiberSafeSelect(0, rdp, wtp, exp, tvp);
+#endif
+
+ /*
+ ** Now to unravel the select sets back into the client's poll
+ ** descriptor list. Is this possibly an area for pissing away
+ ** a few cycles or what?
+ */
+ if (ready > 0)
+ {
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ SOCKET osfd;
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom);
+
+ osfd = (SOCKET) bottom->secret->md.osfd;
+
+ if (FD_ISSET(osfd, &rd))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_READ)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &wt))
+ {
+ if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
+ out_flags |= PR_POLL_READ;
+ if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
+ out_flags |= PR_POLL_WRITE;
+ }
+ if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
+ }
+ pd->out_flags = out_flags;
+ if (out_flags) ready++;
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else if (ready == SOCKET_ERROR)
+ {
+ err = WSAGetLastError();
+ if (err == WSAENOTSOCK)
+ {
+ /* Find the bad fds */
+ int optval;
+ int optlen = sizeof(optval);
+ ready = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++)
+ {
+ pd->out_flags = 0;
+ if ((NULL != pd->fd) && (0 != pd->in_flags))
+ {
+ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1)
+ {
+ PR_ASSERT(WSAGetLastError() == WSAENOTSOCK);
+ if (WSAGetLastError() == WSAENOTSOCK)
+ {
+ pd->out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ }
+ PR_ASSERT(ready > 0);
+ }
+ else _PR_MD_MAP_SELECT_ERROR(err);
+ }
+
+ return ready;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32rng.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32rng.c
new file mode 100644
index 00000000..2ad6ed86
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32rng.c
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <windows.h>
+#include <time.h>
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <primpl.h>
+
+static BOOL
+CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow)
+{
+ LARGE_INTEGER liCount;
+
+ if (!QueryPerformanceCounter(&liCount))
+ return FALSE;
+
+ *lpdwHigh = liCount.u.HighPart;
+ *lpdwLow = liCount.u.LowPart;
+ return TRUE;
+}
+
+extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
+{
+ DWORD dwHigh, dwLow, dwVal;
+ int n = 0;
+ int nBytes;
+ time_t sTime;
+
+ if (size <= 0)
+ return 0;
+
+ CurrentClockTickTime(&dwHigh, &dwLow);
+
+ // get the maximally changing bits first
+ nBytes = sizeof(dwLow) > size ? size : sizeof(dwLow);
+ memcpy((char *)buf, &dwLow, nBytes);
+ n += nBytes;
+ size -= nBytes;
+
+ if (size <= 0)
+ return n;
+
+ nBytes = sizeof(dwHigh) > size ? size : sizeof(dwHigh);
+ memcpy(((char *)buf) + n, &dwHigh, nBytes);
+ n += nBytes;
+ size -= nBytes;
+
+ if (size <= 0)
+ return n;
+
+ // get the number of milliseconds that have elapsed since Windows started
+ dwVal = GetTickCount();
+
+ nBytes = sizeof(dwVal) > size ? size : sizeof(dwVal);
+ memcpy(((char *)buf) + n, &dwVal, nBytes);
+ n += nBytes;
+ size -= nBytes;
+
+ if (size <= 0)
+ return n;
+
+ // get the time in seconds since midnight Jan 1, 1970
+ time(&sTime);
+ nBytes = sizeof(sTime) > size ? size : sizeof(sTime);
+ memcpy(((char *)buf) + n, &sTime, nBytes);
+ n += nBytes;
+
+ return n;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32shm.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32shm.c
new file mode 100644
index 00000000..705f62f1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w32shm.c
@@ -0,0 +1,356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <private/primpl.h>
+#include <string.h>
+#include <prshm.h>
+#include <prerr.h>
+#include <prmem.h>
+
+#if defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY)
+
+extern PRLogModuleInfo *_pr_shm_lm;
+
+/*
+ * NSPR-to-NT access right mapping table for file-mapping objects.
+ *
+ * The OR of these three access masks must equal FILE_MAP_ALL_ACCESS.
+ * This is because if a file-mapping object with the specified name
+ * exists, CreateFileMapping requests full access to the existing
+ * object.
+ */
+static DWORD filemapAccessTable[] = {
+ FILE_MAP_ALL_ACCESS & ~FILE_MAP_WRITE, /* read */
+ FILE_MAP_ALL_ACCESS & ~FILE_MAP_READ, /* write */
+ 0 /* execute */
+};
+
+extern PRSharedMemory * _MD_OpenSharedMemory(
+ const char *name,
+ PRSize size,
+ PRIntn flags,
+ PRIntn mode
+)
+{
+ char ipcname[PR_IPC_NAME_SIZE];
+ PRStatus rc = PR_SUCCESS;
+ DWORD dwHi, dwLo;
+ PRSharedMemory *shm;
+ DWORD flProtect = ( PAGE_READWRITE );
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_SetError(PR_UNKNOWN_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: name is invalid"));
+ return(NULL);
+ }
+
+ shm = PR_NEWZAP( PRSharedMemory );
+ if ( NULL == shm )
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory"));
+ return(NULL);
+ }
+
+ shm->ipcname = PR_MALLOC( strlen( ipcname ) + 1 );
+ if ( NULL == shm->ipcname )
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory"));
+ PR_DELETE(shm);
+ return(NULL);
+ }
+
+ /* copy args to struct */
+ strcpy( shm->ipcname, ipcname );
+ shm->size = size;
+ shm->mode = mode;
+ shm->flags = flags;
+ shm->ident = _PR_SHM_IDENT;
+
+ if (flags & PR_SHM_CREATE ) {
+ /* XXX: Not 64bit safe. Fix when WinNT goes 64bit. */
+ dwHi = 0;
+ dwLo = shm->size;
+
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, filemapAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ shm->handle = CreateFileMapping(
+ (HANDLE)-1 ,
+ lpSA,
+ flProtect,
+ dwHi,
+ dwLo,
+ shm->ipcname);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+
+ if ( NULL == shm->handle ) {
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ( "PR_OpenSharedMemory: CreateFileMapping() failed: %s",
+ shm->ipcname ));
+ _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
+ PR_FREEIF( shm->ipcname )
+ PR_DELETE( shm );
+ return(NULL);
+ } else {
+ if (( flags & PR_SHM_EXCL) && ( GetLastError() == ERROR_ALREADY_EXISTS )) {
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ( "PR_OpenSharedMemory: Request exclusive & already exists",
+ shm->ipcname ));
+ PR_SetError( PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS );
+ CloseHandle( shm->handle );
+ PR_FREEIF( shm->ipcname )
+ PR_DELETE( shm );
+ return(NULL);
+ } else {
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ( "PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d",
+ shm->ipcname, shm->handle ));
+ return(shm);
+ }
+ }
+ } else {
+ shm->handle = OpenFileMapping( FILE_MAP_WRITE, TRUE, shm->ipcname );
+ if ( NULL == shm->handle ) {
+ _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ( "PR_OpenSharedMemory: OpenFileMapping() failed: %s, error: %d",
+ shm->ipcname, PR_GetOSError()));
+ PR_FREEIF( shm->ipcname );
+ PR_DELETE( shm );
+ return(NULL);
+ } else {
+ PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
+ ( "PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d",
+ shm->ipcname, shm->handle ));
+ return(shm);
+ }
+ }
+ /* returns from separate paths */
+}
+
+extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags )
+{
+ PRUint32 access = FILE_MAP_WRITE;
+ void *addr;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ if ( PR_SHM_READONLY & flags )
+ access = FILE_MAP_READ;
+
+ addr = MapViewOfFile( shm->handle,
+ access,
+ 0, 0,
+ shm->size );
+
+ if ( NULL == addr ) {
+ _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
+ PR_LOG( _pr_shm_lm, PR_LOG_ERROR,
+ ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d", PR_GetOSError()));
+ }
+
+ return( addr );
+} /* end _MD_ATTACH_SHARED_MEMORY() */
+
+
+extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr )
+{
+ PRStatus rc = PR_SUCCESS;
+ BOOL wrc;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ wrc = UnmapViewOfFile( addr );
+ if ( FALSE == wrc )
+ {
+ _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
+ PR_LOG( _pr_shm_lm, PR_LOG_ERROR,
+ ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d", PR_GetOSError()));
+ rc = PR_FAILURE;
+ }
+
+ return( rc );
+}
+
+
+extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm )
+{
+ PRStatus rc = PR_SUCCESS;
+ BOOL wrc;
+
+ PR_ASSERT( shm->ident == _PR_SHM_IDENT );
+
+ wrc = CloseHandle( shm->handle );
+ if ( FALSE == wrc )
+ {
+ _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
+ PR_LOG( _pr_shm_lm, PR_LOG_ERROR,
+ ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d", PR_GetOSError()));
+ rc = PR_FAILURE;
+ }
+ PR_FREEIF( shm->ipcname );
+ PR_DELETE( shm );
+
+ return( rc );
+} /* end _MD_CLOSE_SHARED_MEMORY() */
+
+extern PRStatus _MD_DeleteSharedMemory( const char *name )
+{
+ return( PR_SUCCESS );
+}
+
+
+/*
+** Windows implementation of anonymous memory (file) map
+*/
+extern PRLogModuleInfo *_pr_shma_lm;
+
+extern PRFileMap* _md_OpenAnonFileMap(
+ const char *dirName,
+ PRSize size,
+ PRFileMapProtect prot
+)
+{
+ PRFileMap *fm;
+ HANDLE hFileMap;
+
+ fm = PR_CreateFileMap( (PRFileDesc*)-1, size, prot );
+ if ( NULL == fm ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed"));
+ goto Finished;
+ }
+
+ /*
+ ** Make fm->md.hFileMap inheritable. We can't use
+ ** GetHandleInformation and SetHandleInformation
+ ** because these two functions fail with
+ ** ERROR_CALL_NOT_IMPLEMENTED on Win95.
+ */
+ if (DuplicateHandle(GetCurrentProcess(), fm->md.hFileMap,
+ GetCurrentProcess(), &hFileMap,
+ 0, TRUE /* inheritable */,
+ DUPLICATE_SAME_ACCESS) == FALSE) {
+ PR_SetError( PR_UNKNOWN_ERROR, GetLastError() );
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_OpenAnonFileMap(): DuplicateHandle(): failed"));
+ PR_CloseFileMap( fm );
+ fm = NULL;
+ goto Finished;
+ }
+ CloseHandle(fm->md.hFileMap);
+ fm->md.hFileMap = hFileMap;
+
+Finished:
+ return(fm);
+} /* end md_OpenAnonFileMap() */
+
+/*
+** _md_ExportFileMapAsString()
+**
+*/
+extern PRStatus _md_ExportFileMapAsString(
+ PRFileMap *fm,
+ PRSize bufSize,
+ char *buf
+)
+{
+ PRIntn written;
+
+ written = PR_snprintf( buf, bufSize, "%d:%ld:%ld",
+ (PRIntn)fm->prot, (PRInt32)fm->md.hFileMap, (PRInt32)fm->md.dwAccess );
+ /* Watch out on the above snprintf(). Windows HANDLE assumes 32bits; windows calls it void* */
+
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_ExportFileMapAsString(): prot: %x, hFileMap: %x, dwAccess: %x",
+ fm->prot, fm->md.hFileMap, fm->md.dwAccess ));
+
+ return((written == -1)? PR_FAILURE : PR_SUCCESS);
+} /* end _md_ExportFileMapAsString() */
+
+
+/*
+** _md_ImportFileMapFromString()
+**
+*/
+extern PRFileMap * _md_ImportFileMapFromString(
+ const char *fmstring
+)
+{
+ PRIntn prot;
+ PRInt32 hFileMap;
+ PRInt32 dwAccess;
+ PRFileMap *fm = NULL;
+
+ PR_sscanf( fmstring, "%d:%ld:%ld", &prot, &hFileMap, &dwAccess );
+
+ fm = PR_NEWZAP(PRFileMap);
+ if ( NULL == fm ) {
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed"));
+ return(fm);
+ }
+
+ fm->prot = (PRFileMapProtect)prot;
+ fm->md.hFileMap = (HANDLE)hFileMap; /* Assumes HANDLE is 32bit */
+ fm->md.dwAccess = (DWORD)dwAccess;
+ fm->fd = (PRFileDesc*)-1;
+
+ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
+ ("_md_ImportFileMapFromString(): fm: %p, prot: %d, hFileMap: %8.8x, dwAccess: %8.8x, fd: %x",
+ fm, prot, fm->md.hFileMap, fm->md.dwAccess, fm->fd));
+ return(fm);
+} /* end _md_ImportFileMapFromString() */
+
+#else
+Error! Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY not defined?
+#endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */
+/* --- end w32shm.c --- */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95cv.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95cv.c
new file mode 100644
index 00000000..975ac4b0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95cv.c
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * w95cv.c -- Windows 95 Machine-Dependent Code for Condition Variables
+ *
+ * We implement our own condition variable wait queue. Each thread
+ * has a semaphore object (thread->md.blocked_sema) to block on while
+ * waiting on a condition variable.
+ *
+ * We use a deferred condition notify algorithm. When PR_NotifyCondVar
+ * or PR_NotifyAllCondVar is called, the condition notifies are simply
+ * recorded in the _MDLock structure. We defer the condition notifies
+ * until right after we unlock the lock. This way the awakened threads
+ * have a better chance to reaquire the lock.
+ */
+
+#include "primpl.h"
+
+/*
+ * AddThreadToCVWaitQueueInternal --
+ *
+ * Add the thread to the end of the condition variable's wait queue.
+ * The CV's lock must be locked when this function is called.
+ */
+
+static void
+AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv)
+{
+ PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
+ || (cv->waitTail == NULL && cv->waitHead == NULL));
+ cv->nwait += 1;
+ thred->md.inCVWaitQueue = PR_TRUE;
+ thred->md.next = NULL;
+ thred->md.prev = cv->waitTail;
+ if (cv->waitHead == NULL) {
+ cv->waitHead = thred;
+ } else {
+ cv->waitTail->md.next = thred;
+ }
+ cv->waitTail = thred;
+}
+
+/*
+ * md_UnlockAndPostNotifies --
+ *
+ * Unlock the lock, and then do the deferred condition notifies.
+ * If waitThred and waitCV are not NULL, waitThred is added to
+ * the wait queue of waitCV before the lock is unlocked.
+ *
+ * This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK,
+ * the two places where a lock is unlocked.
+ */
+static void
+md_UnlockAndPostNotifies(
+ _MDLock *lock,
+ PRThread *waitThred,
+ _MDCVar *waitCV)
+{
+ PRIntn index;
+ _MDNotified post;
+ _MDNotified *notified, *prev = NULL;
+
+ /*
+ * Time to actually notify any conditions that were affected
+ * while the lock was held. Get a copy of the list that's in
+ * the lock structure and then zero the original. If it's
+ * linked to other such structures, we own that storage.
+ */
+ post = lock->notified; /* a safe copy; we own the lock */
+
+#if defined(DEBUG)
+ ZeroMemory(&lock->notified, sizeof(_MDNotified)); /* reset */
+#else
+ lock->notified.length = 0; /* these are really sufficient */
+ lock->notified.link = NULL;
+#endif
+
+ /*
+ * Figure out how many threads we need to wake up.
+ */
+ notified = &post; /* this is where we start */
+ do {
+ for (index = 0; index < notified->length; ++index) {
+ _MDCVar *cv = notified->cv[index].cv;
+ PRThread *thred;
+ int i;
+
+ /* Fast special case: no waiting threads */
+ if (cv->waitHead == NULL) {
+ notified->cv[index].notifyHead = NULL;
+ continue;
+ }
+
+ /* General case */
+ if (-1 == notified->cv[index].times) {
+ /* broadcast */
+ thred = cv->waitHead;
+ while (thred != NULL) {
+ thred->md.inCVWaitQueue = PR_FALSE;
+ thred = thred->md.next;
+ }
+ notified->cv[index].notifyHead = cv->waitHead;
+ cv->waitHead = cv->waitTail = NULL;
+ cv->nwait = 0;
+ } else {
+ thred = cv->waitHead;
+ i = notified->cv[index].times;
+ while (thred != NULL && i > 0) {
+ thred->md.inCVWaitQueue = PR_FALSE;
+ thred = thred->md.next;
+ i--;
+ }
+ notified->cv[index].notifyHead = cv->waitHead;
+ cv->waitHead = thred;
+ if (cv->waitHead == NULL) {
+ cv->waitTail = NULL;
+ } else {
+ if (cv->waitHead->md.prev != NULL) {
+ cv->waitHead->md.prev->md.next = NULL;
+ cv->waitHead->md.prev = NULL;
+ }
+ }
+ cv->nwait -= notified->cv[index].times - i;
+ }
+ }
+ notified = notified->link;
+ } while (NULL != notified);
+
+ if (waitThred) {
+ AddThreadToCVWaitQueueInternal(waitThred, waitCV);
+ }
+
+ /* Release the lock before notifying */
+ LeaveCriticalSection(&lock->mutex);
+
+ notified = &post; /* this is where we start */
+ do {
+ for (index = 0; index < notified->length; ++index) {
+ PRThread *thred;
+ PRThread *next;
+
+ thred = notified->cv[index].notifyHead;
+ while (thred != NULL) {
+ BOOL rv;
+
+ next = thred->md.next;
+ thred->md.prev = thred->md.next = NULL;
+
+ rv = ReleaseSemaphore(thred->md.blocked_sema, 1, NULL);
+ PR_ASSERT(rv != 0);
+ thred = next;
+ }
+ }
+ prev = notified;
+ notified = notified->link;
+ if (&post != prev) PR_DELETE(prev);
+ } while (NULL != notified);
+}
+
+/*
+ * Notifies just get posted to the protecting mutex. The
+ * actual notification is done when the lock is released so that
+ * MP systems don't contend for a lock that they can't have.
+ */
+static void md_PostNotifyToCvar(_MDCVar *cvar, _MDLock *lock,
+ PRBool broadcast)
+{
+ PRIntn index = 0;
+ _MDNotified *notified = &lock->notified;
+
+ while (1) {
+ for (index = 0; index < notified->length; ++index) {
+ if (notified->cv[index].cv == cvar) {
+ if (broadcast) {
+ notified->cv[index].times = -1;
+ } else if (-1 != notified->cv[index].times) {
+ notified->cv[index].times += 1;
+ }
+ return;
+ }
+ }
+ /* if not full, enter new CV in this array */
+ if (notified->length < _MD_CV_NOTIFIED_LENGTH) break;
+
+ /* if there's no link, create an empty array and link it */
+ if (NULL == notified->link) {
+ notified->link = PR_NEWZAP(_MDNotified);
+ }
+
+ notified = notified->link;
+ }
+
+ /* A brand new entry in the array */
+ notified->cv[index].times = (broadcast) ? -1 : 1;
+ notified->cv[index].cv = cvar;
+ notified->length += 1;
+}
+
+/*
+ * _PR_MD_NEW_CV() -- Creating new condition variable
+ * ... Solaris uses cond_init() in similar function.
+ *
+ * returns: -1 on failure
+ * 0 when it succeeds.
+ *
+ */
+PRInt32
+_PR_MD_NEW_CV(_MDCVar *cv)
+{
+ cv->magic = _MD_MAGIC_CV;
+ /*
+ * The waitHead, waitTail, and nwait fields are zeroed
+ * when the PRCondVar structure is created.
+ */
+ return 0;
+}
+
+void _PR_MD_FREE_CV(_MDCVar *cv)
+{
+ cv->magic = (PRUint32)-1;
+ return;
+}
+
+/*
+ * _PR_MD_WAIT_CV() -- Wait on condition variable
+ */
+void _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
+{
+ PRThread *thred = _PR_MD_CURRENT_THREAD();
+ DWORD rv;
+ DWORD msecs = (timeout == PR_INTERVAL_NO_TIMEOUT) ?
+ INFINITE : PR_IntervalToMilliseconds(timeout);
+
+ /*
+ * If we have pending notifies, post them now.
+ */
+ if (0 != lock->notified.length) {
+ md_UnlockAndPostNotifies(lock, thred, cv);
+ } else {
+ AddThreadToCVWaitQueueInternal(thred, cv);
+ LeaveCriticalSection(&lock->mutex);
+ }
+
+ /* Wait for notification or timeout; don't really care which */
+ rv = WaitForSingleObject(thred->md.blocked_sema, msecs);
+
+ EnterCriticalSection(&(lock->mutex));
+
+ PR_ASSERT(rv != WAIT_ABANDONED);
+ PR_ASSERT(rv != WAIT_FAILED);
+ PR_ASSERT(rv != WAIT_OBJECT_0 || thred->md.inCVWaitQueue == PR_FALSE);
+
+ if (rv == WAIT_TIMEOUT) {
+ if (thred->md.inCVWaitQueue) {
+ PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL)
+ || (cv->waitTail == NULL && cv->waitHead == NULL));
+ cv->nwait -= 1;
+ thred->md.inCVWaitQueue = PR_FALSE;
+ if (cv->waitHead == thred) {
+ cv->waitHead = thred->md.next;
+ if (cv->waitHead == NULL) {
+ cv->waitTail = NULL;
+ } else {
+ cv->waitHead->md.prev = NULL;
+ }
+ } else {
+ PR_ASSERT(thred->md.prev != NULL);
+ thred->md.prev->md.next = thred->md.next;
+ if (thred->md.next != NULL) {
+ thred->md.next->md.prev = thred->md.prev;
+ } else {
+ PR_ASSERT(cv->waitTail == thred);
+ cv->waitTail = thred->md.prev;
+ }
+ }
+ thred->md.next = thred->md.prev = NULL;
+ } else {
+ /*
+ * This thread must have been notified, but the
+ * ReleaseSemaphore call happens after WaitForSingleObject
+ * times out. Wait on the semaphore again to make it
+ * non-signaled. We assume this wait won't take long.
+ */
+ rv = WaitForSingleObject(thred->md.blocked_sema, INFINITE);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+ }
+ PR_ASSERT(thred->md.inCVWaitQueue == PR_FALSE);
+ return;
+} /* --- end _PR_MD_WAIT_CV() --- */
+
+void _PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock)
+{
+ md_PostNotifyToCvar(cv, lock, PR_FALSE);
+ return;
+}
+
+void _PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock)
+{
+ md_PostNotifyToCvar(cv, lock, PR_TRUE);
+ return;
+}
+
+void _PR_MD_UNLOCK(_MDLock *lock)
+{
+ if (0 != lock->notified.length) {
+ md_UnlockAndPostNotifies(lock, NULL, NULL);
+ } else {
+ LeaveCriticalSection(&lock->mutex);
+ }
+ return;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95dllmain.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95dllmain.c
new file mode 100644
index 00000000..1dafe7a2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95dllmain.c
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * The DLL entry point (DllMain) for NSPR.
+ *
+ * This is used to detach threads that were automatically attached by
+ * nspr.
+ */
+
+#include <windows.h>
+#include <primpl.h>
+
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+PRThread *me;
+
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ if (_pr_initialized) {
+ me = _MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ }
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95io.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95io.c
new file mode 100644
index 00000000..5d483cea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95io.c
@@ -0,0 +1,1511 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* Windows 95 IO module
+ *
+ * Assumes synchronous I/O.
+ *
+ */
+
+#include "primpl.h"
+#include <direct.h>
+#include <mbstring.h>
+#ifdef MOZ_UNICODE
+#include <wchar.h>
+#endif /* MOZ_UNICODE */
+
+
+struct _MDLock _pr_ioq_lock;
+
+/*
+ * NSPR-to-NT access right mapping table for files.
+ */
+static DWORD fileAccessTable[] = {
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE
+};
+
+/*
+ * NSPR-to-NT access right mapping table for directories.
+ */
+static DWORD dirAccessTable[] = {
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE|FILE_DELETE_CHILD,
+ FILE_GENERIC_EXECUTE
+};
+
+/*
+ * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME.
+ * We store the value in a PRTime variable for convenience.
+ * This constant is used by _PR_FileTimeToPRTime().
+ */
+#if defined(__MINGW32__)
+static const PRTime _pr_filetime_offset = 116444736000000000LL;
+#else
+static const PRTime _pr_filetime_offset = 116444736000000000i64;
+#endif
+
+#ifdef MOZ_UNICODE
+static void InitUnicodeSupport(void);
+#endif
+
+void
+_PR_MD_INIT_IO()
+{
+ WORD WSAVersion = 0x0101;
+ WSADATA WSAData;
+ int err;
+
+ err = WSAStartup( WSAVersion, &WSAData );
+ PR_ASSERT(0 == err);
+
+#ifdef DEBUG
+ /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */
+ {
+ SYSTEMTIME systime;
+ union {
+ PRTime prt;
+ FILETIME ft;
+ } filetime;
+ BOOL rv;
+
+ systime.wYear = 1970;
+ systime.wMonth = 1;
+ /* wDayOfWeek is ignored */
+ systime.wDay = 1;
+ systime.wHour = 0;
+ systime.wMinute = 0;
+ systime.wSecond = 0;
+ systime.wMilliseconds = 0;
+
+ rv = SystemTimeToFileTime(&systime, &filetime.ft);
+ PR_ASSERT(0 != rv);
+ PR_ASSERT(filetime.prt == _pr_filetime_offset);
+ }
+#endif /* DEBUG */
+
+ _PR_NT_InitSids();
+
+#ifdef MOZ_UNICODE
+ InitUnicodeSupport();
+#endif
+}
+
+PRStatus
+_PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
+{
+ DWORD rv;
+
+ PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
+ INFINITE : PR_IntervalToMilliseconds(ticks);
+ rv = WaitForSingleObject(thread->md.blocked_sema, msecs);
+ switch(rv)
+ {
+ case WAIT_OBJECT_0:
+ return PR_SUCCESS;
+ break;
+ case WAIT_TIMEOUT:
+ _PR_THREAD_LOCK(thread);
+ if (thread->state == _PR_IO_WAIT) {
+ ;
+ } else {
+ if (thread->wait.cvar != NULL) {
+ thread->wait.cvar = NULL;
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* The CVAR was notified just as the timeout
+ * occurred. This led to us being notified twice.
+ * call WaitForSingleObject() to clear the semaphore.
+ */
+ _PR_THREAD_UNLOCK(thread);
+ rv = WaitForSingleObject(thread->md.blocked_sema, 0);
+ PR_ASSERT(rv == WAIT_OBJECT_0);
+ }
+ }
+ return PR_SUCCESS;
+ break;
+ default:
+ return PR_FAILURE;
+ break;
+ }
+}
+PRStatus
+_PR_MD_WAKEUP_WAITER(PRThread *thread)
+{
+ if ( _PR_IS_NATIVE_THREAD(thread) )
+ {
+ if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+ }
+}
+
+
+/* --- FILE IO ----------------------------------------------------------- */
+/*
+ * _PR_MD_OPEN() -- Open a file
+ *
+ * returns: a fileHandle
+ *
+ * The NSPR open flags (osflags) are translated into flags for Win95
+ *
+ * Mode seems to be passed in as a unix style file permissions argument
+ * as in 0666, in the case of opening the logFile.
+ *
+ */
+PRInt32
+_PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
+{
+ HANDLE file;
+ PRInt32 access = 0;
+ PRInt32 flags = 0;
+ PRInt32 flag6 = 0;
+
+ if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH;
+
+ if (osflags & PR_RDONLY || osflags & PR_RDWR)
+ access |= GENERIC_READ;
+ if (osflags & PR_WRONLY || osflags & PR_RDWR)
+ access |= GENERIC_WRITE;
+
+ if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
+ flags = CREATE_NEW;
+ else if (osflags & PR_CREATE_FILE) {
+ if (osflags & PR_TRUNCATE)
+ flags = CREATE_ALWAYS;
+ else
+ flags = OPEN_ALWAYS;
+ } else {
+ if (osflags & PR_TRUNCATE)
+ flags = TRUNCATE_EXISTING;
+ else
+ flags = OPEN_EXISTING;
+ }
+
+ file = CreateFile(name,
+ access,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ flags,
+ flag6,
+ NULL);
+ if (file == INVALID_HANDLE_VALUE) {
+ _PR_MD_MAP_OPEN_ERROR(GetLastError());
+ return -1;
+ }
+
+ return (PRInt32)file;
+}
+
+PRInt32
+_PR_MD_OPEN_FILE(const char *name, PRIntn osflags, int mode)
+{
+ HANDLE file;
+ PRInt32 access = 0;
+ PRInt32 flags = 0;
+ PRInt32 flag6 = 0;
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ if (osflags & PR_CREATE_FILE) {
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ }
+
+ if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH;
+
+ if (osflags & PR_RDONLY || osflags & PR_RDWR)
+ access |= GENERIC_READ;
+ if (osflags & PR_WRONLY || osflags & PR_RDWR)
+ access |= GENERIC_WRITE;
+
+ if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
+ flags = CREATE_NEW;
+ else if (osflags & PR_CREATE_FILE) {
+ if (osflags & PR_TRUNCATE)
+ flags = CREATE_ALWAYS;
+ else
+ flags = OPEN_ALWAYS;
+ } else {
+ if (osflags & PR_TRUNCATE)
+ flags = TRUNCATE_EXISTING;
+ else
+ flags = OPEN_EXISTING;
+ }
+
+ file = CreateFile(name,
+ access,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ lpSA,
+ flags,
+ flag6,
+ NULL);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+ if (file == INVALID_HANDLE_VALUE) {
+ _PR_MD_MAP_OPEN_ERROR(GetLastError());
+ return -1;
+ }
+
+ return (PRInt32)file;
+}
+
+PRInt32
+_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
+{
+ PRUint32 bytes;
+ int rv, err;
+
+ rv = ReadFile((HANDLE)fd->secret->md.osfd,
+ (LPVOID)buf,
+ len,
+ &bytes,
+ NULL);
+
+ if (rv == 0)
+ {
+ err = GetLastError();
+ /* ERROR_HANDLE_EOF can only be returned by async io */
+ PR_ASSERT(err != ERROR_HANDLE_EOF);
+ if (err == ERROR_BROKEN_PIPE)
+ return 0;
+ else {
+ _PR_MD_MAP_READ_ERROR(err);
+ return -1;
+ }
+ }
+ return bytes;
+}
+
+PRInt32
+_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
+{
+ PRInt32 f = fd->secret->md.osfd;
+ PRInt32 bytes;
+ int rv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ rv = WriteFile((HANDLE)f,
+ buf,
+ len,
+ &bytes,
+ NULL );
+
+ if (rv == 0)
+ {
+ _PR_MD_MAP_WRITE_ERROR(GetLastError());
+ return -1;
+ }
+ return bytes;
+} /* --- end _PR_MD_WRITE() --- */
+
+PROffset32
+_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
+{
+ DWORD moveMethod;
+ PROffset32 rv;
+
+ switch (whence) {
+ case PR_SEEK_SET:
+ moveMethod = FILE_BEGIN;
+ break;
+ case PR_SEEK_CUR:
+ moveMethod = FILE_CURRENT;
+ break;
+ case PR_SEEK_END:
+ moveMethod = FILE_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ rv = SetFilePointer((HANDLE)fd->secret->md.osfd, offset, NULL, moveMethod);
+
+ /*
+ * If the lpDistanceToMoveHigh argument (third argument) is
+ * NULL, SetFilePointer returns 0xffffffff on failure.
+ */
+ if (-1 == rv) {
+ _PR_MD_MAP_LSEEK_ERROR(GetLastError());
+ }
+ return rv;
+}
+
+PROffset64
+_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence)
+{
+ DWORD moveMethod;
+ LARGE_INTEGER li;
+ DWORD err;
+
+ switch (whence) {
+ case PR_SEEK_SET:
+ moveMethod = FILE_BEGIN;
+ break;
+ case PR_SEEK_CUR:
+ moveMethod = FILE_CURRENT;
+ break;
+ case PR_SEEK_END:
+ moveMethod = FILE_END;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ li.QuadPart = offset;
+ li.LowPart = SetFilePointer((HANDLE)fd->secret->md.osfd,
+ li.LowPart, &li.HighPart, moveMethod);
+
+ if (0xffffffff == li.LowPart && (err = GetLastError()) != NO_ERROR) {
+ _PR_MD_MAP_LSEEK_ERROR(err);
+ li.QuadPart = -1;
+ }
+ return li.QuadPart;
+}
+
+/*
+ * This is documented to succeed on read-only files, but Win32's
+ * FlushFileBuffers functions fails with "access denied" in such a
+ * case. So we only signal an error if the error is *not* "access
+ * denied".
+ */
+PRInt32
+_PR_MD_FSYNC(PRFileDesc *fd)
+{
+ /*
+ * From the documentation:
+ *
+ * On Windows NT, the function FlushFileBuffers fails if hFile
+ * is a handle to console output. That is because console
+ * output is not buffered. The function returns FALSE, and
+ * GetLastError returns ERROR_INVALID_HANDLE.
+ *
+ * On the other hand, on Win95, it returns without error. I cannot
+ * assume that 0, 1, and 2 are console, because if someone closes
+ * System.out and then opens a file, they might get file descriptor
+ * 1. An error on *that* version of 1 should be reported, whereas
+ * an error on System.out (which was the original 1) should be
+ * ignored. So I use isatty() to ensure that such an error was due
+ * to this bogosity, and if it was, I ignore the error.
+ */
+
+ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd);
+
+ if (!ok) {
+ DWORD err = GetLastError();
+ if (err != ERROR_ACCESS_DENIED) { // from winerror.h
+ _PR_MD_MAP_FSYNC_ERROR(err);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+PRInt32
+_MD_CloseFile(PRInt32 osfd)
+{
+ PRInt32 rv;
+
+ rv = (CloseHandle((HANDLE)osfd))?0:-1;
+ if (rv == -1)
+ _PR_MD_MAP_CLOSE_ERROR(GetLastError());
+ return rv;
+}
+
+
+/* --- DIR IO ------------------------------------------------------------ */
+#define GetFileFromDIR(d) (d)->d_entry.cFileName
+#define FileIsHidden(d) ((d)->d_entry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
+
+void FlipSlashes(char *cp, int len)
+{
+ while (--len >= 0) {
+ if (cp[0] == '/') {
+ cp[0] = PR_DIRECTORY_SEPARATOR;
+ }
+ cp = _mbsinc(cp);
+ }
+} /* end FlipSlashes() */
+
+
+/*
+**
+** Local implementations of standard Unix RTL functions which are not provided
+** by the VC RTL.
+**
+*/
+
+PRStatus
+_PR_MD_CLOSE_DIR(_MDDir *d)
+{
+ if ( d ) {
+ if (FindClose(d->d_hdl)) {
+ d->magic = (PRUint32)-1;
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+}
+
+
+PRStatus
+_PR_MD_OPEN_DIR(_MDDir *d, const char *name)
+{
+ char filename[ MAX_PATH ];
+ int len;
+
+ len = strlen(name);
+ /* Need 5 bytes for \*.* and the trailing null byte. */
+ if (len + 5 > MAX_PATH) {
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
+ return PR_FAILURE;
+ }
+ strcpy(filename, name);
+
+ /*
+ * If 'name' ends in a slash or backslash, do not append
+ * another backslash.
+ */
+ if (filename[len - 1] == '/' || filename[len - 1] == '\\') {
+ len--;
+ }
+ strcpy(&filename[len], "\\*.*");
+ FlipSlashes( filename, strlen(filename) );
+
+ d->d_hdl = FindFirstFile( filename, &(d->d_entry) );
+ if ( d->d_hdl == INVALID_HANDLE_VALUE ) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ d->firstEntry = PR_TRUE;
+ d->magic = _MD_MAGIC_DIR;
+ return PR_SUCCESS;
+}
+
+char *
+_PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
+{
+ PRInt32 err;
+ BOOL rv;
+ char *fileName;
+
+ if ( d ) {
+ while (1) {
+ if (d->firstEntry) {
+ d->firstEntry = PR_FALSE;
+ rv = 1;
+ } else {
+ rv = FindNextFile(d->d_hdl, &(d->d_entry));
+ }
+ if (rv == 0) {
+ break;
+ }
+ fileName = GetFileFromDIR(d);
+ if ( (flags & PR_SKIP_DOT) &&
+ (fileName[0] == '.') && (fileName[1] == '\0'))
+ continue;
+ if ( (flags & PR_SKIP_DOT_DOT) &&
+ (fileName[0] == '.') && (fileName[1] == '.') &&
+ (fileName[2] == '\0'))
+ continue;
+ if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d))
+ continue;
+ return fileName;
+ }
+ err = GetLastError();
+ PR_ASSERT(NO_ERROR != err);
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return NULL;
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+}
+
+PRInt32
+_PR_MD_DELETE(const char *name)
+{
+ if (DeleteFile(name)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_DELETE_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+void
+_PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm)
+{
+ PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime));
+ CopyMemory(prtm, filetime, sizeof(PRTime));
+#if defined(__MINGW32__)
+ *prtm = (*prtm - _pr_filetime_offset) / 10LL;
+#else
+ *prtm = (*prtm - _pr_filetime_offset) / 10i64;
+#endif
+
+#ifdef DEBUG
+ /* Doublecheck our calculation. */
+ {
+ SYSTEMTIME systime;
+ PRExplodedTime etm;
+ PRTime cmp; /* for comparison */
+ BOOL rv;
+
+ rv = FileTimeToSystemTime(filetime, &systime);
+ PR_ASSERT(0 != rv);
+
+ /*
+ * PR_ImplodeTime ignores wday and yday.
+ */
+ etm.tm_usec = systime.wMilliseconds * PR_USEC_PER_MSEC;
+ etm.tm_sec = systime.wSecond;
+ etm.tm_min = systime.wMinute;
+ etm.tm_hour = systime.wHour;
+ etm.tm_mday = systime.wDay;
+ etm.tm_month = systime.wMonth - 1;
+ etm.tm_year = systime.wYear;
+ /*
+ * It is not well-documented what time zone the FILETIME's
+ * are in. WIN32_FIND_DATA is documented to be in UTC (GMT).
+ * But BY_HANDLE_FILE_INFORMATION is unclear about this.
+ * By our best judgement, we assume that FILETIME is in UTC.
+ */
+ etm.tm_params.tp_gmt_offset = 0;
+ etm.tm_params.tp_dst_offset = 0;
+ cmp = PR_ImplodeTime(&etm);
+
+ /*
+ * SYSTEMTIME is in milliseconds precision, so we convert PRTime's
+ * microseconds to milliseconds before doing the comparison.
+ */
+ PR_ASSERT((cmp / PR_USEC_PER_MSEC) == (*prtm / PR_USEC_PER_MSEC));
+ }
+#endif /* DEBUG */
+}
+
+PRInt32
+_PR_MD_STAT(const char *fn, struct stat *info)
+{
+ PRInt32 rv;
+
+ rv = _stat(fn, (struct _stat *)info);
+ if (-1 == rv) {
+ /*
+ * Check for MSVC runtime library _stat() bug.
+ * (It's really a bug in FindFirstFile().)
+ * If a pathname ends in a backslash or slash,
+ * e.g., c:\temp\ or c:/temp/, _stat() will fail.
+ * Note: a pathname ending in a slash (e.g., c:/temp/)
+ * can be handled by _stat() on NT but not on Win95.
+ *
+ * We remove the backslash or slash at the end and
+ * try again.
+ */
+
+ int len = strlen(fn);
+ if (len > 0 && len <= _MAX_PATH
+ && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
+ char newfn[_MAX_PATH + 1];
+
+ strcpy(newfn, fn);
+ newfn[len - 1] = '\0';
+ rv = _stat(newfn, (struct _stat *)info);
+ }
+ }
+
+ if (-1 == rv) {
+ _PR_MD_MAP_STAT_ERROR(errno);
+ }
+ return rv;
+}
+
+#define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\')
+
+/*
+ * IsRootDirectory --
+ *
+ * Return PR_TRUE if the pathname 'fn' is a valid root directory,
+ * else return PR_FALSE. The char buffer pointed to by 'fn' must
+ * be writable. During the execution of this function, the contents
+ * of the buffer pointed to by 'fn' may be modified, but on return
+ * the original contents will be restored. 'buflen' is the size of
+ * the buffer pointed to by 'fn'.
+ *
+ * Root directories come in three formats:
+ * 1. / or \, meaning the root directory of the current drive.
+ * 2. C:/ or C:\, where C is a drive letter.
+ * 3. \\<server name>\<share point name>\ or
+ * \\<server name>\<share point name>, meaning the root directory
+ * of a UNC (Universal Naming Convention) name.
+ */
+
+static PRBool
+IsRootDirectory(char *fn, size_t buflen)
+{
+ char *p;
+ PRBool slashAdded = PR_FALSE;
+ PRBool rv = PR_FALSE;
+
+ if (_PR_IS_SLASH(fn[0]) && fn[1] == '\0') {
+ return PR_TRUE;
+ }
+
+ if (isalpha(fn[0]) && fn[1] == ':' && _PR_IS_SLASH(fn[2])
+ && fn[3] == '\0') {
+ rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE;
+ return rv;
+ }
+
+ /* The UNC root directory */
+
+ if (_PR_IS_SLASH(fn[0]) && _PR_IS_SLASH(fn[1])) {
+ /* The 'server' part should have at least one character. */
+ p = &fn[2];
+ if (*p == '\0' || _PR_IS_SLASH(*p)) {
+ return PR_FALSE;
+ }
+
+ /* look for the next slash */
+ do {
+ p++;
+ } while (*p != '\0' && !_PR_IS_SLASH(*p));
+ if (*p == '\0') {
+ return PR_FALSE;
+ }
+
+ /* The 'share' part should have at least one character. */
+ p++;
+ if (*p == '\0' || _PR_IS_SLASH(*p)) {
+ return PR_FALSE;
+ }
+
+ /* look for the final slash */
+ do {
+ p++;
+ } while (*p != '\0' && !_PR_IS_SLASH(*p));
+ if (_PR_IS_SLASH(*p) && p[1] != '\0') {
+ return PR_FALSE;
+ }
+ if (*p == '\0') {
+ /*
+ * GetDriveType() doesn't work correctly if the
+ * path is of the form \\server\share, so we add
+ * a final slash temporarily.
+ */
+ if ((p + 1) < (fn + buflen)) {
+ *p++ = '\\';
+ *p = '\0';
+ slashAdded = PR_TRUE;
+ } else {
+ return PR_FALSE; /* name too long */
+ }
+ }
+ rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE;
+ /* restore the 'fn' buffer */
+ if (slashAdded) {
+ *--p = '\0';
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
+{
+ HANDLE hFindFile;
+ WIN32_FIND_DATA findFileData;
+ char pathbuf[MAX_PATH + 1];
+
+ if (NULL == fn || '\0' == *fn) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ * FindFirstFile() expands wildcard characters. So
+ * we make sure the pathname contains no wildcard.
+ */
+ if (NULL != _mbspbrk(fn, "?*")) {
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0);
+ return -1;
+ }
+
+ hFindFile = FindFirstFile(fn, &findFileData);
+ if (INVALID_HANDLE_VALUE == hFindFile) {
+ DWORD len;
+ char *filePart;
+
+ /*
+ * FindFirstFile() does not work correctly on root directories.
+ * It also doesn't work correctly on a pathname that ends in a
+ * slash. So we first check to see if the pathname specifies a
+ * root directory. If not, and if the pathname ends in a slash,
+ * we remove the final slash and try again.
+ */
+
+ /*
+ * If the pathname does not contain ., \, and /, it cannot be
+ * a root directory or a pathname that ends in a slash.
+ */
+ if (NULL == _mbspbrk(fn, ".\\/")) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ len = GetFullPathName(fn, sizeof(pathbuf), pathbuf,
+ &filePart);
+ if (0 == len) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ if (len > sizeof(pathbuf)) {
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
+ return -1;
+ }
+ if (IsRootDirectory(pathbuf, sizeof(pathbuf))) {
+ info->type = PR_FILE_DIRECTORY;
+ info->size = 0;
+ /*
+ * These timestamps don't make sense for root directories.
+ */
+ info->modifyTime = 0;
+ info->creationTime = 0;
+ return 0;
+ }
+ if (!_PR_IS_SLASH(pathbuf[len - 1])) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ } else {
+ pathbuf[len - 1] = '\0';
+ hFindFile = FindFirstFile(pathbuf, &findFileData);
+ if (INVALID_HANDLE_VALUE == hFindFile) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ }
+ }
+
+ FindClose(hFindFile);
+
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ info->type = PR_FILE_DIRECTORY;
+ } else {
+ info->type = PR_FILE_FILE;
+ }
+
+ info->size = findFileData.nFileSizeHigh;
+ info->size = (info->size << 32) + findFileData.nFileSizeLow;
+
+ _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime);
+
+ if (0 == findFileData.ftCreationTime.dwLowDateTime &&
+ 0 == findFileData.ftCreationTime.dwHighDateTime) {
+ info->creationTime = info->modifyTime;
+ } else {
+ _PR_FileTimeToPRTime(&findFileData.ftCreationTime,
+ &info->creationTime);
+ }
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
+{
+ PRFileInfo64 info64;
+ PRInt32 rv = _PR_MD_GETFILEINFO64(fn, &info64);
+ if (0 == rv)
+ {
+ info->type = info64.type;
+ info->size = (PRUint32) info64.size;
+ info->modifyTime = info64.modifyTime;
+ info->creationTime = info64.creationTime;
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ int rv;
+
+ BY_HANDLE_FILE_INFORMATION hinfo;
+
+ rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo);
+ if (rv == FALSE) {
+ _PR_MD_MAP_FSTAT_ERROR(GetLastError());
+ return -1;
+ }
+
+ if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_FILE;
+
+ info->size = hinfo.nFileSizeHigh;
+ info->size = (info->size << 32) + hinfo.nFileSizeLow;
+
+ _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime) );
+ _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime) );
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
+{
+ PRFileInfo64 info64;
+ int rv = _PR_MD_GETOPENFILEINFO64(fd, &info64);
+ if (0 == rv)
+ {
+ info->type = info64.type;
+ info->modifyTime = info64.modifyTime;
+ info->creationTime = info64.creationTime;
+ LL_L2I(info->size, info64.size);
+ }
+ return rv;
+}
+
+PRStatus
+_PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
+{
+ BOOL rv;
+
+ /*
+ * The SetHandleInformation function fails with the
+ * ERROR_CALL_NOT_IMPLEMENTED error on Win95.
+ */
+ rv = SetHandleInformation(
+ (HANDLE)fd->secret->md.osfd,
+ HANDLE_FLAG_INHERIT,
+ inheritable ? HANDLE_FLAG_INHERIT : 0);
+ if (0 == rv) {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+void
+_PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported)
+{
+ if (imported) {
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ } else {
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ }
+}
+
+void
+_PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd)
+{
+ DWORD flags;
+
+ PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
+ if (GetHandleInformation((HANDLE)fd->secret->md.osfd, &flags)) {
+ if (flags & HANDLE_FLAG_INHERIT) {
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ } else {
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ }
+ }
+}
+
+PRInt32
+_PR_MD_RENAME(const char *from, const char *to)
+{
+ /* Does this work with dot-relative pathnames? */
+ if (MoveFile(from, to)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_RENAME_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_ACCESS(const char *name, PRAccessHow how)
+{
+PRInt32 rv;
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ rv = _access(name, 02);
+ break;
+ case PR_ACCESS_READ_OK:
+ rv = _access(name, 04);
+ break;
+ case PR_ACCESS_EXISTS:
+ return _access(name, 00);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+ if (rv < 0)
+ _PR_MD_MAP_ACCESS_ERROR(errno);
+ return rv;
+}
+
+PRInt32
+_PR_MD_MKDIR(const char *name, PRIntn mode)
+{
+ /* XXXMB - how to translate the "mode"??? */
+ if (CreateDirectory(name, NULL)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_MKDIR_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_MAKE_DIR(const char *name, PRIntn mode)
+{
+ BOOL rv;
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ rv = CreateDirectory(name, lpSA);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+ if (rv) {
+ return 0;
+ } else {
+ _PR_MD_MAP_MKDIR_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRInt32
+_PR_MD_RMDIR(const char *name)
+{
+ if (RemoveDirectory(name)) {
+ return 0;
+ } else {
+ _PR_MD_MAP_RMDIR_ERROR(GetLastError());
+ return -1;
+ }
+}
+
+PRStatus
+_PR_MD_LOCKFILE(PRInt32 f)
+{
+ PRStatus rc = PR_SUCCESS;
+ DWORD rv;
+
+ rv = LockFile( (HANDLE)f,
+ 0l, 0l,
+ 0x0l, 0xffffffffl );
+ if ( rv == 0 ) {
+ DWORD rc = GetLastError();
+ PR_LOG( _pr_io_lm, PR_LOG_ERROR,
+ ("_PR_MD_LOCKFILE() failed. Error: %d", rc ));
+ rc = PR_FAILURE;
+ }
+
+ return rc;
+} /* end _PR_MD_LOCKFILE() */
+
+PRStatus
+_PR_MD_TLOCKFILE(PRInt32 f)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return PR_FAILURE;
+} /* end _PR_MD_TLOCKFILE() */
+
+
+PRStatus
+_PR_MD_UNLOCKFILE(PRInt32 f)
+{
+ PRInt32 rv;
+
+ rv = UnlockFile( (HANDLE) f,
+ 0l, 0l,
+ 0x0l, 0xffffffffl );
+
+ if ( rv )
+ {
+ return PR_SUCCESS;
+ }
+ else
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+} /* end _PR_MD_UNLOCKFILE() */
+
+PRInt32
+_PR_MD_PIPEAVAILABLE(PRFileDesc *fd)
+{
+ if (NULL == fd)
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+}
+
+#ifdef MOZ_UNICODE
+
+typedef HANDLE (WINAPI *CreateFileWFn) (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
+static CreateFileWFn createFileW = NULL;
+typedef HANDLE (WINAPI *FindFirstFileWFn) (LPCWSTR, LPWIN32_FIND_DATAW);
+static FindFirstFileWFn findFirstFileW = NULL;
+typedef BOOL (WINAPI *FindNextFileWFn) (HANDLE, LPWIN32_FIND_DATAW);
+static FindNextFileWFn findNextFileW = NULL;
+typedef DWORD (WINAPI *GetFullPathNameWFn) (LPCWSTR, DWORD, LPWSTR, LPWSTR *);
+static GetFullPathNameWFn getFullPathNameW = NULL;
+typedef UINT (WINAPI *GetDriveTypeWFn) (LPCWSTR);
+static GetDriveTypeWFn getDriveTypeW = NULL;
+
+static void InitUnicodeSupport(void)
+{
+ HMODULE module;
+
+ /*
+ * The W functions do not exist on Win9x. NSPR won't run on Win9x
+ * if we call the W functions directly. Use GetProcAddress() to
+ * look up their addresses at run time.
+ */
+
+ module = GetModuleHandle("Kernel32.dll");
+ if (!module) {
+ return;
+ }
+
+ createFileW = (CreateFileWFn)GetProcAddress(module, "CreateFileW");
+ findFirstFileW = (FindFirstFileWFn)GetProcAddress(module, "FindFirstFileW");
+ findNextFileW = (FindNextFileWFn)GetProcAddress(module, "FindNextFileW");
+ getDriveTypeW = (GetDriveTypeWFn)GetProcAddress(module, "GetDriveTypeW");
+ getFullPathNameW = (GetFullPathNameWFn)GetProcAddress(module, "GetFullPathNameW");
+}
+
+/* ================ UTF16 Interfaces ================================ */
+void FlipSlashesW(PRUnichar *cp, int len)
+{
+ while (--len >= 0) {
+ if (cp[0] == L'/') {
+ cp[0] = L'\\';
+ }
+ cp++;
+ }
+} /* end FlipSlashesW() */
+
+PRInt32
+_PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, int mode)
+{
+ HANDLE file;
+ PRInt32 access = 0;
+ PRInt32 flags = 0;
+ PRInt32 flag6 = 0;
+ SECURITY_ATTRIBUTES sa;
+ LPSECURITY_ATTRIBUTES lpSA = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ PACL pACL = NULL;
+
+ if (!createFileW) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+ }
+
+ if (osflags & PR_CREATE_FILE) {
+ if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable,
+ &pSD, &pACL) == PR_SUCCESS) {
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = pSD;
+ sa.bInheritHandle = FALSE;
+ lpSA = &sa;
+ }
+ }
+
+ if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH;
+
+ if (osflags & PR_RDONLY || osflags & PR_RDWR)
+ access |= GENERIC_READ;
+ if (osflags & PR_WRONLY || osflags & PR_RDWR)
+ access |= GENERIC_WRITE;
+
+ if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
+ flags = CREATE_NEW;
+ else if (osflags & PR_CREATE_FILE) {
+ if (osflags & PR_TRUNCATE)
+ flags = CREATE_ALWAYS;
+ else
+ flags = OPEN_ALWAYS;
+ } else {
+ if (osflags & PR_TRUNCATE)
+ flags = TRUNCATE_EXISTING;
+ else
+ flags = OPEN_EXISTING;
+ }
+
+ file = createFileW(name,
+ access,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ lpSA,
+ flags,
+ flag6,
+ NULL);
+ if (lpSA != NULL) {
+ _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
+ }
+ if (file == INVALID_HANDLE_VALUE) {
+ _PR_MD_MAP_OPEN_ERROR(GetLastError());
+ return -1;
+ }
+
+ return (PRInt32)file;
+}
+
+PRStatus
+_PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *d, const PRUnichar *name)
+{
+ PRUnichar filename[ MAX_PATH ];
+ int len;
+
+ if (!findFirstFileW) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ len = wcslen(name);
+ /* Need 5 bytes for \*.* and the trailing null byte. */
+ if (len + 5 > MAX_PATH) {
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
+ return PR_FAILURE;
+ }
+ wcscpy(filename, name);
+
+ /*
+ * If 'name' ends in a slash or backslash, do not append
+ * another backslash.
+ */
+ if (filename[len - 1] == L'/' || filename[len - 1] == L'\\') {
+ len--;
+ }
+ wcscpy(&filename[len], L"\\*.*");
+ FlipSlashesW( filename, wcslen(filename) );
+
+ d->d_hdl = findFirstFileW( filename, &(d->d_entry) );
+ if ( d->d_hdl == INVALID_HANDLE_VALUE ) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ d->firstEntry = PR_TRUE;
+ d->magic = _MD_MAGIC_DIR;
+ return PR_SUCCESS;
+}
+
+PRUnichar *
+_PR_MD_READ_DIR_UTF16(_MDDirUTF16 *d, PRIntn flags)
+{
+ PRInt32 err;
+ BOOL rv;
+ PRUnichar *fileName;
+
+ if (!findNextFileW) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+ }
+
+ if ( d ) {
+ while (1) {
+ if (d->firstEntry) {
+ d->firstEntry = PR_FALSE;
+ rv = 1;
+ } else {
+ rv = findNextFileW(d->d_hdl, &(d->d_entry));
+ }
+ if (rv == 0) {
+ break;
+ }
+ fileName = GetFileFromDIR(d);
+ if ( (flags & PR_SKIP_DOT) &&
+ (fileName[0] == L'.') && (fileName[1] == L'\0'))
+ continue;
+ if ( (flags & PR_SKIP_DOT_DOT) &&
+ (fileName[0] == L'.') && (fileName[1] == L'.') &&
+ (fileName[2] == L'\0'))
+ continue;
+ if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d))
+ continue;
+ return fileName;
+ }
+ err = GetLastError();
+ PR_ASSERT(NO_ERROR != err);
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return NULL;
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+}
+
+PRStatus
+_PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *d)
+{
+ if ( d ) {
+ if (FindClose(d->d_hdl)) {
+ d->magic = (PRUint32)-1;
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError());
+ return PR_FAILURE;
+ }
+ }
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+}
+
+#define _PR_IS_W_SLASH(ch) ((ch) == L'/' || (ch) == L'\\')
+
+/*
+ * IsRootDirectoryW --
+ *
+ * Return PR_TRUE if the pathname 'fn' is a valid root directory,
+ * else return PR_FALSE. The PRUnichar buffer pointed to by 'fn' must
+ * be writable. During the execution of this function, the contents
+ * of the buffer pointed to by 'fn' may be modified, but on return
+ * the original contents will be restored. 'buflen' is the size of
+ * the buffer pointed to by 'fn', in PRUnichars.
+ *
+ * Root directories come in three formats:
+ * 1. / or \, meaning the root directory of the current drive.
+ * 2. C:/ or C:\, where C is a drive letter.
+ * 3. \\<server name>\<share point name>\ or
+ * \\<server name>\<share point name>, meaning the root directory
+ * of a UNC (Universal Naming Convention) name.
+ */
+
+static PRBool
+IsRootDirectoryW(PRUnichar *fn, size_t buflen)
+{
+ PRUnichar *p;
+ PRBool slashAdded = PR_FALSE;
+ PRBool rv = PR_FALSE;
+
+ if (_PR_IS_W_SLASH(fn[0]) && fn[1] == L'\0') {
+ return PR_TRUE;
+ }
+
+ if (iswalpha(fn[0]) && fn[1] == L':' && _PR_IS_W_SLASH(fn[2])
+ && fn[3] == L'\0') {
+ rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE;
+ return rv;
+ }
+
+ /* The UNC root directory */
+
+ if (_PR_IS_W_SLASH(fn[0]) && _PR_IS_W_SLASH(fn[1])) {
+ /* The 'server' part should have at least one character. */
+ p = &fn[2];
+ if (*p == L'\0' || _PR_IS_W_SLASH(*p)) {
+ return PR_FALSE;
+ }
+
+ /* look for the next slash */
+ do {
+ p++;
+ } while (*p != L'\0' && !_PR_IS_W_SLASH(*p));
+ if (*p == L'\0') {
+ return PR_FALSE;
+ }
+
+ /* The 'share' part should have at least one character. */
+ p++;
+ if (*p == L'\0' || _PR_IS_W_SLASH(*p)) {
+ return PR_FALSE;
+ }
+
+ /* look for the final slash */
+ do {
+ p++;
+ } while (*p != L'\0' && !_PR_IS_W_SLASH(*p));
+ if (_PR_IS_W_SLASH(*p) && p[1] != L'\0') {
+ return PR_FALSE;
+ }
+ if (*p == L'\0') {
+ /*
+ * GetDriveType() doesn't work correctly if the
+ * path is of the form \\server\share, so we add
+ * a final slash temporarily.
+ */
+ if ((p + 1) < (fn + buflen)) {
+ *p++ = L'\\';
+ *p = L'\0';
+ slashAdded = PR_TRUE;
+ } else {
+ return PR_FALSE; /* name too long */
+ }
+ }
+ rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE;
+ /* restore the 'fn' buffer */
+ if (slashAdded) {
+ *--p = L'\0';
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info)
+{
+ HANDLE hFindFile;
+ WIN32_FIND_DATAW findFileData;
+ PRUnichar pathbuf[MAX_PATH + 1];
+
+ if (!findFirstFileW || !getFullPathNameW || !getDriveTypeW) {
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return -1;
+ }
+
+ if (NULL == fn || L'\0' == *fn) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+
+ /*
+ * FindFirstFile() expands wildcard characters. So
+ * we make sure the pathname contains no wildcard.
+ */
+ if (NULL != wcspbrk(fn, L"?*")) {
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0);
+ return -1;
+ }
+
+ hFindFile = findFirstFileW(fn, &findFileData);
+ if (INVALID_HANDLE_VALUE == hFindFile) {
+ DWORD len;
+ PRUnichar *filePart;
+
+ /*
+ * FindFirstFile() does not work correctly on root directories.
+ * It also doesn't work correctly on a pathname that ends in a
+ * slash. So we first check to see if the pathname specifies a
+ * root directory. If not, and if the pathname ends in a slash,
+ * we remove the final slash and try again.
+ */
+
+ /*
+ * If the pathname does not contain ., \, and /, it cannot be
+ * a root directory or a pathname that ends in a slash.
+ */
+ if (NULL == wcspbrk(fn, L".\\/")) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ len = getFullPathNameW(fn, sizeof(pathbuf)/sizeof(pathbuf[0]), pathbuf,
+ &filePart);
+ if (0 == len) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ if (len > sizeof(pathbuf)/sizeof(pathbuf[0])) {
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
+ return -1;
+ }
+ if (IsRootDirectoryW(pathbuf, sizeof(pathbuf)/sizeof(pathbuf[0]))) {
+ info->type = PR_FILE_DIRECTORY;
+ info->size = 0;
+ /*
+ * These timestamps don't make sense for root directories.
+ */
+ info->modifyTime = 0;
+ info->creationTime = 0;
+ return 0;
+ }
+ if (!_PR_IS_W_SLASH(pathbuf[len - 1])) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ } else {
+ pathbuf[len - 1] = L'\0';
+ hFindFile = findFirstFileW(pathbuf, &findFileData);
+ if (INVALID_HANDLE_VALUE == hFindFile) {
+ _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
+ return -1;
+ }
+ }
+ }
+
+ FindClose(hFindFile);
+
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ info->type = PR_FILE_DIRECTORY;
+ } else {
+ info->type = PR_FILE_FILE;
+ }
+
+ info->size = findFileData.nFileSizeHigh;
+ info->size = (info->size << 32) + findFileData.nFileSizeLow;
+
+ _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime);
+
+ if (0 == findFileData.ftCreationTime.dwLowDateTime &&
+ 0 == findFileData.ftCreationTime.dwHighDateTime) {
+ info->creationTime = info->modifyTime;
+ } else {
+ _PR_FileTimeToPRTime(&findFileData.ftCreationTime,
+ &info->creationTime);
+ }
+
+ return 0;
+}
+/* ================ end of UTF16 Interfaces ================================ */
+#endif /* MOZ_UNICODE */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95sock.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95sock.c
new file mode 100644
index 00000000..01c25258
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95sock.c
@@ -0,0 +1,658 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* Win95 Sockets module
+ *
+ */
+
+#include "primpl.h"
+
+#define READ_FD 1
+#define WRITE_FD 2
+#define CONNECT_FD 3
+
+static PRInt32 socket_io_wait(
+ PRInt32 osfd,
+ PRInt32 fd_type,
+ PRIntervalTime timeout);
+
+
+/* --- SOCKET IO --------------------------------------------------------- */
+
+
+PRInt32
+_PR_MD_SOCKET(int af, int type, int flags)
+{
+ SOCKET sock;
+ u_long one = 1;
+
+ sock = socket(af, type, flags);
+
+ if (sock == INVALID_SOCKET )
+ {
+ _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
+ return (PRInt32)sock;
+ }
+
+ /*
+ ** Make the socket Non-Blocking
+ */
+ if (ioctlsocket( sock, FIONBIO, &one) != 0)
+ {
+ PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError());
+ closesocket(sock);
+ return -1;
+ }
+
+ return (PRInt32)sock;
+}
+
+/*
+** _MD_CloseSocket() -- Close a socket
+**
+*/
+PRInt32
+_MD_CloseSocket(PRInt32 osfd)
+{
+ PRInt32 rv;
+
+ rv = closesocket((SOCKET) osfd );
+ if (rv < 0)
+ _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
+
+ return rv;
+}
+
+PRInt32
+_MD_SocketAvailable(PRFileDesc *fd)
+{
+ PRInt32 result;
+
+ if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
+ return -1;
+ }
+ return result;
+}
+
+PRInt32 _MD_Accept(
+ PRFileDesc *fd,
+ PRNetAddr *raddr,
+ PRUint32 *rlen,
+ PRIntervalTime timeout )
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+
+ while ((rv = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1)
+ {
+ err = WSAGetLastError();
+ if ((err == WSAEWOULDBLOCK) && (!fd->secret->nonblocking))
+ {
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ {
+ return(-1);
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ break;
+ }
+ }
+ return(rv);
+} /* end _MD_accept() */
+
+PRInt32
+_PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv;
+ int err;
+
+ if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1)
+ {
+ err = WSAGetLastError();
+ if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK))
+ {
+ rv = socket_io_wait(osfd, CONNECT_FD, timeout);
+ if ( rv < 0 )
+ {
+ return(-1);
+ }
+ else
+ {
+ PR_ASSERT(rv > 0);
+ /* it's connected */
+ return(0);
+ }
+ }
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+ return rv;
+}
+
+PRInt32
+_PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv;
+
+ rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen);
+
+ if (rv == SOCKET_ERROR) {
+ _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+
+ if (rv == SOCKET_ERROR) {
+ _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
+
+PRInt32
+_PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ int osflags;
+
+ if (0 == flags) {
+ osflags = 0;
+ } else {
+ PR_ASSERT(PR_MSG_PEEK == flags);
+ osflags = MSG_PEEK;
+ }
+ while ((rv = recv( osfd, buf, amount, osflags)) == -1)
+ {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking))
+ {
+ rv = socket_io_wait(osfd, READ_FD, timeout);
+ if ( rv < 0 )
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_RECV_ERROR(err);
+ break;
+ }
+ } /* end while() */
+ return(rv);
+}
+
+PRInt32
+_PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRInt32 bytesSent = 0;
+
+ while(bytesSent < amount )
+ {
+ while ((rv = send( osfd, buf, amount, 0 )) == -1)
+ {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking))
+ {
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 )
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_SEND_ERROR(err);
+ return -1;
+ }
+ }
+ bytesSent += rv;
+ if (fd->secret->nonblocking)
+ {
+ break;
+ }
+ if (bytesSent < amount)
+ {
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 )
+ {
+ return -1;
+ }
+ }
+ }
+ return bytesSent;
+}
+
+PRInt32
+_PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRInt32 bytesSent = 0;
+
+ while(bytesSent < amount)
+ {
+ while ((rv = sendto( osfd, buf, amount, 0, (struct sockaddr *) addr,
+ addrlen)) == -1)
+ {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking))
+ {
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if ( rv < 0 )
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ return -1;
+ }
+ }
+ bytesSent += rv;
+ if (fd->secret->nonblocking)
+ {
+ break;
+ }
+ if (bytesSent < amount)
+ {
+ rv = socket_io_wait(osfd, WRITE_FD, timeout);
+ if (rv < 0)
+ {
+ return -1;
+ }
+ }
+ }
+ return bytesSent;
+}
+
+PRInt32
+_PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+
+ while ((rv = recvfrom( osfd, buf, amount, 0, (struct sockaddr *) addr,
+ addrlen)) == -1)
+ {
+ if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
+ && (!fd->secret->nonblocking))
+ {
+ rv = socket_io_wait(osfd, READ_FD, timeout);
+ if ( rv < 0)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ break;
+ }
+ }
+ return(rv);
+}
+
+PRInt32
+_PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
+{
+ int index;
+ int sent = 0;
+ int rv;
+
+ for (index=0; index < iov_size; index++)
+ {
+ rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
+ if (rv > 0)
+ sent += rv;
+ if ( rv != iov[index].iov_len )
+ {
+ if (rv < 0)
+ {
+ if (fd->secret->nonblocking
+ && (PR_GetError() == PR_WOULD_BLOCK_ERROR)
+ && (sent > 0))
+ {
+ return sent;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ /* Only a nonblocking socket can have partial sends */
+ PR_ASSERT(fd->secret->nonblocking);
+ return sent;
+ }
+ }
+ return sent;
+}
+
+PRInt32
+_PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how)
+{
+PRInt32 rv;
+
+ rv = shutdown(fd->secret->md.osfd, how);
+ if (rv < 0)
+ _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
+ return rv;
+}
+
+PRStatus
+_PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+{
+ PRInt32 rv;
+
+ rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len)
+{
+ PRInt32 rv;
+
+ rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len);
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ PRInt32 rv;
+
+ rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+PRStatus
+_PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv;
+
+ rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv==0) {
+ return PR_SUCCESS;
+ } else {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
+ return PR_FAILURE;
+ }
+}
+
+void
+_MD_MakeNonblock(PRFileDesc *f)
+{
+ return; /* do nothing */
+}
+
+
+
+/*
+ * socket_io_wait --
+ *
+ * Wait for socket i/o, periodically checking for interrupt.
+ *
+ * This function returns 1 on success. On failure, it returns
+ * -1 and sets the error codes. It never returns 0.
+ */
+#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5
+
+static PRInt32 socket_io_wait(
+ PRInt32 osfd,
+ PRInt32 fd_type,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+ struct timeval tv;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime elapsed, remaining;
+ PRBool wait_for_remaining;
+ fd_set rd_wr, ex;
+ int err, len;
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ FD_ZERO(&rd_wr);
+ FD_ZERO(&ex);
+ do {
+ FD_SET(osfd, &rd_wr);
+ FD_SET(osfd, &ex);
+ switch( fd_type )
+ {
+ case READ_FD:
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ break;
+ case WRITE_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ break;
+ case CONNECT_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, &ex, &tv);
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ } /* end switch() */
+ if (rv == -1 )
+ {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ }
+ if ( rv > 0 && fd_type == CONNECT_FD )
+ {
+ /*
+ * Call Sleep(0) to work around a Winsock timing bug.
+ */
+ Sleep(0);
+ if (FD_ISSET((SOCKET)osfd, &ex))
+ {
+ len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
+ (char *) &err, &len) == SOCKET_ERROR)
+ {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (err != 0)
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ else
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ if (FD_ISSET((SOCKET)osfd, &rd_wr))
+ {
+ /* it's connected */
+ return 1;
+ }
+ PR_ASSERT(0);
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ } while (rv == 0);
+ break;
+ default:
+ remaining = timeout;
+ FD_ZERO(&rd_wr);
+ FD_ZERO(&ex);
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+ wait_for_remaining = PR_TRUE;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ wait_for_remaining = PR_FALSE;
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ FD_SET(osfd, &ex);
+ switch( fd_type )
+ {
+ case READ_FD:
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv);
+ break;
+ case WRITE_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv);
+ break;
+ case CONNECT_FD:
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, &ex, &tv);
+ break;
+ default:
+ PR_ASSERT(0);
+ break;
+ } /* end switch() */
+ if (rv == -1)
+ {
+ _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
+ break;
+ }
+ if ( rv > 0 && fd_type == CONNECT_FD )
+ {
+ /*
+ * Call Sleep(0) to work around a Winsock timing bug.
+ */
+ Sleep(0);
+ if (FD_ISSET((SOCKET)osfd, &ex))
+ {
+ len = sizeof(err);
+ if (getsockopt(osfd, SOL_SOCKET, SO_ERROR,
+ (char *) &err, &len) == SOCKET_ERROR)
+ {
+ _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
+ return -1;
+ }
+ if (err != 0)
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ else
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return -1;
+ }
+ if (FD_ISSET((SOCKET)osfd, &rd_wr))
+ {
+ /* it's connected */
+ return 1;
+ }
+ PR_ASSERT(0);
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if _MD_SELECT timed out and the
+ * timeout deadline has not passed yet.
+ */
+ if (rv == 0 )
+ {
+ if (wait_for_remaining) {
+ elapsed = remaining;
+ } else {
+ elapsed = PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ }
+ if (elapsed >= remaining) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = remaining - elapsed;
+ }
+ }
+ } while (rv == 0 );
+ break;
+ }
+ return(rv);
+} /* end socket_io_wait() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95thred.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95thred.c
new file mode 100644
index 00000000..8671d825
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/w95thred.c
@@ -0,0 +1,295 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <process.h> /* for _beginthreadex() */
+
+extern void _PR_Win32InitTimeZone(void); /* defined in ntmisc.c */
+
+/* --- globals ------------------------------------------------ */
+#ifdef _PR_USE_STATIC_TLS
+__declspec(thread) struct PRThread *_pr_thread_last_run;
+__declspec(thread) struct PRThread *_pr_currentThread;
+__declspec(thread) struct _PRCPU *_pr_currentCPU;
+#else
+DWORD _pr_currentThreadIndex;
+DWORD _pr_lastThreadIndex;
+DWORD _pr_currentCPUIndex;
+#endif
+int _pr_intsOff = 0;
+_PRInterruptTable _pr_interruptTable[] = { { 0 } };
+
+void
+_PR_MD_EARLY_INIT()
+{
+ _PR_Win32InitTimeZone();
+
+#ifndef _PR_USE_STATIC_TLS
+ _pr_currentThreadIndex = TlsAlloc();
+ _pr_lastThreadIndex = TlsAlloc();
+ _pr_currentCPUIndex = TlsAlloc();
+#endif
+}
+
+void _PR_MD_CLEANUP_BEFORE_EXIT(void)
+{
+ _PR_NT_FreeSids();
+
+ WSACleanup();
+
+#ifndef _PR_USE_STATIC_TLS
+ TlsFree(_pr_currentThreadIndex);
+ TlsFree(_pr_lastThreadIndex);
+ TlsFree(_pr_currentCPUIndex);
+#endif
+}
+
+PRStatus
+_PR_MD_INIT_THREAD(PRThread *thread)
+{
+ if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
+ /*
+ ** Warning:
+ ** --------
+ ** NSPR requires a real handle to every thread.
+ ** GetCurrentThread() returns a pseudo-handle which
+ ** is not suitable for some thread operations (e.g.,
+ ** suspending). Therefore, get a real handle from
+ ** the pseudo handle via DuplicateHandle(...)
+ */
+ DuplicateHandle(
+ GetCurrentProcess(), /* Process of source handle */
+ GetCurrentThread(), /* Pseudo Handle to dup */
+ GetCurrentProcess(), /* Process of handle */
+ &(thread->md.handle), /* resulting handle */
+ 0L, /* access flags */
+ FALSE, /* Inheritable */
+ DUPLICATE_SAME_ACCESS); /* Options */
+ }
+
+ /* Create the blocking IO semaphore */
+ thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL);
+ if (thread->md.blocked_sema == NULL)
+ return PR_FAILURE;
+ else
+ return PR_SUCCESS;
+}
+
+static unsigned __stdcall
+pr_root(void *arg)
+{
+ PRThread *thread = (PRThread *)arg;
+ thread->md.start(thread);
+ return 0;
+}
+
+PRStatus
+_PR_MD_CREATE_THREAD(PRThread *thread,
+ void (*start)(void *),
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+
+ thread->md.start = start;
+ thread->md.handle = (HANDLE) _beginthreadex(
+ NULL,
+ thread->stack->stackSize,
+ pr_root,
+ (void *)thread,
+ CREATE_SUSPENDED,
+ &(thread->id));
+ if(!thread->md.handle) {
+ return PR_FAILURE;
+ }
+
+ thread->md.id = thread->id;
+ /*
+ * On windows, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL.
+ */
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
+
+ /* Activate the thread */
+ if ( ResumeThread( thread->md.handle ) != -1)
+ return PR_SUCCESS;
+
+ return PR_FAILURE;
+}
+
+void
+_PR_MD_YIELD(void)
+{
+ /* Can NT really yield at all? */
+ Sleep(0);
+}
+
+void
+_PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri)
+{
+ int nativePri;
+ BOOL rv;
+
+ if (newPri < PR_PRIORITY_FIRST) {
+ newPri = PR_PRIORITY_FIRST;
+ } else if (newPri > PR_PRIORITY_LAST) {
+ newPri = PR_PRIORITY_LAST;
+ }
+ switch (newPri) {
+ case PR_PRIORITY_LOW:
+ nativePri = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+ case PR_PRIORITY_NORMAL:
+ nativePri = THREAD_PRIORITY_NORMAL;
+ break;
+ case PR_PRIORITY_HIGH:
+ nativePri = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case PR_PRIORITY_URGENT:
+ nativePri = THREAD_PRIORITY_HIGHEST;
+ }
+ rv = SetThreadPriority(thread->handle, nativePri);
+ PR_ASSERT(rv);
+ if (!rv) {
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("PR_SetThreadPriority: can't set thread priority\n"));
+ }
+ return;
+}
+
+void
+_PR_MD_CLEAN_THREAD(PRThread *thread)
+{
+ BOOL rv;
+
+ if (thread->md.blocked_sema) {
+ rv = CloseHandle(thread->md.blocked_sema);
+ PR_ASSERT(rv);
+ thread->md.blocked_sema = 0;
+ }
+
+ if (thread->md.handle) {
+ rv = CloseHandle(thread->md.handle);
+ PR_ASSERT(rv);
+ thread->md.handle = 0;
+ }
+}
+
+void
+_PR_MD_EXIT_THREAD(PRThread *thread)
+{
+ _PR_MD_CLEAN_THREAD(thread);
+ _PR_MD_SET_CURRENT_THREAD(NULL);
+}
+
+
+void
+_PR_MD_EXIT(PRIntn status)
+{
+ _exit(status);
+}
+
+PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
+{
+ int rv;
+
+ rv = SetThreadAffinityMask(thread->md.handle, mask);
+
+ return rv?0:-1;
+}
+
+PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
+{
+ PRInt32 rv, system_mask;
+
+ rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);
+
+ return rv?0:-1;
+}
+
+void
+_PR_MD_SUSPEND_CPU(_PRCPU *cpu)
+{
+ _PR_MD_SUSPEND_THREAD(cpu->thread);
+}
+
+void
+_PR_MD_RESUME_CPU(_PRCPU *cpu)
+{
+ _PR_MD_RESUME_THREAD(cpu->thread);
+}
+
+void
+_PR_MD_SUSPEND_THREAD(PRThread *thread)
+{
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ DWORD previousSuspendCount;
+ /* XXXMB - SuspendThread() is not a blocking call; how do we
+ * know when the thread is *REALLY* suspended?
+ */
+ previousSuspendCount = SuspendThread(thread->md.handle);
+ PR_ASSERT(previousSuspendCount == 0);
+ }
+}
+
+void
+_PR_MD_RESUME_THREAD(PRThread *thread)
+{
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ DWORD previousSuspendCount;
+ previousSuspendCount = ResumeThread(thread->md.handle);
+ PR_ASSERT(previousSuspendCount == 1);
+ }
+}
+
+PRThread*
+_MD_CURRENT_THREAD(void)
+{
+PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(
+ PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+ PR_ASSERT(thread != NULL);
+ return thread;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/win32_errors.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/win32_errors.c
new file mode 100644
index 00000000..0cf1bb58
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/windows/win32_errors.c
@@ -0,0 +1,562 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prerror.h"
+#include "prlog.h"
+#include <errno.h>
+#include <windows.h>
+
+/*
+ * On Win32, we map three kinds of error codes:
+ * - GetLastError(): for Win32 functions
+ * - WSAGetLastError(): for Winsock functions
+ * - errno: for standard C library functions
+ *
+ * GetLastError() and WSAGetLastError() return error codes in
+ * non-overlapping ranges, so their error codes (ERROR_* and
+ * WSAE*) can be mapped by the same function. On the other hand,
+ * errno and GetLastError() have overlapping ranges, so we need
+ * to use a separate function to map errno.
+ *
+ * We do not check for WSAEINPROGRESS and WSAEINTR because we do not
+ * use blocking Winsock 1.1 calls.
+ *
+ * Except for the 'socket' call, we do not check for WSAEINITIALISED.
+ * It is assumed that if Winsock is not initialized, that fact will
+ * be detected at the time we create new sockets.
+ */
+
+static void _MD_win32_map_default_errno(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case EACCES:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ENOENT:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ default:
+ prError = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_default_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case ERROR_ACCESS_DENIED:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case ERROR_ALREADY_EXISTS:
+ prError = PR_FILE_EXISTS_ERROR;
+ break;
+ case ERROR_DISK_CORRUPT:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_DISK_FULL:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+ case ERROR_DISK_OPERATION_FAILED:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_DRIVE_LOCKED:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case ERROR_FILENAME_EXCED_RANGE:
+ prError = PR_NAME_TOO_LONG_ERROR;
+ break;
+ case ERROR_FILE_CORRUPT:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_FILE_EXISTS:
+ prError = PR_FILE_EXISTS_ERROR;
+ break;
+ case ERROR_FILE_INVALID:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ prError = PR_NO_DEVICE_SPACE_ERROR;
+ break;
+ case ERROR_INVALID_ADDRESS:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ERROR_INVALID_HANDLE:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case ERROR_INVALID_NAME:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ERROR_INVALID_USER_BUFFER:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ERROR_LOCKED:
+ prError = PR_FILE_IS_LOCKED_ERROR;
+ break;
+ case ERROR_NETNAME_DELETED:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+ case ERROR_NOACCESS:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ERROR_NOT_ENOUGH_QUOTA:
+ prError = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case ERROR_NOT_READY:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_NO_MORE_FILES:
+ prError = PR_NO_MORE_FILES_ERROR;
+ break;
+ case ERROR_OPEN_FAILED:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_OPEN_FILES:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_OPERATION_ABORTED:
+ prError = PR_OPERATION_ABORTED_ERROR;
+ break;
+ case ERROR_OUTOFMEMORY:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case ERROR_PATH_BUSY:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ prError = PR_FILE_NOT_FOUND_ERROR;
+ break;
+ case ERROR_SEEK_ON_DEVICE:
+ prError = PR_IO_ERROR;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ prError = PR_FILE_IS_BUSY_ERROR;
+ break;
+ case ERROR_STACK_OVERFLOW:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ prError = PR_SYS_DESC_TABLE_FULL_ERROR;
+ break;
+ case ERROR_WRITE_PROTECT:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case WSAEACCES:
+ prError = PR_NO_ACCESS_RIGHTS_ERROR;
+ break;
+ case WSAEADDRINUSE:
+ prError = PR_ADDRESS_IN_USE_ERROR;
+ break;
+ case WSAEADDRNOTAVAIL:
+ prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
+ break;
+ case WSAEAFNOSUPPORT:
+ prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
+ break;
+ case WSAEALREADY:
+ prError = PR_ALREADY_INITIATED_ERROR;
+ break;
+ case WSAEBADF:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ case WSAECONNABORTED:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case WSAECONNREFUSED:
+ prError = PR_CONNECT_REFUSED_ERROR;
+ break;
+ case WSAECONNRESET:
+ prError = PR_CONNECT_RESET_ERROR;
+ break;
+ case WSAEDESTADDRREQ:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAEFAULT:
+ prError = PR_ACCESS_FAULT_ERROR;
+ break;
+ case WSAEHOSTUNREACH:
+ prError = PR_HOST_UNREACHABLE_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAEISCONN:
+ prError = PR_IS_CONNECTED_ERROR;
+ break;
+ case WSAEMFILE:
+ prError = PR_PROC_DESC_TABLE_FULL_ERROR;
+ break;
+ case WSAEMSGSIZE:
+ prError = PR_BUFFER_OVERFLOW_ERROR;
+ break;
+ case WSAENETDOWN:
+ prError = PR_NETWORK_DOWN_ERROR;
+ break;
+ case WSAENETRESET:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case WSAENETUNREACH:
+ prError = PR_NETWORK_UNREACHABLE_ERROR;
+ break;
+ case WSAENOBUFS:
+ prError = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case WSAENOPROTOOPT:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAENOTCONN:
+ prError = PR_NOT_CONNECTED_ERROR;
+ break;
+ case WSAENOTSOCK:
+ prError = PR_NOT_SOCKET_ERROR;
+ break;
+ case WSAEOPNOTSUPP:
+ prError = PR_OPERATION_NOT_SUPPORTED_ERROR;
+ break;
+ case WSAEPROTONOSUPPORT:
+ prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
+ break;
+ case WSAEPROTOTYPE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAESHUTDOWN:
+ prError = PR_SOCKET_SHUTDOWN_ERROR;
+ break;
+ case WSAESOCKTNOSUPPORT:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case WSAETIMEDOUT:
+ prError = PR_CONNECT_ABORTED_ERROR;
+ break;
+ case WSAEWOULDBLOCK:
+ prError = PR_WOULD_BLOCK_ERROR;
+ break;
+ default:
+ prError = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_opendir_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_closedir_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_unix_readdir_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_delete_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+/* The error code for stat() is in errno. */
+void _MD_win32_map_stat_error(PRInt32 err)
+{
+ _MD_win32_map_default_errno(err);
+}
+
+void _MD_win32_map_fstat_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_rename_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+/* The error code for access() is in errno. */
+void _MD_win32_map_access_error(PRInt32 err)
+{
+ _MD_win32_map_default_errno(err);
+}
+
+void _MD_win32_map_mkdir_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_rmdir_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_read_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_transmitfile_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_write_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_lseek_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_fsync_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+/*
+ * For both CloseHandle() and closesocket().
+ */
+void _MD_win32_map_close_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_socket_error(PRInt32 err)
+{
+ PR_ASSERT(err != WSANOTINITIALISED);
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_recv_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_recvfrom_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_send_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEMSGSIZE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_sendto_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEMSGSIZE:
+ prError = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_accept_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEOPNOTSUPP:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_INVALID_STATE_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_acceptex_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_connect_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEWOULDBLOCK:
+ prError = PR_IN_PROGRESS_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_ALREADY_INITIATED_ERROR;
+ break;
+ case WSAETIMEDOUT:
+ prError = PR_IO_TIMEOUT_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_bind_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEINVAL:
+ prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_listen_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEOPNOTSUPP:
+ prError = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ case WSAEINVAL:
+ prError = PR_INVALID_STATE_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_shutdown_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_getsockname_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAEINVAL:
+ prError = PR_INVALID_STATE_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_getpeername_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_getsockopt_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_setsockopt_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_open_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+void _MD_win32_map_gethostname_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
+
+/* Win32 select() only works on sockets. So in this
+** context, WSAENOTSOCK is equivalent to EBADF on Unix.
+*/
+void _MD_win32_map_select_error(PRInt32 err)
+{
+ PRErrorCode prError;
+
+ switch (err) {
+ case WSAENOTSOCK:
+ prError = PR_BAD_DESCRIPTOR_ERROR;
+ break;
+ default:
+ _MD_win32_map_default_error(err);
+ return;
+ }
+ PR_SetError(prError, err);
+}
+
+void _MD_win32_map_lockf_error(PRInt32 err)
+{
+ _MD_win32_map_default_error(err);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/memory/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/memory/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/memory/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/memory/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/memory/Makefile.in
new file mode 100644
index 00000000..6ba0ba78
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/memory/Makefile.in
@@ -0,0 +1,69 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+CSRCS = prseg.c prshm.c prshma.c
+
+ifdef GC_LEAK_DETECTOR
+CSRCS += prgcleak.c
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+ifdef GC_LEAK_DETECTOR
+INCLUDES += -I$(dist_includedir)/.. -I$(dist_includedir)/../boehm
+endif
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/memory/prgcleak.c b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prgcleak.c
new file mode 100644
index 00000000..414b3851
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prgcleak.c
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Beard <beard@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+/*
+ * prgcleak.c
+ */
+
+#ifdef GC_LEAK_DETECTOR
+
+/* for FILE */
+#include <stdio.h>
+
+/* NSPR stuff */
+#include "generic_threads.h"
+#include "primpl.h"
+
+extern FILE *GC_stdout, *GC_stderr;
+
+extern void GC_gcollect(void);
+extern void GC_clear_roots(void);
+
+static PRStatus PR_CALLBACK scanner(PRThread* t, void** baseAddr,
+ PRUword count, void* closure)
+{
+ if (count) {
+ char* begin = (char*)baseAddr;
+ char* end = (char*)(baseAddr + count);
+ GC_mark_range_proc marker = (GC_mark_range_proc) closure;
+ marker(begin, end);
+ }
+ return PR_SUCCESS;
+}
+
+static void mark_all_stacks(GC_mark_range_proc marker)
+{
+ PR_ScanStackPointers(&scanner, (void *)marker);
+}
+
+#if defined(_PR_PTHREADS)
+#define _PR_MD_CURRENT_CPU() 1
+#endif
+
+static void locker(void* mutex)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_EnterMonitor(mutex);
+}
+
+static void unlocker(void* mutex)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_ExitMonitor(mutex);
+}
+
+static void stopper(void* unused)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_SuspendAll();
+}
+
+static void starter(void* unused)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_ResumeAll();
+}
+
+void _PR_InitGarbageCollector()
+{
+ void* mutex;
+
+ /* redirect GC's stderr to catch startup leaks. */
+ GC_stderr = fopen("StartupLeaks", "w");
+
+ mutex = PR_NewMonitor();
+ PR_ASSERT(mutex != NULL);
+
+ GC_generic_init_threads(&mark_all_stacks, mutex,
+ &locker, &unlocker,
+ &stopper, &starter);
+}
+
+void _PR_ShutdownGarbageCollector()
+{
+ /* do anything you need to shut down the collector. */
+}
+
+#endif /* GC_LEAK_DETECTOR */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/memory/prseg.c b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prseg.c
new file mode 100644
index 00000000..14de6668
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prseg.c
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#if defined(_PR_PTHREADS)
+
+/*
+** The pthreads version doesn't use these functions.
+*/
+void _PR_InitSegs(void)
+{
+}
+
+#else /* _PR_PTHREADS */
+
+void _PR_InitSegs(void)
+{
+ _PR_MD_INIT_SEGS();
+}
+
+/*
+** Allocate a memory segment. The size value is rounded up to the native
+** system page size and a page aligned portion of memory is returned.
+** This memory is not part of the malloc heap. If "vaddr" is not NULL
+** then PR tries to allocate the segment at the desired virtual address.
+*/
+PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr)
+{
+ PRSegment *seg;
+
+ /* calloc the data structure for the segment */
+ seg = PR_NEWZAP(PRSegment);
+
+ if (seg) {
+ size = ((size + _pr_pageSize - 1) >> _pr_pageShift) << _pr_pageShift;
+ /*
+ ** Now, allocate the actual segment memory (or map under some OS)
+ ** The OS specific code decides from where or how to allocate memory.
+ */
+ if (_PR_MD_ALLOC_SEGMENT(seg, size, vaddr) != PR_SUCCESS) {
+ PR_DELETE(seg);
+ return NULL;
+ }
+ }
+
+ return seg;
+}
+
+/*
+** Free a memory segment.
+*/
+void _PR_DestroySegment(PRSegment *seg)
+{
+ _PR_MD_FREE_SEGMENT(seg);
+ PR_DELETE(seg);
+}
+
+#endif /* _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/memory/prshm.c b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prshm.c
new file mode 100644
index 00000000..ac633952
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prshm.c
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prshm.c -- NSPR Named Shared Memory
+**
+** lth. Jul-1999.
+*/
+#include <string.h>
+#include "primpl.h"
+
+extern PRLogModuleInfo *_pr_shm_lm;
+
+
+#if defined PR_HAVE_SYSV_NAMED_SHARED_MEMORY
+/* SysV implementation is in pr/src/md/unix/uxshm.c */
+#elif defined PR_HAVE_POSIX_NAMED_SHARED_MEMORY
+/* Posix implementation is in pr/src/md/unix/uxshm.c */
+#elif defined PR_HAVE_WIN32_NAMED_SHARED_MEMORY
+/* Win32 implementation is in pr/src/md/windows/w32shm.c */
+#else
+/*
+** there is no named_shared_memory
+*/
+extern PRSharedMemory* _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode )
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags )
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr )
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm )
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+extern PRStatus _MD_DeleteSharedMemory( const char *name )
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+#endif /* HAVE_SYSV_NAMED_SHARED_MEMORY */
+
+/*
+** FUNCTION: PR_OpenSharedMemory()
+**
+*/
+PR_IMPLEMENT( PRSharedMemory * )
+ PR_OpenSharedMemory(
+ const char *name,
+ PRSize size,
+ PRIntn flags,
+ PRIntn mode
+)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ return( _PR_MD_OPEN_SHARED_MEMORY( name, size, flags, mode ));
+} /* end PR_OpenSharedMemory() */
+
+/*
+** FUNCTION: PR_AttachSharedMemory()
+**
+*/
+PR_IMPLEMENT( void * )
+ PR_AttachSharedMemory(
+ PRSharedMemory *shm,
+ PRIntn flags
+)
+{
+ return( _PR_MD_ATTACH_SHARED_MEMORY( shm, flags ));
+} /* end PR_AttachSharedMemory() */
+
+/*
+** FUNCTION: PR_DetachSharedMemory()
+**
+*/
+PR_IMPLEMENT( PRStatus )
+ PR_DetachSharedMemory(
+ PRSharedMemory *shm,
+ void *addr
+)
+{
+ return( _PR_MD_DETACH_SHARED_MEMORY( shm, addr ));
+} /* end PR_DetachSharedMemory() */
+
+/*
+** FUNCTION: PR_CloseSharedMemory()
+**
+*/
+PR_IMPLEMENT( PRStatus )
+ PR_CloseSharedMemory(
+ PRSharedMemory *shm
+)
+{
+ return( _PR_MD_CLOSE_SHARED_MEMORY( shm ));
+} /* end PR_CloseSharedMemory() */
+
+/*
+** FUNCTION: PR_DeleteSharedMemory()
+**
+*/
+PR_EXTERN( PRStatus )
+ PR_DeleteSharedMemory(
+ const char *name
+)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ return(_PR_MD_DELETE_SHARED_MEMORY( name ));
+} /* end PR_DestroySharedMemory() */
+/* end prshm.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/memory/prshma.c b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prshma.c
new file mode 100644
index 00000000..fbc22578
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/memory/prshma.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prshma.h -- NSPR Anonymous Shared Memory
+**
+**
+*/
+
+#include "primpl.h"
+
+extern PRLogModuleInfo *_pr_shma_lm;
+
+#if defined(XP_UNIX)
+/* defined in pr/src/md/unix/uxshm.c */
+#elif defined(WIN32)
+/* defined in pr/src/md/windows/w32shm.c */
+#else
+extern PRFileMap * _PR_MD_OPEN_ANON_FILE_MAP( const char *dirName, PRSize size, PRFileMapProtect prot )
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+extern PRStatus _PR_MD_EXPORT_FILE_MAP_AS_STRING(PRFileMap *fm, PRSize bufSize, char *buf)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+extern PRFileMap * _PR_MD_IMPORT_FILE_MAP_FROM_STRING(const char *fmstring)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+#endif
+
+/*
+** PR_OpenAnonFileMap() -- Creates an anonymous file-mapped shared memory
+**
+*/
+PR_IMPLEMENT(PRFileMap*)
+PR_OpenAnonFileMap(
+ const char *dirName,
+ PRSize size,
+ PRFileMapProtect prot
+)
+{
+ return(_PR_MD_OPEN_ANON_FILE_MAP( dirName, size, prot ));
+} /* end PR_OpenAnonFileMap() */
+
+/*
+** PR_ProcessAttrSetInheritableFileMap() -- Prepare FileMap for export
+** to my children processes via PR_CreateProcess()
+**
+**
+*/
+PR_IMPLEMENT( PRStatus)
+PR_ProcessAttrSetInheritableFileMap(
+ PRProcessAttr *attr,
+ PRFileMap *fm,
+ const char *shmname
+)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return( PR_FAILURE);
+} /* end PR_ProcessAttrSetInheritableFileMap() */
+
+/*
+** PR_GetInheritedFileMap() -- Import a PRFileMap previously exported
+** by my parent process via PR_CreateProcess()
+**
+*/
+PR_IMPLEMENT( PRFileMap *)
+PR_GetInheritedFileMap(
+ const char *shmname
+)
+{
+ PRFileMap *fm = NULL;
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return( fm );
+} /* end PR_GetInhteritedFileMap() */
+
+/*
+** PR_ExportFileMapAsString() -- Creates a string identifying a PRFileMap
+**
+*/
+PR_IMPLEMENT( PRStatus )
+PR_ExportFileMapAsString(
+ PRFileMap *fm,
+ PRSize bufSize,
+ char *buf
+)
+{
+ return( _PR_MD_EXPORT_FILE_MAP_AS_STRING( fm, bufSize, buf ));
+} /* end PR_ExportFileMapAsString() */
+
+/*
+** PR_ImportFileMapFromString() -- Creates a PRFileMap from the identifying string
+**
+**
+*/
+PR_IMPLEMENT( PRFileMap * )
+PR_ImportFileMapFromString(
+ const char *fmstring
+)
+{
+ return( _PR_MD_IMPORT_FILE_MAP_FROM_STRING(fmstring));
+} /* end PR_ImportFileMapFromString() */
+/* end prshma.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/misc/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/misc/Makefile.in
new file mode 100644
index 00000000..2ac8e257
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/Makefile.in
@@ -0,0 +1,107 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+CSRCS = \
+ pralarm.c \
+ pratom.c \
+ prcountr.c \
+ prdtoa.c \
+ prenv.c \
+ prerr.c \
+ prerror.c \
+ prerrortable.c \
+ prinit.c \
+ prinrval.c \
+ pripc.c \
+ prlog2.c \
+ prlong.c \
+ prnetdb.c \
+ prolock.c \
+ prrng.c \
+ prsystem.c \
+ prtime.c \
+ prthinfo.c \
+ prtpool.c \
+ prtrace.c \
+ $(NULL)
+
+ifndef USE_PTHREADS
+CSRCS += \
+ pripcsem.c \
+ $(NULL)
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties
+
+include $(topsrcdir)/config/rules.mk
+
+# Prevent floating point errors caused by MSVC 6.0 Processor Pack
+# optimizations (bug 207421). This disables optimizations that
+# could change the precision of floating-point calculations for
+# this single compilation unit.
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+$(OBJDIR)/prdtoa.$(OBJ_SUFFIX): prdtoa.c
+ @$(MAKE_OBJDIR)
+ $(CC) -Fo$@ -c $(CFLAGS) -Op $(call abspath,$<)
+endif
+
+#
+# Generate prerr.h, prerr.c, and prerr.properties from prerr.et.
+#
+build_prerr:
+ cd $(srcdir); $(PERL) compile-et.pl prerr.et
+
+export:: $(TARGETS)
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/compile-et.pl b/src/libs/xpcom18a4/nsprpub/pr/src/misc/compile-et.pl
new file mode 100755
index 00000000..9f0d90bc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/compile-et.pl
@@ -0,0 +1,140 @@
+#!/usr/bin/perl
+
+# usage: compile-et input.et
+
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+sub header
+{
+ local($filename, $comment) = @_;
+
+<<EOF
+$comment
+$comment $filename
+$comment This file is automatically generated; please do not edit it.
+EOF
+}
+
+sub table_base
+{
+ local($name) = @_;
+ local($base) = 0;
+
+ for ($i = 0; $i < length($name); $i++) {
+ $base *= 64;
+ $base += index("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", substr($name, $i, 1)) + 1;
+ }
+ $base -= 0x1000000 if ($base > 0x7fffff);
+ $base*256;
+}
+
+sub code {
+ local($macro, $text) = @_;
+ $code = $table_base + $table_item_count;
+
+ print H "\n";
+ print H "/* ", $text, " */\n";
+ printf H "#define %-40s (%dL)\n", $macro, $code;
+
+ print C "\t{\"", $macro, "\", \"", $text, "\"},\n";
+
+ print PROPERTIES $macro, "=", $text, "\n";
+
+ $table_item_count++;
+}
+
+
+$filename = $ARGV[0];
+open(INPUT, "< $filename") || die "Can't read $filename: $!\n";
+
+$base = "$filename";
+$base =~ s/\.et$//;
+$base =~ s#.*/##;
+
+open(H, "> ${base}.h") || die "Can't write ${base}.h\n";
+open(C, "> ${base}.c") || die "Can't write ${base}.c\n";
+open(PROPERTIES, "> ${base}.properties") || die "Can't write ${base}.properties\n";
+
+print H "/*\n", &header("${base}.h", " *"), " */\n";
+print C "/*\n", &header("${base}.c", " *"), " */\n";
+print PROPERTIES &header("${base}.properties", "#");
+
+$skipone = 0;
+
+while ($_ = <INPUT>) {
+ next if /^#/;
+
+ if (/^[ \t]*(error_table|et)[ \t]+([a-zA-Z][a-zA-Z0-9_]+) *(-?[0-9]*)/) {
+ $table_name = $2;
+ if ($3) {
+ $table_base = $3;
+ }
+ else {
+ $table_base = &table_base($table_name);
+ }
+ $table_item_count = 0;
+
+ print C "#include \"prerror.h\"\n";
+ print C "static const struct PRErrorMessage text[] = {\n";
+ }
+ elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*$/) {
+ $skipone = 1;
+ $macro = $2;
+ }
+ elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*"(.*)"[ \t]*$/) {
+ &code($2, $3);
+ }
+ elsif ($skipone && /^[ \t]*"(.*)"[ \t]*$/) {
+ &code($macro, $1);
+ }
+}
+
+print H "\n";
+print H "extern void ", $table_name, "_InitializePRErrorTable","(void);\n";
+printf H "#define ERROR_TABLE_BASE_%s (%dL)\n", $table_name, $table_base;
+
+print C "\t{0, 0}\n";
+print C "};\n\n";
+printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n",
+ $base, $table_base, $table_item_count;
+print C "\n";
+print C "void ", $table_name, "_InitializePRErrorTable", "(void) {\n";
+print C " PR_ErrorInstallTable(&et);\n";
+print C "}\n";
+
+0;
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/pralarm.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pralarm.c
new file mode 100644
index 00000000..9323bab6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pralarm.c
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/**********************************************************************/
+/******************************* PRALARM ******************************/
+/**********************************************************************/
+
+#ifdef XP_MAC
+#include "pralarm.h"
+#else
+#include "obsolete/pralarm.h"
+#endif
+
+struct PRAlarmID { /* typedef'd in pralarm.h */
+ PRCList list; /* circular list linkage */
+ PRAlarm *alarm; /* back pointer to owning alarm */
+ PRPeriodicAlarmFn function; /* function to call for notify */
+ void *clientData; /* opaque client context */
+ PRIntervalTime period; /* the client defined period */
+ PRUint32 rate; /* rate of notification */
+
+ PRUint32 accumulator; /* keeps track of # notifies */
+ PRIntervalTime epoch; /* when timer was started */
+ PRIntervalTime nextNotify; /* when we'll next do our thing */
+ PRIntervalTime lastNotify; /* when we last did our thing */
+};
+
+typedef enum {alarm_active, alarm_inactive} _AlarmState;
+
+struct PRAlarm { /* typedef'd in pralarm.h */
+ PRCList timers; /* base of alarm ids list */
+ PRLock *lock; /* lock used to protect data */
+ PRCondVar *cond; /* condition that used to wait */
+ PRThread *notifier; /* thread to deliver notifies */
+ PRAlarmID *current; /* current alarm being served */
+ _AlarmState state; /* used to delete the alarm */
+};
+
+static PRAlarmID *pr_getNextAlarm(PRAlarm *alarm, PRAlarmID *id)
+{
+/*
+ * Puts 'id' back into the sorted list iff it's not NULL.
+ * Removes the first element from the list and returns it (or NULL).
+ * List is "assumed" to be short.
+ *
+ * NB: Caller is providing locking
+ */
+ PRCList *timer;
+ PRAlarmID *result = id;
+ PRIntervalTime now = PR_IntervalNow();
+
+ if (!PR_CLIST_IS_EMPTY(&alarm->timers))
+ {
+ if (id != NULL) /* have to put this id back in */
+ {
+ PRIntervalTime idDelta = now - id->nextNotify;
+ timer = alarm->timers.next;
+ do
+ {
+ result = (PRAlarmID*)timer;
+ if ((PRIntervalTime)(now - result->nextNotify) > idDelta)
+ {
+ PR_INSERT_BEFORE(&id->list, &alarm->timers);
+ break;
+ }
+ timer = timer->next;
+ } while (timer != &alarm->timers);
+ }
+ result = (PRAlarmID*)(timer = PR_LIST_HEAD(&alarm->timers));
+ PR_REMOVE_LINK(timer); /* remove it from the list */
+ }
+
+ return result;
+} /* pr_getNextAlarm */
+
+static PRIntervalTime pr_PredictNextNotifyTime(PRAlarmID *id)
+{
+ PRIntervalTime delta;
+ PRFloat64 baseRate = (PRFloat64)id->period / (PRFloat64)id->rate;
+ PRFloat64 offsetFromEpoch = (PRFloat64)id->accumulator * baseRate;
+
+ id->accumulator += 1; /* every call advances to next period */
+ id->lastNotify = id->nextNotify; /* just keeping track of things */
+ id->nextNotify = (PRIntervalTime)(offsetFromEpoch + 0.5);
+
+ delta = id->nextNotify - id->lastNotify;
+ return delta;
+} /* pr_PredictNextNotifyTime */
+
+static void PR_CALLBACK pr_alarmNotifier(void *arg)
+{
+ /*
+ * This is the root of the notifier thread. There is one such thread
+ * for each PRAlarm. It may service an arbitrary (though assumed to be
+ * small) number of alarms using the same thread and structure. It
+ * continues to run until the alarm is destroyed.
+ */
+ PRAlarmID *id = NULL;
+ PRAlarm *alarm = (PRAlarm*)arg;
+ enum {notify, abort, scan} why = scan;
+
+ while (why != abort)
+ {
+ PRIntervalTime pause;
+
+ PR_Lock(alarm->lock);
+ while (why == scan)
+ {
+ alarm->current = NULL; /* reset current id */
+ if (alarm->state == alarm_inactive) why = abort; /* we're toast */
+ else if (why == scan) /* the dominant case */
+ {
+ id = pr_getNextAlarm(alarm, id); /* even if it's the same */
+ if (id == NULL) /* there are no alarms set */
+ (void)PR_WaitCondVar(alarm->cond, PR_INTERVAL_NO_TIMEOUT);
+ else
+ {
+ pause = id->nextNotify - (PR_IntervalNow() - id->epoch);
+ if ((PRInt32)pause <= 0) /* is this one's time up? */
+ {
+ why = notify; /* set up to do our thing */
+ alarm->current = id; /* id we're about to schedule */
+ }
+ else
+ (void)PR_WaitCondVar(alarm->cond, pause); /* dally */
+ }
+ }
+ }
+ PR_Unlock(alarm->lock);
+
+ if (why == notify)
+ {
+ (void)pr_PredictNextNotifyTime(id);
+ if (!id->function(id, id->clientData, ~pause))
+ {
+ /*
+ * Notified function decided not to continue. Free
+ * the alarm id to make sure it doesn't get back on
+ * the list.
+ */
+ PR_DELETE(id); /* free notifier object */
+ id = NULL; /* so it doesn't get back into the list */
+ }
+ why = scan; /* so we can cycle through the loop again */
+ }
+ }
+
+} /* pr_alarm_notifier */
+
+PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm(void)
+{
+ PRAlarm *alarm = PR_NEWZAP(PRAlarm);
+ if (alarm != NULL)
+ {
+ if ((alarm->lock = PR_NewLock()) == NULL) goto done;
+ if ((alarm->cond = PR_NewCondVar(alarm->lock)) == NULL) goto done;
+ alarm->state = alarm_active;
+ PR_INIT_CLIST(&alarm->timers);
+ alarm->notifier = PR_CreateThread(
+ PR_USER_THREAD, pr_alarmNotifier, alarm,
+ PR_GetThreadPriority(PR_GetCurrentThread()),
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (alarm->notifier == NULL) goto done;
+ }
+ return alarm;
+
+done:
+ if (alarm->cond != NULL) PR_DestroyCondVar(alarm->cond);
+ if (alarm->lock != NULL) PR_DestroyLock(alarm->lock);
+ PR_DELETE(alarm);
+ return NULL;
+} /* CreateAlarm */
+
+PR_IMPLEMENT(PRStatus) PR_DestroyAlarm(PRAlarm *alarm)
+{
+ PRStatus rv;
+
+ PR_Lock(alarm->lock);
+ alarm->state = alarm_inactive;
+ rv = PR_NotifyCondVar(alarm->cond);
+ PR_Unlock(alarm->lock);
+
+ if (rv == PR_SUCCESS)
+ rv = PR_JoinThread(alarm->notifier);
+ if (rv == PR_SUCCESS)
+ {
+ PR_DestroyCondVar(alarm->cond);
+ PR_DestroyLock(alarm->lock);
+ PR_DELETE(alarm);
+ }
+ return rv;
+} /* PR_DestroyAlarm */
+
+PR_IMPLEMENT(PRAlarmID*) PR_SetAlarm(
+ PRAlarm *alarm, PRIntervalTime period, PRUint32 rate,
+ PRPeriodicAlarmFn function, void *clientData)
+{
+ /*
+ * Create a new periodic alarm an existing current structure.
+ * Set up the context and compute the first notify time (immediate).
+ * Link the new ID into the head of the list (since it's notifying
+ * immediately).
+ */
+
+ PRAlarmID *id = PR_NEWZAP(PRAlarmID);
+
+ if (!id)
+ return NULL;
+
+ id->alarm = alarm;
+ PR_INIT_CLIST(&id->list);
+ id->function = function;
+ id->clientData = clientData;
+ id->period = period;
+ id->rate = rate;
+ id->epoch = id->nextNotify = PR_IntervalNow();
+ (void)pr_PredictNextNotifyTime(id);
+
+ PR_Lock(alarm->lock);
+ PR_INSERT_BEFORE(&id->list, &alarm->timers);
+ PR_NotifyCondVar(alarm->cond);
+ PR_Unlock(alarm->lock);
+
+ return id;
+} /* PR_SetAlarm */
+
+PR_IMPLEMENT(PRStatus) PR_ResetAlarm(
+ PRAlarmID *id, PRIntervalTime period, PRUint32 rate)
+{
+ /*
+ * Can only be called from within the notify routine. Doesn't
+ * need locking because it can only be called from within the
+ * notify routine.
+ */
+ if (id != id->alarm->current)
+ return PR_FAILURE;
+ id->period = period;
+ id->rate = rate;
+ id->accumulator = 1;
+ id->epoch = PR_IntervalNow();
+ (void)pr_PredictNextNotifyTime(id);
+ return PR_SUCCESS;
+} /* PR_ResetAlarm */
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/pratom.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pratom.c
new file mode 100644
index 00000000..24028e56
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pratom.c
@@ -0,0 +1,409 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** PR Atomic operations
+*/
+
+
+#include "pratom.h"
+#include "primpl.h"
+
+#include <string.h>
+
+/*
+ * The following is a fallback implementation that emulates
+ * atomic operations for platforms without atomic operations.
+ * If a platform has atomic operations, it should define the
+ * macro _PR_HAVE_ATOMIC_OPS, and the following will not be
+ * compiled in.
+ */
+
+#if !defined(_PR_HAVE_ATOMIC_OPS)
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+/*
+ * PR_AtomicDecrement() is used in NSPR's thread-specific data
+ * destructor. Because thread-specific data destructors may be
+ * invoked after a PR_Cleanup() call, we need an implementation
+ * of the atomic routines that doesn't need NSPR to be initialized.
+ */
+
+/*
+ * We use a set of locks for all the emulated atomic operations.
+ * By hashing on the address of the integer to be locked the
+ * contention between multiple threads should be lessened.
+ *
+ * The number of atomic locks can be set by the environment variable
+ * NSPR_ATOMIC_HASH_LOCKS
+ */
+
+/*
+ * lock counts should be a power of 2
+ */
+#define DEFAULT_ATOMIC_LOCKS 16 /* should be in sync with the number of initializers
+ below */
+#define MAX_ATOMIC_LOCKS (4 * 1024)
+
+static pthread_mutex_t static_atomic_locks[DEFAULT_ATOMIC_LOCKS] = {
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };
+
+#ifdef DEBUG
+static PRInt32 static_hash_lock_counts[DEFAULT_ATOMIC_LOCKS];
+static PRInt32 *hash_lock_counts = static_hash_lock_counts;
+#endif
+
+static PRUint32 num_atomic_locks = DEFAULT_ATOMIC_LOCKS;
+static pthread_mutex_t *atomic_locks = static_atomic_locks;
+static PRUint32 atomic_hash_mask = DEFAULT_ATOMIC_LOCKS - 1;
+
+#define _PR_HASH_FOR_LOCK(ptr) \
+ ((PRUint32) (((PRUptrdiff) (ptr) >> 2) ^ \
+ ((PRUptrdiff) (ptr) >> 8)) & \
+ atomic_hash_mask)
+
+void _PR_MD_INIT_ATOMIC()
+{
+char *eval;
+int index;
+
+
+ PR_ASSERT(PR_FloorLog2(MAX_ATOMIC_LOCKS) ==
+ PR_CeilingLog2(MAX_ATOMIC_LOCKS));
+
+ PR_ASSERT(PR_FloorLog2(DEFAULT_ATOMIC_LOCKS) ==
+ PR_CeilingLog2(DEFAULT_ATOMIC_LOCKS));
+
+ if (((eval = getenv("NSPR_ATOMIC_HASH_LOCKS")) != NULL) &&
+ ((num_atomic_locks = atoi(eval)) != DEFAULT_ATOMIC_LOCKS)) {
+
+ if (num_atomic_locks > MAX_ATOMIC_LOCKS)
+ num_atomic_locks = MAX_ATOMIC_LOCKS;
+ else {
+ num_atomic_locks = PR_FloorLog2(num_atomic_locks);
+ num_atomic_locks = 1L << num_atomic_locks;
+ }
+ atomic_locks = (pthread_mutex_t *) PR_Malloc(sizeof(pthread_mutex_t) *
+ num_atomic_locks);
+ if (atomic_locks) {
+ for (index = 0; index < num_atomic_locks; index++) {
+ if (pthread_mutex_init(&atomic_locks[index], NULL)) {
+ PR_DELETE(atomic_locks);
+ atomic_locks = NULL;
+ break;
+ }
+ }
+ }
+#ifdef DEBUG
+ if (atomic_locks) {
+ hash_lock_counts = PR_CALLOC(num_atomic_locks * sizeof(PRInt32));
+ if (hash_lock_counts == NULL) {
+ PR_DELETE(atomic_locks);
+ atomic_locks = NULL;
+ }
+ }
+#endif
+ if (atomic_locks == NULL) {
+ /*
+ * Use statically allocated locks
+ */
+ atomic_locks = static_atomic_locks;
+ num_atomic_locks = DEFAULT_ATOMIC_LOCKS;
+ #ifdef DEBUG
+ hash_lock_counts = static_hash_lock_counts;
+ #endif
+ }
+ atomic_hash_mask = num_atomic_locks - 1;
+ }
+ PR_ASSERT(PR_FloorLog2(num_atomic_locks) ==
+ PR_CeilingLog2(num_atomic_locks));
+}
+
+PRInt32
+_PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+ PRInt32 rv;
+ PRInt32 idx = _PR_HASH_FOR_LOCK(val);
+
+ pthread_mutex_lock(&atomic_locks[idx]);
+ rv = ++(*val);
+#ifdef DEBUG
+ hash_lock_counts[idx]++;
+#endif
+ pthread_mutex_unlock(&atomic_locks[idx]);
+ return rv;
+}
+
+PRInt32
+_PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ PRInt32 rv;
+ PRInt32 idx = _PR_HASH_FOR_LOCK(ptr);
+
+ pthread_mutex_lock(&atomic_locks[idx]);
+ rv = ((*ptr) += val);
+#ifdef DEBUG
+ hash_lock_counts[idx]++;
+#endif
+ pthread_mutex_unlock(&atomic_locks[idx]);
+ return rv;
+}
+
+PRInt32
+_PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+ PRInt32 rv;
+ PRInt32 idx = _PR_HASH_FOR_LOCK(val);
+
+ pthread_mutex_lock(&atomic_locks[idx]);
+ rv = --(*val);
+#ifdef DEBUG
+ hash_lock_counts[idx]++;
+#endif
+ pthread_mutex_unlock(&atomic_locks[idx]);
+ return rv;
+}
+
+PRInt32
+_PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+{
+ PRInt32 rv;
+ PRInt32 idx = _PR_HASH_FOR_LOCK(val);
+
+ pthread_mutex_lock(&atomic_locks[idx]);
+ rv = *val;
+ *val = newval;
+#ifdef DEBUG
+ hash_lock_counts[idx]++;
+#endif
+ pthread_mutex_unlock(&atomic_locks[idx]);
+ return rv;
+}
+#else /* _PR_PTHREADS && !_PR_DCETHREADS */
+/*
+ * We use a single lock for all the emulated atomic operations.
+ * The lock contention should be acceptable.
+ */
+static PRLock *atomic_lock = NULL;
+void _PR_MD_INIT_ATOMIC(void)
+{
+ if (atomic_lock == NULL) {
+ atomic_lock = PR_NewLock();
+ }
+}
+
+PRInt32
+_PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(atomic_lock);
+ rv = ++(*val);
+ PR_Unlock(atomic_lock);
+ return rv;
+}
+
+PRInt32
+_PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val)
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(atomic_lock);
+ rv = ((*ptr) += val);
+ PR_Unlock(atomic_lock);
+ return rv;
+}
+
+PRInt32
+_PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(atomic_lock);
+ rv = --(*val);
+ PR_Unlock(atomic_lock);
+ return rv;
+}
+
+PRInt32
+_PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(atomic_lock);
+ rv = *val;
+ *val = newval;
+ PR_Unlock(atomic_lock);
+ return rv;
+}
+#endif /* _PR_PTHREADS && !_PR_DCETHREADS */
+
+#endif /* !_PR_HAVE_ATOMIC_OPS */
+
+void _PR_InitAtomic(void)
+{
+ _PR_MD_INIT_ATOMIC();
+}
+
+PR_IMPLEMENT(PRInt32)
+PR_AtomicIncrement(PRInt32 *val)
+{
+ return _PR_MD_ATOMIC_INCREMENT(val);
+}
+
+PR_IMPLEMENT(PRInt32)
+PR_AtomicDecrement(PRInt32 *val)
+{
+ return _PR_MD_ATOMIC_DECREMENT(val);
+}
+
+PR_IMPLEMENT(PRInt32)
+PR_AtomicSet(PRInt32 *val, PRInt32 newval)
+{
+ return _PR_MD_ATOMIC_SET(val, newval);
+}
+
+PR_IMPLEMENT(PRInt32)
+PR_AtomicAdd(PRInt32 *ptr, PRInt32 val)
+{
+ return _PR_MD_ATOMIC_ADD(ptr, val);
+}
+/*
+ * For platforms, which don't support the CAS (compare-and-swap) instruction
+ * (or an equivalent), the stack operations are implemented by use of PRLock
+ */
+
+PR_IMPLEMENT(PRStack *)
+PR_CreateStack(const char *stack_name)
+{
+PRStack *stack;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+
+ if ((stack = PR_NEW(PRStack)) == NULL) {
+ return NULL;
+ }
+ if (stack_name) {
+ stack->prstk_name = (char *) PR_Malloc(strlen(stack_name) + 1);
+ if (stack->prstk_name == NULL) {
+ PR_DELETE(stack);
+ return NULL;
+ }
+ strcpy(stack->prstk_name, stack_name);
+ } else
+ stack->prstk_name = NULL;
+
+#ifndef _PR_HAVE_ATOMIC_CAS
+ stack->prstk_lock = PR_NewLock();
+ if (stack->prstk_lock == NULL) {
+ PR_Free(stack->prstk_name);
+ PR_DELETE(stack);
+ return NULL;
+ }
+#endif /* !_PR_HAVE_ATOMIC_CAS */
+
+ stack->prstk_head.prstk_elem_next = NULL;
+
+ return stack;
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_DestroyStack(PRStack *stack)
+{
+ if (stack->prstk_head.prstk_elem_next != NULL) {
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ if (stack->prstk_name)
+ PR_Free(stack->prstk_name);
+#ifndef _PR_HAVE_ATOMIC_CAS
+ PR_DestroyLock(stack->prstk_lock);
+#endif /* !_PR_HAVE_ATOMIC_CAS */
+ PR_DELETE(stack);
+
+ return PR_SUCCESS;
+}
+
+#ifndef _PR_HAVE_ATOMIC_CAS
+
+PR_IMPLEMENT(void)
+PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
+{
+ PR_Lock(stack->prstk_lock);
+ stack_elem->prstk_elem_next = stack->prstk_head.prstk_elem_next;
+ stack->prstk_head.prstk_elem_next = stack_elem;
+ PR_Unlock(stack->prstk_lock);
+ return;
+}
+
+PR_IMPLEMENT(PRStackElem *)
+PR_StackPop(PRStack *stack)
+{
+PRStackElem *element;
+
+ PR_Lock(stack->prstk_lock);
+ element = stack->prstk_head.prstk_elem_next;
+ if (element != NULL) {
+ stack->prstk_head.prstk_elem_next = element->prstk_elem_next;
+ element->prstk_elem_next = NULL; /* debugging aid */
+ }
+ PR_Unlock(stack->prstk_lock);
+ return element;
+}
+#endif /* !_PR_HAVE_ATOMIC_CAS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prcountr.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prcountr.c
new file mode 100644
index 00000000..a4e4f6cc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prcountr.c
@@ -0,0 +1,506 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prcountr.c -- NSPR Instrumentation Counters
+**
+** Implement the interface defined in prcountr.h
+**
+** Design Notes:
+**
+** The Counter Facility (CF) has a single anchor: qNameList.
+** The anchor is a PRCList. qNameList is a list of links in QName
+** structures. From qNameList any QName structure and its
+** associated RName structure can be located.
+**
+** For each QName, a list of RName structures is anchored at
+** rnLink in the QName structure.
+**
+** The counter itself is embedded in the RName structure.
+**
+** For manipulating the counter database, single lock is used to
+** protect the entire list: counterLock.
+**
+** A PRCounterHandle, defined in prcountr.h, is really a pointer
+** to a RName structure. References by PRCounterHandle are
+** dead-reconed to the RName structure. The PRCounterHandle is
+** "overloaded" for traversing the QName structures; only the
+** function PR_FindNextQnameHandle() uses this overloading.
+**
+**
+** ToDo (lth): decide on how to lock or atomically update
+** individual counters. Candidates are: the global lock; a lock
+** per RName structure; Atomic operations (Note that there are
+** not adaquate atomic operations (yet) to achieve this goal). At
+** this writing (6/19/98) , the update of the counter variable in
+** a QName structure is unprotected.
+**
+*/
+
+#include "prcountr.h"
+#include "prclist.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+#include <string.h>
+
+/*
+**
+*/
+typedef struct QName
+{
+ PRCList link;
+ PRCList rNameList;
+ char name[PRCOUNTER_NAME_MAX+1];
+} QName;
+
+/*
+**
+*/
+typedef struct RName
+{
+ PRCList link;
+ QName *qName;
+ PRLock *lock;
+ volatile PRUint32 counter;
+ char name[PRCOUNTER_NAME_MAX+1];
+ char desc[PRCOUNTER_DESC_MAX+1];
+} RName;
+
+
+/*
+** Define the Counter Facility database
+*/
+static PRLock *counterLock;
+static PRCList qNameList;
+static PRLogModuleInfo *lm;
+
+/*
+** _PR_CounterInitialize() -- Initialize the Counter Facility
+**
+*/
+static void _PR_CounterInitialize( void )
+{
+ /*
+ ** This function should be called only once
+ */
+ PR_ASSERT( counterLock == NULL );
+
+ counterLock = PR_NewLock();
+ PR_INIT_CLIST( &qNameList );
+ lm = PR_NewLogModule("counters");
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete"));
+
+ return;
+} /* end _PR_CounterInitialize() */
+
+/*
+** PR_CreateCounter() -- Create a counter
+**
+** ValidateArguments
+** Lock
+** if (qName not already in database)
+** NewQname
+** if (rName already in database )
+** Assert
+** else NewRname
+** NewCounter
+** link 'em up
+** Unlock
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_CreateCounter(
+ const char *qName,
+ const char *rName,
+ const char *description
+)
+{
+ QName *qnp;
+ RName *rnp;
+ PRBool matchQname = PR_FALSE;
+
+ /* Self initialize, if necessary */
+ if ( counterLock == NULL )
+ _PR_CounterInitialize();
+
+ /* Validate input arguments */
+ PR_ASSERT( strlen(qName) <= PRCOUNTER_NAME_MAX );
+ PR_ASSERT( strlen(rName) <= PRCOUNTER_NAME_MAX );
+ PR_ASSERT( strlen(description) <= PRCOUNTER_DESC_MAX );
+
+ /* Lock the Facility */
+ PR_Lock( counterLock );
+
+ /* Do we already have a matching QName? */
+ if (!PR_CLIST_IS_EMPTY( &qNameList ))
+ {
+ qnp = (QName *) PR_LIST_HEAD( &qNameList );
+ do {
+ if ( strcmp(qnp->name, qName) == 0)
+ {
+ matchQname = PR_TRUE;
+ break;
+ }
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+ } while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));
+ }
+ /*
+ ** If we did not find a matching QName,
+ ** allocate one and initialize it.
+ ** link it onto the qNameList.
+ **
+ */
+ if ( matchQname != PR_TRUE )
+ {
+ qnp = PR_NEWZAP( QName );
+ PR_ASSERT( qnp != NULL );
+ PR_INIT_CLIST( &qnp->link );
+ PR_INIT_CLIST( &qnp->rNameList );
+ strcpy( qnp->name, qName );
+ PR_APPEND_LINK( &qnp->link, &qNameList );
+ }
+
+ /* Do we already have a matching RName? */
+ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ {
+ rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
+ do {
+ /*
+ ** No duplicate RNames are allowed within a QName
+ **
+ */
+ PR_ASSERT( strcmp(rnp->name, rName));
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+ } while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));
+ }
+
+ /* Get a new RName structure; initialize its members */
+ rnp = PR_NEWZAP( RName );
+ PR_ASSERT( rnp != NULL );
+ PR_INIT_CLIST( &rnp->link );
+ strcpy( rnp->name, rName );
+ strcpy( rnp->desc, description );
+ rnp->lock = PR_NewLock();
+ if ( rnp->lock == NULL )
+ {
+ PR_ASSERT(0);
+ }
+
+ PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */
+ rnp->qName = qnp; /* point the RName to the QName */
+
+ /* Unlock the Facility */
+ PR_Unlock( counterLock );
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t",
+ qName, qnp, rName, rnp ));
+
+ return((PRCounterHandle)rnp);
+} /* end PR_CreateCounter() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyCounter(
+ PRCounterHandle handle
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s",
+ qnp->name, rnp->name));
+
+ /* Lock the Facility */
+ PR_Lock( counterLock );
+
+ /*
+ ** Remove RName from the list of RNames in QName
+ ** and free RName
+ */
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting RName: %s, %p",
+ rnp->name, rnp));
+ PR_REMOVE_LINK( &rnp->link );
+ PR_Free( rnp->lock );
+ PR_DELETE( rnp );
+
+ /*
+ ** If this is the last RName within QName
+ ** remove QName from the qNameList and free it
+ */
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
+ {
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting unused QName: %s, %p",
+ qnp->name, qnp));
+ PR_REMOVE_LINK( &qnp->link );
+ PR_DELETE( qnp );
+ }
+
+ /* Unlock the Facility */
+ PR_Unlock( counterLock );
+ return;
+} /* end PR_DestroyCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_GetCounterHandleFromName(
+ const char *qName,
+ const char *rName
+)
+{
+ const char *qn, *rn, *desc;
+ PRCounterHandle qh, rh = NULL;
+ RName *rnp = NULL;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t"
+ "QName: %s, RName: %s", qName, rName ));
+
+ qh = PR_FindNextCounterQname( NULL );
+ while (qh != NULL)
+ {
+ rh = PR_FindNextCounterRname( NULL, qh );
+ while ( rh != NULL )
+ {
+ PR_GetCounterNameFromHandle( rh, &qn, &rn, &desc );
+ if ( (strcmp( qName, qn ) == 0)
+ && (strcmp( rName, rn ) == 0 ))
+ {
+ rnp = (RName *)rh;
+ goto foundIt;
+ }
+ rh = PR_FindNextCounterRname( rh, qh );
+ }
+ qh = PR_FindNextCounterQname( NULL );
+ }
+
+foundIt:
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
+ return(rh);
+} /* end PR_GetCounterHandleFromName() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_GetCounterNameFromHandle(
+ PRCounterHandle handle,
+ const char **qName,
+ const char **rName,
+ const char **description
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ *qName = qnp->name;
+ *rName = rnp->name;
+ *description = rnp->desc;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterNameFromHandle: "
+ "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
+ qnp, rnp, qnp->name, rnp->name, rnp->desc ));
+
+ return;
+} /* end PR_GetCounterNameFromHandle() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_IncrementCounter(
+ PRCounterHandle handle
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter++;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_IncrementCounter() */
+
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DecrementCounter(
+ PRCounterHandle handle
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter--;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_DecrementCounter() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_AddToCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter += value;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_AddToCounter() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_SubtractFromCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+)
+{
+ PR_Lock(((RName *)handle)->lock);
+ ((RName *)handle)->counter -= value;
+ PR_Unlock(((RName *)handle)->lock);
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_SubtractFromCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRUint32)
+ PR_GetCounter(
+ PRCounterHandle handle
+)
+{
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return(((RName *)handle)->counter);
+} /* end PR_GetCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_SetCounter(
+ PRCounterHandle handle,
+ PRUint32 value
+)
+{
+ ((RName *)handle)->counter = value;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld",
+ handle, ((RName *)handle)->counter ));
+
+ return;
+} /* end PR_SetCounter() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_FindNextCounterQname(
+ PRCounterHandle handle
+)
+{
+ QName *qnp = (QName *)handle;
+
+ if ( PR_CLIST_IS_EMPTY( &qNameList ))
+ qnp = NULL;
+ else if ( qnp == NULL )
+ qnp = (QName *)PR_LIST_HEAD( &qNameList );
+ else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList )
+ qnp = NULL;
+ else
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns: %p",
+ handle, qnp ));
+
+ return((PRCounterHandle)qnp);
+} /* end PR_FindNextCounterQname() */
+
+
+/*
+**
+*/
+PR_IMPLEMENT(PRCounterHandle)
+ PR_FindNextCounterRname(
+ PRCounterHandle rhandle,
+ PRCounterHandle qhandle
+)
+{
+ RName *rnp = (RName *)rhandle;
+ QName *qnp = (QName *)qhandle;
+
+
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ rnp = NULL;
+ else if ( rnp == NULL )
+ rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
+ else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList )
+ rnp = NULL;
+ else
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
+ rhandle, qhandle, rnp ));
+
+ return((PRCounterHandle)rnp);
+} /* end PR_FindNextCounterRname() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prdtoa.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prdtoa.c
new file mode 100644
index 00000000..13e03853
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prdtoa.c
@@ -0,0 +1,3519 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#define MULTIPLE_THREADS
+#define ACQUIRE_DTOA_LOCK(n) PR_Lock(dtoa_lock[n])
+#define FREE_DTOA_LOCK(n) PR_Unlock(dtoa_lock[n])
+
+static PRLock *dtoa_lock[2];
+
+void _PR_InitDtoa(void)
+{
+ dtoa_lock[0] = PR_NewLock();
+ dtoa_lock[1] = PR_NewLock();
+}
+
+void _PR_CleanupDtoa(void)
+{
+ PR_DestroyLock(dtoa_lock[0]);
+ dtoa_lock[0] = NULL;
+ PR_DestroyLock(dtoa_lock[1]);
+ dtoa_lock[1] = NULL;
+
+ /* FIXME: deal with freelist and p5s. */
+}
+
+#if defined(__arm) || defined(__arm__) || defined(__arm26__) \
+ || defined(__arm32__)
+#define IEEE_ARM
+#elif defined(IS_LITTLE_ENDIAN)
+#define IEEE_8087
+#else
+#define IEEE_MC68k
+#endif
+
+#define Long PRInt32
+#define ULong PRUint32
+#define NO_LONG_LONG
+
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa. If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ * _control87(PC_53, MCW_PC);
+ * does this with many compilers. Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE, IBM, or VAX double-precision
+ * arithmetic (not IEEE double-extended).
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define IEEE_ARM for IEEE-arithmetic machines where the two words
+ * in a double are stored in big endian order but the two shorts
+ * in a word are still stored in little endian order.
+ * #define Long int on machines with 32-bit ints and 64-bit longs.
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic (D_floating).
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and strtod and dtoa should round accordingly.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and Honor_FLT_ROUNDS is not #defined.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ * that use extended-precision instructions to compute rounded
+ * products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define NO_LONG_LONG on machines that do not have a "long long"
+ * integer type (of >= 64 bits). On such machines, you can
+ * #define Just_16 to store 16 bits per 32-bit Long when doing
+ * high-precision integer arithmetic. Whether this speeds things
+ * up or slows things down depends on the machine and the number
+ * being converted. If long long is available and the name is
+ * something other than "long long", #define Llong to be the name,
+ * and if "unsigned Llong" does not work as an unsigned version of
+ * Llong, #define #ULLong to be the corresponding unsigned type.
+ * #define KR_headers for old-style C function headers.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
+ * if memory is available and otherwise does something you deem
+ * appropriate. If MALLOC is undefined, malloc will be invoked
+ * directly -- and assumed always to succeed.
+ * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
+ * memory allocations from a private pool of memory when possible.
+ * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
+ * unless #defined to be a different length. This default length
+ * suffices to get rid of MALLOC calls except for unusual cases,
+ * such as decimal-to-binary conversion of a very long string of
+ * digits. The longest string dtoa can return is about 751 bytes
+ * long. For conversions by strtod of strings of 800 digits and
+ * all dtoa conversions in single-threaded executions with 8-byte
+ * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
+ * pointers, PRIVATE_MEM >= 7112 appears adequate.
+ * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
+ * Infinity and NaN (case insensitively). On some systems (e.g.,
+ * some HP systems), it may be necessary to #define NAN_WORD0
+ * appropriately -- to the most significant word of a quiet NaN.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ * strtod also accepts (case insensitively) strings of the form
+ * NaN(x), where x is a string of hexadecimal digits and spaces;
+ * if there is only one string of hexadecimal digits, it is taken
+ * for the 52 fraction bits of the resulting NaN; if there are two
+ * or more strings of hex digits, the first is for the high 20 bits,
+ * the second and subsequent for the low 32 bits, with intervening
+ * white space ignored; but if this results in none of the 52
+ * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
+ * and NAN_WORD1 are used instead.
+ * #define MULTIPLE_THREADS if the system offers preemptively scheduled
+ * multiple threads. In this case, you must provide (or suitably
+ * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
+ * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed
+ * in pow5mult, ensures lazy evaluation of only one copy of high
+ * powers of 5; omitting this lock would introduce a small
+ * probability of wasting memory, but would otherwise be harmless.)
+ * You must also invoke freedtoa(s) to free the value s returned by
+ * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
+ * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
+ * avoids underflows on inputs whose result does not underflow.
+ * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
+ * floating-point numbers and flushes underflows to zero rather
+ * than implementing gradual underflow, then you must also #define
+ * Sudden_Underflow.
+ * #define YES_ALIAS to permit aliasing certain double values with
+ * arrays of ULongs. This leads to slightly better code with
+ * some compilers and was always used prior to 19990916, but it
+ * is not strictly legal and can cause trouble with aggressively
+ * optimizing compilers (e.g., gcc 2.95.1 under -O2).
+ * #define USE_LOCALE to use the current locale's decimal_point value.
+ * #define SET_INEXACT if IEEE arithmetic is being used and extra
+ * computation should be done to set the inexact flag when the
+ * result is inexact and avoid setting inexact when the result
+ * is exact. In this case, dtoa.c must be compiled in
+ * an environment, perhaps provided by #include "dtoa.c" in a
+ * suitable wrapper, that defines two functions,
+ * int get_inexact(void);
+ * void clear_inexact(void);
+ * such that get_inexact() returns a nonzero value if the
+ * inexact bit is already set, and clear_inexact() sets the
+ * inexact bit to 0. When SET_INEXACT is #defined, strtod
+ * also does extra computations to set the underflow and overflow
+ * flags when appropriate (i.e., when the result is tiny and
+ * inexact or when it is a numeric value rounded to +-infinity).
+ * #define NO_ERRNO if strtod should not assign errno = ERANGE when
+ * the result overflows to +-Infinity or underflows to 0.
+ */
+
+#ifndef Long
+#define Long long
+#endif
+#ifndef ULong
+typedef unsigned Long ULong;
+#endif
+
+#ifdef DEBUG
+#include "stdio.h"
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+#include "stdlib.h"
+#include "string.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+#ifdef MALLOC
+#ifdef KR_headers
+extern char *MALLOC();
+#else
+extern void *MALLOC(size_t);
+#endif
+#else
+# ifdef VBOX_USE_IPRT_IN_NSPR
+# include <iprt/mem.h>
+# define MALLOC RTMemAlloc
+# else
+#define MALLOC malloc
+# endif
+#endif
+
+#ifndef Omit_Private_Memory
+#ifndef PRIVATE_MEM
+#define PRIVATE_MEM 2304
+#endif
+#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
+static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
+#endif
+
+#undef IEEE_Arith
+#undef Avoid_Underflow
+#ifdef IEEE_MC68k
+#define IEEE_Arith
+#endif
+#ifdef IEEE_8087
+#define IEEE_Arith
+#endif
+#ifdef IEEE_ARM
+#define IEEE_Arith
+#endif
+
+#include "errno.h"
+
+#ifdef Bad_float_h
+
+#ifdef IEEE_Arith
+#define DBL_DIG 15
+#define DBL_MAX_10_EXP 308
+#define DBL_MAX_EXP 1024
+#define FLT_RADIX 2
+#endif /*IEEE_Arith*/
+
+#ifdef IBM
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 75
+#define DBL_MAX_EXP 63
+#define FLT_RADIX 16
+#define DBL_MAX 7.2370055773322621e+75
+#endif
+
+#ifdef VAX
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 38
+#define DBL_MAX_EXP 127
+#define FLT_RADIX 2
+#define DBL_MAX 1.7014118346046923e+38
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#else /* ifndef Bad_float_h */
+#include "float.h"
+/*
+ * MacOS 10.2 defines the macro FLT_ROUNDS to an internal function
+ * which does not exist on 10.1. We can safely #define it to 1 here
+ * to allow 10.2 builds to run on 10.1, since we can't use fesetround()
+ * (which does not exist on 10.1 either).
+ */
+#if defined(MACOS_DEPLOYMENT_TARGET) && (MACOS_DEPLOYMENT_TARGET < 100200)
+#undef FLT_ROUNDS
+#define FLT_ROUNDS 1
+#endif
+#endif /* Bad_float_h */
+
+#ifndef __MATH_H__
+#include "math.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CONST
+#ifdef KR_headers
+#define CONST /* blank */
+#else
+#define CONST const
+#endif
+#endif
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) + defined(VAX) + defined(IBM) != 1
+Exactly one of IEEE_8087, IEEE_MC68k, IEEE_ARM, VAX, or IBM should be defined.
+#endif
+
+typedef union { double d; ULong L[2]; } U;
+
+#ifdef YES_ALIAS
+#define dval(x) x
+#ifdef IEEE_8087
+#define word0(x) ((ULong *)&x)[1]
+#define word1(x) ((ULong *)&x)[0]
+#else
+#define word0(x) ((ULong *)&x)[0]
+#define word1(x) ((ULong *)&x)[1]
+#endif
+#else
+#ifdef IEEE_8087
+#define word0(x) ((U*)&x)->L[1]
+#define word1(x) ((U*)&x)->L[0]
+#else
+#define word0(x) ((U*)&x)->L[0]
+#define word1(x) ((U*)&x)->L[1]
+#endif
+#define dval(x) ((U*)&x)->d
+#endif
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) + defined(IEEE_ARM) + defined(VAX)
+#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
+((unsigned short *)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
+((unsigned short *)a)[1] = (unsigned short)c, a++)
+#endif
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#ifdef IEEE_Arith
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+#ifndef NO_IEEE_Scale
+#define Avoid_Underflow
+#ifdef Flush_Denorm /* debugging option */
+#undef Sudden_Underflow
+#endif
+#endif
+
+#ifndef Flt_Rounds
+#ifdef FLT_ROUNDS
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+#ifdef Honor_FLT_ROUNDS
+#define Rounding rounding
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+#else /* ifndef IEEE_Arith */
+#undef Check_FLT_ROUNDS
+#undef Honor_FLT_ROUNDS
+#undef SET_INEXACT
+#undef Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#undef Flt_Rounds
+#define Flt_Rounds 0
+#define Exp_shift 24
+#define Exp_shift1 24
+#define Exp_msk1 0x1000000
+#define Exp_msk11 0x1000000
+#define Exp_mask 0x7f000000
+#define P 14
+#define Bias 65
+#define Exp_1 0x41000000
+#define Exp_11 0x41000000
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask 0xffffff
+#define Frac_mask1 0xffffff
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask 0xefffff
+#define Bndry_mask1 0xffffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 4
+#define Tiny0 0x100000
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#undef Flt_Rounds
+#define Flt_Rounds 1
+#define Exp_shift 23
+#define Exp_shift1 7
+#define Exp_msk1 0x80
+#define Exp_msk11 0x800000
+#define Exp_mask 0x7f80
+#define P 56
+#define Bias 129
+#define Exp_1 0x40800000
+#define Exp_11 0x4080
+#define Ebits 8
+#define Frac_mask 0x7fffff
+#define Frac_mask1 0xffff007f
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask 0xffff007f
+#define Bndry_mask1 0xffff007f
+#define LSB 0x10000
+#define Sign_bit 0x8000
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif /* IBM, VAX */
+#endif /* IEEE_Arith */
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+#ifdef KR_headers
+extern double rnd_prod(), rnd_quot();
+#else
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#endif
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#ifdef KR_headers
+#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff)
+#else
+#define FFFFFFFF 0xffffffffUL
+#endif
+
+#ifdef NO_LONG_LONG
+#undef ULLong
+#ifdef Just_16
+#undef Pack_32
+/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per Long.
+ */
+#endif
+#else /* long long available */
+#ifndef Llong
+#define Llong long long
+#endif
+#ifndef ULLong
+#define ULLong unsigned Llong
+#endif
+#endif /* NO_LONG_LONG */
+
+#ifndef MULTIPLE_THREADS
+#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
+#define FREE_DTOA_LOCK(n) /*nothing*/
+#endif
+
+#define Kmax 15
+
+ struct
+Bigint {
+ struct Bigint *next;
+ int k, maxwds, sign, wds;
+ ULong x[1];
+ };
+
+ typedef struct Bigint Bigint;
+
+ static Bigint *freelist[Kmax+1];
+
+ static Bigint *
+Balloc
+#ifdef KR_headers
+ (k) int k;
+#else
+ (int k)
+#endif
+{
+ int x;
+ Bigint *rv;
+#ifndef Omit_Private_Memory
+ unsigned int len;
+#endif
+
+ ACQUIRE_DTOA_LOCK(0);
+ if (rv = freelist[k]) {
+ freelist[k] = rv->next;
+ }
+ else {
+ x = 1 << k;
+#ifdef Omit_Private_Memory
+ rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+#else
+ len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+ /sizeof(double);
+ if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ rv = (Bigint*)pmem_next;
+ pmem_next += len;
+ }
+ else
+ rv = (Bigint*)MALLOC(len*sizeof(double));
+#endif
+ rv->k = k;
+ rv->maxwds = x;
+ }
+ FREE_DTOA_LOCK(0);
+ rv->sign = rv->wds = 0;
+ return rv;
+ }
+
+ static void
+Bfree
+#ifdef KR_headers
+ (v) Bigint *v;
+#else
+ (Bigint *v)
+#endif
+{
+ if (v) {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
+ }
+
+#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
+y->wds*sizeof(Long) + 2*sizeof(int))
+
+ static Bigint *
+multadd
+#ifdef KR_headers
+ (b, m, a) Bigint *b; int m, a;
+#else
+ (Bigint *b, int m, int a) /* multiply by m and add a */
+#endif
+{
+ int i, wds;
+#ifdef ULLong
+ ULong *x;
+ ULLong carry, y;
+#else
+ ULong carry, *x, y;
+#ifdef Pack_32
+ ULong xi, z;
+#endif
+#endif
+ Bigint *b1;
+
+ wds = b->wds;
+ x = b->x;
+ i = 0;
+ carry = a;
+ do {
+#ifdef ULLong
+ y = *x * (ULLong)m + carry;
+ carry = y >> 32;
+ *x++ = y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ xi = *x;
+ y = (xi & 0xffff) * m + carry;
+ z = (xi >> 16) * m + (y >> 16);
+ carry = z >> 16;
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ y = *x * m + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(++i < wds);
+ if (carry) {
+ if (wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ Bcopy(b1, b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[wds++] = carry;
+ b->wds = wds;
+ }
+ return b;
+ }
+
+ static Bigint *
+s2b
+#ifdef KR_headers
+ (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
+#else
+ (CONST char *s, int nd0, int nd, ULong y9)
+#endif
+{
+ Bigint *b;
+ int i, k;
+ Long x, y;
+
+ x = (nd + 8) / 9;
+ for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+ b = Balloc(k);
+ b->x[0] = y9;
+ b->wds = 1;
+#else
+ b = Balloc(k+1);
+ b->x[0] = y9 & 0xffff;
+ b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do b = multadd(b, 10, *s++ - '0');
+ while(++i < nd0);
+ s++;
+ }
+ else
+ s += 10;
+ for(; i < nd; i++)
+ b = multadd(b, 10, *s++ - '0');
+ return b;
+ }
+
+ static int
+hi0bits
+#ifdef KR_headers
+ (x) register ULong x;
+#else
+ (register ULong x)
+#endif
+{
+ register int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+ }
+
+ static int
+lo0bits
+#ifdef KR_headers
+ (y) ULong *y;
+#else
+ (ULong *y)
+#endif
+{
+ register int k;
+ register ULong x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x)
+ return 32;
+ }
+ *y = x;
+ return k;
+ }
+
+ static Bigint *
+i2b
+#ifdef KR_headers
+ (i) int i;
+#else
+ (int i)
+#endif
+{
+ Bigint *b;
+
+ b = Balloc(1);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+ }
+
+ static Bigint *
+mult
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int k, wa, wb, wc;
+ ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ ULong y;
+#ifdef ULLong
+ ULLong carry, z;
+#else
+ ULong carry, z;
+#ifdef Pack_32
+ ULong z2;
+#endif
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->k;
+ wa = a->wds;
+ wb = b->wds;
+ wc = wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c = Balloc(k);
+ for(x = c->x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef ULLong
+ for(; xb < xbe; xc0++) {
+ if (y = *xb++) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * (ULLong)y + *xc + carry;
+ carry = z >> 32;
+ *xc++ = z & FFFFFFFF;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#else
+#ifdef Pack_32
+ for(; xb < xbe; xb++, xc0++) {
+ if (y = *xb & 0xffff) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ if (y = *xb >> 16) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ }
+ while(x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if (y = *xb++) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+#endif
+ for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
+ c->wds = wc;
+ return c;
+ }
+
+ static Bigint *p5s;
+
+ static Bigint *
+pow5mult
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ Bigint *b1, *p5, *p51;
+ int i;
+ static int p05[3] = { 5, 25, 125 };
+
+ if (i = k & 3)
+ b = multadd(b, p05[i-1], 0);
+
+ if (!(k >>= 2))
+ return b;
+ if (!(p5 = p5s)) {
+ /* first time */
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p5 = p5s)) {
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+#endif
+ }
+ for(;;) {
+ if (k & 1) {
+ b1 = mult(b, p5);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+ if (!(p51 = p5->next)) {
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p51 = p5->next)) {
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+#endif
+ }
+ p5 = p51;
+ }
+ return b;
+ }
+
+ static Bigint *
+lshift
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ int i, k1, n, n1;
+ Bigint *b1;
+ ULong *x, *x1, *xe, z;
+
+#ifdef Pack_32
+ n = k >> 5;
+#else
+ n = k >> 4;
+#endif
+ k1 = b->k;
+ n1 = n + b->wds + 1;
+ for(i = b->maxwds; n1 > i; i <<= 1)
+ k1++;
+ b1 = Balloc(k1);
+ x1 = b1->x;
+ for(i = 0; i < n; i++)
+ *x1++ = 0;
+ x = b->x;
+ xe = x + b->wds;
+#ifdef Pack_32
+ if (k &= 0x1f) {
+ k1 = 32 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if (*x1 = z)
+ ++n1;
+ }
+#else
+ if (k &= 0xf) {
+ k1 = 16 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k & 0xffff | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if (*x1 = z)
+ ++n1;
+ }
+#endif
+ else do
+ *x1++ = *x++;
+ while(x < xe);
+ b1->wds = n1 - 1;
+ Bfree(b);
+ return b1;
+ }
+
+ static int
+cmp
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ ULong *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->wds;
+ j = b->wds;
+#ifdef DEBUG
+ if (i > 1 && !a->x[i-1])
+ Bug("cmp called with a->x[a->wds-1] == 0");
+ if (j > 1 && !b->x[j-1])
+ Bug("cmp called with b->x[b->wds-1] == 0");
+#endif
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for(;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+ }
+
+ static Bigint *
+diff
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int i, wa, wb;
+ ULong *xa, *xae, *xb, *xbe, *xc;
+#ifdef ULLong
+ ULLong borrow, y;
+#else
+ ULong borrow, y;
+#ifdef Pack_32
+ ULong z;
+#endif
+#endif
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ }
+ else
+ i = 0;
+ c = Balloc(a->k);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+ borrow = 0;
+#ifdef ULLong
+ do {
+ y = (ULLong)*xa++ - *xb++ - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *xc++ = y & FFFFFFFF;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *xc++ = y & FFFFFFFF;
+ }
+#else
+#ifdef Pack_32
+ do {
+ y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = (*xa & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ y = *xa++ - *xb++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+#endif
+ while(!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+ }
+
+ static double
+ulp
+#ifdef KR_headers
+ (x) double x;
+#else
+ (double x)
+#endif
+{
+ register Long L;
+ double a;
+
+ L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#endif
+#ifdef IBM
+ L |= Exp_msk1 >> 4;
+#endif
+ word0(a) = L;
+ word1(a) = 0;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ }
+ else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ word0(a) = 0x80000 >> L;
+ word1(a) = 0;
+ }
+ else {
+ word0(a) = 0;
+ L -= Exp_shift;
+ word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ }
+ }
+#endif
+#endif
+ return dval(a);
+ }
+
+ static double
+b2d
+#ifdef KR_headers
+ (a, e) Bigint *a; int *e;
+#else
+ (Bigint *a, int *e)
+#endif
+{
+ ULong *xa, *xa0, w, y, z;
+ int k;
+ double d;
+#ifdef VAX
+ ULong d0, d1;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+ xa0 = a->x;
+ xa = xa0 + a->wds;
+ y = *--xa;
+#ifdef DEBUG
+ if (!y) Bug("zero y in b2d");
+#endif
+ k = hi0bits(y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits) {
+ d0 = Exp_1 | y >> Ebits - k;
+ w = xa > xa0 ? *--xa : 0;
+ d1 = y << (32-Ebits) + k | w >> Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits) {
+ d0 = Exp_1 | y << k | z >> 32 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k | y >> 32 - k;
+ }
+ else {
+ d0 = Exp_1 | y;
+ d1 = z;
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ ret_d:
+#ifdef VAX
+ word0(d) = d0 >> 16 | d0 << 16;
+ word1(d) = d1 >> 16 | d1 << 16;
+#else
+#undef d0
+#undef d1
+#endif
+ return dval(d);
+ }
+
+ static Bigint *
+d2b
+#ifdef KR_headers
+ (d, e, bits) double d; int *e, *bits;
+#else
+ (double d, int *e, int *bits)
+#endif
+{
+ Bigint *b;
+ int de, k;
+ ULong *x, y, z;
+#ifndef Sudden_Underflow
+ int i;
+#endif
+#ifdef VAX
+ ULong d0, d1;
+ d0 = word0(d) >> 16 | word0(d) << 16;
+ d1 = word1(d) >> 16 | word1(d) << 16;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ x = b->x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(d0 >> Exp_shift);
+#ifndef IBM
+ z |= Exp_msk11;
+#endif
+#else
+ if (de = (int)(d0 >> Exp_shift))
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if (y = d1) {
+ if (k = lo0bits(&y)) {
+ x[0] = y | z << 32 - k;
+ z >>= k;
+ }
+ else
+ x[0] = y;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = (x[1] = z) ? 2 : 1;
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ x[0] = z;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = 1;
+ k += 32;
+ }
+#else
+ if (y = d1) {
+ if (k = lo0bits(&y))
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k+16;
+ i = 3;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ }
+ else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ }
+ while(!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+#ifdef IBM
+ *e = (de - Bias - (P-1) << 2) + k;
+ *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+#else
+ *e = de - Bias - (P-1) + k;
+ *bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+ }
+ else {
+ *e = de - Bias - (P-1) + 1 + k;
+#ifdef Pack_32
+ *bits = 32*i - hi0bits(x[i-1]);
+#else
+ *bits = (i+2)*16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+ }
+#undef d0
+#undef d1
+
+ static double
+ratio
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ double da, db;
+ int k, ka, kb;
+
+ dval(da) = b2d(a, &ka);
+ dval(db) = b2d(b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32*(a->wds - b->wds);
+#else
+ k = ka - kb + 16*(a->wds - b->wds);
+#endif
+#ifdef IBM
+ if (k > 0) {
+ word0(da) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(da) *= 1 << k;
+ }
+ else {
+ k = -k;
+ word0(db) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(db) *= 1 << k;
+ }
+#else
+ if (k > 0)
+ word0(da) += k*Exp_msk1;
+ else {
+ k = -k;
+ word0(db) += k*Exp_msk1;
+ }
+#endif
+ return dval(da) / dval(db);
+ }
+
+ static CONST double
+tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+#ifdef VAX
+ , 1e23, 1e24
+#endif
+ };
+
+ static CONST double
+#ifdef IEEE_Arith
+bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+#ifdef Avoid_Underflow
+ 9007199254740992.*9007199254740992.e-256
+ /* = 2^106 * 1e-53 */
+#else
+ 1e-256
+#endif
+ };
+/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
+#define Scale_Bit 0x10
+#define n_bigtens 5
+#else
+#ifdef IBM
+bigtens[] = { 1e16, 1e32, 1e64 };
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
+#define n_bigtens 3
+#else
+bigtens[] = { 1e16, 1e32 };
+static CONST double tinytens[] = { 1e-16, 1e-32 };
+#define n_bigtens 2
+#endif
+#endif
+
+#ifndef IEEE_Arith
+#undef INFNAN_CHECK
+#endif
+
+#ifdef INFNAN_CHECK
+
+#ifndef NAN_WORD0
+#define NAN_WORD0 0x7ff80000
+#endif
+
+#ifndef NAN_WORD1
+#define NAN_WORD1 0
+#endif
+
+ static int
+match
+#ifdef KR_headers
+ (sp, t) char **sp, *t;
+#else
+ (CONST char **sp, char *t)
+#endif
+{
+ int c, d;
+ CONST char *s = *sp;
+
+ while(d = *t++) {
+ if ((c = *++s) >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != d)
+ return 0;
+ }
+ *sp = s + 1;
+ return 1;
+ }
+
+#ifndef No_Hex_NaN
+ static void
+hexnan
+#ifdef KR_headers
+ (rvp, sp) double *rvp; CONST char **sp;
+#else
+ (double *rvp, CONST char **sp)
+#endif
+{
+ ULong c, x[2];
+ CONST char *s;
+ int havedig, udx0, xshift;
+
+ x[0] = x[1] = 0;
+ havedig = xshift = 0;
+ udx0 = 1;
+ s = *sp;
+ while(c = *(CONST unsigned char*)++s) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c += 10 - 'a';
+ else if (c >= 'A' && c <= 'F')
+ c += 10 - 'A';
+ else if (c <= ' ') {
+ if (udx0 && havedig) {
+ udx0 = 0;
+ xshift = 1;
+ }
+ continue;
+ }
+ else if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ }
+ else
+ return; /* invalid form: don't change *sp */
+ havedig = 1;
+ if (xshift) {
+ xshift = 0;
+ x[0] = x[1];
+ x[1] = 0;
+ }
+ if (udx0)
+ x[0] = (x[0] << 4) | (x[1] >> 28);
+ x[1] = (x[1] << 4) | c;
+ }
+ if ((x[0] &= 0xfffff) || x[1]) {
+ word0(*rvp) = Exp_mask | x[0];
+ word1(*rvp) = x[1];
+ }
+ }
+#endif /*No_Hex_NaN*/
+#endif /* INFNAN_CHECK */
+
+ PR_IMPLEMENT(double)
+PR_strtod
+#ifdef KR_headers
+ (s00, se) CONST char *s00; char **se;
+#else
+ (CONST char *s00, char **se)
+#endif
+{
+#ifdef Avoid_Underflow
+ int scale;
+#endif
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ CONST char *s, *s0, *s1;
+ double aadj, aadj1, adj, rv, rv0;
+ Long L;
+ ULong y, z;
+ Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+#ifdef USE_LOCALE
+ CONST char *s2;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ sign = nz0 = nz = 0;
+ dval(rv) = 0.;
+ for(s = s00;;s++) switch(*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ goto ret0;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+ break2:
+ if (*s == '0') {
+ nz0 = 1;
+ while(*++s == '0') ;
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = 10*y + c - '0';
+ else if (nd < 16)
+ z = 10*z + c - '0';
+ nd0 = nd;
+#ifdef USE_LOCALE
+ s1 = localeconv()->decimal_point;
+ if (c == *s1) {
+ c = '.';
+ if (*++s1) {
+ s2 = s;
+ for(;;) {
+ if (*++s2 != *s1) {
+ c = 0;
+ break;
+ }
+ if (!*++s1) {
+ s = s2;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if (c == '.') {
+ c = *++s;
+ if (!nd) {
+ for(; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for(i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10*y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10*z + c;
+ nz = 0;
+ }
+ }
+ }
+ dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ goto ret0;
+ }
+ s00 = s;
+ esign = 0;
+ switch(c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while(c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while((c = *++s) >= '0' && c <= '9')
+ L = 10*L + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ }
+ else
+ e = 0;
+ }
+ else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ word0(rv) = 0x7ff00000;
+ word1(rv) = 0;
+ goto ret;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (match(&s, "an")) {
+ word0(rv) = NAN_WORD0;
+ word1(rv) = NAN_WORD1;
+#ifndef No_Hex_NaN
+ if (*s == '(') /*)*/
+ hexnan(&rv, &s);
+#endif
+ goto ret;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ ret0:
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ dval(rv) = y;
+ if (k > 9) {
+#ifdef SET_INEXACT
+ if (k > DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+ dval(rv) = tens[k - 9] * dval(rv) + z;
+ }
+ bd0 = 0;
+ if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+#ifndef Honor_FLT_ROUNDS
+ && Flt_Rounds == 1
+#endif
+#endif
+ ) {
+ if (!e)
+ goto ret;
+ if (e > 0) {
+ if (e <= Ten_pmax) {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ goto ret;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ e -= i;
+ dval(rv) *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ word0(rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ if ((word0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+ goto ovfl;
+ word0(rv) += P*Exp_msk1;
+#else
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+#endif
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+#ifdef IEEE_Arith
+#ifdef SET_INEXACT
+ inexact = 1;
+ if (k <= DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+ scale = 0;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding = Flt_Rounds) >= 2) {
+ if (sign)
+ rounding = rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding = 0;
+ }
+#endif
+#endif /*IEEE_Arith*/
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if (i = e1 & 15)
+ dval(rv) *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ ovfl:
+#ifndef NO_ERRNO
+ PR_SetError(PR_RANGE_ERROR, 0);
+#endif
+ /* Can't trust HUGE_VAL */
+#ifdef IEEE_Arith
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case 0: /* toward 0 */
+ case 3: /* toward -infinity */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ break;
+ default:
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+ }
+#else /*Honor_FLT_ROUNDS*/
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+#endif /*Honor_FLT_ROUNDS*/
+#ifdef SET_INEXACT
+ /* set overflow bit */
+ dval(rv0) = 1e300;
+ dval(rv0) *= dval(rv0);
+#endif
+#else /*IEEE_Arith*/
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+#endif /*IEEE_Arith*/
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ e1 >>= 4;
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= bigtens[j];
+ /* The last multiplication could overflow. */
+ word0(rv) -= P*Exp_msk1;
+ dval(rv) *= bigtens[j];
+ if ((z = word0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+ goto ovfl;
+ if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ }
+ else
+ word0(rv) += P*Exp_msk1;
+ }
+ }
+ else if (e1 < 0) {
+ e1 = -e1;
+ if (i = e1 & 15)
+ dval(rv) /= tens[i];
+ if (e1 >>= 4) {
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+#ifdef Avoid_Underflow
+ if (e1 & Scale_Bit)
+ scale = 2*P;
+ for(j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ >> Exp_shift)) > 0) {
+ /* scaled rv is denormal; zap j low bits */
+ if (j >= 32) {
+ word1(rv) = 0;
+ if (j >= 53)
+ word0(rv) = (P+2)*Exp_msk1;
+ else
+ word0(rv) &= 0xffffffff << j-32;
+ }
+ else
+ word1(rv) &= 0xffffffff << j;
+ }
+#else
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ /* The last multiplication could underflow. */
+ dval(rv0) = dval(rv);
+ dval(rv) *= tinytens[j];
+ if (!dval(rv)) {
+ dval(rv) = 2.*dval(rv0);
+ dval(rv) *= tinytens[j];
+#endif
+ if (!dval(rv)) {
+ undfl:
+ dval(rv) = 0.;
+#ifndef NO_ERRNO
+ PR_SetError(PR_RANGE_ERROR, 0);
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+#ifndef Avoid_Underflow
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+#endif
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y);
+
+ for(;;) {
+ bd = Balloc(bd0->k);
+ Bcopy(bd, bd0);
+ bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bs = i2b(1);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Honor_FLT_ROUNDS
+ if (rounding != 1)
+ bs2++;
+#endif
+#ifdef Avoid_Underflow
+ j = bbe - scale;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+#ifdef IBM
+ j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+ j = P + 1 - bbbits;
+#endif
+#else /*Sudden_Underflow*/
+ j = bbe;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ bb2 += j;
+ bd2 += j;
+#ifdef Avoid_Underflow
+ bd2 += scale;
+#endif
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ bb1 = mult(bs, bb);
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift(bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult(bd, bd5);
+ if (bd2 > 0)
+ bd = lshift(bd, bd2);
+ if (bs2 > 0)
+ bs = lshift(bs, bs2);
+ delta = diff(bb, bd);
+ dsign = delta->sign;
+ delta->sign = 0;
+ i = cmp(delta, bs);
+#ifdef Honor_FLT_ROUNDS
+ if (rounding != 1) {
+ if (i < 0) {
+ /* Error is less than an ulp */
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (rounding) {
+ if (dsign) {
+ adj = 1.;
+ goto apply_adj;
+ }
+ }
+ else if (!dsign) {
+ adj = -1.;
+ if (!word1(rv)
+ && !(word0(rv) & Frac_mask)) {
+ y = word0(rv) & Exp_mask;
+#ifdef Avoid_Underflow
+ if (!scale || y > 2*P*Exp_msk1)
+#else
+ if (y)
+#endif
+ {
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) <= 0)
+ adj = -0.5;
+ }
+ }
+ apply_adj:
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(rv) & Exp_mask)
+ <= 2*P*Exp_msk1)
+ word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <=
+ P*Exp_msk1) {
+ word0(rv) += P*Exp_msk1;
+ dval(rv) += adj*ulp(dval(rv));
+ word0(rv) -= P*Exp_msk1;
+ }
+ else
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ dval(rv) += adj*ulp(dval(rv));
+ }
+ break;
+ }
+ adj = ratio(delta, bs);
+ if (adj < 1.)
+ adj = 1.;
+ if (adj <= 0x7ffffffe) {
+ /* adj = rounding ? ceil(adj) : floor(adj); */
+ y = adj;
+ if (y != adj) {
+ if (!((rounding>>1) ^ dsign))
+ y++;
+ adj = y;
+ }
+ }
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(rv) += P*Exp_msk1;
+ adj *= ulp(dval(rv));
+ if (dsign)
+ dval(rv) += adj;
+ else
+ dval(rv) -= adj;
+ word0(rv) -= P*Exp_msk1;
+ goto cont;
+ }
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ adj *= ulp(dval(rv));
+ if (dsign)
+ dval(rv) += adj;
+ else
+ dval(rv) -= adj;
+ goto cont;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask
+#ifdef IEEE_Arith
+#ifdef Avoid_Underflow
+ || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+#else
+ || (word0(rv) & Exp_mask) <= Exp_msk1
+#endif
+#endif
+ ) {
+#ifdef SET_INEXACT
+ if (!delta->x[0] && delta->wds <= 1)
+ inexact = 0;
+#endif
+ break;
+ }
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact result */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((word0(rv) & Bndry_mask1) == Bndry_mask1
+ && word1(rv) == (
+#ifdef Avoid_Underflow
+ (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
+#endif
+ 0xffffffff)) {
+ /*boundary case -- increment exponent*/
+ word0(rv) = (word0(rv) & Exp_mask)
+ + Exp_msk1
+#ifdef IBM
+ | Exp_msk1 >> 4
+#endif
+ ;
+ word1(rv) = 0;
+#ifdef Avoid_Underflow
+ dsign = 0;
+#endif
+ break;
+ }
+ }
+ else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+ L = word0(rv) & Exp_mask;
+#ifdef IBM
+ if (L < Exp_msk1)
+#else
+#ifdef Avoid_Underflow
+ if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
+#else
+ if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+#endif /*IBM*/
+ goto undfl;
+ L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+ if (scale) {
+ L = word0(rv) & Exp_mask;
+ if (L <= (2*P+1)*Exp_msk1) {
+ if (L > (P+2)*Exp_msk1)
+ /* round even ==> */
+ /* accept rv */
+ break;
+ /* rv = smallest denormal */
+ goto undfl;
+ }
+ }
+#endif /*Avoid_Underflow*/
+ L = (word0(rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}}*/
+ word0(rv) = L | Bndry_mask1;
+ word1(rv) = 0xffffffff;
+#ifdef IBM
+ goto cont;
+#else
+ break;
+#endif
+ }
+#ifndef ROUND_BIASED
+ if (!(word1(rv) & LSB))
+ break;
+#endif
+ if (dsign)
+ dval(rv) += ulp(dval(rv));
+#ifndef ROUND_BIASED
+ else {
+ dval(rv) -= ulp(dval(rv));
+#ifndef Sudden_Underflow
+ if (!dval(rv))
+ goto undfl;
+#endif
+ }
+#ifdef Avoid_Underflow
+ dsign = 1 - dsign;
+#endif
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = aadj1 = 1.;
+ else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (word1(rv) == Tiny1 && !word0(rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ aadj1 = -1.;
+ }
+ else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2./FLT_RADIX)
+ aadj = 1./FLT_RADIX;
+ else
+ aadj *= 0.5;
+ aadj1 = -aadj;
+ }
+ }
+ else {
+ aadj *= 0.5;
+ aadj1 = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch(Rounding) {
+ case 2: /* towards +infinity */
+ aadj1 -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ aadj1 += 0.5;
+ }
+#else
+ if (Flt_Rounds == 0)
+ aadj1 += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+ }
+ y = word0(rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
+ dval(rv0) = dval(rv);
+ word0(rv) -= P*Exp_msk1;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+ if ((word0(rv) & Exp_mask) >=
+ Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
+ if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ goto ovfl;
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ goto cont;
+ }
+ else
+ word0(rv) += P*Exp_msk1;
+ }
+ else {
+#ifdef Avoid_Underflow
+ if (scale && y <= 2*P*Exp_msk1) {
+ if (aadj <= 0x7fffffff) {
+ if ((z = aadj) <= 0)
+ z = 1;
+ aadj = z;
+ aadj1 = dsign ? aadj : -aadj;
+ }
+ word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ }
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(rv0) = dval(rv);
+ word0(rv) += P*Exp_msk1;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#ifdef IBM
+ if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+#else
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+#endif
+ {
+ if (word0(rv0) == Tiny0
+ && word1(rv0) == Tiny1)
+ goto undfl;
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0(rv) -= P*Exp_msk1;
+ }
+ else {
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+ }
+#else /*Sudden_Underflow*/
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv + adj in some half-way cases.
+ * If rv * ulp(rv) is denormalized (i.e.,
+ * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
+ aadj1 = (double)(int)(aadj + 0.5);
+ if (!dsign)
+ aadj1 = -aadj1;
+ }
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ }
+ z = word0(rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+ if (!scale)
+#endif
+ if (y == z) {
+ /* Can we stop now? */
+ L = (Long)aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ }
+ else if (aadj < .4999999/FLT_RADIX)
+ break;
+ }
+#endif
+ cont:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(rv0) = Exp_1 + (70 << Exp_shift);
+ word1(rv0) = 0;
+ dval(rv0) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+#ifdef Avoid_Underflow
+ if (scale) {
+ word0(rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(rv0) = 0;
+ dval(rv) *= dval(rv0);
+#ifndef NO_ERRNO
+ /* try to avoid the bug of testing an 8087 register value */
+ if (word0(rv) == 0 && word1(rv) == 0)
+ PR_SetError(PR_RANGE_ERROR, 0);
+#endif
+ }
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+ if (inexact && !(word0(rv) & Exp_mask)) {
+ /* set underflow bit */
+ dval(rv0) = 1e-300;
+ dval(rv0) *= dval(rv0);
+ }
+#endif
+ retfree:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ ret:
+ if (se)
+ *se = (char *)s;
+ return sign ? -dval(rv) : dval(rv);
+ }
+
+ static int
+quorem
+#ifdef KR_headers
+ (b, S) Bigint *b, *S;
+#else
+ (Bigint *b, Bigint *S)
+#endif
+{
+ int n;
+ ULong *bx, *bxe, q, *sx, *sxe;
+#ifdef ULLong
+ ULLong borrow, carry, y, ys;
+#else
+ ULong borrow, carry, y, ys;
+#ifdef Pack_32
+ ULong si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+#ifdef DEBUG
+ /*debug*/ if (b->wds > n)
+ /*debug*/ Bug("oversize b in quorem");
+#endif
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug("oversized quotient in quorem");
+#endif
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef ULLong
+ ys = *sx++ * (ULLong)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef ULLong
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+ }
+
+#ifndef MULTIPLE_THREADS
+ static char *dtoa_result;
+#endif
+
+ static char *
+#ifdef KR_headers
+rv_alloc(i) int i;
+#else
+rv_alloc(int i)
+#endif
+{
+ int j, k, *r;
+
+ j = sizeof(ULong);
+ for(k = 0;
+ sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
+ j <<= 1)
+ k++;
+ r = (int*)Balloc(k);
+ *r = k;
+ return
+#ifndef MULTIPLE_THREADS
+ dtoa_result =
+#endif
+ (char *)(r+1);
+ }
+
+ static char *
+#ifdef KR_headers
+nrv_alloc(s, rve, n) char *s, **rve; int n;
+#else
+nrv_alloc(char *s, char **rve, int n)
+#endif
+{
+ char *rv, *t;
+
+ t = rv = rv_alloc(n);
+ while(*t = *s++) t++;
+ if (rve)
+ *rve = t;
+ return rv;
+ }
+
+/* freedtoa(s) must be used to free values s returned by dtoa
+ * when MULTIPLE_THREADS is #defined. It should be used in all cases,
+ * but for consistency with earlier versions of dtoa, it is optional
+ * when MULTIPLE_THREADS is not defined.
+ */
+
+ void
+#ifdef KR_headers
+freedtoa(s) char *s;
+#else
+freedtoa(char *s)
+#endif
+{
+ Bigint *b = (Bigint *)((int *)s - 1);
+ b->maxwds = 1 << (b->k = *(int*)b);
+ Bfree(b);
+#ifndef MULTIPLE_THREADS
+ if (s == dtoa_result)
+ dtoa_result = 0;
+#endif
+ }
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the Long
+ * calculation.
+ */
+
+ static char *
+dtoa
+#ifdef KR_headers
+ (d, mode, ndigits, decpt, sign, rve)
+ double d; int mode, ndigits, *decpt, *sign; char **rve;
+#else
+ (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+#endif
+{
+ /* Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4,5 ==> similar to 2 and 3, respectively, but (in
+ round-nearest mode) with the tests of mode 0 to
+ possibly return a shorter string that rounds to d.
+ With IEEE arithmetic and compilation with
+ -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
+ as modes 2 and 3 when FLT_ROUNDS != 1.
+ 6-9 ==> Debugging modes similar to mode - 4: don't try
+ fast floating-point estimate (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ Long L;
+#ifndef Sudden_Underflow
+ int denorm;
+ ULong x;
+#endif
+ Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+ double d2, ds, eps;
+ char *s, *s0;
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+
+#ifndef MULTIPLE_THREADS
+ if (dtoa_result) {
+ freedtoa(dtoa_result);
+ dtoa_result = 0;
+ }
+#endif
+
+ if (word0(d) & Sign_bit) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0(d) &= ~Sign_bit; /* clear sign bit */
+ }
+ else
+ *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+ if ((word0(d) & Exp_mask) == Exp_mask)
+#else
+ if (word0(d) == 0x8000)
+#endif
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+#ifdef IEEE_Arith
+ if (!word1(d) && !(word0(d) & 0xfffff))
+ return nrv_alloc("Infinity", rve, 8);
+#endif
+ return nrv_alloc("NaN", rve, 3);
+ }
+#endif
+#ifdef IBM
+ dval(d) += 0; /* normalize */
+#endif
+ if (!dval(d)) {
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+#ifdef SET_INEXACT
+ try_quick = oldinexact = get_inexact();
+ inexact = 1;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding = Flt_Rounds) >= 2) {
+ if (*sign)
+ rounding = rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding = 0;
+ }
+#endif
+
+ b = d2b(dval(d), &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+ if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
+#endif
+ dval(d2) = dval(d);
+ word0(d2) &= Frac_mask1;
+ word0(d2) |= Exp_11;
+#ifdef IBM
+ if (j = 11 - hi0bits(word0(d2) & Frac_mask))
+ dval(d2) /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+#ifndef Sudden_Underflow
+ denorm = 0;
+ }
+ else {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P-1) - 1);
+ x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
+ : word1(d) << 32 - i;
+ dval(d2) = x;
+ word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+ i -= (Bias + (P-1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ k = (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax) {
+ if (dval(d) < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ }
+ else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+ try_quick = Rounding == 1;
+#else
+ try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+ if (mode > 5) {
+ mode -= 4;
+ try_quick = 0;
+ }
+ leftright = 1;
+ switch(mode) {
+ case 0:
+ case 1:
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ s = s0 = rv_alloc(i);
+
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1 && rounding != 1)
+ leftright = 0;
+#endif
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ dval(d2) = dval(d);
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k&0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(d) /= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for(; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ dval(d) /= ds;
+ }
+ else if (j1 = -k) {
+ dval(d) *= tens[j1 & 0xf];
+ for(j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ dval(d) *= bigtens[i];
+ }
+ }
+ if (k_check && dval(d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(d) *= 10.;
+ ieps++;
+ }
+ dval(eps) = ieps*dval(d) + 7.;
+ word0(eps) -= (P-1)*Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(d) -= 5.;
+ if (dval(d) > dval(eps))
+ goto one_digit;
+ if (dval(d) < -dval(eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+ for(i = 0;;) {
+ L = dval(d);
+ dval(d) -= L;
+ *s++ = '0' + (int)L;
+ if (dval(d) < dval(eps))
+ goto ret1;
+ if (1. - dval(d) < dval(eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(eps) *= 10.;
+ dval(d) *= 10.;
+ }
+ }
+ else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ dval(eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long)(dval(d));
+ if (!(dval(d) -= L))
+ ilim = i;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ if (dval(d) > 0.5 + dval(eps))
+ goto bump_up;
+ else if (dval(d) < 0.5 - dval(eps)) {
+ while(*--s == '0');
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ dval(d) = dval(d2);
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(d) <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long)(dval(d) / ds);
+ dval(d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(d) < 0) {
+ L--;
+ dval(d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (!dval(d)) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (i == ilim) {
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(rounding) {
+ case 0: goto ret1;
+ case 2: goto bump_up;
+ }
+#endif
+ dval(d) += dval(d);
+ if (dval(d) > ds || dval(d) == ds && L & 1) {
+ bump_up:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+ 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+ 1 + P - bbits;
+#endif
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ b1 = mult(mhi, b);
+ Bfree(b);
+ b = b1;
+ }
+ if (j = b5 - m5)
+ b = pow5mult(b, j);
+ }
+ else
+ b = pow5mult(b, b5);
+ }
+ S = i2b(1);
+ if (s5 > 0)
+ S = pow5mult(S, s5);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case = 0;
+ if ((mode < 2 || leftright)
+#ifdef Honor_FLT_ROUNDS
+ && rounding == 1
+#endif
+ ) {
+ if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & ~Exp_msk1)
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+#ifdef Pack_32
+ if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
+ i = 32 - i;
+#else
+ if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift(b, b2);
+ if (s2 > 0)
+ S = lshift(S, s2);
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd(mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && (mode == 3 || mode == 5)) {
+ if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+ /* no digits, fcvt style */
+ no_digits:
+ k = -1 - ndigits;
+ goto ret;
+ }
+ one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright) {
+ if (m2 > 0)
+ mhi = lshift(mhi, m2);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ }
+
+ for(i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+#ifdef Honor_FLT_ROUNDS
+ && rounding >= 1
+#endif
+ ) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+#ifdef SET_INEXACT
+ else if (!b->x[0] && b->wds <= 1)
+ inexact = 0;
+#endif
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || j == 0 && mode != 1
+#ifndef ROUND_BIASED
+ && !(word1(d) & 1)
+#endif
+ ) {
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto accept_dig;
+ }
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(rounding) {
+ case 0: goto accept_dig;
+ case 2: goto keep_dig;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ j1 = cmp(b, S);
+ if ((j1 > 0 || j1 == 0 && dig & 1)
+ && dig++ == '9')
+ goto round_9_up;
+ }
+ accept_dig:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+#ifdef Honor_FLT_ROUNDS
+ if (!rounding)
+ goto accept_dig;
+#endif
+ if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+#ifdef Honor_FLT_ROUNDS
+ keep_dig:
+#endif
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (mlo == mhi)
+ mlo = mhi = multadd(mhi, 10, 0);
+ else {
+ mlo = multadd(mlo, 10, 0);
+ mhi = multadd(mhi, 10, 0);
+ }
+ }
+ }
+ else
+ for(i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case 0: goto trimzeros;
+ case 2: goto roundoff;
+ }
+#endif
+ b = lshift(b, 1);
+ j = cmp(b, S);
+ if (j > 0 || j == 0 && dig & 1) {
+ roundoff:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else {
+ trimzeros:
+ while(*--s == '0');
+ s++;
+ }
+ ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ ret1:
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(d) = Exp_1 + (70 << Exp_shift);
+ word1(d) = 0;
+ dval(d) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+ }
+#ifdef __cplusplus
+}
+#endif
+
+PR_IMPLEMENT(PRStatus)
+PR_dtoa(PRFloat64 d, PRIntn mode, PRIntn ndigits,
+ PRIntn *decpt, PRIntn *sign, char **rve, char *buf, PRSize bufsize)
+{
+ char *result;
+ PRSize resultlen;
+ PRStatus rv = PR_FAILURE;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (mode < 0 || mode > 3) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return rv;
+ }
+ result = dtoa(d, mode, ndigits, decpt, sign, rve);
+ if (!result) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return rv;
+ }
+ resultlen = strlen(result)+1;
+ if (bufsize < resultlen) {
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ } else {
+ memcpy(buf, result, resultlen);
+ if (rve) {
+ *rve = buf + (*rve - result);
+ }
+ rv = PR_SUCCESS;
+ }
+ freedtoa(result);
+ return rv;
+}
+
+/*
+** conversion routines for floating point
+** prcsn - number of digits of precision to generate floating
+** point value.
+** This should be reparameterized so that you can send in a
+** prcn for the positive and negative ranges. For now,
+** conform to the ECMA JavaScript spec which says numbers
+** less than 1e-6 are in scientific notation.
+** Also, the ECMA spec says that there should always be a
+** '+' or '-' after the 'e' in scientific notation
+*/
+PR_IMPLEMENT(void)
+PR_cnvtf(char *buf,int bufsz, int prcsn,double fval)
+{
+ PRIntn decpt, sign, numdigits;
+ char *num, *nump;
+ char *bufp = buf;
+ char *endnum;
+
+ /* If anything fails, we store an empty string in 'buf' */
+ num = (char*)PR_MALLOC(bufsz);
+ if (num == NULL) {
+ buf[0] = '\0';
+ return;
+ }
+ /* XXX Why use mode 1? */
+ if (PR_dtoa(dval(fval),1,prcsn,&decpt,&sign,&endnum,num,bufsz)
+ == PR_FAILURE) {
+ buf[0] = '\0';
+ goto done;
+ }
+ numdigits = endnum - num;
+ nump = num;
+
+ if (sign &&
+ !(word0(fval) == Sign_bit && word1(fval) == 0) &&
+ !((word0(fval) & Exp_mask) == Exp_mask &&
+ (word1(fval) || (word0(fval) & 0xfffff)))) {
+ *bufp++ = '-';
+ }
+
+ if (decpt == 9999) {
+ while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */
+ goto done;
+ }
+
+ if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) {
+ *bufp++ = *nump++;
+ if (numdigits != 1) {
+ *bufp++ = '.';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = 'e';
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+d", decpt-1);
+ } else if (decpt >= 0) {
+ if (decpt == 0) {
+ *bufp++ = '0';
+ } else {
+ while (decpt--) {
+ if (*nump != '\0') {
+ *bufp++ = *nump++;
+ } else {
+ *bufp++ = '0';
+ }
+ }
+ }
+ if (*nump != '\0') {
+ *bufp++ = '.';
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ }
+ *bufp++ = '\0';
+ } else if (decpt < 0) {
+ *bufp++ = '0';
+ *bufp++ = '.';
+ while (decpt++) {
+ *bufp++ = '0';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = '\0';
+ }
+done:
+ PR_DELETE(num);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prenv.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prenv.c
new file mode 100644
index 00000000..7f9d5ab3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prenv.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <string.h>
+#include "primpl.h"
+
+/* Lock used to lock the environment */
+#if defined(_PR_NO_PREEMPT)
+#define _PR_NEW_LOCK_ENV()
+#define _PR_DELETE_LOCK_ENV()
+#define _PR_LOCK_ENV()
+#define _PR_UNLOCK_ENV()
+#elif defined(_PR_LOCAL_THREADS_ONLY)
+extern _PRCPU * _pr_primordialCPU;
+static PRIntn _is;
+#define _PR_NEW_LOCK_ENV()
+#define _PR_DELETE_LOCK_ENV()
+#define _PR_LOCK_ENV() if (_pr_primordialCPU) _PR_INTSOFF(_is);
+#define _PR_UNLOCK_ENV() if (_pr_primordialCPU) _PR_INTSON(_is);
+#else
+static PRLock *_pr_envLock = NULL;
+#define _PR_NEW_LOCK_ENV() {_pr_envLock = PR_NewLock();}
+#define _PR_DELETE_LOCK_ENV() \
+ { if (_pr_envLock) { PR_DestroyLock(_pr_envLock); _pr_envLock = NULL; } }
+#define _PR_LOCK_ENV() { if (_pr_envLock) PR_Lock(_pr_envLock); }
+#define _PR_UNLOCK_ENV() { if (_pr_envLock) PR_Unlock(_pr_envLock); }
+#endif
+
+/************************************************************************/
+
+void _PR_InitEnv(void)
+{
+ _PR_NEW_LOCK_ENV();
+}
+
+void _PR_CleanupEnv(void)
+{
+ _PR_DELETE_LOCK_ENV();
+}
+
+PR_IMPLEMENT(char*) PR_GetEnv(const char *var)
+{
+ char *ev;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ _PR_LOCK_ENV();
+ ev = _PR_MD_GET_ENV(var);
+ _PR_UNLOCK_ENV();
+ return ev;
+}
+
+PR_IMPLEMENT(PRStatus) PR_SetEnv(const char *string)
+{
+ PRIntn result;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if ( !strchr(string, '=')) return(PR_FAILURE);
+
+ _PR_LOCK_ENV();
+ result = _PR_MD_PUT_ENV((char*)string);
+ _PR_UNLOCK_ENV();
+ return (result)? PR_FAILURE : PR_SUCCESS;
+}
+
+/*
+** DEPRECATED. Use PR_SetEnv() instead.
+*/
+#ifdef XP_MAC
+PR_IMPLEMENT(PRIntn) PR_PutEnv(const char *string)
+{
+ return (PR_SetEnv(string) == PR_SUCCESS) ? PR_TRUE : PR_FALSE;
+}
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.c
new file mode 100644
index 00000000..81baadf3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.c
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *
+ * prerr.c
+ * This file is automatically generated; please do not edit it.
+ */
+#include "prerror.h"
+static const struct PRErrorMessage text[] = {
+ {"PR_OUT_OF_MEMORY_ERROR", "Memory allocation attempt failed"},
+ {"PR_BAD_DESCRIPTOR_ERROR", "Invalid file descriptor"},
+ {"PR_WOULD_BLOCK_ERROR", "The operation would have blocked"},
+ {"PR_ACCESS_FAULT_ERROR", "Invalid memory address argument"},
+ {"PR_INVALID_METHOD_ERROR", "Invalid function for file type"},
+ {"PR_ILLEGAL_ACCESS_ERROR", "Invalid memory address argument"},
+ {"PR_UNKNOWN_ERROR", "Some unknown error has occurred"},
+ {"PR_PENDING_INTERRUPT_ERROR", "Operation interrupted by another thread"},
+ {"PR_NOT_IMPLEMENTED_ERROR", "function not implemented"},
+ {"PR_IO_ERROR", "I/O function error"},
+ {"PR_IO_TIMEOUT_ERROR", "I/O operation timed out"},
+ {"PR_IO_PENDING_ERROR", "I/O operation on busy file descriptor"},
+ {"PR_DIRECTORY_OPEN_ERROR", "The directory could not be opened"},
+ {"PR_INVALID_ARGUMENT_ERROR", "Invalid function argument"},
+ {"PR_ADDRESS_NOT_AVAILABLE_ERROR", "Network address not available (in use?)"},
+ {"PR_ADDRESS_NOT_SUPPORTED_ERROR", "Network address type not supported"},
+ {"PR_IS_CONNECTED_ERROR", "Already connected"},
+ {"PR_BAD_ADDRESS_ERROR", "Network address is invalid"},
+ {"PR_ADDRESS_IN_USE_ERROR", "Local Network address is in use"},
+ {"PR_CONNECT_REFUSED_ERROR", "Connection refused by peer"},
+ {"PR_NETWORK_UNREACHABLE_ERROR", "Network address is presently unreachable"},
+ {"PR_CONNECT_TIMEOUT_ERROR", "Connection attempt timed out"},
+ {"PR_NOT_CONNECTED_ERROR", "Network file descriptor is not connected"},
+ {"PR_LOAD_LIBRARY_ERROR", "Failure to load dynamic library"},
+ {"PR_UNLOAD_LIBRARY_ERROR", "Failure to unload dynamic library"},
+ {"PR_FIND_SYMBOL_ERROR", "Symbol not found in any of the loaded dynamic libraries"},
+ {"PR_INSUFFICIENT_RESOURCES_ERROR", "Insufficient system resources"},
+ {"PR_DIRECTORY_LOOKUP_ERROR", "A directory lookup on a network address has failed"},
+ {"PR_TPD_RANGE_ERROR", "Attempt to access a TPD key that is out of range"},
+ {"PR_PROC_DESC_TABLE_FULL_ERROR", "Process open FD table is full"},
+ {"PR_SYS_DESC_TABLE_FULL_ERROR", "System open FD table is full"},
+ {"PR_NOT_SOCKET_ERROR", "Network operation attempted on non-network file descriptor"},
+ {"PR_NOT_TCP_SOCKET_ERROR", "TCP-specific function attempted on a non-TCP file descriptor"},
+ {"PR_SOCKET_ADDRESS_IS_BOUND_ERROR", "TCP file descriptor is already bound"},
+ {"PR_NO_ACCESS_RIGHTS_ERROR", "Access Denied"},
+ {"PR_OPERATION_NOT_SUPPORTED_ERROR", "The requested operation is not supported by the platform"},
+ {"PR_PROTOCOL_NOT_SUPPORTED_ERROR", "The host operating system does not support the protocol requested"},
+ {"PR_REMOTE_FILE_ERROR", "Access to the remote file has been severed"},
+ {"PR_BUFFER_OVERFLOW_ERROR", "The value requested is too large to be stored in the data buffer provided"},
+ {"PR_CONNECT_RESET_ERROR", "TCP connection reset by peer"},
+ {"PR_RANGE_ERROR", "Unused"},
+ {"PR_DEADLOCK_ERROR", "The operation would have deadlocked"},
+ {"PR_FILE_IS_LOCKED_ERROR", "The file is already locked"},
+ {"PR_FILE_TOO_BIG_ERROR", "Write would result in file larger than the system allows"},
+ {"PR_NO_DEVICE_SPACE_ERROR", "The device for storing the file is full"},
+ {"PR_PIPE_ERROR", "Unused"},
+ {"PR_NO_SEEK_DEVICE_ERROR", "Unused"},
+ {"PR_IS_DIRECTORY_ERROR", "Cannot perform a normal file operation on a directory"},
+ {"PR_LOOP_ERROR", "Symbolic link loop"},
+ {"PR_NAME_TOO_LONG_ERROR", "File name is too long"},
+ {"PR_FILE_NOT_FOUND_ERROR", "File not found"},
+ {"PR_NOT_DIRECTORY_ERROR", "Cannot perform directory operation on a normal file"},
+ {"PR_READ_ONLY_FILESYSTEM_ERROR", "Cannot write to a read-only file system"},
+ {"PR_DIRECTORY_NOT_EMPTY_ERROR", "Cannot delete a directory that is not empty"},
+ {"PR_FILESYSTEM_MOUNTED_ERROR", "Cannot delete or rename a file object while the file system is busy"},
+ {"PR_NOT_SAME_DEVICE_ERROR", "Cannot rename a file to a file system on another device"},
+ {"PR_DIRECTORY_CORRUPTED_ERROR", "The directory object in the file system is corrupted"},
+ {"PR_FILE_EXISTS_ERROR", "Cannot create or rename a filename that already exists"},
+ {"PR_MAX_DIRECTORY_ENTRIES_ERROR", "Directory is full. No additional filenames may be added"},
+ {"PR_INVALID_DEVICE_STATE_ERROR", "The required device was in an invalid state"},
+ {"PR_DEVICE_IS_LOCKED_ERROR", "The device is locked"},
+ {"PR_NO_MORE_FILES_ERROR", "No more entries in the directory"},
+ {"PR_END_OF_FILE_ERROR", "Encountered end of file"},
+ {"PR_FILE_SEEK_ERROR", "Seek error"},
+ {"PR_FILE_IS_BUSY_ERROR", "The file is busy"},
+ {"PR_OPERATION_ABORTED_ERROR", "The I/O operation was aborted"},
+ {"PR_IN_PROGRESS_ERROR", "Operation is still in progress (probably a non-blocking connect)"},
+ {"PR_ALREADY_INITIATED_ERROR", "Operation has already been initiated (probably a non-blocking connect)"},
+ {"PR_GROUP_EMPTY_ERROR", "The wait group is empty"},
+ {"PR_INVALID_STATE_ERROR", "Object state improper for request"},
+ {"PR_NETWORK_DOWN_ERROR", "Network is down"},
+ {"PR_SOCKET_SHUTDOWN_ERROR", "Socket shutdown"},
+ {"PR_CONNECT_ABORTED_ERROR", "Connection aborted"},
+ {"PR_HOST_UNREACHABLE_ERROR", "Host is unreachable"},
+ {"PR_LIBRARY_NOT_LOADED_ERROR", "The library is not loaded"},
+ {"PR_MAX_ERROR", "Placeholder for the end of the list"},
+ {0, 0}
+};
+
+static const struct PRErrorTable et = { text, "prerr", -6000L, 76 };
+
+void nspr_InitializePRErrorTable(void) {
+ PR_ErrorInstallTable(&et);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.et b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.et
new file mode 100644
index 00000000..9281ee6e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.et
@@ -0,0 +1,135 @@
+#
+# 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998-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.
+#
+
+et nspr -6000
+
+ec PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed"
+ec PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor"
+ec PR_WOULD_BLOCK_ERROR, "The operation would have blocked"
+ec PR_ACCESS_FAULT_ERROR, "Invalid memory address argument"
+ec PR_INVALID_METHOD_ERROR, "Invalid function for file type"
+ec PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument"
+ec PR_UNKNOWN_ERROR, "Some unknown error has occurred"
+ec PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread"
+ec PR_NOT_IMPLEMENTED_ERROR, "function not implemented"
+ec PR_IO_ERROR, "I/O function error"
+ec PR_IO_TIMEOUT_ERROR, "I/O operation timed out"
+ec PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor"
+ec PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened"
+ec PR_INVALID_ARGUMENT_ERROR, "Invalid function argument"
+ec PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)"
+ec PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported"
+ec PR_IS_CONNECTED_ERROR, "Already connected"
+ec PR_BAD_ADDRESS_ERROR, "Network address is invalid"
+ec PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use"
+ec PR_CONNECT_REFUSED_ERROR, "Connection refused by peer"
+ec PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable"
+ec PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out"
+ec PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected"
+ec PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library"
+ec PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library"
+ec PR_FIND_SYMBOL_ERROR,
+"Symbol not found in any of the loaded dynamic libraries"
+ec PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources"
+ec PR_DIRECTORY_LOOKUP_ERROR,
+"A directory lookup on a network address has failed"
+ec PR_TPD_RANGE_ERROR,
+"Attempt to access a TPD key that is out of range"
+ec PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full"
+ec PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full"
+ec PR_NOT_SOCKET_ERROR,
+"Network operation attempted on non-network file descriptor"
+ec PR_NOT_TCP_SOCKET_ERROR,
+"TCP-specific function attempted on a non-TCP file descriptor"
+ec PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound"
+ec PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied"
+ec PR_OPERATION_NOT_SUPPORTED_ERROR,
+"The requested operation is not supported by the platform"
+ec PR_PROTOCOL_NOT_SUPPORTED_ERROR,
+"The host operating system does not support the protocol requested"
+ec PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed"
+ec PR_BUFFER_OVERFLOW_ERROR,
+"The value requested is too large to be stored in the data buffer provided"
+ec PR_CONNECT_RESET_ERROR, "TCP connection reset by peer"
+ec PR_RANGE_ERROR, "Unused"
+ec PR_DEADLOCK_ERROR, "The operation would have deadlocked"
+ec PR_FILE_IS_LOCKED_ERROR, "The file is already locked"
+ec PR_FILE_TOO_BIG_ERROR,
+"Write would result in file larger than the system allows"
+ec PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full"
+ec PR_PIPE_ERROR, "Unused"
+ec PR_NO_SEEK_DEVICE_ERROR, "Unused"
+ec PR_IS_DIRECTORY_ERROR,
+"Cannot perform a normal file operation on a directory"
+ec PR_LOOP_ERROR, "Symbolic link loop"
+ec PR_NAME_TOO_LONG_ERROR, "File name is too long"
+ec PR_FILE_NOT_FOUND_ERROR, "File not found"
+ec PR_NOT_DIRECTORY_ERROR,
+"Cannot perform directory operation on a normal file"
+ec PR_READ_ONLY_FILESYSTEM_ERROR,
+"Cannot write to a read-only file system"
+ec PR_DIRECTORY_NOT_EMPTY_ERROR,
+"Cannot delete a directory that is not empty"
+ec PR_FILESYSTEM_MOUNTED_ERROR,
+"Cannot delete or rename a file object while the file system is busy"
+ec PR_NOT_SAME_DEVICE_ERROR,
+"Cannot rename a file to a file system on another device"
+ec PR_DIRECTORY_CORRUPTED_ERROR,
+"The directory object in the file system is corrupted"
+ec PR_FILE_EXISTS_ERROR,
+"Cannot create or rename a filename that already exists"
+ec PR_MAX_DIRECTORY_ENTRIES_ERROR,
+"Directory is full. No additional filenames may be added"
+ec PR_INVALID_DEVICE_STATE_ERROR,
+"The required device was in an invalid state"
+ec PR_DEVICE_IS_LOCKED_ERROR, "The device is locked"
+ec PR_NO_MORE_FILES_ERROR, "No more entries in the directory"
+ec PR_END_OF_FILE_ERROR, "Encountered end of file"
+ec PR_FILE_SEEK_ERROR, "Seek error"
+ec PR_FILE_IS_BUSY_ERROR, "The file is busy"
+ec PR_OPERATION_ABORTED_ERROR, "The I/O operation was aborted"
+ec PR_IN_PROGRESS_ERROR,
+"Operation is still in progress (probably a non-blocking connect)"
+ec PR_ALREADY_INITIATED_ERROR,
+"Operation has already been initiated (probably a non-blocking connect)"
+ec PR_GROUP_EMPTY_ERROR, "The wait group is empty"
+ec PR_INVALID_STATE_ERROR, "Object state improper for request"
+ec PR_NETWORK_DOWN_ERROR, "Network is down"
+ec PR_SOCKET_SHUTDOWN_ERROR, "Socket shutdown"
+ec PR_CONNECT_ABORTED_ERROR, "Connection aborted"
+ec PR_HOST_UNREACHABLE_ERROR, "Host is unreachable"
+ec PR_LIBRARY_NOT_LOADED_ERROR, "The library is not loaded"
+
+ec PR_MAX_ERROR, "Placeholder for the end of the list"
+
+end
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.properties b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.properties
new file mode 100644
index 00000000..c10f7c8b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerr.properties
@@ -0,0 +1,116 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#
+# prerr.properties
+# This file is automatically generated; please do not edit it.
+PR_OUT_OF_MEMORY_ERROR=Memory allocation attempt failed
+PR_BAD_DESCRIPTOR_ERROR=Invalid file descriptor
+PR_WOULD_BLOCK_ERROR=The operation would have blocked
+PR_ACCESS_FAULT_ERROR=Invalid memory address argument
+PR_INVALID_METHOD_ERROR=Invalid function for file type
+PR_ILLEGAL_ACCESS_ERROR=Invalid memory address argument
+PR_UNKNOWN_ERROR=Some unknown error has occurred
+PR_PENDING_INTERRUPT_ERROR=Operation interrupted by another thread
+PR_NOT_IMPLEMENTED_ERROR=function not implemented
+PR_IO_ERROR=I/O function error
+PR_IO_TIMEOUT_ERROR=I/O operation timed out
+PR_IO_PENDING_ERROR=I/O operation on busy file descriptor
+PR_DIRECTORY_OPEN_ERROR=The directory could not be opened
+PR_INVALID_ARGUMENT_ERROR=Invalid function argument
+PR_ADDRESS_NOT_AVAILABLE_ERROR=Network address not available (in use?)
+PR_ADDRESS_NOT_SUPPORTED_ERROR=Network address type not supported
+PR_IS_CONNECTED_ERROR=Already connected
+PR_BAD_ADDRESS_ERROR=Network address is invalid
+PR_ADDRESS_IN_USE_ERROR=Local Network address is in use
+PR_CONNECT_REFUSED_ERROR=Connection refused by peer
+PR_NETWORK_UNREACHABLE_ERROR=Network address is presently unreachable
+PR_CONNECT_TIMEOUT_ERROR=Connection attempt timed out
+PR_NOT_CONNECTED_ERROR=Network file descriptor is not connected
+PR_LOAD_LIBRARY_ERROR=Failure to load dynamic library
+PR_UNLOAD_LIBRARY_ERROR=Failure to unload dynamic library
+PR_FIND_SYMBOL_ERROR=Symbol not found in any of the loaded dynamic libraries
+PR_INSUFFICIENT_RESOURCES_ERROR=Insufficient system resources
+PR_DIRECTORY_LOOKUP_ERROR=A directory lookup on a network address has failed
+PR_TPD_RANGE_ERROR=Attempt to access a TPD key that is out of range
+PR_PROC_DESC_TABLE_FULL_ERROR=Process open FD table is full
+PR_SYS_DESC_TABLE_FULL_ERROR=System open FD table is full
+PR_NOT_SOCKET_ERROR=Network operation attempted on non-network file descriptor
+PR_NOT_TCP_SOCKET_ERROR=TCP-specific function attempted on a non-TCP file descriptor
+PR_SOCKET_ADDRESS_IS_BOUND_ERROR=TCP file descriptor is already bound
+PR_NO_ACCESS_RIGHTS_ERROR=Access Denied
+PR_OPERATION_NOT_SUPPORTED_ERROR=The requested operation is not supported by the platform
+PR_PROTOCOL_NOT_SUPPORTED_ERROR=The host operating system does not support the protocol requested
+PR_REMOTE_FILE_ERROR=Access to the remote file has been severed
+PR_BUFFER_OVERFLOW_ERROR=The value requested is too large to be stored in the data buffer provided
+PR_CONNECT_RESET_ERROR=TCP connection reset by peer
+PR_RANGE_ERROR=Unused
+PR_DEADLOCK_ERROR=The operation would have deadlocked
+PR_FILE_IS_LOCKED_ERROR=The file is already locked
+PR_FILE_TOO_BIG_ERROR=Write would result in file larger than the system allows
+PR_NO_DEVICE_SPACE_ERROR=The device for storing the file is full
+PR_PIPE_ERROR=Unused
+PR_NO_SEEK_DEVICE_ERROR=Unused
+PR_IS_DIRECTORY_ERROR=Cannot perform a normal file operation on a directory
+PR_LOOP_ERROR=Symbolic link loop
+PR_NAME_TOO_LONG_ERROR=File name is too long
+PR_FILE_NOT_FOUND_ERROR=File not found
+PR_NOT_DIRECTORY_ERROR=Cannot perform directory operation on a normal file
+PR_READ_ONLY_FILESYSTEM_ERROR=Cannot write to a read-only file system
+PR_DIRECTORY_NOT_EMPTY_ERROR=Cannot delete a directory that is not empty
+PR_FILESYSTEM_MOUNTED_ERROR=Cannot delete or rename a file object while the file system is busy
+PR_NOT_SAME_DEVICE_ERROR=Cannot rename a file to a file system on another device
+PR_DIRECTORY_CORRUPTED_ERROR=The directory object in the file system is corrupted
+PR_FILE_EXISTS_ERROR=Cannot create or rename a filename that already exists
+PR_MAX_DIRECTORY_ENTRIES_ERROR=Directory is full. No additional filenames may be added
+PR_INVALID_DEVICE_STATE_ERROR=The required device was in an invalid state
+PR_DEVICE_IS_LOCKED_ERROR=The device is locked
+PR_NO_MORE_FILES_ERROR=No more entries in the directory
+PR_END_OF_FILE_ERROR=Encountered end of file
+PR_FILE_SEEK_ERROR=Seek error
+PR_FILE_IS_BUSY_ERROR=The file is busy
+PR_OPERATION_ABORTED_ERROR=The I/O operation was aborted
+PR_IN_PROGRESS_ERROR=Operation is still in progress (probably a non-blocking connect)
+PR_ALREADY_INITIATED_ERROR=Operation has already been initiated (probably a non-blocking connect)
+PR_GROUP_EMPTY_ERROR=The wait group is empty
+PR_INVALID_STATE_ERROR=Object state improper for request
+PR_NETWORK_DOWN_ERROR=Network is down
+PR_SOCKET_SHUTDOWN_ERROR=Socket shutdown
+PR_CONNECT_ABORTED_ERROR=Connection aborted
+PR_HOST_UNREACHABLE_ERROR=Host is unreachable
+PR_LIBRARY_NOT_LOADED_ERROR=The library is not loaded
+PR_MAX_ERROR=Placeholder for the end of the list
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerror.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerror.c
new file mode 100644
index 00000000..f578f2d2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerror.c
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+PR_IMPLEMENT(PRErrorCode) PR_GetError(void)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ return thread->errorCode;
+}
+
+PR_IMPLEMENT(PRInt32) PR_GetOSError(void)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ return thread->osErrorCode;
+}
+
+PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ thread->errorCode = code;
+ thread->osErrorCode = osErr;
+ thread->errorStringLength = 0;
+}
+
+PR_IMPLEMENT(void) PR_SetErrorText(PRIntn textLength, const char *text)
+{
+ PRThread *thread = PR_GetCurrentThread();
+
+ if (0 == textLength)
+ {
+ if (NULL != thread->errorString)
+ PR_DELETE(thread->errorString);
+ thread->errorStringSize = 0;
+ }
+ else
+ {
+ PRIntn size = textLength + 31; /* actual length to allocate. Plus a little extra */
+ if (thread->errorStringSize < textLength+1) /* do we have room? */
+ {
+ if (NULL != thread->errorString)
+ PR_DELETE(thread->errorString);
+ thread->errorString = (char*)PR_MALLOC(size);
+ if ( NULL == thread->errorString ) {
+ thread->errorStringSize = 0;
+ thread->errorStringLength = 0;
+ return;
+ }
+ thread->errorStringSize = size;
+ }
+ memcpy(thread->errorString, text, textLength+1 );
+ }
+ thread->errorStringLength = textLength;
+}
+
+PR_IMPLEMENT(PRInt32) PR_GetErrorTextLength(void)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ return thread->errorStringLength;
+} /* PR_GetErrorTextLength */
+
+PR_IMPLEMENT(PRInt32) PR_GetErrorText(char *text)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ if (0 != thread->errorStringLength)
+ memcpy(text, thread->errorString, thread->errorStringLength+1);
+ return thread->errorStringLength;
+} /* PR_GetErrorText */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerrortable.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerrortable.c
new file mode 100644
index 00000000..a51b4e8f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prerrortable.c
@@ -0,0 +1,240 @@
+/* ***** 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+
+
+/*
+
+Copyright 1987, 1988 by the Student Information Processing Board
+ of the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is
+hereby granted, provided that the above copyright notice
+appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation,
+and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+*/
+
+#include <string.h>
+#ifdef SUNOS4
+#include "md/sunos4.h" /* for strerror */
+#endif
+#include <assert.h>
+#include <errno.h>
+#include "prmem.h"
+#include "prerror.h"
+
+#define ERRCODE_RANGE 8 /* # of bits to shift table number */
+#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
+
+#ifdef NEED_SYS_ERRLIST
+extern char const * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+/* List of error tables */
+struct PRErrorTableList {
+ struct PRErrorTableList *next;
+ const struct PRErrorTable *table;
+ struct PRErrorCallbackTablePrivate *table_private;
+};
+static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL;
+
+/* Supported languages */
+static const char * default_languages[] = { "i-default", "en", 0 };
+static const char * const * callback_languages = default_languages;
+
+/* Callback info */
+static struct PRErrorCallbackPrivate *callback_private = 0;
+static PRErrorCallbackLookupFn *callback_lookup = 0;
+static PRErrorCallbackNewTableFn *callback_newtable = 0;
+
+
+static const char char_set[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+static const char *
+error_table_name (PRErrorCode num)
+{
+ static char buf[6]; /* only used if internal code problems exist */
+
+ long ch;
+ int i;
+ char *p;
+
+ /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
+ p = buf;
+ num >>= ERRCODE_RANGE;
+ /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
+ num &= 077777777;
+ /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
+ for (i = 4; i >= 0; i--) {
+ ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
+ if (ch != 0)
+ *p++ = char_set[ch-1];
+ }
+ *p = '\0';
+ return(buf);
+}
+
+PR_IMPLEMENT(const char *)
+PR_ErrorToString(PRErrorCode code, PRLanguageCode language)
+{
+ /* static buffer only used if code is using inconsistent error message
+ * numbers, so just ignore the possible thread contention
+ */
+ static char buffer[25];
+
+ const char *msg;
+ int offset;
+ PRErrorCode table_num;
+ struct PRErrorTableList *et;
+ int started = 0;
+ char *cp;
+
+ for (et = Table_List; et; et = et->next) {
+ if (et->table->base <= code &&
+ et->table->base + et->table->n_msgs > code) {
+ /* This is the right table */
+ if (callback_lookup) {
+ msg = callback_lookup(code, language, et->table,
+ callback_private, et->table_private);
+ if (msg) return msg;
+ }
+
+ return(et->table->msgs[code - et->table->base].en_text);
+ }
+ }
+
+ if (code >= 0 && code < 256) {
+ return strerror(code);
+ }
+
+ offset = (int) (code & ((1<<ERRCODE_RANGE)-1));
+ table_num = code - offset;
+ strcpy (buffer, "Unknown code ");
+ if (table_num) {
+ strcat(buffer, error_table_name (table_num));
+ strcat(buffer, " ");
+ }
+ for (cp = buffer; *cp; cp++)
+ ;
+ if (offset >= 100) {
+ *cp++ = (char)('0' + offset / 100);
+ offset %= 100;
+ started++;
+ }
+ if (started || offset >= 10) {
+ *cp++ = (char)('0' + offset / 10);
+ offset %= 10;
+ }
+ *cp++ = (char)('0' + offset);
+ *cp = '\0';
+ return(buffer);
+}
+
+PR_IMPLEMENT(const char *)
+PR_ErrorToName(PRErrorCode code)
+{
+ struct PRErrorTableList *et;
+
+ for (et = Table_List; et; et = et->next) {
+ if (et->table->base <= code &&
+ et->table->base + et->table->n_msgs > code) {
+ /* This is the right table */
+ return(et->table->msgs[code - et->table->base].name);
+ }
+ }
+
+ return 0;
+}
+
+PR_IMPLEMENT(const char * const *)
+PR_ErrorLanguages(void)
+{
+ return callback_languages;
+}
+
+PR_IMPLEMENT(PRErrorCode)
+PR_ErrorInstallTable(const struct PRErrorTable *table)
+{
+ struct PRErrorTableList * new_et;
+
+ new_et = (struct PRErrorTableList *)
+ PR_Malloc(sizeof(struct PRErrorTableList));
+ if (!new_et)
+ return errno; /* oops */
+ new_et->table = table;
+ if (callback_newtable) {
+ new_et->table_private = callback_newtable(table, callback_private);
+ } else {
+ new_et->table_private = 0;
+ }
+ new_et->next = Table_List;
+ Table_List = new_et;
+ return 0;
+}
+
+PR_IMPLEMENT(void)
+PR_ErrorInstallCallback(const char * const * languages,
+ PRErrorCallbackLookupFn *lookup,
+ PRErrorCallbackNewTableFn *newtable,
+ struct PRErrorCallbackPrivate *cb_private)
+{
+ struct PRErrorTableList *et;
+
+ assert(strcmp(languages[0], "i-default") == 0);
+ assert(strcmp(languages[1], "en") == 0);
+
+ callback_languages = languages;
+ callback_lookup = lookup;
+ callback_newtable = newtable;
+ callback_private = cb_private;
+
+ if (callback_newtable) {
+ for (et = Table_List; et; et = et->next) {
+ et->table_private = callback_newtable(et->table, callback_private);
+ }
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c
new file mode 100644
index 00000000..eef45968
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c
@@ -0,0 +1,880 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <ctype.h>
+#include <string.h>
+#ifdef VBOX_USE_IPRT_IN_NSPR
+# include <iprt/initterm.h>
+#endif
+
+PRLogModuleInfo *_pr_clock_lm;
+PRLogModuleInfo *_pr_cmon_lm;
+PRLogModuleInfo *_pr_io_lm;
+PRLogModuleInfo *_pr_cvar_lm;
+PRLogModuleInfo *_pr_mon_lm;
+PRLogModuleInfo *_pr_linker_lm;
+PRLogModuleInfo *_pr_sched_lm;
+PRLogModuleInfo *_pr_thread_lm;
+PRLogModuleInfo *_pr_gc_lm;
+PRLogModuleInfo *_pr_shm_lm;
+PRLogModuleInfo *_pr_shma_lm;
+
+PRFileDesc *_pr_stdin;
+PRFileDesc *_pr_stdout;
+PRFileDesc *_pr_stderr;
+
+#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
+
+PRCList _pr_active_local_threadQ =
+ PR_INIT_STATIC_CLIST(&_pr_active_local_threadQ);
+PRCList _pr_active_global_threadQ =
+ PR_INIT_STATIC_CLIST(&_pr_active_global_threadQ);
+
+_MDLock _pr_cpuLock; /* lock for the CPU Q */
+PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ);
+
+PRUint32 _pr_utid;
+
+PRInt32 _pr_userActive;
+PRInt32 _pr_systemActive;
+PRUintn _pr_maxPTDs;
+
+#ifdef _PR_LOCAL_THREADS_ONLY
+
+struct _PRCPU *_pr_currentCPU;
+PRThread *_pr_currentThread;
+PRThread *_pr_lastThread;
+PRInt32 _pr_intsOff;
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+/* Lock protecting all "termination" condition variables of all threads */
+PRLock *_pr_terminationCVLock;
+
+#endif /* !defined(_PR_PTHREADS) */
+
+PRLock *_pr_sleeplock; /* used in PR_Sleep(), classic and pthreads */
+
+static void _PR_InitCallOnce(void);
+
+PRBool _pr_initialized = PR_FALSE;
+
+
+PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
+{
+ /*
+ ** This is the secret handshake algorithm.
+ **
+ ** This release has a simple version compatibility
+ ** check algorithm. This release is not backward
+ ** compatible with previous major releases. It is
+ ** not compatible with future major, minor, or
+ ** patch releases.
+ */
+ int vmajor = 0, vminor = 0, vpatch = 0;
+ const char *ptr = importedVersion;
+
+ while (isdigit(*ptr)) {
+ vmajor = 10 * vmajor + *ptr - '0';
+ ptr++;
+ }
+ if (*ptr == '.') {
+ ptr++;
+ while (isdigit(*ptr)) {
+ vminor = 10 * vminor + *ptr - '0';
+ ptr++;
+ }
+ if (*ptr == '.') {
+ ptr++;
+ while (isdigit(*ptr)) {
+ vpatch = 10 * vpatch + *ptr - '0';
+ ptr++;
+ }
+ }
+ }
+
+ if (vmajor != PR_VMAJOR) {
+ return PR_FALSE;
+ }
+ if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) {
+ return PR_FALSE;
+ }
+ if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+} /* PR_VersionCheck */
+
+
+PR_IMPLEMENT(PRBool) PR_Initialized(void)
+{
+ return _pr_initialized;
+}
+
+PRInt32 _native_threads_only = 0;
+
+#ifdef WINNT
+static void _pr_SetNativeThreadsOnlyMode(void)
+{
+ HMODULE mainExe;
+ PRBool *globalp;
+ char *envp;
+
+ mainExe = GetModuleHandle(NULL);
+ PR_ASSERT(NULL != mainExe);
+ globalp = (PRBool *) GetProcAddress(mainExe, "nspr_native_threads_only");
+ if (globalp) {
+ _native_threads_only = (*globalp != PR_FALSE);
+ } else if (envp = getenv("NSPR_NATIVE_THREADS_ONLY")) {
+ _native_threads_only = (atoi(envp) == 1);
+ }
+}
+#endif
+
+#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+extern PRStatus _pr_init_ipv6(void);
+#endif
+
+static void _PR_InitStuff(void)
+{
+
+ if (_pr_initialized) return;
+ _pr_initialized = PR_TRUE;
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+#endif
+#ifdef _PR_ZONE_ALLOCATOR
+ _PR_InitZones();
+#endif
+#ifdef WINNT
+ _pr_SetNativeThreadsOnlyMode();
+#endif
+
+
+ (void) PR_GetPageSize();
+
+ _pr_clock_lm = PR_NewLogModule("clock");
+ _pr_cmon_lm = PR_NewLogModule("cmon");
+ _pr_io_lm = PR_NewLogModule("io");
+ _pr_mon_lm = PR_NewLogModule("mon");
+ _pr_linker_lm = PR_NewLogModule("linker");
+ _pr_cvar_lm = PR_NewLogModule("cvar");
+ _pr_sched_lm = PR_NewLogModule("sched");
+ _pr_thread_lm = PR_NewLogModule("thread");
+ _pr_gc_lm = PR_NewLogModule("gc");
+ _pr_shm_lm = PR_NewLogModule("shm");
+ _pr_shma_lm = PR_NewLogModule("shma");
+
+ /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */
+ _PR_MD_EARLY_INIT();
+
+ _PR_InitLocks();
+ _PR_InitAtomic();
+ _PR_InitSegs();
+ _PR_InitStacks();
+ _PR_InitTPD();
+ _PR_InitEnv();
+ _PR_InitLayerCache();
+ _PR_InitClock();
+
+ _pr_sleeplock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_sleeplock);
+
+#ifdef GC_LEAK_DETECTOR
+ _PR_InitGarbageCollector();
+#endif
+
+ _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+#ifdef WIN16
+ {
+ PRInt32 top; /* artificial top of stack, win16 */
+ _pr_top_of_task_stack = (char *) &top;
+ }
+#endif
+
+#ifndef _PR_GLOBAL_THREADS_ONLY
+ _PR_InitCPUs();
+#endif
+
+/*
+ * XXX: call _PR_InitMem only on those platforms for which nspr implements
+ * malloc, for now.
+ */
+#ifdef _PR_OVERRIDE_MALLOC
+ _PR_InitMem();
+#endif
+
+ _PR_InitCMon();
+ _PR_InitIO();
+ _PR_InitNet();
+ _PR_InitLog();
+ _PR_InitLinker();
+ _PR_InitCallOnce();
+ _PR_InitDtoa();
+ _PR_InitMW();
+ _PR_InitRWLocks();
+
+ nspr_InitializePRErrorTable();
+
+#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+ _pr_init_ipv6();
+#endif
+
+ _PR_MD_FINAL_INIT();
+}
+
+void _PR_ImplicitInitialization(void)
+{
+ _PR_InitStuff();
+
+ /* Enable interrupts */
+#if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY)
+ _PR_MD_START_INTERRUPTS();
+#endif
+
+}
+
+PR_IMPLEMENT(void) PR_DisableClockInterrupts(void)
+{
+#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
+ if (!_pr_initialized) {
+ _PR_InitStuff();
+ } else {
+ _PR_MD_DISABLE_CLOCK_INTERRUPTS();
+ }
+#endif
+}
+
+PR_IMPLEMENT(void) PR_EnableClockInterrupts(void)
+{
+#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
+ if (!_pr_initialized) {
+ _PR_InitStuff();
+ }
+ _PR_MD_ENABLE_CLOCK_INTERRUPTS();
+#endif
+}
+
+PR_IMPLEMENT(void) PR_BlockClockInterrupts(void)
+{
+#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
+ _PR_MD_BLOCK_CLOCK_INTERRUPTS();
+#endif
+}
+
+PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void)
+{
+#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
+ _PR_MD_UNBLOCK_CLOCK_INTERRUPTS();
+#endif
+}
+
+PR_IMPLEMENT(void) PR_Init(
+ PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
+{
+#if defined(XP_MAC)
+#pragma unused (type, priority, maxPTDs)
+#endif
+
+ _PR_ImplicitInitialization();
+}
+
+PR_IMPLEMENT(PRIntn) PR_Initialize(
+ PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs)
+{
+#if defined(XP_MAC)
+#pragma unused (maxPTDs)
+#endif
+
+ PRIntn rv;
+ _PR_ImplicitInitialization();
+ rv = prmain(argc, argv);
+ PR_Cleanup();
+ return rv;
+} /* PR_Initialize */
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * _PR_CleanupBeforeExit --
+ *
+ * Perform the cleanup work before exiting the process.
+ * We first do the cleanup generic to all platforms. Then
+ * we call _PR_MD_CLEANUP_BEFORE_EXIT(), where platform-dependent
+ * cleanup is done. This function is used by PR_Cleanup().
+ *
+ * See also: PR_Cleanup().
+ *
+ *-----------------------------------------------------------------------
+ */
+#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
+ /* see ptthread.c */
+#else
+static void
+_PR_CleanupBeforeExit(void)
+{
+/*
+Do not make any calls here other than to destroy resources. For example,
+do not make any calls that eventually may end up in PR_Lock. Because the
+thread is destroyed, can not access current thread any more.
+*/
+ _PR_CleanupTPD();
+ if (_pr_terminationCVLock)
+ /*
+ * In light of the comment above, this looks real suspicious.
+ * I'd go so far as to say it's just a problem waiting to happen.
+ */
+ PR_DestroyLock(_pr_terminationCVLock);
+
+ _PR_MD_CLEANUP_BEFORE_EXIT();
+}
+#endif /* defined(_PR_PTHREADS) */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PR_Cleanup --
+ *
+ * Perform a graceful shutdown of the NSPR runtime. PR_Cleanup() may
+ * only be called from the primordial thread, typically at the
+ * end of the main() function. It returns when it has completed
+ * its platform-dependent duty and the process must not make any other
+ * NSPR library calls prior to exiting from main().
+ *
+ * PR_Cleanup() first blocks the primordial thread until all the
+ * other user (non-system) threads, if any, have terminated.
+ * Then it performs cleanup in preparation for exiting the process.
+ * PR_Cleanup() does not exit the primordial thread (which would
+ * in turn exit the process).
+ *
+ * PR_Cleanup() only responds when it is called by the primordial
+ * thread. Calls by any other thread are silently ignored.
+ *
+ * See also: PR_ExitProcess()
+ *
+ *----------------------------------------------------------------------
+ */
+#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
+ /* see ptthread.c */
+#else
+
+PR_IMPLEMENT(PRStatus) PR_Cleanup()
+{
+ PRThread *me = PR_GetCurrentThread();
+ PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL));
+ if ((NULL != me) && (me->flags & _PR_PRIMORDIAL))
+ {
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
+
+ /*
+ * No more recycling of threads
+ */
+ _pr_recycleThreads = 0;
+
+ /*
+ * Wait for all other user (non-system/daemon) threads
+ * to terminate.
+ */
+ PR_Lock(_pr_activeLock);
+ while (_pr_userActive > _pr_primordialExitCount) {
+ PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(_pr_activeLock);
+
+#ifdef IRIX
+ _PR_MD_PRE_CLEANUP(me);
+ /*
+ * The primordial thread must now be running on the primordial cpu
+ */
+ PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0));
+#endif
+
+ _PR_CleanupMW();
+ _PR_CleanupDtoa();
+ _PR_CleanupCallOnce();
+ _PR_ShutdownLinker();
+ /* Release the primordial thread's private data, etc. */
+ _PR_CleanupThread(me);
+
+ _PR_MD_STOP_INTERRUPTS();
+
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("PR_Cleanup: clean up before destroying thread"));
+ _PR_LogCleanup();
+
+ /*
+ * This part should look like the end of _PR_NativeRunThread
+ * and _PR_UserRunThread.
+ */
+ if (_PR_IS_NATIVE_THREAD(me)) {
+ _PR_MD_EXIT_THREAD(me);
+ _PR_NativeDestroyThread(me);
+ } else {
+ _PR_UserDestroyThread(me);
+ PR_DELETE(me->stack);
+ PR_DELETE(me);
+ }
+
+ /*
+ * XXX: We are freeing the heap memory here so that Purify won't
+ * complain, but we should also free other kinds of resources
+ * that are allocated by the _PR_InitXXX() functions.
+ * Ideally, for each _PR_InitXXX(), there should be a corresponding
+ * _PR_XXXCleanup() that we can call here.
+ */
+ _PR_CleanupNet();
+ _PR_CleanupIO();
+#ifdef WINNT
+ _PR_CleanupCPUs();
+#endif
+ _PR_CleanupThreads();
+ PR_DestroyLock(_pr_sleeplock);
+ _pr_sleeplock = NULL;
+ _PR_CleanupLayerCache();
+ _PR_CleanupEnv();
+ _PR_CleanupStacks();
+ _PR_CleanupBeforeExit();
+ _pr_initialized = PR_FALSE;
+ return PR_SUCCESS;
+ }
+ return PR_FAILURE;
+}
+#endif /* defined(_PR_PTHREADS) */
+
+/*
+ *------------------------------------------------------------------------
+ * PR_ProcessExit --
+ *
+ * Cause an immediate, nongraceful, forced termination of the process.
+ * It takes a PRIntn argument, which is the exit status code of the
+ * process.
+ *
+ * See also: PR_Cleanup()
+ *
+ *------------------------------------------------------------------------
+ */
+
+#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
+ /* see ptthread.c */
+#else
+PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
+{
+ _PR_MD_EXIT(status);
+}
+
+#endif /* defined(_PR_PTHREADS) */
+
+PR_IMPLEMENT(PRProcessAttr *)
+PR_NewProcessAttr(void)
+{
+ PRProcessAttr *attr;
+
+ attr = PR_NEWZAP(PRProcessAttr);
+ if (!attr) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+ return attr;
+}
+
+PR_IMPLEMENT(void)
+PR_ResetProcessAttr(PRProcessAttr *attr)
+{
+ PR_FREEIF(attr->currentDirectory);
+ PR_FREEIF(attr->fdInheritBuffer);
+ memset(attr, 0, sizeof(*attr));
+}
+
+PR_IMPLEMENT(void)
+PR_DestroyProcessAttr(PRProcessAttr *attr)
+{
+ PR_FREEIF(attr->currentDirectory);
+ PR_FREEIF(attr->fdInheritBuffer);
+ PR_DELETE(attr);
+}
+
+PR_IMPLEMENT(void)
+PR_ProcessAttrSetStdioRedirect(
+ PRProcessAttr *attr,
+ PRSpecialFD stdioFd,
+ PRFileDesc *redirectFd)
+{
+ switch (stdioFd) {
+ case PR_StandardInput:
+ attr->stdinFd = redirectFd;
+ break;
+ case PR_StandardOutput:
+ attr->stdoutFd = redirectFd;
+ break;
+ case PR_StandardError:
+ attr->stderrFd = redirectFd;
+ break;
+ default:
+ PR_ASSERT(0);
+ }
+}
+
+/*
+ * OBSOLETE
+ */
+PR_IMPLEMENT(void)
+PR_SetStdioRedirect(
+ PRProcessAttr *attr,
+ PRSpecialFD stdioFd,
+ PRFileDesc *redirectFd)
+{
+#if defined(DEBUG)
+ static PRBool warn = PR_TRUE;
+ if (warn) {
+ warn = _PR_Obsolete("PR_SetStdioRedirect()",
+ "PR_ProcessAttrSetStdioRedirect()");
+ }
+#endif
+ PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_ProcessAttrSetCurrentDirectory(
+ PRProcessAttr *attr,
+ const char *dir)
+{
+ PR_FREEIF(attr->currentDirectory);
+ attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1);
+ if (!attr->currentDirectory) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return PR_FAILURE;
+ }
+ strcpy(attr->currentDirectory, dir);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_ProcessAttrSetInheritableFD(
+ PRProcessAttr *attr,
+ PRFileDesc *fd,
+ const char *name)
+{
+ /* We malloc the fd inherit buffer in multiples of this number. */
+#define FD_INHERIT_BUFFER_INCR 128
+ /* The length of "NSPR_INHERIT_FDS=" */
+#define NSPR_INHERIT_FDS_STRLEN 17
+ /* The length of osfd (PRInt32) printed in hexadecimal with 0x prefix */
+#define OSFD_STRLEN 10
+ /* The length of fd type (PRDescType) printed in decimal */
+#define FD_TYPE_STRLEN 1
+ PRSize newSize;
+ int remainder;
+ char *newBuffer;
+ int nwritten;
+ char *cur;
+ int freeSize;
+
+ if (fd->identity != PR_NSPR_IO_LAYER) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (fd->secret->inheritable == _PR_TRI_UNKNOWN) {
+ _PR_MD_QUERY_FD_INHERITABLE(fd);
+ }
+ if (fd->secret->inheritable != _PR_TRI_TRUE) {
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ /*
+ * We also need to account for the : separators and the
+ * terminating null byte.
+ */
+ if (NULL == attr->fdInheritBuffer) {
+ /* The first time, we print "NSPR_INHERIT_FDS=<name>:<type>:<val>" */
+ newSize = NSPR_INHERIT_FDS_STRLEN + strlen(name)
+ + FD_TYPE_STRLEN + OSFD_STRLEN + 2 + 1;
+ } else {
+ /* At other times, we print ":<name>:<type>:<val>" */
+ newSize = attr->fdInheritBufferUsed + strlen(name)
+ + FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1;
+ }
+ if (newSize > attr->fdInheritBufferSize) {
+ /* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */
+ remainder = newSize % FD_INHERIT_BUFFER_INCR;
+ if (remainder != 0) {
+ newSize += (FD_INHERIT_BUFFER_INCR - remainder);
+ }
+ if (NULL == attr->fdInheritBuffer) {
+ newBuffer = (char *) PR_MALLOC(newSize);
+ } else {
+ newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize);
+ }
+ if (NULL == newBuffer) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return PR_FAILURE;
+ }
+ attr->fdInheritBuffer = newBuffer;
+ attr->fdInheritBufferSize = newSize;
+ }
+ cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed;
+ freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed;
+ if (0 == attr->fdInheritBufferUsed) {
+ nwritten = PR_snprintf(cur, freeSize,
+ "NSPR_INHERIT_FDS=%s:%d:0x%lx",
+ name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
+ } else {
+ nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%lx",
+ name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
+ }
+ attr->fdInheritBufferUsed += nwritten;
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD(
+ const char *name)
+{
+ PRFileDesc *fd;
+ const char *envVar;
+ const char *ptr;
+ int len = strlen(name);
+ PRInt32 osfd;
+ int nColons;
+ PRIntn fileType;
+
+ envVar = PR_GetEnv("NSPR_INHERIT_FDS");
+ if (NULL == envVar || '\0' == envVar[0]) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return NULL;
+ }
+
+ ptr = envVar;
+ while (1) {
+ if ((strncmp(ptr, name, len) == 0) && (ptr[len] == ':')) {
+ ptr += len + 1;
+ PR_sscanf(ptr, "%d:0x%lx", &fileType, &osfd);
+ switch ((PRDescType)fileType) {
+ case PR_DESC_FILE:
+ fd = PR_ImportFile(osfd);
+ break;
+ case PR_DESC_PIPE:
+ fd = PR_ImportPipe(osfd);
+ break;
+ case PR_DESC_SOCKET_TCP:
+ fd = PR_ImportTCPSocket(osfd);
+ break;
+ case PR_DESC_SOCKET_UDP:
+ fd = PR_ImportUDPSocket(osfd);
+ break;
+ default:
+ PR_ASSERT(0);
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ fd = NULL;
+ break;
+ }
+ if (fd) {
+ /*
+ * An inherited FD is inheritable by default.
+ * The child process needs to call PR_SetFDInheritable
+ * to make it non-inheritable if so desired.
+ */
+ fd->secret->inheritable = _PR_TRI_TRUE;
+ }
+ return fd;
+ }
+ /* Skip three colons */
+ nColons = 0;
+ while (*ptr) {
+ if (*ptr == ':') {
+ if (++nColons == 3) {
+ break;
+ }
+ }
+ ptr++;
+ }
+ if (*ptr == '\0') {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return NULL;
+ }
+ ptr++;
+ }
+}
+
+PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+ return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
+} /* PR_CreateProcess */
+
+PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached(
+ const char *path,
+ char *const *argv,
+ char *const *envp,
+ const PRProcessAttr *attr)
+{
+#ifndef _PR_MD_CREATE_PROCESS_DETACHED
+ PRProcess *process;
+ PRStatus rv;
+s
+#ifdef XP_OS2
+ process = _PR_CreateOS2ProcessEx(path, argv, envp, attr, PR_TRUE);
+#else
+ process = PR_CreateProcess(path, argv, envp, attr);
+#endif
+ if (NULL == process) {
+ return PR_FAILURE;
+ }
+ rv = PR_DetachProcess(process);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if (rv == PR_FAILURE) {
+ PR_DELETE(process);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+#else /* _PR_MD_CREATE_PROCESS_DETACHED */
+ return _PR_MD_CREATE_PROCESS_DETACHED(path, argv, envp, attr);
+#endif /* _PR_MD_CREATE_PROCESS_DETACHED */
+}
+
+PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process)
+{
+ return _PR_MD_DETACH_PROCESS(process);
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
+{
+ return _PR_MD_WAIT_PROCESS(process, exitCode);
+} /* PR_WaitProcess */
+
+PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
+{
+ return _PR_MD_KILL_PROCESS(process);
+}
+
+/*
+ ********************************************************************
+ *
+ * Module initialization
+ *
+ ********************************************************************
+ */
+
+static struct {
+ PRLock *ml;
+ PRCondVar *cv;
+} mod_init;
+
+static void _PR_InitCallOnce(void) {
+ mod_init.ml = PR_NewLock();
+ PR_ASSERT(NULL != mod_init.ml);
+ mod_init.cv = PR_NewCondVar(mod_init.ml);
+ PR_ASSERT(NULL != mod_init.cv);
+}
+
+void _PR_CleanupCallOnce()
+{
+ PR_DestroyLock(mod_init.ml);
+ mod_init.ml = NULL;
+ PR_DestroyCondVar(mod_init.cv);
+ mod_init.cv = NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CallOnce(
+ PRCallOnceType *once,
+ PRCallOnceFN func)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (!once->initialized) {
+ if (PR_AtomicSet(&once->inProgress, 1) == 0) {
+ once->status = (*func)();
+ PR_Lock(mod_init.ml);
+ once->initialized = 1;
+ PR_NotifyAllCondVar(mod_init.cv);
+ PR_Unlock(mod_init.ml);
+ } else {
+ PR_Lock(mod_init.ml);
+ while (!once->initialized) {
+ PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(mod_init.ml);
+ }
+ }
+ return once->status;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
+ PRCallOnceType *once,
+ PRCallOnceWithArgFN func,
+ void *arg)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (!once->initialized) {
+ if (PR_AtomicSet(&once->inProgress, 1) == 0) {
+ once->status = (*func)(arg);
+ PR_Lock(mod_init.ml);
+ once->initialized = 1;
+ PR_NotifyAllCondVar(mod_init.cv);
+ PR_Unlock(mod_init.ml);
+ } else {
+ PR_Lock(mod_init.ml);
+ while (!once->initialized) {
+ PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(mod_init.ml);
+ }
+ }
+ return once->status;
+}
+
+PRBool _PR_Obsolete(const char *obsolete, const char *preferred)
+{
+#if defined(DEBUG)
+#ifndef XP_MAC
+ PR_fprintf(
+ PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n",
+ obsolete, (NULL == preferred) ? "something else" : preferred);
+#else
+#pragma unused (obsolete, preferred)
+#endif
+#endif
+ return PR_FALSE;
+} /* _PR_Obsolete */
+
+/* prinit.c */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinrval.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinrval.c
new file mode 100644
index 00000000..17229e80
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinrval.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * file: prinrval.c
+ * description: implementation for the kernel interval timing functions
+ */
+
+#include "primpl.h"
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * _PR_InitClock --
+ *
+ *
+ *-----------------------------------------------------------------------
+ */
+
+void _PR_InitClock(void)
+{
+ _PR_MD_INTERVAL_INIT();
+#ifdef DEBUG
+ {
+ PRIntervalTime ticksPerSec = PR_TicksPerSecond();
+
+ PR_ASSERT(ticksPerSec >= PR_INTERVAL_MIN);
+ PR_ASSERT(ticksPerSec <= PR_INTERVAL_MAX);
+ }
+#endif /* DEBUG */
+}
+
+/*
+ * This version of interval times is based on the time of day
+ * capability offered by system. This isn't valid for two reasons:
+ * 1) The time of day is neither linear nor montonically increasing
+ * 2) The units here are milliseconds. That's not appropriate for our use.
+ */
+
+PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow(void)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ return _PR_MD_GET_INTERVAL();
+} /* PR_IntervalNow */
+
+PR_EXTERN(PRUint32) PR_TicksPerSecond(void)
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ return _PR_MD_INTERVAL_PER_SEC();
+} /* PR_TicksPerSecond */
+
+PR_IMPLEMENT(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds)
+{
+ return seconds * PR_TicksPerSecond();
+} /* PR_SecondsToInterval */
+
+PR_IMPLEMENT(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli)
+{
+ PRIntervalTime ticks;
+ PRUint64 tock, tps, msecPerSec, rounding;
+ LL_UI2L(tock, milli);
+ LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
+ LL_I2L(rounding, (PR_MSEC_PER_SEC >> 1));
+ LL_I2L(tps, PR_TicksPerSecond());
+ LL_MUL(tock, tock, tps);
+ LL_ADD(tock, tock, rounding);
+ LL_DIV(tock, tock, msecPerSec);
+ LL_L2UI(ticks, tock);
+ return ticks;
+} /* PR_MillisecondsToInterval */
+
+PR_IMPLEMENT(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro)
+{
+ PRIntervalTime ticks;
+ PRUint64 tock, tps, usecPerSec, rounding;
+ LL_UI2L(tock, micro);
+ LL_I2L(usecPerSec, PR_USEC_PER_SEC);
+ LL_I2L(rounding, (PR_USEC_PER_SEC >> 1));
+ LL_I2L(tps, PR_TicksPerSecond());
+ LL_MUL(tock, tock, tps);
+ LL_ADD(tock, tock, rounding);
+ LL_DIV(tock, tock, usecPerSec);
+ LL_L2UI(ticks, tock);
+ return ticks;
+} /* PR_MicrosecondsToInterval */
+
+PR_IMPLEMENT(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks)
+{
+ return ticks / PR_TicksPerSecond();
+} /* PR_IntervalToSeconds */
+
+PR_IMPLEMENT(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks)
+{
+ PRUint32 milli;
+ PRUint64 tock, tps, msecPerSec, rounding;
+ LL_UI2L(tock, ticks);
+ LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
+ LL_I2L(tps, PR_TicksPerSecond());
+ LL_USHR(rounding, tps, 1);
+ LL_MUL(tock, tock, msecPerSec);
+ LL_ADD(tock, tock, rounding);
+ LL_DIV(tock, tock, tps);
+ LL_L2UI(milli, tock);
+ return milli;
+} /* PR_IntervalToMilliseconds */
+
+PR_IMPLEMENT(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks)
+{
+ PRUint32 micro;
+ PRUint64 tock, tps, usecPerSec, rounding;
+ LL_UI2L(tock, ticks);
+ LL_I2L(usecPerSec, PR_USEC_PER_SEC);
+ LL_I2L(tps, PR_TicksPerSecond());
+ LL_USHR(rounding, tps, 1);
+ LL_MUL(tock, tock, usecPerSec);
+ LL_ADD(tock, tock, rounding);
+ LL_DIV(tock, tock, tps);
+ LL_L2UI(micro, tock);
+ return micro;
+} /* PR_IntervalToMicroseconds */
+
+/* prinrval.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/pripc.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pripc.c
new file mode 100644
index 00000000..cb16aad9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pripc.c
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: pripc.c
+ *
+ * Description: functions for IPC support
+ */
+
+#include "primpl.h"
+
+#include <string.h>
+
+/*
+ * A POSIX IPC name must begin with a '/'.
+ * A POSIX IPC name on Solaris cannot contain any '/' except
+ * the required leading '/'.
+ * A POSIX IPC name on HP-UX and OSF1 must be a valid pathname
+ * in the file system.
+ *
+ * The ftok() function for System V IPC requires a valid pathname
+ * in the file system.
+ *
+ * A Win32 IPC name cannot contain '\'.
+ */
+
+static void _pr_ConvertSemName(char *result)
+{
+#ifdef _PR_HAVE_POSIX_SEMAPHORES
+#if defined(SOLARIS)
+ char *p;
+
+ /* Convert '/' to '_' except for the leading '/' */
+ for (p = result+1; *p; p++) {
+ if (*p == '/') {
+ *p = '_';
+ }
+ }
+ return;
+#else
+ return;
+#endif
+#elif defined(_PR_HAVE_SYSV_SEMAPHORES)
+ return;
+#elif defined(WIN32)
+ return;
+#endif
+}
+
+static void _pr_ConvertShmName(char *result)
+{
+#if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY)
+#if defined(SOLARIS)
+ char *p;
+
+ /* Convert '/' to '_' except for the leading '/' */
+ for (p = result+1; *p; p++) {
+ if (*p == '/') {
+ *p = '_';
+ }
+ }
+ return;
+#else
+ return;
+#endif
+#elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY)
+ return;
+#elif defined(WIN32)
+ return;
+#else
+ return;
+#endif
+}
+
+PRStatus _PR_MakeNativeIPCName(
+ const char *name,
+ char *result,
+ PRIntn size,
+ _PRIPCType type)
+{
+ if (strlen(name) >= (PRSize)size) {
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ return PR_FAILURE;
+ }
+ strcpy(result, name);
+ switch (type) {
+ case _PRIPCSem:
+ _pr_ConvertSemName(result);
+ break;
+ case _PRIPCShm:
+ _pr_ConvertShmName(result);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/pripcsem.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pripcsem.c
new file mode 100644
index 00000000..c6c59ec9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/pripcsem.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: pripcsem.c
+ *
+ * Description: implements the named semaphores API in prsemipc.h
+ * for classic NSPR. If _PR_HAVE_NAMED_SEMAPHORES is not defined,
+ * the named semaphore functions all fail with the error code
+ * PR_NOT_IMPLEMENTED_ERROR.
+ */
+
+#include "primpl.h"
+
+#ifdef _PR_PTHREADS
+
+#error "This file should not be compiled for the pthreads version"
+
+#else
+
+#ifndef _PR_HAVE_NAMED_SEMAPHORES
+
+PRSem * _PR_MD_OPEN_SEMAPHORE(
+ const char *osname, PRIntn flags, PRIntn mode, PRUintn value)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+#endif /* !_PR_HAVE_NAMED_SEMAPHORES */
+
+PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
+ const char *name, PRIntn flags, PRIntn mode, PRUintn value)
+{
+ char osname[PR_IPC_NAME_SIZE];
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
+ == PR_FAILURE) {
+ return NULL;
+ }
+ return _PR_MD_OPEN_SEMAPHORE(osname, flags, mode, value);
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
+{
+ return _PR_MD_WAIT_SEMAPHORE(sem);
+}
+
+PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
+{
+ return _PR_MD_POST_SEMAPHORE(sem);
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
+{
+ return _PR_MD_CLOSE_SEMAPHORE(sem);
+}
+
+PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
+{
+ char osname[PR_IPC_NAME_SIZE];
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
+ == PR_FAILURE) {
+ return PR_FAILURE;
+ }
+ return _PR_MD_DELETE_SEMAPHORE(osname);
+}
+
+#endif /* _PR_PTHREADS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prlog2.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prlog2.c
new file mode 100644
index 00000000..d1a688ad
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prlog2.c
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prbit.h"
+
+/*
+** Compute the log of the least power of 2 greater than or equal to n
+*/
+PR_IMPLEMENT(PRIntn) PR_CeilingLog2(PRUint32 n)
+{
+ PRIntn log2 = 0;
+
+ if (n & (n-1))
+ log2++;
+ if (n >> 16)
+ log2 += 16, n >>= 16;
+ if (n >> 8)
+ log2 += 8, n >>= 8;
+ if (n >> 4)
+ log2 += 4, n >>= 4;
+ if (n >> 2)
+ log2 += 2, n >>= 2;
+ if (n >> 1)
+ log2++;
+ return log2;
+}
+
+/*
+** Compute the log of the greatest power of 2 less than or equal to n.
+** This really just finds the highest set bit in the word.
+*/
+PR_IMPLEMENT(PRIntn) PR_FloorLog2(PRUint32 n)
+{
+ PRIntn log2 = 0;
+
+ if (n >> 16)
+ log2 += 16, n >>= 16;
+ if (n >> 8)
+ log2 += 8, n >>= 8;
+ if (n >> 4)
+ log2 += 4, n >>= 4;
+ if (n >> 2)
+ log2 += 2, n >>= 2;
+ if (n >> 1)
+ log2++;
+ return log2;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prlong.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prlong.c
new file mode 100644
index 00000000..ad1c2a0d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prlong.c
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+static PRInt64 ll_zero = LL_INIT( 0x00000000,0x00000000 );
+static PRInt64 ll_maxint = LL_INIT( 0x7fffffff, 0xffffffff );
+static PRInt64 ll_minint = LL_INIT( 0x80000000, 0x00000000 );
+static PRUint64 ll_maxuint = LL_INIT( 0xffffffff, 0xffffffff );
+
+#if defined(HAVE_WATCOM_BUG_2)
+PRInt64 __pascal __loadds __export
+ LL_Zero(void) { return ll_zero; }
+PRInt64 __pascal __loadds __export
+ LL_MaxInt(void) { return ll_maxint; }
+PRInt64 __pascal __loadds __export
+ LL_MinInt(void) { return ll_minint; }
+PRUint64 __pascal __loadds __export
+ LL_MaxUint(void) { return ll_maxuint; }
+#else
+PR_IMPLEMENT(PRInt64) LL_Zero(void) { return ll_zero; }
+PR_IMPLEMENT(PRInt64) LL_MaxInt(void) { return ll_maxint; }
+PR_IMPLEMENT(PRInt64) LL_MinInt(void) { return ll_minint; }
+PR_IMPLEMENT(PRUint64) LL_MaxUint(void) { return ll_maxuint; }
+#endif
+
+#ifndef HAVE_LONG_LONG
+/*
+** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1.
+*/
+static void norm_udivmod32(PRUint32 *qp, PRUint32 *rp, PRUint64 a, PRUint32 b)
+{
+ PRUint32 d1, d0, q1, q0;
+ PRUint32 r1, r0, m;
+
+ d1 = _hi16(b);
+ d0 = _lo16(b);
+ r1 = a.hi % d1;
+ q1 = a.hi / d1;
+ m = q1 * d0;
+ r1 = (r1 << 16) | _hi16(a.lo);
+ if (r1 < m) {
+ q1--, r1 += b;
+ if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */
+ && r1 < m) {
+ q1--, r1 += b;
+ }
+ }
+ r1 -= m;
+ r0 = r1 % d1;
+ q0 = r1 / d1;
+ m = q0 * d0;
+ r0 = (r0 << 16) | _lo16(a.lo);
+ if (r0 < m) {
+ q0--, r0 += b;
+ if (r0 >= b
+ && r0 < m) {
+ q0--, r0 += b;
+ }
+ }
+ *qp = (q1 << 16) | q0;
+ *rp = r0 - m;
+}
+
+static PRUint32 CountLeadingZeros(PRUint32 a)
+{
+ PRUint32 t;
+ PRUint32 r = 32;
+
+ if ((t = a >> 16) != 0)
+ r -= 16, a = t;
+ if ((t = a >> 8) != 0)
+ r -= 8, a = t;
+ if ((t = a >> 4) != 0)
+ r -= 4, a = t;
+ if ((t = a >> 2) != 0)
+ r -= 2, a = t;
+ if ((t = a >> 1) != 0)
+ r -= 1, a = t;
+ if (a & 1)
+ r--;
+ return r;
+}
+
+PR_IMPLEMENT(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b)
+{
+ PRUint32 n0, n1, n2;
+ PRUint32 q0, q1;
+ PRUint32 rsh, lsh;
+
+ n0 = a.lo;
+ n1 = a.hi;
+
+ if (b.hi == 0) {
+ if (b.lo > n1) {
+ /* (0 q0) = (n1 n0) / (0 D0) */
+
+ lsh = CountLeadingZeros(b.lo);
+
+ if (lsh) {
+ /*
+ * Normalize, i.e. make the most significant bit of the
+ * denominator be set.
+ */
+ b.lo = b.lo << lsh;
+ n1 = (n1 << lsh) | (n0 >> (32 - lsh));
+ n0 = n0 << lsh;
+ }
+
+ a.lo = n0, a.hi = n1;
+ norm_udivmod32(&q0, &n0, a, b.lo);
+ q1 = 0;
+
+ /* remainder is in n0 >> lsh */
+ } else {
+ /* (q1 q0) = (n1 n0) / (0 d0) */
+
+ if (b.lo == 0) /* user wants to divide by zero! */
+ b.lo = 1 / b.lo; /* so go ahead and crash */
+
+ lsh = CountLeadingZeros(b.lo);
+
+ if (lsh == 0) {
+ /*
+ * From (n1 >= b.lo)
+ * && (the most significant bit of b.lo is set),
+ * conclude that
+ * (the most significant bit of n1 is set)
+ * && (the leading quotient digit q1 = 1).
+ *
+ * This special case is necessary, not an optimization
+ * (Shifts counts of 32 are undefined).
+ */
+ n1 -= b.lo;
+ q1 = 1;
+ } else {
+ /*
+ * Normalize.
+ */
+ rsh = 32 - lsh;
+
+ b.lo = b.lo << lsh;
+ n2 = n1 >> rsh;
+ n1 = (n1 << lsh) | (n0 >> rsh);
+ n0 = n0 << lsh;
+
+ a.lo = n1, a.hi = n2;
+ norm_udivmod32(&q1, &n1, a, b.lo);
+ }
+
+ /* n1 != b.lo... */
+
+ a.lo = n0, a.hi = n1;
+ norm_udivmod32(&q0, &n0, a, b.lo);
+
+ /* remainder in n0 >> lsh */
+ }
+
+ if (rp) {
+ rp->lo = n0 >> lsh;
+ rp->hi = 0;
+ }
+ } else {
+ if (b.hi > n1) {
+ /* (0 0) = (n1 n0) / (D1 d0) */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* remainder in (n1 n0) */
+ if (rp) {
+ rp->lo = n0;
+ rp->hi = n1;
+ }
+ } else {
+ /* (0 q0) = (n1 n0) / (d1 d0) */
+
+ lsh = CountLeadingZeros(b.hi);
+ if (lsh == 0) {
+ /*
+ * From (n1 >= b.hi)
+ * && (the most significant bit of b.hi is set),
+ * conclude that
+ * (the most significant bit of n1 is set)
+ * && (the quotient digit q0 = 0 or 1).
+ *
+ * This special case is necessary, not an optimization.
+ */
+
+ /*
+ * The condition on the next line takes advantage of that
+ * n1 >= b.hi (true due to control flow).
+ */
+ if (n1 > b.hi || n0 >= b.lo) {
+ q0 = 1;
+ a.lo = n0, a.hi = n1;
+ LL_SUB(a, a, b);
+ } else {
+ q0 = 0;
+ }
+ q1 = 0;
+
+ if (rp) {
+ rp->lo = n0;
+ rp->hi = n1;
+ }
+ } else {
+ PRInt64 m;
+
+ /*
+ * Normalize.
+ */
+ rsh = 32 - lsh;
+
+ b.hi = (b.hi << lsh) | (b.lo >> rsh);
+ b.lo = b.lo << lsh;
+ n2 = n1 >> rsh;
+ n1 = (n1 << lsh) | (n0 >> rsh);
+ n0 = n0 << lsh;
+
+ a.lo = n1, a.hi = n2;
+ norm_udivmod32(&q0, &n1, a, b.hi);
+ LL_MUL32(m, q0, b.lo);
+
+ if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) {
+ q0--;
+ LL_SUB(m, m, b);
+ }
+
+ q1 = 0;
+
+ /* Remainder is ((n1 n0) - (m1 m0)) >> lsh */
+ if (rp) {
+ a.lo = n0, a.hi = n1;
+ LL_SUB(a, a, m);
+ rp->lo = (a.hi << rsh) | (a.lo >> lsh);
+ rp->hi = a.hi >> lsh;
+ }
+ }
+ }
+ }
+
+ if (qp) {
+ qp->lo = q0;
+ qp->hi = q1;
+ }
+}
+#endif /* !HAVE_LONG_LONG */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prnetdb.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prnetdb.c
new file mode 100644
index 00000000..c47d2abd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prnetdb.c
@@ -0,0 +1,2189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+
+/*
+ * On Unix, the error code for gethostbyname() and gethostbyaddr()
+ * is returned in the global variable h_errno, instead of the usual
+ * errno.
+ */
+#if defined(XP_UNIX)
+#if defined(_PR_NEED_H_ERRNO)
+extern int h_errno;
+#endif
+#define _MD_GETHOST_ERRNO() h_errno
+#else
+#define _MD_GETHOST_ERRNO() _MD_ERRNO()
+#endif
+
+/*
+ * The meaning of the macros related to gethostbyname, gethostbyaddr,
+ * and gethostbyname2 is defined below.
+ * - _PR_HAVE_THREADSAFE_GETHOST: the gethostbyXXX functions return
+ * the result in thread specific storage. For example, AIX, HP-UX,
+ * and OSF1.
+ * - _PR_HAVE_GETHOST_R: have the gethostbyXXX_r functions. See next
+ * two macros.
+ * - _PR_HAVE_GETHOST_R_INT: the gethostbyXXX_r functions return an
+ * int. For example, Linux glibc.
+ * - _PR_HAVE_GETHOST_R_POINTER: the gethostbyXXX_r functions return
+ * a struct hostent* pointer. For example, Solaris and IRIX.
+ */
+#if defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) \
+ || defined(_PR_HAVE_THREADSAFE_GETHOST)
+#define _PR_NO_DNS_LOCK
+#endif
+
+#if defined(_PR_NO_DNS_LOCK)
+#define LOCK_DNS()
+#define UNLOCK_DNS()
+#else
+PRLock *_pr_dnsLock = NULL;
+#define LOCK_DNS() PR_Lock(_pr_dnsLock)
+#define UNLOCK_DNS() PR_Unlock(_pr_dnsLock)
+#endif /* defined(_PR_NO_DNS_LOCK) */
+
+/*
+ * Some platforms have the reentrant getprotobyname_r() and
+ * getprotobynumber_r(). However, they come in two flavors.
+ * Some return a pointer to struct protoent, others return
+ * an int.
+ */
+#if defined(XP_BEOS) && defined(BONE_VERSION)
+#include <arpa/inet.h> /* pick up define for inet_addr */
+#include <sys/socket.h>
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_GETPROTO_R_POINTER
+#endif
+
+#if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \
+ || (defined(LINUX) && defined(_REENTRANT) \
+ && !(defined(__GLIBC__) && __GLIBC__ >= 2))
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_GETPROTO_R_POINTER
+#endif
+
+#if defined(OSF1) \
+ || defined(AIX4_3_PLUS) || (defined(AIX) && defined(_THREAD_SAFE)) \
+ || (defined(HPUX10_10) && defined(_REENTRANT)) \
+ || (defined(HPUX10_20) && defined(_REENTRANT))
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_GETPROTO_R_INT
+#endif
+
+#if (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)
+#define _PR_HAVE_GETPROTO_R
+#define _PR_HAVE_5_ARG_GETPROTO_R
+#endif
+
+#if !defined(_PR_HAVE_GETPROTO_R)
+PRLock* _getproto_lock = NULL;
+#endif
+
+#if defined(_PR_INET6_PROBE)
+PR_EXTERN(PRBool) _pr_ipv6_is_present;
+#endif
+
+#define _PR_IN6_IS_ADDR_UNSPECIFIED(a) \
+ (((a)->pr_s6_addr32[0] == 0) && \
+ ((a)->pr_s6_addr32[1] == 0) && \
+ ((a)->pr_s6_addr32[2] == 0) && \
+ ((a)->pr_s6_addr32[3] == 0))
+
+#define _PR_IN6_IS_ADDR_LOOPBACK(a) \
+ (((a)->pr_s6_addr32[0] == 0) && \
+ ((a)->pr_s6_addr32[1] == 0) && \
+ ((a)->pr_s6_addr32[2] == 0) && \
+ ((a)->pr_s6_addr[12] == 0) && \
+ ((a)->pr_s6_addr[13] == 0) && \
+ ((a)->pr_s6_addr[14] == 0) && \
+ ((a)->pr_s6_addr[15] == 0x1U))
+
+const PRIPv6Addr _pr_in6addr_any = {{{ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0 }}};
+
+const PRIPv6Addr _pr_in6addr_loopback = {{{ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0x1U }}};
+/*
+ * The values at bytes 10 and 11 are compared using pointers to
+ * 8-bit fields, and not 32-bit fields, to make the comparison work on
+ * both big-endian and little-endian systems
+ */
+
+#define _PR_IN6_IS_ADDR_V4MAPPED(a) \
+ (((a)->pr_s6_addr32[0] == 0) && \
+ ((a)->pr_s6_addr32[1] == 0) && \
+ ((a)->pr_s6_addr[8] == 0) && \
+ ((a)->pr_s6_addr[9] == 0) && \
+ ((a)->pr_s6_addr[10] == 0xff) && \
+ ((a)->pr_s6_addr[11] == 0xff))
+
+#define _PR_IN6_IS_ADDR_V4COMPAT(a) \
+ (((a)->pr_s6_addr32[0] == 0) && \
+ ((a)->pr_s6_addr32[1] == 0) && \
+ ((a)->pr_s6_addr32[2] == 0))
+
+#define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->pr_s6_addr32[3])
+
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+
+/*
+ * The _pr_QueryNetIfs() function finds out if the system has
+ * IPv4 or IPv6 source addresses configured and sets _pr_have_inet_if
+ * and _pr_have_inet6_if accordingly.
+ *
+ * We have an implementation using SIOCGIFCONF ioctl and a
+ * default implementation that simply sets _pr_have_inet_if
+ * and _pr_have_inet6_if to true. A better implementation
+ * would be to use the routing sockets (see Chapter 17 of
+ * W. Richard Stevens' Unix Network Programming, Vol. 1, 2nd. Ed.)
+ */
+
+static PRLock *_pr_query_ifs_lock = NULL;
+static PRBool _pr_have_inet_if = PR_FALSE;
+static PRBool _pr_have_inet6_if = PR_FALSE;
+
+#undef DEBUG_QUERY_IFS
+
+#if defined(AIX) \
+ || (defined(DARWIN) && (!defined(HAVE_GETIFADDRS) \
+ || (defined(MACOS_DEPLOYMENT_TARGET) \
+ && MACOS_DEPLOYMENT_TARGET < 100200)))
+
+/*
+ * Use SIOCGIFCONF ioctl on platforms that don't have routing
+ * sockets. Warning: whether SIOCGIFCONF ioctl returns AF_INET6
+ * network interfaces is not portable.
+ *
+ * The _pr_QueryNetIfs() function is derived from the code in
+ * src/lib/libc/net/getifaddrs.c in BSD Unix and the code in
+ * Section 16.6 of W. Richard Stevens' Unix Network Programming,
+ * Vol. 1, 2nd. Ed.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#ifdef DEBUG_QUERY_IFS
+static void
+_pr_PrintIfreq(struct ifreq *ifr)
+{
+ PRNetAddr addr;
+ struct sockaddr *sa;
+ const char* family;
+ char addrstr[64];
+
+ sa = &ifr->ifr_addr;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ family = "inet";
+ memcpy(&addr.inet.ip, &sin->sin_addr, sizeof(sin->sin_addr));
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ family = "inet6";
+ memcpy(&addr.ipv6.ip, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
+ } else {
+ return; /* skip if not AF_INET or AF_INET6 */
+ }
+ addr.raw.family = sa->sa_family;
+ PR_NetAddrToString(&addr, addrstr, sizeof(addrstr));
+ printf("%s: %s %s\n", ifr->ifr_name, family, addrstr);
+}
+#endif
+
+static void
+_pr_QueryNetIfs(void)
+{
+ int sock;
+ int rv;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ struct ifreq *lifr;
+ PRUint32 len, lastlen;
+ char *buf;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ return;
+ }
+
+ /* Issue SIOCGIFCONF request in a loop. */
+ lastlen = 0;
+ len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
+ for (;;) {
+ buf = (char *)PR_Malloc(len);
+ if (NULL == buf) {
+ close(sock);
+ return;
+ }
+ ifc.ifc_buf = buf;
+ ifc.ifc_len = len;
+ rv = ioctl(sock, SIOCGIFCONF, &ifc);
+ if (rv < 0) {
+ if (errno != EINVAL || lastlen != 0) {
+ close(sock);
+ PR_Free(buf);
+ return;
+ }
+ } else {
+ if (ifc.ifc_len == lastlen)
+ break; /* success, len has not changed */
+ lastlen = ifc.ifc_len;
+ }
+ len += 10 * sizeof(struct ifreq); /* increment */
+ PR_Free(buf);
+ }
+ close(sock);
+
+ ifr = ifc.ifc_req;
+ lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
+
+ while (ifr < lifr) {
+ struct sockaddr *sa;
+ int sa_len;
+
+#ifdef DEBUG_QUERY_IFS
+ _pr_PrintIfreq(ifr);
+#endif
+ sa = &ifr->ifr_addr;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+ _pr_have_inet_if = PR_TRUE;
+ }
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)
+ && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ _pr_have_inet6_if = PR_TRUE;
+ }
+ }
+
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ sa_len = PR_MAX(sa->sa_len, sizeof(struct sockaddr));
+#else
+ switch (sa->sa_family) {
+#ifdef AF_LINK
+ case AF_LINK:
+ sa_len = sizeof(struct sockaddr_dl);
+ break;
+#endif
+ case AF_INET6:
+ sa_len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ sa_len = sizeof(struct sockaddr);
+ break;
+ }
+#endif
+ ifr = (struct ifreq *)(((char *)sa) + sa_len);
+ }
+ PR_Free(buf);
+}
+
+#elif (defined(DARWIN) && defined(HAVE_GETIFADDRS)) || defined(FREEBSD) \
+ || defined(NETBSD) || defined(OPENBSD)
+
+/*
+ * Use the BSD getifaddrs function.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+
+#ifdef DEBUG_QUERY_IFS
+static void
+_pr_PrintIfaddrs(struct ifaddrs *ifa)
+{
+ struct sockaddr *sa;
+ const char* family;
+ void *addrp;
+ char addrstr[64];
+
+ sa = ifa->ifa_addr;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ family = "inet";
+ addrp = &sin->sin_addr;
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ family = "inet6";
+ addrp = &sin6->sin6_addr;
+ } else {
+ return; /* skip if not AF_INET or AF_INET6 */
+ }
+ inet_ntop(sa->sa_family, addrp, addrstr, sizeof(addrstr));
+ printf("%s: %s %s\n", ifa->ifa_name, family, addrstr);
+}
+#endif
+
+static void
+_pr_QueryNetIfs(void)
+{
+ struct ifaddrs *ifp;
+ struct ifaddrs *ifa;
+
+ if (getifaddrs(&ifp) == -1) {
+ return;
+ }
+ for (ifa = ifp; ifa; ifa = ifa->ifa_next) {
+ struct sockaddr *sa;
+
+#ifdef DEBUG_QUERY_IFS
+ _pr_PrintIfaddrs(ifa);
+#endif
+ sa = ifa->ifa_addr;
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+ _pr_have_inet_if = 1;
+ }
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)
+ && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ _pr_have_inet6_if = 1;
+ }
+ }
+ }
+ freeifaddrs(ifp);
+}
+
+#else /* default */
+
+/*
+ * Emulate the code in NSPR 4.2 or older. PR_GetIPNodeByName behaves
+ * as if the system had both IPv4 and IPv6 source addresses configured.
+ */
+static void
+_pr_QueryNetIfs(void)
+{
+ _pr_have_inet_if = PR_TRUE;
+ _pr_have_inet6_if = PR_TRUE;
+}
+
+#endif
+
+#endif /* _PR_INET6 && _PR_HAVE_GETHOSTBYNAME2 */
+
+void _PR_InitNet(void)
+{
+#if defined(XP_UNIX)
+#ifdef HAVE_NETCONFIG
+ /*
+ * This one-liner prevents the endless re-open's and re-read's of
+ * /etc/netconfig on EACH and EVERY call to accept(), connect(), etc.
+ */
+ (void)setnetconfig();
+#endif
+#endif
+#if !defined(_PR_NO_DNS_LOCK)
+ _pr_dnsLock = PR_NewLock();
+#endif
+#if !defined(_PR_HAVE_GETPROTO_R)
+ _getproto_lock = PR_NewLock();
+#endif
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+ _pr_query_ifs_lock = PR_NewLock();
+#endif
+}
+
+void _PR_CleanupNet(void)
+{
+#if !defined(_PR_NO_DNS_LOCK)
+ if (_pr_dnsLock) {
+ PR_DestroyLock(_pr_dnsLock);
+ _pr_dnsLock = NULL;
+ }
+#endif
+#if !defined(_PR_HAVE_GETPROTO_R)
+ if (_getproto_lock) {
+ PR_DestroyLock(_getproto_lock);
+ _getproto_lock = NULL;
+ }
+#endif
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+ if (_pr_query_ifs_lock) {
+ PR_DestroyLock(_pr_query_ifs_lock);
+ _pr_query_ifs_lock = NULL;
+ }
+#endif
+}
+
+/*
+** Allocate space from the buffer, aligning it to "align" before doing
+** the allocation. "align" must be a power of 2.
+*/
+static char *Alloc(PRIntn amount, char **bufp, PRIntn *buflenp, PRIntn align)
+{
+ char *buf = *bufp;
+ PRIntn buflen = *buflenp;
+
+ if (align && ((long)buf & (align - 1))) {
+ PRIntn skip = align - ((ptrdiff_t)buf & (align - 1));
+ if (buflen < skip) {
+ return 0;
+ }
+ buf += skip;
+ buflen -= skip;
+ }
+ if (buflen < amount) {
+ return 0;
+ }
+ *bufp = buf + amount;
+ *buflenp = buflen - amount;
+ return buf;
+}
+
+typedef enum _PRIPAddrConversion {
+ _PRIPAddrNoConversion,
+ _PRIPAddrIPv4Mapped,
+ _PRIPAddrIPv4Compat
+} _PRIPAddrConversion;
+
+/*
+** Convert an IPv4 address (v4) to an IPv4-mapped IPv6 address (v6).
+*/
+static void MakeIPv4MappedAddr(const char *v4, char *v6)
+{
+ memset(v6, 0, 10);
+ memset(v6 + 10, 0xff, 2);
+ memcpy(v6 + 12, v4, 4);
+}
+
+/*
+** Convert an IPv4 address (v4) to an IPv4-compatible IPv6 address (v6).
+*/
+static void MakeIPv4CompatAddr(const char *v4, char *v6)
+{
+ memset(v6, 0, 12);
+ memcpy(v6 + 12, v4, 4);
+}
+
+/*
+** Copy a hostent, and all of the memory that it refers to into
+** (hopefully) stacked buffers.
+*/
+static PRStatus CopyHostent(
+ struct hostent *from,
+ char **buf,
+ PRIntn *bufsize,
+ _PRIPAddrConversion conversion,
+ PRHostEnt *to)
+{
+ PRIntn len, na;
+ char **ap;
+
+ if (conversion != _PRIPAddrNoConversion
+ && from->h_addrtype == AF_INET) {
+ PR_ASSERT(from->h_length == 4);
+ to->h_addrtype = PR_AF_INET6;
+ to->h_length = 16;
+ } else {
+#if defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+ if (AF_INET6 == from->h_addrtype)
+ to->h_addrtype = PR_AF_INET6;
+ else
+#endif
+ to->h_addrtype = from->h_addrtype;
+ to->h_length = from->h_length;
+ }
+
+ /* Copy the official name */
+ if (!from->h_name) return PR_FAILURE;
+ len = strlen(from->h_name) + 1;
+ to->h_name = Alloc(len, buf, bufsize, 0);
+ if (!to->h_name) return PR_FAILURE;
+ memcpy(to->h_name, from->h_name, len);
+
+ /* Count the aliases, then allocate storage for the pointers */
+ if (!from->h_aliases) {
+ na = 1;
+ } else {
+ for (na = 1, ap = from->h_aliases; *ap != 0; na++, ap++){;} /* nothing to execute */
+ }
+ to->h_aliases = (char**)Alloc(
+ na * sizeof(char*), buf, bufsize, sizeof(char**));
+ if (!to->h_aliases) return PR_FAILURE;
+
+ /* Copy the aliases, one at a time */
+ if (!from->h_aliases) {
+ to->h_aliases[0] = 0;
+ } else {
+ for (na = 0, ap = from->h_aliases; *ap != 0; na++, ap++) {
+ len = strlen(*ap) + 1;
+ to->h_aliases[na] = Alloc(len, buf, bufsize, 0);
+ if (!to->h_aliases[na]) return PR_FAILURE;
+ memcpy(to->h_aliases[na], *ap, len);
+ }
+ to->h_aliases[na] = 0;
+ }
+
+ /* Count the addresses, then allocate storage for the pointers */
+ for (na = 1, ap = from->h_addr_list; *ap != 0; na++, ap++){;} /* nothing to execute */
+ to->h_addr_list = (char**)Alloc(
+ na * sizeof(char*), buf, bufsize, sizeof(char**));
+ if (!to->h_addr_list) return PR_FAILURE;
+
+ /* Copy the addresses, one at a time */
+ for (na = 0, ap = from->h_addr_list; *ap != 0; na++, ap++) {
+ to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0);
+ if (!to->h_addr_list[na]) return PR_FAILURE;
+ if (conversion != _PRIPAddrNoConversion
+ && from->h_addrtype == AF_INET) {
+ if (conversion == _PRIPAddrIPv4Mapped) {
+ MakeIPv4MappedAddr(*ap, to->h_addr_list[na]);
+ } else {
+ PR_ASSERT(conversion == _PRIPAddrIPv4Compat);
+ MakeIPv4CompatAddr(*ap, to->h_addr_list[na]);
+ }
+ } else {
+ memcpy(to->h_addr_list[na], *ap, to->h_length);
+ }
+ }
+ to->h_addr_list[na] = 0;
+ return PR_SUCCESS;
+}
+
+#if !defined(_PR_HAVE_GETPROTO_R)
+/*
+** Copy a protoent, and all of the memory that it refers to into
+** (hopefully) stacked buffers.
+*/
+static PRStatus CopyProtoent(
+ struct protoent *from, char *buf, PRIntn bufsize, PRProtoEnt *to)
+{
+ PRIntn len, na;
+ char **ap;
+
+ /* Do the easy stuff */
+ to->p_num = from->p_proto;
+
+ /* Copy the official name */
+ if (!from->p_name) return PR_FAILURE;
+ len = strlen(from->p_name) + 1;
+ to->p_name = Alloc(len, &buf, &bufsize, 0);
+ if (!to->p_name) return PR_FAILURE;
+ memcpy(to->p_name, from->p_name, len);
+
+ /* Count the aliases, then allocate storage for the pointers */
+ for (na = 1, ap = from->p_aliases; *ap != 0; na++, ap++){;} /* nothing to execute */
+ to->p_aliases = (char**)Alloc(
+ na * sizeof(char*), &buf, &bufsize, sizeof(char**));
+ if (!to->p_aliases) return PR_FAILURE;
+
+ /* Copy the aliases, one at a time */
+ for (na = 0, ap = from->p_aliases; *ap != 0; na++, ap++) {
+ len = strlen(*ap) + 1;
+ to->p_aliases[na] = Alloc(len, &buf, &bufsize, 0);
+ if (!to->p_aliases[na]) return PR_FAILURE;
+ memcpy(to->p_aliases[na], *ap, len);
+ }
+ to->p_aliases[na] = 0;
+
+ return PR_SUCCESS;
+}
+#endif /* !defined(_PR_HAVE_GETPROTO_R) */
+
+/*
+ * #################################################################
+ * NOTE: tmphe, tmpbuf, bufsize, h, and h_err are local variables
+ * or arguments of PR_GetHostByName, PR_GetIPNodeByName, and
+ * PR_GetHostByAddr. DO NOT CHANGE THE NAMES OF THESE LOCAL
+ * VARIABLES OR ARGUMENTS.
+ * #################################################################
+ */
+#if defined(_PR_HAVE_GETHOST_R_INT)
+
+#define GETHOSTBYNAME(name) \
+ (gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &h_err), h)
+#define GETHOSTBYNAME2(name, af) \
+ (gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h, &h_err), h)
+#define GETHOSTBYADDR(addr, addrlen, af) \
+ (gethostbyaddr_r(addr, addrlen, af, \
+ &tmphe, tmpbuf, bufsize, &h, &h_err), h)
+
+#elif defined(_PR_HAVE_GETHOST_R_POINTER)
+
+#define GETHOSTBYNAME(name) \
+ gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h_err)
+#define GETHOSTBYNAME2(name, af) \
+ gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h_err)
+#define GETHOSTBYADDR(addr, addrlen, af) \
+ gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize, &h_err)
+
+#else
+
+#define GETHOSTBYNAME(name) gethostbyname(name)
+#define GETHOSTBYNAME2(name, af) gethostbyname2(name, af)
+#define GETHOSTBYADDR(addr, addrlen, af) gethostbyaddr(addr, addrlen, af)
+
+#endif /* definition of GETHOSTBYXXX */
+
+PR_IMPLEMENT(PRStatus) PR_GetHostByName(
+ const char *name, char *buf, PRIntn bufsize, PRHostEnt *hp)
+{
+ struct hostent *h;
+ PRStatus rv = PR_FAILURE;
+#if defined(_PR_HAVE_GETHOST_R)
+ char localbuf[PR_NETDB_BUF_SIZE];
+ char *tmpbuf;
+ struct hostent tmphe;
+ int h_err;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#if defined(_PR_HAVE_GETHOST_R)
+ tmpbuf = localbuf;
+ if (bufsize > sizeof(localbuf))
+ {
+ tmpbuf = (char *)PR_Malloc(bufsize);
+ if (NULL == tmpbuf)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return rv;
+ }
+ }
+#endif
+
+ LOCK_DNS();
+
+#ifdef XP_OS2_VACPP
+ h = GETHOSTBYNAME((char *)name);
+#else
+ h = GETHOSTBYNAME(name);
+#endif
+
+ if (NULL == h)
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
+ }
+ else
+ {
+ _PRIPAddrConversion conversion = _PRIPAddrNoConversion;
+ rv = CopyHostent(h, &buf, &bufsize, conversion, hp);
+ if (PR_SUCCESS != rv)
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+ UNLOCK_DNS();
+#if defined(_PR_HAVE_GETHOST_R)
+ if (tmpbuf != localbuf)
+ PR_Free(tmpbuf);
+#endif
+ return rv;
+}
+
+#if !defined(_PR_INET6) && \
+ defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
+typedef struct hostent * (*_pr_getipnodebyname_t)(const char *, int,
+ int, int *);
+typedef struct hostent * (*_pr_getipnodebyaddr_t)(const void *, size_t,
+ int, int *);
+typedef void (*_pr_freehostent_t)(struct hostent *);
+static void * _pr_getipnodebyname_fp;
+static void * _pr_getipnodebyaddr_fp;
+static void * _pr_freehostent_fp;
+
+/*
+ * Look up the addresses of getipnodebyname, getipnodebyaddr,
+ * and freehostent.
+ */
+PRStatus
+_pr_find_getipnodebyname(void)
+{
+ PRLibrary *lib;
+ PRStatus rv;
+#if defined(VMS)
+#define GETIPNODEBYNAME getenv("GETIPNODEBYNAME")
+#define GETIPNODEBYADDR getenv("GETIPNODEBYADDR")
+#define FREEHOSTENT getenv("FREEHOSTENT")
+#else
+#define GETIPNODEBYNAME "getipnodebyname"
+#define GETIPNODEBYADDR "getipnodebyaddr"
+#define FREEHOSTENT "freehostent"
+#endif
+ _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib);
+ if (NULL != _pr_getipnodebyname_fp) {
+ _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT);
+ if (NULL != _pr_freehostent_fp) {
+ _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR);
+ if (NULL != _pr_getipnodebyaddr_fp)
+ rv = PR_SUCCESS;
+ else
+ rv = PR_FAILURE;
+ } else
+ rv = PR_FAILURE;
+ (void)PR_UnloadLibrary(lib);
+ } else
+ rv = PR_FAILURE;
+ return rv;
+}
+#endif
+
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+/*
+** Append the V4 addresses to the end of the list
+*/
+static PRStatus AppendV4AddrsToHostent(
+ struct hostent *from,
+ char **buf,
+ PRIntn *bufsize,
+ PRHostEnt *to)
+{
+ PRIntn na, na_old;
+ char **ap;
+ char **new_addr_list;
+
+ /* Count the addresses, then grow storage for the pointers */
+ for (na_old = 0, ap = to->h_addr_list; *ap != 0; na_old++, ap++)
+ {;} /* nothing to execute */
+ for (na = na_old + 1, ap = from->h_addr_list; *ap != 0; na++, ap++)
+ {;} /* nothing to execute */
+ new_addr_list = (char**)Alloc(
+ na * sizeof(char*), buf, bufsize, sizeof(char**));
+ if (!new_addr_list) return PR_FAILURE;
+
+ /* Copy the V6 addresses, one at a time */
+ for (na = 0, ap = to->h_addr_list; *ap != 0; na++, ap++) {
+ new_addr_list[na] = to->h_addr_list[na];
+ }
+ to->h_addr_list = new_addr_list;
+
+ /* Copy the V4 addresses, one at a time */
+ for (ap = from->h_addr_list; *ap != 0; na++, ap++) {
+ to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0);
+ if (!to->h_addr_list[na]) return PR_FAILURE;
+ MakeIPv4MappedAddr(*ap, to->h_addr_list[na]);
+ }
+ to->h_addr_list[na] = 0;
+ return PR_SUCCESS;
+}
+#endif
+
+PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName(
+ const char *name, PRUint16 af, PRIntn flags,
+ char *buf, PRIntn bufsize, PRHostEnt *hp)
+{
+ struct hostent *h = 0;
+ PRStatus rv = PR_FAILURE;
+#if defined(_PR_HAVE_GETHOST_R)
+ char localbuf[PR_NETDB_BUF_SIZE];
+ char *tmpbuf;
+ struct hostent tmphe;
+ int h_err;
+#endif
+#if defined(_PR_HAVE_GETIPNODEBYNAME)
+ PRUint16 md_af = af;
+ int error_num;
+ int tmp_flags = 0;
+#endif
+#if defined(_PR_HAVE_GETHOSTBYNAME2)
+ PRBool did_af_inet = PR_FALSE;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (af != PR_AF_INET && af != PR_AF_INET6) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+ PR_Lock(_pr_query_ifs_lock);
+ /*
+ * Keep querying the presence of IPv4 and IPv6 interfaces until
+ * at least one is up. This allows us to detect the local
+ * machine going from offline to online.
+ */
+ if (!_pr_have_inet_if && !_pr_have_inet6_if) {
+ _pr_QueryNetIfs();
+#ifdef DEBUG_QUERY_IFS
+ if (_pr_have_inet_if)
+ printf("Have IPv4 source address\n");
+ if (_pr_have_inet6_if)
+ printf("Have IPv6 source address\n");
+#endif
+ }
+ PR_Unlock(_pr_query_ifs_lock);
+#endif
+
+#if defined(_PR_HAVE_GETIPNODEBYNAME)
+ if (flags & PR_AI_V4MAPPED)
+ tmp_flags |= AI_V4MAPPED;
+ if (flags & PR_AI_ADDRCONFIG)
+ tmp_flags |= AI_ADDRCONFIG;
+ if (flags & PR_AI_ALL)
+ tmp_flags |= AI_ALL;
+ if (af == PR_AF_INET6)
+ md_af = AF_INET6;
+ else
+ md_af = af;
+#endif
+
+#if defined(_PR_HAVE_GETHOST_R)
+ tmpbuf = localbuf;
+ if (bufsize > sizeof(localbuf))
+ {
+ tmpbuf = (char *)PR_Malloc(bufsize);
+ if (NULL == tmpbuf)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return rv;
+ }
+ }
+#endif
+
+ /* Do not need to lock the DNS lock if getipnodebyname() is called */
+#ifdef _PR_INET6
+#ifdef _PR_HAVE_GETHOSTBYNAME2
+ LOCK_DNS();
+ if (af == PR_AF_INET6)
+ {
+ if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet6_if)
+ {
+#ifdef _PR_INET6_PROBE
+ if (_pr_ipv6_is_present == PR_TRUE)
+#endif
+ h = GETHOSTBYNAME2(name, AF_INET6);
+ }
+ if ((NULL == h) && (flags & PR_AI_V4MAPPED)
+ && ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if))
+ {
+ did_af_inet = PR_TRUE;
+ h = GETHOSTBYNAME2(name, AF_INET);
+ }
+ }
+ else
+ {
+ if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if)
+ {
+ did_af_inet = PR_TRUE;
+ h = GETHOSTBYNAME2(name, af);
+ }
+ }
+#elif defined(_PR_HAVE_GETIPNODEBYNAME)
+ h = getipnodebyname(name, md_af, tmp_flags, &error_num);
+#else
+#error "Unknown name-to-address translation function"
+#endif /* _PR_HAVE_GETHOSTBYNAME2 */
+#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ {
+#ifdef PR_GETIPNODE_NOT_THREADSAFE
+ LOCK_DNS();
+#endif
+ h = (*((_pr_getipnodebyname_t)_pr_getipnodebyname_fp))(name, md_af, tmp_flags, &error_num);
+ }
+ else
+ {
+ LOCK_DNS();
+ h = GETHOSTBYNAME(name);
+ }
+#else /* _PR_INET6 */
+ LOCK_DNS();
+#ifdef XP_OS2_VACPP
+ h = GETHOSTBYNAME((char *)name);
+#else
+ h = GETHOSTBYNAME(name);
+#endif
+#endif /* _PR_INET6 */
+
+ if (NULL == h)
+ {
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
+#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
+ else
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
+#else
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
+#endif
+ }
+ else
+ {
+ _PRIPAddrConversion conversion = _PRIPAddrNoConversion;
+
+ if (af == PR_AF_INET6) conversion = _PRIPAddrIPv4Mapped;
+ rv = CopyHostent(h, &buf, &bufsize, conversion, hp);
+ if (PR_SUCCESS != rv)
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ freehostent(h);
+#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ (*((_pr_freehostent_t)_pr_freehostent_fp))(h);
+#endif
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+ if ((PR_SUCCESS == rv) && (flags & PR_AI_V4MAPPED)
+ && ((flags & PR_AI_ALL)
+ || ((flags & PR_AI_ADDRCONFIG) && _pr_have_inet_if))
+ && !did_af_inet && (h = GETHOSTBYNAME2(name, AF_INET)) != 0) {
+ rv = AppendV4AddrsToHostent(h, &buf, &bufsize, hp);
+ if (PR_SUCCESS != rv)
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+#endif
+ }
+
+ /* Must match the convoluted logic above for LOCK_DNS() */
+#ifdef _PR_INET6
+#ifdef _PR_HAVE_GETHOSTBYNAME2
+ UNLOCK_DNS();
+#endif /* _PR_HAVE_GETHOSTBYNAME2 */
+#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME)
+#ifdef PR_GETIPNODE_NOT_THREADSAFE
+ UNLOCK_DNS();
+#else
+ if (_pr_ipv6_is_present == PR_FALSE)
+ UNLOCK_DNS();
+#endif
+#else /* _PR_INET6 */
+ UNLOCK_DNS();
+#endif /* _PR_INET6 */
+
+#if defined(_PR_HAVE_GETHOST_R)
+ if (tmpbuf != localbuf)
+ PR_Free(tmpbuf);
+#endif
+
+ return rv;
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetHostByAddr(
+ const PRNetAddr *hostaddr, char *buf, PRIntn bufsize, PRHostEnt *hostentry)
+{
+ struct hostent *h;
+ PRStatus rv = PR_FAILURE;
+ const void *addr;
+ PRUint32 tmp_ip;
+ int addrlen;
+ PRInt32 af;
+#if defined(_PR_HAVE_GETHOST_R)
+ char localbuf[PR_NETDB_BUF_SIZE];
+ char *tmpbuf;
+ struct hostent tmphe;
+ int h_err;
+#endif
+#if defined(_PR_HAVE_GETIPNODEBYADDR)
+ int error_num;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (hostaddr->raw.family == PR_AF_INET6)
+ {
+#if defined(_PR_INET6_PROBE)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ af = AF_INET6;
+ else
+ af = AF_INET;
+#elif defined(_PR_INET6)
+ af = AF_INET6;
+#else
+ af = AF_INET;
+#endif
+#if defined(_PR_GHBA_DISALLOW_V4MAPPED)
+ if (_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip))
+ af = AF_INET;
+#endif
+ }
+ else
+ {
+ PR_ASSERT(hostaddr->raw.family == AF_INET);
+ af = AF_INET;
+ }
+ if (hostaddr->raw.family == PR_AF_INET6) {
+#if defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+ if (af == AF_INET6) {
+ addr = &hostaddr->ipv6.ip;
+ addrlen = sizeof(hostaddr->ipv6.ip);
+ }
+ else
+#endif
+ {
+ PR_ASSERT(af == AF_INET);
+ if (!_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return rv;
+ }
+ tmp_ip = _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)
+ &hostaddr->ipv6.ip);
+ addr = &tmp_ip;
+ addrlen = sizeof(tmp_ip);
+ }
+ } else {
+ PR_ASSERT(hostaddr->raw.family == AF_INET);
+ PR_ASSERT(af == AF_INET);
+ addr = &hostaddr->inet.ip;
+ addrlen = sizeof(hostaddr->inet.ip);
+ }
+
+#if defined(_PR_HAVE_GETHOST_R)
+ tmpbuf = localbuf;
+ if (bufsize > sizeof(localbuf))
+ {
+ tmpbuf = (char *)PR_Malloc(bufsize);
+ if (NULL == tmpbuf)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return rv;
+ }
+ }
+#endif
+
+ /* Do not need to lock the DNS lock if getipnodebyaddr() is called */
+#if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6)
+ h = getipnodebyaddr(addr, addrlen, af, &error_num);
+#elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ {
+#ifdef PR_GETIPNODE_NOT_THREADSAFE
+ LOCK_DNS();
+#endif
+ h = (*((_pr_getipnodebyaddr_t)_pr_getipnodebyaddr_fp))(addr, addrlen,
+ af, &error_num);
+ }
+ else
+ {
+ LOCK_DNS();
+ h = GETHOSTBYADDR(addr, addrlen, af);
+ }
+#else /* _PR_HAVE_GETIPNODEBYADDR */
+ LOCK_DNS();
+#ifdef XP_OS2_VACPP
+ h = GETHOSTBYADDR((char *)addr, addrlen, af);
+#else
+ h = GETHOSTBYADDR(addr, addrlen, af);
+#endif
+#endif /* _PR_HAVE_GETIPNODEBYADDR */
+ if (NULL == h)
+ {
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
+#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
+ else
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
+#else
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
+#endif
+ }
+ else
+ {
+ _PRIPAddrConversion conversion = _PRIPAddrNoConversion;
+ if (hostaddr->raw.family == PR_AF_INET6) {
+ if (af == AF_INET) {
+ if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*)
+ &hostaddr->ipv6.ip)) {
+ conversion = _PRIPAddrIPv4Mapped;
+ } else if (_PR_IN6_IS_ADDR_V4COMPAT((PRIPv6Addr *)
+ &hostaddr->ipv6.ip)) {
+ conversion = _PRIPAddrIPv4Compat;
+ }
+ }
+ }
+ rv = CopyHostent(h, &buf, &bufsize, conversion, hostentry);
+ if (PR_SUCCESS != rv) {
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
+ freehostent(h);
+#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR)
+ if (_pr_ipv6_is_present == PR_TRUE)
+ (*((_pr_freehostent_t)_pr_freehostent_fp))(h);
+#endif
+ }
+
+ /* Must match the convoluted logic above for LOCK_DNS() */
+#if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6)
+#elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE)
+#ifdef PR_GETIPNODE_NOT_THREADSAFE
+ UNLOCK_DNS();
+#else
+ if (_pr_ipv6_is_present == PR_FALSE)
+ UNLOCK_DNS();
+#endif
+#else /* _PR_HAVE_GETIPNODEBYADDR */
+ UNLOCK_DNS();
+#endif /* _PR_HAVE_GETIPNODEBYADDR */
+
+#if defined(_PR_HAVE_GETHOST_R)
+ if (tmpbuf != localbuf)
+ PR_Free(tmpbuf);
+#endif
+
+ return rv;
+}
+
+/******************************************************************************/
+/*
+ * Some systems define a reentrant version of getprotobyname(). Too bad
+ * the signature isn't always the same. But hey, they tried. If there
+ * is such a definition, use it. Otherwise, grab a lock and do it here.
+ */
+/******************************************************************************/
+
+#if !defined(_PR_HAVE_GETPROTO_R)
+/*
+ * This may seem like a silly thing to do, but the compiler SHOULD
+ * complain if getprotobyname_r() is implemented on some system and
+ * we're not using it. For sure these signatures are different than
+ * any usable implementation.
+ */
+
+static struct protoent *getprotobyname_r(const char* name)
+{
+#ifdef XP_OS2_VACPP
+ return getprotobyname((char *)name);
+#else
+ return getprotobyname(name);
+#endif
+} /* getprotobyname_r */
+
+static struct protoent *getprotobynumber_r(PRInt32 number)
+{
+ return getprotobynumber(number);
+} /* getprotobynumber_r */
+
+#endif /* !defined(_PR_HAVE_GETPROTO_R) */
+
+PR_IMPLEMENT(PRStatus) PR_GetProtoByName(
+ const char* name, char* buffer, PRInt32 buflen, PRProtoEnt* result)
+{
+ PRStatus rv = PR_SUCCESS;
+#if defined(_PR_HAVE_GETPROTO_R)
+ struct protoent* res = (struct protoent*)result;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#if defined(_PR_HAVE_GETPROTO_R_INT)
+ {
+ /*
+ ** The protoent_data has a pointer as the first field.
+ ** That implies the buffer better be aligned, and char*
+ ** doesn't promise much.
+ */
+ PRUptrdiff aligned = (PRUptrdiff)buffer;
+ if (0 != (aligned & (sizeof(struct protoent_data*) - 1)))
+ {
+ aligned += sizeof(struct protoent_data*) - 1;
+ aligned &= ~(sizeof(struct protoent_data*) - 1);
+ buflen -= (aligned - (PRUptrdiff)buffer);
+ buffer = (char*)aligned;
+ }
+ }
+#endif /* defined(_PR_HAVE_GETPROTO_R_INT) */
+
+ if (PR_NETDB_BUF_SIZE > buflen)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+#if defined(_PR_HAVE_GETPROTO_R_POINTER)
+ if (NULL == getprotobyname_r(name, res, buffer, buflen))
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+#elif defined(_PR_HAVE_GETPROTO_R_INT)
+ /*
+ ** The buffer needs to be zero'd, and it should be
+ ** at least the size of a struct protoent_data.
+ */
+ memset(buffer, 0, buflen);
+ if (-1 == getprotobyname_r(name, res, (struct protoent_data*)buffer))
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+#elif defined(_PR_HAVE_5_ARG_GETPROTO_R)
+ /* The 5th argument for getprotobyname_r() cannot be NULL */
+ if (-1 == getprotobyname_r(name, res, buffer, buflen, &res))
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+#else /* do it the hard way */
+ {
+ struct protoent *staticBuf;
+ PR_Lock(_getproto_lock);
+ staticBuf = getprotobyname_r(name);
+ if (NULL == staticBuf)
+ {
+ rv = PR_FAILURE;
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ }
+ else
+ {
+ rv = CopyProtoent(staticBuf, buffer, buflen, result);
+ if (PR_FAILURE == rv)
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+ PR_Unlock(_getproto_lock);
+ }
+#endif /* all that */
+ return rv;
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetProtoByNumber(
+ PRInt32 number, char* buffer, PRInt32 buflen, PRProtoEnt* result)
+{
+ PRStatus rv = PR_SUCCESS;
+#if defined(_PR_HAVE_GETPROTO_R)
+ struct protoent* res = (struct protoent*)result;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#if defined(_PR_HAVE_GETPROTO_R_INT)
+ {
+ /*
+ ** The protoent_data has a pointer as the first field.
+ ** That implies the buffer better be aligned, and char*
+ ** doesn't promise much.
+ */
+ PRUptrdiff aligned = (PRUptrdiff)buffer;
+ if (0 != (aligned & (sizeof(struct protoent_data*) - 1)))
+ {
+ aligned += sizeof(struct protoent_data*) - 1;
+ aligned &= ~(sizeof(struct protoent_data*) - 1);
+ buflen -= (aligned - (PRUptrdiff)buffer);
+ buffer = (char*)aligned;
+ }
+ }
+#endif /* defined(_PR_HAVE_GETPROTO_R_INT) */
+
+ if (PR_NETDB_BUF_SIZE > buflen)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+#if defined(_PR_HAVE_GETPROTO_R_POINTER)
+ if (NULL == getprotobynumber_r(number, res, buffer, buflen))
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+
+#elif defined(_PR_HAVE_GETPROTO_R_INT)
+ /*
+ ** The buffer needs to be zero'd for these OS's.
+ */
+ memset(buffer, 0, buflen);
+ if (-1 == getprotobynumber_r(number, res, (struct protoent_data*)buffer))
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+#elif defined(_PR_HAVE_5_ARG_GETPROTO_R)
+ /* The 5th argument for getprotobynumber_r() cannot be NULL */
+ if (-1 == getprotobynumber_r(number, res, buffer, buflen, &res))
+ {
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ return PR_FAILURE;
+ }
+#else /* do it the hard way */
+ {
+ struct protoent *staticBuf;
+ PR_Lock(_getproto_lock);
+ staticBuf = getprotobynumber_r(number);
+ if (NULL == staticBuf)
+ {
+ rv = PR_FAILURE;
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO());
+ }
+ else
+ {
+ rv = CopyProtoent(staticBuf, buffer, buflen, result);
+ if (PR_FAILURE == rv)
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ }
+ PR_Unlock(_getproto_lock);
+ }
+#endif /* all that crap */
+ return rv;
+
+}
+
+PRUintn _PR_NetAddrSize(const PRNetAddr* addr)
+{
+ PRUintn addrsize;
+
+ /*
+ * RFC 2553 added a new field (sin6_scope_id) to
+ * struct sockaddr_in6. PRNetAddr's ipv6 member has a
+ * scope_id field to match the new field. In order to
+ * work with older implementations supporting RFC 2133,
+ * we take the size of struct sockaddr_in6 instead of
+ * addr->ipv6.
+ */
+ if (AF_INET == addr->raw.family)
+ addrsize = sizeof(addr->inet);
+ else if (PR_AF_INET6 == addr->raw.family)
+#if defined(_PR_INET6)
+ addrsize = sizeof(struct sockaddr_in6);
+#else
+ addrsize = sizeof(addr->ipv6);
+#endif
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ else if (AF_UNIX == addr->raw.family)
+ addrsize = sizeof(addr->local);
+#endif
+ else addrsize = 0;
+
+ return addrsize;
+} /* _PR_NetAddrSize */
+
+PR_IMPLEMENT(PRIntn) PR_EnumerateHostEnt(
+ PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address)
+{
+ void *addr = hostEnt->h_addr_list[enumIndex++];
+ memset(address, 0, sizeof(PRNetAddr));
+ if (NULL == addr) enumIndex = 0;
+ else
+ {
+ address->raw.family = hostEnt->h_addrtype;
+ if (PR_AF_INET6 == hostEnt->h_addrtype)
+ {
+ address->ipv6.port = htons(port);
+ address->ipv6.flowinfo = 0;
+ address->ipv6.scope_id = 0;
+ memcpy(&address->ipv6.ip, addr, hostEnt->h_length);
+ }
+ else
+ {
+ PR_ASSERT(AF_INET == hostEnt->h_addrtype);
+ address->inet.port = htons(port);
+ memcpy(&address->inet.ip, addr, hostEnt->h_length);
+ }
+ }
+ return enumIndex;
+} /* PR_EnumerateHostEnt */
+
+PR_IMPLEMENT(PRStatus) PR_InitializeNetAddr(
+ PRNetAddrValue val, PRUint16 port, PRNetAddr *addr)
+{
+ PRStatus rv = PR_SUCCESS;
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->inet));
+ addr->inet.family = AF_INET;
+ addr->inet.port = htons(port);
+ switch (val)
+ {
+ case PR_IpAddrNull:
+ break; /* don't overwrite the address */
+ case PR_IpAddrAny:
+ addr->inet.ip = htonl(INADDR_ANY);
+ break;
+ case PR_IpAddrLoopback:
+ addr->inet.ip = htonl(INADDR_LOOPBACK);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* PR_InitializeNetAddr */
+
+PR_IMPLEMENT(PRStatus) PR_SetNetAddr(
+ PRNetAddrValue val, PRUint16 af, PRUint16 port, PRNetAddr *addr)
+{
+ PRStatus rv = PR_SUCCESS;
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (af == PR_AF_INET6)
+ {
+ if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->ipv6));
+ addr->ipv6.family = af;
+ addr->ipv6.port = htons(port);
+ addr->ipv6.flowinfo = 0;
+ addr->ipv6.scope_id = 0;
+ switch (val)
+ {
+ case PR_IpAddrNull:
+ break; /* don't overwrite the address */
+ case PR_IpAddrAny:
+ addr->ipv6.ip = _pr_in6addr_any;
+ break;
+ case PR_IpAddrLoopback:
+ addr->ipv6.ip = _pr_in6addr_loopback;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ }
+ else
+ {
+ if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->inet));
+ addr->inet.family = af;
+ addr->inet.port = htons(port);
+ switch (val)
+ {
+ case PR_IpAddrNull:
+ break; /* don't overwrite the address */
+ case PR_IpAddrAny:
+ addr->inet.ip = htonl(INADDR_ANY);
+ break;
+ case PR_IpAddrLoopback:
+ addr->inet.ip = htonl(INADDR_LOOPBACK);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ }
+ return rv;
+} /* PR_SetNetAddr */
+
+PR_IMPLEMENT(PRBool)
+PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val)
+{
+ if (addr->raw.family == PR_AF_INET6) {
+ if (val == PR_IpAddrAny) {
+ if (_PR_IN6_IS_ADDR_UNSPECIFIED((PRIPv6Addr *)&addr->ipv6.ip)) {
+ return PR_TRUE;
+ } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)
+ && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip)
+ == htonl(INADDR_ANY)) {
+ return PR_TRUE;
+ }
+ } else if (val == PR_IpAddrLoopback) {
+ if (_PR_IN6_IS_ADDR_LOOPBACK((PRIPv6Addr *)&addr->ipv6.ip)) {
+ return PR_TRUE;
+ } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)
+ && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip)
+ == htonl(INADDR_LOOPBACK)) {
+ return PR_TRUE;
+ }
+ } else if (val == PR_IpAddrV4Mapped
+ && _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)) {
+ return PR_TRUE;
+ }
+ } else {
+ if (addr->raw.family == AF_INET) {
+ if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)) {
+ return PR_TRUE;
+ } else if (val == PR_IpAddrLoopback
+ && addr->inet.ip == htonl(INADDR_LOOPBACK)) {
+ return PR_TRUE;
+ }
+ }
+ }
+ return PR_FALSE;
+}
+
+#ifndef _PR_HAVE_INET_NTOP
+#define XX 127
+static const unsigned char index_hex[256] = {
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,XX,XX, XX,XX,XX,XX,
+ XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+};
+
+/*
+ * StringToV6Addr() returns 1 if the conversion succeeds,
+ * or 0 if the input is not a valid IPv6 address string.
+ * (Same as inet_pton(AF_INET6, string, addr).)
+ */
+static int StringToV6Addr(const char *string, PRIPv6Addr *addr)
+{
+ const unsigned char *s = (const unsigned char *)string;
+ int section = 0; /* index of the current section (a 16-bit
+ * piece of the address */
+ int double_colon = -1; /* index of the section after the first
+ * 16-bit group of zeros represented by
+ * the double colon */
+ unsigned int val;
+ int len;
+
+ /* Handle initial (double) colon */
+ if (*s == ':') {
+ if (s[1] != ':') return 0;
+ s += 2;
+ addr->pr_s6_addr16[0] = 0;
+ section = double_colon = 1;
+ }
+
+ while (*s) {
+ if (section == 8) return 0; /* too long */
+ if (*s == ':') {
+ if (double_colon != -1) return 0; /* two double colons */
+ addr->pr_s6_addr16[section++] = 0;
+ double_colon = section;
+ s++;
+ continue;
+ }
+ for (len = val = 0; len < 4 && index_hex[*s] != XX; len++) {
+ val = (val << 4) + index_hex[*s++];
+ }
+ if (*s == '.') {
+ if (len == 0) return 0; /* nothing between : and . */
+ break;
+ }
+ if (*s == ':') {
+ s++;
+ if (!*s) return 0; /* cannot end with single colon */
+ } else if (*s) {
+ return 0; /* bad character */
+ }
+ addr->pr_s6_addr16[section++] = htons((unsigned short)val);
+ }
+
+ if (*s == '.') {
+ /* Have a trailing v4 format address */
+ if (section > 6) return 0; /* not enough room */
+
+ /*
+ * The number before the '.' is decimal, but we parsed it
+ * as hex. That means it is in BCD. Check it for validity
+ * and convert it to binary.
+ */
+ if (val > 0x0255 || (val & 0xf0) > 0x90 || (val & 0xf) > 9) return 0;
+ val = (val >> 8) * 100 + ((val >> 4) & 0xf) * 10 + (val & 0xf);
+ addr->pr_s6_addr[2 * section] = val;
+
+ s++;
+ val = index_hex[*s++];
+ if (val > 9) return 0;
+ while (*s >= '0' && *s <= '9') {
+ val = val * 10 + *s++ - '0';
+ if (val > 255) return 0;
+ }
+ if (*s != '.') return 0; /* must have exactly 4 decimal numbers */
+ addr->pr_s6_addr[2 * section + 1] = val;
+ section++;
+
+ s++;
+ val = index_hex[*s++];
+ if (val > 9) return 0;
+ while (*s >= '0' && *s <= '9') {
+ val = val * 10 + *s++ - '0';
+ if (val > 255) return 0;
+ }
+ if (*s != '.') return 0; /* must have exactly 4 decimal numbers */
+ addr->pr_s6_addr[2 * section] = val;
+
+ s++;
+ val = index_hex[*s++];
+ if (val > 9) return 0;
+ while (*s >= '0' && *s <= '9') {
+ val = val * 10 + *s++ - '0';
+ if (val > 255) return 0;
+ }
+ if (*s) return 0; /* must have exactly 4 decimal numbers */
+ addr->pr_s6_addr[2 * section + 1] = val;
+ section++;
+ }
+
+ if (double_colon != -1) {
+ /* Stretch the double colon */
+ int tosection;
+ int ncopy = section - double_colon;
+ for (tosection = 7; ncopy--; tosection--) {
+ addr->pr_s6_addr16[tosection] =
+ addr->pr_s6_addr16[double_colon + ncopy];
+ }
+ while (tosection >= double_colon) {
+ addr->pr_s6_addr16[tosection--] = 0;
+ }
+ } else if (section != 8) {
+ return 0; /* too short */
+ }
+ return 1;
+}
+#undef XX
+
+static const char *basis_hex = "0123456789abcdef";
+
+/*
+ * V6AddrToString() returns a pointer to the buffer containing
+ * the text string if the conversion succeeds, and NULL otherwise.
+ * (Same as inet_ntop(AF_INET6, addr, buf, size), except that errno
+ * is not set on failure.)
+ */
+static const char *V6AddrToString(
+ const PRIPv6Addr *addr, char *buf, PRUint32 size)
+{
+#define STUFF(c) do { \
+ if (!size--) return NULL; \
+ *buf++ = (c); \
+} while (0)
+
+ int double_colon = -1; /* index of the first 16-bit
+ * group of zeros represented
+ * by the double colon */
+ int double_colon_length = 1; /* use double colon only if
+ * there are two or more 16-bit
+ * groups of zeros */
+ int zero_length;
+ int section;
+ unsigned int val;
+ const char *bufcopy = buf;
+
+ /* Scan to find the placement of the double colon */
+ for (section = 0; section < 8; section++) {
+ if (addr->pr_s6_addr16[section] == 0) {
+ zero_length = 1;
+ section++;
+ while (section < 8 && addr->pr_s6_addr16[section] == 0) {
+ zero_length++;
+ section++;
+ }
+ /* Select the longest sequence of zeros */
+ if (zero_length > double_colon_length) {
+ double_colon = section - zero_length;
+ double_colon_length = zero_length;
+ }
+ }
+ }
+
+ /* Now start converting to a string */
+ section = 0;
+
+ if (double_colon == 0) {
+ if (double_colon_length == 6 ||
+ (double_colon_length == 5 && addr->pr_s6_addr16[5] == 0xffff)) {
+ /* ipv4 format address */
+ STUFF(':');
+ STUFF(':');
+ if (double_colon_length == 5) {
+ STUFF('f');
+ STUFF('f');
+ STUFF('f');
+ STUFF('f');
+ STUFF(':');
+ }
+ if (addr->pr_s6_addr[12] > 99) STUFF(addr->pr_s6_addr[12]/100 + '0');
+ if (addr->pr_s6_addr[12] > 9) STUFF((addr->pr_s6_addr[12]%100)/10 + '0');
+ STUFF(addr->pr_s6_addr[12]%10 + '0');
+ STUFF('.');
+ if (addr->pr_s6_addr[13] > 99) STUFF(addr->pr_s6_addr[13]/100 + '0');
+ if (addr->pr_s6_addr[13] > 9) STUFF((addr->pr_s6_addr[13]%100)/10 + '0');
+ STUFF(addr->pr_s6_addr[13]%10 + '0');
+ STUFF('.');
+ if (addr->pr_s6_addr[14] > 99) STUFF(addr->pr_s6_addr[14]/100 + '0');
+ if (addr->pr_s6_addr[14] > 9) STUFF((addr->pr_s6_addr[14]%100)/10 + '0');
+ STUFF(addr->pr_s6_addr[14]%10 + '0');
+ STUFF('.');
+ if (addr->pr_s6_addr[15] > 99) STUFF(addr->pr_s6_addr[15]/100 + '0');
+ if (addr->pr_s6_addr[15] > 9) STUFF((addr->pr_s6_addr[15]%100)/10 + '0');
+ STUFF(addr->pr_s6_addr[15]%10 + '0');
+ STUFF('\0');
+ return bufcopy;
+ }
+ }
+
+ while (section < 8) {
+ if (section == double_colon) {
+ STUFF(':');
+ STUFF(':');
+ section += double_colon_length;
+ continue;
+ }
+ val = ntohs(addr->pr_s6_addr16[section]);
+ if (val > 0xfff) {
+ STUFF(basis_hex[val >> 12]);
+ }
+ if (val > 0xff) {
+ STUFF(basis_hex[(val >> 8) & 0xf]);
+ }
+ if (val > 0xf) {
+ STUFF(basis_hex[(val >> 4) & 0xf]);
+ }
+ STUFF(basis_hex[val & 0xf]);
+ section++;
+ if (section < 8 && section != double_colon) STUFF(':');
+ }
+ STUFF('\0');
+ return bufcopy;
+#undef STUFF
+}
+
+#endif /* !_PR_HAVE_INET_NTOP */
+
+PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr)
+{
+ PRStatus status = PR_SUCCESS;
+ PRIntn rv;
+
+#if defined(_PR_HAVE_INET_NTOP)
+ rv = inet_pton(AF_INET6, string, &addr->ipv6.ip);
+ if (1 == rv)
+ {
+ addr->raw.family = PR_AF_INET6;
+ }
+ else
+ {
+ PR_ASSERT(0 == rv);
+ /* clean up after the failed inet_pton() call */
+ memset(&addr->ipv6.ip, 0, sizeof(addr->ipv6.ip));
+ rv = inet_pton(AF_INET, string, &addr->inet.ip);
+ if (1 == rv)
+ {
+ addr->raw.family = AF_INET;
+ }
+ else
+ {
+ PR_ASSERT(0 == rv);
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ status = PR_FAILURE;
+ }
+ }
+#else /* _PR_HAVE_INET_NTOP */
+ rv = StringToV6Addr(string, &addr->ipv6.ip);
+ if (1 == rv) {
+ addr->raw.family = PR_AF_INET6;
+ return PR_SUCCESS;
+ }
+ PR_ASSERT(0 == rv);
+ /* clean up after the failed StringToV6Addr() call */
+ memset(&addr->ipv6.ip, 0, sizeof(addr->ipv6.ip));
+
+ addr->inet.family = AF_INET;
+#ifdef XP_OS2_VACPP
+ addr->inet.ip = inet_addr((char *)string);
+#else
+ addr->inet.ip = inet_addr(string);
+#endif
+ if ((PRUint32) -1 == addr->inet.ip)
+ {
+ /*
+ * The string argument is a malformed address string.
+ */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ status = PR_FAILURE;
+ }
+#endif /* _PR_HAVE_INET_NTOP */
+
+ return status;
+}
+
+PR_IMPLEMENT(PRStatus) PR_NetAddrToString(
+ const PRNetAddr *addr, char *string, PRUint32 size)
+{
+ if (PR_AF_INET6 == addr->raw.family)
+ {
+#if defined(_PR_HAVE_INET_NTOP)
+ if (NULL == inet_ntop(AF_INET6, &addr->ipv6.ip, string, size))
+#else
+ if (NULL == V6AddrToString(&addr->ipv6.ip, string, size))
+#endif
+ {
+ /* the size of the result buffer is inadequate */
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ return PR_FAILURE;
+ }
+ }
+ else
+ {
+ if (size < 16) goto failed;
+ if (AF_INET != addr->raw.family) goto failed;
+ else
+ {
+ unsigned char *byte = (unsigned char*)&addr->inet.ip;
+ PR_snprintf(string, size, "%u.%u.%u.%u",
+ byte[0], byte[1], byte[2], byte[3]);
+ }
+ }
+
+ return PR_SUCCESS;
+
+failed:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+
+} /* PR_NetAddrToString */
+
+/*
+ * Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr
+ */
+PR_IMPLEMENT(void) PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr *v6addr)
+{
+ PRUint8 *dstp;
+ dstp = v6addr->pr_s6_addr;
+ memset(dstp, 0, 10);
+ memset(dstp + 10, 0xff, 2);
+ memcpy(dstp + 12,(char *) &v4addr, 4);
+}
+
+PR_IMPLEMENT(PRUint16) PR_ntohs(PRUint16 n) { return ntohs(n); }
+PR_IMPLEMENT(PRUint32) PR_ntohl(PRUint32 n) { return ntohl(n); }
+PR_IMPLEMENT(PRUint16) PR_htons(PRUint16 n) { return htons(n); }
+PR_IMPLEMENT(PRUint32) PR_htonl(PRUint32 n) { return htonl(n); }
+PR_IMPLEMENT(PRUint64) PR_ntohll(PRUint64 n)
+{
+#ifdef IS_BIG_ENDIAN
+ return n;
+#else
+ PRUint64 tmp;
+ PRUint32 hi, lo;
+ LL_L2UI(lo, n);
+ LL_SHR(tmp, n, 32);
+ LL_L2UI(hi, tmp);
+ hi = PR_ntohl(hi);
+ lo = PR_ntohl(lo);
+ LL_UI2L(n, lo);
+ LL_SHL(n, n, 32);
+ LL_UI2L(tmp, hi);
+ LL_ADD(n, n, tmp);
+ return n;
+#endif
+} /* ntohll */
+
+PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n)
+{
+#ifdef IS_BIG_ENDIAN
+ return n;
+#else
+ PRUint64 tmp;
+ PRUint32 hi, lo;
+ LL_L2UI(lo, n);
+ LL_SHR(tmp, n, 32);
+ LL_L2UI(hi, tmp);
+ hi = htonl(hi);
+ lo = htonl(lo);
+ LL_UI2L(n, lo);
+ LL_SHL(n, n, 32);
+ LL_UI2L(tmp, hi);
+ LL_ADD(n, n, tmp);
+ return n;
+#endif
+} /* htonll */
+
+
+/*
+ * Implementation of PR_GetAddrInfoByName and friends
+ *
+ * Compile-time options:
+ *
+ * _PR_HAVE_GETADDRINFO Define this macro if the target system provides
+ * getaddrinfo. With this defined, NSPR will require
+ * getaddrinfo at run time. If this if not defined,
+ * then NSPR will attempt to dynamically resolve
+ * getaddrinfo, falling back to PR_GetHostByName if
+ * getaddrinfo does not exist on the target system.
+ *
+ * Since getaddrinfo is a relatively new system call on many systems,
+ * we are forced to dynamically resolve it at run time in most cases.
+ * The exception includes any system (such as Mac OS X) that is known to
+ * provide getaddrinfo in all versions that NSPR cares to support.
+ */
+
+#if defined(_PR_HAVE_GETADDRINFO)
+
+#if defined(_PR_INET6)
+
+typedef struct addrinfo PRADDRINFO;
+#define GETADDRINFO getaddrinfo
+#define FREEADDRINFO freeaddrinfo
+
+#elif defined(_PR_INET6_PROBE)
+
+typedef struct addrinfo PRADDRINFO;
+
+/* getaddrinfo/freeaddrinfo prototypes */
+#if defined(WIN32)
+#define FUNC_MODIFIER __stdcall
+#else
+#define FUNC_MODIFIER
+#endif
+typedef int (FUNC_MODIFIER * FN_GETADDRINFO)
+ (const char *nodename,
+ const char *servname,
+ const PRADDRINFO *hints,
+ PRADDRINFO **res);
+typedef int (FUNC_MODIFIER * FN_FREEADDRINFO)
+ (PRADDRINFO *ai);
+
+/* global state */
+static FN_GETADDRINFO _pr_getaddrinfo = NULL;
+static FN_FREEADDRINFO _pr_freeaddrinfo = NULL;
+
+#if defined(VMS)
+#define GETADDRINFO_SYMBOL getenv("GETADDRINFO")
+#define FREEADDRINFO_SYMBOL getenv("FREEADDRINFO")
+#else
+#define GETADDRINFO_SYMBOL "getaddrinfo"
+#define FREEADDRINFO_SYMBOL "freeaddrinfo"
+#endif
+
+PRStatus
+_pr_find_getaddrinfo(void)
+{
+ PRLibrary *lib;
+#ifdef WIN32
+ /*
+ * On windows, we need to search ws2_32.dll for getaddrinfo and
+ * freeaddrinfo. This library might not be loaded yet.
+ */
+ lib = PR_LoadLibrary("ws2_32.dll");
+ if (!lib) {
+ return PR_FAILURE;
+ }
+ _pr_getaddrinfo = (FN_GETADDRINFO)
+ PR_FindFunctionSymbol(lib, GETADDRINFO_SYMBOL);
+ _pr_freeaddrinfo = (FN_FREEADDRINFO)
+ PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL);
+ if (!_pr_getaddrinfo || !_pr_freeaddrinfo) {
+ PR_UnloadLibrary(lib);
+ return PR_FAILURE;
+ }
+ /* Keep ws2_32.dll loaded. */
+ return PR_SUCCESS;
+#else
+ /*
+ * Resolve getaddrinfo by searching all loaded libraries. Then
+ * search library containing getaddrinfo for freeaddrinfo.
+ */
+ _pr_getaddrinfo = (FN_GETADDRINFO)
+ PR_FindFunctionSymbolAndLibrary(GETADDRINFO_SYMBOL, &lib);
+ if (!_pr_getaddrinfo) {
+ return PR_FAILURE;
+ }
+ _pr_freeaddrinfo = (FN_FREEADDRINFO)
+ PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL);
+ PR_UnloadLibrary(lib);
+ if (!_pr_freeaddrinfo) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+#endif
+}
+
+#define GETADDRINFO (*_pr_getaddrinfo)
+#define FREEADDRINFO (*_pr_freeaddrinfo)
+
+#endif /* _PR_INET6 */
+
+#endif /* _PR_HAVE_GETADDRINFO */
+
+/*
+ * If getaddrinfo does not exist, then we will fall back on
+ * PR_GetHostByName, which requires that we allocate a buffer for the
+ * PRHostEnt data structure and its members.
+ */
+typedef struct PRAddrInfoFB {
+ char buf[PR_NETDB_BUF_SIZE];
+ PRHostEnt hostent;
+ PRBool has_cname;
+} PRAddrInfoFB;
+
+static PRAddrInfo *
+pr_GetAddrInfoByNameFB(const char *hostname,
+ PRUint16 af,
+ PRIntn flags)
+{
+ PRStatus rv;
+ PRAddrInfoFB *ai;
+ /* fallback on PR_GetHostByName */
+ ai = PR_NEW(PRAddrInfoFB);
+ if (!ai) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ rv = PR_GetHostByName(hostname, ai->buf, sizeof ai->buf, &ai->hostent);
+ if (rv == PR_FAILURE) {
+ PR_Free(ai);
+ return NULL;
+ }
+ ai->has_cname = !(flags & PR_AI_NOCANONNAME);
+
+ return (PRAddrInfo *) ai;
+}
+
+PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByName(const char *hostname,
+ PRUint16 af,
+ PRIntn flags)
+{
+ /* restrict input to supported values */
+ if ((af != PR_AF_INET && af != PR_AF_UNSPEC) ||
+ (flags & ~ PR_AI_NOCANONNAME) != PR_AI_ADDRCONFIG) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+#if !defined(_PR_HAVE_GETADDRINFO)
+ return pr_GetAddrInfoByNameFB(hostname, af, flags);
+#else
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present) {
+ return pr_GetAddrInfoByNameFB(hostname, af, flags);
+ }
+#endif
+ {
+ PRADDRINFO *res, hints;
+ PRStatus rv;
+
+ /*
+ * we assume a RFC 2553 compliant getaddrinfo. this may at some
+ * point need to be customized as platforms begin to adopt the
+ * RFC 3493.
+ */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = (flags & PR_AI_NOCANONNAME) ? 0: AI_CANONNAME;
+ hints.ai_family = (af == PR_AF_INET) ? AF_INET : AF_UNSPEC;
+
+ /*
+ * it is important to select a socket type in the hints, otherwise we
+ * will get back repetitive entries: one for each socket type. since
+ * we do not expose ai_socktype through our API, it is okay to do this
+ * here. the application may still choose to create a socket of some
+ * other type.
+ */
+ hints.ai_socktype = SOCK_STREAM;
+
+ rv = GETADDRINFO(hostname, NULL, &hints, &res);
+ if (rv == 0)
+ return (PRAddrInfo *) res;
+
+ PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv);
+ }
+ return NULL;
+#endif
+}
+
+PR_IMPLEMENT(void) PR_FreeAddrInfo(PRAddrInfo *ai)
+{
+#if defined(_PR_HAVE_GETADDRINFO)
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present)
+ PR_Free((PRAddrInfoFB *) ai);
+ else
+#endif
+ FREEADDRINFO((PRADDRINFO *) ai);
+#else
+ PR_Free((PRAddrInfoFB *) ai);
+#endif
+}
+
+PR_IMPLEMENT(void *) PR_EnumerateAddrInfo(void *iterPtr,
+ const PRAddrInfo *base,
+ PRUint16 port,
+ PRNetAddr *result)
+{
+#if defined(_PR_HAVE_GETADDRINFO)
+ PRADDRINFO *ai;
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present) {
+ /* using PRAddrInfoFB */
+ PRIntn iter = (PRIntn)(uintptr_t)iterPtr;
+ iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result);
+ if (iter < 0)
+ iter = 0;
+ return (void *)(uintptr_t)iter;
+ }
+#endif
+
+ if (iterPtr)
+ ai = ((PRADDRINFO *) iterPtr)->ai_next;
+ else
+ ai = (PRADDRINFO *) base;
+
+ if (ai) {
+ /* copy sockaddr to PRNetAddr */
+ memcpy(result, ai->ai_addr, ai->ai_addrlen);
+ result->raw.family = ai->ai_addr->sa_family;
+ if (ai->ai_addrlen < sizeof(PRNetAddr))
+ memset(((char*)result)+ai->ai_addrlen, 0, sizeof(PRNetAddr) - ai->ai_addrlen);
+
+ if (result->raw.family == PR_AF_INET)
+ result->inet.port = htons(port);
+ else
+ result->ipv6.port = htons(port);
+ }
+
+ return ai;
+#else
+ /* using PRAddrInfoFB */
+ PRIntn iter = (PRIntn) iterPtr;
+ iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result);
+ if (iter < 0)
+ iter = 0;
+ return (void *) iter;
+#endif
+}
+
+PR_IMPLEMENT(const char *) PR_GetCanonNameFromAddrInfo(const PRAddrInfo *ai)
+{
+#if defined(_PR_HAVE_GETADDRINFO)
+#if defined(_PR_INET6_PROBE)
+ if (!_pr_ipv6_is_present) {
+ const PRAddrInfoFB *fb = (const PRAddrInfoFB *) ai;
+ return fb->has_cname ? fb->hostent.h_name : NULL;
+ }
+#endif
+ return ((const PRADDRINFO *) ai)->ai_canonname;
+#else
+ const PRAddrInfoFB *fb = (const PRAddrInfoFB *) ai;
+ return fb->has_cname ? fb->hostent.h_name : NULL;
+#endif
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prolock.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prolock.c
new file mode 100644
index 00000000..f7339bac
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prolock.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prolock.c -- NSPR Ordered Lock
+**
+** Implement the API defined in prolock.h
+**
+*/
+#include "prolock.h"
+#include "prlog.h"
+#include "prerror.h"
+
+PR_IMPLEMENT(PROrderedLock *)
+ PR_CreateOrderedLock(
+ PRInt32 order,
+ const char *name
+)
+{
+#ifdef XP_MAC
+#pragma unused( order, name )
+#endif
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+} /* end PR_CreateOrderedLock() */
+
+
+PR_IMPLEMENT(void)
+ PR_DestroyOrderedLock(
+ PROrderedLock *lock
+)
+{
+#ifdef XP_MAC
+#pragma unused( lock )
+#endif
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+} /* end PR_DestroyOrderedLock() */
+
+
+PR_IMPLEMENT(void)
+ PR_LockOrderedLock(
+ PROrderedLock *lock
+)
+{
+#ifdef XP_MAC
+#pragma unused( lock )
+#endif
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+} /* end PR_LockOrderedLock() */
+
+
+PR_IMPLEMENT(PRStatus)
+ PR_UnlockOrderedLock(
+ PROrderedLock *lock
+)
+{
+#ifdef XP_MAC
+#pragma unused( lock )
+#endif
+ PR_ASSERT(!"Not implemented"); /* Not implemented yet */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+} /* end PR_UnlockOrderedLock() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prrng.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prrng.c
new file mode 100644
index 00000000..6cd7e239
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prrng.c
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/*
+ * We were not including <string.h> in optimized builds. On AIX this
+ * caused libnspr4.so to export memcpy and some binaries linked with
+ * libnspr4.so resolved their memcpy references with libnspr4.so. To
+ * be backward compatible with old libnspr4.so binaries, we do not
+ * include <string.h> in optimized builds for AIX. (bug 200561)
+ */
+#if !(defined(AIX) && !defined(DEBUG))
+#include <string.h>
+#endif
+
+PRSize _pr_CopyLowBits(
+ void *dst,
+ PRSize dstlen,
+ void *src,
+ PRSize srclen )
+{
+ if (srclen <= dstlen) {
+ memcpy(dst, src, srclen);
+ return srclen;
+ }
+#if defined IS_BIG_ENDIAN
+ memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
+#else
+ memcpy(dst, src, dstlen);
+#endif
+ return dstlen;
+}
+
+PR_IMPLEMENT(PRSize) PR_GetRandomNoise(
+ void *buf,
+ PRSize size
+)
+{
+ return( _PR_MD_GET_RANDOM_NOISE( buf, size ));
+} /* end PR_GetRandomNoise() */
+/* end prrng.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prsystem.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prsystem.c
new file mode 100644
index 00000000..4da19ba2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prsystem.c
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include "prsystem.h"
+#include "prprf.h"
+
+#if defined(BEOS)
+#include <kernel/OS.h>
+#endif
+
+#if defined(OS2)
+#define INCL_DOS
+#include <os2.h>
+/* define the required constant if it is not already defined in the headers */
+#ifndef QSV_NUMPROCESSORS
+#define QSV_NUMPROCESSORS 26
+#endif
+#endif
+
+/* BSD-derived systems use sysctl() to get the number of processors */
+#if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \
+ || defined(OPENBSD) || defined(DARWIN)
+#define _PR_HAVE_SYSCTL
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#endif
+
+#if defined(HPUX)
+#include <sys/mpctl.h>
+#endif
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#include <sys/utsname.h>
+#endif
+
+PR_IMPLEMENT(char) PR_GetDirectorySeparator(void)
+{
+ return PR_DIRECTORY_SEPARATOR;
+} /* PR_GetDirectorySeparator */
+
+/*
+** OBSOLETE -- the function name is misspelled.
+*/
+PR_IMPLEMENT(char) PR_GetDirectorySepartor(void)
+{
+#if defined(DEBUG)
+ static PRBool warn = PR_TRUE;
+ if (warn) {
+ warn = _PR_Obsolete("PR_GetDirectorySepartor()",
+ "PR_GetDirectorySeparator()");
+ }
+#endif
+ return PR_GetDirectorySeparator();
+} /* PR_GetDirectorySepartor */
+
+PR_IMPLEMENT(char) PR_GetPathSeparator(void)
+{
+ return PR_PATH_SEPARATOR;
+} /* PR_GetPathSeparator */
+
+PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen)
+{
+ PRUintn len = 0;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ switch(cmd)
+ {
+ case PR_SI_HOSTNAME:
+ if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen))
+ return PR_FAILURE;
+ /*
+ * On some platforms a system does not have a hostname and
+ * its IP address is returned instead. The following code
+ * should be skipped on those platforms.
+ */
+#ifndef _PR_GET_HOST_ADDR_AS_NAME
+ /* Return the unqualified hostname */
+ while ((len < buflen) && buf[len]) {
+ if (buf[len] == '.') {
+ buf[len] = '\0';
+ break;
+ }
+ len += 1;
+ }
+#endif
+ break;
+
+ case PR_SI_SYSNAME:
+ /* Return the operating system name */
+#if defined(XP_UNIX) || defined(WIN32)
+ if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
+ return PR_FAILURE;
+#else
+ (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME);
+#endif
+ break;
+
+ case PR_SI_RELEASE:
+ /* Return the version of the operating system */
+#if defined(XP_UNIX) || defined(WIN32)
+ if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen))
+ return PR_FAILURE;
+#endif
+#if defined(XP_OS2)
+ {
+ ULONG os2ver[2] = {0};
+ DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION,
+ &os2ver, sizeof(os2ver));
+ /* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially,
+ Warp 4 is version 2.40.00, WSeB 2.45.00 */
+ if (os2ver[0] < 30)
+ (void)PR_snprintf(buf, buflen, "%s%lu",
+ "2.", os2ver[0]);
+ else if (os2ver[0] < 45)
+ (void)PR_snprintf(buf, buflen, "%lu%s%lu",
+ os2ver[0]/10, ".", os2ver[1]);
+ else
+ (void)PR_snprintf(buf, buflen, "%.1f",
+ os2ver[0]/10.0);
+ }
+#endif /* OS2 */
+ break;
+
+ case PR_SI_ARCHITECTURE:
+ /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/
+ (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE);
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+/*
+** PR_GetNumberOfProcessors()
+**
+** Implementation notes:
+** Every platform does it a bit different.
+** numCpus is the returned value.
+** for each platform's "if defined" section
+** declare your local variable
+** do your thing, assign to numCpus
+** order of the if defined()s may be important,
+** especially for unix variants. Do platform
+** specific implementations before XP_UNIX.
+**
+*/
+PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void )
+{
+ PRInt32 numCpus;
+#if defined(WIN32)
+ SYSTEM_INFO info;
+
+ GetSystemInfo( &info );
+ numCpus = info.dwNumberOfProcessors;
+#elif defined(XP_MAC)
+/* Hard-code the number of processors to 1 on the Mac
+** MacOS/9 will always be 1. The MPProcessors() call is for
+** MacOS/X, when issued. Leave it commented out for now. */
+/* numCpus = MPProcessors(); */
+ numCpus = 1;
+#elif defined(BEOS)
+ system_info sysInfo;
+
+ get_system_info(&sysInfo);
+ numCpus = sysInfo.cpu_count;
+#elif defined(OS2)
+ DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus));
+#elif defined(_PR_HAVE_SYSCTL)
+ int mib[2];
+ int rc;
+ size_t len = sizeof(numCpus);
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 );
+ if ( -1 == rc ) {
+ numCpus = -1; /* set to -1 for return value on error */
+ _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
+ }
+#elif defined(HPUX)
+ numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 );
+ if ( numCpus < 1 ) {
+ numCpus = -1; /* set to -1 for return value on error */
+ _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() );
+ }
+#elif defined(IRIX)
+ numCpus = sysconf( _SC_NPROC_ONLN );
+#elif defined(XP_UNIX)
+ numCpus = sysconf( _SC_NPROCESSORS_ONLN );
+#else
+#error "An implementation is required"
+#endif
+ return(numCpus);
+} /* end PR_GetNumberOfProcessors() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prthinfo.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prthinfo.c
new file mode 100644
index 00000000..25cbd185
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prthinfo.c
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prlog.h"
+#include "prthread.h"
+#ifdef XP_MAC
+#include "pprthred.h"
+#else
+#include "private/pprthred.h"
+#endif
+#include "primpl.h"
+
+PR_IMPLEMENT(PRWord *)
+PR_GetGCRegisters(PRThread *t, int isCurrent, int *np)
+{
+ return _MD_HomeGCRegisters(t, isCurrent, np);
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_ThreadScanStackPointers(PRThread* t,
+ PRScanStackFun scanFun, void* scanClosure)
+{
+ PRThread* current = PR_GetCurrentThread();
+ PRWord *sp, *esp, *p0;
+ int n;
+ void **ptd;
+ PRStatus status;
+ PRUint32 index;
+ int stack_end;
+
+ /*
+ ** Store the thread's registers in the thread structure so the GC
+ ** can scan them. Then scan them.
+ */
+ p0 = _MD_HomeGCRegisters(t, t == current, &n);
+ status = scanFun(t, (void**)p0, n, scanClosure);
+ if (status != PR_SUCCESS)
+ return status;
+
+ /* Scan the C stack for pointers into the GC heap */
+#if defined(XP_PC) && defined(WIN16)
+ /*
+ ** Under WIN16, the stack of the current thread is always mapped into
+ ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan
+ ** the "task stack". Otherwise, scan the "cached stack" of the inactive
+ ** thread...
+ */
+ if (t == current) {
+ sp = (PRWord*) &stack_end;
+ esp = (PRWord*) _pr_top_of_task_stack;
+
+ PR_ASSERT(sp <= esp);
+ } else {
+ sp = (PRWord*) PR_GetSP(t);
+ esp = (PRWord*) t->stack->stackTop;
+
+ PR_ASSERT((t->stack->stackSize == 0) ||
+ ((sp > (PRWord*)t->stack->stackBottom) &&
+ (sp <= (PRWord*)t->stack->stackTop)));
+ }
+#else /* ! WIN16 */
+#ifdef HAVE_STACK_GROWING_UP
+ if (t == current) {
+ esp = (PRWord*) &stack_end;
+ } else {
+ esp = (PRWord*) PR_GetSP(t);
+ }
+ sp = (PRWord*) t->stack->stackTop;
+ if (t->stack->stackSize) {
+ PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
+ (esp < (PRWord*)t->stack->stackBottom));
+ }
+#else /* ! HAVE_STACK_GROWING_UP */
+ if (t == current) {
+ sp = (PRWord*) &stack_end;
+ } else {
+ sp = (PRWord*) PR_GetSP(t);
+ }
+ esp = (PRWord*) t->stack->stackTop;
+ if (t->stack->stackSize) {
+ PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
+ (sp < (PRWord*)t->stack->stackTop));
+ }
+#endif /* ! HAVE_STACK_GROWING_UP */
+#endif /* ! WIN16 */
+
+#if defined(WIN16)
+ {
+ prword_t scan;
+ prword_t limit;
+
+ scan = (prword_t) sp;
+ limit = (prword_t) esp;
+ while (scan < limit) {
+ prword_t *test;
+
+ test = *((prword_t **)scan);
+ status = scanFun(t, (void**)&test, 1, scanClosure);
+ if (status != PR_SUCCESS)
+ return status;
+ scan += sizeof(char);
+ }
+ }
+#else
+ if (sp < esp) {
+ status = scanFun(t, (void**)sp, esp - sp, scanClosure);
+ if (status != PR_SUCCESS)
+ return status;
+ }
+#endif
+
+ /*
+ ** Mark all of the per-thread-data items attached to this thread
+ **
+ ** The execution environment better be accounted for otherwise it
+ ** will be collected
+ */
+ status = scanFun(t, (void**)&t->environment, 1, scanClosure);
+ if (status != PR_SUCCESS)
+ return status;
+
+#ifndef GC_LEAK_DETECTOR
+ /* if thread is not allocated on stack, this is redundant. */
+ ptd = t->privateData;
+ for (index = 0; index < t->tpdLength; index++, ptd++) {
+ status = scanFun(t, (void**)ptd, 1, scanClosure);
+ if (status != PR_SUCCESS)
+ return status;
+ }
+#endif
+
+ return PR_SUCCESS;
+}
+
+/* transducer for PR_EnumerateThreads */
+typedef struct PRScanStackData {
+ PRScanStackFun scanFun;
+ void* scanClosure;
+} PRScanStackData;
+
+static PRStatus PR_CALLBACK
+pr_ScanStack(PRThread* t, int i, void* arg)
+{
+#if defined(XP_MAC)
+#pragma unused (i)
+#endif
+ PRScanStackData* data = (PRScanStackData*)arg;
+ return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure);
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure)
+{
+ PRScanStackData data;
+ data.scanFun = scanFun;
+ data.scanClosure = scanClosure;
+ return PR_EnumerateThreads(pr_ScanStack, &data);
+}
+
+PR_IMPLEMENT(PRUword)
+PR_GetStackSpaceLeft(PRThread* t)
+{
+ PRThread *current = PR_CurrentThread();
+ PRWord *sp, *esp;
+ int stack_end;
+
+#if defined(WIN16)
+ /*
+ ** Under WIN16, the stack of the current thread is always mapped into
+ ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan
+ ** the "task stack". Otherwise, scan the "cached stack" of the inactive
+ ** thread...
+ */
+ if (t == current) {
+ sp = (PRWord*) &stack_end;
+ esp = (PRWord*) _pr_top_of_task_stack;
+
+ PR_ASSERT(sp <= esp);
+ } else {
+ sp = (PRWord*) PR_GetSP(t);
+ esp = (PRWord*) t->stack->stackTop;
+
+ PR_ASSERT((t->stack->stackSize == 0) ||
+ ((sp > (PRWord*)t->stack->stackBottom) &&
+ (sp <= (PRWord*)t->stack->stackTop)));
+ }
+#else /* ! WIN16 */
+#ifdef HAVE_STACK_GROWING_UP
+ if (t == current) {
+ esp = (PRWord*) &stack_end;
+ } else {
+ esp = (PRWord*) PR_GetSP(t);
+ }
+ sp = (PRWord*) t->stack->stackTop;
+ if (t->stack->stackSize) {
+ PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
+ (esp < (PRWord*)t->stack->stackBottom));
+ }
+#else /* ! HAVE_STACK_GROWING_UP */
+ if (t == current) {
+ sp = (PRWord*) &stack_end;
+ } else {
+ sp = (PRWord*) PR_GetSP(t);
+ }
+ esp = (PRWord*) t->stack->stackTop;
+ if (t->stack->stackSize) {
+ PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
+ (sp < (PRWord*)t->stack->stackTop));
+ }
+#endif /* ! HAVE_STACK_GROWING_UP */
+#endif /* ! WIN16 */
+ return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtime.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtime.c
new file mode 100644
index 00000000..0a2892e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtime.c
@@ -0,0 +1,1973 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * prtime.c --
+ *
+ * NSPR date and time functions
+ *
+ */
+
+#include "prinit.h"
+#include "prtime.h"
+#include "prlock.h"
+#include "prprf.h"
+#include "prlog.h"
+
+#include <string.h>
+#include <ctype.h>
+
+#ifdef XP_MAC
+#include <time.h>
+#endif
+
+
+
+
+/*
+ * Static variables used by functions in this file
+ */
+
+/*
+ * The following array contains the day of year for the last day of
+ * each month, where index 1 is January, and day 0 is January 1.
+ */
+
+static const int lastDayOfMonth[2][13] = {
+ {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
+ {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}
+};
+
+/*
+ * The number of days in a month
+ */
+
+static const PRInt8 nDays[2][12] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+/*
+ * Declarations for internal functions defined later in this file.
+ */
+
+static void ComputeGMT(PRTime time, PRExplodedTime *gmt);
+static int IsLeapYear(PRInt16 year);
+static void ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset);
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * ComputeGMT --
+ *
+ * Caveats:
+ * - we ignore leap seconds
+ * - our leap-year calculation is only correct for years 1901-2099
+ *
+ *------------------------------------------------------------------------
+ */
+
+static void
+ComputeGMT(PRTime time, PRExplodedTime *gmt)
+{
+ PRInt32 tmp, rem;
+ PRInt32 numDays;
+ PRInt64 numDays64, rem64;
+ int isLeap;
+ PRInt64 sec;
+ PRInt64 usec;
+ PRInt64 usecPerSec;
+ PRInt64 secPerDay;
+
+ /*
+ * We first do the usec, sec, min, hour thing so that we do not
+ * have to do LL arithmetic.
+ */
+
+ LL_I2L(usecPerSec, 1000000L);
+ LL_DIV(sec, time, usecPerSec);
+ LL_MOD(usec, time, usecPerSec);
+ LL_L2I(gmt->tm_usec, usec);
+ /* Correct for weird mod semantics so the remainder is always positive */
+ if (gmt->tm_usec < 0) {
+ PRInt64 one;
+
+ LL_I2L(one, 1L);
+ LL_SUB(sec, sec, one);
+ gmt->tm_usec += 1000000L;
+ }
+
+ LL_I2L(secPerDay, 86400L);
+ LL_DIV(numDays64, sec, secPerDay);
+ LL_MOD(rem64, sec, secPerDay);
+ /* We are sure both of these numbers can fit into PRInt32 */
+ LL_L2I(numDays, numDays64);
+ LL_L2I(rem, rem64);
+ if (rem < 0) {
+ numDays--;
+ rem += 86400L;
+ }
+
+ /* Compute day of week. Epoch started on a Thursday. */
+
+ gmt->tm_wday = (numDays + 4) % 7;
+ if (gmt->tm_wday < 0) {
+ gmt->tm_wday += 7;
+ }
+
+ /* Compute the time of day. */
+
+ gmt->tm_hour = rem / 3600;
+ rem %= 3600;
+ gmt->tm_min = rem / 60;
+ gmt->tm_sec = rem % 60;
+
+ /* Compute the four-year span containing the specified time */
+
+ tmp = numDays / (4 * 365 + 1);
+ rem = numDays % (4 * 365 + 1);
+
+ if (rem < 0) {
+ tmp--;
+ rem += (4 * 365 + 1);
+ }
+
+ /*
+ * Compute the year after 1900 by taking the four-year span and
+ * adjusting for the remainder. This works because 2000 is a
+ * leap year, and 1900 and 2100 are out of the range.
+ */
+
+ tmp = (tmp * 4) + 1970;
+ isLeap = 0;
+
+ /*
+ * 1970 has 365 days
+ * 1971 has 365 days
+ * 1972 has 366 days (leap year)
+ * 1973 has 365 days
+ */
+
+ if (rem >= 365) { /* 1971, etc. */
+ tmp++;
+ rem -= 365;
+ if (rem >= 365) { /* 1972, etc. */
+ tmp++;
+ rem -= 365;
+ if (rem >= 366) { /* 1973, etc. */
+ tmp++;
+ rem -= 366;
+ } else {
+ isLeap = 1;
+ }
+ }
+ }
+
+ gmt->tm_year = tmp;
+ gmt->tm_yday = rem;
+
+ /* Compute the month and day of month. */
+
+ for (tmp = 1; lastDayOfMonth[isLeap][tmp] < gmt->tm_yday; tmp++) {
+ }
+ gmt->tm_month = --tmp;
+ gmt->tm_mday = gmt->tm_yday - lastDayOfMonth[isLeap][tmp];
+
+ gmt->tm_params.tp_gmt_offset = 0;
+ gmt->tm_params.tp_dst_offset = 0;
+}
+
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PR_ExplodeTime --
+ *
+ * Cf. struct tm *gmtime(const time_t *tp) and
+ * struct tm *localtime(const time_t *tp)
+ *
+ *------------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(void)
+PR_ExplodeTime(
+ PRTime usecs,
+ PRTimeParamFn params,
+ PRExplodedTime *exploded)
+{
+ ComputeGMT(usecs, exploded);
+ exploded->tm_params = params(exploded);
+ ApplySecOffset(exploded, exploded->tm_params.tp_gmt_offset
+ + exploded->tm_params.tp_dst_offset);
+}
+
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PR_ImplodeTime --
+ *
+ * Cf. time_t mktime(struct tm *tp)
+ * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough.
+ *
+ *------------------------------------------------------------------------
+ */
+#if defined(HAVE_WATCOM_BUG_2)
+PRTime __pascal __export __loadds
+#else
+PR_IMPLEMENT(PRTime)
+#endif
+PR_ImplodeTime(const PRExplodedTime *exploded)
+{
+ PRExplodedTime copy;
+ PRTime retVal;
+ PRInt64 secPerDay, usecPerSec;
+ PRInt64 temp;
+ PRInt64 numSecs64;
+ PRInt32 fourYears;
+ PRInt32 remainder;
+ PRInt32 numDays;
+ PRInt32 numSecs;
+
+ /* Normalize first. Do this on our copy */
+ copy = *exploded;
+ PR_NormalizeTime(&copy, PR_GMTParameters);
+
+ fourYears = (copy.tm_year - 1970) / 4;
+ remainder = (copy.tm_year - 1970) % 4;
+ if (remainder < 0) {
+ remainder += 4;
+ fourYears--;
+ }
+ numDays = fourYears * (4 * 365 + 1);
+ switch (remainder) {
+ case 0:
+ break;
+ case 1: /* 1970 */
+ numDays += 365;
+ break;
+ case 2: /* 1970-1 */
+ numDays += 365 * 2;
+ break;
+ case 3: /* 1970-2 */
+ numDays += 365 * 3 + 1;
+ break;
+ }
+
+ numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600
+ + copy.tm_min * 60 + copy.tm_sec;
+
+ LL_I2L(temp, numDays);
+ LL_I2L(secPerDay, 86400);
+ LL_MUL(temp, temp, secPerDay);
+ LL_I2L(numSecs64, numSecs);
+ LL_ADD(numSecs64, numSecs64, temp);
+
+ /* apply the GMT and DST offsets */
+ LL_I2L(temp, copy.tm_params.tp_gmt_offset);
+ LL_SUB(numSecs64, numSecs64, temp);
+ LL_I2L(temp, copy.tm_params.tp_dst_offset);
+ LL_SUB(numSecs64, numSecs64, temp);
+
+ LL_I2L(usecPerSec, 1000000L);
+ LL_MUL(temp, numSecs64, usecPerSec);
+ LL_I2L(retVal, copy.tm_usec);
+ LL_ADD(retVal, retVal, temp);
+
+ return retVal;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * IsLeapYear --
+ *
+ * Returns 1 if the year is a leap year, 0 otherwise.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static int IsLeapYear(PRInt16 year)
+{
+ if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * 'secOffset' should be less than 86400 (i.e., a day).
+ * 'time' should point to a normalized PRExplodedTime.
+ */
+
+static void
+ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset)
+{
+ time->tm_sec += secOffset;
+
+ /* Note that in this implementation we do not count leap seconds */
+ if (time->tm_sec < 0 || time->tm_sec >= 60) {
+ time->tm_min += time->tm_sec / 60;
+ time->tm_sec %= 60;
+ if (time->tm_sec < 0) {
+ time->tm_sec += 60;
+ time->tm_min--;
+ }
+ }
+
+ if (time->tm_min < 0 || time->tm_min >= 60) {
+ time->tm_hour += time->tm_min / 60;
+ time->tm_min %= 60;
+ if (time->tm_min < 0) {
+ time->tm_min += 60;
+ time->tm_hour--;
+ }
+ }
+
+ if (time->tm_hour < 0) {
+ /* Decrement mday, yday, and wday */
+ time->tm_hour += 24;
+ time->tm_mday--;
+ time->tm_yday--;
+ if (time->tm_mday < 1) {
+ time->tm_month--;
+ if (time->tm_month < 0) {
+ time->tm_month = 11;
+ time->tm_year--;
+ if (IsLeapYear(time->tm_year))
+ time->tm_yday = 365;
+ else
+ time->tm_yday = 364;
+ }
+ time->tm_mday = nDays[IsLeapYear(time->tm_year)][time->tm_month];
+ }
+ time->tm_wday--;
+ if (time->tm_wday < 0)
+ time->tm_wday = 6;
+ } else if (time->tm_hour > 23) {
+ /* Increment mday, yday, and wday */
+ time->tm_hour -= 24;
+ time->tm_mday++;
+ time->tm_yday++;
+ if (time->tm_mday >
+ nDays[IsLeapYear(time->tm_year)][time->tm_month]) {
+ time->tm_mday = 1;
+ time->tm_month++;
+ if (time->tm_month > 11) {
+ time->tm_month = 0;
+ time->tm_year++;
+ time->tm_yday = 0;
+ }
+ }
+ time->tm_wday++;
+ if (time->tm_wday > 6)
+ time->tm_wday = 0;
+ }
+}
+
+PR_IMPLEMENT(void)
+PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params)
+{
+ int daysInMonth;
+ PRInt32 fourYears;
+ PRInt32 remainder;
+ PRInt32 numDays;
+
+ /* Get back to GMT */
+ time->tm_sec -= time->tm_params.tp_gmt_offset
+ + time->tm_params.tp_dst_offset;
+ time->tm_params.tp_gmt_offset = 0;
+ time->tm_params.tp_dst_offset = 0;
+
+ /* Now normalize GMT */
+
+ if (time->tm_usec < 0 || time->tm_usec >= 1000000) {
+ time->tm_sec += time->tm_usec / 1000000;
+ time->tm_usec %= 1000000;
+ if (time->tm_usec < 0) {
+ time->tm_usec += 1000000;
+ time->tm_sec--;
+ }
+ }
+
+ /* Note that we do not count leap seconds in this implementation */
+ if (time->tm_sec < 0 || time->tm_sec >= 60) {
+ time->tm_min += time->tm_sec / 60;
+ time->tm_sec %= 60;
+ if (time->tm_sec < 0) {
+ time->tm_sec += 60;
+ time->tm_min--;
+ }
+ }
+
+ if (time->tm_min < 0 || time->tm_min >= 60) {
+ time->tm_hour += time->tm_min / 60;
+ time->tm_min %= 60;
+ if (time->tm_min < 0) {
+ time->tm_min += 60;
+ time->tm_hour--;
+ }
+ }
+
+ if (time->tm_hour < 0 || time->tm_hour >= 24) {
+ time->tm_mday += time->tm_hour / 24;
+ time->tm_hour %= 24;
+ if (time->tm_hour < 0) {
+ time->tm_hour += 24;
+ time->tm_mday--;
+ }
+ }
+
+ /* Normalize month and year before mday */
+ if (time->tm_month < 0 || time->tm_month >= 12) {
+ time->tm_year += time->tm_month / 12;
+ time->tm_month %= 12;
+ if (time->tm_month < 0) {
+ time->tm_month += 12;
+ time->tm_year--;
+ }
+ }
+
+ /* Now that month and year are in proper range, normalize mday */
+
+ if (time->tm_mday < 1) {
+ /* mday too small */
+ do {
+ /* the previous month */
+ time->tm_month--;
+ if (time->tm_month < 0) {
+ time->tm_month = 11;
+ time->tm_year--;
+ }
+ time->tm_mday += nDays[IsLeapYear(time->tm_year)][time->tm_month];
+ } while (time->tm_mday < 1);
+ } else {
+ daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month];
+ while (time->tm_mday > daysInMonth) {
+ /* mday too large */
+ time->tm_mday -= daysInMonth;
+ time->tm_month++;
+ if (time->tm_month > 11) {
+ time->tm_month = 0;
+ time->tm_year++;
+ }
+ daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month];
+ }
+ }
+
+ /* Recompute yday and wday */
+ time->tm_yday = time->tm_mday +
+ lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month];
+ fourYears = (time->tm_year - 1970) / 4;
+ remainder = (time->tm_year - 1970) % 4;
+ if (remainder < 0) {
+ remainder += 4;
+ fourYears--;
+ }
+ numDays = fourYears * (4 * 365 + 1);
+ switch (remainder) {
+ case 0:
+ break;
+ case 1:
+ numDays += 365; /* 1970 */
+ break;
+ case 2:
+ numDays += 365 + 365; /* 1970 and 1971 */
+ break;
+ case 3:
+ numDays += 365 + 365 + 366; /* 1970-2 */
+ }
+ numDays += time->tm_yday;
+ time->tm_wday = (numDays + 4) % 7;
+ if (time->tm_wday < 0) {
+ time->tm_wday += 7;
+ }
+
+ /* Recompute time parameters */
+
+ time->tm_params = params(time);
+
+ ApplySecOffset(time, time->tm_params.tp_gmt_offset
+ + time->tm_params.tp_dst_offset);
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * PR_LocalTimeParameters --
+ *
+ * returns the time parameters for the local time zone
+ *
+ * The following uses localtime() from the standard C library.
+ * (time.h) This is our fallback implementation. Unix and PC
+ * use this version. Mac has its own machine-dependent
+ * implementation of this function.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include <time.h>
+
+#if defined(HAVE_INT_LOCALTIME_R)
+
+/*
+ * In this case we could define the macro as
+ * #define MT_safe_localtime(timer, result) \
+ * (localtime_r(timer, result) == 0 ? result : NULL)
+ * I chose to compare the return value of localtime_r with -1 so
+ * that I can catch the cases where localtime_r returns a pointer
+ * to struct tm. The macro definition above would not be able to
+ * detect such mistakes because it is legal to compare a pointer
+ * with 0.
+ */
+
+#define MT_safe_localtime(timer, result) \
+ (localtime_r(timer, result) == -1 ? NULL: result)
+
+#elif defined(HAVE_POINTER_LOCALTIME_R)
+
+#define MT_safe_localtime localtime_r
+
+#else
+
+#if defined(XP_MAC)
+extern struct tm *Maclocaltime(const time_t * t);
+#endif
+
+static PRLock *monitor = NULL;
+
+static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result)
+{
+ struct tm *tmPtr;
+ int needLock = PR_Initialized(); /* We need to use a lock to protect
+ * against NSPR threads only when the
+ * NSPR thread system is activated. */
+
+ if (needLock) {
+ if (monitor == NULL) {
+ monitor = PR_NewLock();
+ }
+ PR_Lock(monitor);
+ }
+
+ /*
+ * Microsoft (all flavors) localtime() returns a NULL pointer if 'clock'
+ * represents a time before midnight January 1, 1970. In
+ * that case, we also return a NULL pointer and the struct tm
+ * object pointed to by 'result' is not modified.
+ *
+ * Watcom C/C++ 11.0 localtime() treats time_t as unsigned long
+ * hence, does not recognize negative values of clock as pre-1/1/70.
+ * We have to manually check (WIN16 only) for negative value of
+ * clock and return NULL.
+ *
+ * With negative values of clock, emx returns the struct tm for
+ * clock plus ULONG_MAX. So we also have to check for the invalid
+ * structs returned for timezones west of Greenwich when clock == 0.
+ */
+
+#if defined(XP_MAC)
+ tmPtr = Maclocaltime(clock);
+#else
+ tmPtr = localtime(clock);
+#endif
+
+#if defined(WIN16) || defined(XP_OS2_EMX)
+ if ( (PRInt32) *clock < 0 ||
+ ( (PRInt32) *clock == 0 && tmPtr->tm_year != 70))
+ result = NULL;
+ else
+ *result = *tmPtr;
+#else
+ if (tmPtr) {
+ *result = *tmPtr;
+ } else {
+ result = NULL;
+ }
+#endif /* WIN16 */
+
+ if (needLock) PR_Unlock(monitor);
+
+ return result;
+}
+
+#endif /* definition of MT_safe_localtime() */
+
+#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)
+
+PR_IMPLEMENT(PRTimeParameters)
+PR_LocalTimeParameters(const PRExplodedTime *gmt)
+{
+
+ PRTimeParameters retVal;
+ struct tm localTime;
+ time_t secs;
+ PRTime secs64;
+ PRInt64 usecPerSec;
+ PRInt64 maxInt32;
+ PRInt64 minInt32;
+ PRInt32 dayOffset;
+ PRInt32 offset2Jan1970;
+ PRInt32 offsetNew;
+ int isdst2Jan1970;
+
+ /*
+ * Calculate the GMT offset. First, figure out what is
+ * 00:00:00 Jan. 2, 1970 GMT (which is exactly a day, or 86400
+ * seconds, since the epoch) in local time. Then we calculate
+ * the difference between local time and GMT in seconds:
+ * gmt_offset = local_time - GMT
+ *
+ * Caveat: the validity of this calculation depends on two
+ * assumptions:
+ * 1. Daylight saving time was not in effect on Jan. 2, 1970.
+ * 2. The time zone of the geographic location has not changed
+ * since Jan. 2, 1970.
+ */
+
+ secs = 86400L;
+ (void) MT_safe_localtime(&secs, &localTime);
+
+ /* GMT is 00:00:00, 2nd of Jan. */
+
+ offset2Jan1970 = (PRInt32)localTime.tm_sec
+ + 60L * (PRInt32)localTime.tm_min
+ + 3600L * (PRInt32)localTime.tm_hour
+ + 86400L * (PRInt32)((PRInt32)localTime.tm_mday - 2L);
+
+ isdst2Jan1970 = localTime.tm_isdst;
+
+ /*
+ * Now compute DST offset. We calculate the overall offset
+ * of local time from GMT, similar to above. The overall
+ * offset has two components: gmt offset and dst offset.
+ * We subtract gmt offset from the overall offset to get
+ * the dst offset.
+ * overall_offset = local_time - GMT
+ * overall_offset = gmt_offset + dst_offset
+ * ==> dst_offset = local_time - GMT - gmt_offset
+ */
+
+ secs64 = PR_ImplodeTime(gmt); /* This is still in microseconds */
+ LL_I2L(usecPerSec, PR_USEC_PER_SEC);
+ LL_DIV(secs64, secs64, usecPerSec); /* Convert to seconds */
+ LL_I2L(maxInt32, PR_INT32_MAX);
+ LL_I2L(minInt32, PR_INT32_MIN);
+ if (LL_CMP(secs64, >, maxInt32) || LL_CMP(secs64, <, minInt32)) {
+ /* secs64 is too large or too small for time_t (32-bit integer) */
+ retVal.tp_gmt_offset = offset2Jan1970;
+ retVal.tp_dst_offset = 0;
+ return retVal;
+ }
+ LL_L2I(secs, secs64);
+
+ /*
+ * On Windows, localtime() (and our MT_safe_localtime() too)
+ * returns a NULL pointer for time before midnight January 1,
+ * 1970 GMT. In that case, we just use the GMT offset for
+ * Jan 2, 1970 and assume that DST was not in effect.
+ */
+
+ if (MT_safe_localtime(&secs, &localTime) == NULL) {
+ retVal.tp_gmt_offset = offset2Jan1970;
+ retVal.tp_dst_offset = 0;
+ return retVal;
+ }
+
+ /*
+ * dayOffset is the offset between local time and GMT in
+ * the day component, which can only be -1, 0, or 1. We
+ * use the day of the week to compute dayOffset.
+ */
+
+ dayOffset = (PRInt32) localTime.tm_wday - gmt->tm_wday;
+
+ /*
+ * Need to adjust for wrapping around of day of the week from
+ * 6 back to 0.
+ */
+
+ if (dayOffset == -6) {
+ /* Local time is Sunday (0) and GMT is Saturday (6) */
+ dayOffset = 1;
+ } else if (dayOffset == 6) {
+ /* Local time is Saturday (6) and GMT is Sunday (0) */
+ dayOffset = -1;
+ }
+
+ offsetNew = (PRInt32)localTime.tm_sec - gmt->tm_sec
+ + 60L * ((PRInt32)localTime.tm_min - gmt->tm_min)
+ + 3600L * ((PRInt32)localTime.tm_hour - gmt->tm_hour)
+ + 86400L * (PRInt32)dayOffset;
+
+ if (localTime.tm_isdst <= 0) {
+ /* DST is not in effect */
+ retVal.tp_gmt_offset = offsetNew;
+ retVal.tp_dst_offset = 0;
+ } else {
+ /* DST is in effect */
+ if (isdst2Jan1970 <=0) {
+ /*
+ * DST was not in effect back in 2 Jan. 1970.
+ * Use the offset back then as the GMT offset,
+ * assuming the time zone has not changed since then.
+ */
+ retVal.tp_gmt_offset = offset2Jan1970;
+ retVal.tp_dst_offset = offsetNew - offset2Jan1970;
+ } else {
+ /*
+ * DST was also in effect back in 2 Jan. 1970.
+ * Then our clever trick (or rather, ugly hack) fails.
+ * We will just assume DST offset is an hour.
+ */
+ retVal.tp_gmt_offset = offsetNew - 3600;
+ retVal.tp_dst_offset = 3600;
+ }
+ }
+
+ return retVal;
+}
+
+#endif /* defined(XP_UNIX) !! defined(XP_PC) */
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PR_USPacificTimeParameters --
+ *
+ * The time parameters function for the US Pacific Time Zone.
+ *
+ *------------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTimeParameters)
+PR_USPacificTimeParameters(const PRExplodedTime *gmt)
+{
+ PRTimeParameters retVal;
+ PRExplodedTime st;
+
+ /*
+ * Based on geographic location and GMT, figure out offset of
+ * standard time from GMT. In this example implementation, we
+ * assume the local time zone is US Pacific Time.
+ */
+
+ retVal.tp_gmt_offset = -8L * 3600L;
+
+ /*
+ * Make a copy of GMT. Note that the tm_params field of this copy
+ * is ignored.
+ */
+
+ st.tm_usec = gmt->tm_usec;
+ st.tm_sec = gmt->tm_sec;
+ st.tm_min = gmt->tm_min;
+ st.tm_hour = gmt->tm_hour;
+ st.tm_mday = gmt->tm_mday;
+ st.tm_month = gmt->tm_month;
+ st.tm_year = gmt->tm_year;
+ st.tm_wday = gmt->tm_wday;
+ st.tm_yday = gmt->tm_yday;
+
+ /* Apply the offset to GMT to obtain the local standard time */
+ ApplySecOffset(&st, retVal.tp_gmt_offset);
+
+ /*
+ * Apply the rules on standard time or GMT to obtain daylight saving
+ * time offset. In this implementation, we use the US DST rule.
+ */
+ if (st.tm_month < 3) {
+ retVal.tp_dst_offset = 0L;
+ } else if (st.tm_month == 3) {
+ if (st.tm_wday == 0) {
+ /* A Sunday */
+ if (st.tm_mday <= 7) {
+ /* First Sunday */
+ /* 01:59:59 PST -> 03:00:00 PDT */
+ if (st.tm_hour < 2) {
+ retVal.tp_dst_offset = 0L;
+ } else {
+ retVal.tp_dst_offset = 3600L;
+ }
+ } else {
+ /* Not first Sunday */
+ retVal.tp_dst_offset = 3600L;
+ }
+ } else {
+ /* Not a Sunday. See if before first Sunday or after */
+ if (st.tm_wday + 1 <= st.tm_mday) {
+ /* After first Sunday */
+ retVal.tp_dst_offset = 3600L;
+ } else {
+ /* Before first Sunday */
+ retVal.tp_dst_offset = 0L;
+ }
+ }
+ } else if (st.tm_month < 9) {
+ retVal.tp_dst_offset = 3600L;
+ } else if (st.tm_month == 9) {
+ if (st.tm_wday == 0) {
+ if (31 - st.tm_mday < 7) {
+ /* Last Sunday */
+ /* 01:59:59 PDT -> 01:00:00 PST */
+ if (st.tm_hour < 1) {
+ retVal.tp_dst_offset = 3600L;
+ } else {
+ retVal.tp_dst_offset = 0L;
+ }
+ } else {
+ /* Not last Sunday */
+ retVal.tp_dst_offset = 3600L;
+ }
+ } else {
+ /* See if before or after last Sunday */
+ if (7 - st.tm_wday <= 31 - st.tm_mday) {
+ /* before last Sunday */
+ retVal.tp_dst_offset = 3600L;
+ } else {
+ retVal.tp_dst_offset = 0L;
+ }
+ }
+ } else {
+ retVal.tp_dst_offset = 0L;
+ }
+ return retVal;
+}
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * PR_GMTParameters --
+ *
+ * Returns the PRTimeParameters for Greenwich Mean Time.
+ * Trivially, both the tp_gmt_offset and tp_dst_offset fields are 0.
+ *
+ *------------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTimeParameters)
+PR_GMTParameters(const PRExplodedTime *gmt)
+{
+#if defined(XP_MAC)
+#pragma unused (gmt)
+#endif
+
+ PRTimeParameters retVal = { 0, 0 };
+ return retVal;
+}
+
+/*
+ * The following code implements PR_ParseTimeString(). It is based on
+ * ns/lib/xp/xp_time.c, revision 1.25, by Jamie Zawinski <jwz@netscape.com>.
+ */
+
+/*
+ * We only recognize the abbreviations of a small subset of time zones
+ * in North America, Europe, and Japan.
+ *
+ * PST/PDT: Pacific Standard/Daylight Time
+ * MST/MDT: Mountain Standard/Daylight Time
+ * CST/CDT: Central Standard/Daylight Time
+ * EST/EDT: Eastern Standard/Daylight Time
+ * AST: Atlantic Standard Time
+ * NST: Newfoundland Standard Time
+ * GMT: Greenwich Mean Time
+ * BST: British Summer Time
+ * MET: Middle Europe Time
+ * EET: Eastern Europe Time
+ * JST: Japan Standard Time
+ */
+
+typedef enum
+{
+ TT_UNKNOWN,
+
+ TT_SUN, TT_MON, TT_TUE, TT_WED, TT_THU, TT_FRI, TT_SAT,
+
+ TT_JAN, TT_FEB, TT_MAR, TT_APR, TT_MAY, TT_JUN,
+ TT_JUL, TT_AUG, TT_SEP, TT_OCT, TT_NOV, TT_DEC,
+
+ TT_PST, TT_PDT, TT_MST, TT_MDT, TT_CST, TT_CDT, TT_EST, TT_EDT,
+ TT_AST, TT_NST, TT_GMT, TT_BST, TT_MET, TT_EET, TT_JST
+} TIME_TOKEN;
+
+/*
+ * This parses a time/date string into a PRTime
+ * (microseconds after "1-Jan-1970 00:00:00 GMT").
+ * It returns PR_SUCCESS on success, and PR_FAILURE
+ * if the time/date string can't be parsed.
+ *
+ * Many formats are handled, including:
+ *
+ * 14 Apr 89 03:20:12
+ * 14 Apr 89 03:20 GMT
+ * Fri, 17 Mar 89 4:01:33
+ * Fri, 17 Mar 89 4:01 GMT
+ * Mon Jan 16 16:12 PDT 1989
+ * Mon Jan 16 16:12 +0130 1989
+ * 6 May 1992 16:41-JST (Wednesday)
+ * 22-AUG-1993 10:59:12.82
+ * 22-AUG-1993 10:59pm
+ * 22-AUG-1993 12:59am
+ * 22-AUG-1993 12:59 PM
+ * Friday, August 04, 1995 3:54 PM
+ * 06/21/95 04:24:34 PM
+ * 20/06/95 21:07
+ * 95-06-08 19:32:48 EDT
+ *
+ * If the input string doesn't contain a description of the timezone,
+ * we consult the `default_to_gmt' to decide whether the string should
+ * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE).
+ * The correct value for this argument depends on what standard specified
+ * the time string which you are parsing.
+ */
+
+PR_IMPLEMENT(PRStatus)
+PR_ParseTimeString(
+ const char *string,
+ PRBool default_to_gmt,
+ PRTime *result)
+{
+ PRExplodedTime tm;
+ TIME_TOKEN dotw = TT_UNKNOWN;
+ TIME_TOKEN month = TT_UNKNOWN;
+ TIME_TOKEN zone = TT_UNKNOWN;
+ int zone_offset = -1;
+ int date = -1;
+ PRInt32 year = -1;
+ int hour = -1;
+ int min = -1;
+ int sec = -1;
+
+ const char *rest = string;
+
+#ifdef DEBUG
+ int iterations = 0;
+#endif
+
+ PR_ASSERT(string && result);
+ if (!string || !result) return PR_FAILURE;
+
+ while (*rest)
+ {
+
+#ifdef DEBUG
+ if (iterations++ > 1000)
+ {
+ PR_ASSERT(0);
+ return PR_FAILURE;
+ }
+#endif
+
+ switch (*rest)
+ {
+ case 'a': case 'A':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'p' || rest[1] == 'P') &&
+ (rest[2] == 'r' || rest[2] == 'R'))
+ month = TT_APR;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_AST;
+ else if (month == TT_UNKNOWN &&
+ (rest[1] == 'u' || rest[1] == 'U') &&
+ (rest[2] == 'g' || rest[2] == 'G'))
+ month = TT_AUG;
+ break;
+ case 'b': case 'B':
+ if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_BST;
+ break;
+ case 'c': case 'C':
+ if (zone == TT_UNKNOWN &&
+ (rest[1] == 'd' || rest[1] == 'D') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_CDT;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_CST;
+ break;
+ case 'd': case 'D':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'e' || rest[1] == 'E') &&
+ (rest[2] == 'c' || rest[2] == 'C'))
+ month = TT_DEC;
+ break;
+ case 'e': case 'E':
+ if (zone == TT_UNKNOWN &&
+ (rest[1] == 'd' || rest[1] == 'D') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_EDT;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 'e' || rest[1] == 'E') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_EET;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_EST;
+ break;
+ case 'f': case 'F':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'e' || rest[1] == 'E') &&
+ (rest[2] == 'b' || rest[2] == 'B'))
+ month = TT_FEB;
+ else if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'r' || rest[1] == 'R') &&
+ (rest[2] == 'i' || rest[2] == 'I'))
+ dotw = TT_FRI;
+ break;
+ case 'g': case 'G':
+ if (zone == TT_UNKNOWN &&
+ (rest[1] == 'm' || rest[1] == 'M') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_GMT;
+ break;
+ case 'j': case 'J':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'a' || rest[1] == 'A') &&
+ (rest[2] == 'n' || rest[2] == 'N'))
+ month = TT_JAN;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_JST;
+ else if (month == TT_UNKNOWN &&
+ (rest[1] == 'u' || rest[1] == 'U') &&
+ (rest[2] == 'l' || rest[2] == 'L'))
+ month = TT_JUL;
+ else if (month == TT_UNKNOWN &&
+ (rest[1] == 'u' || rest[1] == 'U') &&
+ (rest[2] == 'n' || rest[2] == 'N'))
+ month = TT_JUN;
+ break;
+ case 'm': case 'M':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'a' || rest[1] == 'A') &&
+ (rest[2] == 'r' || rest[2] == 'R'))
+ month = TT_MAR;
+ else if (month == TT_UNKNOWN &&
+ (rest[1] == 'a' || rest[1] == 'A') &&
+ (rest[2] == 'y' || rest[2] == 'Y'))
+ month = TT_MAY;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 'd' || rest[1] == 'D') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_MDT;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 'e' || rest[1] == 'E') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_MET;
+ else if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'o' || rest[1] == 'O') &&
+ (rest[2] == 'n' || rest[2] == 'N'))
+ dotw = TT_MON;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_MST;
+ break;
+ case 'n': case 'N':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'o' || rest[1] == 'O') &&
+ (rest[2] == 'v' || rest[2] == 'V'))
+ month = TT_NOV;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_NST;
+ break;
+ case 'o': case 'O':
+ if (month == TT_UNKNOWN &&
+ (rest[1] == 'c' || rest[1] == 'C') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ month = TT_OCT;
+ break;
+ case 'p': case 'P':
+ if (zone == TT_UNKNOWN &&
+ (rest[1] == 'd' || rest[1] == 'D') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_PDT;
+ else if (zone == TT_UNKNOWN &&
+ (rest[1] == 's' || rest[1] == 'S') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ zone = TT_PST;
+ break;
+ case 's': case 'S':
+ if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'a' || rest[1] == 'A') &&
+ (rest[2] == 't' || rest[2] == 'T'))
+ dotw = TT_SAT;
+ else if (month == TT_UNKNOWN &&
+ (rest[1] == 'e' || rest[1] == 'E') &&
+ (rest[2] == 'p' || rest[2] == 'P'))
+ month = TT_SEP;
+ else if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'u' || rest[1] == 'U') &&
+ (rest[2] == 'n' || rest[2] == 'N'))
+ dotw = TT_SUN;
+ break;
+ case 't': case 'T':
+ if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'h' || rest[1] == 'H') &&
+ (rest[2] == 'u' || rest[2] == 'U'))
+ dotw = TT_THU;
+ else if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'u' || rest[1] == 'U') &&
+ (rest[2] == 'e' || rest[2] == 'E'))
+ dotw = TT_TUE;
+ break;
+ case 'u': case 'U':
+ if (zone == TT_UNKNOWN &&
+ (rest[1] == 't' || rest[1] == 'T') &&
+ !(rest[2] >= 'A' && rest[2] <= 'Z') &&
+ !(rest[2] >= 'a' && rest[2] <= 'z'))
+ /* UT is the same as GMT but UTx is not. */
+ zone = TT_GMT;
+ break;
+ case 'w': case 'W':
+ if (dotw == TT_UNKNOWN &&
+ (rest[1] == 'e' || rest[1] == 'E') &&
+ (rest[2] == 'd' || rest[2] == 'D'))
+ dotw = TT_WED;
+ break;
+
+ case '+': case '-':
+ {
+ const char *end;
+ int sign;
+ if (zone_offset != -1)
+ {
+ /* already got one... */
+ rest++;
+ break;
+ }
+ if (zone != TT_UNKNOWN && zone != TT_GMT)
+ {
+ /* GMT+0300 is legal, but PST+0300 is not. */
+ rest++;
+ break;
+ }
+
+ sign = ((*rest == '+') ? 1 : -1);
+ rest++; /* move over sign */
+ end = rest;
+ while (*end >= '0' && *end <= '9')
+ end++;
+ if (rest == end) /* no digits here */
+ break;
+
+ if ((end - rest) == 4)
+ /* offset in HHMM */
+ zone_offset = (((((rest[0]-'0')*10) + (rest[1]-'0')) * 60) +
+ (((rest[2]-'0')*10) + (rest[3]-'0')));
+ else if ((end - rest) == 2)
+ /* offset in hours */
+ zone_offset = (((rest[0]-'0')*10) + (rest[1]-'0')) * 60;
+ else if ((end - rest) == 1)
+ /* offset in hours */
+ zone_offset = (rest[0]-'0') * 60;
+ else
+ /* 3 or >4 */
+ break;
+
+ zone_offset *= sign;
+ zone = TT_GMT;
+ break;
+ }
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int tmp_hour = -1;
+ int tmp_min = -1;
+ int tmp_sec = -1;
+ const char *end = rest + 1;
+ while (*end >= '0' && *end <= '9')
+ end++;
+
+ /* end is now the first character after a range of digits. */
+
+ if (*end == ':')
+ {
+ if (hour >= 0 && min >= 0) /* already got it */
+ break;
+
+ /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */
+ if ((end - rest) > 2)
+ /* it is [0-9][0-9][0-9]+: */
+ break;
+ else if ((end - rest) == 2)
+ tmp_hour = ((rest[0]-'0')*10 +
+ (rest[1]-'0'));
+ else
+ tmp_hour = (rest[0]-'0');
+
+ while (*rest && *rest != ':')
+ rest++;
+ rest++;
+
+ /* move over the colon, and parse minutes */
+
+ end = rest + 1;
+ while (*end >= '0' && *end <= '9')
+ end++;
+
+ if (end == rest)
+ /* no digits after first colon? */
+ break;
+ else if ((end - rest) > 2)
+ /* it is [0-9][0-9][0-9]+: */
+ break;
+ else if ((end - rest) == 2)
+ tmp_min = ((rest[0]-'0')*10 +
+ (rest[1]-'0'));
+ else
+ tmp_min = (rest[0]-'0');
+
+ /* now go for seconds */
+ rest = end;
+ if (*rest == ':')
+ rest++;
+ end = rest;
+ while (*end >= '0' && *end <= '9')
+ end++;
+
+ if (end == rest)
+ /* no digits after second colon - that's ok. */
+ ;
+ else if ((end - rest) > 2)
+ /* it is [0-9][0-9][0-9]+: */
+ break;
+ else if ((end - rest) == 2)
+ tmp_sec = ((rest[0]-'0')*10 +
+ (rest[1]-'0'));
+ else
+ tmp_sec = (rest[0]-'0');
+
+ /* If we made it here, we've parsed hour and min,
+ and possibly sec, so it worked as a unit. */
+
+ /* skip over whitespace and see if there's an AM or PM
+ directly following the time.
+ */
+ if (tmp_hour <= 12)
+ {
+ const char *s = end;
+ while (*s && (*s == ' ' || *s == '\t'))
+ s++;
+ if ((s[0] == 'p' || s[0] == 'P') &&
+ (s[1] == 'm' || s[1] == 'M'))
+ /* 10:05pm == 22:05, and 12:05pm == 12:05 */
+ tmp_hour = (tmp_hour == 12 ? 12 : tmp_hour + 12);
+ else if (tmp_hour == 12 &&
+ (s[0] == 'a' || s[0] == 'A') &&
+ (s[1] == 'm' || s[1] == 'M'))
+ /* 12:05am == 00:05 */
+ tmp_hour = 0;
+ }
+
+ hour = tmp_hour;
+ min = tmp_min;
+ sec = tmp_sec;
+ rest = end;
+ break;
+ }
+ else if ((*end == '/' || *end == '-') &&
+ end[1] >= '0' && end[1] <= '9')
+ {
+ /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95
+ or even 95-06-05...
+ #### But it doesn't handle 1995-06-22.
+ */
+ int n1, n2, n3;
+ const char *s;
+
+ if (month != TT_UNKNOWN)
+ /* if we saw a month name, this can't be. */
+ break;
+
+ s = rest;
+
+ n1 = (*s++ - '0'); /* first 1 or 2 digits */
+ if (*s >= '0' && *s <= '9')
+ n1 = n1*10 + (*s++ - '0');
+
+ if (*s != '/' && *s != '-') /* slash */
+ break;
+ s++;
+
+ if (*s < '0' || *s > '9') /* second 1 or 2 digits */
+ break;
+ n2 = (*s++ - '0');
+ if (*s >= '0' && *s <= '9')
+ n2 = n2*10 + (*s++ - '0');
+
+ if (*s != '/' && *s != '-') /* slash */
+ break;
+ s++;
+
+ if (*s < '0' || *s > '9') /* third 1, 2, or 4 digits */
+ break;
+ n3 = (*s++ - '0');
+ if (*s >= '0' && *s <= '9')
+ n3 = n3*10 + (*s++ - '0');
+
+ if (*s >= '0' && *s <= '9') /* optional digits 3 and 4 */
+ {
+ n3 = n3*10 + (*s++ - '0');
+ if (*s < '0' || *s > '9')
+ break;
+ n3 = n3*10 + (*s++ - '0');
+ }
+
+ if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */
+ (*s >= 'A' && *s <= 'Z') ||
+ (*s >= 'a' && *s <= 'z'))
+ break;
+
+ /* Ok, we parsed three 1-2 digit numbers, with / or -
+ between them. Now decide what the hell they are
+ (DD/MM/YY or MM/DD/YY or YY/MM/DD.)
+ */
+
+ if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */
+ {
+ if (n2 > 12) break;
+ if (n3 > 31) break;
+ year = n1;
+ if (year < 70)
+ year += 2000;
+ else if (year < 100)
+ year += 1900;
+ month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1);
+ date = n3;
+ rest = s;
+ break;
+ }
+
+ if (n1 > 12 && n2 > 12) /* illegal */
+ {
+ rest = s;
+ break;
+ }
+
+ if (n3 < 70)
+ n3 += 2000;
+ else if (n3 < 100)
+ n3 += 1900;
+
+ if (n1 > 12) /* must be DD/MM/YY */
+ {
+ date = n1;
+ month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1);
+ year = n3;
+ }
+ else /* assume MM/DD/YY */
+ {
+ /* #### In the ambiguous case, should we consult the
+ locale to find out the local default? */
+ month = (TIME_TOKEN)(n1 + ((int)TT_JAN) - 1);
+ date = n2;
+ year = n3;
+ }
+ rest = s;
+ }
+ else if ((*end >= 'A' && *end <= 'Z') ||
+ (*end >= 'a' && *end <= 'z'))
+ /* Digits followed by non-punctuation - what's that? */
+ ;
+ else if ((end - rest) == 4) /* four digits is a year */
+ year = (year < 0
+ ? ((rest[0]-'0')*1000L +
+ (rest[1]-'0')*100L +
+ (rest[2]-'0')*10L +
+ (rest[3]-'0'))
+ : year);
+ else if ((end - rest) == 2) /* two digits - date or year */
+ {
+ int n = ((rest[0]-'0')*10 +
+ (rest[1]-'0'));
+ /* If we don't have a date (day of the month) and we see a number
+ less than 32, then assume that is the date.
+
+ Otherwise, if we have a date and not a year, assume this is the
+ year. If it is less than 70, then assume it refers to the 21st
+ century. If it is two digits (>= 70), assume it refers to this
+ century. Otherwise, assume it refers to an unambiguous year.
+
+ The world will surely end soon.
+ */
+ if (date < 0 && n < 32)
+ date = n;
+ else if (year < 0)
+ {
+ if (n < 70)
+ year = 2000 + n;
+ else if (n < 100)
+ year = 1900 + n;
+ else
+ year = n;
+ }
+ /* else what the hell is this. */
+ }
+ else if ((end - rest) == 1) /* one digit - date */
+ date = (date < 0 ? (rest[0]-'0') : date);
+ /* else, three or more than four digits - what's that? */
+
+ break;
+ }
+ }
+
+ /* Skip to the end of this token, whether we parsed it or not.
+ Tokens are delimited by whitespace, or ,;-/
+ But explicitly not :+-.
+ */
+ while (*rest &&
+ *rest != ' ' && *rest != '\t' &&
+ *rest != ',' && *rest != ';' &&
+ *rest != '-' && *rest != '+' &&
+ *rest != '/' &&
+ *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']')
+ rest++;
+ /* skip over uninteresting chars. */
+ SKIP_MORE:
+ while (*rest &&
+ (*rest == ' ' || *rest == '\t' ||
+ *rest == ',' || *rest == ';' || *rest == '/' ||
+ *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']'))
+ rest++;
+
+ /* "-" is ignored at the beginning of a token if we have not yet
+ parsed a year (e.g., the second "-" in "30-AUG-1966"), or if
+ the character after the dash is not a digit. */
+ if (*rest == '-' && ((rest > string && isalpha(rest[-1]) && year < 0)
+ || rest[1] < '0' || rest[1] > '9'))
+ {
+ rest++;
+ goto SKIP_MORE;
+ }
+
+ }
+
+ if (zone != TT_UNKNOWN && zone_offset == -1)
+ {
+ switch (zone)
+ {
+ case TT_PST: zone_offset = -8 * 60; break;
+ case TT_PDT: zone_offset = -7 * 60; break;
+ case TT_MST: zone_offset = -7 * 60; break;
+ case TT_MDT: zone_offset = -6 * 60; break;
+ case TT_CST: zone_offset = -6 * 60; break;
+ case TT_CDT: zone_offset = -5 * 60; break;
+ case TT_EST: zone_offset = -5 * 60; break;
+ case TT_EDT: zone_offset = -4 * 60; break;
+ case TT_AST: zone_offset = -4 * 60; break;
+ case TT_NST: zone_offset = -3 * 60 - 30; break;
+ case TT_GMT: zone_offset = 0 * 60; break;
+ case TT_BST: zone_offset = 1 * 60; break;
+ case TT_MET: zone_offset = 1 * 60; break;
+ case TT_EET: zone_offset = 2 * 60; break;
+ case TT_JST: zone_offset = 9 * 60; break;
+ default:
+ PR_ASSERT (0);
+ break;
+ }
+ }
+
+ /* If we didn't find a year, month, or day-of-the-month, we can't
+ possibly parse this, and in fact, mktime() will do something random
+ (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt
+ a numerologically significant date... */
+ if (month == TT_UNKNOWN || date == -1 || year == -1)
+ return PR_FAILURE;
+
+ memset(&tm, 0, sizeof(tm));
+ if (sec != -1)
+ tm.tm_sec = sec;
+ if (min != -1)
+ tm.tm_min = min;
+ if (hour != -1)
+ tm.tm_hour = hour;
+ if (date != -1)
+ tm.tm_mday = date;
+ if (month != TT_UNKNOWN)
+ tm.tm_month = (((int)month) - ((int)TT_JAN));
+ if (year != -1)
+ tm.tm_year = year;
+ if (dotw != TT_UNKNOWN)
+ tm.tm_wday = (((int)dotw) - ((int)TT_SUN));
+
+ if (zone == TT_UNKNOWN && default_to_gmt)
+ {
+ /* No zone was specified, so pretend the zone was GMT. */
+ zone = TT_GMT;
+ zone_offset = 0;
+ }
+
+ if (zone_offset == -1)
+ {
+ /* no zone was specified, and we're to assume that everything
+ is local. */
+ struct tm localTime;
+ time_t secs;
+
+ PR_ASSERT(tm.tm_month > -1
+ && tm.tm_mday > 0
+ && tm.tm_hour > -1
+ && tm.tm_min > -1
+ && tm.tm_sec > -1);
+
+ /*
+ * To obtain time_t from a tm structure representing the local
+ * time, we call mktime(). However, we need to see if we are
+ * on 1-Jan-1970 or before. If we are, we can't call mktime()
+ * because mktime() will crash on win16. In that case, we
+ * calculate zone_offset based on the zone offset at
+ * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the
+ * date we are parsing to transform the date to GMT. We also
+ * do so if mktime() returns (time_t) -1 (time out of range).
+ */
+
+ /* month, day, hours, mins and secs are always non-negative
+ so we dont need to worry about them. */
+ if(tm.tm_year >= 1970)
+ {
+ PRInt64 usec_per_sec;
+
+ localTime.tm_sec = tm.tm_sec;
+ localTime.tm_min = tm.tm_min;
+ localTime.tm_hour = tm.tm_hour;
+ localTime.tm_mday = tm.tm_mday;
+ localTime.tm_mon = tm.tm_month;
+ localTime.tm_year = tm.tm_year - 1900;
+ /* Set this to -1 to tell mktime "I don't care". If you set
+ it to 0 or 1, you are making assertions about whether the
+ date you are handing it is in daylight savings mode or not;
+ and if you're wrong, it will "fix" it for you. */
+ localTime.tm_isdst = -1;
+ secs = mktime(&localTime);
+ if (secs != (time_t) -1)
+ {
+#if defined(XP_MAC) && (__MSL__ < 0x6000)
+ /*
+ * The mktime() routine in MetroWerks MSL C
+ * Runtime library returns seconds since midnight,
+ * 1 Jan. 1900, not 1970 - in versions of MSL (Metrowerks Standard
+ * Library) prior to version 6. Only for older versions of
+ * MSL do we adjust the value of secs to the NSPR epoch
+ */
+ secs -= ((365 * 70UL) + 17) * 24 * 60 * 60;
+#endif
+ LL_I2L(*result, secs);
+ LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
+ LL_MUL(*result, *result, usec_per_sec);
+ return PR_SUCCESS;
+ }
+ }
+
+ /* So mktime() can't handle this case. We assume the
+ zone_offset for the date we are parsing is the same as
+ the zone offset on 00:00:00 2 Jan 1970 GMT. */
+ secs = 86400;
+ (void) MT_safe_localtime(&secs, &localTime);
+ zone_offset = localTime.tm_min
+ + 60 * localTime.tm_hour
+ + 1440 * (localTime.tm_mday - 2);
+ }
+
+ /* Adjust the hours and minutes before handing them to
+ PR_ImplodeTime(). Note that it's ok for them to be <0 or >24/60
+
+ We adjust the time to GMT before going into PR_ImplodeTime().
+ The zone_offset represents the difference between the time
+ zone parsed and GMT
+ */
+ tm.tm_hour -= (zone_offset / 60);
+ tm.tm_min -= (zone_offset % 60);
+
+ *result = PR_ImplodeTime(&tm);
+
+ return PR_SUCCESS;
+}
+
+/*
+ *******************************************************************
+ *******************************************************************
+ **
+ ** OLD COMPATIBILITY FUNCTIONS
+ **
+ *******************************************************************
+ *******************************************************************
+ */
+
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_FormatTime --
+ *
+ * Format a time value into a buffer. Same semantics as strftime().
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRUint32)
+PR_FormatTime(char *buf, int buflen, const char *fmt, const PRExplodedTime *tm)
+{
+ struct tm a;
+ a.tm_sec = tm->tm_sec;
+ a.tm_min = tm->tm_min;
+ a.tm_hour = tm->tm_hour;
+ a.tm_mday = tm->tm_mday;
+ a.tm_mon = tm->tm_month;
+ a.tm_wday = tm->tm_wday;
+ a.tm_year = tm->tm_year - 1900;
+ a.tm_yday = tm->tm_yday;
+ a.tm_isdst = tm->tm_params.tp_dst_offset ? 1 : 0;
+
+/*
+ * On some platforms, for example SunOS 4, struct tm has two additional
+ * fields: tm_zone and tm_gmtoff.
+ */
+
+#if defined(SUNOS4) || (__GLIBC__ >= 2) || defined(XP_BEOS) \
+ || defined(NETBSD) || defined(OPENBSD) || defined(FREEBSD) \
+ || defined(DARWIN)
+ a.tm_zone = NULL;
+ a.tm_gmtoff = tm->tm_params.tp_gmt_offset + tm->tm_params.tp_dst_offset;
+#endif
+
+ return strftime(buf, buflen, fmt, &a);
+}
+
+
+/*
+ * The following string arrays and macros are used by PR_FormatTimeUSEnglish().
+ */
+
+static const char* abbrevDays[] =
+{
+ "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
+};
+
+static const char* days[] =
+{
+ "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"
+};
+
+static const char* abbrevMonths[] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static const char* months[] =
+{
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+};
+
+
+/*
+ * Add a single character to the given buffer, incrementing the buffer pointer
+ * and decrementing the buffer size. Return 0 on error.
+ */
+#define ADDCHAR( buf, bufSize, ch ) \
+do \
+{ \
+ if( bufSize < 1 ) \
+ { \
+ *(--buf) = '\0'; \
+ return 0; \
+ } \
+ *buf++ = ch; \
+ bufSize--; \
+} \
+while(0)
+
+
+/*
+ * Add a string to the given buffer, incrementing the buffer pointer
+ * and decrementing the buffer size appropriately. Return 0 on error.
+ */
+#define ADDSTR( buf, bufSize, str ) \
+do \
+{ \
+ PRUint32 strSize = strlen( str ); \
+ if( strSize > bufSize ) \
+ { \
+ if( bufSize==0 ) \
+ *(--buf) = '\0'; \
+ else \
+ *buf = '\0'; \
+ return 0; \
+ } \
+ memcpy(buf, str, strSize); \
+ buf += strSize; \
+ bufSize -= strSize; \
+} \
+while(0)
+
+/* Needed by PR_FormatTimeUSEnglish() */
+static unsigned int pr_WeekOfYear(const PRExplodedTime* time,
+ unsigned int firstDayOfWeek);
+
+
+/***********************************************************************************
+ *
+ * Description:
+ * This is a dumbed down version of strftime that will format the date in US
+ * English regardless of the setting of the global locale. This functionality is
+ * needed to write things like MIME headers which must always be in US English.
+ *
+ **********************************************************************************/
+
+PR_IMPLEMENT(PRUint32)
+PR_FormatTimeUSEnglish( char* buf, PRUint32 bufSize,
+ const char* format, const PRExplodedTime* time )
+{
+ char* bufPtr = buf;
+ const char* fmtPtr;
+ char tmpBuf[ 40 ];
+ const int tmpBufSize = sizeof( tmpBuf );
+
+
+ for( fmtPtr=format; *fmtPtr != '\0'; fmtPtr++ )
+ {
+ if( *fmtPtr != '%' )
+ {
+ ADDCHAR( bufPtr, bufSize, *fmtPtr );
+ }
+ else
+ {
+ switch( *(++fmtPtr) )
+ {
+ case '%':
+ /* escaped '%' character */
+ ADDCHAR( bufPtr, bufSize, '%' );
+ break;
+
+ case 'a':
+ /* abbreviated weekday name */
+ ADDSTR( bufPtr, bufSize, abbrevDays[ time->tm_wday ] );
+ break;
+
+ case 'A':
+ /* full weekday name */
+ ADDSTR( bufPtr, bufSize, days[ time->tm_wday ] );
+ break;
+
+ case 'b':
+ /* abbreviated month name */
+ ADDSTR( bufPtr, bufSize, abbrevMonths[ time->tm_month ] );
+ break;
+
+ case 'B':
+ /* full month name */
+ ADDSTR(bufPtr, bufSize, months[ time->tm_month ] );
+ break;
+
+ case 'c':
+ /* Date and time. */
+ PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%a %b %d %H:%M:%S %Y", time );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'd':
+ /* day of month ( 01 - 31 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_mday );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'H':
+ /* hour ( 00 - 23 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_hour );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'I':
+ /* hour ( 01 - 12 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",
+ (time->tm_hour%12) ? time->tm_hour%12 : (PRInt32) 12 );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'j':
+ /* day number of year ( 001 - 366 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.3d",time->tm_yday + 1);
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'm':
+ /* month number ( 01 - 12 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_month+1);
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'M':
+ /* minute ( 00 - 59 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_min );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'p':
+ /* locale's equivalent of either AM or PM */
+ ADDSTR( bufPtr, bufSize, (time->tm_hour<12)?"AM":"PM" );
+ break;
+
+ case 'S':
+ /* seconds ( 00 - 61 ), allows for leap seconds */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_sec );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'U':
+ /* week number of year ( 00 - 53 ), Sunday is the first day of week 1 */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 0 ) );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'w':
+ /* weekday number ( 0 - 6 ), Sunday = 0 */
+ PR_snprintf(tmpBuf,tmpBufSize,"%d",time->tm_wday );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'W':
+ /* Week number of year ( 00 - 53 ), Monday is the first day of week 1 */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 1 ) );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'x':
+ /* Date representation */
+ PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%m/%d/%y", time );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'X':
+ /* Time representation. */
+ PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%H:%M:%S", time );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'y':
+ /* year within century ( 00 - 99 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.2d",time->tm_year % 100 );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'Y':
+ /* year as ccyy ( for example 1986 ) */
+ PR_snprintf(tmpBuf,tmpBufSize,"%.4d",time->tm_year );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ case 'Z':
+ /* Time zone name or no characters if no time zone exists.
+ * Since time zone name is supposed to be independant of locale, we
+ * defer to PR_FormatTime() for this option.
+ */
+ PR_FormatTime( tmpBuf, tmpBufSize, "%Z", time );
+ ADDSTR( bufPtr, bufSize, tmpBuf );
+ break;
+
+ default:
+ /* Unknown format. Simply copy format into output buffer. */
+ ADDCHAR( bufPtr, bufSize, '%' );
+ ADDCHAR( bufPtr, bufSize, *fmtPtr );
+ break;
+
+ }
+ }
+ }
+
+ ADDCHAR( bufPtr, bufSize, '\0' );
+ return (PRUint32)(bufPtr - buf - 1);
+}
+
+
+
+/***********************************************************************************
+ *
+ * Description:
+ * Returns the week number of the year (0-53) for the given time. firstDayOfWeek
+ * is the day on which the week is considered to start (0=Sun, 1=Mon, ...).
+ * Week 1 starts the first time firstDayOfWeek occurs in the year. In other words,
+ * a partial week at the start of the year is considered week 0.
+ *
+ **********************************************************************************/
+
+static unsigned int
+pr_WeekOfYear(const PRExplodedTime* time, unsigned int firstDayOfWeek)
+{
+ int dayOfWeek;
+ int dayOfYear;
+
+ /* Get the day of the year for the given time then adjust it to represent the
+ * first day of the week containing the given time.
+ */
+ dayOfWeek = time->tm_wday - firstDayOfWeek;
+ if (dayOfWeek < 0)
+ dayOfWeek += 7;
+
+ dayOfYear = time->tm_yday - dayOfWeek;
+
+
+ if( dayOfYear <= 0 )
+ {
+ /* If dayOfYear is <= 0, it is in the first partial week of the year. */
+ return 0;
+ }
+ else
+ {
+ /* Count the number of full weeks ( dayOfYear / 7 ) then add a week if there
+ * are any days left over ( dayOfYear % 7 ). Because we are only counting to
+ * the first day of the week containing the given time, rather than to the
+ * actual day representing the given time, any days in week 0 will be "absorbed"
+ * as extra days in the given week.
+ */
+ return (dayOfYear / 7) + ( (dayOfYear % 7) == 0 ? 0 : 1 );
+ }
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtpool.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtpool.c
new file mode 100644
index 00000000..fbedd7de
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtpool.c
@@ -0,0 +1,1217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+
+/*
+ * Thread pools
+ * Thread pools create and manage threads to provide support for
+ * scheduling jobs onto one or more threads.
+ *
+ */
+#ifdef OPT_WINNT
+#include <windows.h>
+#endif
+
+/*
+ * worker thread
+ */
+typedef struct wthread {
+ PRCList links;
+ PRThread *thread;
+} wthread;
+
+/*
+ * queue of timer jobs
+ */
+typedef struct timer_jobq {
+ PRCList list;
+ PRLock *lock;
+ PRCondVar *cv;
+ PRInt32 cnt;
+ PRCList wthreads;
+} timer_jobq;
+
+/*
+ * queue of jobs
+ */
+typedef struct tp_jobq {
+ PRCList list;
+ PRInt32 cnt;
+ PRLock *lock;
+ PRCondVar *cv;
+ PRCList wthreads;
+#ifdef OPT_WINNT
+ HANDLE nt_completion_port;
+#endif
+} tp_jobq;
+
+/*
+ * queue of IO jobs
+ */
+typedef struct io_jobq {
+ PRCList list;
+ PRPollDesc *pollfds;
+ PRInt32 npollfds;
+ PRJob **polljobs;
+ PRLock *lock;
+ PRInt32 cnt;
+ PRFileDesc *notify_fd;
+ PRCList wthreads;
+} io_jobq;
+
+/*
+ * Threadpool
+ */
+struct PRThreadPool {
+ PRInt32 init_threads;
+ PRInt32 max_threads;
+ PRInt32 current_threads;
+ PRInt32 idle_threads;
+ PRUint32 stacksize;
+ tp_jobq jobq;
+ io_jobq ioq;
+ timer_jobq timerq;
+ PRLock *join_lock; /* used with jobp->join_cv */
+ PRCondVar *shutdown_cv;
+ PRBool shutdown;
+};
+
+typedef enum io_op_type
+ { JOB_IO_READ, JOB_IO_WRITE, JOB_IO_CONNECT, JOB_IO_ACCEPT } io_op_type;
+
+#ifdef OPT_WINNT
+typedef struct NT_notifier {
+ OVERLAPPED overlapped; /* must be first */
+ PRJob *jobp;
+} NT_notifier;
+#endif
+
+struct PRJob {
+ PRCList links; /* for linking jobs */
+ PRBool on_ioq; /* job on ioq */
+ PRBool on_timerq; /* job on timerq */
+ PRJobFn job_func;
+ void *job_arg;
+ PRCondVar *join_cv;
+ PRBool join_wait; /* == PR_TRUE, when waiting to join */
+ PRCondVar *cancel_cv; /* for cancelling IO jobs */
+ PRBool cancel_io; /* for cancelling IO jobs */
+ PRThreadPool *tpool; /* back pointer to thread pool */
+ PRJobIoDesc *iod;
+ io_op_type io_op;
+ PRInt16 io_poll_flags;
+ PRNetAddr *netaddr;
+ PRIntervalTime timeout; /* relative value */
+ PRIntervalTime absolute;
+#ifdef OPT_WINNT
+ NT_notifier nt_notifier;
+#endif
+};
+
+#define JOB_LINKS_PTR(_qp) \
+ ((PRJob *) ((char *) (_qp) - offsetof(PRJob, links)))
+
+#define WTHREAD_LINKS_PTR(_qp) \
+ ((wthread *) ((char *) (_qp) - offsetof(wthread, links)))
+
+#define JOINABLE_JOB(_jobp) (NULL != (_jobp)->join_cv)
+
+#define JOIN_NOTIFY(_jobp) \
+ PR_BEGIN_MACRO \
+ PR_Lock(_jobp->tpool->join_lock); \
+ _jobp->join_wait = PR_FALSE; \
+ PR_NotifyCondVar(_jobp->join_cv); \
+ PR_Unlock(_jobp->tpool->join_lock); \
+ PR_END_MACRO
+
+#define CANCEL_IO_JOB(jobp) \
+ PR_BEGIN_MACRO \
+ jobp->cancel_io = PR_FALSE; \
+ jobp->on_ioq = PR_FALSE; \
+ PR_REMOVE_AND_INIT_LINK(&jobp->links); \
+ tp->ioq.cnt--; \
+ PR_NotifyCondVar(jobp->cancel_cv); \
+ PR_END_MACRO
+
+static void delete_job(PRJob *jobp);
+static PRThreadPool * alloc_threadpool(void);
+static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp);
+static void notify_ioq(PRThreadPool *tp);
+static void notify_timerq(PRThreadPool *tp);
+
+/*
+ * locks are acquired in the following order
+ *
+ * tp->ioq.lock,tp->timerq.lock
+ * |
+ * V
+ * tp->jobq->lock
+ */
+
+/*
+ * worker thread function
+ */
+static void wstart(void *arg)
+{
+PRThreadPool *tp = (PRThreadPool *) arg;
+PRCList *head;
+
+ /*
+ * execute jobs until shutdown
+ */
+ while (!tp->shutdown) {
+ PRJob *jobp;
+#ifdef OPT_WINNT
+ BOOL rv;
+ DWORD unused, shutdown;
+ LPOVERLAPPED olp;
+
+ PR_Lock(tp->jobq.lock);
+ tp->idle_threads++;
+ PR_Unlock(tp->jobq.lock);
+ rv = GetQueuedCompletionStatus(tp->jobq.nt_completion_port,
+ &unused, &shutdown, &olp, INFINITE);
+
+ PR_ASSERT(rv);
+ if (shutdown)
+ break;
+ jobp = ((NT_notifier *) olp)->jobp;
+ PR_Lock(tp->jobq.lock);
+ tp->idle_threads--;
+ tp->jobq.cnt--;
+ PR_Unlock(tp->jobq.lock);
+#else
+
+ PR_Lock(tp->jobq.lock);
+ while (PR_CLIST_IS_EMPTY(&tp->jobq.list) && (!tp->shutdown)) {
+ tp->idle_threads++;
+ PR_WaitCondVar(tp->jobq.cv, PR_INTERVAL_NO_TIMEOUT);
+ tp->idle_threads--;
+ }
+ if (tp->shutdown) {
+ PR_Unlock(tp->jobq.lock);
+ break;
+ }
+ head = PR_LIST_HEAD(&tp->jobq.list);
+ /*
+ * remove job from queue
+ */
+ PR_REMOVE_AND_INIT_LINK(head);
+ tp->jobq.cnt--;
+ jobp = JOB_LINKS_PTR(head);
+ PR_Unlock(tp->jobq.lock);
+#endif
+
+ jobp->job_func(jobp->job_arg);
+ if (!JOINABLE_JOB(jobp)) {
+ delete_job(jobp);
+ } else {
+ JOIN_NOTIFY(jobp);
+ }
+ }
+ PR_Lock(tp->jobq.lock);
+ tp->current_threads--;
+ PR_Unlock(tp->jobq.lock);
+}
+
+/*
+ * add a job to the work queue
+ */
+static void
+add_to_jobq(PRThreadPool *tp, PRJob *jobp)
+{
+ /*
+ * add to jobq
+ */
+#ifdef OPT_WINNT
+ PR_Lock(tp->jobq.lock);
+ tp->jobq.cnt++;
+ PR_Unlock(tp->jobq.lock);
+ /*
+ * notify worker thread(s)
+ */
+ PostQueuedCompletionStatus(tp->jobq.nt_completion_port, 0,
+ FALSE, &jobp->nt_notifier.overlapped);
+#else
+ PR_Lock(tp->jobq.lock);
+ PR_APPEND_LINK(&jobp->links,&tp->jobq.list);
+ tp->jobq.cnt++;
+ if ((tp->idle_threads < tp->jobq.cnt) &&
+ (tp->current_threads < tp->max_threads)) {
+ wthread *wthrp;
+ /*
+ * increment thread count and unlock the jobq lock
+ */
+ tp->current_threads++;
+ PR_Unlock(tp->jobq.lock);
+ /* create new worker thread */
+ wthrp = PR_NEWZAP(wthread);
+ if (wthrp) {
+ wthrp->thread = PR_CreateThread(PR_USER_THREAD, wstart,
+ tp, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,tp->stacksize);
+ if (NULL == wthrp->thread) {
+ PR_DELETE(wthrp); /* this sets wthrp to NULL */
+ }
+ }
+ PR_Lock(tp->jobq.lock);
+ if (NULL == wthrp) {
+ tp->current_threads--;
+ } else {
+ PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads);
+ }
+ }
+ /*
+ * wakeup a worker thread
+ */
+ PR_NotifyCondVar(tp->jobq.cv);
+ PR_Unlock(tp->jobq.lock);
+#endif
+}
+
+/*
+ * io worker thread function
+ */
+static void io_wstart(void *arg)
+{
+PRThreadPool *tp = (PRThreadPool *) arg;
+int pollfd_cnt, pollfds_used;
+int rv;
+PRCList *qp;
+PRPollDesc *pollfds;
+PRJob **polljobs;
+int poll_timeout;
+PRIntervalTime now;
+
+ /*
+ * scan io_jobq
+ * construct poll list
+ * call PR_Poll
+ * for all fds, for which poll returns true, move the job to
+ * jobq and wakeup worker thread.
+ */
+ while (!tp->shutdown) {
+ PRJob *jobp;
+
+ pollfd_cnt = tp->ioq.cnt + 10;
+ if (pollfd_cnt > tp->ioq.npollfds) {
+
+ /*
+ * re-allocate pollfd array if the current one is not large
+ * enough
+ */
+ if (NULL != tp->ioq.pollfds)
+ PR_Free(tp->ioq.pollfds);
+ tp->ioq.pollfds = (PRPollDesc *) PR_Malloc(pollfd_cnt *
+ (sizeof(PRPollDesc) + sizeof(PRJob *)));
+ PR_ASSERT(NULL != tp->ioq.pollfds);
+ /*
+ * array of pollfds
+ */
+ pollfds = tp->ioq.pollfds;
+ tp->ioq.polljobs = (PRJob **) (&tp->ioq.pollfds[pollfd_cnt]);
+ /*
+ * parallel array of jobs
+ */
+ polljobs = tp->ioq.polljobs;
+ tp->ioq.npollfds = pollfd_cnt;
+ }
+
+ pollfds_used = 0;
+ /*
+ * add the notify fd; used for unblocking io thread(s)
+ */
+ pollfds[pollfds_used].fd = tp->ioq.notify_fd;
+ pollfds[pollfds_used].in_flags = PR_POLL_READ;
+ pollfds[pollfds_used].out_flags = 0;
+ polljobs[pollfds_used] = NULL;
+ pollfds_used++;
+ /*
+ * fill in the pollfd array
+ */
+ PR_Lock(tp->ioq.lock);
+ for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = qp->next) {
+ jobp = JOB_LINKS_PTR(qp);
+ if (jobp->cancel_io) {
+ CANCEL_IO_JOB(jobp);
+ continue;
+ }
+ if (pollfds_used == (pollfd_cnt))
+ break;
+ pollfds[pollfds_used].fd = jobp->iod->socket;
+ pollfds[pollfds_used].in_flags = jobp->io_poll_flags;
+ pollfds[pollfds_used].out_flags = 0;
+ polljobs[pollfds_used] = jobp;
+
+ pollfds_used++;
+ }
+ if (!PR_CLIST_IS_EMPTY(&tp->ioq.list)) {
+ qp = tp->ioq.list.next;
+ jobp = JOB_LINKS_PTR(qp);
+ if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout)
+ poll_timeout = PR_INTERVAL_NO_TIMEOUT;
+ else if (PR_INTERVAL_NO_WAIT == jobp->timeout)
+ poll_timeout = PR_INTERVAL_NO_WAIT;
+ else {
+ poll_timeout = jobp->absolute - PR_IntervalNow();
+ if (poll_timeout <= 0) /* already timed out */
+ poll_timeout = PR_INTERVAL_NO_WAIT;
+ }
+ } else {
+ poll_timeout = PR_INTERVAL_NO_TIMEOUT;
+ }
+ PR_Unlock(tp->ioq.lock);
+
+ /*
+ * XXXX
+ * should retry if more jobs have been added to the queue?
+ *
+ */
+ PR_ASSERT(pollfds_used <= pollfd_cnt);
+ rv = PR_Poll(tp->ioq.pollfds, pollfds_used, poll_timeout);
+
+ if (tp->shutdown) {
+ break;
+ }
+
+ if (rv > 0) {
+ /*
+ * at least one io event is set
+ */
+ PRStatus rval_status;
+ PRInt32 index;
+
+ PR_ASSERT(pollfds[0].fd == tp->ioq.notify_fd);
+ /*
+ * reset the pollable event, if notified
+ */
+ if (pollfds[0].out_flags & PR_POLL_READ) {
+ rval_status = PR_WaitForPollableEvent(tp->ioq.notify_fd);
+ PR_ASSERT(PR_SUCCESS == rval_status);
+ }
+
+ for(index = 1; index < (pollfds_used); index++) {
+ PRInt16 events = pollfds[index].in_flags;
+ PRInt16 revents = pollfds[index].out_flags;
+ jobp = polljobs[index];
+
+ if ((revents & PR_POLL_NVAL) || /* busted in all cases */
+ (revents & PR_POLL_ERR) ||
+ ((events & PR_POLL_WRITE) &&
+ (revents & PR_POLL_HUP))) { /* write op & hup */
+ PR_Lock(tp->ioq.lock);
+ if (jobp->cancel_io) {
+ CANCEL_IO_JOB(jobp);
+ PR_Unlock(tp->ioq.lock);
+ continue;
+ }
+ PR_REMOVE_AND_INIT_LINK(&jobp->links);
+ tp->ioq.cnt--;
+ jobp->on_ioq = PR_FALSE;
+ PR_Unlock(tp->ioq.lock);
+
+ /* set error */
+ if (PR_POLL_NVAL & revents)
+ jobp->iod->error = PR_BAD_DESCRIPTOR_ERROR;
+ else if (PR_POLL_HUP & revents)
+ jobp->iod->error = PR_CONNECT_RESET_ERROR;
+ else
+ jobp->iod->error = PR_IO_ERROR;
+
+ /*
+ * add to jobq
+ */
+ add_to_jobq(tp, jobp);
+ } else if (revents) {
+ /*
+ * add to jobq
+ */
+ PR_Lock(tp->ioq.lock);
+ if (jobp->cancel_io) {
+ CANCEL_IO_JOB(jobp);
+ PR_Unlock(tp->ioq.lock);
+ continue;
+ }
+ PR_REMOVE_AND_INIT_LINK(&jobp->links);
+ tp->ioq.cnt--;
+ jobp->on_ioq = PR_FALSE;
+ PR_Unlock(tp->ioq.lock);
+
+ if (jobp->io_op == JOB_IO_CONNECT) {
+ if (PR_GetConnectStatus(&pollfds[index]) == PR_SUCCESS)
+ jobp->iod->error = 0;
+ else
+ jobp->iod->error = PR_GetError();
+ } else
+ jobp->iod->error = 0;
+
+ add_to_jobq(tp, jobp);
+ }
+ }
+ }
+ /*
+ * timeout processing
+ */
+ now = PR_IntervalNow();
+ PR_Lock(tp->ioq.lock);
+ for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = qp->next) {
+ jobp = JOB_LINKS_PTR(qp);
+ if (jobp->cancel_io) {
+ CANCEL_IO_JOB(jobp);
+ continue;
+ }
+ if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout)
+ break;
+ if ((PR_INTERVAL_NO_WAIT != jobp->timeout) &&
+ ((PRInt32)(jobp->absolute - now) > 0))
+ break;
+ PR_REMOVE_AND_INIT_LINK(&jobp->links);
+ tp->ioq.cnt--;
+ jobp->on_ioq = PR_FALSE;
+ jobp->iod->error = PR_IO_TIMEOUT_ERROR;
+ add_to_jobq(tp, jobp);
+ }
+ PR_Unlock(tp->ioq.lock);
+ }
+}
+
+/*
+ * timer worker thread function
+ */
+static void timer_wstart(void *arg)
+{
+PRThreadPool *tp = (PRThreadPool *) arg;
+PRCList *qp;
+PRIntervalTime timeout;
+PRIntervalTime now;
+
+ /*
+ * call PR_WaitCondVar with minimum value of all timeouts
+ */
+ while (!tp->shutdown) {
+ PRJob *jobp;
+
+ PR_Lock(tp->timerq.lock);
+ if (PR_CLIST_IS_EMPTY(&tp->timerq.list)) {
+ timeout = PR_INTERVAL_NO_TIMEOUT;
+ } else {
+ PRCList *qp;
+
+ qp = tp->timerq.list.next;
+ jobp = JOB_LINKS_PTR(qp);
+
+ timeout = jobp->absolute - PR_IntervalNow();
+ if (timeout <= 0)
+ timeout = PR_INTERVAL_NO_WAIT; /* already timed out */
+ }
+ if (PR_INTERVAL_NO_WAIT != timeout)
+ PR_WaitCondVar(tp->timerq.cv, timeout);
+ if (tp->shutdown) {
+ PR_Unlock(tp->timerq.lock);
+ break;
+ }
+ /*
+ * move expired-timer jobs to jobq
+ */
+ now = PR_IntervalNow();
+ while (!PR_CLIST_IS_EMPTY(&tp->timerq.list)) {
+ qp = tp->timerq.list.next;
+ jobp = JOB_LINKS_PTR(qp);
+
+ if ((PRInt32)(jobp->absolute - now) > 0) {
+ break;
+ }
+ /*
+ * job timed out
+ */
+ PR_REMOVE_AND_INIT_LINK(&jobp->links);
+ tp->timerq.cnt--;
+ jobp->on_timerq = PR_FALSE;
+ add_to_jobq(tp, jobp);
+ }
+ PR_Unlock(tp->timerq.lock);
+ }
+}
+
+static void
+delete_threadpool(PRThreadPool *tp)
+{
+ if (NULL != tp) {
+ if (NULL != tp->shutdown_cv)
+ PR_DestroyCondVar(tp->shutdown_cv);
+ if (NULL != tp->jobq.cv)
+ PR_DestroyCondVar(tp->jobq.cv);
+ if (NULL != tp->jobq.lock)
+ PR_DestroyLock(tp->jobq.lock);
+ if (NULL != tp->join_lock)
+ PR_DestroyLock(tp->join_lock);
+#ifdef OPT_WINNT
+ if (NULL != tp->jobq.nt_completion_port)
+ CloseHandle(tp->jobq.nt_completion_port);
+#endif
+ /* Timer queue */
+ if (NULL != tp->timerq.cv)
+ PR_DestroyCondVar(tp->timerq.cv);
+ if (NULL != tp->timerq.lock)
+ PR_DestroyLock(tp->timerq.lock);
+
+ if (NULL != tp->ioq.lock)
+ PR_DestroyLock(tp->ioq.lock);
+ if (NULL != tp->ioq.pollfds)
+ PR_Free(tp->ioq.pollfds);
+ if (NULL != tp->ioq.notify_fd)
+ PR_DestroyPollableEvent(tp->ioq.notify_fd);
+ PR_Free(tp);
+ }
+ return;
+}
+
+static PRThreadPool *
+alloc_threadpool(void)
+{
+PRThreadPool *tp;
+
+ tp = (PRThreadPool *) PR_CALLOC(sizeof(*tp));
+ if (NULL == tp)
+ goto failed;
+ tp->jobq.lock = PR_NewLock();
+ if (NULL == tp->jobq.lock)
+ goto failed;
+ tp->jobq.cv = PR_NewCondVar(tp->jobq.lock);
+ if (NULL == tp->jobq.cv)
+ goto failed;
+ tp->join_lock = PR_NewLock();
+ if (NULL == tp->join_lock)
+ goto failed;
+#ifdef OPT_WINNT
+ tp->jobq.nt_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
+ NULL, 0, 0);
+ if (NULL == tp->jobq.nt_completion_port)
+ goto failed;
+#endif
+
+ tp->ioq.lock = PR_NewLock();
+ if (NULL == tp->ioq.lock)
+ goto failed;
+
+ /* Timer queue */
+
+ tp->timerq.lock = PR_NewLock();
+ if (NULL == tp->timerq.lock)
+ goto failed;
+ tp->timerq.cv = PR_NewCondVar(tp->timerq.lock);
+ if (NULL == tp->timerq.cv)
+ goto failed;
+
+ tp->shutdown_cv = PR_NewCondVar(tp->jobq.lock);
+ if (NULL == tp->shutdown_cv)
+ goto failed;
+ tp->ioq.notify_fd = PR_NewPollableEvent();
+ if (NULL == tp->ioq.notify_fd)
+ goto failed;
+ return tp;
+failed:
+ delete_threadpool(tp);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+}
+
+/* Create thread pool */
+PR_IMPLEMENT(PRThreadPool *)
+PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads,
+ PRUint32 stacksize)
+{
+PRThreadPool *tp;
+PRThread *thr;
+int i;
+wthread *wthrp;
+
+ tp = alloc_threadpool();
+ if (NULL == tp)
+ return NULL;
+
+ tp->init_threads = initial_threads;
+ tp->max_threads = max_threads;
+ tp->stacksize = stacksize;
+ PR_INIT_CLIST(&tp->jobq.list);
+ PR_INIT_CLIST(&tp->ioq.list);
+ PR_INIT_CLIST(&tp->timerq.list);
+ PR_INIT_CLIST(&tp->jobq.wthreads);
+ PR_INIT_CLIST(&tp->ioq.wthreads);
+ PR_INIT_CLIST(&tp->timerq.wthreads);
+ tp->shutdown = PR_FALSE;
+
+ PR_Lock(tp->jobq.lock);
+ for(i=0; i < initial_threads; ++i) {
+
+ thr = PR_CreateThread(PR_USER_THREAD, wstart,
+ tp, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD,stacksize);
+ PR_ASSERT(thr);
+ wthrp = PR_NEWZAP(wthread);
+ PR_ASSERT(wthrp);
+ wthrp->thread = thr;
+ PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads);
+ }
+ tp->current_threads = initial_threads;
+
+ thr = PR_CreateThread(PR_USER_THREAD, io_wstart,
+ tp, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,stacksize);
+ PR_ASSERT(thr);
+ wthrp = PR_NEWZAP(wthread);
+ PR_ASSERT(wthrp);
+ wthrp->thread = thr;
+ PR_APPEND_LINK(&wthrp->links, &tp->ioq.wthreads);
+
+ thr = PR_CreateThread(PR_USER_THREAD, timer_wstart,
+ tp, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,stacksize);
+ PR_ASSERT(thr);
+ wthrp = PR_NEWZAP(wthread);
+ PR_ASSERT(wthrp);
+ wthrp->thread = thr;
+ PR_APPEND_LINK(&wthrp->links, &tp->timerq.wthreads);
+
+ PR_Unlock(tp->jobq.lock);
+ return tp;
+}
+
+static void
+delete_job(PRJob *jobp)
+{
+ if (NULL != jobp) {
+ if (NULL != jobp->join_cv) {
+ PR_DestroyCondVar(jobp->join_cv);
+ jobp->join_cv = NULL;
+ }
+ if (NULL != jobp->cancel_cv) {
+ PR_DestroyCondVar(jobp->cancel_cv);
+ jobp->cancel_cv = NULL;
+ }
+ PR_DELETE(jobp);
+ }
+}
+
+static PRJob *
+alloc_job(PRBool joinable, PRThreadPool *tp)
+{
+ PRJob *jobp;
+
+ jobp = PR_NEWZAP(PRJob);
+ if (NULL == jobp)
+ goto failed;
+ if (joinable) {
+ jobp->join_cv = PR_NewCondVar(tp->join_lock);
+ jobp->join_wait = PR_TRUE;
+ if (NULL == jobp->join_cv)
+ goto failed;
+ } else {
+ jobp->join_cv = NULL;
+ }
+#ifdef OPT_WINNT
+ jobp->nt_notifier.jobp = jobp;
+#endif
+ return jobp;
+failed:
+ delete_job(jobp);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+}
+
+/* queue a job */
+PR_IMPLEMENT(PRJob *)
+PR_QueueJob(PRThreadPool *tpool, PRJobFn fn, void *arg, PRBool joinable)
+{
+ PRJob *jobp;
+
+ jobp = alloc_job(joinable, tpool);
+ if (NULL == jobp)
+ return NULL;
+
+ jobp->job_func = fn;
+ jobp->job_arg = arg;
+ jobp->tpool = tpool;
+
+ add_to_jobq(tpool, jobp);
+ return jobp;
+}
+
+/* queue a job, when a socket is readable or writeable */
+static PRJob *
+queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg,
+ PRBool joinable, io_op_type op)
+{
+ PRJob *jobp;
+ PRIntervalTime now;
+
+ jobp = alloc_job(joinable, tpool);
+ if (NULL == jobp) {
+ return NULL;
+ }
+
+ /*
+ * Add a new job to io_jobq
+ * wakeup io worker thread
+ */
+
+ jobp->job_func = fn;
+ jobp->job_arg = arg;
+ jobp->tpool = tpool;
+ jobp->iod = iod;
+ if (JOB_IO_READ == op) {
+ jobp->io_op = JOB_IO_READ;
+ jobp->io_poll_flags = PR_POLL_READ;
+ } else if (JOB_IO_WRITE == op) {
+ jobp->io_op = JOB_IO_WRITE;
+ jobp->io_poll_flags = PR_POLL_WRITE;
+ } else if (JOB_IO_ACCEPT == op) {
+ jobp->io_op = JOB_IO_ACCEPT;
+ jobp->io_poll_flags = PR_POLL_READ;
+ } else if (JOB_IO_CONNECT == op) {
+ jobp->io_op = JOB_IO_CONNECT;
+ jobp->io_poll_flags = PR_POLL_WRITE|PR_POLL_EXCEPT;
+ } else {
+ delete_job(jobp);
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ jobp->timeout = iod->timeout;
+ if ((PR_INTERVAL_NO_TIMEOUT == iod->timeout) ||
+ (PR_INTERVAL_NO_WAIT == iod->timeout)) {
+ jobp->absolute = iod->timeout;
+ } else {
+ now = PR_IntervalNow();
+ jobp->absolute = now + iod->timeout;
+ }
+
+
+ PR_Lock(tpool->ioq.lock);
+
+ if (PR_CLIST_IS_EMPTY(&tpool->ioq.list) ||
+ (PR_INTERVAL_NO_TIMEOUT == iod->timeout)) {
+ PR_APPEND_LINK(&jobp->links,&tpool->ioq.list);
+ } else if (PR_INTERVAL_NO_WAIT == iod->timeout) {
+ PR_INSERT_LINK(&jobp->links,&tpool->ioq.list);
+ } else {
+ PRCList *qp;
+ PRJob *tmp_jobp;
+ /*
+ * insert into the timeout-sorted ioq
+ */
+ for (qp = tpool->ioq.list.prev; qp != &tpool->ioq.list;
+ qp = qp->prev) {
+ tmp_jobp = JOB_LINKS_PTR(qp);
+ if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) {
+ break;
+ }
+ }
+ PR_INSERT_AFTER(&jobp->links,qp);
+ }
+
+ jobp->on_ioq = PR_TRUE;
+ tpool->ioq.cnt++;
+ /*
+ * notify io worker thread(s)
+ */
+ PR_Unlock(tpool->ioq.lock);
+ notify_ioq(tpool);
+ return jobp;
+}
+
+/* queue a job, when a socket is readable */
+PR_IMPLEMENT(PRJob *)
+PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg,
+ PRBool joinable)
+{
+ return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_READ));
+}
+
+/* queue a job, when a socket is writeable */
+PR_IMPLEMENT(PRJob *)
+PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn,void * arg,
+ PRBool joinable)
+{
+ return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_WRITE));
+}
+
+
+/* queue a job, when a socket has a pending connection */
+PR_IMPLEMENT(PRJob *)
+PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn,
+ void * arg, PRBool joinable)
+{
+ return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_ACCEPT));
+}
+
+/* queue a job, when a socket can be connected */
+PR_IMPLEMENT(PRJob *)
+PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod,
+ const PRNetAddr *addr, PRJobFn fn, void * arg, PRBool joinable)
+{
+ PRStatus rv;
+ PRErrorCode err;
+
+ rv = PR_Connect(iod->socket, addr, PR_INTERVAL_NO_WAIT);
+ if ((rv == PR_FAILURE) && ((err = PR_GetError()) == PR_IN_PROGRESS_ERROR)){
+ /* connection pending */
+ return(queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_CONNECT));
+ } else {
+ /*
+ * connection succeeded or failed; add to jobq right away
+ */
+ if (rv == PR_FAILURE)
+ iod->error = err;
+ else
+ iod->error = 0;
+ return(PR_QueueJob(tpool, fn, arg, joinable));
+ }
+}
+
+/* queue a job, when a timer expires */
+PR_IMPLEMENT(PRJob *)
+PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout,
+ PRJobFn fn, void * arg, PRBool joinable)
+{
+ PRIntervalTime now;
+ PRJob *jobp;
+
+ if (PR_INTERVAL_NO_TIMEOUT == timeout) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+ if (PR_INTERVAL_NO_WAIT == timeout) {
+ /*
+ * no waiting; add to jobq right away
+ */
+ return(PR_QueueJob(tpool, fn, arg, joinable));
+ }
+ jobp = alloc_job(joinable, tpool);
+ if (NULL == jobp) {
+ return NULL;
+ }
+
+ /*
+ * Add a new job to timer_jobq
+ * wakeup timer worker thread
+ */
+
+ jobp->job_func = fn;
+ jobp->job_arg = arg;
+ jobp->tpool = tpool;
+ jobp->timeout = timeout;
+
+ now = PR_IntervalNow();
+ jobp->absolute = now + timeout;
+
+
+ PR_Lock(tpool->timerq.lock);
+ jobp->on_timerq = PR_TRUE;
+ if (PR_CLIST_IS_EMPTY(&tpool->timerq.list))
+ PR_APPEND_LINK(&jobp->links,&tpool->timerq.list);
+ else {
+ PRCList *qp;
+ PRJob *tmp_jobp;
+ /*
+ * insert into the sorted timer jobq
+ */
+ for (qp = tpool->timerq.list.prev; qp != &tpool->timerq.list;
+ qp = qp->prev) {
+ tmp_jobp = JOB_LINKS_PTR(qp);
+ if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) {
+ break;
+ }
+ }
+ PR_INSERT_AFTER(&jobp->links,qp);
+ }
+ tpool->timerq.cnt++;
+ /*
+ * notify timer worker thread(s)
+ */
+ notify_timerq(tpool);
+ PR_Unlock(tpool->timerq.lock);
+ return jobp;
+}
+
+static void
+notify_timerq(PRThreadPool *tp)
+{
+ /*
+ * wakeup the timer thread(s)
+ */
+ PR_NotifyCondVar(tp->timerq.cv);
+}
+
+static void
+notify_ioq(PRThreadPool *tp)
+{
+PRStatus rval_status;
+
+ /*
+ * wakeup the io thread(s)
+ */
+ rval_status = PR_SetPollableEvent(tp->ioq.notify_fd);
+ PR_ASSERT(PR_SUCCESS == rval_status);
+}
+
+/*
+ * cancel a job
+ *
+ * XXXX: is this needed? likely to be removed
+ */
+PR_IMPLEMENT(PRStatus)
+PR_CancelJob(PRJob *jobp) {
+
+ PRStatus rval = PR_FAILURE;
+ PRThreadPool *tp;
+
+ if (jobp->on_timerq) {
+ /*
+ * now, check again while holding the timerq lock
+ */
+ tp = jobp->tpool;
+ PR_Lock(tp->timerq.lock);
+ if (jobp->on_timerq) {
+ jobp->on_timerq = PR_FALSE;
+ PR_REMOVE_AND_INIT_LINK(&jobp->links);
+ tp->timerq.cnt--;
+ PR_Unlock(tp->timerq.lock);
+ if (!JOINABLE_JOB(jobp)) {
+ delete_job(jobp);
+ } else {
+ JOIN_NOTIFY(jobp);
+ }
+ rval = PR_SUCCESS;
+ } else
+ PR_Unlock(tp->timerq.lock);
+ } else if (jobp->on_ioq) {
+ /*
+ * now, check again while holding the ioq lock
+ */
+ tp = jobp->tpool;
+ PR_Lock(tp->ioq.lock);
+ if (jobp->on_ioq) {
+ jobp->cancel_cv = PR_NewCondVar(tp->ioq.lock);
+ if (NULL == jobp->cancel_cv) {
+ PR_Unlock(tp->ioq.lock);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return PR_FAILURE;
+ }
+ /*
+ * mark job 'cancelled' and notify io thread(s)
+ * XXXX:
+ * this assumes there is only one io thread; when there
+ * are multiple threads, the io thread processing this job
+ * must be notified.
+ */
+ jobp->cancel_io = PR_TRUE;
+ PR_Unlock(tp->ioq.lock); /* release, reacquire ioq lock */
+ notify_ioq(tp);
+ PR_Lock(tp->ioq.lock);
+ while (jobp->cancel_io)
+ PR_WaitCondVar(jobp->cancel_cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(tp->ioq.lock);
+ PR_ASSERT(!jobp->on_ioq);
+ if (!JOINABLE_JOB(jobp)) {
+ delete_job(jobp);
+ } else {
+ JOIN_NOTIFY(jobp);
+ }
+ rval = PR_SUCCESS;
+ } else
+ PR_Unlock(tp->ioq.lock);
+ }
+ if (PR_FAILURE == rval)
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return rval;
+}
+
+/* join a job, wait until completion */
+PR_IMPLEMENT(PRStatus)
+PR_JoinJob(PRJob *jobp)
+{
+ if (!JOINABLE_JOB(jobp)) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ PR_Lock(jobp->tpool->join_lock);
+ while(jobp->join_wait)
+ PR_WaitCondVar(jobp->join_cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(jobp->tpool->join_lock);
+ delete_job(jobp);
+ return PR_SUCCESS;
+}
+
+/* shutdown threadpool */
+PR_IMPLEMENT(PRStatus)
+PR_ShutdownThreadPool(PRThreadPool *tpool)
+{
+PRStatus rval = PR_SUCCESS;
+
+ PR_Lock(tpool->jobq.lock);
+ tpool->shutdown = PR_TRUE;
+ PR_NotifyAllCondVar(tpool->shutdown_cv);
+ PR_Unlock(tpool->jobq.lock);
+
+ return rval;
+}
+
+/*
+ * join thread pool
+ * wait for termination of worker threads
+ * reclaim threadpool resources
+ */
+PR_IMPLEMENT(PRStatus)
+PR_JoinThreadPool(PRThreadPool *tpool)
+{
+PRStatus rval = PR_SUCCESS;
+PRCList *head;
+PRStatus rval_status;
+
+ PR_Lock(tpool->jobq.lock);
+ while (!tpool->shutdown)
+ PR_WaitCondVar(tpool->shutdown_cv, PR_INTERVAL_NO_TIMEOUT);
+
+ /*
+ * wakeup worker threads
+ */
+#ifdef OPT_WINNT
+ /*
+ * post shutdown notification for all threads
+ */
+ {
+ int i;
+ for(i=0; i < tpool->current_threads; i++) {
+ PostQueuedCompletionStatus(tpool->jobq.nt_completion_port, 0,
+ TRUE, NULL);
+ }
+ }
+#else
+ PR_NotifyAllCondVar(tpool->jobq.cv);
+#endif
+
+ /*
+ * wakeup io thread(s)
+ */
+ notify_ioq(tpool);
+
+ /*
+ * wakeup timer thread(s)
+ */
+ PR_Lock(tpool->timerq.lock);
+ notify_timerq(tpool);
+ PR_Unlock(tpool->timerq.lock);
+
+ while (!PR_CLIST_IS_EMPTY(&tpool->jobq.wthreads)) {
+ wthread *wthrp;
+
+ head = PR_LIST_HEAD(&tpool->jobq.wthreads);
+ PR_REMOVE_AND_INIT_LINK(head);
+ PR_Unlock(tpool->jobq.lock);
+ wthrp = WTHREAD_LINKS_PTR(head);
+ rval_status = PR_JoinThread(wthrp->thread);
+ PR_ASSERT(PR_SUCCESS == rval_status);
+ PR_DELETE(wthrp);
+ PR_Lock(tpool->jobq.lock);
+ }
+ PR_Unlock(tpool->jobq.lock);
+ while (!PR_CLIST_IS_EMPTY(&tpool->ioq.wthreads)) {
+ wthread *wthrp;
+
+ head = PR_LIST_HEAD(&tpool->ioq.wthreads);
+ PR_REMOVE_AND_INIT_LINK(head);
+ wthrp = WTHREAD_LINKS_PTR(head);
+ rval_status = PR_JoinThread(wthrp->thread);
+ PR_ASSERT(PR_SUCCESS == rval_status);
+ PR_DELETE(wthrp);
+ }
+
+ while (!PR_CLIST_IS_EMPTY(&tpool->timerq.wthreads)) {
+ wthread *wthrp;
+
+ head = PR_LIST_HEAD(&tpool->timerq.wthreads);
+ PR_REMOVE_AND_INIT_LINK(head);
+ wthrp = WTHREAD_LINKS_PTR(head);
+ rval_status = PR_JoinThread(wthrp->thread);
+ PR_ASSERT(PR_SUCCESS == rval_status);
+ PR_DELETE(wthrp);
+ }
+
+ /*
+ * Delete queued jobs
+ */
+ while (!PR_CLIST_IS_EMPTY(&tpool->jobq.list)) {
+ PRJob *jobp;
+
+ head = PR_LIST_HEAD(&tpool->jobq.list);
+ PR_REMOVE_AND_INIT_LINK(head);
+ jobp = JOB_LINKS_PTR(head);
+ tpool->jobq.cnt--;
+ delete_job(jobp);
+ }
+
+ /* delete io jobs */
+ while (!PR_CLIST_IS_EMPTY(&tpool->ioq.list)) {
+ PRJob *jobp;
+
+ head = PR_LIST_HEAD(&tpool->ioq.list);
+ PR_REMOVE_AND_INIT_LINK(head);
+ tpool->ioq.cnt--;
+ jobp = JOB_LINKS_PTR(head);
+ delete_job(jobp);
+ }
+
+ /* delete timer jobs */
+ while (!PR_CLIST_IS_EMPTY(&tpool->timerq.list)) {
+ PRJob *jobp;
+
+ head = PR_LIST_HEAD(&tpool->timerq.list);
+ PR_REMOVE_AND_INIT_LINK(head);
+ tpool->timerq.cnt--;
+ jobp = JOB_LINKS_PTR(head);
+ delete_job(jobp);
+ }
+
+ PR_ASSERT(0 == tpool->jobq.cnt);
+ PR_ASSERT(0 == tpool->ioq.cnt);
+ PR_ASSERT(0 == tpool->timerq.cnt);
+
+ delete_threadpool(tpool);
+ return rval;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtrace.c b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtrace.c
new file mode 100644
index 00000000..d26f5027
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/misc/prtrace.c
@@ -0,0 +1,922 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** prtrace.c -- NSPR Trace Instrumentation
+**
+** Implement the API defined in prtrace.h
+**
+**
+**
+*/
+
+#include <string.h>
+#include "prtrace.h"
+#include "prclist.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prenv.h"
+#include "prmem.h"
+#include "prerror.h"
+
+
+#define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 )
+#define DEFAULT_BUFFER_SEGMENTS 2
+
+/*
+** Enumerate states in a RName structure
+*/
+typedef enum TraceState
+{
+ Running = 1,
+ Suspended = 2
+} TraceState;
+
+/*
+** Define QName structure
+*/
+typedef struct QName
+{
+ PRCList link;
+ PRCList rNameList;
+ char name[PRTRACE_NAME_MAX+1];
+} QName;
+
+/*
+** Define RName structure
+*/
+typedef struct RName
+{
+ PRCList link;
+ PRLock *lock;
+ QName *qName;
+ TraceState state;
+ char name[PRTRACE_NAME_MAX+1];
+ char desc[PRTRACE_DESC_MAX+1];
+} RName;
+
+
+/*
+** The Trace Facility database
+**
+*/
+static PRLogModuleInfo *lm;
+
+static PRLock *traceLock; /* Facility Lock */
+static PRCList qNameList; /* anchor to all QName structures */
+static TraceState traceState = Running;
+
+/*
+** in-memory trace buffer controls
+*/
+static PRTraceEntry *tBuf; /* pointer to buffer */
+static PRInt32 bufSize; /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */
+static volatile PRInt32 next; /* index to next PRTraceEntry */
+static PRInt32 last; /* index of highest numbered trace entry */
+
+/*
+** Real-time buffer capture controls
+*/
+static PRInt32 fetchLastSeen = 0;
+static PRBool fetchLostData = PR_FALSE;
+
+/*
+** Buffer write-to-file controls
+*/
+static PRLock *logLock; /* Sync lock */
+static PRCondVar *logCVar; /* Sync Condidtion Variable */
+/*
+** Inter-thread state communication.
+** Controling thread writes to logOrder under protection of logCVar
+** the logging thread reads logOrder and sets logState on Notify.
+**
+** logSegments, logCount, logLostData must be read and written under
+** protection of logLock, logCVar.
+**
+*/
+static enum LogState
+{
+ LogNotRunning, /* Initial state */
+ LogReset, /* Causes logger to re-calc controls */
+ LogActive, /* Logging in progress, set only by log thread */
+ LogSuspend, /* Suspend Logging */
+ LogResume, /* Resume Logging => LogActive */
+ LogStop /* Stop the log thread */
+} logOrder, logState, localState; /* controlling state variables */
+static PRInt32 logSegments; /* Number of buffer segments */
+static PRInt32 logEntries; /* number of Trace Entries in the buffer */
+static PRInt32 logEntriesPerSegment; /* number of PRTraceEntries per buffer segment */
+static PRInt32 logSegSize; /* size of buffer segment */
+static PRInt32 logCount; /* number of segments pending output */
+static PRInt32 logLostData; /* number of lost log buffer segments */
+
+/*
+** end Trace Database
+**
+*/
+
+/*
+** _PR_InitializeTrace() -- Initialize the trace facility
+*/
+static void NewTraceBuffer( PRInt32 size )
+{
+ /*
+ ** calculate the size of the buffer
+ ** round down so that each segment has the same number of
+ ** trace entries
+ */
+ logSegments = DEFAULT_BUFFER_SEGMENTS;
+ logEntries = size / sizeof(PRTraceEntry);
+ logEntriesPerSegment = logEntries / logSegments;
+ logEntries = logSegments * logEntriesPerSegment;
+ bufSize = logEntries * sizeof(PRTraceEntry);
+ logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry);
+ PR_ASSERT( bufSize != 0);
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld",
+ logSegments, logEntries, logEntriesPerSegment, logSegSize ));
+
+
+ tBuf = PR_Malloc( bufSize );
+ if ( tBuf == NULL )
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PRTrace: Failed to get trace buffer"));
+ PR_ASSERT( 0 );
+ }
+ else
+ {
+ PR_LOG( lm, PR_LOG_NOTICE,
+ ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf));
+ }
+
+ next = 0;
+ last = logEntries -1;
+ logCount = 0;
+ logLostData = PR_TRUE; /* not really on first call */
+ logOrder = LogReset;
+
+} /* end NewTraceBuffer() */
+
+/*
+** _PR_InitializeTrace() -- Initialize the trace facility
+*/
+static void _PR_InitializeTrace( void )
+{
+ /* The lock pointer better be null on this call */
+ PR_ASSERT( traceLock == NULL );
+
+ traceLock = PR_NewLock();
+ PR_ASSERT( traceLock != NULL );
+
+ PR_Lock( traceLock );
+
+ PR_INIT_CLIST( &qNameList );
+
+ lm = PR_NewLogModule("trace");
+
+ bufSize = DEFAULT_TRACE_BUFSIZE;
+ NewTraceBuffer( bufSize );
+
+ /* Initialize logging controls */
+ logLock = PR_NewLock();
+ logCVar = PR_NewCondVar( logLock );
+
+ PR_Unlock( traceLock );
+ return;
+} /* end _PR_InitializeTrace() */
+
+/*
+** Create a Trace Handle
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_CreateTrace(
+ const char *qName, /* QName for this trace handle */
+ const char *rName, /* RName for this trace handle */
+ const char *description /* description for this trace handle */
+)
+{
+ QName *qnp;
+ RName *rnp;
+ PRBool matchQname = PR_FALSE;
+
+ /* Self initialize, if necessary */
+ if ( traceLock == NULL )
+ _PR_InitializeTrace();
+
+ /* Validate input arguments */
+ PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX );
+ PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX );
+ PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX );
+
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName));
+
+ /* Lock the Facility */
+ PR_Lock( traceLock );
+
+ /* Do we already have a matching QName? */
+ if (!PR_CLIST_IS_EMPTY( &qNameList ))
+ {
+ qnp = (QName *) PR_LIST_HEAD( &qNameList );
+ do {
+ if ( strcmp(qnp->name, qName) == 0)
+ {
+ matchQname = PR_TRUE;
+ break;
+ }
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+ } while( qnp != (QName *)PR_LIST_HEAD( &qNameList ));
+ }
+ /*
+ ** If we did not find a matching QName,
+ ** allocate one and initialize it.
+ ** link it onto the qNameList.
+ **
+ */
+ if ( matchQname != PR_TRUE )
+ {
+ qnp = PR_NEWZAP( QName );
+ PR_ASSERT( qnp != NULL );
+ PR_INIT_CLIST( &qnp->link );
+ PR_INIT_CLIST( &qnp->rNameList );
+ strcpy( qnp->name, qName );
+ PR_APPEND_LINK( &qnp->link, &qNameList );
+ }
+
+ /* Do we already have a matching RName? */
+ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ {
+ rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList );
+ do {
+ /*
+ ** No duplicate RNames are allowed within a QName
+ **
+ */
+ PR_ASSERT( strcmp(rnp->name, rName));
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+ } while( rnp != (RName *)PR_LIST_HEAD( &qnp->rNameList ));
+ }
+
+ /* Get a new RName structure; initialize its members */
+ rnp = PR_NEWZAP( RName );
+ PR_ASSERT( rnp != NULL );
+ PR_INIT_CLIST( &rnp->link );
+ strcpy( rnp->name, rName );
+ strcpy( rnp->desc, description );
+ rnp->lock = PR_NewLock();
+ rnp->state = Running;
+ if ( rnp->lock == NULL )
+ {
+ PR_ASSERT(0);
+ }
+
+ PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */
+ rnp->qName = qnp; /* point the RName to the QName */
+
+ /* Unlock the Facility */
+ PR_Unlock( traceLock );
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t",
+ qName, qnp, rName, rnp ));
+
+ return((PRTraceHandle)rnp);
+} /* end PR_CreateTrace() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyTrace(
+ PRTraceHandle handle /* Handle to be destroyed */
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s",
+ qnp->name, rnp->name));
+
+ /* Lock the Facility */
+ PR_Lock( traceLock );
+
+ /*
+ ** Remove RName from the list of RNames in QName
+ ** and free RName
+ */
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p",
+ rnp->name, rnp));
+ PR_REMOVE_LINK( &rnp->link );
+ PR_Free( rnp->lock );
+ PR_DELETE( rnp );
+
+ /*
+ ** If this is the last RName within QName
+ ** remove QName from the qNameList and free it
+ */
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) )
+ {
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p",
+ qnp->name, qnp));
+ PR_REMOVE_LINK( &qnp->link );
+ PR_DELETE( qnp );
+ }
+
+ /* Unlock the Facility */
+ PR_Unlock( traceLock );
+ return;
+} /* end PR_DestroyTrace() */
+
+/*
+** Create a TraceEntry in the trace buffer
+*/
+PR_IMPLEMENT(void)
+ PR_Trace(
+ PRTraceHandle handle, /* use this trace handle */
+ PRUint32 userData0, /* User supplied data word 0 */
+ PRUint32 userData1, /* User supplied data word 1 */
+ PRUint32 userData2, /* User supplied data word 2 */
+ PRUint32 userData3, /* User supplied data word 3 */
+ PRUint32 userData4, /* User supplied data word 4 */
+ PRUint32 userData5, /* User supplied data word 5 */
+ PRUint32 userData6, /* User supplied data word 6 */
+ PRUint32 userData7 /* User supplied data word 7 */
+)
+{
+ PRTraceEntry *tep;
+ PRInt32 mark;
+
+ if ( (traceState == Suspended )
+ || ( ((RName *)handle)->state == Suspended ))
+ return;
+
+ /*
+ ** Get the next trace entry slot w/ minimum delay
+ */
+ PR_Lock( traceLock );
+
+ tep = &tBuf[next++];
+ if ( next > last )
+ next = 0;
+ if ( fetchLostData == PR_FALSE && next == fetchLastSeen )
+ fetchLostData = PR_TRUE;
+
+ mark = next;
+
+ PR_Unlock( traceLock );
+
+ /*
+ ** We have a trace entry. Fill it in.
+ */
+ tep->thread = PR_GetCurrentThread();
+ tep->handle = handle;
+ tep->time = PR_Now();
+ tep->userData[0] = userData0;
+ tep->userData[1] = userData1;
+ tep->userData[2] = userData2;
+ tep->userData[3] = userData3;
+ tep->userData[4] = userData4;
+ tep->userData[5] = userData5;
+ tep->userData[6] = userData6;
+ tep->userData[7] = userData7;
+
+ /* When buffer segment is full, signal trace log thread to run */
+ if (( mark % logEntriesPerSegment) == 0 )
+ {
+ PR_Lock( logLock );
+ logCount++;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ /*
+ ** Gh0D! This is awful!
+ ** Anyway, to minimize lost trace data segments,
+ ** I inserted the PR_Sleep(0) to cause a context switch
+ ** so that the log thread could run.
+ ** I know, it perturbs the universe and may cause
+ ** funny things to happen in the optimized builds.
+ ** Take it out, loose data; leave it in risk Heisenberg.
+ */
+ /* PR_Sleep(0); */
+ }
+
+ return;
+} /* end PR_Trace() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_SetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+)
+{
+ RName * rnp;
+
+ switch ( command )
+ {
+ case PRTraceBufSize :
+ PR_Lock( traceLock );
+ PR_Free( tBuf );
+ bufSize = *(PRInt32 *)value;
+ NewTraceBuffer( bufSize );
+ PR_Unlock( traceLock );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize));
+ break;
+
+ case PRTraceEnable :
+ rnp = *(RName **)value;
+ rnp->state = Running;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceEnable: %p", rnp));
+ break;
+
+ case PRTraceDisable :
+ rnp = *(RName **)value;
+ rnp->state = Suspended;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceDisable: %p", rnp));
+ break;
+
+ case PRTraceSuspend :
+ traceState = Suspended;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceSuspend"));
+ break;
+
+ case PRTraceResume :
+ traceState = Running;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceResume"));
+ break;
+
+ case PRTraceSuspendRecording :
+ PR_Lock( logLock );
+ logOrder = LogSuspend;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceSuspendRecording"));
+ break;
+
+ case PRTraceResumeRecording :
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceResumeRecording"));
+ if ( logState != LogSuspend )
+ break;
+ PR_Lock( logLock );
+ logOrder = LogResume;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ break;
+
+ case PRTraceStopRecording :
+ PR_Lock( logLock );
+ logOrder = LogStop;
+ PR_NotifyCondVar( logCVar );
+ PR_Unlock( logLock );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceStopRecording"));
+ break;
+
+ case PRTraceLockHandles :
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceLockTraceHandles"));
+ PR_Lock( traceLock );
+ break;
+
+ case PRTraceUnLockHandles :
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRSetTraceOption: PRTraceUnLockHandles"));
+ PR_Lock( traceLock );
+ break;
+
+ default:
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PRSetTraceOption: Invalid command %ld", command ));
+ PR_ASSERT( 0 );
+ break;
+ } /* end switch() */
+ return;
+} /* end PR_SetTraceOption() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_GetTraceOption(
+ PRTraceOption command, /* One of the enumerated values */
+ void *value /* command value or NULL */
+)
+{
+ switch ( command )
+ {
+ case PRTraceBufSize :
+ *((PRInt32 *)value) = bufSize;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PRGetTraceOption: PRTraceBufSize: %ld", bufSize ));
+ break;
+
+ default:
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PRGetTraceOption: Invalid command %ld", command ));
+ PR_ASSERT( 0 );
+ break;
+ } /* end switch() */
+ return;
+} /* end PR_GetTraceOption() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_GetTraceHandleFromName(
+ const char *qName, /* QName search argument */
+ const char *rName /* RName search argument */
+)
+{
+ const char *qn, *rn, *desc;
+ PRTraceHandle qh, rh = NULL;
+ RName *rnp = NULL;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t"
+ "QName: %s, RName: %s", qName, rName ));
+
+ qh = PR_FindNextTraceQname( NULL );
+ while (qh != NULL)
+ {
+ rh = PR_FindNextTraceRname( NULL, qh );
+ while ( rh != NULL )
+ {
+ PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc );
+ if ( (strcmp( qName, qn ) == 0)
+ && (strcmp( rName, rn ) == 0 ))
+ {
+ rnp = (RName *)rh;
+ goto foundIt;
+ }
+ rh = PR_FindNextTraceRname( rh, qh );
+ }
+ qh = PR_FindNextTraceQname( NULL );
+ }
+
+foundIt:
+ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp ));
+ return(rh);
+} /* end PR_GetTraceHandleFromName() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_GetTraceNameFromHandle(
+ PRTraceHandle handle, /* handle as search argument */
+ const char **qName, /* pointer to associated QName */
+ const char **rName, /* pointer to associated RName */
+ const char **description /* pointer to associated description */
+)
+{
+ RName *rnp = (RName *)handle;
+ QName *qnp = rnp->qName;
+
+ *qName = qnp->name;
+ *rName = rnp->name;
+ *description = rnp->desc;
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetConterNameFromHandle: "
+ "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s",
+ qnp, rnp, qnp->name, rnp->name, rnp->desc ));
+
+ return;
+} /* end PR_GetTraceNameFromHandle() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_FindNextTraceQname(
+ PRTraceHandle handle
+)
+{
+ QName *qnp = (QName *)handle;
+
+ if ( PR_CLIST_IS_EMPTY( &qNameList ))
+ qnp = NULL;
+ else if ( qnp == NULL )
+ qnp = (QName *)PR_LIST_HEAD( &qNameList );
+ else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList )
+ qnp = NULL;
+ else
+ qnp = (QName *)PR_NEXT_LINK( &qnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p",
+ handle, qnp ));
+
+ return((PRTraceHandle)qnp);
+} /* end PR_FindNextTraceQname() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRTraceHandle)
+ PR_FindNextTraceRname(
+ PRTraceHandle rhandle,
+ PRTraceHandle qhandle
+)
+{
+ RName *rnp = (RName *)rhandle;
+ QName *qnp = (QName *)qhandle;
+
+
+ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ))
+ rnp = NULL;
+ else if ( rnp == NULL )
+ rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList );
+ else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList )
+ rnp = NULL;
+ else
+ rnp = (RName *)PR_NEXT_LINK( &rnp->link );
+
+ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p",
+ rhandle, qhandle, rnp ));
+
+ return((PRTraceHandle)rnp);
+} /* end PR_FindNextTraceRname() */
+
+/*
+**
+*/
+static PRFileDesc * InitializeRecording( void )
+{
+ char *logFileName;
+ PRFileDesc *logFile;
+
+ /* Self initialize, if necessary */
+ if ( traceLock == NULL )
+ _PR_InitializeTrace();
+
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PR_RecordTraceEntries: begins"));
+
+ logLostData = 0; /* reset at entry */
+ logState = LogReset;
+
+ /* Get the filename for the logfile from the environment */
+ logFileName = PR_GetEnv( "NSPR_TRACE_LOG" );
+ if ( logFileName == NULL )
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: Environment variable not defined. Exiting"));
+ return NULL;
+ }
+
+ /* Open the logfile */
+ logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 );
+ if ( logFile == NULL )
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld",
+ logFileName, PR_GetOSError()));
+ return NULL;
+ }
+ return logFile;
+} /* end InitializeRecording() */
+
+/*
+**
+*/
+static void ProcessOrders( void )
+{
+ switch ( logOrder )
+ {
+ case LogReset :
+ logOrder = logState = localState;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogReset"));
+ break;
+
+ case LogSuspend :
+ localState = logOrder = logState = LogSuspend;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogSuspend"));
+ break;
+
+ case LogResume :
+ localState = logOrder = logState = LogActive;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogResume"));
+ break;
+
+ case LogStop :
+ logOrder = logState = LogStop;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: LogStop"));
+ break;
+
+ default :
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: Invalid logOrder: %ld", logOrder ));
+ PR_ASSERT( 0 );
+ break;
+ } /* end switch() */
+ return ;
+} /* end ProcessOrders() */
+
+/*
+**
+*/
+static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount )
+{
+ PRInt32 rc;
+
+
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount));
+ rc = PR_Write( logFile, buf , amount );
+ if ( rc == -1 )
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() ));
+ else if ( rc != amount )
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc));
+ else
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount));
+
+ return;
+} /* end WriteTraceSegment() */
+
+/*
+**
+*/
+PR_IMPLEMENT(void)
+ PR_RecordTraceEntries(
+ void
+)
+{
+ PRFileDesc *logFile;
+ PRInt32 lostSegments;
+ PRInt32 currentSegment = 0;
+ void *buf;
+ PRBool doWrite;
+
+ logFile = InitializeRecording();
+ if ( logFile == NULL )
+ {
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PR_RecordTraceEntries: Failed to initialize"));
+ return;
+ }
+
+ /* Do this until told to stop */
+ while ( logState != LogStop )
+ {
+
+ PR_Lock( logLock );
+
+ while ( (logCount == 0) && ( logOrder == logState ) )
+ PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT );
+
+ /* Handle state transitions */
+ if ( logOrder != logState )
+ ProcessOrders();
+
+ /* recalculate local controls */
+ if ( logCount )
+ {
+ lostSegments = logCount - logSegments;
+ if ( lostSegments > 0 )
+ {
+ logLostData += ( logCount - logSegments );
+ logCount = (logCount % logSegments);
+ currentSegment = logCount;
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("PR_RecordTraceEntries: LostData segments: %ld", logLostData));
+ }
+ else
+ {
+ logCount--;
+ }
+
+ buf = tBuf + ( logEntriesPerSegment * currentSegment );
+ if (++currentSegment >= logSegments )
+ currentSegment = 0;
+ doWrite = PR_TRUE;
+ }
+ else
+ doWrite = PR_FALSE;
+
+ PR_Unlock( logLock );
+
+ if ( doWrite == PR_TRUE )
+ {
+ if ( localState != LogSuspend )
+ WriteTraceSegment( logFile, buf, logSegSize );
+ else
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: PR_Write(): is suspended" ));
+ }
+
+ } /* end while(logState...) */
+
+ PR_Close( logFile );
+ PR_LOG( lm, PR_LOG_DEBUG,
+ ("RecordTraceEntries: exiting"));
+ return;
+} /* end PR_RecordTraceEntries() */
+
+/*
+**
+*/
+PR_IMPLEMENT(PRIntn)
+ PR_GetTraceEntries(
+ PRTraceEntry *buffer, /* where to write output */
+ PRInt32 count, /* number to get */
+ PRInt32 *found /* number you got */
+)
+{
+ PRInt32 rc;
+ PRInt32 copied = 0;
+
+ PR_Lock( traceLock );
+
+ /*
+ ** Depending on where the LastSeen and Next indices are,
+ ** copy the trace buffer in one or two pieces.
+ */
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen));
+
+ if ( fetchLastSeen <= next )
+ {
+ while (( count-- > 0 ) && (fetchLastSeen < next ))
+ {
+ *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+ }
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+ }
+ else /* copy in 2 parts */
+ {
+ while ( count-- > 0 && fetchLastSeen <= last )
+ {
+ *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+ }
+ fetchLastSeen = 0;
+
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+
+ while ( count-- > 0 && fetchLastSeen < next )
+ {
+ *(buffer + copied++) = *(tBuf + fetchLastSeen++);
+ }
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen));
+ }
+
+ *found = copied;
+ rc = ( fetchLostData == PR_TRUE )? 1 : 0;
+ fetchLostData = PR_FALSE;
+
+ PR_Unlock( traceLock );
+ return rc;
+} /* end PR_GetTraceEntries() */
+
+/* end prtrace.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/nspr.def b/src/libs/xpcom18a4/nsprpub/pr/src/nspr.def
new file mode 100644
index 00000000..144df2ca
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/nspr.def
@@ -0,0 +1,457 @@
+;+#
+;+# 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 Portable Runtime (NSPR).
+;+#
+;+# The Initial Developer of the Original Code is Netscape
+;+# Communications Corporation. Portions created by Netscape are
+;+# Copyright (C) 2002-2003 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.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+#
+;+NSPR_4.0 {
+;+ global:
+LIBRARY nspr4 ;-
+EXPORTS ;-
+ LL_MaxInt;
+ LL_MinInt;
+ LL_Zero;
+ PR_Abort;
+ PR_AddToCounter;
+ PR_Accept;
+ PR_AcceptRead;
+ PR_Access;
+ PR_AddWaitFileDesc;
+ PR_AllocFileDesc;
+ PR_Assert;
+ PR_AtomicAdd;
+ PR_AtomicDecrement;
+ PR_AtomicIncrement;
+ PR_AtomicSet;
+ PR_AttachSharedMemory;
+ PR_AttachThread;
+ PR_Available;
+ PR_Available64;
+ PR_Bind;
+ PR_BlockClockInterrupts;
+ PR_BlockInterrupt;
+ PR_CEnterMonitor;
+ PR_CExitMonitor;
+ PR_CNotify;
+ PR_CNotifyAll;
+ PR_CSetOnMonitorRecycle;
+ PR_CWait;
+ PR_CallOnce;
+ PR_Calloc;
+ PR_CancelJob;
+ PR_CancelWaitFileDesc;
+ PR_CancelWaitGroup;
+ PR_CeilingLog2;
+ PR_ChangeFileDescNativeHandle;
+ PR_Cleanup;
+ PR_ClearInterrupt;
+ PR_ClearThreadGCAble;
+ PR_Close;
+ PR_CloseDir;
+ PR_CloseFileMap;
+ PR_CloseSemaphore;
+ PR_CloseSharedMemory;
+ PR_Connect;
+ PR_CreateCounter;
+ PR_ConvertIPv4AddrToIPv6;
+ PR_CreateAlarm;
+ PR_CreateFileMap;
+ PR_CreateIOLayerStub;
+ PR_CreateOrderedLock;
+ PR_CreateMWaitEnumerator;
+ PR_CreatePipe;
+ PR_CreateProcess;
+ PR_CreateProcessDetached;
+ PR_CreateSocketPollFd;
+ PR_CreateStack;
+ PR_CreateThread;
+ PR_CreateThreadGCAble;
+ PR_CreateTrace;
+ PR_CreateThreadPool;
+ PR_DecrementCounter;
+ PR_CreateWaitGroup;
+ PR_Delete;
+ PR_DeleteSemaphore;
+ PR_DeleteSharedMemory;
+ PR_DestroyAlarm;
+ PR_DestroyCounter;
+ PR_DestroyCondVar;
+ PR_DestroyLock;
+ PR_DestroyMWaitEnumerator;
+ PR_DestroyOrderedLock;
+ PR_DestroyMonitor;
+ PR_DestroyPollableEvent;
+ PR_DestroyProcessAttr;
+ PR_DestroyRWLock;
+ PR_DestroySem;
+ PR_DestroySocketPollFd;
+ PR_DestroyTrace;
+ PR_DestroyStack;
+ PR_DestroyWaitGroup;
+ PR_DetachProcess;
+ PR_DetachSharedMemory;
+ PR_DetachThread;
+ PR_DisableClockInterrupts;
+ PR_EnableClockInterrupts;
+ PR_EnterMonitor;
+ PR_EnumerateHostEnt;
+ PR_EnumerateThreads;
+ PR_EnumerateWaitGroup;
+ PR_ErrorInstallCallback;
+ PR_ErrorInstallTable;
+ PR_ErrorLanguages;
+ PR_ErrorToName;
+ PR_ErrorToString;
+ PR_ExitMonitor;
+ PR_ExplodeTime;
+ PR_ExportFileMapAsString;
+ PR_FD_CLR;
+ PR_FD_ISSET;
+ PR_FD_NCLR;
+ PR_FD_NISSET;
+ PR_FD_NSET;
+ PR_FD_SET;
+ PR_FD_ZERO;
+ PR_FileDesc2NativeHandle;
+ PR_FindSymbol;
+ PR_FindSymbolAndLibrary;
+ PR_FloorLog2;
+ PR_FormatTime;
+ PR_FindNextCounterQname;
+ PR_FindNextCounterRname;
+ PR_FindNextTraceQname;
+ PR_FindNextTraceRname;
+ PR_FormatTimeUSEnglish;
+ PR_Free;
+ PR_FreeLibraryName;
+ PR_GMTParameters;
+ PR_GetConnectStatus;
+ PR_GetCurrentThread;
+ PR_GetDefaultIOMethods;
+ PR_GetDescType;
+ PR_GetDirectorySeparator;
+ PR_GetCounter;
+ PR_GetCounterHandleFromName;
+ PR_GetCounterNameFromHandle;
+ PR_GetDirectorySepartor;
+ PR_GetEnv;
+ PR_GetError;
+ PR_GetErrorText;
+ PR_GetErrorTextLength;
+ PR_GetFileInfo;
+ PR_GetFileInfo64;
+ PR_GetFileMethods;
+ PR_GetGCRegisters;
+ PR_GetHostByAddr;
+ PR_GetHostByName;
+ PR_GetIPNodeByName;
+ PR_GetIdentitiesLayer;
+ PR_GetInheritedFD;
+ PR_GetInheritedFileMap;
+ PR_GetLayersIdentity;
+ PR_GetLibraryName;
+ PR_GetLibraryPath;
+ PR_GetMonitorEntryCount;
+ PR_GetNameForIdentity;
+ PR_GetOSError;
+ PR_GetOpenFileInfo;
+ PR_GetOpenFileInfo64;
+ PR_GetPageShift;
+ PR_GetPageSize;
+ PR_GetPeerName;
+ PR_GetPipeMethods;
+ PR_GetProtoByName;
+ PR_GetProtoByNumber;
+ PR_GetRandomNoise;
+ PR_GetSP;
+ PR_GetSockName;
+ PR_GetSocketOption;
+ PR_GetSpecialFD;
+ PR_GetStackSpaceLeft;
+ PR_GetSysfdTableMax;
+ PR_GetSystemInfo;
+ PR_GetTCPMethods;
+ PR_GetThreadAffinityMask;
+ PR_GetThreadID;
+ PR_GetThreadPriority;
+ PR_GetThreadPrivate;
+ PR_GetThreadScope;
+ PR_GetThreadState;
+ PR_GetThreadType;
+ PR_GetUDPMethods;
+ PR_GetUniqueIdentity;
+ PR_ImplodeTime;
+ PR_ImportFile;
+ PR_ImportFileMapFromString;
+ PR_ImportTCPSocket;
+ PR_ImportUDPSocket;
+ PR_GetTraceEntries;
+ PR_GetTraceHandleFromName;
+ PR_GetTraceNameFromHandle;
+ PR_GetTraceOption;
+ PR_Init;
+ PR_Initialize;
+ PR_InitializeNetAddr;
+ PR_Initialized;
+ PR_Interrupt;
+ PR_IntervalNow;
+ PR_IntervalToMicroseconds;
+ PR_IntervalToMilliseconds;
+ PR_IncrementCounter;
+ PR_IntervalToSeconds;
+ PR_IsNetAddrType;
+ PR_JoinJob;
+ PR_JoinThread;
+ PR_JoinThreadPool;
+ PR_KillProcess;
+ PR_Listen;
+ PR_LoadLibrary;
+ PR_LoadLibraryWithFlags;
+ PR_LoadStaticLibrary;
+ PR_LocalTimeParameters;
+ PR_Lock;
+ PR_LockFile;
+ PR_LogFlush;
+ PR_LogPrint;
+ PR_MakeDir;
+ PR_Malloc;
+ PR_MemMap;
+ PR_MemUnmap;
+ PR_MicrosecondsToInterval;
+ PR_MillisecondsToInterval;
+ PR_LockOrderedLock;
+ PR_MkDir;
+ PR_NetAddrToString;
+ PR_NewCondVar;
+ PR_NewLock;
+ PR_NewLogModule;
+ PR_NewMonitor;
+ PR_NewNamedMonitor;
+ PR_NewPollableEvent;
+ PR_NewProcessAttr;
+ PR_NewRWLock;
+ PR_NewSem;
+ PR_NewTCPSocket;
+ PR_NewTCPSocketPair;
+ PR_NewThreadPrivateIndex;
+ PR_NewUDPSocket;
+ PR_NormalizeTime;
+ PR_Notify;
+ PR_NotifyAll;
+ PR_NotifyAllCondVar;
+ PR_NotifyCondVar;
+ PR_Now;
+ PR_Open;
+ PR_OpenAnonFileMap;
+ PR_OpenDir;
+ PR_OpenFile;
+ PR_OpenSemaphore;
+ PR_OpenSharedMemory;
+ PR_OpenTCPSocket;
+ PR_OpenUDPSocket;
+ PR_ParseTimeString;
+ PR_Poll;
+ PR_PopIOLayer;
+ PR_PostSem;
+ PR_PostSemaphore;
+ PR_ProcessAttrSetCurrentDirectory;
+ PR_ProcessAttrSetInheritableFD;
+ PR_ProcessAttrSetInheritableFileMap;
+ PR_ProcessAttrSetStdioRedirect;
+ PR_ProcessExit;
+ PR_PushIOLayer;
+ PR_QueueJob;
+ PR_QueueJob_Accept;
+ PR_QueueJob_Connect;
+ PR_QueueJob_Read;
+ PR_QueueJob_Timer;
+ PR_QueueJob_Write;
+ PR_RWLock_Rlock;
+ PR_RWLock_Unlock;
+ PR_RWLock_Wlock;
+ PR_Read;
+ PR_ReadDir;
+ PR_Realloc;
+ PR_Recv;
+ PR_RecvFrom;
+ PR_Rename;
+ PR_ResetAlarm;
+ PR_ResetProcessAttr;
+ PR_ResumeAll;
+ PR_RmDir;
+ PR_ScanStackPointers;
+ PR_RecordTraceEntries;
+ PR_SecondsToInterval;
+ PR_Seek;
+ PR_Seek64;
+ PR_Select;
+ PR_Send;
+ PR_SendFile;
+ PR_SendTo;
+ PR_SetAlarm;
+ PR_SetConcurrency;
+ PR_SetError;
+ PR_SetErrorText;
+ PR_SetFDCacheSize;
+ PR_SetFDInheritable;
+ PR_SetLibraryPath;
+ PR_SetLogBuffering;
+ PR_SetLogFile;
+ PR_SetNetAddr;
+ PR_SetPollableEvent;
+ PR_SetSocketOption;
+ PR_SetCounter;
+ PR_SetStdioRedirect;
+ PR_SetSysfdTableSize;
+ PR_SetThreadAffinityMask;
+ PR_SetThreadDumpProc;
+ PR_SetThreadGCAble;
+ PR_SetThreadPriority;
+ PR_SetThreadPrivate;
+ PR_SetThreadRecycleMode;
+ PR_Shutdown;
+ PR_ShutdownThreadPool;
+ PR_Sleep;
+ PR_Socket;
+ PR_StackPop;
+ PR_StackPush;
+ PR_Stat;
+ PR_StringToNetAddr;
+ PR_SuspendAll;
+ PR_Sync;
+ PR_TLockFile;
+ PR_ThreadScanStackPointers;
+ PR_SetTraceOption;
+ PR_TicksPerSecond;
+ PR_TransmitFile;
+ PR_USPacificTimeParameters;
+ PR_UnblockClockInterrupts;
+ PR_UnblockInterrupt;
+ PR_UnloadLibrary;
+ PR_SubtractFromCounter;
+ PR_Unlock;
+ PR_UnlockFile;
+ PR_VersionCheck;
+ PR_Wait;
+ PR_WaitCondVar;
+ PR_WaitForPollableEvent;
+ PR_Trace;
+ PR_WaitProcess;
+ PR_WaitRecvReady;
+ PR_WaitSem;
+ PR_WaitSemaphore;
+ PR_Write;
+ PR_Writev;
+ PR_Yield;
+ PR_UnlockOrderedLock;
+ PR_cnvtf;
+ PR_dtoa;
+ PR_fprintf;
+ PR_htonl;
+ PR_htonll;
+ PR_htons;
+ PR_ntohl;
+ PR_ntohll;
+ PR_ntohs;
+ PR_smprintf;
+ PR_smprintf_free;
+ PR_snprintf;
+ PR_sprintf_append;
+ PR_sscanf;
+ PR_strtod;
+ PR_sxprintf;
+ PR_vfprintf;
+ PR_vsmprintf;
+ PR_vsnprintf;
+ PR_vsprintf_append;
+ PR_vsxprintf;
+ PRP_DestroyNakedCondVar;
+ PRP_NakedBroadcast;
+ PRP_NakedNotify;
+ PRP_NakedWait;
+ PRP_NewNakedCondVar;
+ PRP_TryLock;
+ libVersionPoint;
+;+ local: *;
+;+};
+;+
+;+NSPRprivate {
+;+ global:
+ GetExecutionEnvironment;
+ PT_FPrintStats;
+ SetExecutionEnvironment;
+;+ local: *;
+;+};
+;+
+;+NSPR_4.1 {
+;+ global:
+ PR_ConnectContinue;
+ PR_CreateIOLayer;
+ PR_EmulateAcceptRead;
+ PR_EmulateSendFile;
+ PR_FindFunctionSymbol;
+ PR_FindFunctionSymbolAndLibrary;
+ PR_GetMemMapAlignment;
+ PR_GetNumberOfProcessors;
+ PR_ImportPipe;
+ PR_SetEnv;
+;+} NSPR_4.0;
+;+
+;+NSPR_4.3 {
+;+ global:
+ LL_MaxUint;
+ PR_CallOnceWithArg;
+ PR_GetLibraryFilePathname;
+;+} NSPR_4.1;
+;+
+;+NSPR_4.4 {
+;+ global:
+ PR_GetPathSeparator;
+;+} NSPR_4.3;
+;+
+;+NSPR_4.5 {
+;+ global:
+ PR_EnumerateAddrInfo;
+ PR_FreeAddrInfo;
+ PR_GetAddrInfoByName;
+ PR_GetCanonNameFromAddrInfo;
+;+} NSPR_4.4;
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/nspr.rc b/src/libs/xpcom18a4/nsprpub/pr/src/nspr.rc
new file mode 100644
index 00000000..d3cc2ef3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/nspr.rc
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include <winver.h>
+
+#define MY_LIBNAME "nspr"
+#define MY_FILEDESCRIPTION "NSPR Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if PR_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", PR_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Netscape Portable Runtime\0"
+ VALUE "ProductVersion", PR_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/nspr_symvec.opt b/src/libs/xpcom18a4/nsprpub/pr/src/nspr_symvec.opt
new file mode 100644
index 00000000..b6441372
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/nspr_symvec.opt
@@ -0,0 +1,500 @@
+! Fixed section of symbol vector for LIBNSPR4 (non-debug)
+!
+GSMATCH=LEQUAL,2,7
+case_sensitive=YES
+!
+! --------------------------------------------------------------------------
+! Ident 2,1 introduced for Mozilla 0.9.4
+! Based on NSPR 4.1.2
+! --------------------------------------------------------------------------
+! Ident 2,2 introduced for Mozilla 1.2
+! Based on NSPR 4.2.2?
+! PR_ResumeSet, PR_ResumeTest, and PR_SuspendAllSuspended has been "removed".
+! Only we can't remove the entry points because OJI is linked against NSPR so
+! we have to make an upwardly compatible change:
+! PR_ResumeSet is now PR_VMS_Stub1
+! PR_ResumeTest is now PR_VMS_Stub2
+! PR_SuspendAllSuspended is PR_VMS_Stub3
+! These are stub functions (defined in openvms.c) solely for the purpose of
+! occupying the slots in our fixed section of the symbol table.
+! --------------------------------------------------------------------------
+! Ident 2,3 introduced for Mozilla 1.3
+! Previously we were missing some symbols from NSPR 4.0 and 4.1, so now we
+! include everything that's specified in nspr.def.
+! --------------------------------------------------------------------------
+! Ident 2,4 introduced for Mozilla 1.3 final.
+! 2,3 was still missing some symbols, in particular PR_CreateThread, which
+! is used by OJI. So insert stubs to force the PR_CreateThread entry down
+! to its Mozilla 1.1 (and Java 1.4-0) location so that everyone can play
+! together and be happy.
+! --------------------------------------------------------------------------
+! Ident 2,5 introduced for post Mozilla 1.3.
+! LL_MaxUint introduced. Replaces Stub54.
+! --------------------------------------------------------------------------
+! Ident 2,6 introduced for post Mozilla 1.4.
+! PR_GetPathSeparator introduced in NSPR 4.4.
+! This replaces stub 53
+! --------------------------------------------------------------------------
+! Ident 2,7 introduced for post Mozilla 1.4.
+! PR_GetAddrInfoByName, PR_FreeAddrInfo, PR_EnumerateAddrInfo and
+! PR_GetCanonNameFromAddrInfo introduced in NSPR 4.5.
+! These replace stubs 49-52
+! --------------------------------------------------------------------------
+!
+SYMBOL_VECTOR=(PR_Accept=PROCEDURE)
+SYMBOL_VECTOR=(PR_AcceptRead=PROCEDURE)
+SYMBOL_VECTOR=(PR_Access=PROCEDURE)
+SYMBOL_VECTOR=(PR_AllocFileDesc=PROCEDURE)
+SYMBOL_VECTOR=(PR_Assert=PROCEDURE)
+SYMBOL_VECTOR=(PR_AtomicAdd=PROCEDURE)
+SYMBOL_VECTOR=(PR_AtomicDecrement=PROCEDURE)
+SYMBOL_VECTOR=(PR_AtomicSet=PROCEDURE)
+SYMBOL_VECTOR=(PR_AttachSharedMemory=PROCEDURE)
+SYMBOL_VECTOR=(PR_AttachThread=PROCEDURE)
+SYMBOL_VECTOR=(PR_Available64=PROCEDURE)
+SYMBOL_VECTOR=(PR_Available=PROCEDURE)
+SYMBOL_VECTOR=(PR_Bind=PROCEDURE)
+SYMBOL_VECTOR=(PR_BlockClockInterrupts=PROCEDURE)
+SYMBOL_VECTOR=(PR_BlockInterrupt=PROCEDURE)
+SYMBOL_VECTOR=(PR_CExitMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_CNotify=PROCEDURE)
+SYMBOL_VECTOR=(PR_CNotifyAll=PROCEDURE)
+SYMBOL_VECTOR=(PR_CSetOnMonitorRecycle=PROCEDURE)
+SYMBOL_VECTOR=(PR_CWait=PROCEDURE)
+SYMBOL_VECTOR=(PR_CallOnce=PROCEDURE)
+SYMBOL_VECTOR=(PR_Calloc=PROCEDURE)
+SYMBOL_VECTOR=(PR_CancelJob=PROCEDURE)
+SYMBOL_VECTOR=(PR_CancelWaitFileDesc=PROCEDURE)
+SYMBOL_VECTOR=(PR_CancelWaitGroup=PROCEDURE)
+SYMBOL_VECTOR=(PR_ChangeFileDescNativeHandle=PROCEDURE)
+SYMBOL_VECTOR=(PR_Cleanup=PROCEDURE)
+SYMBOL_VECTOR=(PR_ClearInterrupt=PROCEDURE)
+SYMBOL_VECTOR=(PR_ClearThreadGCAble=PROCEDURE)
+SYMBOL_VECTOR=(PR_Close=PROCEDURE)
+SYMBOL_VECTOR=(PR_CloseDir=PROCEDURE)
+SYMBOL_VECTOR=(PR_CloseFileMap=PROCEDURE)
+SYMBOL_VECTOR=(PR_CloseSemaphore=PROCEDURE)
+SYMBOL_VECTOR=(PR_CloseSharedMemory=PROCEDURE)
+SYMBOL_VECTOR=(PR_Connect=PROCEDURE)
+SYMBOL_VECTOR=(PR_ConnectContinue=PROCEDURE)
+SYMBOL_VECTOR=(PR_ConvertIPv4AddrToIPv6=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateIOLayer=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateIOLayerStub=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateMWaitEnumerator=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreatePipe=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateProcess=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateProcessDetached=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateSocketPollFd=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateStack=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateThreadGCAble=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateWaitGroup=PROCEDURE)
+SYMBOL_VECTOR=(PR_Delete=PROCEDURE)
+SYMBOL_VECTOR=(PR_DeleteSemaphore=PROCEDURE)
+SYMBOL_VECTOR=(PR_DeleteSharedMemory=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyAlarm=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyMWaitEnumerator=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyPollableEvent=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyProcessAttr=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyRWLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroySem=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroySocketPollFd=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyStack=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyWaitGroup=PROCEDURE)
+SYMBOL_VECTOR=(PR_DetachProcess=PROCEDURE)
+SYMBOL_VECTOR=(PR_DetachSharedMemory=PROCEDURE)
+SYMBOL_VECTOR=(PR_DetachThread=PROCEDURE)
+SYMBOL_VECTOR=(PR_DisableClockInterrupts=PROCEDURE)
+SYMBOL_VECTOR=(PR_EmulateAcceptRead=PROCEDURE)
+SYMBOL_VECTOR=(PR_EmulateSendFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_EnableClockInterrupts=PROCEDURE)
+SYMBOL_VECTOR=(PR_EnterMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_EnumerateHostEnt=PROCEDURE)
+SYMBOL_VECTOR=(PR_EnumerateThreads=PROCEDURE)
+SYMBOL_VECTOR=(PR_EnumerateWaitGroup=PROCEDURE)
+SYMBOL_VECTOR=(PR_ErrorInstallCallback=PROCEDURE)
+SYMBOL_VECTOR=(PR_ErrorInstallTable=PROCEDURE)
+SYMBOL_VECTOR=(PR_ErrorLanguages=PROCEDURE)
+SYMBOL_VECTOR=(PR_ErrorToName=PROCEDURE)
+SYMBOL_VECTOR=(PR_ExitMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_ExportFileMapAsString=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_CLR=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_ISSET=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_NCLR=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_NISSET=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_NSET=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_SET=PROCEDURE)
+SYMBOL_VECTOR=(PR_FD_ZERO=PROCEDURE)
+SYMBOL_VECTOR=(PR_FileDesc2NativeHandle=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindFunctionSymbol=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindFunctionSymbolAndLibrary=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindLibrary=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindSymbol=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindSymbolAndLibrary=PROCEDURE)
+SYMBOL_VECTOR=(PR_FloorLog2=PROCEDURE)
+SYMBOL_VECTOR=(PR_FormatTime=PROCEDURE)
+SYMBOL_VECTOR=(PR_FormatTimeUSEnglish=PROCEDURE)
+SYMBOL_VECTOR=(PR_Free=PROCEDURE)
+SYMBOL_VECTOR=(PR_FreeLibraryName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GMTParameters=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetConnectStatus=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetCurrentThread=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetDefaultIOMethods=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetDirectorySepartor=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetError=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetErrorText=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetErrorTextLength=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetFileInfo64=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetFileInfo=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetFileMethods=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetHostByAddr=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetHostByName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetIPNodeByName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetIdentitiesLayer=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetInheritedFD=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetInheritedFileMap=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetLayersIdentity=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetLibraryName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetLibraryPath=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetMemMapAlignment=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetMonitorEntryCount=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetNameForIdentity=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetNumberOfProcessors=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetOSError=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetOpenFileInfo64=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetOpenFileInfo=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetPageShift=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetPeerName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetPipeMethods=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetProtoByName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetProtoByNumber=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetSP=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetSockName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetSocketOption=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetStackSpaceLeft=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetSysfdTableMax=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetSystemInfo=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetTCPMethods=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadAffinityMask=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadID=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadPriority=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadPrivate=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadScope=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadState=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetThreadType=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetUDPMethods=PROCEDURE)
+SYMBOL_VECTOR=(PR_ImplodeTime=PROCEDURE)
+SYMBOL_VECTOR=(PR_ImportFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_ImportFileMapFromString=PROCEDURE)
+SYMBOL_VECTOR=(PR_ImportPipe=PROCEDURE)
+SYMBOL_VECTOR=(PR_ImportTCPSocket=PROCEDURE)
+SYMBOL_VECTOR=(PR_ImportUDPSocket=PROCEDURE)
+SYMBOL_VECTOR=(PR_Init=PROCEDURE)
+SYMBOL_VECTOR=(PR_Initialize=PROCEDURE)
+SYMBOL_VECTOR=(PR_InitializeNetAddr=PROCEDURE)
+SYMBOL_VECTOR=(PR_Initialized=PROCEDURE)
+SYMBOL_VECTOR=(PR_Interrupt=PROCEDURE)
+SYMBOL_VECTOR=(PR_IntervalToMicroseconds=PROCEDURE)
+SYMBOL_VECTOR=(PR_IntervalToMilliseconds=PROCEDURE)
+SYMBOL_VECTOR=(PR_IntervalToSeconds=PROCEDURE)
+SYMBOL_VECTOR=(PR_IsNetAddrType=PROCEDURE)
+SYMBOL_VECTOR=(PR_JoinJob=PROCEDURE)
+SYMBOL_VECTOR=(PR_JoinThread=PROCEDURE)
+SYMBOL_VECTOR=(PR_JoinThreadPool=PROCEDURE)
+SYMBOL_VECTOR=(PR_KillProcess=PROCEDURE)
+SYMBOL_VECTOR=(PR_Listen=PROCEDURE)
+SYMBOL_VECTOR=(PR_LoadLibrary=PROCEDURE)
+SYMBOL_VECTOR=(PR_LoadLibraryWithFlags=PROCEDURE)
+SYMBOL_VECTOR=(PR_LoadStaticLibrary=PROCEDURE)
+SYMBOL_VECTOR=(PR_LocalTimeParameters=PROCEDURE)
+SYMBOL_VECTOR=(PR_Lock=PROCEDURE)
+SYMBOL_VECTOR=(PR_LockFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_LogFlush=PROCEDURE)
+SYMBOL_VECTOR=(PR_LogPrint=PROCEDURE)
+SYMBOL_VECTOR=(PR_MakeDir=PROCEDURE)
+SYMBOL_VECTOR=(PR_MemMap=PROCEDURE)
+SYMBOL_VECTOR=(PR_MemUnmap=PROCEDURE)
+SYMBOL_VECTOR=(PR_MicrosecondsToInterval=PROCEDURE)
+SYMBOL_VECTOR=(PR_MillisecondsToInterval=PROCEDURE)
+SYMBOL_VECTOR=(PR_MkDir=PROCEDURE)
+SYMBOL_VECTOR=(PR_NetAddrToString=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewLogModule=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewNamedMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewProcessAttr=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewSem=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewTCPSocket=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewTCPSocketPair=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewUDPSocket=PROCEDURE)
+SYMBOL_VECTOR=(PR_NormalizeTime=PROCEDURE)
+SYMBOL_VECTOR=(PR_Notify=PROCEDURE)
+SYMBOL_VECTOR=(PR_NotifyAll=PROCEDURE)
+SYMBOL_VECTOR=(PR_NotifyAllCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PR_NotifyCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PR_Open=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenDir=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenSemaphore=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenTCPSocket=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenUDPSocket=PROCEDURE)
+SYMBOL_VECTOR=(PR_ParseTimeString=PROCEDURE)
+SYMBOL_VECTOR=(PR_Poll=PROCEDURE)
+SYMBOL_VECTOR=(PR_PopIOLayer=PROCEDURE)
+SYMBOL_VECTOR=(PR_PostSem=PROCEDURE)
+SYMBOL_VECTOR=(PR_PostSemaphore=PROCEDURE)
+SYMBOL_VECTOR=(PR_ProcessAttrSetCurren1sb1r7b$=PROCEDURE) ! PR_ProcessAttrSetCurrentDirectory
+SYMBOL_VECTOR=(PR_ProcessAttrSetInheri3dpg1d0$=PROCEDURE) ! PR_ProcessAttrSetInheritableFileMap
+SYMBOL_VECTOR=(PR_ProcessAttrSetInheritableFD=PROCEDURE)
+SYMBOL_VECTOR=(PR_ProcessAttrSetStdioRedirect=PROCEDURE)
+SYMBOL_VECTOR=(PR_ProcessExit=PROCEDURE)
+SYMBOL_VECTOR=(PR_PushIOLayer=PROCEDURE)
+SYMBOL_VECTOR=(PR_QueueJob=PROCEDURE)
+SYMBOL_VECTOR=(PR_QueueJob_Accept=PROCEDURE)
+SYMBOL_VECTOR=(PR_QueueJob_Connect=PROCEDURE)
+SYMBOL_VECTOR=(PR_QueueJob_Read=PROCEDURE)
+SYMBOL_VECTOR=(PR_QueueJob_Timer=PROCEDURE)
+SYMBOL_VECTOR=(PR_QueueJob_Write=PROCEDURE)
+SYMBOL_VECTOR=(PR_RWLock_Rlock=PROCEDURE)
+SYMBOL_VECTOR=(PR_RWLock_Unlock=PROCEDURE)
+SYMBOL_VECTOR=(PR_RWLock_Wlock=PROCEDURE)
+SYMBOL_VECTOR=(PR_Read=PROCEDURE)
+SYMBOL_VECTOR=(PR_ReadDir=PROCEDURE)
+SYMBOL_VECTOR=(PR_Realloc=PROCEDURE)
+SYMBOL_VECTOR=(PR_Recv=PROCEDURE)
+SYMBOL_VECTOR=(PR_RecvFrom=PROCEDURE)
+SYMBOL_VECTOR=(PR_Rename=PROCEDURE)
+SYMBOL_VECTOR=(PR_ResetAlarm=PROCEDURE)
+SYMBOL_VECTOR=(PR_ResetProcessAttr=PROCEDURE)
+SYMBOL_VECTOR=(PR_ResumeAll=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub1=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub2=PROCEDURE)
+SYMBOL_VECTOR=(PR_RmDir=PROCEDURE)
+SYMBOL_VECTOR=(PR_ScanStackPointers=PROCEDURE)
+SYMBOL_VECTOR=(PR_SecondsToInterval=PROCEDURE)
+SYMBOL_VECTOR=(PR_Seek64=PROCEDURE)
+SYMBOL_VECTOR=(PR_Seek=PROCEDURE)
+SYMBOL_VECTOR=(PR_Select=PROCEDURE)
+SYMBOL_VECTOR=(PR_Send=PROCEDURE)
+SYMBOL_VECTOR=(PR_SendFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_SendTo=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetAlarm=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetEnv=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetErrorText=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetFDInheritable=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetLogBuffering=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetLogFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetNetAddr=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetPollableEvent=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetSocketOption=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetStdioRedirect=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetSysfdTableSize=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetThreadAffinityMask=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetThreadDumpProc=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetThreadGCAble=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetThreadPriority=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetThreadPrivate=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetThreadRecycleMode=PROCEDURE)
+SYMBOL_VECTOR=(PR_Shutdown=PROCEDURE)
+SYMBOL_VECTOR=(PR_ShutdownThreadPool=PROCEDURE)
+SYMBOL_VECTOR=(PR_Sleep=PROCEDURE)
+SYMBOL_VECTOR=(PR_Socket=PROCEDURE)
+SYMBOL_VECTOR=(PR_StackPop=PROCEDURE)
+SYMBOL_VECTOR=(PR_StackPush=PROCEDURE)
+SYMBOL_VECTOR=(PR_Stat=PROCEDURE)
+SYMBOL_VECTOR=(PR_SuspendAll=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub3=PROCEDURE)
+SYMBOL_VECTOR=(PR_Sync=PROCEDURE)
+SYMBOL_VECTOR=(PR_TLockFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_ThreadScanStackPointers=PROCEDURE)
+SYMBOL_VECTOR=(PR_TicksPerSecond=PROCEDURE)
+SYMBOL_VECTOR=(PR_TransmitFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_USPacificTimeParameters=PROCEDURE)
+SYMBOL_VECTOR=(PR_UnblockClockInterrupts=PROCEDURE)
+SYMBOL_VECTOR=(PR_UnblockInterrupt=PROCEDURE)
+SYMBOL_VECTOR=(PR_UnloadLibrary=PROCEDURE)
+SYMBOL_VECTOR=(PR_Unlock=PROCEDURE)
+SYMBOL_VECTOR=(PR_UnlockFile=PROCEDURE)
+SYMBOL_VECTOR=(PR_Wait=PROCEDURE)
+SYMBOL_VECTOR=(PR_WaitCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PR_WaitForPollableEvent=PROCEDURE)
+SYMBOL_VECTOR=(PR_WaitProcess=PROCEDURE)
+SYMBOL_VECTOR=(PR_WaitRecvReady=PROCEDURE)
+SYMBOL_VECTOR=(PR_WaitSem=PROCEDURE)
+SYMBOL_VECTOR=(PR_WaitSemaphore=PROCEDURE)
+SYMBOL_VECTOR=(PR_Write=PROCEDURE)
+SYMBOL_VECTOR=(PR_Writev=PROCEDURE)
+SYMBOL_VECTOR=(PR_XIsLocked=PROCEDURE)
+SYMBOL_VECTOR=(PR_XLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_XNotify=PROCEDURE)
+SYMBOL_VECTOR=(PR_XNotifyAll=PROCEDURE)
+SYMBOL_VECTOR=(PR_XUnlock=PROCEDURE)
+SYMBOL_VECTOR=(PR_XWait=PROCEDURE)
+SYMBOL_VECTOR=(PR_Yield=PROCEDURE)
+SYMBOL_VECTOR=(PR_cnvtf=PROCEDURE)
+SYMBOL_VECTOR=(PR_dtoa=PROCEDURE)
+SYMBOL_VECTOR=(PR_htonl=PROCEDURE)
+SYMBOL_VECTOR=(PR_htonll=PROCEDURE)
+SYMBOL_VECTOR=(PR_htons=PROCEDURE)
+SYMBOL_VECTOR=(PR_ntohl=PROCEDURE)
+SYMBOL_VECTOR=(PR_ntohll=PROCEDURE)
+SYMBOL_VECTOR=(PR_ntohs=PROCEDURE)
+SYMBOL_VECTOR=(PR_smprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_smprintf_free=PROCEDURE)
+SYMBOL_VECTOR=(PR_sprintf_append=PROCEDURE)
+SYMBOL_VECTOR=(PR_sxprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_vfprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_vsmprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_vsnprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_vsprintf_append=PROCEDURE)
+SYMBOL_VECTOR=(PR_vsxprintf=PROCEDURE)
+!
+! Start of 2,3 additions
+!
+SYMBOL_VECTOR=(LL_MaxInt=PROCEDURE)
+SYMBOL_VECTOR=(LL_MinInt=PROCEDURE)
+SYMBOL_VECTOR=(LL_Zero=PROCEDURE)
+SYMBOL_VECTOR=(PR_Abort=PROCEDURE)
+SYMBOL_VECTOR=(PR_AddToCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_AddWaitFileDesc=PROCEDURE)
+SYMBOL_VECTOR=(PR_AtomicIncrement=PROCEDURE)
+SYMBOL_VECTOR=(PR_CEnterMonitor=PROCEDURE)
+SYMBOL_VECTOR=(PR_CeilingLog2=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateAlarm=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateFileMap=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateOrderedLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateTrace=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateThreadPool=PROCEDURE)
+SYMBOL_VECTOR=(PR_DecrementCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyOrderedLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_DestroyTrace=PROCEDURE)
+SYMBOL_VECTOR=(PR_ErrorToString=PROCEDURE)
+SYMBOL_VECTOR=(PR_ExplodeTime=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindNextCounterQname=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindNextCounterRname=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindNextTraceQname=PROCEDURE)
+SYMBOL_VECTOR=(PR_FindNextTraceRname=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetDescType=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetDirectorySeparator=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetCounterHandleFromName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetCounterNameFromHandle=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetEnv=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetGCRegisters=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetPageSize=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetRandomNoise=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetSpecialFD=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetUniqueIdentity=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetTraceEntries=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetTraceHandleFromName=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetTraceNameFromHandle=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetTraceOption=PROCEDURE)
+SYMBOL_VECTOR=(PR_IntervalNow=PROCEDURE)
+SYMBOL_VECTOR=(PR_IncrementCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_Malloc=PROCEDURE)
+SYMBOL_VECTOR=(PR_LockOrderedLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewPollableEvent=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewRWLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_NewThreadPrivateIndex=PROCEDURE)
+SYMBOL_VECTOR=(PR_Now=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenAnonFileMap=PROCEDURE)
+SYMBOL_VECTOR=(PR_OpenSharedMemory=PROCEDURE)
+SYMBOL_VECTOR=(PR_RecordTraceEntries=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetConcurrency=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetFDCacheSize=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetLibraryPath=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_StringToNetAddr=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetTraceOption=PROCEDURE)
+SYMBOL_VECTOR=(PR_SubtractFromCounter=PROCEDURE)
+SYMBOL_VECTOR=(PR_VersionCheck=PROCEDURE)
+SYMBOL_VECTOR=(PR_Trace=PROCEDURE)
+SYMBOL_VECTOR=(PR_UnlockOrderedLock=PROCEDURE)
+SYMBOL_VECTOR=(PR_fprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_snprintf=PROCEDURE)
+SYMBOL_VECTOR=(PR_sscanf=PROCEDURE)
+SYMBOL_VECTOR=(PR_strtod=PROCEDURE)
+SYMBOL_VECTOR=(PRP_DestroyNakedCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PRP_NakedBroadcast=PROCEDURE)
+SYMBOL_VECTOR=(PRP_NakedNotify=PROCEDURE)
+SYMBOL_VECTOR=(PRP_NakedWait=PROCEDURE)
+SYMBOL_VECTOR=(PRP_NewNakedCondVar=PROCEDURE)
+SYMBOL_VECTOR=(PRP_TryLock=PROCEDURE)
+SYMBOL_VECTOR=(libVersionPoint=PROCEDURE)
+!
+! NSPR private
+!
+SYMBOL_VECTOR=(GetExecutionEnvironment=PROCEDURE)
+SYMBOL_VECTOR=(PT_FPrintStats=PROCEDURE)
+SYMBOL_VECTOR=(SetExecutionEnvironment=PROCEDURE)
+!
+! Start of 2,4 additions
+! 51 stubs (4 thru 54) so that PR_CreateThread ends up at 1B70.
+! Over time some of these stubs will get replaced by new symbols.
+!
+SYMBOL_VECTOR=(PR_VMS_Stub4=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub5=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub6=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub7=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub8=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub9=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub10=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub11=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub12=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub13=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub14=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub15=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub16=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub17=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub18=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub19=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub20=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub21=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub22=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub23=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub24=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub25=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub26=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub27=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub28=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub29=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub30=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub31=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub32=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub33=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub34=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub35=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub36=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub37=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub38=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub39=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub40=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub41=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub42=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub43=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub44=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub45=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub46=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub47=PROCEDURE)
+SYMBOL_VECTOR=(PR_VMS_Stub48=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetAddrInfoByName=PROCEDURE) ! was Stub49
+SYMBOL_VECTOR=(PR_FreeAddrInfo=PROCEDURE) ! was Stub50
+SYMBOL_VECTOR=(PR_EnumerateAddrInfo=PROCEDURE) ! was Stub51
+SYMBOL_VECTOR=(PR_GetCanonNameFromAddrInfo=PROCEDURE) ! was Stub52
+SYMBOL_VECTOR=(PR_GetPathSeparator=PROCEDURE) ! was Stub53
+SYMBOL_VECTOR=(LL_MaxUint=PROCEDURE) ! was Stub54
+!
+SYMBOL_VECTOR=(PR_CallOnceWithArg=PROCEDURE)
+SYMBOL_VECTOR=(PR_GetLibraryFilePathname=PROCEDURE)
+SYMBOL_VECTOR=(PR_SetError=PROCEDURE)
+SYMBOL_VECTOR=(PR_CreateThread=PROCEDURE)
+!
+! --------------------------------------------------------------------------
+! End of fixed section
+! --------------------------------------------------------------------------
+!
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/os2extra.def b/src/libs/xpcom18a4/nsprpub/pr/src/os2extra.def
new file mode 100644
index 00000000..8dbb34da
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/os2extra.def
@@ -0,0 +1,16 @@
+ ;
+ ; Support plugins that were explicitly linked to the Visual Age
+ ; version of nspr4.dll.
+ ;
+ PR_NewMonitor
+ PR_EnterMonitor
+ PR_ExitMonitor
+ PR_GetCurrentThread
+ PR_AttachThread
+ PR_DetachThread
+ ;
+ ; Exception handler functions that are used by nsAppRunner.cpp
+ ;
+ _PR_OS2_SetFloatExcpHandler
+ _PR_OS2_UnsetFloatExcpHandler
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/prvrsion.c b/src/libs/xpcom18a4/nsprpub/pr/src/prvrsion.c
new file mode 100644
index 00000000..b8f4916d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/prvrsion.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prvrsion.h"
+
+/************************************************************************/
+/**************************IDENTITY AND VERSIONING***********************/
+/************************************************************************/
+#ifndef XP_MAC
+#include "_pr_bld.h"
+#endif
+#if !defined(_BUILD_TIME)
+#ifdef HAVE_LONG_LONG
+#define _BUILD_TIME 0
+#else
+#define _BUILD_TIME {0, 0}
+#endif
+#endif
+#if !defined(_BUILD_STRING)
+#define _BUILD_STRING ""
+#endif
+#if !defined(_PRODUCTION)
+#define _PRODUCTION ""
+#endif
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * A trick to expand the PR_VMAJOR macro before concatenation.
+ */
+#define CONCAT(x, y) x ## y
+#define CONCAT2(x, y) CONCAT(x, y)
+#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libnspr, PR_VMAJOR)
+
+PRVersionDescription VERSION_DESC_NAME =
+{
+ /* version */ 2, /* this is the only one supported */
+ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */
+ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */
+ /* vMajor */ PR_VMAJOR, /* NSPR's version number */
+ /* vMinor */ PR_VMINOR, /* and minor version */
+ /* vPatch */ PR_VPATCH, /* and patch */
+ /* beta */ PR_BETA, /* beta build boolean */
+#if defined(DEBUG)
+ /* debug */ PR_TRUE, /* a debug build */
+#else
+ /* debug */ PR_FALSE, /* an optomized build */
+#endif
+ /* special */ PR_FALSE, /* they're all special, but ... */
+ /* filename */ _PRODUCTION, /* the produced library name */
+ /* description */ "Portable runtime", /* what we are */
+ /* security */ "N/A", /* not applicable here */
+ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved",
+ /* comment */ "License information: http://www.mozilla.org/MPL/",
+ /* specialString */ ""
+};
+
+#ifdef XP_UNIX
+
+/*
+ * Version information for the 'ident' and 'what commands
+ *
+ * NOTE: the first component of the concatenated rcsid string
+ * must not end in a '$' to prevent rcs keyword substitution.
+ */
+static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING " $";
+static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING
+ " " _BUILD_STRING;
+
+#endif /* XP_UNIX */
+
+PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void)
+{
+#ifdef XP_UNIX
+ /*
+ * Add dummy references to rcsid and sccsid to prevent them
+ * from being optimized away as unused variables.
+ */
+ const char *dummy;
+
+ dummy = rcsid;
+ dummy = sccsid;
+#endif
+ return &VERSION_DESC_NAME;
+} /* versionEntryPointType */
+
+/* prvrsion.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/Makefile.in
new file mode 100644
index 00000000..ddda7091
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/Makefile.in
@@ -0,0 +1,79 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OPTIMIZER =
+endif
+endif
+
+CSRCS = \
+ ptio.c \
+ ptsynch.c \
+ ptthread.c \
+ ptmisc.c \
+ $(NULL)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+ifeq ($(OS_ARCH),Linux)
+# for pthread_mutexattr_settype
+DEFINES += -D_XOPEN_SOURCE=500
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c
new file mode 100644
index 00000000..11b7d904
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c
@@ -0,0 +1,4920 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: ptio.c
+** Descritpion: Implemenation of I/O methods for pthreads
+*/
+
+#if defined(_PR_PTHREADS)
+
+#if defined(_PR_POLL_WITH_SELECT)
+#if !(defined(HPUX) && defined(_USE_BIG_FDS))
+/* set fd limit for select(), before including system header files */
+#define FD_SETSIZE (16 * 1024)
+#endif
+#endif
+
+#include <pthread.h>
+#include <string.h> /* for memset() */
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#if defined(DARWIN)
+#include <sys/utsname.h> /* for uname */
+#endif
+#if defined(SOLARIS) || defined(UNIXWARE)
+#include <sys/filio.h> /* to pick up FIONREAD */
+#endif
+#ifdef _PR_POLL_AVAILABLE
+#include <poll.h>
+#endif
+#ifdef AIX
+/* To pick up sysconf() */
+#include <unistd.h>
+#include <dlfcn.h> /* for dlopen */
+#else
+/* To pick up getrlimit() etc. */
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#ifdef SOLARIS
+/*
+ * Define HAVE_SENDFILEV if the system has the sendfilev() system call.
+ * Code built this way won't run on a system without sendfilev().
+ * We can define HAVE_SENDFILEV by default when the minimum release
+ * of Solaris that NSPR supports has sendfilev().
+ */
+#ifdef HAVE_SENDFILEV
+
+#include <sys/sendfile.h>
+
+#define SOLARIS_SENDFILEV(a, b, c, d) sendfilev((a), (b), (c), (d))
+
+#else
+
+#include <dlfcn.h> /* for dlopen */
+
+/*
+ * Match the definitions in <sys/sendfile.h>.
+ */
+typedef struct sendfilevec {
+ int sfv_fd; /* input fd */
+ uint_t sfv_flag; /* flags */
+ off_t sfv_off; /* offset to start reading from */
+ size_t sfv_len; /* amount of data */
+} sendfilevec_t;
+
+#define SFV_FD_SELF (-2)
+
+/*
+ * extern ssize_t sendfilev(int, const struct sendfilevec *, int, size_t *);
+ */
+static ssize_t (*pt_solaris_sendfilev_fptr)() = NULL;
+
+#define SOLARIS_SENDFILEV(a, b, c, d) \
+ (*pt_solaris_sendfilev_fptr)((a), (b), (c), (d))
+
+#endif /* HAVE_SENDFILEV */
+#endif /* SOLARIS */
+
+/*
+ * The send_file() system call is available in AIX 4.3.2 or later.
+ * If this file is compiled on an older AIX system, it attempts to
+ * look up the send_file symbol at run time to determine whether
+ * we can use the faster PR_SendFile/PR_TransmitFile implementation based on
+ * send_file(). On AIX 4.3.2 or later, we can safely skip this
+ * runtime function dispatching and just use the send_file based
+ * implementation.
+ */
+#ifdef AIX
+#ifdef SF_CLOSE
+#define HAVE_SEND_FILE
+#endif
+
+#ifdef HAVE_SEND_FILE
+
+#define AIX_SEND_FILE(a, b, c) send_file(a, b, c)
+
+#else /* HAVE_SEND_FILE */
+
+/*
+ * The following definitions match those in <sys/socket.h>
+ * on AIX 4.3.2.
+ */
+
+/*
+ * Structure for the send_file() system call
+ */
+struct sf_parms {
+ /* --------- header parms ---------- */
+ void *header_data; /* Input/Output. Points to header buf */
+ uint_t header_length; /* Input/Output. Length of the header */
+ /* --------- file parms ------------ */
+ int file_descriptor; /* Input. File descriptor of the file */
+ unsigned long long file_size; /* Output. Size of the file */
+ unsigned long long file_offset; /* Input/Output. Starting offset */
+ long long file_bytes; /* Input/Output. no. of bytes to send */
+ /* --------- trailer parms --------- */
+ void *trailer_data; /* Input/Output. Points to trailer buf */
+ uint_t trailer_length; /* Input/Output. Length of the trailer */
+ /* --------- return info ----------- */
+ unsigned long long bytes_sent; /* Output. no. of bytes sent */
+};
+
+/*
+ * Flags for the send_file() system call
+ */
+#define SF_CLOSE 0x00000001 /* close the socket after completion */
+#define SF_REUSE 0x00000002 /* reuse socket. not supported */
+#define SF_DONT_CACHE 0x00000004 /* don't apply network buffer cache */
+#define SF_SYNC_CACHE 0x00000008 /* sync/update network buffer cache */
+
+/*
+ * prototype: size_t send_file(int *, struct sf_parms *, uint_t);
+ */
+static ssize_t (*pt_aix_sendfile_fptr)() = NULL;
+
+#define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c)
+
+#endif /* HAVE_SEND_FILE */
+#endif /* AIX */
+
+#ifdef LINUX
+#include <sys/sendfile.h>
+#endif
+
+#include "primpl.h"
+
+#if defined(VBOX) && defined(_PR_POLL_AVAILABLE)
+# include <poll.h>
+#endif
+
+#include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */
+#ifdef LINUX
+/* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */
+#ifndef TCP_CORK
+#define TCP_CORK 3
+#endif
+#endif
+
+#ifdef DARWIN
+static PRBool _pr_ipv6_v6only_on_by_default;
+/* The IPV6_V6ONLY socket option is not defined on Mac OS X 10.1. */
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 27
+#endif
+#endif
+
+#if defined(SOLARIS)
+#define _PRSockOptVal_t char *
+#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \
+ || defined(LINUX) || defined(FREEBSD) || defined(BSDI) || defined(VMS) \
+ || defined(NTO) || defined(OPENBSD) || defined(DARWIN) \
+ || defined(UNIXWARE) || defined(NETBSD)
+#define _PRSockOptVal_t void *
+#else
+#error "Cannot determine architecture"
+#endif
+
+#if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11))
+#define _PRSelectFdSetArg_t int *
+#elif defined(AIX4_1)
+#define _PRSelectFdSetArg_t void *
+#elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \
+ || defined(OSF1) || defined(SOLARIS) \
+ || defined(HPUX10_30) || defined(HPUX11) || defined(LINUX) \
+ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
+ || defined(BSDI) || defined(VMS) || defined(NTO) || defined(DARWIN) \
+ || defined(UNIXWARE)
+#define _PRSelectFdSetArg_t fd_set *
+#else
+#error "Cannot determine architecture"
+#endif
+
+static PRFileDesc *pt_SetMethods(
+ PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported);
+
+static PRLock *_pr_flock_lock; /* For PR_LockFile() etc. */
+static PRCondVar *_pr_flock_cv; /* For PR_LockFile() etc. */
+static PRLock *_pr_rename_lock; /* For PR_Rename() */
+
+/**************************************************************************/
+
+/* These two functions are only used in assertions. */
+#if defined(DEBUG)
+
+PRBool IsValidNetAddr(const PRNetAddr *addr)
+{
+ if ((addr != NULL)
+ && (addr->raw.family != AF_UNIX)
+ && (addr->raw.family != PR_AF_INET6)
+ && (addr->raw.family != AF_INET)) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
+{
+ /*
+ * The definition of the length of a Unix domain socket address
+ * is not uniform, so we don't check it.
+ */
+ if ((addr != NULL)
+ && (addr->raw.family != AF_UNIX)
+ && (PR_NETADDR_SIZE(addr) != addr_len)) {
+#if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1
+ /*
+ * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2
+ * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id
+ * field and is 28 bytes. It is possible for socket functions
+ * to return an addr_len greater than sizeof(struct sockaddr_in6).
+ * We need to allow that. (Bugzilla bug #77264)
+ */
+ if ((PR_AF_INET6 == addr->raw.family)
+ && (sizeof(addr->ipv6) == addr_len)) {
+ return PR_TRUE;
+ }
+#endif
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+#endif /* DEBUG */
+
+/*****************************************************************************/
+/************************* I/O Continuation machinery ************************/
+/*****************************************************************************/
+
+/*
+ * The polling interval defines the maximum amount of time that a thread
+ * might hang up before an interrupt is noticed.
+ */
+#define PT_DEFAULT_POLL_MSEC 5000
+#if defined(_PR_POLL_WITH_SELECT)
+#define PT_DEFAULT_SELECT_SEC (PT_DEFAULT_POLL_MSEC/PR_MSEC_PER_SEC)
+#define PT_DEFAULT_SELECT_USEC \
+ ((PT_DEFAULT_POLL_MSEC % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC)
+#endif
+
+/*
+ * pt_SockLen is the type for the length of a socket address
+ * structure, used in the address length argument to bind,
+ * connect, accept, getsockname, getpeername, etc. Posix.1g
+ * defines this type as socklen_t. It is size_t or int on
+ * most current systems.
+ */
+#if defined(HAVE_SOCKLEN_T) \
+ || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)
+typedef socklen_t pt_SockLen;
+#elif (defined(AIX) && !defined(AIX4_1)) \
+ || defined(VMS)
+typedef PRSize pt_SockLen;
+#else
+typedef PRIntn pt_SockLen;
+#endif
+
+typedef struct pt_Continuation pt_Continuation;
+typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents);
+
+typedef enum pr_ContuationStatus
+{
+ pt_continuation_pending,
+ pt_continuation_done
+} pr_ContuationStatus;
+
+struct pt_Continuation
+{
+ /* The building of the continuation operation */
+ ContinuationFn function; /* what function to continue */
+ union { PRIntn osfd; } arg1; /* #1 - the op's fd */
+ union { void* buffer; } arg2; /* #2 - primary transfer buffer */
+ union {
+ PRSize amount; /* #3 - size of 'buffer', or */
+ pt_SockLen *addr_len; /* - length of address */
+#ifdef HPUX11
+ /*
+ * For sendfile()
+ */
+ struct file_spec {
+ off_t offset; /* offset in file to send */
+ size_t nbytes; /* length of file data to send */
+ size_t st_size; /* file size */
+ } file_spec;
+#endif
+ } arg3;
+ union { PRIntn flags; } arg4; /* #4 - read/write flags */
+ union { PRNetAddr *addr; } arg5; /* #5 - send/recv address */
+
+#ifdef HPUX11
+ /*
+ * For sendfile()
+ */
+ int filedesc; /* descriptor of file to send */
+ int nbytes_to_send; /* size of header and file */
+#endif /* HPUX11 */
+
+#ifdef SOLARIS
+ /*
+ * For sendfilev()
+ */
+ int nbytes_to_send; /* size of header and file */
+#endif /* SOLARIS */
+
+#ifdef LINUX
+ /*
+ * For sendfile()
+ */
+ int in_fd; /* descriptor of file to send */
+ off_t offset;
+ size_t count;
+#endif /* LINUX */
+
+ PRIntervalTime timeout; /* client (relative) timeout */
+
+ PRInt16 event; /* flags for poll()'s events */
+
+ /*
+ ** The representation and notification of the results of the operation.
+ ** These function can either return an int return code or a pointer to
+ ** some object.
+ */
+ union { PRSize code; void *object; } result;
+
+ PRIntn syserrno; /* in case it failed, why (errno) */
+ pr_ContuationStatus status; /* the status of the operation */
+};
+
+#if defined(DEBUG)
+
+PTDebug pt_debug; /* this is shared between several modules */
+
+PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
+{
+ PTDebug stats;
+ char buffer[100];
+ PRExplodedTime tod;
+ PRInt64 elapsed, aMil;
+ stats = pt_debug; /* a copy */
+ PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod);
+ (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
+
+ LL_SUB(elapsed, PR_Now(), stats.timeStarted);
+ LL_I2L(aMil, 1000000);
+ LL_DIV(elapsed, elapsed, aMil);
+
+ if (NULL != msg) PR_fprintf(debug_out, "%s", msg);
+ PR_fprintf(
+ debug_out, "\tstarted: %s[%lld]\n", buffer, elapsed);
+ PR_fprintf(
+ debug_out, "\tlocks [created: %u, destroyed: %u]\n",
+ stats.locks_created, stats.locks_destroyed);
+ PR_fprintf(
+ debug_out, "\tlocks [acquired: %u, released: %u]\n",
+ stats.locks_acquired, stats.locks_released);
+ PR_fprintf(
+ debug_out, "\tcvars [created: %u, destroyed: %u]\n",
+ stats.cvars_created, stats.cvars_destroyed);
+ PR_fprintf(
+ debug_out, "\tcvars [notified: %u, delayed_delete: %u]\n",
+ stats.cvars_notified, stats.delayed_cv_deletes);
+} /* PT_FPrintStats */
+
+#else
+
+PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg)
+{
+ /* do nothing */
+} /* PT_FPrintStats */
+
+#endif /* DEBUG */
+
+#if defined(_PR_POLL_WITH_SELECT)
+/*
+ * OSF1 and HPUX report the POLLHUP event for a socket when the
+ * shutdown(SHUT_WR) operation is called for the remote end, even though
+ * the socket is still writeable. Use select(), instead of poll(), to
+ * workaround this problem.
+ */
+static void pt_poll_now_with_select(pt_Continuation *op)
+{
+ PRInt32 msecs;
+ fd_set rd, wr, *rdp, *wrp;
+ struct timeval tv;
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRThread *self = PR_GetCurrentThread();
+
+ PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
+ PR_ASSERT(op->arg1.osfd < FD_SETSIZE);
+
+ switch (op->timeout) {
+ case PR_INTERVAL_NO_TIMEOUT:
+ tv.tv_sec = PT_DEFAULT_SELECT_SEC;
+ tv.tv_usec = PT_DEFAULT_SELECT_USEC;
+ do
+ {
+ PRIntn rv;
+
+ if (op->event & POLLIN) {
+ FD_ZERO(&rd);
+ FD_SET(op->arg1.osfd, &rd);
+ rdp = &rd;
+ } else
+ rdp = NULL;
+ if (op->event & POLLOUT) {
+ FD_ZERO(&wr);
+ FD_SET(op->arg1.osfd, &wr);
+ wrp = &wr;
+ } else
+ wrp = NULL;
+
+ rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);
+
+ if (self->state & PT_THREAD_ABORTED)
+ {
+ self->state &= ~PT_THREAD_ABORTED;
+ op->result.code = -1;
+ op->syserrno = EINTR;
+ op->status = pt_continuation_done;
+ return;
+ }
+
+ if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
+ continue; /* go around the loop again */
+
+ if (rv > 0)
+ {
+ PRInt16 revents = 0;
+
+ if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd))
+ revents |= POLLIN;
+ if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
+ revents |= POLLOUT;
+
+ if (op->function(op, revents))
+ op->status = pt_continuation_done;
+ } else if (rv == -1) {
+ op->result.code = -1;
+ op->syserrno = errno;
+ op->status = pt_continuation_done;
+ }
+ /* else, select timed out */
+ } while (pt_continuation_done != op->status);
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = op->timeout;
+ do
+ {
+ PRIntn rv;
+
+ if (op->event & POLLIN) {
+ FD_ZERO(&rd);
+ FD_SET(op->arg1.osfd, &rd);
+ rdp = &rd;
+ } else
+ rdp = NULL;
+ if (op->event & POLLOUT) {
+ FD_ZERO(&wr);
+ FD_SET(op->arg1.osfd, &wr);
+ wrp = &wr;
+ } else
+ wrp = NULL;
+
+ wait_for_remaining = PR_TRUE;
+ msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
+ if (msecs > PT_DEFAULT_POLL_MSEC) {
+ wait_for_remaining = PR_FALSE;
+ msecs = PT_DEFAULT_POLL_MSEC;
+ }
+ tv.tv_sec = msecs/PR_MSEC_PER_SEC;
+ tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
+ rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv);
+
+ if (self->state & PT_THREAD_ABORTED)
+ {
+ self->state &= ~PT_THREAD_ABORTED;
+ op->result.code = -1;
+ op->syserrno = EINTR;
+ op->status = pt_continuation_done;
+ return;
+ }
+
+ if (rv > 0) {
+ PRInt16 revents = 0;
+
+ if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd))
+ revents |= POLLIN;
+ if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr))
+ revents |= POLLOUT;
+
+ if (op->function(op, revents))
+ op->status = pt_continuation_done;
+
+ } else if ((rv == 0) ||
+ ((errno == EINTR) || (errno == EAGAIN))) {
+ if (rv == 0) { /* select timed out */
+ if (wait_for_remaining)
+ now += remaining;
+ else
+ now += PR_MillisecondsToInterval(msecs);
+ } else
+ now = PR_IntervalNow();
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= op->timeout) {
+ op->result.code = -1;
+ op->syserrno = ETIMEDOUT;
+ op->status = pt_continuation_done;
+ } else
+ remaining = op->timeout - elapsed;
+ } else {
+ op->result.code = -1;
+ op->syserrno = errno;
+ op->status = pt_continuation_done;
+ }
+ } while (pt_continuation_done != op->status);
+ break;
+ }
+
+} /* pt_poll_now_with_select */
+
+#endif /* _PR_POLL_WITH_SELECT */
+
+static void pt_poll_now(pt_Continuation *op)
+{
+ PRInt32 msecs;
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRBool wait_for_remaining;
+ PRThread *self = PR_GetCurrentThread();
+
+ PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout);
+#if defined (_PR_POLL_WITH_SELECT)
+ /*
+ * If the fd is small enough call the select-based poll operation
+ */
+ if (op->arg1.osfd < FD_SETSIZE) {
+ pt_poll_now_with_select(op);
+ return;
+ }
+#endif
+
+ switch (op->timeout) {
+ case PR_INTERVAL_NO_TIMEOUT:
+ msecs = PT_DEFAULT_POLL_MSEC;
+ do
+ {
+ PRIntn rv;
+ struct pollfd tmp_pfd;
+
+ tmp_pfd.revents = 0;
+ tmp_pfd.fd = op->arg1.osfd;
+ tmp_pfd.events = op->event;
+
+ rv = poll(&tmp_pfd, 1, msecs);
+
+ if (self->state & PT_THREAD_ABORTED)
+ {
+ self->state &= ~PT_THREAD_ABORTED;
+ op->result.code = -1;
+ op->syserrno = EINTR;
+ op->status = pt_continuation_done;
+ return;
+ }
+
+ if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN)))
+ continue; /* go around the loop again */
+
+ if (rv > 0)
+ {
+ PRInt16 events = tmp_pfd.events;
+ PRInt16 revents = tmp_pfd.revents;
+
+ if ((revents & POLLNVAL) /* busted in all cases */
+ || ((events & POLLOUT) && (revents & POLLHUP)))
+ /* write op & hup */
+ {
+ op->result.code = -1;
+ if (POLLNVAL & revents) op->syserrno = EBADF;
+ else if (POLLHUP & revents) op->syserrno = EPIPE;
+ op->status = pt_continuation_done;
+ } else {
+ if (op->function(op, revents))
+ op->status = pt_continuation_done;
+ }
+ } else if (rv == -1) {
+ op->result.code = -1;
+ op->syserrno = errno;
+ op->status = pt_continuation_done;
+ }
+ /* else, poll timed out */
+ } while (pt_continuation_done != op->status);
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = op->timeout;
+ do
+ {
+ PRIntn rv;
+ struct pollfd tmp_pfd;
+
+ tmp_pfd.revents = 0;
+ tmp_pfd.fd = op->arg1.osfd;
+ tmp_pfd.events = op->event;
+
+ wait_for_remaining = PR_TRUE;
+ msecs = (PRInt32)PR_IntervalToMilliseconds(remaining);
+ if (msecs > PT_DEFAULT_POLL_MSEC)
+ {
+ wait_for_remaining = PR_FALSE;
+ msecs = PT_DEFAULT_POLL_MSEC;
+ }
+ rv = poll(&tmp_pfd, 1, msecs);
+
+ if (self->state & PT_THREAD_ABORTED)
+ {
+ self->state &= ~PT_THREAD_ABORTED;
+ op->result.code = -1;
+ op->syserrno = EINTR;
+ op->status = pt_continuation_done;
+ return;
+ }
+
+ if (rv > 0)
+ {
+ PRInt16 events = tmp_pfd.events;
+ PRInt16 revents = tmp_pfd.revents;
+
+ if ((revents & POLLNVAL) /* busted in all cases */
+ || ((events & POLLOUT) && (revents & POLLHUP)))
+ /* write op & hup */
+ {
+ op->result.code = -1;
+ if (POLLNVAL & revents) op->syserrno = EBADF;
+ else if (POLLHUP & revents) op->syserrno = EPIPE;
+ op->status = pt_continuation_done;
+ } else {
+ if (op->function(op, revents))
+ {
+ op->status = pt_continuation_done;
+ }
+ }
+ } else if ((rv == 0) ||
+ ((errno == EINTR) || (errno == EAGAIN))) {
+ if (rv == 0) /* poll timed out */
+ {
+ if (wait_for_remaining)
+ now += remaining;
+ else
+ now += PR_MillisecondsToInterval(msecs);
+ }
+ else
+ now = PR_IntervalNow();
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= op->timeout) {
+ op->result.code = -1;
+ op->syserrno = ETIMEDOUT;
+ op->status = pt_continuation_done;
+ } else
+ remaining = op->timeout - elapsed;
+ } else {
+ op->result.code = -1;
+ op->syserrno = errno;
+ op->status = pt_continuation_done;
+ }
+ } while (pt_continuation_done != op->status);
+ break;
+ }
+
+} /* pt_poll_now */
+
+static PRIntn pt_Continue(pt_Continuation *op)
+{
+ op->status = pt_continuation_pending; /* set default value */
+ /*
+ * let each thread call poll directly
+ */
+ pt_poll_now(op);
+ PR_ASSERT(pt_continuation_done == op->status);
+ return op->result.code;
+} /* pt_Continue */
+
+/*****************************************************************************/
+/*********************** specific continuation functions *********************/
+/*****************************************************************************/
+static PRBool pt_connect_cont(pt_Continuation *op, PRInt16 revents)
+{
+ op->syserrno = _MD_unix_get_nonblocking_connect_error(op->arg1.osfd);
+ if (op->syserrno != 0) {
+ op->result.code = -1;
+ } else {
+ op->result.code = 0;
+ }
+ return PR_TRUE; /* this one is cooked */
+} /* pt_connect_cont */
+
+static PRBool pt_accept_cont(pt_Continuation *op, PRInt16 revents)
+{
+ op->syserrno = 0;
+ op->result.code = accept(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.addr_len);
+ if (-1 == op->result.code)
+ {
+ op->syserrno = errno;
+ if (EWOULDBLOCK == errno || EAGAIN == errno || ECONNABORTED == errno)
+ return PR_FALSE; /* do nothing - this one ain't finished */
+ }
+ return PR_TRUE;
+} /* pt_accept_cont */
+
+static PRBool pt_read_cont(pt_Continuation *op, PRInt16 revents)
+{
+ /*
+ * Any number of bytes will complete the operation. It need
+ * not (and probably will not) satisfy the request. The only
+ * error we continue is EWOULDBLOCK|EAGAIN.
+ */
+ op->result.code = read(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
+ op->syserrno = errno;
+ return ((-1 == op->result.code) &&
+ (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
+ PR_FALSE : PR_TRUE;
+} /* pt_read_cont */
+
+static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents)
+{
+ /*
+ * Any number of bytes will complete the operation. It need
+ * not (and probably will not) satisfy the request. The only
+ * error we continue is EWOULDBLOCK|EAGAIN.
+ */
+#if defined(SOLARIS)
+ if (0 == op->arg4.flags)
+ op->result.code = read(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
+ else
+ op->result.code = recv(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
+#else
+ op->result.code = recv(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
+#endif
+ op->syserrno = errno;
+ return ((-1 == op->result.code) &&
+ (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
+ PR_FALSE : PR_TRUE;
+} /* pt_recv_cont */
+
+static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents)
+{
+ PRIntn bytes;
+#if defined(SOLARIS)
+ PRInt32 tmp_amount = op->arg3.amount;
+#endif
+ /*
+ * We want to write the entire amount out, no matter how many
+ * tries it takes. Keep advancing the buffer and the decrementing
+ * the amount until the amount goes away. Return the total bytes
+ * (which should be the original amount) when finished (or an
+ * error).
+ */
+#if defined(SOLARIS)
+retry:
+ bytes = write(op->arg1.osfd, op->arg2.buffer, tmp_amount);
+#else
+ bytes = send(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);
+#endif
+ op->syserrno = errno;
+
+#if defined(SOLARIS)
+ /*
+ * The write system call has been reported to return the ERANGE error
+ * on occasion. Try to write in smaller chunks to workaround this bug.
+ */
+ if ((bytes == -1) && (op->syserrno == ERANGE))
+ {
+ if (tmp_amount > 1)
+ {
+ tmp_amount = tmp_amount/2; /* half the bytes */
+ goto retry;
+ }
+ }
+#endif
+
+ if (bytes >= 0) /* this is progress */
+ {
+ char *bp = (char*)op->arg2.buffer;
+ bp += bytes; /* adjust the buffer pointer */
+ op->arg2.buffer = bp;
+ op->result.code += bytes; /* accumulate the number sent */
+ op->arg3.amount -= bytes; /* and reduce the required count */
+ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
+ }
+ else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
+ {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ else return PR_FALSE;
+} /* pt_send_cont */
+
+static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents)
+{
+ PRIntn bytes;
+ /*
+ * We want to write the entire amount out, no matter how many
+ * tries it takes. Keep advancing the buffer and the decrementing
+ * the amount until the amount goes away. Return the total bytes
+ * (which should be the original amount) when finished (or an
+ * error).
+ */
+ bytes = write(op->arg1.osfd, op->arg2.buffer, op->arg3.amount);
+ op->syserrno = errno;
+ if (bytes >= 0) /* this is progress */
+ {
+ char *bp = (char*)op->arg2.buffer;
+ bp += bytes; /* adjust the buffer pointer */
+ op->arg2.buffer = bp;
+ op->result.code += bytes; /* accumulate the number sent */
+ op->arg3.amount -= bytes; /* and reduce the required count */
+ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
+ }
+ else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
+ {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ else return PR_FALSE;
+} /* pt_write_cont */
+
+static PRBool pt_writev_cont(pt_Continuation *op, PRInt16 revents)
+{
+ PRIntn bytes;
+ struct iovec *iov = (struct iovec*)op->arg2.buffer;
+ /*
+ * Same rules as write, but continuing seems to be a bit more
+ * complicated. As the number of bytes sent grows, we have to
+ * redefine the vector we're pointing at. We might have to
+ * modify an individual vector parms or we might have to eliminate
+ * a pair altogether.
+ */
+ bytes = writev(op->arg1.osfd, iov, op->arg3.amount);
+ op->syserrno = errno;
+ if (bytes >= 0) /* this is progress */
+ {
+ PRIntn iov_index;
+ op->result.code += bytes; /* accumulate the number sent */
+ for (iov_index = 0; iov_index < op->arg3.amount; ++iov_index)
+ {
+ /* how much progress did we make in the i/o vector? */
+ if (bytes < iov[iov_index].iov_len)
+ {
+ /* this element's not done yet */
+ char **bp = (char**)&(iov[iov_index].iov_base);
+ iov[iov_index].iov_len -= bytes; /* there's that much left */
+ *bp += bytes; /* starting there */
+ break; /* go off and do that */
+ }
+ bytes -= iov[iov_index].iov_len; /* that element's consumed */
+ }
+ op->arg2.buffer = &iov[iov_index]; /* new start of array */
+ op->arg3.amount -= iov_index; /* and array length */
+ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
+ }
+ else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
+ {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ else return PR_FALSE;
+} /* pt_writev_cont */
+
+static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents)
+{
+ PRIntn bytes = sendto(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags,
+ (struct sockaddr*)op->arg5.addr, PR_NETADDR_SIZE(op->arg5.addr));
+ op->syserrno = errno;
+ if (bytes >= 0) /* this is progress */
+ {
+ char *bp = (char*)op->arg2.buffer;
+ bp += bytes; /* adjust the buffer pointer */
+ op->arg2.buffer = bp;
+ op->result.code += bytes; /* accumulate the number sent */
+ op->arg3.amount -= bytes; /* and reduce the required count */
+ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;
+ }
+ else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))
+ {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ else return PR_FALSE;
+} /* pt_sendto_cont */
+
+static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents)
+{
+ pt_SockLen addr_len = sizeof(PRNetAddr);
+ op->result.code = recvfrom(
+ op->arg1.osfd, op->arg2.buffer, op->arg3.amount,
+ op->arg4.flags, (struct sockaddr*)op->arg5.addr, &addr_len);
+ op->syserrno = errno;
+ return ((-1 == op->result.code) &&
+ (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?
+ PR_FALSE : PR_TRUE;
+} /* pt_recvfrom_cont */
+
+#ifdef AIX
+static PRBool pt_aix_sendfile_cont(pt_Continuation *op, PRInt16 revents)
+{
+ struct sf_parms *sf_struct = (struct sf_parms *) op->arg2.buffer;
+ ssize_t rv;
+ unsigned long long saved_file_offset;
+ long long saved_file_bytes;
+
+ saved_file_offset = sf_struct->file_offset;
+ saved_file_bytes = sf_struct->file_bytes;
+ sf_struct->bytes_sent = 0;
+
+ if ((sf_struct->file_bytes > 0) && (sf_struct->file_size > 0))
+ PR_ASSERT((sf_struct->file_bytes + sf_struct->file_offset) <=
+ sf_struct->file_size);
+ rv = AIX_SEND_FILE(&op->arg1.osfd, sf_struct, op->arg4.flags);
+ op->syserrno = errno;
+
+ if (rv != -1) {
+ op->result.code += sf_struct->bytes_sent;
+ /*
+ * A bug in AIX 4.3.2 prevents the 'file_bytes' field from
+ * being updated. So, 'file_bytes' is maintained by NSPR to
+ * avoid conflict when this bug is fixed in AIX, in the future.
+ */
+ if (saved_file_bytes != -1)
+ saved_file_bytes -= (sf_struct->file_offset - saved_file_offset);
+ sf_struct->file_bytes = saved_file_bytes;
+ } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+ op->result.code = -1;
+ } else {
+ return PR_FALSE;
+ }
+
+ if (rv == 1) { /* more data to send */
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+#endif /* AIX */
+
+#ifdef HPUX11
+static PRBool pt_hpux_sendfile_cont(pt_Continuation *op, PRInt16 revents)
+{
+ struct iovec *hdtrl = (struct iovec *) op->arg2.buffer;
+ int count;
+
+ count = sendfile(op->arg1.osfd, op->filedesc, op->arg3.file_spec.offset,
+ op->arg3.file_spec.nbytes, hdtrl, op->arg4.flags);
+ PR_ASSERT(count <= op->nbytes_to_send);
+ op->syserrno = errno;
+
+ if (count != -1) {
+ op->result.code += count;
+ } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+ op->result.code = -1;
+ } else {
+ return PR_FALSE;
+ }
+ if (count != -1 && count < op->nbytes_to_send) {
+ if (count < hdtrl[0].iov_len) {
+ /* header not sent */
+
+ hdtrl[0].iov_base = ((char *) hdtrl[0].iov_len) + count;
+ hdtrl[0].iov_len -= count;
+
+ } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes)) {
+ /* header sent, file not sent */
+ PRUint32 file_nbytes_sent = count - hdtrl[0].iov_len;
+
+ hdtrl[0].iov_base = NULL;
+ hdtrl[0].iov_len = 0;
+
+ op->arg3.file_spec.offset += file_nbytes_sent;
+ op->arg3.file_spec.nbytes -= file_nbytes_sent;
+ } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes +
+ hdtrl[1].iov_len)) {
+ PRUint32 trailer_nbytes_sent = count - (hdtrl[0].iov_len +
+ op->arg3.file_spec.nbytes);
+
+ /* header sent, file sent, trailer not sent */
+
+ hdtrl[0].iov_base = NULL;
+ hdtrl[0].iov_len = 0;
+ /*
+ * set file offset and len so that no more file data is
+ * sent
+ */
+ op->arg3.file_spec.offset = op->arg3.file_spec.st_size;
+ op->arg3.file_spec.nbytes = 0;
+
+ hdtrl[1].iov_base =((char *) hdtrl[1].iov_base)+ trailer_nbytes_sent;
+ hdtrl[1].iov_len -= trailer_nbytes_sent;
+ }
+ op->nbytes_to_send -= count;
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+#endif /* HPUX11 */
+
+#ifdef SOLARIS
+static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents)
+{
+ struct sendfilevec *vec = (struct sendfilevec *) op->arg2.buffer;
+ size_t xferred;
+ ssize_t count;
+
+ count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred);
+ op->syserrno = errno;
+ PR_ASSERT((count == -1) || (count == xferred));
+
+ if (count == -1) {
+ if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN
+ && op->syserrno != EINTR) {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ count = xferred;
+ }
+ PR_ASSERT(count <= op->nbytes_to_send);
+
+ op->result.code += count;
+ if (count < op->nbytes_to_send) {
+ op->nbytes_to_send -= count;
+
+ while (count >= vec->sfv_len) {
+ count -= vec->sfv_len;
+ vec++;
+ op->arg3.amount--;
+ }
+ PR_ASSERT(op->arg3.amount > 0);
+
+ vec->sfv_off += count;
+ vec->sfv_len -= count;
+ PR_ASSERT(vec->sfv_len > 0);
+ op->arg2.buffer = vec;
+
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+#endif /* SOLARIS */
+
+#ifdef LINUX
+static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents)
+{
+ ssize_t rv;
+ off_t oldoffset;
+
+ oldoffset = op->offset;
+ rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count);
+ op->syserrno = errno;
+
+ if (rv == -1) {
+ if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
+ op->result.code = -1;
+ return PR_TRUE;
+ }
+ rv = 0;
+ }
+ PR_ASSERT(rv == op->offset - oldoffset);
+ op->result.code += rv;
+ if (rv < op->count) {
+ op->count -= rv;
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+#endif /* LINUX */
+
+void _PR_InitIO(void)
+{
+#if defined(DEBUG)
+ memset(&pt_debug, 0, sizeof(PTDebug));
+ pt_debug.timeStarted = PR_Now();
+#endif
+
+ _pr_flock_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_flock_lock);
+ _pr_flock_cv = PR_NewCondVar(_pr_flock_lock);
+ PR_ASSERT(NULL != _pr_flock_cv);
+ _pr_rename_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_rename_lock);
+
+ _PR_InitFdCache(); /* do that */
+
+ _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE, PR_TRUE);
+ _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE, PR_TRUE);
+ _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE, PR_TRUE);
+ PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);
+
+#ifdef DARWIN
+ /* In Mac OS X v10.3 Panther Beta the IPV6_V6ONLY socket option
+ * is turned on by default, contrary to what RFC 3493, Section
+ * 5.3 says. So we have to turn it off. Find out whether we
+ * are running on such a system.
+ */
+ {
+ int osfd;
+ osfd = socket(AF_INET6, SOCK_STREAM, 0);
+ if (osfd != -1) {
+ int on;
+ int optlen = sizeof(on);
+ if (getsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY,
+ &on, &optlen) == 0) {
+ _pr_ipv6_v6only_on_by_default = on;
+ }
+ close(osfd);
+ }
+ }
+#endif
+} /* _PR_InitIO */
+
+void _PR_CleanupIO(void)
+{
+ _PR_Putfd(_pr_stdin);
+ _pr_stdin = NULL;
+ _PR_Putfd(_pr_stdout);
+ _pr_stdout = NULL;
+ _PR_Putfd(_pr_stderr);
+ _pr_stderr = NULL;
+
+ _PR_CleanupFdCache();
+
+ if (_pr_flock_cv)
+ {
+ PR_DestroyCondVar(_pr_flock_cv);
+ _pr_flock_cv = NULL;
+ }
+ if (_pr_flock_lock)
+ {
+ PR_DestroyLock(_pr_flock_lock);
+ _pr_flock_lock = NULL;
+ }
+ if (_pr_rename_lock)
+ {
+ PR_DestroyLock(_pr_rename_lock);
+ _pr_rename_lock = NULL;
+ }
+} /* _PR_CleanupIO */
+
+PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
+{
+ PRFileDesc *result = NULL;
+ PR_ASSERT(osfd >= PR_StandardInput && osfd <= PR_StandardError);
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ switch (osfd)
+ {
+ case PR_StandardInput: result = _pr_stdin; break;
+ case PR_StandardOutput: result = _pr_stdout; break;
+ case PR_StandardError: result = _pr_stderr; break;
+ default:
+ (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ }
+ return result;
+} /* PR_GetSpecialFD */
+
+/*****************************************************************************/
+/***************************** I/O private methods ***************************/
+/*****************************************************************************/
+
+static PRBool pt_TestAbort(void)
+{
+ PRThread *me = PR_CurrentThread();
+ if(_PT_THREAD_INTERRUPTED(me))
+ {
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ me->state &= ~PT_THREAD_ABORTED;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+} /* pt_TestAbort */
+
+static void pt_MapError(void (*mapper)(PRIntn), PRIntn syserrno)
+{
+ switch (syserrno)
+ {
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); break;
+ case ETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break;
+ default:
+ mapper(syserrno);
+ }
+} /* pt_MapError */
+
+static PRStatus pt_Close(PRFileDesc *fd)
+{
+ if ((NULL == fd) || (NULL == fd->secret)
+ || ((_PR_FILEDESC_OPEN != fd->secret->state)
+ && (_PR_FILEDESC_CLOSED != fd->secret->state)))
+ {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ if (_PR_FILEDESC_OPEN == fd->secret->state)
+ {
+ if (-1 == close(fd->secret->md.osfd))
+ {
+#ifdef OSF1
+ /*
+ * Bug 86941: On Tru64 UNIX V5.0A and V5.1, the close()
+ * system call, when called to close a TCP socket, may
+ * return -1 with errno set to EINVAL but the system call
+ * does close the socket successfully. An application
+ * may safely ignore the EINVAL error. This bug is fixed
+ * on Tru64 UNIX V5.1A and later. The defect tracking
+ * number is QAR 81431.
+ */
+ if (PR_DESC_SOCKET_TCP != fd->methods->file_type
+ || EINVAL != errno)
+ {
+ pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno);
+ return PR_FAILURE;
+ }
+#else
+ pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno);
+ return PR_FAILURE;
+#endif
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
+ }
+ _PR_Putfd(fd);
+ return PR_SUCCESS;
+} /* pt_Close */
+
+static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ PRInt32 syserrno, bytes = -1;
+
+ if (pt_TestAbort()) return bytes;
+
+ bytes = read(fd->secret->md.osfd, buf, amount);
+ syserrno = errno;
+
+ if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ && (!fd->secret->nonblocking))
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = buf;
+ op.arg3.amount = amount;
+ op.timeout = PR_INTERVAL_NO_TIMEOUT;
+ op.function = pt_read_cont;
+ op.event = POLLIN | POLLPRI;
+ bytes = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ if (bytes < 0)
+ pt_MapError(_PR_MD_MAP_READ_ERROR, syserrno);
+ return bytes;
+} /* pt_Read */
+
+static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ PRInt32 syserrno, bytes = -1;
+ PRBool fNeedContinue = PR_FALSE;
+
+ if (pt_TestAbort()) return bytes;
+
+ bytes = write(fd->secret->md.osfd, buf, amount);
+ syserrno = errno;
+
+ if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) )
+ {
+ buf = (char *) buf + bytes;
+ amount -= bytes;
+ fNeedContinue = PR_TRUE;
+ }
+ if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ && (!fd->secret->nonblocking) )
+ {
+ bytes = 0;
+ fNeedContinue = PR_TRUE;
+ }
+
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = (void*)buf;
+ op.arg3.amount = amount;
+ op.timeout = PR_INTERVAL_NO_TIMEOUT;
+ op.result.code = bytes; /* initialize the number sent */
+ op.function = pt_write_cont;
+ op.event = POLLOUT | POLLPRI;
+ bytes = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ if (bytes == -1)
+ pt_MapError(_PR_MD_MAP_WRITE_ERROR, syserrno);
+ return bytes;
+} /* pt_Write */
+
+static PRInt32 pt_Writev(
+ PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_len, PRIntervalTime timeout)
+{
+ PRIntn iov_index;
+ PRBool fNeedContinue = PR_FALSE;
+ PRInt32 syserrno, bytes, rv = -1;
+ struct iovec osiov_local[PR_MAX_IOVECTOR_SIZE], *osiov;
+ int osiov_len;
+
+ if (pt_TestAbort()) return rv;
+
+ /* Ensured by PR_Writev */
+ PR_ASSERT(iov_len <= PR_MAX_IOVECTOR_SIZE);
+
+ /*
+ * We can't pass iov to writev because PRIOVec and struct iovec
+ * may not be binary compatible. Make osiov a copy of iov and
+ * pass osiov to writev. We can modify osiov if we need to
+ * continue the operation.
+ */
+ osiov = osiov_local;
+ osiov_len = iov_len;
+ for (iov_index = 0; iov_index < osiov_len; iov_index++)
+ {
+ osiov[iov_index].iov_base = iov[iov_index].iov_base;
+ osiov[iov_index].iov_len = iov[iov_index].iov_len;
+ }
+
+ rv = bytes = writev(fd->secret->md.osfd, osiov, osiov_len);
+ syserrno = errno;
+
+ if (!fd->secret->nonblocking)
+ {
+ if (bytes >= 0)
+ {
+ /*
+ * If we moved some bytes, how does that implicate the
+ * i/o vector list? In other words, exactly where are
+ * we within that array? What are the parameters for
+ * resumption? Maybe we're done!
+ */
+ for ( ;osiov_len > 0; osiov++, osiov_len--)
+ {
+ if (bytes < osiov->iov_len)
+ {
+ /* this one's not done yet */
+ osiov->iov_base = (char*)osiov->iov_base + bytes;
+ osiov->iov_len -= bytes;
+ break; /* go off and do that */
+ }
+ bytes -= osiov->iov_len; /* this one's done cooked */
+ }
+ PR_ASSERT(osiov_len > 0 || bytes == 0);
+ if (osiov_len > 0)
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout)
+ {
+ rv = -1;
+ syserrno = ETIMEDOUT;
+ }
+ else fNeedContinue = PR_TRUE;
+ }
+ }
+ else if (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else
+ {
+ rv = 0;
+ fNeedContinue = PR_TRUE;
+ }
+ }
+ }
+
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = (void*)osiov;
+ op.arg3.amount = osiov_len;
+ op.timeout = timeout;
+ op.result.code = rv;
+ op.function = pt_writev_cont;
+ op.event = POLLOUT | POLLPRI;
+ rv = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ if (rv == -1) pt_MapError(_PR_MD_MAP_WRITEV_ERROR, syserrno);
+ return rv;
+} /* pt_Writev */
+
+static PRInt32 pt_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
+{
+ return _PR_MD_LSEEK(fd, offset, whence);
+} /* pt_Seek */
+
+static PRInt64 pt_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
+{
+ return _PR_MD_LSEEK64(fd, offset, whence);
+} /* pt_Seek64 */
+
+static PRInt32 pt_Available_f(PRFileDesc *fd)
+{
+ PRInt32 result, cur, end;
+
+ cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR);
+
+ if (cur >= 0)
+ end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END);
+
+ if ((cur < 0) || (end < 0)) {
+ return -1;
+ }
+
+ result = end - cur;
+ _PR_MD_LSEEK(fd, cur, PR_SEEK_SET);
+
+ return result;
+} /* pt_Available_f */
+
+static PRInt64 pt_Available64_f(PRFileDesc *fd)
+{
+ PRInt64 result, cur, end;
+ PRInt64 minus_one;
+
+ LL_I2L(minus_one, -1);
+ cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR);
+
+ if (LL_GE_ZERO(cur))
+ end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END);
+
+ if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one;
+
+ LL_SUB(result, end, cur);
+ (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET);
+
+ return result;
+} /* pt_Available64_f */
+
+static PRInt32 pt_Available_s(PRFileDesc *fd)
+{
+ PRInt32 rv, bytes = -1;
+ if (pt_TestAbort()) return bytes;
+
+ rv = ioctl(fd->secret->md.osfd, FIONREAD, &bytes);
+
+ if (rv == -1)
+ pt_MapError(_PR_MD_MAP_SOCKETAVAILABLE_ERROR, errno);
+ return bytes;
+} /* pt_Available_s */
+
+static PRInt64 pt_Available64_s(PRFileDesc *fd)
+{
+ PRInt64 rv;
+ LL_I2L(rv, pt_Available_s(fd));
+ return rv;
+} /* pt_Available64_s */
+
+static PRStatus pt_FileInfo(PRFileDesc *fd, PRFileInfo *info)
+{
+ PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, info);
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
+} /* pt_FileInfo */
+
+static PRStatus pt_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info)
+{
+ PRInt32 rv = _PR_MD_GETOPENFILEINFO64(fd, info);
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
+} /* pt_FileInfo64 */
+
+static PRStatus pt_Synch(PRFileDesc *fd)
+{
+ return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;
+} /* pt_Synch */
+
+static PRStatus pt_Fsync(PRFileDesc *fd)
+{
+ PRIntn rv = -1;
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = fsync(fd->secret->md.osfd);
+ if (rv < 0) {
+ pt_MapError(_PR_MD_MAP_FSYNC_ERROR, errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* pt_Fsync */
+
+static PRStatus pt_Connect(
+ PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRIntn rv = -1, syserrno;
+ pt_SockLen addr_len;
+ const PRNetAddr *addrp = addr;
+#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
+ PRUint16 md_af = addr->raw.family;
+ PRNetAddr addrCopy;
+#endif
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ addr_len = PR_NETADDR_SIZE(addr);
+#if defined(_PR_INET6)
+ if (addr->raw.family == PR_AF_INET6) {
+ md_af = AF_INET6;
+#ifndef _PR_HAVE_SOCKADDR_LEN
+ addrCopy = *addr;
+ addrCopy.raw.family = AF_INET6;
+ addrp = &addrCopy;
+#endif
+ }
+#endif
+
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ addrCopy = *addr;
+ ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
+ ((struct sockaddr*)&addrCopy)->sa_family = md_af;
+ rv = connect(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);
+#else
+ rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);
+#endif
+ syserrno = errno;
+ if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking))
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ op.arg2.buffer = (void*)&addrCopy;
+#else
+ op.arg2.buffer = (void*)addr;
+#endif
+ op.arg3.amount = addr_len;
+ op.timeout = timeout;
+ op.function = pt_connect_cont;
+ op.event = POLLOUT | POLLPRI;
+ rv = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ }
+ if (-1 == rv) {
+ pt_MapError(_PR_MD_MAP_CONNECT_ERROR, syserrno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* pt_Connect */
+
+static PRStatus pt_ConnectContinue(
+ PRFileDesc *fd, PRInt16 out_flags)
+{
+ int err;
+ PRInt32 osfd;
+
+ if (out_flags & PR_POLL_NVAL)
+ {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0)
+ {
+ PR_ASSERT(out_flags == 0);
+ PR_SetError(PR_IN_PROGRESS_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ osfd = fd->secret->md.osfd;
+
+ err = _MD_unix_get_nonblocking_connect_error(osfd);
+ if (err != 0)
+ {
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* pt_ConnectContinue */
+
+PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
+{
+ /* Find the NSPR layer and invoke its connectcontinue method */
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+
+ if (NULL == bottom)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ return pt_ConnectContinue(bottom, pd->out_flags);
+} /* PR_GetConnectStatus */
+
+static PRFileDesc* pt_Accept(
+ PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRFileDesc *newfd = NULL;
+ PRIntn syserrno, osfd = -1;
+ pt_SockLen addr_len = sizeof(PRNetAddr);
+
+ if (pt_TestAbort()) return newfd;
+
+#ifdef _PR_STRICT_ADDR_LEN
+ if (addr)
+ {
+ /*
+ * Set addr->raw.family just so that we can use the
+ * PR_NETADDR_SIZE macro.
+ */
+ addr->raw.family = fd->secret->af;
+ addr_len = PR_NETADDR_SIZE(addr);
+ }
+#endif
+
+ osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
+ syserrno = errno;
+
+ if (osfd == -1)
+ {
+ if (fd->secret->nonblocking) goto failed;
+
+ if (EWOULDBLOCK != syserrno && EAGAIN != syserrno
+ && ECONNABORTED != syserrno)
+ goto failed;
+ else
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = addr;
+ op.arg3.addr_len = &addr_len;
+ op.timeout = timeout;
+ op.function = pt_accept_cont;
+ op.event = POLLIN | POLLPRI;
+ osfd = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ if (osfd < 0) goto failed;
+ }
+ }
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr)
+ {
+ addr->raw.family = ((struct sockaddr*)addr)->sa_family;
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+ if (addr && (AF_INET6 == addr->raw.family))
+ addr->raw.family = PR_AF_INET6;
+#endif
+ newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE, PR_FALSE);
+ if (newfd == NULL) close(osfd); /* $$$ whoops! this doesn't work $$$ */
+ else
+ {
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
+#ifdef LINUX
+ /*
+ * On Linux, experiments showed that the accepted sockets
+ * inherit the TCP_NODELAY socket option of the listening
+ * socket.
+ */
+ newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;
+#endif
+ }
+ return newfd;
+
+failed:
+ pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno);
+ return NULL;
+} /* pt_Accept */
+
+static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr)
+{
+ PRIntn rv;
+ pt_SockLen addr_len;
+ const PRNetAddr *addrp = addr;
+#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
+ PRUint16 md_af = addr->raw.family;
+ PRNetAddr addrCopy;
+#endif
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ if (addr->raw.family == AF_UNIX)
+ {
+ /* Disallow relative pathnames */
+ if (addr->local.path[0] != '/')
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ }
+
+#if defined(_PR_INET6)
+ if (addr->raw.family == PR_AF_INET6) {
+ md_af = AF_INET6;
+#ifndef _PR_HAVE_SOCKADDR_LEN
+ addrCopy = *addr;
+ addrCopy.raw.family = AF_INET6;
+ addrp = &addrCopy;
+#endif
+ }
+#endif
+
+ addr_len = PR_NETADDR_SIZE(addr);
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ addrCopy = *addr;
+ ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
+ ((struct sockaddr*)&addrCopy)->sa_family = md_af;
+ rv = bind(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);
+#else
+ rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);
+#endif
+
+ if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_BIND_ERROR, errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* pt_Bind */
+
+static PRStatus pt_Listen(PRFileDesc *fd, PRIntn backlog)
+{
+ PRIntn rv;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_LISTEN_ERROR, errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* pt_Listen */
+
+static PRStatus pt_Shutdown(PRFileDesc *fd, PRIntn how)
+{
+ PRIntn rv = -1;
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = shutdown(fd->secret->md.osfd, how);
+
+ if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_SHUTDOWN_ERROR, errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* pt_Shutdown */
+
+static PRInt16 pt_Poll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+ *out_flags = 0;
+ return in_flags;
+} /* pt_Poll */
+
+static PRInt32 pt_Recv(
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ PRInt32 syserrno, bytes = -1;
+ PRIntn osflags;
+
+ if (0 == flags)
+ osflags = 0;
+ else if (PR_MSG_PEEK == flags)
+ osflags = MSG_PEEK;
+ else
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return bytes;
+ }
+
+ if (pt_TestAbort()) return bytes;
+
+ /* recv() is a much slower call on pre-2.6 Solaris than read(). */
+#if defined(SOLARIS)
+ if (0 == osflags)
+ bytes = read(fd->secret->md.osfd, buf, amount);
+ else
+ bytes = recv(fd->secret->md.osfd, buf, amount, osflags);
+#else
+ bytes = recv(fd->secret->md.osfd, buf, amount, osflags);
+#endif
+ syserrno = errno;
+
+ if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ && (!fd->secret->nonblocking))
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = buf;
+ op.arg3.amount = amount;
+ op.arg4.flags = osflags;
+ op.timeout = timeout;
+ op.function = pt_recv_cont;
+ op.event = POLLIN | POLLPRI;
+ bytes = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ }
+ if (bytes < 0)
+ pt_MapError(_PR_MD_MAP_RECV_ERROR, syserrno);
+ return bytes;
+} /* pt_Recv */
+
+static PRInt32 pt_SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ return pt_Recv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
+} /* pt_SocketRead */
+
+static PRInt32 pt_Send(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ PRInt32 syserrno, bytes = -1;
+ PRBool fNeedContinue = PR_FALSE;
+#if defined(SOLARIS)
+ PRInt32 tmp_amount = amount;
+#endif
+
+ /*
+ * Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h,
+ * which has the following:
+ * # define send cma_send
+ * extern int cma_send (int , void *, int, int );
+ * So we need to cast away the 'const' of argument #2 for send().
+ */
+#if defined (HPUX) && defined(_PR_DCETHREADS)
+#define PT_SENDBUF_CAST (void *)
+#else
+#define PT_SENDBUF_CAST
+#endif
+
+ if (pt_TestAbort()) return bytes;
+
+ /*
+ * On pre-2.6 Solaris, send() is much slower than write().
+ * On 2.6 and beyond, with in-kernel sockets, send() and
+ * write() are fairly equivalent in performance.
+ */
+#if defined(SOLARIS)
+ PR_ASSERT(0 == flags);
+retry:
+ bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, tmp_amount);
+#else
+ bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags);
+#endif
+ syserrno = errno;
+
+#if defined(SOLARIS)
+ /*
+ * The write system call has been reported to return the ERANGE error
+ * on occasion. Try to write in smaller chunks to workaround this bug.
+ */
+ if ((bytes == -1) && (syserrno == ERANGE))
+ {
+ if (tmp_amount > 1)
+ {
+ tmp_amount = tmp_amount/2; /* half the bytes */
+ goto retry;
+ }
+ }
+#endif
+
+ if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) )
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout)
+ {
+ bytes = -1;
+ syserrno = ETIMEDOUT;
+ }
+ else
+ {
+ buf = (char *) buf + bytes;
+ amount -= bytes;
+ fNeedContinue = PR_TRUE;
+ }
+ }
+ if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ && (!fd->secret->nonblocking) )
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else
+ {
+ bytes = 0;
+ fNeedContinue = PR_TRUE;
+ }
+ }
+
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = (void*)buf;
+ op.arg3.amount = amount;
+ op.arg4.flags = flags;
+ op.timeout = timeout;
+ op.result.code = bytes; /* initialize the number sent */
+ op.function = pt_send_cont;
+ op.event = POLLOUT | POLLPRI;
+ bytes = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ if (bytes == -1)
+ pt_MapError(_PR_MD_MAP_SEND_ERROR, syserrno);
+ return bytes;
+} /* pt_Send */
+
+static PRInt32 pt_SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ return pt_Send(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
+} /* pt_SocketWrite */
+
+static PRInt32 pt_SendTo(
+ PRFileDesc *fd, const void *buf,
+ PRInt32 amount, PRIntn flags, const PRNetAddr *addr,
+ PRIntervalTime timeout)
+{
+ PRInt32 syserrno, bytes = -1;
+ PRBool fNeedContinue = PR_FALSE;
+ pt_SockLen addr_len;
+ const PRNetAddr *addrp = addr;
+#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
+ PRUint16 md_af = addr->raw.family;
+ PRNetAddr addrCopy;
+#endif
+
+ if (pt_TestAbort()) return bytes;
+
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+#if defined(_PR_INET6)
+ if (addr->raw.family == PR_AF_INET6) {
+ md_af = AF_INET6;
+#ifndef _PR_HAVE_SOCKADDR_LEN
+ addrCopy = *addr;
+ addrCopy.raw.family = AF_INET6;
+ addrp = &addrCopy;
+#endif
+ }
+#endif
+
+ addr_len = PR_NETADDR_SIZE(addr);
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ addrCopy = *addr;
+ ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
+ ((struct sockaddr*)&addrCopy)->sa_family = md_af;
+ bytes = sendto(
+ fd->secret->md.osfd, buf, amount, flags,
+ (struct sockaddr*)&addrCopy, addr_len);
+#else
+ bytes = sendto(
+ fd->secret->md.osfd, buf, amount, flags,
+ (struct sockaddr*)addrp, addr_len);
+#endif
+ syserrno = errno;
+ if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ && (!fd->secret->nonblocking) )
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else fNeedContinue = PR_TRUE;
+ }
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = (void*)buf;
+ op.arg3.amount = amount;
+ op.arg4.flags = flags;
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ op.arg5.addr = (PRNetAddr*)&addrCopy;
+#else
+ op.arg5.addr = (PRNetAddr*)addr;
+#endif
+ op.timeout = timeout;
+ op.result.code = 0; /* initialize the number sent */
+ op.function = pt_sendto_cont;
+ op.event = POLLOUT | POLLPRI;
+ bytes = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+ if (bytes < 0)
+ pt_MapError(_PR_MD_MAP_SENDTO_ERROR, syserrno);
+ return bytes;
+} /* pt_SendTo */
+
+static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRBool fNeedContinue = PR_FALSE;
+ PRInt32 syserrno, bytes = -1;
+ pt_SockLen addr_len = sizeof(PRNetAddr);
+
+ if (pt_TestAbort()) return bytes;
+
+ bytes = recvfrom(
+ fd->secret->md.osfd, buf, amount, flags,
+ (struct sockaddr*)addr, &addr_len);
+ syserrno = errno;
+
+ if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
+ && (!fd->secret->nonblocking) )
+ {
+ if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
+ else fNeedContinue = PR_TRUE;
+ }
+
+ if (fNeedContinue == PR_TRUE)
+ {
+ pt_Continuation op;
+ op.arg1.osfd = fd->secret->md.osfd;
+ op.arg2.buffer = buf;
+ op.arg3.amount = amount;
+ op.arg4.flags = flags;
+ op.arg5.addr = addr;
+ op.timeout = timeout;
+ op.function = pt_recvfrom_cont;
+ op.event = POLLIN | POLLPRI;
+ bytes = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (bytes >= 0)
+ {
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr)
+ {
+ addr->raw.family = ((struct sockaddr*)addr)->sa_family;
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+ if (addr && (AF_INET6 == addr->raw.family))
+ addr->raw.family = PR_AF_INET6;
+#endif
+ if (bytes < 0)
+ pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno);
+ return bytes;
+} /* pt_RecvFrom */
+
+#ifdef AIX
+#ifndef HAVE_SEND_FILE
+static pthread_once_t pt_aix_sendfile_once_block = PTHREAD_ONCE_INIT;
+
+static void pt_aix_sendfile_init_routine(void)
+{
+ void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
+ pt_aix_sendfile_fptr = (ssize_t (*)()) dlsym(handle, "send_file");
+ dlclose(handle);
+}
+
+/*
+ * pt_AIXDispatchSendFile
+ */
+static PRInt32 pt_AIXDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ int rv;
+
+ rv = pthread_once(&pt_aix_sendfile_once_block,
+ pt_aix_sendfile_init_routine);
+ PR_ASSERT(0 == rv);
+ if (pt_aix_sendfile_fptr) {
+ return pt_AIXSendFile(sd, sfd, flags, timeout);
+ } else {
+ return PR_EmulateSendFile(sd, sfd, flags, timeout);
+ }
+}
+#endif /* !HAVE_SEND_FILE */
+
+
+/*
+ * pt_AIXSendFile
+ *
+ * Send file sfd->fd across socket sd. If specified, header and trailer
+ * buffers are sent before and after the file, respectively.
+ *
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
+ *
+ * This implementation takes advantage of the send_file() system
+ * call available in AIX 4.3.2.
+ */
+
+static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ struct sf_parms sf_struct;
+ uint_t send_flags;
+ ssize_t rv;
+ int syserrno;
+ PRInt32 count;
+ unsigned long long saved_file_offset;
+ long long saved_file_bytes;
+
+ sf_struct.header_data = (void *) sfd->header; /* cast away the 'const' */
+ sf_struct.header_length = sfd->hlen;
+ sf_struct.file_descriptor = sfd->fd->secret->md.osfd;
+ sf_struct.file_size = 0;
+ sf_struct.file_offset = sfd->file_offset;
+ if (sfd->file_nbytes == 0)
+ sf_struct.file_bytes = -1;
+ else
+ sf_struct.file_bytes = sfd->file_nbytes;
+ sf_struct.trailer_data = (void *) sfd->trailer;
+ sf_struct.trailer_length = sfd->tlen;
+ sf_struct.bytes_sent = 0;
+
+ saved_file_offset = sf_struct.file_offset;
+ saved_file_bytes = sf_struct.file_bytes;
+
+ send_flags = 0; /* flags processed at the end */
+
+ /* The first argument to send_file() is int*. */
+ PR_ASSERT(sizeof(int) == sizeof(sd->secret->md.osfd));
+ do {
+ rv = AIX_SEND_FILE(&sd->secret->md.osfd, &sf_struct, send_flags);
+ } while (rv == -1 && (syserrno = errno) == EINTR);
+
+ if (rv == -1) {
+ if (syserrno == EAGAIN || syserrno == EWOULDBLOCK) {
+ count = 0; /* Not a real error. Need to continue. */
+ } else {
+ count = -1;
+ }
+ } else {
+ count = sf_struct.bytes_sent;
+ /*
+ * A bug in AIX 4.3.2 prevents the 'file_bytes' field from
+ * being updated. So, 'file_bytes' is maintained by NSPR to
+ * avoid conflict when this bug is fixed in AIX, in the future.
+ */
+ if (saved_file_bytes != -1)
+ saved_file_bytes -= (sf_struct.file_offset - saved_file_offset);
+ sf_struct.file_bytes = saved_file_bytes;
+ }
+
+ if ((rv == 1) || ((rv == -1) && (count == 0))) {
+ pt_Continuation op;
+
+ op.arg1.osfd = sd->secret->md.osfd;
+ op.arg2.buffer = &sf_struct;
+ op.arg4.flags = send_flags;
+ op.result.code = count;
+ op.timeout = timeout;
+ op.function = pt_aix_sendfile_cont;
+ op.event = POLLOUT | POLLPRI;
+ count = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+
+ if (count == -1) {
+ pt_MapError(_MD_aix_map_sendfile_error, syserrno);
+ return -1;
+ }
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+ PR_Close(sd);
+ }
+ PR_ASSERT(count == (sfd->hlen + sfd->tlen +
+ ((sfd->file_nbytes == 0) ?
+ sf_struct.file_size - sfd->file_offset :
+ sfd->file_nbytes)));
+ return count;
+}
+#endif /* AIX */
+
+#ifdef HPUX11
+/*
+ * pt_HPUXSendFile
+ *
+ * Send file sfd->fd across socket sd. If specified, header and trailer
+ * buffers are sent before and after the file, respectively.
+ *
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
+ *
+ * This implementation takes advantage of the sendfile() system
+ * call available in HP-UX B.11.00.
+ */
+
+static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ struct stat statbuf;
+ size_t nbytes_to_send, file_nbytes_to_send;
+ struct iovec hdtrl[2]; /* optional header and trailer buffers */
+ int send_flags;
+ PRInt32 count;
+ int syserrno;
+
+ if (sfd->file_nbytes == 0) {
+ /* Get file size */
+ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+ _PR_MD_MAP_FSTAT_ERROR(errno);
+ return -1;
+ }
+ file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+ } else {
+ file_nbytes_to_send = sfd->file_nbytes;
+ }
+ nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;
+
+ hdtrl[0].iov_base = (void *) sfd->header; /* cast away the 'const' */
+ hdtrl[0].iov_len = sfd->hlen;
+ hdtrl[1].iov_base = (void *) sfd->trailer;
+ hdtrl[1].iov_len = sfd->tlen;
+ /*
+ * SF_DISCONNECT seems to close the socket even if sendfile()
+ * only does a partial send on a nonblocking socket. This
+ * would prevent the subsequent sendfile() calls on that socket
+ * from working. So we don't use the SD_DISCONNECT flag.
+ */
+ send_flags = 0;
+
+ do {
+ count = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,
+ sfd->file_offset, file_nbytes_to_send, hdtrl, send_flags);
+ } while (count == -1 && (syserrno = errno) == EINTR);
+
+ if (count == -1 && (syserrno == EAGAIN || syserrno == EWOULDBLOCK)) {
+ count = 0;
+ }
+ if (count != -1 && count < nbytes_to_send) {
+ pt_Continuation op;
+
+ if (count < sfd->hlen) {
+ /* header not sent */
+
+ hdtrl[0].iov_base = ((char *) sfd->header) + count;
+ hdtrl[0].iov_len = sfd->hlen - count;
+ op.arg3.file_spec.offset = sfd->file_offset;
+ op.arg3.file_spec.nbytes = file_nbytes_to_send;
+ } else if (count < (sfd->hlen + file_nbytes_to_send)) {
+ /* header sent, file not sent */
+
+ hdtrl[0].iov_base = NULL;
+ hdtrl[0].iov_len = 0;
+
+ op.arg3.file_spec.offset = sfd->file_offset + count - sfd->hlen;
+ op.arg3.file_spec.nbytes = file_nbytes_to_send - (count - sfd->hlen);
+ } else if (count < (sfd->hlen + file_nbytes_to_send + sfd->tlen)) {
+ PRUint32 trailer_nbytes_sent;
+
+ /* header sent, file sent, trailer not sent */
+
+ hdtrl[0].iov_base = NULL;
+ hdtrl[0].iov_len = 0;
+ /*
+ * set file offset and len so that no more file data is
+ * sent
+ */
+ op.arg3.file_spec.offset = statbuf.st_size;
+ op.arg3.file_spec.nbytes = 0;
+
+ trailer_nbytes_sent = count - sfd->hlen - file_nbytes_to_send;
+ hdtrl[1].iov_base = ((char *) sfd->trailer) + trailer_nbytes_sent;
+ hdtrl[1].iov_len = sfd->tlen - trailer_nbytes_sent;
+ }
+
+ op.arg1.osfd = sd->secret->md.osfd;
+ op.filedesc = sfd->fd->secret->md.osfd;
+ op.arg2.buffer = hdtrl;
+ op.arg3.file_spec.st_size = statbuf.st_size;
+ op.arg4.flags = send_flags;
+ op.nbytes_to_send = nbytes_to_send - count;
+ op.result.code = count;
+ op.timeout = timeout;
+ op.function = pt_hpux_sendfile_cont;
+ op.event = POLLOUT | POLLPRI;
+ count = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+
+ if (count == -1) {
+ pt_MapError(_MD_hpux_map_sendfile_error, syserrno);
+ return -1;
+ }
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+ PR_Close(sd);
+ }
+ PR_ASSERT(count == nbytes_to_send);
+ return count;
+}
+
+#endif /* HPUX11 */
+
+#ifdef SOLARIS
+
+/*
+ * pt_SolarisSendFile
+ *
+ * Send file sfd->fd across socket sd. If specified, header and trailer
+ * buffers are sent before and after the file, respectively.
+ *
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
+ *
+ * This implementation takes advantage of the sendfilev() system
+ * call available in Solaris 8.
+ */
+
+static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ struct stat statbuf;
+ size_t nbytes_to_send, file_nbytes_to_send;
+ struct sendfilevec sfv_struct[3];
+ int sfvcnt = 0;
+ size_t xferred;
+ PRInt32 count;
+ int syserrno;
+
+ if (sfd->file_nbytes == 0) {
+ /* Get file size */
+ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+ _PR_MD_MAP_FSTAT_ERROR(errno);
+ return -1;
+ }
+ file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+ } else {
+ file_nbytes_to_send = sfd->file_nbytes;
+ }
+
+ nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send;
+
+ if (sfd->hlen != 0) {
+ sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF;
+ sfv_struct[sfvcnt].sfv_flag = 0;
+ sfv_struct[sfvcnt].sfv_off = (off_t) sfd->header;
+ sfv_struct[sfvcnt].sfv_len = sfd->hlen;
+ sfvcnt++;
+ }
+
+ if (file_nbytes_to_send != 0) {
+ sfv_struct[sfvcnt].sfv_fd = sfd->fd->secret->md.osfd;
+ sfv_struct[sfvcnt].sfv_flag = 0;
+ sfv_struct[sfvcnt].sfv_off = sfd->file_offset;
+ sfv_struct[sfvcnt].sfv_len = file_nbytes_to_send;
+ sfvcnt++;
+ }
+
+ if (sfd->tlen != 0) {
+ sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF;
+ sfv_struct[sfvcnt].sfv_flag = 0;
+ sfv_struct[sfvcnt].sfv_off = (off_t) sfd->trailer;
+ sfv_struct[sfvcnt].sfv_len = sfd->tlen;
+ sfvcnt++;
+ }
+
+ if (0 == sfvcnt) {
+ count = 0;
+ goto done;
+ }
+
+ /*
+ * Strictly speaking, we may have sent some bytes when the
+ * sendfilev() is interrupted and we should retry it from an
+ * updated offset. We are not doing that here.
+ */
+ count = SOLARIS_SENDFILEV(sd->secret->md.osfd, sfv_struct,
+ sfvcnt, &xferred);
+
+ PR_ASSERT((count == -1) || (count == xferred));
+
+ if (count == -1) {
+ syserrno = errno;
+ if (syserrno == EINTR
+ || syserrno == EAGAIN || syserrno == EWOULDBLOCK) {
+ count = xferred;
+ }
+ }
+
+ if (count != -1 && count < nbytes_to_send) {
+ pt_Continuation op;
+ struct sendfilevec *vec = sfv_struct;
+ PRInt32 rem = count;
+
+ while (rem >= vec->sfv_len) {
+ rem -= vec->sfv_len;
+ vec++;
+ sfvcnt--;
+ }
+ PR_ASSERT(sfvcnt > 0);
+
+ vec->sfv_off += rem;
+ vec->sfv_len -= rem;
+ PR_ASSERT(vec->sfv_len > 0);
+
+ op.arg1.osfd = sd->secret->md.osfd;
+ op.arg2.buffer = vec;
+ op.arg3.amount = sfvcnt;
+ op.arg4.flags = 0;
+ op.nbytes_to_send = nbytes_to_send - count;
+ op.result.code = count;
+ op.timeout = timeout;
+ op.function = pt_solaris_sendfile_cont;
+ op.event = POLLOUT | POLLPRI;
+ count = pt_Continue(&op);
+ syserrno = op.syserrno;
+ }
+
+done:
+ if (count == -1) {
+ pt_MapError(_MD_solaris_map_sendfile_error, syserrno);
+ return -1;
+ }
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+ PR_Close(sd);
+ }
+ PR_ASSERT(count == nbytes_to_send);
+ return count;
+}
+
+#ifndef HAVE_SENDFILEV
+static pthread_once_t pt_solaris_sendfilev_once_block = PTHREAD_ONCE_INIT;
+
+static void pt_solaris_sendfilev_init_routine(void)
+{
+ void *handle;
+ PRBool close_it = PR_FALSE;
+
+ /*
+ * We do not want to unload libsendfile.so. This handle is leaked
+ * intentionally.
+ */
+ handle = dlopen("libsendfile.so", RTLD_LAZY | RTLD_GLOBAL);
+ PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
+ ("dlopen(libsendfile.so) returns %p", handle));
+
+ if (NULL == handle) {
+ /*
+ * The dlopen(0, mode) call is to allow for the possibility that
+ * sendfilev() may become part of a standard system library in a
+ * future Solaris release.
+ */
+ handle = dlopen(0, RTLD_LAZY | RTLD_GLOBAL);
+ PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
+ ("dlopen(0) returns %p", handle));
+ close_it = PR_TRUE;
+ }
+ pt_solaris_sendfilev_fptr = (ssize_t (*)()) dlsym(handle, "sendfilev");
+ PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
+ ("dlsym(sendfilev) returns %p", pt_solaris_sendfilev_fptr));
+
+ if (close_it) {
+ dlclose(handle);
+ }
+}
+
+/*
+ * pt_SolarisDispatchSendFile
+ */
+static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ int rv;
+
+ rv = pthread_once(&pt_solaris_sendfilev_once_block,
+ pt_solaris_sendfilev_init_routine);
+ PR_ASSERT(0 == rv);
+ if (pt_solaris_sendfilev_fptr) {
+ return pt_SolarisSendFile(sd, sfd, flags, timeout);
+ } else {
+ return PR_EmulateSendFile(sd, sfd, flags, timeout);
+ }
+}
+#endif /* !HAVE_SENDFILEV */
+
+#endif /* SOLARIS */
+
+#ifdef LINUX
+/*
+ * pt_LinuxSendFile
+ *
+ * Send file sfd->fd across socket sd. If specified, header and trailer
+ * buffers are sent before and after the file, respectively.
+ *
+ * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
+ *
+ * return number of bytes sent or -1 on error
+ *
+ * This implementation takes advantage of the sendfile() system
+ * call available in Linux kernel 2.2 or higher.
+ */
+
+static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ struct stat statbuf;
+ size_t file_nbytes_to_send;
+ PRInt32 count = 0;
+ ssize_t rv;
+ int syserrno;
+ off_t offset;
+ PRBool tcp_cork_enabled = PR_FALSE;
+ int tcp_cork;
+
+ if (sfd->file_nbytes == 0) {
+ /* Get file size */
+ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) {
+ _PR_MD_MAP_FSTAT_ERROR(errno);
+ return -1;
+ }
+ file_nbytes_to_send = statbuf.st_size - sfd->file_offset;
+ } else {
+ file_nbytes_to_send = sfd->file_nbytes;
+ }
+
+ if ((sfd->hlen != 0 || sfd->tlen != 0)
+ && sd->secret->md.tcp_nodelay == 0) {
+ tcp_cork = 1;
+ if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
+ &tcp_cork, sizeof tcp_cork) == 0) {
+ tcp_cork_enabled = PR_TRUE;
+ } else {
+ syserrno = errno;
+ if (syserrno != EINVAL) {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno);
+ return -1;
+ }
+ /*
+ * The most likely reason for the EINVAL error is that
+ * TCP_NODELAY is set (with a function other than
+ * PR_SetSocketOption). This is not fatal, so we keep
+ * on going.
+ */
+ PR_LOG(_pr_io_lm, PR_LOG_WARNING,
+ ("pt_LinuxSendFile: "
+ "setsockopt(TCP_CORK) failed with EINVAL\n"));
+ }
+ }
+
+ if (sfd->hlen != 0) {
+ count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout);
+ if (count == -1) {
+ goto failed;
+ }
+ }
+
+ if (file_nbytes_to_send != 0) {
+ offset = sfd->file_offset;
+ do {
+ rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd,
+ &offset, file_nbytes_to_send);
+ } while (rv == -1 && (syserrno = errno) == EINTR);
+ if (rv == -1) {
+ if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) {
+ _MD_linux_map_sendfile_error(syserrno);
+ count = -1;
+ goto failed;
+ }
+ rv = 0;
+ }
+ PR_ASSERT(rv == offset - sfd->file_offset);
+ count += rv;
+
+ if (rv < file_nbytes_to_send) {
+ pt_Continuation op;
+
+ op.arg1.osfd = sd->secret->md.osfd;
+ op.in_fd = sfd->fd->secret->md.osfd;
+ op.offset = offset;
+ op.count = file_nbytes_to_send - rv;
+ op.result.code = count;
+ op.timeout = timeout;
+ op.function = pt_linux_sendfile_cont;
+ op.event = POLLOUT | POLLPRI;
+ count = pt_Continue(&op);
+ syserrno = op.syserrno;
+ if (count == -1) {
+ pt_MapError(_MD_linux_map_sendfile_error, syserrno);
+ goto failed;
+ }
+ }
+ }
+
+ if (sfd->tlen != 0) {
+ rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout);
+ if (rv == -1) {
+ count = -1;
+ goto failed;
+ }
+ count += rv;
+ }
+
+failed:
+ if (tcp_cork_enabled) {
+ tcp_cork = 0;
+ if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
+ &tcp_cork, sizeof tcp_cork) == -1 && count != -1) {
+ _PR_MD_MAP_SETSOCKOPT_ERROR(errno);
+ count = -1;
+ }
+ }
+ if (count != -1) {
+ if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
+ PR_Close(sd);
+ }
+ PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send);
+ }
+ return count;
+}
+#endif /* LINUX */
+
+#ifdef AIX
+extern int _pr_aix_send_file_use_disabled;
+#endif
+
+static PRInt32 pt_SendFile(
+ PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ if (pt_TestAbort()) return -1;
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return -1;
+ }
+#ifdef HPUX11
+ return(pt_HPUXSendFile(sd, sfd, flags, timeout));
+#elif defined(AIX)
+#ifdef HAVE_SEND_FILE
+ /*
+ * A bug in AIX 4.3.2 results in corruption of data transferred by
+ * send_file(); AIX patch PTF U463956 contains the fix. A user can
+ * disable the use of send_file function in NSPR, when this patch is
+ * not installed on the system, by setting the envionment variable
+ * NSPR_AIX_SEND_FILE_USE_DISABLED to 1.
+ */
+ if (_pr_aix_send_file_use_disabled)
+ return(PR_EmulateSendFile(sd, sfd, flags, timeout));
+ else
+ return(pt_AIXSendFile(sd, sfd, flags, timeout));
+#else
+ return(PR_EmulateSendFile(sd, sfd, flags, timeout));
+ /* return(pt_AIXDispatchSendFile(sd, sfd, flags, timeout));*/
+#endif /* HAVE_SEND_FILE */
+#elif defined(SOLARIS)
+#ifdef HAVE_SENDFILEV
+ return(pt_SolarisSendFile(sd, sfd, flags, timeout));
+#else
+ return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout));
+#endif /* HAVE_SENDFILEV */
+#elif defined(LINUX)
+ return(pt_LinuxSendFile(sd, sfd, flags, timeout));
+#else
+ return(PR_EmulateSendFile(sd, sfd, flags, timeout));
+#endif
+}
+
+static PRInt32 pt_TransmitFile(
+ PRFileDesc *sd, PRFileDesc *fd, const void *headers,
+ PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ PRSendFileData sfd;
+
+ sfd.fd = fd;
+ sfd.file_offset = 0;
+ sfd.file_nbytes = 0;
+ sfd.header = headers;
+ sfd.hlen = hlen;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+
+ return(pt_SendFile(sd, &sfd, flags, timeout));
+} /* pt_TransmitFile */
+
+static PRInt32 pt_AcceptRead(
+ PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+
+ if (pt_TestAbort()) return rv;
+ /* The socket must be in blocking mode. */
+ if (sd->secret->nonblocking)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return rv;
+ }
+
+ rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
+ return rv;
+} /* pt_AcceptRead */
+
+static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr)
+{
+ PRIntn rv = -1;
+ pt_SockLen addr_len = sizeof(PRNetAddr);
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = getsockname(
+ fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
+ if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno);
+ return PR_FAILURE;
+ } else {
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr)
+ {
+ addr->raw.family = ((struct sockaddr*)addr)->sa_family;
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+ if (AF_INET6 == addr->raw.family)
+ addr->raw.family = PR_AF_INET6;
+#endif
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
+ return PR_SUCCESS;
+ }
+} /* pt_GetSockName */
+
+static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
+{
+ PRIntn rv = -1;
+ pt_SockLen addr_len = sizeof(PRNetAddr);
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = getpeername(
+ fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);
+
+ if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno);
+ return PR_FAILURE;
+ } else {
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ /* ignore the sa_len field of struct sockaddr */
+ if (addr)
+ {
+ addr->raw.family = ((struct sockaddr*)addr)->sa_family;
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+ if (AF_INET6 == addr->raw.family)
+ addr->raw.family = PR_AF_INET6;
+#endif
+ PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+ PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
+ return PR_SUCCESS;
+ }
+} /* pt_GetPeerName */
+
+static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
+{
+ PRIntn rv;
+ pt_SockLen length;
+ PRInt32 level, name;
+
+ /*
+ * PR_SockOpt_Nonblocking is a special case that does not
+ * translate to a getsockopt() call
+ */
+ if (PR_SockOpt_Nonblocking == data->option)
+ {
+ data->value.non_blocking = fd->secret->nonblocking;
+ return PR_SUCCESS;
+ }
+
+ rv = _PR_MapOptionName(data->option, &level, &name);
+ if (PR_SUCCESS == rv)
+ {
+ switch (data->option)
+ {
+ case PR_SockOpt_Linger:
+ {
+ struct linger linger;
+ length = sizeof(linger);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name, (char *) &linger, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(linger) == length));
+ data->value.linger.polarity =
+ (linger.l_onoff) ? PR_TRUE : PR_FALSE;
+ data->value.linger.linger =
+ PR_SecondsToInterval(linger.l_linger);
+ break;
+ }
+ case PR_SockOpt_Reuseaddr:
+ case PR_SockOpt_Keepalive:
+ case PR_SockOpt_NoDelay:
+ case PR_SockOpt_Broadcast:
+ {
+ PRIntn value;
+ length = sizeof(PRIntn);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name, (char*)&value, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
+ data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;
+ break;
+ }
+ case PR_SockOpt_McastLoopback:
+ {
+ PRUint8 xbool;
+ length = sizeof(xbool);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&xbool, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(xbool) == length));
+ data->value.mcast_loopback = (0 == xbool) ? PR_FALSE : PR_TRUE;
+ break;
+ }
+ case PR_SockOpt_RecvBufferSize:
+ case PR_SockOpt_SendBufferSize:
+ case PR_SockOpt_MaxSegment:
+ {
+ PRIntn value;
+ length = sizeof(PRIntn);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name, (char*)&value, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
+ data->value.recv_buffer_size = value;
+ break;
+ }
+ case PR_SockOpt_IpTimeToLive:
+ case PR_SockOpt_IpTypeOfService:
+ {
+ length = sizeof(PRUintn);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&data->value.ip_ttl, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length));
+ break;
+ }
+ case PR_SockOpt_McastTimeToLive:
+ {
+ PRUint8 ttl;
+ length = sizeof(ttl);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&ttl, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(ttl) == length));
+ data->value.mcast_ttl = ttl;
+ break;
+ }
+ case PR_SockOpt_AddMember:
+ case PR_SockOpt_DropMember:
+ {
+ struct ip_mreq mreq;
+ length = sizeof(mreq);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name, (char*)&mreq, &length);
+ PR_ASSERT((-1 == rv) || (sizeof(mreq) == length));
+ data->value.add_member.mcaddr.inet.ip =
+ mreq.imr_multiaddr.s_addr;
+ data->value.add_member.ifaddr.inet.ip =
+ mreq.imr_interface.s_addr;
+ break;
+ }
+ case PR_SockOpt_McastInterface:
+ {
+ length = sizeof(data->value.mcast_if.inet.ip);
+ rv = getsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&data->value.mcast_if.inet.ip, &length);
+ PR_ASSERT((-1 == rv)
+ || (sizeof(data->value.mcast_if.inet.ip) == length));
+ break;
+ }
+ default:
+ PR_NOT_REACHED("Unknown socket option");
+ break;
+ }
+ if (-1 == rv) _PR_MD_MAP_GETSOCKOPT_ERROR(errno);
+ }
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
+} /* pt_GetSocketOption */
+
+static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)
+{
+ PRIntn rv;
+ PRInt32 level, name;
+
+ /*
+ * PR_SockOpt_Nonblocking is a special case that does not
+ * translate to a setsockopt call.
+ */
+ if (PR_SockOpt_Nonblocking == data->option)
+ {
+ fd->secret->nonblocking = data->value.non_blocking;
+ return PR_SUCCESS;
+ }
+
+ rv = _PR_MapOptionName(data->option, &level, &name);
+ if (PR_SUCCESS == rv)
+ {
+ switch (data->option)
+ {
+ case PR_SockOpt_Linger:
+ {
+ struct linger linger;
+ linger.l_onoff = data->value.linger.polarity;
+ linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name, (char*)&linger, sizeof(linger));
+ break;
+ }
+ case PR_SockOpt_Reuseaddr:
+ case PR_SockOpt_Keepalive:
+ case PR_SockOpt_NoDelay:
+ case PR_SockOpt_Broadcast:
+ {
+ PRIntn value = (data->value.reuse_addr) ? 1 : 0;
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&value, sizeof(PRIntn));
+#ifdef LINUX
+ /* for pt_LinuxSendFile */
+ if (name == TCP_NODELAY && rv == 0) {
+ fd->secret->md.tcp_nodelay = value;
+ }
+#endif
+ break;
+ }
+ case PR_SockOpt_McastLoopback:
+ {
+ PRUint8 xbool = data->value.mcast_loopback ? 1 : 0;
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&xbool, sizeof(xbool));
+ break;
+ }
+ case PR_SockOpt_RecvBufferSize:
+ case PR_SockOpt_SendBufferSize:
+ case PR_SockOpt_MaxSegment:
+ {
+ PRIntn value = data->value.recv_buffer_size;
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&value, sizeof(PRIntn));
+ break;
+ }
+ case PR_SockOpt_IpTimeToLive:
+ case PR_SockOpt_IpTypeOfService:
+ {
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&data->value.ip_ttl, sizeof(PRUintn));
+ break;
+ }
+ case PR_SockOpt_McastTimeToLive:
+ {
+ PRUint8 ttl = data->value.mcast_ttl;
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&ttl, sizeof(ttl));
+ break;
+ }
+ case PR_SockOpt_AddMember:
+ case PR_SockOpt_DropMember:
+ {
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr.s_addr =
+ data->value.add_member.mcaddr.inet.ip;
+ mreq.imr_interface.s_addr =
+ data->value.add_member.ifaddr.inet.ip;
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&mreq, sizeof(mreq));
+ break;
+ }
+ case PR_SockOpt_McastInterface:
+ {
+ rv = setsockopt(
+ fd->secret->md.osfd, level, name,
+ (char*)&data->value.mcast_if.inet.ip,
+ sizeof(data->value.mcast_if.inet.ip));
+ break;
+ }
+ default:
+ PR_NOT_REACHED("Unknown socket option");
+ break;
+ }
+ if (-1 == rv) _PR_MD_MAP_SETSOCKOPT_ERROR(errno);
+ }
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
+} /* pt_SetSocketOption */
+
+/*****************************************************************************/
+/****************************** I/O method objects ***************************/
+/*****************************************************************************/
+
+static PRIOMethods _pr_file_methods = {
+ PR_DESC_FILE,
+ pt_Close,
+ pt_Read,
+ pt_Write,
+ pt_Available_f,
+ pt_Available64_f,
+ pt_Fsync,
+ pt_Seek,
+ pt_Seek64,
+ pt_FileInfo,
+ pt_FileInfo64,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ pt_Poll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRIOMethods _pr_pipe_methods = {
+ PR_DESC_PIPE,
+ pt_Close,
+ pt_Read,
+ pt_Write,
+ pt_Available_s,
+ pt_Available64_s,
+ pt_Synch,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ pt_Poll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRIOMethods _pr_tcp_methods = {
+ PR_DESC_SOCKET_TCP,
+ pt_Close,
+ pt_SocketRead,
+ pt_SocketWrite,
+ pt_Available_s,
+ pt_Available64_s,
+ pt_Synch,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ pt_Writev,
+ pt_Connect,
+ pt_Accept,
+ pt_Bind,
+ pt_Listen,
+ pt_Shutdown,
+ pt_Recv,
+ pt_Send,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ pt_Poll,
+ pt_AcceptRead,
+ pt_TransmitFile,
+ pt_GetSockName,
+ pt_GetPeerName,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ pt_GetSocketOption,
+ pt_SetSocketOption,
+ pt_SendFile,
+ pt_ConnectContinue,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRIOMethods _pr_udp_methods = {
+ PR_DESC_SOCKET_UDP,
+ pt_Close,
+ pt_SocketRead,
+ pt_SocketWrite,
+ pt_Available_s,
+ pt_Available64_s,
+ pt_Synch,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ pt_Writev,
+ pt_Connect,
+ (PRAcceptFN)_PR_InvalidDesc,
+ pt_Bind,
+ pt_Listen,
+ pt_Shutdown,
+ pt_Recv,
+ pt_Send,
+ pt_RecvFrom,
+ pt_SendTo,
+ pt_Poll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ pt_GetSockName,
+ pt_GetPeerName,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ pt_GetSocketOption,
+ pt_SetSocketOption,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+static PRIOMethods _pr_socketpollfd_methods = {
+ (PRDescType) 0,
+ (PRCloseFN)_PR_InvalidStatus,
+ (PRReadFN)_PR_InvalidInt,
+ (PRWriteFN)_PR_InvalidInt,
+ (PRAvailableFN)_PR_InvalidInt,
+ (PRAvailable64FN)_PR_InvalidInt64,
+ (PRFsyncFN)_PR_InvalidStatus,
+ (PRSeekFN)_PR_InvalidInt,
+ (PRSeek64FN)_PR_InvalidInt64,
+ (PRFileInfoFN)_PR_InvalidStatus,
+ (PRFileInfo64FN)_PR_InvalidStatus,
+ (PRWritevFN)_PR_InvalidInt,
+ (PRConnectFN)_PR_InvalidStatus,
+ (PRAcceptFN)_PR_InvalidDesc,
+ (PRBindFN)_PR_InvalidStatus,
+ (PRListenFN)_PR_InvalidStatus,
+ (PRShutdownFN)_PR_InvalidStatus,
+ (PRRecvFN)_PR_InvalidInt,
+ (PRSendFN)_PR_InvalidInt,
+ (PRRecvfromFN)_PR_InvalidInt,
+ (PRSendtoFN)_PR_InvalidInt,
+ pt_Poll,
+ (PRAcceptreadFN)_PR_InvalidInt,
+ (PRTransmitfileFN)_PR_InvalidInt,
+ (PRGetsocknameFN)_PR_InvalidStatus,
+ (PRGetpeernameFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRGetsocketoptionFN)_PR_InvalidStatus,
+ (PRSetsocketoptionFN)_PR_InvalidStatus,
+ (PRSendfileFN)_PR_InvalidInt,
+ (PRConnectcontinueFN)_PR_InvalidStatus,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt,
+ (PRReservedFN)_PR_InvalidInt
+};
+
+#if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \
+ || defined(AIX) || defined(LINUX) || defined(FREEBSD) || defined(NETBSD) \
+ || defined(OPENBSD) || defined(BSDI) || defined(VMS) || defined(NTO) \
+ || defined(DARWIN) || defined(UNIXWARE)
+#define _PR_FCNTL_FLAGS O_NONBLOCK
+#else
+#error "Can't determine architecture"
+#endif
+
+/*
+ * Put a Unix file descriptor in non-blocking mode.
+ */
+static void pt_MakeFdNonblock(PRIntn osfd)
+{
+ PRIntn flags;
+ flags = fcntl(osfd, F_GETFL, 0);
+ flags |= _PR_FCNTL_FLAGS;
+ (void)fcntl(osfd, F_SETFL, flags);
+}
+
+/*
+ * Put a Unix socket fd in non-blocking mode that can
+ * ideally be inherited by an accepted socket.
+ *
+ * Why doesn't pt_MakeFdNonblock do? This is to deal with
+ * the special case of HP-UX. HP-UX has three kinds of
+ * non-blocking modes for sockets: the fcntl() O_NONBLOCK
+ * and O_NDELAY flags and ioctl() FIOSNBIO request. Only
+ * the ioctl() FIOSNBIO form of non-blocking mode is
+ * inherited by an accepted socket.
+ *
+ * Other platforms just use the generic pt_MakeFdNonblock
+ * to put a socket in non-blocking mode.
+ */
+#ifdef HPUX
+static void pt_MakeSocketNonblock(PRIntn osfd)
+{
+ PRIntn one = 1;
+ (void)ioctl(osfd, FIOSNBIO, &one);
+}
+#else
+#define pt_MakeSocketNonblock pt_MakeFdNonblock
+#endif
+
+static PRFileDesc *pt_SetMethods(
+ PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported)
+{
+ PRFileDesc *fd = _PR_Getfd();
+
+ if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ fd->secret->md.osfd = osfd;
+ fd->secret->state = _PR_FILEDESC_OPEN;
+ if (imported) fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ else
+ {
+ /* By default, a Unix fd is not closed on exec. */
+ PRIntn flags;
+ flags = fcntl(osfd, F_GETFD, 0);
+ fd->secret->inheritable = flags & FD_CLOEXEC ? _PR_TRI_FALSE : _PR_TRI_TRUE;
+ }
+ switch (type)
+ {
+ case PR_DESC_FILE:
+ fd->methods = PR_GetFileMethods();
+ break;
+ case PR_DESC_SOCKET_TCP:
+ fd->methods = PR_GetTCPMethods();
+#ifdef _PR_ACCEPT_INHERIT_NONBLOCK
+ if (!isAcceptedSocket) pt_MakeSocketNonblock(osfd);
+#else
+ pt_MakeSocketNonblock(osfd);
+#endif
+ break;
+ case PR_DESC_SOCKET_UDP:
+ fd->methods = PR_GetUDPMethods();
+ pt_MakeFdNonblock(osfd);
+ break;
+ case PR_DESC_PIPE:
+ fd->methods = PR_GetPipeMethods();
+ pt_MakeFdNonblock(osfd);
+ break;
+ default:
+ break;
+ }
+ }
+ return fd;
+} /* pt_SetMethods */
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)
+{
+ return &_pr_file_methods;
+} /* PR_GetFileMethods */
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)
+{
+ return &_pr_pipe_methods;
+} /* PR_GetPipeMethods */
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods(void)
+{
+ return &_pr_tcp_methods;
+} /* PR_GetTCPMethods */
+
+PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods(void)
+{
+ return &_pr_udp_methods;
+} /* PR_GetUDPMethods */
+
+static const PRIOMethods* PR_GetSocketPollFdMethods(void)
+{
+ return &_pr_socketpollfd_methods;
+} /* PR_GetSocketPollFdMethods */
+
+PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(
+ PRInt32 osfd, const PRIOMethods *methods)
+{
+ PRFileDesc *fd = _PR_Getfd();
+
+ if (NULL == fd) goto failed;
+
+ fd->methods = methods;
+ fd->secret->md.osfd = osfd;
+ /* Make fd non-blocking */
+ if (osfd > 2)
+ {
+ /* Don't mess around with stdin, stdout or stderr */
+ if (&_pr_tcp_methods == methods) pt_MakeSocketNonblock(osfd);
+ else pt_MakeFdNonblock(osfd);
+ }
+ fd->secret->state = _PR_FILEDESC_OPEN;
+ fd->secret->inheritable = _PR_TRI_UNKNOWN;
+ return fd;
+
+failed:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return fd;
+} /* PR_AllocFileDesc */
+
+#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
+PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
+#if defined(_PR_INET6_PROBE)
+PR_EXTERN(PRBool) _pr_ipv6_is_present;
+PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket()
+{
+PRInt32 osfd;
+
+#if defined(DARWIN)
+ /*
+ * Disable IPv6 if Darwin version is less than 7.0.0 (OS X 10.3). IPv6 on
+ * lesser versions is not ready for general use (see bug 222031).
+ */
+ {
+ struct utsname u;
+ if (uname(&u) != 0 || atoi(u.release) < 7)
+ return PR_FALSE;
+ }
+#endif
+
+ /*
+ * HP-UX only: HP-UX IPv6 Porting Guide (dated February 2001)
+ * suggests that we call open("/dev/ip6", O_RDWR) to determine
+ * whether IPv6 APIs and the IPv6 stack are on the system.
+ * Our portable test below seems to work fine, so I am using it.
+ */
+ osfd = socket(AF_INET6, SOCK_STREAM, 0);
+ if (osfd != -1) {
+ close(osfd);
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+#endif /* _PR_INET6_PROBE */
+#endif
+
+PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
+{
+ PRIntn osfd;
+ PRDescType ftype;
+ PRFileDesc *fd = NULL;
+ PRInt32 tmp_domain = domain;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (pt_TestAbort()) return NULL;
+
+ if (PF_INET != domain
+ && PR_AF_INET6 != domain
+ && PF_UNIX != domain)
+ {
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+ return fd;
+ }
+ if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP;
+ else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP;
+ else
+ {
+ (void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+ return fd;
+ }
+#if defined(_PR_INET6_PROBE)
+ if (PR_AF_INET6 == domain) {
+ if (_pr_ipv6_is_present == PR_FALSE)
+ domain = AF_INET;
+ else
+ domain = AF_INET6;
+ }
+#elif defined(_PR_INET6)
+ if (PR_AF_INET6 == domain)
+ domain = AF_INET6;
+#else
+ if (PR_AF_INET6 == domain)
+ domain = AF_INET;
+#endif
+
+ osfd = socket(domain, type, proto);
+ if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno);
+ else
+ {
+#ifdef DARWIN
+ if ((domain == AF_INET6) && _pr_ipv6_v6only_on_by_default)
+ {
+ int on = 0;
+ (void)setsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY,
+ &on, sizeof(on));
+ }
+#endif
+ fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE);
+ if (fd == NULL) close(osfd);
+ }
+#ifdef _PR_STRICT_ADDR_LEN
+ if (fd != NULL) fd->secret->af = domain;
+#endif
+#if defined(_PR_INET6_PROBE) || !defined(_PR_INET6)
+ if (fd != NULL) {
+ /*
+ * For platforms with no support for IPv6
+ * create layered socket for IPv4-mapped IPv6 addresses
+ */
+ if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) {
+ if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
+ PR_Close(fd);
+ fd = NULL;
+ }
+ }
+ }
+#endif
+ return fd;
+} /* PR_Socket */
+
+/*****************************************************************************/
+/****************************** I/O public methods ***************************/
+/*****************************************************************************/
+
+PR_IMPLEMENT(PRFileDesc*) PR_OpenFile(
+ const char *name, PRIntn flags, PRIntn mode)
+{
+ PRFileDesc *fd = NULL;
+ PRIntn syserrno, osfd = -1, osflags = 0;;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (pt_TestAbort()) return NULL;
+
+ if (flags & PR_RDONLY) osflags |= O_RDONLY;
+ if (flags & PR_WRONLY) osflags |= O_WRONLY;
+ if (flags & PR_RDWR) osflags |= O_RDWR;
+ if (flags & PR_APPEND) osflags |= O_APPEND;
+ if (flags & PR_TRUNCATE) osflags |= O_TRUNC;
+ if (flags & PR_EXCL) osflags |= O_EXCL;
+ if (flags & PR_SYNC)
+ {
+#if defined(O_SYNC)
+ osflags |= O_SYNC;
+#elif defined(O_FSYNC)
+ osflags |= O_FSYNC;
+#else
+#error "Neither O_SYNC nor O_FSYNC is defined on this platform"
+#endif
+ }
+
+ /*
+ ** We have to hold the lock across the creation in order to
+ ** enforce the sematics of PR_Rename(). (see the latter for
+ ** more details)
+ */
+ if (flags & PR_CREATE_FILE)
+ {
+ osflags |= O_CREAT;
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ }
+
+ osfd = _md_iovector._open64(name, osflags, mode);
+ syserrno = errno;
+
+ if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
+ PR_Unlock(_pr_rename_lock);
+
+ if (osfd == -1)
+ pt_MapError(_PR_MD_MAP_OPEN_ERROR, syserrno);
+ else
+ {
+ fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_FALSE);
+ if (fd == NULL) close(osfd); /* $$$ whoops! this is bad $$$ */
+ }
+ return fd;
+} /* PR_OpenFile */
+
+PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode)
+{
+ return PR_OpenFile(name, flags, mode);
+} /* PR_Open */
+
+PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)
+{
+ PRIntn rv = -1;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = unlink(name);
+
+ if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_UNLINK_ERROR, errno);
+ return PR_FAILURE;
+ } else
+ return PR_SUCCESS;
+} /* PR_Delete */
+
+PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how)
+{
+ PRIntn rv;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ switch (how)
+ {
+ case PR_ACCESS_READ_OK:
+ rv = access(name, R_OK);
+ break;
+ case PR_ACCESS_WRITE_OK:
+ rv = access(name, W_OK);
+ break;
+ case PR_ACCESS_EXISTS:
+ default:
+ rv = access(name, F_OK);
+ }
+ if (0 == rv) return PR_SUCCESS;
+ pt_MapError(_PR_MD_MAP_ACCESS_ERROR, errno);
+ return PR_FAILURE;
+
+} /* PR_Access */
+
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)
+{
+ PRInt32 rv = _PR_MD_GETFILEINFO(fn, info);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+} /* PR_GetFileInfo */
+
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info)
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ rv = _PR_MD_GETFILEINFO64(fn, info);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+} /* PR_GetFileInfo64 */
+
+PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to)
+{
+ PRIntn rv = -1;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ /*
+ ** We have to acquire a lock here to stiffle anybody trying to create
+ ** a new file at the same time. And we have to hold that lock while we
+ ** test to see if the file exists and do the rename. The other place
+ ** where the lock is held is in PR_Open() when possibly creating a
+ ** new file.
+ */
+
+ PR_Lock(_pr_rename_lock);
+ rv = access(to, F_OK);
+ if (0 == rv)
+ {
+ PR_SetError(PR_FILE_EXISTS_ERROR, 0);
+ rv = -1;
+ }
+ else
+ {
+ rv = rename(from, to);
+ if (rv == -1)
+ pt_MapError(_PR_MD_MAP_RENAME_ERROR, errno);
+ }
+ PR_Unlock(_pr_rename_lock);
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
+} /* PR_Rename */
+
+PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir)
+{
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ if (NULL != dir->md.d)
+ {
+ if (closedir(dir->md.d) == -1)
+ {
+ _PR_MD_MAP_CLOSEDIR_ERROR(errno);
+ return PR_FAILURE;
+ }
+ dir->md.d = NULL;
+ PR_DELETE(dir);
+ }
+ return PR_SUCCESS;
+} /* PR_CloseDir */
+
+PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode)
+{
+ PRInt32 rv = -1;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ /*
+ ** This lock is used to enforce rename semantics as described
+ ** in PR_Rename.
+ */
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ rv = mkdir(name, mode);
+ if (-1 == rv)
+ pt_MapError(_PR_MD_MAP_MKDIR_ERROR, errno);
+ if (NULL !=_pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+
+ return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;
+} /* PR_Makedir */
+
+PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode)
+{
+ return PR_MakeDir(name, mode);
+} /* PR_Mkdir */
+
+PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name)
+{
+ PRInt32 rv;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ rv = rmdir(name);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ } else {
+ pt_MapError(_PR_MD_MAP_RMDIR_ERROR, errno);
+ return PR_FAILURE;
+ }
+} /* PR_Rmdir */
+
+
+PR_IMPLEMENT(PRDir*) PR_OpenDir(const char *name)
+{
+ DIR *osdir;
+ PRDir *dir = NULL;
+
+ if (pt_TestAbort()) return dir;
+
+ osdir = opendir(name);
+ if (osdir == NULL)
+ pt_MapError(_PR_MD_MAP_OPENDIR_ERROR, errno);
+ else
+ {
+ dir = PR_NEWZAP(PRDir);
+ dir->md.d = osdir;
+ }
+ return dir;
+} /* PR_OpenDir */
+
+static PRInt32 _pr_poll_with_poll(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRInt32 ready = 0;
+ /*
+ * For restarting poll() if it is interrupted by a signal.
+ * We use these variables to figure out how much time has
+ * elapsed and how much of the timeout still remains.
+ */
+ PRIntervalTime start, elapsed, remaining;
+
+ if (pt_TestAbort()) return -1;
+
+ if (0 == npds) PR_Sleep(timeout);
+ else
+ {
+#define STACK_POLL_DESC_COUNT 64
+ struct pollfd stack_syspoll[STACK_POLL_DESC_COUNT];
+ struct pollfd *syspoll;
+ PRIntn index, msecs;
+
+ if (npds <= STACK_POLL_DESC_COUNT)
+ {
+ syspoll = stack_syspoll;
+ }
+ else
+ {
+ PRThread *me = PR_GetCurrentThread();
+ if (npds > me->syspoll_count)
+ {
+ PR_Free(me->syspoll_list);
+ me->syspoll_list =
+ (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));
+ if (NULL == me->syspoll_list)
+ {
+ me->syspoll_count = 0;
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ me->syspoll_count = npds;
+ }
+ syspoll = me->syspoll_list;
+ }
+
+ for (index = 0; index < npds; ++index)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (pds[index].in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_WRITE,
+ &out_flags_read);
+ }
+ if (pds[index].in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_READ,
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one is ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will return without calling the system
+ * poll function. So zero the out_flags
+ * fields of all the poll descriptors before
+ * this one.
+ */
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1;
+ pds[index].out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ /* now locate the NSPR layer at the bottom of the stack */
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(
+ pds[index].fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ pds[index].out_flags = 0; /* pre-condition */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ syspoll[index].fd = bottom->secret->md.osfd;
+ syspoll[index].events = 0;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_READ;
+ syspoll[index].events |= POLLIN;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_WRITE;
+ syspoll[index].events |= POLLOUT;
+ }
+ if (pds[index].in_flags & PR_POLL_EXCEPT)
+ syspoll[index].events |= POLLPRI;
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pds[index].out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ /* make poll() ignore this entry */
+ syspoll[index].fd = -1;
+ syspoll[index].events = 0;
+ pds[index].out_flags = 0;
+ }
+ }
+ if (0 == ready)
+ {
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT: msecs = 0; break;
+ case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;
+ default:
+ msecs = PR_IntervalToMilliseconds(timeout);
+ start = PR_IntervalNow();
+ }
+
+retry:
+ ready = poll(syspoll, npds, msecs);
+ if (-1 == ready)
+ {
+ PRIntn oserror = errno;
+
+ if (EINTR == oserror)
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ goto retry;
+ else if (timeout == PR_INTERVAL_NO_WAIT)
+ ready = 0; /* don't retry, just time out */
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow()
+ - start);
+ if (elapsed > timeout)
+ ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ msecs = PR_IntervalToMilliseconds(remaining);
+ goto retry;
+ }
+ }
+ }
+ else
+ {
+ _PR_MD_MAP_POLL_ERROR(oserror);
+ }
+ }
+ else if (ready > 0)
+ {
+ for (index = 0; index < npds; ++index)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (0 != syspoll[index].revents)
+ {
+ if (syspoll[index].revents & POLLIN)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_READ)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_READ)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLOUT)
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (syspoll[index].revents & POLLPRI)
+ out_flags |= PR_POLL_EXCEPT;
+ if (syspoll[index].revents & POLLERR)
+ out_flags |= PR_POLL_ERR;
+ if (syspoll[index].revents & POLLNVAL)
+ out_flags |= PR_POLL_NVAL;
+ if (syspoll[index].revents & POLLHUP)
+ out_flags |= PR_POLL_HUP;
+ }
+ }
+ pds[index].out_flags = out_flags;
+ }
+ }
+ }
+ }
+ return ready;
+
+} /* _pr_poll_with_poll */
+
+#if defined(_PR_POLL_WITH_SELECT)
+/*
+ * OSF1 and HPUX report the POLLHUP event for a socket when the
+ * shutdown(SHUT_WR) operation is called for the remote end, even though
+ * the socket is still writeable. Use select(), instead of poll(), to
+ * workaround this problem.
+ */
+static PRInt32 _pr_poll_with_select(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRInt32 ready = 0;
+ /*
+ * For restarting select() if it is interrupted by a signal.
+ * We use these variables to figure out how much time has
+ * elapsed and how much of the timeout still remains.
+ */
+ PRIntervalTime start, elapsed, remaining;
+
+ if (pt_TestAbort()) return -1;
+
+ if (0 == npds) PR_Sleep(timeout);
+ else
+ {
+#define STACK_POLL_DESC_COUNT 64
+ int stack_selectfd[STACK_POLL_DESC_COUNT];
+ int *selectfd;
+ fd_set rd, wr, ex, *rdp = NULL, *wrp = NULL, *exp = NULL;
+ struct timeval tv, *tvp;
+ PRIntn index, msecs, maxfd = 0;
+
+ if (npds <= STACK_POLL_DESC_COUNT)
+ {
+ selectfd = stack_selectfd;
+ }
+ else
+ {
+ PRThread *me = PR_GetCurrentThread();
+ if (npds > me->selectfd_count)
+ {
+ PR_Free(me->selectfd_list);
+ me->selectfd_list = (int *)PR_MALLOC(npds * sizeof(int));
+ if (NULL == me->selectfd_list)
+ {
+ me->selectfd_count = 0;
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return -1;
+ }
+ me->selectfd_count = npds;
+ }
+ selectfd = me->selectfd_list;
+ }
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+
+ for (index = 0; index < npds; ++index)
+ {
+ PRInt16 in_flags_read = 0, in_flags_write = 0;
+ PRInt16 out_flags_read = 0, out_flags_write = 0;
+
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (pds[index].in_flags & PR_POLL_READ)
+ {
+ in_flags_read = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_WRITE,
+ &out_flags_read);
+ }
+ if (pds[index].in_flags & PR_POLL_WRITE)
+ {
+ in_flags_write = (pds[index].fd->methods->poll)(
+ pds[index].fd,
+ pds[index].in_flags & ~PR_POLL_READ,
+ &out_flags_write);
+ }
+ if ((0 != (in_flags_read & out_flags_read))
+ || (0 != (in_flags_write & out_flags_write)))
+ {
+ /* this one is ready right now */
+ if (0 == ready)
+ {
+ /*
+ * We will return without calling the system
+ * poll function. So zero the out_flags
+ * fields of all the poll descriptors before
+ * this one.
+ */
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1;
+ pds[index].out_flags = out_flags_read | out_flags_write;
+ }
+ else
+ {
+ /* now locate the NSPR layer at the bottom of the stack */
+ PRFileDesc *bottom = PR_GetIdentitiesLayer(
+ pds[index].fd, PR_NSPR_IO_LAYER);
+ PR_ASSERT(NULL != bottom); /* what to do about that? */
+ pds[index].out_flags = 0; /* pre-condition */
+ if ((NULL != bottom)
+ && (_PR_FILEDESC_OPEN == bottom->secret->state))
+ {
+ if (0 == ready)
+ {
+ PRBool add_to_rd = PR_FALSE;
+ PRBool add_to_wr = PR_FALSE;
+ PRBool add_to_ex = PR_FALSE;
+
+ selectfd[index] = bottom->secret->md.osfd;
+ if (in_flags_read & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_READ;
+ add_to_rd = PR_TRUE;
+ }
+ if (in_flags_read & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_READ_SYS_WRITE;
+ add_to_wr = PR_TRUE;
+ }
+ if (in_flags_write & PR_POLL_READ)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_READ;
+ add_to_rd = PR_TRUE;
+ }
+ if (in_flags_write & PR_POLL_WRITE)
+ {
+ pds[index].out_flags |=
+ _PR_POLL_WRITE_SYS_WRITE;
+ add_to_wr = PR_TRUE;
+ }
+ if (pds[index].in_flags & PR_POLL_EXCEPT)
+ {
+ add_to_ex = PR_TRUE;
+ }
+ if ((selectfd[index] > maxfd) &&
+ (add_to_rd || add_to_wr || add_to_ex))
+ {
+ maxfd = selectfd[index];
+ /*
+ * If maxfd is too large to be used with
+ * select, fall back to calling poll.
+ */
+ if (maxfd >= FD_SETSIZE)
+ break;
+ }
+ if (add_to_rd)
+ {
+ FD_SET(bottom->secret->md.osfd, &rd);
+ rdp = &rd;
+ }
+ if (add_to_wr)
+ {
+ FD_SET(bottom->secret->md.osfd, &wr);
+ wrp = &wr;
+ }
+ if (add_to_ex)
+ {
+ FD_SET(bottom->secret->md.osfd, &ex);
+ exp = &ex;
+ }
+ }
+ }
+ else
+ {
+ if (0 == ready)
+ {
+ int i;
+ for (i = 0; i < index; i++)
+ {
+ pds[i].out_flags = 0;
+ }
+ }
+ ready += 1; /* this will cause an abrupt return */
+ pds[index].out_flags = PR_POLL_NVAL; /* bogii */
+ }
+ }
+ }
+ else
+ {
+ pds[index].out_flags = 0;
+ }
+ }
+ if (0 == ready)
+ {
+ if (maxfd >= FD_SETSIZE)
+ {
+ /*
+ * maxfd too large to be used with select, fall back to
+ * calling poll
+ */
+ return(_pr_poll_with_poll(pds, npds, timeout));
+ }
+ switch (timeout)
+ {
+ case PR_INTERVAL_NO_WAIT:
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ tvp = NULL;
+ break;
+ default:
+ msecs = PR_IntervalToMilliseconds(timeout);
+ tv.tv_sec = msecs/PR_MSEC_PER_SEC;
+ tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC;
+ tvp = &tv;
+ start = PR_IntervalNow();
+ }
+
+retry:
+ ready = select(maxfd + 1, rdp, wrp, exp, tvp);
+ if (-1 == ready)
+ {
+ PRIntn oserror = errno;
+
+ if ((EINTR == oserror) || (EAGAIN == oserror))
+ {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ goto retry;
+ else if (timeout == PR_INTERVAL_NO_WAIT)
+ ready = 0; /* don't retry, just time out */
+ else
+ {
+ elapsed = (PRIntervalTime) (PR_IntervalNow()
+ - start);
+ if (elapsed > timeout)
+ ready = 0; /* timed out */
+ else
+ {
+ remaining = timeout - elapsed;
+ msecs = PR_IntervalToMilliseconds(remaining);
+ tv.tv_sec = msecs/PR_MSEC_PER_SEC;
+ tv.tv_usec = (msecs % PR_MSEC_PER_SEC) *
+ PR_USEC_PER_MSEC;
+ goto retry;
+ }
+ }
+ } else if (EBADF == oserror)
+ {
+ /* find all the bad fds */
+ ready = 0;
+ for (index = 0; index < npds; ++index)
+ {
+ pds[index].out_flags = 0;
+ if ((NULL != pds[index].fd) &&
+ (0 != pds[index].in_flags))
+ {
+ if (fcntl(selectfd[index], F_GETFL, 0) == -1)
+ {
+ pds[index].out_flags = PR_POLL_NVAL;
+ ready++;
+ }
+ }
+ }
+ } else
+ _PR_MD_MAP_SELECT_ERROR(oserror);
+ }
+ else if (ready > 0)
+ {
+ for (index = 0; index < npds; ++index)
+ {
+ PRInt16 out_flags = 0;
+ if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))
+ {
+ if (FD_ISSET(selectfd[index], &rd))
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_READ)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_READ)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (FD_ISSET(selectfd[index], &wr))
+ {
+ if (pds[index].out_flags
+ & _PR_POLL_READ_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_READ;
+ }
+ if (pds[index].out_flags
+ & _PR_POLL_WRITE_SYS_WRITE)
+ {
+ out_flags |= PR_POLL_WRITE;
+ }
+ }
+ if (FD_ISSET(selectfd[index], &ex))
+ out_flags |= PR_POLL_EXCEPT;
+ }
+ pds[index].out_flags = out_flags;
+ }
+ }
+ }
+ }
+ return ready;
+
+} /* _pr_poll_with_select */
+#endif /* _PR_POLL_WITH_SELECT */
+
+PR_IMPLEMENT(PRInt32) PR_Poll(
+ PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+#if defined(_PR_POLL_WITH_SELECT)
+ return(_pr_poll_with_select(pds, npds, timeout));
+#else
+ return(_pr_poll_with_poll(pds, npds, timeout));
+#endif
+}
+
+PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags)
+{
+ struct dirent *dp;
+
+ if (pt_TestAbort()) return NULL;
+
+ for (;;)
+ {
+ dp = readdir(dir->md.d);
+ if (NULL == dp) return NULL;
+ if ((flags & PR_SKIP_DOT)
+ && ('.' == dp->d_name[0])
+ && (0 == dp->d_name[1])) continue;
+ if ((flags & PR_SKIP_DOT_DOT)
+ && ('.' == dp->d_name[0])
+ && ('.' == dp->d_name[1])
+ && (0 == dp->d_name[2])) continue;
+ if ((flags & PR_SKIP_HIDDEN) && ('.' == dp->d_name[0]))
+ continue;
+ break;
+ }
+ dir->d.name = dp->d_name;
+ return &dir->d;
+} /* PR_ReadDir */
+
+PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void)
+{
+ PRIntn domain = PF_INET;
+
+ return PR_Socket(domain, SOCK_DGRAM, 0);
+} /* PR_NewUDPSocket */
+
+PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket(void)
+{
+ PRIntn domain = PF_INET;
+
+ return PR_Socket(domain, SOCK_STREAM, 0);
+} /* PR_NewTCPSocket */
+
+PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af)
+{
+ return PR_Socket(af, SOCK_DGRAM, 0);
+} /* PR_NewUDPSocket */
+
+PR_IMPLEMENT(PRFileDesc*) PR_OpenTCPSocket(PRIntn af)
+{
+ return PR_Socket(af, SOCK_STREAM, 0);
+} /* PR_NewTCPSocket */
+
+PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *fds[2])
+{
+ PRInt32 osfd[2];
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, osfd) == -1) {
+ pt_MapError(_PR_MD_MAP_SOCKETPAIR_ERROR, errno);
+ return PR_FAILURE;
+ }
+
+ fds[0] = pt_SetMethods(osfd[0], PR_DESC_SOCKET_TCP, PR_FALSE, PR_FALSE);
+ if (fds[0] == NULL) {
+ close(osfd[0]);
+ close(osfd[1]);
+ return PR_FAILURE;
+ }
+ fds[1] = pt_SetMethods(osfd[1], PR_DESC_SOCKET_TCP, PR_FALSE, PR_FALSE);
+ if (fds[1] == NULL) {
+ PR_Close(fds[0]);
+ close(osfd[1]);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* PR_NewTCPSocketPair */
+
+PR_IMPLEMENT(PRStatus) PR_CreatePipe(
+ PRFileDesc **readPipe,
+ PRFileDesc **writePipe
+)
+{
+ int pipefd[2];
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ if (pipe(pipefd) == -1)
+ {
+ /* XXX map pipe error */
+ PR_SetError(PR_UNKNOWN_ERROR, errno);
+ return PR_FAILURE;
+ }
+ fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
+ fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
+ *readPipe = pt_SetMethods(pipefd[0], PR_DESC_PIPE, PR_FALSE, PR_FALSE);
+ if (NULL == *readPipe)
+ {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return PR_FAILURE;
+ }
+ *writePipe = pt_SetMethods(pipefd[1], PR_DESC_PIPE, PR_FALSE, PR_FALSE);
+ if (NULL == *writePipe)
+ {
+ PR_Close(*readPipe);
+ close(pipefd[1]);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+/*
+** Set the inheritance attribute of a file descriptor.
+*/
+PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(
+ PRFileDesc *fd,
+ PRBool inheritable)
+{
+ /*
+ * Only a non-layered, NSPR file descriptor can be inherited
+ * by a child process.
+ */
+ if (fd->identity != PR_NSPR_IO_LAYER)
+ {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (fd->secret->inheritable != inheritable)
+ {
+ if (fcntl(fd->secret->md.osfd, F_SETFD,
+ inheritable ? 0 : FD_CLOEXEC) == -1)
+ {
+ return PR_FAILURE;
+ }
+ fd->secret->inheritable = (_PRTriStateBool) inheritable;
+ }
+ return PR_SUCCESS;
+}
+
+/*****************************************************************************/
+/***************************** I/O friends methods ***************************/
+/*****************************************************************************/
+
+PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd)
+{
+ PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_TRUE);
+ if (NULL == fd) close(osfd);
+ return fd;
+} /* PR_ImportFile */
+
+PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PRInt32 osfd)
+{
+ PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ fd = pt_SetMethods(osfd, PR_DESC_PIPE, PR_FALSE, PR_TRUE);
+ if (NULL == fd) close(osfd);
+ return fd;
+} /* PR_ImportPipe */
+
+PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd)
+{
+ PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE);
+ if (NULL == fd) close(osfd);
+#ifdef _PR_STRICT_ADDR_LEN
+ if (NULL != fd) fd->secret->af = PF_INET;
+#endif
+ return fd;
+} /* PR_ImportTCPSocket */
+
+PR_IMPLEMENT(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd)
+{
+ PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP, PR_FALSE, PR_TRUE);
+ if (NULL != fd) close(osfd);
+ return fd;
+} /* PR_ImportUDPSocket */
+
+PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PRInt32 osfd)
+{
+ PRFileDesc *fd;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ fd = _PR_Getfd();
+
+ if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ else
+ {
+ fd->secret->md.osfd = osfd;
+ fd->secret->inheritable = _PR_TRI_FALSE;
+ fd->secret->state = _PR_FILEDESC_OPEN;
+ fd->methods = PR_GetSocketPollFdMethods();
+ }
+
+ return fd;
+} /* PR_CreateSocketPollFD */
+
+PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd)
+{
+ if (NULL == fd)
+ {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
+ return PR_FAILURE;
+ }
+ fd->secret->state = _PR_FILEDESC_CLOSED;
+ _PR_Putfd(fd);
+ return PR_SUCCESS;
+} /* PR_DestroySocketPollFd */
+
+PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *bottom)
+{
+ PRInt32 osfd = -1;
+ bottom = (NULL == bottom) ?
+ NULL : PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);
+ if (NULL == bottom) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ else osfd = bottom->secret->md.osfd;
+ return osfd;
+} /* PR_FileDesc2NativeHandle */
+
+PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd,
+ PRInt32 handle)
+{
+ if (fd) fd->secret->md.osfd = handle;
+} /* PR_ChangeFileDescNativeHandle*/
+
+PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd)
+{
+ PRStatus status = PR_SUCCESS;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ PR_Lock(_pr_flock_lock);
+ while (-1 == fd->secret->lockCount)
+ PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT);
+ if (0 == fd->secret->lockCount)
+ {
+ fd->secret->lockCount = -1;
+ PR_Unlock(_pr_flock_lock);
+ status = _PR_MD_LOCKFILE(fd->secret->md.osfd);
+ PR_Lock(_pr_flock_lock);
+ fd->secret->lockCount = (PR_SUCCESS == status) ? 1 : 0;
+ PR_NotifyAllCondVar(_pr_flock_cv);
+ }
+ else
+ {
+ fd->secret->lockCount += 1;
+ }
+ PR_Unlock(_pr_flock_lock);
+
+ return status;
+} /* PR_LockFile */
+
+PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd)
+{
+ PRStatus status = PR_SUCCESS;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ PR_Lock(_pr_flock_lock);
+ if (0 == fd->secret->lockCount)
+ {
+ status = _PR_MD_TLOCKFILE(fd->secret->md.osfd);
+ if (PR_SUCCESS == status) fd->secret->lockCount = 1;
+ }
+ else fd->secret->lockCount += 1;
+ PR_Unlock(_pr_flock_lock);
+
+ return status;
+} /* PR_TLockFile */
+
+PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd)
+{
+ PRStatus status = PR_SUCCESS;
+
+ if (pt_TestAbort()) return PR_FAILURE;
+
+ PR_Lock(_pr_flock_lock);
+ if (fd->secret->lockCount == 1)
+ {
+ status = _PR_MD_UNLOCKFILE(fd->secret->md.osfd);
+ if (PR_SUCCESS == status) fd->secret->lockCount = 0;
+ }
+ else fd->secret->lockCount -= 1;
+ PR_Unlock(_pr_flock_lock);
+
+ return status;
+}
+
+/*
+ * The next two entry points should not be in the API, but they are
+ * defined here for historical (or hysterical) reasons.
+ */
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+static PRInt32 PR_GetSysfdTableMax(void)
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PRInt32 PR_GetSysfdTableMax(void)
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+{
+#if defined(XP_UNIX) && !defined(AIX) && !defined(VMS)
+ struct rlimit rlim;
+
+ if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0)
+ return -1;
+
+ return rlim.rlim_max;
+#elif defined(AIX) || defined(VMS)
+ return sysconf(_SC_OPEN_MAX);
+#endif
+}
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+static PRInt32 PR_SetSysfdTableSize(PRIntn table_size)
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+PRInt32 PR_SetSysfdTableSize(PRIntn table_size)
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+{
+#if defined(XP_UNIX) && !defined(AIX) && !defined(VMS)
+ struct rlimit rlim;
+ PRInt32 tableMax = PR_GetSysfdTableMax();
+
+ if (tableMax < 0) return -1;
+ rlim.rlim_max = tableMax;
+
+ /* Grow as much as we can; even if too big */
+ if ( rlim.rlim_max < table_size )
+ rlim.rlim_cur = rlim.rlim_max;
+ else
+ rlim.rlim_cur = table_size;
+
+ if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0)
+ return -1;
+
+ return rlim.rlim_cur;
+#elif defined(AIX) || defined(VMS)
+ return -1;
+#endif
+}
+
+/*
+ * PR_Stat is supported for backward compatibility; some existing Java
+ * code uses it. New code should use PR_GetFileInfo.
+ */
+
+#ifndef NO_NSPR_10_SUPPORT
+PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
+{
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_Stat", "PR_GetFileInfo");
+
+ if (pt_TestAbort()) return -1;
+
+ if (-1 == stat(name, buf)) {
+ pt_MapError(_PR_MD_MAP_STAT_ERROR, errno);
+ return -1;
+ } else {
+ return 0;
+ }
+}
+#endif /* ! NO_NSPR_10_SUPPORT */
+
+
+PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set)
+{
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_ZERO (PR_Select)", "PR_Poll");
+ memset(set, 0, sizeof(PR_fd_set));
+}
+
+PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set)
+{
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_SET (PR_Select)", "PR_Poll");
+ PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC );
+
+ set->harray[set->hsize++] = fh;
+}
+
+PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set)
+{
+ PRUint32 index, index2;
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_CLR (PR_Select)", "PR_Poll");
+
+ for (index = 0; index<set->hsize; index++)
+ if (set->harray[index] == fh) {
+ for (index2=index; index2 < (set->hsize-1); index2++) {
+ set->harray[index2] = set->harray[index2+1];
+ }
+ set->hsize--;
+ break;
+ }
+}
+
+PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set)
+{
+ PRUint32 index;
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_ISSET (PR_Select)", "PR_Poll");
+ for (index = 0; index<set->hsize; index++)
+ if (set->harray[index] == fh) {
+ return 1;
+ }
+ return 0;
+}
+
+PR_IMPLEMENT(void) PR_FD_NSET(PRInt32 fd, PR_fd_set *set)
+{
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_NSET (PR_Select)", "PR_Poll");
+ PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC );
+
+ set->narray[set->nsize++] = fd;
+}
+
+PR_IMPLEMENT(void) PR_FD_NCLR(PRInt32 fd, PR_fd_set *set)
+{
+ PRUint32 index, index2;
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_NCLR (PR_Select)", "PR_Poll");
+
+ for (index = 0; index<set->nsize; index++)
+ if (set->narray[index] == fd) {
+ for (index2=index; index2 < (set->nsize-1); index2++) {
+ set->narray[index2] = set->narray[index2+1];
+ }
+ set->nsize--;
+ break;
+ }
+}
+
+PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PRInt32 fd, PR_fd_set *set)
+{
+ PRUint32 index;
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete("PR_FD_NISSET (PR_Select)", "PR_Poll");
+ for (index = 0; index<set->nsize; index++)
+ if (set->narray[index] == fd) {
+ return 1;
+ }
+ return 0;
+}
+
+#include <sys/types.h>
+#include <sys/time.h>
+#if !defined(SUNOS4) && !defined(HPUX) && !defined(LINUX)
+#include <sys/select.h>
+#endif
+
+static PRInt32
+_PR_getset(PR_fd_set *pr_set, fd_set *set)
+{
+ PRUint32 index;
+ PRInt32 max = 0;
+
+ if (!pr_set)
+ return 0;
+
+ FD_ZERO(set);
+
+ /* First set the pr file handle osfds */
+ for (index=0; index<pr_set->hsize; index++) {
+ FD_SET(pr_set->harray[index]->secret->md.osfd, set);
+ if (pr_set->harray[index]->secret->md.osfd > max)
+ max = pr_set->harray[index]->secret->md.osfd;
+ }
+ /* Second set the native osfds */
+ for (index=0; index<pr_set->nsize; index++) {
+ FD_SET(pr_set->narray[index], set);
+ if (pr_set->narray[index] > max)
+ max = pr_set->narray[index];
+ }
+ return max;
+}
+
+static void
+_PR_setset(PR_fd_set *pr_set, fd_set *set)
+{
+ PRUint32 index, last_used;
+
+ if (!pr_set)
+ return;
+
+ for (last_used=0, index=0; index<pr_set->hsize; index++) {
+ if ( FD_ISSET(pr_set->harray[index]->secret->md.osfd, set) ) {
+ pr_set->harray[last_used++] = pr_set->harray[index];
+ }
+ }
+ pr_set->hsize = last_used;
+
+ for (last_used=0, index=0; index<pr_set->nsize; index++) {
+ if ( FD_ISSET(pr_set->narray[index], set) ) {
+ pr_set->narray[last_used++] = pr_set->narray[index];
+ }
+ }
+ pr_set->nsize = last_used;
+}
+
+PR_IMPLEMENT(PRInt32) PR_Select(
+ PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr,
+ PR_fd_set *pr_ex, PRIntervalTime timeout)
+{
+ fd_set rd, wr, ex;
+ struct timeval tv, *tvp;
+ PRInt32 max, max_fd;
+ PRInt32 rv;
+ /*
+ * For restarting select() if it is interrupted by a Unix signal.
+ * We use these variables to figure out how much time has elapsed
+ * and how much of the timeout still remains.
+ */
+ PRIntervalTime start, elapsed, remaining;
+
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete( "PR_Select", "PR_Poll");
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+
+ max_fd = _PR_getset(pr_rd, &rd);
+ max_fd = (max = _PR_getset(pr_wr, &wr))>max_fd?max:max_fd;
+ max_fd = (max = _PR_getset(pr_ex, &ex))>max_fd?max:max_fd;
+
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ tvp = NULL;
+ } else {
+ tv.tv_sec = (PRInt32)PR_IntervalToSeconds(timeout);
+ tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds(
+ timeout - PR_SecondsToInterval(tv.tv_sec));
+ tvp = &tv;
+ start = PR_IntervalNow();
+ }
+
+retry:
+ rv = select(max_fd + 1, (_PRSelectFdSetArg_t) &rd,
+ (_PRSelectFdSetArg_t) &wr, (_PRSelectFdSetArg_t) &ex, tvp);
+
+ if (rv == -1 && errno == EINTR) {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ goto retry;
+ } else {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout) {
+ rv = 0; /* timed out */
+ } else {
+ remaining = timeout - elapsed;
+ tv.tv_sec = (PRInt32)PR_IntervalToSeconds(remaining);
+ tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds(
+ remaining - PR_SecondsToInterval(tv.tv_sec));
+ goto retry;
+ }
+ }
+ }
+
+ if (rv > 0) {
+ _PR_setset(pr_rd, &rd);
+ _PR_setset(pr_wr, &wr);
+ _PR_setset(pr_ex, &ex);
+ } else if (rv == -1) {
+ pt_MapError(_PR_MD_MAP_SELECT_ERROR, errno);
+ }
+ return rv;
+}
+#endif /* defined(_PR_PTHREADS) */
+
+#ifdef MOZ_UNICODE
+/* ================ UTF16 Interfaces ================================ */
+PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16(
+ const PRUnichar *name, PRIntn flags, PRIntn mode)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDir *dir)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+/* ================ UTF16 Interfaces ================================ */
+#endif /* MOZ_UNICODE */
+
+/* ptio.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptmisc.c b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptmisc.c
new file mode 100644
index 00000000..920d00db
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptmisc.c
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: ptmisc.c
+** Descritpion: Implemenation of miscellaneous methods for pthreads
+*/
+
+#if defined(_PR_PTHREADS)
+
+#include "primpl.h"
+
+#include <stdio.h>
+#ifdef SOLARIS
+#include <thread.h>
+#endif
+
+#define PT_LOG(f)
+
+void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
+void _PR_InitStacks(void) {PT_LOG("_PR_InitStacks")}
+
+PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs)
+{
+#ifdef SOLARIS
+ thr_setconcurrency(numCPUs);
+#else
+ PT_LOG("PR_SetConcurrency");
+#endif
+}
+
+PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 flag)
+ {PT_LOG("PR_SetThreadRecycleMode")}
+
+#endif /* defined(_PR_PTHREADS) */
+
+/* ptmisc.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptsynch.c b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptsynch.c
new file mode 100644
index 00000000..50f756bc
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptsynch.c
@@ -0,0 +1,1126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: ptsynch.c
+** Descritpion: Implemenation for thread synchronization using pthreads
+** Exports: prlock.h, prcvar.h, prmon.h, prcmon.h
+*/
+
+#if defined(_PR_PTHREADS)
+
+#include "primpl.h"
+#include "obsolete/prsem.h"
+
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+static pthread_mutexattr_t _pt_mattr;
+static pthread_condattr_t _pt_cvar_attr;
+
+#if defined(DEBUG)
+extern PTDebug pt_debug; /* this is shared between several modules */
+
+#if defined(_PR_DCETHREADS)
+static pthread_t pt_zero_tid; /* a null pthread_t (pthread_t is a struct
+ * in DCE threads) to compare with */
+#endif /* defined(_PR_DCETHREADS) */
+#endif /* defined(DEBUG) */
+
+/**************************************************************/
+/**************************************************************/
+/*****************************LOCKS****************************/
+/**************************************************************/
+/**************************************************************/
+
+void _PR_InitLocks(void)
+{
+ int rv;
+ rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr);
+ PR_ASSERT(0 == rv);
+
+#ifdef LINUX
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
+ rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
+ PR_ASSERT(0 == rv);
+#endif
+#endif
+
+ rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr);
+ PR_ASSERT(0 == rv);
+}
+
+static void pt_PostNotifies(PRLock *lock, PRBool unlock)
+{
+ PRIntn index, rv;
+ _PT_Notified post;
+ _PT_Notified *notified, *prev = NULL;
+ /*
+ * Time to actually notify any conditions that were affected
+ * while the lock was held. Get a copy of the list that's in
+ * the lock structure and then zero the original. If it's
+ * linked to other such structures, we own that storage.
+ */
+ post = lock->notified; /* a safe copy; we own the lock */
+
+#if defined(DEBUG)
+ memset(&lock->notified, 0, sizeof(_PT_Notified)); /* reset */
+#else
+ lock->notified.length = 0; /* these are really sufficient */
+ lock->notified.link = NULL;
+#endif
+
+ /* should (may) we release lock before notifying? */
+ if (unlock)
+ {
+ rv = pthread_mutex_unlock(&lock->mutex);
+ PR_ASSERT(0 == rv);
+ }
+
+ notified = &post; /* this is where we start */
+ do
+ {
+ for (index = 0; index < notified->length; ++index)
+ {
+ PRCondVar *cv = notified->cv[index].cv;
+ PR_ASSERT(NULL != cv);
+ PR_ASSERT(0 != notified->cv[index].times);
+ if (-1 == notified->cv[index].times)
+ {
+ rv = pthread_cond_broadcast(&cv->cv);
+ PR_ASSERT(0 == rv);
+ }
+ else
+ {
+ while (notified->cv[index].times-- > 0)
+ {
+ rv = pthread_cond_signal(&cv->cv);
+ PR_ASSERT(0 == rv);
+ }
+ }
+#if defined(DEBUG)
+ pt_debug.cvars_notified += 1;
+ if (0 > PR_AtomicDecrement(&cv->notify_pending))
+ {
+ pt_debug.delayed_cv_deletes += 1;
+ PR_DestroyCondVar(cv);
+ }
+#else /* defined(DEBUG) */
+ if (0 > PR_AtomicDecrement(&cv->notify_pending))
+ PR_DestroyCondVar(cv);
+#endif /* defined(DEBUG) */
+ }
+ prev = notified;
+ notified = notified->link;
+ if (&post != prev) PR_DELETE(prev);
+ } while (NULL != notified);
+} /* pt_PostNotifies */
+
+PR_IMPLEMENT(PRLock*) PR_NewLock(void)
+{
+ PRIntn rv;
+ PRLock *lock;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ lock = PR_NEWZAP(PRLock);
+ if (lock != NULL)
+ {
+ rv = _PT_PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr);
+ PR_ASSERT(0 == rv);
+ }
+#if defined(DEBUG)
+ pt_debug.locks_created += 1;
+#endif
+ return lock;
+} /* PR_NewLock */
+
+PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
+{
+ PRIntn rv;
+ PR_ASSERT(NULL != lock);
+ PR_ASSERT(PR_FALSE == lock->locked);
+ PR_ASSERT(0 == lock->notified.length);
+ PR_ASSERT(NULL == lock->notified.link);
+ rv = pthread_mutex_destroy(&lock->mutex);
+ PR_ASSERT(0 == rv);
+#if defined(DEBUG)
+ memset(lock, 0xaf, sizeof(PRLock));
+ pt_debug.locks_destroyed += 1;
+#endif
+ PR_DELETE(lock);
+} /* PR_DestroyLock */
+
+PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
+{
+ PRIntn rv;
+ PR_ASSERT(lock != NULL);
+ rv = pthread_mutex_lock(&lock->mutex);
+ PR_ASSERT(0 == rv);
+ PR_ASSERT(0 == lock->notified.length);
+ PR_ASSERT(NULL == lock->notified.link);
+ PR_ASSERT(PR_FALSE == lock->locked);
+ lock->locked = PR_TRUE;
+ lock->owner = pthread_self();
+#if defined(DEBUG)
+ pt_debug.locks_acquired += 1;
+#endif
+} /* PR_Lock */
+
+PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
+{
+ PRIntn rv;
+
+ PR_ASSERT(lock != NULL);
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex));
+ PR_ASSERT(PR_TRUE == lock->locked);
+ PR_ASSERT(pthread_equal(lock->owner, pthread_self()));
+
+ if (!lock->locked || !pthread_equal(lock->owner, pthread_self()))
+ return PR_FAILURE;
+
+ lock->locked = PR_FALSE;
+ if (0 == lock->notified.length) /* shortcut */
+ {
+ rv = pthread_mutex_unlock(&lock->mutex);
+ PR_ASSERT(0 == rv);
+ }
+ else pt_PostNotifies(lock, PR_TRUE);
+
+#if defined(DEBUG)
+ pt_debug.locks_released += 1;
+#endif
+ return PR_SUCCESS;
+} /* PR_Unlock */
+
+
+/**************************************************************/
+/**************************************************************/
+/***************************CONDITIONS*************************/
+/**************************************************************/
+/**************************************************************/
+
+
+/*
+ * This code is used to compute the absolute time for the wakeup.
+ * It's moderately ugly, so it's defined here and called in a
+ * couple of places.
+ */
+#define PT_NANOPERMICRO 1000UL
+#define PT_BILLION 1000000000UL
+
+static PRIntn pt_TimedWait(
+ pthread_cond_t *cv, pthread_mutex_t *ml, PRIntervalTime timeout)
+{
+ int rv;
+ struct timeval now;
+ struct timespec tmo;
+ PRUint32 ticks = PR_TicksPerSecond();
+
+ tmo.tv_sec = (PRInt32)(timeout / ticks);
+ tmo.tv_nsec = (PRInt32)(timeout - (tmo.tv_sec * ticks));
+ tmo.tv_nsec = (PRInt32)PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec);
+
+ /* pthreads wants this in absolute time, off we go ... */
+ (void)GETTIMEOFDAY(&now);
+ /* that one's usecs, this one's nsecs - grrrr! */
+ tmo.tv_sec += now.tv_sec;
+ tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec);
+ tmo.tv_sec += tmo.tv_nsec / PT_BILLION;
+ tmo.tv_nsec %= PT_BILLION;
+
+ rv = pthread_cond_timedwait(cv, ml, &tmo);
+
+ /* NSPR doesn't report timeouts */
+#ifdef _PR_DCETHREADS
+ if (rv == -1) return (errno == EAGAIN) ? 0 : errno;
+ else return rv;
+#else
+ return (rv == ETIMEDOUT) ? 0 : rv;
+#endif
+} /* pt_TimedWait */
+
+
+/*
+ * Notifies just get posted to the protecting mutex. The
+ * actual notification is done when the lock is released so that
+ * MP systems don't contend for a lock that they can't have.
+ */
+static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast)
+{
+ PRIntn index = 0;
+ _PT_Notified *notified = &cvar->lock->notified;
+
+ PR_ASSERT(PR_TRUE == cvar->lock->locked);
+ PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
+
+ while (1)
+ {
+ for (index = 0; index < notified->length; ++index)
+ {
+ if (notified->cv[index].cv == cvar)
+ {
+ if (broadcast)
+ notified->cv[index].times = -1;
+ else if (-1 != notified->cv[index].times)
+ notified->cv[index].times += 1;
+ goto finished; /* we're finished */
+ }
+ }
+ /* if not full, enter new CV in this array */
+ if (notified->length < PT_CV_NOTIFIED_LENGTH) break;
+
+ /* if there's no link, create an empty array and link it */
+ if (NULL == notified->link)
+ notified->link = PR_NEWZAP(_PT_Notified);
+ notified = notified->link;
+ }
+
+ /* A brand new entry in the array */
+ (void)PR_AtomicIncrement(&cvar->notify_pending);
+ notified->cv[index].times = (broadcast) ? -1 : 1;
+ notified->cv[index].cv = cvar;
+ notified->length += 1;
+
+finished:
+ PR_ASSERT(PR_TRUE == cvar->lock->locked);
+ PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
+} /* pt_PostNotifyToCvar */
+
+PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
+{
+ PRCondVar *cv = PR_NEW(PRCondVar);
+ PR_ASSERT(lock != NULL);
+ if (cv != NULL)
+ {
+ int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
+ PR_ASSERT(0 == rv);
+ cv->lock = lock;
+ cv->notify_pending = 0;
+#if defined(DEBUG)
+ pt_debug.cvars_created += 1;
+#endif
+ }
+ return cv;
+} /* PR_NewCondVar */
+
+PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
+{
+ if (0 > PR_AtomicDecrement(&cvar->notify_pending))
+ {
+ PRIntn rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
+#if defined(DEBUG)
+ memset(cvar, 0xaf, sizeof(PRCondVar));
+ pt_debug.cvars_destroyed += 1;
+#endif
+ PR_DELETE(cvar);
+ }
+} /* PR_DestroyCondVar */
+
+PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
+{
+ PRIntn rv;
+ PRThread *thred = PR_CurrentThread();
+
+ PR_ASSERT(cvar != NULL);
+ /* We'd better be locked */
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex));
+ PR_ASSERT(PR_TRUE == cvar->lock->locked);
+ /* and it better be by us */
+ PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self()));
+
+ if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
+
+ /*
+ * The thread waiting is used for PR_Interrupt
+ */
+ thred->waiting = cvar; /* this is where we're waiting */
+
+ /*
+ * If we have pending notifies, post them now.
+ *
+ * This is not optimal. We're going to post these notifies
+ * while we're holding the lock. That means on MP systems
+ * that they are going to collide for the lock that we will
+ * hold until we actually wait.
+ */
+ if (0 != cvar->lock->notified.length)
+ pt_PostNotifies(cvar->lock, PR_FALSE);
+
+ /*
+ * We're surrendering the lock, so clear out the locked field.
+ */
+ cvar->lock->locked = PR_FALSE;
+
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex);
+ else
+ rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout);
+
+ /* We just got the lock back - this better be empty */
+ PR_ASSERT(PR_FALSE == cvar->lock->locked);
+ cvar->lock->locked = PR_TRUE;
+ cvar->lock->owner = pthread_self();
+
+ PR_ASSERT(0 == cvar->lock->notified.length);
+ thred->waiting = NULL; /* and now we're not */
+ if (_PT_THREAD_INTERRUPTED(thred)) goto aborted;
+ if (rv != 0)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(rv);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+
+aborted:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ thred->state &= ~PT_THREAD_ABORTED;
+ return PR_FAILURE;
+} /* PR_WaitCondVar */
+
+PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
+{
+ PR_ASSERT(cvar != NULL);
+ pt_PostNotifyToCvar(cvar, PR_FALSE);
+ return PR_SUCCESS;
+} /* PR_NotifyCondVar */
+
+PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
+{
+ PR_ASSERT(cvar != NULL);
+ pt_PostNotifyToCvar(cvar, PR_TRUE);
+ return PR_SUCCESS;
+} /* PR_NotifyAllCondVar */
+
+/**************************************************************/
+/**************************************************************/
+/***************************MONITORS***************************/
+/**************************************************************/
+/**************************************************************/
+
+PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void)
+{
+ PRMonitor *mon;
+ PRCondVar *cvar;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ cvar = PR_NEWZAP(PRCondVar);
+ if (NULL == cvar)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ mon = PR_NEWZAP(PRMonitor);
+ if (mon != NULL)
+ {
+ int rv;
+ rv = _PT_PTHREAD_MUTEX_INIT(mon->lock.mutex, _pt_mattr);
+ PR_ASSERT(0 == rv);
+
+ _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
+
+ mon->cvar = cvar;
+ rv = _PT_PTHREAD_COND_INIT(mon->cvar->cv, _pt_cvar_attr);
+ PR_ASSERT(0 == rv);
+ mon->entryCount = 0;
+ mon->cvar->lock = &mon->lock;
+ if (0 != rv)
+ {
+ PR_DELETE(mon);
+ PR_DELETE(cvar);
+ mon = NULL;
+ }
+ }
+ return mon;
+} /* PR_NewMonitor */
+
+PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
+{
+ PRMonitor* mon = PR_NewMonitor();
+ if (mon)
+ mon->name = name;
+ return mon;
+}
+
+PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
+{
+ int rv;
+ PR_ASSERT(mon != NULL);
+ PR_DestroyCondVar(mon->cvar);
+ rv = pthread_mutex_destroy(&mon->lock.mutex); PR_ASSERT(0 == rv);
+#if defined(DEBUG)
+ memset(mon, 0xaf, sizeof(PRMonitor));
+#endif
+ PR_DELETE(mon);
+} /* PR_DestroyMonitor */
+
+
+/* The GC uses this; it is quite arguably a bad interface. I'm just
+ * duplicating it for now - XXXMB
+ */
+PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
+{
+ pthread_t self = pthread_self();
+ if (pthread_equal(mon->owner, self))
+ return mon->entryCount;
+ return 0;
+}
+
+PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
+{
+ pthread_t self = pthread_self();
+
+ PR_ASSERT(mon != NULL);
+ /*
+ * This is safe only if mon->owner (a pthread_t) can be
+ * read in one instruction. Perhaps mon->owner should be
+ * a "PRThread *"?
+ */
+ if (!pthread_equal(mon->owner, self))
+ {
+ PR_Lock(&mon->lock);
+ /* and now I have the lock */
+ PR_ASSERT(0 == mon->entryCount);
+ PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner));
+ _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner);
+ }
+ mon->entryCount += 1;
+} /* PR_EnterMonitor */
+
+PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
+{
+ pthread_t self = pthread_self();
+
+ PR_ASSERT(mon != NULL);
+ /* The lock better be that - locked */
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+ /* we'd better be the owner */
+ PR_ASSERT(pthread_equal(mon->owner, self));
+ if (!pthread_equal(mon->owner, self))
+ return PR_FAILURE;
+
+ /* if it's locked and we have it, then the entries should be > 0 */
+ PR_ASSERT(mon->entryCount > 0);
+ mon->entryCount -= 1; /* reduce by one */
+ if (mon->entryCount == 0)
+ {
+ /* and if it transitioned to zero - unlock */
+ _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); /* make the owner unknown */
+ PR_Unlock(&mon->lock);
+ }
+ return PR_SUCCESS;
+} /* PR_ExitMonitor */
+
+PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout)
+{
+ PRStatus rv;
+ PRInt16 saved_entries;
+ pthread_t saved_owner;
+
+ PR_ASSERT(mon != NULL);
+ /* we'd better be locked */
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+ /* and the entries better be positive */
+ PR_ASSERT(mon->entryCount > 0);
+ /* and it better be by us */
+ PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
+
+ /* tuck these away 'till later */
+ saved_entries = mon->entryCount;
+ mon->entryCount = 0;
+ _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner);
+ _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner);
+
+ rv = PR_WaitCondVar(mon->cvar, timeout);
+
+ /* reinstate the intresting information */
+ mon->entryCount = saved_entries;
+ _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner);
+
+ return rv;
+} /* PR_Wait */
+
+PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
+{
+ PR_ASSERT(NULL != mon);
+ /* we'd better be locked */
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+ /* and the entries better be positive */
+ PR_ASSERT(mon->entryCount > 0);
+ /* and it better be by us */
+ PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
+
+ pt_PostNotifyToCvar(mon->cvar, PR_FALSE);
+
+ return PR_SUCCESS;
+} /* PR_Notify */
+
+PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
+{
+ PR_ASSERT(mon != NULL);
+ /* we'd better be locked */
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(mon->lock.mutex));
+ /* and the entries better be positive */
+ PR_ASSERT(mon->entryCount > 0);
+ /* and it better be by us */
+ PR_ASSERT(pthread_equal(mon->owner, pthread_self()));
+
+ pt_PostNotifyToCvar(mon->cvar, PR_TRUE);
+
+ return PR_SUCCESS;
+} /* PR_NotifyAll */
+
+/**************************************************************/
+/**************************************************************/
+/**************************SEMAPHORES**************************/
+/**************************************************************/
+/**************************************************************/
+PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore)
+{
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete(
+ "PR_PostSem", "locks & condition variables");
+ PR_Lock(semaphore->cvar->lock);
+ PR_NotifyCondVar(semaphore->cvar);
+ semaphore->count += 1;
+ PR_Unlock(semaphore->cvar->lock);
+} /* PR_PostSem */
+
+PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *semaphore)
+{
+ PRStatus status = PR_SUCCESS;
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete(
+ "PR_WaitSem", "locks & condition variables");
+ PR_Lock(semaphore->cvar->lock);
+ while ((semaphore->count == 0) && (PR_SUCCESS == status))
+ status = PR_WaitCondVar(semaphore->cvar, PR_INTERVAL_NO_TIMEOUT);
+ if (PR_SUCCESS == status) semaphore->count -= 1;
+ PR_Unlock(semaphore->cvar->lock);
+ return status;
+} /* PR_WaitSem */
+
+PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *semaphore)
+{
+ static PRBool unwarned = PR_TRUE;
+ if (unwarned) unwarned = _PR_Obsolete(
+ "PR_DestroySem", "locks & condition variables");
+ PR_DestroyLock(semaphore->cvar->lock);
+ PR_DestroyCondVar(semaphore->cvar);
+ PR_DELETE(semaphore);
+} /* PR_DestroySem */
+
+PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
+{
+ PRSemaphore *semaphore;
+ static PRBool unwarned = PR_TRUE;
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (unwarned) unwarned = _PR_Obsolete(
+ "PR_NewSem", "locks & condition variables");
+
+ semaphore = PR_NEWZAP(PRSemaphore);
+ if (NULL != semaphore)
+ {
+ PRLock *lock = PR_NewLock();
+ if (NULL != lock)
+ {
+ semaphore->cvar = PR_NewCondVar(lock);
+ if (NULL != semaphore->cvar)
+ {
+ semaphore->count = value;
+ return semaphore;
+ }
+ PR_DestroyLock(lock);
+ }
+ PR_DELETE(semaphore);
+ }
+ return NULL;
+}
+
+/*
+ * Define the interprocess named semaphore functions.
+ * There are three implementations:
+ * 1. POSIX semaphore based;
+ * 2. System V semaphore based;
+ * 3. unsupported (fails with PR_NOT_IMPLEMENTED_ERROR).
+ */
+
+#ifdef _PR_HAVE_POSIX_SEMAPHORES
+#include <fcntl.h>
+
+PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
+ const char *name,
+ PRIntn flags,
+ PRIntn mode,
+ PRUintn value)
+{
+ PRSem *sem;
+ char osname[PR_IPC_NAME_SIZE];
+
+ if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
+ == PR_FAILURE)
+ {
+ return NULL;
+ }
+
+ sem = PR_NEW(PRSem);
+ if (NULL == sem)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ if (flags & PR_SEM_CREATE)
+ {
+ int oflag = O_CREAT;
+
+ if (flags & PR_SEM_EXCL) oflag |= O_EXCL;
+ sem->sem = sem_open(osname, oflag, mode, value);
+ }
+ else
+ {
+#ifdef HPUX
+ /* Pass 0 as the mode and value arguments to work around a bug. */
+ sem->sem = sem_open(osname, 0, 0, 0);
+#else
+ sem->sem = sem_open(osname, 0);
+#endif
+ }
+ if ((sem_t *) -1 == sem->sem)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ return sem;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
+{
+ int rv;
+ rv = sem_wait(sem->sem);
+ if (0 != rv)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
+{
+ int rv;
+ rv = sem_post(sem->sem);
+ if (0 != rv)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
+{
+ int rv;
+ rv = sem_close(sem->sem);
+ if (0 != rv)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ PR_DELETE(sem);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
+{
+ int rv;
+ char osname[PR_IPC_NAME_SIZE];
+
+ if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
+ == PR_FAILURE)
+ {
+ return PR_FAILURE;
+ }
+ rv = sem_unlink(osname);
+ if (0 != rv)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+#elif defined(_PR_HAVE_SYSV_SEMAPHORES)
+
+#include <fcntl.h>
+#include <sys/sem.h>
+
+/*
+ * From the semctl(2) man page in glibc 2.0
+ */
+#if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \
+ || defined(OPENBSD) || defined(BSDI)
+/* union semun is defined by including <sys/sem.h> */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+};
+#endif
+
+/*
+ * 'a' (97) is the final closing price of NSCP stock.
+ */
+#define NSPR_IPC_KEY_ID 'a' /* the id argument for ftok() */
+
+#define NSPR_SEM_MODE 0666
+
+PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
+ const char *name,
+ PRIntn flags,
+ PRIntn mode,
+ PRUintn value)
+{
+ PRSem *sem;
+ key_t key;
+ union semun arg;
+ struct sembuf sop;
+ struct semid_ds seminfo;
+#define MAX_TRIES 60
+ PRIntn i;
+ char osname[PR_IPC_NAME_SIZE];
+
+ if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
+ == PR_FAILURE)
+ {
+ return NULL;
+ }
+
+ /* Make sure the file exists before calling ftok. */
+ if (flags & PR_SEM_CREATE)
+ {
+ int osfd = open(osname, O_RDWR|O_CREAT, mode);
+ if (-1 == osfd)
+ {
+ _PR_MD_MAP_OPEN_ERROR(errno);
+ return NULL;
+ }
+ if (close(osfd) == -1)
+ {
+ _PR_MD_MAP_CLOSE_ERROR(errno);
+ return NULL;
+ }
+ }
+ key = ftok(osname, NSPR_IPC_KEY_ID);
+ if ((key_t)-1 == key)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return NULL;
+ }
+
+ sem = PR_NEW(PRSem);
+ if (NULL == sem)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ if (flags & PR_SEM_CREATE)
+ {
+ sem->semid = semget(key, 1, mode|IPC_CREAT|IPC_EXCL);
+ if (sem->semid >= 0)
+ {
+ /* creator of a semaphore is responsible for initializing it */
+ arg.val = 0;
+ if (semctl(sem->semid, 0, SETVAL, arg) == -1)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ /* call semop to set sem_otime to nonzero */
+ sop.sem_num = 0;
+ sop.sem_op = value;
+ sop.sem_flg = 0;
+ if (semop(sem->semid, &sop, 1) == -1)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ return sem;
+ }
+
+ if (errno != EEXIST || flags & PR_SEM_EXCL)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ }
+
+ sem->semid = semget(key, 1, NSPR_SEM_MODE);
+ if (sem->semid == -1)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ for (i = 0; i < MAX_TRIES; i++)
+ {
+ arg.buf = &seminfo;
+ semctl(sem->semid, 0, IPC_STAT, arg);
+ if (seminfo.sem_otime != 0) break;
+ sleep(1);
+ }
+ if (i == MAX_TRIES)
+ {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ return sem;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
+{
+ struct sembuf sop;
+
+ sop.sem_num = 0;
+ sop.sem_op = -1;
+ sop.sem_flg = 0;
+ if (semop(sem->semid, &sop, 1) == -1)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
+{
+ struct sembuf sop;
+
+ sop.sem_num = 0;
+ sop.sem_op = 1;
+ sop.sem_flg = 0;
+ if (semop(sem->semid, &sop, 1) == -1)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
+{
+ PR_DELETE(sem);
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
+{
+ key_t key;
+ int semid;
+ /* On some systems (e.g., glibc 2.0) semctl requires a fourth argument */
+ union semun unused;
+ char osname[PR_IPC_NAME_SIZE];
+
+ if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem)
+ == PR_FAILURE)
+ {
+ return PR_FAILURE;
+ }
+ key = ftok(osname, NSPR_IPC_KEY_ID);
+ if ((key_t) -1 == key)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ if (unlink(osname) == -1)
+ {
+ _PR_MD_MAP_UNLINK_ERROR(errno);
+ return PR_FAILURE;
+ }
+ semid = semget(key, 1, NSPR_SEM_MODE);
+ if (-1 == semid)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ unused.val = 0;
+ if (semctl(semid, 0, IPC_RMID, unused) == -1)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(errno);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+#else /* neither POSIX nor System V semaphores are available */
+
+PR_IMPLEMENT(PRSem *) PR_OpenSemaphore(
+ const char *name,
+ PRIntn flags,
+ PRIntn mode,
+ PRUintn value)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
+{
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return PR_FAILURE;
+}
+
+#endif /* end of interprocess named semaphore functions */
+
+/**************************************************************/
+/**************************************************************/
+/******************ROUTINES FOR DCE EMULATION******************/
+/**************************************************************/
+/**************************************************************/
+
+#include "prpdce.h"
+
+PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
+{
+ PRIntn rv = pthread_mutex_trylock(&lock->mutex);
+ if (rv == PT_TRYLOCK_SUCCESS)
+ {
+ PR_ASSERT(PR_FALSE == lock->locked);
+ lock->locked = PR_TRUE;
+ lock->owner = pthread_self();
+ }
+ /* XXX set error code? */
+ return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
+} /* PRP_TryLock */
+
+PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
+{
+ PRCondVar *cv;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ cv = PR_NEW(PRCondVar);
+ if (cv != NULL)
+ {
+ int rv;
+ rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr);
+ PR_ASSERT(0 == rv);
+ cv->lock = _PR_NAKED_CV_LOCK;
+ }
+ return cv;
+} /* PRP_NewNakedCondVar */
+
+PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
+{
+ int rv;
+ rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv);
+#if defined(DEBUG)
+ memset(cvar, 0xaf, sizeof(PRCondVar));
+#endif
+ PR_DELETE(cvar);
+} /* PRP_DestroyNakedCondVar */
+
+PR_IMPLEMENT(PRStatus) PRP_NakedWait(
+ PRCondVar *cvar, PRLock *ml, PRIntervalTime timeout)
+{
+ PRIntn rv;
+ PR_ASSERT(cvar != NULL);
+ /* XXX do we really want to assert this in a naked wait? */
+ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(ml->mutex));
+ if (timeout == PR_INTERVAL_NO_TIMEOUT)
+ rv = pthread_cond_wait(&cvar->cv, &ml->mutex);
+ else
+ rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout);
+ if (rv != 0)
+ {
+ _PR_MD_MAP_DEFAULT_ERROR(rv);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+} /* PRP_NakedWait */
+
+PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
+{
+ int rv;
+ PR_ASSERT(cvar != NULL);
+ rv = pthread_cond_signal(&cvar->cv);
+ PR_ASSERT(0 == rv);
+ return PR_SUCCESS;
+} /* PRP_NakedNotify */
+
+PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
+{
+ int rv;
+ PR_ASSERT(cvar != NULL);
+ rv = pthread_cond_broadcast(&cvar->cv);
+ PR_ASSERT(0 == rv);
+ return PR_SUCCESS;
+} /* PRP_NakedBroadcast */
+
+#endif /* defined(_PR_PTHREADS) */
+
+/* ptsynch.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptthread.c b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptthread.c
new file mode 100644
index 00000000..0a16f5d1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptthread.c
@@ -0,0 +1,1610 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: ptthread.c
+** Descritpion: Implemenation for threds using pthreds
+** Exports: ptthread.h
+*/
+
+#if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS)
+
+#include "prlog.h"
+#include "primpl.h"
+#include "prpdce.h"
+
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+# include <iprt/thread.h>
+# include <iprt/mem.h>
+# include <iprt/asm.h>
+# include <iprt/err.h>
+#endif /* VBOX_USE_IPRT_IN_NSPR */
+
+/*
+ * Record whether or not we have the privilege to set the scheduling
+ * policy and priority of threads. 0 means that privilege is available.
+ * EPERM means that privilege is not available.
+ */
+
+static PRIntn pt_schedpriv = 0;
+extern PRLock *_pr_sleeplock;
+
+static struct _PT_Bookeeping
+{
+ PRLock *ml; /* a lock to protect ourselves */
+ PRCondVar *cv; /* used to signal global things */
+ PRInt32 system, user; /* a count of the two different types */
+ PRUintn this_many; /* number of threads allowed for exit */
+ pthread_key_t key; /* private private data key */
+ PRThread *first, *last; /* list of threads we know about */
+#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ PRInt32 minPrio, maxPrio; /* range of scheduling priorities */
+#endif
+} pt_book = {0};
+
+static void _pt_thread_death(void *arg);
+static void init_pthread_gc_support(void);
+
+#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+static PRIntn pt_PriorityMap(PRThreadPriority pri)
+{
+#ifdef NTO
+ /* This priority algorithm causes lots of problems on Neutrino
+ * for now I have just hard coded everything to run at priority 10
+ * until I can come up with a new algorithm.
+ * Jerry.Kirk@Nexwarecorp.com
+ */
+ return 10;
+#else
+ return pt_book.minPrio +
+ pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST;
+#endif
+}
+#endif
+
+#if defined(GC_LEAK_DETECTOR) && (__GLIBC__ >= 2) && defined(__i386__)
+
+#include <setjmp.h>
+
+typedef struct stack_frame stack_frame;
+
+struct stack_frame {
+ stack_frame* next;
+ void* pc;
+};
+
+static stack_frame* GetStackFrame()
+{
+ jmp_buf jb;
+ stack_frame* currentFrame;
+ setjmp(jb);
+ currentFrame = (stack_frame*)(jb[0].__jmpbuf[JB_BP]);
+ currentFrame = currentFrame->next;
+ return currentFrame;
+}
+
+static void* GetStackTop()
+{
+ stack_frame* frame;
+ frame = GetStackFrame();
+ while (frame != NULL)
+ {
+ ptrdiff_t pc = (ptrdiff_t)frame->pc;
+ if ((pc < 0x08000000) || (pc > 0x7fffffff) || (frame->next < frame))
+ return frame;
+ frame = frame->next;
+ }
+ return NULL;
+}
+#endif /* GC_LEAK_DETECTOR && (__GLIBC__ >= 2) && __i386__ */
+
+/*
+** Initialize a stack for a native pthread thread
+*/
+static void _PR_InitializeStack(PRThreadStack *ts)
+{
+ if( ts && (ts->stackTop == 0) ) {
+ ts->allocBase = (char *) &ts;
+ ts->allocSize = ts->stackSize;
+
+ /*
+ ** Setup stackTop and stackBottom values.
+ */
+#ifdef HAVE_STACK_GROWING_UP
+ ts->stackBottom = ts->allocBase + ts->stackSize;
+ ts->stackTop = ts->allocBase;
+#else
+#ifdef GC_LEAK_DETECTOR
+ ts->stackTop = GetStackTop();
+ ts->stackBottom = ts->stackTop - ts->stackSize;
+#else
+ ts->stackTop = ts->allocBase;
+ ts->stackBottom = ts->allocBase - ts->stackSize;
+#endif
+#endif
+ }
+}
+
+static void *_pt_root(void *arg)
+{
+ PRIntn rv;
+ PRThread *thred = (PRThread*)arg;
+ PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE;
+
+ /*
+ * Both the parent thread and this new thread set thred->id.
+ * The new thread must ensure that thred->id is set before
+ * it executes its startFunc. The parent thread must ensure
+ * that thred->id is set before PR_CreateThread() returns.
+ * Both threads set thred->id without holding a lock. Since
+ * they are writing the same value, this unprotected double
+ * write should be safe.
+ */
+ thred->id = pthread_self();
+
+ /*
+ ** DCE Threads can't detach during creation, so do it late.
+ ** I would like to do it only here, but that doesn't seem
+ ** to work.
+ */
+#if defined(_PR_DCETHREADS)
+ if (detached)
+ {
+ /* pthread_detach() modifies its argument, so we must pass a copy */
+ pthread_t self = thred->id;
+ rv = pthread_detach(&self);
+ PR_ASSERT(0 == rv);
+ }
+#endif /* defined(_PR_DCETHREADS) */
+
+ /* Set up the thread stack information */
+ _PR_InitializeStack(thred->stack);
+
+ /*
+ * Set within the current thread the pointer to our object.
+ * This object will be deleted when the thread termintates,
+ * whether in a join or detached (see _PR_InitThreads()).
+ */
+ rv = pthread_setspecific(pt_book.key, thred);
+ PR_ASSERT(0 == rv);
+
+ /* make the thread visible to the rest of the runtime */
+ PR_Lock(pt_book.ml);
+
+ /* If this is a GCABLE thread, set its state appropriately */
+ if (thred->suspend & PT_THREAD_SETGCABLE)
+ thred->state |= PT_THREAD_GCABLE;
+ thred->suspend = 0;
+
+ thred->prev = pt_book.last;
+ pt_book.last->next = thred;
+ thred->next = NULL;
+ pt_book.last = thred;
+ PR_Unlock(pt_book.ml);
+
+ thred->startFunc(thred->arg); /* make visible to the client */
+
+ /* unhook the thread from the runtime */
+ PR_Lock(pt_book.ml);
+ /*
+ * At this moment, PR_CreateThread() may not have set thred->id yet.
+ * It is safe for a detached thread to free thred only after
+ * PR_CreateThread() has set thred->id.
+ */
+ if (detached)
+ {
+ while (!thred->okToDelete)
+ PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ if (thred->state & PT_THREAD_SYSTEM)
+ pt_book.system -= 1;
+ else if (--pt_book.user == pt_book.this_many)
+ PR_NotifyAllCondVar(pt_book.cv);
+ thred->prev->next = thred->next;
+ if (NULL == thred->next)
+ pt_book.last = thred->prev;
+ else
+ thred->next->prev = thred->prev;
+ PR_Unlock(pt_book.ml);
+
+ /*
+ * Here we set the pthread's backpointer to the PRThread to NULL.
+ * Otherwise the desctructor would get called eagerly as the thread
+ * returns to the pthread runtime. The joining thread would them be
+ * the proud possessor of a dangling reference. However, this is the
+ * last chance to delete the object if the thread is detached, so
+ * just let the destuctor do the work.
+ */
+ if (PR_FALSE == detached)
+ {
+ rv = pthread_setspecific(pt_book.key, NULL);
+ PR_ASSERT(0 == rv);
+ }
+
+ return NULL;
+} /* _pt_root */
+
+#ifdef VBOX_USE_IPRT_IN_NSPR
+static DECLCALLBACK(int) _pt_iprt_root(
+ RTTHREAD Thread, void *pvUser)
+{
+ PRThread *thred = (PRThread *)pvUser;
+ _pt_root(thred);
+ return VINF_SUCCESS;
+}
+#endif /* VBOX_USE_IPRT_IN_NSPR */
+
+static PRThread* pt_AttachThread(void)
+{
+ PRThread *thred = NULL;
+
+ /*
+ * NSPR must have been initialized when PR_AttachThread is called.
+ * We cannot have PR_AttachThread call implicit initialization
+ * because if multiple threads call PR_AttachThread simultaneously,
+ * NSPR may be initialized more than once.
+ * We can't call any function that calls PR_GetCurrentThread()
+ * either (e.g., PR_SetError()) as that will result in infinite
+ * recursion.
+ */
+ if (!_pr_initialized) return NULL;
+
+ /* PR_NEWZAP must not call PR_GetCurrentThread() */
+ thred = PR_NEWZAP(PRThread);
+ if (NULL != thred)
+ {
+ int rv;
+
+ thred->priority = PR_PRIORITY_NORMAL;
+ thred->id = pthread_self();
+ rv = pthread_setspecific(pt_book.key, thred);
+ PR_ASSERT(0 == rv);
+
+ thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN;
+ PR_Lock(pt_book.ml);
+
+ /* then put it into the list */
+ thred->prev = pt_book.last;
+ pt_book.last->next = thred;
+ thred->next = NULL;
+ pt_book.last = thred;
+ PR_Unlock(pt_book.ml);
+
+ }
+ return thred; /* may be NULL */
+} /* pt_AttachThread */
+
+static PRThread* _PR_CreateThread(
+ PRThreadType type, void (*start)(void *arg),
+ void *arg, PRThreadPriority priority, PRThreadScope scope,
+ PRThreadState state, PRUint32 stackSize, PRBool isGCAble)
+{
+ int rv;
+ PRThread *thred;
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ pthread_attr_t tattr;
+#else
+ static uint32_t volatile s_iThread = 0;
+ RTTHREADTYPE enmType;
+ RTTHREAD hThread;
+ uint32_t fFlags = 0;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)priority)
+ priority = PR_PRIORITY_FIRST;
+ else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)priority)
+ priority = PR_PRIORITY_LAST;
+
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ rv = _PT_PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ if (EPERM != pt_schedpriv)
+ {
+#if !defined(_PR_DCETHREADS) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ struct sched_param schedule;
+#endif
+
+#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ rv = pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
+ PR_ASSERT(0 == rv);
+#endif
+
+ /* Use the default scheduling policy */
+
+#if defined(_PR_DCETHREADS)
+ rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority));
+ PR_ASSERT(0 == rv);
+#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ rv = pthread_attr_getschedparam(&tattr, &schedule);
+ PR_ASSERT(0 == rv);
+ schedule.sched_priority = pt_PriorityMap(priority);
+ rv = pthread_attr_setschedparam(&tattr, &schedule);
+ PR_ASSERT(0 == rv);
+#ifdef NTO
+ rv = pthread_attr_setschedpolicy(&tattr, SCHED_RR); /* Round Robin */
+ PR_ASSERT(0 == rv);
+#endif
+#endif /* !defined(_PR_DCETHREADS) */
+ }
+#else /* VBOX_USE_IPRT_IN_NSPR */
+ /* calc priority */
+ switch (priority)
+ {
+ default:
+ case PR_PRIORITY_NORMAL: enmType = RTTHREADTYPE_DEFAULT; break;
+ case PR_PRIORITY_LOW: enmType = RTTHREADTYPE_MAIN_HEAVY_WORKER; break;
+ case PR_PRIORITY_HIGH: enmType = RTTHREADTYPE_MAIN_WORKER; break;
+ case PR_PRIORITY_URGENT: enmType = RTTHREADTYPE_IO; break;
+ }
+#endif /* VBOX_USE_IPRT_IN_NSPR */
+
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ /*
+ * DCE threads can't set detach state before creating the thread.
+ * AIX can't set detach late. Why can't we all just get along?
+ */
+#if !defined(_PR_DCETHREADS)
+ rv = pthread_attr_setdetachstate(&tattr,
+ ((PR_JOINABLE_THREAD == state) ?
+ PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
+ PR_ASSERT(0 == rv);
+#endif /* !defined(_PR_DCETHREADS) */
+#else
+ if (state == PR_JOINABLE_THREAD)
+ fFlags |= RTTHREADFLAGS_WAITABLE;
+#endif /* !VBOX_USE_IPRT_IN_NSPR */
+
+#ifndef VBOX_USE_IPRT_IN_NSPR /* We let stackSize stay zero and let IPRT choose a default size. */
+ if (0 == stackSize) stackSize = (64 * 1024); /* default == 64K */
+#ifdef _MD_MINIMUM_STACK_SIZE
+ if (stackSize < _MD_MINIMUM_STACK_SIZE) stackSize = _MD_MINIMUM_STACK_SIZE;
+#endif
+ /*
+ * Linux doesn't have pthread_attr_setstacksize.
+ */
+#ifndef LINUX
+ rv = pthread_attr_setstacksize(&tattr, stackSize);
+ PR_ASSERT(0 == rv);
+#endif
+#endif /* !VBOX_USE_IPRT_IN_NSPR */
+
+ thred = PR_NEWZAP(PRThread);
+ if (NULL == thred)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, errno);
+ goto done;
+ }
+ else
+ {
+ pthread_t id;
+
+ thred->arg = arg;
+ thred->startFunc = start;
+ thred->priority = priority;
+ if (PR_UNJOINABLE_THREAD == state)
+ thred->state |= PT_THREAD_DETACHED;
+
+ if (PR_LOCAL_THREAD == scope)
+ scope = PR_GLOBAL_THREAD;
+
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ if (PR_GLOBAL_BOUND_THREAD == scope) {
+#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+ if (rv) {
+ /*
+ * system scope not supported
+ */
+ scope = PR_GLOBAL_THREAD;
+ /*
+ * reset scope
+ */
+ rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
+ PR_ASSERT(0 == rv);
+ }
+#endif
+ }
+#endif /* !VBOX_USE_IPRT_IN_NSPR */
+ if (PR_GLOBAL_THREAD == scope)
+ thred->state |= PT_THREAD_GLOBAL;
+ else if (PR_GLOBAL_BOUND_THREAD == scope)
+ thred->state |= (PT_THREAD_GLOBAL | PT_THREAD_BOUND);
+ else /* force it global */
+ thred->state |= PT_THREAD_GLOBAL;
+ if (PR_SYSTEM_THREAD == type)
+ thred->state |= PT_THREAD_SYSTEM;
+
+ thred->suspend =(isGCAble) ? PT_THREAD_SETGCABLE : 0;
+
+ thred->stack = PR_NEWZAP(PRThreadStack);
+ if (thred->stack == NULL) {
+ PRIntn oserr = errno;
+ PR_Free(thred); /* all that work ... poof! */
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, oserr);
+ thred = NULL; /* and for what? */
+ goto done;
+ }
+ thred->stack->stackSize = stackSize;
+ thred->stack->thr = thred;
+
+#ifdef PT_NO_SIGTIMEDWAIT
+ pthread_mutex_init(&thred->suspendResumeMutex,NULL);
+ pthread_cond_init(&thred->suspendResumeCV,NULL);
+#endif
+
+ /* make the thread counted to the rest of the runtime */
+ PR_Lock(pt_book.ml);
+ if (PR_SYSTEM_THREAD == type)
+ pt_book.system += 1;
+ else pt_book.user += 1;
+ PR_Unlock(pt_book.ml);
+
+ /*
+ * We pass a pointer to a local copy (instead of thred->id)
+ * to pthread_create() because who knows what wacky things
+ * pthread_create() may be doing to its argument.
+ */
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
+
+#if !defined(_PR_DCETHREADS)
+ if (EPERM == rv)
+ {
+#if defined(IRIX)
+ if (PR_GLOBAL_BOUND_THREAD == scope) {
+ /*
+ * SCOPE_SYSTEM requires appropriate privilege
+ * reset to process scope and try again
+ */
+ rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
+ PR_ASSERT(0 == rv);
+ thred->state &= ~PT_THREAD_BOUND;
+ }
+#else
+ /* Remember that we don't have thread scheduling privilege. */
+ pt_schedpriv = EPERM;
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("_PR_CreateThread: no thread scheduling privilege"));
+ /* Try creating the thread again without setting priority. */
+#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ rv = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);
+ PR_ASSERT(0 == rv);
+#endif
+#endif /* IRIX */
+ rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
+ }
+#endif
+#else /* VBOX_USE_IPRT_IN_NSPR */
+ rv = RTThreadCreateF(&hThread, _pt_iprt_root, thred, stackSize, enmType, fFlags, "nspr-%u", ASMAtomicIncU32(&s_iThread));
+ if (RT_SUCCESS(rv)) {
+#ifdef VBOX_USE_IPRT_IN_NSPR
+ RTMEM_WILL_LEAK(hThread);
+#endif
+ id = (pthread_t)RTThreadGetNative(hThread);
+ rv = 0;
+ }
+#endif /* VBOX_USE_IPRT_IN_NSPR */
+
+ if (0 != rv)
+ {
+#if defined(_PR_DCETHREADS)
+ PRIntn oserr = errno;
+#else
+ PRIntn oserr = rv;
+#endif
+ PR_Lock(pt_book.ml);
+ if (thred->state & PT_THREAD_SYSTEM)
+ pt_book.system -= 1;
+ else if (--pt_book.user == pt_book.this_many)
+ PR_NotifyAllCondVar(pt_book.cv);
+ PR_Unlock(pt_book.ml);
+
+ PR_Free(thred->stack);
+ PR_Free(thred); /* all that work ... poof! */
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, oserr);
+ thred = NULL; /* and for what? */
+ goto done;
+ }
+
+ /*
+ * Both the parent thread and this new thread set thred->id.
+ * The parent thread must ensure that thred->id is set before
+ * PR_CreateThread() returns. (See comments in _pt_root().)
+ */
+ thred->id = id;
+
+ /*
+ * If the new thread is detached, tell it that PR_CreateThread()
+ * has set thred->id so it's ok to delete thred.
+ */
+ if (PR_UNJOINABLE_THREAD == state)
+ {
+ PR_Lock(pt_book.ml);
+ thred->okToDelete = PR_TRUE;
+ PR_NotifyAllCondVar(pt_book.cv);
+ PR_Unlock(pt_book.ml);
+ }
+ }
+
+done:
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ rv = _PT_PTHREAD_ATTR_DESTROY(&tattr);
+ PR_ASSERT(0 == rv);
+#endif
+
+ return thred;
+} /* _PR_CreateThread */
+
+PR_IMPLEMENT(PRThread*) PR_CreateThread(
+ PRThreadType type, void (*start)(void *arg), void *arg,
+ PRThreadPriority priority, PRThreadScope scope,
+ PRThreadState state, PRUint32 stackSize)
+{
+ return _PR_CreateThread(
+ type, start, arg, priority, scope, state, stackSize, PR_FALSE);
+} /* PR_CreateThread */
+
+PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(
+ PRThreadType type, void (*start)(void *arg), void *arg,
+ PRThreadPriority priority, PRThreadScope scope,
+ PRThreadState state, PRUint32 stackSize)
+{
+ return _PR_CreateThread(
+ type, start, arg, priority, scope, state, stackSize, PR_TRUE);
+} /* PR_CreateThreadGCAble */
+
+PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thred)
+{
+ return thred->environment;
+} /* GetExecutionEnvironment */
+
+PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thred, void *env)
+{
+ thred->environment = env;
+} /* SetExecutionEnvironment */
+
+PR_IMPLEMENT(PRThread*) PR_AttachThread(
+ PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
+{
+ return PR_GetCurrentThread();
+} /* PR_AttachThread */
+
+
+PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
+{
+ int rv = -1;
+ void *result = NULL;
+ PR_ASSERT(thred != NULL);
+
+ if ((0xafafafaf == thred->state)
+ || (PT_THREAD_DETACHED == (PT_THREAD_DETACHED & thred->state))
+ || (PT_THREAD_FOREIGN == (PT_THREAD_FOREIGN & thred->state)))
+ {
+ /*
+ * This might be a bad address, but if it isn't, the state should
+ * either be an unjoinable thread or it's already had the object
+ * deleted. However, the client that called join on a detached
+ * thread deserves all the rath I can muster....
+ */
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ PR_LogPrint(
+ "PR_JoinThread: 0x%X not joinable | already smashed\n", thred);
+ }
+ else
+ {
+#ifndef VBOX_USE_IPRT_IN_NSPR
+ pthread_t id = thred->id;
+ rv = pthread_join(id, &result);
+ PR_ASSERT(rv == 0 && result == NULL);
+ if (0 == rv)
+ {
+#ifdef _PR_DCETHREADS
+ rv = pthread_detach(&id);
+ PR_ASSERT(0 == rv);
+#endif
+ _pt_thread_death(thred);
+ }
+ else
+ {
+ PRErrorCode prerror;
+ switch (rv)
+ {
+ case EINVAL: /* not a joinable thread */
+ case ESRCH: /* no thread with given ID */
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case EDEADLK: /* a thread joining with itself */
+ prerror = PR_DEADLOCK_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, rv);
+ }
+#else /* VBOX_USE_IPRT_IN_NSPR */
+ rv = VERR_INVALID_HANDLE;
+ RTTHREAD hThread = RTThreadFromNative((RTNATIVETHREAD)thred->id);
+ if (hThread != NIL_RTTHREAD)
+ {
+ int rcThread = 0;
+ rv = RTThreadWait(hThread, RT_INDEFINITE_WAIT, &rcThread);
+ PR_ASSERT(RT_SUCCESS(rv) && rcThread == VINF_SUCCESS);
+ if (RT_SUCCESS(rv))
+ {
+ rv = 0;
+ _pt_thread_death(thred);
+ }
+ else
+ PR_SetError(rv == VERR_THREAD_NOT_WAITABLE
+ ? PR_INVALID_ARGUMENT_ERROR
+ : PR_UNKNOWN_ERROR,
+ rv);
+ }
+#endif /* VBOX_USE_IPRT_IN_NSPR */
+ }
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+} /* PR_JoinThread */
+
+PR_IMPLEMENT(void) PR_DetachThread(void) { } /* PR_DetachThread */
+
+PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void)
+{
+ void *thred;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
+ if (NULL == thred) thred = pt_AttachThread();
+ PR_ASSERT(NULL != thred);
+ return (PRThread*)thred;
+} /* PR_GetCurrentThread */
+
+PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thred)
+{
+ return (thred->state & PT_THREAD_BOUND) ?
+ PR_GLOBAL_BOUND_THREAD : PR_GLOBAL_THREAD;
+} /* PR_GetThreadScope() */
+
+PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thred)
+{
+ return (thred->state & PT_THREAD_SYSTEM) ?
+ PR_SYSTEM_THREAD : PR_USER_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thred)
+{
+ return (thred->state & PT_THREAD_DETACHED) ?
+ PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;
+} /* PR_GetThreadState */
+
+PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thred)
+{
+ PR_ASSERT(thred != NULL);
+ return thred->priority;
+} /* PR_GetThreadPriority */
+
+PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri)
+{
+ PRIntn rv = -1;
+
+ PR_ASSERT(NULL != thred);
+
+ if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)newPri)
+ newPri = PR_PRIORITY_FIRST;
+ else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)newPri)
+ newPri = PR_PRIORITY_LAST;
+
+#if defined(_PR_DCETHREADS)
+ rv = pthread_setprio(thred->id, pt_PriorityMap(newPri));
+ /* pthread_setprio returns the old priority */
+#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+ if (EPERM != pt_schedpriv)
+ {
+ int policy;
+ struct sched_param schedule;
+
+ rv = pthread_getschedparam(thred->id, &policy, &schedule);
+ if(0 == rv) {
+ schedule.sched_priority = pt_PriorityMap(newPri);
+ rv = pthread_setschedparam(thred->id, policy, &schedule);
+ if (EPERM == rv)
+ {
+ pt_schedpriv = EPERM;
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN,
+ ("PR_SetThreadPriority: no thread scheduling privilege"));
+ }
+ }
+ if (rv != 0)
+ rv = -1;
+ }
+#endif
+
+ thred->priority = newPri;
+} /* PR_SetThreadPriority */
+
+PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred)
+{
+ /*
+ ** If the target thread indicates that it's waiting,
+ ** find the condition and broadcast to it. Broadcast
+ ** since we don't know which thread (if there are more
+ ** than one). This sounds risky, but clients must
+ ** test their invariants when resumed from a wait and
+ ** I don't expect very many threads to be waiting on
+ ** a single condition and I don't expect interrupt to
+ ** be used very often.
+ **
+ ** I don't know why I thought this would work. Must have
+ ** been one of those weaker momements after I'd been
+ ** smelling the vapors.
+ **
+ ** Even with the followng changes it is possible that
+ ** the pointer to the condition variable is pointing
+ ** at a bogus value. Will the unerlying code detect
+ ** that?
+ */
+ PRCondVar *cv;
+ PR_ASSERT(NULL != thred);
+ if (NULL == thred) return PR_FAILURE;
+
+ thred->state |= PT_THREAD_ABORTED;
+
+ cv = thred->waiting;
+ if ((NULL != cv) && !thred->interrupt_blocked)
+ {
+ PRIntn rv;
+ (void)PR_AtomicIncrement(&cv->notify_pending);
+ rv = pthread_cond_broadcast(&cv->cv);
+ PR_ASSERT(0 == rv);
+ if (0 > PR_AtomicDecrement(&cv->notify_pending))
+ PR_DestroyCondVar(cv);
+ }
+ return PR_SUCCESS;
+} /* PR_Interrupt */
+
+PR_IMPLEMENT(void) PR_ClearInterrupt(void)
+{
+ PRThread *me = PR_CurrentThread();
+ me->state &= ~PT_THREAD_ABORTED;
+} /* PR_ClearInterrupt */
+
+PR_IMPLEMENT(void) PR_BlockInterrupt(void)
+{
+ PRThread *me = PR_CurrentThread();
+ _PT_THREAD_BLOCK_INTERRUPT(me);
+} /* PR_BlockInterrupt */
+
+PR_IMPLEMENT(void) PR_UnblockInterrupt(void)
+{
+ PRThread *me = PR_CurrentThread();
+ _PT_THREAD_UNBLOCK_INTERRUPT(me);
+} /* PR_UnblockInterrupt */
+
+PR_IMPLEMENT(PRStatus) PR_Yield(void)
+{
+ static PRBool warning = PR_TRUE;
+ if (warning) warning = _PR_Obsolete(
+ "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)");
+ return PR_Sleep(PR_INTERVAL_NO_WAIT);
+}
+
+PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks)
+{
+ PRStatus rv = PR_SUCCESS;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (PR_INTERVAL_NO_WAIT == ticks)
+ {
+ _PT_PTHREAD_YIELD();
+ }
+ else
+ {
+ PRCondVar *cv;
+ PRIntervalTime timein;
+
+ timein = PR_IntervalNow();
+ cv = PR_NewCondVar(_pr_sleeplock);
+ PR_ASSERT(cv != NULL);
+ PR_Lock(_pr_sleeplock);
+ do
+ {
+ PRIntervalTime now = PR_IntervalNow();
+ PRIntervalTime delta = now - timein;
+ if (delta > ticks) break;
+ rv = PR_WaitCondVar(cv, ticks - delta);
+ } while (PR_SUCCESS == rv);
+ PR_Unlock(_pr_sleeplock);
+ PR_DestroyCondVar(cv);
+ }
+ return rv;
+} /* PR_Sleep */
+
+static void _pt_thread_death(void *arg)
+{
+ PRThread *thred = (PRThread*)arg;
+
+ if (thred->state & PT_THREAD_FOREIGN)
+ {
+ PR_Lock(pt_book.ml);
+ thred->prev->next = thred->next;
+ if (NULL == thred->next)
+ pt_book.last = thred->prev;
+ else
+ thred->next->prev = thred->prev;
+ PR_Unlock(pt_book.ml);
+ }
+ _PR_DestroyThreadPrivate(thred);
+ PR_Free(thred->privateData);
+ if (NULL != thred->errorString)
+ PR_Free(thred->errorString);
+ PR_Free(thred->stack);
+ if (NULL != thred->syspoll_list)
+ PR_Free(thred->syspoll_list);
+#if defined(_PR_POLL_WITH_SELECT)
+ if (NULL != thred->selectfd_list)
+ PR_Free(thred->selectfd_list);
+#endif
+#if defined(DEBUG)
+ memset(thred, 0xaf, sizeof(PRThread));
+#endif /* defined(DEBUG) */
+ PR_Free(thred);
+} /* _pt_thread_death */
+
+void _PR_InitThreads(
+ PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
+{
+ int rv;
+ PRThread *thred;
+
+#ifdef _PR_NEED_PTHREAD_INIT
+ /*
+ * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily
+ * initialized, but pthread_self() fails to initialize
+ * pthreads and hence returns a null thread ID if invoked
+ * by the primordial thread before any other pthread call.
+ * So we explicitly initialize pthreads here.
+ */
+ pthread_init();
+#endif
+
+#if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
+#if defined(FREEBSD)
+ {
+ pthread_attr_t attr;
+ int policy;
+ /* get the min and max priorities of the default policy */
+ pthread_attr_init(&attr);
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_getschedpolicy(&attr, &policy);
+ pt_book.minPrio = sched_get_priority_min(policy);
+ PR_ASSERT(-1 != pt_book.minPrio);
+ pt_book.maxPrio = sched_get_priority_max(policy);
+ PR_ASSERT(-1 != pt_book.maxPrio);
+ pthread_attr_destroy(&attr);
+ }
+#else
+ /*
+ ** These might be function evaluations
+ */
+ pt_book.minPrio = PT_PRIO_MIN;
+ pt_book.maxPrio = PT_PRIO_MAX;
+#endif
+#endif
+
+ PR_ASSERT(NULL == pt_book.ml);
+ pt_book.ml = PR_NewLock();
+ PR_ASSERT(NULL != pt_book.ml);
+ pt_book.cv = PR_NewCondVar(pt_book.ml);
+ PR_ASSERT(NULL != pt_book.cv);
+ thred = PR_NEWZAP(PRThread);
+ PR_ASSERT(NULL != thred);
+ thred->arg = NULL;
+ thred->startFunc = NULL;
+ thred->priority = priority;
+ thred->id = pthread_self();
+
+ thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD);
+ if (PR_SYSTEM_THREAD == type)
+ {
+ thred->state |= PT_THREAD_SYSTEM;
+ pt_book.system += 1;
+ pt_book.this_many = 0;
+ }
+ else
+ {
+ pt_book.user += 1;
+ pt_book.this_many = 1;
+ }
+ thred->next = thred->prev = NULL;
+ pt_book.first = pt_book.last = thred;
+
+ thred->stack = PR_NEWZAP(PRThreadStack);
+ PR_ASSERT(thred->stack != NULL);
+ thred->stack->stackSize = 0;
+ thred->stack->thr = thred;
+ _PR_InitializeStack(thred->stack);
+
+ /*
+ * Create a key for our use to store a backpointer in the pthread
+ * to our PRThread object. This object gets deleted when the thread
+ * returns from its root in the case of a detached thread. Other
+ * threads delete the objects in Join.
+ *
+ * NB: The destructor logic seems to have a bug so it isn't used.
+ * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998.
+ * More info - the problem is that pthreads calls the destructor
+ * eagerly as the thread returns from its root, rather than lazily
+ * after the thread is joined. Therefore, threads that are joining
+ * and holding PRThread references are actually holding pointers to
+ * nothing.
+ */
+ rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death);
+ PR_ASSERT(0 == rv);
+ rv = pthread_setspecific(pt_book.key, thred);
+ PR_ASSERT(0 == rv);
+ PR_SetThreadPriority(thred, priority);
+} /* _PR_InitThreads */
+
+PR_IMPLEMENT(PRStatus) PR_Cleanup(void)
+{
+ PRThread *me = PR_CurrentThread();
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
+ PR_ASSERT(me->state & PT_THREAD_PRIMORD);
+ if (me->state & PT_THREAD_PRIMORD)
+ {
+ PR_Lock(pt_book.ml);
+ while (pt_book.user > pt_book.this_many)
+ PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(pt_book.ml);
+
+ _PR_CleanupMW();
+ _PR_CleanupDtoa();
+ _PR_CleanupCallOnce();
+ _PR_ShutdownLinker();
+ _PR_LogCleanup();
+ _PR_CleanupNet();
+ /* Close all the fd's before calling _PR_CleanupIO */
+ _PR_CleanupIO();
+
+ /*
+ * I am not sure if it's safe to delete the cv and lock here,
+ * since there may still be "system" threads around. If this
+ * call isn't immediately prior to exiting, then there's a
+ * problem.
+ */
+ if (0 == pt_book.system)
+ {
+ PR_DestroyCondVar(pt_book.cv); pt_book.cv = NULL;
+ PR_DestroyLock(pt_book.ml); pt_book.ml = NULL;
+ }
+ _pt_thread_death(me);
+ PR_DestroyLock(_pr_sleeplock);
+ _pr_sleeplock = NULL;
+ _PR_CleanupLayerCache();
+ _PR_CleanupEnv();
+#ifdef _PR_ZONE_ALLOCATOR
+ _PR_DestroyZones();
+#endif
+ _pr_initialized = PR_FALSE;
+ return PR_SUCCESS;
+ }
+ return PR_FAILURE;
+} /* PR_Cleanup */
+
+PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
+{
+ _exit(status);
+}
+
+PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred)
+{
+#if defined(_PR_DCETHREADS)
+ return (PRUint32)&thred->id; /* this is really a sham! */
+#else
+ return (PRUint32)thred->id; /* and I don't know what they will do with it */
+#endif
+}
+
+/*
+ * $$$
+ * The following two thread-to-processor affinity functions are not
+ * yet implemented for pthreads. By the way, these functions should return
+ * PRStatus rather than PRInt32 to indicate the success/failure status.
+ * $$$
+ */
+
+PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask)
+{
+ return 0; /* not implemented */
+}
+
+PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask )
+{
+ return 0; /* not implemented */
+}
+
+PR_IMPLEMENT(void)
+PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg)
+{
+ thread->dump = dump;
+ thread->dumpArg = arg;
+}
+
+/*
+ * Garbage collection support follows.
+ */
+
+#if defined(_PR_DCETHREADS)
+
+/*
+ * statics for Garbage Collection support. We don't need to protect these
+ * signal masks since the garbage collector itself is protected by a lock
+ * and multiple threads will not be garbage collecting at the same time.
+ */
+static sigset_t javagc_vtalarm_sigmask;
+static sigset_t javagc_intsoff_sigmask;
+
+#else /* defined(_PR_DCETHREADS) */
+
+/* a bogus signal mask for forcing a timed wait */
+/* Not so bogus in AIX as we really do a sigwait */
+static sigset_t sigwait_set;
+
+static struct timespec onemillisec = {0, 1000000L};
+#ifndef PT_NO_SIGTIMEDWAIT
+static struct timespec hundredmillisec = {0, 100000000L};
+#endif
+
+static void suspend_signal_handler(PRIntn sig);
+
+#ifdef PT_NO_SIGTIMEDWAIT
+static void null_signal_handler(PRIntn sig);
+#endif
+
+#endif /* defined(_PR_DCETHREADS) */
+
+/*
+ * Linux pthreads use SIGUSR1 and SIGUSR2 internally, which
+ * conflict with the use of these two signals in our GC support.
+ * So we don't know how to support GC on Linux pthreads.
+ */
+static void init_pthread_gc_support(void)
+{
+ PRIntn rv;
+
+#if defined(_PR_DCETHREADS)
+ rv = sigemptyset(&javagc_vtalarm_sigmask);
+ PR_ASSERT(0 == rv);
+ rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM);
+ PR_ASSERT(0 == rv);
+#else /* defined(_PR_DCETHREADS) */
+ {
+ struct sigaction sigact_usr2;
+
+ sigact_usr2.sa_handler = suspend_signal_handler;
+ sigact_usr2.sa_flags = SA_RESTART;
+ sigemptyset (&sigact_usr2.sa_mask);
+
+ rv = sigaction (SIGUSR2, &sigact_usr2, NULL);
+ PR_ASSERT(0 == rv);
+
+ sigemptyset (&sigwait_set);
+#if defined(PT_NO_SIGTIMEDWAIT)
+ sigaddset (&sigwait_set, SIGUSR1);
+#else
+ sigaddset (&sigwait_set, SIGUSR2);
+#endif /* defined(PT_NO_SIGTIMEDWAIT) */
+ }
+#if defined(PT_NO_SIGTIMEDWAIT)
+ {
+ struct sigaction sigact_null;
+ sigact_null.sa_handler = null_signal_handler;
+ sigact_null.sa_flags = SA_RESTART;
+ sigemptyset (&sigact_null.sa_mask);
+ rv = sigaction (SIGUSR1, &sigact_null, NULL);
+ PR_ASSERT(0 ==rv);
+ }
+#endif /* defined(PT_NO_SIGTIMEDWAIT) */
+#endif /* defined(_PR_DCETHREADS) */
+}
+
+PR_IMPLEMENT(void) PR_SetThreadGCAble(void)
+{
+ PR_Lock(pt_book.ml);
+ PR_CurrentThread()->state |= PT_THREAD_GCABLE;
+ PR_Unlock(pt_book.ml);
+}
+
+PR_IMPLEMENT(void) PR_ClearThreadGCAble(void)
+{
+ PR_Lock(pt_book.ml);
+ PR_CurrentThread()->state &= (~PT_THREAD_GCABLE);
+ PR_Unlock(pt_book.ml);
+}
+
+#if defined(DEBUG)
+static PRBool suspendAllOn = PR_FALSE;
+#endif
+
+static PRBool suspendAllSuspended = PR_FALSE;
+
+PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
+{
+ PRIntn count = 0;
+ PRStatus rv = PR_SUCCESS;
+ PRThread* thred = pt_book.first;
+ PRThread *me = PR_CurrentThread();
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_EnumerateThreads\n"));
+ /*
+ * $$$
+ * Need to suspend all threads other than me before doing this.
+ * This is really a gross and disgusting thing to do. The only
+ * good thing is that since all other threads are suspended, holding
+ * the lock during a callback seems like child's play.
+ * $$$
+ */
+ PR_ASSERT(suspendAllOn);
+
+ while (thred != NULL)
+ {
+ /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking
+ * qp->next after applying the function "func". In particular, "func"
+ * might remove the thread from the queue and put it into another one in
+ * which case qp->next no longer points to the next entry in the original
+ * queue.
+ *
+ * To get around this problem, we save qp->next in qp_next before applying
+ * "func" and use that saved value as the next value after applying "func".
+ */
+ PRThread* next = thred->next;
+
+ if (_PT_IS_GCABLE_THREAD(thred))
+ {
+#if !defined(_PR_DCETHREADS)
+ PR_ASSERT((thred == me) || (thred->suspend & PT_THREAD_SUSPENDED));
+#endif
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("In PR_EnumerateThreads callback thread %X thid = %X\n",
+ thred, thred->id));
+
+ rv = func(thred, count++, arg);
+ if (rv != PR_SUCCESS)
+ return rv;
+ }
+ thred = next;
+ }
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("End PR_EnumerateThreads count = %d \n", count));
+ return rv;
+} /* PR_EnumerateThreads */
+
+/*
+ * PR_SuspendAll and PR_ResumeAll are called during garbage collection. The strategy
+ * we use is to send a SIGUSR2 signal to every gc able thread that we intend to suspend.
+ * The signal handler will record the stack pointer and will block until resumed by
+ * the resume call. Since the signal handler is the last routine called for the
+ * suspended thread, the stack pointer will also serve as a place where all the
+ * registers have been saved on the stack for the previously executing routines.
+ *
+ * Through global variables, we also make sure that PR_Suspend and PR_Resume does not
+ * proceed until the thread is suspended or resumed.
+ */
+
+#if !defined(_PR_DCETHREADS)
+
+/*
+ * In the signal handler, we can not use condition variable notify or wait.
+ * This does not work consistently across all pthread platforms. We also can not
+ * use locking since that does not seem to work reliably across platforms.
+ * Only thing we can do is yielding while testing for a global condition
+ * to change. This does work on pthread supported platforms. We may have
+ * to play with priortities if there are any problems detected.
+ */
+
+ /*
+ * In AIX, you cannot use ANY pthread calls in the signal handler except perhaps
+ * pthread_yield. But that is horribly inefficient. Hence we use only sigwait, no
+ * sigtimedwait is available. We need to use another user signal, SIGUSR1. Actually
+ * SIGUSR1 is also used by exec in Java. So our usage here breaks the exec in Java,
+ * for AIX. You cannot use pthread_cond_wait or pthread_delay_np in the signal
+ * handler as all synchronization mechanisms just break down.
+ */
+
+#if defined(PT_NO_SIGTIMEDWAIT)
+static void null_signal_handler(PRIntn sig)
+{
+ return;
+}
+#endif
+
+static void suspend_signal_handler(PRIntn sig)
+{
+ PRThread *me = PR_CurrentThread();
+
+ PR_ASSERT(me != NULL);
+ PR_ASSERT(_PT_IS_GCABLE_THREAD(me));
+ PR_ASSERT((me->suspend & PT_THREAD_SUSPENDED) == 0);
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("Begin suspend_signal_handler thred %X thread id = %X\n",
+ me, me->id));
+
+ /*
+ * save stack pointer
+ */
+ me->sp = &me;
+
+ /*
+ At this point, the thread's stack pointer has been saved,
+ And it is going to enter a wait loop until it is resumed.
+ So it is _really_ suspended
+ */
+
+ me->suspend |= PT_THREAD_SUSPENDED;
+
+ /*
+ * now, block current thread
+ */
+#if defined(PT_NO_SIGTIMEDWAIT)
+ pthread_cond_signal(&me->suspendResumeCV);
+ while (me->suspend & PT_THREAD_SUSPENDED)
+ {
+#if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \
+ && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) && !defined(DARWIN) /*XXX*/
+ PRIntn rv;
+ sigwait(&sigwait_set, &rv);
+#endif
+ }
+ me->suspend |= PT_THREAD_RESUMED;
+ pthread_cond_signal(&me->suspendResumeCV);
+#else /* defined(PT_NO_SIGTIMEDWAIT) */
+ while (me->suspend & PT_THREAD_SUSPENDED)
+ {
+ PRIntn rv = sigtimedwait(&sigwait_set, NULL, &hundredmillisec);
+ PR_ASSERT(-1 == rv);
+ }
+ me->suspend |= PT_THREAD_RESUMED;
+#endif
+
+ /*
+ * At this point, thread has been resumed, so set a global condition.
+ * The ResumeAll needs to know that this has really been resumed.
+ * So the signal handler sets a flag which PR_ResumeAll will reset.
+ * The PR_ResumeAll must reset this flag ...
+ */
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("End suspend_signal_handler thred = %X tid = %X\n", me, me->id));
+} /* suspend_signal_handler */
+
+static void pt_SuspendSet(PRThread *thred)
+{
+ PRIntn rv;
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("pt_SuspendSet thred %X thread id = %X\n", thred, thred->id));
+
+
+ /*
+ * Check the thread state and signal the thread to suspend
+ */
+
+ PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0);
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("doing pthread_kill in pt_SuspendSet thred %X tid = %X\n",
+ thred, thred->id));
+#if defined(VMS)
+ rv = thread_suspend(thred);
+#else
+ rv = pthread_kill (thred->id, SIGUSR2);
+#endif
+ PR_ASSERT(0 == rv);
+}
+
+static void pt_SuspendTest(PRThread *thred)
+{
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("Begin pt_SuspendTest thred %X thread id = %X\n", thred, thred->id));
+
+
+ /*
+ * Wait for the thread to be really suspended. This happens when the
+ * suspend signal handler stores the stack pointer and sets the state
+ * to suspended.
+ */
+
+#if defined(PT_NO_SIGTIMEDWAIT)
+ pthread_mutex_lock(&thred->suspendResumeMutex);
+ while ((thred->suspend & PT_THREAD_SUSPENDED) == 0)
+ {
+ pthread_cond_timedwait(
+ &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec);
+ }
+ pthread_mutex_unlock(&thred->suspendResumeMutex);
+#else
+ while ((thred->suspend & PT_THREAD_SUSPENDED) == 0)
+ {
+ PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec);
+ PR_ASSERT(-1 == rv);
+ }
+#endif
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("End pt_SuspendTest thred %X tid %X\n", thred, thred->id));
+} /* pt_SuspendTest */
+
+static void pt_ResumeSet(PRThread *thred)
+{
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("pt_ResumeSet thred %X thread id = %X\n", thred, thred->id));
+
+ /*
+ * Clear the global state and set the thread state so that it will
+ * continue past yield loop in the suspend signal handler
+ */
+
+ PR_ASSERT(thred->suspend & PT_THREAD_SUSPENDED);
+
+
+ thred->suspend &= ~PT_THREAD_SUSPENDED;
+
+#if defined(PT_NO_SIGTIMEDWAIT)
+#if defined(VMS)
+ thread_resume(thred);
+#else
+ pthread_kill(thred->id, SIGUSR1);
+#endif
+#endif
+
+} /* pt_ResumeSet */
+
+static void pt_ResumeTest(PRThread *thred)
+{
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("Begin pt_ResumeTest thred %X thread id = %X\n", thred, thred->id));
+
+ /*
+ * Wait for the threads resume state to change
+ * to indicate it is really resumed
+ */
+#if defined(PT_NO_SIGTIMEDWAIT)
+ pthread_mutex_lock(&thred->suspendResumeMutex);
+ while ((thred->suspend & PT_THREAD_RESUMED) == 0)
+ {
+ pthread_cond_timedwait(
+ &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec);
+ }
+ pthread_mutex_unlock(&thred->suspendResumeMutex);
+#else
+ while ((thred->suspend & PT_THREAD_RESUMED) == 0) {
+ PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec);
+ PR_ASSERT(-1 == rv);
+ }
+#endif
+
+ thred->suspend &= ~PT_THREAD_RESUMED;
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, (
+ "End pt_ResumeTest thred %X tid %X\n", thred, thred->id));
+} /* pt_ResumeTest */
+
+static pthread_once_t pt_gc_support_control = PTHREAD_ONCE_INIT;
+
+PR_IMPLEMENT(void) PR_SuspendAll(void)
+{
+#ifdef DEBUG
+ PRIntervalTime stime, etime;
+#endif
+ PRThread* thred = pt_book.first;
+ PRThread *me = PR_CurrentThread();
+ int rv;
+
+ rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
+ PR_ASSERT(0 == rv);
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
+ /*
+ * Stop all threads which are marked GC able.
+ */
+ PR_Lock(pt_book.ml);
+#ifdef DEBUG
+ suspendAllOn = PR_TRUE;
+ stime = PR_IntervalNow();
+#endif
+ while (thred != NULL)
+ {
+ if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
+ pt_SuspendSet(thred);
+ thred = thred->next;
+ }
+
+ /* Wait till they are really suspended */
+ thred = pt_book.first;
+ while (thred != NULL)
+ {
+ if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
+ pt_SuspendTest(thred);
+ thred = thred->next;
+ }
+
+ suspendAllSuspended = PR_TRUE;
+
+#ifdef DEBUG
+ etime = PR_IntervalNow();
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,\
+ ("End PR_SuspendAll (time %dms)\n",
+ PR_IntervalToMilliseconds(etime - stime)));
+#endif
+} /* PR_SuspendAll */
+
+PR_IMPLEMENT(void) PR_ResumeAll(void)
+{
+#ifdef DEBUG
+ PRIntervalTime stime, etime;
+#endif
+ PRThread* thred = pt_book.first;
+ PRThread *me = PR_CurrentThread();
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
+ /*
+ * Resume all previously suspended GC able threads.
+ */
+ suspendAllSuspended = PR_FALSE;
+#ifdef DEBUG
+ stime = PR_IntervalNow();
+#endif
+
+ while (thred != NULL)
+ {
+ if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
+ pt_ResumeSet(thred);
+ thred = thred->next;
+ }
+
+ thred = pt_book.first;
+ while (thred != NULL)
+ {
+ if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
+ pt_ResumeTest(thred);
+ thred = thred->next;
+ }
+
+ PR_Unlock(pt_book.ml);
+#ifdef DEBUG
+ suspendAllOn = PR_FALSE;
+ etime = PR_IntervalNow();
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("End PR_ResumeAll (time %dms)\n",
+ PR_IntervalToMilliseconds(etime - stime)));
+#endif
+} /* PR_ResumeAll */
+
+/* Return the stack pointer for the given thread- used by the GC */
+PR_IMPLEMENT(void *)PR_GetSP(PRThread *thred)
+{
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
+ ("in PR_GetSP thred %X thid = %X, sp = %X \n",
+ thred, thred->id, thred->sp));
+ return thred->sp;
+} /* PR_GetSP */
+
+#else /* !defined(_PR_DCETHREADS) */
+
+static pthread_once_t pt_gc_support_control = pthread_once_init;
+
+/*
+ * For DCE threads, there is no pthread_kill or a way of suspending or resuming a
+ * particular thread. We will just disable the preemption (virtual timer alarm) and
+ * let the executing thread finish the garbage collection. This stops all other threads
+ * (GC able or not) and is very inefficient but there is no other choice.
+ */
+PR_IMPLEMENT(void) PR_SuspendAll()
+{
+ PRIntn rv;
+
+ rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
+ PR_ASSERT(0 == rv); /* returns -1 on failure */
+#ifdef DEBUG
+ suspendAllOn = PR_TRUE;
+#endif
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
+ /*
+ * turn off preemption - i.e add virtual alarm signal to the set of
+ * blocking signals
+ */
+ rv = sigprocmask(
+ SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask);
+ PR_ASSERT(0 == rv);
+ suspendAllSuspended = PR_TRUE;
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_SuspendAll\n"));
+} /* PR_SuspendAll */
+
+PR_IMPLEMENT(void) PR_ResumeAll()
+{
+ PRIntn rv;
+
+ suspendAllSuspended = PR_FALSE;
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
+ /* turn on preemption - i.e re-enable virtual alarm signal */
+
+ rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL);
+ PR_ASSERT(0 == rv);
+#ifdef DEBUG
+ suspendAllOn = PR_FALSE;
+#endif
+
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n"));
+} /* PR_ResumeAll */
+
+/* Return the stack pointer for the given thread- used by the GC */
+PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred)
+{
+ pthread_t tid = thred->id;
+ char *thread_tcb, *top_sp;
+
+ /*
+ * For HPUX DCE threads, pthread_t is a struct with the
+ * following three fields (see pthread.h, dce/cma.h):
+ * cma_t_address field1;
+ * short int field2;
+ * short int field3;
+ * where cma_t_address is typedef'd to be either void*
+ * or char*.
+ */
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n"));
+ thread_tcb = (char*)tid.field1;
+ top_sp = *(char**)(thread_tcb + 128);
+ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %X \n", top_sp));
+ return top_sp;
+} /* PR_GetSP */
+
+#endif /* !defined(_PR_DCETHREADS) */
+
+#endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */
+
+/* ptthread.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/threads/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/threads/Makefile.in
new file mode 100644
index 00000000..5e6731c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/Makefile.in
@@ -0,0 +1,94 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifdef USE_PTHREADS
+ DIRS =
+else
+ifdef USE_BTHREADS
+ DIRS =
+else
+ DIRS = combined
+endif
+endif
+
+ifdef USE_PTHREADS
+CSRCS = \
+ prcmon.c \
+ prrwlock.c \
+ prtpd.c \
+ $(NULL)
+else
+ifdef USE_BTHREADS
+CSRCS = \
+ prcmon.c \
+ prrwlock.c \
+ prtpd.c \
+ $(NULL)
+else
+CSRCS = \
+ prcmon.c \
+ prdump.c \
+ prmon.c \
+ prsem.c \
+ prrwlock.c \
+ prcthr.c \
+ prtpd.c \
+ $(NULL)
+endif
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/Makefile.in
new file mode 100644
index 00000000..476c6c9a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/Makefile.in
@@ -0,0 +1,79 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OPTIMIZER =
+endif
+endif
+
+ifdef USE_PTHREADS
+CSRCS = \
+ $(NULL)
+else
+CSRCS = \
+ prucpu.c \
+ prucv.c \
+ prulock.c \
+ pruthr.c \
+ prustack.c \
+ $(NULL)
+endif
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+DEFINES += -D_NSPR_BUILD_
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/README b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/README
new file mode 100644
index 00000000..aa266652
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/README
@@ -0,0 +1,62 @@
+NSPR 2.0 evolution
+------------------
+
+
+Phase 1- today
+
+Currently (Oct 10, 1996) NSPR 2.0 has two modes. Either _PR_NTHREAD
+is defined, in which case the PR_CreateThread() call always creates a
+native kernel thread, or _PR_NTHREAD is not defined and PR_CreateThread()
+always creates user level threads within the single, original process. This
+source code is reflected in two directories, nspr20/pr/src/threads/native, and
+nspr20/pr/src/threads/user. Although the PR_CreateThread() function has
+a paramter to specify the "scope" of a thread, this parameter is not yet
+used- except on solaris where it uses it to specify bound vs unbound threads.
+
+Phase 2 - next week
+
+The next step is to provide a combination of user and native threads. The
+idea, of course, is to have some small number of native threads and each of
+those threads be able to run user level threads. The number of native
+threads created will most likely be proportional to the number of CPUs in
+the system. For this reason, the specific set of native threads which are
+used to run the user-level threads will be called "CPU" threads.
+
+The user level threads which will be run on the CPU threads are able to
+run on any of the CPU threads available, and over the course of a user-level
+thread's lifetime, it may drift from one CPU thread to another. All
+user-level threads will compete for processing time via a single run queue.
+
+Creation of a CPU thread will be primarily controlled by NSPR itself or by
+the user running a function PR_Concurrency(). The details of PR_Concurrency()
+have not yet been worked out; but the idea is that the user can specify to
+NSPR how many CPU threads are desired.
+
+In this system, user-level threads are created by using PR_CreateThread() and
+specifying the PR_LOCAL_SCOPE option. LOCAL_SCOPE indicates that the thread
+will be under the control of the "local" scheduler. Creating threads with
+GLOBAL_SCOPE, on the other hand will create a thread which is under the
+control of the system's scheduler. In otherwords, this creates a native thread
+which is not a CPU thread; it runs a single thread task and never has more
+than one task to run. LOCAL_SCOPE is much like creating a Solaris unbound
+thread, while GLOBAL_SCOPE is similar to creating a Solaris bound thread.
+
+To implement this architecture, the source code will still maintain the "user"
+and "native" directories which is has today. However a third directory
+"combined" will also exist. To compile a version of NSPR which only creates
+native threads, the user can define _PR_NTHREAD. For exclusive user-level
+threads, do not define _PR_NTHREAD. To get the combined threads, define
+_PR_NTHREAD and _PR_USE_CPUS.
+
+
+Phase 3 - later than next week
+
+The goal is to eliminate the 3 directories. Once these three models are in
+place, the remaining work will be to eliminate the native and user thread
+directories for all platforms, so that the entire thread model is contained
+within what is today called the "combined" model. This new and glorious
+source code will attempt to make the "combined" model on any platforms which
+provide the necessary underlying native threading, but will also be
+capable of using exclusive user-level threads on systems which don't have
+native threads.
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucpu.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucpu.c
new file mode 100644
index 00000000..a3938b1f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucpu.c
@@ -0,0 +1,440 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+_PRCPU *_pr_primordialCPU = NULL;
+
+PRInt32 _pr_md_idle_cpus; /* number of idle cpus */
+/*
+ * The idle threads in MxN models increment/decrement _pr_md_idle_cpus.
+ * If _PR_HAVE_ATOMIC_OPS is not defined, they can't use the atomic
+ * increment/decrement routines (which are based on PR_Lock/PR_Unlock),
+ * because PR_Lock asserts that the calling thread is not an idle thread.
+ * So we use a _MDLock to protect _pr_md_idle_cpus.
+ */
+#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
+#ifndef _PR_HAVE_ATOMIC_OPS
+static _MDLock _pr_md_idle_cpus_lock;
+#endif
+#endif
+PRUintn _pr_numCPU;
+PRInt32 _pr_cpus_exit;
+PRInt32 _pr_cpu_affinity_mask = 0;
+
+#if !defined (_PR_GLOBAL_THREADS_ONLY)
+
+static PRUintn _pr_cpuID;
+
+static void PR_CALLBACK _PR_CPU_Idle(void *);
+
+static _PRCPU *_PR_CreateCPU(void);
+static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread);
+
+#if !defined(_PR_LOCAL_THREADS_ONLY)
+static void _PR_RunCPU(void *arg);
+#endif
+
+void _PR_InitCPUs()
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (_native_threads_only)
+ return;
+
+ _pr_cpuID = 0;
+ _MD_NEW_LOCK( &_pr_cpuLock);
+#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
+#ifndef _PR_HAVE_ATOMIC_OPS
+ _MD_NEW_LOCK(&_pr_md_idle_cpus_lock);
+#endif
+#endif
+
+#ifdef _PR_LOCAL_THREADS_ONLY
+
+#ifdef HAVE_CUSTOM_USER_THREADS
+ _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me);
+#endif
+
+ /* Now start the first CPU. */
+ _pr_primordialCPU = _PR_CreateCPU();
+ _pr_numCPU = 1;
+ _PR_StartCPU(_pr_primordialCPU, me);
+
+ _PR_MD_SET_CURRENT_CPU(_pr_primordialCPU);
+
+ /* Initialize cpu for current thread (could be different from me) */
+ _PR_MD_CURRENT_THREAD()->cpu = _pr_primordialCPU;
+
+ _PR_MD_SET_LAST_THREAD(me);
+
+#else /* Combined MxN model */
+
+ _pr_primordialCPU = _PR_CreateCPU();
+ _pr_numCPU = 1;
+ _PR_CreateThread(PR_SYSTEM_THREAD,
+ _PR_RunCPU,
+ _pr_primordialCPU,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0,
+ _PR_IDLE_THREAD);
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+ _PR_MD_INIT_CPUS();
+}
+
+#ifdef WINNT
+/*
+ * Right now this function merely stops the CPUs and does
+ * not do any other cleanup.
+ *
+ * It is only implemented for WINNT because bug 161998 only
+ * affects the WINNT version of NSPR, but it would be nice
+ * to implement this function for other platforms too.
+ */
+void _PR_CleanupCPUs(void)
+{
+ PRUintn i;
+ PRCList *qp;
+ _PRCPU *cpu;
+
+ _pr_cpus_exit = 1;
+ for (i = 0; i < _pr_numCPU; i++) {
+ _PR_MD_WAKEUP_WAITER(NULL);
+ }
+ for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
+ cpu = _PR_CPU_PTR(qp);
+ _PR_MD_JOIN_THREAD(&cpu->thread->md);
+ }
+}
+#endif
+
+static _PRCPUQueue *_PR_CreateCPUQueue(void)
+{
+ PRInt32 index;
+ _PRCPUQueue *cpuQueue;
+ cpuQueue = PR_NEWZAP(_PRCPUQueue);
+
+ _MD_NEW_LOCK( &cpuQueue->runQLock );
+ _MD_NEW_LOCK( &cpuQueue->sleepQLock );
+ _MD_NEW_LOCK( &cpuQueue->miscQLock );
+
+ for (index = 0; index < PR_PRIORITY_LAST + 1; index++)
+ PR_INIT_CLIST( &(cpuQueue->runQ[index]) );
+ PR_INIT_CLIST( &(cpuQueue->sleepQ) );
+ PR_INIT_CLIST( &(cpuQueue->pauseQ) );
+ PR_INIT_CLIST( &(cpuQueue->suspendQ) );
+ PR_INIT_CLIST( &(cpuQueue->waitingToJoinQ) );
+
+ cpuQueue->numCPUs = 1;
+
+ return cpuQueue;
+}
+
+/*
+ * Create a new CPU.
+ *
+ * This function initializes enough of the _PRCPU structure so
+ * that it can be accessed safely by a global thread or another
+ * CPU. This function does not create the native thread that
+ * will run the CPU nor does it initialize the parts of _PRCPU
+ * that must be initialized by that native thread.
+ *
+ * The reason we cannot simply have the native thread create
+ * and fully initialize a new CPU is that we need to be able to
+ * create a usable _pr_primordialCPU in _PR_InitCPUs without
+ * assuming that the primordial CPU thread we created can run
+ * during NSPR initialization. For example, on Windows while
+ * new threads can be created by DllMain, they won't be able
+ * to run during DLL initialization. If NSPR is initialized
+ * by DllMain, the primordial CPU thread won't run until DLL
+ * initialization is finished.
+ */
+static _PRCPU *_PR_CreateCPU(void)
+{
+ _PRCPU *cpu;
+
+ cpu = PR_NEWZAP(_PRCPU);
+ if (cpu) {
+ cpu->queue = _PR_CreateCPUQueue();
+ if (!cpu->queue) {
+ PR_DELETE(cpu);
+ return NULL;
+ }
+ }
+ return cpu;
+}
+
+/*
+ * Start a new CPU.
+ *
+ * 'cpu' is a _PRCPU structure created by _PR_CreateCPU().
+ * 'thread' is the native thread that will run the CPU.
+ *
+ * If this function fails, 'cpu' is destroyed.
+ */
+static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread)
+{
+ /*
+ ** Start a new cpu. The assumption this code makes is that the
+ ** underlying operating system creates a stack to go with the new
+ ** native thread. That stack will be used by the cpu when pausing.
+ */
+
+ PR_ASSERT(!_native_threads_only);
+
+ cpu->last_clock = PR_IntervalNow();
+
+ /* Before we create any threads on this CPU we have to
+ * set the current CPU
+ */
+ _PR_MD_SET_CURRENT_CPU(cpu);
+ _PR_MD_INIT_RUNNING_CPU(cpu);
+ thread->cpu = cpu;
+
+ cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD,
+ _PR_CPU_Idle,
+ (void *)cpu,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0,
+ _PR_IDLE_THREAD);
+
+ if (!cpu->idle_thread) {
+ /* didn't clean up CPU queue XXXMB */
+ PR_DELETE(cpu);
+ return PR_FAILURE;
+ }
+ PR_ASSERT(cpu->idle_thread->cpu == cpu);
+
+ cpu->idle_thread->no_sched = 0;
+
+ cpu->thread = thread;
+
+ if (_pr_cpu_affinity_mask)
+ PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask);
+
+ /* Created and started a new CPU */
+ _PR_CPU_LIST_LOCK();
+ cpu->id = _pr_cpuID++;
+ PR_APPEND_LINK(&cpu->links, &_PR_CPUQ());
+ _PR_CPU_LIST_UNLOCK();
+
+ return PR_SUCCESS;
+}
+
+#if !defined(_PR_GLOBAL_THREADS_ONLY) && !defined(_PR_LOCAL_THREADS_ONLY)
+/*
+** This code is used during a cpu's initial creation.
+*/
+static void _PR_RunCPU(void *arg)
+{
+ _PRCPU *cpu = (_PRCPU *)arg;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(NULL != me);
+
+ /*
+ * _PR_StartCPU calls _PR_CreateThread to create the
+ * idle thread. Because _PR_CreateThread calls PR_Lock,
+ * the current thread has to remain a global thread
+ * during the _PR_StartCPU call so that it can wait for
+ * the lock if the lock is held by another thread. If
+ * we clear the _PR_GLOBAL_SCOPE flag in
+ * _PR_MD_CREATE_PRIMORDIAL_THREAD, the current thread
+ * will be treated as a local thread and have trouble
+ * waiting for the lock because the CPU is not fully
+ * constructed yet.
+ *
+ * After the CPU is started, it is safe to mark the
+ * current thread as a local thread.
+ */
+
+#ifdef HAVE_CUSTOM_USER_THREADS
+ _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me);
+#endif
+
+ me->no_sched = 1;
+ _PR_StartCPU(cpu, me);
+
+#ifdef HAVE_CUSTOM_USER_THREADS
+ me->flags &= (~_PR_GLOBAL_SCOPE);
+#endif
+
+ _PR_MD_SET_CURRENT_CPU(cpu);
+ _PR_MD_SET_CURRENT_THREAD(cpu->thread);
+ me->cpu = cpu;
+
+ while(1) {
+ PRInt32 is;
+ if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
+ _PR_MD_START_INTERRUPTS();
+ _PR_MD_SWITCH_CONTEXT(me);
+ }
+}
+#endif
+
+static void PR_CALLBACK _PR_CPU_Idle(void *_cpu)
+{
+ _PRCPU *cpu = (_PRCPU *)_cpu;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(NULL != me);
+
+ me->cpu = cpu;
+ cpu->idle_thread = me;
+ if (_MD_LAST_THREAD())
+ _MD_LAST_THREAD()->no_sched = 0;
+ if (!_PR_IS_NATIVE_THREAD(me)) _PR_MD_SET_INTSOFF(0);
+ while(1) {
+ PRInt32 is;
+ PRIntervalTime timeout;
+ if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
+
+ _PR_RUNQ_LOCK(cpu);
+#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
+#ifdef _PR_HAVE_ATOMIC_OPS
+ _PR_MD_ATOMIC_INCREMENT(&_pr_md_idle_cpus);
+#else
+ _PR_MD_LOCK(&_pr_md_idle_cpus_lock);
+ _pr_md_idle_cpus++;
+ _PR_MD_UNLOCK(&_pr_md_idle_cpus_lock);
+#endif /* _PR_HAVE_ATOMIC_OPS */
+#endif
+ /* If someone on runq; do a nonblocking PAUSECPU */
+ if (_PR_RUNQREADYMASK(me->cpu) != 0) {
+ _PR_RUNQ_UNLOCK(cpu);
+ timeout = PR_INTERVAL_NO_WAIT;
+ } else {
+ _PR_RUNQ_UNLOCK(cpu);
+
+ _PR_SLEEPQ_LOCK(cpu);
+ if (PR_CLIST_IS_EMPTY(&_PR_SLEEPQ(me->cpu))) {
+ timeout = PR_INTERVAL_NO_TIMEOUT;
+ } else {
+ PRThread *wakeThread;
+ wakeThread = _PR_THREAD_PTR(_PR_SLEEPQ(me->cpu).next);
+ timeout = wakeThread->sleep;
+ }
+ _PR_SLEEPQ_UNLOCK(cpu);
+ }
+
+ /* Wait for an IO to complete */
+ (void)_PR_MD_PAUSE_CPU(timeout);
+
+#ifdef WINNT
+ if (_pr_cpus_exit) {
+ /* _PR_CleanupCPUs tells us to exit */
+ _PR_MD_END_THREAD();
+ }
+#endif
+
+#if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY)
+#ifdef _PR_HAVE_ATOMIC_OPS
+ _PR_MD_ATOMIC_DECREMENT(&_pr_md_idle_cpus);
+#else
+ _PR_MD_LOCK(&_pr_md_idle_cpus_lock);
+ _pr_md_idle_cpus--;
+ _PR_MD_UNLOCK(&_pr_md_idle_cpus_lock);
+#endif /* _PR_HAVE_ATOMIC_OPS */
+#endif
+
+ _PR_ClockInterrupt();
+
+ /* Now schedule any thread that is on the runq
+ * INTS must be OFF when calling PR_Schedule()
+ */
+ me->state = _PR_RUNNABLE;
+ _PR_MD_SWITCH_CONTEXT(me);
+ if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is);
+ }
+}
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+
+PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs)
+{
+#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_LOCAL_THREADS_ONLY)
+#ifdef XP_MAC
+#pragma unused(numCPUs)
+#endif
+
+ /* do nothing */
+
+#else /* combined, MxN thread model */
+
+ PRUintn newCPU;
+ _PRCPU *cpu;
+ PRThread *thr;
+
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (_native_threads_only)
+ return;
+
+ _PR_CPU_LIST_LOCK();
+ if (_pr_numCPU < numCPUs) {
+ newCPU = numCPUs - _pr_numCPU;
+ _pr_numCPU = numCPUs;
+ } else newCPU = 0;
+ _PR_CPU_LIST_UNLOCK();
+
+ for (; newCPU; newCPU--) {
+ cpu = _PR_CreateCPU();
+ thr = _PR_CreateThread(PR_SYSTEM_THREAD,
+ _PR_RunCPU,
+ cpu,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0,
+ _PR_IDLE_THREAD);
+ }
+#endif
+}
+
+PR_IMPLEMENT(_PRCPU *) _PR_GetPrimordialCPU(void)
+{
+ if (_pr_primordialCPU)
+ return _pr_primordialCPU;
+ else
+ return _PR_MD_CURRENT_CPU();
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucv.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucv.c
new file mode 100644
index 00000000..80d919b8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prucv.c
@@ -0,0 +1,681 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#include "primpl.h"
+#include "prinrval.h"
+#include "prtypes.h"
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+**
+*/
+#pragma warning(disable : 4101)
+#endif
+
+
+/*
+** Notify one thread that it has finished waiting on a condition variable
+** Caller must hold the _PR_CVAR_LOCK(cv)
+*/
+PRBool _PR_NotifyThread (PRThread *thread, PRThread *me)
+{
+ PRBool rv;
+
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
+
+ _PR_THREAD_LOCK(thread);
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+ if ( !_PR_IS_NATIVE_THREAD(thread) ) {
+ if (thread->wait.cvar != NULL) {
+ thread->wait.cvar = NULL;
+
+ _PR_SLEEPQ_LOCK(thread->cpu);
+ /* The notify and timeout can collide; in which case both may
+ * attempt to delete from the sleepQ; only let one do it.
+ */
+ if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ))
+ _PR_DEL_SLEEPQ(thread, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(thread->cpu);
+
+ if (thread->flags & _PR_SUSPENDING) {
+ /*
+ * set thread state to SUSPENDED; a Resume operation
+ * on the thread will move it to the runQ
+ */
+ thread->state = _PR_SUSPENDED;
+ _PR_MISCQ_LOCK(thread->cpu);
+ _PR_ADD_SUSPENDQ(thread, thread->cpu);
+ _PR_MISCQ_UNLOCK(thread->cpu);
+ _PR_THREAD_UNLOCK(thread);
+ } else {
+ /* Make thread runnable */
+ thread->state = _PR_RUNNABLE;
+ _PR_THREAD_UNLOCK(thread);
+
+ _PR_AddThreadToRunQ(me, thread);
+ _PR_MD_WAKEUP_WAITER(thread);
+ }
+
+ rv = PR_TRUE;
+ } else {
+ /* Thread has already been notified */
+ _PR_THREAD_UNLOCK(thread);
+ rv = PR_FALSE;
+ }
+ } else { /* If the thread is a native thread */
+ if (thread->wait.cvar) {
+ thread->wait.cvar = NULL;
+
+ if (thread->flags & _PR_SUSPENDING) {
+ /*
+ * set thread state to SUSPENDED; a Resume operation
+ * on the thread will enable the thread to run
+ */
+ thread->state = _PR_SUSPENDED;
+ } else
+ thread->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(thread);
+ _PR_MD_WAKEUP_WAITER(thread);
+ rv = PR_TRUE;
+ } else {
+ _PR_THREAD_UNLOCK(thread);
+ rv = PR_FALSE;
+ }
+ }
+
+ return rv;
+}
+
+/*
+ * Notify thread waiting on cvar; called when thread is interrupted
+ * The thread lock is held on entry and released before return
+ */
+void _PR_NotifyLockedThread (PRThread *thread)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRCondVar *cvar;
+ PRThreadPriority pri;
+
+ if ( !_PR_IS_NATIVE_THREAD(me))
+ PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
+
+ cvar = thread->wait.cvar;
+ thread->wait.cvar = NULL;
+ _PR_THREAD_UNLOCK(thread);
+
+ _PR_CVAR_LOCK(cvar);
+ _PR_THREAD_LOCK(thread);
+
+ if (!_PR_IS_NATIVE_THREAD(thread)) {
+ _PR_SLEEPQ_LOCK(thread->cpu);
+ /* The notify and timeout can collide; in which case both may
+ * attempt to delete from the sleepQ; only let one do it.
+ */
+ if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ))
+ _PR_DEL_SLEEPQ(thread, PR_TRUE);
+ _PR_SLEEPQ_UNLOCK(thread->cpu);
+
+ /* Make thread runnable */
+ pri = thread->priority;
+ thread->state = _PR_RUNNABLE;
+
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+
+ _PR_AddThreadToRunQ(me, thread);
+ _PR_THREAD_UNLOCK(thread);
+
+ _PR_MD_WAKEUP_WAITER(thread);
+ } else {
+ if (thread->flags & _PR_SUSPENDING) {
+ /*
+ * set thread state to SUSPENDED; a Resume operation
+ * on the thread will enable the thread to run
+ */
+ thread->state = _PR_SUSPENDED;
+ } else
+ thread->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(thread);
+ _PR_MD_WAKEUP_WAITER(thread);
+ }
+
+ _PR_CVAR_UNLOCK(cvar);
+ return;
+}
+
+/*
+** Make the given thread wait for the given condition variable
+*/
+PRStatus _PR_WaitCondVar(
+ PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
+{
+ PRIntn is;
+ PRStatus rv = PR_SUCCESS;
+
+ PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ if (_PR_PENDING_INTERRUPT(thread)) {
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ thread->flags &= ~_PR_INTERRUPT;
+ return PR_FAILURE;
+ }
+
+ thread->wait.cvar = cvar;
+ lock->owner = NULL;
+ _PR_MD_WAIT_CV(&cvar->md,&lock->ilock, timeout);
+ thread->wait.cvar = NULL;
+ lock->owner = thread;
+ if (_PR_PENDING_INTERRUPT(thread)) {
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ thread->flags &= ~_PR_INTERRUPT;
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+ if ( !_PR_IS_NATIVE_THREAD(thread))
+ _PR_INTSOFF(is);
+
+ _PR_CVAR_LOCK(cvar);
+ _PR_THREAD_LOCK(thread);
+
+ if (_PR_PENDING_INTERRUPT(thread)) {
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ thread->flags &= ~_PR_INTERRUPT;
+ _PR_CVAR_UNLOCK(cvar);
+ _PR_THREAD_UNLOCK(thread);
+ if ( !_PR_IS_NATIVE_THREAD(thread))
+ _PR_INTSON(is);
+ return PR_FAILURE;
+ }
+
+ thread->state = _PR_COND_WAIT;
+ thread->wait.cvar = cvar;
+
+ /*
+ ** Put the caller thread on the condition variable's wait Q
+ */
+ PR_APPEND_LINK(&thread->waitQLinks, &cvar->condQ);
+
+ /* Note- for global scope threads, we don't put them on the
+ * global sleepQ, so each global thread must put itself
+ * to sleep only for the time it wants to.
+ */
+ if ( !_PR_IS_NATIVE_THREAD(thread) ) {
+ _PR_SLEEPQ_LOCK(thread->cpu);
+ _PR_ADD_SLEEPQ(thread, timeout);
+ _PR_SLEEPQ_UNLOCK(thread->cpu);
+ }
+ _PR_CVAR_UNLOCK(cvar);
+ _PR_THREAD_UNLOCK(thread);
+
+ /*
+ ** Release lock protecting the condition variable and thereby giving time
+ ** to the next thread which can potentially notify on the condition variable
+ */
+ PR_Unlock(lock);
+
+ PR_LOG(_pr_cvar_lm, PR_LOG_MIN,
+ ("PR_Wait: cvar=%p waiting for %d", cvar, timeout));
+
+ rv = _PR_MD_WAIT(thread, timeout);
+
+ _PR_CVAR_LOCK(cvar);
+ PR_REMOVE_LINK(&thread->waitQLinks);
+ _PR_CVAR_UNLOCK(cvar);
+
+ PR_LOG(_pr_cvar_lm, PR_LOG_MIN,
+ ("PR_Wait: cvar=%p done waiting", cvar));
+
+ if ( !_PR_IS_NATIVE_THREAD(thread))
+ _PR_INTSON(is);
+
+ /* Acquire lock again that we had just relinquished */
+ PR_Lock(lock);
+
+ if (_PR_PENDING_INTERRUPT(thread)) {
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ thread->flags &= ~_PR_INTERRUPT;
+ return PR_FAILURE;
+ }
+
+ return rv;
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me)
+{
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ _PR_MD_NOTIFY_CV(&cvar->md, &cvar->lock->ilock);
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+ PRCList *q;
+ PRIntn is;
+
+ if ( !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
+
+ _PR_CVAR_LOCK(cvar);
+ q = cvar->condQ.next;
+ while (q != &cvar->condQ) {
+#ifndef XP_MAC
+ PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("_PR_NotifyCondVar: cvar=%p", cvar));
+#endif
+ if (_PR_THREAD_CONDQ_PTR(q)->wait.cvar) {
+ if (_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me) == PR_TRUE)
+ break;
+ }
+ q = q->next;
+ }
+ _PR_CVAR_UNLOCK(cvar);
+
+ if ( !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+/*
+** Cndition variable debugging log info.
+*/
+PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen)
+{
+ PRUint32 nb;
+
+ if (cvar->lock->owner) {
+ nb = PR_snprintf(buf, buflen, "[%p] owner=%ld[%p]",
+ cvar, cvar->lock->owner->id, cvar->lock->owner);
+ } else {
+ nb = PR_snprintf(buf, buflen, "[%p]", cvar);
+ }
+ return nb;
+}
+
+/*
+** Expire condition variable waits that are ready to expire. "now" is the current
+** time.
+*/
+void _PR_ClockInterrupt(void)
+{
+ PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
+ _PRCPU *cpu = me->cpu;
+ PRIntervalTime elapsed, now;
+
+ PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
+ /* Figure out how much time elapsed since the last clock tick */
+ now = PR_IntervalNow();
+ elapsed = now - cpu->last_clock;
+ cpu->last_clock = now;
+
+#ifndef XP_MAC
+ PR_LOG(_pr_clock_lm, PR_LOG_MAX,
+ ("ExpireWaits: elapsed=%lld usec", elapsed));
+#endif
+
+ while(1) {
+ _PR_SLEEPQ_LOCK(cpu);
+ if (_PR_SLEEPQ(cpu).next == &_PR_SLEEPQ(cpu)) {
+ _PR_SLEEPQ_UNLOCK(cpu);
+ break;
+ }
+
+ thread = _PR_THREAD_PTR(_PR_SLEEPQ(cpu).next);
+ PR_ASSERT(thread->cpu == cpu);
+
+ if (elapsed < thread->sleep) {
+ thread->sleep -= elapsed;
+ _PR_SLEEPQMAX(thread->cpu) -= elapsed;
+ _PR_SLEEPQ_UNLOCK(cpu);
+ break;
+ }
+ _PR_SLEEPQ_UNLOCK(cpu);
+
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));
+
+ _PR_THREAD_LOCK(thread);
+
+ if (thread->cpu != cpu) {
+ /*
+ ** The thread was switched to another CPU
+ ** between the time we unlocked the sleep
+ ** queue and the time we acquired the thread
+ ** lock, so it is none of our business now.
+ */
+ _PR_THREAD_UNLOCK(thread);
+ continue;
+ }
+
+ /*
+ ** Consume this sleeper's amount of elapsed time from the elapsed
+ ** time value. The next remaining piece of elapsed time will be
+ ** available for the next sleeping thread's timer.
+ */
+ _PR_SLEEPQ_LOCK(cpu);
+ PR_ASSERT(!(thread->flags & _PR_ON_PAUSEQ));
+ if (thread->flags & _PR_ON_SLEEPQ) {
+ _PR_DEL_SLEEPQ(thread, PR_FALSE);
+ elapsed -= thread->sleep;
+ _PR_SLEEPQ_UNLOCK(cpu);
+ } else {
+ /* Thread was already handled; Go get another one */
+ _PR_SLEEPQ_UNLOCK(cpu);
+ _PR_THREAD_UNLOCK(thread);
+ continue;
+ }
+
+ /* Notify the thread waiting on the condition variable */
+ if (thread->flags & _PR_SUSPENDING) {
+ PR_ASSERT((thread->state == _PR_IO_WAIT) ||
+ (thread->state == _PR_COND_WAIT));
+ /*
+ ** Thread is suspended and its condition timeout
+ ** expired. Transfer thread from sleepQ to suspendQ.
+ */
+ thread->wait.cvar = NULL;
+ _PR_MISCQ_LOCK(cpu);
+ thread->state = _PR_SUSPENDED;
+ _PR_ADD_SUSPENDQ(thread, cpu);
+ _PR_MISCQ_UNLOCK(cpu);
+ } else {
+ if (thread->wait.cvar) {
+ PRThreadPriority pri;
+
+ /* Do work very similar to what _PR_NotifyThread does */
+ PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) );
+
+ /* Make thread runnable */
+ pri = thread->priority;
+ thread->state = _PR_RUNNABLE;
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+
+ PR_ASSERT(thread->cpu == cpu);
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(thread, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+
+ if (pri > me->priority)
+ _PR_SET_RESCHED_FLAG();
+
+ thread->wait.cvar = NULL;
+
+ _PR_MD_WAKEUP_WAITER(thread);
+
+ } else if (thread->io_pending == PR_TRUE) {
+ /* Need to put IO sleeper back on runq */
+ int pri = thread->priority;
+
+ thread->io_suspended = PR_TRUE;
+#ifdef WINNT
+ /*
+ * For NT, record the cpu on which I/O was issued
+ * I/O cancellation is done on the same cpu
+ */
+ thread->md.thr_bound_cpu = cpu;
+#endif
+
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+ PR_ASSERT(thread->cpu == cpu);
+ thread->state = _PR_RUNNABLE;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(thread, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ }
+ }
+ _PR_THREAD_UNLOCK(thread);
+ }
+}
+
+/************************************************************************/
+
+/*
+** Create a new condition variable.
+** "lock" is the lock to use with the condition variable.
+**
+** Condition variables are synchronization objects that threads can use
+** to wait for some condition to occur.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low.
+*/
+PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock)
+{
+ PRCondVar *cvar;
+
+ PR_ASSERT(lock != NULL);
+
+ cvar = PR_NEWZAP(PRCondVar);
+ if (cvar) {
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ if(_PR_MD_NEW_CV(&cvar->md)) {
+ PR_DELETE(cvar);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return NULL;
+ }
+#endif
+ if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) {
+ PR_DELETE(cvar);
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return NULL;
+ }
+ cvar->lock = lock;
+ PR_INIT_CLIST(&cvar->condQ);
+
+ } else {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+ return cvar;
+}
+
+/*
+** Destroy a condition variable. There must be no thread
+** waiting on the condvar. The caller is responsible for guaranteeing
+** that the condvar is no longer in use.
+**
+*/
+PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar)
+{
+ PR_ASSERT(cvar->condQ.next == &cvar->condQ);
+
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ _PR_MD_FREE_CV(&cvar->md);
+#endif
+ _PR_MD_FREE_LOCK(&(cvar->ilock));
+
+ PR_DELETE(cvar);
+}
+
+/*
+** Wait for a notify on the condition variable. Sleep for "tiemout" amount
+** of ticks (if "timeout" is zero then the sleep is indefinite). While
+** the thread is waiting it unlocks lock. When the wait has
+** finished the thread regains control of the condition variable after
+** locking the associated lock.
+**
+** The thread waiting on the condvar will be resumed when the condvar is
+** notified (assuming the thread is the next in line to receive the
+** notify) or when the timeout elapses.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable or the thread has been interrupted.
+*/
+extern PRThread *suspendAllThread;
+PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(cvar->lock->owner == me);
+ PR_ASSERT(me != suspendAllThread);
+ if (cvar->lock->owner != me) return PR_FAILURE;
+
+ return _PR_WaitCondVar(me, cvar, cvar->lock, timeout);
+}
+
+/*
+** Notify the highest priority thread waiting on the condition
+** variable. If a thread is waiting on the condition variable (using
+** PR_Wait) then it is awakened and begins waiting on the lock.
+*/
+PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(cvar->lock->owner == me);
+ PR_ASSERT(me != suspendAllThread);
+ if (cvar->lock->owner != me) return PR_FAILURE;
+
+ _PR_NotifyCondVar(cvar, me);
+ return PR_SUCCESS;
+}
+
+/*
+** Notify all of the threads waiting on the condition variable. All of
+** threads are notified in turn. The highest priority thread will
+** probably acquire the lock.
+*/
+PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar)
+{
+ PRCList *q;
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(cvar->lock->owner == me);
+ if (cvar->lock->owner != me) return PR_FAILURE;
+
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ _PR_MD_NOTIFYALL_CV(&cvar->md, &cvar->lock->ilock);
+ return PR_SUCCESS;
+#else /* _PR_GLOBAL_THREADS_ONLY */
+ if ( !_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ _PR_CVAR_LOCK(cvar);
+ q = cvar->condQ.next;
+ while (q != &cvar->condQ) {
+ PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
+ _PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
+ q = q->next;
+ }
+ _PR_CVAR_UNLOCK(cvar);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+
+ return PR_SUCCESS;
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+
+/*********************************************************************/
+/*********************************************************************/
+/********************ROUTINES FOR DCE EMULATION***********************/
+/*********************************************************************/
+/*********************************************************************/
+#include "prpdce.h"
+
+PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)
+{
+ PRCondVar *cvar = PR_NEWZAP(PRCondVar);
+ if (NULL != cvar)
+ {
+ if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE)
+ {
+ PR_DELETE(cvar); cvar = NULL;
+ }
+ else
+ {
+ PR_INIT_CLIST(&cvar->condQ);
+ cvar->lock = _PR_NAKED_CV_LOCK;
+ }
+
+ }
+ return cvar;
+}
+
+PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar)
+{
+ PR_ASSERT(cvar->condQ.next == &cvar->condQ);
+ PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
+
+ _PR_MD_FREE_LOCK(&(cvar->ilock));
+
+ PR_DELETE(cvar);
+}
+
+PR_IMPLEMENT(PRStatus) PRP_NakedWait(
+ PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
+ return _PR_WaitCondVar(me, cvar, lock, timeout);
+} /* PRP_NakedWait */
+
+PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
+
+ _PR_NotifyCondVar(cvar, me);
+
+ return PR_SUCCESS;
+} /* PRP_NakedNotify */
+
+PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar)
+{
+ PRCList *q;
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock);
+
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
+ _PR_MD_LOCK( &(cvar->ilock) );
+ q = cvar->condQ.next;
+ while (q != &cvar->condQ) {
+ PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar));
+ _PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me);
+ q = q->next;
+ }
+ _PR_MD_UNLOCK( &(cvar->ilock) );
+ if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
+
+ return PR_SUCCESS;
+} /* PRP_NakedBroadcast */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prulock.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prulock.c
new file mode 100644
index 00000000..5ede1c7b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prulock.c
@@ -0,0 +1,463 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+**
+*/
+#pragma warning(disable : 4101)
+#endif
+
+
+void _PR_InitLocks(void)
+{
+ _PR_MD_INIT_LOCKS();
+}
+
+/*
+** Deal with delayed interrupts/requested reschedule during interrupt
+** re-enables.
+*/
+void _PR_IntsOn(_PRCPU *cpu)
+{
+ PRUintn missed, pri, i;
+ _PRInterruptTable *it;
+ PRThread *me;
+
+ PR_ASSERT(cpu); /* Global threads don't have CPUs */
+ PR_ASSERT(_PR_MD_GET_INTSOFF() > 0);
+ me = _PR_MD_CURRENT_THREAD();
+#if !defined(XP_MAC)
+ PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
+#endif
+
+ /*
+ ** Process delayed interrupts. This logic is kinda scary because we
+ ** need to avoid losing an interrupt (it's ok to delay an interrupt
+ ** until later).
+ **
+ ** There are two missed state words. _pr_ints.where indicates to the
+ ** interrupt handler which state word is currently safe for
+ ** modification.
+ **
+ ** This code scans both interrupt state words, using the where flag
+ ** to indicate to the interrupt which state word is safe for writing.
+ ** If an interrupt comes in during a scan the other word will be
+ ** modified. This modification will be noticed during the next
+ ** iteration of the loop or during the next call to this routine.
+ */
+ for (i = 0; i < 2; i++) {
+ cpu->where = (1 - i);
+ missed = cpu->u.missed[i];
+ if (missed != 0) {
+ cpu->u.missed[i] = 0;
+ for (it = _pr_interruptTable; it->name; it++) {
+ if (missed & it->missed_bit) {
+#ifndef XP_MAC
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN,
+ ("IntsOn[0]: %s intr", it->name));
+#endif
+ (*it->handler)();
+ }
+ }
+ }
+ }
+
+ if (cpu->u.missed[3] != 0) {
+ _PRCPU *cpu;
+
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_RUNNABLE;
+ pri = me->priority;
+
+ cpu = me->cpu;
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(me, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ _PR_THREAD_UNLOCK(me);
+ _PR_MD_SWITCH_CONTEXT(me);
+ }
+}
+
+/*
+** Unblock the first runnable waiting thread. Skip over
+** threads that are trying to be suspended
+** Note: Caller must hold _PR_LOCK_LOCK()
+*/
+void _PR_UnblockLockWaiter(PRLock *lock)
+{
+ PRThread *t = NULL;
+ PRThread *me;
+ PRCList *q;
+
+ q = lock->waitQ.next;
+ PR_ASSERT(q != &lock->waitQ);
+ while (q != &lock->waitQ) {
+ /* Unblock first waiter */
+ t = _PR_THREAD_CONDQ_PTR(q);
+
+ /*
+ ** We are about to change the thread's state to runnable and for local
+ ** threads, we are going to assign a cpu to it. So, protect thread's
+ ** data structure.
+ */
+ _PR_THREAD_LOCK(t);
+
+ if (t->flags & _PR_SUSPENDING) {
+ q = q->next;
+ _PR_THREAD_UNLOCK(t);
+ continue;
+ }
+
+ /* Found a runnable thread */
+ PR_ASSERT(t->state == _PR_LOCK_WAIT);
+ PR_ASSERT(t->wait.lock == lock);
+ t->wait.lock = 0;
+ PR_REMOVE_LINK(&t->waitQLinks); /* take it off lock's waitQ */
+
+ /*
+ ** If this is a native thread, nothing else to do except to wake it
+ ** up by calling the machine dependent wakeup routine.
+ **
+ ** If this is a local thread, we need to assign it a cpu and
+ ** put the thread on that cpu's run queue. There are two cases to
+ ** take care of. If the currently running thread is also a local
+ ** thread, we just assign our own cpu to that thread and put it on
+ ** the cpu's run queue. If the the currently running thread is a
+ ** native thread, we assign the primordial cpu to it (on NT,
+ ** MD_WAKEUP handles the cpu assignment).
+ */
+
+ if ( !_PR_IS_NATIVE_THREAD(t) ) {
+
+ t->state = _PR_RUNNABLE;
+
+ me = _PR_MD_CURRENT_THREAD();
+
+ _PR_AddThreadToRunQ(me, t);
+ _PR_THREAD_UNLOCK(t);
+ } else {
+ t->state = _PR_RUNNING;
+ _PR_THREAD_UNLOCK(t);
+ }
+ _PR_MD_WAKEUP_WAITER(t);
+ break;
+ }
+ return;
+}
+
+/************************************************************************/
+
+
+PR_IMPLEMENT(PRLock*) PR_NewLock(void)
+{
+ PRLock *lock;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ lock = PR_NEWZAP(PRLock);
+ if (lock) {
+ if (_PR_MD_NEW_LOCK(&lock->ilock) == PR_FAILURE) {
+ PR_DELETE(lock);
+ return(NULL);
+ }
+ PR_INIT_CLIST(&lock->links);
+ PR_INIT_CLIST(&lock->waitQ);
+ }
+ return lock;
+}
+
+/*
+** Destroy the given lock "lock". There is no point in making this race
+** free because if some other thread has the pointer to this lock all
+** bets are off.
+*/
+PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock)
+{
+ PR_ASSERT(lock->owner == 0);
+ _PR_MD_FREE_LOCK(&lock->ilock);
+ PR_DELETE(lock);
+}
+
+extern PRThread *suspendAllThread;
+/*
+** Lock the lock.
+*/
+PR_IMPLEMENT(void) PR_Lock(PRLock *lock)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntn is;
+ PRThread *t;
+ PRCList *q;
+
+ PR_ASSERT(me != suspendAllThread);
+#if !defined(XP_MAC)
+ PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
+#endif
+ PR_ASSERT(lock != NULL);
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ PR_ASSERT(lock->owner != me);
+ _PR_MD_LOCK(&lock->ilock);
+ lock->owner = me;
+ return;
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+ if (_native_threads_only) {
+ PR_ASSERT(lock->owner != me);
+ _PR_MD_LOCK(&lock->ilock);
+ lock->owner = me;
+ return;
+ }
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
+
+retry:
+ _PR_LOCK_LOCK(lock);
+ if (lock->owner == 0) {
+ /* Just got the lock */
+ lock->owner = me;
+ lock->priority = me->priority;
+ /* Add the granted lock to this owning thread's lock list */
+ PR_APPEND_LINK(&lock->links, &me->lockList);
+ _PR_LOCK_UNLOCK(lock);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_FAST_INTSON(is);
+ return;
+ }
+
+ /* If this thread already owns this lock, then it is a deadlock */
+ PR_ASSERT(lock->owner != me);
+
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
+
+#if 0
+ if (me->priority > lock->owner->priority) {
+ /*
+ ** Give the lock owner a priority boost until we get the
+ ** lock. Record the priority we boosted it to.
+ */
+ lock->boostPriority = me->priority;
+ _PR_SetThreadPriority(lock->owner, me->priority);
+ }
+#endif
+
+ /*
+ Add this thread to the asked for lock's list of waiting threads. We
+ add this thread thread in the right priority order so when the unlock
+ occurs, the thread with the higher priority will get the lock.
+ */
+ q = lock->waitQ.next;
+ if (q == &lock->waitQ || _PR_THREAD_CONDQ_PTR(q)->priority ==
+ _PR_THREAD_CONDQ_PTR(lock->waitQ.prev)->priority) {
+ /*
+ * If all the threads in the lock waitQ have the same priority,
+ * then avoid scanning the list: insert the element at the end.
+ */
+ q = &lock->waitQ;
+ } else {
+ /* Sort thread into lock's waitQ at appropriate point */
+ /* Now scan the list for where to insert this entry */
+ while (q != &lock->waitQ) {
+ t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next);
+ if (me->priority > t->priority) {
+ /* Found a lower priority thread to insert in front of */
+ break;
+ }
+ q = q->next;
+ }
+ }
+ PR_INSERT_BEFORE(&me->waitQLinks, q);
+
+ /*
+ Now grab the threadLock since we are about to change the state. We have
+ to do this since a PR_Suspend or PR_SetThreadPriority type call that takes
+ a PRThread* as an argument could be changing the state of this thread from
+ a thread running on a different cpu.
+ */
+
+ _PR_THREAD_LOCK(me);
+ me->state = _PR_LOCK_WAIT;
+ me->wait.lock = lock;
+ _PR_THREAD_UNLOCK(me);
+
+ _PR_LOCK_UNLOCK(lock);
+
+ _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT);
+ goto retry;
+
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+/*
+** Unlock the lock.
+*/
+PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock)
+{
+ PRCList *q;
+ PRThreadPriority pri, boost;
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(lock != NULL);
+ PR_ASSERT(lock->owner == me);
+ PR_ASSERT(me != suspendAllThread);
+#if !defined(XP_MAC)
+ PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
+#endif
+ if (lock->owner != me) {
+ return PR_FAILURE;
+ }
+
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ lock->owner = 0;
+ _PR_MD_UNLOCK(&lock->ilock);
+ return PR_SUCCESS;
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+ if (_native_threads_only) {
+ lock->owner = 0;
+ _PR_MD_UNLOCK(&lock->ilock);
+ return PR_SUCCESS;
+ }
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ _PR_LOCK_LOCK(lock);
+
+ /* Remove the lock from the owning thread's lock list */
+ PR_REMOVE_LINK(&lock->links);
+ pri = lock->priority;
+ boost = lock->boostPriority;
+ if (boost > pri) {
+ /*
+ ** We received a priority boost during the time we held the lock.
+ ** We need to figure out what priority to move to by scanning
+ ** down our list of lock's that we are still holding and using
+ ** the highest boosted priority found.
+ */
+ q = me->lockList.next;
+ while (q != &me->lockList) {
+ PRLock *ll = _PR_LOCK_PTR(q);
+ if (ll->boostPriority > pri) {
+ pri = ll->boostPriority;
+ }
+ q = q->next;
+ }
+ if (pri != me->priority) {
+ _PR_SetThreadPriority(me, pri);
+ }
+ }
+
+ /* Unblock the first waiting thread */
+ q = lock->waitQ.next;
+ if (q != &lock->waitQ)
+ _PR_UnblockLockWaiter(lock);
+ lock->boostPriority = PR_PRIORITY_LOW;
+ lock->owner = 0;
+ _PR_LOCK_UNLOCK(lock);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+ return PR_SUCCESS;
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+/*
+** Test and then lock the lock if it's not already locked by some other
+** thread. Return PR_FALSE if some other thread owned the lock at the
+** time of the call.
+*/
+PR_IMPLEMENT(PRBool) PR_TestAndLock(PRLock *lock)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRBool rv = PR_FALSE;
+ PRIntn is;
+
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
+ if (is == 0) {
+ lock->owner = me;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+#else /* _PR_GLOBAL_THREADS_ONLY */
+
+#ifndef _PR_LOCAL_THREADS_ONLY
+ if (_native_threads_only) {
+ is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
+ if (is == 0) {
+ lock->owner = me;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+ }
+#endif
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+
+ _PR_LOCK_LOCK(lock);
+ if (lock->owner == 0) {
+ /* Just got the lock */
+ lock->owner = me;
+ lock->priority = me->priority;
+ /* Add the granted lock to this owning thread's lock list */
+ PR_APPEND_LINK(&lock->links, &me->lockList);
+ rv = PR_TRUE;
+ }
+ _PR_LOCK_UNLOCK(lock);
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+ return rv;
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+/************************************************************************/
+/************************************************************************/
+/***********************ROUTINES FOR DCE EMULATION***********************/
+/************************************************************************/
+/************************************************************************/
+PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
+ { return (PR_TestAndLock(lock)) ? PR_SUCCESS : PR_FAILURE; }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prustack.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prustack.c
new file mode 100644
index 00000000..fe15843c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/prustack.c
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/* List of free stack virtual memory chunks */
+PRLock *_pr_stackLock;
+PRCList _pr_freeStacks = PR_INIT_STATIC_CLIST(&_pr_freeStacks);
+PRIntn _pr_numFreeStacks;
+PRIntn _pr_maxFreeStacks = 4;
+
+#ifdef DEBUG
+/*
+** A variable that can be set via the debugger...
+*/
+PRBool _pr_debugStacks = PR_FALSE;
+#endif
+
+/* How much space to leave between the stacks, at each end */
+#define REDZONE (2 << _pr_pageShift)
+
+#define _PR_THREAD_STACK_PTR(_qp) \
+ ((PRThreadStack*) ((char*) (_qp) - offsetof(PRThreadStack,links)))
+
+void _PR_InitStacks(void)
+{
+ _pr_stackLock = PR_NewLock();
+}
+
+void _PR_CleanupStacks(void)
+{
+ if (_pr_stackLock) {
+ PR_DestroyLock(_pr_stackLock);
+ _pr_stackLock = NULL;
+ }
+}
+
+/*
+** Allocate a stack for a thread.
+*/
+PRThreadStack *_PR_NewStack(PRUint32 stackSize)
+{
+ PRCList *qp;
+ PRThreadStack *ts;
+ PRThread *thr;
+
+ /*
+ ** Trim the list of free stacks. Trim it backwards, tossing out the
+ ** oldest stack found first (this way more recent stacks have a
+ ** chance of being present in the data cache).
+ */
+ PR_Lock(_pr_stackLock);
+ qp = _pr_freeStacks.prev;
+ while ((_pr_numFreeStacks > _pr_maxFreeStacks) && (qp != &_pr_freeStacks)) {
+ ts = _PR_THREAD_STACK_PTR(qp);
+ thr = _PR_THREAD_STACK_TO_PTR(ts);
+ qp = qp->prev;
+ /*
+ * skip stacks which are still being used
+ */
+ if (thr->no_sched)
+ continue;
+ PR_REMOVE_LINK(&ts->links);
+
+ /* Give platform OS to clear out the stack for debugging */
+ _PR_MD_CLEAR_STACK(ts);
+
+ _pr_numFreeStacks--;
+ _PR_DestroySegment(ts->seg);
+ PR_DELETE(ts);
+ }
+
+ /*
+ ** Find a free thread stack. This searches the list of free'd up
+ ** virtually mapped thread stacks.
+ */
+ qp = _pr_freeStacks.next;
+ ts = 0;
+ while (qp != &_pr_freeStacks) {
+ ts = _PR_THREAD_STACK_PTR(qp);
+ thr = _PR_THREAD_STACK_TO_PTR(ts);
+ qp = qp->next;
+ /*
+ * skip stacks which are still being used
+ */
+ if ((!(thr->no_sched)) && ((ts->allocSize - 2*REDZONE) >= stackSize)) {
+ /*
+ ** Found a stack that is not in use and is big enough. Change
+ ** stackSize to fit it.
+ */
+ stackSize = ts->allocSize - 2*REDZONE;
+ PR_REMOVE_LINK(&ts->links);
+ _pr_numFreeStacks--;
+ ts->links.next = 0;
+ ts->links.prev = 0;
+ PR_Unlock(_pr_stackLock);
+ goto done;
+ }
+ ts = 0;
+ }
+ PR_Unlock(_pr_stackLock);
+
+ if (!ts) {
+ /* Make a new thread stack object. */
+ ts = PR_NEWZAP(PRThreadStack);
+ if (!ts) {
+ return NULL;
+ }
+
+ /*
+ ** Assign some of the virtual space to the new stack object. We
+ ** may not get that piece of VM, but if nothing else we will
+ ** advance the pointer so we don't collide (unless the OS screws
+ ** up).
+ */
+ ts->allocSize = stackSize + 2*REDZONE;
+ ts->seg = _PR_NewSegment(ts->allocSize, 0);
+ if (!ts->seg) {
+ PR_DELETE(ts);
+ return NULL;
+ }
+ }
+
+ done:
+ ts->allocBase = (char*)ts->seg->vaddr;
+ ts->flags = _PR_STACK_MAPPED;
+ ts->stackSize = stackSize;
+
+#ifdef HAVE_STACK_GROWING_UP
+ ts->stackTop = ts->allocBase + REDZONE;
+ ts->stackBottom = ts->stackTop + stackSize;
+#else
+ ts->stackBottom = ts->allocBase + REDZONE;
+ ts->stackTop = ts->stackBottom + stackSize;
+#endif
+
+ PR_LOG(_pr_thread_lm, PR_LOG_NOTICE,
+ ("thread stack: base=0x%x limit=0x%x bottom=0x%x top=0x%x\n",
+ ts->allocBase, ts->allocBase + ts->allocSize - 1,
+ ts->allocBase + REDZONE,
+ ts->allocBase + REDZONE + stackSize - 1));
+
+ _PR_MD_INIT_STACK(ts,REDZONE);
+
+ return ts;
+}
+
+/*
+** Free the stack for the current thread
+*/
+void _PR_FreeStack(PRThreadStack *ts)
+{
+ if (!ts) {
+ return;
+ }
+ if (ts->flags & _PR_STACK_PRIMORDIAL) {
+ PR_DELETE(ts);
+ return;
+ }
+
+ /*
+ ** Put the stack on the free list. This is done because we are still
+ ** using the stack. Next time a thread is created we will trim the
+ ** list down; it's safe to do it then because we will have had to
+ ** context switch to a live stack before another thread can be
+ ** created.
+ */
+ PR_Lock(_pr_stackLock);
+ PR_APPEND_LINK(&ts->links, _pr_freeStacks.prev);
+ _pr_numFreeStacks++;
+ PR_Unlock(_pr_stackLock);
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/pruthr.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/pruthr.c
new file mode 100644
index 00000000..7e31b56b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/combined/pruthr.c
@@ -0,0 +1,1918 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#include <signal.h>
+#include <string.h>
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+**
+*/
+#pragma warning(disable : 4101)
+#endif
+
+#if defined(XP_MAC)
+#include <LowMem.h>
+#endif
+
+/* _pr_activeLock protects the following global variables */
+PRLock *_pr_activeLock;
+PRInt32 _pr_primordialExitCount; /* In PR_Cleanup(), the primordial thread
+ * waits until all other user (non-system)
+ * threads have terminated before it exits.
+ * So whenever we decrement _pr_userActive,
+ * it is compared with
+ * _pr_primordialExitCount.
+ * If the primordial thread is a system
+ * thread, then _pr_primordialExitCount
+ * is 0. If the primordial thread is
+ * itself a user thread, then
+ * _pr_primordialThread is 1.
+ */
+PRCondVar *_pr_primordialExitCVar; /* When _pr_userActive is decremented to
+ * _pr_primordialExitCount, this condition
+ * variable is notified.
+ */
+
+PRLock *_pr_deadQLock;
+PRUint32 _pr_numNativeDead;
+PRUint32 _pr_numUserDead;
+PRCList _pr_deadNativeQ;
+PRCList _pr_deadUserQ;
+
+PRUint32 _pr_join_counter;
+
+PRUint32 _pr_local_threads;
+PRUint32 _pr_global_threads;
+
+PRBool suspendAllOn = PR_FALSE;
+PRThread *suspendAllThread = NULL;
+
+extern PRCList _pr_active_global_threadQ;
+extern PRCList _pr_active_local_threadQ;
+
+static void _PR_DecrActiveThreadCount(PRThread *thread);
+static PRThread *_PR_AttachThread(PRThreadType, PRThreadPriority, PRThreadStack *);
+static void _PR_InitializeNativeStack(PRThreadStack *ts);
+static void _PR_InitializeRecycledThread(PRThread *thread);
+static void _PR_UserRunThread(void);
+
+void _PR_InitThreads(PRThreadType type, PRThreadPriority priority,
+ PRUintn maxPTDs)
+{
+#if defined(XP_MAC)
+#pragma unused (maxPTDs)
+#endif
+
+ PRThread *thread;
+ PRThreadStack *stack;
+
+ _pr_terminationCVLock = PR_NewLock();
+ _pr_activeLock = PR_NewLock();
+
+#ifndef HAVE_CUSTOM_USER_THREADS
+ stack = PR_NEWZAP(PRThreadStack);
+#ifdef HAVE_STACK_GROWING_UP
+ stack->stackTop = (char*) ((((long)&type) >> _pr_pageShift)
+ << _pr_pageShift);
+#else
+#if defined(SOLARIS) || defined (UNIXWARE) && defined (USR_SVR4_THREADS)
+ stack->stackTop = (char*) &thread;
+#elif defined(XP_MAC)
+ stack->stackTop = (char*) LMGetCurStackBase();
+#else
+ stack->stackTop = (char*) ((((long)&type + _pr_pageSize - 1)
+ >> _pr_pageShift) << _pr_pageShift);
+#endif
+#endif
+#else
+ /* If stack is NULL, we're using custom user threads like NT fibers. */
+ stack = PR_NEWZAP(PRThreadStack);
+ if (stack) {
+ stack->stackSize = 0;
+ _PR_InitializeNativeStack(stack);
+ }
+#endif /* HAVE_CUSTOM_USER_THREADS */
+
+ thread = _PR_AttachThread(type, priority, stack);
+ if (thread) {
+ _PR_MD_SET_CURRENT_THREAD(thread);
+
+ if (type == PR_SYSTEM_THREAD) {
+ thread->flags = _PR_SYSTEM;
+ _pr_systemActive++;
+ _pr_primordialExitCount = 0;
+ } else {
+ _pr_userActive++;
+ _pr_primordialExitCount = 1;
+ }
+ thread->no_sched = 1;
+ _pr_primordialExitCVar = PR_NewCondVar(_pr_activeLock);
+ }
+
+ if (!thread) PR_Abort();
+#ifdef _PR_LOCAL_THREADS_ONLY
+ thread->flags |= _PR_PRIMORDIAL;
+#else
+ thread->flags |= _PR_PRIMORDIAL | _PR_GLOBAL_SCOPE;
+#endif
+
+ /*
+ * Needs _PR_PRIMORDIAL flag set before calling
+ * _PR_MD_INIT_THREAD()
+ */
+ if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
+ /*
+ * XXX do what?
+ */
+ }
+
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
+ _pr_global_threads++;
+ } else {
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
+ _pr_local_threads++;
+ }
+
+ _pr_recycleThreads = 0;
+ _pr_deadQLock = PR_NewLock();
+ _pr_numNativeDead = 0;
+ _pr_numUserDead = 0;
+ PR_INIT_CLIST(&_pr_deadNativeQ);
+ PR_INIT_CLIST(&_pr_deadUserQ);
+}
+
+void _PR_CleanupThreads(void)
+{
+ if (_pr_terminationCVLock) {
+ PR_DestroyLock(_pr_terminationCVLock);
+ _pr_terminationCVLock = NULL;
+ }
+ if (_pr_activeLock) {
+ PR_DestroyLock(_pr_activeLock);
+ _pr_activeLock = NULL;
+ }
+ if (_pr_primordialExitCVar) {
+ PR_DestroyCondVar(_pr_primordialExitCVar);
+ _pr_primordialExitCVar = NULL;
+ }
+ /* TODO _pr_dead{Native,User}Q need to be deleted */
+ if (_pr_deadQLock) {
+ PR_DestroyLock(_pr_deadQLock);
+ _pr_deadQLock = NULL;
+ }
+}
+
+/*
+** Initialize a stack for a native thread
+*/
+static void _PR_InitializeNativeStack(PRThreadStack *ts)
+{
+ if( ts && (ts->stackTop == 0) ) {
+ ts->allocSize = ts->stackSize;
+
+ /*
+ ** Setup stackTop and stackBottom values.
+ */
+#ifdef HAVE_STACK_GROWING_UP
+ ts->allocBase = (char*) ((((long)&ts) >> _pr_pageShift)
+ << _pr_pageShift);
+ ts->stackBottom = ts->allocBase + ts->stackSize;
+ ts->stackTop = ts->allocBase;
+#else
+ ts->allocBase = (char*) ((((long)&ts + _pr_pageSize - 1)
+ >> _pr_pageShift) << _pr_pageShift);
+ ts->stackTop = ts->allocBase;
+ ts->stackBottom = ts->allocBase - ts->stackSize;
+#endif
+ }
+}
+
+void _PR_NotifyJoinWaiters(PRThread *thread)
+{
+ /*
+ ** Handle joinable threads. Change the state to waiting for join.
+ ** Remove from our run Q and put it on global waiting to join Q.
+ ** Notify on our "termination" condition variable so that joining
+ ** thread will know about our termination. Switch our context and
+ ** come back later on to continue the cleanup.
+ */
+ PR_ASSERT(thread == _PR_MD_CURRENT_THREAD());
+ if (thread->term != NULL) {
+ PR_Lock(_pr_terminationCVLock);
+ _PR_THREAD_LOCK(thread);
+ thread->state = _PR_JOIN_WAIT;
+ if ( !_PR_IS_NATIVE_THREAD(thread) ) {
+ _PR_MISCQ_LOCK(thread->cpu);
+ _PR_ADD_JOINQ(thread, thread->cpu);
+ _PR_MISCQ_UNLOCK(thread->cpu);
+ }
+ _PR_THREAD_UNLOCK(thread);
+ PR_NotifyCondVar(thread->term);
+ PR_Unlock(_pr_terminationCVLock);
+ _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(thread->state != _PR_JOIN_WAIT);
+ }
+
+}
+
+/*
+ * Zero some of the data members of a recycled thread.
+ *
+ * Note that we can do this either when a dead thread is added to
+ * the dead thread queue or when it is reused. Here, we are doing
+ * this lazily, when the thread is reused in _PR_CreateThread().
+ */
+static void _PR_InitializeRecycledThread(PRThread *thread)
+{
+ /*
+ * Assert that the following data members are already zeroed
+ * by _PR_CleanupThread().
+ */
+#ifdef DEBUG
+ if (thread->privateData) {
+ unsigned int i;
+ for (i = 0; i < thread->tpdLength; i++) {
+ PR_ASSERT(thread->privateData[i] == NULL);
+ }
+ }
+#endif
+ PR_ASSERT(thread->dumpArg == 0 && thread->dump == 0);
+ PR_ASSERT(thread->errorString == 0 && thread->errorStringSize == 0);
+ PR_ASSERT(thread->errorStringLength == 0);
+
+ /* Reset data members in thread structure */
+ thread->errorCode = thread->osErrorCode = 0;
+ thread->io_pending = thread->io_suspended = PR_FALSE;
+ thread->environment = 0;
+ PR_INIT_CLIST(&thread->lockList);
+}
+
+PRStatus _PR_RecycleThread(PRThread *thread)
+{
+ if ( _PR_IS_NATIVE_THREAD(thread) &&
+ _PR_NUM_DEADNATIVE < _pr_recycleThreads) {
+ _PR_DEADQ_LOCK;
+ PR_APPEND_LINK(&thread->links, &_PR_DEADNATIVEQ);
+ _PR_INC_DEADNATIVE;
+ _PR_DEADQ_UNLOCK;
+ return (PR_SUCCESS);
+ } else if ( !_PR_IS_NATIVE_THREAD(thread) &&
+ _PR_NUM_DEADUSER < _pr_recycleThreads) {
+ _PR_DEADQ_LOCK;
+ PR_APPEND_LINK(&thread->links, &_PR_DEADUSERQ);
+ _PR_INC_DEADUSER;
+ _PR_DEADQ_UNLOCK;
+ return (PR_SUCCESS);
+ }
+ return (PR_FAILURE);
+}
+
+/*
+ * Decrement the active thread count, either _pr_systemActive or
+ * _pr_userActive, depending on whether the thread is a system thread
+ * or a user thread. If all the user threads, except possibly
+ * the primordial thread, have terminated, we notify the primordial
+ * thread of this condition.
+ *
+ * Since this function will lock _pr_activeLock, do not call this
+ * function while holding the _pr_activeLock lock, as this will result
+ * in a deadlock.
+ */
+
+static void
+_PR_DecrActiveThreadCount(PRThread *thread)
+{
+ PR_Lock(_pr_activeLock);
+ if (thread->flags & _PR_SYSTEM) {
+ _pr_systemActive--;
+ } else {
+ _pr_userActive--;
+ if (_pr_userActive == _pr_primordialExitCount) {
+ PR_NotifyCondVar(_pr_primordialExitCVar);
+ }
+ }
+ PR_Unlock(_pr_activeLock);
+}
+
+/*
+** Detach thread structure
+*/
+static void
+_PR_DestroyThread(PRThread *thread)
+{
+ _PR_MD_FREE_LOCK(&thread->threadLock);
+ PR_DELETE(thread);
+}
+
+void
+_PR_NativeDestroyThread(PRThread *thread)
+{
+ if(thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ if (NULL != thread->privateData) {
+ PR_ASSERT(0 != thread->tpdLength);
+ PR_DELETE(thread->privateData);
+ thread->tpdLength = 0;
+ }
+ PR_DELETE(thread->stack);
+ _PR_DestroyThread(thread);
+}
+
+void
+_PR_UserDestroyThread(PRThread *thread)
+{
+ if(thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ if (NULL != thread->privateData) {
+ PR_ASSERT(0 != thread->tpdLength);
+ PR_DELETE(thread->privateData);
+ thread->tpdLength = 0;
+ }
+ _PR_MD_FREE_LOCK(&thread->threadLock);
+ if (thread->threadAllocatedOnStack == 1) {
+ _PR_MD_CLEAN_THREAD(thread);
+ /*
+ * Because the no_sched field is set, this thread/stack will
+ * will not be re-used until the flag is cleared by the thread
+ * we will context switch to.
+ */
+ _PR_FreeStack(thread->stack);
+ } else {
+#ifdef WINNT
+ _PR_MD_CLEAN_THREAD(thread);
+#else
+ /*
+ * This assertion does not apply to NT. On NT, every fiber
+ * has its threadAllocatedOnStack equal to 0. Elsewhere,
+ * only the primordial thread has its threadAllocatedOnStack
+ * equal to 0.
+ */
+ PR_ASSERT(thread->flags & _PR_PRIMORDIAL);
+#endif
+ }
+}
+
+
+/*
+** Run a thread's start function. When the start function returns the
+** thread is done executing and no longer needs the CPU. If there are no
+** more user threads running then we can exit the program.
+*/
+void _PR_NativeRunThread(void *arg)
+{
+ PRThread *thread = (PRThread *)arg;
+
+ _PR_MD_SET_CURRENT_THREAD(thread);
+
+ _PR_MD_SET_CURRENT_CPU(NULL);
+
+ /* Set up the thread stack information */
+ _PR_InitializeNativeStack(thread->stack);
+
+ /* Set up the thread md information */
+ if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
+ /*
+ * thread failed to initialize itself, possibly due to
+ * failure to allocate per-thread resources
+ */
+ return;
+ }
+
+ while(1) {
+ thread->state = _PR_RUNNING;
+
+ /*
+ * Add to list of active threads
+ */
+ PR_Lock(_pr_activeLock);
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ());
+ _pr_global_threads++;
+ PR_Unlock(_pr_activeLock);
+
+ (*thread->startFunc)(thread->arg);
+
+ /*
+ * The following two assertions are meant for NT asynch io.
+ *
+ * The thread should have no asynch io in progress when it
+ * exits, otherwise the overlapped buffer, which is part of
+ * the thread structure, would become invalid.
+ */
+ PR_ASSERT(thread->io_pending == PR_FALSE);
+ /*
+ * This assertion enforces the programming guideline that
+ * if an io function times out or is interrupted, the thread
+ * should close the fd to force the asynch io to abort
+ * before it exits. Right now, closing the fd is the only
+ * way to clear the io_suspended flag.
+ */
+ PR_ASSERT(thread->io_suspended == PR_FALSE);
+
+ /*
+ * remove thread from list of active threads
+ */
+ PR_Lock(_pr_activeLock);
+ PR_REMOVE_LINK(&thread->active);
+ _pr_global_threads--;
+ PR_Unlock(_pr_activeLock);
+
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));
+
+ /* All done, time to go away */
+ _PR_CleanupThread(thread);
+
+ _PR_NotifyJoinWaiters(thread);
+
+ _PR_DecrActiveThreadCount(thread);
+
+ thread->state = _PR_DEAD_STATE;
+
+ if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==
+ PR_FAILURE)) {
+ /*
+ * thread not recycled
+ * platform-specific thread exit processing
+ * - for stuff like releasing native-thread resources, etc.
+ */
+ _PR_MD_EXIT_THREAD(thread);
+ /*
+ * Free memory allocated for the thread
+ */
+ _PR_NativeDestroyThread(thread);
+ /*
+ * thread gone, cannot de-reference thread now
+ */
+ return;
+ }
+
+ /* Now wait for someone to activate us again... */
+ _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT);
+ }
+}
+
+static void _PR_UserRunThread(void)
+{
+ PRThread *thread = _PR_MD_CURRENT_THREAD();
+ PRIntn is;
+
+ if (_MD_LAST_THREAD())
+ _MD_LAST_THREAD()->no_sched = 0;
+
+#ifdef HAVE_CUSTOM_USER_THREADS
+ if (thread->stack == NULL) {
+ thread->stack = PR_NEWZAP(PRThreadStack);
+ _PR_InitializeNativeStack(thread->stack);
+ }
+#endif /* HAVE_CUSTOM_USER_THREADS */
+
+ while(1) {
+ /* Run thread main */
+ if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_MD_SET_INTSOFF(0);
+
+ /*
+ * Add to list of active threads
+ */
+ if (!(thread->flags & _PR_IDLE_THREAD)) {
+ PR_Lock(_pr_activeLock);
+ PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ());
+ _pr_local_threads++;
+ PR_Unlock(_pr_activeLock);
+ }
+
+ (*thread->startFunc)(thread->arg);
+
+ /*
+ * The following two assertions are meant for NT asynch io.
+ *
+ * The thread should have no asynch io in progress when it
+ * exits, otherwise the overlapped buffer, which is part of
+ * the thread structure, would become invalid.
+ */
+ PR_ASSERT(thread->io_pending == PR_FALSE);
+ /*
+ * This assertion enforces the programming guideline that
+ * if an io function times out or is interrupted, the thread
+ * should close the fd to force the asynch io to abort
+ * before it exits. Right now, closing the fd is the only
+ * way to clear the io_suspended flag.
+ */
+ PR_ASSERT(thread->io_suspended == PR_FALSE);
+
+ PR_Lock(_pr_activeLock);
+ /*
+ * remove thread from list of active threads
+ */
+ if (!(thread->flags & _PR_IDLE_THREAD)) {
+ PR_REMOVE_LINK(&thread->active);
+ _pr_local_threads--;
+ }
+ PR_Unlock(_pr_activeLock);
+ PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting"));
+
+ /* All done, time to go away */
+ _PR_CleanupThread(thread);
+
+ _PR_INTSOFF(is);
+
+ _PR_NotifyJoinWaiters(thread);
+
+ _PR_DecrActiveThreadCount(thread);
+
+ thread->state = _PR_DEAD_STATE;
+
+ if (!_pr_recycleThreads || (_PR_RecycleThread(thread) ==
+ PR_FAILURE)) {
+ /*
+ ** Destroy the thread resources
+ */
+ _PR_UserDestroyThread(thread);
+ }
+
+ /*
+ ** Find another user thread to run. This cpu has finished the
+ ** previous threads main and is now ready to run another thread.
+ */
+ {
+ PRInt32 is;
+ _PR_INTSOFF(is);
+ _PR_MD_SWITCH_CONTEXT(thread);
+ }
+
+ /* Will land here when we get scheduled again if we are recycling... */
+ }
+}
+
+void _PR_SetThreadPriority(PRThread *thread, PRThreadPriority newPri)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntn is;
+
+ if ( _PR_IS_NATIVE_THREAD(thread) ) {
+ _PR_MD_SET_PRIORITY(&(thread->md), newPri);
+ return;
+ }
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ _PR_THREAD_LOCK(thread);
+ if (newPri != thread->priority) {
+ _PRCPU *cpu = thread->cpu;
+
+ switch (thread->state) {
+ case _PR_RUNNING:
+ /* Change my priority */
+
+ _PR_RUNQ_LOCK(cpu);
+ thread->priority = newPri;
+ if (_PR_RUNQREADYMASK(cpu) >> (newPri + 1)) {
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_SET_RESCHED_FLAG();
+ }
+ _PR_RUNQ_UNLOCK(cpu);
+ break;
+
+ case _PR_RUNNABLE:
+
+ _PR_RUNQ_LOCK(cpu);
+ /* Move to different runQ */
+ _PR_DEL_RUNQ(thread);
+ thread->priority = newPri;
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+ _PR_ADD_RUNQ(thread, cpu, newPri);
+ _PR_RUNQ_UNLOCK(cpu);
+
+ if (newPri > me->priority) {
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_SET_RESCHED_FLAG();
+ }
+
+ break;
+
+ case _PR_LOCK_WAIT:
+ case _PR_COND_WAIT:
+ case _PR_IO_WAIT:
+ case _PR_SUSPENDED:
+
+ thread->priority = newPri;
+ break;
+ }
+ }
+ _PR_THREAD_UNLOCK(thread);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+}
+
+/*
+** Suspend the named thread and copy its gc registers into regBuf
+*/
+static void _PR_Suspend(PRThread *thread)
+{
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ PR_ASSERT(thread != me);
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread) || (!thread->cpu));
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ _PR_THREAD_LOCK(thread);
+ switch (thread->state) {
+ case _PR_RUNNABLE:
+ if (!_PR_IS_NATIVE_THREAD(thread)) {
+ _PR_RUNQ_LOCK(thread->cpu);
+ _PR_DEL_RUNQ(thread);
+ _PR_RUNQ_UNLOCK(thread->cpu);
+
+ _PR_MISCQ_LOCK(thread->cpu);
+ _PR_ADD_SUSPENDQ(thread, thread->cpu);
+ _PR_MISCQ_UNLOCK(thread->cpu);
+ } else {
+ /*
+ * Only LOCAL threads are suspended by _PR_Suspend
+ */
+ PR_ASSERT(0);
+ }
+ thread->state = _PR_SUSPENDED;
+ break;
+
+ case _PR_RUNNING:
+ /*
+ * The thread being suspended should be a LOCAL thread with
+ * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
+ */
+ PR_ASSERT(0);
+ break;
+
+ case _PR_LOCK_WAIT:
+ case _PR_IO_WAIT:
+ case _PR_COND_WAIT:
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ _PR_MD_SUSPEND_THREAD(thread);
+ }
+ thread->flags |= _PR_SUSPENDING;
+ break;
+
+ default:
+ PR_Abort();
+ }
+ _PR_THREAD_UNLOCK(thread);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+}
+
+static void _PR_Resume(PRThread *thread)
+{
+ PRThreadPriority pri;
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ _PR_THREAD_LOCK(thread);
+ switch (thread->state) {
+ case _PR_SUSPENDED:
+ thread->state = _PR_RUNNABLE;
+ thread->flags &= ~_PR_SUSPENDING;
+ if (!_PR_IS_NATIVE_THREAD(thread)) {
+ _PR_MISCQ_LOCK(thread->cpu);
+ _PR_DEL_SUSPENDQ(thread);
+ _PR_MISCQ_UNLOCK(thread->cpu);
+
+ pri = thread->priority;
+
+ _PR_RUNQ_LOCK(thread->cpu);
+ _PR_ADD_RUNQ(thread, thread->cpu, pri);
+ _PR_RUNQ_UNLOCK(thread->cpu);
+
+ if (pri > _PR_MD_CURRENT_THREAD()->priority) {
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_SET_RESCHED_FLAG();
+ }
+ } else {
+ PR_ASSERT(0);
+ }
+ break;
+
+ case _PR_IO_WAIT:
+ case _PR_COND_WAIT:
+ thread->flags &= ~_PR_SUSPENDING;
+/* PR_ASSERT(thread->wait.monitor->stickyCount == 0); */
+ break;
+
+ case _PR_LOCK_WAIT:
+ {
+ PRLock *wLock = thread->wait.lock;
+
+ thread->flags &= ~_PR_SUSPENDING;
+
+ _PR_LOCK_LOCK(wLock);
+ if (thread->wait.lock->owner == 0) {
+ _PR_UnblockLockWaiter(thread->wait.lock);
+ }
+ _PR_LOCK_UNLOCK(wLock);
+ break;
+ }
+ case _PR_RUNNABLE:
+ break;
+ case _PR_RUNNING:
+ /*
+ * The thread being suspended should be a LOCAL thread with
+ * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state
+ */
+ PR_ASSERT(0);
+ break;
+
+ default:
+ /*
+ * thread should have been in one of the above-listed blocked states
+ * (_PR_JOIN_WAIT, _PR_IO_WAIT, _PR_UNBORN, _PR_DEAD_STATE)
+ */
+ PR_Abort();
+ }
+ _PR_THREAD_UNLOCK(thread);
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+
+}
+
+#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
+static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus)
+{
+ PRThread *thread;
+ PRIntn pri;
+ PRUint32 r;
+ PRCList *qp;
+ PRIntn priMin, priMax;
+
+ _PR_RUNQ_LOCK(cpu);
+ r = _PR_RUNQREADYMASK(cpu);
+ if (r==0) {
+ priMin = priMax = PR_PRIORITY_FIRST;
+ } else if (r == (1<<PR_PRIORITY_NORMAL) ) {
+ priMin = priMax = PR_PRIORITY_NORMAL;
+ } else {
+ priMin = PR_PRIORITY_FIRST;
+ priMax = PR_PRIORITY_LAST;
+ }
+ thread = NULL;
+ for (pri = priMax; pri >= priMin ; pri-- ) {
+ if (r & (1 << pri)) {
+ for (qp = _PR_RUNQ(cpu)[pri].next;
+ qp != &_PR_RUNQ(cpu)[pri];
+ qp = qp->next) {
+ thread = _PR_THREAD_PTR(qp);
+ /*
+ * skip non-schedulable threads
+ */
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+ if (thread->no_sched) {
+ thread = NULL;
+ /*
+ * Need to wakeup cpus to avoid missing a
+ * runnable thread
+ * Waking up all CPU's need happen only once.
+ */
+
+ *wakeup_cpus = PR_TRUE;
+ continue;
+ } else if (thread->flags & _PR_BOUND_THREAD) {
+ /*
+ * Thread bound to cpu 0
+ */
+
+ thread = NULL;
+#ifdef IRIX
+ _PR_MD_WAKEUP_PRIMORDIAL_CPU();
+#endif
+ continue;
+ } else if (thread->io_pending == PR_TRUE) {
+ /*
+ * A thread that is blocked for I/O needs to run
+ * on the same cpu on which it was blocked. This is because
+ * the cpu's ioq is accessed without lock protection and scheduling
+ * the thread on a different cpu would preclude this optimization.
+ */
+ thread = NULL;
+ continue;
+ } else {
+ /* Pull thread off of its run queue */
+ _PR_DEL_RUNQ(thread);
+ _PR_RUNQ_UNLOCK(cpu);
+ return(thread);
+ }
+ }
+ }
+ thread = NULL;
+ }
+ _PR_RUNQ_UNLOCK(cpu);
+ return(thread);
+}
+#endif /* !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) */
+
+/*
+** Schedule this native thread by finding the highest priority nspr
+** thread that is ready to run.
+**
+** Note- everyone really needs to call _PR_MD_SWITCH_CONTEXT (which calls
+** PR_Schedule() rather than calling PR_Schedule. Otherwise if there
+** is initialization required for switching from SWITCH_CONTEXT,
+** it will not get done!
+*/
+void _PR_Schedule(void)
+{
+ PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+ PRIntn pri;
+ PRUint32 r;
+ PRCList *qp;
+ PRIntn priMin, priMax;
+#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
+ PRBool wakeup_cpus;
+#endif
+
+ /* Interrupts must be disabled */
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0);
+
+ /* Since we are rescheduling, we no longer want to */
+ _PR_CLEAR_RESCHED_FLAG();
+
+ /*
+ ** Find highest priority thread to run. Bigger priority numbers are
+ ** higher priority threads
+ */
+ _PR_RUNQ_LOCK(cpu);
+ /*
+ * if we are in SuspendAll mode, can schedule only the thread
+ * that called PR_SuspendAll
+ *
+ * The thread may be ready to run now, after completing an I/O
+ * operation, for example
+ */
+ if ((thread = suspendAllThread) != 0) {
+ if ((!(thread->no_sched)) && (thread->state == _PR_RUNNABLE)) {
+ /* Pull thread off of its run queue */
+ _PR_DEL_RUNQ(thread);
+ _PR_RUNQ_UNLOCK(cpu);
+ goto found_thread;
+ } else {
+ thread = NULL;
+ _PR_RUNQ_UNLOCK(cpu);
+ goto idle_thread;
+ }
+ }
+ r = _PR_RUNQREADYMASK(cpu);
+ if (r==0) {
+ priMin = priMax = PR_PRIORITY_FIRST;
+ } else if (r == (1<<PR_PRIORITY_NORMAL) ) {
+ priMin = priMax = PR_PRIORITY_NORMAL;
+ } else {
+ priMin = PR_PRIORITY_FIRST;
+ priMax = PR_PRIORITY_LAST;
+ }
+ thread = NULL;
+ for (pri = priMax; pri >= priMin ; pri-- ) {
+ if (r & (1 << pri)) {
+ for (qp = _PR_RUNQ(cpu)[pri].next;
+ qp != &_PR_RUNQ(cpu)[pri];
+ qp = qp->next) {
+ thread = _PR_THREAD_PTR(qp);
+ /*
+ * skip non-schedulable threads
+ */
+#if !defined(XP_MAC)
+ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD));
+#endif
+ if ((thread->no_sched) && (me != thread)){
+ thread = NULL;
+ continue;
+ } else {
+ /* Pull thread off of its run queue */
+ _PR_DEL_RUNQ(thread);
+ _PR_RUNQ_UNLOCK(cpu);
+ goto found_thread;
+ }
+ }
+ }
+ thread = NULL;
+ }
+ _PR_RUNQ_UNLOCK(cpu);
+
+#if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX)
+
+ wakeup_cpus = PR_FALSE;
+ _PR_CPU_LIST_LOCK();
+ for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) {
+ if (cpu != _PR_CPU_PTR(qp)) {
+ if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus))
+ != NULL) {
+ thread->cpu = cpu;
+ _PR_CPU_LIST_UNLOCK();
+ if (wakeup_cpus == PR_TRUE)
+ _PR_MD_WAKEUP_CPUS();
+ goto found_thread;
+ }
+ }
+ }
+ _PR_CPU_LIST_UNLOCK();
+ if (wakeup_cpus == PR_TRUE)
+ _PR_MD_WAKEUP_CPUS();
+
+#endif /* _PR_LOCAL_THREADS_ONLY */
+
+idle_thread:
+ /*
+ ** There are no threads to run. Switch to the idle thread
+ */
+ PR_LOG(_pr_sched_lm, PR_LOG_MAX, ("pausing"));
+ thread = _PR_MD_CURRENT_CPU()->idle_thread;
+
+found_thread:
+ PR_ASSERT((me == thread) || ((thread->state == _PR_RUNNABLE) &&
+ (!(thread->no_sched))));
+
+ /* Resume the thread */
+ PR_LOG(_pr_sched_lm, PR_LOG_MAX,
+ ("switching to %d[%p]", thread->id, thread));
+ PR_ASSERT(thread->state != _PR_RUNNING);
+ thread->state = _PR_RUNNING;
+
+ /* If we are on the runq, it just means that we went to sleep on some
+ * resource, and by the time we got here another real native thread had
+ * already given us the resource and put us back on the runqueue
+ */
+ PR_ASSERT(thread->cpu == _PR_MD_CURRENT_CPU());
+ if (thread != me)
+ _PR_MD_RESTORE_CONTEXT(thread);
+#if 0
+ /* XXXMB; with setjmp/longjmp it is impossible to land here, but
+ * it is not with fibers... Is this a bad thing? I believe it is
+ * still safe.
+ */
+ PR_NOT_REACHED("impossible return from schedule");
+#endif
+}
+
+/*
+** Attaches a thread.
+** Does not set the _PR_MD_CURRENT_THREAD.
+** Does not specify the scope of the thread.
+*/
+static PRThread *
+_PR_AttachThread(PRThreadType type, PRThreadPriority priority,
+ PRThreadStack *stack)
+{
+#if defined(XP_MAC)
+#pragma unused (type)
+#endif
+
+ PRThread *thread;
+ char *mem;
+
+ if (priority > PR_PRIORITY_LAST) {
+ priority = PR_PRIORITY_LAST;
+ } else if (priority < PR_PRIORITY_FIRST) {
+ priority = PR_PRIORITY_FIRST;
+ }
+
+ mem = (char*) PR_CALLOC(sizeof(PRThread));
+ if (mem) {
+ thread = (PRThread*) mem;
+ thread->priority = priority;
+ thread->stack = stack;
+ thread->state = _PR_RUNNING;
+ PR_INIT_CLIST(&thread->lockList);
+ if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
+ PR_DELETE(thread);
+ return 0;
+ }
+
+ return thread;
+ }
+ return 0;
+}
+
+
+
+PR_IMPLEMENT(PRThread*)
+_PR_NativeCreateThread(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize,
+ PRUint32 flags)
+{
+#if defined(XP_MAC)
+#pragma unused (scope)
+#endif
+
+ PRThread *thread;
+
+ thread = _PR_AttachThread(type, priority, NULL);
+
+ if (thread) {
+ PR_Lock(_pr_activeLock);
+ thread->flags = (flags | _PR_GLOBAL_SCOPE);
+ thread->id = ++_pr_utid;
+ if (type == PR_SYSTEM_THREAD) {
+ thread->flags |= _PR_SYSTEM;
+ _pr_systemActive++;
+ } else {
+ _pr_userActive++;
+ }
+ PR_Unlock(_pr_activeLock);
+
+ thread->stack = PR_NEWZAP(PRThreadStack);
+ if (!thread->stack) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ goto done;
+ }
+ thread->stack->stackSize = stackSize?stackSize:_MD_DEFAULT_STACK_SIZE;
+ thread->stack->thr = thread;
+ thread->startFunc = start;
+ thread->arg = arg;
+
+ /*
+ Set thread flags related to scope and joinable state. If joinable
+ thread, allocate a "termination" conidition variable.
+ */
+ if (state == PR_JOINABLE_THREAD) {
+ thread->term = PR_NewCondVar(_pr_terminationCVLock);
+ if (thread->term == NULL) {
+ PR_DELETE(thread->stack);
+ goto done;
+ }
+ }
+
+ thread->state = _PR_RUNNING;
+ if (_PR_MD_CREATE_THREAD(thread, _PR_NativeRunThread, priority,
+ scope,state,stackSize) == PR_SUCCESS) {
+ return thread;
+ }
+ if (thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = NULL;
+ }
+ PR_DELETE(thread->stack);
+ }
+
+done:
+ if (thread) {
+ _PR_DecrActiveThreadCount(thread);
+ _PR_DestroyThread(thread);
+ }
+ return NULL;
+}
+
+/************************************************************************/
+
+PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize,
+ PRUint32 flags)
+{
+ PRThread *me;
+ PRThread *thread = NULL;
+ PRThreadStack *stack;
+ char *top;
+ PRIntn is;
+ PRIntn native = 0;
+ PRIntn useRecycled = 0;
+ PRBool status;
+
+ /*
+ First, pin down the priority. Not all compilers catch passing out of
+ range enum here. If we let bad values thru, priority queues won't work.
+ */
+ if (priority > PR_PRIORITY_LAST) {
+ priority = PR_PRIORITY_LAST;
+ } else if (priority < PR_PRIORITY_FIRST) {
+ priority = PR_PRIORITY_FIRST;
+ }
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (! (flags & _PR_IDLE_THREAD))
+ me = _PR_MD_CURRENT_THREAD();
+
+#if defined(_PR_GLOBAL_THREADS_ONLY)
+ /*
+ * can create global threads only
+ */
+ if (scope == PR_LOCAL_THREAD)
+ scope = PR_GLOBAL_THREAD;
+#endif
+
+ if (_native_threads_only)
+ scope = PR_GLOBAL_THREAD;
+
+ native = (((scope == PR_GLOBAL_THREAD)|| (scope == PR_GLOBAL_BOUND_THREAD))
+ && _PR_IS_NATIVE_THREAD_SUPPORTED());
+
+ _PR_ADJUST_STACKSIZE(stackSize);
+
+ if (native) {
+ /*
+ * clear the IDLE_THREAD flag which applies to LOCAL
+ * threads only
+ */
+ flags &= ~_PR_IDLE_THREAD;
+ flags |= _PR_GLOBAL_SCOPE;
+ if (_PR_NUM_DEADNATIVE > 0) {
+ _PR_DEADQ_LOCK;
+
+ if (_PR_NUM_DEADNATIVE == 0) { /* Thread safe check */
+ _PR_DEADQ_UNLOCK;
+ } else {
+ thread = _PR_THREAD_PTR(_PR_DEADNATIVEQ.next);
+ PR_REMOVE_LINK(&thread->links);
+ _PR_DEC_DEADNATIVE;
+ _PR_DEADQ_UNLOCK;
+
+ _PR_InitializeRecycledThread(thread);
+ thread->startFunc = start;
+ thread->arg = arg;
+ thread->flags = (flags | _PR_GLOBAL_SCOPE);
+ if (type == PR_SYSTEM_THREAD)
+ {
+ thread->flags |= _PR_SYSTEM;
+ PR_AtomicIncrement(&_pr_systemActive);
+ }
+ else PR_AtomicIncrement(&_pr_userActive);
+
+ if (state == PR_JOINABLE_THREAD) {
+ if (!thread->term)
+ thread->term = PR_NewCondVar(_pr_terminationCVLock);
+ }
+ else {
+ if(thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ }
+
+ thread->priority = priority;
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ /* XXX what about stackSize? */
+ thread->state = _PR_RUNNING;
+ _PR_MD_WAKEUP_WAITER(thread);
+ return thread;
+ }
+ }
+ thread = _PR_NativeCreateThread(type, start, arg, priority,
+ scope, state, stackSize, flags);
+ } else {
+ if (_PR_NUM_DEADUSER > 0) {
+ _PR_DEADQ_LOCK;
+
+ if (_PR_NUM_DEADUSER == 0) { /* thread safe check */
+ _PR_DEADQ_UNLOCK;
+ } else {
+ PRCList *ptr;
+
+ /* Go down list checking for a recycled thread with a
+ * large enough stack. XXXMB - this has a bad degenerate case.
+ */
+ ptr = _PR_DEADUSERQ.next;
+ while( ptr != &_PR_DEADUSERQ ) {
+ thread = _PR_THREAD_PTR(ptr);
+ if ((thread->stack->stackSize >= stackSize) &&
+ (!thread->no_sched)) {
+ PR_REMOVE_LINK(&thread->links);
+ _PR_DEC_DEADUSER;
+ break;
+ } else {
+ ptr = ptr->next;
+ thread = NULL;
+ }
+ }
+
+ _PR_DEADQ_UNLOCK;
+
+ if (thread) {
+ _PR_InitializeRecycledThread(thread);
+ thread->startFunc = start;
+ thread->arg = arg;
+ thread->priority = priority;
+ if (state == PR_JOINABLE_THREAD) {
+ if (!thread->term)
+ thread->term = PR_NewCondVar(_pr_terminationCVLock);
+ } else {
+ if(thread->term) {
+ PR_DestroyCondVar(thread->term);
+ thread->term = 0;
+ }
+ }
+ useRecycled++;
+ }
+ }
+ }
+ if (thread == NULL) {
+#ifndef HAVE_CUSTOM_USER_THREADS
+ stack = _PR_NewStack(stackSize);
+ if (!stack) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+
+ /* Allocate thread object and per-thread data off the top of the stack*/
+ top = stack->stackTop;
+#ifdef HAVE_STACK_GROWING_UP
+ thread = (PRThread*) top;
+ top = top + sizeof(PRThread);
+ /*
+ * Make stack 64-byte aligned
+ */
+ if ((PRUptrdiff)top & 0x3f) {
+ top = (char*)(((PRUptrdiff)top + 0x40) & ~0x3f);
+ }
+#else
+ top = top - sizeof(PRThread);
+ thread = (PRThread*) top;
+ /*
+ * Make stack 64-byte aligned
+ */
+ if ((PRUptrdiff)top & 0x3f) {
+ top = (char*)((PRUptrdiff)top & ~0x3f);
+ }
+#endif
+#if defined(GC_LEAK_DETECTOR)
+ /*
+ * sorry, it is not safe to allocate the thread on the stack,
+ * because we assign to this object before the GC can learn
+ * about this thread. we'll just leak thread objects instead.
+ */
+ thread = PR_NEW(PRThread);
+#endif
+ stack->thr = thread;
+ memset(thread, 0, sizeof(PRThread));
+ thread->threadAllocatedOnStack = 1;
+#else
+ thread = _PR_MD_CREATE_USER_THREAD(stackSize, start, arg);
+ if (!thread) {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ thread->threadAllocatedOnStack = 0;
+ stack = NULL;
+ top = NULL;
+#endif
+
+ /* Initialize thread */
+ thread->tpdLength = 0;
+ thread->privateData = NULL;
+ thread->stack = stack;
+ thread->priority = priority;
+ thread->startFunc = start;
+ thread->arg = arg;
+ PR_INIT_CLIST(&thread->lockList);
+
+ if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) {
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread);
+ }
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return NULL;
+ }
+
+ if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) {
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread->privateData);
+ PR_DELETE(thread);
+ }
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+ return NULL;
+ }
+
+ _PR_MD_INIT_CONTEXT(thread, top, _PR_UserRunThread, &status);
+
+ if (status == PR_FALSE) {
+ _PR_MD_FREE_LOCK(&thread->threadLock);
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread->privateData);
+ PR_DELETE(thread);
+ }
+ return NULL;
+ }
+
+ /*
+ Set thread flags related to scope and joinable state. If joinable
+ thread, allocate a "termination" condition variable.
+ */
+ if (state == PR_JOINABLE_THREAD) {
+ thread->term = PR_NewCondVar(_pr_terminationCVLock);
+ if (thread->term == NULL) {
+ _PR_MD_FREE_LOCK(&thread->threadLock);
+ if (thread->threadAllocatedOnStack == 1)
+ _PR_FreeStack(thread->stack);
+ else {
+ PR_DELETE(thread->privateData);
+ PR_DELETE(thread);
+ }
+ return NULL;
+ }
+ }
+
+ }
+
+ /* Update thread type counter */
+ PR_Lock(_pr_activeLock);
+ thread->flags = flags;
+ thread->id = ++_pr_utid;
+ if (type == PR_SYSTEM_THREAD) {
+ thread->flags |= _PR_SYSTEM;
+ _pr_systemActive++;
+ } else {
+ _pr_userActive++;
+ }
+
+ /* Make thread runnable */
+ thread->state = _PR_RUNNABLE;
+ /*
+ * Add to list of active threads
+ */
+ PR_Unlock(_pr_activeLock);
+
+ if ((! (thread->flags & _PR_IDLE_THREAD)) && _PR_IS_NATIVE_THREAD(me) )
+ thread->cpu = _PR_GetPrimordialCPU();
+ else
+ thread->cpu = _PR_MD_CURRENT_CPU();
+
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));
+
+ if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me)) {
+ _PR_INTSOFF(is);
+ _PR_RUNQ_LOCK(thread->cpu);
+ _PR_ADD_RUNQ(thread, thread->cpu, priority);
+ _PR_RUNQ_UNLOCK(thread->cpu);
+ }
+
+ if (thread->flags & _PR_IDLE_THREAD) {
+ /*
+ ** If the creating thread is a kernel thread, we need to
+ ** awaken the user thread idle thread somehow; potentially
+ ** it could be sleeping in its idle loop, and we need to poke
+ ** it. To do so, wake the idle thread...
+ */
+ _PR_MD_WAKEUP_WAITER(NULL);
+ } else if (_PR_IS_NATIVE_THREAD(me)) {
+ _PR_MD_WAKEUP_WAITER(thread);
+ }
+ if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me) )
+ _PR_INTSON(is);
+ }
+
+ return thread;
+}
+
+PR_IMPLEMENT(PRThread*) PR_CreateThread(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ return _PR_CreateThread(type, start, arg, priority, scope, state,
+ stackSize, 0);
+}
+
+/*
+** Associate a thread object with an existing native thread.
+** "type" is the type of thread object to attach
+** "priority" is the priority to assign to the thread
+** "stack" defines the shape of the threads stack
+**
+** This can return NULL if some kind of error occurs, or if memory is
+** tight.
+**
+** This call is not normally needed unless you create your own native
+** thread. PR_Init does this automatically for the primordial thread.
+*/
+PRThread* _PRI_AttachThread(PRThreadType type,
+ PRThreadPriority priority, PRThreadStack *stack, PRUint32 flags)
+{
+ PRThread *thread;
+
+ if ((thread = _PR_MD_GET_ATTACHED_THREAD()) != NULL) {
+ return thread;
+ }
+ _PR_MD_SET_CURRENT_THREAD(NULL);
+
+ /* Clear out any state if this thread was attached before */
+ _PR_MD_SET_CURRENT_CPU(NULL);
+
+ thread = _PR_AttachThread(type, priority, stack);
+ if (thread) {
+ PRIntn is;
+
+ _PR_MD_SET_CURRENT_THREAD(thread);
+
+ thread->flags = flags | _PR_GLOBAL_SCOPE | _PR_ATTACHED;
+
+ if (!stack) {
+ thread->stack = PR_NEWZAP(PRThreadStack);
+ if (!thread->stack) {
+ _PR_DestroyThread(thread);
+ return NULL;
+ }
+ thread->stack->stackSize = _MD_DEFAULT_STACK_SIZE;
+ }
+ PR_INIT_CLIST(&thread->links);
+
+ if (_PR_MD_INIT_ATTACHED_THREAD(thread) == PR_FAILURE) {
+ PR_DELETE(thread->stack);
+ _PR_DestroyThread(thread);
+ return NULL;
+ }
+
+ _PR_MD_SET_CURRENT_CPU(NULL);
+
+ if (_PR_MD_CURRENT_CPU()) {
+ _PR_INTSOFF(is);
+ PR_Lock(_pr_activeLock);
+ }
+ if (type == PR_SYSTEM_THREAD) {
+ thread->flags |= _PR_SYSTEM;
+ _pr_systemActive++;
+ } else {
+ _pr_userActive++;
+ }
+ if (_PR_MD_CURRENT_CPU()) {
+ PR_Unlock(_pr_activeLock);
+ _PR_INTSON(is);
+ }
+ }
+ return thread;
+}
+
+PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type,
+ PRThreadPriority priority, PRThreadStack *stack)
+{
+#ifdef XP_MAC
+#pragma unused( type, priority, stack )
+#endif
+ return PR_GetCurrentThread();
+}
+
+PR_IMPLEMENT(void) PR_DetachThread(void)
+{
+ /*
+ * On IRIX, Solaris, and Windows, foreign threads are detached when
+ * they terminate.
+ */
+#if !defined(IRIX) && !defined(WIN32) \
+ && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY))
+ PRThread *me;
+ if (_pr_initialized) {
+ me = _PR_MD_GET_ATTACHED_THREAD();
+ if ((me != NULL) && (me->flags & _PR_ATTACHED))
+ _PRI_DetachThread();
+ }
+#endif
+}
+
+void _PRI_DetachThread(void)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (me->flags & _PR_PRIMORDIAL) {
+ /*
+ * ignore, if primordial thread
+ */
+ return;
+ }
+ PR_ASSERT(me->flags & _PR_ATTACHED);
+ PR_ASSERT(_PR_IS_NATIVE_THREAD(me));
+ _PR_CleanupThread(me);
+ PR_DELETE(me->privateData);
+
+ _PR_DecrActiveThreadCount(me);
+
+ _PR_MD_CLEAN_THREAD(me);
+ _PR_MD_SET_CURRENT_THREAD(NULL);
+ if (!me->threadAllocatedOnStack)
+ PR_DELETE(me->stack);
+ _PR_MD_FREE_LOCK(&me->threadLock);
+ PR_DELETE(me);
+}
+
+/*
+** Wait for thread termination:
+** "thread" is the target thread
+**
+** This can return PR_FAILURE if no joinable thread could be found
+** corresponding to the specified target thread.
+**
+** The calling thread is suspended until the target thread completes.
+** Several threads cannot wait for the same thread to complete; one thread
+** will complete successfully and others will terminate with an error PR_FAILURE.
+** The calling thread will not be blocked if the target thread has already
+** terminated.
+*/
+PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread)
+{
+ PRIntn is;
+ PRCondVar *term;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ term = thread->term;
+ /* can't join a non-joinable thread */
+ if (term == NULL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ goto ErrorExit;
+ }
+
+ /* multiple threads can't wait on the same joinable thread */
+ if (term->condQ.next != &term->condQ) {
+ goto ErrorExit;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+
+ /* wait for the target thread's termination cv invariant */
+ PR_Lock (_pr_terminationCVLock);
+ while (thread->state != _PR_JOIN_WAIT) {
+ (void) PR_WaitCondVar(term, PR_INTERVAL_NO_TIMEOUT);
+ }
+ (void) PR_Unlock (_pr_terminationCVLock);
+
+ /*
+ Remove target thread from global waiting to join Q; make it runnable
+ again and put it back on its run Q. When it gets scheduled later in
+ _PR_RunThread code, it will clean up its stack.
+ */
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+ thread->state = _PR_RUNNABLE;
+ if ( !_PR_IS_NATIVE_THREAD(thread) ) {
+ _PR_THREAD_LOCK(thread);
+
+ _PR_MISCQ_LOCK(thread->cpu);
+ _PR_DEL_JOINQ(thread);
+ _PR_MISCQ_UNLOCK(thread->cpu);
+
+ _PR_AddThreadToRunQ(me, thread);
+ _PR_THREAD_UNLOCK(thread);
+ }
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+
+ _PR_MD_WAKEUP_WAITER(thread);
+
+ return PR_SUCCESS;
+
+ErrorExit:
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thread,
+ PRThreadPriority newPri)
+{
+
+ /*
+ First, pin down the priority. Not all compilers catch passing out of
+ range enum here. If we let bad values thru, priority queues won't work.
+ */
+ if ((PRIntn)newPri > (PRIntn)PR_PRIORITY_LAST) {
+ newPri = PR_PRIORITY_LAST;
+ } else if ((PRIntn)newPri < (PRIntn)PR_PRIORITY_FIRST) {
+ newPri = PR_PRIORITY_FIRST;
+ }
+
+ if ( _PR_IS_NATIVE_THREAD(thread) ) {
+ thread->priority = newPri;
+ _PR_MD_SET_PRIORITY(&(thread->md), newPri);
+ } else _PR_SetThreadPriority(thread, newPri);
+}
+
+
+/*
+** This routine prevents all other threads from running. This call is needed by
+** the garbage collector.
+*/
+PR_IMPLEMENT(void) PR_SuspendAll(void)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRCList *qp;
+
+ /*
+ * Stop all user and native threads which are marked GC able.
+ */
+ PR_Lock(_pr_activeLock);
+ suspendAllOn = PR_TRUE;
+ suspendAllThread = _PR_MD_CURRENT_THREAD();
+ _PR_MD_BEGIN_SUSPEND_ALL();
+ for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
+ qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp))) {
+ _PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp));
+ PR_ASSERT((_PR_ACTIVE_THREAD_PTR(qp))->state != _PR_RUNNING);
+ }
+ }
+ for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
+ qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp)))
+ /* PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp)); */
+ _PR_MD_SUSPEND_THREAD(_PR_ACTIVE_THREAD_PTR(qp));
+ }
+ _PR_MD_END_SUSPEND_ALL();
+}
+
+/*
+** This routine unblocks all other threads that were suspended from running by
+** PR_SuspendAll(). This call is needed by the garbage collector.
+*/
+PR_IMPLEMENT(void) PR_ResumeAll(void)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRCList *qp;
+
+ /*
+ * Resume all user and native threads which are marked GC able.
+ */
+ _PR_MD_BEGIN_RESUME_ALL();
+ for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
+ qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp)))
+ _PR_Resume(_PR_ACTIVE_THREAD_PTR(qp));
+ }
+ for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
+ qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) {
+ if ((me != _PR_ACTIVE_THREAD_PTR(qp)) &&
+ _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp)))
+ _PR_MD_RESUME_THREAD(_PR_ACTIVE_THREAD_PTR(qp));
+ }
+ _PR_MD_END_RESUME_ALL();
+ suspendAllThread = NULL;
+ suspendAllOn = PR_FALSE;
+ PR_Unlock(_pr_activeLock);
+}
+
+PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
+{
+ PRCList *qp, *qp_next;
+ PRIntn i = 0;
+ PRStatus rv = PR_SUCCESS;
+ PRThread* t;
+
+ /*
+ ** Currently Enumerate threads happen only with suspension and
+ ** pr_activeLock held
+ */
+ PR_ASSERT(suspendAllOn);
+
+ /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking
+ * qp->next after applying the function "func". In particular, "func"
+ * might remove the thread from the queue and put it into another one in
+ * which case qp->next no longer points to the next entry in the original
+ * queue.
+ *
+ * To get around this problem, we save qp->next in qp_next before applying
+ * "func" and use that saved value as the next value after applying "func".
+ */
+
+ /*
+ * Traverse the list of local and global threads
+ */
+ for (qp = _PR_ACTIVE_LOCAL_THREADQ().next;
+ qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp_next)
+ {
+ qp_next = qp->next;
+ t = _PR_ACTIVE_THREAD_PTR(qp);
+ if (_PR_IS_GCABLE_THREAD(t))
+ {
+ rv = (*func)(t, i, arg);
+ if (rv != PR_SUCCESS)
+ return rv;
+ i++;
+ }
+ }
+ for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next;
+ qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp_next)
+ {
+ qp_next = qp->next;
+ t = _PR_ACTIVE_THREAD_PTR(qp);
+ if (_PR_IS_GCABLE_THREAD(t))
+ {
+ rv = (*func)(t, i, arg);
+ if (rv != PR_SUCCESS)
+ return rv;
+ i++;
+ }
+ }
+ return rv;
+}
+
+/* FUNCTION: _PR_AddSleepQ
+** DESCRIPTION:
+** Adds a thread to the sleep/pauseQ.
+** RESTRICTIONS:
+** Caller must have the RUNQ lock.
+** Caller must be a user level thread
+*/
+PR_IMPLEMENT(void)
+_PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout)
+{
+ _PRCPU *cpu = thread->cpu;
+
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ /* append the thread to the global pause Q */
+ PR_APPEND_LINK(&thread->links, &_PR_PAUSEQ(thread->cpu));
+ thread->flags |= _PR_ON_PAUSEQ;
+ } else {
+ PRIntervalTime sleep;
+ PRCList *q;
+ PRThread *t;
+
+ /* sort onto global sleepQ */
+ sleep = timeout;
+
+ /* Check if we are longest timeout */
+ if (timeout >= _PR_SLEEPQMAX(cpu)) {
+ PR_INSERT_BEFORE(&thread->links, &_PR_SLEEPQ(cpu));
+ thread->sleep = timeout - _PR_SLEEPQMAX(cpu);
+ _PR_SLEEPQMAX(cpu) = timeout;
+ } else {
+ /* Sort thread into global sleepQ at appropriate point */
+ q = _PR_SLEEPQ(cpu).next;
+
+ /* Now scan the list for where to insert this entry */
+ while (q != &_PR_SLEEPQ(cpu)) {
+ t = _PR_THREAD_PTR(q);
+ if (sleep < t->sleep) {
+ /* Found sleeper to insert in front of */
+ break;
+ }
+ sleep -= t->sleep;
+ q = q->next;
+ }
+ thread->sleep = sleep;
+ PR_INSERT_BEFORE(&thread->links, q);
+
+ /*
+ ** Subtract our sleep time from the sleeper that follows us (there
+ ** must be one) so that they remain relative to us.
+ */
+ PR_ASSERT (thread->links.next != &_PR_SLEEPQ(cpu));
+
+ t = _PR_THREAD_PTR(thread->links.next);
+ PR_ASSERT(_PR_THREAD_PTR(t->links.prev) == thread);
+ t->sleep -= sleep;
+ }
+
+ thread->flags |= _PR_ON_SLEEPQ;
+ }
+}
+
+/* FUNCTION: _PR_DelSleepQ
+** DESCRIPTION:
+** Removes a thread from the sleep/pauseQ.
+** INPUTS:
+** If propogate_time is true, then the thread following the deleted
+** thread will be get the time from the deleted thread. This is used
+** when deleting a sleeper that has not timed out.
+** RESTRICTIONS:
+** Caller must have the RUNQ lock.
+** Caller must be a user level thread
+*/
+PR_IMPLEMENT(void)
+_PR_DelSleepQ(PRThread *thread, PRBool propogate_time)
+{
+ _PRCPU *cpu = thread->cpu;
+
+ /* Remove from pauseQ/sleepQ */
+ if (thread->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) {
+ if (thread->flags & _PR_ON_SLEEPQ) {
+ PRCList *q = thread->links.next;
+ if (q != &_PR_SLEEPQ(cpu)) {
+ if (propogate_time == PR_TRUE) {
+ PRThread *after = _PR_THREAD_PTR(q);
+ after->sleep += thread->sleep;
+ } else
+ _PR_SLEEPQMAX(cpu) -= thread->sleep;
+ } else {
+ /* Check if prev is the beggining of the list; if so,
+ * we are the only element on the list.
+ */
+ if (thread->links.prev != &_PR_SLEEPQ(cpu))
+ _PR_SLEEPQMAX(cpu) -= thread->sleep;
+ else
+ _PR_SLEEPQMAX(cpu) = 0;
+ }
+ thread->flags &= ~_PR_ON_SLEEPQ;
+ } else {
+ thread->flags &= ~_PR_ON_PAUSEQ;
+ }
+ PR_REMOVE_LINK(&thread->links);
+ } else
+ PR_ASSERT(0);
+}
+
+void
+_PR_AddThreadToRunQ(
+ PRThread *me, /* the current thread */
+ PRThread *thread) /* the local thread to be added to a run queue */
+{
+ PRThreadPriority pri = thread->priority;
+ _PRCPU *cpu = thread->cpu;
+
+ PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread));
+
+#if defined(WINNT)
+ /*
+ * On NT, we can only reliably know that the current CPU
+ * is not idle. We add the awakened thread to the run
+ * queue of its CPU if its CPU is the current CPU.
+ * For any other CPU, we don't really know whether it
+ * is busy or idle. So in all other cases, we just
+ * "post" the awakened thread to the IO completion port
+ * for the next idle CPU to execute (this is done in
+ * _PR_MD_WAKEUP_WAITER).
+ * Threads with a suspended I/O operation remain bound to
+ * the same cpu until I/O is cancelled
+ *
+ * NOTE: the boolean expression below must be the exact
+ * opposite of the corresponding boolean expression in
+ * _PR_MD_WAKEUP_WAITER.
+ */
+ if ((!_PR_IS_NATIVE_THREAD(me) && (cpu == me->cpu)) ||
+ (thread->md.thr_bound_cpu)) {
+ PR_ASSERT(!thread->md.thr_bound_cpu ||
+ (thread->md.thr_bound_cpu == cpu));
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(thread, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ }
+#else
+ _PR_RUNQ_LOCK(cpu);
+ _PR_ADD_RUNQ(thread, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+ if (!_PR_IS_NATIVE_THREAD(me) && (cpu == me->cpu)) {
+ if (pri > me->priority) {
+ _PR_SET_RESCHED_FLAG();
+ }
+ }
+#endif
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prcmon.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prcmon.c
new file mode 100644
index 00000000..277b7235
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prcmon.c
@@ -0,0 +1,413 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <stdlib.h>
+#include <stddef.h>
+
+/* Lock used to lock the monitor cache */
+#ifdef _PR_NO_PREEMPT
+#define _PR_NEW_LOCK_MCACHE()
+#define _PR_LOCK_MCACHE()
+#define _PR_UNLOCK_MCACHE()
+#else
+#ifdef _PR_LOCAL_THREADS_ONLY
+#define _PR_NEW_LOCK_MCACHE()
+#define _PR_LOCK_MCACHE() { PRIntn _is; _PR_INTSOFF(_is)
+#define _PR_UNLOCK_MCACHE() _PR_INTSON(_is); }
+#else
+PRLock *_pr_mcacheLock;
+#define _PR_NEW_LOCK_MCACHE() (_pr_mcacheLock = PR_NewLock())
+#define _PR_LOCK_MCACHE() PR_Lock(_pr_mcacheLock)
+#define _PR_UNLOCK_MCACHE() PR_Unlock(_pr_mcacheLock)
+#endif
+#endif
+
+/************************************************************************/
+
+typedef struct MonitorCacheEntryStr MonitorCacheEntry;
+
+struct MonitorCacheEntryStr {
+ MonitorCacheEntry* next;
+ void* address;
+ PRMonitor* mon;
+ long cacheEntryCount;
+};
+
+static PRUint32 hash_mask;
+static PRUintn num_hash_buckets;
+static PRUintn num_hash_buckets_log2;
+static MonitorCacheEntry **hash_buckets;
+static MonitorCacheEntry *free_entries;
+static PRUintn num_free_entries;
+static PRBool expanding;
+int _pr_mcache_ready;
+
+static void (*OnMonitorRecycle)(void *address);
+
+#define HASH(address) \
+ ((PRUint32) ( ((PRUptrdiff)(address) >> 2) ^ \
+ ((PRUptrdiff)(address) >> 10) ) \
+ & hash_mask)
+
+/*
+** Expand the monitor cache. This grows the hash buckets and allocates a
+** new chunk of cache entries and throws them on the free list. We keep
+** as many hash buckets as there are entries.
+**
+** Because we call malloc and malloc may need the monitor cache, we must
+** ensure that there are several free monitor cache entries available for
+** malloc to get. FREE_THRESHOLD is used to prevent monitor cache
+** starvation during monitor cache expansion.
+*/
+
+#define FREE_THRESHOLD 5
+
+static PRStatus ExpandMonitorCache(PRUintn new_size_log2)
+{
+ MonitorCacheEntry **old_hash_buckets, *p;
+ PRUintn i, entries, old_num_hash_buckets, added;
+ MonitorCacheEntry **new_hash_buckets, *new_entries;
+
+ entries = 1L << new_size_log2;
+
+ /*
+ ** Expand the monitor-cache-entry free list
+ */
+ new_entries = (MonitorCacheEntry*)
+ PR_CALLOC(entries * sizeof(MonitorCacheEntry));
+ if (NULL == new_entries) return PR_FAILURE;
+
+ /*
+ ** Allocate system monitors for the new monitor cache entries. If we
+ ** run out of system monitors, break out of the loop.
+ */
+ for (i = 0, added = 0, p = new_entries; i < entries; i++, p++, added++) {
+ p->mon = PR_NewMonitor();
+ if (!p->mon)
+ break;
+ }
+ if (added != entries) {
+ if (added == 0) {
+ /* Totally out of system monitors. Lossage abounds */
+ PR_DELETE(new_entries);
+ return PR_FAILURE;
+ }
+
+ /*
+ ** We were able to allocate some of the system monitors. Use
+ ** realloc to shrink down the new_entries memory
+ */
+ p = (MonitorCacheEntry*)
+ PR_REALLOC(new_entries, added * sizeof(MonitorCacheEntry));
+ if (p == 0) {
+ /*
+ ** Total lossage. We just leaked a bunch of system monitors
+ ** all over the floor. This should never ever happen.
+ */
+ PR_ASSERT(p != 0);
+ return PR_FAILURE;
+ }
+#ifdef VBOX
+ new_entries = p;
+#endif
+ }
+
+ /*
+ ** Now that we have allocated all of the system monitors, build up
+ ** the new free list. We can just update the free_list because we own
+ ** the mcache-lock and we aren't calling anyone who might want to use
+ ** it.
+ */
+ for (i = 0, p = new_entries; i < added - 1; i++, p++)
+ p->next = p + 1;
+ p->next = free_entries;
+ free_entries = new_entries;
+ num_free_entries += added;
+
+ /* Try to expand the hash table */
+ new_hash_buckets = (MonitorCacheEntry**)
+ PR_CALLOC(entries * sizeof(MonitorCacheEntry*));
+ if (NULL == new_hash_buckets) {
+ /*
+ ** Partial lossage. In this situation we don't get any more hash
+ ** buckets, which just means that the table lookups will take
+ ** longer. This is bad, but not fatal
+ */
+ PR_LOG(_pr_cmon_lm, PR_LOG_WARNING,
+ ("unable to grow monitor cache hash buckets"));
+ return PR_SUCCESS;
+ }
+
+ /*
+ ** Compute new hash mask value. This value is used to mask an address
+ ** until it's bits are in the right spot for indexing into the hash
+ ** table.
+ */
+ hash_mask = entries - 1;
+
+ /*
+ ** Expand the hash table. We have to rehash everything in the old
+ ** table into the new table.
+ */
+ old_hash_buckets = hash_buckets;
+ old_num_hash_buckets = num_hash_buckets;
+ for (i = 0; i < old_num_hash_buckets; i++) {
+ p = old_hash_buckets[i];
+ while (p) {
+ MonitorCacheEntry *next = p->next;
+
+ /* Hash based on new table size, and then put p in the new table */
+ PRUintn hash = HASH(p->address);
+ p->next = new_hash_buckets[hash];
+ new_hash_buckets[hash] = p;
+
+ p = next;
+ }
+ }
+
+ /*
+ ** Switch over to new hash table and THEN call free of the old
+ ** table. Since free might re-enter _pr_mcache_lock, things would
+ ** break terribly if it used the old hash table.
+ */
+ hash_buckets = new_hash_buckets;
+ num_hash_buckets = entries;
+ num_hash_buckets_log2 = new_size_log2;
+ PR_DELETE(old_hash_buckets);
+
+ PR_LOG(_pr_cmon_lm, PR_LOG_NOTICE,
+ ("expanded monitor cache to %d (buckets %d)",
+ num_free_entries, entries));
+
+ return PR_SUCCESS;
+} /* ExpandMonitorCache */
+
+/*
+** Lookup a monitor cache entry by address. Return a pointer to the
+** pointer to the monitor cache entry on success, null on failure.
+*/
+static MonitorCacheEntry **LookupMonitorCacheEntry(void *address)
+{
+ PRUintn hash;
+ MonitorCacheEntry **pp, *p;
+
+ hash = HASH(address);
+ pp = hash_buckets + hash;
+ while ((p = *pp) != 0) {
+ if (p->address == address) {
+ if (p->cacheEntryCount > 0)
+ return pp;
+ return NULL;
+ }
+ pp = &p->next;
+ }
+ return NULL;
+}
+
+/*
+** Try to create a new cached monitor. If it's already in the cache,
+** great - return it. Otherwise get a new free cache entry and set it
+** up. If the cache free space is getting low, expand the cache.
+*/
+static PRMonitor *CreateMonitor(void *address)
+{
+ PRUintn hash;
+ MonitorCacheEntry **pp, *p;
+
+ hash = HASH(address);
+ pp = hash_buckets + hash;
+ while ((p = *pp) != 0) {
+ if (p->address == address) goto gotit;
+
+ pp = &p->next;
+ }
+
+ /* Expand the monitor cache if we have run out of free slots in the table */
+ if (num_free_entries < FREE_THRESHOLD) {
+ /* Expand monitor cache */
+
+ /*
+ ** This function is called with the lock held. So what's the 'expanding'
+ ** boolean all about? Seems a bit redundant.
+ */
+ if (!expanding) {
+ PRStatus rv;
+
+ expanding = PR_TRUE;
+ rv = ExpandMonitorCache(num_hash_buckets_log2 + 1);
+ expanding = PR_FALSE;
+ if (PR_FAILURE == rv) return NULL;
+
+ /* redo the hash because it'll be different now */
+ hash = HASH(address);
+ } else {
+ /*
+ ** We are in process of expanding and we need a cache
+ ** monitor. Make sure we have enough!
+ */
+ PR_ASSERT(num_free_entries > 0);
+ }
+ }
+
+ /* Make a new monitor */
+ p = free_entries;
+ free_entries = p->next;
+ num_free_entries--;
+ if (OnMonitorRecycle && p->address)
+ OnMonitorRecycle(p->address);
+ p->address = address;
+ p->next = hash_buckets[hash];
+ hash_buckets[hash] = p;
+ PR_ASSERT(p->cacheEntryCount == 0);
+
+ gotit:
+ p->cacheEntryCount++;
+ return p->mon;
+}
+
+/*
+** Initialize the monitor cache
+*/
+void _PR_InitCMon(void)
+{
+ _PR_NEW_LOCK_MCACHE();
+ ExpandMonitorCache(3);
+ _pr_mcache_ready = 1;
+}
+
+/*
+** Create monitor for address. Don't enter the monitor while we have the
+** mcache locked because we might block!
+*/
+PR_IMPLEMENT(PRMonitor*) PR_CEnterMonitor(void *address)
+{
+ PRMonitor *mon;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ _PR_LOCK_MCACHE();
+ mon = CreateMonitor(address);
+ _PR_UNLOCK_MCACHE();
+
+ if (!mon) return NULL;
+
+ PR_EnterMonitor(mon);
+ return mon;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CExitMonitor(void *address)
+{
+ MonitorCacheEntry **pp, *p;
+ PRStatus status = PR_SUCCESS;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ if (pp != NULL) {
+ p = *pp;
+ if (--p->cacheEntryCount == 0) {
+ /*
+ ** Nobody is using the system monitor. Put it on the cached free
+ ** list. We are safe from somebody trying to use it because we
+ ** have the mcache locked.
+ */
+ p->address = 0; /* defensive move */
+ *pp = p->next; /* unlink from hash_buckets */
+ p->next = free_entries; /* link into free list */
+ free_entries = p;
+ num_free_entries++; /* count it as free */
+ }
+ status = PR_ExitMonitor(p->mon);
+ } else {
+ status = PR_FAILURE;
+ }
+ _PR_UNLOCK_MCACHE();
+
+ return status;
+}
+
+PR_IMPLEMENT(PRStatus) PR_CWait(void *address, PRIntervalTime ticks)
+{
+ MonitorCacheEntry **pp;
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ mon = pp ? ((*pp)->mon) : NULL;
+ _PR_UNLOCK_MCACHE();
+
+ if (mon == NULL)
+ return PR_FAILURE;
+ return PR_Wait(mon, ticks);
+}
+
+PR_IMPLEMENT(PRStatus) PR_CNotify(void *address)
+{
+ MonitorCacheEntry **pp;
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ mon = pp ? ((*pp)->mon) : NULL;
+ _PR_UNLOCK_MCACHE();
+
+ if (mon == NULL)
+ return PR_FAILURE;
+ return PR_Notify(mon);
+}
+
+PR_IMPLEMENT(PRStatus) PR_CNotifyAll(void *address)
+{
+ MonitorCacheEntry **pp;
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ mon = pp ? ((*pp)->mon) : NULL;
+ _PR_UNLOCK_MCACHE();
+
+ if (mon == NULL)
+ return PR_FAILURE;
+ return PR_NotifyAll(mon);
+}
+
+PR_IMPLEMENT(void)
+PR_CSetOnMonitorRecycle(void (*callback)(void *address))
+{
+ OnMonitorRecycle = callback;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prcthr.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prcthr.c
new file mode 100644
index 00000000..1e2f469c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prcthr.c
@@ -0,0 +1,446 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+**
+*/
+#pragma warning(disable : 4101)
+#endif
+
+
+extern PRLock *_pr_sleeplock; /* allocated and initialized in prinit */
+/*
+** Routines common to both native and user threads.
+**
+**
+** Clean up a thread object, releasing all of the attached data. Do not
+** free the object itself (it may not have been malloc'd)
+*/
+void _PR_CleanupThread(PRThread *thread)
+{
+ /* Free up per-thread-data */
+ _PR_DestroyThreadPrivate(thread);
+
+ /* Free any thread dump procs */
+ if (thread->dumpArg) {
+ PR_DELETE(thread->dumpArg);
+ }
+ thread->dump = 0;
+
+ PR_DELETE(thread->errorString);
+ thread->errorStringSize = 0;
+ thread->errorStringLength = 0;
+ thread->environment = NULL;
+}
+
+PR_IMPLEMENT(PRStatus) PR_Yield()
+{
+ static PRBool warning = PR_TRUE;
+ if (warning) warning = _PR_Obsolete(
+ "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)");
+ return (PR_Sleep(PR_INTERVAL_NO_WAIT));
+}
+
+/*
+** Make the current thread sleep until "timeout" ticks amount of time
+** has expired. If "timeout" is PR_INTERVAL_NO_WAIT then the call is
+** equivalent to a yield. Waiting for an infinite amount of time is
+** allowed in the expectation that another thread will interrupt().
+**
+** A single lock is used for all threads calling sleep. Each caller
+** does get its own condition variable since each is expected to have
+** a unique 'timeout'.
+*/
+PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout)
+{
+ PRStatus rv = PR_SUCCESS;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (PR_INTERVAL_NO_WAIT == timeout)
+ {
+ /*
+ ** This is a simple yield, nothing more, nothing less.
+ */
+ PRIntn is;
+ PRThread *me = PR_GetCurrentThread();
+ PRUintn pri = me->priority;
+ _PRCPU *cpu = _PR_MD_CURRENT_CPU();
+
+ if ( _PR_IS_NATIVE_THREAD(me) ) _PR_MD_YIELD();
+ else
+ {
+ _PR_INTSOFF(is);
+ _PR_RUNQ_LOCK(cpu);
+ if (_PR_RUNQREADYMASK(cpu) >> pri) {
+ me->cpu = cpu;
+ me->state = _PR_RUNNABLE;
+ _PR_ADD_RUNQ(me, cpu, pri);
+ _PR_RUNQ_UNLOCK(cpu);
+
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: yielding"));
+ _PR_MD_SWITCH_CONTEXT(me);
+ PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: done"));
+
+ _PR_FAST_INTSON(is);
+ }
+ else
+ {
+ _PR_RUNQ_UNLOCK(cpu);
+ _PR_INTSON(is);
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** This is waiting for some finite period of time.
+ ** A thread in this state is interruptible (PR_Interrupt()),
+ ** but the lock and cvar used are local to the implementation
+ ** and not visible to the caller, therefore not notifiable.
+ */
+ PRCondVar *cv;
+ PRIntervalTime timein;
+
+ timein = PR_IntervalNow();
+ cv = PR_NewCondVar(_pr_sleeplock);
+ PR_ASSERT(cv != NULL);
+ PR_Lock(_pr_sleeplock);
+ do
+ {
+ PRIntervalTime delta = PR_IntervalNow() - timein;
+ if (delta > timeout) break;
+ rv = PR_WaitCondVar(cv, timeout - delta);
+ } while (rv == PR_SUCCESS);
+ PR_Unlock(_pr_sleeplock);
+ PR_DestroyCondVar(cv);
+ }
+ return rv;
+}
+
+PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thread)
+{
+ return thread->id;
+}
+
+PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread)
+{
+ return (PRThreadPriority) thread->priority;
+}
+
+PR_IMPLEMENT(PRThread *) PR_GetCurrentThread()
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ return _PR_MD_CURRENT_THREAD();
+}
+
+/*
+** Set the interrupt flag for a thread. The thread will be unable to
+** block in i/o functions when this happens. Also, any PR_Wait's in
+** progress will be undone. The interrupt remains in force until
+** PR_ClearInterrupt is called.
+*/
+PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thread)
+{
+#ifdef _PR_GLOBAL_THREADS_ONLY
+ PRCondVar *victim;
+
+ _PR_THREAD_LOCK(thread);
+ thread->flags |= _PR_INTERRUPT;
+ victim = thread->wait.cvar;
+ _PR_THREAD_UNLOCK(thread);
+ if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) {
+ int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD());
+
+ if (!haveLock) PR_Lock(victim->lock);
+ PR_NotifyAllCondVar(victim);
+ if (!haveLock) PR_Unlock(victim->lock);
+ }
+ return PR_SUCCESS;
+#else /* ! _PR_GLOBAL_THREADS_ONLY */
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSOFF(is);
+
+ _PR_THREAD_LOCK(thread);
+ thread->flags |= _PR_INTERRUPT;
+ switch (thread->state) {
+ case _PR_COND_WAIT:
+ /*
+ * call is made with thread locked;
+ * on return lock is released
+ */
+ if (!(thread->flags & _PR_INTERRUPT_BLOCKED))
+ _PR_NotifyLockedThread(thread);
+ break;
+ case _PR_IO_WAIT:
+ /*
+ * Need to hold the thread lock when calling
+ * _PR_Unblock_IO_Wait(). On return lock is
+ * released.
+ */
+#if defined(XP_UNIX) || defined(WINNT) || defined(WIN16)
+ if (!(thread->flags & _PR_INTERRUPT_BLOCKED))
+ _PR_Unblock_IO_Wait(thread);
+#else
+ _PR_THREAD_UNLOCK(thread);
+#endif
+ break;
+ case _PR_RUNNING:
+ case _PR_RUNNABLE:
+ case _PR_LOCK_WAIT:
+ default:
+ _PR_THREAD_UNLOCK(thread);
+ break;
+ }
+ if (!_PR_IS_NATIVE_THREAD(me))
+ _PR_INTSON(is);
+ return PR_SUCCESS;
+#endif /* _PR_GLOBAL_THREADS_ONLY */
+}
+
+/*
+** Clear the interrupt flag for self.
+*/
+PR_IMPLEMENT(void) PR_ClearInterrupt()
+{
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
+ _PR_THREAD_LOCK(me);
+ me->flags &= ~_PR_INTERRUPT;
+ _PR_THREAD_UNLOCK(me);
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
+}
+
+PR_IMPLEMENT(void) PR_BlockInterrupt()
+{
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
+ _PR_THREAD_LOCK(me);
+ _PR_THREAD_BLOCK_INTERRUPT(me);
+ _PR_THREAD_UNLOCK(me);
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
+} /* PR_BlockInterrupt */
+
+PR_IMPLEMENT(void) PR_UnblockInterrupt()
+{
+ PRIntn is;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is);
+ _PR_THREAD_LOCK(me);
+ _PR_THREAD_UNBLOCK_INTERRUPT(me);
+ _PR_THREAD_UNLOCK(me);
+ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is);
+} /* PR_UnblockInterrupt */
+
+/*
+** Return the thread stack pointer of the given thread.
+*/
+PR_IMPLEMENT(void *) PR_GetSP(PRThread *thread)
+{
+ return (void *)_PR_MD_GET_SP(thread);
+}
+
+PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thread)
+{
+ return thread->environment;
+}
+
+PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thread, void *env)
+{
+ thread->environment = env;
+}
+
+
+PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask)
+{
+#ifdef HAVE_THREAD_AFFINITY
+ return _PR_MD_GETTHREADAFFINITYMASK(thread, mask);
+#else
+
+#if defined(XP_MAC)
+#pragma unused (thread, mask)
+#endif
+
+ return 0;
+#endif
+}
+
+PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask )
+{
+#ifdef HAVE_THREAD_AFFINITY
+#ifndef IRIX
+ return _PR_MD_SETTHREADAFFINITYMASK(thread, mask);
+#else
+ return 0;
+#endif
+#else
+
+#if defined(XP_MAC)
+#pragma unused (thread, mask)
+#endif
+
+ return 0;
+#endif
+}
+
+/* This call is thread unsafe if another thread is calling SetConcurrency()
+ */
+PR_IMPLEMENT(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask)
+{
+#ifdef HAVE_THREAD_AFFINITY
+ PRCList *qp;
+ extern PRUint32 _pr_cpu_affinity_mask;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ _pr_cpu_affinity_mask = mask;
+
+ qp = _PR_CPUQ().next;
+ while(qp != &_PR_CPUQ()) {
+ _PRCPU *cpu;
+
+ cpu = _PR_CPU_PTR(qp);
+ PR_SetThreadAffinityMask(cpu->thread, mask);
+
+ qp = qp->next;
+ }
+#endif
+
+#if defined(XP_MAC)
+#pragma unused (mask)
+#endif
+
+ return 0;
+}
+
+PRUint32 _pr_recycleThreads = 0;
+PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 count)
+{
+ _pr_recycleThreads = count;
+}
+
+PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ return _PR_CreateThread(type, start, arg, priority, scope, state,
+ stackSize, _PR_GCABLE_THREAD);
+}
+
+#ifdef SOLARIS
+PR_IMPLEMENT(PRThread*) PR_CreateThreadBound(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRUintn priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize)
+{
+ return _PR_CreateThread(type, start, arg, priority, scope, state,
+ stackSize, _PR_BOUND_THREAD);
+}
+#endif
+
+
+PR_IMPLEMENT(PRThread*) PR_AttachThreadGCAble(
+ PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
+{
+#ifdef XP_MAC
+#pragma unused (type, priority, stack)
+#endif
+ /* $$$$ not sure how to finese this one */
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ return NULL;
+}
+
+PR_IMPLEMENT(void) PR_SetThreadGCAble()
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ PR_Lock(_pr_activeLock);
+ _PR_MD_CURRENT_THREAD()->flags |= _PR_GCABLE_THREAD;
+ PR_Unlock(_pr_activeLock);
+}
+
+PR_IMPLEMENT(void) PR_ClearThreadGCAble()
+{
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+ PR_Lock(_pr_activeLock);
+ _PR_MD_CURRENT_THREAD()->flags &= (~_PR_GCABLE_THREAD);
+ PR_Unlock(_pr_activeLock);
+}
+
+PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thread)
+{
+#ifdef XP_MAC
+#pragma unused( thread )
+#endif
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (_PR_IS_NATIVE_THREAD(thread)) {
+ return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD :
+ PR_GLOBAL_THREAD;
+ } else
+ return PR_LOCAL_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thread)
+{
+ return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thread)
+{
+ return (NULL == thread->term) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;
+} /* PR_GetThreadState */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prdump.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prdump.c
new file mode 100644
index 00000000..3ea884d2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prdump.c
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+**
+*/
+#pragma warning(disable : 4101)
+#endif
+
+/* XXX use unbuffered nspr stdio */
+
+PRFileDesc *_pr_dumpOut;
+
+PRUint32 _PR_DumpPrintf(PRFileDesc *fd, const char *fmt, ...)
+{
+ char buf[100];
+ PRUint32 nb;
+ va_list ap;
+
+ va_start(ap, fmt);
+ nb = PR_vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ PR_Write(fd, buf, nb);
+
+ return nb;
+}
+
+void _PR_DumpThread(PRFileDesc *fd, PRThread *thread)
+{
+
+#ifndef _PR_GLOBAL_THREADS_ONLY
+ _PR_DumpPrintf(fd, "%05d[%08p] pri=%2d flags=0x%02x",
+ thread->id, thread, thread->priority, thread->flags);
+ switch (thread->state) {
+ case _PR_RUNNABLE:
+ case _PR_RUNNING:
+ break;
+ case _PR_LOCK_WAIT:
+ _PR_DumpPrintf(fd, " lock=%p", thread->wait.lock);
+ break;
+ case _PR_COND_WAIT:
+ _PR_DumpPrintf(fd, " condvar=%p sleep=%lldms",
+ thread->wait.cvar, thread->sleep);
+ break;
+ case _PR_SUSPENDED:
+ _PR_DumpPrintf(fd, " suspended");
+ break;
+ }
+ PR_Write(fd, "\n", 1);
+#endif
+
+ /* Now call dump routine */
+ if (thread->dump) {
+ thread->dump(fd, thread, thread->dumpArg);
+ }
+}
+
+static void DumpThreadQueue(PRFileDesc *fd, PRCList *list)
+{
+#ifndef _PR_GLOBAL_THREADS_ONLY
+ PRCList *q;
+
+ q = list->next;
+ while (q != list) {
+ PRThread *t = _PR_THREAD_PTR(q);
+ _PR_DumpThread(fd, t);
+ q = q->next;
+ }
+#endif
+}
+
+void _PR_DumpThreads(PRFileDesc *fd)
+{
+ PRThread *t;
+ PRIntn i;
+
+ _PR_DumpPrintf(fd, "Current Thread:\n");
+ t = _PR_MD_CURRENT_THREAD();
+ _PR_DumpThread(fd, t);
+
+ _PR_DumpPrintf(fd, "Runnable Threads:\n");
+ for (i = 0; i < 32; i++) {
+ DumpThreadQueue(fd, &_PR_RUNQ(t->cpu)[i]);
+ }
+
+ _PR_DumpPrintf(fd, "CondVar timed wait Threads:\n");
+ DumpThreadQueue(fd, &_PR_SLEEPQ(t->cpu));
+
+ _PR_DumpPrintf(fd, "CondVar wait Threads:\n");
+ DumpThreadQueue(fd, &_PR_PAUSEQ(t->cpu));
+
+ _PR_DumpPrintf(fd, "Suspended Threads:\n");
+ DumpThreadQueue(fd, &_PR_SUSPENDQ(t->cpu));
+}
+
+PR_IMPLEMENT(void) PR_ShowStatus(void)
+{
+ PRIntn is;
+
+ if ( _PR_MD_CURRENT_THREAD()
+ && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_INTSOFF(is);
+ _pr_dumpOut = _pr_stderr;
+ _PR_DumpThreads(_pr_dumpOut);
+ if ( _PR_MD_CURRENT_THREAD()
+ && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_FAST_INTSON(is);
+}
+
+PR_IMPLEMENT(void)
+PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg)
+{
+ thread->dump = dump;
+ thread->dumpArg = arg;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prmon.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prmon.c
new file mode 100644
index 00000000..69d0f655
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prmon.c
@@ -0,0 +1,222 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+/************************************************************************/
+
+/*
+** Create a new monitor.
+*/
+PR_IMPLEMENT(PRMonitor*) PR_NewMonitor()
+{
+ PRMonitor *mon;
+ PRCondVar *cvar;
+ PRLock *lock;
+
+ mon = PR_NEWZAP(PRMonitor);
+ if (mon) {
+ lock = PR_NewLock();
+ if (!lock) {
+ PR_DELETE(mon);
+ return 0;
+ }
+
+ cvar = PR_NewCondVar(lock);
+ if (!cvar) {
+ PR_DestroyLock(lock);
+ PR_DELETE(mon);
+ return 0;
+ }
+ mon->cvar = cvar;
+ mon->name = NULL;
+ }
+ return mon;
+}
+
+PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
+{
+ PRMonitor* mon = PR_NewMonitor();
+ if (mon)
+ mon->name = name;
+ return mon;
+}
+
+/*
+** Destroy a monitor. There must be no thread waiting on the monitor's
+** condition variable. The caller is responsible for guaranteeing that the
+** monitor is no longer in use.
+*/
+PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon)
+{
+ PR_DestroyLock(mon->cvar->lock);
+ PR_DestroyCondVar(mon->cvar);
+ PR_DELETE(mon);
+}
+
+/*
+** Enter the lock associated with the monitor.
+*/
+PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon)
+{
+ if (mon->cvar->lock->owner == _PR_MD_CURRENT_THREAD()) {
+ mon->entryCount++;
+ } else {
+ PR_Lock(mon->cvar->lock);
+ mon->entryCount = 1;
+ }
+}
+
+/*
+** Test and then enter the lock associated with the monitor if it's not
+** already entered by some other thread. Return PR_FALSE if some other
+** thread owned the lock at the time of the call.
+*/
+PR_IMPLEMENT(PRBool) PR_TestAndEnterMonitor(PRMonitor *mon)
+{
+ if (mon->cvar->lock->owner == _PR_MD_CURRENT_THREAD()) {
+ mon->entryCount++;
+ return PR_TRUE;
+ } else {
+ if (PR_TestAndLock(mon->cvar->lock)) {
+ mon->entryCount = 1;
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+/*
+** Exit the lock associated with the monitor once.
+*/
+PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon)
+{
+ if (mon->cvar->lock->owner != _PR_MD_CURRENT_THREAD()) {
+ return PR_FAILURE;
+ }
+ if (--mon->entryCount == 0) {
+ return PR_Unlock(mon->cvar->lock);
+ }
+ return PR_SUCCESS;
+}
+
+/*
+** Return the number of times that the current thread has entered the
+** lock. Returns zero if the current thread has not entered the lock.
+*/
+PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon)
+{
+ return (mon->cvar->lock->owner == _PR_MD_CURRENT_THREAD()) ?
+ mon->entryCount : 0;
+}
+
+/*
+** Wait for a notify on the condition variable. Sleep for "ticks" amount
+** of time (if "tick" is 0 then the sleep is indefinite). While
+** the thread is waiting it exits the monitors lock (as if it called
+** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When
+** the wait has finished the thread regains control of the monitors lock
+** with the same entry count as before the wait began.
+**
+** The thread waiting on the monitor will be resumed when the monitor is
+** notified (assuming the thread is the next in line to receive the
+** notify) or when the "ticks" elapses.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+** This routine can return PR_PENDING_INTERRUPT if the waiting thread
+** has been interrupted.
+*/
+PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks)
+{
+ PRUintn entryCount;
+ PRStatus status;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (mon->cvar->lock->owner != me) return PR_FAILURE;
+
+ entryCount = mon->entryCount;
+ mon->entryCount = 0;
+
+ status = _PR_WaitCondVar(me, mon->cvar, mon->cvar->lock, ticks);
+
+ mon->entryCount = entryCount;
+
+ return status;
+}
+
+/*
+** Notify the highest priority thread waiting on the condition
+** variable. If a thread is waiting on the condition variable (using
+** PR_Wait) then it is awakened and begins waiting on the monitor's lock.
+*/
+PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ if (mon->cvar->lock->owner != me) return PR_FAILURE;
+ PR_NotifyCondVar(mon->cvar);
+ return PR_SUCCESS;
+}
+
+/*
+** Notify all of the threads waiting on the condition variable. All of
+** threads are notified in turn. The highest priority thread will
+** probably acquire the monitor first when the monitor is exited.
+*/
+PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon)
+{
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ if (mon->cvar->lock->owner != me) return PR_FAILURE;
+ PR_NotifyAllCondVar(mon->cvar);
+ return PR_SUCCESS;
+}
+
+/************************************************************************/
+
+PRUint32 _PR_MonitorToString(PRMonitor *mon, char *buf, PRUint32 buflen)
+{
+ PRUint32 nb;
+
+ if (mon->cvar->lock->owner) {
+ nb = PR_snprintf(buf, buflen, "[%p] owner=%d[%p] count=%ld",
+ mon, mon->cvar->lock->owner->id,
+ mon->cvar->lock->owner, mon->entryCount);
+ } else {
+ nb = PR_snprintf(buf, buflen, "[%p]", mon);
+ }
+ return nb;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prrwlock.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prrwlock.c
new file mode 100644
index 00000000..35e0e3e7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prrwlock.c
@@ -0,0 +1,512 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+
+#include <string.h>
+
+#if defined(HPUX) && defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+
+#include <pthread.h>
+#define HAVE_UNIX98_RWLOCK
+#define RWLOCK_T pthread_rwlock_t
+#define RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL)
+#define RWLOCK_DESTROY(lock) pthread_rwlock_destroy(lock)
+#define RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock)
+#define RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock)
+#define RWLOCK_UNLOCK(lock) pthread_rwlock_unlock(lock)
+
+#elif defined(SOLARIS) && (defined(_PR_PTHREADS) \
+ || defined(_PR_GLOBAL_THREADS_ONLY))
+
+#include <synch.h>
+#define HAVE_UI_RWLOCK
+#define RWLOCK_T rwlock_t
+#define RWLOCK_INIT(lock) rwlock_init(lock, USYNC_THREAD, NULL)
+#define RWLOCK_DESTROY(lock) rwlock_destroy(lock)
+#define RWLOCK_RDLOCK(lock) rw_rdlock(lock)
+#define RWLOCK_WRLOCK(lock) rw_wrlock(lock)
+#define RWLOCK_UNLOCK(lock) rw_unlock(lock)
+
+#endif
+
+/*
+ * Reader-writer lock
+ */
+struct PRRWLock {
+ char *rw_name; /* lock name */
+ PRUint32 rw_rank; /* rank of the lock */
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ RWLOCK_T rw_lock;
+#else
+ PRLock *rw_lock;
+ PRInt32 rw_lock_cnt; /* == 0, if unlocked */
+ /* == -1, if write-locked */
+ /* > 0 , # of read locks */
+ PRUint32 rw_reader_cnt; /* number of waiting readers */
+ PRUint32 rw_writer_cnt; /* number of waiting writers */
+ PRCondVar *rw_reader_waitq; /* cvar for readers */
+ PRCondVar *rw_writer_waitq; /* cvar for writers */
+#ifdef DEBUG
+ PRThread *rw_owner; /* lock owner for write-lock */
+#endif
+#endif
+};
+
+#ifdef DEBUG
+#define _PR_RWLOCK_RANK_ORDER_DEBUG /* enable deadlock detection using
+ rank-order for locks
+ */
+#endif
+
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+
+static PRUintn pr_thread_rwlock_key; /* TPD key for lock stack */
+static PRUintn pr_thread_rwlock_alloc_failed;
+
+#define _PR_RWLOCK_RANK_ORDER_LIMIT 10
+
+typedef struct thread_rwlock_stack {
+ PRInt32 trs_index; /* top of stack */
+ PRRWLock *trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT]; /* stack of lock
+ pointers */
+
+} thread_rwlock_stack;
+
+static void _PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock);
+static PRUint32 _PR_GET_THREAD_RWLOCK_RANK(void);
+static void _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock);
+static void _PR_RELEASE_LOCK_STACK(void *lock_stack);
+
+#endif
+
+/*
+ * Reader/Writer Locks
+ */
+
+/*
+ * PR_NewRWLock
+ * Create a reader-writer lock, with the given lock rank and lock name
+ *
+ */
+
+PR_IMPLEMENT(PRRWLock *)
+PR_NewRWLock(PRUint32 lock_rank, const char *lock_name)
+{
+ PRRWLock *rwlock;
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ int err;
+#endif
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ rwlock = PR_NEWZAP(PRRWLock);
+ if (rwlock == NULL)
+ return NULL;
+
+ rwlock->rw_rank = lock_rank;
+ if (lock_name != NULL) {
+ rwlock->rw_name = (char*) PR_Malloc(strlen(lock_name) + 1);
+ if (rwlock->rw_name == NULL) {
+ PR_DELETE(rwlock);
+ return(NULL);
+ }
+ strcpy(rwlock->rw_name, lock_name);
+ } else {
+ rwlock->rw_name = NULL;
+ }
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ err = RWLOCK_INIT(&rwlock->rw_lock);
+ if (err != 0) {
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ PR_Free(rwlock->rw_name);
+ PR_DELETE(rwlock);
+ return NULL;
+ }
+ return rwlock;
+#else
+ rwlock->rw_lock = PR_NewLock();
+ if (rwlock->rw_lock == NULL) {
+ goto failed;
+ }
+ rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock);
+ if (rwlock->rw_reader_waitq == NULL) {
+ goto failed;
+ }
+ rwlock->rw_writer_waitq = PR_NewCondVar(rwlock->rw_lock);
+ if (rwlock->rw_writer_waitq == NULL) {
+ goto failed;
+ }
+ rwlock->rw_reader_cnt = 0;
+ rwlock->rw_writer_cnt = 0;
+ rwlock->rw_lock_cnt = 0;
+ return rwlock;
+
+failed:
+ if (rwlock->rw_reader_waitq != NULL) {
+ PR_DestroyCondVar(rwlock->rw_reader_waitq);
+ }
+ if (rwlock->rw_lock != NULL) {
+ PR_DestroyLock(rwlock->rw_lock);
+ }
+ PR_Free(rwlock->rw_name);
+ PR_DELETE(rwlock);
+ return NULL;
+#endif
+}
+
+/*
+** Destroy the given RWLock "lock".
+*/
+PR_IMPLEMENT(void)
+PR_DestroyRWLock(PRRWLock *rwlock)
+{
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ int err;
+ err = RWLOCK_DESTROY(&rwlock->rw_lock);
+ PR_ASSERT(err == 0);
+#else
+ PR_ASSERT(rwlock->rw_reader_cnt == 0);
+ PR_DestroyCondVar(rwlock->rw_reader_waitq);
+ PR_DestroyCondVar(rwlock->rw_writer_waitq);
+ PR_DestroyLock(rwlock->rw_lock);
+#endif
+ if (rwlock->rw_name != NULL)
+ PR_Free(rwlock->rw_name);
+ PR_DELETE(rwlock);
+}
+
+/*
+** Read-lock the RWLock.
+*/
+PR_IMPLEMENT(void)
+PR_RWLock_Rlock(PRRWLock *rwlock)
+{
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+int err;
+#endif
+
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * assert that rank ordering is not violated; the rank of 'rwlock' should
+ * be equal to or greater than the highest rank of all the locks held by
+ * the thread.
+ */
+ PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) ||
+ (rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK()));
+#endif
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ err = RWLOCK_RDLOCK(&rwlock->rw_lock);
+ PR_ASSERT(err == 0);
+#else
+ PR_Lock(rwlock->rw_lock);
+ /*
+ * wait if write-locked or if a writer is waiting; preference for writers
+ */
+ while ((rwlock->rw_lock_cnt < 0) ||
+ (rwlock->rw_writer_cnt > 0)) {
+ rwlock->rw_reader_cnt++;
+ PR_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);
+ rwlock->rw_reader_cnt--;
+ }
+ /*
+ * Increment read-lock count
+ */
+ rwlock->rw_lock_cnt++;
+
+ PR_Unlock(rwlock->rw_lock);
+#endif
+
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * update thread's lock rank
+ */
+ _PR_SET_THREAD_RWLOCK_RANK(rwlock);
+#endif
+}
+
+/*
+** Write-lock the RWLock.
+*/
+PR_IMPLEMENT(void)
+PR_RWLock_Wlock(PRRWLock *rwlock)
+{
+#if defined(DEBUG)
+PRThread *me = PR_GetCurrentThread();
+#endif
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+int err;
+#endif
+
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * assert that rank ordering is not violated; the rank of 'rwlock' should
+ * be equal to or greater than the highest rank of all the locks held by
+ * the thread.
+ */
+ PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) ||
+ (rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK()));
+#endif
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ err = RWLOCK_WRLOCK(&rwlock->rw_lock);
+ PR_ASSERT(err == 0);
+#else
+ PR_Lock(rwlock->rw_lock);
+ /*
+ * wait if read locked
+ */
+ while (rwlock->rw_lock_cnt != 0) {
+ rwlock->rw_writer_cnt++;
+ PR_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT);
+ rwlock->rw_writer_cnt--;
+ }
+ /*
+ * apply write lock
+ */
+ rwlock->rw_lock_cnt--;
+ PR_ASSERT(rwlock->rw_lock_cnt == -1);
+#ifdef DEBUG
+ PR_ASSERT(me != NULL);
+ rwlock->rw_owner = me;
+#endif
+ PR_Unlock(rwlock->rw_lock);
+#endif
+
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * update thread's lock rank
+ */
+ _PR_SET_THREAD_RWLOCK_RANK(rwlock);
+#endif
+}
+
+/*
+** Unlock the RW lock.
+*/
+PR_IMPLEMENT(void)
+PR_RWLock_Unlock(PRRWLock *rwlock)
+{
+#if defined(DEBUG)
+PRThread *me = PR_GetCurrentThread();
+#endif
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+int err;
+#endif
+
+#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
+ err = RWLOCK_UNLOCK(&rwlock->rw_lock);
+ PR_ASSERT(err == 0);
+#else
+ PR_Lock(rwlock->rw_lock);
+ /*
+ * lock must be read or write-locked
+ */
+ PR_ASSERT(rwlock->rw_lock_cnt != 0);
+ if (rwlock->rw_lock_cnt > 0) {
+
+ /*
+ * decrement read-lock count
+ */
+ rwlock->rw_lock_cnt--;
+ if (rwlock->rw_lock_cnt == 0) {
+ /*
+ * lock is not read-locked anymore; wakeup a waiting writer
+ */
+ if (rwlock->rw_writer_cnt > 0)
+ PR_NotifyCondVar(rwlock->rw_writer_waitq);
+ }
+ } else {
+ PR_ASSERT(rwlock->rw_lock_cnt == -1);
+
+ rwlock->rw_lock_cnt = 0;
+#ifdef DEBUG
+ PR_ASSERT(rwlock->rw_owner == me);
+ rwlock->rw_owner = NULL;
+#endif
+ /*
+ * wakeup a writer, if present; preference for writers
+ */
+ if (rwlock->rw_writer_cnt > 0)
+ PR_NotifyCondVar(rwlock->rw_writer_waitq);
+ /*
+ * else, wakeup all readers, if any
+ */
+ else if (rwlock->rw_reader_cnt > 0)
+ PR_NotifyAllCondVar(rwlock->rw_reader_waitq);
+ }
+ PR_Unlock(rwlock->rw_lock);
+#endif
+
+#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * update thread's lock rank
+ */
+ _PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
+#endif
+ return;
+}
+
+#ifndef _PR_RWLOCK_RANK_ORDER_DEBUG
+
+void _PR_InitRWLocks(void) { }
+
+#else
+
+void _PR_InitRWLocks(void)
+{
+ /*
+ * allocated thread-private-data index for rwlock list
+ */
+ if (PR_NewThreadPrivateIndex(&pr_thread_rwlock_key,
+ _PR_RELEASE_LOCK_STACK) == PR_FAILURE) {
+ pr_thread_rwlock_alloc_failed = 1;
+ return;
+ }
+}
+
+/*
+ * _PR_SET_THREAD_RWLOCK_RANK
+ * Set a thread's lock rank, which is the highest of the ranks of all
+ * the locks held by the thread. Pointers to the locks are added to a
+ * per-thread list, which is anchored off a thread-private data key.
+ */
+
+static void
+_PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
+{
+thread_rwlock_stack *lock_stack;
+PRStatus rv;
+
+ /*
+ * allocate a lock stack
+ */
+ if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL) {
+ lock_stack = (thread_rwlock_stack *)
+ PR_CALLOC(1 * sizeof(thread_rwlock_stack));
+ if (lock_stack) {
+ rv = PR_SetThreadPrivate(pr_thread_rwlock_key, lock_stack);
+ if (rv == PR_FAILURE) {
+ PR_DELETE(lock_stack);
+ pr_thread_rwlock_alloc_failed = 1;
+ return;
+ }
+ } else {
+ pr_thread_rwlock_alloc_failed = 1;
+ return;
+ }
+ }
+ /*
+ * add rwlock to lock stack, if limit is not exceeded
+ */
+ if (lock_stack) {
+ if (lock_stack->trs_index < _PR_RWLOCK_RANK_ORDER_LIMIT)
+ lock_stack->trs_stack[lock_stack->trs_index++] = rwlock;
+ }
+}
+
+static void
+_PR_RELEASE_LOCK_STACK(void *lock_stack)
+{
+ PR_ASSERT(lock_stack);
+ PR_DELETE(lock_stack);
+}
+
+/*
+ * _PR_GET_THREAD_RWLOCK_RANK
+ *
+ * return thread's lock rank. If thread-private-data for the lock
+ * stack is not allocated, return PR_RWLOCK_RANK_NONE.
+ */
+
+static PRUint32
+_PR_GET_THREAD_RWLOCK_RANK(void)
+{
+ thread_rwlock_stack *lock_stack;
+
+ if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL)
+ return (PR_RWLOCK_RANK_NONE);
+ else
+ return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
+}
+
+/*
+ * _PR_UNSET_THREAD_RWLOCK_RANK
+ *
+ * remove the rwlock from the lock stack. Since locks may not be
+ * unlocked in a FIFO order, the entire lock stack is searched.
+ */
+
+static void
+_PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
+{
+ thread_rwlock_stack *lock_stack;
+ int new_index = 0, index, done = 0;
+
+ lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);
+
+ PR_ASSERT(lock_stack != NULL);
+
+ index = lock_stack->trs_index - 1;
+ while (index-- >= 0) {
+ if ((lock_stack->trs_stack[index] == rwlock) && !done) {
+ /*
+ * reset the slot for rwlock
+ */
+ lock_stack->trs_stack[index] = NULL;
+ done = 1;
+ }
+ /*
+ * search for the lowest-numbered empty slot, above which there are
+ * no non-empty slots
+ */
+ if ((lock_stack->trs_stack[index] != NULL) && !new_index)
+ new_index = index + 1;
+ if (done && new_index)
+ break;
+ }
+ /*
+ * set top of stack to highest numbered empty slot
+ */
+ lock_stack->trs_index = new_index;
+
+}
+
+#endif /* _PR_RWLOCK_RANK_ORDER_DEBUG */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prsem.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prsem.c
new file mode 100644
index 00000000..692bc0e9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prsem.c
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "primpl.h"
+#if defined(XP_MAC)
+#include "prsem.h"
+#else
+#include "obsolete/prsem.h"
+#endif
+
+/************************************************************************/
+
+/*
+** Create a new semaphore.
+*/
+PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
+{
+ PRSemaphore *sem;
+ PRCondVar *cvar;
+ PRLock *lock;
+
+ sem = PR_NEWZAP(PRSemaphore);
+ if (sem) {
+#ifdef HAVE_CVAR_BUILT_ON_SEM
+ _PR_MD_NEW_SEM(&sem->md, value);
+#else
+ lock = PR_NewLock();
+ if (!lock) {
+ PR_DELETE(sem);
+ return NULL;
+ }
+
+ cvar = PR_NewCondVar(lock);
+ if (!cvar) {
+ PR_DestroyLock(lock);
+ PR_DELETE(sem);
+ return NULL;
+ }
+ sem->cvar = cvar;
+ sem->count = value;
+#endif
+ }
+ return sem;
+}
+
+/*
+** Destroy a semaphore. There must be no thread waiting on the semaphore.
+** The caller is responsible for guaranteeing that the semaphore is
+** no longer in use.
+*/
+PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *sem)
+{
+#ifdef HAVE_CVAR_BUILT_ON_SEM
+ _PR_MD_DESTROY_SEM(&sem->md);
+#else
+ PR_ASSERT(sem->waiters == 0);
+
+ PR_DestroyLock(sem->cvar->lock);
+ PR_DestroyCondVar(sem->cvar);
+#endif
+ PR_DELETE(sem);
+}
+
+/*
+** Wait on a Semaphore.
+**
+** This routine allows a calling thread to wait or proceed depending upon the
+** state of the semahore sem. The thread can proceed only if the counter value
+** of the semaphore sem is currently greater than 0. If the value of semaphore
+** sem is positive, it is decremented by one and the routine returns immediately
+** allowing the calling thread to continue. If the value of semaphore sem is 0,
+** the calling thread blocks awaiting the semaphore to be released by another
+** thread.
+**
+** This routine can return PR_PENDING_INTERRUPT if the waiting thread
+** has been interrupted.
+*/
+PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *sem)
+{
+ PRStatus status = PR_SUCCESS;
+
+#ifdef HAVE_CVAR_BUILT_ON_SEM
+ return _PR_MD_WAIT_SEM(&sem->md);
+#else
+ PR_Lock(sem->cvar->lock);
+ while (sem->count == 0) {
+ sem->waiters++;
+ status = PR_WaitCondVar(sem->cvar, PR_INTERVAL_NO_TIMEOUT);
+ sem->waiters--;
+ if (status != PR_SUCCESS)
+ break;
+ }
+ if (status == PR_SUCCESS)
+ sem->count--;
+ PR_Unlock(sem->cvar->lock);
+#endif
+
+ return (status);
+}
+
+/*
+** This routine increments the counter value of the semaphore. If other threads
+** are blocked for the semaphore, then the scheduler will determine which ONE
+** thread will be unblocked.
+*/
+PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *sem)
+{
+#ifdef HAVE_CVAR_BUILT_ON_SEM
+ _PR_MD_POST_SEM(&sem->md);
+#else
+ PR_Lock(sem->cvar->lock);
+ if (sem->waiters)
+ PR_NotifyCondVar(sem->cvar);
+ sem->count++;
+ PR_Unlock(sem->cvar->lock);
+#endif
+}
+
+#if DEBUG
+/*
+** Returns the value of the semaphore referenced by sem without affecting
+** the state of the semaphore. The value represents the semaphore vaule
+** at the time of the call, but may not be the actual value when the
+** caller inspects it. (FOR DEBUGGING ONLY)
+*/
+PR_IMPLEMENT(PRUintn) PR_GetValueSem(PRSemaphore *sem)
+{
+ PRUintn rv;
+
+#ifdef HAVE_CVAR_BUILT_ON_SEM
+ rv = _PR_MD_GET_VALUE_SEM(&sem->md);
+#else
+ PR_Lock(sem->cvar->lock);
+ rv = sem->count;
+ PR_Unlock(sem->cvar->lock);
+#endif
+
+ return rv;
+}
+#endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/threads/prtpd.c b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prtpd.c
new file mode 100644
index 00000000..168c6601
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/threads/prtpd.c
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Thread Private Data
+**
+** There is an aribitrary limit on the number of keys that will be allocated
+** by the runtime. It's largish, so it is intended to be a sanity check, not
+** an impediment.
+**
+** There is a counter, initialized to zero and incremented every time a
+** client asks for a new key, that holds the high water mark for keys. All
+** threads logically have the same high water mark and are permitted to
+** ask for TPD up to that key value.
+**
+** The vector to hold the TPD are allocated when PR_SetThreadPrivate() is
+** called. The size of the vector will be some value greater than or equal
+** to the current high water mark. Each thread has its own TPD length and
+** vector.
+**
+** Threads that get private data for keys they have not set (or perhaps
+** don't even exist for that thread) get a NULL return. If the key is
+** beyond the high water mark, an error will be returned.
+*/
+
+/*
+** As of this time, BeOS has its own TPD implementation. Integrating
+** this standard one is a TODO for anyone with a bit of spare time on
+** their hand. For now, we just #ifdef out this whole file and use
+** the routines in pr/src/btthreads/
+*/
+
+#ifndef XP_BEOS
+
+#include "primpl.h"
+
+#include <string.h>
+
+#if defined(WIN95)
+/*
+** Some local variables report warnings on Win95 because the code paths
+** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
+** The pragma suppresses the warning.
+**
+*/
+#pragma warning(disable : 4101)
+#endif
+
+#define _PR_TPD_LIMIT 128 /* arbitary limit on the TPD slots */
+static PRInt32 _pr_tpd_length = 0; /* current length of destructor vector */
+static PRInt32 _pr_tpd_highwater = 0; /* next TPD key to be assigned */
+static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL;
+ /* the destructors are associated with
+ the keys, therefore asserting that
+ the TPD key depicts the data's 'type' */
+
+/*
+** Initialize the thread private data manipulation
+*/
+void _PR_InitTPD(void)
+{
+ _pr_tpd_destructors = (PRThreadPrivateDTOR*)
+ PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*));
+ PR_ASSERT(NULL != _pr_tpd_destructors);
+ _pr_tpd_length = _PR_TPD_LIMIT;
+}
+
+/*
+** Clean up the thread private data manipulation
+*/
+void _PR_CleanupTPD(void)
+{
+} /* _PR_CleanupTPD */
+
+/*
+** This routine returns a new index for per-thread-private data table.
+** The index is visible to all threads within a process. This index can
+** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines
+** to save and retrieve data associated with the index for a thread.
+**
+** The index independently maintains specific values for each binding thread.
+** A thread can only get access to its own thread-specific-data.
+**
+** Upon a new index return the value associated with the index for all threads
+** is NULL, and upon thread creation the value associated with all indices for
+** that thread is NULL.
+**
+** "dtor" is the destructor function to invoke when the private
+** data is set or destroyed
+**
+** Returns PR_FAILURE if the total number of indices will exceed the maximun
+** allowed.
+*/
+
+PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex(
+ PRUintn *newIndex, PRThreadPrivateDTOR dtor)
+{
+ PRStatus rv;
+ PRInt32 index;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ PR_ASSERT(NULL != newIndex);
+ PR_ASSERT(NULL != _pr_tpd_destructors);
+
+ index = PR_AtomicIncrement(&_pr_tpd_highwater) - 1; /* allocate index */
+ if (_PR_TPD_LIMIT <= index)
+ {
+ PR_SetError(PR_TPD_RANGE_ERROR, 0);
+ rv = PR_FAILURE; /* that's just wrong */
+ }
+ else
+ {
+ _pr_tpd_destructors[index] = dtor; /* record destructor @index */
+ *newIndex = (PRUintn)index; /* copy into client's location */
+ rv = PR_SUCCESS; /* that's okay */
+ }
+
+ return rv;
+}
+
+/*
+** Define some per-thread-private data.
+** "index" is an index into the per-thread private data table
+** "priv" is the per-thread-private data
+**
+** If the per-thread private data table has a previously registered
+** destructor function and a non-NULL per-thread-private data value,
+** the destructor function is invoked.
+**
+** This can return PR_FAILURE if index is invalid (ie., beyond the current
+** high water mark) or memory is insufficient to allocate an exanded vector.
+*/
+
+PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv)
+{
+ PRThread *self = PR_GetCurrentThread();
+
+ /*
+ ** The index being set might not have a sufficient vector in this
+ ** thread. But if the index has been allocated, it's okay to go
+ ** ahead and extend this one now.
+ */
+ if ((index >= _PR_TPD_LIMIT) || (index >= _pr_tpd_highwater))
+ {
+ PR_SetError(PR_TPD_RANGE_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ PR_ASSERT(((NULL == self->privateData) && (0 == self->tpdLength))
+ || ((NULL != self->privateData) && (0 != self->tpdLength)));
+
+ if ((NULL == self->privateData) || (self->tpdLength <= index))
+ {
+ void *extension = PR_CALLOC(_pr_tpd_length * sizeof(void*));
+ if (NULL == extension)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return PR_FAILURE;
+ }
+ if (self->privateData) {
+ (void)memcpy(
+ extension, self->privateData,
+ self->tpdLength * sizeof(void*));
+ PR_DELETE(self->privateData);
+ }
+ self->tpdLength = _pr_tpd_length;
+ self->privateData = (void**)extension;
+ }
+ /*
+ ** There wasn't much chance of having to call the destructor
+ ** unless the slot already existed.
+ */
+ else if (self->privateData[index] && _pr_tpd_destructors[index])
+ {
+ void *data = self->privateData[index];
+ self->privateData[index] = NULL;
+ (*_pr_tpd_destructors[index])(data);
+ }
+
+ PR_ASSERT(index < self->tpdLength);
+ self->privateData[index] = priv;
+
+ return PR_SUCCESS;
+}
+
+/*
+** Recover the per-thread-private data for the current thread. "index" is
+** the index into the per-thread private data table.
+**
+** The returned value may be NULL which is indistinguishable from an error
+** condition.
+**
+*/
+
+PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn index)
+{
+ PRThread *self = PR_GetCurrentThread();
+ void *tpd = ((NULL == self->privateData) || (index >= self->tpdLength)) ?
+ NULL : self->privateData[index];
+
+ return tpd;
+}
+
+/*
+** Destroy the thread's private data, if any exists. This is called at
+** thread termination time only. There should be no threading issues
+** since this is being called by the thread itself.
+*/
+void _PR_DestroyThreadPrivate(PRThread* self)
+{
+#define _PR_TPD_DESTRUCTOR_ITERATIONS 4
+
+ if (NULL != self->privateData) /* we have some */
+ {
+ PRBool clean;
+ PRUint32 index;
+ PRInt32 passes = _PR_TPD_DESTRUCTOR_ITERATIONS;
+ PR_ASSERT(0 != self->tpdLength);
+ do
+ {
+ clean = PR_TRUE;
+ for (index = 0; index < self->tpdLength; ++index)
+ {
+ void *priv = self->privateData[index]; /* extract */
+ if (NULL != priv) /* we have data at this index */
+ {
+ if (NULL != _pr_tpd_destructors[index])
+ {
+ self->privateData[index] = NULL; /* precondition */
+ (*_pr_tpd_destructors[index])(priv); /* destroy */
+ clean = PR_FALSE; /* unknown side effects */
+ }
+ }
+ }
+ } while ((--passes > 0) && !clean); /* limit # of passes */
+ /*
+ ** We give up after a fixed number of passes. Any non-NULL
+ ** thread-private data value with a registered destructor
+ ** function is not destroyed.
+ */
+ memset(self->privateData, 0, self->tpdLength * sizeof(void*));
+ }
+} /* _PR_DestroyThreadPrivate */
+
+#endif /* !XP_BEOS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/tests/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/tests/Makefile.in
new file mode 100644
index 00000000..88f26e9d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/Makefile.in
@@ -0,0 +1,571 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+
+#! gmake
+
+MOD_DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+DIRS = dll
+
+CSRCS = \
+ accept.c \
+ acceptread.c \
+ acceptreademu.c \
+ addrstr.c \
+ affinity.c \
+ alarm.c \
+ anonfm.c \
+ append.c \
+ atomic.c \
+ attach.c \
+ bigfile.c \
+ bigfile2.c \
+ bigfile3.c \
+ cleanup.c \
+ cltsrv.c \
+ concur.c \
+ cvar.c \
+ cvar2.c \
+ dceemu.c \
+ dlltest.c \
+ dtoa.c \
+ env.c \
+ errcodes.c \
+ errset.c \
+ exit.c \
+ fdcach.c \
+ fileio.c \
+ foreign.c \
+ forktest.c \
+ formattm.c \
+ fsync.c \
+ getai.c \
+ gethost.c \
+ getproto.c \
+ i2l.c \
+ initclk.c \
+ inrval.c \
+ instrumt.c \
+ intrio.c \
+ intrupt.c \
+ io_timeout.c \
+ ioconthr.c \
+ ipv6.c \
+ join.c \
+ joinkk.c \
+ joinku.c \
+ joinuk.c \
+ joinuu.c \
+ layer.c \
+ lazyinit.c \
+ libfilename.c \
+ lltest.c \
+ lock.c \
+ lockfile.c \
+ logger.c \
+ makedir.c \
+ mbcs.c \
+ multiacc.c \
+ multiwait.c \
+ many_cv.c \
+ nameshm1.c \
+ nbconn.c \
+ nblayer.c \
+ nonblock.c \
+ ntioto.c \
+ ntoh.c \
+ obsints.c \
+ op_2long.c \
+ op_excl.c \
+ op_filnf.c \
+ op_filok.c \
+ op_noacc.c \
+ op_nofil.c \
+ openfile.c \
+ parent.c \
+ peek.c \
+ perf.c \
+ pipeping.c \
+ pipeping2.c \
+ pipepong.c \
+ pipepong2.c \
+ pipeself.c \
+ poll_er.c \
+ poll_nm.c \
+ poll_to.c \
+ pollable.c \
+ prftest.c \
+ prftest1.c \
+ prftest2.c \
+ primblok.c \
+ priotest.c \
+ provider.c \
+ prpoll.c \
+ prpollml.c \
+ ranfile.c \
+ randseed.c \
+ rmdir.c \
+ rwlocktest.c \
+ sel_spd.c \
+ selct_er.c \
+ selct_nm.c \
+ selct_to.c \
+ select2.c \
+ selintr.c \
+ sem.c \
+ sema.c \
+ semaerr.c \
+ semaerr1.c \
+ semaping.c \
+ semapong.c \
+ sendzlf.c \
+ server_test.c \
+ servr_kk.c \
+ servr_ku.c \
+ servr_uk.c \
+ servr_uu.c \
+ short_thread.c \
+ sigpipe.c \
+ socket.c \
+ sockopt.c \
+ sockping.c \
+ sockpong.c \
+ sprintf.c \
+ sproc_ch.c \
+ sproc_p.c \
+ stack.c \
+ stdio.c \
+ str2addr.c \
+ strod.c \
+ suspend.c \
+ switch.c \
+ system.c \
+ testbit.c \
+ testfile.c \
+ thrpool_server.c \
+ thrpool_client.c \
+ threads.c \
+ thruput.c \
+ timemac.c \
+ timetest.c \
+ tmoacc.c \
+ tmocon.c \
+ tpd.c \
+ vercheck.c \
+ version.c \
+ udpsrv.c \
+ writev.c \
+ xnotify.c \
+ y2k.c \
+ y2ktmo.c \
+ zerolen.c \
+ $(NULL)
+
+ifeq ($(OS_TARGET),OS2)
+CSRCS += \
+ sleep.c \
+ stat.c \
+ yield.c \
+ $(NULL)
+endif
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS)
+
+INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private
+
+ifeq ($(OS_ARCH), WINNT)
+ifdef NS_USE_GCC
+ EXTRA_LIBS += -lwsock32
+else
+ EXTRA_LIBS += wsock32.lib
+ LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+ ifdef PROFILE
+ LDOPTS += -PROFILE -MAP
+ endif # profile
+endif # NS_USE_GCC
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO
+else
+ EXTRA_LIBS = $(OS_LIBS)
+ LDOPTS = -Zomf -Zlinker /PM:VIO -Zlinker /ST:0x64000
+endif
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+# Use an absolute pathname as the runtime library path (for the -R
+# or -rpath linker option or the LD_RUN_PATH environment variable).
+ifeq (,$(patsubst /%,,$(DIST)))
+# $(DIST) is already an absolute pathname.
+ABSOLUTE_LIB_DIR = $(dist_libdir)
+else
+# $(DIST) is a relative pathname: prepend the current directory.
+PWD = $(shell pwd)
+ABSOLUTE_LIB_DIR = $(PWD)/$(dist_libdir)
+endif
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+ ifeq ($(USE_CPLUS), 1)
+ CC = CC
+ endif
+ LDOPTS += -rpath $(ABSOLUTE_LIB_DIR)
+ ifdef NS_USE_GCC
+ LDOPTS += -Wl,-rdata_shared
+ else
+ LDOPTS += -rdata_shared
+ endif
+# For 6.x machines, include this flag
+ ifeq ($(basename $(OS_RELEASE)),6)
+ ifndef NS_USE_GCC
+ ifeq ($(USE_N32),1)
+ LDOPTS += -n32
+ else
+ LDOPTS += -32
+ endif
+
+ ifeq ($(USE_PTHREADS), 1)
+ ifeq ($(OS_RELEASE), 6.2)
+ LDOPTS += -Wl,-woff,85
+ endif
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), OSF1)
+ ifeq ($(USE_CPLUS), 1)
+ CC = cxx
+ endif
+# I haven't figured out how to pass -rpath to cc on OSF1 V3.2, so
+# we do static linking.
+ ifeq (,$(filter-out V2.0 V3.2,$(OS_RELEASE)))
+ LIBNSPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ LIBPLC = $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).a
+ EXTRA_LIBS = -lc_r
+ else
+ LDOPTS += -rpath $(ABSOLUTE_LIB_DIR)
+ endif
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+ LDOPTS += -z -Wl,+s,+b,$(ABSOLUTE_LIB_DIR)
+ ifeq ($(USE_64),1)
+ LDOPTS += +DD64
+ endif
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = $(LIBPTHREAD)
+ endif
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+ LDOPTS += -blibpath:$(ABSOLUTE_LIB_DIR):/usr/lib:/lib
+ ifneq ($(OS_ARCH)$(OS_RELEASE),AIX4.1)
+ LDOPTS += -brtl
+ EXTRA_LIBS = -ldl
+ endif
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ ifneq ($(OS_RELEASE), 4.1.3_U1)
+ ifdef NS_USE_GCC
+ LDOPTS += -Xlinker -R -Xlinker $(ABSOLUTE_LIB_DIR)
+ else
+ ifeq ($(USE_CPLUS), 1)
+ CC = CC
+ endif
+ LDOPTS += -R $(ABSOLUTE_LIB_DIR)
+ endif
+ endif
+
+ ifneq ($(LOCAL_THREADS_ONLY),1)
+ ifdef USE_PTHREADS
+ EXTRA_LIBS = -lpthread -lthread
+ else
+ EXTRA_LIBS = -lthread
+ endif
+ endif # LOCAL_THREADS_ONLY
+endif # SunOS
+
+ifeq ($(OS_ARCH), NEC)
+ EXTRA_LIBS = $(OS_LIBS)
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+ export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+endif
+
+ifeq ($(OS_ARCH), NCR)
+# NCR needs to link against -lsocket -lnsl -ldl (and -lc, which is
+# linked implicitly by $(CC)). Note that we did not link with these
+# system libraries when we built libnspr.so.
+ EXTRA_LIBS = -lsocket -lnsl -ldl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+ export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+endif
+
+ifeq ($(OS_ARCH), NEXTSTEP)
+# balazs.pataki@sztaki.hu: linkage is done in a different pass in the `tests'
+# modeul, so we have to pass the `-posix' flag by "hand" to `ld'
+LDOPTS += -posix
+endif
+
+ifeq ($(OS_ARCH), NEWS-OS)
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+#export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+ LIBNSPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ LIBPLC = $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).a
+ EXTRA_LIBS = -lsocket -lnsl -lgen -lresolv
+endif
+
+ifeq ($(OS_ARCH), Linux)
+ ifeq ($(OS_RELEASE), 1.2)
+ EXTRA_LIBS = -ldl
+ else
+ LDOPTS += -Xlinker -rpath $(ABSOLUTE_LIB_DIR)
+ ifeq ($(USE_PTHREADS),1)
+ EXTRA_LIBS = -lpthread
+ endif
+ endif
+endif
+
+ifeq ($(OS_ARCH), SCOOS)
+# SCO Unix needs to link against -lsocket again even though we
+# already linked with these system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+endif
+
+ifeq ($(OS_ARCH),SINIX)
+EXTRA_LIBS = -lsocket -lnsl -lresolv -ldl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+endif
+
+ifeq ($(OS_ARCH),OpenUNIX)
+export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+ifeq ($(USE_PTHREADS),1)
+LDOPTS += -pthread
+endif
+endif
+
+ifeq ($(OS_ARCH), UNIXWARE)
+export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR)
+endif
+
+ifeq ($(OS_ARCH),FreeBSD)
+ifeq ($(USE_PTHREADS),1)
+LDOPTS += -pthread
+endif
+LDOPTS += -Xlinker -R $(ABSOLUTE_LIB_DIR)
+endif
+
+ifeq ($(OS_ARCH),OpenBSD)
+ifeq ($(USE_PTHREADS),1)
+LDOPTS += -pthread
+endif
+endif
+
+ifeq ($(OS_ARCH),BSD_OS)
+ifneq ($(OS_RELEASE),1.1)
+EXTRA_LIBS = -ldl
+endif
+endif
+
+ifeq ($(USE_PTHREADS),1)
+LIBPTHREAD = -lpthread
+ifeq ($(OS_ARCH),AIX)
+LIBPTHREAD = -lpthreads
+endif
+ifeq (,$(filter-out FreeBSD OpenBSD BSD_OS QNX Darwin OpenUNIX,$(OS_ARCH)))
+LIBPTHREAD =
+endif
+ifeq ($(OS_ARCH)$(basename $(OS_RELEASE)),HP-UXB.10)
+LIBPTHREAD = -ldce
+endif
+endif
+
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifeq ($(OS_RELEASE),4.1)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT)
+ link $(LDOPTS) $(EXTRA_LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) -out:$@
+else
+ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ $(LD) $(EXEFLAGS) $(LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) -o $@
+endif # OS/2
+endif # WINNT
+endif # AIX_PRE_4_2
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
+
+# The following tests call BSD socket functions, so they need to link
+# with -lsocket on some platforms.
+ifeq ($(OS_ARCH),SunOS)
+ifneq ($(OS_RELEASE),4.1.3_U1)
+ifeq ($(USE_IPV6),1)
+$(OBJDIR)/gethost: $(OBJDIR)/gethost.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) -lsocket $(EXTRA_LIBS) -o $@
+endif
+$(OBJDIR)/prpoll: $(OBJDIR)/prpoll.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) -lsocket $(EXTRA_LIBS) -o $@
+endif
+endif
+
+ifeq ($(USE_PTHREADS), 1)
+$(OBJDIR)/attach: $(OBJDIR)/attach.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+$(OBJDIR)/foreign: $(OBJDIR)/foreign.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+$(OBJDIR)/provider: $(OBJDIR)/provider.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+$(OBJDIR)/socket: $(OBJDIR)/socket.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+$(OBJDIR)/testfile: $(OBJDIR)/testfile.o
+ $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@
+endif
+
+#
+# Run the test programs with no arguments
+#
+# Test output goes to the file pointed to by the environment variable
+# NSPR_TEST_LOGFILE, if set, else to /dev/null
+#
+ECHO = echo
+PROGRAMS = $(notdir $(PROGS))
+ifdef NSPR_TEST_LOGFILE
+LOGFILE = $(NSPR_TEST_LOGFILE)
+else
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+LOGFILE = nul
+else
+LOGFILE = /dev/null
+endif
+endif
+
+ifeq ($(OS_TARGET),Linux)
+ECHO = /bin/echo
+endif
+
+ALWAYS:
+
+runtests:: $(PROGS) ALWAYS
+ @$(ECHO) "\nNSPR Test Results - $(OBJDIR)\n"
+ @$(ECHO) "BEGIN\t\t\t`date`"
+ @$(ECHO) "NSPR_TEST_LOGFILE\t$(LOGFILE)\n"
+ @$(ECHO) "Test\t\t\tResult\n"
+ @cd $(OBJDIR); for i in $(PROGRAMS); do \
+ $(ECHO) "$$i\c"; \
+ ./$$i >> $(LOGFILE) 2>&1 ; \
+ if [ 0 = $$? ] ; then \
+ $(ECHO) "\t\t\tPassed"; \
+ else \
+ $(ECHO) "\t\t\tFAILED"; \
+ fi; \
+ done
+ @$(ECHO) "\nEND\t\t`date`\n"
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/README.TXT b/src/libs/xpcom18a4/nsprpub/pr/tests/README.TXT
new file mode 100644
index 00000000..eeb1dd0d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/README.TXT
@@ -0,0 +1,434 @@
+File: pr/tests/readme
+
+This document describes the test cases in the NSPR directory
+pr/tests.
+
+=====================================================================
+There are some sub-directories here:
+
+dll
+ sources for the .dll(.so) used by test dlltest.c
+
+macbuild
+ MacIntosh project files
+
+server
+ an empty directory. Does anyone remember why?
+
+w16gui
+ Sources for a modified version of the poppad application from
+ Charles Petzold's book "Programming Windows 3.1". These
+ sources were modified to test the library lib/ds/PLEvent.
+ These files are obsolete and will not be maintained.
+
+ This test was superceded by lib/tests/windows/winevent.c and
+ lib/event.c and is now owned by CPD.
+
+=====================================================================
+The individual files are described here.
+
+The script 'runtests.ksh' enumerates and runs test cases that are
+expected to run on all platforms.
+
+
+accept.c
+ Tests PR_Accept() and related socket functions.
+
+acceptread.c
+ Tests PR_AcceptRead()
+
+alarm.c
+ Tests alarm functions declared in obsolete/pralarm.h.
+ The alarm functions are obsolete, so is this test.
+
+atomic.c
+ Tests Atomic operations defined in pratom.h
+
+attach.c
+ Test PR_AttachThread()
+ Note: This is an NSPR private function.
+
+bigfile.c
+ Test 64bit file offset functions declared in prio.h
+
+bug1test.c
+ Demonstrates a bug on NT.
+
+cleanup.c
+ Tests PR_Cleanup() declared in prinit.h
+
+cltsrv.c
+ Tests many socket functions.
+
+concur.c
+ Tests threading functions and concurrent operations.
+
+cvar.c
+ Tests condition variables.
+
+cvar2.c
+ Tests condition variables. A rather abusive test.
+
+dbmalloc.c
+ Obsolete. Originally for testing debug builds of NSPR's malloc.
+
+dbmalloc1.c
+ Obsolete. Originally for testing debug builds of NSPR's malloc.
+
+dceemu.c
+ Tests special functions for DCE emulation.
+
+depend.c
+ Obsoltet. Tests early spec for library dependency.
+
+dlltest.c
+ Tests dynamic library fucntions. Used with dll/my.c
+
+dtoa.c
+ Tests conversions of double to string.
+
+exit.c
+ Tests PR_ProcessExit() declared in prinit.h
+
+fileio.c
+ Tests NSPR semaphores a bit of file i/o and threading
+ functions.
+
+foreign.c
+ Test auto-attach of a thread created by something other than
+ NSPR.
+
+forktest.c
+ Limited use. Tests unix fork() and related functions.
+
+fsync.c
+ Tests use of PR_Sync() declared in prio.h
+
+getproto.c
+ Tests socket functions PR_GetProtoByName(), etc.
+
+i2l.c
+ Tests LongLong functions for converting 32bit integer to 64bit
+ integer.
+
+initclk.c
+ Tests timing on minimal use of condition variable
+
+inrval.c
+ Tests interval timing functions.
+
+instrumt.c
+ Tests instrumentation functions. prcountr.h prtrace.h
+
+intrupt.c
+ Tests PR_Interrupt()
+
+ioconthr.c
+ Tests i/o continuation mechanism in pthreads.
+
+io_timeout.c
+ Test socket i/o timeouts.
+
+io_timeoutk.c
+ Obsolete. Subsumed in io_timeout.c
+
+io_timeoutu.c
+ Obsolete. Subsumed in io_timeout.c
+
+ipv6.c
+ Tests IPv6. IPv6 is not used by NSPR clients.
+
+join.c
+ Tests PR_JoinThread()
+
+joinkk.c
+ Tests PR_JoinThread()
+
+joinku.c
+ Tests PR_JoinThread()
+
+joinuk.c
+ Tests PR_JoinThread()
+
+joinuu.c
+ Tests PR_JoinThread()
+
+layer.c
+ Tests layered I/O.
+
+lazyinit.c
+ Tests implicit initialization.
+
+lltest.c
+ Tests LongLong (64bit integer) arithmentic and conversions.
+
+lock.c
+ Tests PR_Lock() in heavily threaded environment.
+
+lockfile.c
+ Test PR_Lockfile().
+
+logger.c
+ Tests PR_LOG()
+
+makefile
+ The makefile that builds all the tests
+
+many_cv.c
+ Tests aquiring a large number of condition variables.
+
+multiwait.c
+ ???
+
+nbconn.c
+ Test non-blocking connect.
+
+nblayer.c
+ Tests NSPR's layered I/O capability.
+
+nonblock.c
+ Tests operations on non-blocking socket.
+
+op_2long.c
+ Tests PR_Open() where filename is too long.
+
+op_filnf.c
+ Tests PR_Open() where filename is NotFound.
+
+op_filok.c
+ Tests PR_Open() where filename is accessable.
+
+op_noacc.c
+ Tests PR_Open() where file permissions are wrong.
+ Limited use. Windows has no concept of Unix style file permissions.
+
+op_nofil.c
+ Tests PR_Open() where filename does not exist.
+
+parent.c
+ Test parent/child process capability
+
+perf.c
+ Tests and measures context switch times for various thread
+ syncronization functions.
+
+pipeping.c
+ Tests inter-process pipes. Run with pipepong.c
+
+pipepong.c
+ Tests inter-process pipes. Run with pipeping.c
+
+pipeself.c
+ Tests inter-thread pipes.
+
+pollable.c
+ Tests pollable events. prio.h
+
+poll_er.c
+ Tests PR_Poll() where an error is expected.
+
+poll_nm.c
+ Tests PR_Poll() where normal operation is expected.
+
+poll_to.c
+ Tests PR_Poll() where timeout is expected.
+
+prftest.c
+ Tests printf-like formatting.
+
+prftest1.c
+ Obsolete. Subsumed in prftest.c
+
+prftest2.c
+ Obsolete. Subsumed in prftest.c
+
+priotest.c
+ Limited use. Tests NSPR thread dispatching priority.
+
+provider.c
+
+prpoll.c
+ Tests PR_Poll().
+
+prselect.c
+ Obsolete. PR_Select() is obsolete.
+
+prttools.h
+ Unused file.
+
+ranfile.c
+ Tests random file access.
+
+readme
+ This file.
+
+runtests.ksh
+ A korn shell script that runs a set of tests that should run
+ on any of the NSPR supported platforms.
+
+runtests.pl
+ A perl script to run the test cases. This srcipt runs tests
+ common to all platforms and runs tests applicable to specific
+ platforms. Uses file runtests.txt to control execution.
+
+runtests.txt
+ Control file for perl script: runtests.pl
+
+rwlocktest.c
+ Tests Reader/Writer lock
+
+selct_er.c
+ Obsolete. PR_Select() is obsolete.
+
+selct_nm.c
+ Obsolete. PR_Select() is obsolete.
+
+selct_to.c
+ Obsolete. PR_Select() is obsolete.
+
+select2.c
+ Obsolete. PR_Select() is obsolete.
+
+sel_spd.c
+ Obsolete. PR_Select() is obsolete.
+
+sem.c
+ Obsolete. Semaphores are not supported.
+
+server_test.c
+ Tests sockets by simulating a server in loopback mode.
+ Makes its own client threads.
+
+servr_kk.c
+ Tests client/server sockets, threads using system threads.
+
+servr_ku.c
+ Tests client/server sockets, threads using system and user threads.
+
+servr_uk.c
+ Tests client/server sockets, threads using system and user threads.
+
+servr_uu.c
+ Tests client/server sockets, threads user threads.
+
+short_thread.c
+ Tests short-running threads. Useful for testing for race conditions.
+
+sigpipe.c
+ Tests NSPR's SIGPIPE handler. Unix only.
+
+sleep.c
+ Limited use. Tests sleep capability of platform.
+
+socket.c
+ Tests many socket functions.
+
+sockopt.c
+ Tests setting and getting socket options.
+
+sprintf.c
+ Tests sprintf.
+
+sproc_ch.c
+ Obsolete. Tests IRIX sproc-based threads.
+
+sproc_p.c
+ Obsolete. Tests IRIX sproc-based threads.
+
+stack.c
+ Test atomic stack operations.
+
+stat.c
+ Tests performance of getfileinfo() vs. stat()
+
+stdio.c
+ Tests NSPR's handling of stdin, stdout, stderr.
+
+strod.c
+ Tests formatting of double precision floating point.
+
+suspend.c
+ Private interfaces PR_SuspendAll(), PR_ResumeAll(), etc.
+
+switch.c
+ Tests thread switching
+
+system.c
+ Tests PR_GetSystemInfo()
+
+testbit.c
+ Tests bit arrays.
+
+testfile.c
+ Tests many file I/O functions.
+
+threads.c
+ Tests thread caching.
+
+thruput.c
+ Tests socket thruput. Must be run by hand as client/server.
+ Does not self terminate.
+
+time.c
+ Incomplete. Limited use.
+
+timemac.c
+ Test time and date functions. Originally for Mac.
+
+timetest.c
+ Tests time conversion over a wide range of dates.
+
+tmoacc.c
+ Server to tmocon.c and writev.c
+ Do not run it by itself.
+
+tmocon.c
+ Client thread to tmoacc.c
+
+tpd.c
+ Tests thread private data.
+
+udpsrv.c
+ Tests UDP socket functions.
+
+ut_ttools.h
+ unused file.
+
+version.c
+ Extract and print library version data.
+
+vercheck.c
+ Test PR_VersionCheck().
+
+writev.c
+ Tests gather-write on a socket. Requires tmoacc.c
+
+xnotify.c
+ Tests cached monitors.
+
+yield.c
+ Limited use
+
+y2k.c
+ Test to verify NSPR's date functions as Y2K compliant.
+
+dll\Makefile
+ makefile for mygetval.c, mysetval.c
+
+dll\mygetval.c
+ Dynamic library test. See also dlltest.c
+
+dll\mysetval.c
+ Dynamic library test. See also dlltest.c
+
+w16gui\Makefile
+ Obsolete. Tests for lib/ds/PLEvent on Windows 3.1.
+w16gui\popfile.c
+w16gui\popfind.c
+w16gui\popfont.c
+w16gui\poppad.c
+w16gui\poppad.h
+w16gui\poppad.ico
+w16gui\poppad.rc
+w16gui\popprnt0.c
+w16gui\readme.1st
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/accept.c b/src/libs/xpcom18a4/nsprpub/pr/tests/accept.c
new file mode 100644
index 00000000..4fada1aa
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/accept.c
@@ -0,0 +1,524 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1996 - Netscape Communications Corporation
+**
+** Name: accept.c
+**
+** Description: Run accept() sucessful connection tests.
+**
+** Modification History:
+** 04-Jun-97 AGarcia - Reconvert test file to return a 0 for PASS and a 1 for FAIL
+** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 Revert to return code 0 and 1.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+
+#include "nspr.h"
+#include "prpriv.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "plgetopt.h"
+#include "plerror.h"
+
+#define BASE_PORT 10000
+
+#define CLIENT_DATA 128
+
+#define ACCEPT_NORMAL 0x1
+#define ACCEPT_FAST 0x2
+#define ACCEPT_READ 0x3
+#define ACCEPT_READ_FAST 0x4
+#define ACCEPT_READ_FAST_CB 0x5
+
+#define CLIENT_NORMAL 0x1
+#define CLIENT_TIMEOUT_ACCEPT 0x2
+#define CLIENT_TIMEOUT_SEND 0x3
+
+#define SERVER_MAX_BIND_COUNT 100
+
+#if defined(XP_MAC) || defined(XP_OS2)
+#define TIMEOUTSECS 10
+#else
+#define TIMEOUTSECS 2
+#endif
+PRIntervalTime timeoutTime;
+
+static PRInt32 count = 1;
+static PRFileDesc *output;
+static PRNetAddr serverAddr;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+static PRInt32 clientCommand;
+static PRInt32 iterations;
+static PRStatus rv;
+static PRFileDesc *listenSock;
+static PRFileDesc *clientSock = NULL;
+static PRNetAddr listenAddr;
+static PRNetAddr clientAddr;
+static PRThread *clientThread;
+static PRNetAddr *raddr;
+static char buf[4096 + 2*sizeof(PRNetAddr) + 32];
+static PRInt32 status;
+static PRInt32 bytesRead;
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+void Test_Assert(const char *msg, const char *file, PRIntn line)
+{
+ failed_already=1;
+ if (debug_mode) {
+ PR_fprintf(output, "@%s:%d ", file, line);
+ PR_fprintf(output, msg);
+ }
+} /* Test_Assert */
+
+#define TEST_ASSERT(expr) \
+ if (!(expr)) Test_Assert(#expr, __FILE__, __LINE__)
+
+#ifdef WINNT
+#define CALLBACK_MAGIC 0x12345678
+
+void timeout_callback(void *magic)
+{
+ TEST_ASSERT(magic == (void *)CALLBACK_MAGIC);
+ if (debug_mode)
+ PR_fprintf(output, "timeout callback called okay\n");
+}
+#endif
+
+
+static void PR_CALLBACK
+ClientThread(void *_action)
+{
+ PRInt32 action = * (PRInt32 *) _action;
+ PRInt32 iterations = count;
+ PRFileDesc *sock = NULL;
+
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = listenAddr.inet.port;
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+
+ for (; iterations--;) {
+ PRInt32 rv;
+ char buf[CLIENT_DATA];
+
+ memset(buf, 0xaf, sizeof(buf)); /* initialize with arbitrary data */
+ sock = PR_NewTCPSocket();
+ if (!sock) {
+ if (!debug_mode)
+ failed_already=1;
+ else
+ PR_fprintf(output, "client: unable to create socket\n");
+ return;
+ }
+
+ if (action != CLIENT_TIMEOUT_ACCEPT) {
+
+ if ((rv = PR_Connect(sock, &serverAddr,
+ timeoutTime)) < 0) {
+ if (!debug_mode)
+ failed_already=1;
+ else
+ PR_fprintf(output,
+ "client: unable to connect to server (%ld, %ld, %ld, %ld)\n",
+ iterations, rv, PR_GetError(), PR_GetOSError());
+ goto ErrorExit;
+ }
+
+ if (action != CLIENT_TIMEOUT_SEND) {
+ if ((rv = PR_Send(sock, buf, CLIENT_DATA,
+ 0, timeoutTime))< 0) {
+ if (!debug_mode)
+ failed_already=1;
+ else
+ PR_fprintf(output,
+ "client: unable to send to server (%d, %ld, %ld)\n",
+ CLIENT_DATA, rv, PR_GetError());
+ goto ErrorExit;
+ }
+ } else {
+ PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
+ }
+ } else {
+ PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1));
+ }
+ if (debug_mode)
+ PR_fprintf(output, ".");
+ PR_Close(sock);
+ sock = NULL;
+ }
+ if (debug_mode)
+ PR_fprintf(output, "\n");
+
+ErrorExit:
+ if (sock != NULL)
+ PR_Close(sock);
+}
+
+
+static void
+RunTest(PRInt32 acceptType, PRInt32 clientAction)
+{
+int i;
+
+ /* First bind to the socket */
+ listenSock = PR_NewTCPSocket();
+ if (!listenSock) {
+ failed_already=1;
+ if (debug_mode)
+ PR_fprintf(output, "unable to create listen socket\n");
+ return;
+ }
+ memset(&listenAddr, 0 , sizeof(listenAddr));
+ listenAddr.inet.family = PR_AF_INET;
+ listenAddr.inet.port = PR_htons(BASE_PORT);
+ listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(listenSock, &listenAddr) == PR_FAILURE) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ listenAddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ failed_already=1;
+ if (debug_mode)
+ PR_fprintf(output,"accept: ERROR - PR_Bind failed\n");
+ return;
+ }
+
+
+ rv = PR_Listen(listenSock, 100);
+ if (rv == PR_FAILURE) {
+ failed_already=1;
+ if (debug_mode)
+ PR_fprintf(output, "unable to listen\n");
+ return;
+ }
+
+ clientCommand = clientAction;
+ clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread,
+ (void *)&clientCommand, PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 0);
+ if (!clientThread) {
+ failed_already=1;
+ if (debug_mode)
+ PR_fprintf(output, "error creating client thread\n");
+ return;
+ }
+
+ iterations = count;
+ for (;iterations--;) {
+ switch (acceptType) {
+ case ACCEPT_NORMAL:
+ clientSock = PR_Accept(listenSock, &clientAddr,
+ timeoutTime);
+ switch(clientAction) {
+ case CLIENT_TIMEOUT_ACCEPT:
+ TEST_ASSERT(clientSock == 0);
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ case CLIENT_NORMAL:
+ TEST_ASSERT(clientSock);
+ bytesRead = PR_Recv(clientSock,
+ buf, CLIENT_DATA, 0, timeoutTime);
+ TEST_ASSERT(bytesRead == CLIENT_DATA);
+ break;
+ case CLIENT_TIMEOUT_SEND:
+ TEST_ASSERT(clientSock);
+ bytesRead = PR_Recv(clientSock,
+ buf, CLIENT_DATA, 0, timeoutTime);
+ TEST_ASSERT(bytesRead == -1);
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ }
+ break;
+ case ACCEPT_READ:
+ status = PR_AcceptRead(listenSock, &clientSock,
+ &raddr, buf, CLIENT_DATA, timeoutTime);
+ switch(clientAction) {
+ case CLIENT_TIMEOUT_ACCEPT:
+ /* Invalid test case */
+ TEST_ASSERT(0);
+ break;
+ case CLIENT_NORMAL:
+ TEST_ASSERT(clientSock);
+ TEST_ASSERT(status == CLIENT_DATA);
+ break;
+ case CLIENT_TIMEOUT_SEND:
+ TEST_ASSERT(status == -1);
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ }
+ break;
+#ifdef WINNT
+ case ACCEPT_FAST:
+ clientSock = PR_NTFast_Accept(listenSock,
+ &clientAddr, timeoutTime);
+ switch(clientAction) {
+ case CLIENT_TIMEOUT_ACCEPT:
+ TEST_ASSERT(clientSock == 0);
+ if (debug_mode)
+ PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError());
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ case CLIENT_NORMAL:
+ TEST_ASSERT(clientSock);
+ bytesRead = PR_Recv(clientSock,
+ buf, CLIENT_DATA, 0, timeoutTime);
+ TEST_ASSERT(bytesRead == CLIENT_DATA);
+ break;
+ case CLIENT_TIMEOUT_SEND:
+ TEST_ASSERT(clientSock);
+ bytesRead = PR_Recv(clientSock,
+ buf, CLIENT_DATA, 0, timeoutTime);
+ TEST_ASSERT(bytesRead == -1);
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ }
+ break;
+ break;
+ case ACCEPT_READ_FAST:
+ status = PR_NTFast_AcceptRead(listenSock,
+ &clientSock, &raddr, buf, 4096, timeoutTime);
+ switch(clientAction) {
+ case CLIENT_TIMEOUT_ACCEPT:
+ /* Invalid test case */
+ TEST_ASSERT(0);
+ break;
+ case CLIENT_NORMAL:
+ TEST_ASSERT(clientSock);
+ TEST_ASSERT(status == CLIENT_DATA);
+ break;
+ case CLIENT_TIMEOUT_SEND:
+ TEST_ASSERT(clientSock == NULL);
+ TEST_ASSERT(status == -1);
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ }
+ break;
+ case ACCEPT_READ_FAST_CB:
+ status = PR_NTFast_AcceptRead_WithTimeoutCallback(
+ listenSock, &clientSock, &raddr, buf, 4096,
+ timeoutTime, timeout_callback, (void *)CALLBACK_MAGIC);
+ switch(clientAction) {
+ case CLIENT_TIMEOUT_ACCEPT:
+ /* Invalid test case */
+ TEST_ASSERT(0);
+ break;
+ case CLIENT_NORMAL:
+ TEST_ASSERT(clientSock);
+ TEST_ASSERT(status == CLIENT_DATA);
+ break;
+ case CLIENT_TIMEOUT_SEND:
+ if (debug_mode)
+ PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock);
+ TEST_ASSERT(clientSock == NULL);
+ TEST_ASSERT(status == -1);
+ TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR);
+ break;
+ }
+ break;
+#endif
+ }
+ if (clientSock != NULL) {
+ PR_Close(clientSock);
+ clientSock = NULL;
+ }
+ }
+ PR_Close(listenSock);
+
+ PR_JoinThread(clientThread);
+}
+
+
+void AcceptUpdatedTest(void)
+{
+ RunTest(ACCEPT_NORMAL, CLIENT_NORMAL);
+}
+void AcceptNotUpdatedTest(void)
+{
+ RunTest(ACCEPT_FAST, CLIENT_NORMAL);
+}
+void AcceptReadTest(void)
+{
+ RunTest(ACCEPT_READ, CLIENT_NORMAL);
+}
+void AcceptReadNotUpdatedTest(void)
+{
+ RunTest(ACCEPT_READ_FAST, CLIENT_NORMAL);
+}
+void AcceptReadCallbackTest(void)
+{
+ RunTest(ACCEPT_READ_FAST_CB, CLIENT_NORMAL);
+}
+
+void TimeoutAcceptUpdatedTest(void)
+{
+ RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_ACCEPT);
+}
+void TimeoutAcceptNotUpdatedTest(void)
+{
+ RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_ACCEPT);
+}
+void TimeoutAcceptReadCallbackTest(void)
+{
+ RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_ACCEPT);
+}
+
+void TimeoutReadUpdatedTest(void)
+{
+ RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_SEND);
+}
+void TimeoutReadNotUpdatedTest(void)
+{
+ RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_SEND);
+}
+void TimeoutReadReadTest(void)
+{
+ RunTest(ACCEPT_READ, CLIENT_TIMEOUT_SEND);
+}
+void TimeoutReadReadNotUpdatedTest(void)
+{
+ RunTest(ACCEPT_READ_FAST, CLIENT_TIMEOUT_SEND);
+}
+void TimeoutReadReadCallbackTest(void)
+{
+ RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_SEND);
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+ if (debug_mode)
+ PR_fprintf(output, "%40s: %6.2f usec\n", msg, d / count);
+
+}
+
+int main(int argc, char **argv)
+{
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name [-d] [-c n]
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Gdc:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'c': /* loop counter */
+ count = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ output = PR_STDERR;
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("accept.log");
+ debug_mode = 1;
+#endif
+
+ timeoutTime = PR_SecondsToInterval(TIMEOUTSECS);
+ if (debug_mode)
+ PR_fprintf(output, "\nRun accept() sucessful connection tests\n");
+
+ Measure(AcceptUpdatedTest, "PR_Accept()");
+ Measure(AcceptReadTest, "PR_AcceptRead()");
+#ifdef WINNT
+ Measure(AcceptNotUpdatedTest, "PR_NTFast_Accept()");
+ Measure(AcceptReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
+ Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
+#endif
+ if (debug_mode)
+ PR_fprintf(output, "\nRun accept() timeout in the accept tests\n");
+#ifdef WINNT
+ Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
+#endif
+ Measure(TimeoutReadUpdatedTest, "PR_Accept()");
+ if (debug_mode)
+ PR_fprintf(output, "\nRun accept() timeout in the read tests\n");
+ Measure(TimeoutReadReadTest, "PR_AcceptRead()");
+#ifdef WINNT
+ Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()");
+ Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()");
+ Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()");
+#endif
+ PR_fprintf(output, "%s\n", (failed_already) ? "FAIL" : "PASS");
+ return failed_already;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/acceptread.c b/src/libs/xpcom18a4/nsprpub/pr/tests/acceptread.c
new file mode 100644
index 00000000..ceb445d0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/acceptread.c
@@ -0,0 +1,272 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <prio.h>
+#include <prprf.h>
+#include <prinit.h>
+#include <prnetdb.h>
+#include <prinrval.h>
+#include <prthread.h>
+
+#include <plerror.h>
+
+#include <stdlib.h>
+
+#define DEFAULT_PORT 12273
+#define GET "GET / HTTP/1.0\n\n"
+static PRFileDesc *std_out, *err_out;
+static PRIntervalTime write_dally, accept_timeout;
+
+static PRStatus PrintAddress(const PRNetAddr* address)
+{
+ char buffer[100];
+ PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
+ if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
+ else PR_fprintf(
+ std_out, "Accepted connection from (0x%p)%s:%d\n",
+ address, buffer, address->inet.port);
+ return rv;
+} /* PrintAddress */
+
+static void ConnectingThread(void *arg)
+{
+ PRInt32 nbytes;
+ char buf[1024];
+ PRFileDesc *sock;
+ PRNetAddr peer_addr, *addr;
+
+ addr = (PRNetAddr*)arg;
+
+ sock = PR_NewTCPSocket();
+ if (sock == NULL)
+ {
+ PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_Connect (client) failed");
+ PR_ProcessExit(1);
+ }
+ if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ /*
+ ** Then wait between the connection coming up and sending the expected
+ ** data. At some point in time, the server should fail due to a timeou
+ ** on the AcceptRead() operation, which according to the document is
+ ** only due to the read() portion.
+ */
+ PR_Sleep(write_dally);
+
+ nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");
+
+ nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
+ else
+ {
+ PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
+ buf[sizeof(buf) - 1] = '\0';
+ PR_fprintf(std_out, "%s\n", buf);
+ }
+
+ if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
+ PL_FPrintError(err_out, "PR_Shutdown (client) failed");
+
+ if (PR_FAILURE == PR_Close(sock))
+ PL_FPrintError(err_out, "PR_Close (client) failed");
+
+ return;
+} /* ConnectingThread */
+
+#define BUF_SIZE 117
+static void AcceptingThread(void *arg)
+{
+ PRStatus rv;
+ PRInt32 bytes;
+ PRSize buf_size = BUF_SIZE;
+ PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
+ PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
+ PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
+ PRSocketOptionData sock_opt;
+
+ if (NULL == listen_sock)
+ {
+ PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
+ PR_ProcessExit(1);
+ }
+ sock_opt.option = PR_SockOpt_Reuseaddr;
+ sock_opt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(listen_sock, &sock_opt);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
+ PR_ProcessExit(1);
+ }
+ rv = PR_Bind(listen_sock, listen_addr);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_Bind (server) failed");
+ PR_ProcessExit(1);
+ }
+ rv = PR_Listen(listen_sock, 10);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_Listen (server) failed");
+ PR_ProcessExit(1);
+ }
+ bytes = PR_AcceptRead(
+ listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);
+
+ if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
+ else
+ {
+ PrintAddress(accept_addr);
+ PR_fprintf(
+ std_out, "(Server) read [0x%p..0x%p) %s\n",
+ buf, &buf[BUF_SIZE], buf);
+ bytes = PR_Write(accept_sock, buf, bytes);
+ rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Shutdown (server) failed");
+ }
+
+ if (-1 != bytes)
+ {
+ rv = PR_Close(accept_sock);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Close (server) failed");
+ }
+
+ rv = PR_Close(listen_sock);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Close (server) failed");
+} /* AcceptingThread */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRHostEnt he;
+ PRStatus status;
+ PRIntn next_index;
+ PRUint16 port_number;
+ char netdb_buf[PR_NETDB_BUF_SIZE];
+ PRNetAddr client_addr, server_addr;
+ PRThread *client_thread, *server_thread;
+ PRIntervalTime delta = PR_MillisecondsToInterval(500);
+
+ err_out = PR_STDERR;
+ std_out = PR_STDOUT;
+ accept_timeout = PR_SecondsToInterval(2);
+
+ if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
+ else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);
+
+ status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
+ if (PR_SUCCESS != status)
+ {
+ PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
+ PR_ProcessExit(1);
+ }
+ if (argc < 3)
+ {
+ status = PR_InitializeNetAddr(
+ PR_IpAddrLoopback, port_number, &client_addr);
+ if (PR_SUCCESS != status)
+ {
+ PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
+ PR_ProcessExit(1);
+ }
+ }
+ else
+ {
+ status = PR_GetHostByName(
+ argv[1], netdb_buf, sizeof(netdb_buf), &he);
+ if (status == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_GetHostByName failed");
+ PR_ProcessExit(1);
+ }
+ next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
+ if (next_index == -1)
+ {
+ PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
+ PR_ProcessExit(1);
+ }
+ }
+
+ for (
+ write_dally = 0;
+ write_dally < accept_timeout + (2 * delta);
+ write_dally += delta)
+ {
+ PR_fprintf(
+ std_out, "Testing w/ write_dally = %d msec\n",
+ PR_IntervalToMilliseconds(write_dally));
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, AcceptingThread, &server_addr,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (server_thread == NULL)
+ {
+ PL_FPrintError(err_out, "PR_CreateThread (server) failed");
+ PR_ProcessExit(1);
+ }
+
+ PR_Sleep(delta); /* let the server pot thicken */
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, ConnectingThread, &client_addr,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (client_thread == NULL)
+ {
+ PL_FPrintError(err_out, "PR_CreateThread (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ if (PR_JoinThread(client_thread) == PR_FAILURE)
+ PL_FPrintError(err_out, "PR_JoinThread (client) failed");
+
+ if (PR_JoinThread(server_thread) == PR_FAILURE)
+ PL_FPrintError(err_out, "PR_JoinThread (server) failed");
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/acceptreademu.c b/src/libs/xpcom18a4/nsprpub/pr/tests/acceptreademu.c
new file mode 100644
index 00000000..8d17f31a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/acceptreademu.c
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This test is the same as acceptread.c except that it uses the
+ * emulated acceptread method instead of the regular acceptread.
+ */
+
+#include <prio.h>
+#include <prprf.h>
+#include <prinit.h>
+#include <prnetdb.h>
+#include <prinrval.h>
+#include <prthread.h>
+#include <pprio.h>
+
+#include <plerror.h>
+
+#include <stdlib.h>
+
+#define DEFAULT_PORT 12273
+#define GET "GET / HTTP/1.0\n\n"
+static PRFileDesc *std_out, *err_out;
+static PRIntervalTime write_dally, accept_timeout;
+static PRDescIdentity emu_layer_ident;
+static PRIOMethods emu_layer_methods;
+
+/* the acceptread method in emu_layer_methods */
+static PRInt32 PR_CALLBACK emu_AcceptRead(PRFileDesc *sd, PRFileDesc **nd,
+ PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ return PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
+}
+
+static PRStatus PrintAddress(const PRNetAddr* address)
+{
+ char buffer[100];
+ PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
+ if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString");
+ else PR_fprintf(
+ std_out, "Accepted connection from (0x%p)%s:%d\n",
+ address, buffer, address->inet.port);
+ return rv;
+} /* PrintAddress */
+
+static void ConnectingThread(void *arg)
+{
+ PRInt32 nbytes;
+ char buf[1024];
+ PRFileDesc *sock;
+ PRNetAddr peer_addr, *addr;
+
+ addr = (PRNetAddr*)arg;
+
+ sock = PR_NewTCPSocket();
+ if (sock == NULL)
+ {
+ PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_Connect (client) failed");
+ PR_ProcessExit(1);
+ }
+ if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_GetPeerName (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ /*
+ ** Then wait between the connection coming up and sending the expected
+ ** data. At some point in time, the server should fail due to a timeou
+ ** on the AcceptRead() operation, which according to the document is
+ ** only due to the read() portion.
+ */
+ PR_Sleep(write_dally);
+
+ nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed");
+
+ nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed");
+ else
+ {
+ PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes);
+ buf[sizeof(buf) - 1] = '\0';
+ PR_fprintf(std_out, "%s\n", buf);
+ }
+
+ if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH))
+ PL_FPrintError(err_out, "PR_Shutdown (client) failed");
+
+ if (PR_FAILURE == PR_Close(sock))
+ PL_FPrintError(err_out, "PR_Close (client) failed");
+
+ return;
+} /* ConnectingThread */
+
+#define BUF_SIZE 117
+static void AcceptingThread(void *arg)
+{
+ PRStatus rv;
+ PRInt32 bytes;
+ PRSize buf_size = BUF_SIZE;
+ PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
+ PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
+ PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
+ PRFileDesc *layer;
+ PRSocketOptionData sock_opt;
+
+ if (NULL == listen_sock)
+ {
+ PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
+ PR_ProcessExit(1);
+ }
+ layer = PR_CreateIOLayerStub(emu_layer_ident, &emu_layer_methods);
+ if (NULL == layer)
+ {
+ PL_FPrintError(err_out, "PR_CreateIOLayerStub (server) failed");
+ PR_ProcessExit(1);
+ }
+ if (PR_PushIOLayer(listen_sock, PR_TOP_IO_LAYER, layer) == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_PushIOLayer (server) failed");
+ PR_ProcessExit(1);
+ }
+ sock_opt.option = PR_SockOpt_Reuseaddr;
+ sock_opt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(listen_sock, &sock_opt);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
+ PR_ProcessExit(1);
+ }
+ rv = PR_Bind(listen_sock, listen_addr);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_Bind (server) failed");
+ PR_ProcessExit(1);
+ }
+ rv = PR_Listen(listen_sock, 10);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err_out, "PR_Listen (server) failed");
+ PR_ProcessExit(1);
+ }
+ bytes = PR_AcceptRead(
+ listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);
+
+ if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
+ else
+ {
+ PrintAddress(accept_addr);
+ PR_fprintf(
+ std_out, "(Server) read [0x%p..0x%p) %s\n",
+ buf, &buf[BUF_SIZE], buf);
+ bytes = PR_Write(accept_sock, buf, bytes);
+ rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Shutdown (server) failed");
+ }
+
+ if (-1 != bytes)
+ {
+ rv = PR_Close(accept_sock);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Close (server) failed");
+ }
+
+ rv = PR_Close(listen_sock);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err_out, "PR_Close (server) failed");
+} /* AcceptingThread */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRHostEnt he;
+ PRStatus status;
+ PRIntn next_index;
+ PRUint16 port_number;
+ char netdb_buf[PR_NETDB_BUF_SIZE];
+ PRNetAddr client_addr, server_addr;
+ PRThread *client_thread, *server_thread;
+ PRIntervalTime delta = PR_MillisecondsToInterval(500);
+
+ err_out = PR_STDERR;
+ std_out = PR_STDOUT;
+ accept_timeout = PR_SecondsToInterval(2);
+ emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead");
+ emu_layer_methods = *PR_GetDefaultIOMethods();
+ emu_layer_methods.acceptread = emu_AcceptRead;
+
+ if (argc != 2 && argc != 3) port_number = DEFAULT_PORT;
+ else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]);
+
+ status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr);
+ if (PR_SUCCESS != status)
+ {
+ PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
+ PR_ProcessExit(1);
+ }
+ if (argc < 3)
+ {
+ status = PR_InitializeNetAddr(
+ PR_IpAddrLoopback, port_number, &client_addr);
+ if (PR_SUCCESS != status)
+ {
+ PL_FPrintError(err_out, "PR_InitializeNetAddr failed");
+ PR_ProcessExit(1);
+ }
+ }
+ else
+ {
+ status = PR_GetHostByName(
+ argv[1], netdb_buf, sizeof(netdb_buf), &he);
+ if (status == PR_FAILURE)
+ {
+ PL_FPrintError(err_out, "PR_GetHostByName failed");
+ PR_ProcessExit(1);
+ }
+ next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr);
+ if (next_index == -1)
+ {
+ PL_FPrintError(err_out, "PR_EnumerateHostEnt failed");
+ PR_ProcessExit(1);
+ }
+ }
+
+ for (
+ write_dally = 0;
+ write_dally < accept_timeout + (2 * delta);
+ write_dally += delta)
+ {
+ PR_fprintf(
+ std_out, "Testing w/ write_dally = %d msec\n",
+ PR_IntervalToMilliseconds(write_dally));
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, AcceptingThread, &server_addr,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (server_thread == NULL)
+ {
+ PL_FPrintError(err_out, "PR_CreateThread (server) failed");
+ PR_ProcessExit(1);
+ }
+
+ PR_Sleep(delta); /* let the server pot thicken */
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, ConnectingThread, &client_addr,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (client_thread == NULL)
+ {
+ PL_FPrintError(err_out, "PR_CreateThread (client) failed");
+ PR_ProcessExit(1);
+ }
+
+ if (PR_JoinThread(client_thread) == PR_FAILURE)
+ PL_FPrintError(err_out, "PR_JoinThread (client) failed");
+
+ if (PR_JoinThread(server_thread) == PR_FAILURE)
+ PL_FPrintError(err_out, "PR_JoinThread (server) failed");
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/addrstr.c b/src/libs/xpcom18a4/nsprpub/pr/tests/addrstr.c
new file mode 100644
index 00000000..a18f9a8c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/addrstr.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 "prnetdb.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+const char *testaddrs[] = {
+ "::", "::",
+ "::1", "::1",
+ "::ffff", "::ffff",
+ "::1:0", "::0.1.0.0",
+ "::127.0.0.1", "::127.0.0.1",
+ "::FFFF:127.0.0.1", "::ffff:127.0.0.1",
+ "::FFFE:9504:3501", "::fffe:9504:3501",
+ "0:0:1:0:35c:0:0:0", "0:0:1:0:35c::",
+ "0:0:3f4c:0:0:4552:0:0", "::3f4c:0:0:4552:0:0",
+ "0:0:1245:0:0:0:0567:0", "0:0:1245::567:0",
+ "0:1:2:3:4:5:6:7", "0:1:2:3:4:5:6:7",
+ "1:2:3:0:4:5:6:7", "1:2:3:0:4:5:6:7",
+ "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:0",
+ "1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8",
+ "1:2:3:4:5:6::7", "1:2:3:4:5:6:0:7",
+ 0
+};
+
+const char *badaddrs[] = {
+ "::.1.2.3",
+ "ffff::.1.2.3",
+ "1:2:3:4:5:6:7::8",
+ "1:2:3:4:5:6::7:8",
+ "::ff99.2.3.4",
+ 0
+};
+
+int failed_already = 0;
+
+int main()
+{
+ const char **nexttestaddr = testaddrs;
+ const char **nextbadaddr = badaddrs;
+ const char *in, *expected_out;
+ PRNetAddr addr;
+ char buf[256];
+ PRStatus rv;
+
+ while ((in = *nexttestaddr++) != 0) {
+ expected_out = *nexttestaddr++;
+ rv = PR_StringToNetAddr(in, &addr);
+ if (rv) {
+ printf("cannot convert %s to addr: %d\n", in, rv);
+ failed_already = 1;
+ continue;
+ }
+ rv = PR_NetAddrToString(&addr, buf, sizeof(buf));
+ if (rv) {
+ printf("cannot convert %s back to string: %d\n", in, rv);
+ failed_already = 1;
+ continue;
+ }
+ if (strcmp(buf, expected_out)) {
+ /* This is not necessarily an error */
+ printf("%s expected %s got %s\n", in, expected_out, buf);
+ }
+ }
+ while ((in = *nextbadaddr++) != 0) {
+ if (PR_StringToNetAddr(in, &addr) == PR_SUCCESS) {
+ printf("converted bad addr %s\n", in);
+ failed_already = 1;
+ }
+ }
+ if (failed_already) {
+ printf("FAIL\n");
+ return 1;
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/affinity.c b/src/libs/xpcom18a4/nsprpub/pr/tests/affinity.c
new file mode 100644
index 00000000..46f159bf
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/affinity.c
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "pprthred.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef XP_BEOS
+
+/*
+ * Test PR_GetThreadAffinityMask
+ * The function is called by each of local, global and global bound threads
+ * The test should be run on both single and multi-cpu systems
+ */
+static void PR_CALLBACK thread_start(void *arg)
+{
+PRUint32 mask = 0;
+
+ if (PR_GetThreadAffinityMask(PR_GetCurrentThread(), &mask))
+ printf("\tthread_start: PR_GetCurrentThreadAffinityMask failed\n");
+ else
+ printf("\tthread_start: AffinityMask = 0x%x\n",mask);
+
+}
+
+int main(int argc, char **argv)
+{
+ PRThread *t;
+
+ printf("main: creating local thread\n");
+
+ t = PR_CreateThread(PR_USER_THREAD,
+ thread_start, 0,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ if (NULL == t) {
+ printf("main: cannot create local thread\n");
+ exit(1);
+ }
+
+ PR_JoinThread(t);
+
+ printf("main: creating global thread\n");
+ t = PR_CreateThread(PR_USER_THREAD,
+ thread_start, 0,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ if (NULL == t) {
+ printf("main: cannot create global thread\n");
+ exit(1);
+ }
+
+ PR_JoinThread(t);
+
+ printf("main: creating global bound thread\n");
+ t = PR_CreateThread(PR_USER_THREAD,
+ thread_start, 0,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_BOUND_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ if (NULL == t) {
+ printf("main: cannot create global bound thread\n");
+ exit(1);
+ }
+
+ PR_JoinThread(t);
+
+ return 0;
+}
+
+#else /* !XP_BEOS */
+
+int main()
+{
+ printf( "This test is not supported on the BeOS\n" );
+ return 0;
+}
+#endif /* !XP_BEOS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c b/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c
new file mode 100644
index 00000000..7af2ed4c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c
@@ -0,0 +1,569 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1996 - Netscape Communications Corporation
+**
+** Name: alarmtst.c
+**
+** Description: Test alarms
+**
+** Modification History:
+** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+
+#include "prlog.h"
+#include "prinit.h"
+#ifdef XP_MAC
+#include "pralarm.h"
+#else
+#include "obsolete/pralarm.h"
+#endif
+#include "prlock.h"
+#include "prlong.h"
+#include "prcvar.h"
+#include "prinrval.h"
+#include "prtime.h"
+
+/* Used to get the command line option */
+#include "plgetopt.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(XP_UNIX)
+#include <sys/time.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+static PRIntn debug_mode;
+static PRIntn failed_already=0;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+typedef struct notifyData {
+ PRLock *ml;
+ PRCondVar *child;
+ PRCondVar *parent;
+ PRBool pending;
+ PRUint32 counter;
+} NotifyData;
+
+static void Notifier(void *arg)
+{
+ NotifyData *notifyData = (NotifyData*)arg;
+ PR_Lock(notifyData->ml);
+ while (notifyData->counter > 0)
+ {
+ while (!notifyData->pending)
+ PR_WaitCondVar(notifyData->child, PR_INTERVAL_NO_TIMEOUT);
+ notifyData->counter -= 1;
+ notifyData->pending = PR_FALSE;
+ PR_NotifyCondVar(notifyData->parent);
+ }
+ PR_Unlock(notifyData->ml);
+} /* Notifier */
+/***********************************************************************
+** PRIVATE FUNCTION: ConditionNotify
+** DESCRIPTION:
+**
+** INPUTS: loops
+** OUTPUTS: None
+** RETURN: overhead
+** SIDE EFFECTS:
+**
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM:
+**
+***********************************************************************/
+
+
+static PRIntervalTime ConditionNotify(PRUint32 loops)
+{
+ PRThread *thread;
+ NotifyData notifyData;
+ PRIntervalTime timein, overhead;
+
+ timein = PR_IntervalNow();
+
+ notifyData.counter = loops;
+ notifyData.ml = PR_NewLock();
+ notifyData.child = PR_NewCondVar(notifyData.ml);
+ notifyData.parent = PR_NewCondVar(notifyData.ml);
+ thread = PR_CreateThread(
+ PR_USER_THREAD, Notifier, &notifyData,
+ PR_GetThreadPriority(PR_GetCurrentThread()),
+ thread_scope, PR_JOINABLE_THREAD, 0);
+
+ overhead = PR_IntervalNow() - timein; /* elapsed so far */
+
+ PR_Lock(notifyData.ml);
+ while (notifyData.counter > 0)
+ {
+ notifyData.pending = PR_TRUE;
+ PR_NotifyCondVar(notifyData.child);
+ while (notifyData.pending)
+ PR_WaitCondVar(notifyData.parent, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(notifyData.ml);
+
+ timein = PR_IntervalNow();
+
+ (void)PR_JoinThread(thread);
+ PR_DestroyCondVar(notifyData.child);
+ PR_DestroyCondVar(notifyData.parent);
+ PR_DestroyLock(notifyData.ml);
+
+ overhead += (PR_IntervalNow() - timein); /* more overhead */
+
+ return overhead;
+} /* ConditionNotify */
+
+static PRIntervalTime ConditionTimeout(PRUint32 loops)
+{
+ PRUintn count;
+ PRIntervalTime overhead, timein = PR_IntervalNow();
+
+ PRLock *ml = PR_NewLock();
+ PRCondVar *cv = PR_NewCondVar(ml);
+ PRIntervalTime interval = PR_MillisecondsToInterval(50);
+
+ overhead = PR_IntervalNow() - timein;
+
+ PR_Lock(ml);
+ for (count = 0; count < loops; ++count)
+ {
+ overhead += interval;
+ PR_ASSERT(PR_WaitCondVar(cv, interval) == PR_SUCCESS);
+ }
+ PR_Unlock(ml);
+
+ timein = PR_IntervalNow();
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+ overhead += (PR_IntervalNow() - timein);
+
+ return overhead;
+} /* ConditionTimeout */
+
+typedef struct AlarmData {
+ PRLock *ml;
+ PRCondVar *cv;
+ PRUint32 rate, late, times;
+ PRIntervalTime duration, timein, period;
+} AlarmData;
+
+static PRBool AlarmFn1(PRAlarmID *id, void *clientData, PRUint32 late)
+{
+ PRStatus rv = PR_SUCCESS;
+ PRBool keepGoing, resetAlarm;
+ PRIntervalTime interval, now = PR_IntervalNow();
+ AlarmData *ad = (AlarmData*)clientData;
+
+ PR_Lock(ad->ml);
+ ad->late += late;
+ ad->times += 1;
+ keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ?
+ PR_TRUE : PR_FALSE;
+ if (!keepGoing)
+ rv = PR_NotifyCondVar(ad->cv);
+ resetAlarm = ((ad->times % 31) == 0) ? PR_TRUE : PR_FALSE;
+
+ interval = (ad->period + ad->rate - 1) / ad->rate;
+ if (!late && (interval > 10))
+ {
+ interval &= (now & 0x03) + 1;
+ PR_WaitCondVar(ad->cv, interval);
+ }
+
+ PR_Unlock(ad->ml);
+
+ if (rv != PR_SUCCESS)
+ {
+ if (!debug_mode) failed_already=1;
+ else
+ printf("AlarmFn: notify status: FAIL\n");
+
+ }
+
+ if (resetAlarm)
+ {
+ ad->rate += 3;
+ ad->late = ad->times = 0;
+ if (PR_ResetAlarm(id, ad->period, ad->rate) != PR_SUCCESS)
+ {
+ if (!debug_mode)
+ failed_already=1;
+ else
+ printf("AlarmFn: Resetting alarm status: FAIL\n");
+
+ keepGoing = PR_FALSE;
+ }
+
+ }
+
+ return keepGoing;
+} /* AlarmFn1 */
+
+static PRIntervalTime Alarms1(PRUint32 loops)
+{
+ PRAlarm *alarm;
+ AlarmData ad;
+ PRIntervalTime overhead, timein = PR_IntervalNow();
+ PRIntervalTime duration = PR_SecondsToInterval(3);
+
+ PRLock *ml = PR_NewLock();
+ PRCondVar *cv = PR_NewCondVar(ml);
+
+ ad.ml = ml;
+ ad.cv = cv;
+ ad.rate = 1;
+ ad.times = loops;
+ ad.late = ad.times = 0;
+ ad.duration = duration;
+ ad.timein = PR_IntervalNow();
+ ad.period = PR_SecondsToInterval(1);
+
+ alarm = PR_CreateAlarm();
+
+ (void)PR_SetAlarm(
+ alarm, ad.period, ad.rate, AlarmFn1, &ad);
+
+ overhead = PR_IntervalNow() - timein;
+
+ PR_Lock(ml);
+ while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration)
+ PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(ml);
+
+ timein = PR_IntervalNow();
+ (void)PR_DestroyAlarm(alarm);
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+ overhead += (PR_IntervalNow() - timein);
+
+ return duration + overhead;
+} /* Alarms1 */
+
+static PRBool AlarmFn2(PRAlarmID *id, void *clientData, PRUint32 late)
+{
+#if defined(XP_MAC)
+#pragma unused (id)
+#endif
+
+ PRBool keepGoing;
+ PRStatus rv = PR_SUCCESS;
+ AlarmData *ad = (AlarmData*)clientData;
+ PRIntervalTime interval, now = PR_IntervalNow();
+
+ PR_Lock(ad->ml);
+ ad->times += 1;
+ keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ?
+ PR_TRUE : PR_FALSE;
+ interval = (ad->period + ad->rate - 1) / ad->rate;
+
+ if (!late && (interval > 10))
+ {
+ interval &= (now & 0x03) + 1;
+ PR_WaitCondVar(ad->cv, interval);
+ }
+
+ if (!keepGoing) rv = PR_NotifyCondVar(ad->cv);
+
+ PR_Unlock(ad->ml);
+
+
+ if (rv != PR_SUCCESS)
+ failed_already=1;;
+
+ return keepGoing;
+} /* AlarmFn2 */
+
+static PRIntervalTime Alarms2(PRUint32 loops)
+{
+ PRStatus rv;
+ PRAlarm *alarm;
+ PRIntervalTime overhead, timein = PR_IntervalNow();
+ AlarmData ad;
+ PRIntervalTime duration = PR_SecondsToInterval(30);
+
+ PRLock *ml = PR_NewLock();
+ PRCondVar *cv = PR_NewCondVar(ml);
+
+ ad.ml = ml;
+ ad.cv = cv;
+ ad.rate = 1;
+ ad.times = loops;
+ ad.late = ad.times = 0;
+ ad.duration = duration;
+ ad.timein = PR_IntervalNow();
+ ad.period = PR_SecondsToInterval(1);
+
+ alarm = PR_CreateAlarm();
+
+ (void)PR_SetAlarm(
+ alarm, ad.period, ad.rate, AlarmFn2, &ad);
+
+ overhead = PR_IntervalNow() - timein;
+
+ PR_Lock(ml);
+ while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration)
+ PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(ml);
+
+ timein = PR_IntervalNow();
+
+ rv = PR_DestroyAlarm(alarm);
+ if (rv != PR_SUCCESS)
+ {
+ if (!debug_mode)
+ failed_already=1;
+ else
+ printf("***Destroying alarm status: FAIL\n");
+ }
+
+
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+
+ overhead += (PR_IntervalNow() - timein);
+
+ return duration + overhead;
+} /* Alarms2 */
+
+static PRIntervalTime Alarms3(PRUint32 loops)
+{
+ PRIntn i;
+ PRStatus rv;
+ PRAlarm *alarm;
+ AlarmData ad[3];
+ PRIntervalTime duration = PR_SecondsToInterval(30);
+ PRIntervalTime overhead, timein = PR_IntervalNow();
+
+ PRLock *ml = PR_NewLock();
+ PRCondVar *cv = PR_NewCondVar(ml);
+
+ for (i = 0; i < 3; ++i)
+ {
+ ad[i].ml = ml;
+ ad[i].cv = cv;
+ ad[i].rate = 1;
+ ad[i].times = loops;
+ ad[i].duration = duration;
+ ad[i].late = ad[i].times = 0;
+ ad[i].timein = PR_IntervalNow();
+ ad[i].period = PR_SecondsToInterval(1);
+
+ /* more loops, faster rate => same elapsed time */
+ ad[i].times = (i + 1) * loops;
+ ad[i].rate = (i + 1) * 10;
+ }
+
+ alarm = PR_CreateAlarm();
+
+ for (i = 0; i < 3; ++i)
+ {
+ (void)PR_SetAlarm(
+ alarm, ad[i].period, ad[i].rate,
+ AlarmFn2, &ad[i]);
+ }
+
+ overhead = PR_IntervalNow() - timein;
+
+ PR_Lock(ml);
+ for (i = 0; i < 3; ++i)
+ {
+ while ((PRIntervalTime)(PR_IntervalNow() - ad[i].timein) < duration)
+ PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(ml);
+
+ timein = PR_IntervalNow();
+
+ if (debug_mode)
+ printf
+ ("Alarms3 finished at %u, %u, %u\n",
+ ad[0].timein, ad[1].timein, ad[2].timein);
+
+ rv = PR_DestroyAlarm(alarm);
+ if (rv != PR_SUCCESS)
+ {
+ if (!debug_mode)
+ failed_already=1;
+ else
+ printf("***Destroying alarm status: FAIL\n");
+ }
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+
+ overhead += (duration / 3);
+ overhead += (PR_IntervalNow() - timein);
+
+ return overhead;
+} /* Alarms3 */
+
+static PRUint32 TimeThis(
+ const char *msg, PRUint32 (*func)(PRUint32 loops), PRUint32 loops)
+{
+ PRUint32 overhead, usecs;
+ PRIntervalTime predicted, timein, timeout, ticks;
+
+ if (debug_mode)
+ printf("Testing %s ...", msg);
+
+ timein = PR_IntervalNow();
+ predicted = func(loops);
+ timeout = PR_IntervalNow();
+
+ if (debug_mode)
+ printf(" done\n");
+
+ ticks = timeout - timein;
+ usecs = PR_IntervalToMicroseconds(ticks);
+ overhead = PR_IntervalToMicroseconds(predicted);
+
+ if(ticks < predicted)
+ {
+ if (debug_mode) {
+ printf("\tFinished in negative time\n");
+ printf("\tpredicted overhead was %d usecs\n", overhead);
+ printf("\ttest completed in %d usecs\n\n", usecs);
+ }
+ }
+ else
+ {
+ if (debug_mode)
+ printf(
+ "\ttotal: %d usecs\n\toverhead: %d usecs\n\tcost: %6.3f usecs\n\n",
+ usecs, overhead, ((double)(usecs - overhead) / (double)loops));
+ }
+
+ return overhead;
+} /* TimeThis */
+
+int prmain(int argc, char** argv)
+{
+ PRUint32 cpu, cpus = 0, loops = 0;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name [-d]
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:c:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* GLOBAL threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'l': /* loop count */
+ loops = atoi(opt->value);
+ break;
+ case 'c': /* concurrency limit */
+ cpus = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+
+ if (cpus == 0) cpus = 1;
+ if (loops == 0) loops = 4;
+
+ if (debug_mode)
+ printf("Alarm: Using %d loops\n", loops);
+
+ if (debug_mode)
+ printf("Alarm: Using %d cpu(s)\n", cpus);
+#ifdef XP_MAC
+ SetupMacPrintfLog("alarm.log");
+ debug_mode = 1;
+#endif
+
+ for (cpu = 1; cpu <= cpus; ++cpu)
+ {
+ if (debug_mode)
+ printf("\nAlarm: Using %d CPU(s)\n", cpu);
+
+ PR_SetConcurrency(cpu);
+
+ /* some basic time test */
+ (void)TimeThis("ConditionNotify", ConditionNotify, loops);
+ (void)TimeThis("ConditionTimeout", ConditionTimeout, loops);
+ (void)TimeThis("Alarms1", Alarms1, loops);
+ (void)TimeThis("Alarms2", Alarms2, loops);
+ (void)TimeThis("Alarms3", Alarms3, loops);
+ }
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ PR_Initialize(prmain, argc, argv, 0);
+ PR_STDIO_INIT();
+ if (failed_already) return 1;
+ else return 0;
+
+} /* main */
+
+
+/* alarmtst.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/anonfm.c b/src/libs/xpcom18a4/nsprpub/pr/tests/anonfm.c
new file mode 100644
index 00000000..aeab86b1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/anonfm.c
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: anonfm.c
+** Description: Test anonymous file map
+**
+** Synopsis: anonfm [options] [dirName]
+**
+** Options:
+** -d enable debug mode
+** -h display a help message
+** -s <n> size of the anonymous memory map, in KBytes. default: 100KBytes.
+** -C 1 Operate this process as ClientOne()
+** -C 2 Operate this process as ClientTwo()
+**
+** anonfn.c contains two tests, corresponding to the two protocols for
+** passing an anonymous file map to a child process.
+**
+** ServerOne()/ClientOne() tests the passing of "raw" file map; it uses
+** PR_CreateProcess() [for portability of the test case] to create the
+** child process, but does not use the PRProcessAttr structure for
+** passing the file map data.
+**
+** ServerTwo()/ClientTwo() tests the passing of the file map using the
+** PRProcessAttr structure.
+**
+*/
+#include <plgetopt.h>
+#include <nspr.h>
+#include <private/primpl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** Test harness infrastructure
+*/
+PRLogModuleInfo *lm;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRUint32 failed_already = 0;
+
+PRIntn debug = 0;
+PRIntn client = 0; /* invoke client, style */
+char dirName[512] = "."; /* directory name to contain anon mapped file */
+PRSize fmSize = (100 * 1024 );
+PRUint32 fmMode = 0600;
+PRFileMapProtect fmProt = PR_PROT_READWRITE;
+const char *fmEnvName = "nsprFileMapEnvVariable";
+
+/*
+** Emit help text for this test
+*/
+static void Help( void )
+{
+ printf("anonfm [options] [dirName]\n");
+ printf("-d -- enable debug mode\n");
+ printf("dirName is alternate directory name. Default: . (current directory)\n");
+ exit(1);
+} /* end Help() */
+
+
+/*
+** ClientOne() --
+*/
+static void ClientOne( void )
+{
+ PRFileMap *fm;
+ char *fmString;
+ char *addr;
+ PRStatus rc;
+
+ PR_LOG(lm, msgLevel,
+ ("ClientOne() starting"));
+
+ fmString = PR_GetEnv( fmEnvName );
+ if ( NULL == fmString ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_Getenv() failed"));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_Getenv(): found: %s", fmString));
+
+ fm = PR_ImportFileMapFromString( fmString );
+ if ( NULL == fm ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_ImportFileMapFromString() failed"));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_ImportFileMapFromString(): fm: %p", fm ));
+
+ addr = PR_MemMap( fm, LL_ZERO, fmSize );
+ if ( NULL == addr ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_MemMap() failed, OSError: %d", PR_GetOSError() ));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_MemMap(): addr: %p", addr ));
+
+ /* write to memory map to release server */
+ *addr = 1;
+
+ rc = PR_MemUnmap( addr, fmSize );
+ PR_ASSERT( rc == PR_SUCCESS );
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_MemUnap(): success" ));
+
+ rc = PR_CloseFileMap( fm );
+ if ( PR_FAILURE == rc ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_MemUnap() failed, OSError: %d", PR_GetOSError() ));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ClientOne(): PR_CloseFileMap(): success" ));
+
+ return;
+} /* end ClientOne() */
+
+/*
+** ClientTwo() --
+*/
+static void ClientTwo( void )
+{
+ failed_already = 1;
+} /* end ClientTwo() */
+
+/*
+** ServerOne() --
+*/
+static void ServerOne( void )
+{
+ PRFileMap *fm;
+ PRStatus rc;
+ PRIntn i;
+ char *addr;
+ char fmString[256];
+ char envBuf[256];
+ char *child_argv[8];
+ PRProcess *proc;
+ PRInt32 exit_status;
+
+ PR_LOG(lm, msgLevel,
+ ("ServerOne() starting"));
+
+ fm = PR_OpenAnonFileMap( dirName, fmSize, fmProt );
+ if ( NULL == fm ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("PR_OpenAnonFileMap() failed"));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): FileMap: %p", fm ));
+
+ rc = PR_ExportFileMapAsString( fm, sizeof(fmString), fmString );
+ if ( PR_FAILURE == rc ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("PR_ExportFileMap() failed"));
+ return;
+ }
+
+ /*
+ ** put the string into the environment
+ */
+ PR_snprintf( envBuf, sizeof(envBuf), "%s=%s", fmEnvName, fmString);
+ putenv( envBuf );
+
+ addr = PR_MemMap( fm, LL_ZERO, fmSize );
+ if ( NULL == addr ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("PR_MemMap() failed"));
+ return;
+ }
+
+ /* set initial value for client */
+ for (i = 0; i < (PRIntn)fmSize ; i++ )
+ *(addr+i) = 0x00;
+
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): PR_MemMap(): addr: %p", addr ));
+
+ /*
+ ** set arguments for child process
+ */
+ child_argv[0] = "anonfm";
+ child_argv[1] = "-C";
+ child_argv[2] = "1";
+ child_argv[3] = NULL;
+
+ proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
+ PR_ASSERT( proc );
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): PR_CreateProcess(): proc: %x", proc ));
+
+ /*
+ ** ClientOne() will set the memory to 1
+ */
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): waiting on Client, *addr: %x", *addr ));
+ while( *addr == 0x00 ) {
+ if ( debug )
+ fprintf(stderr, ".");
+ PR_Sleep(PR_MillisecondsToInterval(300));
+ }
+ if ( debug )
+ fprintf(stderr, "\n");
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): Client responded" ));
+
+ rc = PR_WaitProcess( proc, &exit_status );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_MemUnmap( addr, fmSize);
+ if ( PR_FAILURE == rc ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("PR_MemUnmap() failed"));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): PR_MemUnmap(): success" ));
+
+ rc = PR_CloseFileMap(fm);
+ if ( PR_FAILURE == rc ) {
+ failed_already = 1;
+ PR_LOG(lm, msgLevel,
+ ("PR_CloseFileMap() failed"));
+ return;
+ }
+ PR_LOG(lm, msgLevel,
+ ("ServerOne(): PR_CloseFileMap() success" ));
+
+ return;
+} /* end ServerOne() */
+
+/*
+** ServerTwo() --
+*/
+static void ServerTwo( void )
+{
+ PR_LOG(lm, msgLevel,
+ ("ServerTwo(): Not implemented yet" ));
+} /* end ServerTwo() */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ {
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdC:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'C': /* Client style */
+ client = atol(opt->value);
+ break;
+ case 's': /* file size */
+ fmSize = atol( opt->value ) * 1024;
+ break;
+ case 'd': /* debug */
+ debug = 1;
+ msgLevel = PR_LOG_DEBUG;
+ break;
+ case 'h': /* help message */
+ Help();
+ break;
+ default:
+ strcpy(dirName, opt->value);
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ lm = PR_NewLogModule("Test"); /* Initialize logging */
+
+ if ( client == 1 ) {
+ ClientOne();
+ } else if ( client == 2 ) {
+ ClientTwo();
+ } else {
+ ServerOne();
+ if ( failed_already ) goto Finished;
+ ServerTwo();
+ }
+
+Finished:
+ if ( debug )
+ printf("%s\n", (failed_already)? "FAIL" : "PASS");
+ return( (failed_already == PR_TRUE )? 1 : 0 );
+} /* main() */
+/* end anonfm.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/append.c b/src/libs/xpcom18a4/nsprpub/pr/tests/append.c
new file mode 100644
index 00000000..3800e2fb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/append.c
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: append.c
+** Description: Testing File writes where PR_APPEND was used on open
+**
+** append attempts to verify that a file opened with PR_APPEND
+** will always append to the end of file, regardless where the
+** current file pointer is positioned. To do this, PR_Seek() is
+** called before each write with the position set to beginning of
+** file. Subsequent writes should always append.
+** The file is read back, summing the integer data written to the
+** file. If the expected result is equal, the test passes.
+**
+** See BugSplat: 4090
+*/
+#include "plgetopt.h"
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+PRIntn debug = 0;
+PRIntn verbose = 0;
+PRBool failedAlready = PR_FALSE;
+const PRInt32 addedBytes = 1000;
+const PRInt32 buf = 1; /* constant written to fd, addedBytes times */
+PRInt32 inBuf; /* read it back into here */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRStatus rc;
+ PRInt32 rv;
+ PRFileDesc *fd;
+ PRIntn i;
+ PRInt32 sum = 0;
+
+ { /* Get command line options */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "vd");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ break;
+ case 'v': /* verbose */
+ verbose = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ } /* end block "Get command line options" */
+/* ---------------------------------------------------------------------- */
+ fd = PR_Open( "/tmp/nsprAppend", (PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY), 0666 );
+ if ( NULL == fd ) {
+ if (debug) printf("PR_Open() failed for writing: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+
+ for ( i = 0; i < addedBytes ; i++ ) {
+ rv = PR_Write( fd, &buf, sizeof(buf));
+ if ( sizeof(buf) != rv ) {
+ if (debug) printf("PR_Write() failed: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ rv = PR_Seek( fd, 0 , PR_SEEK_SET );
+ if ( -1 == rv ) {
+ if (debug) printf("PR_Seek() failed: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ }
+ rc = PR_Close( fd );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf("PR_Close() failed after writing: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+/* ---------------------------------------------------------------------- */
+ fd = PR_Open( "/tmp/nsprAppend", PR_RDONLY, 0 );
+ if ( NULL == fd ) {
+ if (debug) printf("PR_Open() failed for reading: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+
+ for ( i = 0; i < addedBytes ; i++ ) {
+ rv = PR_Read( fd, &inBuf, sizeof(inBuf));
+ if ( sizeof(inBuf) != rv) {
+ if (debug) printf("PR_Write() failed: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ sum += inBuf;
+ }
+
+ rc = PR_Close( fd );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf("PR_Close() failed after reading: %d\n", PR_GetError());
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+ if ( sum != addedBytes ) {
+ if (debug) printf("Uh Oh! addedBytes: %d. Sum: %d\n", addedBytes, sum);
+ failedAlready = PR_TRUE;
+ goto Finished;
+ }
+
+/* ---------------------------------------------------------------------- */
+Finished:
+ if (debug || verbose) printf("%s\n", (failedAlready)? "FAILED" : "PASSED" );
+ return( (failedAlready)? 1 : 0 );
+} /* main() */
+
+/* append.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/atomic.c b/src/libs/xpcom18a4/nsprpub/pr/tests/atomic.c
new file mode 100644
index 00000000..1295b297
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/atomic.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prprf.h"
+#include "pratom.h"
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRInt32 rv, oldval, test, result = 0;
+ PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput);
+
+ oldval = test = -2;
+ rv = PR_AtomicIncrement(&test);
+ result = result | ((rv == -1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicIncrement(%d) == %d: %s\n",
+ oldval, rv, (rv == -1) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicIncrement(&test);
+ result = result | ((rv == 0) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicIncrement(%d) == %d: %s\n",
+ oldval, rv, (rv == 0) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicIncrement(&test);
+ result = result | ((rv == 1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicIncrement(%d) == %d: %s\n",
+ oldval, rv, (rv == 1) ? "PASSED" : "FAILED");
+
+ oldval = test = -2;
+ rv = PR_AtomicAdd(&test,1);
+ result = result | ((rv == -1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicAdd(&test, 4);
+ result = result | ((rv == 3) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicAdd(&test, -6);
+ result = result | ((rv == -3) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicAdd(%d,%d) == %d: %s\n",
+ oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED");
+
+ oldval = test = 2;
+ rv = PR_AtomicDecrement(&test);
+ result = result | ((rv == 1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicDecrement(%d) == %d: %s\n",
+ oldval, rv, (rv == 1) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicDecrement(&test);
+ result = result | ((rv == 0) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicDecrement(%d) == %d: %s\n",
+ oldval, rv, (rv == 0) ? "PASSED" : "FAILED");
+ oldval = test;
+ rv = PR_AtomicDecrement(&test);
+ result = result | ((rv == -1) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicDecrement(%d) == %d: %s\n",
+ oldval, rv, (rv == -1) ? "PASSED" : "FAILED");
+
+ /* set to a different value */
+ oldval = test = -2;
+ rv = PR_AtomicSet(&test, 2);
+ result = result | (((rv == -2) && (test == 2)) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicSet(%d, %d) == %d: %s\n",
+ oldval, 2, rv, ((rv == -2) && (test == 2)) ? "PASSED" : "FAILED");
+
+ /* set to the same value */
+ oldval = test = -2;
+ rv = PR_AtomicSet(&test, -2);
+ result = result | (((rv == -2) && (test == -2)) ? 0 : 1);
+ PR_fprintf(
+ output, "PR_AtomicSet(%d, %d) == %d: %s\n",
+ oldval, -2, rv, ((rv == -2) && (test == -2)) ? "PASSED" : "FAILED");
+
+ PR_fprintf(
+ output, "Atomic operations test %s\n",
+ (result == 0) ? "PASSED" : "FAILED");
+ return result;
+} /* main */
+
+/* atomic.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/attach.c b/src/libs/xpcom18a4/nsprpub/pr/tests/attach.c
new file mode 100644
index 00000000..20da8ec3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/attach.c
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1996 - Netscape Communications Corporation
+**
+** Name: attach.c
+**
+** Description: Platform-specific code to create a native thread. The native thread will
+** repeatedly call PR_AttachThread and PR_DetachThread. The
+** primordial thread waits for this new thread to finish.
+**
+** Modification History:
+** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 Revert to return code 0 and 1.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+
+/* Used to get the command line option */
+#include "nspr.h"
+#include "pprthred.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#elif defined(_PR_PTHREADS)
+#include <pthread.h>
+#include "md/_pth.h"
+#elif defined(IRIX)
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <errno.h>
+#elif defined(SOLARIS)
+#include <thread.h>
+#elif defined(OS2)
+#define INCL_DOS
+#define INCL_ERRORS
+#include <os2.h>
+#include <process.h>
+#elif defined(XP_BEOS)
+#include <kernel/OS.h>
+#endif
+
+#define DEFAULT_COUNT 1000
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+
+int count;
+
+
+static void
+AttachDetach(void)
+{
+ PRThread *me;
+ PRInt32 index;
+
+ for (index=0;index<count; index++) {
+ me = PR_AttachThread(PR_USER_THREAD,
+ PR_PRIORITY_NORMAL,
+ NULL);
+
+ if (!me) {
+ fprintf(stderr, "Error attaching thread %d: PR_AttachThread failed\n",
+ count);
+ failed_already = 1;
+ return;
+ }
+ PR_DetachThread();
+ }
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+ if (debug_mode)
+ printf("%40s: %6.2f usec\n", msg, d / count);
+}
+
+#ifdef WIN32
+static unsigned __stdcall threadStartFunc(void *arg)
+#elif defined(IRIX) && !defined(_PR_PTHREADS)
+static void threadStartFunc(void *arg)
+#elif defined(XP_BEOS)
+static int32 threadStartFunc(void *arg)
+#else
+static void * threadStartFunc(void *arg)
+#endif
+{
+#ifdef _PR_DCETHREADS
+ {
+ int rv;
+ pthread_t self = pthread_self();
+ rv = pthread_detach(&self);
+ if (debug_mode) PR_ASSERT(0 == rv);
+ else if (0 != rv) failed_already=1;
+ }
+#endif
+
+ Measure(AttachDetach, "Attach/Detach");
+
+#ifndef IRIX
+ return 0;
+#endif
+}
+
+int main(int argc, char **argv)
+{
+#ifdef _PR_PTHREADS
+ int rv;
+ pthread_t threadID;
+ pthread_attr_t attr;
+#elif defined(SOLARIS)
+ int rv;
+ thread_t threadID;
+#elif defined(WIN32)
+ DWORD rv;
+ unsigned threadID;
+ HANDLE hThread;
+#elif defined(IRIX)
+ int rv;
+ int threadID;
+#elif defined(OS2)
+ int rv;
+ TID threadID;
+#elif defined(XP_BEOS)
+ thread_id threadID;
+ int32 threadRV;
+ status_t waitRV;
+#endif
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name [-d] [-c n]
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'c': /* loop count */
+ count = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#if defined(WIN16)
+ printf("attach: This test is not valid for Win16\n");
+ goto exit_now;
+#endif
+
+ if(0 == count) count = DEFAULT_COUNT;
+
+ /*
+ * To force the implicit initialization of nspr20
+ */
+ PR_SetError(0, 0);
+ PR_STDIO_INIT();
+
+ /*
+ * Platform-specific code to create a native thread. The native
+ * thread will repeatedly call PR_AttachThread and PR_DetachThread.
+ * The primordial thread waits for this new thread to finish.
+ */
+
+#ifdef _PR_PTHREADS
+
+ rv = _PT_PTHREAD_ATTR_INIT(&attr);
+ if (debug_mode) PR_ASSERT(0 == rv);
+ else if (0 != rv) {
+ failed_already=1;
+ goto exit_now;
+ }
+
+#ifndef _PR_DCETHREADS
+ rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ if (debug_mode) PR_ASSERT(0 == rv);
+ else if (0 != rv) {
+ failed_already=1;
+ goto exit_now;
+ }
+#endif /* !_PR_DCETHREADS */
+ rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL);
+ if (rv != 0) {
+ fprintf(stderr, "thread creation failed: error code %d\n", rv);
+ failed_already=1;
+ goto exit_now;
+ }
+ else {
+ if (debug_mode)
+ printf ("thread creation succeeded \n");
+
+ }
+ rv = _PT_PTHREAD_ATTR_DESTROY(&attr);
+ if (debug_mode) PR_ASSERT(0 == rv);
+ else if (0 != rv) {
+ failed_already=1;
+ goto exit_now;
+ }
+ rv = pthread_join(threadID, NULL);
+ if (debug_mode) PR_ASSERT(0 == rv);
+ else if (0 != rv) {
+ failed_already=1;
+ goto exit_now;
+ }
+
+#elif defined(SOLARIS)
+
+ rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID);
+ if (rv != 0) {
+ if(!debug_mode) {
+ failed_already=1;
+ goto exit_now;
+ } else
+ fprintf(stderr, "thread creation failed: error code %d\n", rv);
+ }
+ rv = thr_join(threadID, NULL, NULL);
+ if (debug_mode) PR_ASSERT(0 == rv);
+ else if (0 != rv)
+ {
+ failed_already=1;
+ goto exit_now;
+ }
+
+
+#elif defined(WIN32)
+
+ hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL,
+ 0, &threadID);
+ if (hThread == 0) {
+ fprintf(stderr, "thread creation failed: error code %d\n",
+ GetLastError());
+ failed_already=1;
+ goto exit_now;
+ }
+ rv = WaitForSingleObject(hThread, INFINITE);
+ if (debug_mode)PR_ASSERT(rv != WAIT_FAILED);
+ else if (rv == WAIT_FAILED) {
+ failed_already=1;
+ goto exit_now;
+ }
+
+#elif defined(IRIX)
+
+ threadID = sproc(threadStartFunc, PR_SALL, NULL);
+ if (threadID == -1) {
+
+ fprintf(stderr, "thread creation failed: error code %d\n",
+ errno);
+ failed_already=1;
+ goto exit_now;
+
+ }
+ else {
+ if (debug_mode)
+ printf ("thread creation succeeded \n");
+ sleep(3);
+ goto exit_now;
+ }
+ rv = waitpid(threadID, NULL, 0);
+ if (debug_mode) PR_ASSERT(rv != -1);
+ else if (rv != -1) {
+ failed_already=1;
+ goto exit_now;
+ }
+
+#elif defined(OS2)
+
+# ifdef __EMX__
+ threadID = (TID) _beginthread((void *)threadStartFunc, NULL,
+ 32768, NULL);
+# else
+ threadID = (TID) _beginthread((void(* _Optlink)(void*))threadStartFunc, NULL,
+ 32768, NULL);
+# endif
+ if (threadID == -1) {
+ fprintf(stderr, "thread creation failed: error code %d\n", errno);
+ failed_already=1;
+ goto exit_now;
+ }
+ rv = DosWaitThread(&threadID, DCWW_WAIT);
+ if (debug_mode) {
+ PR_ASSERT(rv == NO_ERROR);
+ } else if (rv != NO_ERROR) {
+ failed_already=1;
+ goto exit_now;
+ }
+
+#elif defined(XP_BEOS)
+
+ threadID = spawn_thread(threadStartFunc, NULL, B_NORMAL_PRIORITY, NULL);
+ if (threadID <= B_ERROR) {
+ fprintf(stderr, "thread creation failed: error code %08lx\n", threadID);
+ failed_already = 1;
+ goto exit_now;
+ }
+ if (resume_thread(threadID) != B_OK) {
+ fprintf(stderr, "failed starting thread: error code %08lx\n", threadID);
+ failed_already = 1;
+ goto exit_now;
+ }
+
+ waitRV = wait_for_thread(threadID, &threadRV);
+ if (debug_mode)
+ PR_ASSERT(waitRV == B_OK);
+ else if (waitRV != B_OK) {
+ failed_already = 1;
+ goto exit_now;
+ }
+
+#else
+ if (!debug_mode)
+ failed_already=1;
+ else
+ printf("The attach test does not apply to this platform because\n"
+ "either this platform does not have native threads or the\n"
+ "test needs to be written for this platform.\n");
+ goto exit_now;
+#endif
+
+exit_now:
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile.c b/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile.c
new file mode 100644
index 00000000..19c0a7f9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "prinit.h"
+#include "prerror.h"
+#include "prthread.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#define DEFAULT_COUNT 10
+#define DEFAULT_FILESIZE 1
+#define BUFFER_SIZE 1000000
+
+typedef enum {v_silent, v_whisper, v_shout} Verbosity;
+static void Verbose(Verbosity, const char*, const char*, PRIntn);
+
+#define VERBOSE(_l, _m) Verbose(_l, _m, __FILE__, __LINE__)
+
+static PRIntn test_result = 2;
+static PRFileDesc *output = NULL;
+static PRIntn verbose = v_silent;
+static PRIntn filesize = DEFAULT_FILESIZE;
+
+static PRIntn Usage(void)
+{
+ PR_fprintf(output, "Bigfile test usage:\n");
+ PR_fprintf(output, ">bigfile [-G] [-d] [-v[*v]] [-s <n>] <filename>\n");
+ PR_fprintf(output, "\td\tdebug mode (equivalent to -vvv)\t(false)\n");
+ PR_fprintf(output, "\tv\tAdditional levels of output\t(none)\n");
+ PR_fprintf(output, "\tk\tKeep data file after exit\t(false)\n");
+ PR_fprintf(output, "\ts <n>\tFile size in megabytes\t\t(1 megabyte)\n");
+ PR_fprintf(output, "\t<filename>\tName of test file\t(none)\n");
+ return 2; /* nothing happened */
+} /* Usage */
+
+static PRStatus DeleteIfFound(const char *filename)
+{
+ PRStatus rv;
+ VERBOSE(v_shout, "Checking for existing file");
+ rv = PR_Access(filename, PR_ACCESS_WRITE_OK);
+ if (PR_SUCCESS == rv)
+ {
+ VERBOSE(v_shout, "Deleting existing file");
+ rv = PR_Delete(filename);
+ if (PR_FAILURE == rv) VERBOSE(v_shout, "Cannot delete big file");
+ }
+ else if (PR_FILE_NOT_FOUND_ERROR != PR_GetError())
+ VERBOSE(v_shout, "Cannot access big file");
+ else rv = PR_SUCCESS;
+ return rv;
+} /* DeleteIfFound */
+
+static PRIntn Error(const char *msg, const char *filename)
+{
+ PRInt32 error = PR_GetError();
+ if (NULL != msg)
+ {
+ if (0 == error) PR_fprintf(output, msg);
+ else PL_FPrintError(output, msg);
+ }
+ (void)DeleteIfFound(filename);
+ if (v_shout == verbose) PR_Abort();
+ return 1;
+} /* Error */
+
+static void Verbose(
+ Verbosity level, const char *msg, const char *file, PRIntn line)
+{
+ if (level <= verbose)
+ PR_fprintf(output, "[%s : %d]: %s\n", file, line, msg);
+} /* Verbose */
+
+static void PrintInfo(PRFileInfo64 *info, const char *filename)
+{
+ PRExplodedTime tm;
+ char ctime[40], mtime[40];
+ static const char *types[] = {"FILE", "DIRECTORY", "OTHER"};
+ PR_fprintf(
+ output, "[%s : %d]: File info for %s\n",
+ __FILE__, __LINE__, filename);
+ PR_fprintf(
+ output, " type: %s, size: %llu bytes,\n",
+ types[info->type - 1], info->size);
+
+ PR_ExplodeTime(info->creationTime, PR_GMTParameters, &tm);
+ (void)PR_FormatTime(ctime, sizeof(ctime), "%c GMT", &tm);
+ PR_ExplodeTime(info->modifyTime, PR_GMTParameters, &tm);
+ (void)PR_FormatTime(mtime, sizeof(mtime), "%c GMT", &tm);
+
+ PR_fprintf(
+ output, " creation: %s,\n modify: %s\n", ctime, mtime);
+} /* PrintInfo */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ char *buffer;
+ PLOptStatus os;
+ PRInt32 loop, bytes;
+ PRFileInfo small_info;
+ PRFileInfo64 big_info;
+ PRBool keep = PR_FALSE;
+ PRFileDesc *file = NULL;
+ const char *filename = NULL;
+ PRIntn count = DEFAULT_COUNT;
+ PRInt64 filesize64, big_answer, big_size, one_meg, zero_meg, big_fragment;
+ PRInt64 sevenFox = LL_INIT(0,0x7fffffff);
+
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dtvhs:");
+
+ output = PR_GetSpecialFD(PR_StandardError);
+ PR_STDIO_INIT();
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0:
+ filename = opt->value;
+ break;
+ case 'd': /* debug mode */
+ verbose = v_shout;
+ break;
+ case 'k': /* keep file */
+ keep = PR_TRUE;
+ break;
+ case 'v': /* verbosity */
+ if (v_shout > verbose) verbose += 1;
+ break;
+ case 'c': /* loop counter */
+ count = atoi(opt->value);
+ break;
+ case 's': /* filesize */
+ filesize = atoi(opt->value);
+ break;
+ case 'h': /* confused */
+ default:
+ return Usage();
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == count) count = DEFAULT_COUNT;
+ if (0 == filesize) filesize = DEFAULT_FILESIZE;
+ if (NULL == filename)
+ {
+ if (DEFAULT_FILESIZE != filesize) return Usage();
+ else filename = "bigfile.dat";
+ }
+
+ if (PR_FAILURE == DeleteIfFound(filename)) return 1;
+
+ test_result = 0;
+
+ LL_I2L(zero_meg, 0);
+ LL_I2L(one_meg, 1000000);
+ LL_I2L(filesize64, filesize);
+ buffer = (char*)PR_MALLOC(BUFFER_SIZE);
+ LL_I2L(big_fragment, BUFFER_SIZE);
+ LL_MUL(filesize64, filesize64, one_meg);
+
+ for (loop = 0; loop < BUFFER_SIZE; ++loop) buffer[loop] = (char)loop;
+
+ VERBOSE(v_whisper, "Creating big file");
+ file = PR_Open(filename, PR_CREATE_FILE | PR_WRONLY, 0666);
+ if (NULL == file) return Error("PR_Open()", filename);
+
+ VERBOSE(v_whisper, "Testing available space in empty file");
+ big_answer = file->methods->available64(file);
+ if (!LL_IS_ZERO(big_answer)) return Error("empty available64()", filename);
+
+ LL_SUB(big_size, filesize64, one_meg);
+ VERBOSE(v_whisper, "Creating sparse big file by seeking to end");
+ big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET);
+ if (!LL_EQ(big_answer, big_size)) return Error("seek", filename);
+
+ VERBOSE(v_whisper, "Writing block at end of sparse file");
+ bytes = file->methods->write(file, buffer, BUFFER_SIZE);
+ if (bytes != BUFFER_SIZE) return Error("write", filename);
+
+ VERBOSE(v_whisper, "Testing available space at end of sparse file");
+ big_answer = file->methods->available64(file);
+ if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename);
+
+ VERBOSE(v_whisper, "Getting big info on sparse big file");
+ rv = file->methods->fileInfo64(file, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
+ VERBOSE(v_whisper, "Getting small info on sparse big file");
+ rv = file->methods->fileInfo(file, &small_info);
+ if (LL_CMP(sevenFox, <, filesize64) && (PR_SUCCESS == rv))
+ {
+ VERBOSE(v_whisper, "Should have failed and didn't");
+ return Error("fileInfo()", filename);
+ }
+ else if (LL_CMP(sevenFox, >, filesize64) && (PR_FAILURE == rv))
+ {
+ VERBOSE(v_whisper, "Should have succeeded and didn't");
+ return Error("fileInfo()", filename);
+ }
+
+ VERBOSE(v_whisper, "Rewinding big file");
+ big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
+ if (!LL_IS_ZERO(big_answer)) return Error("rewind seek64()", filename);
+
+ VERBOSE(v_whisper, "Establishing available space in rewound file");
+ big_answer = file->methods->available64(file);
+ if (LL_NE(filesize64, big_answer))
+ return Error("bof available64()", filename);
+
+ VERBOSE(v_whisper, "Closing big file");
+ rv = file->methods->close(file);
+ if (PR_FAILURE == rv) return Error("close()", filename);
+
+ VERBOSE(v_whisper, "Reopening big file");
+ file = PR_Open(filename, PR_RDWR, 0666);
+ if (NULL == file) return Error("open failed", filename);
+
+ VERBOSE(v_whisper, "Checking available data in reopened file");
+ big_answer = file->methods->available64(file);
+ if (LL_NE(filesize64, big_answer))
+ return Error("reopened available64()", filename);
+
+ big_answer = zero_meg;
+ VERBOSE(v_whisper, "Rewriting every byte of big file data");
+ do
+ {
+ bytes = file->methods->write(file, buffer, BUFFER_SIZE);
+ if (bytes != BUFFER_SIZE)
+ return Error("write", filename);
+ LL_ADD(big_answer, big_answer, big_fragment);
+ } while (LL_CMP(big_answer, <, filesize64));
+
+ VERBOSE(v_whisper, "Checking position at eof");
+ big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_CUR);
+ if (LL_NE(big_answer, filesize64))
+ return Error("file size error", filename);
+
+ VERBOSE(v_whisper, "Testing available space at eof");
+ big_answer = file->methods->available64(file);
+ if (!LL_IS_ZERO(big_answer))
+ return Error("eof available64()", filename);
+
+ VERBOSE(v_whisper, "Rewinding full file");
+ big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET);
+ if (!LL_IS_ZERO(big_answer)) return Error("bof seek64()", filename);
+
+ VERBOSE(v_whisper, "Testing available space in rewound file");
+ big_answer = file->methods->available64(file);
+ if (LL_NE(big_answer, filesize64)) return Error("bof available64()", filename);
+
+ VERBOSE(v_whisper, "Seeking to end of big file");
+ big_answer = file->methods->seek64(file, filesize64, PR_SEEK_SET);
+ if (LL_NE(big_answer, filesize64)) return Error("eof seek64()", filename);
+
+ VERBOSE(v_whisper, "Getting info on big file while it's open");
+ rv = file->methods->fileInfo64(file, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
+ VERBOSE(v_whisper, "Closing big file");
+ rv = file->methods->close(file);
+ if (PR_FAILURE == rv) return Error("close()", filename);
+
+ VERBOSE(v_whisper, "Getting info on big file after it's closed");
+ rv = PR_GetFileInfo64(filename, &big_info);
+ if (PR_FAILURE == rv) return Error("fileInfo64()", filename);
+ if (v_shout <= verbose) PrintInfo(&big_info, filename);
+
+ VERBOSE(v_whisper, "Deleting big file");
+ rv = PR_Delete(filename);
+ if (PR_FAILURE == rv) return Error("PR_Delete()", filename);
+
+ PR_DELETE(buffer);
+ return test_result;
+} /* main */
+
+/* bigfile.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile2.c b/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile2.c
new file mode 100644
index 00000000..3e8beeeb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile2.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#define TEST_FILE_NAME "bigfile2.txt"
+
+#define MESSAGE "Hello world!"
+#define MESSAGE_SIZE 13
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *fd;
+ PRInt64 offset, position;
+ PRInt32 nbytes;
+ char buf[MESSAGE_SIZE];
+#ifdef _WIN32
+ HANDLE hFile;
+ LARGE_INTEGER li;
+#endif /* _WIN32 */
+
+ LL_I2L(offset, 1);
+ LL_SHL(offset, offset, 32);
+
+ fd = PR_Open(TEST_FILE_NAME,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666);
+ if (fd == NULL) {
+ fprintf(stderr, "PR_Open failed\n");
+ exit(1);
+ }
+ position = PR_Seek64(fd, offset, PR_SEEK_SET);
+ if (!LL_GE_ZERO(position)) {
+ fprintf(stderr, "PR_Seek64 failed\n");
+ exit(1);
+ }
+ PR_ASSERT(LL_EQ(position, offset));
+ strcpy(buf, MESSAGE);
+ nbytes = PR_Write(fd, buf, sizeof(buf));
+ if (nbytes != sizeof(buf)) {
+ fprintf(stderr, "PR_Write failed\n");
+ exit(1);
+ }
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ memset(buf, 0, sizeof(buf));
+
+#ifdef _WIN32
+ hFile = CreateFile(TEST_FILE_NAME, GENERIC_READ, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "CreateFile failed\n");
+ exit(1);
+ }
+ li.QuadPart = offset;
+ li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
+ fprintf(stderr, "SetFilePointer failed\n");
+ exit(1);
+ }
+ PR_ASSERT(li.QuadPart == offset);
+ if (ReadFile(hFile, buf, sizeof(buf), &nbytes, NULL) == 0) {
+ fprintf(stderr, "ReadFile failed\n");
+ exit(1);
+ }
+ PR_ASSERT(nbytes == sizeof(buf));
+ if (strcmp(buf, MESSAGE)) {
+ fprintf(stderr, "corrupt data:$%s$\n", buf);
+ exit(1);
+ }
+ if (CloseHandle(hFile) == 0) {
+ fprintf(stderr, "CloseHandle failed\n");
+ exit(1);
+ }
+#endif /* _WIN32 */
+
+ if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) {
+ fprintf(stderr, "PR_Delete failed\n");
+ exit(1);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile3.c b/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile3.c
new file mode 100644
index 00000000..6fa25ca6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/bigfile3.c
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#define TEST_FILE_NAME "bigfile3.txt"
+
+#define MESSAGE "Hello world!"
+#define MESSAGE_SIZE 13
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *fd;
+ PRInt64 offset, position;
+ PRInt32 nbytes;
+ char buf[MESSAGE_SIZE];
+#ifdef _WIN32
+ HANDLE hFile;
+ LARGE_INTEGER li;
+#endif /* _WIN32 */
+
+ LL_I2L(offset, 1);
+ LL_SHL(offset, offset, 32);
+
+#ifdef _WIN32
+ hFile = CreateFile(TEST_FILE_NAME, GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "CreateFile failed\n");
+ exit(1);
+ }
+ li.QuadPart = offset;
+ li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
+ if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
+ fprintf(stderr, "SetFilePointer failed\n");
+ exit(1);
+ }
+ PR_ASSERT(li.QuadPart == offset);
+ strcpy(buf, MESSAGE);
+ if (WriteFile(hFile, buf, sizeof(buf), &nbytes, NULL) == 0) {
+ fprintf(stderr, "WriteFile failed\n");
+ exit(1);
+ }
+ PR_ASSERT(nbytes == sizeof(buf));
+ if (CloseHandle(hFile) == 0) {
+ fprintf(stderr, "CloseHandle failed\n");
+ exit(1);
+ }
+#endif /* _WIN32 */
+
+ memset(buf, 0, sizeof(buf));
+
+ fd = PR_Open(TEST_FILE_NAME, PR_RDONLY, 0666);
+ if (fd == NULL) {
+ fprintf(stderr, "PR_Open failed\n");
+ exit(1);
+ }
+ position = PR_Seek64(fd, offset, PR_SEEK_SET);
+ if (!LL_GE_ZERO(position)) {
+ fprintf(stderr, "PR_Seek64 failed\n");
+ exit(1);
+ }
+ PR_ASSERT(LL_EQ(position, offset));
+ nbytes = PR_Read(fd, buf, sizeof(buf));
+ if (nbytes != sizeof(buf)) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ if (strcmp(buf, MESSAGE)) {
+ fprintf(stderr, "corrupt data:$%s$\n", buf);
+ exit(1);
+ }
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) {
+ fprintf(stderr, "PR_Delete failed\n");
+ exit(1);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/bug1test.c b/src/libs/xpcom18a4/nsprpub/pr/tests/bug1test.c
new file mode 100644
index 00000000..fa7d591f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/bug1test.c
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+Attached is a test program that uses the nspr1 to demonstrate a bug
+under NT4.0. The fix has already been mentioned (add a ResetEvent just
+before leaving the critical section in _PR_CondWait in hwmon.c).
+*/
+
+#include "prthread.h"
+#include "prtypes.h"
+#include "prinit.h"
+#include "prmon.h"
+#include "prlog.h"
+
+typedef struct Arg_s
+{
+ PRInt32 a, b;
+} Arg_t;
+
+PRMonitor* gMonitor; // the monitor
+PRInt32 gReading; // number of read locks
+PRInt32 gWriteWaiting; // number of threads waiting for write lock
+PRInt32 gReadWaiting; // number of threads waiting for read lock
+
+PRInt32 gCounter; // a counter
+
+ // stats
+PRInt32 gReads; // number of successful reads
+PRInt32 gMaxReads; // max number of simultaneous reads
+PRInt32 gMaxWriteWaits; // max number of writes that waited for read
+PRInt32 gMaxReadWaits; // max number of reads that waited for write wait
+
+
+void spin (PRInt32 aDelay)
+{
+ PRInt32 index;
+ PRInt32 delay = aDelay * 1000;
+
+ PR_Sleep(0);
+
+ // randomize delay a bit
+ delay = (delay / 2) + (PRInt32)((float)delay *
+ ((float)rand () / (float)RAND_MAX));
+
+ for (index = 0; index < delay * 10; index++)
+ // consume a bunch of cpu cycles
+ ;
+ PR_Sleep(0);
+}
+
+void doWriteThread (void* arg)
+{
+ PRInt32 last;
+ Arg_t *args = (Arg_t*)arg;
+ PRInt32 aWorkDelay = args->a, aWaitDelay = args->b;
+ PR_Sleep(0);
+
+ while (1)
+ {
+ // -- enter write lock
+ PR_EnterMonitor (gMonitor);
+
+ if (0 < gReading) // wait for read locks to go away
+ {
+ PRIntervalTime fiveSecs = PR_SecondsToInterval(5);
+
+ gWriteWaiting++;
+ if (gWriteWaiting > gMaxWriteWaits) // stats
+ gMaxWriteWaits = gWriteWaiting;
+ while (0 < gReading)
+ PR_Wait (gMonitor, fiveSecs);
+ gWriteWaiting--;
+ }
+ // -- write lock entered
+
+ last = gCounter;
+ gCounter++;
+
+ spin (aWorkDelay);
+
+ PR_ASSERT (gCounter == (last + 1)); // test invariance
+
+ // -- exit write lock
+// if (0 < gReadWaiting) // notify waiting reads (do it anyway to show off the CondWait bug)
+ PR_NotifyAll (gMonitor);
+
+ PR_ExitMonitor (gMonitor);
+ // -- write lock exited
+
+ spin (aWaitDelay);
+ }
+}
+
+void doReadThread (void* arg)
+{
+ PRInt32 last;
+ Arg_t *args = (Arg_t*)arg;
+ PRInt32 aWorkDelay = args->a, aWaitDelay = args->b;
+ PR_Sleep(0);
+
+ while (1)
+ {
+ // -- enter read lock
+ PR_EnterMonitor (gMonitor);
+
+ if (0 < gWriteWaiting) // give up the monitor to waiting writes
+ {
+ PRIntervalTime fiveSecs = PR_SecondsToInterval(5);
+
+ gReadWaiting++;
+ if (gReadWaiting > gMaxReadWaits) // stats
+ gMaxReadWaits = gReadWaiting;
+ while (0 < gWriteWaiting)
+ PR_Wait (gMonitor, fiveSecs);
+ gReadWaiting--;
+ }
+
+ gReading++;
+
+ gReads++; // stats
+ if (gReading > gMaxReads) // stats
+ gMaxReads = gReading;
+
+ PR_ExitMonitor (gMonitor);
+ // -- read lock entered
+
+ last = gCounter;
+
+ spin (aWorkDelay);
+
+ PR_ASSERT (gCounter == last); // test invariance
+
+ // -- exit read lock
+ PR_EnterMonitor (gMonitor); // read unlock
+ gReading--;
+
+// if ((0 == gReading) && (0 < gWriteWaiting)) // notify waiting writes (do it anyway to show off the CondWait bug)
+ PR_NotifyAll (gMonitor);
+ PR_ExitMonitor (gMonitor);
+ // -- read lock exited
+
+ spin (aWaitDelay);
+ }
+}
+
+
+void fireThread (
+ char* aName, void (*aProc)(void *arg), Arg_t *aArg)
+{
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, aProc, aArg, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+}
+
+int pseudoMain (int argc, char** argv, char *pad)
+{
+ PRInt32 lastWriteCount = gCounter;
+ PRInt32 lastReadCount = gReads;
+ Arg_t a1 = {500, 250};
+ Arg_t a2 = {500, 500};
+ Arg_t a3 = {250, 500};
+ Arg_t a4 = {750, 250};
+ Arg_t a5 = {100, 750};
+ Arg_t a6 = {100, 500};
+ Arg_t a7 = {100, 750};
+
+ gMonitor = PR_NewMonitor ();
+
+ fireThread ("R1", doReadThread, &a1);
+ fireThread ("R2", doReadThread, &a2);
+ fireThread ("R3", doReadThread, &a3);
+ fireThread ("R4", doReadThread, &a4);
+
+ fireThread ("W1", doWriteThread, &a5);
+ fireThread ("W2", doWriteThread, &a6);
+ fireThread ("W3", doWriteThread, &a7);
+
+ fireThread ("R5", doReadThread, &a1);
+ fireThread ("R6", doReadThread, &a2);
+ fireThread ("R7", doReadThread, &a3);
+ fireThread ("R8", doReadThread, &a4);
+
+ fireThread ("W4", doWriteThread, &a5);
+ fireThread ("W5", doWriteThread, &a6);
+ fireThread ("W6", doWriteThread, &a7);
+
+ while (1)
+ {
+ PRInt32 writeCount, readCount;
+ PRIntervalTime fiveSecs = PR_SecondsToInterval(5);
+ PR_Sleep (fiveSecs); // get out of the way
+
+ // print some stats, not threadsafe, informative only
+ writeCount = gCounter;
+ readCount = gReads;
+ printf ("\ntick %d writes (+%d), %d reads (+%d) [max %d, %d, %d]",
+ writeCount, writeCount - lastWriteCount,
+ readCount, readCount - lastReadCount,
+ gMaxReads, gMaxWriteWaits, gMaxReadWaits);
+ lastWriteCount = writeCount;
+ lastReadCount = readCount;
+ gMaxReads = gMaxWriteWaits = gMaxReadWaits = 0;
+ }
+ return 0;
+}
+
+
+static void padStack (int argc, char** argv)
+{
+ char pad[512]; /* Work around bug in nspr on windoze */
+ pseudoMain (argc, argv, pad);
+}
+
+void main (int argc, char **argv)
+{
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+ padStack (argc, argv);
+}
+
+
+/* bug1test.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/cleanup.c b/src/libs/xpcom18a4/nsprpub/pr/tests/cleanup.c
new file mode 100644
index 00000000..e94979e9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/cleanup.c
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prprf.h"
+#include "prio.h"
+#include "prinit.h"
+#include "prthread.h"
+#include "prinrval.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+static void PR_CALLBACK Thread(void *sleep)
+{
+ PR_Sleep(PR_SecondsToInterval((PRUint32)sleep));
+ printf("Thread exiting\n");
+}
+
+static void Help(void)
+{
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+ PR_fprintf(err, "Cleanup usage: [-g] [-s n] [-t n] [-c n] [-h]\n");
+ PR_fprintf(err, "\t-c Call cleanup before exiting (default: false)\n");
+ PR_fprintf(err, "\t-G Use global threads only (default: local)\n");
+ PR_fprintf(err, "\t-t n Number of threads involved (default: 1)\n");
+ PR_fprintf(err, "\t-s n Seconds thread(s) should dally (defaut: 10)\n");
+ PR_fprintf(err, "\t-S n Seconds main() should dally (defaut: 5)\n");
+ PR_fprintf(err, "\t-C n Value to set concurrency (default 1)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ PRBool cleanup = PR_FALSE;
+ PRThreadScope type = PR_LOCAL_THREAD;
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Ghs:S:t:cC:");
+ PRIntn concurrency = 1, child_sleep = 10, main_sleep = 5, threads = 1;
+
+ PR_STDIO_INIT();
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'c': /* call PR_Cleanup() before exiting */
+ cleanup = PR_TRUE;
+ break;
+ case 'G': /* local vs global threads */
+ type = PR_GLOBAL_THREAD;
+ break;
+ case 's': /* time to sleep */
+ child_sleep = atoi(opt->value);
+ break;
+ case 'S': /* time to sleep */
+ main_sleep = atoi(opt->value);
+ break;
+ case 'C': /* number of cpus to create */
+ concurrency = atoi(opt->value);
+ break;
+ case 't': /* number of threads to create */
+ threads = atoi(opt->value);
+ break;
+ case 'h': /* user wants some guidance */
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_fprintf(err, "Cleanup settings\n");
+ PR_fprintf(err, "\tThread type: %s\n",
+ (PR_LOCAL_THREAD == type) ? "LOCAL" : "GLOBAL");
+ PR_fprintf(err, "\tConcurrency: %d\n", concurrency);
+ PR_fprintf(err, "\tNumber of threads: %d\n", threads);
+ PR_fprintf(err, "\tThread sleep: %d\n", child_sleep);
+ PR_fprintf(err, "\tMain sleep: %d\n", main_sleep);
+ PR_fprintf(err, "\tCleanup will %sbe called\n\n", (cleanup) ? "" : "NOT ");
+
+ PR_SetConcurrency(concurrency);
+
+ while (threads-- > 0)
+ (void)PR_CreateThread(
+ PR_USER_THREAD, Thread, (void*)child_sleep, PR_PRIORITY_NORMAL,
+ type, PR_UNJOINABLE_THREAD, 0);
+ PR_Sleep(PR_SecondsToInterval(main_sleep));
+
+ if (cleanup) PR_Cleanup();
+
+ PR_fprintf(err, "main() exiting\n");
+ return 0;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/cltsrv.c b/src/libs/xpcom18a4/nsprpub/pr/tests/cltsrv.c
new file mode 100644
index 00000000..96027843
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/cltsrv.c
@@ -0,0 +1,1226 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *
+ * Notes:
+ * [1] lth. The call to Sleep() is a hack to get the test case to run
+ * on Windows 95. Without it, the test case fails with an error
+ * WSAECONNRESET following a recv() call. The error is caused by the
+ * server side thread termination without a shutdown() or closesocket()
+ * call. Windows docmunentation suggests that this is predicted
+ * behavior; that other platforms get away with it is ... serindipity.
+ * The test case should shutdown() or closesocket() before
+ * thread termination. I didn't have time to figure out where or how
+ * to do it. The Sleep() call inserts enough delay to allow the
+ * client side to recv() all his data before the server side thread
+ * terminates. Whew! ...
+ *
+ ** Modification History:
+ * 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+ * The debug mode will print all of the printfs associated with this test.
+ * The regress mode will be the default mode. Since the regress tool limits
+ * the output to a one line status:PASS or FAIL,all of the printf statements
+ * have been handled with an if (debug_mode) statement.
+ */
+
+#include "prclist.h"
+#include "prcvar.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prtime.h"
+#include "prmem.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prthread.h"
+
+#include "pprio.h"
+#include "primpl.h"
+
+#include "plstr.h"
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#if defined(XP_UNIX)
+#include <math.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+/*
+** This is the beginning of the test
+*/
+
+#define RECV_FLAGS 0
+#define SEND_FLAGS 0
+#define DEFAULT_LOW 0
+#define DEFAULT_HIGH 0
+#define BUFFER_SIZE 1024
+#define DEFAULT_BACKLOG 5
+#define DEFAULT_PORT 12849
+#define DEFAULT_CLIENTS 1
+#define ALLOWED_IN_ACCEPT 1
+#define DEFAULT_CLIPPING 1000
+#define DEFAULT_WORKERS_MIN 1
+#define DEFAULT_WORKERS_MAX 1
+#define DEFAULT_SERVER "localhost"
+#define DEFAULT_EXECUTION_TIME 10
+#define DEFAULT_CLIENT_TIMEOUT 4000
+#define DEFAULT_SERVER_TIMEOUT 4000
+#define DEFAULT_SERVER_PRIORITY PR_PRIORITY_HIGH
+
+typedef enum CSState_e {cs_init, cs_run, cs_stop, cs_exit} CSState_t;
+
+static void PR_CALLBACK Worker(void *arg);
+typedef struct CSPool_s CSPool_t;
+typedef struct CSWorker_s CSWorker_t;
+typedef struct CSServer_s CSServer_t;
+typedef enum Verbosity
+{
+ TEST_LOG_ALWAYS,
+ TEST_LOG_ERROR,
+ TEST_LOG_WARNING,
+ TEST_LOG_NOTICE,
+ TEST_LOG_INFO,
+ TEST_LOG_STATUS,
+ TEST_LOG_VERBOSE
+} Verbosity;
+
+static PRInt32 domain = AF_INET;
+static PRInt32 protocol = 6; /* TCP */
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE;
+static PRBool pthread_stats = PR_FALSE;
+static Verbosity verbosity = TEST_LOG_ALWAYS;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+struct CSWorker_s
+{
+ PRCList element; /* list of the server's workers */
+
+ PRThread *thread; /* this worker objects thread */
+ CSServer_t *server; /* back pointer to server structure */
+};
+
+struct CSPool_s
+{
+ PRCondVar *exiting;
+ PRCondVar *acceptComplete;
+ PRUint32 accepting, active, workers;
+};
+
+struct CSServer_s
+{
+ PRCList list; /* head of worker list */
+
+ PRLock *ml;
+ PRThread *thread; /* the main server thread */
+ PRCondVar *stateChange;
+
+ PRUint16 port; /* port we're listening on */
+ PRUint32 backlog; /* size of our listener backlog */
+ PRFileDesc *listener; /* the fd accepting connections */
+
+ CSPool_t pool; /* statistics on worker threads */
+ CSState_t state; /* the server's state */
+ struct /* controlling worker counts */
+ {
+ PRUint32 minimum, maximum, accepting;
+ } workers;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+};
+
+typedef struct CSDescriptor_s
+{
+ PRInt32 size; /* size of transfer */
+ char filename[60]; /* filename, null padded */
+} CSDescriptor_t;
+
+typedef struct CSClient_s
+{
+ PRLock *ml;
+ PRThread *thread;
+ PRCondVar *stateChange;
+ PRNetAddr serverAddress;
+
+ CSState_t state;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+} CSClient_t;
+
+#define TEST_LOG(l, p, a) \
+ do { \
+ if (debug_mode || (p <= verbosity)) printf a; \
+ } while (0)
+
+PRLogModuleInfo *cltsrv_log_file = NULL;
+
+#define MY_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+#define TEST_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+static void _MY_Assert(const char *s, const char *file, PRIntn ln)
+{
+ PL_PrintError(NULL);
+#if DEBUG
+ PR_Assert(s, file, ln);
+#endif
+} /* _MW_Assert */
+
+static PRBool Aborted(PRStatus rv)
+{
+ return ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) ?
+ PR_TRUE : PR_FALSE;
+}
+
+static void TimeOfDayMessage(const char *msg, PRThread* me)
+{
+ char buffer[100];
+ PRExplodedTime tod;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod);
+ (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("%s(0x%p): %s\n", msg, me, buffer));
+} /* TimeOfDayMessage */
+
+
+static void PR_CALLBACK Client(void *arg)
+{
+ PRStatus rv;
+ PRIntn index;
+ char buffer[1024];
+ PRFileDesc *fd = NULL;
+ PRUintn clipping = DEFAULT_CLIPPING;
+ PRThread *me = PR_CurrentThread();
+ CSClient_t *client = (CSClient_t*)arg;
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT);
+
+
+ for (index = 0; index < sizeof(buffer); ++index)
+ buffer[index] = (char)index;
+
+ client->started = PR_IntervalNow();
+
+ PR_Lock(client->ml);
+ client->state = cs_run;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+
+ TimeOfDayMessage("Client started at", me);
+
+ while (cs_run == client->state)
+ {
+ PRInt32 bytes, descbytes, filebytes, netbytes;
+
+ (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
+ TEST_LOG(cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): connecting to server at %s\n", me, buffer));
+
+ fd = PR_Socket(domain, SOCK_STREAM, protocol);
+ TEST_ASSERT(NULL != fd);
+ rv = PR_Connect(fd, &client->serverAddress, timeout);
+ if (PR_FAILURE == rv)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): conection failed (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+
+ memset(descriptor, 0, sizeof(*descriptor));
+ descriptor->size = PR_htonl(descbytes = rand() % clipping);
+ PR_snprintf(
+ descriptor->filename, sizeof(descriptor->filename),
+ "CS%p%p-%p.dat", client->started, me, client->operations);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
+ bytes = PR_Send(
+ fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
+ if (sizeof(CSDescriptor_t) != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send descriptor timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send data timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(bytes == filebytes);
+ netbytes += bytes;
+ }
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ if (Aborted(PR_FAILURE))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data aborted\n", me));
+ goto aborted;
+ }
+ else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto retry;
+ }
+ if (0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tClient(0x%p): unexpected end of stream\n",
+ PR_CurrentThread()));
+ break;
+ }
+ filebytes += bytes;
+ }
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+retry:
+ (void)PR_Close(fd); fd = NULL;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): disconnected from server\n", me));
+
+ PR_Lock(client->ml);
+ client->operations += 1;
+ client->bytesTransferred += 2 * descbytes;
+ rv = PR_WaitCondVar(client->stateChange, rand() % clipping);
+ PR_Unlock(client->ml);
+ if (Aborted(rv)) break;
+ }
+
+aborted:
+ client->stopped = PR_IntervalNow();
+
+ PR_ClearInterrupt();
+ if (NULL != fd) rv = PR_Close(fd);
+
+ PR_Lock(client->ml);
+ client->state = cs_exit;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+ PR_DELETE(descriptor);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
+ PR_CurrentThread(), client->operations, client->bytesTransferred));
+
+} /* Client */
+
+static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
+{
+ PRStatus drv, rv;
+ char buffer[1024];
+ PRFileDesc *file = NULL;
+ PRThread * me = PR_CurrentThread();
+ PRInt32 bytes, descbytes, netbytes, filebytes = 0;
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receiving desciptor\n", me));
+ bytes = PR_Recv(
+ fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto exit;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): receive timeout\n", me));
+ }
+ goto exit;
+ }
+ if (0 == bytes)
+ {
+ rv = PR_FAILURE;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): unexpected end of file\n", me));
+ goto exit;
+ }
+ descbytes = PR_ntohl(descriptor->size);
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
+ me, descbytes, descriptor->filename));
+
+ file = PR_Open(
+ descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): open file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(NULL != file);
+
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
+ goto aborted;
+ }
+ /*
+ * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED)
+ * on NT here. This is equivalent to ECONNRESET on Unix.
+ * -wtc
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ if(0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
+ rv = PR_FAILURE;
+ goto aborted;
+ }
+ filebytes += bytes;
+ netbytes = bytes;
+ /* The byte count for PR_Write should be positive */
+ MY_ASSERT(netbytes > 0);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
+ bytes = PR_Write(file, buffer, netbytes);
+ if (netbytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): write file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->operations += 1;
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Close(file);
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+ file = NULL;
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
+ file = PR_Open(descriptor->filename, PR_RDONLY, 0);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): open file timeout\n",
+ PR_CurrentThread()));
+ goto aborted;
+ }
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(NULL != file);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
+ bytes = PR_Read(file, buffer, filebytes);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): read file timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(bytes > 0);
+ netbytes += bytes;
+ filebytes = bytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): send data timeout\n", me));
+ goto aborted;
+ }
+ break;
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+
+ rv = PR_Close(file);
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+ file = NULL;
+
+aborted:
+ PR_ClearInterrupt();
+ if (NULL != file) PR_Close(file);
+ drv = PR_Delete(descriptor->filename);
+ TEST_ASSERT(PR_SUCCESS == drv);
+exit:
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): Finished\n", me));
+
+ PR_DELETE(descriptor);
+
+#if defined(WIN95)
+ PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */
+#endif
+ return rv;
+} /* ProcessRequest */
+
+static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool)
+{
+ CSWorker_t *worker = PR_NEWZAP(CSWorker_t);
+ worker->server = server;
+ PR_INIT_CLIST(&worker->element);
+ worker->thread = PR_CreateThread(
+ PR_USER_THREAD, Worker, worker,
+ DEFAULT_SERVER_PRIORITY, thread_scope,
+ PR_UNJOINABLE_THREAD, 0);
+ if (NULL == worker->thread)
+ {
+ PR_DELETE(worker);
+ return PR_FAILURE;
+ }
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("\tCreateWorker(0x%p): create new worker (0x%p)\n",
+ PR_CurrentThread(), worker->thread));
+
+ return PR_SUCCESS;
+} /* CreateWorker */
+
+static void PR_CALLBACK Worker(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr from;
+ PRFileDesc *fd = NULL;
+ PRThread *me = PR_CurrentThread();
+ CSWorker_t *worker = (CSWorker_t*)arg;
+ CSServer_t *server = worker->server;
+ CSPool_t *pool = &server->pool;
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1));
+
+ PR_Lock(server->ml);
+ PR_APPEND_LINK(&worker->element, &server->list);
+ pool->workers += 1; /* define our existance */
+
+ while (cs_run == server->state)
+ {
+ while (pool->accepting >= server->workers.accepting)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): waiting for accept slot[%d]\n",
+ me, pool->accepting));
+ rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT);
+ if (Aborted(rv) || (cs_run != server->state))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tWorker(0x%p): has been %s\n",
+ me, (Aborted(rv) ? "interrupted" : "stopped")));
+ goto exit;
+ }
+ }
+ pool->accepting += 1; /* how many are really in accept */
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): calling accept\n", me));
+ fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT);
+
+ PR_Lock(server->ml);
+ pool->accepting -= 1;
+ PR_NotifyCondVar(pool->acceptComplete);
+
+ if ((NULL == fd) && Aborted(PR_FAILURE))
+ {
+ if (NULL != server->listener)
+ {
+ PR_Close(server->listener);
+ server->listener = NULL;
+ }
+ goto exit;
+ }
+
+ if (NULL != fd)
+ {
+ /*
+ ** Create another worker of the total number of workers is
+ ** less than the minimum specified or we have none left in
+ ** accept() AND we're not over the maximum.
+ ** This sort of presumes that the number allowed in accept
+ ** is at least as many as the minimum. Otherwise we'll keep
+ ** creating new threads and deleting them soon after.
+ */
+ PRBool another =
+ ((pool->workers < server->workers.minimum) ||
+ ((0 == pool->accepting)
+ && (pool->workers < server->workers.maximum))) ?
+ PR_TRUE : PR_FALSE;
+ pool->active += 1;
+ PR_Unlock(server->ml);
+
+ if (another) (void)CreateWorker(server, pool);
+
+ rv = ProcessRequest(fd, server);
+ if (PR_SUCCESS != rv)
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tWorker(0x%p): server process ended abnormally\n", me));
+ (void)PR_Close(fd); fd = NULL;
+
+ PR_Lock(server->ml);
+ pool->active -= 1;
+ }
+ }
+
+exit:
+ PR_ClearInterrupt();
+ PR_Unlock(server->ml);
+
+ if (NULL != fd)
+ {
+ (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ (void)PR_Close(fd);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): exiting [%u]\n", PR_CurrentThread(), pool->workers));
+
+ PR_Lock(server->ml);
+ pool->workers -= 1; /* undefine our existance */
+ PR_REMOVE_AND_INIT_LINK(&worker->element);
+ PR_NotifyCondVar(pool->exiting);
+ PR_Unlock(server->ml);
+
+ PR_DELETE(worker); /* destruction of the "worker" object */
+
+} /* Worker */
+
+static void PR_CALLBACK Server(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr serverAddress;
+ PRThread *me = PR_CurrentThread();
+ CSServer_t *server = (CSServer_t*)arg;
+ PRSocketOptionData sockOpt;
+
+ server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
+
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(server->listener, &sockOpt);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ memset(&serverAddress, 0, sizeof(serverAddress));
+ if (PR_AF_INET6 != domain)
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
+ else
+ rv = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, DEFAULT_PORT,
+ &serverAddress);
+ rv = PR_Bind(server->listener, &serverAddress);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Listen(server->listener, server->backlog);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ server->started = PR_IntervalNow();
+ TimeOfDayMessage("Server started at", me);
+
+ PR_Lock(server->ml);
+ server->state = cs_run;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ /*
+ ** Create the first worker (actually, a thread that accepts
+ ** connections and then processes the work load as needed).
+ ** From this point on, additional worker threads are created
+ ** as they are needed by existing worker threads.
+ */
+ rv = CreateWorker(server, &server->pool);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ /*
+ ** From here on this thread is merely hanging around as the contact
+ ** point for the main test driver. It's just waiting for the driver
+ ** to declare the test complete.
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): waiting for state change\n", me));
+
+ PR_Lock(server->ml);
+ while ((cs_run == server->state) && !Aborted(rv))
+ {
+ rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(server->ml);
+ PR_ClearInterrupt();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tServer(0x%p): shutting down workers\n", me));
+
+ /*
+ ** Get all the worker threads to exit. They know how to
+ ** clean up after themselves, so this is just a matter of
+ ** waiting for clorine in the pool to take effect. During
+ ** this stage we're ignoring interrupts.
+ */
+ server->workers.minimum = server->workers.maximum = 0;
+
+ PR_Lock(server->ml);
+ while (!PR_CLIST_IS_EMPTY(&server->list))
+ {
+ PRCList *head = PR_LIST_HEAD(&server->list);
+ CSWorker_t *worker = (CSWorker_t*)head;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
+ rv = PR_Interrupt(worker->thread);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_REMOVE_AND_INIT_LINK(head);
+ }
+
+ while (server->pool.workers > 0)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tServer(0x%p): waiting for %u workers to exit\n",
+ me, server->pool.workers));
+ (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ server->state = cs_exit;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tServer(0x%p): stopped after %u operations and %u bytes\n",
+ me, server->operations, server->bytesTransferred));
+
+ if (NULL != server->listener) PR_Close(server->listener);
+ server->stopped = PR_IntervalNow();
+
+} /* Server */
+
+static void WaitForCompletion(PRIntn execution)
+{
+ while (execution > 0)
+ {
+ PRIntn dally = (execution > 30) ? 30 : execution;
+ PR_Sleep(PR_SecondsToInterval(dally));
+ if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+ execution -= dally;
+ }
+} /* WaitForCompletion */
+
+static void Help(void)
+{
+ PR_fprintf(debug_out, "cltsrv test program usage:\n");
+ PR_fprintf(debug_out, "\t-a <n> threads allowed in accept (5)\n");
+ PR_fprintf(debug_out, "\t-b <n> backlock for listen (5)\n");
+ PR_fprintf(debug_out, "\t-c <threads> number of clients to create (1)\n");
+ PR_fprintf(debug_out, "\t-f <low> low water mark for fd caching (0)\n");
+ PR_fprintf(debug_out, "\t-F <high> high water mark for fd caching (0)\n");
+ PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
+ PR_fprintf(debug_out, "\t-s <string> dsn name of server (localhost)\n");
+ PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n");
+ PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n");
+ PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n");
+ PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n");
+ PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n");
+ PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n");
+ PR_fprintf(debug_out, "\t-h this message\n");
+} /* Help */
+
+static Verbosity IncrementVerbosity(void)
+{
+ PRIntn verboge = (PRIntn)verbosity + 1;
+ return (Verbosity)verboge;
+} /* IncrementVerbosity */
+
+PRIntn main(PRIntn argc, char** argv)
+{
+ PRUintn index;
+ PRBool boolean;
+ CSClient_t *client;
+ PRStatus rv, joinStatus;
+ CSServer_t *server = NULL;
+
+ PRUintn backlog = DEFAULT_BACKLOG;
+ PRUintn clients = DEFAULT_CLIENTS;
+ const char *serverName = DEFAULT_SERVER;
+ PRBool serverIsLocal = PR_TRUE;
+ PRUintn accepting = ALLOWED_IN_ACCEPT;
+ PRUintn workersMin = DEFAULT_WORKERS_MIN;
+ PRUintn workersMax = DEFAULT_WORKERS_MAX;
+ PRIntn execution = DEFAULT_EXECUTION_TIME;
+ PRIntn low = DEFAULT_LOW, high = DEFAULT_HIGH;
+
+ /*
+ * -G use global threads
+ * -a <n> threads allowed in accept
+ * -b <n> backlock for listen
+ * -c <threads> number of clients to create
+ * -f <low> low water mark for caching FDs
+ * -F <high> high water mark for caching FDs
+ * -w <threads> minimal number of server threads
+ * -W <threads> maximum number of server threads
+ * -e <seconds> duration of the test in seconds
+ * -s <string> dsn name of server (implies no server here)
+ * -v verbosity
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:f:F:w:W:e:s:vdhp");
+
+ debug_out = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'X': /* use XTP as transport */
+ protocol = 36;
+ break;
+ case '6': /* Use IPv6 */
+ domain = PR_AF_INET6;
+ break;
+ case 'a': /* the value for accepting */
+ accepting = atoi(opt->value);
+ break;
+ case 'b': /* the value for backlock */
+ backlog = atoi(opt->value);
+ break;
+ case 'c': /* number of client threads */
+ clients = atoi(opt->value);
+ break;
+ case 'f': /* low water fd cache */
+ low = atoi(opt->value);
+ break;
+ case 'F': /* low water fd cache */
+ high = atoi(opt->value);
+ break;
+ case 'w': /* minimum server worker threads */
+ workersMin = atoi(opt->value);
+ break;
+ case 'W': /* maximum server worker threads */
+ workersMax = atoi(opt->value);
+ break;
+ case 'e': /* program execution time in seconds */
+ execution = atoi(opt->value);
+ break;
+ case 's': /* server's address */
+ serverName = opt->value;
+ break;
+ case 'v': /* verbosity */
+ verbosity = IncrementVerbosity();
+ break;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'p': /* pthread mode */
+ pthread_stats = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE;
+ if (0 == execution) execution = DEFAULT_EXECUTION_TIME;
+ if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX;
+ if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN;
+ if (0 == accepting) accepting = ALLOWED_IN_ACCEPT;
+ if (0 == backlog) backlog = DEFAULT_BACKLOG;
+
+ if (workersMin > accepting) accepting = workersMin;
+
+ PR_STDIO_INIT();
+ TimeOfDayMessage("Client/Server started at", PR_CurrentThread());
+
+ cltsrv_log_file = PR_NewLogModule("cltsrv_log");
+ MY_ASSERT(NULL != cltsrv_log_file);
+ boolean = PR_SetLogFile("cltsrv.log");
+ MY_ASSERT(boolean);
+
+#ifdef XP_MAC
+ debug_mode = PR_TRUE;
+#endif
+
+ rv = PR_SetFDCacheSize(low, high);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ if (serverIsLocal)
+ {
+ /* Establish the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): starting server\n", PR_CurrentThread()));
+
+ server = PR_NEWZAP(CSServer_t);
+ PR_INIT_CLIST(&server->list);
+ server->state = cs_init;
+ server->ml = PR_NewLock();
+ server->backlog = backlog;
+ server->port = DEFAULT_PORT;
+ server->workers.minimum = workersMin;
+ server->workers.maximum = workersMax;
+ server->workers.accepting = accepting;
+ server->stateChange = PR_NewCondVar(server->ml);
+ server->pool.exiting = PR_NewCondVar(server->ml);
+ server->pool.acceptComplete = PR_NewCondVar(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): creating server thread\n", PR_CurrentThread()));
+
+ server->thread = PR_CreateThread(
+ PR_USER_THREAD, Server, server, PR_PRIORITY_HIGH,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ TEST_ASSERT(NULL != server->thread);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): waiting for server init\n", PR_CurrentThread()));
+
+ PR_Lock(server->ml);
+ while (server->state == cs_init)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): server init complete (port #%d)\n",
+ PR_CurrentThread(), server->port));
+ }
+
+ if (clients != 0)
+ {
+ /* Create all of the clients */
+ PRHostEnt host;
+ char buffer[BUFFER_SIZE];
+ client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t));
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): creating %d client threads\n",
+ PR_CurrentThread(), clients));
+
+ if (!serverIsLocal)
+ {
+ rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host);
+ if (PR_SUCCESS != rv)
+ {
+ PL_FPrintError(PR_STDERR, "PR_GetHostByName");
+ return 2;
+ }
+ }
+
+ for (index = 0; index < clients; ++index)
+ {
+ client[index].state = cs_init;
+ client[index].ml = PR_NewLock();
+ if (serverIsLocal)
+ {
+ if (PR_AF_INET6 != domain)
+ (void)PR_InitializeNetAddr(
+ PR_IpAddrLoopback, DEFAULT_PORT,
+ &client[index].serverAddress);
+ else
+ rv = PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6,
+ DEFAULT_PORT, &client[index].serverAddress);
+ }
+ else
+ {
+ (void)PR_EnumerateHostEnt(
+ 0, &host, DEFAULT_PORT, &client[index].serverAddress);
+ }
+ client[index].stateChange = PR_NewCondVar(client[index].ml);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): creating client threads\n", PR_CurrentThread()));
+ client[index].thread = PR_CreateThread(
+ PR_USER_THREAD, Client, &client[index], PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ TEST_ASSERT(NULL != client[index].thread);
+ PR_Lock(client[index].ml);
+ while (cs_init == client[index].state)
+ PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(client[index].ml);
+ }
+ }
+
+ /* Then just let them go at it for a bit */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): waiting for execution interval (%d seconds)\n",
+ PR_CurrentThread(), execution));
+
+ WaitForCompletion(execution);
+
+ TimeOfDayMessage("Shutting down", PR_CurrentThread());
+
+ if (clients != 0)
+ {
+ for (index = 0; index < clients; ++index)
+ {
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("main(0x%p): notifying client(0x%p) to stop\n",
+ PR_CurrentThread(), client[index].thread));
+
+ PR_Lock(client[index].ml);
+ if (cs_run == client[index].state)
+ {
+ client[index].state = cs_stop;
+ PR_Interrupt(client[index].thread);
+ while (cs_stop == client[index].state)
+ PR_WaitCondVar(
+ client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(client[index].ml);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): joining client(0x%p)\n",
+ PR_CurrentThread(), client[index].thread));
+
+ joinStatus = PR_JoinThread(client[index].thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+ PR_DestroyCondVar(client[index].stateChange);
+ PR_DestroyLock(client[index].ml);
+ }
+ PR_DELETE(client);
+ }
+
+ if (NULL != server)
+ {
+ /* All clients joined - retrieve the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): notifying server(0x%p) to stop\n",
+ PR_CurrentThread(), server->thread));
+
+ PR_Lock(server->ml);
+ server->state = cs_stop;
+ PR_Interrupt(server->thread);
+ while (cs_exit != server->state)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): joining server(0x%p)\n",
+ PR_CurrentThread(), server->thread));
+ joinStatus = PR_JoinThread(server->thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+
+ PR_DestroyCondVar(server->stateChange);
+ PR_DestroyCondVar(server->pool.exiting);
+ PR_DestroyCondVar(server->pool.acceptComplete);
+ PR_DestroyLock(server->ml);
+ PR_DELETE(server);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): test complete\n", PR_CurrentThread()));
+
+ PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+
+ TimeOfDayMessage("Test exiting at", PR_CurrentThread());
+ PR_Cleanup();
+ return 0;
+} /* main */
+
+/* cltsrv.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/concur.c b/src/libs/xpcom18a4/nsprpub/pr/tests/concur.c
new file mode 100644
index 00000000..225b2d28
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/concur.c
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: concur.c
+** Description: test of adding and removing concurrency options
+*/
+
+#include "prcvar.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prlock.h"
+#include "prprf.h"
+#include "prmem.h"
+#include "prlog.h"
+
+#include "plgetopt.h"
+
+#if defined(XP_MAC)
+#include "pprio.h"
+#else
+#include "private/pprio.h"
+#endif
+
+#include <stdlib.h>
+
+#define DEFAULT_RANGE 10
+#define DEFAULT_LOOPS 100
+
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+typedef struct Context
+{
+ PRLock *ml;
+ PRCondVar *cv;
+ PRIntn want, have;
+} Context;
+
+
+/*
+** Make the instance of 'context' static (not on the stack)
+** for Win16 threads
+*/
+static Context context = {NULL, NULL, 0, 0};
+
+static void PR_CALLBACK Dull(void *arg)
+{
+ Context *context = (Context*)arg;
+ PR_Lock(context->ml);
+ context->have += 1;
+ while (context->want >= context->have)
+ PR_WaitCondVar(context->cv, PR_INTERVAL_NO_TIMEOUT);
+ context->have -= 1;
+ PR_Unlock(context->ml);
+} /* Dull */
+
+PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv)
+{
+ PRUintn cpus;
+ PLOptStatus os;
+ PRThread **threads;
+ PRBool debug = PR_FALSE;
+ PRUintn range = DEFAULT_RANGE;
+ PRStatus rc;
+ PRUintn cnt;
+ PRUintn loops = DEFAULT_LOOPS;
+ PRIntervalTime hundredMills = PR_MillisecondsToInterval(100);
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:r:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* GLOBAL threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'd': /* debug mode */
+ debug = PR_TRUE;
+ break;
+ case 'r': /* range limit */
+ range = atoi(opt->value);
+ break;
+ case 'l': /* loop counter */
+ loops = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == range) range = DEFAULT_RANGE;
+ if (0 == loops) loops = DEFAULT_LOOPS;
+
+ context.ml = PR_NewLock();
+ context.cv = PR_NewCondVar(context.ml);
+
+ if (debug)
+ PR_fprintf(
+ PR_STDERR, "Testing with %d CPUs and %d interations\n", range, loops);
+
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * range);
+ while (--loops > 0)
+ {
+ for (cpus = 1; cpus <= range; ++cpus)
+ {
+ PR_SetConcurrency(cpus);
+ context.want = cpus;
+
+ threads[cpus - 1] = PR_CreateThread(
+ PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ }
+
+ PR_Sleep(hundredMills);
+
+ for (cpus = range; cpus > 0; cpus--)
+ {
+ PR_SetConcurrency(cpus);
+ context.want = cpus - 1;
+
+ PR_Lock(context.ml);
+ PR_NotifyCondVar(context.cv);
+ PR_Unlock(context.ml);
+ }
+ for(cnt = 0; cnt < range; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+ }
+ }
+
+
+ if (debug)
+ PR_fprintf(
+ PR_STDERR, "Waiting for %d thread(s) to exit\n", context.have);
+
+ while (context.have > 0) PR_Sleep(hundredMills);
+
+ if (debug)
+ PR_fprintf(
+ PR_STDERR, "Finished [want: %d, have: %d]\n",
+ context.want, context.have);
+
+ PR_DestroyLock(context.ml);
+ PR_DestroyCondVar(context.cv);
+ PR_DELETE(threads);
+
+ PR_fprintf(PR_STDERR, "PASSED\n");
+
+ return 0;
+} /* Concur */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PR_STDIO_INIT();
+ return PR_Initialize(Concur, argc, argv, 0);
+} /* main */
+
+/* concur.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/cvar.c b/src/libs/xpcom18a4/nsprpub/pr/tests/cvar.c
new file mode 100644
index 00000000..32d9f1be
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/cvar.c
@@ -0,0 +1,334 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1996 - Netscape Communications Corporation
+**
+** Name: cvar.c
+**
+** Description: Tests Condition Variable Operations
+**
+** Modification History:
+** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 Revert to return code 0 and 1.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+
+#include "nspr.h"
+
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+PRMonitor *mon;
+#define DEFAULT_COUNT 1000
+PRInt32 count = 0;
+PRIntn debug_mode;
+
+#define kQSIZE 1
+
+typedef struct {
+ PRLock *bufLock;
+ int startIdx;
+ int numFull;
+ PRCondVar *notFull;
+ PRCondVar *notEmpty;
+ void *data[kQSIZE];
+} CircBuf;
+
+static PRBool failed = PR_FALSE;
+
+/*
+** NewCB creates and initializes a new circular buffer.
+*/
+static CircBuf* NewCB(void)
+{
+ CircBuf *cbp;
+
+ cbp = PR_NEW(CircBuf);
+ if (cbp == NULL)
+ return (NULL);
+
+ cbp->bufLock = PR_NewLock();
+ cbp->startIdx = 0;
+ cbp->numFull = 0;
+ cbp->notFull = PR_NewCondVar(cbp->bufLock);
+ cbp->notEmpty = PR_NewCondVar(cbp->bufLock);
+
+ return (cbp);
+}
+
+/*
+** DeleteCB frees a circular buffer.
+*/
+static void DeleteCB(CircBuf *cbp)
+{
+ PR_DestroyLock(cbp->bufLock);
+ PR_DestroyCondVar(cbp->notFull);
+ PR_DestroyCondVar(cbp->notEmpty);
+ PR_DELETE(cbp);
+}
+
+
+/*
+** PutCBData puts new data on the queue. If the queue is full, it waits
+** until there is room.
+*/
+static void PutCBData(CircBuf *cbp, void *data)
+{
+ PR_Lock(cbp->bufLock);
+ /* wait while the buffer is full */
+ while (cbp->numFull == kQSIZE)
+ PR_WaitCondVar(cbp->notFull,PR_INTERVAL_NO_TIMEOUT);
+ cbp->data[(cbp->startIdx + cbp->numFull) % kQSIZE] = data;
+ cbp->numFull += 1;
+
+ /* let a waiting reader know that there is data */
+ PR_NotifyCondVar(cbp->notEmpty);
+ PR_Unlock(cbp->bufLock);
+
+}
+
+
+/*
+** GetCBData gets the oldest data on the queue. If the queue is empty, it waits
+** until new data appears.
+*/
+static void* GetCBData(CircBuf *cbp)
+{
+ void *data;
+
+ PR_Lock(cbp->bufLock);
+ /* wait while the buffer is empty */
+ while (cbp->numFull == 0)
+ PR_WaitCondVar(cbp->notEmpty,PR_INTERVAL_NO_TIMEOUT);
+ data = cbp->data[cbp->startIdx];
+ cbp->startIdx =(cbp->startIdx + 1) % kQSIZE;
+ cbp->numFull -= 1;
+
+ /* let a waiting writer know that there is room */
+ PR_NotifyCondVar(cbp->notFull);
+ PR_Unlock(cbp->bufLock);
+
+ return (data);
+}
+
+
+/************************************************************************/
+
+static int alive;
+
+static void PR_CALLBACK CXReader(void *arg)
+{
+ CircBuf *cbp = (CircBuf *)arg;
+ PRInt32 i, n;
+ void *data;
+
+ n = count / 2;
+ for (i = 0; i < n; i++) {
+ data = GetCBData(cbp);
+ if ((int)data != i)
+ if (debug_mode) printf("data mismatch at for i = %d usec\n", i);
+ }
+
+ PR_EnterMonitor(mon);
+ --alive;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+}
+
+static void PR_CALLBACK CXWriter(void *arg)
+{
+ CircBuf *cbp = (CircBuf *)arg;
+ PRInt32 i, n;
+
+ n = count / 2;
+ for (i = 0; i < n; i++)
+ PutCBData(cbp, (void *)i);
+
+ PR_EnterMonitor(mon);
+ --alive;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+}
+
+static void CondWaitContextSwitch(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *t1, *t2;
+ CircBuf *cbp;
+
+ PR_EnterMonitor(mon);
+
+ alive = 2;
+
+ cbp = NewCB();
+
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ CXReader, cbp,
+ PR_PRIORITY_NORMAL,
+ scope1,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ CXWriter, cbp,
+ PR_PRIORITY_NORMAL,
+ scope2,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ /* Wait for both of the threads to exit */
+ while (alive) {
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ DeleteCB(cbp);
+
+ PR_ExitMonitor(mon);
+}
+
+static void CondWaitContextSwitchUU(void)
+{
+ CondWaitContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void CondWaitContextSwitchUK(void)
+{
+ CondWaitContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+static void CondWaitContextSwitchKK(void)
+{
+ CondWaitContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ if (debug_mode) printf("%40s: %6.2f usec\n", msg, d / count);
+
+ if (0 == d) failed = PR_TRUE;
+}
+
+static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name [-d] [-c n]
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'c': /* loop count */
+ count = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == count) count = DEFAULT_COUNT;
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("cvar.log");
+ debug_mode = 1;
+#endif
+
+ mon = PR_NewMonitor();
+
+ Measure(CondWaitContextSwitchUU, "cond var wait context switch- user/user");
+ Measure(CondWaitContextSwitchUK, "cond var wait context switch- user/kernel");
+ Measure(CondWaitContextSwitchKK, "cond var wait context switch- kernel/kernel");
+
+ PR_DestroyMonitor(mon);
+
+ if (debug_mode) printf("%s\n", (failed) ? "FAILED" : "PASSED");
+
+ if(failed)
+ return 1;
+ else
+ return 0;
+}
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/cvar2.c b/src/libs/xpcom18a4/nsprpub/pr/tests/cvar2.c
new file mode 100644
index 00000000..4b01cb4b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/cvar2.c
@@ -0,0 +1,1008 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1996 - Netscape Communications Corporation
+**
+** Name: cvar2.c
+**
+** Description: Simple test creates several local and global threads;
+** half use a single,shared condvar, and the
+** other half have their own condvar. The main thread then loops
+** notifying them to wakeup.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+
+#include "nspr.h"
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int _debug_on = 0;
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+#define DEFAULT_COUNT 100
+#define DEFAULT_THREADS 5
+PRInt32 count = DEFAULT_COUNT;
+
+typedef struct threadinfo {
+ PRThread *thread;
+ PRInt32 id;
+ PRBool internal;
+ PRInt32 *tcount;
+ PRLock *lock;
+ PRCondVar *cvar;
+ PRIntervalTime timeout;
+ PRInt32 loops;
+
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+ PRInt32 *exitcount;
+} threadinfo;
+
+/*
+** Make exitcount, tcount static. for Win16.
+*/
+static PRInt32 exitcount=0;
+static PRInt32 tcount=0;
+
+
+/* Thread that gets notified; many threads share the same condvar */
+void PR_CALLBACK
+SharedCondVarThread(void *_info)
+{
+ threadinfo *info = (threadinfo *)_info;
+ PRInt32 index;
+
+ for (index=0; index<info->loops; index++) {
+ PR_Lock(info->lock);
+ if (*info->tcount == 0)
+ PR_WaitCondVar(info->cvar, info->timeout);
+#if 0
+ printf("shared thread %ld notified in loop %ld\n", info->id, index);
+#endif
+ (*info->tcount)--;
+ PR_Unlock(info->lock);
+
+ PR_Lock(info->exitlock);
+ (*info->exitcount)++;
+ PR_NotifyCondVar(info->exitcvar);
+ PR_Unlock(info->exitlock);
+ }
+#if 0
+ printf("shared thread %ld terminating\n", info->id);
+#endif
+}
+
+/* Thread that gets notified; no other threads use the same condvar */
+void PR_CALLBACK
+PrivateCondVarThread(void *_info)
+{
+ threadinfo *info = (threadinfo *)_info;
+ PRInt32 index;
+
+ for (index=0; index<info->loops; index++) {
+ PR_Lock(info->lock);
+ if (*info->tcount == 0) {
+ DPRINTF(("PrivateCondVarThread: thread 0x%lx waiting on cvar = 0x%lx\n",
+ PR_GetCurrentThread(), info->cvar));
+ PR_WaitCondVar(info->cvar, info->timeout);
+ }
+#if 0
+ printf("solo thread %ld notified in loop %ld\n", info->id, index);
+#endif
+ (*info->tcount)--;
+ PR_Unlock(info->lock);
+
+ PR_Lock(info->exitlock);
+ (*info->exitcount)++;
+ PR_NotifyCondVar(info->exitcvar);
+DPRINTF(("PrivateCondVarThread: thread 0x%lx notified exitcvar = 0x%lx cnt = %ld\n",
+ PR_GetCurrentThread(), info->exitcvar,(*info->exitcount)));
+ PR_Unlock(info->exitlock);
+ }
+#if 0
+ printf("solo thread %ld terminating\n", info->id);
+#endif
+}
+
+void
+CreateTestThread(threadinfo *info,
+ PRInt32 id,
+ PRLock *lock,
+ PRCondVar *cvar,
+ PRInt32 loops,
+ PRIntervalTime timeout,
+ PRInt32 *tcount,
+ PRLock *exitlock,
+ PRCondVar *exitcvar,
+ PRInt32 *exitcount,
+ PRBool shared,
+ PRThreadScope scope)
+{
+ info->id = id;
+ info->internal = (shared) ? PR_FALSE : PR_TRUE;
+ info->lock = lock;
+ info->cvar = cvar;
+ info->loops = loops;
+ info->timeout = timeout;
+ info->tcount = tcount;
+ info->exitlock = exitlock;
+ info->exitcvar = exitcvar;
+ info->exitcount = exitcount;
+ info->thread = PR_CreateThread(
+ PR_USER_THREAD,
+ shared?SharedCondVarThread:PrivateCondVarThread,
+ info,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!info->thread)
+ PL_PrintError("error creating thread\n");
+}
+
+
+void
+CondVarTestSUU(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+
+ exitcount=0;
+ tcount=0;
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg; ) {
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_LOCAL_THREAD);
+ index++;
+ DPRINTF(("CondVarTestSUU: created thread 0x%lx\n",list[index].thread));
+ }
+
+ for (loops = 0; loops < count; loops++) {
+ /* Notify the threads */
+ for(index=0; index<(arg); index++) {
+ PR_Lock(list[index].lock);
+ (*list[index].tcount)++;
+ PR_NotifyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ DPRINTF(("PrivateCondVarThread: thread 0x%lx notified cvar = 0x%lx\n",
+ PR_GetCurrentThread(), list[index].cvar));
+ }
+
+ /* Wait for threads to finish */
+ PR_Lock(exitlock);
+ while(exitcount < arg)
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ PR_ASSERT(exitcount >= arg);
+ exitcount -= arg;
+ PR_Unlock(exitlock);
+ }
+
+ /* Join all the threads */
+ for(index=0; index<(arg); index++)
+ PR_JoinThread(list[index].thread);
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+ PR_DestroyCondVar(exitcvar);
+ PR_DestroyLock(exitlock);
+
+ PR_DELETE(list);
+}
+
+void
+CondVarTestSUK(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+ exitcount=0;
+ tcount=0;
+
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg; ) {
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_GLOBAL_THREAD);
+ index++;
+ }
+
+ for (loops = 0; loops < count; loops++) {
+ /* Notify the threads */
+ for(index=0; index<(arg); index++) {
+
+ PR_Lock(list[index].lock);
+ (*list[index].tcount)++;
+ PR_NotifyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ }
+
+#if 0
+ printf("wait for threads to be done\n");
+#endif
+ /* Wait for threads to finish */
+ PR_Lock(exitlock);
+ while(exitcount < arg)
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ PR_ASSERT(exitcount >= arg);
+ exitcount -= arg;
+ PR_Unlock(exitlock);
+#if 0
+ printf("threads ready\n");
+#endif
+ }
+
+ /* Join all the threads */
+ for(index=0; index<(arg); index++)
+ PR_JoinThread(list[index].thread);
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+ PR_DestroyCondVar(exitcvar);
+ PR_DestroyLock(exitlock);
+
+ PR_DELETE(list);
+}
+
+void
+CondVarTestPUU(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+ PRInt32 *tcount, *saved_tcount;
+
+ exitcount=0;
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+ saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg; ) {
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_LOCAL_THREAD);
+
+ DPRINTF(("CondVarTestPUU: created thread 0x%lx\n",list[index].thread));
+ index++;
+ tcount++;
+ }
+
+ for (loops = 0; loops < count; loops++) {
+ /* Notify the threads */
+ for(index=0; index<(arg); index++) {
+
+ PR_Lock(list[index].lock);
+ (*list[index].tcount)++;
+ PR_NotifyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ }
+
+ PR_Lock(exitlock);
+ /* Wait for threads to finish */
+ while(exitcount < arg) {
+DPRINTF(("CondVarTestPUU: thread 0x%lx waiting on exitcvar = 0x%lx cnt = %ld\n",
+ PR_GetCurrentThread(), exitcvar, exitcount));
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ }
+ PR_ASSERT(exitcount >= arg);
+ exitcount -= arg;
+ PR_Unlock(exitlock);
+ }
+
+ /* Join all the threads */
+ for(index=0; index<(arg); index++) {
+ DPRINTF(("CondVarTestPUU: joining thread 0x%lx\n",list[index].thread));
+ PR_JoinThread(list[index].thread);
+ if (list[index].internal) {
+ PR_Lock(list[index].lock);
+ PR_DestroyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ PR_DestroyLock(list[index].lock);
+ }
+ }
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+ PR_DestroyCondVar(exitcvar);
+ PR_DestroyLock(exitlock);
+
+ PR_DELETE(list);
+ PR_DELETE(saved_tcount);
+}
+
+void
+CondVarTestPUK(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+ PRInt32 *tcount, *saved_tcount;
+
+ exitcount=0;
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+ saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg; ) {
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_GLOBAL_THREAD);
+
+ index++;
+ tcount++;
+ }
+
+ for (loops = 0; loops < count; loops++) {
+ /* Notify the threads */
+ for(index=0; index<(arg); index++) {
+
+ PR_Lock(list[index].lock);
+ (*list[index].tcount)++;
+ PR_NotifyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ }
+
+ /* Wait for threads to finish */
+ PR_Lock(exitlock);
+ while(exitcount < arg)
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ PR_ASSERT(exitcount >= arg);
+ exitcount -= arg;
+ PR_Unlock(exitlock);
+ }
+
+ /* Join all the threads */
+ for(index=0; index<(arg); index++) {
+ PR_JoinThread(list[index].thread);
+ if (list[index].internal) {
+ PR_Lock(list[index].lock);
+ PR_DestroyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ PR_DestroyLock(list[index].lock);
+ }
+ }
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+ PR_DestroyCondVar(exitcvar);
+ PR_DestroyLock(exitlock);
+
+ PR_DELETE(list);
+ PR_DELETE(saved_tcount);
+}
+
+void
+CondVarTest(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+ PRInt32 *ptcount, *saved_ptcount;
+
+ exitcount=0;
+ tcount=0;
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+ saved_ptcount = ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg*4; ) {
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_LOCAL_THREAD);
+
+ index++;
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_GLOBAL_THREAD);
+
+ index++;
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ ptcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_LOCAL_THREAD);
+ index++;
+ ptcount++;
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_INTERVAL_NO_TIMEOUT,
+ ptcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_GLOBAL_THREAD);
+
+ index++;
+ ptcount++;
+ }
+
+ for (loops = 0; loops < count; loops++) {
+
+ /* Notify the threads */
+ for(index=0; index<(arg*4); index++) {
+ PR_Lock(list[index].lock);
+ (*list[index].tcount)++;
+ PR_NotifyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ }
+
+#if 0
+ printf("wait for threads done\n");
+#endif
+
+ /* Wait for threads to finish */
+ PR_Lock(exitlock);
+ while(exitcount < arg*4)
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ PR_ASSERT(exitcount >= arg*4);
+ exitcount -= arg*4;
+ PR_Unlock(exitlock);
+#if 0
+ printf("threads ready\n");
+#endif
+ }
+
+ /* Join all the threads */
+ for(index=0; index<(arg*4); index++) {
+ PR_JoinThread(list[index].thread);
+ if (list[index].internal) {
+ PR_Lock(list[index].lock);
+ PR_DestroyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ PR_DestroyLock(list[index].lock);
+ }
+ }
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+ PR_DestroyCondVar(exitcvar);
+ PR_DestroyLock(exitlock);
+
+ PR_DELETE(list);
+ PR_DELETE(saved_ptcount);
+}
+
+void
+CondVarTimeoutTest(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg*4; ) {
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_LOCAL_THREAD);
+ index++;
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_GLOBAL_THREAD);
+ index++;
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_LOCAL_THREAD);
+ index++;
+
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_GLOBAL_THREAD);
+
+ index++;
+ }
+
+ for (loops = 0; loops < count; loops++) {
+
+ /* Wait for threads to finish */
+ PR_Lock(exitlock);
+ while(exitcount < arg*4)
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ PR_ASSERT(exitcount >= arg*4);
+ exitcount -= arg*4;
+ PR_Unlock(exitlock);
+ }
+
+
+ /* Join all the threads */
+ for(index=0; index<(arg*4); index++) {
+ PR_JoinThread(list[index].thread);
+ if (list[index].internal) {
+ PR_Lock(list[index].lock);
+ PR_DestroyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ PR_DestroyLock(list[index].lock);
+ }
+ }
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+ PR_DestroyCondVar(exitcvar);
+ PR_DestroyLock(exitlock);
+
+ PR_DELETE(list);
+}
+
+void
+CondVarMixedTest(void *_arg)
+{
+ PRInt32 arg = (PRInt32)_arg;
+ PRInt32 index, loops;
+ threadinfo *list;
+ PRLock *sharedlock;
+ PRCondVar *sharedcvar;
+ PRLock *exitlock;
+ PRCondVar *exitcvar;
+ PRInt32 *ptcount;
+
+ exitcount=0;
+ tcount=0;
+ list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
+ ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4));
+
+ sharedlock = PR_NewLock();
+ sharedcvar = PR_NewCondVar(sharedlock);
+ exitlock = PR_NewLock();
+ exitcvar = PR_NewCondVar(exitlock);
+
+ /* Create the threads */
+ for(index=0; index<arg*4; ) {
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_LOCAL_THREAD);
+ index++;
+ CreateTestThread(&list[index],
+ index,
+ sharedlock,
+ sharedcvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ &tcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_TRUE,
+ PR_GLOBAL_THREAD);
+ index++;
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ ptcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_LOCAL_THREAD);
+ index++;
+ ptcount++;
+
+ list[index].lock = PR_NewLock();
+ list[index].cvar = PR_NewCondVar(list[index].lock);
+ CreateTestThread(&list[index],
+ index,
+ list[index].lock,
+ list[index].cvar,
+ count,
+ PR_MillisecondsToInterval(50),
+ ptcount,
+ exitlock,
+ exitcvar,
+ &exitcount,
+ PR_FALSE,
+ PR_GLOBAL_THREAD);
+ index++;
+ ptcount++;
+ }
+
+
+ /* Notify every 3rd thread */
+ for (loops = 0; loops < count; loops++) {
+
+ /* Notify the threads */
+ for(index=0; index<(arg*4); index+=3) {
+
+ PR_Lock(list[index].lock);
+ *list[index].tcount++;
+ PR_NotifyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+
+ }
+ /* Wait for threads to finish */
+ PR_Lock(exitlock);
+ while(exitcount < arg*4)
+ PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
+ PR_ASSERT(exitcount >= arg*4);
+ exitcount -= arg*4;
+ PR_Unlock(exitlock);
+ }
+
+ /* Join all the threads */
+ for(index=0; index<(arg*4); index++) {
+ PR_JoinThread(list[index].thread);
+ if (list[index].internal) {
+ PR_Lock(list[index].lock);
+ PR_DestroyCondVar(list[index].cvar);
+ PR_Unlock(list[index].lock);
+ PR_DestroyLock(list[index].lock);
+ }
+ }
+
+ PR_DestroyCondVar(sharedcvar);
+ PR_DestroyLock(sharedlock);
+
+ PR_DELETE(list);
+}
+
+void
+CondVarCombinedTest(void *arg)
+{
+ PRThread *threads[3];
+
+ threads[0] = PR_CreateThread(PR_USER_THREAD,
+ CondVarTest,
+ (void *)arg,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ threads[1] = PR_CreateThread(PR_USER_THREAD,
+ CondVarTimeoutTest,
+ (void *)arg,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ threads[2] = PR_CreateThread(PR_USER_THREAD,
+ CondVarMixedTest,
+ (void *)arg,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(threads[0]);
+ PR_JoinThread(threads[1]);
+ PR_JoinThread(threads[2]);
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void *), PRInt32 arg, const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)((void *)arg);
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ printf("%40s: %6.2f usec\n", msg, d / count);
+}
+
+static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
+{
+ PRInt32 threads, default_threads = DEFAULT_THREADS;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "vc:t:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 'c': /* loop counter */
+ count = atoi(opt->value);
+ break;
+ case 't': /* number of threads involved */
+ default_threads = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == count) count = DEFAULT_COUNT;
+ if (0 == default_threads) default_threads = DEFAULT_THREADS;
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("cvar2.log");
+#endif
+
+ printf("\n\
+CondVar Test: \n\
+ \n\
+Simple test creates several local and global threads; half use a single,\n\
+shared condvar, and the other half have their own condvar. The main \n\
+thread then loops notifying them to wakeup. \n\
+ \n\
+The timeout test is very similar except that the threads are not \n\
+notified. They will all wakeup on a 1 second timeout. \n\
+ \n\
+The mixed test combines the simple test and the timeout test; every \n\
+third thread is notified, the other threads are expected to timeout \n\
+correctly. \n\
+ \n\
+Lastly, the combined test creates a thread for each of the above three \n\
+cases and they all run simultaneously. \n\
+ \n\
+This test is run with %d, %d, %d, and %d threads of each type.\n\n",
+default_threads, default_threads*2, default_threads*3, default_threads*4);
+
+ PR_SetConcurrency(2);
+
+ for (threads = default_threads; threads < default_threads*5; threads+=default_threads) {
+ printf("\n%ld Thread tests\n", threads);
+ Measure(CondVarTestSUU, threads, "Condvar simple test shared UU");
+ Measure(CondVarTestSUK, threads, "Condvar simple test shared UK");
+ Measure(CondVarTestPUU, threads, "Condvar simple test priv UU");
+ Measure(CondVarTestPUK, threads, "Condvar simple test priv UK");
+#ifdef XP_MAC
+ /* Mac heaps can't handle thread*4 stack allocations at a time for (10, 15, 20)*4 */
+ Measure(CondVarTest, 5, "Condvar simple test All");
+ Measure(CondVarTimeoutTest, 5, "Condvar timeout test");
+#else
+ Measure(CondVarTest, threads, "Condvar simple test All");
+ Measure(CondVarTimeoutTest, threads, "Condvar timeout test");
+#endif
+#if 0
+ Measure(CondVarMixedTest, threads, "Condvar mixed timeout test");
+ Measure(CondVarCombinedTest, threads, "Combined condvar test");
+#endif
+ }
+
+ printf("PASS\n");
+
+ return 0;
+}
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc.c
new file mode 100644
index 00000000..4295d0c0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc.c
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dbmalloc.c
+**
+** Description: Testing malloc (OBSOLETE)
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include "nspr.h"
+
+void
+usage
+(
+ void
+)
+{
+ fprintf(stderr, "Usage: dbmalloc ('-m'|'-s') '-f' num_fails ('-d'|'-n') filename [...]\n");
+ exit(0);
+}
+
+typedef struct node_struct
+{
+ struct node_struct *next, *prev;
+ int line;
+ char value[4];
+}
+ node_t,
+ *node_pt;
+
+node_pt get_node(const char *line)
+{
+ node_pt rv;
+ int l = strlen(line);
+ rv = (node_pt)PR_MALLOC(sizeof(node_t) + l + 1 - 4);
+ if( (node_pt)0 == rv ) return (node_pt)0;
+ memcpy(&rv->value[0], line, l+1);
+ rv->next = rv->prev = (node_pt)0;
+ return rv;
+}
+
+void
+dump
+(
+ const char *name,
+ node_pt node,
+ int mf,
+ int debug
+)
+{
+ if( (node_pt)0 != node->prev ) dump(name, node->prev, mf, debug);
+ if( 0 != debug ) printf("[%s]: %6d: %s", name, node->line, node->value);
+ if( node->line == mf ) fprintf(stderr, "[%s]: Line %d was allocated!\n", name, node->line);
+ if( (node_pt)0 != node->next ) dump(name, node->next, mf, debug);
+ return;
+}
+
+void
+release
+(
+ node_pt node
+)
+{
+ if( (node_pt)0 != node->prev ) release(node->prev);
+ if( (node_pt)0 != node->next ) release(node->next);
+ PR_DELETE(node);
+}
+
+int
+t2
+(
+ const char *name,
+ int mf,
+ int debug
+)
+{
+ int rv;
+ FILE *fp;
+ int l = 0;
+ node_pt head = (node_pt)0;
+ char buffer[ BUFSIZ ];
+
+ fp = fopen(name, "r");
+ if( (FILE *)0 == fp )
+ {
+ fprintf(stderr, "[%s]: Cannot open \"%s.\"\n", name, name);
+ return -1;
+ }
+
+ /* fgets mallocs a buffer, first time through. */
+ if( (char *)0 == fgets(buffer, BUFSIZ, fp) )
+ {
+ fprintf(stderr, "[%s]: \"%s\" is empty.\n", name, name);
+ (void)fclose(fp);
+ return -1;
+ }
+
+ rewind(fp);
+
+ if( PR_SUCCESS != PR_ClearMallocCount() )
+ {
+ fprintf(stderr, "[%s]: Cannot clear malloc count.\n", name);
+ (void)fclose(fp);
+ return -1;
+ }
+
+ if( PR_SUCCESS != PR_SetMallocCountdown(mf) )
+ {
+ fprintf(stderr, "[%s]: Cannot set malloc countdown to %d\n", name, mf);
+ (void)fclose(fp);
+ return -1;
+ }
+
+ while( fgets(buffer, BUFSIZ, fp) )
+ {
+ node_pt n;
+ node_pt *w = &head;
+
+ if( (strlen(buffer) == (BUFSIZ-1)) && (buffer[BUFSIZ-2] != '\n') )
+ buffer[BUFSIZ-2] == '\n';
+
+ l++;
+
+ n = get_node(buffer);
+ if( (node_pt)0 == n )
+ {
+ printf("[%s]: Line %d: malloc failure!\n", name, l);
+ continue;
+ }
+
+ n->line = l;
+
+ while( 1 )
+ {
+ int comp;
+
+ if( (node_pt)0 == *w )
+ {
+ *w = n;
+ break;
+ }
+
+ comp = strcmp((*w)->value, n->value);
+ if( comp < 0 ) w = &(*w)->next;
+ else w = &(*w)->prev;
+ }
+ }
+
+ (void)fclose(fp);
+
+ dump(name, head, mf, debug);
+
+ rv = PR_GetMallocCount();
+ PR_ClearMallocCountdown();
+
+ release(head);
+
+ return rv;
+}
+
+int nf = 0;
+int debug = 0;
+
+void
+test
+(
+ const char *name
+)
+{
+ int n, i;
+
+ extern int nf, debug;
+
+ printf("[%s]: starting test 0\n", name);
+ n = t2(name, 0, debug);
+ if( -1 == n ) return;
+ printf("[%s]: test 0 had %ld allocations.\n", name, n);
+
+ if( 0 >= n ) return;
+
+ for( i = 0; i < nf; i++ )
+ {
+ int which = rand() % n;
+ if( 0 == which ) printf("[%s]: starting test %d -- no allocation should fail\n", name, i+1);
+ else printf("[%s]: starting test %d -- allocation %d should fail\n", name, i+1, which);
+ (void)t2(name, which, debug);
+ printf("[%s]: test %d done.\n", name, i+1);
+ }
+
+ return;
+}
+
+int
+main
+(
+ int argc,
+ char *argv[]
+)
+{
+ int okay = 0;
+ int multithread = 0;
+
+ struct threadlist
+ {
+ struct threadlist *next;
+ PRThread *thread;
+ }
+ *threadhead = (struct threadlist *)0;
+
+ extern int nf, debug;
+
+ srand(time(0));
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ printf("[main]: We %s using the debugging malloc.\n",
+ PR_IsDebuggingMalloc() ? "ARE" : "ARE NOT");
+
+ while( argv++, --argc )
+ {
+ if( '-' == argv[0][0] )
+ {
+ switch( argv[0][1] )
+ {
+ case 'f':
+ nf = atoi(argv[0][2] ? &argv[0][2] :
+ --argc ? *++argv : "0");
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'n':
+ debug = 0;
+ break;
+ case 'm':
+ multithread = 1;
+ break;
+ case 's':
+ multithread = 0;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ else
+ {
+ FILE *fp = fopen(*argv, "r");
+ if( (FILE *)0 == fp )
+ {
+ fprintf(stderr, "Cannot open \"%s.\"\n", *argv);
+ continue;
+ }
+
+ okay++;
+ (void)fclose(fp);
+ if( multithread )
+ {
+ struct threadlist *n;
+
+ n = (struct threadlist *)malloc(sizeof(struct threadlist));
+ if( (struct threadlist *)0 == n )
+ {
+ fprintf(stderr, "This is getting tedious. \"%s\"\n", *argv);
+ continue;
+ }
+
+ n->next = threadhead;
+ n->thread = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))test,
+ *argv, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD,
+ 0);
+ if( (PRThread *)0 == n->thread )
+ {
+ fprintf(stderr, "Can't create thread for \"%s.\"\n", *argv);
+ continue;
+ }
+ else
+ {
+ threadhead = n;
+ }
+ }
+ else
+ {
+ test(*argv);
+ }
+ }
+ }
+
+ if( okay == 0 ) usage();
+ else while( (struct threadlist *)0 != threadhead )
+ {
+ struct threadlist *x = threadhead->next;
+ (void)PR_JoinThread(threadhead->thread);
+ PR_DELETE(threadhead);
+ threadhead = x;
+ }
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc1.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc1.c
new file mode 100644
index 00000000..ca1b4cb1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dbmalloc1.c
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dbmalloc1.c (OBSOLETE)
+**
+** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+**
+** 12-June-97 AGarcia Revert to return code 0 and 1, remove debug option (obsolete).
+***********************************************************************/
+
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include "nspr.h"
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+/* variable used for both r1 and r2 tests */
+int should_fail =0;
+int actually_failed=0;
+
+
+void
+r1
+(
+ void
+)
+{
+ int i;
+ actually_failed=0;
+ for( i = 0; i < 5; i++ )
+ {
+ void *x = PR_MALLOC(128);
+ if( (void *)0 == x ) {
+ if (debug_mode) printf("\tMalloc %d failed.\n", i+1);
+ actually_failed = 1;
+ }
+ PR_DELETE(x);
+ }
+
+ if (((should_fail != actually_failed) & (!debug_mode))) failed_already=1;
+
+
+ return;
+}
+
+void
+r2
+(
+ void
+)
+{
+ int i;
+
+ for( i = 0; i <= 5; i++ )
+ {
+ should_fail =0;
+ if( 0 == i ) {
+ if (debug_mode) printf("No malloc should fail:\n");
+ }
+ else {
+ if (debug_mode) printf("Malloc %d should fail:\n", i);
+ should_fail = 1;
+ }
+ PR_SetMallocCountdown(i);
+ r1();
+ PR_ClearMallocCountdown();
+ }
+}
+
+int
+main
+(
+ int argc,
+ char *argv[]
+)
+{
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+ r2();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dceemu.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dceemu.c
new file mode 100644
index 00000000..bc037c83
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dceemu.c
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: dceemu.c
+** Description: testing the DCE emulation api
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 Revert to return code 0 and 1, remove debug option (obsolete).
+**/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+
+
+#if defined(_PR_DCETHREADS)
+
+#include "prlog.h"
+#include "prinit.h"
+#include "prpdce.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+PRIntn failed_already=0;
+PRIntn debug_mode=0;
+
+static PRIntn prmain(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRLock *ml = PR_NewLock();
+ PRCondVar *cv = PRP_NewNakedCondVar();
+ PRIntervalTime tenmsecs = PR_MillisecondsToInterval(10);
+
+ rv = PRP_TryLock(ml);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1;
+
+ rv = PRP_TryLock(ml);
+ PR_ASSERT(PR_FAILURE == rv);
+ if ((rv != PR_FAILURE) & (!debug_mode)) failed_already=1;
+
+ rv = PRP_NakedNotify(cv);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1;
+
+ rv = PRP_NakedBroadcast(cv);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1;
+
+ rv = PRP_NakedWait(cv, ml, tenmsecs);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1;
+
+ PR_Unlock(ml);
+
+ rv = PRP_NakedNotify(cv);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1;
+
+ rv = PRP_NakedBroadcast(cv);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1;
+
+ PRP_DestroyNakedCondVar(cv);
+ PR_DestroyLock(ml);
+
+ if (debug_mode) printf("Test succeeded\n");
+
+ return 0;
+
+} /* prmain */
+
+#endif /* #if defined(_PR_DCETHREADS) */
+
+int main(int argc, char **argv)
+{
+
+#if defined(_PR_DCETHREADS)
+ PR_Initialize(prmain, argc, argv, 0);
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+#else
+ return 0;
+#endif
+} /* main */
+
+
+/* decemu.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/depend.c b/src/libs/xpcom18a4/nsprpub/pr/tests/depend.c
new file mode 100644
index 00000000..e3fb691e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/depend.c
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1996 - Netscape Communications Corporation
+**
+**
+** Name: depend.c
+** Description: Test to enumerate the dependencies
+*
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+#include "prinit.h"
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void PrintVersion(
+ const char *msg, const PRVersion* info, PRIntn tab)
+{
+ static const len = 20;
+ static const char *tabs = {" "};
+
+ tab *= 2;
+ if (tab > len) tab = len;
+ printf("%s", &tabs[len - tab]);
+ printf("%s ", msg);
+ printf("%s ", info->id);
+ printf("%d.%d", info->major, info->minor);
+ if (0 != info->patch)
+ printf(".p%d", info->patch);
+ printf("\n");
+} /* PrintDependency */
+
+static void ChaseDependents(const PRVersionInfo *info, PRIntn tab)
+{
+ PrintVersion("exports", &info->selfExport, tab);
+ if (NULL != info->importEnumerator)
+ {
+ const PRDependencyInfo *dependent = NULL;
+ while (NULL != (dependent = info->importEnumerator(dependent)))
+ {
+ const PRVersionInfo *import = dependent->exportInfoFn();
+ PrintVersion("imports", &dependent->importNeeded, tab);
+ ChaseDependents(import, tab + 1);
+ }
+ }
+} /* ChaseDependents */
+
+static PRVersionInfo hack_export;
+static PRVersionInfo dummy_export;
+static PRDependencyInfo dummy_imports[2];
+
+static const PRVersionInfo *HackExportInfo(void)
+{
+ hack_export.selfExport.major = 11;
+ hack_export.selfExport.minor = 10;
+ hack_export.selfExport.patch = 200;
+ hack_export.selfExport.id = "Hack";
+ hack_export.importEnumerator = NULL;
+ return &hack_export;
+}
+
+static const PRDependencyInfo *DummyImports(
+ const PRDependencyInfo *previous)
+{
+ if (NULL == previous) return &dummy_imports[0];
+ else if (&dummy_imports[0] == previous) return &dummy_imports[1];
+ else if (&dummy_imports[1] == previous) return NULL;
+} /* DummyImports */
+
+static const PRVersionInfo *DummyLibVersion(void)
+{
+ dummy_export.selfExport.major = 1;
+ dummy_export.selfExport.minor = 0;
+ dummy_export.selfExport.patch = 0;
+ dummy_export.selfExport.id = "Dumbass application";
+ dummy_export.importEnumerator = DummyImports;
+
+ dummy_imports[0].importNeeded.major = 2;
+ dummy_imports[0].importNeeded.minor = 0;
+ dummy_imports[0].importNeeded.patch = 0;
+ dummy_imports[0].importNeeded.id = "Netscape Portable Runtime";
+ dummy_imports[0].exportInfoFn = PR_ExportInfo;
+
+ dummy_imports[1].importNeeded.major = 5;
+ dummy_imports[1].importNeeded.minor = 1;
+ dummy_imports[1].importNeeded.patch = 2;
+ dummy_imports[1].importNeeded.id = "Hack Library";
+ dummy_imports[1].exportInfoFn = HackExportInfo;
+
+ return &dummy_export;
+} /* DummyLibVersion */
+
+int main(int argc, char **argv)
+{
+ PRIntn tab = 0;
+ const PRVersionInfo *info = DummyLibVersion();
+ const char *buildDate = __DATE__, *buildTime = __TIME__;
+
+ printf("Depend.c build time is %s %s\n", buildDate, buildTime);
+
+ if (NULL != info) ChaseDependents(info, tab);
+
+ return 0;
+} /* main */
+
+/* depend.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dll/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dll/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/Makefile.in
new file mode 100644
index 00000000..62a214f4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/Makefile.in
@@ -0,0 +1,121 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+# Disable optimization of the nspr on SunOS4.1.3
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_RELEASE),4.1.3_U1)
+OPTIMIZER =
+endif
+endif
+
+CSRCS = mygetval.c mysetval.c
+
+INCLUDES = -I$(dist_includedir)
+
+OBJS = $(OBJDIR)/mygetval.$(OBJ_SUFFIX) \
+ $(OBJDIR)/mysetval.$(OBJ_SUFFIX)
+
+ifeq ($(OS_TARGET), WIN16)
+W16OBJS = $(subst $(space),$(comma)$(space),$(OBJS))
+endif
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+# do nothing
+else
+ifdef NS_USE_GCC
+DLLBASE=-Wl,--image-base -Wl,0x30000000
+else
+DLLBASE=/BASE:0x30000000
+endif
+RES=$(OBJDIR)/my.res
+RESNAME=../../../pr/src/nspr.rc
+endif
+endif
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+IMPORT_LIBRARY = $(OBJDIR)/my.$(LIB_SUFFIX)
+SHARED_LIBRARY = $(OBJDIR)/my.dll
+ifeq ($(OS_ARCH), OS2)
+MAPFILE = $(OBJDIR)/my.def
+GARBAGE += $(MAPFILE)
+MKSHLIB += $(MAPFILE)
+endif
+TARGETS = $(SHARED_LIBRARY) $(IMPORT_LIBRARY)
+else
+ifdef MKSHLIB
+SHARED_LIBRARY = $(OBJDIR)/libmy.$(DLL_SUFFIX)
+endif
+TARGETS = $(SHARED_LIBRARY)
+endif
+
+#
+# To create a loadable module on Rhapsody, we must override
+# -dynamiclib with -bundle.
+#
+ifeq ($(OS_ARCH),Darwin)
+DSO_LDOPTS = -bundle
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(OS_TARGET), WIN16)
+# Note: The Win16 target: my.dll requires these macros
+# to be overridden to build the test .dll
+# default values in win16...mk are for release targets.
+#
+OS_DLL_OPTION = NOCASEEXACT
+OS_LIB_FLAGS = -irn
+endif
+
+ifdef SHARED_LIBRARY
+export:: $(TARGETS)
+
+clean::
+ rm -rf $(TARGETS)
+endif
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dll/my.def b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/my.def
new file mode 100644
index 00000000..4423c0f0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/my.def
@@ -0,0 +1,53 @@
+;+#
+;+# 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 Portable Runtime (NSPR).
+;+#
+;+# The Initial Developer of the Original Code is Netscape
+;+# Communications Corporation. Portions created by Netscape are
+;+# Copyright (C) 2002-2003 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.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+#
+;+MY_1.0 {
+;+ global:
+LIBRARY my ;-
+EXPORTS ;-
+ My_GetValue;
+ My_SetValue;
+;+ local: *;
+;+};
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dll/mygetval.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/mygetval.c
new file mode 100644
index 00000000..17f36792
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/mygetval.c
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+#if defined(WIN16)
+#include <windows.h>
+#endif
+#include "prtypes.h"
+
+extern PRIntn my_global;
+
+PR_IMPLEMENT(PRIntn) My_GetValue()
+{
+ return my_global;
+}
+
+#if defined(WIN16)
+int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg,
+ WORD cbHeapSize, LPSTR lpszCmdLine )
+{
+ return TRUE;
+}
+#endif /* WIN16 */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dll/mysetval.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/mysetval.c
new file mode 100644
index 00000000..982f0776
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dll/mysetval.c
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prtypes.h"
+
+PRIntn my_global = 0;
+
+PR_IMPLEMENT(void) My_SetValue(PRIntn val)
+{
+ my_global = val;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dlltest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dlltest.c
new file mode 100644
index 00000000..f8a5f53b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dlltest.c
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dlltest.c
+**
+** Description: test dll functionality.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 Revert to return code 0 and 1.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+#include "prinit.h"
+#include "prlink.h"
+#include "prmem.h"
+#include "prerror.h"
+
+#include "plstr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef PRIntn (PR_CALLBACK *GetFcnType)(void);
+typedef void (PR_CALLBACK *SetFcnType)(PRIntn);
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+int main(int argc, char** argv)
+{
+ PRLibrary *lib, *lib2; /* two handles to the same library */
+ GetFcnType getFcn;
+ SetFcnType setFcn;
+ PRIntn value;
+ PRStatus status;
+ char *libName;
+
+ if (argc >= 2 && PL_strcmp(argv[1], "-d") == 0) {
+ debug_mode = 1;
+ }
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ /*
+ * Test 1: load the library, look up the symbols, call the functions,
+ * and check the results.
+ */
+
+ libName = PR_GetLibraryName("dll", "my");
+ if (debug_mode) printf("Loading library %s\n", libName);
+ lib = PR_LoadLibrary(libName);
+ PR_FreeLibraryName(libName);
+ if (lib == NULL) {
+ PRInt32 textLength = PR_GetErrorTextLength();
+ char *text = (char*)PR_MALLOC(textLength);
+ (void)PR_GetErrorText(text);
+ fprintf(
+ stderr, "PR_LoadLibrary failed (%d, %d, %s)\n",
+ PR_GetError(), PR_GetOSError(), text);
+ if (!debug_mode) failed_already=1;
+ }
+ getFcn = (GetFcnType) PR_FindSymbol(lib, "My_GetValue");
+ setFcn = (SetFcnType) PR_FindFunctionSymbol(lib, "My_SetValue");
+ (*setFcn)(888);
+ value = (*getFcn)();
+ if (value != 888) {
+ fprintf(stderr, "Test 1 failed: set value to 888, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ }
+ if (debug_mode) printf("Test 1 passed\n");
+
+ /*
+ * Test 2: get a second handle to the same library (this should increment
+ * the reference count), look up the symbols, call the functions, and
+ * check the results.
+ */
+
+ getFcn = (GetFcnType) PR_FindSymbolAndLibrary("My_GetValue", &lib2);
+ if (NULL == getFcn || lib != lib2) {
+ fprintf(stderr, "Test 2 failed: handles for the same library are not "
+ "equal: handle 1: %p, handle 2: %p\n", lib, lib2);
+ if (!debug_mode) failed_already=1;
+ }
+ setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue");
+ value = (*getFcn)();
+ if (value != 888) {
+ fprintf(stderr, "Test 2 failed: value should be 888, but got %d\n",
+ value);
+ if (!debug_mode) failed_already=1;
+ }
+ (*setFcn)(777);
+ value = (*getFcn)();
+ if (value != 777) {
+ fprintf(stderr, "Test 2 failed: set value to 777, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ if (debug_mode) printf("Test 2 passed\n");
+
+ /*
+ * Test 3: unload the library. The library should still be accessible
+ * via the second handle. do the same things as above.
+ */
+
+ status = PR_UnloadLibrary(lib);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "Test 3 failed: cannot unload library: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ getFcn = (GetFcnType) PR_FindFunctionSymbol(lib2, "My_GetValue");
+ setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue");
+ (*setFcn)(666);
+ value = (*getFcn)();
+ if (value != 666) {
+ fprintf(stderr, "Test 3 failed: set value to 666, but got %d\n", value);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ if (debug_mode) printf("Test 3 passed\n");
+
+ /*
+ * Test 4: unload the library, testing the reference count mechanism.
+ */
+
+ status = PR_UnloadLibrary(lib2);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "Test 4 failed: cannot unload library: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ getFcn = (GetFcnType) PR_FindFunctionSymbolAndLibrary("My_GetValue", &lib2);
+ if (NULL != getFcn) {
+ fprintf(stderr, "Test 4 failed: how can we find a symbol "
+ "in an already unloaded library?\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ if (debug_mode) {
+ printf("Test 4 passed\n");
+ }
+
+ /*
+ ** Test 5: LoadStaticLibrary()
+ */
+ {
+ PRStaticLinkTable slt[10];
+ PRLibrary *lib;
+
+ lib = PR_LoadStaticLibrary( "my.dll", slt );
+ if ( lib == NULL )
+ {
+ fprintf(stderr, "Test 5: LoadStatiLibrary() failed\n" );
+ goto exit_now;
+ }
+ if (debug_mode)
+ {
+ printf("Test 5 passed\n");
+ }
+ }
+
+ goto exit_now;
+exit_now:
+ PR_Cleanup();
+
+ if (failed_already) {
+ printf("FAILED\n");
+ return 1;
+ } else {
+ printf("PASSED\n");
+ return 0;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/dtoa.c b/src/libs/xpcom18a4/nsprpub/pr/tests/dtoa.c
new file mode 100644
index 00000000..a9258c02
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/dtoa.c
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/******************************************************************************
+ *
+ * This file contains a test program for the function conversion functions
+ * for double precision code:
+ * PR_strtod
+ * PR_dtoa
+ * PR_cnvtf
+ *
+ * This file was ns/nspr/tests/dtoa.c, created by rrj on 1996/06/22.
+ *
+ *****************************************************************************/
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <locale.h>
+#include "prprf.h"
+#include "prdtoa.h"
+
+static int failed_already = 0;
+
+int main( int argc, char* argv[] )
+{
+ double num;
+ double num1;
+ double zero = 0.0;
+ char cnvt[50];
+
+ num = 1e24;
+ num1 = PR_strtod("1e24",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","1e24");
+ failed_already = 1;
+ }
+
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("1e+24",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = 0.001e7;
+ num1 = PR_strtod("0.001e7",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","0.001e7");
+ failed_already = 1;
+ }
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("10000",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = 0.0000000000000753;
+ num1 = PR_strtod("0.0000000000000753",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n",
+ "0.0000000000000753");
+ failed_already = 1;
+ }
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("7.53e-14",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = 1.867e73;
+ num1 = PR_strtod("1.867e73",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","1.867e73");
+ failed_already = 1;
+ }
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("1.867e+73",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+
+ num = -1.867e73;
+ num1 = PR_strtod("-1.867e73",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","-1.867e73");
+ failed_already = 1;
+ }
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("-1.867e+73",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = -1.867e-73;
+ num1 = PR_strtod("-1.867e-73",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","-1.867e-73");
+ failed_already = 1;
+ }
+
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("-1.867e-73",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ /* Testing for infinity */
+ num = 1.0 / zero;
+ num1 = PR_strtod("1.867e765",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","1.867e765");
+ failed_already = 1;
+ }
+
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("Infinity",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = -1.0 / zero;
+ num1 = PR_strtod("-1.867e765",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n","-1.867e765");
+ failed_already = 1;
+ }
+
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("-Infinity",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ /* Testing for NaN. PR_strtod can't parse "NaN" and "Infinity" */
+ num = zero / zero;
+
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("NaN",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = - zero / zero;
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("NaN",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+ num = 1.0000000001e21;
+ num1 = PR_strtod("1.0000000001e21",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n",
+ "1.0000000001e21");
+ failed_already = 1;
+ }
+
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("1.0000000001e+21",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+
+
+ num = -1.0000000001e-21;
+ num1 = PR_strtod("-1.0000000001e-21",NULL);
+ if(num1 != num){
+ fprintf(stderr,"Failed to convert numeric value %s\n",
+ "-1.0000000001e-21");
+ failed_already = 1;
+ }
+ PR_cnvtf(cnvt,sizeof(cnvt),20,num);
+ if(strcmp("-1.0000000001e-21",cnvt) != 0){
+ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt);
+ failed_already = 1;
+ }
+ if (failed_already) {
+ printf("FAILED\n");
+ } else {
+ printf("PASSED\n");
+ }
+ return failed_already;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/env.c b/src/libs/xpcom18a4/nsprpub/pr/tests/env.c
new file mode 100644
index 00000000..7f82fe08
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/env.c
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: env.c
+** Description: Testing environment variable operations
+**
+*/
+#include "prenv.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+PRIntn debug = 0;
+PRIntn verbose = 0;
+PRBool failedAlready = PR_FALSE;
+
+#define ENVNAME "NSPR_ENVIRONMENT_TEST_VARIABLE"
+#define ENVVALUE "The expected result"
+#define ENVBUFSIZE 256
+
+char *envBuf; /* buffer pointer. We leak memory here on purpose! */
+
+static char * NewBuffer( size_t size )
+{
+ char *buf = malloc( size );
+ if ( NULL == buf ) {
+ printf("env: NewBuffer() failed\n");
+ exit(1);
+ }
+ return(buf);
+} /* end NewBuffer() */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ char *value;
+ PRStatus rc;
+
+ { /* Get command line options */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "vd");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ break;
+ case 'v': /* verbose */
+ verbose = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ } /* end block "Get command line options" */
+
+#if 0
+ {
+ /*
+ ** This uses Windows native environment manipulation
+ ** as an experiment. Note the separation of namespace!
+ */
+ BOOL rv;
+ DWORD size;
+ rv = SetEnvironmentVariable( ENVNAME, ENVVALUE );
+ if ( rv == 0 ) {
+ if (debug) printf("env: Shit! SetEnvironmentVariable() failed\n");
+ failedAlready = PR_TRUE;
+ }
+ if (verbose) printf("env: SetEnvironmentVariable() worked\n");
+
+ size = GetEnvironmentVariable( ENVNAME, envBuf, ENVBUFSIZE );
+ if ( size == 0 ) {
+ if (debug) printf("env: Shit! GetEnvironmentVariable() failed. Found: %s\n", envBuf );
+ failedAlready = PR_TRUE;
+ }
+ if (verbose) printf("env: GetEnvironmentVariable() worked. Found: %s\n", envBuf);
+
+ value = PR_GetEnv( ENVNAME );
+ if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
+ if (debug) printf( "env: PR_GetEnv() failed retrieving WinNative. Found: %s\n", value);
+ failedAlready = PR_TRUE;
+ }
+ if (verbose) printf("env: PR_GetEnv() worked. Found: %s\n", value);
+ }
+#endif
+
+ /* set an environment variable, read it back */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "=" ENVVALUE );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed setting\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() worked.\n");
+ }
+
+ value = PR_GetEnv( ENVNAME );
+ if ( (NULL == value ) || (strcmp( value, ENVVALUE))) {
+ if (debug) printf( "env: PR_GetEnv() Failed after setting\n" );
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_GetEnv() worked after setting it. Found: %s\n", value );
+ }
+
+/* ---------------------------------------------------------------------- */
+ /* un-set the variable, using RAW name... should not work */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (verbose) printf( "env: PR_SetEnv() not un-set using RAW name. Good!\n");
+ } else {
+ if (debug) printf("env: PR_SetEnv() un-set using RAW name. Bad!\n" );
+ failedAlready = PR_TRUE;
+ }
+
+ value = PR_GetEnv( ENVNAME );
+ if ( NULL == value ) {
+ if (debug) printf("env: PR_GetEnv() after un-set using RAW name. Bad!\n" );
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf( "env: PR_GetEnv() after RAW un-set found: %s\n", value );
+ }
+
+/* ---------------------------------------------------------------------- */
+ /* set it again ... */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "=" ENVVALUE );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed setting the second time.\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() worked.\n");
+ }
+
+ /* un-set the variable using the form name= */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "=" );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" );
+ }
+
+ value = PR_GetEnv( ENVNAME );
+ if (( NULL == value ) || ( 0x00 == *value )) {
+ if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" );
+ } else {
+ if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
+ failedAlready = PR_TRUE;
+ }
+/* ---------------------------------------------------------------------- */
+ /* un-set the variable using the form name= */
+ envBuf = NewBuffer( ENVBUFSIZE );
+ sprintf( envBuf, ENVNAME "999=" );
+ rc = PR_SetEnv( envBuf );
+ if ( PR_FAILURE == rc ) {
+ if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n");
+ failedAlready = PR_TRUE;
+ } else {
+ if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" );
+ }
+
+ value = PR_GetEnv( ENVNAME "999" );
+ if (( NULL == value ) || ( 0x00 == *value )) {
+ if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" );
+ } else {
+ if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value );
+ failedAlready = PR_TRUE;
+ }
+
+/* ---------------------------------------------------------------------- */
+ if (debug || verbose) printf("\n%s\n", (failedAlready)? "FAILED" : "PASSED" );
+ return( (failedAlready)? 1 : 0 );
+} /* main() */
+
+/* env.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/errcodes.c b/src/libs/xpcom18a4/nsprpub/pr/tests/errcodes.c
new file mode 100644
index 00000000..76156848
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/errcodes.c
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: errcodes.c
+**
+** Description: print nspr error codes
+**
+*/
+#include "prerror.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+static int _debug_on = 0;
+
+struct errinfo {
+ PRErrorCode errcode;
+ char *errname;
+};
+
+struct errinfo errcodes[] = {
+{PR_OUT_OF_MEMORY_ERROR, "PR_OUT_OF_MEMORY_ERROR"},
+{PR_BAD_DESCRIPTOR_ERROR, "PR_BAD_DESCRIPTOR_ERROR"},
+{PR_WOULD_BLOCK_ERROR, "PR_WOULD_BLOCK_ERROR"},
+{PR_ACCESS_FAULT_ERROR, "PR_ACCESS_FAULT_ERROR"},
+{PR_INVALID_METHOD_ERROR, "PR_INVALID_METHOD_ERROR"},
+{PR_ILLEGAL_ACCESS_ERROR, "PR_ILLEGAL_ACCESS_ERROR"},
+{PR_UNKNOWN_ERROR, "PR_UNKNOWN_ERROR"},
+{PR_PENDING_INTERRUPT_ERROR, "PR_PENDING_INTERRUPT_ERROR"},
+{PR_NOT_IMPLEMENTED_ERROR, "PR_NOT_IMPLEMENTED_ERROR"},
+{PR_IO_ERROR, "PR_IO_ERROR"},
+{PR_IO_TIMEOUT_ERROR, "PR_IO_TIMEOUT_ERROR"},
+{PR_IO_PENDING_ERROR, "PR_IO_PENDING_ERROR"},
+{PR_DIRECTORY_OPEN_ERROR, "PR_DIRECTORY_OPEN_ERROR"},
+{PR_INVALID_ARGUMENT_ERROR, "PR_INVALID_ARGUMENT_ERROR"},
+{PR_ADDRESS_NOT_AVAILABLE_ERROR, "PR_ADDRESS_NOT_AVAILABLE_ERROR"},
+{PR_ADDRESS_NOT_SUPPORTED_ERROR, "PR_ADDRESS_NOT_SUPPORTED_ERROR"},
+{PR_IS_CONNECTED_ERROR, "PR_IS_CONNECTED_ERROR"},
+{PR_BAD_ADDRESS_ERROR, "PR_BAD_ADDRESS_ERROR"},
+{PR_ADDRESS_IN_USE_ERROR, "PR_ADDRESS_IN_USE_ERROR"},
+{PR_CONNECT_REFUSED_ERROR, "PR_CONNECT_REFUSED_ERROR"},
+{PR_NETWORK_UNREACHABLE_ERROR, "PR_NETWORK_UNREACHABLE_ERROR"},
+{PR_CONNECT_TIMEOUT_ERROR, "PR_CONNECT_TIMEOUT_ERROR"},
+{PR_NOT_CONNECTED_ERROR, "PR_NOT_CONNECTED_ERROR"},
+{PR_LOAD_LIBRARY_ERROR, "PR_LOAD_LIBRARY_ERROR"},
+{PR_UNLOAD_LIBRARY_ERROR, "PR_UNLOAD_LIBRARY_ERROR"},
+{PR_FIND_SYMBOL_ERROR, "PR_FIND_SYMBOL_ERROR"},
+{PR_INSUFFICIENT_RESOURCES_ERROR, "PR_INSUFFICIENT_RESOURCES_ERROR"},
+{PR_DIRECTORY_LOOKUP_ERROR, "PR_DIRECTORY_LOOKUP_ERROR"},
+{PR_TPD_RANGE_ERROR, "PR_TPD_RANGE_ERROR"},
+{PR_PROC_DESC_TABLE_FULL_ERROR, "PR_PROC_DESC_TABLE_FULL_ERROR"},
+{PR_SYS_DESC_TABLE_FULL_ERROR, "PR_SYS_DESC_TABLE_FULL_ERROR"},
+{PR_NOT_SOCKET_ERROR, "PR_NOT_SOCKET_ERROR"},
+{PR_NOT_TCP_SOCKET_ERROR, "PR_NOT_TCP_SOCKET_ERROR"},
+{PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "PR_SOCKET_ADDRESS_IS_BOUND_ERROR"},
+{PR_NO_ACCESS_RIGHTS_ERROR, "PR_NO_ACCESS_RIGHTS_ERROR"},
+{PR_OPERATION_NOT_SUPPORTED_ERROR, "PR_OPERATION_NOT_SUPPORTED_ERROR"},
+{PR_PROTOCOL_NOT_SUPPORTED_ERROR, "PR_PROTOCOL_NOT_SUPPORTED_ERROR"},
+{PR_REMOTE_FILE_ERROR, "PR_REMOTE_FILE_ERROR"},
+{PR_BUFFER_OVERFLOW_ERROR, "PR_BUFFER_OVERFLOW_ERROR"},
+{PR_CONNECT_RESET_ERROR, "PR_CONNECT_RESET_ERROR"},
+{PR_RANGE_ERROR, "PR_RANGE_ERROR"},
+{PR_DEADLOCK_ERROR, "PR_DEADLOCK_ERROR"},
+{PR_FILE_IS_LOCKED_ERROR, "PR_FILE_IS_LOCKED_ERROR"},
+{PR_FILE_TOO_BIG_ERROR, "PR_FILE_TOO_BIG_ERROR"},
+{PR_NO_DEVICE_SPACE_ERROR, "PR_NO_DEVICE_SPACE_ERROR"},
+{PR_PIPE_ERROR, "PR_PIPE_ERROR"},
+{PR_NO_SEEK_DEVICE_ERROR, "PR_NO_SEEK_DEVICE_ERROR"},
+{PR_IS_DIRECTORY_ERROR, "PR_IS_DIRECTORY_ERROR"},
+{PR_LOOP_ERROR, "PR_LOOP_ERROR"},
+{PR_NAME_TOO_LONG_ERROR, "PR_NAME_TOO_LONG_ERROR"},
+{PR_FILE_NOT_FOUND_ERROR, "PR_FILE_NOT_FOUND_ERROR"},
+{PR_NOT_DIRECTORY_ERROR, "PR_NOT_DIRECTORY_ERROR"},
+{PR_READ_ONLY_FILESYSTEM_ERROR, "PR_READ_ONLY_FILESYSTEM_ERROR"},
+{PR_DIRECTORY_NOT_EMPTY_ERROR, "PR_DIRECTORY_NOT_EMPTY_ERROR"},
+{PR_FILESYSTEM_MOUNTED_ERROR, "PR_FILESYSTEM_MOUNTED_ERROR"},
+{PR_NOT_SAME_DEVICE_ERROR, "PR_NOT_SAME_DEVICE_ERROR"},
+{PR_DIRECTORY_CORRUPTED_ERROR, "PR_DIRECTORY_CORRUPTED_ERROR"},
+{PR_FILE_EXISTS_ERROR, "PR_FILE_EXISTS_ERROR"},
+{PR_MAX_DIRECTORY_ENTRIES_ERROR, "PR_MAX_DIRECTORY_ENTRIES_ERROR"},
+{PR_INVALID_DEVICE_STATE_ERROR, "PR_INVALID_DEVICE_STATE_ERROR"},
+{PR_DEVICE_IS_LOCKED_ERROR, "PR_DEVICE_IS_LOCKED_ERROR"},
+{PR_NO_MORE_FILES_ERROR, "PR_NO_MORE_FILES_ERROR"},
+{PR_END_OF_FILE_ERROR, "PR_END_OF_FILE_ERROR"},
+{PR_FILE_SEEK_ERROR, "PR_FILE_SEEK_ERROR"},
+{PR_FILE_IS_BUSY_ERROR, "PR_FILE_IS_BUSY_ERROR"},
+{PR_IN_PROGRESS_ERROR, "PR_IN_PROGRESS_ERROR"},
+{PR_ALREADY_INITIATED_ERROR, "PR_ALREADY_INITIATED_ERROR"},
+{PR_GROUP_EMPTY_ERROR, "PR_GROUP_EMPTY_ERROR"},
+{PR_INVALID_STATE_ERROR, "PR_INVALID_STATE_ERROR"},
+{PR_NETWORK_DOWN_ERROR, "PR_NETWORK_DOWN_ERROR"},
+{PR_SOCKET_SHUTDOWN_ERROR, "PR_SOCKET_SHUTDOWN_ERROR"},
+{PR_CONNECT_ABORTED_ERROR, "PR_CONNECT_ABORTED_ERROR"},
+{PR_HOST_UNREACHABLE_ERROR, "PR_HOST_UNREACHABLE_ERROR"}
+};
+
+int
+main(int argc, char **argv)
+{
+
+ int count, errnum;
+
+ /*
+ * -d debug mode
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ count = sizeof(errcodes)/sizeof(errcodes[0]);
+ printf("\nNumber of error codes = %d\n\n",count);
+ for (errnum = 0; errnum < count; errnum++) {
+ printf("%-40s = %d\n",errcodes[errnum].errname,
+ errcodes[errnum].errcode);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/errset.c b/src/libs/xpcom18a4/nsprpub/pr/tests/errset.c
new file mode 100644
index 00000000..7d025f12
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/errset.c
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: errset.c
+**
+** Description: errset.c exercises the functions in prerror.c.
+** This code is a unit test of the prerror.c capability.
+**
+** Note: There's some fluff in here. The guts of the test
+** were plagerized from another test. So, sue me.
+**
+**
+*/
+#include "prerror.h"
+#include "plgetopt.h"
+#include "prlog.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static int _debug_on = 0;
+
+struct errinfo {
+ PRErrorCode errcode;
+ char *errname;
+};
+
+struct errinfo errcodes[] = {
+{PR_OUT_OF_MEMORY_ERROR, "PR_OUT_OF_MEMORY_ERROR"},
+{PR_UNKNOWN_ERROR, "An intentionally long error message text intended to force a delete of the current errorString buffer and get another one."},
+{PR_BAD_DESCRIPTOR_ERROR, "PR_BAD_DESCRIPTOR_ERROR"},
+{PR_WOULD_BLOCK_ERROR, "PR_WOULD_BLOCK_ERROR"},
+{PR_ACCESS_FAULT_ERROR, "PR_ACCESS_FAULT_ERROR"},
+{PR_INVALID_METHOD_ERROR, "PR_INVALID_METHOD_ERROR"},
+{PR_ILLEGAL_ACCESS_ERROR, "PR_ILLEGAL_ACCESS_ERROR"},
+{PR_UNKNOWN_ERROR, "PR_UNKNOWN_ERROR"},
+{PR_PENDING_INTERRUPT_ERROR, "PR_PENDING_INTERRUPT_ERROR"},
+{PR_NOT_IMPLEMENTED_ERROR, "PR_NOT_IMPLEMENTED_ERROR"},
+{PR_IO_ERROR, "PR_IO_ERROR"},
+{PR_IO_TIMEOUT_ERROR, "PR_IO_TIMEOUT_ERROR"},
+{PR_IO_PENDING_ERROR, "PR_IO_PENDING_ERROR"},
+{PR_DIRECTORY_OPEN_ERROR, "PR_DIRECTORY_OPEN_ERROR"},
+{PR_INVALID_ARGUMENT_ERROR, "PR_INVALID_ARGUMENT_ERROR"},
+{PR_ADDRESS_NOT_AVAILABLE_ERROR, "PR_ADDRESS_NOT_AVAILABLE_ERROR"},
+{PR_ADDRESS_NOT_SUPPORTED_ERROR, "PR_ADDRESS_NOT_SUPPORTED_ERROR"},
+{PR_IS_CONNECTED_ERROR, "PR_IS_CONNECTED_ERROR"},
+{PR_BAD_ADDRESS_ERROR, "PR_BAD_ADDRESS_ERROR"},
+{PR_ADDRESS_IN_USE_ERROR, "PR_ADDRESS_IN_USE_ERROR"},
+{PR_CONNECT_REFUSED_ERROR, "PR_CONNECT_REFUSED_ERROR"},
+{PR_NETWORK_UNREACHABLE_ERROR, "PR_NETWORK_UNREACHABLE_ERROR"},
+{PR_CONNECT_TIMEOUT_ERROR, "PR_CONNECT_TIMEOUT_ERROR"},
+{PR_NOT_CONNECTED_ERROR, "PR_NOT_CONNECTED_ERROR"},
+{PR_LOAD_LIBRARY_ERROR, "PR_LOAD_LIBRARY_ERROR"},
+{PR_UNLOAD_LIBRARY_ERROR, "PR_UNLOAD_LIBRARY_ERROR"},
+{PR_FIND_SYMBOL_ERROR, "PR_FIND_SYMBOL_ERROR"},
+{PR_INSUFFICIENT_RESOURCES_ERROR, "PR_INSUFFICIENT_RESOURCES_ERROR"},
+{PR_DIRECTORY_LOOKUP_ERROR, "PR_DIRECTORY_LOOKUP_ERROR"},
+{PR_TPD_RANGE_ERROR, "PR_TPD_RANGE_ERROR"},
+{PR_PROC_DESC_TABLE_FULL_ERROR, "PR_PROC_DESC_TABLE_FULL_ERROR"},
+{PR_SYS_DESC_TABLE_FULL_ERROR, "PR_SYS_DESC_TABLE_FULL_ERROR"},
+{PR_NOT_SOCKET_ERROR, "PR_NOT_SOCKET_ERROR"},
+{PR_NOT_TCP_SOCKET_ERROR, "PR_NOT_TCP_SOCKET_ERROR"},
+{PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "PR_SOCKET_ADDRESS_IS_BOUND_ERROR"},
+{PR_NO_ACCESS_RIGHTS_ERROR, "PR_NO_ACCESS_RIGHTS_ERROR"},
+{PR_OPERATION_NOT_SUPPORTED_ERROR, "PR_OPERATION_NOT_SUPPORTED_ERROR"},
+{PR_PROTOCOL_NOT_SUPPORTED_ERROR, "PR_PROTOCOL_NOT_SUPPORTED_ERROR"},
+{PR_REMOTE_FILE_ERROR, "PR_REMOTE_FILE_ERROR"},
+{PR_BUFFER_OVERFLOW_ERROR, "PR_BUFFER_OVERFLOW_ERROR"},
+{PR_CONNECT_RESET_ERROR, "PR_CONNECT_RESET_ERROR"},
+{PR_RANGE_ERROR, "PR_RANGE_ERROR"},
+{PR_DEADLOCK_ERROR, "PR_DEADLOCK_ERROR"},
+{PR_FILE_IS_LOCKED_ERROR, "PR_FILE_IS_LOCKED_ERROR"},
+{PR_FILE_TOO_BIG_ERROR, "PR_FILE_TOO_BIG_ERROR"},
+{PR_NO_DEVICE_SPACE_ERROR, "PR_NO_DEVICE_SPACE_ERROR"},
+{PR_PIPE_ERROR, "PR_PIPE_ERROR"},
+{PR_NO_SEEK_DEVICE_ERROR, "PR_NO_SEEK_DEVICE_ERROR"},
+{PR_IS_DIRECTORY_ERROR, "PR_IS_DIRECTORY_ERROR"},
+{PR_LOOP_ERROR, "PR_LOOP_ERROR"},
+{PR_NAME_TOO_LONG_ERROR, "PR_NAME_TOO_LONG_ERROR"},
+{PR_FILE_NOT_FOUND_ERROR, "PR_FILE_NOT_FOUND_ERROR"},
+{PR_NOT_DIRECTORY_ERROR, "PR_NOT_DIRECTORY_ERROR"},
+{PR_READ_ONLY_FILESYSTEM_ERROR, "PR_READ_ONLY_FILESYSTEM_ERROR"},
+{PR_DIRECTORY_NOT_EMPTY_ERROR, "PR_DIRECTORY_NOT_EMPTY_ERROR"},
+{PR_FILESYSTEM_MOUNTED_ERROR, "PR_FILESYSTEM_MOUNTED_ERROR"},
+{PR_NOT_SAME_DEVICE_ERROR, "PR_NOT_SAME_DEVICE_ERROR"},
+{PR_DIRECTORY_CORRUPTED_ERROR, "PR_DIRECTORY_CORRUPTED_ERROR"},
+{PR_FILE_EXISTS_ERROR, "PR_FILE_EXISTS_ERROR"},
+{PR_MAX_DIRECTORY_ENTRIES_ERROR, "PR_MAX_DIRECTORY_ENTRIES_ERROR"},
+{PR_INVALID_DEVICE_STATE_ERROR, "PR_INVALID_DEVICE_STATE_ERROR"},
+{PR_DEVICE_IS_LOCKED_ERROR, "PR_DEVICE_IS_LOCKED_ERROR"},
+{PR_NO_MORE_FILES_ERROR, "PR_NO_MORE_FILES_ERROR"},
+{PR_END_OF_FILE_ERROR, "PR_END_OF_FILE_ERROR"},
+{PR_FILE_SEEK_ERROR, "PR_FILE_SEEK_ERROR"},
+{PR_FILE_IS_BUSY_ERROR, "PR_FILE_IS_BUSY_ERROR"},
+{PR_IN_PROGRESS_ERROR, "PR_IN_PROGRESS_ERROR"},
+{PR_ALREADY_INITIATED_ERROR, "PR_ALREADY_INITIATED_ERROR"},
+{PR_GROUP_EMPTY_ERROR, "PR_GROUP_EMPTY_ERROR"},
+{PR_INVALID_STATE_ERROR, "PR_INVALID_STATE_ERROR"},
+{PR_NETWORK_DOWN_ERROR, "PR_NETWORK_DOWN_ERROR"},
+{PR_SOCKET_SHUTDOWN_ERROR, "PR_SOCKET_SHUTDOWN_ERROR"},
+{PR_CONNECT_ABORTED_ERROR, "PR_CONNECT_ABORTED_ERROR"},
+{PR_HOST_UNREACHABLE_ERROR, "PR_HOST_UNREACHABLE_ERROR"}
+};
+
+int
+main(int argc, char **argv)
+{
+
+ int count, errnum;
+
+ /*
+ * -d debug mode
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ count = sizeof(errcodes)/sizeof(errcodes[0]);
+ printf("\nNumber of error codes = %d\n\n",count);
+ for (errnum = 0; errnum < count; errnum++) {
+ PRInt32 len1, len2, err;
+ char msg[256];
+
+ PR_SetError( errnum, -5 );
+ err = PR_GetError();
+ PR_ASSERT( err == errnum );
+ err = PR_GetOSError();
+ PR_ASSERT( err == -5 );
+ PR_SetErrorText( strlen(errcodes[errnum].errname), errcodes[errnum].errname );
+ len1 = PR_GetErrorTextLength();
+ len2 = PR_GetErrorText( msg );
+ PR_ASSERT( len1 == len2 );
+ printf("%5.5d -- %s\n", errnum, msg );
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/exit.c b/src/libs/xpcom18a4/nsprpub/pr/tests/exit.c
new file mode 100644
index 00000000..6ccbe86d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/exit.c
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prinit.h"
+#include "prthread.h"
+#include "prproces.h"
+#include "prinrval.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+static PRInt32 dally = 0;
+static PRFileDesc *err = NULL;
+static PRBool verbose = PR_FALSE, force = PR_FALSE;
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: [-t s] [-h]\n");
+ PR_fprintf(err, "\t-d Verbose output (default: FALSE)\n");
+ PR_fprintf(err, "\t-x Forced termination (default: FALSE)\n");
+ PR_fprintf(err, "\t-t Time for thread to block (default: 10 seconds)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+static void Dull(void *arg)
+{
+ PR_Sleep(PR_SecondsToInterval(dally));
+ if (verbose && force)
+ PR_fprintf(err, "If you see this, the test failed\n");
+} /* Dull */
+
+static PRIntn PR_CALLBACK RealMain(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "ht:dx");
+
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* verbosity */
+ verbose = PR_TRUE;
+ break;
+ case 'x': /* force exit */
+ force = PR_TRUE;
+ break;
+ case 't': /* seconds to dally in child */
+ dally = atoi(opt->value);
+ break;
+ case 'h': /* user wants some guidance */
+ default:
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == dally) dally = 10;
+
+ /*
+ * Create LOCAL and GLOBAL threads
+ */
+ (void)PR_CreateThread(
+ PR_USER_THREAD, Dull, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+
+ (void)PR_CreateThread(
+ PR_USER_THREAD, Dull, NULL, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+
+ if (verbose)
+ PR_fprintf(
+ err, "Main is exiting now. Program should exit %s.\n",
+ (force) ? "immediately" : "after child dally time");
+
+ if (force)
+ {
+ PR_ProcessExit(0);
+ if (verbose)
+ {
+ PR_fprintf(err, "You should not have gotten here.\n");
+ return 1;
+ }
+ }
+ return 0;
+
+}
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/fdcach.c b/src/libs/xpcom18a4/nsprpub/pr/tests/fdcach.c
new file mode 100644
index 00000000..33382fa8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/fdcach.c
@@ -0,0 +1,259 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: fdcach.c
+ * Description:
+ * This test verifies that the fd cache and stack are working
+ * correctly.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Define ORDER_PRESERVED if the implementation of PR_SetFDCacheSize
+ * preserves the ordering of the fd's when moving them between the
+ * cache and the stack.
+ */
+#define ORDER_PRESERVED 1
+
+/*
+ * NUM_FDS must be <= FD_CACHE_SIZE.
+ */
+#define FD_CACHE_SIZE 1024
+#define NUM_FDS 20
+
+int main(int argc, char **argv)
+{
+ int i;
+ PRFileDesc *fds[NUM_FDS];
+ PRFileDesc *savefds[NUM_FDS];
+ int numfds = sizeof(fds)/sizeof(fds[0]);
+
+ /*
+ * Switch between cache and stack when they are empty.
+ * Then start with the fd cache.
+ */
+ PR_SetFDCacheSize(0, FD_CACHE_SIZE);
+ PR_SetFDCacheSize(0, 0);
+ PR_SetFDCacheSize(0, FD_CACHE_SIZE);
+
+ /* Add some fd's to the fd cache. */
+ for (i = 0; i < numfds; i++) {
+ savefds[i] = PR_NewTCPSocket();
+ if (NULL == savefds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ }
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ /*
+ * Create some fd's. These fd's should come from
+ * the fd cache. Verify the FIFO ordering of the fd
+ * cache.
+ */
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (fds[i] != savefds[i]) {
+ fprintf(stderr, "fd cache malfunctioned\n");
+ exit(1);
+ }
+ }
+ /* Put the fd's back to the fd cache. */
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ /* Switch to the fd stack. */
+ PR_SetFDCacheSize(0, 0);
+
+ /*
+ * Create some fd's. These fd's should come from
+ * the fd stack.
+ */
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+#ifdef ORDER_PRESERVED
+ if (fds[i] != savefds[numfds-1-i]) {
+ fprintf(stderr, "fd stack malfunctioned\n");
+ exit(1);
+ }
+#else
+ savefds[numfds-1-i] = fds[i];
+#endif
+ }
+ /* Put the fd's back to the fd stack. */
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ /*
+ * Now create some fd's and verify the LIFO ordering of
+ * the fd stack.
+ */
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (fds[i] != savefds[numfds-1-i]) {
+ fprintf(stderr, "fd stack malfunctioned\n");
+ exit(1);
+ }
+ }
+ /* Put the fd's back to the fd stack. */
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ /* Switch to the fd cache. */
+ PR_SetFDCacheSize(0, FD_CACHE_SIZE);
+
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+#ifdef ORDER_PRESERVED
+ if (fds[i] != savefds[i]) {
+ fprintf(stderr, "fd cache malfunctioned\n");
+ exit(1);
+ }
+#else
+ savefds[i] = fds[i];
+#endif
+ }
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (fds[i] != savefds[i]) {
+ fprintf(stderr, "fd cache malfunctioned\n");
+ exit(1);
+ }
+ }
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ /* Switch to the fd stack. */
+ PR_SetFDCacheSize(0, 0);
+
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+#ifdef ORDER_PRESERVED
+ if (fds[i] != savefds[numfds-1-i]) {
+ fprintf(stderr, "fd stack malfunctioned\n");
+ exit(1);
+ }
+#else
+ savefds[numfds-1-i];
+#endif
+ }
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < numfds; i++) {
+ fds[i] = PR_NewTCPSocket();
+ if (NULL == fds[i]) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (fds[i] != savefds[numfds-1-i]) {
+ fprintf(stderr, "fd stack malfunctioned\n");
+ exit(1);
+ }
+ }
+ for (i = 0; i < numfds; i++) {
+ if (PR_Close(savefds[i]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+
+ PR_Cleanup();
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/fileio.c b/src/libs/xpcom18a4/nsprpub/pr/tests/fileio.c
new file mode 100644
index 00000000..0b154047
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/fileio.c
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: fileio.c
+**
+** Description: Program to copy one file to another.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 Revert to return code 0 and 1, remove debug option (obsolete).
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+#include "prinit.h"
+#include "prthread.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prmon.h"
+#include "prmem.h"
+#include "prio.h"
+#include "prlog.h"
+
+#include <stdio.h>
+
+#ifdef XP_MAC
+#include "prsem.h"
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#else
+#include "obsolete/prsem.h"
+#endif
+
+
+#define TBSIZE 1024
+
+static PRUint8 tbuf[TBSIZE];
+
+static PRFileDesc *t1, *t2;
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+static void InitialSetup(void)
+{
+ PRUintn i;
+ PRInt32 nWritten, rv;
+
+ t1 = PR_Open("t1.tmp", PR_CREATE_FILE | PR_RDWR, 0);
+ PR_ASSERT(t1 != NULL);
+
+ for (i=0; i<TBSIZE; i++)
+ tbuf[i] = i;
+
+ nWritten = PR_Write((PRFileDesc*)t1, tbuf, TBSIZE);
+ PR_ASSERT(nWritten == TBSIZE);
+
+ rv = PR_Seek(t1,0,PR_SEEK_SET);
+ PR_ASSERT(rv == 0);
+
+ t2 = PR_Open("t2.tmp", PR_CREATE_FILE | PR_RDWR, 0);
+ PR_ASSERT(t2 != NULL);
+}
+
+
+static void VerifyAndCleanup(void)
+{
+ PRUintn i;
+ PRInt32 nRead, rv;
+
+ for (i=0; i<TBSIZE; i++)
+ tbuf[i] = 0;
+
+ rv = PR_Seek(t2,0,PR_SEEK_SET);
+ PR_ASSERT(rv == 0);
+
+ nRead = PR_Read((PRFileDesc*)t2, tbuf, TBSIZE);
+ PR_ASSERT(nRead == TBSIZE);
+
+ for (i=0; i<TBSIZE; i++)
+ if (tbuf[i] != (PRUint8)i) {
+ if (debug_mode) printf("data mismatch for index= %d \n", i);
+ else failed_already=1;
+ }
+ PR_Close(t1);
+ PR_Close(t2);
+
+ PR_Delete("t1.tmp");
+ PR_Delete("t2.tmp");
+
+ if (debug_mode) printf("fileio test passed\n");
+}
+
+
+/*------------------ Following is the real test program ---------*/
+/*
+ Program to copy one file to another. Two temporary files get
+ created. First one gets written in one write call. Then,
+ a reader thread reads from this file into a double buffer.
+ The writer thread writes from double buffer into the other
+ temporary file. The second temporary file gets verified
+ for accurate data.
+*/
+
+PRSemaphore *emptyBufs; /* number of empty buffers */
+PRSemaphore *fullBufs; /* number of buffers that are full */
+
+#define BSIZE 100
+
+struct {
+ char data[BSIZE];
+ PRUintn nbytes; /* number of bytes in this buffer */
+} buf[2];
+
+static void PR_CALLBACK reader(void *arg)
+{
+ PRUintn i = 0;
+ PRInt32 nbytes;
+
+ do {
+ (void) PR_WaitSem(emptyBufs);
+ nbytes = PR_Read((PRFileDesc*)arg, buf[i].data, BSIZE);
+ if (nbytes >= 0) {
+ buf[i].nbytes = nbytes;
+ PR_PostSem(fullBufs);
+ i = (i + 1) % 2;
+ }
+ } while (nbytes > 0);
+}
+
+static void PR_CALLBACK writer(void *arg)
+{
+ PRUintn i = 0;
+ PRInt32 nbytes;
+
+ do {
+ (void) PR_WaitSem(fullBufs);
+ nbytes = buf[i].nbytes;
+ if (nbytes > 0) {
+ nbytes = PR_Write((PRFileDesc*)arg, buf[i].data, nbytes);
+ PR_PostSem(emptyBufs);
+ i = (i + 1) % 2;
+ }
+ } while (nbytes > 0);
+}
+
+int main(int argc, char **argv)
+{
+ PRThread *r, *w;
+
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("fileio.log");
+ debug_mode = 1;
+#endif
+
+ emptyBufs = PR_NewSem(2); /* two empty buffers */
+
+ fullBufs = PR_NewSem(0); /* zero full buffers */
+
+ /* Create initial temp file setup */
+ InitialSetup();
+
+ /* create the reader thread */
+
+ r = PR_CreateThread(PR_USER_THREAD,
+ reader, t1,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ w = PR_CreateThread(PR_USER_THREAD,
+ writer, t2,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ /* Do the joining for both threads */
+ (void) PR_JoinThread(r);
+ (void) PR_JoinThread(w);
+
+ /* Do the verification and clean up */
+ VerifyAndCleanup();
+
+ PR_DestroySem(emptyBufs);
+ PR_DestroySem(fullBufs);
+
+ PR_Cleanup();
+
+ if(failed_already)
+ {
+ printf("Fail\n");
+ return 1;
+ }
+ else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/foreign.c b/src/libs/xpcom18a4/nsprpub/pr/tests/foreign.c
new file mode 100644
index 00000000..37f154e1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/foreign.c
@@ -0,0 +1,416 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: foreign.c
+** Description: Testing various functions w/ foreign threads
+**
+** We create a thread and get it to call exactly one runtime function.
+** The thread is allowed to be created by some other environment that
+** NSPR, but it does not announce itself to the runtime prior to calling
+** in.
+**
+** The goal: try to survive.
+**
+*/
+
+#include "prcvar.h"
+#include "prenv.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prthread.h"
+#include "prtypes.h"
+#include "prprf.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static enum {
+ thread_nspr, thread_pthread, thread_uithread, thread_sproc, thread_win32
+} thread_provider;
+
+typedef void (*StartFn)(void*);
+typedef struct StartObject
+{
+ StartFn start;
+ void *arg;
+} StartObject;
+
+static PRFileDesc *output;
+
+static int _debug_on = 0;
+
+#define DEFAULT_THREAD_COUNT 10
+
+#define DPRINTF(arg) if (_debug_on) PR_fprintf arg
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include <pthread.h>
+#include "md/_pth.h"
+static void *pthread_start(void *arg)
+{
+ StartFn start = ((StartObject*)arg)->start;
+ void *data = ((StartObject*)arg)->arg;
+ PR_Free(arg);
+ start(data);
+ return NULL;
+} /* pthread_start */
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+#include <thread.h>
+static void *uithread_start(void *arg)
+{
+ StartFn start = ((StartObject*)arg)->start;
+ void *data = ((StartObject*)arg)->arg;
+ PR_Free(arg);
+ start(data);
+ return NULL;
+} /* uithread_start */
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+#include <sys/types.h>
+#include <sys/prctl.h>
+static void sproc_start(void *arg, PRSize size)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+} /* sproc_start */
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+
+#if defined(WIN32)
+#include <process.h> /* for _beginthreadex() */
+
+static PRUintn __stdcall windows_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return 0;
+} /* windows_start */
+#endif /* defined(WIN32) */
+
+static PRStatus CreateThread(StartFn start, void *arg)
+{
+ PRStatus rv;
+
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ {
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, start, arg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
+ }
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ {
+ int rv;
+ pthread_t id;
+ pthread_attr_t tattr;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ rv = _PT_PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+ PR_ASSERT(0 == rv);
+
+#if !defined(LINUX)
+ rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = _PT_PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
+ (void)_PT_PTHREAD_ATTR_DESTROY(&tattr);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ break;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+ case thread_uithread:
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ {
+ int rv;
+ thread_t id;
+ long flags;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ flags = THR_DETACHED;
+
+ rv = thr_create(NULL, NULL, uithread_start, start_object, flags, &id);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ break;
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+
+ case thread_sproc:
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ {
+ PRInt32 pid;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ pid = sprocsp(
+ sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
+ rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+ break;
+ case thread_win32:
+#if defined(WIN32)
+ {
+ void *th;
+ PRUintn id;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ th = (void*)_beginthreadex(
+ NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
+ 0U, /* DWORD - initial thread stack size, in bytes */
+ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
+ start_object, /* LPVOID - argument for new thread */
+ 0U, /*DWORD dwCreationFlags - creation flags */
+ &id /* LPDWORD - pointer to returned thread identifier */ );
+
+ rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif
+ break;
+ default:
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* CreateThread */
+
+static void PR_CALLBACK lazyEntry(void *arg)
+{
+ PR_ASSERT(NULL == arg);
+} /* lazyEntry */
+
+
+static void OneShot(void *arg)
+{
+ PRUintn pdkey;
+ PRLock *lock;
+ PRFileDesc *fd;
+ PRDir *dir;
+ PRFileDesc *pair[2];
+ PRIntn test = (PRIntn)arg;
+
+ for (test = 0; test < 12; ++test) {
+
+ switch (test)
+ {
+ case 0:
+ lock = PR_NewLock();
+ DPRINTF((output,"Thread[0x%x] called PR_NewLock\n",
+ PR_GetCurrentThread()));
+ PR_DestroyLock(lock);
+ break;
+
+ case 1:
+ (void)PR_SecondsToInterval(1);
+ DPRINTF((output,"Thread[0x%x] called PR_SecondsToInterval\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 2: (void)PR_CreateThread(
+ PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+ DPRINTF((output,"Thread[0x%x] called PR_CreateThread\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 3:
+ fd = PR_Open("foreign.tmp", PR_CREATE_FILE | PR_RDWR, 0666);
+ DPRINTF((output,"Thread[0x%x] called PR_Open\n",
+ PR_GetCurrentThread()));
+ PR_Close(fd);
+ break;
+
+ case 4:
+ fd = PR_NewUDPSocket();
+ DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n",
+ PR_GetCurrentThread()));
+ PR_Close(fd);
+ break;
+
+ case 5:
+ fd = PR_NewTCPSocket();
+ DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n",
+ PR_GetCurrentThread()));
+ PR_Close(fd);
+ break;
+
+ case 6:
+ dir = PR_OpenDir("/tmp/");
+ DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n",
+ PR_GetCurrentThread()));
+ PR_CloseDir(dir);
+ break;
+
+ case 7:
+ (void)PR_NewThreadPrivateIndex(&pdkey, NULL);
+ DPRINTF((output,"Thread[0x%x] called PR_NewThreadPrivateIndex\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 8:
+ (void)PR_GetEnv("PATH");
+ DPRINTF((output,"Thread[0x%x] called PR_GetEnv\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 9:
+ (void)PR_NewTCPSocketPair(pair);
+ DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n",
+ PR_GetCurrentThread()));
+ PR_Close(pair[0]);
+ PR_Close(pair[1]);
+ break;
+
+ case 10:
+ PR_SetConcurrency(2);
+ DPRINTF((output,"Thread[0x%x] called PR_SetConcurrency\n",
+ PR_GetCurrentThread()));
+ break;
+
+ case 11:
+ PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH);
+ DPRINTF((output,"Thread[0x%x] called PR_SetThreadPriority\n",
+ PR_GetCurrentThread()));
+ break;
+
+ default:
+ break;
+ } /* switch() */
+ }
+} /* OneShot */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRInt32 thread_cnt = DEFAULT_THREAD_COUNT;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
+
+#if defined(WIN32)
+ thread_provider = thread_win32;
+#elif defined(_PR_PTHREADS)
+ thread_provider = thread_pthread;
+#elif defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ thread_provider = thread_uithread;
+#elif defined(IRIX)
+ thread_provider = thread_sproc;
+#else
+ thread_provider = thread_nspr;
+#endif
+
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(2);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+
+ while (thread_cnt-- > 0)
+ {
+ rv = CreateThread(OneShot, (void*)thread_cnt);
+ PR_ASSERT(PR_SUCCESS == rv);
+ PR_Sleep(PR_MillisecondsToInterval(5));
+ }
+ PR_Sleep(PR_SecondsToInterval(3));
+ return (PR_SUCCESS == PR_Cleanup()) ? 0 : 1;
+} /* main */
+
+/* foreign.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/forktest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/forktest.c
new file mode 100644
index 00000000..ad260ad7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/forktest.c
@@ -0,0 +1,346 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: forktest.c
+**
+** Description: UNIX test for fork functions.
+**
+** Modification History:
+** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+** 12-June-97 AGarcic - Revert to return code 0 and 1, remove debug option (obsolete).
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+PRIntn failed_already=0;
+
+#ifdef XP_UNIX
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+static char *message = "Hello world!";
+
+static void
+ClientThreadFunc(void *arg)
+{
+ PRNetAddr addr;
+ PRFileDesc *sock = NULL;
+ PRInt32 tmp = (PRInt32)arg;
+
+ /*
+ * Make sure the PR_Accept call will block
+ */
+
+ printf("Wait one second before connect\n");
+ fflush(stdout);
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = 0;
+ if ((sock = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "failed to create TCP socket: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ if (PR_Bind(sock, &addr) != PR_SUCCESS) {
+ fprintf(stderr, "PR_Bind failed: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
+ addr.inet.port = PR_htons((PRInt16)tmp);
+ printf("Connecting to port %hu\n", PR_ntohs(addr.inet.port));
+ fflush(stdout);
+ if (PR_Connect(sock, &addr, PR_SecondsToInterval(5)) !=
+ PR_SUCCESS) {
+ fprintf(stderr, "PR_Connect failed: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ printf("Writing message \"%s\"\n", message);
+ fflush(stdout);
+ if (PR_Send(sock, message, strlen(message) + 1, 0, PR_INTERVAL_NO_TIMEOUT) ==
+ -1) {
+ fprintf(stderr, "PR_Send failed: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+finish:
+ if (sock) {
+ PR_Close(sock);
+ }
+ return;
+}
+
+/*
+ * DoIO --
+ * This function creates a thread that acts as a client and itself.
+ * acts as a server. Then it joins the client thread.
+ */
+static void
+DoIO(void)
+{
+ PRThread *clientThread;
+ PRFileDesc *listenSock = NULL;
+ PRFileDesc *sock = NULL;
+ PRNetAddr addr;
+ PRInt32 nBytes;
+ char buf[128];
+
+ listenSock = PR_NewTCPSocket();
+ if (!listenSock) {
+ fprintf(stderr, "failed to create a TCP socket: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = 0;
+ if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "failed to bind socket: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "failed to get socket port number: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc,
+ (void *) PR_ntohs(addr.inet.port), PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "Cannot create client thread: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already = 1;
+ goto finish;
+ }
+ printf("Accepting connection at port %hu\n", PR_ntohs(addr.inet.port));
+ fflush(stdout);
+ sock = PR_Accept(listenSock, &addr, PR_SecondsToInterval(5));
+ if (!sock) {
+ fprintf(stderr, "PR_Accept failed: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+ nBytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Recv failed: error code %d\n",
+ PR_GetError());
+ failed_already = 1;
+ goto finish;
+ }
+
+ /*
+ * Make sure it has proper null byte to mark end of string
+ */
+
+ buf[sizeof(buf) - 1] = '\0';
+ printf("Received \"%s\" from the client\n", buf);
+ fflush(stdout);
+ if (!strcmp(buf, message)) {
+ PR_JoinThread(clientThread);
+
+ printf("The message is received correctly\n");
+ fflush(stdout);
+ } else {
+ fprintf(stderr, "The message should be \"%s\"\n",
+ message);
+ failed_already = 1;
+ }
+
+finish:
+ if (listenSock) {
+ PR_Close(listenSock);
+ }
+ if (sock) {
+ PR_Close(sock);
+ }
+ return;
+}
+
+#ifdef _PR_DCETHREADS
+
+#include <syscall.h>
+
+pid_t PR_UnixFork1(void)
+{
+ pid_t parent = getpid();
+ int rv = syscall(SYS_fork);
+
+ if (rv == -1) {
+ return (pid_t) -1;
+ } else {
+ /* For each process, rv is the pid of the other process */
+ if (rv == parent) {
+ /* the child */
+ return 0;
+ } else {
+ /* the parent */
+ return rv;
+ }
+ }
+}
+
+#elif defined(SOLARIS)
+
+/*
+ * It seems like that in Solaris 2.4 one must call fork1() if the
+ * the child process is going to use thread functions. Solaris 2.5
+ * doesn't have this problem. Calling fork() also works.
+ */
+
+pid_t PR_UnixFork1(void)
+{
+ return fork1();
+}
+
+#else
+
+pid_t PR_UnixFork1(void)
+{
+ return fork();
+}
+
+#endif /* PR_DCETHREADS */
+
+int main(
+int argc,
+char *argv[]
+)
+{
+ pid_t pid;
+ int rv;
+
+ /* main test program */
+
+ DoIO();
+
+ pid = PR_UnixFork1();
+
+ if (pid == (pid_t) -1) {
+ fprintf(stderr, "Fork failed: errno %d\n", errno);
+ failed_already=1;
+ return 1;
+ } else if (pid > 0) {
+ int childStatus;
+
+ printf("Fork succeeded. Parent process continues.\n");
+ DoIO();
+ if ((rv = waitpid(pid, &childStatus, 0)) != pid) {
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ /*
+ * nspr may handle SIGCLD signal
+ */
+ if ((rv < 0) && (errno == ECHILD)) {
+ } else
+#endif
+ {
+ fprintf(stderr, "waitpid failed: %d\n", errno);
+ failed_already = 1;
+ }
+ } else if (!WIFEXITED(childStatus)
+ || WEXITSTATUS(childStatus) != 0) {
+ failed_already = 1;
+ }
+ printf("Parent process exits.\n");
+ if (!failed_already) {
+ printf("PASSED\n");
+ } else {
+ printf("FAILED\n");
+ }
+ return failed_already;
+ } else {
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ extern void _PR_IRIX_CHILD_PROCESS(void);
+ _PR_IRIX_CHILD_PROCESS();
+#endif
+ printf("Fork succeeded. Child process continues.\n");
+ DoIO();
+ printf("Child process exits.\n");
+ return failed_already;
+ }
+}
+
+#else /* XP_UNIX */
+
+int main( int argc,
+char *argv[]
+)
+{
+
+ printf("The fork test is applicable to Unix only.\n");
+ return 0;
+
+}
+
+#endif /* XP_UNIX */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/formattm.c b/src/libs/xpcom18a4/nsprpub/pr/tests/formattm.c
new file mode 100644
index 00000000..c3c758b5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/formattm.c
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+/* A test program for PR_FormatTime and PR_FormatTimeUSEnglish */
+
+#include "prtime.h"
+
+#include <stdio.h>
+
+int main()
+{
+ char buffer[256];
+ PRTime now;
+ PRExplodedTime tod;
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_LocalTimeParameters, &tod);
+ (void)PR_FormatTime(buffer, sizeof(buffer),
+ "%a %b %d %H:%M:%S %Z %Y", &tod);
+ printf("%s\n", buffer);
+ (void)PR_FormatTimeUSEnglish(buffer, sizeof(buffer),
+ "%a %b %d %H:%M:%S %Z %Y", &tod);
+ printf("%s\n", buffer);
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/freeif.c b/src/libs/xpcom18a4/nsprpub/pr/tests/freeif.c
new file mode 100644
index 00000000..7aa16b49
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/freeif.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * A test to see if the macros PR_DELETE and PR_FREEIF are
+ * properly defined. (See Bugzilla bug #39110.)
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void Noop(void) { }
+
+static void Fail(void)
+{
+ printf("FAIL\n");
+ exit(1);
+}
+
+int main()
+{
+ int foo = 1;
+ char *ptr = NULL;
+
+ /* this fails to compile with the old definition of PR_DELETE */
+ if (foo)
+ PR_DELETE(ptr);
+ else
+ Noop();
+
+ /* this nests incorrectly with the old definition of PR_FREEIF */
+ if (foo)
+ PR_FREEIF(ptr);
+ else
+ Fail();
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/fsync.c b/src/libs/xpcom18a4/nsprpub/pr/tests/fsync.c
new file mode 100644
index 00000000..cea298b3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/fsync.c
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "prinrval.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+static PRFileDesc *err = NULL;
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: [-S] [-K <n>] [-h] <filename>\n");
+ PR_fprintf(err, "\t-c Nuber of iterations (default: 10)\n");
+ PR_fprintf(err, "\t-S Sync the file (default: FALSE)\n");
+ PR_fprintf(err, "\t-K Size of file (K bytes) (default: 10)\n");
+ PR_fprintf(err, "\t Name of file to write (default: /usr/tmp/sync.dat)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PLOptStatus os;
+ PRUint8 *buffer;
+ PRFileDesc *file = NULL;
+ const char *filename = "sync.dat";
+ PRUint32 index, loops, iterations = 10, filesize = 10;
+ PRIntn flags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hSK:c:");
+ PRIntervalTime time, total = 0, shortest = 0x7fffffff, longest = 0;
+
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* Name of file to create */
+ filename = opt->value;
+ break;
+ case 'S': /* Use sych option on file */
+ flags |= PR_SYNC;
+ break;
+ case 'K': /* Size of file to write */
+ filesize = atoi(opt->value);
+ break;
+ case 'c': /* Number of iterations */
+ iterations = atoi(opt->value);
+ break;
+ case 'h': /* user wants some guidance */
+ default: /* user needs some guidance */
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ file = PR_Open(filename, flags, 0666);
+ if (NULL == file)
+ {
+ PL_FPrintError(err, "Failed to open file");
+ return 1;
+ }
+
+ buffer = (PRUint8*)PR_CALLOC(1024);
+ if (NULL == buffer)
+ {
+ PL_FPrintError(err, "Cannot allocate buffer");
+ return 1;
+ }
+
+ for (index = 0; index < sizeof(buffer); ++index)
+ buffer[index] = (PRUint8)index;
+
+ for (loops = 0; loops < iterations; ++loops)
+ {
+ time = PR_IntervalNow();
+ for (index = 0; index < filesize; ++index)
+ {
+ PR_Write(file, buffer, 1024);
+ }
+ time = (PR_IntervalNow() - time);
+
+ total += time;
+ if (time < shortest) shortest = time;
+ else if (time > longest) longest = time;
+ if (0 != PR_Seek(file, 0, PR_SEEK_SET))
+ {
+ PL_FPrintError(err, "Rewinding file");
+ return 1;
+ }
+ }
+
+ total = total / iterations;
+ PR_fprintf(
+ err, "%u iterations over a %u kbyte %sfile: %u [%u] %u\n",
+ iterations, filesize, ((flags & PR_SYNC) ? "SYNCH'd " : ""),
+ PR_IntervalToMicroseconds(shortest),
+ PR_IntervalToMicroseconds(total),
+ PR_IntervalToMicroseconds(longest));
+
+ PR_DELETE(buffer);
+ rv = PR_Close(file);
+ if (PR_SUCCESS != rv)
+ {
+ PL_FPrintError(err, "Closing file failed");
+ return 1;
+ }
+ rv = PR_Delete(filename);
+ if (PR_SUCCESS != rv)
+ {
+ PL_FPrintError(err, "Deleting file failed");
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/getai.c b/src/libs/xpcom18a4/nsprpub/pr/tests/getai.c
new file mode 100644
index 00000000..bc4a59a7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/getai.c
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ PRAddrInfo *ai;
+ void *iter;
+ PRNetAddr addr;
+
+ ai = PR_GetAddrInfoByName(argv[1], PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
+ if (ai == NULL) {
+ fprintf(stderr, "PR_GetAddrInfoByName failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("%s\n", PR_GetCanonNameFromAddrInfo(ai));
+ iter = NULL;
+ while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) {
+ char buf[128];
+ PR_NetAddrToString(&addr, buf, sizeof buf);
+ printf("%s\n", buf);
+ }
+ PR_FreeAddrInfo(ai);
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/gethost.c b/src/libs/xpcom18a4/nsprpub/pr/tests/gethost.c
new file mode 100644
index 00000000..3af41a3f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/gethost.c
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: gethost.c
+ *
+ * Description: tests various functions in prnetdb.h
+ *
+ * Usage: gethost [-6] [hostname]
+ */
+
+#include "prio.h"
+#include "prnetdb.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define DEFAULT_HOST_NAME "mcom.com"
+
+static void Help(void)
+{
+ fprintf(stderr, "Usage: gethost [-h] [hostname]\n");
+ fprintf(stderr, "\t-h help\n");
+ fprintf(stderr, "\thostname Name of host (default: %s)\n",
+ DEFAULT_HOST_NAME);
+} /* Help */
+
+/*
+ * Prints the contents of a PRHostEnt structure
+ */
+void PrintHostent(const PRHostEnt *he)
+{
+ int i;
+ int j;
+
+ printf("h_name: %s\n", he->h_name);
+ for (i = 0; he->h_aliases[i]; i++) {
+ printf("h_aliases[%d]: %s\n", i, he->h_aliases[i]);
+ }
+ printf("h_addrtype: %d\n", he->h_addrtype);
+ printf("h_length: %d\n", he->h_length);
+ for (i = 0; he->h_addr_list[i]; i++) {
+ printf("h_addr_list[%d]: ", i);
+ for (j = 0; j < he->h_length; j++) {
+ if (j != 0) printf(".");
+ printf("%u", (unsigned char)he->h_addr_list[i][j]);
+ }
+ printf("\n");
+ }
+}
+
+int main(int argc, char **argv)
+{
+ const char *hostName = DEFAULT_HOST_NAME;
+ PRHostEnt he, reversehe;
+ char buf[PR_NETDB_BUF_SIZE];
+ char reversebuf[PR_NETDB_BUF_SIZE];
+ PRIntn idx;
+ PRNetAddr addr;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "h");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 0: /* naked */
+ hostName = opt->value;
+ break;
+ case 'h': /* Help message */
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (PR_GetHostByName(hostName, buf, sizeof(buf), &he) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetHostByName failed\n");
+ exit(1);
+ }
+ PrintHostent(&he);
+ idx = 0;
+ while (1) {
+ idx = PR_EnumerateHostEnt(idx, &he, 0, &addr);
+ if (idx == -1) {
+ fprintf(stderr, "PR_EnumerateHostEnt failed\n");
+ exit(1);
+ }
+ if (idx == 0) break; /* normal loop termination */
+ printf("reverse lookup\n");
+ if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf),
+ &reversehe) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetHostByAddr failed\n");
+ exit(1);
+ }
+ PrintHostent(&reversehe);
+ }
+
+ printf("PR_GetIPNodeByName with PR_AF_INET\n");
+ if (PR_GetIPNodeByName(hostName, PR_AF_INET, PR_AI_DEFAULT,
+ buf, sizeof(buf), &he) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetIPNodeByName failed\n");
+ exit(1);
+ }
+ PrintHostent(&he);
+ printf("PR_GetIPNodeByName with PR_AF_INET6\n");
+ if (PR_GetIPNodeByName(hostName, PR_AF_INET6, PR_AI_DEFAULT,
+ buf, sizeof(buf), &he) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetIPNodeByName failed\n");
+ exit(1);
+ }
+ PrintHostent(&he);
+ idx = 0;
+ printf("PR_GetHostByAddr with PR_AF_INET6\n");
+ while (1) {
+ idx = PR_EnumerateHostEnt(idx, &he, 0, &addr);
+ if (idx == -1) {
+ fprintf(stderr, "PR_EnumerateHostEnt failed\n");
+ exit(1);
+ }
+ if (idx == 0) break; /* normal loop termination */
+ printf("reverse lookup\n");
+ if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf),
+ &reversehe) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetHostByAddr failed\n");
+ exit(1);
+ }
+ PrintHostent(&reversehe);
+ }
+ printf("PR_GetHostByAddr with PR_AF_INET6 done\n");
+
+ PR_StringToNetAddr("::1", &addr);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_TRUE) {
+ fprintf(stderr, "addr should not be ipv4 mapped address\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+
+ PR_StringToNetAddr("127.0.0.1", &addr);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+ PR_StringToNetAddr("::FFFF:127.0.0.1", &addr);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_FALSE) {
+ fprintf(stderr, "addr should be ipv4 mapped address\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+
+ if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
+ fprintf(stderr, "addr should be unspecified address\n");
+ exit(1);
+ }
+ if (PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+
+ if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
+ fprintf(stderr, "addr should be unspecified address\n");
+ exit(1);
+ }
+ if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = 0;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
+ fprintf(stderr, "addr should be unspecified address\n");
+ exit(1);
+ }
+ {
+ char buf[256];
+ PR_NetAddrToString(&addr, buf, 256);
+ printf("IPv4 INADDRANY: %s\n", buf);
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = 0;
+ addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+ {
+ char buf[256];
+ PR_NetAddrToString(&addr, buf, 256);
+ printf("IPv4 LOOPBACK: %s\n", buf);
+ }
+
+ if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
+ fprintf(stderr, "addr should be unspecified address\n");
+ exit(1);
+ }
+ {
+ char buf[256];
+ PR_NetAddrToString(&addr, buf, 256);
+ printf("IPv6 INADDRANY: %s\n", buf);
+ }
+ if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+ fprintf(stderr, "addr should be loopback address\n");
+ exit(1);
+ }
+ {
+ char buf[256];
+ PR_NetAddrToString(&addr, buf, 256);
+ printf("IPv6 LOOPBACK: %s\n", buf);
+ }
+ {
+ PRIPv6Addr v6addr;
+ char tmp_buf[256];
+
+ PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr);
+
+ PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &v6addr);
+ PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr);
+ addr.ipv6.ip = v6addr;
+ PR_NetAddrToString(&addr, tmp_buf, 256);
+ printf("IPv4-mapped IPv6 LOOPBACK: %s\n", tmp_buf);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/getproto.c b/src/libs/xpcom18a4/nsprpub/pr/tests/getproto.c
new file mode 100644
index 00000000..7381bbd8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/getproto.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *************************************************************************
+ *
+ * File: getproto.c
+ *
+ * A test program for PR_GetProtoByName and PR_GetProtoByNumber
+ *
+ *************************************************************************
+ */
+
+#include "plstr.h"
+#include "plerror.h"
+#include "prinit.h"
+#include "prprf.h"
+#include "prnetdb.h"
+#include "prerror.h"
+
+int main()
+{
+ PRFileDesc *prstderr = PR_GetSpecialFD(PR_StandardError);
+ PRBool failed = PR_FALSE;
+ PRProtoEnt proto;
+ char buf[2048];
+ PRStatus rv;
+
+ PR_STDIO_INIT();
+ rv = PR_GetProtoByName("tcp", buf, sizeof(buf), &proto);
+ if (PR_FAILURE == rv) {
+ failed = PR_TRUE;
+ PL_FPrintError(prstderr, "PR_GetProtoByName failed");
+ }
+ else if (6 != proto.p_num) {
+ PR_fprintf(
+ prstderr,"tcp is usually 6, but is %d on this machine\n",
+ proto.p_num);
+ }
+ else PR_fprintf(prstderr, "tcp is protocol number %d\n", proto.p_num);
+
+ rv = PR_GetProtoByName("udp", buf, sizeof(buf), &proto);
+ if (PR_FAILURE == rv) {
+ failed = PR_TRUE;
+ PL_FPrintError(prstderr, "PR_GetProtoByName failed");
+ }
+ else if (17 != proto.p_num) {
+ PR_fprintf(
+ prstderr, "udp is usually 17, but is %d on this machine\n",
+ proto.p_num);
+ }
+ else PR_fprintf(prstderr, "udp is protocol number %d\n", proto.p_num);
+
+ rv = PR_GetProtoByNumber(6, buf, sizeof(buf), &proto);
+ if (PR_FAILURE == rv) {
+ failed = PR_TRUE;
+ PL_FPrintError(prstderr, "PR_GetProtoByNumber failed");
+ }
+ else if (PL_strcmp("tcp", proto.p_name)) {
+ PR_fprintf(
+ prstderr, "Protocol number 6 is usually tcp, but is %s"
+ " on this platform\n", proto.p_name);
+ }
+ else PR_fprintf(prstderr, "Protocol number 6 is %s\n", proto.p_name);
+
+ rv = PR_GetProtoByNumber(17, buf, sizeof(buf), &proto);
+ if (PR_FAILURE == rv) {
+ failed = PR_TRUE;
+ PL_FPrintError(prstderr, "PR_GetProtoByNumber failed");
+ }
+ else if (PL_strcmp("udp", proto.p_name)) {
+ PR_fprintf(
+ prstderr, "Protocol number 17 is usually udp, but is %s"
+ " on this platform\n", proto.p_name);
+ }
+ else PR_fprintf(prstderr, "Protocol number 17 is %s\n", proto.p_name);
+
+ PR_fprintf(prstderr, (failed) ? "FAILED\n" : "PASSED\n");
+ return (failed) ? 1 : 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/i2l.c b/src/libs/xpcom18a4/nsprpub/pr/tests/i2l.c
new file mode 100644
index 00000000..4ff67bc0
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/i2l.c
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <stdlib.h>
+
+#include "prio.h"
+#include "prinit.h"
+#include "prprf.h"
+#include "prlong.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+typedef union Overlay_i
+{
+ PRInt32 i;
+ PRInt64 l;
+} Overlay_i;
+
+typedef union Overlay_u
+{
+ PRUint32 i;
+ PRUint64 l;
+} Overlay_u;
+
+static PRFileDesc *err = NULL;
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: -i n | -u n | -h\n");
+ PR_fprintf(err, "\t-i n treat following number as signed integer\n");
+ PR_fprintf(err, "\t-u n treat following number as unsigned integer\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+static PRIntn PR_CALLBACK RealMain(PRIntn argc, char **argv)
+{
+ Overlay_i si;
+ Overlay_u ui;
+ PLOptStatus os;
+ PRBool bsi = PR_FALSE, bui = PR_FALSE;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hi:u:");
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'i': /* signed integer */
+ si.i = (PRInt32)atoi(opt->value);
+ bsi = PR_TRUE;
+ break;
+ case 'u': /* unsigned */
+ ui.i = (PRUint32)atoi(opt->value);
+ bui = PR_TRUE;
+ break;
+ case 'h': /* user wants some guidance */
+ default:
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#if defined(HAVE_LONG_LONG)
+ PR_fprintf(err, "We have long long\n");
+#else
+ PR_fprintf(err, "We don't have long long\n");
+#endif
+
+ if (bsi)
+ {
+ PR_fprintf(err, "Converting %ld: ", si.i);
+ LL_I2L(si.l, si.i);
+ PR_fprintf(err, "%lld\n", si.l);
+ }
+
+ if (bui)
+ {
+ PR_fprintf(err, "Converting %lu: ", ui.i);
+ LL_I2L(ui.l, ui.i);
+ PR_fprintf(err, "%llu\n", ui.l);
+ }
+ return 0;
+
+} /* main */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
+
+/* i2l.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/initclk.c b/src/libs/xpcom18a4/nsprpub/pr/tests/initclk.c
new file mode 100644
index 00000000..ba306d20
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/initclk.c
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This is a regression test for the bug that the interval timer
+ * is not initialized when _PR_CreateCPU calls PR_IntervalNow.
+ * The bug would make this test program finish prematurely,
+ * when the SHORT_TIMEOUT period expires. The correct behavior
+ * is for the test to finish when the LONG_TIMEOUT period expires.
+ */
+
+#include "prlock.h"
+#include "prcvar.h"
+#include "prthread.h"
+#include "prinrval.h"
+#include "prlog.h"
+#include <stdio.h>
+
+/* The timeouts, in milliseconds */
+#define SHORT_TIMEOUT 1000
+#define LONG_TIMEOUT 3000
+
+PRLock *lock1, *lock2;
+PRCondVar *cv1, *cv2;
+
+void ThreadFunc(void *arg)
+{
+ PR_Lock(lock1);
+ PR_WaitCondVar(cv1, PR_MillisecondsToInterval(SHORT_TIMEOUT));
+ PR_Unlock(lock1);
+}
+
+int main()
+{
+ PRThread *thread;
+ PRIntervalTime start, end;
+ PRUint32 elapsed_ms;
+
+ lock1 = PR_NewLock();
+ PR_ASSERT(NULL != lock1);
+ cv1 = PR_NewCondVar(lock1);
+ PR_ASSERT(NULL != cv1);
+ lock2 = PR_NewLock();
+ PR_ASSERT(NULL != lock2);
+ cv2 = PR_NewCondVar(lock2);
+ PR_ASSERT(NULL != cv2);
+ start = PR_IntervalNow();
+ thread = PR_CreateThread(
+ PR_USER_THREAD,
+ ThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ PR_ASSERT(NULL != thread);
+ PR_Lock(lock2);
+ PR_WaitCondVar(cv2, PR_MillisecondsToInterval(LONG_TIMEOUT));
+ PR_Unlock(lock2);
+ PR_JoinThread(thread);
+ end = PR_IntervalNow();
+ elapsed_ms = PR_IntervalToMilliseconds((PRIntervalTime)(end - start));
+ /* Allow 100ms imprecision */
+ if (elapsed_ms < LONG_TIMEOUT - 100 || elapsed_ms > LONG_TIMEOUT + 100) {
+ printf("Elapsed time should be %u ms but is %u ms\n",
+ LONG_TIMEOUT, elapsed_ms);
+ printf("FAIL\n");
+ exit(1);
+ }
+ printf("Elapsed time: %u ms, expected time: %u ms\n",
+ LONG_TIMEOUT, elapsed_ms);
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/inrval.c b/src/libs/xpcom18a4/nsprpub/pr/tests/inrval.c
new file mode 100644
index 00000000..b057c685
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/inrval.c
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** file: inrval.c
+** description: Interval conversion test.
+** Modification History:
+** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+**/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#ifdef XP_MAC
+#include "pralarm.h"
+#else
+#include "obsolete/pralarm.h"
+#endif
+
+#include "prio.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "prlong.h"
+#include "prcvar.h"
+#include "prinrval.h"
+#include "prtime.h"
+
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static PRIntn debug_mode;
+static PRFileDesc *output;
+
+
+static void TestConversions(void)
+{
+ PRIntervalTime ticks = PR_TicksPerSecond();
+
+ if (debug_mode) {
+ PR_fprintf(output, "PR_TicksPerSecond: %ld\n\n", ticks);
+ PR_fprintf(output, "PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1));
+ PR_fprintf(output, "PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000));
+ PR_fprintf(output, "PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000));
+
+ PR_fprintf(output, "PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3));
+ PR_fprintf(output, "PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000));
+ PR_fprintf(output, "PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000));
+
+ PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
+
+ ticks *= 3;
+ PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks));
+ PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks));
+ } /*end debug mode */
+} /* TestConversions */
+
+static void TestIntervalOverhead(void)
+{
+ /* Hopefully the optimizer won't delete this function */
+ PRUint32 elapsed, per_call, loops = 1000000;
+
+ PRIntervalTime timeout, timein = PR_IntervalNow();
+ while (--loops > 0)
+ timeout = PR_IntervalNow();
+
+ elapsed = 1000U * PR_IntervalToMicroseconds(timeout - timein);
+ per_call = elapsed / 1000000U;
+ PR_fprintf(
+ output, "Overhead of 'PR_IntervalNow()' is %u nsecs\n\n", per_call);
+} /* TestIntervalOverhead */
+
+static void TestNowOverhead(void)
+{
+ PRTime timeout, timein;
+ PRInt32 overhead, loops = 1000000;
+ PRInt64 elapsed, per_call, ten23rd, ten26th;
+
+ LL_I2L(ten23rd, 1000);
+ LL_I2L(ten26th, 1000000);
+
+ timein = PR_Now();
+ while (--loops > 0)
+ timeout = PR_Now();
+
+ LL_SUB(elapsed, timeout, timein);
+ LL_MUL(elapsed, elapsed, ten23rd);
+ LL_DIV(per_call, elapsed, ten26th);
+ LL_L2I(overhead, per_call);
+ PR_fprintf(
+ output, "Overhead of 'PR_Now()' is %u nsecs\n\n", overhead);
+} /* TestNowOverhead */
+
+static void TestIntervals(void)
+{
+ PRStatus rv;
+ PRUint32 delta;
+ PRInt32 seconds;
+ PRUint64 elapsed, thousand;
+ PRTime timein, timeout;
+ PRLock *ml = PR_NewLock();
+ PRCondVar *cv = PR_NewCondVar(ml);
+ for (seconds = 0; seconds < 10; ++seconds)
+ {
+ PRIntervalTime ticks = PR_SecondsToInterval(seconds);
+ PR_Lock(ml);
+ timein = PR_Now();
+ rv = PR_WaitCondVar(cv, ticks);
+ timeout = PR_Now();
+ PR_Unlock(ml);
+ LL_SUB(elapsed, timeout, timein);
+ LL_I2L(thousand, 1000);
+ LL_DIV(elapsed, elapsed, thousand);
+ LL_L2UI(delta, elapsed);
+ if (debug_mode) PR_fprintf(output,
+ "TestIntervals: %swaiting %ld seconds took %ld msecs\n",
+ ((rv == PR_SUCCESS) ? "" : "FAILED "), seconds, delta);
+ }
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+ if (debug_mode) PR_fprintf(output, "\n");
+} /* TestIntervals */
+
+static PRIntn PR_CALLBACK RealMain(int argc, char** argv)
+{
+ PRUint32 vcpu, cpus = 0, loops = 1000;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+
+ /* main test */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dl:c:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'c': /* concurrency counter */
+ cpus = atoi(opt->value);
+ break;
+ case 'l': /* loop counter */
+ loops = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ PR_fprintf(output, "inrval: Examine stdout to determine results.\n");
+
+ if (cpus == 0) cpus = 8;
+ if (loops == 0) loops = 1000;
+
+ if (debug_mode > 0)
+ {
+ PR_fprintf(output, "Inrval: Using %d loops\n", loops);
+ PR_fprintf(output, "Inrval: Using 1 and %d cpu(s)\n", cpus);
+ }
+
+ for (vcpu = 1; vcpu <= cpus; vcpu += cpus - 1)
+ {
+ if (debug_mode)
+ PR_fprintf(output, "\nInrval: Using %d CPU(s)\n\n", vcpu);
+ PR_SetConcurrency(vcpu);
+
+ TestNowOverhead();
+ TestIntervalOverhead();
+ TestConversions();
+ TestIntervals();
+ }
+
+ return 0;
+}
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/instrumt.c b/src/libs/xpcom18a4/nsprpub/pr/tests/instrumt.c
new file mode 100644
index 00000000..f1577609
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/instrumt.c
@@ -0,0 +1,507 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: instrumt.c
+** Description: This test is for the NSPR debug aids defined in
+** prcountr.h, prtrace.h, prolock.h
+**
+** The test case tests the three debug aids in NSPR:
+**
+** Diagnostic messages can be enabled using "instrumt -v 6"
+** This sets the msgLevel to something that PR_LOG() likes.
+** Also define in the environment "NSPR_LOG_MODULES=Test:6"
+**
+** CounterTest() tests the counter facility. This test
+** creates 4 threads. Each thread either increments, decrements,
+** adds to or subtracts from a counter, depending on an argument
+** passed to the thread at thread-create time. Each of these threads
+** does COUNT_LIMIT iterations doing its thing. When all 4 threads
+** are done, the result of the counter is evaluated. If all was atomic,
+** the the value of the counter should be zero.
+**
+** TraceTest():
+** This test mingles with the counter test. Counters trace.
+** A thread to extract trace entries on the fly is started.
+** A thread to dump trace entries to a file is started.
+**
+** OrderedLockTest():
+**
+**
+**
+**
+**
+*/
+
+#include <stdio.h>
+#include <plstr.h>
+#include <prclist.h>
+#include <prmem.h>
+#include <plgetopt.h>
+#include <prlog.h>
+#include <prmon.h>
+#include <pratom.h>
+#include <prtrace.h>
+#include <prcountr.h>
+#include <prolock.h>
+
+#define COUNT_LIMIT (10 * ( 1024))
+
+#define SMALL_TRACE_BUFSIZE ( 60 * 1024 )
+
+typedef enum
+{
+ CountLoop = 1,
+ TraceLoop = 2,
+ TraceFlow = 3
+} TraceTypes;
+
+
+PRLogModuleLevel msgLevel = PR_LOG_ALWAYS;
+
+PRBool help = PR_FALSE;
+PRBool failed = PR_FALSE;
+
+
+PRLogModuleInfo *lm;
+PRMonitor *mon;
+PRInt32 activeThreads = 0;
+PR_DEFINE_COUNTER( hCounter );
+PR_DEFINE_TRACE( hTrace );
+
+static void Help(void)
+{
+ printf("Help? ... Ha!\n");
+}
+
+static void ListCounters(void)
+{
+ PR_DEFINE_COUNTER( qh );
+ PR_DEFINE_COUNTER( rh );
+ const char *qn, *rn, *dn;
+ const char **qname = &qn, **rname = &rn, **desc = &dn;
+ PRUint32 tCtr;
+
+ PR_INIT_COUNTER_HANDLE( qh, NULL );
+ PR_FIND_NEXT_COUNTER_QNAME(qh, qh );
+ while ( qh != NULL )
+ {
+ PR_INIT_COUNTER_HANDLE( rh, NULL );
+ PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
+ while ( rh != NULL )
+ {
+ PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc );
+ tCtr = PR_GET_COUNTER(tCtr, rh);
+ PR_LOG( lm, msgLevel,
+ ( "QName: %s RName: %s Desc: %s Value: %ld\n",
+ qn, rn, dn, tCtr ));
+ PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh );
+ }
+ PR_FIND_NEXT_COUNTER_QNAME(qh, qh);
+ }
+ return;
+} /* end ListCounters() */
+
+static void ListTraces(void)
+{
+ PR_DEFINE_TRACE( qh );
+ PR_DEFINE_TRACE( rh );
+ const char *qn, *rn, *dn;
+ const char **qname = &qn, **rname = &rn, **desc = &dn;
+
+ PR_INIT_TRACE_HANDLE( qh, NULL );
+ PR_FIND_NEXT_TRACE_QNAME(qh, qh );
+ while ( qh != NULL )
+ {
+ PR_INIT_TRACE_HANDLE( rh, NULL );
+ PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
+ while ( rh != NULL )
+ {
+ PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc );
+ PR_LOG( lm, msgLevel,
+ ( "QName: %s RName: %s Desc: %s",
+ qn, rn, dn ));
+ PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh );
+ }
+ PR_FIND_NEXT_TRACE_QNAME(qh, qh);
+ }
+ return;
+} /* end ListCounters() */
+
+
+static PRInt32 one = 1;
+static PRInt32 two = 2;
+static PRInt32 three = 3;
+static PRInt32 four = 4;
+
+/*
+** Thread to iteratively count something.
+*/
+static void PR_CALLBACK CountSomething( void *arg )
+{
+ PRInt32 switchVar = *((PRInt32 *)arg);
+ PRInt32 i;
+
+ PR_LOG( lm, msgLevel,
+ ("CountSomething: begin thread %ld", switchVar ));
+
+ for ( i = 0; i < COUNT_LIMIT ; i++)
+ {
+ switch ( switchVar )
+ {
+ case 1 :
+ PR_INCREMENT_COUNTER( hCounter );
+ break;
+ case 2 :
+ PR_DECREMENT_COUNTER( hCounter );
+ break;
+ case 3 :
+ PR_ADD_TO_COUNTER( hCounter, 1 );
+ break;
+ case 4 :
+ PR_SUBTRACT_FROM_COUNTER( hCounter, 1 );
+ break;
+ default :
+ PR_ASSERT( 0 );
+ break;
+ }
+ PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 );
+ } /* end for() */
+
+ PR_LOG( lm, msgLevel,
+ ("CounterSomething: end thread %ld", switchVar ));
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ return;
+} /* end CountSomething() */
+
+/*
+** Create the counter threads.
+*/
+static void CounterTest( void )
+{
+ PRThread *t1, *t2, *t3, *t4;
+ PRIntn i = 0;
+ PR_DEFINE_COUNTER( tc );
+ PR_DEFINE_COUNTER( zCounter );
+
+ PR_LOG( lm, msgLevel,
+ ("Begin CounterTest"));
+
+ /*
+ ** Test Get and Set of a counter.
+ **
+ */
+ PR_CREATE_COUNTER( zCounter, "Atomic", "get/set test", "test get and set of counter" );
+ PR_SET_COUNTER( zCounter, 9 );
+ PR_GET_COUNTER( i, zCounter );
+ if ( i != 9 )
+ {
+ failed = PR_TRUE;
+ PR_LOG( lm, msgLevel,
+ ("Counter set/get failed"));
+ }
+
+ activeThreads += 4;
+ PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" );
+
+ PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" );
+ PR_ASSERT( tc == hCounter );
+
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &one,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &two,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ t3 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &three,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t3);
+
+ t4 = PR_CreateThread(PR_USER_THREAD,
+ CountSomething, &four,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t4);
+
+ PR_LOG( lm, msgLevel,
+ ("Counter Threads started"));
+
+ ListCounters();
+ return;
+} /* end CounterTest() */
+
+/*
+** Thread to dump trace buffer to a file.
+*/
+static void PR_CALLBACK RecordTrace(void *arg )
+{
+ PR_RECORD_TRACE_ENTRIES();
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ return;
+} /* end RecordTrace() */
+
+
+
+#define NUM_TRACE_RECORDS ( 10000 )
+/*
+** Thread to extract and print trace entries from the buffer.
+*/
+static void PR_CALLBACK SampleTrace( void *arg )
+{
+#if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
+ PRInt32 found, rc;
+ PRTraceEntry *foundEntries;
+ PRInt32 i;
+
+ foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry));
+ PR_ASSERT(foundEntries != NULL );
+
+ do
+ {
+ rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found);
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace: Lost Data: %ld found: %ld", rc, found ));
+
+ if ( found != 0)
+ {
+ for ( i = 0 ; i < found; i++ )
+ {
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld",
+ (foundEntries +i)->thread,
+ (foundEntries +i)->time,
+ (foundEntries +i)->userData[0],
+ (foundEntries +i)->userData[1],
+ (foundEntries +i)->userData[2] ));
+ }
+ }
+ PR_Sleep(PR_MillisecondsToInterval(50));
+ }
+ while( found != 0 && activeThreads >= 1 );
+
+ PR_Free( foundEntries );
+
+ PR_EnterMonitor(mon);
+ --activeThreads;
+ PR_Notify( mon );
+ PR_ExitMonitor(mon);
+
+ PR_LOG( lm, msgLevel,
+ ("SampleTrace(): exiting"));
+
+#endif
+ return;
+} /* end RecordTrace() */
+
+/*
+** Basic trace test.
+*/
+static void TraceTest( void )
+{
+ PRInt32 i;
+ PRInt32 size;
+ PR_DEFINE_TRACE( th );
+ PRThread *t1, *t2;
+
+ PR_LOG( lm, msgLevel,
+ ("Begin TraceTest"));
+
+ size = SMALL_TRACE_BUFSIZE;
+ PR_SET_TRACE_OPTION( PRTraceBufSize, &size );
+ PR_GET_TRACE_OPTION( PRTraceBufSize, &i );
+
+ PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" );
+ PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" );
+
+ PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" );
+ PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" );
+
+
+
+ activeThreads += 2;
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ RecordTrace, NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t1);
+
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ SampleTrace, 0,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ PR_ASSERT(t2);
+
+ ListTraces();
+
+ PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" );
+ PR_ASSERT( th == hTrace );
+
+ PR_LOG( lm, msgLevel,
+ ("End TraceTest"));
+ return;
+} /* end TraceTest() */
+
+
+/*
+** Ordered lock test.
+*/
+static void OrderedLockTest( void )
+{
+ PR_LOG( lm, msgLevel,
+ ("Begin OrderedLockTest"));
+
+
+} /* end OrderedLockTest() */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+#if defined(DEBUG) || defined(FORCE_NSPR_TRACE)
+ PRUint32 counter;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:");
+ lm = PR_NewLogModule("Test");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* verbose mode */
+ msgLevel = (PRLogModuleLevel)atol( opt->value);
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" );
+ mon = PR_NewMonitor();
+ PR_EnterMonitor( mon );
+
+ TraceTest();
+ CounterTest();
+ OrderedLockTest();
+
+ /* Wait for all threads to exit */
+ while ( activeThreads > 0 ) {
+ if ( activeThreads == 1 )
+ PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL );
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ PR_GET_COUNTER( counter, hCounter );
+ }
+ PR_ExitMonitor( mon );
+
+ /*
+ ** Evaluate results
+ */
+ PR_GET_COUNTER( counter, hCounter );
+ if ( counter != 0 )
+ {
+ failed = PR_TRUE;
+ PR_LOG( lm, msgLevel,
+ ("Expected counter == 0, found: %ld", counter));
+ printf("FAIL\n");
+ }
+ else
+ {
+ printf("PASS\n");
+ }
+
+
+ PR_DESTROY_COUNTER( hCounter );
+
+ PR_DestroyMonitor( mon );
+
+ PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0);
+ PR_DESTROY_TRACE( hTrace );
+#else
+ printf("Test not defined\n");
+#endif
+ return 0;
+} /* main() */
+/* end instrumt.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/intrio.c b/src/libs/xpcom18a4/nsprpub/pr/tests/intrio.c
new file mode 100644
index 00000000..e1dcf661
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/intrio.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * File: intrio.c
+ * Purpose: testing i/o interrupts (see Bugzilla bug #31120)
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+/* for synchronization between the main thread and iothread */
+static PRLock *lock;
+static PRCondVar *cvar;
+static PRBool iothread_ready;
+
+static void PR_CALLBACK AbortIO(void *arg)
+{
+ PRStatus rv;
+ PR_Sleep(PR_SecondsToInterval(2));
+ rv = PR_Interrupt((PRThread*)arg);
+ PR_ASSERT(PR_SUCCESS == rv);
+} /* AbortIO */
+
+static void PR_CALLBACK IOThread(void *arg)
+{
+ PRFileDesc *sock, *newsock;
+ PRNetAddr addr;
+
+ sock = PR_OpenTCPSocket(PR_AF_INET6);
+ if (sock == NULL) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Bind(sock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_Listen(sock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+ /* tell the main thread that we are ready */
+ PR_Lock(lock);
+ iothread_ready = PR_TRUE;
+ PR_NotifyCondVar(cvar);
+ PR_Unlock(lock);
+ newsock = PR_Accept(sock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (newsock != NULL) {
+ fprintf(stderr, "PR_Accept shouldn't have succeeded\n");
+ exit(1);
+ }
+ if (PR_GetError() != PR_PENDING_INTERRUPT_ERROR) {
+ fprintf(stderr, "PR_Accept failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("PR_Accept() is interrupted as expected\n");
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+static void Test(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *iothread, *abortio;
+
+ printf("A %s thread will be interrupted by a %s thread\n",
+ (scope1 == PR_LOCAL_THREAD ? "local" : "global"),
+ (scope2 == PR_LOCAL_THREAD ? "local" : "global"));
+ iothread_ready = PR_FALSE;
+ iothread = PR_CreateThread(
+ PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL,
+ scope1, PR_JOINABLE_THREAD, 0);
+ if (iothread == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+ PR_Lock(lock);
+ while (!iothread_ready)
+ PR_WaitCondVar(cvar, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(lock);
+ abortio = PR_CreateThread(
+ PR_USER_THREAD, AbortIO, iothread, PR_PRIORITY_NORMAL,
+ scope2, PR_JOINABLE_THREAD, 0);
+ if (abortio == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+ if (PR_JoinThread(iothread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(abortio) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+}
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PR_STDIO_INIT();
+ lock = PR_NewLock();
+ if (lock == NULL) {
+ fprintf(stderr, "PR_NewLock failed\n");
+ exit(1);
+ }
+ cvar = PR_NewCondVar(lock);
+ if (cvar == NULL) {
+ fprintf(stderr, "PR_NewCondVar failed\n");
+ exit(1);
+ }
+ /* test all four combinations */
+ Test(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+ Test(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+ Test(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+ Test(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+ printf("PASSED\n");
+ return 0;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/intrupt.c b/src/libs/xpcom18a4/nsprpub/pr/tests/intrupt.c
new file mode 100644
index 00000000..f6f38105
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/intrupt.c
@@ -0,0 +1,373 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: intrupt.c
+ * Purpose: testing thread interrupts
+ */
+
+#include "plgetopt.h"
+#include "prcvar.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prthread.h"
+#include "prtypes.h"
+#include "prnetdb.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+#define DEFAULT_TCP_PORT 12500
+
+static PRLock *ml = NULL;
+static PRCondVar *cv = NULL;
+
+static PRBool passed = PR_TRUE;
+static PRBool debug_mode = PR_FALSE;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+static void PR_CALLBACK AbortCV(void *arg)
+{
+ PRStatus rv;
+ PRThread *me = PR_CurrentThread();
+
+ /* some other thread (main) is doing the interrupt */
+ PR_Lock(ml);
+ rv = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+ if (debug_mode) printf( "Expected interrupt on wait CV and ");
+ if (PR_FAILURE == rv)
+ {
+ if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
+ {
+ if (debug_mode) printf("got it\n");
+ }
+ else
+ {
+ if (debug_mode) printf("got random error\n");
+ passed = PR_FALSE;
+ }
+ }
+ else
+ {
+ if (debug_mode) printf("got a successful completion\n");
+ passed = PR_FALSE;
+ }
+
+ rv = PR_WaitCondVar(cv, 10);
+ if (debug_mode)
+ {
+ printf(
+ "Expected success on wait CV and %s\n",
+ (PR_SUCCESS == rv) ? "got it" : "failed");
+ }
+ passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
+
+ /* interrupt myself, then clear */
+ PR_Interrupt(me);
+ PR_ClearInterrupt();
+ rv = PR_WaitCondVar(cv, 10);
+ if (debug_mode)
+ {
+ printf("Expected success on wait CV and ");
+ if (PR_FAILURE == rv)
+ {
+ printf(
+ "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
+ "got interrupted" : "a random failure");
+ }
+ printf("got it\n");
+ }
+ passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
+
+ /* set, then wait - interrupt - then wait again */
+ PR_Interrupt(me);
+ rv = PR_WaitCondVar(cv, 10);
+ if (debug_mode) printf( "Expected interrupt on wait CV and ");
+ if (PR_FAILURE == rv)
+ {
+ if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
+ {
+ if (debug_mode) printf("got it\n");
+ }
+ else
+ {
+ if (debug_mode) printf("failed\n");
+ passed = PR_FALSE;
+ }
+ }
+ else
+ {
+ if (debug_mode) printf("got a successful completion\n");
+ passed = PR_FALSE;
+ }
+
+ rv = PR_WaitCondVar(cv, 10);
+ if (debug_mode)
+ {
+ printf(
+ "Expected success on wait CV and %s\n",
+ (PR_SUCCESS == rv) ? "got it" : "failed");
+ }
+ passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
+
+ PR_Unlock(ml);
+
+} /* AbortCV */
+
+static void PR_CALLBACK AbortIO(void *arg)
+{
+ PRStatus rv;
+ PR_Sleep(PR_SecondsToInterval(2));
+ rv = PR_Interrupt((PRThread*)arg);
+ PR_ASSERT(PR_SUCCESS == rv);
+} /* AbortIO */
+
+static void PR_CALLBACK AbortJoin(void *arg)
+{
+} /* AbortJoin */
+
+static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr)
+{
+ PRStatus rv;
+ PRInt16 port = DEFAULT_TCP_PORT;
+
+ *listner = PR_NewTCPSocket();
+ PR_ASSERT(*listner != NULL);
+ memset(netaddr, 0, sizeof(*netaddr));
+ (*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY);
+ (*netaddr).inet.family = PR_AF_INET;
+ do
+ {
+ (*netaddr).inet.port = PR_htons(port);
+ rv = PR_Bind(*listner, netaddr);
+ port += 1;
+ PR_ASSERT(port < (DEFAULT_TCP_PORT + 10));
+ } while (PR_FAILURE == rv);
+
+ rv = PR_Listen(*listner, 5);
+
+ if (PR_GetSockName(*listner, netaddr) < 0) {
+ if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n");
+ passed = PR_FALSE;
+ return;
+ }
+
+}
+
+static void PR_CALLBACK IntrBlock(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr netaddr;
+ PRFileDesc *listner;
+
+ /* some other thread (main) is doing the interrupt */
+ /* block the interrupt */
+ PR_BlockInterrupt();
+ PR_Lock(ml);
+ rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4));
+ PR_Unlock(ml);
+ if (debug_mode)
+ {
+ printf("Expected success on wait CV and ");
+ if (PR_FAILURE == rv)
+ {
+ printf(
+ "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
+ "got interrupted" : "got a random failure");
+ } else
+ printf("got it\n");
+ }
+ passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
+
+ setup_listen_socket(&listner, &netaddr);
+ PR_UnblockInterrupt();
+ if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
+ {
+ PRInt32 error = PR_GetError();
+ if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
+ if (PR_PENDING_INTERRUPT_ERROR == error)
+ {
+ if (debug_mode) printf("got it\n");
+ }
+ else
+ {
+ if (debug_mode) printf("failed\n");
+ passed = PR_FALSE;
+ }
+ }
+ else
+ {
+ if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
+ passed = PR_FALSE;
+ }
+
+ (void)PR_Close(listner); listner = NULL;
+} /* TestIntrBlock */
+
+void PR_CALLBACK Intrupt(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr netaddr;
+ PRFileDesc *listner;
+ PRThread *abortCV, *abortIO, *abortJoin, *intrBlock;
+
+ ml = PR_NewLock();
+ cv = PR_NewCondVar(ml);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("intrupt.log");
+ debug_mode = PR_TRUE;
+#endif
+
+ /* Part I */
+ if (debug_mode) printf("Part I\n");
+ abortCV = PR_CreateThread(
+ PR_USER_THREAD, AbortCV, 0, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+
+ PR_Sleep(PR_SecondsToInterval(2));
+ rv = PR_Interrupt(abortCV);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(abortCV);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ /* Part II */
+ if (debug_mode) printf("Part II\n");
+ abortJoin = PR_CreateThread(
+ PR_USER_THREAD, AbortJoin, 0, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ PR_Sleep(PR_SecondsToInterval(2));
+ if (debug_mode) printf("Expecting to interrupt an exited thread ");
+ rv = PR_Interrupt(abortJoin);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(abortJoin);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if (debug_mode) printf("and succeeded\n");
+
+ /* Part III */
+ if (debug_mode) printf("Part III\n");
+ setup_listen_socket(&listner, &netaddr);
+ abortIO = PR_CreateThread(
+ PR_USER_THREAD, AbortIO, PR_CurrentThread(), PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+
+ if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
+ {
+ PRInt32 error = PR_GetError();
+ if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
+ if (PR_PENDING_INTERRUPT_ERROR == error)
+ {
+ if (debug_mode) printf("got it\n");
+ }
+ else
+ {
+ if (debug_mode) printf("failed\n");
+ passed = PR_FALSE;
+ }
+ }
+ else
+ {
+ if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
+ passed = PR_FALSE;
+ }
+
+ (void)PR_Close(listner); listner = NULL;
+
+ rv = PR_JoinThread(abortIO);
+ PR_ASSERT(PR_SUCCESS == rv);
+ /* Part VI */
+ if (debug_mode) printf("Part VI\n");
+ intrBlock = PR_CreateThread(
+ PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+
+ PR_Sleep(PR_SecondsToInterval(2));
+ rv = PR_Interrupt(intrBlock);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(intrBlock);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+} /* Intrupt */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRThread *intrupt;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dG");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ PR_STDIO_INIT();
+ intrupt = PR_CreateThread(
+ PR_USER_THREAD, Intrupt, NULL, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ if (intrupt == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ passed = PR_FALSE;
+ } else {
+ PRStatus rv;
+ rv = PR_JoinThread(intrupt);
+ PR_ASSERT(rv == PR_SUCCESS);
+ }
+ printf("%s\n", ((passed) ? "PASSED" : "FAILED"));
+ return ((passed) ? 0 : 1);
+} /* main */
+
+/* intrupt.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeout.c b/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeout.c
new file mode 100644
index 00000000..2a680aa5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeout.c
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** Test socket IO timeouts
+**
+**
+**
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include "nspr.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+#define NUM_THREADS 1
+#define BASE_PORT 8000
+#define DEFAULT_ACCEPT_TIMEOUT 2
+
+typedef struct threadInfo {
+ PRInt16 id;
+ PRInt16 accept_timeout;
+ PRLock *dead_lock;
+ PRCondVar *dead_cv;
+ PRInt32 *alive;
+} threadInfo;
+
+PRIntn failed_already = 0;
+PRIntn debug_mode = 0;
+
+#define LOCAL_SCOPE_STRING "LOCAL scope"
+#define GLOBAL_SCOPE_STRING "GLOBAL scope"
+#define GLOBAL_BOUND_SCOPE_STRING "GLOBAL_BOUND scope"
+
+void
+thread_main(void *_info)
+{
+ threadInfo *info = (threadInfo *)_info;
+ PRNetAddr listenAddr;
+ PRNetAddr clientAddr;
+ PRFileDesc *listenSock = NULL;
+ PRFileDesc *clientSock;
+ PRStatus rv;
+ PRThreadScope tscope;
+ char *scope_str;
+
+
+ if (debug_mode)
+ printf("thread %d is alive\n", info->id);
+ tscope = PR_GetThreadScope(PR_GetCurrentThread());
+
+ switch(tscope) {
+ case PR_LOCAL_THREAD:
+ scope_str = LOCAL_SCOPE_STRING;
+ break;
+ case PR_GLOBAL_THREAD:
+ scope_str = GLOBAL_SCOPE_STRING;
+ break;
+ case PR_GLOBAL_BOUND_THREAD:
+ scope_str = GLOBAL_BOUND_SCOPE_STRING;
+ break;
+ default:
+ PR_ASSERT(!"Invalid thread scope");
+ break;
+ }
+ printf("thread id %d, scope %s\n", info->id, scope_str);
+
+ listenSock = PR_NewTCPSocket();
+ if (!listenSock) {
+ if (debug_mode)
+ printf("unable to create listen socket\n");
+ failed_already=1;
+ goto dead;
+ }
+
+ listenAddr.inet.family = PR_AF_INET;
+ listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
+ listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ rv = PR_Bind(listenSock, &listenAddr);
+ if (rv == PR_FAILURE) {
+ if (debug_mode)
+ printf("unable to bind\n");
+ failed_already=1;
+ goto dead;
+ }
+
+ rv = PR_Listen(listenSock, 4);
+ if (rv == PR_FAILURE) {
+ if (debug_mode)
+ printf("unable to listen\n");
+ failed_already=1;
+ goto dead;
+ }
+
+ if (debug_mode)
+ printf("thread %d going into accept for %d seconds\n",
+ info->id, info->accept_timeout + info->id);
+
+ clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id));
+
+ if (clientSock == NULL) {
+ if (PR_GetError() == PR_IO_TIMEOUT_ERROR) {
+ if (debug_mode) {
+ printf("PR_Accept() timeout worked!\n");
+ printf("TEST PASSED! PR_Accept() returned error %d\n",
+ PR_IO_TIMEOUT_ERROR);
+ }
+ } else {
+ if (debug_mode)
+ printf("TEST FAILED! PR_Accept() returned error %d\n",
+ PR_GetError());
+ failed_already=1;
+ }
+ } else {
+ if (debug_mode)
+ printf ("TEST FAILED! PR_Accept() succeeded?\n");
+ failed_already=1;
+ PR_Close(clientSock);
+ }
+
+dead:
+ if (listenSock) {
+ PR_Close(listenSock);
+ }
+ PR_Lock(info->dead_lock);
+ (*info->alive)--;
+ PR_NotifyCondVar(info->dead_cv);
+ PR_Unlock(info->dead_lock);
+
+ if (debug_mode)
+ printf("thread %d is dead\n", info->id);
+
+ PR_Free(info);
+}
+
+void
+thread_test(PRThreadScope scope, PRInt32 num_threads)
+{
+ PRInt32 index;
+ PRThread *thr;
+ PRLock *dead_lock;
+ PRCondVar *dead_cv;
+ PRInt32 alive;
+
+ if (debug_mode)
+ printf("IO Timeout test started with %d threads\n", num_threads);
+
+ dead_lock = PR_NewLock();
+ dead_cv = PR_NewCondVar(dead_lock);
+ alive = num_threads;
+
+ for (index = 0; index < num_threads; index++) {
+ threadInfo *info = (threadInfo *)PR_Malloc(sizeof(threadInfo));
+
+ info->id = index;
+ info->dead_lock = dead_lock;
+ info->dead_cv = dead_cv;
+ info->alive = &alive;
+ info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
+
+ thr = PR_CreateThread( PR_USER_THREAD,
+ thread_main,
+ (void *)info,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
+
+ if (!thr) {
+ printf("Failed to create thread, error = %d(%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+
+ PR_Lock(dead_lock);
+ alive--;
+ PR_Unlock(dead_lock);
+ }
+ }
+
+ PR_Lock(dead_lock);
+ while(alive) {
+ if (debug_mode)
+ printf("main loop awake; alive = %d\n", alive);
+ PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(dead_lock);
+
+ PR_DestroyCondVar(dead_cv);
+ PR_DestroyLock(dead_lock);
+}
+
+int main(int argc, char **argv)
+{
+ PRInt32 num_threads = 0;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name [-d] [-t <threads>]
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 't': /* threads to involve */
+ num_threads = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ if (0 == num_threads)
+ num_threads = NUM_THREADS;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("io_timeout.log");
+ debug_mode = 1;
+#endif
+
+ printf("test with global bound thread\n");
+ thread_test(PR_GLOBAL_BOUND_THREAD, num_threads);
+
+ printf("test with local thread\n");
+ thread_test(PR_LOCAL_THREAD, num_threads);
+
+ printf("test with global thread\n");
+ thread_test(PR_GLOBAL_THREAD, num_threads);
+
+ PR_Cleanup();
+
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutk.c b/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutk.c
new file mode 100644
index 00000000..26e3beeb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutk.c
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** name io_timeoutk.c
+** Description:Test socket IO timeouts (kernel level)
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include "nspr.h"
+
+#define NUM_THREADS 1
+#define BASE_PORT 8000
+#define DEFAULT_ACCEPT_TIMEOUT 2
+
+typedef struct threadInfo {
+ PRInt16 id;
+ PRInt16 accept_timeout;
+ PRLock *dead_lock;
+ PRCondVar *dead_cv;
+ PRInt32 *alive;
+} threadInfo;
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+
+void
+thread_main(void *_info)
+{
+ threadInfo *info = (threadInfo *)_info;
+ PRNetAddr listenAddr;
+ PRNetAddr clientAddr;
+ PRFileDesc *listenSock = NULL;
+ PRFileDesc *clientSock;
+ PRStatus rv;
+
+ if (debug_mode) printf("thread %d is alive\n", info->id);
+
+ listenSock = PR_NewTCPSocket();
+ if (!listenSock) {
+ if (debug_mode) printf("unable to create listen socket\n");
+ goto dead;
+ }
+
+ listenAddr.inet.family = AF_INET;
+ listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
+ listenAddr.inet.ip = PR_htonl(INADDR_ANY);
+ rv = PR_Bind(listenSock, &listenAddr);
+ if (rv == PR_FAILURE) {
+ if (debug_mode) printf("unable to bind\n");
+ goto dead;
+ }
+
+ rv = PR_Listen(listenSock, 4);
+ if (rv == PR_FAILURE) {
+ if (debug_mode) printf("unable to listen\n");
+ goto dead;
+ }
+
+ if (debug_mode) printf("thread %d going into accept for %d seconds\n",
+ info->id, info->accept_timeout + info->id);
+
+ clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id));
+
+ if (clientSock == NULL) {
+ if (PR_GetError() == PR_IO_TIMEOUT_ERROR)
+ if (debug_mode) {
+ printf("PR_Accept() timeout worked!\n");
+ printf("TEST FAILED! PR_Accept() returned error %d\n",
+ PR_GetError());
+ }
+ else failed_already=1;
+ } else {
+ if (debug_mode) printf ("TEST FAILED! PR_Accept() succeeded?\n");
+ else failed_already=1;
+ PR_Close(clientSock);
+ }
+
+dead:
+ if (listenSock) {
+ PR_Close(listenSock);
+ }
+ PR_Lock(info->dead_lock);
+ (*info->alive)--;
+ PR_NotifyCondVar(info->dead_cv);
+ PR_Unlock(info->dead_lock);
+
+ if (debug_mode) printf("thread %d is dead\n", info->id);
+}
+
+void
+thread_test(PRInt32 scope, PRInt32 num_threads)
+{
+ PRInt32 index;
+ PRThread *thr;
+ PRLock *dead_lock;
+ PRCondVar *dead_cv;
+ PRInt32 alive;
+
+ if (debug_mode) printf("IO Timeout test started with %d threads\n", num_threads);
+
+ dead_lock = PR_NewLock();
+ dead_cv = PR_NewCondVar(dead_lock);
+ alive = num_threads;
+
+ for (index = 0; index < num_threads; index++) {
+ threadInfo *info = (threadInfo *)malloc(sizeof(threadInfo));
+
+ info->id = index;
+ info->dead_lock = dead_lock;
+ info->dead_cv = dead_cv;
+ info->alive = &alive;
+ info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
+
+ thr = PR_CreateThread( PR_USER_THREAD,
+ thread_main,
+ (void *)info,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
+
+ if (!thr) {
+ PR_Lock(dead_lock);
+ alive--;
+ PR_Unlock(dead_lock);
+ }
+ }
+
+ PR_Lock(dead_lock);
+ while(alive) {
+ if (debug_mode) printf("main loop awake; alive = %d\n", alive);
+ PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(dead_lock);
+}
+
+int main(int argc, char **argv)
+{
+ PRInt32 num_threads;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ if (argc > 2)
+ num_threads = atoi(argv[2]);
+ else
+ num_threads = NUM_THREADS;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) printf("kernel level test\n");
+ thread_test(PR_GLOBAL_THREAD, num_threads);
+
+ PR_Cleanup();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutu.c b/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutu.c
new file mode 100644
index 00000000..c17a93f7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/io_timeoutu.c
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/*
+** name io_timeoutu.c
+** Description: Test socket IO timeouts (user level)
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include "nspr.h"
+
+#define NUM_THREADS 1
+#define BASE_PORT 8000
+#define DEFAULT_ACCEPT_TIMEOUT 2
+
+typedef struct threadInfo {
+ PRInt16 id;
+ PRInt16 accept_timeout;
+ PRLock *dead_lock;
+ PRCondVar *dead_cv;
+ PRInt32 *alive;
+} threadInfo;
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+void
+thread_main(void *_info)
+{
+ threadInfo *info = (threadInfo *)_info;
+ PRNetAddr listenAddr;
+ PRNetAddr clientAddr;
+ PRFileDesc *listenSock = NULL;
+ PRFileDesc *clientSock;
+ PRStatus rv;
+
+ if (debug_mode) printf("thread %d is alive\n", info->id);
+
+ listenSock = PR_NewTCPSocket();
+ if (!listenSock) {
+ if (debug_mode) printf("unable to create listen socket\n");
+ goto dead;
+ }
+
+ listenAddr.inet.family = AF_INET;
+ listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
+ listenAddr.inet.ip = PR_htonl(INADDR_ANY);
+ rv = PR_Bind(listenSock, &listenAddr);
+ if (rv == PR_FAILURE) {
+ if (debug_mode) printf("unable to bind\n");
+ goto dead;
+ }
+
+ rv = PR_Listen(listenSock, 4);
+ if (rv == PR_FAILURE) {
+ if (debug_mode) printf("unable to listen\n");
+ goto dead;
+ }
+
+ if (debug_mode) printf("thread %d going into accept for %d seconds\n",
+ info->id, info->accept_timeout + info->id);
+
+ clientSock = PR_Accept(
+ listenSock, &clientAddr, PR_SecondsToInterval(
+ info->accept_timeout + info->id));
+
+ if (clientSock == NULL) {
+ if (PR_GetError() == PR_IO_TIMEOUT_ERROR)
+ if (debug_mode) {
+ printf("PR_Accept() timeout worked!\n");
+ printf("TEST FAILED! PR_Accept() returned error %d\n",
+ }
+ PR_GetError());
+ else failed_already=1;
+ } else {
+ if (debug_mode) printf ("TEST FAILED! PR_Accept() succeeded?\n");
+ else failed_already=1;
+ PR_Close(clientSock);
+ }
+
+dead:
+ if (listenSock) {
+ PR_Close(listenSock);
+ }
+ PR_Lock(info->dead_lock);
+ (*info->alive)--;
+ PR_NotifyCondVar(info->dead_cv);
+ PR_Unlock(info->dead_lock);
+
+ if (debug_mode) printf("thread %d is dead\n", info->id);
+}
+
+void
+thread_test(PRInt32 scope, PRInt32 num_threads)
+{
+ PRInt32 index;
+ PRThread *thr;
+ PRLock *dead_lock;
+ PRCondVar *dead_cv;
+ PRInt32 alive;
+
+ if (debug_mode) printf("IO Timeout test started with %d threads\n", num_threads);
+
+ dead_lock = PR_NewLock();
+ dead_cv = PR_NewCondVar(dead_lock);
+ alive = num_threads;
+
+ for (index = 0; index < num_threads; index++) {
+ threadInfo *info = (threadInfo *)malloc(sizeof(threadInfo));
+
+ info->id = index;
+ info->dead_lock = dead_lock;
+ info->dead_cv = dead_cv;
+ info->alive = &alive;
+ info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
+
+ thr = PR_CreateThread( PR_USER_THREAD,
+ thread_main,
+ (void *)info,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0);
+
+ if (!thr) {
+ PR_Lock(dead_lock);
+ alive--;
+ PR_Unlock(dead_lock);
+ }
+ }
+
+ PR_Lock(dead_lock);
+ while(alive) {
+ if (debug_mode) printf("main loop awake; alive = %d\n", alive);
+ PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(dead_lock);
+}
+
+int main(int argc, char **argv)
+{
+ PRInt32 num_threads;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ if (argc > 2)
+ num_threads = atoi(argv[2]);
+ else
+ num_threads = NUM_THREADS;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) printf("user level test\n");
+ thread_test(PR_LOCAL_THREAD, num_threads);
+
+ PR_Cleanup();
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/ioconthr.c b/src/libs/xpcom18a4/nsprpub/pr/tests/ioconthr.c
new file mode 100644
index 00000000..2e39522d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/ioconthr.c
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * This is a test for the io continuation thread machinery
+ * in pthreads.
+ */
+
+#include "nspr.h"
+#include <stdio.h>
+
+int num_threads = 10; /* must be an even number */
+PRThreadScope thread_scope = PR_GLOBAL_THREAD;
+
+void ThreadFunc(void *arg)
+{
+ PRFileDesc *fd = (PRFileDesc *) arg;
+ char buf[1024];
+ PRInt32 nbytes;
+ PRErrorCode err;
+
+ nbytes = PR_Recv(fd, buf, sizeof(buf), 0, PR_SecondsToInterval(20));
+ if (nbytes == -1) {
+ err = PR_GetError();
+ if (err != PR_PENDING_INTERRUPT_ERROR) {
+ fprintf(stderr, "PR_Recv failed: (%d, %d)\n",
+ err, PR_GetOSError());
+ PR_ProcessExit(1);
+ }
+ /*
+ * After getting an I/O interrupt, this thread must
+ * close the fd before it exits due to a limitation
+ * of our NT implementation.
+ */
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ PR_ProcessExit(1);
+ }
+ } else {
+ fprintf(stderr, "PR_Recv received %d bytes!?\n", nbytes);
+ PR_ProcessExit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc **fds;
+ PRThread **threads;
+ PRIntervalTime start, elapsed;
+ int index;
+
+ fds = (PRFileDesc **) PR_MALLOC(2 * num_threads * sizeof(PRFileDesc *));
+ PR_ASSERT(fds != NULL);
+ threads = (PRThread **) PR_MALLOC(num_threads * sizeof(PRThread *));
+ PR_ASSERT(threads != NULL);
+
+ for (index = 0; index < num_threads; index++) {
+ if (PR_NewTCPSocketPair(&fds[2 * index]) == PR_FAILURE) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ PR_ProcessExit(1);
+ }
+ threads[index] = PR_CreateThread(
+ PR_USER_THREAD, ThreadFunc, fds[2 * index],
+ PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == threads[index]) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+
+ /* Let the threads block in PR_Recv */
+ PR_Sleep(PR_SecondsToInterval(2));
+
+ printf("Interrupting the threads\n");
+ fflush(stdout);
+ start = PR_IntervalNow();
+ for (index = 0; index < num_threads; index++) {
+ if (PR_Interrupt(threads[index]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Interrupt failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+ for (index = 0; index < num_threads; index++) {
+ if (PR_JoinThread(threads[index]) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start);
+ printf("Threads terminated in %d milliseconds\n",
+ PR_IntervalToMilliseconds(elapsed));
+ fflush(stdout);
+
+ /* We are being very generous and allow 10 seconds. */
+ if (elapsed >= PR_SecondsToInterval(10)) {
+ fprintf(stderr, "Interrupting threads took longer than 10 seconds!!\n");
+ PR_ProcessExit(1);
+ }
+
+ for (index = 0; index < num_threads; index++) {
+ /* fds[2 * index] was passed to and closed by threads[index]. */
+ if (PR_Close(fds[2 * index + 1]) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ PR_ProcessExit(1);
+ }
+ }
+ PR_DELETE(threads);
+ PR_DELETE(fds);
+ printf("PASS\n");
+ PR_Cleanup();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/ipv6.c b/src/libs/xpcom18a4/nsprpub/pr/tests/ipv6.c
new file mode 100644
index 00000000..742239ae
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/ipv6.c
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prenv.h"
+#include "prmem.h"
+#include "prlink.h"
+#include "prsystem.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prvrsion.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+#include "obsolete/probslet.h"
+
+#include <string.h>
+
+#define DNS_BUFFER 100
+#define ADDR_BUFFER 100
+#define HOST_BUFFER 1024
+#define PROTO_BUFFER 1500
+
+#define NETADDR_SIZE(addr) \
+ (PR_AF_INET == (addr)->raw.family ? \
+ sizeof((addr)->inet) : sizeof((addr)->ipv6))
+
+static PRFileDesc *err = NULL;
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: [-V] [-h]\n");
+ PR_fprintf(err, "\t<nul> Name of host to lookup (default: self)\n");
+ PR_fprintf(err, "\t-V Display runtime version info (default: FALSE)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+static void DumpAddr(const PRNetAddr* address, const char *msg)
+{
+ PRUint32 *word = (PRUint32*)address;
+ PRUint32 addr_len = sizeof(PRNetAddr);
+ PR_fprintf(err, "%s[%d]\t", msg, NETADDR_SIZE(address));
+ while (addr_len > 0)
+ {
+ PR_fprintf(err, " %08x", *word++);
+ addr_len -= sizeof(PRUint32);
+ }
+ PR_fprintf(err, "\n");
+} /* DumpAddr */
+
+static PRStatus PrintAddress(const PRNetAddr* address)
+{
+ PRNetAddr translation;
+ char buffer[ADDR_BUFFER];
+ PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
+ if (PR_FAILURE == rv) PL_FPrintError(err, "PR_NetAddrToString");
+ else
+ {
+ PR_fprintf(err, "\t%s\n", buffer);
+ memset(&translation, 0, sizeof(translation));
+ rv = PR_StringToNetAddr(buffer, &translation);
+ if (PR_FAILURE == rv) PL_FPrintError(err, "PR_StringToNetAddr");
+ else
+ {
+ PRSize addr_len = NETADDR_SIZE(address);
+ if (0 != memcmp(address, &translation, addr_len))
+ {
+ PR_fprintf(err, "Address translations do not match\n");
+ DumpAddr(address, "original");
+ DumpAddr(&translation, "translate");
+ rv = PR_FAILURE;
+ }
+ }
+ }
+ return rv;
+} /* PrintAddress */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PLOptStatus os;
+ PRHostEnt host;
+ PRProtoEnt proto;
+ const char *name = NULL;
+ PRBool failed = PR_FALSE, version = PR_FALSE;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Vh");
+
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* Name of host to lookup */
+ name = opt->value;
+ break;
+ case 'V': /* Do version discovery */
+ version = PR_TRUE;
+ break;
+ case 'h': /* user wants some guidance */
+ default:
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (version)
+ {
+#if defined(WINNT)
+#define NSPR_LIB "libnspr4"
+#else
+#define NSPR_LIB "nspr4"
+#endif
+ const PRVersionDescription *version_info;
+ char *nspr_path = PR_GetEnv("LD_LIBRARY_PATH");
+ char *nspr_name = PR_GetLibraryName(nspr_path, NSPR_LIB);
+ PRLibrary *runtime = PR_LoadLibrary(nspr_name);
+ if (NULL == runtime)
+ PL_FPrintError(err, "PR_LoadLibrary");
+ else
+ {
+ versionEntryPointType versionPoint = (versionEntryPointType)
+ PR_FindSymbol(runtime, "libVersionPoint");
+ if (NULL == versionPoint)
+ PL_FPrintError(err, "PR_FindSymbol");
+ else
+ {
+ char buffer[100];
+ PRExplodedTime exploded;
+ version_info = versionPoint();
+ (void)PR_fprintf(err, "Runtime library version information\n");
+ PR_ExplodeTime(
+ version_info->buildTime, PR_GMTParameters, &exploded);
+ (void)PR_FormatTime(
+ buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded);
+ (void)PR_fprintf(err, " Build time: %s GMT\n", buffer);
+ (void)PR_fprintf(
+ err, " Build time: %s\n", version_info->buildTimeString);
+ (void)PR_fprintf(
+ err, " %s V%u.%u.%u (%s%s%s)\n",
+ version_info->description,
+ version_info->vMajor,
+ version_info->vMinor,
+ version_info->vPatch,
+ (version_info->beta ? " beta " : ""),
+ (version_info->debug ? " debug " : ""),
+ (version_info->special ? " special" : ""));
+ (void)PR_fprintf(err, " filename: %s\n", version_info->filename);
+ (void)PR_fprintf(err, " security: %s\n", version_info->security);
+ (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright);
+ (void)PR_fprintf(err, " comment: %s\n", version_info->comment);
+ }
+ }
+ if (NULL != nspr_name) PR_FreeLibraryName(nspr_name);
+ }
+
+ {
+ if (NULL == name)
+ {
+ char *me = (char*)PR_MALLOC(DNS_BUFFER);
+ rv = PR_GetSystemInfo(PR_SI_HOSTNAME, me, DNS_BUFFER);
+ if (PR_FAILURE == rv)
+ {
+ failed = PR_TRUE;
+ PL_FPrintError(err, "PR_GetSystemInfo");
+ return 2;
+ }
+ name = me; /* just leak the storage */
+ }
+ }
+
+ {
+ char buffer[HOST_BUFFER];
+ PR_fprintf(err, "Translating the name %s ...", name);
+
+ rv = PR_GetHostByName(name, buffer, sizeof(buffer), &host);
+ if (PR_FAILURE == rv)
+ {
+ failed = PR_TRUE;
+ PL_FPrintError(err, "PR_GetHostByName");
+ }
+ else
+ {
+ PRIntn index = 0;
+ PRNetAddr address;
+ memset(&address, 0, sizeof(PRNetAddr));
+ PR_fprintf(err, "success .. enumerating results\n");
+ do
+ {
+ index = PR_EnumerateHostEnt(index, &host, 0, &address);
+ if (index > 0) PrintAddress(&address);
+ else if (-1 == index)
+ {
+ failed = PR_TRUE;
+ PL_FPrintError(err, "PR_EnumerateHostEnt");
+ }
+ } while (index > 0);
+ }
+ }
+
+
+ {
+ char buffer[PROTO_BUFFER];
+ /*
+ ** Get Proto by name/number
+ */
+ rv = PR_GetProtoByName("tcp", &buffer[1], sizeof(buffer) - 1, &proto);
+ rv = PR_GetProtoByNumber(6, &buffer[3], sizeof(buffer) - 3, &proto);
+ }
+
+ return (failed) ? 1 : 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/join.c b/src/libs/xpcom18a4/nsprpub/pr/tests/join.c
new file mode 100644
index 00000000..73d7eb83
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/join.c
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dbmalloc1.c
+**
+** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions.
+**
+** Modification History:
+**
+** 19-May-97 AGarcia - separate the four join tests into different unit test modules.
+** AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+#include "prttools.h"
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+/***********************************************************************
+** PRIVATE FUNCTION: Test_Result
+** DESCRIPTION: Used in conjunction with the regress tool, prints out the
+** status of the test case.
+** INPUTS: PASS/FAIL
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+**
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM: Determine what the status is and print accordingly.
+**
+***********************************************************************/
+
+
+static void Test_Result (int result)
+{
+ if (result == PASS)
+ printf ("PASS\n");
+ else
+ printf ("FAIL\n");
+ exit (1);
+}
+
+
+/*
+ Program to test joining of threads. Two threads are created. One
+ to be waited upon until it has started. The other to join after it has
+ completed.
+*/
+
+
+static void PR_CALLBACK lowPriority(void *arg)
+{
+}
+
+static void PR_CALLBACK highPriority(void *arg)
+{
+}
+
+static void PR_CALLBACK unjoinable(void *arg)
+{
+ PR_Sleep(PR_INTERVAL_NO_TIMEOUT);
+}
+
+void runTest(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *low,*high;
+
+ /* create the low and high priority threads */
+
+ low = PR_CreateThread(PR_USER_THREAD,
+ lowPriority, 0,
+ PR_PRIORITY_LOW,
+ scope1,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!low) {
+ if (debug_mode) printf("\tcannot create low priority thread\n");
+ else Test_Result(FAIL);
+ return;
+ }
+
+ high = PR_CreateThread(PR_USER_THREAD,
+ highPriority, 0,
+ PR_PRIORITY_HIGH,
+ scope2,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!high) {
+ if (debug_mode) printf("\tcannot create high priority thread\n");
+ else Test_Result(FAIL);
+ return;
+ }
+
+ /* Do the joining for both threads */
+ if (PR_JoinThread(low) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join low priority thread\n");
+ else Test_Result (FAIL);
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined low priority thread\n");
+ }
+ if (PR_JoinThread(high) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join high priority thread\n");
+ else Test_Result(FAIL);
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined high priority thread\n");
+ }
+}
+
+void joinWithUnjoinable(void)
+{
+ PRThread *thread;
+
+ /* create the unjoinable thread */
+
+ thread = PR_CreateThread(PR_USER_THREAD,
+ unjoinable, 0,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (!thread) {
+ if (debug_mode) printf("\tcannot create unjoinable thread\n");
+ else Test_Result(FAIL);
+ return;
+ }
+
+ if (PR_JoinThread(thread) == PR_SUCCESS) {
+ if (debug_mode) printf("\tsuccessfully joined with unjoinable thread?!\n");
+ else Test_Result(FAIL);
+ return;
+ } else {
+ if (debug_mode) printf("\tcannot join with unjoinable thread, as expected\n");
+ if (PR_GetError() != PR_INVALID_ARGUMENT_ERROR) {
+ if (debug_mode) printf("\tWrong error code\n");
+ else Test_Result(FAIL);
+ return;
+ }
+ }
+ if (PR_Interrupt(thread) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot interrupt unjoinable thread\n");
+ else Test_Result(FAIL);
+ return;
+ } else {
+ if (debug_mode) printf("\tinterrupted unjoinable thread\n");
+ }
+}
+
+static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("join.log");
+ debug_mode = 1;
+#endif
+
+
+
+ /* main test */
+ printf("User-User test\n");
+ runTest(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+ printf("User-Kernel test\n");
+ runTest(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+ printf("Kernel-User test\n");
+ runTest(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+ printf("Kernel-Kernel test\n");
+ runTest(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+ printf("Join with unjoinable thread\n");
+ joinWithUnjoinable();
+
+ printf("PASSED\n");
+
+ return 0;
+}
+
+
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/joinkk.c b/src/libs/xpcom18a4/nsprpub/pr/tests/joinkk.c
new file mode 100644
index 00000000..0fd991e5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/joinkk.c
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dbmalloc1.c
+**
+** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions.
+**
+** Modification History:
+**
+** 19-May-97 AGarcia - separate the four join tests into different unit test modules.
+** AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+/*
+ Program to test joining of threads. Two threads are created. One
+ to be waited upon until it has started. The other to join after it has
+ completed.
+*/
+
+
+static void lowPriority(void *arg)
+{
+}
+
+static void highPriority(void *arg)
+{
+}
+
+void runTest(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *low,*high;
+
+ /* create the low and high priority threads */
+
+ low = PR_CreateThread(PR_USER_THREAD,
+ lowPriority, 0,
+ PR_PRIORITY_LOW,
+ scope1,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!low) {
+ if (debug_mode) printf("\tcannot create low priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ high = PR_CreateThread(PR_USER_THREAD,
+ highPriority, 0,
+ PR_PRIORITY_HIGH,
+ scope2,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!high) {
+ if (debug_mode) printf("\tcannot create high priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ /* Do the joining for both threads */
+ if (PR_JoinThread(low) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join low priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined low priority thread\n");
+ }
+ if (PR_JoinThread(high) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join high priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined high priority thread\n");
+ }
+}
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("join.log");
+#endif
+
+
+
+ /* main test */
+
+ if (debug_mode) printf("Kernel-Kernel test\n");
+ runTest(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+
+ if(failed_already)
+ {
+ printf("FAIL\n");
+ return 1;
+ }
+ else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+
+}
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/joinku.c b/src/libs/xpcom18a4/nsprpub/pr/tests/joinku.c
new file mode 100644
index 00000000..ecaa24c9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/joinku.c
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dbmalloc1.c
+**
+** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions.
+**
+** Modification History:
+**
+** 19-May-97 AGarcia - separate the four join tests into different unit test modules.
+** AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+
+/*
+ Program to test joining of threads. Two threads are created. One
+ to be waited upon until it has started. The other to join after it has
+ completed.
+*/
+
+
+static void lowPriority(void *arg)
+{
+}
+
+static void highPriority(void *arg)
+{
+}
+
+void runTest(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *low,*high;
+
+ /* create the low and high priority threads */
+
+ low = PR_CreateThread(PR_USER_THREAD,
+ lowPriority, 0,
+ PR_PRIORITY_LOW,
+ scope1,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!low) {
+ if (debug_mode) printf("\tcannot create low priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ high = PR_CreateThread(PR_USER_THREAD,
+ highPriority, 0,
+ PR_PRIORITY_HIGH,
+ scope2,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!high) {
+ if (debug_mode) printf("\tcannot create high priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ /* Do the joining for both threads */
+ if (PR_JoinThread(low) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join low priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined low priority thread\n");
+ }
+ if (PR_JoinThread(high) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join high priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined high priority thread\n");
+ }
+}
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("joinku.log");
+#endif
+
+
+
+ /* main test */
+
+ if (debug_mode) printf("Kernel-User test\n");
+ runTest(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+
+
+ if(failed_already)
+ {
+ printf("FAIL\n");
+ return 1;
+ }
+ else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+
+}
+
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/joinuk.c b/src/libs/xpcom18a4/nsprpub/pr/tests/joinuk.c
new file mode 100644
index 00000000..1564731d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/joinuk.c
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: joinuk.c
+**
+** Description: Join kernel - user
+**
+** Modification History:
+**
+** 19-May-97 AGarcia - separate the four join tests into different unit test modules.
+** AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+PRIntn failed_already=0;
+PRIntn debug_mode;
+/*
+ Program to test joining of threads. Two threads are created. One
+ to be waited upon until it has started. The other to join after it has
+ completed.
+*/
+
+
+static void lowPriority(void *arg)
+{
+}
+
+static void highPriority(void *arg)
+{
+}
+
+void runTest(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *low,*high;
+
+ /* create the low and high priority threads */
+
+ low = PR_CreateThread(PR_USER_THREAD,
+ lowPriority, 0,
+ PR_PRIORITY_LOW,
+ scope1,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!low) {
+ if (debug_mode) printf("\tcannot create low priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ high = PR_CreateThread(PR_USER_THREAD,
+ highPriority, 0,
+ PR_PRIORITY_HIGH,
+ scope2,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!high) {
+ if (debug_mode) printf("\tcannot create high priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ /* Do the joining for both threads */
+ if (PR_JoinThread(low) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join low priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined low priority thread\n");
+ }
+ if (PR_JoinThread(high) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join high priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined high priority thread\n");
+ }
+}
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("joinuk.log");
+#endif
+
+
+
+ /* main test */
+
+ if (debug_mode) printf("User-Kernel test\n");
+ runTest(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+
+
+ if(failed_already)
+ {
+ printf("FAIL\n");
+ return 1;
+ } else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+}
+
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/joinuu.c b/src/libs/xpcom18a4/nsprpub/pr/tests/joinuu.c
new file mode 100644
index 00000000..ea0d2d70
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/joinuu.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: dbmalloc1.c
+**
+** Description: Join tests user - user
+**
+** Modification History:
+**
+** 19-May-97 AGarcia - separate the four join tests into different unit test modules.
+** AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+
+/*
+ Program to test joining of threads. Two threads are created. One
+ to be waited upon until it has started. The other to join after it has
+ completed.
+*/
+
+
+static void lowPriority(void *arg)
+{
+}
+
+static void highPriority(void *arg)
+{
+}
+
+void runTest(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *low,*high;
+
+ /* create the low and high priority threads */
+
+ low = PR_CreateThread(PR_USER_THREAD,
+ lowPriority, 0,
+ PR_PRIORITY_LOW,
+ scope1,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!low) {
+ if (debug_mode) printf("\tcannot create low priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ high = PR_CreateThread(PR_USER_THREAD,
+ highPriority, 0,
+ PR_PRIORITY_HIGH,
+ scope2,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!high) {
+ if (debug_mode) printf("\tcannot create high priority thread\n");
+ else failed_already=1;
+ return;
+ }
+
+ /* Do the joining for both threads */
+ if (PR_JoinThread(low) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join low priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined low priority thread\n");
+ }
+ if (PR_JoinThread(high) == PR_FAILURE) {
+ if (debug_mode) printf("\tcannot join high priority thread\n");
+ else failed_already=1;
+ return;
+ } else {
+ if (debug_mode) printf("\tjoined high priority thread\n");
+ }
+}
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("joinuu.log");
+#endif
+
+
+
+ /* main test */
+ if (debug_mode) printf("User-User test\n");
+ runTest(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+
+ if(failed_already)
+ {
+ printf("FAIL\n");
+ return 1;
+ } else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+
+
+}
+
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/layer.c b/src/libs/xpcom18a4/nsprpub/pr/tests/layer.c
new file mode 100644
index 00000000..7eae46a2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/layer.c
@@ -0,0 +1,465 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "prnetdb.h"
+#include "prthread.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+#include "prwin16.h"
+
+#include <stdlib.h>
+
+/*
+** Testing layering of I/O
+**
+** The layered server
+** A thread that acts as a server. It creates a TCP listener with a dummy
+** layer pushed on top. Then listens for incoming connections. Each connection
+** request for connection will be layered as well, accept one request, echo
+** it back and close.
+**
+** The layered client
+** Pretty much what you'd expect.
+*/
+
+static PRFileDesc *logFile;
+static PRDescIdentity identity;
+static PRNetAddr server_address;
+
+static PRIOMethods myMethods;
+
+typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
+
+static PRIntn minor_iterations = 5;
+static PRIntn major_iterations = 1;
+static Verbosity verbosity = quiet;
+static PRUint16 default_port = 12273;
+
+static PRFileDesc *PushLayer(PRFileDesc *stack)
+{
+ PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods);
+ PRStatus rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return stack;
+} /* PushLayer */
+
+static PRFileDesc *PushNewLayers(PRFileDesc *stack)
+{
+ PRDescIdentity tmp_identity;
+ PRFileDesc *layer;
+ PRStatus rv;
+
+ /* push a dummy layer */
+ tmp_identity = PR_GetUniqueIdentity("Dummy 1");
+ layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods());
+ rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
+ stack);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ /* push a data procesing layer */
+ layer = PR_CreateIOLayerStub(identity, &myMethods);
+ rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
+ stack);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ /* push another dummy layer */
+ tmp_identity = PR_GetUniqueIdentity("Dummy 2");
+ layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods());
+ rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer,
+ stack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return stack;
+} /* PushLayer */
+
+#if 0
+static PRFileDesc *PopLayer(PRFileDesc *stack)
+{
+ PRFileDesc *popped = PR_PopIOLayer(stack, identity);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack);
+ popped->dtor(popped);
+
+ return stack;
+} /* PopLayer */
+#endif
+
+static void PR_CALLBACK Client(void *arg)
+{
+ PRStatus rv;
+ PRUint8 buffer[100];
+ PRIntn empty_flags = 0;
+ PRIntn bytes_read, bytes_sent;
+ PRFileDesc *stack = (PRFileDesc*)arg;
+
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buffer, 0, sizeof(buffer));
+
+ rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(PR_SUCCESS == rv);
+ while (minor_iterations-- > 0)
+ {
+ bytes_sent = PR_Send(
+ stack, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(sizeof(buffer) == bytes_sent);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client sending %d bytes\n", bytes_sent);
+ bytes_read = PR_Recv(
+ stack, buffer, bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client receiving %d bytes\n", bytes_read);
+ PR_ASSERT(bytes_read == bytes_sent);
+ }
+
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Client shutting down stack\n");
+
+ rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
+} /* Client */
+
+static void PR_CALLBACK Server(void *arg)
+{
+ PRStatus rv;
+ PRUint8 buffer[100];
+ PRFileDesc *service;
+ PRUintn empty_flags = 0;
+ PRIntn bytes_read, bytes_sent;
+ PRFileDesc *stack = (PRFileDesc*)arg;
+ PRNetAddr client_address;
+
+ service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Server accepting connection\n");
+
+ do
+ {
+ bytes_read = PR_Recv(
+ service, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (0 != bytes_read)
+ {
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server receiving %d bytes\n", bytes_read);
+ PR_ASSERT(bytes_read > 0);
+ bytes_sent = PR_Send(
+ service, buffer, bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server sending %d bytes\n", bytes_sent);
+ PR_ASSERT(bytes_read == bytes_sent);
+ }
+
+ } while (0 != bytes_read);
+
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Server shutting down and closing stack\n");
+ rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
+
+} /* Server */
+
+static PRInt32 PR_CALLBACK MyRecv(
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ char *b = (char*)buf;
+ PRFileDesc *lo = fd->lower;
+ PRInt32 rv, readin = 0, request = 0;
+ rv = lo->methods->recv(lo, &request, sizeof(request), flags, timeout);
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MyRecv sending permission for %d bytes\n", request);
+ if (0 < rv)
+ {
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MyRecv received permission request for %d bytes\n", request);
+ rv = lo->methods->send(
+ lo, &request, sizeof(request), flags, timeout);
+ if (0 < rv)
+ {
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MyRecv sending permission for %d bytes\n", request);
+ while (readin < request)
+ {
+ rv = lo->methods->recv(
+ lo, b + readin, amount - readin, flags, timeout);
+ if (rv <= 0) break;
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MyRecv received %d bytes\n", rv);
+ readin += rv;
+ }
+ rv = readin;
+ }
+ }
+ return rv;
+} /* MyRecv */
+
+static PRInt32 PR_CALLBACK MySend(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ PRFileDesc *lo = fd->lower;
+ const char *b = (const char*)buf;
+ PRInt32 rv, wroteout = 0, request;
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MySend asking permission to send %d bytes\n", amount);
+ rv = lo->methods->send(lo, &amount, sizeof(amount), flags, timeout);
+ if (0 < rv)
+ {
+ rv = lo->methods->recv(
+ lo, &request, sizeof(request), flags, timeout);
+ if (0 < rv)
+ {
+ PR_ASSERT(request == amount);
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MySend got permission to send %d bytes\n", request);
+ while (wroteout < request)
+ {
+ rv = lo->methods->send(
+ lo, b + wroteout, request - wroteout, flags, timeout);
+ if (rv <= 0) break;
+ if (verbosity > chatty) PR_fprintf(
+ logFile, "MySend wrote %d bytes\n", rv);
+ wroteout += rv;
+ }
+ rv = amount;
+ }
+ }
+ return rv;
+} /* MySend */
+
+static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
+{
+ PRIntn verbage = (PRIntn)verbosity + delta;
+ if (verbage < (PRIntn)silent) verbage = (PRIntn)silent;
+ else if (verbage > (PRIntn)noisy) verbage = (PRIntn)noisy;
+ return (Verbosity)verbage;
+} /* ChangeVerbosity */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRIntn mits;
+ PLOptStatus os;
+ PRFileDesc *client, *service;
+ PRFileDesc *client_stack, *service_stack;
+ PRNetAddr any_address;
+ const char *server_name = NULL;
+ const PRIOMethods *stubMethods;
+ PRThread *client_thread, *server_thread;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0:
+ server_name = opt->value;
+ break;
+ case 'd': /* debug mode */
+ if (verbosity < noisy)
+ verbosity = ChangeVerbosity(verbosity, 1);
+ break;
+ case 'q': /* debug mode */
+ if (verbosity > silent)
+ verbosity = ChangeVerbosity(verbosity, -1);
+ break;
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'C': /* number of threads waiting */
+ major_iterations = atoi(opt->value);
+ break;
+ case 'c': /* number of client threads */
+ minor_iterations = atoi(opt->value);
+ break;
+ case 'p': /* default port */
+ default_port = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ PR_STDIO_INIT();
+
+ logFile = PR_GetSpecialFD(PR_StandardError);
+
+ identity = PR_GetUniqueIdentity("Dummy");
+ stubMethods = PR_GetDefaultIOMethods();
+
+ /*
+ ** The protocol we're going to implement is one where in order to initiate
+ ** a send, the sender must first solicit permission. Therefore, every
+ ** send is really a send - receive - send sequence.
+ */
+ myMethods = *stubMethods; /* first get the entire batch */
+ myMethods.recv = MyRecv; /* then override the ones we care about */
+ myMethods.send = MySend; /* then override the ones we care about */
+
+ if (NULL == server_name)
+ rv = PR_InitializeNetAddr(
+ PR_IpAddrLoopback, default_port, &server_address);
+ else
+ {
+ rv = PR_StringToNetAddr(server_name, &server_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_InitializeNetAddr(
+ PR_IpAddrNull, default_port, &server_address);
+ }
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ /* one type w/o layering */
+
+ mits = minor_iterations;
+ while (major_iterations-- > 0)
+ {
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Beginning non-layered test\n");
+ client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
+ service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
+
+ minor_iterations = mits;
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, Server, service,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != server_thread);
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, Client, client,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != client_thread);
+
+ rv = PR_JoinThread(client_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(server_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Ending non-layered test\n");
+
+ /* with layering */
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Beginning layered test\n");
+ client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
+ PushLayer(client);
+ service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
+ PushLayer(service);
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
+
+ minor_iterations = mits;
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, Server, service,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != server_thread);
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, Client, client,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != client_thread);
+
+ rv = PR_JoinThread(client_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(server_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
+ /* with layering, using new style stack */
+ if (verbosity > silent)
+ PR_fprintf(logFile,
+ "Beginning layered test with new style stack\n");
+ client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
+ client_stack = PR_CreateIOLayer(client);
+ PushNewLayers(client_stack);
+ service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
+ service_stack = PR_CreateIOLayer(service);
+ PushNewLayers(service_stack);
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
+
+ minor_iterations = mits;
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, Server, service_stack,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != server_thread);
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, Client, client_stack,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != client_thread);
+
+ rv = PR_JoinThread(client_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(server_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Close(client_stack); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service_stack); PR_ASSERT(PR_SUCCESS == rv);
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Ending layered test\n");
+ }
+ return 0;
+} /* main */
+
+/* layer.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/lazyinit.c b/src/libs/xpcom18a4/nsprpub/pr/tests/lazyinit.c
new file mode 100644
index 00000000..09f0b6fa
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/lazyinit.c
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: lazyinit.c
+** Description: Testing lazy initialization
+**
+** Since you only get to initialize once, you have to rerun the test
+** for each test case. The test cases are numbered. If you want to
+** add more tests, take the next number and add it to the switch
+** statement.
+**
+** This test is problematic on systems that don't support the notion
+** of console output. The workarounds to emulate that feature include
+** initializations themselves, which defeats the purpose here.
+*/
+
+#include "prcvar.h"
+#include "prenv.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prthread.h"
+#include "prtypes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void PR_CALLBACK lazyEntry(void *arg)
+{
+ PR_ASSERT(NULL == arg);
+} /* lazyEntry */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRUintn pdkey;
+ PRStatus status;
+ char *path = NULL;
+ PRDir *dir = NULL;
+ PRLock *ml = NULL;
+ PRCondVar *cv = NULL;
+ PRThread *thread = NULL;
+ PRIntervalTime interval = 0;
+ PRFileDesc *file, *udp, *tcp, *pair[2];
+ PRIntn test;
+
+ if ( argc < 2)
+ {
+ test = 0;
+ }
+ else
+ test = atoi(argv[1]);
+
+ switch (test)
+ {
+ case 0: ml = PR_NewLock();
+ break;
+
+ case 1: interval = PR_SecondsToInterval(1);
+ break;
+
+ case 2: thread = PR_CreateThread(
+ PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ break;
+
+ case 3: file = PR_Open("/usr/tmp/", PR_RDONLY, 0);
+ break;
+
+ case 4: udp = PR_NewUDPSocket();
+ break;
+
+ case 5: tcp = PR_NewTCPSocket();
+ break;
+
+ case 6: dir = PR_OpenDir("/usr/tmp/");
+ break;
+
+ case 7: (void)PR_NewThreadPrivateIndex(&pdkey, NULL);
+ break;
+
+ case 8: path = PR_GetEnv("PATH");
+ break;
+
+ case 9: status = PR_NewTCPSocketPair(pair);
+ break;
+
+ case 10: PR_SetConcurrency(2);
+ break;
+
+ default:
+ printf(
+ "lazyinit: unrecognized command line argument: %s\n",
+ argv[1] );
+ printf( "FAIL\n" );
+ exit( 1 );
+ break;
+ } /* switch() */
+ return 0;
+} /* Lazy */
+
+/* lazyinit.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/libfilename.c b/src/libs/xpcom18a4/nsprpub/pr/tests/libfilename.c
new file mode 100644
index 00000000..ab482936
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/libfilename.c
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 ***** */
+
+/***********************************************************************
+**
+** Name: libfilename.c
+**
+** Description: test PR_GetLibraryFilePathname.
+**
+***********************************************************************/
+
+#include "nspr.h"
+#include "pprio.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+PRBool debug_mode = PR_FALSE;
+
+static PRStatus RunTest(const char *name, PRFuncPtr addr)
+{
+ char *pathname;
+ PRFileDesc *fd;
+
+ pathname = PR_GetLibraryFilePathname(name, addr);
+ if (pathname == NULL) {
+ fprintf(stderr, "PR_GetLibraryFilePathname failed\n");
+ /* we let this test pass if this function is not implemented */
+ if (PR_GetError() == PR_NOT_IMPLEMENTED_ERROR) {
+ return PR_SUCCESS;
+ }
+ return PR_FAILURE;
+ }
+
+ if (debug_mode) printf("Pathname is %s\n", pathname);
+ fd = PR_OpenFile(pathname, PR_RDONLY, 0);
+ if (fd == NULL) {
+ fprintf(stderr, "PR_Open failed: %d\n", (int)PR_GetError());
+ return PR_FAILURE;
+ }
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed: %d\n", (int)PR_GetError());
+ return PR_FAILURE;
+ }
+ PR_Free(pathname);
+ return PR_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+ char *name;
+ PRFuncPtr addr;
+ PRLibrary *lib;
+ PRBool failed = PR_FALSE;
+
+ if (argc >= 2 && strcmp(argv[1], "-d") == 0) {
+ debug_mode = PR_TRUE;
+ }
+
+ /* First test a library that is implicitly linked. */
+#ifdef WINNT
+ name = PR_Malloc(strlen("libnspr4.dll")+1);
+ strcpy(name, "libnspr4.dll");
+#else
+ name = PR_GetLibraryName(NULL, "nspr4");
+#endif
+ addr = (PRFuncPtr)PR_GetTCPMethods()->close;
+ if (RunTest(name, addr) == PR_FAILURE) {
+ failed = PR_TRUE;
+ }
+ PR_FreeLibraryName(name);
+
+ /* Next test a library that is dynamically loaded. */
+ name = PR_GetLibraryName("dll", "my");
+ if (debug_mode) printf("Loading library %s\n", name);
+ lib = PR_LoadLibrary(name);
+ if (!lib) {
+ fprintf(stderr, "PR_LoadLibrary failed\n");
+ exit(1);
+ }
+ PR_FreeLibraryName(name);
+ name = PR_GetLibraryName(NULL, "my");
+ addr = PR_FindFunctionSymbol(lib, "My_GetValue");
+ if (RunTest(name, addr) == PR_FAILURE) {
+ failed = PR_TRUE;
+ }
+ PR_FreeLibraryName(name);
+ PR_UnloadLibrary(lib);
+ if (failed) {
+ printf("FAIL\n");
+ return 1;
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/lltest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/lltest.c
new file mode 100644
index 00000000..f8ce4c6a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/lltest.c
@@ -0,0 +1,859 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** testll.c -- test suite for 64bit integer (longlong) operations
+**
+** Summary: testll [-d] | [-h]
+**
+** Where:
+** -d set debug mode on; displays individual test failures
+** -v verbose mode; displays progress in test, plus -d
+** -h gives usage message.
+**
+** Description:
+** lltest.c tests the functions defined in NSPR 2.0's prlong.h.
+**
+** Successive tests begin to depend on other LL functions working
+** correctly. So, ... Do not change the order of the tests as run
+** from main().
+**
+** Caveats:
+** Do not even begin to think that this is an exhaustive test!
+**
+** These tests try a little of everything, but not all boundary
+** conditions and limits are tested.
+** You want better coverage? ... Add it.
+**
+** ---
+** Author: Lawrence Hardiman <larryh@netscape.com>.
+** ---
+** Revision History:
+** 01-Oct-1997. Original implementation.
+**
+*/
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+/* --- Local Definitions --- */
+#define ReportProgress(m) if (verboseMode) PR_fprintf(output, (m));
+
+
+/* --- Global variables --- */
+static PRIntn failedAlready = 0;
+static PRFileDesc* output = NULL;
+static PRBool debugMode = PR_FALSE;
+static PRBool verboseMode = PR_FALSE;
+
+/*
+** Constants used in tests.
+*/
+const PRInt64 bigZero = LL_INIT( 0, 0 );
+const PRInt64 bigOne = LL_INIT( 0, 1 );
+const PRInt64 bigTwo = LL_INIT( 0, 2 );
+const PRInt64 bigSixTeen = LL_INIT( 0, 16 );
+const PRInt64 bigThirtyTwo = LL_INIT( 0, 32 );
+const PRInt64 bigMinusOne = LL_INIT( 0xffffffff, 0xffffffff );
+const PRInt64 bigMinusTwo = LL_INIT( 0xffffffff, 0xfffffffe );
+const PRInt64 bigNumber = LL_INIT( 0x7fffffff, 0xffffffff );
+const PRInt64 bigMinusNumber = LL_INIT( 0x80000000, 0x00000001 );
+const PRInt64 bigMaxInt32 = LL_INIT( 0x00000000, 0x7fffffff );
+const PRInt64 big2To31 = LL_INIT( 0x00000000, 0x80000000 );
+const PRUint64 bigZeroFox = LL_INIT( 0x00000000, 0xffffffff );
+const PRUint64 bigFoxFox = LL_INIT( 0xffffffff, 0xffffffff );
+const PRUint64 bigFoxZero = LL_INIT( 0xffffffff, 0x00000000 );
+const PRUint64 bigEightZero = LL_INIT( 0x80000000, 0x00000000 );
+const PRUint64 big64K = LL_INIT( 0x00000000, 0x00010000 );
+const PRInt64 bigInt0 = LL_INIT( 0x01a00000, 0x00001000 );
+const PRInt64 bigInt1 = LL_INIT( 0x01a00000, 0x00001100 );
+const PRInt64 bigInt2 = LL_INIT( 0x01a00000, 0x00000100 );
+const PRInt64 bigInt3 = LL_INIT( 0x01a00001, 0x00001000 );
+const PRInt64 bigInt4 = LL_INIT( 0x01a00001, 0x00001100 );
+const PRInt64 bigInt5 = LL_INIT( 0x01a00001, 0x00000100 );
+const PRInt64 bigInt6 = LL_INIT( 0xb1a00000, 0x00001000 );
+const PRInt64 bigInt7 = LL_INIT( 0xb1a00000, 0x00001100 );
+const PRInt64 bigInt8 = LL_INIT( 0xb1a00000, 0x00000100 );
+const PRInt64 bigInt9 = LL_INIT( 0xb1a00001, 0x00001000 );
+const PRInt64 bigInt10 = LL_INIT( 0xb1a00001, 0x00001100 );
+const PRInt64 bigInt11 = LL_INIT( 0xb1a00001, 0x00000100 );
+const PRInt32 one = 1l;
+const PRInt32 minusOne = -1l;
+const PRInt32 sixteen = 16l;
+const PRInt32 thirtyTwo = 32l;
+const PRInt32 sixtyThree = 63l;
+
+/*
+** SetFailed() -- Report individual test failure
+**
+*/
+static void
+SetFailed( char *what, char *how )
+{
+ failedAlready = 1;
+ if ( debugMode )
+ PR_fprintf(output, "%s: failed: %s\n", what, how );
+ return;
+}
+
+static void
+ResultFailed( char *what, char *how, PRInt64 expected, PRInt64 got)
+{
+ if ( debugMode)
+ {
+ SetFailed( what, how );
+ PR_fprintf(output, "Expected: 0x%llx Got: 0x%llx\n", expected, got );
+ }
+ return;
+}
+
+
+/*
+** TestAssignment() -- Test the assignment
+*/
+static void TestAssignment( void )
+{
+ PRInt64 zero = LL_Zero();
+ PRInt64 min = LL_MinInt();
+ PRInt64 max = LL_MaxInt();
+ if (!LL_EQ(zero, bigZero))
+ SetFailed("LL_EQ(zero, bigZero)", "!=");
+ if (!LL_CMP(max, >, min))
+ SetFailed("LL_CMP(max, >, min)", "!>");
+}
+
+/*
+** TestComparisons() -- Test the longlong comparison operations
+*/
+static void
+TestComparisons( void )
+{
+ ReportProgress("Testing Comparisons Operations\n");
+
+ /* test for zero */
+ if ( !LL_IS_ZERO( bigZero ))
+ SetFailed( "LL_IS_ZERO", "Zero is not zero" );
+
+ if ( LL_IS_ZERO( bigOne ))
+ SetFailed( "LL_IS_ZERO", "One tests as zero" );
+
+ if ( LL_IS_ZERO( bigMinusOne ))
+ SetFailed( "LL_IS_ZERO", "Minus One tests as zero" );
+
+ /* test equal */
+ if ( !LL_EQ( bigZero, bigZero ))
+ SetFailed( "LL_EQ", "zero EQ zero");
+
+ if ( !LL_EQ( bigOne, bigOne ))
+ SetFailed( "LL_EQ", "one EQ one" );
+
+ if ( !LL_EQ( bigNumber, bigNumber ))
+ SetFailed( "LL_EQ", "bigNumber EQ bigNumber" );
+
+ if ( !LL_EQ( bigMinusOne, bigMinusOne ))
+ SetFailed( "LL_EQ", "minus one EQ minus one");
+
+ if ( LL_EQ( bigZero, bigOne ))
+ SetFailed( "LL_EQ", "zero EQ one");
+
+ if ( LL_EQ( bigOne, bigZero ))
+ SetFailed( "LL_EQ", "one EQ zero" );
+
+ if ( LL_EQ( bigMinusOne, bigOne ))
+ SetFailed( "LL_EQ", "minus one EQ one");
+
+ if ( LL_EQ( bigNumber, bigOne ))
+ SetFailed( "LL_EQ", "bigNumber EQ one");
+
+ /* test not equal */
+ if ( LL_NE( bigZero, bigZero ))
+ SetFailed( "LL_NE", "0 NE 0");
+
+ if ( LL_NE( bigOne, bigOne ))
+ SetFailed( "LL_NE", "1 NE 1");
+
+ if ( LL_NE( bigMinusOne, bigMinusOne ))
+ SetFailed( "LL_NE", "-1 NE -1");
+
+ if ( LL_NE( bigNumber, bigNumber ))
+ SetFailed( "LL_NE", "n NE n");
+
+ if ( LL_NE( bigMinusNumber, bigMinusNumber ))
+ SetFailed( "LL_NE", "-n NE -n");
+
+ if ( !LL_NE( bigZero, bigOne))
+ SetFailed( "LL_NE", "0 NE 1");
+
+ if ( !LL_NE( bigOne, bigMinusNumber))
+ SetFailed( "LL_NE", "1 NE -n");
+
+ /* Greater than or equal to zero */
+ if ( !LL_GE_ZERO( bigZero ))
+ SetFailed( "LL_GE_ZERO", "0");
+
+ if ( !LL_GE_ZERO( bigOne ))
+ SetFailed( "LL_GE_ZERO", "1");
+
+ if ( !LL_GE_ZERO( bigNumber ))
+ SetFailed( "LL_GE_ZERO", "n");
+
+ if ( LL_GE_ZERO( bigMinusOne ))
+ SetFailed( "LL_GE_ZERO", "-1");
+
+ if ( LL_GE_ZERO( bigMinusNumber ))
+ SetFailed( "LL_GE_ZERO", "-n");
+
+ /* Algebraic Compare two values */
+ if ( !LL_CMP( bigZero, ==, bigZero ))
+ SetFailed( "LL_CMP", "0 == 0");
+
+ if ( LL_CMP( bigZero, >, bigZero ))
+ SetFailed( "LL_CMP", "0 > 0");
+
+ if ( LL_CMP( bigZero, <, bigZero ))
+ SetFailed( "LL_CMP", "0 < 0");
+
+ if ( LL_CMP( bigNumber, <, bigOne ))
+ SetFailed( "LL_CMP", "n < 1");
+
+ if ( !LL_CMP( bigNumber, >, bigOne ))
+ SetFailed( "LL_CMP", "n <= 1");
+
+ if ( LL_CMP( bigOne, >, bigNumber ))
+ SetFailed( "LL_CMP", "1 > n");
+
+ if ( LL_CMP( bigMinusNumber, >, bigNumber ))
+ SetFailed( "LL_CMP", "-n > n");
+
+ if ( LL_CMP( bigNumber, !=, bigNumber))
+ SetFailed( "LL_CMP", "n != n");
+
+ if ( !LL_CMP( bigMinusOne, >, bigMinusTwo ))
+ SetFailed( "LL_CMP", "-1 <= -2");
+
+ if ( !LL_CMP( bigMaxInt32, <, big2To31 ))
+ SetFailed( "LL_CMP", "Max 32-bit signed int >= 2^31");
+
+ /* Two positive numbers */
+ if ( !LL_CMP( bigInt0, <=, bigInt0 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt0, <=, bigInt1 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( LL_CMP( bigInt0, <=, bigInt2 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt0, <=, bigInt3 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt0, <=, bigInt4 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt0, <=, bigInt5 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ /* Two negative numbers */
+ if ( !LL_CMP( bigInt6, <=, bigInt6 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt6, <=, bigInt7 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( LL_CMP( bigInt6, <=, bigInt8 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt6, <=, bigInt9 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt6, <=, bigInt10 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( !LL_CMP( bigInt6, <=, bigInt11 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ /* One positive, one negative */
+ if ( LL_CMP( bigInt0, <=, bigInt6 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( LL_CMP( bigInt0, <=, bigInt7 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ if ( LL_CMP( bigInt0, <=, bigInt8 ))
+ SetFailed( "LL_CMP", "LL_CMP(<=) failed");
+
+ /* Bitwise Compare two numbers */
+ if ( !LL_UCMP( bigZero, ==, bigZero ))
+ SetFailed( "LL_UCMP", "0 == 0");
+
+ if ( LL_UCMP( bigZero, >, bigZero ))
+ SetFailed( "LL_UCMP", "0 > 0");
+
+ if ( LL_UCMP( bigZero, <, bigZero ))
+ SetFailed( "LL_UCMP", "0 < 0");
+
+ if ( LL_UCMP( bigNumber, <, bigOne ))
+ SetFailed( "LL_UCMP", "n < 1");
+
+ if ( !LL_UCMP( bigNumber, >, bigOne ))
+ SetFailed( "LL_UCMP", "n < 1");
+
+ if ( LL_UCMP( bigOne, >, bigNumber ))
+ SetFailed( "LL_UCMP", "1 > n");
+
+ if ( LL_UCMP( bigMinusNumber, <, bigNumber ))
+ SetFailed( "LL_UCMP", "-n < n");
+
+ /* Two positive numbers */
+ if ( !LL_UCMP( bigInt0, <=, bigInt0 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt0, <=, bigInt1 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( LL_UCMP( bigInt0, <=, bigInt2 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt0, <=, bigInt3 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt0, <=, bigInt4 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt0, <=, bigInt5 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ /* Two negative numbers */
+ if ( !LL_UCMP( bigInt6, <=, bigInt6 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt6, <=, bigInt7 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( LL_UCMP( bigInt6, <=, bigInt8 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt6, <=, bigInt9 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt6, <=, bigInt10 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt6, <=, bigInt11 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ /* One positive, one negative */
+ if ( !LL_UCMP( bigInt0, <=, bigInt6 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt0, <=, bigInt7 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ if ( !LL_UCMP( bigInt0, <=, bigInt8 ))
+ SetFailed( "LL_UCMP", "LL_UCMP(<=) failed");
+
+ return;
+}
+
+/*
+** TestLogicalOperations() -- Tests for AND, OR, ...
+**
+*/
+static void
+TestLogicalOperations( void )
+{
+ PRUint64 result, result2;
+
+ ReportProgress("Testing Logical Operations\n");
+
+ /* Test AND */
+ LL_AND( result, bigZero, bigZero );
+ if ( !LL_IS_ZERO( result ))
+ ResultFailed( "LL_AND", "0 & 0", bigZero, result );
+
+ LL_AND( result, bigOne, bigOne );
+ if ( LL_IS_ZERO( result ))
+ ResultFailed( "LL_AND", "1 & 1", bigOne, result );
+
+ LL_AND( result, bigZero, bigOne );
+ if ( !LL_IS_ZERO( result ))
+ ResultFailed( "LL_AND", "1 & 1", bigZero, result );
+
+ LL_AND( result, bigMinusOne, bigMinusOne );
+ if ( !LL_UCMP( result, ==, bigMinusOne ))
+ ResultFailed( "LL_AND", "-1 & -1", bigMinusOne, result );
+
+ /* test OR */
+ LL_OR( result, bigZero, bigZero );
+ if ( !LL_IS_ZERO( result ))
+ ResultFailed( "LL_OR", "0 | 1", bigZero, result);
+
+ LL_OR( result, bigZero, bigOne );
+ if ( LL_IS_ZERO( result ))
+ ResultFailed( "LL_OR", "0 | 1", bigOne, result );
+
+ LL_OR( result, bigZero, bigMinusNumber );
+ if ( !LL_UCMP( result, ==, bigMinusNumber ))
+ ResultFailed( "LL_OR", "0 | -n", bigMinusNumber, result);
+
+ LL_OR( result, bigMinusNumber, bigZero );
+ if ( !LL_UCMP( result, ==, bigMinusNumber ))
+ ResultFailed( "LL_OR", "-n | 0", bigMinusNumber, result );
+
+ /* test XOR */
+ LL_XOR( result, bigZero, bigZero );
+ if ( LL_UCMP( result, !=, bigZero ))
+ ResultFailed( "LL_XOR", "0 ^ 0", bigZero, result);
+
+ LL_XOR( result, bigOne, bigZero );
+ if ( LL_UCMP( result, !=, bigOne ))
+ ResultFailed( "LL_XOR", "1 ^ 0", bigZero, result );
+
+ LL_XOR( result, bigMinusNumber, bigZero );
+ if ( LL_UCMP( result, !=, bigMinusNumber ))
+ ResultFailed( "LL_XOR", "-n ^ 0", bigMinusNumber, result );
+
+ LL_XOR( result, bigMinusNumber, bigMinusNumber );
+ if ( LL_UCMP( result, !=, bigZero ))
+ ResultFailed( "LL_XOR", "-n ^ -n", bigMinusNumber, result);
+
+ /* test OR2. */
+ result = bigZero;
+ LL_OR2( result, bigOne );
+ if ( LL_UCMP( result, !=, bigOne ))
+ ResultFailed( "LL_OR2", "(r=0) |= 1", bigOne, result);
+
+ result = bigOne;
+ LL_OR2( result, bigNumber );
+ if ( LL_UCMP( result, !=, bigNumber ))
+ ResultFailed( "LL_OR2", "(r=1) |= n", bigNumber, result);
+
+ result = bigMinusNumber;
+ LL_OR2( result, bigMinusNumber );
+ if ( LL_UCMP( result, !=, bigMinusNumber ))
+ ResultFailed( "LL_OR2", "(r=-n) |= -n", bigMinusNumber, result);
+
+ /* test NOT */
+ LL_NOT( result, bigMinusNumber);
+ LL_NOT( result2, result);
+ if ( LL_UCMP( result2, !=, bigMinusNumber ))
+ ResultFailed( "LL_NOT", "r != ~(~-n)", bigMinusNumber, result);
+
+ /* test Negation */
+ LL_NEG( result, bigMinusNumber );
+ LL_NEG( result2, result );
+ if ( LL_CMP( result2, !=, bigMinusNumber ))
+ ResultFailed( "LL_NEG", "r != -(-(-n))", bigMinusNumber, result);
+
+ return;
+}
+
+
+
+/*
+** TestConversion() -- Test Conversion Operations
+**
+*/
+static void
+TestConversion( void )
+{
+ PRInt64 result;
+ PRInt64 resultU;
+ PRInt32 result32;
+ PRUint32 resultU32;
+ float resultF;
+ PRFloat64 resultD;
+
+ ReportProgress("Testing Conversion Operations\n");
+
+ /* LL_L2I -- Convert to signed 32bit */
+ LL_L2I(result32, bigOne );
+ if ( result32 != one )
+ SetFailed( "LL_L2I", "r != 1");
+
+ LL_L2I(result32, bigMinusOne );
+ if ( result32 != minusOne )
+ SetFailed( "LL_L2I", "r != -1");
+
+ /* LL_L2UI -- Convert 64bit to unsigned 32bit */
+ LL_L2UI( resultU32, bigMinusOne );
+ if ( resultU32 != (PRUint32) minusOne )
+ SetFailed( "LL_L2UI", "r != -1");
+
+ LL_L2UI( resultU32, bigOne );
+ if ( resultU32 != (PRUint32) one )
+ SetFailed( "LL_L2UI", "r != 1");
+
+ /* LL_L2F -- Convert to 32bit floating point */
+ LL_L2F( resultF, bigOne );
+ if ( resultF != 1.0 )
+ SetFailed( "LL_L2F", "r != 1.0");
+
+ LL_L2F( resultF, bigMinusOne );
+ if ( resultF != -1.0 )
+ SetFailed( "LL_L2F", "r != 1.0");
+
+ /* LL_L2D -- Convert to 64bit floating point */
+ LL_L2D( resultD, bigOne );
+ if ( resultD != 1.0L )
+ SetFailed( "LL_L2D", "r != 1.0");
+
+ LL_L2D( resultD, bigMinusOne );
+ if ( resultD != -1.0L )
+ SetFailed( "LL_L2D", "r != -1.0");
+
+ /* LL_I2L -- Convert 32bit signed to 64bit signed */
+ LL_I2L( result, one );
+ if ( LL_CMP(result, !=, bigOne ))
+ SetFailed( "LL_I2L", "r != 1");
+
+ LL_I2L( result, minusOne );
+ if ( LL_CMP(result, !=, bigMinusOne ))
+ SetFailed( "LL_I2L", "r != -1");
+
+ /* LL_UI2L -- Convert 32bit unsigned to 64bit unsigned */
+ LL_UI2L( resultU, (PRUint32) one );
+ if ( LL_CMP(resultU, !=, bigOne ))
+ SetFailed( "LL_UI2L", "r != 1");
+
+ /* [lth.] This did not behave as expected, but it is correct
+ */
+ LL_UI2L( resultU, (PRUint32) minusOne );
+ if ( LL_CMP(resultU, !=, bigZeroFox ))
+ ResultFailed( "LL_UI2L", "r != -1", bigZeroFox, resultU);
+
+ /* LL_F2L -- Convert 32bit float to 64bit signed */
+ LL_F2L( result, 1.0 );
+ if ( LL_CMP(result, !=, bigOne ))
+ SetFailed( "LL_F2L", "r != 1");
+
+ LL_F2L( result, -1.0 );
+ if ( LL_CMP(result, !=, bigMinusOne ))
+ SetFailed( "LL_F2L", "r != -1");
+
+ /* LL_D2L -- Convert 64bit Float to 64bit signed */
+ LL_D2L( result, 1.0L );
+ if ( LL_CMP(result, !=, bigOne ))
+ SetFailed( "LL_D2L", "r != 1");
+
+ LL_D2L( result, -1.0L );
+ if ( LL_CMP(result, !=, bigMinusOne ))
+ SetFailed( "LL_D2L", "r != -1");
+
+ return;
+}
+
+static void ShiftCompileOnly()
+{
+ /*
+ ** This function is only compiled, never called.
+ ** The real test is to see if it compiles w/o
+ ** warnings. This is no small feat, by the way.
+ */
+ PRInt64 ia, ib;
+ PRUint64 ua, ub;
+ LL_SHR(ia, ib, 32);
+ LL_SHL(ia, ib, 32);
+
+ LL_USHR(ua, ub, 32);
+ LL_ISHL(ia, 49, 32);
+
+} /* ShiftCompileOnly */
+
+
+/*
+** TestShift() -- Test Shifting Operations
+**
+*/
+static void
+TestShift( void )
+{
+ static const PRInt64 largeTwoZero = LL_INIT( 0x00000002, 0x00000000 );
+ PRInt64 result;
+ PRUint64 resultU;
+
+ ReportProgress("Testing Shifting Operations\n");
+
+ /* LL_SHL -- Shift left algebraic */
+ LL_SHL( result, bigOne, one );
+ if ( LL_CMP( result, !=, bigTwo ))
+ ResultFailed( "LL_SHL", "r != 2", bigOne, result );
+
+ LL_SHL( result, bigTwo, thirtyTwo );
+ if ( LL_CMP( result, !=, largeTwoZero ))
+ ResultFailed( "LL_SHL", "r != twoZero", largeTwoZero, result);
+
+ /* LL_SHR -- Shift right algebraic */
+ LL_SHR( result, bigFoxZero, thirtyTwo );
+ if ( LL_CMP( result, !=, bigMinusOne ))
+ ResultFailed( "LL_SHR", "r != -1", bigMinusOne, result);
+
+ LL_SHR( result, bigTwo, one );
+ if ( LL_CMP( result, !=, bigOne ))
+ ResultFailed( "LL_SHR", "r != 1", bigOne, result);
+
+ LL_SHR( result, bigFoxFox, thirtyTwo );
+ if ( LL_CMP( result, !=, bigMinusOne ))
+ ResultFailed( "LL_SHR", "r != -1 (was ff,ff)", bigMinusOne, result);
+
+ /* LL_USHR -- Logical shift right */
+ LL_USHR( resultU, bigZeroFox, thirtyTwo );
+ if ( LL_UCMP( resultU, !=, bigZero ))
+ ResultFailed( "LL_USHR", "r != 0 ", bigZero, result);
+
+ LL_USHR( resultU, bigFoxFox, thirtyTwo );
+ if ( LL_UCMP( resultU, !=, bigZeroFox ))
+ ResultFailed( "LL_USHR", "r != 0 ", bigZeroFox, result);
+
+ /* LL_ISHL -- Shift a 32bit integer into a 64bit result */
+ LL_ISHL( resultU, minusOne, thirtyTwo );
+ if ( LL_UCMP( resultU, !=, bigFoxZero ))
+ ResultFailed( "LL_ISHL", "r != ff,00 ", bigFoxZero, result);
+
+ LL_ISHL( resultU, one, sixtyThree );
+ if ( LL_UCMP( resultU, !=, bigEightZero ))
+ ResultFailed( "LL_ISHL", "r != 80,00 ", bigEightZero, result);
+
+ LL_ISHL( resultU, one, sixteen );
+ if ( LL_UCMP( resultU, !=, big64K ))
+ ResultFailed( "LL_ISHL", "r != 64K ", big64K, resultU);
+
+ return;
+}
+
+
+/*
+** TestArithmetic() -- Test arithmetic operations.
+**
+*/
+static void
+TestArithmetic( void )
+{
+ PRInt64 largeVal = LL_INIT( 0x00000001, 0xffffffff );
+ PRInt64 largeValPlusOne = LL_INIT( 0x00000002, 0x00000000 );
+ PRInt64 largeValTimesTwo = LL_INIT( 0x00000003, 0xfffffffe );
+ PRInt64 largeMultCand = LL_INIT( 0x00000000, 0x7fffffff );
+ PRInt64 largeMinusMultCand = LL_INIT( 0xffffffff, 0x10000001 );
+ PRInt64 largeMultCandx64K = LL_INIT( 0x00007fff, 0xffff0000 );
+ PRInt64 largeNumSHL5 = LL_INIT( 0x0000001f, 0xffffffe0 );
+ PRInt64 result, result2;
+
+ /* Addition */
+ LL_ADD( result, bigOne, bigOne );
+ if ( LL_CMP( result, !=, bigTwo ))
+ ResultFailed( "LL_ADD", "r != 1 + 1", bigTwo, result);
+
+ LL_ADD( result, bigMinusOne, bigOne );
+ if ( LL_CMP( result, !=, bigZero ))
+ ResultFailed( "LL_ADD", "r != -1 + 1", bigOne, result);
+
+ LL_ADD( result, largeVal, bigOne );
+ if ( LL_CMP( result, !=, largeValPlusOne ))
+ ResultFailed( "LL_ADD", "lVP1 != lV + 1", largeValPlusOne, result);
+
+ /* Subtraction */
+ LL_SUB( result, bigOne, bigOne );
+ if ( LL_CMP( result, !=, bigZero ))
+ ResultFailed( "LL_SUB", "r != 1 - 1", bigZero, result);
+
+ LL_SUB( result, bigTwo, bigOne );
+ if ( LL_CMP( result, !=, bigOne ))
+ ResultFailed( "LL_SUB", "r != 2 - 1", bigOne, result);
+
+ LL_SUB( result, largeValPlusOne, bigOne );
+ if ( LL_CMP( result, !=, largeVal ))
+ ResultFailed( "LL_SUB", "r != lVP1 - 1", largeVal, result);
+
+
+ /* Multiply */
+ LL_MUL( result, largeVal, bigTwo );
+ if ( LL_CMP( result, !=, largeValTimesTwo ))
+ ResultFailed( "LL_MUL", "r != lV*2", largeValTimesTwo, result);
+
+ LL_MUL( result, largeMultCand, big64K );
+ if ( LL_CMP( result, !=, largeMultCandx64K ))
+ ResultFailed( "LL_MUL", "r != lV*64K", largeMultCandx64K, result);
+
+ LL_NEG( result2, largeMultCand );
+ LL_MUL( result, largeMultCand, bigMinusOne );
+ if ( LL_CMP( result, !=, result2 ))
+ ResultFailed( "LL_MUL", "r != -lMC", result2, result);
+
+ LL_SHL( result2, bigZeroFox, 5);
+ LL_MUL( result, bigZeroFox, bigThirtyTwo );
+ if ( LL_CMP( result, !=, largeNumSHL5 ))
+ ResultFailed( "LL_MUL", "r != 0f<<5", largeNumSHL5, result );
+
+
+
+ /* LL_DIV() Division */
+ LL_DIV( result, bigOne, bigOne);
+ if ( LL_CMP( result, !=, bigOne ))
+ ResultFailed( "LL_DIV", "1 != 1", bigOne, result);
+
+ LL_DIV( result, bigNumber, bigOne );
+ if ( LL_CMP( result, !=, bigNumber ))
+ ResultFailed( "LL_DIV", "r != n / 1", bigNumber, result);
+
+ LL_DIV( result, bigNumber, bigMinusOne );
+ if ( LL_CMP( result, !=, bigMinusNumber ))
+ ResultFailed( "LL_DIV", "r != n / -1", bigMinusNumber, result);
+
+ LL_DIV( result, bigMinusNumber, bigMinusOne );
+ if ( LL_CMP( result, !=, bigNumber ))
+ ResultFailed( "LL_DIV", "r != -n / -1", bigNumber, result);
+
+ LL_SHL( result2, bigZeroFox, 5 );
+ LL_DIV( result, result2, bigOne );
+ if ( LL_CMP( result, !=, result2 ))
+ ResultFailed( "LL_DIV", "0f<<5 != 0f<<5", result2, result);
+
+ LL_SHL( result2, bigZeroFox, 5 );
+ LL_NEG( result2, result2 );
+ LL_DIV( result, result2, bigOne );
+ if ( LL_CMP( result, !=, result2 ))
+ ResultFailed( "LL_DIV", "-0f<<5 != -0f<<5", result2, result);
+
+ LL_SHL( result2, bigZeroFox, 17 );
+ LL_DIV( result, result2, bigMinusOne );
+ LL_NEG( result2, result2 );
+ if ( LL_CMP( result, !=, result2 ))
+ ResultFailed( "LL_DIV", "-0f<<17 != -0f<<17", result2, result);
+
+
+ /* LL_MOD() Modulo Division */
+ LL_ADD( result2, bigThirtyTwo, bigOne );
+ LL_MOD( result, result2, bigSixTeen );
+ if ( LL_CMP( result, !=, bigOne ))
+ ResultFailed( "LL_MOD", "r != 1", bigSixTeen, result);
+
+
+ LL_MUL( result2, bigZeroFox, bigThirtyTwo );
+ LL_ADD( result2, result2, bigSixTeen);
+ LL_MOD( result, result2, bigThirtyTwo );
+ if ( LL_CMP( result, !=, bigSixTeen ))
+ ResultFailed( "LL_MOD", "r != 16", bigSixTeen, result);
+
+ /* LL_UDIVMOD */
+ LL_DIV( result, bigOne, bigOne);
+ if ( LL_CMP( result, !=, bigOne ))
+ ResultFailed( "LL_DIV", "r != 16", bigSixTeen, result);
+
+
+ return;
+}
+
+static void TestWellknowns(void)
+{
+ PRInt64 max = LL_MAXINT, min = LL_MININT, zero = LL_ZERO;
+ PRInt64 mmax = LL_MaxInt(), mmin = LL_MinInt(), mzero = LL_Zero();
+ if (LL_NE(max, mmax))
+ ResultFailed( "max, mmax", "max != mmax", max, mmax);
+ if (LL_NE(min, mmin))
+ ResultFailed( "min, mmin", "min != mmin", max, mmin);
+ if (LL_NE(zero, mzero))
+ ResultFailed( "zero, mzero", "zero != mzero", zero, mzero);
+} /* TestWellknowns */
+
+/*
+** Initialize() -- Initialize the test case
+**
+** Parse command line options
+**
+*/
+static PRIntn
+Initialize( PRIntn argc, char **argv )
+{
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dvh");
+ PLOptStatus os;
+
+ /*
+ ** Parse command line options
+ */
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* set debug mode */
+ debugMode = PR_TRUE;
+ break;
+
+ case 'v': /* set verbose mode */
+ verboseMode = PR_TRUE;
+ debugMode = PR_TRUE;
+ break;
+
+ case 'h': /* user wants some guidance */
+ default:
+ PR_fprintf(output, "You get help.\n");
+ return(1);
+ }
+ }
+ PL_DestroyOptState(opt);
+ return(0);
+}
+
+PRIntn main( int argc, char **argv )
+{
+ PR_STDIO_INIT();
+ output = PR_GetSpecialFD(PR_StandardError);
+
+ if ( Initialize( argc, argv ))
+ return(1);
+
+ TestAssignment();
+ TestComparisons();
+ TestLogicalOperations();
+ TestConversion();
+ TestShift();
+ TestArithmetic();
+ TestWellknowns();
+
+ /*
+ ** That's all folks!
+ */
+ if ( failedAlready )
+ {
+ PR_fprintf(output, "FAIL\n");\
+ }
+ else
+ {
+ PR_fprintf(output, "PASS\n");\
+ }
+ return failedAlready;
+} /* end main() */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/lock.c b/src/libs/xpcom18a4/nsprpub/pr/tests/lock.c
new file mode 100644
index 00000000..e0e23d01
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/lock.c
@@ -0,0 +1,547 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: lock.c
+** Purpose: test basic locking functions
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+**
+** 11-Aug-97 LarryH. Win16 port of NSPR.
+** - Added "PASS", "FAIL" messages on completion.
+** - Change stack variables to static scope variables
+** because of shadow-stack use by Win16
+** - Added PR_CALLBACK attribute to functions called by NSPR
+** - Added command line arguments:
+** - l <num> to control the number of loops
+** - c <num> to control the number of CPUs.
+** (was positional argv).
+**
+**
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prio.h"
+#include "prcmon.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmon.h"
+#include "prmem.h"
+#include "prthread.h"
+#include "prtypes.h"
+
+#include "plstr.h"
+
+#include <stdlib.h>
+
+#if defined(XP_UNIX)
+#include <string.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+static PRIntn failed_already=0;
+static PRFileDesc *std_err = NULL;
+static PRBool verbosity = PR_FALSE;
+static PRBool debug_mode = PR_FALSE;
+
+const static PRIntervalTime contention_interval = 50;
+
+typedef struct LockContentious_s {
+ PRLock *ml;
+ PRInt32 loops;
+ PRUint32 contender;
+ PRUint32 contentious;
+ PRIntervalTime overhead;
+ PRIntervalTime interval;
+} LockContentious_t;
+
+typedef struct MonitorContentious_s {
+ PRMonitor *ml;
+ PRInt32 loops;
+ PRUint32 contender;
+ PRUint32 contentious;
+ PRIntervalTime overhead;
+ PRIntervalTime interval;
+} MonitorContentious_t;
+
+
+static PRIntervalTime Sleeper(PRUint32 loops)
+{
+ PRIntervalTime predicted = 0;
+ while (loops-- > 0)
+ {
+ predicted += contention_interval;
+ (void)PR_Sleep(contention_interval);
+ }
+ return predicted;
+} /* Sleeper */
+
+/*
+** BASIC LOCKS
+*/
+static PRIntervalTime MakeLock(PRUint32 loops)
+{
+ PRLock *ml = NULL;
+ while (loops-- > 0)
+ {
+ ml = PR_NewLock();
+ PR_DestroyLock(ml);
+ ml = NULL;
+ }
+ return 0;
+} /* MakeLock */
+
+static PRIntervalTime NonContentiousLock(PRUint32 loops)
+{
+ PRLock *ml = NULL;
+ ml = PR_NewLock();
+ while (loops-- > 0)
+ {
+ PR_Lock(ml);
+ PR_Unlock(ml);
+ }
+ PR_DestroyLock(ml);
+ return 0;
+} /* NonContentiousLock */
+
+static void PR_CALLBACK LockContender(void *arg)
+{
+ LockContentious_t *contention = (LockContentious_t*)arg;
+ while (contention->loops-- > 0)
+ {
+ PR_Lock(contention->ml);
+ contention->contender+= 1;
+ contention->overhead += contention->interval;
+ PR_Sleep(contention->interval);
+ PR_Unlock(contention->ml);
+ }
+} /* LockContender */
+
+static PRIntervalTime ContentiousLock(PRUint32 loops)
+{
+ PRStatus status;
+ PRThread *thread = NULL;
+ LockContentious_t * contention;
+ PRIntervalTime rv, overhead, timein = PR_IntervalNow();
+
+ contention = PR_NEWZAP(LockContentious_t);
+ contention->loops = loops;
+ contention->overhead = 0;
+ contention->ml = PR_NewLock();
+ contention->interval = contention_interval;
+ thread = PR_CreateThread(
+ PR_USER_THREAD, LockContender, contention,
+ PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(thread != NULL);
+
+ overhead = PR_IntervalNow() - timein;
+
+ while (contention->loops-- > 0)
+ {
+ PR_Lock(contention->ml);
+ contention->contentious+= 1;
+ contention->overhead += contention->interval;
+ PR_Sleep(contention->interval);
+ PR_Unlock(contention->ml);
+ }
+
+ timein = PR_IntervalNow();
+ status = PR_JoinThread(thread);
+ PR_DestroyLock(contention->ml);
+ overhead += (PR_IntervalNow() - timein);
+ rv = overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
+ PR_Free(contention);
+ return rv;
+} /* ContentiousLock */
+
+/*
+** MONITORS
+*/
+static PRIntervalTime MakeMonitor(PRUint32 loops)
+{
+ PRMonitor *ml = NULL;
+ while (loops-- > 0)
+ {
+ ml = PR_NewMonitor();
+ PR_DestroyMonitor(ml);
+ ml = NULL;
+ }
+ return 0;
+} /* MakeMonitor */
+
+static PRIntervalTime NonContentiousMonitor(PRUint32 loops)
+{
+ PRMonitor *ml = NULL;
+ ml = PR_NewMonitor();
+ while (loops-- > 0)
+ {
+ PR_EnterMonitor(ml);
+ PR_ExitMonitor(ml);
+ }
+ PR_DestroyMonitor(ml);
+ return 0;
+} /* NonContentiousMonitor */
+
+static void PR_CALLBACK TryEntry(void *arg)
+{
+ PRMonitor *ml = (PRMonitor*)arg;
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread created\n");
+ PR_EnterMonitor(ml);
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread acquired monitor\n");
+ PR_ExitMonitor(ml);
+ if (debug_mode) PR_fprintf(std_err, "Reentrant thread released monitor\n");
+} /* TryEntry */
+
+static PRIntervalTime ReentrantMonitor(PRUint32 loops)
+{
+ PRStatus status;
+ PRThread *thread;
+ PRMonitor *ml = PR_NewMonitor();
+ if (debug_mode) PR_fprintf(std_err, "\nMonitor created for reentrant test\n");
+
+ PR_EnterMonitor(ml);
+ PR_EnterMonitor(ml);
+ if (debug_mode) PR_fprintf(std_err, "Monitor acquired twice\n");
+
+ thread = PR_CreateThread(
+ PR_USER_THREAD, TryEntry, ml,
+ PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(thread != NULL);
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PR_ExitMonitor(ml);
+ if (debug_mode) PR_fprintf(std_err, "Monitor released first time\n");
+
+ PR_ExitMonitor(ml);
+ if (debug_mode) PR_fprintf(std_err, "Monitor released second time\n");
+
+ status = PR_JoinThread(thread);
+ if (debug_mode) PR_fprintf(std_err,
+ "Reentrant thread joined %s\n",
+ (status == PR_SUCCESS) ? "successfully" : "in error");
+
+ PR_DestroyMonitor(ml);
+ return 0;
+} /* ReentrantMonitor */
+
+static void PR_CALLBACK MonitorContender(void *arg)
+{
+ MonitorContentious_t *contention = (MonitorContentious_t*)arg;
+ while (contention->loops-- > 0)
+ {
+ PR_EnterMonitor(contention->ml);
+ contention->contender+= 1;
+ contention->overhead += contention->interval;
+ PR_Sleep(contention->interval);
+ PR_ExitMonitor(contention->ml);
+ }
+} /* MonitorContender */
+
+static PRUint32 ContentiousMonitor(PRUint32 loops)
+{
+ PRStatus status;
+ PRThread *thread = NULL;
+ MonitorContentious_t * contention;
+ PRIntervalTime rv, overhead, timein = PR_IntervalNow();
+
+ contention = PR_NEWZAP(MonitorContentious_t);
+ contention->loops = loops;
+ contention->overhead = 0;
+ contention->ml = PR_NewMonitor();
+ contention->interval = contention_interval;
+ thread = PR_CreateThread(
+ PR_USER_THREAD, MonitorContender, contention,
+ PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(thread != NULL);
+
+ overhead = PR_IntervalNow() - timein;
+
+ while (contention->loops-- > 0)
+ {
+ PR_EnterMonitor(contention->ml);
+ contention->contentious+= 1;
+ contention->overhead += contention->interval;
+ PR_Sleep(contention->interval);
+ PR_ExitMonitor(contention->ml);
+ }
+
+ timein = PR_IntervalNow();
+ status = PR_JoinThread(thread);
+ PR_DestroyMonitor(contention->ml);
+ overhead += (PR_IntervalNow() - timein);
+ rv = overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
+ PR_Free(contention);
+ return rv;
+} /* ContentiousMonitor */
+
+/*
+** CACHED MONITORS
+*/
+static PRIntervalTime NonContentiousCMonitor(PRUint32 loops)
+{
+ MonitorContentious_t contention;
+ while (loops-- > 0)
+ {
+ PR_CEnterMonitor(&contention);
+ PR_CExitMonitor(&contention);
+ }
+ return 0;
+} /* NonContentiousCMonitor */
+
+static void PR_CALLBACK Contender(void *arg)
+{
+ MonitorContentious_t *contention = (MonitorContentious_t*)arg;
+ while (contention->loops-- > 0)
+ {
+ PR_CEnterMonitor(contention);
+ contention->contender+= 1;
+ contention->overhead += contention->interval;
+ PR_Sleep(contention->interval);
+ PR_CExitMonitor(contention);
+ }
+} /* Contender */
+
+static PRIntervalTime ContentiousCMonitor(PRUint32 loops)
+{
+ PRStatus status;
+ PRThread *thread = NULL;
+ MonitorContentious_t * contention;
+ PRIntervalTime overhead, timein = PR_IntervalNow();
+
+ contention = PR_NEWZAP(MonitorContentious_t);
+ contention->ml = NULL;
+ contention->loops = loops;
+ contention->interval = contention_interval;
+ thread = PR_CreateThread(
+ PR_USER_THREAD, Contender, contention,
+ PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(thread != NULL);
+
+ overhead = PR_IntervalNow() - timein;
+
+ while (contention->loops-- > 0)
+ {
+ PR_CEnterMonitor(contention);
+ contention->contentious+= 1;
+ contention->overhead += contention->interval;
+ PR_Sleep(contention->interval);
+ PR_CExitMonitor(contention);
+ }
+
+ timein = PR_IntervalNow();
+ status = PR_JoinThread(thread);
+ overhead += (PR_IntervalNow() - timein);
+ overhead += overhead + contention->overhead;
+ if (verbosity)
+ PR_fprintf(
+ std_err, "Access ratio: %u to %u\n",
+ contention->contentious, contention->contender);
+ PR_Free(contention);
+ return overhead;
+} /* ContentiousCMonitor */
+
+static PRIntervalTime Test(
+ const char* msg, PRUint32 (*test)(PRUint32 loops),
+ PRUint32 loops, PRIntervalTime overhead)
+{
+ /*
+ * overhead - overhead not measured by the test.
+ * duration - wall clock time it took to perform test.
+ * predicted - extra time test says should not be counted
+ *
+ * Time accountable to the test is duration - overhead - predicted
+ * All times are Intervals and accumulated for all iterations.
+ */
+ PRFloat64 elapsed;
+ PRIntervalTime accountable, duration;
+ PRUintn spaces = PL_strlen(msg);
+ PRIntervalTime timeout, timein = PR_IntervalNow();
+ PRIntervalTime predicted = test(loops);
+ timeout = PR_IntervalNow();
+ duration = timeout - timein;
+
+ if (debug_mode)
+ {
+ accountable = duration - predicted;
+ accountable -= overhead;
+ elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable);
+ PR_fprintf(PR_STDOUT, "%s:", msg);
+ while (spaces++ < 50) PR_fprintf(PR_STDOUT, " ");
+ if ((PRInt32)accountable < 0)
+ PR_fprintf(PR_STDOUT, "*****.** usecs/iteration\n");
+ else
+ PR_fprintf(PR_STDOUT, "%8.2f usecs/iteration\n", elapsed/loops);
+ }
+ return duration;
+} /* Test */
+
+int main(int argc, char **argv)
+{
+ PRBool rv = PR_TRUE;
+ PRIntervalTime duration;
+ PRUint32 cpu, cpus = 2, loops = 100;
+
+
+ PR_STDIO_INIT();
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ {
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Command line argument -l <num> sets the number of loops.
+ Command line argument -c <num> sets the number of cpus.
+ Usage: lock [-d] [-l <num>] [-c <num>]
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dvl:c:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'v': /* debug mode */
+ verbosity = PR_TRUE;
+ break;
+ case 'l': /* number of loops */
+ loops = atoi(opt->value);
+ break;
+ case 'c': /* number of cpus */
+ cpus = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ /* main test */
+ PR_SetConcurrency(8);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("lock.log");
+ debug_mode = 1;
+#endif
+
+ if (loops == 0) loops = 100;
+ if (debug_mode)
+ {
+ std_err = PR_STDERR;
+ PR_fprintf(std_err, "Lock: Using %d loops\n", loops);
+ }
+
+ if (cpus == 0) cpus = 2;
+ if (debug_mode) PR_fprintf(std_err, "Lock: Using %d cpu(s)\n", cpus);
+
+ (void)Sleeper(10); /* try filling in the caches */
+
+ for (cpu = 1; cpu <= cpus; ++cpu)
+ {
+ if (debug_mode) PR_fprintf(std_err, "\nLock: Using %d CPU(s)\n", cpu);
+ PR_SetConcurrency(cpu);
+
+ duration = Test("Overhead of PR_Sleep", Sleeper, loops, 0);
+ duration = 0;
+
+ (void)Test("Lock creation/deletion", MakeLock, loops, 0);
+ (void)Test("Lock non-contentious locking/unlocking", NonContentiousLock, loops, 0);
+ (void)Test("Lock contentious locking/unlocking", ContentiousLock, loops, duration);
+ (void)Test("Monitor creation/deletion", MakeMonitor, loops, 0);
+ (void)Test("Monitor non-contentious locking/unlocking", NonContentiousMonitor, loops, 0);
+ (void)Test("Monitor contentious locking/unlocking", ContentiousMonitor, loops, duration);
+
+ (void)Test("Cached monitor non-contentious locking/unlocking", NonContentiousCMonitor, loops, 0);
+ (void)Test("Cached monitor contentious locking/unlocking", ContentiousCMonitor, loops, duration);
+
+ (void)ReentrantMonitor(loops);
+ }
+
+ if (debug_mode)
+ PR_fprintf(
+ std_err, "%s: test %s\n", "Lock(mutex) test",
+ ((rv) ? "passed" : "failed"));
+ else {
+ if (!rv)
+ failed_already=1;
+ }
+
+ if(failed_already)
+ {
+ PR_fprintf(PR_STDOUT, "FAIL\n");
+ return 1;
+ }
+ else
+ {
+ PR_fprintf(PR_STDOUT, "PASS\n");
+ return 0;
+ }
+
+} /* main */
+
+/* testlock.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/lockfile.c b/src/libs/xpcom18a4/nsprpub/pr/tests/lockfile.c
new file mode 100644
index 00000000..27f8821e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/lockfile.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: lockfile.c
+** Purpose: test basic locking functions
+** Just because this times stuff, don't think its a perforamnce
+** test!!!
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prcmon.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmon.h"
+#include "prthread.h"
+#include "prtypes.h"
+
+#ifndef XP_MAC
+#include "private/pprio.h"
+#else
+#include "pprio.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+const static PRIntervalTime contention_interval = 50;
+
+typedef struct LockContentious_s {
+ PRLock *ml;
+ PRInt32 loops;
+ PRIntervalTime overhead;
+ PRIntervalTime interval;
+} LockContentious_t;
+
+#define LOCKFILE "prlock.fil"
+
+
+
+static PRIntervalTime NonContentiousLock(PRInt32 loops)
+{
+ PRFileDesc *_lockfile;
+ while (loops-- > 0)
+ {
+ _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666);
+ if (!_lockfile) {
+ if (debug_mode) printf(
+ "could not create lockfile: %d [%d]\n",
+ PR_GetError(), PR_GetOSError());
+ return PR_INTERVAL_NO_TIMEOUT;
+ }
+ PR_LockFile(_lockfile);
+ PR_UnlockFile(_lockfile);
+ PR_Close(_lockfile);
+ }
+ return 0;
+} /* NonContentiousLock */
+
+static void PR_CALLBACK LockContender(void *arg)
+{
+ LockContentious_t *contention = (LockContentious_t*)arg;
+ PRFileDesc *_lockfile;
+ while (contention->loops-- > 0)
+ {
+ _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666);
+ if (!_lockfile) {
+ if (debug_mode) printf(
+ "could not create lockfile: %d [%d]\n",
+ PR_GetError(), PR_GetOSError());
+ break;
+ }
+ PR_LockFile(_lockfile);
+ PR_Sleep(contention->interval);
+ PR_UnlockFile(_lockfile);
+ PR_Close(_lockfile);
+ }
+
+} /* LockContender */
+
+/*
+** Win16 requires things passed to Threads not be on the stack
+*/
+static LockContentious_t contention;
+
+static PRIntervalTime ContentiousLock(PRInt32 loops)
+{
+ PRStatus status;
+ PRThread *thread = NULL;
+ PRIntervalTime overhead, timein = PR_IntervalNow();
+
+ contention.loops = loops;
+ contention.overhead = 0;
+ contention.ml = PR_NewLock();
+ contention.interval = contention_interval;
+ thread = PR_CreateThread(
+ PR_USER_THREAD, LockContender, &contention,
+ PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(thread != NULL);
+
+ overhead = PR_IntervalNow() - timein;
+
+ while (contention.loops > 0)
+ {
+ PR_Lock(contention.ml);
+ contention.overhead += contention.interval;
+ PR_Sleep(contention.interval);
+ PR_Unlock(contention.ml);
+ }
+
+ timein = PR_IntervalNow();
+ status = PR_JoinThread(thread);
+ PR_DestroyLock(contention.ml);
+ overhead += (PR_IntervalNow() - timein);
+ return overhead + contention.overhead;
+} /* ContentiousLock */
+
+static PRIntervalTime Test(
+ const char* msg, PRIntervalTime (*test)(PRInt32 loops),
+ PRInt32 loops, PRIntervalTime overhead)
+{
+ /*
+ * overhead - overhead not measured by the test.
+ * duration - wall clock time it took to perform test.
+ * predicted - extra time test says should not be counted
+ *
+ * Time accountable to the test is duration - overhead - predicted
+ * All times are Intervals and accumulated for all iterations.
+ */
+ PRFloat64 elapsed;
+ PRIntervalTime accountable, duration;
+ PRUintn spaces = strlen(msg);
+ PRIntervalTime timeout, timein = PR_IntervalNow();
+ PRIntervalTime predicted = test(loops);
+ timeout = PR_IntervalNow();
+ duration = timeout - timein;
+ accountable = duration - predicted;
+ accountable -= overhead;
+ elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable);
+ if (debug_mode) printf("%s:", msg);
+ while (spaces++ < 50) if (debug_mode) printf(" ");
+ if ((PRInt32)accountable < 0) {
+ if (debug_mode) printf("*****.** usecs/iteration\n");
+ } else {
+ if (debug_mode) printf("%8.2f usecs/iteration\n", elapsed/loops);
+ }
+ return duration;
+} /* Test */
+
+int main(int argc, char **argv)
+{
+ PRIntervalTime duration;
+ PRUint32 cpu, cpus = 2;
+ PRInt32 loops = 100;
+
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("lockfile.log");
+ debug_mode = 1;
+#endif
+
+ if (argc > 1) loops = atoi(argv[1]);
+ if (loops == 0) loops = 100;
+ if (debug_mode) printf("Lock: Using %d loops\n", loops);
+
+ cpus = (argc < 3) ? 2 : atoi(argv[2]);
+ if (cpus == 0) cpus = 2;
+ if (debug_mode) printf("Lock: Using %d cpu(s)\n", cpus);
+
+
+ for (cpu = 1; cpu <= cpus; ++cpu)
+ {
+ if (debug_mode) printf("\nLockFile: Using %d CPU(s)\n", cpu);
+ PR_SetConcurrency(cpu);
+
+ duration = Test("LockFile non-contentious locking/unlocking", NonContentiousLock, loops, 0);
+ (void)Test("LockFile contentious locking/unlocking", ContentiousLock, loops, duration);
+ }
+
+ PR_Delete(LOCKFILE); /* try to get rid of evidence */
+
+ if (debug_mode) printf("%s: test %s\n", "Lock(mutex) test", ((failed_already) ? "failed" : "passed"));
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+} /* main */
+
+/* testlock.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/logger.c b/src/libs/xpcom18a4/nsprpub/pr/tests/logger.c
new file mode 100644
index 00000000..58c55d3e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/logger.c
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: logger.c
+ * Description: test program for logging's basic functions
+ */
+
+#include "prinit.h"
+#include "prlog.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prthread.h"
+#include "prinrval.h"
+
+#include <stdio.h>
+
+#ifdef XP_MAC
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+/* lth. re-define PR_LOG() */
+#if 0
+#undef PR_LOG_TEST
+#undef PR_LOG
+#define PR_LOG_TEST(_module,_level) ((_module)->level <= (_level))
+#define PR_LOG(_module,_level,_args) \
+ { \
+ if (PR_LOG_TEST(_module,_level)) \
+ PR_LogPrint _args ; \
+ }
+#endif
+
+
+static void Error(const char* msg)
+{
+ printf("\t%s\n", msg);
+} /* Error */
+
+static void PR_CALLBACK forked(void *arg)
+{
+ PRIntn i;
+ PRLock *ml;
+ PRCondVar *cv;
+
+ PR_LogPrint("%s logging creating mutex\n", (const char*)arg);
+ ml = PR_NewLock();
+ PR_LogPrint("%s logging creating condition variable\n", (const char*)arg);
+ cv = PR_NewCondVar(ml);
+
+ PR_LogPrint("%s waiting on condition timeout 10 times\n", (const char*)arg);
+ for (i = 0; i < 10; ++i)
+ {
+ PR_Lock(ml);
+ PR_WaitCondVar(cv, PR_SecondsToInterval(1));
+ PR_Unlock(ml);
+ }
+
+ PR_LogPrint("%s logging destroying condition variable\n", (const char*)arg);
+ PR_DestroyCondVar(cv);
+ PR_LogPrint("%s logging destroying mutex\n", (const char*)arg);
+ PR_DestroyLock(ml);
+ PR_LogPrint("%s forked thread exiting\n", (const char*)arg);
+}
+
+static void UserLogStuff( void )
+{
+ PRLogModuleInfo *myLM;
+ PRIntn i;
+
+ myLM = PR_NewLogModule( "userStuff" );
+ if (! myLM )
+ {
+ printf("UserLogStuff(): can't create new log module\n" );
+ return;
+ }
+
+ PR_LOG( myLM, PR_LOG_NOTICE, ("Log a Notice %d\n", 1 ));
+
+ for (i = 0; i < 10 ; i++ )
+ {
+ PR_LOG( myLM, PR_LOG_DEBUG, ("Log Debug number: %d\n", i));
+ PR_Sleep( 300 );
+ }
+
+} /* end UserLogStuff() */
+
+int main(PRIntn argc, const char **argv)
+{
+ PRThread *thread;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifndef XP_MAC
+ if (argc > 1)
+ {
+ if (!PR_SetLogFile(argv[1]))
+ {
+ Error("Access: Cannot create log file");
+ goto exit;
+ }
+ }
+#else
+ SetupMacPrintfLog("logger.log");
+#endif
+
+ /* Start logging something here */
+ PR_LogPrint("%s logging into %s\n", argv[0], argv[1]);
+
+ PR_LogPrint("%s creating new thread\n", argv[0]);
+
+ /*
+ ** Now change buffering.
+ */
+ PR_SetLogBuffering( 65500 );
+ thread = PR_CreateThread(
+ PR_USER_THREAD, forked, (void*)argv[0], PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ PR_LogPrint("%s joining thread\n", argv[0]);
+
+ UserLogStuff();
+
+ PR_JoinThread(thread);
+
+ PR_LogFlush();
+ return 0;
+
+exit:
+ return -1;
+}
+
+/* logger.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/makedir.c b/src/libs/xpcom18a4/nsprpub/pr/tests/makedir.c
new file mode 100644
index 00000000..2720f13e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/makedir.c
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * This test calls PR_MakeDir to create a bunch of directories
+ * with various mode bits.
+ */
+
+#include "prio.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main()
+{
+ if (PR_MakeDir("tdir0400", 0400) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0200", 0200) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0100", 0100) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0500", 0500) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0600", 0600) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0300", 0300) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0700", 0700) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0640", 0640) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0660", 0660) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0644", 0644) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0664", 0664) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ if (PR_MakeDir("tdir0666", 0666) == PR_FAILURE) {
+ fprintf(stderr, "PR_MakeDir failed\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/many_cv.c b/src/libs/xpcom18a4/nsprpub/pr/tests/many_cv.c
new file mode 100644
index 00000000..c61b714d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/many_cv.c
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prprf.h"
+#include "prthread.h"
+#include "prcvar.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmem.h"
+
+#include "primpl.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+static PRInt32 Random(void)
+{
+ PRInt32 ran = rand() >> 16;
+ return ran;
+} /* Random */
+
+static void Help(void)
+{
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+ PR_fprintf(err, "many_cv usage: [-c n] [-l n] [-h]\n");
+ PR_fprintf(err, "\t-c n Number of conditions per lock (default: 10)\n");
+ PR_fprintf(err, "\t-l n Number of times to loop the test (default: 1)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ PLOptStatus os;
+ PRIntn index, nl;
+ PRLock *ml = NULL;
+ PRCondVar **cv = NULL;
+ PRBool stats = PR_FALSE;
+ PRIntn nc, loops = 1, cvs = 10;
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hsc:l:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 's': /* number of CVs to association with lock */
+ stats = PR_TRUE;
+ break;
+ case 'c': /* number of CVs to association with lock */
+ cvs = atoi(opt->value);
+ break;
+ case 'l': /* number of times to run the tests */
+ loops = atoi(opt->value);
+ break;
+ case 'h': /* user wants some guidance */
+ default:
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_fprintf(err, "Settings\n");
+ PR_fprintf(err, "\tConditions / lock: %d\n", cvs);
+ PR_fprintf(err, "\tLoops to run test: %d\n", loops);
+
+ ml = PR_NewLock();
+ PR_ASSERT(NULL != ml);
+
+ cv = (PRCondVar**)PR_CALLOC(sizeof(PRCondVar*) * cvs);
+ PR_ASSERT(NULL != cv);
+
+ for (index = 0; index < cvs; ++index)
+ {
+ cv[index] = PR_NewCondVar(ml);
+ PR_ASSERT(NULL != cv[index]);
+ }
+
+ for (index = 0; index < loops; ++index)
+ {
+ PR_Lock(ml);
+ for (nl = 0; nl < cvs; ++nl)
+ {
+ PRInt32 ran = Random() % 8;
+ if (0 == ran) PR_NotifyAllCondVar(cv[nl]);
+ else for (nc = 0; nc < ran; ++nc)
+ PR_NotifyCondVar(cv[nl]);
+ }
+ PR_Unlock(ml);
+ }
+
+ for (index = 0; index < cvs; ++index)
+ PR_DestroyCondVar(cv[index]);
+
+ PR_DELETE(cv);
+
+ PR_DestroyLock(ml);
+
+ printf("PASS\n");
+
+ PT_FPrintStats(err, "\nPThread Statistics\n");
+ return 0;
+}
+
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/mbcs.c b/src/libs/xpcom18a4/nsprpub/pr/tests/mbcs.c
new file mode 100644
index 00000000..7ab89118
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/mbcs.c
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: mbcs.c
+**
+** Synopsis: mbcs {dirName}
+**
+** where dirName is the directory to be traversed. dirName is required.
+**
+** Description:
+** mbcs.c tests use of multi-byte characters, as would be passed to
+** NSPR funtions by internationalized applications.
+**
+** mbcs.c, when run on any single-byte platform, should run correctly.
+** In truth, running the mbcs test on a single-byte platform is
+** really meaningless. mbcs.c, nor any NSPR library or test is not
+** intended for use with any wide character set, including Unicode.
+** mbcs.c should not be included in runtests.ksh because it requires
+** extensive user intervention to set-up and run.
+**
+** mbcs.c should be run on a platform using some form of multi-byte
+** characters. The initial platform for this test is a Japanese
+** language Windows NT 4.0 machine. ... Thank you Noriko Hoshi.
+**
+** To run mbcs.c, the tester should create a directory tree containing
+** some files in the same directory from which the test is run; i.e.
+** the current working directory. The directory and files should be
+** named such that when represented in the local multi-byte character
+** set, one or more characters of the name is longer than a single
+** byte.
+**
+*/
+
+#include <plgetopt.h>
+#include <nspr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** Test harness infrastructure
+*/
+PRLogModuleInfo *lm;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRIntn debug = 0;
+PRUint32 failed_already = 0;
+/* end Test harness infrastructure */
+
+char *dirName = NULL; /* directory name to traverse */
+
+/*
+** Traverse directory
+*/
+static void TraverseDirectory( unsigned char *dir )
+{
+ PRDir *cwd;
+ PRDirEntry *dirEntry;
+ PRFileInfo info;
+ PRStatus rc;
+ PRInt32 err;
+ PRFileDesc *fd;
+ char nextDir[256];
+ char file[256];
+
+ printf("Directory: %s\n", dir );
+ cwd = PR_OpenDir( dir );
+ if ( NULL == cwd ) {
+ printf("PR_OpenDir() failed on directory: %s, with error: %d, %d\n",
+ dir, PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ while( NULL != (dirEntry = PR_ReadDir( cwd, PR_SKIP_BOTH | PR_SKIP_HIDDEN ))) {
+ sprintf( file, "%s/%s", dir, dirEntry->name );
+ rc = PR_GetFileInfo( file, &info );
+ if ( PR_FAILURE == rc ) {
+ printf("PR_GetFileInfo() failed on file: %s, with error: %d, %d\n",
+ dirEntry->name, PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ if ( PR_FILE_FILE == info.type ) {
+ printf("File: %s \tsize: %ld\n", dirEntry->name, info.size );
+ fd = PR_Open( file, PR_RDONLY, 0 );
+ if ( NULL == fd ) {
+ printf("PR_Open() failed. Error: %ld, OSError: %ld\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ rc = PR_Close( fd );
+ if ( PR_FAILURE == rc ) {
+ printf("PR_Close() failed. Error: %ld, OSError: %ld\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ } else if ( PR_FILE_DIRECTORY == info.type ) {
+ sprintf( nextDir, "%s/%s", dir, dirEntry->name );
+ TraverseDirectory(nextDir);
+ } else {
+ printf("type is not interesting for file: %s\n", dirEntry->name );
+ /* keep going */
+ }
+ }
+ /* assume end-of-file, actually could be error */
+
+ rc = PR_CloseDir( cwd );
+ if ( PR_FAILURE == rc ) {
+ printf("PR_CloseDir() failed on directory: %s, with error: %d, %d\n",
+ dir, PR_GetError(), PR_GetOSError());
+ }
+
+} /* end TraverseDirectory() */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ { /* get command line options */
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dv");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ msgLevel = PR_LOG_ERROR;
+ break;
+ case 'v': /* verbose mode */
+ msgLevel = PR_LOG_DEBUG;
+ break;
+ default:
+ dirName = strdup(opt->value);
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ } /* end get command line options */
+
+ lm = PR_NewLogModule("Test"); /* Initialize logging */
+
+
+ if ( dirName == NULL ) {
+ printf("you gotta specify a directory as an operand!\n");
+ exit(1);
+ }
+
+ TraverseDirectory( dirName );
+
+ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS");
+ return( (failed_already == PR_TRUE )? 1 : 0 );
+} /* main() */
+/* end template.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/multiacc.c b/src/libs/xpcom18a4/nsprpub/pr/tests/multiacc.c
new file mode 100644
index 00000000..ccae270b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/multiacc.c
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: multiacc.c
+ *
+ * Description:
+ * This test creates multiple threads that accept on the
+ * same listening socket.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NUM_SERVER_THREADS 10
+
+static int num_server_threads = NUM_SERVER_THREADS;
+static PRThreadScope thread_scope = PR_GLOBAL_THREAD;
+static PRBool exit_flag = PR_FALSE;
+
+static void ServerThreadFunc(void *arg)
+{
+ PRFileDesc *listenSock = (PRFileDesc *) arg;
+ PRFileDesc *acceptSock;
+ PRErrorCode err;
+ PRStatus status;
+
+ while (!exit_flag) {
+ acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == acceptSock) {
+ err = PR_GetError();
+ if (PR_PENDING_INTERRUPT_ERROR == err) {
+ printf("server thread is interrupted\n");
+ fflush(stdout);
+ continue;
+ }
+ fprintf(stderr, "PR_Accept failed: %d\n", err);
+ exit(1);
+ }
+ status = PR_Close(acceptSock);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRNetAddr serverAddr;
+ PRFileDesc *dummySock;
+ PRFileDesc *listenSock;
+ PRFileDesc *clientSock;
+ PRThread *dummyThread;
+ PRThread **serverThreads;
+ PRStatus status;
+ PRUint16 port;
+ int idx;
+ PRInt32 nbytes;
+ char buf[1024];
+
+ serverThreads = (PRThread **)
+ PR_Malloc(num_server_threads * sizeof(PRThread *));
+ if (NULL == serverThreads) {
+ fprintf(stderr, "PR_Malloc failed\n");
+ exit(1);
+ }
+
+ /*
+ * Create a dummy listening socket and have the first
+ * (dummy) thread listen on it. This is to ensure that
+ * the first thread becomes the I/O continuation thread
+ * in the pthreads implementation (see ptio.c) and remains
+ * so throughout the test, so that we never have to
+ * recycle the I/O continuation thread.
+ */
+ dummySock = PR_NewTCPSocket();
+ if (NULL == dummySock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&serverAddr, 0, sizeof(serverAddr));
+ status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ status = PR_Bind(dummySock, &serverAddr);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ status = PR_Listen(dummySock, 5);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ listenSock = PR_NewTCPSocket();
+ if (NULL == listenSock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&serverAddr, 0, sizeof(serverAddr));
+ status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ status = PR_Bind(listenSock, &serverAddr);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ status = PR_GetSockName(listenSock, &serverAddr);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ port = PR_ntohs(serverAddr.inet.port);
+ status = PR_Listen(listenSock, 5);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ printf("creating dummy thread\n");
+ fflush(stdout);
+ dummyThread = PR_CreateThread(PR_USER_THREAD,
+ ServerThreadFunc, dummySock, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == dummyThread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ printf("sleeping one second before creating server threads\n");
+ fflush(stdout);
+ PR_Sleep(PR_SecondsToInterval(1));
+ for (idx = 0; idx < num_server_threads; idx++) {
+ serverThreads[idx] = PR_CreateThread(PR_USER_THREAD,
+ ServerThreadFunc, listenSock, PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == serverThreads[idx]) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ }
+
+ memset(&serverAddr, 0, sizeof(serverAddr));
+ PR_InitializeNetAddr(PR_IpAddrLoopback, port, &serverAddr);
+ clientSock = PR_NewTCPSocket();
+ if (NULL == clientSock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ printf("sleeping one second before connecting\n");
+ fflush(stdout);
+ PR_Sleep(PR_SecondsToInterval(1));
+ status = PR_Connect(clientSock, &serverAddr, PR_INTERVAL_NO_TIMEOUT);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Connect failed\n");
+ exit(1);
+ }
+ nbytes = PR_Read(clientSock, buf, sizeof(buf));
+ if (nbytes != 0) {
+ fprintf(stderr, "expected 0 bytes but got %d bytes\n", nbytes);
+ exit(1);
+ }
+ status = PR_Close(clientSock);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ printf("sleeping one second before shutting down server threads\n");
+ fflush(stdout);
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ exit_flag = PR_TRUE;
+ status = PR_Interrupt(dummyThread);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Interrupt failed\n");
+ exit(1);
+ }
+ status = PR_JoinThread(dummyThread);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ for (idx = 0; idx < num_server_threads; idx++) {
+ status = PR_Interrupt(serverThreads[idx]);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Interrupt failed\n");
+ exit(1);
+ }
+ status = PR_JoinThread(serverThreads[idx]);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ }
+ PR_Free(serverThreads);
+ status = PR_Close(dummySock);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(listenSock);
+ if (PR_FAILURE == status) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/multiwait.c b/src/libs/xpcom18a4/nsprpub/pr/tests/multiwait.c
new file mode 100644
index 00000000..10e22dad
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/multiwait.c
@@ -0,0 +1,725 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "pratom.h"
+#include "prlock.h"
+#include "prmwait.h"
+#include "prclist.h"
+#include "prerror.h"
+#include "prinrval.h"
+#include "prnetdb.h"
+#include "prthread.h"
+
+#include "plstr.h"
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <string.h>
+
+typedef struct Shared
+{
+ const char *title;
+ PRLock *list_lock;
+ PRWaitGroup *group;
+ PRIntervalTime timeout;
+} Shared;
+
+typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
+
+static PRFileDesc *debug = NULL;
+static PRInt32 desc_allocated = 0;
+static PRUint16 default_port = 12273;
+static enum Verbosity verbosity = quiet;
+static PRInt32 ops_required = 1000, ops_done = 0;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+static PRIntn client_threads = 20, worker_threads = 2, wait_objects = 50;
+
+#if defined(DEBUG)
+#define MW_ASSERT(_expr) \
+ ((_expr)?((void)0):_MW_Assert(# _expr,__FILE__,__LINE__))
+static void _MW_Assert(const char *s, const char *file, PRIntn ln)
+{
+ if (NULL != debug) PL_FPrintError(debug, NULL);
+ PR_Assert(s, file, ln);
+} /* _MW_Assert */
+#else
+#define MW_ASSERT(_expr)
+#endif
+
+static void PrintRecvDesc(PRRecvWait *desc, const char *msg)
+{
+ const char *tag[] = {
+ "PR_MW_INTERRUPT", "PR_MW_TIMEOUT",
+ "PR_MW_FAILURE", "PR_MW_SUCCESS", "PR_MW_PENDING"};
+ PR_fprintf(
+ debug, "%s: PRRecvWait(@0x%x): {fd: 0x%x, outcome: %s, tmo: %u}\n",
+ msg, desc, desc->fd, tag[desc->outcome + 3], desc->timeout);
+} /* PrintRecvDesc */
+
+static Shared *MakeShared(const char *title)
+{
+ Shared *shared = PR_NEWZAP(Shared);
+ shared->group = PR_CreateWaitGroup(1);
+ shared->timeout = PR_SecondsToInterval(1);
+ shared->list_lock = PR_NewLock();
+ shared->title = title;
+ return shared;
+} /* MakeShared */
+
+static void DestroyShared(Shared *shared)
+{
+ PRStatus rv;
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: destroying group\n", shared->title);
+ rv = PR_DestroyWaitGroup(shared->group);
+ MW_ASSERT(PR_SUCCESS == rv);
+ PR_DestroyLock(shared->list_lock);
+ PR_DELETE(shared);
+} /* DestroyShared */
+
+static PRRecvWait *CreateRecvWait(PRFileDesc *fd, PRIntervalTime timeout)
+{
+ PRRecvWait *desc_out = PR_NEWZAP(PRRecvWait);
+ MW_ASSERT(NULL != desc_out);
+
+ MW_ASSERT(NULL != fd);
+ desc_out->fd = fd;
+ desc_out->timeout = timeout;
+ desc_out->buffer.length = 120;
+ desc_out->buffer.start = PR_CALLOC(120);
+
+ PR_AtomicIncrement(&desc_allocated);
+
+ if (verbosity > chatty)
+ PrintRecvDesc(desc_out, "Allocated");
+ return desc_out;
+} /* CreateRecvWait */
+
+static void DestroyRecvWait(PRRecvWait *desc_out)
+{
+ if (verbosity > chatty)
+ PrintRecvDesc(desc_out, "Destroying");
+ PR_Close(desc_out->fd);
+ if (NULL != desc_out->buffer.start)
+ PR_DELETE(desc_out->buffer.start);
+ PR_Free(desc_out);
+ (void)PR_AtomicDecrement(&desc_allocated);
+} /* DestroyRecvWait */
+
+static void CancelGroup(Shared *shared)
+{
+ PRRecvWait *desc_out;
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s Reclaiming wait descriptors\n", shared->title);
+
+ do
+ {
+ desc_out = PR_CancelWaitGroup(shared->group);
+ if (NULL != desc_out) DestroyRecvWait(desc_out);
+ } while (NULL != desc_out);
+
+ MW_ASSERT(0 == desc_allocated);
+ MW_ASSERT(PR_GROUP_EMPTY_ERROR == PR_GetError());
+} /* CancelGroup */
+
+static void PR_CALLBACK ClientThread(void* arg)
+{
+ PRStatus rv;
+ PRInt32 bytes;
+ PRIntn empty_flags = 0;
+ PRNetAddr server_address;
+ unsigned char buffer[100];
+ Shared *shared = (Shared*)arg;
+ PRFileDesc *server = PR_NewTCPSocket();
+ if ((NULL == server)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) return;
+ MW_ASSERT(NULL != server);
+
+ if (verbosity > chatty)
+ PR_fprintf(debug, "%s: Server socket @0x%x\n", shared->title, server);
+
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buffer, 0, sizeof(buffer));
+
+ rv = PR_InitializeNetAddr(PR_IpAddrLoopback, default_port, &server_address);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: Client opening connection\n", shared->title);
+ rv = PR_Connect(server, &server_address, PR_INTERVAL_NO_TIMEOUT);
+
+ if (PR_FAILURE == rv)
+ {
+ if (verbosity > silent) PL_FPrintError(debug, "Client connect failed");
+ return;
+ }
+
+ while (ops_done < ops_required)
+ {
+ bytes = PR_Send(
+ server, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if ((-1 == bytes) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
+ MW_ASSERT(sizeof(buffer) == bytes);
+ if (verbosity > chatty)
+ PR_fprintf(
+ debug, "%s: Client sent %d bytes\n",
+ shared->title, sizeof(buffer));
+ bytes = PR_Recv(
+ server, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(
+ debug, "%s: Client received %d bytes\n",
+ shared->title, sizeof(buffer));
+ if ((-1 == bytes) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
+ MW_ASSERT(sizeof(buffer) == bytes);
+ PR_Sleep(shared->timeout);
+ }
+ rv = PR_Close(server);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+} /* ClientThread */
+
+static void OneInThenCancelled(Shared *shared)
+{
+ PRStatus rv;
+ PRRecvWait *desc_out, *desc_in = PR_NEWZAP(PRRecvWait);
+
+ shared->timeout = PR_INTERVAL_NO_TIMEOUT;
+
+ desc_in->fd = PR_NewTCPSocket();
+ desc_in->timeout = shared->timeout;
+
+ if (verbosity > chatty) PrintRecvDesc(desc_in, "Adding desc");
+
+ rv = PR_AddWaitFileDesc(shared->group, desc_in);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ if (verbosity > chatty) PrintRecvDesc(desc_in, "Cancelling");
+ rv = PR_CancelWaitFileDesc(shared->group, desc_in);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ desc_out = PR_WaitRecvReady(shared->group);
+ MW_ASSERT(desc_out == desc_in);
+ MW_ASSERT(PR_MW_INTERRUPT == desc_out->outcome);
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+ if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready");
+
+ rv = PR_Close(desc_in->fd);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: destroying group\n", shared->title);
+
+ PR_DELETE(desc_in);
+} /* OneInThenCancelled */
+
+static void OneOpOneThread(Shared *shared)
+{
+ PRStatus rv;
+ PRRecvWait *desc_out, *desc_in = PR_NEWZAP(PRRecvWait);
+
+ desc_in->fd = PR_NewTCPSocket();
+ desc_in->timeout = shared->timeout;
+
+ if (verbosity > chatty) PrintRecvDesc(desc_in, "Adding desc");
+
+ rv = PR_AddWaitFileDesc(shared->group, desc_in);
+ MW_ASSERT(PR_SUCCESS == rv);
+ desc_out = PR_WaitRecvReady(shared->group);
+ MW_ASSERT(desc_out == desc_in);
+ MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome);
+ MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError());
+ if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready");
+
+ rv = PR_Close(desc_in->fd);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ PR_DELETE(desc_in);
+} /* OneOpOneThread */
+
+static void ManyOpOneThread(Shared *shared)
+{
+ PRStatus rv;
+ PRIntn index;
+ PRRecvWait *desc_in;
+ PRRecvWait *desc_out;
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: adding %d descs\n", shared->title, wait_objects);
+
+ for (index = 0; index < wait_objects; ++index)
+ {
+ desc_in = CreateRecvWait(PR_NewTCPSocket(), shared->timeout);
+
+ rv = PR_AddWaitFileDesc(shared->group, desc_in);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+
+ while (ops_done < ops_required)
+ {
+ desc_out = PR_WaitRecvReady(shared->group);
+ MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome);
+ MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError());
+ if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready/readding");
+ rv = PR_AddWaitFileDesc(shared->group, desc_out);
+ MW_ASSERT(PR_SUCCESS == rv);
+ (void)PR_AtomicIncrement(&ops_done);
+ }
+
+ CancelGroup(shared);
+} /* ManyOpOneThread */
+
+static void PR_CALLBACK SomeOpsThread(void *arg)
+{
+ PRRecvWait *desc_out;
+ PRStatus rv = PR_SUCCESS;
+ Shared *shared = (Shared*)arg;
+ do /* until interrupted */
+ {
+ desc_out = PR_WaitRecvReady(shared->group);
+ if (NULL == desc_out)
+ {
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+ if (verbosity > quiet) PR_fprintf(debug, "Aborted\n");
+ break;
+ }
+ MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome);
+ MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError());
+ if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready");
+
+ if (verbosity > chatty) PrintRecvDesc(desc_out, "Re-Adding");
+ desc_out->timeout = shared->timeout;
+ rv = PR_AddWaitFileDesc(shared->group, desc_out);
+ PR_AtomicIncrement(&ops_done);
+ if (ops_done > ops_required) break;
+ } while (PR_SUCCESS == rv);
+ MW_ASSERT(PR_SUCCESS == rv);
+} /* SomeOpsThread */
+
+static void SomeOpsSomeThreads(Shared *shared)
+{
+ PRStatus rv;
+ PRThread **thread;
+ PRIntn index;
+ PRRecvWait *desc_in;
+
+ thread = (PRThread**)PR_CALLOC(sizeof(PRThread*) * worker_threads);
+
+ /* Create some threads */
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating threads\n", shared->title);
+ for (index = 0; index < worker_threads; ++index)
+ {
+ thread[index] = PR_CreateThread(
+ PR_USER_THREAD, SomeOpsThread, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ }
+
+ /* then create some operations */
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating desc\n", shared->title);
+ for (index = 0; index < wait_objects; ++index)
+ {
+ desc_in = CreateRecvWait(PR_NewTCPSocket(), shared->timeout);
+ rv = PR_AddWaitFileDesc(shared->group, desc_in);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: sleeping\n", shared->title);
+ while (ops_done < ops_required) PR_Sleep(shared->timeout);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: interrupting/joining threads\n", shared->title);
+ for (index = 0; index < worker_threads; ++index)
+ {
+ rv = PR_Interrupt(thread[index]);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(thread[index]);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+ PR_DELETE(thread);
+
+ CancelGroup(shared);
+} /* SomeOpsSomeThreads */
+
+static PRStatus ServiceRequest(Shared *shared, PRRecvWait *desc)
+{
+ PRInt32 bytes_out;
+
+ if (verbosity > chatty)
+ PR_fprintf(
+ debug, "%s: Service received %d bytes\n",
+ shared->title, desc->bytesRecv);
+
+ if (0 == desc->bytesRecv) goto quitting;
+ if ((-1 == desc->bytesRecv)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) goto aborted;
+
+ bytes_out = PR_Send(
+ desc->fd, desc->buffer.start, desc->bytesRecv, 0, shared->timeout);
+ if (verbosity > chatty)
+ PR_fprintf(
+ debug, "%s: Service sent %d bytes\n",
+ shared->title, bytes_out);
+
+ if ((-1 == bytes_out)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) goto aborted;
+ MW_ASSERT(bytes_out == desc->bytesRecv);
+
+ return PR_SUCCESS;
+
+aborted:
+quitting:
+ return PR_FAILURE;
+} /* ServiceRequest */
+
+static void PR_CALLBACK ServiceThread(void *arg)
+{
+ PRStatus rv = PR_SUCCESS;
+ PRRecvWait *desc_out = NULL;
+ Shared *shared = (Shared*)arg;
+ do /* until interrupted */
+ {
+ if (NULL != desc_out)
+ {
+ desc_out->timeout = PR_INTERVAL_NO_TIMEOUT;
+ if (verbosity > chatty)
+ PrintRecvDesc(desc_out, "Service re-adding");
+ rv = PR_AddWaitFileDesc(shared->group, desc_out);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+
+ desc_out = PR_WaitRecvReady(shared->group);
+ if (NULL == desc_out)
+ {
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+ break;
+ }
+
+ switch (desc_out->outcome)
+ {
+ case PR_MW_SUCCESS:
+ {
+ PR_AtomicIncrement(&ops_done);
+ if (verbosity > chatty)
+ PrintRecvDesc(desc_out, "Service ready");
+ rv = ServiceRequest(shared, desc_out);
+ break;
+ }
+ case PR_MW_INTERRUPT:
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+ rv = PR_FAILURE; /* if interrupted, then exit */
+ break;
+ case PR_MW_TIMEOUT:
+ MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError());
+ case PR_MW_FAILURE:
+ if (verbosity > silent)
+ PL_FPrintError(debug, "RecvReady failure");
+ break;
+ default:
+ break;
+ }
+ } while (PR_SUCCESS == rv);
+
+ if (NULL != desc_out) DestroyRecvWait(desc_out);
+
+} /* ServiceThread */
+
+static void PR_CALLBACK EnumerationThread(void *arg)
+{
+ PRStatus rv;
+ PRIntn count;
+ PRRecvWait *desc;
+ Shared *shared = (Shared*)arg;
+ PRIntervalTime five_seconds = PR_SecondsToInterval(5);
+ PRMWaitEnumerator *enumerator = PR_CreateMWaitEnumerator(shared->group);
+ MW_ASSERT(NULL != enumerator);
+
+ while (PR_SUCCESS == PR_Sleep(five_seconds))
+ {
+ count = 0;
+ desc = NULL;
+ while (NULL != (desc = PR_EnumerateWaitGroup(enumerator, desc)))
+ {
+ if (verbosity > chatty) PrintRecvDesc(desc, shared->title);
+ count += 1;
+ }
+ if (verbosity > silent)
+ PR_fprintf(debug,
+ "%s Enumerated %d objects\n", shared->title, count);
+ }
+
+ MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError());
+
+
+ rv = PR_DestroyMWaitEnumerator(enumerator);
+ MW_ASSERT(PR_SUCCESS == rv);
+} /* EnumerationThread */
+
+static void PR_CALLBACK ServerThread(void *arg)
+{
+ PRStatus rv;
+ PRIntn index;
+ PRRecvWait *desc_in;
+ PRThread **worker_thread;
+ Shared *shared = (Shared*)arg;
+ PRFileDesc *listener, *service;
+ PRNetAddr server_address, client_address;
+
+ worker_thread = (PRThread**)PR_CALLOC(sizeof(PRThread*) * worker_threads);
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: Server creating worker_threads\n", shared->title);
+ for (index = 0; index < worker_threads; ++index)
+ {
+ worker_thread[index] = PR_CreateThread(
+ PR_USER_THREAD, ServiceThread, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ }
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &server_address);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ listener = PR_NewTCPSocket(); MW_ASSERT(NULL != listener);
+ if (verbosity > chatty)
+ PR_fprintf(
+ debug, "%s: Server listener socket @0x%x\n",
+ shared->title, listener);
+ rv = PR_Bind(listener, &server_address); MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Listen(listener, 10); MW_ASSERT(PR_SUCCESS == rv);
+ while (ops_done < ops_required)
+ {
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: Server accepting connection\n", shared->title);
+ service = PR_Accept(listener, &client_address, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == service)
+ {
+ if (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) break;
+ PL_PrintError("Accept failed");
+ MW_ASSERT(!"Accept failed");
+ }
+ else
+ {
+ desc_in = CreateRecvWait(service, shared->timeout);
+ desc_in->timeout = PR_INTERVAL_NO_TIMEOUT;
+ if (verbosity > chatty)
+ PrintRecvDesc(desc_in, "Service adding");
+ rv = PR_AddWaitFileDesc(shared->group, desc_in);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+ }
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: Server interrupting worker_threads\n", shared->title);
+ for (index = 0; index < worker_threads; ++index)
+ {
+ rv = PR_Interrupt(worker_thread[index]);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(worker_thread[index]);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+ PR_DELETE(worker_thread);
+
+ PR_Close(listener);
+
+ CancelGroup(shared);
+
+} /* ServerThread */
+
+static void RealOneGroupIO(Shared *shared)
+{
+ /*
+ ** Create a server that listens for connections and then services
+ ** requests that come in over those connections. The server never
+ ** deletes a connection and assumes a basic RPC model of operation.
+ **
+ ** Use worker_threads threads to service how every many open ports
+ ** there might be.
+ **
+ ** Oh, ya. Almost forget. Create (some) clients as well.
+ */
+ PRStatus rv;
+ PRIntn index;
+ PRThread *server_thread, *enumeration_thread, **client_thread;
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating server_thread\n", shared->title);
+
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, ServerThread, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating enumeration_thread\n", shared->title);
+
+ enumeration_thread = PR_CreateThread(
+ PR_USER_THREAD, EnumerationThread, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: snoozing before creating clients\n", shared->title);
+ PR_Sleep(5 * shared->timeout);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: creating client_threads\n", shared->title);
+ client_thread = (PRThread**)PR_CALLOC(sizeof(PRThread*) * client_threads);
+ for (index = 0; index < client_threads; ++index)
+ {
+ client_thread[index] = PR_CreateThread(
+ PR_USER_THREAD, ClientThread, shared,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ }
+
+ while (ops_done < ops_required) PR_Sleep(shared->timeout);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: interrupting/joining client_threads\n", shared->title);
+ for (index = 0; index < client_threads; ++index)
+ {
+ rv = PR_Interrupt(client_thread[index]);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(client_thread[index]);
+ MW_ASSERT(PR_SUCCESS == rv);
+ }
+ PR_DELETE(client_thread);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: interrupting/joining enumeration_thread\n", shared->title);
+ rv = PR_Interrupt(enumeration_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(enumeration_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+
+ if (verbosity > quiet)
+ PR_fprintf(debug, "%s: interrupting/joining server_thread\n", shared->title);
+ rv = PR_Interrupt(server_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(server_thread);
+ MW_ASSERT(PR_SUCCESS == rv);
+} /* RealOneGroupIO */
+
+static void RunThisOne(
+ void (*func)(Shared*), const char *name, const char *test_name)
+{
+ Shared *shared;
+ if ((NULL == test_name) || (0 == PL_strcmp(name, test_name)))
+ {
+ if (verbosity > silent)
+ PR_fprintf(debug, "%s()\n", name);
+ shared = MakeShared(name);
+ ops_done = 0;
+ func(shared); /* run the test */
+ MW_ASSERT(0 == desc_allocated);
+ DestroyShared(shared);
+ }
+} /* RunThisOne */
+
+static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
+{
+ PRIntn verbage = (PRIntn)verbosity;
+ return (Verbosity)(verbage += delta);
+} /* ChangeVerbosity */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ const char *test_name = NULL;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dqGc:o:p:t:w:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0:
+ test_name = opt->value;
+ break;
+ case 'd': /* debug mode */
+ if (verbosity < noisy)
+ verbosity = ChangeVerbosity(verbosity, 1);
+ break;
+ case 'q': /* debug mode */
+ if (verbosity > silent)
+ verbosity = ChangeVerbosity(verbosity, -1);
+ break;
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'c': /* number of client threads */
+ client_threads = atoi(opt->value);
+ break;
+ case 'o': /* operations to compelete */
+ ops_required = atoi(opt->value);
+ break;
+ case 'p': /* default port */
+ default_port = atoi(opt->value);
+ break;
+ case 't': /* number of threads waiting */
+ worker_threads = atoi(opt->value);
+ break;
+ case 'w': /* number of wait objects */
+ wait_objects = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (verbosity > 0)
+ debug = PR_GetSpecialFD(PR_StandardError);
+
+ RunThisOne(OneInThenCancelled, "OneInThenCancelled", test_name);
+ RunThisOne(OneOpOneThread, "OneOpOneThread", test_name);
+ RunThisOne(ManyOpOneThread, "ManyOpOneThread", test_name);
+ RunThisOne(SomeOpsSomeThreads, "SomeOpsSomeThreads", test_name);
+ RunThisOne(RealOneGroupIO, "RealOneGroupIO", test_name);
+ return 0;
+} /* main */
+
+/* multwait.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/nameshm1.c b/src/libs/xpcom18a4/nsprpub/pr/tests/nameshm1.c
new file mode 100644
index 00000000..e70f0e2a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/nameshm1.c
@@ -0,0 +1,599 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: nameshm1.c -- Test Named Shared Memory
+**
+** Description:
+** nameshm1 tests Named Shared Memory. nameshm1 performs two tests of
+** named shared memory.
+**
+** The first test is a basic test. The basic test operates as a single
+** process. The process exercises all the API elements of the facility.
+** This test also attempts to write to all locations in the shared
+** memory.
+**
+** The second test is a client-server test. The client-server test
+** creates a new instance of nameshm1, passing the -C argument to the
+** new process; this creates the client-side process. The server-side
+** (the instance of nameshm1 created from the command line) and the
+** client-side interact via inter-process semaphores to verify that the
+** shared memory segment can be read and written by both sides in a
+** synchronized maner.
+**
+** Note: Because this test runs in two processes, the log files created
+** by the test are not in chronological sequence; makes it hard to read.
+** As a temporary circumvention, I changed the definition(s) of the
+** _PUT_LOG() macro in prlog.c to force a flushall(), or equivalent.
+** This causes the log entries to be emitted in true chronological
+** order.
+**
+** Synopsis: nameshm1 [options] [name]
+**
+** Options:
+** -d Enables debug trace via PR_LOG()
+** -v Enables verbose mode debug trace via PR_LOG()
+** -w Causes the basic test to attempt to write to the segment
+** mapped as read-only. When this option is specified, the
+** test should crash with a seg-fault; this is a destructive
+** test and is considered successful when it seg-faults.
+**
+** -C Causes nameshm1 to start as the client-side of a
+** client-server pair of processes. Only the instance
+** of nameshm1 operating as the server-side process should
+** specify the -C option when creating the client-side process;
+** the -C option should not be specified at the command line.
+** The client-side uses the shared memory segment created by
+** the server-side to communicate with the server-side
+** process.
+**
+** -p <n> Specify the number of iterations the client-server tests
+** should perform. Default: 1000.
+**
+** -s <n> Size, in KBytes (1024), of the shared memory segment.
+** Default: (10 * 1024)
+**
+** -i <n> Number of client-side iterations. Default: 3
+**
+** name specifies the name of the shared memory segment to be used.
+** Default: /tmp/xxxNSPRshm
+**
+**
+** See also: prshm.h
+**
+** /lth. Aug-1999.
+*/
+
+#include <plgetopt.h>
+#include <nspr.h>
+#include <stdlib.h>
+#include <string.h>
+#include <private/primpl.h>
+
+#define SEM_NAME1 "/tmp/nameshmSEM1"
+#define SEM_NAME2 "/tmp/nameshmSEM2"
+#define SEM_MODE 0666
+#define SHM_MODE 0666
+
+#define NameSize (1024)
+
+PRIntn debug = 0;
+PRIntn failed_already = 0;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRLogModuleInfo *lm;
+
+/* command line options */
+PRIntn optDebug = 0;
+PRIntn optVerbose = 0;
+PRUint32 optWriteRO = 0; /* test write to read-only memory. should crash */
+PRUint32 optClient = 0;
+PRUint32 optCreate = 1;
+PRUint32 optAttachRW = 1;
+PRUint32 optAttachRO = 1;
+PRUint32 optClose = 1;
+PRUint32 optDelete = 1;
+PRInt32 optPing = 1000;
+PRUint32 optSize = (10 * 1024 );
+PRInt32 optClientIterations = 3;
+char optName[NameSize] = "/tmp/xxxNSPRshm";
+
+char buf[1024] = "";
+
+
+static void BasicTest( void )
+{
+ PRSharedMemory *shm;
+ char *addr; /* address of shared memory segment */
+ PRUint32 i;
+ PRInt32 rc;
+
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Begin BasicTest" ));
+
+ if ( PR_FAILURE == PR_DeleteSharedMemory( optName )) {
+ PR_LOG( lm, msgLevel,
+ ("nameshm1: Initial PR_DeleteSharedMemory() failed. No problem"));
+ } else
+ PR_LOG( lm, msgLevel,
+ ("nameshm1: Initial PR_DeleteSharedMemory() success"));
+
+
+ shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE );
+ if ( NULL == shm )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Create: success: %p", shm ));
+
+ addr = PR_AttachSharedMemory( shm , 0 );
+ if ( NULL == addr )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Attach: success: %p", addr ));
+
+ /* fill memory with i */
+ for ( i = 0; i < optSize ; i++ )
+ {
+ *(addr + i) = i;
+ }
+
+ rc = PR_DetachSharedMemory( shm, addr );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Detach: success: " ));
+
+ rc = PR_CloseSharedMemory( shm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Close: success: " ));
+
+ rc = PR_DeleteSharedMemory( optName );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Delete: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RW Delete: success: " ));
+
+ PR_LOG( lm, msgLevel,
+ ("nameshm1: BasicTest(): Passed"));
+
+ return;
+} /* end BasicTest() */
+
+static void ReadOnlyTest( void )
+{
+ PRSharedMemory *shm;
+ char *roAddr; /* read-only address of shared memory segment */
+ PRInt32 rc;
+
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Begin ReadOnlyTest" ));
+
+ shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE);
+ if ( NULL == shm )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Create: success: %p", shm ));
+
+
+ roAddr = PR_AttachSharedMemory( shm , PR_SHM_READONLY );
+ if ( NULL == roAddr )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Attach: success: %p", roAddr ));
+
+ if ( optWriteRO )
+ {
+ *roAddr = 0x00; /* write to read-only memory */
+ failed_already = 1;
+ PR_LOG( lm, msgLevel, ("nameshm1: Wrote to read-only memory segment!"));
+ return;
+ }
+
+ rc = PR_DetachSharedMemory( shm, roAddr );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Detach: success: " ));
+
+ rc = PR_CloseSharedMemory( shm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Close: success: " ));
+
+ rc = PR_DeleteSharedMemory( optName );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Destroy: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: RO Destroy: success: " ));
+
+ PR_LOG( lm, msgLevel,
+ ("nameshm1: ReadOnlyTest(): Passed"));
+
+ return;
+} /* end ReadOnlyTest() */
+
+static void DoClient( void )
+{
+ PRStatus rc;
+ PRSem *sem1, *sem2;
+ PRSharedMemory *shm;
+ PRUint32 *addr;
+ PRInt32 i;
+
+ PR_LOG( lm, msgLevel,
+ ("nameshm1: DoClient(): Starting"));
+
+ sem1 = PR_OpenSemaphore( SEM_NAME1, 0, 0, 0 );
+ PR_ASSERT( sem1 );
+
+ sem2 = PR_OpenSemaphore( SEM_NAME2, 0, 0, 0 );
+ PR_ASSERT( sem1 );
+
+ shm = PR_OpenSharedMemory( optName, optSize, 0, SHM_MODE );
+ if ( NULL == shm )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Create: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Create: success: %p", shm ));
+
+ addr = PR_AttachSharedMemory( shm , 0 );
+ if ( NULL == addr )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Attach: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Attach: success: %p", addr ));
+
+ PR_LOG( lm, msgLevel,
+ ( "Client found: %s", addr));
+
+ PR_Sleep(PR_SecondsToInterval(4));
+ for ( i = 0 ; i < optPing ; i++ )
+ {
+ rc = PR_WaitSemaphore( sem2 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ (*addr)++;
+ PR_ASSERT( (*addr % 2) == 0 );
+ if ( optVerbose )
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Client ping: %d, i: %d", *addr, i));
+
+ rc = PR_PostSemaphore( sem1 );
+ PR_ASSERT( PR_FAILURE != rc );
+ }
+
+ rc = PR_CloseSemaphore( sem1 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_CloseSemaphore( sem2 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_DetachSharedMemory( shm, addr );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Detach: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Detach: success: " ));
+
+ rc = PR_CloseSharedMemory( shm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Close: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: DoClient(): Close: success: " ));
+
+ return;
+} /* end DoClient() */
+
+static void ClientServerTest( void )
+{
+ PRStatus rc;
+ PRSem *sem1, *sem2;
+ PRProcess *proc;
+ PRInt32 exit_status;
+ PRSharedMemory *shm;
+ PRUint32 *addr;
+ PRInt32 i;
+ char *child_argv[8];
+ char buf[24];
+
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Begin ClientServerTest" ));
+
+ rc = PR_DeleteSharedMemory( optName );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Destroy: failed. No problem"));
+ } else
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Destroy: success" ));
+
+
+ shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE);
+ if ( NULL == shm )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Create: success: %p", shm ));
+
+ addr = PR_AttachSharedMemory( shm , 0 );
+ if ( NULL == addr )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Attach: success: %p", addr ));
+
+ sem1 = PR_OpenSemaphore( SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0 );
+ PR_ASSERT( sem1 );
+
+ sem2 = PR_OpenSemaphore( SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 1 );
+ PR_ASSERT( sem1 );
+
+ strcpy( (char*)addr, "FooBar" );
+
+ child_argv[0] = "nameshm1";
+ child_argv[1] = "-C";
+ child_argv[2] = "-p";
+ sprintf( buf, "%d", optPing );
+ child_argv[3] = buf;
+ child_argv[4] = optName;
+ child_argv[5] = NULL;
+
+ proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
+ PR_ASSERT( proc );
+
+ PR_Sleep( PR_SecondsToInterval(4));
+
+ *addr = 1;
+ for ( i = 0 ; i < optPing ; i++ )
+ {
+ rc = PR_WaitSemaphore( sem1 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ (*addr)++;
+ PR_ASSERT( (*addr % 2) == 1 );
+ if ( optVerbose )
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server pong: %d, i: %d", *addr, i));
+
+
+ rc = PR_PostSemaphore( sem2 );
+ PR_ASSERT( PR_FAILURE != rc );
+ }
+
+ rc = PR_WaitProcess( proc, &exit_status );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_CloseSemaphore( sem1 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_CloseSemaphore( sem2 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_DeleteSemaphore( SEM_NAME1 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_DeleteSemaphore( SEM_NAME2 );
+ PR_ASSERT( PR_FAILURE != rc );
+
+ rc = PR_DetachSharedMemory( shm, addr );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Detach: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Detach: success: " ));
+
+ rc = PR_CloseSharedMemory( shm );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Close: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Close: success: " ));
+
+ rc = PR_DeleteSharedMemory( optName );
+ if ( PR_FAILURE == rc )
+ {
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Destroy: Error: %ld. OSError: %ld",
+ PR_GetError(), PR_GetOSError()));
+ failed_already = 1;
+ return;
+ }
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Server: Destroy: success" ));
+
+ return;
+} /* end ClientServerTest() */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ {
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Cdvw:s:p:i:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* debug mode */
+ optVerbose = 1;
+ /* no break! fall into debug option */
+ case 'd': /* debug mode */
+ debug = 1;
+ msgLevel = PR_LOG_DEBUG;
+ break;
+ case 'w': /* try writing to memory mapped read-only */
+ optWriteRO = 1;
+ break;
+ case 'C':
+ optClient = 1;
+ break;
+ case 's':
+ optSize = atol(opt->value) * 1024;
+ break;
+ case 'p':
+ optPing = atol(opt->value);
+ break;
+ case 'i':
+ optClientIterations = atol(opt->value);
+ break;
+ default:
+ strcpy( optName, opt->value );
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ lm = PR_NewLogModule("Test"); /* Initialize logging */
+
+ PR_LOG( lm, msgLevel,
+ ( "nameshm1: Starting" ));
+
+ if ( optClient )
+ {
+ DoClient();
+ } else {
+ BasicTest();
+ if ( failed_already != 0 )
+ goto Finished;
+ ReadOnlyTest();
+ if ( failed_already != 0 )
+ goto Finished;
+ ClientServerTest();
+ }
+
+Finished:
+ if ( debug ) printf("%s\n", (failed_already)? "FAIL" : "PASS" );
+ return( (failed_already)? 1 : 0 );
+} /* main() */
+/* end instrumt.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/nbconn.c b/src/libs/xpcom18a4/nsprpub/pr/tests/nbconn.c
new file mode 100644
index 00000000..d2fe6093
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/nbconn.c
@@ -0,0 +1,591 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * A test for nonblocking connect. Functions tested include PR_Connect,
+ * PR_Poll, and PR_GetConnectStatus.
+ *
+ * The test should be invoked with a host name, for example:
+ * nbconn www.netscape.com
+ * It will do a nonblocking connect to port 80 (HTTP) on that host,
+ * and when connected, issue the "GET /" HTTP command.
+ *
+ * You should run this test in three ways:
+ * 1. To a known web site, such as www.netscape.com. The HTML of the
+ * top-level page at the web site should be printed.
+ * 2. To a machine not running a web server at port 80. This test should
+ * fail. Ideally the error code should be PR_CONNECT_REFUSED_ERROR.
+ * But it is possible to return PR_UNKNOWN_ERROR on certain platforms.
+ * 3. To an unreachable machine, for example, a machine that is off line.
+ * The test should fail after the connect times out. Ideally the
+ * error code should be PR_IO_TIMEOUT_ERROR, but it is possible to
+ * return PR_UNKNOWN_ERROR on certain platforms.
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include <stdio.h>
+
+#ifdef XP_MAC
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+static char *hosts[4] = {"cynic", "warp", "gandalf", "neon"};
+#endif
+
+#define SERVER_MAX_BIND_COUNT 100
+#define DATA_BUF_SIZE 256
+#define TCP_SERVER_PORT 10000
+#define TCP_UNUSED_PORT 211
+
+typedef struct Server_Param {
+ PRFileDesc *sp_fd; /* server port */
+} Server_Param;
+static void PR_CALLBACK TCP_Server(void *arg);
+
+int _debug_on;
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+static PRIntn connection_success_test();
+static PRIntn connection_failure_test();
+
+int main(int argc, char **argv)
+{
+ PRHostEnt he;
+ char buf[1024];
+ PRNetAddr addr;
+ PRPollDesc pd;
+ PRStatus rv;
+ PRSocketOptionData optData;
+ const char *hostname = NULL;
+ PRIntn default_case, n, bytes_read, bytes_sent;
+ PRInt32 failed_already = 0;
+#ifdef XP_MAC
+ int index;
+ PRIntervalTime timeout;
+#endif
+
+ /*
+ * -d debug mode
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* debug mode */
+ hostname = opt->value;
+ break;
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("nbconn.log");
+ for (index=0; index<4; index++) {
+ argv[1] = hosts[index];
+ timeout = PR_INTERVAL_NO_TIMEOUT;
+ if (index == 3)
+ timeout = PR_SecondsToInterval(10UL);
+#endif
+
+
+ PR_STDIO_INIT();
+#ifndef XP_MAC
+ if (hostname)
+ default_case = 0;
+ else
+ default_case = 1;
+#endif
+
+ if (default_case) {
+
+ /*
+ * In the default case the following tests are executed:
+ * 1. successful connection: a server thread accepts a connection
+ * from the main thread
+ * 2. unsuccessful connection: the main thread tries to connect to a
+ * non-existent port and expects to get an error
+ */
+ rv = connection_success_test();
+ if (rv == 0)
+ rv = connection_failure_test();
+ return rv;
+ } else {
+ PRFileDesc *sock;
+
+ if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) {
+ printf( "Unknown host: %s\n", argv[1]);
+ exit(1);
+ } else {
+ printf( "host: %s\n", buf);
+ }
+ PR_EnumerateHostEnt(0, &he, 80, &addr);
+
+ sock = PR_NewTCPSocket();
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(sock, &optData);
+ rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ printf( "Connect in progress\n");
+ }
+
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
+#endif
+ if (n == -1) {
+ printf( "PR_Poll failed\n");
+ exit(1);
+ }
+ printf( "PR_Poll returns %d\n", n);
+ if (pd.out_flags & PR_POLL_READ) {
+ printf( "PR_POLL_READ\n");
+ }
+ if (pd.out_flags & PR_POLL_WRITE) {
+ printf( "PR_POLL_WRITE\n");
+ }
+ if (pd.out_flags & PR_POLL_EXCEPT) {
+ printf( "PR_POLL_EXCEPT\n");
+ }
+ if (pd.out_flags & PR_POLL_ERR) {
+ printf( "PR_POLL_ERR\n");
+ }
+ if (pd.out_flags & PR_POLL_NVAL) {
+ printf( "PR_POLL_NVAL\n");
+ }
+
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ printf("PR_GetConnectStatus: connect succeeded\n");
+ /* Mac and Win16 have trouble printing to the console. */
+#if !defined(XP_MAC) && !defined(WIN16)
+ PR_Write(sock, "GET /\r\n\r\n", 9);
+ PR_Shutdown(sock, PR_SHUTDOWN_SEND);
+ pd.in_flags = PR_POLL_READ;
+ while (1) {
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ printf( "poll returns %d\n", n);
+ n = PR_Read(sock, buf, sizeof(buf));
+ printf( "read returns %d\n", n);
+ if (n <= 0) {
+ break;
+ }
+ PR_Write(PR_STDOUT, buf, n);
+ }
+#endif
+ } else {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ printf( "PR_GetConnectStatus: connect still in progress\n");
+ exit(1);
+ }
+ printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ PR_Close(sock);
+#ifdef XP_MAC
+ } /* end of for loop */
+#endif
+ printf( "PASS\n");
+ return 0;
+
+ }
+}
+
+
+/*
+ * TCP Server
+ * Server Thread
+ * Accept a connection from the client and write some data
+ */
+static void PR_CALLBACK
+TCP_Server(void *arg)
+{
+ Server_Param *sp = (Server_Param *) arg;
+ PRFileDesc *sockfd, *newsockfd;
+ char data_buf[DATA_BUF_SIZE];
+ PRIntn rv, bytes_read;
+
+ sockfd = sp->sp_fd;
+ if ((newsockfd = PR_Accept(sockfd, NULL,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr,"ERROR - PR_Accept failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ return;
+ }
+ bytes_read = 0;
+ while (bytes_read != DATA_BUF_SIZE) {
+ rv = PR_Read(newsockfd, data_buf + bytes_read ,
+ DATA_BUF_SIZE - bytes_read);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(newsockfd);
+ return;
+ }
+ PR_ASSERT(rv != 0);
+ bytes_read += rv;
+ }
+ DPRINTF(("Bytes read from client - %d\n",bytes_read));
+ rv = PR_Write(newsockfd, data_buf,DATA_BUF_SIZE);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(newsockfd);
+ return;
+ }
+ PR_ASSERT(rv == DATA_BUF_SIZE);
+ DPRINTF(("Bytes written to client - %d\n",rv));
+ PR_Close(newsockfd);
+}
+
+
+/*
+ * test for successful connection using a non-blocking socket
+ */
+static PRIntn
+connection_success_test()
+{
+ PRFileDesc *sockfd = NULL, *conn_fd = NULL;
+ PRNetAddr netaddr;
+ PRInt32 i, rv;
+ PRPollDesc pd;
+ PRSocketOptionData optData;
+ PRThread *thr = NULL;
+ Server_Param sp;
+ char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE];
+ PRIntn default_case, n, bytes_read, bytes_sent;
+ PRIntn failed_already = 0;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_Listen(sockfd, 32) < 0) {
+ fprintf(stderr,"ERROR - PR_Listen failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if ((conn_fd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(conn_fd, &optData);
+ rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE) {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ DPRINTF(("Connect in progress\n"));
+ } else {
+ fprintf(stderr,"Error - PR_Connect failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ }
+ /*
+ * Now create a thread to accept a connection
+ */
+ sp.sp_fd = sockfd;
+ thr = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)&sp,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (thr == NULL) {
+ fprintf(stderr,"Error - PR_CreateThread failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ DPRINTF(("Created TCP_Server thread [0x%x]\n",thr));
+ pd.fd = conn_fd;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
+#endif
+ if (n == -1) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ PRInt32 rv;
+
+ DPRINTF(("Connection successful\n"));
+
+ /*
+ * Write some data, read it back and check data integrity to
+ * make sure the connection is good
+ */
+ pd.in_flags = PR_POLL_WRITE;
+ bytes_sent = 0;
+ memset(send_buf, 'a', DATA_BUF_SIZE);
+ while (bytes_sent != DATA_BUF_SIZE) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_WRITE));
+ rv = PR_Write(conn_fd, send_buf + bytes_sent,
+ DATA_BUF_SIZE - bytes_sent);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT(rv > 0);
+ bytes_sent += rv;
+ }
+ DPRINTF(("Bytes written to server - %d\n",bytes_sent));
+ PR_Shutdown(conn_fd, PR_SHUTDOWN_SEND);
+ pd.in_flags = PR_POLL_READ;
+ bytes_read = 0;
+ memset(recv_buf, 0, DATA_BUF_SIZE);
+ while (bytes_read != DATA_BUF_SIZE) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_READ));
+ rv = PR_Read(conn_fd, recv_buf + bytes_read ,
+ DATA_BUF_SIZE - bytes_read);
+ if (rv < 0) {
+ fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ PR_ASSERT(rv != 0);
+ bytes_read += rv;
+ }
+ DPRINTF(("Bytes read from server - %d\n",bytes_read));
+ /*
+ * verify the data read
+ */
+ if (memcmp(send_buf, recv_buf, DATA_BUF_SIZE) != 0) {
+ fprintf(stderr,"ERROR - data corruption\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ DPRINTF(("Data integrity verified\n"));
+ } else {
+ fprintf(stderr,"PR_GetConnectStatus: connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already = 1;
+ goto def_exit;
+ }
+def_exit:
+ if (thr) {
+ PR_JoinThread(thr);
+ thr = NULL;
+ }
+ if (sockfd) {
+ PR_Close(sockfd);
+ sockfd = NULL;
+ }
+ if (conn_fd) {
+ PR_Close(conn_fd);
+ conn_fd = NULL;
+ }
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+
+}
+
+/*
+ * test for connection to a non-existent port using a non-blocking socket
+ */
+static PRIntn
+connection_failure_test()
+{
+ PRFileDesc *sockfd = NULL, *conn_fd = NULL;
+ PRNetAddr netaddr;
+ PRInt32 i, rv;
+ PRPollDesc pd;
+ PRSocketOptionData optData;
+ PRIntn n, failed_already = 0;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+#ifdef AIX
+ /*
+ * On AIX, set to unused/reserved port
+ */
+ netaddr.inet.port = PR_htons(TCP_UNUSED_PORT);
+#endif
+ if ((conn_fd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"Error - PR_NewTCPSocket failed\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ optData.option = PR_SockOpt_Nonblocking;
+ optData.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(conn_fd, &optData);
+ rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == PR_FAILURE) {
+ DPRINTF(("PR_Connect to a non-listen port failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError()));
+ } else {
+ PR_ASSERT(rv == PR_SUCCESS);
+ fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n");
+ failed_already=1;
+ goto def_exit;
+ }
+ pd.fd = conn_fd;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+#ifndef XP_MAC
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+#else
+ n = PR_Poll(&pd, 1, timeout);
+#endif
+ if (n == -1) {
+ fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ goto def_exit;
+ }
+ if (PR_GetConnectStatus(&pd) == PR_SUCCESS) {
+ PRInt32 rv;
+ fprintf(stderr,"PR_GetConnectStatus succeeded, expected to fail\n");
+ failed_already = 1;
+ goto def_exit;
+ }
+ rv = PR_GetError();
+ DPRINTF(("Connection failed, successfully with PR_Error %d\n",rv));
+def_exit:
+ if (sockfd) {
+ PR_Close(sockfd);
+ sockfd = NULL;
+ }
+ if (conn_fd) {
+ PR_Close(conn_fd);
+ conn_fd = NULL;
+ }
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/nblayer.c b/src/libs/xpcom18a4/nsprpub/pr/tests/nblayer.c
new file mode 100644
index 00000000..4ecc955c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/nblayer.c
@@ -0,0 +1,707 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "prerror.h"
+#include "prnetdb.h"
+#include "prthread.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+#include "prwin16.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** Testing layering of I/O
+**
+** The layered server
+** A thread that acts as a server. It creates a TCP listener with a dummy
+** layer pushed on top. Then listens for incoming connections. Each connection
+** request for connection will be layered as well, accept one request, echo
+** it back and close.
+**
+** The layered client
+** Pretty much what you'd expect.
+*/
+
+static PRFileDesc *logFile;
+static PRDescIdentity identity;
+static PRNetAddr server_address;
+
+static PRIOMethods myMethods;
+
+typedef enum {rcv_get_debit, rcv_send_credit, rcv_data} RcvState;
+typedef enum {xmt_send_debit, xmt_recv_credit, xmt_data} XmtState;
+
+struct PRFilePrivate
+{
+ RcvState rcvstate;
+ XmtState xmtstate;
+ PRInt32 rcvreq, rcvinprogress;
+ PRInt32 xmtreq, xmtinprogress;
+};
+
+typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;
+
+static PRIntn minor_iterations = 5;
+static PRIntn major_iterations = 1;
+static Verbosity verbosity = quiet;
+static PRUint16 default_port = 12273;
+
+static PRFileDesc *PushLayer(PRFileDesc *stack)
+{
+ PRStatus rv;
+ PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods);
+ layer->secret = PR_NEWZAP(PRFilePrivate);
+ rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer);
+ PR_ASSERT(PR_SUCCESS == rv);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack);
+ return stack;
+} /* PushLayer */
+
+static PRFileDesc *PopLayer(PRFileDesc *stack)
+{
+ PRFileDesc *popped = PR_PopIOLayer(stack, identity);
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack);
+ PR_DELETE(popped->secret);
+ popped->dtor(popped);
+ return stack;
+} /* PopLayer */
+
+static void PR_CALLBACK Client(void *arg)
+{
+ PRStatus rv;
+ PRIntn mits;
+ PRInt32 ready;
+ PRUint8 buffer[100];
+ PRPollDesc polldesc;
+ PRIntn empty_flags = 0;
+ PRIntn bytes_read, bytes_sent;
+ PRFileDesc *stack = (PRFileDesc*)arg;
+
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buffer, 0, sizeof(buffer));
+
+ rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT);
+ if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError()))
+ {
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Client connect 'in progress'\n");
+ do
+ {
+ polldesc.fd = stack;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ if (verbosity > quiet)
+ PR_fprintf(
+ logFile, "Client connect 'in progress' [0x%x]\n",
+ polldesc.out_flags);
+ rv = PR_GetConnectStatus(&polldesc);
+ if ((PR_FAILURE == rv)
+ && (PR_IN_PROGRESS_ERROR != PR_GetError())) break;
+ } while (PR_FAILURE == rv);
+ }
+ PR_ASSERT(PR_SUCCESS == rv);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client created connection\n");
+
+ for (mits = 0; mits < minor_iterations; ++mits)
+ {
+ bytes_sent = 0;
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer));
+ do
+ {
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client sending %d bytes\n",
+ sizeof(buffer) - bytes_sent);
+ ready = PR_Send(
+ stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent,
+ empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client send status [%d]\n", ready);
+ if (0 < ready) bytes_sent += ready;
+ else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
+ {
+ polldesc.fd = stack;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_WRITE;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ }
+ else break;
+ } while (bytes_sent < sizeof(buffer));
+ PR_ASSERT(sizeof(buffer) == bytes_sent);
+
+ bytes_read = 0;
+ do
+ {
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client receiving %d bytes\n",
+ bytes_sent - bytes_read);
+ ready = PR_Recv(
+ stack, buffer + bytes_read, bytes_sent - bytes_read,
+ empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Client receive status [%d]\n", ready);
+ if (0 < ready) bytes_read += ready;
+ else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
+ {
+ polldesc.fd = stack;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_READ;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ }
+ else break;
+ } while (bytes_read < bytes_sent);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Client received %d bytes\n", bytes_read);
+ PR_ASSERT(bytes_read == bytes_sent);
+ }
+
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Client shutting down stack\n");
+
+ rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
+} /* Client */
+
+static void PR_CALLBACK Server(void *arg)
+{
+ PRStatus rv;
+ PRInt32 ready;
+ PRUint8 buffer[100];
+ PRFileDesc *service;
+ PRUintn empty_flags = 0;
+ struct PRPollDesc polldesc;
+ PRIntn bytes_read, bytes_sent;
+ PRFileDesc *stack = (PRFileDesc*)arg;
+ PRNetAddr client_address;
+
+ do
+ {
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server accepting connection\n");
+ service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server accept status [0x%p]\n", service);
+ if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
+ {
+ polldesc.fd = stack;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ }
+ } while (NULL == service);
+ PR_ASSERT(NULL != service);
+
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Server accepting connection\n");
+
+ do
+ {
+ bytes_read = 0;
+ do
+ {
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Server receiving %d bytes\n",
+ sizeof(buffer) - bytes_read);
+ ready = PR_Recv(
+ service, buffer + bytes_read, sizeof(buffer) - bytes_read,
+ empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server receive status [%d]\n", ready);
+ if (0 < ready) bytes_read += ready;
+ else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
+ {
+ polldesc.fd = service;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_READ;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ }
+ else break;
+ } while (bytes_read < sizeof(buffer));
+
+ if (0 != bytes_read)
+ {
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server received %d bytes\n", bytes_read);
+ PR_ASSERT(bytes_read > 0);
+
+ bytes_sent = 0;
+ do
+ {
+ ready = PR_Send(
+ service, buffer + bytes_sent, bytes_read - bytes_sent,
+ empty_flags, PR_INTERVAL_NO_TIMEOUT);
+ if (0 < ready)
+ {
+ bytes_sent += ready;
+ }
+ else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError()))
+ {
+ polldesc.fd = service;
+ polldesc.out_flags = 0;
+ polldesc.in_flags = PR_POLL_WRITE;
+ ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT);
+ if ((1 != ready) /* if not 1, then we're dead */
+ || (0 == (polldesc.in_flags & polldesc.out_flags)))
+ { PR_ASSERT(!"Whoa!"); break; }
+ }
+ else break;
+ } while (bytes_sent < bytes_read);
+ PR_ASSERT(bytes_read == bytes_sent);
+ if (verbosity > chatty)
+ PR_fprintf(logFile, "Server sent %d bytes\n", bytes_sent);
+ }
+ } while (0 != bytes_read);
+
+ if (verbosity > quiet)
+ PR_fprintf(logFile, "Server shutting down stack\n");
+ rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
+
+} /* Server */
+
+static PRStatus PR_CALLBACK MyClose(PRFileDesc *fd)
+{
+ PR_DELETE(fd->secret); /* manage my secret file object */
+ return (PR_GetDefaultIOMethods())->close(fd); /* let him do all the work */
+} /* MyClose */
+
+static PRInt16 PR_CALLBACK MyPoll(
+ PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
+{
+ PRInt16 my_flags, new_flags;
+ PRFilePrivate *mine = (PRFilePrivate*)fd->secret;
+ if (0 != (PR_POLL_READ & in_flags))
+ {
+ /* client thinks he's reading */
+ switch (mine->rcvstate)
+ {
+ case rcv_send_credit:
+ my_flags = (in_flags & ~PR_POLL_READ) | PR_POLL_WRITE;
+ break;
+ case rcv_data:
+ case rcv_get_debit:
+ my_flags = in_flags;
+ default: break;
+ }
+ }
+ else if (0 != (PR_POLL_WRITE & in_flags))
+ {
+ /* client thinks he's writing */
+ switch (mine->xmtstate)
+ {
+ case xmt_recv_credit:
+ my_flags = (in_flags & ~PR_POLL_WRITE) | PR_POLL_READ;
+ break;
+ case xmt_send_debit:
+ case xmt_data:
+ my_flags = in_flags;
+ default: break;
+ }
+ }
+ else PR_ASSERT(!"How'd I get here?");
+ new_flags = (fd->lower->methods->poll)(fd->lower, my_flags, out_flags);
+ if (verbosity > chatty)
+ PR_fprintf(
+ logFile, "Poll [i: 0x%x, m: 0x%x, o: 0x%x, n: 0x%x]\n",
+ in_flags, my_flags, *out_flags, new_flags);
+ return new_flags;
+} /* MyPoll */
+
+static PRFileDesc * PR_CALLBACK MyAccept(
+ PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
+{
+ PRStatus rv;
+ PRFileDesc *newfd, *layer = fd;
+ PRFileDesc *newstack;
+ PRFilePrivate *newsecret;
+
+ PR_ASSERT(fd != NULL);
+ PR_ASSERT(fd->lower != NULL);
+
+ newstack = PR_NEW(PRFileDesc);
+ if (NULL == newstack)
+ {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ newsecret = PR_NEW(PRFilePrivate);
+ if (NULL == newsecret)
+ {
+ PR_DELETE(newstack);
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ return NULL;
+ }
+ *newstack = *fd; /* make a copy of the accepting layer */
+ *newsecret = *fd->secret;
+ newstack->secret = newsecret;
+
+ newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
+ if (NULL == newfd)
+ {
+ PR_DELETE(newsecret);
+ PR_DELETE(newstack);
+ return NULL;
+ }
+
+ /* this PR_PushIOLayer call cannot fail */
+ rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
+ PR_ASSERT(PR_SUCCESS == rv);
+ return newfd; /* that's it */
+}
+
+static PRInt32 PR_CALLBACK MyRecv(
+ PRFileDesc *fd, void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ char *b;
+ PRInt32 rv;
+ PRFileDesc *lo = fd->lower;
+ PRFilePrivate *mine = (PRFilePrivate*)fd->secret;
+
+ do
+ {
+ switch (mine->rcvstate)
+ {
+ case rcv_get_debit:
+ b = (char*)&mine->rcvreq;
+ mine->rcvreq = amount;
+ rv = lo->methods->recv(
+ lo, b + mine->rcvinprogress,
+ sizeof(mine->rcvreq) - mine->rcvinprogress, flags, timeout);
+ if (0 == rv) goto closed;
+ if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break;
+ mine->rcvinprogress += rv; /* accumulate the read */
+ if (mine->rcvinprogress < sizeof(mine->rcvreq)) break; /* loop */
+ mine->rcvstate = rcv_send_credit;
+ mine->rcvinprogress = 0;
+ case rcv_send_credit:
+ b = (char*)&mine->rcvreq;
+ rv = lo->methods->send(
+ lo, b + mine->rcvinprogress,
+ sizeof(mine->rcvreq) - mine->rcvinprogress, flags, timeout);
+ if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break;
+ mine->rcvinprogress += rv; /* accumulate the read */
+ if (mine->rcvinprogress < sizeof(mine->rcvreq)) break; /* loop */
+ mine->rcvstate = rcv_data;
+ mine->rcvinprogress = 0;
+ case rcv_data:
+ b = (char*)buf;
+ rv = lo->methods->recv(
+ lo, b + mine->rcvinprogress,
+ mine->rcvreq - mine->rcvinprogress, flags, timeout);
+ if (0 == rv) goto closed;
+ if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break;
+ mine->rcvinprogress += rv; /* accumulate the read */
+ if (mine->rcvinprogress < amount) break; /* loop */
+ mine->rcvstate = rcv_get_debit;
+ mine->rcvinprogress = 0;
+ return mine->rcvreq; /* << -- that's it! */
+ default:
+ break;
+ }
+ } while (-1 != rv);
+ return rv;
+closed:
+ mine->rcvinprogress = 0;
+ mine->rcvstate = rcv_get_debit;
+ return 0;
+} /* MyRecv */
+
+static PRInt32 PR_CALLBACK MySend(
+ PRFileDesc *fd, const void *buf, PRInt32 amount,
+ PRIntn flags, PRIntervalTime timeout)
+{
+ char *b;
+ PRInt32 rv;
+ PRFileDesc *lo = fd->lower;
+ PRFilePrivate *mine = (PRFilePrivate*)fd->secret;
+
+ do
+ {
+ switch (mine->xmtstate)
+ {
+ case xmt_send_debit:
+ b = (char*)&mine->xmtreq;
+ mine->xmtreq = amount;
+ rv = lo->methods->send(
+ lo, b - mine->xmtinprogress,
+ sizeof(mine->xmtreq) - mine->xmtinprogress, flags, timeout);
+ if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break;
+ mine->xmtinprogress += rv;
+ if (mine->xmtinprogress < sizeof(mine->xmtreq)) break;
+ mine->xmtstate = xmt_recv_credit;
+ mine->xmtinprogress = 0;
+ case xmt_recv_credit:
+ b = (char*)&mine->xmtreq;
+ rv = lo->methods->recv(
+ lo, b + mine->xmtinprogress,
+ sizeof(mine->xmtreq) - mine->xmtinprogress, flags, timeout);
+ if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break;
+ mine->xmtinprogress += rv;
+ if (mine->xmtinprogress < sizeof(mine->xmtreq)) break;
+ mine->xmtstate = xmt_data;
+ mine->xmtinprogress = 0;
+ case xmt_data:
+ b = (char*)buf;
+ rv = lo->methods->send(
+ lo, b + mine->xmtinprogress,
+ mine->xmtreq - mine->xmtinprogress, flags, timeout);
+ if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break;
+ mine->xmtinprogress += rv;
+ if (mine->xmtinprogress < amount) break;
+ mine->xmtstate = xmt_send_debit;
+ mine->xmtinprogress = 0;
+ return mine->xmtreq; /* <<-- That's the one! */
+ default:
+ break;
+ }
+ } while (-1 != rv);
+ return rv;
+} /* MySend */
+
+static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta)
+{
+ PRIntn verbage = (PRIntn)verbosity + delta;
+ if (verbage < (PRIntn)silent) verbage = (PRIntn)silent;
+ else if (verbage > (PRIntn)noisy) verbage = (PRIntn)noisy;
+ return (Verbosity)verbage;
+} /* ChangeVerbosity */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PLOptStatus os;
+ PRFileDesc *client, *service;
+ PRNetAddr any_address;
+ const char *server_name = NULL;
+ const PRIOMethods *stubMethods;
+ PRThread *client_thread, *server_thread;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PRSocketOptionData socket_noblock, socket_nodelay;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0:
+ server_name = opt->value;
+ break;
+ case 'd': /* debug mode */
+ if (verbosity < noisy)
+ verbosity = ChangeVerbosity(verbosity, 1);
+ break;
+ case 'q': /* debug mode */
+ if (verbosity > silent)
+ verbosity = ChangeVerbosity(verbosity, -1);
+ break;
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'C': /* number of threads waiting */
+ major_iterations = atoi(opt->value);
+ break;
+ case 'c': /* number of client threads */
+ minor_iterations = atoi(opt->value);
+ break;
+ case 'p': /* default port */
+ default_port = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ PR_STDIO_INIT();
+
+ logFile = PR_GetSpecialFD(PR_StandardError);
+ identity = PR_GetUniqueIdentity("Dummy");
+ stubMethods = PR_GetDefaultIOMethods();
+
+ /*
+ ** The protocol we're going to implement is one where in order to initiate
+ ** a send, the sender must first solicit permission. Therefore, every
+ ** send is really a send - receive - send sequence.
+ */
+ myMethods = *stubMethods; /* first get the entire batch */
+ myMethods.accept = MyAccept; /* then override the ones we care about */
+ myMethods.recv = MyRecv; /* then override the ones we care about */
+ myMethods.send = MySend; /* then override the ones we care about */
+ myMethods.close = MyClose; /* then override the ones we care about */
+ myMethods.poll = MyPoll; /* then override the ones we care about */
+
+ if (NULL == server_name)
+ rv = PR_InitializeNetAddr(
+ PR_IpAddrLoopback, default_port, &server_address);
+ else
+ {
+ rv = PR_StringToNetAddr(server_name, &server_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_InitializeNetAddr(
+ PR_IpAddrNull, default_port, &server_address);
+ }
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ socket_noblock.value.non_blocking = PR_TRUE;
+ socket_noblock.option = PR_SockOpt_Nonblocking;
+ socket_nodelay.value.no_delay = PR_TRUE;
+ socket_nodelay.option = PR_SockOpt_NoDelay;
+
+ /* one type w/o layering */
+
+ while (major_iterations-- > 0)
+ {
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Beginning non-layered test\n");
+
+ client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
+ service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
+
+ rv = PR_SetSocketOption(client, &socket_noblock);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetSocketOption(service, &socket_noblock);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetSocketOption(client, &socket_nodelay);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetSocketOption(service, &socket_nodelay);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
+
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, Server, service,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != server_thread);
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, Client, client,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != client_thread);
+
+ rv = PR_JoinThread(client_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(server_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Ending non-layered test\n");
+
+ /* with layering */
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Beginning layered test\n");
+ client = PR_NewTCPSocket(); PR_ASSERT(NULL != client);
+ service = PR_NewTCPSocket(); PR_ASSERT(NULL != service);
+
+ rv = PR_SetSocketOption(client, &socket_noblock);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetSocketOption(service, &socket_noblock);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetSocketOption(client, &socket_nodelay);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetSocketOption(service, &socket_nodelay);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ PushLayer(client);
+ PushLayer(service);
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv);
+
+ server_thread = PR_CreateThread(
+ PR_USER_THREAD, Server, service,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != server_thread);
+
+ client_thread = PR_CreateThread(
+ PR_USER_THREAD, Client, client,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 16 * 1024);
+ PR_ASSERT(NULL != client_thread);
+
+ rv = PR_JoinThread(client_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_JoinThread(server_thread);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Close(PopLayer(client)); PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Close(PopLayer(service)); PR_ASSERT(PR_SUCCESS == rv);
+ if (verbosity > silent)
+ PR_fprintf(logFile, "Ending layered test\n");
+ }
+ return 0;
+} /* main */
+
+/* nblayer.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/nonblock.c b/src/libs/xpcom18a4/nsprpub/pr/tests/nonblock.c
new file mode 100644
index 00000000..102fd84b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/nonblock.c
@@ -0,0 +1,273 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "prio.h"
+#include "prerror.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prnetdb.h"
+#include "plerror.h"
+#ifndef XP_MAC
+#include "obsolete/probslet.h"
+#else
+#include "probslet.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUMBER_ROUNDS 5
+
+#if defined(WIN16)
+/*
+** Make win16 unit_time interval 300 milliseconds, others get 100
+*/
+#define UNIT_TIME 200 /* unit time in milliseconds */
+#else
+#define UNIT_TIME 100 /* unit time in milliseconds */
+#endif
+#define CHUNK_SIZE 10
+#undef USE_PR_SELECT /* If defined, we use PR_Select.
+ * If not defined, use PR_Poll instead. */
+
+#if defined(USE_PR_SELECT)
+#include "pprio.h"
+#endif
+
+#ifdef XP_MAC
+int fprintf(FILE *stream, const char *fmt, ...)
+{
+PR_LogPrint(fmt);
+return 0;
+}
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+static void PR_CALLBACK
+clientThreadFunc(void *arg)
+{
+ PRUintn port = (PRUintn)arg;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ char buf[CHUNK_SIZE];
+ int i;
+ PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME);
+ PRSocketOptionData optval;
+ PRStatus retVal;
+ PRInt32 nBytes;
+
+ /* Initialize the buffer so that Purify won't complain */
+ memset(buf, 0, sizeof(buf));
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons((PRUint16)port);
+ addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip);
+
+ /* time 1 */
+ PR_Sleep(unitTime);
+ sock = PR_NewTCPSocket();
+ optval.option = PR_SockOpt_Nonblocking;
+ optval.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(sock, &optval);
+ retVal = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (retVal == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) {
+#if !defined(USE_PR_SELECT)
+ PRPollDesc pd;
+ PRInt32 n;
+ fprintf(stderr, "connect: EWOULDBLOCK, good\n");
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE;
+ n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(n == 1);
+ PR_ASSERT(pd.out_flags == PR_POLL_WRITE);
+#else
+ PR_fd_set writeSet;
+ PRInt32 n;
+ fprintf(stderr, "connect: EWOULDBLOCK, good\n");
+ PR_FD_ZERO(&writeSet);
+ PR_FD_SET(sock, &writeSet);
+ n = PR_Select(0, NULL, &writeSet, NULL, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(n == 1);
+ PR_ASSERT(PR_FD_ISSET(sock, &writeSet));
+#endif
+ }
+ printf("client connected\n");
+ fflush(stdout);
+
+ /* time 4, 7, 11, etc. */
+ for (i = 0; i < NUMBER_ROUNDS; i++) {
+ PR_Sleep(3 * unitTime);
+ nBytes = PR_Write(sock, buf, sizeof(buf));
+ if (nBytes == -1) {
+ if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
+ fprintf(stderr, "write: EWOULDBLOCK\n");
+ exit(1);
+ } else {
+ fprintf(stderr, "write: failed\n");
+ }
+ }
+ printf("client sent %d bytes\n", nBytes);
+ fflush(stdout);
+ }
+
+ PR_Close(sock);
+}
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ PRFileDesc *listenSock, *sock;
+ PRUint16 listenPort;
+ PRNetAddr addr;
+ char buf[CHUNK_SIZE];
+ PRThread *clientThread;
+ PRInt32 retVal;
+ PRSocketOptionData optval;
+ PRIntn i;
+ PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("nonblock.log");
+#endif
+
+ /* Create a listening socket */
+ if ((listenSock = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ exit(1);
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ listenPort = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ exit(1);
+ }
+
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on port %hu\n\n",
+ listenPort);
+ printf("%s", buf);
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ exit(1);
+ }
+
+ printf("client thread created.\n");
+
+ optval.option = PR_SockOpt_Nonblocking;
+ optval.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(listenSock, &optval);
+ /* time 0 */
+ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (sock != NULL || PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ PL_PrintError("First Accept\n");
+ fprintf(stderr, "First PR_Accept() xxx\n" );
+ exit(1);
+ }
+ printf("accept: EWOULDBLOCK, good\n");
+ fflush(stdout);
+ /* time 2 */
+ PR_Sleep(2 * unitTime);
+ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (sock == NULL) {
+ PL_PrintError("Second Accept\n");
+ fprintf(stderr, "Second PR_Accept() failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("accept: succeeded, good\n");
+ fflush(stdout);
+ PR_Close(listenSock);
+
+ PR_SetSocketOption(sock, &optval);
+
+ /* time 3, 5, 6, 8, etc. */
+ for (i = 0; i < NUMBER_ROUNDS; i++) {
+ PR_Sleep(unitTime);
+ retVal = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (retVal != -1 || PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ PL_PrintError("First Receive:\n");
+ fprintf(stderr, "First PR_Recv: retVal: %ld, Error: %ld\n",
+ retVal, PR_GetError());
+ exit(1);
+ }
+ printf("read: EWOULDBLOCK, good\n");
+ fflush(stdout);
+ PR_Sleep(2 * unitTime);
+ retVal = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
+ if (retVal != CHUNK_SIZE) {
+ PL_PrintError("Second Receive:\n");
+ fprintf(stderr, "Second PR_Recv: retVal: %ld, Error: %ld\n",
+ retVal, PR_GetError());
+ exit(1);
+ }
+ printf("read: %d bytes, good\n", retVal);
+ fflush(stdout);
+ }
+ PR_Close(sock);
+
+ printf("All tests finished\n");
+ printf("PASS\n");
+ return 0;
+}
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/ntioto.c b/src/libs/xpcom18a4/nsprpub/pr/tests/ntioto.c
new file mode 100644
index 00000000..44e2a608
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/ntioto.c
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: ntioto.c
+** Description:
+** This test, ntioto.c, was designed to reproduce a bug reported by NES
+** on WindowsNT (fibers implementation). NSPR was asserting in ntio.c
+** after PR_AcceptRead() had timed out. I/O performed subsequent to the
+** call to PR_AcceptRead() could complete on a CPU other than the one
+** on which it was started. The assert in ntio.c detected this, then
+** asserted.
+**
+** Design:
+** This test will fail with an assert in ntio.c if the problem it was
+** designed to catch occurs. It returns 0 otherwise.
+**
+** The main() thread initializes and tears things down. A file is
+** opened for writing; this file will be written to by AcceptThread()
+** and JitterThread(). Main() creates a socket for reading, listens
+** and binds the socket.
+**
+** ConnectThread() connects to the socket created by main, then polls
+** the "state" variable. When state is AllDone, ConnectThread() exits.
+**
+** AcceptThread() calls PR_AcceptRead() on the socket. He fully expects
+** it to time out. After the timeout, AccpetThread() interacts with
+** JitterThread() via a common condition variable and the state
+** variable. The two threads ping-pong back and forth, each thread
+** writes the the file opened by main. This should provoke the
+** condition reported by NES (if we didn't fix it).
+**
+** The failure is not solid. It may fail within a few ping-pongs between
+** AcceptThread() and JitterThread() or may take a while. The default
+** iteration count, jitter, is set by DEFAULT_JITTER. This may be
+** modified at the command line with the -j option.
+**
+*/
+
+#include <plgetopt.h>
+#include <nspr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** Test harness infrastructure
+*/
+PRLogModuleInfo *lm;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRIntn debug = 0;
+PRIntn verbose = 0;
+PRUint32 failed_already = 0;
+/* end Test harness infrastructure */
+
+/* JITTER_DEFAULT: the number of times AcceptThread() and JitterThread() ping-pong */
+#define JITTER_DEFAULT 100000
+#define BASE_PORT 9867
+
+PRIntervalTime timeout;
+PRNetAddr listenAddr;
+PRFileDesc *listenSock;
+PRLock *ml;
+PRCondVar *cv;
+volatile enum {
+ RunJitter,
+ RunAcceptRead,
+ AllDone
+} state = RunAcceptRead;
+PRFileDesc *file1;
+PRIntn iCounter = 0;
+PRIntn jitter = JITTER_DEFAULT;
+PRBool resume = PR_FALSE;
+
+/*
+** Emit help text for this test
+*/
+static void Help( void )
+{
+ printf("Template: Help(): display your help message(s) here");
+ exit(1);
+} /* end Help() */
+
+
+/*
+** static computation of PR_AcceptRead() buffer size.
+*/
+#define ACCEPT_READ_DATASIZE 10
+#define ACCEPT_READ_BUFSIZE (PR_ACCEPT_READ_BUF_OVERHEAD + ACCEPT_READ_DATASIZE)
+
+static void AcceptThread(void *arg)
+{
+ PRIntn bytesRead;
+ char dataBuf[ACCEPT_READ_BUFSIZE];
+ PRFileDesc *arSock;
+ PRNetAddr *arAddr;
+
+ bytesRead = PR_AcceptRead( listenSock,
+ &arSock,
+ &arAddr,
+ dataBuf,
+ ACCEPT_READ_DATASIZE,
+ PR_SecondsToInterval(1));
+
+ if ( bytesRead == -1 && PR_GetError() == PR_IO_TIMEOUT_ERROR )
+ if ( debug ) printf("AcceptRead timed out\n");
+ else
+ if ( debug ) printf("Oops! read: %d, error: %d\n", bytesRead, PR_GetError());
+
+ while( state != AllDone ) {
+ PR_Lock( ml );
+ while( state != RunAcceptRead )
+ PR_WaitCondVar( cv, PR_INTERVAL_NO_TIMEOUT );
+ if ( ++iCounter >= jitter )
+ state = AllDone;
+ else
+ state = RunJitter;
+ if ( verbose ) printf(".");
+ PR_NotifyCondVar( cv );
+ PR_Unlock( ml );
+ PR_Write( file1, ".", 1 );
+ }
+
+ return;
+} /* end AcceptThread() */
+
+static void JitterThread(void *arg)
+{
+ while( state != AllDone ) {
+ PR_Lock( ml );
+ while( state != RunJitter && state != AllDone )
+ PR_WaitCondVar( cv, PR_INTERVAL_NO_TIMEOUT );
+ if ( state != AllDone)
+ state = RunAcceptRead;
+ if ( verbose ) printf("+");
+ PR_NotifyCondVar( cv );
+ PR_Unlock( ml );
+ PR_Write( file1, "+", 1 );
+ }
+ return;
+} /* end Goofy() */
+
+static void ConnectThread( void *arg )
+{
+ PRStatus rv;
+ PRFileDesc *clientSock;
+ PRNetAddr serverAddress;
+ clientSock = PR_NewTCPSocket();
+
+ PR_ASSERT(clientSock);
+
+ if ( resume ) {
+ if ( debug ) printf("pausing 3 seconds before connect\n");
+ PR_Sleep( PR_SecondsToInterval(3));
+ }
+
+ memset(&serverAddress, 0, sizeof(serverAddress));
+ rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &serverAddress);
+ PR_ASSERT( PR_SUCCESS == rv );
+ rv = PR_Connect( clientSock,
+ &serverAddress,
+ PR_SecondsToInterval(1));
+ PR_ASSERT( PR_SUCCESS == rv );
+
+ /* that's all we do. ... Wait for the acceptread() to timeout */
+ while( state != AllDone )
+ PR_Sleep( PR_SecondsToInterval(1));
+ return;
+} /* end ConnectThread() */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRThread *tJitter;
+ PRThread *tAccept;
+ PRThread *tConnect;
+ PRStatus rv;
+ /* This test if valid for WinNT only! */
+
+#if !defined(WINNT)
+ return 0;
+#endif
+
+ {
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdrvj:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ msgLevel = PR_LOG_ERROR;
+ break;
+ case 'v': /* verbose mode */
+ verbose = 1;
+ msgLevel = PR_LOG_DEBUG;
+ break;
+ case 'j':
+ jitter = atoi(opt->value);
+ if ( jitter == 0)
+ jitter = JITTER_DEFAULT;
+ break;
+ case 'r':
+ resume = PR_TRUE;
+ break;
+ case 'h': /* help message */
+ Help();
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ lm = PR_NewLogModule("Test"); /* Initialize logging */
+
+ /* set concurrency */
+ PR_SetConcurrency( 4 );
+
+ /* setup thread synchronization mechanics */
+ ml = PR_NewLock();
+ cv = PR_NewCondVar( ml );
+
+ /* setup a tcp socket */
+ memset(&listenAddr, 0, sizeof(listenAddr));
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr);
+ PR_ASSERT( PR_SUCCESS == rv );
+
+ listenSock = PR_NewTCPSocket();
+ PR_ASSERT( listenSock );
+
+ rv = PR_Bind( listenSock, &listenAddr);
+ PR_ASSERT( PR_SUCCESS == rv );
+
+ rv = PR_Listen( listenSock, 5 );
+ PR_ASSERT( PR_SUCCESS == rv );
+
+ /* open a file for writing, provoke bug */
+ file1 = PR_Open("xxxTestFile", PR_CREATE_FILE | PR_RDWR, 666);
+
+ /* create Connect thread */
+ tConnect = PR_CreateThread(
+ PR_USER_THREAD, ConnectThread, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0 );
+ PR_ASSERT( tConnect );
+
+ /* create jitter off thread */
+ tJitter = PR_CreateThread(
+ PR_USER_THREAD, JitterThread, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0 );
+ PR_ASSERT( tJitter );
+
+ /* create acceptread thread */
+ tAccept = PR_CreateThread(
+ PR_USER_THREAD, AcceptThread, NULL,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD, 0 );
+ PR_ASSERT( tAccept );
+
+ /* wait for all threads to quit, then terminate gracefully */
+ PR_JoinThread( tConnect );
+ PR_JoinThread( tAccept );
+ PR_JoinThread( tJitter );
+ PR_Close( listenSock );
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+ PR_Close( file1 );
+ PR_Delete( "xxxTestFile");
+
+ /* test return and exit */
+ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS");
+ return( (failed_already == PR_TRUE )? 1 : 0 );
+} /* main() */
+/* end ntioto.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/ntoh.c b/src/libs/xpcom18a4/nsprpub/pr/tests/ntoh.c
new file mode 100644
index 00000000..e424f548
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/ntoh.c
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * A test program for PR_htons, PR_ntohs, PR_htonl, PR_ntohl,
+ * PR_htonll, and PR_ntohll.
+ */
+
+#include "prnetdb.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Byte sequence in network byte order */
+static unsigned char bytes_n[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+/* Integers in host byte order */
+static PRUint16 s_h = 0x0102;
+static PRUint32 l_h = 0x01020304;
+static PRUint64 ll_h = LL_INIT(0x01020304, 0x05060708);
+
+int main()
+{
+ union {
+ PRUint16 s;
+ PRUint32 l;
+ PRUint64 ll;
+ unsigned char bytes[8];
+ } un;
+
+ un.s = s_h;
+ printf("%u %u\n",
+ un.bytes[0], un.bytes[1]);
+ un.s = PR_htons(un.s);
+ printf("%u %u\n",
+ un.bytes[0], un.bytes[1]);
+ if (memcmp(un.bytes, bytes_n, 2)) {
+ fprintf(stderr, "PR_htons failed\n");
+ exit(1);
+ }
+ un.s = PR_ntohs(un.s);
+ printf("%u %u\n",
+ un.bytes[0], un.bytes[1]);
+ if (un.s != s_h) {
+ fprintf(stderr, "PR_ntohs failed\n");
+ exit(1);
+ }
+
+ un.l = l_h;
+ printf("%u %u %u %u\n",
+ un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]);
+ un.l = PR_htonl(un.l);
+ printf("%u %u %u %u\n",
+ un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]);
+ if (memcmp(un.bytes, bytes_n, 4)) {
+ fprintf(stderr, "PR_htonl failed\n");
+ exit(1);
+ }
+ un.l = PR_ntohl(un.l);
+ printf("%u %u %u %u\n",
+ un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]);
+ if (un.l != l_h) {
+ fprintf(stderr, "PR_ntohl failed\n");
+ exit(1);
+ }
+
+ un.ll = ll_h;
+ printf("%u %u %u %u %u %u %u %u\n",
+ un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3],
+ un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]);
+ un.ll = PR_htonll(un.ll);
+ printf("%u %u %u %u %u %u %u %u\n",
+ un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3],
+ un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]);
+ if (memcmp(un.bytes, bytes_n, 8)) {
+ fprintf(stderr, "PR_htonll failed\n");
+ exit(1);
+ }
+ un.ll = PR_ntohll(un.ll);
+ printf("%u %u %u %u %u %u %u %u\n",
+ un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3],
+ un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]);
+ if (LL_NE(un.ll, ll_h)) {
+ fprintf(stderr, "PR_ntohll failed\n");
+ exit(1);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/obsints.c b/src/libs/xpcom18a4/nsprpub/pr/tests/obsints.c
new file mode 100644
index 00000000..87182f55
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/obsints.c
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * Test: obsints.c
+ *
+ * Description: make sure that protypes.h defines the obsolete integer
+ * types intn, uintn, uint, int8, uint8, int16, uint16, int32, uint32,
+ * int64, and uint64.
+ */
+
+#include <stdio.h>
+
+#ifdef NO_NSPR_10_SUPPORT
+
+/* nothing to do */
+int main()
+{
+ printf("PASS\n");
+ return 0;
+}
+
+#else /* NO_NSPR_10_SUPPORT */
+
+#include "prtypes.h" /* which includes protypes.h */
+
+int main()
+{
+ /*
+ * Compilation fails if any of these integer types are not
+ * defined by protypes.h.
+ */
+ intn in;
+ uintn uin;
+ uint ui;
+ int8 i8;
+ uint8 ui8;
+ int16 i16;
+ uint16 ui16;
+ int32 i32;
+ uint32 ui32;
+ int64 i64;
+ uint64 ui64;
+
+ printf("PASS\n");
+ return 0;
+}
+
+#endif /* NO_NSPR_10_SUPPORT */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/op_2long.c b/src/libs/xpcom18a4/nsprpub/pr/tests/op_2long.c
new file mode 100644
index 00000000..27f64d79
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/op_2long.c
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: op_2long.c
+**
+** Description: Test Program to verify the PR_NAME_TOO_LONG_ERROR
+**
+** Modification History:
+** 03-June-97 AGarcia- Initial version
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "prinit.h"
+#include "prmem.h"
+#include "prio.h"
+#include "prerror.h"
+#include <stdio.h>
+#include "plerror.h"
+#include "plgetopt.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#else
+#endif
+
+static PRFileDesc *t1;
+PRIntn error_code;
+
+/*
+ * should exceed any system's maximum file name length
+ * Note: was set at 4096. This is legal on some unix (Linux 2.1+) platforms.
+ *
+ */
+#define TOO_LONG 5000
+
+int main(int argc, char **argv)
+{
+ char nameTooLong[TOO_LONG];
+ int i;
+
+ /* Generate a really long pathname */
+ for (i = 0; i < TOO_LONG - 1; i++) {
+ if (i % 10 == 0) {
+ nameTooLong[i] = '/';
+ } else {
+ nameTooLong[i] = 'a';
+ }
+ }
+ nameTooLong[TOO_LONG - 1] = 0;
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("pr_open_re.log");
+#endif
+
+ PR_STDIO_INIT();
+ t1 = PR_Open(nameTooLong, PR_RDWR, 0666);
+ if (t1 == NULL) {
+ if (PR_GetError() == PR_NAME_TOO_LONG_ERROR) {
+ PL_PrintError("error code is");
+ printf ("PASS\n");
+ return 0;
+ }
+ else {
+ PL_PrintError("error code is");
+ printf ("FAIL\n");
+ return 1;
+ }
+ }
+
+ else {
+ printf ("Test passed\n");
+ return 0;
+ }
+
+
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/op_excl.c b/src/libs/xpcom18a4/nsprpub/pr/tests/op_excl.c
new file mode 100644
index 00000000..b0bb6ace
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/op_excl.c
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: op_excl.c
+**
+** Description: Test Program to verify function of PR_EXCL open flag
+**
+** Modification History:
+** 27-Oct-1999 lth. Initial version
+***********************************************************************/
+
+#include <plgetopt.h>
+#include <nspr.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+** Test harness infrastructure
+*/
+PRLogModuleInfo *lm;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRIntn debug = 0;
+PRUint32 failed_already = 0;
+/* end Test harness infrastructure */
+/*
+** Emit help text for this test
+*/
+static void Help( void )
+{
+ printf("op_excl: Help");
+ printf("op_excl [-d]");
+ printf("-d enables debug messages");
+ exit(1);
+} /* end Help() */
+
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRFileDesc *fd;
+ PRStatus rv;
+ PRInt32 written;
+ char outBuf[] = "op_excl.c test file";
+#define OUT_SIZE sizeof(outBuf)
+#define NEW_FILENAME "xxxExclNewFile"
+
+ {
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hd");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ msgLevel = PR_LOG_ERROR;
+ break;
+ case 'h': /* help message */
+ Help();
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ lm = PR_NewLogModule("Test"); /* Initialize logging */
+
+ /*
+ ** First, open a file, PR_EXCL, we believe not to exist
+ */
+ fd = PR_Open( NEW_FILENAME, PR_CREATE_FILE | PR_EXCL | PR_WRONLY, 0666 );
+ if ( NULL == fd ) {
+ if (debug) fprintf( stderr, "Open exclusive. Expected success, got failure\n");
+ failed_already = 1;
+ goto Finished;
+ }
+
+ written = PR_Write( fd, outBuf, OUT_SIZE );
+ if ( OUT_SIZE != written ) {
+ if (debug) fprintf( stderr, "Write after open exclusive failed\n");
+ failed_already = 1;
+ goto Finished;
+ }
+
+ rv = PR_Close(fd);
+ if ( PR_FAILURE == rv ) {
+ if (debug) fprintf( stderr, "Close after open exclusive failed\n");
+ failed_already = 1;
+ goto Finished;
+ }
+
+ /*
+ ** Second, open the same file, PR_EXCL, expect it to fail
+ */
+ fd = PR_Open( NEW_FILENAME, PR_CREATE_FILE | PR_EXCL | PR_WRONLY, 0666 );
+ if ( NULL != fd ) {
+ if (debug) fprintf( stderr, "Open exclusive. Expected failure, got success\n");
+ failed_already = 1;
+ PR_Close(fd);
+ }
+
+ rv = PR_Delete( NEW_FILENAME );
+ if ( PR_FAILURE == rv ) {
+ if (debug) fprintf( stderr, "PR_Delete() failed\n");
+ failed_already = 1;
+ }
+
+Finished:
+ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS");
+ return( (failed_already == PR_TRUE )? 1 : 0 );
+} /* main() */
+/* end op_excl.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/op_filnf.c b/src/libs/xpcom18a4/nsprpub/pr/tests/op_filnf.c
new file mode 100644
index 00000000..aeb2014d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/op_filnf.c
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: op_filnf.c
+**
+** Description: Test Program to verify the PR_FILE_NOT_FOUND_ERROR
+** This test program also uses the TRUNCATE option
+**
+** Modification History:
+** 03-June-97 AGarcia- Initial version
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "prinit.h"
+#include "prmem.h"
+#include "prio.h"
+#include "prerror.h"
+#include <stdio.h>
+#include "plgetopt.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#else
+#endif
+
+static PRFileDesc *t1;
+PRIntn error_code;
+
+int main(int argc, char **argv)
+{
+
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("pr_open_re.log");
+#endif
+
+
+ PR_STDIO_INIT();
+ t1 = PR_Open("/usr/tmp/ttools/err03.tmp", PR_TRUNCATE | PR_RDWR, 0666);
+ if (t1 == NULL)
+ if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) {
+ printf ("error code is %d \n", PR_GetError());
+ printf ("PASS\n");
+ return 0;
+ }
+ else {
+ printf ("error code is %d \n", PR_GetError());
+ printf ("FAIL\n");
+ return 1;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/op_filok.c b/src/libs/xpcom18a4/nsprpub/pr/tests/op_filok.c
new file mode 100644
index 00000000..acb86a7e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/op_filok.c
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: op_filok.c
+**
+** Description: Test Program to verify the PR_Open finding an existing file.
+**
+** Modification History:
+** 03-June-97 AGarcia- Initial version
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "prinit.h"
+#include "prmem.h"
+#include "prio.h"
+#include "prerror.h"
+#include <stdio.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#else
+#endif
+
+/*
+ * The name of a file that is guaranteed to exist
+ * on every machine of a particular OS.
+ */
+#ifdef VMS
+#define EXISTING_FILENAME "SYS$LOGIN:LOGIN.COM"
+#elif XP_UNIX
+#define EXISTING_FILENAME "/bin/sh"
+#elif defined(WIN32)
+#define EXISTING_FILENAME "c:/autoexec.bat"
+#elif defined(OS2)
+#define EXISTING_FILENAME "c:/config.sys"
+#elif defined(BEOS)
+#define EXISTING_FILENAME "/boot/beos/bin/sh"
+#else
+#error "Unknown OS"
+#endif
+
+static PRFileDesc *t1;
+
+int main(int argc, char **argv)
+{
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("pr_open_re.log");
+#endif
+
+ PR_STDIO_INIT();
+
+ t1 = PR_Open(EXISTING_FILENAME, PR_RDONLY, 0666);
+
+ if (t1 == NULL) {
+ printf ("error code is %d \n", PR_GetError());
+ printf ("File %s should be found\n",
+ EXISTING_FILENAME);
+ return 1;
+ } else {
+ if (PR_Close(t1) == PR_SUCCESS) {
+ printf ("Test passed \n");
+ return 0;
+ } else {
+ printf ("cannot close file\n");
+ printf ("error code is %d\n", PR_GetError());
+ return 1;
+ }
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/op_noacc.c b/src/libs/xpcom18a4/nsprpub/pr/tests/op_noacc.c
new file mode 100644
index 00000000..ab1254de
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/op_noacc.c
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: op_noacc.c
+**
+** Description: Test Program to verify the PR_NO_ACCESS_RIGHTS_ERROR in PR_Open
+**
+** Modification History:
+** 03-June-97 AGarcia- Initial version
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "prinit.h"
+#include "prmem.h"
+#include "prio.h"
+#include "prerror.h"
+#include <stdio.h>
+#include "plgetopt.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#else
+#endif
+
+static PRFileDesc *err01;
+PRIntn error_code;
+
+int main(int argc, char **argv)
+{
+
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("pr_open_re.log");
+#endif
+
+#ifdef XP_PC
+ printf("op_noacc: Test not valid on MS-Windows.\n\tNo concept of 'mode' on Open() call\n");
+ return(0);
+#endif
+
+
+ PR_STDIO_INIT();
+ err01 = PR_Open("err01.tmp", PR_CREATE_FILE | PR_RDWR, 0);
+ if (err01 == NULL)
+ if (PR_GetError() == PR_NO_ACCESS_RIGHTS_ERROR) {
+ printf ("error code is %d\n",PR_GetError());
+ printf ("PASS\n");
+ return 0;
+ }
+ else {
+ printf ("FAIL\n");
+ return 1;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/op_nofil.c b/src/libs/xpcom18a4/nsprpub/pr/tests/op_nofil.c
new file mode 100644
index 00000000..20bc11e1
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/op_nofil.c
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: op_nofil.c
+**
+** Description: Test Program to verify the PR_FILE_NOT_FOUND_ERROR
+**
+** Modification History:
+** 03-June-97 AGarcia- Initial version
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "prinit.h"
+#include "prmem.h"
+#include "prio.h"
+#include "prerror.h"
+#include <stdio.h>
+#include "plgetopt.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#else
+#endif
+
+/*
+ * A file name that cannot exist
+ */
+#define NO_SUCH_FILE "/no/such/file.tmp"
+
+static PRFileDesc *t1;
+
+int main(int argc, char **argv)
+{
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("pr_open_re.log");
+#endif
+
+ PR_STDIO_INIT();
+ t1 = PR_Open(NO_SUCH_FILE, PR_RDONLY, 0666);
+ if (t1 == NULL) {
+ if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) {
+ printf ("error code is PR_FILE_NOT_FOUND_ERROR, as expected\n");
+ printf ("PASS\n");
+ return 0;
+ } else {
+ printf ("error code is %d \n", PR_GetError());
+ printf ("FAIL\n");
+ return 1;
+ }
+ }
+ printf ("File %s exists on this machine!?\n", NO_SUCH_FILE);
+ if (PR_Close(t1) == PR_FAILURE) {
+ printf ("cannot close file\n");
+ printf ("error code is %d \n", PR_GetError());
+ }
+ printf ("FAIL\n");
+ return 1;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/openfile.c b/src/libs/xpcom18a4/nsprpub/pr/tests/openfile.c
new file mode 100644
index 00000000..8f863c06
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/openfile.c
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * This test calls PR_OpenFile to create a bunch of files
+ * with various file modes.
+ */
+
+#include "prio.h"
+#include "prerror.h"
+#include "prinit.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TEMPLATE_FILE_NAME "template.txt"
+
+int main()
+{
+ FILE *template;
+ char buf[32];
+ PRInt32 nbytes;
+ PRFileDesc *fd;
+
+
+ /* Write in text mode. Let stdio deal with line endings. */
+ template = fopen(TEMPLATE_FILE_NAME, "w");
+ fputs("line 1\nline 2\n", template);
+ fclose(template);
+
+ /* Read in binary mode */
+ fd = PR_OpenFile(TEMPLATE_FILE_NAME, PR_RDONLY, 0666);
+ nbytes = PR_Read(fd, buf, sizeof(buf));
+ PR_Close(fd);
+ PR_Delete(TEMPLATE_FILE_NAME);
+
+ fd = PR_OpenFile("tfil0700.txt", PR_RDWR | PR_CREATE_FILE, 0700);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0500.txt", PR_RDWR | PR_CREATE_FILE, 0500);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0400.txt", PR_RDWR | PR_CREATE_FILE, 0400);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0644.txt", PR_RDWR | PR_CREATE_FILE, 0644);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0664.txt", PR_RDWR | PR_CREATE_FILE, 0664);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0660.txt", PR_RDWR | PR_CREATE_FILE, 0660);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0666.txt", PR_RDWR | PR_CREATE_FILE, 0666);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ fd = PR_OpenFile("tfil0640.txt", PR_RDWR | PR_CREATE_FILE, 0640);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_OpenFile failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ PR_Write(fd, buf, nbytes);
+ PR_Close(fd);
+
+ PR_Cleanup();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/parent.c b/src/libs/xpcom18a4/nsprpub/pr/tests/parent.c
new file mode 100644
index 00000000..a81d5ec6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/parent.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** file: parent.c
+** description: test the process machinery
+*/
+
+#include "prmem.h"
+#include "prprf.h"
+#include "prinit.h"
+#include "prproces.h"
+#include "prinrval.h"
+
+typedef struct Child
+{
+ const char *name;
+ char **argv;
+ PRProcess *process;
+ PRProcessAttr *attr;
+} Child;
+
+/* for the default test 'cvar -c 2000' */
+static char *default_argv[] = {"cvar", "-c", "2000", NULL};
+
+static void PrintUsage(void)
+{
+ PR_fprintf(PR_GetSpecialFD(PR_StandardError),
+ "Usage: parent [-d] child [options]\n");
+}
+
+PRIntn main (PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRInt32 test_status = 1;
+ PRIntervalTime t_start, t_elapsed;
+ PRFileDesc *debug = NULL;
+ Child *child = PR_NEWZAP(Child);
+
+ if (1 == argc)
+ {
+ /* no command-line arguments: run the default test */
+ child->argv = default_argv;
+ }
+ else
+ {
+ argv += 1; /* don't care about our program name */
+ while (*argv != NULL && argv[0][0] == '-')
+ {
+ if (argv[0][1] == 'd')
+ debug = PR_GetSpecialFD(PR_StandardError);
+ else
+ {
+ PrintUsage();
+ return 2; /* not sufficient */
+ }
+ argv += 1;
+ }
+ child->argv = argv;
+ }
+
+ if (NULL == *child->argv)
+ {
+ PrintUsage();
+ return 2;
+ }
+
+ child->name = *child->argv;
+ if (NULL != debug) PR_fprintf(debug, "Forking %s\n", child->name);
+
+ child->attr = PR_NewProcessAttr();
+ PR_ProcessAttrSetStdioRedirect(
+ child->attr, PR_StandardOutput,
+ PR_GetSpecialFD(PR_StandardOutput));
+ PR_ProcessAttrSetStdioRedirect(
+ child->attr, PR_StandardError,
+ PR_GetSpecialFD(PR_StandardError));
+
+ t_start = PR_IntervalNow();
+ child->process = PR_CreateProcess(
+ child->name, child->argv, NULL, child->attr);
+ t_elapsed = (PRIntervalTime) (PR_IntervalNow() - t_start);
+
+ PR_DestroyProcessAttr(child->attr);
+
+ test_status = (NULL == child->process) ? 1 : 0;
+ if (NULL != debug)
+ {
+ PR_fprintf(
+ debug, "Child was %sforked\n",
+ (0 == test_status) ? "" : "NOT ");
+ if (0 == test_status)
+ PR_fprintf(
+ debug, "PR_CreateProcess took %lu microseconds\n",
+ PR_IntervalToMicroseconds(t_elapsed));
+ }
+
+ if (0 == test_status)
+ {
+ if (NULL != debug) PR_fprintf(debug, "Waiting for child to exit\n");
+ rv = PR_WaitProcess(child->process, &test_status);
+ if (PR_SUCCESS == rv)
+ {
+ if (NULL != debug)
+ PR_fprintf(
+ debug, "Child exited %s\n",
+ (0 == test_status) ? "successfully" : "with error");
+ }
+ else
+ {
+ test_status = 1;
+ if (NULL != debug)
+ PR_fprintf(debug, "PR_WaitProcess failed\n");
+ }
+ }
+ PR_DELETE(child);
+ PR_Cleanup();
+ return test_status;
+
+} /* main */
+
+/* parent.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/peek.c b/src/libs/xpcom18a4/nsprpub/pr/tests/peek.c
new file mode 100644
index 00000000..22fcfec6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/peek.c
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * A test case for the PR_MSG_PEEK flag of PR_Recv().
+ *
+ * Test both blocking and non-blocking sockets.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFFER_SIZE 1024
+
+static int iterations = 10;
+
+/*
+ * In iteration i, recv_amount[i] is the number of bytes we
+ * wish to receive, and send_amount[i] is the number of bytes
+ * we actually send. Therefore, the number of elements in the
+ * recv_amount or send_amount array should equal to 'iterations'.
+ * For this test to pass we need to ensure that
+ * recv_amount[i] <= BUFFER_SIZE,
+ * send_amount[i] <= BUFFER_SIZE,
+ * send_amount[i] <= recv_amount[i].
+ */
+static PRInt32 recv_amount[10] = {
+ 16, 128, 256, 1024, 512, 512, 128, 256, 32, 32};
+static PRInt32 send_amount[10] = {
+ 16, 64, 128, 1024, 512, 256, 128, 64, 16, 32};
+
+/* Blocking I/O */
+static void ServerB(void *arg)
+{
+ PRFileDesc *listenSock = (PRFileDesc *) arg;
+ PRFileDesc *sock;
+ char buf[BUFFER_SIZE];
+ PRInt32 nbytes;
+ int i;
+ int j;
+
+ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == sock) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+
+ for (i = 0; i < iterations; i++) {
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "server: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "server: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "server: received expected data\n");
+
+ PR_Sleep(PR_SecondsToInterval(1));
+ memset(buf, 2*i+1, send_amount[i]);
+ nbytes = PR_Send(sock, buf, send_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Send failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ }
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+/* Non-blocking I/O */
+static void ClientNB(void *arg)
+{
+ PRFileDesc *sock;
+ PRSocketOptionData opt;
+ PRUint16 port = (PRUint16) arg;
+ PRNetAddr addr;
+ char buf[BUFFER_SIZE];
+ PRPollDesc pd;
+ PRInt32 npds;
+ PRInt32 nbytes;
+ int i;
+ int j;
+
+ sock = PR_OpenTCPSocket(PR_AF_INET6);
+ if (NULL == sock) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE;
+ if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetSocketOption failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
+ == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+ fprintf(stderr, "PR_Connect failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == npds) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (1 != npds) {
+ fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
+ exit(1);
+ }
+ if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetConnectStatus failed\n");
+ exit(1);
+ }
+ }
+
+ for (i = 0; i < iterations; i++) {
+ PR_Sleep(PR_SecondsToInterval(1));
+ memset(buf, 2*i, send_amount[i]);
+ while ((nbytes = PR_Send(sock, buf, send_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ fprintf(stderr, "PR_Send failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_WRITE;
+ npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == npds) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (1 != npds) {
+ fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
+ exit(1);
+ }
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+
+ memset(buf, 0, sizeof(buf));
+ while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_READ;
+ npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == npds) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (1 != npds) {
+ fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
+ exit(1);
+ }
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i+1) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i+1, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "client: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i+1) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i+1, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "client: peeked expected data\n");
+
+ memset(buf, 0, sizeof(buf));
+ nbytes = PR_Recv(sock, buf, recv_amount[i],
+ 0, PR_INTERVAL_NO_TIMEOUT);
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Recv failed\n");
+ exit(1);
+ }
+ if (send_amount[i] != nbytes) {
+ fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
+ exit(1);
+ }
+ for (j = 0; j < nbytes; j++) {
+ if (buf[j] != 2*i+1) {
+ fprintf(stderr, "byte %d should be %d but is %d\n",
+ j, 2*i+1, buf[j]);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "client: received expected data\n");
+ }
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+static void
+RunTest(PRThreadScope scope, PRFileDesc *listenSock, PRUint16 port)
+{
+ PRThread *server, *client;
+
+ server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock,
+ PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == server) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ client = PR_CreateThread(
+ PR_USER_THREAD, ClientNB, (void *) port,
+ PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == client) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+
+ if (PR_JoinThread(server) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(client) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock;
+ PRNetAddr addr;
+ PRUint16 port;
+
+ listenSock = PR_OpenTCPSocket(PR_AF_INET6);
+ if (NULL == listenSock) {
+ fprintf(stderr, "PR_OpenTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_SetNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ port = PR_ntohs(addr.ipv6.port);
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ fprintf(stderr, "Running the test with local threads\n");
+ RunTest(PR_LOCAL_THREAD, listenSock, port);
+ fprintf(stderr, "Running the test with global threads\n");
+ RunTest(PR_GLOBAL_THREAD, listenSock, port);
+
+ if (PR_Close(listenSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/perf.c b/src/libs/xpcom18a4/nsprpub/pr/tests/perf.c
new file mode 100644
index 00000000..edd3a6ef
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/perf.c
@@ -0,0 +1,485 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int _debug_on = 0;
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "prsem.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#else
+#include "obsolete/prsem.h"
+#endif
+
+PRLock *lock;
+PRMonitor *mon;
+PRMonitor *mon2;
+
+#define DEFAULT_COUNT 1000
+
+PRInt32 count;
+
+static void nop(int a, int b, int c)
+{
+}
+
+static void LocalProcedureCall(void)
+{
+ PRInt32 i;
+
+ for (i = 0; i < count; i++) {
+ nop(i, i, 5);
+ }
+}
+
+static void DLLProcedureCall(void)
+{
+ PRInt32 i;
+ PRThreadState state;
+ PRThread *self = PR_CurrentThread();
+
+ for (i = 0; i < count; i++) {
+ state = PR_GetThreadState(self);
+ }
+}
+
+static void Now(void)
+{
+ PRInt32 i;
+ PRTime time;
+
+ for (i = 0; i < count; i++) {
+ time = PR_Now();
+ }
+}
+
+static void Interval(void)
+{
+ PRInt32 i;
+ PRIntervalTime time;
+
+ for (i = 0; i < count; i++) {
+ time = PR_IntervalNow();
+ }
+}
+
+static void IdleLock(void)
+{
+ PRInt32 i;
+
+ for (i = 0; i < count; i++) {
+ PR_Lock(lock);
+ PR_Unlock(lock);
+ }
+}
+
+static void IdleMonitor(void)
+{
+ PRInt32 i;
+
+ for (i = 0; i < count; i++) {
+ PR_EnterMonitor(mon);
+ PR_ExitMonitor(mon);
+ }
+}
+
+static void IdleCMonitor(void)
+{
+ PRInt32 i;
+
+ for (i = 0; i < count; i++) {
+ PR_CEnterMonitor((void*)7);
+ PR_CExitMonitor((void*)7);
+ }
+}
+
+/************************************************************************/
+
+static void PR_CALLBACK dull(void *arg)
+{
+}
+
+static void CDThread(void)
+{
+ PRInt32 i;
+ int num_threads = count;
+
+ /*
+ * Cannot create too many threads
+ */
+ if (num_threads > 1000)
+ num_threads = 1000;
+
+ for (i = 0; i < num_threads; i++) {
+ PRThread *t = PR_CreateThread(PR_USER_THREAD,
+ dull, 0,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (NULL == t) {
+ fprintf(stderr, "CDThread: cannot create thread %3d\n", i);
+ } else {
+ DPRINTF(("CDThread: created thread %3d \n",i));
+ }
+ PR_Sleep(0);
+ }
+}
+
+static int alive;
+static int cxq;
+
+static void PR_CALLBACK CXReader(void *arg)
+{
+ PRInt32 i, n;
+
+ PR_EnterMonitor(mon);
+ n = count / 2;
+ for (i = 0; i < n; i++) {
+ while (cxq == 0) {
+ DPRINTF(("CXReader: thread = 0x%lx waiting\n",
+ PR_GetCurrentThread()));
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ --cxq;
+ PR_Notify(mon);
+ }
+ PR_ExitMonitor(mon);
+
+ PR_EnterMonitor(mon2);
+ --alive;
+ PR_Notify(mon2);
+ PR_ExitMonitor(mon2);
+ DPRINTF(("CXReader: thread = 0x%lx exiting\n", PR_GetCurrentThread()));
+}
+
+static void PR_CALLBACK CXWriter(void *arg)
+{
+ PRInt32 i, n;
+
+ PR_EnterMonitor(mon);
+ n = count / 2;
+ for (i = 0; i < n; i++) {
+ while (cxq == 1) {
+ DPRINTF(("CXWriter: thread = 0x%lx waiting\n",
+ PR_GetCurrentThread()));
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ ++cxq;
+ PR_Notify(mon);
+ }
+ PR_ExitMonitor(mon);
+
+ PR_EnterMonitor(mon2);
+ --alive;
+ PR_Notify(mon2);
+ PR_ExitMonitor(mon2);
+ DPRINTF(("CXWriter: thread = 0x%lx exiting\n", PR_GetCurrentThread()));
+}
+
+static void ContextSwitch(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *t1, *t2;
+
+ PR_EnterMonitor(mon2);
+ alive = 2;
+ cxq = 0;
+
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ CXReader, 0,
+ PR_PRIORITY_NORMAL,
+ scope1,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (NULL == t1) {
+ fprintf(stderr, "ContextSwitch: cannot create thread\n");
+ } else {
+ DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n",
+ (scope1 == PR_GLOBAL_THREAD ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
+ t1));
+ }
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ CXWriter, 0,
+ PR_PRIORITY_NORMAL,
+ scope2,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (NULL == t2) {
+ fprintf(stderr, "ContextSwitch: cannot create thread\n");
+ } else {
+ DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n",
+ (scope2 == PR_GLOBAL_THREAD ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
+ t2));
+ }
+
+ /* Wait for both of the threads to exit */
+ while (alive) {
+ PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(mon2);
+}
+
+static void ContextSwitchUU(void)
+{
+ ContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void ContextSwitchUK(void)
+{
+ ContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+static void ContextSwitchKU(void)
+{
+ ContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void ContextSwitchKK(void)
+{
+ ContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+/************************************************************************/
+
+static void PR_CALLBACK SemaThread(void *argSema)
+{
+ PRSemaphore **sem = (PRSemaphore **)argSema;
+ PRInt32 i, n;
+
+ n = count / 2;
+ for (i = 0; i < n; i++) {
+ DPRINTF(("SemaThread: thread = 0x%lx waiting on sem = 0x%lx\n",
+ PR_GetCurrentThread(), sem[0]));
+ PR_WaitSem(sem[0]);
+ DPRINTF(("SemaThread: thread = 0x%lx posting on sem = 0x%lx\n",
+ PR_GetCurrentThread(), sem[1]));
+ PR_PostSem(sem[1]);
+ }
+
+ PR_EnterMonitor(mon2);
+ --alive;
+ PR_Notify(mon2);
+ PR_ExitMonitor(mon2);
+ DPRINTF(("SemaThread: thread = 0x%lx exiting\n", PR_GetCurrentThread()));
+}
+
+static PRSemaphore *sem_set1[2];
+static PRSemaphore *sem_set2[2];
+
+static void SemaContextSwitch(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *t1, *t2;
+ sem_set1[0] = PR_NewSem(1);
+ sem_set1[1] = PR_NewSem(0);
+ sem_set2[0] = sem_set1[1];
+ sem_set2[1] = sem_set1[0];
+
+ PR_EnterMonitor(mon2);
+ alive = 2;
+ cxq = 0;
+
+ t1 = PR_CreateThread(PR_USER_THREAD,
+ SemaThread,
+ sem_set1,
+ PR_PRIORITY_NORMAL,
+ scope1,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (NULL == t1) {
+ fprintf(stderr, "SemaContextSwitch: cannot create thread\n");
+ } else {
+ DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n",
+ (scope1 == PR_GLOBAL_THREAD ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
+ t1));
+ }
+ t2 = PR_CreateThread(PR_USER_THREAD,
+ SemaThread,
+ sem_set2,
+ PR_PRIORITY_NORMAL,
+ scope2,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (NULL == t2) {
+ fprintf(stderr, "SemaContextSwitch: cannot create thread\n");
+ } else {
+ DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n",
+ (scope2 == PR_GLOBAL_THREAD ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"),
+ t2));
+ }
+
+ /* Wait for both of the threads to exit */
+ while (alive) {
+ PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(mon2);
+
+ PR_DestroySem(sem_set1[0]);
+ PR_DestroySem(sem_set1[1]);
+}
+
+static void SemaContextSwitchUU(void)
+{
+ SemaContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void SemaContextSwitchUK(void)
+{
+ SemaContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+static void SemaContextSwitchKU(void)
+{
+ SemaContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void SemaContextSwitchKK(void)
+{
+ SemaContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow() - start;
+ d = (double)PR_IntervalToMicroseconds(stop);
+
+ printf("%40s: %6.2f usec\n", msg, d / count);
+}
+
+int main(int argc, char **argv)
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 'c': /* loop count */
+ count = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == count) count = DEFAULT_COUNT;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_BlockClockInterrupts();
+ PR_UnblockClockInterrupts();
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("perf.log");
+#endif
+
+ lock = PR_NewLock();
+ mon = PR_NewMonitor();
+ mon2 = PR_NewMonitor();
+
+ Measure(LocalProcedureCall, "local procedure call overhead");
+ Measure(DLLProcedureCall, "DLL procedure call overhead");
+ Measure(Now, "current calendar time");
+ Measure(Interval, "interval time");
+ Measure(IdleLock, "idle lock lock/unlock pair");
+ Measure(IdleMonitor, "idle monitor entry/exit pair");
+ Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
+ Measure(CDThread, "create/destroy thread pair");
+ Measure(ContextSwitchUU, "context switch - user/user");
+ Measure(ContextSwitchUK, "context switch - user/kernel");
+ Measure(ContextSwitchKU, "context switch - kernel/user");
+ Measure(ContextSwitchKK, "context switch - kernel/kernel");
+ Measure(SemaContextSwitchUU, "sema context switch - user/user");
+ Measure(SemaContextSwitchUK, "sema context switch - user/kernel");
+ Measure(SemaContextSwitchKU, "sema context switch - kernel/user");
+ Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel");
+
+ printf("--------------\n");
+ printf("Adding 7 additional CPUs\n");
+
+ PR_SetConcurrency(8);
+ printf("--------------\n");
+
+ Measure(LocalProcedureCall, "local procedure call overhead");
+ Measure(DLLProcedureCall, "DLL procedure call overhead");
+ Measure(Now, "current calendar time");
+ Measure(Interval, "interval time");
+ Measure(IdleLock, "idle lock lock/unlock pair");
+ Measure(IdleMonitor, "idle monitor entry/exit pair");
+ Measure(IdleCMonitor, "idle cache monitor entry/exit pair");
+ Measure(CDThread, "create/destroy thread pair");
+ Measure(ContextSwitchUU, "context switch - user/user");
+ Measure(ContextSwitchUK, "context switch - user/kernel");
+ Measure(ContextSwitchKU, "context switch - kernel/user");
+ Measure(ContextSwitchKK, "context switch - kernel/kernel");
+ Measure(SemaContextSwitchUU, "sema context switch - user/user");
+ Measure(SemaContextSwitchUK, "sema context switch - user/kernel");
+ Measure(SemaContextSwitchKU, "sema context switch - kernel/user");
+ Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel");
+
+ PR_DestroyLock(lock);
+ PR_DestroyMonitor(mon);
+ PR_DestroyMonitor(mon2);
+
+ PR_Cleanup();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/pipeping.c b/src/libs/xpcom18a4/nsprpub/pr/tests/pipeping.c
new file mode 100644
index 00000000..dd18eb6f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/pipeping.c
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: pipeping.c
+ *
+ * Description:
+ * This test runs in conjunction with the pipepong test.
+ * This test creates two pipes and redirects the stdin and
+ * stdout of the pipepong test to the pipes. Then this
+ * test writes "ping" to the pipepong test and the pipepong
+ * test writes "pong" back. To run this pair of tests,
+ * just invoke pipeping.
+ *
+ * Tested areas: process creation, pipes, file descriptor
+ * inheritance, standard I/O redirection.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+#include "prproces.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_OS2
+static char *child_argv[] = { "pipepong.exe", NULL };
+#else
+static char *child_argv[] = { "pipepong", NULL };
+#endif
+
+#define NUM_ITERATIONS 10
+
+int main()
+{
+ PRFileDesc *in_pipe[2];
+ PRFileDesc *out_pipe[2];
+ PRStatus status;
+ PRProcess *process;
+ PRProcessAttr *attr;
+ char buf[1024];
+ PRInt32 nBytes;
+ PRInt32 exitCode;
+ int idx;
+
+ status = PR_CreatePipe(&in_pipe[0], &in_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+ status = PR_CreatePipe(&out_pipe[0], &out_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+
+ status = PR_SetFDInheritable(in_pipe[0], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(in_pipe[1], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(out_pipe[0], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(out_pipe[1], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+
+ attr = PR_NewProcessAttr();
+ if (attr == NULL) {
+ fprintf(stderr, "PR_NewProcessAttr failed\n");
+ exit(1);
+ }
+
+ PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, out_pipe[0]);
+ PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, in_pipe[1]);
+
+ process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr);
+ if (process == NULL) {
+ fprintf(stderr, "PR_CreateProcess failed\n");
+ exit(1);
+ }
+ PR_DestroyProcessAttr(attr);
+ status = PR_Close(out_pipe[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(in_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ strcpy(buf, "ping");
+ printf("ping process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(out_pipe[1], buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ }
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(in_pipe[0], buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("ping process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "pong") != 0) {
+ fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+ }
+
+ status = PR_Close(in_pipe[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(out_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_WaitProcess(process, &exitCode);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitProcess failed\n");
+ exit(1);
+ }
+ if (exitCode == 0) {
+ printf("PASS\n");
+ return 0;
+ } else {
+ printf("FAIL\n");
+ return 1;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/pipeping2.c b/src/libs/xpcom18a4/nsprpub/pr/tests/pipeping2.c
new file mode 100644
index 00000000..b1f2b420
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/pipeping2.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * File: pipeping2.c
+ *
+ * Description:
+ * This test runs in conjunction with the pipepong2 test.
+ * This test creates two pipes and passes two pipe fd's
+ * to the pipepong2 test. Then this test writes "ping" to
+ * to the pipepong2 test and the pipepong2 test writes "pong"
+ * back. To run this pair of tests, just invoke pipeping2.
+ *
+ * Tested areas: process creation, pipes, file descriptor
+ * inheritance.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+#include "prproces.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+static char *child_argv[] = { "pipepong2", NULL };
+
+int main()
+{
+ PRFileDesc *in_pipe[2];
+ PRFileDesc *out_pipe[2];
+ PRStatus status;
+ PRProcess *process;
+ PRProcessAttr *attr;
+ char buf[1024];
+ PRInt32 nBytes;
+ PRInt32 exitCode;
+ int idx;
+
+ status = PR_CreatePipe(&in_pipe[0], &in_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+ status = PR_CreatePipe(&out_pipe[0], &out_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+
+ status = PR_SetFDInheritable(in_pipe[0], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(in_pipe[1], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(out_pipe[0], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(out_pipe[1], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+
+ attr = PR_NewProcessAttr();
+ if (attr == NULL) {
+ fprintf(stderr, "PR_NewProcessAttr failed\n");
+ exit(1);
+ }
+
+ status = PR_ProcessAttrSetInheritableFD(attr, out_pipe[0], "PIPE_READ");
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n");
+ exit(1);
+ }
+ status = PR_ProcessAttrSetInheritableFD(attr, in_pipe[1], "PIPE_WRITE");
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n");
+ exit(1);
+ }
+
+ process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr);
+ if (process == NULL) {
+ fprintf(stderr, "PR_CreateProcess failed\n");
+ exit(1);
+ }
+ PR_DestroyProcessAttr(attr);
+ status = PR_Close(out_pipe[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(in_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ strcpy(buf, "ping");
+ printf("ping process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(out_pipe[1], buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(in_pipe[0], buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ printf("ping process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "pong") != 0) {
+ fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+ }
+
+ status = PR_Close(in_pipe[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(out_pipe[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_WaitProcess(process, &exitCode);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitProcess failed\n");
+ exit(1);
+ }
+ if (exitCode == 0) {
+ printf("PASS\n");
+ return 0;
+ } else {
+ printf("FAIL\n");
+ return 1;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/pipepong.c b/src/libs/xpcom18a4/nsprpub/pr/tests/pipepong.c
new file mode 100644
index 00000000..66771601
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/pipepong.c
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: pipepong.c
+ *
+ * Description:
+ * This test runs in conjunction with the pipeping test.
+ * The pipeping test creates two pipes and redirects the
+ * stdin and stdout of this test to the pipes. Then the
+ * pipeping test writes "ping" to this test and this test
+ * writes "pong" back. Note that this test does not depend
+ * on NSPR at all. To run this pair of tests, just invoke
+ * pipeping.
+ *
+ * Tested areas: process creation, pipes, file descriptor
+ * inheritance, standard I/O redirection.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+int main()
+{
+ char buf[1024];
+ size_t nBytes;
+ int idx;
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ memset(buf, 0, sizeof(buf));
+ nBytes = fread(buf, 1, 5, stdin);
+ fprintf(stderr, "pong process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "ping") != 0) {
+ fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+
+ strcpy(buf, "pong");
+ fprintf(stderr, "pong process: sending \"%s\"\n", buf);
+ nBytes = fwrite(buf, 1, 5, stdout);
+ if (nBytes != 5) {
+ fprintf(stderr, "pong process: fwrite failed\n");
+ exit(1);
+ }
+ fflush(stdout);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/pipepong2.c b/src/libs/xpcom18a4/nsprpub/pr/tests/pipepong2.c
new file mode 100644
index 00000000..19494bbd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/pipepong2.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * File: pipepong2.c
+ *
+ * Description:
+ * This test runs in conjunction with the pipeping2 test.
+ * The pipeping2 test creates two pipes and passes two
+ * pipe fd's to this test. Then the pipeping2 test writes
+ * "ping" to this test and this test writes "pong" back.
+ * To run this pair of tests, just invoke pipeping2.
+ *
+ * Tested areas: process creation, pipes, file descriptor
+ * inheritance.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+int main()
+{
+ PRFileDesc *pipe_read, *pipe_write;
+ PRStatus status;
+ char buf[1024];
+ PRInt32 nBytes;
+ int idx;
+
+ pipe_read = PR_GetInheritedFD("PIPE_READ");
+ if (pipe_read == NULL) {
+ fprintf(stderr, "PR_GetInheritedFD failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(pipe_read, PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+ pipe_write = PR_GetInheritedFD("PIPE_WRITE");
+ if (pipe_write == NULL) {
+ fprintf(stderr, "PR_GetInheritedFD failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(pipe_write, PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(pipe_read, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("pong process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "ping") != 0) {
+ fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+
+ strcpy(buf, "pong");
+ printf("pong process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(pipe_write, buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed\n");
+ exit(1);
+ }
+ }
+
+ status = PR_Close(pipe_read);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(pipe_write);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/pipeself.c b/src/libs/xpcom18a4/nsprpub/pr/tests/pipeself.c
new file mode 100644
index 00000000..5bb9791a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/pipeself.c
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: pipeself.c
+ *
+ * Description:
+ * This test has two threads communicating with each other using
+ * two unidirectional pipes. The primordial thread is the ping
+ * thread and the other thread is the pong thread. The ping
+ * thread writes "ping" to the pong thread and the pong thread
+ * writes "pong" back.
+ */
+
+#include "prio.h"
+#include "prerror.h"
+#include "prthread.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NUM_ITERATIONS 10
+
+static PRFileDesc *ping_in, *ping_out;
+static PRFileDesc *pong_in, *pong_out;
+
+static void PongThreadFunc(void *arg)
+{
+ char buf[1024];
+ int idx;
+ PRInt32 nBytes;
+ PRStatus status;
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(pong_in, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ printf("pong thread: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "pong thread: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "ping") != 0) {
+ fprintf(stderr, "pong thread: expected \"ping\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+ strcpy(buf, "pong");
+ printf("pong thread: sending \"%s\"\n", buf);
+ nBytes = PR_Write(pong_out, buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ }
+ }
+
+ status = PR_Close(pong_in);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(pong_out);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+int main()
+{
+ PRStatus status;
+ PRThread *pongThread;
+ char buf[1024];
+ PRInt32 nBytes;
+ int idx;
+
+ status = PR_CreatePipe(&ping_in, &pong_out);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+ status = PR_CreatePipe(&pong_in, &ping_out);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+
+ pongThread = PR_CreateThread(PR_USER_THREAD, PongThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (pongThread == NULL) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ strcpy(buf, "ping");
+ printf("ping thread: sending \"%s\"\n", buf);
+ nBytes = PR_Write(ping_out, buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ }
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(ping_in, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ printf("ping thread: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "ping thread: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "pong") != 0) {
+ fprintf(stderr, "ping thread: expected \"pong\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+ }
+
+ status = PR_Close(ping_in);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(ping_out);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_JoinThread(pongThread);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+
+#ifdef XP_UNIX
+ /*
+ * Test PR_Available for pipes
+ */
+ status = PR_CreatePipe(&ping_in, &ping_out);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_CreatePipe failed\n");
+ exit(1);
+ }
+ nBytes = PR_Write(ping_out, buf, 250);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ }
+ nBytes = PR_Available(ping_in);
+ if (nBytes < 0) {
+ fprintf(stderr, "PR_Available failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ } else if (nBytes != 250) {
+ fprintf(stderr, "PR_Available: expected 250 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ printf("PR_Available: expected %d, got %d bytes\n",250, nBytes);
+ /* read some data */
+ nBytes = PR_Read(ping_in, buf, 7);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ /* check available data */
+ nBytes = PR_Available(ping_in);
+ if (nBytes < 0) {
+ fprintf(stderr, "PR_Available failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ } else if (nBytes != (250 - 7)) {
+ fprintf(stderr, "PR_Available: expected 243 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ printf("PR_Available: expected %d, got %d bytes\n",243, nBytes);
+ /* read all data */
+ nBytes = PR_Read(ping_in, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ } else if (nBytes != 243) {
+ fprintf(stderr, "PR_Read failed: expected %d, got %d bytes\n",
+ 243, nBytes);
+ exit(1);
+ }
+ /* check available data */
+ nBytes = PR_Available(ping_in);
+ if (nBytes < 0) {
+ fprintf(stderr, "PR_Available failed: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ } else if (nBytes != 0) {
+ fprintf(stderr, "PR_Available: expected 0 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ printf("PR_Available: expected %d, got %d bytes\n", 0, nBytes);
+
+ status = PR_Close(ping_in);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_Close(ping_out);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+#endif /* XP_UNIX */
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/poll_er.c b/src/libs/xpcom18a4/nsprpub/pr/tests/poll_er.c
new file mode 100644
index 00000000..b68c7986
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/poll_er.c
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: prpoll_err.c
+**
+** Description: This program tests PR_Poll with sockets.
+** error reporting operation is tested
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+#ifdef XP_BEOS
+#include <stdio.h>
+int main()
+{
+ printf( "This test is not ported to the BeOS\n" );
+ return 0;
+}
+#else
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "primpl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+static void
+ClientThreadFunc(void *arg)
+{
+ PRFileDesc *badFD = (PRFileDesc *) arg;
+ /*
+ * Make the fd invalid
+ */
+#if defined(XP_UNIX)
+ close(PR_FileDesc2NativeHandle(badFD));
+#elif defined(XP_OS2)
+ soclose(PR_FileDesc2NativeHandle(badFD));
+#elif defined(WIN32) || defined(WIN16)
+ closesocket(PR_FileDesc2NativeHandle(badFD));
+#elif defined(XP_MAC)
+ _PR_MD_CLOSE_SOCKET(PR_FileDesc2NativeHandle(badFD));
+#else
+#error "Unknown architecture"
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1, *listenSock2;
+ PRFileDesc *badFD;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ char buf[128];
+ PRPollDesc pds0[10], pds1[10], *pds, *other_pds;
+ PRIntn npds;
+ PRInt32 retVal;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) {
+ printf("This program tests PR_Poll with sockets.\n");
+ printf("error reporting is tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ if (debug_mode) printf("%s", buf);
+
+ /* Set up the poll descriptor array */
+ pds = pds0;
+ other_pds = pds1;
+ memset(pds, 0, sizeof(pds));
+ pds[0].fd = listenSock1;
+ pds[0].in_flags = PR_POLL_READ;
+ pds[1].fd = listenSock2;
+ pds[1].in_flags = PR_POLL_READ;
+ npds = 2;
+
+
+ /* Testing bad fd */
+ if (debug_mode) printf("PR_Poll should detect a bad file descriptor\n");
+ if ((badFD = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a TCP socket\n");
+ goto exit_now;
+ }
+
+ pds[2].fd = badFD;
+ pds[2].in_flags = PR_POLL_READ;
+ npds = 3;
+
+ if (PR_CreateThread(PR_USER_THREAD, ClientThreadFunc,
+ badFD, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0) == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+
+ retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
+ if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) {
+ fprintf(stderr, "Failed to detect the bad fd: "
+ "PR_Poll returns %d, out_flags is 0x%hx\n",
+ retVal, pds[2].out_flags);
+ failed_already=1;
+ goto exit_now;
+ }
+ if (debug_mode) printf("PR_Poll detected the bad fd. Test passed.\n\n");
+ PR_Cleanup();
+ goto exit_now;
+exit_now:
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+}
+
+#endif /* XP_BEOS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/poll_nm.c b/src/libs/xpcom18a4/nsprpub/pr/tests/poll_nm.c
new file mode 100644
index 00000000..63a64a63
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/poll_nm.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: prpoll_norm.c
+**
+** Description: This program tests PR_Poll with sockets.
+** Normal operation are tested
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prnetdb.h"
+#ifndef XP_MAC
+#include "obsolete/probslet.h"
+#else
+#include "probslet.h"
+#endif
+
+#ifndef XP_MAC
+#include "private/pprio.h"
+#else
+#include "pprio.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+#define NUM_ITERATIONS 5
+
+#ifdef XP_MAC
+int fprintf(FILE *stream, const char *fmt, ...)
+{
+PR_LogPrint(fmt);
+return 0;
+}
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+static void PR_CALLBACK
+clientThreadFunc(void *arg)
+{
+ PRUintn port = (PRUintn) arg;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ char buf[128];
+ int i;
+ PRStatus sts;
+ PRInt32 n;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons((PRUint16)port);
+ addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ memset(buf, 0, sizeof(buf));
+ PR_snprintf(buf, sizeof(buf), "%hu", port);
+
+ for (i = 0; i < NUM_ITERATIONS; i++) {
+ sock = PR_NewTCPSocket();
+ PR_ASSERT(sock != NULL);
+
+ sts = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(sts == PR_SUCCESS);
+
+ n = PR_Write(sock, buf, sizeof(buf));
+ PR_ASSERT(n >= 0);
+
+ sts = PR_Close(sock);
+ PR_ASSERT(sts == PR_SUCCESS);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ char buf[128];
+ PRThread *clientThread;
+ PRPollDesc pds0[20], pds1[20], *pds, *other_pds;
+ PRIntn npds;
+ PRInt32 retVal;
+ PRIntn i, j;
+ PRSocketOptionData optval;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ debug_mode = 1;
+ SetupMacPrintfLog("poll_nm.log");
+#endif
+
+ if (debug_mode) {
+ printf("This program tests PR_Poll with sockets.\n");
+ printf("Normal operation are tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ optval.option = PR_SockOpt_Nonblocking;
+ optval.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(listenSock1, &optval);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ PR_SetSocketOption(listenSock2, &optval);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ if (debug_mode) printf("%s", buf);
+
+ /* Set up the poll descriptor array */
+ pds = pds0;
+ other_pds = pds1;
+ memset(pds, 0, sizeof(pds));
+ pds[0].fd = listenSock1;
+ pds[0].in_flags = PR_POLL_READ;
+ pds[1].fd = listenSock2;
+ pds[1].in_flags = PR_POLL_READ;
+ /* Add some unused entries to test if they are ignored by PR_Poll() */
+ memset(&pds[2], 0, sizeof(pds[2]));
+ memset(&pds[3], 0, sizeof(pds[3]));
+ memset(&pds[4], 0, sizeof(pds[4]));
+ npds = 5;
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort1,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort2,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if (debug_mode) {
+ printf("Two client threads are created. Each of them will\n");
+ printf("send data to one of the two ports the server is listening on.\n");
+ printf("The data they send is the port number. Each of them send\n");
+ printf("the data five times, so you should see ten lines below,\n");
+ printf("interleaved in an arbitrary order.\n");
+ }
+
+ /* two clients, three events per iteration: accept, read, close */
+ i = 0;
+ while (i < 2 * 3 * NUM_ITERATIONS) {
+ PRPollDesc *tmp;
+ int nextIndex;
+ int nEvents = 0;
+
+ retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(retVal != 0); /* no timeout */
+ if (retVal == -1) {
+ fprintf(stderr, "PR_Poll failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ nextIndex = 2;
+ /* the two listening sockets */
+ for (j = 0; j < 2; j++) {
+ other_pds[j] = pds[j];
+ PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0
+ && (pds[j].out_flags & PR_POLL_EXCEPT) == 0);
+ if (pds[j].out_flags & PR_POLL_READ) {
+ PRFileDesc *sock;
+
+ nEvents++;
+ sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (sock == NULL) {
+ fprintf(stderr, "PR_Accept() failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ other_pds[nextIndex].fd = sock;
+ other_pds[nextIndex].in_flags = PR_POLL_READ;
+ nextIndex++;
+ } else if (pds[j].out_flags & PR_POLL_ERR) {
+ fprintf(stderr, "PR_Poll() indicates that an fd has error\n");
+ failed_already=1;
+ goto exit_now;
+ } else if (pds[j].out_flags & PR_POLL_NVAL) {
+ fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n",
+ PR_FileDesc2NativeHandle(pds[j].fd));
+ failed_already=1;
+ goto exit_now;
+ }
+ }
+
+ for (j = 2; j < npds; j++) {
+ if (NULL == pds[j].fd) {
+ /*
+ * Keep the unused entries in the poll descriptor array
+ * for testing purposes.
+ */
+ other_pds[nextIndex] = pds[j];
+ nextIndex++;
+ continue;
+ }
+
+ PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0
+ && (pds[j].out_flags & PR_POLL_EXCEPT) == 0);
+ if (pds[j].out_flags & PR_POLL_READ) {
+ PRInt32 nAvail;
+ PRInt32 nRead;
+
+ nEvents++;
+ nAvail = PR_Available(pds[j].fd);
+ nRead = PR_Read(pds[j].fd, buf, sizeof(buf));
+ PR_ASSERT(nAvail == nRead);
+ if (nRead == -1) {
+ fprintf(stderr, "PR_Read() failed\n");
+ failed_already=1;
+ goto exit_now;
+ } else if (nRead == 0) {
+ PR_Close(pds[j].fd);
+ continue;
+ } else {
+ /* Just to be safe */
+ buf[127] = '\0';
+ if (debug_mode) printf("The server received \"%s\" from a client\n", buf);
+ }
+ } else if (pds[j].out_flags & PR_POLL_ERR) {
+ fprintf(stderr, "PR_Poll() indicates that an fd has error\n");
+ failed_already=1;
+ goto exit_now;
+ } else if (pds[j].out_flags & PR_POLL_NVAL) {
+ fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ other_pds[nextIndex] = pds[j];
+ nextIndex++;
+ }
+
+ PR_ASSERT(retVal == nEvents);
+ /* swap */
+ tmp = pds;
+ pds = other_pds;
+ other_pds = tmp;
+ npds = nextIndex;
+ i += nEvents;
+ }
+
+ if (debug_mode) printf("Tests passed\n");
+
+exit_now:
+
+ if (listenSock1) {
+ PR_Close(listenSock1);
+ }
+ if (listenSock2) {
+ PR_Close(listenSock2);
+ }
+
+ PR_Cleanup();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/poll_to.c b/src/libs/xpcom18a4/nsprpub/pr/tests/poll_to.c
new file mode 100644
index 00000000..93fcc79d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/poll_to.c
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: prpoll_to.c
+**
+** Description: This program tests PR_Poll with sockets.
+** Timeout operation is tested
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prnetdb.h"
+
+#ifndef XP_MAC
+#include "private/pprio.h"
+#else
+#include "pprio.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ char buf[128];
+ PRPollDesc pds0[10], pds1[10], *pds, *other_pds;
+ PRIntn npds;
+ PRInt32 retVal;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) {
+ printf("This program tests PR_Poll with sockets.\n");
+ printf("Timeout is tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ if (debug_mode) printf("%s", buf);
+
+ /* Set up the poll descriptor array */
+ pds = pds0;
+ other_pds = pds1;
+ memset(pds, 0, sizeof(pds));
+ pds[0].fd = listenSock1;
+ pds[0].in_flags = PR_POLL_READ;
+ pds[1].fd = listenSock2;
+ pds[1].in_flags = PR_POLL_READ;
+ npds = 2;
+
+ /* Testing timeout */
+ if (debug_mode) printf("PR_Poll should time out in 5 seconds\n");
+ retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5));
+ if (retVal != 0) {
+ PR_snprintf(buf, sizeof(buf),
+ "PR_Poll should time out and return 0, but it returns %ld\n",
+ retVal);
+ fprintf(stderr, "%s", buf);
+ if (!debug_mode) failed_already=1;
+ goto exit_now;
+ }
+ if (debug_mode) printf("PR_Poll timed out. Test passed.\n\n");
+
+exit_now:
+
+ if (listenSock1) {
+ PR_Close(listenSock1);
+ }
+ if (listenSock2) {
+ PR_Close(listenSock2);
+ }
+
+ PR_Cleanup();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/pollable.c b/src/libs/xpcom18a4/nsprpub/pr/tests/pollable.c
new file mode 100644
index 00000000..20da55a3
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/pollable.c
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * A test for the pollable events.
+ *
+ * A number of threads are in a ring configuration, each waiting on
+ * a pollable event that is set by its upstream neighbor.
+ */
+
+#include "prinit.h"
+#include "prio.h"
+#include "prthread.h"
+#include "prerror.h"
+#include "prmem.h"
+#include "prlog.h"
+#include "prprf.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+#define DEFAULT_THREADS 10
+#define DEFAULT_LOOPS 100
+
+PRIntn numThreads = DEFAULT_THREADS;
+PRIntn numIterations = DEFAULT_LOOPS;
+PRIntervalTime dally = PR_INTERVAL_NO_WAIT;
+PRFileDesc *debug_out = NULL;
+PRBool debug_mode = PR_FALSE;
+PRBool verbosity = PR_FALSE;
+
+typedef struct ThreadData {
+ PRFileDesc *event;
+ int index;
+ struct ThreadData *next;
+} ThreadData;
+
+void ThreadRoutine(void *arg)
+{
+ ThreadData *data = (ThreadData *) arg;
+ PRIntn i;
+ PRPollDesc pd;
+ PRInt32 rv;
+
+ pd.fd = data->event;
+ pd.in_flags = PR_POLL_READ;
+
+ for (i = 0; i < numIterations; i++) {
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == -1) {
+ PR_fprintf(PR_STDERR, "PR_Poll failed\n");
+ exit(1);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "thread %d awakened\n", data->index);
+ }
+ PR_ASSERT(rv != 0);
+ PR_ASSERT(pd.out_flags & PR_POLL_READ);
+ if (PR_WaitForPollableEvent(data->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "consume event failed\n");
+ exit(1);
+ }
+ if (dally != PR_INTERVAL_NO_WAIT) {
+ PR_Sleep(dally);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "thread %d posting event\n", data->index);
+ }
+ if (PR_SetPollableEvent(data->next->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "post event failed\n");
+ exit(1);
+ }
+ }
+}
+
+static void Help(void)
+{
+ debug_out = PR_STDOUT;
+
+ PR_fprintf(
+ debug_out, "Usage: pollable [-c n] [-t n] [-d] [-v] [-G] [-C n] [-D n]\n");
+ PR_fprintf(
+ debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
+ PR_fprintf(
+ debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
+ PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
+ PR_fprintf(debug_out, "-D n\tdally setting (msecs) (default: 0)\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ ThreadData selfData;
+ ThreadData *data;
+ PRThread **thread;
+ void *block;
+ PRIntn i;
+ PRIntervalTime timeStart, timeEnd;
+ PRPollDesc pd;
+ PRInt32 rv;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PRBool help = PR_FALSE;
+ PRUintn concurrency = 1;
+ PRUintn average;
+ PLOptStatus os;
+ PLOptState *opt;
+
+ PR_STDIO_INIT();
+
+ opt = PL_CreateOptState(argc, argv, "hdvc:t:C:GD:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) {
+ continue;
+ }
+ switch (opt->option) {
+ case 'v': /* verbose mode */
+ verbosity = PR_TRUE;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop counter */
+ numIterations = atoi(opt->value);
+ break;
+ case 't': /* thread limit */
+ numThreads = atoi(opt->value);
+ break;
+ case 'C': /* Concurrency limit */
+ concurrency = atoi(opt->value);
+ break;
+ case 'G': /* global threads only */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'D': /* dally */
+ dally = PR_MillisecondsToInterval(atoi(opt->value));
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (help) {
+ return 1;
+ }
+
+ if (concurrency > 1) {
+ PR_SetConcurrency(concurrency);
+ }
+
+ if (PR_TRUE == debug_mode) {
+ debug_out = PR_STDOUT;
+ PR_fprintf(debug_out, "Test parameters\n");
+ PR_fprintf(debug_out, "\tThreads involved: %d\n", numThreads);
+ PR_fprintf(debug_out, "\tIteration limit: %d\n", numIterations);
+ PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
+ PR_fprintf(debug_out, "\tThread type: %s\n",
+ (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
+ }
+
+ /*
+ * Malloc a block of memory and divide it into data and thread.
+ */
+ block = PR_MALLOC(numThreads * (sizeof(ThreadData) + sizeof(PRThread *)));
+ if (block == NULL) {
+ PR_fprintf(PR_STDERR, "cannot malloc, failed\n");
+ exit(1);
+ }
+ data = (ThreadData *) block;
+ thread = (PRThread **) &data[numThreads];
+
+ /* Pollable event */
+ selfData.event = PR_NewPollableEvent();
+ if (selfData.event == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ selfData.next = &data[0];
+ for (i = 0; i < numThreads; i++) {
+ data[i].event = PR_NewPollableEvent();
+ if (data[i].event == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ data[i].index = i;
+ if (i != numThreads - 1) {
+ data[i].next = &data[i + 1];
+ } else {
+ data[i].next = &selfData;
+ }
+
+ thread[i] = PR_CreateThread(PR_USER_THREAD,
+ ThreadRoutine, &data[i], PR_PRIORITY_NORMAL,
+ thread_scope, PR_JOINABLE_THREAD, 0);
+ if (thread[i] == NULL) {
+ PR_fprintf(PR_STDERR, "cannot create thread\n");
+ exit(1);
+ }
+ }
+
+ timeStart = PR_IntervalNow();
+ pd.fd = selfData.event;
+ pd.in_flags = PR_POLL_READ;
+ for (i = 0; i < numIterations; i++) {
+ if (dally != PR_INTERVAL_NO_WAIT) {
+ PR_Sleep(dally);
+ }
+ if (verbosity) {
+ PR_fprintf(debug_out, "main thread posting event\n");
+ }
+ if (PR_SetPollableEvent(selfData.next->event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "set event failed\n");
+ exit(1);
+ }
+ rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (rv == -1) {
+ PR_fprintf(PR_STDERR, "wait failed\n");
+ exit(1);
+ }
+ PR_ASSERT(rv != 0);
+ PR_ASSERT(pd.out_flags & PR_POLL_READ);
+ if (verbosity) {
+ PR_fprintf(debug_out, "main thread awakened\n");
+ }
+ if (PR_WaitForPollableEvent(selfData.event) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "consume event failed\n");
+ exit(1);
+ }
+ }
+ timeEnd = PR_IntervalNow();
+
+ if (debug_mode) {
+ average = PR_IntervalToMicroseconds(timeEnd - timeStart)
+ / (numIterations * numThreads);
+ PR_fprintf(debug_out, "Average switch times %d usecs for %d threads\n",
+ average, numThreads);
+ }
+
+ for (i = 0; i < numThreads; i++) {
+ if (PR_JoinThread(thread[i]) == PR_FAILURE) {
+ PR_fprintf(PR_STDERR, "join thread failed\n");
+ exit(1);
+ }
+ PR_DestroyPollableEvent(data[i].event);
+ }
+ PR_DELETE(block);
+ PR_DestroyPollableEvent(selfData.event);
+
+ PR_fprintf(PR_STDOUT, "PASSED\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prftest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/prftest.c
new file mode 100644
index 00000000..d3e7407d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prftest.c
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: prftest.c
+ * Description:
+ * This is a simple test of the PR_snprintf() function defined
+ * in prprf.c.
+ */
+
+#include "prlong.h"
+#include "prprf.h"
+
+#include <string.h>
+
+#define BUF_SIZE 128
+
+int main() {
+ PRInt16 i16;
+ PRIntn n;
+ PRInt32 i32;
+ PRInt64 i64;
+ char buf[BUF_SIZE];
+ char answer[BUF_SIZE];
+ int i, rv = 0;
+
+ i16 = -1;
+ n = -1;
+ i32 = -1;
+ LL_I2L(i64, i32);
+
+ PR_snprintf(buf, BUF_SIZE, "%hx %x %lx %llx", i16, n, i32, i64);
+ strcpy(answer, "ffff ");
+ for (i = PR_BYTES_PER_INT * 2; i; i--) {
+ strcat(answer, "f");
+ }
+ strcat(answer, " ffffffff ffffffffffffffff");
+
+ if (!strcmp(buf, answer)) {
+ printf("PR_snprintf test 1 passed\n");
+ } else {
+ printf("PR_snprintf test 1 failed\n");
+ printf("Converted string is %s\n", buf);
+ printf("Should be %s\n", answer);
+ rv = 1;
+ }
+
+ i16 = -32;
+ n = 30;
+ i32 = 64;
+ LL_I2L(i64, 333);
+ PR_snprintf(buf, BUF_SIZE, "%d %hd %lld %ld", n, i16, i64, i32);
+ if (!strcmp(buf, "30 -32 333 64")) {
+ printf("PR_snprintf test 2 passed\n");
+ } else {
+ printf("PR_snprintf test 2 failed\n");
+ printf("Converted string is %s\n", buf);
+ printf("Should be 30 -32 333 64\n");
+ rv = 1;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prftest1.c b/src/libs/xpcom18a4/nsprpub/pr/tests/prftest1.c
new file mode 100644
index 00000000..5ea26f65
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prftest1.c
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prftest1.c
+** Description:
+** This is a simple test of the PR_snprintf() function defined
+** in prprf.c.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+#include "prttools.h"
+
+#include "prinit.h"
+#include "prlong.h"
+#include "prprf.h"
+
+#include <string.h>
+
+#define BUF_SIZE 128
+
+/***********************************************************************
+** PRIVATE FUNCTION: Test_Result
+** DESCRIPTION: Used in conjunction with the regress tool, prints out the
+** status of the test case.
+** INPUTS: PASS/FAIL
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+**
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM: Determine what the status is and print accordingly.
+**
+***********************************************************************/
+
+
+static void Test_Result (int result)
+{
+ if (result == PASS)
+ printf ("PASS\n");
+ else
+ printf ("FAIL\n");
+}
+
+int main( int argc, char *argv[])
+{
+ PRInt16 i16;
+ PRIntn n;
+ PRInt32 i32;
+ PRInt64 i64;
+ char buf[BUF_SIZE];
+ char answer[BUF_SIZE];
+ int i;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+ PR_STDIO_INIT();
+
+ i16 = -1;
+ n = -1;
+ i32 = -1;
+ LL_I2L(i64, i32);
+
+ PR_snprintf(buf, BUF_SIZE, "%hx %x %lx %llx", i16, n, i32, i64);
+ strcpy(answer, "ffff ");
+ for (i = PR_BYTES_PER_INT * 2; i; i--) {
+ strcat(answer, "f");
+ }
+ strcat(answer, " ffffffff ffffffffffffffff");
+
+ if (!strcmp(buf, answer)) {
+ if (debug_mode) printf("PR_snprintf test 1 passed\n");
+ else Test_Result (PASS);
+ } else {
+ if (debug_mode) {
+ printf("PR_snprintf test 1 failed\n");
+ printf("Converted string is %s\n", buf);
+ printf("Should be %s\n", answer);
+ }
+ else
+ Test_Result (FAIL);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prftest2.c b/src/libs/xpcom18a4/nsprpub/pr/tests/prftest2.c
new file mode 100644
index 00000000..0e5b2244
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prftest2.c
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: prftest2.c
+** Description:
+** This is a simple test of the PR_snprintf() function defined
+** in prprf.c.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prlong.h"
+#include "prinit.h"
+#include "prprf.h"
+
+#include <string.h>
+
+#define BUF_SIZE 128
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+int main( int argc, char *argv[])
+{
+ PRInt16 i16;
+ PRIntn n;
+ PRInt32 i32;
+ PRInt64 i64;
+ char buf[BUF_SIZE];
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+
+ PR_STDIO_INIT();
+ i16 = -32;
+ n = 30;
+ i32 = 64;
+ LL_I2L(i64, 333);
+ PR_snprintf(buf, BUF_SIZE, "%d %hd %lld %ld", n, i16, i64, i32);
+ if (!strcmp(buf, "30 -32 333 64")) {
+ if (debug_mode) printf("PR_snprintf test 2 passed\n");
+ } else {
+ if (debug_mode) {
+ printf("PR_snprintf test 2 failed\n");
+ printf("Converted string is %s\n", buf);
+ printf("Should be 30 -32 333 64\n");
+ }
+ else failed_already=1;
+ }
+ if(failed_already)
+ {
+ printf("FAILED\n");
+ return 1;
+ }
+ else
+ {
+ printf("PASSED\n");
+ return 0;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/primblok.c b/src/libs/xpcom18a4/nsprpub/pr/tests/primblok.c
new file mode 100644
index 00000000..8a188834
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/primblok.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * File: primblok.c
+ * Purpose: testing whether the primordial thread can block in a
+ * native blocking function without affecting the correct
+ * functioning of NSPR I/O functions (Bugzilla bug #30746)
+ */
+
+#if !defined(WINNT)
+
+#include <stdio.h>
+
+int main()
+{
+ printf("This test is not relevant on this platform\n");
+ return 0;
+}
+
+#else /* WINNT */
+
+#include "nspr.h"
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TEST_FILE_NAME "primblok.dat"
+
+/* use InterlockedExchange to update this variable */
+static LONG iothread_done;
+
+static void PR_CALLBACK IOThread(void *arg)
+{
+ PRFileDesc *fd;
+ char buf[32];
+ PRInt32 nbytes;
+
+ /* Give the primordial thread one second to block */
+ Sleep(1000);
+
+ /*
+ * See if our PR_Write call will hang when the primordial
+ * thread is blocking in a native blocking function.
+ */
+ fd = PR_Open(TEST_FILE_NAME, PR_WRONLY|PR_CREATE_FILE, 0666);
+ if (NULL == fd) {
+ fprintf(stderr, "PR_Open failed\n");
+ exit(1);
+ }
+ memset(buf, 0xaf, sizeof(buf));
+ fprintf(stderr, "iothread: calling PR_Write\n");
+ nbytes = PR_Write(fd, buf, sizeof(buf));
+ fprintf(stderr, "iothread: PR_Write returned\n");
+ if (nbytes != sizeof(buf)) {
+ fprintf(stderr, "PR_Write returned %d\n", nbytes);
+ exit(1);
+ }
+ if (PR_Close(fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) {
+ fprintf(stderr, "PR_Delete failed\n");
+ exit(1);
+ }
+
+ /* Tell the main thread that we are done */
+ InterlockedExchange(&iothread_done, 1);
+}
+
+int main()
+{
+ PRThread *iothread;
+
+ /* Must be a global thread */
+ iothread = PR_CreateThread(
+ PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (iothread == NULL) {
+ fprintf(stderr, "cannot create thread\n");
+ exit(1);
+ }
+
+ /*
+ * Block in a native blocking function.
+ * Give iothread 5 seconds to finish its task.
+ */
+ Sleep(5000);
+
+ /*
+ * Is iothread done or is it hung?
+ *
+ * I'm actually only interested in reading the value
+ * of iothread_done. I'm using InterlockedExchange as
+ * a thread-safe way to read iothread_done.
+ */
+ if (InterlockedExchange(&iothread_done, 1) == 0) {
+ fprintf(stderr, "iothread is hung\n");
+ fprintf(stderr, "FAILED\n");
+ exit(1);
+ }
+
+ if (PR_JoinThread(iothread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ printf("PASSED\n");
+ return 0;
+} /* main */
+
+#endif /* WINNT */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/priotest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/priotest.c
new file mode 100644
index 00000000..16def03d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/priotest.c
@@ -0,0 +1,233 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: priotest.c
+ * Purpose: testing priorities
+ */
+
+#ifdef XP_MAC
+#error "This test does not run on Macintosh"
+#else
+
+
+#include "prcmon.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prmon.h"
+#include "prprf.h"
+#include "prthread.h"
+#include "prtypes.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define DEFAULT_DURATION 5
+
+static PRBool failed = PR_FALSE;
+static PRIntervalTime oneSecond;
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE;
+
+static PRUint32 PerSecond(PRIntervalTime timein)
+{
+ PRUint32 loop = 0;
+ while (((PRIntervalTime)(PR_IntervalNow()) - timein) < oneSecond)
+ loop += 1;
+ return loop;
+} /* PerSecond */
+
+static void PR_CALLBACK Low(void *arg)
+{
+ PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg;
+ while (1)
+ {
+ t0 = PerSecond(PR_IntervalNow());
+ *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8;
+ t3 = t2; t2 = t1; t1 = t0;
+ }
+} /* Low */
+
+static void PR_CALLBACK High(void *arg)
+{
+ PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg;
+ while (1)
+ {
+ PRIntervalTime timein = PR_IntervalNow();
+ PR_Sleep(oneSecond >> 2); /* 0.25 seconds */
+ t0 = PerSecond(timein);
+ *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8;
+ t3 = t2; t2 = t1; t1 = t0;
+ }
+} /* High */
+
+static void Help(void)
+{
+ PR_fprintf(
+ debug_out, "Usage: priotest [-d] [-c n]\n");
+ PR_fprintf(
+ debug_out, "-c n\tduration of test in seconds (default: %d)\n", DEFAULT_DURATION);
+ PR_fprintf(
+ debug_out, "-d\tturn on debugging output (default: FALSE)\n");
+} /* Help */
+
+static void RudimentaryTests(void)
+{
+ /*
+ ** Try some rudimentary tests like setting valid priority and
+ ** getting it back, or setting invalid priorities and getting
+ ** back a valid answer.
+ */
+ PRThreadPriority priority;
+ PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT);
+ priority = PR_GetThreadPriority(PR_GetCurrentThread());
+ failed = ((PR_TRUE == failed) || (PR_PRIORITY_URGENT != priority))
+ ? PR_TRUE : PR_FALSE;
+ if (debug_mode && (PR_PRIORITY_URGENT != priority))
+ {
+ PR_fprintf(debug_out, "PR_[S/G]etThreadPriority() failed\n");
+ }
+
+
+ PR_SetThreadPriority(
+ PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_FIRST - 1));
+ priority = PR_GetThreadPriority(PR_GetCurrentThread());
+ failed = ((PR_TRUE == failed) || (PR_PRIORITY_FIRST != priority))
+ ? PR_TRUE : PR_FALSE;
+ if (debug_mode && (PR_PRIORITY_FIRST != priority))
+ {
+ PR_fprintf(debug_out, "PR_SetThreadPriority(-1) failed\n");
+ }
+
+ PR_SetThreadPriority(
+ PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_LAST + 1));
+ priority = PR_GetThreadPriority(PR_GetCurrentThread());
+ failed = ((PR_TRUE == failed) || (PR_PRIORITY_LAST != priority))
+ ? PR_TRUE : PR_FALSE;
+ if (debug_mode && (PR_PRIORITY_LAST != priority))
+ {
+ PR_fprintf(debug_out, "PR_SetThreadPriority(+1) failed\n");
+ }
+
+} /* RudimentataryTests */
+
+static void CreateThreads(PRUint32 *lowCount, PRUint32 *highCount)
+{
+ (void)PR_CreateThread(
+ PR_USER_THREAD, Low, lowCount, PR_PRIORITY_LOW,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ (void)PR_CreateThread(
+ PR_USER_THREAD, High, highCount, PR_PRIORITY_HIGH,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+} /* CreateThreads */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ PRIntn duration = DEFAULT_DURATION;
+ PRUint32 totalCount, highCount = 0, lowCount = 0;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdc:");
+
+ debug_out = PR_STDOUT;
+ oneSecond = PR_SecondsToInterval(1);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* test duration */
+ duration = atoi(opt->value);
+ break;
+ case 'h': /* help message */
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+ PR_STDIO_INIT();
+
+ if (duration == 0) duration = DEFAULT_DURATION;
+
+ RudimentaryTests();
+
+ printf("Priority test: running for %d seconds\n\n", duration);
+
+ (void)PerSecond(PR_IntervalNow());
+ totalCount = PerSecond(PR_IntervalNow());
+
+ PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT);
+
+ if (debug_mode)
+ {
+ PR_fprintf(debug_out,
+ "The high priority thread should get approximately three\n");
+ PR_fprintf( debug_out,
+ "times what the low priority thread manages. A maximum of \n");
+ PR_fprintf( debug_out, "%d cycles are available.\n\n", totalCount);
+ }
+
+ duration = (duration + 4) / 5;
+ CreateThreads(&lowCount, &highCount);
+ while (duration--)
+ {
+ PRIntn loop = 5;
+ while (loop--) PR_Sleep(oneSecond);
+ if (debug_mode)
+ PR_fprintf(debug_out, "high : low :: %d : %d\n", highCount, lowCount);
+ }
+
+
+ PR_ProcessExit((failed) ? 1 : 0);
+
+ PR_ASSERT(!"You can't get here -- but you did!");
+ return 1; /* or here */
+
+} /* main */
+
+#endif /* ifdef XP_MAC */
+
+/* priotest.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/provider.c b/src/libs/xpcom18a4/nsprpub/pr/tests/provider.c
new file mode 100644
index 00000000..54b3a53c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/provider.c
@@ -0,0 +1,1447 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *
+ * Notes:
+ * [1] lth. The call to Sleep() is a hack to get the test case to run
+ * on Windows 95. Without it, the test case fails with an error
+ * WSAECONNRESET following a recv() call. The error is caused by the
+ * server side thread termination without a shutdown() or closesocket()
+ * call. Windows docmunentation suggests that this is predicted
+ * behavior; that other platforms get away with it is ... serindipity.
+ * The test case should shutdown() or closesocket() before
+ * thread termination. I didn't have time to figure out where or how
+ * to do it. The Sleep() call inserts enough delay to allow the
+ * client side to recv() all his data before the server side thread
+ * terminates. Whew! ...
+ *
+ ** Modification History:
+ * 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+ * The debug mode will print all of the printfs associated with this test.
+ * The regress mode will be the default mode. Since the regress tool limits
+ * the output to a one line status:PASS or FAIL,all of the printf statements
+ * have been handled with an if (debug_mode) statement.
+ */
+
+#include "prclist.h"
+#include "prcvar.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prtime.h"
+#include "prmem.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prthread.h"
+
+#include "pprio.h"
+#include "primpl.h"
+
+#include "plstr.h"
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#if defined(XP_UNIX)
+#include <math.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+/*
+** This is the beginning of the test
+*/
+
+#define RECV_FLAGS 0
+#define SEND_FLAGS 0
+#define BUFFER_SIZE 1024
+#define DEFAULT_BACKLOG 5
+#define DEFAULT_PORT 13000
+#define DEFAULT_CLIENTS 1
+#define ALLOWED_IN_ACCEPT 1
+#define DEFAULT_CLIPPING 1000
+#define DEFAULT_WORKERS_MIN 1
+#define DEFAULT_WORKERS_MAX 1
+#define DEFAULT_SERVER "localhost"
+#define DEFAULT_EXECUTION_TIME 10
+#define DEFAULT_CLIENT_TIMEOUT 4000
+#define DEFAULT_SERVER_TIMEOUT 4000
+#define DEFAULT_SERVER_PRIORITY PR_PRIORITY_HIGH
+
+typedef enum CSState_e {cs_init, cs_run, cs_stop, cs_exit} CSState_t;
+
+static void PR_CALLBACK Worker(void *arg);
+typedef struct CSPool_s CSPool_t;
+typedef struct CSWorker_s CSWorker_t;
+typedef struct CSServer_s CSServer_t;
+typedef enum Verbosity
+{
+ TEST_LOG_ALWAYS,
+ TEST_LOG_ERROR,
+ TEST_LOG_WARNING,
+ TEST_LOG_NOTICE,
+ TEST_LOG_INFO,
+ TEST_LOG_STATUS,
+ TEST_LOG_VERBOSE
+} Verbosity;
+
+static enum {
+ thread_nspr, thread_pthread, thread_uithread, thread_sproc, thread_win32
+} thread_provider;
+
+static PRInt32 domain = AF_INET;
+static PRInt32 protocol = 6; /* TCP */
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE;
+static PRBool pthread_stats = PR_FALSE;
+static Verbosity verbosity = TEST_LOG_ALWAYS;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+struct CSWorker_s
+{
+ PRCList element; /* list of the server's workers */
+
+ PRThread *thread; /* this worker objects thread */
+ CSServer_t *server; /* back pointer to server structure */
+};
+
+struct CSPool_s
+{
+ PRCondVar *exiting;
+ PRCondVar *acceptComplete;
+ PRUint32 accepting, active, workers;
+};
+
+struct CSServer_s
+{
+ PRCList list; /* head of worker list */
+
+ PRLock *ml;
+ PRThread *thread; /* the main server thread */
+ PRCondVar *stateChange;
+
+ PRUint16 port; /* port we're listening on */
+ PRUint32 backlog; /* size of our listener backlog */
+ PRFileDesc *listener; /* the fd accepting connections */
+
+ CSPool_t pool; /* statistics on worker threads */
+ CSState_t state; /* the server's state */
+ struct /* controlling worker counts */
+ {
+ PRUint32 minimum, maximum, accepting;
+ } workers;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+};
+
+typedef struct CSDescriptor_s
+{
+ PRInt32 size; /* size of transfer */
+ char filename[60]; /* filename, null padded */
+} CSDescriptor_t;
+
+typedef struct CSClient_s
+{
+ PRLock *ml;
+ PRThread *thread;
+ PRCondVar *stateChange;
+ PRNetAddr serverAddress;
+
+ CSState_t state;
+
+ /* statistics */
+ PRIntervalTime started, stopped;
+ PRUint32 operations, bytesTransferred;
+} CSClient_t;
+
+#define TEST_LOG(l, p, a) \
+ do { \
+ if (debug_mode || (p <= verbosity)) printf a; \
+ } while (0)
+
+PRLogModuleInfo *cltsrv_log_file = NULL;
+
+#define MY_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+#define TEST_ASSERT(_expr) \
+ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__))
+
+static void _MY_Assert(const char *s, const char *file, PRIntn ln)
+{
+ PL_PrintError(NULL);
+#if DEBUG
+ PR_Assert(s, file, ln);
+#endif
+} /* _MW_Assert */
+
+static PRBool Aborted(PRStatus rv)
+{
+ return ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) ?
+ PR_TRUE : PR_FALSE;
+}
+
+static void TimeOfDayMessage(const char *msg, PRThread* me)
+{
+ char buffer[100];
+ PRExplodedTime tod;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod);
+ (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("%s(0x%p): %s\n", msg, me, buffer));
+} /* TimeOfDayMessage */
+
+
+static void PR_CALLBACK Client(void *arg)
+{
+ PRStatus rv;
+ PRIntn index;
+ char buffer[1024];
+ PRFileDesc *fd = NULL;
+ PRUintn clipping = DEFAULT_CLIPPING;
+ CSClient_t *client = (CSClient_t*)arg;
+ PRThread *me = client->thread = PR_CurrentThread();
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT);
+
+
+ for (index = 0; index < sizeof(buffer); ++index)
+ buffer[index] = (char)index;
+
+ client->started = PR_IntervalNow();
+
+ PR_Lock(client->ml);
+ client->state = cs_run;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+
+ TimeOfDayMessage("Client started at", me);
+
+ while (cs_run == client->state)
+ {
+ PRInt32 bytes, descbytes, filebytes, netbytes;
+
+ (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer));
+ TEST_LOG(cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): connecting to server at %s\n", me, buffer));
+
+ fd = PR_Socket(domain, SOCK_STREAM, protocol);
+ TEST_ASSERT(NULL != fd);
+ rv = PR_Connect(fd, &client->serverAddress, timeout);
+ if (PR_FAILURE == rv)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): conection failed\n", me));
+ goto aborted;
+ }
+
+ memset(descriptor, 0, sizeof(*descriptor));
+ descriptor->size = PR_htonl(descbytes = rand() % clipping);
+ PR_snprintf(
+ descriptor->filename, sizeof(descriptor->filename),
+ "CS%p%p-%p.dat", client->started, me, client->operations);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes));
+ bytes = PR_Send(
+ fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout);
+ if (sizeof(CSDescriptor_t) != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send descriptor timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ if (Aborted(PR_FAILURE)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): send data timeout\n", me));
+ goto retry;
+ }
+ }
+ TEST_ASSERT(bytes == filebytes);
+ netbytes += bytes;
+ }
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tClient(0x%p): receiving %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ if (Aborted(PR_FAILURE))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data aborted\n", me));
+ goto aborted;
+ }
+ else if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive data timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tClient(0x%p): receive error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto retry;
+ }
+ if (0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tClient(0x%p): unexpected end of stream\n",
+ PR_CurrentThread()));
+ break;
+ }
+ filebytes += bytes;
+ }
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+retry:
+ (void)PR_Close(fd); fd = NULL;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tClient(0x%p): disconnected from server\n", me));
+
+ PR_Lock(client->ml);
+ client->operations += 1;
+ client->bytesTransferred += 2 * descbytes;
+ rv = PR_WaitCondVar(client->stateChange, rand() % clipping);
+ PR_Unlock(client->ml);
+ if (Aborted(rv)) break;
+ }
+
+aborted:
+ client->stopped = PR_IntervalNow();
+
+ PR_ClearInterrupt();
+ if (NULL != fd) rv = PR_Close(fd);
+
+ PR_Lock(client->ml);
+ client->state = cs_exit;
+ PR_NotifyCondVar(client->stateChange);
+ PR_Unlock(client->ml);
+ PR_DELETE(descriptor);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tClient(0x%p): stopped after %u operations and %u bytes\n",
+ PR_CurrentThread(), client->operations, client->bytesTransferred));
+
+} /* Client */
+
+static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server)
+{
+ PRStatus drv, rv;
+ char buffer[1024];
+ PRFileDesc *file = NULL;
+ PRThread * me = PR_CurrentThread();
+ PRInt32 bytes, descbytes, netbytes, filebytes = 0;
+ CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t);
+ PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receiving desciptor\n", me));
+ bytes = PR_Recv(
+ fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto exit;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): receive timeout\n", me));
+ }
+ goto exit;
+ }
+ if (0 == bytes)
+ {
+ rv = PR_FAILURE;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): unexpected end of file\n", me));
+ goto exit;
+ }
+ descbytes = PR_ntohl(descriptor->size);
+ TEST_ASSERT(sizeof(*descriptor) == bytes);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n",
+ me, descbytes, descriptor->filename));
+
+ file = PR_Open(
+ descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\tProcessRequest(0x%p): open file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(NULL != file);
+
+ filebytes = 0;
+ while (filebytes < descbytes)
+ {
+ netbytes = sizeof(buffer);
+ if ((descbytes - filebytes) < netbytes)
+ netbytes = descbytes - filebytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes));
+ bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout);
+ if (-1 == bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): receive data timeout\n", me));
+ goto aborted;
+ }
+ /*
+ * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED)
+ * on NT here. This is equivalent to ECONNRESET on Unix.
+ * -wtc
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ if(0 == bytes)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_WARNING,
+ ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me));
+ rv = PR_FAILURE;
+ goto aborted;
+ }
+ filebytes += bytes;
+ netbytes = bytes;
+ /* The byte count for PR_Write should be positive */
+ MY_ASSERT(netbytes > 0);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes));
+ bytes = PR_Write(file, buffer, netbytes);
+ if (netbytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): write file timeout\n", me));
+ goto aborted;
+ }
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->operations += 1;
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Close(file); file = NULL;
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename));
+ file = PR_Open(descriptor->filename, PR_RDONLY, 0);
+ if (NULL == file)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): open file timeout\n",
+ PR_CurrentThread()));
+ goto aborted;
+ }
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(NULL != file);
+
+ netbytes = 0;
+ while (netbytes < descbytes)
+ {
+ filebytes = sizeof(buffer);
+ if ((descbytes - netbytes) < filebytes)
+ filebytes = descbytes - netbytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes));
+ bytes = PR_Read(file, buffer, filebytes);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): read file timeout\n", me));
+ else
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n",
+ me, PR_GetError(), PR_GetOSError()));
+ goto aborted;
+ }
+ TEST_ASSERT(bytes > 0);
+ netbytes += bytes;
+ filebytes = bytes;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes));
+ bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout);
+ if (filebytes != bytes)
+ {
+ rv = PR_FAILURE;
+ if (Aborted(rv)) goto aborted;
+ if (PR_IO_TIMEOUT_ERROR == PR_GetError())
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tProcessRequest(0x%p): send data timeout\n", me));
+ goto aborted;
+ }
+ break;
+ }
+ TEST_ASSERT(bytes > 0);
+ }
+
+ PR_Lock(server->ml);
+ server->bytesTransferred += filebytes;
+ PR_Unlock(server->ml);
+
+ rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ if (Aborted(rv)) goto aborted;
+
+ rv = PR_Close(file); file = NULL;
+ if (Aborted(rv)) goto aborted;
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+aborted:
+ PR_ClearInterrupt();
+ if (NULL != file) PR_Close(file);
+ drv = PR_Delete(descriptor->filename);
+ TEST_ASSERT(PR_SUCCESS == drv);
+exit:
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tProcessRequest(0x%p): Finished\n", me));
+
+ PR_DELETE(descriptor);
+
+#if defined(WIN95)
+ PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */
+#endif
+ return rv;
+} /* ProcessRequest */
+
+typedef void (*StartFn)(void*);
+typedef struct StartObject
+{
+ StartFn start;
+ void *arg;
+} StartObject;
+
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include "md/_pth.h"
+#include <pthread.h>
+
+static void *pthread_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return NULL;
+} /* pthread_start */
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+#include <thread.h>
+
+static void *uithread_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return NULL;
+} /* uithread_start */
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+#include <sys/types.h>
+#include <sys/prctl.h>
+static void sproc_start(void *arg, PRSize size)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+} /* sproc_start */
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+
+#if defined(WIN32)
+#include <process.h> /* for _beginthreadex() */
+
+static PRUintn __stdcall windows_start(void *arg)
+{
+ StartObject *so = (StartObject*)arg;
+ StartFn start = so->start;
+ void *data = so->arg;
+ PR_Free(so);
+ start(data);
+ return 0;
+} /* windows_start */
+#endif /* defined(WIN32) */
+
+static PRStatus JoinThread(PRThread *thread)
+{
+ PRStatus rv;
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ rv = PR_JoinThread(thread);
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ rv = PR_SUCCESS;
+ break;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ case thread_uithread:
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ rv = PR_SUCCESS;
+ break;
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+ case thread_win32:
+#if defined(WIN32)
+ rv = PR_SUCCESS;
+ break;
+#endif
+ default:
+ rv = PR_FAILURE;
+ break;
+ }
+ return rv;
+} /* JoinThread */
+
+static PRStatus NewThread(
+ StartFn start, void *arg, PRThreadPriority prio, PRThreadState state)
+{
+ PRStatus rv;
+
+ switch (thread_provider)
+ {
+ case thread_nspr:
+ {
+ PRThread *thread = PR_CreateThread(
+ PR_USER_THREAD, start, arg,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+ rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
+ }
+ break;
+ case thread_pthread:
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ {
+ int rv;
+ pthread_t id;
+ pthread_attr_t tattr;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ rv = _PT_PTHREAD_ATTR_INIT(&tattr);
+ PR_ASSERT(0 == rv);
+
+ rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+ PR_ASSERT(0 == rv);
+
+#if !defined(LINUX)
+ rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
+ PR_ASSERT(0 == rv);
+#endif
+
+ rv = _PT_PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
+ (void)_PT_PTHREAD_ATTR_DESTROY(&tattr);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
+ break;
+
+ case thread_uithread:
+#if defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ {
+ int rv;
+ thread_t id;
+ long flags;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+
+ flags = THR_DETACHED;
+
+ rv = thr_create(NULL, NULL, uithread_start, start_object, flags, &id);
+ return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY) */
+ break;
+
+ case thread_sproc:
+#if defined(IRIX) && !defined(_PR_PTHREADS)
+ {
+ PRInt32 pid;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ pid = sprocsp(
+ sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
+ rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
+ break;
+ case thread_win32:
+#if defined(WIN32)
+ {
+ void *th;
+ PRUintn id;
+ StartObject *start_object;
+ start_object = PR_NEW(StartObject);
+ PR_ASSERT(NULL != start_object);
+ start_object->start = start;
+ start_object->arg = arg;
+ th = (void*)_beginthreadex(
+ NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
+ 0U, /* DWORD - initial thread stack size, in bytes */
+ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
+ start_object, /* LPVOID - argument for new thread */
+ 0U, /*DWORD dwCreationFlags - creation flags */
+ &id /* LPDWORD - pointer to returned thread identifier */ );
+
+ rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
+ }
+#else
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+#endif
+ break;
+ default:
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
+ rv = PR_FAILURE;
+ }
+ return rv;
+} /* NewThread */
+
+static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool)
+{
+ PRStatus rv;
+ CSWorker_t *worker = PR_NEWZAP(CSWorker_t);
+ worker->server = server;
+ PR_INIT_CLIST(&worker->element);
+ rv = NewThread(
+ Worker, worker, DEFAULT_SERVER_PRIORITY, PR_UNJOINABLE_THREAD);
+ if (PR_FAILURE == rv) PR_DELETE(worker);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("\tCreateWorker(0x%p): create new worker (0x%p)\n",
+ PR_CurrentThread(), worker->thread));
+
+ return rv;
+} /* CreateWorker */
+
+static void PR_CALLBACK Worker(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr from;
+ PRFileDesc *fd = NULL;
+ CSWorker_t *worker = (CSWorker_t*)arg;
+ CSServer_t *server = worker->server;
+ CSPool_t *pool = &server->pool;
+
+ PRThread *me = worker->thread = PR_CurrentThread();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1));
+
+ PR_Lock(server->ml);
+ PR_APPEND_LINK(&worker->element, &server->list);
+ pool->workers += 1; /* define our existance */
+
+ while (cs_run == server->state)
+ {
+ while (pool->accepting >= server->workers.accepting)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): waiting for accept slot[%d]\n",
+ me, pool->accepting));
+ rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT);
+ if (Aborted(rv) || (cs_run != server->state))
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tWorker(0x%p): has been %s\n",
+ me, (Aborted(rv) ? "interrupted" : "stopped")));
+ goto exit;
+ }
+ }
+ pool->accepting += 1; /* how many are really in accept */
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\t\tWorker(0x%p): calling accept\n", me));
+ fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT);
+
+ PR_Lock(server->ml);
+ pool->accepting -= 1;
+ PR_NotifyCondVar(pool->acceptComplete);
+
+ if ((NULL == fd) && Aborted(PR_FAILURE))
+ {
+ if (NULL != server->listener)
+ {
+ PR_Close(server->listener);
+ server->listener = NULL;
+ }
+ goto exit;
+ }
+
+ if (NULL != fd)
+ {
+ /*
+ ** Create another worker of the total number of workers is
+ ** less than the minimum specified or we have none left in
+ ** accept() AND we're not over the maximum.
+ ** This sort of presumes that the number allowed in accept
+ ** is at least as many as the minimum. Otherwise we'll keep
+ ** creating new threads and deleting them soon after.
+ */
+ PRBool another =
+ ((pool->workers < server->workers.minimum) ||
+ ((0 == pool->accepting)
+ && (pool->workers < server->workers.maximum))) ?
+ PR_TRUE : PR_FALSE;
+ pool->active += 1;
+ PR_Unlock(server->ml);
+
+ if (another) (void)CreateWorker(server, pool);
+
+ rv = ProcessRequest(fd, server);
+ if (PR_SUCCESS != rv)
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ERROR,
+ ("\t\tWorker(0x%p): server process ended abnormally\n", me));
+ (void)PR_Close(fd); fd = NULL;
+
+ PR_Lock(server->ml);
+ pool->active -= 1;
+ }
+ }
+
+exit:
+ PR_ClearInterrupt();
+ PR_Unlock(server->ml);
+
+ if (NULL != fd)
+ {
+ (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH);
+ (void)PR_Close(fd);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\t\tWorker(0x%p): exiting [%u]\n", PR_CurrentThread(), pool->workers));
+
+ PR_Lock(server->ml);
+ pool->workers -= 1; /* undefine our existance */
+ PR_REMOVE_AND_INIT_LINK(&worker->element);
+ PR_NotifyCondVar(pool->exiting);
+ PR_Unlock(server->ml);
+
+ PR_DELETE(worker); /* destruction of the "worker" object */
+
+} /* Worker */
+
+static void PR_CALLBACK Server(void *arg)
+{
+ PRStatus rv;
+ PRNetAddr serverAddress;
+ CSServer_t *server = (CSServer_t*)arg;
+ PRThread *me = server->thread = PR_CurrentThread();
+ PRSocketOptionData sockOpt;
+
+ server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
+
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(server->listener, &sockOpt);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ memset(&serverAddress, 0, sizeof(serverAddress));
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
+
+ rv = PR_Bind(server->listener, &serverAddress);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ rv = PR_Listen(server->listener, server->backlog);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ server->started = PR_IntervalNow();
+ TimeOfDayMessage("Server started at", me);
+
+ PR_Lock(server->ml);
+ server->state = cs_run;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ /*
+ ** Create the first worker (actually, a thread that accepts
+ ** connections and then processes the work load as needed).
+ ** From this point on, additional worker threads are created
+ ** as they are needed by existing worker threads.
+ */
+ rv = CreateWorker(server, &server->pool);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ /*
+ ** From here on this thread is merely hanging around as the contact
+ ** point for the main test driver. It's just waiting for the driver
+ ** to declare the test complete.
+ */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): waiting for state change\n", me));
+
+ PR_Lock(server->ml);
+ while ((cs_run == server->state) && !Aborted(rv))
+ {
+ rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(server->ml);
+ PR_ClearInterrupt();
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("\tServer(0x%p): shutting down workers\n", me));
+
+ /*
+ ** Get all the worker threads to exit. They know how to
+ ** clean up after themselves, so this is just a matter of
+ ** waiting for clorine in the pool to take effect. During
+ ** this stage we're ignoring interrupts.
+ */
+ server->workers.minimum = server->workers.maximum = 0;
+
+ PR_Lock(server->ml);
+ while (!PR_CLIST_IS_EMPTY(&server->list))
+ {
+ PRCList *head = PR_LIST_HEAD(&server->list);
+ CSWorker_t *worker = (CSWorker_t*)head;
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker));
+ rv = PR_Interrupt(worker->thread);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_REMOVE_AND_INIT_LINK(head);
+ }
+
+ while (server->pool.workers > 0)
+ {
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("\tServer(0x%p): waiting for %u workers to exit\n",
+ me, server->pool.workers));
+ (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ server->state = cs_exit;
+ PR_NotifyCondVar(server->stateChange);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("\tServer(0x%p): stopped after %u operations and %u bytes\n",
+ me, server->operations, server->bytesTransferred));
+
+ if (NULL != server->listener) PR_Close(server->listener);
+ server->stopped = PR_IntervalNow();
+
+} /* Server */
+
+static void WaitForCompletion(PRIntn execution)
+{
+ while (execution > 0)
+ {
+ PRIntn dally = (execution > 30) ? 30 : execution;
+ PR_Sleep(PR_SecondsToInterval(dally));
+ if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n");
+ execution -= dally;
+ }
+} /* WaitForCompletion */
+
+static void Help(void)
+{
+ PR_fprintf(debug_out, "cltsrv test program usage:\n");
+ PR_fprintf(debug_out, "\t-a <n> threads allowed in accept (5)\n");
+ PR_fprintf(debug_out, "\t-b <n> backlock for listen (5)\n");
+ PR_fprintf(debug_out, "\t-c <threads> number of clients to create (1)\n");
+ PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
+ PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds (10)\n");
+ PR_fprintf(debug_out, "\t-s <string> dsn name of server (localhost)\n");
+ PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n");
+ PR_fprintf(debug_out, "\t-T <string> thread provider ('n' | 'p' | 'u' | 'w')(n)\n");
+ PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n");
+ PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n");
+ PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n");
+ PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n");
+ PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n");
+ PR_fprintf(debug_out, "\t-h this message\n");
+} /* Help */
+
+static Verbosity IncrementVerbosity(void)
+{
+ PRIntn verboge = (PRIntn)verbosity + 1;
+ return (Verbosity)verboge;
+} /* IncrementVerbosity */
+
+PRIntn main(PRIntn argc, char** argv)
+{
+ PRUintn index;
+ PRBool boolean;
+ CSClient_t *client;
+ PRStatus rv, joinStatus;
+ CSServer_t *server = NULL;
+ char *thread_type;
+
+ PRUintn backlog = DEFAULT_BACKLOG;
+ PRUintn clients = DEFAULT_CLIENTS;
+ const char *serverName = DEFAULT_SERVER;
+ PRBool serverIsLocal = PR_TRUE;
+ PRUintn accepting = ALLOWED_IN_ACCEPT;
+ PRUintn workersMin = DEFAULT_WORKERS_MIN;
+ PRUintn workersMax = DEFAULT_WORKERS_MAX;
+ PRIntn execution = DEFAULT_EXECUTION_TIME;
+
+ /*
+ * -G use global threads
+ * -a <n> threads allowed in accept
+ * -b <n> backlock for listen
+ * -c <threads> number of clients to create
+ * -w <threads> minimal number of server threads
+ * -W <threads> maximum number of server threads
+ * -e <seconds> duration of the test in seconds
+ * -s <string> dsn name of server (implies no server here)
+ * -v verbosity
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:T:vdhp");
+
+#if defined(WIN32)
+ thread_provider = thread_win32;
+#elif defined(_PR_PTHREADS)
+ thread_provider = thread_pthread;
+#elif defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)
+ thread_provider = thread_uithread;
+#elif defined(IRIX)
+ thread_provider = thread_sproc;
+#else
+ thread_provider = thread_nspr;
+#endif
+
+ debug_out = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'X': /* use XTP as transport */
+ protocol = 36;
+ break;
+ case '6': /* Use IPv6 */
+ domain = PR_AF_INET6;
+ break;
+ case 'a': /* the value for accepting */
+ accepting = atoi(opt->value);
+ break;
+ case 'b': /* the value for backlock */
+ backlog = atoi(opt->value);
+ break;
+ case 'T': /* the thread provider */
+ if ('n' == *opt->value) thread_provider = thread_nspr;
+ else if ('p' == *opt->value) thread_provider = thread_pthread;
+ else if ('u' == *opt->value) thread_provider = thread_uithread;
+ else if ('w' == *opt->value) thread_provider = thread_win32;
+ else {Help(); return 2; }
+ break;
+ case 'c': /* number of client threads */
+ clients = atoi(opt->value);
+ break;
+ case 'w': /* minimum server worker threads */
+ workersMin = atoi(opt->value);
+ break;
+ case 'W': /* maximum server worker threads */
+ workersMax = atoi(opt->value);
+ break;
+ case 'e': /* program execution time in seconds */
+ execution = atoi(opt->value);
+ break;
+ case 's': /* server's address */
+ serverName = opt->value;
+ break;
+ case 'v': /* verbosity */
+ verbosity = IncrementVerbosity();
+ break;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'p': /* pthread mode */
+ pthread_stats = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE;
+ if (0 == execution) execution = DEFAULT_EXECUTION_TIME;
+ if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX;
+ if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN;
+ if (0 == accepting) accepting = ALLOWED_IN_ACCEPT;
+ if (0 == backlog) backlog = DEFAULT_BACKLOG;
+
+ if (workersMin > accepting) accepting = workersMin;
+
+ PR_STDIO_INIT();
+ TimeOfDayMessage("Client/Server started at", PR_CurrentThread());
+
+ cltsrv_log_file = PR_NewLogModule("cltsrv_log");
+ MY_ASSERT(NULL != cltsrv_log_file);
+ boolean = PR_SetLogFile("cltsrv.log");
+ MY_ASSERT(boolean);
+
+#ifdef XP_MAC
+ debug_mode = PR_TRUE;
+#endif
+
+ if (serverIsLocal)
+ {
+ /* Establish the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): starting server\n", PR_CurrentThread()));
+
+ server = PR_NEWZAP(CSServer_t);
+ PR_INIT_CLIST(&server->list);
+ server->state = cs_init;
+ server->ml = PR_NewLock();
+ server->backlog = backlog;
+ server->port = DEFAULT_PORT;
+ server->workers.minimum = workersMin;
+ server->workers.maximum = workersMax;
+ server->workers.accepting = accepting;
+ server->stateChange = PR_NewCondVar(server->ml);
+ server->pool.exiting = PR_NewCondVar(server->ml);
+ server->pool.acceptComplete = PR_NewCondVar(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): creating server thread\n", PR_CurrentThread()));
+
+ rv = NewThread(
+ Server, server, PR_PRIORITY_HIGH, PR_JOINABLE_THREAD);
+ TEST_ASSERT(PR_SUCCESS == rv);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): waiting for server init\n", PR_CurrentThread()));
+
+ PR_Lock(server->ml);
+ while (server->state == cs_init)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): server init complete (port #%d)\n",
+ PR_CurrentThread(), server->port));
+ }
+
+ if (clients != 0)
+ {
+ /* Create all of the clients */
+ PRHostEnt host;
+ char buffer[BUFFER_SIZE];
+ client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t));
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): creating %d client threads\n",
+ PR_CurrentThread(), clients));
+
+ if (!serverIsLocal)
+ {
+ rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host);
+ if (PR_SUCCESS != rv)
+ {
+ PL_FPrintError(PR_STDERR, "PR_GetHostByName");
+ return 2;
+ }
+ }
+
+ for (index = 0; index < clients; ++index)
+ {
+ client[index].state = cs_init;
+ client[index].ml = PR_NewLock();
+ if (serverIsLocal)
+ {
+ (void)PR_InitializeNetAddr(
+ PR_IpAddrLoopback, DEFAULT_PORT,
+ &client[index].serverAddress);
+ }
+ else
+ {
+ (void)PR_EnumerateHostEnt(
+ 0, &host, DEFAULT_PORT, &client[index].serverAddress);
+ }
+ client[index].stateChange = PR_NewCondVar(client[index].ml);
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_INFO,
+ ("main(0x%p): creating client threads\n", PR_CurrentThread()));
+ rv = NewThread(
+ Client, &client[index], PR_PRIORITY_NORMAL, PR_JOINABLE_THREAD);
+ TEST_ASSERT(PR_SUCCESS == rv);
+ PR_Lock(client[index].ml);
+ while (cs_init == client[index].state)
+ PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(client[index].ml);
+ }
+ }
+
+ /* Then just let them go at it for a bit */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): waiting for execution interval (%d seconds)\n",
+ PR_CurrentThread(), execution));
+
+ WaitForCompletion(execution);
+
+ TimeOfDayMessage("Shutting down", PR_CurrentThread());
+
+ if (clients != 0)
+ {
+ for (index = 0; index < clients; ++index)
+ {
+ TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS,
+ ("main(0x%p): notifying client(0x%p) to stop\n",
+ PR_CurrentThread(), client[index].thread));
+
+ PR_Lock(client[index].ml);
+ if (cs_run == client[index].state)
+ {
+ client[index].state = cs_stop;
+ PR_Interrupt(client[index].thread);
+ while (cs_stop == client[index].state)
+ PR_WaitCondVar(
+ client[index].stateChange, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(client[index].ml);
+
+ TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE,
+ ("main(0x%p): joining client(0x%p)\n",
+ PR_CurrentThread(), client[index].thread));
+
+ joinStatus = JoinThread(client[index].thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+ PR_DestroyCondVar(client[index].stateChange);
+ PR_DestroyLock(client[index].ml);
+ }
+ PR_DELETE(client);
+ }
+
+ if (NULL != server)
+ {
+ /* All clients joined - retrieve the server */
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): notifying server(0x%p) to stop\n",
+ PR_CurrentThread(), server->thread));
+
+ PR_Lock(server->ml);
+ server->state = cs_stop;
+ PR_Interrupt(server->thread);
+ while (cs_exit != server->state)
+ PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(server->ml);
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_NOTICE,
+ ("main(0x%p): joining server(0x%p)\n",
+ PR_CurrentThread(), server->thread));
+ joinStatus = JoinThread(server->thread);
+ TEST_ASSERT(PR_SUCCESS == joinStatus);
+
+ PR_DestroyCondVar(server->stateChange);
+ PR_DestroyCondVar(server->pool.exiting);
+ PR_DestroyCondVar(server->pool.acceptComplete);
+ PR_DestroyLock(server->ml);
+ PR_DELETE(server);
+ }
+
+ TEST_LOG(
+ cltsrv_log_file, TEST_LOG_ALWAYS,
+ ("main(0x%p): test complete\n", PR_CurrentThread()));
+
+ if (thread_provider == thread_win32)
+ thread_type = "\nWin32 Thread Statistics\n";
+ else if (thread_provider == thread_pthread)
+ thread_type = "\npthread Statistics\n";
+ else if (thread_provider == thread_uithread)
+ thread_type = "\nUnix International (UI) Thread Statistics\n";
+ else if (thread_provider == thread_sproc)
+ thread_type = "\nsproc Statistics\n";
+ else {
+ PR_ASSERT(thread_provider == thread_nspr);
+ thread_type = "\nPRThread Statistics\nn";
+ }
+
+ PT_FPrintStats(debug_out, thread_type);
+
+ TimeOfDayMessage("Test exiting at", PR_CurrentThread());
+ PR_Cleanup();
+ return 0;
+} /* main */
+
+/* cltsrv.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prpoll.c b/src/libs/xpcom18a4/nsprpub/pr/tests/prpoll.c
new file mode 100644
index 00000000..5e4893f9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prpoll.c
@@ -0,0 +1,373 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#ifdef XP_OS2_VACPP
+#include <io.h> /* for close() */
+#endif
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prnetdb.h"
+
+#ifndef XP_MAC
+#include "private/pprio.h"
+#else
+#include "pprio.h"
+#endif
+
+#define CLIENT_LOOPS 5
+#define BUF_SIZE 128
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static void
+clientThreadFunc(void *arg)
+{
+ PRUint16 port = (PRUint16) arg;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ char buf[BUF_SIZE];
+ int i;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons(port);
+ addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ PR_snprintf(buf, sizeof(buf), "%hu", port);
+
+ for (i = 0; i < 5; i++) {
+ sock = PR_NewTCPSocket();
+ PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+
+ PR_Write(sock, buf, sizeof(buf));
+ PR_Close(sock);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1, *listenSock2;
+ PRFileDesc *badFD;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ char buf[BUF_SIZE];
+ PRThread *clientThread;
+ PRPollDesc pds0[10], pds1[10], *pds, *other_pds;
+ PRIntn npds;
+ PRInt32 retVal;
+ PRInt32 sd, rv;
+ struct sockaddr_in saddr;
+ PRIntn saddr_len;
+ PRUint16 listenPort3;
+ PRFileDesc *socket_poll_fd;
+ PRIntn i, j;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ printf("This program tests PR_Poll with sockets.\n");
+ printf("Timeout, error reporting, and normal operation are tested.\n\n");
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ exit(1);
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ exit(1);
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ exit(1);
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ exit(1);
+ }
+ /* Set up the poll descriptor array */
+ pds = pds0;
+ other_pds = pds1;
+ memset(pds, 0, sizeof(pds));
+ npds = 0;
+ pds[npds].fd = listenSock1;
+ pds[npds].in_flags = PR_POLL_READ;
+ npds++;
+ pds[npds].fd = listenSock2;
+ pds[npds].in_flags = PR_POLL_READ;
+ npds++;
+
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+ PR_ASSERT(sd >= 0);
+ memset((char *) &saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ saddr.sin_port = htons(0);
+
+ rv = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr));
+ PR_ASSERT(rv == 0);
+ saddr_len = sizeof(saddr);
+ rv = getsockname(sd, (struct sockaddr *) &saddr, &saddr_len);
+ PR_ASSERT(rv == 0);
+ listenPort3 = ntohs(saddr.sin_port);
+
+ rv = listen(sd, 5);
+ PR_ASSERT(rv == 0);
+ pds[npds].fd = socket_poll_fd = PR_CreateSocketPollFd(sd);
+ PR_ASSERT(pds[npds].fd);
+ pds[npds].in_flags = PR_POLL_READ;
+ npds++;
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu, %hu and %hu\n\n",
+ listenPort1, listenPort2, listenPort3);
+ printf("%s", buf);
+
+ /* Testing timeout */
+ printf("PR_Poll should time out in 5 seconds\n");
+ retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5));
+ if (retVal != 0) {
+ PR_snprintf(buf, sizeof(buf),
+ "PR_Poll should time out and return 0, but it returns %ld\n",
+ retVal);
+ fprintf(stderr, "%s", buf);
+ exit(1);
+ }
+ printf("PR_Poll timed out. Test passed.\n\n");
+
+ /* Testing bad fd */
+ printf("PR_Poll should detect a bad file descriptor\n");
+ if ((badFD = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a TCP socket\n");
+ exit(1);
+ }
+
+ pds[npds].fd = badFD;
+ pds[npds].in_flags = PR_POLL_READ;
+ npds++;
+ PR_Close(badFD); /* make the fd bad */
+#if 0
+ retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
+ if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) {
+ fprintf(stderr, "Failed to detect the bad fd: "
+ "PR_Poll returns %d, out_flags is 0x%hx\n",
+ retVal, pds[npds - 1].out_flags);
+ exit(1);
+ }
+ printf("PR_Poll detected the bad fd. Test passed.\n\n");
+#endif
+ npds--;
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort1,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ exit(1);
+ }
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort2,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ exit(1);
+ }
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort3,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ exit(1);
+ }
+
+
+ printf("Three client threads are created. Each of them will\n");
+ printf("send data to one of the three ports the server is listening on.\n");
+ printf("The data they send is the port number. Each of them send\n");
+ printf("the data five times, so you should see ten lines below,\n");
+ printf("interleaved in an arbitrary order.\n");
+
+ /* 30 events total */
+ i = 0;
+ while (i < 30) {
+ PRPollDesc *tmp;
+ int nextIndex;
+ int nEvents = 0;
+
+ retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(retVal != 0); /* no timeout */
+ if (retVal == -1) {
+ fprintf(stderr, "PR_Poll failed\n");
+ exit(1);
+ }
+
+ nextIndex = 3;
+ /* the three listening sockets */
+ for (j = 0; j < 3; j++) {
+ other_pds[j] = pds[j];
+ PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0
+ && (pds[j].out_flags & PR_POLL_EXCEPT) == 0);
+ if (pds[j].out_flags & PR_POLL_READ) {
+ PRFileDesc *sock;
+
+ nEvents++;
+ if (j == 2) {
+ int newsd;
+ newsd = accept(PR_FileDesc2NativeHandle(pds[j].fd), NULL, 0);
+ if (newsd == -1) {
+ fprintf(stderr, "accept() failed\n");
+ exit(1);
+ }
+ other_pds[nextIndex].fd = PR_CreateSocketPollFd(newsd);
+ PR_ASSERT(other_pds[nextIndex].fd);
+ other_pds[nextIndex].in_flags = PR_POLL_READ;
+ } else {
+ sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (sock == NULL) {
+ fprintf(stderr, "PR_Accept() failed\n");
+ exit(1);
+ }
+ other_pds[nextIndex].fd = sock;
+ other_pds[nextIndex].in_flags = PR_POLL_READ;
+ }
+ nextIndex++;
+ } else if (pds[j].out_flags & PR_POLL_ERR) {
+ fprintf(stderr, "PR_Poll() indicates that an fd has error\n");
+ exit(1);
+ } else if (pds[j].out_flags & PR_POLL_NVAL) {
+ fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n",
+ PR_FileDesc2NativeHandle(pds[j].fd));
+ exit(1);
+ }
+ }
+
+ for (j = 3; j < npds; j++) {
+ PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0
+ && (pds[j].out_flags & PR_POLL_EXCEPT) == 0);
+ if (pds[j].out_flags & PR_POLL_READ) {
+ PRInt32 nBytes;
+
+ nEvents++;
+ /* XXX: This call is a hack and should be fixed */
+ if (PR_GetDescType(pds[j].fd) == (PRDescType) 0) {
+ nBytes = recv(PR_FileDesc2NativeHandle(pds[j].fd), buf,
+ sizeof(buf), 0);
+ if (nBytes == -1) {
+ fprintf(stderr, "recv() failed\n");
+ exit(1);
+ }
+ printf("Server read %d bytes from native fd %d\n",nBytes,
+ PR_FileDesc2NativeHandle(pds[j].fd));
+#ifdef WIN32
+ closesocket((SOCKET)PR_FileDesc2NativeHandle(pds[j].fd));
+#else
+ close(PR_FileDesc2NativeHandle(pds[j].fd));
+#endif
+ PR_DestroySocketPollFd(pds[j].fd);
+ } else {
+ nBytes = PR_Read(pds[j].fd, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read() failed\n");
+ exit(1);
+ }
+ PR_Close(pds[j].fd);
+ }
+ /* Just to be safe */
+ buf[BUF_SIZE - 1] = '\0';
+ printf("The server received \"%s\" from a client\n", buf);
+ } else if (pds[j].out_flags & PR_POLL_ERR) {
+ fprintf(stderr, "PR_Poll() indicates that an fd has error\n");
+ exit(1);
+ } else if (pds[j].out_flags & PR_POLL_NVAL) {
+ fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n");
+ exit(1);
+ } else {
+ other_pds[nextIndex] = pds[j];
+ nextIndex++;
+ }
+ }
+
+ PR_ASSERT(retVal == nEvents);
+ /* swap */
+ tmp = pds;
+ pds = other_pds;
+ other_pds = tmp;
+ npds = nextIndex;
+ i += nEvents;
+ }
+ PR_DestroySocketPollFd(socket_poll_fd);
+
+ printf("All tests finished\n");
+ PR_Cleanup();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prpollml.c b/src/libs/xpcom18a4/nsprpub/pr/tests/prpollml.c
new file mode 100644
index 00000000..720b525c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prpollml.c
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * This test exercises the code that allocates and frees the syspoll_list
+ * array of PRThread in the pthreads version. This test is intended to be
+ * run under Purify to verify that there is no memory leak.
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define POLL_DESC_COUNT 256 /* This should be greater than the
+ * STACK_POLL_DESC_COUNT macro in
+ * ptio.c to cause syspoll_list to
+ * be created. */
+
+static PRPollDesc pd[POLL_DESC_COUNT];
+
+static void Test(void)
+{
+ int i;
+ PRInt32 rv;
+ PRIntervalTime timeout;
+
+ timeout = PR_MillisecondsToInterval(10);
+ /* cause syspoll_list to grow */
+ for (i = 1; i <= POLL_DESC_COUNT; i++) {
+ rv = PR_Poll(pd, i, timeout);
+ if (rv != 0) {
+ fprintf(stderr,
+ "PR_Poll should time out but returns %d (%d, %d)\n",
+ rv, PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ }
+ /* syspoll_list should be large enough for all these */
+ for (i = POLL_DESC_COUNT; i >= 1; i--) {
+ rv = PR_Poll(pd, i, timeout);
+ if (rv != 0) {
+ fprintf(stderr, "PR_Poll should time out but returns %d\n", rv);
+ exit(1);
+ }
+ }
+}
+
+static void ThreadFunc(void *arg)
+{
+ Test();
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ PRThread *thread;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons(0);
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ for (i = 0; i < POLL_DESC_COUNT; i++) {
+ sock = PR_NewTCPSocket();
+ if (sock == NULL) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_Bind(sock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_Listen(sock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ pd[i].fd = sock;
+ pd[i].in_flags = PR_POLL_READ;
+ }
+
+ /* first run the test on the primordial thread */
+ Test();
+
+ /* then run the test on all three kinds of threads */
+ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ for (i = 0; i < POLL_DESC_COUNT; i++) {
+ if (PR_Close(pd[i].fd) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ }
+ PR_Cleanup();
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prselect.c b/src/libs/xpcom18a4/nsprpub/pr/tests/prselect.c
new file mode 100644
index 00000000..ff6ebdc6
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prselect.c
@@ -0,0 +1,372 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1997 - Netscape Communications Corporation
+**
+** Name: prselect_err.c
+**
+** Description: tests PR_Select with sockets Error condition functions.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+#include "prttools.h"
+
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prerror.h"
+#include "prnetdb.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/***********************************************************************
+** PRIVATE FUNCTION: Test_Result
+** DESCRIPTION: Used in conjunction with the regress tool, prints out the
+** status of the test case.
+** INPUTS: PASS/FAIL
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+**
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM: Determine what the status is and print accordingly.
+**
+***********************************************************************/
+
+
+static Test_Result (int result)
+{
+ if (result == PASS)
+ printf ("PASS\n");
+ else
+ printf ("FAIL\n");
+}
+
+static void
+clientThreadFunc(void *arg)
+{
+ PRUint16 port = (PRUint16) arg;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ char buf[128];
+ int i;
+
+ addr.inet.family = AF_INET;
+ addr.inet.port = PR_htons(port);
+ addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
+ PR_snprintf(buf, sizeof(buf), "%hu", port);
+
+ for (i = 0; i < 5; i++) {
+ sock = PR_NewTCPSocket();
+ PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ PR_Write(sock, buf, sizeof(buf));
+ PR_Close(sock);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1, *listenSock2;
+ PRFileDesc *badFD;
+ PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds;
+ PRIntn nfds;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ PR_fd_set readFdSet;
+ char buf[128];
+ PRThread *clientThread;
+ PRInt32 retVal;
+ PRIntn i, j;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) {
+ printf("This program tests PR_Select with sockets. Timeout, error\n");
+ printf("reporting, and normal operation are tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ if (!debug_mode) Test_Result(FAIL);
+ exit(1);
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ printf("%s", buf);
+
+ /* Set up the fd set */
+ PR_FD_ZERO(&readFdSet);
+ PR_FD_SET(listenSock1, &readFdSet);
+ PR_FD_SET(listenSock2, &readFdSet);
+
+ /* Testing timeout */
+ if (debug_mode) printf("PR_Select should time out in 5 seconds\n");
+ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
+ PR_SecondsToInterval(5));
+ if (retVal != 0) {
+ PR_snprintf(buf, sizeof(buf),
+ "PR_Select should time out and return 0, but it returns %ld\n",
+ retVal);
+ fprintf(stderr, "%s", buf);
+ if (retVal == -1) {
+ fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
+ PR_GetOSError());
+ if (!debug_mode) Test_Result(FAIL);
+ }
+ exit(1);
+ }
+ if (debug_mode) printf("PR_Select timed out. Test passed.\n\n");
+ else Test_Result(PASS);
+
+ /* Testing bad fd */
+ printf("PR_Select should detect a bad file descriptor\n");
+ if ((badFD = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a TCP socket\n");
+ exit(1);
+ }
+
+ PR_FD_SET(listenSock1, &readFdSet);
+ PR_FD_SET(listenSock2, &readFdSet);
+ PR_FD_SET(badFD, &readFdSet);
+ PR_Close(badFD); /* make the fd bad */
+ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) {
+ fprintf(stderr, "Failed to detect the bad fd: "
+ "PR_Select returns %d\n", retVal);
+ if (retVal == -1) {
+ fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
+ PR_GetOSError());
+ }
+ exit(1);
+ }
+ printf("PR_Select detected a bad fd. Test passed.\n\n");
+ PR_FD_CLR(badFD, &readFdSet);
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort1,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ exit(1);
+ }
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort2,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ exit(1);
+ }
+
+ printf("Two client threads are created. Each of them will\n");
+ printf("send data to one of the two ports the server is listening on.\n");
+ printf("The data they send is the port number. Each of them send\n");
+ printf("the data five times, so you should see ten lines below,\n");
+ printf("interleaved in an arbitrary order.\n");
+
+ /* set up the fd array */
+ fds = fds0;
+ other_fds = fds1;
+ fds[0] = listenSock1;
+ fds[1] = listenSock2;
+ nfds = 2;
+ PR_FD_SET(listenSock1, &readFdSet);
+ PR_FD_SET(listenSock2, &readFdSet);
+
+ /* 20 events total */
+ i = 0;
+ while (i < 20) {
+ PRFileDesc **tmp;
+ int nextIndex;
+ int nEvents = 0;
+
+ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
+ PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(retVal != 0); /* no timeout */
+ if (retVal == -1) {
+ fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ exit(1);
+ }
+
+ nextIndex = 2;
+ /* the two listening sockets */
+ for (j = 0; j < 2; j++) {
+ other_fds[j] = fds[j];
+ if (PR_FD_ISSET(fds[j], &readFdSet)) {
+ PRFileDesc *sock;
+
+ nEvents++;
+ sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (sock == NULL) {
+ fprintf(stderr, "PR_Accept() failed\n");
+ exit(1);
+ }
+ other_fds[nextIndex] = sock;
+ PR_FD_SET(sock, &readFdSet);
+ nextIndex++;
+ }
+ PR_FD_SET(fds[j], &readFdSet);
+ }
+
+ for (j = 2; j < nfds; j++) {
+ if (PR_FD_ISSET(fds[j], &readFdSet)) {
+ PRInt32 nBytes;
+
+ PR_FD_CLR(fds[j], &readFdSet);
+ nEvents++;
+ nBytes = PR_Read(fds[j], buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read() failed\n");
+ exit(1);
+ }
+ /* Just to be safe */
+ buf[127] = '\0';
+ PR_Close(fds[j]);
+ printf("The server received \"%s\" from a client\n", buf);
+ } else {
+ PR_FD_SET(fds[j], &readFdSet);
+ other_fds[nextIndex] = fds[j];
+ nextIndex++;
+ }
+ }
+
+ PR_ASSERT(retVal == nEvents);
+ /* swap */
+ tmp = fds;
+ fds = other_fds;
+ other_fds = tmp;
+ nfds = nextIndex;
+ i += nEvents;
+ }
+
+ printf("All tests finished\n");
+ PR_Cleanup();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/prttools.h b/src/libs/xpcom18a4/nsprpub/pr/tests/prttools.h
new file mode 100644
index 00000000..dc38f316
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/prttools.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* Used in Regress Tool */
+#define NOSTATUS 2
+#define PASS 1
+#define FAIL 0
+
+PRIntn debug_mode=0;
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/randseed.c b/src/libs/xpcom18a4/nsprpub/pr/tests/randseed.c
new file mode 100644
index 00000000..df80bb8f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/randseed.c
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: rngseed.c
+** Description:
+** Test NSPR's Random Number Seed generator
+**
+** Initial test: Just make sure it outputs some data.
+**
+** ... more? ... check some iterations to ensure it is random (no dupes)
+** ... more? ... histogram distribution of random numbers
+*/
+
+#include <plgetopt.h>
+#include <nspr.h>
+#include <prrng.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+** Test harness infrastructure
+*/
+PRLogModuleInfo *lm;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRIntn debug = 0;
+PRUint32 failed_already = 0;
+/* end Test harness infrastructure */
+
+PRIntn optRandCount = 30;
+char buf[40];
+PRSize bufSize = sizeof(buf);
+PRSize rSize;
+PRIntn i;
+
+/*
+** Emit help text for this test
+*/
+static void Help( void )
+{
+ printf("Template: Help(): display your help message(s) here");
+ exit(1);
+} /* end Help() */
+
+static void PrintRand( void *buf, PRIntn size )
+{
+ PRUint32 *rp = buf;
+ PRIntn i;
+
+ printf("%4.4d--\n", size );
+ while (size > 0 ) {
+ switch( size ) {
+ case 1 :
+ printf("%2.2X\n", *(rp++) );
+ size -= 4;
+ break;
+ case 2 :
+ printf("%4.4X\n", *(rp++) );
+ size -= 4;
+ break;
+ case 3 :
+ printf("%6.6X\n", *(rp++) );
+ size -= 4;
+ break;
+ default:
+ while ( size >= 4) {
+ PRIntn i = 3;
+ do {
+ printf("%8.8X ", *(rp++) );
+ size -= 4;
+ } while( i-- );
+ i = 3;
+ printf("\n");
+ }
+ break;
+ } /* end switch() */
+ } /* end while() */
+} /* end PrintRand() */
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ {
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdv");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ msgLevel = PR_LOG_ERROR;
+ break;
+ case 'v': /* verbose mode */
+ msgLevel = PR_LOG_DEBUG;
+ break;
+ case 'h': /* help message */
+ Help();
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ lm = PR_NewLogModule("Test"); /* Initialize logging */
+ for ( i = 0; i < optRandCount ; i++ ) {
+ memset( buf, 0, bufSize );
+ rSize = PR_GetRandomNoise( buf, bufSize );
+ if (!rSize) {
+ fprintf(stderr, "Not implemented\n" );
+ failed_already = PR_TRUE;
+ break;
+ }
+ if (debug) PrintRand( buf, rSize );
+ }
+
+ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS");
+ return( (failed_already == PR_TRUE )? 1 : 0 );
+} /* main() */
+/* end template.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/ranfile.c b/src/libs/xpcom18a4/nsprpub/pr/tests/ranfile.c
new file mode 100644
index 00000000..a024bcd8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/ranfile.c
@@ -0,0 +1,433 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Contact: AOF<freier@netscape.com>
+**
+** Name: ranfile.c
+**
+** Description: Test to hammer on various components of NSPR
+** Modification History:
+** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prthread.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prmem.h"
+#include "prinrval.h"
+#include "prio.h"
+
+#include <string.h>
+#include <stdio.h>
+
+static PRIntn debug_mode = 0;
+static PRIntn failed_already=0;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+typedef enum {sg_go, sg_stop, sg_done} Action;
+typedef enum {sg_okay, sg_open, sg_close, sg_delete, sg_write, sg_seek} Problem;
+
+typedef struct Hammer_s {
+ PRLock *ml;
+ PRCondVar *cv;
+ PRUint32 id;
+ PRUint32 limit;
+ PRUint32 writes;
+ PRThread *thread;
+ PRIntervalTime timein;
+ Action action;
+ Problem problem;
+} Hammer_t;
+
+#define DEFAULT_LIMIT 10
+#define DEFAULT_THREADS 2
+#define DEFAULT_LOOPS 1
+
+static PRInt32 pageSize = 1024;
+static const char* baseName = "./";
+static const char *programName = "Random File";
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+/***********************************************************************
+** PRIVATE FUNCTION: Random
+** DESCRIPTION:
+** Generate a pseudo-random number
+** INPUTS: None
+** OUTPUTS: None
+** RETURN: A pseudo-random unsigned number, 32-bits wide
+** SIDE EFFECTS:
+** Updates random seed (a static)
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM:
+** Uses the current interval timer value, promoted to a 64 bit
+** float as a multiplier for a static residue (which begins
+** as an uninitialized variable). The result is bits [16..48)
+** of the product. Seed is then updated with the return value
+** promoted to a float-64.
+***********************************************************************/
+static PRUint32 Random(void)
+{
+ PRUint32 rv;
+ PRUint64 shift;
+ static PRFloat64 seed = 0x58a9382; /* Just make sure it isn't 0! */
+ PRFloat64 random = seed * (PRFloat64)PR_IntervalNow();
+ LL_USHR(shift, *((PRUint64*)&random), 16);
+ LL_L2UI(rv, shift);
+ seed = (PRFloat64)rv;
+ return rv;
+} /* Random */
+
+/***********************************************************************
+** PRIVATE FUNCTION: Thread
+** DESCRIPTION:
+** Hammer on the file I/O system
+** INPUTS: A pointer to the thread's private data
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+** Creates, accesses and deletes a file
+** RESTRICTIONS:
+** (Currently) must have file create permission in "/usr/tmp".
+** MEMORY: NA
+** ALGORITHM:
+** This function is a root of a thread
+** 1) Creates a (hopefully) unique file in /usr/tmp/
+** 2) Writes a zero to a random number of sequential pages
+** 3) Closes the file
+** 4) Reopens the file
+** 5) Seeks to a random page within the file
+** 6) Writes a one byte on that page
+** 7) Repeat steps [5..6] for each page in the file
+** 8) Close and delete the file
+** 9) Repeat steps [1..8] until told to stop
+** 10) Notify complete and return
+***********************************************************************/
+static void PR_CALLBACK Thread(void *arg)
+{
+ PRUint32 index;
+ char filename[30];
+ const char zero = 0;
+ PRFileDesc *file = NULL;
+ PRStatus rv = PR_SUCCESS;
+ Hammer_t *cd = (Hammer_t*)arg;
+
+ (void)sprintf(filename, "%ssg%04ld.dat", baseName, cd->id);
+
+ if (debug_mode) printf("Starting work on %s\n", filename);
+
+ while (PR_TRUE)
+ {
+ PRUint32 bytes;
+ PRUint32 minor = (Random() % cd->limit) + 1;
+ PRUint32 random = (Random() % cd->limit) + 1;
+ PRUint32 pages = (Random() % cd->limit) + 10;
+ while (minor-- > 0)
+ {
+ cd->problem = sg_okay;
+ if (cd->action != sg_go) goto finished;
+ cd->problem = sg_open;
+ file = PR_Open(filename, PR_RDWR|PR_CREATE_FILE, 0666);
+ if (file == NULL) goto finished;
+ for (index = 0; index < pages; index++)
+ {
+ cd->problem = sg_okay;
+ if (cd->action != sg_go) goto close;
+ cd->problem = sg_seek;
+ bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET);
+ if (bytes != pageSize * index) goto close;
+ cd->problem = sg_write;
+ bytes = PR_Write(file, &zero, sizeof(zero));
+ if (bytes <= 0) goto close;
+ cd->writes += 1;
+ }
+ cd->problem = sg_close;
+ rv = PR_Close(file);
+ if (rv != PR_SUCCESS) goto purge;
+
+ cd->problem = sg_okay;
+ if (cd->action != sg_go) goto purge;
+
+ cd->problem = sg_open;
+ file = PR_Open(filename, PR_RDWR, 0666);
+ for (index = 0; index < pages; index++)
+ {
+ cd->problem = sg_okay;
+ if (cd->action != sg_go) goto close;
+ cd->problem = sg_seek;
+ bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET);
+ if (bytes != pageSize * index) goto close;
+ cd->problem = sg_write;
+ bytes = PR_Write(file, &zero, sizeof(zero));
+ if (bytes <= 0) goto close;
+ cd->writes += 1;
+ random = (random + 511) % pages;
+ }
+ cd->problem = sg_close;
+ rv = PR_Close(file);
+ if (rv != PR_SUCCESS) goto purge;
+ cd->problem = sg_delete;
+ rv = PR_Delete(filename);
+ if (rv != PR_SUCCESS) goto finished;
+ }
+ }
+
+close:
+ (void)PR_Close(file);
+purge:
+ (void)PR_Delete(filename);
+finished:
+ PR_Lock(cd->ml);
+ cd->action = sg_done;
+ PR_NotifyCondVar(cd->cv);
+ PR_Unlock(cd->ml);
+
+ if (debug_mode) printf("Ending work on %s\n", filename);
+
+ return;
+} /* Thread */
+
+static Hammer_t hammer[100];
+static PRCondVar *cv;
+/***********************************************************************
+** PRIVATE FUNCTION: main
+** DESCRIPTION:
+** Hammer on the file I/O system
+** INPUTS: The usual argc and argv
+** argv[0] - program name (not used)
+** argv[1] - the number of times to execute the major loop
+** argv[2] - the number of threads to toss into the batch
+** argv[3] - the clipping number applied to randoms
+** default values: loops = 2, threads = 10, limit = 57
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+** Creates, accesses and deletes lots of files
+** RESTRICTIONS:
+** (Currently) must have file create permission in "/usr/tmp".
+** MEMORY: NA
+** ALGORITHM:
+** 1) Fork a "Thread()"
+** 2) Wait for 'interleave' seconds
+** 3) For [0..'threads') repeat [1..2]
+** 4) Mark all objects to stop
+** 5) Collect the threads, accumulating the results
+** 6) For [0..'loops') repeat [1..5]
+** 7) Print accumulated results and exit
+**
+** Characteristic output (from IRIX)
+** Random File: Using loops = 2, threads = 10, limit = 57
+** Random File: [min [avg] max] writes/sec average
+***********************************************************************/
+int main (int argc, char *argv[])
+{
+ PRLock *ml;
+ PRUint32 id = 0;
+ int active, poll;
+ PRIntervalTime interleave;
+ PRIntervalTime duration = 0;
+ int limit = 0, loops = 0, threads = 0, times;
+ PRUint32 writes, writesMin = 0x7fffffff, writesTot = 0, durationTot = 0, writesMax = 0;
+
+ const char *where[] = {"okay", "open", "close", "delete", "write", "seek"};
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:t:i:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'G': /* global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'l': /* limiting number */
+ limit = atoi(opt->value);
+ break;
+ case 't': /* number of threads */
+ threads = atoi(opt->value);
+ break;
+ case 'i': /* iteration counter */
+ loops = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ interleave = PR_SecondsToInterval(10);
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("ranfile.log");
+ debug_mode = 1;
+#endif
+
+ ml = PR_NewLock();
+ cv = PR_NewCondVar(ml);
+
+ if (loops == 0) loops = DEFAULT_LOOPS;
+ if (limit == 0) limit = DEFAULT_LIMIT;
+ if (threads == 0) threads = DEFAULT_THREADS;
+
+ if (debug_mode) printf(
+ "%s: Using loops = %d, threads = %d, limit = %d and %s threads\n",
+ programName, loops, threads, limit,
+ (thread_scope == PR_LOCAL_THREAD) ? "LOCAL" : "GLOBAL");
+
+ for (times = 0; times < loops; ++times)
+ {
+ if (debug_mode) printf("%s: Setting concurrency level to %d\n", programName, times + 1);
+ PR_SetConcurrency(times + 1);
+ for (active = 0; active < threads; active++)
+ {
+ hammer[active].ml = ml;
+ hammer[active].cv = cv;
+ hammer[active].id = id++;
+ hammer[active].writes = 0;
+ hammer[active].action = sg_go;
+ hammer[active].problem = sg_okay;
+ hammer[active].limit = (Random() % limit) + 1;
+ hammer[active].timein = PR_IntervalNow();
+ hammer[active].thread = PR_CreateThread(
+ PR_USER_THREAD, Thread, &hammer[active],
+ PR_GetThreadPriority(PR_GetCurrentThread()),
+ thread_scope, PR_JOINABLE_THREAD, 0);
+
+ PR_Lock(ml);
+ PR_WaitCondVar(cv, interleave); /* start new ones slowly */
+ PR_Unlock(ml);
+ }
+
+ /*
+ * The last thread started has had the opportunity to run for
+ * 'interleave' seconds. Now gather them all back in.
+ */
+ PR_Lock(ml);
+ for (poll = 0; poll < threads; poll++)
+ {
+ if (hammer[poll].action == sg_go) /* don't overwrite done */
+ hammer[poll].action = sg_stop; /* ask him to stop */
+ }
+ PR_Unlock(ml);
+
+ while (active > 0)
+ {
+ for (poll = 0; poll < threads; poll++)
+ {
+ PR_Lock(ml);
+ while (hammer[poll].action < sg_done)
+ PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(ml);
+
+ active -= 1; /* this is another one down */
+ (void)PR_JoinThread(hammer[poll].thread);
+ hammer[poll].thread = NULL;
+ if (hammer[poll].problem == sg_okay)
+ {
+ duration = PR_IntervalToMilliseconds(
+ PR_IntervalNow() - hammer[poll].timein);
+ writes = hammer[poll].writes * 1000 / duration;
+ if (writes < writesMin)
+ writesMin = writes;
+ if (writes > writesMax)
+ writesMax = writes;
+ writesTot += hammer[poll].writes;
+ durationTot += duration;
+ }
+ else
+ if (debug_mode) printf(
+ "%s: test failed %s after %ld seconds\n",
+ programName, where[hammer[poll].problem], duration);
+ else failed_already=1;
+ }
+ }
+ }
+ if (debug_mode) printf(
+ "%s: [%ld [%ld] %ld] writes/sec average\n",
+ programName, writesMin, writesTot * 1000 / durationTot, writesMax);
+
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+
+ if (failed_already)
+ {
+ printf("FAIL\n");
+ return 1;
+ }
+ else
+ {
+ printf("PASS\n");
+ return 0;
+ }
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/rmdir.c b/src/libs/xpcom18a4/nsprpub/pr/tests/rmdir.c
new file mode 100644
index 00000000..81689e8d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/rmdir.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: rmdir.c
+** Description: Demonstrate bugzilla 80884.
+**
+** after fix to unix_errors.c, message should report correct
+** failure of PR_Rmdir().
+**
+**
+**
+*/
+
+#include <prio.h>
+#include <stdio.h>
+#include <prerror.h>
+#include <prlog.h>
+#include "plgetopt.h"
+
+#define DIRNAME "xxxBug80884/"
+#define FILENAME "file80883"
+
+PRBool failed_already = PR_FALSE;
+PRBool debug_mode = PR_FALSE;
+
+PRLogModuleInfo *lm;
+
+/*
+** Help() -- print Usage information
+*/
+static void Help( void ) {
+ fprintf(stderr, "template usage:\n"
+ "\t-d debug mode\n"
+ );
+} /* --- end Help() */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dh");
+ PRFileDesc* fd;
+ PRErrorCode err;
+
+ /* parse command line options */
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ lm = PR_NewLogModule( "testcase" );
+
+ (void) PR_MkDir( DIRNAME, 0777);
+ fd = PR_Open( DIRNAME FILENAME, PR_CREATE_FILE|PR_RDWR, 0666);
+ if (fd == 0) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr, "create file fails: %d: %s\n", err,
+ PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ PR_Close(fd);
+
+ if (PR_RmDir( DIRNAME ) == PR_SUCCESS) {
+ fprintf(stderr, "remove directory succeeds\n");
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ err = PR_GetError();
+ fprintf(stderr, "remove directory fails with: %d: %s\n", err,
+ PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
+
+ (void) PR_Delete( DIRNAME FILENAME);
+ (void) PR_RmDir( DIRNAME );
+
+ return 0;
+
+Finished:
+ if ( debug_mode ) printf("%s\n", ( failed_already ) ? "FAILED" : "PASS" );
+ return( (failed_already)? 1 : 0 );
+} /* --- end main() */
+/* --- end template.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/runtests.ksh b/src/libs/xpcom18a4/nsprpub/pr/tests/runtests.ksh
new file mode 100755
index 00000000..3af86d39
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/runtests.ksh
@@ -0,0 +1,292 @@
+#!/bin/ksh
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#
+# tests.ksh
+# korn shell script for nspr tests
+#
+
+SYSTEM_INFO=`uname -a`
+OS_ARCH=`uname -s`
+if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "OS/2" ]
+then
+ NULL_DEVICE=nul
+else
+ NULL_DEVICE=/dev/null
+fi
+
+#
+# Irrevelant tests
+#
+#bug1test - used to demonstrate a bug on NT
+#bigfile2 - requires 4Gig file creation. See BugZilla #5451
+#bigfile3 - requires 4Gig file creation. See BugZilla #5451
+#dbmalloc - obsolete; originally for testing debug version of nspr's malloc
+#dbmalloc1 - obsolete; originally for testing debug version of nspr's malloc
+#depend - obsolete; used to test a initial spec for library dependencies
+#dceemu - used to tests special functions in NSPR for DCE emulation
+#ipv6 - IPV6 not in use by NSPR clients
+#mbcs - tests use of multi-byte charset for filenames. See BugZilla #25140
+#sproc_ch - obsolete; sproc-based tests for Irix
+#sproc_p - obsolete; sproc-based tests for Irix
+#io_timeoutk - obsolete; subsumed in io_timeout
+#io_timeoutu - obsolete; subsumed in io_timeout
+#prftest1 - obsolete; subsumed by prftest
+#prftest2 - obsolete; subsumed by prftest
+#prselect - obsolete; PR_Select is obsolete
+#select2 - obsolete; PR_Select is obsolete
+#sem - obsolete; PRSemaphore is obsolete
+#stat - for OS2?
+#suspend - private interfaces PR_SuspendAll, PR_ResumeAll, etc..
+#thruput - needs to be run manually as client/server
+#time - used to measure time with native calls and nspr calls
+#tmoacc - should be run with tmocon
+#tmocon - should be run with tmoacc
+#op_noacc - limited use
+#yield - limited use for PR_Yield
+
+#
+# Tests not run (but should)
+#
+
+#forktest (failed on IRIX)
+#nbconn - fails on some platforms
+#poll_er - fails on some platforms? limited use?
+#prpoll - the bad-FD test needs to be moved to a different test
+#sleep - specific to OS/2
+
+LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE}
+
+#
+# Tests run on all platforms
+#
+
+TESTS="
+accept
+acceptread
+acceptreademu
+affinity
+alarm
+anonfm
+atomic
+attach
+bigfile
+cleanup
+cltsrv
+concur
+cvar
+cvar2
+dlltest
+dtoa
+errcodes
+exit
+fdcach
+fileio
+foreign
+formattm
+fsync
+gethost
+getproto
+i2l
+initclk
+inrval
+instrumt
+intrio
+intrupt
+io_timeout
+ioconthr
+join
+joinkk
+joinku
+joinuk
+joinuu
+layer
+lazyinit
+libfilename
+lltest
+lock
+lockfile
+logger
+many_cv
+multiwait
+nameshm1
+nblayer
+nonblock
+ntioto
+ntoh
+op_2long
+op_excl
+op_filnf
+op_filok
+op_nofil
+parent
+peek
+perf
+pipeping
+pipeping2
+pipeself
+poll_nm
+poll_to
+pollable
+prftest
+primblok
+provider
+prpollml
+ranfile
+randseed
+rwlocktest
+sel_spd
+selct_er
+selct_nm
+selct_to
+selintr
+sema
+semaerr
+semaping
+sendzlf
+server_test
+servr_kk
+servr_uk
+servr_ku
+servr_uu
+short_thread
+sigpipe
+socket
+sockopt
+sockping
+sprintf
+stack
+stdio
+str2addr
+strod
+switch
+system
+testbit
+testfile
+threads
+timemac
+timetest
+tpd
+udpsrv
+vercheck
+version
+writev
+xnotify
+zerolen"
+
+rval=0
+
+
+#
+# When set, value of the environment variable TEST_TIMEOUT is the maximum
+# time (secs) allowed for a test program beyond which it is terminated.
+# If TEST_TIMEOUT is not set or if it's value is 0, then test programs
+# don't timeout.
+#
+# Running runtests.ksh under MKS toolkit on NT, 95, 98 does not cause
+# timeout detection correctly. For these platforms, do not attempt timeout
+# test. (lth).
+#
+#
+
+OS_PLATFORM=`uname`
+OBJDIR=`basename $PWD`
+echo "\nNSPR Test Results - $OBJDIR\n"
+echo "BEGIN\t\t\t`date`"
+echo "NSPR_TEST_LOGFILE\t${LOGFILE}\n"
+echo "Test\t\t\tResult\n"
+if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] || [ $OS_PLATFORM = "OS/2" ] ; then
+ for prog in $TESTS
+ do
+ echo "$prog\c"
+ echo "\nBEGIN TEST: $prog\n" >> ${LOGFILE} 2>&1
+ ./$prog >> ${LOGFILE} 2>&1
+ if [ 0 = $? ] ; then
+ echo "\t\t\tPassed";
+ else
+ echo "\t\t\tFAILED";
+ rval=1
+ fi;
+ echo "\nEND TEST: $prog\n" >> ${LOGFILE} 2>&1
+ done
+else
+ for prog in $TESTS
+ do
+ echo "$prog\c"
+ echo "\nBEGIN TEST: $prog\n" >> ${LOGFILE} 2>&1
+ export test_rval
+ ./$prog >> ${LOGFILE} 2>&1 &
+ test_pid=$!
+ sleep_pid=0
+ if [ "$TEST_TIMEOUT" -gt 0 ]
+ then
+ (sleep $TEST_TIMEOUT; kill $test_pid >/dev/null 2>&1 ) &
+ sleep_pid=$!
+ fi
+ wait $test_pid
+ test_rval=$?
+ [ $sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1
+ if [ 0 = $test_rval ] ; then
+ echo "\t\t\tPassed";
+ else
+ echo "\t\t\tFAILED";
+ rval=1
+ fi;
+ echo "\nEND TEST: $prog\n" >> ${LOGFILE} 2>&1
+ done
+fi;
+
+echo "END\t\t\t`date`"
+exit $rval
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/runtests.sh b/src/libs/xpcom18a4/nsprpub/pr/tests/runtests.sh
new file mode 100755
index 00000000..bb4a65eb
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/runtests.sh
@@ -0,0 +1,292 @@
+#!/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 Netscape Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#
+# tests.ksh
+# korn shell script for nspr tests
+#
+
+SYSTEM_INFO=`uname -a`
+OS_ARCH=`uname -s`
+if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "OS/2" ]
+then
+ NULL_DEVICE=nul
+else
+ NULL_DEVICE=/dev/null
+fi
+
+#
+# Irrevelant tests
+#
+#bug1test - used to demonstrate a bug on NT
+#bigfile2 - requires 4Gig file creation. See BugZilla #5451
+#bigfile3 - requires 4Gig file creation. See BugZilla #5451
+#dbmalloc - obsolete; originally for testing debug version of nspr's malloc
+#dbmalloc1 - obsolete; originally for testing debug version of nspr's malloc
+#depend - obsolete; used to test a initial spec for library dependencies
+#dceemu - used to tests special functions in NSPR for DCE emulation
+#ipv6 - IPV6 not in use by NSPR clients
+#mbcs - tests use of multi-byte charset for filenames. See BugZilla #25140
+#sproc_ch - obsolete; sproc-based tests for Irix
+#sproc_p - obsolete; sproc-based tests for Irix
+#io_timeoutk - obsolete; subsumed in io_timeout
+#io_timeoutu - obsolete; subsumed in io_timeout
+#prftest1 - obsolete; subsumed by prftest
+#prftest2 - obsolete; subsumed by prftest
+#prselect - obsolete; PR_Select is obsolete
+#select2 - obsolete; PR_Select is obsolete
+#sem - obsolete; PRSemaphore is obsolete
+#stat - for OS2?
+#suspend - private interfaces PR_SuspendAll, PR_ResumeAll, etc..
+#thruput - needs to be run manually as client/server
+#time - used to measure time with native calls and nspr calls
+#tmoacc - should be run with tmocon
+#tmocon - should be run with tmoacc
+#op_noacc - limited use
+#yield - limited use for PR_Yield
+
+#
+# Tests not run (but should)
+#
+
+#forktest (failed on IRIX)
+#nbconn - fails on some platforms
+#poll_er - fails on some platforms? limited use?
+#prpoll - the bad-FD test needs to be moved to a different test
+#sleep - specific to OS/2
+
+LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE}
+
+#
+# Tests run on all platforms
+#
+
+TESTS="
+accept
+acceptread
+acceptreademu
+affinity
+alarm
+anonfm
+atomic
+attach
+bigfile
+cleanup
+cltsrv
+concur
+cvar
+cvar2
+dlltest
+dtoa
+errcodes
+exit
+fdcach
+fileio
+foreign
+formattm
+fsync
+gethost
+getproto
+i2l
+initclk
+inrval
+instrumt
+intrio
+intrupt
+io_timeout
+ioconthr
+join
+joinkk
+joinku
+joinuk
+joinuu
+layer
+lazyinit
+libfilename
+lltest
+lock
+lockfile
+logger
+many_cv
+multiwait
+nameshm1
+nblayer
+nonblock
+ntioto
+ntoh
+op_2long
+op_excl
+op_filnf
+op_filok
+op_nofil
+parent
+peek
+perf
+pipeping
+pipeping2
+pipeself
+poll_nm
+poll_to
+pollable
+prftest
+primblok
+provider
+prpollml
+ranfile
+randseed
+rwlocktest
+sel_spd
+selct_er
+selct_nm
+selct_to
+selintr
+sema
+semaerr
+semaping
+sendzlf
+server_test
+servr_kk
+servr_uk
+servr_ku
+servr_uu
+short_thread
+sigpipe
+socket
+sockopt
+sockping
+sprintf
+stack
+stdio
+str2addr
+strod
+switch
+system
+testbit
+testfile
+threads
+timemac
+timetest
+tpd
+udpsrv
+vercheck
+version
+writev
+xnotify
+zerolen"
+
+rval=0
+
+
+#
+# When set, value of the environment variable TEST_TIMEOUT is the maximum
+# time (secs) allowed for a test program beyond which it is terminated.
+# If TEST_TIMEOUT is not set or if it's value is 0, then test programs
+# don't timeout.
+#
+# Running runtests.ksh under MKS toolkit on NT, 95, 98 does not cause
+# timeout detection correctly. For these platforms, do not attempt timeout
+# test. (lth).
+#
+#
+
+OS_PLATFORM=`uname`
+OBJDIR=`basename $PWD`
+printf "\nNSPR Test Results - $OBJDIR\n\n"
+printf "BEGIN\t\t\t`date`\n"
+printf "NSPR_TEST_LOGFILE\t${LOGFILE}\n\n"
+printf "Test\t\t\tResult\n\n"
+if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] || [ $OS_PLATFORM = "OS/2" ] ; then
+ for prog in $TESTS
+ do
+ printf "$prog"
+ printf "\nBEGIN TEST: $prog\n\n" >> ${LOGFILE} 2>&1
+ ./$prog >> ${LOGFILE} 2>&1
+ if [ 0 = $? ] ; then
+ printf "\t\t\tPassed\n";
+ else
+ printf "\t\t\tFAILED\n";
+ rval=1
+ fi;
+ printf "\nEND TEST: $prog\n\n" >> ${LOGFILE} 2>&1
+ done
+else
+ for prog in $TESTS
+ do
+ printf "$prog"
+ printf "\nBEGIN TEST: $prog\n\n" >> ${LOGFILE} 2>&1
+ export test_rval
+ ./$prog >> ${LOGFILE} 2>&1 &
+ test_pid=$!
+ sleep_pid=0
+ if test -n "$TEST_TIMEOUT" && test "$TEST_TIMEOUT" -gt 0
+ then
+ (sleep $TEST_TIMEOUT; kill $test_pid >/dev/null 2>&1 ) &
+ sleep_pid=$!
+ fi
+ wait $test_pid
+ test_rval=$?
+ [ $sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1
+ if [ 0 = $test_rval ] ; then
+ printf "\t\t\tPassed\n";
+ else
+ printf "\t\t\tFAILED\n";
+ rval=1
+ fi;
+ printf "\nEND TEST: $prog\n\n" >> ${LOGFILE} 2>&1
+ done
+fi;
+
+printf "END\t\t\t`date`\n"
+exit $rval
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/runy2ktests.ksh b/src/libs/xpcom18a4/nsprpub/pr/tests/runy2ktests.ksh
new file mode 100755
index 00000000..e7a32501
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/runy2ktests.ksh
@@ -0,0 +1,269 @@
+#!/bin/ksh
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#
+# runy2ktests.ksh
+# Set system clock to Y2K dates of interest and run the Y2K tests.
+# Needs root/administrator privilege
+#
+# WARNING: Because this script needs to be run with root/administrator
+# privilege, thorough understanding of the script and extreme
+# caution are urged.
+#
+
+#
+# SECTION I
+# Define variables
+#
+
+SYSTEM_INFO=`uname -a`
+OS_ARCH=`uname -s`
+if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "Windows_95" ]
+then
+ NULL_DEVICE=nul
+else
+ NULL_DEVICE=/dev/null
+fi
+
+#
+# Test dates for NSPR Y2K tests
+#
+Y2KDATES=" 123123591998.55
+ 090923591999.55
+ 123123591999.55
+ 022823592000.55
+ 022923592000.55
+ 123123592000.55"
+
+Y2KDATES_AIX=" 12312359.5598
+ 09092359.5599
+ 12312359.5599
+ 02282359.5500
+ 02292359.5500
+ 12312359.5500"
+
+Y2KDATES_HPUX=" 123123591998
+ 090923591999
+ 123123591999
+ 022823592000
+ 022923592000
+ 123123592000"
+
+Y2KDATES_MKS=" 1231235998.55
+ 0909235999.55
+ 1231235999.55
+ 0228235900.55
+ 0229235900.55
+ 1231235900.55"
+
+#
+# NSPR Y2K tests
+#
+Y2KTESTS="
+y2k \n
+y2ktmo \n
+y2k \n
+../runtests.ksh"
+
+Y2KTESTS_HPUX="
+y2k \n
+y2ktmo -l 60\n
+y2k \n
+../runtests.ksh"
+
+#
+# SECTION II
+# Define functions
+#
+
+save_date()
+{
+ case $OS_ARCH in
+ AIX)
+ SAVED_DATE=`date "+%m%d%H%M.%S%y"`
+ ;;
+ HP-UX)
+ SAVED_DATE=`date "+%m%d%H%M%Y"`
+ ;;
+ Windows_NT)
+ SAVED_DATE=`date "+%m%d%H%M%y.%S"`
+ ;;
+ Windows_95)
+ SAVED_DATE=`date "+%m%d%H%M%y.%S"`
+ ;;
+ *)
+ SAVED_DATE=`date "+%m%d%H%M%Y.%S"`
+ ;;
+ esac
+}
+
+set_date()
+{
+ case $OS_ARCH in
+ Windows_NT)
+#
+# The date command in MKS Toolkit releases 5.1 and 5.2
+# uses the current DST status for the date we want to
+# set the system clock to. However, the DST status for
+# that date may be different from the current DST status.
+# We can work around this problem by invoking the date
+# command with the same date twice.
+#
+ date "$1" > $NULL_DEVICE
+ date "$1" > $NULL_DEVICE
+ ;;
+ *)
+ date "$1" > $NULL_DEVICE
+ ;;
+ esac
+}
+
+restore_date()
+{
+ set_date "$SAVED_DATE"
+}
+
+savedate()
+{
+ case $OS_ARCH in
+ AIX)
+ SAVED_DATE=`date "+%m%d%H%M.%S%y"`
+ ;;
+ HP-UX)
+ SAVED_DATE=`date "+%m%d%H%M%Y"`
+ ;;
+ Windows_NT)
+ SAVED_DATE=`date "+%m%d%H%M%y.%S"`
+ ;;
+ Windows_95)
+ SAVED_DATE=`date "+%m%d%H%M%y.%S"`
+ ;;
+ *)
+ SAVED_DATE=`date "+%m%d%H%M%Y.%S"`
+ ;;
+ esac
+}
+
+set_y2k_test_parameters()
+{
+#
+# set dates
+#
+ case $OS_ARCH in
+ AIX)
+ DATES=$Y2KDATES_AIX
+ ;;
+ HP-UX)
+ DATES=$Y2KDATES_HPUX
+ ;;
+ Windows_NT)
+ DATES=$Y2KDATES_MKS
+ ;;
+ Windows_95)
+ DATES=$Y2KDATES_MKS
+ ;;
+ *)
+ DATES=$Y2KDATES
+ ;;
+ esac
+
+#
+# set tests
+#
+ case $OS_ARCH in
+ HP-UX)
+ TESTS=$Y2KTESTS_HPUX
+ ;;
+ *)
+ TESTS=$Y2KTESTS
+ ;;
+ esac
+}
+
+#
+# runtests:
+# - runs each test in $TESTS after setting the
+# system clock to each date in $DATES
+#
+
+runtests()
+{
+for newdate in ${DATES}
+do
+ set_date $newdate
+ echo $newdate
+ echo "BEGIN\t\t\t`date`"
+ echo "Date\t\t\t\t\tTest\t\t\tResult"
+ echo $TESTS | while read prog
+ do
+ echo "`date`\t\t\c"
+ echo "$prog\c"
+ ./$prog >> ${LOGFILE} 2>&1
+ if [ 0 = $? ] ; then
+ echo "\t\t\tPassed";
+ else
+ echo "\t\t\tFAILED";
+ fi;
+ done
+ echo "END\t\t\t`date`\n"
+done
+
+}
+
+#
+# SECTION III
+# Run tests
+#
+
+LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE}
+OBJDIR=`basename $PWD`
+echo "\nNSPR Year 2000 Test Results - $OBJDIR\n"
+echo "SYSTEM:\t\t\t${SYSTEM_INFO}"
+echo "NSPR_TEST_LOGFILE:\t${LOGFILE}\n"
+
+
+save_date
+
+#
+# Run NSPR Y2k and standard tests
+#
+
+set_y2k_test_parameters
+runtests
+
+restore_date
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/rwlocktest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/rwlocktest.c
new file mode 100644
index 00000000..b7c4f1e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/rwlocktest.c
@@ -0,0 +1,241 @@
+/* ***** 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/*
+ *
+ * RWLock tests
+ *
+ * Several threads are created to access and modify data arrays using
+ * PRRWLocks for synchronization. Two data arrays, array_A and array_B, are
+ * initialized with random data and a third array, array_C, is initialized
+ * with the sum of the first 2 arrays.
+ *
+ * Each one of the threads acquires a read lock to verify that the sum of
+ * the arrays A and B is equal to array C, and acquires a write lock to
+ * consistently update arrays A and B so that their is equal to array C.
+ *
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prrwlock.h"
+
+static int _debug_on;
+static void rwtest(void *args);
+static PRInt32 *array_A,*array_B,*array_C;
+static void update_array(void);
+static void check_array(void);
+
+typedef struct thread_args {
+ PRRWLock *rwlock;
+ PRInt32 loop_cnt;
+} thread_args;
+
+PRFileDesc *output;
+PRFileDesc *errhandle;
+
+#define DEFAULT_THREAD_CNT 4
+#define DEFAULT_LOOP_CNT 100
+#define TEST_ARRAY_SIZE 100
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRInt32 cnt;
+ PRStatus rc;
+ PRInt32 i;
+
+ PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
+ PRInt32 loop_cnt = DEFAULT_LOOP_CNT;
+ PRThread **threads;
+ thread_args *params;
+ PRRWLock *rwlock1;
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ case 'c': /* loop count */
+ loop_cnt = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(4);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ errhandle = PR_GetSpecialFD(PR_StandardError);
+
+ rwlock1 = PR_NewRWLock(0,"Lock 1");
+ if (rwlock1 == NULL) {
+ PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
+ params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt);
+
+ /*
+ * allocate and initialize data arrays
+ */
+ array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
+ array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
+ array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE);
+ cnt = 0;
+ for (i=0; i < TEST_ARRAY_SIZE;i++) {
+ array_A[i] = cnt++;
+ array_B[i] = cnt++;
+ array_C[i] = array_A[i] + array_B[i];
+ }
+
+ if (_debug_on)
+ PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0],
+ thread_cnt, loop_cnt);
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ PRThreadScope scope;
+
+ params[cnt].rwlock = rwlock1;
+ params[cnt].loop_cnt = loop_cnt;
+
+ /*
+ * create LOCAL and GLOBAL threads alternately
+ */
+ if (cnt & 1)
+ scope = PR_LOCAL_THREAD;
+ else
+ scope = PR_GLOBAL_THREAD;
+
+ threads[cnt] = PR_CreateThread(PR_USER_THREAD,
+ rwtest, &params[cnt],
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (threads[cnt] == NULL) {
+ PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
+ PR_GetError());
+ PR_ProcessExit(2);
+ }
+ if (_debug_on)
+ PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
+ threads[cnt]);
+ }
+
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+
+ }
+
+ PR_DELETE(threads);
+ PR_DELETE(params);
+
+ PR_DELETE(array_A);
+ PR_DELETE(array_B);
+ PR_DELETE(array_C);
+
+ PR_DestroyRWLock(rwlock1);
+
+
+ printf("PASS\n");
+ return 0;
+}
+
+static void rwtest(void *args)
+{
+ PRInt32 index;
+ thread_args *arg = (thread_args *) args;
+
+
+ for (index = 0; index < arg->loop_cnt; index++) {
+
+ /*
+ * verify sum, update arrays and verify sum again
+ */
+
+ PR_RWLock_Rlock(arg->rwlock);
+ check_array();
+ PR_RWLock_Unlock(arg->rwlock);
+
+ PR_RWLock_Wlock(arg->rwlock);
+ update_array();
+ PR_RWLock_Unlock(arg->rwlock);
+
+ PR_RWLock_Rlock(arg->rwlock);
+ check_array();
+ PR_RWLock_Unlock(arg->rwlock);
+ }
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] lock = 0x%x exiting\n",
+ PR_GetCurrentThread(), arg->rwlock);
+
+}
+
+static void check_array(void)
+{
+PRInt32 i;
+
+ for (i=0; i < TEST_ARRAY_SIZE;i++)
+ if (array_C[i] != (array_A[i] + array_B[i])) {
+ PR_fprintf(output, "Error - data check failed\n");
+ PR_ProcessExit(1);
+ }
+}
+
+static void update_array(void)
+{
+PRInt32 i;
+
+ for (i=0; i < TEST_ARRAY_SIZE;i++) {
+ array_A[i] += i;
+ array_B[i] -= i;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sel_spd.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sel_spd.c
new file mode 100644
index 00000000..6760e640
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sel_spd.c
@@ -0,0 +1,567 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Test the speed of select within NSPR
+ *
+ */
+
+#include "nspr.h"
+#include "prpriv.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+int fprintf(FILE *stream, const char *fmt, ...)
+{
+PR_LogPrint(fmt);
+return 0;
+}
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+#define PORT_BASE 19000
+
+typedef struct timer_slot_t {
+ unsigned long d_connect;
+ unsigned long d_cl_data;
+ unsigned long d_sv_data;
+ unsigned long d_close;
+ unsigned long d_total;
+ unsigned long requests;
+} timer_slot_t;
+
+static long _iterations = 5;
+static long _client_data = 8192;
+
+#if defined(XP_MAC)
+/*
+ * Mac does not scale well specially the requirement for thread stack
+ * space and buffer allocation space. It is easy to get into a fragmented
+ * memory and not be able to allocate thread stack or client/server data
+ * buffer.
+*/
+static long _server_data = (8*1024);
+static long _threads_max = 10, _threads = 10;
+#else
+static long _server_data = (128*1024);
+static long _threads_max = 10, _threads = 10;
+#endif
+
+static int verbose=0;
+static PRMonitor *exit_cv;
+static long _thread_exit_count;
+static timer_slot_t *timer_data;
+static PRThreadScope scope1, scope2;
+
+void tally_results(int);
+
+/* return the diff in microseconds */
+unsigned long _delta(PRIntervalTime *start, PRIntervalTime *stop)
+{
+ /*
+ * Will C do the right thing with unsigned arithemtic?
+ */
+ return PR_IntervalToMicroseconds(*stop - *start);
+}
+
+int _readn(PRFileDesc *sock, char *buf, int len)
+{
+ int rem;
+ int bytes;
+
+ for (rem=len; rem; rem -= bytes) {
+ bytes = PR_Recv(sock, buf+len-rem, rem, 0, PR_INTERVAL_NO_TIMEOUT);
+ if (bytes <= 0)
+ return -1;
+ }
+ return len;
+}
+
+void
+_thread_exit(int id)
+{
+ PR_EnterMonitor(exit_cv);
+#ifdef DEBUG
+ fprintf(stdout, "Thread %d EXIT\n", id);
+#endif
+
+ _thread_exit_count--;
+ if (_thread_exit_count == 0) {
+#ifdef DEBUG
+ fprintf(stdout, "Thread %d EXIT triggered notify\n", id);
+#endif
+ PR_Notify(exit_cv);
+ }
+ PR_ExitMonitor(exit_cv);
+}
+
+void
+_server_thread(void *arg_id)
+{
+ void _client_thread(void *);
+ PRThread *thread;
+ int *id = (int *)arg_id;
+ PRFileDesc *sock;
+ PRSocketOptionData sockopt;
+ PRNetAddr sa;
+ PRFileDesc * newsock;
+ char *data_buffer = NULL;
+ int data_buffer_size;
+ int index;
+ PRIntervalTime start,
+ connect_done,
+ read_done,
+ write_done,
+ close_done;
+
+
+#ifdef DEBUG
+ fprintf(stdout, "server thread %d alive\n", *id);
+#endif
+
+ data_buffer_size = (_client_data>_server_data?_client_data:_server_data);
+
+ if ( (data_buffer = (char *)PR_Malloc(data_buffer_size * sizeof(char))) == NULL ) {
+ fprintf(stderr, "Error creating buffer in server thread %d\n", *id);
+ goto done;
+ }
+
+
+ if ( (sock = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Error creating socket in server thread %d\n", *id);
+ goto done;
+ }
+
+ sockopt.option = PR_SockOpt_Reuseaddr;
+ sockopt.value.reuse_addr = PR_TRUE;
+ if ( PR_SetSocketOption(sock, &sockopt) == PR_FAILURE) {
+ fprintf(stderr, "Error setting socket option in server thread %d\n", *id);
+ goto done;
+ }
+
+ memset(&sa, 0 , sizeof(sa));
+ sa.inet.family = PR_AF_INET;
+ sa.inet.port = PR_htons(PORT_BASE + *id);
+ sa.inet.ip = PR_htonl(PR_INADDR_ANY);
+
+ if ( PR_Bind(sock, &sa) < 0) {
+ fprintf(stderr, "Error binding socket in server thread %d errno = %d\n", *id, errno);
+ goto done;
+ }
+
+ if ( PR_Listen(sock, 32) < 0 ) {
+ fprintf(stderr, "Error listening to socket in server thread %d\n", *id);
+ goto done;
+ }
+
+ /* Tell the client to start */
+ if ( (thread = PR_CreateThread(PR_USER_THREAD,
+ _client_thread,
+ id,
+ PR_PRIORITY_NORMAL,
+ scope2,
+ PR_UNJOINABLE_THREAD,
+ 0)) == NULL)
+ fprintf(stderr, "Error creating client thread %d\n", *id);
+
+ for (index = 0; index< _iterations; index++) {
+
+#ifdef DEBUG
+ fprintf(stdout, "server thread %d loop %d\n", *id, index);
+#endif
+
+ start = PR_IntervalNow();
+
+ if ( (newsock = PR_Accept(sock, &sa,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr, "Error accepting connection %d in server thread %d\n",
+ index, *id);
+ goto done;
+ }
+#ifdef DEBUG
+ fprintf(stdout, "server thread %d got connection %d\n", *id, newsock);
+#endif
+
+
+ connect_done = PR_IntervalNow();
+
+ if ( _readn(newsock, data_buffer, _client_data) < _client_data) {
+ fprintf(stderr, "Error reading client data for iteration %d in server thread %d\n", index, *id );
+ goto done;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "server thread %d read %d bytes\n", *id, _client_data);
+#endif
+ read_done = PR_IntervalNow();
+
+ if ( PR_Send(newsock, data_buffer, _server_data, 0,
+ PR_INTERVAL_NO_TIMEOUT) < _server_data) {
+ fprintf(stderr, "Error sending client data for iteration %d in server thread %d\n", index, *id );
+ goto done;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "server thread %d write %d bytes\n", *id, _server_data);
+#endif
+
+ write_done = PR_IntervalNow();
+
+ PR_Close(newsock);
+
+ close_done = PR_IntervalNow();
+
+ timer_data[2*(*id)].d_connect += _delta(&start, &connect_done);
+ timer_data[2*(*id)].d_cl_data += _delta(&connect_done, &read_done);
+ timer_data[2*(*id)].d_sv_data += _delta(&read_done, &write_done);
+ timer_data[2*(*id)].d_close += _delta(&write_done, &close_done);
+ timer_data[2*(*id)].d_total += _delta(&start, &close_done);
+ timer_data[2*(*id)].requests++;
+
+
+#ifdef DEBUG
+ fprintf(stdout, "server: %d %d %d %d %d\n",
+ _delta(&start, &connect_done), _delta(&connect_done, &read_done),
+ _delta(&read_done, &write_done), _delta(&write_done, &close_done),
+ _delta(&start, &close_done));
+#endif
+ }
+
+done:
+ if (data_buffer != NULL) PR_Free (data_buffer);
+ if (sock) PR_Close(sock);
+ _thread_exit(*id);
+ return;
+}
+
+void
+_client_thread(void *arg_id)
+{
+ int *id = (int *)arg_id;
+ int index;
+ PRNetAddr sa;
+ PRFileDesc *sock_h;
+ char *data_buffer = NULL;
+ int data_buffer_size;
+ int bytes;
+ PRIntervalTime start,
+ connect_done,
+ read_done,
+ write_done,
+ close_done;
+ PRStatus rv;
+
+#ifdef DEBUG
+ fprintf(stdout, "client thread %d alive\n", *id);
+#endif
+
+ data_buffer_size = (_client_data>_server_data?_client_data:_server_data);
+
+ if ( (data_buffer = (char *)PR_Malloc(data_buffer_size * sizeof(char))) == NULL) {
+ fprintf(stderr, "Error creating buffer in server thread %d\n", *id);
+ goto done;
+ }
+
+ memset(&sa, 0 , sizeof(sa));
+ rv = PR_InitializeNetAddr(PR_IpAddrLoopback, PORT_BASE + *id, &sa);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ for (index = 0; index< _iterations; index++) {
+
+#ifdef DEBUG
+ fprintf(stdout, "client thread %d loop %d\n", *id, index);
+#endif
+
+ start = PR_IntervalNow();
+ if ( (sock_h = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Error creating socket %d in client thread %d\n",
+ index, *id);
+ goto done;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "client thread %d socket created %d\n", *id, sock_h);
+#endif
+
+ if ( PR_Connect(sock_h, &sa,
+ PR_INTERVAL_NO_TIMEOUT) < 0) {
+ fprintf(stderr, "Error accepting connection %d in client thread %d\n",
+ index, *id);
+ goto done;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "client thread %d socket connected %d\n", *id, sock_h);
+#endif
+
+ connect_done = PR_IntervalNow();
+ if ( PR_Send(sock_h, data_buffer, _client_data, 0,
+ PR_INTERVAL_NO_TIMEOUT) < _client_data) {
+ fprintf(stderr, "Error sending client data for iteration %d in client thread %d\n", index, *id );
+ goto done;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "client thread %d socket wrote %d\n", *id, _client_data);
+#endif
+
+ write_done = PR_IntervalNow();
+ if ( (bytes = _readn(sock_h, data_buffer, _server_data)) < _server_data) {
+ fprintf(stderr, "Error reading server data for iteration %d in client thread %d (read %d bytes)\n", index, *id, bytes );
+ goto done;
+ }
+
+#ifdef DEBUG
+ fprintf(stdout, "client thread %d socket read %d\n", *id, _server_data);
+#endif
+
+ read_done = PR_IntervalNow();
+ PR_Close(sock_h);
+ close_done = PR_IntervalNow();
+
+ timer_data[2*(*id)+1].d_connect += _delta(&start, &connect_done);
+ timer_data[2*(*id)+1].d_cl_data += _delta(&connect_done, &write_done);
+ timer_data[2*(*id)+1].d_sv_data += _delta(&write_done, &read_done);
+ timer_data[2*(*id)+1].d_close += _delta(&read_done, &close_done);
+ timer_data[2*(*id)+1].d_total += _delta(&start, &close_done);
+ timer_data[2*(*id)+1].requests++;
+ }
+done:
+ if (data_buffer != NULL) PR_Free (data_buffer);
+ _thread_exit(*id);
+
+ return;
+}
+
+static
+void do_work(void)
+{
+ int index;
+
+ _thread_exit_count = _threads * 2;
+ for (index=0; index<_threads; index++) {
+ PRThread *thread;
+ int *id = (int *)PR_Malloc(sizeof(int));
+
+ *id = index;
+
+ if ( (thread = PR_CreateThread(PR_USER_THREAD,
+ _server_thread,
+ id,
+ PR_PRIORITY_NORMAL,
+ scope1,
+ PR_UNJOINABLE_THREAD,
+ 0)) == NULL)
+ fprintf(stderr, "Error creating server thread %d\n", index);
+ }
+
+ PR_EnterMonitor(exit_cv);
+ while (_thread_exit_count > 0)
+ PR_Wait(exit_cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(exit_cv);
+
+ fprintf(stdout, "TEST COMPLETE!\n");
+
+ tally_results(verbose);
+
+}
+
+static void do_workUU(void)
+{
+ scope1 = PR_LOCAL_THREAD;
+ scope2 = PR_LOCAL_THREAD;
+ do_work();
+}
+
+static void do_workUK(void)
+{
+ scope1 = PR_LOCAL_THREAD;
+ scope2 = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+static void do_workKU(void)
+{
+ scope1 = PR_GLOBAL_THREAD;
+ scope2 = PR_LOCAL_THREAD;
+ do_work();
+}
+
+static void do_workKK(void)
+{
+ scope1 = PR_GLOBAL_THREAD;
+ scope2 = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ printf("%40s: %6.2f usec\n", msg, d / _iterations);
+}
+
+
+int main(int argc, char **argv)
+{
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ int opt;
+ extern char *optarg;
+#endif
+
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ while ( (opt = getopt(argc, argv, "c:s:i:t:v")) != EOF) {
+ switch(opt) {
+ case 'i':
+ _iterations = atoi(optarg);
+ break;
+ case 't':
+ _threads_max = _threads = atoi(optarg);
+ break;
+ case 'c':
+ _client_data = atoi(optarg);
+ break;
+ case 's':
+ _server_data = atoi(optarg);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("sel_spd.log");
+#endif
+
+ fprintf(stdout, "Running test for %d iterations with %d simultaneous threads.\n",
+ _iterations, _threads);
+ fprintf(stdout, "\tWill send %d bytes of client data and %d bytes of server data\n",
+ _client_data, _server_data);
+
+ if ( (exit_cv = PR_NewMonitor()) == NULL)
+ fprintf(stderr, "Error creating monitor for exit cv\n");
+ if ( (timer_data = (timer_slot_t *)PR_Malloc(2*_threads * sizeof(timer_slot_t))) == NULL)
+ fprintf(stderr, "error allocating thread time results array\n");
+ memset(timer_data, 0 , 2*_threads*sizeof(timer_slot_t));
+
+ Measure(do_workUU, "select loop user/user");
+ Measure(do_workUK, "select loop user/kernel");
+ Measure(do_workKU, "select loop kernel/user");
+ Measure(do_workKK, "select loop kernel/kernel");
+
+
+ return 0;
+}
+
+void
+tally_results(int verbose)
+{
+ int index;
+ unsigned long tot_connect = 0;
+ unsigned long tot_cl_data = 0;
+ unsigned long tot_sv_data = 0;
+ unsigned long tot_close = 0;
+ unsigned long tot_all = 0;
+ unsigned long tot_requests = 0;
+
+ fprintf(stdout, "Server results:\n\n");
+ for (index=0; index<_threads_max*2; index+=2) {
+
+ if (verbose)
+ fprintf(stdout, "server thread %u\t%u\t%u\t%u\t%u\t%u\t%u\n",
+ index, timer_data[index].requests, timer_data[index].d_connect,
+ timer_data[index].d_cl_data, timer_data[index].d_sv_data,
+ timer_data[index].d_close, timer_data[index].d_total);
+
+ tot_connect += timer_data[index].d_connect / _threads;
+ tot_cl_data += timer_data[index].d_cl_data / _threads;
+ tot_sv_data += timer_data[index].d_sv_data / _threads;
+ tot_close += timer_data[index].d_close / _threads;
+ tot_all += timer_data[index].d_total / _threads;
+ tot_requests += timer_data[index].requests / _threads;
+ }
+ fprintf(stdout, "----------\n");
+ fprintf(stdout, "server per thread totals %u\t%u\t%u\t%u\t%u\n",
+ tot_requests, tot_connect, tot_cl_data, tot_sv_data, tot_close);
+ fprintf(stdout, "server per thread elapsed time %u\n", tot_all);
+ fprintf(stdout, "----------\n");
+
+ tot_connect = tot_cl_data = tot_sv_data = tot_close = tot_all = tot_requests = 0;
+ fprintf(stdout, "Client results:\n\n");
+ for (index=1; index<_threads_max*2; index+=2) {
+
+ if (verbose)
+ fprintf(stdout, "client thread %u\t%u\t%u\t%u\t%u\t%u\t%u\n",
+ index, timer_data[index].requests, timer_data[index].d_connect,
+ timer_data[index].d_cl_data, timer_data[index].d_sv_data,
+ timer_data[index].d_close, timer_data[index].d_total);
+
+ tot_connect += timer_data[index].d_connect / _threads;
+ tot_cl_data += timer_data[index].d_cl_data / _threads;
+ tot_sv_data += timer_data[index].d_sv_data / _threads;
+ tot_close += timer_data[index].d_close / _threads;
+ tot_all += timer_data[index].d_total / _threads;
+ tot_requests += timer_data[index].requests / _threads;
+ }
+ fprintf(stdout, "----------\n");
+ fprintf(stdout, "client per thread totals %u\t%u\t%u\t%u\t%u\n",
+ tot_requests, tot_connect, tot_cl_data, tot_sv_data, tot_close);
+ fprintf(stdout, "client per thread elapsed time %u\n", tot_all);
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/selct_er.c b/src/libs/xpcom18a4/nsprpub/pr/tests/selct_er.c
new file mode 100644
index 00000000..e658813f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/selct_er.c
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1997 - Netscape Communications Corporation
+**
+** Name: prselect_err.c
+**
+** Description: tests PR_Select with sockets Error condition functions.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+#ifdef XP_BEOS
+#include <stdio.h>
+int main()
+{
+ printf( "This test is not ported to the BeOS\n" );
+ return 0;
+}
+#else
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "primpl.h"
+#include "pprio.h"
+#include "prnetdb.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1, *listenSock2;
+ PRFileDesc *badFD;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ PR_fd_set readFdSet;
+ char buf[128];
+ PRInt32 retVal;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) {
+ printf("This program tests PR_Select with sockets. Error\n");
+ printf("reporting operations are tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = AF_INET;
+ addr.inet.ip = PR_htonl(INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ if (debug_mode) printf("%s", buf);
+
+ /* Set up the fd set */
+ PR_FD_ZERO(&readFdSet);
+ PR_FD_SET(listenSock1, &readFdSet);
+ PR_FD_SET(listenSock2, &readFdSet);
+
+
+ /* Testing bad fd */
+ if (debug_mode) printf("PR_Select should detect a bad file descriptor\n");
+ if ((badFD = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ PR_FD_SET(badFD, &readFdSet);
+ /*
+ * Make the fd invalid
+ */
+#if defined(XP_UNIX)
+ close(PR_FileDesc2NativeHandle(badFD));
+#elif defined(XP_OS2)
+ soclose(PR_FileDesc2NativeHandle(badFD));
+#elif defined(WIN32) || defined(WIN16)
+ closesocket(PR_FileDesc2NativeHandle(badFD));
+#elif defined(XP_MAC)
+ _PR_MD_CLOSE_SOCKET(PR_FileDesc2NativeHandle(badFD));
+#else
+#error "Unknown architecture"
+#endif
+
+ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) {
+ fprintf(stderr, "Failed to detect the bad fd: "
+ "PR_Select returns %d\n", retVal);
+ if (retVal == -1) {
+ fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
+ PR_GetOSError());
+ failed_already=1;
+ }
+ goto exit_now;
+ }
+ if (debug_mode) printf("PR_Select detected a bad fd. Test passed.\n\n");
+ PR_FD_CLR(badFD, &readFdSet);
+
+ PR_Cleanup();
+ goto exit_now;
+exit_now:
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
+
+#endif /* XP_BEOS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/selct_nm.c b/src/libs/xpcom18a4/nsprpub/pr/tests/selct_nm.c
new file mode 100644
index 00000000..56a80a76
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/selct_nm.c
@@ -0,0 +1,320 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1997 - Netscape Communications Corporation
+**
+** Name: prselect_norm.c
+**
+** Description: tests PR_Select with sockets - Normal operations.
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prerror.h"
+#include "prnetdb.h"
+
+#ifdef XP_MAC
+#include "probslet.h"
+#else
+#include "obsolete/probslet.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+static void
+clientThreadFunc(void *arg)
+{
+ PRUintn port = (PRUintn) arg;
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ char buf[128];
+ int i;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons((PRUint16)port);
+ addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.port);
+
+ for (i = 0; i < 5; i++) {
+ sock = PR_NewTCPSocket();
+ PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ PR_Write(sock, buf, sizeof(buf));
+ PR_Close(sock);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1, *listenSock2;
+ PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds;
+ PRIntn nfds;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ PR_fd_set readFdSet;
+ char buf[128];
+ PRThread *clientThread;
+ PRInt32 retVal;
+ PRIntn i, j;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) {
+ printf("This program tests PR_Select with sockets. \n");
+ printf(" Normal operation are tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+failed_already=1;
+ goto exit_now;
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ if (debug_mode) printf("%s", buf);
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort1,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ clientThreadFunc, (void *) listenPort2,
+ PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (clientThread == NULL) {
+ fprintf(stderr, "can't create thread\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if (debug_mode) {
+ printf("Two client threads are created. Each of them will\n");
+ printf("send data to one of the two ports the server is listening on.\n");
+ printf("The data they send is the port number. Each of them send\n");
+ printf("the data five times, so you should see ten lines below,\n");
+ printf("interleaved in an arbitrary order.\n");
+ }
+ /* set up the fd array */
+ fds = fds0;
+ other_fds = fds1;
+ fds[0] = listenSock1;
+ fds[1] = listenSock2;
+ nfds = 2;
+ /* Set up the fd set */
+ PR_FD_ZERO(&readFdSet);
+ PR_FD_SET(listenSock1, &readFdSet);
+ PR_FD_SET(listenSock2, &readFdSet);
+
+ /* 20 events total */
+ i = 0;
+ while (i < 20) {
+ PRFileDesc **tmp;
+ int nextIndex;
+ int nEvents = 0;
+
+ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
+ PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(retVal != 0); /* no timeout */
+ if (retVal == -1) {
+ fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+ failed_already=1;
+ goto exit_now;
+ }
+
+ nextIndex = 2;
+ /* the two listening sockets */
+ for (j = 0; j < 2; j++) {
+ other_fds[j] = fds[j];
+ if (PR_FD_ISSET(fds[j], &readFdSet)) {
+ PRFileDesc *sock;
+
+ nEvents++;
+ sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (sock == NULL) {
+ fprintf(stderr, "PR_Accept() failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ other_fds[nextIndex] = sock;
+ PR_FD_SET(sock, &readFdSet);
+ nextIndex++;
+ }
+ PR_FD_SET(fds[j], &readFdSet);
+ }
+
+ for (j = 2; j < nfds; j++) {
+ if (PR_FD_ISSET(fds[j], &readFdSet)) {
+ PRInt32 nBytes;
+
+ PR_FD_CLR(fds[j], &readFdSet);
+ nEvents++;
+ nBytes = PR_Read(fds[j], buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read() failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ /* Just to be safe */
+ buf[127] = '\0';
+ PR_Close(fds[j]);
+ if (debug_mode) printf("The server received \"%s\" from a client\n", buf);
+ } else {
+ PR_FD_SET(fds[j], &readFdSet);
+ other_fds[nextIndex] = fds[j];
+ nextIndex++;
+ }
+ }
+
+ PR_ASSERT(retVal == nEvents);
+ /* swap */
+ tmp = fds;
+ fds = other_fds;
+ other_fds = tmp;
+ nfds = nextIndex;
+ i += nEvents;
+ }
+
+ if (debug_mode) printf("Test passed\n");
+
+ PR_Cleanup();
+ goto exit_now;
+exit_now:
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/selct_to.c b/src/libs/xpcom18a4/nsprpub/pr/tests/selct_to.c
new file mode 100644
index 00000000..b5600fa9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/selct_to.c
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+** 1997 - Netscape Communications Corporation
+**
+** Name: prselect_to.c
+**
+** Description: tests PR_Select with sockets. Time out functions
+**
+** Modification History:
+** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prio.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prnetdb.h"
+
+#ifdef XP_MAC
+#include "probslet.h"
+#else
+#include "obsolete/probslet.h"
+#endif
+
+#include "prerror.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+int main(int argc, char **argv)
+{
+ PRFileDesc *listenSock1, *listenSock2;
+ PRUint16 listenPort1, listenPort2;
+ PRNetAddr addr;
+ PR_fd_set readFdSet;
+ char buf[128];
+ PRInt32 retVal;
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (debug_mode) {
+ printf("This program tests PR_Select with sockets. Timeout \n");
+ printf("operations are tested.\n\n");
+ }
+
+ /* Create two listening sockets */
+ if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort1 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+
+ if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr, "Can't create a new TCP socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(0);
+ if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "Can't bind socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ listenPort2 = PR_ntohs(addr.inet.port);
+ if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
+ fprintf(stderr, "Can't listen on a socket\n");
+ failed_already=1;
+ goto exit_now;
+ }
+ PR_snprintf(buf, sizeof(buf),
+ "The server thread is listening on ports %hu and %hu\n\n",
+ listenPort1, listenPort2);
+ if (debug_mode) printf("%s", buf);
+
+ /* Set up the fd set */
+ PR_FD_ZERO(&readFdSet);
+ PR_FD_SET(listenSock1, &readFdSet);
+ PR_FD_SET(listenSock2, &readFdSet);
+
+ /* Testing timeout */
+ if (debug_mode) printf("PR_Select should time out in 5 seconds\n");
+ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
+ PR_SecondsToInterval(5));
+ if (retVal != 0) {
+ PR_snprintf(buf, sizeof(buf),
+ "PR_Select should time out and return 0, but it returns %ld\n",
+ retVal);
+ fprintf(stderr, "%s", buf);
+ if (retVal == -1) {
+ fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(),
+ PR_GetOSError());
+ failed_already=1;
+ }
+ goto exit_now;
+ }
+ if (debug_mode) printf("PR_Select timed out. Test passed.\n\n");
+
+ PR_Cleanup();
+
+exit_now:
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/select2.c b/src/libs/xpcom18a4/nsprpub/pr/tests/select2.c
new file mode 100644
index 00000000..0651c450
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/select2.c
@@ -0,0 +1,354 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: select2.c
+**
+** Description: Measure PR_Select and Empty_Select performance.
+**
+** Modification History:
+** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+#include "prttools.h"
+#include "primpl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(OS2)
+#include <sys/time.h>
+#endif
+
+#define PORT 8000
+#define DEFAULT_COUNT 10
+PRInt32 count;
+
+
+/***********************************************************************
+** PRIVATE FUNCTION: Test_Result
+** DESCRIPTION: Used in conjunction with the regress tool, prints out the
+** status of the test case.
+** INPUTS: PASS/FAIL
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+**
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM: Determine what the status is and print accordingly.
+**
+***********************************************************************/
+
+
+static void Test_Result (int result)
+{
+ switch (result)
+ {
+ case PASS:
+ printf ("PASS\n");
+ break;
+ case FAIL:
+ printf ("FAIL\n");
+ break;
+ default:
+ printf ("NOSTATUS\n");
+ break;
+ }
+}
+
+static void EmptyPRSelect(void)
+{
+ PRInt32 index = count;
+ PRInt32 rv;
+
+ for (; index--;)
+ rv = PR_Select(0, NULL, NULL, NULL, PR_INTERVAL_NO_WAIT);
+}
+
+static void EmptyNativeSelect(void)
+{
+ PRInt32 rv;
+ PRInt32 index = count;
+ struct timeval timeout;
+
+ timeout.tv_sec = timeout.tv_usec = 0;
+ for (; index--;)
+ rv = select(0, NULL, NULL, NULL, &timeout);
+}
+
+static void PRSelectTest(void)
+{
+ PRFileDesc *listenSocket;
+ PRNetAddr serverAddr;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ return;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address\n");
+ PR_Close(listenSocket);
+ return;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ PR_Close(listenSocket);
+ return;
+ }
+ if (debug_mode) printf("Listening on port %d\n", PORT);
+
+ {
+ PRFileDesc *newSock;
+ PRNetAddr rAddr;
+ PRInt32 loops = 0;
+ PR_fd_set rdset;
+ PRInt32 rv;
+ PRInt32 bytesRead;
+ char buf[11];
+
+ loops++;
+
+ if (debug_mode) printf("Going into accept\n");
+
+ newSock = PR_Accept(listenSocket,
+ &rAddr,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ if (newSock) {
+ if (debug_mode) printf("Got connection!\n");
+ } else {
+ if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError());
+ else Test_Result (FAIL);
+ }
+
+ PR_FD_ZERO(&rdset);
+ PR_FD_SET(newSock, &rdset);
+
+ if (debug_mode) printf("Going into select \n");
+
+ rv = PR_Select(0, &rdset, 0, 0, PR_INTERVAL_NO_TIMEOUT);
+
+ if (debug_mode) printf("return from select is %d\n", rv);
+
+ if (PR_FD_ISSET(newSock, &rdset)) {
+ if (debug_mode) printf("I can't believe it- the socket is ready okay!\n");
+ } else {
+ if (debug_mode) printf("Damn; the select test failed...\n");
+ else Test_Result (FAIL);
+ }
+
+ strcpy(buf, "XXXXXXXXXX");
+ bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT);
+ buf[10] = '\0';
+
+ if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf);
+
+ PR_Close(newSock);
+ }
+
+}
+
+#if defined(XP_UNIX)
+
+static void NativeSelectTest(void)
+{
+ PRFileDesc *listenSocket;
+ PRNetAddr serverAddr;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ return;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address\n");
+ PR_Close(listenSocket);
+ return;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ PR_Close(listenSocket);
+ return;
+ }
+ if (debug_mode) printf("Listening on port %d\n", PORT);
+
+ {
+ PRIntn osfd;
+ char buf[11];
+ fd_set rdset;
+ PRNetAddr rAddr;
+ PRFileDesc *newSock;
+ struct timeval timeout;
+ PRInt32 bytesRead, rv, loops = 0;
+
+ loops++;
+
+ if (debug_mode) printf("Going into accept\n");
+
+ newSock = PR_Accept(listenSocket, &rAddr, PR_INTERVAL_NO_TIMEOUT);
+
+ if (newSock) {
+ if (debug_mode) printf("Got connection!\n");
+ } else {
+ if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError());
+ else Test_Result (FAIL);
+ }
+
+ osfd = PR_FileDesc2NativeHandle(newSock);
+ FD_ZERO(&rdset);
+ FD_SET(osfd, &rdset);
+
+ if (debug_mode) printf("Going into select \n");
+
+
+ timeout.tv_sec = 2; timeout.tv_usec = 0;
+ rv = select(osfd + 1, &rdset, NULL, NULL, &timeout);
+
+ if (debug_mode) printf("return from select is %d\n", rv);
+
+ if (FD_ISSET(osfd, &rdset)) {
+ if (debug_mode)
+ printf("I can't believe it- the socket is ready okay!\n");
+ } else {
+ if (debug_mode) printf("Damn; the select test failed...\n");
+ else Test_Result (FAIL);
+ }
+
+ strcpy(buf, "XXXXXXXXXX");
+ bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT);
+ buf[10] = '\0';
+
+ if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf);
+
+ PR_Close(newSock);
+ }
+
+} /* NativeSelectTest */
+
+#endif /* defined(XP_UNIX) */
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+ PRInt32 tot;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+ tot = PR_IntervalToMilliseconds(stop-start);
+
+ if (debug_mode) printf("%40s: %6.2f usec avg, %d msec total\n", msg, d / count, tot);
+}
+
+void main(int argc, char **argv)
+{
+
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (argc > 2) {
+ count = atoi(argv[2]);
+ } else {
+ count = DEFAULT_COUNT;
+ }
+
+#if defined(XP_UNIX)
+ Measure(NativeSelectTest, "time to call 1 element select()");
+#endif
+ Measure(EmptyPRSelect, "time to call Empty PR_select()");
+ Measure(EmptyNativeSelect, "time to call Empty select()");
+ Measure(PRSelectTest, "time to call 1 element PR_select()");
+
+ if (!debug_mode) Test_Result (NOSTATUS);
+ PR_Cleanup();
+
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/selintr.c b/src/libs/xpcom18a4/nsprpub/pr/tests/selintr.c
new file mode 100644
index 00000000..f47efca4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/selintr.c
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * 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 ***** */
+
+/*
+ * Test whether classic NSPR's select() wrapper properly blocks
+ * the periodic SIGALRM clocks. On some platforms (such as
+ * HP-UX and SINIX) an interrupted select() system call is
+ * restarted with the originally specified timeout, ignoring
+ * the time that has elapsed. If a select() call is interrupted
+ * repeatedly, it will never time out. (See Bugzilla bug #39674.)
+ */
+
+#if !defined(XP_UNIX)
+
+/*
+ * This test is applicable to Unix only.
+ */
+
+int main()
+{
+ return 0;
+}
+
+#else /* XP_UNIX */
+
+#include "nspr.h"
+
+#include <sys/time.h>
+#include <stdio.h>
+
+int main()
+{
+ struct timeval timeout;
+ int rv;
+
+ PR_SetError(0, 0); /* force NSPR to initialize */
+ PR_EnableClockInterrupts();
+
+ /* 2 seconds timeout */
+ timeout.tv_sec = 2;
+ timeout.tv_usec = 0;
+ rv = select(1, NULL, NULL, NULL, &timeout);
+ printf("select returned %d\n", rv);
+ return 0;
+}
+
+#endif /* XP_UNIX */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sem.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sem.c
new file mode 100644
index 00000000..09c9f3cd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sem.c
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: sem.c
+**
+** Description: Tests Semaphonre functions.
+**
+** Modification History:
+** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "prpriv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+/*
+ Since we don't have stdin, stdout everywhere, we will fake
+ it with our in-memory buffers called stdin and stdout.
+*/
+
+#define SBSIZE 1024
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "prsem.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#else
+#include "obsolete/prsem.h"
+#endif
+
+static char stdinBuf[SBSIZE];
+static char stdoutBuf[SBSIZE];
+
+static PRUintn stdinBufIdx = 0;
+static PRUintn stdoutBufIdx = 0;
+static PRStatus finalResult = PR_SUCCESS;
+
+
+static size_t dread (PRUintn device, char *buf, size_t bufSize)
+{
+ PRUintn i;
+
+ /* during first read call, initialize the stdinBuf buffer*/
+ if (stdinBufIdx == 0) {
+ for (i=0; i<SBSIZE; i++)
+ stdinBuf[i] = i;
+ }
+
+ /* now copy data from stdinBuf to the given buffer upto bufSize */
+ for (i=0; i<bufSize; i++) {
+ if (stdinBufIdx == SBSIZE)
+ break;
+ buf[i] = stdinBuf[stdinBufIdx++];
+ }
+
+ return i;
+}
+
+static size_t dwrite (PRUintn device, char *buf, size_t bufSize)
+{
+ PRUintn i, j;
+
+ /* copy data from the given buffer upto bufSize to stdoutBuf */
+ for (i=0; i<bufSize; i++) {
+ if (stdoutBufIdx == SBSIZE)
+ break;
+ stdoutBuf[stdoutBufIdx++] = buf[i];
+ }
+
+ /* during last write call, compare the two buffers */
+ if (stdoutBufIdx == SBSIZE)
+ for (j=0; j<SBSIZE; j++)
+ if (stdinBuf[j] != stdoutBuf[j]) {
+ if (debug_mode) printf("data mismatch for index= %d \n", j);
+ finalResult = PR_FAILURE;
+ }
+
+ return i;
+}
+
+/*------------------ Following is the real test program ---------*/
+/*
+ Program to copy standard input to standard output. The program
+ uses two threads. One reads the input and puts the data in a
+ double buffer. The other reads the buffer contents and writes
+ it to standard output.
+*/
+
+PRSemaphore *emptyBufs; /* number of empty buffers */
+PRSemaphore *fullBufs; /* number of buffers that are full */
+
+#define BSIZE 100
+
+struct {
+ char data[BSIZE];
+ PRUintn nbytes; /* number of bytes in this buffer */
+} buf[2];
+
+static void PR_CALLBACK reader(void *arg)
+{
+ PRUintn i = 0;
+ size_t nbytes;
+
+ do {
+ (void) PR_WaitSem(emptyBufs);
+ nbytes = dread(0, buf[i].data, BSIZE);
+ buf[i].nbytes = nbytes;
+ PR_PostSem(fullBufs);
+ i = (i + 1) % 2;
+ } while (nbytes > 0);
+}
+
+static void writer(void)
+{
+ PRUintn i = 0;
+ size_t nbytes;
+
+ do {
+ (void) PR_WaitSem(fullBufs);
+ nbytes = buf[i].nbytes;
+ if (nbytes > 0) {
+ nbytes = dwrite(1, buf[i].data, nbytes);
+ PR_PostSem(emptyBufs);
+ i = (i + 1) % 2;
+ }
+ } while (nbytes > 0);
+}
+
+int main(int argc, char **argv)
+{
+ PRThread *r;
+
+ PR_STDIO_INIT();
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ {
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ /* main test */
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("sem.log");
+ debug_mode = 1;
+#endif
+
+ emptyBufs = PR_NewSem(2); /* two empty buffers */
+
+ fullBufs = PR_NewSem(0); /* zero full buffers */
+
+ /* create the reader thread */
+
+ r = PR_CreateThread(PR_USER_THREAD,
+ reader, 0,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+
+ /* Do the writer operation in this thread */
+ writer();
+
+ PR_DestroySem(emptyBufs);
+ PR_DestroySem(fullBufs);
+
+ if (finalResult == PR_SUCCESS) {
+ if (debug_mode) printf("sem Test Passed.\n");
+ }
+ else{
+ if (debug_mode) printf("sem Test Failed.\n");
+ failed_already=1;
+ }
+ PR_Cleanup();
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sema.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sema.c
new file mode 100644
index 00000000..3dff8a00
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sema.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+#define SEM_NAME1 "/tmp/foo.sem"
+#define SEM_NAME2 "/tmp/bar.sem"
+#define SEM_MODE 0666
+#define ITERATIONS 1000
+
+static PRBool debug_mode = PR_FALSE;
+static PRIntn iterations = ITERATIONS;
+static PRIntn counter;
+static PRSem *sem1, *sem2;
+
+/*
+ * Thread 2 waits on semaphore 2 and posts to semaphore 1.
+ */
+void ThreadFunc(void *arg)
+{
+ PRIntn i;
+
+ for (i = 0; i < iterations; i++) {
+ if (PR_WaitSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitSemaphore failed\n");
+ exit(1);
+ }
+ if (counter == 2*i+1) {
+ if (debug_mode) printf("thread 2: counter = %d\n", counter);
+ } else {
+ fprintf(stderr, "thread 2: counter should be %d but is %d\n",
+ 2*i+1, counter);
+ exit(1);
+ }
+ counter++;
+ if (PR_PostSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_PostSemaphore failed\n");
+ exit(1);
+ }
+ }
+}
+
+static void Help(void)
+{
+ fprintf(stderr, "sema test program usage:\n");
+ fprintf(stderr, "\t-d debug mode (FALSE)\n");
+ fprintf(stderr, "\t-c <count> loop count (%d)\n", ITERATIONS);
+ fprintf(stderr, "\t-h this message\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ PRThread *thred;
+ PRIntn i;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop count */
+ iterations = atoi(opt->value);
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) {
+ fprintf(stderr, "warning: removed semaphore %s left over "
+ "from previous run\n", SEM_NAME1);
+ }
+ if (PR_DeleteSemaphore(SEM_NAME2) == PR_SUCCESS) {
+ fprintf(stderr, "warning: removed semaphore %s left over "
+ "from previous run\n", SEM_NAME2);
+ }
+
+ sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 1);
+ if (NULL == sem1) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0);
+ if (NULL == sem2) {
+ fprintf(stderr, "PR_OpenSemaphore failed\n");
+ exit(1);
+ }
+ thred = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == thred) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+
+ /*
+ * Thread 1 waits on semaphore 1 and posts to semaphore 2.
+ */
+ for (i = 0; i < iterations; i++) {
+ if (PR_WaitSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitSemaphore failed\n");
+ exit(1);
+ }
+ if (counter == 2*i) {
+ if (debug_mode) printf("thread 1: counter = %d\n", counter);
+ } else {
+ fprintf(stderr, "thread 1: counter should be %d but is %d\n",
+ 2*i, counter);
+ exit(1);
+ }
+ counter++;
+ if (PR_PostSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_PostSemaphore failed\n");
+ exit(1);
+ }
+ }
+
+ if (PR_JoinThread(thred) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+
+ if (PR_CloseSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ }
+ if (PR_CloseSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ }
+ if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSemaphore failed\n");
+ }
+ if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSemaphore failed\n");
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/semaerr.c b/src/libs/xpcom18a4/nsprpub/pr/tests/semaerr.c
new file mode 100644
index 00000000..8feb8d81
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/semaerr.c
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+#define NO_SUCH_SEM_NAME "/tmp/nosuchsem.sem"
+#define SEM_NAME1 "/tmp/foo.sem"
+#define SEM_MODE 0666
+
+static PRBool debug_mode = PR_FALSE;
+
+static void Help(void)
+{
+ fprintf(stderr, "semaerr test program usage:\n");
+ fprintf(stderr, "\t-d debug mode (FALSE)\n");
+ fprintf(stderr, "\t-h this message\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dh");
+ PRSem *sem;
+ char *child_argv[32];
+ char **child_arg;
+ PRProcess *proc;
+ PRInt32 exit_code;
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /*
+ * Open a nonexistent semaphore without the PR_SEM_CREATE
+ * flag should fail with PR_FILE_NOT_FOUND_ERROR.
+ */
+ (void) PR_DeleteSemaphore(NO_SUCH_SEM_NAME);
+ sem = PR_OpenSemaphore(NO_SUCH_SEM_NAME, 0, 0, 0);
+ if (NULL != sem) {
+ fprintf(stderr, "Opening nonexistent semaphore %s "
+ "without the PR_SEM_CREATE flag should fail "
+ "but succeeded\n", NO_SUCH_SEM_NAME);
+ exit(1);
+ }
+ if (PR_GetError() != PR_FILE_NOT_FOUND_ERROR) {
+ fprintf(stderr, "Expected error is %d but got (%d, %d)\n",
+ PR_FILE_NOT_FOUND_ERROR, PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+
+ /*
+ * Create a semaphore and let the another process
+ * try PR_SEM_CREATE and PR_SEM_CREATE|PR_SEM_EXCL.
+ */
+ if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) {
+ fprintf(stderr, "warning: deleted semaphore %s from previous "
+ "run of the test\n", SEM_NAME1);
+ }
+ sem = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0);
+ if (sem == NULL) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ child_arg = child_argv;
+ *child_arg++ = "semaerr1";
+ if (debug_mode) {
+ *child_arg++ = "-d";
+ }
+ *child_arg = NULL;
+ proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
+ if (proc == NULL) {
+ fprintf(stderr, "PR_CreateProcess failed\n");
+ exit(1);
+ }
+ if (PR_WaitProcess(proc, &exit_code) == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitProcess failed\n");
+ exit(1);
+ }
+ if (exit_code != 0) {
+ fprintf(stderr, "process semaerr1 failed\n");
+ exit(1);
+ }
+ if (PR_CloseSemaphore(sem) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ exit(1);
+ }
+ if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSemaphore failed\n");
+ exit(1);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/semaerr1.c b/src/libs/xpcom18a4/nsprpub/pr/tests/semaerr1.c
new file mode 100644
index 00000000..eeccdc43
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/semaerr1.c
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+#define SEM_NAME1 "/tmp/foo.sem"
+#define SEM_NAME2 "/tmp/bar.sem"
+#define SEM_MODE 0666
+
+static PRBool debug_mode = PR_FALSE;
+
+static void Help(void)
+{
+ fprintf(stderr, "semaerr1 test program usage:\n");
+ fprintf(stderr, "\t-d debug mode (FALSE)\n");
+ fprintf(stderr, "\t-h this message\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dh");
+ PRSem *sem;
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /*
+ * PR_SEM_CREATE|PR_SEM_EXCL should be able to
+ * create a nonexistent semaphore.
+ */
+ (void) PR_DeleteSemaphore(SEM_NAME2);
+ sem = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE|PR_SEM_EXCL, SEM_MODE, 0);
+ if (sem == NULL) {
+ fprintf(stderr, "PR_OpenSemaphore failed\n");
+ exit(1);
+ }
+ if (PR_CloseSemaphore(sem) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ exit(1);
+ }
+ if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSemaphore failed\n");
+ exit(1);
+ }
+
+ /*
+ * Opening an existing semaphore with PR_SEM_CREATE|PR_SEM_EXCL.
+ * should fail with PR_FILE_EXISTS_ERROR.
+ */
+ sem = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE|PR_SEM_EXCL, SEM_MODE, 0);
+ if (sem != NULL) {
+ fprintf(stderr, "PR_OpenSemaphore should fail but succeeded\n");
+ exit(1);
+ }
+ if (PR_GetError() != PR_FILE_EXISTS_ERROR) {
+ fprintf(stderr, "Expect %d but got %d\n", PR_FILE_EXISTS_ERROR,
+ PR_GetError());
+ exit(1);
+ }
+
+ /*
+ * Try again, with just PR_SEM_CREATE. This should succeed.
+ */
+ sem = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0);
+ if (sem == NULL) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ if (PR_CloseSemaphore(sem) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ exit(1);
+ }
+
+ sem = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE|PR_SEM_EXCL, SEM_MODE, 0);
+ if (sem == NULL) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ if (PR_CloseSemaphore(sem) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ exit(1);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/semaping.c b/src/libs/xpcom18a4/nsprpub/pr/tests/semaping.c
new file mode 100644
index 00000000..7b145fc5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/semaping.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+#define SHM_NAME "/tmp/counter"
+#define SEM_NAME1 "/tmp/foo.sem"
+#define SEM_NAME2 "/tmp/bar.sem"
+#define SEM_MODE 0666
+#define SHM_MODE 0666
+#define ITERATIONS 1000
+
+static PRBool debug_mode = PR_FALSE;
+static PRIntn iterations = ITERATIONS;
+static PRSem *sem1, *sem2;
+
+static void Help(void)
+{
+ fprintf(stderr, "semaping test program usage:\n");
+ fprintf(stderr, "\t-d debug mode (FALSE)\n");
+ fprintf(stderr, "\t-c <count> loop count (%d)\n", ITERATIONS);
+ fprintf(stderr, "\t-h this message\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ PRProcess *proc;
+ PRIntn i;
+ char *child_argv[32];
+ char **child_arg;
+ char iterations_buf[32];
+ PRSharedMemory *shm;
+ PRIntn *counter_addr;
+ PRInt32 exit_code;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop count */
+ iterations = atoi(opt->value);
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (PR_DeleteSharedMemory(SHM_NAME) == PR_SUCCESS) {
+ fprintf(stderr, "warning: removed shared memory %s left over "
+ "from previous run\n", SHM_NAME);
+ }
+ if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) {
+ fprintf(stderr, "warning: removed semaphore %s left over "
+ "from previous run\n", SEM_NAME1);
+ }
+ if (PR_DeleteSemaphore(SEM_NAME2) == PR_SUCCESS) {
+ fprintf(stderr, "warning: removed semaphore %s left over "
+ "from previous run\n", SEM_NAME2);
+ }
+
+ shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), PR_SHM_CREATE, SHM_MODE);
+ if (NULL == shm) {
+ fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ counter_addr = PR_AttachSharedMemory(shm, 0);
+ if (NULL == counter_addr) {
+ fprintf(stderr, "PR_AttachSharedMemory failed\n");
+ exit(1);
+ }
+ *counter_addr = 0;
+ sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 1);
+ if (NULL == sem1) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0);
+ if (NULL == sem2) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+
+ child_arg = &child_argv[0];
+ *child_arg++ = "semapong";
+ if (debug_mode != PR_FALSE) {
+ *child_arg++ = "-d";
+ }
+ if (iterations != ITERATIONS) {
+ *child_arg++ = "-c";
+ PR_snprintf(iterations_buf, sizeof(iterations_buf), "%d", iterations);
+ *child_arg++ = iterations_buf;
+ }
+ *child_arg = NULL;
+ proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
+ if (NULL == proc) {
+ fprintf(stderr, "PR_CreateProcess failed\n");
+ exit(1);
+ }
+
+ /*
+ * Process 1 waits on semaphore 1 and posts to semaphore 2.
+ */
+ for (i = 0; i < iterations; i++) {
+ if (PR_WaitSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitSemaphore failed\n");
+ exit(1);
+ }
+ if (*counter_addr == 2*i) {
+ if (debug_mode) printf("process 1: counter = %d\n", *counter_addr);
+ } else {
+ fprintf(stderr, "process 1: counter should be %d but is %d\n",
+ 2*i, *counter_addr);
+ exit(1);
+ }
+ (*counter_addr)++;
+ if (PR_PostSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_PostSemaphore failed\n");
+ exit(1);
+ }
+ }
+ if (PR_DetachSharedMemory(shm, counter_addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_DetachSharedMemory failed\n");
+ exit(1);
+ }
+ if (PR_CloseSharedMemory(shm) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSharedMemory failed\n");
+ exit(1);
+ }
+ if (PR_CloseSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ }
+ if (PR_CloseSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ }
+
+ if (PR_WaitProcess(proc, &exit_code) == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitProcess failed\n");
+ exit(1);
+ }
+ if (exit_code != 0) {
+ fprintf(stderr, "process 2 failed with exit code %d\n", exit_code);
+ exit(1);
+ }
+
+ if (PR_DeleteSharedMemory(SHM_NAME) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSharedMemory failed\n");
+ }
+ if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSemaphore failed\n");
+ }
+ if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) {
+ fprintf(stderr, "PR_DeleteSemaphore failed\n");
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/semapong.c b/src/libs/xpcom18a4/nsprpub/pr/tests/semapong.c
new file mode 100644
index 00000000..d3733290
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/semapong.c
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+
+#define SHM_NAME "/tmp/counter"
+#define SEM_NAME1 "/tmp/foo.sem"
+#define SEM_NAME2 "/tmp/bar.sem"
+#define ITERATIONS 1000
+
+static PRBool debug_mode = PR_FALSE;
+static PRIntn iterations = ITERATIONS;
+static PRSem *sem1, *sem2;
+
+static void Help(void)
+{
+ fprintf(stderr, "semapong test program usage:\n");
+ fprintf(stderr, "\t-d debug mode (FALSE)\n");
+ fprintf(stderr, "\t-c <count> loop count (%d)\n", ITERATIONS);
+ fprintf(stderr, "\t-h this message\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ PRIntn i;
+ PRSharedMemory *shm;
+ PRIntn *counter_addr;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop count */
+ iterations = atoi(opt->value);
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), 0, 0666);
+ if (NULL == shm) {
+ fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ sem1 = PR_OpenSemaphore(SEM_NAME1, 0, 0, 0);
+ if (NULL == sem1) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ sem2 = PR_OpenSemaphore(SEM_NAME2, 0, 0, 0);
+ if (NULL == sem2) {
+ fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+
+ counter_addr = PR_AttachSharedMemory(shm, 0);
+ if (NULL == counter_addr) {
+ fprintf(stderr, "PR_AttachSharedMemory failed\n");
+ exit(1);
+ }
+
+ /*
+ * Process 2 waits on semaphore 2 and posts to semaphore 1.
+ */
+ for (i = 0; i < iterations; i++) {
+ if (PR_WaitSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitSemaphore failed\n");
+ exit(1);
+ }
+ if (*counter_addr == 2*i+1) {
+ if (debug_mode) printf("process 2: counter = %d\n", *counter_addr);
+ } else {
+ fprintf(stderr, "process 2: counter should be %d but is %d\n",
+ 2*i+1, *counter_addr);
+ exit(1);
+ }
+ (*counter_addr)++;
+ if (PR_PostSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_PostSemaphore failed\n");
+ exit(1);
+ }
+ }
+ if (PR_DetachSharedMemory(shm, counter_addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_DetachSharedMemory failed\n");
+ exit(1);
+ }
+ if (PR_CloseSharedMemory(shm) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSharedMemory failed\n");
+ exit(1);
+ }
+ if (PR_CloseSemaphore(sem1) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ }
+ if (PR_CloseSemaphore(sem2) == PR_FAILURE) {
+ fprintf(stderr, "PR_CloseSemaphore failed\n");
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sendzlf.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sendzlf.c
new file mode 100644
index 00000000..5416475b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sendzlf.c
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Test: sendzlf.c
+ *
+ * Description: send a zero-length file with PR_SendFile and
+ * PR_TransmitFile.
+ */
+
+#define ZERO_LEN_FILE_NAME "zerolen.tmp"
+#define HEADER_STR "Header"
+#define HEADER_LEN 6 /* length of HEADER_STR, not counting the null byte */
+#define TRAILER_STR "Trailer"
+#define TRAILER_LEN 7 /* length of TRAILER_STR, not counting the null byte */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void ClientThread(void *arg)
+{
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ PRUint16 port = (PRUint16) arg;
+ char buf[1024];
+ char *bufPtr;
+ PRInt32 nbytes;
+ PRInt32 ntotal;
+ PRInt32 nexpected;
+
+ sock = PR_NewTCPSocket();
+ if (NULL == sock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ fprintf(stderr, "PR_Connect failed\n");
+ exit(1);
+ }
+ ntotal = 0;
+ bufPtr = buf;
+ while ((nbytes = PR_Read(sock, bufPtr, sizeof(buf)-ntotal)) > 0) {
+ ntotal += nbytes;
+ bufPtr += nbytes;
+ }
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ nexpected = HEADER_LEN+TRAILER_LEN+TRAILER_LEN+HEADER_LEN+HEADER_LEN;
+ if (ntotal != nexpected) {
+ fprintf(stderr, "total bytes read should be %d but is %d\n",
+ nexpected, ntotal);
+ exit(1);
+ }
+ if (memcmp(buf, HEADER_STR TRAILER_STR TRAILER_STR HEADER_STR HEADER_STR,
+ nexpected) != 0) {
+ fprintf(stderr, "wrong data is received\n");
+ exit(1);
+ }
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+static void ServerThread(void *arg)
+{
+ PRFileDesc *listenSock = (PRFileDesc *) arg;
+ PRFileDesc *acceptSock;
+ PRFileDesc *file;
+ PRSendFileData sfd;
+ char header[1024], trailer[1024];
+ PRInt32 nbytes;
+
+ /* Create a zero-length file */
+ file = PR_Open(ZERO_LEN_FILE_NAME,
+ PR_CREATE_FILE|PR_TRUNCATE|PR_RDWR, 0666);
+ if (NULL == file) {
+ fprintf(stderr, "PR_Open failed\n");
+ exit(1);
+ }
+ sfd.fd = file;
+ sfd.file_offset = 0;
+ sfd.file_nbytes = 0;
+ memcpy(header, HEADER_STR, HEADER_LEN);
+ memcpy(trailer, TRAILER_STR, TRAILER_LEN);
+ sfd.header = header;
+ sfd.hlen = HEADER_LEN;
+ sfd.trailer = trailer;
+ sfd.tlen = TRAILER_LEN;
+ acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == acceptSock) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+ /* Send both header and trailer */
+ nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (HEADER_LEN+TRAILER_LEN != nbytes) {
+ fprintf(stderr, "PR_SendFile should return %d but returned %d\n",
+ HEADER_LEN+TRAILER_LEN, nbytes);
+ exit(1);
+ }
+ /* Trailer only, no header */
+ sfd.hlen = 0;
+ nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (TRAILER_LEN != nbytes) {
+ fprintf(stderr, "PR_SendFile should return %d but returned %d\n",
+ TRAILER_LEN, nbytes);
+ exit(1);
+ }
+ /* Header only, no trailer */
+ sfd.hlen = HEADER_LEN;
+ sfd.tlen = 0;
+ nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (HEADER_LEN != nbytes) {
+ fprintf(stderr, "PR_SendFile should return %d but returned %d\n",
+ HEADER_LEN, nbytes);
+ exit(1);
+ }
+ /* Try PR_TransmitFile */
+ nbytes = PR_TransmitFile(acceptSock, file, header, HEADER_LEN,
+ PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT);
+ if (HEADER_LEN != nbytes) {
+ fprintf(stderr, "PR_TransmitFile should return %d but returned %d\n",
+ HEADER_LEN, nbytes);
+ exit(1);
+ }
+ if (PR_Close(acceptSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_Close(file) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_Delete(ZERO_LEN_FILE_NAME) == PR_FAILURE) {
+ fprintf(stderr, "PR_Delete failed\n");
+ exit(1);
+ }
+}
+
+int main()
+{
+ PRFileDesc *listenSock;
+ PRThread *clientThread;
+ PRThread *serverThread;
+ PRNetAddr addr;
+ PRThreadScope scope = PR_GLOBAL_THREAD;
+
+ listenSock = PR_NewTCPSocket();
+ if (NULL == listenSock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ /* Find out what port number we are bound to. */
+ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
+ PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == clientThread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ serverThread = PR_CreateThread(PR_USER_THREAD,
+ ServerThread, listenSock,
+ PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
+ if (NULL == serverThread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(clientThread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(serverThread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ if (PR_Close(listenSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/server_test.c b/src/libs/xpcom18a4/nsprpub/pr/tests/server_test.c
new file mode 100644
index 00000000..ffe37a5e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/server_test.c
@@ -0,0 +1,634 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** This server simulates a server running in loopback mode.
+**
+** The idea is that a single server is created. The server initially creates
+** a number of worker threads. Then, with the server running, a number of
+** clients are created which start requesting service from the server.
+**
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "pprthred.h"
+
+#include <string.h>
+
+#define PORT 15004
+#define THREAD_STACKSIZE 0
+
+#define PASS 0
+#define FAIL 1
+static int debug_mode = 0;
+
+static int _iterations = 1000;
+static int _clients = 1;
+static int _client_data = 250;
+static int _server_data = (8*1024);
+
+static PRThreadScope ServerScope, ClientScope;
+
+#define SERVER "Server"
+#define MAIN "Main"
+
+#define SERVER_STATE_STARTUP 0
+#define SERVER_STATE_READY 1
+#define SERVER_STATE_DYING 2
+#define SERVER_STATE_DEAD 4
+int ServerState;
+PRLock *ServerStateCVLock;
+PRCondVar *ServerStateCV;
+
+#undef DEBUGPRINTS
+#ifdef DEBUGPRINTS
+#define DPRINTF printf
+#else
+#define DPRINTF
+#endif
+
+
+/***********************************************************************
+** PRIVATE FUNCTION: Test_Result
+** DESCRIPTION: Used in conjunction with the regress tool, prints out the
+** status of the test case.
+** INPUTS: PASS/FAIL
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+**
+** RESTRICTIONS:
+** None
+** MEMORY: NA
+** ALGORITHM: Determine what the status is and print accordingly.
+**
+***********************************************************************/
+
+
+static void Test_Result (int result)
+{
+ switch (result)
+ {
+ case PASS:
+ printf ("PASS\n");
+ break;
+ case FAIL:
+ printf ("FAIL\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static void do_work(void);
+
+/* --- Server state functions --------------------------------------------- */
+void
+SetServerState(char *waiter, PRInt32 state)
+{
+ PR_Lock(ServerStateCVLock);
+ ServerState = state;
+ PR_NotifyCondVar(ServerStateCV);
+
+ if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
+
+ PR_Unlock(ServerStateCVLock);
+}
+
+int
+WaitServerState(char *waiter, PRInt32 state)
+{
+ PRInt32 rv;
+
+ PR_Lock(ServerStateCVLock);
+
+ if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
+
+ while(!(ServerState & state))
+ PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
+ rv = ServerState;
+
+ if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
+ waiter, state, ServerState);
+ PR_Unlock(ServerStateCVLock);
+
+ return rv;
+}
+
+/* --- Server Functions ------------------------------------------- */
+
+PRLock *workerThreadsLock;
+PRInt32 workerThreads;
+PRInt32 workerThreadsBusy;
+
+void
+WorkerThreadFunc(void *_listenSock)
+{
+ PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
+ PRInt32 bytesRead;
+ PRInt32 bytesWritten;
+ char *dataBuf;
+ char *sendBuf;
+
+ if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
+ _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
+ dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
+ if (!dataBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+ sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+
+ if (debug_mode) DPRINTF("\tServer worker thread running\n");
+
+ while(1) {
+ PRInt32 bytesToRead = _client_data;
+ PRInt32 bytesToWrite = _server_data;
+ PRFileDesc *newSock;
+ PRNetAddr *rAddr;
+ PRInt32 loops = 0;
+
+ loops++;
+
+ if (debug_mode) DPRINTF("\tServer thread going into accept\n");
+
+ bytesRead = PR_AcceptRead(listenSock,
+ &newSock,
+ &rAddr,
+ dataBuf,
+ bytesToRead,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
+
+ PR_AtomicIncrement(&workerThreadsBusy);
+ if (workerThreadsBusy == workerThreads) {
+
+ PR_Lock(workerThreadsLock);
+ if (workerThreadsBusy == workerThreads) {
+ PRThread *WorkerThread;
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSock,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread)
+ if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
+ else {
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
+ }
+ }
+ PR_Unlock(workerThreadsLock);
+ }
+
+ bytesToRead -= bytesRead;
+ while (bytesToRead) {
+ bytesRead = PR_Recv(newSock,
+ dataBuf,
+ bytesToRead,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
+ continue;
+ }
+ if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
+ }
+
+ bytesWritten = PR_Send(newSock,
+ sendBuf,
+ bytesToWrite,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesWritten != _server_data)
+ if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
+ bytesWritten, PR_GetOSError());
+ else
+ if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
+
+ PR_Close(newSock);
+ PR_AtomicDecrement(&workerThreadsBusy);
+ }
+}
+
+PRFileDesc *
+ServerSetup(void)
+{
+ PRFileDesc *listenSocket;
+ PRNetAddr serverAddr;
+ PRThread *WorkerThread;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ else Test_Result(FAIL);
+ return NULL;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
+ PR_GetOSError());
+ else Test_Result(FAIL);
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ else Test_Result(FAIL);
+ PR_Close(listenSocket);
+
+ return NULL;
+ }
+
+ /* Create Clients */
+ workerThreads = 0;
+ workerThreadsBusy = 0;
+
+ workerThreadsLock = PR_NewLock();
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSocket,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread) {
+ if (debug_mode) printf("error creating working thread\n");
+ PR_Close(listenSocket);
+ return NULL;
+ }
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
+
+ return listenSocket;
+}
+
+/* The main server loop */
+void
+ServerThreadFunc(void *unused)
+{
+ PRFileDesc *listenSocket;
+
+ /* Do setup */
+ listenSocket = ServerSetup();
+
+ if (!listenSocket) {
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ } else {
+
+ if (debug_mode) DPRINTF("\tServer up\n");
+
+ /* Tell clients they can start now. */
+ SetServerState(SERVER, SERVER_STATE_READY);
+
+ /* Now wait for server death signal */
+ WaitServerState(SERVER, SERVER_STATE_DYING);
+
+ /* Cleanup */
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ }
+}
+
+/* --- Client Functions ------------------------------------------- */
+
+PRInt32 numRequests;
+PRInt32 numClients;
+PRMonitor *clientMonitor;
+
+void
+ClientThreadFunc(void *unused)
+{
+ PRNetAddr serverAddr;
+ PRFileDesc *clientSocket;
+ char *sendBuf;
+ char *recvBuf;
+ PRInt32 rv;
+ PRInt32 bytesNeeded;
+
+ sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+ recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
+ if (!recvBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+
+ while(numRequests > 0) {
+
+ if ( (numRequests % 10) == 0 )
+ if (debug_mode) printf(".");
+ if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
+
+ clientSocket = PR_NewTCPSocket();
+ if (!clientSocket) {
+ if (debug_mode) printf("Client error creating socket: OS error %d\n",
+ PR_GetOSError());
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connecting\n");
+
+ rv = PR_Connect(clientSocket,
+ &serverAddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (!clientSocket) {
+ if (debug_mode) printf("\tClient error connecting\n");
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connected\n");
+
+ rv = PR_Send(clientSocket,
+ sendBuf,
+ _client_data,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != _client_data) {
+ if (debug_mode) printf("Client error sending data (%d)\n", rv);
+ PR_Close(clientSocket);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
+
+ bytesNeeded = _server_data;
+ while(bytesNeeded) {
+ rv = PR_Recv(clientSocket,
+ recvBuf,
+ bytesNeeded,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv <= 0) {
+ if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
+ rv, (_server_data - bytesNeeded), _server_data);
+ break;
+ }
+ if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
+ bytesNeeded -= rv;
+ }
+
+ PR_Close(clientSocket);
+
+ PR_AtomicDecrement(&numRequests);
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ --numClients;
+ PR_Notify(clientMonitor);
+ PR_ExitMonitor(clientMonitor);
+
+ PR_DELETE(sendBuf);
+ PR_DELETE(recvBuf);
+}
+
+void
+RunClients(void)
+{
+ PRInt32 index;
+
+ numRequests = _iterations;
+ numClients = _clients;
+ clientMonitor = PR_NewMonitor();
+
+ for (index=0; index<_clients; index++) {
+ PRThread *clientThread;
+
+
+ clientThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ClientThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ClientScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!clientThread) {
+ if (debug_mode) printf("\terror creating client thread %d\n", index);
+ } else
+ if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
+
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ while(numClients)
+ PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(clientMonitor);
+}
+
+/* --- Main Function ---------------------------------------------- */
+
+static
+void do_work()
+{
+ PRThread *ServerThread;
+ PRInt32 state;
+
+ SetServerState(MAIN, SERVER_STATE_STARTUP);
+ ServerThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ServerThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_JOINABLE_THREAD,
+ THREAD_STACKSIZE);
+ if (!ServerThread) {
+ if (debug_mode) printf("error creating main server thread\n");
+ return;
+ }
+
+ /* Wait for server to be ready */
+ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
+
+ if (!(state & SERVER_STATE_DEAD)) {
+ /* Run Test Clients */
+ RunClients();
+
+ /* Send death signal to server */
+ SetServerState(MAIN, SERVER_STATE_DYING);
+ }
+
+ PR_JoinThread(ServerThread);
+}
+
+static void do_workUU(void)
+{
+ ServerScope = PR_LOCAL_THREAD;
+ ClientScope = PR_LOCAL_THREAD;
+ do_work();
+}
+
+static void do_workUK(void)
+{
+ ServerScope = PR_LOCAL_THREAD;
+ ClientScope = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+static void do_workKU(void)
+{
+ ServerScope = PR_GLOBAL_THREAD;
+ ClientScope = PR_LOCAL_THREAD;
+ do_work();
+}
+
+static void do_workKK(void)
+{
+ ServerScope = PR_GLOBAL_THREAD;
+ ClientScope = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
+}
+
+
+main(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+ if (debug_mode) {
+ printf("Enter number of iterations: \n");
+ scanf("%d", &_iterations);
+ printf("Enter number of clients : \n");
+ scanf("%d", &_clients);
+ printf("Enter size of client data : \n");
+ scanf("%d", &_client_data);
+ printf("Enter size of server data : \n");
+ scanf("%d", &_server_data);
+ }
+ else {
+ _iterations = 10;
+ _clients = 1;
+ _client_data = 10;
+ _server_data = 10;
+ }
+
+ if (debug_mode) {
+ printf("\n\n%d iterations with %d client threads.\n",
+ _iterations, _clients);
+ printf("Sending %d bytes of client data and %d bytes of server data\n",
+ _client_data, _server_data);
+ }
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ ServerStateCVLock = PR_NewLock();
+ ServerStateCV = PR_NewCondVar(ServerStateCVLock);
+
+ Measure(do_workUU, "server loop user/user");
+ #if 0
+ Measure(do_workUK, "server loop user/kernel");
+ Measure(do_workKU, "server loop kernel/user");
+ Measure(do_workKK, "server loop kernel/kernel");
+ #endif
+
+ PR_Cleanup();
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/servr_kk.c b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_kk.c
new file mode 100644
index 00000000..a8fdf1df
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_kk.c
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** This server simulates a server running in loopback mode.
+**
+** The idea is that a single server is created. The server initially creates
+** a number of worker threads. Then, with the server running, a number of
+** clients are created which start requesting service from the server.
+**
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "pprthred.h"
+
+#include <string.h>
+
+#define PORT 15004
+#define THREAD_STACKSIZE 0
+
+static int _iterations = 1000;
+static int _clients = 1;
+static int _client_data = 250;
+static int _server_data = (8*1024);
+
+static PRThreadScope ServerScope, ClientScope;
+
+#define SERVER "Server"
+#define MAIN "Main"
+
+#define SERVER_STATE_STARTUP 0
+#define SERVER_STATE_READY 1
+#define SERVER_STATE_DYING 2
+#define SERVER_STATE_DEAD 4
+int ServerState;
+PRLock *ServerStateCVLock;
+PRCondVar *ServerStateCV;
+
+#ifdef DEBUGPRINTS
+#define DPRINTF printf
+#else
+#define DPRINTF
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+static void do_work(void);
+
+/* --- Server state functions --------------------------------------------- */
+void
+SetServerState(char *waiter, PRInt32 state)
+{
+ PR_Lock(ServerStateCVLock);
+ ServerState = state;
+ PR_NotifyCondVar(ServerStateCV);
+
+ if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
+
+ PR_Unlock(ServerStateCVLock);
+}
+
+int
+WaitServerState(char *waiter, PRInt32 state)
+{
+ PRInt32 rv;
+
+ PR_Lock(ServerStateCVLock);
+
+ if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
+
+ while(!(ServerState & state))
+ PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
+ rv = ServerState;
+
+ if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
+ waiter, state, ServerState);
+ PR_Unlock(ServerStateCVLock);
+
+ return rv;
+}
+
+/* --- Server Functions ------------------------------------------- */
+
+PRLock *workerThreadsLock;
+PRInt32 workerThreads;
+PRInt32 workerThreadsBusy;
+
+void
+WorkerThreadFunc(void *_listenSock)
+{
+ PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
+ PRInt32 bytesRead;
+ PRInt32 bytesWritten;
+ char *dataBuf;
+ char *sendBuf;
+
+ if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
+ _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
+ dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
+ if (!dataBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+ sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+
+ if (debug_mode) DPRINTF("\tServer worker thread running\n");
+
+ while(1) {
+ PRInt32 bytesToRead = _client_data;
+ PRInt32 bytesToWrite = _server_data;
+ PRFileDesc *newSock;
+ PRNetAddr *rAddr;
+ PRInt32 loops = 0;
+
+ loops++;
+
+ if (debug_mode) DPRINTF("\tServer thread going into accept\n");
+
+ bytesRead = PR_AcceptRead(listenSock,
+ &newSock,
+ &rAddr,
+ dataBuf,
+ bytesToRead,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
+
+ PR_AtomicIncrement(&workerThreadsBusy);
+ if (workerThreadsBusy == workerThreads) {
+
+ PR_Lock(workerThreadsLock);
+ if (workerThreadsBusy == workerThreads) {
+ PRThread *WorkerThread;
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSock,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread)
+ if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
+ else {
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
+ }
+ }
+ PR_Unlock(workerThreadsLock);
+ }
+
+ bytesToRead -= bytesRead;
+ while (bytesToRead) {
+ bytesRead = PR_Recv(newSock,
+ dataBuf,
+ bytesToRead,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
+ continue;
+ }
+ if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
+ }
+
+ bytesWritten = PR_Send(newSock,
+ sendBuf,
+ bytesToWrite,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesWritten != _server_data)
+ if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
+ bytesWritten, PR_GetOSError());
+ else
+ if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
+
+ PR_Close(newSock);
+ PR_AtomicDecrement(&workerThreadsBusy);
+ }
+}
+
+PRFileDesc *
+ServerSetup(void)
+{
+ PRFileDesc *listenSocket;
+ PRSocketOptionData sockOpt;
+ PRNetAddr serverAddr;
+ PRThread *WorkerThread;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ else failed_already=1;
+ return NULL;
+ }
+
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ else failed_already=1;
+ PR_Close(listenSocket);
+
+ return NULL;
+ }
+
+ /* Create Clients */
+ workerThreads = 0;
+ workerThreadsBusy = 0;
+
+ workerThreadsLock = PR_NewLock();
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSocket,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread) {
+ if (debug_mode) printf("error creating working thread\n");
+ PR_Close(listenSocket);
+ return NULL;
+ }
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
+
+ return listenSocket;
+}
+
+/* The main server loop */
+void
+ServerThreadFunc(void *unused)
+{
+ PRFileDesc *listenSocket;
+
+ /* Do setup */
+ listenSocket = ServerSetup();
+
+ if (!listenSocket) {
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ } else {
+
+ if (debug_mode) DPRINTF("\tServer up\n");
+
+ /* Tell clients they can start now. */
+ SetServerState(SERVER, SERVER_STATE_READY);
+
+ /* Now wait for server death signal */
+ WaitServerState(SERVER, SERVER_STATE_DYING);
+
+ /* Cleanup */
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ }
+}
+
+/* --- Client Functions ------------------------------------------- */
+
+PRInt32 numRequests;
+PRInt32 numClients;
+PRMonitor *clientMonitor;
+
+void
+ClientThreadFunc(void *unused)
+{
+ PRNetAddr serverAddr;
+ PRFileDesc *clientSocket;
+ char *sendBuf;
+ char *recvBuf;
+ PRInt32 rv;
+ PRInt32 bytesNeeded;
+
+ sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+ recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
+ if (!recvBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+
+ while(numRequests > 0) {
+
+ if ( (numRequests % 10) == 0 )
+ if (debug_mode) printf(".");
+ if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
+
+ clientSocket = PR_NewTCPSocket();
+ if (!clientSocket) {
+ if (debug_mode) printf("Client error creating socket: OS error %d\n",
+ PR_GetOSError());
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connecting\n");
+
+ rv = PR_Connect(clientSocket,
+ &serverAddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (!clientSocket) {
+ if (debug_mode) printf("\tClient error connecting\n");
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connected\n");
+
+ rv = PR_Send(clientSocket,
+ sendBuf,
+ _client_data,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != _client_data) {
+ if (debug_mode) printf("Client error sending data (%d)\n", rv);
+ PR_Close(clientSocket);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
+
+ bytesNeeded = _server_data;
+ while(bytesNeeded) {
+ rv = PR_Recv(clientSocket,
+ recvBuf,
+ bytesNeeded,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv <= 0) {
+ if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
+ rv, (_server_data - bytesNeeded), _server_data);
+ break;
+ }
+ if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
+ bytesNeeded -= rv;
+ }
+
+ PR_Close(clientSocket);
+
+ PR_AtomicDecrement(&numRequests);
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ --numClients;
+ PR_Notify(clientMonitor);
+ PR_ExitMonitor(clientMonitor);
+
+ PR_DELETE(sendBuf);
+ PR_DELETE(recvBuf);
+}
+
+void
+RunClients(void)
+{
+ PRInt32 index;
+
+ numRequests = _iterations;
+ numClients = _clients;
+ clientMonitor = PR_NewMonitor();
+
+ for (index=0; index<_clients; index++) {
+ PRThread *clientThread;
+
+
+ clientThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ClientThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ClientScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!clientThread) {
+ if (debug_mode) printf("\terror creating client thread %d\n", index);
+ } else
+ if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
+
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ while(numClients)
+ PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(clientMonitor);
+}
+
+/* --- Main Function ---------------------------------------------- */
+
+static
+void do_work()
+{
+ PRThread *ServerThread;
+ PRInt32 state;
+
+ SetServerState(MAIN, SERVER_STATE_STARTUP);
+ ServerThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ServerThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_JOINABLE_THREAD,
+ THREAD_STACKSIZE);
+ if (!ServerThread) {
+ if (debug_mode) printf("error creating main server thread\n");
+ return;
+ }
+
+ /* Wait for server to be ready */
+ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
+
+ if (!(state & SERVER_STATE_DEAD)) {
+ /* Run Test Clients */
+ RunClients();
+
+ /* Send death signal to server */
+ SetServerState(MAIN, SERVER_STATE_DYING);
+ }
+
+ PR_JoinThread(ServerThread);
+}
+
+static void do_workUU(void)
+{
+ ServerScope = PR_LOCAL_THREAD;
+ ClientScope = PR_LOCAL_THREAD;
+ do_work();
+}
+
+static void do_workUK(void)
+{
+ ServerScope = PR_LOCAL_THREAD;
+ ClientScope = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+static void do_workKU(void)
+{
+ ServerScope = PR_GLOBAL_THREAD;
+ ClientScope = PR_LOCAL_THREAD;
+ do_work();
+}
+
+static void do_workKK(void)
+{
+ ServerScope = PR_GLOBAL_THREAD;
+ ClientScope = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
+}
+
+
+int main(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+ if (debug_mode) {
+ printf("Enter number of iterations: \n");
+ scanf("%d", &_iterations);
+ printf("Enter number of clients : \n");
+ scanf("%d", &_clients);
+ printf("Enter size of client data : \n");
+ scanf("%d", &_client_data);
+ printf("Enter size of server data : \n");
+ scanf("%d", &_server_data);
+ }
+ else {
+ _iterations = 7;
+ _clients = 7;
+ _client_data = 100;
+ _server_data = 100;
+ }
+
+ if (debug_mode) {
+ printf("\n\n%d iterations with %d client threads.\n",
+ _iterations, _clients);
+ printf("Sending %d bytes of client data and %d bytes of server data\n",
+ _client_data, _server_data);
+ }
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ PR_SetThreadRecycleMode(64);
+
+ ServerStateCVLock = PR_NewLock();
+ ServerStateCV = PR_NewCondVar(ServerStateCVLock);
+
+
+ Measure(do_workKK, "server loop kernel/kernel");
+
+ PR_Cleanup();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/servr_ku.c b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_ku.c
new file mode 100644
index 00000000..fa0a168e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_ku.c
@@ -0,0 +1,593 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** This server simulates a server running in loopback mode.
+**
+** The idea is that a single server is created. The server initially creates
+** a number of worker threads. Then, with the server running, a number of
+** clients are created which start requesting service from the server.
+**
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "pprthred.h"
+
+#include <string.h>
+
+#define PORT 15004
+#define THREAD_STACKSIZE 0
+
+static int _iterations = 1000;
+static int _clients = 1;
+static int _client_data = 250;
+static int _server_data = (8*1024);
+
+static PRThreadScope ServerScope, ClientScope;
+
+#define SERVER "Server"
+#define MAIN "Main"
+
+#define SERVER_STATE_STARTUP 0
+#define SERVER_STATE_READY 1
+#define SERVER_STATE_DYING 2
+#define SERVER_STATE_DEAD 4
+int ServerState;
+PRLock *ServerStateCVLock;
+PRCondVar *ServerStateCV;
+
+#ifdef DEBUGPRINTS
+#define DPRINTF printf
+#else
+#define DPRINTF
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+static void do_work(void);
+
+/* --- Server state functions --------------------------------------------- */
+void
+SetServerState(char *waiter, PRInt32 state)
+{
+ PR_Lock(ServerStateCVLock);
+ ServerState = state;
+ PR_NotifyCondVar(ServerStateCV);
+
+ if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
+
+ PR_Unlock(ServerStateCVLock);
+}
+
+int
+WaitServerState(char *waiter, PRInt32 state)
+{
+ PRInt32 rv;
+
+ PR_Lock(ServerStateCVLock);
+
+ if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
+
+ while(!(ServerState & state))
+ PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
+ rv = ServerState;
+
+ if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
+ waiter, state, ServerState);
+ PR_Unlock(ServerStateCVLock);
+
+ return rv;
+}
+
+/* --- Server Functions ------------------------------------------- */
+
+PRLock *workerThreadsLock;
+PRInt32 workerThreads;
+PRInt32 workerThreadsBusy;
+
+void
+WorkerThreadFunc(void *_listenSock)
+{
+ PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
+ PRInt32 bytesRead;
+ PRInt32 bytesWritten;
+ char *dataBuf;
+ char *sendBuf;
+
+ if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
+ _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
+ dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
+ if (!dataBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+ sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+
+ if (debug_mode) DPRINTF("\tServer worker thread running\n");
+
+ while(1) {
+ PRInt32 bytesToRead = _client_data;
+ PRInt32 bytesToWrite = _server_data;
+ PRFileDesc *newSock;
+ PRNetAddr *rAddr;
+ PRInt32 loops = 0;
+
+ loops++;
+
+ if (debug_mode) DPRINTF("\tServer thread going into accept\n");
+
+ bytesRead = PR_AcceptRead(listenSock,
+ &newSock,
+ &rAddr,
+ dataBuf,
+ bytesToRead,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
+
+ PR_AtomicIncrement(&workerThreadsBusy);
+ if (workerThreadsBusy == workerThreads) {
+
+ PR_Lock(workerThreadsLock);
+ if (workerThreadsBusy == workerThreads) {
+ PRThread *WorkerThread;
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSock,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread)
+ if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
+ else {
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
+ }
+ }
+ PR_Unlock(workerThreadsLock);
+ }
+
+ bytesToRead -= bytesRead;
+ while (bytesToRead) {
+ bytesRead = PR_Recv(newSock,
+ dataBuf,
+ bytesToRead,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
+ continue;
+ }
+ if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
+ }
+
+ bytesWritten = PR_Send(newSock,
+ sendBuf,
+ bytesToWrite,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesWritten != _server_data)
+ if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
+ bytesWritten, PR_GetOSError());
+ else
+ if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
+
+ PR_Close(newSock);
+ PR_AtomicDecrement(&workerThreadsBusy);
+ }
+}
+
+PRFileDesc *
+ServerSetup(void)
+{
+ PRFileDesc *listenSocket;
+ PRSocketOptionData sockOpt;
+ PRNetAddr serverAddr;
+ PRThread *WorkerThread;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ else failed_already=1;
+ return NULL;
+ }
+
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ else failed_already=1;
+ PR_Close(listenSocket);
+
+ return NULL;
+ }
+
+ /* Create Clients */
+ workerThreads = 0;
+ workerThreadsBusy = 0;
+
+ workerThreadsLock = PR_NewLock();
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSocket,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread) {
+ if (debug_mode) printf("error creating working thread\n");
+ PR_Close(listenSocket);
+ return NULL;
+ }
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
+
+ return listenSocket;
+}
+
+/* The main server loop */
+void
+ServerThreadFunc(void *unused)
+{
+ PRFileDesc *listenSocket;
+
+ /* Do setup */
+ listenSocket = ServerSetup();
+
+ if (!listenSocket) {
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ } else {
+
+ if (debug_mode) DPRINTF("\tServer up\n");
+
+ /* Tell clients they can start now. */
+ SetServerState(SERVER, SERVER_STATE_READY);
+
+ /* Now wait for server death signal */
+ WaitServerState(SERVER, SERVER_STATE_DYING);
+
+ /* Cleanup */
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ }
+}
+
+/* --- Client Functions ------------------------------------------- */
+
+PRInt32 numRequests;
+PRInt32 numClients;
+PRMonitor *clientMonitor;
+
+void
+ClientThreadFunc(void *unused)
+{
+ PRNetAddr serverAddr;
+ PRFileDesc *clientSocket;
+ char *sendBuf;
+ char *recvBuf;
+ PRInt32 rv;
+ PRInt32 bytesNeeded;
+
+ sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+ recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
+ if (!recvBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+
+ while(numRequests > 0) {
+
+ if ( (numRequests % 10) == 0 )
+ if (debug_mode) printf(".");
+ if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
+
+ clientSocket = PR_NewTCPSocket();
+ if (!clientSocket) {
+ if (debug_mode) printf("Client error creating socket: OS error %d\n",
+ PR_GetOSError());
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connecting\n");
+
+ rv = PR_Connect(clientSocket,
+ &serverAddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (!clientSocket) {
+ if (debug_mode) printf("\tClient error connecting\n");
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connected\n");
+
+ rv = PR_Send(clientSocket,
+ sendBuf,
+ _client_data,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != _client_data) {
+ if (debug_mode) printf("Client error sending data (%d)\n", rv);
+ PR_Close(clientSocket);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
+
+ bytesNeeded = _server_data;
+ while(bytesNeeded) {
+ rv = PR_Recv(clientSocket,
+ recvBuf,
+ bytesNeeded,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv <= 0) {
+ if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
+ rv, (_server_data - bytesNeeded), _server_data);
+ break;
+ }
+ if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
+ bytesNeeded -= rv;
+ }
+
+ PR_Close(clientSocket);
+
+ PR_AtomicDecrement(&numRequests);
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ --numClients;
+ PR_Notify(clientMonitor);
+ PR_ExitMonitor(clientMonitor);
+
+ PR_DELETE(sendBuf);
+ PR_DELETE(recvBuf);
+}
+
+void
+RunClients(void)
+{
+ PRInt32 index;
+
+ numRequests = _iterations;
+ numClients = _clients;
+ clientMonitor = PR_NewMonitor();
+
+ for (index=0; index<_clients; index++) {
+ PRThread *clientThread;
+
+
+ clientThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ClientThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ClientScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!clientThread) {
+ if (debug_mode) printf("\terror creating client thread %d\n", index);
+ } else
+ if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
+
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ while(numClients)
+ PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(clientMonitor);
+}
+
+/* --- Main Function ---------------------------------------------- */
+
+static
+void do_work()
+{
+ PRThread *ServerThread;
+ PRInt32 state;
+
+ SetServerState(MAIN, SERVER_STATE_STARTUP);
+ ServerThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ServerThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_JOINABLE_THREAD,
+ THREAD_STACKSIZE);
+ if (!ServerThread) {
+ if (debug_mode) printf("error creating main server thread\n");
+ return;
+ }
+
+ /* Wait for server to be ready */
+ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
+
+ if (!(state & SERVER_STATE_DEAD)) {
+ /* Run Test Clients */
+ RunClients();
+
+ /* Send death signal to server */
+ SetServerState(MAIN, SERVER_STATE_DYING);
+ }
+
+ PR_JoinThread(ServerThread);
+}
+
+
+static void do_workKU(void)
+{
+ ServerScope = PR_GLOBAL_THREAD;
+ ClientScope = PR_LOCAL_THREAD;
+ do_work();
+}
+
+
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
+}
+
+
+main(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+ if (debug_mode) {
+ printf("Enter number of iterations: \n");
+ scanf("%d", &_iterations);
+ printf("Enter number of clients : \n");
+ scanf("%d", &_clients);
+ printf("Enter size of client data : \n");
+ scanf("%d", &_client_data);
+ printf("Enter size of server data : \n");
+ scanf("%d", &_server_data);
+ }
+ else {
+ _iterations = 7;
+ _clients = 7;
+ _client_data = 100;
+ _server_data = 100;
+ }
+
+ if (debug_mode) {
+ printf("\n\n%d iterations with %d client threads.\n",
+ _iterations, _clients);
+ printf("Sending %d bytes of client data and %d bytes of server data\n",
+ _client_data, _server_data);
+ }
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ PR_SetThreadRecycleMode(64);
+
+ ServerStateCVLock = PR_NewLock();
+ ServerStateCV = PR_NewCondVar(ServerStateCVLock);
+
+ Measure(do_workKU, "server loop kernel/user");
+
+ PR_Cleanup();
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uk.c b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uk.c
new file mode 100644
index 00000000..139081af
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uk.c
@@ -0,0 +1,595 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** This server simulates a server running in loopback mode.
+**
+** The idea is that a single server is created. The server initially creates
+** a number of worker threads. Then, with the server running, a number of
+** clients are created which start requesting service from the server.
+**
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "pprthred.h"
+
+#include <string.h>
+
+#define PORT 15004
+#define THREAD_STACKSIZE 0
+
+static int _iterations = 1000;
+static int _clients = 1;
+static int _client_data = 250;
+static int _server_data = (8*1024);
+
+static PRThreadScope ServerScope, ClientScope;
+
+#define SERVER "Server"
+#define MAIN "Main"
+
+#define SERVER_STATE_STARTUP 0
+#define SERVER_STATE_READY 1
+#define SERVER_STATE_DYING 2
+#define SERVER_STATE_DEAD 4
+int ServerState;
+PRLock *ServerStateCVLock;
+PRCondVar *ServerStateCV;
+
+#ifdef DEBUGPRINTS
+#define DPRINTF printf
+#else
+#define DPRINTF
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+
+
+static void do_work(void);
+
+/* --- Server state functions --------------------------------------------- */
+void
+SetServerState(char *waiter, PRInt32 state)
+{
+ PR_Lock(ServerStateCVLock);
+ ServerState = state;
+ PR_NotifyCondVar(ServerStateCV);
+
+ if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
+
+ PR_Unlock(ServerStateCVLock);
+}
+
+int
+WaitServerState(char *waiter, PRInt32 state)
+{
+ PRInt32 rv;
+
+ PR_Lock(ServerStateCVLock);
+
+ if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
+
+ while(!(ServerState & state))
+ PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
+ rv = ServerState;
+
+ if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
+ waiter, state, ServerState);
+ PR_Unlock(ServerStateCVLock);
+
+ return rv;
+}
+
+/* --- Server Functions ------------------------------------------- */
+
+PRLock *workerThreadsLock;
+PRInt32 workerThreads;
+PRInt32 workerThreadsBusy;
+
+void
+WorkerThreadFunc(void *_listenSock)
+{
+ PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
+ PRInt32 bytesRead;
+ PRInt32 bytesWritten;
+ char *dataBuf;
+ char *sendBuf;
+
+ if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
+ _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
+ dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
+ if (!dataBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+ sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+
+ if (debug_mode) DPRINTF("\tServer worker thread running\n");
+
+ while(1) {
+ PRInt32 bytesToRead = _client_data;
+ PRInt32 bytesToWrite = _server_data;
+ PRFileDesc *newSock;
+ PRNetAddr *rAddr;
+ PRInt32 loops = 0;
+
+ loops++;
+
+ if (debug_mode) DPRINTF("\tServer thread going into accept\n");
+
+ bytesRead = PR_AcceptRead(listenSock,
+ &newSock,
+ &rAddr,
+ dataBuf,
+ bytesToRead,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
+
+ PR_AtomicIncrement(&workerThreadsBusy);
+ if (workerThreadsBusy == workerThreads) {
+
+ PR_Lock(workerThreadsLock);
+ if (workerThreadsBusy == workerThreads) {
+ PRThread *WorkerThread;
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSock,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread)
+ if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
+ else {
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
+ }
+ }
+ PR_Unlock(workerThreadsLock);
+ }
+
+ bytesToRead -= bytesRead;
+ while (bytesToRead) {
+ bytesRead = PR_Recv(newSock,
+ dataBuf,
+ bytesToRead,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
+ continue;
+ }
+ if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
+ }
+
+ bytesWritten = PR_Send(newSock,
+ sendBuf,
+ bytesToWrite,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesWritten != _server_data)
+ if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
+ bytesWritten, PR_GetOSError());
+ else
+ if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
+
+ PR_Close(newSock);
+ PR_AtomicDecrement(&workerThreadsBusy);
+ }
+}
+
+PRFileDesc *
+ServerSetup(void)
+{
+ PRFileDesc *listenSocket;
+ PRSocketOptionData sockOpt;
+ PRNetAddr serverAddr;
+ PRThread *WorkerThread;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ else
+ return NULL;
+ }
+
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ else failed_already=1;
+ PR_Close(listenSocket);
+
+ return NULL;
+ }
+
+ /* Create Clients */
+ workerThreads = 0;
+ workerThreadsBusy = 0;
+
+ workerThreadsLock = PR_NewLock();
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSocket,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread) {
+ if (debug_mode) printf("error creating working thread\n");
+ PR_Close(listenSocket);
+ return NULL;
+ }
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
+
+ return listenSocket;
+}
+
+/* The main server loop */
+void
+ServerThreadFunc(void *unused)
+{
+ PRFileDesc *listenSocket;
+
+ /* Do setup */
+ listenSocket = ServerSetup();
+
+ if (!listenSocket) {
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ } else {
+
+ if (debug_mode) DPRINTF("\tServer up\n");
+
+ /* Tell clients they can start now. */
+ SetServerState(SERVER, SERVER_STATE_READY);
+
+ /* Now wait for server death signal */
+ WaitServerState(SERVER, SERVER_STATE_DYING);
+
+ /* Cleanup */
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ }
+}
+
+/* --- Client Functions ------------------------------------------- */
+
+PRInt32 numRequests;
+PRInt32 numClients;
+PRMonitor *clientMonitor;
+
+void
+ClientThreadFunc(void *unused)
+{
+ PRNetAddr serverAddr;
+ PRFileDesc *clientSocket;
+ char *sendBuf;
+ char *recvBuf;
+ PRInt32 rv;
+ PRInt32 bytesNeeded;
+
+ sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+ recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
+ if (!recvBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+
+ while(numRequests > 0) {
+
+ if ( (numRequests % 10) == 0 )
+ if (debug_mode) printf(".");
+ if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
+
+ clientSocket = PR_NewTCPSocket();
+ if (!clientSocket) {
+ if (debug_mode) printf("Client error creating socket: OS error %d\n",
+ PR_GetOSError());
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connecting\n");
+
+ rv = PR_Connect(clientSocket,
+ &serverAddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (!clientSocket) {
+ if (debug_mode) printf("\tClient error connecting\n");
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connected\n");
+
+ rv = PR_Send(clientSocket,
+ sendBuf,
+ _client_data,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != _client_data) {
+ if (debug_mode) printf("Client error sending data (%d)\n", rv);
+ PR_Close(clientSocket);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
+
+ bytesNeeded = _server_data;
+ while(bytesNeeded) {
+ rv = PR_Recv(clientSocket,
+ recvBuf,
+ bytesNeeded,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv <= 0) {
+ if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
+ rv, (_server_data - bytesNeeded), _server_data);
+ break;
+ }
+ if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
+ bytesNeeded -= rv;
+ }
+
+ PR_Close(clientSocket);
+
+ PR_AtomicDecrement(&numRequests);
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ --numClients;
+ PR_Notify(clientMonitor);
+ PR_ExitMonitor(clientMonitor);
+
+ PR_DELETE(sendBuf);
+ PR_DELETE(recvBuf);
+}
+
+void
+RunClients(void)
+{
+ PRInt32 index;
+
+ numRequests = _iterations;
+ numClients = _clients;
+ clientMonitor = PR_NewMonitor();
+
+ for (index=0; index<_clients; index++) {
+ PRThread *clientThread;
+
+
+ clientThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ClientThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ClientScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!clientThread) {
+ if (debug_mode) printf("\terror creating client thread %d\n", index);
+ } else
+ if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
+
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ while(numClients)
+ PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(clientMonitor);
+}
+
+/* --- Main Function ---------------------------------------------- */
+
+static
+void do_work()
+{
+ PRThread *ServerThread;
+ PRInt32 state;
+
+ SetServerState(MAIN, SERVER_STATE_STARTUP);
+ ServerThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ServerThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_JOINABLE_THREAD,
+ THREAD_STACKSIZE);
+ if (!ServerThread) {
+ if (debug_mode) printf("error creating main server thread\n");
+ return;
+ }
+
+ /* Wait for server to be ready */
+ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
+
+ if (!(state & SERVER_STATE_DEAD)) {
+ /* Run Test Clients */
+ RunClients();
+
+ /* Send death signal to server */
+ SetServerState(MAIN, SERVER_STATE_DYING);
+ }
+
+ PR_JoinThread(ServerThread);
+}
+
+
+static void do_workUK(void)
+{
+ ServerScope = PR_LOCAL_THREAD;
+ ClientScope = PR_GLOBAL_THREAD;
+ do_work();
+}
+
+
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
+}
+
+
+main(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+ if (debug_mode) {
+ printf("Enter number of iterations: \n");
+ scanf("%d", &_iterations);
+ printf("Enter number of clients : \n");
+ scanf("%d", &_clients);
+ printf("Enter size of client data : \n");
+ scanf("%d", &_client_data);
+ printf("Enter size of server data : \n");
+ scanf("%d", &_server_data);
+ }
+ else {
+ _iterations = 7;
+ _clients = 7;
+ _client_data = 100;
+ _server_data = 100;
+ }
+
+ if (debug_mode) {
+ printf("\n\n%d iterations with %d client threads.\n",
+ _iterations, _clients);
+ printf("Sending %d bytes of client data and %d bytes of server data\n",
+ _client_data, _server_data);
+ }
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ PR_SetThreadRecycleMode(64);
+
+ ServerStateCVLock = PR_NewLock();
+ ServerStateCV = PR_NewCondVar(ServerStateCVLock);
+
+ Measure(do_workUK, "server loop user/kernel");
+
+ PR_Cleanup();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uu.c b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uu.c
new file mode 100644
index 00000000..3bd1d574
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/servr_uu.c
@@ -0,0 +1,593 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** This server simulates a server running in loopback mode.
+**
+** The idea is that a single server is created. The server initially creates
+** a number of worker threads. Then, with the server running, a number of
+** clients are created which start requesting service from the server.
+**
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "pprthred.h"
+
+#include <string.h>
+
+#define PORT 15004
+#define THREAD_STACKSIZE 0
+
+static int _iterations = 1000;
+static int _clients = 1;
+static int _client_data = 250;
+static int _server_data = (8*1024);
+
+static PRThreadScope ServerScope, ClientScope;
+
+#define SERVER "Server"
+#define MAIN "Main"
+
+#define SERVER_STATE_STARTUP 0
+#define SERVER_STATE_READY 1
+#define SERVER_STATE_DYING 2
+#define SERVER_STATE_DEAD 4
+int ServerState;
+PRLock *ServerStateCVLock;
+PRCondVar *ServerStateCV;
+
+#ifdef DEBUGPRINTS
+#define DPRINTF printf
+#else
+#define DPRINTF
+#endif
+
+PRIntn failed_already=0;
+PRIntn debug_mode;
+
+static void do_work(void);
+
+/* --- Server state functions --------------------------------------------- */
+void
+SetServerState(char *waiter, PRInt32 state)
+{
+ PR_Lock(ServerStateCVLock);
+ ServerState = state;
+ PR_NotifyCondVar(ServerStateCV);
+
+ if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
+
+ PR_Unlock(ServerStateCVLock);
+}
+
+int
+WaitServerState(char *waiter, PRInt32 state)
+{
+ PRInt32 rv;
+
+ PR_Lock(ServerStateCVLock);
+
+ if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
+
+ while(!(ServerState & state))
+ PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
+ rv = ServerState;
+
+ if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n",
+ waiter, state, ServerState);
+ PR_Unlock(ServerStateCVLock);
+
+ return rv;
+}
+
+/* --- Server Functions ------------------------------------------- */
+
+PRLock *workerThreadsLock;
+PRInt32 workerThreads;
+PRInt32 workerThreadsBusy;
+
+void
+WorkerThreadFunc(void *_listenSock)
+{
+ PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
+ PRInt32 bytesRead;
+ PRInt32 bytesWritten;
+ char *dataBuf;
+ char *sendBuf;
+
+ if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
+ _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
+ dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
+ if (!dataBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+ sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tServer could not malloc space!?\n");
+
+ if (debug_mode) DPRINTF("\tServer worker thread running\n");
+
+ while(1) {
+ PRInt32 bytesToRead = _client_data;
+ PRInt32 bytesToWrite = _server_data;
+ PRFileDesc *newSock;
+ PRNetAddr *rAddr;
+ PRInt32 loops = 0;
+
+ loops++;
+
+ if (debug_mode) DPRINTF("\tServer thread going into accept\n");
+
+ bytesRead = PR_AcceptRead(listenSock,
+ &newSock,
+ &rAddr,
+ dataBuf,
+ bytesToRead,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
+
+ PR_AtomicIncrement(&workerThreadsBusy);
+ if (workerThreadsBusy == workerThreads) {
+
+ PR_Lock(workerThreadsLock);
+ if (workerThreadsBusy == workerThreads) {
+ PRThread *WorkerThread;
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSock,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread)
+ if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
+ else {
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
+ }
+ }
+ PR_Unlock(workerThreadsLock);
+ }
+
+ bytesToRead -= bytesRead;
+ while (bytesToRead) {
+ bytesRead = PR_Recv(newSock,
+ dataBuf,
+ bytesToRead,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesRead < 0) {
+ if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
+ continue;
+ }
+ if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
+ }
+
+ bytesWritten = PR_Send(newSock,
+ sendBuf,
+ bytesToWrite,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytesWritten != _server_data)
+ if (debug_mode) printf("\tError sending data to client (%d, %d)\n",
+ bytesWritten, PR_GetOSError());
+ else
+ if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
+
+ PR_Close(newSock);
+ PR_AtomicDecrement(&workerThreadsBusy);
+ }
+}
+
+PRFileDesc *
+ServerSetup(void)
+{
+ PRFileDesc *listenSocket;
+ PRSocketOptionData sockOpt;
+ PRNetAddr serverAddr;
+ PRThread *WorkerThread;
+
+ if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
+ if (debug_mode) printf("\tServer error creating listen socket\n");
+ else failed_already=1;
+ return NULL;
+ }
+
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+
+ if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
+ PR_GetOSError());
+ else failed_already=1;
+ PR_Close(listenSocket);
+ return NULL;
+ }
+
+ if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
+ if (debug_mode) printf("\tServer error listening to server socket\n");
+ else failed_already=1;
+ PR_Close(listenSocket);
+
+ return NULL;
+ }
+
+ /* Create Clients */
+ workerThreads = 0;
+ workerThreadsBusy = 0;
+
+ workerThreadsLock = PR_NewLock();
+
+ WorkerThread = PR_CreateThread(
+ PR_SYSTEM_THREAD,
+ WorkerThreadFunc,
+ listenSocket,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!WorkerThread) {
+ if (debug_mode) printf("error creating working thread\n");
+ PR_Close(listenSocket);
+ return NULL;
+ }
+ PR_AtomicIncrement(&workerThreads);
+ if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
+
+ return listenSocket;
+}
+
+/* The main server loop */
+void
+ServerThreadFunc(void *unused)
+{
+ PRFileDesc *listenSocket;
+
+ /* Do setup */
+ listenSocket = ServerSetup();
+
+ if (!listenSocket) {
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ } else {
+
+ if (debug_mode) DPRINTF("\tServer up\n");
+
+ /* Tell clients they can start now. */
+ SetServerState(SERVER, SERVER_STATE_READY);
+
+ /* Now wait for server death signal */
+ WaitServerState(SERVER, SERVER_STATE_DYING);
+
+ /* Cleanup */
+ SetServerState(SERVER, SERVER_STATE_DEAD);
+ }
+}
+
+/* --- Client Functions ------------------------------------------- */
+
+PRInt32 numRequests;
+PRInt32 numClients;
+PRMonitor *clientMonitor;
+
+void
+ClientThreadFunc(void *unused)
+{
+ PRNetAddr serverAddr;
+ PRFileDesc *clientSocket;
+ char *sendBuf;
+ char *recvBuf;
+ PRInt32 rv;
+ PRInt32 bytesNeeded;
+
+ sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
+ if (!sendBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+ recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
+ if (!recvBuf)
+ if (debug_mode) printf("\tClient could not malloc space!?\n");
+
+ memset(&serverAddr, 0, sizeof(PRNetAddr));
+ serverAddr.inet.family = PR_AF_INET;
+ serverAddr.inet.port = PR_htons(PORT);
+ serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+
+ while(numRequests > 0) {
+
+ if ( (numRequests % 10) == 0 )
+ if (debug_mode) printf(".");
+ if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
+
+ clientSocket = PR_NewTCPSocket();
+ if (!clientSocket) {
+ if (debug_mode) printf("Client error creating socket: OS error %d\n",
+ PR_GetOSError());
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connecting\n");
+
+ rv = PR_Connect(clientSocket,
+ &serverAddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (!clientSocket) {
+ if (debug_mode) printf("\tClient error connecting\n");
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient connected\n");
+
+ rv = PR_Send(clientSocket,
+ sendBuf,
+ _client_data,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != _client_data) {
+ if (debug_mode) printf("Client error sending data (%d)\n", rv);
+ PR_Close(clientSocket);
+ continue;
+ }
+
+ if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
+
+ bytesNeeded = _server_data;
+ while(bytesNeeded) {
+ rv = PR_Recv(clientSocket,
+ recvBuf,
+ bytesNeeded,
+ 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv <= 0) {
+ if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n",
+ rv, (_server_data - bytesNeeded), _server_data);
+ break;
+ }
+ if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
+ bytesNeeded -= rv;
+ }
+
+ PR_Close(clientSocket);
+
+ PR_AtomicDecrement(&numRequests);
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ --numClients;
+ PR_Notify(clientMonitor);
+ PR_ExitMonitor(clientMonitor);
+
+ PR_DELETE(sendBuf);
+ PR_DELETE(recvBuf);
+}
+
+void
+RunClients(void)
+{
+ PRInt32 index;
+
+ numRequests = _iterations;
+ numClients = _clients;
+ clientMonitor = PR_NewMonitor();
+
+ for (index=0; index<_clients; index++) {
+ PRThread *clientThread;
+
+
+ clientThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ClientThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ClientScope,
+ PR_UNJOINABLE_THREAD,
+ THREAD_STACKSIZE);
+
+ if (!clientThread) {
+ if (debug_mode) printf("\terror creating client thread %d\n", index);
+ } else
+ if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
+
+ }
+
+ PR_EnterMonitor(clientMonitor);
+ while(numClients)
+ PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(clientMonitor);
+}
+
+/* --- Main Function ---------------------------------------------- */
+
+static
+void do_work()
+{
+ PRThread *ServerThread;
+ PRInt32 state;
+
+ SetServerState(MAIN, SERVER_STATE_STARTUP);
+ ServerThread = PR_CreateThread(
+ PR_USER_THREAD,
+ ServerThreadFunc,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ ServerScope,
+ PR_JOINABLE_THREAD,
+ THREAD_STACKSIZE);
+ if (!ServerThread) {
+ if (debug_mode) printf("error creating main server thread\n");
+ return;
+ }
+
+ /* Wait for server to be ready */
+ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
+
+ if (!(state & SERVER_STATE_DEAD)) {
+ /* Run Test Clients */
+ RunClients();
+
+ /* Send death signal to server */
+ SetServerState(MAIN, SERVER_STATE_DYING);
+ }
+
+ PR_JoinThread(ServerThread);
+}
+
+static void do_workUU(void)
+{
+ ServerScope = PR_LOCAL_THREAD;
+ ClientScope = PR_LOCAL_THREAD;
+ do_work();
+}
+
+
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+
+ if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
+}
+
+
+main(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+ if (debug_mode) {
+ printf("Enter number of iterations: \n");
+ scanf("%d", &_iterations);
+ printf("Enter number of clients : \n");
+ scanf("%d", &_clients);
+ printf("Enter size of client data : \n");
+ scanf("%d", &_client_data);
+ printf("Enter size of server data : \n");
+ scanf("%d", &_server_data);
+ }
+ else {
+ _iterations = 7;
+ _clients = 7;
+ _client_data = 100;
+ _server_data = 100;
+ }
+
+ if (debug_mode) {
+ printf("\n\n%d iterations with %d client threads.\n",
+ _iterations, _clients);
+ printf("Sending %d bytes of client data and %d bytes of server data\n",
+ _client_data, _server_data);
+ }
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ PR_SetThreadRecycleMode(64);
+
+ ServerStateCVLock = PR_NewLock();
+ ServerStateCV = PR_NewCondVar(ServerStateCVLock);
+
+ Measure(do_workUU, "server loop user/user");
+
+ PR_Cleanup();
+
+ if(failed_already)
+ return 1;
+ else
+ return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/short_thread.c b/src/libs/xpcom18a4/nsprpub/pr/tests/short_thread.c
new file mode 100644
index 00000000..42a52d7c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/short_thread.c
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <stdio.h>
+#include "nspr.h"
+#include "plgetopt.h"
+
+/*
+ * Create a thread that exits right away; useful for testing race conditions in thread
+ * creation
+ */
+
+int _debug_on = 0;
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+static void housecleaning(void *cur_time);
+
+int main (int argc, char **argv)
+{
+ static PRIntervalTime thread_start_time;
+ static PRThread *housekeeping_tid = NULL;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (( housekeeping_tid =
+ PR_CreateThread (PR_USER_THREAD, housecleaning, (void*)&thread_start_time,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0))
+ == NULL ) {
+ fprintf(stderr,
+ "simple_test: Error - PR_CreateThread failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ exit( 1 );
+ }
+ PR_Cleanup();
+ return(0);
+}
+
+static void
+housecleaning (void *cur_time)
+{
+ DPRINTF(("Child Thread exiting\n"));
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sigpipe.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sigpipe.c
new file mode 100644
index 00000000..ecb9689c
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sigpipe.c
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ *************************************************************************
+ *
+ * Test: sigpipe.c
+ *
+ * Test the SIGPIPE handler in NSPR. This test applies to Unix only.
+ *
+ *************************************************************************
+ */
+
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+
+int main(void)
+{
+ /* This test applies to Unix and OS/2 (emx build). */
+ return 0;
+}
+
+#else /* XP_UNIX && OS/2 */
+
+#include "nspr.h"
+
+#ifdef XP_OS2
+#define INCL_DOSQUEUES
+#define INCL_DOSERRORS
+#include <os2.h>
+#endif
+
+#include <stdio.h>
+#ifdef XP_OS2_VACPP
+#define EPIPE EBADF /* IBM's write() doesn't return EPIPE */
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+static void Test(void *arg)
+{
+#ifdef XP_OS2
+ HFILE pipefd[2];
+#else
+ int pipefd[2];
+#endif
+ int rv;
+ char c = '\0';
+
+#ifdef XP_OS2
+ if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) {
+#else
+ if (pipe(pipefd) == -1) {
+#endif
+ fprintf(stderr, "cannot create pipe: %d\n", errno);
+ exit(1);
+ }
+ close(pipefd[0]);
+
+ rv = write(pipefd[1], &c, 1);
+ if (rv != -1) {
+ fprintf(stderr, "write to broken pipe should have failed with EPIPE but returned %d\n", rv);
+ exit(1);
+ }
+ if (errno != EPIPE) {
+ fprintf(stderr, "write to broken pipe failed but with wrong errno: %d\n", errno);
+ exit(1);
+ }
+ close(pipefd[1]);
+ printf("write to broken pipe failed with EPIPE, as expected\n");
+}
+
+int main(void)
+{
+ PRThread *thread;
+
+ /* This initializes NSPR. */
+ PR_SetError(0, 0);
+
+ thread = PR_CreateThread(PR_USER_THREAD, Test, NULL, PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (thread == NULL) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(thread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ Test(NULL);
+
+ printf("PASSED\n");
+ return 0;
+}
+
+#endif /* XP_UNIX */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sleep.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sleep.c
new file mode 100644
index 00000000..51847367
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sleep.c
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+
+#include <stdio.h>
+
+#ifndef XP_OS2
+#include <unistd.h>
+#endif
+#include <sys/time.h>
+
+#if defined(HAVE_SVID_GETTOD)
+#define GTOD(_a) gettimeofday(_a)
+#else
+#define GTOD(_a) gettimeofday((_a), NULL)
+#endif
+
+#if defined (XP_OS2_VACPP)
+#define INCL_DOSPROCESS
+#include <os2.h>
+#endif
+
+static PRIntn rv = 0;
+
+static void Other(void *unused)
+{
+ PRIntn didit = 0;
+ while (PR_SUCCESS == PR_Sleep(PR_MillisecondsToInterval(250)))
+ {
+ fprintf(stderr, ".");
+ didit += 1;
+ }
+ if (didit < 5) rv = 1;
+}
+
+PRIntn main ()
+{
+ PRUint32 elapsed;
+ PRThread *thread;
+ struct timeval timein, timeout;
+ PRInt32 onePercent = 3000000UL / 100UL;
+
+ fprintf (stderr, "First sleep will sleep 3 seconds.\n");
+ fprintf (stderr, " sleep 1 begin\n");
+ (void)GTOD(&timein);
+ sleep (3);
+ (void)GTOD(&timeout);
+ fprintf (stderr, " sleep 1 end\n");
+ elapsed = 1000000UL * (timeout.tv_sec - timein.tv_sec);
+ elapsed += (timeout.tv_usec - timein.tv_usec);
+ fprintf(stderr, "elapsed %u usecs\n", elapsed);
+ if (labs(elapsed - 3000000UL) > onePercent) rv = 1;
+
+ PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 100);
+ PR_STDIO_INIT();
+
+ fprintf (stderr, "Second sleep should do the same (does it?).\n");
+ fprintf (stderr, " sleep 2 begin\n");
+ (void)GTOD(&timein);
+ sleep (3);
+ (void)GTOD(&timeout);
+ fprintf (stderr, " sleep 2 end\n");
+ elapsed = 1000000UL * (timeout.tv_sec - timein.tv_sec);
+ elapsed += (timeout.tv_usec - timein.tv_usec);
+ fprintf(stderr, "elapsed %u usecs\n", elapsed);
+ if (labs(elapsed - 3000000UL) > onePercent) rv = 1;
+
+ fprintf (stderr, "What happens to other threads?\n");
+ fprintf (stderr, "You should see dots every quarter second.\n");
+ fprintf (stderr, "If you don't, you're probably running on classic NSPR.\n");
+ thread = PR_CreateThread(
+ PR_USER_THREAD, Other, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+ fprintf (stderr, " sleep 2 begin\n");
+ (void)GTOD(&timein);
+ sleep (3);
+ (void)GTOD(&timeout);
+ fprintf (stderr, " sleep 2 end\n");
+ PR_Interrupt(thread);
+ PR_JoinThread(thread);
+ elapsed = 1000000UL * (timeout.tv_sec - timein.tv_sec);
+ elapsed += (timeout.tv_usec - timein.tv_usec);
+ fprintf(stderr, "elapsed %u usecs\n", elapsed);
+ if (labs(elapsed - 3000000UL) > onePercent) rv = 1;
+ fprintf(stderr, "%s\n", (0 == rv) ? "PASSED" : "FAILED");
+ return rv;
+}
+
+#else /* defined(XP_UNIX) */
+
+PRIntn main()
+{
+ return 2;
+}
+
+#endif /* defined(XP_UNIX) */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/socket.c b/src/libs/xpcom18a4/nsprpub/pr/tests/socket.c
new file mode 100644
index 00000000..8e4a899b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/socket.c
@@ -0,0 +1,2354 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: socket.c
+**
+** Description: Test socket functionality.
+**
+** Modification History:
+*/
+#include "primpl.h"
+
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef XP_UNIX
+#include <sys/mman.h>
+#endif
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include <pthread.h>
+#endif
+
+#ifdef WIN32
+#include <process.h>
+#endif
+
+static int _debug_on = 0;
+static int test_cancelio = 0;
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "prsem.h"
+int fprintf(FILE *stream, const char *fmt, ...)
+{
+ PR_LogPrint(fmt);
+ return 0;
+}
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#else
+#include "obsolete/prsem.h"
+#endif
+
+#ifdef XP_PC
+#define mode_t int
+#endif
+
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+#ifdef XP_PC
+char *TEST_DIR = "prdir";
+char *SMALL_FILE_NAME = "prsmallf";
+char *LARGE_FILE_NAME = "prlargef";
+#else
+char *TEST_DIR = "/tmp/prsocket_test_dir";
+char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file";
+char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file";
+#endif
+#define SMALL_FILE_SIZE (3 * 1024) /* 3 KB */
+#define SMALL_FILE_OFFSET_1 (512)
+#define SMALL_FILE_LEN_1 (1 * 1024) /* 1 KB */
+#define SMALL_FILE_OFFSET_2 (75)
+#define SMALL_FILE_LEN_2 (758)
+#define SMALL_FILE_OFFSET_3 (1024)
+#define SMALL_FILE_LEN_3 (SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3)
+#define SMALL_FILE_HEADER_SIZE (64) /* 64 bytes */
+#define SMALL_FILE_TRAILER_SIZE (128) /* 128 bytes */
+
+#define LARGE_FILE_SIZE (3 * 1024 * 1024) /* 3 MB */
+#define LARGE_FILE_OFFSET_1 (0)
+#define LARGE_FILE_LEN_1 (2 * 1024 * 1024) /* 2 MB */
+#define LARGE_FILE_OFFSET_2 (64)
+#define LARGE_FILE_LEN_2 (1 * 1024 * 1024 + 75)
+#define LARGE_FILE_OFFSET_3 (2 * 1024 * 1024 - 128)
+#define LARGE_FILE_LEN_3 (LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3)
+#define LARGE_FILE_OFFSET_4 PR_GetPageSize()
+#define LARGE_FILE_LEN_4 769
+#define LARGE_FILE_HEADER_SIZE (512)
+#define LARGE_FILE_TRAILER_SIZE (64)
+
+#define BUF_DATA_SIZE (2 * 1024)
+#define TCP_MESG_SIZE 1024
+/*
+ * set UDP datagram size small enough that datagrams sent to a port on the
+ * local host will not be lost
+ */
+#define UDP_DGRAM_SIZE 128
+#define NUM_TCP_CLIENTS 5 /* for a listen queue depth of 5 */
+#define NUM_UDP_CLIENTS 10
+
+#ifndef XP_MAC
+#define NUM_TRANSMITFILE_CLIENTS 4
+#else
+/* Mac can't handle more than 2* (3Mb) allocations for large file size buffers */
+#define NUM_TRANSMITFILE_CLIENTS 2
+#endif
+
+#define NUM_TCP_CONNECTIONS_PER_CLIENT 5
+#define NUM_TCP_MESGS_PER_CONNECTION 10
+#define NUM_UDP_DATAGRAMS_PER_CLIENT 5
+#define TCP_SERVER_PORT 10000
+#define UDP_SERVER_PORT TCP_SERVER_PORT
+#define SERVER_MAX_BIND_COUNT 100
+
+static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
+static PRInt32 num_udp_clients = NUM_UDP_CLIENTS;
+static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS;
+static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
+static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
+static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
+static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT;
+static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE;
+
+static PRInt32 thread_count;
+PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET;
+
+/* an I/O layer that uses the emulated senfile method */
+static PRDescIdentity emuSendFileIdentity;
+static PRIOMethods emuSendFileMethods;
+
+int failed_already=0;
+typedef struct buffer {
+ char data[BUF_DATA_SIZE];
+} buffer;
+
+PRNetAddr tcp_server_addr, udp_server_addr;
+
+typedef struct Serve_Client_Param {
+ PRFileDesc *sockfd; /* socket to read from/write to */
+ PRInt32 datalen; /* bytes of data transfered in each read/write */
+} Serve_Client_Param;
+
+typedef struct Server_Param {
+ PRSemaphore *addr_sem; /* sem to post on, after setting up the address */
+ PRMonitor *exit_mon; /* monitor to signal on exit */
+ PRInt32 *exit_counter; /* counter to decrement, before exit */
+ PRInt32 datalen; /* bytes of data transfered in each read/write */
+} Server_Param;
+
+
+typedef struct Client_Param {
+ PRNetAddr server_addr;
+ PRMonitor *exit_mon; /* monitor to signal on exit */
+ PRInt32 *exit_counter; /* counter to decrement, before exit */
+ PRInt32 datalen;
+ PRInt32 udp_connect; /* if set clients connect udp sockets */
+} Client_Param;
+
+/* the sendfile method in emuSendFileMethods */
+static PRInt32 PR_CALLBACK
+emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd,
+ PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ return PR_EmulateSendFile(sd, sfd, flags, timeout);
+}
+
+/* the transmitfile method in emuSendFileMethods */
+static PRInt32 PR_CALLBACK
+emu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers,
+ PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
+{
+ PRSendFileData sfd;
+
+ sfd.fd = fd;
+ sfd.file_offset = 0;
+ sfd.file_nbytes = 0;
+ sfd.header = headers;
+ sfd.hlen = hlen;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+ return emu_SendFile(sd, &sfd, flags, timeout);
+}
+
+/*
+ * readn
+ * read data from sockfd into buf
+ */
+static PRInt32
+readn(PRFileDesc *sockfd, char *buf, int len)
+{
+ int rem;
+ int bytes;
+ int offset = 0;
+ int err;
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
+
+ if (test_cancelio)
+ timeout = PR_SecondsToInterval(2);
+
+ for (rem=len; rem; offset += bytes, rem -= bytes) {
+ DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
+ PR_GetCurrentThread(), rem));
+retry:
+ bytes = PR_Recv(sockfd, buf + offset, rem, 0,
+ timeout);
+ DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
+ PR_GetCurrentThread(), bytes));
+ if (bytes < 0) {
+#ifdef WINNT
+ printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()),
+ PR_GetOSError());
+ if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) {
+ if (PR_NT_CancelIo(sockfd) != PR_SUCCESS)
+ printf("PR_NT_CancelIO: error = %d\n",PR_GetError());
+ timeout = PR_INTERVAL_NO_TIMEOUT;
+ goto retry;
+ }
+#endif
+ return -1;
+ }
+ }
+ return len;
+}
+
+/*
+ * writen
+ * write data from buf to sockfd
+ */
+static PRInt32
+writen(PRFileDesc *sockfd, char *buf, int len)
+{
+ int rem;
+ int bytes;
+ int offset = 0;
+
+ for (rem=len; rem; offset += bytes, rem -= bytes) {
+ DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
+ PR_GetCurrentThread(), rem));
+ bytes = PR_Send(sockfd, buf + offset, rem, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
+ PR_GetCurrentThread(), bytes));
+ if (bytes <= 0)
+ return -1;
+ }
+ return len;
+}
+
+/*
+ * Serve_Client
+ * Thread, started by the server, for serving a client connection.
+ * Reads data from socket and writes it back, unmodified, and
+ * closes the socket
+ */
+static void PR_CALLBACK
+Serve_Client(void *arg)
+{
+ Serve_Client_Param *scp = (Serve_Client_Param *) arg;
+ PRFileDesc *sockfd;
+ buffer *in_buf;
+ PRInt32 bytes, j;
+
+ sockfd = scp->sockfd;
+ bytes = scp->datalen;
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
+ failed_already=1;
+ goto exit;
+ }
+
+
+ for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
+ /*
+ * Read data from client and send it back to the client unmodified
+ */
+ if (readn(sockfd, in_buf->data, bytes) < bytes) {
+ fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n");
+ failed_already=1;
+ goto exit;
+ }
+ /*
+ * shutdown reads, after the last read
+ */
+ if (j == num_tcp_mesgs_per_connection - 1)
+ if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
+ }
+ DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(),
+ (*((int *) in_buf->data))));
+ if (writen(sockfd, in_buf->data, bytes) < bytes) {
+ fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n");
+ failed_already=1;
+ goto exit;
+ }
+ }
+ /*
+ * shutdown reads and writes
+ */
+ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
+ failed_already=1;
+ }
+
+exit:
+ PR_Close(sockfd);
+ if (in_buf) {
+ PR_DELETE(in_buf);
+ }
+}
+
+PRThread* create_new_thread(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize, PRInt32 index)
+{
+PRInt32 native_thread = 0;
+
+ PR_ASSERT(state == PR_UNJOINABLE_THREAD);
+#if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32)
+ switch(index % 4) {
+ case 0:
+ scope = (PR_LOCAL_THREAD);
+ break;
+ case 1:
+ scope = (PR_GLOBAL_THREAD);
+ break;
+ case 2:
+ scope = (PR_GLOBAL_BOUND_THREAD);
+ break;
+ case 3:
+ native_thread = 1;
+ break;
+ default:
+ PR_ASSERT(!"Invalid scope");
+ break;
+ }
+ if (native_thread) {
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ pthread_t tid;
+ if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg))
+ return((PRThread *) tid);
+ else
+ return (NULL);
+#else
+ HANDLE thandle;
+ unsigned tid;
+
+ thandle = (HANDLE) _beginthreadex(
+ NULL,
+ stackSize,
+ (unsigned (__stdcall *)(void *))start,
+ arg,
+ 0,
+ &tid);
+ return((PRThread *) thandle);
+#endif
+ } else {
+ return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+ }
+#else
+ return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+#endif
+}
+
+/*
+ * TCP Server
+ * Server Thread
+ * Bind an address to a socket and listen for incoming connections
+ * Start a Serve_Client thread for each incoming connection.
+ */
+static void PR_CALLBACK
+TCP_Server(void *arg)
+{
+ PRThread *t;
+ Server_Param *sp = (Server_Param *) arg;
+ Serve_Client_Param *scp;
+ PRFileDesc *sockfd, *newsockfd;
+ PRNetAddr netaddr;
+ PRInt32 i;
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
+ goto exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+
+ if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT,
+ &netaddr) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
+ goto exit;
+ }
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
+ perror("PR_Bind");
+ failed_already=1;
+ goto exit;
+ }
+
+ if (PR_Listen(sockfd, 32) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
+ failed_already=1;
+ goto exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit;
+ }
+
+ DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
+ netaddr.inet.ip, netaddr.inet.port));
+ if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
+ PR_ntohs(PR_NetAddrInetPort(&netaddr)),
+ &tcp_server_addr) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
+ goto exit;
+ }
+ if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
+ PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
+ &tcp_server_addr.ipv6.ip);
+
+ /*
+ * Wake up parent thread because server address is bound and made
+ * available in the global variable 'tcp_server_addr'
+ */
+ PR_PostSem(sp->addr_sem);
+
+ for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) {
+ /* test both null and non-null 'addr' argument to PR_Accept */
+ PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
+
+ DPRINTF(("TCP_Server: Accepting connection\n"));
+ if ((newsockfd = PR_Accept(sockfd, addrp,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n");
+ goto exit;
+ }
+ DPRINTF(("TCP_Server: Accepted connection\n"));
+ scp = PR_NEW(Serve_Client_Param);
+ if (scp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ goto exit;
+ }
+
+ /*
+ * Start a Serve_Client thread for each incoming connection
+ */
+ scp->sockfd = newsockfd;
+ scp->datalen = sp->datalen;
+
+ t = create_new_thread(PR_USER_THREAD,
+ Serve_Client, (void *)scp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0, i);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ goto exit;
+ }
+ DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t));
+ }
+
+exit:
+ if (sockfd) {
+ PR_Close(sockfd);
+ }
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+
+ PR_EnterMonitor(sp->exit_mon);
+ --(*sp->exit_counter);
+ PR_Notify(sp->exit_mon);
+ PR_ExitMonitor(sp->exit_mon);
+ DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
+}
+
+/*
+ * UDP Server
+ * Server Thread
+ * Bind an address to a socket, read data from clients and send data
+ * back to clients
+ */
+static void PR_CALLBACK
+UDP_Server(void *arg)
+{
+ Server_Param *sp = (Server_Param *) arg;
+ PRFileDesc *sockfd;
+ buffer *in_buf;
+ PRNetAddr netaddr;
+ PRInt32 bytes, i, rv = 0;
+
+
+ bytes = sp->datalen;
+ /*
+ * Create a udp socket
+ */
+ if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n");
+ failed_already=1;
+ return;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT,
+ &netaddr) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
+ failed_already=1;
+ return;
+ }
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
+ perror("PR_Bind");
+ failed_already=1;
+ return;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
+ failed_already=1;
+ return;
+ }
+
+ DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
+ netaddr.inet.ip, netaddr.inet.port));
+ /*
+ * We can't use the IP address returned by PR_GetSockName in
+ * netaddr.inet.ip because netaddr.inet.ip is returned
+ * as 0 (= PR_INADDR_ANY).
+ */
+
+ if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
+ PR_ntohs(PR_NetAddrInetPort(&netaddr)),
+ &udp_server_addr) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
+ failed_already=1;
+ return;
+ }
+ if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
+ PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
+ &udp_server_addr.ipv6.ip);
+
+ /*
+ * Wake up parent thread because server address is bound and made
+ * available in the global variable 'udp_server_addr'
+ */
+ PR_PostSem(sp->addr_sem);
+
+ bytes = sp->datalen;
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
+ failed_already=1;
+ return;
+ }
+ /*
+ * Receive datagrams from clients and send them back, unmodified, to the
+ * clients
+ */
+ memset(&netaddr, 0 , sizeof(netaddr));
+ for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) {
+ DPRINTF(("UDP_Server: calling PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
+ netaddr.inet.ip, netaddr.inet.port, bytes, in_buf->data,
+ in_buf->data[0]));
+
+ rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
+ netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data,
+ in_buf->data[0]));
+ if (rv != bytes) {
+ return;
+ }
+ rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != bytes) {
+ return;
+ }
+ }
+
+ PR_DELETE(in_buf);
+ PR_Close(sockfd);
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+ PR_EnterMonitor(sp->exit_mon);
+ --(*sp->exit_counter);
+ PR_Notify(sp->exit_mon);
+ PR_ExitMonitor(sp->exit_mon);
+ DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread()));
+}
+
+/*
+ * TCP_Client
+ * Client Thread
+ * Connect to the server at the address specified in the argument.
+ * Fill in a buffer, write data to server, read it back and check
+ * for data corruption.
+ * Close the socket for server connection
+ */
+static void PR_CALLBACK
+TCP_Client(void *arg)
+{
+ Client_Param *cp = (Client_Param *) arg;
+ PRFileDesc *sockfd;
+ buffer *in_buf, *out_buf;
+ union PRNetAddr netaddr;
+ PRInt32 bytes, i, j;
+
+
+ bytes = cp->datalen;
+ out_buf = PR_NEW(buffer);
+ if (out_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
+ failed_already=1;
+ return;
+ }
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
+ failed_already=1;
+ return;
+ }
+ netaddr = cp->server_addr;
+
+ for (i = 0; i < num_tcp_connections_per_client; i++) {
+ if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) {
+ fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
+ failed_already=1;
+ return;
+ }
+ if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
+ fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ return;
+ }
+ for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
+ /*
+ * fill in random data
+ */
+ memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
+ /*
+ * write to server
+ */
+#ifdef WINNT
+ if (test_cancelio && (j == 0))
+ PR_Sleep(PR_SecondsToInterval(12));
+#endif
+ if (writen(sockfd, out_buf->data, bytes) < bytes) {
+ fprintf(stderr,"prsocket_test: ERROR - TCP_Client:writen\n");
+ failed_already=1;
+ return;
+ }
+ DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
+ PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
+ if (readn(sockfd, in_buf->data, bytes) < bytes) {
+ fprintf(stderr,"prsocket_test: ERROR - TCP_Client:readn\n");
+ failed_already=1;
+ return;
+ }
+ /*
+ * verify the data read
+ */
+ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
+ fprintf(stderr,"prsocket_test: ERROR - data corruption\n");
+ failed_already=1;
+ return;
+ }
+ }
+ /*
+ * shutdown reads and writes
+ */
+ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
+ failed_already=1;
+ }
+ PR_Close(sockfd);
+ }
+
+ PR_DELETE(out_buf);
+ PR_DELETE(in_buf);
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+
+ PR_EnterMonitor(cp->exit_mon);
+ --(*cp->exit_counter);
+ PR_Notify(cp->exit_mon);
+ PR_ExitMonitor(cp->exit_mon);
+ DPRINTF(("TCP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
+}
+
+/*
+ * UDP_Client
+ * Client Thread
+ * Create a socket and bind an address
+ * Communicate with the server at the address specified in the argument.
+ * Fill in a buffer, write data to server, read it back and check
+ * for data corruption.
+ * Close the socket
+ */
+static void PR_CALLBACK
+UDP_Client(void *arg)
+{
+ Client_Param *cp = (Client_Param *) arg;
+ PRFileDesc *sockfd;
+ buffer *in_buf, *out_buf;
+ union PRNetAddr netaddr;
+ PRInt32 bytes, i, rv;
+
+
+ bytes = cp->datalen;
+ out_buf = PR_NEW(buffer);
+ if (out_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
+ failed_already=1;
+ return;
+ }
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
+ failed_already=1;
+ return;
+ }
+ if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) {
+ fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n");
+ failed_already=1;
+ return;
+ }
+
+ /*
+ * bind an address for the client, let the system chose the port
+ * number
+ */
+ memset(&netaddr, 0 , sizeof(netaddr));
+ if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0,
+ &netaddr) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
+ failed_already=1;
+ return;
+ }
+ if (PR_Bind(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
+ perror("PR_Bind");
+ return;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
+ failed_already=1;
+ return;
+ }
+
+ DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
+ netaddr.inet.ip, netaddr.inet.port));
+
+ netaddr = cp->server_addr;
+
+ if (cp->udp_connect) {
+ if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
+ fprintf(stderr,"prsocket_test: PR_Connect failed\n");
+ failed_already=1;
+ return;
+ }
+ }
+
+ for (i = 0; i < num_udp_datagrams_per_client; i++) {
+ /*
+ * fill in random data
+ */
+ DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n",
+ PR_GetCurrentThread(), out_buf->data, bytes));
+ memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes);
+ /*
+ * write to server
+ */
+ if (cp->udp_connect)
+ rv = PR_Send(sockfd, out_buf->data, bytes, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ else
+ rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != bytes) {
+ return;
+ }
+ DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
+ PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
+ if (cp->udp_connect)
+ rv = PR_Recv(sockfd, in_buf->data, bytes, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ else
+ rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (rv != bytes) {
+ return;
+ }
+ DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n",
+ PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data))));
+ /*
+ * verify the data read
+ */
+ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
+ fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n");
+ failed_already=1;
+ return;
+ }
+ }
+ PR_Close(sockfd);
+
+ PR_DELETE(in_buf);
+ PR_DELETE(out_buf);
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+
+ PR_EnterMonitor(cp->exit_mon);
+ --(*cp->exit_counter);
+ PR_Notify(cp->exit_mon);
+ PR_ExitMonitor(cp->exit_mon);
+ PR_DELETE(cp);
+ DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
+}
+
+/*
+ * TCP_Socket_Client_Server_Test - concurrent server test
+ *
+ * One server and several clients are started
+ * Each client connects to the server and sends a chunk of data
+ * For each connection, server starts another thread to read the data
+ * from the client and send it back to the client, unmodified.
+ * Each client checks that data received from server is same as the
+ * data it sent to the server.
+ *
+ */
+
+static PRInt32
+TCP_Socket_Client_Server_Test(void)
+{
+ int i;
+ PRThread *t;
+ PRSemaphore *server_sem;
+ Server_Param *sparamp;
+ Client_Param *cparamp;
+ PRMonitor *mon2;
+ PRInt32 datalen;
+
+
+ datalen = tcp_mesg_size;
+ thread_count = 0;
+ /*
+ * start the server thread
+ */
+ sparamp = PR_NEW(Server_Param);
+ if (sparamp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ return -1;
+ }
+ server_sem = PR_NewSem(0);
+ if (server_sem == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
+ failed_already=1;
+ return -1;
+ }
+ mon2 = PR_NewMonitor();
+ if (mon2 == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
+ failed_already=1;
+ return -1;
+ }
+ PR_EnterMonitor(mon2);
+
+ sparamp->addr_sem = server_sem;
+ sparamp->exit_mon = mon2;
+ sparamp->exit_counter = &thread_count;
+ sparamp->datalen = datalen;
+ t = PR_CreateThread(PR_USER_THREAD,
+ TCP_Server, (void *)sparamp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ return -1;
+ }
+ DPRINTF(("Created TCP server = 0x%lx\n", t));
+ thread_count++;
+
+ /*
+ * wait till the server address is setup
+ */
+ PR_WaitSem(server_sem);
+
+ /*
+ * Now start a bunch of client threads
+ */
+
+ cparamp = PR_NEW(Client_Param);
+ if (cparamp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ return -1;
+ }
+ cparamp->server_addr = tcp_server_addr;
+ cparamp->exit_mon = mon2;
+ cparamp->exit_counter = &thread_count;
+ cparamp->datalen = datalen;
+ for (i = 0; i < num_tcp_clients; i++) {
+ t = create_new_thread(PR_USER_THREAD,
+ TCP_Client, (void *) cparamp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0, i);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ return -1;
+ }
+ DPRINTF(("Created TCP client = 0x%lx\n", t));
+ thread_count++;
+ }
+ /* Wait for server and client threads to exit */
+ while (thread_count) {
+ PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("TCP Server - thread_count = %d\n", thread_count));
+ }
+ PR_ExitMonitor(mon2);
+ printf("%30s","TCP_Socket_Client_Server_Test:");
+ printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
+ num_tcp_clients, num_tcp_connections_per_client);
+ printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
+ num_tcp_mesgs_per_connection, tcp_mesg_size);
+
+ return 0;
+}
+
+/*
+ * UDP_Socket_Client_Server_Test - iterative server test
+ *
+ * One server and several clients are started
+ * Each client connects to the server and sends a chunk of data
+ * For each connection, server starts another thread to read the data
+ * from the client and send it back to the client, unmodified.
+ * Each client checks that data received from server is same as the
+ * data it sent to the server.
+ *
+ */
+
+static PRInt32
+UDP_Socket_Client_Server_Test(void)
+{
+ int i;
+ PRThread *t;
+ PRSemaphore *server_sem;
+ Server_Param *sparamp;
+ Client_Param *cparamp;
+ PRMonitor *mon2;
+ PRInt32 datalen;
+ PRInt32 udp_connect = 1;
+
+
+ datalen = udp_datagram_size;
+ thread_count = 0;
+ /*
+ * start the server thread
+ */
+ sparamp = PR_NEW(Server_Param);
+ if (sparamp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ return -1;
+ }
+ server_sem = PR_NewSem(0);
+ if (server_sem == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
+ failed_already=1;
+ return -1;
+ }
+ mon2 = PR_NewMonitor();
+ if (mon2 == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
+ failed_already=1;
+ return -1;
+ }
+ PR_EnterMonitor(mon2);
+
+ sparamp->addr_sem = server_sem;
+ sparamp->exit_mon = mon2;
+ sparamp->exit_counter = &thread_count;
+ sparamp->datalen = datalen;
+ DPRINTF(("Creating UDP server"));
+ t = PR_CreateThread(PR_USER_THREAD,
+ UDP_Server, (void *)sparamp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ return -1;
+ }
+ thread_count++;
+
+ /*
+ * wait till the server address is setup
+ */
+ PR_WaitSem(server_sem);
+
+ /*
+ * Now start a bunch of client threads
+ */
+
+ for (i = 0; i < num_udp_clients; i++) {
+ cparamp = PR_NEW(Client_Param);
+ if (cparamp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ return -1;
+ }
+ cparamp->server_addr = udp_server_addr;
+ cparamp->exit_mon = mon2;
+ cparamp->exit_counter = &thread_count;
+ cparamp->datalen = datalen;
+ /*
+ * Cause every other client thread to connect udp sockets
+ */
+#ifndef XP_MAC
+ cparamp->udp_connect = udp_connect;
+#else
+ /* No support for UDP connects on Mac */
+ cparamp->udp_connect = 0;
+#endif
+ if (udp_connect)
+ udp_connect = 0;
+ else
+ udp_connect = 1;
+ DPRINTF(("Creating UDP client %d\n", i));
+ t = PR_CreateThread(PR_USER_THREAD,
+ UDP_Client, (void *) cparamp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ return -1;
+ }
+ thread_count++;
+ }
+ /* Wait for server and client threads to exit */
+ while (thread_count) {
+ PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("UDP Server - thread_count = %d\n", thread_count));
+ }
+ PR_ExitMonitor(mon2);
+ printf("%30s","UDP_Socket_Client_Server_Test: ");
+ printf("%2ld Server %2ld Clients\n",1l, num_udp_clients);
+ printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":",
+ num_udp_datagrams_per_client, udp_datagram_size);
+
+ return 0;
+}
+
+static PRFileDesc *small_file_fd, *large_file_fd;
+static void *small_file_addr, *small_file_header, *large_file_addr;
+static void *small_file_trailer, *large_file_header, *large_file_trailer;
+/*
+ * TransmitFile_Client
+ * Client Thread
+ */
+static void
+TransmitFile_Client(void *arg)
+{
+ PRFileDesc *sockfd;
+ union PRNetAddr netaddr;
+ char *small_buf, *large_buf;
+ Client_Param *cp = (Client_Param *) arg;
+ PRInt32 rlen;
+
+ small_buf = (char*)PR_Malloc(SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
+ SMALL_FILE_TRAILER_SIZE);
+ if (small_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
+ failed_already=1;
+ return;
+ }
+ large_buf = (char*)PR_Malloc(LARGE_FILE_SIZE + LARGE_FILE_HEADER_SIZE +
+ LARGE_FILE_TRAILER_SIZE);
+ if (large_buf == NULL) {
+ fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
+ failed_already=1;
+ return;
+ }
+ netaddr.inet.family = cp->server_addr.inet.family;
+ netaddr.inet.port = cp->server_addr.inet.port;
+ netaddr.inet.ip = cp->server_addr.inet.ip;
+
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
+ failed_already=1;
+ return;
+ }
+
+ if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
+ fprintf(stderr,"prsocket_test: PR_Connect failed\n");
+ failed_already=1;
+ return;
+ }
+ /*
+ * read the small file and verify the data
+ */
+ if (readn(sockfd, small_buf, SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)
+ != (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) {
+ fprintf(stderr,
+ "prsocket_test: TransmitFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
+ SMALL_FILE_SIZE) != 0) {
+ fprintf(stderr,
+ "prsocket_test: TransmitFile_Client ERROR - small file data corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * read the large file and verify the data
+ */
+ if (readn(sockfd, large_buf, LARGE_FILE_SIZE) != LARGE_FILE_SIZE) {
+ fprintf(stderr,
+ "prsocket_test: TransmitFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(large_file_addr, large_buf, LARGE_FILE_SIZE) != 0) {
+ fprintf(stderr,
+ "prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
+ failed_already=1;
+ }
+#endif
+
+
+ /*
+ * receive data from PR_SendFile
+ */
+ /*
+ * case 1: small file with header and trailer
+ */
+ rlen = SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
+ SMALL_FILE_TRAILER_SIZE;
+ if (readn(sockfd, small_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 1. ERROR - small file header corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
+ SMALL_FILE_SIZE) != 0) {
+ fprintf(stderr,
+ "SendFile 1. ERROR - small file data corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(small_file_trailer,
+ small_buf + SMALL_FILE_HEADER_SIZE + SMALL_FILE_SIZE,
+ SMALL_FILE_TRAILER_SIZE) != 0) {
+ fprintf(stderr,
+ "SendFile 1. ERROR - small file trailer corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 2: partial large file at zero offset, file with header and trailer
+ */
+ rlen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
+ LARGE_FILE_TRAILER_SIZE;
+ if (readn(sockfd, large_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 2. ERROR - large file header corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(large_file_addr, large_buf + LARGE_FILE_HEADER_SIZE,
+ LARGE_FILE_LEN_1) != 0) {
+ fprintf(stderr,
+ "SendFile 2. ERROR - large file data corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(large_file_trailer,
+ large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_1,
+ LARGE_FILE_TRAILER_SIZE) != 0) {
+ fprintf(stderr,
+ "SendFile 2. ERROR - large file trailer corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 3: partial small file at non-zero offset, with header
+ */
+ rlen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
+ if (readn(sockfd, small_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 3. ERROR - small file header corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_1,
+ small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_1) != 0) {
+ fprintf(stderr,
+ "SendFile 3. ERROR - small file data corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 4: partial small file at non-zero offset, with trailer
+ */
+ rlen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
+ if (readn(sockfd, small_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_2, small_buf,
+ SMALL_FILE_LEN_2) != 0) {
+ fprintf(stderr,
+ "SendFile 4. ERROR - small file data corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(small_file_trailer, small_buf + SMALL_FILE_LEN_2,
+ SMALL_FILE_TRAILER_SIZE) != 0) {
+ fprintf(stderr,
+ "SendFile 4. ERROR - small file trailer corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 5: partial large file at non-zero offset, file with header
+ */
+ rlen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
+ if (readn(sockfd, large_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 5. ERROR - large file header corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_2,
+ large_buf + LARGE_FILE_HEADER_SIZE,
+ LARGE_FILE_LEN_2) != 0) {
+ fprintf(stderr,
+ "SendFile 5. ERROR - large file data corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 6: partial small file at non-zero offset, with header
+ */
+ rlen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
+ if (readn(sockfd, small_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 6. ERROR - small file header corruption\n");
+ return;
+ }
+ if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_3,
+ small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_3) != 0) {
+#if 0
+ char *i, *j;
+ int k;
+
+ i = (char *) small_file_addr + SMALL_FILE_OFFSET_3;
+ j = small_buf + SMALL_FILE_HEADER_SIZE;
+ k = SMALL_FILE_LEN_3;
+ while (k-- > 0) {
+ if (*i++ != *j++)
+ printf("i = %d j = %d\n",
+ (int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)),
+ (int) (j - (small_buf + SMALL_FILE_HEADER_SIZE)));
+ }
+#endif
+ fprintf(stderr,
+ "SendFile 6. ERROR - small file data corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 7: partial large file at non-zero offset, with header
+ */
+ rlen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
+ if (readn(sockfd, large_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 7. ERROR - large file header corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_3,
+ large_buf + LARGE_FILE_HEADER_SIZE,
+ LARGE_FILE_LEN_3) != 0) {
+ fprintf(stderr,
+ "SendFile 7. ERROR - large file data corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ /*
+ * case 8: partial large file at non-zero, page-aligned offset, with
+ * header and trailer
+ */
+ rlen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
+ LARGE_FILE_TRAILER_SIZE;
+ if (readn(sockfd, large_buf, rlen) != rlen) {
+ fprintf(stderr,
+ "prsocket_test: SendFile_Client failed to receive file\n");
+ failed_already=1;
+ return;
+ }
+#ifdef XP_UNIX
+ if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
+ fprintf(stderr,
+ "SendFile 2. ERROR - large file header corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_4,
+ large_buf + LARGE_FILE_HEADER_SIZE,
+ LARGE_FILE_LEN_4) != 0) {
+ fprintf(stderr,
+ "SendFile 2. ERROR - large file data corruption\n");
+ failed_already=1;
+ return;
+ }
+ if (memcmp(large_file_trailer,
+ large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_4,
+ LARGE_FILE_TRAILER_SIZE) != 0) {
+ fprintf(stderr,
+ "SendFile 2. ERROR - large file trailer corruption\n");
+ failed_already=1;
+ return;
+ }
+#endif
+ PR_DELETE(small_buf);
+ PR_DELETE(large_buf);
+ PR_Close(sockfd);
+
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+
+ PR_EnterMonitor(cp->exit_mon);
+ --(*cp->exit_counter);
+ PR_Notify(cp->exit_mon);
+ PR_ExitMonitor(cp->exit_mon);
+ DPRINTF(("TransmitFile_Client [0x%lx] exiting\n", PR_GetCurrentThread()));
+}
+
+/*
+ * Serve_TransmitFile_Client
+ * Thread, started by the server, for serving a client connection.
+ * Trasmits a small file, with a header, and a large file, without
+ * a header
+ */
+static void
+Serve_TransmitFile_Client(void *arg)
+{
+ Serve_Client_Param *scp = (Serve_Client_Param *) arg;
+ PRFileDesc *sockfd;
+ PRInt32 bytes;
+ PRFileDesc *local_small_file_fd=NULL;
+ PRFileDesc *local_large_file_fd=NULL;
+ PRSendFileData sfd;
+ PRInt32 slen;
+
+ sockfd = scp->sockfd;
+ local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0);
+
+ if (local_small_file_fd == NULL) {
+ fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
+ SMALL_FILE_NAME);
+ failed_already=1;
+ goto done;
+ }
+ local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0);
+
+ if (local_large_file_fd == NULL) {
+ fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
+ LARGE_FILE_NAME);
+ failed_already=1;
+ goto done;
+ }
+ bytes = PR_TransmitFile(sockfd, local_small_file_fd, small_file_header,
+ SMALL_FILE_HEADER_SIZE, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytes != (SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE)) {
+ fprintf(stderr,
+ "prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ bytes = PR_TransmitFile(sockfd, local_large_file_fd, NULL, 0,
+ PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT);
+ if (bytes != LARGE_FILE_SIZE) {
+ fprintf(stderr,
+ "prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+
+ /*
+ * PR_SendFile test cases
+ */
+
+ /*
+ * case 1: small file with header and trailer
+ */
+ sfd.fd = local_small_file_fd;
+ sfd.file_offset = 0;
+ sfd.file_nbytes = 0;
+ sfd.header = small_file_header;
+ sfd.hlen = SMALL_FILE_HEADER_SIZE;
+ sfd.trailer = small_file_trailer;
+ sfd.tlen = SMALL_FILE_TRAILER_SIZE;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE +
+ SMALL_FILE_TRAILER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 1. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+
+ /*
+ * case 2: partial large file at zero offset, file with header and trailer
+ */
+ sfd.fd = local_large_file_fd;
+ sfd.file_offset = 0;
+ sfd.file_nbytes = LARGE_FILE_LEN_1;
+ sfd.header = large_file_header;
+ sfd.hlen = LARGE_FILE_HEADER_SIZE;
+ sfd.trailer = large_file_trailer;
+ sfd.tlen = LARGE_FILE_TRAILER_SIZE;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
+ LARGE_FILE_TRAILER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ /*
+ * case 3: partial small file at non-zero offset, with header
+ */
+ sfd.fd = local_small_file_fd;
+ sfd.file_offset = SMALL_FILE_OFFSET_1;
+ sfd.file_nbytes = SMALL_FILE_LEN_1;
+ sfd.header = small_file_header;
+ sfd.hlen = SMALL_FILE_HEADER_SIZE;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ /*
+ * case 4: partial small file at non-zero offset, with trailer
+ */
+ sfd.fd = local_small_file_fd;
+ sfd.file_offset = SMALL_FILE_OFFSET_2;
+ sfd.file_nbytes = SMALL_FILE_LEN_2;
+ sfd.header = NULL;
+ sfd.hlen = 0;
+ sfd.trailer = small_file_trailer;
+ sfd.tlen = SMALL_FILE_TRAILER_SIZE;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ /*
+ * case 5: partial large file at non-zero offset, file with header
+ */
+ sfd.fd = local_large_file_fd;
+ sfd.file_offset = LARGE_FILE_OFFSET_2;
+ sfd.file_nbytes = LARGE_FILE_LEN_2;
+ sfd.header = large_file_header;
+ sfd.hlen = LARGE_FILE_HEADER_SIZE;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 5. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ /*
+ * case 6: partial small file from non-zero offset till end of file, with header
+ */
+ sfd.fd = local_small_file_fd;
+ sfd.file_offset = SMALL_FILE_OFFSET_3;
+ sfd.file_nbytes = 0; /* data from offset to end-of-file */
+ sfd.header = small_file_header;
+ sfd.hlen = SMALL_FILE_HEADER_SIZE;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 6. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ /*
+ * case 7: partial large file at non-zero offset till end-of-file, with header
+ */
+ sfd.fd = local_large_file_fd;
+ sfd.file_offset = LARGE_FILE_OFFSET_3;
+ sfd.file_nbytes = 0; /* data until end-of-file */
+ sfd.header = large_file_header;
+ sfd.hlen = LARGE_FILE_HEADER_SIZE;
+ sfd.trailer = NULL;
+ sfd.tlen = 0;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 7. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+ /*
+ * case 8: partial large file at non-zero page-aligned offset,
+ * with header and trailer
+ */
+ sfd.fd = local_large_file_fd;
+ sfd.file_offset = LARGE_FILE_OFFSET_4;
+ sfd.file_nbytes = LARGE_FILE_LEN_4;
+ sfd.header = large_file_header;
+ sfd.hlen = LARGE_FILE_HEADER_SIZE;
+ sfd.trailer = large_file_trailer;
+ sfd.tlen = LARGE_FILE_TRAILER_SIZE;
+ bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_CLOSE_SOCKET,
+ PR_INTERVAL_NO_TIMEOUT);
+ slen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
+ LARGE_FILE_TRAILER_SIZE;
+ if (bytes != slen) {
+ fprintf(stderr,
+ "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
+ slen, bytes);
+ fprintf(stderr,
+ "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+done:
+ if (local_small_file_fd != NULL)
+ PR_Close(local_small_file_fd);
+ if (local_large_file_fd != NULL)
+ PR_Close(local_large_file_fd);
+}
+
+/*
+ * TransmitFile Server
+ * Server Thread
+ * Bind an address to a socket and listen for incoming connections
+ * Create worker threads to service clients
+ */
+static void
+TransmitFile_Server(void *arg)
+{
+ PRThread **t = NULL; /* an array of PRThread pointers */
+ Server_Param *sp = (Server_Param *) arg;
+ Serve_Client_Param *scp;
+ PRFileDesc *sockfd = NULL, *newsockfd;
+ PRNetAddr netaddr;
+ PRInt32 i;
+
+ t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *));
+ if (t == NULL) {
+ fprintf(stderr, "prsocket_test: run out of memory\n");
+ failed_already=1;
+ goto exit;
+ }
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) {
+ fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
+ failed_already=1;
+ goto exit;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
+ failed_already=1;
+ perror("PR_Bind");
+ goto exit;
+ }
+
+ if (PR_Listen(sockfd, 32) < 0) {
+ fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
+ failed_already=1;
+ goto exit;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,
+ "prsocket_test: ERROR - PR_GetSockName failed\n");
+ failed_already=1;
+ goto exit;
+ }
+
+ DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
+ netaddr.inet.ip, netaddr.inet.port));
+ tcp_server_addr.inet.family = netaddr.inet.family;
+ tcp_server_addr.inet.port = netaddr.inet.port;
+ tcp_server_addr.inet.ip = netaddr.inet.ip;
+
+ /*
+ * Wake up parent thread because server address is bound and made
+ * available in the global variable 'tcp_server_addr'
+ */
+ PR_PostSem(sp->addr_sem);
+
+ for (i = 0; i < num_transmitfile_clients ; i++) {
+ /* test both null and non-null 'addr' argument to PR_Accept */
+ PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
+
+ if ((newsockfd = PR_Accept(sockfd, addrp,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr,
+ "prsocket_test: ERROR - PR_Accept failed\n");
+ failed_already=1;
+ goto exit;
+ }
+ /* test both regular and emulated PR_SendFile */
+ if (i%2) {
+ PRFileDesc *layer = PR_CreateIOLayerStub(
+ emuSendFileIdentity, &emuSendFileMethods);
+ if (layer == NULL) {
+ fprintf(stderr,
+ "prsocket_test: ERROR - PR_CreateIOLayerStub failed\n");
+ failed_already=1;
+ goto exit;
+ }
+ if (PR_PushIOLayer(newsockfd, PR_TOP_IO_LAYER, layer)
+ == PR_FAILURE) {
+ fprintf(stderr,
+ "prsocket_test: ERROR - PR_PushIOLayer failed\n");
+ failed_already=1;
+ goto exit;
+ }
+ }
+ scp = PR_NEW(Serve_Client_Param);
+ if (scp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ goto exit;
+ }
+
+ /*
+ * Start a Serve_Client thread for each incoming connection
+ */
+ scp->sockfd = newsockfd;
+ scp->datalen = sp->datalen;
+
+ t[i] = PR_CreateThread(PR_USER_THREAD,
+ Serve_TransmitFile_Client, (void *)scp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (t[i] == NULL) {
+ fprintf(stderr,
+ "prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ goto exit;
+ }
+ DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t));
+ }
+
+ /*
+ * Wait for all the worker threads to end, so that we know
+ * they are no longer using the small and large file fd's.
+ */
+
+ for (i = 0; i < num_transmitfile_clients; i++) {
+ PR_JoinThread(t[i]);
+ }
+
+exit:
+ if (t) {
+ PR_DELETE(t);
+ }
+ if (sockfd) {
+ PR_Close(sockfd);
+ }
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+
+ PR_EnterMonitor(sp->exit_mon);
+ --(*sp->exit_counter);
+ PR_Notify(sp->exit_mon);
+ PR_ExitMonitor(sp->exit_mon);
+ DPRINTF(("TransmitFile_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
+}
+
+/*
+ * Socket_Misc_Test - test miscellaneous functions
+ *
+ */
+static PRInt32
+Socket_Misc_Test(void)
+{
+ PRIntn i, rv = 0, bytes, count, len;
+ PRThread *t;
+ PRSemaphore *server_sem;
+ Server_Param *sparamp;
+ Client_Param *cparamp;
+ PRMonitor *mon2;
+ PRInt32 datalen;
+
+ /*
+ * We deliberately pick a buffer size that is not a nice multiple
+ * of 1024.
+ */
+#define TRANSMITFILE_BUF_SIZE (4 * 1024 - 11)
+
+ typedef struct {
+ char data[TRANSMITFILE_BUF_SIZE];
+ } file_buf;
+ file_buf *buf = NULL;
+
+ /*
+ * create file(s) to be transmitted
+ */
+ if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
+ printf("prsocket_test failed to create dir %s\n",TEST_DIR);
+ failed_already=1;
+ return -1;
+ }
+
+ small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777);
+
+ if (small_file_fd == NULL) {
+ fprintf(stderr,"prsocket_test failed to create/open file %s\n",
+ SMALL_FILE_NAME);
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ buf = PR_NEW(file_buf);
+ if (buf == NULL) {
+ fprintf(stderr,"prsocket_test failed to allocate buffer\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ /*
+ * fill in random data
+ */
+ for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
+ buf->data[i] = i;
+ }
+ count = 0;
+ do {
+ len = (SMALL_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ?
+ TRANSMITFILE_BUF_SIZE : (SMALL_FILE_SIZE - count);
+ bytes = PR_Write(small_file_fd, buf->data, len);
+ if (bytes <= 0) {
+ fprintf(stderr,
+ "prsocket_test failed to write to file %s\n",
+ SMALL_FILE_NAME);
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ count += bytes;
+ } while (count < SMALL_FILE_SIZE);
+#ifdef XP_UNIX
+ /*
+ * map the small file; used in checking for data corruption
+ */
+ small_file_addr = mmap(0, SMALL_FILE_SIZE, PROT_READ,
+ MAP_SHARED, small_file_fd->secret->md.osfd, 0);
+ if (small_file_addr == (void *) -1) {
+ fprintf(stderr,"prsocket_test failed to mmap file %s\n",
+ SMALL_FILE_NAME);
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+#endif
+ /*
+ * header for small file
+ */
+ small_file_header = PR_MALLOC(SMALL_FILE_HEADER_SIZE);
+ if (small_file_header == NULL) {
+ fprintf(stderr,"prsocket_test failed to malloc header file\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ memset(small_file_header, (int) PR_IntervalNow(),
+ SMALL_FILE_HEADER_SIZE);
+ /*
+ * trailer for small file
+ */
+ small_file_trailer = PR_MALLOC(SMALL_FILE_TRAILER_SIZE);
+ if (small_file_trailer == NULL) {
+ fprintf(stderr,"prsocket_test failed to malloc header trailer\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ memset(small_file_trailer, (int) PR_IntervalNow(),
+ SMALL_FILE_TRAILER_SIZE);
+ /*
+ * setup large file
+ */
+ large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777);
+
+ if (large_file_fd == NULL) {
+ fprintf(stderr,"prsocket_test failed to create/open file %s\n",
+ LARGE_FILE_NAME);
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ /*
+ * fill in random data
+ */
+ for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) {
+ buf->data[i] = i;
+ }
+ count = 0;
+ do {
+ len = (LARGE_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ?
+ TRANSMITFILE_BUF_SIZE : (LARGE_FILE_SIZE - count);
+ bytes = PR_Write(large_file_fd, buf->data, len);
+ if (bytes <= 0) {
+ fprintf(stderr,
+ "prsocket_test failed to write to file %s: (%ld, %ld)\n",
+ LARGE_FILE_NAME,
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ count += bytes;
+ } while (count < LARGE_FILE_SIZE);
+#ifdef XP_UNIX
+ /*
+ * map the large file; used in checking for data corruption
+ */
+ large_file_addr = mmap(0, LARGE_FILE_SIZE, PROT_READ,
+ MAP_SHARED, large_file_fd->secret->md.osfd, 0);
+ if (large_file_addr == (void *) -1) {
+ fprintf(stderr,"prsocket_test failed to mmap file %s\n",
+ LARGE_FILE_NAME);
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+#endif
+ /*
+ * header for large file
+ */
+ large_file_header = PR_MALLOC(LARGE_FILE_HEADER_SIZE);
+ if (large_file_header == NULL) {
+ fprintf(stderr,"prsocket_test failed to malloc header file\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ memset(large_file_header, (int) PR_IntervalNow(),
+ LARGE_FILE_HEADER_SIZE);
+ /*
+ * trailer for large file
+ */
+ large_file_trailer = PR_MALLOC(LARGE_FILE_TRAILER_SIZE);
+ if (large_file_trailer == NULL) {
+ fprintf(stderr,"prsocket_test failed to malloc header trailer\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ memset(large_file_trailer, (int) PR_IntervalNow(),
+ LARGE_FILE_TRAILER_SIZE);
+
+ datalen = tcp_mesg_size;
+ thread_count = 0;
+ /*
+ * start the server thread
+ */
+ sparamp = PR_NEW(Server_Param);
+ if (sparamp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ server_sem = PR_NewSem(0);
+ if (server_sem == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ mon2 = PR_NewMonitor();
+ if (mon2 == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ PR_EnterMonitor(mon2);
+
+ sparamp->addr_sem = server_sem;
+ sparamp->exit_mon = mon2;
+ sparamp->exit_counter = &thread_count;
+ sparamp->datalen = datalen;
+ t = PR_CreateThread(PR_USER_THREAD,
+ TransmitFile_Server, (void *)sparamp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ DPRINTF(("Created TCP server = 0x%x\n", t));
+ thread_count++;
+
+ /*
+ * wait till the server address is setup
+ */
+ PR_WaitSem(server_sem);
+
+ /*
+ * Now start a bunch of client threads
+ */
+
+ cparamp = PR_NEW(Client_Param);
+ if (cparamp == NULL) {
+ fprintf(stderr,"prsocket_test: PR_NEW failed\n");
+ failed_already=1;
+ rv = -1;
+ goto done;
+ }
+ cparamp->server_addr = tcp_server_addr;
+ cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ cparamp->exit_mon = mon2;
+ cparamp->exit_counter = &thread_count;
+ cparamp->datalen = datalen;
+ for (i = 0; i < num_transmitfile_clients; i++) {
+ t = create_new_thread(PR_USER_THREAD,
+ TransmitFile_Client, (void *) cparamp,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0, i);
+ if (t == NULL) {
+ fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
+ rv = -1;
+ failed_already=1;
+ goto done;
+ }
+ DPRINTF(("Created TransmitFile client = 0x%lx\n", t));
+ thread_count++;
+ }
+ /* Wait for server and client threads to exit */
+ while (thread_count) {
+ PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("Socket_Misc_Test - thread_count = %d\n", thread_count));
+ }
+ PR_ExitMonitor(mon2);
+done:
+ if (buf) {
+ PR_DELETE(buf);
+ }
+#ifdef XP_UNIX
+ munmap((char*)small_file_addr, SMALL_FILE_SIZE);
+ munmap((char*)large_file_addr, LARGE_FILE_SIZE);
+#endif
+ PR_Close(small_file_fd);
+ PR_Close(large_file_fd);
+ if ((PR_Delete(SMALL_FILE_NAME)) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: failed to unlink file %s\n",
+ SMALL_FILE_NAME);
+ failed_already=1;
+ }
+ if ((PR_Delete(LARGE_FILE_NAME)) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test: failed to unlink file %s\n",
+ LARGE_FILE_NAME);
+ failed_already=1;
+ }
+ if ((PR_RmDir(TEST_DIR)) == PR_FAILURE) {
+ fprintf(stderr,"prsocket_test failed to rmdir %s: (%ld, %ld)\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ }
+
+ printf("%-29s%s","Socket_Misc_Test",":");
+ printf("%2d Server %2d Clients\n",1, num_transmitfile_clients);
+ printf("%30s Sizes of Transmitted Files - %4d KB, %2d MB \n",":",
+ SMALL_FILE_SIZE/1024, LARGE_FILE_SIZE/(1024 * 1024));
+
+
+ return rv;
+}
+/************************************************************************/
+
+/*
+ * Test Socket NSPR APIs
+ */
+
+int
+main(int argc, char **argv)
+{
+ /*
+ * -d debug mode
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("socket.log");
+#endif
+ PR_SetConcurrency(4);
+
+ emuSendFileIdentity = PR_GetUniqueIdentity("Emulated SendFile");
+ emuSendFileMethods = *PR_GetDefaultIOMethods();
+ emuSendFileMethods.transmitfile = emu_TransmitFile;
+ emuSendFileMethods.sendfile = emu_SendFile;
+
+ /*
+ * run client-server test with TCP, Ipv4-Ipv4
+ */
+ printf("TCP Client/Server Test - IPv4/Ipv4\n");
+ if (TCP_Socket_Client_Server_Test() < 0) {
+ printf("TCP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("TCP_Socket_Client_Server_Test Passed\n");
+ /*
+ * client-server test, Ipv6-Ipv4
+ */
+ client_domain = PR_AF_INET6;
+ printf("TCP Client/Server Test - IPv6/Ipv4\n");
+ if (TCP_Socket_Client_Server_Test() < 0) {
+ printf("TCP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("TCP_Socket_Client_Server_Test Passed\n");
+ /*
+ * client-server test, Ipv4-Ipv6
+ */
+ client_domain = PR_AF_INET;
+ server_domain = PR_AF_INET6;
+ printf("TCP Client/Server Test - IPv4/Ipv6\n");
+ if (TCP_Socket_Client_Server_Test() < 0) {
+ printf("TCP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("TCP_Socket_Client_Server_Test Passed\n");
+ /*
+ * client-server test, Ipv6-Ipv6
+ */
+ client_domain = PR_AF_INET6;
+ server_domain = PR_AF_INET6;
+ printf("TCP Client/Server Test - IPv6/Ipv6\n");
+ if (TCP_Socket_Client_Server_Test() < 0) {
+ printf("TCP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("TCP_Socket_Client_Server_Test Passed\n");
+ test_cancelio = 0;
+ /*
+ * run client-server test with UDP, IPv4/IPv4
+ */
+ printf("UDP Client/Server Test - IPv4/Ipv4\n");
+ client_domain = PR_AF_INET;
+ server_domain = PR_AF_INET;
+ if (UDP_Socket_Client_Server_Test() < 0) {
+ printf("UDP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("UDP_Socket_Client_Server_Test Passed\n");
+ /*
+ * run client-server test with UDP, IPv6/IPv4
+ */
+ printf("UDP Client/Server Test - IPv6/Ipv4\n");
+ client_domain = PR_AF_INET6;
+ server_domain = PR_AF_INET;
+ if (UDP_Socket_Client_Server_Test() < 0) {
+ printf("UDP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("UDP_Socket_Client_Server_Test Passed\n");
+ /*
+ * run client-server test with UDP,IPv4-IPv6
+ */
+ printf("UDP Client/Server Test - IPv4/Ipv6\n");
+ client_domain = PR_AF_INET;
+ server_domain = PR_AF_INET6;
+ if (UDP_Socket_Client_Server_Test() < 0) {
+ printf("UDP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("UDP_Socket_Client_Server_Test Passed\n");
+ /*
+ * run client-server test with UDP,IPv6-IPv6
+ */
+ printf("UDP Client/Server Test - IPv6/Ipv6\n");
+ client_domain = PR_AF_INET6;
+ server_domain = PR_AF_INET6;
+ if (UDP_Socket_Client_Server_Test() < 0) {
+ printf("UDP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("UDP_Socket_Client_Server_Test Passed\n");
+ /*
+ * Misc socket tests - including transmitfile, etc.
+ */
+
+#if !defined(WIN16)
+ /*
+** The 'transmit file' test does not run because
+** transmit file is not implemented in NSPR yet.
+**
+*/
+ if (Socket_Misc_Test() < 0) {
+ printf("Socket_Misc_Test failed\n");
+ failed_already=1;
+ goto done;
+ } else
+ printf("Socket_Misc_Test passed\n");
+
+ /*
+ * run client-server test with TCP again to test
+ * recycling used sockets from PR_TransmitFile().
+ */
+ if (TCP_Socket_Client_Server_Test() < 0) {
+ printf("TCP_Socket_Client_Server_Test failed\n");
+ goto done;
+ } else
+ printf("TCP_Socket_Client_Server_Test Passed\n");
+#endif
+
+done:
+ PR_Cleanup();
+ if (failed_already) return 1;
+ else return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sockopt.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sockopt.c
new file mode 100644
index 00000000..905e2387
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sockopt.c
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "prio.h"
+#include "prinit.h"
+#include "prprf.h"
+#ifdef XP_MAC
+#include "probslet.h"
+#else
+#include "obsolete/probslet.h"
+#endif
+
+#include "plerror.h"
+
+static PRFileDesc *err = NULL;
+static PRBool failed = PR_FALSE;
+
+#ifndef XP_MAC
+static void Failed(const char *msg1, const char *msg2)
+{
+ if (NULL != msg1) PR_fprintf(err, "%s ", msg1);
+ PL_FPrintError(err, msg2);
+ failed = PR_TRUE;
+} /* Failed */
+
+#else
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+static void Failed(const char *msg1, const char *msg2)
+{
+ if (NULL != msg1) printf("%s ", msg1);
+ printf (msg2);
+ failed |= PR_TRUE;
+} /* Failed */
+
+#endif
+
+static PRSockOption Incr(PRSockOption *option)
+{
+ PRIntn val = ((PRIntn)*option) + 1;
+ *option = (PRSockOption)val;
+ return (PRSockOption)val;
+} /* Incr */
+
+PRIntn main(PRIntn argc, char *argv)
+{
+ PRStatus rv;
+ PRFileDesc *udp = PR_NewUDPSocket();
+ PRFileDesc *tcp = PR_NewTCPSocket();
+ const char *tag[] =
+ {
+ "PR_SockOpt_Nonblocking", /* nonblocking io */
+ "PR_SockOpt_Linger", /* linger on close if data present */
+ "PR_SockOpt_Reuseaddr", /* allow local address reuse */
+ "PR_SockOpt_Keepalive", /* keep connections alive */
+ "PR_SockOpt_RecvBufferSize", /* send buffer size */
+ "PR_SockOpt_SendBufferSize", /* receive buffer size */
+
+ "PR_SockOpt_IpTimeToLive", /* time to live */
+ "PR_SockOpt_IpTypeOfService", /* type of service and precedence */
+
+ "PR_SockOpt_AddMember", /* add an IP group membership */
+ "PR_SockOpt_DropMember", /* drop an IP group membership */
+ "PR_SockOpt_McastInterface", /* multicast interface address */
+ "PR_SockOpt_McastTimeToLive", /* multicast timetolive */
+ "PR_SockOpt_McastLoopback", /* multicast loopback */
+
+ "PR_SockOpt_NoDelay", /* don't delay send to coalesce packets */
+ "PR_SockOpt_MaxSegment", /* maximum segment size */
+ "PR_SockOpt_Broadcast", /* Enable broadcast */
+ "PR_SockOpt_Last"
+ };
+
+ err = PR_GetSpecialFD(PR_StandardError);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("sockopt.log");
+#endif
+
+ if (NULL == udp) Failed("PR_NewUDPSocket()", NULL);
+ else if (NULL == tcp) Failed("PR_NewTCPSocket()", NULL);
+ else
+ {
+ PRSockOption option;
+ PRUint32 segment = 1024;
+ PRNetAddr addr;
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr);
+ if (PR_FAILURE == rv) Failed("PR_InitializeNetAddr()", NULL);
+ rv = PR_Bind(udp, &addr);
+ if (PR_FAILURE == rv) Failed("PR_Bind()", NULL);
+ for(option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option))
+ {
+ PRSocketOptionData data;
+ PRFileDesc *fd = tcp;
+ data.option = option;
+ switch (option)
+ {
+ case PR_SockOpt_Nonblocking:
+ data.value.non_blocking = PR_TRUE;
+ break;
+ case PR_SockOpt_Linger:
+ data.value.linger.polarity = PR_TRUE;
+ data.value.linger.linger = PR_SecondsToInterval(2);
+ break;
+ case PR_SockOpt_Reuseaddr:
+ data.value.reuse_addr = PR_TRUE;
+ break;
+ case PR_SockOpt_Keepalive:
+ data.value.keep_alive = PR_TRUE;
+ break;
+ case PR_SockOpt_RecvBufferSize:
+ data.value.recv_buffer_size = segment;
+ break;
+ case PR_SockOpt_SendBufferSize:
+ data.value.send_buffer_size = segment;
+ break;
+ case PR_SockOpt_IpTimeToLive:
+ data.value.ip_ttl = 64;
+ break;
+ case PR_SockOpt_IpTypeOfService:
+ data.value.tos = 0;
+ break;
+ case PR_SockOpt_McastTimeToLive:
+ fd = udp;
+ data.value.mcast_ttl = 4;
+ break;
+ case PR_SockOpt_McastLoopback:
+ fd = udp;
+ data.value.mcast_loopback = PR_TRUE;
+ break;
+ case PR_SockOpt_NoDelay:
+ data.value.no_delay = PR_TRUE;
+ break;
+#ifndef WIN32
+ case PR_SockOpt_MaxSegment:
+ data.value.max_segment = segment;
+ break;
+#endif
+ case PR_SockOpt_Broadcast:
+ fd = udp;
+ data.value.broadcast = PR_TRUE;
+ break;
+ default: continue;
+ }
+
+ /*
+ * TCP_MAXSEG can only be read, not set
+ */
+ if (option != PR_SockOpt_MaxSegment) {
+#ifdef WIN32
+ if (option != PR_SockOpt_McastLoopback)
+#endif
+ {
+ rv = PR_SetSocketOption(fd, &data);
+ if (PR_FAILURE == rv)
+ Failed("PR_SetSocketOption()", tag[option]);
+ }
+ }
+
+ rv = PR_GetSocketOption(fd, &data);
+ if (PR_FAILURE == rv) Failed("PR_GetSocketOption()", tag[option]);
+ }
+ PR_Close(udp);
+ PR_Close(tcp);
+ }
+#ifndef XP_MAC
+ PR_fprintf(err, "%s\n", (failed) ? "FAILED" : "PASSED");
+#else
+ printf("%s\n", (failed) ? "FAILED" : "PASSED");
+#endif
+ return (failed) ? 1 : 0;
+} /* main */
+
+/* sockopt.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sockping.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sockping.c
new file mode 100644
index 00000000..09365138
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sockping.c
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: sockping.c
+ *
+ * Description:
+ * This test runs in conjunction with the sockpong test.
+ * This test creates a socket pair and passes one socket
+ * to the sockpong test. Then this test writes "ping" to
+ * to the sockpong test and the sockpong test writes "pong"
+ * back. To run this pair of tests, just invoke sockping.
+ *
+ * Tested areas: process creation, socket pairs, file
+ * descriptor inheritance.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+#include "prproces.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+static char *child_argv[] = { "sockpong", NULL };
+
+int main()
+{
+ PRFileDesc *sock[2];
+ PRStatus status;
+ PRProcess *process;
+ PRProcessAttr *attr;
+ char buf[1024];
+ PRInt32 nBytes;
+ PRInt32 exitCode;
+ int idx;
+
+ status = PR_NewTCPSocketPair(sock);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_NewTCPSocketPair failed\n");
+ exit(1);
+ }
+
+ status = PR_SetFDInheritable(sock[0], PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ status = PR_SetFDInheritable(sock[1], PR_TRUE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+
+ attr = PR_NewProcessAttr();
+ if (attr == NULL) {
+ fprintf(stderr, "PR_NewProcessAttr failed\n");
+ exit(1);
+ }
+
+ status = PR_ProcessAttrSetInheritableFD(attr, sock[1], "SOCKET");
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n");
+ exit(1);
+ }
+
+ process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr);
+ if (process == NULL) {
+ fprintf(stderr, "PR_CreateProcess failed\n");
+ exit(1);
+ }
+ PR_DestroyProcessAttr(attr);
+ status = PR_Close(sock[1]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ strcpy(buf, "ping");
+ printf("ping process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(sock[0], buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(sock[0], buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("ping process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "pong") != 0) {
+ fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+ }
+
+ status = PR_Close(sock[0]);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ status = PR_WaitProcess(process, &exitCode);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_WaitProcess failed\n");
+ exit(1);
+ }
+ if (exitCode == 0) {
+ printf("PASS\n");
+ return 0;
+ } else {
+ printf("FAIL\n");
+ return 1;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sockpong.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sockpong.c
new file mode 100644
index 00000000..e54e3423
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sockpong.c
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: sockpong.c
+ *
+ * Description:
+ * This test runs in conjunction with the sockping test.
+ * The sockping test creates a socket pair and passes one
+ * socket to this test. Then the sockping test writes
+ * "ping" to this test and this test writes "pong" back.
+ * To run this pair of tests, just invoke sockping.
+ *
+ * Tested areas: process creation, socket pairs, file
+ * descriptor inheritance.
+ */
+
+#include "prerror.h"
+#include "prio.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NUM_ITERATIONS 10
+
+int main()
+{
+ PRFileDesc *sock;
+ PRStatus status;
+ char buf[1024];
+ PRInt32 nBytes;
+ int idx;
+
+ sock = PR_GetInheritedFD("SOCKET");
+ if (sock == NULL) {
+ fprintf(stderr, "PR_GetInheritedFD failed\n");
+ exit(1);
+ }
+ status = PR_SetFDInheritable(sock, PR_FALSE);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_SetFDInheritable failed\n");
+ exit(1);
+ }
+
+ for (idx = 0; idx < NUM_ITERATIONS; idx++) {
+ memset(buf, 0, sizeof(buf));
+ nBytes = PR_Read(sock, buf, sizeof(buf));
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Read failed: (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ exit(1);
+ }
+ printf("pong process: received \"%s\"\n", buf);
+ if (nBytes != 5) {
+ fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n",
+ nBytes);
+ exit(1);
+ }
+ if (strcmp(buf, "ping") != 0) {
+ fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n",
+ buf);
+ exit(1);
+ }
+
+ strcpy(buf, "pong");
+ printf("pong process: sending \"%s\"\n", buf);
+ nBytes = PR_Write(sock, buf, 5);
+ if (nBytes == -1) {
+ fprintf(stderr, "PR_Write failed\n");
+ exit(1);
+ }
+ }
+
+ status = PR_Close(sock);
+ if (status == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sprintf.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sprintf.c
new file mode 100644
index 00000000..7fe2ac19
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sprintf.c
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: sprintf.c
+ * Description:
+ * This is a test program for the PR_snprintf() functions defined
+ * in prprf.c. This test program is based on ns/nspr/tests/sprintf.c,
+ * revision 1.10.
+ * Modification History:
+ * 20-May-1997 AGarcia replaced printf statment to return PASS\n. This is to be used by the
+ * regress tool parsing routine.
+ ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+ * recognize the return code from tha main program.
+ */
+
+#include "prinit.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "prlong.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define countof(a) (sizeof(a)/sizeof(a[0]))
+
+static char sbuf[20000];
+
+
+/*
+** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf.
+** Make sure the results are identical
+*/
+static void test_i(char *pattern, int i)
+{
+ char *s;
+ char buf[200];
+ int n;
+
+ /* try all three routines */
+ s = PR_smprintf(pattern, i);
+ PR_ASSERT(s != 0);
+ n = PR_snprintf(buf, sizeof(buf), pattern, i);
+ PR_ASSERT(n <= sizeof(buf));
+ sprintf(sbuf, pattern, i);
+
+ /* compare results */
+ if ((strncmp(s, buf, sizeof(buf)) != 0) ||
+ (strncmp(s, sbuf, sizeof(sbuf)) != 0)) {
+ fprintf(stderr,
+ "pattern='%s' i=%d\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n",
+ pattern, i, s, buf, sbuf);
+ PR_smprintf_free(s);
+ exit(-1);
+ }
+ PR_smprintf_free(s);
+}
+
+static void TestI(void)
+{
+ static int nums[] = {
+ 0, 1, -1, 10, -10,
+ 32767, -32768,
+ };
+ static char *signs[] = {
+ "",
+ "0", "-", "+", " ",
+ "0-", "0+", "0 ", "-0", "-+", "- ",
+ "+0", "+-", "+ ", " 0", " -", " +",
+ "0-+", "0- ", "0+-", "0+ ", "0 -", "0 +",
+ "-0+", "-0 ", "-+0", "-+ ", "- 0", "- +",
+ "+0-", "+0 ", "+-0", "+- ", "+ 0", "+ -",
+ " 0-", " 0+", " -0", " -+", " +0", " +-",
+ "0-+ ", "0- +", "0+- ", "0+ -", "0 -+", "0 +-",
+ "-0+ ", "-0 +", "-+0 ", "-+ 0", "- 0+", "- +0",
+ "+0- ", "+0 -", "+-0 ", "+- 0", "+ 0-", "+ -0",
+ " 0-+", " 0+-", " -0+", " -+0", " +0-", " +-0",
+ };
+ static char *precs[] = {
+ "", "3", "5", "43",
+ "7.3", "7.5", "7.11", "7.43",
+ };
+ static char *formats[] = {
+ "d", "o", "x", "u",
+ "hd", "ho", "hx", "hu"
+ };
+ int f, s, n, p;
+ char fmt[20];
+
+ for (f = 0; f < countof(formats); f++) {
+ for (s = 0; s < countof(signs); s++) {
+ for (p = 0; p < countof(precs); p++) {
+ fmt[0] = '%';
+ fmt[1] = 0;
+ if (signs[s]) strcat(fmt, signs[s]);
+ if (precs[p]) strcat(fmt, precs[p]);
+ if (formats[f]) strcat(fmt, formats[f]);
+ for (n = 0; n < countof(nums); n++) {
+ test_i(fmt, nums[n]);
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+/*
+** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf.
+** Make sure the results are identical
+*/
+static void test_l(char *pattern, char *spattern, PRInt32 l)
+{
+ char *s;
+ char buf[200];
+ int n;
+
+ /* try all three routines */
+ s = PR_smprintf(pattern, l);
+ PR_ASSERT(s != 0);
+ n = PR_snprintf(buf, sizeof(buf), pattern, l);
+ PR_ASSERT(n <= sizeof(buf));
+ sprintf(sbuf, spattern, l);
+
+ /* compare results */
+ if ((strncmp(s, buf, sizeof(buf)) != 0) ||
+ (strncmp(s, sbuf, sizeof(sbuf)) != 0)) {
+ fprintf(stderr,
+ "pattern='%s' l=%ld\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n",
+ pattern, l, s, buf, sbuf);
+ PR_smprintf_free(s);
+ exit(-1);
+ }
+ PR_smprintf_free(s);
+}
+
+static void TestL(void)
+{
+ static PRInt32 nums[] = {
+ 0,
+ 1,
+ -1,
+ 10,
+ -10,
+ 32767,
+ -32768,
+ PR_INT32(0x7fffffff), /* 2147483647L */
+ -1 - PR_INT32(0x7fffffff) /* -2147483648L */
+ };
+ static char *signs[] = {
+ "",
+ "0", "-", "+", " ",
+ "0-", "0+", "0 ", "-0", "-+", "- ",
+ "+0", "+-", "+ ", " 0", " -", " +",
+ "0-+", "0- ", "0+-", "0+ ", "0 -", "0 +",
+ "-0+", "-0 ", "-+0", "-+ ", "- 0", "- +",
+ "+0-", "+0 ", "+-0", "+- ", "+ 0", "+ -",
+ " 0-", " 0+", " -0", " -+", " +0", " +-",
+ "0-+ ", "0- +", "0+- ", "0+ -", "0 -+", "0 +-",
+ "-0+ ", "-0 +", "-+0 ", "-+ 0", "- 0+", "- +0",
+ "+0- ", "+0 -", "+-0 ", "+- 0", "+ 0-", "+ -0",
+ " 0-+", " 0+-", " -0+", " -+0", " +0-", " +-0",
+ };
+ static char *precs[] = {
+ "", "3", "5", "43",
+ ".3", ".43",
+ "7.3", "7.5", "7.11", "7.43",
+ };
+ static char *formats[] = { "ld", "lo", "lx", "lu" };
+
+#if PR_BYTES_PER_INT == 4
+ static char *sformats[] = { "d", "o", "x", "u" };
+#elif PR_BYTES_PER_LONG == 4
+ static char *sformats[] = { "ld", "lo", "lx", "lu" };
+#else
+#error Neither int nor long is 4 bytes on this platform
+#endif
+
+ int f, s, n, p;
+ char fmt[40], sfmt[40];
+
+ for (f = 0; f < countof(formats); f++) {
+ for (s = 0; s < countof(signs); s++) {
+ for (p = 0; p < countof(precs); p++) {
+ fmt[0] = '%';
+ fmt[1] = 0;
+ if (signs[s]) strcat(fmt, signs[s]);
+ if (precs[p]) strcat(fmt, precs[p]);
+ strcpy(sfmt, fmt);
+ if (formats[f]) strcat(fmt, formats[f]);
+ if (sformats[f]) strcat(sfmt, sformats[f]);
+ for (n = 0; n < countof(nums); n++) {
+ test_l(fmt, sfmt, nums[n]);
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+/*
+** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf.
+** Make sure the results are identical
+*/
+static void test_ll(char *pattern, char *spattern, PRInt64 l)
+{
+ char *s;
+ char buf[200];
+ int n;
+
+ /* try all three routines */
+ s = PR_smprintf(pattern, l);
+ PR_ASSERT(s != 0);
+ n = PR_snprintf(buf, sizeof(buf), pattern, l);
+ PR_ASSERT(n <= sizeof(buf));
+#if defined(HAVE_LONG_LONG)
+ sprintf(sbuf, spattern, l);
+
+ /* compare results */
+ if ((strncmp(s, buf, sizeof(buf)) != 0) ||
+ (strncmp(s, sbuf, sizeof(sbuf)) != 0)) {
+#if PR_BYTES_PER_LONG == 8
+#define FORMAT_SPEC "%ld"
+#elif defined(WIN16)
+#define FORMAT_SPEC "%Ld"
+#elif defined(WIN32)
+#define FORMAT_SPEC "%I64d"
+#else
+#define FORMAT_SPEC "%lld"
+#endif
+ fprintf(stderr,
+ "pattern='%s' ll=" FORMAT_SPEC "\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n",
+ pattern, l, s, buf, sbuf);
+ printf("FAIL\n");
+ PR_smprintf_free(s);
+ exit(-1);
+ }
+ PR_smprintf_free(s);
+#else
+ /* compare results */
+ if ((strncmp(s, buf, sizeof(buf)) != 0)) {
+ fprintf(stderr,
+ "pattern='%s'\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n",
+ pattern, s, buf, sbuf);
+ printf("FAIL\n");
+ PR_smprintf_free(s);
+ exit(-1);
+ }
+ PR_smprintf_free(s);
+#endif
+}
+
+static void TestLL(void)
+{
+ static PRInt64 nums[] = {
+ LL_INIT(0, 0),
+ LL_INIT(0, 1),
+ LL_INIT(0xffffffff, 0xffffffff), /* -1 */
+ LL_INIT(0, 10),
+ LL_INIT(0xffffffff, 0xfffffff6), /* -10 */
+ LL_INIT(0, 32767),
+ LL_INIT(0xffffffff, 0xffff8000), /* -32768 */
+ LL_INIT(0, 0x7fffffff), /* 2147483647 */
+ LL_INIT(0xffffffff, 0x80000000), /* -2147483648 */
+ LL_INIT(0x7fffffff, 0xffffffff), /* 9223372036854775807 */
+ LL_INIT(0x80000000, 0) /* -9223372036854775808 */
+ };
+
+ static char *signs[] = {
+ "",
+ "0", "-", "+", " ",
+ "0-", "0+", "0 ", "-0", "-+", "- ",
+ "+0", "+-", "+ ", " 0", " -", " +",
+ "0-+", "0- ", "0+-", "0+ ", "0 -", "0 +",
+ "-0+", "-0 ", "-+0", "-+ ", "- 0", "- +",
+ "+0-", "+0 ", "+-0", "+- ", "+ 0", "+ -",
+ " 0-", " 0+", " -0", " -+", " +0", " +-",
+ "0-+ ", "0- +", "0+- ", "0+ -", "0 -+", "0 +-",
+ "-0+ ", "-0 +", "-+0 ", "-+ 0", "- 0+", "- +0",
+ "+0- ", "+0 -", "+-0 ", "+- 0", "+ 0-", "+ -0",
+ " 0-+", " 0+-", " -0+", " -+0", " +0-", " +-0",
+ };
+ static char *precs[] = {
+ "", "3", "5", "43",
+ ".3", ".43",
+ "7.3", "7.5", "7.11", "7.43",
+ };
+ static char *formats[] = { "lld", "llo", "llx", "llu" };
+
+#if PR_BYTES_PER_LONG == 8
+ static char *sformats[] = { "ld", "lo", "lx", "lu" };
+#elif defined(WIN16)
+ /* Watcom uses the format string "%Ld" instead of "%lld". */
+ static char *sformats[] = { "Ld", "Lo", "Lx", "Lu" };
+#elif defined(WIN32)
+ static char *sformats[] = { "I64d", "I64o", "I64x", "I64u" };
+#else
+ static char *sformats[] = { "lld", "llo", "llx", "llu" };
+#endif
+
+ int f, s, n, p;
+ char fmt[40], sfmt[40];
+
+ for (f = 0; f < countof(formats); f++) {
+ for (s = 0; s < countof(signs); s++) {
+ for (p = 0; p < countof(precs); p++) {
+ fmt[0] = '%';
+ fmt[1] = 0;
+ if (signs[s]) strcat(fmt, signs[s]);
+ if (precs[p]) strcat(fmt, precs[p]);
+ strcpy(sfmt, fmt);
+ if (formats[f]) strcat(fmt, formats[f]);
+ if (sformats[f]) strcat(sfmt, sformats[f]);
+ for (n = 0; n < countof(nums); n++) {
+ test_ll(fmt, sfmt, nums[n]);
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+/*
+** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf.
+** Make sure the results are identical
+*/
+static void test_s(char *pattern, char *ss)
+{
+ char *s;
+ unsigned char before[8];
+ char buf[200];
+ unsigned char after[8];
+ int n;
+
+ memset(before, 0xBB, 8);
+ memset(after, 0xAA, 8);
+
+ /* try all three routines */
+ s = PR_smprintf(pattern, ss);
+ PR_ASSERT(s != 0);
+ n = PR_snprintf(buf, sizeof(buf), pattern, ss);
+ PR_ASSERT(n <= sizeof(buf));
+ sprintf(sbuf, pattern, ss);
+
+ for (n = 0; n < 8; n++) {
+ PR_ASSERT(before[n] == 0xBB);
+ PR_ASSERT(after[n] == 0xAA);
+ }
+
+ /* compare results */
+ if ((strncmp(s, buf, sizeof(buf)) != 0) ||
+ (strncmp(s, sbuf, sizeof(sbuf)) != 0)) {
+ fprintf(stderr,
+ "pattern='%s' ss=%.20s\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n",
+ pattern, ss, s, buf, sbuf);
+ printf("FAIL\n");
+ PR_smprintf_free(s);
+ exit(-1);
+ }
+ PR_smprintf_free(s);
+}
+
+static void TestS(void)
+{
+ static char *strs[] = {
+ "",
+ "a",
+ "abc",
+ "abcde",
+ "abcdefABCDEF",
+ "abcdefghijklmnopqrstuvwxyz0123456789!@#$"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$"
+ "abcdefghijklmnopqrstuvwxyz0123456789!@#$",
+ };
+ /* '0' is not relevant to printing strings */
+ static char *signs[] = {
+ "",
+ "-", "+", " ",
+ "-+", "- ", "+-", "+ ", " -", " +",
+ "-+ ", "- +", "+- ", "+ -", " -+", " +-",
+ };
+ static char *precs[] = {
+ "", "3", "5", "43",
+ ".3", ".43",
+ "7.3", "7.5", "7.11", "7.43",
+ };
+ static char *formats[] = { "s" };
+ int f, s, n, p;
+ char fmt[40];
+
+ for (f = 0; f < countof(formats); f++) {
+ for (s = 0; s < countof(signs); s++) {
+ for (p = 0; p < countof(precs); p++) {
+ fmt[0] = '%';
+ fmt[1] = 0;
+ if (signs[s]) strcat(fmt+strlen(fmt), signs[s]);
+ if (precs[p]) strcat(fmt+strlen(fmt), precs[p]);
+ if (formats[f]) strcat(fmt+strlen(fmt), formats[f]);
+ for (n = 0; n < countof(strs); n++) {
+ test_s(fmt, strs[n]);
+ }
+ }
+ }
+ }
+}
+
+/************************************************************************/
+
+int main(int argc, char **argv)
+{
+ PR_STDIO_INIT();
+ TestI();
+ TestL();
+ TestLL();
+ TestS();
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sproc_ch.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sproc_ch.c
new file mode 100644
index 00000000..98dee083
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sproc_ch.c
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Test sproc_ch.c
+ *
+ * The purpose of this test and the sproc_p.c test is to test the shutdown
+ * of all the IRIX sprocs in a program when one of them dies due to an error.
+ *
+ * There are three sprocs in this test: the parent, the child, and the
+ * grandchild. The parent and child sprocs never stop on their own.
+ * The grandchild sproc gets a segmentation fault and dies. You should
+ * You should use "ps" to see if the parent and child sprocs are killed
+ * after the grandchild dies.
+ */
+
+#include "prinit.h"
+#include <stdio.h>
+
+#if !defined(IRIX)
+
+int main()
+{
+ printf("This test applies to IRIX only.\n");
+ return 0;
+}
+
+#else /* IRIX */
+
+#include "prthread.h"
+#include <sys/types.h>
+#include <unistd.h>
+
+void SegFault(void *unused)
+{
+ int *p = 0;
+
+ printf("The grandchild sproc has pid %d.\n", getpid());
+ printf("The grandchild sproc will get a segmentation fault and die.\n");
+ printf("The parent and child sprocs should be killed after the "
+ "grandchild sproc dies.\n");
+ printf("Use 'ps' to make sure this is so.\n");
+ fflush(stdout);
+ /* Force a segmentation fault */
+ *p = 0;
+}
+
+void NeverStops(void *unused)
+{
+ int i = 0;
+
+ printf("The child sproc has pid %d.\n", getpid());
+ printf("The child sproc won't stop on its own.\n");
+ fflush(stdout);
+
+ /* create the grandchild sproc */
+ PR_CreateThread(PR_USER_THREAD, SegFault, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+
+ while (1) {
+ i++;
+ }
+}
+
+int main()
+{
+ int i= 0;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ printf("The parent sproc has pid %d.\n", getpid());
+ printf("The parent sproc won't stop on its own.\n");
+ fflush(stdout);
+
+ /* create the child sproc */
+ PR_CreateThread(PR_USER_THREAD, NeverStops, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+
+ while (1) {
+ i++;
+ }
+ return 0;
+}
+
+#endif /* IRIX */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/sproc_p.c b/src/libs/xpcom18a4/nsprpub/pr/tests/sproc_p.c
new file mode 100644
index 00000000..e8ded66b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/sproc_p.c
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Test sproc_p.c
+ *
+ * The purpose of this test and the sproc_ch.c test is to test the shutdown
+ * of all the IRIX sprocs in a program when one of them dies due to an error.
+ *
+ * In this test, the parent sproc gets a segmentation fault and dies.
+ * The child sproc never stops on its own. You should use "ps" to see if
+ * the child sproc is killed after the parent dies.
+ */
+
+#include "prinit.h"
+#include <stdio.h>
+
+#if !defined(IRIX)
+
+int main()
+{
+ printf("This test applies to IRIX only.\n");
+ return 0;
+}
+
+#else /* IRIX */
+
+#include "prthread.h"
+#include <sys/types.h>
+#include <unistd.h>
+
+void NeverStops(void *unused)
+{
+ int i = 0;
+
+ printf("The child sproc has pid %d.\n", getpid());
+ printf("The child sproc won't stop on its own.\n");
+ fflush(stdout);
+
+ /* I never stop */
+ while (1) {
+ i++;
+ }
+}
+
+int main()
+{
+ int *p = 0;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ printf("The parent sproc has pid %d.\n", getpid());
+ printf("The parent sproc will first create a child sproc.\n");
+ printf("Then the parent sproc will get a segmentation fault and die.\n");
+ printf("The child sproc should be killed after the parent sproc dies.\n");
+ printf("Use 'ps' to make sure this is so.\n");
+ fflush(stdout);
+
+ PR_CreateThread(PR_USER_THREAD, NeverStops, NULL,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+
+ /* Force a segmentation fault */
+ *p = 0;
+ return 0;
+}
+
+#endif /* IRIX */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/stack.c b/src/libs/xpcom18a4/nsprpub/pr/tests/stack.c
new file mode 100644
index 00000000..c47cb71f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/stack.c
@@ -0,0 +1,310 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/*
+ *
+ * Test atomic stack operations
+ *
+ * Two stacks are created and threads add data items (each containing
+ * one of the first n integers) to the first stack, remove data items
+ * from the first stack and add them to the second stack. The primordial
+ * thread compares the sum of the first n integers to the sum of the
+ * integers in the data items in the second stack. The test succeeds if
+ * they are equal.
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+typedef struct _DataRecord {
+ PRInt32 data;
+ PRStackElem link;
+} DataRecord;
+
+#define RECORD_LINK_PTR(lp) ((DataRecord*) ((char*) (lp) - offsetof(DataRecord,link)))
+
+#define MAX_THREAD_CNT 100
+#define DEFAULT_THREAD_CNT 4
+#define DEFAULT_DATA_CNT 100
+#define DEFAULT_LOOP_CNT 10000
+
+/*
+ * sum of the first n numbers using the formula n*(n+1)/2
+ */
+#define SUM_OF_NUMBERS(n) ((n & 1) ? (((n + 1)/2) * n) : ((n/2) * (n+1)))
+
+typedef struct stack_data {
+ PRStack *list1;
+ PRStack *list2;
+ PRInt32 initial_data_value;
+ PRInt32 data_cnt;
+ PRInt32 loops;
+} stack_data;
+
+static void stackop(void *arg);
+
+static int _debug_on;
+
+PRFileDesc *output;
+PRFileDesc *errhandle;
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRInt32 rv, cnt, sum;
+ DataRecord *Item;
+ PRStack *list1, *list2;
+ PRStackElem *node;
+ PRStatus rc;
+
+ PRInt32 thread_cnt = DEFAULT_THREAD_CNT;
+ PRInt32 data_cnt = DEFAULT_DATA_CNT;
+ PRInt32 loops = DEFAULT_LOOP_CNT;
+ PRThread **threads;
+ stack_data *thread_args;
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:l:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 't': /* thread count */
+ thread_cnt = atoi(opt->value);
+ break;
+ case 'c': /* data count */
+ data_cnt = atoi(opt->value);
+ break;
+ case 'l': /* loop count */
+ loops = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_SetConcurrency(4);
+
+ output = PR_GetSpecialFD(PR_StandardOutput);
+ errhandle = PR_GetSpecialFD(PR_StandardError);
+ list1 = PR_CreateStack("Stack_1");
+ if (list1 == NULL) {
+ PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+ list2 = PR_CreateStack("Stack_2");
+ if (list2 == NULL) {
+ PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n",
+ PR_GetError());
+ return 1;
+ }
+
+
+ threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt);
+ thread_args = (stack_data *) PR_CALLOC(sizeof(stack_data) * thread_cnt);
+
+ if (_debug_on)
+ PR_fprintf(output,"%s: thread_cnt = %d data_cnt = %d\n", argv[0],
+ thread_cnt, data_cnt);
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ PRThreadScope scope;
+
+ thread_args[cnt].list1 = list1;
+ thread_args[cnt].list2 = list2;
+ thread_args[cnt].loops = loops;
+ thread_args[cnt].data_cnt = data_cnt;
+ thread_args[cnt].initial_data_value = 1 + cnt * data_cnt;
+
+ if (cnt & 1)
+ scope = PR_GLOBAL_THREAD;
+ else
+ scope = PR_LOCAL_THREAD;
+
+
+ threads[cnt] = PR_CreateThread(PR_USER_THREAD,
+ stackop, &thread_args[cnt],
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (threads[cnt] == NULL) {
+ PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n",
+ PR_GetError());
+ PR_ProcessExit(2);
+ }
+ if (_debug_on)
+ PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0],
+ threads[cnt]);
+ }
+
+ for(cnt = 0; cnt < thread_cnt; cnt++) {
+ rc = PR_JoinThread(threads[cnt]);
+ PR_ASSERT(rc == PR_SUCCESS);
+ }
+
+ node = PR_StackPop(list1);
+ /*
+ * list1 should be empty
+ */
+ if (node != NULL) {
+ PR_fprintf(errhandle, "Error - Stack 1 not empty\n");
+ PR_ASSERT(node == NULL);
+ PR_ProcessExit(4);
+ }
+
+ cnt = data_cnt * thread_cnt;
+ sum = 0;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list2);
+ /*
+ * There should be at least 'cnt' number of records
+ */
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ProcessExit(3);
+ }
+ Item = RECORD_LINK_PTR(node);
+ sum += Item->data;
+ }
+ node = PR_StackPop(list2);
+ /*
+ * there should be exactly 'cnt' number of records
+ */
+ if (node != NULL) {
+ PR_fprintf(errhandle, "Error - Stack 2 not empty\n");
+ PR_ASSERT(node == NULL);
+ PR_ProcessExit(4);
+ }
+ PR_DELETE(threads);
+ PR_DELETE(thread_args);
+
+ PR_DestroyStack(list1);
+ PR_DestroyStack(list2);
+
+ if (sum == SUM_OF_NUMBERS(data_cnt * thread_cnt)) {
+ PR_fprintf(output, "%s successful\n", argv[0]);
+ PR_fprintf(output, "\t\tsum = 0x%x, expected = 0x%x\n", sum,
+ SUM_OF_NUMBERS(thread_cnt * data_cnt));
+ return 0;
+ } else {
+ PR_fprintf(output, "%s failed: sum = 0x%x, expected = 0x%x\n",
+ argv[0], sum,
+ SUM_OF_NUMBERS(data_cnt * thread_cnt));
+ return 2;
+ }
+}
+
+static void stackop(void *thread_arg)
+{
+ PRInt32 val, cnt, index, loops;
+ DataRecord *Items, *Item;
+ PRStack *list1, *list2;
+ PRStackElem *node;
+ stack_data *arg = (stack_data *) thread_arg;
+
+ val = arg->initial_data_value;
+ cnt = arg->data_cnt;
+ loops = arg->loops;
+ list1 = arg->list1;
+ list2 = arg->list2;
+
+ /*
+ * allocate memory for the data records
+ */
+ Items = (DataRecord *) PR_CALLOC(sizeof(DataRecord) * cnt);
+ PR_ASSERT(Items != NULL);
+ index = 0;
+
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] init_val = %d cnt = %d data1 = 0x%x datan = 0x%x\n",
+ PR_GetCurrentThread(), val, cnt, &Items[0], &Items[cnt-1]);
+
+
+ /*
+ * add the data records to list1
+ */
+ while (cnt-- > 0) {
+ Items[index].data = val++;
+ PR_StackPush(list1, &Items[index].link);
+ index++;
+ }
+
+ /*
+ * pop data records from list1 and add them back to list1
+ * generates contention for the stack accesses
+ */
+ while (loops-- > 0) {
+ cnt = arg->data_cnt;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list1);
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ASSERT(node != NULL);
+ PR_ProcessExit(3);
+ }
+ PR_StackPush(list1, node);
+ }
+ }
+ /*
+ * remove the data records from list1 and add them to list2
+ */
+ cnt = arg->data_cnt;
+ while (cnt-- > 0) {
+ node = PR_StackPop(list1);
+ if (node == NULL) {
+ PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n");
+ PR_ASSERT(node != NULL);
+ PR_ProcessExit(3);
+ }
+ PR_StackPush(list2, node);
+ }
+ if (_debug_on)
+ PR_fprintf(output,
+ "Thread[0x%x] init_val = %d cnt = %d exiting\n",
+ PR_GetCurrentThread(), val, cnt);
+
+}
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/stat.c b/src/libs/xpcom18a4/nsprpub/pr/tests/stat.c
new file mode 100644
index 00000000..73803d05
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/stat.c
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Program to test different ways to get file info; right now it
+ * only works for solaris and OS/2.
+ *
+ */
+#include "nspr.h"
+#include "prpriv.h"
+#include "prinrval.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_OS2
+#include <io.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#define DEFAULT_COUNT 100000
+PRInt32 count;
+
+#ifndef XP_PC
+char *filename = "/etc/passwd";
+#else
+char *filename = "..\\stat.c";
+#endif
+
+static void statPRStat(void)
+{
+ PRFileInfo finfo;
+ PRInt32 index = count;
+
+ for (;index--;) {
+ PR_GetFileInfo(filename, &finfo);
+ }
+}
+
+static void statStat(void)
+{
+ struct stat finfo;
+ PRInt32 index = count;
+
+ for (;index--;) {
+ stat(filename, &finfo);
+ }
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+ PRInt32 tot;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+ tot = PR_IntervalToMilliseconds(stop-start);
+
+ printf("%40s: %6.2f usec avg, %d msec total\n", msg, d / count, tot);
+}
+
+void main(int argc, char **argv)
+{
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (argc > 1) {
+ count = atoi(argv[1]);
+ } else {
+ count = DEFAULT_COUNT;
+ }
+
+ Measure(statPRStat, "time to call PR_GetFileInfo()");
+ Measure(statStat, "time to call stat()");
+
+ PR_Cleanup();
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/stdio.c b/src/libs/xpcom18a4/nsprpub/pr/tests/stdio.c
new file mode 100644
index 00000000..d0d84e4e
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/stdio.c
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: stdio.c
+ * Description: testing the "special" fds
+ * Modification History:
+ * 20-May-1997 AGarcia - Replace Test succeeded status with PASS. This is used by the
+ * regress tool parsing code.
+ ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
+** recognize the return code from tha main program.
+ */
+
+
+#include "prlog.h"
+#include "prinit.h"
+#include "prio.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static PRIntn PR_CALLBACK stdio(PRIntn argc, char **argv)
+{
+ PRInt32 rv;
+
+ PRFileDesc *out = PR_GetSpecialFD(PR_StandardOutput);
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+
+ rv = PR_Write(
+ out, "This to standard out\n",
+ strlen("This to standard out\n"));
+ PR_ASSERT((PRInt32)strlen("This to standard out\n") == rv);
+ rv = PR_Write(
+ err, "This to standard err\n",
+ strlen("This to standard err\n"));
+ PR_ASSERT((PRInt32)strlen("This to standard err\n") == rv);
+
+ return 0;
+
+} /* stdio */
+
+int main(int argc, char **argv)
+{
+ PR_STDIO_INIT();
+ return PR_Initialize(stdio, argc, argv, 0);
+} /* main */
+
+
+/* stdio.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/str2addr.c b/src/libs/xpcom18a4/nsprpub/pr/tests/str2addr.c
new file mode 100644
index 00000000..b1d4cf4a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/str2addr.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: str2addr.c
+ * Description: a test for PR_StringToNetAddr
+ */
+
+#include "nspr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Address string to convert */
+#define DEFAULT_IPV4_ADDR_STR "207.200.73.41"
+
+/* Expected conversion result, in network byte order */
+static unsigned char default_ipv4_addr[] = {207, 200, 73, 41};
+
+int main(int argc, char **argv)
+{
+ PRNetAddr addr;
+ const char *addrStr;
+ unsigned char *bytes;
+ int idx;
+
+ addrStr = DEFAULT_IPV4_ADDR_STR;
+ if (PR_StringToNetAddr(addrStr, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_StringToNetAddr failed\n");
+ exit(1);
+ }
+ if (addr.inet.family != PR_AF_INET) {
+ fprintf(stderr, "addr.inet.family should be %d but is %d\n",
+ PR_AF_INET, addr.inet.family);
+ exit(1);
+ }
+ bytes = (unsigned char *) &addr.inet.ip;
+ for (idx = 0; idx < 4; idx++) {
+ if (bytes[idx] != default_ipv4_addr[idx]) {
+ fprintf(stderr, "byte %d of IPv4 addr should be %d but is %d\n",
+ idx, default_ipv4_addr[idx], bytes[idx]);
+ exit(1);
+ }
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/strod.c b/src/libs/xpcom18a4/nsprpub/pr/tests/strod.c
new file mode 100644
index 00000000..242617a7
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/strod.c
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prinit.h"
+#include "prio.h"
+#include "prprf.h"
+#include "prdtoa.h"
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+static void Help(void)
+{
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+ PR_fprintf(err, "Usage: /.strod [-n n] [-l n] [-h]\n");
+ PR_fprintf(err, "\t-n n Number to translate (default: 1234567890123456789)\n");
+ PR_fprintf(err, "\t-l n Times to loop the test (default: 1)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+static PRIntn PR_CALLBACK RealMain(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ PRIntn loops = 1;
+ PRFloat64 answer;
+ const char *number = "1234567890123456789";
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hc:l:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'n': /* number to translate */
+ number = opt->value;
+ break;
+ case 'l': /* number of times to run the tests */
+ loops = atoi(opt->value);
+ break;
+ case 'h': /* user wants some guidance */
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_fprintf(err, "Settings\n");
+ PR_fprintf(err, "\tNumber to translate %s\n", number);
+ PR_fprintf(err, "\tLoops to run test: %d\n", loops);
+
+ while (loops--)
+ {
+ answer = PR_strtod(number, NULL);
+ PR_fprintf(err, "Translation = %20.0f\n", answer);
+ }
+ return 0;
+}
+
+
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/suspend.c b/src/libs/xpcom18a4/nsprpub/pr/tests/suspend.c
new file mode 100644
index 00000000..44ba6f87
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/suspend.c
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#ifdef XP_BEOS
+#include <stdio.h>
+int main()
+{
+ printf( "This test is not ported to the BeOS\n" );
+ return 0;
+}
+#else
+
+#include "nspr.h"
+#include "prpriv.h"
+#include "prinrval.h"
+
+#if defined(XP_MAC)
+#include "gcint.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "gcint.h"
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+PRMonitor *mon;
+PRInt32 count;
+PRInt32 alive;
+
+#define SLEEP_TIME 4 /* secs */
+
+void PR_CALLBACK
+Level_2_Thread(void *arg)
+{
+ PR_Sleep(PR_MillisecondsToInterval(4 * 1000));
+ printf("Level_2_Thread[0x%lx] exiting\n",PR_GetCurrentThread());
+ return;
+}
+
+void PR_CALLBACK
+Level_1_Thread(void *arg)
+{
+ PRUint32 tmp = (PRUint32)arg;
+ PRThreadScope scope = (PRThreadScope) tmp;
+ PRThread *thr;
+
+ thr = PR_CreateThreadGCAble(PR_USER_THREAD,
+ Level_2_Thread,
+ NULL,
+ PR_PRIORITY_HIGH,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ if (!thr) {
+ printf("Could not create thread!\n");
+ } else {
+ printf("Level_1_Thread[0x%lx] created %15s thread 0x%lx\n",
+ PR_GetCurrentThread(),
+ (scope == PR_GLOBAL_THREAD) ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD",
+ thr);
+ PR_JoinThread(thr);
+ }
+ PR_EnterMonitor(mon);
+ alive--;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+ printf("Thread[0x%lx] exiting\n",PR_GetCurrentThread());
+}
+
+static PRStatus PR_CALLBACK print_thread(PRThread *thread, int i, void *arg)
+{
+ PRInt32 words;
+ PRWord *registers;
+
+ printf(
+ "\nprint_thread[0x%lx]: %-20s - i = %ld\n",thread,
+ (PR_GLOBAL_THREAD == PR_GetThreadScope(thread)) ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD", i);
+ registers = PR_GetGCRegisters(thread, 0, (int *)&words);
+ printf("Regsters R0 = 0x%x R1 = 0x%x R2 = 0x%x R3 = 0x%x\n",
+ registers[0],registers[1],registers[2],registers[3]);
+ printf("Stack Pointer = 0x%lx\n", PR_GetSP(thread));
+ return PR_SUCCESS;
+}
+
+static void Level_0_Thread(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *thr;
+ PRThread *me = PR_GetCurrentThread();
+ int n;
+ PRInt32 words;
+ PRWord *registers;
+
+ alive = 0;
+ mon = PR_NewMonitor();
+
+ alive = count;
+ for (n=0; n<count; n++) {
+ thr = PR_CreateThreadGCAble(PR_USER_THREAD,
+ Level_1_Thread,
+ (void *)scope2,
+ PR_PRIORITY_NORMAL,
+ scope1,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (!thr) {
+ printf("Could not create thread!\n");
+ alive--;
+ }
+ printf("Level_0_Thread[0x%lx] created %15s thread 0x%lx\n",
+ PR_GetCurrentThread(),
+ (scope1 == PR_GLOBAL_THREAD) ?
+ "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD",
+ thr);
+
+ PR_Sleep(0);
+ }
+ PR_SuspendAll();
+ PR_EnumerateThreads(print_thread, NULL);
+ registers = PR_GetGCRegisters(me, 1, (int *)&words);
+ printf("My Registers: R0 = 0x%x R1 = 0x%x R2 = 0x%x R3 = 0x%x\n",
+ registers[0],registers[1],registers[2],registers[3]);
+ printf("My Stack Pointer = 0x%lx\n", PR_GetSP(me));
+ PR_ResumeAll();
+
+ /* Wait for all threads to exit */
+ PR_EnterMonitor(mon);
+ while (alive) {
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ PR_ExitMonitor(mon);
+ PR_DestroyMonitor(mon);
+}
+
+static void CreateThreadsUU(void)
+{
+ Level_0_Thread(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void CreateThreadsUK(void)
+{
+ Level_0_Thread(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+static void CreateThreadsKU(void)
+{
+ Level_0_Thread(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void CreateThreadsKK(void)
+{
+ Level_0_Thread(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+
+void
+main(int argc, char **argv)
+{
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("suspend.log");
+#endif
+
+ if (argc > 1) {
+ count = atoi(argv[1]);
+ } else {
+ count = 5;
+ }
+
+ printf("\n\n%20s%30s\n\n"," ","Suspend_Resume Test");
+ CreateThreadsUU();
+ CreateThreadsUK();
+ CreateThreadsKU();
+ CreateThreadsKK();
+ PR_SetConcurrency(2);
+
+ printf("\n%20s%30s\n\n"," ","Added 2nd CPU\n");
+
+ CreateThreadsUK();
+ CreateThreadsKK();
+ CreateThreadsUU();
+ CreateThreadsKU();
+ PR_Cleanup();
+}
+
+#endif /* XP_BEOS */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/switch.c b/src/libs/xpcom18a4/nsprpub/pr/tests/switch.c
new file mode 100644
index 00000000..2e42b793
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/switch.c
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: switch.c
+** Description: trying to time context switches
+*/
+
+#include "prinit.h"
+#include "prcvar.h"
+#include "prmem.h"
+#include "prinrval.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prthread.h"
+#include "prprf.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#if defined(XP_MAC)
+#include "pprio.h"
+#define printf PR_LogPrint
+#else
+#include "private/pprio.h"
+#endif
+
+#include <stdlib.h>
+
+#define INNER_LOOPS 100
+#define DEFAULT_LOOPS 100
+#define DEFAULT_THREADS 10
+
+static PRFileDesc *debug_out = NULL;
+static PRBool debug_mode = PR_FALSE, verbosity = PR_FALSE, failed = PR_FALSE;
+
+typedef struct Shared
+{
+ PRLock *ml;
+ PRCondVar *cv;
+ PRBool twiddle;
+ PRThread *thread;
+ struct Shared *next;
+} Shared;
+
+static void Help(void)
+{
+ debug_out = PR_STDOUT;
+
+ PR_fprintf(
+ debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n");
+ PR_fprintf(
+ debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS);
+ PR_fprintf(
+ debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS);
+ PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n");
+ PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n");
+ PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n");
+} /* Help */
+
+static void PR_CALLBACK Notified(void *arg)
+{
+ Shared *shared = (Shared*)arg;
+ PRStatus status = PR_SUCCESS;
+ while (PR_SUCCESS == status)
+ {
+ PR_Lock(shared->ml);
+ while (shared->twiddle && (PR_SUCCESS == status))
+ status = PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT);
+ if (verbosity) PR_fprintf(debug_out, "+");
+ shared->twiddle = PR_TRUE;
+ shared->next->twiddle = PR_FALSE;
+ PR_NotifyCondVar(shared->next->cv);
+ PR_Unlock(shared->ml);
+ }
+} /* Notified */
+
+static Shared home;
+PRIntn PR_CALLBACK Switch(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ PRStatus status;
+ PRBool help = PR_FALSE;
+ PRUintn concurrency = 1;
+ Shared *shared, *link;
+ PRIntervalTime timein, timeout;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PRUintn thread_count, inner_count, loop_count, average;
+ PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'v': /* verbose mode */
+ verbosity = PR_TRUE;
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop counter */
+ loop_limit = atoi(opt->value);
+ break;
+ case 't': /* thread limit */
+ thread_limit = atoi(opt->value);
+ break;
+ case 'C': /* Concurrency limit */
+ concurrency = atoi(opt->value);
+ break;
+ case 'G': /* global threads only */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'h': /* help message */
+ Help();
+ help = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (help) return -1;
+
+ if (PR_TRUE == debug_mode)
+ {
+ debug_out = PR_STDOUT;
+ PR_fprintf(debug_out, "Test parameters\n");
+ PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit);
+ PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit);
+ PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency);
+ PR_fprintf(
+ debug_out, "\tThread type: %s\n",
+ (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
+ }
+
+ PR_SetConcurrency(concurrency);
+
+ link = &home;
+ home.ml = PR_NewLock();
+ home.cv = PR_NewCondVar(home.ml);
+ home.twiddle = PR_FALSE;
+ home.next = NULL;
+
+ timeout = 0;
+
+ for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
+ {
+ shared = PR_NEWZAP(Shared);
+
+ shared->ml = home.ml;
+ shared->cv = PR_NewCondVar(home.ml);
+ shared->twiddle = PR_TRUE;
+ shared->next = link;
+ link = shared;
+
+ shared->thread = PR_CreateThread(
+ PR_USER_THREAD, Notified, shared,
+ PR_PRIORITY_HIGH, thread_scope,
+ PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(shared->thread != NULL);
+ if (NULL == shared->thread)
+ failed = PR_TRUE;
+ }
+
+ for (loop_count = 1; loop_count <= loop_limit; ++loop_count)
+ {
+ timein = PR_IntervalNow();
+ for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count)
+ {
+ PR_Lock(home.ml);
+ home.twiddle = PR_TRUE;
+ shared->twiddle = PR_FALSE;
+ PR_NotifyCondVar(shared->cv);
+ while (home.twiddle)
+ {
+ status = PR_WaitCondVar(home.cv, PR_INTERVAL_NO_TIMEOUT);
+ if (PR_FAILURE == status)
+ failed = PR_TRUE;
+ }
+ PR_Unlock(home.ml);
+ }
+ timeout += (PR_IntervalNow() - timein);
+ }
+
+ if (debug_mode)
+ {
+ average = PR_IntervalToMicroseconds(timeout)
+ / (INNER_LOOPS * loop_limit * thread_count);
+ PR_fprintf(
+ debug_out, "Average switch times %d usecs for %d threads\n",
+ average, thread_limit);
+ }
+
+ link = shared;
+ for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
+ {
+ if (&home == link) break;
+ status = PR_Interrupt(link->thread);
+ if (PR_SUCCESS != status)
+ {
+ failed = PR_TRUE;
+ if (debug_mode)
+ PL_FPrintError(debug_out, "Failed to interrupt");
+ }
+ link = link->next;
+ }
+
+ for (thread_count = 1; thread_count <= thread_limit; ++thread_count)
+ {
+ link = shared->next;
+ status = PR_JoinThread(shared->thread);
+ if (PR_SUCCESS != status)
+ {
+ failed = PR_TRUE;
+ if (debug_mode)
+ PL_FPrintError(debug_out, "Failed to join");
+ }
+ PR_DestroyCondVar(shared->cv);
+ PR_DELETE(shared);
+ if (&home == link) break;
+ shared = link;
+ }
+ PR_DestroyCondVar(home.cv);
+ PR_DestroyLock(home.ml);
+
+ PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n"));
+ return ((failed) ? 1 : 0);
+} /* Switch */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn result;
+ PR_STDIO_INIT();
+ result = PR_Initialize(Switch, argc, argv, 0);
+ return result;
+} /* main */
+
+/* switch.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/system.c b/src/libs/xpcom18a4/nsprpub/pr/tests/system.c
new file mode 100644
index 00000000..b4a89a0a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/system.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "prsystem.h"
+
+#include "plerror.h"
+
+static char *tag[] =
+{
+ "PR_SI_HOSTNAME",
+ "PR_SI_SYSNAME",
+ "PR_SI_RELEASE",
+ "PR_SI_ARCHITECTURE"
+};
+
+static PRSysInfo Incr(PRSysInfo *cmd)
+{
+ PRIntn tmp = (PRIntn)*cmd + 1;
+ *cmd = (PRSysInfo)tmp;
+ return (PRSysInfo)tmp;
+} /* Incr */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRSysInfo cmd;
+ PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput);
+
+ char *info = (char*)PR_Calloc(SYS_INFO_BUFFER_LENGTH, 1);
+ for (cmd = PR_SI_HOSTNAME; cmd <= PR_SI_ARCHITECTURE; Incr(&cmd))
+ {
+ rv = PR_GetSystemInfo(cmd, info, SYS_INFO_BUFFER_LENGTH);
+ if (PR_SUCCESS == rv) PR_fprintf(output, "%s: %s\n", tag[cmd], info);
+ else PL_FPrintError(output, tag[cmd]);
+ }
+ PR_DELETE(info);
+
+ PR_fprintf(output, "Host page size is %d\n", PR_GetPageSize());
+ PR_fprintf(output, "Page shift is %d\n", PR_GetPageShift());
+ PR_fprintf(output, "Number of processors is: %d\n", PR_GetNumberOfProcessors());
+
+ return 0;
+} /* main */
+
+/* system.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/testbit.c b/src/libs/xpcom18a4/nsprpub/pr/tests/testbit.c
new file mode 100644
index 00000000..1ad0b8f4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/testbit.c
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: lazyinit.c
+** Description: Test the functions and macros declared in prbit.h
+**
+*/
+
+#include "nspr.h"
+
+#define ErrorReport(x) { printf((x)); failed = 1; }
+
+prbitmap_t myMap[512/32] = { 0 };
+
+PRInt32 rc;
+PRInt32 i;
+PRIntn failed = 0;
+
+PRIntn main(PRIntn argc, char **argv )
+{
+ /*
+ ** Test bitmap things.
+ */
+ if ( PR_TEST_BIT( myMap, 0 ))
+ ErrorReport("Test 0.0: Failed\n");
+
+ if ( PR_TEST_BIT( myMap, 31 ))
+ ErrorReport("Test 0.1: Failed\n");
+
+ if ( PR_TEST_BIT( myMap, 128 ))
+ ErrorReport("Test 0.2: Failed\n");
+
+ if ( PR_TEST_BIT( myMap, 129 ))
+ ErrorReport("Test 0.3: Failed\n");
+
+
+ PR_SET_BIT( myMap, 0 );
+ if ( !PR_TEST_BIT( myMap, 0 ))
+ ErrorReport("Test 1.0: Failed\n");
+
+ PR_CLEAR_BIT( myMap, 0 );
+ if ( PR_TEST_BIT( myMap, 0 ))
+ ErrorReport("Test 1.0.1: Failed\n");
+
+ PR_SET_BIT( myMap, 31 );
+ if ( !PR_TEST_BIT( myMap, 31 ))
+ ErrorReport("Test 1.1: Failed\n");
+
+ PR_CLEAR_BIT( myMap, 31 );
+ if ( PR_TEST_BIT( myMap, 31 ))
+ ErrorReport("Test 1.1.1: Failed\n");
+
+ PR_SET_BIT( myMap, 128 );
+ if ( !PR_TEST_BIT( myMap, 128 ))
+ ErrorReport("Test 1.2: Failed\n");
+
+ PR_CLEAR_BIT( myMap, 128 );
+ if ( PR_TEST_BIT( myMap, 128 ))
+ ErrorReport("Test 1.2.1: Failed\n");
+
+ PR_SET_BIT( myMap, 129 );
+ if ( !PR_TEST_BIT( myMap, 129 ))
+ ErrorReport("Test 1.3: Failed\n");
+
+ PR_CLEAR_BIT( myMap, 129 );
+ if ( PR_TEST_BIT( myMap, 129 ))
+ ErrorReport("Test 1.3.1: Failed\n");
+
+
+ /*
+ ** Test Ceiling and Floor functions and macros
+ */
+ if ((rc = PR_CeilingLog2(32)) != 5 )
+ ErrorReport("Test 10.0: Failed\n");
+
+ if ((rc = PR_FloorLog2(32)) != 5 )
+ ErrorReport("Test 10.1: Failed\n");
+
+
+ /*
+ ** Evaluate results and exit
+ */
+ if (failed)
+ {
+ printf("FAILED\n");
+ return(1);
+ }
+ else
+ {
+ printf("PASSED\n");
+ return(0);
+ }
+} /* end main() */
+/* end testbit.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/testfile.c b/src/libs/xpcom18a4/nsprpub/pr/tests/testfile.c
new file mode 100644
index 00000000..4d2228e8
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/testfile.c
@@ -0,0 +1,1008 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-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.
+ */
+
+#include "nspr.h"
+#include "prpriv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#endif
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include <pthread.h>
+#endif
+
+#if defined(XP_OS2)
+#define INCL_DOSFILEMGR
+#include <os2.h>
+#ifdef XP_OS2_EMX
+#include <getopt.h>
+#include <errno.h>
+#endif /* XP_OS2_EMX */
+#endif /* XP_OS2 */
+
+static int _debug_on = 0;
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "primpl.h"
+#define printf PR_LogPrint
+#define setbuf(x,y)
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+#ifdef XP_WIN
+#define mode_t int
+#endif
+
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+PRLock *lock;
+PRMonitor *mon;
+PRInt32 count;
+int thread_count;
+
+#ifdef WIN16
+#define BUF_DATA_SIZE 256 * 120
+#else
+#define BUF_DATA_SIZE 256 * 1024
+#endif
+
+#define NUM_RDWR_THREADS 10
+#define NUM_DIRTEST_THREADS 4
+#define CHUNK_SIZE 512
+
+typedef struct buffer {
+ char data[BUF_DATA_SIZE];
+} buffer;
+
+typedef struct File_Rdwr_Param {
+ char *pathname;
+ char *buf;
+ int offset;
+ int len;
+} File_Rdwr_Param;
+
+#ifdef XP_PC
+#ifdef XP_OS2
+char *TEST_DIR = "prdir";
+#else
+char *TEST_DIR = "C:\\temp\\prdir";
+#endif
+char *FILE_NAME = "pr_testfile";
+char *HIDDEN_FILE_NAME = "hidden_pr_testfile";
+#else
+char *TEST_DIR = "/tmp/testfile_dir";
+char *FILE_NAME = "pr_testfile";
+char *HIDDEN_FILE_NAME = ".hidden_pr_testfile";
+#endif
+buffer *in_buf, *out_buf;
+char pathname[256], renamename[256];
+#define TMPDIR_LEN 64
+char testdir[TMPDIR_LEN];
+static PRInt32 PR_CALLBACK DirTest(void *argunused);
+PRInt32 dirtest_failed = 0;
+
+PRThread* create_new_thread(PRThreadType type,
+ void (*start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize, PRInt32 index)
+{
+PRInt32 native_thread = 0;
+
+ PR_ASSERT(state == PR_UNJOINABLE_THREAD);
+
+#if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) || defined(XP_OS2)
+
+ switch(index % 4) {
+ case 0:
+ scope = (PR_LOCAL_THREAD);
+ break;
+ case 1:
+ scope = (PR_GLOBAL_THREAD);
+ break;
+ case 2:
+ scope = (PR_GLOBAL_BOUND_THREAD);
+ break;
+ case 3:
+ native_thread = 1;
+ break;
+ default:
+ PR_ASSERT(!"Invalid scope");
+ break;
+ }
+ if (native_thread) {
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+ pthread_t tid;
+ if (!pthread_create(&tid, NULL, start, arg))
+ return((PRThread *) tid);
+ else
+ return (NULL);
+#elif defined(XP_OS2)
+ TID tid;
+
+ tid = (TID)_beginthread((void(* _Optlink)(void*))start,
+ NULL, 32768, arg);
+ if (tid == -1) {
+ printf("_beginthread failed. errno %d\n", errno);
+ return (NULL);
+ }
+ else
+ return((PRThread *) tid);
+#else
+ HANDLE thandle;
+ unsigned tid;
+
+ thandle = (HANDLE) _beginthreadex(
+ NULL,
+ stackSize,
+ (unsigned (__stdcall *)(void *))start,
+ arg,
+ 0,
+ &tid);
+ return((PRThread *) thandle);
+#endif
+ } else {
+ return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+ }
+#else
+ return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
+#endif
+}
+
+static void PR_CALLBACK File_Write(void *arg)
+{
+PRFileDesc *fd_file;
+File_Rdwr_Param *fp = (File_Rdwr_Param *) arg;
+char *name, *buf;
+int offset, len;
+
+ setbuf(stdout, NULL);
+ name = fp->pathname;
+ buf = fp->buf;
+ offset = fp->offset;
+ len = fp->len;
+
+ fd_file = PR_Open(name, PR_RDWR | PR_CREATE_FILE, 0777);
+ if (fd_file == NULL) {
+ printf("testfile failed to create/open file %s\n",name);
+ return;
+ }
+ if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) {
+ printf("testfile failed to seek in file %s\n",name);
+ return;
+ }
+ if ((PR_Write(fd_file, buf, len)) < 0) {
+ printf("testfile failed to write to file %s\n",name);
+ return;
+ }
+ DPRINTF(("Write out_buf[0] = 0x%x\n",(*((int *) buf))));
+ PR_Close(fd_file);
+ PR_DELETE(fp);
+
+ PR_EnterMonitor(mon);
+ --thread_count;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+}
+
+static void PR_CALLBACK File_Read(void *arg)
+{
+PRFileDesc *fd_file;
+File_Rdwr_Param *fp = (File_Rdwr_Param *) arg;
+char *name, *buf;
+int offset, len;
+
+ setbuf(stdout, NULL);
+ name = fp->pathname;
+ buf = fp->buf;
+ offset = fp->offset;
+ len = fp->len;
+
+ fd_file = PR_Open(name, PR_RDONLY, 0);
+ if (fd_file == NULL) {
+ printf("testfile failed to open file %s\n",name);
+ return;
+ }
+ if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) {
+ printf("testfile failed to seek in file %s\n",name);
+ return;
+ }
+ if ((PR_Read(fd_file, buf, len)) < 0) {
+ printf("testfile failed to read to file %s\n",name);
+ return;
+ }
+ DPRINTF(("Read in_buf[0] = 0x%x\n",(*((int *) buf))));
+ PR_Close(fd_file);
+ PR_DELETE(fp);
+
+ PR_EnterMonitor(mon);
+ --thread_count;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+}
+
+
+static PRInt32 Misc_File_Tests(char *pathname)
+{
+PRFileDesc *fd_file;
+int len, rv = 0;
+PRFileInfo file_info, file_info1;
+char tmpname[1024];
+
+ setbuf(stdout, NULL);
+ /*
+ * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
+ */
+
+ fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
+
+ if (fd_file == NULL) {
+ printf("testfile failed to create/open file %s\n",pathname);
+ return -1;
+ }
+ if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
+ printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (PR_Access(pathname, PR_ACCESS_EXISTS) != 0) {
+ printf("testfile PR_Access failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (PR_Access(pathname, PR_ACCESS_WRITE_OK) != 0) {
+ printf("testfile PR_Access failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (PR_Access(pathname, PR_ACCESS_READ_OK) != 0) {
+ printf("testfile PR_Access failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+
+
+ if (PR_GetFileInfo(pathname, &file_info) < 0) {
+ printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (file_info.type != PR_FILE_FILE) {
+ printf(
+ "testfile: Error - PR_GetFileInfo returned incorrect type for file %s\n",
+ pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (file_info.size != 0) {
+ printf(
+ "testfile PR_GetFileInfo returned incorrect size (%d should be 0) for file %s\n",
+ file_info.size, pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ file_info1 = file_info;
+
+ len = PR_Available(fd_file);
+ if (len < 0) {
+ printf("testfile PR_Available failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ } else if (len != 0) {
+ printf(
+ "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
+ 0, len);
+ rv = -1;
+ goto cleanup;
+ }
+ if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
+ printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
+ goto cleanup;
+ }
+ if (LL_NE(file_info.creationTime , file_info1.creationTime)) {
+ printf(
+ "testfile PR_GetFileInfo returned incorrect status-change time: %s\n",
+ pathname);
+ printf("ft = %lld, ft1 = %lld\n",file_info.creationTime,
+ file_info1.creationTime);
+ rv = -1;
+ goto cleanup;
+ }
+ len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
+ if (len < 0) {
+ printf("testfile failed to write to file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
+ printf("testfile PR_GetFileInfo failed on file %s\n",pathname);
+ goto cleanup;
+ }
+ if (file_info.size != CHUNK_SIZE) {
+ printf(
+ "testfile PR_GetFileInfo returned incorrect size (%d should be %d) for file %s\n",
+ file_info.size, CHUNK_SIZE, pathname);
+ rv = -1;
+ goto cleanup;
+ }
+ if (LL_CMP(file_info.modifyTime, < , file_info1.modifyTime)) {
+ printf(
+ "testfile PR_GetFileInfo returned incorrect modify time: %s\n",
+ pathname);
+ printf("ft = %lld, ft1 = %lld\n",file_info.modifyTime,
+ file_info1.modifyTime);
+ rv = -1;
+ goto cleanup;
+ }
+
+ len = PR_Available(fd_file);
+ if (len < 0) {
+ printf("testfile PR_Available failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ } else if (len != 0) {
+ printf(
+ "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
+ 0, len);
+ rv = -1;
+ goto cleanup;
+ }
+
+ PR_Seek(fd_file, 0, PR_SEEK_SET);
+ len = PR_Available(fd_file);
+ if (len < 0) {
+ printf("testfile PR_Available failed on file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ } else if (len != CHUNK_SIZE) {
+ printf(
+ "testfile PR_Available failed: expected/returned = %d/%d bytes\n",
+ CHUNK_SIZE, len);
+ rv = -1;
+ goto cleanup;
+ }
+ PR_Close(fd_file);
+
+ strcpy(tmpname,pathname);
+ strcat(tmpname,".RENAMED");
+ if (PR_FAILURE == PR_Rename(pathname, tmpname)) {
+ printf("testfile failed to rename file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+
+ fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
+ len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
+ PR_Close(fd_file);
+ if (PR_SUCCESS == PR_Rename(pathname, tmpname)) {
+ printf("testfile renamed to existing file %s\n",pathname);
+ }
+
+ if ((PR_Delete(tmpname)) < 0) {
+ printf("testfile failed to unlink file %s\n",tmpname);
+ rv = -1;
+ }
+
+cleanup:
+ if ((PR_Delete(pathname)) < 0) {
+ printf("testfile failed to unlink file %s\n",pathname);
+ rv = -1;
+ }
+ return rv;
+}
+
+
+static PRInt32 PR_CALLBACK FileTest(void)
+{
+PRDir *fd_dir;
+int i, offset, len, rv = 0;
+PRThread *t;
+PRThreadScope scope;
+File_Rdwr_Param *fparamp;
+
+ /*
+ * Create Test dir
+ */
+ if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
+ printf("testfile failed to create dir %s\n",TEST_DIR);
+ return -1;
+ }
+ fd_dir = PR_OpenDir(TEST_DIR);
+ if (fd_dir == NULL) {
+ printf("testfile failed to open dir %s\n",TEST_DIR);
+ rv = -1;
+ goto cleanup;
+ }
+
+ PR_CloseDir(fd_dir);
+
+ strcat(pathname, TEST_DIR);
+ strcat(pathname, "/");
+ strcat(pathname, FILE_NAME);
+
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ printf(
+ "testfile failed to alloc buffer struct\n");
+ rv = -1;
+ goto cleanup;
+ }
+ out_buf = PR_NEW(buffer);
+ if (out_buf == NULL) {
+ printf(
+ "testfile failed to alloc buffer struct\n");
+ rv = -1;
+ goto cleanup;
+ }
+
+ /*
+ * Start a bunch of writer threads
+ */
+ offset = 0;
+ len = CHUNK_SIZE;
+ PR_EnterMonitor(mon);
+ for (i = 0; i < NUM_RDWR_THREADS; i++) {
+ fparamp = PR_NEW(File_Rdwr_Param);
+ if (fparamp == NULL) {
+ printf(
+ "testfile failed to alloc File_Rdwr_Param struct\n");
+ rv = -1;
+ goto cleanup;
+ }
+ fparamp->pathname = pathname;
+ fparamp->buf = out_buf->data + offset;
+ fparamp->offset = offset;
+ fparamp->len = len;
+ memset(fparamp->buf, i, len);
+
+ t = create_new_thread(PR_USER_THREAD,
+ File_Write, (void *)fparamp,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0, i);
+ offset += len;
+ }
+ thread_count = i;
+ /* Wait for writer threads to exit */
+ while (thread_count) {
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(mon);
+
+
+ /*
+ * Start a bunch of reader threads
+ */
+ offset = 0;
+ len = CHUNK_SIZE;
+ PR_EnterMonitor(mon);
+ for (i = 0; i < NUM_RDWR_THREADS; i++) {
+ fparamp = PR_NEW(File_Rdwr_Param);
+ if (fparamp == NULL) {
+ printf(
+ "testfile failed to alloc File_Rdwr_Param struct\n");
+ rv = -1;
+ goto cleanup;
+ }
+ fparamp->pathname = pathname;
+ fparamp->buf = in_buf->data + offset;
+ fparamp->offset = offset;
+ fparamp->len = len;
+
+ t = create_new_thread(PR_USER_THREAD,
+ File_Read, (void *)fparamp,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_UNJOINABLE_THREAD,
+ 0, i);
+ offset += len;
+ if ((offset + len) > BUF_DATA_SIZE)
+ break;
+ }
+ thread_count = i;
+
+ /* Wait for reader threads to exit */
+ while (thread_count) {
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_ExitMonitor(mon);
+
+ if (memcmp(in_buf->data, out_buf->data, offset) != 0) {
+ printf("File Test failed: file data corrupted\n");
+ rv = -1;
+ goto cleanup;
+ }
+
+ if ((PR_Delete(pathname)) < 0) {
+ printf("testfile failed to unlink file %s\n",pathname);
+ rv = -1;
+ goto cleanup;
+ }
+
+ /*
+ * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
+ */
+ if (Misc_File_Tests(pathname) < 0) {
+ rv = -1;
+ }
+
+cleanup:
+ if ((PR_RmDir(TEST_DIR)) < 0) {
+ printf("testfile failed to rmdir %s\n", TEST_DIR);
+ rv = -1;
+ }
+ return rv;
+}
+
+struct dirtest_arg {
+ PRMonitor *mon;
+ PRInt32 done;
+};
+
+static PRInt32 RunDirTest(void)
+{
+int i;
+PRThread *t;
+PRMonitor *mon;
+struct dirtest_arg thrarg;
+
+ mon = PR_NewMonitor();
+ if (!mon) {
+ printf("RunDirTest: Error - failed to create monitor\n");
+ dirtest_failed = 1;
+ return -1;
+ }
+ thrarg.mon = mon;
+
+ for (i = 0; i < NUM_DIRTEST_THREADS; i++) {
+
+ thrarg.done= 0;
+ t = create_new_thread(PR_USER_THREAD,
+ DirTest, &thrarg,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0, i);
+ if (!t) {
+ printf("RunDirTest: Error - failed to create thread\n");
+ dirtest_failed = 1;
+ return -1;
+ }
+ PR_EnterMonitor(mon);
+ while (!thrarg.done)
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ PR_ExitMonitor(mon);
+
+ }
+ PR_DestroyMonitor(mon);
+ return 0;
+}
+
+static PRInt32 PR_CALLBACK DirTest(void *arg)
+{
+struct dirtest_arg *tinfo = (struct dirtest_arg *) arg;
+PRFileDesc *fd_file;
+PRDir *fd_dir;
+int i;
+int path_len;
+PRDirEntry *dirEntry;
+PRFileInfo info;
+PRInt32 num_files = 0;
+#if defined(XP_PC) && defined(WIN32)
+HANDLE hfile;
+#endif
+
+#define FILES_IN_DIR 20
+
+ /*
+ * Create Test dir
+ */
+ DPRINTF(("Creating test dir %s\n",TEST_DIR));
+ if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
+ printf(
+ "testfile failed to create dir %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ fd_dir = PR_OpenDir(TEST_DIR);
+ if (fd_dir == NULL) {
+ printf(
+ "testfile failed to open dirctory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ strcpy(pathname, TEST_DIR);
+ strcat(pathname, "/");
+ strcat(pathname, FILE_NAME);
+ path_len = strlen(pathname);
+
+ for (i = 0; i < FILES_IN_DIR; i++) {
+
+ sprintf(pathname + path_len,"%d%s",i,"");
+
+ DPRINTF(("Creating test file %s\n",pathname));
+
+ fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
+
+ if (fd_file == NULL) {
+ printf(
+ "testfile failed to create/open file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ PR_Close(fd_file);
+ }
+#if defined(XP_UNIX) || defined(XP_MAC) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
+ /*
+ * Create a hidden file - a platform-dependent operation
+ */
+ strcpy(pathname, TEST_DIR);
+ strcat(pathname, "/");
+ strcat(pathname, HIDDEN_FILE_NAME);
+#if defined(XP_UNIX) || defined(XP_MAC) || defined(XP_BEOS)
+ DPRINTF(("Creating hidden test file %s\n",pathname));
+ fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
+
+ if (fd_file == NULL) {
+ printf(
+ "testfile failed to create/open hidden file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+#if defined(XP_MAC)
+ {
+#include <files.h>
+
+ OSErr err;
+ FCBPBRec fcbpb;
+ CInfoPBRec pb;
+ Str255 pascalMacPath;
+
+ fcbpb.ioNamePtr = pascalMacPath;
+ fcbpb.ioVRefNum = 0;
+ fcbpb.ioRefNum = fd_file->secret->md.osfd;
+ fcbpb.ioFCBIndx = 0;
+
+ err = PBGetFCBInfoSync(&fcbpb);
+ if (err != noErr) {
+ PR_Close(fd_file);
+ return -1;
+ }
+
+ pb.hFileInfo.ioNamePtr = pascalMacPath;
+ pb.hFileInfo.ioVRefNum = fcbpb.ioFCBVRefNum;
+ pb.hFileInfo.ioDirID = fcbpb.ioFCBParID;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ err = PBGetCatInfoSync(&pb);
+ if (err != noErr) {
+ PR_Close(fd_file);
+ return -1;
+ }
+
+ pb.hFileInfo.ioNamePtr = pascalMacPath;
+ pb.hFileInfo.ioVRefNum = fcbpb.ioFCBVRefNum;
+ pb.hFileInfo.ioDirID = fcbpb.ioFCBParID;
+ pb.hFileInfo.ioFDirIndex = 0;
+
+ pb.hFileInfo.ioFlFndrInfo.fdFlags |= fInvisible;
+
+ err = PBSetCatInfoSync(&pb);
+ if (err != noErr) {
+ PR_Close(fd_file);
+ return -1;
+ }
+
+ }
+#endif
+
+ PR_Close(fd_file);
+
+
+#elif defined(XP_PC) && defined(WIN32)
+ DPRINTF(("Creating hidden test file %s\n",pathname));
+ hfile = CreateFile(pathname, GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_HIDDEN,
+ NULL);
+ if (hfile == INVALID_HANDLE_VALUE) {
+ printf("testfile failed to create/open hidden file %s [0, %d]\n",
+ pathname, GetLastError());
+ return -1;
+ }
+ CloseHandle(hfile);
+
+#elif defined(OS2)
+ DPRINTF(("Creating hidden test file %s\n",pathname));
+ fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, (int)FILE_HIDDEN);
+
+ if (fd_file == NULL) {
+ printf("testfile failed to create/open hidden file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ PR_Close(fd_file);
+#endif /* XP _UNIX || XP_MAC*/
+
+#endif /* XP_UNIX || XP_MAC ||(XP_PC && WIN32) */
+
+
+ if (PR_FAILURE == PR_CloseDir(fd_dir))
+ {
+ printf(
+ "testfile failed to close dirctory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ fd_dir = PR_OpenDir(TEST_DIR);
+ if (fd_dir == NULL) {
+ printf(
+ "testfile failed to reopen dirctory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ /*
+ * List all files, including hidden files
+ */
+ DPRINTF(("Listing all files in directory %s\n",TEST_DIR));
+#if defined(XP_UNIX) || defined(XP_MAC) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
+ num_files = FILES_IN_DIR + 1;
+#else
+ num_files = FILES_IN_DIR;
+#endif
+ while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_BOTH)) != NULL) {
+ num_files--;
+ strcpy(pathname, TEST_DIR);
+ strcat(pathname, "/");
+ strcat(pathname, dirEntry->name);
+ DPRINTF(("\t%s\n",dirEntry->name));
+
+ if ((PR_GetFileInfo(pathname, &info)) < 0) {
+ printf(
+ "testfile failed to GetFileInfo file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ if (info.type != PR_FILE_FILE) {
+ printf(
+ "testfile incorrect fileinfo for file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ }
+ if (num_files != 0)
+ {
+ printf(
+ "testfile failed to find all files in directory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ PR_CloseDir(fd_dir);
+
+#if defined(XP_UNIX) || defined(XP_MAC) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS)
+
+ /*
+ * List all files, except hidden files
+ */
+
+ fd_dir = PR_OpenDir(TEST_DIR);
+ if (fd_dir == NULL) {
+ printf(
+ "testfile failed to reopen dirctory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ DPRINTF(("Listing non-hidden files in directory %s\n",TEST_DIR));
+ while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_HIDDEN)) != NULL) {
+ DPRINTF(("\t%s\n",dirEntry->name));
+ if (!strcmp(HIDDEN_FILE_NAME, dirEntry->name)) {
+ printf("testfile found hidden file %s\n", pathname);
+ return -1;
+ }
+
+ }
+ /*
+ * Delete hidden file
+ */
+ strcpy(pathname, TEST_DIR);
+ strcat(pathname, "/");
+ strcat(pathname, HIDDEN_FILE_NAME);
+ if (PR_FAILURE == PR_Delete(pathname)) {
+ printf(
+ "testfile failed to delete hidden file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ PR_CloseDir(fd_dir);
+#endif /* XP_UNIX || XP_MAC || (XP_PC && WIN32) */
+
+ strcpy(renamename, TEST_DIR);
+ strcat(renamename, ".RENAMED");
+ if (PR_FAILURE == PR_Rename(TEST_DIR, renamename)) {
+ printf(
+ "testfile failed to rename directory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ if (PR_FAILURE == PR_MkDir(TEST_DIR, 0777)) {
+ printf(
+ "testfile failed to recreate dir %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ if (PR_SUCCESS == PR_Rename(renamename, TEST_DIR)) {
+ printf(
+ "testfile renamed directory to existing name %s\n",
+ renamename);
+ return -1;
+ }
+
+ if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
+ printf(
+ "testfile failed to rmdir %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ if (PR_FAILURE == PR_Rename(renamename, TEST_DIR)) {
+ printf(
+ "testfile failed to rename directory %s [%d, %d]\n",
+ renamename, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ fd_dir = PR_OpenDir(TEST_DIR);
+ if (fd_dir == NULL) {
+ printf(
+ "testfile failed to reopen directory %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+
+ strcpy(pathname, TEST_DIR);
+ strcat(pathname, "/");
+ strcat(pathname, FILE_NAME);
+ path_len = strlen(pathname);
+
+ for (i = 0; i < FILES_IN_DIR; i++) {
+
+ sprintf(pathname + path_len,"%d%s",i,"");
+
+ if (PR_FAILURE == PR_Delete(pathname)) {
+ printf(
+ "testfile failed to delete file %s [%d, %d]\n",
+ pathname, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ }
+
+ PR_CloseDir(fd_dir);
+
+ if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
+ printf(
+ "testfile failed to rmdir %s [%d, %d]\n",
+ TEST_DIR, PR_GetError(), PR_GetOSError());
+ return -1;
+ }
+ PR_EnterMonitor(tinfo->mon);
+ tinfo->done = 1;
+ PR_Notify(tinfo->mon);
+ PR_ExitMonitor(tinfo->mon);
+
+ return 0;
+}
+/************************************************************************/
+
+/*
+ * Test file and directory NSPR APIs
+ */
+
+int main(int argc, char **argv)
+{
+#ifdef WIN32
+ PRUint32 len;
+#endif
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ int opt;
+ extern char *optarg;
+ extern int optind;
+#endif
+#if defined(XP_UNIX) || defined(XP_OS2_EMX)
+ while ((opt = getopt(argc, argv, "d")) != EOF) {
+ switch(opt) {
+ case 'd':
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("testfile.log");
+#endif
+
+ mon = PR_NewMonitor();
+ if (mon == NULL) {
+ printf("testfile: PR_NewMonitor failed\n");
+ exit(2);
+ }
+#ifdef WIN32
+ len = GetTempPath(TMPDIR_LEN, testdir);
+ if ((len > 0) && (len < (TMPDIR_LEN - 6))) {
+ /*
+ * enough space for prdir
+ */
+ strcpy((testdir + len),"prdir");
+ TEST_DIR = testdir;
+ printf("TEST_DIR = %s\n",TEST_DIR);
+ }
+
+#endif
+
+ if (FileTest() < 0) {
+ printf("File Test failed\n");
+ exit(2);
+ }
+ printf("File Test passed\n");
+ if ((RunDirTest() < 0) || dirtest_failed) {
+ printf("Dir Test failed\n");
+ exit(2);
+ }
+ printf("Dir Test passed\n");
+
+ PR_DestroyMonitor(mon);
+ PR_Cleanup();
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/threads.c b/src/libs/xpcom18a4/nsprpub/pr/tests/threads.c
new file mode 100644
index 00000000..e1d188d4
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/threads.c
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+#include "prinrval.h"
+#include "plgetopt.h"
+#include "pprthred.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+PRMonitor *mon;
+PRInt32 count, iterations, alive;
+
+PRBool debug_mode = PR_FALSE, passed = PR_TRUE;
+
+void
+PR_CALLBACK
+ReallyDumbThread(void *arg)
+{
+ return;
+}
+
+void
+PR_CALLBACK
+DumbThread(void *arg)
+{
+ PRInt32 tmp = (PRInt32)arg;
+ PRThreadScope scope = (PRThreadScope)tmp;
+ PRThread *thr;
+
+ thr = PR_CreateThread(PR_USER_THREAD,
+ ReallyDumbThread,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ scope,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ if (!thr) {
+ if (debug_mode) {
+ printf("Could not create really dumb thread (%d, %d)!\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ passed = PR_FALSE;
+ } else {
+ PR_JoinThread(thr);
+ }
+ PR_EnterMonitor(mon);
+ alive--;
+ PR_Notify(mon);
+ PR_ExitMonitor(mon);
+}
+
+static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2)
+{
+ PRThread *thr;
+ int n;
+
+ alive = 0;
+ mon = PR_NewMonitor();
+
+ alive = count;
+ for (n=0; n<count; n++) {
+ thr = PR_CreateThread(PR_USER_THREAD,
+ DumbThread,
+ (void *)scope2,
+ PR_PRIORITY_NORMAL,
+ scope1,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (!thr) {
+ if (debug_mode) {
+ printf("Could not create dumb thread (%d, %d)!\n",
+ PR_GetError(), PR_GetOSError());
+ }
+ passed = PR_FALSE;
+ alive--;
+ }
+
+ PR_Sleep(0);
+ }
+
+ /* Wait for all threads to exit */
+ PR_EnterMonitor(mon);
+ while (alive) {
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ PR_ExitMonitor(mon);
+ PR_DestroyMonitor(mon);
+}
+
+static void CreateThreadsUU(void)
+{
+ CreateThreads(PR_LOCAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void CreateThreadsUK(void)
+{
+ CreateThreads(PR_LOCAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+static void CreateThreadsKU(void)
+{
+ CreateThreads(PR_GLOBAL_THREAD, PR_LOCAL_THREAD);
+}
+
+static void CreateThreadsKK(void)
+{
+ CreateThreads(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD);
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ if (debug_mode)
+ {
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+ printf("%40s: %6.2f usec\n", msg, d / count);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int index;
+
+ PR_STDIO_INIT();
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_HIGH, 0);
+
+ {
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dc:i:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'c': /* loop counter */
+ count = atoi(opt->value);
+ break;
+ case 'i': /* loop counter */
+ iterations = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("threads.log");
+ count = 10;
+ iterations = 10;
+ debug_mode = PR_TRUE;
+#else
+ if (0 == count) count = 50;
+ if (0 == iterations) iterations = 10;
+
+#endif
+
+ if (debug_mode)
+ {
+ printf("\
+** Tests lots of thread creations. \n\
+** Create %ld native threads %ld times. \n\
+** Create %ld user threads %ld times \n", iterations,count,iterations,count);
+ }
+
+ for (index=0; index<iterations; index++) {
+ Measure(CreateThreadsUU, "Create user/user threads");
+ Measure(CreateThreadsUK, "Create user/native threads");
+ Measure(CreateThreadsKU, "Create native/user threads");
+ Measure(CreateThreadsKK, "Create native/native threads");
+ }
+
+ if (debug_mode) printf("\nNow switch to recycling threads \n\n");
+ PR_SetThreadRecycleMode(1);
+
+ for (index=0; index<iterations; index++) {
+ Measure(CreateThreadsUU, "Create user/user threads");
+ Measure(CreateThreadsUK, "Create user/native threads");
+ Measure(CreateThreadsKU, "Create native/user threads");
+ Measure(CreateThreadsKK, "Create native/native threads");
+ }
+
+
+ printf("%s\n", ((passed) ? "PASS" : "FAIL"));
+
+ PR_Cleanup();
+
+ if (passed) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_client.c b/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_client.c
new file mode 100644
index 00000000..9f6ceb69
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_client.c
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: thrpool_client.c
+**
+** Description: Test threadpool functionality.
+**
+** Modification History:
+*/
+#include "primpl.h"
+
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef XP_UNIX
+#include <sys/mman.h>
+#endif
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include <pthread.h>
+#endif
+
+#ifdef WIN32
+#include <process.h>
+#endif
+
+static int _debug_on = 0;
+static int server_port = -1;
+static char *program_name = NULL;
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "prsem.h"
+int fprintf(FILE *stream, const char *fmt, ...)
+{
+ PR_LogPrint(fmt);
+ return 0;
+}
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#else
+#include "obsolete/prsem.h"
+#endif
+
+#ifdef XP_PC
+#define mode_t int
+#endif
+
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+#define BUF_DATA_SIZE (2 * 1024)
+#define TCP_MESG_SIZE 1024
+#define NUM_TCP_CLIENTS 10 /* for a listen queue depth of 5 */
+
+#define NUM_TCP_CONNECTIONS_PER_CLIENT 10
+#define NUM_TCP_MESGS_PER_CONNECTION 10
+#define TCP_SERVER_PORT 10000
+
+static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
+static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
+static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
+static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
+
+int failed_already=0;
+
+typedef struct buffer {
+ char data[BUF_DATA_SIZE];
+} buffer;
+
+PRNetAddr tcp_server_addr, udp_server_addr;
+
+typedef struct Client_Param {
+ PRNetAddr server_addr;
+ PRMonitor *exit_mon; /* monitor to signal on exit */
+ PRInt32 *exit_counter; /* counter to decrement, before exit */
+ PRInt32 datalen;
+} Client_Param;
+
+/*
+ * readn
+ * read data from sockfd into buf
+ */
+static PRInt32
+readn(PRFileDesc *sockfd, char *buf, int len)
+{
+ int rem;
+ int bytes;
+ int offset = 0;
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
+
+ for (rem=len; rem; offset += bytes, rem -= bytes) {
+ DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
+ PR_GetCurrentThread(), rem));
+ bytes = PR_Recv(sockfd, buf + offset, rem, 0,
+ timeout);
+ DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
+ PR_GetCurrentThread(), bytes));
+ if (bytes < 0) {
+ return -1;
+ }
+ }
+ return len;
+}
+
+/*
+ * writen
+ * write data from buf to sockfd
+ */
+static PRInt32
+writen(PRFileDesc *sockfd, char *buf, int len)
+{
+ int rem;
+ int bytes;
+ int offset = 0;
+
+ for (rem=len; rem; offset += bytes, rem -= bytes) {
+ DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
+ PR_GetCurrentThread(), rem));
+ bytes = PR_Send(sockfd, buf + offset, rem, 0,
+ PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
+ PR_GetCurrentThread(), bytes));
+ if (bytes <= 0)
+ return -1;
+ }
+ return len;
+}
+
+/*
+ * TCP_Client
+ * Client job
+ * Connect to the server at the address specified in the argument.
+ * Fill in a buffer, write data to server, read it back and check
+ * for data corruption.
+ * Close the socket for server connection
+ */
+static void PR_CALLBACK
+TCP_Client(void *arg)
+{
+ Client_Param *cp = (Client_Param *) arg;
+ PRFileDesc *sockfd;
+ buffer *in_buf, *out_buf;
+ union PRNetAddr netaddr;
+ PRInt32 bytes, i, j;
+
+
+ DPRINTF(("TCP client started\n"));
+ bytes = cp->datalen;
+ out_buf = PR_NEW(buffer);
+ if (out_buf == NULL) {
+ fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name);
+ failed_already=1;
+ return;
+ }
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name);
+ failed_already=1;
+ return;
+ }
+ netaddr.inet.family = cp->server_addr.inet.family;
+ netaddr.inet.port = cp->server_addr.inet.port;
+ netaddr.inet.ip = cp->server_addr.inet.ip;
+
+ for (i = 0; i < num_tcp_connections_per_client; i++) {
+ if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) {
+ fprintf(stderr,"%s: PR_OpenTCPSocket failed\n", program_name);
+ failed_already=1;
+ return;
+ }
+
+ DPRINTF(("TCP client connecting to server:%d\n", server_port));
+ if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
+ fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
+ PR_GetError(), PR_GetOSError());
+ failed_already=1;
+ return;
+ }
+ for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
+ /*
+ * fill in random data
+ */
+ memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
+ /*
+ * write to server
+ */
+ if (writen(sockfd, out_buf->data, bytes) < bytes) {
+ fprintf(stderr,"%s: ERROR - TCP_Client:writen\n", program_name);
+ failed_already=1;
+ return;
+ }
+ /*
+ DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
+ PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
+ */
+ if (readn(sockfd, in_buf->data, bytes) < bytes) {
+ fprintf(stderr,"%s: ERROR - TCP_Client:readn\n", program_name);
+ failed_already=1;
+ return;
+ }
+ /*
+ * verify the data read
+ */
+ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
+ fprintf(stderr,"%s: ERROR - data corruption\n", program_name);
+ failed_already=1;
+ return;
+ }
+ }
+ /*
+ * shutdown reads and writes
+ */
+ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
+ fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name);
+ failed_already=1;
+ }
+ PR_Close(sockfd);
+ }
+
+ PR_DELETE(out_buf);
+ PR_DELETE(in_buf);
+
+ /*
+ * Decrement exit_counter and notify parent thread
+ */
+
+ PR_EnterMonitor(cp->exit_mon);
+ --(*cp->exit_counter);
+ PR_Notify(cp->exit_mon);
+ PR_ExitMonitor(cp->exit_mon);
+ DPRINTF(("TCP_Client exiting\n"));
+}
+
+/*
+ * TCP_Socket_Client_Server_Test - concurrent server test
+ *
+ * Each client connects to the server and sends a chunk of data
+ * For each connection, server reads the data
+ * from the client and sends it back to the client, unmodified.
+ * Each client checks that data received from server is same as the
+ * data it sent to the server.
+ *
+ */
+
+static PRInt32
+TCP_Socket_Client_Server_Test(void)
+{
+ int i;
+ Client_Param *cparamp;
+ PRMonitor *mon2;
+ PRInt32 datalen;
+ PRInt32 connections = 0;
+ PRThread *thr;
+
+ datalen = tcp_mesg_size;
+ connections = 0;
+
+ mon2 = PR_NewMonitor();
+ if (mon2 == NULL) {
+ fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name);
+ failed_already=1;
+ return -1;
+ }
+
+ /*
+ * Start client jobs
+ */
+ cparamp = PR_NEW(Client_Param);
+ if (cparamp == NULL) {
+ fprintf(stderr,"%s: PR_NEW failed\n", program_name);
+ failed_already=1;
+ return -1;
+ }
+ cparamp->server_addr.inet.family = PR_AF_INET;
+ cparamp->server_addr.inet.port = PR_htons(server_port);
+ cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
+ cparamp->exit_mon = mon2;
+ cparamp->exit_counter = &connections;
+ cparamp->datalen = datalen;
+ for (i = 0; i < num_tcp_clients; i++) {
+ thr = PR_CreateThread(PR_USER_THREAD, TCP_Client, (void *)cparamp,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
+ if (NULL == thr) {
+ fprintf(stderr,"%s: PR_CreateThread failed\n", program_name);
+ failed_already=1;
+ return -1;
+ }
+ PR_EnterMonitor(mon2);
+ connections++;
+ PR_ExitMonitor(mon2);
+ DPRINTF(("Created TCP client = 0x%lx\n", thr));
+ }
+ /* Wait for client jobs to exit */
+ PR_EnterMonitor(mon2);
+ while (0 != connections) {
+ PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("Client job count = %d\n", connections));
+ }
+ PR_ExitMonitor(mon2);
+ printf("%30s","TCP_Socket_Client_Server_Test:");
+ printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
+ num_tcp_clients, num_tcp_connections_per_client);
+ printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
+ num_tcp_mesgs_per_connection, tcp_mesg_size);
+
+ PR_DELETE(cparamp);
+ return 0;
+}
+
+/************************************************************************/
+
+int
+main(int argc, char **argv)
+{
+ /*
+ * -d debug mode
+ */
+ PLOptStatus os;
+ PLOptState *opt;
+ program_name = argv[0];
+
+ opt = PL_CreateOptState(argc, argv, "dp:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ case 'p':
+ server_port = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("socket.log");
+#endif
+ PR_SetConcurrency(4);
+
+ TCP_Socket_Client_Server_Test();
+
+ PR_Cleanup();
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_server.c b/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_server.c
new file mode 100644
index 00000000..cafa67ad
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_server.c
@@ -0,0 +1,607 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/***********************************************************************
+**
+** Name: thrpool.c
+**
+** Description: Test threadpool functionality.
+**
+** Modification History:
+*/
+#include "primpl.h"
+
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#ifdef XP_UNIX
+#include <sys/mman.h>
+#endif
+#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
+#include <pthread.h>
+#endif
+
+/* for getcwd */
+#if defined(XP_UNIX) || defined (XP_OS2_EMX) || defined(XP_BEOS)
+#include <unistd.h>
+#elif defined(XP_PC)
+#include <direct.h>
+#endif
+
+#ifdef WIN32
+#include <process.h>
+#endif
+
+static int _debug_on = 0;
+static char *program_name = NULL;
+static void serve_client_write(void *arg);
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "prsem.h"
+int fprintf(FILE *stream, const char *fmt, ...)
+{
+ PR_LogPrint(fmt);
+ return 0;
+}
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#else
+#include "obsolete/prsem.h"
+#endif
+
+#ifdef XP_PC
+#define mode_t int
+#endif
+
+#define DPRINTF(arg) if (_debug_on) printf arg
+
+
+#define BUF_DATA_SIZE (2 * 1024)
+#define TCP_MESG_SIZE 1024
+#define NUM_TCP_CLIENTS 10 /* for a listen queue depth of 5 */
+
+
+#define NUM_TCP_CONNECTIONS_PER_CLIENT 10
+#define NUM_TCP_MESGS_PER_CONNECTION 10
+#define TCP_SERVER_PORT 10000
+#define SERVER_MAX_BIND_COUNT 100
+
+static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
+static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
+static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
+static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
+static void TCP_Server_Accept(void *arg);
+
+
+int failed_already=0;
+typedef struct buffer {
+ char data[BUF_DATA_SIZE];
+} buffer;
+
+
+typedef struct Server_Param {
+ PRJobIoDesc iod; /* socket to read from/write to */
+ PRInt32 datalen; /* bytes of data transfered in each read/write */
+ PRNetAddr netaddr;
+ PRMonitor *exit_mon; /* monitor to signal on exit */
+ PRInt32 *job_counterp; /* counter to decrement, before exit */
+ PRInt32 conn_counter; /* counter to decrement, before exit */
+ PRThreadPool *tp;
+} Server_Param;
+
+typedef struct Serve_Client_Param {
+ PRJobIoDesc iod; /* socket to read from/write to */
+ PRInt32 datalen; /* bytes of data transfered in each read/write */
+ PRMonitor *exit_mon; /* monitor to signal on exit */
+ PRInt32 *job_counterp; /* counter to decrement, before exit */
+ PRThreadPool *tp;
+} Serve_Client_Param;
+
+typedef struct Session {
+ PRJobIoDesc iod; /* socket to read from/write to */
+ buffer *in_buf;
+ PRInt32 bytes;
+ PRInt32 msg_num;
+ PRInt32 bytes_read;
+ PRMonitor *exit_mon; /* monitor to signal on exit */
+ PRInt32 *job_counterp; /* counter to decrement, before exit */
+ PRThreadPool *tp;
+} Session;
+
+static void
+serve_client_read(void *arg)
+{
+ Session *sp = (Session *) arg;
+ int rem;
+ int bytes;
+ int offset;
+ PRFileDesc *sockfd;
+ char *buf;
+ PRJob *jobp;
+
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
+
+ sockfd = sp->iod.socket;
+ buf = sp->in_buf->data;
+
+ PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection);
+ PR_ASSERT(sp->bytes_read < sp->bytes);
+
+ offset = sp->bytes_read;
+ rem = sp->bytes - offset;
+ bytes = PR_Recv(sockfd, buf + offset, rem, 0, timeout);
+ if (bytes < 0) {
+ return;
+ }
+ sp->bytes_read += bytes;
+ sp->iod.timeout = PR_SecondsToInterval(60);
+ if (sp->bytes_read < sp->bytes) {
+ jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ return;
+ }
+ PR_ASSERT(sp->bytes_read == sp->bytes);
+ DPRINTF(("serve_client: read complete, msg(%d) \n", sp->msg_num));
+
+ sp->iod.timeout = PR_SecondsToInterval(60);
+ jobp = PR_QueueJob_Write(sp->tp, &sp->iod, serve_client_write, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+
+ return;
+}
+
+static void
+serve_client_write(void *arg)
+{
+ Session *sp = (Session *) arg;
+ int bytes;
+ PRFileDesc *sockfd;
+ char *buf;
+ PRJob *jobp;
+
+ sockfd = sp->iod.socket;
+ buf = sp->in_buf->data;
+
+ PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection);
+
+ bytes = PR_Send(sockfd, buf, sp->bytes, 0, PR_INTERVAL_NO_TIMEOUT);
+ PR_ASSERT(bytes == sp->bytes);
+
+ if (bytes < 0) {
+ return;
+ }
+ DPRINTF(("serve_client: write complete, msg(%d) \n", sp->msg_num));
+ sp->msg_num++;
+ if (sp->msg_num < num_tcp_mesgs_per_connection) {
+ sp->bytes_read = 0;
+ sp->iod.timeout = PR_SecondsToInterval(60);
+ jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ return;
+ }
+
+ DPRINTF(("serve_client: read/write complete, msg(%d) \n", sp->msg_num));
+ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
+ fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name);
+ }
+
+ PR_Close(sockfd);
+ PR_EnterMonitor(sp->exit_mon);
+ --(*sp->job_counterp);
+ PR_Notify(sp->exit_mon);
+ PR_ExitMonitor(sp->exit_mon);
+
+ PR_DELETE(sp->in_buf);
+ PR_DELETE(sp);
+
+ return;
+}
+
+/*
+ * Serve_Client
+ * Thread, started by the server, for serving a client connection.
+ * Reads data from socket and writes it back, unmodified, and
+ * closes the socket
+ */
+static void PR_CALLBACK
+Serve_Client(void *arg)
+{
+ Serve_Client_Param *scp = (Serve_Client_Param *) arg;
+ buffer *in_buf;
+ Session *sp;
+ PRJob *jobp;
+
+ sp = PR_NEW(Session);
+ sp->iod = scp->iod;
+
+ in_buf = PR_NEW(buffer);
+ if (in_buf == NULL) {
+ fprintf(stderr,"%s: failed to alloc buffer struct\n",program_name);
+ failed_already=1;
+ return;
+ }
+
+ sp->in_buf = in_buf;
+ sp->bytes = scp->datalen;
+ sp->msg_num = 0;
+ sp->bytes_read = 0;
+ sp->tp = scp->tp;
+ sp->exit_mon = scp->exit_mon;
+ sp->job_counterp = scp->job_counterp;
+
+ sp->iod.timeout = PR_SecondsToInterval(60);
+ jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ PR_DELETE(scp);
+}
+
+static void
+print_stats(void *arg)
+{
+ Server_Param *sp = (Server_Param *) arg;
+ PRThreadPool *tp = sp->tp;
+ PRInt32 counter;
+ PRJob *jobp;
+
+ PR_EnterMonitor(sp->exit_mon);
+ counter = (*sp->job_counterp);
+ PR_ExitMonitor(sp->exit_mon);
+
+ printf("PRINT_STATS: #client connections = %d\n",counter);
+
+
+ jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500),
+ print_stats, sp, PR_FALSE);
+
+ PR_ASSERT(NULL != jobp);
+}
+
+static int job_counter = 0;
+/*
+ * TCP Server
+ * Server binds an address to a socket, starts a client process and
+ * listens for incoming connections.
+ * Each client connects to the server and sends a chunk of data
+ * Starts a Serve_Client job for each incoming connection, to read
+ * the data from the client and send it back to the client, unmodified.
+ * Each client checks that data received from server is same as the
+ * data it sent to the server.
+ * Finally, the threadpool is shutdown
+ */
+static void PR_CALLBACK
+TCP_Server(void *arg)
+{
+ PRThreadPool *tp = (PRThreadPool *) arg;
+ Server_Param *sp;
+ PRFileDesc *sockfd;
+ PRNetAddr netaddr;
+ PRMonitor *sc_mon;
+ PRJob *jobp;
+ int i;
+ PRStatus rval;
+
+ /*
+ * Create a tcp socket
+ */
+ if ((sockfd = PR_NewTCPSocket()) == NULL) {
+ fprintf(stderr,"%s: PR_NewTCPSocket failed\n", program_name);
+ return;
+ }
+ memset(&netaddr, 0 , sizeof(netaddr));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons(TCP_SERVER_PORT);
+ netaddr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ /*
+ * try a few times to bind server's address, if addresses are in
+ * use
+ */
+ i = 0;
+ while (PR_Bind(sockfd, &netaddr) < 0) {
+ if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
+ netaddr.inet.port += 2;
+ if (i++ < SERVER_MAX_BIND_COUNT)
+ continue;
+ }
+ fprintf(stderr,"%s: ERROR - PR_Bind failed\n", program_name);
+ perror("PR_Bind");
+ failed_already=1;
+ return;
+ }
+
+ if (PR_Listen(sockfd, 32) < 0) {
+ fprintf(stderr,"%s: ERROR - PR_Listen failed\n", program_name);
+ failed_already=1;
+ return;
+ }
+
+ if (PR_GetSockName(sockfd, &netaddr) < 0) {
+ fprintf(stderr,"%s: ERROR - PR_GetSockName failed\n", program_name);
+ failed_already=1;
+ return;
+ }
+
+ DPRINTF((
+ "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
+ netaddr.inet.ip, netaddr.inet.port));
+
+ sp = PR_NEW(Server_Param);
+ if (sp == NULL) {
+ fprintf(stderr,"%s: PR_NEW failed\n", program_name);
+ failed_already=1;
+ return;
+ }
+ sp->iod.socket = sockfd;
+ sp->iod.timeout = PR_SecondsToInterval(60);
+ sp->datalen = tcp_mesg_size;
+ sp->exit_mon = sc_mon;
+ sp->job_counterp = &job_counter;
+ sp->conn_counter = 0;
+ sp->tp = tp;
+ sp->netaddr = netaddr;
+
+ /* create and cancel an io job */
+ jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ rval = PR_CancelJob(jobp);
+ PR_ASSERT(PR_SUCCESS == rval);
+
+ /*
+ * create the client process
+ */
+ {
+#define MAX_ARGS 4
+ char *argv[MAX_ARGS + 1];
+ int index = 0;
+ char port[32];
+ char path[1024 + sizeof("/thrpool_client")];
+ (void)getcwd(path, sizeof(path));
+ (void)strcat(path, "/thrpool_client");
+#ifdef XP_PC
+ (void)strcat(path, ".exe");
+#endif
+ argv[index++] = path;
+ sprintf(port,"%d",PR_ntohs(netaddr.inet.port));
+ if (_debug_on)
+ {
+ argv[index++] = "-d";
+ argv[index++] = "-p";
+ argv[index++] = port;
+ argv[index++] = NULL;
+ } else {
+ argv[index++] = "-p";
+ argv[index++] = port;
+ argv[index++] = NULL;
+ }
+ PR_ASSERT(MAX_ARGS >= (index - 1));
+
+ DPRINTF(("creating client process %s ...\n", path));
+ if (PR_FAILURE == PR_CreateProcessDetached(path, argv, NULL, NULL)) {
+ fprintf(stderr,
+ "thrpool_server: ERROR - PR_CreateProcessDetached failed\n");
+ failed_already=1;
+ return;
+ }
+ }
+
+ sc_mon = PR_NewMonitor();
+ if (sc_mon == NULL) {
+ fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name);
+ failed_already=1;
+ return;
+ }
+
+ sp->iod.socket = sockfd;
+ sp->iod.timeout = PR_SecondsToInterval(60);
+ sp->datalen = tcp_mesg_size;
+ sp->exit_mon = sc_mon;
+ sp->job_counterp = &job_counter;
+ sp->conn_counter = 0;
+ sp->tp = tp;
+ sp->netaddr = netaddr;
+
+ /* create and cancel a timer job */
+ jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(5000),
+ print_stats, sp, PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ rval = PR_CancelJob(jobp);
+ PR_ASSERT(PR_SUCCESS == rval);
+
+ DPRINTF(("TCP_Server: Accepting connections \n"));
+
+ jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ return;
+}
+
+static void
+TCP_Server_Accept(void *arg)
+{
+ Server_Param *sp = (Server_Param *) arg;
+ PRThreadPool *tp = sp->tp;
+ Serve_Client_Param *scp;
+ PRFileDesc *newsockfd;
+ PRJob *jobp;
+
+ if ((newsockfd = PR_Accept(sp->iod.socket, &sp->netaddr,
+ PR_INTERVAL_NO_TIMEOUT)) == NULL) {
+ fprintf(stderr,"%s: ERROR - PR_Accept failed\n", program_name);
+ failed_already=1;
+ goto exit;
+ }
+ scp = PR_NEW(Serve_Client_Param);
+ if (scp == NULL) {
+ fprintf(stderr,"%s: PR_NEW failed\n", program_name);
+ failed_already=1;
+ goto exit;
+ }
+
+ /*
+ * Start a Serve_Client job for each incoming connection
+ */
+ scp->iod.socket = newsockfd;
+ scp->iod.timeout = PR_SecondsToInterval(60);
+ scp->datalen = tcp_mesg_size;
+ scp->exit_mon = sp->exit_mon;
+ scp->job_counterp = sp->job_counterp;
+ scp->tp = sp->tp;
+
+ PR_EnterMonitor(sp->exit_mon);
+ (*sp->job_counterp)++;
+ PR_ExitMonitor(sp->exit_mon);
+ jobp = PR_QueueJob(tp, Serve_Client, scp,
+ PR_FALSE);
+
+ PR_ASSERT(NULL != jobp);
+ DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", jobp));
+
+ /*
+ * single-threaded update; no lock needed
+ */
+ sp->conn_counter++;
+ if (sp->conn_counter <
+ (num_tcp_clients * num_tcp_connections_per_client)) {
+ jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp,
+ PR_FALSE);
+ PR_ASSERT(NULL != jobp);
+ return;
+ }
+ jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500),
+ print_stats, sp, PR_FALSE);
+
+ PR_ASSERT(NULL != jobp);
+ DPRINTF(("TCP_Server: Created print_stats timer job = 0x%lx\n", jobp));
+
+exit:
+ PR_EnterMonitor(sp->exit_mon);
+ /* Wait for server jobs to finish */
+ while (0 != *sp->job_counterp) {
+ PR_Wait(sp->exit_mon, PR_INTERVAL_NO_TIMEOUT);
+ DPRINTF(("TCP_Server: conn_counter = %d\n",
+ *sp->job_counterp));
+ }
+
+ PR_ExitMonitor(sp->exit_mon);
+ if (sp->iod.socket) {
+ PR_Close(sp->iod.socket);
+ }
+ PR_DestroyMonitor(sp->exit_mon);
+ printf("%30s","TCP_Socket_Client_Server_Test:");
+ printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
+ num_tcp_clients, num_tcp_connections_per_client);
+ printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
+ num_tcp_mesgs_per_connection, tcp_mesg_size);
+
+ DPRINTF(("%s: calling PR_ShutdownThreadPool\n", program_name));
+ PR_ShutdownThreadPool(sp->tp);
+ PR_DELETE(sp);
+}
+
+/************************************************************************/
+
+#define DEFAULT_INITIAL_THREADS 4
+#define DEFAULT_MAX_THREADS 100
+#define DEFAULT_STACKSIZE (512 * 1024)
+
+int
+main(int argc, char **argv)
+{
+ PRInt32 initial_threads = DEFAULT_INITIAL_THREADS;
+ PRInt32 max_threads = DEFAULT_MAX_THREADS;
+ PRInt32 stacksize = DEFAULT_STACKSIZE;
+ PRThreadPool *tp = NULL;
+ PRStatus rv;
+ PRJob *jobp;
+
+ /*
+ * -d debug mode
+ */
+ PLOptStatus os;
+ PLOptState *opt;
+
+ program_name = argv[0];
+ opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("socket.log");
+#endif
+ PR_SetConcurrency(4);
+
+ tp = PR_CreateThreadPool(initial_threads, max_threads, stacksize);
+ if (NULL == tp) {
+ printf("PR_CreateThreadPool failed\n");
+ failed_already=1;
+ goto done;
+ }
+ jobp = PR_QueueJob(tp, TCP_Server, tp, PR_TRUE);
+ rv = PR_JoinJob(jobp);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ DPRINTF(("%s: calling PR_JoinThreadPool\n", program_name));
+ rv = PR_JoinThreadPool(tp);
+ PR_ASSERT(PR_SUCCESS == rv);
+ DPRINTF(("%s: returning from PR_JoinThreadPool\n", program_name));
+
+done:
+ PR_Cleanup();
+ if (failed_already) return 1;
+ else return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/thruput.c b/src/libs/xpcom18a4/nsprpub/pr/tests/thruput.c
new file mode 100644
index 00000000..e6319dbe
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/thruput.c
@@ -0,0 +1,412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: thruput.c
+** Description: Test server's throughput capability comparing various
+** implmentation strategies.
+**
+** Note: Requires a server machine and an aribitrary number of
+** clients to bang on it. Trust the numbers on the server
+** more than those being displayed by the various clients.
+*/
+
+#include "prerror.h"
+#include "prinrval.h"
+#include "prinit.h"
+#include "prio.h"
+#include "prlock.h"
+#include "prmem.h"
+#include "prnetdb.h"
+#include "prprf.h"
+#include "prthread.h"
+
+#include "pprio.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#define ADDR_BUFFER 100
+#define PORT_NUMBER 51877
+#define SAMPLING_INTERVAL 10
+#define BUFFER_SIZE (32 * 1024)
+
+static PRInt32 domain = PR_AF_INET;
+static PRInt32 protocol = 6; /* TCP */
+static PRFileDesc *err = NULL;
+static PRIntn concurrency = 1;
+static PRInt32 xport_buffer = -1;
+static PRUint32 initial_streams = 1;
+static PRInt32 buffer_size = BUFFER_SIZE;
+static PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+typedef struct Shared
+{
+ PRLock *ml;
+ PRUint32 sampled;
+ PRUint32 threads;
+ PRIntervalTime timein;
+ PRNetAddr server_address;
+} Shared;
+
+static Shared *shared = NULL;
+
+static PRStatus PrintAddress(const PRNetAddr* address)
+{
+ char buffer[ADDR_BUFFER];
+ PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));
+ if (PR_SUCCESS == rv)
+ PR_fprintf(err, "%s:%u\n", buffer, PR_ntohs(address->inet.port));
+ else PL_FPrintError(err, "PR_NetAddrToString");
+ return rv;
+} /* PrintAddress */
+
+
+static void PR_CALLBACK Clientel(void *arg)
+{
+ PRStatus rv;
+ PRFileDesc *xport;
+ PRInt32 bytes, sampled;
+ PRIntervalTime now, interval;
+ PRBool do_display = PR_FALSE;
+ Shared *shared = (Shared*)arg;
+ char *buffer = (char*)PR_Malloc(buffer_size);
+ PRNetAddr *server_address = &shared->server_address;
+ PRIntervalTime connect_timeout = PR_SecondsToInterval(5);
+ PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL);
+
+ PR_fprintf(err, "Client connecting to ");
+ (void)PrintAddress(server_address);
+
+ do
+ {
+ xport = PR_Socket(domain, PR_SOCK_STREAM, protocol);
+ if (NULL == xport)
+ {
+ PL_FPrintError(err, "PR_Socket");
+ return;
+ }
+
+ if (xport_buffer != -1)
+ {
+ PRSocketOptionData data;
+ data.option = PR_SockOpt_RecvBufferSize;
+ data.value.recv_buffer_size = (PRSize)xport_buffer;
+ rv = PR_SetSocketOption(xport, &data);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err, "PR_SetSocketOption - ignored");
+ data.option = PR_SockOpt_SendBufferSize;
+ data.value.send_buffer_size = (PRSize)xport_buffer;
+ rv = PR_SetSocketOption(xport, &data);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err, "PR_SetSocketOption - ignored");
+ }
+
+ rv = PR_Connect(xport, server_address, connect_timeout);
+ if (PR_FAILURE == rv)
+ {
+ PL_FPrintError(err, "PR_Connect");
+ if (PR_IO_TIMEOUT_ERROR != PR_GetError())
+ PR_Sleep(connect_timeout);
+ PR_Close(xport); /* delete it and start over */
+ }
+ } while (PR_FAILURE == rv);
+
+ do
+ {
+ bytes = PR_Recv(
+ xport, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT);
+ PR_Lock(shared->ml);
+ now = PR_IntervalNow();
+ shared->sampled += bytes;
+ interval = now - shared->timein;
+ if (interval > sampling_interval)
+ {
+ sampled = shared->sampled;
+ shared->timein = now;
+ shared->sampled = 0;
+ do_display = PR_TRUE;
+ }
+ PR_Unlock(shared->ml);
+
+ if (do_display)
+ {
+ PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval);
+ PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate);
+ do_display = PR_FALSE;
+ }
+
+ } while (bytes > 0);
+} /* Clientel */
+
+static void Client(const char *server_name)
+{
+ PRStatus rv;
+ PRHostEnt host;
+ char buffer[PR_NETDB_BUF_SIZE];
+ PRIntervalTime dally = PR_SecondsToInterval(60);
+ PR_fprintf(err, "Translating the name %s\n", server_name);
+ rv = PR_GetHostByName(server_name, buffer, sizeof(buffer), &host);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err, "PR_GetHostByName");
+ else
+ {
+ if (PR_EnumerateHostEnt(
+ 0, &host, PORT_NUMBER, &shared->server_address) < 0)
+ PL_FPrintError(err, "PR_EnumerateHostEnt");
+ else
+ {
+ do
+ {
+ shared->threads += 1;
+ (void)PR_CreateThread(
+ PR_USER_THREAD, Clientel, shared,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_UNJOINABLE_THREAD, 8 * 1024);
+ if (shared->threads == initial_streams)
+ {
+ PR_Sleep(dally);
+ initial_streams += 1;
+ }
+ } while (PR_TRUE);
+ }
+ }
+}
+
+static void PR_CALLBACK Servette(void *arg)
+{
+ PRInt32 bytes, sampled;
+ PRIntervalTime now, interval;
+ PRBool do_display = PR_FALSE;
+ PRFileDesc *client = (PRFileDesc*)arg;
+ char *buffer = (char*)PR_Malloc(buffer_size);
+ PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL);
+
+ if (xport_buffer != -1)
+ {
+ PRStatus rv;
+ PRSocketOptionData data;
+ data.option = PR_SockOpt_RecvBufferSize;
+ data.value.recv_buffer_size = (PRSize)xport_buffer;
+ rv = PR_SetSocketOption(client, &data);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err, "PR_SetSocketOption - ignored");
+ data.option = PR_SockOpt_SendBufferSize;
+ data.value.send_buffer_size = (PRSize)xport_buffer;
+ rv = PR_SetSocketOption(client, &data);
+ if (PR_FAILURE == rv)
+ PL_FPrintError(err, "PR_SetSocketOption - ignored");
+ }
+
+ do
+ {
+ bytes = PR_Send(
+ client, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT);
+
+ PR_Lock(shared->ml);
+ now = PR_IntervalNow();
+ shared->sampled += bytes;
+ interval = now - shared->timein;
+ if (interval > sampling_interval)
+ {
+ sampled = shared->sampled;
+ shared->timein = now;
+ shared->sampled = 0;
+ do_display = PR_TRUE;
+ }
+ PR_Unlock(shared->ml);
+
+ if (do_display)
+ {
+ PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval);
+ PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate);
+ do_display = PR_FALSE;
+ }
+ } while (bytes > 0);
+} /* Servette */
+
+static void Server(void)
+{
+ PRStatus rv;
+ PRNetAddr server_address, client_address;
+ PRFileDesc *xport = PR_Socket(domain, PR_SOCK_STREAM, protocol);
+
+ if (NULL == xport)
+ {
+ PL_FPrintError(err, "PR_Socket");
+ return;
+ }
+
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, PORT_NUMBER, &server_address);
+ if (PR_FAILURE == rv) PL_FPrintError(err, "PR_InitializeNetAddr");
+ else
+ {
+ rv = PR_Bind(xport, &server_address);
+ if (PR_FAILURE == rv) PL_FPrintError(err, "PR_Bind");
+ else
+ {
+ PRFileDesc *client;
+ rv = PR_Listen(xport, 10);
+ PR_fprintf(err, "Server listening on ");
+ (void)PrintAddress(&server_address);
+ do
+ {
+ client = PR_Accept(
+ xport, &client_address, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == client) PL_FPrintError(err, "PR_Accept");
+ else
+ {
+ PR_fprintf(err, "Server accepting from ");
+ (void)PrintAddress(&client_address);
+ shared->threads += 1;
+ (void)PR_CreateThread(
+ PR_USER_THREAD, Servette, client,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_UNJOINABLE_THREAD, 8 * 1024);
+ }
+ } while (PR_TRUE);
+
+ }
+ }
+} /* Server */
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: [-h] [<server>]\n");
+ PR_fprintf(err, "\t-s <n> Initial # of connections (default: 1)\n");
+ PR_fprintf(err, "\t-C <n> Set 'concurrency' (default: 1)\n");
+ PR_fprintf(err, "\t-b <nK> Client buffer size (default: 32k)\n");
+ PR_fprintf(err, "\t-B <nK> Transport recv/send buffer size (default: sys)\n");
+ PR_fprintf(err, "\t-G Use GLOBAL threads (default: LOCAL)\n");
+ PR_fprintf(err, "\t-X Use XTP transport (default: TCP)\n");
+ PR_fprintf(err, "\t-6 Use IPv6 (default: IPv4)\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+ PR_fprintf(err, "\t<server> DNS name of server\n");
+ PR_fprintf(err, "\t\tIf <server> is not specified, this host will be\n");
+ PR_fprintf(err, "\t\tthe server and not act as a client.\n");
+} /* Help */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PLOptStatus os;
+ const char *server_name = NULL;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hGX6C:b:s:B:");
+
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* Name of server */
+ server_name = opt->value;
+ break;
+ case 'G': /* Globular threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'X': /* Use XTP as the transport */
+ protocol = 36;
+ break;
+ case '6': /* Use IPv6 */
+ domain = PR_AF_INET6;
+ break;
+ case 's': /* initial_streams */
+ initial_streams = atoi(opt->value);
+ break;
+ case 'C': /* concurrency */
+ concurrency = atoi(opt->value);
+ break;
+ case 'b': /* buffer size */
+ buffer_size = 1024 * atoi(opt->value);
+ break;
+ case 'B': /* buffer size */
+ xport_buffer = 1024 * atoi(opt->value);
+ break;
+ case 'h': /* user wants some guidance */
+ default:
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ shared = PR_NEWZAP(Shared);
+ shared->ml = PR_NewLock();
+
+ PR_fprintf(err,
+ "This machine is %s\n",
+ (NULL == server_name) ? "the SERVER" : "a CLIENT");
+
+ PR_fprintf(err,
+ "Transport being used is %s\n",
+ (6 == protocol) ? "TCP" : "XTP");
+
+ if (PR_GLOBAL_THREAD == thread_scope)
+ {
+ if (1 != concurrency)
+ {
+ PR_fprintf(err, " **Concurrency > 1 and GLOBAL threads!?!?\n");
+ PR_fprintf(err, " **Ignoring concurrency\n");
+ concurrency = 1;
+ }
+ }
+
+ if (1 != concurrency)
+ {
+ PR_SetConcurrency(concurrency);
+ PR_fprintf(err, "Concurrency set to %u\n", concurrency);
+ }
+
+ PR_fprintf(err,
+ "All threads will be %s\n",
+ (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");
+
+ PR_fprintf(err, "Client buffer size will be %u\n", buffer_size);
+
+ if (-1 != xport_buffer)
+ PR_fprintf(
+ err, "Transport send & receive buffer size will be %u\n", xport_buffer);
+
+
+ if (NULL == server_name) Server();
+ else Client(server_name);
+
+} /* main */
+
+/* thruput.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/time.c b/src/libs/xpcom18a4/nsprpub/pr/tests/time.c
new file mode 100644
index 00000000..b8e7d61a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/time.c
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Program to test different ways to get the time; right now it is tuned
+ * only for solaris.
+ * solaris results (100000 iterations):
+ * time to get time with time(): 4.63 usec avg, 463 msec total
+ * time to get time with gethrtime(): 2.17 usec avg, 217 msec total
+ * time to get time with gettimeofday(): 1.25 usec avg, 125 msec total
+ *
+ *
+ */
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "prpriv.h"
+#include "prinrval.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#define DEFAULT_COUNT 100000
+PRInt32 count;
+
+time_t itime;
+hrtime_t ihrtime;
+
+void
+ftime_init()
+{
+ itime = time(NULL);
+ ihrtime = gethrtime();
+}
+
+time_t
+ftime()
+{
+ hrtime_t now = gethrtime();
+
+ return itime + ((now - ihrtime) / 1000000000ll);
+}
+
+static void timeTime(void)
+{
+ PRInt32 index = count;
+ time_t rv;
+
+ for (;index--;)
+ rv = time(NULL);
+}
+
+static void timeGethrtime(void)
+{
+ PRInt32 index = count;
+ time_t rv;
+
+ for (;index--;)
+ rv = ftime();
+}
+
+static void timeGettimeofday(void)
+{
+ PRInt32 index = count;
+ time_t rv;
+ struct timeval tp;
+
+ for (;index--;)
+ rv = gettimeofday(&tp, NULL);
+}
+
+static void timePRTime32(void)
+{
+ PRInt32 index = count;
+ PRInt32 rv32;
+ PRTime q;
+ PRTime rv;
+
+ LL_I2L(q, 1000000);
+
+ for (;index--;) {
+ rv = PR_Now();
+ LL_DIV(rv, rv, q);
+ LL_L2I(rv32, rv);
+ }
+}
+
+static void timePRTime64(void)
+{
+ PRInt32 index = count;
+ PRTime rv;
+
+ for (;index--;)
+ rv = PR_Now();
+}
+
+/************************************************************************/
+
+static void Measure(void (*func)(void), const char *msg)
+{
+ PRIntervalTime start, stop;
+ double d;
+ PRInt32 tot;
+
+ start = PR_IntervalNow();
+ (*func)();
+ stop = PR_IntervalNow();
+
+ d = (double)PR_IntervalToMicroseconds(stop - start);
+ tot = PR_IntervalToMilliseconds(stop-start);
+
+ if (debug_mode) printf("%40s: %6.2f usec avg, %d msec total\n", msg, d / count, tot);
+}
+
+void main(int argc, char **argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+
+ if (argc > 1) {
+ count = atoi(argv[1]);
+ } else {
+ count = DEFAULT_COUNT;
+ }
+
+ ftime_init();
+
+ Measure(timeTime, "time to get time with time()");
+ Measure(timeGethrtime, "time to get time with gethrtime()");
+ Measure(timeGettimeofday, "time to get time with gettimeofday()");
+ Measure(timePRTime32, "time to get time with PR_Time() (32bit)");
+ Measure(timePRTime64, "time to get time with PR_Time() (64bit)");
+
+ PR_Cleanup();
+ return 0;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/timemac.c b/src/libs/xpcom18a4/nsprpub/pr/tests/timemac.c
new file mode 100644
index 00000000..c58c24bd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/timemac.c
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * file: timemac.c
+ * description: test time and date routines on the Mac
+ */
+#include <stdio.h>
+#include "prinit.h"
+#include "prtime.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+
+static char *dayOfWeek[] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" };
+static char *month[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
+
+static void printExplodedTime(const PRExplodedTime *et) {
+ PRInt32 totalOffset;
+ PRInt32 hourOffset, minOffset;
+ const char *sign;
+
+ /* Print day of the week, month, day, hour, minute, and second */
+ printf( "%s %s %ld %02ld:%02ld:%02ld ",
+ dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday,
+ et->tm_hour, et->tm_min, et->tm_sec);
+
+ /* Print time zone */
+ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset;
+ if (totalOffset == 0) {
+ printf("UTC ");
+ } else {
+ sign = "";
+ if (totalOffset < 0) {
+ totalOffset = -totalOffset;
+ sign = "-";
+ }
+ hourOffset = totalOffset / 3600;
+ minOffset = (totalOffset % 3600) / 60;
+ printf("%s%02ld%02ld ", sign, hourOffset, minOffset);
+ }
+
+ /* Print year */
+ printf("%d", et->tm_year);
+}
+
+int main(int argc, char** argv)
+{
+ PR_STDIO_INIT();
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("timemac.log");
+#endif
+
+ /*
+ *************************************************************
+ **
+ ** Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime
+ ** on the current time
+ **
+ *************************************************************
+ */
+
+ {
+ PRTime t1, t2;
+ PRExplodedTime et;
+
+ printf("*********************************************\n");
+ printf("** **\n");
+ printf("** Testing PR_Now(), PR_ExplodeTime, and **\n");
+ printf("** PR_ImplodeTime on the current time **\n");
+ printf("** **\n");
+ printf("*********************************************\n\n");
+ t1 = PR_Now();
+
+ /* First try converting to UTC */
+
+ PR_ExplodeTime(t1, PR_GMTParameters, &et);
+ if (et.tm_params.tp_gmt_offset || et.tm_params.tp_dst_offset) {
+ printf("ERROR: UTC has nonzero gmt or dst offset.\n");
+ return 1;
+ }
+ printf("Current UTC is ");
+ printExplodedTime(&et);
+ printf("\n");
+
+ t2 = PR_ImplodeTime(&et);
+ if (LL_NE(t1, t2)) {
+ printf("ERROR: Explode and implode are NOT inverse.\n");
+ return 1;
+ }
+
+ /* Next, try converting to local (US Pacific) time */
+
+ PR_ExplodeTime(t1, PR_LocalTimeParameters, &et);
+ printf("Current local time is ");
+ printExplodedTime(&et);
+ printf("\n");
+ printf("GMT offset is %ld, DST offset is %ld\n",
+ et.tm_params.tp_gmt_offset, et.tm_params.tp_dst_offset);
+ t2 = PR_ImplodeTime(&et);
+ if (LL_NE(t1, t2)) {
+ printf("ERROR: Explode and implode are NOT inverse.\n");
+ return 1;
+ }
+ }
+
+ printf("Please examine the results\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/timetest.c b/src/libs/xpcom18a4/nsprpub/pr/tests/timetest.c
new file mode 100644
index 00000000..8560b719
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/timetest.c
@@ -0,0 +1,782 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * file: timetest.c
+ * description: test time and date routines
+ */
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prtime.h"
+#include "prprf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "macstdlibextras.h"
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+int failed_already=0;
+PRBool debug_mode = PR_FALSE;
+
+static char *dayOfWeek[] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" };
+static char *month[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
+
+static void PrintExplodedTime(const PRExplodedTime *et) {
+ PRInt32 totalOffset;
+ PRInt32 hourOffset, minOffset;
+ const char *sign;
+
+ /* Print day of the week, month, day, hour, minute, and second */
+ if (debug_mode) printf("%s %s %ld %02ld:%02ld:%02ld ",
+ dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday,
+ et->tm_hour, et->tm_min, et->tm_sec);
+
+ /* Print time zone */
+ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset;
+ if (totalOffset == 0) {
+ if (debug_mode) printf("UTC ");
+ } else {
+ sign = "+";
+ if (totalOffset < 0) {
+ totalOffset = -totalOffset;
+ sign = "-";
+ }
+ hourOffset = totalOffset / 3600;
+ minOffset = (totalOffset % 3600) / 60;
+ if (debug_mode)
+ printf("%s%02ld%02ld ", sign, hourOffset, minOffset);
+ }
+
+ /* Print year */
+ if (debug_mode) printf("%hd", et->tm_year);
+}
+
+static int ExplodedTimeIsEqual(const PRExplodedTime *et1,
+ const PRExplodedTime *et2)
+{
+ if (et1->tm_usec == et2->tm_usec &&
+ et1->tm_sec == et2->tm_sec &&
+ et1->tm_min == et2->tm_min &&
+ et1->tm_hour == et2->tm_hour &&
+ et1->tm_mday == et2->tm_mday &&
+ et1->tm_month == et2->tm_month &&
+ et1->tm_year == et2->tm_year &&
+ et1->tm_wday == et2->tm_wday &&
+ et1->tm_yday == et2->tm_yday &&
+ et1->tm_params.tp_gmt_offset == et2->tm_params.tp_gmt_offset &&
+ et1->tm_params.tp_dst_offset == et2->tm_params.tp_dst_offset) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void
+testParseTimeString(PRTime t)
+{
+ PRExplodedTime et;
+ PRTime t2;
+ char timeString[128];
+ char buf[128];
+ PRInt32 totalOffset;
+ PRInt32 hourOffset, minOffset;
+ const char *sign;
+ PRInt64 usec_per_sec;
+
+ /* Truncate the microsecond part of PRTime */
+ LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
+ LL_DIV(t, t, usec_per_sec);
+ LL_MUL(t, t, usec_per_sec);
+
+ PR_ExplodeTime(t, PR_LocalTimeParameters, &et);
+
+ /* Print day of the week, month, day, hour, minute, and second */
+ PR_snprintf(timeString, 128, "%s %s %ld %02ld:%02ld:%02ld ",
+ dayOfWeek[et.tm_wday], month[et.tm_month], et.tm_mday,
+ et.tm_hour, et.tm_min, et.tm_sec);
+ /* Print time zone */
+ totalOffset = et.tm_params.tp_gmt_offset + et.tm_params.tp_dst_offset;
+ if (totalOffset == 0) {
+ strcat(timeString, "GMT "); /* I wanted to use "UTC" here, but
+ * PR_ParseTimeString doesn't
+ * understand "UTC". */
+ } else {
+ sign = "+";
+ if (totalOffset < 0) {
+ totalOffset = -totalOffset;
+ sign = "-";
+ }
+ hourOffset = totalOffset / 3600;
+ minOffset = (totalOffset % 3600) / 60;
+ PR_snprintf(buf, 128, "%s%02ld%02ld ", sign, hourOffset, minOffset);
+ strcat(timeString, buf);
+ }
+ /* Print year */
+ PR_snprintf(buf, 128, "%hd", et.tm_year);
+ strcat(timeString, buf);
+
+ if (PR_ParseTimeString(timeString, PR_FALSE, &t2) == PR_FAILURE) {
+ fprintf(stderr, "PR_ParseTimeString() failed\n");
+ exit(1);
+ }
+ if (LL_NE(t, t2)) {
+ fprintf(stderr, "PR_ParseTimeString() incorrect\n");
+ PR_snprintf(buf, 128, "t is %lld, t2 is %lld, time string is %s\n",
+ t, t2, timeString);
+ fprintf(stderr, "%s\n", buf);
+ exit(1);
+ }
+}
+
+int main(int argc, char** argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt;
+
+ PR_STDIO_INIT();
+ opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+#ifdef XP_MAC
+ /* Set up the console */
+ InitializeSIOUX(true);
+ debug_mode = PR_TRUE;
+#endif
+ /* Testing zero PRTime (the epoch) */
+ {
+ PRTime t;
+ PRExplodedTime et;
+
+ LL_I2L(t, 0);
+ if (debug_mode) printf("The NSPR epoch is:\n");
+ PR_ExplodeTime(t, PR_LocalTimeParameters, &et);
+ PrintExplodedTime(&et);
+ if (debug_mode) printf("\n");
+ PR_ExplodeTime(t, PR_GMTParameters, &et);
+ PrintExplodedTime(&et);
+ if (debug_mode) printf("\n\n");
+ testParseTimeString(t);
+ }
+
+ /*
+ *************************************************************
+ **
+ ** Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime
+ ** on the current time
+ **
+ *************************************************************
+ */
+
+ {
+ PRTime t1, t2;
+ PRExplodedTime et;
+
+ if (debug_mode) {
+ printf("*********************************************\n");
+ printf("** **\n");
+ printf("** Testing PR_Now(), PR_ExplodeTime, and **\n");
+ printf("** PR_ImplodeTime on the current time **\n");
+ printf("** **\n");
+ printf("*********************************************\n\n");
+ }
+ t1 = PR_Now();
+
+ /* First try converting to UTC */
+
+ PR_ExplodeTime(t1, PR_GMTParameters, &et);
+ if (et.tm_params.tp_gmt_offset || et.tm_params.tp_dst_offset) {
+ if (debug_mode) printf("ERROR: UTC has nonzero gmt or dst offset.\n");
+ else failed_already=1;
+ return 1;
+ }
+ if (debug_mode) printf("Current UTC is ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf("\n");
+
+ t2 = PR_ImplodeTime(&et);
+ if (LL_NE(t1, t2)) {
+ if (debug_mode) printf("ERROR: Explode and implode are NOT inverse.\n");
+ else printf("FAIL\n");
+ return 1;
+ }
+
+ /* Next, try converting to local (US Pacific) time */
+
+ PR_ExplodeTime(t1, PR_LocalTimeParameters, &et);
+ if (debug_mode) printf("Current local time is ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf("\n");
+ if (debug_mode) printf("GMT offset is %ld, DST offset is %ld\n",
+ et.tm_params.tp_gmt_offset, et.tm_params.tp_dst_offset);
+ t2 = PR_ImplodeTime(&et);
+ if (LL_NE(t1, t2)) {
+ if (debug_mode) printf("ERROR: Explode and implode are NOT inverse.\n");
+ return 1;
+ }
+
+ if (debug_mode) printf("Please examine the results\n");
+ testParseTimeString(t1);
+ }
+
+
+ /*
+ *******************************************
+ **
+ ** Testing PR_NormalizeTime()
+ **
+ *******************************************
+ */
+
+ /* July 4, 2001 is Wednesday */
+ {
+ PRExplodedTime et;
+
+ if (debug_mode) {
+ printf("\n");
+ printf("**********************************\n");
+ printf("** **\n");
+ printf("** Testing PR_NormalizeTime() **\n");
+ printf("** **\n");
+ printf("**********************************\n\n");
+ }
+ et.tm_year = 2001;
+ et.tm_month = 7 - 1;
+ et.tm_mday = 4;
+ et.tm_hour = 0;
+ et.tm_min = 0;
+ et.tm_sec = 0;
+ et.tm_usec = 0;
+ et.tm_params = PR_GMTParameters(&et);
+
+ PR_NormalizeTime(&et, PR_GMTParameters);
+
+ if (debug_mode) printf("July 4, 2001 is %s.\n", dayOfWeek[et.tm_wday]);
+ if (et.tm_wday == 3) {
+ if (debug_mode) printf("PASS\n");
+ } else {
+ if (debug_mode) printf("ERROR: It should be Wednesday\n");
+ else failed_already=1;
+ return 1;
+ }
+ testParseTimeString(PR_ImplodeTime(&et));
+
+ /* June 12, 1997 23:00 PST == June 13, 1997 00:00 PDT */
+ et.tm_year = 1997;
+ et.tm_month = 6 - 1;
+ et.tm_mday = 12;
+ et.tm_hour = 23;
+ et.tm_min = 0;
+ et.tm_sec = 0;
+ et.tm_usec = 0;
+ et.tm_params.tp_gmt_offset = -8 * 3600;
+ et.tm_params.tp_dst_offset = 0;
+
+ PR_NormalizeTime(&et, PR_USPacificTimeParameters);
+
+ if (debug_mode) {
+ printf("Thu Jun 12, 1997 23:00:00 PST is ");
+ }
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(".\n");
+ if (et.tm_wday == 5) {
+ if (debug_mode) printf("PASS\n");
+ } else {
+ if (debug_mode) printf("ERROR: It should be Friday\n");
+ else failed_already=1;
+ return 1;
+ }
+ testParseTimeString(PR_ImplodeTime(&et));
+
+ /* Feb 14, 1997 00:00:00 PDT == Feb 13, 1997 23:00:00 PST */
+ et.tm_year = 1997;
+ et.tm_month = 2 - 1;
+ et.tm_mday = 14;
+ et.tm_hour = 0;
+ et.tm_min = 0;
+ et.tm_sec = 0;
+ et.tm_usec = 0;
+ et.tm_params.tp_gmt_offset = -8 * 3600;
+ et.tm_params.tp_dst_offset = 3600;
+
+ PR_NormalizeTime(&et, PR_USPacificTimeParameters);
+
+ if (debug_mode) {
+ printf("Fri Feb 14, 1997 00:00:00 PDT is ");
+ }
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(".\n");
+ if (et.tm_wday == 4) {
+ if (debug_mode) printf("PASS\n");
+ } else {
+ if (debug_mode) printf("ERROR: It should be Thursday\n");
+ else failed_already=1;
+ return 1;
+ }
+ testParseTimeString(PR_ImplodeTime(&et));
+
+ /* What time is Nov. 7, 1996, 18:29:23 PDT? */
+ et.tm_year = 1996;
+ et.tm_month = 11 - 1;
+ et.tm_mday = 7;
+ et.tm_hour = 18;
+ et.tm_min = 29;
+ et.tm_sec = 23;
+ et.tm_usec = 0;
+ et.tm_params.tp_gmt_offset = -8 * 3600; /* PDT */
+ et.tm_params.tp_dst_offset = 3600;
+
+ PR_NormalizeTime(&et, PR_LocalTimeParameters);
+ if (debug_mode) printf("Nov 7 18:29:23 PDT 1996 is ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(".\n");
+ testParseTimeString(PR_ImplodeTime(&et));
+
+ /* What time is Oct. 7, 1995, 18:29:23 PST? */
+ et.tm_year = 1995;
+ et.tm_month = 10 - 1;
+ et.tm_mday = 7;
+ et.tm_hour = 18;
+ et.tm_min = 29;
+ et.tm_sec = 23;
+ et.tm_params.tp_gmt_offset = -8 * 3600; /* PST */
+ et.tm_params.tp_dst_offset = 0;
+
+ PR_NormalizeTime(&et, PR_LocalTimeParameters);
+ if (debug_mode) printf("Oct 7 18:29:23 PST 1995 is ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(".\n");
+ testParseTimeString(PR_ImplodeTime(&et));
+
+ if (debug_mode) printf("Please examine the results\n");
+ }
+
+ /*
+ **************************************************************
+ **
+ ** Testing range of years
+ **
+ **************************************************************
+ */
+
+ {
+ PRExplodedTime et1, et2;
+ PRTime ttt;
+ PRTime secs;
+
+ if (debug_mode) {
+ printf("\n");
+ printf("***************************************\n");
+ printf("** **\n");
+ printf("** Testing range of years **\n");
+ printf("** **\n");
+ printf("***************************************\n\n");
+ }
+ /* April 4, 1917 GMT */
+ et1.tm_usec = 0;
+ et1.tm_sec = 0;
+ et1.tm_min = 0;
+ et1.tm_hour = 0;
+ et1.tm_mday = 4;
+ et1.tm_month = 4 - 1;
+ et1.tm_year = 1917;
+ et1.tm_params = PR_GMTParameters(&et1);
+ PR_NormalizeTime(&et1, PR_LocalTimeParameters);
+ secs = PR_ImplodeTime(&et1);
+ if (LL_GE_ZERO(secs)) {
+ if (debug_mode)
+ printf("ERROR: April 4, 1917 GMT returns a nonnegative second count\n");
+ failed_already = 1;
+ return 1;
+ }
+ PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2);
+ if (!ExplodedTimeIsEqual(&et1, &et2)) {
+ if (debug_mode)
+ printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for April 4, 1917 GMT\n");
+ failed_already=1;
+ return 1;
+ }
+ ttt = PR_ImplodeTime(&et1);
+ testParseTimeString( ttt );
+
+ if (debug_mode) printf("Test passed for April 4, 1917\n");
+
+ /* July 4, 2050 */
+ et1.tm_usec = 0;
+ et1.tm_sec = 0;
+ et1.tm_min = 0;
+ et1.tm_hour = 0;
+ et1.tm_mday = 4;
+ et1.tm_month = 7 - 1;
+ et1.tm_year = 2050;
+ et1.tm_params = PR_GMTParameters(&et1);
+ PR_NormalizeTime(&et1, PR_LocalTimeParameters);
+ secs = PR_ImplodeTime(&et1);
+ if (!LL_GE_ZERO(secs)) {
+ if (debug_mode)
+ printf("ERROR: July 4, 2050 GMT returns a negative second count\n");
+ failed_already = 1;
+ return 1;
+ }
+ PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2);
+ if (!ExplodedTimeIsEqual(&et1, &et2)) {
+ if (debug_mode)
+ printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for July 4, 2050 GMT\n");
+ failed_already=1;
+ return 1;
+ }
+ testParseTimeString(PR_ImplodeTime(&et1));
+
+ if (debug_mode) printf("Test passed for July 4, 2050\n");
+
+ }
+
+ /*
+ **************************************************************
+ **
+ ** Stress test
+ *
+ ** Go through four years, starting from
+ ** 00:00:00 PST Jan. 1, 1993, incrementing
+ ** every 10 minutes.
+ **
+ **************************************************************
+ */
+
+ {
+ PRExplodedTime et, et1, et2;
+ PRInt64 usecPer10Min;
+ int day, hour, min;
+ PRTime usecs;
+ int dstInEffect = 0;
+
+ if (debug_mode) {
+ printf("\n");
+ printf("*******************************************************\n");
+ printf("** **\n");
+ printf("** Stress test **\n");
+ printf("** Starting from midnight Jan. 1, 1993 PST, **\n");
+ printf("** going through four years in 10-minute increment **\n");
+ printf("** **\n");
+ printf("*******************************************************\n\n");
+ }
+ LL_I2L(usecPer10Min, 600000000L);
+
+ /* 00:00:00 PST Jan. 1, 1993 */
+ et.tm_usec = 0;
+ et.tm_sec = 0;
+ et.tm_min = 0;
+ et.tm_hour = 0;
+ et.tm_mday = 1;
+ et.tm_month = 0;
+ et.tm_year = 1993;
+ et.tm_params.tp_gmt_offset = -8 * 3600;
+ et.tm_params.tp_dst_offset = 0;
+ usecs = PR_ImplodeTime(&et);
+
+ for (day = 0; day < 4 * 365 + 1; day++) {
+ for (hour = 0; hour < 24; hour++) {
+ for (min = 0; min < 60; min += 10) {
+ LL_ADD(usecs, usecs, usecPer10Min);
+ PR_ExplodeTime(usecs, PR_USPacificTimeParameters, &et1);
+
+ et2 = et;
+ et2.tm_usec += 600000000L;
+ PR_NormalizeTime(&et2, PR_USPacificTimeParameters);
+
+ if (!ExplodedTimeIsEqual(&et1, &et2)) {
+ if (debug_mode) printf("ERROR: componentwise comparison failed\n");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf("\n");
+ PrintExplodedTime(&et2);
+ if (debug_mode) printf("\n");
+ failed_already=1;
+ return 1;
+ }
+
+ if (LL_NE(usecs, PR_ImplodeTime(&et1))) {
+ if (debug_mode)
+ printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf("\n");
+ failed_already=1;
+ return 1;
+ }
+ testParseTimeString(usecs);
+
+ if (!dstInEffect && et1.tm_params.tp_dst_offset) {
+ dstInEffect = 1;
+ if (debug_mode) printf("DST changeover from ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(" to ");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf(".\n");
+ } else if (dstInEffect && !et1.tm_params.tp_dst_offset) {
+ dstInEffect = 0;
+ if (debug_mode) printf("DST changeover from ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(" to ");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf(".\n");
+ }
+
+ et = et1;
+ }
+ }
+ }
+ if (debug_mode) printf("Test passed\n");
+ }
+
+
+ /* Same stress test, but with PR_LocalTimeParameters */
+
+ {
+ PRExplodedTime et, et1, et2;
+ PRInt64 usecPer10Min;
+ int day, hour, min;
+ PRTime usecs;
+ int dstInEffect = 0;
+
+ if (debug_mode) {
+ printf("\n");
+ printf("*******************************************************\n");
+ printf("** **\n");
+ printf("** Stress test **\n");
+ printf("** Starting from midnight Jan. 1, 1993 PST, **\n");
+ printf("** going through four years in 10-minute increment **\n");
+ printf("** **\n");
+ printf("*******************************************************\n\n");
+ }
+
+ LL_I2L(usecPer10Min, 600000000L);
+
+ /* 00:00:00 PST Jan. 1, 1993 */
+ et.tm_usec = 0;
+ et.tm_sec = 0;
+ et.tm_min = 0;
+ et.tm_hour = 0;
+ et.tm_mday = 1;
+ et.tm_month = 0;
+ et.tm_year = 1993;
+ et.tm_params.tp_gmt_offset = -8 * 3600;
+ et.tm_params.tp_dst_offset = 0;
+ usecs = PR_ImplodeTime(&et);
+
+ for (day = 0; day < 4 * 365 + 1; day++) {
+ for (hour = 0; hour < 24; hour++) {
+ for (min = 0; min < 60; min += 10) {
+ LL_ADD(usecs, usecs, usecPer10Min);
+ PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1);
+
+ et2 = et;
+ et2.tm_usec += 600000000L;
+ PR_NormalizeTime(&et2, PR_LocalTimeParameters);
+
+ if (!ExplodedTimeIsEqual(&et1, &et2)) {
+ if (debug_mode) printf("ERROR: componentwise comparison failed\n");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf("\n");
+ PrintExplodedTime(&et2);
+ if (debug_mode) printf("\n");
+ return 1;
+ }
+
+ if (LL_NE(usecs, PR_ImplodeTime(&et1))) {
+ printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf("\n");
+ failed_already=1;
+ return 1;
+ }
+ testParseTimeString(usecs);
+
+ if (!dstInEffect && et1.tm_params.tp_dst_offset) {
+ dstInEffect = 1;
+ if (debug_mode) printf("DST changeover from ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(" to ");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf(".\n");
+ } else if (dstInEffect && !et1.tm_params.tp_dst_offset) {
+ dstInEffect = 0;
+ if (debug_mode) printf("DST changeover from ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(" to ");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf(".\n");
+ }
+
+ et = et1;
+ }
+ }
+ }
+ if (debug_mode) printf("Test passed\n");
+ }
+
+ /* Same stress test, but with PR_LocalTimeParameters and going backward */
+
+ {
+ PRExplodedTime et, et1, et2;
+ PRInt64 usecPer10Min;
+ int day, hour, min;
+ PRTime usecs;
+ int dstInEffect = 0;
+
+ if (debug_mode) {
+ printf("\n");
+ printf("*******************************************************\n");
+ printf("** **\n");
+ printf("** Stress test **\n");
+ printf("** Starting from midnight Jan. 1, 1997 PST, **\n");
+ printf("** going back four years in 10-minute increment **\n");
+ printf("** **\n");
+ printf("*******************************************************\n\n");
+ }
+
+ LL_I2L(usecPer10Min, 600000000L);
+
+ /* 00:00:00 PST Jan. 1, 1997 */
+ et.tm_usec = 0;
+ et.tm_sec = 0;
+ et.tm_min = 0;
+ et.tm_hour = 0;
+ et.tm_mday = 1;
+ et.tm_month = 0;
+ et.tm_year = 1997;
+ et.tm_params.tp_gmt_offset = -8 * 3600;
+ et.tm_params.tp_dst_offset = 0;
+ usecs = PR_ImplodeTime(&et);
+
+ for (day = 0; day < 4 * 365 + 1; day++) {
+ for (hour = 0; hour < 24; hour++) {
+ for (min = 0; min < 60; min += 10) {
+ LL_SUB(usecs, usecs, usecPer10Min);
+ PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1);
+
+ et2 = et;
+ et2.tm_usec -= 600000000L;
+ PR_NormalizeTime(&et2, PR_LocalTimeParameters);
+
+ if (!ExplodedTimeIsEqual(&et1, &et2)) {
+ if (debug_mode) printf("ERROR: componentwise comparison failed\n");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf("\n");
+ PrintExplodedTime(&et2);
+ if (debug_mode) printf("\n");
+ return 1;
+ }
+
+ if (LL_NE(usecs, PR_ImplodeTime(&et1))) {
+ if (debug_mode)
+ printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf("\n");
+ failed_already=1;
+ return 1;
+ }
+ testParseTimeString(usecs);
+
+ if (!dstInEffect && et1.tm_params.tp_dst_offset) {
+ dstInEffect = 1;
+ if (debug_mode) printf("DST changeover from ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(" to ");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf(".\n");
+ } else if (dstInEffect && !et1.tm_params.tp_dst_offset) {
+ dstInEffect = 0;
+ if (debug_mode) printf("DST changeover from ");
+ PrintExplodedTime(&et);
+ if (debug_mode) printf(" to ");
+ PrintExplodedTime(&et1);
+ if (debug_mode) printf(".\n");
+ }
+
+ et = et1;
+ }
+ }
+ }
+ }
+
+#ifdef XP_MAC
+ if (1)
+ {
+ char dummyChar;
+
+ printf("Press return to exit\n\n");
+ scanf("%c", &dummyChar);
+ }
+#endif
+
+ if (failed_already) return 1;
+ else return 0;
+
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/tmoacc.c b/src/libs/xpcom18a4/nsprpub/pr/tests/tmoacc.c
new file mode 100644
index 00000000..fa974a13
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/tmoacc.c
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+#define BASE_PORT 9867
+#define DEFAULT_THREADS 1
+#define DEFAULT_BACKLOG 10
+#define DEFAULT_TIMEOUT 10
+#define RANDOM_RANGE 100 /* should be significantly smaller than RAND_MAX */
+
+typedef enum {running, stopped} Status;
+
+typedef struct Shared
+{
+ PRLock *ml;
+ PRCondVar *cv;
+ PRBool passed;
+ PRBool random;
+ PRFileDesc *debug;
+ PRIntervalTime timeout;
+ PRFileDesc *listenSock;
+ Status status;
+} Shared;
+
+static PRIntervalTime Timeout(const Shared *shared)
+{
+ PRIntervalTime timeout = shared->timeout;
+ if (shared->random)
+ {
+ PRIntervalTime half = timeout >> 1; /* one half of the interval */
+ PRIntervalTime quarter = half >> 1; /* one quarter of the interval */
+ /* something in [0..timeout / 2) */
+ PRUint32 random = (rand() % RANDOM_RANGE) * half / RANDOM_RANGE;
+ timeout = (3 * quarter) + random; /* [75..125)% */
+ }
+ return timeout;
+} /* Timeout */
+
+static void Accept(void *arg)
+{
+ PRStatus rv;
+ char *buffer = NULL;
+ PRNetAddr clientAddr;
+ Shared *shared = (Shared*)arg;
+ PRInt32 recv_length = 0, flags = 0;
+ PRFileDesc *clientSock;
+ PRIntn toread, byte, bytes, loop = 0;
+ struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
+
+ do
+ {
+ PRUint32 checksum = 0;
+ if (NULL != shared->debug)
+ PR_fprintf(shared->debug, "[%d]accepting ... ", loop++);
+ clientSock = PR_Accept(
+ shared->listenSock, &clientAddr, Timeout(shared));
+ if (clientSock != NULL)
+ {
+ if (NULL != shared->debug)
+ PR_fprintf(shared->debug, "reading length ... ");
+ bytes = PR_Recv(
+ clientSock, &descriptor, sizeof(descriptor),
+ flags, Timeout(shared));
+ if (sizeof(descriptor) == bytes)
+ {
+ /* and, before doing something stupid ... */
+ descriptor.length = PR_ntohl(descriptor.length);
+ descriptor.checksum = PR_ntohl(descriptor.checksum);
+ if (NULL != shared->debug)
+ PR_fprintf(shared->debug, "%d bytes ... ", descriptor.length);
+ toread = descriptor.length;
+ if (recv_length < descriptor.length)
+ {
+ if (NULL != buffer) PR_DELETE(buffer);
+ buffer = (char*)PR_MALLOC(descriptor.length);
+ recv_length = descriptor.length;
+ }
+ for (toread = descriptor.length; toread > 0; toread -= bytes)
+ {
+ bytes = PR_Recv(
+ clientSock, &buffer[descriptor.length - toread],
+ toread, flags, Timeout(shared));
+ if (-1 == bytes)
+ {
+ if (NULL != shared->debug)
+ PR_fprintf(shared->debug, "read data failed...");
+ bytes = 0;
+ }
+ }
+ }
+ else if (NULL != shared->debug)
+ {
+ PR_fprintf(shared->debug, "read desciptor failed...");
+ descriptor.length = -1;
+ }
+ if (NULL != shared->debug)
+ PR_fprintf(shared->debug, "closing");
+ rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
+ if ((PR_FAILURE == rv) && (NULL != shared->debug))
+ {
+ PR_fprintf(shared->debug, " failed");
+ shared->passed = PR_FALSE;
+ }
+ rv = PR_Close(clientSock);
+ if (PR_FAILURE == rv) if (NULL != shared->debug)
+ {
+ PR_fprintf(shared->debug, " failed");
+ shared->passed = PR_FALSE;
+ }
+ if (descriptor.length > 0)
+ {
+ for (byte = 0; byte < descriptor.length; ++byte)
+ {
+ PRUint32 overflow = checksum & 0x80000000;
+ checksum = (checksum << 1);
+ if (0x00000000 != overflow) checksum += 1;
+ checksum += buffer[byte];
+ }
+ if ((descriptor.checksum != checksum) && (NULL != shared->debug))
+ {
+ PR_fprintf(shared->debug, " ... data mismatch");
+ shared->passed = PR_FALSE;
+ }
+ }
+ else if (0 == descriptor.length)
+ {
+ PR_Lock(shared->ml);
+ shared->status = stopped;
+ PR_NotifyCondVar(shared->cv);
+ PR_Unlock(shared->ml);
+ }
+ if (NULL != shared->debug)
+ PR_fprintf(shared->debug, "\n");
+ }
+ else
+ {
+ if (PR_PENDING_INTERRUPT_ERROR != PR_GetError())
+ {
+ if (NULL != shared->debug) PL_PrintError("Accept");
+ shared->passed = PR_FALSE;
+ }
+ }
+ } while (running == shared->status);
+ if (NULL != buffer) PR_DELETE(buffer);
+} /* Accept */
+
+PRIntn Tmoacc(PRIntn argc, char **argv)
+{
+ PRStatus rv;
+ PRIntn exitStatus;
+ PRIntn index;
+ Shared *shared;
+ PLOptStatus os;
+ PRThread **thread;
+ PRNetAddr listenAddr;
+ PRSocketOptionData sockOpt;
+ PRIntn timeout = DEFAULT_TIMEOUT;
+ PRIntn threads = DEFAULT_THREADS;
+ PRIntn backlog = DEFAULT_BACKLOG;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dGb:t:T:R");
+
+ shared = PR_NEWZAP(Shared);
+
+ shared->debug = NULL;
+ shared->passed = PR_TRUE;
+ shared->random = PR_TRUE;
+ shared->status = running;
+ shared->ml = PR_NewLock();
+ shared->cv = PR_NewCondVar(shared->ml);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ shared->debug = PR_GetSpecialFD(PR_StandardError);
+ break;
+ case 'G': /* use global threads */
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'b': /* size of listen backlog */
+ backlog = atoi(opt->value);
+ break;
+ case 't': /* number of threads doing accept */
+ threads = atoi(opt->value);
+ break;
+ case 'T': /* timeout used for network operations */
+ timeout = atoi(opt->value);
+ break;
+ case 'R': /* randomize the timeout values */
+ shared->random = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ if (0 == threads) threads = DEFAULT_THREADS;
+ if (0 == backlog) backlog = DEFAULT_BACKLOG;
+ if (0 == timeout) timeout = DEFAULT_TIMEOUT;
+
+ PR_STDIO_INIT();
+ memset(&listenAddr, 0, sizeof(listenAddr));
+ rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ shared->timeout = PR_SecondsToInterval(timeout);
+
+ /* First bind to the socket */
+ shared->listenSock = PR_NewTCPSocket();
+ if (shared->listenSock)
+ {
+ sockOpt.option = PR_SockOpt_Reuseaddr;
+ sockOpt.value.reuse_addr = PR_TRUE;
+ rv = PR_SetSocketOption(shared->listenSock, &sockOpt);
+ PR_ASSERT(PR_SUCCESS == rv);
+ rv = PR_Bind(shared->listenSock, &listenAddr);
+ if (rv != PR_FAILURE)
+ {
+ rv = PR_Listen(shared->listenSock, threads + backlog);
+ if (PR_SUCCESS == rv)
+ {
+ thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*));
+ for (index = 0; index < threads; ++index)
+ {
+ thread[index] = PR_CreateThread(
+ PR_USER_THREAD, Accept, shared,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 0);
+ PR_ASSERT(NULL != thread[index]);
+ }
+
+ PR_Lock(shared->ml);
+ while (shared->status == running)
+ PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(shared->ml);
+ for (index = 0; index < threads; ++index)
+ {
+ rv = PR_Interrupt(thread[index]);
+ PR_ASSERT(PR_SUCCESS== rv);
+ rv = PR_JoinThread(thread[index]);
+ PR_ASSERT(PR_SUCCESS== rv);
+ }
+ PR_DELETE(thread);
+ }
+ else
+ {
+ if (shared->debug) PL_PrintError("Listen");
+ shared->passed = PR_FALSE;
+ }
+ }
+ else
+ {
+ if (shared->debug) PL_PrintError("Bind");
+ shared->passed = PR_FALSE;
+ }
+
+ PR_Close(shared->listenSock);
+ }
+ else
+ {
+ if (shared->debug) PL_PrintError("Create");
+ shared->passed = PR_FALSE;
+ }
+
+ PR_DestroyCondVar(shared->cv);
+ PR_DestroyLock(shared->ml);
+
+ PR_fprintf(
+ PR_GetSpecialFD(PR_StandardError), "%s\n",
+ ((shared->passed) ? "PASSED" : "FAILED"));
+
+ exitStatus = (shared->passed) ? 0 : 1;
+ PR_DELETE(shared);
+ return exitStatus;
+}
+
+int main(int argc, char **argv)
+{
+ return (PR_VersionCheck(PR_VERSION)) ?
+ PR_Initialize(Tmoacc, argc, argv, 4) : -1;
+} /* main */
+
+/* tmoacc */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/tmocon.c b/src/libs/xpcom18a4/nsprpub/pr/tests/tmocon.c
new file mode 100644
index 00000000..269e3003
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/tmocon.c
@@ -0,0 +1,401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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 Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-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.
+ */
+
+/***********************************************************************
+**
+** Name: tmocon.c
+**
+** Description: test client socket connection.
+**
+** Modification History:
+** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
+** The debug mode will print all of the printfs associated with this test.
+** The regress mode will be the default mode. Since the regress tool limits
+** the output to a one line status:PASS or FAIL,all of the printf statements
+** have been handled with an if (debug_mode) statement.
+***********************************************************************/
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "pprio.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* for getcwd */
+#if defined(XP_UNIX) || defined (XP_OS2_EMX) || defined(XP_BEOS)
+#include <unistd.h>
+#elif defined(XP_PC)
+#include <direct.h>
+#endif
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+
+#define BASE_PORT 9867
+
+#define DEFAULT_DALLY 1
+#define DEFAULT_THREADS 1
+#define DEFAULT_TIMEOUT 10
+#define DEFAULT_MESSAGES 100
+#define DEFAULT_MESSAGESIZE 100
+
+static PRFileDesc *debug_out = NULL;
+
+typedef struct Shared
+{
+ PRBool random;
+ PRBool failed;
+ PRBool intermittant;
+ PRIntn debug;
+ PRInt32 messages;
+ PRIntervalTime dally;
+ PRIntervalTime timeout;
+ PRInt32 message_length;
+ PRNetAddr serverAddress;
+} Shared;
+
+static PRIntervalTime Timeout(const Shared *shared)
+{
+ PRIntervalTime timeout = shared->timeout;
+ if (shared->random)
+ {
+ PRIntervalTime quarter = timeout >> 2; /* one quarter of the interval */
+ PRUint32 random = rand() % quarter; /* something in[0..timeout / 4) */
+ timeout = (((3 * quarter) + random) >> 2) + quarter; /* [75..125)% */
+ }
+ return timeout;
+} /* Timeout */
+
+static void CauseTimeout(const Shared *shared)
+{
+ if (shared->intermittant) PR_Sleep(Timeout(shared));
+} /* CauseTimeout */
+
+static PRStatus MakeReceiver(Shared *shared)
+{
+ PRStatus rv = PR_FAILURE;
+ if (PR_IsNetAddrType(&shared->serverAddress, PR_IpAddrLoopback))
+ {
+ char *argv[3];
+ char path[1024 + sizeof("/tmoacc")];
+ (void)getcwd(path, sizeof(path));
+ (void)strcat(path, "/tmoacc");
+#ifdef XP_PC
+ (void)strcat(path, ".exe");
+#endif
+ argv[0] = path;
+ if (shared->debug > 0)
+ {
+ argv[1] = "-d";
+ argv[2] = NULL;
+ }
+ else argv[1] = NULL;
+ if (shared->debug > 1)
+ PR_fprintf(debug_out, " creating accept process %s ...", path);
+ fflush(stdout);
+ rv = PR_CreateProcessDetached(path, argv, NULL, NULL);
+ if (PR_SUCCESS == rv)
+ {
+ if (shared->debug > 1)
+ PR_fprintf(debug_out, " wait 5 seconds");
+ if (shared->debug > 1)
+ PR_fprintf(debug_out, " before connecting to accept process ...");
+ fflush(stdout);
+ PR_Sleep(PR_SecondsToInterval(5));
+ return rv;
+ }
+ shared->failed = PR_TRUE;
+ if (shared->debug > 0)
+ PL_FPrintError(debug_out, "PR_CreateProcessDetached failed");
+ }
+ return rv;
+} /* MakeReceiver */
+
+static void Connect(void *arg)
+{
+ PRStatus rv;
+ char *buffer = NULL;
+ PRFileDesc *clientSock;
+ Shared *shared = (Shared*)arg;
+ PRInt32 loop, bytes, flags = 0;
+ struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
+ debug_out = (0 == shared->debug) ? NULL : PR_GetSpecialFD(PR_StandardError);
+
+ buffer = (char*)PR_MALLOC(shared->message_length);
+
+ for (bytes = 0; bytes < shared->message_length; ++bytes)
+ buffer[bytes] = (char)bytes;
+
+ descriptor.checksum = 0;
+ for (bytes = 0; bytes < shared->message_length; ++bytes)
+ {
+ PRUint32 overflow = descriptor.checksum & 0x80000000;
+ descriptor.checksum = (descriptor.checksum << 1);
+ if (0x00000000 != overflow) descriptor.checksum += 1;
+ descriptor.checksum += buffer[bytes];
+ }
+ descriptor.checksum = PR_htonl(descriptor.checksum);
+
+ for (loop = 0; loop < shared->messages; ++loop)
+ {
+ if (shared->debug > 1)
+ PR_fprintf(debug_out, "[%d]socket ... ", loop);
+ clientSock = PR_NewTCPSocket();
+ if (clientSock)
+ {
+ /*
+ * We need to slow down the rate of generating connect requests,
+ * otherwise the listen backlog queue on the accept side may
+ * become full and we will get connection refused or timeout
+ * error.
+ */
+
+ PR_Sleep(shared->dally);
+ if (shared->debug > 1)
+ {
+ char buf[128];
+ PR_NetAddrToString(&shared->serverAddress, buf, sizeof(buf));
+ PR_fprintf(debug_out, "connecting to %s ... ", buf);
+ }
+ rv = PR_Connect(
+ clientSock, &shared->serverAddress, Timeout(shared));
+ if (PR_SUCCESS == rv)
+ {
+ PRInt32 descriptor_length = (loop < (shared->messages - 1)) ?
+ shared->message_length : 0;
+ descriptor.length = PR_htonl(descriptor_length);
+ if (shared->debug > 1)
+ PR_fprintf(
+ debug_out, "sending %d bytes ... ", descriptor_length);
+ CauseTimeout(shared); /* might cause server to timeout */
+ bytes = PR_Send(
+ clientSock, &descriptor, sizeof(descriptor),
+ flags, Timeout(shared));
+ if (bytes != sizeof(descriptor))
+ {
+ shared->failed = PR_TRUE;
+ if (shared->debug > 0)
+ PL_FPrintError(debug_out, "PR_Send failed");
+ }
+ if (0 != descriptor_length)
+ {
+ CauseTimeout(shared);
+ bytes = PR_Send(
+ clientSock, buffer, descriptor_length,
+ flags, Timeout(shared));
+ if (bytes != descriptor_length)
+ {
+ shared->failed = PR_TRUE;
+ if (shared->debug > 0)
+ PL_FPrintError(debug_out, "PR_Send failed");
+ }
+ }
+ if (shared->debug > 1) PR_fprintf(debug_out, "closing ... ");
+ rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
+ rv = PR_Close(clientSock);
+ if (shared->debug > 1)
+ {
+ if (PR_SUCCESS == rv) PR_fprintf(debug_out, "\n");
+ else PL_FPrintError(debug_out, "shutdown failed");
+ }
+ }
+ else
+ {
+ if (shared->debug > 1) PL_FPrintError(debug_out, "connect failed");
+ PR_Close(clientSock);
+ if ((loop == 0) && (PR_GetError() == PR_CONNECT_REFUSED_ERROR))
+ {
+ if (MakeReceiver(shared) == PR_FAILURE) break;
+ }
+ else
+ {
+ if (shared->debug > 1) PR_fprintf(debug_out, " exiting\n");
+ break;
+ }
+ }
+ }
+ else
+ {
+ shared->failed = PR_TRUE;
+ if (shared->debug > 0) PL_FPrintError(debug_out, "create socket");
+ break;
+ }
+ }
+
+ PR_DELETE(buffer);
+} /* Connect */
+
+int Tmocon(int argc, char **argv)
+{
+ /*
+ * USAGE
+ * -d turn on debugging output (default = off)
+ * -v turn on verbose output (default = off)
+ * -h <n> dns name of host serving the connection (default = self)
+ * -i dally intermittantly to cause timeouts (default = off)
+ * -m <n> number of messages to send (default = 100)
+ * -s <n> size of each message (default = 100)
+ * -t <n> number of threads sending (default = 1)
+ * -G use global threads (default = local)
+ * -T <n> timeout on I/O operations (seconds) (default = 10)
+ * -D <n> dally between connect requests (seconds)(default = 0)
+ * -R randomize the dally types around 'T' (default = no)
+ */
+
+ PRStatus rv;
+ int exitStatus;
+ PLOptStatus os;
+ Shared *shared = NULL;
+ PRThread **thread = NULL;
+ PRIntn index, threads = DEFAULT_THREADS;
+ PRThreadScope thread_scope = PR_LOCAL_THREAD;
+ PRInt32 dally = DEFAULT_DALLY, timeout = DEFAULT_TIMEOUT;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "divGRh:m:s:t:T:D:");
+
+ shared = PR_NEWZAP(Shared);
+
+ shared->debug = 0;
+ shared->failed = PR_FALSE;
+ shared->random = PR_FALSE;
+ shared->messages = DEFAULT_MESSAGES;
+ shared->message_length = DEFAULT_MESSAGESIZE;
+
+ PR_STDIO_INIT();
+ memset(&shared->serverAddress, 0, sizeof(shared->serverAddress));
+ rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &shared->serverAddress);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd':
+ if (0 == shared->debug) shared->debug = 1;
+ break;
+ case 'v':
+ if (0 == shared->debug) shared->debug = 2;
+ break;
+ case 'i':
+ shared->intermittant = PR_TRUE;
+ break;
+ case 'R':
+ shared->random = PR_TRUE;
+ break;
+ case 'G':
+ thread_scope = PR_GLOBAL_THREAD;
+ break;
+ case 'h': /* the value for backlock */
+ {
+ PRIntn es = 0;
+ PRHostEnt host;
+ char buffer[1024];
+ (void)PR_GetHostByName(
+ opt->value, buffer, sizeof(buffer), &host);
+ es = PR_EnumerateHostEnt(
+ es, &host, BASE_PORT, &shared->serverAddress);
+ PR_ASSERT(es > 0);
+ }
+ break;
+ case 'm': /* number of messages to send */
+ shared->messages = atoi(opt->value);
+ break;
+ case 't': /* number of threads sending */
+ threads = atoi(opt->value);
+ break;
+ case 'D': /* dally time between transmissions */
+ dally = atoi(opt->value);
+ break;
+ case 'T': /* timeout on I/O operations */
+ timeout = atoi(opt->value);
+ break;
+ case 's': /* total size of each message */
+ shared->message_length = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == timeout) timeout = DEFAULT_TIMEOUT;
+ if (0 == threads) threads = DEFAULT_THREADS;
+ if (0 == shared->messages) shared->messages = DEFAULT_MESSAGES;
+ if (0 == shared->message_length) shared->message_length = DEFAULT_MESSAGESIZE;
+
+ shared->dally = PR_SecondsToInterval(dally);
+ shared->timeout = PR_SecondsToInterval(timeout);
+
+ thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*));
+
+ for (index = 0; index < threads; ++index)
+ thread[index] = PR_CreateThread(
+ PR_USER_THREAD, Connect, shared,
+ PR_PRIORITY_NORMAL, thread_scope,
+ PR_JOINABLE_THREAD, 0);
+ for (index = 0; index < threads; ++index)
+ rv = PR_JoinThread(thread[index]);
+
+ PR_DELETE(thread);
+
+ PR_fprintf(
+ PR_GetSpecialFD(PR_StandardError), "%s\n",
+ ((shared->failed) ? "FAILED" : "PASSED"));
+ exitStatus = (shared->failed) ? 1 : 0;
+ PR_DELETE(shared);
+ return exitStatus;
+}
+
+int main(int argc, char **argv)
+{
+ return (PR_VersionCheck(PR_VERSION)) ?
+ PR_Initialize(Tmocon, argc, argv, 4) : -1;
+} /* main */
+
+/* tmocon.c */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/tpd.c b/src/libs/xpcom18a4/nsprpub/pr/tests/tpd.c
new file mode 100644
index 00000000..c9bc5c78
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/tpd.c
@@ -0,0 +1,334 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+** File: tpd.c
+** Description: Exercising the thread private data bailywick.
+*/
+
+#include "prmem.h"
+#include "prinit.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "prthread.h"
+#include "prtypes.h"
+
+#if defined(XP_MAC)
+#include "pprio.h"
+#else
+#include "private/pprio.h"
+#endif
+
+#include "plgetopt.h"
+
+static PRUintn key[128];
+static PRIntn debug = 0;
+static PRBool failed = PR_FALSE;
+static PRBool should = PR_TRUE;
+static PRBool did = PR_TRUE;
+static PRFileDesc *fout = NULL;
+
+static void PrintProgress(PRIntn line)
+{
+ failed = failed || (should && !did);
+ failed = failed || (!should && did);
+ if (debug > 0)
+ {
+#if defined(WIN16)
+ printf(
+ "@ line %d destructor should%s have been called and was%s\n",
+ line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
+#else
+ PR_fprintf(
+ fout, "@ line %d destructor should%s have been called and was%s\n",
+ line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT"));
+#endif
+ }
+} /* PrintProgress */
+
+static void MyAssert(const char *expr, const char *file, PRIntn line)
+{
+ if (debug > 0)
+ (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line);
+} /* MyAssert */
+
+#define MY_ASSERT(_expr) \
+ ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__))
+
+
+static void PR_CALLBACK Destructor(void *data)
+{
+ MY_ASSERT(NULL != data);
+ if (should) did = PR_TRUE;
+ else failed = PR_TRUE;
+ /*
+ * We don't actually free the storage since it's actually allocated
+ * on the stack. Normally, this would not be the case and this is
+ * the opportunity to free whatever.
+ PR_Free(data);
+ */
+} /* Destructor */
+
+static void PR_CALLBACK Thread(void *null)
+{
+ void *pd;
+ PRStatus rv;
+ PRUintn keys;
+ char *key_string[] = {
+ "Key #0", "Key #1", "Key #2", "Key #3",
+ "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 8; ++keys)
+ {
+ pd = PR_GetThreadPrivate(key[keys]);
+ MY_ASSERT(NULL == pd);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 4; keys < 8; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_FAILURE == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+
+ /* put in keys and leave them there for thread exit */
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+ did = PR_FALSE; should = PR_TRUE;
+
+} /* Thread */
+
+static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv)
+{
+ void *pd;
+ PRStatus rv;
+ PRUintn keys;
+ PRThread *thread;
+ char *key_string[] = {
+ "Key #0", "Key #1", "Key #2", "Key #3",
+ "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
+
+ fout = PR_STDOUT;
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_NewThreadPrivateIndex(&key[keys], Destructor);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 8; ++keys)
+ {
+ pd = PR_GetThreadPrivate(key[keys]);
+ MY_ASSERT(NULL == pd);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ for (keys = 4; keys < 8; ++keys)
+ key[keys] = 4096; /* set to invalid value */
+ did = should = PR_FALSE;
+ for (keys = 4; keys < 8; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_FAILURE == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], key_string[keys]);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 0; keys < 4; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = PR_NewThreadPrivateIndex(&key[keys], Destructor);
+ MY_ASSERT(PR_SUCCESS == rv);
+ rv = PR_SetThreadPrivate(key[keys], "EXTENSION");
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = PR_FALSE; should = PR_TRUE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+ PrintProgress(__LINE__);
+
+ did = should = PR_FALSE;
+ for (keys = 8; keys < 127; ++keys)
+ {
+ rv = PR_SetThreadPrivate(key[keys], NULL);
+ MY_ASSERT(PR_SUCCESS == rv);
+ }
+
+ thread = PR_CreateThread(
+ PR_USER_THREAD, Thread, NULL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ (void)PR_JoinThread(thread);
+
+ PrintProgress(__LINE__);
+
+#if defined(WIN16)
+ printf(
+ "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
+#else
+ (void)PR_fprintf(
+ fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
+#endif
+
+ return 0;
+
+} /* Tpd */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dl:r:");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ PR_STDIO_INIT();
+ return PR_Initialize(Tpd, argc, argv, 0);
+} /* main */
+
+/* tpd.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/udpsrv.c b/src/libs/xpcom18a4/nsprpub/pr/tests/udpsrv.c
new file mode 100644
index 00000000..b9b615a2
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/udpsrv.c
@@ -0,0 +1,566 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*******************************************************************
+** udpsrc.c -- Test basic function of UDP server
+**
+** udpsrv operates on the same machine with program udpclt.
+** udpsrv is the server side of a udp sockets application.
+** udpclt is the client side of a udp sockets application.
+**
+** The test is designed to assist developers in porting/debugging
+** the UDP socket functions of NSPR.
+**
+** This test is not a stress test.
+**
+** main() starts two threads: UDP_Server() and UDP_Client();
+** main() uses PR_JoinThread() to wait for the threads to complete.
+**
+** UDP_Server() does repeated recvfrom()s from a socket.
+** He detects an EOF condition set by UDP_Client(). For each
+** packet received by UDP_Server(), he checks its content for
+** expected content, then sends the packet back to UDP_Client().
+**
+** UDP_Client() sends packets to UDP_Server() using sendto()
+** he recieves packets back from the server via recvfrom().
+** After he sends enough packets containing UDP_AMOUNT_TO_WRITE
+** bytes of data, he sends an EOF message.
+**
+** The test issues a pass/fail message at end.
+**
+** Notes:
+** The variable "_debug_on" can be set to 1 to cause diagnostic
+** messages related to client/server synchronization. Useful when
+** the test hangs.
+**
+** Error messages are written to stdout.
+**
+********************************************************************
+*/
+/* --- include files --- */
+#include "nspr.h"
+#include "prpriv.h"
+
+#include "plgetopt.h"
+#include "prttools.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef XP_PC
+#define mode_t int
+#endif
+
+#define UDP_BUF_SIZE 4096
+#define UDP_DGRAM_SIZE 128
+#define UDP_AMOUNT_TO_WRITE (PRInt32)((UDP_DGRAM_SIZE * 1000l) +1)
+#define NUM_UDP_CLIENTS 1
+#define NUM_UDP_DATAGRAMS_PER_CLIENT 5
+#define UDP_SERVER_PORT 9050
+#define UDP_CLIENT_PORT 9053
+#define MY_INADDR PR_INADDR_ANY
+#define PEER_INADDR PR_INADDR_LOOPBACK
+
+#define UDP_TIMEOUT 400000
+/* #define UDP_TIMEOUT PR_INTERVAL_NO_TIMEOUT */
+
+/* --- static data --- */
+static PRIntn _debug_on = 0;
+static PRBool passed = PR_TRUE;
+static PRUint32 cltBytesRead = 0;
+static PRUint32 srvBytesRead = 0;
+static PRFileDesc *output = NULL;
+
+/* --- static function declarations --- */
+#define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg)
+
+
+
+/*******************************************************************
+** ListNetAddr() -- Display the Net Address on stdout
+**
+** Description: displays the component parts of a PRNetAddr struct
+**
+** Arguments: address of PRNetAddr structure to display
+**
+** Returns: void
+**
+** Notes:
+**
+********************************************************************
+*/
+void ListNetAddr( char *msg, PRNetAddr *na )
+{
+ char mbuf[256];
+
+ sprintf( mbuf, "ListNetAddr: %s family: %d, port: %d, ip: %8.8X\n",
+ msg, na->inet.family, PR_ntohs( na->inet.port), PR_ntohl(na->inet.ip) );
+#if 0
+ DPRINTF( mbuf );
+#endif
+} /* --- end ListNetAddr() --- */
+
+/********************************************************************
+** UDP_Server() -- Test a UDP server application
+**
+** Description: The Server side of a UDP Client/Server application.
+**
+** Arguments: none
+**
+** Returns: void
+**
+** Notes:
+**
+**
+********************************************************************
+*/
+static void PR_CALLBACK UDP_Server( void *arg )
+{
+ static char svrBuf[UDP_BUF_SIZE];
+ PRFileDesc *svrSock;
+ PRInt32 rv;
+ PRNetAddr netaddr;
+ PRBool bound = PR_FALSE;
+ PRBool endOfInput = PR_FALSE;
+ PRInt32 numBytes = UDP_DGRAM_SIZE;
+
+ DPRINTF("udpsrv: UDP_Server(): starting\n" );
+
+ /* --- Create the socket --- */
+ DPRINTF("udpsrv: UDP_Server(): Creating UDP Socket\n" );
+ svrSock = PR_NewUDPSocket();
+ if ( svrSock == NULL )
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" );
+ return;
+ }
+
+ /* --- Initialize the sockaddr_in structure --- */
+ memset( &netaddr, 0, sizeof( netaddr ));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.port = PR_htons( UDP_SERVER_PORT );
+ netaddr.inet.ip = PR_htonl( MY_INADDR );
+
+ /* --- Bind the socket --- */
+ while ( !bound )
+ {
+ DPRINTF("udpsrv: UDP_Server(): Binding socket\n" );
+ rv = PR_Bind( svrSock, &netaddr );
+ if ( rv < 0 )
+ {
+ if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
+ {
+ if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
+ PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
+ PR_Sleep( PR_MillisecondsToInterval( 2000 ));
+ continue;
+ }
+ else
+ {
+ passed = PR_FALSE;
+ if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \
+ PR_Bind(): failed: %ld with error: %ld\n",
+ rv, PR_GetError() );
+ PR_Close( svrSock );
+ return;
+ }
+ }
+ else
+ bound = PR_TRUE;
+ }
+ ListNetAddr( "UDP_Server: after bind", &netaddr );
+
+ /* --- Recv the socket --- */
+ while( !endOfInput )
+ {
+ DPRINTF("udpsrv: UDP_Server(): RecvFrom() socket\n" );
+ rv = PR_RecvFrom( svrSock, svrBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
+ if ( rv == -1 )
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n",
+ PR_GetError() );
+ PR_Close( svrSock );
+ return;
+ }
+ ListNetAddr( "UDP_Server after RecvFrom", &netaddr );
+
+ srvBytesRead += rv;
+
+ if ( svrBuf[0] == 'E' )
+ {
+ DPRINTF("udpsrv: UDP_Server(): EOF on input detected\n" );
+ endOfInput = PR_TRUE;
+ }
+
+ /* --- Send the socket --- */
+ DPRINTF("udpsrv: UDP_Server(): SendTo(): socket\n" );
+ rv = PR_SendTo( svrSock, svrBuf, rv, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT );
+ if ( rv == -1 )
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n",
+ PR_GetError() );
+ PR_Close( svrSock );
+ return;
+ }
+ ListNetAddr( "UDP_Server after SendTo", &netaddr );
+ }
+
+ /* --- Close the socket --- */
+ DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
+ rv = PR_Close( svrSock );
+ if ( rv != PR_SUCCESS )
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" );
+ return;
+ }
+
+ DPRINTF("udpsrv: UDP_Server(): Normal end\n" );
+} /* --- end UDP_Server() --- */
+
+
+static char cltBuf[UDP_BUF_SIZE];
+static char cltBufin[UDP_BUF_SIZE];
+/********************************************************************
+** UDP_Client() -- Test a UDP client application
+**
+** Description:
+**
+** Arguments:
+**
+**
+** Returns:
+** 0 -- Successful execution
+** 1 -- Test failed.
+**
+** Notes:
+**
+**
+********************************************************************
+*/
+static void PR_CALLBACK UDP_Client( void *arg )
+{
+ PRFileDesc *cltSock;
+ PRInt32 rv;
+ PRBool bound = PR_FALSE;
+ PRNetAddr netaddr;
+ PRNetAddr netaddrx;
+ PRBool endOfInput = PR_FALSE;
+ PRInt32 numBytes = UDP_DGRAM_SIZE;
+ PRInt32 writeThisMany = UDP_AMOUNT_TO_WRITE;
+ int i;
+
+
+ DPRINTF("udpsrv: UDP_Client(): starting\n" );
+
+ /* --- Create the socket --- */
+ cltSock = PR_NewUDPSocket();
+ if ( cltSock == NULL )
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" );
+ return;
+ }
+
+ /* --- Initialize the sockaddr_in structure --- */
+ memset( &netaddr, 0, sizeof( netaddr ));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.ip = PR_htonl( MY_INADDR );
+ netaddr.inet.port = PR_htons( UDP_CLIENT_PORT );
+
+ /* --- Initialize the write buffer --- */
+ for ( i = 0; i < UDP_BUF_SIZE ; i++ )
+ cltBuf[i] = i;
+
+ /* --- Bind the socket --- */
+ while ( !bound )
+ {
+ DPRINTF("udpsrv: UDP_Client(): Binding socket\n" );
+ rv = PR_Bind( cltSock, &netaddr );
+ if ( rv < 0 )
+ {
+ if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR )
+ {
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n");
+ PR_Sleep( PR_MillisecondsToInterval( 2000 ));
+ continue;
+ }
+ else
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n",
+ rv, PR_GetError() );
+ PR_Close( cltSock );
+ return;
+ }
+ }
+ else
+ bound = PR_TRUE;
+ }
+ ListNetAddr( "UDP_Client after Bind", &netaddr );
+
+ /* --- Initialize the sockaddr_in structure --- */
+ memset( &netaddr, 0, sizeof( netaddr ));
+ netaddr.inet.family = PR_AF_INET;
+ netaddr.inet.ip = PR_htonl( PEER_INADDR );
+ netaddr.inet.port = PR_htons( UDP_SERVER_PORT );
+
+ /* --- send and receive packets until no more data left */
+ while( !endOfInput )
+ {
+ /*
+ ** Signal EOF in the data stream on the last packet
+ */
+ if ( writeThisMany <= UDP_DGRAM_SIZE )
+ {
+ DPRINTF("udpsrv: UDP_Client(): Send EOF packet\n" );
+ cltBuf[0] = 'E';
+ endOfInput = PR_TRUE;
+ }
+
+ /* --- SendTo the socket --- */
+ if ( writeThisMany > UDP_DGRAM_SIZE )
+ numBytes = UDP_DGRAM_SIZE;
+ else
+ numBytes = writeThisMany;
+ writeThisMany -= numBytes;
+ {
+ char mbuf[256];
+ sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n",
+ writeThisMany, numBytes );
+ DPRINTF( mbuf );
+ }
+
+ DPRINTF("udpsrv: UDP_Client(): SendTo(): socket\n" );
+ rv = PR_SendTo( cltSock, cltBuf, numBytes, 0, &netaddr, UDP_TIMEOUT );
+ if ( rv == -1 )
+ {
+ passed = PR_FALSE;
+ if (debug_mode)
+ PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n",
+ PR_GetError() );
+ PR_Close( cltSock );
+ return;
+ }
+ ListNetAddr( "UDP_Client after SendTo", &netaddr );
+
+ /* --- RecvFrom the socket --- */
+ memset( cltBufin, 0, UDP_BUF_SIZE );
+ DPRINTF("udpsrv: UDP_Client(): RecvFrom(): socket\n" );
+ rv = PR_RecvFrom( cltSock, cltBufin, numBytes, 0, &netaddrx, UDP_TIMEOUT );
+ if ( rv == -1 )
+ {
+ passed = PR_FALSE;
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n",
+ PR_GetError() );
+ PR_Close( cltSock );
+ return;
+ }
+ ListNetAddr( "UDP_Client after RecvFrom()", &netaddr );
+ cltBytesRead += rv;
+
+ /* --- verify buffer --- */
+ for ( i = 0; i < rv ; i++ )
+ {
+ if ( cltBufin[i] != i )
+ {
+ /* --- special case, end of input --- */
+ if ( endOfInput && i == 0 && cltBufin[0] == 'E' )
+ continue;
+ passed = PR_FALSE;
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): return data mismatch\n" );
+ PR_Close( cltSock );
+ return;
+ }
+ }
+ if (debug_mode) PR_fprintf(output, ".");
+ }
+
+ /* --- Close the socket --- */
+ DPRINTF("udpsrv: UDP_Server(): Closing socket\n" );
+ rv = PR_Close( cltSock );
+ if ( rv != PR_SUCCESS )
+ {
+ passed = PR_FALSE;
+ if (debug_mode) PR_fprintf(output,
+ "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" );
+ return;
+ }
+ DPRINTF("udpsrv: UDP_Client(): ending\n" );
+} /* --- end UDP_Client() --- */
+
+/********************************************************************
+** main() -- udpsrv
+**
+** arguments:
+**
+** Returns:
+** 0 -- Successful execution
+** 1 -- Test failed.
+**
+** Description:
+**
+** Standard test case setup.
+**
+** Calls the function UDP_Server()
+**
+********************************************************************
+*/
+
+int main(int argc, char **argv)
+{
+ PRThread *srv, *clt;
+/* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d -v
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dv");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = 1;
+ break;
+ case 'v': /* verbose mode */
+ _debug_on = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ PR_STDIO_INIT();
+ output = PR_STDERR;
+
+#ifdef XP_MAC
+ SetupMacPrintfLog("udpsrv.log");
+#endif
+
+ PR_SetConcurrency(4);
+
+ /*
+ ** Create the Server thread
+ */
+ DPRINTF( "udpsrv: Creating Server Thread\n" );
+ srv = PR_CreateThread( PR_USER_THREAD,
+ UDP_Server,
+ (void *) 0,
+ PR_PRIORITY_LOW,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+ if ( srv == NULL )
+ {
+ if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
+ passed = PR_FALSE;
+ }
+
+ /*
+ ** Give the Server time to Start
+ */
+ DPRINTF( "udpsrv: Pausing to allow Server to start\n" );
+ PR_Sleep( PR_MillisecondsToInterval(200) );
+
+ /*
+ ** Create the Client thread
+ */
+ DPRINTF( "udpsrv: Creating Client Thread\n" );
+ clt = PR_CreateThread( PR_USER_THREAD,
+ UDP_Client,
+ (void *) 0,
+ PR_PRIORITY_LOW,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+ if ( clt == NULL )
+ {
+ if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" );
+ passed = PR_FALSE;
+ }
+
+ /*
+ **
+ */
+ DPRINTF("udpsrv: Waiting to join Server & Client Threads\n" );
+ PR_JoinThread( srv );
+ PR_JoinThread( clt );
+
+ /*
+ ** Evaluate test results
+ */
+ if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \
+ srvBytesRead(%ld), expected(%ld)\n",
+ cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE );
+ if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE )
+ {
+ passed = PR_FALSE;
+ }
+ PR_Cleanup();
+ if ( passed )
+ return 0;
+ else
+ return 1;
+} /* --- end main() --- */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/ut_ttools.h b/src/libs/xpcom18a4/nsprpub/pr/tests/ut_ttools.h
new file mode 100644
index 00000000..dc38f316
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/ut_ttools.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/* Used in Regress Tool */
+#define NOSTATUS 2
+#define PASS 1
+#define FAIL 0
+
+PRIntn debug_mode=0;
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/vercheck.c b/src/libs/xpcom18a4/nsprpub/pr/tests/vercheck.c
new file mode 100644
index 00000000..eed5006a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/vercheck.c
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * File: vercheck.c
+ *
+ * Description:
+ * This test tests the PR_VersionCheck() function. The
+ * compatible_version and incompatible_version arrays
+ * need to be updated for each patch or release.
+ *
+ * Tested areas: library version compatibility check.
+ */
+
+#include "prinit.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * This release (4.5) is backward compatible with the
+ * 4.0.x, 4.1.x, 4.2.x, 4.3.x, and 4.4.x releases. It, of course,
+ * is compatible with itself.
+ */
+static char *compatible_version[] = {
+ "4.0", "4.0.1", "4.1", "4.1.1", "4.1.2", "4.1.3",
+ "4.2", "4.2.1", "4.2.2", "4.3", "4.4", "4.4.1", PR_VERSION
+};
+
+/*
+ * This release is not backward compatible with the old
+ * NSPR 2.1 and 3.x releases.
+ *
+ * Any release is incompatible with future releases and
+ * patches.
+ */
+static char *incompatible_version[] = {
+ "2.1 19980529",
+ "3.0", "3.0.1",
+ "3.1", "3.1.1", "3.1.2", "3.1.3",
+ "3.5", "3.5.1",
+ "4.5.3",
+ "4.6", "4.6.1",
+ "10.0", "11.1", "12.14.20"
+};
+
+int main()
+{
+ int idx;
+ int num_compatible = sizeof(compatible_version) / sizeof(char *);
+ int num_incompatible = sizeof(incompatible_version) / sizeof(char *);
+
+ printf("NSPR release %s:\n", PR_VERSION);
+ for (idx = 0; idx < num_compatible; idx++) {
+ if (PR_VersionCheck(compatible_version[idx]) == PR_FALSE) {
+ fprintf(stderr, "Should be compatible with version %s\n",
+ compatible_version[idx]);
+ exit(1);
+ }
+ printf("Compatible with version %s\n", compatible_version[idx]);
+ }
+
+ for (idx = 0; idx < num_incompatible; idx++) {
+ if (PR_VersionCheck(incompatible_version[idx]) == PR_TRUE) {
+ fprintf(stderr, "Should be incompatible with version %s\n",
+ incompatible_version[idx]);
+ exit(1);
+ }
+ printf("Incompatible with version %s\n", incompatible_version[idx]);
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/version.c b/src/libs/xpcom18a4/nsprpub/pr/tests/version.c
new file mode 100644
index 00000000..597f5571
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/version.c
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prlink.h"
+#include "prvrsion.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+PR_IMPORT(const PRVersionDescription *) libVersionPoint(void);
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv = 1;
+ PLOptStatus os;
+ PRIntn verbosity = 0;
+ PRLibrary *runtime = NULL;
+ const char *library_name = NULL;
+ const PRVersionDescription *version_info;
+ char buffer[100];
+ PRExplodedTime exploded;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "d");
+
+ PRFileDesc *err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* fully qualified library name */
+ library_name = opt->value;
+ break;
+ case 'd': /* verbodity */
+ verbosity += 1;
+ break;
+ default:
+ PR_fprintf(err, "Usage: version [-d] {fully qualified library name}\n");
+ return 2; /* but not a lot else */
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (NULL != library_name)
+ {
+ runtime = PR_LoadLibrary(library_name);
+ if (NULL == runtime) {
+ PL_FPrintError(err, "PR_LoadLibrary");
+ return 3;
+ } else {
+ versionEntryPointType versionPoint = (versionEntryPointType)
+ PR_FindSymbol(runtime, "libVersionPoint");
+ if (NULL == versionPoint) {
+ PL_FPrintError(err, "PR_FindSymbol");
+ return 4;
+ }
+ version_info = versionPoint();
+ }
+ } else
+ version_info = libVersionPoint(); /* NSPR's version info */
+
+ (void)PR_fprintf(err, "Runtime library version information\n");
+ PR_ExplodeTime(
+ version_info->buildTime, PR_GMTParameters, &exploded);
+ (void)PR_FormatTime(
+ buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded);
+ (void)PR_fprintf(err, " Build time: %s GMT\n", buffer);
+ (void)PR_fprintf(
+ err, " Build time: %s\n", version_info->buildTimeString);
+ (void)PR_fprintf(
+ err, " %s V%u.%u.%u (%s%s%s)\n",
+ version_info->description,
+ version_info->vMajor,
+ version_info->vMinor,
+ version_info->vPatch,
+ (version_info->beta ? " beta " : ""),
+ (version_info->debug ? " debug " : ""),
+ (version_info->special ? " special" : ""));
+ (void)PR_fprintf(err, " filename: %s\n", version_info->filename);
+ (void)PR_fprintf(err, " security: %s\n", version_info->security);
+ (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright);
+ (void)PR_fprintf(err, " comment: %s\n", version_info->comment);
+ rv = 0;
+ return rv;
+}
+
+/* version.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/.cvsignore b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/Makefile.in b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/Makefile.in
new file mode 100644
index 00000000..ead153ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/Makefile.in
@@ -0,0 +1,99 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+
+
+MOD_DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+W16STDIO = $(MOD_DEPTH)/pr/src/md/windows/$(OBJDIR)/w16stdio.$(OBJ_SUFFIX)
+
+CSRCS = poppad.c \
+ popfile.c \
+ popfont.c \
+ popfind.c \
+ popprnt0.c
+
+
+INCLUDES = -I$(dist_includedir)
+LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib
+LIBPLDS = $(dist_libdir)/plds$(MOD_MAJOR_VERSION).lib
+TARGETS = $(OBJDIR)/poppad.exe
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+
+include $(topsrcdir)/config/rules.mk
+
+
+ifeq ($(OS_TARGET),WIN16)
+$(OBJDIR)/poppad.exe: $(OBJS)
+ @$(MAKE_OBJDIR)
+ echo system windows >w16link
+ echo name $@ >>w16link
+ echo option map >>w16link
+ echo option stack=16K >>w16link
+ echo debug $(DEBUGTYPE) all >>w16link
+ echo file >>w16link
+ echo $(OBJDIR)\\poppad.$(OBJ_SUFFIX), >>w16link
+ echo $(OBJDIR)\\popfile.$(OBJ_SUFFIX), >>w16link
+ echo $(OBJDIR)\\popfont.$(OBJ_SUFFIX), >>w16link
+ echo $(OBJDIR)\\popfind.$(OBJ_SUFFIX), >>w16link
+ echo $(OBJDIR)\\popprnt0.$(OBJ_SUFFIX), >>w16link
+ echo $(W16STDIO) >>w16link
+ echo library $(LIBPR) >>w16link
+ echo library $(LIBPLDS) >>w16link
+ echo library clibl, commdlg >>w16link
+ echo library winsock.lib >>w16link
+ wlink @w16link.
+ wrc -bt=windows poppad.rc $(OBJDIR)\\poppad.exe
+else
+$(OBJDIR)/poppad.exe: $(OBJS)
+ link $(LDOPTS) $< $(LIBPLC) $(LIBPR) wsock32.lib -out:$@
+endif
+
+export:: $(TARGETS)
+
+
+clean::
+ rm -rf $(TARGETS)
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfile.c b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfile.c
new file mode 100644
index 00000000..9aa7187d
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfile.c
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*------------------------------------------
+ POPFILE.C -- Popup Editor File Functions
+ (c) Charles Petzold, 1992
+ ------------------------------------------*/
+
+#include <windows.h>
+#include <commdlg.h>
+#include <stdlib.h>
+
+static OPENFILENAME ofn ;
+
+void PopFileInitialize (HWND hwnd)
+ {
+ static char *szFilter[] = { "Text Files (*.TXT)", "*.txt",
+ "ASCII Files (*.ASC)", "*.asc",
+ "All Files (*.*)", "*.*",
+ "" } ;
+
+ ofn.lStructSize = sizeof (OPENFILENAME) ;
+ ofn.hwndOwner = hwnd ;
+ ofn.hInstance = NULL ;
+ ofn.lpstrFilter = szFilter [0] ;
+ ofn.lpstrCustomFilter = NULL ;
+ ofn.nMaxCustFilter = 0 ;
+ ofn.nFilterIndex = 0 ;
+ ofn.lpstrFile = NULL ; // Set in Open and Close functions
+ ofn.nMaxFile = _MAX_PATH ;
+ ofn.lpstrFileTitle = NULL ; // Set in Open and Close functions
+ ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT ;
+ ofn.lpstrInitialDir = NULL ;
+ ofn.lpstrTitle = NULL ;
+ ofn.Flags = 0 ; // Set in Open and Close functions
+ ofn.nFileOffset = 0 ;
+ ofn.nFileExtension = 0 ;
+ ofn.lpstrDefExt = "txt" ;
+ ofn.lCustData = 0L ;
+ ofn.lpfnHook = NULL ;
+ ofn.lpTemplateName = NULL ;
+ }
+
+BOOL PopFileOpenDlg (HWND hwnd, LPSTR lpstrFileName, LPSTR lpstrTitleName)
+ {
+ ofn.hwndOwner = hwnd ;
+ ofn.lpstrFile = lpstrFileName ;
+ ofn.lpstrFileTitle = lpstrTitleName ;
+ ofn.Flags = OFN_CREATEPROMPT ;
+
+ return GetOpenFileName (&ofn) ;
+ }
+
+BOOL PopFileSaveDlg (HWND hwnd, LPSTR lpstrFileName, LPSTR lpstrTitleName)
+ {
+ ofn.hwndOwner = hwnd ;
+ ofn.lpstrFile = lpstrFileName ;
+ ofn.lpstrFileTitle = lpstrTitleName ;
+ ofn.Flags = OFN_OVERWRITEPROMPT ;
+
+ return GetSaveFileName (&ofn) ;
+ }
+
+static long PopFileLength (int hFile)
+ {
+ long lCurrentPos = _llseek (hFile, 0L, 1) ;
+ long lFileLength = _llseek (hFile, 0L, 2) ;
+
+ _llseek (hFile, lCurrentPos, 0) ;
+
+ return lFileLength ;
+ }
+
+BOOL PopFileRead (HWND hwndEdit, LPSTR lpstrFileName)
+ {
+ long lLength ;
+ HANDLE hBuffer ;
+ int hFile ;
+ LPSTR lpstrBuffer ;
+
+ if (-1 == (hFile = _lopen (lpstrFileName, OF_READ | OF_SHARE_DENY_WRITE)))
+ return FALSE ;
+
+ if ((lLength = PopFileLength (hFile)) >= 32000)
+ {
+ _lclose (hFile) ;
+ return FALSE ;
+ }
+
+ if (NULL == (hBuffer = GlobalAlloc (GHND, lLength + 1)))
+ {
+ _lclose (hFile) ;
+ return FALSE ;
+ }
+
+ lpstrBuffer = GlobalLock (hBuffer) ;
+ _lread (hFile, lpstrBuffer, (WORD) lLength) ;
+ _lclose (hFile) ;
+ lpstrBuffer [(WORD) lLength] = '\0' ;
+
+ SetWindowText (hwndEdit, lpstrBuffer) ;
+ GlobalUnlock (hBuffer) ;
+ GlobalFree (hBuffer) ;
+
+ return TRUE ;
+ }
+
+BOOL PopFileWrite (HWND hwndEdit, LPSTR lpstrFileName)
+ {
+ HANDLE hBuffer ;
+ int hFile ;
+ LPSTR lpstrBuffer ;
+ WORD wLength ;
+
+ if (-1 == (hFile = _lopen (lpstrFileName, OF_WRITE | OF_SHARE_EXCLUSIVE)))
+ if (-1 == (hFile = _lcreat (lpstrFileName, 0)))
+ return FALSE ;
+
+ wLength = GetWindowTextLength (hwndEdit) ;
+ hBuffer = (HANDLE) SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L) ;
+ lpstrBuffer = (LPSTR) LocalLock (hBuffer) ;
+
+ if (wLength != _lwrite (hFile, lpstrBuffer, wLength))
+ {
+ _lclose (hFile) ;
+ return FALSE ;
+ }
+
+ _lclose (hFile) ;
+ LocalUnlock (hBuffer) ;
+
+ return TRUE ;
+ }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfind.c b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfind.c
new file mode 100644
index 00000000..023095ea
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfind.c
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*--------------------------------------------------------
+ POPFIND.C -- Popup Editor Search and Replace Functions
+ (c) Charles Petzold, 1992
+ --------------------------------------------------------*/
+
+#include <windows.h>
+#include <commdlg.h>
+#include <string.h>
+#define MAX_STRING_LEN 256
+
+static char szFindText [MAX_STRING_LEN] ;
+static char szReplText [MAX_STRING_LEN] ;
+
+HWND PopFindFindDlg (HWND hwnd)
+ {
+ static FINDREPLACE fr ; // must be static for modeless dialog!!!
+
+ fr.lStructSize = sizeof (FINDREPLACE) ;
+ fr.hwndOwner = hwnd ;
+ fr.hInstance = NULL ;
+ fr.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD ;
+ fr.lpstrFindWhat = szFindText ;
+ fr.lpstrReplaceWith = NULL ;
+ fr.wFindWhatLen = sizeof (szFindText) ;
+ fr.wReplaceWithLen = 0 ;
+ fr.lCustData = 0 ;
+ fr.lpfnHook = NULL ;
+ fr.lpTemplateName = NULL ;
+
+ return FindText (&fr) ;
+ }
+
+HWND PopFindReplaceDlg (HWND hwnd)
+ {
+ static FINDREPLACE fr ; // must be static for modeless dialog!!!
+
+ fr.lStructSize = sizeof (FINDREPLACE) ;
+ fr.hwndOwner = hwnd ;
+ fr.hInstance = NULL ;
+ fr.Flags = FR_HIDEUPDOWN | FR_HIDEMATCHCASE | FR_HIDEWHOLEWORD ;
+ fr.lpstrFindWhat = szFindText ;
+ fr.lpstrReplaceWith = szReplText ;
+ fr.wFindWhatLen = sizeof (szFindText) ;
+ fr.wReplaceWithLen = sizeof (szReplText) ;
+ fr.lCustData = 0 ;
+ fr.lpfnHook = NULL ;
+ fr.lpTemplateName = NULL ;
+
+ return ReplaceText (&fr) ;
+ }
+
+BOOL PopFindFindText (HWND hwndEdit, int *piSearchOffset, LPFINDREPLACE lpfr)
+ {
+ int iPos ;
+ LOCALHANDLE hLocal ;
+ LPSTR lpstrDoc, lpstrPos ;
+
+ // Get a pointer to the edit document
+
+ hLocal = (HWND) SendMessage (hwndEdit, EM_GETHANDLE, 0, 0L) ;
+ lpstrDoc = (LPSTR) LocalLock (hLocal) ;
+
+ // Search the document for the find string
+
+ lpstrPos = _fstrstr (lpstrDoc + *piSearchOffset, lpfr->lpstrFindWhat) ;
+ LocalUnlock (hLocal) ;
+
+ // Return an error code if the string cannot be found
+
+ if (lpstrPos == NULL)
+ return FALSE ;
+
+ // Find the position in the document and the new start offset
+
+ iPos = lpstrPos - lpstrDoc ;
+ *piSearchOffset = iPos + _fstrlen (lpfr->lpstrFindWhat) ;
+
+ // Select the found text
+
+ SendMessage (hwndEdit, EM_SETSEL, 0,
+ MAKELONG (iPos, *piSearchOffset)) ;
+
+ return TRUE ;
+ }
+
+BOOL PopFindNextText (HWND hwndEdit, int *piSearchOffset)
+ {
+ FINDREPLACE fr ;
+
+ fr.lpstrFindWhat = szFindText ;
+
+ return PopFindFindText (hwndEdit, piSearchOffset, &fr) ;
+ }
+
+BOOL PopFindReplaceText (HWND hwndEdit, int *piSearchOffset, LPFINDREPLACE lpfr)
+ {
+ // Find the text
+
+ if (!PopFindFindText (hwndEdit, piSearchOffset, lpfr))
+ return FALSE ;
+
+ // Replace it
+
+ SendMessage (hwndEdit, EM_REPLACESEL, 0, (long) lpfr->lpstrReplaceWith) ;
+
+ return TRUE ;
+ }
+
+BOOL PopFindValidFind (void)
+ {
+ return *szFindText != '\0' ;
+ }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfont.c b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfont.c
new file mode 100644
index 00000000..5f28af70
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popfont.c
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*------------------------------------------
+ POPFONT.C -- Popup Editor Font Functions
+ (c) Charles Petzold, 1992
+ ------------------------------------------*/
+
+#include <windows.h>
+#include <commdlg.h>
+
+static LOGFONT logfont ;
+static HFONT hFont ;
+
+BOOL PopFontChooseFont (HWND hwnd)
+ {
+ CHOOSEFONT cf ;
+
+ cf.lStructSize = sizeof (CHOOSEFONT) ;
+ cf.hwndOwner = hwnd ;
+ cf.hDC = NULL ;
+ cf.lpLogFont = &logfont ;
+ cf.iPointSize = 0 ;
+ cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS
+ | CF_EFFECTS ;
+ cf.rgbColors = 0L ;
+ cf.lCustData = 0L ;
+ cf.lpfnHook = NULL ;
+ cf.lpTemplateName = NULL ;
+ cf.hInstance = NULL ;
+ cf.lpszStyle = NULL ;
+ cf.nFontType = 0 ; // Returned from ChooseFont
+ cf.nSizeMin = 0 ;
+ cf.nSizeMax = 0 ;
+
+ return ChooseFont (&cf) ;
+ }
+
+void PopFontInitialize (HWND hwndEdit)
+ {
+ GetObject (GetStockObject (SYSTEM_FONT), sizeof (LOGFONT),
+ (LPSTR) &logfont) ;
+ hFont = CreateFontIndirect (&logfont) ;
+ SendMessage (hwndEdit, WM_SETFONT, hFont, 0L) ;
+ }
+
+void PopFontSetFont (HWND hwndEdit)
+ {
+ HFONT hFontNew ;
+
+ hFontNew = CreateFontIndirect (&logfont) ;
+ SendMessage (hwndEdit, WM_SETFONT, hFontNew, 0L) ;
+ DeleteObject (hFont) ;
+ hFont = hFontNew ;
+ }
+
+void PopFontDeinitialize (void)
+ {
+ DeleteObject (hFont) ;
+ }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.c b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.c
new file mode 100644
index 00000000..c62ef23b
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.c
@@ -0,0 +1,672 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*---------------------------------------
+ POPPAD.C -- Popup Editor
+ (c) Charles Petzold, 1992
+ ---------------------------------------*/
+
+#include "nspr.h"
+#include "plevent.h"
+#include <windows.h>
+#include <commdlg.h>
+#include <stdlib.h>
+#include "poppad.h"
+#include <time.h>
+
+#define EDITID 1
+#define UNTITLED "(untitled)"
+
+long FAR PASCAL _export WndProc (HWND, UINT, UINT, LONG) ;
+BOOL FAR PASCAL _export AboutDlgProc (HWND, UINT, UINT, LONG) ;
+
+/* Declarations for NSPR customization
+**
+*/
+typedef struct PadEvent
+{
+ PLEvent plEvent;
+ int unused;
+} PadEvent;
+
+static void PR_CALLBACK TimerThread( void *arg);
+static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent );
+static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent );
+static PRThread *tThread;
+static PLEventQueue *padQueue;
+static int quitSwitch = 0;
+static long ThreadSleepTime = 1000;
+static long timerCount = 0;
+static char *startMessage = "Poppad: NSPR GUI and event test program.\n"
+ "You should see lines of 50 characters\n"
+ "with a new character appearing at 1 second intervals.\n"
+ "Every 10 seconds gets a '+'; every 5 seconds gets a '_';\n"
+ "every 1 second gets a '.'.\n\n"
+ "You should be able to type in the window.\n\n\n";
+
+
+ // Functions in POPFILE.C
+
+void PopFileInitialize (HWND) ;
+BOOL PopFileOpenDlg (HWND, LPSTR, LPSTR) ;
+BOOL PopFileSaveDlg (HWND, LPSTR, LPSTR) ;
+BOOL PopFileRead (HWND, LPSTR) ;
+BOOL PopFileWrite (HWND, LPSTR) ;
+
+ // Functions in POPFIND.C
+
+HWND PopFindFindDlg (HWND) ;
+HWND PopFindReplaceDlg (HWND) ;
+BOOL PopFindFindText (HWND, int *, LPFINDREPLACE) ;
+BOOL PopFindReplaceText (HWND, int *, LPFINDREPLACE) ;
+BOOL PopFindNextText (HWND, int *) ;
+BOOL PopFindValidFind (void) ;
+
+ // Functions in POPFONT.C
+
+void PopFontInitialize (HWND) ;
+BOOL PopFontChooseFont (HWND) ;
+void PopFontSetFont (HWND) ;
+void PopFontDeinitialize (void) ;
+
+ // Functions in POPPRNT.C
+
+BOOL PopPrntPrintFile (HANDLE, HWND, HWND, LPSTR) ;
+
+ // Global variables
+
+static char szAppName [] = "PopPad" ;
+static HWND hDlgModeless ;
+static HWND hwndEdit ;
+
+int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow)
+ {
+ MSG msg;
+ HWND hwnd ;
+ HANDLE hAccel ;
+ WNDCLASS wndclass ;
+
+ PR_STDIO_INIT();
+ PR_Init(0, 0, 0);
+
+ if (!hPrevInstance)
+ {
+ wndclass.style = CS_HREDRAW | CS_VREDRAW ;
+ wndclass.lpfnWndProc = WndProc ;
+ wndclass.cbClsExtra = 0 ;
+ wndclass.cbWndExtra = 0 ;
+ wndclass.hInstance = hInstance ;
+ wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
+ wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
+ wndclass.lpszMenuName = szAppName ;
+ wndclass.lpszClassName = szAppName ;
+
+ RegisterClass (&wndclass) ;
+ }
+
+ hwnd = CreateWindow (szAppName, NULL,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, hInstance, lpszCmdLine) ;
+
+ ShowWindow (hwnd, nCmdShow) ;
+ UpdateWindow (hwnd);
+
+ hAccel = LoadAccelerators (hInstance, szAppName) ;
+
+ for(;;)
+ {
+ if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
+ {
+ if (GetMessage(&msg, NULL, 0, 0))
+ {
+ if (hDlgModeless == NULL || !IsDialogMessage (hDlgModeless, &msg))
+ {
+ if (!TranslateAccelerator (hwnd, hAccel, &msg))
+ {
+ TranslateMessage (&msg) ;
+ DispatchMessage (&msg) ;
+ } /* end if !TranslateAccelerator */
+ }
+ }
+ else
+ {
+ break;
+ } /* end if GetMessage() */
+ }
+ else /* !PeekMessage */
+ {
+ PR_Sleep(50);
+ }/* end if PeekMessage() */
+ } /* end for() */
+
+ PR_JoinThread( tThread );
+ PL_DestroyEventQueue( padQueue );
+ PR_Cleanup();
+ return msg.wParam ;
+ }
+
+void DoCaption (HWND hwnd, char *szTitleName)
+ {
+ char szCaption [64 + _MAX_FNAME + _MAX_EXT] ;
+
+ wsprintf (szCaption, "%s - %s", (LPSTR) szAppName,
+ (LPSTR) (szTitleName [0] ? szTitleName : UNTITLED)) ;
+
+ SetWindowText (hwnd, szCaption) ;
+ }
+
+void OkMessage (HWND hwnd, char *szMessage, char *szTitleName)
+ {
+ char szBuffer [64 + _MAX_FNAME + _MAX_EXT] ;
+
+ wsprintf (szBuffer, szMessage,
+ (LPSTR) (szTitleName [0] ? szTitleName : UNTITLED)) ;
+
+ MessageBox (hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION) ;
+ }
+
+short AskAboutSave (HWND hwnd, char *szTitleName)
+ {
+ char szBuffer [64 + _MAX_FNAME + _MAX_EXT] ;
+ short nReturn ;
+
+ wsprintf (szBuffer, "Save current changes in %s?",
+ (LPSTR) (szTitleName [0] ? szTitleName : UNTITLED)) ;
+
+ nReturn = MessageBox (hwnd, szBuffer, szAppName,
+ MB_YESNOCANCEL | MB_ICONQUESTION) ;
+
+ if (nReturn == IDYES)
+ if (!SendMessage (hwnd, WM_COMMAND, IDM_SAVE, 0L))
+ nReturn = IDCANCEL ;
+
+ return nReturn ;
+ }
+
+long FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,
+ LONG lParam)
+ {
+ static BOOL bNeedSave = FALSE ;
+ static char szFileName [_MAX_PATH] ;
+ static char szTitleName [_MAX_FNAME + _MAX_EXT] ;
+ static FARPROC lpfnAboutDlgProc ;
+ static HANDLE hInst ;
+ static int iOffset ;
+ static UINT messageFindReplace ;
+ LONG lSelect ;
+ LPFINDREPLACE lpfr ;
+ WORD wEnable ;
+
+ switch (message)
+ {
+ case WM_CREATE:
+ // Get About dialog instance address
+
+ hInst = ((LPCREATESTRUCT) lParam)->hInstance ;
+ lpfnAboutDlgProc = MakeProcInstance ((FARPROC) AboutDlgProc,
+ hInst) ;
+
+ // Create the edit control child window
+
+ hwndEdit = CreateWindow ("edit", NULL,
+ WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
+ WS_BORDER | ES_LEFT | ES_MULTILINE |
+ ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
+ 0, 0, 0, 0,
+ hwnd, EDITID, hInst, NULL) ;
+
+ SendMessage (hwndEdit, EM_LIMITTEXT, 32000, 0L) ;
+
+ // Initialize common dialog box stuff
+
+ PopFileInitialize (hwnd) ;
+ PopFontInitialize (hwndEdit) ;
+
+ messageFindReplace = RegisterWindowMessage (FINDMSGSTRING) ;
+
+ // Process command line
+
+ lstrcpy (szFileName, (LPSTR)
+ (((LPCREATESTRUCT) lParam)->lpCreateParams)) ;
+
+ if (lstrlen (szFileName) > 0)
+ {
+ GetFileTitle (szFileName, szTitleName,
+ sizeof (szTitleName)) ;
+
+ if (!PopFileRead (hwndEdit, szFileName))
+ OkMessage (hwnd, "File %s cannot be read!",
+ szTitleName) ;
+ }
+
+ DoCaption (hwnd, szTitleName) ;
+
+ /* Initialize Event Processing for NSPR
+ ** Retrieve the event queue just created
+ ** Create the TimerThread
+ */
+ PL_InitializeEventsLib("someName");
+ padQueue = PL_GetMainEventQueue();
+ tThread = PR_CreateThread(PR_USER_THREAD,
+ TimerThread,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+ return 0 ;
+
+ case WM_SETFOCUS:
+ SetFocus (hwndEdit) ;
+ return 0 ;
+
+ case WM_SIZE:
+ MoveWindow (hwndEdit, 0, 0, LOWORD (lParam),
+ HIWORD (lParam), TRUE) ;
+ return 0 ;
+
+ case WM_INITMENUPOPUP:
+ switch (lParam)
+ {
+ case 1: // Edit menu
+
+ // Enable Undo if edit control can do it
+
+ EnableMenuItem (wParam, IDM_UNDO,
+ SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?
+ MF_ENABLED : MF_GRAYED) ;
+
+ // Enable Paste if text is in the clipboard
+
+ EnableMenuItem (wParam, IDM_PASTE,
+ IsClipboardFormatAvailable (CF_TEXT) ?
+ MF_ENABLED : MF_GRAYED) ;
+
+ // Enable Cut, Copy, and Del if text is selected
+
+ lSelect = SendMessage (hwndEdit, EM_GETSEL, 0, 0L) ;
+ wEnable = HIWORD (lSelect) != LOWORD (lSelect) ?
+ MF_ENABLED : MF_GRAYED ;
+
+ EnableMenuItem (wParam, IDM_CUT, wEnable) ;
+ EnableMenuItem (wParam, IDM_COPY, wEnable) ;
+ EnableMenuItem (wParam, IDM_DEL, wEnable) ;
+ break ;
+
+ case 2: // Search menu
+
+ // Enable Find, Next, and Replace if modeless
+ // dialogs are not already active
+
+ wEnable = hDlgModeless == NULL ?
+ MF_ENABLED : MF_GRAYED ;
+
+ EnableMenuItem (wParam, IDM_FIND, wEnable) ;
+ EnableMenuItem (wParam, IDM_NEXT, wEnable) ;
+ EnableMenuItem (wParam, IDM_REPLACE, wEnable) ;
+ break ;
+ }
+ return 0 ;
+
+ case WM_COMMAND :
+ // Messages from edit control
+
+ if (LOWORD (lParam) && wParam == EDITID)
+ {
+ switch (HIWORD (lParam))
+ {
+ case EN_UPDATE:
+ bNeedSave = TRUE ;
+ return 0 ;
+
+ case EN_ERRSPACE:
+ case EN_MAXTEXT:
+ MessageBox (hwnd, "Edit control out of space.",
+ szAppName, MB_OK | MB_ICONSTOP) ;
+ return 0 ;
+ }
+ break ;
+ }
+
+ switch (wParam)
+ {
+ // Messages from File menu
+
+ case IDM_NEW:
+ if (bNeedSave && IDCANCEL ==
+ AskAboutSave (hwnd, szTitleName))
+ return 0 ;
+
+ SetWindowText (hwndEdit, "\0") ;
+ szFileName [0] = '\0' ;
+ szTitleName [0] = '\0' ;
+ DoCaption (hwnd, szTitleName) ;
+ bNeedSave = FALSE ;
+ return 0 ;
+
+ case IDM_OPEN:
+ if (bNeedSave && IDCANCEL ==
+ AskAboutSave (hwnd, szTitleName))
+ return 0 ;
+
+ if (PopFileOpenDlg (hwnd, szFileName, szTitleName))
+ {
+ if (!PopFileRead (hwndEdit, szFileName))
+ {
+ OkMessage (hwnd, "Could not read file %s!",
+ szTitleName) ;
+ szFileName [0] = '\0' ;
+ szTitleName [0] = '\0' ;
+ }
+ }
+
+ DoCaption (hwnd, szTitleName) ;
+ bNeedSave = FALSE ;
+ return 0 ;
+
+ case IDM_SAVE:
+ if (szFileName [0])
+ {
+ if (PopFileWrite (hwndEdit, szFileName))
+ {
+ bNeedSave = FALSE ;
+ return 1 ;
+ }
+ else
+ OkMessage (hwnd, "Could not write file %s",
+ szTitleName) ;
+ return 0 ;
+ }
+ // fall through
+ case IDM_SAVEAS:
+ if (PopFileSaveDlg (hwnd, szFileName, szTitleName))
+ {
+ DoCaption (hwnd, szTitleName) ;
+
+ if (PopFileWrite (hwndEdit, szFileName))
+ {
+ bNeedSave = FALSE ;
+ return 1 ;
+ }
+ else
+ OkMessage (hwnd, "Could not write file %s",
+ szTitleName) ;
+ }
+ return 0 ;
+
+ case IDM_PRINT:
+ if (!PopPrntPrintFile (hInst, hwnd, hwndEdit,
+ szTitleName))
+ OkMessage (hwnd, "Could not print file %s",
+ szTitleName) ;
+ return 0 ;
+
+ case IDM_EXIT:
+ SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
+ return 0 ;
+
+ // Messages from Edit menu
+
+ case IDM_UNDO:
+ SendMessage (hwndEdit, WM_UNDO, 0, 0L) ;
+ return 0 ;
+
+ case IDM_CUT:
+ SendMessage (hwndEdit, WM_CUT, 0, 0L) ;
+ return 0 ;
+
+ case IDM_COPY:
+ SendMessage (hwndEdit, WM_COPY, 0, 0L) ;
+ return 0 ;
+
+ case IDM_PASTE:
+ SendMessage (hwndEdit, WM_PASTE, 0, 0L) ;
+ return 0 ;
+
+ case IDM_DEL:
+ SendMessage (hwndEdit, WM_CLEAR, 0, 0L) ;
+ return 0 ;
+
+ case IDM_SELALL:
+ SendMessage (hwndEdit, EM_SETSEL, 0,
+ MAKELONG (0, 32767)) ;
+ return 0 ;
+
+ // Messages from Search menu
+
+ case IDM_FIND:
+ iOffset = HIWORD (
+ SendMessage (hwndEdit, EM_GETSEL, 0, 0L)) ;
+ hDlgModeless = PopFindFindDlg (hwnd) ;
+ return 0 ;
+
+ case IDM_NEXT:
+ iOffset = HIWORD (
+ SendMessage (hwndEdit, EM_GETSEL, 0, 0L)) ;
+
+ if (PopFindValidFind ())
+ PopFindNextText (hwndEdit, &iOffset) ;
+ else
+ hDlgModeless = PopFindFindDlg (hwnd) ;
+
+ return 0 ;
+
+ case IDM_REPLACE:
+ iOffset = HIWORD (
+ SendMessage (hwndEdit, EM_GETSEL, 0, 0L)) ;
+
+ hDlgModeless = PopFindReplaceDlg (hwnd) ;
+ return 0 ;
+
+ case IDM_FONT:
+ if (PopFontChooseFont (hwnd))
+ PopFontSetFont (hwndEdit) ;
+
+ return 0 ;
+
+ // Messages from Help menu
+
+ case IDM_HELP:
+ OkMessage (hwnd, "Help not yet implemented!", NULL) ;
+ return 0 ;
+
+ case IDM_ABOUT:
+ DialogBox (hInst, "AboutBox", hwnd, lpfnAboutDlgProc);
+ return 0 ;
+ }
+ break ;
+
+ case WM_CLOSE:
+ if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))
+ DestroyWindow (hwnd) ;
+
+ return 0 ;
+
+ case WM_QUERYENDSESSION:
+ if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))
+ return 1L ;
+
+ return 0 ;
+
+ case WM_DESTROY:
+ PopFontDeinitialize () ;
+ PostQuitMessage (0) ;
+ quitSwitch = 1;
+ return 0 ;
+
+ default:
+ // Process "Find-Replace" messages
+
+ if (message == messageFindReplace)
+ {
+ lpfr = (LPFINDREPLACE) lParam ;
+
+ if (lpfr->Flags & FR_DIALOGTERM)
+ hDlgModeless = NULL ;
+
+ if (lpfr->Flags & FR_FINDNEXT)
+ if (!PopFindFindText (hwndEdit, &iOffset, lpfr))
+ OkMessage (hwnd, "Text not found!", NULL) ;
+
+ if (lpfr->Flags & FR_REPLACE ||
+ lpfr->Flags & FR_REPLACEALL)
+ if (!PopFindReplaceText (hwndEdit, &iOffset, lpfr))
+ OkMessage (hwnd, "Text not found!", NULL) ;
+
+ if (lpfr->Flags & FR_REPLACEALL)
+ while (PopFindReplaceText (hwndEdit, &iOffset, lpfr));
+
+ return 0 ;
+ }
+ break ;
+ }
+ return DefWindowProc (hwnd, message, wParam, lParam) ;
+ }
+
+BOOL FAR PASCAL _export AboutDlgProc (HWND hDlg, UINT message, UINT wParam,
+ LONG lParam)
+ {
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ return TRUE ;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDOK:
+ EndDialog (hDlg, 0) ;
+ return TRUE ;
+ }
+ break ;
+ }
+ return FALSE ;
+ }
+/*
+** TimerThread() -- The Main function of the timer pop thread
+**
+*/
+static void PR_CALLBACK TimerThread( void *arg)
+{
+ do {
+ PadEvent *ev;
+
+ /*
+ ** Should we quit now?
+ */
+ if ( quitSwitch )
+ break;
+ /*
+ ** Create and Post the event the event
+ */
+ PL_ENTER_EVENT_QUEUE_MONITOR( padQueue );
+ ev = (PadEvent *) PR_NEW( PadEvent );
+ PL_InitEvent( &ev->plEvent, NULL,
+ (PLHandleEventProc)HandlePadEvent,
+ (PLDestroyEventProc)DestroyPadEvent );
+ PL_PostEvent( padQueue, &ev->plEvent );
+ PL_EXIT_EVENT_QUEUE_MONITOR( padQueue );
+
+ PR_Sleep( ThreadSleepTime );
+ } while(1);
+ return;
+}
+
+/*
+** HandlePadEvent() -- gets called because of PostEvent
+*/
+static void PR_CALLBACK HandlePadEvent( PadEvent *padEvent )
+{
+ if ( timerCount++ == 0 )
+ {
+ char *cp;
+
+ for ( cp = startMessage; *cp != 0 ; cp++ )
+ {
+ SendMessage( hwndEdit, WM_CHAR, *cp, MAKELONG( *cp, 1 ));
+ }
+ }
+ /*
+ ** Send a WM_CHAR event the edit Window
+ */
+ if ((timerCount % 10) == 0)
+ {
+ SendMessage( hwndEdit, WM_CHAR, '+', MAKELONG( '+', 1 ));
+ }
+ else if ((timerCount % 5) == 0)
+ {
+ SendMessage( hwndEdit, WM_CHAR, '_', MAKELONG( '_', 1 ));
+ }
+ else
+ {
+ SendMessage( hwndEdit, WM_CHAR, '.', MAKELONG( '.', 1 ));
+ }
+
+ if ( (timerCount % 50) == 0)
+ {
+ SendMessage( hwndEdit, WM_CHAR, '\n', MAKELONG( '\n', 1 ));
+ }
+
+ /*
+ ** PL_RevokeEvents() is broken. Test to fix it.
+ */
+ {
+ static long revokeCounter = 0;
+
+ if (revokeCounter++ > 10 )
+ {
+ PR_Sleep( ThreadSleepTime * 10 );
+ SendMessage( hwndEdit, WM_CHAR, '*', MAKELONG( '\n', 1 ));
+ PL_RevokeEvents( padQueue, NULL );
+ revokeCounter = 0;
+ }
+ }
+ return;
+}
+
+/*
+** DestroyPadEvent() -- Called after HandlePadEvent()
+*/
+static void PR_CALLBACK DestroyPadEvent( PadEvent *padevent )
+{
+ PR_Free( padevent );
+ return;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.h b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.h
new file mode 100644
index 00000000..202095e5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*----------------------
+ POPPAD.H header file
+ (c) Charles Petzold, 1992
+ ----------------------*/
+
+#define IDM_NEW 10
+#define IDM_OPEN 11
+#define IDM_SAVE 12
+#define IDM_SAVEAS 13
+#define IDM_PRINT 14
+#define IDM_EXIT 15
+
+#define IDM_UNDO 20
+#define IDM_CUT 21
+#define IDM_COPY 22
+#define IDM_PASTE 23
+#define IDM_DEL 24
+#define IDM_SELALL 25
+
+#define IDM_FIND 30
+#define IDM_NEXT 31
+#define IDM_REPLACE 32
+
+#define IDM_FONT 40
+
+#define IDM_HELP 50
+#define IDM_ABOUT 51
+
+#define IDD_FNAME 10
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.ico b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.ico
new file mode 100644
index 00000000..fe7097c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.ico
Binary files differ
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.rc b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.rc
new file mode 100644
index 00000000..227f5e4a
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/poppad.rc
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*---------------------------
+ POPPAD.RC resource script
+ ---------------------------*/
+
+#include <windows.h>
+#include "poppad.h"
+
+PopPad ICON "poppad.ico"
+
+PopPad MENU
+ {
+ POPUP "&File"
+ {
+ MENUITEM "&New", IDM_NEW
+ MENUITEM "&Open...", IDM_OPEN
+ MENUITEM "&Save", IDM_SAVE
+ MENUITEM "Save &As...", IDM_SAVEAS
+ MENUITEM SEPARATOR
+ MENUITEM "&Print...", IDM_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_EXIT
+ }
+ POPUP "&Edit"
+ {
+ MENUITEM "&Undo\tCtrl+Z", IDM_UNDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t\tCtrl+X", IDM_CUT
+ MENUITEM "&Copy\tCtrl+C", IDM_COPY
+ MENUITEM "&Paste\tCtrl+V", IDM_PASTE
+ MENUITEM "De&lete\tDel", IDM_DEL
+ MENUITEM SEPARATOR
+ MENUITEM "&Select All", IDM_SELALL
+ }
+ POPUP "&Search"
+ {
+ MENUITEM "&Find...", IDM_FIND
+ MENUITEM "Find &Next\tF3", IDM_NEXT
+ MENUITEM "&Replace...", IDM_REPLACE
+ }
+ POPUP "&Character"
+ {
+ MENUITEM "&Font...", IDM_FONT
+ }
+ POPUP "&Help"
+ {
+ MENUITEM "&Help", IDM_HELP
+ MENUITEM "&About PopPad...", IDM_ABOUT
+ }
+ }
+
+PopPad ACCELERATORS
+ {
+ "^Z", IDM_UNDO
+ VK_BACK, IDM_UNDO, VIRTKEY, ALT
+ "^X", IDM_CUT
+ VK_DELETE, IDM_CUT, VIRTKEY, SHIFT
+ "^C", IDM_COPY
+ VK_INSERT, IDM_COPY, VIRTKEY, CONTROL
+ "^V", IDM_PASTE
+ VK_INSERT, IDM_PASTE, VIRTKEY, SHIFT
+ VK_DELETE, IDM_DEL, VIRTKEY
+ VK_F3, IDM_NEXT, VIRTKEY
+ VK_F1, IDM_HELP, VIRTKEY
+ }
+
+AboutBox DIALOG 20, 20, 160, 80
+ STYLE WS_POPUP | WS_DLGFRAME
+ {
+ CTEXT "PopPad" -1, 0, 12, 160, 8
+ ICON "PopPad" -1, 8, 8, 0, 0
+ CTEXT "Popup Editor for Microsoft Windows" -1, 0, 36, 160, 8
+ CTEXT "Copyright (c) Charles Petzold, 1992" -1, 0, 48, 160, 8
+ DEFPUSHBUTTON "OK" IDOK, 64, 60, 32, 14, WS_GROUP
+ }
+
+PrintDlgBox DIALOG 20, 20, 100, 76
+ STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+ CAPTION "PopPad"
+ {
+ CTEXT "Sending", -1, 0, 10, 100, 8
+ CTEXT "", IDD_FNAME, 0, 20, 100, 8
+ CTEXT "to print spooler.", -1, 0, 30, 100, 8
+ DEFPUSHBUTTON "Cancel", IDCANCEL, 34, 50, 32, 14, WS_GROUP
+ }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popprnt0.c b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popprnt0.c
new file mode 100644
index 00000000..4e76377f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/popprnt0.c
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*---------------------------------------------------------------
+ POPPRNT0.C -- Popup Editor Printing Functions (dummy version)
+ (c) Charles Petzold, 1992
+ ---------------------------------------------------------------*/
+
+#include <windows.h>
+
+BOOL PopPrntPrintFile (HANDLE hInst, HWND hwnd, HWND hwndEdit,
+ LPSTR lpstrTitleName)
+ {
+ return FALSE ;
+ }
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/readme.1st b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/readme.1st
new file mode 100644
index 00000000..afdf847f
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/w16gui/readme.1st
@@ -0,0 +1,37 @@
+readme.1st.
+
+The files in the pr/tests/w16gui directory are taken
+from "Programming Windows 3.1" by Charles Petzold,
+specifically, the programs in chapter 14 related
+to the "poppad4" sample application.
+
+These programs are compiled with nspr20 to test nspr 2.0
+and to demostrate the use of nspr in a gui application.
+
+Library (DLL) PLDSxx.lib PLDSxx.dll is required to be
+linked with this test case. Functions in this dll are
+in the source ns/nspr20/lib/ds/plevent.* files.
+
+Permission to use.
+
+The source for poppad.c are used under license from
+Petzold. The license to use is stated in the book.
+The following paragraph of the license grants that
+use.
+
+ 5. SAMPLE CODE. If the SOFTWARE includes Sample Code, then
+ Microsoft grants you a royalty-free right to reproduce and
+ distribute the sample code of the SOFTWARE provided that you:
+ (a) distribute the sample code only in conjunction with and
+ as part of your software product; (b) do not use Microsoft's
+ or its authors' names, logos, or trademarks to market your
+ software product; (c) include the copyright notice that appears
+ on the SOFTWARE on your product label and as a part of the
+ sign-on message for your software product; and (d) agree to
+ idemnify, hold harmless, and defend Microsoft and its authors
+ from and against any claims or lawsuits, including attorneys'
+ fees, that arise or result from the use or distribution of
+ your software product.
+
+lth. 9/24/97.
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/writev.c b/src/libs/xpcom18a4/nsprpub/pr/tests/writev.c
new file mode 100644
index 00000000..603526c9
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/writev.c
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "nspr.h"
+
+#include "plgetopt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#define printf PR_LogPrint
+#endif
+
+
+#ifndef IOV_MAX
+#define IOV_MAX 16
+#endif
+
+#define BASE_PORT 9867
+
+int PR_CALLBACK Writev(int argc, char **argv)
+{
+
+ PRStatus rv;
+ PRNetAddr serverAddr;
+ PRFileDesc *clientSock, *debug = NULL;
+
+ char *buffer = NULL;
+ PRIOVec *iov = NULL;
+ PRBool passed = PR_TRUE;
+ PRIntervalTime timein, elapsed, timeout;
+ PRIntervalTime tmo_min = 0x7fffffff, tmo_max = 0, tmo_elapsed = 0;
+ PRInt32 tmo_counted = 0, iov_index, loop, bytes, number_fragments;
+ PRInt32 message_length = 100, fragment_length = 100, messages = 100;
+ struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
+
+ /*
+ * USAGE
+ * -h dns name of host serving the connection (default = self)
+ * -m number of messages to send (default = 100)
+ * -s size of each message (default = 100)
+ * -f size of each message fragment (default = 100)
+ */
+
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dh:m:s:f:");
+
+ PR_STDIO_INIT();
+ rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &serverAddr);
+ PR_ASSERT(PR_SUCCESS == rv);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'h': /* the remote host */
+ {
+ PRIntn es = 0;
+ PRHostEnt host;
+ char buffer[1024];
+ (void)PR_GetHostByName(opt->value, buffer, sizeof(buffer), &host);
+ es = PR_EnumerateHostEnt(es, &host, BASE_PORT, &serverAddr);
+ PR_ASSERT(es > 0);
+ }
+ break;
+ case 'd': /* debug mode */
+ debug = PR_GetSpecialFD(PR_StandardError);
+ break;
+ case 'm': /* number of messages to send */
+ messages = atoi(opt->value);
+ break;
+ case 's': /* total size of each message */
+ message_length = atoi(opt->value);
+ break;
+ case 'f': /* size of each message fragment */
+ fragment_length = atoi(opt->value);
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ buffer = (char*)malloc(message_length);
+
+ number_fragments = (message_length + fragment_length - 1) / fragment_length + 1;
+ while (IOV_MAX < number_fragments)
+ {
+ fragment_length = message_length / (IOV_MAX - 2);
+ number_fragments = (message_length + fragment_length - 1) /
+ fragment_length + 1;
+ if (NULL != debug) PR_fprintf(debug,
+ "Too many fragments - reset fragment length to %ld\n", fragment_length);
+ }
+ iov = (PRIOVec*)malloc(number_fragments * sizeof(PRIOVec));
+
+ iov[0].iov_base = (char*)&descriptor;
+ iov[0].iov_len = sizeof(descriptor);
+ for (iov_index = 1; iov_index < number_fragments; ++iov_index)
+ {
+ iov[iov_index].iov_base = buffer + (iov_index - 1) * fragment_length;
+ iov[iov_index].iov_len = fragment_length;
+ }
+
+ for (bytes = 0; bytes < message_length; ++bytes)
+ buffer[bytes] = (char)bytes;
+
+ timeout = PR_SecondsToInterval(1);
+
+ for (loop = 0; loop < messages; ++loop)
+ {
+ if (NULL != debug)
+ PR_fprintf(debug, "[%d]socket ... ", loop);
+ clientSock = PR_NewTCPSocket();
+ if (clientSock)
+ {
+ timein = PR_IntervalNow();
+ if (NULL != debug)
+ PR_fprintf(debug, "connecting ... ");
+ rv = PR_Connect(clientSock, &serverAddr, timeout);
+ if (PR_SUCCESS == rv)
+ {
+ descriptor.checksum = 0;
+ descriptor.length = (loop < (messages - 1)) ? message_length : 0;
+ if (0 == descriptor.length) number_fragments = 1;
+ else
+ for (iov_index = 0; iov_index < descriptor.length; ++iov_index)
+ {
+ PRUint32 overflow = descriptor.checksum & 0x80000000;
+ descriptor.checksum = (descriptor.checksum << 1);
+ if (0x00000000 != overflow) descriptor.checksum += 1;
+ descriptor.checksum += buffer[iov_index];
+ }
+ if (NULL != debug) PR_fprintf(
+ debug, "sending %d bytes ... ", descriptor.length);
+
+ /* then, at the last moment ... */
+ descriptor.length = PR_ntohl(descriptor.length);
+ descriptor.checksum = PR_ntohl(descriptor.checksum);
+
+ bytes = PR_Writev(clientSock, iov, number_fragments, timeout);
+ if (NULL != debug)
+ PR_fprintf(debug, "closing ... ");
+ rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
+ rv = PR_Close(clientSock);
+ if (NULL != debug) PR_fprintf(
+ debug, "%s\n", ((PR_SUCCESS == rv) ? "good" : "bad"));
+ elapsed = PR_IntervalNow() - timein;
+ if (elapsed < tmo_min) tmo_min = elapsed;
+ else if (elapsed > tmo_max) tmo_max = elapsed;
+ tmo_elapsed += elapsed;
+ tmo_counted += 1;
+ }
+ else
+ {
+ if (NULL != debug) PR_fprintf(
+ debug, "failed - retrying (%d, %d)\n",
+ PR_GetError(), PR_GetOSError());
+ PR_Close(clientSock);
+ }
+ }
+ else if (NULL != debug)
+ {
+ PR_fprintf(debug, "unable to create client socket\n");
+ passed = PR_FALSE;
+ }
+ }
+ if (NULL != debug) {
+ if (0 == tmo_counted) {
+ PR_fprintf(debug, "No connection made\n");
+ } else {
+ PR_fprintf(
+ debug, "\nTimings: %d [%d] %d (microseconds)\n",
+ PR_IntervalToMicroseconds(tmo_min),
+ PR_IntervalToMicroseconds(tmo_elapsed / tmo_counted),
+ PR_IntervalToMicroseconds(tmo_max));
+ }
+ }
+
+ PR_DELETE(buffer);
+ PR_DELETE(iov);
+
+ PR_fprintf(
+ PR_GetSpecialFD(PR_StandardError),
+ "%s\n", (passed) ? "PASSED" : "FAILED");
+ return (passed) ? 0 : 1;
+}
+
+int main(int argc, char **argv)
+{
+ return (PR_VersionCheck(PR_VERSION)) ?
+ PR_Initialize(Writev, argc, argv, 4) : -1;
+} /* main */
+
+/* writev.c */
+
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/xnotify.c b/src/libs/xpcom18a4/nsprpub/pr/tests/xnotify.c
new file mode 100644
index 00000000..97f64917
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/xnotify.c
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prprf.h"
+#include "prio.h"
+#include "prcvar.h"
+#include "prmon.h"
+#include "prcmon.h"
+#include "prlock.h"
+#include "prerror.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prthread.h"
+
+static PRLock *ml = NULL;
+static PRIntervalTime base;
+static PRFileDesc *err = NULL;
+
+typedef struct CMonShared
+{
+ PRInt32 o1, o2;
+} CMonShared;
+
+typedef struct MonShared
+{
+ PRMonitor *o1, *o2;
+} MonShared;
+
+typedef struct LockShared
+{
+ PRLock *o1, *o2;
+ PRCondVar *cv1, *cv2;
+} LockShared;
+
+static void LogNow(const char *msg, PRStatus rv)
+{
+ PRIntervalTime now = PR_IntervalNow();
+ PR_Lock(ml);
+ PR_fprintf(err, "%6ld: %s", (now - base), msg);
+ if (PR_FAILURE == rv) PL_FPrintError(err, " ");
+ else PR_fprintf(err, "\n");
+ PR_Unlock(ml);
+} /* LogNow */
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n");
+ PR_fprintf(err, "\t-d debug mode (default: FALSE)\n");
+ PR_fprintf(err, "\t-l test with locks (default: FALSE)\n");
+ PR_fprintf(err, "\t-m tests with monitors (default: FALSE)\n");
+ PR_fprintf(err, "\t-c tests with cmonitors (default: FALSE)\n");
+ PR_fprintf(err, "\t-h help\n");
+} /* Help */
+
+static void PR_CALLBACK T2CMon(void *arg)
+{
+ PRStatus rv;
+ CMonShared *shared = (CMonShared*)arg;
+
+ PR_CEnterMonitor(&shared->o1);
+ LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
+ rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5));
+ if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
+ else LogNow("T2 wait failed on o1", rv);
+
+ rv = PR_CNotify(&shared->o1);
+ if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
+ else LogNow("T2 notify on o1 failed", rv);
+
+ PR_CExitMonitor(&shared->o1);
+} /* T2CMon */
+
+static void PR_CALLBACK T3CMon(void *arg)
+{
+ PRStatus rv;
+ CMonShared *shared = (CMonShared*)arg;
+
+ PR_CEnterMonitor(&shared->o2);
+ LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
+ rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5));
+ if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
+ else LogNow("T3 wait failed on o2", rv);
+ rv = PR_CNotify(&shared->o2);
+ LogNow("T3 notify on o2", rv);
+ PR_CExitMonitor(&shared->o2);
+
+} /* T3CMon */
+
+static CMonShared sharedCM;
+
+static void T1CMon(void)
+{
+ PRStatus rv;
+ PRThread *t2, *t3;
+
+ PR_fprintf(err, "\n**********************************\n");
+ PR_fprintf(err, " CACHED MONITORS\n");
+ PR_fprintf(err, "**********************************\n");
+
+ base = PR_IntervalNow();
+
+ PR_CEnterMonitor(&sharedCM.o1);
+ LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
+ rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3));
+ if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
+ else LogNow("T1 wait on o1 failed", rv);
+ PR_CExitMonitor(&sharedCM.o1);
+
+ LogNow("T1 creating T2", PR_SUCCESS);
+ t2 = PR_CreateThread(
+ PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ LogNow("T1 creating T3", PR_SUCCESS);
+ t3 = PR_CreateThread(
+ PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ PR_CEnterMonitor(&sharedCM.o2);
+ LogNow("T1 waiting forever on o2", PR_SUCCESS);
+ rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT);
+ if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
+ else LogNow("T1 wait on o2 failed", rv);
+ PR_CExitMonitor(&sharedCM.o2);
+
+ (void)PR_JoinThread(t2);
+ (void)PR_JoinThread(t3);
+
+} /* T1CMon */
+
+static void PR_CALLBACK T2Mon(void *arg)
+{
+ PRStatus rv;
+ MonShared *shared = (MonShared*)arg;
+
+ PR_EnterMonitor(shared->o1);
+ LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
+ rv = PR_Wait(shared->o1, PR_SecondsToInterval(5));
+ if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
+ else LogNow("T2 wait failed on o1", rv);
+
+ rv = PR_Notify(shared->o1);
+ if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
+ else LogNow("T2 notify on o1 failed", rv);
+
+ PR_ExitMonitor(shared->o1);
+} /* T2Mon */
+
+static void PR_CALLBACK T3Mon(void *arg)
+{
+ PRStatus rv;
+ MonShared *shared = (MonShared*)arg;
+
+ PR_EnterMonitor(shared->o2);
+ LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
+ rv = PR_Wait(shared->o2, PR_SecondsToInterval(5));
+ if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
+ else LogNow("T3 wait failed on o2", rv);
+ rv = PR_Notify(shared->o2);
+ LogNow("T3 notify on o2", rv);
+ PR_ExitMonitor(shared->o2);
+
+} /* T3Mon */
+
+static MonShared sharedM;
+static void T1Mon(void)
+{
+ PRStatus rv;
+ PRThread *t2, *t3;
+
+ PR_fprintf(err, "\n**********************************\n");
+ PR_fprintf(err, " MONITORS\n");
+ PR_fprintf(err, "**********************************\n");
+
+ sharedM.o1 = PR_NewMonitor();
+ sharedM.o2 = PR_NewMonitor();
+
+ base = PR_IntervalNow();
+
+ PR_EnterMonitor(sharedM.o1);
+ LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
+ rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3));
+ if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
+ else LogNow("T1 wait on o1 failed", rv);
+ PR_ExitMonitor(sharedM.o1);
+
+ LogNow("T1 creating T2", PR_SUCCESS);
+ t2 = PR_CreateThread(
+ PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ LogNow("T1 creating T3", PR_SUCCESS);
+ t3 = PR_CreateThread(
+ PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ PR_EnterMonitor(sharedM.o2);
+ LogNow("T1 waiting forever on o2", PR_SUCCESS);
+ rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT);
+ if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
+ else LogNow("T1 wait on o2 failed", rv);
+ PR_ExitMonitor(sharedM.o2);
+
+ (void)PR_JoinThread(t2);
+ (void)PR_JoinThread(t3);
+
+ PR_DestroyMonitor(sharedM.o1);
+ PR_DestroyMonitor(sharedM.o2);
+
+} /* T1Mon */
+
+static void PR_CALLBACK T2Lock(void *arg)
+{
+ PRStatus rv;
+ LockShared *shared = (LockShared*)arg;
+
+ PR_Lock(shared->o1);
+ LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
+ rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5));
+ if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
+ else LogNow("T2 wait failed on o1", rv);
+
+ rv = PR_NotifyCondVar(shared->cv1);
+ if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
+ else LogNow("T2 notify on o1 failed", rv);
+
+ PR_Unlock(shared->o1);
+} /* T2Lock */
+
+static void PR_CALLBACK T3Lock(void *arg)
+{
+ PRStatus rv;
+ LockShared *shared = (LockShared*)arg;
+
+ PR_Lock(shared->o2);
+ LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
+ rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5));
+ if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
+ else LogNow("T3 wait failed on o2", rv);
+ rv = PR_NotifyCondVar(shared->cv2);
+ LogNow("T3 notify on o2", rv);
+ PR_Unlock(shared->o2);
+
+} /* T3Lock */
+
+/*
+** Make shared' a static variable for Win16
+*/
+static LockShared sharedL;
+
+static void T1Lock(void)
+{
+ PRStatus rv;
+ PRThread *t2, *t3;
+ sharedL.o1 = PR_NewLock();
+ sharedL.o2 = PR_NewLock();
+ sharedL.cv1 = PR_NewCondVar(sharedL.o1);
+ sharedL.cv2 = PR_NewCondVar(sharedL.o2);
+
+ PR_fprintf(err, "\n**********************************\n");
+ PR_fprintf(err, " LOCKS\n");
+ PR_fprintf(err, "**********************************\n");
+
+ base = PR_IntervalNow();
+
+ PR_Lock(sharedL.o1);
+ LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
+ rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3));
+ if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
+ else LogNow("T1 wait on o1 failed", rv);
+ PR_Unlock(sharedL.o1);
+
+ LogNow("T1 creating T2", PR_SUCCESS);
+ t2 = PR_CreateThread(
+ PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ LogNow("T1 creating T3", PR_SUCCESS);
+ t3 = PR_CreateThread(
+ PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+
+ PR_Lock(sharedL.o2);
+ LogNow("T1 waiting forever on o2", PR_SUCCESS);
+ rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT);
+ if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
+ else LogNow("T1 wait on o2 failed", rv);
+ PR_Unlock(sharedL.o2);
+
+ (void)PR_JoinThread(t2);
+ (void)PR_JoinThread(t3);
+
+ PR_DestroyLock(sharedL.o1);
+ PR_DestroyLock(sharedL.o2);
+ PR_DestroyCondVar(sharedL.cv1);
+ PR_DestroyCondVar(sharedL.cv2);
+} /* T1Lock */
+
+static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
+{
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc");
+ PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE;
+
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode (noop) */
+ break;
+ case 'l': /* locks */
+ locks = PR_TRUE;
+ break;
+ case 'm': /* monitors */
+ monitors = PR_TRUE;
+ break;
+ case 'c': /* cached monitors */
+ cmonitors = PR_TRUE;
+ break;
+ case 'h': /* needs guidance */
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ ml = PR_NewLock();
+ if (locks) T1Lock();
+ if (monitors) T1Mon();
+ if (cmonitors) T1CMon();
+
+ PR_DestroyLock(ml);
+
+ PR_fprintf(err, "Done!\n");
+ return 0;
+} /* main */
+
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv;
+
+ PR_STDIO_INIT();
+ rv = PR_Initialize(RealMain, argc, argv, 0);
+ return rv;
+} /* main */
+/* xnotify.c */
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/y2k.c b/src/libs/xpcom18a4/nsprpub/pr/tests/y2k.c
new file mode 100644
index 00000000..80fc10a5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/y2k.c
@@ -0,0 +1,840 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * file: y2k.c
+ * description: Test for y2k compliance for NSPR.
+ *
+ * Sep 1999. lth. Added "Sun" specified dates to the test data.
+ */
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* Used to get the command line option */
+#include "plgetopt.h"
+
+#include "prinit.h"
+#include "prtime.h"
+#include "prprf.h"
+#include "prlog.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef XP_MAC
+#include "prlog.h"
+#include "macstdlibextras.h"
+extern void SetupMacPrintfLog(char *logFile);
+#endif
+
+#define PRINT_DETAILS
+
+int failed_already=0;
+PRBool debug_mode = PR_FALSE;
+
+static char *dayOfWeek[] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" };
+static char *month[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };
+
+PRLogModuleInfo *lm;
+
+static void PrintExplodedTime(const PRExplodedTime *et) {
+ PRInt32 totalOffset;
+ PRInt32 hourOffset, minOffset;
+ const char *sign;
+
+ /* Print day of the week, month, day, hour, minute, and second */
+ printf("%s %s %2ld %02ld:%02ld:%02ld ",
+ dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday,
+ et->tm_hour, et->tm_min, et->tm_sec);
+
+ /* Print year */
+ printf("%hd ", et->tm_year);
+
+ /* Print time zone */
+ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset;
+ if (totalOffset == 0) {
+ printf("UTC ");
+ } else {
+ sign = "+";
+ if (totalOffset < 0) {
+ totalOffset = -totalOffset;
+ sign = "-";
+ }
+ hourOffset = totalOffset / 3600;
+ minOffset = (totalOffset % 3600) / 60;
+ printf("%s%02ld%02ld ", sign, hourOffset, minOffset);
+ }
+#ifdef PRINT_DETAILS
+ printf("{%d, %d, %d, %d, %d, %d, %d, %d, %d, { %d, %d}}\n",et->tm_usec,
+ et->tm_sec,
+ et->tm_min,
+ et->tm_hour,
+ et->tm_mday,
+ et->tm_month,
+ et->tm_year,
+ et->tm_wday,
+ et->tm_yday,
+ et->tm_params.tp_gmt_offset,
+ et->tm_params.tp_dst_offset);
+#endif
+}
+
+static int ExplodedTimeIsEqual(const PRExplodedTime *et1,
+ const PRExplodedTime *et2)
+{
+ if (et1->tm_usec == et2->tm_usec &&
+ et1->tm_sec == et2->tm_sec &&
+ et1->tm_min == et2->tm_min &&
+ et1->tm_hour == et2->tm_hour &&
+ et1->tm_mday == et2->tm_mday &&
+ et1->tm_month == et2->tm_month &&
+ et1->tm_year == et2->tm_year &&
+ et1->tm_wday == et2->tm_wday &&
+ et1->tm_yday == et2->tm_yday &&
+ et1->tm_params.tp_gmt_offset == et2->tm_params.tp_gmt_offset &&
+ et1->tm_params.tp_dst_offset == et2->tm_params.tp_dst_offset) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * TEST 1: TestExplodeImplodeTime
+ * Description:
+ * For each given timestamp T (a PRTime value), call PR_ExplodeTime
+ * with GMT, US Pacific, and local time parameters. Compare the
+ * resulting calendar (exploded) time values with the expected
+ * values.
+ *
+ * Note: the expected local time values depend on the local time
+ * zone. The local time values stored in this test are for the US
+ * Pacific Time Zone. If you are running this test in a different
+ * time zone, you need to modify the values in the localt array.
+ * An example is provided below.
+ *
+ * Call PR_ImplodeTime for each of the exploded values and compare
+ * the resulting PRTime values with the original input.
+ *
+ * This test is run for the values of time T corresponding to the
+ * following dates:
+ * - 12/31/99 - before 2000
+ * - 01/01/00 - after 2000
+ * - Leap year - Feb 29, 2000
+ * - March 1st, 2001 (after 1 year)
+ * - March 1st, 2005 (after second leap year)
+ * - 09/09/99 (used by some programs as an end of file marker)
+ *
+ * Call PR_Now, convert to calendar time using PR_ExplodeTime and
+ * manually check the result for correctness. The time should match
+ * the system clock.
+ *
+ * Tested functions: PR_Now, PR_ExplodeTime, PR_ImplodeTime,
+ * PR_LocalTimeParameters, PR_GMTParameters.
+ */
+
+static PRTime prt[] = {
+ LL_INIT(220405, 2133125120), /* 946634400000000 */
+ LL_INIT(220425, 2633779200), /* 946720800000000 */
+ LL_INIT(221612, 2107598848), /* 951818400000000 */
+ LL_INIT(228975, 663398400), /* 983440800000000 */
+ LL_INIT(258365, 1974568960), /* 1109671200000000 */
+ LL_INIT(218132, 1393788928), /* 936871200000000 */
+ /* Sun's dates follow */
+ LL_INIT( 213062, 4077979648 ), /* Dec 31 1998 10:00:00 */
+ LL_INIT( 218152, 1894443008 ), /* Sep 10 1999 10:00:00 */
+ LL_INIT( 221592, 1606944768 ), /* Feb 28 2000 10:00:00 */
+ LL_INIT( 227768, 688924672 ), /* Dec 31 2000 10:00:00 */
+ LL_INIT( 227788, 1189578752 ), /* Jan 1 2001 10:00:00 */
+};
+
+static PRExplodedTime gmt[] = {
+ { 0, 0, 0, 10, 31, 11, 1999, 5, 364, {0, 0}}, /* 1999/12/31 10:00:00 GMT */
+ { 0, 0, 0, 10, 1, 0, 2000, 6, 0, {0, 0}}, /* 2000/01/01 10:00:00 GMT */
+ { 0, 0, 0, 10, 29, 1, 2000, 2, 59, {0, 0}}, /* 2000/02/29 10:00:00 GMT */
+ { 0, 0, 0, 10, 1, 2, 2001, 4, 59, {0, 0}}, /* 2001/3/1 10:00:00 GMT */
+ { 0, 0, 0, 10, 1, 2, 2005, 2, 59, {0, 0}}, /* 2005/3/1 10:00:00 GMT */
+ { 0, 0, 0, 10, 9, 8, 1999, 4, 251, {0, 0}}, /* 1999/9/9 10:00:00 GMT */
+ /* Sun's dates follow */
+ { 0, 0, 0, 10, 31, 11, 1998, 4, 364, {0, 0}}, /* 12/31/1998 10:00:00 GMT */
+ { 0, 0, 0, 10, 10, 8, 1999, 5, 252, {0, 0}}, /* 9/10/1999 10:00:00 GMT */
+ { 0, 0, 0, 10, 28, 1, 2000, 1, 58, {0, 0}}, /* 2/28/2000 10:00:00 GMT */
+ { 0, 0, 0, 10, 31, 11, 2000, 0, 365, {0, 0}}, /* 12/31/2000 10:00:00 GMT */
+ { 0, 0, 0, 10, 1, 0, 2001, 1, 0, {0, 0}} /* 1/1/2001 10:00:00 GMT */
+};
+
+static PRExplodedTime uspt[] = {
+{ 0, 0, 0, 2, 31, 11, 1999, 5, 364, {-28800, 0}}, /* 1999/12/31 2:00:00 PST */
+{ 0, 0, 0, 2, 1, 0, 2000, 6, 0, {-28800, 0}}, /* 2000/01/01 2:00:00 PST */
+{ 0, 0, 0, 2, 29, 1, 2000, 2, 59, {-28800, 0}}, /* 2000/02/29 2:00:00 PST */
+{ 0, 0, 0, 2, 1, 2, 2001, 4, 59, {-28800, 0}}, /* 2001/3/1 2:00:00 PST */
+{ 0, 0, 0, 2, 1, 2, 2005, 2, 59, {-28800, 0}}, /* 2005/3/1 2:00:00 PST */
+{ 0, 0, 0, 3, 9, 8, 1999, 4, 251, {-28800, 3600}}, /* 1999/9/9 3:00:00 PDT */
+ /* Sun's dates follow */
+ { 0, 0, 0, 2, 31, 11, 1998, 4, 364, {-28800, 0}}, /* 12/31/1998 00:00:00 GMT */
+ { 0, 0, 0, 3, 10, 8, 1999, 5, 252, {-28800, 3600}}, /* 9/10/1999 00:00:00 GMT */
+ { 0, 0, 0, 2, 28, 1, 2000, 1, 58, {-28800, 0}}, /* 2/28/2000 00:00:00 GMT */
+ { 0, 0, 0, 2, 31, 11, 2000, 0, 365, {-28800, 0}}, /* 12/31/2000 00:00:00 GMT */
+ { 0, 0, 0, 2, 1, 0, 2001, 1, 0, {-28800, 0}} /* 1/1/2001 00:00:00 GMT */
+};
+
+/*
+ * This test assumes that we are in US Pacific Time Zone.
+ * If you are running this test in a different time zone,
+ * you need to modify the localt array and fill in the
+ * expected results. The localt array for US Eastern Time
+ * Zone is provided as an example.
+ */
+static PRExplodedTime localt[] = {
+{ 0, 0, 0, 2, 31, 11, 1999, 5, 364, {-28800, 0}}, /* 1999/12/31 2:00:00 PST */
+{ 0, 0, 0, 2, 1, 0, 2000, 6, 0, {-28800, 0}}, /* 2000/01/01 2:00:00 PST */
+{ 0, 0, 0, 2, 29, 1, 2000, 2, 59, {-28800, 0}}, /* 2000/02/29 2:00:00 PST */
+{ 0, 0, 0, 2, 1, 2, 2001, 4, 59, {-28800, 0}}, /* 2001/3/1 2:00:00 PST */
+{ 0, 0, 0, 2, 1, 2, 2005, 2, 59, {-28800, 0}}, /* 2005/3/1 2:00:00 PST */
+{ 0, 0, 0, 3, 9, 8, 1999, 4, 251, {-28800, 3600}}, /* 1999/9/9 3:00:00 PDT */
+ /* Sun's dates follow */
+ { 0, 0, 0, 2, 31, 11, 1998, 4, 364, {-28800, 0}}, /* 12/31/1998 00:00:00 GMT */
+ { 0, 0, 0, 3, 10, 8, 1999, 5, 252, {-28800, 3600}}, /* 9/10/1999 00:00:00 GMT */
+ { 0, 0, 0, 2, 28, 1, 2000, 1, 58, {-28800, 0}}, /* 2/28/2000 00:00:00 GMT */
+ { 0, 0, 0, 2, 31, 11, 2000, 0, 365, {-28800, 0}}, /* 12/31/2000 00:00:00 GMT */
+ { 0, 0, 0, 2, 1, 0, 2001, 1, 0, {-28800, 0}} /* 1/1/2001 00:00:00 GMT */
+};
+
+#ifdef US_EASTERN_TIME
+static PRExplodedTime localt[] = {
+{ 0, 0, 0, 5, 31, 11, 1999, 5, 364, {-18000, 0}}, /* 1999/12/31 2:00:00 EST */
+{ 0, 0, 0, 5, 1, 0, 2000, 6, 0, {-18000, 0}}, /* 2000/01/01 2:00:00 EST */
+{ 0, 0, 0, 5, 29, 1, 2000, 2, 59, {-18000, 0}}, /* 2000/02/29 2:00:00 EST */
+{ 0, 0, 0, 5, 1, 2, 2001, 4, 59, {-18000, 0}}, /* 2001/3/1 2:00:00 EST */
+{ 0, 0, 0, 5, 1, 2, 2005, 2, 59, {-18000, 0}}, /* 2005/3/1 2:00:00 EST */
+{ 0, 0, 0, 6, 9, 8, 1999, 4, 251, {-18000, 3600}}, /* 1999/9/9 3:00:00 EDT */
+ /* Sun's dates follow */
+ { 0, 0, 0, 5, 31, 11, 1998, 4, 364, {-18000 0}}, /* 12/31/1998 00:00:00 GMT */
+ { 0, 0, 0, 6, 10, 8, 1999, 5, 252, {-18000 3600}}, /* 9/10/1999 00:00:00 GMT */
+ { 0, 0, 0, 5, 28, 1, 2000, 1, 58, {-18000 0}}, /* 2/28/2000 00:00:00 GMT */
+ { 0, 0, 0, 5, 31, 11, 2000, 0, 365, {-18000 0}}, /* 12/31/2000 00:00:00 GMT */
+ { 0, 0, 0, 5, 1, 0, 2001, 1, 0, {-18000 0}} /* 1/1/2001 00:00:00 GMT */
+};
+#endif
+
+static PRStatus TestExplodeImplodeTime(void)
+{
+ PRTime prt_tmp;
+ PRTime now;
+ int idx;
+ int array_size = sizeof(prt) / sizeof(PRTime);
+ PRExplodedTime et_tmp;
+ char buf[1024];
+
+ for (idx = 0; idx < array_size; idx++) {
+ PR_snprintf(buf, sizeof(buf), "%lld", prt[idx]);
+ if (debug_mode) printf("Time stamp %s\n", buf);
+ PR_ExplodeTime(prt[idx], PR_GMTParameters, &et_tmp);
+ if (!ExplodedTimeIsEqual(&et_tmp, &gmt[idx])) {
+ fprintf(stderr, "GMT not equal\n");
+ PrintExplodedTime(&et_tmp);
+ PrintExplodedTime(&gmt[idx]);
+ exit(1);
+ }
+ prt_tmp = PR_ImplodeTime(&et_tmp);
+ if (LL_NE(prt_tmp, prt[idx])) {
+ fprintf(stderr, "PRTime not equal\n");
+ exit(1);
+ }
+ if (debug_mode) {
+ printf("GMT: ");
+ PrintExplodedTime(&et_tmp);
+ printf("\n");
+ }
+
+ PR_ExplodeTime(prt[idx], PR_USPacificTimeParameters, &et_tmp);
+ if (!ExplodedTimeIsEqual(&et_tmp, &uspt[idx])) {
+ fprintf(stderr, "US Pacific Time not equal\n");
+ PrintExplodedTime(&et_tmp);
+ PrintExplodedTime(&uspt[idx]);
+ exit(1);
+ }
+ prt_tmp = PR_ImplodeTime(&et_tmp);
+ if (LL_NE(prt_tmp, prt[idx])) {
+ fprintf(stderr, "PRTime not equal\n");
+ exit(1);
+ }
+ if (debug_mode) {
+ printf("US Pacific Time: ");
+ PrintExplodedTime(&et_tmp);
+ printf("\n");
+ }
+
+ PR_ExplodeTime(prt[idx], PR_LocalTimeParameters, &et_tmp);
+ if (!ExplodedTimeIsEqual(&et_tmp, &localt[idx])) {
+ fprintf(stderr, "not equal\n");
+ PrintExplodedTime(&et_tmp);
+ PrintExplodedTime(&localt[idx]);
+ exit(1);
+ }
+ prt_tmp = PR_ImplodeTime(&et_tmp);
+ if (LL_NE(prt_tmp, prt[idx])) {
+ fprintf(stderr, "not equal\n");
+ exit(1);
+ }
+ if (debug_mode) {
+ printf("Local time:");
+ PrintExplodedTime(&et_tmp);
+ printf("\n\n");
+ }
+ }
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_GMTParameters, &et_tmp);
+ printf("Current GMT is ");
+ PrintExplodedTime(&et_tmp);
+ printf("\n");
+ prt_tmp = PR_ImplodeTime(&et_tmp);
+ if (LL_NE(prt_tmp, now)) {
+ fprintf(stderr, "not equal\n");
+ exit(1);
+ }
+ PR_ExplodeTime(now, PR_USPacificTimeParameters, &et_tmp);
+ printf("Current US Pacific Time is ");
+ PrintExplodedTime(&et_tmp);
+ printf("\n");
+ prt_tmp = PR_ImplodeTime(&et_tmp);
+ if (LL_NE(prt_tmp, now)) {
+ fprintf(stderr, "not equal\n");
+ exit(1);
+ }
+ PR_ExplodeTime(now, PR_LocalTimeParameters, &et_tmp);
+ printf("Current local time is ");
+ PrintExplodedTime(&et_tmp);
+ printf("\n");
+ prt_tmp = PR_ImplodeTime(&et_tmp);
+ if (LL_NE(prt_tmp, now)) {
+ fprintf(stderr, "not equal\n");
+ exit(1);
+ }
+ printf("Please verify the results\n\n");
+
+ if (debug_mode) printf("Test 1 passed\n");
+ return PR_SUCCESS;
+}
+/* End of Test 1: TestExplodeImplodeTime */
+
+/*
+ * Test 2: Normalize Time
+ */
+
+/*
+ * time increment for addition to PRExplodeTime
+ */
+typedef struct time_increment {
+ PRInt32 ti_usec;
+ PRInt32 ti_sec;
+ PRInt32 ti_min;
+ PRInt32 ti_hour;
+} time_increment_t;
+
+/*
+ * Data for testing PR_Normalize
+ * Add the increment to base_time, normalize it to GMT and US Pacific
+ * Time zone.
+ */
+typedef struct normalize_test_data {
+ PRExplodedTime base_time;
+ time_increment_t increment;
+ PRExplodedTime expected_gmt_time;
+ PRExplodedTime expected_uspt_time;
+} normalize_test_data_t;
+
+
+/*
+ * Test data - the base time values cover dates of interest including y2k - 1,
+ * y2k + 1, y2k leap year, y2k leap date + 1year,
+ * y2k leap date + 4 years
+ */
+normalize_test_data_t normalize_test_array[] = {
+ /*usec sec min hour mday mo year wday yday {gmtoff, dstoff }*/
+
+ /* Fri 12/31/1999 19:32:48 PST */
+ {{0, 48, 32, 19, 31, 11, 1999, 5, 364, { -28800, 0}},
+ {0, 0, 30, 20},
+ {0, 48, 2, 0, 2, 0, 2000, 0, 1, { 0, 0}}, /*Sun Jan 2 00:02:48 UTC 2000*/
+ {0, 48, 2, 16, 1, 0, 2000, 6, 0, { -28800, 0}},/* Sat Jan 1 16:02:48
+ PST 2000*/
+ },
+ /* Fri 99-12-31 23:59:02 GMT */
+ {{0, 2, 59, 23, 31, 11, 1999, 5, 364, { 0, 0}},
+ {0, 0, 45, 0},
+ {0, 2, 44, 0, 1, 0, 2000, 6, 0, { 0, 0}},/* Sat Jan 1 00:44:02 UTC 2000*/
+ {0, 2, 44, 16, 31, 11, 1999, 5, 364, { -28800, 0}}/*Fri Dec 31 16:44:02
+ PST 1999*/
+ },
+ /* 99-12-25 12:00:00 GMT */
+ {{0, 0, 0, 12, 25, 11, 1999, 6, 358, { 0, 0}},
+ {0, 0, 0, 364 * 24},
+ {0, 0, 0, 12, 23, 11, 2000, 6, 357, { 0, 0}},/*Sat Dec 23 12:00:00
+ 2000 UTC*/
+ {0, 0, 0, 4, 23, 11, 2000, 6, 357, { -28800, 0}}/*Sat Dec 23 04:00:00
+ 2000 -0800*/
+ },
+ /* 00-01-1 00:00:00 PST */
+ {{0, 0, 0, 0, 1, 0, 2000, 6, 0, { -28800, 0}},
+ {0, 0, 0, 48},
+ {0, 0, 0, 8, 3, 0, 2000, 1, 2, { 0, 0}},/*Mon Jan 3 08:00:00 2000 UTC*/
+ {0, 0, 0, 0, 3, 0, 2000, 1, 2, { -28800, 0}}/*Mon Jan 3 00:00:00 2000
+ -0800*/
+ },
+ /* 00-01-10 12:00:00 PST */
+ {{0, 0, 0, 12, 10, 0, 2000, 1, 9, { -28800, 0}},
+ {0, 0, 0, 364 * 5 * 24},
+ {0, 0, 0, 20, 3, 0, 2005, 1, 2, { 0, 0}},/*Mon Jan 3 20:00:00 2005 UTC */
+ {0, 0, 0, 12, 3, 0, 2005, 1, 2, { -28800, 0}}/*Mon Jan 3 12:00:00
+ 2005 -0800*/
+ },
+ /* 00-02-28 15:39 GMT */
+ {{0, 0, 39, 15, 28, 1, 2000, 1, 58, { 0, 0}},
+ {0, 0, 0, 24},
+ {0, 0, 39, 15, 29, 1, 2000, 2, 59, { 0, 0}}, /*Tue Feb 29 15:39:00 2000
+ UTC*/
+ {0, 0, 39, 7, 29, 1, 2000, 2, 59, { -28800, 0}}/*Tue Feb 29 07:39:00
+ 2000 -0800*/
+ },
+ /* 01-03-01 12:00 PST */
+ {{0, 0, 0, 12, 3, 0, 2001, 3, 2, { -28800, 0}},/*Wed Jan 3 12:00:00
+ -0800 2001*/
+ {0, 30, 30,45},
+ {0, 30, 30, 17, 5, 0, 2001, 5, 4, { 0, 0}}, /*Fri Jan 5 17:30:30 2001
+ UTC*/
+ {0, 30, 30, 9, 5, 0, 2001, 5, 4, { -28800, 0}} /*Fri Jan 5 09:30:30
+ 2001 -0800*/
+ },
+ /* 2004-04-26 12:00 GMT */
+ {{0, 0, 0, 20, 3, 0, 2001, 3, 2, { 0, 0}},
+ {0, 0, 30,0},
+ {0, 0, 30, 20, 3, 0, 2001, 3, 2, { 0, 0}},/*Wed Jan 3 20:30:00 2001 UTC*/
+ {0, 0, 30, 12, 3, 0, 2001, 3, 2, { -28800, 0}}/*Wed Jan 3 12:30:00
+ 2001 -0800*/
+ },
+ /* 99-09-09 00:00 GMT */
+ {{0, 0, 0, 0, 9, 8, 1999, 4, 251, { 0, 0}},
+ {0, 0, 0, 12},
+ {0, 0, 0, 12, 9, 8, 1999, 4, 251, { 0, 0}},/*Thu Sep 9 12:00:00 1999 UTC*/
+ {0, 0, 0, 5, 9, 8, 1999, 4, 251, { -28800, 3600}}/*Thu Sep 9 05:00:00
+ 1999 -0700*/
+ }
+};
+
+void add_time_increment(PRExplodedTime *et1, time_increment_t *it)
+{
+ et1->tm_usec += it->ti_usec;
+ et1->tm_sec += it->ti_sec;
+ et1->tm_min += it->ti_min;
+ et1->tm_hour += it->ti_hour;
+}
+
+/*
+** TestNormalizeTime() -- Test PR_NormalizeTime()
+** For each data item, add the time increment to the base_time and then
+** normalize it for GMT and local time zones. This test assumes that
+** the local time zone is the Pacific Time Zone. The normalized values
+** should match the expected values in the data item.
+**
+*/
+PRStatus TestNormalizeTime(void)
+{
+int idx, count;
+normalize_test_data_t *itemp;
+time_increment_t *itp;
+
+ count = sizeof(normalize_test_array)/sizeof(normalize_test_array[0]);
+ for (idx = 0; idx < count; idx++) {
+ itemp = &normalize_test_array[idx];
+ if (debug_mode) {
+ printf("%2d. %15s",idx +1,"Base time: ");
+ PrintExplodedTime(&itemp->base_time);
+ printf("\n");
+ }
+ itp = &itemp->increment;
+ if (debug_mode) {
+ printf("%20s %2d hrs %2d min %3d sec\n","Add",itp->ti_hour,
+ itp->ti_min, itp->ti_sec);
+ }
+ add_time_increment(&itemp->base_time, &itemp->increment);
+ PR_NormalizeTime(&itemp->base_time, PR_LocalTimeParameters);
+ if (debug_mode) {
+ printf("%19s","PST time: ");
+ PrintExplodedTime(&itemp->base_time);
+ printf("\n");
+ }
+ if (!ExplodedTimeIsEqual(&itemp->base_time,
+ &itemp->expected_uspt_time)) {
+ printf("PR_NormalizeTime failed\n");
+ if (debug_mode)
+ PrintExplodedTime(&itemp->expected_uspt_time);
+ return PR_FAILURE;
+ }
+ PR_NormalizeTime(&itemp->base_time, PR_GMTParameters);
+ if (debug_mode) {
+ printf("%19s","GMT time: ");
+ PrintExplodedTime(&itemp->base_time);
+ printf("\n");
+ }
+
+ if (!ExplodedTimeIsEqual(&itemp->base_time,
+ &itemp->expected_gmt_time)) {
+ printf("PR_NormalizeTime failed\n");
+ return PR_FAILURE;
+ }
+ }
+ return PR_SUCCESS;
+}
+
+
+/*
+** ParseTest. Structure defining a string time and a matching exploded time
+**
+*/
+typedef struct ParseTest
+{
+ char *sDate; /* string to be converted using PR_ParseTimeString() */
+ PRExplodedTime et; /* expected result of the conversion */
+} ParseTest;
+
+static ParseTest parseArray[] =
+{
+ /* |<----- expected result ------------------------------------------->| */
+ /* "string to test" usec sec min hour day mo year wday julian {gmtoff, dstoff }*/
+ { "Thursday 1 Jan 1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "1 Jan 1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "1-Jan-1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "01-Jan-1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "January 1, 1970", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "January 1, 1970 00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "January 01, 1970 00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "January 01 1970 00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "January 01 1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "01-01-1970", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "01/01/1970", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "01/01/70", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "01/01/70 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "70/01/01 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "70/1/1 00:00:", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "00:00 Thursday, January 1, 1970",{ 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "1-Jan-70 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "70-01-01 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+ { "70/01/01 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}},
+
+ /* 31-Dec-1969 */
+ { "Wed 31 Dec 1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}},
+ { "31 Dec 1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}},
+ { "12/31/69 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}},
+ { "12/31/1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}},
+ { "12-31-69 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}},
+ { "12-31-1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}},
+ { "69-12-31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}},
+ { "69/12/31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}},
+
+ /* "Sun". 31-Dec-1998 (?) */
+ { "Thu 31 Dec 1998 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+ { "12/31/98 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+ { "12/31/1998 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+ { "12-31-98 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+ { "12-31-1998 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+ { "98-12-31 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+ { "98/12/31 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}},
+
+ /* 09-Sep-1999. Interesting because of its use as an eof marker? */
+ { "09 Sep 1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "9/9/99 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "9/9/1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "9-9-99 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "9-9-1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "09-09-99 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "09-09-1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+ { "99-09-09 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}},
+
+ /* "Sun". 10-Sep-1999. Because Sun said so. */
+ { "10 Sep 1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "9/10/99 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "9/10/1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "9-10-99 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "9-10-1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "09-10-99 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "09-10-1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+ { "99-09-10 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}},
+
+ /* 31-Dec-1999 */
+ { "31 Dec 1999 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+ { "12/31/99 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+ { "12/31/1999 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+ { "12-31-99 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+ { "12-31-1999 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+ { "99-12-31 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+ { "99/12/31 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}},
+
+ /* 01-Jan-2000 */
+ { "01 Jan 2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+ { "1/1/00 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+ { "1/1/2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+ { "1-1-00 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+ { "1-1-2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+ { "01-01-00 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+ { "Saturday 01-01-2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}},
+
+ /* "Sun". 28-Feb-2000 */
+ { "28 Feb 2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+ { "2/28/00 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+ { "2/28/2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+ { "2-28-00 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+ { "2-28-2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+ { "02-28-00 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+ { "02-28-2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}},
+
+ /* 29-Feb-2000 */
+ { "29 Feb 2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+ { "2/29/00 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+ { "2/29/2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+ { "2-29-00 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+ { "2-29-2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+ { "02-29-00 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+ { "02-29-2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}},
+
+ /* 01-Mar-2000 */
+ { "01 Mar 2000 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}},
+ { "3/1/00 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}},
+ { "3/1/2000 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}},
+ { "3-1-00 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}},
+ { "03-01-00 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}},
+ { "03-01-2000 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}},
+
+ /* "Sun". 31-Dec-2000 */
+ { "31 Dec 2000 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+ { "12/31/00 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+ { "12/31/2000 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+ { "12-31-00 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+ { "12-31-2000 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+ { "00-12-31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+ { "00/12/31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}},
+
+ /* "Sun". 01-Jan-2001 */
+ { "01 Jan 2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+ { "1/1/01 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+ { "1/1/2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+ { "1-1-01 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+ { "1-1-2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+ { "01-01-01 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+ { "Saturday 01-01-2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}},
+
+ /* 01-Mar-2001 */
+ { "01 Mar 2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+ { "3/1/01 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+ { "3/1/2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+ { "3-1-01 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+ { "3-1-2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+ { "03-01-01 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+ { "03-01-2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}},
+
+ /* 29-Feb-2004 */
+ { "29 Feb 2004 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}},
+ { "2/29/04 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}},
+ { "2/29/2004 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}},
+ { "2-29-04 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}},
+ { "2-29-2004 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}},
+
+ /* 01-Mar-2004 */
+ { "01 Mar 2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+ { "3/1/04 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+ { "3/1/2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+ { "3-1-04 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+ { "3-1-2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+ { "03-01-04 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+ { "03-01-2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}},
+
+ /* 01-Mar-2005 */
+ { "01 Mar 2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+ { "3/1/05 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+ { "3/1/2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+ { "3-1-05 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+ { "3-1-2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+ { "03-01-05 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+ { "03-01-2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}},
+
+ /* last element. string must be null */
+ { NULL }
+}; /* end array of ParseTest */
+
+/*
+** TestParseTime() -- Test PR_ParseTimeString() for y2k compliance
+**
+** TestParseTime() loops thru the array parseArray. For each element in
+** the array, he calls PR_ParseTimeString() with sDate as the conversion
+** argument. The result (ct) is then converted to a PRExplodedTime structure
+** and compared with the exploded time value (parseArray[n].et) in the
+** array element; if equal, the element passes the test.
+**
+** The array parseArray[] contains entries that are interesting to the
+** y2k problem.
+**
+**
+*/
+static PRStatus TestParseTime( void )
+{
+ ParseTest *ptp = parseArray;
+ PRTime ct;
+ PRExplodedTime cet;
+ char *sp = ptp->sDate;
+ PRStatus rc;
+ PRStatus rv = PR_SUCCESS;
+
+ while ( sp != NULL)
+ {
+ rc = PR_ParseTimeString( sp, PR_FALSE, &ct );
+ if ( PR_FAILURE == rc )
+ {
+ printf("TestParseTime(): PR_ParseTimeString() failed to convert: %s\n", sp );
+ rv = PR_FAILURE;
+ failed_already = 1;
+ }
+ else
+ {
+ PR_ExplodeTime( ct, PR_LocalTimeParameters , &cet );
+
+ if ( !ExplodedTimeIsEqual( &cet, &ptp->et ))
+ {
+ printf("TestParseTime(): Exploded time compare failed: %s\n", sp );
+ if ( debug_mode )
+ {
+ PrintExplodedTime( &cet );
+ printf("\n");
+ PrintExplodedTime( &ptp->et );
+ printf("\n");
+ }
+
+ rv = PR_FAILURE;
+ failed_already = 1;
+ }
+ }
+
+ /* point to next element in array, keep going */
+ ptp++;
+ sp = ptp->sDate;
+ } /* end while() */
+
+ return( rv );
+} /* end TestParseTime() */
+
+int main(int argc, char** argv)
+{
+ /* The command line argument: -d is used to determine if the test is being run
+ in debug mode. The regress tool requires only one line output:PASS or FAIL.
+ All of the printfs associated with this test has been handled with a if (debug_mode)
+ test.
+ Usage: test_name -d
+ */
+ PLOptStatus os;
+ PLOptState *opt;
+
+ PR_STDIO_INIT();
+ opt = PL_CreateOptState(argc, argv, "d");
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ /* main test */
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ lm = PR_NewLogModule("test");
+
+#ifdef XP_MAC
+ /* Set up the console */
+ InitializeSIOUX(true);
+ debug_mode = PR_TRUE;
+#endif
+
+ if ( PR_FAILURE == TestExplodeImplodeTime())
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("TestExplodeImplodeTime() failed"));
+ }
+ else
+ printf("Test 1: Calendar Time Test passed\n");
+
+ if ( PR_FAILURE == TestNormalizeTime())
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("TestNormalizeTime() failed"));
+ }
+ else
+ printf("Test 2: Normalize Time Test passed\n");
+
+ if ( PR_FAILURE == TestParseTime())
+ {
+ PR_LOG( lm, PR_LOG_ERROR,
+ ("TestParseTime() failed"));
+ }
+ else
+ printf("Test 3: Parse Time Test passed\n");
+
+#ifdef XP_MAC
+ if (1)
+ {
+ char dummyChar;
+
+ printf("Press return to exit\n\n");
+ scanf("%c", &dummyChar);
+ }
+#endif
+
+ if (failed_already)
+ return 1;
+ else
+ return 0;
+} /* end main() y2k.c */
+
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/y2ktmo.c b/src/libs/xpcom18a4/nsprpub/pr/tests/y2ktmo.c
new file mode 100644
index 00000000..a37ae072
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/y2ktmo.c
@@ -0,0 +1,546 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Test: y2ktmo
+ *
+ * Description:
+ * This test tests the interval time facilities in NSPR for Y2K
+ * compliance. All the functions that take a timeout argument
+ * are tested: PR_Sleep, socket I/O (PR_Accept is taken as a
+ * representative), PR_Poll, PR_WaitCondVar, PR_Wait, and
+ * PR_CWait. A thread of each thread scope (local, global, and
+ * global bound) is created to call each of these functions.
+ * The test should be started at the specified number of seconds
+ * (called the lead time) before a Y2K rollover test date. The
+ * timeout values for these threads will span over the rollover
+ * date by at least the specified number of seconds. For
+ * example, if the lead time is 5 seconds, the test should
+ * be started at time (D - 5), where D is a rollover date, and
+ * the threads will time out at or after time (D + 5). The
+ * timeout values for the threads are spaced one second apart.
+ *
+ * When a thread times out, it calls PR_IntervalNow() to verify
+ * that it did wait for the specified time. In addition, it
+ * calls a platform-native function to verify the actual elapsed
+ * time again, to rule out the possibility that PR_IntervalNow()
+ * is broken. We allow the actual elapsed time to deviate from
+ * the specified timeout by a certain tolerance (in milliseconds).
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(XP_UNIX)
+#include <sys/time.h> /* for gettimeofday */
+#endif
+#if defined(WIN32)
+#include <sys/types.h>
+#include <sys/timeb.h> /* for _ftime */
+#endif
+
+#define DEFAULT_LEAD_TIME_SECS 5
+#define DEFAULT_TOLERANCE_MSECS 500
+
+static PRBool debug_mode = PR_FALSE;
+static PRInt32 lead_time_secs = DEFAULT_LEAD_TIME_SECS;
+static PRInt32 tolerance_msecs = DEFAULT_TOLERANCE_MSECS;
+static PRIntervalTime start_time;
+static PRIntervalTime tolerance;
+
+#if defined(XP_UNIX)
+static struct timeval start_time_tv;
+#endif
+#if defined(WIN32)
+static struct _timeb start_time_tb;
+#endif
+
+static void SleepThread(void *arg)
+{
+ PRIntervalTime timeout = (PRIntervalTime) arg;
+ PRIntervalTime elapsed;
+#if defined(XP_UNIX) || defined(WIN32)
+ PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
+ PRInt32 elapsed_msecs;
+#endif
+#if defined(XP_UNIX)
+ struct timeval end_time_tv;
+#endif
+#if defined(WIN32)
+ struct _timeb end_time_tb;
+#endif
+
+ if (PR_Sleep(timeout) == PR_FAILURE) {
+ fprintf(stderr, "PR_Sleep failed\n");
+ exit(1);
+ }
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
+ if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#if defined(XP_UNIX)
+ gettimeofday(&end_time_tv, NULL);
+ elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
+ + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
+#endif
+#if defined(WIN32)
+ _ftime(&end_time_tb);
+ elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
+ + (end_time_tb.millitm - start_time_tb.millitm);
+#endif
+#if defined(XP_UNIX) || defined(WIN32)
+ if (elapsed_msecs + tolerance_msecs < timeout_msecs
+ || elapsed_msecs > timeout_msecs + tolerance_msecs) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#endif
+ if (debug_mode) {
+ fprintf(stderr, "Sleep thread (scope %d) done\n",
+ PR_GetThreadScope(PR_GetCurrentThread()));
+ }
+}
+
+static void AcceptThread(void *arg)
+{
+ PRIntervalTime timeout = (PRIntervalTime) arg;
+ PRIntervalTime elapsed;
+#if defined(XP_UNIX) || defined(WIN32)
+ PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
+ PRInt32 elapsed_msecs;
+#endif
+#if defined(XP_UNIX)
+ struct timeval end_time_tv;
+#endif
+#if defined(WIN32)
+ struct _timeb end_time_tb;
+#endif
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ PRFileDesc *accepted;
+
+ sock = PR_NewTCPSocket();
+ if (sock == NULL) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = 0;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ if (PR_Bind(sock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_Listen(sock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+ accepted = PR_Accept(sock, NULL, timeout);
+ if (accepted != NULL || PR_GetError() != PR_IO_TIMEOUT_ERROR) {
+ fprintf(stderr, "PR_Accept did not time out\n");
+ exit(1);
+ }
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
+ if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#if defined(XP_UNIX)
+ gettimeofday(&end_time_tv, NULL);
+ elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
+ + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
+#endif
+#if defined(WIN32)
+ _ftime(&end_time_tb);
+ elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
+ + (end_time_tb.millitm - start_time_tb.millitm);
+#endif
+#if defined(XP_UNIX) || defined(WIN32)
+ if (elapsed_msecs + tolerance_msecs < timeout_msecs
+ || elapsed_msecs > timeout_msecs + tolerance_msecs) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#endif
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (debug_mode) {
+ fprintf(stderr, "Accept thread (scope %d) done\n",
+ PR_GetThreadScope(PR_GetCurrentThread()));
+ }
+}
+
+static void PollThread(void *arg)
+{
+ PRIntervalTime timeout = (PRIntervalTime) arg;
+ PRIntervalTime elapsed;
+#if defined(XP_UNIX) || defined(WIN32)
+ PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
+ PRInt32 elapsed_msecs;
+#endif
+#if defined(XP_UNIX)
+ struct timeval end_time_tv;
+#endif
+#if defined(WIN32)
+ struct _timeb end_time_tb;
+#endif
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ PRPollDesc pd;
+ PRIntn rv;
+
+ sock = PR_NewTCPSocket();
+ if (sock == NULL) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = 0;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ if (PR_Bind(sock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ if (PR_Listen(sock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+ pd.fd = sock;
+ pd.in_flags = PR_POLL_READ;
+ rv = PR_Poll(&pd, 1, timeout);
+ if (rv != 0) {
+ fprintf(stderr, "PR_Poll did not time out\n");
+ exit(1);
+ }
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
+ if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#if defined(XP_UNIX)
+ gettimeofday(&end_time_tv, NULL);
+ elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
+ + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
+#endif
+#if defined(WIN32)
+ _ftime(&end_time_tb);
+ elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
+ + (end_time_tb.millitm - start_time_tb.millitm);
+#endif
+#if defined(XP_UNIX) || defined(WIN32)
+ if (elapsed_msecs + tolerance_msecs < timeout_msecs
+ || elapsed_msecs > timeout_msecs + tolerance_msecs) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#endif
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (debug_mode) {
+ fprintf(stderr, "Poll thread (scope %d) done\n",
+ PR_GetThreadScope(PR_GetCurrentThread()));
+ }
+}
+
+static void WaitCondVarThread(void *arg)
+{
+ PRIntervalTime timeout = (PRIntervalTime) arg;
+ PRIntervalTime elapsed;
+#if defined(XP_UNIX) || defined(WIN32)
+ PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
+ PRInt32 elapsed_msecs;
+#endif
+#if defined(XP_UNIX)
+ struct timeval end_time_tv;
+#endif
+#if defined(WIN32)
+ struct _timeb end_time_tb;
+#endif
+ PRLock *ml;
+ PRCondVar *cv;
+
+ ml = PR_NewLock();
+ if (ml == NULL) {
+ fprintf(stderr, "PR_NewLock failed\n");
+ exit(1);
+ }
+ cv = PR_NewCondVar(ml);
+ if (cv == NULL) {
+ fprintf(stderr, "PR_NewCondVar failed\n");
+ exit(1);
+ }
+ PR_Lock(ml);
+ PR_WaitCondVar(cv, timeout);
+ PR_Unlock(ml);
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
+ if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#if defined(XP_UNIX)
+ gettimeofday(&end_time_tv, NULL);
+ elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
+ + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
+#endif
+#if defined(WIN32)
+ _ftime(&end_time_tb);
+ elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
+ + (end_time_tb.millitm - start_time_tb.millitm);
+#endif
+#if defined(XP_UNIX) || defined(WIN32)
+ if (elapsed_msecs + tolerance_msecs < timeout_msecs
+ || elapsed_msecs > timeout_msecs + tolerance_msecs) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#endif
+ PR_DestroyCondVar(cv);
+ PR_DestroyLock(ml);
+ if (debug_mode) {
+ fprintf(stderr, "wait cond var thread (scope %d) done\n",
+ PR_GetThreadScope(PR_GetCurrentThread()));
+ }
+}
+
+static void WaitMonitorThread(void *arg)
+{
+ PRIntervalTime timeout = (PRIntervalTime) arg;
+ PRIntervalTime elapsed;
+#if defined(XP_UNIX) || defined(WIN32)
+ PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
+ PRInt32 elapsed_msecs;
+#endif
+#if defined(XP_UNIX)
+ struct timeval end_time_tv;
+#endif
+#if defined(WIN32)
+ struct _timeb end_time_tb;
+#endif
+ PRMonitor *mon;
+
+ mon = PR_NewMonitor();
+ if (mon == NULL) {
+ fprintf(stderr, "PR_NewMonitor failed\n");
+ exit(1);
+ }
+ PR_EnterMonitor(mon);
+ PR_Wait(mon, timeout);
+ PR_ExitMonitor(mon);
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
+ if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#if defined(XP_UNIX)
+ gettimeofday(&end_time_tv, NULL);
+ elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
+ + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
+#endif
+#if defined(WIN32)
+ _ftime(&end_time_tb);
+ elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
+ + (end_time_tb.millitm - start_time_tb.millitm);
+#endif
+#if defined(XP_UNIX) || defined(WIN32)
+ if (elapsed_msecs + tolerance_msecs < timeout_msecs
+ || elapsed_msecs > timeout_msecs + tolerance_msecs) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#endif
+ PR_DestroyMonitor(mon);
+ if (debug_mode) {
+ fprintf(stderr, "wait monitor thread (scope %d) done\n",
+ PR_GetThreadScope(PR_GetCurrentThread()));
+ }
+}
+
+static void WaitCMonitorThread(void *arg)
+{
+ PRIntervalTime timeout = (PRIntervalTime) arg;
+ PRIntervalTime elapsed;
+#if defined(XP_UNIX) || defined(WIN32)
+ PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
+ PRInt32 elapsed_msecs;
+#endif
+#if defined(XP_UNIX)
+ struct timeval end_time_tv;
+#endif
+#if defined(WIN32)
+ struct _timeb end_time_tb;
+#endif
+ int dummy;
+
+ PR_CEnterMonitor(&dummy);
+ PR_CWait(&dummy, timeout);
+ PR_CExitMonitor(&dummy);
+ elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
+ if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#if defined(XP_UNIX)
+ gettimeofday(&end_time_tv, NULL);
+ elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
+ + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
+#endif
+#if defined(WIN32)
+ _ftime(&end_time_tb);
+ elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
+ + (end_time_tb.millitm - start_time_tb.millitm);
+#endif
+#if defined(XP_UNIX) || defined(WIN32)
+ if (elapsed_msecs + tolerance_msecs < timeout_msecs
+ || elapsed_msecs > timeout_msecs + tolerance_msecs) {
+ fprintf(stderr, "timeout wrong\n");
+ exit(1);
+ }
+#endif
+ if (debug_mode) {
+ fprintf(stderr, "wait cached monitor thread (scope %d) done\n",
+ PR_GetThreadScope(PR_GetCurrentThread()));
+ }
+}
+
+typedef void (*NSPRThreadFunc)(void*);
+
+static NSPRThreadFunc threadFuncs[] = {
+ SleepThread, AcceptThread, PollThread,
+ WaitCondVarThread, WaitMonitorThread, WaitCMonitorThread};
+
+static PRThreadScope threadScopes[] = {
+ PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD};
+
+static void Help(void)
+{
+ fprintf(stderr, "y2ktmo test program usage:\n");
+ fprintf(stderr, "\t-d debug mode (FALSE)\n");
+ fprintf(stderr, "\t-l <secs> lead time (%d)\n",
+ DEFAULT_LEAD_TIME_SECS);
+ fprintf(stderr, "\t-t <msecs> tolerance (%d)\n",
+ DEFAULT_TOLERANCE_MSECS);
+ fprintf(stderr, "\t-h this message\n");
+} /* Help */
+
+int main(int argc, char **argv)
+{
+ PRThread **threads;
+ int num_thread_funcs = sizeof(threadFuncs)/sizeof(NSPRThreadFunc);
+ int num_thread_scopes = sizeof(threadScopes)/sizeof(PRThreadScope);
+ int i, j;
+ int idx;
+ PRInt32 secs;
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "dl:t:h");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option) {
+ case 'd': /* debug mode */
+ debug_mode = PR_TRUE;
+ break;
+ case 'l': /* lead time */
+ lead_time_secs = atoi(opt->value);
+ break;
+ case 't': /* tolerance */
+ tolerance_msecs = atoi(opt->value);
+ break;
+ case 'h':
+ default:
+ Help();
+ return 2;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (debug_mode) {
+ fprintf(stderr, "lead time: %d secs\n", lead_time_secs);
+ fprintf(stderr, "tolerance: %d msecs\n", tolerance_msecs);
+ }
+
+ start_time = PR_IntervalNow();
+#if defined(XP_UNIX)
+ gettimeofday(&start_time_tv, NULL);
+#endif
+#if defined(WIN32)
+ _ftime(&start_time_tb);
+#endif
+ tolerance = PR_MillisecondsToInterval(tolerance_msecs);
+
+ threads = PR_Malloc(
+ num_thread_scopes * num_thread_funcs * sizeof(PRThread*));
+ if (threads == NULL) {
+ fprintf(stderr, "PR_Malloc failed\n");
+ exit(1);
+ }
+
+ /* start to time out 5 seconds after a rollover date */
+ secs = lead_time_secs + 5;
+ idx = 0;
+ for (i = 0; i < num_thread_scopes; i++) {
+ for (j = 0; j < num_thread_funcs; j++) {
+ threads[idx] = PR_CreateThread(PR_USER_THREAD, threadFuncs[j],
+ (void*)PR_SecondsToInterval(secs), PR_PRIORITY_NORMAL,
+ threadScopes[i], PR_JOINABLE_THREAD, 0);
+ if (threads[idx] == NULL) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ secs++;
+ idx++;
+ }
+ }
+ for (idx = 0; idx < num_thread_scopes*num_thread_funcs; idx++) {
+ if (PR_JoinThread(threads[idx]) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+ }
+ PR_Free(threads);
+ printf("PASS\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/yield.c b/src/libs/xpcom18a4/nsprpub/pr/tests/yield.c
new file mode 100644
index 00000000..5f441a19
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/yield.c
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include <stdio.h>
+#include "prthread.h"
+#include "prinit.h"
+#ifndef XP_OS2
+#include "private/pprmisc.h"
+#include <windows.h>
+#else
+#include "primpl.h"
+#include <os2.h>
+#endif
+
+#define THREADS 10
+
+
+void
+threadmain(void *_id)
+{
+ int id = (int)_id;
+ int index;
+
+ printf("thread %d alive\n", id);
+ for (index=0; index<10; index++) {
+ printf("thread %d yielding\n", id);
+ PR_Sleep(0);
+ printf("thread %d awake\n", id);
+ }
+ printf("thread %d dead\n", id);
+
+}
+
+main()
+{
+ int index;
+ PRThread *a[THREADS];
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 5);
+ PR_STDIO_INIT();
+
+ for (index=0; index<THREADS; index++) {
+ a[index] = PR_CreateThread(PR_USER_THREAD,
+ threadmain,
+ (void *)index,
+ PR_PRIORITY_NORMAL,
+ index%2?PR_LOCAL_THREAD:PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ }
+ for(index=0; index<THREADS; index++)
+ PR_JoinThread(a[index]);
+ printf("main dying\n");
+}
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/zerolen.c b/src/libs/xpcom18a4/nsprpub/pr/tests/zerolen.c
new file mode 100644
index 00000000..f43f60fd
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/tests/zerolen.c
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+/*
+ * Test: zerolen.c
+ *
+ * Description: a test for Bugzilla bug #17699. We perform
+ * the same test for PR_Writev, PR_Write, and PR_Send. In
+ * each test the server thread first fills up the connection
+ * to the client so that the next write operation will fail
+ * with EAGAIN. Then it calls PR_Writev, PR_Write, or PR_Send
+ * with a zero-length buffer. The client thread initially
+ * does not read so that the connection can be filled up.
+ * Then it empties the connection so that the server thread's
+ * PR_Writev, PR_Write, or PR_Send call can succeed.
+ *
+ * Bug #17699 is specific to the pthreads version on Unix,
+ * so on other platforms this test does nothing.
+ */
+
+#ifndef XP_UNIX
+
+#include <stdio.h>
+
+int main()
+{
+ printf("PASS\n");
+ return 0;
+}
+
+#else /* XP_UNIX */
+
+#include "nspr.h"
+#include "private/pprio.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+static void ClientThread(void *arg)
+{
+ PRFileDesc *sock;
+ PRNetAddr addr;
+ PRUint16 port = (PRUint16) arg;
+ char buf[1024];
+ PRInt32 nbytes;
+
+ sock = PR_NewTCPSocket();
+ if (NULL == sock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ fprintf(stderr, "PR_Connect failed\n");
+ exit(1);
+ }
+ /*
+ * Sleep 5 seconds to force the server thread to get EAGAIN.
+ */
+ if (PR_Sleep(PR_SecondsToInterval(5)) == PR_FAILURE) {
+ fprintf(stderr, "PR_Sleep failed\n");
+ exit(1);
+ }
+ /*
+ * Then start reading.
+ */
+ while ((nbytes = PR_Read(sock, buf, sizeof(buf))) > 0) {
+ /* empty loop body */
+ }
+ if (-1 == nbytes) {
+ fprintf(stderr, "PR_Read failed\n");
+ exit(1);
+ }
+ if (PR_Close(sock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+}
+
+int main()
+{
+ PRFileDesc *listenSock;
+ PRFileDesc *acceptSock;
+ int osfd;
+ PRThread *clientThread;
+ PRNetAddr addr;
+ char buf[1024];
+ PRInt32 nbytes;
+ PRIOVec iov;
+
+ memset(buf, 0, sizeof(buf)); /* Initialize the buffer. */
+ listenSock = PR_NewTCPSocket();
+ if (NULL == listenSock) {
+ fprintf(stderr, "PR_NewTCPSocket failed\n");
+ exit(1);
+ }
+ if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_InitializeNetAddr failed\n");
+ exit(1);
+ }
+ if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_Bind failed\n");
+ exit(1);
+ }
+ /* Find out what port number we are bound to. */
+ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
+ fprintf(stderr, "PR_GetSockName failed\n");
+ exit(1);
+ }
+ if (PR_Listen(listenSock, 5) == PR_FAILURE) {
+ fprintf(stderr, "PR_Listen failed\n");
+ exit(1);
+ }
+
+ /*
+ * First test PR_Writev.
+ */
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == clientThread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == acceptSock) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+ osfd = PR_FileDesc2NativeHandle(acceptSock);
+ while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) {
+ /* empty loop body */
+ }
+ if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ fprintf(stderr, "write failed\n");
+ exit(1);
+ }
+ iov.iov_base = buf;
+ iov.iov_len = 0;
+ printf("calling PR_Writev with a zero-length buffer\n");
+ fflush(stdout);
+ nbytes = PR_Writev(acceptSock, &iov, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes != 0) {
+ fprintf(stderr, "PR_Writev should return 0 but returns %d\n", nbytes);
+ exit(1);
+ }
+ if (PR_Close(acceptSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(clientThread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+
+ /*
+ * Then test PR_Write.
+ */
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == clientThread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == acceptSock) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+ osfd = PR_FileDesc2NativeHandle(acceptSock);
+ while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) {
+ /* empty loop body */
+ }
+ if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ fprintf(stderr, "write failed\n");
+ exit(1);
+ }
+ printf("calling PR_Write with a zero-length buffer\n");
+ fflush(stdout);
+ nbytes = PR_Write(acceptSock, buf, 0);
+ if (nbytes != 0) {
+ fprintf(stderr, "PR_Write should return 0 but returns %d\n", nbytes);
+ exit(1);
+ }
+ if (PR_Close(acceptSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(clientThread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+
+ /*
+ * Finally test PR_Send.
+ */
+ clientThread = PR_CreateThread(PR_USER_THREAD,
+ ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)),
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ if (NULL == clientThread) {
+ fprintf(stderr, "PR_CreateThread failed\n");
+ exit(1);
+ }
+ acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
+ if (NULL == acceptSock) {
+ fprintf(stderr, "PR_Accept failed\n");
+ exit(1);
+ }
+ osfd = PR_FileDesc2NativeHandle(acceptSock);
+ while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) {
+ /* empty loop body */
+ }
+ if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ fprintf(stderr, "write failed\n");
+ exit(1);
+ }
+ printf("calling PR_Send with a zero-length buffer\n");
+ fflush(stdout);
+ nbytes = PR_Send(acceptSock, buf, 0, 0, PR_INTERVAL_NO_TIMEOUT);
+ if (nbytes != 0) {
+ fprintf(stderr, "PR_Send should return 0 but returns %d\n", nbytes);
+ exit(1);
+ }
+ if (PR_Close(acceptSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ if (PR_JoinThread(clientThread) == PR_FAILURE) {
+ fprintf(stderr, "PR_JoinThread failed\n");
+ exit(1);
+ }
+
+ if (PR_Close(listenSock) == PR_FAILURE) {
+ fprintf(stderr, "PR_Close failed\n");
+ exit(1);
+ }
+ printf("PASS\n");
+ return 0;
+}
+
+#endif /* XP_UNIX */
diff --git a/src/libs/xpcom18a4/nsprpub/tools/.cvsignore b/src/libs/xpcom18a4/nsprpub/tools/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/tools/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/nsprpub/tools/Makefile.in b/src/libs/xpcom18a4/nsprpub/tools/Makefile.in
new file mode 100644
index 00000000..eb18de01
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/tools/Makefile.in
@@ -0,0 +1,249 @@
+#
+# ***** 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 Portable Runtime (NSPR).
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# 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 *****
+
+#! gmake
+
+MOD_DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(MOD_DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(OS_TARGET), WIN16)
+OS_CFLAGS = $(OS_EXE_CFLAGS)
+endif
+
+
+DIRS =
+
+CSRCS = \
+ httpget.c \
+ tail.c \
+ $(NULL)
+
+ifeq (,$(filter-out WINNT OS2,$(OS_ARCH)))
+PROG_SUFFIX = .exe
+else
+PROG_SUFFIX =
+endif
+
+PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX)))
+
+TARGETS = $(PROGS)
+
+INCLUDES = -I$(dist_includedir)
+
+NSPR_VERSION = 3
+
+# Setting the variables LDOPTS and LIBPR. We first initialize
+# them to the default values, then adjust them for some platforms.
+LDOPTS = -L$(dist_libdir)
+LIBPR = -lnspr$(NSPR_VERSION)
+LIBPLC = -lplc$(NSPR_VERSION)
+
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET), WIN16)
+ LIBPR = $(dist_libdir)/nspr$(NSPR_VERSION).lib
+ LIBPLC= $(dist_libdir)/plc$(NSPR_VERSION).lib
+else
+LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO
+LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).$(LIB_SUFFIX)
+LIBPLC= $(dist_libdir)/libplc$(NSPR_VERSION).$(LIB_SUFFIX)
+endif
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ ifeq ($(MOZ_OS2_TOOLS),VACPP)
+ LDOPTS = -NOE -DEBUG -nologo -PMTYPE:VIO
+ LIBPR = $(dist_libdir)/nspr$(NSPR_VERSION).lib
+ LIBPLC= $(dist_libdir)/plc$(NSPR_VERSION).lib
+ else
+ LDOPTS += -Zomf -Zlinker /PM:VIO
+ endif
+endif
+
+ifneq ($(OS_ARCH), WINNT)
+PWD = $(shell pwd)
+endif
+
+ifeq ($(OS_ARCH), IRIX)
+LDOPTS += -rpath $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), OSF1)
+LDOPTS += -rpath $(PWD)/$(dist_libdir) -lpthread
+endif
+
+ifeq ($(OS_ARCH), HP-UX)
+LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir)
+endif
+
+# AIX
+ifeq ($(OS_ARCH),AIX)
+LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib
+LIBPR = -lnspr$(NSPR_VERSION)_shr
+LIBPLC = -lplc$(NSPR_VERSION)_shr
+endif
+
+# Solaris
+ifeq ($(OS_ARCH), SunOS)
+ifneq ($(OS_RELEASE), 4.1.3_U1)
+ifdef NS_USE_GCC
+LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir)
+else
+LDOPTS += -R $(PWD)/$(dist_libdir)
+endif
+endif
+
+# SunOS 5.4 and 5.5 need to link with -lthread or -lpthread,
+# even though we already linked with these system libraries
+# when we built libnspr.so.
+ifeq ($(OS_RELEASE), 5.4)
+EXTRA_LIBS = -lthread
+endif
+
+ifeq ($(OS_RELEASE), 5.5)
+ifdef USE_PTHREADS
+EXTRA_LIBS = -lpthread
+else
+EXTRA_LIBS = -lthread
+endif
+endif
+endif # SunOS
+
+ifeq ($(OS_ARCH), NCR)
+# XXX: We see some strange problems when we link with libnspr.so.
+# So for now we use static libraries on NCR. The shared library
+# stuff below is commented out.
+LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).a
+LIBPLC = $(dist_libdir)/libplc$(NSPR_VERSION).a
+EXTRA_LIBS = -lsocket -lnsl -ldl
+
+# NCR needs to link against -lsocket -lnsl (and -lc, which is linked
+# implicitly by $(CC)) again even though we already linked with these
+# system libraries when we built libnspr.so.
+#EXTRA_LIBS = -lsocket -lnsl
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+#export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+ifeq ($(OS_ARCH), SCOOS)
+# SCO Unix needs to link against -lsocket again even though we
+# already linked with these system libraries when we built libnspr.so.
+EXTRA_LIBS = -lsocket
+# This hardcodes in the executable programs the directory to find
+# libnspr.so etc. at program startup. Equivalent to the -R or -rpath
+# option for ld on other platforms.
+export LD_RUN_PATH = $(PWD)/$(dist_libdir)
+endif
+
+#####################################################
+#
+# The rules
+#
+#####################################################
+
+include $(topsrcdir)/config/rules.mk
+
+AIX_PRE_4_2 = 0
+ifeq ($(OS_ARCH),AIX)
+ifneq ($(OS_RELEASE),4.2)
+ifneq ($(USE_PTHREADS), 1)
+#AIX_PRE_4_2 = 1
+endif
+endif
+endif
+
+ifeq ($(AIX_PRE_4_2),1)
+
+# AIX releases prior to 4.2 need a special two-step linking hack
+# in order to both override the system select() and be able to
+# get at the original system select().
+#
+# We use a pattern rule in ns/nspr20/config/rules.mk to generate
+# the .$(OBJ_SUFFIX) file from the .c source file, then do the
+# two-step linking hack below.
+
+$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ rm -f $@ $(AIX_TMP)
+ $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(NSPR_VERSION).a
+ $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP)
+ rm -f $(AIX_TMP)
+
+else
+
+# All platforms that are not AIX pre-4.2.
+
+$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX)
+ @$(MAKE_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ifeq ($(OS_TARGET),WIN16)
+ echo system windows >w16link
+ echo option map >>w16link
+ echo option stack=10K >>w16link
+ echo option heapsize=32K >>w16link
+ echo debug $(DEBUGTYPE) all >>w16link
+ echo name $@ >>w16link
+ echo file >>w16link
+ echo $< >>w16link
+ echo library >>w16link
+ echo $(LIBPR), >>w16link
+ echo $(LIBPLC), >>w16link
+ echo winsock.lib >>w16link
+ wlink @w16link.
+else
+ link $(LDOPTS) $< $(LIBPR) $(LIBPLC) wsock32.lib -out:$@
+endif
+else
+ifeq ($(OS_ARCH),OS2)
+ $(LINK) $(LDOPTS) $< $(LIBPR) $(LIBPLC) $(OS_LIBS) $(EXTRA_LIBS) -o $@
+else
+ $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPLC) $(EXTRA_LIBS) -o $@
+endif
+endif
+endif
+
+export:: $(TARGETS)
+clean::
+ rm -f $(TARGETS)
+
diff --git a/src/libs/xpcom18a4/nsprpub/tools/httpget.c b/src/libs/xpcom18a4/nsprpub/tools/httpget.c
new file mode 100644
index 00000000..6eea9351
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/tools/httpget.c
@@ -0,0 +1,466 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+
+/*
+ * Author: Wan-Teh Chang
+ *
+ * Given an HTTP URL, httpget uses the GET method to fetch the file.
+ * The fetched file is written to stdout by default, or can be
+ * saved in an output file.
+ *
+ * This is a single-threaded program.
+ */
+
+#include "prio.h"
+#include "prnetdb.h"
+#include "prlog.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "prinit.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* for atoi */
+
+#define FCOPY_BUFFER_SIZE (16 * 1024)
+#define INPUT_BUFFER_SIZE 1024
+#define LINE_SIZE 512
+#define HOST_SIZE 256
+#define PORT_SIZE 32
+#define PATH_SIZE 512
+
+/*
+ * A buffer for storing the excess input data for ReadLine.
+ * The data in the buffer starts from (including) the element pointed to
+ * by inputHead, and ends just before (not including) the element pointed
+ * to by inputTail. The buffer is empty if inputHead == inputTail.
+ */
+
+static char inputBuf[INPUT_BUFFER_SIZE];
+/*
+ * inputBufEnd points just past the end of inputBuf
+ */
+static char *inputBufEnd = inputBuf + sizeof(inputBuf);
+static char *inputHead = inputBuf;
+static char *inputTail = inputBuf;
+
+static PRBool endOfStream = PR_FALSE;
+
+/*
+ * ReadLine --
+ *
+ * Read in a line of text, terminated by CRLF or LF, from fd into buf.
+ * The terminating CRLF or LF is included (always as '\n'). The text
+ * in buf is terminated by a null byte. The excess bytes are stored in
+ * inputBuf for use in the next ReadLine call or FetchFile call.
+ * Returns the number of bytes in buf. 0 means end of stream. Returns
+ * -1 if read fails.
+ */
+
+PRInt32 ReadLine(PRFileDesc *fd, char *buf, PRUint32 bufSize)
+{
+ char *dst = buf;
+ char *bufEnd = buf + bufSize; /* just past the end of buf */
+ PRBool lineFound = PR_FALSE;
+ char *crPtr = NULL; /* points to the CR ('\r') character */
+ PRInt32 nRead;
+
+loop:
+ PR_ASSERT(inputBuf <= inputHead && inputHead <= inputTail
+ && inputTail <= inputBufEnd);
+ while (lineFound == PR_FALSE && inputHead != inputTail
+ && dst < bufEnd - 1) {
+ if (*inputHead == '\r') {
+ crPtr = dst;
+ } else if (*inputHead == '\n') {
+ lineFound = PR_TRUE;
+ if (crPtr == dst - 1) {
+ dst--;
+ }
+ }
+ *(dst++) = *(inputHead++);
+ }
+ if (lineFound == PR_TRUE || dst == bufEnd - 1 || endOfStream == PR_TRUE) {
+ *dst = '\0';
+ return dst - buf;
+ }
+
+ /*
+ * The input buffer should be empty now
+ */
+ PR_ASSERT(inputHead == inputTail);
+
+ nRead = PR_Read(fd, inputBuf, sizeof(inputBuf));
+ if (nRead == -1) {
+ *dst = '\0';
+ return -1;
+ } else if (nRead == 0) {
+ endOfStream = PR_TRUE;
+ *dst = '\0';
+ return dst - buf;
+ }
+ inputHead = inputBuf;
+ inputTail = inputBuf + nRead;
+ goto loop;
+}
+
+PRInt32 DrainInputBuffer(char *buf, PRUint32 bufSize)
+{
+ PRInt32 nBytes = inputTail - inputHead;
+
+ if (nBytes == 0) {
+ if (endOfStream) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ if ((PRInt32) bufSize < nBytes) {
+ nBytes = bufSize;
+ }
+ memcpy(buf, inputHead, nBytes);
+ inputHead += nBytes;
+ return nBytes;
+}
+
+PRStatus FetchFile(PRFileDesc *in, PRFileDesc *out)
+{
+ char buf[FCOPY_BUFFER_SIZE];
+ PRInt32 nBytes;
+
+ while ((nBytes = DrainInputBuffer(buf, sizeof(buf))) > 0) {
+ if (PR_Write(out, buf, nBytes) != nBytes) {
+ fprintf(stderr, "httpget: cannot write to file\n");
+ return PR_FAILURE;
+ }
+ }
+ if (nBytes < 0) {
+ /* Input buffer is empty and end of stream */
+ return PR_SUCCESS;
+ }
+ while ((nBytes = PR_Read(in, buf, sizeof(buf))) > 0) {
+ if (PR_Write(out, buf, nBytes) != nBytes) {
+ fprintf(stderr, "httpget: cannot write to file\n");
+ return PR_FAILURE;
+ }
+ }
+ if (nBytes < 0) {
+ fprintf(stderr, "httpget: cannot read from socket\n");
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PRStatus FastFetchFile(PRFileDesc *in, PRFileDesc *out, PRUint32 size)
+{
+ PRInt32 nBytes;
+ PRFileMap *outfMap;
+ void *addr;
+ char *start;
+ PRUint32 rem;
+ PRUint32 bytesToRead;
+ PRStatus rv;
+ PRInt64 sz64;
+
+ LL_UI2L(sz64, size);
+ outfMap = PR_CreateFileMap(out, sz64, PR_PROT_READWRITE);
+ PR_ASSERT(outfMap);
+ addr = PR_MemMap(outfMap, LL_ZERO, size);
+ if (addr == (void *) -1) {
+ fprintf(stderr, "cannot memory-map file: (%d, %d)\n", PR_GetError(),
+ PR_GetOSError());
+
+ PR_CloseFileMap(outfMap);
+ return PR_FAILURE;
+ }
+ PR_ASSERT(addr != (void *) -1);
+ start = (char *) addr;
+ rem = size;
+ while ((nBytes = DrainInputBuffer(start, rem)) > 0) {
+ start += nBytes;
+ rem -= nBytes;
+ }
+ if (nBytes < 0) {
+ /* Input buffer is empty and end of stream */
+ return PR_SUCCESS;
+ }
+ bytesToRead = (rem < FCOPY_BUFFER_SIZE) ? rem : FCOPY_BUFFER_SIZE;
+ while (rem > 0 && (nBytes = PR_Read(in, start, bytesToRead)) > 0) {
+ start += nBytes;
+ rem -= nBytes;
+ bytesToRead = (rem < FCOPY_BUFFER_SIZE) ? rem : FCOPY_BUFFER_SIZE;
+ }
+ if (nBytes < 0) {
+ fprintf(stderr, "httpget: cannot read from socket\n");
+ return PR_FAILURE;
+ }
+ rv = PR_MemUnmap(addr, size);
+ PR_ASSERT(rv == PR_SUCCESS);
+ rv = PR_CloseFileMap(outfMap);
+ PR_ASSERT(rv == PR_SUCCESS);
+ return PR_SUCCESS;
+}
+
+PRStatus ParseURL(char *url, char *host, PRUint32 hostSize,
+ char *port, PRUint32 portSize, char *path, PRUint32 pathSize)
+{
+ char *start, *end;
+ char *dst;
+ char *hostEnd;
+ char *portEnd;
+ char *pathEnd;
+
+ if (strncmp(url, "http", 4)) {
+ fprintf(stderr, "httpget: the protocol must be http\n");
+ return PR_FAILURE;
+ }
+ if (strncmp(url + 4, "://", 3) || url[7] == '\0') {
+ fprintf(stderr, "httpget: malformed URL: %s\n", url);
+ return PR_FAILURE;
+ }
+
+ start = end = url + 7;
+ dst = host;
+ hostEnd = host + hostSize;
+ while (*end && *end != ':' && *end != '/') {
+ if (dst == hostEnd - 1) {
+ fprintf(stderr, "httpget: host name too long\n");
+ return PR_FAILURE;
+ }
+ *(dst++) = *(end++);
+ }
+ *dst = '\0';
+
+ if (*end == '\0') {
+ PR_snprintf(port, portSize, "%d", 80);
+ PR_snprintf(path, pathSize, "%s", "/");
+ return PR_SUCCESS;
+ }
+
+ if (*end == ':') {
+ end++;
+ dst = port;
+ portEnd = port + portSize;
+ while (*end && *end != '/') {
+ if (dst == portEnd - 1) {
+ fprintf(stderr, "httpget: port number too long\n");
+ return PR_FAILURE;
+ }
+ *(dst++) = *(end++);
+ }
+ *dst = '\0';
+ if (*end == '\0') {
+ PR_snprintf(path, pathSize, "%s", "/");
+ return PR_SUCCESS;
+ }
+ } else {
+ PR_snprintf(port, portSize, "%d", 80);
+ }
+
+ dst = path;
+ pathEnd = path + pathSize;
+ while (*end) {
+ if (dst == pathEnd - 1) {
+ fprintf(stderr, "httpget: file pathname too long\n");
+ return PR_FAILURE;
+ }
+ *(dst++) = *(end++);
+ }
+ *dst = '\0';
+ return PR_SUCCESS;
+}
+
+void PrintUsage(void) {
+ fprintf(stderr, "usage: httpget url\n"
+ " httpget -o outputfile url\n"
+ " httpget url -o outputfile\n");
+}
+
+int main(int argc, char **argv)
+{
+ PRHostEnt hostentry;
+ char buf[PR_NETDB_BUF_SIZE];
+ PRNetAddr addr;
+ PRFileDesc *socket = NULL, *file = NULL;
+ PRIntn cmdSize;
+ char host[HOST_SIZE];
+ char port[PORT_SIZE];
+ char path[PATH_SIZE];
+ char line[LINE_SIZE];
+ int exitStatus = 0;
+ PRBool endOfHeader = PR_FALSE;
+ char *url;
+ char *fileName = NULL;
+ PRUint32 fileSize;
+
+ if (argc != 2 && argc != 4) {
+ PrintUsage();
+ exit(1);
+ }
+
+ if (argc == 2) {
+ /*
+ * case 1: httpget url
+ */
+ url = argv[1];
+ } else {
+ if (strcmp(argv[1], "-o") == 0) {
+ /*
+ * case 2: httpget -o outputfile url
+ */
+ fileName = argv[2];
+ url = argv[3];
+ } else {
+ /*
+ * case 3: httpget url -o outputfile
+ */
+ url = argv[1];
+ if (strcmp(argv[2], "-o") != 0) {
+ PrintUsage();
+ exit(1);
+ }
+ fileName = argv[3];
+ }
+ }
+
+ if (ParseURL(url, host, sizeof(host), port, sizeof(port),
+ path, sizeof(path)) == PR_FAILURE) {
+ exit(1);
+ }
+
+ if (PR_GetHostByName(host, buf, sizeof(buf), &hostentry)
+ == PR_FAILURE) {
+ fprintf(stderr, "httpget: unknown host name: %s\n", host);
+ exit(1);
+ }
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons((short) atoi(port));
+ addr.inet.ip = *((PRUint32 *) hostentry.h_addr_list[0]);
+
+ socket = PR_NewTCPSocket();
+ if (socket == NULL) {
+ fprintf(stderr, "httpget: cannot create new tcp socket\n");
+ exit(1);
+ }
+
+ if (PR_Connect(socket, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+ fprintf(stderr, "httpget: cannot connect to http server\n");
+ exitStatus = 1;
+ goto done;
+ }
+
+ if (fileName == NULL) {
+ file = PR_STDOUT;
+ } else {
+ file = PR_Open(fileName, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
+ 00777);
+ if (file == NULL) {
+ fprintf(stderr, "httpget: cannot open file %s: (%d, %d)\n",
+ fileName, PR_GetError(), PR_GetOSError());
+ exitStatus = 1;
+ goto done;
+ }
+ }
+
+ cmdSize = PR_snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n\r\n", path);
+ PR_ASSERT(cmdSize == (PRIntn) strlen("GET HTTP/1.0\r\n\r\n")
+ + (PRIntn) strlen(path));
+ if (PR_Write(socket, buf, cmdSize) != cmdSize) {
+ fprintf(stderr, "httpget: cannot write to http server\n");
+ exitStatus = 1;
+ goto done;
+ }
+
+ if (ReadLine(socket, line, sizeof(line)) <= 0) {
+ fprintf(stderr, "httpget: cannot read line from http server\n");
+ exitStatus = 1;
+ goto done;
+ }
+
+ /* HTTP response: 200 == OK */
+ if (strstr(line, "200") == NULL) {
+ fprintf(stderr, "httpget: %s\n", line);
+ exitStatus = 1;
+ goto done;
+ }
+
+ while (ReadLine(socket, line, sizeof(line)) > 0) {
+ if (line[0] == '\n') {
+ endOfHeader = PR_TRUE;
+ break;
+ }
+ if (strncmp(line, "Content-Length", 14) == 0
+ || strncmp(line, "Content-length", 14) == 0) {
+ char *p = line + 14;
+
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (*p != ':') {
+ continue;
+ }
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ fileSize = 0;
+ while ('0' <= *p && *p <= '9') {
+ fileSize = 10 * fileSize + (*p - '0');
+ p++;
+ }
+ }
+ }
+ if (endOfHeader == PR_FALSE) {
+ fprintf(stderr, "httpget: cannot read line from http server\n");
+ exitStatus = 1;
+ goto done;
+ }
+
+ if (fileName == NULL || fileSize == 0) {
+ FetchFile(socket, file);
+ } else {
+ FastFetchFile(socket, file, fileSize);
+ }
+
+done:
+ if (socket) PR_Close(socket);
+ if (file) PR_Close(file);
+ PR_Cleanup();
+ return exitStatus;
+}
diff --git a/src/libs/xpcom18a4/nsprpub/tools/tail.c b/src/libs/xpcom18a4/nsprpub/tools/tail.c
new file mode 100644
index 00000000..dc729c15
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/tools/tail.c
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * 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 ***** */
+
+#include "prio.h"
+#include "prprf.h"
+#include "prinit.h"
+#include "prthread.h"
+#include "prinrval.h"
+
+#include "plerror.h"
+#include "plgetopt.h"
+
+#include <stdlib.h>
+
+#define BUFFER_SIZE 500
+
+static PRFileDesc *out = NULL, *err = NULL;
+
+static void Help(void)
+{
+ PR_fprintf(err, "Usage: tail [-n <n>] [-f] [-h] <filename>\n");
+ PR_fprintf(err, "\t-t <n> Dally time in milliseconds\n");
+ PR_fprintf(err, "\t-n <n> Number of bytes before <eof>\n");
+ PR_fprintf(err, "\t-f Follow the <eof>\n");
+ PR_fprintf(err, "\t-h This message and nothing else\n");
+} /* Help */
+
+PRIntn main(PRIntn argc, char **argv)
+{
+ PRIntn rv = 0;
+ PLOptStatus os;
+ PRStatus status;
+ PRFileDesc *file;
+ PRFileInfo fileInfo;
+ PRIntervalTime dally;
+ char buffer[BUFFER_SIZE];
+ PRBool follow = PR_FALSE;
+ const char *filename = NULL;
+ PRUint32 position = 0, seek = 0, time = 0;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hfn:");
+
+ out = PR_GetSpecialFD(PR_StandardOutput);
+ err = PR_GetSpecialFD(PR_StandardError);
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 0: /* it's the filename */
+ filename = opt->value;
+ break;
+ case 'n': /* bytes before end of file */
+ seek = atoi(opt->value);
+ break;
+ case 't': /* dally time */
+ time = atoi(opt->value);
+ break;
+ case 'f': /* follow the end of file */
+ follow = PR_TRUE;
+ break;
+ case 'h': /* user wants some guidance */
+ Help(); /* so give him an earful */
+ return 2; /* but not a lot else */
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+
+ if (0 == time) time = 1000;
+ dally = PR_MillisecondsToInterval(time);
+
+ if (NULL == filename)
+ {
+ (void)PR_fprintf(out, "Input file not specified\n");
+ rv = 1; goto done;
+ }
+ file = PR_Open(filename, PR_RDONLY, 0);
+ if (NULL == file)
+ {
+ PL_FPrintError(err, "File cannot be opened for reading");
+ return 1;
+ }
+
+ status = PR_GetOpenFileInfo(file, &fileInfo);
+ if (PR_FAILURE == status)
+ {
+ PL_FPrintError(err, "Cannot acquire status of file");
+ rv = 1; goto done;
+ }
+ if (seek > 0)
+ {
+ if (seek > fileInfo.size) seek = 0;
+ position = PR_Seek(file, (fileInfo.size - seek), PR_SEEK_SET);
+ if (-1 == (PRInt32)position)
+ PL_FPrintError(err, "Cannot seek to starting position");
+ }
+
+ do
+ {
+ while (position < fileInfo.size)
+ {
+ PRInt32 read, bytes = fileInfo.size - position;
+ if (bytes > sizeof(buffer)) bytes = sizeof(buffer);
+ read = PR_Read(file, buffer, bytes);
+ if (read != bytes)
+ PL_FPrintError(err, "Cannot read to eof");
+ position += read;
+ PR_Write(out, buffer, read);
+ }
+
+ if (follow)
+ {
+ PR_Sleep(dally);
+ status = PR_GetOpenFileInfo(file, &fileInfo);
+ if (PR_FAILURE == status)
+ {
+ PL_FPrintError(err, "Cannot acquire status of file");
+ rv = 1; goto done;
+ }
+ }
+ } while (follow);
+
+done:
+ PR_Close(file);
+
+ return rv;
+} /* main */
+
+/* tail.c */
diff --git a/src/libs/xpcom18a4/python/.cvsignore b/src/libs/xpcom18a4/python/.cvsignore
new file mode 100644
index 00000000..9d5da30c
--- /dev/null
+++ b/src/libs/xpcom18a4/python/.cvsignore
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+*.idb
+*.pdb \ No newline at end of file
diff --git a/src/libs/xpcom18a4/python/Makefile.kmk b/src/libs/xpcom18a4/python/Makefile.kmk
new file mode 100644
index 00000000..49653847
--- /dev/null
+++ b/src/libs/xpcom18a4/python/Makefile.kmk
@@ -0,0 +1,730 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for Python bindings
+#
+
+#
+# Copyright (C) 2009-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# List of supported Python versions, defining a number of
+# VBOX_PYTHON[26|27|31|32|32M|33|33M|34|34M|35|35M|36|36M|37|37M|38|38M|39|39M|310|310M|DEF]_[INC|LIB] variables
+# which get picked up below.
+#
+ifeq ($(KBUILD_TARGET),darwin) # Relatively predictable, don't script.
+ ifn1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.10 10.9 10.8 10.7 10.6 10.5 10.4) ## @todo @bugref{9790}: if $(VBOX_DEF_MACOSX_VERSION_MIN) vge 10.11
+ VBOX_PYTHON_SUFFTBD := .tbd
+ else
+ VBOX_PYTHON_SUFFTBD :=
+ endif
+ ifndef VBOX_WITHOUT_VBOXPYTHON_FOR_OSX_10_6
+ if1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.5 10.4)
+ VBOX_PYTHON26_INC = $(VBOX_PATH_MACOSX_SDK_10_6)/usr/include/python2.6
+ VBOX_PYTHON26_LIB = $(VBOX_PATH_MACOSX_SDK_10_6)/usr/lib/libpython2.6.dylib
+ else if "$(VBOX_DEF_MACOSX_VERSION_MIN)" == "10.9" && "$(VBOX_XCODE_VERSION)" == "6.2" # 'effing 10.9 SDK in Xcode 6.2 is missing python. Stupid, stupid Apple!!
+ VBOX_PYTHON26_INC = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.6/Headers
+ VBOX_PYTHON26_LIB = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.6/Python
+ else if "$(VBOX_DEF_MACOSX_VERSION_MIN)" vlt "10.13"
+ VBOX_PYTHON26_INC = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.6/Headers
+ VBOX_PYTHON26_LIB = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.6/Python$(VBOX_PYTHON_SUFFTBD)
+ endif
+ if !defined(VBOX_OSE) || "$(wildcard $(VBOX_PYTHON26_LIB))" != ""
+ VBOX_PYTHON26_LIB_X86 = $(VBOX_PYTHON26_LIB)
+ else
+ VBOX_PYTHON26_INC =
+ VBOX_PYTHON26_LIB =
+ endif
+ endif
+ ifndef VBOX_WITHOUT_VBOXPYTHON_FOR_OSX_10_7
+ if1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.6 10.5 10.4)
+ VBOX_PYTHON27_INC = $(VBOX_PATH_MACOSX_SDK_10_7)/usr/include/python2.7
+ VBOX_PYTHON27_LIB = $(VBOX_PATH_MACOSX_SDK_10_7)/usr/lib/libpython2.7.dylib
+ else if "$(VBOX_DEF_MACOSX_VERSION_MIN)" == "10.9" && "$(VBOX_XCODE_VERSION)" == "6.2" # 'effing 10.9 SDK in Xcode 6.2 is missing python. Stupid, stupid Apple!!
+ VBOX_PYTHON27_INC = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/Headers
+ VBOX_PYTHON27_LIB = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/Python
+ else
+ VBOX_PYTHON27_INC = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.7/Headers
+ VBOX_PYTHON27_LIB = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.7/Python$(VBOX_PYTHON_SUFFTBD)
+ endif
+ if !defined(VBOX_OSE) || "$(wildcard $(VBOX_PYTHON27_LIB))" != ""
+ VBOX_PYTHON27_LIB_X86 = $(VBOX_PYTHON27_LIB)
+ else
+ VBOX_PYTHON27_INC =
+ VBOX_PYTHON27_LIB =
+ endif
+ endif
+ # No Python 3.x yet as part of OSX versions including El Capitan, 10.11.
+
+else
+ # Use the script.
+ $(eval $(subst |,$(NL),$(shell $(VBOX_BLD_PYTHON) \
+ $(PATH_SUB_CURRENT)/gen_python_deps.py \
+ $(KBUILD_TARGET) \
+ $(KBUILD_TARGET_ARCH) \
+ $(if-expr defined(VBOX_WITH_MULTIVERSION_PYTHON),1,0))))
+endif
+
+ifndef VBOX_ONLY_SDK
+
+ #
+ # Base Python Client Module - the C++/XPCOM bits (not actually built).
+ #
+ VBoxPythonBase_TEMPLATE = XPComDll
+ VBoxPythonBase_CXXFLAGS = -Wno-write-strings
+ VBoxPythonBase_CXXFLAGS.solaris = $(VBOX_GCC_Wno-unknown-pragmas) # /usr/include/python[23].[75]*/ceval.h:67: warning: ignoring #pragma no_inline(PyEval_EvalFrameEx)
+ VBoxPythonBase_DLLSUFF.darwin = .so
+ VBoxPythonBase_DEFS = \
+ _IMPL_NS_COM \
+ _IMPL_NS_BASE \
+ EXPORT_XPTI_API \
+ EXPORT_XPT_API \
+ VBOX_PYXPCOM \
+ VBOX_WITH_XPCOM \
+ VBOX_PYXPCOM_VERSIONED
+ #VBoxPythonBase_DEFS.debug = \
+ # VBOX_DEBUG_LIFETIMES
+ VBoxPythonBase_INCS = \
+ src
+ VBoxPythonBase_SOURCES = \
+ src/module/_xpcom.cpp \
+ src/dllmain.cpp \
+ src/ErrorUtils.cpp \
+ src/PyGBase.cpp \
+ src/PyGInputStream.cpp \
+ src/PyGModule.cpp \
+ src/PyGStub.cpp \
+ src/PyGWeakReference.cpp \
+ src/PyIClassInfo.cpp \
+ src/PyIComponentManager.cpp \
+ src/PyIComponentManagerObsolete.cpp \
+ src/PyIEnumerator.cpp \
+ src/PyIID.cpp \
+ src/PyIInputStream.cpp \
+ src/PyIInterfaceInfo.cpp \
+ src/PyIInterfaceInfoManager.cpp \
+ src/PyISimpleEnumerator.cpp \
+ src/PyISupports.cpp \
+ src/PyIVariant.cpp \
+ src/Pyxpt_info.cpp \
+ src/TypeObject.cpp \
+ src/VariantUtils.cpp
+ VBoxPythonBase_LIBS = \
+ $(PATH_STAGE_LIB)/VBoxCOM$(VBOX_SUFF_LIB) \
+ $(PATH_STAGE_BIN)/VBoxXPCOM$(VBOX_SUFF_DLL)
+
+ # pymalloc abi variant.
+ VBoxPythonBase_m_EXTENDS = VBoxPythonBase
+ VBoxPythonBase_m_DEFS = MODULE_NAME_SUFFIX=m $(VBoxPythonBase_DEFS)
+
+ # 32-bit base.
+ VBoxPythonBase_x86_TEMPLATE = XPComDll-x86
+ VBoxPythonBase_x86_EXTENDS = VBoxPythonBase
+ VBoxPythonBase_x86_DEFS = MODULE_NAME_SUFFIX=_x86 $(VBoxPythonBase_DEFS)
+ VBoxPythonBase_x86_LIBS = \
+ $(PATH_STAGE_LIB)/VBoxCOM-x86$(VBOX_SUFF_LIB) \
+ $(PATH_STAGE_BIN)/VBoxXPCOM-x86$(VBOX_SUFF_DLL)
+
+ # 32-bit pymalloc abi variant.
+ VBoxPythonBase_x86_m_EXTENDS = VBoxPythonBase_x86
+ VBoxPythonBase_x86_m_DEFS = MODULE_NAME_SUFFIX=_x86m $(VBoxPythonBase_DEFS)
+
+
+ ifdef VBOX_PYTHON26_INC
+ #
+ # Python 2.6 version
+ #
+ DLLS += VBoxPython2_6
+ VBoxPython2_6_EXTENDS = VBoxPythonBase
+ VBoxPython2_6_EXTENDS_BY = appending
+ ifdef KMK_WITH_VERSION_COMPARE
+ VBoxPython2_6_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.6",OSX106,)
+ else
+ VBoxPython2_6_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.6",OSX106,)
+ endif
+ VBoxPython2_6_INCS = $(VBOX_PYTHON26_INC)
+ VBoxPython2_6_LIBS = $(VBOX_PYTHON26_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON26_LIB_X86
+ DLLS += VBoxPython2_6_x86
+ VBoxPython2_6_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython2_6_x86_EXTENDS_BY = appending
+ ifdef KMK_WITH_VERSION_COMPARE
+ VBoxPython2_6_x86_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.6",OSX106,-x86)
+ else
+ VBoxPython2_6_x86_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.6",OSX106,-x86)
+ endif
+ VBoxPython2_6_x86_INCS = $(VBOX_PYTHON26_INC)
+ VBoxPython2_6_x86_LIBS = $(VBOX_PYTHON26_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON27_INC
+ #
+ # Python 2.7 version
+ #
+ DLLS += VBoxPython2_7
+ VBoxPython2_7_EXTENDS = VBoxPythonBase
+ VBoxPython2_7_EXTENDS_BY = appending
+ ifdef KMK_WITH_VERSION_COMPARE
+ VBoxPython2_7_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,)
+ else
+ VBoxPython2_7_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,)
+ endif
+ VBoxPython2_7_INCS = $(VBOX_PYTHON27_INC)
+ VBoxPython2_7_LIBS = $(VBOX_PYTHON27_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON27_LIB_X86
+ DLLS += VBoxPython2_7_x86
+ VBoxPython2_7_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython2_7_x86_EXTENDS_BY = appending
+ ifdef KMK_WITH_VERSION_COMPARE
+ VBoxPython2_7_x86_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,-x86)
+ else
+ VBoxPython2_7_x86_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,-x86)
+ endif
+ VBoxPython2_7_x86_INCS = $(VBOX_PYTHON27_INC)
+ VBoxPython2_7_x86_LIBS = $(VBOX_PYTHON27_LIB_X86)
+ endif
+ endif
+ endif
+
+ #
+ # Unversioned Python 2.x.
+ #
+ if defined(VBOX_PYTHON27_INC) || defined(VBOX_PYTHON26_INC)
+ DLLS += VBoxPython2
+ VBoxPython2_EXTENDS = VBoxPythonBase
+ VBoxPython2_EXTENDS_BY = appending
+ VBoxPython2_DEFS = VBOX_PYXPCOM_MAJOR_VERSIONED
+ ifdef KMK_WITH_VERSION_COMPARE
+ VBoxPython2_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,)
+ else
+ VBoxPython2_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,)
+ endif
+ if defined(VBOX_PYTHON26_INC)
+ VBoxPython2_INCS = $(VBOX_PYTHON26_INC)
+ ifn1of ($(KBUILD_TARGET), linux)
+ VBoxPython2_LIBS = $(VBOX_PYTHON26_LIB)
+ endif
+ else
+ VBoxPython2_INCS = $(VBOX_PYTHON27_INC)
+ ifn1of ($(KBUILD_TARGET), linux)
+ VBoxPython2_LIBS = $(VBOX_PYTHON27_LIB)
+ endif
+ endif
+ endif
+
+ if defined(VBOX_WITH_32_ON_64_MAIN_API) && (defined(VBOX_PYTHON27_LIB_X86) || defined(VBOX_PYTHON26_INC_X86))
+ DLLS += VBoxPython2_x86
+ VBoxPython2_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython2_x86_EXTENDS_BY = appending
+ VBoxPython2_x86_DEFS = VBOX_PYXPCOM_MAJOR_VERSIONED $(VBoxPythonBase_x86_DEFS)
+ ifdef KMK_WITH_VERSION_COMPARE
+ VBoxPython2_x86_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,-x86)
+ else
+ VBoxPython2_x86_TEMPLATE = XPComDll$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,-x86)
+ endif
+ if defined(VBOX_PYTHON26LIB_X86)
+ VBoxPython2_x86_INCS = $(VBOX_PYTHON26_INC)
+ ifn1of ($(KBUILD_TARGET), linux)
+ VBoxPython2_x86_LIBS = $(VBOX_PYTHON26_LIB_X86)
+ endif
+ else
+ VBoxPython2_x86_INCS = $(VBOX_PYTHON27_INC)
+ ifn1of ($(KBUILD_TARGET), linux)
+ VBoxPython2_x86_LIBS = $(VBOX_PYTHON27_LIB_X86)
+ endif
+ endif
+ endif
+
+
+ ifdef VBOX_PYTHON31_INC
+ #
+ # Python 3.1 version
+ #
+ DLLS += VBoxPython3_1
+ VBoxPython3_1_EXTENDS = VBoxPythonBase
+ VBoxPython3_1_EXTENDS_BY = appending
+ VBoxPython3_1_INCS = $(VBOX_PYTHON31_INC)
+ VBoxPython3_1_LIBS = $(VBOX_PYTHON31_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON31_LIB_X86
+ DLLS += VBoxPython3_1_x86
+ VBoxPython3_1_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_1_x86_EXTENDS_BY = appending
+ VBoxPython3_1_x86_INCS = $(VBOX_PYTHON31_INC)
+ VBoxPython3_1_x86_LIBS = $(VBOX_PYTHON31_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON32_INC
+ #
+ # Python 3.2 version
+ #
+ DLLS += VBoxPython3_2
+ VBoxPython3_2_EXTENDS = VBoxPythonBase
+ VBoxPython3_2_EXTENDS_BY = appending
+ VBoxPython3_2_INCS = $(VBOX_PYTHON32_INC)
+ VBoxPython3_2_LIBS = $(VBOX_PYTHON32_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON32_LIB_X86
+ DLLS += VBoxPython3_2_x86
+ VBoxPython3_2_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_2_x86_EXTENDS_BY = appending
+ VBoxPython3_2_x86_INCS = $(VBOX_PYTHON32_INC)
+ VBoxPython3_2_x86_LIBS = $(VBOX_PYTHON32_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON32M_INC
+ #
+ # Python 3.2 version with pymalloc
+ #
+ DLLS += VBoxPython3_2m
+ VBoxPython3_2m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3_2m_EXTENDS_BY = appending
+ VBoxPython3_2m_INCS = $(VBOX_PYTHON32M_INC)
+ VBoxPython3_2m_LIBS = $(VBOX_PYTHON32M_LIB)
+ VBoxPython3_2m_DEFS = MODULE_NAME_SUFFIX
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON32M_LIB_X86
+ DLLS += VBoxPython3_2m_x86
+ VBoxPython3_2m_x86_EXTENDS = VBoxPythonBase_x86_m
+ VBoxPython3_2m_x86_EXTENDS_BY = appending
+ VBoxPython3_2m_x86_INCS = $(VBOX_PYTHON32M_INC)
+ VBoxPython3_2m_x86_LIBS = $(VBOX_PYTHON32M_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifndef VBOX_WITH_ONLY_PYTHON_LIMITED_API
+
+ ifdef VBOX_PYTHON33_INC
+ #
+ # Python 3.3 version
+ #
+ DLLS += VBoxPython3_3
+ VBoxPython3_3_EXTENDS = VBoxPythonBase
+ VBoxPython3_3_EXTENDS_BY = appending
+ VBoxPython3_3_INCS = $(VBOX_PYTHON33_INC)
+ VBoxPython3_3_LIBS = $(VBOX_PYTHON33_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON33_LIB_X86
+ DLLS += VBoxPython3_3_x86
+ VBoxPython3_3_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_3_x86_EXTENDS_BY = appending
+ VBoxPython3_3_x86_INCS = $(VBOX_PYTHON33_INC)
+ VBoxPython3_3_x86_LIBS = $(VBOX_PYTHON33_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON33M_INC
+ #
+ # Python 3.3 version with pymalloc
+ #
+ DLLS += VBoxPython3_3m
+ VBoxPython3_3m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3_3m_EXTENDS_BY = appending
+ VBoxPython3_3m_INCS = $(VBOX_PYTHON33M_INC)
+ VBoxPython3_3m_LIBS = $(VBOX_PYTHON33M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON33M_LIB_X86
+ DLLS += VBoxPython3_3m_x86
+ VBoxPython3_3m_x86_EXTENDS = VBoxPythonBase_x86_m
+ VBoxPython3_3m_x86_EXTENDS_BY = appending
+ VBoxPython3_3m_x86_INCS = $(VBOX_PYTHON33M_INC)
+ VBoxPython3_3m_x86_LIBS = $(VBOX_PYTHON33M_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON34_INC
+ #
+ # Python 3.4 version
+ #
+ DLLS += VBoxPython3_4
+ VBoxPython3_4_EXTENDS = VBoxPythonBase
+ VBoxPython3_4_EXTENDS_BY = appending
+ VBoxPython3_4_INCS = $(VBOX_PYTHON34_INC)
+ VBoxPython3_4_LIBS = $(VBOX_PYTHON34_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON34_LIB_X86
+ DLLS += VBoxPython3_4_x86
+ VBoxPython3_4_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_4_x86_EXTENDS_BY = appending
+ VBoxPython3_4_x86_INCS = $(VBOX_PYTHON34_INC)
+ VBoxPython3_4_x86_LIBS = $(VBOX_PYTHON34_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON34M_INC
+ #
+ # Python 3.4 version with pymalloc
+ #
+ DLLS += VBoxPython3_4m
+ VBoxPython3_4m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3_4m_EXTENDS_BY = appending
+ VBoxPython3_4m_INCS = $(VBOX_PYTHON34M_INC)
+ VBoxPython3_4m_LIBS = $(VBOX_PYTHON34M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON34M_LIB_X86
+ DLLS += VBoxPython3_4m_x86
+ VBoxPython3_4m_x86_EXTENDS = VBoxPythonBase_x86_m
+ VBoxPython3_4m_x86_EXTENDS_BY = appending
+ VBoxPython3_4m_x86_INCS = $(VBOX_PYTHON34M_INC)
+ VBoxPython3_4m_x86_LIBS = $(VBOX_PYTHON34M_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON35_INC
+ #
+ # Python 3.5 version
+ #
+ DLLS += VBoxPython3_5
+ VBoxPython3_5_EXTENDS = VBoxPythonBase
+ VBoxPython3_5_EXTENDS_BY = appending
+ VBoxPython3_5_INCS = $(VBOX_PYTHON35_INC)
+ VBoxPython3_5_LIBS = $(VBOX_PYTHON35_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON35_LIB_X86
+ DLLS += VBoxPython3_5_x86
+ VBoxPython3_5_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_5_x86_EXTENDS_BY = appending
+ VBoxPython3_5_x86_INCS = $(VBOX_PYTHON35_INC)
+ VBoxPython3_5_x86_LIBS = $(VBOX_PYTHON35_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON35M_INC
+ #
+ # Python 3.5 version with pymalloc
+ #
+ DLLS += VBoxPython3_5m
+ VBoxPython3_5m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3_5m_EXTENDS_BY = appending
+ VBoxPython3_5m_INCS = $(VBOX_PYTHON35M_INC)
+ VBoxPython3_5m_LIBS = $(VBOX_PYTHON35M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON35M_LIB_X86
+ DLLS += VBoxPython3_5m_x86
+ VBoxPython3_5m_x86_EXTENDS = VBoxPythonBase_x86_m
+ VBoxPython3_5m_x86_EXTENDS_BY = appending
+ VBoxPython3_5m_x86_INCS = $(VBOX_PYTHON35M_INC)
+ VBoxPython3_5m_x86_LIBS = $(VBOX_PYTHON35M_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON36_INC
+ #
+ # Python 3.6 version
+ #
+ DLLS += VBoxPython3_6
+ VBoxPython3_6_EXTENDS = VBoxPythonBase
+ VBoxPython3_6_EXTENDS_BY = appending
+ VBoxPython3_6_INCS = $(VBOX_PYTHON36_INC)
+ VBoxPython3_6_LIBS = $(VBOX_PYTHON36_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON36_LIB_X86
+ DLLS += VBoxPython3_6_x86
+ VBoxPython3_6_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_6_x86_EXTENDS_BY = appending
+ VBoxPython3_6_x86_INCS = $(VBOX_PYTHON36_INC)
+ VBoxPython3_6_x86_LIBS = $(VBOX_PYTHON36_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON36M_INC
+ #
+ # Python 3.6 version with pymalloc
+ #
+ DLLS += VBoxPython3_6m
+ VBoxPython3_6m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3_6m_EXTENDS_BY = appending
+ VBoxPython3_6m_INCS = $(VBOX_PYTHON36M_INC)
+ VBoxPython3_6m_LIBS = $(VBOX_PYTHON36M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON36M_LIB_X86
+ DLLS += VBoxPython3_6m_x86
+ VBoxPython3_6m_x86_EXTENDS = VBoxPythonBase_x86_m
+ VBoxPython3_6m_x86_EXTENDS_BY = appending
+ VBoxPython3_6m_x86_INCS = $(VBOX_PYTHON36M_INC)
+ VBoxPython3_6m_x86_LIBS = $(VBOX_PYTHON36M_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON37_INC
+ #
+ # Python 3.7 version
+ #
+ DLLS += VBoxPython3_7
+ VBoxPython3_7_EXTENDS = VBoxPythonBase
+ VBoxPython3_7_EXTENDS_BY = appending
+ VBoxPython3_7_INCS = $(VBOX_PYTHON37_INC)
+ VBoxPython3_7_LIBS = $(VBOX_PYTHON37_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON37_LIB_X86
+ DLLS += VBoxPython3_7_x86
+ VBoxPython3_7_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_7_x86_EXTENDS_BY = appending
+ VBoxPython3_7_x86_INCS = $(VBOX_PYTHON37_INC)
+ VBoxPython3_7_x86_LIBS = $(VBOX_PYTHON37_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON37M_INC
+ #
+ # Python 3.7 version with pymalloc
+ #
+ DLLS += VBoxPython3_7m
+ VBoxPython3_7m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3_7m_EXTENDS_BY = appending
+ VBoxPython3_7m_INCS = $(VBOX_PYTHON37M_INC)
+ VBoxPython3_7m_LIBS = $(VBOX_PYTHON37M_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON37M_LIB_X86
+ DLLS += VBoxPython3_7m_x86
+ VBoxPython3_7m_x86_EXTENDS = VBoxPythonBase_x86_m
+ VBoxPython3_7m_x86_EXTENDS_BY = appending
+ VBoxPython3_7m_x86_INCS = $(VBOX_PYTHON37M_INC)
+ VBoxPython3_7m_x86_LIBS = $(VBOX_PYTHON37M_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON38_INC
+ #
+ # Python 3.8 version (implicitly with pymalloc)
+ #
+ DLLS += VBoxPython3_8
+ VBoxPython3_8_EXTENDS = VBoxPythonBase
+ VBoxPython3_8_EXTENDS_BY = appending
+ VBoxPython3_8_INCS = $(VBOX_PYTHON38_INC)
+ VBoxPython3_8_LIBS = $(VBOX_PYTHON38_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON38_LIB_X86
+ DLLS += VBoxPython3_8_x86
+ VBoxPython3_8_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_8_x86_EXTENDS_BY = appending
+ VBoxPython3_8_x86_INCS = $(VBOX_PYTHON38_INC)
+ VBoxPython3_8_x86_LIBS = $(VBOX_PYTHON38_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON39_INC
+ #
+ # Python 3.9 version (implicitly with pymalloc)
+ #
+ DLLS += VBoxPython3_9
+ VBoxPython3_9_EXTENDS = VBoxPythonBase
+ VBoxPython3_9_EXTENDS_BY = appending
+ VBoxPython3_9_INCS = $(VBOX_PYTHON39_INC)
+ VBoxPython3_9_LIBS = $(VBOX_PYTHON39_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON39_LIB_X86
+ DLLS += VBoxPython3_9_x86
+ VBoxPython3_9_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_9_x86_EXTENDS_BY = appending
+ VBoxPython3_9_x86_INCS = $(VBOX_PYTHON39_INC)
+ VBoxPython3_9_x86_LIBS = $(VBOX_PYTHON39_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON310_INC
+ #
+ # Python 3.10 version (implicitly with pymalloc)
+ #
+ DLLS += VBoxPython3_10
+ VBoxPython3_10_EXTENDS = VBoxPythonBase
+ VBoxPython3_10_EXTENDS_BY = appending
+ VBoxPython3_10_INCS = $(VBOX_PYTHON310_INC)
+ VBoxPython3_10_LIBS = $(VBOX_PYTHON310_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON310_LIB_X86
+ DLLS += VBoxPython3_10_x86
+ VBoxPython3_10_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_10_x86_EXTENDS_BY = appending
+ VBoxPython3_10_x86_INCS = $(VBOX_PYTHON310_INC)
+ VBoxPython3_10_x86_LIBS = $(VBOX_PYTHON310_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON311_INC
+ #
+ # Python 3.11 version (implicitly with pymalloc)
+ #
+ DLLS += VBoxPython3_11
+ VBoxPython3_11_EXTENDS = VBoxPythonBase
+ VBoxPython3_11_EXTENDS_BY = appending
+ VBoxPython3_11_INCS = $(VBOX_PYTHON311_INC)
+ VBoxPython3_11_LIBS = $(VBOX_PYTHON311_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON311_LIB_X86
+ DLLS += VBoxPython3_11_x86
+ VBoxPython3_11_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_11_x86_EXTENDS_BY = appending
+ VBoxPython3_11_x86_INCS = $(VBOX_PYTHON311_INC)
+ VBoxPython3_11_x86_LIBS = $(VBOX_PYTHON311_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHON312_INC
+ #
+ # Python 3.12 version (implicitly with pymalloc)
+ #
+ DLLS += VBoxPython3_12
+ VBoxPython3_12_EXTENDS = VBoxPythonBase
+ VBoxPython3_12_EXTENDS_BY = appending
+ VBoxPython3_12_INCS = $(VBOX_PYTHON312_INC)
+ VBoxPython3_12_LIBS = $(VBOX_PYTHON312_LIB)
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHON312_LIB_X86
+ DLLS += VBoxPython3_12_x86
+ VBoxPython3_12_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython3_12_x86_EXTENDS_BY = appending
+ VBoxPython3_12_x86_INCS = $(VBOX_PYTHON312_INC)
+ VBoxPython3_12_x86_LIBS = $(VBOX_PYTHON312_LIB_X86)
+ endif
+ endif
+ endif
+
+ ifdef VBOX_PYTHONDEF_INC
+ #
+ # Python without versioning
+ #
+ DLLS += VBoxPython
+ VBoxPython_EXTENDS = VBoxPythonBase
+ VBoxPython_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_DEFS))
+ VBoxPython_INCS = $(VBoxPythonBase_INCS) $(VBOX_PYTHONDEF_INC)
+ if "$(KBUILD_TARGET)" == "linux"
+ VBoxPython_LIBS = $(VBoxPythonBase_LIBS)
+ else
+ VBoxPython_LIBS = $(VBoxPythonBase_LIBS) $(VBOX_PYTHONDEF_LIB)
+ endif
+
+ ifdef VBOX_WITH_32_ON_64_MAIN_API
+ ifdef VBOX_PYTHONDEF_LIB_X86
+ VBoxPython_x86_EXTENDS = VBoxPythonBase_x86
+ VBoxPython_x86_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_x86_DEFS))
+ VBoxPython_x86_INCS = $(VBoxPythonBase_x86_INCS) $(VBOX_PYTHONDEF_INC)
+ if "$(KBUILD_TARGET)" == "linux"
+ VBoxPython_x86_LIBS = $(VBoxPythonBase_x86_LIBS)
+ else
+ VBoxPython_x86_LIBS = $(VBoxPythonBase_x86_LIBS) $(VBOX_PYTHONDEF_LIB_X86)
+ endif
+ endif
+ endif
+ endif
+
+ endif # !VBOX_WITH_ONLY_PYTHON_LIMITED_API
+
+ ifndef VBOX_WITHOUT_PYTHON_LIMITED_API
+ #
+ # If there is python 3.3 or later present, we can build a generic
+ # 3.x extension. Since 3.3 and 3.4 are rather old, we will pick
+ # those headers last.
+ #
+ # Note! No library dependencies are needed here (at least that's
+ # how the xxlimited.so demo extension is done on linux and darwin).
+ # Note! The 'm' ABI suffix was discontinued in 3.8.
+ # TODO: ASSUMING that we don't need a different headers for pymalloc
+ # ('m' builds < 3.8) and CRT malloc.
+ #
+ VBOX_PYTHON_LIMITED_API_VER := $(firstword $(foreach ver, 35 36 38 39 310 311 312 34 33 \
+ ,$(if-expr defined(VBOX_PYTHON$(ver)_INC),$(ver),)$(if-expr defined(VBOX_PYTHON$(ver)M_INC),$(ver)M,)))
+ ifneq ($(VBOX_PYTHON_LIMITED_API_VER),)
+ DLLS += VBoxPython3
+ VBoxPython3_EXTENDS = VBoxPythonBase
+ VBoxPython3_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_DEFS)) Py_LIMITED_API=0x03030000
+ VBoxPython3_INCS = $(VBoxPythonBase_INCS) $(VBOX_PYTHON$(VBOX_PYTHON_LIMITED_API_VER)_INC)
+
+ DLLS += VBoxPython3m
+ VBoxPython3m_EXTENDS = VBoxPythonBase_m
+ VBoxPython3m_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_m_DEFS)) Py_LIMITED_API=0x03030000
+ VBoxPython3m_INCS = $(VBoxPythonBase_m_INCS) $(VBOX_PYTHON$(VBOX_PYTHON_LIMITED_API_VER)_INC)
+ endif
+ endif # VBOX_WITH_PYTHON_LIMITED_API
+
+endif # VBOX_ONLY_SDK
+
+#
+# Install the python modules.
+#
+INSTALLS += VBoxPython-inst-py-xpcom
+VBoxPython-inst-py-xpcom_INST = $(INST_SDK)bindings/xpcom/python/xpcom/
+VBoxPython-inst-py-xpcom_MODE = a+r,u+w
+VBoxPython-inst-py-xpcom_SOURCES = \
+ vboxxpcom.py \
+ components.py \
+ file.py \
+ __init__.py \
+ nsError.py \
+ primitives.py \
+ xpcom_consts.py \
+ xpt.py \
+ client/__init__.py=>client/__init__.py \
+ server/__init__.py=>server/__init__.py \
+ server/enumerator.py=>server/enumerator.py \
+ server/factory.py=>server/factory.py \
+ server/loader.py=>server/loader.py \
+ server/module.py=>server/module.py \
+ server/policy.py=>server/policy.py
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/src/libs/xpcom18a4/python/README.vbox b/src/libs/xpcom18a4/python/README.vbox
new file mode 100644
index 00000000..b85f854c
--- /dev/null
+++ b/src/libs/xpcom18a4/python/README.vbox
@@ -0,0 +1,5 @@
+ PyXPCOM sources (see http://developer.mozilla.org/en/docs/PyXPCOM)
+were taken from :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot,
+directory extensions/python/xpcom, branch DOM_AGNOSTIC2_BRANCH, Aug 14 2008.
+
+ Imported to VirtualBox codebase in revision 34814.
diff --git a/src/libs/xpcom18a4/python/__init__.py b/src/libs/xpcom18a4/python/__init__.py
new file mode 100755
index 00000000..3a5943b6
--- /dev/null
+++ b/src/libs/xpcom18a4/python/__init__.py
@@ -0,0 +1,173 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# Activestate Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@activestate.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+#
+
+# The XPCOM (Cross Platform COM) package.
+from __future__ import print_function
+import sys
+if sys.version_info[0] <= 2:
+ import exceptions
+ XPCOMBaseException = exceptions.Exception
+else:
+ XPCOMBaseException = Exception
+
+# A global "verbose" flag - currently used by the
+# server package to print trace messages
+verbose = 0
+# Map of nsresult -> constant_name.
+hr_map = {}
+
+# The standard XPCOM exception object.
+# Instances of this class are raised by the XPCOM extension module.
+class Exception(XPCOMBaseException):
+ def __init__(self, errno, message = None):
+ assert int(errno) == errno, "The errno param must be an integer"
+ self.errno = errno
+ self.msg = message
+ XPCOMBaseException.__init__(self, errno)
+ def __str__(self):
+ if not hr_map:
+ from . import nsError
+ for name, val in list(nsError.__dict__.items()):
+ if type(val)==type(0):
+ hr_map[val] = name
+ message = self.msg
+ if message is None:
+ message = hr_map.get(self.errno)
+ if message is None:
+ message = ""
+ return "0x%x (%s)" % (self.errno & 0xFFFFFFFF, message)
+
+# An alias for Exception - allows code to say "from xpcom import COMException"
+# rather than "Exception", preventing clashes with the builtin Exception
+COMException = Exception
+
+# Exceptions thrown by servers. It can be good for diagnostics to
+# differentiate between a ServerException (which was presumably explicitly thrown)
+# and a normal exception which may simply be propagating down.
+# (When ServerException objects are thrown across the XPConnect
+# gateway they will be converted back to normal client exceptions if
+# subsequently re-caught by Python)
+class ServerException(Exception):
+ def __init__(self, errno=None, *args, **kw):
+ if errno is None:
+ from . import nsError
+ errno = nsError.NS_ERROR_FAILURE
+ Exception.__init__(self, errno, *args, **kw)
+
+# Logging support - setup the 'xpcom' logger to write to the Mozilla
+# console service, and also to sys.stderr, or optionally a file.
+# Environment variables supports:
+# PYXPCOM_LOG_FILE=filename - if set, used instead of sys.stderr.
+# PYXPCOM_LOG_LEVEL=level - level may be a number or a logging level
+# constant (eg, 'debug', 'error')
+# Later it may make sense to allow a different log level to be set for
+# the file than for the console service.
+import logging
+class ConsoleServiceStream:
+ # enough of a stream to keep logging happy
+ def flush(self):
+ pass
+ def write(self, msg):
+ import xpcom._xpcom as _xpcom
+ _xpcom.LogConsoleMessage(msg)
+ def close(self):
+ pass
+
+def setupLogging():
+ import os
+ if sys.version_info[0] <= 2:
+ import threading, thread
+ hdlr = logging.StreamHandler(ConsoleServiceStream())
+ fmt = logging.Formatter(logging.BASIC_FORMAT)
+ hdlr.setFormatter(fmt)
+ # There is a bug in 2.3 and 2.4.x logging module in that it doesn't
+ # use an RLock, leading to deadlocks in some cases (specifically,
+ # logger.warning("ob is %r", ob), and where repr(ob) itself tries to log)
+ # Later versions of logging use an RLock, so we detect an "old" style
+ # handler and update its lock
+ if sys.version_info[0] <= 2:
+ if type(hdlr.lock) == thread.LockType:
+ hdlr.lock = threading.RLock()
+
+ logger.addHandler(hdlr)
+ # The console handler in mozilla does not go to the console!?
+ # Add a handler to print to stderr, or optionally a file
+ # PYXPCOM_LOG_FILE can specify a filename
+ filename = os.environ.get("PYXPCOM_LOG_FILE")
+ stream = sys.stderr # this is what logging uses as default
+ if filename:
+ try:
+ # open without buffering so never pending output
+ stream = open(filename, "wU", 0)
+ except IOError as why:
+ print("pyxpcom failed to open log file '%s': %s" % (filename, why), file=sys.stderr)
+ # stream remains default
+
+ hdlr = logging.StreamHandler(stream)
+ # see above - fix a deadlock problem on this handler too.
+ if sys.version_info[0] <= 2:
+ if type(hdlr.lock) == thread.LockType:
+ hdlr.lock = threading.RLock()
+
+ fmt = logging.Formatter(logging.BASIC_FORMAT)
+ hdlr.setFormatter(fmt)
+ logger.addHandler(hdlr)
+ # Allow PYXPCOM_LOG_LEVEL to set the level
+ level = os.environ.get("PYXPCOM_LOG_LEVEL")
+ if level:
+ try:
+ level = int(level)
+ except ValueError:
+ try:
+ # might be a symbolic name - all are upper-case
+ level = int(getattr(logging, level.upper()))
+ except (AttributeError, ValueError):
+ logger.warning("The PYXPCOM_LOG_LEVEL variable specifies an "
+ "invalid level")
+ level = None
+ if level:
+ logger.setLevel(level)
+
+logger = logging.getLogger('xpcom')
+# If someone else has already setup this logger, leave things alone.
+if len(logger.handlers) == 0:
+ setupLogging()
+
+# Cleanup namespace - but leave 'logger' there for people to use, so they
+# don't need to know the exact name of the logger.
+del ConsoleServiceStream, logging, setupLogging
diff --git a/src/libs/xpcom18a4/python/client/.cvsignore b/src/libs/xpcom18a4/python/client/.cvsignore
new file mode 100644
index 00000000..52e4e611
--- /dev/null
+++ b/src/libs/xpcom18a4/python/client/.cvsignore
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
diff --git a/src/libs/xpcom18a4/python/client/__init__.py b/src/libs/xpcom18a4/python/client/__init__.py
new file mode 100755
index 00000000..48adc7f5
--- /dev/null
+++ b/src/libs/xpcom18a4/python/client/__init__.py
@@ -0,0 +1,539 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+import os
+from types import MethodType
+import logging
+from xpcom import xpt, COMException, nsError, logger
+
+# Suck in stuff from _xpcom we use regularly to prevent a module lookup
+from xpcom._xpcom import IID_nsISupports, IID_nsIClassInfo, \
+ IID_nsISupportsCString, IID_nsISupportsString, \
+ IID_nsISupportsWeakReference, IID_nsIWeakReference, \
+ XPTI_GetInterfaceInfoManager, GetComponentManager, XPTC_InvokeByIndex
+
+# Python 3 hacks:
+import sys
+if sys.version_info[0] >= 3:
+ long = int # pylint: disable=W0622,C0103
+
+# Attribute names we may be __getattr__'d for, but know we don't want to delegate
+# Could maybe just look for startswith("__") but this may screw things for some objects.
+_special_getattr_names = ["__del__", "__len__", "__nonzero__", "__eq__", "__neq__"]
+
+_just_int_interfaces = ["nsISupportsPRInt32", "nsISupportsPRInt16", "nsISupportsPRUint32", "nsISupportsPRUint16", "nsISupportsPRUint8", "nsISupportsPRBool"]
+_just_long_interfaces = ["nsISupportsPRInt64", "nsISupportsPRUint64"]
+_just_float_interfaces = ["nsISupportsDouble", "nsISupportsFloat"]
+# When doing a specific conversion, the order we try the interfaces in.
+_int_interfaces = _just_int_interfaces + _just_float_interfaces
+_long_interfaces = _just_long_interfaces + _just_int_interfaces + _just_float_interfaces
+_float_interfaces = _just_float_interfaces + _just_long_interfaces + _just_int_interfaces
+
+method_template = """
+def %s(self, %s):
+ return XPTC_InvokeByIndex(self._comobj_, %d, (%s, (%s)))
+"""
+def _MakeMethodCode(method):
+ # Build a declaration
+ param_no = 0
+ param_decls = []
+ param_flags = []
+ param_names = []
+ used_default = 0
+ for param in method.params:
+ param_no = param_no + 1
+ param_name = "Param%d" % (param_no,)
+ param_default = ""
+ if not param.hidden_indicator and param.IsIn() and not param.IsDipper():
+ if param.IsOut() or used_default: # If the param is "inout", provide a useful default for the "in" direction.
+ param_default = " = None"
+ used_default = 1 # Once we have used one once, we must for the rest!
+ param_decls.append(param_name + param_default)
+ param_names.append(param_name)
+
+ type_repr = xpt.MakeReprForInvoke(param)
+ param_flags.append( (param.param_flags,) + type_repr )
+ sep = ", "
+ param_decls = sep.join(param_decls)
+ if len(param_names)==1: # Damn tuple reprs.
+ param_names = param_names[0] + ","
+ else:
+ param_names = sep.join(param_names)
+ # A couple of extra newlines make them easier to read for debugging :-)
+ return method_template % (method.name, param_decls, method.method_index, tuple(param_flags), param_names)
+
+# Keyed by IID, each item is a tuple of (methods, getters, setters)
+interface_cache = {}
+# Keyed by [iid][name], each item is an unbound method.
+interface_method_cache = {}
+
+# Keyed by clsid from nsIClassInfo - everything ever queried for the CID.
+contractid_info_cache = {}
+have_shutdown = 0
+
+def _shutdown():
+ interface_cache.clear()
+ interface_method_cache.clear()
+ contractid_info_cache.clear()
+ global have_shutdown
+ have_shutdown = 1
+
+# Fully process the named method, generating method code etc.
+def BuildMethod(method_info, iid):
+ name = method_info.name
+ try:
+ return interface_method_cache[iid][name]
+ except KeyError:
+ pass
+ # Generate it.
+ assert not (method_info.IsSetter() or method_info.IsGetter()), "getters and setters should have been weeded out by now"
+ method_code = _MakeMethodCode(method_info)
+ # Build the method - We only build a function object here
+ # - they are bound to each instance as needed.
+
+## print "Method Code for %s (%s):" % (name, iid)
+## print method_code
+ codeObject = compile(method_code, "<XPCOMObject method '%s'>" % (name,), "exec")
+ # Exec the code object
+ tempNameSpace = {}
+ exec(codeObject, globals(), tempNameSpace)
+ ret = tempNameSpace[name]
+ if iid not in interface_method_cache:
+ interface_method_cache[iid] = {}
+ interface_method_cache[iid][name] = ret
+ return ret
+
+from xpcom.xpcom_consts import XPT_MD_GETTER, XPT_MD_SETTER, XPT_MD_NOTXPCOM, XPT_MD_CTOR, XPT_MD_HIDDEN
+FLAGS_TO_IGNORE = XPT_MD_NOTXPCOM | XPT_MD_CTOR | XPT_MD_HIDDEN
+
+# Pre-process the interface - generate a list of methods, constants etc,
+# but don't actually generate the method code.
+def BuildInterfaceInfo(iid):
+ assert not have_shutdown, "Can't build interface info after a shutdown"
+ ret = interface_cache.get(iid, None)
+ if ret is None:
+ # Build the data for the cache.
+ method_code_blocks = []
+ getters = {}
+ setters = {}
+ method_infos = {}
+
+ interface = xpt.Interface(iid)
+ for m in interface.methods:
+ flags = m.flags
+ if flags & FLAGS_TO_IGNORE == 0:
+ if flags & XPT_MD_SETTER:
+ param_flags = list([(x.param_flags,) + xpt.MakeReprForInvoke(x) for x in m.params])
+ setters[m.name] = m.method_index, param_flags
+ elif flags & XPT_MD_GETTER:
+ param_flags = list([(x.param_flags,) + xpt.MakeReprForInvoke(x) for x in m.params])
+ getters[m.name] = m.method_index, param_flags
+ else:
+ method_infos[m.name] = m
+
+ # Build the constants.
+ constants = {}
+ for c in interface.constants:
+ constants[c.name] = c.value
+ ret = method_infos, getters, setters, constants
+ interface_cache[iid] = ret
+ return ret
+
+class _XPCOMBase:
+ def __cmp__(self, other):
+ try:
+ other = other._comobj_
+ except AttributeError:
+ pass
+ return cmp(self._comobj_, other)
+
+ def __hash__(self):
+ return hash(self._comobj_)
+
+ # The basic rich compare ops for equality
+ def __eq__(self, other):
+ try:
+ other = other._comobj_
+ except AttributeError:
+ pass
+ return self._comobj_ == other
+
+ def __neq__(self, other):
+ try:
+ other = other._comobj_
+ except AttributeError:
+ pass
+ return self._comobj_ != other
+
+ # See if the object support strings.
+ def __str__(self):
+ try:
+ self._comobj_.QueryInterface(IID_nsISupportsCString, 0)
+ return str(self._comobj_)
+ except COMException:
+ return self.__repr__()
+
+ def __unicode__(self):
+ try:
+ prin = self._comobj_.QueryInterface(IID_nsISupportsString)
+ except COMException:
+ return unicode(str(self))
+ return prin.data
+
+ # Try the numeric support.
+ def _do_conversion(self, interface_names, cvt):
+ iim = XPTI_GetInterfaceInfoManager()
+ for interface_name in interface_names:
+ iid = iim.GetInfoForName(interface_name).GetIID()
+ try:
+ prim = self._comobj_.QueryInterface(iid)
+ return cvt(prim.data)
+ except COMException:
+ pass
+ raise ValueError("This object does not support automatic numeric conversion to this type")
+
+ def __int__(self):
+ if sys.version_info[0] >= 3:
+ return self._do_conversion(_int_interfaces + _long_interfaces, int)
+ return self._do_conversion(_int_interfaces, int)
+
+ def __long__(self):
+ return self._do_conversion(_long_interfaces, long)
+
+ def __float__(self):
+ return self._do_conversion(_float_interfaces, float)
+
+class Component(_XPCOMBase):
+ def __init__(self, ob, iid = IID_nsISupports):
+ assert not hasattr(ob, "_comobj_"), "Should be a raw nsIWhatever, not a wrapped one"
+ ob_name = None
+ if not hasattr(ob, "IID"):
+ ob_name = ob
+ cm = GetComponentManager()
+ ob = cm.createInstanceByContractID(ob)
+ assert not hasattr(ob, "_comobj_"), "The created object should be a raw nsIWhatever, not a wrapped one"
+ # Keep a reference to the object in the component too
+ self.__dict__['_comobj_'] = ob
+ # hit __dict__ directly to avoid __setattr__()
+ self.__dict__['_interfaces_'] = {} # keyed by IID
+ self.__dict__['_interface_names_'] = {} # keyed by IID name
+ self.__dict__['_interface_infos_'] = {} # keyed by IID
+ self.__dict__['_name_to_interface_iid_'] = {}
+ self.__dict__['_tried_classinfo_'] = 0
+
+ if ob_name is None:
+ ob_name = "<unknown>"
+ self.__dict__['_object_name_'] = ob_name
+ self.QueryInterface(iid)
+
+ def _build_all_supported_interfaces_(self):
+ # Use nsIClassInfo, but don't do it at object construction to keep perf up.
+ # Only pay the penalty when we really need it.
+ assert not self._tried_classinfo_, "already tried to get the class info."
+ self.__dict__['_tried_classinfo_'] = 1
+ # See if nsIClassInfo is supported.
+ try:
+ classinfo = self._comobj_.QueryInterface(IID_nsIClassInfo, 0)
+ except COMException:
+ classinfo = None
+ if classinfo is not None:
+ try:
+ real_cid = classinfo.contractID
+ except COMException:
+ real_cid = None
+ if real_cid:
+ self.__dict__['_object_name_'] = real_cid
+ contractid_info = contractid_info_cache.get(real_cid)
+ else:
+ contractid_info = None
+ if contractid_info is None:
+ try:
+ interface_infos = classinfo.getInterfaces()
+ except COMException:
+ interface_infos = []
+ for nominated_iid in interface_infos:
+ # Interface may appear twice in the class info list, so check this here.
+ if nominated_iid not in self.__dict__['_interface_infos_']:
+ # Just invoke our QI on the object
+ self.queryInterface(nominated_iid)
+ if real_cid is not None:
+ contractid_info = {}
+ contractid_info['_name_to_interface_iid_'] = self.__dict__['_name_to_interface_iid_']
+ contractid_info['_interface_infos_'] = self.__dict__['_interface_infos_']
+ contractid_info_cache[real_cid] = contractid_info
+ else:
+ for key, val in list(contractid_info.items()):
+ self.__dict__[key].update(val)
+
+ self.__dict__['_com_classinfo_'] = classinfo
+
+ def _remember_interface_info(self, iid):
+ # XXX - there is no good reason to cache this only in each instance
+ # It should be cached at the module level, so we don't need to
+ # rebuild the world for each new object.
+ iis = self.__dict__['_interface_infos_']
+ assert iid not in iis, "Already remembered this interface!"
+ try:
+ method_infos, getters, setters, constants = BuildInterfaceInfo(iid)
+ except COMException as why:
+ # Failing to build an interface info generally isn't a real
+ # problem - its probably just that the interface is non-scriptable.
+ logger.info("Failed to build interface info for %s: %s", iid, why)
+ # Remember the fact we failed.
+ iis[iid] = None
+ return
+
+ # Remember all the names so we can delegate
+ iis[iid] = method_infos, getters, setters, constants
+ names = self.__dict__['_name_to_interface_iid_']
+ for name in list(method_infos.keys()): names[name] = iid
+ for name in list(getters.keys()): names[name] = iid
+ for name in list(setters.keys()): names[name] = iid
+ for name in list(constants.keys()): names[name] = iid
+
+ def QueryInterface(self, iid):
+ if iid in self._interfaces_:
+ assert iid.name in self._interface_names_, "_interfaces_ has the key, but _interface_names_ does not!"
+ return self
+ # Haven't seen this before - do a real QI.
+ if iid not in self._interface_infos_:
+ self._remember_interface_info(iid)
+ iface_info = self._interface_infos_[iid]
+ if iface_info is None:
+ # We have tried, but failed, to get this interface info. Its
+ # unlikely to work later either - its probably non-scriptable.
+ # That means our component wrappers are useless - so just return a
+ # raw nsISupports object with no wrapper.
+ return self._comobj_.QueryInterface(iid, 0)
+
+ raw_iface = self._comobj_.QueryInterface(iid, 0)
+
+ method_infos, getters, setters, constants = iface_info
+ new_interface = _Interface(raw_iface, iid, method_infos,
+ getters, setters, constants)
+ self._interfaces_[iid] = new_interface
+ self._interface_names_[iid.name] = new_interface
+ # As we 'flatten' objects when possible, a QI on an object just
+ # returns ourself - all the methods etc on this interface are
+ # available.
+ return self
+
+ queryInterface = QueryInterface # Alternate name.
+
+ def __getattr__(self, attr):
+ if attr in _special_getattr_names:
+ raise AttributeError(attr)
+ # First allow the interface name to return the "raw" interface
+ interface = self.__dict__['_interface_names_'].get(attr, None)
+ if interface is not None:
+ return interface
+ # See if we know the IID of an interface providing this attribute
+ iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
+ # This may be first time trying this interface - get the nsIClassInfo
+ if iid is None and not self._tried_classinfo_:
+ self._build_all_supported_interfaces_()
+ iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
+ # If the request is for an interface name, it may now be
+ # available.
+ interface = self.__dict__['_interface_names_'].get(attr, None)
+ if interface is not None:
+ return interface
+
+ if iid is not None:
+ interface = self.__dict__['_interfaces_'].get(iid, None)
+ if interface is None:
+ self.QueryInterface(iid)
+ interface = self.__dict__['_interfaces_'][iid]
+ return getattr(interface, attr)
+ # Some interfaces may provide this name via "native" support.
+ # Loop over all interfaces, and if found, cache it for next time.
+ for interface in list(self.__dict__['_interfaces_'].values()):
+ try:
+ ret = getattr(interface, attr)
+ self.__dict__['_name_to_interface_iid_'][attr] = interface._iid_
+ return ret
+ except AttributeError:
+ pass
+ raise AttributeError("XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr))
+
+ def __setattr__(self, attr, val):
+ iid = self._name_to_interface_iid_.get(attr, None)
+ # This may be first time trying this interface - get the nsIClassInfo
+ if iid is None and not self._tried_classinfo_:
+ self._build_all_supported_interfaces_()
+ iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
+ if iid is not None:
+ interface = self._interfaces_.get(iid, None)
+ if interface is None:
+ self.QueryInterface(iid)
+ interface = self.__dict__['_interfaces_'][iid]
+ setattr(interface, attr, val)
+ return
+ raise AttributeError("XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr))
+
+ def _get_classinfo_repr_(self):
+ try:
+ if not self._tried_classinfo_:
+ self._build_all_supported_interfaces_()
+ assert self._tried_classinfo_, "Should have tried the class info by now!"
+ except COMException:
+ # Error building the info - ignore the error, but ensure that
+ # we are flagged as *not* having built, so the error is seen
+ # by the first caller who actually *needs* this to work.
+ self.__dict__['_tried_classinfo_'] = 0
+
+ iface_names = list(self.__dict__['_interface_names_'].keys())
+ try:
+ iface_names.remove("nsISupports")
+ except ValueError:
+ pass
+ iface_names.sort()
+
+ iface_desc = "implementing %s" % (",".join(iface_names),)
+ return iface_desc
+
+ def __repr__(self):
+ # We can advantage from nsIClassInfo - use it.
+ iface_desc = self._get_classinfo_repr_()
+ return "<XPCOM component '%s' (%s)>" % (self._object_name_,iface_desc)
+
+class _Interface(_XPCOMBase):
+ def __init__(self, comobj, iid, method_infos, getters, setters, constants):
+ self.__dict__['_comobj_'] = comobj
+ self.__dict__['_iid_'] = iid
+ self.__dict__['_property_getters_'] = getters
+ self.__dict__['_property_setters_'] = setters
+ self.__dict__['_method_infos_'] = method_infos # method infos waiting to be turned into real methods.
+ self.__dict__['_methods_'] = {} # unbound methods
+ self.__dict__['_object_name_'] = iid.name
+ self.__dict__.update(constants)
+ # We remember the constant names to prevent the user trying to assign to them!
+ self.__dict__['_constant_names_'] = list(constants.keys())
+
+ def __getattr__(self, attr):
+ # Allow the underlying interface to provide a better implementation if desired.
+ if attr in _special_getattr_names:
+ raise AttributeError(attr)
+
+ ret = getattr(self.__dict__['_comobj_'], attr, None)
+ if ret is not None:
+ return ret
+ # Do the function thing first.
+ unbound_method = self.__dict__['_methods_'].get(attr, None)
+ if unbound_method is not None:
+ return MethodType(unbound_method, self)
+
+ getters = self.__dict__['_property_getters_']
+ info = getters.get(attr)
+ if info is not None:
+ method_index, param_infos = info
+ if len(param_infos)!=1: # Only expecting a retval
+ raise RuntimeError("Can't get properties with this many args!")
+ args = ( param_infos, () )
+ return XPTC_InvokeByIndex(self._comobj_, method_index, args)
+
+ # See if we have a method info waiting to be turned into a method.
+ # Do this last as it is a one-off hit.
+ method_info = self.__dict__['_method_infos_'].get(attr, None)
+ if method_info is not None:
+ unbound_method = BuildMethod(method_info, self._iid_)
+ # Cache it locally
+ self.__dict__['_methods_'][attr] = unbound_method
+ return MethodType(unbound_method, self)
+
+ raise AttributeError("XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr))
+
+ def __setattr__(self, attr, val):
+ # If we already have a __dict__ item of that name, and its not one of
+ # our constants, we just directly set it, and leave.
+ if attr in self.__dict__ and attr not in self.__dict__['_constant_names_']:
+ self.__dict__[attr] = val
+ return
+ # Start sniffing for what sort of attribute this might be?
+ setters = self.__dict__['_property_setters_']
+ info = setters.get(attr)
+ if info is None:
+ raise AttributeError("XPCOM component '%s' can not set attribute '%s'" % (self._object_name_, attr))
+ method_index, param_infos = info
+ if len(param_infos)!=1: # Only expecting a single input val
+ raise RuntimeError("Can't set properties with this many args!")
+ real_param_infos = ( param_infos, (val,) )
+ return XPTC_InvokeByIndex(self._comobj_, method_index, real_param_infos)
+
+ def __repr__(self):
+ return "<XPCOM interface '%s'>" % (self._object_name_,)
+
+
+# Called by the _xpcom C++ framework to wrap interfaces up just
+# before they are returned.
+def MakeInterfaceResult(ob, iid):
+ return Component(ob, iid)
+
+class WeakReference:
+ """A weak-reference object. You construct a weak reference by passing
+ any COM object you like. If the object does not support weak
+ refs, you will get a standard NS_NOINTERFACE exception.
+
+ Once you have a weak-reference, you can "call" the object to get
+ back a strong reference. Eg:
+
+ >>> some_ob = components.classes['...']
+ >>> weak_ref = WeakReference(some_ob)
+ >>> new_ob = weak_ref() # new_ob is effectively "some_ob" at this point
+ >>> # EXCEPT: new_ob may be None if some_ob has already died - a
+ >>> # weak reference does not keep the object alive (that is the point)
+
+ You should never hold onto this resulting strong object for a long time,
+ or else you defeat the purpose of the weak-reference.
+ """
+ def __init__(self, ob, iid = None):
+ swr = Component(ob._comobj_, IID_nsISupportsWeakReference)
+ self._comobj_ = Component(swr.GetWeakReference()._comobj_, IID_nsIWeakReference)
+ if iid is None:
+ try:
+ iid = ob.IID
+ except AttributeError:
+ iid = IID_nsISupports
+ self._iid_ = iid
+ def __call__(self, iid = None):
+ if iid is None: iid = self._iid_
+ try:
+ return Component(self._comobj_.QueryReferent(iid)._comobj_, iid)
+ except COMException as details:
+ if details.errno != nsError.NS_ERROR_NULL_POINTER:
+ raise
+ return None
diff --git a/src/libs/xpcom18a4/python/components.py b/src/libs/xpcom18a4/python/components.py
new file mode 100755
index 00000000..b0910f87
--- /dev/null
+++ b/src/libs/xpcom18a4/python/components.py
@@ -0,0 +1,248 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+# This module provides the JavaScript "components" interface
+from . import xpt
+import xpcom
+import xpcom._xpcom as _xpcom
+import xpcom.client
+import xpcom.server
+
+StringTypes = [bytes, str]
+
+def _get_good_iid(iid):
+ if iid is None:
+ iid = _xpcom.IID_nsISupports
+ elif type(iid) in StringTypes and len(iid)>0 and iid[0] != "{":
+ iid = getattr(interfaces, iid)
+ return iid
+
+# The "manager" object.
+manager = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentManager)
+
+# The component registrar
+registrar = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentRegistrar)
+
+# The "interfaceInfoManager" object - JS doesnt have this.
+interfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager()
+
+# The serviceManager - JS doesnt have this either!
+serviceManager = _xpcom.GetServiceManager()
+
+# The "Exception" object
+Exception = xpcom.COMException
+
+# Base class for our collections.
+# It appears that all objects supports "." and "[]" notation.
+# eg, "interface.nsISupports" or interfaces["nsISupports"]
+class _ComponentCollection:
+ # Bases are to over-ride 2 methods.
+ # _get_one(self, name) - to return one object by name
+ # _build_dict - to return a dictionary which provide access into
+ def __init__(self):
+ self._dict_data = None
+ def keys(self):
+ if self._dict_data is None:
+ self._dict_data = self._build_dict()
+ return list(self._dict_data.keys())
+ def items(self):
+ if self._dict_data is None:
+ self._dict_data = self._build_dict()
+ return list(self._dict_data.items())
+ def values(self):
+ if self._dict_data is None:
+ self._dict_data = self._build_dict()
+ return list(self._dict_data.values())
+# def has_key(self, key):
+# if self._dict_data is None:
+# self._dict_data = self._build_dict()
+# return self._dict_data.has_key(key)
+
+ def __len__(self):
+ if self._dict_data is None:
+ self._dict_data = self._build_dict()
+ return len(self._dict_data)
+
+ def __getattr__(self, attr):
+ if self._dict_data is not None and attr in self._dict_data:
+ return self._dict_data[attr]
+ return self._get_one(attr)
+ def __getitem__(self, item):
+ if self._dict_data is not None and item in self._dict_data:
+ return self._dict_data[item]
+ return self._get_one(item)
+
+_constants_by_iid_map = {}
+
+class _Interface:
+ # An interface object.
+ def __init__(self, name, iid):
+ # Bypass self.__setattr__ when initializing attributes.
+ d = self.__dict__
+ d['_iidobj_'] = iid # Allows the C++ framework to treat this as a native IID.
+ d['name'] = name
+ def __cmp__(self, other):
+ this_iid = self._iidobj_
+ other_iid = getattr(other, "_iidobj_", other)
+ return cmp(this_iid, other_iid)
+ def __eq__(self, other):
+ this_iid = self._iidobj_
+ other_iid = getattr(other, "_iidobj_", other)
+ return this_iid == other_iid
+ def __hash__(self):
+ return hash(self._iidobj_)
+ def __str__(self):
+ return str(self._iidobj_)
+ def __getitem__(self, item):
+ raise TypeError("components.interface objects are not subscriptable")
+ def __setitem__(self, item, value):
+ raise TypeError("components.interface objects are not subscriptable")
+ def __setattr__(self, attr, value):
+ raise AttributeError("Can not set attributes on components.Interface objects")
+ def __getattr__(self, attr):
+ # Support constants as attributes.
+ c = _constants_by_iid_map.get(self._iidobj_)
+ if c is None:
+ c = {}
+ i = xpt.Interface(self._iidobj_)
+ for c_ob in i.constants:
+ c[c_ob.name] = c_ob.value
+ _constants_by_iid_map[self._iidobj_] = c
+ if attr in c:
+ return c[attr]
+ raise AttributeError("'%s' interfaces do not define a constant '%s'" % (self.name, attr))
+
+
+class _Interfaces(_ComponentCollection):
+ def _get_one(self, name):
+ try:
+ item = interfaceInfoManager.GetInfoForName(name)
+ except xpcom.COMException as why:
+ # Present a better exception message, and give a more useful error code.
+ from . import nsError
+ raise xpcom.COMException(nsError.NS_ERROR_NO_INTERFACE, "The interface '%s' does not exist" % (name,))
+ return _Interface(item.GetName(), item.GetIID())
+
+ def _build_dict(self):
+ ret = {}
+ enum = interfaceInfoManager.EnumerateInterfaces()
+ while not enum.IsDone():
+ # Call the Python-specific FetchBlock, to keep the loop in C.
+ items = enum.FetchBlock(500, _xpcom.IID_nsIInterfaceInfo)
+ # This shouldnt be necessary, but appears to be so!
+ for item in items:
+ ret[item.GetName()] = _Interface(item.GetName(), item.GetIID())
+ return ret
+
+# And the actual object people use.
+interfaces = _Interfaces()
+
+del _Interfaces # Keep our namespace clean.
+
+#################################################
+class _Class:
+ def __init__(self, contractid):
+ self.contractid = contractid
+ def __getattr__(self, attr):
+ if attr == "clsid":
+ rc = registrar.contractIDToCID(self.contractid)
+ # stash it away - it can never change!
+ self.clsid = rc
+ return rc
+ raise AttributeError("%s class has no attribute '%s'" % (self.contractid, attr))
+ def createInstance(self, iid = None):
+ import xpcom.client
+ try:
+ return xpcom.client.Component(self.contractid, _get_good_iid(iid))
+ except xpcom.COMException as details:
+ from . import nsError
+ # Handle "no such component" in a cleaner way for the user.
+ if details.errno == nsError.NS_ERROR_FACTORY_NOT_REGISTERED:
+ raise xpcom.COMException(details.errno, "No such component '%s'" % (self.contractid,))
+ raise # Any other exception reraise.
+ def getService(self, iid = None):
+ return serviceManager.getServiceByContractID(self.contractid, _get_good_iid(iid))
+
+class _Classes(_ComponentCollection):
+ def __init__(self):
+ _ComponentCollection.__init__(self)
+ def _get_one(self, name):
+ # XXX - Need to check the contractid is valid!
+ return _Class(name)
+
+ def _build_dict(self):
+ ret = {}
+ enum = registrar.enumerateContractIDs()
+ while enum.hasMoreElements():
+ # Call the Python-specific FetchBlock, to keep the loop in C.
+ items = enum.fetchBlock(2000, _xpcom.IID_nsISupportsCString)
+ for item in items:
+ name = str(item.data)
+ ret[name] = _Class(name)
+ return ret
+
+classes = _Classes()
+
+del _Classes
+
+del _ComponentCollection
+
+# The ID function
+ID = _xpcom.ID
+
+# A helper to cleanup our namespace as xpcom shuts down.
+class _ShutdownObserver:
+ _com_interfaces_ = interfaces.nsIObserver
+ def observe(self, service, topic, extra):
+ global manager, registrar, classes, interfaces, interfaceInfoManager, _shutdownObserver, serviceManager, _constants_by_iid_map
+ manager = registrar = classes = interfaces = interfaceInfoManager = _shutdownObserver = serviceManager = _constants_by_iid_map = None
+ xpcom.client._shutdown()
+ xpcom.server._shutdown()
+ def _query_interface_(self, iid): # VBox: Needed so that the interface check in the DefaultPolicy initialization will pass; @bugref{10079}.
+ if iid == interfaces.nsIObserver:
+ return 1
+ return None
+
+svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/observer-service;1", interfaces.nsIObserverService)
+# Observers will be QI'd for a weak-reference, so we must keep the
+# observer alive ourself, and must keep the COM object alive,
+# _not_ just the Python instance!!!
+_shutdownObserver = xpcom.server.WrapObject(_ShutdownObserver(), interfaces.nsIObserver)
+# Say we want a weak ref due to an assertion failing. If this is fixed, we can pass 0,
+# and remove the lifetime hacks above! See http://bugzilla.mozilla.org/show_bug.cgi?id=99163
+svc.addObserver(_shutdownObserver, "xpcom-shutdown", 1)
+del svc, _ShutdownObserver
diff --git a/src/libs/xpcom18a4/python/doc/advanced.html b/src/libs/xpcom18a4/python/doc/advanced.html
new file mode 100644
index 00000000..ab6994fc
--- /dev/null
+++ b/src/libs/xpcom18a4/python/doc/advanced.html
@@ -0,0 +1,176 @@
+<html>
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Python XPCOM Advanced Topics</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Advanced Topics</h1>
+
+<p>This document contains a series of tidbits that don't fit
+anywhere else. As the Python XPCOM Package documentation matures, most of
+these topics will have another home.</p>
+
+<h2>XPCOM Services</h2>
+<p>An XPCOM service is simply a singleton registered by name.&nbsp; Python has
+full support for both using and implementing XPCOM services.&nbsp; To use a
+service, use <i>xpcom.components.services</i> just like the JavaScript
+counterpart.&nbsp; There is nothing special about implementing a service in
+Python; see the standard XPCOM documentation on services for more information.</p>
+
+<h2>nsIVariant</h2>
+
+<p>There is (almost) full support for <i>nsIVariant</i>.&nbsp; Any <i>nsIVariant</i>
+parameters will automatically be translated to and from regular Python objects
+giving, in effect, a multi-type parameter.&nbsp; This should be automatic, so
+there is not much else to say!&nbsp; Note that if you really want, you can
+create and pass your own <i>nsIVariant</i> object instead of a regular Python
+object, thereby allowing explicit control over the type of variant created.</p>
+
+<h2>nsISupports Primitives.</h2>
+
+<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I
+term collectively the <i>nsISupports Primitives Interfaces</i>.&nbsp; These
+are a set of interfaces a component can support to allow automatic conversion to
+and from many basic types.&nbsp; For example, an interface can define that it
+supports the <i>nsISupportsCString</i> interface, and this could be used by any
+program that wishes to get a string representation of the object.&nbsp; If an
+interface wishes to expose itself as a &quot;boolean value&quot;, it may choose
+to support the <i>nsISupportsPRBool</i> interface.</p>
+<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are
+calling), you can use
+the builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the
+object<i>.</i>&nbsp; In the
+case of <i>str()</i>, if the object does not support the <i>nsISupportsCString</i>
+or <i>nsISupportsString</i> interfaces, the default string <i>str()</i> for the
+object will be returned (i.e., what is normally returned for most XPCOM objects -
+support for these interface is not very common!).&nbsp; In the case of the numeric functions, a <i>ValueError</i>
+exception will be raised if the objects do not support any interface that can be
+used for the conversion.&nbsp;<i>ValueError</i> is used instead of <i>TypeError</i>,
+as the type itself (i.e., an XPCOM object) can sometimes be used in this context -
+hence it is the specific <i>value</i> of the object that is the problem.</p>
+<p>The use of <i>repr()</i> on an XPCOM interface object prevents support
+attempts for these interfaces, and allows you to see the
+&quot;real&quot; object, rather than what the object wants you to see!</p>
+<p>When you implement an XPCOM object, you have two choices for implementation
+of these interfaces:</p>
+<ul>
+ <li>You can explicitly handle these interfaces like any other interface.&nbsp;
+ In this case, you have full control.&nbsp; However, if you
+ implement only one of these standard interfaces, then you are only
+ overriding the default behavior for that specific interface - all other
+ interfaces not explicitly listed in your class will still get the behavior
+ described below.<br>
+ </li>
+ <li>If your class does not define support for these interfaces, the framework
+ will use standard Python class semantics to implement them - i.e., if your
+ class provides a <i>__str__</i> method, it will be used to implement <i>nsISupportsCString</i>
+ and <i>nsISupportsString</i>, if you provide <i>__int__</i>, <i>__long__</i>,
+ <i>__float__</i> etc., methods, they will be used to implement the numeric
+ interfaces.&nbsp; If your class defines no such special methods, then the <i>
+ QueryInterface()</i> for those interfaces fails (rather than the QI succeeding
+ and the operation to fetch the data failing).</li>
+</ul>
+<blockquote>
+<p>This allows for an interesting feature that would not normally be
+possible.&nbsp; Consider Python code that does a <i>str()</i> on an&nbsp; XPCOM
+interface, and where the XPCOM interface itself is implemented in Python and
+provides a <i>__str__</i> method.&nbsp; The <i>str()</i> on the original
+interface queries for the <i>nsISupportsCString</i> interface.&nbsp; The
+Python implemented object responds to this interface and delegates to the <i>__str__</i>
+method. At the end of all this, <i>str()</i> returns the same result
+as if the objects were native Python objects with no XPCOM layer in between.</p>
+
+</blockquote>
+
+<h2>Enumerators</h2>
+
+<p>The primary enumerator used by XPCOM is <i>nsISimpleEnumerator</i>.
+Although the Python XPCOM package has full support for <i>nsIEnumerator</i>,
+since this interface is not &quot;scriptable&quot;, you should avoided using it in interfaces
+you design.</p>
+
+<p>When you use <i>nsISimpleEnumerator</i> from Python, the following enhancements
+are available:</p>
+<ul>
+ <li>The <i>GetNext()</i> method takes an optional IID as a parameter. If
+ this is specified, the returned object will be of this interface.&nbsp; This
+ prevents the manual <i>QueryInterface()</i> generally required from other
+ languages.</li>
+ <li>There is a <i>FetchBlock(num, [iid])</i> method, which fetches the
+ specified number of elements in one operation and returns a Python
+ list. This can be useful for large enumerator sets, so the loop
+ iterating the elements runs at full C++ speed.</li>
+</ul>
+<p><i>nsIEnumerator</i> has similar enhancements.</p>
+<p>When implementing a Python XPCOM object, the Python class <i>xpcom.server.enumerator.SimpleEnumerator()</i>
+can be used.&nbsp; You can pass a standard Python sequence (list, etc), and it
+will be correctly wrapped in an <i>nsISimpleEnumerator</i> interface.</p>
+<h2>Files</h2>
+<p>The Python XPCOM package provides an <i> xpcom.file</i> module.&nbsp; This implements
+a Python-like file object on top of the XPCOM/Mozilla stream interfaces.&nbsp;
+When run from within the Mozilla environment, this allows you to open almost any
+URL supported by Mozilla (including &quot;chrome://&quot; etc.,).</p>
+<p>See this module for more information, including test code.</p>
+<h2>XPCOM Object Identity</h2>
+<p>XPCOM has defined rules for object identity and for how objects must behave
+in their <i> QueryInterface()</i> implementations.&nbsp; The Python XPCOM framework
+manages this for you; your code can return new Python instances etc., when
+responding to new interfaces, and the framework itself will ensure the XPCOM
+semantics are followed.&nbsp; Critically, the framework provides no mechanism
+for breaking these rules.</p>
+<h2>Policies</h2>
+<p>The Python XPCOM framework has the concept of &quot;policies&quot; that
+define how XPCOM semantics are mapped to Python objects.&nbsp; It is the policy
+that implements delegation of <i> QueryInterface()</i>, translates property
+references into direct property references, and failing that, &quot;get_name&quot;
+and &quot;set_name&quot; calls, decides how to handle exceptions in the
+component, and so on.</p>
+<p>The default policy is very flexible and suitable for most purposes.
+Indeed, the Komodo project has never had to implement a custom policy.
+However, you should be aware the feature exists should you wish to do some
+bizarre things, such as using Python as a bridge between XPCOM and some other
+component technology.</p>
+
+</body>
+
+</html>
diff --git a/src/libs/xpcom18a4/python/doc/architecture.html b/src/libs/xpcom18a4/python/doc/architecture.html
new file mode 100644
index 00000000..d12a2a76
--- /dev/null
+++ b/src/libs/xpcom18a4/python/doc/architecture.html
@@ -0,0 +1,116 @@
+<html>
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Architecture</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Package Architecture</h1>
+<h2><a name="Architecture">Architecture</a></h2>
+<p>Much of the design for the Python XPCOM Package has been borrowed from the Python MS-COM
+extensions in <i>win32com</i>. Most of the major limitations and drawbacks in the <i>win32com</i>
+design have been addressed, mainly &quot;auto-wrapping&quot; of
+interface objects, which is not supported by <i>win32com</i>.</p>
+<p>Like <i>win32com</i>, this architecture includes the concept of <i>client COM</i> and <i>server
+COM.</i> </p>
+<p>Client COM:</p>
+<ul>
+ <li>calls other interfaces</li>
+ <li>is supported by <i>PyInterfaces</i> implemented in C++, which assists
+in making the COM calls</li>
+ <li>is supported by <i>PyGateways</i>, which assists in receiving
+external COM calls and dispatching them to the correct Python object</li>
+ <li> is supported in the <i>xpcom/client</i> package</li>
+</ul>
+<p>Server COM:</p>
+<ul>
+ <li>implements interfaces for use by other XPCOM applications or components</li>
+ <li> is
+supported in the <i>xpcom/server</i> package</li>
+</ul>
+<p>The XPConnect framework is very powerful, and far exceeds what COM's <i>
+IDispatch</i> can offer.&nbsp; Thus, we are able to get by with far fewer interfaces
+supported in the C++ level, and defer most things to the Python code that uses
+XPConnect.&nbsp; As a result, the requirement for a huge number of interfaces to
+exist in the <i>.pyd</i> does not exist.&nbsp; There are, however, a number of
+interfaces that do require native C++ support: these are interfaces
+required to &quot;boot&quot; the XPConnect support (i.e., the interfaces that are
+used to get information about interfaces), and also two gateways that need to
+work without interface information available. This last requirement is
+due to the XPCOM shutdown-ordering - it may be a bug, but is not an unreasonable
+amount of code anyway.</p>
+<p><b>Auto-wrapping</b> of COM objects is supported by both client COM and
+server COM.&nbsp;For client COM, auto-wrapping means that the
+Python programmer always sees Python &quot;component&quot; objects, rather than
+raw C++ interface objects; to the user, it all appears to &quot;just
+work&quot;.&nbsp; This is a major source of frustration in the <i>win32com</i>
+framework.</p>
+<p>For server COM, auto-wrapping means that you can
+pass Python instances wherever a COM object is expected. If the Python
+instance supports COM interfaces, by virtue of having a <i>_com_interfaces_</i>
+attribute that lists the interface requested, it will be automatically wrapped
+in the correct COM object.&nbsp;</p>
+<p><b>Error Handling:</b> The C++ framework has good error handling support,
+and uses the XPCOM console service to log debug messages, Python exceptions and
+tracebacks.&nbsp; <i>win32com</i> does not have good exception/traceback support
+at the C++ level, mainly because COM does not define a service like
+the console where debug messages can go.&nbsp; This does mean that in Mozilla
+release builds, these debug messages are likely to be lost, but the <i>--console</i>
+command line option to a release Mozilla will get them back.&nbsp; Therefore,
+the other error-support utilities, such as the error callbacks made on the
+policy object, may be used.</p>
+<p><b>Component Loader, Modules and Factories:</b>&nbsp; XPCOM has the concept
+of a component loader - a module used to load all components of a
+particular type.&nbsp; For example, the <i>moz.jsloader.1</i> component loads all
+the JavaScript components.&nbsp;Similarly, the <i>moz.pyloader.1</i>
+component loads all Python components.&nbsp; However, unlike
+JavaScript, the Python component loader is actually implemented in Python
+itself!&nbsp;Since the Python component loader can not be used to load
+itself, this component has some special code, <i>pyloader.dll,</i> to boot-strap itself.</p>
+<p>This means is that all XPCOM components, including the Python loader itself and all
+XPCOM module and factory interfaces, are implemented in
+Python.&nbsp;<b>There are no components or interfaces implemented purely in C++
+in this entire package!</b></p>
+
+</body>
+
+</html>
diff --git a/src/libs/xpcom18a4/python/doc/configure.html b/src/libs/xpcom18a4/python/doc/configure.html
new file mode 100644
index 00000000..e2b5d416
--- /dev/null
+++ b/src/libs/xpcom18a4/python/doc/configure.html
@@ -0,0 +1,196 @@
+<html>
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Configuring your Environment</title>
+</head>
+
+<body>
+
+<h1>Building, Configuring and Testing Python XPCOM Package</h1>
+<p>This document attempts to explain how to build, configure and test the
+Python XPCOM Package. This document assumes you have already successfully
+built
+Mozilla from source and your environment is currently set up for such a build -
+see the <a href="http://www.mozilla.org/build/">Mozilla build documentation</a>
+for more information.</p>
+<p>PyXPCOM can be built on Windows using either the <i>nmake makefile.win</i>
+process, or the <i>configure; gmake</i> process used by Linux.</p>
+<h2>configure; gmake Instructions</h2>
+<h3>Preparing for the build</h3>
+<ul>
+ <li>Apply the patch in <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=129216">bugzilla
+ bug 129216</a>. (If this bug is marked as &quot;FIXED&quot;, it probably
+ means there is no need to apply the patch and that these docs are out of
+ date)</li>
+ <li>On Linux, you must have Python built for dynamic linking.&nbsp; <a href="http://aspn.activestate.com/ASPN/Python">ActivePython</a>
+ 2.1 is one such build.</li>
+ <li>On Windows, you must have a Python source tree installed and built.&nbsp;
+ Patches gratefully accepted that allow an installed Python to be used (it
+ should not be hard!)</li>
+ <li>Ensure the Python interpreter you wish to use is on your path, such that
+ &quot;python&quot; will execute it correctly.&nbsp; The configure process
+ uses this to locate the Python support files.</li>
+</ul>
+<h3>Building</h3>
+<ul>
+ <li>From the top-level Mozilla directory, execute <i>./configure
+ --enable-extensions=python/xpcom</i>. As per the Mozilla build
+ instructions, you may add this option to your <i>.mozconfig</i> file.&nbsp;
+ If you wish to enable debugging, just enable it as you would normally for
+ Mozilla; PyXPCOM will pick up the same settings.<br>
+ (On Windows you will need to execute <i>sh ./configure ...</i> if running
+ from a Command Prompt.&nbsp; See the <a href="http://www.mozilla.org/build/win32.html#ss2.2b">Mozilla
+ win32 specific gmake build instructions</a> for more details.</li>
+ <li>Build the Mozilla tree as normal; PyXPCOM will automatically be
+ built.&nbsp; Alternatively, change to the top-level PyXPCOM directory and
+ execute <i>gmake</i> in that directory.</li>
+</ul>
+<h2>PyXPCOM outside Mozilla</h2>
+<p>When you are using PyXPCOM from inside mozilla, no additional configuration
+options should be necessary.&nbsp; However, if you wish to use PyXPCOM from
+stand-alone Python (ie, so you can write simple Python scripts that can be
+executed normally and use XPCOM), then additional environment variables must be
+setup.</p>
+<ul>
+ <li><a name="PYTHONPATH"><b>PYTHONPATH</b></a> - <tt>PYTHONPATH</tt> needs to
+ be set appropriately.&nbsp;You must manually ensure that the <i>mozilla/dist/bin/python</i>
+ directory (which is where PyXPCOM was installed during the build process) is
+ listed.&nbsp; Note that when PyXPCOM is used from within Mozilla (or any
+ other xpcom process), this path will automatically be added to sys.path.&nbsp;
+ It is only when Python directly uses xpcom that this step is necessary.<br>
+ If anything is wrong here you should get a normal <tt>ImportError</tt>.</li>
+</ul>
+<blockquote>
+ <p>Note that on Windows, the PYTHONPATH is generally maintained in the
+ Registry; however, you can set this variable at a DOS prompt, and it will still be
+added to the core PYTHONPATH.
+</blockquote>
+<ul>
+ <li><b><a name="PATH">PATH</a>, LD_LIBRARY_PATH, etc</b> - On Windows, you
+ must ensure that the Mozilla bin directory is listed on your PATH, or that
+ you execute your scripts with the Mozilla bin directory as the current
+ directory.<br>
+ On Linux, you must set your PATH and LD_LIBRARY_PATH variables
+ appropriately.&nbsp; However, you may find it simpler and easier to use the <i>run-mozilla.sh</i>
+ script in the Mozilla bin directory.&nbsp; For example, changing to the
+ Mozilla bin directory and executing:<br>
+ <i>./run-mozilla.sh python ~/src/mozilla/extensions/python/xpcom/test/regrtest.py</i><br>
+ should setup a correct environment and execute the PyXPCOM test suite.</li>
+</ul>
+<h2><a name="RunningTheTests">Testing your Setup</a></h2>
+<p>The Python XPCOM Package has a complete test suite.</p>
+<p>In the rest of this section, we walk through some simpler tests a step at a time,
+to help diagnose any problems.</p>
+<p><b>Note:</b> We recommend you do all your testing outside of <i> mozilla.exe</i>; it is far simpler to test all of
+this using the PyXPCOM package stand-alone.</p>
+<p><b>Note:</b> On Windows, if you use a debug build of Mozilla (i.e., in <i>dist\WIN32_D.OBJ\bin)</i>,
+ you <b>must</b> use <i>python_d.exe</i>; if you use a release build (i.e., in
+ a <i>dist\WIN32_O.OBJ\bin</i> directory), you must use <i>python.exe</i>.&nbsp;
+<i>makefile.stupid.win</i> handles this automatically.</p>
+<p>To test your setup:</p>
+<ol>
+ <li>Start Python, and check<br>
+ &gt;&gt;&gt; <i>import xpcom</i><br>
+ works. If not, <a href="#PYTHONPATH">check your PYTHONPATH</a> - the
+ main PyXPCOM package can not be located.&nbsp; Also check your <a href="#PATH">PATH</a>,
+ and if you are on Linux, remember that executing ./run-mozilla.sh python is
+ the easiest way.</li>
+ <li>Check<i><br>
+ &gt;&gt;&gt; import xpcom._xpcom</i><br>
+
+works. If not, then most likely your <a href="#PATH">Mozilla
+ directory is not on your path</a>, or something is wrong with <i>_xpcom(_d).pyd/_xpcommodule.so</i>.</li>
+
+ <li>Next run a simple test: <i>test/test_misc.py</i>.&nbsp;With a Windows debug build, the command may look like:<br>
+ <i>C:\Anywhere&gt; python_d \src\python\xpcom\test\test_misc.py<br>
+ </i>or on Linux<br>
+ <i>/home/user/src/mozilla/dist/bin$ python /home/user/src/python/xpcom/test/test_misc.py</i></li>
+</ol>
+<p>If you can't get this going, you won't get much further! (You may see a few
+errors - that is OK, as long as it appears something worked!).&nbsp; If
+everything looks OK, the
+next step is to register our test component and run our full test suite.</p>
+<h2><a name="Registration">Registering the Loader and Test Component</a></h2>
+<p>First register the generic Python loader. For instructions, see the <a href="file:///F:/src/as/Komodo/src/pyxpcom/xpcom/doc/architecture.html">architecture
+document</a>.&nbsp;Do this only once, regardless of how many
+Python components you have.&nbsp; Then install the test component itself, and
+finally you can test it!</p>
+<h3>Registering the Python Loader and Component</h3>
+<p>To register the Python Loader and Component:</p>
+<ol>
+ <li>Ensure the build process has put <i>pyloader.dll </i>(or <i>modpyloader.so</i>
+ for Unix), and the files <i> py_test_component.py </i> and <i> py_test_component.idl</i> into
+ the Mozilla <i>bin/components</i> directory.&nbsp; If not, copy the files
+ there manually.</li>
+ <li>Run <i>regxpcom </i>(or .<i>/run-mozilla.sh ./regxpcom</i> if appropriate).&nbsp;<i>regxpcom</i> is a standard Mozilla
+ executable, found in the <i>bin</i> directory, that detects the new DLL and
+ .py
+ files and registers them accordingly.&nbsp; You should
+ see a few messages that include the following:</li>
+</ol>
+<blockquote>
+ <pre>Registering: PythonComponentLoader
+Registered 1 Python components in pyloader.dll
+nsNativeComponentLoader: autoregistering succeeded
+Auto-registering all Python components in F:\src\mozilla\dist\WIN32_D.OBJ\bin\components
+Registering: PythonTestComponent
+Registered 1 Python components in py_test_component.py</pre>
+</blockquote>
+<p>If so (or you see no message at all), you are ready to run the test suite.</p>
+<p><b>Note</b>: If you execute this same step a second time, you will not
+see any of the above mentioned messages.&nbsp;XPCOM knows that nothing has
+changed since you last ran <i>regxpcom</i>, so nothing is registered.&nbsp; If
+you do not see these messages the first time you run it, there is the
+possibility that some other process, possibly the build process, has already
+executed this step.</p>
+<h2><b>Running the Test Suite</b></h2>
+<p>Before running the test suite, you should change to the <i>mozilla/xpcom/sample</i>
+directory and build it.&nbsp; This will build and install a sample component
+which is used by the test suite.&nbsp; If you do not have this component
+available, some of the Python tests will fail.</p>
+
+<p>To run the test suite, run <i>xpcom/test/regrtest.py.</i>&nbsp; This runs the
+tests and ensures that the test output is as expected.&nbsp; If all tests
+pass, you have a fully functioning Python XPCOM package.&nbsp; Enjoy!</p>
+
+</body>
+
+</html>
diff --git a/src/libs/xpcom18a4/python/doc/credits.html b/src/libs/xpcom18a4/python/doc/credits.html
new file mode 100644
index 00000000..2be7809f
--- /dev/null
+++ b/src/libs/xpcom18a4/python/doc/credits.html
@@ -0,0 +1,86 @@
+<html>
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Language" content="en-au">
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Credits and Acknowledgements</title>
+</head>
+
+<body>
+
+<h1>Credits and Acknowledgements</h1>
+<h2>ActiveState Tool Corporation</h2>
+<p>The Python XPCOM Package was developed primarily by <a href="mailto:markh@activestate.com">Mark
+Hammond</a> of <a href="http://www.ActiveState.com">ActiveState Tool Corporation</a>.</p>
+<p>The developers on the <a href="http://www.ActiveState.com/Products/Komodo">Komodo
+project</a> deserve high praise for putting up with early versions when almost
+nothing worked, and for believing in Python as a viable XPCOM language.&nbsp;
+Their feedback and patience has allowed the first public release to be amazingly
+functional and bug-free.</p>
+<h3>Komodo Development Team (at December 2000)</h3>
+<p><a href="mailto:davida@activestate.com">David Ascher</a>, <a href="mailto:aaronb@ActiveState.com">Aaron Bingham</a>,
+<a href="mailto:bindu@activestate.com">Bin Du</a>, <a href="mailto:markh@activestate.com">Mark
+Hammond</a>, <a href="mailto:trentm@activestate.com">Trent Mick (build god)</a>,&nbsp;
+<a href="mailto:paulp@activestate.com">Paul Prescod</a>,&nbsp; <a href="mailto:ericp@ActiveState.com">Eric Promislow</a>,
+<a href="mailto:kens@ActiveState.com">Ken Simpson</a>, <a href="mailto:neilw@ActiveState.com">Neil Watkiss</a>,
+<a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a>.</p>
+<h2>Mozilla/Netscape</h2>
+<p>The following people at <a href="http://www.netscape.com">Netscape</a> and <a href="http://www.mozilla.org">Mozilla</a>
+(or not there but still heavily involved in the project) have provided enormous
+help in getting things integrated with their build system, answering us on the
+newsgroup, teaching us the finer points of XPCOM, gently slapping us for accidentally
+referring to <i>jscript</i>, etc., and otherwise lending us a clue in the
+Mozilla/Netscape/XPCOM world.</p>
+<p><a href="mailto:jband@netscape.com">John Bandhauer</a>, <a href="mailto:brendan@meer.net">Brendan
+Eich</a>, <a href="mailto:shaver@zeroknowledge.com">Mike Shaver</a>, <a href="mailto:evaughan@netscape.com">Eric Vaughan</a>,
+<a href="mailto:hyatt@netscape.com">David Hyatt</a></p>
+<h2>External Contributors</h2>
+<p>The following people have made contributions to the project, simply because
+they find it useful and enjoy supporting Open Source projects.</p>
+<p><a href="mailto:cmeerw@web.de">Christof Meerwald</a></p>
+<h2>Documentation Credits</h2>
+<p>The following people have contributed to the Python XPCOM Package
+documentation&nbsp;</p>
+<p><a href="mailto:markh@activestate.com">Mark
+Hammond</a>, <a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a></p>
+
+</body>
+
+</html>
diff --git a/src/libs/xpcom18a4/python/doc/tutorial.html b/src/libs/xpcom18a4/python/doc/tutorial.html
new file mode 100644
index 00000000..808d4c06
--- /dev/null
+++ b/src/libs/xpcom18a4/python/doc/tutorial.html
@@ -0,0 +1,286 @@
+<html>
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Python XPCOM Package Tutorial</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Package Tutorial</h1>
+<p>This is a quick introduction to the Python XPCOM Package. We assume that you have a good understanding of Python and <a href="http://www.mozilla.org/projects/xpcom/">XPCOM</a>,
+and have experience both using and implementing XPCOM objects in some other
+language (e.g., C++ or JavaScript). We <b><i>do not</i></b> attempt to
+provide a tutorial to XPCOM or Python itself, only to using Python <i>and</i>
+ XPCOM.</p>
+<p>This tutorial contains the following sections:</p>
+<ul>
+ <li><a href="#Using">Using XPCOM Objects and Interfaces</a> - when you wish to
+ <i>use</i> a component written by anyone else in any XPCOM supported
+ language.</li>
+ <li><a href="#Implementing">Implementing XPCOM Objects and Interfaces</a> -
+ when you wish to implement a component for use by anyone else in any xpcom
+ supported language.</li>
+ <li><a href="#Parameters">Parameters and Types</a> - useful information
+ regarding how Python translates XPCOM types, and handles byref parameters.</li>
+</ul>
+<p>For anything not covered here, try the <a href="advanced.html">advanced
+documentation</a>, and if that fails, use the source, Luke!</p>
+<h2><a name="Using">Using XPCOM object and interfaces.</a></h2>
+<p>The techniques for using XPCOM in Python have been borrowed from JavaScript -
+thus, the model described here should be quite familiar to existing JavaScript
+XPCOM programmers.</p>
+<h3>xpcom.components module</h3>
+<p>When using an XPCOM object, the primary module used is the <u><i>xpcom.components</i></u>
+ module.&nbsp; Using this module, you can get a Python object that supports any
+scriptable XPCOM interface. Once you have this Python object, you can
+simply call XPCOM methods on the object, as normal.</p>
+<p>The <u><i>xpcom.components</i></u> module defines the following public
+members:</p>
+<table border="1" width="100%">
+ <tr>
+ <td width="16%"><b>Name</b></td>
+ <td width="84%"><b>Description</b></td>
+ </tr>
+ <tr>
+ <td width="16%">classes</td>
+ <td width="84%">A mapping (dictionary-like object) used to get XPCOM
+ &quot;classes&quot;.&nbsp; These are indexed by XPCOM contract ID, just
+ like the JavaScript object of the same name.&nbsp;&nbsp;
+ <p>Example:</p>
+ <pre>cls = components.classes[&quot;@mozilla.org/sample;1&quot;]
+ob = cls.createInstance() # Now have an nsISupports</pre>
+ </td>
+ </tr>
+ <tr>
+ <td width="16%">interfaces</td>
+ <td width="84%">An object that exposes all XPCOM interface IDs (IIDs).&nbsp;
+ Like the JavaScript object of the same name, this object uses
+ &quot;dot&quot; notation, as demonstrated below.
+ <p>Example:</p>
+ <pre>ob = cls.createInstance(components.interfaces.nsISample)
+# Now have an nsISample</pre>
+ </td>
+ </tr>
+</table>
+<p>For many people, this is all you need to know. Consider the Mozilla Sample Component.&nbsp; The Mozilla Sample
+Component has a contract ID of <i>@mozilla.org/sample;1</i>,
+and implements the <i>nsISample</i> interface.</p>
+<p>Thus, a complete Python program that uses this component is shown below.</p>
+<pre>from xpcom import components
+cls = components.classes[&quot;@mozilla.org/sample;1&quot;]
+ob = cls.createInstance() # no need to specify an IID for most components
+# nsISample defines a &quot;value&quot; property - let's use it!
+ob.value = &quot;new value&quot;
+if ob.value != &quot;new value&quot;:
+ print &quot;Eeek - what happened?&quot;</pre>
+<p>And that is it - a complete Python program that uses XPCOM.</p>
+<h2><a name="Implementing">Implementing XPCOM Objects and Interfaces.</a></h2>
+<p>Implementing XPCOM objects is almost as simple as using them. The
+basic strategy is this:</p>
+<ol>
+ <li>Create a standard Python source file, with a standard Python class.</li>
+ <li>Add some special <a href="#Attributes"> attributes</a> to your class for use by the Python XPCOM
+ framework. This controls the XPCOM behavior of your object.</li>
+ <li>Implement the XPCOM <a href="#Properties"> properties</a> and methods of your classes as normal.</li>
+ <li>Put the Python source file in the Mozilla <i> components</i> directory.</li>
+ <li>Run <i> regxpcom.</i></li>
+</ol>
+<p>Your component is now ready to be used.</p>
+<h3><a name="Attributes">Attributes</a></h3>
+<p>There are two classes of attributes: those used at runtime to define the object
+behavior and those used at registration time to control object
+registration.&nbsp; Not all objects require registration, thus not all
+Python XPCOM objects will have registration-related attributes.</p>
+<table border="1" width="100%">
+ <tr>
+ <td width="17%"><b>Attribute</b></td>
+ <td width="83%"><b>Description</b></td>
+ </tr>
+ <tr>
+ <td width="17%">_com_interfaces_</td>
+ <td width="83%">The interface IDs (IIDs) supported by the component.&nbsp;
+ For simplicity, this may be either a single IID, or a list of IIDs.&nbsp;
+ There is no need to specify base interfaces, as all parent interfaces are
+ automatically supported. Thus, it is never necessary to nominate <i>
+ nsISupports</i> in the list of interfaces.
+ <p>This attribute is required. Objects without such an attribute are
+ deemed unsuitable for use as a XPCOM object.</td>
+ </tr>
+ <tr>
+ <td width="17%">_reg_contractid_</td>
+ <td width="83%">The contract ID of the component.&nbsp; Required if the
+ component requires registration (i.e., exists in the components directory).</td>
+ </tr>
+ <tr>
+ <td width="17%">_reg_clsid_</td>
+ <td width="83%">The Class ID (CLSID) of the component, as a string in the
+ standard &quot;{XXX-XXX-XXX-XXX}&quot; format. Required if the
+ component requires registration (i.e., exists in the components directory).</td>
+ </tr>
+ <tr>
+ <td width="17%">_reg_registrar_</td>
+ <td width="83%">Nominates a function that is called at registration
+ time. The default is for no extra function to be called. This can
+ be useful if a component has special registration requirements and needs
+ to hook into the registration process.</td>
+ </tr>
+ <tr>
+ <td width="17%">_reg_desc_</td>
+ <td width="83%">The description of the XPCOM object. This may be used by
+ browsers or other such objects.&nbsp; If not specified, the contract ID
+ is used.</td>
+ </tr>
+</table>
+<h3><a name="Properties">Properties</a></h3>
+<p>A Python class can support XPCOM properties in one of two ways.&nbsp; Either
+a standard Python property of the same name can exist - our sample
+component demonstrates this with the <i>boolean_value</i> property.&nbsp;
+Alternatively, the class can provide the <i>get_propertyName(self)</i> and <i>set_propertyName(self,
+value)</i> functions (with <i>propertyName</i> changed to the appropriate value for the
+property), and these functions will be called instead.</p>
+<h4>Example:&nbsp; The Python XPCOM Test Component</h4>
+<p>As an example, examine the Python XPCOM Test Component.&nbsp; This
+code can be found in <i>py_test_component.py</i>.</p>
+<pre>from xpcom import components
+
+class PythonTestComponent:
+ _com_interfaces_ = components.interfaces.nsIPythonTestInterface
+ _reg_clsid_ = &quot;{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}&quot;
+ _reg_contractid_ = &quot;Python.TestComponent&quot;
+ def __init__(self):
+ self.boolean_value = 1
+ ...
+ def do_boolean(self, p1, p2):
+ ret = p1 ^ p2
+ return ret, not ret, ret
+...</pre>
+<p><b>Note:</b> This component only specifies the mandatory attributes - <i>_com_interfaces</i>,
+<i>_reg_clsid_</i> and <i>_reg_contractid_</i>.</p>
+<p>This sample code demonstrates supporting the <i>boolean_value</i> attribute,
+supported implicitly, as it is defined in the IDL and exists as a real Python
+attribute of that name, and a method called <i>do_boolean</i>.</p>
+<h4>Tip: The xpcom/xpt.py Script</h4>
+<p> The xpcom/xpt.py script is a useful script that can generate the skeleton of a class for
+any XPCOM interface.&nbsp; Just specify the interface name on the command-line,
+and paste the output into your source file.</p>
+<p>This is the output of running this program over the <i>nsISample</i>
+interface (i.e., assuming we wanted to implement a component that supported this
+interface):</p>
+<pre>class nsISample:
+ _com_interfaces_ = xpcom.components.interfaces.nsISample
+ # If this object needs to be registered, the following 2 are also needed.
+ # _reg_clsid_ = {a new clsid generated for this object}
+ # _reg_contractid_ = &quot;The.Object.Name&quot;
+
+ def get_value( self ):
+ # Result: string
+ pass
+ def set_value( self, param0 ):
+ # Result: void - None
+ # In: param0: string
+ pass
+ def writeValue( self, param0 ):
+ # Result: void - None
+ # In: param0: string
+ pass
+ def poke( self, param0 ):
+ # Result: void - None
+ # In: param0: string
+ pass</pre>
+<p><b>Note:</b> The types of the parameters and the function itself are included in
+the comments.&nbsp;You need to implement the functions
+themselves.&nbsp; Another advantage of this script is that the <a href="#HiddenParams">hidden
+parameters</a> are handled for you; the comments indicate when parameters
+have been hidden.</p>
+<h2><a name="Parameters">Parameters and Types</a></h2>
+<p>This section briefly describes the XPCOM type support in
+Python.</p>
+<p>All XPCOM interfaces define parameters of a specific type.&nbsp; There is
+currently no concept of a variant, or union of all types. Thus, the
+conversion rules are very straightforward, and generally surprise free: for
+any given XPCOM method, there is only one possible type for a given parameter.</p>
+<h3>Type Conversion Rules:</h3>
+<ul>
+ <li>All numeric types will attempt to be coerced to the correct type.&nbsp;
+ Thus, you can pass a Python float to an XPCOM method expecting an integer,
+ or vice-versa. Specifically, when an integer is required, you can pass
+ any Python object for which <i>int()</i> would succeed; for a Python float,
+ any object for which <i>float()</i> would succeed is acceptable.&nbsp; This
+ means that you can pass a Python string object as an integer, as long as the
+ string was holding a valid integer.</li>
+ <li>Strings and Unicode objects are interchangeable, but no other automatic
+ string conversions are performed.&nbsp; Thus, you can not pass an integer
+ where a string is expected, even though the reverse is true.</li>
+ <li>Any sequence object can be passed as an array.&nbsp; List objects are
+ always returned for arrays.</li>
+ <li>Any Python instance suitable for use as a XPCOM object (i.e., with the
+ <a href="#Implementing">necessary annotations</a>) can be
+ passed as a XPCOM object. No special wrapping step is needed to turn a
+ Python instance into a XPCOM object.&nbsp; Note you must pass a class <i>instance</i>,
+ not the class itself.</li>
+ <li><a name="HiddenParams">Many XPCOM <b> method signatures</b> specify
+ &quot;count&quot; or &quot;size&quot; parameters.&nbsp; For example, every
+ time an array is passed via XPCOM, the method signature will always specify
+ an integer that holds the count of the array.&nbsp; These parameters are
+ always hidden in Python.&nbsp; As the size param can be implied from the
+ length of the Python sequence passed, the Python programmer need never pass
+ these parameters;&nbsp;in contrast, JavaScript requires these redundant parameters.</a></li>
+</ul>
+
+<h2>Interface Flattening</h2>
+<p>Most people can ignore this information - Python XPCOM objects just
+work.&nbsp; However, if you are familiar with xpcom from C++ and the concept of <i>QueryInterface</i>,
+you may like to read this.</p>
+<p>Most components support the concept of &quot;interface
+flattening&quot;.&nbsp; Such objects can report the interfaces they support,
+allowing languages such as Python and Javascript avoid using <i>QueryInterface</i>.&nbsp;
+When you are using an XPCOM object from Python, you can just call methods and
+reference properties without regard for the interface that implements it.</p>
+<p>When multiple interfaces share the same method or property name, you can use
+the name of the interface as a differentiator.&nbsp; Thus, <i>ob.nsIFoo.close()</i>
+will call close on <i>ob</i>'s <i>nsIFoo</i> interface, while <i>ob.nsIBar.close()</i>
+will use the <i>nsIBar</i> interface.&nbsp; <i>ob.close()</i> is not defined.</p>
+
+</body>
+
+</html>
+
+
diff --git a/src/libs/xpcom18a4/python/file.py b/src/libs/xpcom18a4/python/file.py
new file mode 100755
index 00000000..59b0da58
--- /dev/null
+++ b/src/libs/xpcom18a4/python/file.py
@@ -0,0 +1,318 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 Python file objects for Mozilla/xpcom.
+
+Introduction:
+ This module defines various class that are implemented using
+ Mozilla streams. This allows you to open Mozilla URI's, and
+ treat them as Python file object.
+
+Example:
+>>> file = URIFile("chrome://whatever")
+>>> data = file.read(5) # Pass no arg to read everything.
+
+Known Limitations:
+ * Not all URL schemes will work from "python.exe" - most notably
+ "chrome://" and "http://" URLs - this is because a simple initialization of
+ xpcom by Python does not load up the full set of Mozilla URL handlers.
+ If you can work out how to correctly initialize the chrome registry and
+ setup a message queue.
+
+Known Bugs:
+ * Only read ("r") mode is supported. Although write ("w") mode doesnt make
+ sense for HTTP type URLs, it potentially does for file:// etc type ones.
+ * No concept of text mode vs binary mode. It appears Mozilla takes care of
+ this internally (ie, all "text/???" mime types are text, rest are binary)
+
+"""
+
+from xpcom import components, Exception, _xpcom
+import os
+import threading # for locks.
+
+NS_RDONLY = 0x01
+NS_WRONLY = 0x02
+NS_RDWR = 0x04
+NS_CREATE_FILE = 0x08
+NS_APPEND = 0x10
+NS_TRUNCATE = 0x20
+NS_SYNC = 0x40
+NS_EXCL = 0x80
+
+# A helper function that may come in useful
+def LocalFileToURL(localFileName):
+ "Convert a filename to an XPCOM nsIFileURL object."
+ # Create an nsILocalFile
+ localFile = components.classes["@mozilla.org/file/local;1"] \
+ .createInstance(components.interfaces.nsILocalFile)
+ localFile.initWithPath(localFileName)
+
+ # Use the IO Service to create the interface, then QI for a FileURL
+ io_service = components.classes["@mozilla.org/network/io-service;1"] \
+ .getService(components.interfaces.nsIIOService)
+ url = io_service.newFileURI(localFile).queryInterface(components.interfaces.nsIFileURL)
+ # Setting the "file" attribute causes initialization...
+ url.file = localFile
+ return url
+
+# A base class for file objects.
+class _File:
+ def __init__(self, name_thingy = None, mode="r"):
+ self.lockob = threading.Lock()
+ self.inputStream = self.outputStream = None
+ if name_thingy is not None:
+ self.init(name_thingy, mode)
+
+ def __del__(self):
+ self.close()
+
+ # The Moz file streams are not thread safe.
+ def _lock(self):
+ self.lockob.acquire()
+ def _release(self):
+ self.lockob.release()
+ def read(self, n = -1):
+ assert self.inputStream is not None, "Not setup for read!"
+ self._lock()
+ try:
+ return str(self.inputStream.read(n))
+ finally:
+ self._release()
+
+ def readlines(self):
+ # Not part of the xpcom interface, but handy for direct Python users.
+ # Not 100% faithful, but near enough for now!
+ lines = self.read().split("\n")
+ if len(lines) and len(lines[-1]) == 0:
+ lines = lines[:-1]
+ return [s+"\n" for s in lines ]
+
+ def write(self, data):
+ assert self.outputStream is not None, "Not setup for write!"
+ self._lock()
+ try:
+ self.outputStream.write(data, len(data))
+ finally:
+ self._release()
+
+ def close(self):
+ self._lock()
+ try:
+ if self.inputStream is not None:
+ self.inputStream.close()
+ self.inputStream = None
+ if self.outputStream is not None:
+ self.outputStream.close()
+ self.outputStream = None
+ self.channel = None
+ finally:
+ self._release()
+
+ def flush(self):
+ self._lock()
+ try:
+ if self.outputStream is not None: self.outputStream.flush()
+ finally:
+ self._release()
+
+# A synchronous "file object" used to open a URI.
+class URIFile(_File):
+ def init(self, url, mode="r"):
+ self.close()
+ if mode != "r":
+ raise ValueError("only 'r' mode supported")
+ io_service = components.classes["@mozilla.org/network/io-service;1"] \
+ .getService(components.interfaces.nsIIOService)
+ if hasattr(url, "queryInterface"):
+ url_ob = url
+ else:
+ url_ob = io_service.newURI(url, None, None)
+ # Mozilla asserts and starts saying "NULL POINTER" if this is wrong!
+ if not url_ob.scheme:
+ raise ValueError("The URI '%s' is invalid (no scheme)"
+ % (url_ob.spec,))
+ self.channel = io_service.newChannelFromURI(url_ob)
+ self.inputStream = self.channel.open()
+
+# A "file object" implemented using Netscape's native file support.
+# Based on io.js - http://lxr.mozilla.org/seamonkey/source/xpcom/tests/utils/io.js
+# You open this file using a local file name (as a string) so it really is pointless -
+# you may as well be using a standard Python file object!
+class LocalFile(_File):
+ def __init__(self, *args):
+ self.fileIO = None
+ _File.__init__(self, *args)
+
+ def init(self, name, mode = "r"):
+ name = os.path.abspath(name) # Moz libraries under Linux fail with relative paths.
+ self.close()
+ file = components.classes['@mozilla.org/file/local;1'].createInstance("nsILocalFile")
+ file.initWithPath(name)
+ if mode in ["w","a"]:
+ self.fileIO = components.classes["@mozilla.org/network/file-output-stream;1"].createInstance("nsIFileOutputStream")
+ if mode== "w":
+ if file.exists():
+ file.remove(0)
+ moz_mode = NS_CREATE_FILE | NS_WRONLY
+ elif mode=="a":
+ moz_mode = NS_APPEND
+ else:
+ assert 0, "Can't happen!"
+ self.fileIO.init(file, moz_mode, -1,0)
+ self.outputStream = self.fileIO
+ elif mode == "r":
+ self.fileIO = components.classes["@mozilla.org/network/file-input-stream;1"].createInstance("nsIFileInputStream")
+ self.fileIO.init(file, NS_RDONLY, -1,0)
+ self.inputStream = components.classes["@mozilla.org/scriptableinputstream;1"].createInstance("nsIScriptableInputStream")
+ self.inputStream.init(self.fileIO)
+ else:
+ raise ValueError("Unknown mode")
+
+ def close(self):
+ if self.fileIO is not None:
+ self.fileIO.close()
+ self.fileIO = None
+ _File.close(self)
+
+ def read(self, n = -1):
+ return _File.read(self, n)
+
+
+##########################################################
+##
+## Test Code
+##
+##########################################################
+def _DoTestRead(file, expected):
+ # read in a couple of chunks, just to test that our various arg combinations work.
+ got = file.read(3)
+ got = got + file.read(300)
+ got = got + file.read(0)
+ got = got + file.read()
+ if got != expected:
+ raise RuntimeError("Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected)))
+
+def _DoTestBufferRead(file, expected):
+ # read in a couple of chunks, just to test that our various arg combinations work.
+ buffer = _xpcom.AllocateBuffer(50)
+ got = ''
+ while 1:
+ # Note - we need to reach into the file object so we
+ # can get at the native buffer supported function.
+ num = file.inputStream.read(buffer)
+ if num == 0:
+ break
+ got = got + str(buffer[:num])
+ if got != expected:
+ raise RuntimeError("Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected)))
+
+def _TestLocalFile():
+ import tempfile, os
+ fname = tempfile.mktemp()
+ data = "Hello from Python"
+ test_file = LocalFile(fname, "w")
+ try:
+ test_file.write(data)
+ test_file.close()
+ # Make sure Python can read it OK.
+ f = open(fname, "r")
+ assert f.read() == data, "Eeek - Python could not read the data back correctly!"
+ f.close()
+ # For the sake of the test, try a re-init.
+ test_file.init(fname, "r")
+ got = str(test_file.read())
+ assert got == data, got
+ test_file.close()
+ # Try reading in chunks.
+ test_file = LocalFile(fname, "r")
+ got = test_file.read(10) + test_file.read()
+ assert got == data, got
+ test_file.close()
+ # Open the same file again for writing - this should delete the old one.
+ if not os.path.isfile(fname):
+ raise RuntimeError("The file '%s' does not exist, but we are explicitly testing create semantics when it does" % (fname,))
+ test_file = LocalFile(fname, "w")
+ test_file.write(data)
+ test_file.close()
+ # Make sure Python can read it OK.
+ f = open(fname, "r")
+ assert f.read() == data, "Eeek - Python could not read the data back correctly after recreating an existing file!"
+ f.close()
+
+ # XXX - todo - test "a" mode!
+ finally:
+ os.unlink(fname)
+
+def _TestAll():
+ # A mini test suite.
+ # Get a test file, and convert it to a file:// URI.
+ # check what we read is the same as when
+ # we read this file "normally"
+ fname = components.__file__
+ if fname[-1] in "cCoO": # fix .pyc/.pyo
+ fname = fname[:-1]
+ expected = open(fname, "rb").read()
+ # convert the fname to a URI.
+ url = LocalFileToURL(fname)
+ # First try passing a URL as a string.
+ _DoTestRead( URIFile( url.spec), expected)
+ # Now with a URL object.
+ _DoTestRead( URIFile( url ), expected)
+
+ _DoTestBufferRead( URIFile( url ), expected)
+
+ # For the sake of testing, do our pointless, demo object!
+ _DoTestRead( LocalFile(fname), expected )
+
+ # Now do the full test of our pointless, demo object!
+ _TestLocalFile()
+
+def _TestURI(url):
+ test_file = URIFile(url)
+ print("Opened file is", test_file)
+ got = test_file.read()
+ print("Read %d bytes of data from %r" % (len(got), url))
+ test_file.close()
+
+if __name__=='__main__':
+ import sys
+ if len(sys.argv) < 2:
+ print("No URL specified on command line - performing self-test")
+ _TestAll()
+ else:
+ _TestURI(sys.argv[1])
diff --git a/src/libs/xpcom18a4/python/gen_python_deps.py b/src/libs/xpcom18a4/python/gen_python_deps.py
new file mode 100755
index 00000000..81de3bed
--- /dev/null
+++ b/src/libs/xpcom18a4/python/gen_python_deps.py
@@ -0,0 +1,147 @@
+#!/usr/bin/python
+
+"""
+Copyright (C) 2009-2023 Oracle and/or its affiliates.
+
+This file is part of VirtualBox base platform packages, as
+available from https://www.virtualbox.org.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation, in version 3 of the
+License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses>.
+
+SPDX-License-Identifier: GPL-3.0-only
+"""
+
+from __future__ import print_function
+import os,sys
+from distutils.version import StrictVersion
+
+versions = ["2.6", "2.7", "3.1", "3.2", "3.2m", "3.3", "3.3m", "3.4", "3.4m", "3.5", "3.5m", "3.6", "3.6m", "3.7", "3.7m", "3.8", "3.9", "3.10", "3.11", "3.12" ]
+prefixes = ["/usr", "/usr/local", "/opt", "/opt/local"]
+known = {}
+
+def checkPair(p, v, dllpre, dllsuff, bitness_magic):
+ incdir = os.path.join(p, "include", "python"+v)
+ incfile = os.path.join(incdir, "Python.h")
+ if not os.path.isfile(incfile):
+ return None
+
+ lib = os.path.join(p, "lib/i386-linux-gnu", dllpre+"python"+v+dllsuff)
+ if not os.path.isfile(lib):
+ lib = os.path.join(p, "lib", dllpre+"python"+v+dllsuff)
+ if not os.path.isfile(lib):
+ lib = None
+
+ if bitness_magic == 1:
+ lib64 = os.path.join(p, "lib", "64", dllpre+"python"+v+dllsuff)
+ if not os.path.isfile(lib64):
+ lib64 = None
+ elif bitness_magic == 2:
+ lib64 = os.path.join(p, "lib/x86_64-linux-gnu", dllpre+"python"+v+dllsuff)
+ if not os.path.isfile(lib64):
+ lib64 = os.path.join(p, "lib64", dllpre+"python"+v+dllsuff)
+ if not os.path.isfile(lib64):
+ lib64 = os.path.join(p, "lib", dllpre+"python"+v+dllsuff)
+ if not os.path.isfile(lib64):
+ lib64 = None
+ else:
+ lib64 = None
+
+ if lib is None and lib64 is None:
+ return None
+ else:
+ return [incdir, lib, lib64]
+
+def print_vars(vers, known, sep, bitness_magic):
+ print("VBOX_PYTHON%s_INC=%s%s" %(vers, known[0], sep))
+ if bitness_magic > 0:
+ if known[2]:
+ print("VBOX_PYTHON%s_LIB=%s%s" %(vers, known[2], sep))
+ if known[1]:
+ print("VBOX_PYTHON%s_LIB_X86=%s%s" %(vers, known[1], sep))
+ else:
+ print("VBOX_PYTHON%s_LIB=%s%s" %(vers, known[1], sep))
+
+
+def main(argv):
+ global prefixes
+ global versions
+
+ dllpre = "lib"
+ dllsuff = ".so"
+ bitness_magic = 0
+
+ if len(argv) > 1:
+ target = argv[1]
+ else:
+ target = sys.platform
+
+ if len(argv) > 2:
+ arch = argv[2]
+ else:
+ arch = "unknown"
+
+ if len(argv) > 3:
+ multi = int(argv[3])
+ else:
+ multi = 1
+
+ if multi == 0:
+ prefixes = ["/usr"]
+ versions = [str(sys.version_info[0])+'.'+str(sys.version_info[1]),
+ str(sys.version_info[0])+'.'+str(sys.version_info[1])+'m']
+
+ if target == 'darwin':
+ ## @todo Pick up the locations from VBOX_PATH_MACOSX_SDK_10_*.
+ prefixes = ['/Developer/SDKs/MacOSX10.4u.sdk/usr',
+ '/Developer/SDKs/MacOSX10.5.sdk/usr',
+ '/Developer/SDKs/MacOSX10.6.sdk/usr',
+ '/Developer/SDKs/MacOSX10.7.sdk/usr']
+ dllsuff = '.dylib'
+
+ if target == 'solaris' and arch == 'amd64':
+ bitness_magic = 1
+
+ if target == 'linux' and arch == 'amd64':
+ bitness_magic = 2
+
+ for v in versions:
+ if v.endswith("m"):
+ realversion = v[:-1]
+ else:
+ realversion = v
+ if StrictVersion(realversion) < StrictVersion('2.6'):
+ continue
+ for p in prefixes:
+ c = checkPair(p, v, dllpre, dllsuff, bitness_magic)
+ if c is not None:
+ known[v] = c
+ break
+ keys = list(known.keys())
+ # we want default to be the lowest versioned Python
+ keys.sort()
+ d = None
+ # We need separator other than newline, to sneak through $(shell)
+ sep = "|"
+ for k in keys:
+ if d is None:
+ d = k
+ vers = k.replace('.', '').upper()
+ print_vars(vers, known[k], sep, bitness_magic)
+ if d is not None:
+ print_vars("DEF", known[d], sep, bitness_magic)
+ else:
+ print(argv[0] + ": No Python development package found!", file=sys.stderr)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/src/libs/xpcom18a4/python/nsError.py b/src/libs/xpcom18a4/python/nsError.py
new file mode 100755
index 00000000..af9cdbfd
--- /dev/null
+++ b/src/libs/xpcom18a4/python/nsError.py
@@ -0,0 +1,166 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is ActiveState Tool Corp.
+# Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001
+# ActiveState Tool Corp. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+# Generated by h2py from nsError.h
+# CMD line: h2py.py -i (nsresult) nsError.h
+
+# XXX - NOTE - some manual code at the end, and all literals moved back to ints
+NS_ERROR_MODULE_XPCOM = 1
+NS_ERROR_MODULE_BASE = 2
+NS_ERROR_MODULE_GFX = 3
+NS_ERROR_MODULE_WIDGET = 4
+NS_ERROR_MODULE_CALENDAR = 5
+NS_ERROR_MODULE_NETWORK = 6
+NS_ERROR_MODULE_PLUGINS = 7
+NS_ERROR_MODULE_LAYOUT = 8
+NS_ERROR_MODULE_HTMLPARSER = 9
+NS_ERROR_MODULE_RDF = 10
+NS_ERROR_MODULE_UCONV = 11
+NS_ERROR_MODULE_REG = 12
+NS_ERROR_MODULE_FILES = 13
+NS_ERROR_MODULE_DOM = 14
+NS_ERROR_MODULE_IMGLIB = 15
+NS_ERROR_MODULE_MAILNEWS = 16
+NS_ERROR_MODULE_EDITOR = 17
+NS_ERROR_MODULE_XPCONNECT = 18
+NS_ERROR_MODULE_PROFILE = 19
+NS_ERROR_MODULE_LDAP = 20
+NS_ERROR_MODULE_SECURITY = 21
+NS_ERROR_MODULE_DOM_XPATH = 22
+NS_ERROR_MODULE_DOM_RANGE = 23
+NS_ERROR_MODULE_URILOADER = 24
+NS_ERROR_MODULE_CONTENT = 25
+NS_ERROR_MODULE_PYXPCOM = 26
+NS_ERROR_MODULE_XSLT = 27
+NS_ERROR_MODULE_IPC = 28
+NS_ERROR_MODULE_SVG = 29
+NS_ERROR_MODULE_GENERAL = 51
+
+def NS_FAILED(_nsresult): return ((_nsresult) & -2147483648)
+
+NS_ERROR_SEVERITY_SUCCESS = 0
+NS_ERROR_SEVERITY_ERROR = 1
+NS_ERROR_MODULE_BASE_OFFSET = 69
+def NS_ERROR_GET_CODE(err): return ((err) & 65535)
+
+def NS_ERROR_GET_MODULE(err): return (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 8191))
+
+def NS_ERROR_GET_SEVERITY(err): return (((err) >> 31) & 1)
+
+NS_OK = 0
+NS_COMFALSE = 1
+NS_ERROR_BASE = ( -1041039360)
+NS_ERROR_NOT_INITIALIZED = (NS_ERROR_BASE + 1)
+NS_ERROR_ALREADY_INITIALIZED = (NS_ERROR_BASE + 2)
+NS_ERROR_NOT_IMPLEMENTED = ( -2147467263)
+NS_NOINTERFACE = ( -2147467262)
+NS_ERROR_NO_INTERFACE = NS_NOINTERFACE
+NS_ERROR_INVALID_POINTER = ( -2147467261)
+NS_ERROR_NULL_POINTER = NS_ERROR_INVALID_POINTER
+NS_ERROR_ABORT = ( -2147467260)
+NS_ERROR_FAILURE = ( -2147467259)
+NS_ERROR_UNEXPECTED = ( -2147418113)
+NS_ERROR_OUT_OF_MEMORY = ( -2147024882)
+NS_ERROR_ILLEGAL_VALUE = ( -2147024809)
+NS_ERROR_INVALID_ARG = NS_ERROR_ILLEGAL_VALUE
+NS_ERROR_NO_AGGREGATION = ( -2147221232)
+NS_ERROR_NOT_AVAILABLE = ( -2147221231)
+NS_ERROR_FACTORY_NOT_REGISTERED = ( -2147221164)
+NS_ERROR_FACTORY_REGISTER_AGAIN = ( -2147221163)
+NS_ERROR_FACTORY_NOT_LOADED = ( -2147221000)
+NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT = \
+ (NS_ERROR_BASE + 257)
+NS_ERROR_FACTORY_EXISTS = (NS_ERROR_BASE + 256)
+NS_ERROR_PROXY_INVALID_IN_PARAMETER = ( -2147418096)
+NS_ERROR_PROXY_INVALID_OUT_PARAMETER = ( -2147418095)
+
+##### END OF GENERATED CODE
+#####
+def NS_ERROR_GENERATE_FAILURE(module,code):
+ # slightly optimized, and avoids 2.3->2.4 long/int changes
+ # return (NS_ERROR_SEVERITY_ERROR<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+ return -2147483648 | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+
+def NS_ERROR_GENERATE_SUCCESS(module,code):
+ #return (NS_ERROR_SEVERITY_SUCCESS<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+ return ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
+
+NS_BASE_STREAM_CLOSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
+NS_BASE_STREAM_OSERROR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3)
+NS_BASE_STREAM_ILLEGAL_ARGS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4)
+NS_BASE_STREAM_NO_CONVERTER = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5)
+NS_BASE_STREAM_BAD_CONVERSION = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6)
+NS_BASE_STREAM_WOULD_BLOCK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7)
+NS_ERROR_FILE_UNRECOGNIZED_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1)
+NS_ERROR_FILE_UNRESOLVABLE_SYMLINK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2)
+NS_ERROR_FILE_EXECUTION_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3)
+NS_ERROR_FILE_UNKNOWN_TYPE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4)
+NS_ERROR_FILE_DESTINATION_NOT_DIR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5)
+NS_ERROR_FILE_TARGET_DOES_NOT_EXIST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6)
+NS_ERROR_FILE_COPY_OR_MOVE_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7)
+NS_ERROR_FILE_ALREADY_EXISTS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8)
+NS_ERROR_FILE_INVALID_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9)
+NS_ERROR_FILE_DISK_FULL = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10)
+NS_ERROR_FILE_CORRUPTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11)
+NS_ERROR_FILE_NOT_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12)
+NS_ERROR_FILE_IS_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13)
+NS_ERROR_FILE_IS_LOCKED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14)
+NS_ERROR_FILE_TOO_BIG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15)
+NS_ERROR_FILE_NO_DEVICE_SPACE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16)
+NS_ERROR_FILE_NAME_TOO_LONG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17)
+NS_ERROR_FILE_NOT_FOUND = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18)
+NS_ERROR_FILE_READ_ONLY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19)
+NS_ERROR_FILE_DIR_NOT_EMPTY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20)
+NS_ERROR_FILE_ACCESS_DENIED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21)
+
+## from netCore.h
+NS_ERROR_ALREADY_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 11)
+
+NS_ERROR_NOT_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 12)
+NS_ERROR_IN_PROGRESS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 15)
+NS_ERROR_OFFLINE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 16)
+
+## from nsISocketTransportService.idl
+NS_ERROR_CONNECTION_REFUSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 13)
+
+NS_ERROR_NET_TIMEOUT = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 14)
+
+# Status nsresult codes: used with nsIProgressEventSink::OnStatus
+NS_NET_STATUS_RESOLVING_HOST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 3)
+NS_NET_STATUS_CONNECTED_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 4)
+NS_NET_STATUS_SENDING_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 5)
+NS_NET_STATUS_RECEIVING_FROM = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 6)
+NS_NET_STATUS_CONNECTING_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 7)
diff --git a/src/libs/xpcom18a4/python/primitives.py b/src/libs/xpcom18a4/python/primitives.py
new file mode 100755
index 00000000..464f12e4
--- /dev/null
+++ b/src/libs/xpcom18a4/python/primitives.py
@@ -0,0 +1,39 @@
+# Various utilities for working with nsISupportsPrimitive
+from xpcom import components
+
+_primitives_map = {}
+
+def _build_map():
+ ifaces = components.interfaces
+ iface = ifaces.nsISupportsPrimitive
+ m = _primitives_map
+
+ m[iface.TYPE_ID] = ifaces.nsISupportsID
+ m[iface.TYPE_CSTRING] = ifaces.nsISupportsCString
+ m[iface.TYPE_STRING] = ifaces.nsISupportsString
+ m[iface.TYPE_PRBOOL] = ifaces.nsISupportsPRBool
+ m[iface.TYPE_PRUINT8] = ifaces.nsISupportsPRUint8
+ m[iface.TYPE_PRUINT16] = ifaces.nsISupportsPRUint16
+ m[iface.TYPE_PRUINT32] = ifaces.nsISupportsPRUint32
+ m[iface.TYPE_PRUINT64] = ifaces.nsISupportsPRUint64
+ m[iface.TYPE_PRINT16] = ifaces.nsISupportsPRInt16
+ m[iface.TYPE_PRINT32] = ifaces.nsISupportsPRInt32
+ m[iface.TYPE_PRINT64] = ifaces.nsISupportsPRInt64
+ m[iface.TYPE_PRTIME] = ifaces.nsISupportsPRTime
+ m[iface.TYPE_CHAR] = ifaces.nsISupportsChar
+ m[iface.TYPE_FLOAT] = ifaces.nsISupportsFloat
+ m[iface.TYPE_DOUBLE] = ifaces.nsISupportsDouble
+ # Do interface pointer specially - it provides the IID.
+ #m[iface.TYPE_INTERFACE_POINTER] = ifaces.nsISupportsDouble
+
+def GetPrimitive(ob):
+ if len(_primitives_map)==0:
+ _build_map()
+
+ prin = ob.QueryInterface(components.interfaces.nsISupportsPrimitive)
+ try:
+ better = _primitives_map[prin.type]
+ except KeyError:
+ raise ValueError("This primitive type (%d) is not supported" % (prin.type,))
+ prin = prin.QueryInterface(better)
+ return prin.data
diff --git a/src/libs/xpcom18a4/python/readme.html b/src/libs/xpcom18a4/python/readme.html
new file mode 100644
index 00000000..112f43e0
--- /dev/null
+++ b/src/libs/xpcom18a4/python/readme.html
@@ -0,0 +1,121 @@
+<html>
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Python XPCOM module</title>
+</head>
+
+<body>
+
+<h1>Python XPCOM Package</h1>
+
+<p>Mozilla CVS Version - Last updated May 2002</p>
+<p>This is the readme for the Python interface to <b>XPCOM</b>.</p>
+<p><b>XPCOM </b>is an acronym for &quot;Cross Platform COM&quot;.&nbsp; It has
+come out of the <a href="http://www.mozilla.org">Mozilla</a> project, which
+maintains the <a href="http://www.mozilla.org/projects/xpcom/">main XPCOM
+project pages.</a>&nbsp; The Python XPCOM package is a set of Python bindings to
+XPCOM, allowing a Python programmer to both use and implement XPCOM
+interfaces.&nbsp; If you don't know what <a href="http://www.python.org">Python</a>
+is, then none of this probably interests you at all!</p>
+<p>This readme has links to the following information:</p>
+<ul>
+ <li><a href="doc/configure.html">Building, Configuring and
+ Testing the Python
+ XPCOM Package</a></li>
+ <li><a href="doc/tutorial.html">A tutorial for the Python XPCOM package</a></li>
+ <li>Some <a href="doc/advanced.html">advanced
+ topics and other miscellaneous information</a></li>
+ <li><a href="doc/architecture.html">Information on the architecture</a></li>
+ <li>A list of the <a href="#KnownBugs">known issues and bugs</a>, the <a href="#ReleaseHistory">release
+ history</a> and the <a href="doc/credits.html">PyXPCOM acknowledgements</a></li>
+</ul>
+<p>Note: <b>This package requires Python 1.6 or later</b>; we recommend using
+the latest
+official Python version.&nbsp; This package works
+very well with the latest <a href="http://www.ActiveState.com/Products/ActivePython">ActivePython</a>,
+and does not require any external modules or packages beyond what is provided in
+the core Python release for each platform.</p>
+<h2>About the Python XPCOM Package</h2>
+<p>The Python XPCOM Package was developed by <a href="http://www.ActiveState.com">ActiveState
+Tool Corporation</a>, and came out of their <a href="http://www.ActiveState.com/Products/Komodo">Komodo
+project</a>.&nbsp; The Python XPCOM package is released under the <a href="http://www.mozilla.org/MPL/">Mozilla
+Public License (MPL)</a></p>
+<p>Please see the <a href="doc/credits.html">credits file</a> for a list of
+contributors. </p>
+<h2><a name="KnownBugs">Known Bugs</a>/Issues</h2>
+<ul>
+ <li>No attempt is made to recurse sub-directories of the main
+&quot;components&quot; directory.&nbsp; This is because we may decide on some
+smart scheme for recursion (similar to Python packages), and don't want people
+to rely on simple recursive searches.</li>
+ <li>No unregistration support at all.&nbsp;The main Python Component Loader supports
+ unregistration, but the actual Python objects themselves do not support unregistration.&nbsp;It is unclear if the Component Loader
+ unregistration process needs to manually remove each component it is responsible
+for.</li>
+ <li>All Python-implemented components unconditionally support
+weak-references.&nbsp; There is no way to disable this feature for any or all
+components.&nbsp; It is unclear if there is a need to prevent this, but it is
+documented here just in case!</li>
+</ul>
+<h2><a name="ReleaseHistory">Release History</a></h2>
+<h3>Version 0.90 - January 2001</h3>
+<ul>
+ <li>First public release.</li>
+</ul>
+<h3>Version 0.91 - January 2001</h3>
+<ul>
+ <li>Fix a seg fault on Linux when PYTHONPATH is not set.</li>
+ <li>Changes to allow building with stand-alone XPCOM.</li>
+</ul>
+
+<h3>Version 0.92 - May 2001</h3>
+<p>Implement interface flattening.&nbsp; You should (almost) never need to use <i>QueryInterface()</i>!&nbsp;
+We are still 100% backwards compatible, so usage of QI still works - just is
+generally not necessary.</p>
+
+<h3>Version 0.93 - May 2002</h3>
+
+<p>Implement <i>nsIVariant</i> and all new string types.&nbsp; Complete move to
+autoconf build system.</p>
+
+</body>
+
+</html>
diff --git a/src/libs/xpcom18a4/python/server/.cvsignore b/src/libs/xpcom18a4/python/server/.cvsignore
new file mode 100644
index 00000000..52e4e611
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/.cvsignore
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
diff --git a/src/libs/xpcom18a4/python/server/__init__.py b/src/libs/xpcom18a4/python/server/__init__.py
new file mode 100755
index 00000000..48b15106
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/__init__.py
@@ -0,0 +1,88 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# Activestate Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# The xpcom.server package.
+
+from xpcom.server.policy import DefaultPolicy
+from xpcom import _xpcom
+
+# We define the concept of a single "tracer" object - similar to the single
+# Python "trace hook" for debugging. Someone can set
+# xpcom.server.tracer to some class/function, and it will be used in place
+# of the real xpcom object. Presumably this "trace" object will delegate
+# to the real object, but presumably also taking some other action, such
+# as calling a profiler or debugger.
+# tracer_unwrap is a function used to "unwrap" the tracer object.
+# If is expected that tracer_unwrap will be called with an object
+# previously returned by "tracer()".
+tracer = tracer_unwrap = None
+
+# Wrap an instance in an interface (via a policy)
+def WrapObject(ob, iid, policy = None, bWrapClient = 1):
+ """Called by the framework to attempt to wrap
+ an object in a policy.
+ If iid is None, it will use the first interface the object indicates it supports.
+ """
+ if policy is None:
+ policy = DefaultPolicy
+ if tracer is not None:
+ ob = tracer(ob)
+ return _xpcom.WrapObject(policy( ob, iid ), iid, bWrapClient)
+
+# Unwrap a Python object back into the Python object
+def UnwrapObject(ob):
+ if ob is None:
+ return None
+ ret = _xpcom.UnwrapObject(ob)._obj_
+ if tracer_unwrap is not None:
+ ret = tracer_unwrap(ret)
+ return ret
+
+# Create the main module for the Python loader.
+# This is a once only init process, and the returned object
+# if used to load all other Python components.
+
+# This means that we keep all factories, modules etc implemented in
+# Python!
+def NS_GetModule( serviceManager, nsIFile ):
+ from . import loader
+ iid = _xpcom.IID_nsIModule
+ return WrapObject(loader.MakePythonComponentLoaderModule(serviceManager, nsIFile), iid, bWrapClient = 0)
+
+def _shutdown():
+ from xpcom.server.policy import _shutdown
+ _shutdown()
diff --git a/src/libs/xpcom18a4/python/server/enumerator.py b/src/libs/xpcom18a4/python/server/enumerator.py
new file mode 100755
index 00000000..d3fb89a9
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/enumerator.py
@@ -0,0 +1,58 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+from xpcom import components
+
+# This class is created by Python components when it
+# needs to return an enumerator.
+# For example, a component may implement a function:
+# nsISimpleEnumerator enumSomething();
+# This could could simply say:
+# return SimpleEnumerator([something1, something2, something3])
+class SimpleEnumerator:
+ _com_interfaces_ = [components.interfaces.nsISimpleEnumerator]
+
+ def __init__(self, data):
+ self._data = data
+ self._index = 0
+
+ def hasMoreElements(self):
+ return self._index < len(self._data)
+
+ def getNext(self):
+ self._index = self._index + 1
+ return self._data[self._index-1]
diff --git a/src/libs/xpcom18a4/python/server/factory.py b/src/libs/xpcom18a4/python/server/factory.py
new file mode 100755
index 00000000..b65483dd
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/factory.py
@@ -0,0 +1,68 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+# Class factory
+#
+# Hardly worth its own source file!
+import xpcom
+from xpcom import components, nsError, _xpcom, logger
+
+class Factory:
+ _com_interfaces_ = components.interfaces.nsIFactory
+ # This will only ever be constructed via other Python code,
+ # so we can have ctor args.
+ def __init__(self, klass):
+ self.klass = klass
+
+ def createInstance(self, outer, iid):
+ if outer is not None:
+ raise xpcom.ServerException(nsError.NS_ERROR_NO_AGGREGATION)
+
+ logger.debug("Python Factory creating %s", self.klass.__name__)
+ try:
+ return self.klass()
+ except:
+ # An exception here may not be obvious to the user - none
+ # of their code has been called yet. It can be handy on
+ # failure to tell the user what class failed!
+ logger.error("Creation of class '%r' failed!\nException details follow\n",
+ self.klass)
+ # The framework itself will also report the error.
+ raise
+
+ def lockServer(self, lock):
+ logger.debug("Python Factory LockServer called '%s'", lock)
diff --git a/src/libs/xpcom18a4/python/server/loader.py b/src/libs/xpcom18a4/python/server/loader.py
new file mode 100755
index 00000000..ebd42b61
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/loader.py
@@ -0,0 +1,227 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# Activestate Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either 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 *****
+
+import xpcom
+from xpcom import components, logger
+from . import module
+import glob
+import os
+from xpcom.client import Component
+
+# Until we get interface constants.
+When_Startup = 0
+When_Component = 1
+When_Timer = 2
+
+def _has_good_attr(object, attr):
+ # Actually allows "None" to be specified to disable inherited attributes.
+ return getattr(object, attr, None) is not None
+
+def FindCOMComponents(py_module):
+ # For now, just run over all classes looking for likely candidates.
+ comps = []
+ for name, object in list(py_module.__dict__.items()):
+ try:
+ if (type(object) == type or issubclass(object, object)) and \
+ _has_good_attr(object, "_com_interfaces_") and \
+ _has_good_attr(object, "_reg_clsid_") and \
+ _has_good_attr(object, "_reg_contractid_"):
+ comps.append(object)
+ except TypeError:
+ # The issubclass call raises TypeError when the obj is not a class.
+ pass;
+ return comps
+
+def register_self(klass, compMgr, location, registryLocation, componentType):
+ pcl = PythonComponentLoader
+ from xpcom import _xpcom
+ svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/categorymanager;1", components.interfaces.nsICategoryManager)
+ svc.addCategoryEntry("component-loader", pcl._reg_component_type_, pcl._reg_contractid_, 1, 1)
+
+class PythonComponentLoader:
+ _com_interfaces_ = components.interfaces.nsIComponentLoader
+ _reg_clsid_ = "{63B68B1E-3E62-45f0-98E3-5E0B5797970C}" # Never copy these!
+ _reg_contractid_ = "moz.pyloader.1"
+ _reg_desc_ = "Python component loader"
+ # Optional function which performs additional special registration
+ # Appears that no special unregistration is needed for ComponentLoaders, hence no unregister function.
+ _reg_registrar_ = (register_self,None)
+ # Custom attributes for ComponentLoader registration.
+ _reg_component_type_ = "script/python"
+
+ def __init__(self):
+ self.com_modules = {} # Keyed by module's FQN as obtained from nsIFile.path
+ self.moduleFactory = module.Module
+ self.num_modules_this_register = 0
+
+ def _getCOMModuleForLocation(self, componentFile):
+ fqn = componentFile.path
+ mod = self.com_modules.get(fqn)
+ if mod is not None:
+ return mod
+ import ihooks, sys
+ base_name = os.path.splitext(os.path.basename(fqn))[0]
+ loader = ihooks.ModuleLoader()
+
+ module_name_in_sys = "component:%s" % (base_name,)
+ stuff = loader.find_module(base_name, [componentFile.parent.path])
+ assert stuff is not None, "Couldnt find the module '%s'" % (base_name,)
+ py_mod = loader.load_module( module_name_in_sys, stuff )
+
+ # Make and remember the COM module.
+ comps = FindCOMComponents(py_mod)
+ mod = self.moduleFactory(comps)
+
+ self.com_modules[fqn] = mod
+ return mod
+
+ def getFactory(self, clsid, location, type):
+ # return the factory
+ assert type == self._reg_component_type_, "Being asked to create an object not of my type:%s" % (type,)
+ # FIXME: how to do this without obsolete component manager?
+ cmo = components.manager.queryInterface(components.interfaces.nsIComponentManagerObsolete)
+ file_interface = cmo.specForRegistryLocation(location)
+ # delegate to the module.
+ m = self._getCOMModuleForLocation(file_interface)
+ return m.getClassObject(components.manager, clsid, components.interfaces.nsIFactory)
+
+ def init(self, comp_mgr, registry):
+ # void
+ self.comp_mgr = comp_mgr
+ logger.debug("Python component loader init() called")
+
+ # Called when a component of the appropriate type is registered,
+ # to give the component loader an opportunity to do things like
+ # annotate the registry and such.
+ def onRegister (self, clsid, type, className, proId, location, replace, persist):
+ logger.debug("Python component loader - onRegister() called")
+
+ def autoRegisterComponents (self, when, directory):
+ directory_path = directory.path
+ self.num_modules_this_register = 0
+ logger.debug("Auto-registering all Python components in '%s'", directory_path)
+
+ # ToDo - work out the right thing here
+ # eg - do we recurse?
+ # - do we support packages?
+ entries = directory.directoryEntries
+ while entries.HasMoreElements():
+ entry = entries.GetNext(components.interfaces.nsIFile)
+ if os.path.splitext(entry.path)[1]==".py":
+ try:
+ self.autoRegisterComponent(when, entry)
+ # Handle some common user errors
+ except xpcom.COMException as details:
+ from xpcom import nsError
+ # If the interface name does not exist, suppress the traceback
+ if details.errno==nsError.NS_ERROR_NO_INTERFACE:
+ logger.error("Registration of '%s' failed\n %s",
+ entry.leafName, details.message)
+ else:
+ logger.exception("Registration of '%s' failed!", entry.leafName)
+ except SyntaxError as details:
+ # Syntax error in source file - no useful traceback here either.
+ logger.error("Registration of '%s' failed\n %s",
+ entry.leafName, details)
+ except:
+ # All other exceptions get the full traceback.
+ logger.exception("Registration of '%s' failed.", entry.leafName)
+
+ def autoRegisterComponent (self, when, componentFile):
+ # bool return
+
+ # Check if we actually need to do anything
+ modtime = componentFile.lastModifiedTime
+ loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
+ if not loader_mgr.hasFileChanged(componentFile, None, modtime):
+ return 1
+
+ if self.num_modules_this_register == 0:
+ # New components may have just installed new Python
+ # modules into the main python directory (including new .pth files)
+ # So we ask Python to re-process our site directory.
+ # Note that the pyloader does the equivalent when loading.
+ try:
+ from xpcom import _xpcom
+ import site
+ NS_XPCOM_CURRENT_PROCESS_DIR="XCurProcD"
+ dirname = _xpcom.GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR)
+ dirname.append("python")
+ site.addsitedir(dirname.path)
+ except:
+ logger.exception("PyXPCOM loader failed to process site directory before component registration")
+
+ self.num_modules_this_register += 1
+
+ # auto-register via the module.
+ m = self._getCOMModuleForLocation(componentFile)
+ m.registerSelf(components.manager, componentFile, None, self._reg_component_type_)
+ loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
+ loader_mgr.saveFileInfo(componentFile, None, modtime)
+ return 1
+
+ def autoUnregisterComponent (self, when, componentFile):
+ # bool return
+ # auto-unregister via the module.
+ m = self._getCOMModuleForLocation(componentFile)
+ loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
+ try:
+ m.unregisterSelf(components.manager, componentFile)
+ finally:
+ loader_mgr.removeFileInfo(componentFile, None)
+ return 1
+
+ def registerDeferredComponents (self, when):
+ # bool return
+ logger.debug("Python component loader - registerDeferred() called")
+ return 0 # no more to register
+
+ def unloadAll (self, when):
+ # This is called at shutdown time - don't get too upset if an error
+ # results from logging due to the logfile being closed
+ try:
+ logger.debug("Python component loader being asked to unload all components!")
+ except:
+ # Evil blank except, but restricting to just catching IOError
+ # failure means custom logs could still screw us
+ pass
+ self.comp_mgr = None
+ self.com_modules = {}
+
+def MakePythonComponentLoaderModule(serviceManager, nsIFile):
+ from . import module
+ return module.Module( [PythonComponentLoader] )
diff --git a/src/libs/xpcom18a4/python/server/module.py b/src/libs/xpcom18a4/python/server/module.py
new file mode 100755
index 00000000..73024e95
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/module.py
@@ -0,0 +1,108 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is ActiveState Tool Corp.
+# Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001
+# ActiveState Tool Corp. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+from xpcom import components
+from xpcom import ServerException, Exception
+from xpcom import nsError
+
+from . import factory
+
+import types
+import os
+
+class Module:
+ _com_interfaces_ = components.interfaces.nsIModule
+ def __init__(self, comps):
+ # Build a map of classes we can provide factories for.
+ c = self.components = {}
+ for klass in comps:
+ c[components.ID(klass._reg_clsid_)] = klass
+ self.klassFactory = factory.Factory
+
+ def getClassObject(self, compMgr, clsid, iid):
+ # Single retval result.
+ try:
+ klass = self.components[clsid]
+ except KeyError:
+ raise ServerException(nsError.NS_ERROR_FACTORY_NOT_REGISTERED)
+
+ # We can ignore the IID - the auto-wrap process will automatically QI us.
+ return self.klassFactory(klass)
+
+ def registerSelf(self, compMgr, location, loaderStr, componentType):
+ # void function.
+ fname = os.path.basename(location.path)
+ for klass in list(self.components.values()):
+ reg_contractid = klass._reg_contractid_
+ print("Registering '%s' (%s)" % (reg_contractid, fname))
+ reg_desc = getattr(klass, "_reg_desc_", reg_contractid)
+ compMgr = compMgr.queryInterface(components.interfaces.nsIComponentRegistrar)
+ compMgr.registerFactoryLocation(klass._reg_clsid_,
+ reg_desc,
+ reg_contractid,
+ location,
+ loaderStr,
+ componentType)
+
+ # See if this class nominates custom register_self
+ extra_func = getattr(klass, "_reg_registrar_", (None,None))[0]
+ if extra_func is not None:
+ extra_func(klass, compMgr, location, loaderStr, componentType)
+
+ def unregisterSelf(self, compMgr, location, loaderStr):
+ # void function.
+ for klass in list(self.components.values()):
+ ok = 1
+ try:
+ compMgr.unregisterComponentSpec(klass._reg_clsid_, location)
+ except Exception:
+ ok = 0
+ # Give the class a bash even if we failed!
+ extra_func = getattr(klass, "_reg_registrar_", (None,None))[1]
+ if extra_func is not None:
+ try:
+ extra_func(klass, compMgr, location, loaderStr)
+ except Exception:
+ ok = 0
+ if ok:
+ print("Successfully unregistered", klass.__name__)
+ else:
+ print("Unregistration of", klass.__name__, "failed. (probably just not already registered)")
+
+ def canUnload(self, compMgr):
+ # single bool result
+ return 0 # we can never unload!
+
diff --git a/src/libs/xpcom18a4/python/server/policy.py b/src/libs/xpcom18a4/python/server/policy.py
new file mode 100755
index 00000000..7f84167c
--- /dev/null
+++ b/src/libs/xpcom18a4/python/server/policy.py
@@ -0,0 +1,398 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <mhammond@skippinet.com.au> (original author)
+#
+# 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 *****
+
+from xpcom import xpcom_consts, _xpcom, client, nsError, logger
+from xpcom import ServerException, COMException
+import xpcom
+import xpcom.server
+import operator
+import types
+import logging
+import sys
+
+# Python 3 hacks:
+if sys.version_info[0] >= 3:
+ long = int # pylint: disable=W0622,C0103
+
+
+IID_nsISupports = _xpcom.IID_nsISupports
+IID_nsIVariant = _xpcom.IID_nsIVariant
+XPT_MD_IS_GETTER = xpcom_consts.XPT_MD_IS_GETTER
+XPT_MD_IS_SETTER = xpcom_consts.XPT_MD_IS_SETTER
+
+VARIANT_INT_TYPES = xpcom_consts.VTYPE_INT8, xpcom_consts.VTYPE_INT16, xpcom_consts.VTYPE_INT32, \
+ xpcom_consts.VTYPE_UINT8, xpcom_consts.VTYPE_UINT16, xpcom_consts.VTYPE_INT32
+VARIANT_LONG_TYPES = xpcom_consts.VTYPE_INT64, xpcom_consts.VTYPE_UINT64
+VARIANT_FLOAT_TYPES = xpcom_consts.VTYPE_FLOAT, xpcom_consts.VTYPE_DOUBLE
+VARIANT_STRING_TYPES = xpcom_consts.VTYPE_CHAR, xpcom_consts.VTYPE_CHAR_STR, xpcom_consts.VTYPE_STRING_SIZE_IS, \
+ xpcom_consts.VTYPE_CSTRING
+VARIANT_UNICODE_TYPES = xpcom_consts.VTYPE_WCHAR, xpcom_consts.VTYPE_DOMSTRING, xpcom_consts.VTYPE_WSTRING_SIZE_IS, \
+ xpcom_consts.VTYPE_ASTRING
+
+_supports_primitives_map_ = {} # Filled on first use.
+
+_interface_sequence_types_ = tuple, list
+if sys.version_info[0] <= 2:
+ _string_types_ = str, unicode
+else:
+ _string_types_ = bytes, str
+XPTI_GetInterfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager
+
+def _GetNominatedInterfaces(obj):
+ ret = getattr(obj, "_com_interfaces_", None)
+ if ret is None: return None
+ # See if the user only gave one.
+ if type(ret) not in _interface_sequence_types_:
+ ret = [ret]
+ real_ret = []
+ # For each interface, walk to the root of the interface tree.
+ iim = XPTI_GetInterfaceInfoManager()
+ for interface in ret:
+ # Allow interface name or IID.
+ interface_info = None
+ if type(interface) in _string_types_:
+ try:
+ interface_info = iim.GetInfoForName(interface)
+ except COMException:
+ pass
+ if interface_info is None:
+ # Allow a real IID
+ interface_info = iim.GetInfoForIID(interface)
+ real_ret.append(interface_info.GetIID())
+ parent = interface_info.GetParent()
+ while parent is not None:
+ parent_iid = parent.GetIID()
+ if parent_iid == IID_nsISupports:
+ break
+ real_ret.append(parent_iid)
+ parent = parent.GetParent()
+ return real_ret
+
+##
+## ClassInfo support
+##
+## We cache class infos by class
+class_info_cache = {}
+
+def GetClassInfoForObject(ob):
+ if xpcom.server.tracer_unwrap is not None:
+ ob = xpcom.server.tracer_unwrap(ob)
+ klass = ob.__class__
+ ci = class_info_cache.get(klass)
+ if ci is None:
+ ci = DefaultClassInfo(klass)
+ ci = xpcom.server.WrapObject(ci, _xpcom.IID_nsIClassInfo, bWrapClient = 0)
+ class_info_cache[klass] = ci
+ return ci
+
+class DefaultClassInfo:
+ _com_interfaces_ = _xpcom.IID_nsIClassInfo
+ def __init__(self, klass):
+ self.klass = klass
+ self.contractID = getattr(klass, "_reg_contractid_", None)
+ self.classDescription = getattr(klass, "_reg_desc_", None)
+ self.classID = getattr(klass, "_reg_clsid_", None)
+ self.implementationLanguage = 3 # Python - avoid lookups just for this
+ self.flags = 0 # what to do here??
+ self.interfaces = None
+
+ def get_classID(self):
+ if self.classID is None:
+ raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED, "Class '%r' has no class ID" % (self.klass,))
+ return self.classID
+
+ def getInterfaces(self):
+ if self.interfaces is None:
+ self.interfaces = _GetNominatedInterfaces(self.klass)
+ return self.interfaces
+
+ def getHelperForLanguage(self, language):
+ return None # Not sure what to do here.
+
+class DefaultPolicy:
+ def __init__(self, instance, iid):
+ self._obj_ = instance
+ self._nominated_interfaces_ = ni = _GetNominatedInterfaces(instance)
+ self._iid_ = iid
+ if ni is None:
+ raise ValueError("The object '%r' can not be used as a COM object" % (instance,))
+ # This is really only a check for the user
+ if __debug__:
+ if iid != IID_nsISupports and iid not in ni:
+ # The object may delegate QI.
+ delegate_qi = getattr(instance, "_query_interface_", None)
+ # Perform the actual QI and throw away the result - the _real_
+ # QI performed by the framework will set things right!
+ if delegate_qi is None or not delegate_qi(iid):
+ raise ServerException(nsError.NS_ERROR_NO_INTERFACE)
+ # Stuff for the magic interface conversion.
+ self._interface_info_ = None
+ self._interface_iid_map_ = {} # Cache - Indexed by (method_index, param_index)
+
+ def _QueryInterface_(self, com_object, iid):
+ # Framework allows us to return a single boolean integer,
+ # or a COM object.
+ if iid in self._nominated_interfaces_:
+ # We return the underlying object re-wrapped
+ # in a new gateway - which is desirable, as one gateway should only support
+ # one interface (this wont affect the users of this policy - we can have as many
+ # gateways as we like pointing to the same Python objects - the users never
+ # see what object the call came in from.
+ # NOTE: We could have simply returned the instance and let the framework
+ # do the auto-wrap for us - but this way we prevent a round-trip back into Python
+ # code just for the autowrap.
+ return xpcom.server.WrapObject(self._obj_, iid, bWrapClient = 0)
+
+ # Always support nsIClassInfo
+ if iid == _xpcom.IID_nsIClassInfo:
+ return GetClassInfoForObject(self._obj_)
+
+ # See if the instance has a QI
+ # use lower-case "_query_interface_" as win32com does, and it doesnt really matter.
+ delegate = getattr(self._obj_, "_query_interface_", None)
+ if delegate is not None:
+ # The COM object itself doesnt get passed to the child
+ # (again, as win32com doesnt). It is rarely needed
+ # (in win32com, we dont even pass it to the policy, although we have identified
+ # one place where we should - for marshalling - so I figured I may as well pass it
+ # to the policy layer here, but no all the way down to the object.
+ return delegate(iid)
+ # Finally see if we are being queried for one of the "nsISupports primitives"
+ if not _supports_primitives_map_:
+ iim = _xpcom.XPTI_GetInterfaceInfoManager()
+ for (iid_name, attr, cvt) in _supports_primitives_data_:
+ special_iid = iim.GetInfoForName(iid_name).GetIID()
+ _supports_primitives_map_[special_iid] = (attr, cvt)
+ attr, cvt = _supports_primitives_map_.get(iid, (None,None))
+ if attr is not None and hasattr(self._obj_, attr):
+ return xpcom.server.WrapObject(SupportsPrimitive(iid, self._obj_, attr, cvt), iid, bWrapClient = 0)
+ # Out of clever things to try!
+ return None # We dont support this IID.
+
+ def _MakeInterfaceParam_(self, interface, iid, method_index, mi, param_index):
+ # Wrap a "raw" interface object in a nice object. The result of this
+ # function will be passed to one of the gateway methods.
+ if iid is None:
+ # look up the interface info - this will be true for all xpcom called interfaces.
+ if self._interface_info_ is None:
+ import xpcom.xpt
+ self._interface_info_ = xpcom.xpt.Interface( self._iid_ )
+ iid = self._interface_iid_map_.get( (method_index, param_index))
+ if iid is None:
+ iid = self._interface_info_.GetIIDForParam(method_index, param_index)
+ self._interface_iid_map_[(method_index, param_index)] = iid
+ # handle nsIVariant
+ if iid == IID_nsIVariant:
+ interface = interface.QueryInterface(iid)
+ dt = interface.dataType
+ if dt in VARIANT_INT_TYPES:
+ return interface.getAsInt32()
+ if dt in VARIANT_LONG_TYPES:
+ return interface.getAsInt64()
+ if dt in VARIANT_FLOAT_TYPES:
+ return interface.getAsFloat()
+ if dt in VARIANT_STRING_TYPES:
+ return interface.getAsStringWithSize()
+ if dt in VARIANT_UNICODE_TYPES:
+ return interface.getAsWStringWithSize()
+ if dt == xpcom_consts.VTYPE_BOOL:
+ return interface.getAsBool()
+ if dt == xpcom_consts.VTYPE_INTERFACE:
+ return interface.getAsISupports()
+ if dt == xpcom_consts.VTYPE_INTERFACE_IS:
+ return interface.getAsInterface()
+ if dt == xpcom_consts.VTYPE_EMPTY or dt == xpcom_consts.VTYPE_VOID:
+ return None
+ if dt == xpcom_consts.VTYPE_ARRAY:
+ return interface.getAsArray()
+ if dt == xpcom_consts.VTYPE_EMPTY_ARRAY:
+ return []
+ if dt == xpcom_consts.VTYPE_ID:
+ return interface.getAsID()
+ # all else fails...
+ logger.warning("Warning: nsIVariant type %d not supported - returning a string", dt)
+ try:
+ return interface.getAsString()
+ except COMException:
+ logger.exception("Error: failed to get Variant as a string - returning variant object")
+ return interface
+
+ return client.Component(interface, iid)
+
+ def _CallMethod_(self, com_object, index, info, params):
+ #print "_CallMethod_", index, info, params
+ flags, name, param_descs, ret = info
+ assert ret[1][0] == xpcom_consts.TD_UINT32, "Expected an nsresult (%s)" % (ret,)
+ if XPT_MD_IS_GETTER(flags):
+ # Look for a function of that name
+ func = getattr(self._obj_, "get_" + name, None)
+ if func is None:
+ assert len(param_descs)==1 and len(params)==0, "Can only handle a single [out] arg for a default getter"
+ ret = getattr(self._obj_, name) # Let attribute error go here!
+ else:
+ ret = func(*params)
+ return 0, ret
+ elif XPT_MD_IS_SETTER(flags):
+ # Look for a function of that name
+ func = getattr(self._obj_, "set_" + name, None)
+ if func is None:
+ assert len(param_descs)==1 and len(params)==1, "Can only handle a single [in] arg for a default setter"
+ setattr(self._obj_, name, params[0]) # Let attribute error go here!
+ else:
+ func(*params)
+ return 0
+ else:
+ # A regular method.
+ func = getattr(self._obj_, name)
+ return 0, func(*params)
+
+ def _doHandleException(self, func_name, exc_info):
+ exc_val = exc_info[1]
+ is_server_exception = isinstance(exc_val, ServerException)
+ if is_server_exception:
+ # When a component raised an explicit COM exception, it is
+ # considered 'normal' - however, we still write a debug log
+ # record to help track these otherwise silent exceptions.
+
+ # Note that Python 2.3 does not allow an explicit exc_info tuple
+ # and passing 'True' will not work as there is no exception pending.
+ # Trick things!
+ if logger.isEnabledFor(logging.DEBUG):
+ try:
+ if sys.version_info[0] <= 2:
+ exec('raise exc_info[0], exc_info[1], exc_info[2]')
+ else:
+ raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
+ except:
+ logger.debug("'%s' raised COM Exception %s",
+ func_name, exc_val, exc_info = 1)
+ return exc_val.errno
+ # Unhandled exception - always print a warning and the traceback.
+ # As above, trick the logging module to handle Python 2.3
+ try:
+ if sys.version_info[0] <= 2:
+ exec('raise exc_info[0], exc_info[1], exc_info[2]')
+ else:
+ raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
+ except:
+ logger.exception("Unhandled exception calling '%s'", func_name)
+ return nsError.NS_ERROR_FAILURE
+
+ # Called whenever an unhandled Python exception is detected as a result
+ # of _CallMethod_ - this exception may have been raised during the _CallMethod_
+ # invocation, or after its return, but when unpacking the results
+ # eg, type errors, such as a Python integer being used as a string "out" param.
+ def _CallMethodException_(self, com_object, index, info, params, exc_info):
+ # Later we may want to have some smart "am I debugging" flags?
+ # Or maybe just delegate to the actual object - it's probably got the best
+ # idea what to do with them!
+ flags, name, param_descs, ret = info
+ exc_typ, exc_val, exc_tb = exc_info
+ # use the xpt module to get a better repr for the method.
+ # But if we fail, ignore it!
+ try:
+ import xpcom.xpt
+ m = xpcom.xpt.Method(info, index, None)
+ func_repr = m.Describe().lstrip()
+ except COMException:
+ func_repr = "%s(%r)" % (name, param_descs)
+ except:
+ # any other errors are evil!? Log it
+ self._doHandleException("<building method repr>", sys.exc_info())
+ # And fall through to logging the original error.
+ return self._doHandleException(func_repr, exc_info)
+
+ # Called whenever a gateway fails due to anything other than _CallMethod_.
+ # Really only used for the component loader etc objects, so most
+ # users should never see exceptions triggered here.
+ def _GatewayException_(self, name, exc_info):
+ return self._doHandleException(name, exc_info)
+
+if sys.version_info[0] <= 2:
+ _supports_primitives_data_ = [
+ ("nsISupportsCString", "__str__", str),
+ ("nsISupportsString", "__unicode__", unicode),
+ ("nsISupportsPRUint64", "__long__", long),
+ ("nsISupportsPRInt64", "__long__", long),
+ ("nsISupportsPRUint32", "__int__", int),
+ ("nsISupportsPRInt32", "__int__", int),
+ ("nsISupportsPRUint16", "__int__", int),
+ ("nsISupportsPRInt16", "__int__", int),
+ ("nsISupportsPRUint8", "__int__", int),
+ ("nsISupportsPRBool", "__nonzero__", operator.truth),
+ ("nsISupportsDouble", "__float__", float),
+ ("nsISupportsFloat", "__float__", float),
+ ]
+else:
+ _supports_primitives_data_ = [
+ ("nsISupportsCString", "__str__", str),
+ ("nsISupportsString", "__unicode__", str),
+ ("nsISupportsPRUint64", "__long__", int),
+ ("nsISupportsPRInt64", "__long__", int),
+ ("nsISupportsPRUint32", "__int__", int),
+ ("nsISupportsPRInt32", "__int__", int),
+ ("nsISupportsPRUint16", "__int__", int),
+ ("nsISupportsPRInt16", "__int__", int),
+ ("nsISupportsPRUint8", "__int__", int),
+ ("nsISupportsPRBool", "__nonzero__", operator.truth),
+ ("nsISupportsDouble", "__float__", float),
+ ("nsISupportsFloat", "__float__", float),
+ ]
+
+# Support for the nsISupports primitives:
+class SupportsPrimitive:
+ _com_interfaces_ = ["nsISupports"]
+ def __init__(self, iid, base_ob, attr_name, converter):
+ self.iid = iid
+ self.base_ob = base_ob
+ self.attr_name = attr_name
+ self.converter = converter
+ def _query_interface_(self, iid):
+ if iid == self.iid:
+ return 1
+ return None
+ def get_data(self):
+ method = getattr(self.base_ob, self.attr_name)
+ val = method()
+ return self.converter(val)
+ def set_data(self, val):
+ raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+ def toString(self):
+ return str(self.get_data())
+
+def _shutdown():
+ class_info_cache.clear()
diff --git a/src/libs/xpcom18a4/python/src/ErrorUtils.cpp b/src/libs/xpcom18a4/python/src/ErrorUtils.cpp
new file mode 100644
index 00000000..9400799b
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/ErrorUtils.cpp
@@ -0,0 +1,483 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsReadableUtils.h"
+#include <nsIConsoleService.h>
+#ifdef VBOX
+# include <nsIExceptionService.h>
+# include <iprt/err.h>
+# include <iprt/string.h>
+#endif
+#include "nspr.h" // PR_fprintf
+
+static char *PyTraceback_AsString(PyObject *exc_tb);
+
+// The internal helper that actually moves the
+// formatted string to the target!
+
+// Only used in really bad situations!
+static void _PanicErrorWrite(const char *msg)
+{
+ nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+ if (consoleService)
+ consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
+ PR_fprintf(PR_STDERR,"%s\n", msg);
+}
+
+// Called when our "normal" error logger fails.
+static void HandleLogError(const char *pszMessageText)
+{
+ nsCAutoString streamout;
+
+ _PanicErrorWrite("Failed to log an error record");
+ if (PyXPCOM_FormatCurrentException(streamout))
+ _PanicErrorWrite(streamout.get());
+ _PanicErrorWrite("Original error follows:");
+ _PanicErrorWrite(pszMessageText);
+}
+
+static const char *LOGGER_WARNING = "warning";
+static const char *LOGGER_ERROR = "error";
+static const char *LOGGER_DEBUG = "debug";
+
+// Our "normal" error logger - calls back to the logging module.
+void DoLogMessage(const char *methodName, const char *pszMessageText)
+{
+ // We use the logging module now. Originally this code called
+ // the logging module directly by way of the C API's
+ // PyImport_ImportModule/PyObject_CallMethod etc. However, this
+ // causes problems when there is no Python caller on the stack -
+ // the logging module's findCaller method fails with a None frame.
+ // We now work around this by calling PyRun_SimpleString - this
+ // causes a new frame to be created for executing the compiled
+ // string, and the logging module no longer fails.
+ // XXX - this implementation is less than ideal - findCaller now
+ // returns ("<string>", 2). Ideally we would compile with a
+ // filename something similar to "<pydom error reporter>".
+
+ // But this also means we need a clear error state...
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
+// We will execute:
+// import logging
+// logging.getLogger('xpcom').{warning/error/etc}("%s", {msg_text})
+ nsCAutoString c("import logging\nlogging.getLogger('xpcom').");
+ c += methodName;
+ c += "('%s', ";
+ // Pull a trick to ensure a valid string - use Python repr!
+#if PY_MAJOR_VERSION <= 2
+ PyObject *obMessage = PyString_FromString(pszMessageText);
+#else
+ PyObject *obMessage = PyUnicode_FromString(pszMessageText);
+#endif
+ if (obMessage) {
+ PyObject *repr = PyObject_Repr(obMessage);
+ if (repr) {
+#if PY_MAJOR_VERSION <= 2
+ c += PyString_AsString(repr);
+#else
+ c += PyUnicode_AsUTF8(repr);
+#endif
+ Py_DECREF(repr);
+ }
+ Py_DECREF(obMessage);
+ }
+ c += ")\n";
+ if (PyRun_SimpleString(c.get()) != 0) {
+ HandleLogError(pszMessageText);
+ }
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+}
+
+void LogMessage(const char *methodName, const char *pszMessageText)
+{
+ // Be careful to save and restore the Python exception state
+ // before calling back to Python, or we lose the original error.
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+ DoLogMessage(methodName, pszMessageText);
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+}
+
+
+void LogMessage(const char *methodName, nsACString &text)
+{
+ char *c = ToNewCString(text);
+ LogMessage(methodName, c);
+ nsCRT::free(c);
+}
+
+// A helper for the various logging routines.
+static void VLogF(const char *methodName, const char *fmt, va_list argptr)
+{
+ char buff[512];
+#ifdef VBOX /* Enable the use of VBox formatting types. */
+ RTStrPrintfV(buff, sizeof(buff), fmt, argptr);
+#else
+ // Use safer NS_ functions.
+ PR_vsnprintf(buff, sizeof(buff), fmt, argptr);
+#endif
+
+ LogMessage(methodName, buff);
+}
+
+PRBool PyXPCOM_FormatCurrentException(nsCString &streamout)
+{
+ PRBool ok = PR_FALSE;
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+ PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
+ if (exc_typ) {
+ ok = PyXPCOM_FormatGivenException(streamout, exc_typ, exc_val,
+ exc_tb);
+ }
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ return ok;
+}
+
+PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
+ PyObject *exc_typ, PyObject *exc_val,
+ PyObject *exc_tb)
+{
+ if (!exc_typ)
+ return PR_FALSE;
+ streamout += "\n";
+
+ if (exc_tb) {
+ const char *szTraceback = PyTraceback_AsString(exc_tb);
+ if (szTraceback == NULL)
+ streamout += "Can't get the traceback info!";
+ else {
+ streamout += "Traceback (most recent call last):\n";
+ streamout += szTraceback;
+ PyMem_Free((void *)szTraceback);
+ }
+ }
+ PyObject *temp = PyObject_Str(exc_typ);
+ if (temp) {
+#if PY_MAJOR_VERSION <= 2
+ streamout += PyString_AsString(temp);
+#else
+ streamout += PyUnicode_AsUTF8(temp);
+#endif
+ Py_DECREF(temp);
+ } else
+ streamout += "Can't convert exception to a string!";
+ streamout += ": ";
+ if (exc_val != NULL) {
+ temp = PyObject_Str(exc_val);
+ if (temp) {
+#if PY_MAJOR_VERSION <= 2
+ streamout += PyString_AsString(temp);
+#else
+ streamout += PyUnicode_AsUTF8(temp);
+#endif
+ Py_DECREF(temp);
+ } else
+ streamout += "Can't convert exception value to a string!";
+ }
+ return PR_TRUE;
+}
+
+void PyXPCOM_LogError(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ // NOTE: It is tricky to use logger.exception here - the exception
+ // state when called back from the C code is clear. Only Python 2.4
+ // and later allows an explicit exc_info tuple().
+
+ // Don't use VLogF here, instead arrange for exception info and
+ // traceback to be in the same buffer.
+ char buff[512];
+ PR_vsnprintf(buff, sizeof(buff), fmt, marker);
+ // If we have a Python exception, also log that:
+ nsCAutoString streamout(buff);
+ if (PyXPCOM_FormatCurrentException(streamout)) {
+ LogMessage(LOGGER_ERROR, streamout);
+ }
+ va_end(marker);
+}
+
+void PyXPCOM_LogWarning(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF(LOGGER_WARNING, fmt, marker);
+ va_end(marker);
+}
+
+void PyXPCOM_Log(const char *level, const nsCString &msg)
+{
+ DoLogMessage(level, msg.get());
+}
+
+#ifdef DEBUG
+void PyXPCOM_LogDebug(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF(LOGGER_DEBUG, fmt, marker);
+ va_end(marker);
+}
+#endif
+
+#ifdef VBOX
+PyObject *PyXPCOM_BuildErrorMessage(nsresult r)
+{
+ char msg[512];
+ bool gotMsg = false;
+
+ if (!gotMsg)
+ {
+ nsresult rc;
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
+ if (NS_SUCCEEDED (rc))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+ if (NS_SUCCEEDED (rc))
+ {
+ nsCOMPtr <nsIException> ex;
+ rc = em->GetExceptionFromProvider(r, NULL, getter_AddRefs (ex));
+ if (NS_SUCCEEDED (rc) && ex)
+ {
+ nsXPIDLCString emsg;
+ ex->GetMessage(getter_Copies(emsg));
+ PR_snprintf(msg, sizeof(msg), "%s",
+ emsg.get());
+ gotMsg = true;
+ }
+ }
+ }
+ }
+
+ if (!gotMsg)
+ {
+ const RTCOMERRMSG* pMsg = RTErrCOMGet(r);
+ if (strncmp(pMsg->pszMsgFull, "Unknown", 7) != 0)
+ {
+ PR_snprintf(msg, sizeof(msg), "%s (%s)",
+ pMsg->pszMsgFull, pMsg->pszDefine);
+ gotMsg = true;
+ }
+ }
+
+ if (!gotMsg)
+ {
+ PR_snprintf(msg, sizeof(msg), "Error 0x%x in module 0x%x",
+ NS_ERROR_GET_CODE(r), NS_ERROR_GET_MODULE(r));
+ }
+ PyObject *evalue = Py_BuildValue("is", r, msg);
+ return evalue;
+}
+#endif
+
+PyObject *PyXPCOM_BuildPyException(nsresult r)
+{
+#ifndef VBOX
+ // Need the message etc.
+ PyObject *evalue = Py_BuildValue("i", r);
+#else
+ PyObject *evalue = PyXPCOM_BuildErrorMessage(r);
+#endif
+ PyErr_SetObject(PyXPCOM_Error, evalue);
+ Py_XDECREF(evalue);
+ return NULL;
+}
+
+nsresult PyXPCOM_SetCOMErrorFromPyException()
+{
+ if (!PyErr_Occurred())
+ // No error occurred
+ return NS_OK;
+ nsresult rv = NS_ERROR_FAILURE;
+ if (PyErr_ExceptionMatches(PyExc_MemoryError))
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ // todo:
+ // * Set an exception using the exception service.
+
+ // Once we have returned to the xpcom caller, we don't want to leave a
+ // Python exception pending - it may get noticed when the next call
+ // is made on the same thread.
+ PyErr_Clear();
+ return rv;
+}
+
+/* Obtains a string from a Python traceback.
+ This is the exact same string as "traceback.print_exc" would return.
+
+ Pass in a Python traceback object (probably obtained from PyErr_Fetch())
+ Result is a string which must be free'd using PyMem_Free()
+*/
+#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
+
+char *PyTraceback_AsString(PyObject *exc_tb)
+{
+ const char *errMsg = NULL; /* holds a local error message */
+ char *result = NULL; /* a valid, allocated result. */
+ PyObject *modStringIO = NULL;
+ PyObject *modTB = NULL;
+ PyObject *obFuncStringIO = NULL;
+ PyObject *obStringIO = NULL;
+ PyObject *obFuncTB = NULL;
+ PyObject *argsTB = NULL;
+ PyObject *obResult = NULL;
+
+#if PY_MAJOR_VERSION <= 2
+ /* Import the modules we need - cStringIO and traceback */
+ modStringIO = PyImport_ImportModule("cStringIO");
+ if (modStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
+
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant import traceback\n");
+ /* Construct a cStringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
+#else
+ /* Import the modules we need - io and traceback */
+ modStringIO = PyImport_ImportModule("io");
+ if (modStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant import io\n");
+
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant import traceback\n");
+ /* Construct a StringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find io.StringIO\n");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("io.StringIO() failed\n");
+#endif
+ /* Get the traceback.print_exception function, and call it. */
+ obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
+ if (obFuncTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
+
+ argsTB = Py_BuildValue("OOO",
+ exc_tb ? exc_tb : Py_None,
+ Py_None,
+ obStringIO);
+ if (argsTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
+
+ obResult = PyObject_CallObject(obFuncTB, argsTB);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
+ /* Now call the getvalue() method in the StringIO instance */
+ Py_DECREF(obFuncStringIO);
+ obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
+ Py_DECREF(obResult);
+ obResult = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
+
+ /* And it should be a string all ready to go - duplicate it. */
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(obResult))
+#else
+ if (!PyUnicode_Check(obResult))
+#endif
+ TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
+
+ { // a temp scope so I can use temp locals.
+#if PY_MAJOR_VERSION <= 2
+ char *tempResult = PyString_AsString(obResult);
+#else
+ /* PyUnicode_AsUTF8() is const char * as of Python 3.7, char * earlier. */
+ const char *tempResult = (const char *)PyUnicode_AsUTF8(obResult);
+#endif
+ result = (char *)PyMem_Malloc(strlen(tempResult)+1);
+ if (result==NULL)
+ TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string\n");
+
+ strcpy(result, tempResult);
+ } // end of temp scope.
+done:
+ /* All finished - first see if we encountered an error */
+ if (result==NULL && errMsg != NULL) {
+ result = (char *)PyMem_Malloc(strlen(errMsg)+1);
+ if (result != NULL)
+ /* if it does, not much we can do! */
+ strcpy(result, errMsg);
+ }
+ Py_XDECREF(modStringIO);
+ Py_XDECREF(modTB);
+ Py_XDECREF(obFuncStringIO);
+ Py_XDECREF(obStringIO);
+ Py_XDECREF(obFuncTB);
+ Py_XDECREF(argsTB);
+ Py_XDECREF(obResult);
+ return result;
+}
+
+// See comments in PyXPCOM.h for why we need this!
+void PyXPCOM_MakePendingCalls()
+{
+ while (1) {
+ int rc = Py_MakePendingCalls();
+ if (rc == 0)
+ break;
+ // An exception - just report it as normal.
+ // Note that a traceback is very unlikely!
+ PyXPCOM_LogError("Unhandled exception detected before entering Python.\n");
+ PyErr_Clear();
+ // And loop around again until we are told everything is done!
+ }
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGBase.cpp b/src/libs/xpcom18a4/python/src/PyGBase.cpp
new file mode 100644
index 00000000..e73b2a6d
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGBase.cpp
@@ -0,0 +1,852 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// PyGBase.cpp - implementation of the PyG_Base class
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIModule.h>
+#include <nsIComponentLoader.h>
+#include <nsIInputStream.h>
+
+static PRInt32 cGateways = 0;
+PRInt32 _PyXPCOM_GetGatewayCount(void)
+{
+ return cGateways;
+}
+
+extern PyG_Base *MakePyG_nsIModule(PyObject *);
+extern PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance);
+extern PyG_Base *MakePyG_nsIInputStream(PyObject *instance);
+
+static char *PyXPCOM_szDefaultGatewayAttributeName = (char*)"_com_instance_default_gateway_";
+PyG_Base *GetDefaultGateway(PyObject *instance);
+void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
+PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway);
+
+/*static*/ nsresult
+PyG_Base::CreateNew(PyObject *pPyInstance, const nsIID &iid, void **ppResult)
+{
+ NS_PRECONDITION(ppResult && *ppResult==NULL, "NULL or uninitialized pointer");
+ if (ppResult==nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ PyG_Base *ret;
+ // Hack for few extra gateways we support.
+ if (iid.Equals(NS_GET_IID(nsIModule)))
+ ret = MakePyG_nsIModule(pPyInstance);
+ else if (iid.Equals(NS_GET_IID(nsIComponentLoader)))
+ ret = MakePyG_nsIComponentLoader(pPyInstance);
+ else if (iid.Equals(NS_GET_IID(nsIInputStream)))
+ ret = MakePyG_nsIInputStream(pPyInstance);
+ else
+ ret = new PyXPCOM_XPTStub(pPyInstance, iid);
+ if (ret==nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ ret->AddRef(); // The first reference for the caller.
+ *ppResult = ret->ThisAsIID(iid);
+ NS_ABORT_IF_FALSE(*ppResult != NULL, "ThisAsIID() gave NULL, but we know it supports it!");
+ return *ppResult ? NS_OK : NS_ERROR_FAILURE;
+}
+
+PyG_Base::PyG_Base(PyObject *instance, const nsIID &iid)
+{
+ // Note that "instance" is the _policy_ instance!!
+ PR_AtomicIncrement(&cGateways);
+ m_pBaseObject = GetDefaultGateway(instance);
+ // m_pWeakRef is an nsCOMPtr and needs no init.
+
+ NS_ABORT_IF_FALSE(!(iid.Equals(NS_GET_IID(nsISupportsWeakReference)) || iid.Equals(NS_GET_IID(nsIWeakReference))),"Should not be creating gateways with weak-ref interfaces");
+ m_iid = iid;
+ m_pPyObject = instance;
+ NS_PRECONDITION(instance, "NULL PyObject for PyXPCOM_XPTStub!");
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ // If XPCOM reference count logging is enabled, then allow us to give the Python class.
+ PyObject *realInstance = PyObject_GetAttrString(instance, "_obj_");
+ PyObject *r = PyObject_Repr(realInstance);
+ const char *szRepr;
+ if (r==NULL) {
+ PyXPCOM_LogError("Getting the __repr__ of the object failed");
+ PyErr_Clear();
+ szRepr = "(repr failed!)";
+ }
+ else
+#if PY_MAJOR_VERSION <= 2
+ szRepr = PyString_AsString(r);
+#else
+ szRepr = PyUnicode_AsUTF8(r);
+#endif
+ if (szRepr==NULL) szRepr = "";
+ int reprOffset = *szRepr=='<' ? 1 : 0;
+ static const char *reprPrefix = "component:";
+ if (strncmp(reprPrefix, szRepr+reprOffset, strlen(reprPrefix)) == 0)
+ reprOffset += strlen(reprPrefix);
+ strncpy(refcntLogRepr, szRepr + reprOffset, sizeof(refcntLogRepr)-1);
+ refcntLogRepr[sizeof(refcntLogRepr)-1] = '\0';
+ // See if we should get rid of the " at 0x12345" portion.
+ char *lastPos = strstr(refcntLogRepr, " at ");
+ if (lastPos) *lastPos = '\0';
+ Py_XDECREF(realInstance);
+ Py_XDECREF(r);
+#endif // NS_BUILD_REFCNT_LOGGING
+
+#ifdef DEBUG_LIFETIMES
+ {
+ char *iid_repr;
+ nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
+ if (iim!=nsnull)
+ iim->GetNameForIID(&iid, &iid_repr);
+ PyObject *real_instance = PyObject_GetAttrString(instance, "_obj_");
+ PyObject *real_repr = PyObject_Repr(real_instance);
+
+ PYXPCOM_LOG_DEBUG("PyG_Base created at %p\n instance_repr=%s\n IID=%s\n", this, PyString_AsString(real_repr), iid_repr);
+ nsMemory::Free(iid_repr);
+ Py_XDECREF(real_instance);
+ Py_XDECREF(real_repr);
+ }
+#endif // DEBUG_LIFETIMES
+ Py_XINCREF(instance); // instance should never be NULL - but whats an X between friends!
+
+ PyXPCOM_DLLAddRef();
+
+#ifdef DEBUG_FULL
+ LogF("PyGatewayBase: created %s", m_pPyObject ? PyXPCOM_ObTypeName(m_pPyObject) : "<NULL>");
+#endif
+}
+
+PyG_Base::~PyG_Base()
+{
+ PR_AtomicDecrement(&cGateways);
+#ifdef DEBUG_LIFETIMES
+ PYXPCOM_LOG_DEBUG("PyG_Base: deleted %p", this);
+#endif
+ if ( m_pPyObject ) {
+ CEnterLeavePython celp;
+ Py_DECREF(m_pPyObject);
+ }
+ if (m_pBaseObject)
+ m_pBaseObject->Release();
+ if (m_pWeakRef) {
+ // Need to ensure some other thread isnt doing a QueryReferent on
+ // our weak reference at the same time
+ CEnterLeaveXPCOMFramework _celf;
+ PyXPCOM_GatewayWeakReference *p = (PyXPCOM_GatewayWeakReference *)(nsISupports *)m_pWeakRef;
+ p->m_pBase = nsnull;
+ m_pWeakRef = nsnull;
+ }
+ PyXPCOM_DLLRelease();
+}
+
+// Get the correct interface pointer for this object given the IID.
+void *PyG_Base::ThisAsIID( const nsIID &iid )
+{
+ if (this==NULL) return NULL;
+ if (iid.Equals(NS_GET_IID(nsISupports)))
+ return (nsISupports *)(nsIInternalPython *)this;
+ if (iid.Equals(NS_GET_IID(nsISupportsWeakReference)))
+ return (nsISupportsWeakReference *)this;
+ if (iid.Equals(NS_GET_IID(nsIInternalPython)))
+ return (nsISupports *)(nsIInternalPython *)this;
+ return NULL;
+}
+
+// Call back into Python, passing a Python instance, and get back
+// an interface object that wraps the instance.
+/*static*/ PRBool
+PyG_Base::AutoWrapPythonInstance(PyObject *ob, const nsIID &iid, nsISupports **ppret)
+{
+ NS_PRECONDITION(ppret!=NULL, "null pointer when wrapping a Python instance!");
+ NS_PRECONDITION(ob && PyObject_HasAttrString(ob, "__class__"),
+ "AutoWrapPythonInstance is expecting an non-NULL instance!");
+ PRBool ok = PR_FALSE;
+ // XXX - todo - this static object leaks! (but Python on Windows leaks 2000+ objects as it is ;-)
+ static PyObject *func = NULL; // fetch this once and remember!
+ PyObject *obIID = NULL;
+ PyObject *wrap_ret = NULL;
+ PyObject *args = NULL;
+ if (func==NULL) { // not thread-safe, but nothing bad can happen, except an extra reference leak
+ PyObject *mod = PyImport_ImportModule("xpcom.server");
+ if (mod)
+ func = PyObject_GetAttrString(mod, "WrapObject");
+ Py_XDECREF(mod);
+ if (func==NULL) goto done;
+ }
+ // See if the instance has previously been wrapped.
+ if (CheckDefaultGateway(ob, iid, ppret)) {
+ ok = PR_TRUE; // life is good!
+ } else {
+ PyErr_Clear();
+
+ obIID = Py_nsIID::PyObjectFromIID(iid);
+ if (obIID==NULL) goto done;
+ args = Py_BuildValue("OOzi", ob, obIID, NULL, 0);
+ if (args==NULL) goto done;
+ wrap_ret = PyEval_CallObject(func, args);
+ if (wrap_ret==NULL) goto done;
+ ok = Py_nsISupports::InterfaceFromPyObject(wrap_ret, iid, ppret, PR_FALSE, PR_FALSE);
+#ifdef DEBUG
+ if (ok)
+ // Check we _now_ have a default gateway
+ {
+ nsISupports *temp = NULL;
+ NS_ABORT_IF_FALSE(CheckDefaultGateway(ob, iid, &temp), "Auto-wrapped object didnt get a default gateway!");
+ if (temp) temp->Release();
+ }
+#endif
+ }
+done:
+// Py_XDECREF(func); -- func is static for performance reasons.
+ Py_XDECREF(obIID);
+ Py_XDECREF(wrap_ret);
+ Py_XDECREF(args);
+ return ok;
+}
+
+// Call back into Python, passing a raw nsIInterface object, getting back
+// the object to actually use as the gateway parameter for this interface.
+// For example, it is expected that the policy will wrap the interface
+// object in one of the xpcom.client.Interface objects, allowing
+// natural usage of the interface from Python clients.
+// Note that piid will usually be NULL - this is because the runtime
+// reflection interfaces dont provide this information to me.
+// In this case, the Python code may choose to lookup the complete
+// interface info to obtain the IID.
+// It is expected (but should not be assumed) that the method info
+// or the IID will be NULL.
+// Worst case, the code should provide a wrapper for the nsiSupports interface,
+// so at least the user can simply QI the object.
+PyObject *
+PyG_Base::MakeInterfaceParam(nsISupports *pis,
+ const nsIID *piid,
+ int methodIndex /* = -1 */,
+ const XPTParamDescriptor *d /* = NULL */,
+ int paramIndex /* = -1 */)
+{
+ if (pis==NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ // This condition is true today, but not necessarily so.
+ // But if it ever triggers, the poor Python code has no real hope
+ // of returning something useful, so we should at least do our
+ // best to provide the useful data.
+ NS_WARN_IF_FALSE( ((piid != NULL) ^ (d != NULL)) == 1, "No information on the interface available - Python's gunna have a hard time doing much with it!");
+ PyObject *obIID = NULL;
+ PyObject *obISupports = NULL;
+ PyObject *obParamDesc = NULL;
+ PyObject *result = NULL;
+
+ // get the basic interface first, as if we fail, we can try and use this.
+ // If we don't know the IID, we must explicitly query for nsISupports.
+ nsCOMPtr<nsISupports> piswrap;
+ nsIID iid_check;
+ if (piid) {
+ iid_check = *piid;
+ piswrap = pis;
+ } else {
+ /* HACK ALERT! Dropping the python interpreter lock here while
+ doing QueryInterface because it may involve IPC to a python
+ object in the same interpreter and deadlock. Not at all
+ sure if this is a good idea or not for the internal PyXPCOM
+ state, but it might fix the deadloock... Hoping for the best. */
+ Py_BEGIN_ALLOW_THREADS;
+ iid_check = NS_GET_IID(nsISupports);
+ pis->QueryInterface(iid_check, getter_AddRefs(piswrap));
+ Py_END_ALLOW_THREADS;
+ }
+
+ obISupports = Py_nsISupports::PyObjectFromInterface(piswrap, iid_check, PR_FALSE);
+ if (!obISupports)
+ goto done;
+ if (piid==NULL) {
+ obIID = Py_None;
+ Py_INCREF(Py_None);
+ } else
+ obIID = Py_nsIID::PyObjectFromIID(*piid);
+ if (obIID==NULL)
+ goto done;
+ obParamDesc = PyObject_FromXPTParamDescriptor(d);
+ if (obParamDesc==NULL)
+ goto done;
+
+ result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_MakeInterfaceParam_",
+ (char*)"OOiOi",
+ obISupports,
+ obIID,
+ methodIndex,
+ obParamDesc,
+ paramIndex);
+done:
+ if (PyErr_Occurred()) {
+ NS_WARN_IF_FALSE(result==NULL, "Have an error, but also a result!");
+ PyXPCOM_LogError("Wrapping an interface object for the gateway failed\n");
+ }
+ Py_XDECREF(obIID);
+ Py_XDECREF(obParamDesc);
+ if (result==NULL) { // we had an error.
+ PyErr_Clear(); // but are not reporting it back to Python itself!
+ // return our obISupports. If NULL, we are really hosed and nothing we can do.
+ return obISupports;
+ }
+ // Dont need to return this - we have a better result.
+ Py_XDECREF(obISupports);
+ return result;
+}
+
+NS_IMETHODIMP
+PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
+{
+#ifdef PYXPCOM_DEBUG_FULL
+ {
+ char *sziid = iid.ToString();
+ LogF("PyGatewayBase::QueryInterface: %s", sziid);
+ Allocator::Free(sziid);
+ }
+#endif
+ NS_PRECONDITION(ppv, "NULL pointer");
+ if (ppv==nsnull)
+ return NS_ERROR_NULL_POINTER;
+ *ppv = nsnull;
+ // If one of our native interfaces (but NOT nsISupports if we have a base)
+ // return this.
+ // It is important is that nsISupports come from the base object
+ // to ensure that we live by XPCOM identity rules (other interfaces need
+ // not abide by this rule - only nsISupports.)
+ if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports)))
+ && (*ppv=ThisAsIID(iid)) != NULL ) {
+ AddRef();
+ return NS_OK;
+ }
+ // If we have a "base object", then we need to delegate _every_ remaining
+ // QI to it.
+ if (m_pBaseObject != NULL)
+ return m_pBaseObject->QueryInterface(iid, ppv);
+
+ // Call the Python policy to see if it (says it) supports the interface
+ PRBool supports = PR_FALSE;
+ { // temp scope for Python lock
+ CEnterLeavePython celp;
+
+ PyObject * ob = Py_nsIID::PyObjectFromIID(iid);
+ // must say this is an 'internal' call, else we recurse QI into
+ // oblivion.
+ PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface(
+ (nsXPTCStubBase *)this,
+ iid, PR_FALSE, PR_TRUE);
+ if ( !ob || !this_interface_ob) {
+ Py_XDECREF(ob);
+ Py_XDECREF(this_interface_ob);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PyObject *result = PyObject_CallMethod(m_pPyObject, (char*)"_QueryInterface_",
+ (char*)"OO",
+ this_interface_ob, ob);
+ Py_DECREF(ob);
+ Py_DECREF(this_interface_ob);
+
+ if ( result ) {
+ if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) {
+ // If OK, but NULL, _QI_ returned None, which simply means
+ // "no such interface"
+ supports = (*ppv!=NULL);
+ // result has been QI'd and AddRef'd all ready for return.
+ } else {
+ // Dump this message and any Python exception before
+ // reporting the fact that QI failed - this error
+ // may provide clues!
+ PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", PyXPCOM_ObTypeName(result));
+ // supports remains false
+ }
+ Py_DECREF(result);
+ } else {
+ NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!");
+ NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!");
+ PyXPCOM_LogError("The _QueryInterface_ processing failed.\n");
+ // supports remains false.
+ // We have reported the error, and are returning to COM,
+ // so we should clear it.
+ PyErr_Clear();
+ }
+ } // end of temp scope for Python lock - lock released here!
+ if ( !supports )
+ return NS_ERROR_NO_INTERFACE;
+ return NS_OK;
+}
+
+nsrefcnt
+PyG_Base::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ // If we have no pBaseObject, then we need to ignore them
+ if (m_pBaseObject == NULL)
+ NS_LOG_ADDREF(this, cnt, refcntLogRepr, sizeof(*this));
+#endif
+ return cnt;
+}
+
+nsrefcnt
+PyG_Base::Release(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ if (m_pBaseObject == NULL)
+ NS_LOG_RELEASE(this, cnt, refcntLogRepr);
+#endif
+ if ( cnt == 0 )
+ delete this;
+ return cnt;
+}
+
+NS_IMETHODIMP
+PyG_Base::GetWeakReference(nsIWeakReference **ret)
+{
+ // always delegate back to the "base" gateway for the object, as this tear-off
+ // interface may not live as long as the base. So we recurse back to the base.
+ if (m_pBaseObject) {
+ NS_PRECONDITION(m_pWeakRef == nsnull, "Not a base object, but do have a weak-ref!");
+ return m_pBaseObject->GetWeakReference(ret);
+ }
+ NS_PRECONDITION(ret, "null pointer");
+ if (ret==nsnull) return NS_ERROR_INVALID_POINTER;
+ if (!m_pWeakRef) {
+ // First query for a weak reference - create it.
+ // XXX - this looks like it needs thread safety!?
+ m_pWeakRef = new PyXPCOM_GatewayWeakReference(this);
+ NS_ABORT_IF_FALSE(m_pWeakRef, "Shouldn't be able to fail creating a weak reference!");
+ if (!m_pWeakRef)
+ return NS_ERROR_UNEXPECTED;
+ }
+ *ret = m_pWeakRef;
+ (*ret)->AddRef();
+ return NS_OK;
+}
+
+nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
+{
+ nsresult rc = NS_OK;
+ if (PyErr_Occurred()) {
+ // The error handling - fairly involved, but worth it as
+ // good error reporting is critical for users to know WTF
+ // is going on - especially with TypeErrors etc in their
+ // return values (ie, after the Python code has successfully
+ // exited, but we encountered errors unpacking their
+ // result values for the COM caller - there is literally no
+ // way to catch these exceptions from Python code, as their
+ // is no Python function directly on the call-stack)
+
+ // First line of attack in an error is to call-back on the policy.
+ // If the callback of the error handler succeeds and returns an
+ // integer (for the nsresult), we take no further action.
+
+ // If this callback fails, we log _2_ exceptions - the error
+ // handler error, and the original error.
+
+ PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
+ PyObject *exc_typ, *exc_val, *exc_tb;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
+
+ PyObject *err_result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_GatewayException_",
+ (char*)"z(OOO)",
+ szMethodName,
+ exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
+ exc_val ? exc_val : Py_None, // may well be NULL.
+ exc_tb ? exc_tb : Py_None); // may well be NULL.
+ if (err_result == NULL) {
+ PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
+ } else if (err_result == Py_None) {
+ // The exception handler has chosen not to do anything with
+ // this error, so we still need to print it!
+ ;
+ } else if (PyInt_Check(err_result)) {
+ // The exception handler has given us the nresult.
+ rc = PyInt_AsLong(err_result);
+ bProcessMainError = PR_FALSE;
+ } else {
+ // The exception handler succeeded, but returned other than
+ // int or None.
+ PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result));
+ }
+ Py_XDECREF(err_result);
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ if (bProcessMainError) {
+ PyXPCOM_LogError("The function '%s' failed\n", szMethodName);
+ rc = PyXPCOM_SetCOMErrorFromPyException();
+ }
+ PyErr_Clear();
+ }
+ return rc;
+}
+
+static nsresult do_dispatch(
+ PyObject *pPyObject,
+ PyObject **ppResult,
+ const char *szMethodName,
+ const char *szFormat,
+ va_list va
+ )
+{
+ NS_PRECONDITION(ppResult, "Must provide a result buffer");
+ *ppResult = nsnull;
+ // Build the Invoke arguments...
+ PyObject *args = NULL;
+ PyObject *method = NULL;
+ PyObject *real_ob = NULL;
+ nsresult ret = NS_ERROR_FAILURE;
+ if ( szFormat )
+ args = Py_VaBuildValue((char *)szFormat, va);
+ else
+ args = PyTuple_New(0);
+ if ( !args )
+ goto done;
+
+ // make sure a tuple.
+ if ( !PyTuple_Check(args) ) {
+ PyObject *a = PyTuple_New(1);
+ if ( a == NULL )
+ {
+ Py_DECREF(args);
+ goto done;
+ }
+ PyTuple_SET_ITEM(a, 0, args);
+ args = a;
+ }
+ // Bit to a hack here to maintain the use of a policy.
+ // We actually get the policies underlying object
+ // to make the call on.
+ real_ob = PyObject_GetAttrString(pPyObject, "_obj_");
+ if (real_ob == NULL) {
+ PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
+ goto done;
+ }
+ method = PyObject_GetAttrString(real_ob, (char *)szMethodName);
+ if ( !method ) {
+ PyErr_Clear();
+ ret = NS_PYXPCOM_NO_SUCH_METHOD;
+ goto done;
+ }
+ // Make the call
+ *ppResult = PyEval_CallObject(method, args);
+ ret = *ppResult ? NS_OK : NS_ERROR_FAILURE;
+done:
+ Py_XDECREF(method);
+ Py_XDECREF(real_ob);
+ Py_XDECREF(args);
+ return ret;
+}
+
+
+nsresult PyG_Base::InvokeNativeViaPolicyInternal(
+ const char *szMethodName,
+ PyObject **ppResult,
+ const char *szFormat,
+ va_list va
+ )
+{
+ if ( m_pPyObject == NULL || szMethodName == NULL )
+ return NS_ERROR_NULL_POINTER;
+
+ PyObject *temp = nsnull;
+ if (ppResult == nsnull)
+ ppResult = &temp;
+ nsresult nr = do_dispatch(m_pPyObject, ppResult, szMethodName, szFormat, va);
+
+ // If temp is NULL, they provided a buffer, and we dont touch it.
+ // If not NULL, *ppResult = temp, and _we_ do own it.
+ Py_XDECREF(temp);
+ return nr;
+}
+
+nsresult PyG_Base::InvokeNativeViaPolicy(
+ const char *szMethodName,
+ PyObject **ppResult /* = NULL */,
+ const char *szFormat /* = NULL */,
+ ...
+ )
+{
+ va_list va;
+ va_start(va, szFormat);
+ nsresult nr = InvokeNativeViaPolicyInternal(szMethodName, ppResult, szFormat, va);
+ va_end(va);
+
+ if (nr == NS_PYXPCOM_NO_SUCH_METHOD) {
+ // Only problem was missing method.
+ PyErr_Format(PyExc_AttributeError, "The object does not have a '%s' function.", szMethodName);
+ }
+ return nr == NS_OK ? NS_OK : HandleNativeGatewayError(szMethodName);
+}
+
+nsresult PyG_Base::InvokeNativeGetViaPolicy(
+ const char *szPropertyName,
+ PyObject **ppResult /* = NULL */
+ )
+{
+ PyObject *ob_ret = NULL;
+ nsresult ret = NS_OK;
+ PyObject *real_ob = NULL;
+ if ( m_pPyObject == NULL || szPropertyName == NULL )
+ return NS_ERROR_NULL_POINTER;
+ // First see if we have a method of that name.
+ char buf[256];
+ strcpy(buf, "get_");
+ strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
+ buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
+ ret = InvokeNativeViaPolicyInternal(buf, ppResult, nsnull, nsnull);
+ if (ret == NS_PYXPCOM_NO_SUCH_METHOD) {
+ // No method of that name - just try a property.
+ // Bit to a hack here to maintain the use of a policy.
+ // We actually get the policies underlying object
+ // to make the call on.
+ real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
+ if (real_ob == NULL) {
+ PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
+ ret = HandleNativeGatewayError(szPropertyName);
+ goto done;
+ }
+ ob_ret = PyObject_GetAttrString(real_ob, (char *)szPropertyName);
+ if (ob_ret==NULL) {
+ PyErr_Format(PyExc_AttributeError,
+ "The object does not have a 'get_%s' function, or a '%s attribute.",
+ szPropertyName, szPropertyName);
+ } else {
+ ret = NS_OK;
+ if (ppResult)
+ *ppResult = ob_ret;
+ else
+ Py_XDECREF(ob_ret);
+ }
+ }
+ if (ret != NS_OK)
+ ret = HandleNativeGatewayError(szPropertyName);
+
+done:
+ Py_XDECREF(real_ob);
+ return ret;
+}
+
+nsresult PyG_Base::InvokeNativeSetViaPolicy(
+ const char *szPropertyName,
+ ...
+ )
+{
+ if ( m_pPyObject == NULL || szPropertyName == NULL )
+ return NS_ERROR_NULL_POINTER;
+ nsresult ret = NS_OK;
+ PyObject *real_ob = NULL;
+ char buf[256];
+ strcpy(buf, "set_");
+ strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1);
+ buf[sizeof(buf)/sizeof(buf[0])-1] = '\0';
+ va_list va;
+ va_start(va, szPropertyName);
+ ret = InvokeNativeViaPolicyInternal(buf, NULL, "O", va);
+ va_end(va);
+ if (ret == NS_PYXPCOM_NO_SUCH_METHOD) {
+ // No method of that name - just try a property.
+ // Bit to a hack here to maintain the use of a policy.
+ // We actually get the policies underlying object
+ // to make the call on.
+ real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_");
+ if (real_ob == NULL) {
+ PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute.");
+ ret = HandleNativeGatewayError(szPropertyName);
+ goto done;
+ }
+ va_list va2;
+ va_start(va2, szPropertyName);
+ PyObject *arg = va_arg( va2, PyObject *);
+ va_end(va2);
+ if (PyObject_SetAttrString(real_ob, (char *)szPropertyName, arg) == 0)
+ ret = NS_OK;
+ else {
+ PyErr_Format(PyExc_AttributeError,
+ "The object does not have a 'set_%s' function, or a '%s attribute.",
+ szPropertyName, szPropertyName);
+ }
+ }
+ if (ret != NS_OK)
+ ret = HandleNativeGatewayError(szPropertyName);
+done:
+ Py_XDECREF(real_ob);
+ return ret;
+}
+
+// Get at the underlying Python object.
+PyObject *PyG_Base::UnwrapPythonObject(void)
+{
+ Py_INCREF(m_pPyObject);
+ return m_pPyObject;
+}
+/******************************************************
+
+ Some special support to help with object identity.
+
+ In the simplest case, assume a Python XPCOM object is
+ supporting a function "nsIWhatever GetWhatever()",
+ so implements it as:
+ return self
+ it is almost certain they intend returning
+ the same COM OBJECT to the caller! Thus, if a user of this COM
+ object does:
+
+ p1 = foo.GetWhatever();
+ p2 = foo.GetWhatever();
+
+ We almost certainly expect p1==p2==foo.
+
+ We previously _did_ have special support for the "self"
+ example above, but this implements a generic scheme that
+ works for _all_ objects.
+
+ Whenever we are asked to "AutoWrap" a Python object, the
+ first thing we do is see if it has been auto-wrapped before.
+
+ If not, we create a new wrapper, then make a COM weak reference
+ to that wrapper, and store it directly back into the instance
+ we are auto-wrapping! The use of a weak-reference prevents
+ cycles.
+
+ The existance of this attribute in an instance indicates if it
+ has been previously auto-wrapped.
+
+ If it _has_ previously been auto-wrapped, we de-reference the
+ weak reference, and use that gateway.
+
+*********************************************************************/
+
+PyG_Base *GetDefaultGateway(PyObject *policy)
+{
+ // NOTE: Instance is the policy, not the real instance
+ PyObject *instance = PyObject_GetAttrString(policy, "_obj_");
+ if (instance == nsnull)
+ return nsnull;
+ PyObject *ob_existing_weak = PyObject_GetAttrString(instance, PyXPCOM_szDefaultGatewayAttributeName);
+ Py_DECREF(instance);
+ if (ob_existing_weak != NULL) {
+ PRBool ok = PR_TRUE;
+ nsCOMPtr<nsIWeakReference> pWeakRef;
+ ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
+ NS_GET_IID(nsIWeakReference),
+ getter_AddRefs(pWeakRef),
+ PR_FALSE));
+ Py_DECREF(ob_existing_weak);
+ nsISupports *pip;
+ if (ok) {
+ nsresult nr = pWeakRef->QueryReferent( NS_GET_IID(nsIInternalPython), (void **)&pip);
+ if (NS_FAILED(nr))
+ return nsnull;
+ return (PyG_Base *)(nsIInternalPython *)pip;
+ }
+ } else
+ PyErr_Clear();
+ return nsnull;
+}
+
+PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway)
+{
+ NS_ABORT_IF_FALSE(real_inst, "Did not have an _obj_ attribute");
+ if (real_inst==NULL) {
+ PyErr_Clear();
+ return PR_FALSE;
+ }
+ PyObject *ob_existing_weak = PyObject_GetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName);
+ if (ob_existing_weak != NULL) {
+ // We have an existing default, but as it is a weak reference, it
+ // may no longer be valid. Check it.
+ PRBool ok = PR_TRUE;
+ nsCOMPtr<nsIWeakReference> pWeakRef;
+ ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak,
+ NS_GET_IID(nsIWeakReference),
+ getter_AddRefs(pWeakRef),
+ PR_FALSE));
+ Py_DECREF(ob_existing_weak);
+ if (ok) {
+ Py_BEGIN_ALLOW_THREADS;
+ ok = NS_SUCCEEDED(pWeakRef->QueryReferent( iid, (void **)(ret_gateway)));
+ Py_END_ALLOW_THREADS;
+ }
+ if (!ok) {
+ // We have the attribute, but not valid - wipe it
+ // before restoring it.
+ if (0 != PyObject_DelAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName))
+ PyErr_Clear();
+ }
+ return ok;
+ }
+ PyErr_Clear();
+ return PR_FALSE;
+}
+
+void AddDefaultGateway(PyObject *instance, nsISupports *gateway)
+{
+ // NOTE: Instance is the _policy_!
+ PyObject *real_inst = PyObject_GetAttrString(instance, "_obj_");
+ NS_ABORT_IF_FALSE(real_inst, "Could not get the '_obj_' element");
+ if (!real_inst) return;
+ if (!PyObject_HasAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName)) {
+ nsCOMPtr<nsISupportsWeakReference> swr( do_QueryInterface((nsISupportsWeakReference *)(gateway)) );
+ NS_ABORT_IF_FALSE(swr, "Our gateway failed with a weak reference query");
+ // Create the new default gateway - get a weak reference for our gateway.
+ if (swr) {
+ nsCOMPtr<nsIWeakReference> pWeakReference;
+ swr->GetWeakReference( getter_AddRefs(pWeakReference) );
+ if (pWeakReference) {
+ PyObject *ob_new_weak = Py_nsISupports::PyObjectFromInterface(pWeakReference,
+ NS_GET_IID(nsIWeakReference),
+ PR_FALSE ); /* bMakeNicePyObject */
+ // pWeakReference reference consumed.
+ if (ob_new_weak) {
+ PyObject_SetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName, ob_new_weak);
+ Py_DECREF(ob_new_weak);
+ }
+ }
+ }
+ }
+ Py_DECREF(real_inst);
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGInputStream.cpp b/src/libs/xpcom18a4/python/src/PyGInputStream.cpp
new file mode 100644
index 00000000..d7c27043
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGInputStream.cpp
@@ -0,0 +1,173 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+// PyGInputStream.cpp
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written October 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInputStream.h>
+
+class PyG_nsIInputStream : public PyG_Base, public nsIInputStream
+{
+public:
+ PyG_nsIInputStream(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIInputStream)) {;}
+ PYGATEWAY_BASE_SUPPORT(nsIInputStream, PyG_Base);
+
+ NS_IMETHOD Close(void);
+ NS_IMETHOD Available(PRUint32 *_retval);
+ NS_IMETHOD Read(char * buf, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking);
+};
+
+
+PyG_Base *MakePyG_nsIInputStream(PyObject *instance)
+{
+ return new PyG_nsIInputStream(instance);
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::Close()
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "close";
+ return InvokeNativeViaPolicy(methodName, NULL);
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::Available(PRUint32 *_retval)
+{
+ NS_PRECONDITION(_retval, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *ret;
+ const char *methodName = "available";
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ Py_XDECREF(ret);
+ }
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval)
+{
+ NS_PRECONDITION(_retval, "null pointer");
+ NS_PRECONDITION(buf, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *ret;
+ const char *methodName = "read";
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count);
+ if (NS_SUCCEEDED(nr)) {
+#if 0 /* VBox: new buffer protocol (though I could use it for Py_LIMITED_API and ditch the warning, but cpython specific) */
+ Py_buffer py_view;
+ if (PyObject_GetBuffer(ret, &py_view, PyBUF_SIMPLE) == 0) {
+ if (py_view.len <= count) {
+ count = py_view.len;
+ } else {
+ PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
+ }
+ memcpy(buf, py_view.py_buf, count);
+ PyBuffer_Release(&py_view);
+ *_retval = count;
+ } else {
+ PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret));
+ nr = HandleNativeGatewayError(methodName);
+ }
+#else /* Old protocol: */
+# ifndef VBOX /* unsafe cast on 64-bit hosts. */
+ PRUint32 py_size;
+ const void *py_buf;
+ if (PyObject_AsReadBuffer(ret, &py_buf, (Py_ssize_t*)&py_size)!=0) {
+# else /* VBOX */
+ const void *py_buf;
+# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
+ Py_ssize_t py_size;
+# else
+ int py_size;
+# endif
+ if (PyObject_AsReadBuffer(ret, &py_buf, &py_size)!=0) {
+# endif /* VBOX */
+ PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret));
+ nr = HandleNativeGatewayError(methodName);
+ } else {
+ if (py_size > count) {
+ PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
+ py_size = count;
+ }
+ memcpy(buf, py_buf, py_size);
+ *_retval = py_size;
+ }
+#endif
+ }
+ return nr;
+}
+
+
+NS_IMETHODIMP
+PyG_nsIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_WARNING("ReadSegments() not implemented!!!");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+PyG_nsIInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ NS_PRECONDITION(aNonBlocking, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *ret;
+ const char *methodName = "isNonBlocking";
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret);
+ if (NS_SUCCEEDED(nr)) {
+ *aNonBlocking = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ Py_XDECREF(ret);
+ }
+ return nr;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGModule.cpp b/src/libs/xpcom18a4/python/src/PyGModule.cpp
new file mode 100644
index 00000000..599e0f87
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGModule.cpp
@@ -0,0 +1,297 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+// Unfortunately, we can not use an XPConnect object for
+// the nsiModule and nsiComponentLoader interfaces.
+// As XPCOM shuts down, it shuts down the interface manager before
+// it releases all the modules. This is a bit of a problem for
+// us, as it means we can't get runtime info on the interface at shutdown time.
+
+#include "PyXPCOM_std.h"
+#include <nsIModule.h>
+#include <nsIComponentLoader.h>
+
+class PyG_nsIModule : public PyG_Base, public nsIModule
+{
+public:
+ PyG_nsIModule(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIModule)) {;}
+ PYGATEWAY_BASE_SUPPORT(nsIModule, PyG_Base);
+
+ NS_DECL_NSIMODULE
+};
+
+PyG_Base *MakePyG_nsIModule(PyObject *instance)
+{
+ return new PyG_nsIModule(instance);
+}
+
+
+// Create a factory object for creating instances of aClass.
+NS_IMETHODIMP
+PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr,
+ const nsCID& aClass,
+ const nsIID& aIID,
+ void** r_classObj)
+{
+ NS_PRECONDITION(r_classObj, "null pointer");
+ *r_classObj = nsnull;
+ CEnterLeavePython _celp;
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *iid = Py_nsIID::PyObjectFromIID(aIID);
+ PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass);
+ const char *methodName = "getClassObject";
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "OOO", cm, clsid, iid);
+ Py_XDECREF(cm);
+ Py_XDECREF(iid);
+ Py_XDECREF(clsid);
+ if (NS_SUCCEEDED(nr)) {
+ nr = Py_nsISupports::InterfaceFromPyObject(ret, aIID, (nsISupports **)r_classObj, PR_FALSE);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ if (NS_FAILED(nr)) {
+ NS_ABORT_IF_FALSE(*r_classObj==NULL, "returning error result with an interface - probable leak!");
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation,
+ const char* componentType)
+{
+ NS_PRECONDITION(aCompMgr, "null pointer");
+ NS_PRECONDITION(aPath, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
+ const char *methodName = "registerSelf";
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType);
+ Py_XDECREF(cm);
+ Py_XDECREF(path);
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation)
+{
+ NS_PRECONDITION(aCompMgr, "null pointer");
+ NS_PRECONDITION(aPath, "null pointer");
+ CEnterLeavePython _celp;
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
+ const char *methodName = "unregisterSelf";
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation);
+ Py_XDECREF(cm);
+ Py_XDECREF(path);
+ return nr;
+}
+
+NS_IMETHODIMP
+PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
+{
+ NS_PRECONDITION(aCompMgr, "null pointer");
+ NS_PRECONDITION(okToUnload, "null pointer");
+ CEnterLeavePython _celp;
+ // we are shutting down - don't ask for a nice wrapped object.
+ PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_FALSE);
+ const char *methodName = "canUnload";
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm);
+ Py_XDECREF(cm);
+ if (NS_SUCCEEDED(nr)) {
+ *okToUnload = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+class PyG_nsIComponentLoader : public PyG_Base, public nsIComponentLoader
+{
+public:
+ PyG_nsIComponentLoader(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIComponentLoader)) {;}
+ PYGATEWAY_BASE_SUPPORT(nsIComponentLoader, PyG_Base);
+
+ NS_DECL_NSICOMPONENTLOADER
+};
+
+PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance)
+{
+ return new PyG_nsIComponentLoader(instance);
+}
+
+/* nsIFactory getFactory (in nsIIDRef aCID, in string aLocation, in string aType); */
+NS_IMETHODIMP PyG_nsIComponentLoader::GetFactory(const nsIID & aCID, const char *aLocation, const char *aType, nsIFactory **_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "getFactory";
+ PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "Ozz",
+ iid,
+ aLocation,
+ aType);
+ Py_XDECREF(iid);
+ if (NS_SUCCEEDED(nr)) {
+ Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIFactory), (nsISupports **)_retval, PR_FALSE);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* void init (in nsIComponentManager aCompMgr, in nsISupports aRegistry); */
+NS_IMETHODIMP PyG_nsIComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aRegistry)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "init";
+ PyObject *c = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
+ PyObject *r = PyObject_FromNSInterface(aRegistry, NS_GET_IID(nsISupports));
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OO", c, r);
+ Py_XDECREF(c);
+ Py_XDECREF(r);
+ return nr;
+}
+
+/* void onRegister (in nsIIDRef aCID, in string aType, in string aClassName, in string aContractID, in string aLocation, in boolean aReplace, in boolean aPersist); */
+NS_IMETHODIMP PyG_nsIComponentLoader::OnRegister(const nsIID & aCID, const char *aType, const char *aClassName, const char *aContractID, const char *aLocation, PRBool aReplace, PRBool aPersist)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "onRegister";
+ PyObject *iid = Py_nsIID::PyObjectFromIID(aCID);
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "Ossssii",
+ iid,
+ aType,
+ aClassName,
+ aContractID,
+ aLocation,
+ aReplace,
+ aPersist);
+ Py_XDECREF(iid);
+ return nr;
+}
+
+/* void autoRegisterComponents (in long aWhen, in nsIFile aDirectory); */
+NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIFile *aDirectory)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "autoRegisterComponents";
+ PyObject *c = PyObject_FromNSInterface(aDirectory, NS_GET_IID(nsIFile));
+ nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "iO", aWhen, c);
+ Py_XDECREF(c);
+ return nr;
+}
+
+/* boolean autoRegisterComponent (in long aWhen, in nsIFile aComponent); */
+NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "autoRegisterComponent";
+ PyObject *ret = NULL;
+ PyObject *c = PyObject_FromNSInterface(aComponent, NS_GET_IID(nsIFile));
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
+ Py_XDECREF(c);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* boolean autoUnregisterComponent (in long aWhen, in nsIFile aComponent); */
+NS_IMETHODIMP PyG_nsIComponentLoader::AutoUnregisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "autoUnregisterComponent";
+ PyObject *ret = NULL;
+ PyObject *c = PyObject_FromNSInterface(aComponent, NS_GET_IID(nsIFile));
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c);
+ Py_XDECREF(c);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* boolean registerDeferredComponents (in long aWhen); */
+NS_IMETHODIMP PyG_nsIComponentLoader::RegisterDeferredComponents(PRInt32 aWhen, PRBool *_retval)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "registerDeferredComponents";
+ PyObject *ret = NULL;
+ nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", aWhen);
+ if (NS_SUCCEEDED(nr)) {
+ *_retval = PyInt_AsLong(ret);
+ if (PyErr_Occurred())
+ nr = HandleNativeGatewayError(methodName);
+ }
+ Py_XDECREF(ret);
+ return nr;
+}
+
+/* void unloadAll (in long aWhen); */
+NS_IMETHODIMP PyG_nsIComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ CEnterLeavePython _celp;
+ const char *methodName = "unloadAll";
+ return InvokeNativeViaPolicy(methodName, NULL, "i", aWhen);
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGStub.cpp b/src/libs/xpcom18a4/python/src/PyGStub.cpp
new file mode 100644
index 00000000..6f219333
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGStub.cpp
@@ -0,0 +1,180 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// PyXPTStub - the stub for implementing interfaces.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+
+void *PyXPCOM_XPTStub::ThisAsIID(const nsIID &iid)
+{
+ if (iid.Equals(NS_GET_IID(nsISupports)))
+ return (nsISupports *)(nsXPTCStubBase *)this;
+ else if (iid.Equals(m_iid))
+ return (nsISupports *)(nsXPTCStubBase *)this;
+ else
+ return PyG_Base::ThisAsIID(iid);
+}
+
+
+NS_IMETHODIMP
+PyXPCOM_XPTStub::GetInterfaceInfo(nsIInterfaceInfo** info)
+{
+ NS_PRECONDITION(info, "NULL pointer");
+ if (info==nsnull)
+ return NS_ERROR_NULL_POINTER;
+ // Simply get the XPCOM runtime to provide this
+ // (but there must be some reason why they dont get it themselves!?
+ // Maybe because they dont know the IID?
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!");
+ if (iim==nsnull)
+ return NS_ERROR_FAILURE;
+
+ return iim->GetInfoForIID( &m_iid, info);
+}
+
+// call this method and return result
+NS_IMETHODIMP
+PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params)
+{
+ nsresult rc = NS_ERROR_FAILURE;
+ NS_PRECONDITION(info, "NULL methodinfo pointer");
+ NS_PRECONDITION(params, "NULL variant pointer");
+ CEnterLeavePython _celp;
+ PyObject *obParams = NULL;
+ PyObject *result = NULL;
+ PyObject *obThisObject = NULL;
+ PyObject *obMI = PyObject_FromXPTMethodDescriptor(info);
+ PyXPCOM_GatewayVariantHelper arg_helper(this, methodIndex, info, params);
+ if (obMI==NULL)
+ goto done;
+ // base object is passed raw.
+ obThisObject = PyObject_FromNSInterface((nsXPTCStubBase *)this,
+ m_iid, PR_FALSE);
+ obParams = arg_helper.MakePyArgs();
+ if (obParams==NULL)
+ goto done;
+ result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_CallMethod_",
+ (char*)"OiOO",
+ obThisObject,
+ (int)methodIndex,
+ obMI,
+ obParams);
+ if (result!=NULL) {
+ rc = arg_helper.ProcessPythonResult(result);
+ // Use an xor to check failure && pyerr, or !failure && !pyerr.
+ NS_ABORT_IF_FALSE( ((NS_FAILED(rc)!=0)^(PyErr_Occurred()!=0)) == 0, "We must have failure with a Python error, or success without a Python error.");
+ }
+done:
+ if (PyErr_Occurred()) {
+ // The error handling - fairly involved, but worth it as
+ // good error reporting is critical for users to know WTF
+ // is going on - especially with TypeErrors etc in their
+ // return values (ie, after the Python code has successfully
+ // exited, but we encountered errors unpacking the
+ // result values for the COM caller - there is literally no
+ // way to catch these exceptions from Python code, as their
+ // is no Python function on the call-stack)
+
+ // First line of attack in an error is to call-back on the policy.
+ // If the callback of the error handler succeeds and returns an
+ // integer (for the nsresult), we take no further action.
+
+ // If this callback fails, we log _2_ exceptions - the error handler
+ // error, and the original error.
+
+ PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
+ PyObject *exc_typ, *exc_val, *exc_tb;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
+ PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
+
+ PyObject *err_result = PyObject_CallMethod(m_pPyObject,
+ (char*)"_CallMethodException_",
+ (char*)"OiOO(OOO)",
+ obThisObject,
+ (int)methodIndex,
+ obMI,
+ obParams,
+ exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming...
+ exc_val ? exc_val : Py_None, // may well be NULL.
+ exc_tb ? exc_tb : Py_None); // may well be NULL.
+ if (err_result == NULL) {
+ PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n");
+ } else if (err_result == Py_None) {
+ // The exception handler has chosen not to do anything with
+ // this error, so we still need to print it!
+ ;
+ } else if (PyInt_Check(err_result)) {
+ // The exception handler has given us the nresult.
+ rc = PyInt_AsLong(err_result);
+ bProcessMainError = PR_FALSE;
+ } else {
+ // The exception handler succeeded, but returned other than
+ // int or None.
+ PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result));
+ }
+ Py_XDECREF(err_result);
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ if (bProcessMainError) {
+ PyXPCOM_LogError("The function '%s' failed\n", info->GetName());
+ rc = PyXPCOM_SetCOMErrorFromPyException();
+ }
+ // else everything is already setup,
+ // just clear the Python error state.
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(obMI);
+ Py_XDECREF(obParams);
+ Py_XDECREF(obThisObject);
+ Py_XDECREF(result);
+ return rc;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp b/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp
new file mode 100644
index 00000000..e5254acc
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp
@@ -0,0 +1,112 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+// PyGWeakReference - implements weak references for gateways.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written November 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+PyXPCOM_GatewayWeakReference::PyXPCOM_GatewayWeakReference( PyG_Base *base )
+{
+ m_pBase = base;
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ // bloat view uses 40 chars - stick "(WR)" at the end of this position.
+ strncpy(refcntLogRepr, m_pBase->refcntLogRepr, sizeof(refcntLogRepr));
+ refcntLogRepr[sizeof(refcntLogRepr)-1] = '\0';
+ char *dest = refcntLogRepr + ((strlen(refcntLogRepr) > 36) ? 36 : strlen(refcntLogRepr));
+ strcpy(dest, "(WR)");
+#endif // NS_BUILD_REFCNT_LOGGING
+}
+
+PyXPCOM_GatewayWeakReference::~PyXPCOM_GatewayWeakReference()
+{
+ // Simply zap my reference to the gateway!
+ // No need to zap my gateway's reference to me, as
+ // it already holds a reference, so if we are destructing,
+ // then it can't possibly hold one.
+ m_pBase = NULL;
+}
+
+nsrefcnt
+PyXPCOM_GatewayWeakReference::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ NS_LOG_ADDREF(this, cnt, refcntLogRepr, sizeof(*this));
+#endif
+ return cnt;
+}
+
+nsrefcnt
+PyXPCOM_GatewayWeakReference::Release(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ NS_LOG_RELEASE(this, cnt, refcntLogRepr);
+#endif
+ if ( cnt == 0 )
+ delete this;
+ return cnt;
+}
+
+NS_IMPL_THREADSAFE_QUERY_INTERFACE1(PyXPCOM_GatewayWeakReference, nsIWeakReference)
+
+NS_IMETHODIMP
+PyXPCOM_GatewayWeakReference::QueryReferent(REFNSIID iid, void * *ret)
+{
+ {
+ // Temp scope for lock. We can't hold the lock during
+ // a QI, as this may itself need the lock.
+ // Make sure our object isn't dieing right now on another thread.
+ CEnterLeaveXPCOMFramework _celf;
+ if (m_pBase == NULL)
+ return NS_ERROR_NULL_POINTER;
+ m_pBase->AddRef(); // Can't die while we have a ref.
+ } // end of lock scope - lock unlocked.
+ nsresult nr = m_pBase->QueryInterface(iid, ret);
+ m_pBase->Release();
+ return nr;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp b/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp
new file mode 100644
index 00000000..6d0f499d
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp
@@ -0,0 +1,181 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp. Portions created by ActiveState Tool Corp. are Copyright (C) 2001 ActiveState Tool Corp. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2001 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2001, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsIClassInfo.h"
+
+static nsIClassInfo *_GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIClassInfo);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIClassInfo *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyGetInterfaces(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsIClassInfo *pI = _GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID** iidArray = nsnull;
+ PRUint32 iidCount = 0;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInterfaces(&iidCount, &iidArray);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ PyObject *ret = PyTuple_New(iidCount);
+ if (ret==NULL)
+ return NULL;
+ for (PRUint32 i=0;i<iidCount;i++)
+ PyTuple_SET_ITEM( ret, i, Py_nsIID::PyObjectFromIID(*(iidArray[i])) );
+ return ret;
+}
+
+static PyObject *PyGetHelperForLanguage(PyObject *self, PyObject *args)
+{
+ PRUint32 language = nsIProgrammingLanguage::PYTHON;
+ if (!PyArg_ParseTuple(args, "|i", &language))
+ return NULL;
+ nsIClassInfo *pI = _GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ nsCOMPtr<nsISupports> pi;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetHelperForLanguage(language, getter_AddRefs(pi));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsISupports));
+}
+
+static PyObject *MakeStringOrNone(char *v)
+{
+ if (v)
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromString(v);
+#else
+ return PyUnicode_FromString(v);
+#endif
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#define GETATTR_CHECK_RESULT(nr) if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr)
+
+PyObject *
+Py_nsIClassInfo::getattr(const char *name)
+{
+ nsIClassInfo *pI = _GetI(this);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult nr;
+ PyObject *ret = NULL;
+ if (strcmp(name, "contractID")==0) {
+ char *str_ret = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetContractID(&str_ret);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = MakeStringOrNone(str_ret);
+ nsMemory::Free(str_ret);
+ } else if (strcmp(name, "classDescription")==0) {
+ char *str_ret = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetClassDescription(&str_ret);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = MakeStringOrNone(str_ret);
+ nsMemory::Free(str_ret);
+ } else if (strcmp(name, "classID")==0) {
+ nsIID *iid = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetClassID(&iid);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = Py_nsIID::PyObjectFromIID(*iid);
+ nsMemory::Free(iid);
+ } else if (strcmp(name, "implementationLanguage")==0) {
+ PRUint32 i;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = pI->GetImplementationLanguage(&i);
+ Py_END_ALLOW_THREADS;
+ GETATTR_CHECK_RESULT(nr);
+ ret = PyInt_FromLong(i);
+ } else {
+ ret = Py_nsISupports::getattr(name);
+ }
+ return ret;
+}
+
+int
+Py_nsIClassInfo::setattr(const char *name, PyObject *v)
+{
+ return Py_nsISupports::setattr(name, v);
+
+}
+
+struct PyMethodDef
+PyMethods_IClassInfo[] =
+{
+ { "getInterfaces", PyGetInterfaces, 1},
+ { "GetInterfaces", PyGetInterfaces, 1},
+ { "getHelperForLanguage", PyGetHelperForLanguage, 1},
+ { "GetHelperForLanguage", PyGetHelperForLanguage, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp b/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp
new file mode 100644
index 00000000..c3b89112
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp
@@ -0,0 +1,138 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+static nsIComponentManager *GetI(PyObject *self) {
+ static const nsIID iid = NS_GET_IID(nsIComponentManager);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return NS_STATIC_CAST(nsIComponentManager*, Py_nsISupports::GetI(self));
+}
+
+static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
+{
+ // second arg to CreateInstanceByContractID is a "delegate" - we
+ // aren't sure of the semantics of this yet and it seems rarely used,
+ // so we just punt for now.
+ char *pid, *notyet = NULL;
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "s|zO", &pid, &notyet, &obIID))
+ return NULL;
+ if (notyet != NULL) {
+ PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
+ return NULL;
+ }
+ nsIComponentManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (obIID==NULL)
+ iid = NS_GET_IID(nsISupports);
+ else
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsISupports> pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CreateInstanceByContractID(pid, NULL, iid, getter_AddRefs(pis));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
+}
+
+static PyObject *PyCreateInstance(PyObject *self, PyObject *args)
+{
+ char *notyet = NULL;
+ PyObject *obClassID = NULL, *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "O|zO", &obClassID, &notyet, &obIID))
+ return NULL;
+ if (notyet != NULL) {
+ PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
+ return NULL;
+ }
+ nsIComponentManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID classID;
+ if (!Py_nsIID::IIDFromPyObject(obClassID, &classID))
+ return NULL;
+ nsIID iid;
+ if (obIID==NULL)
+ iid = NS_GET_IID(nsISupports);
+ else
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsISupports> pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CreateInstance(classID, NULL, iid, getter_AddRefs(pis));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
+}
+
+struct PyMethodDef
+PyMethods_IComponentManager[] =
+{
+ { "createInstanceByContractID", PyCreateInstanceByContractID, 1},
+ { "createInstance", PyCreateInstance, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp b/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp
new file mode 100644
index 00000000..7d07d421
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp
@@ -0,0 +1,203 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+static nsIComponentManagerObsolete *GetI(PyObject *self) {
+ static const nsIID iid = NS_GET_IID(nsIComponentManagerObsolete);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIComponentManagerObsolete *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
+{
+ char *pid, *notyet = NULL;
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "s|zO", &pid, &notyet, &obIID))
+ return NULL;
+ if (notyet != NULL) {
+ PyErr_SetString(PyExc_ValueError, "2nd arg must be none");
+ return NULL;
+ }
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (obIID==NULL)
+ iid = NS_GET_IID(nsISupports);
+ else
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsISupports *pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&pis);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE, PR_FALSE);
+}
+
+static PyObject *PyContractIDToClassID(PyObject *self, PyObject *args)
+{
+ char *pid;
+ if (!PyArg_ParseTuple(args, "s", &pid))
+ return NULL;
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->ContractIDToClassID(pid, &iid);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsIID::PyObjectFromIID(iid);
+}
+
+static PyObject *PyCLSIDToContractID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID;
+ if (!PyArg_ParseTuple(args, "O", &obIID))
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ char *ret_pid = nsnull;
+ char *ret_class = nsnull;
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CLSIDToContractID(iid, &ret_class, &ret_pid);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ob_pid = PyString_FromString(ret_pid);
+ PyObject *ob_class = PyString_FromString(ret_class);
+#else
+ PyObject *ob_pid = PyUnicode_FromString(ret_pid);
+ PyObject *ob_class = PyUnicode_FromString(ret_class);
+#endif
+ PyObject *ret = Py_BuildValue("OO", ob_pid, ob_class);
+ nsMemory::Free(ret_pid);
+ nsMemory::Free(ret_class);
+ Py_XDECREF(ob_pid);
+ Py_XDECREF(ob_class);
+ return ret;
+}
+
+static PyObject *PyEnumerateCLSIDs(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIEnumerator *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->EnumerateCLSIDs(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
+}
+
+static PyObject *PyEnumerateContractIDs(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ nsIComponentManagerObsolete *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIEnumerator *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->EnumerateContractIDs(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
+}
+
+struct PyMethodDef
+PyMethods_IComponentManagerObsolete[] =
+{
+ { "CreateInstanceByContractID", PyCreateInstanceByContractID, 1},
+ { "createInstanceByContractID", PyCreateInstanceByContractID, 1},
+ { "EnumerateCLSIDs", PyEnumerateCLSIDs, 1},
+ { "enumerateCLSIDs", PyEnumerateCLSIDs, 1},
+ { "EnumerateContractIDs", PyEnumerateContractIDs, 1},
+ { "enumerateContractIDs", PyEnumerateContractIDs, 1},
+ { "ContractIDToClassID", PyContractIDToClassID, 1},
+ { "contractIDToClassID", PyContractIDToClassID, 1},
+ { "CLSIDToContractID", PyCLSIDToContractID, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp b/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp
new file mode 100644
index 00000000..b196d956
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp
@@ -0,0 +1,235 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIEnumerator.h>
+
+static nsIEnumerator *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIEnumerator);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIEnumerator *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyFirst(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":First"))
+ return NULL;
+
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->First();
+ Py_END_ALLOW_THREADS;
+ return PyInt_FromLong(r);
+}
+
+static PyObject *PyNext(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":Next"))
+ return NULL;
+
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Next();
+ Py_END_ALLOW_THREADS;
+ return PyInt_FromLong(r);
+}
+
+static PyObject *PyCurrentItem(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "|O:CurrentItem", &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsISupports *pRet = nsnull;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->CurrentItem(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ if (obIID) {
+ nsISupports *temp;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pRet->QueryInterface(iid, (void **)&temp);
+ pRet->Release();
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) ) {
+ return PyXPCOM_BuildPyException(r);
+ }
+ pRet = temp;
+ }
+ PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
+ NS_IF_RELEASE(pRet);
+ return ret;
+}
+
+// A method added for Python performance if you really need
+// it. Allows you to fetch a block of objects in one
+// hit, allowing the loop to remain implemented in C.
+static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ int n_wanted;
+ int n_fetched = 0;
+ if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsIEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ // We want to fetch with the thread-lock released,
+ // but this means we can not append to the PyList
+ nsISupports **fetched = new nsISupports*[n_wanted];
+ if (fetched==nsnull) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
+ nsresult r = NS_OK;
+ Py_BEGIN_ALLOW_THREADS;
+ for (;n_fetched<n_wanted;) {
+ nsISupports *pNew;
+ r = pI->CurrentItem(&pNew);
+ if (NS_FAILED(r)) {
+ r = 0; // Normal enum end
+ break;
+ }
+ if (obIID) {
+ nsISupports *temp;
+ r = pNew->QueryInterface(iid, (void **)&temp);
+ pNew->Release();
+ if ( NS_FAILED(r) ) {
+ break;
+ }
+ pNew = temp;
+ }
+ fetched[n_fetched] = pNew;
+ n_fetched++; // must increment before breaking out.
+ if (NS_FAILED(pI->Next()))
+ break; // not an error condition.
+ }
+ Py_END_ALLOW_THREADS;
+ PyObject *ret;
+ if (NS_SUCCEEDED(r)) {
+ ret = PyList_New(n_fetched);
+ if (ret)
+ for (int i=0;i<n_fetched;i++) {
+ PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
+ NS_IF_RELEASE(fetched[i]);
+ PyList_SET_ITEM(ret, i, new_ob);
+ }
+ } else
+ ret = PyXPCOM_BuildPyException(r);
+
+ if ( ret == NULL ) {
+ // Free the objects we consumed.
+ for (int i=0;i<n_fetched;i++)
+ fetched[i]->Release();
+
+ }
+ delete [] fetched;
+ return ret;
+}
+
+static PyObject *PyIsDone(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":IsDone"))
+ return NULL;
+
+ nsIEnumerator *pI = GetI(self);
+ nsresult r;
+ if (pI==NULL)
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->IsDone();
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(r))
+ return PyXPCOM_BuildPyException(r);
+ PyObject *ret = r==NS_OK ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+
+struct PyMethodDef
+PyMethods_IEnumerator[] =
+{
+ { "First", PyFirst, 1},
+ { "first", PyFirst, 1},
+ { "Next", PyNext, 1},
+ { "next", PyNext, 1},
+ { "CurrentItem", PyCurrentItem, 1},
+ { "currentItem", PyCurrentItem, 1},
+ { "IsDone", PyIsDone, 1},
+ { "isDone", PyIsDone, 1},
+ { "FetchBlock", PyFetchBlock, 1},
+ { "fetchBlock", PyFetchBlock, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIID.cpp b/src/libs/xpcom18a4/python/src/PyIID.cpp
new file mode 100644
index 00000000..f24ae20e
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIID.cpp
@@ -0,0 +1,410 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// Py_nsIID.cpp -- IID type for Python/XPCOM
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+//
+// @doc
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+
+nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
+
+// @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
+PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID;
+ PyObject *obBuf;
+ if ( PyArg_ParseTuple(args, "O", &obBuf)) {
+#if PY_MAJOR_VERSION <= 2
+ if (PyBuffer_Check(obBuf)) {
+ PyBufferProcs *pb = NULL;
+ pb = obBuf->ob_type->tp_as_buffer;
+ void *buf = NULL;
+ int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
+#else
+ if (PyObject_CheckBuffer(obBuf)) {
+# ifndef Py_LIMITED_API
+ Py_buffer view;
+ if (PyObject_GetBuffer(obBuf, &view, PyBUF_CONTIG_RO) != 0) {
+ PyErr_Format(PyExc_ValueError, "Could not get contiguous buffer from object");
+ return NULL;
+ }
+ Py_ssize_t size = view.len;
+ const void *buf = view.buf;
+# else /* Py_LIMITED_API - the buffer API is non-existant, from what I can tell */
+ const void *buf = NULL;
+ Py_ssize_t size = 0;
+ if (PyObject_AsReadBuffer(obBuf, &buf, &size) != 0) {
+ PyErr_Format(PyExc_ValueError, "Could not get read-only buffer from object");
+ return NULL;
+ }
+# endif /* Py_LIMITED_API */
+#endif
+ if (size != sizeof(nsIID) || buf==NULL) {
+#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
+ PyBuffer_Release(&view);
+#endif
+#ifdef VBOX
+ PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", (int)sizeof(nsIID));
+#else
+ PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
+#endif
+ return NULL;
+ }
+ nsIID iid;
+ unsigned char const *ptr = (unsigned char const *)buf;
+ iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
+ ptr = ((unsigned char const *)buf) + offsetof(nsIID, m1);
+ iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
+ ptr = ((unsigned char const *)buf) + offsetof(nsIID, m2);
+ iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
+ ptr = ((unsigned char const *)buf) + offsetof(nsIID, m3);
+ for (int i=0;i<8;i++) {
+ iid.m3[i] = *((PRUint8 const *)ptr);
+ ptr += sizeof(PRUint8);
+ }
+#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
+ PyBuffer_Release(&view);
+#endif
+ return new Py_nsIID(iid);
+ }
+ }
+ PyErr_Clear();
+ // @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID.
+ if ( !PyArg_ParseTuple(args, "O", &obIID) )
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ return new Py_nsIID(iid);
+}
+
+/*static*/ PRBool
+Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) {
+ PRBool ok = PR_TRUE;
+ nsIID iid;
+ if (ob==NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "The IID object is invalid!");
+ return PR_FALSE;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(ob)) {
+ ok = iid.Parse(PyString_AsString(ob));
+#else
+ if (PyUnicode_Check(ob)) {
+ ok = iid.Parse(PyUnicode_AsUTF8(ob));
+#endif
+ if (!ok) {
+ PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
+ return PR_FALSE;
+ }
+#ifndef Py_LIMITED_API
+ } else if (ob->ob_type == &type) {
+#else
+ } else if (ob->ob_type == Py_nsIID::GetTypeObject()) {
+#endif
+ iid = ((Py_nsIID *)ob)->m_iid;
+ } else if (PyObject_HasAttrString(ob, "__class__")) {
+ // Get the _iidobj_ attribute
+ PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_");
+ if (use_ob==NULL) {
+ PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects");
+ return PR_FALSE;
+ }
+#ifndef Py_LIMITED_API
+ if (use_ob->ob_type != &type) {
+#else
+ if (use_ob->ob_type != Py_nsIID::GetTypeObject()) {
+#endif
+ Py_DECREF(use_ob);
+ PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
+ return PR_FALSE;
+ }
+ iid = ((Py_nsIID *)use_ob)->m_iid;
+ Py_DECREF(use_ob);
+ } else {
+ PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", PyXPCOM_ObTypeName(ob));
+ ok = PR_FALSE;
+ }
+ if (ok) *pRet = iid;
+ return ok;
+}
+
+
+// @object Py_nsIID|A Python object, representing an IID/CLSID.
+// <nl>All pythoncom functions that return a CLSID/IID will return one of these
+// objects. However, in almost all cases, functions that expect a CLSID/IID
+// as a param will accept either a string object, or a native Py_nsIID object.
+#ifndef Py_LIMITED_API
+PyTypeObject Py_nsIID::type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "IID",
+ sizeof(Py_nsIID),
+ 0,
+ PyTypeMethod_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ PyTypeMethod_getattr, /* tp_getattr */
+ 0, /* tp_setattr */
+#if PY_MAJOR_VERSION <= 2
+ PyTypeMethod_compare, /* tp_compare */
+#else
+ 0, /* reserved */
+#endif
+ PyTypeMethod_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ PyTypeMethod_hash, /* tp_hash */
+ 0, /* tp_call */
+ PyTypeMethod_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ PyTypeMethod_richcompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+};
+#else /* Py_LIMITED_API */
+NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) Py_nsIID::s_pType = NULL;
+
+PyTypeObject *Py_nsIID::GetTypeObject(void)
+{
+ PyTypeObject *pTypeObj = Py_nsIID::s_pType;
+ if (pTypeObj)
+ return pTypeObj;
+
+ PyType_Slot aTypeSlots[] = {
+ { Py_tp_base, &PyType_Type },
+ { Py_tp_dealloc, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_dealloc },
+ { Py_tp_getattr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_getattr },
+ { Py_tp_repr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_repr },
+ { Py_tp_hash, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_hash },
+ { Py_tp_str, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_str },
+ { Py_tp_richcompare, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_richcompare },
+ { 0, NULL } /* terminator */
+ };
+ PyType_Spec TypeSpec = {
+ /* .name: */ "IID",
+ /* .basicsize: */ sizeof(Py_nsIID),
+ /* .itemsize: */ 0,
+ /* .flags: */ 0,
+ /* .slots: */ aTypeSlots,
+ };
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
+
+ pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
+ assert(pTypeObj);
+
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ Py_nsIID::s_pType = pTypeObj;
+ return pTypeObj;
+}
+#endif /* Py_LIMITED_API */
+
+Py_nsIID::Py_nsIID(const nsIID &riid)
+{
+#ifndef Py_LIMITED_API
+ ob_type = &type;
+#else
+ ob_type = GetTypeObject();
+#endif
+#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */
+ PyObject_Init(this, ob_type);
+#else
+ _Py_NewReference(this);
+#endif
+
+ m_iid = riid;
+}
+
+/*static*/PyObject *
+Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
+{
+ Py_nsIID *me = (Py_nsIID *)self;
+ if (strcmp(name, "name")==0) {
+ char *iid_repr = nsnull;
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ if (iim!=nsnull)
+ iim->GetNameForIID(&me->m_iid, &iid_repr);
+ if (iid_repr==nsnull)
+ iid_repr = me->m_iid.ToString();
+ PyObject *ret;
+ if (iid_repr != nsnull) {
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(iid_repr);
+#else
+ ret = PyUnicode_FromString(iid_repr);
+#endif
+ nsMemory::Free(iid_repr);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString("<cant get IID info!>");
+#else
+ ret = PyUnicode_FromString("<cant get IID info!>");
+#endif
+ return ret;
+ }
+ return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
+}
+
+#if PY_MAJOR_VERSION <= 2
+/* static */ int
+Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
+{
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ Py_nsIID *o_iid = (Py_nsIID *)other;
+ int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
+ return rc == 0 ? 0 : (rc < 0 ? -1 : 1);
+}
+#endif
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_richcompare(PyObject *self, PyObject *other, int op)
+{
+ PyObject *result = NULL;
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ Py_nsIID *o_iid = (Py_nsIID *)other;
+ int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
+ switch (op)
+ {
+ case Py_LT:
+ result = rc < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = rc <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = rc == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = rc != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = rc > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = rc >= 0 ? Py_True : Py_False;
+ break;
+ }
+ Py_XINCREF(result);
+ return result;
+}
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_repr(PyObject *self)
+{
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ char buf[256];
+ char *sziid = s_iid->m_iid.ToString();
+#ifdef VBOX
+ snprintf(buf, sizeof(buf), "_xpcom.ID('%s')", sziid);
+#else
+ sprintf(buf, "_xpcom.IID('%s')", sziid);
+#endif
+ nsMemory::Free(sziid);
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromString(buf);
+#else
+ return PyUnicode_FromString(buf);
+#endif
+}
+
+/* static */ PyObject *
+Py_nsIID::PyTypeMethod_str(PyObject *self)
+{
+ Py_nsIID *s_iid = (Py_nsIID *)self;
+ char *sziid = s_iid->m_iid.ToString();
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ret = PyString_FromString(sziid);
+#else
+ PyObject *ret = PyUnicode_FromString(sziid);
+#endif
+ nsMemory::Free(sziid);
+ return ret;
+}
+
+#if PY_VERSION_HEX >= 0x03020000
+/* static */Py_hash_t
+Py_nsIID::PyTypeMethod_hash(PyObject *self)
+#else
+/* static */long
+Py_nsIID::PyTypeMethod_hash(PyObject *self)
+#endif
+{
+ const nsIID &iid = ((Py_nsIID *)self)->m_iid;
+
+#if PY_VERSION_HEX >= 0x03020000
+ Py_hash_t ret = iid.m0 + iid.m1 + iid.m2;
+#else
+ long ret = iid.m0 + iid.m1 + iid.m2;
+#endif
+ for (int i=0;i<7;i++)
+ ret += iid.m3[i];
+ if ( ret == -1 )
+ return -2;
+ return ret;
+}
+
+/*static*/ void
+Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
+{
+ delete (Py_nsIID *)ob;
+}
diff --git a/src/libs/xpcom18a4/python/src/PyIInputStream.cpp b/src/libs/xpcom18a4/python/src/PyIInputStream.cpp
new file mode 100644
index 00000000..b290a3e4
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIInputStream.cpp
@@ -0,0 +1,190 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written September 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsIInputStream.h"
+
+// Prevents us needing to use an nsIScriptableInputStream
+// (and even that can't read binary data!!!)
+
+static nsIInputStream *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIInputStream);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIInputStream *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
+{
+ PRUint32 nread;
+ void *buf;
+#ifndef VBOX /* unsafe cast on 64-bit hosts. */
+ PRUint32 buf_len;
+ if (PyObject_AsWriteBuffer(obBuffer, &buf, (Py_ssize_t *)&buf_len) != 0) {
+#else /* VBOX */
+# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
+ Py_ssize_t buf_len;
+# else
+ int buf_len;
+# endif /* VBOX */
+ if (PyObject_AsWriteBuffer(obBuffer, &buf, &buf_len) != 0) {
+#endif
+ PyErr_Clear();
+ PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
+ return NULL;
+ }
+ if (n==(PRUint32)-1) {
+ n = buf_len;
+ } else {
+ if (n > buf_len) {
+ NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer! Buffer size used.\n");
+ n = buf_len;
+ }
+ }
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Read((char *)buf, n, &nread);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(nread);
+}
+
+static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
+{
+ if (n==(PRUint32)-1) {
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Available(&n);
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(r))
+ return PyXPCOM_BuildPyException(r);
+ }
+ if (n==0) { // mozilla will assert if we alloc zero bytes.
+#if PY_MAJOR_VERSION <= 2
+ return PyBuffer_New(0);
+#else
+ return PyBytes_FromString("");
+#endif
+ }
+ char *buf = (char *)nsMemory::Alloc(n);
+ if (buf==NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ nsresult r;
+ PRUint32 nread;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->Read(buf, n, &nread);
+ Py_END_ALLOW_THREADS;
+ PyObject *rc = NULL;
+ if ( NS_SUCCEEDED(r) ) {
+#if PY_MAJOR_VERSION <= 2
+ rc = PyBuffer_New(nread);
+ if (rc != NULL) {
+ void *ob_buf;
+#ifndef VBOX /* unsafe cast on 64-bit hosts. */
+ PRUint32 buf_len;
+ if (PyObject_AsWriteBuffer(rc, &ob_buf, (Py_ssize_t *)&buf_len) != 0) {
+#else /* VBOX */
+# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
+ Py_ssize_t buf_len;
+# else
+ int buf_len;
+# endif /* VBOX */
+ if (PyObject_AsWriteBuffer(rc, &ob_buf, &buf_len) != 0) {
+#endif
+ // should never fail - we just created it!
+ return NULL;
+ }
+ if (buf_len != nread) {
+ PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
+ return NULL;
+ }
+ memcpy(ob_buf, buf, nread);
+ }
+#else
+ rc = PyBytes_FromStringAndSize(buf, nread);
+#endif
+ } else
+ PyXPCOM_BuildPyException(r);
+ nsMemory::Free(buf);
+ return rc;
+}
+
+static PyObject *PyRead(PyObject *self, PyObject *args)
+{
+ PyObject *obBuffer = NULL;
+ PRUint32 n = (PRUint32)-1;
+
+ nsIInputStream *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+ if (PyArg_ParseTuple(args, "|i", (int *)&n))
+ // This worked - no args, or just an int.
+ return DoPyRead_Size(pI, n);
+ // try our other supported arg format.
+ PyErr_Clear();
+ if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
+ PyErr_Clear();
+ PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
+ return NULL;
+ }
+ return DoPyRead_Buffer(pI, obBuffer, n);
+}
+
+
+struct PyMethodDef
+PyMethods_IInputStream[] =
+{
+ { "read", PyRead, 1},
+ // The rest are handled as normal
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp b/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp
new file mode 100644
index 00000000..7e1a9466
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp
@@ -0,0 +1,431 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+
+
+static nsIInterfaceInfo *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIInterfaceInfo);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIInterfaceInfo *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyGetName(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetName"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ char *name;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetName(&name);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ret = PyString_FromString(name);
+#else
+ PyObject *ret = PyUnicode_FromString(name);
+#endif
+ nsMemory::Free(name);
+ return ret;
+}
+
+static PyObject *PyGetIID(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetIID"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID *iid_ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInterfaceIID(&iid_ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
+ nsMemory::Free(iid_ret);
+ return ret;
+}
+
+static PyObject *PyIsScriptable(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":IsScriptable"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRBool b_ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->IsScriptable(&b_ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(b_ret);
+}
+
+static PyObject *PyGetParent(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetParent"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsCOMPtr<nsIInterfaceInfo> pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetParent(getter_AddRefs(pRet));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
+}
+
+static PyObject *PyGetMethodCount(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetMethodCount"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRUint16 ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetMethodCount(&ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(ret);
+}
+
+
+static PyObject *PyGetConstantCount(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":GetConstantCount"))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRUint16 ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetConstantCount(&ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *PyGetMethodInfo(PyObject *self, PyObject *args)
+{
+ PRUint16 index;
+ if (!PyArg_ParseTuple(args, "h:GetMethodInfo", &index))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ PRUint16 nmethods;
+ pI->GetMethodCount(&nmethods);
+ if (index>=nmethods) {
+ PyErr_SetString(PyExc_ValueError, "The method index is out of range");
+ return NULL;
+ }
+
+ const nsXPTMethodInfo *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetMethodInfo(index, &pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyObject_FromXPTMethodDescriptor(pRet);
+}
+
+static PyObject *PyGetMethodInfoForName(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s:GetMethodInfoForName", &name))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ const nsXPTMethodInfo *pRet;
+ PRUint16 index;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetMethodInfoForName(name, &index, &pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ PyObject *ret_i = PyObject_FromXPTMethodDescriptor(pRet);
+ if (ret_i==NULL)
+ return NULL;
+ PyObject *real_ret = Py_BuildValue("iO", (int)index, ret_i);
+ Py_DECREF(ret_i);
+ return real_ret;
+}
+
+
+static PyObject *PyGetConstant(PyObject *self, PyObject *args)
+{
+ PRUint16 index;
+ if (!PyArg_ParseTuple(args, "h:GetConstant", &index))
+ return NULL;
+
+ nsIInterfaceInfo *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ const nsXPTConstant *pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetConstant(index, &pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyObject_FromXPTConstant(pRet);
+}
+
+static PRBool __GetMethodInfoHelper(nsIInterfaceInfo *pii, int mi, int pi, const nsXPTMethodInfo **ppmi)
+{
+ PRUint16 nmethods=0;
+ pii->GetMethodCount(&nmethods);
+ if (mi<0 || mi>=nmethods) {
+ PyErr_SetString(PyExc_ValueError, "The method index is out of range");
+ return PR_FALSE;
+ }
+ const nsXPTMethodInfo *pmi;
+ nsresult r = pii->GetMethodInfo(mi, &pmi);
+ if ( NS_FAILED(r) ) {
+ PyXPCOM_BuildPyException(r);
+ return PR_FALSE;
+ }
+
+ int nparams=0;
+ nparams = pmi->GetParamCount();
+ if (pi<0 || pi>=nparams) {
+ PyErr_SetString(PyExc_ValueError, "The param index is out of range");
+ return PR_FALSE;
+ }
+ *ppmi = pmi;
+ return PR_TRUE;
+}
+
+static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi;
+ if (!PyArg_ParseTuple(args, "hh:GetInfoForParam", &mi, &pi))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsCOMPtr<nsIInterfaceInfo> pnewii;
+ nsresult n = pii->GetInfoForParam(mi, &param_info, getter_AddRefs(pnewii));
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo));
+}
+
+static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi;
+ if (!PyArg_ParseTuple(args, "hh:GetIIDForParam", &mi, &pi))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsIID *piid;
+ nsresult n = pii->GetIIDForParam(mi, &param_info, &piid);
+ if (NS_FAILED(n) || piid==nsnull)
+ return PyXPCOM_BuildPyException(n);
+ PyObject *rc = Py_nsIID::PyObjectFromIID(*piid);
+ nsMemory::Free((void*)piid);
+ return rc;
+}
+
+static PyObject *PyGetTypeForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi, dim;
+ if (!PyArg_ParseTuple(args, "hhh:GetTypeForParam", &mi, &pi, &dim))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ nsXPTType datumType;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetTypeForParam(mi, &param_info, dim, &datumType);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyObject_FromXPTType(&datumType);
+}
+
+static PyObject *PyGetSizeIsArgNumberForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi, dim;
+ if (!PyArg_ParseTuple(args, "hhh:GetSizeIsArgNumberForParam", &mi, &pi, &dim))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ PRUint8 ret;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetSizeIsArgNumberForParam(mi, &param_info, dim, &ret);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *PyGetLengthIsArgNumberForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi, dim;
+ if (!PyArg_ParseTuple(args, "hhh:GetLengthIsArgNumberForParam", &mi, &pi, &dim))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ PRUint8 ret;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetLengthIsArgNumberForParam(mi, &param_info, dim, &ret);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyInt_FromLong(ret);
+}
+
+static PyObject *PyGetInterfaceIsArgNumberForParam(PyObject *self, PyObject *args)
+{
+ nsIInterfaceInfo *pii = GetI(self);
+ if (pii==NULL)
+ return NULL;
+ PRUint16 mi, pi;
+ if (!PyArg_ParseTuple(args, "hhh:GetInterfaceIsArgNumberForParam", &mi, &pi))
+ return NULL;
+ const nsXPTMethodInfo *pmi;
+ if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
+ return NULL;
+ PRUint8 ret;
+ const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
+ nsresult n = pii->GetInterfaceIsArgNumberForParam(mi, &param_info, &ret);
+ if (NS_FAILED(n))
+ return PyXPCOM_BuildPyException(n);
+ return PyInt_FromLong(ret);
+}
+
+struct PyMethodDef
+PyMethods_IInterfaceInfo[] =
+{
+ { "GetName", PyGetName, 1},
+ { "GetIID", PyGetIID, 1},
+ { "IsScriptable", PyIsScriptable, 1},
+ { "GetParent", PyGetParent, 1},
+ { "GetMethodCount", PyGetMethodCount, 1},
+ { "GetConstantCount", PyGetConstantCount, 1},
+ { "GetMethodInfo", PyGetMethodInfo, 1},
+ { "GetMethodInfoForName", PyGetMethodInfoForName, 1},
+ { "GetConstant", PyGetConstant, 1},
+ { "GetInfoForParam", PyGetInfoForParam, 1},
+ { "GetIIDForParam", PyGetIIDForParam, 1},
+ { "GetTypeForParam", PyGetTypeForParam, 1},
+ { "GetSizeIsArgNumberForParam", PyGetSizeIsArgNumberForParam, 1},
+ { "GetLengthIsArgNumberForParam", PyGetLengthIsArgNumberForParam, 1},
+ { "GetInterfaceIsArgNumberForParam", PyGetInterfaceIsArgNumberForParam, 1},
+ {NULL}
+};
+
+/*
+ NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) = 0;
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) = 0;
+ NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) = 0;
+ NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) = 0;
+ NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) = 0;
+ NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) = 0;
+ NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
+ NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0;
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) = 0;
+
+*/
diff --git a/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp b/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp
new file mode 100644
index 00000000..7c629413
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp
@@ -0,0 +1,206 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+
+static nsIInterfaceInfoManager *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIInterfaceInfoManager);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIInterfaceInfoManager *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "O", &obIID))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsIInterfaceInfo> pi;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInfoForIID(&iid, getter_AddRefs(pi));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ nsIID new_iid = NS_GET_IID(nsIInterfaceInfo);
+ // Can not auto-wrap the interface info manager as it is critical to
+ // building the support we need for autowrap.
+ return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE);
+}
+
+static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsCOMPtr<nsIInterfaceInfo> pi;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetInfoForName(name, getter_AddRefs(pi));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ // Can not auto-wrap the interface info manager as it is critical to
+ // building the support we need for autowrap.
+ return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
+}
+
+static PyObject *PyGetNameForIID(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "O", &obIID))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ char *ret_name = NULL;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetNameForIID(&iid, &ret_name);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+#if PY_MAJOR_VERSION <= 2
+ PyObject *ret = PyString_FromString(ret_name);
+#else
+ PyObject *ret = PyUnicode_FromString(ret_name);
+#endif
+ nsMemory::Free(ret_name);
+ return ret;
+}
+
+static PyObject *PyGetIIDForName(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsIID *iid_ret;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetIIDForName(name, &iid_ret);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret);
+ nsMemory::Free(iid_ret);
+ return ret;
+}
+
+static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ nsIInterfaceInfoManager *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsCOMPtr<nsIEnumerator> pRet;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->EnumerateInterfaces(getter_AddRefs(pRet));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator));
+}
+
+// TODO:
+// void autoRegisterInterfaces();
+
+PyMethodDef
+PyMethods_IInterfaceInfoManager[] =
+{
+ { "GetInfoForIID", PyGetInfoForIID, 1},
+ { "getInfoForIID", PyGetInfoForIID, 1},
+ { "GetInfoForName", PyGetInfoForName, 1},
+ { "getInfoForName", PyGetInfoForName, 1},
+ { "GetIIDForName", PyGetIIDForName, 1},
+ { "getIIDForName", PyGetIIDForName, 1},
+ { "GetNameForIID", PyGetNameForIID, 1},
+ { "getNameForIID", PyGetNameForIID, 1},
+ { "EnumerateInterfaces", PyEnumerateInterfaces, 1},
+ { "enumerateInterfaces", PyEnumerateInterfaces, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp b/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp
new file mode 100644
index 00000000..b94d8eb2
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp
@@ -0,0 +1,202 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsISimpleEnumerator.h>
+
+static nsISimpleEnumerator *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsISimpleEnumerator);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsISimpleEnumerator *)Py_nsISupports::GetI(self);
+}
+
+
+static PyObject *PyHasMoreElements(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":HasMoreElements"))
+ return NULL;
+
+ nsISimpleEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsresult r;
+ PRBool more;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->HasMoreElements(&more);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ return PyInt_FromLong(more);
+}
+
+static PyObject *PyGetNext(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ if (!PyArg_ParseTuple(args, "|O:GetNext", &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsISimpleEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ nsISupports *pRet = nsnull;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pI->GetNext(&pRet);
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ if (obIID) {
+ nsISupports *temp;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pRet->QueryInterface(iid, (void **)&temp);
+ pRet->Release();
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) ) {
+ return PyXPCOM_BuildPyException(r);
+ }
+ pRet = temp;
+ }
+ PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
+ NS_IF_RELEASE(pRet);
+ return ret;
+}
+
+// A method added for Python performance if you really need
+// it. Allows you to fetch a block of objects in one
+// hit, allowing the loop to remain implemented in C.
+static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
+{
+ PyObject *obIID = NULL;
+ int n_wanted;
+ int n_fetched = 0;
+ if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID))
+ return NULL;
+
+ nsIID iid(NS_GET_IID(nsISupports));
+ if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsISimpleEnumerator *pI = GetI(self);
+ if (pI==NULL)
+ return NULL;
+
+ // We want to fetch with the thread-lock released,
+ // but this means we can not append to the PyList
+ nsISupports **fetched = new nsISupports*[n_wanted];
+ if (fetched==nsnull) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ memset(fetched, 0, sizeof(nsISupports *) * n_wanted);
+ nsresult r = NS_OK;
+ PRBool more;
+ Py_BEGIN_ALLOW_THREADS;
+ for (;n_fetched<n_wanted;) {
+ r = pI->HasMoreElements(&more);
+ if (NS_FAILED(r))
+ break; // this _is_ an error!
+ if (!more)
+ break; // Normal enum end.
+ nsISupports *pNew;
+ r = pI->GetNext(&pNew);
+ if (NS_FAILED(r)) // IS an error
+ break;
+ if (obIID) {
+ nsISupports *temp;
+ r = pNew->QueryInterface(iid, (void **)&temp);
+ pNew->Release();
+ if ( NS_FAILED(r) ) {
+ break;
+ }
+ pNew = temp;
+ }
+ fetched[n_fetched] = pNew;
+ n_fetched++;
+ }
+ Py_END_ALLOW_THREADS;
+ PyObject *ret;
+ if (NS_SUCCEEDED(r)) {
+ ret = PyList_New(n_fetched);
+ if (ret)
+ for (int i=0;i<n_fetched;i++) {
+ PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
+ NS_IF_RELEASE(fetched[i]);
+ PyList_SET_ITEM(ret, i, new_ob);
+ }
+ } else
+ ret = PyXPCOM_BuildPyException(r);
+
+ if ( ret == NULL ) {
+ // Free the objects we consumed.
+ for (int i=0;i<n_fetched;i++)
+ fetched[i]->Release();
+
+ }
+ delete [] fetched;
+ return ret;
+}
+
+
+struct PyMethodDef
+PyMethods_ISimpleEnumerator[] =
+{
+ { "HasMoreElements", PyHasMoreElements, 1},
+ { "hasMoreElements", PyHasMoreElements, 1},
+ { "GetNext", PyGetNext, 1},
+ { "getNext", PyGetNext, 1},
+ { "FetchBlock", PyFetchBlock, 1},
+ { "fetchBlock", PyFetchBlock, 1},
+ {NULL}
+};
diff --git a/src/libs/xpcom18a4/python/src/PyISupports.cpp b/src/libs/xpcom18a4/python/src/PyISupports.cpp
new file mode 100644
index 00000000..84504038
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyISupports.cpp
@@ -0,0 +1,621 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include "nsISupportsPrimitives.h"
+
+static PRInt32 cInterfaces=0;
+static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!!
+
+#ifdef VBOX_DEBUG_LIFETIMES
+# include <iprt/log.h>
+# include <iprt/stream.h>
+
+/*static*/ RTLISTNODE Py_nsISupports::g_List;
+/*static*/ RTONCE Py_nsISupports::g_Once = RTONCE_INITIALIZER;
+/*static*/ RTCRITSECT Py_nsISupports::g_CritSect;
+
+/*static*/ DECLCALLBACK(int32_t)
+Py_nsISupports::initOnceCallback(void *pvUser1)
+{
+ NOREF(pvUser1);
+ RTListInit(&g_List);
+ return RTCritSectInit(&g_CritSect);
+}
+
+/*static*/ void
+Py_nsISupports::dumpList(void)
+{
+ RTOnce(&g_Once, initOnceCallback, NULL);
+ RTCritSectEnter(&g_CritSect);
+
+ uint32_t i = 0;
+ Py_nsISupports *pCur;
+ RTListForEach(&g_List, pCur, Py_nsISupports, m_ListEntry)
+ {
+ nsISupports *pISup = pCur->m_obj;
+ PyXPCOM_LogWarning("#%u: %p iid=%RTuuid obj=%p", i, pCur, &pCur->m_iid, pISup);
+ i++;
+ }
+
+ RTCritSectLeave(&g_CritSect);
+}
+
+/*static*/ void
+Py_nsISupports::dumpListToStdOut()
+{
+ RTOnce(&g_Once, initOnceCallback, NULL);
+ RTCritSectEnter(&g_CritSect);
+
+ uint32_t i = 0;
+ Py_nsISupports *pCur;
+ RTListForEach(&g_List, pCur, Py_nsISupports, m_ListEntry)
+ {
+ nsISupports *pISup = pCur->m_obj;
+ RTPrintf("#%u: %p iid=%RTuuid obj=%p\n", i, pCur, &pCur->m_iid, pISup);
+ i++;
+ }
+
+ RTCritSectLeave(&g_CritSect);
+}
+
+PRInt32
+_PyXPCOM_DumpInterfaces(void)
+{
+ Py_nsISupports::dumpListToStdOut();
+ return NS_OK;
+}
+
+#endif /* _DEBUG_LIFETIMES */
+
+
+
+PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
+ const nsIID &iid,
+ PRBool bMakeNicePyObject /*= PR_TRUE */)
+{
+ return Py_nsISupports::PyObjectFromInterface(aInterface, iid,
+ bMakeNicePyObject);
+}
+
+PRInt32
+_PyXPCOM_GetInterfaceCount(void)
+{
+ return cInterfaces;
+}
+
+#ifndef Py_LIMITED_API
+Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type)
+#else
+Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyXPCOM_TypeObject *this_type)
+#endif
+{
+#ifndef Py_LIMITED_API
+ ob_type = this_type;
+#else
+ ob_type = this_type->m_pTypeObj;
+ m_pMyTypeObj = this_type;
+#endif
+ m_obj = punk;
+ m_iid = iid;
+ // refcnt of object managed by caller.
+ PR_AtomicIncrement(&cInterfaces);
+ PyXPCOM_DLLAddRef();
+#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */
+ PyObject_Init(this, ob_type);
+#else
+ _Py_NewReference(this);
+#endif
+
+#ifdef VBOX_DEBUG_LIFETIMES
+ RTOnce(&g_Once, initOnceCallback, NULL);
+ RTCritSectEnter(&g_CritSect);
+ RTListAppend(&g_List, &m_ListEntry);
+ RTCritSectLeave(&g_CritSect);
+ PyXPCOM_LogWarning("Creating %p: iid=%RTuuid obj=%p", this, &m_iid, punk);
+#endif
+}
+
+Py_nsISupports::~Py_nsISupports()
+{
+#ifdef VBOX_DEBUG_LIFETIMES
+ RTCritSectEnter(&g_CritSect);
+ nsISupports *punk = m_obj;
+ RTListNodeRemove(&m_ListEntry);
+ RTCritSectLeave(&g_CritSect);
+ PyXPCOM_LogWarning("Destroying %p: iid=%RTuuid obj=%p", this, &m_iid, punk);
+#endif
+
+ SafeRelease(this);
+ PR_AtomicDecrement(&cInterfaces);
+ PyXPCOM_DLLRelease();
+}
+
+/*static*/ nsISupports *
+Py_nsISupports::GetI(PyObject *self, nsIID *ret_iid)
+{
+ if (self==NULL) {
+ PyErr_SetString(PyExc_ValueError, "The Python object is invalid");
+ return NULL;
+ }
+ Py_nsISupports *pis = (Py_nsISupports *)self;
+ if (pis->m_obj==NULL) {
+ // This should never be able to happen.
+ PyErr_SetString(PyExc_ValueError, "Internal Error - The XPCOM object has been released.");
+ return NULL;
+ }
+ if (ret_iid)
+ *ret_iid = pis->m_iid;
+ return pis->m_obj;
+}
+
+/*static*/ void
+Py_nsISupports::SafeRelease(Py_nsISupports *ob)
+{
+ if (!ob)
+ return;
+ if (ob->m_obj)
+ {
+ Py_BEGIN_ALLOW_THREADS;
+ ob->m_obj = nsnull;
+ Py_END_ALLOW_THREADS;
+ }
+}
+
+/* virtual */ PyObject *
+Py_nsISupports::getattr(const char *name)
+{
+ if (strcmp(name, "IID")==0)
+ return Py_nsIID::PyObjectFromIID( m_iid );
+
+ // Support for __unicode__ until we get a tp_unicode slot.
+ if (strcmp(name, "__unicode__")==0) {
+ nsresult rv;
+ PRUnichar *val = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ { // scope to kill pointer while thread-lock released.
+ nsCOMPtr<nsISupportsString> ss( do_QueryInterface(m_obj, &rv ));
+ if (NS_SUCCEEDED(rv))
+ rv = ss->ToString(&val);
+ } // end-scope
+ Py_END_ALLOW_THREADS;
+ PyObject *ret = NS_FAILED(rv) ?
+ PyXPCOM_BuildPyException(rv) :
+ PyObject_FromNSString(val);
+ if (val) nsMemory::Free(val);
+ return ret;
+ }
+#ifndef Py_LIMITED_API
+ PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type;
+#else
+ PyXPCOM_TypeObject *this_type = m_pMyTypeObj;
+#endif
+#if PY_MAJOR_VERSION <= 2
+ return Py_FindMethodInChain(&this_type->chain, this, (char *)name);
+#else
+ PyMethodChain *chain = &this_type->chain;
+ if (name[0] == '_' && name[1] == '_') {
+# ifndef Py_LIMITED_API /** @todo ? */
+ if (!strcmp(name, "__doc__")) {
+ const char *doc = ob_type->tp_doc;
+ if (doc)
+ return PyUnicode_FromString(doc);
+ }
+# endif
+ }
+ while (chain) {
+ PyMethodDef *ml = chain->methods;
+ for (; ml->ml_name; ml++) {
+ if (!strcmp(name, ml->ml_name))
+ return PyCFunction_New(ml, this);
+ }
+ chain = chain->link;
+ }
+ PyErr_SetString(PyExc_AttributeError, name);
+ return NULL;
+#endif
+}
+
+/* virtual */ int
+Py_nsISupports::setattr(const char *name, PyObject *v)
+{
+ char buf[128];
+#ifdef VBOX
+ snprintf(buf, sizeof(buf), "%s has read-only attributes", PyXPCOM_ObTypeName(this) );
+#else
+ sprintf(buf, "%s has read-only attributes", PyXPCOM_ObTypeName(this) );
+#endif
+ PyErr_SetString(PyExc_TypeError, buf);
+ return -1;
+}
+
+/*static*/ Py_nsISupports *
+Py_nsISupports::Constructor(nsISupports *pInitObj, const nsIID &iid)
+{
+ return new Py_nsISupports(pInitObj,
+ iid,
+ type);
+}
+
+PRBool
+Py_nsISupports::InterfaceFromPyISupports(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppv)
+{
+ nsISupports *pis;
+ PRBool rc = PR_FALSE;
+ if ( !Check(ob) )
+ {
+ PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", PyXPCOM_ObTypeName(ob));
+ goto done;
+ }
+ nsIID already_iid;
+ pis = GetI(ob, &already_iid);
+ if ( !pis )
+ goto done; /* exception was set by GetI() */
+ /* note: we don't (yet) explicitly hold a reference to pis */
+ if (iid.Equals(Py_nsIID_NULL)) {
+ // a bit of a hack - we are asking for the arbitary interface
+ // wrapped by this object, not some other specific interface -
+ // so no QI, just an AddRef();
+ Py_BEGIN_ALLOW_THREADS
+ pis->AddRef();
+ Py_END_ALLOW_THREADS
+ *ppv = pis;
+ } else {
+ // specific interface requested - if it is not already the
+ // specific interface, QI for it and discard pis.
+ if (iid.Equals(already_iid)) {
+ *ppv = pis;
+ pis->AddRef();
+ } else {
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS
+ r = pis->QueryInterface(iid, (void **)ppv);
+ Py_END_ALLOW_THREADS
+ if ( NS_FAILED(r) )
+ {
+ PyXPCOM_BuildPyException(r);
+ goto done;
+ }
+ /* note: the QI added a ref for the return value */
+ }
+ }
+ rc = PR_TRUE;
+done:
+ return rc;
+}
+
+PRBool
+Py_nsISupports::InterfaceFromPyObject(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppv,
+ PRBool bNoneOK,
+ PRBool bTryAutoWrap /* = PR_TRUE */)
+{
+ if ( ob == NULL )
+ {
+ // don't overwrite an error message
+ if ( !PyErr_Occurred() )
+ PyErr_SetString(PyExc_TypeError, "The Python object is invalid");
+ return PR_FALSE;
+ }
+ if ( ob == Py_None )
+ {
+ if ( bNoneOK )
+ {
+ *ppv = NULL;
+ return PR_TRUE;
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context");
+ return PR_FALSE;
+ }
+ }
+
+ // support nsIVariant
+ if (iid.Equals(NS_GET_IID(nsIVariant)) || iid.Equals(NS_GET_IID(nsIWritableVariant))) {
+ // Check it is not already nsIVariant
+ if (PyObject_HasAttrString(ob, "__class__")) {
+ PyObject *sub_ob = PyObject_GetAttrString(ob, "_comobj_");
+ if (sub_ob==NULL) {
+ PyErr_Clear();
+ } else {
+ if (InterfaceFromPyISupports(sub_ob, iid, ppv)) {
+ Py_DECREF(sub_ob);
+ return PR_TRUE;
+ }
+ PyErr_Clear();
+ Py_DECREF(sub_ob);
+ }
+ }
+ nsresult nr = PyObject_AsVariant(ob, (nsIVariant **)ppv);
+ if (NS_FAILED(nr)) {
+ PyXPCOM_BuildPyException(nr);
+ return PR_FALSE;
+ }
+ NS_ASSERTION(ppv != nsnull, "PyObject_AsVariant worked but gave null!");
+ return PR_TRUE;
+ }
+ // end of variant support.
+
+ if (PyObject_HasAttrString(ob, "__class__")) {
+ // Get the _comobj_ attribute
+ PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_");
+ if (use_ob==NULL) {
+ PyErr_Clear();
+ if (bTryAutoWrap)
+ // Try and auto-wrap it - errors will leave Py exception set,
+ return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv);
+ PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XPCOM object");
+ return PR_FALSE;
+ } else
+ ob = use_ob;
+
+ } else {
+ Py_INCREF(ob);
+ }
+ PRBool rc = InterfaceFromPyISupports(ob, iid, ppv);
+ Py_DECREF(ob);
+ return rc;
+}
+
+
+// Interface conversions
+/*static*/void
+#ifndef Py_LIMITED_API
+Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
+#else
+Py_nsISupports::RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t)
+#endif
+{
+ if (mapIIDToType==NULL)
+ mapIIDToType = PyDict_New();
+
+ if (mapIIDToType) {
+ PyObject *key = Py_nsIID::PyObjectFromIID(iid);
+ if (key)
+ PyDict_SetItem(mapIIDToType, key, (PyObject *)t);
+ Py_XDECREF(key);
+ }
+}
+
+/*static */PyObject *
+Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
+ const nsIID &riid,
+ PRBool bMakeNicePyObject, /* = PR_TRUE */
+ PRBool bIsInternalCall /* = PR_FALSE */)
+{
+ // Quick exit.
+ if (pis==NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ if (!bIsInternalCall) {
+#ifdef NS_DEBUG
+ nsISupports *queryResult = nsnull;
+ Py_BEGIN_ALLOW_THREADS;
+ pis->QueryInterface(riid, (void **)&queryResult);
+ Py_END_ALLOW_THREADS;
+ NS_ASSERTION(queryResult == pis, "QueryInterface needed");
+ NS_IF_RELEASE(queryResult);
+#endif
+ }
+
+#ifndef Py_LIMITED_API
+ PyTypeObject *createType = NULL;
+#else
+ PyXPCOM_TypeObject *createType = NULL;
+#endif
+ // If the IID is for nsISupports, dont bother with
+ // a map lookup as we know the type!
+ if (!riid.Equals(NS_GET_IID(nsISupports))) {
+ // Look up the map
+ PyObject *obiid = Py_nsIID::PyObjectFromIID(riid);
+ if (!obiid) return NULL;
+
+ if (mapIIDToType != NULL)
+#ifndef Py_LIMITED_API
+ createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid);
+#else
+ createType = (PyXPCOM_TypeObject *)PyDict_GetItem(mapIIDToType, obiid);
+#endif
+ Py_DECREF(obiid);
+ }
+ if (createType==NULL)
+ createType = Py_nsISupports::type;
+#ifndef Py_LIMITED_API
+ // Check it is indeed one of our types.
+ if (!PyXPCOM_TypeObject::IsType(createType)) {
+ PyErr_SetString(PyExc_RuntimeError, "The type map is invalid");
+ return NULL;
+ }
+ // we can now safely cast the thing to a PyComTypeObject and use it
+ PyXPCOM_TypeObject *myCreateType = (PyXPCOM_TypeObject *)createType;
+#else /* Since the mapIIDToType is only updated by us, there should be no need for the above. */
+ PyXPCOM_TypeObject * const myCreateType = createType;
+#endif
+ if (myCreateType->ctor==NULL) {
+ PyErr_SetString(PyExc_TypeError, "The type does not declare a PyCom constructor");
+ return NULL;
+ }
+
+ Py_nsISupports *ret = (*myCreateType->ctor)(pis, riid);
+#ifdef _DEBUG_LIFETIMES
+ PyXPCOM_LogF("XPCOM Object created at 0x%0xld, nsISupports at 0x%0xld",
+ ret, ret->m_obj);
+#endif
+ if (ret && bMakeNicePyObject)
+ return MakeDefaultWrapper(ret, riid);
+ return ret;
+}
+
+// Call back into Python, passing a raw nsIInterface object, getting back
+// the object to actually pass to Python.
+PyObject *
+Py_nsISupports::MakeDefaultWrapper(PyObject *pyis,
+ const nsIID &iid)
+{
+ NS_PRECONDITION(pyis, "NULL pyobject!");
+ PyObject *obIID = NULL;
+ PyObject *args = NULL;
+ PyObject *mod = NULL;
+ PyObject *ret = NULL;
+
+ obIID = Py_nsIID::PyObjectFromIID(iid);
+ if (obIID==NULL)
+ goto done;
+
+ if (g_obFuncMakeInterfaceCount==NULL) {
+ PyObject *mod = PyImport_ImportModule("xpcom.client");
+ if (mod)
+ g_obFuncMakeInterfaceCount = PyObject_GetAttrString(mod, "MakeInterfaceResult");
+ Py_XDECREF(mod);
+ }
+ if (g_obFuncMakeInterfaceCount==NULL) goto done;
+
+ args = Py_BuildValue("OO", pyis, obIID);
+ if (args==NULL) goto done;
+ ret = PyEval_CallObject(g_obFuncMakeInterfaceCount, args);
+done:
+ if (PyErr_Occurred()) {
+ NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
+ PyXPCOM_LogError("Creating an interface object to be used as a result failed\n");
+ PyErr_Clear();
+ }
+ Py_XDECREF(mod);
+ Py_XDECREF(args);
+ Py_XDECREF(obIID);
+ if (ret==NULL) // eek - error - return the original with no refcount mod.
+ ret = pyis;
+ else
+ // no error - decref the old object
+ Py_DECREF(pyis);
+ // return our obISupports. If NULL, we are really hosed and nothing we can do.
+ return ret;
+}
+
+// @pymethod <o Py_nsISupports>|Py_nsISupports|QueryInterface|Queries an object for a specific interface.
+PyObject *
+Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
+{
+ PyObject *obiid;
+ int bWrap = 1;
+ // @pyparm IID|iid||The IID requested.
+ // @rdesc The result is always a <o Py_nsISupports> object.
+ // Any error (including E_NOINTERFACE) will generate a <o com_error> exception.
+ if (!PyArg_ParseTuple(args, "O|i:QueryInterface", &obiid, &bWrap))
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obiid, &iid))
+ return NULL;
+
+ nsISupports *pMyIS = GetI(self);
+ if (pMyIS==NULL) return NULL;
+
+ // Optimization, If we already wrap the IID, just return
+ // ourself.
+ if (!bWrap && iid.Equals(((Py_nsISupports *)self)->m_iid)) {
+ Py_INCREF(self);
+ return self;
+ }
+
+ nsCOMPtr<nsISupports> pis;
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = pMyIS->QueryInterface(iid, getter_AddRefs(pis));
+ Py_END_ALLOW_THREADS;
+
+ /* Note that this failure may include E_NOINTERFACE */
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ /* Return a type based on the IID (with no extra ref) */
+ return ((Py_nsISupports *)self)->MakeInterfaceResult(pis, iid, (PRBool)bWrap);
+}
+
+
+#ifdef VBOX
+static PyObject *
+QueryErrorObject(PyObject *self, PyObject *args)
+{
+ nsresult rc = 0;
+
+ if (!PyArg_ParseTuple(args, "i", &rc))
+ return NULL;
+
+ return PyXPCOM_BuildErrorMessage(rc);
+}
+#endif
+
+// @object Py_nsISupports|The base object for all PythonCOM objects. Wraps a COM nsISupports interface.
+/*static*/ struct PyMethodDef
+Py_nsISupports::methods[] =
+{
+ { "queryInterface", Py_nsISupports::QueryInterface, 1, "Queries the object for an interface."},
+ { "QueryInterface", Py_nsISupports::QueryInterface, 1, "An alias for queryInterface."},
+#ifdef VBOX
+ { "QueryErrorObject", QueryErrorObject, 1, "Query an error object for given status code."},
+#endif
+ {NULL}
+};
+
+/*static*/void Py_nsISupports::InitType(void)
+{
+ type = new PyXPCOM_TypeObject(
+ "nsISupports",
+ NULL,
+ sizeof(Py_nsISupports),
+ methods,
+ Constructor);
+}
+
+PyXPCOM_TypeObject *Py_nsISupports::type = NULL;
+PyObject *Py_nsISupports::mapIIDToType = NULL;
diff --git a/src/libs/xpcom18a4/python/src/PyIVariant.cpp b/src/libs/xpcom18a4/python/src/PyIVariant.cpp
new file mode 100644
index 00000000..cd9f79c4
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyIVariant.cpp
@@ -0,0 +1,231 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * Mark Hammond.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// This code is part of the XPCOM extensions for Python.
+//
+// Written April 2002
+
+#include "PyXPCOM_std.h"
+#include "nsIVariant.h"
+
+// Prevents us needing to use an nsIScriptableInputStream
+// (and even that can't read binary data!!!)
+
+static nsIVariant *GetI(PyObject *self) {
+ nsIID iid = NS_GET_IID(nsIVariant);
+
+ if (!Py_nsISupports::Check(self, iid)) {
+ PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
+ return NULL;
+ }
+ return (nsIVariant *)Py_nsISupports::GetI(self);
+}
+
+static PyObject *MyBool( PRBool v) {
+ PyObject *ret = v ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+static PyObject *MyChar( char c) {
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromStringAndSize(&c, 1);
+#else
+ return PyUnicode_FromStringAndSize(&c, 1);
+#endif
+}
+static PyObject *MyUChar( PRUnichar c) {
+ return PyObject_FromNSString( &c, 1);
+}
+static PyObject *MyUnicode( PRUnichar *p) {
+ return PyObject_FromNSString(p);
+}
+
+#define GET_SIMPLE(Type, FuncGet, FuncConvert) \
+static PyObject *FuncGet(PyObject *self, PyObject *args) { \
+ nsIVariant *pI = GetI(self); \
+ if (pI==NULL) return NULL; \
+ if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \
+ Type t; \
+ nsresult nr = pI->FuncGet(&t); \
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \
+ return FuncConvert(t); \
+}
+
+#define GET_ALLOCATED(Type, FuncGet, FuncConvert, FuncFree) \
+static PyObject *FuncGet(PyObject *self, PyObject *args) { \
+ nsIVariant *pI = GetI(self); \
+ if (pI==NULL) return NULL; \
+ if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \
+ Type t; \
+ nsresult nr = pI->FuncGet(&t); \
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \
+ PyObject *ret = FuncConvert(t); \
+ FuncFree(t); \
+ return ret; \
+}
+
+#define GET_ALLOCATED_SIZE(Type, FuncGet, FuncConvert, FuncFree) \
+static PyObject *FuncGet(PyObject *self, PyObject *args) { \
+ nsIVariant *pI = GetI(self); \
+ if (pI==NULL) return NULL; \
+ if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \
+ Type t; PRUint32 size; \
+ nsresult nr = pI->FuncGet(&size, &t); \
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \
+ PyObject *ret = FuncConvert(t, size); \
+ FuncFree(t); \
+ return ret; \
+}
+
+GET_SIMPLE(PRUint8, GetAsInt8, PyInt_FromLong)
+GET_SIMPLE(PRUint8, GetAsUint8, PyInt_FromLong)
+GET_SIMPLE(PRInt16, GetAsInt16, PyInt_FromLong)
+GET_SIMPLE(PRUint16, GetAsUint16, PyInt_FromLong)
+GET_SIMPLE(PRInt32, GetAsInt32, PyInt_FromLong)
+GET_SIMPLE(PRUint32, GetAsUint32, PyInt_FromLong)
+GET_SIMPLE(PRInt64, GetAsInt64, PyLong_FromLongLong)
+GET_SIMPLE(PRUint64, GetAsUint64, PyLong_FromUnsignedLongLong)
+GET_SIMPLE(float, GetAsFloat, PyFloat_FromDouble)
+GET_SIMPLE(double, GetAsDouble, PyFloat_FromDouble)
+GET_SIMPLE(PRBool, GetAsBool, MyBool)
+GET_SIMPLE(char, GetAsChar, MyChar)
+GET_SIMPLE(PRUnichar, GetAsWChar, MyUChar)
+GET_SIMPLE(nsIID, GetAsID, Py_nsIID::PyObjectFromIID)
+
+#if PY_MAJOR_VERSION <= 2
+GET_ALLOCATED(char *, GetAsString, PyString_FromString, nsMemory::Free)
+#else
+GET_ALLOCATED(char *, GetAsString, PyUnicode_FromString, nsMemory::Free)
+#endif
+GET_ALLOCATED(PRUnichar *, GetAsWString, MyUnicode, nsMemory::Free)
+#if PY_MAJOR_VERSION <= 2
+GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyString_FromStringAndSize, nsMemory::Free)
+#else
+GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyUnicode_FromStringAndSize, nsMemory::Free)
+#endif
+GET_ALLOCATED_SIZE(PRUnichar *, GetAsWStringWithSize, PyObject_FromNSString, nsMemory::Free)
+
+static PyObject *GetAsInterface(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
+ nsCOMPtr<nsISupports> p;
+ nsIID *iid;
+ nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ return Py_nsISupports::PyObjectFromInterface(p, *iid);
+}
+
+static PyObject *GetAsISupports(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
+ nsCOMPtr<nsISupports> p;
+ nsIID *iid;
+ nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ return Py_nsISupports::PyObjectFromInterface(p, *iid);
+}
+
+extern PyObject *PyObject_FromVariantArray( Py_nsISupports*, nsIVariant *v);
+
+static PyObject *GetAsArray(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":GetAsArray")) return NULL;
+ return PyObject_FromVariantArray((Py_nsISupports *)self, pI);
+}
+
+static PyObject *Get(PyObject *self, PyObject *args) {
+ nsIVariant *pI = GetI(self);
+ if (pI==NULL) return NULL;
+ if (!PyArg_ParseTuple(args, ":Get")) return NULL;
+ return PyObject_FromVariant((Py_nsISupports *)self, pI);
+}
+
+struct PyMethodDef
+PyMethods_IVariant[] =
+{
+ { "getAsInt8", GetAsInt8, 1},
+ { "getAsUint8", GetAsUint8, 1},
+ { "getAsInt16", GetAsInt16, 1},
+ { "getAsUint16", GetAsUint16, 1},
+ { "getAsInt32", GetAsInt32, 1},
+ { "getAsUint32", GetAsUint32, 1},
+ { "getAsInt64", GetAsInt64, 1},
+ { "getAsUint64", GetAsUint64, 1},
+ { "getAsFloat", GetAsFloat, 1},
+ { "getAsDouble", GetAsDouble, 1},
+ { "getAsBool", GetAsBool, 1},
+ { "getAsChar", GetAsChar, 1},
+ { "getAsWChar", GetAsWChar, 1},
+ { "getAsString", GetAsString, 1},
+ { "getAsWString", GetAsWString, 1},
+ { "getAsStringWithSize", GetAsStringWithSize, 1},
+ { "getAsWStringWithSize", GetAsWStringWithSize, 1},
+ { "getAsISupports", GetAsISupports, 1},
+ { "getAsInterface", GetAsInterface, 1},
+ { "getAsArray", GetAsArray, 1},
+ { "getAsID", GetAsID, 1},
+ { "get", Get, 1},
+ {NULL}
+};
+
+PyObject *
+Py_nsIVariant::getattr(const char *name)
+{
+
+ PyObject *ret = NULL;
+ if (strcmp(name, "dataType")==0) {
+ nsIVariant *pI = ::GetI(this);
+ if (pI) {
+ PRUint16 dt;
+ nsresult nr = pI->GetDataType(&dt);
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ ret = PyInt_FromLong(dt);
+ }
+ } else {
+ ret = Py_nsISupports::getattr(name);
+ }
+ return ret;
+}
+
+int
+Py_nsIVariant::setattr(const char *name, PyObject *v)
+{
+ return Py_nsISupports::setattr(name, v);
+}
diff --git a/src/libs/xpcom18a4/python/src/PyXPCOM.h b/src/libs/xpcom18a4/python/src/PyXPCOM.h
new file mode 100644
index 00000000..91bc8d12
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyXPCOM.h
@@ -0,0 +1,1036 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// PyXPCOM.h - the main header file for the Python XPCOM support.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#ifndef __PYXPCOM_H__
+#define __PYXPCOM_H__
+
+#include "nsIAllocator.h"
+#include "nsIWeakReference.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIClassInfo.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIServiceManager.h"
+#include "nsIInputStream.h"
+#include "nsIVariant.h"
+#include "nsIModule.h"
+
+#include "nsXPIDLString.h"
+#include "nsCRT.h"
+#include "xptcall.h"
+#include "xpt_xdr.h"
+
+#ifdef VBOX_DEBUG_LIFETIMES
+# include <iprt/critsect.h>
+# include <iprt/list.h>
+# include <iprt/once.h>
+#endif
+
+#ifdef HAVE_LONG_LONG
+ // Mozilla also defines this - we undefine it to
+ // prevent a compiler warning.
+# undef HAVE_LONG_LONG
+#endif // HAVE_LONG_LONG
+
+#ifdef _POSIX_C_SOURCE // Ditto here
+# undef _POSIX_C_SOURCE
+#endif // _POSIX_C_SOURCE
+
+#ifdef VBOX_PYXPCOM
+// unfortunatelly, if SOLARIS is defined Python porting layer
+// defines gethostname() in invalid fashion what kills compilation
+# ifdef SOLARIS
+# undef SOLARIS
+# define SOLARIS_WAS_DEFINED
+# endif
+
+// Python.h/pyconfig.h redefines _XOPEN_SOURCE on some hosts
+# ifdef _XOPEN_SOURCE
+# define VBOX_XOPEN_SOURCE_DEFINED _XOPEN_SOURCE
+# undef _XOPEN_SOURCE
+# endif
+
+#endif /* VBOX_PYXPCOM */
+
+#include <Python.h>
+
+#ifdef VBOX_PYXPCOM
+
+# ifdef SOLARIS_WAS_DEFINED
+# define SOLARIS
+# undef SOLARIS_WAS_DEFINED
+# endif
+
+// restore the old value of _XOPEN_SOURCE if not defined by Python.h/pyconfig.h
+# if !defined(_XOPEN_SOURCE) && defined(VBOX_XOPEN_SOURCE_DEFINED)
+# define _XOPEN_SOURCE VBOX_XOPEN_SOURCE_DEFINED
+# endif
+# undef VBOX_XOPEN_SOURCE_DEFINED
+
+# if (PY_VERSION_HEX <= 0x02040000)
+// although in more recent versions of Python this type is ssize_t, earlier
+// it was used as int
+typedef int Py_ssize_t;
+# endif
+
+# if (PY_VERSION_HEX <= 0x02030000)
+// this one not defined before
+inline PyObject *PyBool_FromLong(long ok)
+{
+ PyObject *result;
+ if (ok)
+ result = Py_True;
+ else
+ result = Py_False;
+ Py_INCREF(result);
+ return result;
+}
+# endif
+
+# if PY_MAJOR_VERSION >= 3
+# define PyInt_FromLong(l) PyLong_FromLong(l)
+# define PyInt_Check(o) PyLong_Check(o)
+# define PyInt_AsLong(o) PyLong_AsLong(o)
+# define PyNumber_Int(o) PyNumber_Long(o)
+# if !defined(Py_LIMITED_API) && PY_VERSION_HEX <= 0x03030000 /* 3.3 added PyUnicode_AsUTF8AndSize */
+# ifndef PyUnicode_AsUTF8
+# define PyUnicode_AsUTF8(o) _PyUnicode_AsString(o)
+# endif
+# ifndef PyUnicode_AsUTF8AndSize
+# define PyUnicode_AsUTF8AndSize(o,s) _PyUnicode_AsStringAndSize(o,s)
+# endif
+# endif
+typedef struct PyMethodChain
+{
+ PyMethodDef *methods;
+ struct PyMethodChain *link;
+} PyMethodChain;
+# endif
+
+#endif /* VBOX_PYXPCOM */
+
+#ifdef BUILD_PYXPCOM
+ /* We are building the main dll */
+# define PYXPCOM_EXPORT NS_EXPORT
+#else
+ /* This module uses the dll */
+# define PYXPCOM_EXPORT NS_IMPORT
+#endif // BUILD_PYXPCOM
+
+// An IID we treat as NULL when passing as a reference.
+extern PYXPCOM_EXPORT nsIID Py_nsIID_NULL;
+
+class Py_nsISupports;
+
+
+/** @name VBox limited API hacks:
+ * @{ */
+#ifndef Py_LIMITED_API
+
+# define PyXPCOM_ObTypeName(obj) (Py_TYPE(obj)->tp_name)
+
+#else /* Py_LIMITED_API */
+
+# if PY_VERSION_HEX <= 0x03030000
+# error "Py_LIMITED_API mode only works for Python 3.3 and higher."
+# endif
+
+const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj);
+# define PyXPCOM_ObTypeName(obj) PyXPCOMGetObTypeName(Py_TYPE(obj))
+
+# if Py_LIMITED_API < 0x030A0000
+/* Note! While we should not technically be using PyUnicode_AsUTF8AndSize, it was
+ made part of the limited API in 3.10 (see https://bugs.python.org/issue41784 and
+ https://github.com/python/cpython/commit/a05195ac61f1908ac5990cccb5aa82442bdaf15d). */
+extern "C" PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize(PyObject *, Py_ssize_t *);
+# endif
+
+/* PyUnicode_AsUTF8 is just PyUnicode_AsUTF8AndSize without returning a size. */
+# define PyUnicode_AsUTF8(o) PyUnicode_AsUTF8AndSize(o, NULL)
+
+DECLINLINE(int) PyRun_SimpleString(const char *pszCode)
+{
+ /* Get the main mode dictionary: */
+ PyObject *pMainMod = PyImport_AddModule("__main__");
+ if (pMainMod) {
+ PyObject *pMainModDict = PyModule_GetDict(pMainMod);
+
+ /* Compile and run the code. */
+ PyObject *pCodeObject = Py_CompileString(pszCode, "PyXPCOM", Py_file_input);
+ if (pCodeObject) {
+ PyObject *pResult = PyEval_EvalCode(pCodeObject, pMainModDict, pMainModDict);
+ Py_DECREF(pCodeObject);
+ if (pResult) {
+ Py_DECREF(pResult);
+ return 0;
+ }
+ PyErr_Print();
+ }
+ }
+ return -1;
+}
+
+DECLINLINE(PyObject *) PyTuple_GET_ITEM(PyObject *pTuple, Py_ssize_t idx)
+{
+ return PyTuple_GetItem(pTuple, idx);
+}
+
+DECLINLINE(int) PyTuple_SET_ITEM(PyObject *pTuple, Py_ssize_t idx, PyObject *pItem)
+{
+ int rc = PyTuple_SetItem(pTuple, idx, pItem); /* Steals pItem ref, just like PyTuple_SET_ITEM. */
+ Assert(rc == 0);
+ return rc;
+}
+
+DECLINLINE(int) PyList_SET_ITEM(PyObject *pList, Py_ssize_t idx, PyObject *pItem)
+{
+ int rc = PyList_SetItem(pList, idx, pItem); /* Steals pItem ref, just like PyList_SET_ITEM. */
+ Assert(rc == 0);
+ return rc;
+}
+
+DECLINLINE(Py_ssize_t) PyBytes_GET_SIZE(PyObject *pBytes)
+{
+ return PyBytes_Size(pBytes);
+}
+
+DECLINLINE(const char *) PyBytes_AS_STRING(PyObject *pBytes)
+{
+ return PyBytes_AsString(pBytes);
+}
+
+DECLINLINE(Py_ssize_t) PyUnicode_GET_SIZE(PyObject *pUnicode)
+{
+ /* Note! Currently only used for testing for zero or 1 codepoints, so we don't
+ really need to deal with the different way these two treats surrogate pairs. */
+# if Py_LIMITED_API >= 0x03030000
+ return PyUnicode_GetLength(pUnicode);
+# else
+ return PyUnicode_GetSize(pUnicode);
+# endif
+}
+
+# define PyObject_CheckBuffer(pAllegedBuffer) PyObject_CheckReadBuffer(pAllegedBuffer)
+
+# include <iprt/asm.h>
+DECLINLINE(Py_hash_t) _Py_HashPointer(void *p)
+{
+ Py_hash_t uHash = (Py_hash_t)RT_CONCAT(ASMRotateRightU,ARCH_BITS)((uintptr_t)p, 4);
+ return uHash != -1 ? uHash : -2;
+}
+
+#endif /* Py_LIMITED_API */
+/** @} */
+
+
+/*************************************************************************
+**************************************************************************
+
+ Error and exception related function.
+
+**************************************************************************
+*************************************************************************/
+
+#define NS_PYXPCOM_NO_SUCH_METHOD \
+ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_PYXPCOM, 0)
+
+// The exception object (loaded from the xpcom .py code)
+extern PYXPCOM_EXPORT PyObject *PyXPCOM_Error;
+
+// Client related functions - generally called by interfaces before
+// they return NULL back to Python to indicate the error.
+// All these functions return NULL so interfaces can generally
+// just "return PyXPCOM_BuildPyException(hr, punk, IID_IWhatever)"
+PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res);
+
+#ifdef VBOX
+// Build human readable error message out of XPCOM error
+PYXPCOM_EXPORT PyObject *PyXPCOM_BuildErrorMessage(nsresult r);
+#endif
+
+// Used in gateways to handle the current Python exception
+// NOTE: this function assumes it is operating within the Python context
+PYXPCOM_EXPORT nsresult PyXPCOM_SetCOMErrorFromPyException();
+
+// Write current exception and traceback to a string.
+PYXPCOM_EXPORT PRBool PyXPCOM_FormatCurrentException(nsCString &streamout);
+// Write specified exception and traceback to a string.
+PYXPCOM_EXPORT PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
+ PyObject *exc_typ, PyObject *exc_val,
+ PyObject *exc_tb);
+
+// A couple of logging/error functions. These probably end up
+// being written to the console service.
+
+// Log a warning for the user - something at runtime
+// they may care about, but nothing that prevents us actually
+// working.
+// As it's designed for user error/warning, it exists in non-debug builds.
+PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...);
+
+// Log an error for the user - something that _has_ prevented
+// us working. This is probably accompanied by a traceback.
+// As it's designed for user error/warning, it exists in non-debug builds.
+PYXPCOM_EXPORT void PyXPCOM_LogError(const char *fmt, ...);
+
+// The raw one
+PYXPCOM_EXPORT void PyXPCOM_Log(const char *level, const nsCString &msg);
+
+#ifdef DEBUG
+// Mainly designed for developers of the XPCOM package.
+// Only enabled in debug builds.
+PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
+#define PYXPCOM_LOG_DEBUG PyXPCOM_LogDebug
+#else
+#define PYXPCOM_LOG_DEBUG()
+#endif // DEBUG
+
+// Some utility converters
+// moz strings to PyObject.
+PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsACString &s,
+ PRBool bAssumeUTF8 = PR_FALSE );
+PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsAString &s );
+PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const PRUnichar *s,
+ PRUint32 len = (PRUint32)-1);
+
+// PyObjects to moz strings. As per the moz string guide, we pass a reference
+// to an abstract string
+PYXPCOM_EXPORT PRBool PyObject_AsNSString( PyObject *ob, nsAString &aStr);
+
+// Variants.
+PYXPCOM_EXPORT nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet);
+PYXPCOM_EXPORT PyObject *PyObject_FromVariant( Py_nsISupports *parent,
+ nsIVariant *v);
+
+// Interfaces - these are the "official" functions
+PYXPCOM_EXPORT PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
+ const nsIID &iid,
+ PRBool bMakeNicePyObject = PR_TRUE);
+
+/*************************************************************************
+**************************************************************************
+
+ Support for CALLING (ie, using) interfaces.
+
+**************************************************************************
+*************************************************************************/
+
+typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &);
+
+//////////////////////////////////////////////////////////////////////////
+// class PyXPCOM_TypeObject
+// Base class for (most of) the type objects.
+
+#ifndef Py_LIMITED_API
+class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject {
+#else
+class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyObject {
+#endif
+public:
+ PyXPCOM_TypeObject(
+ const char *name,
+ PyXPCOM_TypeObject *pBaseType,
+ int typeSize,
+ struct PyMethodDef* methodList,
+ PyXPCOM_I_CTOR ctor);
+ ~PyXPCOM_TypeObject();
+
+ PyMethodChain chain;
+ PyXPCOM_TypeObject *baseType;
+ PyXPCOM_I_CTOR ctor;
+
+ static PRBool IsType(PyTypeObject *t);
+ // Static methods for the Python type.
+ static void Py_dealloc(PyObject *ob);
+ static PyObject *Py_repr(PyObject *ob);
+ static PyObject *Py_str(PyObject *ob);
+ static PyObject *Py_getattr(PyObject *self, char *name);
+ static int Py_setattr(PyObject *op, char *name, PyObject *v);
+ static int Py_cmp(PyObject *ob1, PyObject *ob2);
+ static PyObject *Py_richcmp(PyObject *ob1, PyObject *ob2, int op);
+#if PY_VERSION_HEX >= 0x03020000
+ static Py_hash_t Py_hash(PyObject *self);
+#else
+ static long Py_hash(PyObject *self);
+#endif
+#ifdef Py_LIMITED_API
+ PyTypeObject *m_pTypeObj; /**< The python type object we wrap. */
+#endif
+};
+
+//////////////////////////////////////////////////////////////////////////
+// class Py_nsISupports
+// This class serves 2 purposes:
+// * It is a base class for other interfaces we support "natively"
+// * It is instantiated for _all_ other interfaces.
+//
+// This is different than win32com, where a PyIUnknown only
+// ever holds an IUnknown - but here, we could be holding
+// _any_ interface.
+class PYXPCOM_EXPORT Py_nsISupports : public PyObject
+{
+public:
+ // Check if a Python object can safely be cast to an Py_nsISupports,
+ // and optionally check that the object is wrapping the specified
+ // interface.
+ static PRBool Check( PyObject *ob, const nsIID &checkIID = Py_nsIID_NULL) {
+ Py_nsISupports *self = static_cast<Py_nsISupports *>(ob);
+ if (ob==NULL || !PyXPCOM_TypeObject::IsType(ob->ob_type ))
+ return PR_FALSE;
+ if (!checkIID.Equals(Py_nsIID_NULL))
+ return self->m_iid.Equals(checkIID) != 0;
+ return PR_TRUE;
+ }
+ // Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED
+ static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL);
+ nsCOMPtr<nsISupports> m_obj;
+ nsIID m_iid;
+#ifdef Py_LIMITED_API
+ /** Because PyXPCOM_TypeObject cannot inherit from PyTypeObject in
+ * Py_LIMITED_API mode, we cannot use ob_type to get to the method list.
+ * Instead of we store it here. */
+ PyXPCOM_TypeObject *m_pMyTypeObj;
+#endif
+
+ // Given an nsISupports and an Interface ID, create and return an object
+ // Does not QI the object - the caller must ensure the nsISupports object
+ // is really a pointer to an object identified by the IID (although
+ // debug builds should check this)
+ // PRBool bMakeNicePyObject indicates if we should call back into
+ // Python to wrap the object. This allows Python code to
+ // see the correct xpcom.client.Interface object even when calling
+ // xpcom functions directly from C++.
+ // NOTE: There used to be a bAddRef param to this as an internal
+ // optimization, but since removed. This function *always* takes a
+ // reference to the nsISupports.
+ static PyObject *PyObjectFromInterface(nsISupports *ps,
+ const nsIID &iid,
+ PRBool bMakeNicePyObject = PR_TRUE,
+ PRBool bIsInternalCall = PR_FALSE);
+
+ // Given a Python object that is a registered COM type, return a given
+ // interface pointer on its underlying object, with a NEW REFERENCE ADDED.
+ // bTryAutoWrap indicates if a Python instance object should attempt to
+ // be automatically wrapped in an XPCOM object. This is really only
+ // provided to stop accidental recursion should the object returned by
+ // the wrap process itself be in instance (where it should already be
+ // a COM object.
+ // If |iid|==nsIVariant, then arbitary Python objects will be wrapped
+ // in an nsIVariant.
+ static PRBool InterfaceFromPyObject(
+ PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppret,
+ PRBool bNoneOK,
+ PRBool bTryAutoWrap = PR_TRUE);
+
+ // Given a Py_nsISupports, return an interface.
+ // Object *must* be Py_nsISupports - there is no
+ // "autowrap", no "None" support, etc
+ static PRBool InterfaceFromPyISupports(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppv);
+
+ static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid);
+ // The Python methods
+ static PyObject *QueryInterface(PyObject *self, PyObject *args);
+
+ // Internal (sort-of) objects.
+ static NS_EXPORT_STATIC_MEMBER_(PyXPCOM_TypeObject) *type;
+ static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
+ static PyObject *mapIIDToType;
+ static void SafeRelease(Py_nsISupports *ob);
+#ifndef Py_LIMITED_API
+ static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
+#else
+ static void RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t);
+#endif
+ static void InitType();
+#ifdef VBOX_DEBUG_LIFETIMES
+ static void dumpList(void);
+ static void dumpListToStdOut(void);
+#endif
+
+ virtual ~Py_nsISupports();
+ virtual PyObject *getattr(const char *name);
+ virtual int setattr(const char *name, PyObject *val);
+ // A virtual function to sub-classes can customize the way
+ // nsISupports objects are returned from their methods.
+ // ps is a new object just obtained from some operation performed on us
+ virtual PyObject *MakeInterfaceResult(nsISupports *ps, const nsIID &iid,
+ PRBool bMakeNicePyObject = PR_TRUE) {
+ return PyObjectFromInterface(ps, iid, bMakeNicePyObject);
+ }
+
+protected:
+ // ctor is protected - must create objects via
+ // PyObjectFromInterface()
+ Py_nsISupports(nsISupports *p,
+ const nsIID &iid,
+#ifndef Py_LIMITED_API
+ PyTypeObject *type);
+#else
+ PyXPCOM_TypeObject *type);
+#endif
+
+ // Make a default wrapper for an ISupports (which is an
+ // xpcom.client.Component instance)
+ static PyObject *MakeDefaultWrapper(PyObject *pyis, const nsIID &iid);
+
+#ifdef VBOX_DEBUG_LIFETIMES
+ static DECLCALLBACK(int32_t) initOnceCallback(void *pvUser1);
+
+ RTLISTNODE m_ListEntry; /**< List entry. */
+
+ static RTONCE g_Once; /**< Init list and critsect once. */
+ static RTCRITSECT g_CritSect; /**< Critsect protecting the list. */
+ static RTLISTANCHOR g_List; /**< List of live interfaces.*/
+#endif
+};
+
+// Python/XPCOM IID support
+class PYXPCOM_EXPORT Py_nsIID : public PyObject
+{
+public:
+ Py_nsIID(const nsIID &riid);
+ nsIID m_iid;
+
+ PRBool
+ IsEqual(const nsIID &riid) {
+ return m_iid.Equals(riid);
+ }
+
+ PRBool
+ IsEqual(PyObject *ob) {
+ return ob &&
+#ifndef Py_LIMITED_API
+ ob->ob_type== &type &&
+#else
+ ob->ob_type == s_pType &&
+#endif
+ m_iid.Equals(((Py_nsIID *)ob)->m_iid);
+ }
+
+ PRBool
+ IsEqual(Py_nsIID &iid) {
+ return m_iid.Equals(iid.m_iid);
+ }
+
+ static PyObject *
+ PyObjectFromIID(const nsIID &iid) {
+ return new Py_nsIID(iid);
+ }
+
+ static PRBool IIDFromPyObject(PyObject *ob, nsIID *pRet);
+ /* Python support */
+ static PyObject *PyTypeMethod_getattr(PyObject *self, char *name);
+#if PY_MAJOR_VERSION <= 2
+ static int PyTypeMethod_compare(PyObject *self, PyObject *ob);
+#endif
+ static PyObject *PyTypeMethod_richcompare(PyObject *self, PyObject *ob, int op);
+ static PyObject *PyTypeMethod_repr(PyObject *self);
+#if PY_VERSION_HEX >= 0x03020000
+ static Py_hash_t PyTypeMethod_hash(PyObject *self);
+#else
+ static long PyTypeMethod_hash(PyObject *self);
+#endif
+ static PyObject *PyTypeMethod_str(PyObject *self);
+ static void PyTypeMethod_dealloc(PyObject *self);
+#ifndef Py_LIMITED_API
+ static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type;
+#else
+ static NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) s_pType;
+ static PyTypeObject *GetTypeObject(void);
+#endif
+ static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
+};
+
+///////////////////////////////////////////////////////
+//
+// Helper classes for managing arrays of variants.
+class PythonTypeDescriptor; // Forward declare.
+
+class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper {
+public:
+ PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent, int methodindex);
+ ~PyXPCOM_InterfaceVariantHelper();
+ PRBool Init(PyObject *obParams);
+ PRBool FillArray();
+
+ PyObject *MakePythonResult();
+
+ nsXPTCVariant *m_var_array;
+ int m_num_array;
+ int m_methodindex;
+protected:
+ PyObject *MakeSinglePythonResult(int index);
+ PRBool FillInVariant(const PythonTypeDescriptor &, int, int);
+ PRBool PrepareOutVariant(const PythonTypeDescriptor &td, int value_index);
+ PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
+ PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
+
+ PyObject *m_pyparams; // sequence of actual params passed (ie, not including hidden)
+ PyObject *m_typedescs; // desc of _all_ params, including hidden.
+ PythonTypeDescriptor *m_python_type_desc_array;
+ void **m_buffer_array;
+ Py_nsISupports *m_parent;
+
+};
+
+/*************************************************************************
+**************************************************************************
+
+ Support for IMPLEMENTING interfaces.
+
+**************************************************************************
+*************************************************************************/
+#define NS_IINTERNALPYTHON_IID_STR "AC7459FC-E8AB-4f2e-9C4F-ADDC53393A20"
+#define NS_IINTERNALPYTHON_IID \
+ { 0xac7459fc, 0xe8ab, 0x4f2e, { 0x9c, 0x4f, 0xad, 0xdc, 0x53, 0x39, 0x3a, 0x20 } }
+
+class PyXPCOM_GatewayWeakReference;
+
+// This interface is needed primarily to give us a known vtable base.
+// If we QI a Python object for this interface, we can safely cast the result
+// to a PyG_Base. Any other interface, we do now know which vtable we will get.
+// We also allow the underlying PyObject to be extracted
+class nsIInternalPython : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IINTERNALPYTHON_IID)
+ // Get the underlying Python object with new reference added
+ virtual PyObject *UnwrapPythonObject(void) = 0;
+};
+
+// This is roughly equivalent to PyGatewayBase in win32com
+//
+class PYXPCOM_EXPORT PyG_Base : public nsIInternalPython, public nsISupportsWeakReference
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSWEAKREFERENCE
+ PyObject *UnwrapPythonObject(void);
+
+ // A static "constructor" - the real ctor is protected.
+ static nsresult CreateNew(PyObject *pPyInstance,
+ const nsIID &iid,
+ void **ppResult);
+
+ // A utility to auto-wrap an arbitary Python instance
+ // in a COM gateway.
+ static PRBool AutoWrapPythonInstance(PyObject *ob,
+ const nsIID &iid,
+ nsISupports **ppret);
+
+
+ // A helper that creates objects to be passed for nsISupports
+ // objects. See extensive comments in PyG_Base.cpp.
+ PyObject *MakeInterfaceParam(nsISupports *pis,
+ const nsIID *piid,
+ int methodIndex = -1,
+ const XPTParamDescriptor *d = NULL,
+ int paramIndex = -1);
+
+ // A helper that ensures all casting and vtable offsetting etc
+ // done against this object happens in the one spot!
+ virtual void *ThisAsIID( const nsIID &iid ) = 0;
+
+ // Helpers for "native" interfaces.
+ // Not used by the generic stub interface.
+ nsresult HandleNativeGatewayError(const char *szMethodName);
+
+ // These data members used by the converter helper functions - hence public
+ nsIID m_iid;
+ PyObject * m_pPyObject;
+ // We keep a reference count on this object, and the object
+ // itself uses normal refcount rules - thus, it will only
+ // die when we die, and all external references are removed.
+ // This means that once we have created it (and while we
+ // are alive) it will never die.
+ nsCOMPtr<nsIWeakReference> m_pWeakRef;
+#ifdef NS_BUILD_REFCNT_LOGGING
+ char refcntLogRepr[64]; // sigh - I wish I knew how to use the Moz string classes :( OK for debug only tho.
+#endif
+protected:
+ PyG_Base(PyObject *instance, const nsIID &iid);
+ virtual ~PyG_Base();
+ PyG_Base *m_pBaseObject; // A chain to implement identity rules.
+ nsresult InvokeNativeViaPolicy( const char *szMethodName,
+ PyObject **ppResult = NULL,
+ const char *szFormat = NULL,
+ ...
+ );
+ nsresult InvokeNativeViaPolicyInternal( const char *szMethodName,
+ PyObject **ppResult,
+ const char *szFormat,
+ va_list va);
+ nsresult InvokeNativeGetViaPolicy(const char *szPropertyName,
+ PyObject **ppResult = NULL
+ );
+ nsresult InvokeNativeSetViaPolicy(const char *szPropertyName,
+ ...);
+};
+
+class PYXPCOM_EXPORT PyXPCOM_XPTStub : public PyG_Base, public nsXPTCStubBase
+{
+friend class PyG_Base;
+public:
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
+ {return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
+ NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
+ NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params);
+
+ virtual void *ThisAsIID(const nsIID &iid);
+protected:
+ PyXPCOM_XPTStub(PyObject *instance, const nsIID &iid) : PyG_Base(instance, iid) {;}
+private:
+};
+
+// For the Gateways we manually implement.
+#define PYGATEWAY_BASE_SUPPORT(INTERFACE, GATEWAY_BASE) \
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \
+ {return PyG_Base::QueryInterface(aIID, aInstancePtr);} \
+ NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \
+ NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \
+ virtual void *ThisAsIID(const nsIID &iid) { \
+ if (iid.Equals(NS_GET_IID(INTERFACE))) return (INTERFACE *)this; \
+ return GATEWAY_BASE::ThisAsIID(iid); \
+ } \
+
+extern PYXPCOM_EXPORT void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
+
+extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetGatewayCount(void);
+extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetInterfaceCount(void);
+#ifdef VBOX_DEBUG_LIFETIMES
+extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_DumpInterfaces(void);
+#endif
+
+
+// Weak Reference class. This is a true COM object, representing
+// a weak reference to a Python object. For each Python XPCOM object,
+// there is exactly zero or one corresponding weak reference instance.
+// When both are alive, each holds a pointer to the other. When the main
+// object dies due to XPCOM reference counting, it zaps the pointer
+// in its corresponding weak reference object. Thus, the weak-reference
+// can live beyond the object (possibly with a NULL pointer back to the
+// "real" object, but as implemented, the weak reference will never be
+// destroyed before the object
+class PYXPCOM_EXPORT PyXPCOM_GatewayWeakReference : public nsIWeakReference {
+public:
+ PyXPCOM_GatewayWeakReference(PyG_Base *base);
+ virtual ~PyXPCOM_GatewayWeakReference();
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIWEAKREFERENCE
+ PyG_Base *m_pBase; // NO REF COUNT!!!
+#ifdef NS_BUILD_REFCNT_LOGGING
+ char refcntLogRepr[41];
+#endif
+};
+
+
+// Helpers classes for our gateways.
+class PYXPCOM_EXPORT PyXPCOM_GatewayVariantHelper
+{
+public:
+ PyXPCOM_GatewayVariantHelper( PyG_Base *gateway,
+ int methodIndex,
+ const nsXPTMethodInfo *info,
+ nsXPTCMiniVariant* params );
+ ~PyXPCOM_GatewayVariantHelper();
+ PyObject *MakePyArgs();
+ nsresult ProcessPythonResult(PyObject *ob);
+ PyG_Base *m_gateway;
+private:
+ nsresult BackFillVariant( PyObject *ob, int index);
+ PyObject *MakeSingleParam(int index, PythonTypeDescriptor &td);
+ PRBool GetIIDForINTERFACE_ID(int index, const nsIID **ppret);
+ nsresult GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **ppiid);
+ PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
+ PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
+ PRBool CanSetSizeIs( int var_index, PRBool is_arg1 );
+ nsIInterfaceInfo *GetInterfaceInfo(); // NOTE: no ref count on result.
+
+
+ nsXPTCMiniVariant* m_params;
+ const nsXPTMethodInfo *m_info;
+ int m_method_index;
+ PythonTypeDescriptor *m_python_type_desc_array;
+ int m_num_type_descs;
+ nsCOMPtr<nsIInterfaceInfo> m_interface_info;
+};
+
+// Misc converters.
+PyObject *PyObject_FromXPTType( const nsXPTType *d);
+// XPTTypeDescriptor derived from XPTType - latter is automatically processed via PyObject_FromXPTTypeDescriptor XPTTypeDescriptor
+PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d);
+
+PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d);
+PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d);
+PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d);
+
+// DLL reference counting functions.
+// Although we maintain the count, we never actually
+// finalize Python when it hits zero!
+void PyXPCOM_DLLAddRef();
+void PyXPCOM_DLLRelease();
+
+/*************************************************************************
+**************************************************************************
+
+ LOCKING AND THREADING
+
+**************************************************************************
+*************************************************************************/
+
+//
+// We have 2 discrete locks in use (when no free-threaded is used, anyway).
+// The first type of lock is the global Python lock. This is the standard lock
+// in use by Python, and must be used as documented by Python. Specifically, no
+// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without
+// first having this thread lock.
+//
+// The second type of lock is a "global framework lock", and used whenever 2 threads
+// of C code need access to global data. This is different than the Python
+// lock - this lock is used when no Python code can ever be called by the
+// threads, but the C code still needs thread-safety.
+
+// We also supply helper classes which make the usage of these locks a one-liner.
+
+// The "framework" lock, implemented as a PRLock
+PYXPCOM_EXPORT void PyXPCOM_AcquireGlobalLock(void);
+PYXPCOM_EXPORT void PyXPCOM_ReleaseGlobalLock(void);
+
+// Helper class for the DLL global lock.
+//
+// This class magically waits for PyXPCOM framework global lock, and releases it
+// when finished.
+// NEVER new one of these objects - only use on the stack!
+class CEnterLeaveXPCOMFramework {
+public:
+ CEnterLeaveXPCOMFramework() {PyXPCOM_AcquireGlobalLock();}
+ ~CEnterLeaveXPCOMFramework() {PyXPCOM_ReleaseGlobalLock();}
+};
+
+// Python thread-lock stuff. Free-threading patches use different semantics, but
+// these are abstracted away here...
+//#include <threadstate.h>
+
+// Helper class for Enter/Leave Python
+//
+// This class magically waits for the Python global lock, and releases it
+// when finished.
+
+// Nested invocations will deadlock, so be careful.
+
+// NEVER new one of these objects - only use on the stack!
+
+PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
+PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
+
+// For 2.3, use the PyGILState_ calls
+#if (PY_VERSION_HEX >= 0x02030000)
+#define PYXPCOM_USE_PYGILSTATE
+#endif
+
+#ifdef PYXPCOM_USE_PYGILSTATE
+class CEnterLeavePython {
+public:
+ CEnterLeavePython() {
+ state = PyGILState_Ensure();
+ // See "pending calls" comment below. We reach into the Python
+ // implementation to see if we are the first call on the stack.
+# ifndef Py_LIMITED_API
+ if (PyThreadState_Get()->gilstate_counter==1) {
+# else
+ if (state == PyGILState_UNLOCKED) {
+# endif
+ PyXPCOM_MakePendingCalls();
+ }
+ }
+ ~CEnterLeavePython() {
+ PyGILState_Release(state);
+ }
+ PyGILState_STATE state;
+};
+#else
+
+extern PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
+PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
+PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
+PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
+PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
+PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
+
+// Pre 2.3 thread-state dances.
+class CEnterLeavePython {
+public:
+ CEnterLeavePython() {
+ created = PyXPCOM_ThreadState_Ensure();
+ PyXPCOM_InterpreterLock_Acquire();
+ if (created) {
+ // If pending python calls are waiting as we enter Python,
+ // it will generally mean an asynch signal handler, etc.
+ // We can either call it here, or wait for Python to call it
+ // as part of its "even 'n' opcodes" check. If we wait for
+ // Python to check it and the pending call raises an exception,
+ // then it is _our_ code that will fail - this is unfair,
+ // as the signal was raised before we were entered - indeed,
+ // we may be directly responding to the signal!
+ // Thus, we flush all the pending calls here, and report any
+ // exceptions via our normal exception reporting mechanism.
+ // We can then execute our code in the knowledge that only
+ // signals raised _while_ we are executing will cause exceptions.
+ PyXPCOM_MakePendingCalls();
+ }
+ }
+ ~CEnterLeavePython() {
+ // The interpreter state must be cleared
+ // _before_ we release the lock, as some of
+ // the sys. attributes cleared (eg, the current exception)
+ // may need the lock to invoke their destructors -
+ // specifically, when exc_value is a class instance, and
+ // the exception holds the last reference!
+ if ( created )
+ PyXPCOM_ThreadState_Clear();
+ PyXPCOM_InterpreterLock_Release();
+ if ( created )
+ PyXPCOM_ThreadState_Free();
+ }
+private:
+ PRBool created;
+};
+#endif // PYXPCOM_USE_PYGILSTATE
+
+// Our classes.
+// Hrm - So we can't have templates, eh??
+// preprocessor to the rescue, I guess.
+#define PyXPCOM_INTERFACE_DECLARE(ClassName, InterfaceName, Methods ) \
+ \
+extern struct PyMethodDef Methods[]; \
+ \
+class ClassName : public Py_nsISupports \
+{ \
+public: \
+ static PYXPCOM_EXPORT PyXPCOM_TypeObject *type; \
+ static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
+ return new ClassName(pInitObj, iid); \
+ } \
+ static void InitType() { \
+ type = new PyXPCOM_TypeObject( \
+ #InterfaceName, \
+ Py_nsISupports::type, \
+ sizeof(ClassName), \
+ Methods, \
+ Constructor); \
+ const nsIID &iid = NS_GET_IID(InterfaceName); \
+ RegisterInterface(iid, type); \
+ } \
+protected: \
+ ClassName(nsISupports *p, const nsIID &iid) : \
+ Py_nsISupports(p, iid, type) { \
+ /* The IID _must_ be the IID of the interface we are wrapping! */ \
+ NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \
+ } \
+}; \
+ \
+// End of PyXPCOM_INTERFACE_DECLARE macro
+
+#define PyXPCOM_ATTR_INTERFACE_DECLARE(ClassName, InterfaceName, Methods )\
+ \
+extern struct PyMethodDef Methods[]; \
+ \
+class ClassName : public Py_nsISupports \
+{ \
+public: \
+ static PyXPCOM_TypeObject *type; \
+ static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
+ return new ClassName(pInitObj, iid); \
+ } \
+ static void InitType() { \
+ type = new PyXPCOM_TypeObject( \
+ #InterfaceName, \
+ Py_nsISupports::type, \
+ sizeof(ClassName), \
+ Methods, \
+ Constructor); \
+ const nsIID &iid = NS_GET_IID(InterfaceName); \
+ RegisterInterface(iid, type); \
+} \
+ virtual PyObject *getattr(const char *name); \
+ virtual int setattr(const char *name, PyObject *val); \
+protected: \
+ ClassName(nsISupports *p, const nsIID &iid) : \
+ Py_nsISupports(p, iid, type) { \
+ /* The IID _must_ be the IID of the interface we are wrapping! */ \
+ NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \
+ } \
+}; \
+ \
+// End of PyXPCOM_ATTR_INTERFACE_DECLARE macro
+
+#define PyXPCOM_INTERFACE_DEFINE(ClassName, InterfaceName, Methods ) \
+PyXPCOM_TypeObject *ClassName::type = NULL;
+
+
+// And the classes
+PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
+PyXPCOM_INTERFACE_DECLARE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
+PyXPCOM_INTERFACE_DECLARE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
+PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
+PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
+// deprecated, but retained for backward compatibility:
+PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
+#endif // __PYXPCOM_H__
diff --git a/src/libs/xpcom18a4/python/src/PyXPCOM_std.h b/src/libs/xpcom18a4/python/src/PyXPCOM_std.h
new file mode 100644
index 00000000..b7b7ff8c
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/PyXPCOM_std.h
@@ -0,0 +1,56 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// standard include - sets up all the defines used by
+// the mozilla make process - too lazy to work out how to integrate
+// with their make, so this will do!
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+// This header is considered internal - hence
+// we can use it to trigger "exports"
+#define BUILD_PYXPCOM
+
+#include "PyXPCOM.h"
diff --git a/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp b/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp
new file mode 100644
index 00000000..d1df54fe
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp
@@ -0,0 +1,197 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+// Pyxpt_info.cpp - wrappers for the xpt_info objects.
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+#include "PyXPCOM_std.h"
+
+PyObject *PyObject_FromXPTType( const nsXPTType *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ // build an object using the same format as a TypeDescriptor.
+ return Py_BuildValue("bzzz",
+ d->flags,
+ NULL, NULL, NULL);
+}
+
+PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return Py_BuildValue("bbbh",
+ d->prefix.flags,
+ d->argnum,
+ d->argnum2,
+ d->type.iface // this is actually a union!
+ );
+}
+
+PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PyObject *ob = PyObject_FromXPTTypeDescriptor(&d->type);
+ PyObject *ret = Py_BuildValue("bO", d->flags, ob);
+ Py_DECREF(ob);
+ return ret;
+}
+
+PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d)
+{
+ if (d==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PyObject *ob_params = PyTuple_New(d->num_args);
+ if (ob_params==NULL)
+ return NULL;
+ for (int i=0;i<d->num_args;i++)
+ PyTuple_SET_ITEM(ob_params, i, PyObject_FromXPTParamDescriptor(d->params+i));
+ PyObject *ob_ret = PyObject_FromXPTParamDescriptor(d->result);
+ PyObject *ret = Py_BuildValue("bsOO", d->flags, d->name, ob_params, ob_ret);
+ Py_XDECREF(ob_ret);
+ Py_XDECREF(ob_params);
+ return ret;
+}
+
+PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
+{
+ if (c==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PyObject *ob_type = PyObject_FromXPTTypeDescriptor(&c->type);
+ if (ob_type==NULL)
+ return NULL;
+ PyObject *v = NULL;
+ switch (c->type.prefix.flags) {
+ case TD_INT8:
+ v = PyInt_FromLong( c->value.i8 );
+ break;
+ case TD_INT16:
+ v = PyInt_FromLong( c->value.i16 );
+ break;
+ case TD_INT32:
+ v = PyInt_FromLong( c->value.i32 );
+ break;
+ case TD_INT64:
+ v = PyLong_FromLongLong(c->value.i64);
+ break;
+ case TD_UINT8:
+ v = PyInt_FromLong( c->value.ui8 );
+ break;
+ case TD_UINT16:
+ v = PyInt_FromLong( c->value.ui16 );
+ break;
+ case TD_UINT32:
+ v = PyInt_FromLong( c->value.ui32 );
+ break;
+ case TD_UINT64:
+ v = PyLong_FromUnsignedLongLong(c->value.ui64);
+ break;
+ case TD_FLOAT:
+ v = PyFloat_FromDouble(c->value.flt);
+ break;
+ case TD_DOUBLE:
+ v = PyFloat_FromDouble(c->value.dbl);
+ break;
+ case TD_BOOL:
+ v = c->value.bul ? Py_True : Py_False;
+ Py_INCREF(v);
+ break;
+ case TD_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ v = PyString_FromStringAndSize(&c->value.ch, 1);
+#else
+ v = PyUnicode_FromStringAndSize(&c->value.ch, 1);
+#endif
+ break;
+ case TD_WCHAR:
+ v = PyObject_FromNSString((PRUnichar *)&c->value.wch, 1);
+ break;
+ // TD_VOID = 13,
+ case TD_PNSIID:
+ v = Py_nsIID::PyObjectFromIID(*c->value.iid);
+ break;
+ // TD_DOMSTRING = 15,
+ case TD_PSTRING:
+#if PY_MAJOR_VERSION <= 2
+ v = PyString_FromString(c->value.str);
+#else
+ v = PyUnicode_FromString(c->value.str);
+#endif
+ break;
+ case TD_PWSTRING:
+ v = PyObject_FromNSString((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr));
+ break;
+ // TD_INTERFACE_TYPE = 18,
+ // TD_INTERFACE_IS_TYPE = 19,
+ // TD_ARRAY = 20,
+ // TD_PSTRING_SIZE_IS = 21,
+ // TD_PWSTRING_SIZE_IS = 22
+ // TD_UTF8STRING = 23,
+ // TD_CSTRING = 24,
+ // TD_ASTRING = 25
+ default:
+#if PY_MAJOR_VERSION <= 2
+ v = PyString_FromString("Unknown type code!!");
+#else
+ v = PyUnicode_FromString("Unknown type code!!");
+#endif
+ break;
+
+ }
+ PyObject *ret = Py_BuildValue("sbO", c->name, ob_type, v);
+ Py_DECREF(ob_type);
+ Py_DECREF(v);
+ return ret;
+}
diff --git a/src/libs/xpcom18a4/python/src/TypeObject.cpp b/src/libs/xpcom18a4/python/src/TypeObject.cpp
new file mode 100644
index 00000000..37cc13d7
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/TypeObject.cpp
@@ -0,0 +1,457 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+#include <nsXPCOM.h>
+#include <nsISupportsPrimitives.h>
+
+#if defined(Py_LIMITED_API) && defined(RT_OS_LINUX)
+# include <features.h>
+# ifdef __GLIBC_PREREQ
+# if __GLIBC_PREREQ(2,9)
+# define PYXPCOM_HAVE_PIPE2
+# include <fcntl.h>
+# endif
+# endif
+#endif
+
+
+#ifndef Py_LIMITED_API
+static PyTypeObject PyInterfaceType_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "interface-type", /* Name of this type */
+ sizeof(PyTypeObject), /* Basic object size */
+ 0, /* Item size for varobject */
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ PyType_Type.tp_getattr, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ PyType_Type.tp_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /* tp_getattro */
+ 0, /*tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ "Define the behavior of a PythonCOM Interface type.",
+};
+
+#else /* Py_LIMITED_API */
+
+/** The offset of PyTypeObject::ob_name. */
+static size_t g_offObTypeNameMember = sizeof(PyVarObject);
+
+/**
+ * Base type object for XPCOM interfaces. Created dynamicially.
+ */
+static PyTypeObject *g_pPyInterfaceTypeObj = NULL;
+
+/**
+ * Gets the base XPCOM interface type object, creating it if needed.
+ */
+static PyTypeObject *PyXPCOM_CreateInterfaceType(void)
+{
+ static char g_szTypeDoc[] = "Define the behavior of a PythonCOM Interface type."; /* need non-const */
+ PyType_Slot aTypeSlots[] = {
+ { Py_tp_doc, g_szTypeDoc },
+ { 0, NULL } /* terminator */
+ };
+ static const char g_szClassNm[] = "interface-type";
+ PyType_Spec TypeSpec = {
+ /* .name: */ g_szClassNm,
+ /* .basicsize: */ 0,
+ /* .itemsize: */ 0,
+ /* .flags: */ Py_TPFLAGS_BASETYPE,
+ /* .slots: */ aTypeSlots,
+ };
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
+
+ PyTypeObject *pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
+ assert(pTypeObj);
+
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ g_pPyInterfaceTypeObj = pTypeObj;
+
+ /*
+ * Verify/correct g_offObTypeNameMember.
+ *
+ * Using pipe+write to probe the memory content, banking on the kernel
+ * to return EFAULT when we pass it an invalid address.
+ */
+ for (size_t off = sizeof(PyVarObject); off < sizeof(PyVarObject) + 64; off += sizeof(char *)) {
+ const char * const pszProbe = *(const char **)((uintptr_t)(pTypeObj) + off);
+ if (RT_VALID_PTR(pszProbe)) {
+ int fds[2] = { -1, -1 };
+# ifdef PYXPCOM_HAVE_PIPE2
+ int rc = pipe2(fds, O_CLOEXEC);
+# else
+ int rc = pipe(fds);
+# endif
+ if (rc)
+ break;
+
+ ssize_t cbWritten = write(fds[1], pszProbe, sizeof(g_szClassNm));
+ if (cbWritten == (ssize_t)sizeof(g_szClassNm)) {
+ char szReadBack[sizeof(g_szClassNm)];
+ ssize_t offRead = 0;
+ while (offRead < cbWritten) {
+ ssize_t cbRead = read(fds[0], &szReadBack[offRead], cbWritten - offRead);
+ if (cbRead >= 0) {
+ offRead += cbRead;
+ } else if (errno != EINTR)
+ break;
+ }
+ if ( cbWritten == offRead
+ && memcmp(szReadBack, g_szClassNm, sizeof(szReadBack)) == 0) {
+ g_offObTypeNameMember = off;
+ close(fds[0]);
+ close(fds[1]);
+ return pTypeObj;
+ }
+ }
+ close(fds[0]);
+ close(fds[1]);
+ }
+ }
+ assert(0);
+
+ return pTypeObj;
+}
+
+/**
+ * Gets the base XPCOM interface type object, creating it if needed.
+ */
+static PyTypeObject *PyXPCOM_GetInterfaceType(void)
+{
+ PyTypeObject *pTypeObj = g_pPyInterfaceTypeObj;
+ if (pTypeObj)
+ return pTypeObj;
+ return PyXPCOM_CreateInterfaceType();
+}
+
+/**
+ * Get the PyTypeObject::ob_name value.
+ *
+ * @todo This is _horrible_, but there appears to be no simple tp_name getter
+ * till https://bugs.python.org/issue31497 (2017 / 3.7.0). But even then
+ * it is not part of the limited API.
+ */
+const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj)
+{
+ return *(const char **)((uintptr_t)(pTypeObj) + g_offObTypeNameMember);
+}
+
+#endif /* Py_LIMITED_API */
+
+/*static*/ PRBool
+PyXPCOM_TypeObject::IsType(PyTypeObject *t)
+{
+#if PY_MAJOR_VERSION <= 2
+ return t->ob_type == &PyInterfaceType_Type;
+#elif !defined(Py_LIMITED_API)
+ return Py_TYPE(t) == &PyInterfaceType_Type;
+#else
+ return Py_TYPE(t) == g_pPyInterfaceTypeObj /* Typically not the case as t->ob_type is &PyType_Type */
+ || PyType_IsSubtype(t, g_pPyInterfaceTypeObj); /* rather than g_pPyInterfaceTypeObj because of PyType_FromSpec(). */
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//
+// The type methods
+//
+/*static*/PyObject *
+PyXPCOM_TypeObject::Py_getattr(PyObject *self, char *name)
+{
+ return ((Py_nsISupports *)self)->getattr(name);
+}
+
+/*static*/int
+PyXPCOM_TypeObject::Py_setattr(PyObject *op, char *name, PyObject *v)
+{
+ return ((Py_nsISupports *)op)->setattr(name, v);
+}
+
+// @pymethod int|Py_nsISupports|__cmp__|Implements XPCOM rules for object identity.
+/*static*/int
+PyXPCOM_TypeObject::Py_cmp(PyObject *self, PyObject *other)
+{
+ // @comm NOTE: Copied from COM - have not confirmed these rules are true for XPCOM
+ // @comm As per the XPCOM rules for object identity, both objects are queried for nsISupports, and these values compared.
+ // The only meaningful test is for equality - the result of other comparisons is undefined
+ // (ie, determined by the object's relative addresses in memory.
+ nsISupports *pUnkOther;
+ nsISupports *pUnkThis;
+ if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
+ return -1;
+ if (!Py_nsISupports::InterfaceFromPyObject(other, NS_GET_IID(nsISupports), &pUnkOther, PR_FALSE)) {
+ pUnkThis->Release();
+ return -1;
+ }
+ int rc = pUnkThis==pUnkOther ? 0 :
+ (pUnkThis < pUnkOther ? -1 : 1);
+ pUnkThis->Release();
+ pUnkOther->Release();
+ return rc;
+}
+
+/*static*/PyObject *
+PyXPCOM_TypeObject::Py_richcmp(PyObject *self, PyObject *other, int op)
+{
+ PyObject *result = NULL;
+ int rc = Py_cmp(self, other);
+ switch (op)
+ {
+ case Py_LT:
+ result = rc < 0 ? Py_True : Py_False;
+ break;
+ case Py_LE:
+ result = rc <= 0 ? Py_True : Py_False;
+ break;
+ case Py_EQ:
+ result = rc == 0 ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = rc != 0 ? Py_True : Py_False;
+ break;
+ case Py_GT:
+ result = rc > 0 ? Py_True : Py_False;
+ break;
+ case Py_GE:
+ result = rc >= 0 ? Py_True : Py_False;
+ break;
+ }
+ Py_XINCREF(result);
+ return result;
+}
+
+// @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules.
+#if PY_VERSION_HEX >= 0x03020000
+/*static*/Py_hash_t PyXPCOM_TypeObject::Py_hash(PyObject *self)
+#else
+/*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self)
+#endif
+{
+ // We always return the value of the nsISupports *.
+ nsISupports *pUnkThis;
+ if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE))
+ return -1;
+#if PY_VERSION_HEX >= 0x03020000
+ Py_hash_t ret = _Py_HashPointer(pUnkThis);
+#else
+ long ret = _Py_HashPointer(pUnkThis);
+#endif
+ pUnkThis->Release();
+ return ret;
+}
+
+// @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object
+/*static */PyObject *
+PyXPCOM_TypeObject::Py_repr(PyObject *self)
+{
+ // @comm The repr of this object displays both the object's address, and its attached nsISupports's address
+ Py_nsISupports *pis = (Py_nsISupports *)self;
+ // Try and get the IID name.
+ char *iid_repr = nsnull;
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ if (iim!=nsnull)
+ iim->GetNameForIID(&pis->m_iid, &iid_repr);
+ if (iid_repr==nsnull)
+ // no IIM available, or it doesnt know the name.
+ iid_repr = pis->m_iid.ToString();
+ // XXX - need some sort of buffer overflow.
+ char buf[512];
+#ifdef VBOX
+ snprintf(buf, sizeof(buf), "<XPCOM object (%s) at %p/%p>",
+ iid_repr, (void *)self, (void *)pis->m_obj.get());
+#else
+ sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>",
+ iid_repr, (void *)self, (void *)pis->m_obj.get());
+#endif
+ nsMemory::Free(iid_repr);
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromString(buf);
+#else
+ return PyUnicode_FromString(buf);
+#endif
+}
+
+/*static */PyObject *
+PyXPCOM_TypeObject::Py_str(PyObject *self)
+{
+ Py_nsISupports *pis = (Py_nsISupports *)self;
+ nsresult rv;
+ char *val = NULL;
+ Py_BEGIN_ALLOW_THREADS;
+ { // scope to kill pointer while thread-lock released.
+ nsCOMPtr<nsISupportsCString> ss( do_QueryInterface(pis->m_obj, &rv ));
+ if (NS_SUCCEEDED(rv))
+ rv = ss->ToString(&val);
+ } // end-scope
+ Py_END_ALLOW_THREADS;
+ PyObject *ret;
+ if (NS_FAILED(rv))
+ ret = Py_repr(self);
+ else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(val);
+#else
+ ret = PyUnicode_FromString(val);
+#endif
+ if (val) nsMemory::Free(val);
+ return ret;
+}
+
+/* static */void
+PyXPCOM_TypeObject::Py_dealloc(PyObject *self)
+{
+ delete (Py_nsISupports *)self;
+}
+
+PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector)
+{
+#ifndef Py_LIMITED_API
+ static const PyTypeObject type_template = {
+ PyVarObject_HEAD_INIT(&PyInterfaceType_Type, 0)
+ "XPCOMTypeTemplate", /*tp_name*/
+ sizeof(Py_nsISupports), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ Py_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ Py_getattr, /* tp_getattr */
+ Py_setattr, /* tp_setattr */
+#if PY_MAJOR_VERSION <= 2
+ Py_cmp, /* tp_compare */
+#else
+ 0, /* reserved */
+#endif
+ Py_repr, /* tp_repr */
+ 0, /* tp_as_number*/
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ Py_hash, /* tp_hash */
+ 0, /* tp_call */
+ Py_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ Py_richcmp, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ };
+
+ *((PyTypeObject *)this) = type_template;
+#else /* Py_LIMITED_API */
+ /* Create the type specs: */
+ PyType_Slot aTypeSlots[] = {
+ { Py_tp_base, PyXPCOM_GetInterfaceType() },
+ { Py_tp_dealloc, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_dealloc },
+ { Py_tp_getattr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_getattr },
+ { Py_tp_setattr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_setattr },
+ { Py_tp_repr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_repr },
+ { Py_tp_hash, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_hash },
+ { Py_tp_str, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_str },
+ { Py_tp_richcompare, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_richcmp },
+ { 0, NULL } /* terminator */
+ };
+ PyType_Spec TypeSpec = {
+ /* .name: */ name,
+ /* .basicsize: */ typeSize,
+ /* .itemsize: */ 0,
+ /* .flags: */ Py_TPFLAGS_BASETYPE /*?*/,
+ /* .slots: */ aTypeSlots,
+ };
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
+
+ m_pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
+ assert(m_pTypeObj);
+
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+
+ /* Initialize the PyObject part - needed so we can keep instance in a PyDict: */
+ ob_type = PyXPCOM_GetInterfaceType();
+ PyObject_Init(this, ob_type); /* VBox: Needed for 3.9 and up (also works on Python 2.7), includes _Py_NewReferences. @bugref{10079} */
+
+#endif /* Py_LIMITED_API */
+
+ chain.methods = methodList;
+ chain.link = pBase ? &pBase->chain : NULL;
+
+ baseType = pBase;
+ ctor = thector;
+
+#ifndef Py_LIMITED_API
+ // cast away const, as Python doesnt use it.
+ tp_name = (char *)name;
+ tp_basicsize = typeSize;
+#endif
+}
+
+PyXPCOM_TypeObject::~PyXPCOM_TypeObject()
+{
+}
+
diff --git a/src/libs/xpcom18a4/python/src/VariantUtils.cpp b/src/libs/xpcom18a4/python/src/VariantUtils.cpp
new file mode 100644
index 00000000..ac14a2cf
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/VariantUtils.cpp
@@ -0,0 +1,3112 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * Unicode corrections by Shane Hathaway (http://hathawaymix.org),
+ * inspired by Mikhail Sobolev
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <nsIInterfaceInfoManager.h>
+#include <nsAString.h>
+#include <nsString.h>
+#include <nsReadableUtils.h>
+
+// ------------------------------------------------------------------------
+// nsString utilities
+// ------------------------------------------------------------------------
+// one day we may know what they look like.
+inline
+PRBool
+IsNullDOMString( const nsAString& aString )
+{
+ return PR_FALSE;
+}
+
+inline
+PRBool
+IsNullDOMString( const nsACString& aString )
+{
+ return PR_FALSE;
+}
+
+#define PyUnicode_FromPRUnichar(src, size) \
+ PyUnicode_DecodeUTF16((char*)(src),sizeof(PRUnichar)*(size),NULL,NULL)
+
+// Create a zero-terminated PRUnichar buffer from a Python unicode.
+// On success, returns 0. On failure, returns -1 and sets an exception.
+// dest_out must not be null. size_out may be null.
+static int
+PyUnicode_AsPRUnichar(PyObject *obj, PRUnichar **dest_out, PRUint32 *size_out)
+{
+ PRUint32 size;
+ PyObject *s;
+ const void *src;
+ PRUnichar *dest;
+
+ s = PyUnicode_AsUTF16String(obj);
+ if (!s)
+ return -1;
+ // Drop the UTF-16 byte order mark at the beginning of
+ // the string. (See the docs on PyUnicode_AsUTF16String.)
+ // Some Mozilla libraries don't like the mark.
+#if PY_MAJOR_VERSION <= 2
+ size = (PyString_GET_SIZE(s) - 2) / sizeof(PRUnichar);
+ src = PyString_AS_STRING(s) + 2;
+#else
+ if (!PyBytes_Check(s)) {
+ PyErr_SetString(PyExc_TypeError, "internal error in PyXPCOM, parameter must be a bytes object");
+ return -1;
+ }
+ size = (PyBytes_GET_SIZE(s) - 2) / sizeof(PRUnichar);
+ src = PyBytes_AS_STRING(s) + 2;
+#endif
+ dest = (PRUnichar *)nsMemory::Alloc(sizeof(PRUnichar) * (size + 1));
+ if (!dest) {
+ PyErr_NoMemory();
+ Py_DECREF(s);
+ return -1;
+ }
+ memcpy(dest, src, sizeof(PRUnichar) * size);
+ Py_DECREF(s);
+ dest[size] = 0;
+ *dest_out = dest;
+ if (size_out)
+ *size_out = size;
+ return 0;
+}
+
+PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 /*= PR_FALSE */)
+{
+ PyObject *ret;
+ if (IsNullDOMString(s)) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ if (bAssumeUTF8) {
+ const nsPromiseFlatCString& temp = PromiseFlatCString(s);
+ ret = PyUnicode_DecodeUTF8(temp.get(), temp.Length(), NULL);
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize(NULL, s.Length());
+#else
+ ret = PyUnicode_FromStringAndSize(NULL, s.Length());
+#endif
+ if (!ret)
+ return NULL;
+ // Need "CopyAsciiTo"!?
+ nsACString::const_iterator fromBegin, fromEnd;
+#if PY_MAJOR_VERSION <= 2
+ char* dest = (char *)PyString_AS_STRING(ret);
+#else
+ char* dest = (char *)PyUnicode_AsUTF8(ret);
+#endif
+ copy_string(s.BeginReading(fromBegin), s.EndReading(fromEnd), dest);
+ }
+ }
+ return ret;
+}
+
+PyObject *PyObject_FromNSString( const nsAString &s )
+{
+ PyObject *ret;
+ if (IsNullDOMString(s)) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ const nsPromiseFlatString& temp = PromiseFlatString(s);
+ ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
+ }
+ return ret;
+}
+
+PyObject *PyObject_FromNSString( const PRUnichar *s,
+ PRUint32 len /* = (PRUint32)-1*/)
+{
+ return PyUnicode_FromPRUnichar(s,
+ len==((PRUint32)-1)? nsCRT::strlen(s) : len);
+}
+
+PRBool PyObject_AsNSString( PyObject *val, nsAString &aStr)
+{
+ if (val == Py_None) {
+ aStr.Truncate();
+ return NS_OK;
+ }
+ PyObject *val_use = NULL;
+ PRBool ok = PR_TRUE;
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ ok = PR_FALSE;
+ }
+ if (ok && (val_use = PyUnicode_FromObject(val))==NULL)
+ ok = PR_FALSE;
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ ok = PR_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (ok) {
+ if (PyUnicode_GET_SIZE(val_use) == 0) {
+ aStr.Truncate();
+ }
+ else {
+ PRUint32 nch;
+ PRUnichar *tempo;
+ // can we do this without the copy?
+ if (PyUnicode_AsPRUnichar(val_use, &tempo, &nch) < 0)
+ return PR_FALSE;
+ aStr.Assign(tempo, nch);
+ nsMemory::Free(tempo);
+ }
+ }
+ Py_XDECREF(val_use);
+ return ok;
+}
+
+// Array utilities
+static PRUint32 GetArrayElementSize( PRUint8 t)
+{
+ PRUint32 ret;
+ switch (t & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_U8:
+ case nsXPTType::T_I8:
+ ret = sizeof(PRInt8);
+ break;
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ ret = sizeof(PRInt16);
+ break;
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ ret = sizeof(PRInt32);
+ break;
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ ret = sizeof(PRInt64);
+ break;
+ case nsXPTType::T_FLOAT:
+ ret = sizeof(float);
+ break;
+ case nsXPTType::T_DOUBLE:
+ ret = sizeof(double);
+ break;
+ case nsXPTType::T_BOOL:
+ ret = sizeof(PRBool);
+ break;
+ case nsXPTType::T_CHAR:
+ ret = sizeof(char);
+ break;
+ case nsXPTType::T_WCHAR:
+ ret = sizeof(PRUnichar);
+ break;
+ case nsXPTType::T_IID:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_INTERFACE_IS:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_UTF8STRING:
+
+ ret = sizeof( void * );
+ break;
+ default:
+ NS_ABORT_IF_FALSE(0, "Unknown array type code!");
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static nsresult
+GetArrayElementIID(Py_nsISupports* self,
+ nsXPTCVariant* dispatchParams,
+ PRUint16 methodIndex,
+ PRUint8 paramIndex,
+ nsIID *result)
+{
+ nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ nsresult rc;
+
+ rc = iim->GetInfoForIID(&self->m_iid, getter_AddRefs(ii));
+ if (NS_FAILED(rc))
+ return rc;
+
+
+ const nsXPTMethodInfo *mi;
+ rc = ii->GetMethodInfo(methodIndex, &mi);
+ if (NS_FAILED(rc))
+ return rc;
+
+ const nsXPTParamInfo& paramInfo = mi->GetParam(paramIndex);
+
+ if (!paramInfo.GetType().IsArray()) {
+ PyXPCOM_LogWarning("Passing non-array to GetArrayElementIID\n");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsXPTType elemType;
+ rc = ii->GetTypeForParam(methodIndex, &paramInfo, 1, &elemType);
+ if (NS_FAILED(rc))
+ return rc;
+
+ PRUint8 tag = elemType.TagPart();
+ if (tag == nsXPTType::T_INTERFACE)
+ {
+ rc = ii->GetIIDForParamNoAlloc(methodIndex, &paramInfo, result);
+ }
+ else if (tag == nsXPTType::T_INTERFACE_IS)
+ {
+ PyXPCOM_LogWarning("Unable to handle T_INTERFACE_IS yet\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ else
+ {
+ // this may be valid case, for arrays of other types
+ // we don't need IID for
+ rc = NS_ERROR_INVALID_ARG;
+ }
+
+ return rc;
+}
+
+
+void FreeSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type)
+{
+ // Free each array element - NOT the array itself
+ // Thus, we only need to free arrays or pointers.
+ void **p = (void **)array_ptr;
+ PRUint32 i;
+ switch(array_type & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_IID:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ for (i=0; i<sequence_size; i++)
+ if (p[i]) nsMemory::Free(p[i]);
+ break;
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ for (i=0; i<sequence_size; i++)
+ if (p[i]) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ ((nsISupports *)p[i])->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ break;
+
+ // Ones we know need no deallocation
+ case nsXPTType::T_U8:
+ case nsXPTType::T_I8:
+ case nsXPTType::T_I16:
+ case nsXPTType::T_U16:
+ case nsXPTType::T_I32:
+ case nsXPTType::T_U32:
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U64:
+ case nsXPTType::T_FLOAT:
+ case nsXPTType::T_DOUBLE:
+ case nsXPTType::T_BOOL:
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ break;
+
+ // And a warning should new type codes appear, as they may need deallocation.
+ default:
+ PyXPCOM_LogWarning("Deallocating unknown type %d (0x%x) - possible memory leak\n");
+ break;
+ }
+}
+
+#define FILL_SIMPLE_POINTER( type, val ) *((type *)pthis) = (type)(val)
+#define BREAK_FALSE {rc=PR_FALSE;break;}
+
+
+PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size,
+ PRUint32 array_element_size, PRUint8 array_type, nsIID *pIID)
+{
+ PRUint8 *pthis = (PRUint8 *)array_ptr;
+ NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!");
+ PRBool rc = PR_TRUE;
+ // We handle T_U8 specially as a string/Unicode.
+ // If it is NOT a string, we just fall through and allow the standard
+ // sequence unpack code process it (just slower!)
+#if PY_MAJOR_VERSION <= 2
+ if ( array_type == nsXPTType::T_U8 &&
+ (PyString_Check(sequence_ob) || PyUnicode_Check(sequence_ob))) {
+#else
+ if ( array_type == nsXPTType::T_U8 && PyUnicode_Check(sequence_ob)) {
+#endif
+
+ PRBool release_seq;
+ if (PyUnicode_Check(sequence_ob)) {
+ release_seq = PR_TRUE;
+#if PY_MAJOR_VERSION <= 2
+ sequence_ob = PyObject_Str(sequence_ob);
+#else
+ sequence_ob = PyUnicode_AsUTF8String(sequence_ob);
+#endif
+ } else
+ release_seq = PR_FALSE;
+ if (!sequence_ob) // presumably a memory error, or Unicode encoding error.
+ return PR_FALSE;
+#if PY_MAJOR_VERSION <= 2
+ memcpy(pthis, PyString_AS_STRING(sequence_ob), sequence_size);
+#else
+ memcpy(pthis, PyUnicode_AsUTF8(sequence_ob), sequence_size);
+#endif
+ if (release_seq)
+ {
+ Py_DECREF(sequence_ob);
+ }
+ return PR_TRUE;
+ }
+
+ for (PRUint32 i=0; rc && i<sequence_size; i++,pthis += array_element_size) {
+ PyObject *val = PySequence_GetItem(sequence_ob, i);
+ PyObject *val_use = NULL;
+ if (val==NULL)
+ return PR_FALSE;
+ switch(array_type) {
+ case nsXPTType::T_I8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) );
+ break;
+ case nsXPTType::T_U8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) );
+ break;
+ case nsXPTType::T_FLOAT:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_BOOL:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) );
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ FILL_SIMPLE_POINTER( char, *PyUnicode_AsUTF8(val) );
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+#endif
+ if ((val_use = PyUnicode_FromObject(val)) == NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+ // Lossy!
+#ifndef Py_LIMITED_API
+ FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
+#else
+ FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) );
+#endif
+ break;
+
+ case nsXPTType::T_IID: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(val, &iid))
+ BREAK_FALSE;
+ nsIID **pp = (nsIID **)pthis;
+ // If there is an existing IID, free it.
+ if (*pp)
+ nsMemory::Free(*pp);
+ *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID));
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ memcpy(*pp, &iid, sizeof(iid));
+ break;
+ }
+
+ // case nsXPTType::T_BSTR:
+
+ case nsXPTType::T_CHAR_STR: {
+ // If it is an existing string, free it.
+ char **pp = (char **)pthis;
+ if (*pp)
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ const char *sz = PyString_AS_STRING(val_use);
+ int nch = PyString_GET_SIZE(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ const char *sz = PyBytes_AS_STRING(val_use);
+ int nch = PyBytes_GET_SIZE(val_use);
+#endif
+
+ *pp = (char *)nsMemory::Alloc(nch+1);
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ strncpy(*pp, sz, nch+1);
+ break;
+ }
+ case nsXPTType::T_WCHAR_STR: {
+ // If it is an existing string, free it.
+ PRUnichar **pp = (PRUnichar **)pthis;
+ if (*pp)
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0)
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: // hmm - ignoring the IID can't be good :(
+ case nsXPTType::T_INTERFACE: {
+ // We do allow NULL here, even tho doing so will no-doubt crash some objects.
+ // (but there will certainly be objects out there that will allow NULL :-(
+ nsISupports *pnew;
+ if (!Py_nsISupports::InterfaceFromPyObject(val, NS_GET_IID(nsISupports), &pnew, PR_TRUE))
+ BREAK_FALSE;
+ nsISupports **pp = (nsISupports **)pthis;
+ if (*pp) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ (*pp)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ *pp = pnew; // ref-count added by InterfaceFromPyObject
+ break;
+ }
+ default:
+ // try and limp along in this case.
+ // leave rc TRUE
+ PyXPCOM_LogWarning("Converting Python object for an array element - The object type (0x%x) is unknown - leaving param alone!\n", array_type);
+ break;
+ }
+ Py_XDECREF(val_use);
+ Py_DECREF(val);
+ }
+ return rc;
+}
+
+static PyObject *UnpackSingleArray(Py_nsISupports *parent, void *array_ptr,
+ PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
+{
+ if (array_ptr==NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ if (array_type == nsXPTType::T_U8)
+#if PY_MAJOR_VERSION <= 2
+ return PyString_FromStringAndSize( (char *)array_ptr, sequence_size );
+#else
+ return PyBytes_FromStringAndSize( (char *)array_ptr, sequence_size );
+#endif
+
+ PRUint32 array_element_size = GetArrayElementSize(array_type);
+ PyObject *list_ret = PyList_New(sequence_size);
+ PRUint8 *pthis = (PRUint8 *)array_ptr;
+ for (PRUint32 i=0; i<sequence_size; i++,pthis += array_element_size) {
+ PyObject *val = NULL;
+ switch(array_type) {
+ case nsXPTType::T_I8:
+ val = PyInt_FromLong( *((PRInt8 *)pthis) );
+ break;
+ case nsXPTType::T_I16:
+ val = PyInt_FromLong( *((PRInt16 *)pthis) );
+ break;
+ case nsXPTType::T_I32:
+ val = PyInt_FromLong( *((PRInt32 *)pthis) );
+ break;
+ case nsXPTType::T_I64:
+ val = PyLong_FromLongLong( *((PRInt64 *)pthis) );
+ break;
+ // case nsXPTType::T_U8 - handled above!
+ case nsXPTType::T_U16:
+ val = PyInt_FromLong( *((PRUint16 *)pthis) );
+ break;
+ case nsXPTType::T_U32:
+ val = PyInt_FromLong( *((PRUint32 *)pthis) );
+ break;
+ case nsXPTType::T_U64:
+ val = PyLong_FromUnsignedLongLong( *((PRUint64 *)pthis) );
+ break;
+ case nsXPTType::T_FLOAT:
+ val = PyFloat_FromDouble( *((float*)pthis) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ val = PyFloat_FromDouble( *((double*)pthis) );
+ break;
+ case nsXPTType::T_BOOL:
+ val = (*((PRBool *)pthis)) ? Py_True : Py_False;
+ Py_INCREF(val);
+ break;
+ case nsXPTType::T_IID:
+ val = Py_nsIID::PyObjectFromIID( **((nsIID **)pthis) );
+ break;
+
+ case nsXPTType::T_CHAR_STR: {
+ char **pp = (char **)pthis;
+ if (*pp==NULL) {
+ Py_INCREF(Py_None);
+ val = Py_None;
+ } else
+#if PY_MAJOR_VERSION <= 2
+ val = PyString_FromString(*pp);
+#else
+ val = PyUnicode_FromString(*pp);
+#endif
+ break;
+ }
+ case nsXPTType::T_WCHAR_STR: {
+ PRUnichar **pp = (PRUnichar **)pthis;
+ if (*pp==NULL) {
+ Py_INCREF(Py_None);
+ val = Py_None;
+ } else {
+ val = PyUnicode_FromPRUnichar( *pp, nsCRT::strlen(*pp) );
+ }
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS:
+ case nsXPTType::T_INTERFACE: {
+ nsISupports **pp = (nsISupports **)pthis;
+ // If we have an owning parent, let it create
+ // the object for us.
+ if (iid && iid->Equals(NS_GET_IID(nsIVariant)))
+ val = PyObject_FromVariant(parent, (nsIVariant *)*pp);
+ else if (parent)
+ val = parent->MakeInterfaceResult(*pp, iid ? *iid : NS_GET_IID(nsISupports));
+ else
+ val = Py_nsISupports::PyObjectFromInterface(
+ *pp,
+ iid ? *iid : NS_GET_IID(nsISupports),
+ PR_TRUE);
+ break;
+ }
+ default: {
+ char buf[128];
+ sprintf(buf, "Unknown XPCOM array type flags (0x%x)", array_type);
+ PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf);
+#if PY_MAJOR_VERSION <= 2
+ val = PyString_FromString(buf);
+#else
+ val = PyUnicode_FromString(buf);
+#endif
+ break;
+ }
+ }
+ if (val==NULL) {
+ NS_ABORT_IF_FALSE(PyErr_Occurred(), "NULL result in array conversion, but no error set!");
+ return NULL;
+ }
+ PyList_SET_ITEM(list_ret, i, val); // ref-count consumed.
+ }
+ return list_ret;
+}
+
+
+// ------------------------------------------------------------------------
+// nsIVariant utilities
+// ------------------------------------------------------------------------
+struct BVFTResult {
+ BVFTResult() {pis = NULL;iid=Py_nsIID_NULL;}
+ nsISupports *pis;
+ nsIID iid;
+};
+
+static PRUint16 BestVariantTypeForPyObject( PyObject *ob, BVFTResult *pdata = NULL)
+{
+ nsISupports *ps = NULL;
+ nsIID iid;
+ // start with some fast concrete checks.
+ if (ob==Py_None)
+ return nsIDataType::VTYPE_EMPTY;
+ if (ob==Py_True || ob == Py_False)
+ return nsIDataType::VTYPE_BOOL;
+ if (PyInt_Check(ob))
+ return nsIDataType::VTYPE_INT32;
+ if (PyLong_Check(ob))
+ return nsIDataType::VTYPE_INT64;
+ if (PyFloat_Check(ob))
+ return nsIDataType::VTYPE_DOUBLE;
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(ob))
+ return nsIDataType::VTYPE_STRING_SIZE_IS;
+#endif
+ if (PyUnicode_Check(ob))
+ return nsIDataType::VTYPE_WSTRING_SIZE_IS;
+ if (PyTuple_Check(ob) || PyList_Check(ob)) {
+ if (PySequence_Length(ob))
+ return nsIDataType::VTYPE_ARRAY;
+ return nsIDataType::VTYPE_EMPTY_ARRAY;
+ }
+ // Now do expensive or abstract checks.
+ if (Py_nsISupports::InterfaceFromPyObject(ob, NS_GET_IID(nsISupports), &ps, PR_TRUE)) {
+ if (pdata) {
+ pdata->pis = ps;
+ pdata->iid = NS_GET_IID(nsISupports);
+ } else
+ ps->Release();
+ return nsIDataType::VTYPE_INTERFACE_IS;
+ } else
+ PyErr_Clear();
+ if (Py_nsIID::IIDFromPyObject(ob, &iid)) {
+ if (pdata)
+ pdata->iid = iid;
+ return nsIDataType::VTYPE_ID;
+ } else
+ PyErr_Clear();
+ if (PySequence_Check(ob)) {
+ if (PySequence_Length(ob))
+ return nsIDataType::VTYPE_ARRAY;
+ return nsIDataType::VTYPE_EMPTY_ARRAY;
+ }
+ return (PRUint16)-1;
+}
+
+nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet)
+{
+ nsresult nr = NS_OK;
+ nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr);
+ NS_ENSURE_SUCCESS(nr, nr);
+ // *sigh* - I tried the abstract API (PyNumber_Check, etc)
+ // but our COM instances too often qualify.
+ BVFTResult cvt_result;
+ PRUint16 dt = BestVariantTypeForPyObject(ob, &cvt_result);
+ switch (dt) {
+ case nsIDataType::VTYPE_BOOL:
+ nr = v->SetAsBool(ob==Py_True);
+ break;
+ case nsIDataType::VTYPE_INT32:
+ nr = v->SetAsInt32(PyInt_AsLong(ob));
+ break;
+ case nsIDataType::VTYPE_INT64:
+ nr = v->SetAsInt64(PyLong_AsLongLong(ob));
+ break;
+ case nsIDataType::VTYPE_DOUBLE:
+ nr = v->SetAsDouble(PyFloat_AsDouble(ob));
+ break;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ {
+#if PY_MAJOR_VERSION <= 2
+ nr = v->SetAsStringWithSize(PyString_Size(ob), PyString_AsString(ob));
+#else
+ Py_ssize_t cb = 0;
+ const char *psz = PyUnicode_AsUTF8AndSize(ob, &cb);
+ nr = v->SetAsStringWithSize(cb, psz);
+#endif
+ break;
+ }
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+#if PY_VERSION_HEX >= 0x03030000
+ if (PyUnicode_GetLength(ob) == 0) {
+#else
+ if (PyUnicode_GetSize(ob) == 0) {
+#endif
+ nr = v->SetAsWStringWithSize(0, (PRUnichar*)NULL);
+ }
+ else {
+ PRUint32 nch;
+ PRUnichar *p;
+ if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) {
+ PyXPCOM_LogWarning("Failed to convert object to unicode", PyXPCOM_ObTypeName(ob));
+ nr = NS_ERROR_UNEXPECTED;
+ break;
+ }
+ nr = v->SetAsWStringWithSize(nch, p);
+ nsMemory::Free(p);
+ }
+ break;
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ {
+ nsISupports *ps = cvt_result.pis;
+ nr = v->SetAsInterface(cvt_result.iid, ps);
+ if (ps) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ ps->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ break;
+ }
+ case nsIDataType::VTYPE_ID:
+ nr = v->SetAsID(cvt_result.iid);
+ break;
+ case nsIDataType::VTYPE_ARRAY:
+ {
+ int seq_length = PySequence_Length(ob);
+ NS_ABORT_IF_FALSE(seq_length!=0, "VTYPE_ARRAY assumes at least one element!");
+ PyObject *first = PySequence_GetItem(ob, 0);
+ if (!first) break;
+ int array_type = BestVariantTypeForPyObject(first);
+ Py_DECREF(first);
+ // Arrays can't handle all types. This means we lost embedded NULLs.
+ // This should really be fixed in XPCOM.
+ if (array_type == nsIDataType::VTYPE_STRING_SIZE_IS) array_type = nsIDataType::VTYPE_CHAR_STR;
+ if (array_type == nsIDataType::VTYPE_WSTRING_SIZE_IS) array_type = nsIDataType::VTYPE_WCHAR_STR;
+ PRUint32 element_size = GetArrayElementSize(array_type);
+ int cb_buffer_pointer = seq_length * element_size;
+ void *buffer_pointer;
+ if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) {
+ nr = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ memset(buffer_pointer, 0, cb_buffer_pointer);
+ if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type, nsnull)) {
+ nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer);
+ FreeSingleArray(buffer_pointer, seq_length, array_type);
+ } else
+ nr = NS_ERROR_UNEXPECTED;
+ nsMemory::Free(buffer_pointer);
+ break;
+ }
+ case nsIDataType::VTYPE_EMPTY:
+ nr = v->SetAsEmpty();
+ break;
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ nr = v->SetAsEmptyArray();
+ break;
+ case (PRUint16)-1:
+ PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob));
+ nr = NS_ERROR_UNEXPECTED;
+ default:
+ NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!");
+ PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob));
+ nr = NS_ERROR_UNEXPECTED;
+ }
+ if (NS_FAILED(nr))
+ return nr;
+ return v->QueryInterface(NS_GET_IID(nsIVariant), (void **)aRet);
+}
+
+static PyObject *MyBool_FromBool(PRBool v)
+{
+ PyObject *ret = v ? Py_True : Py_False;
+ Py_INCREF(ret);
+ return ret;
+}
+
+#define GET_FROM_V(Type, FuncGet, FuncConvert) { \
+ Type t; \
+ if (NS_FAILED(nr = FuncGet( &t ))) goto done;\
+ ret = FuncConvert(t);\
+ break; \
+}
+
+PyObject *PyObject_FromVariantArray( Py_nsISupports *parent, nsIVariant *v)
+{
+ nsresult nr;
+ NS_PRECONDITION(v, "NULL variant!");
+ if (!v)
+ return PyXPCOM_BuildPyException(NS_ERROR_INVALID_POINTER);
+#ifdef NS_DEBUG
+ PRUint16 dt;
+ nr = v->GetDataType(&dt);
+ NS_ABORT_IF_FALSE(dt == nsIDataType::VTYPE_ARRAY, "expected an array variant");
+#endif
+ nsIID iid;
+ void *p;
+ PRUint16 type;
+ PRUint32 count;
+ nr = v->GetAsArray(&type, &iid, &count, &p);
+ if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
+ PyObject *ret = UnpackSingleArray(parent, p, count, (PRUint8)type, &iid);
+ FreeSingleArray(p, count, (PRUint8)type);
+ nsMemory::Free(p);
+ return ret;
+}
+
+PyObject *PyObject_FromVariant( Py_nsISupports *parent, nsIVariant *v)
+{
+ if (!v) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ PRUint16 dt;
+ nsresult nr;
+ PyObject *ret = NULL;
+ nr = v->GetDataType(&dt);
+ if (NS_FAILED(nr)) goto done;
+ switch (dt) {
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_EMPTY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ break;
+ case nsIDataType::VTYPE_ARRAY:
+ ret = PyObject_FromVariantArray(parent, v);
+ break;
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ GET_FROM_V(PRInt32, v->GetAsInt32, PyInt_FromLong);
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ GET_FROM_V(PRUint32, v->GetAsUint32, PyLong_FromUnsignedLong);
+ case nsIDataType::VTYPE_INT64:
+ GET_FROM_V(PRInt64, v->GetAsInt64, PyLong_FromLongLong);
+ case nsIDataType::VTYPE_UINT64:
+ GET_FROM_V(PRUint64, v->GetAsUint64, PyLong_FromUnsignedLongLong);
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ GET_FROM_V(double, v->GetAsDouble, PyFloat_FromDouble);
+ case nsIDataType::VTYPE_BOOL:
+ GET_FROM_V(PRBool, v->GetAsBool, MyBool_FromBool);
+ default:
+ PyXPCOM_LogWarning("Converting variant to Python object - variant type '%d' unknown - using string.\n", dt);
+ // Fall through to the string case
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_CSTRING: {
+ nsCAutoString s;
+ if (NS_FAILED(nr=v->GetAsACString(s))) goto done;
+ ret = PyObject_FromNSString(s);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_ASTRING: {
+ nsAutoString s;
+ if (NS_FAILED(nr=v->GetAsAString(s))) goto done;
+ ret = PyObject_FromNSString(s);
+ break;
+ }
+ case nsIDataType::VTYPE_ID:
+ GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID);
+ case nsIDataType::VTYPE_INTERFACE: {
+ nsCOMPtr<nsISupports> p;
+ if (NS_FAILED(nr=v->GetAsISupports(getter_AddRefs(p)))) goto done;
+ if (parent)
+ ret = parent->MakeInterfaceResult(p, NS_GET_IID(nsISupports));
+ else
+ ret = Py_nsISupports::PyObjectFromInterface(
+ p, NS_GET_IID(nsISupports), PR_TRUE);
+ break;
+ }
+ case nsIDataType::VTYPE_INTERFACE_IS: {
+ nsCOMPtr<nsISupports> p;
+ nsIID *iid;
+ if (NS_FAILED(nr=v->GetAsInterface(&iid, getter_AddRefs(p)))) goto done;
+ // If the variant itself holds a variant, we should
+ // probably unpack that too?
+ ret = parent->MakeInterfaceResult(p, *iid);
+ break;
+ // case nsIDataType::VTYPE_WCHAR_STR
+ // case nsIDataType::VTYPE_UTF8STRING
+ }
+ }
+done:
+ if (NS_FAILED(nr)) {
+ NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
+ PyXPCOM_BuildPyException(nr);
+ }
+ return ret;
+}
+
+// ------------------------------------------------------------------------
+// TypeDescriptor helper class
+// ------------------------------------------------------------------------
+class PythonTypeDescriptor {
+public:
+ PythonTypeDescriptor() {
+ param_flags = type_flags = argnum = argnum2 = 0;
+ extra = NULL;
+ is_auto_out = PR_FALSE;
+ is_auto_in = PR_FALSE;
+ have_set_auto = PR_FALSE;
+ }
+ ~PythonTypeDescriptor() {
+ Py_XDECREF(extra);
+ }
+ PRUint8 param_flags;
+ PRUint8 type_flags;
+ PRUint8 argnum; /* used for iid_is and size_is */
+ PRUint8 argnum2; /* used for length_is */
+ PyObject *extra; // The IID object, or the type of the array.
+ // Extra items to help our processing.
+ // Is this auto-filled by some other "in" param?
+ PRBool is_auto_in;
+ // Is this auto-filled by some other "out" param?
+ PRBool is_auto_out;
+ // If is_auto_out, have I already filled it? Used when multiple
+ // params share a size_is fields - first time sets it, subsequent
+ // time check it.
+ PRBool have_set_auto;
+};
+
+static int ProcessPythonTypeDescriptors(PythonTypeDescriptor *pdescs, int num)
+{
+ // Loop over the array, checking all the params marked as having an arg.
+ // If these args nominate another arg as the size_is param, then
+ // we reset the size_is param to _not_ requiring an arg.
+ int i;
+ for (i=0;i<num;i++) {
+ PythonTypeDescriptor &ptd = pdescs[i];
+ // Can't use XPT_TDP_TAG() - it uses a ".flags" reference in the macro.
+ switch (ptd.type_flags & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_ARRAY:
+ NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index");
+ if (ptd.argnum2 < num) {
+ if (XPT_PD_IS_IN(ptd.param_flags))
+ pdescs[ptd.argnum2].is_auto_in = PR_TRUE;
+ if (XPT_PD_IS_OUT(ptd.param_flags))
+ pdescs[ptd.argnum2].is_auto_out = PR_TRUE;
+ }
+ break;
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index");
+ if (ptd.argnum < num) {
+ if (XPT_PD_IS_IN(ptd.param_flags))
+ pdescs[ptd.argnum].is_auto_in = PR_TRUE;
+ if (XPT_PD_IS_OUT(ptd.param_flags))
+ pdescs[ptd.argnum].is_auto_out = PR_TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ int total_params_needed = 0;
+ for (i=0;i<num;i++)
+ if (XPT_PD_IS_IN(pdescs[i].param_flags) && !pdescs[i].is_auto_in && !XPT_PD_IS_DIPPER(pdescs[i].param_flags))
+ total_params_needed++;
+
+ return total_params_needed;
+}
+
+/*************************************************************************
+**************************************************************************
+
+Helpers when CALLING interfaces.
+
+**************************************************************************
+*************************************************************************/
+
+PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent, int methodindex)
+{
+ m_var_array=nsnull;
+ m_buffer_array=nsnull;
+ m_pyparams=nsnull;
+ m_typedescs = nsnull;
+ m_python_type_desc_array = nsnull;
+ m_num_array = 0;
+ m_methodindex = methodindex;
+ // Parent should never die before we do, but let's not take the chance.
+ m_parent = parent;
+ Py_INCREF(parent);
+}
+
+PyXPCOM_InterfaceVariantHelper::~PyXPCOM_InterfaceVariantHelper()
+{
+ Py_DECREF(m_parent);
+ Py_XDECREF(m_pyparams);
+ for (int i=0;i<m_num_array;i++) {
+ if (m_var_array) {
+ nsXPTCVariant &ns_v = m_var_array[i];
+ if (ns_v.IsValInterface()) {
+ if (ns_v.val.p) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ ((nsISupports *)ns_v.val.p)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+ }
+ if (ns_v.IsValDOMString() && ns_v.val.p) {
+ delete (const nsAString *)ns_v.val.p;
+ }
+ if (ns_v.IsValCString() && ns_v.val.p) {
+ delete (const nsACString *)ns_v.val.p;
+ }
+ if (ns_v.IsValUTF8String() && ns_v.val.p) {
+ delete (const nsACString *)ns_v.val.p;
+ }
+ if (ns_v.IsValArray()) {
+ nsXPTCVariant &ns_v = m_var_array[i];
+ if (ns_v.val.p) {
+ PRUint8 array_type = (PRUint8)PyInt_AsLong(m_python_type_desc_array[i].extra);
+ PRUint32 seq_size = GetSizeIs(i, PR_FALSE);
+ FreeSingleArray(ns_v.val.p, seq_size, array_type);
+ }
+ }
+ // IsOwned must be the last check of the loop, as
+ // this frees the underlying data used above (eg, by the array free process)
+ if (ns_v.IsValAllocated() && !ns_v.IsValInterface() && !ns_v.IsValDOMString()) {
+ NS_ABORT_IF_FALSE(ns_v.IsPtrData(), "expecting a pointer to free");
+ nsMemory::Free(ns_v.val.p);
+ }
+ }
+ if (m_buffer_array && m_buffer_array[i])
+ nsMemory::Free(m_buffer_array[i]);
+ }
+ delete [] m_python_type_desc_array;
+ delete [] m_buffer_array;
+ delete [] m_var_array;
+}
+
+PRBool PyXPCOM_InterfaceVariantHelper::Init(PyObject *obParams)
+{
+ PRBool ok = PR_FALSE;
+ int i;
+ int total_params_needed = 0;
+ if (!PySequence_Check(obParams) || PySequence_Length(obParams)!=2) {
+ PyErr_Format(PyExc_TypeError, "Param descriptors must be a sequence of exactly length 2");
+ return PR_FALSE;
+ }
+ PyObject *typedescs = PySequence_GetItem(obParams, 0);
+ if (typedescs==NULL)
+ return PR_FALSE;
+ // NOTE: The length of the typedescs may be different than the
+ // args actually passed. The typedescs always include all
+ // hidden params (such as "size_is"), while the actual
+ // args never include this.
+ m_num_array = PySequence_Length(typedescs);
+ if (PyErr_Occurred()) goto done;
+
+ m_pyparams = PySequence_GetItem(obParams, 1);
+ if (m_pyparams==NULL) goto done;
+
+ m_python_type_desc_array = new PythonTypeDescriptor[m_num_array];
+ if (!m_python_type_desc_array) goto done;
+
+ // Pull apart the type descs and stash them.
+ for (i=0;i<m_num_array;i++) {
+ PyObject *desc_object = PySequence_GetItem(typedescs, i);
+ if (desc_object==NULL)
+ goto done;
+
+ // Pull apart the typedesc tuple back into a structure we can work with.
+ PythonTypeDescriptor &ptd = m_python_type_desc_array[i];
+ PRBool this_ok = PyArg_ParseTuple(desc_object, "bbbbO:type_desc",
+ &ptd.param_flags, &ptd.type_flags, &ptd.argnum, &ptd.argnum2, &ptd.extra);
+ Py_DECREF(desc_object);
+ if (!this_ok) goto done;
+ Py_INCREF(ptd.extra);
+
+ }
+ total_params_needed = ProcessPythonTypeDescriptors(m_python_type_desc_array, m_num_array);
+ // OK - check we got the number of args we expected.
+ // If not, its really an internal error rather than the user.
+ if (PySequence_Length(m_pyparams) != total_params_needed) {
+#ifdef VBOX
+ PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %ld were provided",
+ total_params_needed, (long)PySequence_Length(m_pyparams));
+#else
+ PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %d were provided",
+ total_params_needed, PySequence_Length(m_pyparams));
+#endif
+ goto done;
+ }
+
+ // Init the other arrays.
+ m_var_array = new nsXPTCVariant[m_num_array];
+ if (!m_var_array) goto done;
+ /*memset(m_var_array, 0, m_num_array * sizeof(m_var_array[0])); - VBox not needed */
+
+ m_buffer_array = new void *[m_num_array];
+ if (!m_buffer_array) goto done;
+ memset(m_buffer_array, 0, m_num_array * sizeof(m_buffer_array[0]));
+
+ ok = PR_TRUE;
+done:
+ if (!ok && !PyErr_Occurred())
+ PyErr_NoMemory();
+
+ Py_XDECREF(typedescs);
+ return ok;
+}
+
+
+PRBool PyXPCOM_InterfaceVariantHelper::FillArray()
+{
+ int param_index = 0;
+ int i;
+ for (i=0;i<m_num_array;i++) {
+ PythonTypeDescriptor &ptd = m_python_type_desc_array[i];
+ // stash the type_flags into the variant, and remember how many extra bits of info we have.
+ m_var_array[i].type = ptd.type_flags;
+ if (XPT_PD_IS_IN(ptd.param_flags) && !ptd.is_auto_in && !XPT_PD_IS_DIPPER(ptd.param_flags)) {
+ if (!FillInVariant(ptd, i, param_index))
+ return PR_FALSE;
+ param_index++;
+ }
+ if ((XPT_PD_IS_OUT(ptd.param_flags) && !ptd.is_auto_out) || XPT_PD_IS_DIPPER(ptd.param_flags)) {
+ if (!PrepareOutVariant(ptd, i))
+ return PR_FALSE;
+ }
+ }
+ // There may be out "size_is" params we havent touched yet
+ // (ie, as the param itself is marked "out", we never got to
+ // touch the associated "size_is".
+ // Final loop to handle this.
+ for (i=0;i<m_num_array;i++) {
+ PythonTypeDescriptor &ptd = m_python_type_desc_array[i];
+ if (ptd.is_auto_out && !ptd.have_set_auto) {
+ // Call PrepareOutVariant to ensure buffers etc setup.
+ if (!PrepareOutVariant(ptd, i))
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+
+
+PRBool PyXPCOM_InterfaceVariantHelper::SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_array, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_array, "size_is param is invalid");
+ PythonTypeDescriptor &td_size = m_python_type_desc_array[argnum];
+ NS_ABORT_IF_FALSE(td_size.is_auto_in || td_size.is_auto_out, "Setting size_is, but param is not marked as auto!");
+ NS_ABORT_IF_FALSE( (td_size.type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ nsXPTCVariant &ns_v = m_var_array[argnum];
+
+ if (!td_size.have_set_auto) {
+ ns_v.type = td_size.type_flags;
+ ns_v.val.u32 = new_size;
+ // In case it is "out", setup the necessary pointers.
+ PrepareOutVariant(td_size, argnum);
+ td_size.have_set_auto = PR_TRUE;
+ } else {
+ if (ns_v.val.u32 != new_size) {
+ PyErr_Format(PyExc_ValueError, "Array lengths inconsistent; array size previously set to %d, but second array is of size %d", ns_v.val.u32, new_size);
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+
+PRUint32 PyXPCOM_InterfaceVariantHelper::GetSizeIs( int var_index, PRBool is_arg1)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_array, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_array, "size_is param is invalid");
+ NS_ABORT_IF_FALSE( (m_python_type_desc_array[argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ PRBool is_out = XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags);
+ nsXPTCVariant &ns_v = m_var_array[argnum];
+ return is_out ? *((PRUint32 *)ns_v.ptr) : ns_v.val.u32;
+}
+
+#define MAKE_VALUE_BUFFER(size) \
+ if ((this_buffer_pointer = (void *)nsMemory::Alloc((size))) == nsnull) { \
+ PyErr_NoMemory(); \
+ BREAK_FALSE; \
+ }
+
+PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor &td, int value_index, int param_index)
+{
+ PRBool rc = PR_TRUE;
+ // Get a reference to the variant we are filling for convenience.
+ nsXPTCVariant &ns_v = m_var_array[value_index];
+ NS_ABORT_IF_FALSE(ns_v.type == td.type_flags, "Expecting variant all setup for us");
+
+ // We used to avoid passing internal buffers to PyString etc objects
+ // for 2 reasons: paranoia (so incorrect external components couldn't break
+ // Python) and simplicity (in vs in-out issues, etc)
+ // However, at least one C++ implemented component (nsITimelineService)
+ // uses a "char *", and keys on the address (assuming that the same
+ // *pointer* is passed rather than value. Therefore, we have a special case
+ // - T_CHAR_STR that is "in" gets the Python string pointer passed.
+ void *&this_buffer_pointer = m_buffer_array[value_index]; // Freed at object destruction with PyMem_Free()
+ NS_ABORT_IF_FALSE(this_buffer_pointer==nsnull, "We appear to already have a buffer");
+ int cb_this_buffer_pointer = 0;
+ if (XPT_PD_IS_IN(td.param_flags)) {
+ NS_ABORT_IF_FALSE(!td.is_auto_in, "Param is 'auto-in', but we are filling it normally!");
+ PyObject *val_use = NULL; // a temp object converters can use, and will be DECREF'd
+ PyObject *val = PySequence_GetItem(m_pyparams, param_index);
+ NS_WARN_IF_FALSE(val, "Have an 'in' param, but no Python value!");
+ if (val==NULL) {
+ PyErr_Format(PyExc_ValueError, "Param %d is marked as 'in', but no value was given", value_index);
+ return PR_FALSE;
+ }
+ switch (XPT_TDP_TAG(ns_v.type)) {
+ case nsXPTType::T_I8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.i8 = (PRInt8)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_I16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.i16 = (PRInt16)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_I32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.i32 = (PRInt32)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_I64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE
+ ns_v.val.i64 = (PRInt64)PyLong_AsLongLong(val_use);
+ break;
+ case nsXPTType::T_U8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.u8 = (PRUint8)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_U16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.u16 = (PRUint16)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_U32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.u32 = (PRUint32)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_U64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE
+ ns_v.val.u64 = (PRUint64)PyLong_AsUnsignedLongLong(val_use);
+ break;
+ case nsXPTType::T_FLOAT:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ ns_v.val.f = (float)PyFloat_AsDouble(val_use);
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ ns_v.val.d = PyFloat_AsDouble(val_use);
+ break;
+ case nsXPTType::T_BOOL:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ ns_v.val.b = (PRBool)PyInt_AsLong(val_use);
+ break;
+ case nsXPTType::T_CHAR:{
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ if (PyString_GET_SIZE(val_use) != 1) {
+ PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+ BREAK_FALSE;
+ }
+
+ ns_v.val.c = *PyString_AS_STRING(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if (PyUnicode_GET_SIZE(val) != 1) {
+ PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+ BREAK_FALSE;
+ }
+
+# ifndef Py_LIMITED_API
+ ns_v.val.c = *PyUnicode_AS_UNICODE(val_use);
+# else
+ ns_v.val.c = PyUnicode_ReadChar(val_use, 0);
+# endif
+#endif
+ break;
+ }
+
+ case nsXPTType::T_WCHAR: {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+#endif
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyUnicode_FromObject() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a unicode object!");
+ if (PyUnicode_GET_SIZE(val_use) != 1) {
+ PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character");
+ BREAK_FALSE;
+ }
+ // Lossy!
+#ifndef Py_LIMITED_API
+ ns_v.val.wc = *PyUnicode_AS_UNICODE(val_use);
+#else
+ ns_v.val.wc = PyUnicode_ReadChar(val_use, 0);
+#endif
+ break;
+ }
+ // case nsXPTType::T_VOID: /* fall through */
+ case nsXPTType::T_IID:
+ nsIID iid;
+ MAKE_VALUE_BUFFER(sizeof(nsIID));
+ if (!Py_nsIID::IIDFromPyObject(val, &iid))
+ BREAK_FALSE;
+ memcpy(this_buffer_pointer, &iid, sizeof(iid));
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ nsString *s = new nsString();
+ if (!s) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ ns_v.val.p = s;
+ // We created it - flag as such for cleanup.
+ ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR;
+
+ if (!PyObject_AsNSString(val, *s))
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_UTF8STRING: {
+ PRBool bIsUTF8 = XPT_TDP_TAG(ns_v.type) == nsXPTType::T_UTF8STRING;
+ if (val==Py_None) {
+ ns_v.val.p = new nsCString();
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(val)) {
+ // strings are assumed to already be UTF8 encoded.
+ val_use = val;
+ Py_INCREF(val);
+ }
+ else
+#endif
+ if (PyUnicode_Check(val)) {
+ // Unicode objects are encoded by us.
+ if (bIsUTF8)
+ val_use = PyUnicode_AsUTF8String(val);
+ else
+#if PY_MAJOR_VERSION <= 2
+ val_use = PyObject_Str(val);
+#else
+ val_use = PyUnicode_AsUTF8String(val);
+#endif
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects");
+#else
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be unicode objects");
+#endif
+ BREAK_FALSE;
+ }
+ if (!val_use)
+ BREAK_FALSE;
+#if PY_MAJOR_VERSION <= 2
+ ns_v.val.p = new nsCString(PyString_AS_STRING(val_use),
+ PyString_GET_SIZE(val_use));
+#else
+ ns_v.val.p = new nsCString(PyBytes_AS_STRING(val_use),
+ PyBytes_GET_SIZE(val_use));
+#endif
+ }
+
+ if (!ns_v.val.p) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ // We created it - flag as such for cleanup.
+ ns_v.flags |= bIsUTF8 ? nsXPTCVariant::VAL_IS_UTF8STR : nsXPTCVariant::VAL_IS_CSTR;
+ break;
+ }
+ case nsXPTType::T_CHAR_STR: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ // If an "in" char *, and we have a PyString, then pass the
+ // pointer (hoping everyone else plays by the rules too.
+ if (!XPT_PD_IS_OUT(td.param_flags) && PyString_Check(val)) {
+ ns_v.val.p = (void *)PyString_AS_STRING(val);
+ break;
+ }
+
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ cb_this_buffer_pointer = PyString_GET_SIZE(val_use)+1;
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyString_AS_STRING(val_use), cb_this_buffer_pointer);
+#else
+
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ cb_this_buffer_pointer = PyBytes_GET_SIZE(val_use)+1;
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyBytes_AS_STRING(val_use), cb_this_buffer_pointer);
+#endif
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ }
+
+ case nsXPTType::T_WCHAR_STR: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ PRUnichar *sv;
+ PRUint32 nch;
+ if (PyUnicode_AsPRUnichar(val_use, &sv, &nch) < 0)
+ BREAK_FALSE;
+ cb_this_buffer_pointer = (nch + 1) * sizeof(PRUnichar);
+ this_buffer_pointer = sv;
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ }
+ case nsXPTType::T_INTERFACE: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(td.extra, &iid))
+ BREAK_FALSE;
+ if (!Py_nsISupports::InterfaceFromPyObject(
+ val,
+ iid,
+ (nsISupports **)&ns_v.val.p,
+ PR_TRUE))
+ BREAK_FALSE;
+ // We have added a reference - flag as such for cleanup.
+ ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE;
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: {
+ nsIID iid;
+ nsXPTCVariant &ns_viid = m_var_array[td.argnum];
+ NS_WARN_IF_FALSE(XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!");
+ // This is a pretty serious problem, but not Python's fault!
+ // Just return an nsISupports and hope the caller does whatever
+ // QI they need before using it.
+ if (XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID &&
+ XPT_PD_IS_IN(ns_viid.type)) {
+ nsIID *piid = (nsIID *)ns_viid.val.p;
+ if (piid==NULL)
+ // Also serious, but like below, not our fault!
+ iid = NS_GET_IID(nsISupports);
+ else
+ iid = *piid;
+ } else
+ // Use NULL IID to avoid a QI in this case.
+ iid = Py_nsIID_NULL;
+ if (!Py_nsISupports::InterfaceFromPyObject(
+ val,
+ iid,
+ (nsISupports **)&ns_v.val.p,
+ PR_TRUE))
+ BREAK_FALSE;
+ // We have added a reference - flag as such for cleanup.
+ ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE;
+ break;
+ }
+ case nsXPTType::T_PSTRING_SIZE_IS: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ cb_this_buffer_pointer = PyString_GET_SIZE(val_use);
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyString_AS_STRING(val_use), cb_this_buffer_pointer);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ cb_this_buffer_pointer = PyBytes_GET_SIZE(val_use);
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memcpy(this_buffer_pointer, PyBytes_AS_STRING(val_use), cb_this_buffer_pointer);
+#endif
+ ns_v.val.p = this_buffer_pointer;
+ rc = SetSizeIs(value_index, PR_TRUE, cb_this_buffer_pointer);
+ break;
+ }
+
+ case nsXPTType::T_PWSTRING_SIZE_IS: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyObject_Unicode didnt return a unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ PRUnichar *sv;
+ PRUint32 nch;
+ if (PyUnicode_AsPRUnichar(val_use, &sv, &nch) < 0)
+ BREAK_FALSE;
+ cb_this_buffer_pointer = (nch + 1) * sizeof(PRUnichar);
+ this_buffer_pointer = sv;
+ ns_v.val.p = this_buffer_pointer;
+ rc = SetSizeIs(value_index, PR_TRUE, nch);
+ break;
+ }
+ case nsXPTType::T_ARRAY: {
+ if (val==Py_None) {
+ ns_v.val.p = nsnull;
+ break;
+ }
+ if (!PyInt_Check(td.extra)) {
+ PyErr_SetString(PyExc_TypeError, "The array info is not valid");
+ BREAK_FALSE;
+ }
+ if (!PySequence_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a sequence");
+ BREAK_FALSE;
+ }
+ int array_type = PyInt_AsLong(td.extra);
+ PRUint32 element_size = GetArrayElementSize(array_type);
+ int seq_length = PySequence_Length(val);
+ cb_this_buffer_pointer = seq_length * element_size;
+ if (cb_this_buffer_pointer==0)
+ // prevent assertions allocing zero bytes. Can't use NULL.
+ cb_this_buffer_pointer = 1;
+ MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
+ memset(this_buffer_pointer, 0, cb_this_buffer_pointer);
+ rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK, nsnull);
+ if (!rc) break;
+ rc = SetSizeIs(value_index, PR_FALSE, seq_length);
+ if (!rc) break;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ARRAY;
+ ns_v.val.p = this_buffer_pointer;
+ break;
+ }
+ default:
+ PyErr_Format(PyExc_TypeError, "The object type (0x%x) is unknown", XPT_TDP_TAG(ns_v.type));
+ rc = PR_FALSE;
+ break;
+ }
+ Py_DECREF(val); // Cant be NULL!
+ Py_XDECREF(val_use);
+ }
+ return rc && !PyErr_Occurred();
+}
+
+PRBool PyXPCOM_InterfaceVariantHelper::PrepareOutVariant(const PythonTypeDescriptor &td, int value_index)
+{
+ PRBool rc = PR_TRUE;
+ nsXPTCVariant &ns_v = m_var_array[value_index];
+ void *&this_buffer_pointer = m_buffer_array[value_index]; // Freed at object destruction with PyMem_Free()
+ // Do the out param thang...
+ if (XPT_PD_IS_OUT(td.param_flags) || XPT_PD_IS_DIPPER(td.param_flags)) {
+ NS_ABORT_IF_FALSE(ns_v.ptr == NULL, "already have a pointer!");
+ ns_v.ptr = &ns_v;
+ ns_v.flags |= nsXPTCVariant::PTR_IS_DATA;
+
+ // Special flags based on the data type
+ switch (XPT_TDP_TAG(ns_v.type)) {
+ case nsXPTType::T_I8:
+ case nsXPTType::T_I16:
+ case nsXPTType::T_I32:
+ case nsXPTType::T_I64:
+ case nsXPTType::T_U8:
+ case nsXPTType::T_U16:
+ case nsXPTType::T_U32:
+ case nsXPTType::T_U64:
+ case nsXPTType::T_FLOAT:
+ case nsXPTType::T_DOUBLE:
+ case nsXPTType::T_BOOL:
+ case nsXPTType::T_CHAR:
+ case nsXPTType::T_WCHAR:
+ case nsXPTType::T_VOID:
+ break;
+
+ case nsXPTType::T_INTERFACE:
+ case nsXPTType::T_INTERFACE_IS:
+ NS_ABORT_IF_FALSE(this_buffer_pointer==NULL, "Can't have an interface and a buffer pointer!");
+ ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+ break;
+ case nsXPTType::T_ARRAY:
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ARRAY;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+ // Even if ns_val.p already setup as part of "in" processing,
+ // we need to ensure setup for out.
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull || ns_v.val.p==this_buffer_pointer, "Garbage in our pointer?");
+ ns_v.val.p = this_buffer_pointer;
+ this_buffer_pointer = nsnull;
+ break;
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ case nsXPTType::T_WCHAR_STR:
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_IID:
+ // If we stashed a value in the this_buffer_pointer, and
+ // we are passing it as an OUT param, we do _not_ want to
+ // treat it as a temporary buffer.
+ // For example, if we pass an IID or string as an IN param,
+ // we allocate a buffer for the value, but this is NOT cleaned up
+ // via normal VARIANT cleanup rules - hence we clean it up ourselves.
+ // If the param is IN/OUT, then the buffer falls under the normal variant
+ // rules (ie, is flagged as VAL_IS_ALLOCD), so we dont clean it as a temporary.
+ // (it may have been changed under us - we free the _new_ value.
+ // Even if ns_val.p already setup as part of "in" processing,
+ // we need to ensure setup for out.
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull || ns_v.val.p==this_buffer_pointer, "Garbage in our pointer?");
+ ns_v.val.p = this_buffer_pointer;
+ ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD;
+ this_buffer_pointer = nsnull;
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING: {
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull, "T_DOMTSTRINGS cant be out and have a value (ie, no in/outs are allowed!");
+ NS_ABORT_IF_FALSE(XPT_PD_IS_DIPPER(td.param_flags) && XPT_PD_IS_IN(td.param_flags), "out DOMStrings must really be in dippers!");
+ ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR;
+ // Dippers are really treated like "in" params.
+ ns_v.ptr = new nsString();
+ ns_v.val.p = ns_v.ptr; // VAL_IS_* says the .p is what gets freed
+ if (!ns_v.ptr) {
+ PyErr_NoMemory();
+ rc = PR_FALSE;
+ }
+ break;
+ }
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_UTF8STRING: {
+ NS_ABORT_IF_FALSE(ns_v.val.p==nsnull, "T_DOMTSTRINGS cant be out and have a value (ie, no in/outs are allowed!");
+ NS_ABORT_IF_FALSE(XPT_PD_IS_DIPPER(td.param_flags) && XPT_PD_IS_IN(td.param_flags), "out DOMStrings must really be in dippers!");
+ ns_v.flags |= ( XPT_TDP_TAG(ns_v.type)==nsXPTType::T_CSTRING ? nsXPTCVariant::VAL_IS_CSTR : nsXPTCVariant::VAL_IS_UTF8STR);
+ ns_v.ptr = new nsCString();
+ ns_v.val.p = ns_v.ptr; // VAL_IS_* says the .p is what gets freed
+ if (!ns_v.ptr) {
+ PyErr_NoMemory();
+ rc = PR_FALSE;
+ }
+ break;
+ }
+ default:
+ NS_ABORT_IF_FALSE(0, "Unknown type - don't know how to prepare the output value");
+ break; // Nothing to do!
+ }
+ }
+ return rc;
+}
+
+
+PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
+{
+ nsXPTCVariant &ns_v = m_var_array[index];
+ PyObject *ret = nsnull;
+ NS_ABORT_IF_FALSE(ns_v.IsPtrData() || ns_v.IsValDOMString(), "expecting a pointer if you want a result!");
+
+ // Re-fetch the type descriptor.
+ PythonTypeDescriptor &td = m_python_type_desc_array[index];
+ // Make sure the type tag of the variant hasnt changed on us.
+ NS_ABORT_IF_FALSE(ns_v.type==td.type_flags, "variant type has changed under us!");
+
+ // If the pointer is NULL, we can get out now!
+ if (ns_v.ptr==nsnull) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ switch (XPT_TDP_TAG(ns_v.type)) {
+ case nsXPTType::T_I8:
+ ret = PyInt_FromLong( *((PRInt8 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_I16:
+ ret = PyInt_FromLong( *((PRInt16 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_I32:
+ ret = PyInt_FromLong( *((PRInt32 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_I64:
+ ret = PyLong_FromLongLong( *((PRInt64 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U8:
+ ret = PyInt_FromLong( *((PRUint8 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U16:
+ ret = PyInt_FromLong( *((PRUint16 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U32:
+ ret = PyInt_FromLong( *((PRUint32 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_U64:
+ ret = PyLong_FromUnsignedLongLong( *((PRUint64 *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_FLOAT:
+ ret = PyFloat_FromDouble( *((float *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ ret = PyFloat_FromDouble( *((double *)ns_v.ptr) );
+ break;
+ case nsXPTType::T_BOOL:
+ ret = *((PRBool *)ns_v.ptr) ? Py_True : Py_False;
+ Py_INCREF(ret);
+ break;
+ case nsXPTType::T_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize( ((char *)ns_v.ptr), 1 );
+#else
+ ret = PyUnicode_FromStringAndSize( ((char *)ns_v.ptr), 1 );
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR:
+ ret = PyUnicode_FromPRUnichar( ((PRUnichar *)ns_v.ptr), 1 );
+ break;
+// case nsXPTType::T_VOID:
+ case nsXPTType::T_IID:
+ ret = Py_nsIID::PyObjectFromIID( **((nsIID **)ns_v.ptr) );
+ break;
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ nsAString *rs = (nsAString *)ns_v.ptr;
+ ret = PyObject_FromNSString(*rs);
+ break;
+ }
+ case nsXPTType::T_UTF8STRING:
+ case nsXPTType::T_CSTRING: {
+ nsCString *rs = (nsCString *)ns_v.ptr;
+ ret = PyObject_FromNSString(*rs, XPT_TDP_TAG(ns_v.type)==nsXPTType::T_UTF8STRING);
+ break;
+ }
+
+ case nsXPTType::T_CHAR_STR:
+ if (*((char **)ns_v.ptr) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString( *((char **)ns_v.ptr) );
+#else
+ ret = PyUnicode_FromString( *((char **)ns_v.ptr) );
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR_STR: {
+ PRUnichar *us = *((PRUnichar **)ns_v.ptr);
+ if (us == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ ret = PyUnicode_FromPRUnichar( us, nsCRT::strlen(us));
+ }
+ break;
+ }
+ case nsXPTType::T_INTERFACE: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(td.extra, &iid))
+ break;
+ nsISupports *iret = *((nsISupports **)ns_v.ptr);
+ // Our cleanup code manages iret reference ownership, and our
+ // new object takes its own.
+ if (iid.Equals(NS_GET_IID(nsIVariant)))
+ ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
+ else
+ ret = m_parent->MakeInterfaceResult(iret, iid);
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: {
+ nsIID iid;
+ nsXPTCVariant &ns_viid = m_var_array[td.argnum];
+ NS_WARN_IF_FALSE(XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!");
+ if (XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID) {
+ nsIID *piid = (nsIID *)ns_viid.val.p;
+ if (piid==NULL)
+ // Also serious, but like below, not our fault!
+ iid = NS_GET_IID(nsISupports);
+ else
+ iid = *piid;
+ } else {
+ // This is a pretty serious problem, but not Python's fault!
+ // Just return an nsISupports and hope the caller does whatever
+ // QI they need before using it.
+ NS_ERROR("Failed to get the IID for T_INTERFACE_IS!");
+ iid = NS_GET_IID(nsISupports);
+ }
+ nsISupports *iret = *((nsISupports **)ns_v.ptr);
+ if (iid.Equals(NS_GET_IID(nsIVariant)))
+ ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
+ else
+ ret = m_parent->MakeInterfaceResult(iret, iid);
+ break;
+ }
+ case nsXPTType::T_ARRAY: {
+ if ( (* ((void **)ns_v.ptr)) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ }
+ if (!PyInt_Check(td.extra)) {
+ PyErr_SetString(PyExc_TypeError, "The array info is not valid");
+ break;
+ }
+ PRUint8 array_type = (PRUint8)PyInt_AsLong(td.extra);
+ PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
+ nsXPTCVariant &ns_viid = m_var_array[td.argnum];
+ nsIID iid;
+ nsresult res = GetArrayElementIID(m_parent,
+ m_var_array,
+ m_methodindex,
+ index,
+ &iid);
+ ret = UnpackSingleArray(m_parent, * ((void **)ns_v.ptr),
+ seq_size, array_type&XPT_TDP_TAGMASK,
+ NS_SUCCEEDED(res) ? &iid : NULL);
+ break;
+ }
+
+ case nsXPTType::T_PSTRING_SIZE_IS:
+ if (*((char **)ns_v.ptr) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize( *((char **)ns_v.ptr), string_size );
+#else
+ ret = PyUnicode_FromStringAndSize( *((char **)ns_v.ptr), string_size );
+#endif
+ }
+ break;
+
+ case nsXPTType::T_PWSTRING_SIZE_IS:
+ if (*((PRUnichar **)ns_v.ptr) == NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+ ret = PyUnicode_FromPRUnichar( *((PRUnichar **)ns_v.ptr), string_size );
+ }
+ break;
+ default:
+ PyErr_Format(PyExc_ValueError, "Unknown XPCOM type code (0x%x)", XPT_TDP_TAG(ns_v.type));
+ /* ret remains nsnull */
+ break;
+ }
+ return ret;
+}
+
+
+PyObject *PyXPCOM_InterfaceVariantHelper::MakePythonResult()
+{
+ // First we count the results.
+ int i = 0;
+ int n_results = 0;
+ PyObject *ret = NULL;
+ PRBool have_retval = PR_FALSE;
+ for (i=0;i<m_num_array;i++) {
+ PythonTypeDescriptor &td = m_python_type_desc_array[i];
+ if (!td.is_auto_out) {
+ if (XPT_PD_IS_OUT(td.param_flags) || XPT_PD_IS_DIPPER(td.param_flags))
+ n_results++;
+ if (XPT_PD_IS_RETVAL(td.param_flags))
+ have_retval = PR_TRUE;
+ }
+ }
+ if (n_results==0) {
+ ret = Py_None;
+ Py_INCREF(ret);
+ } else {
+ if (n_results > 1) {
+ ret = PyTuple_New(n_results);
+ if (ret==NULL)
+ return NULL;
+ }
+ int ret_index = 0;
+ int max_index = m_num_array;
+ // Stick the retval at the front if we have have
+ if (have_retval && n_results > 1) {
+ PyObject *val = MakeSinglePythonResult(m_num_array-1);
+ if (val==NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(ret, 0, val);
+ max_index--;
+ ret_index++;
+
+ }
+ for (i=0;ret_index < n_results && i < max_index;i++) {
+ if (!m_python_type_desc_array[i].is_auto_out) {
+ if (XPT_PD_IS_OUT(m_python_type_desc_array[i].param_flags) || XPT_PD_IS_DIPPER(m_python_type_desc_array[i].param_flags)) {
+ PyObject *val = MakeSinglePythonResult(i);
+ if (val==NULL) {
+ Py_XDECREF(ret);
+ return NULL;
+ }
+ if (n_results > 1) {
+ PyTuple_SET_ITEM(ret, ret_index, val);
+ ret_index++;
+ } else {
+ NS_ABORT_IF_FALSE(ret==NULL, "shouldnt already have a ret!");
+ ret = val;
+ }
+ }
+ }
+ }
+
+ }
+ return ret;
+}
+
+/*************************************************************************
+**************************************************************************
+
+ Helpers when IMPLEMENTING interfaces.
+
+**************************************************************************
+*************************************************************************/
+
+PyXPCOM_GatewayVariantHelper::PyXPCOM_GatewayVariantHelper( PyG_Base *gw, int method_index, const nsXPTMethodInfo *info, nsXPTCMiniVariant* params )
+{
+ m_params = params;
+ m_info = info;
+ // no references added - this class is only alive for
+ // a single gateway invocation
+ m_gateway = gw;
+ m_method_index = method_index;
+ m_python_type_desc_array = NULL;
+ m_num_type_descs = 0;
+}
+
+PyXPCOM_GatewayVariantHelper::~PyXPCOM_GatewayVariantHelper()
+{
+ delete [] m_python_type_desc_array;
+}
+
+PyObject *PyXPCOM_GatewayVariantHelper::MakePyArgs()
+{
+ NS_PRECONDITION(sizeof(XPTParamDescriptor) == sizeof(nsXPTParamInfo), "We depend on nsXPTParamInfo being a wrapper over the XPTParamDescriptor struct");
+ // Setup our array of Python typedescs, and determine the number of objects we
+ // pass to Python.
+ m_num_type_descs = m_info->num_args;
+ m_python_type_desc_array = new PythonTypeDescriptor[m_num_type_descs];
+ if (m_python_type_desc_array==nsnull)
+ return PyErr_NoMemory();
+
+ // First loop to count the number of objects
+ // we pass to Python
+ int i;
+ for (i=0;i<m_info->num_args;i++) {
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i;
+ PythonTypeDescriptor &td = m_python_type_desc_array[i];
+ td.param_flags = pi->flags;
+ td.type_flags = pi->type.prefix.flags;
+ td.argnum = pi->type.argnum;
+ td.argnum2 = pi->type.argnum2;
+ }
+ int num_args = ProcessPythonTypeDescriptors(m_python_type_desc_array, m_num_type_descs);
+ PyObject *ret = PyTuple_New(num_args);
+ if (ret==NULL)
+ return NULL;
+ int this_arg = 0;
+ for (i=0;i<m_num_type_descs;i++) {
+ PythonTypeDescriptor &td = m_python_type_desc_array[i];
+ if (XPT_PD_IS_IN(td.param_flags) && !td.is_auto_in && !XPT_PD_IS_DIPPER(td.param_flags)) {
+ PyObject *sub = MakeSingleParam( i, td );
+ if (sub==NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ NS_ABORT_IF_FALSE(this_arg>=0 && this_arg<num_args, "We are going off the end of the array!");
+ PyTuple_SET_ITEM(ret, this_arg, sub);
+ this_arg++;
+ }
+ }
+ return ret;
+}
+
+PRBool PyXPCOM_GatewayVariantHelper::CanSetSizeIs( int var_index, PRBool is_arg1 )
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid");
+ return XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags);
+}
+
+PRBool PyXPCOM_GatewayVariantHelper::SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid");
+ PythonTypeDescriptor &td_size = m_python_type_desc_array[argnum];
+ NS_ABORT_IF_FALSE( XPT_PD_IS_OUT(td_size.param_flags), "size param must be out if we want to set it!");
+ NS_ABORT_IF_FALSE(td_size.is_auto_out, "Setting size_is, but param is not marked as auto!");
+
+ nsXPTCMiniVariant &ns_v = m_params[argnum];
+ NS_ABORT_IF_FALSE( (td_size.type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ NS_ABORT_IF_FALSE(ns_v.val.p, "NULL pointer for size_is value!");
+ if (ns_v.val.p) {
+ if (!td_size.have_set_auto) {
+ *((PRUint32 *)ns_v.val.p) = new_size;
+ td_size.have_set_auto = PR_TRUE;
+ } else {
+ if (*((PRUint32 *)ns_v.val.p) != new_size ) {
+ PyErr_Format(PyExc_ValueError, "Array lengths inconsistent; array size previously set to %d, but second array is of size %d", ns_v.val.u32, new_size);
+ return PR_FALSE;
+ }
+ }
+ }
+ return PR_TRUE;
+}
+
+PRUint32 PyXPCOM_GatewayVariantHelper::GetSizeIs( int var_index, PRBool is_arg1)
+{
+ NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid");
+ PRUint8 argnum = is_arg1 ?
+ m_python_type_desc_array[var_index].argnum :
+ m_python_type_desc_array[var_index].argnum2;
+ NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid");
+ if (argnum >= m_num_type_descs) {
+ PyErr_SetString(PyExc_ValueError, "dont have a valid size_is indicator for this param");
+ return PR_FALSE;
+ }
+ PRBool is_out = XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags);
+ nsXPTCMiniVariant &ns_v = m_params[argnum];
+ NS_ABORT_IF_FALSE( (m_python_type_desc_array[argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32");
+ return is_out ? *((PRUint32 *)ns_v.val.p) : ns_v.val.u32;
+}
+
+#undef DEREF_IN_OR_OUT
+#define DEREF_IN_OR_OUT( element, ret_type ) (ret_type)(is_out ? *((ret_type *)ns_v.val.p) : (ret_type)(element))
+
+PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDescriptor &td)
+{
+ NS_PRECONDITION(XPT_PD_IS_IN(td.param_flags), "Must be an [in] param!");
+ nsXPTCMiniVariant &ns_v = m_params[index];
+ PyObject *ret = NULL;
+ PRBool is_out = XPT_PD_IS_OUT(td.param_flags);
+
+ switch (td.type_flags & XPT_TDP_TAGMASK) {
+ case nsXPTType::T_I8:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i8, PRInt8 ) );
+ break;
+ case nsXPTType::T_I16:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i16, PRInt16) );
+ break;
+ case nsXPTType::T_I32:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i32, PRInt32) );
+ break;
+ case nsXPTType::T_I64:
+ ret = PyLong_FromLongLong( DEREF_IN_OR_OUT(ns_v.val.i64, PRInt64) );
+ break;
+ case nsXPTType::T_U8:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u8, PRUint8) );
+ break;
+ case nsXPTType::T_U16:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u16, PRUint16) );
+ break;
+ case nsXPTType::T_U32:
+ ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u32, PRUint32) );
+ break;
+ case nsXPTType::T_U64:
+ ret = PyLong_FromUnsignedLongLong( DEREF_IN_OR_OUT(ns_v.val.u64, PRUint64) );
+ break;
+ case nsXPTType::T_FLOAT:
+ ret = PyFloat_FromDouble( DEREF_IN_OR_OUT(ns_v.val.f, float) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ ret = PyFloat_FromDouble( DEREF_IN_OR_OUT(ns_v.val.d, double) );
+ break;
+ case nsXPTType::T_BOOL: {
+ PRBool temp = DEREF_IN_OR_OUT(ns_v.val.b, PRBool);
+ ret = temp ? Py_True : Py_False;
+ Py_INCREF(ret);
+ break;
+ }
+ case nsXPTType::T_CHAR: {
+ char temp = DEREF_IN_OR_OUT(ns_v.val.c, char);
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize(&temp, 1);
+#else
+ ret = PyUnicode_FromStringAndSize(&temp, 1);
+#endif
+ break;
+ }
+ case nsXPTType::T_WCHAR: {
+ PRUnichar temp = (PRUnichar)DEREF_IN_OR_OUT(ns_v.val.wc, PRUnichar);
+ ret = PyUnicode_FromPRUnichar(&temp, 1);
+ break;
+ }
+// case nsXPTType::T_VOID:
+ case nsXPTType::T_IID: {
+ ret = Py_nsIID::PyObjectFromIID( * DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *) );
+ break;
+ }
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout");
+ const nsAString *rs = (const nsAString *)ns_v.val.p;
+ ret = PyObject_FromNSString(*rs);
+ break;
+ }
+ case nsXPTType::T_CSTRING:
+ case nsXPTType::T_UTF8STRING: {
+ NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout");
+ const nsCString *rs = (const nsCString *)ns_v.val.p;
+ ret = PyObject_FromNSString(*rs, (td.type_flags & XPT_TDP_TAGMASK)==nsXPTType::T_UTF8STRING);
+ break;
+ }
+ case nsXPTType::T_CHAR_STR: {
+ char *t = DEREF_IN_OR_OUT(ns_v.val.p, char *);
+ if (t==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(t);
+#else
+ ret = PyUnicode_FromString(t);
+#endif
+ break;
+ }
+
+ case nsXPTType::T_WCHAR_STR: {
+ PRUnichar *us = DEREF_IN_OR_OUT(ns_v.val.p, PRUnichar *);
+ if (us==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ ret = PyUnicode_FromPRUnichar( us, nsCRT::strlen(us));
+ }
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: // our Python code does it :-)
+ case nsXPTType::T_INTERFACE: {
+ nsISupports *iret = DEREF_IN_OR_OUT(ns_v.val.p, nsISupports *);
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ ret = m_gateway->MakeInterfaceParam(iret, NULL, m_method_index, pi, index);
+ break;
+ }
+/***
+ nsISupports *iret = DEREF_IN_OR_OUT(ns_v.val.p, nsISupports *);
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ nsXPTCMiniVariant &ns_viid = m_params[td.argnum];
+ NS_ABORT_IF_FALSE((m_python_type_desc_array[td.argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!");
+ const nsIID * iid = NULL;
+ if (XPT_PD_IS_IN(m_python_type_desc_array[td.argnum].param_flags))
+ // may still be inout!
+ iid = DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *);
+
+ ret = m_gateway->MakeInterfaceParam(iret, iid, m_method_index, pi, index);
+ break;
+ }
+****/
+ case nsXPTType::T_ARRAY: {
+ void *t = DEREF_IN_OR_OUT(ns_v.val.p, void *);
+ if (t==NULL) {
+ // JS may send us a NULL here occasionally - as the
+ // type is array, we silently convert this to a zero
+ // length list, a-la JS.
+ ret = PyList_New(0);
+ } else {
+ PRUint8 array_type;
+ nsIID *piid;
+ nsresult ns = GetArrayType(index, &array_type, &piid);
+ if (NS_FAILED(ns)) {
+ PyXPCOM_BuildPyException(ns);
+ break;
+ }
+ PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
+ ret = UnpackSingleArray(NULL, t, seq_size, array_type&XPT_TDP_TAGMASK, piid);
+ }
+ break;
+ }
+ case nsXPTType::T_PSTRING_SIZE_IS: {
+ char *t = DEREF_IN_OR_OUT(ns_v.val.p, char *);
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+ if (t==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromStringAndSize(t, string_size);
+#else
+ ret = PyUnicode_FromStringAndSize(t, string_size);
+#endif
+ break;
+ }
+ case nsXPTType::T_PWSTRING_SIZE_IS: {
+ PRUnichar *t = DEREF_IN_OR_OUT(ns_v.val.p, PRUnichar *);
+ PRUint32 string_size = GetSizeIs(index, PR_TRUE);
+ if (t==NULL) {
+ ret = Py_None;
+ Py_INCREF(Py_None);
+ } else {
+ ret = PyUnicode_FromPRUnichar(t, string_size);
+ }
+ break;
+ }
+ default:
+ // As this is called by external components,
+ // we return _something_ rather than failing before any user code has run!
+ {
+ char buf[128];
+ sprintf(buf, "Unknown XPCOM type flags (0x%x)", td.type_flags);
+ PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf);
+#if PY_MAJOR_VERSION <= 2
+ ret = PyString_FromString(buf);
+#else
+ ret = PyUnicode_FromString(buf);
+#endif
+ break;
+ }
+ }
+ return ret;
+}
+
+nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **iid)
+{
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!");
+ if (iim==nsnull)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ nsresult rc = iim->GetInfoForIID( &m_gateway->m_iid, getter_AddRefs(ii));
+ if (NS_FAILED(rc))
+ return rc;
+ nsXPTType datumType;
+ const nsXPTParamInfo& param_info = m_info->GetParam((PRUint8)index);
+ rc = ii->GetTypeForParam(m_method_index, &param_info, 1, &datumType);
+ if (NS_FAILED(rc))
+ return rc;
+ if (iid) {
+ *iid = (nsIID *)&NS_GET_IID(nsISupports);
+ if (XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE ||
+ XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE_IS ||
+ XPT_TDP_TAG(datumType)==nsXPTType::T_ARRAY)
+ ii->GetIIDForParam(m_method_index, &param_info, iid);
+ }
+ *ret = datumType.flags;
+ return NS_OK;
+}
+
+PRBool PyXPCOM_GatewayVariantHelper::GetIIDForINTERFACE_ID(int index, const nsIID **ppret)
+{
+ // Not sure if the IID pointed at by by this is allows to be
+ // in or out, so we will allow it.
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ nsXPTType typ = pi->GetType();
+ NS_WARN_IF_FALSE(XPT_TDP_TAG(typ) == nsXPTType::T_IID, "INTERFACE_IS IID param isnt an IID!");
+ NS_ABORT_IF_FALSE(typ.IsPointer(), "Expecting to re-fill a pointer value.");
+ if (XPT_TDP_TAG(typ) != nsXPTType::T_IID)
+ *ppret = &NS_GET_IID(nsISupports);
+ else {
+ nsXPTCMiniVariant &ns_v = m_params[index];
+ if (pi->IsOut()) {
+ nsIID **pp = (nsIID **)ns_v.val.p;
+ if (pp && *pp)
+ *ppret = *pp;
+ else
+ *ppret = &NS_GET_IID(nsISupports);
+ } else if (pi->IsIn()) {
+ nsIID *p = (nsIID *)ns_v.val.p;
+ if (p)
+ *ppret = p;
+ else
+ *ppret = &NS_GET_IID(nsISupports);
+ } else {
+ NS_ERROR("Param is not in or out!");
+ *ppret = &NS_GET_IID(nsISupports);
+ }
+ }
+ return PR_TRUE;
+}
+
+nsIInterfaceInfo *PyXPCOM_GatewayVariantHelper::GetInterfaceInfo()
+{
+ if (!m_interface_info) {
+ nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
+ NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
+ if (iim)
+ iim->GetInfoForIID(&m_gateway->m_iid, getter_AddRefs(m_interface_info));
+ }
+ return m_interface_info;
+}
+
+#undef FILL_SIMPLE_POINTER
+#define FILL_SIMPLE_POINTER( type, ob ) *((type *)ns_v.val.p) = (type)(ob)
+
+nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index)
+{
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index;
+ NS_ABORT_IF_FALSE(pi->IsOut() || pi->IsDipper(), "The value must be marked as [out] (or a dipper) to be back-filled!");
+ NS_ABORT_IF_FALSE(!pi->IsShared(), "Dont know how to back-fill a shared out param");
+ nsXPTCMiniVariant &ns_v = m_params[index];
+
+ nsXPTType typ = pi->GetType();
+ PyObject* val_use = NULL;
+
+ NS_ABORT_IF_FALSE(pi->IsDipper() || ns_v.val.p, "No space for result!");
+ if (!pi->IsDipper() && !ns_v.val.p) return NS_ERROR_INVALID_POINTER;
+
+ PRBool rc = PR_TRUE;
+ switch (XPT_TDP_TAG(typ)) {
+ case nsXPTType::T_I8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_I64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) );
+ break;
+ case nsXPTType::T_U8:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U16:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U32:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_U64:
+ if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
+ FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) );
+ break;
+ case nsXPTType::T_FLOAT:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) );
+ break;
+ case nsXPTType::T_BOOL:
+ if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
+ FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) );
+ break;
+ case nsXPTType::T_CHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) );
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+# ifndef Py_LIMITED_API
+ FILL_SIMPLE_POINTER( char, *PyUnicode_AS_UNICODE(val) );
+# else
+ FILL_SIMPLE_POINTER( char, PyUnicode_ReadChar(val, 0) );
+# endif
+#endif
+ break;
+
+ case nsXPTType::T_WCHAR:
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a Unicode object");
+ BREAK_FALSE;
+ }
+#endif
+ if ((val_use = PyUnicode_FromObject(val))==NULL)
+ BREAK_FALSE;
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+ // Lossy!
+#ifndef Py_LIMITED_API
+ FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
+#else
+ FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) );
+#endif
+ break;
+
+// case nsXPTType::T_VOID:
+ case nsXPTType::T_IID: {
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(val, &iid))
+ BREAK_FALSE;
+ nsIID **pp = (nsIID **)ns_v.val.p;
+ // If there is an existing [in] IID, free it.
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID));
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ memcpy(*pp, &iid, sizeof(iid));
+ break;
+ }
+
+ case nsXPTType::T_ASTRING:
+ case nsXPTType::T_DOMSTRING: {
+ nsAString *ws = (nsAString *)ns_v.val.p;
+ NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
+ if (!PyObject_AsNSString(val, *ws))
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_CSTRING: {
+ nsCString *ws = (nsCString *)ns_v.val.p;
+ NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
+ if (val == Py_None) {
+ NS_ABORT_IF_FALSE(0, "dont handle None here yet");
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyObject_Str(val);
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+ const char *sz = PyString_AS_STRING(val_use);
+ ws->Assign(sz, PyString_GET_SIZE(val_use));
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyUnicode_AsUTF8String(val);
+ const char *sz = PyBytes_AS_STRING(val_use);
+ ws->Assign(sz, PyBytes_GET_SIZE(val_use));
+#endif
+ }
+ break;
+ }
+ case nsXPTType::T_UTF8STRING: {
+ nsCString *ws = (nsCString *)ns_v.val.p;
+ NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
+ if (val == Py_None) {
+ NS_ABORT_IF_FALSE(0, "dont handle None here yet");
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ if (PyString_Check(val)) {
+ val_use = val;
+ Py_INCREF(val);
+ }
+ else
+#endif
+ if (PyUnicode_Check(val)) {
+ val_use = PyUnicode_AsUTF8String(val);
+ } else {
+#if PY_MAJOR_VERSION <= 2
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects");
+#else
+ PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be unicode objects");
+#endif
+ BREAK_FALSE;
+ }
+#if PY_MAJOR_VERSION <= 2
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "must have a string object!");
+ const char *sz = PyString_AS_STRING(val_use);
+ ws->Assign(sz, PyString_GET_SIZE(val_use));
+#else
+ NS_ABORT_IF_FALSE(PyBytes_Check(val_use), "must have a bytes object!");
+ const char *sz = PyBytes_AS_STRING(val_use);
+ ws->Assign(sz, PyBytes_GET_SIZE(val_use));
+#endif
+ }
+ break;
+ }
+
+ case nsXPTType::T_CHAR_STR: {
+ // If it is an existing string, free it.
+ char **pp = (char **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ const char *sz = PyString_AS_STRING(val_use);
+ int nch = PyString_GET_SIZE(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ const char *sz = PyBytes_AS_STRING(val_use);
+ int nch = PyBytes_GET_SIZE(val_use);
+#endif
+
+ *pp = (char *)nsMemory::Alloc(nch+1);
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ strncpy(*pp, sz, nch+1);
+ break;
+ }
+ case nsXPTType::T_WCHAR_STR: {
+ // If it is an existing string, free it.
+ PRUnichar **pp = (PRUnichar **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+ if (val == Py_None)
+ break; // Remains NULL.
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyUnicode_FromObject(val);
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0)
+ BREAK_FALSE;
+ break;
+ }
+ case nsXPTType::T_INTERFACE: {
+ nsISupports *pnew = nsnull;
+ // Find out what IID we are declared to use.
+ nsIID *iid = NULL;
+ nsIInterfaceInfo *ii = GetInterfaceInfo();
+ if (ii)
+ ii->GetIIDForParam(m_method_index, pi, &iid);
+
+ // Get it the "standard" way.
+ // We do allow NULL here, even tho doing so will no-doubt crash some objects.
+ // (but there will certainly be objects out there that will allow NULL :-(
+ nsIID iid_use = iid ? *iid : NS_GET_IID(nsISupports);
+ if (!Py_nsISupports::InterfaceFromPyObject(val, iid_use, &pnew, PR_TRUE))
+ BREAK_FALSE;
+ nsISupports **pp = (nsISupports **)ns_v.val.p;
+ if (*pp && pi->IsIn()) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ (*pp)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+
+ *pp = pnew; // ref-count added by InterfaceFromPyObject
+ break;
+ }
+ case nsXPTType::T_INTERFACE_IS: {
+ const nsIID *piid;
+ if (!GetIIDForINTERFACE_ID(pi->type.argnum, &piid))
+ BREAK_FALSE;
+
+ nsISupports *pnew = nsnull;
+ // Get it the "standard" way.
+ // We do allow NULL here, even tho doing so will no-doubt crash some objects.
+ // (but there will certainly be objects out there that will allow NULL :-(
+ if (!Py_nsISupports::InterfaceFromPyObject(val, *piid, &pnew, PR_TRUE))
+ BREAK_FALSE;
+ nsISupports **pp = (nsISupports **)ns_v.val.p;
+ if (*pp && pi->IsIn()) {
+ Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
+ (*pp)->Release();
+ Py_END_ALLOW_THREADS;
+ }
+
+ *pp = pnew; // ref-count added by InterfaceFromPyObject
+ break;
+ }
+
+ case nsXPTType::T_PSTRING_SIZE_IS: {
+ const char *sz = nsnull;
+ PRUint32 nch = 0;
+ if (val != Py_None) {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyObject_Str(val))==NULL)
+ BREAK_FALSE;
+ // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
+ NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
+
+ sz = PyString_AS_STRING(val_use);
+ nch = PyString_GET_SIZE(val_use);
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ if ((val_use = PyUnicode_AsUTF8String(val))==NULL)
+ BREAK_FALSE;
+
+ sz = PyBytes_AS_STRING(val_use);
+ nch = PyBytes_GET_SIZE(val_use);
+#endif
+ }
+ PRBool bBackFill = PR_FALSE;
+ PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_TRUE);
+ // If we can not change the size, check our sequence is correct.
+ if (!bCanSetSizeIs) {
+ PRUint32 existing_size = GetSizeIs(index, PR_TRUE);
+ if (nch != existing_size) {
+ PyErr_Format(PyExc_ValueError, "This function is expecting a string of exactly length %d - %d characters were passed", existing_size, nch);
+ BREAK_FALSE;
+ }
+ // It we have an "inout" param, but an "in" count, then
+ // it is probably a buffer the caller expects us to
+ // fill in-place!
+ bBackFill = pi->IsIn();
+ }
+ if (bBackFill) {
+ memcpy(*(char **)ns_v.val.p, sz, nch);
+ } else {
+ // If we have an existing string, free it!
+ char **pp = (char **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = nsnull;
+ if (sz==nsnull) // None specified.
+ break; // Remains NULL.
+ *pp = (char *)nsMemory::Alloc(nch);
+ if (*pp==NULL) {
+ PyErr_NoMemory();
+ BREAK_FALSE;
+ }
+ memcpy(*pp, sz, nch);
+ if (bCanSetSizeIs)
+ rc = SetSizeIs(index, PR_TRUE, nch);
+ else {
+ NS_ABORT_IF_FALSE(GetSizeIs(index, PR_TRUE) == nch, "Can't set sizeis, but string isnt correct size");
+ }
+ }
+ break;
+ }
+
+ case nsXPTType::T_PWSTRING_SIZE_IS: {
+ PRUnichar *sz = nsnull;
+ PRUint32 nch = 0;
+ PRUint32 nbytes = 0;
+
+ if (val != Py_None) {
+#if PY_MAJOR_VERSION <= 2
+ if (!PyString_Check(val) && !PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
+ BREAK_FALSE;
+ }
+ val_use = PyUnicode_FromObject(val);
+ NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
+#else
+ if (!PyUnicode_Check(val)) {
+ PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object");
+ BREAK_FALSE;
+ }
+ val_use = val;
+ Py_INCREF(val_use);
+#endif
+ if (PyUnicode_AsPRUnichar(val_use, &sz, &nch) < 0)
+ BREAK_FALSE;
+ nbytes = sizeof(PRUnichar) * nch;
+ }
+ PRBool bBackFill = PR_FALSE;
+ PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_TRUE);
+ // If we can not change the size, check our sequence is correct.
+ if (!bCanSetSizeIs) {
+ // It is a buffer the caller prolly wants us to fill in-place!
+ PRUint32 existing_size = GetSizeIs(index, PR_TRUE);
+ if (nch != existing_size) {
+ PyErr_Format(PyExc_ValueError, "This function is expecting a string of exactly length %d - %d characters were passed", existing_size, nch);
+ BREAK_FALSE;
+ }
+ // It we have an "inout" param, but an "in" count, then
+ // it is probably a buffer the caller expects us to
+ // fill in-place!
+ bBackFill = pi->IsIn();
+ }
+ if (bBackFill) {
+ memcpy(*(PRUnichar **)ns_v.val.p, sz, nbytes);
+ } else {
+ // If it is an existing string, free it.
+ PRUnichar **pp = (PRUnichar **)ns_v.val.p;
+ if (*pp && pi->IsIn())
+ nsMemory::Free(*pp);
+ *pp = sz;
+ sz = nsnull;
+ if (bCanSetSizeIs)
+ rc = SetSizeIs(index, PR_TRUE, nch);
+ else {
+ NS_ABORT_IF_FALSE(GetSizeIs(index, PR_TRUE) == nch, "Can't set sizeis, but string isnt correct size");
+ }
+ }
+ if (sz)
+ nsMemory::Free(sz);
+ break;
+ }
+ case nsXPTType::T_ARRAY: {
+ // If it is an existing array of the correct size, keep it.
+ PRUint32 sequence_size = 0;
+ PRUint8 array_type;
+ nsIID *piid;
+ nsresult ns = GetArrayType(index, &array_type, &piid);
+ if (NS_FAILED(ns))
+ return ns;
+ PRUint32 element_size = GetArrayElementSize(array_type);
+ if (val != Py_None) {
+ if (!PySequence_Check(val)) {
+ PyErr_Format(PyExc_TypeError, "Object for xpcom array must be a sequence, not type '%s'", PyXPCOM_ObTypeName(val));
+ BREAK_FALSE;
+ }
+ sequence_size = PySequence_Length(val);
+ }
+ PRUint32 existing_size = GetSizeIs(index, PR_FALSE);
+ PRBool bBackFill = PR_FALSE;
+ PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_FALSE);
+ // If we can not change the size, check our sequence is correct.
+ if (!bCanSetSizeIs) {
+ // It is a buffer the caller prolly wants us to fill in-place!
+ if (sequence_size != existing_size) {
+ PyErr_Format(PyExc_ValueError, "This function is expecting a sequence of exactly length %d - %d items were passed", existing_size, sequence_size);
+ BREAK_FALSE;
+ }
+ // It we have an "inout" param, but an "in" count, then
+ // it is probably a buffer the caller expects us to
+ // fill in-place!
+ bBackFill = pi->IsIn();
+ }
+ if (bBackFill)
+ rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
+ else {
+ // If it is an existing array, free it.
+ void **pp = (void **)ns_v.val.p;
+ if (*pp && pi->IsIn()) {
+ FreeSingleArray(*pp, existing_size, array_type);
+ nsMemory::Free(*pp);
+ }
+ *pp = nsnull;
+ if (val == Py_None)
+ break; // Remains NULL.
+ size_t nbytes = sequence_size * element_size;
+ if (nbytes==0) nbytes = 1; // avoid assertion about 0 bytes
+ *pp = (void *)nsMemory::Alloc(nbytes);
+ memset(*pp, 0, nbytes);
+ rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
+ if (!rc) break;
+ if (bCanSetSizeIs)
+ rc = SetSizeIs(index, PR_FALSE, sequence_size);
+ else {
+ NS_ABORT_IF_FALSE(GetSizeIs(index, PR_FALSE) == sequence_size, "Can't set sizeis, but string isnt correct size");
+ }
+ }
+ break;
+ }
+ default:
+ // try and limp along in this case.
+ // leave rc TRUE
+ PyXPCOM_LogWarning("Converting Python object for an [out] param - The object type (0x%x) is unknown - leaving param alone!\n", XPT_TDP_TAG(typ));
+ break;
+ }
+ Py_XDECREF(val_use);
+ if (!rc)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult PyXPCOM_GatewayVariantHelper::ProcessPythonResult(PyObject *ret_ob)
+{
+ // NOTE - although we return an nresult, if we leave a Python
+ // exception set, then our caller may take additional action
+ // (ie, translating our nsresult to a more appropriate nsresult
+ // for the Python exception.)
+ NS_PRECONDITION(!PyErr_Occurred(), "Expecting no Python exception to be pending when processing the return result");
+
+ nsresult rc = NS_OK;
+ // If we dont get a tuple back, then the result is only
+ // an int nresult for the underlying function.
+ // (ie, the policy is expected to return (NS_OK, user_retval),
+ // but can also return (say), NS_ERROR_FAILURE
+ if (PyInt_Check(ret_ob))
+ return PyInt_AsLong(ret_ob);
+ // Now it must be the tuple.
+ if (!PyTuple_Check(ret_ob) ||
+ PyTuple_Size(ret_ob)!=2 ||
+ !PyInt_Check(PyTuple_GET_ITEM(ret_ob, 0))) {
+ PyErr_SetString(PyExc_TypeError, "The Python result must be a single integer or a tuple of length==2 and first item an int.");
+ return NS_ERROR_FAILURE;
+ }
+ PyObject *user_result = PyTuple_GET_ITEM(ret_ob, 1);
+ // Count up how many results our function needs.
+ int i;
+ int num_results = 0;
+ int last_result = -1; // optimization if we only have one - this is it!
+ int index_retval = -1;
+ for (i=0;i<m_num_type_descs;i++) {
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i;
+ if (!m_python_type_desc_array[i].is_auto_out) {
+ if (pi->IsOut() || pi->IsDipper()) {
+ num_results++;
+ last_result = i;
+ }
+ if (pi->IsRetval())
+ index_retval = i;
+ }
+ }
+
+ if (num_results==0) {
+ ; // do nothing
+ } else if (num_results==1) {
+ // May or may not be the nominated retval - who cares!
+ NS_ABORT_IF_FALSE(last_result >=0 && last_result < m_num_type_descs, "Have one result, but dont know its index!");
+ rc = BackFillVariant( user_result, last_result );
+ } else {
+ // Loop over each one, filling as we go.
+ // We allow arbitary sequences here, but _not_ strings
+ // or Unicode!
+ // NOTE - We ALWAYS do the nominated retval first.
+ // The Python pattern is always:
+ // return retval [, byref1 [, byref2 ...] ]
+ // But the retval is often the last param described in the info.
+ if (!PySequence_Check(user_result) ||
+#if PY_MAJOR_VERSION <= 2
+ PyString_Check(user_result) ||
+#else
+ PyBytes_Check(user_result) ||
+#endif
+ PyUnicode_Check(user_result)) {
+ PyErr_SetString(PyExc_TypeError, "This function has multiple results, but a sequence was not given to fill them");
+ return NS_ERROR_FAILURE;
+ }
+ int num_user_results = PySequence_Length(user_result);
+ // If they havent given enough, we dont really care.
+ // although a warning is probably appropriate.
+ if (num_user_results != num_results) {
+ const char *method_name = m_info->GetName();
+ PyXPCOM_LogWarning("The method '%s' has %d out params, but %d were supplied by the Python code\n",
+ method_name,
+ num_results,
+ num_user_results);
+ }
+ int this_py_index = 0;
+ if (index_retval != -1) {
+ // We always return the nominated result first!
+ PyObject *sub = PySequence_GetItem(user_result, 0);
+ if (sub==NULL)
+ return NS_ERROR_FAILURE;
+ rc = BackFillVariant(sub, index_retval);
+ Py_DECREF(sub);
+ this_py_index = 1;
+ }
+ for (i=0;NS_SUCCEEDED(rc) && i<m_info->GetParamCount();i++) {
+ // If weve already done it, or dont need to do it!
+ if (i==index_retval || m_python_type_desc_array[i].is_auto_out)
+ continue;
+ nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i;
+ if (pi->IsOut()) {
+ PyObject *sub = PySequence_GetItem(user_result, this_py_index);
+ if (sub==NULL)
+ return NS_ERROR_FAILURE;
+ rc = BackFillVariant(sub, i);
+ Py_DECREF(sub);
+ this_py_index++;
+ }
+ }
+ }
+ return rc;
+}
diff --git a/src/libs/xpcom18a4/python/src/dllmain.cpp b/src/libs/xpcom18a4/python/src/dllmain.cpp
new file mode 100644
index 00000000..4cc08578
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/dllmain.cpp
@@ -0,0 +1,352 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM_std.h"
+#include <prthread.h>
+#include "nsIThread.h"
+#include "nsILocalFile.h"
+
+#ifdef XP_WIN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#endif
+
+static PRInt32 g_cLockCount = 0;
+static PRLock *g_lockMain = nsnull;
+
+PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
+
+PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
+PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
+PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
+// deprecated, but retained for backward compatibility:
+PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+
+////////////////////////////////////////////////////////////
+// Thread-state helpers/global functions.
+// Only used if there is no Python PyGILState_* API
+//
+static PyThreadState *ptsGlobal = nsnull;
+PyInterpreterState *PyXPCOM_InterpreterState = nsnull;
+PRUintn tlsIndex = 0;
+
+
+// This function must be called at some time when the interpreter lock and state is valid.
+// Called by init{module} functions and also COM factory entry point.
+void PyXPCOM_InterpreterState_Ensure()
+{
+ if (PyXPCOM_InterpreterState==NULL) {
+ PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
+ if (threadStateSave==NULL)
+ Py_FatalError("Can not setup interpreter state, as current state is invalid");
+
+ PyXPCOM_InterpreterState = threadStateSave->interp;
+ PyThreadState_Swap(threadStateSave);
+ }
+}
+
+void PyXPCOM_InterpreterState_Free()
+{
+ PyXPCOM_ThreadState_Free();
+ PyXPCOM_InterpreterState = NULL; // Eek - should I be freeing something?
+}
+
+// This structure is stored in the TLS slot. At this stage only a Python thread state
+// is kept, but this may change in the future...
+struct ThreadData{
+ PyThreadState *ts;
+};
+
+// Ensure that we have a Python thread state available to use.
+// If this is called for the first time on a thread, it will allocate
+// the thread state. This does NOT change the state of the Python lock.
+// Returns TRUE if a new thread state was created, or FALSE if a
+// thread state already existed.
+PRBool PyXPCOM_ThreadState_Ensure()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ if (pData==NULL) { /* First request on this thread */
+ /* Check we have an interpreter state */
+ if (PyXPCOM_InterpreterState==NULL) {
+ Py_FatalError("Can not setup thread state, as have no interpreter state");
+ }
+ pData = (ThreadData *)nsMemory::Alloc(sizeof(ThreadData));
+ if (!pData)
+ Py_FatalError("Out of memory allocating thread state.");
+ memset(pData, 0, sizeof(*pData));
+ if (NS_FAILED( PR_SetThreadPrivate( tlsIndex, pData ) ) ) {
+ NS_ABORT_IF_FALSE(0, "Could not create thread data for this thread!");
+ Py_FatalError("Could not thread private thread data!");
+ }
+ pData->ts = PyThreadState_New(PyXPCOM_InterpreterState);
+ return PR_TRUE; // Did create a thread state state
+ }
+ return PR_FALSE; // Thread state was previously created
+}
+
+// Asuming we have a valid thread state, acquire the Python lock.
+void PyXPCOM_InterpreterLock_Acquire()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
+ PyThreadState *thisThreadState = pData->ts;
+ PyEval_AcquireThread(thisThreadState);
+}
+
+// Asuming we have a valid thread state, release the Python lock.
+void PyXPCOM_InterpreterLock_Release()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!");
+ PyThreadState *thisThreadState = pData->ts;
+ PyEval_ReleaseThread(thisThreadState);
+}
+
+// Free the thread state for the current thread
+// (Presumably previously create with a call to
+// PyXPCOM_ThreadState_Ensure)
+void PyXPCOM_ThreadState_Free()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ if (!pData) return;
+ PyThreadState *thisThreadState = pData->ts;
+ PyThreadState_Delete(thisThreadState);
+ PR_SetThreadPrivate(tlsIndex, NULL);
+ nsMemory::Free(pData);
+}
+
+void PyXPCOM_ThreadState_Clear()
+{
+ ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex);
+ PyThreadState *thisThreadState = pData->ts;
+ PyThreadState_Clear(thisThreadState);
+}
+#endif // PYXPCOM_USE_PYGILSTATE
+
+////////////////////////////////////////////////////////////
+// Lock/exclusion global functions.
+//
+void PyXPCOM_AcquireGlobalLock(void)
+{
+ NS_PRECONDITION(g_lockMain != nsnull, "Cant acquire a NULL lock!");
+ PR_Lock(g_lockMain);
+}
+void PyXPCOM_ReleaseGlobalLock(void)
+{
+ NS_PRECONDITION(g_lockMain != nsnull, "Cant release a NULL lock!");
+ PR_Unlock(g_lockMain);
+}
+
+void PyXPCOM_DLLAddRef(void)
+{
+ // Must be thread-safe, although cant have the Python lock!
+ CEnterLeaveXPCOMFramework _celf;
+ PRInt32 cnt = PR_AtomicIncrement(&g_cLockCount);
+ if (cnt==1) { // First call
+ if (!Py_IsInitialized()) {
+ Py_Initialize();
+ // Make sure our Windows framework is all setup.
+ PyXPCOM_Globals_Ensure();
+ // Make sure we have _something_ as sys.argv.
+ if (PySys_GetObject((char*)"argv")==NULL) {
+ PyObject *path = PyList_New(0);
+#if PY_MAJOR_VERSION <= 2
+ PyObject *str = PyString_FromString("");
+#else
+ PyObject *str = PyUnicode_FromString("");
+#endif
+ PyList_Append(path, str);
+ PySys_SetObject((char*)"argv", path);
+ Py_XDECREF(path);
+ Py_XDECREF(str);
+ }
+
+ // Must force Python to start using thread locks, as
+ // we are free-threaded (maybe, I think, sometimes :-)
+ PyEval_InitThreads();
+#ifndef PYXPCOM_USE_PYGILSTATE
+ // Release Python lock, as first thing we do is re-get it.
+ ptsGlobal = PyEval_SaveThread();
+#endif
+ // NOTE: We never finalize Python!!
+ }
+ }
+}
+void PyXPCOM_DLLRelease(void)
+{
+ PR_AtomicDecrement(&g_cLockCount);
+}
+
+void pyxpcom_construct(void)
+{
+ g_lockMain = PR_NewLock();
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PRStatus status;
+ status = PR_NewThreadPrivateIndex( &tlsIndex, NULL );
+ NS_WARN_IF_FALSE(status==0, "Could not allocate TLS storage");
+ if (NS_FAILED(status)) {
+ PR_DestroyLock(g_lockMain);
+ return; // PR_FALSE;
+ }
+#endif // PYXPCOM_USE_PYGILSTATE
+ return; // PR_TRUE;
+}
+
+void pyxpcom_destruct(void)
+{
+ PR_DestroyLock(g_lockMain);
+#ifndef PYXPCOM_USE_PYGILSTATE
+ // I can't locate a way to kill this -
+ // should I pass a dtor to PR_NewThreadPrivateIndex??
+ // TlsFree(tlsIndex);
+#endif // PYXPCOM_USE_PYGILSTATE
+}
+
+// Yet another attempt at cross-platform library initialization and finalization.
+struct DllInitializer {
+ DllInitializer() {
+ pyxpcom_construct();
+ }
+ ~DllInitializer() {
+ pyxpcom_destruct();
+ }
+} dll_initializer;
+
+////////////////////////////////////////////////////////////
+// Other helpers/global functions.
+//
+PRBool PyXPCOM_Globals_Ensure()
+{
+ PRBool rc = PR_TRUE;
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PyXPCOM_InterpreterState_Ensure();
+#endif
+
+ // The exception object - we load it from .py code!
+ if (PyXPCOM_Error == NULL) {
+ rc = PR_FALSE;
+ PyObject *mod = NULL;
+
+ mod = PyImport_ImportModule("xpcom");
+ if (mod!=NULL) {
+ PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
+ Py_DECREF(mod);
+ }
+ rc = (PyXPCOM_Error != NULL);
+ }
+ if (!rc)
+ return rc;
+
+ static PRBool bHaveInitXPCOM = PR_FALSE;
+ if (!bHaveInitXPCOM) {
+ nsCOMPtr<nsIThread> thread_check;
+ // xpcom appears to assert if already initialized
+ // Is there an official way to determine this?
+ if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
+ // not already initialized.
+#ifdef XP_WIN
+ // On Windows, we need to locate the Mozilla bin
+ // directory. This by using locating a Moz DLL we depend
+ // on, and assume it lives in that bin dir. Different
+ // moz build types (eg, xulrunner, suite) package
+ // XPCOM itself differently - but all appear to require
+ // nspr4.dll - so this is what we use.
+ char landmark[MAX_PATH+1];
+ HMODULE hmod = GetModuleHandle("nspr4.dll");
+ if (hmod==NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.dll.");
+ return PR_FALSE;
+ }
+ GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
+ char *end = landmark + (strlen(landmark)-1);
+ while (end > landmark && *end != '\\')
+ end--;
+ if (end > landmark) *end = '\0';
+
+ nsCOMPtr<nsILocalFile> ns_bin_dir;
+ NS_ConvertASCIItoUCS2 strLandmark(landmark);
+ NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
+ nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
+#else
+ // Elsewhere, Mozilla can find it itself (we hope!)
+ nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+#endif // XP_WIN
+ if (NS_FAILED(rv)) {
+ PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
+ return PR_FALSE;
+ }
+ }
+ // Even if xpcom was already init, we want to flag it as init!
+ bHaveInitXPCOM = PR_TRUE;
+ // Register our custom interfaces.
+
+ Py_nsISupports::InitType();
+ Py_nsIComponentManager::InitType();
+ Py_nsIInterfaceInfoManager::InitType();
+ Py_nsIEnumerator::InitType();
+ Py_nsISimpleEnumerator::InitType();
+ Py_nsIInterfaceInfo::InitType();
+ Py_nsIInputStream::InitType();
+ Py_nsIClassInfo::InitType();
+ Py_nsIVariant::InitType();
+ // for backward compatibility:
+ Py_nsIComponentManagerObsolete::InitType();
+
+ }
+ return rc;
+}
+
diff --git a/src/libs/xpcom18a4/python/src/loader/pyloader.cpp b/src/libs/xpcom18a4/python/src/loader/pyloader.cpp
new file mode 100644
index 00000000..dc116f1d
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/loader/pyloader.cpp
@@ -0,0 +1,435 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+// pyloader
+//
+// Not part of the main Python _xpcom package, but a separate, thin DLL.
+//
+// The main loader and registrar for Python. A thin DLL that is designed to live in
+// the xpcom "components" directory. Simply locates and loads the standard
+// pyxpcom core library and transfers control to that.
+
+#include <PyXPCOM.h>
+
+#include "nsDirectoryServiceDefs.h"
+#include "nsILocalFile.h"
+
+#include "nspr.h" // PR_fprintf
+
+#if (PY_VERSION_HEX >= 0x02030000)
+#define PYXPCOM_USE_PYGILSTATE
+#endif
+
+static char *PyTraceback_AsString(PyObject *exc_tb);
+
+#ifdef XP_WIN
+#include "windows.h"
+#endif
+
+#ifdef XP_UNIX
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#endif
+
+#include "nsITimelineService.h"
+
+typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr,
+ nsIFile* location,
+ nsIModule** result);
+
+
+static void LogError(const char *fmt, ...);
+static void LogDebug(const char *fmt, ...);
+
+// Ensure that any paths guaranteed by this package exist on sys.path
+// Only called once as we are first loaded into the process.
+void AddStandardPaths()
+{
+ // Put {bin}\Python on the path if it exists.
+ nsresult rv;
+ nsCOMPtr<nsIFile> aFile;
+ rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(aFile));
+ if (NS_FAILED(rv)) {
+ LogError("The Python XPCOM loader could not locate the 'bin' directory\n");
+ return;
+ }
+ aFile->Append(NS_LITERAL_STRING("python"));
+ nsAutoString pathBuf;
+ aFile->GetPath(pathBuf);
+ PyObject *obPath = PySys_GetObject("path");
+ if (!obPath) {
+ LogError("The Python XPCOM loader could not get the Python sys.path variable\n");
+ return;
+ }
+ NS_LossyConvertUCS2toASCII pathCBuf(pathBuf);
+ LogDebug("The Python XPCOM loader is adding '%s' to sys.path\n", pathCBuf.get());
+ PyObject *newStr = PyString_FromString(pathCBuf.get());
+ PyList_Insert(obPath, 0, newStr);
+ Py_XDECREF(newStr);
+ // And now try and get Python to process this directory as a "site dir"
+ // - ie, look for .pth files, etc
+ nsCAutoString cmdBuf(NS_LITERAL_CSTRING("import site;site.addsitedir(r'") + pathCBuf + NS_LITERAL_CSTRING("')\n"));
+ if (0 != PyRun_SimpleString((char *)cmdBuf.get())) {
+ LogError("The directory '%s' could not be added as a site directory", pathCBuf.get());
+ PyErr_Clear();
+ }
+ // and somewhat like Python itself (site, citecustomize), we attempt
+ // to import "sitepyxpcom" ignoring ImportError
+ if (NULL==PyImport_ImportModule("sitepyxpcom")) {
+ if (!PyErr_ExceptionMatches(PyExc_ImportError))
+ LogError("Failed to import 'sitepyxpcom'");
+ PyErr_Clear();
+ }
+}
+
+////////////////////////////////////////////////////////////
+// This is the main entry point that delegates into Python
+nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
+ nsIFile* location,
+ nsIModule** result)
+{
+ NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
+ NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
+ NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
+#ifndef LOADER_LINKS_WITH_PYTHON
+ if (!Py_IsInitialized()) {
+ Py_Initialize();
+ if (!Py_IsInitialized()) {
+ PyXPCOM_LogError("Python initialization failed!\n");
+ return NS_ERROR_FAILURE;
+ }
+ PyEval_InitThreads();
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PyXPCOM_InterpreterState_Ensure();
+#endif
+ PyEval_SaveThread();
+ }
+#endif // LOADER_LINKS_WITH_PYTHON
+ CEnterLeavePython _celp;
+ PyObject *func = NULL;
+ PyObject *obServMgr = NULL;
+ PyObject *obLocation = NULL;
+ PyObject *wrap_ret = NULL;
+ PyObject *args = NULL;
+ PyObject *mod = PyImport_ImportModule("xpcom.server");
+ if (!mod) goto done;
+ func = PyObject_GetAttrString(mod, "NS_GetModule");
+ if (func==NULL) goto done;
+ obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager));
+ if (obServMgr==NULL) goto done;
+ obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile));
+ if (obLocation==NULL) goto done;
+ args = Py_BuildValue("OO", obServMgr, obLocation);
+ if (args==NULL) goto done;
+ wrap_ret = PyEval_CallObject(func, args);
+ if (wrap_ret==NULL) goto done;
+ Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
+done:
+ nsresult nr = NS_OK;
+ if (PyErr_Occurred()) {
+ PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
+ nr = PyXPCOM_SetCOMErrorFromPyException();
+ }
+ Py_XDECREF(func);
+ Py_XDECREF(obServMgr);
+ Py_XDECREF(obLocation);
+ Py_XDECREF(wrap_ret);
+ Py_XDECREF(mod);
+ Py_XDECREF(args);
+ return nr;
+}
+
+extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
+ nsIFile* location,
+ nsIModule** result)
+{
+#ifdef XP_UNIX
+ // *sob* - seems necessary to open the .so as RTLD_GLOBAL
+ dlopen(PYTHON_SO,RTLD_NOW | RTLD_GLOBAL);
+#endif
+ PRBool bDidInitPython = !Py_IsInitialized(); // well, I will next line, anyway :-)
+ if (bDidInitPython) {
+ NS_TIMELINE_START_TIMER("PyXPCOM: Python initializing");
+ Py_Initialize();
+ if (!Py_IsInitialized()) {
+ LogError("Python initialization failed!\n");
+ return NS_ERROR_FAILURE;
+ }
+#ifndef NS_DEBUG
+ Py_OptimizeFlag = 1;
+#endif // NS_DEBUG
+ PyEval_InitThreads();
+ NS_TIMELINE_STOP_TIMER("PyXPCOM: Python initializing");
+ NS_TIMELINE_MARK_TIMER("PyXPCOM: Python initializing");
+ }
+ // Get the Python interpreter state
+ NS_TIMELINE_START_TIMER("PyXPCOM: Python threadstate setup");
+#ifndef PYXPCOM_USE_PYGILSTATE
+ PyThreadState *threadStateCreated = NULL;
+ PyThreadState *threadState = PyThreadState_Swap(NULL);
+ if (threadState==NULL) {
+ // no thread-state - set one up.
+ // *sigh* - what I consider a bug is that Python
+ // will deadlock unless we own the lock before creating
+ // a new interpreter (it appear Py_NewInterpreter has
+ // really only been tested/used with no thread lock
+ PyEval_AcquireLock();
+ threadState = threadStateCreated = Py_NewInterpreter();
+ PyThreadState_Swap(NULL);
+ }
+ PyEval_ReleaseLock();
+ PyEval_AcquireThread(threadState);
+#else
+ PyGILState_STATE state = PyGILState_Ensure();
+#endif // PYXPCOM_USE_PYGILSTATE
+#ifdef MOZ_TIMELINE
+ // If the timeline service is installed, see if we can install our hooks.
+ if (NULL==PyImport_ImportModule("timeline_hook")) {
+ if (!PyErr_ExceptionMatches(PyExc_ImportError))
+ LogError("Failed to import 'timeline_hook'");
+ PyErr_Clear(); // but don't care if we can't.
+ }
+#endif
+ // Add the standard paths always - we may not have been the first to
+ // init Python.
+ AddStandardPaths();
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+ // Abandon the thread-lock, as the first thing Python does
+ // is re-establish the lock (the Python thread-state story SUCKS!!!)
+ if (threadStateCreated) {
+ Py_EndInterpreter(threadStateCreated);
+ PyEval_ReleaseLock(); // see Py_NewInterpreter call above
+ } else {
+ PyEval_ReleaseThread(threadState);
+ PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
+ if (threadStateSave)
+ PyThreadState_Delete(threadStateSave);
+ }
+#else
+ // If we initialized Python, then we will also have acquired the thread
+ // lock. In that case, we want to leave it unlocked, so other threads
+ // are free to run, even if they aren't running Python code.
+ PyGILState_Release(bDidInitPython ? PyGILState_UNLOCKED : state);
+#endif
+
+ NS_TIMELINE_STOP_TIMER("PyXPCOM: Python threadstate setup");
+ NS_TIMELINE_MARK_TIMER("PyXPCOM: Python threadstate setup");
+ NS_TIMELINE_START_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
+ nsresult rc = PyXPCOM_NSGetModule(servMgr, location, result);
+ NS_TIMELINE_STOP_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
+ NS_TIMELINE_MARK_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
+ return rc;
+}
+
+// The internal helper that actually moves the
+// formatted string to the target!
+
+void LogMessage(const char *prefix, const char *pszMessageText)
+{
+ PR_fprintf(PR_STDERR, "%s", pszMessageText);
+}
+
+void LogMessage(const char *prefix, nsACString &text)
+{
+ LogMessage(prefix, nsPromiseFlatCString(text).get());
+}
+
+// A helper for the various logging routines.
+static void VLogF(const char *prefix, const char *fmt, va_list argptr)
+{
+ char buff[512];
+
+ vsprintf(buff, fmt, argptr);
+
+ LogMessage(prefix, buff);
+}
+
+static void LogError(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF("PyXPCOM Loader Error: ", fmt, marker);
+ // If we have a Python exception, also log that:
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+ if (exc_typ) {
+ nsCAutoString streamout;
+
+ if (exc_tb) {
+ const char *szTraceback = PyTraceback_AsString(exc_tb);
+ if (szTraceback == NULL)
+ streamout += "Can't get the traceback info!";
+ else {
+ streamout += "Traceback (most recent call last):\n";
+ streamout += szTraceback;
+ PyMem_Free((void *)szTraceback);
+ }
+ }
+ PyObject *temp = PyObject_Str(exc_typ);
+ if (temp) {
+ streamout += PyString_AsString(temp);
+ Py_DECREF(temp);
+ } else
+ streamout += "Can convert exception to a string!";
+ streamout += ": ";
+ if (exc_val != NULL) {
+ temp = PyObject_Str(exc_val);
+ if (temp) {
+ streamout += PyString_AsString(temp);
+ Py_DECREF(temp);
+ } else
+ streamout += "Can convert exception value to a string!";
+ }
+ streamout += "\n";
+ LogMessage("PyXPCOM Exception:", streamout);
+ }
+ PyErr_Restore(exc_typ, exc_val, exc_tb);
+ va_end(marker);
+}
+/*** - not currently used - silence compiler warning.
+static void LogWarning(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF("PyXPCOM Loader Warning: ", fmt, marker);
+}
+***/
+#ifdef DEBUG
+static void LogDebug(const char *fmt, ...)
+{
+ va_list marker;
+ va_start(marker, fmt);
+ VLogF("PyXPCOM Loader Debug: ", fmt, marker);
+ va_end(marker);
+}
+#else
+static void LogDebug(const char *fmt, ...)
+{
+}
+#endif
+
+/* Obtains a string from a Python traceback.
+ This is the exact same string as "traceback.print_exc" would return.
+
+ Pass in a Python traceback object (probably obtained from PyErr_Fetch())
+ Result is a string which must be free'd using PyMem_Free()
+*/
+#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
+
+char *PyTraceback_AsString(PyObject *exc_tb)
+{
+ char *errMsg = NULL; /* a static that hold a local error message */
+ char *result = NULL; /* a valid, allocated result. */
+ PyObject *modStringIO = NULL;
+ PyObject *modTB = NULL;
+ PyObject *obFuncStringIO = NULL;
+ PyObject *obStringIO = NULL;
+ PyObject *obFuncTB = NULL;
+ PyObject *argsTB = NULL;
+ PyObject *obResult = NULL;
+
+ /* Import the modules we need - cStringIO and traceback */
+ modStringIO = PyImport_ImportModule("cStringIO");
+ if (modStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant import cStringIO\n");
+
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant import traceback\n");
+ /* Construct a cStringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n");
+ /* Get the traceback.print_exception function, and call it. */
+ obFuncTB = PyObject_GetAttrString(modTB, "print_tb");
+ if (obFuncTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n");
+
+ argsTB = Py_BuildValue("OOO",
+ exc_tb ? exc_tb : Py_None,
+ Py_None,
+ obStringIO);
+ if (argsTB==NULL)
+ TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n");
+
+ obResult = PyObject_CallObject(obFuncTB, argsTB);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n");
+ /* Now call the getvalue() method in the StringIO instance */
+ Py_DECREF(obFuncStringIO);
+ obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
+ if (obFuncStringIO==NULL)
+ TRACEBACK_FETCH_ERROR("cant find getvalue function\n");
+ Py_DECREF(obResult);
+ obResult = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obResult==NULL)
+ TRACEBACK_FETCH_ERROR("getvalue() failed.\n");
+
+ /* And it should be a string all ready to go - duplicate it. */
+ if (!PyString_Check(obResult))
+ TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n");
+
+ { // a temp scope so I can use temp locals.
+ char *tempResult = PyString_AsString(obResult);
+ result = (char *)PyMem_Malloc(strlen(tempResult)+1);
+ if (result==NULL)
+ TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string");
+
+ strcpy(result, tempResult);
+ } // end of temp scope.
+done:
+ /* All finished - first see if we encountered an error */
+ if (result==NULL && errMsg != NULL) {
+ result = (char *)PyMem_Malloc(strlen(errMsg)+1);
+ if (result != NULL)
+ /* if it does, not much we can do! */
+ strcpy(result, errMsg);
+ }
+ Py_XDECREF(modStringIO);
+ Py_XDECREF(modTB);
+ Py_XDECREF(obFuncStringIO);
+ Py_XDECREF(obStringIO);
+ Py_XDECREF(obFuncTB);
+ Py_XDECREF(argsTB);
+ Py_XDECREF(obResult);
+ return result;
+}
diff --git a/src/libs/xpcom18a4/python/src/module/_xpcom.cpp b/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
new file mode 100644
index 00000000..d40d2b52
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
@@ -0,0 +1,950 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <mhammond@skippinet.com.au> (original author)
+ *
+ * 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 ***** */
+
+//
+// This code is part of the XPCOM extensions for Python.
+//
+// Written May 2000 by Mark Hammond.
+//
+// Based heavily on the Python COM support, which is
+// (c) Mark Hammond and Greg Stein.
+//
+// (c) 2000, ActiveState corp.
+
+#include "PyXPCOM.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIFile.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIConsoleService.h"
+#include "nspr.h" // PR_fprintf
+#ifdef VBOX
+# include "nsEventQueueUtils.h"
+#endif
+
+#ifdef XP_WIN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+#endif
+
+#include "nsIEventQueue.h"
+#include "nsIProxyObjectManager.h"
+
+#define LOADER_LINKS_WITH_PYTHON
+
+#ifndef PYXPCOM_USE_PYGILSTATE
+extern PYXPCOM_EXPORT void PyXPCOM_InterpreterState_Ensure();
+#endif
+
+#ifdef VBOX_PYXPCOM
+# include <iprt/cdefs.h>
+# include <VBox/com/com.h>
+# ifndef MODULE_NAME_SUFFIX
+# define MANGLE_MODULE_NAME(a_szName) a_szName
+# define MANGLE_MODULE_INIT(a_Name) a_Name
+# else
+# define MANGLE_MODULE_NAME(a_szName) a_szName RT_XSTR(MODULE_NAME_SUFFIX)
+# define MANGLE_MODULE_INIT(a_Name) RT_CONCAT(a_Name, MODULE_NAME_SUFFIX)
+# endif
+# if defined(VBOX_PYXPCOM_VERSIONED) && !defined(VBOX_PYXPCOM_MAJOR_VERSIONED)
+# if PY_VERSION_HEX >= 0x030a0000 && PY_VERSION_HEX < 0x030b0000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_10")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_10)
+
+# elif PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_9")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_9)
+
+# elif PY_VERSION_HEX >= 0x03080000 && PY_VERSION_HEX < 0x03090000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_8")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_8)
+
+# elif PY_VERSION_HEX >= 0x03070000 && PY_VERSION_HEX < 0x03080000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_7")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_7)
+
+# elif PY_VERSION_HEX >= 0x03060000 && PY_VERSION_HEX < 0x03070000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_6")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_6)
+
+# elif PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03060000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_5")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_5)
+
+# elif PY_VERSION_HEX >= 0x03040000 && PY_VERSION_HEX < 0x03050000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_4")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_4)
+
+# elif PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x03040000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_3")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_3)
+
+# elif PY_VERSION_HEX >= 0x03020000 && PY_VERSION_HEX < 0x03030000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_2")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_2)
+
+# elif PY_VERSION_HEX >= 0x03010000 && PY_VERSION_HEX < 0x03020000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_1")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_1)
+
+# elif PY_VERSION_HEX >= 0x02080000 && PY_VERSION_HEX < 0x02090000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_8")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_8)
+
+# elif PY_VERSION_HEX >= 0x02070000 && PY_VERSION_HEX < 0x02080000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_7")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_7)
+
+# elif PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x02070000
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_6")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_6)
+# else
+# error "Fix module versioning. This Python version is not recognized."
+# endif
+# else
+# if PY_MAJOR_VERSION <= 2 && defined(VBOX_PYXPCOM_MAJOR_VERSIONED)
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2)
+# elif PY_MAJOR_VERSION <= 2
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython")
+# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython)
+# elif defined(Py_LIMITED_API) || defined(VBOX_PYXPCOM_MAJOR_VERSIONED)
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3)
+# else
+# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython")
+# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython)
+# endif
+# endif
+#else
+#define MODULE_NAME "_xpcom"
+#endif
+
+// "boot-strap" methods - interfaces we need to get the base
+// interface support!
+
+#ifndef VBOX
+/* deprecated, included for backward compatibility */
+static PyObject *
+PyXPCOMMethod_NS_GetGlobalComponentManager(PyObject *self, PyObject *args)
+{
+ if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetComponentManager instead") < 0)
+ return NULL;
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIComponentManager> cm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetComponentManager(getter_AddRefs(cm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ nsCOMPtr<nsIComponentManagerObsolete> ocm(do_QueryInterface(cm, &rv));
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ return Py_nsISupports::PyObjectFromInterface(ocm, NS_GET_IID(nsIComponentManagerObsolete), PR_FALSE);
+}
+#endif
+
+static PyObject *
+PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIComponentManager> cm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetComponentManager(getter_AddRefs(cm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE);
+}
+
+// No xpcom callable way to get at the registrar, even though the interface
+// is scriptable.
+static PyObject *
+PyXPCOMMethod_GetComponentRegistrar(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIComponentRegistrar> cm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetComponentRegistrar(getter_AddRefs(cm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsISupports), PR_FALSE);
+}
+
+static PyObject *
+PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsCOMPtr<nsIServiceManager> sm;
+ nsresult rv;
+ Py_BEGIN_ALLOW_THREADS;
+ rv = NS_GetServiceManager(getter_AddRefs(sm));
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(rv) )
+ return PyXPCOM_BuildPyException(rv);
+
+ // Return a type based on the IID.
+ return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager));
+}
+
+#ifndef VBOX
+/* deprecated, included for backward compatibility */
+static PyObject *
+PyXPCOMMethod_GetGlobalServiceManager(PyObject *self, PyObject *args)
+{
+ if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetServiceManager instead") < 0)
+ return NULL;
+
+ return PyXPCOMMethod_GetComponentManager(self, args);
+}
+#endif
+
+static PyObject *
+PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ nsIInterfaceInfoManager* im;
+ Py_BEGIN_ALLOW_THREADS;
+ im = XPTI_GetInterfaceInfoManager();
+ Py_END_ALLOW_THREADS;
+ if ( im == nsnull )
+ return PyXPCOM_BuildPyException(NS_ERROR_FAILURE);
+
+ /* Return a type based on the IID (with no extra ref) */
+ // Can not auto-wrap the interface info manager as it is critical to
+ // building the support we need for autowrap.
+ PyObject *ret = Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE);
+ NS_IF_RELEASE(im);
+ return ret;
+}
+
+static PyObject *
+PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
+{
+ PyObject *obIS, *obParams;
+ nsCOMPtr<nsISupports> pis;
+ int index;
+
+ // We no longer rely on PyErr_Occurred() for our error state,
+ // but keeping this assertion can't hurt - it should still always be true!
+ NS_WARN_IF_FALSE(!PyErr_Occurred(), "Should be no pending Python error!");
+
+ if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
+ return NULL;
+
+ if (!Py_nsISupports::Check(obIS)) {
+ return PyErr_Format(PyExc_TypeError,
+ "First param must be a native nsISupports wrapper (got %s)",
+ PyXPCOM_ObTypeName(obIS));
+ }
+ // Ack! We must ask for the "native" interface supported by
+ // the object, not specifically nsISupports, else we may not
+ // back the same pointer (eg, Python, following identity rules,
+ // will return the "original" gateway when QI'd for nsISupports)
+ if (!Py_nsISupports::InterfaceFromPyObject(
+ obIS,
+ Py_nsIID_NULL,
+ getter_AddRefs(pis),
+ PR_FALSE))
+ return NULL;
+
+ PyXPCOM_InterfaceVariantHelper arg_helper((Py_nsISupports *)obIS, index);
+ if (!arg_helper.Init(obParams))
+ return NULL;
+
+ if (!arg_helper.FillArray())
+ return NULL;
+
+ nsresult r;
+ Py_BEGIN_ALLOW_THREADS;
+ r = XPTC_InvokeByIndex(pis, index, arg_helper.m_num_array, arg_helper.m_var_array);
+/** @todo bird: Maybe we could processing pending XPCOM events here to make
+ * life a bit simpler inside python? */
+ Py_END_ALLOW_THREADS;
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ return arg_helper.MakePythonResult();
+}
+
+static PyObject *
+PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
+{
+ PyObject *ob, *obIID;
+ int bWrapClient = 1;
+ if (!PyArg_ParseTuple(args, "OO|i", &ob, &obIID, &bWrapClient))
+ return NULL;
+
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+
+ nsCOMPtr<nsISupports> ret;
+ nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, getter_AddRefs(ret));
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+
+ // _ALL_ wrapped objects are associated with a weak-ref
+ // to their "main" instance.
+ AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance.
+
+ // Now wrap it in an interface.
+ return Py_nsISupports::PyObjectFromInterface(ret, iid, bWrapClient);
+}
+
+static PyObject *
+PyXPCOMMethod_UnwrapObject(PyObject *self, PyObject *args)
+{
+ PyObject *ob;
+ if (!PyArg_ParseTuple(args, "O", &ob))
+ return NULL;
+
+ nsISupports *uob = NULL;
+ nsIInternalPython *iob = NULL;
+ PyObject *ret = NULL;
+ if (!Py_nsISupports::InterfaceFromPyObject(ob,
+ NS_GET_IID(nsISupports),
+ &uob,
+ PR_FALSE))
+ goto done;
+ if (NS_FAILED(uob->QueryInterface(NS_GET_IID(nsIInternalPython), reinterpret_cast<void **>(&iob)))) {
+ PyErr_SetString(PyExc_ValueError, "This XPCOM object is not implemented by Python");
+ goto done;
+ }
+ ret = iob->UnwrapPythonObject();
+done:
+ Py_BEGIN_ALLOW_THREADS;
+ NS_IF_RELEASE(uob);
+ NS_IF_RELEASE(iob);
+ Py_END_ALLOW_THREADS;
+ return ret;
+}
+
+// @pymethod int|pythoncom|_GetInterfaceCount|Retrieves the number of interface objects currently in existance
+static PyObject *
+PyXPCOMMethod_GetInterfaceCount(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":_GetInterfaceCount"))
+ return NULL;
+ return PyInt_FromLong(_PyXPCOM_GetInterfaceCount());
+ // @comm If is occasionally a good idea to call this function before your Python program
+ // terminates. If this function returns non-zero, then you still have PythonCOM objects
+ // alive in your program (possibly in global variables).
+}
+
+#ifdef VBOX_DEBUG_LIFETIMES
+// @pymethod int|pythoncom|_DumpInterfaces|Dumps the interfaces still in existance to standard output
+static PyObject *
+PyXPCOMMethod_DumpInterfaces(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":_DumpInterfaces"))
+ return NULL;
+ return PyInt_FromLong(_PyXPCOM_DumpInterfaces());
+}
+#endif
+
+// @pymethod int|pythoncom|_GetGatewayCount|Retrieves the number of gateway objects currently in existance
+static PyObject *
+PyXPCOMMethod_GetGatewayCount(PyObject *self, PyObject *args)
+{
+ // @comm This is the number of Python object that implement COM servers which
+ // are still alive (ie, serving a client). The only way to reduce this count
+ // is to have the process which uses these PythonCOM servers release its references.
+ if (!PyArg_ParseTuple(args, ":_GetGatewayCount"))
+ return NULL;
+ return PyInt_FromLong(_PyXPCOM_GetGatewayCount());
+}
+
+static PyObject *
+PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
+{
+ // @comm This is the number of Python object that implement COM servers which
+ // are still alive (ie, serving a client). The only way to reduce this count
+ // is to have the process which uses these PythonCOM servers release its references.
+ if (!PyArg_ParseTuple(args, ":NS_ShutdownXPCOM"))
+ return NULL;
+ nsresult nr;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = NS_ShutdownXPCOM(nsnull);
+ Py_END_ALLOW_THREADS;
+
+#ifdef VBOX_DEBUG_LIFETIME
+ Py_nsISupports::dumpList();
+#endif
+
+ // Dont raise an exception - as we are probably shutting down
+ // and dont really case - just return the status
+ return PyInt_FromLong(nr);
+}
+
+static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
+
+// A hack to work around their magic constants!
+static PyObject *
+PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
+{
+ PyObject *obQueue, *obIID, *obOb;
+ int flags;
+ if (!PyArg_ParseTuple(args, "OOOi", &obQueue, &obIID, &obOb, &flags))
+ return NULL;
+ nsIID iid;
+ if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
+ return NULL;
+ nsCOMPtr<nsISupports> pob;
+ if (!Py_nsISupports::InterfaceFromPyObject(obOb, iid, getter_AddRefs(pob), PR_FALSE))
+ return NULL;
+ nsIEventQueue *pQueue = NULL;
+ nsIEventQueue *pQueueRelease = NULL;
+
+ if (PyInt_Check(obQueue)) {
+ pQueue = (nsIEventQueue *)PyInt_AsLong(obQueue);
+ } else {
+ if (!Py_nsISupports::InterfaceFromPyObject(obQueue, NS_GET_IID(nsIEventQueue), (nsISupports **)&pQueue, PR_TRUE))
+ return NULL;
+ pQueueRelease = pQueue;
+ }
+
+ nsresult rv_proxy;
+ nsCOMPtr<nsISupports> presult;
+ Py_BEGIN_ALLOW_THREADS;
+ nsCOMPtr<nsIProxyObjectManager> proxyMgr =
+ do_GetService(kProxyObjectManagerCID, &rv_proxy);
+
+ if ( NS_SUCCEEDED(rv_proxy) ) {
+ rv_proxy = proxyMgr->GetProxyForObject(pQueue,
+ iid,
+ pob,
+ flags,
+ getter_AddRefs(presult));
+ }
+ if (pQueueRelease)
+ pQueueRelease->Release();
+ Py_END_ALLOW_THREADS;
+
+ PyObject *result;
+ if (NS_SUCCEEDED(rv_proxy) ) {
+ result = Py_nsISupports::PyObjectFromInterface(presult, iid);
+ } else {
+ result = PyXPCOM_BuildPyException(rv_proxy);
+ }
+ return result;
+}
+
+static PyObject *
+PyXPCOMMethod_MakeVariant(PyObject *self, PyObject *args)
+{
+ PyObject *ob;
+ if (!PyArg_ParseTuple(args, "O:MakeVariant", &ob))
+ return NULL;
+ nsCOMPtr<nsIVariant> pVar;
+ nsresult nr = PyObject_AsVariant(ob, getter_AddRefs(pVar));
+ if (NS_FAILED(nr))
+ return PyXPCOM_BuildPyException(nr);
+ if (pVar == nsnull) {
+ NS_ERROR("PyObject_AsVariant worked but returned a NULL ptr!");
+ return PyXPCOM_BuildPyException(NS_ERROR_UNEXPECTED);
+ }
+ return Py_nsISupports::PyObjectFromInterface(pVar, NS_GET_IID(nsIVariant));
+}
+
+static PyObject *
+PyXPCOMMethod_GetVariantValue(PyObject *self, PyObject *args)
+{
+ PyObject *ob, *obParent = NULL;
+ if (!PyArg_ParseTuple(args, "O|O:GetVariantValue", &ob, &obParent))
+ return NULL;
+
+ nsCOMPtr<nsIVariant> var;
+ if (!Py_nsISupports::InterfaceFromPyObject(ob,
+ NS_GET_IID(nsISupports),
+ getter_AddRefs(var),
+ PR_FALSE))
+ return PyErr_Format(PyExc_ValueError,
+ "Object is not an nsIVariant (got %s)",
+ PyXPCOM_ObTypeName(ob));
+
+ Py_nsISupports *parent = nsnull;
+ if (obParent && obParent != Py_None) {
+ if (!Py_nsISupports::Check(obParent)) {
+ PyErr_SetString(PyExc_ValueError,
+ "Object not an nsISupports wrapper");
+ return NULL;
+ }
+ parent = (Py_nsISupports *)obParent;
+ }
+ return PyObject_FromVariant(parent, var);
+}
+
+PyObject *PyGetSpecialDirectory(PyObject *self, PyObject *args)
+{
+ char *dirname;
+ if (!PyArg_ParseTuple(args, "s:GetSpecialDirectory", &dirname))
+ return NULL;
+ nsCOMPtr<nsIFile> file;
+ nsresult r = NS_GetSpecialDirectory(dirname, getter_AddRefs(file));
+ if ( NS_FAILED(r) )
+ return PyXPCOM_BuildPyException(r);
+ // returned object swallows our reference.
+ return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile));
+}
+
+PyObject *AllocateBuffer(PyObject *self, PyObject *args)
+{
+ int bufSize;
+ if (!PyArg_ParseTuple(args, "i", &bufSize))
+ return NULL;
+#if PY_MAJOR_VERSION <= 2
+ return PyBuffer_New(bufSize);
+#else
+ return PyBytes_FromStringAndSize(NULL, bufSize);
+#endif
+}
+
+// Writes a message to the console service. This could be done via pure
+// Python code, but is useful when the logging code is actually the
+// xpcom .py framework itself (ie, we don't want our logging framework to
+// call back into the very code generating the log messages!
+PyObject *LogConsoleMessage(PyObject *self, PyObject *args)
+{
+ char *msg;
+ if (!PyArg_ParseTuple(args, "s", &msg))
+ return NULL;
+
+ nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+ if (consoleService)
+ consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
+ else {
+ // This either means no such service, or in shutdown - hardly worth
+ // the warning, and not worth reporting an error to Python about - its
+ // log handler would just need to catch and ignore it.
+ // And as this is only called by this logging setup, any messages should
+ // still go to stderr or a logfile.
+ NS_WARNING("pyxpcom can't log console message.");
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef VBOX
+
+# include <VBox/com/NativeEventQueue.h>
+# include <iprt/err.h>
+
+static PyObject *
+PyXPCOMMethod_WaitForEvents(PyObject *self, PyObject *args)
+{
+ long lTimeout;
+ if (!PyArg_ParseTuple(args, "l", &lTimeout))
+ return NULL;
+
+ int rc;
+ com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
+ NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
+ if (!aEventQ)
+ {
+ PyErr_SetString(PyExc_TypeError, "the main event queue is NULL");
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+
+ RTMSINTERVAL cMsTimeout = (RTMSINTERVAL)lTimeout;
+ if (lTimeout < 0 || (long)cMsTimeout != lTimeout)
+ cMsTimeout = RT_INDEFINITE_WAIT;
+ rc = aEventQ->processEventQueue(cMsTimeout);
+
+ Py_END_ALLOW_THREADS
+ if (RT_SUCCESS(rc))
+ return PyInt_FromLong(0);
+
+ if ( rc == VERR_TIMEOUT
+ || rc == VERR_INTERRUPTED)
+ return PyInt_FromLong(1);
+
+ if (rc == VERR_INVALID_CONTEXT)
+ {
+ PyErr_SetString(PyExc_Exception, "wrong thread, use the main thread");
+ return NULL;
+ }
+
+ return PyInt_FromLong(2);
+}
+
+static PyObject*
+PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args)
+{
+ com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
+ NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
+ if (!aEventQ)
+ return NULL;
+
+ int rc = aEventQ->interruptEventQueueProcessing();
+ return PyBool_FromLong(RT_SUCCESS(rc));
+}
+
+static nsresult deinitVBoxPython();
+
+static PyObject*
+PyXPCOMMethod_DeinitCOM(PyObject *self, PyObject *args)
+{
+ nsresult nr;
+ Py_BEGIN_ALLOW_THREADS;
+ nr = deinitVBoxPython();
+ Py_END_ALLOW_THREADS;
+ return PyInt_FromLong(nr);
+}
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+static PyObject*
+PyXPCOMMethod_AttachThread(PyObject *self, PyObject *args)
+{
+ nsresult rv;
+ PRInt32 result = 0;
+ nsCOMPtr<nsIEventQueueService> eqs;
+
+ // Create the Event Queue for this thread...
+ Py_BEGIN_ALLOW_THREADS;
+ eqs =
+ do_GetService(kEventQueueServiceCID, &rv);
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 1;
+ goto done;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ rv = eqs->CreateThreadEventQueue();
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 2;
+ goto done;
+ }
+
+ done:
+ /** @todo: better throw an exception on error */
+ return PyInt_FromLong(result);
+}
+
+static PyObject*
+PyXPCOMMethod_DetachThread(PyObject *self, PyObject *args)
+{
+ nsresult rv;
+ PRInt32 result = 0;
+ nsCOMPtr<nsIEventQueueService> eqs;
+
+ // Destroy the Event Queue for this thread...
+ Py_BEGIN_ALLOW_THREADS;
+ eqs =
+ do_GetService(kEventQueueServiceCID, &rv);
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 1;
+ goto done;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ rv = eqs->DestroyThreadEventQueue();
+ Py_END_ALLOW_THREADS;
+ if (NS_FAILED(rv))
+ {
+ result = 2;
+ goto done;
+ }
+
+ done:
+ /** @todo: better throw an exception on error */
+ return PyInt_FromLong(result);
+}
+
+#endif /* VBOX */
+
+extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
+
+static struct PyMethodDef xpcom_methods[]=
+{
+ {"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
+ {"GetComponentRegistrar", PyXPCOMMethod_GetComponentRegistrar, 1},
+#ifndef VBOX
+ {"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1}, // deprecated
+#endif
+ {"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
+ {"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
+ {"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
+#ifndef VBOX
+ {"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1}, // deprecated
+ {"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc.
+#endif
+ {"ID", PyXPCOMMethod_IID, 1}, // This is the official name.
+ {"NS_ShutdownXPCOM", PyXPCOMMethod_NS_ShutdownXPCOM, 1},
+ {"WrapObject", PyXPCOMMethod_WrapObject, 1},
+ {"UnwrapObject", PyXPCOMMethod_UnwrapObject, 1},
+ {"_GetInterfaceCount", PyXPCOMMethod_GetInterfaceCount, 1},
+ {"_GetGatewayCount", PyXPCOMMethod_GetGatewayCount, 1},
+ {"getProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
+ {"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
+ {"GetSpecialDirectory", PyGetSpecialDirectory, 1},
+ {"AllocateBuffer", AllocateBuffer, 1},
+ {"LogConsoleMessage", LogConsoleMessage, 1, "Write a message to the xpcom console service"},
+ {"MakeVariant", PyXPCOMMethod_MakeVariant, 1},
+ {"GetVariantValue", PyXPCOMMethod_GetVariantValue, 1},
+#ifdef VBOX
+ {"WaitForEvents", PyXPCOMMethod_WaitForEvents, 1},
+ {"InterruptWait", PyXPCOMMethod_InterruptWait, 1},
+ {"DeinitCOM", PyXPCOMMethod_DeinitCOM, 1},
+ {"AttachThread", PyXPCOMMethod_AttachThread, 1},
+ {"DetachThread", PyXPCOMMethod_DetachThread, 1},
+#endif
+#ifdef VBOX_DEBUG_LIFETIMES
+ {"_DumpInterfaces", PyXPCOMMethod_DumpInterfaces, 1},
+#endif
+ // These should no longer be used - just use the logging.getLogger('pyxpcom')...
+ /* bird: The above comment refers to LogWarning and LogError. Both now removed. */
+ { NULL }
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef xpcom_module =
+{
+ PyModuleDef_HEAD_INIT,
+ MODULE_NAME, /* name of module */
+ NULL, /* module documentation */
+ -1, /* size of per-interpreter state or -1 if using globals */
+ xpcom_methods
+};
+#endif
+
+
+#define REGISTER_IID(t) { \
+ PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \
+ PyDict_SetItemString(dict, "IID_"#t, iid_ob); \
+ Py_DECREF(iid_ob); \
+ }
+
+#define REGISTER_INT(val) { \
+ PyObject *ob = PyInt_FromLong(val); \
+ PyDict_SetItemString(dict, #val, ob); \
+ Py_DECREF(ob); \
+ }
+
+
+////////////////////////////////////////////////////////////
+// The module init code.
+//
+#if PY_MAJOR_VERSION <= 2
+extern "C" NS_EXPORT
+void
+#else
+PyObject *
+#endif
+init_xpcom() {
+ PyObject *oModule;
+
+ // ensure the framework has valid state to work with.
+ if (!PyXPCOM_Globals_Ensure())
+#if PY_MAJOR_VERSION <= 2
+ return;
+#else
+ return NULL;
+#endif
+
+ // Must force Python to start using thread locks
+ PyEval_InitThreads();
+
+ // Create the module and add the functions
+#if PY_MAJOR_VERSION <= 2
+ oModule = Py_InitModule(MODULE_NAME, xpcom_methods);
+#else
+ oModule = PyModule_Create(&xpcom_module);
+#endif
+
+ PyObject *dict = PyModule_GetDict(oModule);
+ PyObject *pycom_Error = PyXPCOM_Error;
+ if (pycom_Error == NULL || PyDict_SetItemString(dict, "error", pycom_Error) != 0)
+ {
+ PyErr_SetString(PyExc_MemoryError, "can't define error");
+#if PY_MAJOR_VERSION <= 2
+ return;
+#else
+ return NULL;
+#endif
+ }
+#ifndef Py_LIMITED_API
+ PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
+#else
+ PyDict_SetItemString(dict, "IIDType", (PyObject *)Py_nsIID::GetTypeObject());
+#endif
+
+ REGISTER_IID(nsISupports);
+ REGISTER_IID(nsISupportsCString);
+ REGISTER_IID(nsISupportsString);
+ REGISTER_IID(nsIModule);
+ REGISTER_IID(nsIFactory);
+ REGISTER_IID(nsIWeakReference);
+ REGISTER_IID(nsISupportsWeakReference);
+ REGISTER_IID(nsIClassInfo);
+ REGISTER_IID(nsIServiceManager);
+ REGISTER_IID(nsIComponentRegistrar);
+
+ // Register our custom interfaces.
+ REGISTER_IID(nsIComponentManager);
+ REGISTER_IID(nsIInterfaceInfoManager);
+ REGISTER_IID(nsIEnumerator);
+ REGISTER_IID(nsISimpleEnumerator);
+ REGISTER_IID(nsIInterfaceInfo);
+ REGISTER_IID(nsIInputStream);
+ REGISTER_IID(nsIClassInfo);
+ REGISTER_IID(nsIVariant);
+ // for backward compatibility:
+ REGISTER_IID(nsIComponentManagerObsolete);
+
+ // No good reason not to expose this impl detail, and tests can use it
+ REGISTER_IID(nsIInternalPython);
+ // We have special support for proxies - may as well add their constants!
+ REGISTER_INT(PROXY_SYNC);
+ REGISTER_INT(PROXY_ASYNC);
+ REGISTER_INT(PROXY_ALWAYS);
+ // Build flags that may be useful.
+ PyObject *ob = PyBool_FromLong(
+#ifdef NS_DEBUG
+ 1
+#else
+ 0
+#endif
+ );
+ PyDict_SetItemString(dict, "NS_DEBUG", ob);
+ Py_DECREF(ob);
+#if PY_MAJOR_VERSION >= 3
+ return oModule;
+#endif
+}
+
+#ifdef VBOX_PYXPCOM
+# include <VBox/com/com.h>
+using namespace com;
+
+# include <iprt/initterm.h>
+# include <iprt/string.h>
+# include <iprt/alloca.h>
+# include <iprt/stream.h>
+
+/** Set if NS_ShutdownXPCOM has been called successfully already and we don't
+ * need to do it again during module termination. This avoids assertion in the
+ * VBoxCOM glue code. */
+static bool g_fComShutdownAlready = true;
+
+# if PY_MAJOR_VERSION <= 2
+extern "C" NS_EXPORT
+void
+# else
+/** @todo r=klaus this is hacky, but as Python3 doesn't deal with ELF
+ * visibility, assuming that all globals are visible (which is ugly and not
+ * true in our case). */
+# undef PyMODINIT_FUNC
+# define PyMODINIT_FUNC extern "C" NS_EXPORT PyObject*
+PyMODINIT_FUNC
+# endif
+initVBoxPython() { /* NOTE! This name is redefined at the top of the file! */
+ static bool s_vboxInited = false;
+ if (!s_vboxInited) {
+ int rc = 0; /* Error handling in this code is NON-EXISTING. Sigh. */
+
+# if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
+ rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+# else
+ const char *home = getenv("VBOX_PROGRAM_PATH");
+ if (home) {
+ size_t len = strlen(home);
+ char *exepath = (char *)alloca(len + 32);
+ memcpy(exepath, home, len);
+ memcpy(exepath + len, "/pythonfake", sizeof("/pythonfake"));
+ rc = RTR3InitEx(RTR3INIT_VER_CUR, RTR3INIT_FLAGS_DLL | RTR3INIT_FLAGS_UNOBTRUSIVE, 0, NULL, exepath);
+ } else {
+ rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
+ }
+# endif
+
+ rc = com::Initialize();
+ g_fComShutdownAlready = false;
+
+# if PY_MAJOR_VERSION <= 2
+ init_xpcom();
+# else
+ return init_xpcom();
+# endif
+ }
+# if PY_MAJOR_VERSION >= 3
+ return NULL;
+# endif
+}
+
+static
+nsresult deinitVBoxPython()
+{
+ nsresult nr;
+ if (!g_fComShutdownAlready)
+ {
+ nr = com::Shutdown();
+ if (!NS_FAILED(nr))
+ g_fComShutdownAlready = true;
+ }
+ else
+ nr = NS_ERROR_NOT_INITIALIZED;
+ return nr;
+}
+
+#endif /* VBOX_PYXPCOM */
diff --git a/src/libs/xpcom18a4/python/src/readme.html b/src/libs/xpcom18a4/python/src/readme.html
new file mode 100644
index 00000000..b049dbad
--- /dev/null
+++ b/src/libs/xpcom18a4/python/src/readme.html
@@ -0,0 +1,99 @@
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
+<meta name="ProgId" content="FrontPage.Editor.Document">
+<title>Building the Python XPCOM package</title>
+</head>
+
+<body>
+
+<h1>Building the Python XPCOM package.</h1>
+
+<p>This file describes how to build the Python XPCOM C++ sources.</p>
+<p>There are the following steps</p>
+<ul>
+ <li><a href="#ConfiguringTheEnvironment">Configure environment variables</a></li>
+ <li><a href="#BuildingTheSources">Building the sources</a></li>
+</ul>
+<p>Testing etc is described in the <a href="../readme.html">main readme</a>.</p>
+<h2><a name="ConfiguringTheEnvironment">Configuring environment variables</a></h2>
+<h3> MOZ_SRC&nbsp;</h3>
+<p><b>Windows: </b>Run the standard MOZENV.BAT used to build Mozilla.&nbsp; This
+sets MOZ_SRC</p>
+<p><b>Unix:</b> Set MOZ_SRC to point to the base source directory - assumes
+&quot;mozilla&quot; sub-directory with mozilla directory tree under that. eg: assuming
+<i>/home/user/src/mozilla/dist/...</i>&quot;</p>
+<pre>export MOZ_SRC=/home/user/src</pre>
+<h3>PYTHON_SRC</h3>
+<p><b>Windows:</b> Set <i> PYTHON_SRC</i> to point to the base Python source directory.&nbsp;
+eg: assuming <i>c:\src\python\PCBuild\...</i><pre>set PYTHON_SRC=c:\src\python</pre>
+<p>Unix: Set PYTHON_SRC to point to the base of an &quot;installed&quot; Python
+tree. eg:<pre>export PYTHON_SRC=/usr/local/ActivePython-1.6</pre>
+<h2><a name="BuildingTheSources">Building the sources</a></h2>
+<p>You must ensure some environment variables are setup.&nbsp; The section on <a href="#ConfiguringTheEnvironment">configuring
+environment variables explains how.</a></p>
+<p>There are 2 build processes to run All C++ sources are in the <i>xpcom\src</i>
+ directory.:</p>
+<h3>Windows</h3>
+<ul>
+ <li> Execute &quot;compile.py&quot; in this directory. This will take <i>Setup.in</i>, create an MSDev project, and build
+ <i>..\_xpcom.pyd</i> and <i>..\_xpcom_d.pyd</i>&quot;</li>
+ <li> Change to the <i>loader</i> directory.</li>
+ <li> Run <i>nmake -f makefile.win</i>. This will create <i>pyloader.dll</i>, and
+ automatically copy it to the Mozilla build directory.</li>
+ <a href="#ConfiguringTheEnvironment">
+ </ul>
+ <p>Finally, </a><a href="../readme.html#RunningTheTests">run the tests</a>,
+ where we also test everything imports correctly.</p>
+<h3>Linux</h3>
+<p><b> NOTE:</b> Do not attempt to use &quot;Setup.in&quot; to create a Makefile&nbsp;</p>
+<ul>
+ <li>Run &quot;make&quot; in this directory.&nbsp; This will create <i>../_xpcommodule.so</i></li>
+ <li> Run "make" in the loader directory. This will create <i>libpyloader.so</i>,
+ and copy it to the Mozilla directory.</li>
+ <a href="#ConfiguringTheEnvironment">
+ </ul>
+ <p>Finally, </a><a href="../readme.html#RunningTheTests">running the tests</a>,
+ where we also test everything imports correctly.</p>
+
+</body>
+
+</html>
diff --git a/src/libs/xpcom18a4/python/test/.cvsignore b/src/libs/xpcom18a4/python/test/.cvsignore
new file mode 100644
index 00000000..52e4e611
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/.cvsignore
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
diff --git a/src/libs/xpcom18a4/python/test/output/test_com_exceptions b/src/libs/xpcom18a4/python/test/output/test_com_exceptions
new file mode 100644
index 00000000..16e4bda1
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_com_exceptions
@@ -0,0 +1,8 @@
+test_com_exceptions
+** Unhandled exception calling 'int8 do_short(in int16, inout int16, out int16, out retval int16);'
+** Returning nsresult of NS_ERROR_FAILURE
+** Unhandled exception calling 'int8 do_unsigned_short(in uint16, inout uint16, out uint16, out retval uint16);'
+** Returning nsresult of NS_ERROR_FAILURE
+** Unhandled exception calling 'int8 do_unsigned_long_long(in uint64, inout uint64, out uint64, out retval uint64);'
+** Returning nsresult of NS_ERROR_FAILURE
+The xpcom exception tests passed
diff --git a/src/libs/xpcom18a4/python/test/output/test_comfile b/src/libs/xpcom18a4/python/test/output/test_comfile
new file mode 100644
index 00000000..8de43add
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_comfile
@@ -0,0 +1,7 @@
+test_comfile
+Open as string test worked.
+Open as URL test worked.
+File test using buffers worked.
+Local file read test worked.
+Read the correct data.
+Chunks read the correct data.
diff --git a/src/libs/xpcom18a4/python/test/output/test_components b/src/libs/xpcom18a4/python/test/output/test_components
new file mode 100644
index 00000000..4a6386e7
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_components
@@ -0,0 +1,4 @@
+test_components
+The interfaces object appeared to work!
+The classes object appeared to work!
+The ID function appeared to work!
diff --git a/src/libs/xpcom18a4/python/test/output/test_isupports_primitives b/src/libs/xpcom18a4/python/test/output/test_isupports_primitives
new file mode 100644
index 00000000..7765ac21
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_isupports_primitives
@@ -0,0 +1,2 @@
+test_isupports_primitives
+The nsISupports primitive interface tests appeared to work
diff --git a/src/libs/xpcom18a4/python/test/output/test_streams b/src/libs/xpcom18a4/python/test/output/test_streams
new file mode 100644
index 00000000..e81ef151
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_streams
@@ -0,0 +1 @@
+test_streams
diff --git a/src/libs/xpcom18a4/python/test/output/test_test_component b/src/libs/xpcom18a4/python/test/output/test_test_component
new file mode 100644
index 00000000..c57c1325
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_test_component
@@ -0,0 +1,4 @@
+test_test_component
+Testing the Python.TestComponent component
+The Python test component worked!
+Javascript could successfully use the Python test component.
diff --git a/src/libs/xpcom18a4/python/test/output/test_weakreferences b/src/libs/xpcom18a4/python/test/output/test_weakreferences
new file mode 100644
index 00000000..b337d26a
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/output/test_weakreferences
@@ -0,0 +1,2 @@
+test_weakreferences
+Weak-reference tests appear to have worked!
diff --git a/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py b/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py
new file mode 100755
index 00000000..447c5446
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py
@@ -0,0 +1,126 @@
+# test tools for the pyxpcom bindings
+from xpcom import _xpcom
+import unittest
+
+# export a "getmemusage()" function that returns a useful "bytes used" count
+# for the current process. Growth in this when doing the same thing over and
+# over implies a leak.
+
+try:
+ import win32api
+ import win32pdh
+ import win32pdhutil
+ have_pdh = 1
+except ImportError:
+ have_pdh = 0
+
+# XXX - win32pdh is slow, particularly finding our current process.
+# A better way would be good.
+
+# Our win32pdh specific functions - they can be at the top-level on all
+# platforms, but will only actually be called if the modules are available.
+def FindMyCounter():
+ pid_me = win32api.GetCurrentProcessId()
+
+ object = "Process"
+ items, instances = win32pdh.EnumObjectItems(None,None,object, -1)
+ for instance in instances:
+ # We use 2 counters - "ID Process" and "Working Set"
+ counter = "ID Process"
+ format = win32pdh.PDH_FMT_LONG
+
+ hq = win32pdh.OpenQuery()
+ path = win32pdh.MakeCounterPath( (None,object,instance, None, -1,"ID Process") )
+ hc1 = win32pdh.AddCounter(hq, path)
+ path = win32pdh.MakeCounterPath( (None,object,instance, None, -1,"Working Set") )
+ hc2 = win32pdh.AddCounter(hq, path)
+ win32pdh.CollectQueryData(hq)
+ type, pid = win32pdh.GetFormattedCounterValue(hc1, format)
+ if pid==pid_me:
+ win32pdh.RemoveCounter(hc1) # not needed any more
+ return hq, hc2
+ # Not mine - close the query and try again
+ win32pdh.RemoveCounter(hc1)
+ win32pdh.RemoveCounter(hc2)
+ win32pdh.CloseQuery(hq)
+ else:
+ raise RuntimeError, "Can't find myself!?"
+
+def CloseCounter(hq, hc):
+ win32pdh.RemoveCounter(hc)
+ win32pdh.CloseQuery(hq)
+
+def GetCounterValue(hq, hc):
+ win32pdh.CollectQueryData(hq)
+ format = win32pdh.PDH_FMT_LONG
+ type, val = win32pdh.GetFormattedCounterValue(hc, format)
+ return val
+
+g_pdh_data = None
+# The pdh function that does the work
+def pdh_getmemusage():
+ global g_pdh_data
+ if g_pdh_data is None:
+ hq, hc = FindMyCounter()
+ g_pdh_data = hq, hc
+ hq, hc = g_pdh_data
+ return GetCounterValue(hq, hc)
+
+# The public bit
+if have_pdh:
+ getmemusage = pdh_getmemusage
+else:
+ def getmemusage():
+ return 0
+
+# Test runner utilities, including some support for builtin leak tests.
+class TestLoader(unittest.TestLoader):
+ def loadTestsFromTestCase(self, testCaseClass):
+ """Return a suite of all tests cases contained in testCaseClass"""
+ leak_tests = []
+ for name in self.getTestCaseNames(testCaseClass):
+ real_test = testCaseClass(name)
+ leak_test = self._getTestWrapper(real_test)
+ leak_tests.append(leak_test)
+ return self.suiteClass(leak_tests)
+ def _getTestWrapper(self, test):
+ # later! see pywin32's win32/test/util.py
+ return test
+ def loadTestsFromModule(self, mod):
+ if hasattr(mod, "suite"):
+ ret = mod.suite()
+ else:
+ ret = unittest.TestLoader.loadTestsFromModule(self, mod)
+ assert ret.countTestCases() > 0, "No tests in %r" % (mod,)
+ return ret
+ def loadTestsFromName(self, name, module=None):
+ test = unittest.TestLoader.loadTestsFromName(self, name, module)
+ if isinstance(test, unittest.TestSuite):
+ pass # hmmm? print "Don't wrap suites yet!", test._tests
+ elif isinstance(test, unittest.TestCase):
+ test = self._getTestWrapper(test)
+ else:
+ print "XXX - what is", test
+ return test
+
+# A base class our tests should derive from (well, one day it will be)
+TestCase = unittest.TestCase
+
+def suite_from_functions(*funcs):
+ suite = unittest.TestSuite()
+ for func in funcs:
+ suite.addTest(unittest.FunctionTestCase(func))
+ return suite
+
+def testmain(*args, **kw):
+ new_kw = kw.copy()
+ if not new_kw.has_key('testLoader'):
+ new_kw['testLoader'] = TestLoader()
+ try:
+ unittest.main(*args, **new_kw)
+ finally:
+ _xpcom.NS_ShutdownXPCOM()
+ ni = _xpcom._GetInterfaceCount()
+ ng = _xpcom._GetGatewayCount()
+ if ni or ng:
+ print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
diff --git a/src/libs/xpcom18a4/python/test/regrtest.py b/src/libs/xpcom18a4/python/test/regrtest.py
new file mode 100644
index 00000000..90d07948
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/regrtest.py
@@ -0,0 +1,91 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <mhammond@skippinet.com.au> (original author)
+#
+# 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 *****
+
+# regrtest.py
+#
+# The Regression Tests for the xpcom package.
+import os
+import sys
+
+import unittest
+
+# A little magic to create a single "test suite" from all test_ files
+# in this dir. A single suite makes for prettier output test :)
+def suite():
+ # Loop over all test_*.py files here
+ try:
+ me = __file__
+ except NameError:
+ me = sys.argv[0]
+ me = os.path.abspath(me)
+ files = os.listdir(os.path.dirname(me))
+ suite = unittest.TestSuite()
+ # XXX - add the others here!
+ #suite.addTest(unittest.FunctionTestCase(import_all))
+ for file in files:
+ base, ext = os.path.splitext(file)
+ if ext=='.py' and os.path.basename(base).startswith("test_"):
+ mod = __import__(base)
+ if hasattr(mod, "suite"):
+ test = mod.suite()
+ else:
+ test = unittest.defaultTestLoader.loadTestsFromModule(mod)
+ suite.addTest(test)
+ return suite
+
+class CustomLoader(unittest.TestLoader):
+ def loadTestsFromModule(self, module):
+ return suite()
+
+try:
+ unittest.TestProgram(testLoader=CustomLoader())(argv=sys.argv)
+finally:
+ from xpcom import _xpcom
+ _xpcom.NS_ShutdownXPCOM() # To get leak stats and otherwise ensure life is good.
+ ni = _xpcom._GetInterfaceCount()
+ ng = _xpcom._GetGatewayCount()
+ if ni or ng:
+ # The old 'regrtest' that was not based purely on unittest did not
+ # do this check at the end - it relied on each module doing it itself.
+ # Thus, these leaks are not new, just newly noticed :) Likely to be
+ # something silly like module globals.
+ if ni == 6 and ng == 1:
+ print "Sadly, there are 6/1 leaks, but these appear normal and benign"
+ else:
+ print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
+ else:
+ print "yay! Our leaks have all vanished!"
diff --git a/src/libs/xpcom18a4/python/test/test_com_exceptions.py b/src/libs/xpcom18a4/python/test/test_com_exceptions.py
new file mode 100755
index 00000000..7813bf98
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_com_exceptions.py
@@ -0,0 +1,124 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is ActiveState Tool Corp.
+# Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001
+# ActiveState Tool Corp. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+# Test pyxpcom exception.
+
+from xpcom import components, nsError, ServerException, COMException, logger
+from xpcom.server import WrapObject
+from pyxpcom_test_tools import testmain
+
+import unittest
+import logging
+
+class PythonFailingComponent:
+ # Re-use the test interface for this test.
+ _com_interfaces_ = components.interfaces.nsIPythonTestInterfaceExtra
+
+ def do_boolean(self, p1, p2):
+ # This should cause the caller to see a "silent" NS_ERROR_FAILURE exception.
+ raise ServerException()
+
+ def do_octet(self, p1, p2):
+ # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
+ raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+ def do_short(self, p1, p2):
+ # This should cause the caller to see a "debug" NS_ERROR_FAILURE exception.
+ raise COMException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+ def do_unsigned_short(self, p1, p2):
+ # This should cause the caller to see a "debug" NS_ERROR_FAILURE exception.
+ raise "Foo"
+
+ def do_long(self, p1, p2):
+ # This should cause the caller to see a "silent" NS_ERROR_FAILURE exception.
+ raise ServerException
+
+ def do_unsigned_long(self, p1, p2):
+ # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
+ raise ServerException, nsError.NS_ERROR_NOT_IMPLEMENTED
+
+ def do_long_long(self, p1, p2):
+ # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception.
+ raise ServerException, (nsError.NS_ERROR_NOT_IMPLEMENTED, "testing")
+
+ def do_unsigned_long_long(self, p1, p2):
+ # Report of a crash in this case - test it!
+ raise ServerException, "A bad exception param"
+
+class TestHandler(logging.Handler):
+ def __init__(self, level=logging.ERROR): # only counting error records
+ logging.Handler.__init__(self, level)
+ self.records = []
+
+ def reset(self):
+ self.records = []
+
+ def handle(self, record):
+ self.records.append(record)
+
+class ExceptionTests(unittest.TestCase):
+
+ def _testit(self, expected_errno, num_tracebacks, func, *args):
+
+ # Screw with the logger
+ old_handlers = logger.handlers
+ test_handler = TestHandler()
+ logger.handlers = [test_handler]
+
+ try:
+ try:
+ apply(func, args)
+ except COMException, what:
+ if what.errno != expected_errno:
+ raise
+ finally:
+ logger.handlers = old_handlers
+ self.failUnlessEqual(num_tracebacks, len(test_handler.records))
+
+ def testEmAll(self):
+ ob = WrapObject( PythonFailingComponent(), components.interfaces.nsIPythonTestInterfaceExtra)
+ self._testit(nsError.NS_ERROR_FAILURE, 0, ob.do_boolean, 0, 0)
+ self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_octet, 0, 0)
+ self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_short, 0, 0)
+ self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_unsigned_short, 0, 0)
+ self._testit(nsError.NS_ERROR_FAILURE, 0, ob.do_long, 0, 0)
+ self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_unsigned_long, 0, 0)
+ self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_long_long, 0, 0)
+ self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_unsigned_long_long, 0, 0)
+
+if __name__=='__main__':
+ testmain()
diff --git a/src/libs/xpcom18a4/python/test/test_comfile.py b/src/libs/xpcom18a4/python/test/test_comfile.py
new file mode 100755
index 00000000..9ffebe37
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_comfile.py
@@ -0,0 +1,49 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond (markh@activestate.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either 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 *****
+
+"""Test the xpcom.file module."""
+from pyxpcom_test_tools import suite_from_functions, testmain
+
+import xpcom.file
+
+# Make this test run under our std test suite
+def suite():
+ return suite_from_functions(xpcom.file._TestAll)
+
+if __name__=='__main__':
+ testmain()
+
diff --git a/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done
diff --git a/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h
new file mode 100644
index 00000000..7d0cd8c9
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h
@@ -0,0 +1,1411 @@
+/*
+ * DO NOT EDIT. THIS FILE IS GENERATED FROM py_test_component.idl
+ */
+
+#ifndef __gen_py_test_component_h__
+#define __gen_py_test_component_h__
+
+
+#ifndef __gen_nsISupports_h__
+#include "nsISupports.h"
+#endif
+
+#ifndef __gen_nsIVariant_h__
+#include "nsIVariant.h"
+#endif
+
+/* For IDL files that don't want to include root IDL files. */
+#ifndef NS_NO_VTABLE
+#define NS_NO_VTABLE
+#endif
+
+/* starting interface: nsIPythonTestInterface */
+#define NS_IPYTHONTESTINTERFACE_IID_STR "1ecaed4f-e4d5-4ee7-abf0-7d72ae1441d7"
+
+#define NS_IPYTHONTESTINTERFACE_IID \
+ {0x1ecaed4f, 0xe4d5, 0x4ee7, \
+ { 0xab, 0xf0, 0x7d, 0x72, 0xae, 0x14, 0x41, 0xd7 }}
+
+class NS_NO_VTABLE nsIPythonTestInterface : public nsISupports {
+ public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACE_IID)
+
+ enum { One = 1 };
+
+ enum { Two = 2 };
+
+ enum { MinusOne = -1 };
+
+ enum { BigLong = 2147483647 };
+
+ enum { BiggerLong = 4294967295 };
+
+ enum { BigULong = 4294967295U };
+
+ /* attribute boolean boolean_value; */
+ NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) = 0;
+ NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) = 0;
+
+ /* attribute octet octet_value; */
+ NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) = 0;
+ NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) = 0;
+
+ /* attribute short short_value; */
+ NS_IMETHOD GetShort_value(PRInt16 *aShort_value) = 0;
+ NS_IMETHOD SetShort_value(PRInt16 aShort_value) = 0;
+
+ /* attribute unsigned short ushort_value; */
+ NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) = 0;
+ NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) = 0;
+
+ /* attribute long long_value; */
+ NS_IMETHOD GetLong_value(PRInt32 *aLong_value) = 0;
+ NS_IMETHOD SetLong_value(PRInt32 aLong_value) = 0;
+
+ /* attribute unsigned long ulong_value; */
+ NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) = 0;
+ NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) = 0;
+
+ /* attribute long long long_long_value; */
+ NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) = 0;
+ NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) = 0;
+
+ /* attribute unsigned long long ulong_long_value; */
+ NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) = 0;
+ NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) = 0;
+
+ /* attribute float float_value; */
+ NS_IMETHOD GetFloat_value(float *aFloat_value) = 0;
+ NS_IMETHOD SetFloat_value(float aFloat_value) = 0;
+
+ /* attribute double double_value; */
+ NS_IMETHOD GetDouble_value(double *aDouble_value) = 0;
+ NS_IMETHOD SetDouble_value(double aDouble_value) = 0;
+
+ /* attribute char char_value; */
+ NS_IMETHOD GetChar_value(char *aChar_value) = 0;
+ NS_IMETHOD SetChar_value(char aChar_value) = 0;
+
+ /* attribute wchar wchar_value; */
+ NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) = 0;
+ NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) = 0;
+
+ /* attribute string string_value; */
+ NS_IMETHOD GetString_value(char * *aString_value) = 0;
+ NS_IMETHOD SetString_value(const char * aString_value) = 0;
+
+ /* attribute wstring wstring_value; */
+ NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) = 0;
+ NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) = 0;
+
+ /* attribute AString astring_value; */
+ NS_IMETHOD GetAstring_value(nsAString & aAstring_value) = 0;
+ NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) = 0;
+
+ /* attribute ACString acstring_value; */
+ NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) = 0;
+ NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) = 0;
+
+ /* attribute AUTF8String utf8string_value; */
+ NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) = 0;
+ NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) = 0;
+
+ /* attribute nsIIDRef iid_value; */
+ NS_IMETHOD GetIid_value(nsIID & *aIid_value) = 0;
+ NS_IMETHOD SetIid_value(const nsIID & aIid_value) = 0;
+
+ /* attribute nsIPythonTestInterface interface_value; */
+ NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) = 0;
+ NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) = 0;
+
+ /* attribute nsISupports isupports_value; */
+ NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) = 0;
+ NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) = 0;
+
+ /* boolean do_boolean (in boolean p1, inout boolean p2, out boolean p3); */
+ NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) = 0;
+
+ /* octet do_octet (in octet p1, inout octet p2, out octet p3); */
+ NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) = 0;
+
+ /* short do_short (in short p1, inout short p2, out short p3); */
+ NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) = 0;
+
+ /* unsigned short do_unsigned_short (in unsigned short p1, inout unsigned short p2, out unsigned short p3); */
+ NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) = 0;
+
+ /* long do_long (in long p1, inout long p2, out long p3); */
+ NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) = 0;
+
+ /* unsigned long do_unsigned_long (in unsigned long p1, inout unsigned long p2, out unsigned long p3); */
+ NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) = 0;
+
+ /* long long do_long_long (in long long p1, inout long long p2, out long long p3); */
+ NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) = 0;
+
+ /* unsigned long long do_unsigned_long_long (in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); */
+ NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) = 0;
+
+ /* float do_float (in float p1, inout float p2, out float p3); */
+ NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) = 0;
+
+ /* double do_double (in double p1, inout double p2, out double p3); */
+ NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) = 0;
+
+ /* char do_char (in char p1, inout char p2, out char p3); */
+ NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) = 0;
+
+ /* wchar do_wchar (in wchar p1, inout wchar p2, out wchar p3); */
+ NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) = 0;
+
+ /* string do_string (in string p1, inout string p2, out string p3); */
+ NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) = 0;
+
+ /* wstring do_wstring (in wstring p1, inout wstring p2, out wstring p3); */
+ NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) = 0;
+
+ /* nsIIDRef do_nsIIDRef (in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); */
+ NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) = 0;
+
+ /* nsIPythonTestInterface do_nsIPythonTestInterface (in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); */
+ NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) = 0;
+
+ /* nsISupports do_nsISupports (in nsISupports p1, inout nsISupports p2, out nsISupports p3); */
+ NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) = 0;
+
+ /* void do_nsISupportsIs (in nsIIDRef iid, [iid_is (iid), retval] out nsQIResult result); */
+ NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIPYTHONTESTINTERFACE \
+ NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value); \
+ NS_IMETHOD SetBoolean_value(PRBool aBoolean_value); \
+ NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value); \
+ NS_IMETHOD SetOctet_value(PRUint8 aOctet_value); \
+ NS_IMETHOD GetShort_value(PRInt16 *aShort_value); \
+ NS_IMETHOD SetShort_value(PRInt16 aShort_value); \
+ NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value); \
+ NS_IMETHOD SetUshort_value(PRUint16 aUshort_value); \
+ NS_IMETHOD GetLong_value(PRInt32 *aLong_value); \
+ NS_IMETHOD SetLong_value(PRInt32 aLong_value); \
+ NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value); \
+ NS_IMETHOD SetUlong_value(PRUint32 aUlong_value); \
+ NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value); \
+ NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value); \
+ NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value); \
+ NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value); \
+ NS_IMETHOD GetFloat_value(float *aFloat_value); \
+ NS_IMETHOD SetFloat_value(float aFloat_value); \
+ NS_IMETHOD GetDouble_value(double *aDouble_value); \
+ NS_IMETHOD SetDouble_value(double aDouble_value); \
+ NS_IMETHOD GetChar_value(char *aChar_value); \
+ NS_IMETHOD SetChar_value(char aChar_value); \
+ NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value); \
+ NS_IMETHOD SetWchar_value(PRUnichar aWchar_value); \
+ NS_IMETHOD GetString_value(char * *aString_value); \
+ NS_IMETHOD SetString_value(const char * aString_value); \
+ NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value); \
+ NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value); \
+ NS_IMETHOD GetAstring_value(nsAString & aAstring_value); \
+ NS_IMETHOD SetAstring_value(const nsAString & aAstring_value); \
+ NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value); \
+ NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value); \
+ NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value); \
+ NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value); \
+ NS_IMETHOD GetIid_value(nsIID & *aIid_value); \
+ NS_IMETHOD SetIid_value(const nsIID & aIid_value); \
+ NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value); \
+ NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value); \
+ NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value); \
+ NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value); \
+ NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval); \
+ NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval); \
+ NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval); \
+ NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval); \
+ NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval); \
+ NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval); \
+ NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval); \
+ NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval); \
+ NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval); \
+ NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval); \
+ NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval); \
+ NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval); \
+ NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval); \
+ NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval); \
+ NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval); \
+ NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval); \
+ NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval); \
+ NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result);
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIPYTHONTESTINTERFACE(_to) \
+ NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) { return _to GetBoolean_value(aBoolean_value); } \
+ NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) { return _to SetBoolean_value(aBoolean_value); } \
+ NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) { return _to GetOctet_value(aOctet_value); } \
+ NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) { return _to SetOctet_value(aOctet_value); } \
+ NS_IMETHOD GetShort_value(PRInt16 *aShort_value) { return _to GetShort_value(aShort_value); } \
+ NS_IMETHOD SetShort_value(PRInt16 aShort_value) { return _to SetShort_value(aShort_value); } \
+ NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) { return _to GetUshort_value(aUshort_value); } \
+ NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) { return _to SetUshort_value(aUshort_value); } \
+ NS_IMETHOD GetLong_value(PRInt32 *aLong_value) { return _to GetLong_value(aLong_value); } \
+ NS_IMETHOD SetLong_value(PRInt32 aLong_value) { return _to SetLong_value(aLong_value); } \
+ NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) { return _to GetUlong_value(aUlong_value); } \
+ NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) { return _to SetUlong_value(aUlong_value); } \
+ NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) { return _to GetLong_long_value(aLong_long_value); } \
+ NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) { return _to SetLong_long_value(aLong_long_value); } \
+ NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) { return _to GetUlong_long_value(aUlong_long_value); } \
+ NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) { return _to SetUlong_long_value(aUlong_long_value); } \
+ NS_IMETHOD GetFloat_value(float *aFloat_value) { return _to GetFloat_value(aFloat_value); } \
+ NS_IMETHOD SetFloat_value(float aFloat_value) { return _to SetFloat_value(aFloat_value); } \
+ NS_IMETHOD GetDouble_value(double *aDouble_value) { return _to GetDouble_value(aDouble_value); } \
+ NS_IMETHOD SetDouble_value(double aDouble_value) { return _to SetDouble_value(aDouble_value); } \
+ NS_IMETHOD GetChar_value(char *aChar_value) { return _to GetChar_value(aChar_value); } \
+ NS_IMETHOD SetChar_value(char aChar_value) { return _to SetChar_value(aChar_value); } \
+ NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) { return _to GetWchar_value(aWchar_value); } \
+ NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) { return _to SetWchar_value(aWchar_value); } \
+ NS_IMETHOD GetString_value(char * *aString_value) { return _to GetString_value(aString_value); } \
+ NS_IMETHOD SetString_value(const char * aString_value) { return _to SetString_value(aString_value); } \
+ NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) { return _to GetWstring_value(aWstring_value); } \
+ NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) { return _to SetWstring_value(aWstring_value); } \
+ NS_IMETHOD GetAstring_value(nsAString & aAstring_value) { return _to GetAstring_value(aAstring_value); } \
+ NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) { return _to SetAstring_value(aAstring_value); } \
+ NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) { return _to GetAcstring_value(aAcstring_value); } \
+ NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) { return _to SetAcstring_value(aAcstring_value); } \
+ NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) { return _to GetUtf8string_value(aUtf8string_value); } \
+ NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) { return _to SetUtf8string_value(aUtf8string_value); } \
+ NS_IMETHOD GetIid_value(nsIID & *aIid_value) { return _to GetIid_value(aIid_value); } \
+ NS_IMETHOD SetIid_value(const nsIID & aIid_value) { return _to SetIid_value(aIid_value); } \
+ NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) { return _to GetInterface_value(aInterface_value); } \
+ NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) { return _to SetInterface_value(aInterface_value); } \
+ NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) { return _to GetIsupports_value(aIsupports_value); } \
+ NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) { return _to SetIsupports_value(aIsupports_value); } \
+ NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) { return _to Do_boolean(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) { return _to Do_octet(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) { return _to Do_short(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) { return _to Do_unsigned_short(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) { return _to Do_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) { return _to Do_unsigned_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) { return _to Do_long_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) { return _to Do_unsigned_long_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) { return _to Do_float(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) { return _to Do_double(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) { return _to Do_char(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) { return _to Do_wchar(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) { return _to Do_string(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) { return _to Do_wstring(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) { return _to Do_nsIIDRef(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) { return _to Do_nsIPythonTestInterface(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) { return _to Do_nsISupports(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) { return _to Do_nsISupportsIs(iid, result); }
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACE(_to) \
+ NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetBoolean_value(aBoolean_value); } \
+ NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetBoolean_value(aBoolean_value); } \
+ NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetOctet_value(aOctet_value); } \
+ NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetOctet_value(aOctet_value); } \
+ NS_IMETHOD GetShort_value(PRInt16 *aShort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetShort_value(aShort_value); } \
+ NS_IMETHOD SetShort_value(PRInt16 aShort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetShort_value(aShort_value); } \
+ NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUshort_value(aUshort_value); } \
+ NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUshort_value(aUshort_value); } \
+ NS_IMETHOD GetLong_value(PRInt32 *aLong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetLong_value(aLong_value); } \
+ NS_IMETHOD SetLong_value(PRInt32 aLong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetLong_value(aLong_value); } \
+ NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUlong_value(aUlong_value); } \
+ NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUlong_value(aUlong_value); } \
+ NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetLong_long_value(aLong_long_value); } \
+ NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetLong_long_value(aLong_long_value); } \
+ NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUlong_long_value(aUlong_long_value); } \
+ NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUlong_long_value(aUlong_long_value); } \
+ NS_IMETHOD GetFloat_value(float *aFloat_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFloat_value(aFloat_value); } \
+ NS_IMETHOD SetFloat_value(float aFloat_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetFloat_value(aFloat_value); } \
+ NS_IMETHOD GetDouble_value(double *aDouble_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDouble_value(aDouble_value); } \
+ NS_IMETHOD SetDouble_value(double aDouble_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetDouble_value(aDouble_value); } \
+ NS_IMETHOD GetChar_value(char *aChar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetChar_value(aChar_value); } \
+ NS_IMETHOD SetChar_value(char aChar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetChar_value(aChar_value); } \
+ NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetWchar_value(aWchar_value); } \
+ NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetWchar_value(aWchar_value); } \
+ NS_IMETHOD GetString_value(char * *aString_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetString_value(aString_value); } \
+ NS_IMETHOD SetString_value(const char * aString_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetString_value(aString_value); } \
+ NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetWstring_value(aWstring_value); } \
+ NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetWstring_value(aWstring_value); } \
+ NS_IMETHOD GetAstring_value(nsAString & aAstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetAstring_value(aAstring_value); } \
+ NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetAstring_value(aAstring_value); } \
+ NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetAcstring_value(aAcstring_value); } \
+ NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetAcstring_value(aAcstring_value); } \
+ NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUtf8string_value(aUtf8string_value); } \
+ NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUtf8string_value(aUtf8string_value); } \
+ NS_IMETHOD GetIid_value(nsIID & *aIid_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIid_value(aIid_value); } \
+ NS_IMETHOD SetIid_value(const nsIID & aIid_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetIid_value(aIid_value); } \
+ NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetInterface_value(aInterface_value); } \
+ NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetInterface_value(aInterface_value); } \
+ NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIsupports_value(aIsupports_value); } \
+ NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetIsupports_value(aIsupports_value); } \
+ NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_boolean(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_octet(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_short(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_short(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_long_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_long_long(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_float(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_double(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_char(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_wchar(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_string(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_wstring(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsIIDRef(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsIPythonTestInterface(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsISupports(p1, p2, p3, _retval); } \
+ NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsISupportsIs(iid, result); }
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsPythonTestInterface : public nsIPythonTestInterface
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPYTHONTESTINTERFACE
+
+ nsPythonTestInterface();
+
+private:
+ ~nsPythonTestInterface();
+
+protected:
+ /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsPythonTestInterface, nsIPythonTestInterface)
+
+nsPythonTestInterface::nsPythonTestInterface()
+{
+ /* member initializers and constructor code */
+}
+
+nsPythonTestInterface::~nsPythonTestInterface()
+{
+ /* destructor code */
+}
+
+/* attribute boolean boolean_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetBoolean_value(PRBool *aBoolean_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetBoolean_value(PRBool aBoolean_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute octet octet_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetOctet_value(PRUint8 *aOctet_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetOctet_value(PRUint8 aOctet_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute short short_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetShort_value(PRInt16 *aShort_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetShort_value(PRInt16 aShort_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute unsigned short ushort_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUshort_value(PRUint16 *aUshort_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUshort_value(PRUint16 aUshort_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute long long_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetLong_value(PRInt32 *aLong_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetLong_value(PRInt32 aLong_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute unsigned long ulong_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUlong_value(PRUint32 *aUlong_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUlong_value(PRUint32 aUlong_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute long long long_long_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetLong_long_value(PRInt64 *aLong_long_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetLong_long_value(PRInt64 aLong_long_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute unsigned long long ulong_long_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUlong_long_value(PRUint64 *aUlong_long_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUlong_long_value(PRUint64 aUlong_long_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute float float_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetFloat_value(float *aFloat_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetFloat_value(float aFloat_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute double double_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetDouble_value(double *aDouble_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetDouble_value(double aDouble_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute char char_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetChar_value(char *aChar_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetChar_value(char aChar_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute wchar wchar_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetWchar_value(PRUnichar *aWchar_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetWchar_value(PRUnichar aWchar_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute string string_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetString_value(char * *aString_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetString_value(const char * aString_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute wstring wstring_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetWstring_value(PRUnichar * *aWstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetWstring_value(const PRUnichar * aWstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute AString astring_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetAstring_value(nsAString & aAstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetAstring_value(const nsAString & aAstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute ACString acstring_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetAcstring_value(nsACString & aAcstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetAcstring_value(const nsACString & aAcstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute AUTF8String utf8string_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetUtf8string_value(nsACString & aUtf8string_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetUtf8string_value(const nsACString & aUtf8string_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsIIDRef iid_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetIid_value(nsIID & *aIid_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetIid_value(const nsIID & aIid_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsIPythonTestInterface interface_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetInterface_value(nsIPythonTestInterface * *aInterface_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetInterface_value(nsIPythonTestInterface * aInterface_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute nsISupports isupports_value; */
+NS_IMETHODIMP nsPythonTestInterface::GetIsupports_value(nsISupports * *aIsupports_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterface::SetIsupports_value(nsISupports * aIsupports_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* boolean do_boolean (in boolean p1, inout boolean p2, out boolean p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* octet do_octet (in octet p1, inout octet p2, out octet p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* short do_short (in short p1, inout short p2, out short p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* unsigned short do_unsigned_short (in unsigned short p1, inout unsigned short p2, out unsigned short p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* long do_long (in long p1, inout long p2, out long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* unsigned long do_unsigned_long (in unsigned long p1, inout unsigned long p2, out unsigned long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* long long do_long_long (in long long p1, inout long long p2, out long long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* unsigned long long do_unsigned_long_long (in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* float do_float (in float p1, inout float p2, out float p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_float(float p1, float *p2, float *p3, float *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* double do_double (in double p1, inout double p2, out double p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_double(double p1, double *p2, double *p3, double *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* char do_char (in char p1, inout char p2, out char p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_char(char p1, char *p2, char *p3, char *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* wchar do_wchar (in wchar p1, inout wchar p2, out wchar p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* string do_string (in string p1, inout string p2, out string p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_string(const char *p1, char **p2, char **p3, char **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* wstring do_wstring (in wstring p1, inout wstring p2, out wstring p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIIDRef do_nsIIDRef (in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIPythonTestInterface do_nsIPythonTestInterface (in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsISupports do_nsISupports (in nsISupports p1, inout nsISupports p2, out nsISupports p3); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void do_nsISupportsIs (in nsIIDRef iid, [iid_is (iid), retval] out nsQIResult result); */
+NS_IMETHODIMP nsPythonTestInterface::Do_nsISupportsIs(const nsIID & iid, void * *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+/* starting interface: nsIPythonTestInterfaceExtra */
+#define NS_IPYTHONTESTINTERFACEEXTRA_IID_STR "b38d1538-fe92-42c3-831f-285242edeea4"
+
+#define NS_IPYTHONTESTINTERFACEEXTRA_IID \
+ {0xb38d1538, 0xfe92, 0x42c3, \
+ { 0x83, 0x1f, 0x28, 0x52, 0x42, 0xed, 0xee, 0xa4 }}
+
+class NS_NO_VTABLE nsIPythonTestInterfaceExtra : public nsIPythonTestInterface {
+ public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACEEXTRA_IID)
+
+ /* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+ NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) = 0;
+
+ /* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+ NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) = 0;
+
+ /* void CompareStringArrays ([array, size_is (count)] in string arr1, [array, size_is (count)] in string arr2, in unsigned long count, [retval] out short result); */
+ NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) = 0;
+
+ /* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */
+ NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) = 0;
+
+ /* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */
+ NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) = 0;
+
+ /* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */
+ NS_IMETHOD DoubleString(PRUint32 *count, char **str) = 0;
+
+ /* void DoubleString2 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count)] out string out_str); */
+ NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) = 0;
+
+ /* void DoubleString3 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count), retval] out string out_str); */
+ NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) = 0;
+
+ /* void DoubleString4 ([size_is (count)] in string in_str, inout PRUint32 count, [size_is (count)] out string out_str); */
+ NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) = 0;
+
+ /* void UpString (in PRUint32 count, [size_is (count)] inout string str); */
+ NS_IMETHOD UpString(PRUint32 count, char **str) = 0;
+
+ /* void UpString2 (in PRUint32 count, [size_is (count)] in string in_str, [size_is (count)] out string out_str); */
+ NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) = 0;
+
+ /* void CopyUTF8String (in AUTF8String in_str, out AUTF8String out_str); */
+ NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) = 0;
+
+ /* void CopyUTF8String2 (in AUTF8String in_str, out AUTF8String out_str); */
+ NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) = 0;
+
+ /* void GetFixedString (in PRUint32 count, [size_is (count)] out string out_str); */
+ NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) = 0;
+
+ /* void DoubleWideString (inout PRUint32 count, [size_is (count)] inout wstring str); */
+ NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) = 0;
+
+ /* void DoubleWideString2 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count)] out wstring out_str); */
+ NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) = 0;
+
+ /* void DoubleWideString3 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count), retval] out wstring out_str); */
+ NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) = 0;
+
+ /* void DoubleWideString4 ([size_is (count)] in wstring in_str, inout PRUint32 count, [size_is (count)] out wstring out_str); */
+ NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) = 0;
+
+ /* void UpWideString (in PRUint32 count, [size_is (count)] inout wstring str); */
+ NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) = 0;
+
+ /* void UpWideString2 (in PRUint32 count, [size_is (count)] in wstring in_str, [size_is (count)] out wstring out_str); */
+ NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) = 0;
+
+ /* void GetFixedWideString (in PRUint32 count, [size_is (count)] out string out_str); */
+ NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) = 0;
+
+ /* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */
+ NS_IMETHOD GetStrings(PRUint32 *count, char ***str) = 0;
+
+ /* void UpOctetArray (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+ NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) = 0;
+
+ /* void UpOctetArray2 (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+ NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) = 0;
+
+ /* void CheckInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [retval] out PRBool all_non_null); */
+ NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) = 0;
+
+ /* void CopyInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [array, size_is (out_count)] out nsISupports out_data, out PRUint32 out_count); */
+ NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) = 0;
+
+ /* void GetInterfaceArray (out PRUint32 count, [array, size_is (count)] out nsISupports data); */
+ NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) = 0;
+
+ /* void ExtendInterfaceArray (inout PRUint32 count, [array, size_is (count)] inout nsISupports data); */
+ NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) = 0;
+
+ /* void CheckIIDArray (in PRUint32 count, [array, size_is (count)] in nsIIDRef data, [retval] out PRBool all_mine); */
+ NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) = 0;
+
+ /* void GetIIDArray (out PRUint32 count, [array, size_is (count)] out nsIIDRef data); */
+ NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) = 0;
+
+ /* void ExtendIIDArray (inout PRUint32 count, [array, size_is (count)] inout nsIIDRef data); */
+ NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) = 0;
+
+ /* void SumArrays (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] in PRInt32 array2, [retval] out PRInt32 result); */
+ NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) = 0;
+
+ /* void GetArrays (out PRUint32 count, [array, size_is (count)] out PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+ NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) = 0;
+
+ /* void GetFixedArray (in PRUint32 count, [array, size_is (count)] out PRInt32 array1); */
+ NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) = 0;
+
+ /* void CopyArray (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+ NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) = 0;
+
+ /* void CopyAndDoubleArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+ NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) = 0;
+
+ /* void AppendArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] inout PRInt32 array2); */
+ NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) = 0;
+
+ /* void AppendVariant (in nsIVariant variant, inout nsIVariant result); */
+ NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) = 0;
+
+ /* nsIVariant CopyVariant (in nsIVariant variant); */
+ NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) = 0;
+
+ /* nsIVariant SumVariants (in PRUint32 incount, [array, size_is (incount)] in nsIVariant variants); */
+ NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIPYTHONTESTINTERFACEEXTRA \
+ NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray); \
+ NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray); \
+ NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result); \
+ NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray); \
+ NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray); \
+ NS_IMETHOD DoubleString(PRUint32 *count, char **str); \
+ NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str); \
+ NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str); \
+ NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str); \
+ NS_IMETHOD UpString(PRUint32 count, char **str); \
+ NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str); \
+ NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str); \
+ NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str); \
+ NS_IMETHOD GetFixedString(PRUint32 count, char **out_str); \
+ NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str); \
+ NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str); \
+ NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str); \
+ NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str); \
+ NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str); \
+ NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str); \
+ NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str); \
+ NS_IMETHOD GetStrings(PRUint32 *count, char ***str); \
+ NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data); \
+ NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data); \
+ NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null); \
+ NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count); \
+ NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data); \
+ NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data); \
+ NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine); \
+ NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data); \
+ NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data); \
+ NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result); \
+ NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2); \
+ NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1); \
+ NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2); \
+ NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2); \
+ NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2); \
+ NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result); \
+ NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval); \
+ NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval);
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIPYTHONTESTINTERFACEEXTRA(_to) \
+ NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { return _to MultiplyEachItemInIntegerArray(val, count, valueArray); } \
+ NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { return _to MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); } \
+ NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) { return _to CompareStringArrays(arr1, arr2, count, result); } \
+ NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) { return _to DoubleStringArray(count, valueArray); } \
+ NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) { return _to ReverseStringArray(count, valueArray); } \
+ NS_IMETHOD DoubleString(PRUint32 *count, char **str) { return _to DoubleString(count, str); } \
+ NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return _to DoubleString2(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return _to DoubleString3(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) { return _to DoubleString4(in_str, count, out_str); } \
+ NS_IMETHOD UpString(PRUint32 count, char **str) { return _to UpString(count, str); } \
+ NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) { return _to UpString2(count, in_str, out_str); } \
+ NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) { return _to CopyUTF8String(in_str, out_str); } \
+ NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) { return _to CopyUTF8String2(in_str, out_str); } \
+ NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) { return _to GetFixedString(count, out_str); } \
+ NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) { return _to DoubleWideString(count, str); } \
+ NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return _to DoubleWideString2(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return _to DoubleWideString3(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) { return _to DoubleWideString4(in_str, count, out_str); } \
+ NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) { return _to UpWideString(count, str); } \
+ NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) { return _to UpWideString2(count, in_str, out_str); } \
+ NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) { return _to GetFixedWideString(count, out_str); } \
+ NS_IMETHOD GetStrings(PRUint32 *count, char ***str) { return _to GetStrings(count, str); } \
+ NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) { return _to UpOctetArray(count, data); } \
+ NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) { return _to UpOctetArray2(count, data); } \
+ NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) { return _to CheckInterfaceArray(count, data, all_non_null); } \
+ NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) { return _to CopyInterfaceArray(count, data, out_data, out_count); } \
+ NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) { return _to GetInterfaceArray(count, data); } \
+ NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) { return _to ExtendInterfaceArray(count, data); } \
+ NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) { return _to CheckIIDArray(count, data, all_mine); } \
+ NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) { return _to GetIIDArray(count, data); } \
+ NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) { return _to ExtendIIDArray(count, data); } \
+ NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) { return _to SumArrays(count, array1, array2, result); } \
+ NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) { return _to GetArrays(count, array1, array2); } \
+ NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) { return _to GetFixedArray(count, array1); } \
+ NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) { return _to CopyArray(count, array1, array2); } \
+ NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return _to CopyAndDoubleArray(count, array1, array2); } \
+ NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return _to AppendArray(count, array1, array2); } \
+ NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) { return _to AppendVariant(variant, result); } \
+ NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) { return _to CopyVariant(variant, _retval); } \
+ NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) { return _to SumVariants(incount, variants, _retval); }
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACEEXTRA(_to) \
+ NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->MultiplyEachItemInIntegerArray(val, count, valueArray); } \
+ NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); } \
+ NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->CompareStringArrays(arr1, arr2, count, result); } \
+ NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleStringArray(count, valueArray); } \
+ NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->ReverseStringArray(count, valueArray); } \
+ NS_IMETHOD DoubleString(PRUint32 *count, char **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString(count, str); } \
+ NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString2(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString3(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString4(in_str, count, out_str); } \
+ NS_IMETHOD UpString(PRUint32 count, char **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpString(count, str); } \
+ NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpString2(count, in_str, out_str); } \
+ NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyUTF8String(in_str, out_str); } \
+ NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyUTF8String2(in_str, out_str); } \
+ NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedString(count, out_str); } \
+ NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString(count, str); } \
+ NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString2(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString3(in_count, in_str, out_count, out_str); } \
+ NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString4(in_str, count, out_str); } \
+ NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpWideString(count, str); } \
+ NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpWideString2(count, in_str, out_str); } \
+ NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedWideString(count, out_str); } \
+ NS_IMETHOD GetStrings(PRUint32 *count, char ***str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetStrings(count, str); } \
+ NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpOctetArray(count, data); } \
+ NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpOctetArray2(count, data); } \
+ NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) { return !_to ? NS_ERROR_NULL_POINTER : _to->CheckInterfaceArray(count, data, all_non_null); } \
+ NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyInterfaceArray(count, data, out_data, out_count); } \
+ NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetInterfaceArray(count, data); } \
+ NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) { return !_to ? NS_ERROR_NULL_POINTER : _to->ExtendInterfaceArray(count, data); } \
+ NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) { return !_to ? NS_ERROR_NULL_POINTER : _to->CheckIIDArray(count, data, all_mine); } \
+ NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIIDArray(count, data); } \
+ NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->ExtendIIDArray(count, data); } \
+ NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->SumArrays(count, array1, array2, result); } \
+ NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetArrays(count, array1, array2); } \
+ NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedArray(count, array1); } \
+ NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyArray(count, array1, array2); } \
+ NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyAndDoubleArray(count, array1, array2); } \
+ NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->AppendArray(count, array1, array2); } \
+ NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) { return !_to ? NS_ERROR_NULL_POINTER : _to->AppendVariant(variant, result); } \
+ NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyVariant(variant, _retval); } \
+ NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->SumVariants(incount, variants, _retval); }
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsPythonTestInterfaceExtra : public nsIPythonTestInterfaceExtra
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPYTHONTESTINTERFACEEXTRA
+
+ nsPythonTestInterfaceExtra();
+
+private:
+ ~nsPythonTestInterfaceExtra();
+
+protected:
+ /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsPythonTestInterfaceExtra, nsIPythonTestInterfaceExtra)
+
+nsPythonTestInterfaceExtra::nsPythonTestInterfaceExtra()
+{
+ /* member initializers and constructor code */
+}
+
+nsPythonTestInterfaceExtra::~nsPythonTestInterfaceExtra()
+{
+ /* destructor code */
+}
+
+/* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CompareStringArrays ([array, size_is (count)] in string arr1, [array, size_is (count)] in string arr2, in unsigned long count, [retval] out short result); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleStringArray(PRUint32 *count, char ***valueArray)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::ReverseStringArray(PRUint32 count, char ***valueArray)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString(PRUint32 *count, char **str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString2 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString3 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count), retval] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleString4 ([size_is (count)] in string in_str, inout PRUint32 count, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString4(const char *in_str, PRUint32 *count, char **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpString (in PRUint32 count, [size_is (count)] inout string str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpString(PRUint32 count, char **str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpString2 (in PRUint32 count, [size_is (count)] in string in_str, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpString2(PRUint32 count, const char *in_str, char **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyUTF8String (in AUTF8String in_str, out AUTF8String out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyUTF8String(const nsACString & in_str, nsACString & out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyUTF8String2 (in AUTF8String in_str, out AUTF8String out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyUTF8String2(const nsACString & in_str, nsACString & out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetFixedString (in PRUint32 count, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedString(PRUint32 count, char **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString (inout PRUint32 count, [size_is (count)] inout wstring str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString(PRUint32 *count, PRUnichar **str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString2 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count)] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString3 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count), retval] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void DoubleWideString4 ([size_is (count)] in wstring in_str, inout PRUint32 count, [size_is (count)] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpWideString (in PRUint32 count, [size_is (count)] inout wstring str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpWideString(PRUint32 count, PRUnichar **str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpWideString2 (in PRUint32 count, [size_is (count)] in wstring in_str, [size_is (count)] out wstring out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetFixedWideString (in PRUint32 count, [size_is (count)] out string out_str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedWideString(PRUint32 count, char **out_str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetStrings(PRUint32 *count, char ***str)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpOctetArray (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpOctetArray(PRUint32 *count, PRUint8 **data)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void UpOctetArray2 (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::UpOctetArray2(PRUint32 *count, PRUint8 **data)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CheckInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [retval] out PRBool all_non_null); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [array, size_is (out_count)] out nsISupports out_data, out PRUint32 out_count); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetInterfaceArray (out PRUint32 count, [array, size_is (count)] out nsISupports data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetInterfaceArray(PRUint32 *count, nsISupports ***data)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ExtendInterfaceArray (inout PRUint32 count, [array, size_is (count)] inout nsISupports data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::ExtendInterfaceArray(PRUint32 *count, nsISupports ***data)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CheckIIDArray (in PRUint32 count, [array, size_is (count)] in nsIIDRef data, [retval] out PRBool all_mine); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetIIDArray (out PRUint32 count, [array, size_is (count)] out nsIIDRef data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetIIDArray(PRUint32 *count, nsIID & **data)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ExtendIIDArray (inout PRUint32 count, [array, size_is (count)] inout nsIIDRef data); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::ExtendIIDArray(PRUint32 *count, nsIID & **data)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void SumArrays (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] in PRInt32 array2, [retval] out PRInt32 result); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetArrays (out PRUint32 count, [array, size_is (count)] out PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetFixedArray (in PRUint32 count, [array, size_is (count)] out PRInt32 array1); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedArray(PRUint32 count, PRInt32 **array1)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyArray (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void CopyAndDoubleArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void AppendArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] inout PRInt32 array2); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void AppendVariant (in nsIVariant variant, inout nsIVariant result); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::AppendVariant(nsIVariant *variant, nsIVariant **result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIVariant CopyVariant (in nsIVariant variant); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyVariant(nsIVariant *variant, nsIVariant **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIVariant SumVariants (in PRUint32 incount, [array, size_is (incount)] in nsIVariant variants); */
+NS_IMETHODIMP nsPythonTestInterfaceExtra::SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+/* starting interface: nsIPythonTestInterfaceDOMStrings */
+#define NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID_STR "657ae651-a973-4818-8c06-f4b948b3d758"
+
+#define NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID \
+ {0x657ae651, 0xa973, 0x4818, \
+ { 0x8c, 0x06, 0xf4, 0xb9, 0x48, 0xb3, 0xd7, 0x58 }}
+
+class NS_NO_VTABLE nsIPythonTestInterfaceDOMStrings : public nsIPythonTestInterfaceExtra {
+ public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID)
+
+ /* DOMString GetDOMStringResult (in PRInt32 length); */
+ NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) = 0;
+
+ /* void GetDOMStringOut (in PRInt32 length, [retval] out DOMString s); */
+ NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) = 0;
+
+ /* PRUint32 GetDOMStringLength (in DOMString s); */
+ NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) = 0;
+
+ /* PRUint32 GetDOMStringRefLength (in DOMStringRef s); */
+ NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) = 0;
+
+ /* PRUint32 GetDOMStringPtrLength (in DOMStringPtr s); */
+ NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) = 0;
+
+ /* void ConcatDOMStrings (in DOMString s1, in DOMString s2, out DOMString ret); */
+ NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) = 0;
+
+ /* attribute DOMString domstring_value; */
+ NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) = 0;
+ NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) = 0;
+
+ /* readonly attribute DOMString domstring_value_ro; */
+ NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) = 0;
+
+};
+
+/* Use this macro when declaring classes that implement this interface. */
+#define NS_DECL_NSIPYTHONTESTINTERFACEDOMSTRINGS \
+ NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval); \
+ NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s); \
+ NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval); \
+ NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval); \
+ NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval); \
+ NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret); \
+ NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value); \
+ NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value); \
+ NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro);
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object. */
+#define NS_FORWARD_NSIPYTHONTESTINTERFACEDOMSTRINGS(_to) \
+ NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) { return _to GetDOMStringResult(length, _retval); } \
+ NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) { return _to GetDOMStringOut(length, s); } \
+ NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) { return _to GetDOMStringLength(s, _retval); } \
+ NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) { return _to GetDOMStringRefLength(s, _retval); } \
+ NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) { return _to GetDOMStringPtrLength(s, _retval); } \
+ NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) { return _to ConcatDOMStrings(s1, s2, ret); } \
+ NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) { return _to GetDomstring_value(aDomstring_value); } \
+ NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) { return _to SetDomstring_value(aDomstring_value); } \
+ NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) { return _to GetDomstring_value_ro(aDomstring_value_ro); }
+
+/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
+#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACEDOMSTRINGS(_to) \
+ NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringResult(length, _retval); } \
+ NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringOut(length, s); } \
+ NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringLength(s, _retval); } \
+ NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringRefLength(s, _retval); } \
+ NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringPtrLength(s, _retval); } \
+ NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) { return !_to ? NS_ERROR_NULL_POINTER : _to->ConcatDOMStrings(s1, s2, ret); } \
+ NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDomstring_value(aDomstring_value); } \
+ NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetDomstring_value(aDomstring_value); } \
+ NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDomstring_value_ro(aDomstring_value_ro); }
+
+#if 0
+/* Use the code below as a template for the implementation class for this interface. */
+
+/* Header file */
+class nsPythonTestInterfaceDOMStrings : public nsIPythonTestInterfaceDOMStrings
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPYTHONTESTINTERFACEDOMSTRINGS
+
+ nsPythonTestInterfaceDOMStrings();
+
+private:
+ ~nsPythonTestInterfaceDOMStrings();
+
+protected:
+ /* additional members */
+};
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsPythonTestInterfaceDOMStrings, nsIPythonTestInterfaceDOMStrings)
+
+nsPythonTestInterfaceDOMStrings::nsPythonTestInterfaceDOMStrings()
+{
+ /* member initializers and constructor code */
+}
+
+nsPythonTestInterfaceDOMStrings::~nsPythonTestInterfaceDOMStrings()
+{
+ /* destructor code */
+}
+
+/* DOMString GetDOMStringResult (in PRInt32 length); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringResult(PRInt32 length, nsAString & _retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void GetDOMStringOut (in PRInt32 length, [retval] out DOMString s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringOut(PRInt32 length, nsAString & s)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 GetDOMStringLength (in DOMString s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringLength(const nsAString & s, PRUint32 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 GetDOMStringRefLength (in DOMStringRef s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 GetDOMStringPtrLength (in DOMStringPtr s); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void ConcatDOMStrings (in DOMString s1, in DOMString s2, out DOMString ret); */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute DOMString domstring_value; */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDomstring_value(nsAString & aDomstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::SetDomstring_value(const nsAString & aDomstring_value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute DOMString domstring_value_ro; */
+NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDomstring_value_ro(nsAString & aDomstring_value_ro)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* End of implementation class template. */
+#endif
+
+
+#endif /* __gen_py_test_component_h__ */
diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.html b/src/libs/xpcom18a4/python/test/test_component/py_test_component.html
new file mode 100644
index 00000000..1e17d24c
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_component/py_test_component.html
@@ -0,0 +1,182 @@
+<!-- ***** 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 PyXPCOM.
+ -
+ - The Initial Developer of the Original Code is
+ - ActiveState Tool Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 2000-2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. 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 ***** -->
+
+<center><b><font size=+2>Python Component Sample</font></b>
+
+<p>
+<br>
+Last modified
+<script>
+document.write(document.lastModified);
+</script>
+</center>
+
+<p>XPConnect allows JavaScript
+to transparantly access and manipulate XPCOM objects;
+
+<p>Big Deal, I hear you say! But it also works for Python!!!
+
+<p>
+This sample demonstrates accessing a XPCOM object through XPConnect.
+The JavaScript executed when this page loads creates an instance
+of the Python object by
+using the <tt>Components</tt> object, then accesses it through
+the <a href="py_test_component.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>:
+<br>
+<pre>
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["component://mozilla/sample/sample-world"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+</pre>
+
+<p>
+The buttons on the form are connected to JavaScript event handlers which
+call the methods defined in Python
+
+
+<p><b><a name="Compiling">Compiling the idl</b>
+
+<p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac)
+is compiled at build time (except on Mac) thus
+you will have to build mozilla in order to test this out. If you
+have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>.
+
+<p>Once you have the XPIDL compiler enter the following command at your
+prompt:
+<br><tt>D:\whereever\xpcom\test\test_component>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I
+d:\mozilla\dist\idl -m typelib py_test_component.idl</tt>. You must then copy the generated .xpt file
+to the mozilla component directory.
+
+<p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder
+containing the other idl files, needed because nsISample.idl inherits from
+nsISupports.idl. The <tt>-m typelib</tt> instruction tells the compiler
+to build the .XPT typelib file.</tt>.
+
+<p>
+For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl
+compiler page</a>.
+
+<p><b>Running the sample</b>
+<p><b>NOTE: This doesnt work for me - I get an access denied error using XPConnect!</b>
+<p>Using Mozilla, load this file. Pay attention
+to the console when clicking "write".
+
+<!-- XXX keep in sync with stuff in pre tag below -->
+<script>
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["Python.TestComponent"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+ var field = document.getElementById('Value');
+ field.value = sample.str_value;
+}
+
+function set()
+{
+ var field = document.getElementById('Value');
+ sample.str_value = field.value;
+}
+
+function poke()
+{
+ var field = document.getElementById('Value');
+ sample.poke(field.value);
+}
+
+function write()
+{
+ sample.writeValue("here is what I'm writing: ");
+}
+</script>
+
+<p>
+<form name="form">
+<input type="button" value="Get" onclick="get();">
+<input type="button" value="Set" onclick="set();">
+<input type="button" value="Poke" onclick="poke();">
+<input type="text" id="Value">
+<input type="button" value="Write" onclick="write();">
+<form>
+
+<hr>
+
+<p>
+JavaScript and form source:
+
+<!-- XXX keep in sync with actual script -->
+<pre>
+&lt;script&gt;
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["component://Python.TestComponent"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+ var field = document.getElementById('Value');
+ field.value = sample.str_value;
+}
+
+function set()
+{
+ var field = document.getElementById('Value');
+ sample.str_value = field.value;
+}
+
+function poke()
+{
+ var field = document.getElementById('Value');
+ sample.poke(field.value);
+}
+
+function write()
+{
+ sample.writeValue("here is what I'm writing: ");
+}
+&lt;/script&gt;
+
+&lt;form name=&quot;form&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Get&quot; onclick=&quot;get();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Set&quot; onclick=&quot;set();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Poke&quot; onclick=&quot;poke();&quot;&gt;
+&lt;input type=&quot;text&quot; id=&quot;Value&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Write&quot; onclick=&quot;write();&quot;&gt;
+&lt;form>
+
+</pre>
diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl b/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl
new file mode 100644
index 00000000..cd3e1c45
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl
@@ -0,0 +1,231 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+// NOTE: This is a TEST interface, not a DEMO interface :-)
+// We try to get as many data-types etc exposed, meaning this
+// doesnt really make a good demo of a "simple component"
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+
+[scriptable, uuid(1ECAED4F-E4D5-4ee7-ABF0-7D72AE1441D7)]
+interface nsIPythonTestInterface : nsISupports
+{
+ // Some constants for us to test - one for every type supported by xpidl
+ const short One = 1;
+ const long Two = 2;
+ const long MinusOne = -1;
+ const long BigLong = 0x7FFFFFFF;
+ const long BiggerLong = 0xFFFFFFFF;
+ const unsigned long BigULong = 0xFFFFFFFF;
+
+ // Declare every type supported as an attribute.
+ attribute boolean boolean_value; // PRBool
+ attribute octet octet_value; // PRUint8
+ attribute short short_value; // PRInt16
+ attribute unsigned short ushort_value; // PRUint16
+ attribute long long_value; // PRInt32
+ attribute unsigned long ulong_value; // PRUint32
+ attribute long long long_long_value; // PRInt64
+ attribute unsigned long long ulong_long_value; // PRUint64
+ attribute float float_value; // float
+ attribute double double_value; // double
+ attribute char char_value; // char
+ attribute wchar wchar_value; // PRUnichar
+ attribute string string_value; // char *
+ attribute wstring wstring_value; // PRUnichar*
+ attribute AString astring_value; // nsAString &
+ attribute ACString acstring_value; // nsACString &
+ attribute AUTF8String utf8string_value; // nsAUTF8String &
+ attribute nsIIDRef iid_value; // an IID
+ attribute nsIPythonTestInterface interface_value; // A specific interface
+ attribute nsISupports isupports_value; // A generic interface
+
+ // Declare every type supported as a method with an "in", "in/out" and "out" params
+ boolean do_boolean(in boolean p1, inout boolean p2, out boolean p3);
+ octet do_octet(in octet p1, inout octet p2, out octet p3);
+ short do_short(in short p1, inout short p2, out short p3);
+ unsigned short do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3);
+ long do_long(in long p1, inout long p2, out long p3);
+ unsigned long do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3);
+ long long do_long_long(in long long p1, inout long long p2, out long long p3);
+ unsigned long long do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3);
+ float do_float(in float p1, inout float p2, out float p3);
+ double do_double(in double p1, inout double p2, out double p3);
+ char do_char(in char p1, inout char p2, out char p3);
+ wchar do_wchar(in wchar p1, inout wchar p2, out wchar p3);
+ string do_string(in string p1, inout string p2, out string p3);
+ wstring do_wstring(in wstring p1, inout wstring p2, out wstring p3);
+ nsIIDRef do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3);
+ nsIPythonTestInterface do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3);
+ nsISupports do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3);
+ void do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result);
+// Do I really need these??
+// void do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
+// void do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
+// void do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result);
+};
+
+// Another interface - we use another interface purely for testing purposes -
+// We ensure that the entire interface hierarcy is available correctly.
+[scriptable, uuid(B38D1538-FE92-42c3-831F-285242EDEEA4)]
+interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface
+{
+ // These were copied from the XPCOM test 'xpctest.idl'
+ // (and a few extras added)
+ void MultiplyEachItemInIntegerArray(
+ in PRInt32 val,
+ in PRUint32 count,
+ [array, size_is(count)] inout PRInt32 valueArray);
+ void MultiplyEachItemInIntegerArrayAndAppend(
+ in PRInt32 val,
+ inout PRUint32 count,
+ [array, size_is(count)] inout PRInt32 valueArray);
+
+ // Note that this method shares a single "size_is" between 2 params!
+ void CompareStringArrays([array, size_is(count)] in string arr1,
+ [array, size_is(count)] in string arr2,
+ in unsigned long count,
+ [retval] out short result);
+
+ void DoubleStringArray(inout PRUint32 count,
+ [array, size_is(count)] inout string valueArray);
+ void ReverseStringArray(in PRUint32 count,
+ [array, size_is(count)] inout string valueArray);
+
+ // One count, one inout array.
+ void DoubleString(inout PRUint32 count,
+ [size_is(count)] inout string str);
+ // One in count and in array, plus out count and out array
+ void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+ out PRUint32 out_count, [size_is(out_count)] out string out_str);
+ // As per DoubleString2, but out string also marked retval
+ void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+ out PRUint32 out_count, [size_is(out_count), retval] out string out_str);
+ // One in array, one out array, one share inout count.
+ void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str);
+ // UpString defines the count as only "in" - meaning the result must be the same size
+ void UpString(in PRUint32 count,
+ [size_is(count)] inout string str);
+ // UpString2 defines count as only "in", and a string as only "out"
+ void UpString2(in PRUint32 count,
+ [size_is(count)] in string in_str,
+ [size_is(count)]out string out_str);
+ void CopyUTF8String(in AUTF8String in_str, out AUTF8String out_str);
+ void CopyUTF8String2(in AUTF8String in_str, out AUTF8String out_str);
+ // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+ void GetFixedString(in PRUint32 count, [size_is(count)]out string out_str);
+
+ void DoubleWideString(inout PRUint32 count,
+ [size_is(count)] inout wstring str);
+ void DoubleWideString2(in PRUint32 in_count, [size_is(in_count)] in wstring in_str,
+ out PRUint32 out_count, [size_is(out_count)] out wstring out_str);
+ void DoubleWideString3(in PRUint32 in_count, [size_is(in_count)] in wstring in_str,
+ out PRUint32 out_count, [size_is(out_count), retval] out wstring out_str);
+ void DoubleWideString4([size_is(count)] in wstring in_str, inout PRUint32 count, [size_is(count)] out wstring out_str);
+ // UpWideString defines the count as only "in" - meaning the result must be the same size
+ void UpWideString(in PRUint32 count,
+ [size_is(count)] inout wstring str);
+ // UpWideString2 defines count as only "in", and a string as only "out"
+ void UpWideString2(in PRUint32 count,
+ [size_is(count)] in wstring in_str,
+ [size_is(count)]out wstring out_str);
+ // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+ void GetFixedWideString(in PRUint32 count, [size_is(count)]out string out_str);
+
+ void GetStrings(out PRUint32 count,
+ [retval, array, size_is(count)] out string str);
+
+ void UpOctetArray(inout PRUint32 count,
+ [array, size_is(count)] inout PRUint8 data);
+
+ void UpOctetArray2(inout PRUint32 count,
+ [array, size_is(count)] inout PRUint8 data);
+
+ // Arrays of interfaces
+ void CheckInterfaceArray(in PRUint32 count,
+ [array, size_is(count)] in nsISupports data,
+ [retval] out PRBool all_non_null);
+ void CopyInterfaceArray(in PRUint32 count,
+ [array, size_is(count)] in nsISupports data,
+ [array, size_is(out_count)] out nsISupports out_data,
+ out PRUint32 out_count);
+ void GetInterfaceArray(out PRUint32 count,
+ [array, size_is(count)] out nsISupports data);
+ void ExtendInterfaceArray(inout PRUint32 count,
+ [array, size_is(count)] inout nsISupports data);
+
+ // Arrays of IIDs
+ void CheckIIDArray(in PRUint32 count,
+ [array, size_is(count)] in nsIIDRef data,
+ [retval] out PRBool all_mine);
+ void GetIIDArray(out PRUint32 count,
+ [array, size_is(count)] out nsIIDRef data);
+ void ExtendIIDArray(inout PRUint32 count,
+ [array, size_is(count)] inout nsIIDRef data);
+
+ // More specific tests.
+ // Test our count param can be shared as an "in" param.
+ void SumArrays(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]in PRInt32 array2, [retval]out PRInt32 result);
+ // Test our count param can be shared as an "out" param.
+ void GetArrays(out PRUint32 count, [array, size_is(count)]out PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
+ // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+ void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1);
+ // Test our "in" count param can be shared as one "in", plus one "out" param.
+ void CopyArray(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
+ // Test our "in-out" count param can be shared as one "in", plus one "out" param.
+ void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2);
+ // Test our "in-out" count param can be shared as one "in", plus one "in-out" param.
+ void AppendArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]inout PRInt32 array2);
+ void AppendVariant(in nsIVariant variant, inout nsIVariant result);
+ nsIVariant CopyVariant(in nsIVariant variant);
+ nsIVariant SumVariants(in PRUint32 incount, [array, size_is(incount)]in nsIVariant variants);
+};
+
+// DOM String support is a "recent" (01/2001) addition to XPCOM. These test
+// have their own interface for no real good reason ;-)
+[scriptable, uuid(657ae651-a973-4818-8c06-f4b948b3d758)]
+interface nsIPythonTestInterfaceDOMStrings : nsIPythonTestInterfaceExtra
+{
+ DOMString GetDOMStringResult(in PRInt32 length);
+ void GetDOMStringOut(in PRInt32 length, [retval] out DOMString s);
+ PRUint32 GetDOMStringLength(in DOMString s);
+ PRUint32 GetDOMStringRefLength(in DOMStringRef s);
+ PRUint32 GetDOMStringPtrLength(in DOMStringPtr s);
+ void ConcatDOMStrings(in DOMString s1, in DOMString s2, out DOMString ret);
+ attribute DOMString domstring_value;
+ readonly attribute DOMString domstring_value_ro;
+};
diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.py b/src/libs/xpcom18a4/python/test/test_component/py_test_component.py
new file mode 100755
index 00000000..c0373de9
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_component/py_test_component.py
@@ -0,0 +1,421 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+# NOTE: This is a TEST interface, not a DEMO interface :-)
+# We try to get as many data-types etc exposed, meaning this
+# doesnt really make a good demo of a "simple component"
+
+
+from xpcom import components, verbose
+
+class PythonTestComponent:
+ # Note we only list the "child" interface, not our intermediate interfaces
+ # (which we must, by definition, also support)
+ _com_interfaces_ = components.interfaces.nsIPythonTestInterfaceDOMStrings
+ _reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}"
+ _reg_contractid_ = "Python.TestComponent"
+ def __init__(self):
+ self.boolean_value = 1
+ self.octet_value = 2
+ self.short_value = 3
+ self.ushort_value = 4
+ self.long_value = 5
+ self.ulong_value = 6
+ self.long_long_value = 7
+ self.ulong_long_value = 8
+ self.float_value = 9.0
+ self.double_value = 10.0
+ self.char_value = "a"
+ self.wchar_value = "b"
+ self.string_value = "cee"
+ self.wstring_value = "dee"
+ self.astring_value = "astring"
+ self.acstring_value = "acstring"
+ self.utf8string_value = "utf8string"
+ self.iid_value = self._reg_clsid_
+ self.interface_value = None
+ self.isupports_value = None
+ self.domstring_value = "dom"
+
+ def __del__(self):
+ if verbose:
+ print "Python.TestComponent: __del__ method called - object is destructing"
+
+ def do_boolean(self, p1, p2):
+ # boolean do_boolean(in boolean p1, inout boolean p2, out boolean p3);
+ ret = p1 ^ p2
+ return ret, not ret, ret
+
+ def do_octet(self, p1, p2):
+ # octet do_octet(in octet p1, inout octet p2, out octet p3);
+ return p1+p2, p1-p2, p1*p2
+
+ def do_short(self, p1, p2):
+ # short do_short(in short p1, inout short p2, out short p3);
+ return p1+p2, p1-p2, p1*p2
+
+ def do_unsigned_short(self, p1, p2):
+ # unsigned short do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3);
+ return p1+p2, p1-p2, p1*p2
+ def do_long(self, p1, p2):
+ # long do_long(in long p1, inout long p2, out long p3);
+ return p1+p2, p1-p2, p1*p2
+
+ def do_unsigned_long(self, p1, p2):
+ # unsigned long do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3);
+ return p1+p2, p1-p2, p1*p2
+ def do_long_long(self, p1, p2):
+ # long long do_long_long(in long long p1, inout long long p2, out long long p3);
+ return p1+p2, p1-p2, p1*p2
+ def do_unsigned_long_long(self, p1, p2):
+ # unsigned long long do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3);
+ return p1+p2, p1-p2, p1*p2
+ def do_float(self, p1, p2):
+ # float do_float(in float p1, inout float p2, out float p3);
+ return p1+p2, p1-p2, p1*p2
+ def do_double(self, p1, p2):
+ # double do_double(in double p1, inout double p2, out double p3);
+ return p1+p2, p1-p2, p1*p2
+ def do_char(self, p1, p2):
+ # char do_char(in char p1, inout char p2, out char p3);
+ return chr(ord(p1)+ord(p2)), p2, p1
+ def do_wchar(self, p1, p2):
+ # wchar do_wchar(in wchar p1, inout wchar p2, out wchar p3);
+ return chr(ord(p1)+ord(p2)), p2, p1
+ def do_string(self, p1, p2):
+ # string do_string(in string p1, inout string p2, out string p3);
+ ret = ""
+ if p1 is not None: ret = ret + p1
+ if p2 is not None: ret = ret + p2
+ return ret, p1, p2
+ def do_wstring(self, p1, p2):
+ # wstring do_wstring(in wstring p1, inout wstring p2, out wstring p3);
+ ret = u""
+ if p1 is not None: ret = ret + p1
+ if p2 is not None: ret = ret + p2
+ return ret, p1, p2
+ def do_nsIIDRef(self, p1, p2):
+ # nsIIDRef do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3);
+ return p1, self._reg_clsid_, p2
+ def do_nsIPythonTestInterface(self, p1, p2):
+ # nsIPythonTestInterface do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3);
+ return p2, p1, self
+ def do_nsISupports(self, p1, p2):
+ # nsISupports do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3);
+ return self, p1, p2
+ def do_nsISupportsIs(self, iid):
+ # void do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result)
+ # Note the framework does the QI etc on us, so there is no real point me doing it.
+ # (However, user code _should_ do the QI - otherwise any errors are deemed "internal" (as they
+ # are raised by the C++ framework), and therefore logged to the console, etc.
+ # A user QI allows the user to fail gracefully, whatever gracefully means for them!
+ return self
+# Do I really need these??
+## def do_nsISupportsIs2(self, iid, interface):
+## # void do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid),retval] inout nsQIResult result);
+## return iid, interface
+## def do_nsISupportsIs3(self, interface):
+## # void do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result);
+## return self._com_interfaces_, interface
+## def do_nsISupportsIs4(self):
+## # void do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result);
+## return self._com_interfaces_, self
+
+ # Methods from the nsIPythonTestInterfaceExtra interface
+ #
+ def MultiplyEachItemInIntegerArray(self, val, valueArray):
+ # void MultiplyEachItemInIntegerArray(
+ # in PRInt32 val,
+ # in PRUint32 count,
+ # [array, size_is(count)] inout PRInt32 valueArray);
+ # NOTE - the "sizeis" params are never passed to or returned from Python!
+ results = []
+ for item in valueArray:
+ results.append(item * val)
+ return results
+ def MultiplyEachItemInIntegerArrayAndAppend(self, val, valueArray):
+ #void MultiplyEachItemInIntegerArrayAndAppend(
+ # in PRInt32 val,
+ # inout PRUint32 count,
+ # [array, size_is(count)] inout PRInt32 valueArray);
+ results = valueArray[:]
+ for item in valueArray:
+ results.append(item * val)
+ return results
+ def DoubleStringArray(self, valueArray):
+ # void DoubleStringArray(inout PRUint32 count,
+ # [array, size_is(count)] inout string valueArray);
+ results = []
+ for item in valueArray:
+ results.append(item * 2)
+ return results
+
+ def ReverseStringArray(self, valueArray):
+ # void ReverseStringArray(in PRUint32 count,
+ # [array, size_is(count)] inout string valueArray);
+ valueArray.reverse()
+ return valueArray
+
+ # Note that this method shares a single "size_is" between 2 params!
+ def CompareStringArrays(self, ar1, ar2):
+ # void CompareStringArrays([array, size_is(count)] in string arr1,
+ # [array, size_is(count)] in string arr2,
+ # in unsigned long count,
+ # [retval] out short result);
+ return cmp(ar1, ar2)
+
+ def DoubleString(self, val):
+ # void DoubleString(inout PRUint32 count,
+ # [size_is(count)] inout string str);
+ return val * 2
+ def DoubleString2(self, val):
+ # void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+ # out PRUint32 out_count, [size_is(out_count)] out string out_str);
+ return val * 2
+ def DoubleString3(self, val):
+ # void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str,
+ # out PRUint32 out_count, [size_is(out_count), retval] string out_str);
+ return val * 2
+ def DoubleString4(self, val):
+ # void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str);
+ return val * 2
+ def UpString(self, val):
+ # // UpString defines the count as only "in" - meaning the result must be the same size
+ # void UpString(in PRUint32 count,
+ # [size_is(count)] inout string str);
+ return val.upper()
+ UpString2 = UpString
+ # // UpString2 defines count as only "in", and a string as only "out"
+ # void UpString2(in PRUint32 count,
+ # [size_is(count)] inout string in_str,
+ # [size_is(count)]out string out_str);
+
+ def GetFixedString(self, count):
+ # void GetFixedString(in PRUint32 count, [size_is(count)out string out_str);
+ return "A" * count
+
+ # DoubleWideString functions are identical to DoubleString, except use wide chars!
+ def DoubleWideString(self, val):
+ return val * 2
+ def DoubleWideString2(self, val):
+ return val * 2
+ def DoubleWideString3(self, val):
+ return val * 2
+ def DoubleWideString4(self, val):
+ return val * 2
+ def UpWideString(self, val):
+ return val.upper()
+ UpWideString2 = UpWideString
+ def CopyUTF8String(self, v):
+ return v
+ def CopyUTF8String2(self, v):
+ return v.encode("utf8")
+ # Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!)
+ def GetFixedWideString(self, count):
+ # void GetFixedWideString(in PRUint32 count, [size_is(count)out string out_str);
+ return u"A" * count
+
+ def GetStrings(self):
+ # void GetStrings(out PRUint32 count,
+ # [retval, array, size_is(count)] out string str);
+ return "Hello from the Python test component".split()
+ # Some tests for our special "PRUint8" support.
+ def UpOctetArray( self, data ):
+ # void UpOctetArray(inout PRUint32 count,
+ # [array, size_is(count)] inout PRUint8 data);
+ return data.upper()
+
+ def UpOctetArray2( self, data ):
+ # void UpOctetArray2(inout PRUint32 count,
+ # [array, size_is(count)] inout PRUint8 data);
+ data = data.upper()
+ # This time we return a list of integers.
+ return map( ord, data )
+
+ # Arrays of interfaces
+ def CheckInterfaceArray(self, interfaces):
+ # void CheckInterfaceArray(in PRUint32 count,
+ # [array, size_is(count)] in nsISupports data,
+ # [retval] out PRBool all_non_null);
+ ret = 1
+ for i in interfaces:
+ if i is None:
+ ret = 0
+ break
+ return ret
+ def CopyInterfaceArray(self, a):
+ return a
+ def GetInterfaceArray(self):
+ # void GetInterfaceArray(out PRUint32 count,
+ # [array, size_is(count)] out nsISupports data);
+ return self, self, self, None
+ def ExtendInterfaceArray(self, data):
+ # void ExtendInterfaceArray(inout PRUint32 count,
+ # [array, size_is(count)] inout nsISupports data);
+ return data * 2
+
+ # Arrays of IIDs
+ def CheckIIDArray(self, data):
+ # void CheckIIDArray(in PRUint32 count,
+ # [array, size_is(count)] in nsIIDRef data,
+ # [retval] out PRBool all_mine);
+ ret = 1
+ for i in data:
+ if i!= self._com_interfaces_ and i != self._reg_clsid_:
+ ret = 0
+ break
+ return ret
+ def GetIIDArray(self):
+ # void GetIIDArray(out PRUint32 count,
+ # [array, size_is(count)] out nsIIDRef data);
+ return self._com_interfaces_, self._reg_clsid_
+ def ExtendIIDArray(self, data):
+ # void ExtendIIDArray(inout PRUint32 count,
+ # [array, size_is(count)] inout nsIIDRef data);
+ return data * 2
+
+ # Test our count param can be shared as an "in" param.
+ def SumArrays(self, array1, array2):
+ # void SumArrays(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]in array2, [retval]result);
+ if len(array1)!=len(array2):
+ print "SumArrays - not expecting different lengths!"
+ result = 0
+ for i in array1:
+ result = result + i
+ for i in array2:
+ result = result+i
+ return result
+
+ # Test our count param can be shared as an "out" param.
+ def GetArrays(self):
+ # void GetArrays(out PRUint32 count, [array, size_is(count)]out array1, [array, size_is(count)]out array2);
+ return (1,2,3), (4,5,6)
+ # Test we can get an "out" array with an "in" size
+ def GetFixedArray(self, size):
+ # void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1]);
+ return 0 * size
+
+ # Test our "in" count param can be shared as one "in", plus one "out" param.
+ def CopyArray(self, array1):
+ # void CopyArray(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2);
+ return array1
+ # Test our "in-out" count param can be shared as one "in", plus one "out" param.
+ def CopyAndDoubleArray(self, array):
+ # void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2);
+ return array + array
+ # Test our "in-out" count param can be shared as one "in", plus one "in-out" param.
+ def AppendArray(self, array1, array2):
+ # void AppendArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]inout array2);
+ rc = array1
+ if array2 is not None:
+ rc.extend(array2)
+ return rc
+ # Test nsIVariant support
+ def AppendVariant(self, invar, inresult):
+ if type(invar)==type([]):
+ invar_use = invar[0]
+ for v in invar[1:]:
+ invar_use += v
+ else:
+ invar_use = invar
+ if type(inresult)==type([]):
+ inresult_use = inresult[0]
+ for v in inresult[1:]:
+ inresult_use += v
+ else:
+ inresult_use = inresult
+ if inresult_use is None and invar_use is None:
+ return None
+ return inresult_use + invar_use
+
+ def CopyVariant(self, invar):
+ return invar
+
+ def SumVariants(self, variants):
+ if len(variants) == 0:
+ return None
+ result = variants[0]
+ for v in variants[1:]:
+ result += v
+ return result
+
+ # Some tests for the "new" (Feb-2001) DOMString type.
+ def GetDOMStringResult( self, length ):
+ # Result: DOMString &
+ if length == -1:
+ return None
+ return "P" * length
+ def GetDOMStringOut( self, length ):
+ # Result: DOMString &
+ if length == -1:
+ return None
+ return "y" * length
+ def GetDOMStringLength( self, param0 ):
+ # Result: uint32
+ # In: param0: DOMString &
+ if param0 is None: return -1
+ return len(param0)
+
+ def GetDOMStringRefLength( self, param0 ):
+ # Result: uint32
+ # In: param0: DOMString &
+ if param0 is None: return -1
+ return len(param0)
+
+ def GetDOMStringPtrLength( self, param0 ):
+ # Result: uint32
+ # In: param0: DOMString *
+ if param0 is None: return -1
+ return len(param0)
+
+ def ConcatDOMStrings( self, param0, param1 ):
+ # Result: void - None
+ # In: param0: DOMString &
+ # In: param1: DOMString &
+ # Out: DOMString &
+ return param0 + param1
+ def get_domstring_value( self ):
+ # Result: DOMString &
+ return self.domstring_value
+ def set_domstring_value( self, param0 ):
+ # Result: void - None
+ # In: param0: DOMString &
+ self.domstring_value = param0
+
+ def get_domstring_value_ro( self ):
+ # Result: DOMString &
+ return self.domstring_value
diff --git a/src/libs/xpcom18a4/python/test/test_components.py b/src/libs/xpcom18a4/python/test/test_components.py
new file mode 100755
index 00000000..80007722
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_components.py
@@ -0,0 +1,109 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <markh@activestate.com> (original author)
+#
+# 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 *****
+
+"""Tests the "xpcom.components" object.
+"""
+
+import xpcom.components
+from pyxpcom_test_tools import suite_from_functions, testmain
+
+if not __debug__:
+ raise RuntimeError, "This test uses assert, so must be run in debug mode"
+
+def test_interfaces():
+ "Test the xpcom.components.interfaces object"
+
+ iid = xpcom.components.interfaces.nsISupports
+ assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
+ iid = xpcom.components.interfaces['nsISupports']
+ assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
+
+ # Test dictionary semantics
+ num_fetched = num_nsisupports = 0
+ for name, iid in xpcom.components.interfaces.items():
+ num_fetched = num_fetched + 1
+ if name == "nsISupports":
+ num_nsisupports = num_nsisupports + 1
+ assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!"
+ assert xpcom.components.interfaces[name] == iid
+ # Check all the lengths match.
+ assert len(xpcom.components.interfaces.keys()) == len(xpcom.components.interfaces.values()) == \
+ len(xpcom.components.interfaces.items()) == len(xpcom.components.interfaces) == \
+ num_fetched, "The collection lengths were wrong"
+ assert num_nsisupports == 1, "Didnt find exactly 1 nsiSupports!"
+
+def test_classes():
+ # Need a well-known contractID here?
+ prog_id = "@mozilla.org/supports-array;1"
+ clsid = xpcom.components.ID("{bda17d50-0d6b-11d3-9331-00104ba0fd40}")
+
+ # Check we can create the instance (dont check we can do anything with it tho!)
+ klass = xpcom.components.classes[prog_id]
+ instance = klass.createInstance()
+
+ # Test dictionary semantics
+ num_fetched = num_mine = 0
+ for name, klass in xpcom.components.classes.items():
+ num_fetched = num_fetched + 1
+ if name == prog_id:
+ assert klass.clsid == clsid, "Eeek - didn't get the correct IID - got %s" %klass.clsid
+ num_mine = num_mine + 1
+
+# xpcom appears to add charset info to the contractid!?
+# assert xpcom.components.classes[name].contractid == prog_id, "Expected '%s', got '%s'" % (prog_id, xpcom.components.classes[name].contractid)
+ # Check all the lengths match.
+ if len(xpcom.components.classes.keys()) == len(xpcom.components.classes.values()) == \
+ len(xpcom.components.classes.items()) == len(xpcom.components.classes) == \
+ num_fetched:
+ pass
+ else:
+ raise RuntimeError, "The collection lengths were wrong"
+ if num_fetched <= 0:
+ raise RuntimeError, "Didnt get any classes!!!"
+ if num_mine != 1:
+ raise RuntimeError, "Didnt find exactly 1 of my contractid! (%d)" % (num_mine,)
+
+def test_id():
+ id = xpcom.components.ID(str(xpcom._xpcom.IID_nsISupports))
+ assert id == xpcom._xpcom.IID_nsISupports
+
+# Make this test run under our std test suite
+def suite():
+ return suite_from_functions(test_interfaces, test_classes, test_id)
+
+if __name__=='__main__':
+ testmain()
diff --git a/src/libs/xpcom18a4/python/test/test_isupports_primitives.py b/src/libs/xpcom18a4/python/test/test_isupports_primitives.py
new file mode 100755
index 00000000..3d0e7023
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_isupports_primitives.py
@@ -0,0 +1,207 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+# Test our support for the interfaces defined in nsISupportsPrimitives.idl
+#
+# The framework supports nsISupportsCString and nsISupportsString, but
+# only if our class doesnt provide explicit support.
+
+from xpcom import components
+from xpcom import primitives
+import xpcom.server, xpcom.client
+from pyxpcom_test_tools import testmain
+import unittest
+
+class NoSupportsString:
+ _com_interfaces_ = [components.interfaces.nsISupports]
+
+class ImplicitSupportsString:
+ _com_interfaces_ = [components.interfaces.nsISupports]
+ def __str__(self):
+ return "<MyImplicitStrObject>"
+
+class ExplicitSupportsString:
+ _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+ components.interfaces.nsISupportsCString]
+ type = components.interfaces.nsISupportsPrimitive.TYPE_CSTRING
+ test_data = "<MyExplicitStrObject>"
+ # __str__ will be ignored by XPCOM, as we have _explicit_ support.
+ def __str__(self):
+ return "<MyImplicitStrObject>"
+ # These are the ones that will be used.
+ def get_data(self):
+ return self.test_data
+ def toString(self):
+ return self.test_data
+
+class ImplicitSupportsUnicode:
+ _com_interfaces_ = [components.interfaces.nsISupports]
+ test_data = u"Copyright \xa9 the initial developer"
+ def __unicode__(self):
+ # An extended character in unicode tests can't hurt!
+ return self.test_data
+
+class ExplicitSupportsUnicode:
+ _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+ components.interfaces.nsISupportsString]
+ type = components.interfaces.nsISupportsPrimitive.TYPE_STRING
+ # __unicode__ will be ignored by XPCOM, as we have _explicit_ support.
+ test_data = u"Copyright \xa9 the initial developer"
+ def __unicode__(self):
+ return self.test_data
+ def get_data(self):
+ return self.test_data
+
+class ImplicitSupportsInt:
+ _com_interfaces_ = [components.interfaces.nsISupports]
+ def __int__(self):
+ return 99
+
+class ExplicitSupportsInt:
+ _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+ components.interfaces.nsISupportsPRInt32]
+ type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT32
+ def get_data(self):
+ return 99
+
+class ImplicitSupportsLong:
+ _com_interfaces_ = [components.interfaces.nsISupports]
+ def __long__(self):
+ return 99L
+
+class ExplicitSupportsLong:
+ _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+ components.interfaces.nsISupportsPRInt64]
+ type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT64
+ def get_data(self):
+ return 99
+
+class ExplicitSupportsFloat:
+ _com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
+ components.interfaces.nsISupportsDouble]
+ type = components.interfaces.nsISupportsPrimitive.TYPE_DOUBLE
+ def get_data(self):
+ return 99.99
+
+class ImplicitSupportsFloat:
+ _com_interfaces_ = [components.interfaces.nsISupports]
+ def __float__(self):
+ return 99.99
+
+class PrimitivesTestCase(unittest.TestCase):
+ def testNoSupports(self):
+ ob = xpcom.server.WrapObject( NoSupportsString(), components.interfaces.nsISupports)
+ if not str(ob).startswith("<XPCOM "):
+ raise RuntimeError, "Wrong str() value: %s" % (ob,)
+
+ def testImplicitString(self):
+ ob = xpcom.server.WrapObject( ImplicitSupportsString(), components.interfaces.nsISupports)
+ self.failUnlessEqual(str(ob), "<MyImplicitStrObject>")
+
+ def testExplicitString(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
+ self.failUnlessEqual(str(ob), "<MyExplicitStrObject>")
+
+ def testImplicitUnicode(self):
+ ob = xpcom.server.WrapObject( ImplicitSupportsUnicode(), components.interfaces.nsISupports)
+ self.failUnlessEqual(unicode(ob), ImplicitSupportsUnicode.test_data)
+
+ def testExplicitUnicode(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports)
+ self.failUnlessEqual(unicode(ob), ExplicitSupportsUnicode.test_data)
+
+ def testConvertInt(self):
+ # Try our conversions.
+ ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
+ self.failUnlessRaises( ValueError, int, ob)
+
+ def testExplicitInt(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
+ self.failUnlessAlmostEqual(float(ob), 99.0)
+ self.failUnlessEqual(int(ob), 99)
+
+ def testImplicitInt(self):
+ ob = xpcom.server.WrapObject( ImplicitSupportsInt(), components.interfaces.nsISupports)
+ self.failUnlessAlmostEqual(float(ob), 99.0)
+ self.failUnlessEqual(int(ob), 99)
+
+ def testExplicitLong(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
+ if long(ob) != 99 or not repr(long(ob)).endswith("L"):
+ raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
+ self.failUnlessAlmostEqual(float(ob), 99.0)
+
+ def testImplicitLong(self):
+ ob = xpcom.server.WrapObject( ImplicitSupportsLong(), components.interfaces.nsISupports)
+ if long(ob) != 99 or not repr(long(ob)).endswith("L"):
+ raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
+ self.failUnlessAlmostEqual(float(ob), 99.0)
+
+ def testExplicitFloat(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
+ self.failUnlessEqual(float(ob), 99.99)
+ self.failUnlessEqual(int(ob), 99)
+
+ def testImplicitFloat(self):
+ ob = xpcom.server.WrapObject( ImplicitSupportsFloat(), components.interfaces.nsISupports)
+ self.failUnlessEqual(float(ob), 99.99)
+ self.failUnlessEqual(int(ob), 99)
+
+class PrimitivesModuleTestCase(unittest.TestCase):
+ def testExplicitString(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
+ self.failUnlessEqual(primitives.GetPrimitive(ob), "<MyExplicitStrObject>")
+
+ def testExplicitUnicode(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports)
+ self.failUnlessEqual(primitives.GetPrimitive(ob), ExplicitSupportsUnicode.test_data)
+ self.failUnlessEqual(type(primitives.GetPrimitive(ob)), unicode)
+
+ def testExplicitInt(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
+ self.failUnlessEqual(primitives.GetPrimitive(ob), 99)
+
+ def testExplicitLong(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
+ self.failUnlessEqual(primitives.GetPrimitive(ob), 99)
+
+ def testExplicitFloat(self):
+ ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
+ self.failUnlessEqual(primitives.GetPrimitive(ob), 99.99)
+
+if __name__=='__main__':
+ testmain()
diff --git a/src/libs/xpcom18a4/python/test/test_misc.py b/src/libs/xpcom18a4/python/test/test_misc.py
new file mode 100755
index 00000000..6cf1b74e
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_misc.py
@@ -0,0 +1,236 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# Activestate Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either 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 *****
+
+import xpcom
+import xpcom.client
+import xpcom.server
+import xpcom._xpcom
+import xpcom.components
+import string
+from pyxpcom_test_tools import testmain
+
+import unittest
+
+import traceback, getopt, sys
+
+verbose_level = 0
+
+reportedSampleMissing = 0
+
+def get_sample_component_cpp():
+ global reportedSampleMissing
+ contractid = "@mozilla.org/sample;1" # The C++ version.
+ try:
+ return xpcom.components.classes[contractid].createInstance()
+ except xpcom.COMException:
+ if not reportedSampleMissing:
+ print "***"
+ print "*** This test requires an XPCOM sample component,"
+ print "*** which does not exist. To build this test, you"
+ print "*** should change to the 'mozilla/xpcom/sample' directory,"
+ print "*** and run 'make', then run this test again."
+ print "***"
+ reportedSampleMissing = 1
+ else:
+ print "(skipping - no C++ sample...) ",
+ return None
+
+def get_sample_component_js():
+ # This should *always* exist - no special make process.
+ contractid = "@mozilla.org/jssample;1" # the JS version
+ return xpcom.components.classes[contractid].createInstance()
+
+class TestDumpInterfaces(unittest.TestCase):
+ def testAllInterfaces(self):
+ "Dump every interface under the sun!"
+ import xpcom, xpcom.xpt, xpcom._xpcom
+ iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
+
+ if verbose_level:
+ print "Dumping every interface I can find"
+ enum = iim.EnumerateInterfaces()
+ rc = enum.First()
+ num = 0
+ while rc==0:
+ item = enum.CurrentItem(xpcom._xpcom.IID_nsIInterfaceInfo)
+ try:
+ iid = item.GetIID()
+ except xpcom.COMException:
+ if verbose_level:
+ print "Can't dump", item
+ continue # Dont bother dumping this.
+ interface = xpcom.xpt.Interface(iid)
+ num = num + 1
+ text = interface.Describe()
+ if verbose_level:
+ print text
+
+ rc = enum.Next()
+ if num < 200:
+ print "Only found", num, "interfaces - this seems unusually low!"
+
+class TestEnumContractIDs(unittest.TestCase):
+ def testContractIDs(self):
+ """Enumerate all the ContractIDs registered"""
+ enum = xpcom.components.registrar.enumerateContractIDs()
+ n = 0
+ while enum.hasMoreElements():
+ item = enum.getNext(xpcom.components.interfaces.nsISupportsCString)
+ n = n + 1
+ if verbose_level:
+ print "ContractID:", item.data
+ if n < 200:
+ print "Only found", n, "ContractIDs - this seems unusually low!"
+
+class TestSampleComponent(unittest.TestCase):
+ def _doTestSampleComponent(self, test_flat = 0):
+ """Test the standard Netscape 'sample' sample"""
+ c = get_sample_component_cpp()
+ if c is None:
+ return
+ if not test_flat:
+ c = c.queryInterface(xpcom.components.interfaces.nsISample)
+ self.failUnlessEqual(c.value, "initial value")
+ c.value = "new value"
+ self.failUnlessEqual(c.value, "new value")
+ c.poke("poked value")
+ self.failUnlessEqual(c.value, "poked value")
+ c.writeValue("Python just poked:")
+
+ def testSampleComponentFlat(self):
+ """Test the standard Netscape 'sample' sample using interface flattening"""
+ self._doTestSampleComponent(1)
+
+ def testSampleComponentOld(self):
+ """Test the standard Netscape 'sample' sample using explicit QI"""
+ self._doTestSampleComponent(0)
+
+ def _doTestHash(self, c):
+ "Test that hashing COM objects works"
+ d = {}
+ d[c] = None
+ if not d.has_key(c):
+ raise RuntimeError, "Can't get the exact same object back!"
+ if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISupports)):
+ raise RuntimeError, "Can't get back as nsISupports"
+
+ # And the same in reverse - stick an nsISupports in, and make sure an explicit interface comes back.
+ d = {}
+# contractid = "@mozilla.org/sample;1" # The C++ version.
+# c = xpcom.components.classes[contractid].createInstance() \
+# .queryInterface(xpcom.components.interfaces.nsISupports)
+ d[c] = None
+ if not d.has_key(c):
+ raise RuntimeError, "Can't get the exact same object back!"
+ if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISample)):
+ raise RuntimeError, "Can't get back as nsISupports"
+
+ def testHashJS(self):
+ c = get_sample_component_js()
+ self._doTestHash(c)
+
+ def testHashCPP(self):
+ c = get_sample_component_cpp()
+ if c is not None:
+ self._doTestHash(c)
+
+
+class TestIIDs(unittest.TestCase):
+ def TestIIDs(self):
+ "Do some basic IID semantic tests."
+ iid_str = "{7ee4bdc6-cb53-42c1-a9e4-616b8e012aba}"
+ IID = xpcom._xpcom.IID
+ self.failUnlessEqual(IID(iid_str), IID(iid_str))
+ self.failUnlessEqual(hash(IID(iid_str)), hash(IID(iid_str)))
+ self.failUnlessEqual(IID(iid_str), IID(iid_str.upper()))
+ self.failUnlessEqual(hash(IID(iid_str)), hash(IID(iid_str.upper())))
+ # If the above work, this shoud too, but WTF
+ dict = {}
+ dict[IID(iid_str)] = None
+ self.failUnless(dict.has_key(IID(iid_str)), "hashes failed in dictionary")
+ self.failUnless(dict.has_key(IID(iid_str.upper())), "uppercase hash failed in dictionary")
+
+class TestRepr(unittest.TestCase):
+ def _doTestRepr(self, progid, interfaces):
+ if isinstance(progid, str):
+ ob = xpcom.components.classes[progid].createInstance()
+ else:
+ ob = progid
+ self.failUnless(repr(ob).find(str(progid)) >= 0, repr(ob))
+ for interface_name in interfaces.split():
+ self.failUnless(repr(ob).find(interface_name) >= 0, repr(ob))
+
+ def testReprPython(self):
+ "Test repr() of Python objects"
+ self._doTestRepr("Python.TestComponent", "nsIPythonTestInterfaceDOMStrings nsIPythonTestInterfaceExtra nsIPythonTestInterface")
+
+ # JS does not provide class-info :(
+ #def testReprJS(self):
+ # self._doTestRepr("@mozilla.org/jssample;1", "nsISample")
+
+ def testReprSample(self):
+ "Test repr() of non-Python objects"
+ ob = get_sample_component_cpp()
+ if ob is None:
+ return
+ self._doTestRepr(ob, "nsISample")
+
+class TestUnwrap(unittest.TestCase):
+ "Test the unwrap facilities"
+ def testUnwrap(self):
+ # First test that a Python object can be unwrapped.
+ ob = xpcom.components.classes["Python.TestComponent"].createInstance()
+ pyob = xpcom.server.UnwrapObject(ob)
+ # This depends on our __repr__ implementation, but that's OK - it
+ # can be updated should our __repr__ change :)
+ self.failUnless(str(pyob).startswith("<component:py_test_component.PythonTestComponent"))
+ # Test that a non-Python implemented object can NOT be unwrapped.
+ ob = get_sample_component_cpp()
+ if ob is None:
+ return
+ self.failUnlessRaises(ValueError, xpcom.server.UnwrapObject, ob)
+
+class TestNonScriptable(unittest.TestCase):
+ def testQI(self):
+ # Test we can QI for a non-scriptable interface. We can't *do* much
+ # with it (other than pass it on), but we should still work and get
+ # a basic wrapper.
+ ob = xpcom.components.classes["Python.TestComponent"].createInstance()
+ ob = ob.queryInterface(xpcom._xpcom.IID_nsIInternalPython)
+
+if __name__=='__main__':
+ testmain()
diff --git a/src/libs/xpcom18a4/python/test/test_streams.py b/src/libs/xpcom18a4/python/test/test_streams.py
new file mode 100755
index 00000000..96ac6559
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_streams.py
@@ -0,0 +1,96 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000,2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+import xpcom
+from xpcom import _xpcom, components, COMException, ServerException, nsError
+from StringIO import StringIO
+import unittest
+from pyxpcom_test_tools import testmain
+
+test_data = "abcdefeghijklmnopqrstuvwxyz"
+
+class koTestSimpleStream:
+ _com_interfaces_ = [components.interfaces.nsIInputStream]
+ # We avoid registering this object - see comments in get_test_inout_? below.
+
+ def __init__(self):
+ self.data=StringIO(test_data)
+ self._non_blocking = False
+
+ def close( self ):
+ pass
+
+ def available( self ):
+ return self.data.len-self.data.pos
+
+ def readStr( self, amount):
+ return self.data.read(amount)
+
+ read=readStr
+
+ def get_observer( self ):
+ raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+ def set_observer( self, param0 ):
+ raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
+
+ def isNonBlocking(self):
+ return self._non_blocking
+
+def get_test_input():
+ # We use a couple of internal hacks here that mean we can avoid having the object
+ # registered. This code means that we are still working over the xpcom boundaries, tho
+ # (and the point of this test is not the registration, etc).
+ import xpcom.server, xpcom.client
+ ob = xpcom.server.WrapObject( koTestSimpleStream(), _xpcom.IID_nsISupports)
+ ob = xpcom.client.Component(ob._comobj_, components.interfaces.nsIInputStream)
+ return ob
+
+class StreamTests(unittest.TestCase):
+ def testInput(self):
+ self.do_test_input( get_test_input() )
+
+ def do_test_input(self, myStream):
+ self.failUnlessEqual(str(myStream.read(5)), test_data[:5])
+ self.failUnlessEqual(str(myStream.read(0)), '')
+ self.failUnlessEqual(str(myStream.read(5)), test_data[5:10])
+ self.failUnlessEqual(str(myStream.read(-1)), test_data[10:])
+ self.failIf(myStream.isNonBlocking(), "Expected default to be blocking")
+ # stream observer mechanism has changed - we should test that.
+
+if __name__=='__main__':
+ testmain()
diff --git a/src/libs/xpcom18a4/python/test/test_test_component.js b/src/libs/xpcom18a4/python/test/test_test_component.js
new file mode 100644
index 00000000..54e39382
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_test_component.js
@@ -0,0 +1,138 @@
+/* ***** 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 Python XPCOM language bindings.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com> (original author)
+ *
+ * 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 ***** */
+
+/* Javascript code calling the Python test interface. */
+
+var extended_unicode_string = "The Euro Symbol is '\u20ac'";
+
+function MakeTestInterface()
+{
+ var clazz = Components.classes["Python.TestComponent"];
+ var iface = Components.interfaces.nsIPythonTestInterfaceDOMStrings;
+ return new clazz(iface);
+}
+
+var c = new MakeTestInterface();
+
+if (c.boolean_value != 1)
+ throw("boolean_value has wrong initial value");
+c.boolean_value = false;
+if (c.boolean_value != false)
+ throw("boolean_value has wrong new value");
+
+// Python's own test does thorough testing of all numeric types
+// Wont bother from here!
+
+if (c.char_value != 'a')
+ throw("char_value has wrong initial value");
+c.char_value = 'b';
+if (c.char_value != 'b')
+ throw("char_value has wrong new value");
+
+if (c.wchar_value != 'b')
+ throw("wchar_value has wrong initial value");
+c.wchar_value = 'c';
+if (c.wchar_value != 'c')
+ throw("wchar_value has wrong new value");
+
+if (c.string_value != 'cee')
+ throw("string_value has wrong initial value");
+c.string_value = 'dee';
+if (c.string_value != 'dee')
+ throw("string_value has wrong new value");
+
+if (c.wstring_value != 'dee')
+ throw("wstring_value has wrong initial value");
+c.wstring_value = 'eee';
+if (c.wstring_value != 'eee')
+ throw("wstring_value has wrong new value");
+c.wstring_value = extended_unicode_string;
+if (c.wstring_value != extended_unicode_string)
+ throw("wstring_value has wrong new value");
+
+if (c.domstring_value != 'dom')
+ throw("domstring_value has wrong initial value");
+c.domstring_value = 'New value';
+if (c.domstring_value != 'New value')
+ throw("domstring_value has wrong new value");
+c.domstring_value = extended_unicode_string;
+if (c.domstring_value != extended_unicode_string)
+ throw("domstring_value has wrong new value");
+
+if (c.utf8string_value != 'utf8string')
+ throw("utf8string_value has wrong initial value");
+c.utf8string_value = 'New value';
+if (c.utf8string_value != 'New value')
+ throw("utf8string_value has wrong new value");
+c.utf8string_value = extended_unicode_string;
+if (c.utf8string_value != extended_unicode_string)
+ throw("utf8string_value has wrong new value");
+
+var v = new Object();
+v.value = "Hello"
+var l = new Object();
+l.value = v.value.length;
+c.DoubleString(l, v);
+if ( v.value != "HelloHello")
+ throw("Could not double the string!");
+
+var v = new Object();
+v.value = "Hello"
+var l = new Object();
+l.value = v.value.length;
+c.DoubleWideString(l, v);
+if ( v.value != "HelloHello")
+ throw("Could not double the wide string!");
+
+// Some basic array tests
+var v = new Array()
+v[0] = 1;
+v[2] = 2;
+v[3] = 3;
+var v2 = new Array()
+v2[0] = 4;
+v2[2] = 5;
+v2[3] = 6;
+if (c.SumArrays(v.length, v, v2) != 21)
+ throw("Could not sum an array of integers!");
+
+var count = new Object();
+count.value = 0;
+var out = [];
+c.DoubleStringArray(count, out);
+
+print("javascript successfully tested the Python test component.");
diff --git a/src/libs/xpcom18a4/python/test/test_test_component.py b/src/libs/xpcom18a4/python/test/test_test_component.py
new file mode 100755
index 00000000..dd78133a
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_test_component.py
@@ -0,0 +1,575 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <MarkH@ActiveState.com> (original author)
+#
+# 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 *****
+
+import sys, os, time
+import xpcom.components
+import xpcom._xpcom
+import xpcom.nsError
+
+MakeVariant = xpcom._xpcom.MakeVariant
+
+try:
+ import gc
+except ImportError:
+ gc = None
+
+num_errors = 0
+
+component_iid = xpcom.components.ID("{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}")
+new_iid = xpcom.components.ID("{2AF747D3-ECBC-457b-9AF9-5C5D80EDC360}")
+
+contractid = "Python.TestComponent"
+
+really_big_string = "This is really repetitive!" * 10000
+really_big_wstring = u"This is really repetitive!" * 10000
+extended_unicode_string = u"The Euro Symbol is '\u20ac'"
+
+# Exception raised when a -ve integer is converted to an unsigned C integer
+# (via an extension module). This changed in Python 2.2
+if sys.hexversion > 0x02010000:
+ UnsignedMismatchException = TypeError
+else:
+ UnsignedMismatchException = OverflowError
+
+def print_error(error):
+ print error
+ global num_errors
+ num_errors = num_errors + 1
+
+def _test_value(what, got, expecting):
+ ok = got == expecting
+ if type(got)==type(expecting)==type(0.0):
+ ok = abs(got-expecting) < 0.001
+ if not ok:
+ print_error("*** Error %s - got '%r', but expecting '%r'" % (what, got, expecting))
+
+def test_attribute(ob, attr_name, expected_init, new_value, new_value_really = None):
+ if xpcom.verbose:
+ print "Testing attribute %s" % (attr_name,)
+ if new_value_really is None:
+ new_value_really = new_value # Handy for eg bools - set a BOOL to 2, you still get back 1!
+
+ _test_value( "getting initial attribute value (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
+ setattr(ob, attr_name, new_value)
+ _test_value( "getting new attribute value (%s)" % (attr_name,), getattr(ob, attr_name), new_value_really)
+ # And set it back to the expected init.
+ setattr(ob, attr_name, expected_init)
+ _test_value( "getting back initial attribute value after change (%s)" % (attr_name,), getattr(ob, attr_name), expected_init)
+
+def test_string_attribute(ob, attr_name, expected_init, is_dumb_sz = False, ascii_only = False):
+ test_attribute(ob, attr_name, expected_init, "normal value")
+ val = "a null >\0<"
+ if is_dumb_sz:
+ expected = "a null >" # dumb strings are \0 terminated.
+ else:
+ expected = val
+ test_attribute(ob, attr_name, expected_init, val, expected)
+ test_attribute(ob, attr_name, expected_init, "")
+ test_attribute(ob, attr_name, expected_init, really_big_string)
+ test_attribute(ob, attr_name, expected_init, u"normal unicode value")
+ val = u"a null >\0<"
+ if is_dumb_sz:
+ expected = "a null >" # dumb strings are \0 terminated.
+ else:
+ expected = val
+ test_attribute(ob, attr_name, expected_init, val, expected)
+ test_attribute(ob, attr_name, expected_init, u"")
+ test_attribute(ob, attr_name, expected_init, really_big_wstring)
+ if not ascii_only:
+ test_attribute(ob, attr_name, expected_init, extended_unicode_string)
+
+def test_attribute_failure(ob, attr_name, new_value, expected_exception):
+ try:
+ setattr(ob, attr_name, new_value)
+ print_error("*** Setting attribute '%s' to '%r' didnt yield an exception!" % (attr_name, new_value) )
+ except:
+ exc_typ = sys.exc_info()[0]
+ exc_val = sys.exc_info()[1]
+ ok = issubclass(exc_typ, expected_exception)
+ if not ok:
+ print_error("*** Wrong exception setting '%s' to '%r'- got '%s: %s', expected '%s'" % (attr_name, new_value, exc_typ, exc_val, expected_exception))
+
+
+def test_method(method, args, expected_results):
+ if xpcom.verbose:
+ print "Testing %s%s" % (method.__name__, `args`)
+ ret = method(*args)
+ if ret != expected_results:
+ print_error("calling method %s - expected %r, but got %r" % (method.__name__, expected_results, ret))
+
+def test_int_method(meth):
+ test_method(meth, (0,0), (0,0,0))
+ test_method(meth, (1,1), (2,0,1))
+ test_method(meth, (5,2), (7,3,10))
+# test_method(meth, (2,5), (7,-3,10))
+
+def test_constant(ob, cname, val):
+ v = getattr(ob, cname)
+ if v != val:
+ print_error("Bad value for constant '%s' - got '%r'" % (cname, v))
+ try:
+ setattr(ob, cname, 0)
+ print_error("The object allowed us to set the constant '%s'" % (cname,))
+ except AttributeError:
+ pass
+
+def test_base_interface(c):
+ test_attribute(c, "boolean_value", 1, 0)
+ test_attribute(c, "boolean_value", 1, -1, 1) # Set a bool to anything, you should always get back 0 or 1
+ test_attribute(c, "boolean_value", 1, 4, 1) # Set a bool to anything, you should always get back 0 or 1
+ test_attribute(c, "boolean_value", 1, "1", 1) # This works by virtual of PyNumber_Int - not sure I agree, but...
+ test_attribute_failure(c, "boolean_value", "boo", ValueError)
+ test_attribute_failure(c, "boolean_value", test_base_interface, TypeError)
+
+ test_attribute(c, "octet_value", 2, 5)
+ test_attribute(c, "octet_value", 2, 0)
+ test_attribute(c, "octet_value", 2, 128) # octet is unsigned 8 bit
+ test_attribute(c, "octet_value", 2, 255) # octet is unsigned 8 bit
+ test_attribute(c, "octet_value", 2, -1, 255) # octet is unsigned 8 bit
+ test_attribute_failure(c, "octet_value", "boo", ValueError)
+
+ test_attribute(c, "short_value", 3, 10)
+ test_attribute(c, "short_value", 3, -1) # 16 bit signed
+ test_attribute(c, "short_value", 3, 0xFFFF, -1) # 16 bit signed
+ test_attribute(c, "short_value", 3, 0L)
+ test_attribute(c, "short_value", 3, 1L)
+ test_attribute(c, "short_value", 3, -1L)
+ test_attribute(c, "short_value", 3, 0xFFFFL, -1)
+ test_attribute_failure(c, "short_value", "boo", ValueError)
+
+ test_attribute(c, "ushort_value", 4, 5)
+ test_attribute(c, "ushort_value", 4, 0)
+ test_attribute(c, "ushort_value", 4, -1, 0xFFFF) # 16 bit signed
+ test_attribute(c, "ushort_value", 4, 0xFFFF) # 16 bit signed
+ test_attribute(c, "ushort_value", 4, 0L)
+ test_attribute(c, "ushort_value", 4, 1L)
+ test_attribute(c, "ushort_value", 4, -1L, 0xFFFF)
+ test_attribute_failure(c, "ushort_value", "boo", ValueError)
+
+ test_attribute(c, "long_value", 5, 7)
+ test_attribute(c, "long_value", 5, 0)
+ test_attribute(c, "long_value", 5, -1, -1) # 32 bit signed.
+ test_attribute(c, "long_value", 5, -1) # 32 bit signed.
+ test_attribute(c, "long_value", 5, 0L)
+ test_attribute(c, "long_value", 5, 1L)
+ test_attribute(c, "long_value", 5, -1L)
+ test_attribute_failure(c, "long_value", 0xFFFFL * 0xFFFF, OverflowError) # long int too long to convert
+ test_attribute_failure(c, "long_value", "boo", ValueError)
+
+ test_attribute(c, "ulong_value", 6, 7)
+ test_attribute(c, "ulong_value", 6, 0)
+ test_attribute(c, "ulong_value", 6, -1) # 32 bit signed.
+ test_attribute_failure(c, "ulong_value", "boo", ValueError)
+
+ test_attribute(c, "long_long_value", 7, 8)
+ test_attribute(c, "long_long_value", 7, 0)
+ test_attribute(c, "long_long_value", 7, -1)
+ test_attribute(c, "long_long_value", 7, 0xFFFF)
+ test_attribute(c, "long_long_value", 7, 0xFFFFL * 2)
+ test_attribute_failure(c, "long_long_value", 0xFFFFL * 0xFFFF * 0xFFFF * 0xFFFF, OverflowError) # long int too long to convert
+ test_attribute_failure(c, "long_long_value", "boo", ValueError)
+
+ test_attribute(c, "ulong_long_value", 8, 9)
+ test_attribute(c, "ulong_long_value", 8, 0)
+ test_attribute_failure(c, "ulong_long_value", "boo", ValueError)
+ test_attribute_failure(c, "ulong_long_value", -1, UnsignedMismatchException) # can't convert negative value to unsigned long)
+
+ test_attribute(c, "float_value", 9.0, 10.2)
+ test_attribute(c, "float_value", 9.0, 0)
+ test_attribute(c, "float_value", 9.0, -1)
+ test_attribute(c, "float_value", 9.0, 1L)
+ test_attribute_failure(c, "float_value", "boo", ValueError)
+
+ test_attribute(c, "double_value", 10.0, 9.0)
+ test_attribute(c, "double_value", 10.0, 0)
+ test_attribute(c, "double_value", 10.0, -1)
+ test_attribute(c, "double_value", 10.0, 1L)
+ test_attribute_failure(c, "double_value", "boo", ValueError)
+
+ test_attribute(c, "char_value", "a", "b")
+ test_attribute(c, "char_value", "a", "\0")
+ test_attribute_failure(c, "char_value", "xy", ValueError)
+ test_attribute(c, "char_value", "a", u"c")
+ test_attribute(c, "char_value", "a", u"\0")
+ test_attribute_failure(c, "char_value", u"xy", ValueError)
+
+ test_attribute(c, "wchar_value", "b", "a")
+ test_attribute(c, "wchar_value", "b", "\0")
+ test_attribute_failure(c, "wchar_value", "hi", ValueError)
+ test_attribute(c, "wchar_value", "b", u"a")
+ test_attribute(c, "wchar_value", "b", u"\0")
+ test_attribute_failure(c, "wchar_value", u"hi", ValueError)
+
+ test_string_attribute(c, "string_value", "cee", is_dumb_sz = True, ascii_only = True)
+ test_string_attribute(c, "wstring_value", "dee", is_dumb_sz = True)
+ test_string_attribute(c, "astring_value", "astring")
+ test_string_attribute(c, "acstring_value", "acstring", ascii_only = True)
+
+ test_string_attribute(c, "utf8string_value", "utf8string")
+ # Test a string already encoded gets through correctly.
+ test_attribute(c, "utf8string_value", "utf8string", extended_unicode_string.encode("utf8"), extended_unicode_string)
+
+ # This will fail internal string representation :( Test we don't crash
+ try:
+ c.wstring_value = "a big char >" + chr(129) + "<"
+ print_error("strings with chars > 128 appear to have stopped failing?")
+ except UnicodeError:
+ pass
+
+ test_attribute(c, "iid_value", component_iid, new_iid)
+ test_attribute(c, "iid_value", component_iid, str(new_iid), new_iid)
+ test_attribute(c, "iid_value", component_iid, xpcom._xpcom.ID(new_iid))
+
+ test_attribute_failure(c, "no_attribute", "boo", AttributeError)
+
+ test_attribute(c, "interface_value", None, c)
+ test_attribute_failure(c, "interface_value", 2, TypeError)
+
+ test_attribute(c, "isupports_value", None, c)
+
+ # The methods
+ test_method(c.do_boolean, (0,1), (1,0,1))
+ test_method(c.do_boolean, (1,0), (1,0,1))
+ test_method(c.do_boolean, (1,1), (0,1,0))
+
+ test_int_method(c.do_octet)
+ test_int_method(c.do_short)
+
+ test_int_method(c.do_unsigned_short)
+ test_int_method(c.do_long)
+ test_int_method(c.do_unsigned_long)
+ test_int_method(c.do_long_long)
+ test_int_method(c.do_unsigned_long)
+ test_int_method(c.do_float)
+ test_int_method(c.do_double)
+
+ test_method(c.do_char, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
+ test_method(c.do_char, ("A", "\0"), ("A", "\0","A") )
+ test_method(c.do_wchar, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") )
+ test_method(c.do_wchar, ("A", "\0"), ("A", "\0","A") )
+
+ test_method(c.do_string, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
+ test_method(c.do_string, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
+ test_method(c.do_string, (None, u"Python"), ("Python", None, "Python") )
+ test_method(c.do_string, (None, really_big_string), (really_big_string, None, really_big_string) )
+ test_method(c.do_string, (None, really_big_wstring), (really_big_string, None, really_big_string) )
+ test_method(c.do_wstring, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") )
+ test_method(c.do_wstring, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") )
+ test_method(c.do_string, (None, really_big_wstring), (really_big_wstring, None, really_big_wstring) )
+ test_method(c.do_string, (None, really_big_string), (really_big_wstring, None, really_big_wstring) )
+ test_method(c.do_nsIIDRef, (component_iid, new_iid), (component_iid, component_iid, new_iid))
+ test_method(c.do_nsIIDRef, (new_iid, component_iid), (new_iid, component_iid, component_iid))
+ test_method(c.do_nsIPythonTestInterface, (None, None), (None, None, c))
+ test_method(c.do_nsIPythonTestInterface, (c, c), (c, c, c))
+ test_method(c.do_nsISupports, (None, None), (c, None, None))
+ test_method(c.do_nsISupports, (c,c), (c, c, c))
+ test_method(c.do_nsISupportsIs, (xpcom._xpcom.IID_nsISupports,), c)
+ test_method(c.do_nsISupportsIs, (xpcom.components.interfaces.nsIPythonTestInterface,), c)
+## test_method(c.do_nsISupportsIs2, (xpcom.components.interfaces.nsIPythonTestInterface,c), (xpcom.components.interfaces.nsIPythonTestInterface,c))
+## test_method(c.do_nsISupportsIs3, (c,), (xpcom.components.interfaces.nsIPythonTestInterface,c))
+## test_method(c.do_nsISupportsIs4, (), (xpcom.components.interfaces.nsIPythonTestInterface,c))
+ # Test the constants.
+ test_constant(c, "One", 1)
+ test_constant(c, "Two", 2)
+ test_constant(c, "MinusOne", -1)
+ test_constant(c, "BigLong", 0x7FFFFFFF)
+ test_constant(c, "BiggerLong", -1)
+ test_constant(c, "BigULong", -1)
+ # Test the components.Interfaces semantics
+ i = xpcom.components.interfaces.nsIPythonTestInterface
+ test_constant(i, "One", 1)
+ test_constant(i, "Two", 2)
+ test_constant(i, "MinusOne", -1)
+ test_constant(i, "BigLong", 0x7FFFFFFF)
+ test_constant(i, "BigULong", -1)
+
+def test_derived_interface(c, test_flat = 0):
+ val = "Hello\0there"
+ expected = val * 2
+
+ test_method(c.DoubleString, (val,), expected)
+ test_method(c.DoubleString2, (val,), expected)
+ test_method(c.DoubleString3, (val,), expected)
+ test_method(c.DoubleString4, (val,), expected)
+ test_method(c.UpString, (val,), val.upper())
+ test_method(c.UpString2, (val,), val.upper())
+ test_method(c.GetFixedString, (20,), "A"*20)
+ val = u"Hello\0there"
+ expected = val * 2
+ test_method(c.DoubleWideString, (val,), expected)
+ test_method(c.DoubleWideString2, (val,), expected)
+ test_method(c.DoubleWideString3, (val,), expected)
+ test_method(c.DoubleWideString4, (val,), expected)
+ test_method(c.UpWideString, (val,), val.upper())
+ test_method(c.UpWideString2, (val,), val.upper())
+ test_method(c.GetFixedWideString, (20,), u"A"*20)
+ val = extended_unicode_string
+ test_method(c.CopyUTF8String, ("foo",), "foo")
+ test_method(c.CopyUTF8String, (u"foo",), "foo")
+ test_method(c.CopyUTF8String, (val,), val)
+ test_method(c.CopyUTF8String, (val.encode("utf8"),), val)
+ test_method(c.CopyUTF8String2, ("foo",), "foo")
+ test_method(c.CopyUTF8String2, (u"foo",), "foo")
+ test_method(c.CopyUTF8String2, (val,), val)
+ test_method(c.CopyUTF8String2, (val.encode("utf8"),), val)
+ items = [1,2,3,4,5]
+ test_method(c.MultiplyEachItemInIntegerArray, (3, items,), map(lambda i:i*3, items))
+
+ test_method(c.MultiplyEachItemInIntegerArrayAndAppend, (3, items), items + map(lambda i:i*3, items))
+ items = "Hello from Python".split()
+ expected = map( lambda x: x*2, items)
+ test_method(c.DoubleStringArray, (items,), expected)
+
+ test_method(c.CompareStringArrays, (items, items), cmp(items, items))
+ # Can we pass lists and tuples correctly?
+ test_method(c.CompareStringArrays, (items, tuple(items)), cmp(items, items))
+ items2 = ["Not", "the", "same"]
+ test_method(c.CompareStringArrays, (items, items2), cmp(items, items2))
+
+ expected = items[:]
+ expected.reverse()
+ test_method(c.ReverseStringArray, (items,), expected)
+
+ expected = "Hello from the Python test component".split()
+ test_method(c.GetStrings, (), expected)
+
+ val = "Hello\0there"
+ test_method(c.UpOctetArray, (val,), val.upper())
+ test_method(c.UpOctetArray, (unicode(val),), val.upper())
+ # Passing Unicode objects here used to cause us grief.
+ test_method(c.UpOctetArray2, (val,), val.upper())
+
+ test_method(c.CheckInterfaceArray, ((c, c),), 1)
+ test_method(c.CheckInterfaceArray, ((c, None),), 0)
+ test_method(c.CheckInterfaceArray, ((),), 1)
+ test_method(c.CopyInterfaceArray, ((c, c),), [c,c])
+
+ test_method(c.GetInterfaceArray, (), [c,c,c, None])
+ test_method(c.ExtendInterfaceArray, ((c,c,c, None),), [c,c,c,None,c,c,c,None] )
+
+ expected = [xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings, xpcom.components.classes[contractid].clsid]
+ test_method(c.GetIIDArray, (), expected)
+
+ val = [xpcom.components.interfaces.nsIPythonTestInterfaceExtra, xpcom.components.classes[contractid].clsid]
+ expected = val * 2
+ test_method(c.ExtendIIDArray, (val,), expected)
+
+ test_method(c.GetArrays, (), ( [1,2,3], [4,5,6] ) )
+ test_method(c.CopyArray, ([1,2,3],), [1,2,3] )
+ test_method(c.CopyAndDoubleArray, ([1,2,3],), [1,2,3,1,2,3] )
+ test_method(c.AppendArray, ([1,2,3],), [1,2,3])
+ test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6])
+
+ test_method(c.CopyVariant, (None,), None)
+ test_method(c.CopyVariant, (1,), 1)
+ test_method(c.CopyVariant, (1.0,), 1.0)
+ test_method(c.CopyVariant, (-1,), -1)
+ test_method(c.CopyVariant, (sys.maxint+1,), sys.maxint+1)
+ test_method(c.CopyVariant, ("foo",), "foo")
+ test_method(c.CopyVariant, (u"foo",), u"foo")
+ test_method(c.CopyVariant, (c,), c)
+ test_method(c.CopyVariant, (component_iid,), component_iid)
+ test_method(c.CopyVariant, ((1,2),), [1,2])
+ test_method(c.CopyVariant, ((1.2,2.1),), [1.2,2.1])
+ test_method(c.CopyVariant, (("foo","bar"),), ["foo", "bar"])
+ test_method(c.CopyVariant, ((component_iid,component_iid),), [component_iid,component_iid])
+ test_method(c.CopyVariant, ((c,c),), [c,c])
+ sup = c.queryInterface(xpcom.components.interfaces.nsISupports)._comobj_
+ test_method(c.CopyVariant, ((sup, sup),), [sup,sup])
+ test_method(c.AppendVariant, (1,2), 3)
+ test_method(c.AppendVariant, ((1,2),(3,4)), 10)
+ test_method(c.AppendVariant, ("bar", "foo"), "foobar")
+ test_method(c.AppendVariant, (None, None), None)
+
+ test_method(c.SumVariants, ([],), None)
+ # Array's dont expose their interface, so we are unable to auto-wrap
+ # variant arrays, as they aren't aware if the IID of the array
+ test_method(c.SumVariants, ([MakeVariant(1),MakeVariant(2),MakeVariant(3)],), 6)
+ test_method(c.SumVariants, ([MakeVariant('foo'), MakeVariant('bar')],), 'foobar')
+
+ if not test_flat:
+ c = c.queryInterface(xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings)
+# NULL DOM strings don't work yet.
+# test_method(c.GetDOMStringResult, (-1,), None)
+ test_method(c.GetDOMStringResult, (3,), "PPP")
+# test_method(c.GetDOMStringOut, (-1,), None)
+ test_method(c.GetDOMStringOut, (4,), "yyyy")
+ val = "Hello there"
+ test_method(c.GetDOMStringLength, (val,), len(val))
+ test_method(c.GetDOMStringRefLength, (val,), len(val))
+ test_method(c.GetDOMStringPtrLength, (val,), len(val))
+ test_method(c.ConcatDOMStrings, (val,val), val+val)
+ test_attribute(c, "domstring_value", "dom", "new dom")
+ if c.domstring_value_ro != "dom":
+ print "Read-only DOMString not correct - got", c.domstring_ro
+ try:
+ c.dom_string_ro = "new dom"
+ print "Managed to set a readonly attribute - eek!"
+ except AttributeError:
+ pass
+ except:
+ print "Unexpected exception when setting readonly attribute: %s: %s" % (sys.exc_info()[0], sys.exc_info()[1])
+ if c.domstring_value_ro != "dom":
+ print "Read-only DOMString not correct after failed set attempt - got", c.domstring_ro
+
+def do_test_failures():
+ c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
+ try:
+ ret = c.do_nsISupportsIs( xpcom._xpcom.IID_nsIInterfaceInfoManager )
+ print "*** got", ret, "***"
+ raise RuntimeError, "We worked when using an IID we dont support!?!"
+ except xpcom.Exception, details:
+ if details.errno != xpcom.nsError.NS_ERROR_NO_INTERFACE:
+ raise RuntimeError, "Wrong COM exception type: %r" % (details,)
+
+def test_failures():
+ # This extra stack-frame ensures Python cleans up sys.last_traceback etc
+ do_test_failures()
+
+def test_all():
+ c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterface)
+ test_base_interface(c)
+ # Now create an instance using the derived IID, and test that.
+ c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra)
+ test_base_interface(c)
+ test_derived_interface(c)
+ # Now create an instance and test interface flattening.
+ c = xpcom.components.classes[contractid].createInstance()
+ test_base_interface(c)
+ test_derived_interface(c, test_flat=1)
+
+ # We had a bug where a "set" of an attribute before a "get" failed.
+ # Don't let it happen again :)
+ c = xpcom.components.classes[contractid].createInstance()
+ c.boolean_value = 0
+
+ # This name is used in exceptions etc - make sure we got it from nsIClassInfo OK.
+ assert c._object_name_ == "Python.TestComponent"
+
+ test_failures()
+
+try:
+ from sys import gettotalrefcount
+except ImportError:
+ # Not a Debug build - assume no references (can't be leaks then :-)
+ def gettotalrefcount():
+ return 0
+
+from pyxpcom_test_tools import getmemusage
+
+def test_from_js():
+ # Ensure we can find the js test script - same dir as this!
+ # Assume the path of sys.argv[0] is where we can find the js test code.
+ # (Running under the regression test is a little painful)
+ script_dir = os.path.split(sys.argv[0])[0]
+ fname = os.path.join( script_dir, "test_test_component.js")
+ if not os.path.isfile(fname):
+ raise RuntimeError, "Can not find '%s'" % (fname,)
+ # Note we _dont_ pump the test output out, as debug "xpcshell" spews
+ # extra debug info that will cause our output comparison to fail.
+ data = os.popen('xpcshell "' + fname + '"').readlines()
+ good = 0
+ for line in data:
+ if line.strip() == "javascript successfully tested the Python test component.":
+ good = 1
+ if not good:
+ print "** The javascript test appeared to fail! Test output follows **"
+ print "".join(data)
+ print "** End of javascript test output **"
+ raise RuntimeError, "test failed"
+
+def doit(num_loops = -1):
+ if "-v" in sys.argv: # Hack the verbose flag for the server
+ xpcom.verbose = 1
+ # Do the test lots of times - can help shake-out ref-count bugs.
+ if num_loops == -1: num_loops = 5
+ for i in xrange(num_loops):
+ test_all()
+
+ if i==0:
+ # First loop is likely to "leak" as we cache things.
+ # Leaking after that is a problem.
+ if gc is not None:
+ gc.collect()
+ num_refs = gettotalrefcount()
+ mem_usage = getmemusage()
+
+ if num_errors:
+ break
+
+ if gc is not None:
+ gc.collect()
+
+ lost = gettotalrefcount() - num_refs
+ # Sometimes we get spurious counts off by 1 or 2.
+ # This can't indicate a real leak, as we have looped
+ # more than twice!
+ if abs(lost)>3: # 2 or 3 :)
+ print "*** Lost %d references" % (lost,)
+
+ # sleep to allow the OS to recover
+ time.sleep(1)
+ mem_lost = getmemusage() - mem_usage
+ # working set size is fickle, and when we were leaking strings, this test
+ # would report a leak of 100MB. So we allow a 3MB buffer - but even this
+ # may still occasionally report spurious warnings. If you are really
+ # worried, bump the counter to a huge value, and if there is a leak it will
+ # show.
+ if mem_lost > 3000000:
+ print "*** Lost %.6f MB of memory" % (mem_lost/1000000.0,)
+
+ assert num_errors==0, "There were %d errors testing the Python component" % (num_errors,)
+
+def suite():
+ from pyxpcom_test_tools import suite_from_functions
+ return suite_from_functions(doit, test_from_js)
+
+if __name__=='__main__':
+ num_iters = 10 # times times is *lots* - we do a fair bit of work!
+ if __name__=='__main__' and len(sys.argv) > 1:
+ num_iters = int(sys.argv[1])
+
+ print "Testing the Python.TestComponent component"
+ doit(num_iters)
+ print "The Python test component worked."
+ test_from_js()
+ print "JS successfully used our Python test component."
+ xpcom._xpcom.NS_ShutdownXPCOM()
+ ni = xpcom._xpcom._GetInterfaceCount()
+ ng = xpcom._xpcom._GetGatewayCount()
+ if ni or ng:
+ print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
diff --git a/src/libs/xpcom18a4/python/test/test_weakreferences.py b/src/libs/xpcom18a4/python/test/test_weakreferences.py
new file mode 100755
index 00000000..9bfb3fbc
--- /dev/null
+++ b/src/libs/xpcom18a4/python/test/test_weakreferences.py
@@ -0,0 +1,114 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <markh@activestate.com> (original author)
+#
+# 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 *****
+
+# test_weakreferences.py - Test our weak reference implementation.
+from xpcom import components, _xpcom
+import xpcom.server, xpcom.client
+from pyxpcom_test_tools import suite_from_functions, testmain
+
+try:
+ from sys import gettotalrefcount
+except ImportError:
+ # Not a Debug build - assume no references (can't be leaks then :-)
+ gettotalrefcount = lambda: 0
+
+num_alive = 0
+
+class koTestSimple:
+ _com_interfaces_ = [components.interfaces.nsIInputStream]
+ def __init__(self):
+ global num_alive
+ num_alive += 1
+ def __del__(self):
+ global num_alive
+ num_alive -= 1
+ def close( self ):
+ pass
+
+def test():
+ ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsIInputStream)
+
+ if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+
+ # Check we can create a weak reference to our object.
+ wr = xpcom.client.WeakReference(ob)
+ if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+
+ # Check we can call methods via the weak reference.
+ if wr() is None: raise RuntimeError, "Our weak-reference is returning None before it should!"
+ wr().close()
+
+ ob = None # This should kill the object.
+ if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+ if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!"
+
+ # Now a test that we can get a _new_ interface from the weak reference - ie,
+ # an IID the real object has never previously been queried for
+ # (this behaviour previously caused a bug - never again ;-)
+ ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsISupports)
+ if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+ wr = xpcom.client.WeakReference(ob, components.interfaces.nsIInputStream)
+ if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+ wr() # This would die once upon a time ;-)
+ ob = None # This should kill the object.
+ if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,)
+ if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!"
+
+def test_refcount(num_loops=-1):
+ # Do the test lots of times - can help shake-out ref-count bugs.
+ if num_loops == -1: num_loops = 10
+ for i in xrange(num_loops):
+ test()
+
+ if i==0:
+ # First loop is likely to "leak" as we cache things.
+ # Leaking after that is a problem.
+ num_refs = gettotalrefcount()
+
+ lost = gettotalrefcount() - num_refs
+ # Sometimes we get spurious counts off by 1 or 2.
+ # This can't indicate a real leak, as we have looped
+ # more than twice!
+ if abs(lost)>2:
+ print "*** Lost %d references" % (lost,)
+
+# Make this test run under our std test suite
+def suite():
+ return suite_from_functions(test_refcount)
+
+if __name__=='__main__':
+ testmain()
diff --git a/src/libs/xpcom18a4/python/tools/regxpcom.py b/src/libs/xpcom18a4/python/tools/regxpcom.py
new file mode 100755
index 00000000..2b7ea6a4
--- /dev/null
+++ b/src/libs/xpcom18a4/python/tools/regxpcom.py
@@ -0,0 +1,68 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <mhammond@skippinet.com.au> (original author)
+#
+# 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 *****
+
+# regxpcom.py - basically the standard regxpcom.cpp ported to Python.
+# In general, you should use regxpcom.exe instead of this.
+
+from xpcom import components, _xpcom
+from xpcom.client import Component
+import sys
+import os
+
+registrar = Component(_xpcom.GetComponentRegistrar(),
+ components.interfaces.nsIComponentRegistrar)
+
+def ProcessArgs(args):
+
+ unregister = 0
+ for arg in args:
+ spec = components.classes['@mozilla.org/file/local;1'].createInstance()
+ spec = spec.QueryInterface(components.interfaces.nsILocalFile)
+ spec.initWithPath(os.path.abspath(arg))
+ if arg == "-u":
+ registrar.autoUnregister(spec)
+ print "Successfully unregistered", spec.path
+ else:
+ registrar.autoRegister(spec)
+ print "Successfully registered", spec.path
+
+if len(sys.argv) < 2:
+ registrar.autoRegister( None)
+else:
+ ProcessArgs(sys.argv[1:])
+
+#_xpcom.NS_ShutdownXPCOM()
diff --git a/src/libs/xpcom18a4/python/tools/tracer_demo.py b/src/libs/xpcom18a4/python/tools/tracer_demo.py
new file mode 100755
index 00000000..045c3db8
--- /dev/null
+++ b/src/libs/xpcom18a4/python/tools/tracer_demo.py
@@ -0,0 +1,113 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <mhammond@skippinet.com.au> (original author)
+#
+# 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 *****
+
+# This is a demo is how to use the xpcom.server "tracer" facility.
+#
+# This demo installs a tracer that uses the Python profiler. It then
+# creates the Python test component, and references some methods
+# and properties. It then dumps the profile statistics.
+
+# This same technique could also be used for debugging, for example.
+
+import profile
+
+p = profile.Profile()
+getters = {}
+setters = {}
+
+# A wrapper around a function - looks like a function,
+# but actually profiles the delegate.
+class TracerDelegate:
+ def __init__(self, callme):
+ self.callme = callme
+ def __call__(self, *args):
+ return p.runcall(self.callme, *args)
+
+# A wrapper around each of our XPCOM objects. All PyXPCOM calls
+# in are made on this object, which creates a TracerDelagate around
+# every function. As the function is called, it collects profile info.
+class Tracer:
+ def __init__(self, ob):
+ self.__dict__['_ob'] = ob
+ def __repr__(self):
+ return "<Tracer around %r>" % (self._ob,)
+ def __str__(self):
+ return "<Tracer around %r>" % (self._ob,)
+ def __getattr__(self, attr):
+ ret = getattr(self._ob, attr) # Attribute error just goes up
+ if callable(ret):
+ return TracerDelegate(ret)
+ else:
+ if not attr.startswith("_com_") and not attr.startswith("_reg_"):
+ getters[attr] = getters.setdefault(attr,0) + 1
+ return ret
+ def __setattr__(self, attr, val):
+ if self.__dict__.has_key(attr):
+ self.__dict__[attr] = val
+ return
+ setters[attr] = setters.setdefault(attr,0) + 1
+ setattr(self._ob, attr, val)
+
+# Installed as a global XPCOM function that if exists, will be called
+# to wrap each XPCOM object created.
+def MakeTracer(ob):
+ # In some cases we may be asked to wrap ourself, so handle that.
+ if isinstance(ob, Tracer):
+ return ob
+ return Tracer(ob)
+
+def test():
+ import xpcom.server, xpcom.components
+ xpcom.server.tracer = MakeTracer
+ contractid = "Python.TestComponent"
+ for i in range(100):
+ c = xpcom.components.classes[contractid].createInstance().queryInterface(xpcom.components.interfaces.nsIPythonTestInterface)
+ c.boolean_value = 0
+ a = c.boolean_value
+ c.do_boolean(0,1)
+ print "Finshed"
+ p.print_stats()
+ print "%-30s%s" % ("Attribute Gets", "Number")
+ print "-" * 36
+ for name, num in getters.items():
+ print "%-30s%d" % (name, num)
+ print "%-30s%s" % ("Attribute Sets", "Number")
+ print "-" * 36
+ for name, num in setters.items():
+ print "%-30s%d" % (name, num)
+
+test()
diff --git a/src/libs/xpcom18a4/python/vboxxpcom.py b/src/libs/xpcom18a4/python/vboxxpcom.py
new file mode 100755
index 00000000..56efdabd
--- /dev/null
+++ b/src/libs/xpcom18a4/python/vboxxpcom.py
@@ -0,0 +1,83 @@
+"""
+Copyright (C) 2008-2023 Oracle and/or its affiliates.
+
+This file is part of VirtualBox base platform packages, as
+available from https://www.virtualbox.org.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation, in version 3 of the
+License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses>.
+
+SPDX-License-Identifier: GPL-3.0-only
+"""
+
+import xpcom
+import sys
+import platform
+
+#
+# This code overcomes somewhat unlucky feature of Python, where it searches
+# for binaries in the same place as platfom independent modules, while
+# rest of Python bindings expect _xpcom to be inside xpcom module
+#
+
+_asVBoxPythons = [
+ 'VBoxPython' + str(sys.version_info[0]) + '_' + str(sys.version_info[1]),
+ 'VBoxPython' + str(sys.version_info[0]),
+ 'VBoxPython'
+]
+
+# For Python 3.2 and later use the right ABI flag suffix for the module.
+if sys.hexversion >= 0x030200f0 and sys.abiflags:
+ _asNew = []
+ for sCandidate in _asVBoxPythons:
+ if sCandidate[-1:].isdigit():
+ _asNew.append(sCandidate + sys.abiflags)
+ else:
+ _asNew.append(sCandidate)
+ _asVBoxPythons = _asNew
+ del _asNew
+
+# On platforms where we ship both 32-bit and 64-bit API bindings, we have to
+# look for the right set if we're a 32-bit process.
+if platform.system() in [ 'SunOS', ] and sys.maxsize <= 2**32:
+ _asNew = [ sCandidate + '_x86' for sCandidate in _asVBoxPythons ]
+ _asNew.extend(_asVBoxPythons)
+ _asVBoxPythons = _asNew
+ del _asNew
+
+# On Darwin (aka Mac OS X) we know exactly where things are in a normal
+# VirtualBox installation.
+## @todo Edit this at build time to the actual VBox location set in the make files.
+## @todo We know the location for most hardened builds, not just darwin!
+if platform.system() == 'Darwin':
+ sys.path.append('/Applications/VirtualBox.app/Contents/MacOS')
+
+_oVBoxPythonMod = None
+for m in _asVBoxPythons:
+ try:
+ _oVBoxPythonMod = __import__(m)
+ break
+ except:
+ pass
+ #except Exception as x:
+ # print('m=%s x=%s' % (m, x))
+
+if platform.system() == 'Darwin':
+ sys.path.remove('/Applications/VirtualBox.app/Contents/MacOS')
+
+if _oVBoxPythonMod == None:
+ raise Exception('Cannot find VBoxPython module (tried: %s)' % (', '.join(_asVBoxPythons),))
+
+sys.modules['xpcom._xpcom'] = _oVBoxPythonMod
+xpcom._xpcom = _oVBoxPythonMod
+
diff --git a/src/libs/xpcom18a4/python/xpcom_consts.py b/src/libs/xpcom18a4/python/xpcom_consts.py
new file mode 100644
index 00000000..933f93ef
--- /dev/null
+++ b/src/libs/xpcom18a4/python/xpcom_consts.py
@@ -0,0 +1,272 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Hammond <mhammond@skippinet.com.au> (original author)
+#
+# 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 *****
+
+# Could maybe later have a process that extracted these enums should they change.
+# from nsFileLocations.h
+App_DirectoryBase = 0x00010000
+App_PrefsDirectory30 = App_DirectoryBase + 1
+App_PrefsDirectory40 = App_DirectoryBase + 2
+App_PrefsDirectory50 = App_DirectoryBase + 3
+App_ResDirectory = App_DirectoryBase + 5
+App_UserProfileDirectory30 = App_DirectoryBase + 10
+App_UserProfileDirectory40 = App_DirectoryBase + 11
+App_UserProfileDirectory50 = App_DirectoryBase + 12
+App_DefaultUserProfileRoot30 = App_DirectoryBase + 13
+App_DefaultUserProfileRoot40 = App_DirectoryBase + 14
+App_DefaultUserProfileRoot50 = App_DirectoryBase + 15
+App_ProfileDefaultsFolder30 = App_DirectoryBase + 16
+App_ProfileDefaultsFolder40 = App_DirectoryBase + 17
+App_ProfileDefaultsFolder50 = App_DirectoryBase + 18
+App_PrefDefaultsFolder50 = App_DirectoryBase + 19
+App_DefaultsFolder50 = App_DirectoryBase + 25
+App_ComponentsDirectory = App_DirectoryBase + 30
+App_ChromeDirectory = App_DirectoryBase + 31
+App_PluginsDirectory = App_DirectoryBase + 32
+App_UserChromeDirectory = App_DirectoryBase + 40
+App_FileBase = App_DirectoryBase + 1000
+App_PreferencesFile30 = App_FileBase + 1
+App_PreferencesFile40 = App_FileBase + 2
+App_PreferencesFile50 = App_FileBase + 3
+App_BookmarksFile30 = App_FileBase + 10
+App_BookmarksFile40 = App_FileBase + 11
+App_BookmarksFile50 = App_FileBase + 12
+App_Registry40 = App_FileBase + 20
+App_Registry50 = App_FileBase + 21
+App_LocalStore50 = App_FileBase + 30
+App_History50 = App_FileBase + 40
+App_MailDirectory50 = App_FileBase + 50
+App_ImapMailDirectory50 = App_FileBase + 60
+App_NewsDirectory50 = App_FileBase + 70
+App_MessengerFolderCache50 = App_FileBase + 80
+App_UsersPanels50 = App_FileBase + 90
+App_SearchFile50 = App_FileBase + 100
+App_SearchDirectory50 = App_FileBase + 101
+
+# From nsSpecialSystemDirectory.h
+OS_DriveDirectory = 1
+OS_TemporaryDirectory = 2
+OS_CurrentProcessDirectory= 3
+OS_CurrentWorkingDirectory= 4
+
+XPCOM_CurrentProcessComponentDirectory= 5
+XPCOM_CurrentProcessComponentRegistry= 6
+
+Moz_BinDirectory = 10
+
+Mac_SystemDirectory = 101
+Mac_DesktopDirectory = 102
+Mac_TrashDirectory = 103
+Mac_StartupDirectory = 104
+Mac_ShutdownDirectory = 105
+Mac_AppleMenuDirectory = 106
+Mac_ControlPanelDirectory = 107
+Mac_ExtensionDirectory = 108
+Mac_FontsDirectory = 109
+Mac_PreferencesDirectory = 110
+Mac_DocumentsDirectory = 111
+Mac_InternetSearchDirectory = 112
+
+Win_SystemDirectory = 201
+Win_WindowsDirectory = 202
+
+Win_HomeDirectory = 203
+Win_Desktop = 204
+Win_Programs = 205
+Win_Controls = 206
+Win_Printers = 207
+Win_Personal = 208
+Win_Favorites = 209
+Win_Startup = 210
+Win_Recent = 211
+Win_Sendto = 212
+Win_Bitbucket = 213
+Win_Startmenu = 214
+Win_Desktopdirectory = 215
+Win_Drives = 216
+Win_Network = 217
+Win_Nethood = 218
+Win_Fonts = 219
+Win_Templates = 220
+Win_Common_Startmenu = 221
+Win_Common_Programs = 222
+Win_Common_Startup = 223
+Win_Common_Desktopdirectory = 224
+Win_Appdata = 225
+Win_Printhood = 226
+
+Unix_LocalDirectory = 301
+Unix_LibDirectory = 302
+Unix_HomeDirectory = 303
+
+BeOS_SettingsDirectory = 401
+BeOS_HomeDirectory = 402
+BeOS_DesktopDirectory = 403
+BeOS_SystemDirectory = 404
+
+OS2_SystemDirectory = 501
+
+# Type/Variant related constants.
+TD_INT8 = 0
+TD_INT16 = 1
+TD_INT32 = 2
+TD_INT64 = 3
+TD_UINT8 = 4
+TD_UINT16 = 5
+TD_UINT32 = 6
+TD_UINT64 = 7
+TD_FLOAT = 8
+TD_DOUBLE = 9
+TD_BOOL = 10
+TD_CHAR = 11
+TD_WCHAR = 12
+TD_VOID = 13
+TD_PNSIID = 14
+TD_DOMSTRING = 15
+TD_PSTRING = 16
+TD_PWSTRING = 17
+TD_INTERFACE_TYPE = 18
+TD_INTERFACE_IS_TYPE = 19
+TD_ARRAY = 20
+TD_PSTRING_SIZE_IS = 21
+TD_PWSTRING_SIZE_IS = 22
+TD_UTF8STRING = 23
+TD_CSTRING = 24
+TD_ASTRING = 25
+
+# From xpt_struct.h
+XPT_TDP_POINTER = 0x80
+XPT_TDP_UNIQUE_POINTER = 0x40
+XPT_TDP_REFERENCE = 0x20
+XPT_TDP_FLAGMASK = 0xe0
+XPT_TDP_TAGMASK = (~XPT_TDP_FLAGMASK)
+def XPT_TDP_TAG(tdp): return (tdp & XPT_TDP_TAGMASK)
+
+def XPT_TDP_IS_POINTER(flags): return (flags & XPT_TDP_POINTER)
+def XPT_TDP_IS_UNIQUE_POINTER(flags): return (flags & XPT_TDP_UNIQUE_POINTER)
+def XPT_TDP_IS_REFERENCE(flags): return (flags & XPT_TDP_REFERENCE)
+
+XPT_ID_SCRIPTABLE = 0x80
+XPT_ID_FLAGMASK = 0x80
+XPT_ID_TAGMASK = ~XPT_ID_FLAGMASK
+def XPT_ID_TAG(id): return id & XPT_ID_TAGMASK
+
+def XPT_ID_IS_SCRIPTABLE(flags): return flags & XPT_ID_SCRIPTABLE
+
+XPT_PD_IN = 0x80
+XPT_PD_OUT = 0x40
+XPT_PD_RETVAL = 0x20
+XPT_PD_SHARED = 0x10
+XPT_PD_DIPPER = 0x08
+XPT_PD_FLAGMASK = 0xf0
+
+def XPT_PD_IS_IN(flags): return (flags & XPT_PD_IN)
+def XPT_PD_IS_OUT(flags): return (flags & XPT_PD_OUT)
+def XPT_PD_IS_RETVAL(flags): return (flags & XPT_PD_RETVAL)
+def XPT_PD_IS_SHARED(flags): return (flags & XPT_PD_SHARED)
+def XPT_PD_IS_DIPPER(flags): return (flags & XPT_PD_DIPPER)
+
+XPT_MD_GETTER = 0x80
+XPT_MD_SETTER = 0x40
+XPT_MD_NOTXPCOM = 0x20
+XPT_MD_CTOR = 0x10
+XPT_MD_HIDDEN = 0x08
+XPT_MD_FLAGMASK = 0xf8
+
+def XPT_MD_IS_GETTER(flags): return (flags & XPT_MD_GETTER)
+def XPT_MD_IS_SETTER(flags): return (flags & XPT_MD_SETTER)
+def XPT_MD_IS_NOTXPCOM(flags): return (flags & XPT_MD_NOTXPCOM)
+def XPT_MD_IS_CTOR(flags): return (flags & XPT_MD_CTOR)
+def XPT_MD_IS_HIDDEN(flags): return (flags & XPT_MD_HIDDEN)
+
+# From xptinfo.h
+
+T_I8 = TD_INT8
+T_I16 = TD_INT16
+T_I32 = TD_INT32
+T_I64 = TD_INT64
+T_U8 = TD_UINT8
+T_U16 = TD_UINT16
+T_U32 = TD_UINT32
+T_U64 = TD_UINT64
+T_FLOAT = TD_FLOAT
+T_DOUBLE = TD_DOUBLE
+T_BOOL = TD_BOOL
+T_CHAR = TD_CHAR
+T_WCHAR = TD_WCHAR
+T_VOID = TD_VOID
+T_IID = TD_PNSIID
+T_DOMSTRING = TD_DOMSTRING
+T_CHAR_STR = TD_PSTRING
+T_WCHAR_STR = TD_PWSTRING
+T_INTERFACE = TD_INTERFACE_TYPE
+T_INTERFACE_IS = TD_INTERFACE_IS_TYPE
+T_ARRAY = TD_ARRAY
+T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS
+T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS
+T_UTF8STRING = TD_UTF8STRING
+T_CSTRING = TD_CSTRING
+T_ASTRING = TD_ASTRING
+
+# from nsIVariant
+VTYPE_INT8 = 0
+VTYPE_INT16 = 1
+VTYPE_INT32 = 2
+VTYPE_INT64 = 3
+VTYPE_UINT8 = 4
+VTYPE_UINT16 = 5
+VTYPE_UINT32 = 6
+VTYPE_UINT64 = 7
+VTYPE_FLOAT = 8
+VTYPE_DOUBLE = 9
+VTYPE_BOOL = 10
+VTYPE_CHAR = 11
+VTYPE_WCHAR = 12
+VTYPE_VOID = 13
+VTYPE_ID = 14
+VTYPE_DOMSTRING = 15
+VTYPE_CHAR_STR = 16
+VTYPE_WCHAR_STR = 17
+VTYPE_INTERFACE = 18
+VTYPE_INTERFACE_IS = 19
+VTYPE_ARRAY = 20
+VTYPE_STRING_SIZE_IS = 21
+VTYPE_WSTRING_SIZE_IS = 22
+VTYPE_UTF8STRING = 23
+VTYPE_CSTRING = 24
+VTYPE_ASTRING = 25
+VTYPE_EMPTY_ARRAY = 254
+VTYPE_EMPTY = 255
diff --git a/src/libs/xpcom18a4/python/xpt.py b/src/libs/xpcom18a4/python/xpt.py
new file mode 100755
index 00000000..67021572
--- /dev/null
+++ b/src/libs/xpcom18a4/python/xpt.py
@@ -0,0 +1,471 @@
+# ***** 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 Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# David Ascher <DavidA@ActiveState.com> (original author)
+# Mark Hammond <mhammond@skippinet.com.au>
+#
+# 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 *****
+
+"""
+Program: xpt.py
+
+Task: describe interfaces etc using XPCOM reflection.
+
+Subtasks:
+ output (nearly) exactly the same stuff as xpt_dump, for verification
+ output Python source code that can be used as a template for an interface
+
+Status: Works pretty well if you ask me :-)
+
+Author:
+ David Ascher did an original version that parsed XPT files
+ directly. Mark Hammond changed it to use the reflection interfaces,
+ but kept most of the printing logic.
+
+
+Revision:
+
+ 0.1: March 6, 2000
+ 0.2: April 2000 - Mark removed lots of Davids lovely parsing code in favour
+ of the new xpcom interfaces that provide this info.
+
+ May 2000 - Moved into Perforce - track the log there!
+ Early 2001 - Moved into the Mozilla CVS tree - track the log there!
+
+Todo:
+ Fill out this todo list.
+
+"""
+
+import string, sys
+import xpcom
+import xpcom._xpcom
+
+from .xpcom_consts import *
+
+class Interface:
+ def __init__(self, iid):
+ iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
+ if hasattr(iid, "upper"): # Is it a stringy thing.
+ item = iim.GetInfoForName(iid)
+ else:
+ item = iim.GetInfoForIID(iid)
+ self.interface_info = item
+ self.namespace = "" # where does this come from?
+ self.methods = Methods(item)
+ self.constants = Constants(item)
+
+ # delegate attributes to the real interface
+ def __getattr__(self, attr):
+ return getattr(self.interface_info, attr)
+
+ def GetParent(self):
+ try:
+ raw_parent = self.interface_info.GetParent()
+ if raw_parent is None:
+ return None
+ return Interface(raw_parent.GetIID())
+ except xpcom.Exception:
+ # Parent interface is probably not scriptable - assume nsISupports.
+ if xpcom.verbose:
+ # The user may be confused as to why this is happening!
+ print("The parent interface of IID '%s' can not be located - assuming nsISupports")
+ return Interface(xpcom._xpcom.IID_nsISupports)
+
+ def Describe_Python(self):
+ method_reprs = []
+ methods = [m for m in self.methods if not m.IsNotXPCOM()]
+ for m in methods:
+ method_reprs.append(m.Describe_Python())
+ method_joiner = "\n"
+ methods_repr = method_joiner.join(method_reprs)
+ return \
+"""class %s:
+ _com_interfaces_ = xpcom.components.interfaces.%s
+ # If this object needs to be registered, the following 2 are also needed.
+ # _reg_clsid_ = "{a new clsid generated for this object}"
+ # _reg_contractid_ = "The.Object.Name"\n%s""" % (self.GetName(), self.GetIID().name, methods_repr)
+
+ def Describe(self):
+ # Make the IID look like xtp_dump - "(" instead of "{"
+ iid_use = "(" + str(self.GetIID())[1:-1] + ")"
+ s = ' - '+self.namespace+'::'+ self.GetName() + ' ' + iid_use + ':\n'
+
+ parent = self.GetParent()
+ if parent is not None:
+ s = s + ' Parent: ' + parent.namespace + '::' + parent.GetName() + '\n'
+ s = s + ' Flags:\n'
+ if self.IsScriptable(): word = 'TRUE'
+ else: word = 'FALSE'
+ s = s + ' Scriptable: ' + word + '\n'
+ s = s + ' Methods:\n'
+ methods = [m for m in self.methods if not m.IsNotXPCOM()]
+ if len(methods):
+ for m in methods:
+ s = s + ' ' + m.Describe() + '\n'
+ else:
+ s = s + ' No Methods\n'
+ s = s + ' Constants:\n'
+ if self.constants:
+ for c in self.constants:
+ s = s + ' ' + c.Describe() + '\n'
+ else:
+ s = s + ' No Constants\n'
+
+ return s
+
+# A class that allows caching and iterating of methods.
+class Methods:
+ def __init__(self, interface_info):
+ self.interface_info = interface_info
+ try:
+ self.items = [None] * interface_info.GetMethodCount()
+ except xpcom.Exception:
+ if xpcom.verbose:
+ print("** GetMethodCount failed?? - assuming no methods")
+ self.items = []
+ def __len__(self):
+ return len(self.items)
+ def __getitem__(self, index):
+ ret = self.items[index]
+ if ret is None:
+ mi = self.interface_info.GetMethodInfo(index)
+ ret = self.items[index] = Method(mi, index, self.interface_info)
+ return ret
+
+class Method:
+
+ def __init__(self, method_info, method_index, interface_info = None):
+ self.interface_info = interface_info
+ self.method_index = method_index
+ self.flags, self.name, param_descs, self.result_desc = method_info
+ # Build the params.
+ self.params = []
+ pi=0
+ for pd in param_descs:
+ self.params.append( Parameter(pd, pi, method_index, interface_info) )
+ pi = pi + 1
+ # Run over the params setting the "sizeof" params to hidden.
+ for p in self.params:
+ td = p.type_desc
+ tag = XPT_TDP_TAG(td[0])
+ if tag==T_ARRAY and p.IsIn():
+ self.params[td[1]].hidden_indicator = 2
+ elif tag in [T_PSTRING_SIZE_IS, T_PWSTRING_SIZE_IS] and p.IsIn():
+ self.params[td[1]].hidden_indicator = 1
+
+ def IsGetter(self):
+ return (self.flags & XPT_MD_GETTER)
+ def IsSetter(self):
+ return (self.flags & XPT_MD_SETTER)
+ def IsNotXPCOM(self):
+ return (self.flags & XPT_MD_NOTXPCOM)
+ def IsConstructor(self):
+ return (self.flags & XPT_MD_CTOR)
+ def IsHidden(self):
+ return (self.flags & XPT_MD_HIDDEN)
+
+ def Describe_Python(self):
+ if self.method_index < 3: # Ignore QI etc
+ return ""
+ base_name = self.name
+ if self.IsGetter():
+ name = "get_%s" % (base_name,)
+ elif self.IsSetter():
+ name = "set_%s" % (base_name,)
+ else:
+ name = base_name
+ param_decls = ["self"]
+ in_comments = []
+ out_descs = []
+ result_comment = "Result: void - None"
+ for p in self.params:
+ in_desc, in_desc_comments, out_desc, this_result_comment = p.Describe_Python()
+ if in_desc is not None:
+ param_decls.append(in_desc)
+ if in_desc_comments is not None:
+ in_comments.append(in_desc_comments)
+ if out_desc is not None:
+ out_descs.append(out_desc)
+ if this_result_comment is not None:
+ result_comment = this_result_comment
+ joiner = "\n # "
+ in_comment = out_desc = ""
+ if in_comments: in_comment = joiner + joiner.join(in_comments)
+ if out_descs: out_desc = joiner + joiner.join(out_descs)
+
+ return """ def %s( %s ):
+ # %s%s%s
+ pass""" % (name, ", ".join(param_decls), result_comment, in_comment, out_desc)
+
+ def Describe(self):
+ s = ''
+ if self.IsGetter():
+ G = 'G'
+ else:
+ G = ' '
+ if self.IsSetter():
+ S = 'S'
+ else: S = ' '
+ if self.IsHidden():
+ H = 'H'
+ else:
+ H = ' '
+ if self.IsNotXPCOM():
+ N = 'N'
+ else:
+ N = ' '
+ if self.IsConstructor():
+ C = 'C'
+ else:
+ C = ' '
+
+ def desc(a): return a.Describe()
+ method_desc = string.join(list(map(desc, self.params)), ', ')
+ result_type = TypeDescriber(self.result_desc[0], None)
+ return_desc = result_type.Describe()
+ i = string.find(return_desc, 'retval ')
+ if i != -1:
+ return_desc = return_desc[:i] + return_desc[i+len('retval '):]
+ return G+S+H+N+C+' '+return_desc+' '+self.name + '('+ method_desc + ');'
+
+class Parameter:
+ def __init__(self, param_desc, param_index, method_index, interface_info = None):
+ self.param_flags, self.type_desc = param_desc
+ self.hidden_indicator = 0 # Is this a special "size" type param that will be hidden from Python?
+ self.param_index = param_index
+ self.method_index= method_index
+ self.interface_info = interface_info
+ def __repr__(self):
+ return "<param %(param_index)d (method %(method_index)d) - flags = 0x%(param_flags)x, type = %(type_desc)s>" % self.__dict__
+ def IsIn(self):
+ return XPT_PD_IS_IN(self.param_flags)
+ def IsOut(self):
+ return XPT_PD_IS_OUT(self.param_flags)
+ def IsInOut(self):
+ return self.IsIn() and self.IsOut()
+ def IsRetval(self):
+ return XPT_PD_IS_RETVAL(self.param_flags)
+ def IsShared(self):
+ return XPT_PD_IS_SHARED(self.param_flags)
+ def IsDipper(self):
+ return XPT_PD_IS_DIPPER(self.param_flags)
+
+ def Describe_Python(self):
+ name = "param%d" % (self.param_index,)
+ if self.hidden_indicator:
+ # Could remove the comment - Im trying to tell the user where that param has
+ # gone from the signature!
+ return None, "%s is a hidden parameter" % (name,), None, None
+ t = TypeDescriber(self.type_desc[0], self)
+ decl = in_comment = out_comment = result_comment = None
+ type_desc = t.Describe()
+ if self.IsIn() and not self.IsDipper():
+ decl = name
+ extra=""
+ if self.IsOut():
+ extra = "Out"
+ in_comment = "In%s: %s: %s" % (extra, name, type_desc)
+ elif self.IsOut() or self.IsDipper():
+ if self.IsRetval():
+ result_comment = "Result: %s" % (type_desc,)
+ else:
+ out_comment = "Out: %s" % (type_desc,)
+ return decl, in_comment, out_comment, result_comment
+
+ def Describe(self):
+ parts = []
+ if self.IsInOut():
+ parts.append('inout')
+ elif self.IsIn():
+ parts.append('in')
+ elif self.IsOut():
+ parts.append('out')
+
+ if self.IsDipper(): parts.append("dipper")
+ if self.IsRetval(): parts.append('retval')
+ if self.IsShared(): parts.append('shared')
+ t = TypeDescriber(self.type_desc[0], self)
+ type_str = t.Describe()
+ parts.append(type_str)
+ return string.join(parts)
+
+# A class that allows caching and iterating of constants.
+class Constants:
+ def __init__(self, interface_info):
+ self.interface_info = interface_info
+ try:
+ self.items = [None] * interface_info.GetConstantCount()
+ except xpcom.Exception:
+ if xpcom.verbose:
+ print("** GetConstantCount failed?? - assuming no constants")
+ self.items = []
+ def __len__(self):
+ return len(self.items)
+ def __getitem__(self, index):
+ ret = self.items[index]
+ if ret is None:
+ ci = self.interface_info.GetConstant(index)
+ ret = self.items[index] = Constant(ci)
+ return ret
+
+class Constant:
+ def __init__(self, ci):
+ self.name, self.type, self.value = ci
+
+ def Describe(self):
+ return TypeDescriber(self.type, None).Describe() + ' ' +self.name+' = '+str(self.value)+';'
+
+ __str__ = Describe
+
+def MakeReprForInvoke(param):
+ tag = param.type_desc[0] & XPT_TDP_TAGMASK
+ if tag == T_INTERFACE:
+ i_info = param.interface_info
+ try:
+ iid = i_info.GetIIDForParam(param.method_index, param.param_index)
+ except xpcom.Exception:
+ # IID not available (probably not scriptable) - just use nsISupports.
+ iid = xpcom._xpcom.IID_nsISupports
+ return param.type_desc[0], 0, 0, str(iid)
+ elif tag == T_ARRAY:
+ i_info = param.interface_info
+ array_desc = i_info.GetTypeForParam(param.method_index, param.param_index, 1)
+ return param.type_desc[:-1] + array_desc[:1]
+ return param.type_desc
+
+
+class TypeDescriber:
+ def __init__(self, type_flags, param):
+ self.type_flags = type_flags
+ self.tag = XPT_TDP_TAG(self.type_flags)
+ self.param = param
+ def IsPointer(self):
+ return XPT_TDP_IS_POINTER(self.type_flags)
+ def IsUniquePointer(self):
+ return XPT_TDP_IS_UNIQUE_POINTER(self.type_flags)
+ def IsReference(self):
+ return XPT_TDP_IS_REFERENCE(self.type_flags)
+ def repr_for_invoke(self):
+ return (self.type_flags,)
+ def GetName(self):
+ is_ptr = self.IsPointer()
+ data = type_info_map.get(self.tag)
+ if data is None:
+ data = ("unknown",)
+ if self.IsReference():
+ if len(data) > 2:
+ return data[2]
+ return data[0] + " &"
+ if self.IsPointer():
+ if len(data)>1:
+ return data[1]
+ return data[0] + " *"
+ return data[0]
+
+ def Describe(self):
+ if self.tag == T_ARRAY:
+ # NOTE - Adding a type specifier to the array is different from xpt_dump.exe
+ if self.param is None or self.param.interface_info is None:
+ type_desc = "" # Dont have explicit info about the array type :-(
+ else:
+ i_info = self.param.interface_info
+ type_code = i_info.GetTypeForParam(self.param.method_index, self.param.param_index, 1)
+ type_desc = TypeDescriber( type_code[0], None).Describe()
+ return self.GetName() + "[" + type_desc + "]"
+ elif self.tag == T_INTERFACE:
+ if self.param is None or self.param.interface_info is None:
+ return "nsISomething" # Dont have explicit info about the IID :-(
+ i_info = self.param.interface_info
+ m_index = self.param.method_index
+ p_index = self.param.param_index
+ try:
+ iid = i_info.GetIIDForParam(m_index, p_index)
+ return iid.name
+ except xpcom.Exception:
+ return "nsISomething"
+ return self.GetName()
+
+# These are just for output purposes, so should be
+# the same as xpt_dump uses
+type_info_map = {
+ T_I8 : ("int8",),
+ T_I16 : ("int16",),
+ T_I32 : ("int32",),
+ T_I64 : ("int64",),
+ T_U8 : ("uint8",),
+ T_U16 : ("uint16",),
+ T_U32 : ("uint32",),
+ T_U64 : ("uint64",),
+ T_FLOAT : ("float",),
+ T_DOUBLE : ("double",),
+ T_BOOL : ("boolean",),
+ T_CHAR : ("char",),
+ T_WCHAR : ("wchar_t", "wstring"),
+ T_VOID : ("void",),
+ T_IID : ("reserved", "nsIID *", "nsIID &"),
+ T_DOMSTRING : ("DOMString",),
+ T_CHAR_STR : ("reserved", "string"),
+ T_WCHAR_STR : ("reserved", "wstring"),
+ T_INTERFACE : ("reserved", "Interface"),
+ T_INTERFACE_IS : ("reserved", "InterfaceIs *"),
+ T_ARRAY : ("reserved", "Array"),
+ T_PSTRING_SIZE_IS : ("reserved", "string_s"),
+ T_PWSTRING_SIZE_IS : ("reserved", "wstring_s"),
+}
+
+def dump_interface(iid, mode):
+ interface = Interface(iid)
+ describer_name = "Describe"
+ if mode == "xptinfo": mode = None
+ if mode is not None:
+ describer_name = describer_name + "_" + mode.capitalize()
+ describer = getattr(interface, describer_name)
+ print(describer())
+
+if __name__=='__main__':
+ if len(sys.argv) == 1:
+ print("Usage: xpt.py [-xptinfo] interface_name, ...")
+ print(" -info: Dump in a style similar to the xptdump tool")
+ print("Dumping nsISupports and nsIInterfaceInfo")
+ sys.argv.append('nsIInterfaceInfo')
+ sys.argv.append('-xptinfo')
+ sys.argv.append('nsISupports')
+ sys.argv.append('nsIInterfaceInfo')
+
+ mode = "Python"
+ for i in sys.argv[1:]:
+ if i[0] == "-":
+ mode = i[1:]
+ else:
+ dump_interface(i, mode)
diff --git a/src/libs/xpcom18a4/vboxdeps.cpp b/src/libs/xpcom18a4/vboxdeps.cpp
new file mode 100644
index 00000000..37f70bba
--- /dev/null
+++ b/src/libs/xpcom18a4/vboxdeps.cpp
@@ -0,0 +1,75 @@
+/* The usual story: drag stuff from the libraries into the link. */
+
+
+#include <plstr.h>
+#include <prio.h>
+#include <nsDeque.h>
+#include <nsHashSets.h>
+#include <nsIPipe.h>
+#include <xptcall.h>
+#include <nsProxyRelease.h>
+#include "xpcom/proxy/src/nsProxyEventPrivate.h"
+#include "nsTraceRefcnt.h"
+#include "nsDebug.h"
+
+uintptr_t deps[] =
+{
+ (uintptr_t)PL_strncpy,
+ (uintptr_t)PL_strchr,
+ (uintptr_t)PL_strncpyz,
+ (uintptr_t)PL_HashString,
+ (uintptr_t)PR_DestroyPollableEvent,
+ (uintptr_t)NS_NewPipe2,
+ (uintptr_t)NS_ProxyRelease,
+ (uintptr_t)nsTraceRefcnt::LogRelease,
+ (uintptr_t)nsDebug::Assertion,
+ 0
+};
+
+class foobardep : public nsXPTCStubBase
+{
+public:
+ NS_IMETHOD_(nsrefcnt) AddRef(void)
+ {
+ return 1;
+ }
+
+ NS_IMETHOD_(nsrefcnt) Release(void)
+ {
+ return 0;
+ }
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info)
+ {
+ (void)info;
+ return 0;
+ }
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params)
+ {
+ (void)methodIndex;
+ (void)info;
+ (void)params;
+ return 0;
+ }
+
+};
+
+
+
+void foodep(void)
+{
+ nsVoidHashSetSuper *a = new nsVoidHashSetSuper();
+ a->Init(123);
+ nsDeque *b = new nsDeque((nsDequeFunctor*)0);
+
+ //nsXPTCStubBase
+ nsProxyEventObject *c = new nsProxyEventObject();
+ c->Release();
+
+ foobardep *d = new foobardep();
+ nsXPTCStubBase *e = d;
+ e->Release();
+}
+
diff --git a/src/libs/xpcom18a4/xpcom-config.h b/src/libs/xpcom18a4/xpcom-config.h
new file mode 100644
index 00000000..ee34a6d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom-config.h
@@ -0,0 +1,69 @@
+/* xpcom/xpcom-config.h. Generated automatically by configure. */
+/* Global defines needed by xpcom clients */
+
+#ifndef _XPCOM_CONFIG_H_
+#define _XPCOM_CONFIG_H_
+
+/* Define this to throw() if the compiler complains about
+ * constructors returning NULL
+ */
+#define CPP_THROW_NEW throw()
+
+/* Define if the c++ compiler supports a 2-byte wchar_t */
+#define HAVE_CPP_2BYTE_WCHAR_T 1
+
+/* Define if the c++ compiler supports changing access with |using| */
+#define HAVE_CPP_ACCESS_CHANGING_USING 1
+
+/* Define if the c++ compiler can resolve ambiguity with |using| */
+#define HAVE_CPP_AMBIGUITY_RESOLVING_USING 1
+
+/* Define if the c++ compiler has builtin Bool type */
+/* #undef HAVE_CPP_BOOL */
+
+/* Define if a dyanmic_cast to void* gives the most derived object */
+#define HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR 1
+
+/* Define if the c++ compiler supports the |explicit| keyword */
+#define HAVE_CPP_EXPLICIT 1
+
+/* Define if the c++ compiler supports the modern template
+ * specialization syntax
+ */
+#define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX 1
+
+/* Define if the c++ compiler supports the |std| namespace */
+#define HAVE_CPP_NAMESPACE_STD 1
+
+/* Define if the c++ compiler supports reinterpret_cast */
+#define HAVE_CPP_NEW_CASTS 1
+
+/* Define if the c++ compiler supports partial template specialization */
+#define HAVE_CPP_PARTIAL_SPECIALIZATION 1
+
+/* Define if the c++ compiler has trouble comparing a constant
+ * reference to a templatized class to zero
+ */
+/* #undef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO */
+
+/* Define if the c++ compiler supports the |typename| keyword */
+#define HAVE_CPP_TYPENAME 1
+
+/* Define if the stanard template operator!=() is ambiguous */
+#define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL 1
+
+/* Define if statvfs() is available */
+#define HAVE_STATVFS 1
+
+/* Define if the c++ compiler requires implementations of
+ * unused virtual methods
+ */
+#define NEED_CPP_UNUSED_IMPLEMENTATIONS 1
+
+/* Define to either <new> or <new.h> */
+#define NEW_H <new>
+
+/* Define if binary compatibility with Mozilla 1.x string code is desired */
+#define MOZ_V1_STRING_ABI 1
+
+#endif /* _XPCOM_CONFIG_H_ */
diff --git a/src/libs/xpcom18a4/xpcom-namespace-cleanup.map b/src/libs/xpcom18a4/xpcom-namespace-cleanup.map
new file mode 100644
index 00000000..2488ca1a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom-namespace-cleanup.map
@@ -0,0 +1,34 @@
+# GNU ld version script, for linux
+# Gets rid of all non-prefixed non-C++ global symbols. They cause problem if
+# VirtualBox drags in the system-provided nspr library or some other code from
+# the Mozilla project. VirtualBox shouldn't pollute the namespace.
+
+#
+# Copyright (C) 2008-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+{
+ global:
+ _Z*; VBoxNs*;
+ __bss_start; _edata; _end; _fini; _init;
+ local:
+ *;
+};
diff --git a/src/libs/xpcom18a4/xpcom-private.h b/src/libs/xpcom18a4/xpcom-private.h
new file mode 100644
index 00000000..e0721fae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom-private.h
@@ -0,0 +1,32 @@
+/* xpcom/xpcom-private.h. Generated automatically by configure. */
+/* The following defines are only used by the xpcom implementation */
+
+#ifndef _XPCOM_PRIVATE_H_
+#define _XPCOM_PRIVATE_H_
+
+/* Define to build the static component loader */
+#define ENABLE_STATIC_COMPONENT_LOADER 1
+
+/* Define if getpagesize() is available */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if iconv() is available */
+#define HAVE_ICONV 1
+
+/* Define if iconv() supports const input */
+/* #undef HAVE_ICONV_WITH_CONST_INPUT */
+
+/* Define if mbrtowc() is available */
+#define HAVE_MBRTOWC 1
+
+/* Define if <sys/mount.h> is present */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define if <sys/vfs.h> is present */
+#define HAVE_SYS_VFS_H 1
+
+/* Define if wcrtomb() is available */
+#define HAVE_WCRTOMB 1
+
+#endif /* _XPCOM_PRIVATE_H_ */
+
diff --git a/src/libs/xpcom18a4/xpcom/.cvsignore b/src/libs/xpcom18a4/xpcom/.cvsignore
new file mode 100644
index 00000000..34b091a9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+xpcom-config.h
+xpcom-private.h
diff --git a/src/libs/xpcom18a4/xpcom/Makefile.in b/src/libs/xpcom18a4/xpcom/Makefile.in
new file mode 100644
index 00000000..8bfe9abe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/Makefile.in
@@ -0,0 +1,84 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+GRE_MODULE = 1
+
+DIRS = \
+ MoreFiles \
+ typelib \
+ string \
+ glue \
+ base \
+ ds \
+ io \
+ components \
+ threads \
+ reflect \
+ proxy \
+ build \
+ tools \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef MOZ_DEBUG
+DIRS += windbgdlg
+endif
+endif
+
+ifdef ENABLE_TESTS
+DIRS += \
+ tests \
+ sample \
+ typelib/xpt/tests \
+ reflect/xptinfo/tests \
+ reflect/xptcall/tests \
+ proxy/tests
+endif
+
+# xpcom-config.h is generated by configure
+SDK_HEADERS = xpcom-config.h
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/Makefile.kup b/src/libs/xpcom18a4/xpcom/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore b/src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in b/src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in
new file mode 100644
index 00000000..56d89456
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in
@@ -0,0 +1,70 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = macmorefiles
+REQUIRES =
+
+# ifeq for standalone builds
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+
+LIBRARY_NAME = macmorefiles_s
+
+CSRCS = \
+ MoreFilesX.c \
+ FSCopyObject.c \
+ $(NULL)
+
+EXPORTS += \
+ MoreFilesX.h \
+ FSCopyObject.h \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a
+# static lib.
+FORCE_STATIC_LIB=1
+FORCE_USE_PIC=1
+
+endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c
new file mode 100644
index 00000000..d1b7af9e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c
@@ -0,0 +1,2765 @@
+/*
+ File: MoreFilesX.c
+
+ Contains: A collection of useful high-level File Manager routines
+ which use the HFS Plus APIs wherever possible.
+
+ Version: MoreFilesX 1.0.1
+
+
+*/
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+// Modified 2006-01-23 - added this comment.
+
+#if defined(__MACH__)
+ #include <Carbon/Carbon.h>
+ #include <string.h>
+#else
+ #include <Carbon.h>
+ #include <string.h>
+#endif
+
+#include "MoreFilesX.h"
+
+/* Set BuildingMoreFilesXForMacOS9 to 1 if building for Mac OS 9 */
+#ifndef BuildingMoreFilesXForMacOS9
+ #define BuildingMoreFilesXForMacOS9 0
+#endif
+
+/*****************************************************************************/
+
+#pragma mark ----- Local type definitions -----
+
+struct FSIterateContainerGlobals
+{
+ IterateContainerFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
+ FSCatalogInfoBitmap whichInfo; /* fields of the CatalogInfo to get */
+ FSCatalogInfo catalogInfo; /* FSCatalogInfo */
+ FSRef ref; /* FSRef */
+ FSSpec spec; /* FSSpec */
+ FSSpec *specPtr; /* pointer to spec field, or NULL */
+ HFSUniStr255 name; /* HFSUniStr255 */
+ HFSUniStr255 *namePtr; /* pointer to name field, or NULL */
+ void *yourDataPtr; /* a pointer to caller supplied data the filter may need to access */
+ ItemCount maxLevels; /* maximum levels to iterate through */
+ ItemCount currentLevel; /* the current level FSIterateContainerLevel is on */
+ Boolean quitFlag; /* set to true if filter wants to kill interation */
+ Boolean containerChanged; /* temporary - set to true if the current container changed during iteration */
+ OSErr result; /* result */
+ ItemCount actualObjects; /* number of objects returned */
+};
+typedef struct FSIterateContainerGlobals FSIterateContainerGlobals;
+
+struct FSDeleteContainerGlobals
+{
+ OSErr result; /* result */
+ ItemCount actualObjects; /* number of objects returned */
+ FSCatalogInfo catalogInfo; /* FSCatalogInfo */
+};
+typedef struct FSDeleteContainerGlobals FSDeleteContainerGlobals;
+
+/*****************************************************************************/
+
+#pragma mark ----- Local prototypes -----
+
+static
+void
+FSDeleteContainerLevel(
+ const FSRef *container,
+ FSDeleteContainerGlobals *theGlobals);
+
+static
+void
+FSIterateContainerLevel(
+ FSIterateContainerGlobals *theGlobals);
+
+static
+OSErr
+GenerateUniqueHFSUniStr(
+ long *startSeed,
+ const FSRef *dir1,
+ const FSRef *dir2,
+ HFSUniStr255 *uniqueName);
+
+/*****************************************************************************/
+
+#pragma mark ----- File Access Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFork(
+ SInt16 srcRefNum,
+ SInt16 dstRefNum,
+ void *copyBufferPtr,
+ ByteCount copyBufferSize)
+{
+ OSErr srcResult;
+ OSErr dstResult;
+ OSErr result;
+ SInt64 forkSize;
+ ByteCount readActualCount;
+
+ /* check input parameters */
+ require_action((NULL != copyBufferPtr) && (0 != copyBufferSize), BadParameter, result = paramErr);
+
+ /* get source fork size */
+ result = FSGetForkSize(srcRefNum, &forkSize);
+ require_noerr(result, SourceFSGetForkSizeFailed);
+
+ /* allocate disk space for destination fork */
+ result = FSSetForkSize(dstRefNum, fsFromStart, forkSize);
+ require_noerr(result, DestinationFSSetForkSizeFailed);
+
+ /* reset source fork's position to 0 */
+ result = FSSetForkPosition(srcRefNum, fsFromStart, 0);
+ require_noerr(result, SourceFSSetForkPositionFailed);
+
+ /* reset destination fork's position to 0 */
+ result = FSSetForkPosition(dstRefNum, fsFromStart, 0);
+ require_noerr(result, DestinationFSSetForkPositionFailed);
+
+ /* If copyBufferSize is greater than 4K bytes, make it a multiple of 4k bytes */
+ /* This will make writes on local volumes faster */
+ if ( (copyBufferSize >= 0x00001000) && ((copyBufferSize & 0x00000fff) != 0) )
+ {
+ copyBufferSize &= ~(0x00001000 - 1);
+ }
+
+ /* copy source to destination */
+ srcResult = dstResult = noErr;
+ while ( (noErr == srcResult) && (noErr == dstResult) )
+ {
+ srcResult = FSReadFork(srcRefNum, fsAtMark + noCacheMask, 0, copyBufferSize, copyBufferPtr, &readActualCount);
+ dstResult = FSWriteFork(dstRefNum, fsAtMark + noCacheMask, 0, readActualCount, copyBufferPtr, NULL);
+ }
+
+ /* make sure there were no errors at the destination */
+ require_noerr_action(dstResult, DestinationFSWriteForkFailed, result = dstResult);
+
+ /* make sure the error at the source was eofErr */
+ require_action(eofErr == srcResult, SourceResultNotEofErr, result = srcResult);
+
+ /* everything went as expected */
+ result = noErr;
+
+SourceResultNotEofErr:
+DestinationFSWriteForkFailed:
+DestinationFSSetForkPositionFailed:
+SourceFSSetForkPositionFailed:
+DestinationFSSetForkSizeFailed:
+SourceFSGetForkSizeFailed:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Volume Access Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolParms(
+ FSVolumeRefNum volRefNum,
+ UInt32 bufferSize,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ UInt32 *actualInfoSize)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action((NULL != volParmsInfo) && (NULL != actualInfoSize),
+ BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
+ pb.ioParam.ioReqCount = (SInt32)bufferSize;
+ result = PBHGetVolParmsSync(&pb);
+ require_noerr(result, PBHGetVolParmsSync);
+
+ /* return number of bytes the file system returned in volParmsInfo buffer */
+ *actualInfoSize = (UInt32)pb.ioParam.ioActCount;
+
+PBHGetVolParmsSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVRefNum(
+ const FSRef *ref,
+ FSVolumeRefNum *vRefNum)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != vRefNum, BadParameter, result = paramErr);
+
+ /* get the volume refNum from the FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* return volume refNum from catalogInfo */
+ *vRefNum = catalogInfo.volume;
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVInfo(
+ FSVolumeRefNum volume,
+ HFSUniStr255 *volumeName, /* can be NULL */
+ UInt64 *freeBytes, /* can be NULL */
+ UInt64 *totalBytes) /* can be NULL */
+{
+ OSErr result;
+ FSVolumeInfo info;
+
+ /* ask for the volume's sizes only if needed */
+ result = FSGetVolumeInfo(volume, 0, NULL,
+ (((NULL != freeBytes) || (NULL != totalBytes)) ? kFSVolInfoSizes : kFSVolInfoNone),
+ &info, volumeName, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( NULL != freeBytes )
+ {
+ *freeBytes = info.freeBytes;
+ }
+ if ( NULL != totalBytes )
+ {
+ *totalBytes = info.totalBytes;
+ }
+
+FSGetVolumeInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolFileSystemID(
+ FSVolumeRefNum volume,
+ UInt16 *fileSystemID, /* can be NULL */
+ UInt16 *signature) /* can be NULL */
+{
+ OSErr result;
+ FSVolumeInfo info;
+
+ result = FSGetVolumeInfo(volume, 0, NULL, kFSVolInfoFSInfo, &info, NULL, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( NULL != fileSystemID )
+ {
+ *fileSystemID = info.filesystemID;
+ }
+ if ( NULL != signature )
+ {
+ *signature = info.signature;
+ }
+
+FSGetVolumeInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetMountedVolumes(
+ FSRef ***volumeRefsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numVolumes)
+{
+ OSErr result;
+ OSErr memResult;
+ ItemCount volumeIndex;
+ FSRef ref;
+
+ /* check parameters */
+ require_action((NULL != volumeRefsHandle) && (NULL != numVolumes),
+ BadParameter, result = paramErr);
+
+ /* No volumes yet */
+ *numVolumes = 0;
+
+ /* Allocate a handle for the results */
+ *volumeRefsHandle = (FSRef **)NewHandle(0);
+ require_action(NULL != *volumeRefsHandle, NewHandle, result = memFullErr);
+
+ /* Call FSGetVolumeInfo in loop to get all volumes starting with the first */
+ volumeIndex = 1;
+ do
+ {
+ result = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoNone, NULL, NULL, &ref);
+ if ( noErr == result )
+ {
+ /* concatenate the FSRef to the end of the handle */
+ PtrAndHand(&ref, (Handle)*volumeRefsHandle, sizeof(FSRef));
+ memResult = MemError();
+ require_noerr_action(memResult, MemoryAllocationFailed, result = memResult);
+
+ ++(*numVolumes); /* increment the volume count */
+ ++volumeIndex; /* and the volumeIndex to get the next volume*/
+ }
+ } while ( noErr == result );
+
+ /* nsvErr is OK -- it just means there are no more volumes */
+ require(nsvErr == result, FSGetVolumeInfo);
+
+ return ( noErr );
+
+ /**********************/
+
+MemoryAllocationFailed:
+FSGetVolumeInfo:
+
+ /* dispose of handle if already allocated and clear the outputs */
+ if ( NULL != *volumeRefsHandle )
+ {
+ DisposeHandle((Handle)*volumeRefsHandle);
+ *volumeRefsHandle = NULL;
+ }
+ *numVolumes = 0;
+
+NewHandle:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- FSRef/FSpec/Path/Name Conversion Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSRefMakeFSSpec(
+ const FSRef *ref,
+ FSSpec *spec)
+{
+ OSErr result;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMakeFSRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ FSRef *ref)
+{
+ OSErr result;
+ FSRefParam pb;
+
+ /* check parameters */
+ require_action(NULL != ref, BadParameter, result = paramErr);
+
+ pb.ioVRefNum = volRefNum;
+ pb.ioDirID = dirID;
+ pb.ioNamePtr = (StringPtr)name;
+ pb.newRef = ref;
+ result = PBMakeFSRefSync(&pb);
+ require_noerr(result, PBMakeFSRefSync);
+
+PBMakeFSRefSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSStatus
+FSMakePath(
+ SInt16 volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ UInt8 *path,
+ UInt32 maxPathSize)
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != path, BadParameter, result = paramErr);
+
+ /* convert the inputs to an FSRef */
+ result = FSMakeFSRef(volRefNum, dirID, name, &ref);
+ require_noerr(result, FSMakeFSRef);
+
+ /* and then convert the FSRef to a path */
+ result = FSRefMakePath(&ref, path, maxPathSize);
+ require_noerr(result, FSRefMakePath);
+
+FSRefMakePath:
+FSMakeFSRef:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSStatus
+FSPathMakeFSSpec(
+ const UInt8 *path,
+ FSSpec *spec,
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ /* convert the POSIX path to an FSRef */
+ result = FSPathMakeRef(path, &ref, isDirectory);
+ require_noerr(result, FSPathMakeRef);
+
+ /* and then convert the FSRef to an FSSpec */
+ result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+FSPathMakeRef:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+UnicodeNameGetHFSName(
+ UniCharCount nameLength,
+ const UniChar *name,
+ TextEncoding textEncodingHint,
+ Boolean isVolumeName,
+ Str31 hfsName)
+{
+ OSStatus result;
+ ByteCount unicodeByteLength;
+ ByteCount unicodeBytesConverted;
+ ByteCount actualPascalBytes;
+ UnicodeMapping uMapping;
+ UnicodeToTextInfo utInfo;
+
+ /* check parameters */
+ require_action(NULL != hfsName, BadParameter, result = paramErr);
+
+ /* make sure output is valid in case we get errors or there's nothing to convert */
+ hfsName[0] = 0;
+
+ unicodeByteLength = nameLength * sizeof(UniChar);
+ if ( 0 == unicodeByteLength )
+ {
+ /* do nothing */
+ result = noErr;
+ }
+ else
+ {
+ /* if textEncodingHint is kTextEncodingUnknown, get a "default" textEncodingHint */
+ if ( kTextEncodingUnknown == textEncodingHint )
+ {
+ ScriptCode script;
+ RegionCode region;
+
+ script = (ScriptCode)GetScriptManagerVariable(smSysScript);
+ region = (RegionCode)GetScriptManagerVariable(smRegionCode);
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region,
+ NULL, &textEncodingHint );
+ if ( paramErr == result )
+ {
+ /* ok, ignore the region and try again */
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &textEncodingHint );
+ }
+ if ( noErr != result )
+ {
+ /* ok... try something */
+ textEncodingHint = kTextEncodingMacRoman;
+ }
+ }
+
+ uMapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeV2_0,
+ kUnicodeCanonicalDecompVariant, kUnicode16BitFormat);
+ uMapping.otherEncoding = GetTextEncodingBase(textEncodingHint);
+ uMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
+
+ result = CreateUnicodeToTextInfo(&uMapping, &utInfo);
+ require_noerr(result, CreateUnicodeToTextInfo);
+
+ result = ConvertFromUnicodeToText(utInfo, unicodeByteLength, name, kUnicodeLooseMappingsMask,
+ 0, NULL, 0, NULL, /* offsetCounts & offsetArrays */
+ isVolumeName ? kHFSMaxVolumeNameChars : kHFSMaxFileNameChars,
+ &unicodeBytesConverted, &actualPascalBytes, &hfsName[1]);
+ require_noerr(result, ConvertFromUnicodeToText);
+
+ hfsName[0] = (unsigned char)actualPascalBytes; /* fill in length byte */
+
+ConvertFromUnicodeToText:
+
+ /* verify the result in debug builds -- there's really not anything you can do if it fails */
+ verify_noerr(DisposeUnicodeToTextInfo(&utInfo));
+ }
+
+CreateUnicodeToTextInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+HFSNameGetUnicodeName(
+ ConstStr31Param hfsName,
+ TextEncoding textEncodingHint,
+ HFSUniStr255 *unicodeName)
+{
+ ByteCount unicodeByteLength;
+ OSStatus result;
+ UnicodeMapping uMapping;
+ TextToUnicodeInfo tuInfo;
+ ByteCount pascalCharsRead;
+
+ /* check parameters */
+ require_action(NULL != unicodeName, BadParameter, result = paramErr);
+
+ /* make sure output is valid in case we get errors or there's nothing to convert */
+ unicodeName->length = 0;
+
+ if ( 0 == StrLength(hfsName) )
+ {
+ result = noErr;
+ }
+ else
+ {
+ /* if textEncodingHint is kTextEncodingUnknown, get a "default" textEncodingHint */
+ if ( kTextEncodingUnknown == textEncodingHint )
+ {
+ ScriptCode script;
+ RegionCode region;
+
+ script = GetScriptManagerVariable(smSysScript);
+ region = GetScriptManagerVariable(smRegionCode);
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region,
+ NULL, &textEncodingHint);
+ if ( paramErr == result )
+ {
+ /* ok, ignore the region and try again */
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &textEncodingHint);
+ }
+ if ( noErr != result )
+ {
+ /* ok... try something */
+ textEncodingHint = kTextEncodingMacRoman;
+ }
+ }
+
+ uMapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeV2_0,
+ kUnicodeCanonicalDecompVariant, kUnicode16BitFormat);
+ uMapping.otherEncoding = GetTextEncodingBase(textEncodingHint);
+ uMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
+
+ result = CreateTextToUnicodeInfo(&uMapping, &tuInfo);
+ require_noerr(result, CreateTextToUnicodeInfo);
+
+ result = ConvertFromTextToUnicode(tuInfo, hfsName[0], &hfsName[1],
+ 0, /* no control flag bits */
+ 0, NULL, 0, NULL, /* offsetCounts & offsetArrays */
+ sizeof(unicodeName->unicode), /* output buffer size in bytes */
+ &pascalCharsRead, &unicodeByteLength, unicodeName->unicode);
+ require_noerr(result, ConvertFromTextToUnicode);
+
+ /* convert from byte count to char count */
+ unicodeName->length = unicodeByteLength / sizeof(UniChar);
+
+ConvertFromTextToUnicode:
+
+ /* verify the result in debug builds -- there's really not anything you can do if it fails */
+ verify_noerr(DisposeTextToUnicodeInfo(&tuInfo));
+ }
+
+CreateTextToUnicodeInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- File/Directory Manipulation Routines -----
+
+/*****************************************************************************/
+
+Boolean FSRefValid(const FSRef *ref)
+{
+ return ( noErr == FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, NULL, NULL) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetParentRef(
+ const FSRef *ref,
+ FSRef *parentRef)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != parentRef, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeID, &catalogInfo, NULL, NULL, parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /*
+ * Note: FSRefs always point to real file system objects. So, there cannot
+ * be a FSRef to the parent of volume root directories. Early versions of
+ * Mac OS X do not handle this case correctly and incorrectly return a
+ * FSRef for the parent of volume root directories instead of returning an
+ * invalid FSRef (a cleared FSRef is invalid). The next three lines of code
+ * ensure that you won't run into this bug. WW9D!
+ */
+ if ( fsRtDirID == catalogInfo.nodeID )
+ {
+ /* clear parentRef and return noErr which is the proper behavior */
+ memset(parentRef, 0, sizeof(FSRef));
+ }
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetFileDirName(
+ const FSRef *ref,
+ HFSUniStr255 *outName)
+{
+ OSErr result;
+
+ /* check parameters */
+ require_action(NULL != outName, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, outName, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetNodeID(
+ const FSRef *ref,
+ long *nodeID, /* can be NULL */
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information to get */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != nodeID )
+ {
+ whichInfo |= kFSCatInfoNodeID;
+ }
+ if ( NULL != isDirectory )
+ {
+ whichInfo |= kFSCatInfoNodeFlags;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ if ( NULL != nodeID )
+ {
+ *nodeID = catalogInfo.nodeID;
+ }
+ if ( NULL != isDirectory )
+ {
+ *isDirectory = (0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags));
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetUserPrivilegesPermissions(
+ const FSRef *ref,
+ UInt8 *userPrivileges, /* can be NULL */
+ UInt32 permissions[4]) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information to get */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != userPrivileges )
+ {
+ whichInfo |= kFSCatInfoUserPrivs;
+ }
+ if ( NULL != permissions )
+ {
+ whichInfo |= kFSCatInfoPermissions;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ if ( NULL != userPrivileges )
+ {
+ *userPrivileges = catalogInfo.userPrivileges;
+ }
+ if ( NULL != permissions )
+ {
+ BlockMoveData(&catalogInfo.permissions, permissions, sizeof(UInt32) * 4);
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCheckLock(
+ const FSRef *ref)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSVolumeInfo volumeInfo;
+
+ /* get nodeFlags and vRefNum for container */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoVolume, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* is file locked? */
+ if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) )
+ {
+ result = fLckdErr; /* file is locked */
+ }
+ else
+ {
+ /* file isn't locked, but is volume locked? */
+
+ /* get volume flags */
+ result = FSGetVolumeInfo(catalogInfo.volume, 0, NULL, kFSVolInfoFlags, &volumeInfo, NULL, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( 0 != (volumeInfo.flags & kFSVolFlagHardwareLockedMask) )
+ {
+ result = wPrErr; /* volume locked by hardware */
+ }
+ else if ( 0 != (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) )
+ {
+ result = vLckdErr; /* volume locked by software */
+ }
+ }
+
+FSGetVolumeInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetForkSizes(
+ const FSRef *ref,
+ UInt64 *dataLogicalSize, /* can be NULL */
+ UInt64 *rsrcLogicalSize) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfoBitmap whichInfo;
+ FSCatalogInfo catalogInfo;
+
+ whichInfo = kFSCatInfoNodeFlags;
+ if ( NULL != dataLogicalSize )
+ {
+ /* get data fork size */
+ whichInfo |= kFSCatInfoDataSizes;
+ }
+ if ( NULL != rsrcLogicalSize )
+ {
+ /* get resource fork size */
+ whichInfo |= kFSCatInfoRsrcSizes;
+ }
+
+ /* get nodeFlags and catalog info */
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure FSRef was to a file */
+ require_action(0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), FSRefNotFile, result = notAFileErr);
+
+ if ( NULL != dataLogicalSize )
+ {
+ /* return data fork size */
+ *dataLogicalSize = catalogInfo.dataLogicalSize;
+ }
+ if ( NULL != rsrcLogicalSize )
+ {
+ /* return resource fork size */
+ *rsrcLogicalSize = catalogInfo.rsrcLogicalSize;
+ }
+
+FSRefNotFile:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetTotalForkSizes(
+ const FSRef *ref,
+ UInt64 *totalLogicalSize, /* can be NULL */
+ UInt64 *totalPhysicalSize, /* can be NULL */
+ ItemCount *forkCount) /* can be NULL */
+{
+ OSErr result;
+ CatPositionRec forkIterator;
+ SInt64 forkSize;
+ SInt64 *forkSizePtr;
+ UInt64 forkPhysicalSize;
+ UInt64 *forkPhysicalSizePtr;
+
+ /* Determine if forkSize needed */
+ if ( NULL != totalLogicalSize)
+ {
+ *totalLogicalSize = 0;
+ forkSizePtr = &forkSize;
+ }
+ else
+ {
+ forkSizePtr = NULL;
+ }
+
+ /* Determine if forkPhysicalSize is needed */
+ if ( NULL != totalPhysicalSize )
+ {
+ *totalPhysicalSize = 0;
+ forkPhysicalSizePtr = &forkPhysicalSize;
+ }
+ else
+ {
+ forkPhysicalSizePtr = NULL;
+ }
+
+ /* zero fork count if returning it */
+ if ( NULL != forkCount )
+ {
+ *forkCount = 0;
+ }
+
+ /* Iterate through the forks to get the sizes */
+ forkIterator.initialize = 0;
+ do
+ {
+ result = FSIterateForks(ref, &forkIterator, NULL, forkSizePtr, forkPhysicalSizePtr);
+ if ( noErr == result )
+ {
+ if ( NULL != totalLogicalSize )
+ {
+ *totalLogicalSize += forkSize;
+ }
+
+ if ( NULL != totalPhysicalSize )
+ {
+ *totalPhysicalSize += forkPhysicalSize;
+ }
+
+ if ( NULL != forkCount )
+ {
+ ++*forkCount;
+ }
+ }
+ } while ( noErr == result );
+
+ /* any error result other than errFSNoMoreItems is serious */
+ require(errFSNoMoreItems == result, FSIterateForks);
+
+ /* Normal exit */
+ result = noErr;
+
+FSIterateForks:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSBumpDate(
+ const FSRef *ref)
+{
+ OSStatus result;
+ FSCatalogInfo catalogInfo;
+ UTCDateTime oldDateTime;
+#if !BuildingMoreFilesXForMacOS9
+ FSRef parentRef;
+ Boolean notifyParent;
+#endif
+
+#if !BuildingMoreFilesXForMacOS9
+ /* Get the node flags, the content modification date and time, and the parent ref */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoContentMod, &catalogInfo, NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Notify the parent if this is a file */
+ notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
+#else
+ /* Get the content modification date and time */
+ result = FSGetCatalogInfo(ref, kFSCatInfoContentMod, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+#endif
+
+ oldDateTime = catalogInfo.contentModDate;
+
+ /* Get the current date and time */
+ result = GetUTCDateTime(&catalogInfo.contentModDate, kUTCDefaultOptions);
+ require_noerr(result, GetUTCDateTime);
+
+ /* if the old date and time is the the same as the current, bump the seconds by one */
+ if ( (catalogInfo.contentModDate.fraction == oldDateTime.fraction) &&
+ (catalogInfo.contentModDate.lowSeconds == oldDateTime.lowSeconds) &&
+ (catalogInfo.contentModDate.highSeconds == oldDateTime.highSeconds) )
+ {
+ ++catalogInfo.contentModDate.lowSeconds;
+ if ( 0 == catalogInfo.contentModDate.lowSeconds )
+ {
+ ++catalogInfo.contentModDate.highSeconds;
+ }
+ }
+
+ /* Bump the content modification date and time */
+ result = FSSetCatalogInfo(ref, kFSCatInfoContentMod, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+#if !BuildingMoreFilesXForMacOS9
+ /*
+ * The problem with FNNotify is that it is not available under Mac OS 9
+ * and there's no way to test for that except for looking for the symbol
+ * or something. So, I'll just conditionalize this for those who care
+ * to send a notification.
+ */
+
+ /* Send a notification for the parent of the file, or for the directory */
+ result = FNNotify(notifyParent ? &parentRef : ref, kFNDirectoryModifiedMessage, kNilOptions);
+ require_noerr(result, FNNotify);
+#endif
+
+ /* ignore errors from FSSetCatalogInfo (volume might be write protected) and FNNotify */
+FNNotify:
+FSSetCatalogInfo:
+
+ return ( noErr );
+
+ /**********************/
+
+GetUTCDateTime:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetFinderInfo(
+ const FSRef *ref,
+ FinderInfo *info, /* can be NULL */
+ ExtendedFinderInfo *extendedInfo, /* can be NULL */
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information is really needed */
+ whichInfo = kFSCatInfoNone;
+
+ if ( NULL != info )
+ {
+ /* get FinderInfo */
+ whichInfo |= kFSCatInfoFinderInfo;
+ }
+
+ if ( NULL != extendedInfo )
+ {
+ /* get ExtendedFinderInfo */
+ whichInfo |= kFSCatInfoFinderXInfo;
+ }
+
+ if ( NULL != isDirectory )
+ {
+ whichInfo |= kFSCatInfoNodeFlags;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* return FinderInfo if requested */
+ if ( NULL != info )
+ {
+ BlockMoveData(catalogInfo.finderInfo, info, sizeof(FinderInfo));
+ }
+
+ /* return ExtendedFinderInfo if requested */
+ if ( NULL != extendedInfo)
+ {
+ BlockMoveData(catalogInfo.extFinderInfo, extendedInfo, sizeof(ExtendedFinderInfo));
+ }
+
+ /* set isDirectory Boolean if requested */
+ if ( NULL != isDirectory)
+ {
+ *isDirectory = (0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags));
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetFinderInfo(
+ const FSRef *ref,
+ const FinderInfo *info,
+ const ExtendedFinderInfo *extendedInfo)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information will be set */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != info )
+ {
+ /* set FinderInfo */
+ whichInfo |= kFSCatInfoFinderInfo;
+ BlockMoveData(info, catalogInfo.finderInfo, sizeof(FinderInfo));
+ }
+ if ( NULL != extendedInfo )
+ {
+ /* set ExtendedFinderInfo */
+ whichInfo |= kFSCatInfoFinderXInfo;
+ BlockMoveData(extendedInfo, catalogInfo.extFinderInfo, sizeof(ExtendedFinderInfo));
+ }
+
+ result = FSSetCatalogInfo(ref, whichInfo, &catalogInfo);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSChangeCreatorType(
+ const FSRef *ref,
+ OSType fileCreator,
+ OSType fileType)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSRef parentRef;
+
+ /* get nodeFlags, finder info, and parent FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo, &catalogInfo , NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure FSRef was to a file */
+ require_action(0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), FSRefNotFile, result = notAFileErr);
+
+ /* If fileType not 0x00000000, change fileType */
+ if ( fileType != (OSType)0x00000000 )
+ {
+ ((FileInfo *)&catalogInfo.finderInfo)->fileType = fileType;
+ }
+
+ /* If creator not 0x00000000, change creator */
+ if ( fileCreator != (OSType)0x00000000 )
+ {
+ ((FileInfo *)&catalogInfo.finderInfo)->fileCreator = fileCreator;
+ }
+
+ /* now, save the new information back to disk */
+ result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+ /* and attempt to bump the parent directory's mod date to wake up */
+ /* the Finder to the change we just made (ignore errors from this) */
+ verify_noerr(FSBumpDate(&parentRef));
+
+FSSetCatalogInfo:
+FSRefNotFile:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSChangeFinderFlags(
+ const FSRef *ref,
+ Boolean setBits,
+ UInt16 flagBits)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSRef parentRef;
+
+ /* get the current finderInfo */
+ result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* set or clear the appropriate bits in the finderInfo.finderFlags */
+ if ( setBits )
+ {
+ /* OR in the bits */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits;
+ }
+ else
+ {
+ /* AND out the bits */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits;
+ }
+
+ /* save the modified finderInfo */
+ result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+ /* and attempt to bump the parent directory's mod date to wake up the Finder */
+ /* to the change we just made (ignore errors from this) */
+ verify_noerr(FSBumpDate(&parentRef));
+
+FSSetCatalogInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetInvisible(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kIsInvisible) );
+}
+
+OSErr
+FSClearInvisible(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kIsInvisible) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetNameLocked(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kNameLocked) );
+}
+
+OSErr
+FSClearNameLocked(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kNameLocked) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetIsStationery(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kIsStationery) );
+}
+
+OSErr
+FSClearIsStationery(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kIsStationery) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetHasCustomIcon(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kHasCustomIcon) );
+}
+
+OSErr
+FSClearHasCustomIcon(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kHasCustomIcon) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSClearHasBeenInited(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kHasBeenInited) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFileMgrAttributes(
+ const FSRef *sourceRef,
+ const FSRef *destinationRef,
+ Boolean copyLockBit)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* get the source information */
+ result = FSGetCatalogInfo(sourceRef, kFSCatInfoSettableInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* don't copy the hasBeenInited bit; clear it */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~kHasBeenInited;
+
+ /* should the locked bit be copied? */
+ if ( !copyLockBit )
+ {
+ /* no, make sure the locked bit is clear */
+ catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
+ }
+
+ /* set the destination information */
+ result = FSSetCatalogInfo(destinationRef, kFSCatInfoSettableInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+FSSetCatalogInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMoveRenameObjectUnicode(
+ const FSRef *ref,
+ const FSRef *destDirectory,
+ UniCharCount nameLength,
+ const UniChar *name, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* if function fails along the way, newRef is final location of file */
+{
+ OSErr result;
+ FSVolumeRefNum vRefNum;
+ FSCatalogInfo catalogInfo;
+ FSRef originalDirectory;
+ TextEncoding originalTextEncodingHint;
+ HFSUniStr255 originalName;
+ HFSUniStr255 uniqueName; /* unique name given to object while moving it to destination */
+ long theSeed; /* the seed for generating unique names */
+
+ /* check parameters */
+ require_action(NULL != newRef, BadParameter, result = paramErr);
+
+ /* newRef = input to start with */
+ BlockMoveData(ref, newRef, sizeof(FSRef));
+
+ /* get destDirectory's vRefNum */
+ result = FSGetCatalogInfo(destDirectory, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, DestinationBad);
+
+ /* save vRefNum */
+ vRefNum = catalogInfo.volume;
+
+ /* get ref's vRefNum, TextEncoding, name and parent directory*/
+ result = FSGetCatalogInfo(ref, kFSCatInfoTextEncoding + kFSCatInfoVolume, &catalogInfo, &originalName, NULL, &originalDirectory);
+ require_noerr(result, SourceBad);
+
+ /* save TextEncoding */
+ originalTextEncodingHint = catalogInfo.textEncodingHint;
+
+ /* make sure ref and destDirectory are on same volume */
+ require_action(vRefNum == catalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* Skip a few steps if we're not renaming */
+ if ( NULL != name )
+ {
+ /* generate a name that is unique in both directories */
+ theSeed = 0x4a696d4c; /* a fine unlikely filename */
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &originalDirectory, destDirectory, &uniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStrFailed);
+
+ /* Rename the object to uniqueName */
+ result = FSRenameUnicode(ref, uniqueName.length, uniqueName.unicode, kTextEncodingUnknown, newRef);
+ require_noerr(result, FSRenameUnicodeBeforeMoveFailed);
+
+ if ( FSCompareFSRefs(destDirectory, &originalDirectory) != noErr )
+ {
+ /* Move object to its new home */
+ result = FSMoveObject(newRef, destDirectory, newRef);
+ require_noerr(result, FSMoveObjectAfterRenameFailed);
+ }
+
+ /* Rename the object to new name */
+ result = FSRenameUnicode(ref, nameLength, name, textEncodingHint, newRef);
+ require_noerr(result, FSRenameUnicodeAfterMoveFailed);
+ }
+ else
+ {
+ /* Move object to its new home */
+ result = FSMoveObject(newRef, destDirectory, newRef);
+ require_noerr(result, FSMoveObjectNoRenameFailed);
+ }
+
+ return ( result );
+
+ /*************/
+
+/*
+ * failure handling code when renaming
+ */
+
+FSRenameUnicodeAfterMoveFailed:
+
+ /* Error handling: move object back to original location - ignore errors */
+ verify_noerr(FSMoveObject(newRef, &originalDirectory, newRef));
+
+FSMoveObjectAfterRenameFailed:
+
+ /* Error handling: rename object back to original name - ignore errors */
+ verify_noerr(FSRenameUnicode(newRef, originalName.length, originalName.unicode, originalTextEncodingHint, newRef));
+
+FSRenameUnicodeBeforeMoveFailed:
+GenerateUniqueHFSUniStrFailed:
+
+/*
+ * failure handling code for renaming or not
+ */
+FSMoveObjectNoRenameFailed:
+NotSameVolume:
+SourceBad:
+DestinationBad:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The FSDeleteContainerLevel function deletes the contents of a container
+ directory. All files and subdirectories in the specified container are
+ deleted. If a locked file or directory is encountered, it is unlocked
+ and then deleted. If any unexpected errors are encountered,
+ FSDeleteContainerLevel quits and returns to the caller.
+
+ container --> FSRef to a directory.
+ theGlobals --> A pointer to a FSDeleteContainerGlobals struct
+ which contains the variables that do not need to
+ be allocated each time FSDeleteContainerLevel
+ recurses. That lets FSDeleteContainerLevel use
+ less stack space per recursion level.
+*/
+
+static
+void
+FSDeleteContainerLevel(
+ const FSRef *container,
+ FSDeleteContainerGlobals *theGlobals)
+{
+ /* level locals */
+ FSIterator iterator;
+ FSRef itemToDelete;
+ UInt16 nodeFlags;
+
+ /* Open FSIterator for flat access and give delete optimization hint */
+ theGlobals->result = FSOpenIterator(container, kFSIterateFlat + kFSIterateDelete, &iterator);
+ require_noerr(theGlobals->result, FSOpenIterator);
+
+ /* delete the contents of the directory */
+ do
+ {
+ /* get 1 item to delete */
+ theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects,
+ NULL, kFSCatInfoNodeFlags, &theGlobals->catalogInfo,
+ &itemToDelete, NULL, NULL);
+ if ( (noErr == theGlobals->result) && (1 == theGlobals->actualObjects) )
+ {
+ /* save node flags in local in case we have to recurse */
+ nodeFlags = theGlobals->catalogInfo.nodeFlags;
+
+ /* is it a file or directory? */
+ if ( 0 != (nodeFlags & kFSNodeIsDirectoryMask) )
+ {
+ /* it's a directory -- delete its contents before attempting to delete it */
+ FSDeleteContainerLevel(&itemToDelete, theGlobals);
+ }
+ /* are we still OK to delete? */
+ if ( noErr == theGlobals->result )
+ {
+ /* is item locked? */
+ if ( 0 != (nodeFlags & kFSNodeLockedMask) )
+ {
+ /* then attempt to unlock it (ignore result since FSDeleteObject will set it correctly) */
+ theGlobals->catalogInfo.nodeFlags = nodeFlags & ~kFSNodeLockedMask;
+ (void) FSSetCatalogInfo(&itemToDelete, kFSCatInfoNodeFlags, &theGlobals->catalogInfo);
+ }
+ /* delete the item */
+ theGlobals->result = FSDeleteObject(&itemToDelete);
+ }
+ }
+ } while ( noErr == theGlobals->result );
+
+ /* we found the end of the items normally, so return noErr */
+ if ( errFSNoMoreItems == theGlobals->result )
+ {
+ theGlobals->result = noErr;
+ }
+
+ /* close the FSIterator (closing an open iterator should never fail) */
+ verify_noerr(FSCloseIterator(iterator));
+
+FSOpenIterator:
+
+ return;
+}
+
+/*****************************************************************************/
+
+OSErr
+FSDeleteContainerContents(
+ const FSRef *container)
+{
+ FSDeleteContainerGlobals theGlobals;
+
+ /* delete container's contents */
+ FSDeleteContainerLevel(container, &theGlobals);
+
+ return ( theGlobals.result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSDeleteContainer(
+ const FSRef *container)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* get nodeFlags for container */
+ result = FSGetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure container is a directory */
+ require_action(0 != (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), ContainerNotDirectory, result = dirNFErr);
+
+ /* delete container's contents */
+ result = FSDeleteContainerContents(container);
+ require_noerr(result, FSDeleteContainerContents);
+
+ /* is container locked? */
+ if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) )
+ {
+ /* then attempt to unlock container (ignore result since FSDeleteObject will set it correctly) */
+ catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
+ (void) FSSetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo);
+ }
+
+ /* delete the container */
+ result = FSDeleteObject(container);
+
+FSDeleteContainerContents:
+ContainerNotDirectory:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The FSIterateContainerLevel function iterates the contents of a container
+ directory and calls a IterateContainerFilterProc function once for each
+ file and directory found.
+
+ theGlobals --> A pointer to a FSIterateContainerGlobals struct
+ which contains the variables needed globally by
+ all recusion levels of FSIterateContainerLevel.
+ That makes FSIterateContainer thread safe since
+ each call to it uses its own global world.
+ It also contains the variables that do not need
+ to be allocated each time FSIterateContainerLevel
+ recurses. That lets FSIterateContainerLevel use
+ less stack space per recursion level.
+*/
+
+static
+void
+FSIterateContainerLevel(
+ FSIterateContainerGlobals *theGlobals)
+{
+ FSIterator iterator;
+
+ /* If maxLevels is zero, we aren't checking levels */
+ /* If currentLevel < maxLevels, look at this level */
+ if ( (theGlobals->maxLevels == 0) ||
+ (theGlobals->currentLevel < theGlobals->maxLevels) )
+ {
+ /* Open FSIterator for flat access to theGlobals->ref */
+ theGlobals->result = FSOpenIterator(&theGlobals->ref, kFSIterateFlat, &iterator);
+ require_noerr(theGlobals->result, FSOpenIterator);
+
+ ++theGlobals->currentLevel; /* Go to next level */
+
+ /* Call FSGetCatalogInfoBulk in loop to get all items in the container */
+ do
+ {
+ theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects,
+ &theGlobals->containerChanged, theGlobals->whichInfo, &theGlobals->catalogInfo,
+ &theGlobals->ref, theGlobals->specPtr, theGlobals->namePtr);
+ if ( (noErr == theGlobals->result || errFSNoMoreItems == theGlobals->result) &&
+ (0 != theGlobals->actualObjects) )
+ {
+ /* Call the IterateFilterProc */
+ theGlobals->quitFlag = CallIterateContainerFilterProc(theGlobals->iterateFilter,
+ theGlobals->containerChanged, theGlobals->currentLevel,
+ &theGlobals->catalogInfo, &theGlobals->ref,
+ theGlobals->specPtr, theGlobals->namePtr, theGlobals->yourDataPtr);
+ /* Is it a directory? */
+ if ( 0 != (theGlobals->catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) )
+ {
+ /* Keep going? */
+ if ( !theGlobals->quitFlag )
+ {
+ /* Dive again if the IterateFilterProc didn't say "quit" */
+ FSIterateContainerLevel(theGlobals);
+ }
+ }
+ }
+ /* time to fall back a level? */
+ } while ( (noErr == theGlobals->result) && (!theGlobals->quitFlag) );
+
+ /* errFSNoMoreItems is OK - it only means we hit the end of this level */
+ /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
+ if ( (errFSNoMoreItems == theGlobals->result) ||
+ (afpAccessDenied == theGlobals->result) )
+ {
+ theGlobals->result = noErr;
+ }
+
+ --theGlobals->currentLevel; /* Return to previous level as we leave */
+
+ /* Close the FSIterator (closing an open iterator should never fail) */
+ verify_noerr(FSCloseIterator(iterator));
+ }
+
+FSOpenIterator:
+
+ return;
+}
+
+/*****************************************************************************/
+
+OSErr
+FSIterateContainer(
+ const FSRef *container,
+ ItemCount maxLevels,
+ FSCatalogInfoBitmap whichInfo,
+ Boolean wantFSSpec,
+ Boolean wantName,
+ IterateContainerFilterProcPtr iterateFilter,
+ void *yourDataPtr)
+{
+ OSErr result;
+ FSIterateContainerGlobals theGlobals;
+
+ /* make sure there is an iterateFilter */
+ require_action(iterateFilter != NULL, NoIterateFilter, result = paramErr);
+
+ /*
+ * set up the globals we need to access from the recursive routine
+ */
+ theGlobals.iterateFilter = iterateFilter;
+ /* we need the node flags no matter what was requested so we can detect files vs. directories */
+ theGlobals.whichInfo = whichInfo | kFSCatInfoNodeFlags;
+ /* start with input container -- the first OpenIterator will ensure it is a directory */
+ theGlobals.ref = *container;
+ if ( wantFSSpec )
+ {
+ theGlobals.specPtr = &theGlobals.spec;
+ }
+ else
+ {
+ theGlobals.specPtr = NULL;
+ }
+ if ( wantName )
+ {
+ theGlobals.namePtr = &theGlobals.name;
+ }
+ else
+ {
+ theGlobals.namePtr = NULL;
+ }
+ theGlobals.yourDataPtr = yourDataPtr;
+ theGlobals.maxLevels = maxLevels;
+ theGlobals.currentLevel = 0;
+ theGlobals.quitFlag = false;
+ theGlobals.containerChanged = false;
+ theGlobals.result = noErr;
+ theGlobals.actualObjects = 0;
+
+ /* here we go into recursion land... */
+ FSIterateContainerLevel(&theGlobals);
+ result = theGlobals.result;
+ require_noerr(result, FSIterateContainerLevel);
+
+FSIterateContainerLevel:
+NoIterateFilter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetDirectoryItems(
+ const FSRef *container,
+ FSRef ***refsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numRefs,
+ Boolean *containerChanged)
+{
+ /* Grab items 10 at a time. */
+ enum { kMaxItemsPerBulkCall = 10 };
+
+ OSErr result;
+ OSErr memResult;
+ FSIterator iterator;
+ FSRef refs[kMaxItemsPerBulkCall];
+ ItemCount actualObjects;
+ Boolean changed;
+
+ /* check parameters */
+ require_action((NULL != refsHandle) && (NULL != numRefs) && (NULL != containerChanged),
+ BadParameter, result = paramErr);
+
+ *numRefs = 0;
+ *containerChanged = false;
+ *refsHandle = (FSRef **)NewHandle(0);
+ require_action(NULL != *refsHandle, NewHandle, result = memFullErr);
+
+ /* open an FSIterator */
+ result = FSOpenIterator(container, kFSIterateFlat, &iterator);
+ require_noerr(result, FSOpenIterator);
+
+ /* Call FSGetCatalogInfoBulk in loop to get all items in the container */
+ do
+ {
+ result = FSGetCatalogInfoBulk(iterator, kMaxItemsPerBulkCall, &actualObjects,
+ &changed, kFSCatInfoNone, NULL, refs, NULL, NULL);
+
+ /* if the container changed, set containerChanged for output, but keep going */
+ if ( changed )
+ {
+ *containerChanged = changed;
+ }
+
+ /* any result other than noErr and errFSNoMoreItems is serious */
+ require((noErr == result) || (errFSNoMoreItems == result), FSGetCatalogInfoBulk);
+
+ /* add objects to output array and count */
+ if ( 0 != actualObjects )
+ {
+ /* concatenate the FSRefs to the end of the handle */
+ PtrAndHand(refs, (Handle)*refsHandle, actualObjects * sizeof(FSRef));
+ memResult = MemError();
+ require_noerr_action(memResult, MemoryAllocationFailed, result = memResult);
+
+ *numRefs += actualObjects;
+ }
+ } while ( noErr == result );
+
+ verify_noerr(FSCloseIterator(iterator)); /* closing an open iterator should never fail, but... */
+
+ return ( noErr );
+
+ /**********************/
+
+MemoryAllocationFailed:
+FSGetCatalogInfoBulk:
+
+ /* close the iterator */
+ verify_noerr(FSCloseIterator(iterator));
+
+FSOpenIterator:
+ /* dispose of handle if already allocated and clear the outputs */
+ if ( NULL != *refsHandle )
+ {
+ DisposeHandle((Handle)*refsHandle);
+ *refsHandle = NULL;
+ }
+ *numRefs = 0;
+
+NewHandle:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The GenerateUniqueName function generates a HFSUniStr255 name that is
+ unique in both dir1 and dir2.
+
+ startSeed --> A pointer to a long which is used to generate the
+ unique name.
+ <-- It is modified on output to a value which should
+ be used to generate the next unique name.
+ dir1 --> The first directory.
+ dir2 --> The second directory.
+ uniqueName <-- A pointer to a HFSUniStr255 where the unique name
+ is to be returned.
+*/
+
+static
+OSErr
+GenerateUniqueHFSUniStr(
+ long *startSeed,
+ const FSRef *dir1,
+ const FSRef *dir2,
+ HFSUniStr255 *uniqueName)
+{
+ OSErr result;
+ long i;
+ FSRefParam pb;
+ FSRef newRef;
+ unsigned char hexStr[17] = "0123456789ABCDEF";
+
+ /* set up the parameter block */
+ pb.name = uniqueName->unicode;
+ pb.nameLength = 8; /* always 8 characters */
+ pb.textEncodingHint = kTextEncodingUnknown;
+ pb.newRef = &newRef;
+
+ /* loop until we get fnfErr with a filename in both directories */
+ result = noErr;
+ while ( fnfErr != result )
+ {
+ /* convert startSeed to 8 character Unicode string */
+ uniqueName->length = 8;
+ for ( i = 0; i < 8; ++i )
+ {
+ uniqueName->unicode[i] = hexStr[((*startSeed >> ((7-i)*4)) & 0xf)];
+ }
+
+ /* try in dir1 */
+ pb.ref = dir1;
+ result = PBMakeFSRefUnicodeSync(&pb);
+ if ( fnfErr == result )
+ {
+ /* try in dir2 */
+ pb.ref = dir2;
+ result = PBMakeFSRefUnicodeSync(&pb);
+ if ( fnfErr != result )
+ {
+ /* exit if anything other than noErr or fnfErr */
+ require_noerr(result, Dir2PBMakeFSRefUnicodeSyncFailed);
+ }
+ }
+ else
+ {
+ /* exit if anything other than noErr or fnfErr */
+ require_noerr(result, Dir1PBMakeFSRefUnicodeSyncFailed);
+ }
+
+ /* increment seed for next pass through loop, */
+ /* or for next call to GenerateUniqueHFSUniStr */
+ ++(*startSeed);
+ }
+
+ /* we have a unique file name which doesn't exist in dir1 or dir2 */
+ result = noErr;
+
+Dir2PBMakeFSRefUnicodeSyncFailed:
+Dir1PBMakeFSRefUnicodeSyncFailed:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSExchangeObjectsCompat(
+ const FSRef *sourceRef,
+ const FSRef *destRef,
+ FSRef *newSourceRef,
+ FSRef *newDestRef)
+{
+ enum
+ {
+ /* get all settable info except for mod dates, plus the volume refNum and parent directory ID */
+ kGetCatInformationMask = (kFSCatInfoSettableInfo |
+ kFSCatInfoVolume |
+ kFSCatInfoParentDirID) &
+ ~(kFSCatInfoContentMod | kFSCatInfoAttrMod),
+ /* set everything possible except for mod dates */
+ kSetCatinformationMask = kFSCatInfoSettableInfo &
+ ~(kFSCatInfoContentMod | kFSCatInfoAttrMod)
+ };
+
+ OSErr result;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+ FSCatalogInfo sourceCatalogInfo; /* source file's catalog information */
+ FSCatalogInfo destCatalogInfo; /* destination file's catalog information */
+ HFSUniStr255 sourceName; /* source file's Unicode name */
+ HFSUniStr255 destName; /* destination file's Unicode name */
+ FSRef sourceCurrentRef; /* FSRef to current location of source file throughout this function */
+ FSRef destCurrentRef; /* FSRef to current location of destination file throughout this function */
+ FSRef sourceParentRef; /* FSRef to parent directory of source file */
+ FSRef destParentRef; /* FSRef to parent directory of destination file */
+ HFSUniStr255 sourceUniqueName; /* unique name given to source file while exchanging it with destination */
+ HFSUniStr255 destUniqueName; /* unique name given to destination file while exchanging it with source */
+ long theSeed; /* the seed for generating unique names */
+ Boolean sameParentDirs; /* true if source and destinatin parent directory is the same */
+
+ /* check parameters */
+ require_action((NULL != newSourceRef) && (NULL != newDestRef), BadParameter, result = paramErr);
+
+ /* output refs and current refs = input refs to start with */
+ BlockMoveData(sourceRef, newSourceRef, sizeof(FSRef));
+ BlockMoveData(sourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ BlockMoveData(destRef, newDestRef, sizeof(FSRef));
+ BlockMoveData(destRef, &destCurrentRef, sizeof(FSRef));
+
+ /* get source volume's vRefNum */
+ result = FSGetCatalogInfo(&sourceCurrentRef, kFSCatInfoVolume, &sourceCatalogInfo, NULL, NULL, NULL);
+ require_noerr(result, DetermineSourceVRefNumFailed);
+
+ /* see if that volume supports FSExchangeObjects */
+ result = FSGetVolParms(sourceCatalogInfo.volume, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ if ( (noErr == result) && VolSupportsFSExchangeObjects(&volParmsInfo) )
+ {
+ /* yes - use FSExchangeObjects */
+ result = FSExchangeObjects(sourceRef, destRef);
+ }
+ else
+ {
+ /* no - emulate FSExchangeObjects */
+
+ /* Note: The compatibility case won't work for files with *Btree control blocks. */
+ /* Right now the only *Btree files are created by the system. */
+
+ /* get all catalog information and Unicode names for each file */
+ result = FSGetCatalogInfo(&sourceCurrentRef, kGetCatInformationMask, &sourceCatalogInfo, &sourceName, NULL, &sourceParentRef);
+ require_noerr(result, SourceFSGetCatalogInfoFailed);
+
+ result = FSGetCatalogInfo(&destCurrentRef, kGetCatInformationMask, &destCatalogInfo, &destName, NULL, &destParentRef);
+ require_noerr(result, DestFSGetCatalogInfoFailed);
+
+ /* make sure source and destination are on same volume */
+ require_action(sourceCatalogInfo.volume == destCatalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* make sure both files are *really* files */
+ require_action((0 == (sourceCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) &&
+ (0 == (destCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)), NotAFile, result = notAFileErr);
+
+ /* generate 2 names that are unique in both directories */
+ theSeed = 0x4a696d4c; /* a fine unlikely filename */
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &sourceUniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStr1Failed);
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &destUniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStr2Failed);
+
+ /* rename sourceCurrentRef to sourceUniqueName */
+ result = FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef);
+ require_noerr(result, FSRenameUnicode1Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* rename destCurrentRef to destUniqueName */
+ result = FSRenameUnicode(&destCurrentRef, destUniqueName.length, destUniqueName.unicode, kTextEncodingUnknown, newDestRef);
+ require_noerr(result, FSRenameUnicode2Failed);
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+
+ /* are the source and destination parent directories the same? */
+ sameParentDirs = ( sourceCatalogInfo.parentDirID == destCatalogInfo.parentDirID );
+ if ( !sameParentDirs )
+ {
+ /* move source file to dest parent directory */
+ result = FSMoveObject(&sourceCurrentRef, &destParentRef, newSourceRef);
+ require_noerr(result, FSMoveObject1Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* move dest file to source parent directory */
+ result = FSMoveObject(&destCurrentRef, &sourceParentRef, newDestRef);
+ require_noerr(result, FSMoveObject2Failed);
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+ }
+
+ /* At this point, the files are in their new locations (if they were moved). */
+ /* The source file is named sourceUniqueName and is in the directory referred to */
+ /* by destParentRef. The destination file is named destUniqueName and is in the */
+ /* directory referred to by sourceParentRef. */
+
+ /* give source file the dest file's catalog information except for mod dates */
+ result = FSSetCatalogInfo(&sourceCurrentRef, kSetCatinformationMask, &destCatalogInfo);
+ require_noerr(result, FSSetCatalogInfo1Failed);
+
+ /* give dest file the source file's catalog information except for mod dates */
+ result = FSSetCatalogInfo(&destCurrentRef, kSetCatinformationMask, &sourceCatalogInfo);
+ require_noerr(result, FSSetCatalogInfo2Failed);
+
+ /* rename source file with dest file's name */
+ result = FSRenameUnicode(&sourceCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newSourceRef);
+ require_noerr(result, FSRenameUnicode3Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* rename dest file with source file's name */
+ result = FSRenameUnicode(&destCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newDestRef);
+ require_noerr(result, FSRenameUnicode4Failed);
+
+ /* we're done with no errors, so swap newSourceRef and newDestRef */
+ BlockMoveData(newDestRef, newSourceRef, sizeof(FSRef));
+ BlockMoveData(&sourceCurrentRef, newDestRef, sizeof(FSRef));
+ }
+
+ return ( result );
+
+ /**********************/
+
+/* If there are any failures while emulating FSExchangeObjects, attempt to reverse any steps */
+/* already taken. In any case, newSourceRef and newDestRef will refer to the files in whatever */
+/* state and location they ended up in so that both files can be found by the calling code. */
+
+FSRenameUnicode4Failed:
+
+ /* attempt to rename source file to sourceUniqueName */
+ if ( noErr == FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef) )
+ {
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+ }
+
+FSRenameUnicode3Failed:
+
+ /* attempt to restore dest file's catalog information */
+ verify_noerr(FSSetCatalogInfo(&destCurrentRef, kFSCatInfoSettableInfo, &destCatalogInfo));
+
+FSSetCatalogInfo2Failed:
+
+ /* attempt to restore source file's catalog information */
+ verify_noerr(FSSetCatalogInfo(&sourceCurrentRef, kFSCatInfoSettableInfo, &sourceCatalogInfo));
+
+FSSetCatalogInfo1Failed:
+
+ if ( !sameParentDirs )
+ {
+ /* attempt to move dest file back to dest directory */
+ if ( noErr == FSMoveObject(&destCurrentRef, &destParentRef, newDestRef) )
+ {
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+ }
+ }
+
+FSMoveObject2Failed:
+
+ if ( !sameParentDirs )
+ {
+ /* attempt to move source file back to source directory */
+ if ( noErr == FSMoveObject(&sourceCurrentRef, &sourceParentRef, newSourceRef) )
+ {
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+ }
+ }
+
+FSMoveObject1Failed:
+
+ /* attempt to rename dest file to original name */
+ verify_noerr(FSRenameUnicode(&destCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newDestRef));
+
+FSRenameUnicode2Failed:
+
+ /* attempt to rename source file to original name */
+ verify_noerr(FSRenameUnicode(&sourceCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newSourceRef));
+
+FSRenameUnicode1Failed:
+GenerateUniqueHFSUniStr2Failed:
+GenerateUniqueHFSUniStr1Failed:
+NotAFile:
+NotSameVolume:
+DestFSGetCatalogInfoFailed:
+SourceFSGetCatalogInfoFailed:
+DetermineSourceVRefNumFailed:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Shared Environment Routines -----
+
+/*****************************************************************************/
+
+/* Renamed from FSLockRange to MFX_FSLockRange to avoid a conflict with
+ * the FSLockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSLockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioReqCount = rangeLength;
+ pb.ioParam.ioPosMode = fsFromStart;
+ pb.ioParam.ioPosOffset = rangeStart;
+ result = PBLockRangeSync(&pb);
+ require_noerr(result, PBLockRangeSync);
+
+PBLockRangeSync:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/* Renamed from FSUnlockRange to MFX_FSUnlockRange to avoid a conflict with
+ * the FSUnlockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSUnlockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioReqCount = rangeLength;
+ pb.ioParam.ioPosMode = fsFromStart;
+ pb.ioParam.ioPosOffset = rangeStart;
+ result = PBUnlockRangeSync(&pb);
+ require_noerr(result, PBUnlockRangeSync);
+
+PBUnlockRangeSync:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetDirAccess(
+ const FSRef *ref,
+ SInt32 *ownerID, /* can be NULL */
+ SInt32 *groupID, /* can be NULL */
+ SInt32 *accessRights) /* can be NULL */
+{
+ OSErr result;
+ FSSpec spec;
+ HParamBlockRec pb;
+
+ /* get FSSpec from FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* get directory access info for FSSpec */
+ pb.accessParam.ioNamePtr = (StringPtr)spec.name;
+ pb.accessParam.ioVRefNum = spec.vRefNum;
+ pb.fileParam.ioDirID = spec.parID;
+ result = PBHGetDirAccessSync(&pb);
+ require_noerr(result, PBHGetDirAccessSync);
+
+ /* return the IDs and access rights */
+ if ( NULL != ownerID )
+ {
+ *ownerID = pb.accessParam.ioACOwnerID;
+ }
+ if ( NULL != groupID )
+ {
+ *groupID = pb.accessParam.ioACGroupID;
+ }
+ if ( NULL != accessRights )
+ {
+ *accessRights = pb.accessParam.ioACAccess;
+ }
+
+PBHGetDirAccessSync:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetDirAccess(
+ const FSRef *ref,
+ SInt32 ownerID,
+ SInt32 groupID,
+ SInt32 accessRights)
+{
+ OSErr result;
+ FSSpec spec;
+ HParamBlockRec pb;
+
+ enum
+ {
+ /* Just the bits that can be set */
+ kSetDirAccessSettableMask = (kioACAccessBlankAccessMask +
+ kioACAccessEveryoneWriteMask + kioACAccessEveryoneReadMask + kioACAccessEveryoneSearchMask +
+ kioACAccessGroupWriteMask + kioACAccessGroupReadMask + kioACAccessGroupSearchMask +
+ kioACAccessOwnerWriteMask + kioACAccessOwnerReadMask + kioACAccessOwnerSearchMask)
+ };
+
+ /* get FSSpec from FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* set directory access info for FSSpec */
+ pb.accessParam.ioNamePtr = (StringPtr)spec.name;
+ pb.accessParam.ioVRefNum = spec.vRefNum;
+ pb.fileParam.ioDirID = spec.parID;
+ pb.accessParam.ioACOwnerID = ownerID;
+ pb.accessParam.ioACGroupID = groupID;
+ pb.accessParam.ioACAccess = accessRights & kSetDirAccessSettableMask;
+ result = PBHSetDirAccessSync(&pb);
+ require_noerr(result, PBHSetDirAccessSync);
+
+PBHSetDirAccessSync:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolMountInfoSize(
+ FSVolumeRefNum volRefNum,
+ SInt16 *size)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != size, BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)size;
+ result = PBGetVolMountInfoSize(&pb);
+ require_noerr(result, PBGetVolMountInfoSize);
+
+PBGetVolMountInfoSize:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolMountInfo(
+ FSVolumeRefNum volRefNum,
+ void *volMountInfo)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != volMountInfo, BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volMountInfo;
+ result = PBGetVolMountInfo(&pb);
+ require_noerr(result, PBGetVolMountInfo);
+
+PBGetVolMountInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+// This function exists in Mac OS X 10.5, we cannot re-define it here.
+// We don't use this function, so just don't compile it.
+#if 0
+OSErr
+FSVolumeMount(
+ const void *volMountInfo,
+ FSVolumeRefNum *volRefNum)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != volRefNum, BadParameter, result = paramErr);
+
+ pb.ioParam.ioBuffer = (Ptr)volMountInfo;
+ result = PBVolumeMount(&pb);
+ require_noerr(result, PBVolumeMount);
+
+ /* return the volume reference number */
+ *volRefNum = pb.ioParam.ioVRefNum;
+
+PBVolumeMount:
+BadParameter:
+
+ return ( result );
+}
+#endif
+
+/*****************************************************************************/
+
+OSErr
+FSMapID(
+ FSVolumeRefNum volRefNum,
+ SInt32 ugID,
+ SInt16 objType,
+ Str31 name)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != name, BadParameter, result = paramErr);
+
+ pb.objParam.ioNamePtr = NULL;
+ pb.objParam.ioVRefNum = volRefNum;
+ pb.objParam.ioObjType = objType;
+ pb.objParam.ioObjNamePtr = name;
+ pb.objParam.ioObjID = ugID;
+ result = PBHMapIDSync(&pb);
+ require_noerr(result, PBHMapIDSync);
+
+PBHMapIDSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMapName(
+ FSVolumeRefNum volRefNum,
+ ConstStr255Param name,
+ SInt16 objType,
+ SInt32 *ugID)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != ugID, BadParameter, result = paramErr);
+
+ pb.objParam.ioNamePtr = NULL;
+ pb.objParam.ioVRefNum = volRefNum;
+ pb.objParam.ioObjType = objType;
+ pb.objParam.ioObjNamePtr = (StringPtr)name;
+ result = PBHMapNameSync(&pb);
+ require_noerr(result, PBHMapNameSync);
+
+ /* return the user or group ID */
+ *ugID = pb.objParam.ioObjID;
+
+PBHMapNameSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFile(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *copyName, /* can be NULL (no rename during copy) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* can be NULL */
+{
+ OSErr result;
+ FSSpec srcFileSpec;
+ FSCatalogInfo catalogInfo;
+ HParamBlockRec pb;
+ Str31 hfsName;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+
+ /* get source FSSpec from source FSRef */
+ result = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
+ require_noerr(result, FSGetCatalogInfo_srcFileRef);
+
+ /* Make sure the volume supports CopyFile */
+ result = FSGetVolParms(srcFileSpec.vRefNum, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ require_action((noErr == result) && VolHasCopyFile(&volParmsInfo),
+ NoCopyFileSupport, result = paramErr);
+
+ /* get destination volume reference number and destination directory ID from destination FSRef */
+ result = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo_dstDirectoryRef);
+
+ /* tell the server to copy the object */
+ pb.copyParam.ioVRefNum = srcFileSpec.vRefNum;
+ pb.copyParam.ioDirID = srcFileSpec.parID;
+ pb.copyParam.ioNamePtr = (StringPtr)srcFileSpec.name;
+ pb.copyParam.ioDstVRefNum = catalogInfo.volume;
+ pb.copyParam.ioNewDirID = (long)catalogInfo.nodeID;
+ pb.copyParam.ioNewName = NULL;
+ if ( NULL != copyName )
+ {
+ result = UnicodeNameGetHFSName(nameLength, copyName, textEncodingHint, false, hfsName);
+ require_noerr(result, UnicodeNameGetHFSName);
+
+ pb.copyParam.ioCopyName = hfsName;
+ }
+ else
+ {
+ pb.copyParam.ioCopyName = NULL;
+ }
+ result = PBHCopyFileSync(&pb);
+ require_noerr(result, PBHCopyFileSync);
+
+ if ( NULL != newRef )
+ {
+ verify_noerr(FSMakeFSRef(pb.copyParam.ioDstVRefNum, pb.copyParam.ioNewDirID,
+ pb.copyParam.ioCopyName, newRef));
+ }
+
+PBHCopyFileSync:
+UnicodeNameGetHFSName:
+FSGetCatalogInfo_dstDirectoryRef:
+NoCopyFileSupport:
+FSGetCatalogInfo_srcFileRef:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMoveRename(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *moveName, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* can be NULL */
+{
+ OSErr result;
+ FSSpec srcFileSpec;
+ FSCatalogInfo catalogInfo;
+ HParamBlockRec pb;
+ Str31 hfsName;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+
+ /* get source FSSpec from source FSRef */
+ result = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
+ require_noerr(result, FSGetCatalogInfo_srcFileRef);
+
+ /* Make sure the volume supports MoveRename */
+ result = FSGetVolParms(srcFileSpec.vRefNum, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ require_action((noErr == result) && VolHasMoveRename(&volParmsInfo),
+ NoMoveRenameSupport, result = paramErr);
+
+ /* get destination volume reference number and destination directory ID from destination FSRef */
+ result = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo_dstDirectoryRef);
+
+ /* make sure the source and destination are on the same volume */
+ require_action(srcFileSpec.vRefNum == catalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* tell the server to move and rename the object */
+ pb.copyParam.ioVRefNum = srcFileSpec.vRefNum;
+ pb.copyParam.ioDirID = srcFileSpec.parID;
+ pb.copyParam.ioNamePtr = (StringPtr)srcFileSpec.name;
+ pb.copyParam.ioNewDirID = (long)catalogInfo.nodeID;
+ pb.copyParam.ioNewName = NULL;
+ if ( NULL != moveName )
+ {
+ result = UnicodeNameGetHFSName(nameLength, moveName, textEncodingHint, false, hfsName);
+ require_noerr(result, UnicodeNameGetHFSName);
+
+ pb.copyParam.ioCopyName = hfsName;
+ }
+ else
+ {
+ pb.copyParam.ioCopyName = NULL;
+ }
+ result = PBHMoveRenameSync(&pb);
+ require_noerr(result, PBHMoveRenameSync);
+
+ if ( NULL != newRef )
+ {
+ verify_noerr(FSMakeFSRef(pb.copyParam.ioVRefNum, pb.copyParam.ioNewDirID,
+ pb.copyParam.ioCopyName, newRef));
+ }
+
+PBHMoveRenameSync:
+UnicodeNameGetHFSName:
+NotSameVolume:
+FSGetCatalogInfo_dstDirectoryRef:
+NoMoveRenameSupport:
+FSGetCatalogInfo_srcFileRef:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- File ID Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSResolveFileIDRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 fileID,
+ FSRef *ref)
+{
+ OSErr result;
+ FIDParam pb;
+ Str255 tempStr;
+
+ /* check parameters */
+ require_action(NULL != ref, BadParameter, result = paramErr);
+
+ /* resolve the file ID reference */
+ tempStr[0] = 0;
+ pb.ioNamePtr = tempStr;
+ pb.ioVRefNum = volRefNum;
+ pb.ioFileID = fileID;
+ result = PBResolveFileIDRefSync((HParmBlkPtr)&pb);
+ require_noerr(result, PBResolveFileIDRefSync);
+
+ /* and then make an FSRef to the file */
+ result = FSMakeFSRef(volRefNum, pb.ioSrcDirID, tempStr, ref);
+ require_noerr(result, FSMakeFSRef);
+
+FSMakeFSRef:
+PBResolveFileIDRefSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCreateFileIDRef(
+ const FSRef *ref,
+ SInt32 *fileID)
+{
+ OSErr result;
+ FSSpec spec;
+ FIDParam pb;
+
+ /* check parameters */
+ require_action(NULL != fileID, BadParameter, result = paramErr);
+
+ /* Get an FSSpec from the FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Create (or get) the file ID reference using the FSSpec */
+ pb.ioNamePtr = (StringPtr)spec.name;
+ pb.ioVRefNum = spec.vRefNum;
+ pb.ioSrcDirID = spec.parID;
+ result = PBCreateFileIDRefSync((HParmBlkPtr)&pb);
+ require((noErr == result) || (fidExists == result) || (afpIDExists == result),
+ PBCreateFileIDRefSync);
+
+ /* return the file ID reference */
+ *fileID = pb.ioFileID;
+
+PBCreateFileIDRefSync:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Utility Routines -----
+
+/*****************************************************************************/
+
+Ptr
+GetTempBuffer(
+ ByteCount buffReqSize,
+ ByteCount *buffActSize)
+{
+ enum
+ {
+ kSlopMemory = 0x00008000 /* 32K - Amount of free memory to leave when allocating buffers */
+ };
+
+ Ptr tempPtr;
+
+ /* check parameters */
+ require_action(NULL != buffActSize, BadParameter, tempPtr = NULL);
+
+ /* Make request a multiple of 4K bytes */
+ buffReqSize = buffReqSize & 0xfffff000;
+
+ if ( buffReqSize < 0x00001000 )
+ {
+ /* Request was smaller than 4K bytes - make it 4K */
+ buffReqSize = 0x00001000;
+ }
+
+ /* Attempt to allocate the memory */
+ tempPtr = NewPtr(buffReqSize);
+
+ /* If request failed, go to backup plan */
+ if ( (tempPtr == NULL) && (buffReqSize > 0x00001000) )
+ {
+ /*
+ ** Try to get largest 4K byte block available
+ ** leaving some slop for the toolbox if possible
+ */
+ long freeMemory = (FreeMem() - kSlopMemory) & 0xfffff000;
+
+ buffReqSize = MaxBlock() & 0xfffff000;
+
+ if ( buffReqSize > freeMemory )
+ {
+ buffReqSize = freeMemory;
+ }
+
+ if ( buffReqSize == 0 )
+ {
+ buffReqSize = 0x00001000;
+ }
+
+ tempPtr = NewPtr(buffReqSize);
+ }
+
+ /* Return bytes allocated */
+ if ( tempPtr != NULL )
+ {
+ *buffActSize = buffReqSize;
+ }
+ else
+ {
+ *buffActSize = 0;
+ }
+
+BadParameter:
+
+ return ( tempPtr );
+}
+
+/*****************************************************************************/
+
+OSErr
+FileRefNumGetFSRef(
+ short refNum,
+ FSRef *ref)
+{
+ return ( FSGetForkCBInfo(refNum, 0, NULL, NULL, NULL, ref, NULL) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetDefault(
+ const FSRef *newDefault,
+ FSRef *oldDefault)
+{
+ OSErr result;
+ FSVolumeRefNum vRefNum;
+ long dirID;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action((NULL != newDefault) && (NULL != oldDefault), BadParameter, result = paramErr);
+
+ /* Get nodeFlags, vRefNum and dirID (nodeID) of newDefault */
+ result = FSGetCatalogInfo(newDefault,
+ kFSCatInfoNodeFlags + kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Make sure newDefault is a directory */
+ require_action(0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags), NewDefaultNotDirectory,
+ result = dirNFErr);
+
+ /* Get the current working directory. */
+ result = HGetVol(NULL, &vRefNum, &dirID);
+ require_noerr(result, HGetVol);
+
+ /* Return the oldDefault FSRef */
+ result = FSMakeFSRef(vRefNum, dirID, NULL, oldDefault);
+ require_noerr(result, FSMakeFSRef);
+
+ /* Set the new current working directory */
+ result = HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID);
+ require_noerr(result, HSetVol);
+
+HSetVol:
+FSMakeFSRef:
+HGetVol:
+NewDefaultNotDirectory:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSRestoreDefault(
+ const FSRef *oldDefault)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != oldDefault, BadParameter, result = paramErr);
+
+ /* Get nodeFlags, vRefNum and dirID (nodeID) of oldDefault */
+ result = FSGetCatalogInfo(oldDefault,
+ kFSCatInfoNodeFlags + kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Make sure oldDefault is a directory */
+ require_action(0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags), OldDefaultNotDirectory,
+ result = dirNFErr);
+
+ /* Set the current working directory to oldDefault */
+ result = HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID);
+ require_noerr(result, HSetVol);
+
+HSetVol:
+OldDefaultNotDirectory:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h
new file mode 100644
index 00000000..378e4552
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h
@@ -0,0 +1,1800 @@
+/*
+ File: MoreFilesX.h
+
+ Contains: A collection of useful high-level File Manager routines
+ which use the HFS Plus APIs wherever possible.
+
+ Version: MoreFilesX 1.0.1
+
+
+*/
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+// Modified 2006-01-23 - added this comment.
+
+#ifndef __MOREFILESX__
+#define __MOREFILESX__
+
+#ifndef __CARBON__
+ #if defined(__MACH__)
+ #include <Carbon/Carbon.h>
+ #else
+ #include <Carbon.h>
+ #endif
+#endif
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PRAGMA_IMPORT
+#pragma import on
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+
+/*****************************************************************************/
+
+#pragma mark ----- FinderInfo and ExtendedFinderInfo -----
+
+/*
+ * FSGetFinderInfo and FSSetFinderInfo use these unions for Finder information.
+ */
+
+union FinderInfo
+{
+ FileInfo file;
+ FolderInfo folder;
+};
+typedef union FinderInfo FinderInfo;
+
+union ExtendedFinderInfo
+{
+ ExtendedFileInfo file;
+ ExtendedFolderInfo folder;
+};
+typedef union ExtendedFinderInfo ExtendedFinderInfo;
+
+/*****************************************************************************/
+
+#pragma mark ----- GetVolParmsInfoBuffer Macros -----
+
+/*
+ * Macros to get information out of GetVolParmsInfoBuffer.
+ */
+
+/* version 1 field getters */
+#define GetVolParmsInfoVersion(volParms) \
+ ((volParms)->vMVersion)
+#define GetVolParmsInfoAttrib(volParms) \
+ ((volParms)->vMAttrib)
+#define GetVolParmsInfoLocalHand(volParms) \
+ ((volParms)->vMLocalHand)
+#define GetVolParmsInfoServerAdr(volParms) \
+ ((volParms)->vMServerAdr)
+
+/* version 2 field getters (assume zero result if version < 2) */
+#define GetVolParmsInfoVolumeGrade(volParms) \
+ (((volParms)->vMVersion >= 2) ? (volParms)->vMVolumeGrade : 0)
+#define GetVolParmsInfoForeignPrivID(volParms) \
+ (((volParms)->vMVersion >= 2) ? (volParms)->vMForeignPrivID : 0)
+
+/* version 3 field getters (assume zero result if version < 3) */
+#define GetVolParmsInfoExtendedAttributes(volParms) \
+ (((volParms)->vMVersion >= 3) ? (volParms)->vMExtendedAttributes : 0)
+
+/* attribute bits supported by all versions of GetVolParmsInfoBuffer */
+#define VolIsNetworkVolume(volParms) \
+ ((volParms)->vMServerAdr != 0)
+#define VolHasLimitFCBs(volParms) \
+ (((volParms)->vMAttrib & (1L << bLimitFCBs)) != 0)
+#define VolHasLocalWList(volParms) \
+ (((volParms)->vMAttrib & (1L << bLocalWList)) != 0)
+#define VolHasNoMiniFndr(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoMiniFndr)) != 0)
+#define VolHasNoVNEdit(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoVNEdit)) != 0)
+#define VolHasNoLclSync(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoLclSync)) != 0)
+#define VolHasTrshOffLine(volParms) \
+ (((volParms)->vMAttrib & (1L << bTrshOffLine)) != 0)
+#define VolHasNoSwitchTo(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoSwitchTo)) != 0)
+#define VolHasNoDeskItems(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoDeskItems)) != 0)
+#define VolHasNoBootBlks(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoBootBlks)) != 0)
+#define VolHasAccessCntl(volParms) \
+ (((volParms)->vMAttrib & (1L << bAccessCntl)) != 0)
+#define VolHasNoSysDir(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoSysDir)) != 0)
+#define VolHasExtFSVol(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasExtFSVol)) != 0)
+#define VolHasOpenDeny(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasOpenDeny)) != 0)
+#define VolHasCopyFile(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasCopyFile)) != 0)
+#define VolHasMoveRename(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasMoveRename)) != 0)
+#define VolHasDesktopMgr(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasDesktopMgr)) != 0)
+#define VolHasShortName(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasShortName)) != 0)
+#define VolHasFolderLock(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasFolderLock)) != 0)
+#define VolHasPersonalAccessPrivileges(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasPersonalAccessPrivileges)) != 0)
+#define VolHasUserGroupList(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasUserGroupList)) != 0)
+#define VolHasCatSearch(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasCatSearch)) != 0)
+#define VolHasFileIDs(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasFileIDs)) != 0)
+#define VolHasBTreeMgr(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasBTreeMgr)) != 0)
+#define VolHasBlankAccessPrivileges(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasBlankAccessPrivileges)) != 0)
+#define VolSupportsAsyncRequests(volParms) \
+ (((volParms)->vMAttrib & (1L << bSupportsAsyncRequests)) != 0)
+#define VolSupportsTrashVolumeCache(volParms) \
+ (((volParms)->vMAttrib & (1L << bSupportsTrashVolumeCache)) != 0)
+
+/* attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer */
+#define VolIsEjectable(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsEjectable)) != 0)
+#define VolSupportsHFSPlusAPIs(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsHFSPlusAPIs)) != 0)
+#define VolSupportsFSCatalogSearch(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSCatalogSearch)) != 0)
+#define VolSupportsFSExchangeObjects(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSExchangeObjects)) != 0)
+#define VolSupports2TBFiles(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupports2TBFiles)) != 0)
+#define VolSupportsLongNames(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsLongNames)) != 0)
+#define VolSupportsMultiScriptNames(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsMultiScriptNames)) != 0)
+#define VolSupportsNamedForks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsNamedForks)) != 0)
+#define VolSupportsSubtreeIterators(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSubtreeIterators)) != 0)
+#define VolL2PCanMapFileBlocks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bL2PCanMapFileBlocks)) != 0)
+#define VolParentModDateChanges(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bParentModDateChanges)) != 0)
+#define VolAncestorModDateChanges(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bAncestorModDateChanges)) != 0)
+#define VolSupportsSymbolicLinks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSymbolicLinks)) != 0)
+#define VolIsAutoMounted(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsAutoMounted)) != 0)
+
+/*****************************************************************************/
+
+#pragma mark ----- userPrivileges Bit Masks and Macros -----
+
+/*
+ * Bit masks and macros to get common information out of userPrivileges byte
+ * returned by FSGetCatalogInfo.
+ *
+ * Note: The userPrivileges byte is the same as the ioACUser byte returned
+ * by PBGetCatInfo, and is the 1's complement of the user's privileges
+ * byte returned in ioACAccess by PBHGetDirAccess. That's where the
+ * ioACUser names came from.
+ *
+ * The userPrivileges are user's effective privileges based on the
+ * user ID and the groups that user belongs to, and the owner, group,
+ * and everyone privileges for the given directory.
+ */
+
+enum
+{
+ /* mask for just the access restriction bits */
+ kioACUserAccessMask = (kioACUserNoSeeFolderMask +
+ kioACUserNoSeeFilesMask +
+ kioACUserNoMakeChangesMask),
+ /* common access privilege settings */
+ kioACUserFull = 0x00, /* no access restiction bits on */
+ kioACUserNone = kioACUserAccessMask, /* all access restiction bits on */
+ kioACUserDropBox = (kioACUserNoSeeFolderMask +
+ kioACUserNoSeeFilesMask), /* make changes, but not see files or folders */
+ kioACUserBulletinBoard = kioACUserNoMakeChangesMask /* see files and folders, but not make changes */
+};
+
+
+/* Macros for testing ioACUser bits. */
+
+#define UserIsOwner(userPrivileges) \
+ (((userPrivileges) & kioACUserNotOwnerMask) == 0)
+#define UserHasFullAccess(userPrivileges) \
+ (((userPrivileges) & (kioACUserAccessMask)) == kioACUserFull)
+#define UserHasDropBoxAccess(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserDropBox)
+#define UserHasBulletinBoard(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserBulletinBoard)
+#define UserHasNoAccess(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserNone)
+
+/*****************************************************************************/
+
+#pragma mark ----- File Access Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFork
+
+OSErr
+FSCopyFork(
+ SInt16 srcRefNum,
+ SInt16 dstRefNum,
+ void *copyBufferPtr,
+ ByteCount copyBufferSize);
+
+/*
+ The FSCopyFork function copies all data from the source fork to the
+ destination fork of open file forks and makes sure the destination EOF
+ is equal to the source EOF.
+
+ srcRefNum --> The source file reference number.
+ dstRefNum --> The destination file reference number.
+ copyBufferPtr --> Pointer to buffer to use during copy. The
+ buffer should be at least 4K-bytes minimum.
+ The larger the buffer, the faster the copy
+ (up to a point).
+ copyBufferSize --> The size of the copy buffer.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Volume Access Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolParms
+
+OSErr
+FSGetVolParms(
+ FSVolumeRefNum volRefNum,
+ UInt32 bufferSize,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ UInt32 *actualInfoSize);
+
+/*
+ The FSGetVolParms function returns information about the characteristics
+ of a volume. A result of paramErr usually just means the volume doesn't
+ support GetVolParms and the feature you were going to check
+ for isn't available.
+
+ volRefNum --> Volume specification.
+ bufferSize --> Size of buffer pointed to by volParmsInfo.
+ volParmsInfo <-- A GetVolParmsInfoBuffer record where the volume
+ attributes information is returned.
+ actualInfoSize <-- The number of bytes actually returned
+ in volParmsInfo.
+
+ __________
+
+ Also see: The GetVolParmsInfoBuffer Macros for checking attribute bits
+ in this file
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVRefNum
+
+OSErr
+FSGetVRefNum(
+ const FSRef *ref,
+ FSVolumeRefNum *vRefNum);
+
+/*
+ The FSGetVRefNum function determines the volume reference
+ number of a volume from a FSRef.
+
+ ref --> The FSRef.
+ vRefNum <-- The volume reference number.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVInfo
+
+OSErr
+FSGetVInfo(
+ FSVolumeRefNum volume,
+ HFSUniStr255 *volumeName, /* can be NULL */
+ UInt64 *freeBytes, /* can be NULL */
+ UInt64 *totalBytes); /* can be NULL */
+
+/*
+ The FSGetVInfo function returns the name, available space (in bytes),
+ and total space (in bytes) for the specified volume.
+
+ volume --> The volume reference number.
+ volumeName <** An optional pointer to a HFSUniStr255.
+ If not NULL, the volume name will be returned in
+ the HFSUniStr255.
+ freeBytes <** An optional pointer to a UInt64.
+ If not NULL, the number of free bytes on the
+ volume will be returned in the UInt64.
+ totalBytes <** An optional pointer to a UInt64.
+ If not NULL, the total number of bytes on the
+ volume will be returned in the UInt64.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolFileSystemID
+
+OSErr
+FSGetVolFileSystemID(
+ FSVolumeRefNum volume,
+ UInt16 *fileSystemID, /* can be NULL */
+ UInt16 *signature); /* can be NULL */
+
+/*
+ The FSGetVolFileSystemID function returns the file system ID and signature
+ of a mounted volume. The file system ID identifies the file system
+ that handles requests to a particular volume. The signature identifies the
+ volume type of the volume (for example, FSID 0 is Macintosh HFS Plus, HFS
+ or MFS, where a signature of 0x4244 identifies the volume as HFS).
+ Here's a partial list of file system ID numbers (only Apple's file systems
+ are listed):
+ FSID File System
+ ----- -----------------------------------------------------
+ $0000 Macintosh HFS Plus, HFS or MFS
+ $0100 ProDOS File System
+ $0101 PowerTalk Mail Enclosures
+ $4147 ISO 9660 File Access (through Foreign File Access)
+ $4242 High Sierra File Access (through Foreign File Access)
+ $464D QuickTake File System (through Foreign File Access)
+ $4953 Macintosh PC Exchange (MS-DOS)
+ $4A48 Audio CD Access (through Foreign File Access)
+ $4D4B Apple Photo Access (through Foreign File Access)
+ $6173 AppleShare (later versions of AppleShare only)
+
+ See the Technical Note "FL 35 - Determining Which File System
+ Is Active" and the "Guide to the File System Manager" for more
+ information.
+
+ volume --> The volume reference number.
+ fileSystemID <** An optional pointer to a UInt16.
+ If not NULL, the volume's file system ID will
+ be returned in the UInt16.
+ signature <** An optional pointer to a UInt16.
+ If not NULL, the volume's signature will
+ be returned in the UInt16.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetMountedVolumes
+
+OSErr
+FSGetMountedVolumes(
+ FSRef ***volumeRefsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numVolumes);
+
+/*
+ The FSGetMountedVolumes function returns the list of volumes currently
+ mounted in an array of FSRef records. The array of FSRef records is
+ returned in a Handle, volumeRefsHandle, which is allocated by
+ FSGetMountedVolumes. The caller is responsible for disposing of
+ volumeRefsHandle if the FSGetMountedVolumes returns noErr.
+
+ volumeRefsHandle <-- Pointer to an FSRef Handle where the array of
+ FSRefs is to be returned.
+ numVolumes <-- The number of volumes returned in the array.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- FSRef/FSpec/Path/Name Conversion Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSRefMakeFSSpec
+
+OSErr
+FSRefMakeFSSpec(
+ const FSRef *ref,
+ FSSpec *spec);
+
+/*
+ The FSRefMakeFSSpec function returns an FSSpec for the file or
+ directory specified by the ref parameter.
+
+ ref --> An FSRef specifying the file or directory.
+ spec <-- The FSSpec.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMakeFSRef
+
+OSErr
+FSMakeFSRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ FSRef *ref);
+
+/*
+ The FSMakeFSRef function creates an FSRef from the traditional
+ volume reference number, directory ID and pathname inputs. It is
+ functionally equivalent to FSMakeFSSpec followed by FSpMakeFSRef.
+
+ volRefNum --> Volume specification.
+ dirID --> Directory specification.
+ name --> The file or directory name, or NULL.
+ ref <-- The FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMakePath
+
+OSStatus
+FSMakePath(
+ SInt16 vRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ UInt8 *path,
+ UInt32 maxPathSize);
+
+/*
+ The FSMakePath function creates a pathname from the traditional volume reference
+ number, directory ID, and pathname inputs. It is functionally equivalent to
+ FSMakeFSSpec, FSpMakeFSRef, FSRefMakePath.
+
+ volRefNum --> Volume specification.
+ dirID --> Directory specification.
+ name --> The file or directory name, or NULL.
+ path <-- A pointer to a buffer which FSMakePath will
+ fill with a C string representing the pathname
+ to the file or directory specified. The format of
+ the pathname returned can be determined with the
+ Gestalt selector gestaltFSAttr's
+ gestaltFSUsesPOSIXPathsForConversion bit.
+ If the gestaltFSUsesPOSIXPathsForConversion bit is
+ clear, the pathname is a Mac OS File Manager full
+ pathname in a C string, and file or directory names
+ in the pathname may be mangled as returned by
+ the File Manager. If the
+ gestaltFSUsesPOSIXPathsForConversion bit is set,
+ the pathname is a UTF8 encoded POSIX absolute
+ pathname in a C string. In either case, the
+ pathname returned can be passed back to
+ FSPathMakeRef to create an FSRef to the file or
+ directory, or FSPathMakeFSSpec to craete an FSSpec
+ to the file or directory.
+ maxPathSize --> The size of the path buffer in bytes. If the path
+ buffer is too small for the pathname string,
+ FSMakePath returns pathTooLongErr or
+ buffersTooSmall.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSPathMakeFSSpec
+
+OSStatus
+FSPathMakeFSSpec(
+ const UInt8 *path,
+ FSSpec *spec,
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The FSPathMakeFSSpec function converts a pathname to an FSSpec.
+
+ path --> A pointer to a C String that is the pathname. The
+ format of the pathname you must supply can be
+ determined with the Gestalt selector gestaltFSAttr's
+ gestaltFSUsesPOSIXPathsForConversion bit.
+ If the gestaltFSUsesPOSIXPathsForConversion bit is
+ clear, the pathname must be a Mac OS File Manager
+ full pathname in a C string. If the
+ gestaltFSUsesPOSIXPathsForConversion bit is set,
+ the pathname must be a UTF8 encoded POSIX absolute
+ pathname in a C string.
+ spec <-- The FSSpec.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the specified path is a directory, or false will
+ be returned in the Boolean if the specified path is
+ a file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark UnicodeNameGetHFSName
+
+OSErr
+UnicodeNameGetHFSName(
+ UniCharCount nameLength,
+ const UniChar *name,
+ TextEncoding textEncodingHint,
+ Boolean isVolumeName,
+ Str31 hfsName);
+
+/*
+ The UnicodeNameGetHFSName function converts a Unicode string
+ to a Pascal Str31 (or Str27) string using an algorithm similar to that used
+ by the File Manager. Note that if the name is too long or cannot be converted
+ using the given text encoding hint, you will get an error instead of the
+ mangled name that the File Manager would return.
+
+ nameLength --> Number of UniChar in name parameter.
+ name --> The Unicode string to convert.
+ textEncodingHint --> The text encoding hint used for the conversion.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ isVolumeName --> If true, the output name will be limited to
+ 27 characters (kHFSMaxVolumeNameChars). If false,
+ the output name will be limited to 31 characters
+ (kHFSMaxFileNameChars).
+ hfsName <-- The hfsName as a Pascal string.
+
+ __________
+
+ Also see: HFSNameGetUnicodeName
+*/
+
+/*****************************************************************************/
+
+#pragma mark HFSNameGetUnicodeName
+
+OSErr
+HFSNameGetUnicodeName(
+ ConstStr31Param hfsName,
+ TextEncoding textEncodingHint,
+ HFSUniStr255 *unicodeName);
+
+/*
+ The HFSNameGetUnicodeName function converts a Pascal Str31 string to an
+ Unicode HFSUniStr255 string using the same routines as the File Manager.
+
+ hfsName --> The Pascal string to convert.
+ textEncodingHint --> The text encoding hint used for the conversion.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ unicodeName <-- The Unicode string.
+
+ __________
+
+ Also see: UnicodeNameGetHFSName
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- File/Directory Manipulation Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSRefValid
+
+Boolean FSRefValid(const FSRef *ref);
+
+/*
+ The FSRefValid function determines if an FSRef is valid. If the result is
+ true, then the FSRef refers to an existing file or directory.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetParentRef
+
+OSErr
+FSGetParentRef(
+ const FSRef *ref,
+ FSRef *parentRef);
+
+/*
+ The FSGetParentRef function gets the parent directory FSRef of the
+ specified object.
+
+ Note: FSRefs always point to real file system objects. So, there cannot
+ be a FSRef to the parent of volume root directories. If you call
+ FSGetParentRef with a ref to the root directory of a volume, the
+ function result will be noErr and the parentRef will be invalid (using it
+ for other file system requests will fail).
+
+ ref --> FSRef to a file or directory.
+ parentRef <-- The parent directory's FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetFileDirName
+
+OSErr
+FSGetFileDirName(
+ const FSRef *ref,
+ HFSUniStr255 *outName);
+
+/*
+ The FSGetFileDirName function gets the name of the file or directory
+ specified.
+
+ ref --> FSRef to a file or directory.
+ outName <-- The file or directory name.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetNodeID
+
+OSErr
+FSGetNodeID(
+ const FSRef *ref,
+ long *nodeID, /* can be NULL */
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The GetNodeIDFromFSRef function gets the node ID number of the
+ file or directory specified (note: the node ID is the directory ID
+ for directories).
+
+ ref --> FSRef to a file or directory.
+ nodeID <** An optional pointer to a long.
+ If not NULL, the node ID will be returned in
+ the long.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the object is a directory, or false will be
+ returned in the Boolean if object is a file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetUserPrivilegesPermissions
+
+OSErr
+FSGetUserPrivilegesPermissions(
+ const FSRef *ref,
+ UInt8 *userPrivileges, /* can be NULL */
+ UInt32 permissions[4]); /* can be NULL */
+
+/*
+ The FSGetUserPrivilegesPermissions function gets the userPrivileges and/or
+ permissions of the file or directory specified.
+
+ ref --> FSRef to a file or directory.
+ userPrivileges <** An optional pointer to a UInt8.
+ If not NULL, the userPrivileges will be returned
+ in the UInt8.
+ permissions <** An optional pointer to an UInt32[4] array.
+ If not NULL, the permissions will be returned
+ in the UInt32[4] array.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCheckLock
+
+OSErr
+FSCheckLock(
+ const FSRef *ref);
+
+/*
+ The FSCheckLock function determines if a file or directory is locked.
+ If FSCheckLock returns noErr, then the file or directory is not locked
+ and the volume it is on is not locked either. If FSCheckLock returns
+ fLckdErr, then the file or directory is locked. If FSCheckLock returns
+ wPrErr, then the volume is locked by hardware (i.e., locked tab on
+ removable media). If FSCheckLock returns vLckdErr, then the volume is
+ locked by software.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetForkSizes
+
+OSErr
+FSGetForkSizes(
+ const FSRef *ref,
+ UInt64 *dataLogicalSize, /* can be NULL */
+ UInt64 *rsrcLogicalSize); /* can be NULL */
+
+/*
+ The FSGetForkSizes returns the size of the data and/or resource fork for
+ the specified file.
+
+ ref --> FSRef to a file or directory.
+ dataLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the data fork's size will be
+ returned in the UInt64.
+ rsrcLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the resource fork's size will be
+ returned in the UInt64.
+
+ __________
+
+ Also see: FSGetTotalForkSizes
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetTotalForkSizes
+
+OSErr
+FSGetTotalForkSizes(
+ const FSRef *ref,
+ UInt64 *totalLogicalSize, /* can be NULL */
+ UInt64 *totalPhysicalSize, /* can be NULL */
+ ItemCount *forkCount); /* can be NULL */
+
+/*
+ The FSGetTotalForkSizes returns the total logical size and/or the total
+ physical size of the specified file (i.e., it adds the sizes of all file
+ forks). It optionally returns the number of file forks.
+
+ ref --> FSRef to a file or directory.
+ totalLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the sum of all fork logical sizes
+ will be returned in the UInt64.
+ totalPhysicalSize <** An optional pointer to a UInt64.
+ If not NULL, the sum of all fork physical sizes
+ will be returned in the UInt64.
+ forkCount <** An optional pointer to a ItemCount.
+ If not NULL, the number of file forks
+ will be returned in the ItemCount.
+
+ __________
+
+ Also see: FSGetForkSizes
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSBumpDate
+
+OSErr
+FSBumpDate(
+ const FSRef *ref);
+
+/*
+ The FSBumpDate function changes the content modification date of a file
+ or directory to the current date/time. If the content modification date
+ is already equal to the current date/time, then add one second to the
+ content modification date.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetFinderInfo
+
+OSErr
+FSGetFinderInfo(
+ const FSRef *ref,
+ FinderInfo *info, /* can be NULL */
+ ExtendedFinderInfo *extendedInfo, /* can be NULL */
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The FSGetFinderInfo function gets the finder information for a file or
+ directory.
+
+ ref --> FSRef to a file or directory.
+ info <** An optional pointer to a FinderInfo.
+ If not NULL, the FileInfo (if ref is a file) or
+ the FolderInfo (if ref is a folder) will be
+ returned in the FinderInfo.
+ extendedInfo <** An optional pointer to a ExtendedFinderInfo.
+ If not NULL, the ExtendedFileInfo (if ref is a file)
+ or the ExtendedFolderInfo (if ref is a folder) will
+ be returned in the ExtendedFinderInfo.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the object is a directory, or false will be
+ returned in the Boolean if object is a file.
+
+ __________
+
+ Also see: FSSetFinderInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetFinderInfo
+
+OSErr
+FSSetFinderInfo(
+ const FSRef *ref,
+ const FinderInfo *info, /* can be NULL */
+ const ExtendedFinderInfo *extendedInfo); /* can be NULL */
+
+/*
+ The FSSetFinderInfo function sets the finder information for a file or
+ directory.
+
+ ref --> FSRef to a file or directory.
+ info **> A pointer to a FinderInfo record with the new
+ FileInfo (if ref is a file) or new FolderInfo
+ (if ref is a folder), or NULL if the FinderInfo
+ is not to be changed.
+ extendedInfo **> A pointer to a FinderInfo record with the new
+ ExtendedFileInfo (if ref is a file) or new
+ ExtendedFolderInfo (if ref is a folder), or NULL
+ if the ExtendedFinderInfo is not to be changed.
+
+ __________
+
+ Also see: FSGetFinderInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSChangeCreatorType
+
+OSErr
+FSChangeCreatorType(
+ const FSRef *ref,
+ OSType fileCreator,
+ OSType fileType);
+
+/*
+ The FSChangeCreatorType function changes the creator and/or file type of a file.
+
+ ref --> FSRef to a file.
+ creator --> The new creator type or 0x00000000 to leave
+ the creator type alone.
+ fileType --> The new file type or 0x00000000 to leave the
+ file type alone.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSChangeFinderFlags
+
+OSErr
+FSChangeFinderFlags(
+ const FSRef *ref,
+ Boolean setBits,
+ UInt16 flagBits);
+
+/*
+ The FSChangeFinderFlags function sets or clears flag bits in
+ the finderFlags field of a file's FileInfo record or a
+ directory's FolderInfo record.
+
+ ref --> FSRef to a file or directory.
+ setBits --> If true, then set the bits specified in flagBits.
+ If false, then clear the bits specified in flagBits.
+ flagBits --> The flagBits parameter specifies which Finder Flag
+ bits to set or clear. If a bit in flagBits is set,
+ then the same bit in fdFlags is either set or
+ cleared depending on the state of the setBits
+ parameter.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetInvisible
+
+OSErr
+FSSetInvisible(
+ const FSRef *ref);
+
+#pragma mark FSClearInvisible
+
+OSErr
+FSClearInvisible(
+ const FSRef *ref);
+
+/*
+ The FSSetInvisible and FSClearInvisible functions set or clear the
+ kIsInvisible bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetNameLocked
+
+OSErr
+FSSetNameLocked(
+ const FSRef *ref);
+
+#pragma mark FSClearNameLocked
+
+OSErr
+FSClearNameLocked(
+ const FSRef *ref);
+
+/*
+ The FSSetNameLocked and FSClearNameLocked functions set or clear the
+ kNameLocked bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetIsStationery
+
+OSErr
+FSSetIsStationery(
+ const FSRef *ref);
+
+#pragma mark FSClearIsStationery
+
+OSErr
+FSClearIsStationery(
+ const FSRef *ref);
+
+/*
+ The FSSetIsStationery and FSClearIsStationery functions set or clear the
+ kIsStationery bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetHasCustomIcon
+
+OSErr
+FSSetHasCustomIcon(
+ const FSRef *ref);
+
+#pragma mark FSClearHasCustomIcon
+
+OSErr
+FSClearHasCustomIcon(
+ const FSRef *ref);
+
+/*
+ The FSSetHasCustomIcon and FSClearHasCustomIcon functions set or clear the
+ kHasCustomIcon bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSClearHasBeenInited
+
+OSErr
+FSClearHasBeenInited(
+ const FSRef *ref);
+
+/*
+ The FSClearHasBeenInited function clears the kHasBeenInited bit in the
+ finderFlags field of the specified file or directory's finder information.
+
+ Note: There is no FSSetHasBeenInited function because ONLY the Finder
+ should set the kHasBeenInited bit.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFileMgrAttributes
+
+OSErr
+FSCopyFileMgrAttributes(
+ const FSRef *sourceRef,
+ const FSRef *destinationRef,
+ Boolean copyLockBit);
+
+/*
+ The CopyFileMgrAttributes function copies all File Manager attributes
+ from the source file or directory to the destination file or directory.
+ If copyLockBit is true, then set the locked state of the destination
+ to match the source.
+
+ sourceRef --> FSRef to a file or directory.
+ destinationRef --> FSRef to a file or directory.
+ copyLockBit --> If true, set the locked state of the destination
+ to match the source.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMoveRenameObjectUnicode
+
+OSErr
+FSMoveRenameObjectUnicode(
+ const FSRef *ref,
+ const FSRef *destDirectory,
+ UniCharCount nameLength,
+ const UniChar *name, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* if function fails along the way, newRef is final location of file */
+
+/*
+ The FSMoveRenameObjectUnicode function moves a file or directory and
+ optionally renames it. The source and destination locations must be on
+ the same volume.
+
+ Note: If the input ref parameter is invalid, this call will fail and
+ newRef, like ref, will be invalid.
+
+ ref --> FSRef to a file or directory.
+ destDirectory --> FSRef to the destination directory.
+ nameLength --> Number of UniChar in name parameter.
+ name --> An Unicode string with the new name for the
+ moved object, or NULL if no rename is wanted.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <-- The new FSRef of the object moved. Note that if
+ this function fails at any step along the way,
+ newRef is still then final location of the object.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteContainerContents
+
+OSErr
+FSDeleteContainerContents(
+ const FSRef *container);
+
+/*
+ The FSDeleteContainerContents function deletes the contents of a container
+ directory. All files and subdirectories in the specified container are
+ deleted. If a locked file or directory is encountered, it is unlocked and
+ then deleted. If any unexpected errors are encountered,
+ FSDeleteContainerContents quits and returns to the caller.
+
+ container --> FSRef to a directory.
+
+ __________
+
+ Also see: FSDeleteContainer
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteContainer
+
+OSErr
+FSDeleteContainer(
+ const FSRef *container);
+
+/*
+ The FSDeleteContainer function deletes a container directory and its contents.
+ All files and subdirectories in the specified container are deleted.
+ If a locked file or directory is encountered, it is unlocked and then
+ deleted. After deleting the container's contents, the container is
+ deleted. If any unexpected errors are encountered, FSDeleteContainer
+ quits and returns to the caller.
+
+ container --> FSRef to a directory.
+
+ __________
+
+ Also see: FSDeleteContainerContents
+*/
+
+/*****************************************************************************/
+
+#pragma mark IterateContainerFilterProcPtr
+
+typedef CALLBACK_API( Boolean , IterateContainerFilterProcPtr ) (
+ Boolean containerChanged,
+ ItemCount currentLevel,
+ const FSCatalogInfo *catalogInfo,
+ const FSRef *ref,
+ const FSSpec *spec,
+ const HFSUniStr255 *name,
+ void *yourDataPtr);
+
+/*
+ This is the prototype for the IterateContainerFilterProc function which
+ is called once for each file and directory found by FSIterateContainer.
+ The IterateContainerFilterProc can use the read-only data it receives for
+ whatever it wants.
+
+ The result of the IterateContainerFilterProc function indicates if
+ iteration should be stopped. To stop iteration, return true; to continue
+ iteration, return false.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within the IterateContainerFilterProc.
+
+ containerChanged --> Set to true if the container's contents changed
+ during iteration.
+ currentLevel --> The current recursion level into the container.
+ 1 = the container, 2 = the container's immediate
+ subdirectories, etc.
+ catalogInfo --> The catalog information for the current object.
+ Only the fields requested by the whichInfo
+ parameter passed to FSIterateContainer are valid.
+ ref --> The FSRef to the current object.
+ spec --> The FSSpec to the current object if the wantFSSpec
+ parameter passed to FSIterateContainer is true.
+ name --> The name of the current object if the wantName
+ parameter passed to FSIterateContainer is true.
+ yourDataPtr --> An optional pointer to whatever data structure you
+ might want to access from within the
+ IterateFilterProc.
+ result <-- To stop iteration, return true; to continue
+ iteration, return false.
+
+ __________
+
+ Also see: FSIterateContainer
+*/
+
+/*****************************************************************************/
+
+#pragma mark CallIterateContainerFilterProc
+
+#define CallIterateContainerFilterProc(userRoutine, containerChanged, currentLevel, catalogInfo, ref, spec, name, yourDataPtr) \
+ (*(userRoutine))((containerChanged), (currentLevel), (catalogInfo), (ref), (spec), (name), (yourDataPtr))
+
+/*****************************************************************************/
+
+#pragma mark FSIterateContainer
+
+OSErr
+FSIterateContainer(
+ const FSRef *container,
+ ItemCount maxLevels,
+ FSCatalogInfoBitmap whichInfo,
+ Boolean wantFSSpec,
+ Boolean wantName,
+ IterateContainerFilterProcPtr iterateFilter,
+ void *yourDataPtr);
+
+/*
+ The FSIterateContainer function performs a recursive iteration (scan) of the
+ specified container directory and calls your IterateContainerFilterProc
+ function once for each file and directory found.
+
+ The maxLevels parameter lets you control how deep the recursion goes.
+ If maxLevels is 1, FSIterateContainer only scans the specified directory;
+ if maxLevels is 2, FSIterateContainer scans the specified directory and
+ one subdirectory below the specified directory; etc. Set maxLevels to
+ zero to scan all levels.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within your IterateContainerFilterProc.
+
+ container --> The FSRef to the container directory to iterate.
+ maxLevels --> Maximum number of directory levels to scan or
+ zero to scan all directory levels.
+ whichInfo --> The fields of the FSCatalogInfo you wish to get.
+ wantFSSpec --> Set to true if you want the FSSpec to each
+ object passed to your IterateContainerFilterProc.
+ wantName --> Set to true if you want the name of each
+ object passed to your IterateContainerFilterProc.
+ iterateFilter --> A pointer to the IterateContainerFilterProc you
+ want called once for each file and directory found
+ by FSIterateContainer.
+ yourDataPtr --> An optional pointer to whatever data structure you
+ might want to access from within the
+ IterateFilterProc.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetDirectoryItems
+
+OSErr
+FSGetDirectoryItems(
+ const FSRef *container,
+ FSRef ***refsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numRefs,
+ Boolean *containerChanged);
+
+/*
+ The FSGetDirectoryItems function returns the list of items in the specified
+ container. The array of FSRef records is returned in a Handle, refsHandle,
+ which is allocated by FSGetDirectoryItems. The caller is responsible for
+ disposing of refsHandle if the FSGetDirectoryItems returns noErr.
+
+ container --> FSRef to a directory.
+ refsHandle <-- Pointer to an FSRef Handle where the array of
+ FSRefs is to be returned.
+ numRefs <-- The number of FSRefs returned in the array.
+ containerChanged <-- Set to true if the container changes while the
+ list of items is being obtained.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSExchangeObjectsCompat
+
+OSErr
+FSExchangeObjectsCompat(
+ const FSRef *sourceRef,
+ const FSRef *destRef,
+ FSRef *newSourceRef,
+ FSRef *newDestRef);
+
+/*
+ The FSExchangeObjectsCompat function exchanges the data between two files.
+
+ The FSExchangeObjectsCompat function is an enhanced version of
+ FSExchangeObjects function. The two enhancements FSExchangeObjectsCompat
+ provides are:
+
+ 1, FSExchangeObjectsCompat will work on volumes which do not support
+ FSExchangeObjects. FSExchangeObjectsCompat does this by emulating
+ FSExchangeObjects through a series of File Manager operations. If
+ there is a failure at any step along the way, FSExchangeObjectsCompat
+ attempts to undo any steps already taken to leave the files in their
+ original state in their original locations.
+
+ 2. FSExchangeObjectsCompat returns new FSRefs to the source and
+ destination files. Note that if this function fails at any step along
+ the way, newSourceRef and newDestRef still give you access to the final
+ locations of the files being exchanged -- even if they are renamed or
+ not in their original locations.
+
+ sourceRef --> FSRef to the source file.
+ destRef --> FSRef to the destination file.
+ newSourceRef <-- The new FSRef to the source file.
+ newDestRef <-- The new FSRef to the destination file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Shared Environment Routines -----
+
+/*****************************************************************************/
+
+#pragma mark MFX_FSLockRange
+/* Renamed from FSLockRange to MFX_FSLockRange to avoid a conflict with
+ * the FSLockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSLockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart);
+
+/*
+ The LockRange function locks (denies access to) a portion of a file
+ that was opened with shared read/write permission.
+
+ refNum --> The file reference number of an open file.
+ rangeLength --> The number of bytes in the range.
+ rangeStart --> The starting byte in the range to lock.
+
+ __________
+
+ Also see: UnlockRange
+*/
+
+/*****************************************************************************/
+
+#pragma mark MFX_FSUnlockRange
+/* Renamed from FSUnlockRange to MFX_FSUnlockRange to avoid a conflict with
+ * the FSUnlockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSUnlockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart);
+
+/*
+ The UnlockRange function unlocks (allows access to) a previously locked
+ portion of a file that was opened with shared read/write permission.
+
+ refNum --> The file reference number of an open file.
+ rangeLength --> The number of bytes in the range.
+ rangeStart --> The starting byte in the range to unlock.
+
+ __________
+
+ Also see: LockRange
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetDirAccess
+
+OSErr
+FSGetDirAccess(
+ const FSRef *ref,
+ SInt32 *ownerID, /* can be NULL */
+ SInt32 *groupID, /* can be NULL */
+ SInt32 *accessRights); /* can be NULL */
+
+/*
+ The FSGetDirAccess function retrieves the directory access control
+ information for a directory on a shared volume.
+
+ ref --> An FSRef specifying the directory.
+ ownerID <** An optional pointer to a SInt32.
+ If not NULL, the directory's owner ID
+ will be returned in the SInt32.
+ groupID <** An optional pointer to a SInt32.
+ If not NULL, the directory's group ID, or 0
+ if no group affiliation, will be returned in
+ the SInt32.
+ accessRights <** An optional pointer to a SInt32.
+ If not NULL, the directory's access rights
+ will be returned in the SInt32.
+
+ __________
+
+ Also see: FSSetDirAccess, FSMapID, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetDirAccess
+
+OSErr
+FSSetDirAccess(
+ const FSRef *ref,
+ SInt32 ownerID,
+ SInt32 groupID,
+ SInt32 accessRights);
+
+/*
+ The FSpSetDirAccess function changes the directory access control
+ information for a directory on a shared volume. You must be the owner of
+ a directory to change its access control information.
+
+ ref --> An FSRef specifying the directory.
+ ownerID --> The directory's owner ID.
+ groupID --> The directory's group ID or 0 if no group affiliation.
+ accessRights --> The directory's access rights.
+
+ __________
+
+ Also see: FSGetDirAccess, FSMapID, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolMountInfoSize
+
+OSErr
+FSGetVolMountInfoSize(
+ FSVolumeRefNum volRefNum,
+ SInt16 *size);
+
+/*
+ The FSGetVolMountInfoSize function determines the how much space the
+ program needs to allocate for a volume mounting information record.
+
+ volRefNum --> Volume specification.
+ size <-- The space needed (in bytes) of the volume
+ mounting information record.
+
+ __________
+
+ Also see: FSGetVolMountInfo, VolumeMount
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolMountInfo
+
+OSErr
+FSGetVolMountInfo(
+ FSVolumeRefNum volRefNum,
+ void *volMountInfo);
+
+/*
+ The FSGetVolMountInfo function retrieves a volume mounting information
+ record containing all the information needed to mount the volume,
+ except for passwords.
+
+ volRefNum --> Volume specification.
+ volMountInfo <-- The volume mounting information.
+
+ __________
+
+ Also see: FSGetVolMountInfoSize, VolumeMount
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSVolumeMount
+
+// This function exists in Mac OS X 10.5, we cannot re-define it here.
+// We don't use this function, so just don't compile it.
+#if 0
+OSErr
+FSVolumeMount(
+ const void *volMountInfo,
+ FSVolumeRefNum *volRefNum);
+#endif
+
+/*
+ The VolumeMount function mounts a volume using a volume mounting
+ information record.
+
+ volMountInfo --> A volume mounting information record.
+ volRefNum <-- The volume reference number.
+
+ __________
+
+ Also see: FSGetVolMountInfoSize, FSGetVolMountInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMapID
+
+OSErr
+FSMapID(
+ FSVolumeRefNum volRefNum,
+ SInt32 ugID,
+ SInt16 objType,
+ Str31 name);
+
+/*
+ The FSMapID function determines the name of a user or group if you know
+ the user or group ID.
+
+ volRefNum --> Volume specification.
+ objType --> The mapping function code:
+ kOwnerID2Name to map a user ID to a user name
+ kGroupID2Name to map a group ID to a group name
+ name <** An optional pointer to a buffer (minimum Str31).
+ If not NULL, the user or group name
+ will be returned in the buffer.
+
+ __________
+
+ Also see: FSGetDirAccess, FSSetDirAccess, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMapName
+
+OSErr
+FSMapName(
+ FSVolumeRefNum volRefNum,
+ ConstStr255Param name,
+ SInt16 objType,
+ SInt32 *ugID);
+
+/*
+ The FSMapName function determines the user or group ID if you know the
+ user or group name.
+
+ volRefNum --> Volume specification.
+ name --> The user or group name.
+ objType --> The mapping function code:
+ kOwnerName2ID to map a user name to a user ID
+ kGroupName2ID to map a user name to a group ID
+ ugID <-- The user or group ID.
+
+ __________
+
+ Also see: FSGetDirAccess, FSSetDirAccess, FSMapID
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFile
+
+OSErr
+FSCopyFile(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *copyName, /* can be NULL (no rename during copy) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* can be NULL */
+
+/*
+ The FSCopyFile function duplicates a file and optionally renames it.
+ The source and destination volumes must be on the same file server.
+ This function instructs the server to copy the file.
+
+ srcFileRef --> An FSRef specifying the source file.
+ dstDirectoryRef --> An FSRef specifying the destination directory.
+ nameLength --> Number of UniChar in copyName parameter (ignored
+ if copyName is NULL).
+ copyName --> Points to the new file name if the file is to be
+ renamed, or NULL if the file isn't to be renamed.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <** An optional pointer to a FSRef.
+ If not NULL, the FSRef of the duplicated file
+ will be returned in the FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMoveRename
+
+OSErr
+FSMoveRename(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *moveName, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* can be NULL */
+
+/*
+ The FSMoveRename function moves a file or directory (object), and
+ optionally renames it. The source and destination locations must be on
+ the same shared volume.
+
+ srcFileRef --> An FSRef specifying the source file.
+ dstDirectoryRef --> An FSRef specifying the destination directory.
+ nameLength --> Number of UniChar in moveName parameter (ignored
+ if copyName is NULL)
+ moveName --> Points to the new object name if the object is to be
+ renamed, or NULL if the object isn't to be renamed.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <** An optional pointer to a FSRef.
+ If not NULL, the FSRef of the moved object
+ will be returned in the FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- File ID Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSResolveFileIDRef
+
+OSErr
+FSResolveFileIDRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 fileID,
+ FSRef *ref);
+
+/*
+ The FSResolveFileIDRef function returns an FSRef for the file with the
+ specified file ID reference.
+
+ volRefNum --> Volume specification.
+ fileID --> The file ID reference.
+ ref <-- The FSRef for the file ID reference.
+
+ __________
+
+ Also see: FSCreateFileIDRef, FSDeleteFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCreateFileIDRef
+
+OSErr
+FSCreateFileIDRef(
+ const FSRef *ref,
+ SInt32 *fileID);
+
+/*
+ The FSCreateFileIDRef function creates a file ID reference for the
+ specified file, or if a file ID reference already exists, supplies
+ the file ID reference and returns the result code fidExists or afpIDExists.
+
+ ref --> The FSRef for the file.
+ fileID <-- The file ID reference (if result is noErr,
+ fidExists, or afpIDExists).
+
+ __________
+
+ Also see: GetFSRefFromFileIDRef, FSDeleteFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteFileIDRef
+
+/*
+ Why is there no FSDeleteFileIDRef routine? There are two reasons:
+
+ 1. Since Mac OS 8.1, PBDeleteFileIDRef hasn't deleted file ID references.
+ On HFS volumes, deleting a file ID reference breaks aliases (which
+ use file ID references to track files as they are moved around on a
+ volume) and file ID references are automatically deleted when the file
+ they refer to is deleted. On HFS Plus volumes, file ID references are
+ always created when a file is created, deleted when the file is deleted,
+ and cannot be deleted at any other time.
+
+ 2. PBDeleteFileIDRef causes a memory access fault under Mac OS X 10.0
+ through 10.1.x. While this will be fixed in a future release, the
+ implementation, like the Mac OS 8/9 implementation, does not delete
+ file ID references.
+
+ __________
+
+ Also see: GetFSRefFromFileIDRef, FSCreateFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Utility Routines -----
+
+/*****************************************************************************/
+
+#pragma mark GetTempBuffer
+
+Ptr
+GetTempBuffer(
+ ByteCount buffReqSize,
+ ByteCount *buffActSize);
+
+/*
+ The GetTempBuffer function allocates a temporary buffer for file system
+ operations which is at least 4K bytes and a multiple of 4K bytes.
+
+ buffReqSize --> Size you'd like the buffer to be.
+ buffActSize <-- The size of the buffer allocated.
+ function result <-- Pointer to memory allocated, or NULL if no memory
+ was available. The caller is responsible for
+ disposing of this buffer with DisposePtr.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FileRefNumGetFSRef
+
+OSErr
+FileRefNumGetFSRef(
+ short refNum,
+ FSRef *ref);
+
+/*
+ The FileRefNumGetFSRef function gets the FSRef of an open file.
+
+ refNum --> The file reference number of an open file.
+ ref <-- The FSRef to the open file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetDefault
+
+OSErr
+FSSetDefault(
+ const FSRef *newDefault,
+ FSRef *oldDefault);
+
+/*
+ The FSSetDefault function sets the current working directory to the
+ directory specified by newDefault. The previous current working directory
+ is returned in oldDefault and must be used to restore the current working
+ directory to its previous state with the FSRestoreDefault function.
+ These two functions are designed to be used as a wrapper around
+ Standard I/O routines where the location of the file is implied to be the
+ current working directory. This is how you should use these functions:
+
+ result = FSSetDefault(&newDefault, &oldDefault);
+ if ( noErr == result )
+ {
+ // call the Stdio functions like remove, rename,
+ // fopen, freopen, etc here!
+
+ result = FSRestoreDefault(&oldDefault);
+ }
+
+ newDefault --> An FSRef that specifies the new current working
+ directory.
+ oldDefault <-- The previous current working directory's FSRef.
+
+ __________
+
+ Also see: FSRestoreDefault
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSRestoreDefault
+
+OSErr
+FSRestoreDefault(
+ const FSRef *oldDefault);
+
+/*
+ The FSRestoreDefault function restores the current working directory
+ to the directory specified by oldDefault. The oldDefault parameter was
+ previously obtained from the FSSetDefault function.
+ These two functions are designed to be used as a wrapper around
+ Standard I/O routines where the location of the file is implied to be the
+ current working directory. This is how you should use these functions:
+
+ result = FSSetDefault(&newDefault, &oldDefault);
+ if ( noErr == result )
+ {
+ // call the Stdio functions like remove, rename,
+ // fopen, freopen, etc here!
+
+ result = FSRestoreDefault(&oldDefault);
+ }
+
+ oldDefault --> The FSRef of the location to restore.
+
+ __________
+
+ Also see: FSSetDefault
+*/
+
+/*****************************************************************************/
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#ifdef PRAGMA_IMPORT_OFF
+#pragma import off
+#elif PRAGMA_IMPORT
+#pragma import reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MOREFILESX__ */
+
diff --git a/src/libs/xpcom18a4/xpcom/base/.cvsignore b/src/libs/xpcom18a4/xpcom/base/.cvsignore
new file mode 100644
index 00000000..235f7398
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+bloatblame
diff --git a/src/libs/xpcom18a4/xpcom/base/Makefile.in b/src/libs/xpcom18a4/xpcom/base/Makefile.in
new file mode 100644
index 00000000..a897bca8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/Makefile.in
@@ -0,0 +1,133 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = xpcom_base
+LIBRARY_NAME = xpcombase_s
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+CPPSRCS = \
+ nsAllocator.cpp \
+ nsConsoleMessage.cpp \
+ nsConsoleService.cpp \
+ nsDebugImpl.cpp \
+ nsErrorService.cpp \
+ nsExceptionService.cpp \
+ nsID.cpp \
+ nsMemoryImpl.cpp \
+ nsTraceRefcntImpl.cpp \
+ $(NULL)
+
+ifdef GC_LEAK_DETECTOR
+CSRCS += nsGarbageCollector.c
+CPPSRCS += nsLeakDetector.cpp
+REQUIRES += boehm
+endif
+
+EXPORTS = \
+ nsAgg.h \
+ nsAutoPtr.h \
+ nsCom.h \
+ nsDebugImpl.h \
+ nsIAllocator.h \
+ nsIID.h \
+ nsISupportsObsolete.h \
+ nsTraceRefcntImpl.h \
+ nsWeakPtr.h \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef MOZ_DEBUG
+CSRCS += pure_api.c
+EXPORTS += pure.h
+endif
+CPPSRCS += nsStackFrameWin.cpp
+endif
+
+ifneq ($(OS_ARCH),WINNT)
+CPPSRCS += nsStackFrameUnix.cpp
+endif
+
+SDK_XPIDLSRCS = \
+ nsIDebug.idl \
+ nsIInterfaceRequestor.idl \
+ nsIMemory.idl \
+ nsIProgrammingLanguage.idl \
+ nsISupports.idl \
+ nsITraceRefcnt.idl \
+ nsIWeakReference.idl \
+ nsrootidl.idl \
+
+SDK_HEADERS = \
+ nsError.h \
+ nsID.h \
+ nsISupportsBase.h \
+ nscore.h \
+
+XPIDLSRCS = \
+ nsIConsoleListener.idl \
+ nsIConsoleMessage.idl \
+ nsIConsoleService.idl \
+ nsIErrorService.idl \
+ nsIException.idl \
+ nsIExceptionService.idl \
+ $(NULL)
+
+ifdef GC_LEAK_DETECTOR
+XPIDLSRCS += nsILeakDetector.idl
+endif
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAgg.h b/src/libs/xpcom18a4/xpcom/base/nsAgg.h
new file mode 100644
index 00000000..c818639e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAgg.h
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAgg_h___
+#define nsAgg_h___
+
+#include "nsISupports.h"
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Put this in your class's declaration:
+#define NS_DECL_AGGREGATED \
+ NS_DECL_ISUPPORTS \
+ \
+public: \
+ \
+ /* You must implement this operation instead of the nsISupports */ \
+ /* methods if you inherit from nsAggregated. */ \
+ NS_IMETHOD \
+ AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr); \
+ \
+protected: \
+ \
+ class Internal : public nsISupports { \
+ public: \
+ \
+ Internal() {} \
+ \
+ NS_IMETHOD QueryInterface(const nsIID& aIID, \
+ void** aInstancePtr); \
+ NS_IMETHOD_(nsrefcnt) AddRef(void); \
+ NS_IMETHOD_(nsrefcnt) Release(void); \
+ \
+ }; \
+ \
+ friend class Internal; \
+ \
+ nsISupports* fOuter; \
+ Internal fAggregated; \
+ \
+ nsISupports* GetInner(void) { return &fAggregated; } \
+ \
+public: \
+
+
+// Put this in your class's constructor:
+#define NS_INIT_AGGREGATED(outer) \
+ PR_BEGIN_MACRO \
+ fOuter = outer ? outer : &fAggregated; \
+ PR_END_MACRO
+
+
+// Put this in your class's implementation file:
+#define NS_IMPL_AGGREGATED(_class) \
+NS_IMETHODIMP \
+_class::QueryInterface(const nsIID& aIID, void** aInstancePtr) \
+{ \
+ return fOuter->QueryInterface(aIID, aInstancePtr); \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::AddRef(void) \
+{ \
+ return fOuter->AddRef(); \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::Release(void) \
+{ \
+ return fOuter->Release(); \
+} \
+ \
+NS_IMETHODIMP \
+_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr) \
+{ \
+ _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+ return agg->AggregatedQueryInterface(aIID, aInstancePtr); \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::Internal::AddRef(void) \
+{ \
+ _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+ NS_PRECONDITION(PRInt32(agg->mRefCnt) >= 0, "illegal refcnt"); \
+ ++agg->mRefCnt; \
+ NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this)); \
+ return agg->mRefCnt; \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::Internal::Release(void) \
+{ \
+ _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+ NS_PRECONDITION(0 != agg->mRefCnt, "dup release"); \
+ --agg->mRefCnt; \
+ NS_LOG_RELEASE(this, agg->mRefCnt, #_class); \
+ if (agg->mRefCnt == 0) { \
+ agg->mRefCnt = 1; /* stabilize */ \
+ NS_DELETEXPCOM(agg); \
+ return 0; \
+ } \
+ return agg->mRefCnt; \
+} \
+
+// for use with QI macros in nsISupportsUtils.h:
+
+#define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class) \
+ NS_IMPL_AGGREGATED_QUERY_HEAD(_class)
+
+#define NS_IMPL_AGGREGATED_QUERY_HEAD(_class) \
+NS_IMETHODIMP \
+_class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) \
+{ \
+ NS_ASSERTION(aInstancePtr, \
+ "AggregatedQueryInterface requires a non-NULL result ptr!"); \
+ if ( !aInstancePtr ) \
+ return NS_ERROR_NULL_POINTER; \
+ nsISupports* foundInterface;
+
+#endif /* nsAgg_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp b/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp
new file mode 100644
index 00000000..d565329d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// obsolete
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAllocator.h b/src/libs/xpcom18a4/xpcom/base/nsAllocator.h
new file mode 100644
index 00000000..5320469c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAllocator.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// obsolete
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef nsAllocator_h__
+#define nsAllocator_h__
+
+#include "nsIAllocator.h"
+#include "prmem.h"
+#include "nsAgg.h"
+#include "nsIFactory.h"
+
+#endif // nsAllocator_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h b/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h
new file mode 100644
index 00000000..874b1e31
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h
@@ -0,0 +1,1353 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author of nsCOMPtr)
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAutoPtr_h___
+#define nsAutoPtr_h___
+
+ // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
+#ifndef nsCOMPtr_h___
+ // For |already_AddRefed|, |nsDerivedSafe|, |NSCAP_Zero|,
+ // |NSCAP_DONT_PROVIDE_NONCONST_OPEQ|,
+ // |NSCAP_FEATURE_INLINE_STARTASSIGNMENT|
+#include "nsCOMPtr.h"
+#endif
+
+/*****************************************************************************/
+
+// template <class T> class nsAutoPtrGetterTransfers;
+
+template <class T>
+class nsAutoPtr
+ {
+ private:
+ void**
+ begin_assignment()
+ {
+ assign(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+
+ void
+ assign( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ delete oldPtr;
+ }
+
+ private:
+ T* mRawPtr;
+
+ public:
+ typedef T element_type;
+
+ ~nsAutoPtr()
+ {
+ delete mRawPtr;
+ }
+
+ // Constructors
+
+ nsAutoPtr()
+ : mRawPtr(0)
+ // default constructor
+ {
+ }
+
+ nsAutoPtr( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ }
+
+ nsAutoPtr( nsAutoPtr<T>& aSmartPtr )
+ : mRawPtr( aSmartPtr.forget() )
+ // Construct by transferring ownership from another smart pointer.
+ {
+ }
+
+
+ // Assignment operators
+
+ nsAutoPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ nsAutoPtr<T>& operator=( nsAutoPtr<T>& rhs )
+ // assign by transferring ownership from another smart pointer.
+ {
+ assign(rhs.forget());
+ return *this;
+ }
+
+ // Other pointer operators
+
+ T*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by
+ |operator T*() const|. Use |get()| _only_ to resolve
+ ambiguity.
+ */
+ {
+ return mRawPtr;
+ }
+
+ operator T*() const
+ /*
+ ...makes an |nsAutoPtr| act like its underlying raw pointer
+ type whenever it is used in a context where a raw pointer
+ is expected. It is this operator that makes an |nsAutoPtr|
+ substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|,
+ except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ T*
+ forget()
+ {
+ T* temp = mRawPtr;
+ mRawPtr = 0;
+ return temp;
+ }
+
+ T*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsAutoPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsAutoPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsAutoPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsAutoPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ T&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*().");
+ return *get();
+ }
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsAutoPtr<T>*
+address_of( const nsAutoPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsAutoPtr<T>*
+address_of( nsAutoPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsAutoPtr<T>*
+address_of( const nsAutoPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsAutoPtrGetterTransfers
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsAutoPtr<IFoo> fooP;
+ ...->GetTransferedPointer(getter_Transfers(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
+
+ When initialized with a |nsAutoPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the
+ outer call (|GetTransferedPointer| in this case) can fill in.
+
+ This type should be a nested class inside |nsAutoPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsAutoPtrGetterTransfers( nsAutoPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsAutoPtr<T>& mTargetSmartPtr;
+ };
+
+template <class T>
+inline
+nsAutoPtrGetterTransfers<T>
+getter_Transfers( nsAutoPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsAutoPtr| when
+ ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
+ */
+ {
+ return nsAutoPtrGetterTransfers<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsAutoPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsAutoPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsAutoPtr| to |0|
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsAutoPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+/*****************************************************************************/
+
+// template <class T> class nsAutoArrayPtrGetterTransfers;
+
+template <class T>
+class nsAutoArrayPtr
+ {
+ private:
+ void**
+ begin_assignment()
+ {
+ assign(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+
+ void
+ assign( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ delete [] oldPtr;
+ }
+
+ private:
+ T* mRawPtr;
+
+ public:
+ typedef T element_type;
+
+ ~nsAutoArrayPtr()
+ {
+ delete [] mRawPtr;
+ }
+
+ // Constructors
+
+ nsAutoArrayPtr()
+ : mRawPtr(0)
+ // default constructor
+ {
+ }
+
+ nsAutoArrayPtr( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ }
+
+ nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr )
+ : mRawPtr( aSmartPtr.forget() )
+ // Construct by transferring ownership from another smart pointer.
+ {
+ }
+
+
+ // Assignment operators
+
+ nsAutoArrayPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ nsAutoArrayPtr<T>& operator=( nsAutoArrayPtr<T>& rhs )
+ // assign by transferring ownership from another smart pointer.
+ {
+ assign(rhs.forget());
+ return *this;
+ }
+
+ // Other pointer operators
+
+ T*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by
+ |operator T*() const|. Use |get()| _only_ to resolve
+ ambiguity.
+ */
+ {
+ return mRawPtr;
+ }
+
+ operator T*() const
+ /*
+ ...makes an |nsAutoArrayPtr| act like its underlying raw pointer
+ type whenever it is used in a context where a raw pointer
+ is expected. It is this operator that makes an |nsAutoArrayPtr|
+ substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|,
+ except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ T*
+ forget()
+ {
+ T* temp = mRawPtr;
+ mRawPtr = 0;
+ return temp;
+ }
+
+ T*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsAutoArrayPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsAutoArrayPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsAutoArrayPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsAutoArrayPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ T&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*().");
+ return *get();
+ }
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsAutoArrayPtr<T>*
+address_of( const nsAutoArrayPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsAutoArrayPtr<T>*
+address_of( nsAutoArrayPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsAutoArrayPtr<T>*
+address_of( const nsAutoArrayPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsAutoArrayPtrGetterTransfers
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsAutoArrayPtr<IFoo> fooP;
+ ...->GetTransferedPointer(getter_Transfers(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
+
+ When initialized with a |nsAutoArrayPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the
+ outer call (|GetTransferedPointer| in this case) can fill in.
+
+ This type should be a nested class inside |nsAutoArrayPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsAutoArrayPtr<T>& mTargetSmartPtr;
+ };
+
+template <class T>
+inline
+nsAutoArrayPtrGetterTransfers<T>
+getter_Transfers( nsAutoArrayPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsAutoArrayPtr| when
+ ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible.
+ */
+ {
+ return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsAutoArrayPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsAutoArrayPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsAutoArrayPtr| to |0|
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsAutoArrayPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+
+/*****************************************************************************/
+
+// template <class T> class nsRefPtrGetterAddRefs;
+
+template <class T>
+class nsRefPtr
+ {
+ private:
+
+ void
+ assign_with_AddRef( T* rawPtr )
+ {
+ if ( rawPtr )
+ rawPtr->AddRef();
+ assign_assuming_AddRef(rawPtr);
+ }
+
+ void**
+ begin_assignment()
+ {
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+
+ void
+ assign_assuming_AddRef( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ if ( oldPtr )
+ oldPtr->Release();
+ }
+
+ private:
+ T* mRawPtr;
+
+ public:
+ typedef T element_type;
+
+ ~nsRefPtr()
+ {
+ if ( mRawPtr )
+ mRawPtr->Release();
+ }
+
+ // Constructors
+
+ nsRefPtr()
+ : mRawPtr(0)
+ // default constructor
+ {
+ }
+
+ nsRefPtr( const nsRefPtr<T>& aSmartPtr )
+ : mRawPtr(aSmartPtr.mRawPtr)
+ // copy-constructor
+ {
+ if ( mRawPtr )
+ mRawPtr->AddRef();
+ }
+
+ nsRefPtr( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if ( mRawPtr )
+ mRawPtr->AddRef();
+ }
+
+ nsRefPtr( const already_AddRefed<T>& aSmartPtr )
+ : mRawPtr(aSmartPtr.mRawPtr)
+ // construct from |dont_AddRef(expr)|
+ {
+ }
+
+ // Assignment operators
+
+ nsRefPtr<T>&
+ operator=( const nsRefPtr<T>& rhs )
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsRefPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ return *this;
+ }
+
+ nsRefPtr<T>&
+ operator=( const already_AddRefed<T>& rhs )
+ // assign from |dont_AddRef(expr)|
+ {
+ assign_assuming_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ // Other pointer operators
+
+ void
+ swap( nsRefPtr<T>& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ T* temp = rhs.mRawPtr;
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ }
+
+ void
+ swap( T*& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ T* temp = rhs;
+ rhs = mRawPtr;
+ mRawPtr = temp;
+ }
+
+ nsDerivedSafe<T>*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
+ Use |get()| _only_ to resolve ambiguity.
+
+ Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
+ */
+ {
+ return NS_CONST_CAST(nsDerivedSafe<T>*,
+ NS_REINTERPRET_CAST(const nsDerivedSafe<T>*, mRawPtr));
+ }
+
+ operator nsDerivedSafe<T>*() const
+ /*
+ ...makes an |nsRefPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
+ and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
+ that makes an |nsRefPtr| substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ nsDerivedSafe<T>*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsRefPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsRefPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsRefPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsRefPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ nsDerivedSafe<T>&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*().");
+ return *get();
+ }
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsRefPtr<T>*
+address_of( const nsRefPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsRefPtr<T>*
+address_of( nsRefPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsRefPtr<T>*
+address_of( const nsRefPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsRefPtrGetterAddRefs
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsRefPtr<IFoo> fooP;
+ ...->GetAddRefedPointer(getter_AddRefs(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
+
+ When initialized with a |nsRefPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the
+ outer call (|GetAddRefedPointer| in this case) can fill in.
+
+ This type should be a nested class inside |nsRefPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsRefPtrGetterAddRefs( nsRefPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsRefPtr<T>& mTargetSmartPtr;
+ };
+
+template <class T>
+inline
+nsRefPtrGetterAddRefs<T>
+getter_AddRefs( nsRefPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsRefPtr| when
+ ...makes the class |nsRefPtrGetterAddRefs<T>| invisible.
+ */
+ {
+ return nsRefPtrGetterAddRefs<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsRefPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsRefPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsRefPtr| to |0|
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsRefPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+/*****************************************************************************/
+
+#endif // !defined(nsAutoPtr_h___)
diff --git a/src/libs/xpcom18a4/xpcom/base/nsCom.h b/src/libs/xpcom18a4/xpcom/base/nsCom.h
new file mode 100644
index 00000000..54b0b8bf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsCom.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCom_h__
+#define nsCom_h__
+#include "nscore.h"
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp
new file mode 100644
index 00000000..02dc589b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Base implementation for console messages.
+ */
+
+#include "nsConsoleMessage.h"
+#include "nsReadableUtils.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleMessage, nsIConsoleMessage)
+
+nsConsoleMessage::nsConsoleMessage()
+{
+}
+
+nsConsoleMessage::nsConsoleMessage(const PRUnichar *message)
+{
+ mMessage.Assign(message);
+}
+
+NS_IMETHODIMP
+nsConsoleMessage::GetMessage(PRUnichar **result) {
+ *result = ToNewUnicode(mMessage);
+
+ return NS_OK;
+}
+
+// NS_IMETHODIMP
+// nsConsoleMessage::Init(const PRUnichar *message) {
+// nsAutoString newMessage(message);
+// mMessage = ToNewUnicode(newMessage);
+// return NS_OK;
+// }
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h
new file mode 100644
index 00000000..3d4a7e6c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsconsolemessage_h__
+#define __nsconsolemessage_h__
+
+#include "nsIConsoleMessage.h"
+#include "nsString.h"
+
+class nsConsoleMessage : public nsIConsoleMessage {
+public:
+ nsConsoleMessage();
+ nsConsoleMessage(const PRUnichar *message);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICONSOLEMESSAGE
+
+private:
+ ~nsConsoleMessage() {}
+
+ nsString mMessage;
+};
+
+#endif /* __nsconsolemessage_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp
new file mode 100644
index 00000000..1b369071
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp
@@ -0,0 +1,321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Maintains a circular buffer of recent messages, and notifies
+ * listeners when new messages are logged.
+ */
+
+/* Threadsafe. */
+
+#include "nsMemory.h"
+#include "nsIServiceManager.h"
+#include "nsIProxyObjectManager.h"
+#include "nsSupportsArray.h"
+
+#include "nsConsoleService.h"
+#include "nsConsoleMessage.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleService, nsIConsoleService)
+
+nsConsoleService::nsConsoleService()
+ : mCurrent(0), mFull(PR_FALSE), mListening(PR_FALSE), mLock(nsnull)
+{
+ // XXX grab this from a pref!
+ // hm, but worry about circularity, bc we want to be able to report
+ // prefs errs...
+ mBufferSize = 250;
+
+ // XXX deal with these two allocations by detecting null mLock in factory?
+ mMessages = (nsIConsoleMessage **)
+ nsMemory::Alloc(mBufferSize * sizeof(nsIConsoleMessage *));
+
+ mLock = PR_NewLock();
+
+ // Array elements should be 0 initially for circular buffer algorithm.
+ for (PRUint32 i = 0; i < mBufferSize; i++) {
+ mMessages[i] = nsnull;
+ }
+
+}
+
+nsConsoleService::~nsConsoleService()
+{
+ PRUint32 i = 0;
+ while (i < mBufferSize && mMessages[i] != nsnull) {
+ NS_RELEASE(mMessages[i]);
+ i++;
+ }
+
+#ifdef DEBUG_mccabe
+ if (mListeners.Count() != 0) {
+ fprintf(stderr,
+ "WARNING - %d console error listeners still registered!\n"
+ "More calls to nsIConsoleService::UnregisterListener needed.\n",
+ mListeners.Count());
+ }
+
+#endif
+
+ nsMemory::Free(mMessages);
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+static PRBool PR_CALLBACK snapshot_enum_func(nsHashKey *key, void *data, void* closure)
+{
+ nsISupportsArray *array = (nsISupportsArray *)closure;
+
+ // Copy each element into the temporary nsSupportsArray...
+ array->AppendElement((nsISupports*)data);
+ return PR_TRUE;
+}
+
+// nsIConsoleService methods
+NS_IMETHODIMP
+nsConsoleService::LogMessage(nsIConsoleMessage *message)
+{
+ if (message == nsnull)
+ return NS_ERROR_INVALID_ARG;
+
+ nsSupportsArray listenersSnapshot;
+ nsIConsoleMessage *retiredMessage;
+
+ NS_ADDREF(message); // early, in case it's same as replaced below.
+
+ /*
+ * Lock while updating buffer, and while taking snapshot of
+ * listeners array.
+ */
+ {
+ nsAutoLock lock(mLock);
+
+ /*
+ * If there's already a message in the slot we're about to replace,
+ * we've wrapped around, and we need to release the old message. We
+ * save a pointer to it, so we can release below outside the lock.
+ */
+ retiredMessage = mMessages[mCurrent];
+
+ mMessages[mCurrent++] = message;
+ if (mCurrent == mBufferSize) {
+ mCurrent = 0; // wrap around.
+ mFull = PR_TRUE;
+ }
+
+ /*
+ * Copy the listeners into the snapshot array - in case a listener
+ * is removed during an Observe(...) notification...
+ */
+ mListeners.Enumerate(snapshot_enum_func, &listenersSnapshot);
+ }
+ if (retiredMessage != nsnull)
+ NS_RELEASE(retiredMessage);
+
+ /*
+ * Iterate through any registered listeners and tell them about
+ * the message. We use the mListening flag to guard against
+ * recursive message logs. This could sometimes result in
+ * listeners being skipped because of activity on other threads,
+ * when we only care about the recursive case.
+ */
+ nsCOMPtr<nsIConsoleListener> listener;
+ nsresult rv;
+ nsresult returned_rv;
+ PRUint32 snapshotCount;
+ rv = listenersSnapshot.Count(&snapshotCount);
+ if (NS_FAILED(rv))
+ return rv;
+
+ {
+ nsAutoLock lock(mLock);
+ if (mListening)
+ return NS_OK;
+ mListening = PR_TRUE;
+ }
+
+ returned_rv = NS_OK;
+ for (PRUint32 i = 0; i < snapshotCount; i++) {
+ rv = listenersSnapshot.GetElementAt(i, getter_AddRefs(listener));
+ if (NS_FAILED(rv)) {
+ returned_rv = rv;
+ break; // fall thru to mListening restore code below.
+ }
+ listener->Observe(message);
+ }
+
+ {
+ nsAutoLock lock(mLock);
+ mListening = PR_FALSE;
+ }
+
+ return returned_rv;
+}
+
+NS_IMETHODIMP
+nsConsoleService::LogStringMessage(const PRUnichar *message)
+{
+ nsConsoleMessage *msg = new nsConsoleMessage(message);
+ return this->LogMessage(msg);
+}
+
+NS_IMETHODIMP
+nsConsoleService::GetMessageArray(nsIConsoleMessage ***messages, PRUint32 *count)
+{
+ nsIConsoleMessage **messageArray;
+
+ /*
+ * Lock the whole method, as we don't want anyone mucking with mCurrent or
+ * mFull while we're copying out the buffer.
+ */
+ nsAutoLock lock(mLock);
+
+ if (mCurrent == 0 && !mFull) {
+ /*
+ * Make a 1-length output array so that nobody gets confused,
+ * and return a count of 0. This should result in a 0-length
+ * array object when called from script.
+ */
+ messageArray = (nsIConsoleMessage **)
+ nsMemory::Alloc(sizeof (nsIConsoleMessage *));
+ *messageArray = nsnull;
+ *messages = messageArray;
+ *count = 0;
+
+ return NS_OK;
+ }
+
+ PRUint32 resultSize = mFull ? mBufferSize : mCurrent;
+ messageArray =
+ (nsIConsoleMessage **)nsMemory::Alloc((sizeof (nsIConsoleMessage *))
+ * resultSize);
+
+ if (messageArray == nsnull) {
+ *messages = nsnull;
+ *count = 0;
+ return NS_ERROR_FAILURE;
+ }
+
+ PRUint32 i;
+ if (mFull) {
+ for (i = 0; i < mBufferSize; i++) {
+ // if full, fill the buffer starting from mCurrent (which'll be
+ // oldest) wrapping around the buffer to the most recent.
+ messageArray[i] = mMessages[(mCurrent + i) % mBufferSize];
+ NS_ADDREF(messageArray[i]);
+ }
+ } else {
+ for (i = 0; i < mCurrent; i++) {
+ messageArray[i] = mMessages[i];
+ NS_ADDREF(messageArray[i]);
+ }
+ }
+ *count = resultSize;
+ *messages = messageArray;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsConsoleService::RegisterListener(nsIConsoleListener *listener) {
+ nsresult rv;
+
+ /*
+ * Store a threadsafe proxy to the listener rather than the
+ * listener itself; we want the console service to be callable
+ * from any thread, but listeners can be implemented in
+ * thread-specific ways, and we always want to call them on their
+ * originating thread. JavaScript is the motivating example.
+ */
+ nsCOMPtr<nsIConsoleListener> proxiedListener;
+
+ rv = GetProxyForListener(listener, getter_AddRefs(proxiedListener));
+ if (NS_FAILED(rv))
+ return rv;
+
+ {
+ nsAutoLock lock(mLock);
+ nsISupportsKey key(listener);
+
+ /*
+ * Put the proxy event listener into a hashtable using the *real*
+ * listener as the key.
+ *
+ * This is necessary because proxy objects do *not* maintain
+ * nsISupports identity. Therefore, since GetProxyForListener(...)
+ * can return different proxies for the same object (see bug #85831)
+ * we need to use the real object as the unique key...
+ */
+ mListeners.Put(&key, proxiedListener);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsConsoleService::UnregisterListener(nsIConsoleListener *listener) {
+ nsAutoLock lock(mLock);
+
+ nsISupportsKey key(listener);
+ mListeners.Remove(&key);
+ return NS_OK;
+}
+
+nsresult
+nsConsoleService::GetProxyForListener(nsIConsoleListener* aListener,
+ nsIConsoleListener** aProxy)
+{
+ nsresult rv;
+ *aProxy = nsnull;
+
+ nsCOMPtr<nsIProxyObjectManager> proxyManager =
+ (do_GetService(NS_XPCOMPROXY_CONTRACTID));
+
+ if (proxyManager == nsnull)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ /*
+ * NOTE this will fail if the calling thread doesn't have an eventQ.
+ *
+ * Would it be better to catch that case and leave the listener unproxied?
+ */
+ rv = proxyManager->GetProxyForObject(NS_CURRENT_EVENTQ,
+ NS_GET_IID(nsIConsoleListener),
+ aListener,
+ PROXY_ASYNC | PROXY_ALWAYS,
+ (void**) aProxy);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h
new file mode 100644
index 00000000..59758f84
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * nsConsoleService class declaration.
+ */
+
+#ifndef __nsconsoleservice_h__
+#define __nsconsoleservice_h__
+
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsAutoLock.h"
+
+#include "nsIConsoleService.h"
+
+class nsConsoleService : public nsIConsoleService
+{
+public:
+ nsConsoleService();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICONSOLESERVICE
+
+private:
+ ~nsConsoleService();
+
+ // build (or find) a proxy for the listener
+ nsresult GetProxyForListener(nsIConsoleListener* aListener,
+ nsIConsoleListener** aProxy);
+
+ // Circular buffer of saved messages
+ nsIConsoleMessage **mMessages;
+
+ // How big?
+ PRUint32 mBufferSize;
+
+ // Index of slot in mMessages that'll be filled by *next* log message
+ PRUint32 mCurrent;
+
+ // Is the buffer full? (Has mCurrent wrapped around at least once?)
+ PRBool mFull;
+
+ // Listeners to notify whenever a new message is logged.
+ nsSupportsHashtable mListeners;
+
+ // Current listener being notified of a logged error - to prevent
+ // stack overflows.
+ PRBool mListening;
+
+ // To serialize interesting methods.
+ PRLock *mLock;
+};
+
+#endif /* __nsconsoleservice_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp
new file mode 100644
index 00000000..f8806092
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp
@@ -0,0 +1,477 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ * Henry Sobotka
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOMPrivate.h"
+#include "nsDebugImpl.h"
+#include "nsDebug.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "prinit.h"
+#include "plstr.h"
+#include "nsError.h"
+#include "prerror.h"
+#include "prerr.h"
+
+#if defined(XP_BEOS)
+/* For DEBUGGER macros */
+#include <Debug.h>
+#endif
+
+#if defined(XP_UNIX) || defined(_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
+/* for abort() and getenv() */
+#include <stdlib.h>
+#endif
+
+#if defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT)
+#include <signal.h>
+/* for nsTraceRefcnt::WalkTheStack() */
+#include "nsISupportsUtils.h"
+#include "nsTraceRefcntImpl.h"
+
+#if defined(__GNUC__) && defined(__i386)
+# define DebugBreak() { asm("int $3"); }
+#elif defined(__APPLE__) && defined(TARGET_CARBON)
+# include "MacTypes.h"
+# define DebugBreak() { Debugger(); }
+#else
+# define DebugBreak()
+#endif
+#endif
+
+#if defined(XP_OS2)
+ /* Added definitions for DebugBreak() for 2 different OS/2 compilers. Doing
+ * the int3 on purpose so that a developer can step over the
+ * instruction if so desired. Not always possible if trapping due to exception
+ * handling IBM-AKR
+ */
+ #define INCL_WINDIALOGS // need for WinMessageBox
+ #include <os2.h>
+ #include <string.h>
+
+ #if defined(DEBUG)
+ #define DebugBreak() { asm("int $3"); }
+ #else
+ #define DebugBreak()
+ #endif /* DEBUG */
+#endif /* XP_OS2 */
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <signal.h>
+#elif defined(XP_MAC)
+ #define TEMP_MAC_HACK
+
+ //------------------------
+ #ifdef TEMP_MAC_HACK
+ #include <MacTypes.h>
+ #include <Processes.h>
+ #include <string.h>
+
+ // TEMPORARY UNTIL WE HAVE MACINTOSH ENVIRONMENT VARIABLES THAT CAN TURN ON
+ // LOGGING ON MACINTOSH
+ // At this moment, NSPR's logging is a no-op on Macintosh.
+
+ #include <stdarg.h>
+ #include <stdio.h>
+
+ #undef PR_LOG
+ #undef PR_LogFlush
+ #define PR_LOG(module,level,args) dprintf args
+ #define PR_LogFlush()
+ static void dprintf(const char *format, ...)
+ {
+ va_list ap;
+ Str255 buffer;
+
+ va_start(ap, format);
+ buffer[0] = std::vsnprintf((char *)buffer + 1, sizeof(buffer) - 1, format, ap);
+ va_end(ap);
+ if (PL_strcasestr((char *)&buffer[1], "warning"))
+ printf("¥¥¥%s\n", (char*)buffer + 1);
+ else
+ DebugStr(buffer);
+ }
+ #endif // TEMP_MAC_HACK
+ //------------------------
+#elif defined(XP_UNIX)
+#include<stdlib.h>
+#endif
+
+/*
+ * Determine if debugger is present in windows.
+ */
+#if defined (_WIN32)
+
+typedef WINBASEAPI BOOL (WINAPI* LPFNISDEBUGGERPRESENT)();
+PRBool InDebugger()
+{
+ PRBool fReturn = PR_FALSE;
+ LPFNISDEBUGGERPRESENT lpfnIsDebuggerPresent = NULL;
+ HINSTANCE hKernel = LoadLibrary("Kernel32.dll");
+
+ if(hKernel)
+ {
+ lpfnIsDebuggerPresent =
+ (LPFNISDEBUGGERPRESENT)GetProcAddress(hKernel, "IsDebuggerPresent");
+ if(lpfnIsDebuggerPresent)
+ {
+ fReturn = (*lpfnIsDebuggerPresent)();
+ }
+ FreeLibrary(hKernel);
+ }
+
+ return fReturn;
+}
+
+#endif /* WIN32*/
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsDebugImpl, nsIDebug)
+
+nsDebugImpl::nsDebugImpl()
+{
+}
+
+/**
+ * Implementation of the nsDebug methods. Note that this code is
+ * always compiled in, in case some other module that uses it is
+ * compiled with debugging even if this library is not.
+ */
+static PRLogModuleInfo* gDebugLog;
+
+static void InitLog(void)
+{
+ if (0 == gDebugLog) {
+ gDebugLog = PR_NewLogModule("nsDebug");
+ gDebugLog->level = PR_LOG_DEBUG;
+ }
+}
+
+
+
+NS_IMETHODIMP
+nsDebugImpl::Assertion(const char *aStr, const char *aExpr, const char *aFile, PRInt32 aLine)
+{
+ InitLog();
+
+ char buf[1000];
+ PR_snprintf(buf, sizeof(buf),
+ "###!!! ASSERTION: %s: '%s', file %s, line %d",
+ aStr, aExpr, aFile, aLine);
+
+ // Write out the assertion message to the debug log
+ PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf));
+ PR_LogFlush();
+
+ // And write it out to the stderr
+ fprintf(stderr, "%s\n", buf);
+ fflush(stderr);
+
+#if defined(_WIN32)
+ char* assertBehavior = getenv("XPCOM_DEBUG_BREAK");
+ if (assertBehavior && strcmp(assertBehavior, "warn") == 0)
+ return NS_OK;
+
+ if(!InDebugger())
+ {
+ DWORD code = IDRETRY;
+
+ /* Create the debug dialog out of process to avoid the crashes caused by
+ * Windows events leaking into our event loop from an in process dialog.
+ * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg).
+ * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792
+ */
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ char executable[MAX_PATH];
+ char* pName;
+
+ memset(&pi, 0, sizeof(pi));
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.wShowWindow = SW_SHOW;
+
+ if(GetModuleFileName(GetModuleHandle(XPCOM_DLL), executable, MAX_PATH) &&
+ NULL != (pName = strrchr(executable, '\\')) &&
+ NULL != strcpy(pName+1, "windbgdlg.exe") &&
+#ifdef DEBUG_jband
+ (printf("Launching %s\n", executable), PR_TRUE) &&
+#endif
+ CreateProcess(executable, buf, NULL, NULL, PR_FALSE,
+ DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &si, &pi) &&
+ WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE) &&
+ GetExitCodeProcess(pi.hProcess, &code))
+ {
+ CloseHandle(pi.hProcess);
+ }
+
+ switch(code)
+ {
+ case IDABORT:
+ //This should exit us
+ raise(SIGABRT);
+ //If we are ignored exit this way..
+ _exit(3);
+ break;
+
+ case IDIGNORE:
+ return NS_OK;
+ // Fall Through
+ }
+ }
+#endif
+
+#if defined(XP_OS2)
+ char* assertBehavior = getenv("XPCOM_DEBUG_BREAK");
+ if (assertBehavior && strcmp(assertBehavior, "warn") == 0)
+ return NS_OK;
+
+ char msg[1200];
+ PR_snprintf(msg, sizeof(msg),
+ "%s\n\nClick Cancel to Debug Application.\n"
+ "Click Enter to continue running the Application.", buf);
+ ULONG code = MBID_ERROR;
+ code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg,
+ "nsDebug::Assertion", 0,
+ MB_ERROR | MB_ENTERCANCEL);
+
+ /* It is possible that we are executing on a thread that doesn't have a
+ * message queue. In that case, the message won't appear, and code will
+ * be 0xFFFF. We'll give the user a chance to debug it by calling
+ * Break()
+ * Actually, that's a really bad idea since this happens a lot with threadsafe
+ * assertions and since it means that you can't actually run the debug build
+ * outside a debugger without it crashing constantly.
+ */
+ if(( code == MBID_ENTER ) || (code == MBID_ERROR))
+ {
+ return NS_OK;
+ // If Retry, Fall Through
+ }
+#endif
+
+ Break(aFile, aLine);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDebugImpl::Break(const char *aFile, PRInt32 aLine)
+{
+#ifndef TEMP_MAC_HACK
+ // Write out the assertion message to the debug log
+ InitLog();
+
+ PR_LOG(gDebugLog, PR_LOG_ERROR,
+ ("###!!! Break: at file %s, line %d", aFile, aLine));
+ PR_LogFlush();
+
+ fprintf(stderr, "Break: at file %s, line %d\n",aFile, aLine); fflush(stderr);
+ fflush(stderr);
+
+#if defined(_WIN32)
+#ifdef _M_IX86
+ ::DebugBreak();
+#endif
+#elif defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT)
+ fprintf(stderr, "\07");
+
+ char *assertBehavior = getenv("XPCOM_DEBUG_BREAK");
+
+ if (!assertBehavior) {
+
+ // the default; nothing else to do
+ ;
+
+ } else if ( strcmp(assertBehavior, "suspend")== 0 ) {
+
+ // the suspend case is first because we wanna send the signal before
+ // other threads have had a chance to get too far from the state that
+ // caused this assertion (in case they happen to have been involved).
+ //
+ fprintf(stderr, "Suspending process; attach with the debugger.\n");
+ kill(0, SIGSTOP);
+
+ } else if ( strcmp(assertBehavior, "warn")==0 ) {
+
+ // same as default; nothing else to do (see "suspend" case comment for
+ // why this compare isn't done as part of the default case)
+ //
+ ;
+
+ }
+ else if ( strcmp(assertBehavior,"stack")==0 ) {
+
+ // walk the stack
+ //
+ nsTraceRefcntImpl::WalkTheStack(stderr);
+ }
+ else if ( strcmp(assertBehavior,"abort")==0 ) {
+
+ // same as UNIX_CRASH_ON_ASSERT
+ //
+ Abort(aFile, aLine);
+
+ } else if ( strcmp(assertBehavior,"trap")==0 ) {
+
+ DebugBreak();
+
+ } else {
+
+ fprintf(stderr, "unrecognized value of XPCOM_DEBUG_BREAK env var!\n");
+
+ }
+ fflush(stderr); // this shouldn't really be necessary, i don't think,
+ // but maybe there's some lame stdio that buffers stderr
+
+#elif defined(XP_BEOS)
+ {
+#ifdef UNIX_CRASH_ON_ASSERT
+ char buf[2000];
+ sprintf(buf, "Break: at file %s, line %d", aFile, aLine);
+ DEBUGGER(buf);
+#endif
+ }
+#else
+ Abort(aFile, aLine);
+#endif
+#endif // TEMP_MAC_HACK
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDebugImpl::Abort(const char *aFile, PRInt32 aLine)
+{
+ InitLog();
+
+ PR_LOG(gDebugLog, PR_LOG_ERROR,
+ ("###!!! Abort: at file %s, line %d", aFile, aLine));
+ PR_LogFlush();
+ fprintf(stderr, "\07 Abort\n"); fflush(stderr);
+ fflush(stderr);
+
+#if defined(_WIN32)
+#ifdef _M_IX86
+ long* __p = (long*) 0x7;
+ *__p = 0x7;
+#else /* _M_ALPHA */
+ PR_Abort();
+#endif
+#elif defined(XP_MAC)
+ ExitToShell();
+#elif defined(XP_UNIX)
+ PR_Abort();
+#elif defined(XP_OS2)
+ DebugBreak();
+ return NS_OK;
+#elif defined(XP_BEOS)
+ {
+#ifndef DEBUG_cls
+ char buf[2000];
+ sprintf(buf, "Abort: at file %s, line %d", aFile, aLine);
+ DEBUGGER(buf);
+#endif
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDebugImpl::Warning(const char* aMessage,
+ const char* aFile, PRIntn aLine)
+{
+ InitLog();
+
+ char buf[1000];
+ PR_snprintf(buf, sizeof(buf),
+ "WARNING: %s, file %s, line %d",
+ aMessage, aFile, aLine);
+
+ // Write out the warning message to the debug log
+ PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf));
+
+ // And write it out to the stdout
+ fprintf(stderr, "%s\n", buf);
+ fflush(stderr);
+ return NS_OK;
+}
+
+NS_METHOD
+nsDebugImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ *aInstancePtr = nsnull;
+ nsIDebug* debug = new nsDebugImpl();
+ if (!debug)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = debug->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv)) {
+ delete debug;
+ }
+
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_ErrorAccordingToNSPR()
+{
+ PRErrorCode err = PR_GetError();
+ switch (err) {
+ case PR_OUT_OF_MEMORY_ERROR: return NS_ERROR_OUT_OF_MEMORY;
+ case PR_WOULD_BLOCK_ERROR: return NS_BASE_STREAM_WOULD_BLOCK;
+ case PR_FILE_NOT_FOUND_ERROR: return NS_ERROR_FILE_NOT_FOUND;
+ case PR_READ_ONLY_FILESYSTEM_ERROR: return NS_ERROR_FILE_READ_ONLY;
+ case PR_NOT_DIRECTORY_ERROR: return NS_ERROR_FILE_NOT_DIRECTORY;
+ case PR_IS_DIRECTORY_ERROR: return NS_ERROR_FILE_IS_DIRECTORY;
+ case PR_LOOP_ERROR: return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
+ case PR_FILE_EXISTS_ERROR: return NS_ERROR_FILE_ALREADY_EXISTS;
+ case PR_FILE_IS_LOCKED_ERROR: return NS_ERROR_FILE_IS_LOCKED;
+ case PR_FILE_TOO_BIG_ERROR: return NS_ERROR_FILE_TOO_BIG;
+ case PR_NO_DEVICE_SPACE_ERROR: return NS_ERROR_FILE_NO_DEVICE_SPACE;
+ case PR_NAME_TOO_LONG_ERROR: return NS_ERROR_FILE_NAME_TOO_LONG;
+ case PR_DIRECTORY_NOT_EMPTY_ERROR: return NS_ERROR_FILE_DIR_NOT_EMPTY;
+ case PR_NO_ACCESS_RIGHTS_ERROR: return NS_ERROR_FILE_ACCESS_DENIED;
+ default: return NS_ERROR_FAILURE;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h
new file mode 100644
index 00000000..b6ca9770
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h
@@ -0,0 +1,61 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDebug.h"
+
+class nsDebugImpl : public nsIDebug
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDEBUG
+
+ nsDebugImpl();
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsDebugImpl() {}
+};
+
+
+#define NS_DEBUG_CONTRACTID "@mozilla.org/xpcom/debug;1"
+#define NS_DEBUG_CLASSNAME "nsDebug Interface"
+#define NS_DEBUG_CID \
+{ /* a80b1fb3-aaf6-4852-b678-c27eb7a518af */ \
+ 0xa80b1fb3, \
+ 0xaaf6, \
+ 0x4852, \
+ {0xb6, 0x78, 0xc2, 0x7e, 0xb7, 0xa5, 0x18, 0xaf} \
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsError.h b/src/libs/xpcom18a4/xpcom/base/nsError.h
new file mode 100644
index 00000000..e0f3fe54
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsError.h
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsError_h__
+#define nsError_h__
+
+#ifndef nscore_h___
+#include "nscore.h" /* needed for nsresult */
+#endif
+
+/*
+ * To add error code to your module, you need to do the following:
+ *
+ * 1) Add a module offset code. Add yours to the bottom of the list
+ * right below this comment, adding 1.
+ *
+ * 2) In your module, define a header file which uses one of the
+ * NE_ERROR_GENERATExxxxxx macros. Some examples below:
+ *
+ * #define NS_ERROR_MYMODULE_MYERROR1 NS_ERROR_GENERATE(NS_ERROR_SEVERITY_ERROR,NS_ERROR_MODULE_MYMODULE,1)
+ * #define NS_ERROR_MYMODULE_MYERROR2 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_MYMODULE,2)
+ * #define NS_ERROR_MYMODULE_MYERROR3 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_MYMODULE,3)
+ *
+ */
+
+
+/**
+ * @name Standard Module Offset Code. Each Module should identify a unique number
+ * and then all errors associated with that module become offsets from the
+ * base associated with that module id. There are 16 bits of code bits for
+ * each module.
+ */
+
+#define NS_ERROR_MODULE_XPCOM 1
+#define NS_ERROR_MODULE_BASE 2
+#define NS_ERROR_MODULE_GFX 3
+#define NS_ERROR_MODULE_WIDGET 4
+#define NS_ERROR_MODULE_CALENDAR 5
+#define NS_ERROR_MODULE_NETWORK 6
+#define NS_ERROR_MODULE_PLUGINS 7
+#define NS_ERROR_MODULE_LAYOUT 8
+#define NS_ERROR_MODULE_HTMLPARSER 9
+#define NS_ERROR_MODULE_RDF 10
+#define NS_ERROR_MODULE_UCONV 11
+#define NS_ERROR_MODULE_REG 12
+#define NS_ERROR_MODULE_FILES 13
+#define NS_ERROR_MODULE_DOM 14
+#define NS_ERROR_MODULE_IMGLIB 15
+#define NS_ERROR_MODULE_MAILNEWS 16
+#define NS_ERROR_MODULE_EDITOR 17
+#define NS_ERROR_MODULE_XPCONNECT 18
+#define NS_ERROR_MODULE_PROFILE 19
+#define NS_ERROR_MODULE_LDAP 20
+#define NS_ERROR_MODULE_SECURITY 21
+#define NS_ERROR_MODULE_DOM_XPATH 22
+#define NS_ERROR_MODULE_DOM_RANGE 23
+#define NS_ERROR_MODULE_URILOADER 24
+#define NS_ERROR_MODULE_CONTENT 25
+#define NS_ERROR_MODULE_PYXPCOM 26
+#define NS_ERROR_MODULE_XSLT 27
+#define NS_ERROR_MODULE_IPC 28
+#define NS_ERROR_MODULE_SVG 29
+
+/* NS_ERROR_MODULE_GENERAL should be used by modules that do not
+ * care if return code values overlap. Callers of methods that
+ * return such codes should be aware that they are not
+ * globally unique. Implementors should be careful about blindly
+ * returning codes from other modules that might also use
+ * the generic base.
+ */
+#define NS_ERROR_MODULE_GENERAL 51
+
+/**
+ * @name Standard Error Handling Macros
+ */
+
+#define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000))
+#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000)))
+
+/**
+ * @name Severity Code. This flag identifies the level of warning
+ */
+
+#define NS_ERROR_SEVERITY_SUCCESS 0
+#define NS_ERROR_SEVERITY_ERROR 1
+
+/**
+ * @name Mozilla Code. This flag separates consumers of mozilla code
+ * from the native platform
+ */
+
+#define NS_ERROR_MODULE_BASE_OFFSET 0x45
+
+/**
+ * @name Standard Error Generating Macros
+ */
+
+#define NS_ERROR_GENERATE(sev,module,code) \
+ ((nsresult) (((PRUint32)(sev)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
+
+#define NS_ERROR_GENERATE_SUCCESS(module,code) \
+ ((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_SUCCESS)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
+
+#define NS_ERROR_GENERATE_FAILURE(module,code) \
+ ((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_ERROR)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
+
+/**
+ * @name Standard Macros for retrieving error bits
+ */
+
+#define NS_ERROR_GET_CODE(err) ((err) & 0xffff)
+#define NS_ERROR_GET_MODULE(err) (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff))
+#define NS_ERROR_GET_SEVERITY(err) (((err) >> 31) & 0x1)
+
+/**
+ * @name Standard return values
+ */
+
+/*@{*/
+
+/* Standard "it worked" return value */
+#define NS_OK 0
+
+#define NS_ERROR_BASE ((nsresult) 0xC1F30000)
+
+/* Returned when an instance is not initialized */
+#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
+
+/* Returned when an instance is already initialized */
+#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2)
+
+/* Returned by a not implemented function */
+#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L)
+
+/* Returned when a given interface is not supported. */
+#define NS_NOINTERFACE ((nsresult) 0x80004002L)
+#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
+
+#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L)
+#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER
+
+/* Returned when a function aborts */
+#define NS_ERROR_ABORT ((nsresult) 0x80004004L)
+
+/* Returned when a function fails */
+#define NS_ERROR_FAILURE ((nsresult) 0x80004005L)
+
+/* Returned when an IPC fails */
+#define NS_ERROR_CALL_FAILED ((nsresult) 0x800706beL)
+
+/* Returned when an unexpected error occurs */
+#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL)
+
+/* Returned when a memory allocation fails */
+#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL)
+
+/* Returned when an illegal value is passed */
+#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
+#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
+
+/* Returned when a class doesn't allow aggregation */
+#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L)
+
+/* Returned when an operation can't complete due to an unavailable resource */
+#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L)
+
+/* Returned when a class is not registered */
+#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
+
+/* Returned when a class cannot be registered, but may be tried again later */
+#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L)
+
+/* Returned when a dynamically loaded factory couldn't be found */
+#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)
+
+/* Returned when a factory doesn't support signatures */
+#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \
+ (NS_ERROR_BASE + 0x101)
+
+/* Returned when a factory already is registered */
+#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
+
+/* Socket failures */
+#define NS_ERROR_SOCKET_FAIL (NS_ERROR_BASE + 0x200)
+
+
+/* For COM compatibility reasons, we want to use exact error code numbers
+ for NS_ERROR_PROXY_INVALID_IN_PARAMETER and NS_ERROR_PROXY_INVALID_OUT_PARAMETER.
+ The first matches:
+
+ #define RPC_E_INVALID_PARAMETER _HRESULT_TYPEDEF_(0x80010010L)
+
+ Errors returning this mean that the xpcom proxy code could not create a proxy for
+ one of the in paramaters.
+
+ Because of this, we are ignoring the convention if using a base and offset for
+ error numbers.
+
+*/
+
+/* Returned when a proxy could not be create a proxy for one of the IN parameters
+ This is returned only when the "real" meathod has NOT been invoked.
+*/
+
+#define NS_ERROR_PROXY_INVALID_IN_PARAMETER ((nsresult) 0x80010010L)
+
+/* Returned when a proxy could not be create a proxy for one of the OUT parameters
+ This is returned only when the "real" meathod has ALREADY been invoked.
+*/
+
+#define NS_ERROR_PROXY_INVALID_OUT_PARAMETER ((nsresult) 0x80010011L)
+
+
+/*@}*/
+
+ /* I/O Errors */
+
+ /* Stream closed */
+#define NS_BASE_STREAM_CLOSED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
+ /* Error from the operating system */
+#define NS_BASE_STREAM_OSERROR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3)
+ /* Illegal arguments */
+#define NS_BASE_STREAM_ILLEGAL_ARGS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4)
+ /* For unichar streams */
+#define NS_BASE_STREAM_NO_CONVERTER NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5)
+ /* For unichar streams */
+#define NS_BASE_STREAM_BAD_CONVERSION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6)
+
+#define NS_BASE_STREAM_WOULD_BLOCK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7)
+
+
+#define NS_ERROR_FILE_UNRECOGNIZED_PATH NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1)
+#define NS_ERROR_FILE_UNRESOLVABLE_SYMLINK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2)
+#define NS_ERROR_FILE_EXECUTION_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3)
+#define NS_ERROR_FILE_UNKNOWN_TYPE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4)
+#define NS_ERROR_FILE_DESTINATION_NOT_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5)
+#define NS_ERROR_FILE_TARGET_DOES_NOT_EXIST NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6)
+#define NS_ERROR_FILE_COPY_OR_MOVE_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7)
+#define NS_ERROR_FILE_ALREADY_EXISTS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8)
+#define NS_ERROR_FILE_INVALID_PATH NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9)
+#define NS_ERROR_FILE_DISK_FULL NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10)
+#define NS_ERROR_FILE_CORRUPTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11)
+#define NS_ERROR_FILE_NOT_DIRECTORY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12)
+#define NS_ERROR_FILE_IS_DIRECTORY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13)
+#define NS_ERROR_FILE_IS_LOCKED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14)
+#define NS_ERROR_FILE_TOO_BIG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15)
+#define NS_ERROR_FILE_NO_DEVICE_SPACE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16)
+#define NS_ERROR_FILE_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17)
+#define NS_ERROR_FILE_NOT_FOUND NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18)
+#define NS_ERROR_FILE_READ_ONLY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19)
+#define NS_ERROR_FILE_DIR_NOT_EMPTY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20)
+#define NS_ERROR_FILE_ACCESS_DENIED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21)
+
+#define NS_SUCCESS_FILE_DIRECTORY_EMPTY NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_FILES, 1)
+
+ /* Result codes used by nsIVariant */
+
+#define NS_ERROR_CANNOT_CONVERT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 1)
+#define NS_ERROR_OBJECT_IS_IMMUTABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 2)
+#define NS_ERROR_LOSS_OF_SIGNIFICANT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 3)
+
+#define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1)
+
+
+ /*
+ * This will return the nsresult corresponding to the most recent NSPR failure
+ * returned by PR_GetError.
+ *
+ ***********************************************************************
+ * Do not depend on this function. It will be going away!
+ ***********************************************************************
+ */
+extern NS_COM nsresult
+NS_ErrorAccordingToNSPR();
+
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4251) /* 'nsCOMPtr<class nsIInputStream>' needs to have dll-interface to be used by clients of class 'nsInputStream' */
+#pragma warning(disable: 4275) /* non dll-interface class 'nsISupports' used as base for dll-interface class 'nsIRDFNode' */
+#endif
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp b/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp
new file mode 100644
index 00000000..f38495ed
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsErrorService.h"
+#include "nsCRT.h"
+
+static void* PR_CALLBACK
+CloneCString(nsHashKey *aKey, void *aData, void* closure)
+{
+ return nsCRT::strdup((const char*)aData);
+}
+
+static PRBool PR_CALLBACK
+DeleteCString(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsCRT::free((char*)aData);
+ return PR_TRUE;
+}
+
+nsInt2StrHashtable::nsInt2StrHashtable()
+ : mHashtable(CloneCString, nsnull, DeleteCString, nsnull, 16)
+{
+}
+
+nsresult
+nsInt2StrHashtable::Put(PRUint32 key, const char* aData)
+{
+ char* value = nsCRT::strdup(aData);
+ if (value == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsPRUint32Key k(key);
+ char* oldValue = (char*)mHashtable.Put(&k, value);
+ if (oldValue)
+ nsCRT::free(oldValue);
+ return NS_OK;
+}
+
+char*
+nsInt2StrHashtable::Get(PRUint32 key)
+{
+ nsPRUint32Key k(key);
+ const char* value = (const char*)mHashtable.Get(&k);
+ if (value == nsnull)
+ return nsnull;
+ return nsCRT::strdup(value);
+}
+
+nsresult
+nsInt2StrHashtable::Remove(PRUint32 key)
+{
+ nsPRUint32Key k(key);
+ char* oldValue = (char*)mHashtable.Remove(&k);
+ if (oldValue)
+ nsCRT::free(oldValue);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMPL_ISUPPORTS1(nsErrorService, nsIErrorService)
+
+NS_METHOD
+nsErrorService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_NO_AGGREGATION(outer);
+ nsErrorService* serv = new nsErrorService();
+ if (serv == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(serv);
+ nsresult rv = serv->QueryInterface(aIID, aInstancePtr);
+ NS_RELEASE(serv);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsErrorService::RegisterErrorStringBundle(PRInt16 errorModule, const char *stringBundleURL)
+{
+ return mErrorStringBundleURLMap.Put(errorModule, stringBundleURL);
+}
+
+NS_IMETHODIMP
+nsErrorService::UnregisterErrorStringBundle(PRInt16 errorModule)
+{
+ return mErrorStringBundleURLMap.Remove(errorModule);
+}
+
+NS_IMETHODIMP
+nsErrorService::GetErrorStringBundle(PRInt16 errorModule, char **result)
+{
+ char* value = mErrorStringBundleURLMap.Get(errorModule);
+ if (value == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = value;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsErrorService::RegisterErrorStringBundleKey(nsresult error, const char *stringBundleKey)
+{
+ return mErrorStringBundleKeyMap.Put(error, stringBundleKey);
+}
+
+NS_IMETHODIMP
+nsErrorService::UnregisterErrorStringBundleKey(nsresult error)
+{
+ return mErrorStringBundleKeyMap.Remove(error);
+}
+
+NS_IMETHODIMP
+nsErrorService::GetErrorStringBundleKey(nsresult error, char **result)
+{
+ char* value = mErrorStringBundleKeyMap.Get(error);
+ if (value == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = value;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/base/nsErrorService.h b/src/libs/xpcom18a4/xpcom/base/nsErrorService.h
new file mode 100644
index 00000000..70a30c0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsErrorService.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsErrorService_h__
+#define nsErrorService_h__
+
+#include "nsIErrorService.h"
+#include "nsHashtable.h"
+
+class nsInt2StrHashtable
+{
+public:
+ nsInt2StrHashtable();
+
+ nsresult Put(PRUint32 key, const char* aData);
+ char* Get(PRUint32 key);
+ nsresult Remove(PRUint32 key);
+
+protected:
+ nsObjectHashtable mHashtable;
+};
+
+class nsErrorService : public nsIErrorService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIERRORSERVICE
+
+ nsErrorService() {}
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsErrorService() {}
+
+protected:
+ nsInt2StrHashtable mErrorStringBundleURLMap;
+ nsInt2StrHashtable mErrorStringBundleKeyMap;
+};
+
+#endif // nsErrorService_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp
new file mode 100644
index 00000000..f68f2d5f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.h"
+#include "nsExceptionService.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+#include "prthread.h"
+#include "prlock.h"
+static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
+
+#define CHECK_SERVICE_USE_OK() if (tlsIndex == BAD_TLS_INDEX) return NS_ERROR_NOT_INITIALIZED
+#define CHECK_MANAGER_USE_OK() if (!mService || nsExceptionService::tlsIndex == BAD_TLS_INDEX) return NS_ERROR_NOT_INITIALIZED
+
+// A key for our registered module providers hashtable
+class nsProviderKey : public nsHashKey {
+protected:
+ PRUint32 mKey;
+public:
+ nsProviderKey(PRUint32 key) : mKey(key) {}
+ PRUint32 HashCode(void) const {
+ return mKey;
+ }
+ PRBool Equals(const nsHashKey *aKey) const {
+ return mKey == ((const nsProviderKey *) aKey)->mKey;
+ }
+ nsHashKey *Clone() const {
+ return new nsProviderKey(mKey);
+ }
+ PRUint32 GetValue() { return mKey; }
+};
+
+/** Exception Manager definition **/
+class nsExceptionManager : public nsIExceptionManager
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEXCEPTIONMANAGER
+
+ nsExceptionManager(nsExceptionService *svc);
+ /* additional members */
+ nsCOMPtr<nsIException> mCurrentException;
+ nsExceptionManager *mNextThread; // not ref-counted.
+ nsExceptionService *mService; // not ref-counted
+#ifdef NS_DEBUG
+ static PRInt32 totalInstances;
+#endif
+
+#ifdef NS_DEBUG
+ inline nsrefcnt ReleaseQuiet() {
+ // shut up NS_ASSERT_OWNINGTHREAD (see explanation below)
+ nsAutoOwningThread old = _mOwningThread;
+ _mOwningThread = nsAutoOwningThread();
+ nsrefcnt ref = Release();
+ NS_ASSERTION(ref == 0, "the object is still referenced by other threads while it shouldn't");
+ if (ref != 0)
+ _mOwningThread = old;
+ return ref;
+ }
+#else
+ inline nsrefcnt ReleaseQuiet(void) { return Release(); }
+#endif
+
+private:
+ ~nsExceptionManager();
+};
+
+
+#ifdef NS_DEBUG
+PRInt32 nsExceptionManager::totalInstances = 0;
+#endif
+
+// Note: the nsExceptionManager object is single threaded - the exception
+// service itself ensures one per thread. However, there are two methods that
+// may be called on foreign threads: DropAllThreads (called on the thread
+// shutting down xpcom) and ThreadDestruct (called after xpcom destroyed the
+// internal thread struct, so that PR_GetCurrentThread() will create a new one
+// from scratch which will obviously not match the old one stored in the
+// instance on creation). In both cases, there should be no other threads
+// holding objects (i.e. it's thread-safe to call them), but
+// NS_CheckThreadSafe() assertions will still happen and yell in the debug
+// build. Since it is quite annoying, we use a special ReleaseQuiet() method
+// in DoDropThread() to shut them up.
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsExceptionManager, nsIExceptionManager)
+
+nsExceptionManager::nsExceptionManager(nsExceptionService *svc) :
+ mNextThread(nsnull),
+ mService(svc)
+{
+ /* member initializers and constructor code */
+#ifdef NS_DEBUG
+ PR_AtomicIncrement(&totalInstances);
+#endif
+}
+
+nsExceptionManager::~nsExceptionManager()
+{
+ /* destructor code */
+#ifdef NS_DEBUG
+ PR_AtomicDecrement(&totalInstances);
+#endif // NS_DEBUG
+}
+
+/* void setCurrentException (in nsIException error); */
+NS_IMETHODIMP nsExceptionManager::SetCurrentException(nsIException *error)
+{
+ CHECK_MANAGER_USE_OK();
+ mCurrentException = error;
+ return NS_OK;
+}
+
+/* nsIException getCurrentException (); */
+NS_IMETHODIMP nsExceptionManager::GetCurrentException(nsIException **_retval)
+{
+ CHECK_MANAGER_USE_OK();
+ *_retval = mCurrentException;
+ NS_IF_ADDREF(*_retval);
+ return NS_OK;
+}
+
+/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
+NS_IMETHODIMP nsExceptionManager::GetExceptionFromProvider(nsresult rc, nsIException * defaultException, nsIException **_retval)
+{
+ CHECK_MANAGER_USE_OK();
+ // Just delegate back to the service with the provider map.
+ return mService->GetExceptionFromProvider(rc, defaultException, _retval);
+}
+
+/* The Exception Service */
+
+PRUintn nsExceptionService::tlsIndex = BAD_TLS_INDEX;
+PRLock *nsExceptionService::lock = nsnull;
+nsExceptionManager *nsExceptionService::firstThread = nsnull;
+
+#ifdef NS_DEBUG
+PRInt32 nsExceptionService::totalInstances = 0;
+#endif
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsExceptionService, nsIExceptionService, nsIObserver)
+
+nsExceptionService::nsExceptionService()
+ : mProviders(4, PR_TRUE) /* small, thread-safe hashtable */
+{
+#ifdef NS_DEBUG
+ if (PR_AtomicIncrement(&totalInstances)!=1) {
+ NS_ERROR("The nsExceptionService is a singleton!");
+ }
+#endif
+ /* member initializers and constructor code */
+ if (tlsIndex == BAD_TLS_INDEX) {
+ PRStatus status;
+ status = PR_NewThreadPrivateIndex( &tlsIndex, ThreadDestruct );
+ NS_WARN_IF_FALSE(status==0, "ScriptErrorService could not allocate TLS storage.");
+ }
+ lock = PR_NewLock();
+ NS_WARN_IF_FALSE(lock, "Error allocating ExceptionService lock");
+
+ // observe XPCOM shutdown.
+ nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
+ NS_WARN_IF_FALSE(observerService, "Could not get observer service!");
+ if (observerService)
+ observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+}
+
+nsExceptionService::~nsExceptionService()
+{
+ Shutdown();
+ if (lock) {
+ PRLock *tmp = lock;
+ lock = nsnull;
+ PR_DestroyLock(tmp);
+ }
+ /* destructor code */
+#ifdef NS_DEBUG
+ PR_AtomicDecrement(&totalInstances);
+#endif
+}
+
+/*static*/
+void nsExceptionService::ThreadDestruct( void *data )
+{
+ if (!lock) {
+ NS_WARNING("nsExceptionService ignoring thread destruction after shutdown");
+ return;
+ }
+ DropThread( (nsExceptionManager *)data );
+}
+
+
+void nsExceptionService::Shutdown()
+{
+ PRUintn tmp = tlsIndex;
+ tlsIndex = BAD_TLS_INDEX;
+ PR_SetThreadPrivate(tmp, nsnull);
+ mProviders.Reset();
+ if (lock) {
+ DropAllThreads();
+ }
+}
+
+/* void setCurrentException (in nsIException error); */
+NS_IMETHODIMP nsExceptionService::SetCurrentException(nsIException *error)
+{
+ CHECK_SERVICE_USE_OK();
+ nsCOMPtr<nsIExceptionManager> sm;
+ nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
+ if (NS_FAILED(nr))
+ return nr;
+ return sm->SetCurrentException(error);
+}
+
+/* nsIException getCurrentException (); */
+NS_IMETHODIMP nsExceptionService::GetCurrentException(nsIException **_retval)
+{
+ CHECK_SERVICE_USE_OK();
+ nsCOMPtr<nsIExceptionManager> sm;
+ nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
+ if (NS_FAILED(nr))
+ return nr;
+ return sm->GetCurrentException(_retval);
+}
+
+/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
+NS_IMETHODIMP nsExceptionService::GetExceptionFromProvider(nsresult rc,
+ nsIException * defaultException, nsIException **_retval)
+{
+ CHECK_SERVICE_USE_OK();
+ return DoGetExceptionFromProvider(rc, defaultException, _retval);
+}
+
+/* readonly attribute nsIExceptionManager currentExceptionManager; */
+NS_IMETHODIMP nsExceptionService::GetCurrentExceptionManager(nsIExceptionManager * *aCurrentScriptManager)
+{
+ CHECK_SERVICE_USE_OK();
+ nsExceptionManager *mgr = (nsExceptionManager *)PR_GetThreadPrivate(tlsIndex);
+ if (mgr == nsnull) {
+ // Stick the new exception object in with no reference count.
+ mgr = new nsExceptionManager(this);
+ if (mgr == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ PR_SetThreadPrivate(tlsIndex, mgr);
+ // The reference count is held in the thread-list
+ AddThread(mgr);
+ }
+ *aCurrentScriptManager = mgr;
+ NS_ADDREF(*aCurrentScriptManager);
+ return NS_OK;
+}
+
+/* void registerErrorProvider (in nsIExceptionProvider provider, in PRUint32 moduleCode); */
+NS_IMETHODIMP nsExceptionService::RegisterExceptionProvider(nsIExceptionProvider *provider, PRUint32 errorModule)
+{
+ CHECK_SERVICE_USE_OK();
+
+ nsProviderKey key(errorModule);
+ if (mProviders.Put(&key, provider)) {
+ NS_WARNING("Registration of exception provider overwrote another provider with the same module code!");
+ }
+ return NS_OK;
+}
+
+/* void unregisterErrorProvider (in nsIExceptionProvider provider, in PRUint32 errorModule); */
+NS_IMETHODIMP nsExceptionService::UnregisterExceptionProvider(nsIExceptionProvider *provider, PRUint32 errorModule)
+{
+ CHECK_SERVICE_USE_OK();
+ nsProviderKey key(errorModule);
+ if (!mProviders.Remove(&key)) {
+ NS_WARNING("Attempt to unregister an unregistered exception provider!");
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+// nsIObserver
+NS_IMETHODIMP nsExceptionService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
+{
+ Shutdown();
+ return NS_OK;
+}
+
+nsresult
+nsExceptionService::DoGetExceptionFromProvider(nsresult errCode,
+ nsIException * defaultException,
+ nsIException **_exc)
+{
+ // Check for an existing exception
+ nsresult nr = GetCurrentException(_exc);
+ if (NS_SUCCEEDED(nr) && *_exc) {
+ (*_exc)->GetResult(&nr);
+ // If it matches our result then use it
+ if (nr == errCode)
+ return NS_OK;
+ NS_RELEASE(*_exc);
+ }
+ nsProviderKey key(NS_ERROR_GET_MODULE(errCode));
+ nsCOMPtr<nsIExceptionProvider> provider =
+ dont_AddRef((nsIExceptionProvider *)mProviders.Get(&key));
+
+ // No provider so we'll return the default exception
+ if (!provider) {
+ *_exc = defaultException;
+ NS_IF_ADDREF(*_exc);
+ return NS_OK;
+ }
+
+ return provider->GetException(errCode, defaultException, _exc);
+}
+
+// thread management
+/*static*/ void nsExceptionService::AddThread(nsExceptionManager *thread)
+{
+ PR_Lock(lock);
+ thread->mNextThread = firstThread;
+ firstThread = thread;
+ NS_ADDREF(thread);
+ PR_Unlock(lock);
+}
+
+/*static*/ void nsExceptionService::DoDropThread(nsExceptionManager *thread)
+{
+ nsExceptionManager **emp = &firstThread;
+ while (*emp != thread) {
+ if (!*emp)
+ {
+ NS_WARNING("Could not find the thread to drop!");
+ return;
+ }
+ emp = &(*emp)->mNextThread;
+ }
+ *emp = thread->mNextThread;
+ thread->ReleaseQuiet();
+ thread = nsnull;
+}
+
+/*static*/ void nsExceptionService::DropThread(nsExceptionManager *thread)
+{
+ PR_Lock(lock);
+ DoDropThread(thread);
+ PR_Unlock(lock);
+}
+
+/*static*/ void nsExceptionService::DropAllThreads()
+{
+ PR_Lock(lock);
+ while (firstThread)
+ DoDropThread(firstThread);
+ PR_Unlock(lock);
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h
new file mode 100644
index 00000000..441a4c5b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsExceptionService_h__
+#define nsExceptionService_h__
+
+#include "nsVoidArray.h"
+#include "nsIException.h"
+#include "nsIExceptionService.h"
+#include "nsIObserverService.h"
+#include "nsHashtable.h"
+#include "nsIObserver.h"
+
+class nsExceptionManager;
+
+/** Exception Service definition **/
+class nsExceptionService : public nsIExceptionService, public nsIObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEXCEPTIONSERVICE
+ NS_DECL_NSIEXCEPTIONMANAGER
+ NS_DECL_NSIOBSERVER
+
+ nsExceptionService();
+
+ /* additional members */
+ nsresult DoGetExceptionFromProvider(nsresult errCode,
+ nsIException *defaultException,
+ nsIException **_richError);
+ void Shutdown();
+
+
+ /* thread management and cleanup */
+ static void AddThread(nsExceptionManager *);
+ static void DropThread(nsExceptionManager *);
+ static void DoDropThread(nsExceptionManager *thread);
+
+ static void DropAllThreads();
+ static nsExceptionManager *firstThread;
+
+ nsSupportsHashtable mProviders;
+
+ /* single lock protects both providers hashtable
+ and thread list */
+ static PRLock* lock;
+
+ static PRUintn tlsIndex;
+ static void PR_CALLBACK ThreadDestruct( void *data );
+#ifdef NS_DEBUG
+ static PRInt32 totalInstances;
+#endif
+
+private:
+ ~nsExceptionService();
+};
+
+
+#endif // nsExceptionService_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c b/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c
new file mode 100644
index 00000000..b0447598
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Beard <beard@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ nsGarbageCollector.c
+ */
+
+#ifdef GC_LEAK_DETECTOR
+
+/* for FILE */
+#include <stdio.h>
+
+/* NSPR stuff */
+#include "generic_threads.h"
+#include "prthread.h"
+#include "prlock.h"
+
+/* Linux/Win32 export private NSPR files to include/private */
+#ifdef XP_MAC
+#include "pprthred.h"
+#else
+#include "private/pprthred.h"
+#endif
+
+#include "nsLeakDetector.h"
+
+extern FILE *GC_stdout, *GC_stderr;
+
+extern void GC_gcollect(void);
+extern void GC_clear_roots(void);
+
+static PRStatus PR_CALLBACK scanner(PRThread* t, void** baseAddr, PRUword count, void* closure)
+{
+ char* begin = (char*)baseAddr;
+ char* end = (char*)(baseAddr + count);
+ GC_mark_range_proc marker = (GC_mark_range_proc) closure;
+ marker(begin, end);
+ return PR_SUCCESS;
+}
+
+static void mark_all_stacks(GC_mark_range_proc marker)
+{
+ /* PR_ThreadScanStackPointers(PR_GetCurrentThread(), &scanner, marker); */
+ PR_ScanStackPointers(&scanner, (void *)marker);
+}
+
+static void locker(void* mutex)
+{
+ PR_Lock(mutex);
+}
+
+static void unlocker(void* mutex)
+{
+ PR_Unlock(mutex);
+}
+
+static void stopper(void* unused)
+{
+ PR_SuspendAll();
+}
+
+static void starter(void* unused)
+{
+ PR_ResumeAll();
+}
+
+nsresult NS_InitGarbageCollector()
+{
+ PRLock* mutex;
+
+ /* redirect GC's stderr to catch startup leaks. */
+ GC_stderr = fopen("StartupLeaks", "w");
+
+ mutex = PR_NewLock();
+ if (mutex == NULL)
+ return NS_ERROR_FAILURE;
+
+ GC_generic_init_threads(&mark_all_stacks, mutex,
+ &locker, &unlocker,
+ &stopper, &starter);
+
+ return NS_OK;
+}
+
+nsresult NS_ShutdownGarbageCollector()
+{
+ /* do anything you need to shut down the collector. */
+ return NS_OK;
+}
+
+#endif /* GC_LEAK_DETECTOR */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h b/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h
new file mode 100644
index 00000000..2195f42d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * XXX This file is obsolete. Use nsIMemory.idl or nsMemory.h instead.
+ */
+
+#ifndef nsIAllocator_h___
+#define nsIAllocator_h___
+
+#include "nsMemory.h"
+
+#define nsIAllocator nsIMemory
+#define nsAllocator nsMemory
+#define GetGlobalAllocator GetGlobalMemoryService
+
+#define NS_IALLOCATOR_IID NS_GET_IID(nsIMemory)
+#define NS_ALLOCATOR_CONTRACTID NS_MEMORY_CONTRACTID
+#define NS_ALLOCATOR_CLASSNAME NS_MEMORY_CLASSNAME
+#define NS_ALLOCATOR_CID NS_MEMORY_CID
+
+#endif /* nsIAllocator_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl
new file mode 100644
index 00000000..f983132d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Used by the console service to notify listeners of new console messages.
+ */
+
+#include "nsISupports.idl"
+#include "nsIConsoleMessage.idl"
+
+[scriptable, uuid(eaaf61d6-1dd1-11b2-bc6e-8fc96480f20d)]
+interface nsIConsoleListener : nsISupports
+{
+ void observe(in nsIConsoleMessage aMessage);
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl
new file mode 100644
index 00000000..0662a2d2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * This is intended as a base interface; implementations may want to
+ * provide an object that can be qi'ed to provide more specific
+ * message information.
+ */
+[scriptable, uuid(41bd8784-1dd2-11b2-9553-8606958fffe1)]
+interface nsIConsoleMessage : nsISupports
+{
+ readonly attribute wstring message;
+};
+
+%{ C++
+#define NS_CONSOLEMESSAGE_CID \
+{ 0x56c9d666, 0x1dd2, 0x11b2, { 0xb4, 0x3c, 0xa8, 0x4b, 0xf3, 0xb3, 0xec, 0xbb }}
+
+#define NS_CONSOLEMESSAGE_CONTRACTID "@mozilla.org/consolemessage;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl
new file mode 100644
index 00000000..283c7acc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIConsoleListener.idl"
+#include "nsIConsoleMessage.idl"
+
+[scriptable, uuid(a647f184-1dd1-11b2-a9d1-8537b201161b)]
+interface nsIConsoleService : nsISupports
+{
+ void logMessage(in nsIConsoleMessage message);
+
+ /**
+ * Convenience method for logging simple messages.
+ */
+ void logStringMessage(in wstring message);
+
+ /**
+ * Get an array of all the messages logged so far. If no messages
+ * are logged, this function will return a count of 0, but still
+ * will allocate one word for messages, so as to show up as a
+ * 0-length array when called from script.
+ */
+ void getMessageArray([array, size_is(count)] out nsIConsoleMessage messages,
+ out PRUint32 count);
+
+ /**
+ * To guard against stack overflows from listeners that could log
+ * messages (it's easy to do this inadvertently from listeners
+ * implemented in JavaScript), we don't call any listeners when
+ * another error is already being logged.
+ */
+ void registerListener(in nsIConsoleListener listener);
+
+ /**
+ * Each registered listener should also be unregistered.
+ */
+ void unregisterListener(in nsIConsoleListener listener);
+
+};
+
+
+%{ C++
+#define NS_CONSOLESERVICE_CLASSNAME "Console Service"
+
+#define NS_CONSOLESERVICE_CID \
+{ 0x7e3ff85c, 0x1dd2, 0x11b2, { 0x8d, 0x4b, 0xeb, 0x45, 0x2c, 0xb0, 0xff, 0x40 }}
+
+#define NS_CONSOLESERVICE_CONTRACTID "@mozilla.org/consoleservice;1"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsID.cpp b/src/libs/xpcom18a4/xpcom/base/nsID.cpp
new file mode 100644
index 00000000..adb0d41c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsID.cpp
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Daniel Bratell <bratell@lysator.liu.se>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsID.h"
+#include "prprf.h"
+#include "prmem.h"
+
+static const char gIDFormat[] =
+ "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
+
+static const char gIDFormat2[] =
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+
+
+/**
+ * Multiplies the_int_var with 16 (0x10) and adds the value of the
+ * hexadecimal digit the_char. If it fails it returns PR_FALSE from
+ * the function it's used in.
+ */
+
+#define ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(the_char, the_int_var) \
+ the_int_var = (the_int_var << 4) + the_char; \
+ if(the_char >= '0' && the_char <= '9') the_int_var -= '0'; \
+ else if(the_char >= 'a' && the_char <= 'f') the_int_var -= 'a'-10; \
+ else if(the_char >= 'A' && the_char <= 'F') the_int_var -= 'A'-10; \
+ else return PR_FALSE
+
+
+/**
+ * Parses number_of_chars characters from the char_pointer pointer and
+ * puts the number in the dest_variable. The pointer is moved to point
+ * at the first character after the parsed ones. If it fails it returns
+ * PR_FALSE from the function the macro is used in.
+ */
+
+#define PARSE_CHARS_TO_NUM(char_pointer, dest_variable, number_of_chars) \
+ do { PRInt32 _i=number_of_chars; \
+ dest_variable = 0; \
+ while(_i) { \
+ ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(*char_pointer, dest_variable); \
+ char_pointer++; \
+ _i--; \
+ } } while(0)
+
+
+/**
+ * Parses a hyphen from the char_pointer string. If there is no hyphen there
+ * the function returns PR_FALSE from the function it's used in. The
+ * char_pointer is advanced one step.
+ */
+
+ #define PARSE_HYPHEN(char_pointer) if(*(char_pointer++) != '-') return PR_FALSE
+
+/*
+ * Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into
+ * an nsID. It can also handle the old format without the { and }.
+ */
+
+NS_COM PRBool nsID::Parse(const char *aIDStr)
+{
+ /* Optimized for speed */
+ if(!aIDStr) {
+ return PR_FALSE;
+ }
+
+ PRBool expectFormat1 = (aIDStr[0] == '{');
+ if(expectFormat1) aIDStr++;
+
+ PARSE_CHARS_TO_NUM(aIDStr, m0, 8);
+ PARSE_HYPHEN(aIDStr);
+ PARSE_CHARS_TO_NUM(aIDStr, m1, 4);
+ PARSE_HYPHEN(aIDStr);
+ PARSE_CHARS_TO_NUM(aIDStr, m2, 4);
+ PARSE_HYPHEN(aIDStr);
+ int i;
+ for(i=0; i<2; i++)
+ PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
+ PARSE_HYPHEN(aIDStr);
+ while(i < 8) {
+ PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
+ i++;
+ }
+
+ return expectFormat1 ? *aIDStr == '}' : PR_TRUE;
+}
+
+/*
+ * Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ * format. The string is allocated with PR_Malloc and should be freed by
+ * the caller.
+ */
+
+NS_COM char *nsID::ToString() const
+{
+ char *res = (char*)PR_Malloc(39); // use PR_Malloc if this is to be freed with nsCRT::free
+
+ if (res != NULL) {
+ PR_snprintf(res, 39, gIDFormat,
+ m0, (PRUint32) m1, (PRUint32) m2,
+ (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
+ (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
+ (PRUint32) m3[6], (PRUint32) m3[7]);
+ }
+ return res;
+}
+
+#ifdef VBOX
+void nsID::ToProvidedString(char (&dest)[NSID_LENGTH]) const
+{
+ PR_snprintf(dest, NSID_LENGTH, gIDFormat,
+ m0, (PRUint32) m1, (PRUint32) m2,
+ (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
+ (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
+ (PRUint32) m3[6], (PRUint32) m3[7]);
+}
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsID.h b/src/libs/xpcom18a4/xpcom/base/nsID.h
new file mode 100644
index 00000000..257ba927
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsID.h
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsID_h__
+#define nsID_h__
+
+#include <string.h>
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifdef VBOX
+#define NSID_LENGTH 39
+#endif
+
+/**
+ * A "unique identifier". This is modeled after OSF DCE UUIDs.
+ * @status FROZEN
+ */
+
+struct nsID {
+ /**
+ * @name Indentifier values
+ */
+
+ //@{
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+ //@}
+
+ /**
+ * @name Methods
+ */
+
+ //@{
+ /**
+ * Equivalency method. Compares this nsID with another.
+ * @return <b>PR_TRUE</b> if they are the same, <b>PR_FALSE</b> if not.
+ */
+
+ inline PRBool Equals(const nsID& other) const {
+ // One would think that this could be done faster with a really
+ // efficient implementation of memcmp(), but evidently no
+ // memcmp()'s out there are better than this code.
+ //
+ // See bug http://bugzilla.mozilla.org/show_bug.cgi?id=164580 for
+ // details.
+
+ return (PRBool)
+ ((((PRUint32*) &m0)[0] == ((PRUint32*) &other.m0)[0]) &&
+ (((PRUint32*) &m0)[1] == ((PRUint32*) &other.m0)[1]) &&
+ (((PRUint32*) &m0)[2] == ((PRUint32*) &other.m0)[2]) &&
+ (((PRUint32*) &m0)[3] == ((PRUint32*) &other.m0)[3]));
+ }
+
+ /**
+ * nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ * string into an nsID
+ */
+ NS_COM PRBool Parse(const char *aIDStr);
+
+ /**
+ * nsID string encoder. Returns an allocated string in
+ * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format. Caller should free string.
+ */
+ NS_COM char* ToString() const;
+
+#ifdef VBOX
+ /**
+ * nsID string encoder. Builds a string in
+ * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format, into a char[NSID_LENGTH]
+ * buffer provided by the caller (for instance, on the stack).
+ */
+ NS_COM void ToProvidedString(char (&dest)[NSID_LENGTH]) const;
+#endif
+
+ //@}
+};
+
+/*
+ * Class IDs
+ */
+
+typedef nsID nsCID;
+
+// Define an CID
+#define NS_DEFINE_CID(_name, _cidspec) \
+ const nsCID _name = _cidspec
+
+#define REFNSCID const nsCID&
+
+/**
+ * An "interface id" which can be used to uniquely identify a given
+ * interface.
+ */
+
+typedef nsID nsIID;
+
+/**
+ * A macro shorthand for <tt>const nsIID&<tt>
+ */
+
+#define REFNSIID const nsIID&
+
+/**
+ * Define an IID
+ * obsolete - do not use this macro
+ */
+
+#define NS_DEFINE_IID(_name, _iidspec) \
+ const nsIID _name = _iidspec
+
+/**
+ * A macro to build the static const IID accessor method
+ */
+
+#define NS_DEFINE_STATIC_IID_ACCESSOR(the_iid) \
+ static const nsIID& GetIID() {static const nsIID iid = the_iid; return iid;}
+
+/**
+ * A macro to build the static const CID accessor method
+ */
+
+#define NS_DEFINE_STATIC_CID_ACCESSOR(the_cid) \
+ static const nsID& GetCID() {static const nsID cid = the_cid; return cid;}
+
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl b/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl
new file mode 100644
index 00000000..73b3912a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl
@@ -0,0 +1,67 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+
+/**
+ * nsIDebug is an interface between XPCOM Glue and XPCOM. Users should access
+ * the nsIDebug interface through the static class nsDebug.
+ * @see nsDebug.h
+ *
+ * @status UNDER_REVIEW
+ *
+ */
+
+[scriptable, uuid(3bf0c3d7-3bd9-4cf2-a971-33572c503e1e)]
+interface nsIDebug : nsISupports
+{
+ void assertion(in string aStr,
+ in string aExpr,
+ in string aFile,
+ in long aLine);
+
+ void warning(in string aStr,
+ in string aFile,
+ in long aLine);
+
+ void break(in string aFile,
+ in long aLine);
+
+ void abort(in string aFile,
+ in long aLine);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl b/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl
new file mode 100644
index 00000000..c4ed3964
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * nsIErrorService: This is an interim service that allows nsresult codes to be mapped to
+ * string bundles that can be used to look up error messages. String bundle keys can also
+ * be mapped.
+ *
+ * This service will eventually get replaced by extending xpidl to allow errors to be defined.
+ * (http://bugzilla.mozilla.org/show_bug.cgi?id=13423).
+ */
+[scriptable, uuid(e72f94b2-5f85-11d4-9877-00c04fa0cf4a)]
+interface nsIErrorService : nsISupports
+{
+ /**
+ * Registers a string bundle URL for an error module. Error modules are obtained from
+ * nsresult code with NS_ERROR_GET_MODULE.
+ */
+ void registerErrorStringBundle(in short errorModule, in string stringBundleURL);
+
+ /**
+ * Registers a string bundle URL for an error module.
+ */
+ void unregisterErrorStringBundle(in short errorModule);
+
+ /**
+ * Retrieves a string bundle URL for an error module.
+ */
+ string getErrorStringBundle(in short errorModule);
+
+ /**
+ * Registers a key in a string bundle for an nsresult error code. Only the code portion
+ * of the nsresult is used (obtained with NS_ERROR_GET_CODE) in this registration. The
+ * string bundle key is used to look up internationalized messages in the string bundle.
+ */
+ void registerErrorStringBundleKey(in nsresult error, in string stringBundleKey);
+
+ /**
+ * Unregisters a key in a string bundle for an nsresult error code.
+ */
+ void unregisterErrorStringBundleKey(in nsresult error);
+
+ /**
+ * Retrieves a key in a string bundle for an nsresult error code. If no key is registered
+ * for the specified nsresult's code (obtained with NS_ERROR_GET_CODE), then the stringified
+ * version of the nsresult code is returned.
+ */
+ string getErrorStringBundleKey(in nsresult error);
+};
+
+%{C++
+
+// The global nsIErrorService:
+#define NS_ERRORSERVICE_NAME "Error Service"
+#define NS_ERRORSERVICE_CONTRACTID "@mozilla.org/xpcom/error-service;1"
+#define NS_ERRORSERVICE_CID \
+{ /* 744afd5e-5f8c-11d4-9877-00c04fa0cf4a */ \
+ 0x744afd5e, \
+ 0x5f8c, \
+ 0x11d4, \
+ {0x98, 0x77, 0x00, 0xc0, 0x4f, 0xa0, 0xcf, 0x4a} \
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIException.idl b/src/libs/xpcom18a4/xpcom/base/nsIException.idl
new file mode 100644
index 00000000..affbb36e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIException.idl
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Interfaces for representing cross-language exceptions and stack traces.
+ */
+
+
+#include "nsISupports.idl"
+#include "nsIProgrammingLanguage.idl"
+
+// XXX - most "string"s in this file should probably move to Unicode
+// so may as well use AStrings...
+
+
+[scriptable, uuid(91d82105-7c62-4f8b-9779-154277c0ee90)]
+interface nsIStackFrame : nsISupports
+{
+ // see nsIProgrammingLanguage for list of language consts
+ readonly attribute PRUint32 language;
+ readonly attribute string languageName;
+ readonly attribute string filename;
+ readonly attribute string name;
+ // Valid line numbers begin at '1'. '0' indicates unknown.
+ readonly attribute PRInt32 lineNumber;
+ readonly attribute string sourceLine;
+ readonly attribute nsIStackFrame caller;
+
+ string toString();
+};
+
+[scriptable, uuid(F3A8D3B4-C424-4edc-8BF6-8974C983BA78)]
+interface nsIException : nsISupports
+{
+ // A custom message set by the thrower.
+ readonly attribute string message;
+ // The nsresult associated with this exception.
+ readonly attribute nsresult result;
+ // The name of the error code (ie, a string repr of |result|)
+ readonly attribute string name;
+
+ // Filename location. This is the location that caused the
+ // error, which may or may not be a source file location.
+ // For example, standard language errors would generally have
+ // the same location as their top stack entry. File
+ // parsers may put the location of the file they were parsing,
+ // etc.
+
+ // null indicates "no data"
+ readonly attribute string filename;
+ // Valid line numbers begin at '1'. '0' indicates unknown.
+ readonly attribute PRUint32 lineNumber;
+ // Valid column numbers begin at 0.
+ // We don't have an unambiguous indicator for unknown.
+ readonly attribute PRUint32 columnNumber;
+
+ // A stack trace, if available.
+ readonly attribute nsIStackFrame location;
+ // An inner exception that triggered this, if available.
+ readonly attribute nsIException inner;
+
+ // Arbitary data for the implementation.
+ readonly attribute nsISupports data;
+
+ // A generic formatter - make it suitable to print, etc.
+ string toString();
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl b/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl
new file mode 100644
index 00000000..22ebe751
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * ActiveState Tool Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIException.idl"
+
+// An exception provider. These can turn special nsresult codes
+// into nsIExceptions
+
+[scriptable, uuid(0577744c-c1d2-47f2-8bcc-ce7a9e5a88fc)]
+interface nsIExceptionProvider : nsISupports
+{
+ /** Gets an nsIException or returns NULL if not possible. **/
+ nsIException getException(in nsresult result, in nsIException defaultException);
+};
+
+// A ScriptErrorManager for a single thread. These objects
+// are _not_ thread-safe. Use the ScriptErrorService
+// to get a script error manager for your current thread.
+[scriptable, uuid(efc9d00b-231c-4feb-852c-ac017266a415)]
+interface nsIExceptionManager : nsISupports
+{
+ /** Sets (or clears with nsnull) the current error on the this thread. */
+ void setCurrentException( in nsIException error);
+
+ /** Gets the current error for the current thread, or NULL if no error */
+ nsIException getCurrentException();
+
+ /** Gets an exception from a registered exception provider..
+ This has no effect on the "current exception" */
+ nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException);
+};
+
+
+// The Exception Service. Allows you to get an set exceptions in a thread
+// safe manner, or to get an ExceptionManager for your specific thread.
+[scriptable, uuid(35A88F54-F267-4414-92A7-191F6454AB52)]
+interface nsIExceptionService : nsIExceptionManager
+{
+ /** Obtains an exception manager for the current thread. */
+ readonly attribute nsIExceptionManager currentExceptionManager;
+
+ /** Installs an "exception provider" which is capable of
+ translating an nsresult into an exception. This enables
+ error providers to return simple nsresults and only provide
+ rich errors when specifically requested. It also has the
+ advantage of allowing code like the DOM to handle all errors
+ in a single function rather than at each XPCOM entry point.
+ NOTE: This interface must be thread-safe - it will be called
+ on whatever thread needs the error translation performed.*/
+ void registerExceptionProvider( in nsIExceptionProvider provider, in PRUint32 moduleCode );
+ void unregisterExceptionProvider( in nsIExceptionProvider provider, in PRUint32 moduleCode );
+};
+
+
+%{ C++
+#define NS_EXCEPTIONSERVICE_CLASSNAME "Exception Service"
+// {35A88F54-F267-4414-92A7-191F6454AB52}
+#define NS_EXCEPTIONSERVICE_CID \
+{ 0x35a88f54, 0xf267, 0x4414, { 0x92, 0xa7, 0x19, 0x1f, 0x64, 0x54, 0xab, 0x52 } }
+#define NS_EXCEPTIONSERVICE_CONTRACTID "@mozilla.org/exceptionservice;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIID.h b/src/libs/xpcom18a4/xpcom/base/nsIID.h
new file mode 100644
index 00000000..f00d6b23
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIID.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsIID_h
+#define __nsIID_h
+#include "nsID.h"
+#endif /* __nsIID_h */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl b/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl
new file mode 100644
index 00000000..31388643
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl
@@ -0,0 +1,72 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Travis Bogard <travis@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * The nsIInterfaceRequestor interface defines a generic interface for
+ * requesting interfaces that a given object might provide access to.
+ * This is very similar to QueryInterface found in nsISupports.
+ * The main difference is that interfaces returned from GetInterface()
+ * are not required to provide a way back to the object implementing this
+ * interface. The semantics of QI() dictate that given an interface A that
+ * you QI() on to get to interface B, you must be able to QI on B to get back
+ * to A. This interface however allows you to obtain an interface C from A
+ * that may or most likely will not have the ability to get back to A.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(033A1470-8B2A-11d3-AF88-00A024FFC08C)]
+interface nsIInterfaceRequestor : nsISupports
+{
+ /**
+ * Retrieves the specified interface pointer.
+ *
+ * @param uuid The IID of the interface being requested.
+ * @param result [out] The interface pointer to be filled in if
+ * the interface is accessible.
+ * @return NS_OK - interface was successfully returned.
+ * NS_NOINTERFACE - interface not accessible.
+ * NS_ERROR* - method failure.
+ */
+ void getInterface(in nsIIDRef uuid,
+ [iid_is(uuid),retval] out nsQIResult result);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl b/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl
new file mode 100644
index 00000000..6d27fa70
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl
@@ -0,0 +1,54 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick C. Beard <beard@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsICollection;
+
+/**
+ * Controls the leak detector.
+ */
+[scriptable, uuid(a2ec052c-1dd1-11b2-9c92-84be252fe47e)]
+interface nsILeakDetector : nsISupports {
+ void dumpLeaks();
+ void traceObject(in nsISupports object, in PRBool verbose);
+ void traceCollection(in nsICollection objects, in PRBool verbose);
+ void markObject(in nsISupports object, in PRBool marked);
+ readonly attribute nsISupports services;
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl b/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl
new file mode 100644
index 00000000..071aed06
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ *
+ * nsIMemory: interface to allocate and deallocate memory. Also provides
+ * for notifications in low-memory situations.
+ *
+ * A client that wishes to be notified of low memory situations (for
+ * example, because the client maintains a large memory cache that
+ * could be released when memory is tight) should register with the
+ * observer service (see nsIObserverService) using the topic
+ * "memory-pressure". There are three specific types of notications
+ * that can occur. These types will be passed as the |aData|
+ * parameter of the of the "memory-pressure" notification:
+ *
+ * "low-memory"
+ * This will be passed as the extra data when the pressure
+ * observer is being asked to flush for low-memory conditions.
+ *
+ * "heap-minimize"
+ * This will be passed as the extra data when the pressure
+ * observer is being asked to flush because of a heap minimize
+ * call.
+ *
+ * "alloc-failure"
+ * This will be passed as the extra data when the pressure
+ * observer has been asked to flush because a malloc() or
+ * realloc() has failed.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(59e7e77a-38e4-11d4-8cf5-0060b0fc14a3)]
+interface nsIMemory : nsISupports
+{
+ /**
+ * Allocates a block of memory of a particular size. If the memory
+ * cannot be allocated (because of an out-of-memory condition), null
+ * is returned.
+ *
+ * @param size - the size of the block to allocate
+ * @result the block of memory
+ */
+ [noscript, notxpcom] voidPtr alloc(in size_t size);
+
+ /**
+ * Reallocates a block of memory to a new size.
+ *
+ * @param ptr - the block of memory to reallocate
+ * @param size - the new size
+ * @result the reallocated block of memory
+ *
+ * If ptr is null, this function behaves like malloc.
+ * If s is the size of the block to which ptr points, the first
+ * min(s, size) bytes of ptr's block are copied to the new block.
+ * If the allocation succeeds, ptr is freed and a pointer to the
+ * new block returned. If the allocation fails, ptr is not freed
+ * and null is returned. The returned value may be the same as ptr.
+ */
+ [noscript, notxpcom] voidPtr realloc(in voidPtr ptr,
+ in size_t newSize);
+
+ /**
+ * Frees a block of memory. Null is a permissible value, in which case
+ * nothing happens.
+ *
+ * @param ptr - the block of memory to free
+ */
+ [noscript, notxpcom] void free(in voidPtr ptr);
+
+ /**
+ * Attempts to shrink the heap.
+ * @param immediate - if true, heap minimization will occur
+ * immediately if the call was made on the main thread. If
+ * false, the flush will be scheduled to happen when the app is
+ * idle.
+ * @return NS_ERROR_FAILURE if 'immediate' is set an the call
+ * was not on the application's main thread.
+ */
+ void heapMinimize(in boolean immediate);
+
+ /**
+ * This predicate can be used to determine if we're in a low-memory
+ * situation (what constitutes low-memory is platform dependent). This
+ * can be used to trigger the memory pressure observers.
+ */
+ boolean isLowMemory();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl b/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl
new file mode 100644
index 00000000..2fe6fb58
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#ifdef XP_OS2 // OS2 has UNKNOWN problems :)
+#undef UNKNOWN
+#endif
+%}
+
+/**
+ * Enumeration of Programming Languages
+ * @status FROZEN
+ */
+
+[scriptable, uuid(ea604e90-40ba-11d5-90bb-0010a4e73d9a)]
+interface nsIProgrammingLanguage : nsISupports
+{
+ /**
+ * Identifiers for programming languages.
+ */
+ const PRUint32 UNKNOWN = 0;
+ const PRUint32 CPLUSPLUS = 1;
+ const PRUint32 JAVASCRIPT = 2;
+ const PRUint32 PYTHON = 3;
+ const PRUint32 PERL = 4;
+ const PRUint32 JAVA = 5;
+ const PRUint32 ZX81_BASIC = 6; // it could happen :)
+ const PRUint32 JAVASCRIPT2 = 7;
+ // This list can grow indefinitely. Just don't ever change an existing item.
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupports.idl b/src/libs/xpcom18a4/xpcom/base/nsISupports.idl
new file mode 100644
index 00000000..6bf08ac4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISupports.idl
@@ -0,0 +1,80 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The mother of all xpcom interfaces.
+ * @status FROZEN
+ */
+
+/* In order to get both the right typelib and the right header we force
+* the 'real' output from xpidl to be commented out in the generated header
+* and includes a copy of the original nsISupports.h. This is all just to deal
+* with the Mac specific ": public __comobject" thing.
+*/
+
+#include "nsrootidl.idl"
+
+%{C++
+/*
+ * Start commenting out the C++ versions of the below in the output header
+ */
+#if 0
+%}
+
+[scriptable, uuid(00000000-0000-0000-c000-000000000046)]
+interface nsISupports {
+ void QueryInterface(in nsIIDRef uuid,
+ [iid_is(uuid),retval] out nsQIResult result);
+ [noscript, notxpcom] nsrefcnt AddRef();
+ [noscript, notxpcom] nsrefcnt Release();
+};
+
+%{C++
+/*
+ * End commenting out the C++ versions of the above in the output header
+ */
+#endif
+%}
+
+
+%{C++
+#include "nsISupportsBase.h"
+
+#ifndef MOZILLA_STRICT_API
+#include "nsISupportsUtils.h"
+#endif
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h b/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h
new file mode 100644
index 00000000..bea876f5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h
@@ -0,0 +1,119 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsISupportsBase_h__
+#define nsISupportsBase_h__
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsID_h__
+#include "nsID.h"
+#endif
+
+
+/*@{*/
+/**
+ * IID for the nsISupports interface
+ * {00000000-0000-0000-c000-000000000046}
+ *
+ * To maintain binary compatibility with COM's IUnknown, we define the IID
+ * of nsISupports to be the same as that of COM's IUnknown.
+ */
+#define NS_ISUPPORTS_IID \
+ { 0x00000000, 0x0000, 0x0000, \
+ {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
+
+/**
+ * Reference count values
+ *
+ * This is the return type for AddRef() and Release() in nsISupports.
+ * IUnknown of COM returns an unsigned long from equivalent functions.
+ * The following ifdef exists to maintain binary compatibility with
+ * IUnknown.
+ */
+#if defined(XP_WIN) && PR_BYTES_PER_LONG == 4
+typedef unsigned long nsrefcnt;
+#else
+typedef PRUint32 nsrefcnt;
+#endif
+
+/**
+ * Basic component object model interface. Objects which implement
+ * this interface support runtime interface discovery (QueryInterface)
+ * and a reference counted memory model (AddRef/Release). This is
+ * modelled after the win32 IUnknown API.
+ */
+class NS_NO_VTABLE nsISupports {
+public:
+
+ /**
+ * @name Methods
+ */
+
+ //@{
+ /**
+ * A run time mechanism for interface discovery.
+ * @param aIID [in] A requested interface IID
+ * @param aInstancePtr [out] A pointer to an interface pointer to
+ * receive the result.
+ * @return <b>NS_OK</b> if the interface is supported by the associated
+ * instance, <b>NS_NOINTERFACE</b> if it is not.
+ * <b>NS_ERROR_INVALID_POINTER</b> if <i>aInstancePtr</i> is <b>NULL</b>.
+ */
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0;
+ /**
+ * Increases the reference count for this interface.
+ * The associated instance will not be deleted unless
+ * the reference count is returned to zero.
+ *
+ * @return The resulting reference count.
+ */
+ NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
+
+ /**
+ * Decreases the reference count for this interface.
+ * Generally, if the reference count returns to zero,
+ * the associated instance is deleted.
+ *
+ * @return The resulting reference count.
+ */
+ NS_IMETHOD_(nsrefcnt) Release(void) = 0;
+
+ //@}
+};
+/*@}*/
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h b/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h
new file mode 100644
index 00000000..874d859f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h
@@ -0,0 +1,243 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#ifndef nsISupportsObsolete_h__
+#define nsISupportsObsolete_h__
+
+#include "prcmon.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define NS_INIT_REFCNT() NS_INIT_ISUPPORTS()
+
+/**
+ * Macro to free an array of pointers to nsISupports (or classes
+ * derived from it). A convenience wrapper around
+ * NS_FREE_XPCOM_POINTER_ARRAY.
+ *
+ * Note that if you know that none of your nsISupports pointers are
+ * going to be 0, you can gain a bit of speed by calling
+ * NS_FREE_XPCOM_POINTER_ARRAY directly and using NS_RELEASE as your
+ * free function.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ */
+#define NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(size, array) \
+ NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_IF_RELEASE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* use these functions to associate get/set methods with a
+ C++ member variable
+*/
+
+#define NS_METHOD_GETTER(_method, _type, _member) \
+_method(_type* aResult) \
+{\
+ if (!aResult) return NS_ERROR_NULL_POINTER; \
+ *aResult = _member; \
+ return NS_OK; \
+}
+
+#define NS_METHOD_SETTER(_method, _type, _member) \
+_method(_type aResult) \
+{ \
+ _member = aResult; \
+ return NS_OK; \
+}
+
+/*
+ * special for strings to get/set char* strings
+ * using PL_strdup and PR_FREEIF
+ */
+#define NS_METHOD_GETTER_STR(_method,_member) \
+_method(char* *aString) \
+{ \
+ if (!aString) return NS_ERROR_NULL_POINTER; \
+ if (!(*aString = PL_strdup(_member))) \
+ return NS_ERROR_OUT_OF_MEMORY; \
+ return NS_OK; \
+}
+
+#define NS_METHOD_SETTER_STR(_method, _member) \
+_method(const char *aString) \
+{ \
+ if (_member) PR_Free(_member); \
+ if (!aString) \
+ _member = nsnull; \
+ else if (!(_member = PL_strdup(aString))) \
+ return NS_ERROR_OUT_OF_MEMORY; \
+ return NS_OK; \
+}
+
+/* Getter/Setter macros.
+ Usage:
+ NS_IMPL_[CLASS_]GETTER[_<type>](method, [type,] member);
+ NS_IMPL_[CLASS_]SETTER[_<type>](method, [type,] member);
+ NS_IMPL_[CLASS_]GETSET[_<type>]([class, ]postfix, [type,] member);
+
+ where:
+ CLASS_ - implementation is inside a class definition
+ (otherwise the class name is needed)
+ Do NOT use in publicly exported header files, because
+ the implementation may be included many times over.
+ Instead, use the non-CLASS_ version.
+ _<type> - For more complex (STR, IFACE) data types
+ (otherwise the simple data type is needed)
+ method - name of the method, such as GetWidth or SetColor
+ type - simple data type if required
+ member - class member variable such as m_width or mColor
+ class - the class name, such as Window or MyObject
+ postfix - Method part after Get/Set such as "Width" for "GetWidth"
+
+ Example:
+ class Window {
+ public:
+ NS_IMPL_CLASS_GETSET(Width, int, m_width);
+ NS_IMPL_CLASS_GETTER_STR(GetColor, m_color);
+ NS_IMETHOD SetColor(char *color);
+
+ private:
+ int m_width; // read/write
+ char *m_color; // readonly
+ };
+
+ // defined outside of class
+ NS_IMPL_SETTER_STR(Window::GetColor, m_color);
+
+ Questions/Comments to alecf@netscape.com
+*/
+
+
+/*
+ * Getter/Setter implementation within a class definition
+ */
+
+/* simple data types */
+#define NS_IMPL_CLASS_GETTER(_method, _type, _member) \
+NS_IMETHOD NS_METHOD_GETTER(_method, _type, _member)
+
+#define NS_IMPL_CLASS_SETTER(_method, _type, _member) \
+NS_IMETHOD NS_METHOD_SETTER(_method, _type, _member)
+
+#define NS_IMPL_CLASS_GETSET(_postfix, _type, _member) \
+NS_IMPL_CLASS_GETTER(Get##_postfix, _type, _member) \
+NS_IMPL_CLASS_SETTER(Set##_postfix, _type, _member)
+
+/* strings */
+#define NS_IMPL_CLASS_GETTER_STR(_method, _member) \
+NS_IMETHOD NS_METHOD_GETTER_STR(_method, _member)
+
+#define NS_IMPL_CLASS_SETTER_STR(_method, _member) \
+NS_IMETHOD NS_METHOD_SETTER_STR(_method, _member)
+
+#define NS_IMPL_CLASS_GETSET_STR(_postfix, _member) \
+NS_IMPL_CLASS_GETTER_STR(Get##_postfix, _member) \
+NS_IMPL_CLASS_SETTER_STR(Set##_postfix, _member)
+
+/* Getter/Setter implementation outside of a class definition */
+
+/* simple data types */
+#define NS_IMPL_GETTER(_method, _type, _member) \
+NS_IMETHODIMP NS_METHOD_GETTER(_method, _type, _member)
+
+#define NS_IMPL_SETTER(_method, _type, _member) \
+NS_IMETHODIMP NS_METHOD_SETTER(_method, _type, _member)
+
+#define NS_IMPL_GETSET(_class, _postfix, _type, _member) \
+NS_IMPL_GETTER(_class::Get##_postfix, _type, _member) \
+NS_IMPL_SETTER(_class::Set##_postfix, _type, _member)
+
+/* strings */
+#define NS_IMPL_GETTER_STR(_method, _member) \
+NS_IMETHODIMP NS_METHOD_GETTER_STR(_method, _member)
+
+#define NS_IMPL_SETTER_STR(_method, _member) \
+NS_IMETHODIMP NS_METHOD_SETTER_STR(_method, _member)
+
+#define NS_IMPL_GETSET_STR(_class, _postfix, _member) \
+NS_IMPL_GETTER_STR(_class::Get##_postfix, _member) \
+NS_IMPL_SETTER_STR(_class::Set##_postfix, _member)
+
+/**
+ * IID for the nsIsThreadsafe interface
+ * {88210890-47a6-11d2-bec3-00805f8a66dc}
+ *
+ * This interface is *only* used for debugging purposes to determine if
+ * a given component is threadsafe.
+ */
+#define NS_ISTHREADSAFE_IID \
+ { 0x88210890, 0x47a6, 0x11d2, \
+ {0xbe, 0xc3, 0x00, 0x80, 0x5f, 0x8a, 0x66, 0xdc} }
+
+#define NS_LOCK_INSTANCE() \
+ PR_CEnterMonitor((void*)this)
+#define NS_UNLOCK_INSTANCE() \
+ PR_CExitMonitor((void*)this)
+
+/**
+ * This implements query interface with two assumptions: First, the
+ * class in question implements nsISupports and its own interface and
+ * nothing else. Second, the implementation of the class's primary
+ * inheritance chain leads to its own interface.
+ *
+ * @param _class The name of the class implementing the method
+ * @param _classiiddef The name of the #define symbol that defines the IID
+ * for the class (e.g. NS_ISUPPORTS_IID)
+ */
+#if defined(NS_DEBUG)
+#define NS_VERIFY_THREADSAFE_INTERFACE(_iface) \
+ if (NULL != (_iface)) { \
+ nsISupports* tmp; \
+ static NS_DEFINE_IID(kIsThreadsafeIID, NS_ISTHREADSAFE_IID); \
+ NS_PRECONDITION((NS_OK == _iface->QueryInterface(kIsThreadsafeIID, \
+ (void**)&tmp)), \
+ "Interface is not threadsafe"); \
+ }
+#else
+#define NS_VERIFY_THREADSAFE_INTERFACE(_iface)
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl b/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl
new file mode 100644
index 00000000..0351196a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl
@@ -0,0 +1,62 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike Shaver <shaver@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * System information service.
+ *
+ * At present, a thin wrapper around PR_GetSystemInfo.
+ */
+
+[scriptable,uuid(4189b420-1dd2-11b2-bff7-daaf5c1f7b10)]
+interface nsISystemInfo : nsISupports
+{
+ /** The system hostname. */
+ readonly attribute string hostname;
+
+ /** The operating system name. */
+ readonly attribute string OSName;
+
+ /** The operating system version. */
+ readonly attribute string OSVersion;
+
+ /** The processor architecture of the machine. */
+ readonly attribute string architecture;
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl b/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl
new file mode 100644
index 00000000..536861a0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+
+/**
+ * nsITraceRefcnt is an interface between XPCOM Glue and XPCOM. Users should
+ * access the nsITraceRefcnt interface through the static class nsTraceRefcnt.
+ * @see nsTraceRefcnt.h
+ *
+ * @status UNDER_REVIEW
+ */
+
+[uuid(273dc92f-0fe6-4545-96a9-21be77828039)]
+interface nsITraceRefcnt : nsISupports
+{
+ void logAddRef(in voidPtr aPtr,
+ in nsrefcnt aNewRefcnt,
+ in string aTypeName,
+ in unsigned long aInstanceSize);
+
+ void logRelease(in voidPtr aPtr,
+ in nsrefcnt aNewRefcnt,
+ in string aTypeName);
+
+ void logCtor(in voidPtr aPtr,
+ in string aTypeName,
+ in unsigned long aInstanceSize);
+
+ void logDtor(in voidPtr aPtr,
+ in string aTypeName,
+ in unsigned long aInstanceSize);
+
+
+ void logAddCOMPtr(in voidPtr aPtr, in nsISupports aObject);
+
+ void logReleaseCOMPtr(in voidPtr aPtr, in nsISupports aObject);
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl b/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl
new file mode 100644
index 00000000..2806fc8a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl
@@ -0,0 +1,102 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+
+/**
+ * An instance of |nsIWeakReference| is a proxy object that cooperates with
+ * its referent to give clients a non-owning, non-dangling reference. Clients
+ * own the proxy, and should generally manage it with an |nsCOMPtr| (see the
+ * type |nsWeakPtr| for a |typedef| name that stands out) as they would any
+ * other XPCOM object. The |QueryReferent| member function provides a
+ * (hopefully short-lived) owning reference on demand, through which clients
+ * can get useful access to the referent, while it still exists.
+ *
+ * @status FROZEN
+ * @version 1.0
+ * @see nsISupportsWeakReference
+ * @see nsWeakReference
+ * @see nsWeakPtr
+ */
+[scriptable, uuid(9188bc85-f92e-11d2-81ef-0060083a0bcf)]
+interface nsIWeakReference : nsISupports
+ {
+ /**
+ * |QueryReferent| queries the referent, if it exists, and like |QueryInterface|, produces
+ * an owning reference to the desired interface. It is designed to look and act exactly
+ * like (a proxied) |QueryInterface|. Don't hold on to the produced interface permanently;
+ * that would defeat the purpose of using a non-owning |nsIWeakReference| in the first place.
+ */
+ void QueryReferent( in nsIIDRef uuid, [iid_is(uuid), retval] out nsQIResult result );
+ };
+
+
+/**
+ * |nsISupportsWeakReference| is a factory interface which produces appropriate
+ * instances of |nsIWeakReference|. Weak references in this scheme can only be
+ * produced for objects that implement this interface.
+ *
+ * @status FROZEN
+ * @version 1.0
+ * @see nsIWeakReference
+ * @see nsSupportsWeakReference
+ */
+[scriptable, uuid(9188bc86-f92e-11d2-81ef-0060083a0bcf)]
+interface nsISupportsWeakReference : nsISupports
+ {
+ /**
+ * |GetWeakReference| produces an appropriate instance of |nsIWeakReference|.
+ * As with all good XPCOM `getters', you own the resulting interface and should
+ * manage it with an |nsCOMPtr|.
+ *
+ * @see nsIWeakReference
+ * @see nsWeakPtr
+ * @see nsCOMPtr
+ */
+ nsIWeakReference GetWeakReference();
+ };
+
+
+%{C++
+#ifndef MOZILLA_STRICT_API
+#include "nsIWeakReferenceUtils.h"
+#endif
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp
new file mode 100644
index 00000000..a42f77bf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick C. Beard <beard@netscape.com>
+ * Scott Collins <scc@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#if defined(GC_LEAK_DETECTOR)
+
+#include "nsLeakDetector.h"
+#include "nsCOMPtr.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsIGenericFactory.h"
+#include "nsILeakDetector.h"
+#include "nsICollection.h"
+
+#include <stdio.h>
+#include <time.h>
+
+#include "gc.h"
+
+extern "C" {
+extern FILE *GC_stdout, *GC_stderr;
+extern void GC_trace_object(GC_PTR object, int verbose);
+extern void GC_mark_object(GC_PTR object, GC_word mark);
+}
+
+static nsresult nextLeakFile()
+{
+ if (GC_stderr != NULL)
+ fclose(GC_stderr);
+
+ // generate a time stamped report name.
+ time_t timer;
+ time(&timer);
+ tm* now = localtime(&timer);
+
+ char reportName[256];
+ sprintf(reportName, "Leaks%02d%02d%02d",
+ now->tm_hour, now->tm_min, now->tm_sec);
+ GC_stderr = fopen(reportName, "w");
+
+ return NS_OK;
+}
+
+static FILE* openTraceFile()
+{
+ // generate a time stamped report name.
+ time_t timer;
+ time(&timer);
+ tm* now = localtime(&timer);
+
+ char reportName[256];
+ sprintf(reportName, "Trace%02d%02d%02d",
+ now->tm_hour, now->tm_min, now->tm_sec);
+ return fopen(reportName, "w");
+}
+
+class nsLeakDetector : public nsILeakDetector {
+public:
+ nsLeakDetector();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSILEAKDETECTOR
+private:
+ ~nsLeakDetector() {}
+};
+
+NS_IMPL_ISUPPORTS1(nsLeakDetector, nsILeakDetector)
+
+nsLeakDetector::nsLeakDetector() {
+ }
+
+NS_METHOD nsLeakDetector::DumpLeaks()
+{
+ GC_gcollect();
+
+ return nextLeakFile();
+}
+
+NS_METHOD nsLeakDetector::TraceObject(nsISupports* object, PRBool verbose)
+{
+ FILE* trace = openTraceFile();
+ if (trace != NULL) {
+ FILE* old_stderr = GC_stderr;
+ GC_stderr = trace;
+ GC_trace_object(object, (verbose ? 1 : 0));
+ GC_stderr = old_stderr;
+ fclose(trace);
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_METHOD nsLeakDetector::TraceCollection(nsICollection* objects, PRBool verbose)
+{
+ PRUint32 count;
+ if (NS_FAILED(objects->Count(&count)))
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsISupports>* elements = new nsCOMPtr<nsISupports>[count];
+ if (elements == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (PRUint32 i = 0; i < count; ++i)
+ objects->GetElementAt(i, getter_AddRefs(elements[i]));
+
+ nsresult rv = NS_ERROR_FAILURE;
+ FILE* trace = openTraceFile();
+ if (trace != NULL) {
+ FILE* old_stderr = GC_stderr;
+ GC_stderr = trace;
+ GC_trace_object(elements, (verbose ? 1 : 0));
+ GC_stderr = old_stderr;
+ fclose(trace);
+ rv = NS_OK;
+ }
+
+ delete[] elements;
+
+ return rv;
+}
+
+NS_METHOD nsLeakDetector::MarkObject(nsISupports* object, PRBool marked)
+{
+ GC_mark_object(object, (marked ? 1 : 0));
+ return NS_OK;
+}
+
+NS_METHOD nsLeakDetector::GetServices(nsISupports* *result)
+{
+ return NS_GetServiceManager((nsIServiceManager**)result);
+}
+
+#define NS_CLEAKDETECTOR_CID_STR "bb1ba360-1dd1-11b2-b30e-aa2314429f54"
+#define NS_CLEAKDETECTOR_CID {0xbb1ba360, 0x1dd1, 0x11b2, {0xb3, 0x0e, 0xaa, 0x23, 0x14, 0x42, 0x9f, 0x54}}
+#define NS_CLEAKDETECTOR_CONTRACTID "@mozilla.org/xpcom/leakdetector;1"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsLeakDetector)
+
+static NS_DEFINE_CID(kCLeakDetectorCID, NS_CLEAKDETECTOR_CID);
+
+nsresult NS_InitLeakDetector()
+{
+ nsresult rv;
+
+ // open the first leak file.
+ rv = nextLeakFile();
+ if (NS_FAILED(rv))
+ return rv;
+
+ static const nsModuleComponentInfo info = {
+ "Leak Detector", kCLeakDetectorCID, NS_CLEAKDETECTOR_CONTRACTID, nsLeakDetectorConstructor
+ };
+
+ // create a generic factory for the leak detector.
+ nsCOMPtr<nsIGenericFactory> factory;
+ rv = NS_NewGenericFactory(getter_AddRefs(factory), &info);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // register this factory with the component manager.
+ return nsComponentManager::RegisterFactory(info.mCID, info.mDescription, info.mContractID, factory, PR_TRUE);
+}
+
+#ifdef XP_MAC
+#define SHUTDOWN_LEAKS_EARLY
+#undef SHUTDOWN_LEAKS_MEDIUM
+#undef SHUTDOWN_LEAKS_LATE
+#else
+#undef SHUTDOWN_LEAKS_EARLY
+#undef SHUTDOWN_LEAKS_MEDIUM
+#define SHUTDOWN_LEAKS_LATE
+#endif
+
+class LeakDetectorFinalizer
+{
+public:
+ ~LeakDetectorFinalizer();
+};
+
+#ifdef SHUTDOWN_LEAKS_LATE
+// do shutdown leaks when XPCOM library is unloaded
+LeakDetectorFinalizer gLeakDetectorFinalizer;
+#endif
+
+LeakDetectorFinalizer::~LeakDetectorFinalizer()
+{
+ GC_gcollect();
+
+#if 0
+ nextLeakFile();
+ if (GC_stdout != NULL) {
+ fprintf(GC_stdout, "ShutDown Leaks\n");
+ GC_clear_roots();
+ GC_gcollect();
+ }
+#endif
+}
+
+nsresult NS_ShutdownLeakDetector()
+{
+#if defined(SHUTDOWN_LEAKS_MEDIUM)
+ // Make this the first atexit() called so it's before the atexit() crashes
+ // see http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=23552
+ static LeakDetectorFinalizer trick;
+#elif defined(SHUTDOWN_LEAKS_EARLY)
+ // do shutdown leaks now
+ LeakDetectorFinalizer trick;
+#endif
+ return NS_OK;
+}
+
+#endif /* defined(GC_LEAK_DETECTOR) */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h
new file mode 100644
index 00000000..5c560401
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h
@@ -0,0 +1,60 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick C. Beard <beard@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsLeakDetector_h
+#define nsLeakDetector_h
+
+#ifndef nsError_h
+#include "nsError.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+nsresult NS_InitGarbageCollector(void);
+nsresult NS_InitLeakDetector(void);
+nsresult NS_ShutdownLeakDetector(void);
+nsresult NS_ShutdownGarbageCollector(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* nsLeakDetector_h */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp
new file mode 100644
index 00000000..8aa16e58
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp
@@ -0,0 +1,548 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMemoryImpl.h"
+#include "prmem.h"
+#include "nsAlgorithm.h"
+#include "nsIServiceManager.h"
+#include "nsIObserverService.h"
+#include "nsAutoLock.h"
+#include "nsIThread.h"
+#include "nsIEventQueueService.h"
+#include "nsString.h"
+
+#if defined(XP_WIN)
+#include <windows.h>
+#define NS_MEMORY_FLUSHER_THREAD
+#elif defined(XP_MAC)
+#include <MacMemory.h>
+#define NS_MEMORY_FLUSHER_THREAD
+#else
+// Need to implement the nsIMemory::IsLowMemory() predicate
+#undef NS_MEMORY_FLUSHER_THREAD
+#endif
+
+//----------------------------------------------------------------------
+
+#if defined(XDEBUG_waterson)
+#define NS_TEST_MEMORY_FLUSHER
+#endif
+
+/**
+ * A runnable that is used to periodically check the status
+ * of the system, determine if too much memory is in use,
+ * and if so, trigger a "memory flush".
+ */
+class MemoryFlusher : public nsIRunnable
+{
+protected:
+ nsMemoryImpl* mMemoryImpl; // WEAK, it owns us.
+ PRBool mRunning;
+ PRIntervalTime mTimeout;
+ PRLock* mLock;
+ PRCondVar* mCVar;
+
+ MemoryFlusher(nsMemoryImpl* aMemoryImpl);
+
+ enum {
+ kInitialTimeout = 60 /*seconds*/
+ };
+
+private:
+ ~MemoryFlusher();
+
+public:
+ /**
+ * Create a memory flusher.
+ * @param aResult the memory flusher
+ * @param aMemoryImpl the owning nsMemoryImpl object
+ * @return NS_OK if the memory flusher was created successfully
+ */
+ static nsresult
+ Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRUNNABLE
+
+ /**
+ * Stop the memory flusher.
+ */
+ nsresult Stop();
+};
+
+
+MemoryFlusher::MemoryFlusher(nsMemoryImpl* aMemoryImpl)
+ : mMemoryImpl(aMemoryImpl),
+ mRunning(PR_FALSE),
+ mTimeout(PR_SecondsToInterval(kInitialTimeout)),
+ mLock(nsnull),
+ mCVar(nsnull)
+{
+}
+
+MemoryFlusher::~MemoryFlusher()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ if (mCVar)
+ PR_DestroyCondVar(mCVar);
+}
+
+
+nsresult
+MemoryFlusher::Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl)
+{
+ MemoryFlusher* result = new MemoryFlusher(aMemoryImpl);
+ if (! result)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ do {
+ if ((result->mLock = PR_NewLock()) == nsnull)
+ break;
+
+ if ((result->mCVar = PR_NewCondVar(result->mLock)) == nsnull)
+ break;
+
+ NS_ADDREF(*aResult = result);
+ return NS_OK;
+ } while (0);
+
+ // Something bad happened if we get here...
+ delete result;
+ return NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryFlusher, nsIRunnable)
+
+NS_IMETHODIMP
+MemoryFlusher::Run()
+{
+ nsresult rv;
+
+ mRunning = PR_TRUE;
+
+ while (1) {
+ PRStatus status;
+
+ {
+ nsAutoLock l(mLock);
+ if (! mRunning) {
+ rv = NS_OK;
+ break;
+ }
+
+ status = PR_WaitCondVar(mCVar, mTimeout);
+ }
+
+ if (status != PR_SUCCESS) {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ if (! mRunning) {
+ rv = NS_OK;
+ break;
+ }
+
+ PRBool isLowMemory;
+ rv = mMemoryImpl->IsLowMemory(&isLowMemory);
+ if (NS_FAILED(rv))
+ break;
+
+#ifdef NS_TEST_MEMORY_FLUSHER
+ // Fire the flusher *every* time
+ isLowMemory = PR_TRUE;
+#endif
+
+ if (isLowMemory) {
+ mMemoryImpl->FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE);
+ }
+ }
+
+ mRunning = PR_FALSE;
+
+ return rv;
+}
+
+
+nsresult
+MemoryFlusher::Stop()
+{
+ if (mRunning) {
+ nsAutoLock l(mLock);
+ mRunning = PR_FALSE;
+ PR_NotifyCondVar(mCVar);
+ }
+
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------
+
+nsMemoryImpl* gMemory = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryImpl, nsIMemory)
+
+NS_METHOD
+nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
+ if (gMemory && NS_SUCCEEDED(gMemory->QueryInterface(aIID, aInstancePtr)))
+ return NS_OK;
+
+ nsMemoryImpl* mm = new nsMemoryImpl();
+ if (mm == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv;
+
+ do {
+ rv = mm->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ break;
+
+ rv = NS_ERROR_OUT_OF_MEMORY;
+
+ mm->mFlushLock = PR_NewLock();
+ if (! mm->mFlushLock)
+ break;
+
+ rv = NS_OK;
+ } while (0);
+
+ if (NS_FAILED(rv))
+ delete mm;
+
+ return rv;
+}
+
+
+nsMemoryImpl::nsMemoryImpl()
+ : mFlusher(nsnull),
+ mFlushLock(nsnull),
+ mIsFlushing(PR_FALSE)
+{
+}
+
+nsMemoryImpl::~nsMemoryImpl()
+{
+ if (mFlushLock)
+ PR_DestroyLock(mFlushLock);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures
+
+#ifdef DEBUG_xwarren
+#define NS_OUT_OF_MEMORY_TESTER
+#endif
+
+#ifdef NS_OUT_OF_MEMORY_TESTER
+
+// flush memory one in this number of times:
+#define NS_FLUSH_FREQUENCY 100000
+
+// fail allocation one in this number of flushes:
+#define NS_FAIL_FREQUENCY 10
+
+PRUint32 gFlushFreq = 0;
+PRUint32 gFailFreq = 0;
+
+static void*
+mallocator(PRSize size, PRUint32& counter, PRUint32 max)
+{
+ if (counter++ >= max) {
+ counter = 0;
+ NS_ASSERTION(0, "about to fail allocation... watch out");
+ return nsnull;
+ }
+ return PR_Malloc(size);
+}
+
+static void*
+reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max)
+{
+ if (counter++ >= max) {
+ counter = 0;
+ NS_ASSERTION(0, "about to fail reallocation... watch out");
+ return nsnull;
+ }
+ return PR_Realloc(ptr, size);
+}
+
+#define MALLOC1(s) mallocator(s, gFlushFreq, NS_FLUSH_FREQUENCY)
+#define REALLOC1(p, s) reallocator(p, s, gFlushFreq, NS_FLUSH_FREQUENCY)
+
+#else
+
+#define MALLOC1(s) PR_Malloc(s)
+#define REALLOC1(p, s) PR_Realloc(p, s)
+
+#endif // NS_OUT_OF_MEMORY_TESTER
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP_(void *)
+nsMemoryImpl::Alloc(PRSize size)
+{
+ NS_ASSERTION(size, "nsMemoryImpl::Alloc of 0");
+ void* result = MALLOC1(size);
+ if (! result) {
+ // Request an asynchronous flush
+ FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
+ }
+ return result;
+}
+
+NS_IMETHODIMP_(void *)
+nsMemoryImpl::Realloc(void * ptr, PRSize size)
+{
+ void* result = REALLOC1(ptr, size);
+ if (! result) {
+ // Request an asynchronous flush
+ FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
+ }
+ return result;
+}
+
+NS_IMETHODIMP_(void)
+nsMemoryImpl::Free(void * ptr)
+{
+ PR_Free(ptr);
+}
+
+NS_IMETHODIMP
+nsMemoryImpl::HeapMinimize(PRBool aImmediate)
+{
+ return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate);
+}
+
+NS_IMETHODIMP
+nsMemoryImpl::IsLowMemory(PRBool *result)
+{
+#if defined(XP_WIN)
+ MEMORYSTATUS stat;
+ GlobalMemoryStatus(&stat);
+ *result = ((float)stat.dwAvailPageFile / stat.dwTotalPageFile) < 0.1;
+#elif defined(XP_MAC)
+
+ const long kReserveHeapFreeSpace = (256 * 1024);
+ const long kReserveHeapContigSpace = (128 * 1024);
+
+ long totalSpace, contiguousSpace;
+ // this call measures how much memory would be available if the OS
+ // purged. Despite the name, it does not purge (that happens
+ // automatically when heap space is low).
+ ::PurgeSpace(&totalSpace, &contiguousSpace);
+ if (totalSpace < kReserveHeapFreeSpace || contiguousSpace < kReserveHeapContigSpace)
+ {
+ NS_WARNING("Found that heap mem is low");
+ *result = PR_TRUE;
+ return NS_OK;
+ }
+
+ // see how much temp mem is available (since our allocators allocate 1Mb chunks
+ // in temp mem. We don't use TempMaxMem() (to get contig space) here, because it
+ // compacts the application heap, so can be slow.
+ const long kReserveTempFreeSpace = (2 * 1024 * 1024); // 2Mb
+ long totalTempSpace = ::TempFreeMem();
+ if (totalTempSpace < kReserveTempFreeSpace)
+ {
+ NS_WARNING("Found that temp mem is low");
+ *result = PR_TRUE;
+ return NS_OK;
+ }
+
+ *result = PR_FALSE;
+
+#else
+ *result = PR_FALSE;
+#endif
+ return NS_OK;
+}
+
+nsresult
+nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
+{
+ nsresult rv;
+
+ if (aImmediate) {
+ // They've asked us to run the flusher *immediately*. We've
+ // got to be on the UI main thread for us to be able to do
+ // that...are we?
+ PRBool isOnUIThread = PR_FALSE;
+
+ nsCOMPtr<nsIThread> main;
+ rv = nsIThread::GetMainThread(getter_AddRefs(main));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIThread> current;
+ rv = nsIThread::GetCurrent(getter_AddRefs(current));
+ if (NS_SUCCEEDED(rv)) {
+ if (current == main)
+ isOnUIThread = PR_TRUE;
+ }
+ }
+
+ if (! isOnUIThread) {
+ NS_ERROR("can't synchronously flush memory: not on UI thread");
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ {
+ // Are we already flushing?
+ nsAutoLock l(mFlushLock);
+ if (mIsFlushing)
+ return NS_OK;
+
+ // Well, we are now!
+ mIsFlushing = PR_TRUE;
+ }
+
+ // Run the flushers immediately if we can; otherwise, proxy to the
+ // UI thread an run 'em asynchronously.
+ if (aImmediate) {
+ rv = RunFlushers(this, aReason);
+ }
+ else {
+ nsCOMPtr<nsIEventQueueService> eqs = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
+ if (eqs) {
+ nsCOMPtr<nsIEventQueue> eq;
+ rv = eqs->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eq));
+ if (NS_SUCCEEDED(rv)) {
+ PL_InitEvent(&mFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent);
+ mFlushEvent.mReason = aReason;
+
+ rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &mFlushEvent));
+ }
+ }
+ }
+
+ return rv;
+}
+
+nsresult
+nsMemoryImpl::RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason)
+{
+ nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
+ if (os) {
+ os->NotifyObservers(aSelf, "memory-pressure", aReason);
+ }
+
+ {
+ // Done flushing
+ nsAutoLock l(aSelf->mFlushLock);
+ aSelf->mIsFlushing = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+void*
+nsMemoryImpl::HandleFlushEvent(PLEvent* aEvent)
+{
+ nsMemoryImpl* self = NS_STATIC_CAST(nsMemoryImpl*, PL_GetEventOwner(aEvent));
+ FlushEvent* event = NS_REINTERPRET_CAST(FlushEvent*, aEvent);
+
+ RunFlushers(self, event->mReason);
+ return 0;
+}
+
+void
+nsMemoryImpl::DestroyFlushEvent(PLEvent* aEvent)
+{
+ // no-op, since mEvent is a member of nsMemoryImpl
+}
+
+static void
+EnsureGlobalMemoryService()
+{
+ if (gMemory) return;
+ nsresult rv = nsMemoryImpl::Create(nsnull, NS_GET_IID(nsIMemory), (void**)&gMemory);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "nsMemoryImpl::Create failed");
+ NS_ASSERTION(gMemory, "improper xpcom initialization");
+}
+
+nsresult
+nsMemoryImpl::Startup()
+{
+ EnsureGlobalMemoryService();
+ if (! gMemory)
+ return NS_ERROR_FAILURE;
+
+#ifdef NS_MEMORY_FLUSHER_THREAD
+ nsresult rv;
+
+ // Create and start a memory flusher thread
+ rv = MemoryFlusher::Create(&gMemory->mFlusher, gMemory);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = NS_NewThread(getter_AddRefs(gMemory->mFlusherThread),
+ gMemory->mFlusher,
+ 0, /* XXX use default stack size? */
+ PR_JOINABLE_THREAD);
+
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ return NS_OK;
+}
+
+nsresult
+nsMemoryImpl::Shutdown()
+{
+ if (gMemory) {
+#ifdef NS_MEMORY_FLUSHER_THREAD
+ if (gMemory->mFlusher) {
+ // Stop the runnable...
+ gMemory->mFlusher->Stop();
+ NS_RELEASE(gMemory->mFlusher);
+
+ // ...and wait for the thread to exit
+ if (gMemory->mFlusherThread)
+ gMemory->mFlusherThread->Join();
+ }
+#endif
+
+ NS_RELEASE(gMemory);
+ gMemory = nsnull;
+ }
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h
new file mode 100644
index 00000000..c9086d11
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsMemoryImpl_h__
+#define nsMemoryImpl_h__
+
+#include "nsMemory.h"
+#include "nsISupportsArray.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsCOMPtr.h"
+#include "plevent.h"
+
+struct PRLock;
+class MemoryFlusher;
+
+class nsMemoryImpl : public nsIMemory
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMEMORY
+
+ nsMemoryImpl();
+
+ nsresult FlushMemory(const PRUnichar* aReason, PRBool aImmediate);
+
+ // called from xpcom initialization/finalization:
+ static nsresult Startup();
+ static nsresult Shutdown();
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsMemoryImpl();
+
+protected:
+ MemoryFlusher* mFlusher;
+ nsCOMPtr<nsIThread> mFlusherThread;
+
+ PRLock* mFlushLock;
+ PRBool mIsFlushing;
+
+ struct FlushEvent {
+ PLEvent mEvent;
+ const PRUnichar* mReason;
+ };
+
+ FlushEvent mFlushEvent;
+
+ static nsresult RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason);
+
+ static void* PR_CALLBACK HandleFlushEvent(PLEvent* aEvent);
+ static void PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent);
+};
+
+#endif // nsMemoryImpl_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp
new file mode 100644
index 00000000..11fe0fca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp
@@ -0,0 +1,375 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsStackFrameWin.h code, released
+ * December 20, 2000.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsStackFrameUnix.h"
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "nscore.h"
+
+// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
+// if __USE_GNU is defined. I suppose its some kind of standards
+// adherence thing.
+//
+#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU)
+#define __USE_GNU
+#endif
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#endif
+
+
+
+// This thing is exported by libstdc++
+// Yes, this is a gcc only hack
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include <cxxabi.h>
+#include <stdlib.h> // for free()
+#endif // MOZ_DEMANGLE_SYMBOLS
+
+void DemangleSymbol(const char * aSymbol,
+ char * aBuffer,
+ int aBufLen)
+{
+ aBuffer[0] = '\0';
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ /* See demangle.h in the gcc source for the voodoo */
+ char * demangled = abi::__cxa_demangle(aSymbol,0,0,0);
+
+ if (demangled)
+ {
+ strncpy(aBuffer,demangled,aBufLen);
+ free(demangled);
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+}
+
+
+#if defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) // i386 or PPC Linux stackwalking code
+
+#include <setjmp.h>
+//
+
+void DumpStackToFile(FILE* aStream)
+{
+ jmp_buf jb;
+ setjmp(jb);
+
+ // Stack walking code courtesy Kipp's "leaky".
+
+ // Get the frame pointer out of the jmp_buf
+ void **bp = (void**)
+#if defined(__i386)
+ (jb[0].__jmpbuf[JB_BP]);
+#elif defined(PPC)
+ (jb[0].__jmpbuf[JB_GPR1]);
+#endif
+
+ int skip = 2;
+ for ( ; (void**)*bp > bp; bp = (void**)*bp) {
+ void *pc = *(bp+1);
+ if (--skip <= 0) {
+ Dl_info info;
+ int ok = dladdr(pc, &info);
+ if (!ok) {
+ fprintf(aStream, "UNKNOWN %p\n", pc);
+ continue;
+ }
+
+ PRUint32 foff = (char*)pc - (char*)info.dli_fbase;
+
+ const char * symbol = info.dli_sname;
+ int len;
+ if (!symbol || !(len = strlen(symbol))) {
+ fprintf(aStream, "UNKNOWN [%s +0x%08X]\n",
+ info.dli_fname, foff);
+ continue;
+ }
+
+ char demangled[4096] = "\0";
+
+ DemangleSymbol(symbol, demangled, sizeof(demangled));
+
+ if (strlen(demangled)) {
+ symbol = demangled;
+ len = strlen(symbol);
+ }
+
+ PRUint32 off = (char*)pc - (char*)info.dli_saddr;
+ fprintf(aStream, "%s+0x%08X [%s +0x%08X]\n",
+ symbol, off, info.dli_fname, foff);
+ }
+ }
+}
+
+#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))
+
+/*
+ * Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak".
+ */
+
+#include <synch.h>
+#include <ucontext.h>
+#include <sys/frame.h>
+#include <sys/regset.h>
+#include <sys/stack.h>
+
+static int load_address ( void * pc, void * arg, FILE * aStream );
+static int write_address_file ( void * pc );
+static struct bucket * newbucket ( void * pc );
+static struct frame * cs_getmyframeptr ( void );
+static void cs_walk_stack ( void * (*read_func)(char * address),
+ struct frame * fp,
+ int (*operate_func)(void *, void *),
+ void * usrarg, FILE * aStream );
+static void cs_operate ( void (*operate_func)(void *, void *),
+ void * usrarg, FILE * aStream );
+
+#ifndef STACK_BIAS
+#define STACK_BIAS 0
+#endif /*STACK_BIAS*/
+
+#define LOGSIZE 4096
+
+/* type of demangling function */
+typedef int demf_t(const char *, char *, size_t);
+
+static demf_t *demf;
+
+static int initialized = 0;
+
+#if defined(sparc) || defined(__sparc)
+#define FRAME_PTR_REGISTER REG_SP
+#endif
+
+#if defined(i386) || defined(__i386)
+#define FRAME_PTR_REGISTER EBP
+#endif
+
+struct bucket {
+ void * pc;
+ int index;
+ struct bucket * next;
+};
+
+struct mybuf {
+ char * buffer;
+ int chars_left;
+};
+
+
+static void myinit();
+
+#pragma init (myinit)
+
+static void
+myinit()
+{
+
+ if (! initialized) {
+#ifndef __GNUC__
+ void *handle;
+ const char *libdem = "libdemangle.so.1";
+
+ /* load libdemangle if we can and need to (only try this once) */
+ if ((handle = dlopen(libdem, RTLD_LAZY)) != NULL) {
+ demf = (demf_t *)dlsym(handle,
+ "cplus_demangle"); /*lint !e611 */
+ /*
+ * lint override above is to prevent lint from
+ * complaining about "suspicious cast".
+ */
+ }
+#endif /*__GNUC__*/
+ }
+ initialized = 1;
+}
+
+
+static int
+write_address_file(void * pc, FILE* aStream)
+{
+ static struct bucket table[2048];
+ static mutex_t lock;
+ struct bucket * ptr;
+
+ unsigned int val = NS_PTR_TO_INT32(pc);
+
+ ptr = table + ((val >> 2)&2047);
+
+ mutex_lock(&lock);
+ while (ptr->next) {
+ if (ptr->next->pc == pc)
+ break;
+ ptr = ptr->next;
+ }
+
+ if (ptr->next) {
+ mutex_unlock(&lock);
+ return (ptr->next->index);
+ } else {
+ char buffer[4096], dembuff[4096];
+ Dl_info info;
+ const char *func = "??", *lib = "??";
+
+ ptr->next = newbucket(pc);
+ mutex_unlock(&lock);
+
+ if (dladdr(pc, & info)) {
+ if (info.dli_fname)
+ lib = info.dli_fname;
+ if (info.dli_sname)
+ func = info.dli_sname;
+ }
+
+#ifdef __GNUC__
+ DemangleSymbol(func, dembuff, sizeof(dembuff));
+#else
+ if (!demf || demf(func, dembuff, sizeof (dembuff)))
+ dembuff[0] = 0;
+#endif /*__GNUC__*/
+ if (strlen(dembuff)) {
+ func = dembuff;
+ }
+ fprintf(aStream, "%u %s:%s+0x%x\n",
+ ptr->next->index,
+ lib,
+ func,
+ (char *)pc - (char*)info.dli_saddr);
+
+ return (ptr->next->index);
+ }
+}
+
+
+static int
+load_address(void * pc, void * arg, FILE * aStream)
+{
+ struct mybuf * buf = (struct mybuf *) arg;
+
+ char name[80];
+ int len;
+
+ sprintf(name, " %u", write_address_file(pc, aStream));
+
+ len = strlen(name);
+
+ if (len >= buf->chars_left)
+ return (1);
+
+ strcat(buf->buffer, name);
+
+ buf->chars_left -= len;
+
+ return (0);
+}
+
+
+static struct bucket *
+newbucket(void * pc)
+{
+ struct bucket * ptr = (struct bucket *) malloc(sizeof (*ptr));
+ static int index; /* protected by lock in caller */
+
+ ptr->index = index++;
+ ptr->next = NULL;
+ ptr->pc = pc;
+ return (ptr);
+}
+
+
+static struct frame *
+csgetframeptr()
+{
+ ucontext_t u;
+ struct frame *fp;
+
+ (void) getcontext(&u);
+
+ fp = (struct frame *)
+ ((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] +
+ STACK_BIAS);
+
+ /* make sure to return parents frame pointer.... */
+
+ return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS));
+}
+
+
+static void
+cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, FILE *),
+ void *usrarg, FILE * aStream)
+{
+
+ while (fp != 0 && fp->fr_savpc != 0) {
+
+ if (operate_func((void *)fp->fr_savpc, usrarg, aStream) != 0)
+ break;
+ /*
+ * watch out - libthread stacks look funny at the top
+ * so they may not have their STACK_BIAS set
+ */
+
+ fp = (struct frame *)((ulong_t)fp->fr_savfp +
+ (fp->fr_savfp?(ulong_t)STACK_BIAS:0));
+ }
+}
+
+
+static void
+cs_operate(int (*operate_func)(void *, void *, FILE *), void * usrarg, FILE *aStream)
+{
+ cswalkstack(csgetframeptr(), operate_func, usrarg, aStream);
+}
+
+void DumpStackToFile(FILE* aStream)
+{
+ char buffer[LOGSIZE];
+ struct mybuf mybuf;
+
+ if (!initialized)
+ myinit();
+
+ mybuf.chars_left = LOGSIZE - strlen(buffer)-1;
+ mybuf.buffer = buffer;
+ cs_operate(load_address, &mybuf, aStream);
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h
new file mode 100644
index 00000000..1673ae76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsStackFrameWin.h code, released
+ * December 20, 2000.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsStackFrameUnix_h___
+#define nsStackFrameUnix_h___
+
+#include "stdio.h"
+
+void DumpStackToFile(FILE* out);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp
new file mode 100644
index 00000000..7228356b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp
@@ -0,0 +1,351 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsStackFrameWin.h code, released
+ * December 20, 2003.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Judge, 20-December-2000
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nscore.h"
+#include "windows.h"
+#include "imagehlp.h"
+#include "stdio.h"
+#include "nsStackFrameWin.h"
+
+// Define these as static pointers so that we can load the DLL on the
+// fly (and not introduce a link-time dependency on it). Tip o' the
+// hat to Matt Pietrick for this idea. See:
+//
+// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
+//
+
+
+PR_BEGIN_EXTERN_C
+
+SYMSETOPTIONSPROC _SymSetOptions;
+
+SYMINITIALIZEPROC _SymInitialize;
+
+SYMCLEANUPPROC _SymCleanup;
+
+STACKWALKPROC _StackWalk;
+
+SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
+
+SYMGETMODULEBASEPROC _SymGetModuleBase;
+
+SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
+
+SYMLOADMODULE _SymLoadModule;
+
+SYMUNDNAME _SymUnDName;
+
+SYMGETMODULEINFO _SymGetModuleInfo;
+
+ENUMLOADEDMODULES _EnumerateLoadedModules;
+
+SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
+
+PR_END_EXTERN_C
+
+
+
+
+PRBool
+EnsureImageHlpInitialized()
+{
+ static PRBool gInitialized = PR_FALSE;
+
+ if (! gInitialized) {
+ HMODULE module = ::LoadLibrary("IMAGEHLP.DLL");
+ if (!module) return PR_FALSE;
+
+ _SymSetOptions = (SYMSETOPTIONSPROC) ::GetProcAddress(module, "SymSetOptions");
+ if (!_SymSetOptions) return PR_FALSE;
+
+ _SymInitialize = (SYMINITIALIZEPROC) ::GetProcAddress(module, "SymInitialize");
+ if (!_SymInitialize) return PR_FALSE;
+
+ _SymCleanup = (SYMCLEANUPPROC)GetProcAddress(module, "SymCleanup");
+ if (!_SymCleanup) return PR_FALSE;
+
+ _StackWalk = (STACKWALKPROC)GetProcAddress(module, "StackWalk");
+ if (!_StackWalk) return PR_FALSE;
+
+ _SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress(module, "SymFunctionTableAccess");
+ if (!_SymFunctionTableAccess) return PR_FALSE;
+
+ _SymGetModuleBase = (SYMGETMODULEBASEPROC)GetProcAddress(module, "SymGetModuleBase");
+ if (!_SymGetModuleBase) return PR_FALSE;
+
+ _SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr");
+ if (!_SymGetSymFromAddr) return PR_FALSE;
+
+ _SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule");
+ if (!_SymLoadModule) return PR_FALSE;
+
+ _SymUnDName = (SYMUNDNAME)GetProcAddress(module, "SymUnDName");
+ if (!_SymUnDName) return PR_FALSE;
+
+ _SymGetModuleInfo = (SYMGETMODULEINFO)GetProcAddress(module, "SymGetModuleInfo");
+ if (!_SymGetModuleInfo) return PR_FALSE;
+
+ _EnumerateLoadedModules = (ENUMLOADEDMODULES)GetProcAddress(module, "EnumerateLoadedModules");
+ if (!_EnumerateLoadedModules) return PR_FALSE;
+
+ _SymGetLineFromAddr = (SYMGETLINEFROMADDRPROC)GetProcAddress(module, "SymGetLineFromAddr");
+ if (!_SymGetLineFromAddr) return PR_FALSE;
+
+ gInitialized = PR_TRUE;
+ }
+
+ return gInitialized;
+}
+
+/*
+ * Callback used by SymGetModuleInfoEspecial
+ */
+static BOOL CALLBACK callbackEspecial(LPSTR aModuleName, ULONG aModuleBase, ULONG aModuleSize, PVOID aUserContext)
+{
+ BOOL retval = TRUE;
+ DWORD addr = (DWORD)aUserContext;
+
+ /*
+ * You'll want to control this if we are running on an
+ * architecture where the addresses go the other direction.
+ * Not sure this is even a realistic consideration.
+ */
+ const BOOL addressIncreases = TRUE;
+
+ /*
+ * If it falls in side the known range, load the symbols.
+ */
+ if(addressIncreases
+ ? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize))
+ : (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize))
+ )
+ {
+ BOOL loadRes = FALSE;
+ HANDLE process = GetCurrentProcess();
+
+ loadRes = _SymLoadModule(process, NULL, aModuleName, NULL, aModuleBase, aModuleSize);
+ PR_ASSERT(FALSE != loadRes);
+ }
+
+ return retval;
+}
+
+/*
+ * SymGetModuleInfoEspecial
+ *
+ * Attempt to determine the module information.
+ * Bug 112196 says this DLL may not have been loaded at the time
+ * SymInitialize was called, and thus the module information
+ * and symbol information is not available.
+ * This code rectifies that problem.
+ */
+BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo)
+{
+ BOOL retval = FALSE;
+
+ /*
+ * Init the vars if we have em.
+ */
+ aModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE);
+ if (nsnull != aLineInfo) {
+ aLineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINE);
+ }
+
+ /*
+ * Give it a go.
+ * It may already be loaded.
+ */
+ retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
+
+ if (FALSE == retval) {
+ BOOL enumRes = FALSE;
+
+ /*
+ * Not loaded, here's the magic.
+ * Go through all the modules.
+ */
+ enumRes = _EnumerateLoadedModules(aProcess, callbackEspecial, (PVOID)aAddr);
+ if(FALSE != enumRes)
+ {
+ /*
+ * One final go.
+ * If it fails, then well, we have other problems.
+ */
+ retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
+ }
+ }
+
+ /*
+ * If we got module info, we may attempt line info as well.
+ * We will not report failure if this does not work.
+ */
+ if (FALSE != retval && nsnull != aLineInfo && nsnull != _SymGetLineFromAddr) {
+ DWORD displacement = 0;
+ BOOL lineRes = FALSE;
+
+ lineRes = _SymGetLineFromAddr(aProcess, aAddr, &displacement, aLineInfo);
+ }
+
+ return retval;
+}
+
+PRBool
+EnsureSymInitialized()
+{
+ static PRBool gInitialized = PR_FALSE;
+
+ if (! gInitialized) {
+ if (! EnsureImageHlpInitialized())
+ return PR_FALSE;
+ _SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+ gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE);
+ }
+ return gInitialized;
+}
+
+
+/**
+ * Walk the stack, translating PC's found into strings and recording the
+ * chain in aBuffer. For this to work properly, the dll's must be rebased
+ * so that the address in the file agrees with the address in memory.
+ * Otherwise StackWalk will return FALSE when it hits a frame in a dll's
+ * whose in memory address doesn't match it's in-file address.
+ *
+ * Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does
+ * the rebasing and accordingly I've made a tool to use it to rebase the
+ * DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp).
+ */
+
+
+void
+DumpStackToFile(FILE* aStream)
+{
+ HANDLE myProcess = ::GetCurrentProcess();
+ HANDLE myThread = ::GetCurrentThread();
+ BOOL ok;
+
+ ok = EnsureSymInitialized();
+ if (! ok)
+ return;
+
+ // Get the context information for this thread. That way we will
+ // know where our sp, fp, pc, etc. are and can fill in the
+ // STACKFRAME with the initial values.
+ CONTEXT context;
+ context.ContextFlags = CONTEXT_FULL;
+ ok = GetThreadContext(myThread, &context);
+ if (! ok)
+ return;
+
+ // Setup initial stack frame to walk from
+ STACKFRAME frame;
+ memset(&frame, 0, sizeof(frame));
+ frame.AddrPC.Offset = context.Eip;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrStack.Offset = context.Esp;
+ frame.AddrStack.Mode = AddrModeFlat;
+ frame.AddrFrame.Offset = context.Ebp;
+ frame.AddrFrame.Mode = AddrModeFlat;
+
+ // Now walk the stack and map the pc's to symbol names
+ int skip = 2;
+ while (1) {
+ ok = _StackWalk(IMAGE_FILE_MACHINE_I386,
+ myProcess,
+ myThread,
+ &frame,
+ &context,
+ 0, // read process memory routine
+ _SymFunctionTableAccess, // function table access routine
+ _SymGetModuleBase, // module base routine
+ 0); // translate address routine
+
+ if (!ok) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ fprintf(aStream, "### ERROR: WalkStack: %s", lpMsgBuf);
+ fflush(aStream);
+ LocalFree( lpMsgBuf );
+ }
+ if (!ok || frame.AddrPC.Offset == 0)
+ break;
+
+ if (skip-- > 0)
+ continue;
+
+ //
+ // Attempt to load module info before we attempt to reolve the symbol.
+ // This just makes sure we get good info if available.
+ //
+ IMAGEHLP_MODULE modInfo;
+ modInfo.SizeOfStruct = sizeof(modInfo);
+ BOOL modInfoRes = TRUE;
+ modInfoRes = SymGetModuleInfoEspecial(myProcess, frame.AddrPC.Offset, &modInfo, nsnull);
+
+ char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
+ PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf;
+ symbol->SizeOfStruct = sizeof(buf);
+ symbol->MaxNameLength = 512;
+
+ DWORD displacement;
+ ok = _SymGetSymFromAddr(myProcess,
+ frame.AddrPC.Offset,
+ &displacement,
+ symbol);
+
+ if (ok) {
+ fprintf(aStream, "%s+0x%08X\n", symbol->Name, displacement);
+ }
+ else {
+ fprintf(aStream, "0x%08X\n", frame.AddrPC.Offset);
+ }
+ }
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h
new file mode 100644
index 00000000..d9b6585c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsStackFrameWin.h code, released
+ * December 20, 2000.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Judge, 20-December-2000
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsStackFrameWin_h___
+#define nsStackFrameWin_h___
+
+
+#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
+#include "nspr.h"
+#include <windows.h>
+#include <imagehlp.h>
+
+// Define these as static pointers so that we can load the DLL on the
+// fly (and not introduce a link-time dependency on it). Tip o' the
+// hat to Matt Pietrick for this idea. See:
+//
+// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
+//
+PR_BEGIN_EXTERN_C
+
+typedef DWORD (__stdcall *SYMSETOPTIONSPROC)(DWORD);
+extern SYMSETOPTIONSPROC _SymSetOptions;
+
+typedef BOOL (__stdcall *SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
+extern SYMINITIALIZEPROC _SymInitialize;
+
+typedef BOOL (__stdcall *SYMCLEANUPPROC)(HANDLE);
+extern SYMCLEANUPPROC _SymCleanup;
+
+typedef BOOL (__stdcall *STACKWALKPROC)(DWORD,
+ HANDLE,
+ HANDLE,
+ LPSTACKFRAME,
+ LPVOID,
+ PREAD_PROCESS_MEMORY_ROUTINE,
+ PFUNCTION_TABLE_ACCESS_ROUTINE,
+ PGET_MODULE_BASE_ROUTINE,
+ PTRANSLATE_ADDRESS_ROUTINE);
+extern STACKWALKPROC _StackWalk;
+
+typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD);
+extern SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
+
+typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD);
+extern SYMGETMODULEBASEPROC _SymGetModuleBase;
+
+typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL);
+extern SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
+
+typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD);
+extern SYMLOADMODULE _SymLoadModule;
+
+typedef DWORD ( __stdcall *SYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
+extern SYMUNDNAME _SymUnDName;
+
+typedef DWORD ( __stdcall *SYMGETMODULEINFO)( HANDLE, DWORD, PIMAGEHLP_MODULE);
+extern SYMGETMODULEINFO _SymGetModuleInfo;
+
+typedef BOOL ( __stdcall *ENUMLOADEDMODULES)( HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
+extern ENUMLOADEDMODULES _EnumerateLoadedModules;
+
+typedef BOOL (__stdcall *SYMGETLINEFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE);
+extern SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
+
+PRBool EnsureSymInitialized();
+
+PRBool EnsureImageHlpInitialized();
+
+/*
+ * SymGetModuleInfoEspecial
+ *
+ * Attempt to determine the module information.
+ * Bug 112196 says this DLL may not have been loaded at the time
+ * SymInitialize was called, and thus the module information
+ * and symbol information is not available.
+ * This code rectifies that problem.
+ * Line information is optional.
+ */
+BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo);
+
+
+void DumpStackToFile(FILE* out);
+
+PR_END_EXTERN_C
+
+#endif //WIN32
+
+#endif //nsStackFrameWin_h___
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp
new file mode 100644
index 00000000..f74e84df
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp
@@ -0,0 +1,1444 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTraceRefcntImpl.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsVoidArray.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "plstr.h"
+#include <stdlib.h>
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include <math.h>
+
+#if defined(_WIN32)
+#include <windows.h>
+#elif defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))
+#include <setjmp.h>
+
+//
+// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
+// if __USE_GNU is defined. I suppose its some kind of standards
+// adherence thing.
+//
+#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU)
+#define __USE_GNU
+#endif
+
+#include <dlfcn.h>
+#endif
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#endif
+
+#if defined(XP_MAC) && !TARGET_CARBON
+#include "macstdlibextras.h"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM void
+NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
+ double *meanResult, double *stdDevResult)
+{
+ double mean = 0.0, var = 0.0, stdDev = 0.0;
+ if (n > 0.0 && sumOfValues >= 0) {
+ mean = sumOfValues / n;
+ double temp = (n * sumOfSquaredValues) - (sumOfValues * sumOfValues);
+ if (temp < 0.0 || n <= 1)
+ var = 0.0;
+ else
+ var = temp / (n * (n - 1));
+ // for some reason, Windows says sqrt(0.0) is "-1.#J" (?!) so do this:
+ stdDev = var != 0.0 ? sqrt(var) : 0.0;
+ }
+ *meanResult = mean;
+ *stdDevResult = stdDev;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+#include "plhash.h"
+#include "prmem.h"
+
+#include "prlock.h"
+
+static PRLock* gTraceLock;
+
+#define LOCK_TRACELOG() PR_Lock(gTraceLock)
+#define UNLOCK_TRACELOG() PR_Unlock(gTraceLock)
+
+static PLHashTable* gBloatView;
+static PLHashTable* gTypesToLog;
+static PLHashTable* gObjectsToLog;
+static PLHashTable* gSerialNumbers;
+static PRInt32 gNextSerialNumber;
+
+static PRBool gLogging;
+static PRBool gLogToLeaky;
+static PRBool gLogLeaksOnly;
+
+static void (*leakyLogAddRef)(void* p, int oldrc, int newrc);
+static void (*leakyLogRelease)(void* p, int oldrc, int newrc);
+
+static PRBool gInitialized = PR_FALSE;
+static FILE *gBloatLog = nsnull;
+static FILE *gRefcntsLog = nsnull;
+static FILE *gAllocLog = nsnull;
+static FILE *gLeakyLog = nsnull;
+static FILE *gCOMPtrLog = nsnull;
+static PRBool gActivityIsLegal = PR_FALSE;
+
+struct serialNumberRecord {
+ PRInt32 serialNumber;
+ PRInt32 refCount;
+ PRInt32 COMPtrCount;
+};
+
+struct nsTraceRefcntStats {
+ nsrefcnt mAddRefs;
+ nsrefcnt mReleases;
+ nsrefcnt mCreates;
+ nsrefcnt mDestroys;
+ double mRefsOutstandingTotal;
+ double mRefsOutstandingSquared;
+ double mObjsOutstandingTotal;
+ double mObjsOutstandingSquared;
+};
+
+#ifdef DEBUG_dbaron_off
+ // I hope to turn this on for everybody once we hit it a little less.
+#define ASSERT_ACTIVITY_IS_LEGAL \
+ NS_WARN_IF_FALSE(gActivityIsLegal, \
+ "XPCOM objects created/destroyed from static ctor/dtor")
+#else
+#define ASSERT_ACTIVITY_IS_LEGAL
+#endif
+
+
+// These functions are copied from nsprpub/lib/ds/plhash.c, with changes
+// to the functions not called Default* to free the serialNumberRecord or
+// the BloatEntry.
+
+static void * PR_CALLBACK
+DefaultAllocTable(void *pool, PRSize size)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ return PR_MALLOC(size);
+}
+
+static void PR_CALLBACK
+DefaultFreeTable(void *pool, void *item)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ PR_Free(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+DefaultAllocEntry(void *pool, const void *key)
+{
+#if defined(XP_MAC)
+#pragma unused (pool,key)
+#endif
+
+ return PR_NEW(PLHashEntry);
+}
+
+static void PR_CALLBACK
+SerialNumberFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY) {
+ PR_Free(NS_REINTERPRET_CAST(serialNumberRecord*,he->value));
+ PR_Free(he);
+ }
+}
+
+static void PR_CALLBACK
+TypesToLogFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY) {
+ nsCRT::free(NS_CONST_CAST(char*,
+ NS_REINTERPRET_CAST(const char*, he->key)));
+ PR_Free(he);
+ }
+}
+
+static const PLHashAllocOps serialNumberHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, SerialNumberFreeEntry
+};
+
+static const PLHashAllocOps typesToLogHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, TypesToLogFreeEntry
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BloatEntry {
+public:
+ BloatEntry(const char* className, PRUint32 classSize)
+ : mClassSize(classSize) {
+ mClassName = PL_strdup(className);
+ Clear(&mNewStats);
+ Clear(&mAllStats);
+ mTotalLeaked = 0;
+ }
+
+ ~BloatEntry() {
+ PL_strfree(mClassName);
+ }
+
+ PRUint32 GetClassSize() { return (PRUint32)mClassSize; }
+ const char* GetClassName() { return mClassName; }
+
+ static void Clear(nsTraceRefcntStats* stats) {
+ stats->mAddRefs = 0;
+ stats->mReleases = 0;
+ stats->mCreates = 0;
+ stats->mDestroys = 0;
+ stats->mRefsOutstandingTotal = 0;
+ stats->mRefsOutstandingSquared = 0;
+ stats->mObjsOutstandingTotal = 0;
+ stats->mObjsOutstandingSquared = 0;
+ }
+
+ void Accumulate() {
+ mAllStats.mAddRefs += mNewStats.mAddRefs;
+ mAllStats.mReleases += mNewStats.mReleases;
+ mAllStats.mCreates += mNewStats.mCreates;
+ mAllStats.mDestroys += mNewStats.mDestroys;
+ mAllStats.mRefsOutstandingTotal += mNewStats.mRefsOutstandingTotal;
+ mAllStats.mRefsOutstandingSquared += mNewStats.mRefsOutstandingSquared;
+ mAllStats.mObjsOutstandingTotal += mNewStats.mObjsOutstandingTotal;
+ mAllStats.mObjsOutstandingSquared += mNewStats.mObjsOutstandingSquared;
+ Clear(&mNewStats);
+ }
+
+ void AddRef(nsrefcnt refcnt) {
+ mNewStats.mAddRefs++;
+ if (refcnt == 1) {
+ Ctor();
+ }
+ AccountRefs();
+ }
+
+ void Release(nsrefcnt refcnt) {
+ mNewStats.mReleases++;
+ if (refcnt == 0) {
+ Dtor();
+ }
+ AccountRefs();
+ }
+
+ void Ctor() {
+ mNewStats.mCreates++;
+ AccountObjs();
+ }
+
+ void Dtor() {
+ mNewStats.mDestroys++;
+ AccountObjs();
+ }
+
+ void AccountRefs() {
+ PRInt32 cnt = (mNewStats.mAddRefs - mNewStats.mReleases);
+ mNewStats.mRefsOutstandingTotal += cnt;
+ mNewStats.mRefsOutstandingSquared += cnt * cnt;
+ }
+
+ void AccountObjs() {
+ PRInt32 cnt = (mNewStats.mCreates - mNewStats.mDestroys);
+ mNewStats.mObjsOutstandingTotal += cnt;
+ mNewStats.mObjsOutstandingSquared += cnt * cnt;
+ }
+
+ static PRIntn PR_CALLBACK DumpEntry(PLHashEntry *he, PRIntn i, void *arg) {
+ BloatEntry* entry = (BloatEntry*)he->value;
+ if (entry) {
+ entry->Accumulate();
+ NS_STATIC_CAST(nsVoidArray*, arg)->AppendElement(entry);
+ }
+ return HT_ENUMERATE_NEXT;
+ }
+
+ static PRIntn PR_CALLBACK TotalEntries(PLHashEntry *he, PRIntn i, void *arg) {
+ BloatEntry* entry = (BloatEntry*)he->value;
+ if (entry && nsCRT::strcmp(entry->mClassName, "TOTAL") != 0) {
+ entry->Total((BloatEntry*)arg);
+ }
+ return HT_ENUMERATE_NEXT;
+ }
+
+ void Total(BloatEntry* total) {
+ total->mAllStats.mAddRefs += mNewStats.mAddRefs + mAllStats.mAddRefs;
+ total->mAllStats.mReleases += mNewStats.mReleases + mAllStats.mReleases;
+ total->mAllStats.mCreates += mNewStats.mCreates + mAllStats.mCreates;
+ total->mAllStats.mDestroys += mNewStats.mDestroys + mAllStats.mDestroys;
+ total->mAllStats.mRefsOutstandingTotal += mNewStats.mRefsOutstandingTotal + mAllStats.mRefsOutstandingTotal;
+ total->mAllStats.mRefsOutstandingSquared += mNewStats.mRefsOutstandingSquared + mAllStats.mRefsOutstandingSquared;
+ total->mAllStats.mObjsOutstandingTotal += mNewStats.mObjsOutstandingTotal + mAllStats.mObjsOutstandingTotal;
+ total->mAllStats.mObjsOutstandingSquared += mNewStats.mObjsOutstandingSquared + mAllStats.mObjsOutstandingSquared;
+ PRInt32 count = (mNewStats.mCreates + mAllStats.mCreates);
+ total->mClassSize += mClassSize * count; // adjust for average in DumpTotal
+ total->mTotalLeaked += (PRInt32)(mClassSize *
+ ((mNewStats.mCreates + mAllStats.mCreates)
+ -(mNewStats.mDestroys + mAllStats.mDestroys)));
+ }
+
+ nsresult DumpTotal(PRUint32 nClasses, FILE* out) {
+ mClassSize /= mAllStats.mCreates;
+ return Dump(-1, out, nsTraceRefcntImpl::ALL_STATS);
+ }
+
+ static PRBool HaveLeaks(nsTraceRefcntStats* stats) {
+ return ((stats->mAddRefs != stats->mReleases) ||
+ (stats->mCreates != stats->mDestroys));
+ }
+
+ static nsresult PrintDumpHeader(FILE* out, const char* msg) {
+ fprintf(out, "\n== BloatView: %s\n\n", msg);
+ fprintf(out,
+ " |<----------------Class--------------->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|\n");
+ fprintf(out,
+ " Per-Inst Leaked Total Rem Mean StdDev Total Rem Mean StdDev\n");
+ return NS_OK;
+ }
+
+ nsresult Dump(PRIntn i, FILE* out, nsTraceRefcntImpl::StatisticsType type) {
+ nsTraceRefcntStats* stats = (type == nsTraceRefcntImpl::NEW_STATS) ? &mNewStats : &mAllStats;
+ if (gLogLeaksOnly && !HaveLeaks(stats)) {
+ return NS_OK;
+ }
+
+ double meanRefs, stddevRefs;
+ NS_MeanAndStdDev(stats->mAddRefs + stats->mReleases,
+ stats->mRefsOutstandingTotal,
+ stats->mRefsOutstandingSquared,
+ &meanRefs, &stddevRefs);
+
+ double meanObjs, stddevObjs;
+ NS_MeanAndStdDev(stats->mCreates + stats->mDestroys,
+ stats->mObjsOutstandingTotal,
+ stats->mObjsOutstandingSquared,
+ &meanObjs, &stddevObjs);
+
+ if ((stats->mAddRefs - stats->mReleases) != 0 ||
+ stats->mAddRefs != 0 ||
+ meanRefs != 0 ||
+ stddevRefs != 0 ||
+ (stats->mCreates - stats->mDestroys) != 0 ||
+ stats->mCreates != 0 ||
+ meanObjs != 0 ||
+ stddevObjs != 0) {
+ fprintf(out, "%4d %-40.40s %8d %8d %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f)\n",
+ i+1, mClassName,
+ (PRInt32)mClassSize,
+ (nsCRT::strcmp(mClassName, "TOTAL"))
+ ?(PRInt32)((stats->mCreates - stats->mDestroys) * mClassSize)
+ :mTotalLeaked,
+ stats->mCreates,
+ (stats->mCreates - stats->mDestroys),
+ meanObjs,
+ stddevObjs,
+ stats->mAddRefs,
+ (stats->mAddRefs - stats->mReleases),
+ meanRefs,
+ stddevRefs);
+ }
+ return NS_OK;
+ }
+
+protected:
+ char* mClassName;
+ double mClassSize; // this is stored as a double because of the way we compute the avg class size for total bloat
+ PRInt32 mTotalLeaked; // used only for TOTAL entry
+ nsTraceRefcntStats mNewStats;
+ nsTraceRefcntStats mAllStats;
+};
+
+static void PR_CALLBACK
+BloatViewFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY) {
+ BloatEntry* entry = NS_REINTERPRET_CAST(BloatEntry*,he->value);
+ delete entry;
+ PR_Free(he);
+ }
+}
+
+const static PLHashAllocOps bloatViewHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, BloatViewFreeEntry
+};
+
+static void
+RecreateBloatView()
+{
+ gBloatView = PL_NewHashTable(256,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues,
+ &bloatViewHashAllocOps, NULL);
+}
+
+static BloatEntry*
+GetBloatEntry(const char* aTypeName, PRUint32 aInstanceSize)
+{
+ if (!gBloatView) {
+ RecreateBloatView();
+ }
+ BloatEntry* entry = NULL;
+ if (gBloatView) {
+ entry = (BloatEntry*)PL_HashTableLookup(gBloatView, aTypeName);
+ if (entry == NULL && aInstanceSize > 0) {
+
+ entry = new BloatEntry(aTypeName, aInstanceSize);
+ PLHashEntry* e = PL_HashTableAdd(gBloatView, aTypeName, entry);
+ if (e == NULL) {
+ delete entry;
+ entry = NULL;
+ }
+ } else {
+ NS_ASSERTION(aInstanceSize == 0 ||
+ entry->GetClassSize() == aInstanceSize,
+ "bad size recorded");
+ }
+ }
+ return entry;
+}
+
+static PRIntn PR_CALLBACK DumpSerialNumbers(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure)
+{
+ serialNumberRecord* record = NS_REINTERPRET_CAST(serialNumberRecord *,aHashEntry->value);
+#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
+ fprintf((FILE*) aClosure, "%d (%d references; %d from COMPtrs)\n",
+ record->serialNumber,
+ record->refCount,
+ record->COMPtrCount);
+#else
+ fprintf((FILE*) aClosure, "%d (%d references)\n",
+ record->serialNumber,
+ record->refCount);
+#endif
+ return HT_ENUMERATE_NEXT;
+}
+
+
+#endif /* NS_BUILD_REFCNT_LOGGING */
+
+nsresult
+nsTraceRefcntImpl::DumpStatistics(StatisticsType type, FILE* out)
+{
+ nsresult rv = NS_OK;
+#ifdef NS_BUILD_REFCNT_LOGGING
+ if (gBloatLog == nsnull || gBloatView == nsnull) {
+ return NS_ERROR_FAILURE;
+ }
+ if (out == nsnull) {
+ out = gBloatLog;
+ }
+
+ LOCK_TRACELOG();
+
+ PRBool wasLogging = gLogging;
+ gLogging = PR_FALSE; // turn off logging for this method
+
+ const char* msg;
+ if (type == NEW_STATS) {
+ if (gLogLeaksOnly)
+ msg = "NEW (incremental) LEAK STATISTICS";
+ else
+ msg = "NEW (incremental) LEAK AND BLOAT STATISTICS";
+ }
+ else {
+ if (gLogLeaksOnly)
+ msg = "ALL (cumulative) LEAK STATISTICS";
+ else
+ msg = "ALL (cumulative) LEAK AND BLOAT STATISTICS";
+ }
+ rv = BloatEntry::PrintDumpHeader(out, msg);
+ if (NS_FAILED(rv)) goto done;
+
+ {
+ BloatEntry total("TOTAL", 0);
+ PL_HashTableEnumerateEntries(gBloatView, BloatEntry::TotalEntries, &total);
+ total.DumpTotal(gBloatView->nentries, out);
+
+ nsVoidArray entries;
+ PL_HashTableEnumerateEntries(gBloatView, BloatEntry::DumpEntry, &entries);
+
+ fprintf(stdout, "nsTraceRefcntImpl::DumpStatistics: %d entries\n",
+ entries.Count());
+
+ // Sort the entries alphabetically by classname.
+ PRInt32 i, j;
+ for (i = entries.Count() - 1; i >= 1; --i) {
+ for (j = i - 1; j >= 0; --j) {
+ BloatEntry* left = NS_STATIC_CAST(BloatEntry*, entries[i]);
+ BloatEntry* right = NS_STATIC_CAST(BloatEntry*, entries[j]);
+
+ if (PL_strcmp(left->GetClassName(), right->GetClassName()) < 0) {
+ entries.ReplaceElementAt(right, i);
+ entries.ReplaceElementAt(left, j);
+ }
+ }
+ }
+
+ // Enumerate from back-to-front, so things come out in alpha order
+ for (i = 0; i < entries.Count(); ++i) {
+ BloatEntry* entry = NS_STATIC_CAST(BloatEntry*, entries[i]);
+ entry->Dump(i, out, type);
+ }
+ }
+
+ if (gSerialNumbers) {
+ fprintf(out, "\n\nSerial Numbers of Leaked Objects:\n");
+ PL_HashTableEnumerateEntries(gSerialNumbers, DumpSerialNumbers, out);
+ }
+
+done:
+ gLogging = wasLogging;
+ UNLOCK_TRACELOG();
+#endif
+ return rv;
+}
+
+void
+nsTraceRefcntImpl::ResetStatistics()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ LOCK_TRACELOG();
+ if (gBloatView) {
+ PL_HashTableDestroy(gBloatView);
+ gBloatView = nsnull;
+ }
+ UNLOCK_TRACELOG();
+#endif
+}
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+static PRBool LogThisType(const char* aTypeName)
+{
+ void* he = PL_HashTableLookup(gTypesToLog, aTypeName);
+ return nsnull != he;
+}
+
+static PRInt32 GetSerialNumber(void* aPtr, PRBool aCreate)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr);
+ if (hep && *hep) {
+ return PRInt32((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->serialNumber);
+ }
+ else if (aCreate) {
+ serialNumberRecord *record = PR_NEW(serialNumberRecord);
+ record->serialNumber = ++gNextSerialNumber;
+ record->refCount = 0;
+ record->COMPtrCount = 0;
+ PL_HashTableRawAdd(gSerialNumbers, hep, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr, NS_REINTERPRET_CAST(void*,record));
+ return gNextSerialNumber;
+ }
+ else {
+ return 0;
+ }
+}
+
+static PRInt32* GetRefCount(void* aPtr)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr);
+ if (hep && *hep) {
+ return &((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->refCount);
+ } else {
+ return nsnull;
+ }
+}
+
+static PRInt32* GetCOMPtrCount(void* aPtr)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr);
+ if (hep && *hep) {
+ return &((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->COMPtrCount);
+ } else {
+ return nsnull;
+ }
+}
+
+static void RecycleSerialNumberPtr(void* aPtr)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PL_HashTableRemove(gSerialNumbers, aPtr);
+}
+
+static PRBool LogThisObj(PRInt32 aSerialNumber)
+{
+ return nsnull != PL_HashTableLookup(gObjectsToLog, (const void*)(uintptr_t)(aSerialNumber));
+}
+
+static PRBool InitLog(const char* envVar, const char* msg, FILE* *result)
+{
+ const char* value = getenv(envVar);
+ if (value) {
+ if (nsCRT::strcmp(value, "1") == 0) {
+ *result = stdout;
+ fprintf(stdout, "### %s defined -- logging %s to stdout\n",
+ envVar, msg);
+ return PR_TRUE;
+ }
+ else if (nsCRT::strcmp(value, "2") == 0) {
+ *result = stderr;
+ fprintf(stdout, "### %s defined -- logging %s to stderr\n",
+ envVar, msg);
+ return PR_TRUE;
+ }
+ else {
+ FILE *stream = ::fopen(value, "w");
+ if (stream != NULL) {
+ *result = stream;
+ fprintf(stdout, "### %s defined -- logging %s to %s\n",
+ envVar, msg, value);
+ return PR_TRUE;
+ }
+ else {
+ fprintf(stdout, "### %s defined -- unable to log %s to %s\n",
+ envVar, msg, value);
+ return PR_FALSE;
+ }
+ }
+ }
+ return PR_FALSE;
+}
+
+
+static PLHashNumber PR_CALLBACK HashNumber(const void* aKey)
+{
+ return PLHashNumber(NS_PTR_TO_INT32(aKey));
+}
+
+static void InitTraceLog(void)
+{
+ if (gInitialized) return;
+ gInitialized = PR_TRUE;
+
+#if defined(XP_MAC) && !TARGET_CARBON
+ // this can get called before Toolbox has been initialized.
+ InitializeMacToolbox();
+#endif
+
+ PRBool defined;
+ defined = InitLog("XPCOM_MEM_BLOAT_LOG", "bloat/leaks", &gBloatLog);
+ if (!defined)
+ gLogLeaksOnly = InitLog("XPCOM_MEM_LEAK_LOG", "leaks", &gBloatLog);
+ if (defined || gLogLeaksOnly) {
+ RecreateBloatView();
+ if (!gBloatView) {
+ NS_WARNING("out of memory");
+ gBloatLog = nsnull;
+ gLogLeaksOnly = PR_FALSE;
+ }
+ }
+
+ (void)InitLog("XPCOM_MEM_REFCNT_LOG", "refcounts", &gRefcntsLog);
+
+ (void)InitLog("XPCOM_MEM_ALLOC_LOG", "new/delete", &gAllocLog);
+
+ defined = InitLog("XPCOM_MEM_LEAKY_LOG", "for leaky", &gLeakyLog);
+ if (defined) {
+ gLogToLeaky = PR_TRUE;
+ void* p = nsnull;
+ void* q = nsnull;
+#ifdef HAVE_LIBDL
+ p = dlsym(0, "__log_addref");
+ q = dlsym(0, "__log_release");
+#endif
+ if (p && q) {
+ leakyLogAddRef = (void (*)(void*,int,int)) p;
+ leakyLogRelease = (void (*)(void*,int,int)) q;
+ }
+ else {
+ gLogToLeaky = PR_FALSE;
+ fprintf(stdout, "### ERROR: XPCOM_MEM_LEAKY_LOG defined, but can't locate __log_addref and __log_release symbols\n");
+ fflush(stdout);
+ }
+ }
+
+ const char* classes = getenv("XPCOM_MEM_LOG_CLASSES");
+
+#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
+ if (classes) {
+ (void)InitLog("XPCOM_MEM_COMPTR_LOG", "nsCOMPtr", &gCOMPtrLog);
+ } else {
+ if (getenv("XPCOM_MEM_COMPTR_LOG")) {
+ fprintf(stdout, "### XPCOM_MEM_COMPTR_LOG defined -- but XPCOM_MEM_LOG_CLASSES is not defined\n");
+ }
+ }
+#else
+ const char* comptr_log = getenv("XPCOM_MEM_COMPTR_LOG");
+ if (comptr_log) {
+ fprintf(stdout, "### XPCOM_MEM_COMPTR_LOG defined -- but it will not work without dynamic_cast\n");
+ }
+#endif
+
+ if (classes) {
+ // if XPCOM_MEM_LOG_CLASSES was set to some value, the value is interpreted
+ // as a list of class names to track
+ gTypesToLog = PL_NewHashTable(256,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues,
+ &typesToLogHashAllocOps, NULL);
+ if (!gTypesToLog) {
+ NS_WARNING("out of memory");
+ fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- unable to log specific classes\n");
+ }
+ else {
+ fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- only logging these classes: ");
+ const char* cp = classes;
+ for (;;) {
+ char* cm = (char*) strchr(cp, ',');
+ if (cm) {
+ *cm = '\0';
+ }
+ PL_HashTableAdd(gTypesToLog, nsCRT::strdup(cp), (void*)1);
+ fprintf(stdout, "%s ", cp);
+ if (!cm) break;
+ *cm = ',';
+ cp = cm + 1;
+ }
+ fprintf(stdout, "\n");
+ }
+
+ gSerialNumbers = PL_NewHashTable(256,
+ HashNumber,
+ PL_CompareValues,
+ PL_CompareValues,
+ &serialNumberHashAllocOps, NULL);
+
+
+ }
+
+ const char* objects = getenv("XPCOM_MEM_LOG_OBJECTS");
+ if (objects) {
+ gObjectsToLog = PL_NewHashTable(256,
+ HashNumber,
+ PL_CompareValues,
+ PL_CompareValues,
+ NULL, NULL);
+
+ if (!gObjectsToLog) {
+ NS_WARNING("out of memory");
+ fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- unable to log specific objects\n");
+ }
+ else if (! (gRefcntsLog || gAllocLog || gCOMPtrLog)) {
+ fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- but none of XPCOM_MEM_(REFCNT|ALLOC|COMPTR)_LOG is defined\n");
+ }
+ else {
+ fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- only logging these objects: ");
+ const char* cp = objects;
+ for (;;) {
+ char* cm = (char*) strchr(cp, ',');
+ if (cm) {
+ *cm = '\0';
+ }
+ PRInt32 top = 0;
+ PRInt32 bottom = 0;
+ while (*cp) {
+ if (*cp == '-') {
+ bottom = top;
+ top = 0;
+ ++cp;
+ }
+ top *= 10;
+ top += *cp - '0';
+ ++cp;
+ }
+ if (!bottom) {
+ bottom = top;
+ }
+ for(PRInt32 serialno = bottom; serialno <= top; serialno++) {
+ PL_HashTableAdd(gObjectsToLog, (const void*)serialno, (void*)1);
+ fprintf(stdout, "%d ", serialno);
+ }
+ if (!cm) break;
+ *cm = ',';
+ cp = cm + 1;
+ }
+ fprintf(stdout, "\n");
+ }
+ }
+
+
+ if (gBloatLog || gRefcntsLog || gAllocLog || gLeakyLog || gCOMPtrLog) {
+ gLogging = PR_TRUE;
+ }
+
+ gTraceLock = PR_NewLock();
+}
+
+#endif
+
+#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
+#include "nsStackFrameWin.h"
+void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ DumpStackToFile(aStream);
+}
+
+// WIN32 x86 stack walking code
+// i386 or PPC Linux stackwalking code or Solaris
+#elif (defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))) || (defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)))
+#include "nsStackFrameUnix.h"
+void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ DumpStackToFile(aStream);
+}
+
+#elif defined(XP_MAC)
+
+/**
+ * Stack walking code for the Mac OS.
+ */
+
+#include "gc_fragments.h"
+
+#include <typeinfo>
+
+extern "C" {
+void MWUnmangle(const char *mangled_name, char *unmangled_name, size_t buffersize);
+}
+
+struct traceback_table {
+ long zero;
+ long magic;
+ long reserved;
+ long codeSize;
+ short nameLength;
+ char name[2];
+};
+
+static char* pc2name(long* pc, char name[], long size)
+{
+ name[0] = '\0';
+
+ // make sure pc is instruction aligned (at least).
+ if (UInt32(pc) == (UInt32(pc) & 0xFFFFFFFC)) {
+ long instructionsToLook = 4096;
+ long* instruction = (long*)pc;
+
+ // look for the traceback table.
+ while (instructionsToLook--) {
+ if (instruction[0] == 0x4E800020 && instruction[1] == 0x00000000) {
+ traceback_table* tb = (traceback_table*)&instruction[1];
+ memcpy(name, tb->name + 1, --nameLength);
+ name[nameLength] = '\0';
+ break;
+ }
+ ++instruction;
+ }
+ }
+
+ return name;
+}
+
+struct stack_frame {
+ stack_frame* next; // savedSP
+ void* savedCR;
+ void* savedLR;
+ void* reserved0;
+ void* reserved1;
+ void* savedTOC;
+};
+
+static asm stack_frame* getStackFrame()
+{
+ mr r3, sp
+ blr
+}
+
+NS_COM void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ stack_frame* currentFrame = getStackFrame(); // WalkTheStack's frame.
+ currentFrame = currentFrame->next; // WalkTheStack's caller's frame.
+ currentFrame = currentFrame->next; // WalkTheStack's caller's caller's frame.
+
+ while (true) {
+ // LR saved at 8(SP) in each frame. subtract 4 to get address of calling instruction.
+ void* pc = currentFrame->savedLR;
+
+ // convert PC to name, unmangle it, and generate source location, if possible.
+ static char symbol_name[1024], unmangled_name[1024], file_name[256]; UInt32 file_offset;
+
+ if (GC_address_to_source((char*)pc, symbol_name, file_name, &file_offset)) {
+ MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name));
+ fprintf(aStream, "%s[%s,%ld]\n", unmangled_name, file_name, file_offset);
+ } else {
+ pc2name((long*)pc, symbol_name, sizeof(symbol_name));
+ MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name));
+ fprintf(aStream, "%s(0x%08X)\n", unmangled_name, pc);
+ }
+
+ currentFrame = currentFrame->next;
+ // the bottom-most frame is marked as pointing to NULL, or is ODD if a 68K transition frame.
+ if (currentFrame == NULL || UInt32(currentFrame) & 0x1)
+ break;
+ }
+}
+
+#else // unsupported platform.
+
+void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ fprintf(aStream, "write me, dammit!\n");
+}
+
+#endif
+
+//----------------------------------------------------------------------
+
+// This thing is exported by libstdc++
+// Yes, this is a gcc only hack
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include <cxxabi.h>
+#include <stdlib.h> // for free()
+#endif // MOZ_DEMANGLE_SYMBOLS
+
+NS_COM void
+nsTraceRefcntImpl::DemangleSymbol(const char * aSymbol,
+ char * aBuffer,
+ int aBufLen)
+{
+ NS_ASSERTION(nsnull != aSymbol,"null symbol");
+ NS_ASSERTION(nsnull != aBuffer,"null buffer");
+ NS_ASSERTION(aBufLen >= 32 ,"pulled 32 out of you know where");
+
+ aBuffer[0] = '\0';
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ /* See demangle.h in the gcc source for the voodoo */
+ char * demangled = abi::__cxa_demangle(aSymbol,0,0,0);
+
+ if (demangled)
+ {
+ strncpy(aBuffer,demangled,aBufLen);
+ free(demangled);
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+}
+
+
+//----------------------------------------------------------------------
+
+NS_COM void
+nsTraceRefcntImpl::LoadLibrarySymbols(const char* aLibraryName,
+ void* aLibrayHandle)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+#if defined(_WIN32) && defined(_M_IX86) /* Win32 x86 only */
+ if (!gInitialized)
+ InitTraceLog();
+
+ if (gAllocLog || gRefcntsLog) {
+ fprintf(stdout, "### Loading symbols for %s\n", aLibraryName);
+ fflush(stdout);
+
+ HANDLE myProcess = ::GetCurrentProcess();
+ BOOL ok = EnsureSymInitialized();
+ if (ok) {
+ const char* baseName = aLibraryName;
+ // just get the base name of the library if a full path was given:
+ PRInt32 len = strlen(aLibraryName);
+ for (PRInt32 i = len - 1; i >= 0; i--) {
+ if (aLibraryName[i] == '\\') {
+ baseName = &aLibraryName[i + 1];
+ break;
+ }
+ }
+ DWORD baseAddr = _SymLoadModule(myProcess,
+ NULL,
+ (char*)baseName,
+ (char*)baseName,
+ 0,
+ 0);
+ ok = (baseAddr != nsnull);
+ }
+ if (!ok) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ fprintf(stdout, "### ERROR: LoadLibrarySymbols for %s: %s\n",
+ aLibraryName, lpMsgBuf);
+ fflush(stdout);
+ LocalFree( lpMsgBuf );
+ }
+ }
+#endif
+#endif
+}
+
+//----------------------------------------------------------------------
+
+
+
+
+
+
+// don't use the logging ones. :-)
+NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::AddRef(void)
+{
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
+ ++mRefCnt;
+ return mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::Release(void)
+{
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ --mRefCnt;
+ if (mRefCnt == 0) {
+ mRefCnt = 1; /* stabilize */
+ delete this;
+ return 0;
+ }
+ return mRefCnt;
+}
+
+NS_IMPL_QUERY_INTERFACE1(nsTraceRefcntImpl, nsITraceRefcnt)
+
+nsTraceRefcntImpl::nsTraceRefcntImpl()
+{
+ /* member initializers and constructor code */
+}
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogAddRef(void* aPtr,
+ nsrefcnt aRefcnt,
+ const char* aClazz,
+ PRUint32 classSize)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aClazz, classSize);
+ if (entry) {
+ entry->AddRef(aRefcnt);
+ }
+ }
+
+ // Here's the case where neither NS_NEWXPCOM nor MOZ_COUNT_CTOR were used,
+ // yet we still want to see creation information:
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, aRefcnt == 1);
+ PRInt32* count = GetRefCount(aPtr);
+ if(count)
+ (*count)++;
+
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+ if (aRefcnt == 1 && gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog, "\n<%s> 0x%08X %d Create\n",
+ aClazz, NS_PTR_TO_INT32(aPtr), serialno);
+ WalkTheStack(gAllocLog);
+ }
+
+ if (gRefcntsLog && loggingThisType && loggingThisObject) {
+ if (gLogToLeaky) {
+ (*leakyLogAddRef)(aPtr, aRefcnt - 1, aRefcnt);
+ }
+ else {
+ // Can't use PR_LOG(), b/c it truncates the line
+ fprintf(gRefcntsLog,
+ "\n<%s> 0x%08X %d AddRef %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
+ WalkTheStack(gRefcntsLog);
+ fflush(gRefcntsLog);
+ }
+ }
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogRelease(void* aPtr,
+ nsrefcnt aRefcnt,
+ const char* aClazz)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aClazz, 0);
+ if (entry) {
+ entry->Release(aRefcnt);
+ }
+ }
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, PR_FALSE);
+ PRInt32* count = GetRefCount(aPtr);
+ if(count)
+ (*count)--;
+
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+ if (gRefcntsLog && loggingThisType && loggingThisObject) {
+ if (gLogToLeaky) {
+ (*leakyLogRelease)(aPtr, aRefcnt + 1, aRefcnt);
+ }
+ else {
+ // Can't use PR_LOG(), b/c it truncates the line
+ fprintf(gRefcntsLog,
+ "\n<%s> 0x%08X %d Release %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
+ WalkTheStack(gRefcntsLog);
+ fflush(gRefcntsLog);
+ }
+ }
+
+ // Here's the case where neither NS_DELETEXPCOM nor MOZ_COUNT_DTOR were used,
+ // yet we still want to see deletion information:
+
+ if (aRefcnt == 0 && gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog,
+ "\n<%s> 0x%08X %d Destroy\n",
+ aClazz, NS_PTR_TO_INT32(aPtr), serialno);
+ WalkTheStack(gAllocLog);
+ }
+
+ if (aRefcnt == 0 && gSerialNumbers && loggingThisType) {
+ RecycleSerialNumberPtr(aPtr);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogCtor(void* aPtr,
+ const char* aType,
+ PRUint32 aInstanceSize)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aType, aInstanceSize);
+ if (entry) {
+ entry->Ctor();
+ }
+ }
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aType));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, PR_TRUE);
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+ if (gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog, "\n<%s> 0x%08X %d Ctor (%d)\n",
+ aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
+ WalkTheStack(gAllocLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogDtor(void* aPtr,
+ const char* aType,
+ PRUint32 aInstanceSize)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aType, aInstanceSize);
+ if (entry) {
+ entry->Dtor();
+ }
+ }
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aType));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, PR_FALSE);
+ RecycleSerialNumberPtr(aPtr);
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+
+ // (If we're on a losing architecture, don't do this because we'll be
+ // using LogDeleteXPCOM instead to get file and line numbers.)
+ if (gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog, "\n<%s> 0x%08X %d Dtor (%d)\n",
+ aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
+ WalkTheStack(gAllocLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr,
+ nsISupports* aObject)
+{
+#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
+ // Get the most-derived object.
+ void *object = dynamic_cast<void *>(aObject);
+
+ // This is a very indirect way of finding out what the class is
+ // of the object being logged. If we're logging a specific type,
+ // then
+ if (!gTypesToLog || !gSerialNumbers) {
+ return NS_OK;
+ }
+ PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
+ if (serialno == 0) {
+ return NS_OK;
+ }
+
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ PRInt32* count = GetCOMPtrCount(object);
+ if(count)
+ (*count)++;
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+
+ if (gCOMPtrLog && loggingThisObject) {
+ fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrAddRef %d 0x%08X\n",
+ NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
+ WalkTheStack(gCOMPtrLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr,
+ nsISupports* aObject)
+{
+#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
+ // Get the most-derived object.
+ void *object = dynamic_cast<void *>(aObject);
+
+ // This is a very indirect way of finding out what the class is
+ // of the object being logged. If we're logging a specific type,
+ // then
+ if (!gTypesToLog || !gSerialNumbers) {
+ return NS_OK;
+ }
+ PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
+ if (serialno == 0) {
+ return NS_OK;
+ }
+
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ PRInt32* count = GetCOMPtrCount(object);
+ if(count)
+ (*count)--;
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+
+ if (gCOMPtrLog && loggingThisObject) {
+ fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrRelease %d 0x%08X\n",
+ NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
+ WalkTheStack(gCOMPtrLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+NS_COM void
+nsTraceRefcntImpl::Startup()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ SetActivityIsLegal(PR_TRUE);
+#endif
+}
+
+NS_COM void
+nsTraceRefcntImpl::Shutdown()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+
+ if (gBloatView) {
+ PL_HashTableDestroy(gBloatView);
+ gBloatView = nsnull;
+ }
+ if (gTypesToLog) {
+ PL_HashTableDestroy(gTypesToLog);
+ gTypesToLog = nsnull;
+ }
+ if (gObjectsToLog) {
+ PL_HashTableDestroy(gObjectsToLog);
+ gObjectsToLog = nsnull;
+ }
+ if (gSerialNumbers) {
+ PL_HashTableDestroy(gSerialNumbers);
+ gSerialNumbers = nsnull;
+ }
+
+ SetActivityIsLegal(PR_FALSE);
+
+#endif
+}
+
+NS_COM void
+nsTraceRefcntImpl::SetActivityIsLegal(PRBool aLegal)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ gActivityIsLegal = aLegal;
+#endif
+}
+
+
+NS_METHOD
+nsTraceRefcntImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ *aInstancePtr = nsnull;
+ nsITraceRefcnt* tracer = new nsTraceRefcntImpl();
+ if (!tracer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = tracer->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv)) {
+ delete tracer;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h
new file mode 100644
index 00000000..528b285d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsTraceRefcntImpl_h___
+#define nsTraceRefcntImpl_h___
+
+#include <stdio.h> // for FILE
+#include "nsITraceRefcnt.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_MeanAndStdDev VBoxNsxpNS_MeanAndStdDev
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+class nsTraceRefcntImpl : public nsITraceRefcnt
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITRACEREFCNT
+
+ nsTraceRefcntImpl();
+
+ static NS_COM void Startup();
+ static NS_COM void Shutdown();
+
+ enum StatisticsType {
+ ALL_STATS,
+ NEW_STATS
+ };
+
+ static NS_COM nsresult DumpStatistics(StatisticsType type = ALL_STATS,
+ FILE* out = 0);
+
+ static NS_COM void ResetStatistics(void);
+
+ static NS_COM void LoadLibrarySymbols(const char* aLibraryName,
+ void* aLibrayHandle);
+
+
+ static NS_COM void DemangleSymbol(const char * aSymbol,
+ char * aBuffer,
+ int aBufLen);
+
+ static NS_COM void WalkTheStack(FILE* aStream);
+ /**
+ * Tell nsTraceRefcnt whether refcounting, allocation, and destruction
+ * activity is legal. This is used to trigger assertions for any such
+ * activity that occurs because of static constructors or destructors.
+ */
+ static NS_COM void SetActivityIsLegal(PRBool aLegal);
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsTraceRefcntImpl() {}
+};
+
+#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1"
+#define NS_TRACE_REFCNT_CLASSNAME "nsTraceRefcnt Interface"
+#define NS_TRACE_REFCNT_CID \
+{ /* e3e7511e-a395-4924-94b1-d527861cded4 */ \
+ 0xe3e7511e, \
+ 0xa395, \
+ 0x4924, \
+ {0x94, 0xb1, 0xd5, 0x27, 0x86, 0x1c, 0xde, 0xd4} \
+} \
+
+////////////////////////////////////////////////////////////////////////////////
+// And now for that utility that you've all been asking for...
+
+extern "C" NS_COM void
+NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
+ double *meanResult, double *stdDevResult);
+
+////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h b/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h
new file mode 100644
index 00000000..c15e31f0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsWeakPtr_h__
+#define nsWeakPtr_h__
+
+#include "nsIWeakReference.h"
+#include "nsCOMPtr.h"
+
+// typedef nsCOMPtr<nsIWeakReference> nsWeakPtr;
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nscore.h b/src/libs/xpcom18a4/xpcom/base/nscore.h
new file mode 100644
index 00000000..b7bfa11f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nscore.h
@@ -0,0 +1,468 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nscore_h___
+#define nscore_h___
+
+/**
+ * Make sure that we have the proper platform specific
+ * c++ definitions needed by nscore.h
+ */
+#ifndef _XPCOM_CONFIG_H_
+#include "xpcom-config.h"
+#endif
+
+/**
+ * Incorporate the core NSPR data types which XPCOM uses.
+ */
+#include "prtypes.h"
+
+/* Core XPCOM declarations. */
+
+/**
+ * Macros defining the target platform...
+ */
+#ifdef _WIN32
+#define NS_WIN32 1
+
+#elif defined(__unix)
+#define NS_UNIX 1
+
+#elif defined(XP_OS2)
+#define NS_OS2 1
+#endif
+/*----------------------------------------------------------------------*/
+/* Import/export defines */
+
+/**
+ * Using the visibility("hidden") attribute allows the compiler to use
+ * PC-relative addressing to call this function. If a function does not
+ * access any global data, and does not call any methods which are not either
+ * file-local or hidden, then on ELF systems we avoid loading the address of
+ * the PLT into a register at the start of the function, which reduces code
+ * size and frees up a register for general use.
+ *
+ * As a general rule, this should be used for any non-exported symbol
+ * (including virtual method implementations). NS_IMETHOD uses this by
+ * default; if you need to have your NS_IMETHOD functions exported, you can
+ * wrap your class as follows:
+ *
+ * #undef IMETHOD_VISIBILITY
+ * #define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+ *
+ * class Foo {
+ * ...
+ * };
+ *
+ * #undef IMETHOD_VISIBILITY
+ * #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+ *
+ * Don't forget to change the visibility back to hidden before the end
+ * of a header!
+ *
+ * Other examples:
+ *
+ * NS_HIDDEN_(int) someMethod();
+ * SomeCtor() NS_HIDDEN;
+ */
+
+#ifdef HAVE_VISIBILITY_ATTRIBUTE
+#define NS_VISIBILITY_HIDDEN __attribute__ ((visibility ("hidden")))
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define NS_VISIBILITY_DEFAULT __attribute__ ((visibility ("default")))
+# else
+# define NS_VISIBILITY_DEFAULT
+# endif
+
+#define NS_HIDDEN_(type) NS_VISIBILITY_HIDDEN type
+#else
+#define NS_VISIBILITY_HIDDEN
+#define NS_VISIBILITY_DEFAULT
+
+#define NS_HIDDEN_(type) type
+#endif
+
+#define NS_HIDDEN NS_VISIBILITY_HIDDEN
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+/**
+ * Mark a function as using a potentially non-standard function calling
+ * convention. This can be used on functions that are called very
+ * frequently, to reduce the overhead of the function call. It is still worth
+ * using the macro for C++ functions which take no parameters since it allows
+ * passing |this| in a register.
+ *
+ * - Do not use this on any scriptable interface method since xptcall won't be
+ * aware of the different calling convention.
+ * - This must appear on the declaration, not the definition.
+ * - Adding this to a public function _will_ break binary compatibility.
+ * - This may be used on virtual functions but you must ensure it is applied
+ * to all implementations - the compiler will _not_ warn but it will crash.
+ * - This has no effect for inline functions or functions which take a
+ * variable number of arguments.
+ *
+ * Examples: int NS_FASTCALL func1(char *foo);
+ * NS_HIDDEN_(int) NS_FASTCALL func2(char *foo);
+ */
+
+#if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 3) && !defined(XP_OS2)
+#define NS_FASTCALL __attribute__ ((regparm (3), stdcall))
+#else
+#define NS_FASTCALL
+#endif
+
+/* XXX: nike, maybe fix */
+#define NS_EXPORT_STATIC_MEMBER_(type) type
+#define NS_IMPORT_STATIC_MEMBER_(type) type
+
+#ifdef NS_WIN32
+
+#define NS_IMPORT __declspec(dllimport)
+#define NS_IMPORT_(type) type __declspec(dllimport) __stdcall
+#define NS_EXPORT __declspec(dllexport)
+#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall
+#define NS_IMETHOD_(type) virtual type __stdcall
+#define NS_IMETHODIMP_(type) type __stdcall
+#define NS_METHOD_(type) type __stdcall
+#define NS_CALLBACK_(_type, _name) _type (__stdcall * _name)
+#define NS_STDCALL __stdcall
+
+#elif defined(XP_MAC)
+
+#define NS_IMPORT
+#define NS_IMPORT_(type) type
+#define NS_EXPORT __declspec(export)
+#define NS_EXPORT_(type) __declspec(export) type
+#define NS_IMETHOD_(type) virtual type
+#define NS_IMETHODIMP_(type) type
+#define NS_METHOD_(type) type
+#define NS_CALLBACK_(_type, _name) _type (* _name)
+#define NS_STDCALL
+
+#elif defined(XP_OS2) && defined(__declspec)
+
+#define NS_IMPORT __declspec(dllimport)
+#define NS_IMPORT_(type) type __declspec(dllimport) __stdcall
+#define NS_EXPORT __declspec(dllexport)
+#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall
+#define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type
+#define NS_IMETHODIMP_(type) type
+#define NS_METHOD_(type) type
+#define NS_CALLBACK_(_type, _name) _type (* _name)
+#define NS_STDCALL
+
+#else
+
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define NS_IMPORT
+# define NS_IMPORT_(type) type
+# define NS_EXPORT __attribute__((visibility("default")))
+# define NS_EXPORT_(type) __attribute__((visibility("default"))) type
+# define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type
+# define NS_IMETHODIMP_(type) type
+# define NS_METHOD_(type) type
+# define NS_CALLBACK_(_type, _name) _type (* _name)
+# define NS_STDCALL
+# else
+# define NS_IMPORT
+# define NS_IMPORT_(type) type
+# define NS_EXPORT
+# define NS_EXPORT_(type) type
+# define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type
+# define NS_IMETHODIMP_(type) type
+# define NS_METHOD_(type) type
+# define NS_CALLBACK_(_type, _name) _type (* _name)
+# define NS_STDCALL
+# endif
+#endif
+
+/**
+ * Macro for creating typedefs for pointer-to-member types which are
+ * declared with stdcall. It is important to use this for any type which is
+ * declared as stdcall (i.e. NS_IMETHOD). For example, instead of writing:
+ *
+ * typedef nsresult (nsIFoo::*someType)(nsISupports* arg);
+ *
+ * you should write:
+ *
+ * typedef
+ * NS_STDCALL_FUNCPROTO(nsresult, someType, nsIFoo, typeFunc, (nsISupports*));
+ *
+ * where nsIFoo::typeFunc is any method declared as
+ * NS_IMETHOD typeFunc(nsISupports*);
+ *
+ * XXX this can be simplified to always use the non-typeof implementation
+ * when http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11893 is fixed.
+ */
+
+#ifdef __GNUC__
+#define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \
+ typeof(&class::func) name
+#else
+#define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \
+ ret (NS_STDCALL class::*name) args
+#endif
+
+/**
+ * Generic API modifiers which return the standard XPCOM nsresult type
+ */
+#define NS_IMETHOD NS_IMETHOD_(nsresult)
+#define NS_IMETHODIMP NS_IMETHODIMP_(nsresult)
+#define NS_METHOD NS_METHOD_(nsresult)
+#define NS_CALLBACK(_name) NS_CALLBACK_(nsresult, _name)
+
+/**
+ * Import/Export macros for XPCOM APIs
+ */
+
+#ifdef _IMPL_NS_COM
+#define NS_COM NS_EXPORT
+#elif _IMPL_NS_COM_OFF
+#define NS_COM
+#elif XPCOM_GLUE
+#define NS_COM
+#else
+#define NS_COM NS_IMPORT
+#endif
+
+
+/**
+ * NS_NO_VTABLE is emitted by xpidl in interface declarations whenever
+ * xpidl can determine that the interface can't contain a constructor.
+ * This results in some space savings and possible runtime savings -
+ * see bug 49416. We undefine it first, as xpidl-generated headers
+ * define it for IDL uses that don't include this file.
+ */
+#ifdef NS_NO_VTABLE
+#undef NS_NO_VTABLE
+#endif
+#if defined(_MSC_VER) && _MSC_VER >= 1100
+#define NS_NO_VTABLE __declspec(novtable)
+#else
+#define NS_NO_VTABLE
+#endif
+
+
+/**
+ * Generic XPCOM result data type
+ */
+typedef PRUint32 nsresult;
+
+/**
+ * The preferred symbol for null.
+ */
+#define nsnull 0
+
+#include "nsError.h"
+
+/* ------------------------------------------------------------------------ */
+/* Casting macros for hiding C++ features from older compilers */
+
+ /*
+ All our compiler support template specialization, but not all support the
+ |template <>| notation. The compiler that don't understand this notation
+ just omit it for specialization.
+
+ Need to add an autoconf test for this.
+ */
+
+ /* under Metrowerks (Mac), we don't have autoconf yet */
+#ifdef __MWERKS__
+ #define HAVE_CPP_PARTIAL_SPECIALIZATION
+ #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+
+ #define HAVE_CPP_ACCESS_CHANGING_USING
+ #define HAVE_CPP_AMBIGUITY_RESOLVING_USING
+ #define HAVE_CPP_EXPLICIT
+ #define HAVE_CPP_TYPENAME
+ #define HAVE_CPP_BOOL
+ #define HAVE_CPP_NAMESPACE_STD
+ #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL
+ #define HAVE_CPP_2BYTE_WCHAR_T
+#endif
+
+ /* under VC++ (Windows), we don't have autoconf yet */
+#if defined(_MSC_VER) && (_MSC_VER>=1100)
+ /* VC++ 5.0 and greater implement template specialization, 4.2 is unknown */
+ #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+
+ #define HAVE_CPP_EXPLICIT
+ #define HAVE_CPP_TYPENAME
+ #define HAVE_CPP_ACCESS_CHANGING_USING
+
+ #if (_MSC_VER==1100)
+ /* VC++5.0 has an internal compiler error (sometimes) without this */
+ #undef HAVE_CPP_ACCESS_CHANGING_USING
+ #endif
+
+ #define HAVE_CPP_NAMESPACE_STD
+ #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL
+ #define HAVE_CPP_2BYTE_WCHAR_T
+#endif
+
+#ifndef __PRUNICHAR__
+#define __PRUNICHAR__
+ /* For now, don't use wchar_t on Unix because it breaks the Netscape
+ * commercial build. When this is fixed there will be no need for the
+ * |NS_REINTERPRET_CAST| in nsLiteralString.h either.
+ */
+ #if defined(HAVE_CPP_2BYTE_WCHAR_T) && (defined(NS_WIN32) || defined(XP_MAC))
+ typedef wchar_t PRUnichar;
+ #else
+ typedef PRUint16 PRUnichar;
+ #endif
+#endif
+
+ /*
+ If the compiler doesn't support |explicit|, we'll just make it go away, trusting
+ that the builds under compilers that do have it will keep us on the straight and narrow.
+ */
+#ifndef HAVE_CPP_EXPLICIT
+ #define explicit
+#endif
+
+#ifndef HAVE_CPP_TYPENAME
+ #define typename
+#endif
+
+#ifdef HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+ #define NS_SPECIALIZE_TEMPLATE template <>
+#else
+ #define NS_SPECIALIZE_TEMPLATE
+#endif
+
+/* unix and beos now determine this automatically */
+#if ! defined XP_UNIX && ! defined XP_BEOS && !defined(XP_OS2)
+#ifndef HAVE_CPP_NEW_CASTS
+#define HAVE_CPP_NEW_CASTS 1 /* we'll be optimistic. */
+#endif
+#endif
+
+#if defined(HAVE_CPP_NEW_CASTS)
+#define NS_STATIC_CAST(__type, __ptr) static_cast< __type >(__ptr)
+#define NS_CONST_CAST(__type, __ptr) const_cast< __type >(__ptr)
+
+#define NS_REINTERPRET_POINTER_CAST(__type, __ptr) reinterpret_cast< __type >(__ptr)
+#define NS_REINTERPRET_NONPOINTER_CAST(__type, __obj) reinterpret_cast< __type >(__obj)
+#define NS_REINTERPRET_CAST(__type, __expr) reinterpret_cast< __type >(__expr)
+
+#else
+#define NS_STATIC_CAST(__type, __ptr) ((__type)(__ptr))
+#define NS_CONST_CAST(__type, __ptr) ((__type)(__ptr))
+
+#define NS_REINTERPRET_POINTER_CAST(__type, __ptr) ((__type)((void*)(__ptr)))
+#define NS_REINTERPRET_NONPOINTER_CAST(__type, __obj) ((__type)(__obj))
+
+ /* Note: the following is only appropriate for pointers. */
+#define NS_REINTERPRET_CAST(__type, __expr) NS_REINTERPRET_POINTER_CAST(__type, __expr)
+ /*
+ Why cast to a |void*| first? Well, when old-style casting from
+ a pointer to a base to a pointer to a derived class, the cast will be
+ ambiguous if the source pointer type appears multiple times in the
+ destination, e.g.,
+
+ class Base {};
+ class Derived : public Base, public Base {};
+
+ void foo( Base* b )
+ {
+ ((Derived*)b)->some_derived_member ... // Error: Ambiguous, expand from which |Base|?
+ }
+
+ an old-style cast (like |static_cast|) will change the pointer, but
+ here, doesn't know how. The cast to |void*| prevents it from thinking
+ it needs to expand the original pointer.
+
+ The cost is, |NS_REINTERPRET_CAST| is no longer appropriate for non-pointer
+ conversions. Also, mis-applying |NS_REINTERPRET_CAST| to cast |this| to something
+ will still expand the pointer to the outer object in standards complying compilers.
+ */
+
+ /*
+ No sense in making an NS_DYNAMIC_CAST() macro: you can't duplicate
+ the semantics. So if you want to dynamic_cast, then just use it
+ "straight", no macro.
+ */
+#endif
+
+#if __cplusplus+0 > 201100L
+#define NS_DEFAULT = default
+#define NS_DELETE = delete
+#else
+#define NS_DEFAULT
+#define NS_DELETE
+#endif
+
+
+#ifndef VBOX
+/*
+ * Use these macros to do 64bit safe pointer conversions.
+ */
+
+#define NS_PTR_TO_INT32(x) ((char *)(x) - (char *)0)
+#define NS_INT32_TO_PTR(x) ((void *)((char *)0 + (x)))
+#else /* VBOX */
+// This stuff is (contrary to the comment) totally 64bit unsafe, so strip
+// it down to only do one direction, which is used by the hashing code.
+#define NS_PTR_TO_INT32(x) ((PRInt32)((char *)(x) - (char *)0))
+#endif /* VBOX */
+
+/*
+ * These macros allow you to give a hint to the compiler about branch
+ * probability so that it can better optimize. Use them like this:
+ *
+ * if (NS_LIKELY(v == 1)) {
+ * ... expected code path ...
+ * }
+ *
+ * if (NS_UNLIKELY(v == 0)) {
+ * ... non-expected code path ...
+ * }
+ *
+ */
+
+#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(FORTIFY_RUNNING)
+#define NS_LIKELY(x) (__builtin_expect(!!(x), 1))
+#define NS_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+#else
+#define NS_LIKELY(x) (x)
+#define NS_UNLIKELY(x) (x)
+#endif
+
+#endif /* nscore_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl b/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl
new file mode 100644
index 00000000..0538e4bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl
@@ -0,0 +1,128 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Root idl declarations to be used by all.
+ * @status FROZEN
+ */
+
+%{C++
+
+#include "nscore.h"
+#include "prtime.h"
+
+/*
+ * Forward declarations for new string types
+ */
+class nsAString;
+class nsACString;
+
+/*
+ * Start commenting out the C++ versions of the below in the output header
+ */
+#if 0
+%}
+
+typedef boolean PRBool ;
+typedef octet PRUint8 ;
+typedef unsigned short PRUint16 ;
+typedef unsigned short PRUnichar;
+typedef unsigned long PRUint32 ;
+typedef unsigned long long PRUint64 ;
+typedef unsigned long long PRTime ;
+typedef short PRInt16 ;
+typedef long PRInt32 ;
+typedef long long PRInt64 ;
+
+typedef unsigned long nsrefcnt ;
+typedef unsigned long nsresult ;
+
+// XXX need this built into xpidl compiler so that it's really size_t or PRSize
+// and it's scriptable:
+typedef unsigned long size_t;
+
+[ptr] native voidPtr(void);
+[ptr] native charPtr(char);
+[ptr] native unicharPtr(PRUnichar);
+
+[ref, nsid] native nsIDRef(nsID);
+[ref, nsid] native nsIIDRef(nsIID);
+[ref, nsid] native nsCIDRef(nsCID);
+
+[ptr, nsid] native nsIDPtr(nsID);
+[ptr, nsid] native nsIIDPtr(nsIID);
+[ptr, nsid] native nsCIDPtr(nsCID);
+
+// NOTE: Be careful in using the following 3 types. The *Ref and *Ptr variants
+// are more commonly used (and better supported). Those variants require
+// nsMemory alloc'd copies when used as 'out' params while these types do not.
+// However, currently these types can not be used for 'in' params. And, methods
+// that use them as 'out' params *must* be declared [notxpcom] (with an explicit
+// return type of nsresult). This makes such methods implicitly not scriptable.
+// Use of these types in methods without a [notxpcom] declaration will cause
+// the xpidl compiler to raise an error.
+// See: http://bugzilla.mozilla.org/show_bug.cgi?id=93792
+
+[nsid] native nsIID(nsIID);
+[nsid] native nsID(nsID);
+[nsid] native nsCID(nsCID);
+
+[ptr] native nsQIResult(void);
+
+[ref, domstring] native DOMString(ignored);
+[ref, domstring] native DOMStringRef(ignored);
+[ptr, domstring] native DOMStringPtr(ignored);
+
+[ref, utf8string] native AUTF8String(ignored);
+[ref, utf8string] native AUTF8StringRef(ignored);
+[ptr, utf8string] native AUTF8StringPtr(ignored);
+
+[ref, cstring] native ACString(ignored);
+[ref, cstring] native ACStringRef(ignored);
+[ptr, cstring] native ACStringPtr(ignored);
+
+[ref, astring] native AString(ignored);
+[ref, astring] native AStringRef(ignored);
+[ptr, astring] native AStringPtr(ignored);
+
+%{C++
+/*
+ * End commenting out the C++ versions of the above in the output header
+ */
+#endif
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/pure.h b/src/libs/xpcom18a4/xpcom/base/pure.h
new file mode 100644
index 00000000..ea11b99d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/pure.h
@@ -0,0 +1,135 @@
+/*
+ * Header file of Pure API function declarations.
+ *
+ * Explicitly no copyright.
+ * You may recompile and redistribute these definitions as required.
+ *
+ * Version 1.0
+ */
+
+#if defined(c_plusplus) || defined(__cplusplus)
+extern "C" {
+#endif
+
+#define PURE_H_VERSION 1
+
+//////////////////////////////
+// API's Specific to Purify //
+//////////////////////////////
+
+// TRUE when Purify is running.
+int __cdecl PurifyIsRunning(void) ;
+//
+// Print a string to the viewer.
+//
+int __cdecl PurePrintf(const char *fmt, ...) ;
+int __cdecl PurifyPrintf(const char *fmt, ...) ;
+//
+// Purify functions for leak and memory-in-use functionalty.
+//
+int __cdecl PurifyNewInuse(void) ;
+int __cdecl PurifyAllInuse(void) ;
+int __cdecl PurifyClearInuse(void) ;
+int __cdecl PurifyNewLeaks(void) ;
+int __cdecl PurifyAllLeaks(void) ;
+int __cdecl PurifyClearLeaks(void) ;
+//
+// Purify functions for handle leakage.
+//
+int __cdecl PurifyAllHandlesInuse(void) ;
+int __cdecl PurifyNewHandlesInuse(void) ;
+//
+// Functions that tell you about the state of memory.
+//
+int __cdecl PurifyDescribe(void *addr) ;
+int __cdecl PurifyWhatColors(void *addr, int size) ;
+//
+// Functions to test the state of memory. If the memory is not
+// accessable, an error is signaled just as if there were a memory
+// reference and the function returns false.
+//
+int __cdecl PurifyAssertIsReadable(const void *addr, int size) ;
+int __cdecl PurifyAssertIsWritable(const void *addr, int size) ;
+//
+// Functions to test the state of memory. If the memory is not
+// accessable, these functions return false. No error is signaled.
+//
+int __cdecl PurifyIsReadable(const void *addr, int size) ;
+int __cdecl PurifyIsWritable(const void *addr, int size) ;
+int __cdecl PurifyIsInitialized(const void *addr, int size) ;
+//
+// Functions to set the state of memory.
+//
+void __cdecl PurifyMarkAsInitialized(void *addr, int size) ;
+void __cdecl PurifyMarkAsUninitialized(void *addr, int size) ;
+//
+// Functions to do late detection of ABWs, FMWs, IPWs.
+//
+#define PURIFY_HEAP_CRT 0xfffffffe
+#define PURIFY_HEAP_ALL 0xfffffffd
+#define PURIFY_HEAP_BLOCKS_LIVE 0x80000000
+#define PURIFY_HEAP_BLOCKS_DEFERRED_FREE 0x40000000
+#define PURIFY_HEAP_BLOCKS_ALL (PURIFY_HEAP_BLOCKS_LIVE|PURIFY_HEAP_BLOCKS_DEFERRED_FREE)
+int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr) ;
+int __cdecl PurifySetLateDetectScanCounter(int counter);
+int __cdecl PurifySetLateDetectScanInterval(int seconds);
+
+
+////////////////////////////////
+// API's Specific to Quantify //
+////////////////////////////////
+
+// TRUE when Quantify is running.
+int __cdecl QuantifyIsRunning(void) ;
+
+//
+// Functions for controlling collection
+//
+int __cdecl QuantifyDisableRecordingData(void) ;
+int __cdecl QuantifyStartRecordingData(void) ;
+int __cdecl QuantifyStopRecordingData(void) ;
+int __cdecl QuantifyClearData(void) ;
+int __cdecl QuantifyIsRecordingData(void) ;
+
+// Add a comment to the dataset
+int __cdecl QuantifyAddAnnotation(char *) ;
+
+// Save the current data, creating a "checkpoint" dataset
+int __cdecl QuantifySaveData(void) ;
+
+////////////////////////////////
+// API's Specific to Coverage //
+////////////////////////////////
+
+// TRUE when Coverage is running.
+int __cdecl CoverageIsRunning(void) ;
+//
+// Functions for controlling collection
+//
+int __cdecl CoverageDisableRecordingData(void) ;
+int __cdecl CoverageStartRecordingData(void) ;
+int __cdecl CoverageStopRecordingData(void) ;
+int __cdecl CoverageClearData(void) ;
+int __cdecl CoverageIsRecordingData(void) ;
+// Add a comment to the dataset
+int __cdecl CoverageAddAnnotation(char *) ;
+
+// Save the current data, creating a "checkpoint" dataset
+int __cdecl CoverageSaveData(void) ;
+
+
+
+
+////////////////////////////////
+// API's Specific to Purelock //
+////////////////////////////////
+
+// TRUE when Purelock is running.
+int __cdecl PurelockIsRunning(void) ;
+
+
+
+
+#if defined(c_plusplus) || defined(__cplusplus)
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/pure_api.c b/src/libs/xpcom18a4/xpcom/base/pure_api.c
new file mode 100644
index 00000000..716460ed
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/pure_api.c
@@ -0,0 +1,126 @@
+/*
+ * Header file of Pure API function declarations.
+ *
+ * Explicitly no copyright.
+ * You may recompile and redistribute these definitions as required.
+ *
+ * NOTE1: In some situations when compiling with MFC, you should
+ * enable the setting 'Not using precompiled headers' in Visual C++
+ * to avoid a compiler diagnostic.
+ *
+ * NOTE2: This file works through the use of deep magic. Calls to functions
+ * in this file are replaced with calls into the OCI runtime system
+ * when an instrumented version of this program is run.
+ *
+ * NOTE3: The static vars avoidGy_n (where n is a unique number) are used
+ * to prevent optimizing the functions away when compiler option
+ * /Gy is set. This is needed so that NOTE2 works properly.
+ */
+static int avoidGy_1;
+static int avoidGy_2;
+static int avoidGy_3;
+static int avoidGy_4;
+static int avoidGy_5;
+static int avoidGy_6;
+static int avoidGy_7;
+static int avoidGy_8;
+static int avoidGy_9;
+static int avoidGy_10;
+static int avoidGy_11;
+static int avoidGy_12;
+static int avoidGy_13;
+static int avoidGy_14;
+static int avoidGy_15;
+static int avoidGy_16;
+static int avoidGy_17;
+static int avoidGy_18;
+static int avoidGy_19;
+static int avoidGy_20;
+static int avoidGy_21;
+static int avoidGy_22;
+static int avoidGy_23;
+static int avoidGy_24;
+static int avoidGy_25;
+static int avoidGy_26;
+static int avoidGy_27;
+static int avoidGy_28;
+static int avoidGy_29;
+static int avoidGy_30;
+static int avoidGy_31;
+static int avoidGy_32;
+static int avoidGy_33;
+static int avoidGy_34;
+static int avoidGy_35;
+static int avoidGy_36;
+static int avoidGy_37;
+static int avoidGy_38;
+static int avoidGy_39;
+static int avoidGy_40;
+static int avoidGy_41;
+static int avoidGy_42;
+static int avoidGy_43;
+static int avoidGy_44;
+static int avoidGy_45;
+static int avoidGy_46;
+static int avoidGy_47;
+static int avoidGy_48;
+static int avoidGy_49;
+static int avoidGy_50;
+static int avoidGy_51;
+static int avoidGy_52;
+static int avoidGy_53;
+static int avoidGy_54;
+static int avoidGy_55;
+static int avoidGy_56;
+static int avoidGy_57;
+static int avoidGy_58;
+static int avoidGy_59;
+static int avoidGy_60;
+static int avoidGy_PL_01;
+__declspec(dllexport) int __cdecl PurePrintf(const char *fmt, ...) { avoidGy_1++; fmt; return 0; }
+__declspec(dllexport) int __cdecl PurifyIsRunning(void) { avoidGy_2++; return 0; }
+__declspec(dllexport) int __cdecl PurifyPrintf(const char *fmt, ...) { avoidGy_3++; fmt; return 0; }
+__declspec(dllexport) int __cdecl PurifyNewInuse(void) { avoidGy_4++; return 0; }
+__declspec(dllexport) int __cdecl PurifyAllInuse(void) { avoidGy_5++; return 0; }
+__declspec(dllexport) int __cdecl PurifyClearInuse(void) { avoidGy_6++; return 0; }
+__declspec(dllexport) int __cdecl PurifyNewLeaks(void) { avoidGy_7++; return 0; }
+__declspec(dllexport) int __cdecl PurifyAllLeaks(void) { avoidGy_8++; return 0; }
+__declspec(dllexport) int __cdecl PurifyClearLeaks(void) { avoidGy_9++; return 0; }
+__declspec(dllexport) int __cdecl PurifyAllHandlesInuse(void) { avoidGy_10++; return 0; }
+__declspec(dllexport) int __cdecl PurifyNewHandlesInuse(void) { avoidGy_11++; return 0; }
+__declspec(dllexport) int __cdecl PurifyDescribe(void *addr) { avoidGy_12++; addr; return 0; }
+__declspec(dllexport) int __cdecl PurifyWhatColors(void *addr, int size) { avoidGy_13++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyAssertIsReadable(const void *addr, int size) { avoidGy_14++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyAssertIsWritable(const void *addr, int size) { avoidGy_15++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyIsReadable(const void *addr, int size) { avoidGy_16++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyIsWritable(const void *addr, int size) { avoidGy_17++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyIsInitialized(const void *addr, int size) { avoidGy_18++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyRed(void *addr, int size) { avoidGy_19++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyGreen(void *addr, int size) { avoidGy_20++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyYellow(void *addr, int size) { avoidGy_21++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyBlue(void *addr, int size) { avoidGy_22++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkAsInitialized(void *addr, int size) { avoidGy_23++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkAsUninitialized(void *addr, int size) { avoidGy_24++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkForTrap(void *addr, int size) { avoidGy_25++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkForNoTrap(void *addr, int size) { avoidGy_26++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr)
+ { avoidGy_27++; hHeap; dwFlags; addr; return 1; }
+__declspec(dllexport) int __cdecl PurifySetLateDetectScanCounter(int counter) { avoidGy_28++; counter; return 0; };
+__declspec(dllexport) int __cdecl PurifySetLateDetectScanInterval(int seconds) { avoidGy_29++; seconds; return 0; };
+__declspec(dllexport) int __cdecl CoverageIsRunning(void) { avoidGy_30++; return 0; }
+__declspec(dllexport) int __cdecl CoverageDisableRecordingData(void) { avoidGy_31++; return 0; }
+__declspec(dllexport) int __cdecl CoverageStartRecordingData(void) { avoidGy_32++; return 0; }
+__declspec(dllexport) int __cdecl CoverageStopRecordingData(void) { avoidGy_33++; return 0; }
+__declspec(dllexport) int __cdecl CoverageClearData(void) { avoidGy_34++; return 0; }
+__declspec(dllexport) int __cdecl CoverageIsRecordingData(void) { avoidGy_35++; return 0; }
+__declspec(dllexport) int __cdecl CoverageAddAnnotation(char *str) { avoidGy_36++; str; return 0; }
+__declspec(dllexport) int __cdecl CoverageSaveData(void) { avoidGy_37++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyIsRunning(void) { avoidGy_42++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyDisableRecordingData(void) { avoidGy_43++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyStartRecordingData(void) { avoidGy_44++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyStopRecordingData(void) { avoidGy_45++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyClearData(void) { avoidGy_46++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyIsRecordingData(void) { avoidGy_47++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyAddAnnotation(char *str) { avoidGy_48++; str; return 0; }
+__declspec(dllexport) int __cdecl QuantifySaveData(void) { avoidGy_49++; return 0; }
+__declspec(dllexport) int __cdecl PurelockIsRunning(void) { avoidGy_PL_01++; return 0; }
diff --git a/src/libs/xpcom18a4/xpcom/build/.cvsignore b/src/libs/xpcom18a4/xpcom/build/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/build/Makefile.in b/src/libs/xpcom18a4/xpcom/build/Makefile.in
new file mode 100644
index 00000000..5c2386ce
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/Makefile.in
@@ -0,0 +1,165 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xpcom
+
+PACKAGE_FILE = xpcom.pkg
+PACKAGE_VARS += USE_SHORT_LIBNAME
+
+ifdef ENABLE_TESTS
+PACKAGE_FILE += xpcom-tests.pkg
+endif
+
+# Do not set EXPORT_LIBRARY as we do not want xpcom in the static libs list
+#EXPORT_LIBRARY = 1
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+# pull in MoreFiles for MacOSX
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += macmorefiles
+endif
+
+CPPSRCS = nsXPComInit.cpp \
+ nsStringAPI.cpp \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS += dlldeps.cpp
+endif
+
+ifdef XPCOM_USE_LEA
+CSRCS += malloc.c
+endif
+
+ifeq ($(OS_TARGET),OS2)
+CPPSRCS += nsOS2VACLegacy.cpp
+endif
+
+ifdef GC_LEAK_DETECTOR
+EXTRA_DSO_LIBS = boehm
+endif
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomds_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomio_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomcomponents_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomthreads_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomproxy_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcombase_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xptcall.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xptinfo.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xptcmd.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)string_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I.. \
+ -I$(srcdir)/../glue \
+ -I$(srcdir)/../base \
+ -I$(srcdir)/../ds \
+ -I$(srcdir)/../io \
+ -I$(srcdir)/../components \
+ -I$(srcdir)/../threads \
+ -I$(srcdir)/../threads/_xpidlgen \
+ -I$(srcdir)/../proxy/src \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsXPCOM.h \
+ nsXPCOMCID.h \
+ $(NULL)
+
+SDK_LIBRARY = $(IMPORT_LIBRARY)
+SDK_BINARY = $(SHARED_LIBRARY)
+
+# pull in MoreFiles for MacOSX
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+EXTRA_DSO_LIBS = macmorefiles_s
+EXTRA_DSO_LDOPTS += $(EXTRA_DSO_LIBS)
+EXTRA_DEPS += $(DIST)/lib/$(LIB_PREFIX)macmorefiles_s.$(LIB_SUFFIX)
+endif
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+FORCE_SHARED_LIB = 1
+
+# UNIX98 iconv support
+OS_LIBS += $(LIBICONV)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += \
+ -D_IMPL_NS_COM \
+ -DEXPORT_XPT_API \
+ -DEXPORT_XPTC_API \
+ -DEXPORT_XPTI_API
+
+EXTRA_DSO_LDOPTS += $(NSPR_LIBS)
+
+ifdef GC_LEAK_DETECTOR
+DEFINES += -DGC_LEAK_DETECTOR
+endif
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+CXXFLAGS += $(TK_CFLAGS)
+EXTRA_DSO_LDOPTS += $(TK_LIBS)
+endif
+
+ifeq ($(OS_ARCH),BeOS)
+EXTRA_DSO_LDOPTS += -lbe
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,shell32 ole32 uuid)
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,imagehlp)
+endif
+endif # WINNT
diff --git a/src/libs/xpcom18a4/xpcom/build/dlldeps.cpp b/src/libs/xpcom18a4/xpcom/build/dlldeps.cpp
new file mode 100644
index 00000000..5fc31189
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/dlldeps.cpp
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Force references to all of the symbols that we want exported from
+// the dll that are located in the .lib files we link with
+
+#include "nsVoidArray.h"
+#include "nsValueArray.h"
+#include "nsIAtom.h"
+//#include "nsIBuffer.h"
+#include "nsIByteArrayInputStream.h"
+#include "nsFixedSizeAllocator.h"
+#include "nsRecyclingAllocator.h"
+#include "nsIThread.h"
+#include "nsDeque.h"
+#include "nsTraceRefcnt.h"
+#include "nsTraceRefcntImpl.h"
+#include "nsXPIDLString.h"
+#include "nsIEnumerator.h"
+#include "nsEnumeratorUtils.h"
+#include "nsQuickSort.h"
+#include "nsString.h"
+#include "nsPrintfCString.h"
+#include "nsSupportsArray.h"
+#include "nsArray.h"
+#include "nsArrayEnumerator.h"
+#include "nsProxyEventPrivate.h"
+#include "nsProxyRelease.h"
+#include "xpt_xdr.h"
+#include "xptcall.h"
+#include "nsILocalFile.h"
+#include "nsIGenericFactory.h"
+#include "nsIPipe.h"
+#include "nsStreamUtils.h"
+#include "nsWeakReference.h"
+#include "nsTextFormatter.h"
+#include "nsIStorageStream.h"
+#include "nsLinebreakConverter.h"
+#include "nsIBinaryInputStream.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsReadableUtils.h"
+#include "nsStaticNameTable.h"
+#include "nsProcess.h"
+#include "nsStringEnumerator.h"
+#include "nsIInputStreamTee.h"
+#include "nsCheapSets.h"
+#ifdef DEBUG
+#include "pure.h"
+#endif
+#include "nsHashKeys.h"
+#include "nsTHashtable.h"
+#include "pldhash.h"
+#include "nsVariant.h"
+#include "nsEscape.h"
+#include "nsStreamUtils.h"
+
+#define NS_STRINGAPI_IMPL
+#include "nsStringAPI.h"
+
+void XXXNeverCalled()
+{
+ nsTextFormatter::snprintf(nsnull,0,nsnull);
+ nsTextFormatter::smprintf(nsnull, nsnull);
+ nsTextFormatter::smprintf_free(nsnull);
+ nsVoidArray();
+ nsSmallVoidArray();
+ nsStringHashSet();
+ nsCStringHashSet();
+ nsInt32HashSet();
+ nsVoidHashSet();
+ nsCheapStringSet();
+ nsCheapInt32Set();
+ nsValueArray(0);
+ nsSupportsArray();
+ NS_GetNumberOfAtoms();
+ NS_NewPipe2(nsnull, nsnull, PR_FALSE, PR_FALSE, 0, 0, nsnull);
+ NS_NewInputStreamReadyEvent(nsnull, nsnull, nsnull);
+ NS_NewOutputStreamReadyEvent(nsnull, nsnull, nsnull);
+ NS_AsyncCopy(nsnull, nsnull, nsnull, NS_ASYNCCOPY_VIA_READSEGMENTS, 0, nsnull, nsnull);
+ PL_DHashStubEnumRemove(nsnull, nsnull, nsnull, nsnull);
+ nsIDHashKey::HashKey(nsnull);
+ nsFixedSizeAllocator a;
+ nsRecyclingAllocator recyclingAllocator(2);
+ a.Init(0, 0, 0, 0, 0);
+ a.Alloc(0);
+ a.Free(0, 0);
+ nsIThread::GetCurrent(nsnull);
+ nsDeque(nsnull);
+ nsTraceRefcnt::LogAddCOMPtr(nsnull, nsnull);
+ nsTraceRefcntImpl::DumpStatistics();
+ NS_NewEmptyEnumerator(nsnull);
+ new nsArrayEnumerator(nsnull);
+ NS_QuickSort(nsnull, 0, 0, nsnull, nsnull);
+ nsString();
+ nsProxyObject(nsnull, 0, nsnull);
+ NS_ProxyRelease(nsnull, nsnull, PR_FALSE);
+ XPT_DoString(nsnull, nsnull, nsnull);
+ XPT_DoHeader(nsnull, nsnull, nsnull);
+#ifdef DEBUG
+ PurePrintf(0);
+#endif
+ XPTC_InvokeByIndex(nsnull, 0, 0, nsnull);
+ xptc_dummy();
+ xptc_dummy2();
+ XPTI_GetInterfaceInfoManager();
+ NS_NewGenericFactory(nsnull, nsnull);
+ NS_NewGenericModule2(nsnull, nsnull);
+ NS_GetWeakReference(nsnull);
+ nsCOMPtr<nsISupports> dummyFoo(do_GetInterface(nsnull));
+ NS_NewByteArrayInputStream(nsnull, nsnull, 0);
+ NS_NewStorageStream(0,0, nsnull);
+ nsString foo;
+ nsPrintfCString bar("");
+ nsLinebreakConverter::ConvertStringLineBreaks(foo,
+ nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent);
+ NS_NewLocalFile(nsString(), PR_FALSE, nsnull);
+ NS_NewNativeLocalFile(nsCString(), PR_FALSE, nsnull);
+ new nsProcess();
+ nsStaticCaseInsensitiveNameTable();
+ nsAutoString str1;
+ str1.AssignWithConversion(nsnull, 0);
+ nsCAutoString str2;
+ ToNewUnicode(str1);
+ ToNewUnicode(str2);
+ ToNewCString(str1);
+ ToNewCString(str2);
+ PL_DHashTableFinish(nsnull);
+ NS_NewInputStreamTee(nsnull, nsnull, nsnull);
+ NS_NewArray(nsnull);
+ nsCOMArray<nsISupports> dummyArray;
+ NS_NewArray(nsnull, dummyArray);
+ NS_NewArrayEnumerator(nsnull, dummyArray);
+ new nsVariant();
+ nsUnescape(nsnull);
+ nsEscape(nsnull, url_XAlphas);
+ nsStringArray array;
+ NS_NewStringEnumerator(nsnull, &array);
+ NS_NewAdoptingStringEnumerator(nsnull, &array);
+ nsCStringArray carray;
+ NS_NewUTF8StringEnumerator(nsnull, &carray);
+ NS_NewAdoptingUTF8StringEnumerator(nsnull, &carray);
+ nsVoidableString str3;
+ nsCStringContainer sc1;
+ NS_CStringContainerInit(sc1);
+ NS_CStringContainerFinish(sc1);
+ NS_CStringGetData(str2, nsnull, nsnull);
+ NS_CStringSetData(str2, nsnull, 0);
+ NS_CStringSetDataRange(str2, 0, 0, nsnull, 0);
+ NS_CStringCopy(str2, str2);
+ nsStringContainer sc2;
+ NS_StringContainerInit(sc2);
+ NS_StringContainerFinish(sc2);
+ NS_StringGetData(str1, nsnull, nsnull);
+ NS_StringSetData(str1, nsnull, 0);
+ NS_StringSetDataRange(str1, 0, 0, nsnull, 0);
+ NS_StringCopy(str1, str1);
+ {
+ nsAdoptingCString foo, bar;
+ foo = bar;
+ }
+ {
+ nsAdoptingString foo, bar;
+ foo = bar;
+ }
+ NS_UTF16ToCString(str1, NS_CSTRING_ENCODING_ASCII, str2);
+ NS_CStringToUTF16(str2, NS_CSTRING_ENCODING_ASCII, str1);
+}
diff --git a/src/libs/xpcom18a4/xpcom/build/malloc.c b/src/libs/xpcom18a4/xpcom/build/malloc.c
new file mode 100644
index 00000000..96691829
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/malloc.c
@@ -0,0 +1,5126 @@
+#define USE_MALLOC_LOCK
+#define DEFAULT_TRIM_THRESHOLD (256 * 1024)
+
+/* ---------- To make a malloc.h, start cutting here ------------ */
+
+/*
+ ****************************************************************
+ * THIS IS A PRERELEASE. It has not yet been tested adequately. *
+ * If you use it, please send back comments, suggestions, *
+ * performance reports, etc. *
+ ****************************************************************
+*/
+
+/*
+ A version (aka dlmalloc) of malloc/free/realloc written by Doug
+ Lea and released to the public domain. Use this code without
+ permission or acknowledgement in any way you wish. Send questions,
+ comments, complaints, performance data, etc to dl@cs.oswego.edu
+
+* VERSION 2.7.0pre7 Wed Jan 10 13:33:01 2001 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+* Quickstart
+
+ This library is all in one file to simplify the most common usage:
+ ftp it, compile it (-O), and link it into another program. All
+ of the compile-time options default to reasonable values for use on
+ most unix platforms. Compile -DWIN32 for reasonable defaults on windows.
+ You might later want to step through various compile options.
+
+* Why use this malloc?
+
+ This is not the fastest, most space-conserving, most portable, or
+ most tunable malloc ever written. However it is among the fastest
+ while also being among the most space-conserving, portable and tunable.
+ Consistent balance across these factors results in a good general-purpose
+ allocator for malloc-intensive programs.
+
+ The main properties of the algorithms are:
+ * For large (>= 512 bytes) requests, it is a pure best-fit allocator,
+ with ties normally decided via FIFO (i.e. least recently used).
+ * For small (<= 64 bytes by default) requests, it is a caching
+ allocator, that maintains pools of quickly recycled chunks.
+ * In between, and for combinations of large and small requests, it does
+ the best it can trying to meet both goals at once.
+
+ Compared to 2.6.X versions, this version is generally faster,
+ especially for programs that allocate and free many small chunks.
+
+ For a longer but slightly out of date high-level description, see
+ http://gee.cs.oswego.edu/dl/html/malloc.html
+
+ You may already by default be using a c library containing a malloc
+ that is somehow based on some version of this malloc (for example in
+ linux). You might still want to use the one in this file in order to
+ customize settings or to avoid overheads associated with library
+ versions.
+
+* Synopsis of public routines
+
+ (Much fuller descriptions are contained in the program documentation below.)
+
+ malloc(size_t n);
+ Return a pointer to a newly allocated chunk of at least n bytes, or null
+ if no space is available.
+ free(Void_t* p);
+ Release the chunk of memory pointed to by p, or no effect if p is null.
+ realloc(Void_t* p, size_t n);
+ Return a pointer to a chunk of size n that contains the same data
+ as does chunk p up to the minimum of (n, p's size) bytes, or null
+ if no space is available. The returned pointer may or may not be
+ the same as p. If p is null, equivalent to malloc. Unless the
+ #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
+ size argument of zero (re)allocates a minimum-sized chunk.
+ memalign(size_t alignment, size_t n);
+ Return a pointer to a newly allocated chunk of n bytes, aligned
+ in accord with the alignment argument, which must be a power of
+ two.
+ valloc(size_t n);
+ Equivalent to memalign(pagesize, n), where pagesize is the page
+ size of the system (or as near to this as can be figured out from
+ all the includes/defines below.)
+ pvalloc(size_t n);
+ Equivalent to valloc(minimum-page-that-holds(n)), that is,
+ round up n to nearest pagesize.
+ calloc(size_t unit, size_t quantity);
+ Returns a pointer to quantity * unit bytes, with all locations
+ set to zero.
+ cfree(Void_t* p);
+ Equivalent to free(p).
+ malloc_trim(size_t pad);
+ Release all but pad bytes of freed top-most memory back
+ to the system. Return 1 if successful, else 0.
+ malloc_usable_size(Void_t* p);
+ Report the number usable allocated bytes associated with allocated
+ chunk p. This may or may not report more bytes than were requested,
+ due to alignment and minimum size constraints.
+ malloc_stats();
+ Prints brief summary statistics on stderr.
+ mallinfo()
+ Returns (by copy) a struct containing various summary statistics.
+ mallopt(int parameter_number, int parameter_value)
+ Changes one of the tunable parameters described below. Returns
+ 1 if successful in changing the parameter, else 0.
+
+* Vital statistics:
+
+ Assumed pointer representation: 4 or 8 bytes
+ (Thanks to Wolfram Gloger for contributing most of the
+ changes supporting dual 4/8.)
+
+ Assumed size_t representation: 4 or 8 bytes
+ Note that size_t is allowed to be 4 bytes even if pointers are 8.
+ You can adjust this by defining INTERNAL_SIZE_T
+
+ Alignment: 2 * sizeof(size_t)
+ (i.e., 8 byte alignment with 4byte size_t). This suffices for
+ nearly all current machines and C compilers. However, you can
+ define MALLOC_ALIGNMENT to be wider than this if necessary.
+
+ Minimum overhead per allocated chunk: 4 or 8 bytes
+ Each malloced chunk has a hidden word of overhead holding size
+ and status information.
+
+ Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead)
+ 8-byte ptrs: 24/32 bytes (including, 4/8 overhead)
+
+ When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
+ ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
+ needed; 4 (8) for a trailing size field and 8 (16) bytes for
+ free list pointers. Thus, the minimum allocatable size is
+ 16/24/32 bytes.
+
+ Even a request for zero bytes (i.e., malloc(0)) returns a
+ pointer to something of the minimum allocatable size.
+
+ The maximum overhead wastage (i.e., number of extra bytes
+ allocated than were requested in malloc) is less than or equal
+ to the minimum size, except for requests >= mmap_threshold that
+ are serviced via mmap(), where the worst case wastage is 2 *
+ sizeof(size_t) bytes plus the remainder from a system page (the
+ minimal mmap unit); typically 4096 bytes.
+
+ Maximum allocated size: 4-byte size_t: 2^31 minus about two pages
+ 8-byte size_t: 2^63 minus about two pages
+
+ It is assumed that (possibly signed) size_t values suffice
+ to represent chunk sizes. `Possibly signed' is due to the fact
+ that `size_t' may be defined on a system as either a signed or
+ an unsigned type. The ISO C standard says that it must be
+ unsigned, but a few systems are known not to adhere to this.
+ Additionally, even when size_t is unsigned, sbrk (which is by
+ default used to obtain memory from system) accepts signed
+ arguments, and may not be able to handle size_t-wide arguments
+ with negative sign bit. To be conservative, values that would
+ appear as negative after accounting for overhead and alignment
+ are rejected.
+
+ Requests for sizes outside this range will perform an optional
+ failure action and then return null. (Requests may also
+ also fail because a system is out of memory.)
+
+ Thread-safety: NOT thread-safe unless USE_MALLOC_LOCK defined
+
+ When USE_MALLOC_LOCK is defined, wrappers are created to
+ surround every public call with either a pthread mutex or
+ a win32 critical section (depending on WIN32). This is not
+ especially fast, and can be a major bottleneck in programs with
+ many threads. It is designed only to provide minimal protection
+ in concurrent environments, and to provide a basis for
+ extensions. If you are using malloc in a concurrent program,
+ you would be far better off obtaining ptmalloc, which is
+ derived from a version of this malloc, and is well-tuned for
+ concurrent programs. (See http://www.malloc.de)
+
+ Compliance: I believe it is compliant with the 1997 Single Unix Specification
+
+ (See http://www.opennc.org). Probably other standards as well.
+
+* Limitations
+
+ Here are some features that are NOT currently supported
+
+ * No automated mechanism for fully checking that all accesses
+ to malloced memory stay within their bounds. However, there
+ are several add-ons and adaptations of this or other mallocs
+ available that do this.
+ * No support for compaction.
+
+* Synopsis of compile-time options:
+
+ People have reported using previous versions of this malloc on all
+ versions of Unix, sometimes by tweaking some of the defines
+ below. It has been tested most extensively on Solaris and
+ Linux. It is also reported to work on WIN32 platforms.
+ People also report using it in stand-alone embedded systems.
+
+ The implementation is in straight, hand-tuned ANSI C. It is not
+ at all modular. (Sorry!) It uses a lot of macros. To be at all
+ usable, this code should be compiled using an optimizing compiler
+ (for example gcc -O3) that can simplify expressions and control
+ paths. (FAQ: some macros import variables as arguments rather than
+ declare locals because people reported that some debuggers
+ otherwise get confused.)
+
+ OPTION DEFAULT VALUE
+
+ Compilation Environment options:
+
+ __STD_C derived from C compiler defines
+ WIN32 NOT defined
+ HAVE_MEMCPY defined
+ USE_MEMCPY 1 if HAVE_MEMCPY is defined
+ HAVE_MMAP defined as 1
+ MMAP_AS_MORECORE_SIZE (1024 * 1024)
+ HAVE_MREMAP defined as 0 unless linux defined
+ malloc_getpagesize derived from system #includes, or 4096 if not
+ HAVE_USR_INCLUDE_MALLOC_H NOT defined
+ LACKS_UNISTD_H NOT defined unless WIN32
+ LACKS_SYS_PARAM_H NOT defined unless WIN32
+ LACKS_SYS_MMAN_H NOT defined unless WIN32
+
+ Changing default word sizes:
+
+ INTERNAL_SIZE_T size_t
+ MALLOC_ALIGNMENT 2 * sizeof(INTERNAL_SIZE_T)
+
+ Configuration and functionality options:
+
+ USE_DL_PREFIX NOT defined
+ USE_PUBLIC_MALLOC_WRAPPERS NOT defined
+ USE_MALLOC_LOCK NOT defined
+ DEBUG NOT defined
+ REALLOC_ZERO_BYTES_FREES NOT defined
+ MALLOC_FAILURE_ACTION errno = ENOMEM, if __STD_C defined, else no-op
+ TRIM_FASTBINS 0
+
+ Options for customizing MORECORE:
+
+ MORECORE sbrk
+ MORECORE_CONTIGUOUS 1
+
+ Tuning options that are also dynamically changeable via mallopt:
+
+ DEFAULT_MXFAST 64
+ DEFAULT_TRIM_THRESHOLD 128 * 1024
+ DEFAULT_TOP_PAD 0
+ DEFAULT_MMAP_THRESHOLD 128 * 1024
+ DEFAULT_MMAP_MAX 256
+
+ There are several other #defined constants and macros that you
+ probably don't want to touch unless you are extending or adapting malloc.
+
+*/
+#include "xpcom-private.h"
+
+
+
+/*
+ WIN32 sets up defaults for MS environment and compilers.
+ Otherwise defaults are for unix.
+*/
+
+/* #define WIN32 */
+
+#ifdef WIN32
+
+#include <windows.h>
+
+/* Win32 doesn't supply or need the following headers */
+#define LACKS_UNISTD_H
+#define LACKS_SYS_PARAM_H
+#define LACKS_SYS_MMAN_H
+
+/* Use the supplied emulation of sbrk */
+#define MORECORE sbrk
+#define MORECORE_CONTIGUOUS 1
+#define MORECORE_FAILURE ((void*)(-1))
+
+/* Use the supplied emulation mmap, munmap */
+#define HAVE_MMAP 1
+#define MUNMAP_FAILURE (-1)
+/* These values don't really matter in windows mmap emulation */
+#define MAP_PRIVATE 1
+#define MAP_ANONYMOUS 2
+#define PROT_READ 1
+#define PROT_WRITE 2
+
+/* Emulation functions defined at the end of this file */
+
+/* If USE_MALLOC_LOCK, use supplied critical-section-based lock functions */
+#ifdef USE_MALLOC_LOCK
+static int slwait(int *sl);
+static int slrelease(int *sl);
+#endif
+
+static long getpagesize(void);
+static long getregionsize(void);
+static void *sbrk(long size);
+static void *mmap(void *ptr, long size, long prot, long type, long handle, long arg);
+static long munmap(void *ptr, long size);
+
+static void vminfo (unsigned long *free, unsigned long *reserved, unsigned long *committed);
+static int cpuinfo (int whole, unsigned long *kernel, unsigned long *user);
+
+#endif
+
+
+
+/*
+ __STD_C should be nonzero if using ANSI-standard C compiler, a C++
+ compiler, or a C compiler sufficiently close to ANSI to get away
+ with it.
+*/
+
+#ifndef __STD_C
+#ifdef __STDC__
+#define __STD_C 1
+#else
+#if __cplusplus
+#define __STD_C 1
+#else
+#define __STD_C 0
+#endif /*__cplusplus*/
+#endif /*__STDC__*/
+#endif /*__STD_C*/
+
+
+/*
+ Void_t* is the pointer type that malloc should say it returns
+*/
+
+#ifndef Void_t
+#if (__STD_C || defined(WIN32))
+#define Void_t void
+#else
+#define Void_t char
+#endif
+#endif /*Void_t*/
+
+#if __STD_C
+#include <stddef.h> /* for size_t */
+#else
+#include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* define LACKS_UNISTD_H if your system does not have a <unistd.h>. */
+
+/* #define LACKS_UNISTD_H */
+
+#ifndef LACKS_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* define LACKS_SYS_PARAM_H if your system does not have a <sys/param.h>. */
+
+/* #define LACKS_SYS_PARAM_H */
+
+
+#include <stdio.h> /* needed for malloc_stats */
+#include <errno.h> /* needed for optional MALLOC_FAILURE_ACTION */
+
+
+/*
+ Debugging:
+
+ Because freed chunks may be overwritten with bookkeeping fields, this
+ malloc will often die when freed memory is overwritten by user
+ programs. This can be very effective (albeit in an annoying way)
+ in helping track down dangling pointers.
+
+ If you compile with -DDEBUG, a number of assertion checks are
+ enabled that will catch more memory errors. You probably won't be
+ able to make much sense of the actual assertion errors, but they
+ should help you locate incorrectly overwritten memory. The
+ checking is fairly extensive, and will slow down execution
+ noticeably. Calling malloc_stats or mallinfo with DEBUG set will
+ attempt to check every non-mmapped allocated and free chunk in the
+ course of computing the summmaries. (By nature, mmapped regions
+ cannot be checked very much automatically.)
+
+ Setting DEBUG may also be helpful if you are trying to modify
+ this code. The assertions in the check routines spell out in more
+ detail the assumptions and invariants underlying the algorithms.
+
+*/
+
+#if DEBUG
+#include <assert.h>
+#else
+#define assert(x) ((void)0)
+#endif
+
+
+/*
+ INTERNAL_SIZE_T is the word-size used for internal bookkeeping
+ of chunk sizes.
+
+ The default version is the same as size_t.
+
+ While not strictly necessary, it is best to define this as an
+ unsigned type, even if size_t is a signed type. This may avoid some
+ artificial size limitations on some systems.
+
+ On a 64-bit machine, you may be able to reduce malloc overhead by
+ defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the
+ expense of not being able to handle more than 2^32 of malloced
+ space. If this limitation is acceptable, you are encouraged to set
+ this unless you are on a platform requiring 16byte alignments. In
+ this case the alignment requirements turn out to negate any
+ potential advantages of decreasing size_t word size.
+
+ Note to implementors: To deal with all this, comparisons and
+ difference computations among INTERNAL_SIZE_Ts should normally cast
+ INTERNAL_SIZE_T's to long or unsigned long, as appropriate, being
+ aware of the fact that casting an unsigned int to a wider long does not
+ sign-extend. (This also makes checking for negative numbers awkward.)
+
+*/
+
+#ifndef INTERNAL_SIZE_T
+#define INTERNAL_SIZE_T size_t
+#endif
+
+/* The corresponding word size */
+#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
+
+
+/*
+ MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.
+ It must be a power of two at least 2 * SIZE_SZ, even on machines
+ for which smaller alignments would suffice. It may be defined as
+ larger than this though. (Note however that code and data structures
+ are optimized for the case of 8-byte alignment.)
+
+*/
+
+ /* #define MALLOC_ALIGNMENT 16 */
+
+#ifndef MALLOC_ALIGNMENT
+#define MALLOC_ALIGNMENT (2 * SIZE_SZ)
+#endif
+
+/* The corresponding bit mask value */
+#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
+
+
+/*
+ REALLOC_ZERO_BYTES_FREES should be set if a call to
+ realloc with zero bytes should be the same as a call to free.
+ Some people think it should. Otherwise, since this malloc
+ returns a unique pointer for malloc(0), so does realloc(p, 0).
+*/
+
+/* #define REALLOC_ZERO_BYTES_FREES */
+
+
+/*
+ USE_DL_PREFIX will prefix all public routines with the string 'dl'.
+ This is necessary when you only want to use this malloc in one part
+ of a program, using your regular system malloc elsewhere.
+*/
+
+/* #define USE_DL_PREFIX */
+
+
+/*
+ USE_MALLOC_LOCK causes wrapper functions to surround each
+ callable routine with pthread mutex lock/unlock.
+
+ USE_MALLOC_LOCK forces USE_PUBLIC_MALLOC_WRAPPERS to be defined
+*/
+
+/* #define USE_MALLOC_LOCK */
+
+
+/*
+ If USE_PUBLIC_MALLOC_WRAPPERS is defined, every public routine is
+ actually a wrapper function that first calls MALLOC_PREACTION, then
+ calls the internal routine, and follows it with
+ MALLOC_POSTACTION. This is needed for locking, but you can also use
+ this, without USE_MALLOC_LOCK, for purposes of interception,
+ instrumentation, etc. It is a sad fact that using wrappers often
+ noticeably degrades performance of malloc-intensive programs.
+*/
+
+#ifdef USE_MALLOC_LOCK
+#define USE_PUBLIC_MALLOC_WRAPPERS
+#else
+/* #define USE_PUBLIC_MALLOC_WRAPPERS */
+#endif
+
+
+
+
+/*
+ HAVE_MEMCPY should be defined if you are not otherwise using
+ ANSI STD C, but still have memcpy and memset in your C library
+ and want to use them in calloc and realloc. Otherwise simple
+ macro versions are defined below.
+
+ USE_MEMCPY should be defined as 1 if you actually want to
+ have memset and memcpy called. People report that the macro
+ versions are faster than libc versions on some systems.
+
+ Even if USE_MEMCPY is set to 1, loops to copy/clear small chunks
+ (of <= 36 bytes) are manually unrolled in realloc and calloc.
+*/
+
+#define HAVE_MEMCPY
+
+#ifndef USE_MEMCPY
+#ifdef HAVE_MEMCPY
+#define USE_MEMCPY 1
+#else
+#define USE_MEMCPY 0
+#endif
+#endif
+
+
+#if (__STD_C || defined(HAVE_MEMCPY))
+
+#ifdef WIN32
+ /*
+ On Win32 platforms, 'memset()' and 'memcpy()' are already declared in
+ 'windows.h'
+ */
+#else
+#if __STD_C
+void* memset(void*, int, size_t);
+void* memcpy(void*, const void*, size_t);
+void* memmove(void*, const void*, size_t);
+#else
+Void_t* memset();
+Void_t* memcpy();
+Void_t* memmove();
+#endif
+#endif
+#endif
+
+
+/*
+ MALLOC_FAILURE_ACTION is the action to take before "return 0" when
+ malloc fails to be able to return memory, either because memory is
+ exhausted or because of illegal arguments.
+
+ By default, sets errno if running on STD_C platform, else does nothing.
+*/
+
+#ifndef MALLOC_FAILURE_ACTION
+#if __STD_C
+#define MALLOC_FAILURE_ACTION \
+ errno = ENOMEM;
+
+#else
+
+#define MALLOC_FAILURE_ACTION
+#endif
+#endif
+
+/*
+ Define HAVE_MMAP as true to optionally make malloc() use mmap() to
+ allocate very large blocks. These will be returned to the
+ operating system immediately after a free(). Also, if mmap
+ is available, it is used as a backup strategy in cases where
+ MORECORE fails to provide space from system.
+
+ This malloc is best tuned to work with mmap for large requests.
+ If you do not have mmap, allocation of very large chunks (1MB
+ or so) may be slower than you'd like.
+*/
+
+#ifndef HAVE_MMAP
+#define HAVE_MMAP 1
+#endif
+
+/*
+ MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if
+ sbrk fails, and mmap is used as a backup (which is done only if
+ HAVE_MMAP). The value must be a multiple of page size. This
+ backup strategy generally applies only when systems have "holes" in
+ address space, so sbrk cannot perform contiguous expansion, but
+ there is still space available on system. On systems for which
+ this is known to be useful (i.e. most linux kernels), this occurs
+ only when programs allocate huge amounts of memory. Between this,
+ and the fact that mmap regions tend to be limited, the size should
+ be large, to avoid too many mmap calls and thus avoid running out
+ of kernel resources.
+*/
+
+#ifndef MMAP_AS_MORECORE_SIZE
+#define MMAP_AS_MORECORE_SIZE (1024 * 1024)
+#endif
+
+
+
+/*
+ Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
+ large blocks. This is currently only possible on Linux with
+ kernel versions newer than 1.3.77.
+*/
+
+#ifndef HAVE_MREMAP
+#ifdef linux
+#define HAVE_MREMAP 1
+#else
+#define HAVE_MREMAP 0
+#endif
+
+#endif /* HAVE_MMAP */
+
+
+/*
+
+ This version of malloc supports the standard SVID/XPG mallinfo
+ routine that returns a struct containing usage properties and
+ statistics. It should work on any SVID/XPG compliant system that has
+ a /usr/include/malloc.h defining struct mallinfo. (If you'd like to
+ install such a thing yourself, cut out the preliminary declarations
+ as described above and below and save them in a malloc.h file. But
+ there's no compelling reason to bother to do this.)
+
+ The main declaration needed is the mallinfo struct that is returned
+ (by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a
+ bunch of field that are not even meaningful in this version of
+ malloc. These fields are are instead filled by mallinfo() with
+ other numbers that might be of interest.
+
+ HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
+ /usr/include/malloc.h file that includes a declaration of struct
+ mallinfo. If so, it is included; else an SVID2/XPG2 compliant
+ version is declared below. These must be precisely the same for
+ mallinfo() to work.
+
+*/
+
+/* #define HAVE_USR_INCLUDE_MALLOC_H */
+
+#ifdef HAVE_USR_INCLUDE_MALLOC_H
+#include "/usr/include/malloc.h"
+#else
+
+/* SVID2/XPG mallinfo structure */
+
+struct mallinfo {
+ int arena; /* non-mmapped space allocated from system */
+ int ordblks; /* number of free chunks */
+ int smblks; /* number of fastbin blocks */
+ int hblks; /* number of mmapped regions */
+ int hblkhd; /* space in mmapped regions */
+ int usmblks; /* maximum total allocated space */
+ int fsmblks; /* space available in freed fastbin blocks */
+ int uordblks; /* total allocated space */
+ int fordblks; /* total free space */
+ int keepcost; /* top-most, releasable (via malloc_trim) space */
+};
+
+/* SVID2/XPG mallopt options */
+
+#define M_MXFAST 1 /* Set maximum fastbin size */
+#define M_NLBLKS 2 /* UNUSED in this malloc */
+#define M_GRAIN 3 /* UNUSED in this malloc */
+#define M_KEEP 4 /* UNUSED in this malloc */
+
+
+#endif
+
+
+/* Additional mallopt options supported in this malloc */
+
+#ifndef M_TRIM_THRESHOLD
+#define M_TRIM_THRESHOLD -1
+#endif
+
+#ifndef M_TOP_PAD
+#define M_TOP_PAD -2
+#endif
+
+#ifndef M_MMAP_THRESHOLD
+#define M_MMAP_THRESHOLD -3
+#endif
+
+#ifndef M_MMAP_MAX
+#define M_MMAP_MAX -4
+#endif
+
+
+/*
+ MXFAST is the maximum request size used for "fastbins", special bins
+ that hold returned chunks without consolidating their spaces. This
+ enables future requests for chunks of the same size to be handled
+ very quickly, but can increase fragmentation, and thus increase the
+ overall memory footprint of a program.
+
+ This malloc manages fastbins very conservatively yet still
+ efficiently, so fragmentation is rarely a problem for values less
+ than or equal to the default. The maximum supported value of MXFAST
+ is 80. You wouldn't want it any higher than this anyway. Fastbins
+ are designed especially for use with many small structs, objects or
+ strings -- the default handles structs/objects/arrays with sizes up
+ to 8 4byte fields, or small strings representing words, tokens,
+ etc. Using fastbins for larger objects normally worsens
+ fragmentation without improving speed.
+
+ MXFAST is set in REQUEST size units. It is internally used in
+ chunksize units, which adds padding and alignment. You can reduce
+ MXFAST to 0 to disable all use of fastbins. This causes the malloc
+ algorithm to be a close approximation of fifo-best-fit in all cases,
+ not just for larger requests, but will generally cause it to be
+ slower.
+
+*/
+
+#ifndef DEFAULT_MXFAST
+#define DEFAULT_MXFAST 64
+#endif
+
+
+/*
+ M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
+ to keep before releasing via malloc_trim in free().
+
+ Automatic trimming is mainly useful in long-lived programs.
+ Because trimming via sbrk can be slow on some systems, and can
+ sometimes be wasteful (in cases where programs immediately
+ afterward allocate more large chunks) the value should be high
+ enough so that your overall system performance would improve by
+ releasing.
+
+ The trim threshold and the mmap control parameters (see below)
+ can be traded off with one another. Trimming and mmapping are
+ two different ways of releasing unused memory back to the
+ system. Between these two, it is often possible to keep
+ system-level demands of a long-lived program down to a bare
+ minimum. For example, in one test suite of sessions measuring
+ the XF86 X server on Linux, using a trim threshold of 128K and a
+ mmap threshold of 192K led to near-minimal long term resource
+ consumption.
+
+ If you are using this malloc in a long-lived program, it should
+ pay to experiment with these values. As a rough guide, you
+ might set to a value close to the average size of a process
+ (program) running on your system. Releasing this much memory
+ would allow such a process to run in memory. Generally, it's
+ worth it to tune for trimming rather tham memory mapping when a
+ program undergoes phases where several large chunks are
+ allocated and released in ways that can reuse each other's
+ storage, perhaps mixed with phases where there are no such
+ chunks at all. And in well-behaved long-lived programs,
+ controlling release of large blocks via trimming versus mapping
+ is usually faster.
+
+ However, in most programs, these parameters serve mainly as
+ protection against the system-level effects of carrying around
+ massive amounts of unneeded memory. Since frequent calls to
+ sbrk, mmap, and munmap otherwise degrade performance, the default
+ parameters are set to relatively high values that serve only as
+ safeguards.
+
+ The default trim value is high enough to cause trimming only in
+ fairly extreme (by current memory consumption standards) cases.
+ It must be greater than page size to have any useful effect. To
+ disable trimming completely, you can set to (unsigned long)(-1);
+
+ Trim settings interact with fastbin (MXFAST) settings: Unless
+ TRIM_FASTBINS is defined, automatic trimming never takes place upon
+ freeing a chunk with size less than or equal to MXFAST. Trimming is
+ instead delayed until subsequent freeing of larger chunks. However,
+ you can still force an attempted trim by calling malloc_trim.
+
+ Also, trimming is not generally possible in cases where
+ the main arena is obtained via mmap.
+
+*/
+
+
+#ifndef DEFAULT_TRIM_THRESHOLD
+#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
+#endif
+
+
+
+/*
+ M_TOP_PAD is the amount of extra `padding' space to allocate or
+ retain whenever sbrk is called. It is used in two ways internally:
+
+ * When sbrk is called to extend the top of the arena to satisfy
+ a new malloc request, this much padding is added to the sbrk
+ request.
+
+ * When malloc_trim is called automatically from free(),
+ it is used as the `pad' argument.
+
+ In both cases, the actual amount of padding is rounded
+ so that the end of the arena is always a system page boundary.
+
+ The main reason for using padding is to avoid calling sbrk so
+ often. Having even a small pad greatly reduces the likelihood
+ that nearly every malloc request during program start-up (or
+ after trimming) will invoke sbrk, which needlessly wastes
+ time.
+
+ Automatic rounding-up to page-size units is normally sufficient
+ to avoid measurable overhead, so the default is 0. However, in
+ systems where sbrk is relatively slow, it can pay to increase
+ this value, at the expense of carrying around more memory than
+ the program needs.
+
+*/
+
+#ifndef DEFAULT_TOP_PAD
+#define DEFAULT_TOP_PAD (0)
+#endif
+
+/*
+
+ M_MMAP_THRESHOLD is the request size threshold for using mmap()
+ to service a request. Requests of at least this size that cannot
+ be allocated using already-existing space will be serviced via mmap.
+ (If enough normal freed space already exists it is used instead.)
+
+ Using mmap segregates relatively large chunks of memory so that
+ they can be individually obtained and released from the host
+ system. A request serviced through mmap is never reused by any
+ other request (at least not directly; the system may just so
+ happen to remap successive requests to the same locations).
+
+ Segregating space in this way has the benefit that mmapped space
+ can ALWAYS be individually released back to the system, which
+ helps keep the system level memory demands of a long-lived
+ program low. Mapped memory can never become `locked' between
+ other chunks, as can happen with normally allocated chunks, which
+ means that even trimming via malloc_trim would not release them.
+
+ However, it has the disadvantages that:
+
+ 1. The space cannot be reclaimed, consolidated, and then
+ used to service later requests, as happens with normal chunks.
+ 2. It can lead to more wastage because of mmap page alignment
+ requirements
+ 3. It causes malloc performance to be more dependent on host
+ system memory management support routines which may vary in
+ implementation quality and may impose arbitrary
+ limitations. Generally, servicing a request via normal
+ malloc steps is faster than going through a system's mmap.
+
+ All together, these considerations should lead you to use mmap
+ only for relatively large requests.
+
+*/
+
+
+#ifndef DEFAULT_MMAP_THRESHOLD
+#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
+#endif
+
+/*
+ M_MMAP_MAX is the maximum number of requests to simultaneously
+ service using mmap. This parameter exists because:
+
+ 1. Some systems have a limited number of internal tables for
+ use by mmap.
+ 2. In most systems, overreliance on mmap can degrade overall
+ performance.
+ 3. If a program allocates many large regions, it is probably
+ better off using normal sbrk-based allocation routines that
+ can reclaim and reallocate normal heap memory.
+
+ Setting to 0 disables use of mmap for servicing large requests. If
+ HAVE_MMAP is not set, the default value is 0, and attempts to set it
+ to non-zero values in mallopt will fail.
+*/
+
+
+
+#ifndef DEFAULT_MMAP_MAX
+#if HAVE_MMAP
+#define DEFAULT_MMAP_MAX (256)
+#else
+#define DEFAULT_MMAP_MAX (0)
+#endif
+#endif
+
+
+/*
+ TRIM_FASTBINS controls whether free() of a very small chunk can
+ immediately lead to trimming. Setting to true (1) can reduce memory
+ footprint, but will almost always slow down (by a few percent)
+ programs that use a lot of small chunks.
+
+ Define this only if you are willing to give up some speed to more
+ aggressively reduce system-level memory footprint when releasing
+ memory in programs that use many small chunks. You can get
+ essentially the same effect by setting MXFAST to 0, but this can
+ lead to even greater slowdowns in programs using many small chunks.
+ TRIM_FASTBINS is an in-between compile-time option, that disables
+ only those chunks bordering topmost memory from being placed in
+ fastbins.
+
+*/
+
+
+#ifndef TRIM_FASTBINS
+#define TRIM_FASTBINS 0
+#endif
+
+
+/*
+ MORECORE-related declarations. By default, rely on sbrk
+*/
+
+
+#ifdef LACKS_UNISTD_H
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
+#if __STD_C
+extern Void_t* sbrk(ptrdiff_t);
+#else
+extern Void_t* sbrk();
+#endif
+#endif
+#endif
+
+/*
+ MORECORE is the name of the routine to call to obtain more memory
+ from the system. See below for general guidance on writing
+ alternative MORECORE functions, as well as a version for WIN32 and a
+ sample version for pre-OSX macos.
+*/
+
+#ifndef MORECORE
+#define MORECORE sbrk
+#endif
+
+
+/*
+ MORECORE_FAILURE is the value returned upon failure of MORECORE
+ as well as mmap. Since it cannot be an otherwise valid memory address,
+ and must reflect values of standard sys calls, you probably ought not
+ try to redefine it.
+*/
+
+#ifndef MORECORE_FAILURE
+#define MORECORE_FAILURE (-1)
+#endif
+
+/*
+ If MORECORE_CONTIGUOUS is true, take advantage of fact that
+ consecutive calls to MORECORE with positive arguments always return
+ contiguous increasing addresses. This is true of unix sbrk. Even
+ if not defined, when regions happen to be contiguous, malloc will
+ permit allocations spanning regions obtained from different
+ calls. But defining this when applicable enables some stronger
+ consistency checks and space efficiencies.
+*/
+
+
+#ifndef MORECORE_CONTIGUOUS
+#define MORECORE_CONTIGUOUS 1
+#endif
+
+
+/*
+ The system page size. To the extent possible, this malloc manages
+ memory from the system in page-size units. Note that this value is
+ cached during initialization into a field of malloc_state. So even
+ if malloc_getpagesize is a function, it is only called once.
+
+ The following mechanics for getpagesize were adapted from bsd/gnu
+ getpagesize.h. If none of the system-probes here apply, a value of
+ 4096 is used, which should be OK: If they don't apply, then using
+ the actual value probably doesn't impact performance.
+*/
+
+#ifndef malloc_getpagesize
+
+#ifndef LACKS_UNISTD_H
+# include <unistd.h>
+#endif
+
+# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
+# ifndef _SC_PAGE_SIZE
+# define _SC_PAGE_SIZE _SC_PAGESIZE
+# endif
+# endif
+
+# ifdef _SC_PAGE_SIZE
+# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
+# else
+# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+ extern size_t getpagesize();
+# define malloc_getpagesize getpagesize()
+# else
+# ifdef WIN32 /* use supplied emulation of getpagesize */
+# define malloc_getpagesize getpagesize()
+# else
+# ifndef LACKS_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+# ifdef EXEC_PAGESIZE
+# define malloc_getpagesize EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# ifndef CLSIZE
+# define malloc_getpagesize NBPG
+# else
+# define malloc_getpagesize (NBPG * CLSIZE)
+# endif
+# else
+# ifdef NBPC
+# define malloc_getpagesize NBPC
+# else
+# ifdef PAGESIZE
+# define malloc_getpagesize PAGESIZE
+# else /* just guess */
+# define malloc_getpagesize (4096)
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+
+/* Two-phase Name mangling */
+
+#ifndef USE_PUBLIC_MALLOC_WRAPPERS
+#define cALLOc public_cALLOc
+#define fREe public_fREe
+#define cFREe public_cFREe
+#define mALLOc public_mALLOc
+#define mEMALIGn public_mEMALIGn
+#define rEALLOc public_rEALLOc
+#define vALLOc public_vALLOc
+#define pVALLOc public_pVALLOc
+#define mALLINFo public_mALLINFo
+#define mALLOPt public_mALLOPt
+#define mTRIm public_mTRIm
+#define mSTATs public_mSTATs
+#define mUSABLe public_mUSABLe
+#endif
+
+#ifdef USE_DL_PREFIX
+#define public_cALLOc dlcalloc
+#define public_fREe dlfree
+#define public_cFREe dlcfree
+#define public_mALLOc dlmalloc
+#define public_mEMALIGn dlmemalign
+#define public_rEALLOc dlrealloc
+#define public_vALLOc dlvalloc
+#define public_pVALLOc dlpvalloc
+#define public_mALLINFo dlmallinfo
+#define public_mALLOPt dlmallopt
+#define public_mTRIm dlmalloc_trim
+#define public_mSTATs dlmalloc_stats
+#define public_mUSABLe dlmalloc_usable_size
+#else /* USE_DL_PREFIX */
+#define public_cALLOc calloc
+#define public_fREe free
+#define public_cFREe cfree
+#define public_mALLOc malloc
+#define public_mEMALIGn memalign
+#define public_rEALLOc realloc
+#define public_vALLOc valloc
+#define public_pVALLOc pvalloc
+#define public_mALLINFo mallinfo
+#define public_mALLOPt mallopt
+#define public_mTRIm malloc_trim
+#define public_mSTATs malloc_stats
+#define public_mUSABLe malloc_usable_size
+#endif /* USE_DL_PREFIX */
+
+#if __STD_C
+
+Void_t* public_mALLOc(size_t);
+void public_fREe(Void_t*);
+Void_t* public_rEALLOc(Void_t*, size_t);
+Void_t* public_mEMALIGn(size_t, size_t);
+Void_t* public_vALLOc(size_t);
+Void_t* public_pVALLOc(size_t);
+Void_t* public_cALLOc(size_t, size_t);
+void public_cFREe(Void_t*);
+int public_mTRIm(size_t);
+size_t public_mUSABLe(Void_t*);
+void public_mSTATs();
+int public_mALLOPt(int, int);
+struct mallinfo public_mALLINFo(void);
+#else
+Void_t* public_mALLOc();
+void public_fREe();
+Void_t* public_rEALLOc();
+Void_t* public_mEMALIGn();
+Void_t* public_vALLOc();
+Void_t* public_pVALLOc();
+Void_t* public_cALLOc();
+void public_cFREe();
+int public_mTRIm();
+size_t public_mUSABLe();
+void public_mSTATs();
+int public_mALLOPt();
+struct mallinfo public_mALLINFo();
+#endif
+
+
+#ifdef __cplusplus
+}; /* end of extern "C" */
+#endif
+
+
+
+/* ---------- To make a malloc.h, end cutting here ------------ */
+
+
+/* Declarations of internal utilities defined below */
+
+
+
+
+#ifdef USE_PUBLIC_MALLOC_WRAPPERS
+#if __STD_C
+
+static Void_t* mALLOc(size_t);
+static void fREe(Void_t*);
+static Void_t* rEALLOc(Void_t*, size_t);
+static Void_t* mEMALIGn(size_t, size_t);
+static Void_t* vALLOc(size_t);
+static Void_t* pVALLOc(size_t);
+static Void_t* cALLOc(size_t, size_t);
+static void cFREe(Void_t*);
+static int mTRIm(size_t);
+static size_t mUSABLe(Void_t*);
+static void mSTATs();
+static int mALLOPt(int, int);
+static struct mallinfo mALLINFo(void);
+#else
+static Void_t* mALLOc();
+static void fREe();
+static Void_t* rEALLOc();
+static Void_t* mEMALIGn();
+static Void_t* vALLOc();
+static Void_t* pVALLOc();
+static Void_t* cALLOc();
+static void cFREe();
+static int mTRIm();
+static size_t mUSABLe();
+static void mSTATs();
+static int mALLOPt();
+static struct mallinfo mALLINFo();
+#endif
+#endif
+
+
+
+/* ---------- public wrappers --------------- */
+
+#ifdef USE_PUBLIC_MALLOC_WRAPPERS
+
+/*
+ MALLOC_PREACTION and MALLOC_POSTACTION should be
+ defined to return 0 on success, and nonzero on failure.
+ The return value of MALLOC_POSTACTION is currently ignored
+ in wrapper functions since there is no reasonable default
+ action to take on failure.
+*/
+
+
+#ifdef USE_MALLOC_LOCK
+
+#ifdef WIN32
+
+static int mALLOC_MUTEx;
+
+#define MALLOC_PREACTION slwait(&mALLOC_MUTEx)
+#define MALLOC_POSTACTION slrelease(&mALLOC_MUTEx)
+
+#else
+
+#include <pthread.h>
+
+static pthread_mutex_t mALLOC_MUTEx = PTHREAD_MUTEX_INITIALIZER;
+
+#define MALLOC_PREACTION pthread_mutex_lock(&mALLOC_MUTEx)
+#define MALLOC_POSTACTION pthread_mutex_unlock(&mALLOC_MUTEx)
+
+#endif /* USE_MALLOC_LOCK */
+
+#else
+
+/* Substitute anything you like for these */
+
+#define MALLOC_PREACTION (0)
+#define MALLOC_POSTACTION (0)
+
+#endif
+
+Void_t* public_mALLOc(size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = mALLOc(bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+void public_fREe(Void_t* m) {
+ if (MALLOC_PREACTION != 0) {
+ return;
+ }
+ fREe(m);
+ if (MALLOC_POSTACTION != 0) {
+ }
+}
+
+Void_t* public_rEALLOc(Void_t* m, size_t bytes) {
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = rEALLOc(m, bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_mEMALIGn(size_t alignment, size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = mEMALIGn(alignment, bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_vALLOc(size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = vALLOc(bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_pVALLOc(size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = pVALLOc(bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_cALLOc(size_t n, size_t elem_size) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = cALLOc(n, elem_size);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+void public_cFREe(Void_t* m) {
+ if (MALLOC_PREACTION != 0) {
+ return;
+ }
+ cFREe(m);
+ if (MALLOC_POSTACTION != 0) {
+ }
+}
+
+int public_mTRIm(size_t s) {
+ int result;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ result = mTRIm(s);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return result;
+}
+
+
+size_t public_mUSABLe(Void_t* m) {
+ size_t result;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ result = mUSABLe(m);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return result;
+}
+
+
+void public_mSTATs() {
+ if (MALLOC_PREACTION != 0) {
+ return;
+ }
+ mSTATs();
+ if (MALLOC_POSTACTION != 0) {
+ }
+}
+
+struct mallinfo public_mALLINFo() {
+ struct mallinfo m;
+ if (MALLOC_PREACTION != 0) {
+ return m;
+ }
+ m = mALLINFo();
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+int public_mALLOPt(int p, int v) {
+ int result;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ result = mALLOPt(p, v);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return result;
+}
+
+#endif
+
+
+
+/* ------------- Optional versions of memcopy ---------------- */
+
+
+#if USE_MEMCPY
+
+#define MALLOC_COPY(dest, src, nbytes, overlap) \
+ ((overlap) ? memmove(dest, src, nbytes) : memcpy(dest, src, nbytes))
+#define MALLOC_ZERO(dest, nbytes) memset(dest, 0, nbytes)
+
+#else /* !USE_MEMCPY */
+
+/* Use Duff's device for good zeroing/copying performance. */
+
+#define MALLOC_ZERO(charp, nbytes) \
+do { \
+ INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp); \
+ long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
+ if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
+ switch (mctmp) { \
+ case 0: for(;;) { *mzp++ = 0; \
+ case 7: *mzp++ = 0; \
+ case 6: *mzp++ = 0; \
+ case 5: *mzp++ = 0; \
+ case 4: *mzp++ = 0; \
+ case 3: *mzp++ = 0; \
+ case 2: *mzp++ = 0; \
+ case 1: *mzp++ = 0; if(mcn <= 0) break; mcn--; } \
+ } \
+} while(0)
+
+/* For overlapping case, dest is always _below_ src. */
+
+#define MALLOC_COPY(dest,src,nbytes,overlap) \
+do { \
+ INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src; \
+ INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest; \
+ long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
+ if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
+ switch (mctmp) { \
+ case 0: for(;;) { *mcdst++ = *mcsrc++; \
+ case 7: *mcdst++ = *mcsrc++; \
+ case 6: *mcdst++ = *mcsrc++; \
+ case 5: *mcdst++ = *mcsrc++; \
+ case 4: *mcdst++ = *mcsrc++; \
+ case 3: *mcdst++ = *mcsrc++; \
+ case 2: *mcdst++ = *mcsrc++; \
+ case 1: *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; } \
+ } \
+} while(0)
+
+#endif
+
+/* ------------------ MMAP support ------------------ */
+
+
+#if HAVE_MMAP
+
+#include <fcntl.h>
+#ifndef LACKS_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+
+/*
+ Nearly all versions of mmap support MAP_ANONYMOUS,
+ so the following is unlikely to be needed, but is
+ supplied just in case.
+*/
+
+#ifndef MAP_ANONYMOUS
+
+static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
+
+#define MMAP(addr, size, prot, flags) ((dev_zero_fd < 0) ? \
+ (dev_zero_fd = open("/dev/zero", O_RDWR), \
+ mmap((addr), (size), (prot), (flags), dev_zero_fd, 0)) : \
+ mmap((addr), (size), (prot), (flags), dev_zero_fd, 0))
+
+#else
+
+#define MMAP(addr, size, prot, flags) \
+ (mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS, -1, 0))
+
+#endif
+
+#endif /* HAVE_MMAP */
+
+
+/* ---------- Alternative MORECORE functions ------------ */
+
+
+/*
+ General Requirements for MORECORE.
+
+ The MORECORE function must have the following properties:
+
+ If MORECORE_CONTIGUOUS is false:
+
+ * MORECORE must allocate in multiples of pagesize. It will
+ only be called with arguments that are multiples of pagesize.
+
+ * MORECORE must page-align. That is, MORECORE(0) must
+ return an address at a page boundary.
+
+ else (i.e. If MORECORE_CONTIGUOUS is true):
+
+ * Consecutive calls to MORECORE with positive arguments
+ return increasing addresses, indicating that space has been
+ contiguously extended.
+
+ * MORECORE need not allocate in multiples of pagesize.
+ Calls to MORECORE need not have args of multiples of pagesize.
+
+ * MORECORE need not page-align.
+
+ In either case:
+
+ * MORECORE may allocate more memory than requested. (Or even less,
+ but this will generally result in a malloc failure.)
+
+ * MORECORE must not allocate memory when given argument zero, but
+ instead return one past the end address of memory from previous
+ nonzero call. This malloc does NOT call MORECORE(0)
+ until at least one call with positive arguments is made, so
+ the initial value returned is not important.
+
+ * Even though consecutive calls to MORECORE need not return contiguous
+ addresses, it must be OK for malloc'ed chunks to span multiple
+ regions in those cases where they do happen to be contiguous.
+
+ * MORECORE need not handle negative arguments -- it may instead
+ just return MORECORE_FAILURE when given negative arguments.
+ Negative arguments are always multiples of pagesize. MORECORE
+ must not misinterpret negative args as large positive unsigned
+ args.
+
+ There is some variation across systems about the type of the
+ argument to sbrk/MORECORE. If size_t is unsigned, then it cannot
+ actually be size_t, because sbrk supports negative args, so it is
+ normally the signed type of the same width as size_t (sometimes
+ declared as "intptr_t", and sometimes "ptrdiff_t"). It doesn't much
+ matter though. Internally, we use "long" as arguments, which should
+ work across all reasonable possibilities.
+
+ Additionally, if MORECORE ever returns failure for a positive
+ request, and HAVE_MMAP is true, then mmap is used as a noncontiguous
+ system allocator. This is a useful backup strategy for systems with
+ holes in address spaces -- in this case sbrk cannot contiguously
+ expand the heap, but mmap may be able to map noncontiguous space.
+ If you'd like mmap to ALWAYS be used, you can define MORECORE to be
+ a function that always returns MORECORE_FAILURE.
+
+ If you are using this malloc with something other than unix sbrk to
+ supply memory regions, you probably want to set MORECORE_CONTIGUOUS
+ as false. As an example, here is a custom allocator kindly
+ contributed for pre-OSX macOS. It uses virtually but not
+ necessarily physically contiguous non-paged memory (locked in,
+ present and won't get swapped out). You can use it by uncommenting
+ this section, adding some #includes, and setting up the appropriate
+ defines above:
+
+ #define MORECORE osMoreCore
+ #define MORECORE_CONTIGUOUS 0
+
+ There is also a shutdown routine that should somehow be called for
+ cleanup upon program exit.
+
+ #define MAX_POOL_ENTRIES 100
+ #define MINIMUM_MORECORE_SIZE (64 * 1024)
+ static int next_os_pool;
+ void *our_os_pools[MAX_POOL_ENTRIES];
+
+ void *osMoreCore(int size)
+ {
+ void *ptr = 0;
+ static void *sbrk_top = 0;
+
+ if (size > 0)
+ {
+ if (size < MINIMUM_MORECORE_SIZE)
+ size = MINIMUM_MORECORE_SIZE;
+ if (CurrentExecutionLevel() == kTaskLevel)
+ ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
+ if (ptr == 0)
+ {
+ return (void *) MORECORE_FAILURE;
+ }
+ // save ptrs so they can be freed during cleanup
+ our_os_pools[next_os_pool] = ptr;
+ next_os_pool++;
+ ptr = (void *) ((((unsigned long) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
+ sbrk_top = (char *) ptr + size;
+ return ptr;
+ }
+ else if (size < 0)
+ {
+ // we don't currently support shrink behavior
+ return (void *) MORECORE_FAILURE;
+ }
+ else
+ {
+ return sbrk_top;
+ }
+ }
+
+ // cleanup any allocated memory pools
+ // called as last thing before shutting down driver
+
+ void osCleanupMem(void)
+ {
+ void **ptr;
+
+ for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
+ if (*ptr)
+ {
+ PoolDeallocate(*ptr);
+ *ptr = 0;
+ }
+ }
+
+*/
+
+
+
+
+
+/*
+ ----------------------- Chunk representations -----------------------
+*/
+
+
+/*
+ This struct declaration is misleading (but accurate and necessary).
+ It declares a "view" into memory allowing access to necessary
+ fields at known offsets from a given base. See explanation below.
+*/
+
+struct malloc_chunk {
+
+ INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
+ INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
+
+ struct malloc_chunk* fd; /* double links -- used only if free. */
+ struct malloc_chunk* bk;
+};
+
+
+typedef struct malloc_chunk* mchunkptr;
+
+/*
+
+ malloc_chunk details:
+
+ (The following includes lightly edited explanations by Colin Plumb.)
+
+ Chunks of memory are maintained using a `boundary tag' method as
+ described in e.g., Knuth or Standish. (See the paper by Paul
+ Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
+ survey of such techniques.) Sizes of free chunks are stored both
+ in the front of each chunk and at the end. This makes
+ consolidating fragmented chunks into bigger chunks very fast. The
+ size fields also hold bits representing whether chunks are free or
+ in use.
+
+ An allocated chunk looks like this:
+
+
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of previous chunk, if allocated | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of chunk, in bytes |P|
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | User data starts here... .
+ . .
+ . (malloc_usable_space() bytes) .
+ . |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of chunk |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ Where "chunk" is the front of the chunk for the purpose of most of
+ the malloc code, but "mem" is the pointer that is returned to the
+ user. "Nextchunk" is the beginning of the next contiguous chunk.
+
+ Chunks always begin on even word boundries, so the mem portion
+ (which is returned to the user) is also on an even word boundary, and
+ thus double-word aligned.
+
+ Free chunks are stored in circular doubly-linked lists, and look like this:
+
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of previous chunk |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ `head:' | Size of chunk, in bytes |P|
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Forward pointer to next chunk in list |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Back pointer to previous chunk in list |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Unused space (may be 0 bytes long) .
+ . .
+ . |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ `foot:' | Size of chunk, in bytes |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The P (PREV_INUSE) bit, stored in the unused low-order bit of the
+ chunk size (which is always a multiple of two words), is an in-use
+ bit for the *previous* chunk. If that bit is *clear*, then the
+ word before the current chunk size contains the previous chunk
+ size, and can be used to find the front of the previous chunk.
+ The very first chunk allocated always has this bit set,
+ preventing access to non-existent (or non-owned) memory. If
+ prev_inuse is set for any given chunk, then you CANNOT determine
+ the size of the previous chunk, and might even get a memory
+ addressing fault when trying to do so.
+
+ Note that the `foot' of the current chunk is actually represented
+ as the prev_size of the NEXT chunk. (This makes it easier to
+ deal with alignments etc).
+
+ The two exceptions to all this are
+
+ 1. The special chunk `top' doesn't bother using the
+ trailing size field since there is no next contiguous chunk
+ that would have to index off it. After initialization, `top'
+ is forced to always exist. If it would become less than
+ MINSIZE bytes long, it is replenished.
+
+ 2. Chunks allocated via mmap, which have the second-lowest-order
+ bit (IS_MMAPPED) set in their size fields. Because they are
+ allocated one-by-one, each must contain its own trailing size field.
+
+*/
+
+
+
+/*
+ Size and alignment checks and conversions
+*/
+
+/* conversion from malloc headers to user pointers, and back */
+
+#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
+
+/* The smallest possible chunk */
+#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk))
+
+/* The smallest size we can malloc is an aligned minimal chunk */
+
+#define MINSIZE ((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
+
+/* Check if m has acceptable alignment */
+
+#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
+
+/*
+ Check for negative/huge sizes.
+ This cannot just test for < 0 because argument might
+ be an unsigned type of uncertain width.
+*/
+
+#define IS_NEGATIVE(x) \
+ ((unsigned long)x >= \
+ (unsigned long)((((INTERNAL_SIZE_T)(1)) << ((SIZE_SZ)*8 - 1))))
+
+
+/* pad request bytes into a usable size -- internal version */
+
+#define request2size(req) \
+ (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
+ MINSIZE : \
+ ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
+
+
+/*
+ Same, except check for negative/huge arguments.
+ This lets through args that are positive but wrap into
+ negatives when padded. However, these are trapped
+ elsewhere.
+*/
+
+#define checked_request2size(req, sz) \
+ if (IS_NEGATIVE(req)) { \
+ MALLOC_FAILURE_ACTION; \
+ return 0; \
+ } \
+ (sz) = request2size(req);
+
+
+
+
+/*
+ Physical chunk operations
+*/
+
+
+/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
+
+#define PREV_INUSE 0x1
+
+
+/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
+
+#define IS_MMAPPED 0x2
+
+
+/* Bits to mask off when extracting size */
+
+#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
+
+
+/* Ptr to next physical malloc_chunk. */
+
+#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
+
+
+/* Ptr to previous physical malloc_chunk */
+
+#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
+
+
+/* Treat space at ptr + offset as a chunk */
+
+#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
+
+
+
+
+/*
+ Dealing with use bits
+
+ Note: IS_MMAPPED is intentionally not masked off from size field in
+ macros for which mmapped chunks should never be seen. This should
+ cause helpful core dumps to occur if it is tried by accident by
+ people extending or adapting this malloc.
+
+*/
+
+
+/* extract p's inuse bit */
+
+#define inuse(p)\
+((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
+
+
+/* extract inuse bit of previous chunk */
+
+#define prev_inuse(p) ((p)->size & PREV_INUSE)
+
+
+/* check for mmap()'ed chunk */
+
+#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+
+
+/* set/clear chunk as being inuse without otherwise disturbing */
+
+#define set_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
+
+#define clear_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
+
+
+/* check/set/clear inuse bits in known places */
+
+#define inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
+
+#define set_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
+
+#define clear_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
+
+
+
+
+/*
+ Dealing with size fields
+*/
+
+/* Get size, ignoring use bits */
+
+#define chunksize(p) ((p)->size & ~(SIZE_BITS))
+
+/* Set size at head, without disturbing its use bit */
+
+#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
+
+/* Set size/use field */
+
+#define set_head(p, s) ((p)->size = (s))
+
+/* Set size at footer (only when chunk is not in use) */
+
+#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
+
+
+
+
+
+/*
+ ------------------ Internal data structures --------------------
+
+ All internal state is held in an instance of malloc_state defined
+ below. There are no other static variables, except in two optional
+ cases:
+ * If USE_MALLOC_LOCK is defined, the mALLOC_MUTEx declared
+ above.
+ * If HAVE_MMAP is true, but mmap doesn't support
+ MAP_ANONYMOUS, a dummy file descriptor for mmap.
+
+ Beware of lots of tricks that minimize the total space
+ requirements. The result is a little over 1K bytes (for 4byte
+ pointers and size_t.)
+
+*/
+
+/*
+
+ Bins
+
+ An array of bin headers for free chunks. Each bin is doubly
+ linked. The bins are approximately proportionally (log) spaced.
+ There are a lot of these bins (128). This may look excessive, but
+ works very well in practice. Most bins hold sizes that are
+ unusual as malloc request sizes, but are more usual for fragments
+ and consolidated sets of chunks, which is what these bins hold, so
+ they can be found quickly. All procedures maintain the invariant
+ that no consolidated chunk physically borders another one, so each
+ chunk in a list is known to be preceeded and followed by either
+ inuse chunks or the ends of memory.
+
+ Chunks in bins are kept in size order, with ties going to the
+ approximately least recently used chunk. Ordering is irrelevant
+ for the small bins, which all contain the same-sized chunks, but
+ facilitates best-fit allocation for larger chunks. (These lists
+ are just sequential. Keeping them in order almost never requires
+ enough traversal to warrant using fancier ordered data
+ structures.) Chunks of the same size are linked with the most
+ recently freed at the front, and allocations are taken from the
+ back. This results in LRU (FIFO) allocation order, which tends
+ to give each chunk an equal opportunity to be consolidated with
+ adjacent freed chunks, resulting in larger free chunks and less
+ fragmentation.
+
+ To simplify use in double-linked lists, each bin header acts
+ as a malloc_chunk. This avoids special-casing for headers.
+ But to conserve space and (mainly) improve locality, we allocate
+ only the fd/bk pointers of bins, and then use repositioning tricks
+ to treat these as the fields of a malloc_chunk*.
+*/
+
+typedef struct malloc_chunk* mbinptr;
+
+#define NBINS 128
+
+
+/* addressing -- note that bin_at(0) does not exist */
+
+#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1)))
+
+
+/* analog of ++bin */
+
+#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1)))
+
+
+/* Reminders about list directionality within bins */
+
+#define first(b) ((b)->fd)
+#define last(b) ((b)->bk)
+
+/*
+ Take a chunk off a bin list
+*/
+
+#define unlink(P, BK, FD) { \
+ FD = P->fd; \
+ BK = P->bk; \
+ FD->bk = BK; \
+ BK->fd = FD; \
+}
+
+/*
+ Indexing bins
+
+ Bins for sizes < 512 bytes contain chunks of all the same size, spaced
+ 8 bytes apart. Larger bins are approximately logarithmically spaced:
+
+ 64 bins of size 8
+ 32 bins of size 64
+ 16 bins of size 512
+ 8 bins of size 4096
+ 4 bins of size 32768
+ 2 bins of size 262144
+ 1 bin of size what's left
+
+ There is actually a little bit of slop in the numbers in bin_index
+ for the sake of speed. This makes no difference elsewhere.
+
+ The bins top out at around 1mb because we expect to service large
+ chunks via mmap.
+
+*/
+
+/* The first NSMALLBIN bins (and fastbins) hold only one size */
+#define NSMALLBINS 64
+#define SMALLBIN_WIDTH 8
+#define MIN_LARGE_SIZE 512
+
+#define in_smallbin_range(sz) ((sz) < MIN_LARGE_SIZE)
+
+#define smallbin_index(sz) (((unsigned)(sz)) >> 3)
+
+#define largebin_index(sz) \
+(((((unsigned long)(sz)) >> 6) <= 32)? 56 + (((unsigned long)(sz)) >> 6): \
+ ((((unsigned long)(sz)) >> 9) <= 20)? 91 + (((unsigned long)(sz)) >> 9): \
+ ((((unsigned long)(sz)) >> 12) <= 10)? 110 + (((unsigned long)(sz)) >> 12): \
+ ((((unsigned long)(sz)) >> 15) <= 4)? 119 + (((unsigned long)(sz)) >> 15): \
+ ((((unsigned long)(sz)) >> 18) <= 2)? 124 + (((unsigned long)(sz)) >> 18): \
+ 126)
+
+#define bin_index(sz) \
+ ((in_smallbin_range(sz)) ? smallbin_index(sz) : largebin_index(sz))
+
+
+/*
+ Unsorted chunks
+
+ All remainders from chunk splits, as well as all returned chunks,
+ are first placed in the "unsorted" bin. They are then placed
+ in regular bins after malloc gives them ONE chance to be used before
+ binning. So, basically, the unsorted_chunks list acts as a queue,
+ with chunks being placed on it in free (and malloc_consolidate),
+ and taken off (to be either used or placed in bins) in malloc.
+
+*/
+
+
+/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
+
+#define unsorted_chunks(M) (bin_at(M, 1))
+
+
+/*
+ Top
+
+ The top-most available chunk (i.e., the one bordering the end of
+ available memory) is treated specially. It is never included in
+ any bin, is used only if no other chunk is available, and is
+ released back to the system if it is very large (see
+ M_TRIM_THRESHOLD). `top' is never properly linked to its bin
+ since it is always handled specially. Because top initially
+ points to its own bin with initial zero size, thus forcing
+ extension on the first malloc request, we avoid having any special
+ code in malloc to check whether it even exists yet. But we still
+ need to do so when getting memory from system, so we make
+ initial_top treat the bin as a legal but unusable chunk during the
+ interval between initialization and the first call to
+ sYSMALLOc. (This is somewhat delicate, since it relies on
+ the 2 preceding words to be zero during this interval as well.)
+*/
+
+
+/* Conveniently, the unsorted bin can be used as dummy top on first call */
+#define initial_top(M) (unsorted_chunks(M))
+
+/*
+ Binmap
+
+ To help compensate for the large number of bins, a one-level index
+ structure is used for bin-by-bin searching. `binmap' is a
+ bitvector recording whether bins are definitely empty so they can
+ be skipped over during during traversals. The bits are NOT always
+ cleared as soon as bins are empty, but instead only
+ when they are noticed to be empty during traversal in malloc.
+
+*/
+
+/* Conservatively use 32 bits per map word, even if on 64bit system */
+#define BINMAPSHIFT 5
+#define BITSPERMAP (1U << BINMAPSHIFT)
+#define BINMAPSIZE (NBINS / BITSPERMAP)
+
+#define idx2block(i) ((i) >> BINMAPSHIFT)
+#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1))))
+
+#define mark_bin(m,i) ((m)->binmap[idx2block(i)] |= idx2bit(i))
+#define unmark_bin(m,i) ((m)->binmap[idx2block(i)] &= ~(idx2bit(i)))
+#define get_binmap(m,i) ((m)->binmap[idx2block(i)] & idx2bit(i))
+
+
+/*
+ Fastbins
+
+ An array of lists holding recently freed small chunks. Fastbins
+ are not doubly linked. It is faster to single-link them, and
+ since chunks are never removed from the middles of these lists,
+ double linking is not necessary.
+
+ Chunks in fastbins keep their inuse bit set, so they cannot
+ be consolidated with other free chunks. malloc_consolidate
+ releases all chunks in fastbins and consolidates them with
+ other free chunks.
+*/
+
+typedef struct malloc_chunk* mfastbinptr;
+
+/* offset 2 to use otherwise unindexable first 2 bins */
+#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2)
+
+/* The maximum fastbin request size we support */
+#define MAX_FAST_SIZE 80
+
+#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1)
+
+
+
+/*
+ Flag bit held in max_fast indicating that there probably are some
+ fastbin chunks . It is set true on entering a chunk into any fastbin,
+ and cleared only in malloc_consolidate.
+
+ The truth value is inverted so that have_fastchunks will be true
+ upon startup (since statics are zero-filled).
+*/
+
+
+#define have_fastchunks(M) (((M)->max_fast & 1U) == 0)
+#define clear_fastchunks(M) ((M)->max_fast |= 1U)
+#define set_fastchunks(M) ((M)->max_fast &= ~1U)
+
+/*
+ Initialization value of max_fast.
+ Use impossibly small value if 0.
+ Value also has flag bit clear.
+*/
+#define req2max_fast(s) (((((s) == 0)? SMALLBIN_WIDTH: request2size(s))) | 1U)
+
+
+/*
+ NONCONTIGUOUS_REGIONS is a special value for sbrk_base indicating that
+ MORECORE does not return contiguous regions. In this case, we do not check
+ or assume that the address of each chunk is at least sbrk_base. Otherwise,
+ contiguity is exploited in merging together, when possible, results
+ from consecutive MORECORE calls.
+
+ The possible values for sbrk_base are:
+ MORECORE_FAILURE:
+ MORECORE has not yet been called, but we expect contiguous space
+ NONCONTIGUOUS_REGIONS:
+ we don't expect or rely on contiguous space
+ any other legal address:
+ the first address returned by MORECORE when contiguous
+*/
+
+#define NONCONTIGUOUS_REGIONS ((char*)(-3))
+
+
+/*
+ ----------- Internal state representation and initialization -----------
+*/
+
+
+struct malloc_state {
+
+ /* The maximum chunk size to be eligible for fastbin */
+ INTERNAL_SIZE_T max_fast; /* low bit used as fastbin flag */
+
+ /* Base of the topmost chunk -- not otherwise kept in a bin */
+ mchunkptr top;
+
+ /* The remainder from the most recent split of a small request */
+ mchunkptr last_remainder;
+
+ /* Fastbins */
+ mfastbinptr fastbins[NFASTBINS];
+
+ /* Normal bins packed as described above */
+ mchunkptr bins[NBINS * 2];
+
+ /* Bitmap of bins */
+ unsigned int binmap[BINMAPSIZE];
+
+ /* Tunable parameters */
+ unsigned long trim_threshold;
+ INTERNAL_SIZE_T top_pad;
+ INTERNAL_SIZE_T mmap_threshold;
+
+ /* Memory map support */
+ int n_mmaps;
+ int n_mmaps_max;
+ int max_n_mmaps;
+
+ /* Bookkeeping for sbrk */
+ unsigned int pagesize; /* Cache malloc_getpagesize */
+ char* sbrk_base; /* first address returned by sbrk,
+ or NONCONTIGUOUS_REGIONS */
+ /* Statistics */
+
+ INTERNAL_SIZE_T mmapped_mem;
+ INTERNAL_SIZE_T sbrked_mem;
+
+ INTERNAL_SIZE_T max_sbrked_mem;
+ INTERNAL_SIZE_T max_mmapped_mem;
+ INTERNAL_SIZE_T max_total_mem;
+};
+
+typedef struct malloc_state *mstate;
+
+/*
+ There is exactly one instance of this struct in this malloc.
+
+ If you are adapting this malloc in a way that does NOT use a static
+ malloc_state, you MUST explicitly zero-fill it before using. This
+ malloc relies on the property that malloc_state is initialized to
+ all zeroes (as is true of C statics).
+
+*/
+
+static struct malloc_state av_; /* never directly referenced */
+
+/*
+ All uses of av_ are via get_malloc_state().
+ This simplifies construction of multithreaded, etc extensions.
+
+ At most one call to get_malloc_state is made per invocation of
+ the public versions of malloc, free, and all other routines
+ except realloc, valloc, and vpalloc. Also, it is called
+ in check* routines if DEBUG is set.
+*/
+
+#define get_malloc_state() (&(av_))
+
+/*
+ Initialize a malloc_state struct.
+
+ This is called only from within malloc_consolidate, which needs
+ be called in the same contexts anyway. It is never called directly
+ outside of malloc_consolidate because some optimizing compilers try
+ to inline it at all call points, which turns out not to be an
+ optimization at all. (Inlining it only in malloc_consolidate is fine though.)
+*/
+
+#if __STD_C
+static void malloc_init_state(mstate av)
+#else
+static void malloc_init_state(av) mstate av;
+#endif
+{
+ int i;
+ mbinptr bin;
+
+
+ /* Uncomment this if you are not using a static av */
+ /* MALLOC_ZERO(av, sizeof(struct malloc_state); */
+
+ /* Establish circular links for normal bins */
+ for (i = 1; i < NBINS; ++i) {
+ bin = bin_at(av,i);
+ bin->fd = bin->bk = bin;
+ }
+
+ av->max_fast = req2max_fast(DEFAULT_MXFAST);
+
+ av->top_pad = DEFAULT_TOP_PAD;
+ av->n_mmaps_max = DEFAULT_MMAP_MAX;
+ av->mmap_threshold = DEFAULT_MMAP_THRESHOLD;
+
+#if MORECORE_CONTIGUOUS
+ av->trim_threshold = DEFAULT_TRIM_THRESHOLD;
+ av->sbrk_base = (char*)MORECORE_FAILURE;
+#else
+ av->trim_threshold = (unsigned long)(-1);
+ av->sbrk_base = NONCONTIGUOUS_REGIONS;
+#endif
+
+ av->top = initial_top(av);
+ av->pagesize = malloc_getpagesize;
+}
+
+/*
+ Other internal utilities operating on mstates
+*/
+
+#if __STD_C
+static Void_t* sYSMALLOc(INTERNAL_SIZE_T, mstate);
+static int sYSTRIm(size_t, mstate);
+static void malloc_consolidate(mstate);
+#else
+static Void_t* sYSMALLOc();
+static int sYSTRIm();
+static void malloc_consolidate();
+#endif
+
+
+/*
+ Debugging support
+
+ These routines make a number of assertions about the states
+ of data structures that should be true at all times. If any
+ are not true, it's very likely that a user program has somehow
+ trashed memory. (It's also possible that there is a coding error
+ in malloc. In which case, please report it!)
+
+*/
+
+#if ! DEBUG
+
+#define check_chunk(P)
+#define check_free_chunk(P)
+#define check_inuse_chunk(P)
+#define check_remalloced_chunk(P,N)
+#define check_malloced_chunk(P,N)
+#define check_malloc_state()
+
+#else
+#define check_chunk(P) do_check_chunk(P)
+#define check_free_chunk(P) do_check_free_chunk(P)
+#define check_inuse_chunk(P) do_check_inuse_chunk(P)
+#define check_remalloced_chunk(P,N) do_check_remalloced_chunk(P,N)
+#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
+#define check_malloc_state() do_check_malloc_state()
+
+
+/*
+ Properties of all chunks
+*/
+
+#if __STD_C
+static void do_check_chunk(mchunkptr p)
+#else
+static void do_check_chunk(p) mchunkptr p;
+#endif
+{
+
+ mstate av = get_malloc_state();
+ unsigned long sz = chunksize(p);
+
+ if (!chunk_is_mmapped(p)) {
+
+ /* Has legal address ... */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(((char*)p) >= ((char*)(av->sbrk_base)));
+ }
+
+ if (p != av->top) {
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(((char*)p + sz) <= ((char*)(av->top)));
+ }
+ }
+ else {
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(((char*)p + sz) <= ((char*)(av->sbrk_base) + av->sbrked_mem));
+ }
+ /* top size is always at least MINSIZE */
+ assert((long)(sz) >= (long)(MINSIZE));
+ /* top predecessor always marked inuse */
+ assert(prev_inuse(p));
+ }
+
+ }
+ else {
+#if HAVE_MMAP
+ /* address is outside main heap */
+ /* unless mmap has been used as sbrk backup */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(! (((char*)p) >= ((char*)av->sbrk_base) &&
+ ((char*)p) < ((char*)(av->sbrk_base) + av->sbrked_mem)));
+ }
+ /* chunk is page-aligned */
+ assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);
+ /* mem is aligned */
+ assert(aligned_OK(chunk2mem(p)));
+#else
+ /* force an appropriate assert violation if debug set */
+ assert(!chunk_is_mmapped(p));
+#endif
+ }
+
+}
+
+/*
+ Properties of free chunks
+*/
+
+
+#if __STD_C
+static void do_check_free_chunk(mchunkptr p)
+#else
+static void do_check_free_chunk(p) mchunkptr p;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+ mchunkptr next = chunk_at_offset(p, sz);
+
+ do_check_chunk(p);
+
+ /* Chunk must claim to be free ... */
+ assert(!inuse(p));
+ assert (!chunk_is_mmapped(p));
+
+ /* Unless a special marker, must have OK fields */
+ if ((unsigned long)sz >= (unsigned long)MINSIZE)
+ {
+ assert((sz & MALLOC_ALIGN_MASK) == 0);
+ assert(aligned_OK(chunk2mem(p)));
+ /* ... matching footer field */
+ assert(next->prev_size == sz);
+ /* ... and is fully consolidated */
+ assert(prev_inuse(p));
+ assert (next == av->top || inuse(next));
+
+ /* ... and has minimally sane links */
+ assert(p->fd->bk == p);
+ assert(p->bk->fd == p);
+ }
+ else /* markers are always of size SIZE_SZ */
+ assert(sz == SIZE_SZ);
+}
+
+/*
+ Properties of inuse chunks
+*/
+
+
+#if __STD_C
+static void do_check_inuse_chunk(mchunkptr p)
+#else
+static void do_check_inuse_chunk(p) mchunkptr p;
+#endif
+{
+ mstate av = get_malloc_state();
+ mchunkptr next;
+ do_check_chunk(p);
+
+ if (chunk_is_mmapped(p))
+ return; /* mmapped chunks have no next/prev */
+
+ /* Check whether it claims to be in use ... */
+ assert(inuse(p));
+
+ next = next_chunk(p);
+
+ /* ... and is surrounded by OK chunks.
+ Since more things can be checked with free chunks than inuse ones,
+ if an inuse chunk borders them and debug is on, it's worth doing them.
+ */
+ if (!prev_inuse(p)) {
+ /* Note that we cannot even look at prev unless it is not inuse */
+ mchunkptr prv = prev_chunk(p);
+ assert(next_chunk(prv) == p);
+ do_check_free_chunk(prv);
+ }
+
+ if (next == av->top) {
+ assert(prev_inuse(next));
+ assert(chunksize(next) >= MINSIZE);
+ }
+ else if (!inuse(next))
+ do_check_free_chunk(next);
+
+}
+
+/*
+ Properties of chunks recycled from fastbins
+*/
+
+#if __STD_C
+static void do_check_remalloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
+#else
+static void do_check_remalloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
+#endif
+{
+
+ INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+
+ do_check_inuse_chunk(p);
+
+ /* Legal size ... */
+ assert((sz & MALLOC_ALIGN_MASK) == 0);
+ assert((long)sz - (long)MINSIZE >= 0);
+ assert((long)sz - (long)s >= 0);
+ assert((long)sz - (long)(s + MINSIZE) < 0);
+
+ /* ... and alignment */
+ assert(aligned_OK(chunk2mem(p)));
+
+}
+
+/*
+ Properties of nonrecycled chunks at the point they are malloced
+*/
+
+#if __STD_C
+static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
+#else
+static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
+#endif
+{
+ /* same as recycled case ... */
+ do_check_remalloced_chunk(p, s);
+
+ /*
+ ... plus, must obey implementation invariant that prev_inuse is
+ always true of any allocated chunk; i.e., that each allocated
+ chunk borders either a previously allocated and still in-use
+ chunk, or the base of its memory arena. This is ensured
+ by making all allocations from the the `lowest' part of any found
+ chunk. This does not necessarily hold however for chunks
+ recycled via fastbins.
+ */
+
+ assert(prev_inuse(p));
+}
+
+
+/*
+ Properties of malloc_state.
+
+ This may be useful for debugging malloc, as well as detecting user
+ programmer errors that somehow write into malloc_state.
+*/
+
+static void do_check_malloc_state()
+{
+ mstate av = get_malloc_state();
+ int i;
+ mchunkptr p;
+ mchunkptr q;
+ mbinptr b;
+ unsigned int biton;
+ int empty;
+ unsigned int idx;
+ INTERNAL_SIZE_T size;
+ unsigned long total = 0;
+ int max_fast_bin;
+
+
+ /* internal size_t must be no wider than pointer type */
+ assert(sizeof(INTERNAL_SIZE_T) <= sizeof(char*));
+
+ /* alignment is a power of 2 */
+ assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-1)) == 0);
+
+ /* cannot run remaining checks until fully initialized */
+ if (av->top == 0 || av->top == initial_top(av))
+ return;
+
+ /* pagesize is a power of 2 */
+ assert((av->pagesize & (av->pagesize-1)) == 0);
+
+ /* properties of fastbins */
+
+ /* max_fast is in allowed range */
+
+ assert((av->max_fast & ~1) <= request2size(MAX_FAST_SIZE));
+
+ max_fast_bin = fastbin_index(av->max_fast);
+
+ for (i = 0; i < NFASTBINS; ++i) {
+ p = av->fastbins[i];
+
+ /* all bins past max_fast are empty */
+ if (i > max_fast_bin)
+ assert(p == 0);
+
+ while (p != 0) {
+ /* each chunk claims to be inuse */
+ do_check_inuse_chunk(p);
+ total += chunksize(p);
+ /* chunk belongs in this bin */
+ assert(fastbin_index(chunksize(p)) == i);
+ p = p->fd;
+ }
+ }
+
+ if (total != 0)
+ assert(have_fastchunks(av));
+
+ /* check normal bins */
+ for (i = 1; i < NBINS; ++i) {
+ b = bin_at(av,i);
+
+ /* binmap is accurate (except for bin 1 == unsorted_chunks) */
+ if (i >= 2) {
+ biton = get_binmap(av,i);
+ empty = last(b) == b;
+ if (!biton)
+ assert(empty);
+ else if (!empty)
+ assert(biton);
+ }
+
+ for (p = last(b); p != b; p = p->bk) {
+ /* each chunk claims to be free */
+ do_check_free_chunk(p);
+ size = chunksize(p);
+ total += size;
+ if (i >= 2) {
+ /* chunk belongs in bin */
+ idx = bin_index(size);
+ assert(idx == i);
+ /* lists are sorted */
+ assert(p->bk == b || chunksize(p->bk) >= chunksize(p));
+ }
+ /* chunk is followed by a legal chain of inuse chunks */
+ for (q = next_chunk(p);
+ q != av->top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE;
+ q = next_chunk(q))
+ do_check_inuse_chunk(q);
+
+ }
+ }
+
+ /* top chunk is OK */
+ check_chunk(av->top);
+
+ /* sanity checks for statistics */
+
+ assert(total <= (unsigned long)(av->max_total_mem));
+ assert(av->n_mmaps >= 0);
+ assert(av->n_mmaps <= av->n_mmaps_max);
+ assert(av->n_mmaps <= av->max_n_mmaps);
+ assert(av->max_n_mmaps <= av->n_mmaps_max);
+
+ assert((unsigned long)(av->sbrked_mem) <=
+ (unsigned long)(av->max_sbrked_mem));
+
+ assert((unsigned long)(av->mmapped_mem) <=
+ (unsigned long)(av->max_mmapped_mem));
+
+ assert((unsigned long)(av->max_total_mem) >=
+ (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem));
+
+}
+
+
+#endif
+
+
+
+
+
+/* ----------- Routines dealing with system allocation -------------- */
+
+/*
+ Handle malloc cases requiring more memory from system.
+ malloc relays to sYSMALLOc if it cannot allocate out of
+ existing memory.
+
+ On entry, it is assumed that av->top does not have enough
+ space to service request for nb bytes, thus requiring more meory
+ from system.
+*/
+
+#if __STD_C
+static Void_t* sYSMALLOc(INTERNAL_SIZE_T nb, mstate av)
+#else
+static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
+#endif
+{
+ mchunkptr old_top; /* incoming value of av->top */
+ INTERNAL_SIZE_T old_size; /* its size */
+ char* old_end; /* its end address */
+
+ long size; /* arg to first MORECORE or mmap call */
+ char* brk; /* return value from MORECORE */
+ char* mm; /* return value from mmap call*/
+
+ long correction; /* arg to 2nd MORECORE call */
+ char* snd_brk; /* 2nd return val */
+
+ INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
+ INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */
+ char* aligned_brk; /* aligned offset into brk */
+
+ mchunkptr p; /* the allocated/returned chunk */
+ mchunkptr remainder; /* remainder from allocation */
+ long remainder_size; /* its size */
+
+ unsigned long sum; /* for updating stats */
+
+ size_t pagemask = av->pagesize - 1;
+
+ /*
+ If have mmap, and the request size meets the mmap threshold, and
+ the system supports mmap, and there are few enough currently
+ allocated mmapped regions, and a call to mmap succeeds, try to
+ directly map this request rather than expanding top.
+ */
+
+#if HAVE_MMAP
+ if ((unsigned long)nb >= (unsigned long)(av->mmap_threshold) &&
+ (av->n_mmaps < av->n_mmaps_max)) {
+
+ /*
+ Round up size to nearest page. For mmapped chunks, the overhead
+ is one SIZE_SZ unit larger than for normal chunks, because there
+ is no following chunk whose prev_size field could be used.
+ */
+ size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
+
+ mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
+
+ if (mm != (char*)(MORECORE_FAILURE)) {
+
+ /*
+ The offset to the start of the mmapped region is stored
+ in the prev_size field of the chunk. This allows us to adjust
+ returned start address to meet alignment requirements here
+ and in memalign(), and still be able to compute proper
+ address argument for later munmap in free() and realloc().
+ */
+
+ front_misalign = (INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK;
+ if (front_misalign > 0) {
+ correction = MALLOC_ALIGNMENT - front_misalign;
+ p = (mchunkptr)(mm + correction);
+ p->prev_size = correction;
+ set_head(p, (size - correction) |IS_MMAPPED);
+ }
+ else {
+ p = (mchunkptr)mm;
+ set_head(p, size|IS_MMAPPED);
+ }
+
+ check_chunk(p);
+
+ /* update statistics */
+
+ if (++av->n_mmaps > av->max_n_mmaps)
+ av->max_n_mmaps = av->n_mmaps;
+
+ sum = av->mmapped_mem += size;
+ if (sum > (unsigned long)(av->max_mmapped_mem))
+ av->max_mmapped_mem = sum;
+ sum += av->sbrked_mem;
+ if (sum > (unsigned long)(av->max_total_mem))
+ av->max_total_mem = sum;
+
+ return chunk2mem(p);
+ }
+ }
+#endif
+
+ /* record incoming configuration of top */
+
+ old_top = av->top;
+ old_size = chunksize(old_top);
+ old_end = (char*)(chunk_at_offset(old_top, old_size));
+
+ brk = snd_brk = (char*)(MORECORE_FAILURE);
+
+ /*
+ If not the first time through, we require old_size to be
+ at least MINSIZE and to have prev_inuse set.
+ */
+
+ assert(old_top == initial_top(av) ||
+ ((unsigned long) (old_size) >= (unsigned long)(MINSIZE) &&
+ prev_inuse(old_top)));
+
+
+ /* Request enough space for nb + pad + overhead */
+
+ size = nb + av->top_pad + MINSIZE;
+
+ /*
+ If contiguous, we can subtract out existing space that we hope to
+ combine with new space. We add it back later only if
+ we don't actually get contiguous space.
+ */
+
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS)
+ size -= old_size;
+
+ /*
+ Round to a multiple of page size.
+ If MORECORE is not contiguous, this ensures that we only call it
+ with whole-page arguments. And if MORECORE is contiguous and
+ this is not first time through, this preserves page-alignment of
+ previous calls. Otherwise, we re-correct anyway to page-align below.
+ */
+
+ size = (size + pagemask) & ~pagemask;
+
+ /*
+ Don't try to call MORECORE if argument is so big as to appear
+ negative. Note that since mmap takes size_t arg, it may succeed
+ below even if we cannot call MORECORE.
+ */
+
+ if (size > 0)
+ brk = (char*)(MORECORE(size));
+
+ /*
+ If have mmap, try using it as a backup when MORECORE fails. This
+ is worth doing on systems that have "holes" in address space, so
+ sbrk cannot extend to give contiguous space, but space is available
+ elsewhere. Note that we ignore mmap max count and threshold limits,
+ since there is no reason to artificially limit use here.
+ */
+
+#if HAVE_MMAP
+ if (brk == (char*)(MORECORE_FAILURE)) {
+
+ /* Cannot merge with old top, so add its size back in */
+
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS)
+ size = (size + old_size + pagemask) & ~pagemask;
+
+ /* If we are relying on mmap as backup, then use larger units */
+
+ if ((unsigned long)size < (unsigned long)MMAP_AS_MORECORE_SIZE)
+ size = MMAP_AS_MORECORE_SIZE;
+
+ brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
+
+ if (brk != (char*)(MORECORE_FAILURE)) {
+
+ /* We do not need, and cannot use, another sbrk call to find end */
+ snd_brk = brk + size;
+
+ /*
+ Record that we no longer have a contiguous sbrk region.
+ After the first time mmap is used as backup, we cannot
+ ever rely on contiguous space.
+ */
+ av->sbrk_base = NONCONTIGUOUS_REGIONS;
+ }
+ }
+#endif
+
+ if (brk != (char*)(MORECORE_FAILURE)) {
+
+ av->sbrked_mem += size;
+
+ /*
+ If MORECORE extends previous space, we can likewise extend top size.
+ */
+
+ if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
+ set_head(old_top, (size + old_size) | PREV_INUSE);
+ }
+
+ /*
+ Otherwise, make adjustments guided by the special values of
+ av->sbrk_base (MORECORE_FAILURE or NONCONTIGUOUS_REGIONS):
+
+ * If the first time through or noncontiguous, we need to call sbrk
+ just to find out where the end of memory lies.
+
+ * We need to ensure that all returned chunks from malloc will meet
+ MALLOC_ALIGNMENT
+
+ * If there was an intervening foreign sbrk, we need to adjust sbrk
+ request size to account for fact that we will not be able to
+ combine new space with existing space in old_top.
+
+ * Almost all systems internally allocate whole pages at a time, in
+ which case we might as well use the whole last page of request.
+ So we allocate enough more memory to hit a page boundary now,
+ which in turn causes future contiguous calls to page-align.
+
+ */
+
+ else {
+ front_misalign = 0;
+ end_misalign = 0;
+ correction = 0;
+ aligned_brk = brk;
+
+ /* handle contiguous cases */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+
+ /* Guarantee alignment of first new chunk made from this space */
+
+ front_misalign = (INTERNAL_SIZE_T)chunk2mem(brk) & MALLOC_ALIGN_MASK;
+ if (front_misalign > 0) {
+
+ /*
+ Skip over some bytes to arrive at an aligned position.
+ We don't need to specially mark these wasted front bytes.
+ They will never be accessed anyway because
+ prev_inuse of av->top (and any chunk created from its start)
+ is always true after initialization.
+ */
+
+ correction = MALLOC_ALIGNMENT - front_misalign;
+ aligned_brk += correction;
+ }
+
+ /*
+ If this isn't adjacent to a previous sbrk, then we will not
+ be able to merge with old_top space, so must add to 2nd request.
+ */
+
+ correction += old_size;
+
+ /* Pad out to hit a page boundary */
+
+ end_misalign = (INTERNAL_SIZE_T)(brk + size + correction);
+ correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
+
+ assert(correction >= 0);
+
+ snd_brk = (char*)(MORECORE(correction));
+
+ /*
+ If can't allocate correction, try to at least find out current
+ brk. It might be enough to proceed without failing.
+
+ Note that if second sbrk did NOT fail, we assume that space
+ is contiguous with first sbrk. This is a safe assumption unless
+ program is multithreaded but doesn't use locks and a foreign sbrk
+ occurred between our first and second calls.
+ */
+
+ if (snd_brk == (char*)(MORECORE_FAILURE)) {
+ correction = 0;
+ snd_brk = (char*)(MORECORE(0));
+ }
+ }
+
+ /* handle non-contiguous cases */
+ else {
+
+ /* MORECORE/mmap must correctly align etc */
+ assert(((unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK) == 0);
+
+ /* Find out current end of memory */
+ if (snd_brk == (char*)(MORECORE_FAILURE)) {
+ snd_brk = (char*)(MORECORE(0));
+ }
+
+ /* This must lie on a page boundary */
+ if (snd_brk != (char*)(MORECORE_FAILURE)) {
+ assert(((INTERNAL_SIZE_T)(snd_brk) & pagemask) == 0);
+ }
+ }
+
+ /* Adjust top based on results of second sbrk */
+ if (snd_brk != (char*)(MORECORE_FAILURE)) {
+
+ av->top = (mchunkptr)aligned_brk;
+ set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
+
+ av->sbrked_mem += correction;
+
+ /* If first time through and contiguous, record base */
+ if (old_top == initial_top(av)) {
+ if (av->sbrk_base == (char*)(MORECORE_FAILURE))
+ av->sbrk_base = brk;
+ }
+
+ /*
+ Otherwise, we either have a gap due to foreign sbrk or a
+ non-contiguous region. Insert a double fencepost at old_top
+ to prevent consolidation with space we don't own. These
+ fenceposts are artificial chunks that are marked as inuse
+ and are in any case too small to use. We need two to make
+ sizes and alignments work out.
+ */
+
+ else {
+
+ /*
+ Shrink old_top to insert fenceposts, keeping size a
+ multiple of MALLOC_ALIGNMENT.
+ */
+ old_size = (old_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
+ set_head(old_top, old_size | PREV_INUSE);
+
+ /*
+ Note that the following assignments overwrite old_top when
+ old_size was previously MINSIZE. This is intentional. We
+ need the fencepost, even if old_top otherwise gets lost.
+ */
+ chunk_at_offset(old_top, old_size )->size =
+ SIZE_SZ|PREV_INUSE;
+
+ chunk_at_offset(old_top, old_size + SIZE_SZ)->size =
+ SIZE_SZ|PREV_INUSE;
+
+ /* If possible, release the rest. */
+ if (old_size >= MINSIZE)
+ fREe(chunk2mem(old_top));
+
+ }
+ }
+ }
+
+ /* Update statistics */
+
+ sum = av->sbrked_mem;
+ if (sum > (unsigned long)(av->max_sbrked_mem))
+ av->max_sbrked_mem = sum;
+
+ sum += av->mmapped_mem;
+ if (sum > (unsigned long)(av->max_total_mem))
+ av->max_total_mem = sum;
+
+ check_malloc_state();
+
+ /* finally, do the allocation */
+
+ p = av->top;
+ size = chunksize(p);
+ remainder_size = (long)size - (long)nb;
+
+ /* check that one of the above allocation paths succeeded */
+ if (remainder_size >= (long)MINSIZE) {
+ remainder = chunk_at_offset(p, nb);
+ av->top = remainder;
+ set_head(p, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+
+ check_malloced_chunk(p, nb);
+ return chunk2mem(p);
+ }
+ }
+
+ /* catch all failure paths */
+ MALLOC_FAILURE_ACTION;
+ return 0;
+}
+
+
+/*
+ sYSTRIm is an inverse of sorts to sYSMALLOc.
+ It gives memory back to the system (via negative
+ arguments to sbrk) if there is unused memory at the `high' end of
+ the malloc pool. It is called automatically by free()
+ when top space exceeds the trim threshold.
+ returns 1 if it actually released any memory, else 0.
+*/
+
+#if __STD_C
+static int sYSTRIm(size_t pad, mstate av)
+#else
+static int sYSTRIm(pad, av) size_t pad; mstate av;
+#endif
+{
+ long top_size; /* Amount of top-most memory */
+ long extra; /* Amount to release */
+ long released; /* Amount actually released */
+ char* current_brk; /* address returned by pre-check sbrk call */
+ char* new_brk; /* address returned by post-check sbrk call */
+ size_t pagesz;
+
+ /* Don't bother trying if sbrk doesn't provide contiguous regions */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+
+ pagesz = av->pagesize;
+ top_size = chunksize(av->top);
+
+ /* Release in pagesize units, keeping at least one page */
+ extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
+
+ if (extra > 0) {
+
+ /*
+ Only proceed if end of memory is where we last set it.
+ This avoids problems if there were foreign sbrk calls.
+ */
+ current_brk = (char*)(MORECORE(0));
+ if (current_brk == (char*)(av->top) + top_size) {
+
+ /*
+ Attempt to release memory. We ignore return value,
+ and instead call again to find out where new end of memory is.
+ This avoids problems if first call releases less than we asked,
+ of if failure somehow altered brk value. (We could still
+ encounter problems if it altered brk in some very bad way,
+ but the only thing we can do is adjust anyway, which will cause
+ some downstream failure.)
+ */
+
+ MORECORE(-extra);
+ new_brk = (char*)(MORECORE(0));
+
+ if (new_brk != (char*)MORECORE_FAILURE) {
+ released = (long)(current_brk - new_brk);
+
+ if (released != 0) {
+ /* Success. Adjust top. */
+ av->sbrked_mem -= released;
+ set_head(av->top, (top_size - released) | PREV_INUSE);
+ check_malloc_state();
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* ----------------------- Main public routines ----------------------- */
+
+
+/*
+ Malloc routine. See running comments for algorithm description.
+*/
+
+#if __STD_C
+Void_t* mALLOc(size_t bytes)
+#else
+ Void_t* mALLOc(bytes) size_t bytes;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ INTERNAL_SIZE_T nb; /* normalized request size */
+ unsigned int idx; /* associated bin index */
+ mbinptr bin; /* associated bin */
+ mfastbinptr* fb; /* associated fastbin */
+
+ mchunkptr victim; /* inspected/selected chunk */
+ INTERNAL_SIZE_T size; /* its size */
+ int victim_index; /* its bin index */
+
+ mchunkptr remainder; /* remainder from a split */
+ long remainder_size; /* its size */
+
+ unsigned int block; /* bit map traverser */
+ unsigned int bit; /* bit map traverser */
+ unsigned int map; /* current word of binmap */
+
+ mchunkptr fwd; /* misc temp for linking */
+ mchunkptr bck; /* misc temp for linking */
+
+
+ /*
+ Check request for legality and convert to internal form, nb.
+ This rejects negative arguments when size_t is treated as
+ signed. It also rejects arguments that are so large that the size
+ appears negative when aligned and padded. The converted form
+ adds SIZE_T bytes overhead plus possibly more to obtain necessary
+ alignment and/or to obtain a size of at least MINSIZE, the
+ smallest allocatable size.
+ */
+
+ checked_request2size(bytes, nb);
+
+ /*
+ If the size qualifies as a fastbin, first check corresponding bin.
+ This code is safe to execute even if av not yet initialized, so we
+ can try it first, which saves some time on this fast path.
+ */
+
+ if (nb <= av->max_fast) {
+ fb = &(av->fastbins[(fastbin_index(nb))]);
+ if ( (victim = *fb) != 0) {
+ *fb = victim->fd;
+ check_remalloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+
+ /*
+ If a small request, check regular bin. Since these "smallbins"
+ hold one size each, no searching within bins is necessary.
+
+ (If a large request, we need to wait until unsorted chunks are
+ processed to find best fit. But for small ones, fits are exact
+ anyway, so we can check now, which is faster.)
+ */
+
+ if (in_smallbin_range(nb)) {
+ idx = smallbin_index(nb);
+ bin = bin_at(av,idx);
+
+ if ( (victim = last(bin)) != bin) {
+ if (victim == 0) /* initialization check */
+ malloc_consolidate(av);
+ else {
+ bck = victim->bk;
+ set_inuse_bit_at_offset(victim, nb);
+ bin->bk = bck;
+ bck->fd = bin;
+
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+ }
+
+ /*
+ If a large request, consolidate fastbins before continuing.
+ While it might look excessive to kill all fastbins before
+ even seeing if there is space available, this avoids
+ fragmentation problems normally associated with fastbins.
+ Also, in practice, programs tend to have runs of either small or
+ large requests, but less often mixtures, so consolidation is not
+ usually invoked all that often.
+ */
+
+ else {
+ idx = largebin_index(nb);
+ if (have_fastchunks(av)) /* consolidation/initialization check */
+ malloc_consolidate(av);
+ }
+
+
+ /*
+ Process recently freed or remaindered chunks, taking one only if
+ it is exact fit, or, if a small request, it is the remainder from
+ the most recent non-exact fit. Place other traversed chunks in
+ bins. Note that this step is the only place in any routine where
+ chunks are placed in bins.
+
+ The outer loop here is needed because we might not realize until
+ near the end of malloc that we should have consolidated, so must
+ do so and retry. This happens at most once, and only when we would
+ otherwise need to expand memory to service a "small" request.
+ */
+
+
+ for(;;) {
+
+ while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
+ bck = victim->bk;
+ size = chunksize(victim);
+
+ /*
+ If a small request, try to use last remainder if it is the
+ only chunk in unsorted bin. This helps promote locality for
+ runs of consecutive small requests. This is the only
+ exception to best-fit.
+ */
+
+ if (in_smallbin_range(nb) &&
+ victim == av->last_remainder &&
+ bck == unsorted_chunks(av) &&
+ (remainder_size = (long)size - (long)nb) >= (long)MINSIZE) {
+
+ /* split and reattach remainder */
+ remainder = chunk_at_offset(victim, nb);
+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+ av->last_remainder = remainder;
+ remainder->bk = remainder->fd = unsorted_chunks(av);
+
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* remove from unsorted list */
+ unsorted_chunks(av)->bk = bck;
+ bck->fd = unsorted_chunks(av);
+
+ /* Take now instead of binning if exact fit */
+
+ if (size == nb) {
+ set_inuse_bit_at_offset(victim, size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* place chunk in bin */
+
+ if (in_smallbin_range(size)) {
+ victim_index = smallbin_index(size);
+ bck = bin_at(av, victim_index);
+ fwd = bck->fd;
+ }
+ else {
+ victim_index = largebin_index(size);
+ bck = bin_at(av, victim_index);
+ fwd = bck->fd;
+
+ /* maintain large bins in sorted order */
+ if (fwd != bck) {
+ /* if smaller than smallest, bypass loop below */
+ if ((unsigned long)size <=
+ (unsigned long)(chunksize(bck->bk))) {
+ fwd = bck;
+ bck = bck->bk;
+ }
+ else {
+ while (fwd != bck &&
+ (unsigned long)size < (unsigned long)(chunksize(fwd))) {
+ fwd = fwd->fd;
+ }
+ bck = fwd->bk;
+ }
+ }
+ }
+
+ mark_bin(av, victim_index);
+ victim->bk = bck;
+ victim->fd = fwd;
+ fwd->bk = victim;
+ bck->fd = victim;
+ }
+
+ /*
+ If a large request, scan through the chunks of current bin in
+ sorted order to find smallest that fits. This is the only step
+ where an unbounded number of chunks might be scanned without doing
+ anything useful with them. However the lists tend to be very
+ short.
+ */
+
+ if (!in_smallbin_range(nb)) {
+ bin = bin_at(av, idx);
+
+ /* skip scan if largest chunk is too small */
+ if ((victim = last(bin)) != bin &&
+ (long)(chunksize(first(bin))) - (long)(nb) >= 0) {
+ do {
+ size = chunksize(victim);
+ remainder_size = (long)size - (long)nb;
+
+ if (remainder_size >= 0) {
+ unlink(victim, bck, fwd);
+
+ /* Exhaust */
+ if (remainder_size < (long)MINSIZE) {
+ set_inuse_bit_at_offset(victim, size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ /* Split */
+ else {
+ remainder = chunk_at_offset(victim, nb);
+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+ remainder->bk = remainder->fd = unsorted_chunks(av);
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+ } while ( (victim = victim->bk) != bin);
+ }
+ }
+
+ /*
+ Search for a chunk by scanning bins, starting with next largest
+ bin. This search is strictly by best-fit; i.e., the smallest
+ (with ties going to approximately the least recently used) chunk
+ that fits is selected.
+
+ The bitmap avoids needing to check that most blocks are nonempty.
+ The particular case of skipping all bins during warm-up phases
+ when no chunks have been returned yet is faster than it might look.
+ */
+
+ ++idx;
+ bin = bin_at(av,idx);
+ block = idx2block(idx);
+ map = av->binmap[block];
+ bit = idx2bit(idx);
+
+ for (;;) {
+ /*
+ Skip rest of block if there are no more set bits in this block.
+ */
+
+ if (bit > map || bit == 0) {
+ for (;;) {
+ if (++block >= BINMAPSIZE) /* out of bins */
+ break;
+
+ else if ( (map = av->binmap[block]) != 0) {
+ bin = bin_at(av, (block << BINMAPSHIFT));
+ bit = 1;
+ break;
+ }
+ }
+ /* Optimizers seem to like this double-break better than goto */
+ if (block >= BINMAPSIZE)
+ break;
+ }
+
+ /* Advance to bin with set bit. There must be one. */
+ while ((bit & map) == 0) {
+ bin = next_bin(bin);
+ bit <<= 1;
+ }
+
+ victim = last(bin);
+
+ /* False alarm -- the bin is empty. Clear the bit. */
+ if (victim == bin) {
+ av->binmap[block] = map &= ~bit; /* Write through */
+ bin = next_bin(bin);
+ bit <<= 1;
+ }
+
+ /* We know the first chunk in this bin is big enough to use. */
+ else {
+ size = chunksize(victim);
+ remainder_size = (long)size - (long)nb;
+
+ assert(remainder_size >= 0);
+
+ /* unlink */
+ bck = victim->bk;
+ bin->bk = bck;
+ bck->fd = bin;
+
+
+ /* Exhaust */
+ if (remainder_size < (long)MINSIZE) {
+ set_inuse_bit_at_offset(victim, size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* Split */
+ else {
+ remainder = chunk_at_offset(victim, nb);
+
+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+ remainder->bk = remainder->fd = unsorted_chunks(av);
+ /* advertise as last remainder */
+ if (in_smallbin_range(nb))
+ av->last_remainder = remainder;
+
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+ }
+
+ /*
+ If large enough, split off the chunk bordering the end of memory
+ ("top"). Note that this use of top is in accord with the best-fit search
+ rule. In effect, top is treated as larger (and thus less well
+ fitting) than any other available chunk since it can be extended
+ to be as large as necessary (up to system limitations).
+
+ We require that "top" always exists (i.e., has size >= MINSIZE)
+ after initialization, so if it would otherwise be exhuasted by
+ current request, it is replenished. (Among the reasons for
+ ensuring it exists is that we may need MINSIZE space to put in
+ fenceposts in sysmalloc.)
+ */
+
+ victim = av->top;
+ size = chunksize(victim);
+ remainder_size = (long)size - (long)nb;
+
+ if (remainder_size >= (long)MINSIZE) {
+ remainder = chunk_at_offset(victim, nb);
+ av->top = remainder;
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /*
+ If there is space available in fastbins, consolidate and retry,
+ to possibly avoid expanding memory. This can occur only if nb is
+ in smallbin range so we didn't consolidate upon entry.
+ */
+
+ else if (have_fastchunks(av)) {
+ assert(in_smallbin_range(nb));
+ idx = smallbin_index(nb); /* restore original bin index */
+ malloc_consolidate(av);
+ }
+
+ /*
+ Otherwise, relay to handle system-dependent cases
+ */
+ else
+ return sYSMALLOc(nb, av);
+ }
+}
+
+
+
+/*
+ Free routine. See running comments for algorithm description.
+*/
+
+#if __STD_C
+void fREe(Void_t* mem)
+#else
+void fREe(mem) Void_t* mem;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ mchunkptr p; /* chunk corresponding to mem */
+ INTERNAL_SIZE_T size; /* its size */
+ mfastbinptr* fb; /* associated fastbin */
+ mchunkptr nextchunk; /* next contiguous chunk */
+ INTERNAL_SIZE_T nextsize; /* its size */
+ int nextinuse; /* true if nextchunk is used */
+ INTERNAL_SIZE_T prevsize; /* size of previous contiguous chunk */
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+
+
+ /* free(0) has no effect */
+ if (mem != 0) {
+
+ p = mem2chunk(mem);
+ check_inuse_chunk(p);
+
+ size = chunksize(p);
+
+ /*
+ If eligible, place chunk on a fastbin so it can be found
+ and used quickly in malloc.
+ */
+
+ if ((unsigned long)size <= (unsigned long)av->max_fast
+
+#if TRIM_FASTBINS
+ /*
+ If TRIM_FASTBINS set, don't place chunks
+ bordering top into fastbins
+ */
+ && (chunk_at_offset(p, size) != av->top)
+#endif
+ ) {
+
+ set_fastchunks(av);
+ fb = &(av->fastbins[fastbin_index(size)]);
+ p->fd = *fb;
+ *fb = p;
+ }
+
+ /*
+ Consolidate non-mmapped chunks as they arrive.
+ */
+
+ else if (!chunk_is_mmapped(p)) {
+
+ nextchunk = chunk_at_offset(p, size);
+
+ /* consolidate backward */
+ if (!prev_inuse(p)) {
+ prevsize = p->prev_size;
+ size += prevsize;
+ p = chunk_at_offset(p, -((long) prevsize));
+ unlink(p, bck, fwd);
+ }
+
+ nextsize = chunksize(nextchunk);
+
+ if (nextchunk != av->top) {
+
+ /* get and clear inuse bit */
+ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+ set_head(nextchunk, nextsize);
+
+ /* consolidate forward */
+ if (!nextinuse) {
+ unlink(nextchunk, bck, fwd);
+ size += nextsize;
+ }
+
+ /*
+ Place chunk in unsorted chunk list. Chunks are
+ not placed into regular bins until after they have
+ been given one chance to be used in malloc.
+ */
+
+ bck = unsorted_chunks(av);
+ fwd = bck->fd;
+ p->bk = bck;
+ p->fd = fwd;
+ bck->fd = p;
+ fwd->bk = p;
+
+ set_head(p, size | PREV_INUSE);
+ set_foot(p, size);
+ }
+
+ /*
+ If the chunk borders the current high end of memory,
+ consolidate into top
+ */
+
+ else {
+ size += nextsize;
+ set_head(p, size | PREV_INUSE);
+ av->top = p;
+
+ /*
+ If the total unused topmost memory exceeds trim
+ threshold, ask malloc_trim to reduce top.
+
+ Unless max_fast is 0, we don't know if there are fastbins
+ bordering top, so we cannot tell for sure whether threshold has
+ been reached unless fastbins are consolidated. But we don't
+ want to consolidate on each free. As a compromise,
+ consolidation is performed if half the threshold is
+ reached.
+
+ */
+
+ if ((unsigned long)(size) > (unsigned long)(av->trim_threshold / 2)) {
+ if (have_fastchunks(av)) {
+ malloc_consolidate(av);
+ size = chunksize(av->top);
+ }
+
+ if ((unsigned long)(size) > (unsigned long)(av->trim_threshold))
+ sYSTRIm(av->top_pad, av);
+ }
+ }
+ }
+
+ /*
+ If the chunk was allocated via mmap, release via munmap()
+ Note that if HAVE_MMAP is false but chunk_is_mmapped is
+ true, then user must have overwritten memory. There's nothing
+ we can do to catch this error unless DEBUG is set, in which case
+ check_inuse_chunk (above) will have triggered error.
+ */
+
+ else {
+#if HAVE_MMAP
+ int ret;
+ INTERNAL_SIZE_T offset = p->prev_size;
+ av->n_mmaps--;
+ av->mmapped_mem -= (size + offset);
+ ret = munmap((char*)p - offset, size + offset);
+ /* munmap returns non-zero on failure */
+ assert(ret == 0);
+#endif
+ }
+ }
+}
+
+
+
+/*
+ malloc_consolidate is a specialized version of free() that tears
+ down chunks held in fastbins. Free itself cannot be used for this
+ purpose since, among other things, it might place chunks back onto
+ fastbins. So, instead, we need to use a minor variant of the same
+ code.
+
+ Also, because this routine needs to be called the first time through
+ malloc anyway, it turns out to be the perfect place to bury
+ initialization code.
+*/
+
+#if __STD_C
+static void malloc_consolidate(mstate av)
+#else
+static void malloc_consolidate(av) mstate av;
+#endif
+{
+ mfastbinptr* fb;
+ mfastbinptr* maxfb;
+ mchunkptr p;
+ mchunkptr nextp;
+ mchunkptr unsorted_bin;
+ mchunkptr first_unsorted;
+
+ /* These have same use as in free() */
+ mchunkptr nextchunk;
+ INTERNAL_SIZE_T size;
+ INTERNAL_SIZE_T nextsize;
+ INTERNAL_SIZE_T prevsize;
+ int nextinuse;
+ mchunkptr bck;
+ mchunkptr fwd;
+
+ /*
+ If max_fast is 0, we know that malloc hasn't
+ yet been initialized, in which case do so.
+ */
+
+ if (av->max_fast == 0) {
+ malloc_init_state(av);
+ check_malloc_state();
+ }
+ else if (have_fastchunks(av)) {
+ clear_fastchunks(av);
+
+ unsorted_bin = unsorted_chunks(av);
+
+ /*
+ Remove each chunk from fast bin and consolidate it, placing it
+ then in unsorted bin. Among other reasons for doing this,
+ placing in unsorted bin avoids needing to calculate actual bins
+ until malloc is sure that chunks aren't immediately going to be
+ reused anyway.
+ */
+
+ maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
+ fb = &(av->fastbins[0]);
+ do {
+ if ( (p = *fb) != 0) {
+ *fb = 0;
+
+ do {
+ check_inuse_chunk(p);
+ nextp = p->fd;
+
+ /* Slightly streamlined version of consolidation code in free() */
+ size = p->size & ~PREV_INUSE;
+ nextchunk = chunk_at_offset(p, size);
+
+ if (!prev_inuse(p)) {
+ prevsize = p->prev_size;
+ size += prevsize;
+ p = chunk_at_offset(p, -((long) prevsize));
+ unlink(p, bck, fwd);
+ }
+
+ nextsize = chunksize(nextchunk);
+
+ if (nextchunk != av->top) {
+
+ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+ set_head(nextchunk, nextsize);
+
+ if (!nextinuse) {
+ size += nextsize;
+ unlink(nextchunk, bck, fwd);
+ }
+
+ first_unsorted = unsorted_bin->fd;
+ unsorted_bin->fd = p;
+ first_unsorted->bk = p;
+
+ set_head(p, size | PREV_INUSE);
+ p->bk = unsorted_bin;
+ p->fd = first_unsorted;
+ set_foot(p, size);
+ }
+
+ else {
+ size += nextsize;
+ set_head(p, size | PREV_INUSE);
+ av->top = p;
+ }
+
+ } while ( (p = nextp) != 0);
+
+ }
+ } while (fb++ != maxfb);
+ }
+}
+
+
+
+
+/*
+ Realloc algorithm cases:
+
+ * Chunks that were obtained via mmap cannot be extended or shrunk
+ unless HAVE_MREMAP is defined, in which case mremap is used.
+ Otherwise, if the reallocation is for additional space, they are
+ copied. If for less, they are just left alone.
+
+ * Otherwise, if the reallocation is for additional space, and the
+ chunk can be extended, it is, else a malloc-copy-free sequence is
+ taken. There are several different ways that a chunk could be
+ extended. All are tried:
+
+ * Extending forward into following adjacent free chunk.
+ * Shifting backwards, joining preceding adjacent space
+ * Both shifting backwards and extending forward.
+ * Extending into newly sbrked space
+
+ * If there is not enough memory available to realloc, realloc
+ returns null, but does NOT free the existing space.
+
+ * If the reallocation is for less space, the newly unused space is
+ lopped off and freed. Unless the #define REALLOC_ZERO_BYTES_FREES
+ is set, realloc with a size argument of zero (re)allocates a
+ minimum-sized chunk.
+
+
+ The old unix realloc convention of allowing the last-free'd chunk
+ to be used as an argument to realloc is no longer supported.
+ I don't know of any programs still relying on this feature,
+ and allowing it would also allow too many other incorrect
+ usages of realloc to be sensible.
+*/
+
+#if __STD_C
+Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
+#else
+Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ INTERNAL_SIZE_T nb; /* padded request size */
+
+ mchunkptr oldp; /* chunk corresponding to oldmem */
+ INTERNAL_SIZE_T oldsize; /* its size */
+
+ mchunkptr newp; /* chunk to return */
+ INTERNAL_SIZE_T newsize; /* its size */
+ Void_t* newmem; /* corresponding user mem */
+
+ mchunkptr next; /* next contiguous chunk after oldp */
+ mchunkptr prev; /* previous contiguous chunk before oldp */
+
+ mchunkptr remainder; /* extra space at end of newp */
+ long remainder_size; /* its size */
+
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+
+ INTERNAL_SIZE_T copysize; /* bytes to copy */
+ int ncopies; /* INTERNAL_SIZE_T words to copy */
+ INTERNAL_SIZE_T* s; /* copy source */
+ INTERNAL_SIZE_T* d; /* copy destination */
+
+
+#ifdef REALLOC_ZERO_BYTES_FREES
+ if (bytes == 0) {
+ fREe(oldmem);
+ return 0;
+ }
+#endif
+
+ /* realloc of null is supposed to be same as malloc */
+ if (oldmem == 0) return mALLOc(bytes);
+
+ checked_request2size(bytes, nb);
+
+ oldp = mem2chunk(oldmem);
+ oldsize = chunksize(oldp);
+
+ check_inuse_chunk(oldp);
+
+ if (!chunk_is_mmapped(oldp)) {
+
+ if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
+ /* already big enough; split below */
+ newp = oldp;
+ newsize = oldsize;
+ }
+
+ else {
+ newp = 0;
+ newsize = 0;
+
+ next = chunk_at_offset(oldp, oldsize);
+
+ if (next == av->top) { /* Expand forward into top */
+ newsize = oldsize + chunksize(next);
+
+ if ((unsigned long)(newsize) >= (unsigned long)(nb + MINSIZE)) {
+ set_head_size(oldp, nb);
+ av->top = chunk_at_offset(oldp, nb);
+ set_head(av->top, (newsize - nb) | PREV_INUSE);
+ return chunk2mem(oldp);
+ }
+
+ else if (!prev_inuse(oldp)) { /* Shift backwards + top */
+ prev = prev_chunk(oldp);
+ newsize += chunksize(prev);
+
+ if ((unsigned long)(newsize) >= (unsigned long)(nb + MINSIZE)) {
+ newp = prev;
+ unlink(prev, bck, fwd);
+ av->top = chunk_at_offset(newp, nb);
+ set_head(av->top, (newsize - nb) | PREV_INUSE);
+ newsize = nb;
+ }
+ }
+ }
+
+ else if (!inuse(next)) { /* Forward into next chunk */
+ newsize = oldsize + chunksize(next);
+
+ if (((unsigned long)(newsize) >= (unsigned long)(nb))) {
+ newp = oldp;
+ unlink(next, bck, fwd);
+ }
+
+ else if (!prev_inuse(oldp)) { /* Forward + backward */
+ prev = prev_chunk(oldp);
+ newsize += chunksize(prev);
+
+ if (((unsigned long)(newsize) >= (unsigned long)(nb))) {
+ newp = prev;
+ unlink(prev, bck, fwd);
+ unlink(next, bck, fwd);
+ }
+ }
+ }
+
+ else if (!prev_inuse(oldp)) { /* Backward only */
+ prev = prev_chunk(oldp);
+ newsize = oldsize + chunksize(prev);
+
+ if ((unsigned long)(newsize) >= (unsigned long)(nb)) {
+ newp = prev;
+ unlink(prev, bck, fwd);
+ }
+ }
+
+ if (newp != 0) {
+ if (newp != oldp) {
+ /* Backward copies are not worth unrolling */
+ MALLOC_COPY(chunk2mem(newp), oldmem, oldsize - SIZE_SZ, 1);
+ }
+ }
+
+ /* Must allocate */
+ else {
+ newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
+ if (newmem == 0)
+ return 0; /* propagate failure */
+
+ newp = mem2chunk(newmem);
+ newsize = chunksize(newp);
+
+ /*
+ Avoid copy if newp is next chunk after oldp.
+ */
+ if (newp == next) {
+ newsize += oldsize;
+ newp = oldp;
+ }
+ else {
+
+ /*
+ Unroll copy of <= 36 bytes (72 if 8byte sizes)
+ We know that contents have an odd number of
+ INTERNAL_SIZE_T-sized words; minimally 3.
+ */
+
+ copysize = oldsize - SIZE_SZ;
+ s = (INTERNAL_SIZE_T*)oldmem;
+ d = (INTERNAL_SIZE_T*)(chunk2mem(newp));
+ ncopies = copysize / sizeof(INTERNAL_SIZE_T);
+ assert(ncopies >= 3);
+
+ if (ncopies > 9)
+ MALLOC_COPY(d, s, copysize, 0);
+
+ else {
+ *(d+0) = *(s+0);
+ *(d+1) = *(s+1);
+ *(d+2) = *(s+2);
+ if (ncopies > 4) {
+ *(d+3) = *(s+3);
+ *(d+4) = *(s+4);
+ if (ncopies > 6) {
+ *(d+5) = *(s+5);
+ *(d+6) = *(s+6);
+ if (ncopies > 8) {
+ *(d+7) = *(s+7);
+ *(d+8) = *(s+8);
+ }
+ }
+ }
+ }
+
+ fREe(oldmem);
+ check_inuse_chunk(newp);
+ return chunk2mem(newp);
+ }
+ }
+ }
+
+
+ /* If possible, free extra space in old or extended chunk */
+
+ remainder_size = (long)newsize - (long)nb;
+ assert(remainder_size >= 0);
+
+ if (remainder_size >= (long)MINSIZE) { /* split remainder */
+ remainder = chunk_at_offset(newp, nb);
+ set_head_size(newp, nb);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ /* Mark remainder as inuse so free() won't complain */
+ set_inuse_bit_at_offset(remainder, remainder_size);
+ fREe(chunk2mem(remainder));
+ }
+
+ else { /* not enough extra to split off */
+ set_head_size(newp, newsize);
+ set_inuse_bit_at_offset(newp, newsize);
+ }
+
+ check_inuse_chunk(newp);
+ return chunk2mem(newp);
+ }
+
+ /*
+ Handle mmap cases
+ */
+
+ else {
+#if HAVE_MMAP
+
+#if HAVE_MREMAP
+ INTERNAL_SIZE_T offset = oldp->prev_size;
+ size_t pagemask = av->pagesize - 1;
+ char *cp;
+ unsigned long sum;
+
+ /* Note the extra SIZE_SZ overhead */
+ newsize = (nb + offset + SIZE_SZ + pagemask) & ~pagemask;
+
+ /* don't need to remap if still within same page */
+ if (oldsize == newsize - offset)
+ return oldmem;
+
+ cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
+
+ if (cp != (char*)MORECORE_FAILURE) {
+
+ newp = (mchunkptr)(cp + offset);
+ set_head(newp, (newsize - offset)|IS_MMAPPED);
+
+ assert(aligned_OK(chunk2mem(newp)));
+ assert((newp->prev_size == offset));
+
+ /* update statistics */
+ sum = av->mmapped_mem += newsize - oldsize;
+ if (sum > (unsigned long)(av->max_mmapped_mem))
+ av->max_mmapped_mem = sum;
+ sum += av->sbrked_mem;
+ if (sum > (unsigned long)(av->max_total_mem))
+ av->max_total_mem = sum;
+
+ return chunk2mem(newp);
+ }
+
+#endif
+
+ /* Note the extra SIZE_SZ overhead. */
+ if ((long)oldsize - (long)SIZE_SZ >= (long)nb)
+ newmem = oldmem; /* do nothing */
+ else {
+ /* Must alloc, copy, free. */
+ newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
+ if (newmem != 0) {
+ MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ, 0);
+ fREe(oldmem);
+ }
+ }
+ return newmem;
+
+#else
+ /* If !HAVE_MMAP, but chunk_is_mmapped, user must have overwritten mem */
+ check_malloc_state();
+ MALLOC_FAILURE_ACTION;
+ return 0;
+#endif
+ }
+
+}
+
+
+
+/*
+ memalign requests more than enough space from malloc, finds a spot
+ within that chunk that meets the alignment request, and then
+ possibly frees the leading and trailing space.
+
+ Alignments must be powers of two. If the argument is not a
+ power of two, the nearest greater power is used.
+
+ 8-byte alignment is guaranteed by normal malloc calls, so don't
+ bother calling memalign with an argument of 8 or less.
+
+ Overreliance on memalign is a sure way to fragment space.
+*/
+
+
+#if __STD_C
+Void_t* mEMALIGn(size_t alignment, size_t bytes)
+#else
+Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
+#endif
+{
+ INTERNAL_SIZE_T nb; /* padded request size */
+ char* m; /* memory returned by malloc call */
+ mchunkptr p; /* corresponding chunk */
+ char* brk; /* alignment point within p */
+ mchunkptr newp; /* chunk to return */
+ INTERNAL_SIZE_T newsize; /* its size */
+ INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */
+ mchunkptr remainder; /* spare room at end to split off */
+ long remainder_size; /* its size */
+
+
+ /* If need less alignment than we give anyway, just relay to malloc */
+
+ if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);
+
+ /* Otherwise, ensure that it is at least a minimum chunk size */
+
+ if (alignment < MINSIZE) alignment = MINSIZE;
+
+ /* Make sure alignment is power of 2 (in case MINSIZE is not). */
+ if ((alignment & (alignment - 1)) != 0) {
+ size_t a = MALLOC_ALIGNMENT * 2;
+ while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
+ alignment = a;
+ }
+
+ checked_request2size(bytes, nb);
+
+ /* Call malloc with worst case padding to hit alignment. */
+
+ m = (char*)(mALLOc(nb + alignment + MINSIZE));
+
+ if (m == 0) return 0; /* propagate failure */
+
+ p = mem2chunk(m);
+
+ if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */
+
+ /*
+ Find an aligned spot inside chunk. Since we need to give back
+ leading space in a chunk of at least MINSIZE, if the first
+ calculation places us at a spot with less than MINSIZE leader,
+ we can move to the next aligned spot -- we've allocated enough
+ total room so that this is always possible.
+ */
+
+ brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) &
+ -((signed long) alignment));
+ if ((long)(brk - (char*)(p)) < (long)MINSIZE)
+ brk = brk + alignment;
+
+ newp = (mchunkptr)brk;
+ leadsize = brk - (char*)(p);
+ newsize = chunksize(p) - leadsize;
+
+ /* For mmapped chunks, just adjust offset */
+ if (chunk_is_mmapped(p)) {
+ newp->prev_size = p->prev_size + leadsize;
+ set_head(newp, newsize|IS_MMAPPED);
+ return chunk2mem(newp);
+ }
+
+ /* Otherwise, give back leader, use the rest */
+
+ set_head(newp, newsize | PREV_INUSE);
+ set_inuse_bit_at_offset(newp, newsize);
+ set_head_size(p, leadsize);
+ fREe(chunk2mem(p));
+ p = newp;
+
+ assert (newsize >= nb &&
+ (((unsigned long)(chunk2mem(p))) % alignment) == 0);
+ }
+
+ /* Also give back spare room at the end */
+ if (!chunk_is_mmapped(p)) {
+
+ remainder_size = (long)(chunksize(p)) - (long)nb;
+
+ if (remainder_size >= (long)MINSIZE) {
+ remainder = chunk_at_offset(p, nb);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_head_size(p, nb);
+ fREe(chunk2mem(remainder));
+ }
+ }
+
+ check_inuse_chunk(p);
+ return chunk2mem(p);
+
+}
+
+
+
+
+/*
+ calloc calls malloc, then zeroes out the allocated chunk.
+*/
+
+#if __STD_C
+Void_t* cALLOc(size_t n_elements, size_t elem_size)
+#else
+Void_t* cALLOc(n_elements, elem_size) size_t n_elements; size_t elem_size;
+#endif
+{
+ mchunkptr p;
+ INTERNAL_SIZE_T clearsize;
+ int nclears;
+ INTERNAL_SIZE_T* d;
+
+ Void_t* mem = mALLOc(n_elements * elem_size);
+
+ if (mem != 0) {
+ p = mem2chunk(mem);
+ if (!chunk_is_mmapped(p)) { /* don't need to clear mmapped space */
+
+ /*
+ Unroll clear of <= 36 bytes (72 if 8byte sizes)
+ We know that contents have an odd number of
+ INTERNAL_SIZE_T-sized words; minimally 3.
+ */
+
+ d = (INTERNAL_SIZE_T*)mem;
+ clearsize = chunksize(p) - SIZE_SZ;
+ nclears = clearsize / sizeof(INTERNAL_SIZE_T);
+ assert(nclears >= 3);
+
+ if (nclears > 9)
+ MALLOC_ZERO(d, clearsize);
+
+ else {
+ *(d+0) = 0;
+ *(d+1) = 0;
+ *(d+2) = 0;
+ if (nclears > 4) {
+ *(d+3) = 0;
+ *(d+4) = 0;
+ if (nclears > 6) {
+ *(d+5) = 0;
+ *(d+6) = 0;
+ if (nclears > 8) {
+ *(d+7) = 0;
+ *(d+8) = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ return mem;
+}
+
+
+/*
+ cfree just calls free. It is needed/defined on some systems
+ that pair it with calloc, presumably for odd historical reasons
+ (such as: cfree is used in example code in first edition of K&R).
+*/
+
+#if __STD_C
+void cFREe(Void_t *mem)
+#else
+void cFREe(mem) Void_t *mem;
+#endif
+{
+ fREe(mem);
+}
+
+
+
+
+
+/*
+ valloc just invokes memalign with alignment argument equal
+ to the page size of the system (or as near to this as can
+ be figured out from all the includes/defines above.)
+*/
+
+#if __STD_C
+Void_t* vALLOc(size_t bytes)
+#else
+Void_t* vALLOc(bytes) size_t bytes;
+#endif
+{
+ /* Ensure initialization/consolidation */
+ mstate av = get_malloc_state();
+ malloc_consolidate(av);
+ return mEMALIGn(av->pagesize, bytes);
+}
+
+/*
+ pvalloc just invokes valloc for the nearest pagesize
+ that will accommodate request
+*/
+
+
+#if __STD_C
+Void_t* pVALLOc(size_t bytes)
+#else
+Void_t* pVALLOc(bytes) size_t bytes;
+#endif
+{
+ mstate av = get_malloc_state();
+ size_t pagesz;
+
+ /* Ensure initialization/consolidation */
+ malloc_consolidate(av);
+
+ pagesz = av->pagesize;
+ return mEMALIGn(pagesz, (bytes + pagesz - 1) & ~(pagesz - 1));
+}
+
+
+/*
+ Malloc_Trim gives memory back to the system (via negative
+ arguments to sbrk) if there is unused memory at the `high' end of
+ the malloc pool. You can call this after freeing large blocks of
+ memory to potentially reduce the system-level memory requirements
+ of a program. However, it cannot guarantee to reduce memory. Under
+ some allocation patterns, some large free blocks of memory will be
+ locked between two used chunks, so they cannot be given back to
+ the system.
+
+ The `pad' argument to malloc_trim represents the amount of free
+ trailing space to leave untrimmed. If this argument is zero,
+ only the minimum amount of memory to maintain internal data
+ structures will be left (one page or less). Non-zero arguments
+ can be supplied to maintain enough trailing space to service
+ future expected allocations without having to re-obtain memory
+ from the system.
+
+ Malloc_trim returns 1 if it actually released any memory, else 0.
+*/
+
+#if __STD_C
+int mTRIm(size_t pad)
+#else
+int mTRIm(pad) size_t pad;
+#endif
+{
+ mstate av = get_malloc_state();
+ /* Ensure initialization/consolidation */
+ malloc_consolidate(av);
+
+ return sYSTRIm(pad, av);
+}
+
+/*
+ malloc_usable_size tells you how many bytes you can actually use in
+ an allocated chunk, which may be more than you requested (although
+ often not). You can use this many bytes without worrying about
+ overwriting other allocated objects. Not a particularly great
+ programming practice, but still sometimes useful.
+*/
+
+#if __STD_C
+size_t mUSABLe(Void_t* mem)
+#else
+size_t mUSABLe(mem) Void_t* mem;
+#endif
+{
+ mchunkptr p;
+ if (mem != 0) {
+ p = mem2chunk(mem);
+ if (chunk_is_mmapped(p))
+ return chunksize(p) - 2*SIZE_SZ;
+ else if (inuse(p))
+ return chunksize(p) - SIZE_SZ;
+ }
+ return 0;
+}
+
+
+
+
+/*
+ mallinfo returns a copy of updated current mallinfo.
+*/
+
+struct mallinfo mALLINFo()
+{
+ mstate av = get_malloc_state();
+ struct mallinfo mi;
+ int i;
+ mbinptr b;
+ mchunkptr p;
+ INTERNAL_SIZE_T avail;
+ int navail;
+ int nfastblocks;
+ int fastbytes;
+
+ /* Ensure initialization */
+ if (av->top == 0) malloc_consolidate(av);
+
+ check_malloc_state();
+
+ /* Account for top */
+ avail = chunksize(av->top);
+ navail = 1; /* top always exists */
+
+ /* traverse fastbins */
+ nfastblocks = 0;
+ fastbytes = 0;
+
+ for (i = 0; i < NFASTBINS; ++i) {
+ for (p = av->fastbins[i]; p != 0; p = p->fd) {
+ ++nfastblocks;
+ fastbytes += chunksize(p);
+ }
+ }
+
+ avail += fastbytes;
+
+ /* traverse regular bins */
+ for (i = 1; i < NBINS; ++i) {
+ b = bin_at(av, i);
+ for (p = last(b); p != b; p = p->bk) {
+ avail += chunksize(p);
+ navail++;
+ }
+ }
+
+ mi.smblks = nfastblocks;
+ mi.ordblks = navail;
+ mi.fordblks = avail;
+ mi.uordblks = av->sbrked_mem - avail;
+ mi.arena = av->sbrked_mem;
+ mi.hblks = av->n_mmaps;
+ mi.hblkhd = av->mmapped_mem;
+ mi.fsmblks = fastbytes;
+ mi.keepcost = chunksize(av->top);
+ mi.usmblks = av->max_total_mem;
+ return mi;
+}
+
+
+
+/*
+ malloc_stats prints on stderr the amount of space obtained from the
+ system (both via sbrk and mmap), the maximum amount (which may be
+ more than current if malloc_trim and/or munmap got called), and the
+ current number of bytes allocated via malloc (or realloc, etc) but
+ not yet freed. Note that this is the number of bytes allocated, not
+ the number requested. It will be larger than the number requested
+ because of alignment and bookkeeping overhead. Because it includes
+ alignment wastage as being in use, this figure may be greater than zero
+ even when no user-level chunks are allocated.
+
+ The reported current and maximum system memory can be inaccurate if
+ a program makes other calls to system memory allocation functions
+ (normally sbrk) outside of malloc.
+
+ malloc_stats prints only the most commonly interesting statistics.
+ More information can be obtained by calling mallinfo.
+*/
+
+void mSTATs()
+{
+ struct mallinfo mi = mALLINFo();
+
+#ifdef WIN32
+ {
+ unsigned long free, reserved, committed;
+ vminfo (&free, &reserved, &committed);
+ fprintf(stderr, "free bytes = %10lu\n",
+ free);
+ fprintf(stderr, "reserved bytes = %10lu\n",
+ reserved);
+ fprintf(stderr, "committed bytes = %10lu\n",
+ committed);
+ }
+#endif
+
+
+ fprintf(stderr, "max system bytes = %10lu\n",
+ (unsigned long)(mi.usmblks));
+ fprintf(stderr, "system bytes = %10lu\n",
+ (unsigned long)(mi.arena + mi.hblkhd));
+ fprintf(stderr, "in use bytes = %10lu\n",
+ (unsigned long)(mi.uordblks + mi.hblkhd));
+
+#ifdef WIN32
+ {
+ unsigned long kernel, user;
+ if (cpuinfo (TRUE, &kernel, &user)) {
+ fprintf(stderr, "kernel ms = %10lu\n",
+ kernel);
+ fprintf(stderr, "user ms = %10lu\n",
+ user);
+ }
+ }
+#endif
+}
+
+
+
+/*
+ mallopt is the general SVID/XPG interface to tunable parameters.
+ The format is to provide a (parameter-number, parameter-value)
+ pair. mallopt then sets the corresponding parameter to the
+ argument value if it can (i.e., so long as the value is
+ meaningful), and returns 1 if successful else 0. See descriptions
+ of tunable parameters above for meanings.
+*/
+
+#if __STD_C
+int mALLOPt(int param_number, int value)
+#else
+int mALLOPt(param_number, value) int param_number; int value;
+#endif
+{
+ mstate av = get_malloc_state();
+ /* Ensure initialization/consolidation */
+ malloc_consolidate(av);
+
+ switch(param_number) {
+ case M_MXFAST:
+ if (value >= 0 && value <= MAX_FAST_SIZE) {
+ av->max_fast = req2max_fast(value);
+ return 1;
+ }
+ else
+ return 0;
+
+ case M_TRIM_THRESHOLD:
+ av->trim_threshold = value;
+ return 1;
+
+ case M_TOP_PAD:
+ av->top_pad = value;
+ return 1;
+
+ case M_MMAP_THRESHOLD:
+ av->mmap_threshold = value;
+ return 1;
+
+ case M_MMAP_MAX:
+#if HAVE_MMAP
+ av->n_mmaps_max = value;
+ return 1;
+#else
+ if (value != 0)
+ return 0;
+ else {
+ av->n_mmaps_max = value;
+ return 1;
+ }
+#endif
+
+ default:
+ return 0;
+ }
+}
+
+
+/* -------------------------------------------------------------- */
+
+/*
+ Emulation of sbrk for win32.
+ Donated by J. Walter <Walter@GeNeSys-e.de>.
+ For additional information about this code, and malloc on Win32, see
+ http://www.genesys-e.de/jwalter/
+
+*/
+
+
+#ifdef WIN32
+
+#ifdef _DEBUG
+/* #define TRACE */
+#endif
+
+/* Support for USE_MALLOC_LOCK */
+#ifdef USE_MALLOC_LOCK
+
+/* Wait for spin lock */
+static int slwait (int *sl) {
+ while (InterlockedCompareExchange ((void **) sl, (void *) 1, (void *) 0) != 0)
+ Sleep (0);
+ return 0;
+}
+
+/* Release spin lock */
+static int slrelease (int *sl) {
+ InterlockedExchange (sl, 0);
+ return 0;
+}
+
+#ifdef NEEDED
+/* Spin lock for emulation code */
+static int g_sl;
+#endif
+
+#endif /* USE_MALLOC_LOCK */
+
+/* getpagesize for windows */
+static long getpagesize (void) {
+ static long g_pagesize = 0;
+ if (! g_pagesize) {
+ SYSTEM_INFO system_info;
+ GetSystemInfo (&system_info);
+ g_pagesize = system_info.dwPageSize;
+ }
+ return g_pagesize;
+}
+static long getregionsize (void) {
+ static long g_regionsize = 0;
+ if (! g_regionsize) {
+ SYSTEM_INFO system_info;
+ GetSystemInfo (&system_info);
+ g_regionsize = system_info.dwAllocationGranularity;
+ }
+ return g_regionsize;
+}
+
+/* A region list entry */
+typedef struct _region_list_entry {
+ void *top_allocated;
+ void *top_committed;
+ void *top_reserved;
+ long reserve_size;
+ struct _region_list_entry *previous;
+} region_list_entry;
+
+/* Allocate and link a region entry in the region list */
+static int region_list_append (region_list_entry **last, void *base_reserved, long reserve_size) {
+ region_list_entry *next = HeapAlloc (GetProcessHeap (), 0, sizeof (region_list_entry));
+ if (! next)
+ return FALSE;
+ next->top_allocated = (char *) base_reserved;
+ next->top_committed = (char *) base_reserved;
+ next->top_reserved = (char *) base_reserved + reserve_size;
+ next->reserve_size = reserve_size;
+ next->previous = *last;
+ *last = next;
+ return TRUE;
+}
+/* Free and unlink the last region entry from the region list */
+static int region_list_remove (region_list_entry **last) {
+ region_list_entry *previous = (*last)->previous;
+ if (! HeapFree (GetProcessHeap (), sizeof (region_list_entry), *last))
+ return FALSE;
+ *last = previous;
+ return TRUE;
+}
+
+#define CEIL(size,to) (((size)+(to)-1)&~((to)-1))
+#define FLOOR(size,to) ((size)&~((to)-1))
+
+#define SBRK_SCALE 0
+/* #define SBRK_SCALE 1 */
+/* #define SBRK_SCALE 2 */
+/* #define SBRK_SCALE 4 */
+
+/* sbrk for windows */
+static void *sbrk (long size) {
+ static long g_pagesize, g_my_pagesize;
+ static long g_regionsize, g_my_regionsize;
+ static region_list_entry *g_last;
+ void *result = (void *) MORECORE_FAILURE;
+#ifdef TRACE
+ printf ("sbrk %d\n", size);
+#endif
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Wait for spin lock */
+ slwait (&g_sl);
+#endif
+ /* First time initialization */
+ if (! g_pagesize) {
+ g_pagesize = getpagesize ();
+ g_my_pagesize = g_pagesize << SBRK_SCALE;
+ }
+ if (! g_regionsize) {
+ g_regionsize = getregionsize ();
+ g_my_regionsize = g_regionsize << SBRK_SCALE;
+ }
+ if (! g_last) {
+ if (! region_list_append (&g_last, 0, 0))
+ goto sbrk_exit;
+ }
+ /* Assert invariants */
+ assert (g_last);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&
+ g_last->top_allocated <= g_last->top_committed);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&
+ g_last->top_committed <= g_last->top_reserved &&
+ (unsigned) g_last->top_committed % g_pagesize == 0);
+ assert ((unsigned) g_last->top_reserved % g_regionsize == 0);
+ assert ((unsigned) g_last->reserve_size % g_regionsize == 0);
+ /* Allocation requested? */
+ if (size >= 0) {
+ /* Allocation size is the requested size */
+ long allocate_size = size;
+ /* Compute the size to commit */
+ long to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
+ /* Do we reach the commit limit? */
+ if (to_commit > 0) {
+ /* Round size to commit */
+ long commit_size = CEIL (to_commit, g_my_pagesize);
+ /* Compute the size to reserve */
+ long to_reserve = (char *) g_last->top_committed + commit_size - (char *) g_last->top_reserved;
+ /* Do we reach the reserve limit? */
+ if (to_reserve > 0) {
+ /* Compute the remaining size to commit in the current region */
+ long remaining_commit_size = (char *) g_last->top_reserved - (char *) g_last->top_committed;
+ if (remaining_commit_size > 0) {
+ /* Assert preconditions */
+ assert ((unsigned) g_last->top_committed % g_pagesize == 0);
+ assert (0 < remaining_commit_size && remaining_commit_size % g_pagesize == 0); {
+ /* Commit this */
+ void *base_committed = VirtualAlloc (g_last->top_committed, remaining_commit_size,
+ MEM_COMMIT, PAGE_READWRITE);
+ /* Check returned pointer for consistency */
+ if (base_committed != g_last->top_committed)
+ goto sbrk_exit;
+ /* Assert postconditions */
+ assert ((unsigned) base_committed % g_pagesize == 0);
+#ifdef TRACE
+ printf ("Commit %p %d\n", base_committed, remaining_commit_size);
+#endif
+ /* Adjust the regions commit top */
+ g_last->top_committed = (char *) base_committed + remaining_commit_size;
+ }
+ } {
+ /* Now we are going to search and reserve. */
+ int contiguous = -1;
+ int found = FALSE;
+ MEMORY_BASIC_INFORMATION memory_info;
+ void *base_reserved;
+ long reserve_size;
+ do {
+ /* Assume contiguous memory */
+ contiguous = TRUE;
+ /* Round size to reserve */
+ reserve_size = CEIL (to_reserve, g_my_regionsize);
+ /* Start with the current region's top */
+ memory_info.BaseAddress = g_last->top_reserved;
+ /* Assert preconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
+ assert (0 < reserve_size && reserve_size % g_regionsize == 0);
+ while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {
+ /* Assert postconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
+#ifdef TRACE
+ printf ("Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize,
+ memory_info.State == MEM_FREE ? "FREE":
+ (memory_info.State == MEM_RESERVE ? "RESERVED":
+ (memory_info.State == MEM_COMMIT ? "COMMITTED": "?")));
+#endif
+ /* Region is free, well aligned and big enough: we are done */
+ if (memory_info.State == MEM_FREE &&
+ (unsigned) memory_info.BaseAddress % g_regionsize == 0 &&
+ memory_info.RegionSize >= (unsigned) reserve_size) {
+ found = TRUE;
+ break;
+ }
+ /* From now on we can't get contiguous memory! */
+ contiguous = FALSE;
+ /* Recompute size to reserve */
+ reserve_size = CEIL (allocate_size, g_my_regionsize);
+ memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;
+ /* Assert preconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
+ assert (0 < reserve_size && reserve_size % g_regionsize == 0);
+ }
+ /* Search failed? */
+ if (! found)
+ goto sbrk_exit;
+ /* Assert preconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_regionsize == 0);
+ assert (0 < reserve_size && reserve_size % g_regionsize == 0);
+ /* Try to reserve this */
+ base_reserved = VirtualAlloc (memory_info.BaseAddress, reserve_size,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (! base_reserved) {
+ int rc = GetLastError ();
+ if (rc != ERROR_INVALID_ADDRESS)
+ goto sbrk_exit;
+ }
+ /* A null pointer signals (hopefully) a race condition with another thread. */
+ /* In this case, we try again. */
+ } while (! base_reserved);
+ /* Check returned pointer for consistency */
+ if (memory_info.BaseAddress && base_reserved != memory_info.BaseAddress)
+ goto sbrk_exit;
+ /* Assert postconditions */
+ assert ((unsigned) base_reserved % g_regionsize == 0);
+#ifdef TRACE
+ printf ("Reserve %p %d\n", base_reserved, reserve_size);
+#endif
+ /* Did we get contiguous memory? */
+ if (contiguous) {
+ long start_size = (char *) g_last->top_committed - (char *) g_last->top_allocated;
+ /* Adjust allocation size */
+ allocate_size -= start_size;
+ /* Adjust the regions allocation top */
+ g_last->top_allocated = g_last->top_committed;
+ /* Recompute the size to commit */
+ to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
+ /* Round size to commit */
+ commit_size = CEIL (to_commit, g_my_pagesize);
+ }
+ /* Append the new region to the list */
+ if (! region_list_append (&g_last, base_reserved, reserve_size))
+ goto sbrk_exit;
+ /* Didn't we get contiguous memory? */
+ if (! contiguous) {
+ /* Recompute the size to commit */
+ to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
+ /* Round size to commit */
+ commit_size = CEIL (to_commit, g_my_pagesize);
+ }
+ }
+ }
+ /* Assert preconditions */
+ assert ((unsigned) g_last->top_committed % g_pagesize == 0);
+ assert (0 < commit_size && commit_size % g_pagesize == 0); {
+ /* Commit this */
+ void *base_committed = VirtualAlloc (g_last->top_committed, commit_size,
+ MEM_COMMIT, PAGE_READWRITE);
+ /* Check returned pointer for consistency */
+ if (base_committed != g_last->top_committed)
+ goto sbrk_exit;
+ /* Assert postconditions */
+ assert ((unsigned) base_committed % g_pagesize == 0);
+#ifdef TRACE
+ printf ("Commit %p %d\n", base_committed, commit_size);
+#endif
+ /* Adjust the regions commit top */
+ g_last->top_committed = (char *) base_committed + commit_size;
+ }
+ }
+ /* Adjust the regions allocation top */
+ g_last->top_allocated = (char *) g_last->top_allocated + allocate_size;
+ result = (char *) g_last->top_allocated - size;
+ /* Deallocation requested? */
+ } else if (size < 0) {
+ long deallocate_size = - size;
+ /* As long as we have a region to release */
+ while ((char *) g_last->top_allocated - deallocate_size < (char *) g_last->top_reserved - g_last->reserve_size) {
+ /* Get the size to release */
+ long release_size = g_last->reserve_size;
+ /* Get the base address */
+ void *base_reserved = (char *) g_last->top_reserved - release_size;
+ /* Assert preconditions */
+ assert ((unsigned) base_reserved % g_regionsize == 0);
+ assert (0 < release_size && release_size % g_regionsize == 0); {
+ /* Release this */
+ int rc = VirtualFree (base_reserved, 0,
+ MEM_RELEASE);
+ /* Check returned code for consistency */
+ if (! rc)
+ goto sbrk_exit;
+#ifdef TRACE
+ printf ("Release %p %d\n", base_reserved, release_size);
+#endif
+ }
+ /* Adjust deallocation size */
+ deallocate_size -= (char *) g_last->top_allocated - (char *) base_reserved;
+ /* Remove the old region from the list */
+ if (! region_list_remove (&g_last))
+ goto sbrk_exit;
+ } {
+ /* Compute the size to decommit */
+ long to_decommit = (char *) g_last->top_committed - ((char *) g_last->top_allocated - deallocate_size);
+ if (to_decommit >= g_my_pagesize) {
+ /* Compute the size to decommit */
+ long decommit_size = FLOOR (to_decommit, g_my_pagesize);
+ /* Compute the base address */
+ void *base_committed = (char *) g_last->top_committed - decommit_size;
+ /* Assert preconditions */
+ assert ((unsigned) base_committed % g_pagesize == 0);
+ assert (0 < decommit_size && decommit_size % g_pagesize == 0); {
+ /* Decommit this */
+ int rc = VirtualFree ((char *) base_committed, decommit_size,
+ MEM_DECOMMIT);
+ /* Check returned code for consistency */
+ if (! rc)
+ goto sbrk_exit;
+#ifdef TRACE
+ printf ("Decommit %p %d\n", base_committed, decommit_size);
+#endif
+ }
+ /* Adjust deallocation size and regions commit and allocate top */
+ deallocate_size -= (char *) g_last->top_allocated - (char *) base_committed;
+ g_last->top_committed = base_committed;
+ g_last->top_allocated = base_committed;
+ }
+ }
+ /* Adjust regions allocate top */
+ g_last->top_allocated = (char *) g_last->top_allocated - deallocate_size;
+ /* Check for underflow */
+ if ((char *) g_last->top_reserved - g_last->reserve_size > (char *) g_last->top_allocated ||
+ g_last->top_allocated > g_last->top_committed) {
+ /* Adjust regions allocate top */
+ g_last->top_allocated = (char *) g_last->top_reserved - g_last->reserve_size;
+ goto sbrk_exit;
+ }
+ result = g_last->top_allocated;
+ }
+ /* Assert invariants */
+ assert (g_last);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&
+ g_last->top_allocated <= g_last->top_committed);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&
+ g_last->top_committed <= g_last->top_reserved &&
+ (unsigned) g_last->top_committed % g_pagesize == 0);
+ assert ((unsigned) g_last->top_reserved % g_regionsize == 0);
+ assert ((unsigned) g_last->reserve_size % g_regionsize == 0);
+
+sbrk_exit:
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Release spin lock */
+ slrelease (&g_sl);
+#endif
+ return result;
+}
+
+/* mmap for windows */
+static void *mmap (void *ptr, long size, long prot, long type, long handle, long arg) {
+ static long g_pagesize;
+ static long g_regionsize;
+#ifdef TRACE
+ printf ("mmap %d\n", size);
+#endif
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Wait for spin lock */
+ slwait (&g_sl);
+#endif
+ /* First time initialization */
+ if (! g_pagesize)
+ g_pagesize = getpagesize ();
+ if (! g_regionsize)
+ g_regionsize = getregionsize ();
+ /* Assert preconditions */
+ assert ((unsigned) ptr % g_regionsize == 0);
+ assert (size % g_pagesize == 0);
+ /* Allocate this */
+ ptr = VirtualAlloc (ptr, size,
+ MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
+ if (! ptr) {
+ ptr = (void *) MORECORE_FAILURE;
+ goto mmap_exit;
+ }
+ /* Assert postconditions */
+ assert ((unsigned) ptr % g_regionsize == 0);
+#ifdef TRACE
+ printf ("Commit %p %d\n", ptr, size);
+#endif
+mmap_exit:
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Release spin lock */
+ slrelease (&g_sl);
+#endif
+ return ptr;
+}
+
+/* munmap for windows */
+static long munmap (void *ptr, long size) {
+ static long g_pagesize;
+ static long g_regionsize;
+ int rc = MUNMAP_FAILURE;
+#ifdef TRACE
+ printf ("munmap %p %d\n", ptr, size);
+#endif
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Wait for spin lock */
+ slwait (&g_sl);
+#endif
+ /* First time initialization */
+ if (! g_pagesize)
+ g_pagesize = getpagesize ();
+ if (! g_regionsize)
+ g_regionsize = getregionsize ();
+ /* Assert preconditions */
+ assert ((unsigned) ptr % g_regionsize == 0);
+ assert (size % g_pagesize == 0);
+ /* Free this */
+ if (! VirtualFree (ptr, 0,
+ MEM_RELEASE))
+ goto munmap_exit;
+ rc = 0;
+#ifdef TRACE
+ printf ("Release %p %d\n", ptr, size);
+#endif
+munmap_exit:
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Release spin lock */
+ slrelease (&g_sl);
+#endif
+ return rc;
+}
+
+static void vminfo (unsigned long *free, unsigned long *reserved, unsigned long *committed) {
+ MEMORY_BASIC_INFORMATION memory_info;
+ memory_info.BaseAddress = 0;
+ *free = *reserved = *committed = 0;
+ while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {
+ switch (memory_info.State) {
+ case MEM_FREE:
+ *free += memory_info.RegionSize;
+ break;
+ case MEM_RESERVE:
+ *reserved += memory_info.RegionSize;
+ break;
+ case MEM_COMMIT:
+ *committed += memory_info.RegionSize;
+ break;
+ }
+ memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;
+ }
+}
+
+static int cpuinfo (int whole, unsigned long *kernel, unsigned long *user) {
+ if (whole) {
+ __int64 creation64, exit64, kernel64, user64;
+ int rc = GetProcessTimes (GetCurrentProcess (),
+ (FILETIME *) &creation64,
+ (FILETIME *) &exit64,
+ (FILETIME *) &kernel64,
+ (FILETIME *) &user64);
+ if (! rc) {
+ *kernel = 0;
+ *user = 0;
+ return FALSE;
+ }
+ *kernel = (unsigned long) (kernel64 / 10000);
+ *user = (unsigned long) (user64 / 10000);
+ return TRUE;
+ } else {
+ __int64 creation64, exit64, kernel64, user64;
+ int rc = GetThreadTimes (GetCurrentThread (),
+ (FILETIME *) &creation64,
+ (FILETIME *) &exit64,
+ (FILETIME *) &kernel64,
+ (FILETIME *) &user64);
+ if (! rc) {
+ *kernel = 0;
+ *user = 0;
+ return FALSE;
+ }
+ *kernel = (unsigned long) (kernel64 / 10000);
+ *user = (unsigned long) (user64 / 10000);
+ return TRUE;
+ }
+}
+
+#endif /* WIN32 */
+
+/*
+
+History:
+
+ V2.7.0
+ * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
+ * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
+ helping test this.)
+ * memalign: check alignment arg
+ * realloc: use memmove when regions may overlap.
+ * Collect all cases in malloc requiring system memory into sYSMALLOc
+ * Use mmap as backup to sbrk, if available; fold these mmap-related
+ operations into others.
+ * Place all internal state in malloc_state
+ * Introduce fastbins (although similar to 2.5.1)
+ * Many minor tunings and cosmetic improvements
+ * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
+ * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
+ Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
+ * Adjust request2size to fit with MALLOC_FAILURE_ACTION.
+ * Include errno.h to support default failure action.
+ * Further improve WIN32 'sbrk()' emulation's 'findRegion()' routine
+ to avoid infinite loop when allocating initial memory larger
+ than RESERVED_SIZE and/or subsequent memory larger than
+ NEXT_SIZE. Thanks to Andreas Mueller <a.mueller at paradatec.de>
+ for finding this one.
+
+ V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
+ * return null for negative arguments
+ * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
+ * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
+ (e.g. WIN32 platforms)
+ * Cleanup header file inclusion for WIN32 platforms
+ * Cleanup code to avoid Microsoft Visual C++ compiler complaints
+ * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
+ memory allocation routines
+ * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
+ * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
+ usage of 'assert' in non-WIN32 code
+ * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
+ avoid infinite loop
+ * Always call 'fREe()' rather than 'free()'
+
+ V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
+ * Fixed ordering problem with boundary-stamping
+
+ V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
+ * Added pvalloc, as recommended by H.J. Liu
+ * Added 64bit pointer support mainly from Wolfram Gloger
+ * Added anonymously donated WIN32 sbrk emulation
+ * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
+ * malloc_extend_top: fix mask error that caused wastage after
+ foreign sbrks
+ * Add linux mremap support code from HJ Liu
+
+ V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
+ * Integrated most documentation with the code.
+ * Add support for mmap, with help from
+ Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+ * Use last_remainder in more cases.
+ * Pack bins using idea from colin@nyx10.cs.du.edu
+ * Use ordered bins instead of best-fit threshhold
+ * Eliminate block-local decls to simplify tracing and debugging.
+ * Support another case of realloc via move into top
+ * Fix error occuring when initial sbrk_base not word-aligned.
+ * Rely on page size for units instead of SBRK_UNIT to
+ avoid surprises about sbrk alignment conventions.
+ * Add mallinfo, mallopt. Thanks to Raymond Nijssen
+ (raymond@es.ele.tue.nl) for the suggestion.
+ * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
+ * More precautions for cases where other routines call sbrk,
+ courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+ * Added macros etc., allowing use in linux libc from
+ H.J. Lu (hjl@gnu.ai.mit.edu)
+ * Inverted this history list
+
+ V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
+ * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
+ * Removed all preallocation code since under current scheme
+ the work required to undo bad preallocations exceeds
+ the work saved in good cases for most test programs.
+ * No longer use return list or unconsolidated bins since
+ no scheme using them consistently outperforms those that don't
+ given above changes.
+ * Use best fit for very large chunks to prevent some worst-cases.
+ * Added some support for debugging
+
+ V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
+ * Removed footers when chunks are in use. Thanks to
+ Paul Wilson (wilson@cs.texas.edu) for the suggestion.
+
+ V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
+ * Added malloc_trim, with help from Wolfram Gloger
+ (wmglo@Dent.MED.Uni-Muenchen.DE).
+
+ V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
+
+ V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
+ * realloc: try to expand in both directions
+ * malloc: swap order of clean-bin strategy;
+ * realloc: only conditionally expand backwards
+ * Try not to scavenge used bins
+ * Use bin counts as a guide to preallocation
+ * Occasionally bin return list chunks in first scan
+ * Add a few optimizations from colin@nyx10.cs.du.edu
+
+ V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
+ * faster bin computation & slightly different binning
+ * merged all consolidations to one part of malloc proper
+ (eliminating old malloc_find_space & malloc_clean_bin)
+ * Scan 2 returns chunks (not just 1)
+ * Propagate failure in realloc if malloc returns 0
+ * Add stuff to allow compilation on non-ANSI compilers
+ from kpv@research.att.com
+
+ V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
+ * removed potential for odd address access in prev_chunk
+ * removed dependency on getpagesize.h
+ * misc cosmetics and a bit more internal documentation
+ * anticosmetics: mangled names in macros to evade debugger strangeness
+ * tested on sparc, hp-700, dec-mips, rs6000
+ with gcc & native cc (hp, dec only) allowing
+ Detlefs & Zorn comparison study (in SIGPLAN Notices.)
+
+ Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
+ * Based loosely on libg++-1.2X malloc. (It retains some of the overall
+ structure of old version, but most details differ.)
+
+*/
+
+
diff --git a/src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp b/src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp
new file mode 100644
index 00000000..c9c04b30
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp
@@ -0,0 +1,753 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * innotek GmbH.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * innotek GmbH / Knut St. Osmundsen
+ *
+ * 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 ***** */
+
+/*
+ * This module contains wrappers for a handful of XPCOM methods which someone
+ * have been so kind as to link their plugins against. This module will only
+ * provide the minimum of what necessary to make legacy plugins work with
+ * the GCC based mozilla. Luckily this only means the IBM oji JAVA plugins.
+ *
+ * Actually, I haven't seen npoji6 calling any of these yet.
+ */
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** @group Visual Age for C++ v3.6.5 target (OS/2). */
+/* @{ */
+/** Indicate Visual Age for C++ v3.6.5 target */
+#define VFT_VAC365 1
+/** VFTable/Interface Calling Convention for Win32. */
+#define VFTCALL _Optlink
+/** First Entry which VAC uses. */
+#define VFTFIRST_DECL unsigned uFirst[2]
+#define VFTFIRST_VAL() {0, 0},
+/** This deltas which VAC uses. */
+#define VFTDELTA_DECL(n) unsigned uDelta##n
+#define VFTDELTA_VAL() 0,
+/** @} */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "nscore.h"
+#include "nsIServiceManagerUtils.h"
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+#ifndef __cplusplus
+typedef struct nsID
+{
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+} nsID, nsCID, nsIID;
+#define REFNSIID const nsIID *
+
+typedef PRUint32 nsrefcnt;
+#endif
+
+
+/**
+ * nsISupports vftable.
+ */
+typedef struct vftable_nsISupports
+{
+ VFTFIRST_DECL;
+ nsresult (*VFTCALL QueryInterface)(void *pvThis, REFNSIID aIID, void** aInstancePtr);
+ VFTDELTA_DECL(QueryInterface);
+ nsrefcnt (*VFTCALL AddRef)(void *pvThis);
+ VFTDELTA_DECL(AddRef);
+ nsrefcnt (*VFTCALL Release)(void *pvThis);
+ VFTDELTA_DECL(Release);
+} VFTnsISupports;
+
+/**
+ * nsGetServiceByCID::nsCOMPtr_helper vftable.
+ */
+typedef struct vftable_nsGetServiceByCID_nsCOMPtr_helper
+{
+ VFTFIRST_DECL;
+ /* virtual nsresult operator()( const nsIID&, void** ) const; */
+ nsresult (*VFTCALL __operator_paratheses)(void *pvThis, REFNSIID aIID, void** aInstancePtr);
+ VFTDELTA_DECL(__operator_paratheses);
+ void * (*VFTCALL __destructor)(void *pvThis, unsigned __dtorFlags, unsigned __vtt);
+ VFTDELTA_DECL(__destructor);
+} VFTnsGetServiceByCID_nsCOMPtr_helper;
+
+/**
+ * nsQueryInterface::nsCOMPtr_helper vftable.
+ */
+typedef struct vftable_nsQueryInterface_nsCOMPtr_helper
+{
+ VFTFIRST_DECL;
+ nsresult (*VFTCALL __operator_paratheses)(void *pvThis, REFNSIID aIID, void** aInstancePtr);
+ VFTDELTA_DECL(__operator_paratheses);
+} VFTnsQueryInterface_nsCOMPtr_helper;
+
+
+
+
+/**
+ * nsISupport object.
+ */
+typedef struct obj_nsISupports
+{
+ VFTnsISupports *pVFT;
+} obj_nsISupports;
+
+/**
+ * nsCOMPtr_base object.
+ */
+typedef struct obj_nsCOMPtr_base
+{
+ obj_nsISupports *mRawPtr;
+} obj_nsCOMPtr_base;
+
+/**
+ * nsGetServiceByCID_nsCOMPtr_helper object.
+ */
+typedef struct obj_nsGetServiceByCID_nsCOMPtr_helper
+{
+ VFTnsGetServiceByCID_nsCOMPtr_helper *pVFT; /* ?? */
+ nsID *mCID; /* const nsCID& */
+ void *mServiceManager;/* nsCOMPtr<nsIServiceManager> */
+ nsresult *mErrorPtr;
+} obj_nsGetServiceByCID_nsCOMPtr_helper;
+
+/**
+ * nsQueryInterface_nsCOMPtr_helper object.
+ */
+typedef struct obj_nsQueryInterface_nsCOMPtr_helper
+{
+ VFTnsQueryInterface_nsCOMPtr_helper *pVFT; /* ?? */
+ obj_nsISupports *mRawPtr; /* const nsCID& */
+ nsresult *mErrorPtr;
+} obj_nsQueryInterface_nsCOMPtr_helper;
+
+
+
+
+/**
+ * nsCOMPtr_base::~nsCOMPtr_base()
+ *
+ * @remark This guys doing the oji plugin have been very unfortunate to link in this
+ * without any similar new operator. The object is thus created in the plugin
+ * but freed by xpcom.dll. As the plugin and mozilla have different CRTs this
+ * is a good way of asking for trouble. But, they guys've been lucky, the VAC
+ * CRT might just handle this ok.
+ * However, we cannot perform this delete as we have no VAC CRT around, and
+ * hence we will leak this object.
+ * ----
+ * assembly:
+ public __dt__13nsCOMPtr_baseFv
+__dt__13nsCOMPtr_baseFv proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; __dtorFlags
+
+; 63 if ( mRawPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax],0h
+ je @BLBL4
+
+; 64 NSCAP_RELEASE(this, mRawPtr);
+ mov ecx,[ebp+08h]; this
+ mov ecx,[ecx]
+ mov ecx,[ecx]
+ mov eax,[ebp+08h]; this
+ mov eax,[eax]
+ add eax,[ecx+01ch]
+ mov ecx,[ebp+08h]; this
+ mov ecx,[ecx]
+ mov ecx,[ecx]
+ call dword ptr [ecx+018h]
+@BLBL4:
+
+; 65 }
+ test byte ptr [ebp+0ch],01h; __dtorFlags
+ je @BLBL6
+ mov eax,[ebp+08h]; this
+ call __dl__FPv
+@BLBL6:
+ mov eax,[ebp+08h]; this
+ add esp,08h
+ pop ebp
+ ret
+__dt__13nsCOMPtr_baseFv endp
+*/
+extern "C" void * VFTCALL __dt__13nsCOMPtr_baseFv(void *pvThis, unsigned __dtorFlags)
+{
+ obj_nsCOMPtr_base *pThis = (obj_nsCOMPtr_base*)pvThis;
+//asm("int $3");
+ if (pThis->mRawPtr)
+ {
+ /* NSCAP_RELEASE(this, mRawPtr); */
+ pThis->mRawPtr->pVFT->Release((char*)pThis->mRawPtr + pThis->mRawPtr->pVFT->uDeltaRelease);
+ }
+
+ /*
+ * Delete the object...
+ * (As memtioned before we'll rather leak this.)
+ */
+ #if 0
+ if (!(__dtorFlags & 1))
+ __dl__FPv(this)
+ #endif
+
+ return pvThis;
+}
+
+/** workaround for _Optlink bug.. */
+extern "C" void * VFTCALL _dt__13nsCOMPtr_baseFv(void *pvThis, unsigned __dtorFlags)
+{
+ return __dt__13nsCOMPtr_baseFv(pvThis, __dtorFlags);
+}
+
+
+
+/**
+ *
+ * -----
+ * assembly:
+; 92 nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+ align 010h
+
+ public __cl__17nsGetServiceByCIDCFRC4nsIDPPv
+__cl__17nsGetServiceByCIDCFRC4nsIDPPv proc
+ push ebp
+ mov ebp,esp
+ sub esp,014h
+ push ebx
+ sub esp,08h
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; aIID
+ mov [ebp+010h],ecx; aInstancePtr
+
+; 94 nsresult status = NS_ERROR_FAILURE;
+ mov dword ptr [ebp-04h],080004005h; status
+
+; 95 if ( mServiceManager ) {
+ mov eax,[ebp+08h]; this
+ add eax,08h
+ call __opP13nsDerivedSafeXT17nsIServiceManager___8nsCOMPtrXT17nsIServiceManager_CFv
+ test eax,eax
+ je @BLBL13
+
+; 96 status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr);
+ mov eax,[ebp+08h]; this
+ add eax,08h
+ call __rf__8nsCOMPtrXT17nsIServiceManager_CFv
+ mov [ebp-08h],eax; __212
+ mov eax,[ebp+010h]; aInstancePtr
+ push eax
+ mov ecx,[ebp+0ch]; aIID
+ mov edx,[ebp+08h]; this
+ mov edx,[edx+04h]
+ mov ebx,[ebp-08h]; __212
+ mov ebx,[ebx]
+ mov eax,[ebp-08h]; __212
+ add eax,[ebx+024h]
+ sub esp,0ch
+ mov ebx,[ebp-08h]; __212
+ mov ebx,[ebx]
+ call dword ptr [ebx+020h]
+ add esp,010h
+ mov [ebp-04h],eax; status
+
+; 97 } else {
+ jmp @BLBL14
+ align 010h
+@BLBL13:
+
+; 95 if ( mServiceManager ) {
+
+; 98 nsCOMPtr<nsIServiceManager> mgr;
+ lea eax,[ebp-0ch]; mgr
+ call __ct__8nsCOMPtrXT17nsIServiceManager_Fv
+
+; 99 NS_GetServiceManager(getter_AddRefs(mgr));
+ lea edx,[ebp-0ch]; mgr
+ lea eax,[ebp-010h]; __216
+ call getter_AddRefs__FR8nsCOMPtrXT17nsIServiceManager_
+ sub esp,04h
+ lea eax,[ebp-010h]; __216
+ sub esp,04h
+ call __opPP17nsIServiceManager__15nsGetterAddRefsXT17nsIServiceManager_Fv
+ add esp,08h
+ call NS_GetServiceManager
+ mov edx,02h
+ lea eax,[ebp-010h]; __216
+ call __dt__15nsGetterAddRefsXT17nsIServiceManager_Fv
+
+; 100 if (mgr)
+ lea eax,[ebp-0ch]; mgr
+ call __opP13nsDerivedSafeXT17nsIServiceManager___8nsCOMPtrXT17nsIServiceManager_CFv
+ test eax,eax
+ je @BLBL15
+
+; 101 status = mgr->GetService(mCID, aIID, (void**)aInstancePtr);
+ lea eax,[ebp-0ch]; mgr
+ call __rf__8nsCOMPtrXT17nsIServiceManager_CFv
+ mov [ebp-014h],eax; __217
+ mov eax,[ebp+010h]; aInstancePtr
+ push eax
+ mov ecx,[ebp+0ch]; aIID
+ mov edx,[ebp+08h]; this
+ mov edx,[edx+04h]
+ mov ebx,[ebp-014h]; __217
+ mov ebx,[ebx]
+ mov eax,[ebp-014h]; __217
+ add eax,[ebx+024h]
+ sub esp,0ch
+ mov ebx,[ebp-014h]; __217
+ mov ebx,[ebx]
+ call dword ptr [ebx+020h]
+ add esp,010h
+ mov [ebp-04h],eax; status
+@BLBL15:
+
+; 102 }
+ mov edx,02h
+ lea eax,[ebp-0ch]; mgr
+ call __dt__8nsCOMPtrXT17nsIServiceManager_Fv
+@BLBL14:
+
+; 103 if ( NS_FAILED(status) )
+ test byte ptr [ebp-01h],080h; status
+ je @BLBL16
+
+; 104 *aInstancePtr = 0;
+ mov eax,[ebp+010h]; aInstancePtr
+ mov dword ptr [eax],0h
+@BLBL16:
+
+; 106 if ( mErrorPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax+0ch],0h
+ je @BLBL17
+
+; 107 *mErrorPtr = status;
+ mov eax,[ebp+08h]; this
+ mov eax,[eax+0ch]
+ mov ebx,[ebp-04h]; status
+ mov [eax],ebx
+@BLBL17:
+
+; 108 return status;
+ mov eax,[ebp-04h]; status
+ add esp,08h
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ ret
+__cl__17nsGetServiceByCIDCFRC4nsIDPPv endp
+
+ * -----
+ * C++ Code:
+nsresult
+nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status = NS_ERROR_FAILURE;
+ if ( mServiceManager ) {
+ status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetService(mCID, aIID, (void**)aInstancePtr);
+ }
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+ */
+extern "C" nsresult VFTCALL GSBC_COM__operator_paratheses(void *pvThis, REFNSIID aIID, void** aInstancePtr)
+{
+ obj_nsGetServiceByCID_nsCOMPtr_helper *pThis = (obj_nsGetServiceByCID_nsCOMPtr_helper *)pvThis;
+ nsresult status = NS_ERROR_FAILURE;
+//asm("int $3");
+
+ /* For convenience we don't use mServiceManager here because it's a wrapped object.
+ * We ASSUME that there is only one service manager floating around....
+ */
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetService(*pThis->mCID, aIID, (void**)aInstancePtr);
+
+ if (NS_FAILED(status))
+ *aInstancePtr = 0;
+
+ if (pThis->mErrorPtr)
+ *pThis->mErrorPtr = status;
+ return status;
+}
+
+/**
+ * Just a destructor.
+ * -----
+ * assembly:
+; 59 virtual ~nsGetServiceByCID() {};
+ align 010h
+
+__dt__17nsGetServiceByCIDFv proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; __dtorFlags
+ mov [ebp+010h],ecx; __vtt
+ mov eax,[ebp+08h]; this
+ mov dword ptr [eax],offset FLAT:__vft17nsGetServiceByCID15nsCOMPtr_helper
+ mov edx,02h
+ mov eax,[ebp+08h]; this
+ add eax,08h
+ call __dt__8nsCOMPtrXT17nsIServiceManager_Fv
+ test byte ptr [ebp+0ch],01h; __dtorFlags
+ je @BLBL24
+ mov eax,[ebp+08h]; this
+ call __dl__FPv
+@BLBL24:
+ mov eax,[ebp+08h]; this
+ add esp,08h
+ pop ebp
+ ret
+__dt__17nsGetServiceByCIDFv endp
+ */
+extern "C" void * VFTCALL GSBC_COM__destructor(void *pvThis, unsigned __dtorFlags, unsigned __vtt)
+{
+ obj_nsGetServiceByCID_nsCOMPtr_helper *pThis = (obj_nsGetServiceByCID_nsCOMPtr_helper *)pvThis;
+//asm("int $3");
+
+ /*
+ * Because previously mentioned issues with VAC heaps, we'll
+ * not do anything in here.
+ * (We will then skip destruction of all parents and such, but
+ * I don't think that will hurt anyone.)
+ */
+ __dtorFlags = __dtorFlags;
+ __vtt = __vtt;
+ return pThis;
+}
+
+
+/**
+ * VFT for nsGetServiceByCID::nsCOMPtr_helper or something like that.
+ * It's just implementing an operator() and the destructor.
+ *
+ * @remark We need to skip an underscore to get the name right.
+ * ----
+ * assembly:
+__vft17nsGetServiceByCID15nsCOMPtr_helper dd 0
+ db 0h,0h,0h,0h
+ dd offset FLAT:__cl__17nsGetServiceByCIDCFRC4nsIDPPv
+ db 0h,0h,0h,0h
+ dd offset FLAT:__dt__17nsGetServiceByCIDFv
+ db 0h,0h,0h,0h
+ */
+extern const VFTnsGetServiceByCID_nsCOMPtr_helper _vft17nsGetServiceByCID15nsCOMPtr_helper =
+{
+ VFTFIRST_VAL()
+ GSBC_COM__operator_paratheses, VFTDELTA_VAL()
+ GSBC_COM__destructor, VFTDELTA_VAL()
+};
+
+
+
+/**
+ *
+ * -----
+ * assembly
+; 42 nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const
+ align 010h
+
+ public __cl__16nsQueryInterfaceCFRC4nsIDPPv
+__cl__16nsQueryInterfaceCFRC4nsIDPPv proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ push ebx
+ sub esp,0ch
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; aIID
+ mov [ebp+010h],ecx; answer
+
+; 45 if ( mRawPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax+04h],0h
+ je @BLBL1
+
+; 46 {
+; 47 status = mRawPtr->QueryInterface(aIID, answer);
+ mov ecx,[ebp+010h]; answer
+ mov edx,[ebp+0ch]; aIID
+ mov ebx,[ebp+08h]; this
+ mov ebx,[ebx+04h]
+ mov ebx,[ebx]
+ mov eax,[ebp+08h]; this
+ mov eax,[eax+04h]
+ add eax,[ebx+0ch]
+ mov ebx,[ebp+08h]; this
+ mov ebx,[ebx+04h]
+ mov ebx,[ebx]
+ call dword ptr [ebx+08h]
+ mov [ebp-04h],eax; status
+
+; 48 #ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+; 49 NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+; 50 #endif
+; 51 }
+ jmp @BLBL2
+ align 010h
+@BLBL1:
+
+; 45 if ( mRawPtr )
+
+; 53 status = NS_ERROR_NULL_POINTER;
+ mov dword ptr [ebp-04h],080004003h; status
+@BLBL2:
+
+; 55 if ( mErrorPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax+08h],0h
+ je @BLBL3
+
+; 56 *mErrorPtr = status;
+ mov eax,[ebp+08h]; this
+ mov eax,[eax+08h]
+ mov ebx,[ebp-04h]; status
+ mov [eax],ebx
+@BLBL3:
+
+; 57 return status;
+ mov eax,[ebp-04h]; status
+ add esp,0ch
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ ret
+__cl__16nsQueryInterfaceCFRC4nsIDPPv endp
+
+ * -----
+ * C++ Code:
+nsresult
+nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mRawPtr )
+ {
+ status = mRawPtr->QueryInterface(aIID, answer);
+#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+#endif
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+ */
+extern "C" nsresult VFTCALL QI_COM__operator_paratheses(void *pvThis, REFNSIID aIID, void** aInstancePtr)
+{
+ obj_nsQueryInterface_nsCOMPtr_helper *pThis = (obj_nsQueryInterface_nsCOMPtr_helper *)pvThis;
+ nsresult status = NS_ERROR_NULL_POINTER;
+//asm("int $3");
+
+ if (pThis->mRawPtr)
+ {
+ status = pThis->mRawPtr->pVFT->QueryInterface(pThis->mRawPtr, aIID, aInstancePtr);
+ /* don't care about warnings, do we? */
+ }
+
+ if (pThis->mErrorPtr)
+ *pThis->mErrorPtr = status;
+ return status;
+}
+
+
+
+/**
+ * VFT for nsQueryInterface::nsCOMPtr_helper or something like that.
+ * No destructor, only an operator().
+ *
+ * @remark We need to skip an underscore to get the name right.
+ * -----
+ * assembly:
+__vft16nsQueryInterface15nsCOMPtr_helper dd 0
+ db 0h,0h,0h,0h
+ dd offset FLAT:__cl__16nsQueryInterfaceCFRC4nsIDPPv
+ db 0h,0h,0h,0h
+ */
+extern const VFTnsQueryInterface_nsCOMPtr_helper _vft16nsQueryInterface15nsCOMPtr_helper =
+{
+ VFTFIRST_VAL()
+ QI_COM__operator_paratheses, VFTDELTA_VAL()
+};
+
+/**
+ *
+ * -----
+ * C++ Code:
+void
+assign_assuming_AddRef( nsISupports* newPtr )
+{
+ / *
+ |AddRef()|ing the new value (before entering this function) before
+ |Release()|ing the old lets us safely ignore the self-assignment case.
+ We must, however, be careful only to |Release()| _after_ doing the
+ assignment, in case the |Release()| leads to our _own_ destruction,
+ which would, in turn, cause an incorrect second |Release()| of our old
+ pointer. Thank <waterson@netscape.com> for discovering this.
+ * /
+ nsISupports* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ NSCAP_LOG_ASSIGNMENT(this, newPtr);
+ NSCAP_LOG_RELEASE(this, oldPtr);
+ if ( oldPtr )
+ NSCAP_RELEASE(this, oldPtr);
+}
+ */
+extern "C" void VFTCALL assign_assuming_AddRef__13nsCOMPtr_baseFP11nsISupports(void *pvThis, obj_nsISupports *newPtr)
+{
+ obj_nsCOMPtr_base *pThis = (obj_nsCOMPtr_base *)pvThis;
+ obj_nsISupports *oldPtr;
+
+ oldPtr = pThis->mRawPtr;
+ pThis->mRawPtr = newPtr;
+ if (oldPtr)
+ {
+ /* NSCAP_RELEASE(this, oldPtr); */
+ pThis->mRawPtr->pVFT->Release(oldPtr + oldPtr->pVFT->uDeltaRelease);
+ }
+}
+
+
+
+
+/**
+ *
+ * -----
+ * Assembly:
+; 77 nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid )
+ align 010h
+
+ public assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID
+assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ push ebx
+ sub esp,0ch
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; helper
+ mov [ebp+010h],ecx; iid
+
+; 80 if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ lea ecx,[ebp-04h]; newRawPtr
+ mov edx,[ebp+010h]; iid
+ mov ebx,[ebp+0ch]; helper
+ mov ebx,[ebx]
+ mov eax,[ebp+0ch]; helper
+ add eax,[ebx+0ch]
+ mov ebx,[ebp+0ch]; helper
+ mov ebx,[ebx]
+ call dword ptr [ebx+08h]
+ test eax,080000000h
+ je @BLBL8
+
+; 81 newRawPtr = 0;
+ mov dword ptr [ebp-04h],0h; newRawPtr
+@BLBL8:
+
+; 82 assign_assuming_AddRef(newRawPtr);
+ mov edx,[ebp-04h]; newRawPtr
+ mov eax,[ebp+08h]; this
+ call assign_assuming_AddRef__13nsCOMPtr_baseFP11nsISupports
+ add esp,0ch
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ ret
+assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID endp
+
+ * -----
+ * C Code:
+void
+nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+ */
+extern "C" void VFTCALL assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID(
+ void *pvThis, void * helper, REFNSIID iid)
+{
+ obj_nsCOMPtr_base *pThis = (obj_nsCOMPtr_base *)pvThis;
+ obj_nsISupports* newRawPtr = NULL;
+ nsresult status = NS_ERROR_FAILURE;
+//asm("int $3");
+
+ /* this may or may not be correct but the layout is the same. */
+ obj_nsQueryInterface_nsCOMPtr_helper * pHelper = (obj_nsQueryInterface_nsCOMPtr_helper*)helper;
+
+ /* if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) */
+ status = pHelper->pVFT->__operator_paratheses((char*)pHelper + pHelper->pVFT->uDelta__operator_paratheses,
+ iid, (void**)&newRawPtr);
+ if (NS_FAILED(status))
+ newRawPtr = 0;
+
+ /* assign_assuming_AddRef(newRawPtr); */
+ assign_assuming_AddRef__13nsCOMPtr_baseFP11nsISupports(pThis, newRawPtr);
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp b/src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp
new file mode 100644
index 00000000..ca9a76e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp
@@ -0,0 +1,261 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+#include "nsCharTraits.h"
+
+#define NS_STRINGAPI_IMPL
+#include "nsStringAPI.h"
+#include "nsNativeCharsetUtils.h"
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_StringContainerInit(nsStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsStringContainer) >= sizeof(nsString),
+ "nsStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsString object
+ new (&aContainer) nsString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_StringContainerFinish(nsStringContainer &aContainer)
+{
+ // call the nsString dtor
+ NS_REINTERPRET_CAST(nsString *, &aContainer)->~nsString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_StringGetData(const nsAString &aStr, const PRUnichar **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsAString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(PRUnichar *)
+NS_StringCloneData(const nsAString &aStr)
+{
+ return ToNewUnicode(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetData(nsAString &aStr, const PRUnichar *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetDataRange(nsAString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const PRUnichar *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringContainerInit(nsCStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsCStringContainer) >= sizeof(nsCString),
+ "nsCStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsCString object
+ new (&aContainer) nsCString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_CStringContainerFinish(nsCStringContainer &aContainer)
+{
+ // call the nsCString dtor
+ NS_REINTERPRET_CAST(nsCString *, &aContainer)->~nsCString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_CStringGetData(const nsACString &aStr, const char **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsACString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(char *)
+NS_CStringCloneData(const nsACString &aStr)
+{
+ return ToNewCString(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetData(nsACString &aStr, const char *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetDataRange(nsACString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const char *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringToUTF16(const nsACString &aSrc,
+ nsCStringEncoding aSrcEncoding,
+ nsAString &aDest)
+{
+ switch (aSrcEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ CopyASCIItoUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF8toUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyNativeToUnicode(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_UTF16ToCString(const nsAString &aSrc,
+ nsCStringEncoding aDestEncoding,
+ nsACString &aDest)
+{
+ switch (aDestEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ LossyCopyUTF16toASCII(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF16toUTF8(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyUnicodeToNative(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPCOM.h b/src/libs/xpcom18a4/xpcom/build/nsXPCOM.h
new file mode 100644
index 00000000..4e60c74e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPCOM.h
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsXPCOM_h__
+#define nsXPCOM_h__
+
+#include "nscore.h"
+#include "nsXPCOMCID.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_InitXPCOM2 VBoxNsxpNS_InitXPCOM2
+#define NS_ShutdownXPCOM VBoxNsxpNS_ShutdownXPCOM
+#define NS_NewNativeLocalFile VBoxNsxpNS_NewNativeLocalFile
+#define NS_GetServiceManager VBoxNsxpNS_GetServiceManager
+#define NS_GetComponentManager VBoxNsxpNS_GetComponentManager
+#define NS_GetComponentRegistrar VBoxNsxpNS_GetComponentRegistrar
+#define NS_GetDebug VBoxNsxpNS_GetDebug
+#define NS_GetMemoryManager VBoxNsxpNS_GetMemoryManager
+#define NS_GetTraceRefcnt VBoxNsxpNS_GetTraceRefcnt
+#define NS_NewLocalFile VBoxNsxpNS_NewLocalFile
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+class nsAString;
+class nsACString;
+
+class nsIComponentManager;
+class nsIComponentRegistrar;
+class nsIServiceManager;
+class nsIFile;
+class nsILocalFile;
+class nsIDirectoryServiceProvider;
+class nsIMemory;
+class nsIDebug;
+class nsITraceRefcnt;
+
+/**
+ * Initialises XPCOM. You must call this method before proceeding
+ * to use xpcom. The one exception is that you may call
+ * NS_NewLocalFile to create a nsIFile.
+ *
+ * @status FROZEN
+ *
+ * @note Use <CODE>NS_NewLocalFile</CODE> or <CODE>NS_NewNativeLocalFile</CODE>
+ * to create the file object you supply as the bin directory path in this
+ * call. The function may be safely called before the rest of XPCOM or
+ * embedding has been initialised.
+ *
+ * @param result The service manager. You may pass null.
+ *
+ * @param binDirectory The directory containing the component
+ * registry and runtime libraries;
+ * or use <CODE>nsnull</CODE> to use the working
+ * directory.
+ *
+ * @param appFileLocationProvider The object to be used by Gecko that specifies
+ * to Gecko where to find profiles, the component
+ * registry preferences and so on; or use
+ * <CODE>nsnull</CODE> for the default behaviour.
+ *
+ * @see NS_NewLocalFile
+ * @see nsILocalFile
+ * @see nsIDirectoryServiceProvider
+ *
+ * @return NS_OK for success;
+ * NS_ERROR_NOT_INITIALIZED if static globals were not initialied, which
+ * can happen if XPCOM is reloaded, but did not completly shutdown.
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_InitXPCOM2(nsIServiceManager* *result,
+ nsIFile* binDirectory,
+ nsIDirectoryServiceProvider* appFileLocationProvider);
+/**
+ * Shutdown XPCOM. You must call this method after you are finished
+ * using xpcom.
+ *
+ * @status FROZEN
+ *
+ * @param servMgr The service manager which was returned by NS_InitXPCOM2.
+ * This will release servMgr. You may pass null.
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_ShutdownXPCOM(nsIServiceManager* servMgr);
+
+
+/**
+ * Public Method to access to the service manager.
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the service manager
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result);
+
+/**
+ * Public Method to access to the component manager.
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the service
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result);
+
+/**
+ * Public Method to access to the component registration manager.
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the service
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result);
+
+/**
+ * Public Method to access to the memory manager. See nsIMemory
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the memory manager
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetMemoryManager(nsIMemory* *result);
+
+/**
+ * Public Method to create an instance of a nsILocalFile. This function
+ * may be called prior to NS_InitXPCOM2.
+ *
+ * @status FROZEN
+ *
+ * @param path
+ * A string which specifies a full file path to a
+ * location. Relative paths will be treated as an
+ * error (NS_ERROR_FILE_UNRECOGNIZED_PATH).
+ * |NS_NewNativeLocalFile|'s path must be in the
+ * filesystem charset.
+ * @param followLinks
+ * This attribute will determine if the nsLocalFile will auto
+ * resolve symbolic links. By default, this value will be false
+ * on all non unix systems. On unix, this attribute is effectively
+ * a noop.
+ * @param result Interface pointer to a new instance of an nsILocalFile
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure.
+ */
+
+extern "C" NS_COM nsresult
+NS_NewLocalFile(const nsAString &path,
+ PRBool followLinks,
+ nsILocalFile* *result);
+
+extern "C" NS_COM nsresult
+NS_NewNativeLocalFile(const nsACString &path,
+ PRBool followLinks,
+ nsILocalFile* *result);
+
+
+extern "C" NS_COM nsresult
+NS_GetDebug(nsIDebug* *result);
+
+extern "C" NS_COM nsresult
+NS_GetTraceRefcnt(nsITraceRefcnt* *result);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h b/src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h
new file mode 100644
index 00000000..d5bd039c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsXPCOMCID_h__
+#define nsXPCOMCID_h__
+
+/**
+ * XPCOM Directory Service Contract ID
+ * The directory service provides ways to obtain file system locations. The
+ * directory service is a singleton.
+ *
+ * This contract supports the nsIDirectoryService and the nsIProperties
+ * interfaces.
+ *
+ */
+#define NS_DIRECTORY_SERVICE_CONTRACTID "@mozilla.org/file/directory_service;1"
+
+/**
+ * XPCOM File
+ * The file abstraction provides ways to obtain and access files and
+ * directories located on the local system.
+ *
+ * This contract supports the nsIFile interface and the nsILocalFile interface.
+ * This contract may also support platform specific interfaces such as
+ * nsILocalFileMac on platforms where additional interfaces are required.
+ *
+ */
+#define NS_LOCAL_FILE_CONTRACTID "@mozilla.org/file/local;1"
+
+/**
+ * XPCOM Category Manager Contract ID
+ * The contract supports the nsICategoryManager interface. The
+ * category manager is a singleton.
+ */
+#define NS_CATEGORYMANAGER_CONTRACTID "@mozilla.org/categorymanager;1"
+
+/**
+ * XPCOM Properties Object Contract ID
+ * Simple mapping object which supports the nsIProperties interface.
+ */
+#define NS_PROPERTIES_CONTRACTID "@mozilla.org/properties;1"
+
+/**
+ * XPCOM Array Object ContractID
+ * Simple array implementation which supports the nsIArray and
+ * nsIMutableArray interfaces.
+ */
+#define NS_ARRAY_CONTRACTID "@mozilla.org/array;1"
+
+/**
+ * The following are the CIDs and Contract IDs of the nsISupports wrappers for
+ * primative types.
+ */
+#define NS_SUPPORTS_ID_CID \
+{ 0xacf8dc40, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_ID_CONTRACTID "@mozilla.org/supports-id;1"
+
+#define NS_SUPPORTS_CSTRING_CID \
+{ 0xacf8dc41, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_CSTRING_CONTRACTID "@mozilla.org/supports-cstring;1"
+
+#define NS_SUPPORTS_STRING_CID \
+{ 0xacf8dc42, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_STRING_CONTRACTID "@mozilla.org/supports-string;1"
+
+#define NS_SUPPORTS_PRBOOL_CID \
+{ 0xacf8dc43, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRBOOL_CONTRACTID "@mozilla.org/supports-PRBool;1"
+
+#define NS_SUPPORTS_PRUINT8_CID \
+{ 0xacf8dc44, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT8_CONTRACTID "@mozilla.org/supports-PRUint8;1"
+
+#define NS_SUPPORTS_PRUINT16_CID \
+{ 0xacf8dc46, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT16_CONTRACTID "@mozilla.org/supports-PRUint16;1"
+
+#define NS_SUPPORTS_PRUINT32_CID \
+{ 0xacf8dc47, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT32_CONTRACTID "@mozilla.org/supports-PRUint32;1"
+
+#define NS_SUPPORTS_PRUINT64_CID \
+{ 0xacf8dc48, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT64_CONTRACTID "@mozilla.org/supports-PRUint64;1"
+
+#define NS_SUPPORTS_PRTIME_CID \
+{ 0xacf8dc49, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRTIME_CONTRACTID "@mozilla.org/supports-PRTime;1"
+
+#define NS_SUPPORTS_CHAR_CID \
+{ 0xacf8dc4a, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_CHAR_CONTRACTID "@mozilla.org/supports-char;1"
+
+#define NS_SUPPORTS_PRINT16_CID \
+{ 0xacf8dc4b, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRINT16_CONTRACTID "@mozilla.org/supports-PRInt16;1"
+
+#define NS_SUPPORTS_PRINT32_CID \
+{ 0xacf8dc4c, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRINT32_CONTRACTID "@mozilla.org/supports-PRInt32;1"
+
+#define NS_SUPPORTS_PRINT64_CID \
+{ 0xacf8dc4d, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRINT64_CONTRACTID "@mozilla.org/supports-PRInt64;1"
+
+#define NS_SUPPORTS_FLOAT_CID \
+{ 0xcbf86870, 0x4ac0, 0x11d3, \
+{ 0xba, 0xea, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
+#define NS_SUPPORTS_FLOAT_CONTRACTID "@mozilla.org/supports-float;1"
+
+#define NS_SUPPORTS_DOUBLE_CID \
+{ 0xcbf86871, 0x4ac0, 0x11d3, \
+{ 0xba, 0xea, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
+#define NS_SUPPORTS_DOUBLE_CONTRACTID "@mozilla.org/supports-double;1"
+
+#define NS_SUPPORTS_VOID_CID \
+{ 0xaf10f3e0, 0x568d, 0x11d3, \
+{ 0xba, 0xf8, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
+#define NS_SUPPORTS_VOID_CONTRACTID "@mozilla.org/supports-void;1"
+
+#define NS_SUPPORTS_INTERFACE_POINTER_CID \
+{ 0xA99FEBBA, 0x1DD1, 0x11B2, \
+{ 0xA9, 0x43, 0xB0, 0x23, 0x34, 0xA6, 0xD0, 0x83 } }
+#define NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID "@mozilla.org/supports-interface-pointer;1"
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h b/src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h
new file mode 100644
index 00000000..cd526ba3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsXPComPrivate_h__
+#define nsXPComPrivate_h__
+
+#include "nscore.h"
+#include "nsXPCOM.h"
+
+class nsStringContainer;
+class nsCStringContainer;
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_GetFrozenFunctions VBoxNsxpNS_GetFrozenFunctions
+#define NS_RegisterXPCOMExitRoutine VBoxNsxpNS_RegisterXPCOMExitRoutine
+#define NS_UnregisterXPCOMExitRoutine VBoxNsxpNS_UnregisterXPCOMExitRoutine
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/**
+ * Private Method to register an exit routine. This method
+ * allows you to setup a callback that will be called from
+ * the NS_ShutdownXPCOM function after all services and
+ * components have gone away.
+ *
+ * This API is for the exclusive use of the xpcom glue library.
+ *
+ * Note that these APIs are NOT threadsafe and must be called on the
+ * main thread.
+ *
+ * @status FROZEN
+ * @param exitRoutine pointer to user defined callback function
+ * of type XPCOMExitRoutine.
+ * @param priority higher priorities are called before lower
+ * priorities.
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure.
+ *
+ */
+typedef NS_CALLBACK(XPCOMExitRoutine)(void);
+
+extern "C" NS_COM nsresult
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority);
+
+extern "C" NS_COM nsresult
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine);
+
+
+// PUBLIC
+typedef nsresult (* InitFunc)(nsIServiceManager* *result, nsIFile* binDirectory, nsIDirectoryServiceProvider* appFileLocationProvider);
+typedef nsresult (* ShutdownFunc)(nsIServiceManager* servMgr);
+typedef nsresult (* GetServiceManagerFunc)(nsIServiceManager* *result);
+typedef nsresult (* GetComponentManagerFunc)(nsIComponentManager* *result);
+typedef nsresult (* GetComponentRegistrarFunc)(nsIComponentRegistrar* *result);
+typedef nsresult (* GetMemoryManagerFunc)(nsIMemory* *result);
+typedef nsresult (* NewLocalFileFunc)(const nsAString &path, PRBool followLinks, nsILocalFile* *result);
+typedef nsresult (* NewNativeLocalFileFunc)(const nsACString &path, PRBool followLinks, nsILocalFile* *result);
+
+typedef nsresult (* GetDebugFunc)(nsIDebug* *result);
+typedef nsresult (* GetTraceRefcntFunc)(nsITraceRefcnt* *result);
+
+typedef nsresult (* StringContainerInitFunc)(nsStringContainer&);
+typedef void (* StringContainerFinishFunc)(nsStringContainer&);
+typedef PRUint32 (* StringGetDataFunc)(const nsAString&, const PRUnichar**, PRBool*);
+typedef PRUnichar* (* StringCloneDataFunc)(const nsAString&);
+typedef nsresult (* StringSetDataFunc)(nsAString&, const PRUnichar*, PRUint32);
+typedef nsresult (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, const PRUnichar*, PRUint32);
+typedef nsresult (* StringCopyFunc)(nsAString &, const nsAString &);
+
+typedef nsresult (* CStringContainerInitFunc)(nsCStringContainer&);
+typedef void (* CStringContainerFinishFunc)(nsCStringContainer&);
+typedef PRUint32 (* CStringGetDataFunc)(const nsACString&, const char**, PRBool*);
+typedef char* (* CStringCloneDataFunc)(const nsACString&);
+typedef nsresult (* CStringSetDataFunc)(nsACString&, const char*, PRUint32);
+typedef nsresult (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32);
+typedef nsresult (* CStringCopyFunc)(nsACString &, const nsACString &);
+
+typedef nsresult (* CStringToUTF16)(const nsACString &, PRUint32, const nsAString &);
+typedef nsresult (* UTF16ToCString)(const nsAString &, PRUint32, const nsACString &);
+
+// PRIVATE
+typedef nsresult (* RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority);
+typedef nsresult (* UnregisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine);
+
+typedef struct XPCOMFunctions{
+ PRUint32 version;
+ PRUint32 size;
+
+ InitFunc init;
+ ShutdownFunc shutdown;
+ GetServiceManagerFunc getServiceManager;
+ GetComponentManagerFunc getComponentManager;
+ GetComponentRegistrarFunc getComponentRegistrar;
+ GetMemoryManagerFunc getMemoryManager;
+ NewLocalFileFunc newLocalFile;
+ NewNativeLocalFileFunc newNativeLocalFile;
+
+ RegisterXPCOMExitRoutineFunc registerExitRoutine;
+ UnregisterXPCOMExitRoutineFunc unregisterExitRoutine;
+
+ // Added for Mozilla 1.5
+ GetDebugFunc getDebug;
+ GetTraceRefcntFunc getTraceRefcnt;
+
+ // Added for Mozilla 1.7
+ StringContainerInitFunc stringContainerInit;
+ StringContainerFinishFunc stringContainerFinish;
+ StringGetDataFunc stringGetData;
+ StringSetDataFunc stringSetData;
+ StringSetDataRangeFunc stringSetDataRange;
+ StringCopyFunc stringCopy;
+ CStringContainerInitFunc cstringContainerInit;
+ CStringContainerFinishFunc cstringContainerFinish;
+ CStringGetDataFunc cstringGetData;
+ CStringSetDataFunc cstringSetData;
+ CStringSetDataRangeFunc cstringSetDataRange;
+ CStringCopyFunc cstringCopy;
+ CStringToUTF16 cstringToUTF16;
+ UTF16ToCString utf16ToCString;
+ StringCloneDataFunc stringCloneData;
+ CStringCloneDataFunc cstringCloneData;
+
+} XPCOMFunctions;
+
+typedef nsresult (PR_CALLBACK *GetFrozenFunctionsFunc)(XPCOMFunctions *entryPoints, const char* libraryPath);
+extern "C" NS_COM nsresult
+NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath);
+
+// think hard before changing this
+#define XPCOM_GLUE_VERSION 1
+
+
+/* XPCOM Specific Defines
+ *
+ * XPCOM_DLL - name of the loadable xpcom library on disk.
+ * XPCOM_SEARCH_KEY - name of the environment variable that can be
+ * modified to include additional search paths.
+ * GRE_CONF_NAME - Name of the GRE Configuration file
+ */
+
+#ifdef XPCOM_DLL_BASE
+#define XPCOM_DLL XPCOM_DLL_BASE MOZ_DLL_SUFFIX
+#endif
+
+#if defined(XP_WIN32) || defined(XP_OS2)
+
+#define XPCOM_SEARCH_KEY "PATH"
+#define GRE_CONF_NAME "gre.config"
+#define GRE_WIN_REG_LOC "Software\\mozilla.org\\GRE\\"
+#ifndef XPCOM_DLL
+#define XPCOM_DLL "xpcom"MOZ_DLL_SUFFIX
+#endif
+
+#elif defined(XP_BEOS)
+
+#define XPCOM_SEARCH_KEY "ADDON_PATH"
+#define GRE_CONF_NAME ".gre.config"
+#define GRE_CONF_PATH "/boot/home/config/settings/GRE/gre.conf"
+#ifndef XPCOM_DLL
+#define XPCOM_DLL "libxpcom"MOZ_DLL_SUFFIX
+#endif
+
+#else // Unix
+
+#ifndef XPCOM_DLL
+#define XPCOM_DLL "libxpcom"MOZ_DLL_SUFFIX
+#endif
+
+// you have to love apple..
+#ifdef XP_MACOSX
+#define XPCOM_SEARCH_KEY "DYLD_LIBRARY_PATH"
+#else
+#define XPCOM_SEARCH_KEY "LD_LIBRARY_PATH"
+#endif
+
+#define GRE_CONF_NAME ".gre.config"
+#define GRE_CONF_PATH "/etc/gre.conf"
+#define GRE_CONF_DIR "/etc/gre.d/"
+#endif
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ #define XPCOM_FILE_PATH_SEPARATOR "\\"
+ #define XPCOM_ENV_PATH_SEPARATOR ";"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ #define XPCOM_FILE_PATH_SEPARATOR "/"
+ #define XPCOM_ENV_PATH_SEPARATOR ":"
+#else
+ #error need_to_define_your_file_path_separator_and_illegal_characters
+#endif
+
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp b/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp
new file mode 100644
index 00000000..65d84b6b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp
@@ -0,0 +1,1079 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nscore.h"
+#include "prlink.h"
+#include "nsCOMPtr.h"
+#include "nsObserverList.h"
+#include "nsObserverService.h"
+#include "nsProperties.h"
+#include "nsIProperties.h"
+#include "nsPersistentProperties.h"
+#include "nsScriptableInputStream.h"
+#include "nsBinaryStream.h"
+#include "nsStorageStream.h"
+
+#include "nsMemoryImpl.h"
+#include "nsDebugImpl.h"
+#include "nsTraceRefcntImpl.h"
+#include "nsErrorService.h"
+#include "nsByteBuffer.h"
+
+#include "nsSupportsArray.h"
+#include "nsArray.h"
+#include "nsSupportsPrimitives.h"
+#include "nsConsoleService.h"
+#include "nsExceptionService.h"
+
+#include "nsComponentManager.h"
+#include "nsCategoryManagerUtils.h"
+#include "nsIServiceManager.h"
+#include "nsGenericFactory.h"
+
+#include "nsEventQueueService.h"
+#include "nsEventQueue.h"
+#ifdef VBOX
+# include "nsEventQueueUtils.h"
+# include "nsProxyRelease.h"
+#endif /* VBOX */
+
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h" // access to the impl of nsProxyObjectManager for the generic factory registration.
+
+#include "xptinfo.h"
+#include "nsIInterfaceInfoManager.h"
+
+#include "nsTimerImpl.h"
+#include "TimerThread.h"
+
+#include "nsThread.h"
+#include "nsProcess.h"
+#include "nsEnvironment.h"
+
+#include "nsEmptyEnumerator.h"
+
+#include "nsILocalFile.h"
+#include "nsLocalFile.h"
+#if defined(XP_UNIX) || defined(XP_OS2)
+#include "nsNativeCharsetUtils.h"
+#endif
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCategoryManager.h"
+#include "nsICategoryManager.h"
+#include "nsStringStream.h"
+#include "nsMultiplexInputStream.h"
+
+#include "nsFastLoadService.h"
+
+#include "nsAtomService.h"
+#include "nsAtomTable.h"
+#include "nsTraceRefcnt.h"
+#include "nsTimelineService.h"
+
+#include "nsVariant.h"
+
+#ifdef GC_LEAK_DETECTOR
+#include "nsLeakDetector.h"
+#endif
+#include "nsRecyclingAllocator.h"
+
+#include "SpecialSystemDirectory.h"
+
+#include "ipcdclient.h"
+#include "ipcService.h"
+#include "ipcConfig.h"
+#include "ipcCID.h"
+#include "ipcLockService.h"
+#include "ipcLockCID.h"
+#include "tmTransactionService.h"
+#include "ipcDConnectService.h"
+
+#include <locale.h>
+
+// Registry Factory creation function defined in nsRegistry.cpp
+// We hook into this function locally to create and register the registry
+// Since noone outside xpcom needs to know about this and nsRegistry.cpp
+// does not have a local include file, we are putting this definition
+// here rather than in nsIRegistry.h
+extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
+extern nsresult NS_CategoryManagerGetFactory( nsIFactory** );
+
+#ifdef DEBUG
+extern void _FreeAutoLockStatics();
+#endif
+
+static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
+static NS_DEFINE_CID(kMemoryCID, NS_MEMORY_CID);
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEventQueueServiceImpl, Init)
+
+#define NS_ENVIRONMENT_CLASSNAME "Environment Service"
+
+#include "nsXPCOM.h"
+// ds/nsISupportsPrimitives
+#define NS_SUPPORTS_ID_CLASSNAME "Supports ID"
+#define NS_SUPPORTS_CSTRING_CLASSNAME "Supports String"
+#define NS_SUPPORTS_STRING_CLASSNAME "Supports WString"
+#define NS_SUPPORTS_PRBOOL_CLASSNAME "Supports PRBool"
+#define NS_SUPPORTS_PRUINT8_CLASSNAME "Supports PRUint8"
+#define NS_SUPPORTS_PRUINT16_CLASSNAME "Supports PRUint16"
+#define NS_SUPPORTS_PRUINT32_CLASSNAME "Supports PRUint32"
+#define NS_SUPPORTS_PRUINT64_CLASSNAME "Supports PRUint64"
+#define NS_SUPPORTS_PRTIME_CLASSNAME "Supports PRTime"
+#define NS_SUPPORTS_CHAR_CLASSNAME "Supports Char"
+#define NS_SUPPORTS_PRINT16_CLASSNAME "Supports PRInt16"
+#define NS_SUPPORTS_PRINT32_CLASSNAME "Supports PRInt32"
+#define NS_SUPPORTS_PRINT64_CLASSNAME "Supports PRInt64"
+#define NS_SUPPORTS_FLOAT_CLASSNAME "Supports float"
+#define NS_SUPPORTS_DOUBLE_CLASSNAME "Supports double"
+#define NS_SUPPORTS_VOID_CLASSNAME "Supports void"
+#define NS_SUPPORTS_INTERFACE_POINTER_CLASSNAME "Supports interface pointer"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsIDImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsStringImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCStringImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBoolImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTimeImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCharImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsArray)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsConsoleService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerManager)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream)
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant)
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsRecyclingAllocatorImpl)
+
+#ifdef MOZ_TIMELINE
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimelineService)
+#endif
+
+static NS_METHOD
+nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer,
+ const nsIID& aIID,
+ void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim(dont_AddRef(XPTI_GetInterfaceInfoManager()));
+ if (!iim) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return iim->QueryInterface(aIID, aInstancePtr);
+}
+
+
+PR_STATIC_CALLBACK(nsresult)
+RegisterGenericFactory(nsIComponentRegistrar* registrar,
+ const nsModuleComponentInfo *info)
+{
+ nsresult rv;
+ nsIGenericFactory* fact;
+ rv = NS_NewGenericFactory(&fact, info);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = registrar->RegisterFactory(info->mCID,
+ info->mDescription,
+ info->mContractID,
+ fact);
+ NS_RELEASE(fact);
+ return rv;
+}
+
+// In order to support the installer, we need
+// to be told out of band if we should cause
+// an autoregister. If the file ".autoreg" exists in the binary
+// directory, we check its timestamp against the timestamp of the
+// compreg.dat file. If the .autoreg file is newer, we autoregister.
+static PRBool CheckUpdateFile()
+{
+ nsresult rv;
+ nsCOMPtr<nsIProperties> directoryService;
+ nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(directoryService));
+
+ if (!directoryService)
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> file;
+ rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(file));
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
+ return PR_FALSE;
+ }
+
+ file->AppendNative(nsDependentCString(".autoreg"));
+
+ PRBool exists;
+ file->Exists(&exists);
+ if (!exists)
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> compregFile;
+ rv = directoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(compregFile));
+
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
+ return PR_FALSE;
+ }
+
+ // Don't need to check whether compreg exists; if it doesn't
+ // we won't even be here.
+
+ PRInt64 compregModTime, autoregModTime;
+ compregFile->GetLastModifiedTime(&compregModTime);
+ file->GetLastModifiedTime(&autoregModTime);
+
+ return LL_CMP(autoregModTime, >, compregModTime);
+}
+
+#if 0 /// @todo later
+NS_GENERIC_FACTORY_CONSTRUCTOR(ipcService)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcLockService, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR(tmTransactionService)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcDConnectService, Init)
+
+// enable this code to make the IPC DCONNECT service auto-start.
+NS_METHOD
+ipcDConnectServiceRegisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const char *componentType,
+ const nsModuleComponentInfo *info)
+{
+ //
+ // add ipcService to the XPCOM startup category
+ //
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman) {
+ nsXPIDLCString prevEntry;
+ catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcDConnectService",
+ IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
+ getter_Copies(prevEntry));
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+ipcDConnectServiceUnregisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const nsModuleComponentInfo *info)
+{
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman)
+ catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
+ IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE);
+ return NS_OK;
+}
+#endif
+
+nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
+nsIProperties *gDirectoryService = NULL;
+PRBool gXPCOMShuttingDown = PR_FALSE;
+
+// For each class that wishes to support nsIClassInfo, add a line like this
+// NS_DECL_CLASSINFO(nsMyClass)
+
+#define COMPONENT(NAME, Ctor) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
+
+#define COMPONENT_CI(NAME, Ctor, Class) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor, \
+ NULL, NULL, NULL, NS_CI_INTERFACE_GETTER_NAME(Class), NULL, \
+ &NS_CLASSINFO_NAME(Class) }
+
+static const nsModuleComponentInfo components[] = {
+ COMPONENT(MEMORY, nsMemoryImpl::Create),
+ COMPONENT(DEBUG, nsDebugImpl::Create),
+#define NS_ERRORSERVICE_CLASSNAME NS_ERRORSERVICE_NAME
+ COMPONENT(ERRORSERVICE, nsErrorService::Create),
+
+ COMPONENT(BYTEBUFFER, ByteBufferImpl::Create),
+ COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create),
+ COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor),
+ COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor),
+ COMPONENT(STORAGESTREAM, nsStorageStreamConstructor),
+
+#define NS_PROPERTIES_CLASSNAME "Properties"
+ COMPONENT(PROPERTIES, nsProperties::Create),
+
+#define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */
+ COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create),
+
+ COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create),
+ COMPONENT(ARRAY, nsArrayConstructor),
+ COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor),
+ COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor),
+ COMPONENT(ATOMSERVICE, nsAtomServiceConstructor),
+#ifdef MOZ_TIMELINE
+ COMPONENT(TIMELINESERVICE, nsTimelineServiceConstructor),
+#endif
+ COMPONENT(OBSERVERSERVICE, nsObserverService::Create),
+ COMPONENT(GENERICFACTORY, nsGenericFactory::Create),
+ COMPONENT(EVENTQUEUESERVICE, nsEventQueueServiceImplConstructor),
+ COMPONENT(EVENTQUEUE, nsEventQueueImpl::Create),
+ COMPONENT(THREAD, nsThread::Create),
+
+#define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID
+ COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create),
+
+ COMPONENT(TIMER, nsTimerImplConstructor),
+ COMPONENT(TIMERMANAGER, nsTimerManagerConstructor),
+
+#define COMPONENT_SUPPORTS(TYPE, Type) \
+ COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##ImplConstructor)
+
+ COMPONENT_SUPPORTS(ID, ID),
+ COMPONENT_SUPPORTS(STRING, String),
+ COMPONENT_SUPPORTS(CSTRING, CString),
+ COMPONENT_SUPPORTS(PRBOOL, PRBool),
+ COMPONENT_SUPPORTS(PRUINT8, PRUint8),
+ COMPONENT_SUPPORTS(PRUINT16, PRUint16),
+ COMPONENT_SUPPORTS(PRUINT32, PRUint32),
+ COMPONENT_SUPPORTS(PRUINT64, PRUint64),
+ COMPONENT_SUPPORTS(PRTIME, PRTime),
+ COMPONENT_SUPPORTS(CHAR, Char),
+ COMPONENT_SUPPORTS(PRINT16, PRInt16),
+ COMPONENT_SUPPORTS(PRINT32, PRInt32),
+ COMPONENT_SUPPORTS(PRINT64, PRInt64),
+ COMPONENT_SUPPORTS(FLOAT, Float),
+ COMPONENT_SUPPORTS(DOUBLE, Double),
+ COMPONENT_SUPPORTS(VOID, Void),
+ COMPONENT_SUPPORTS(INTERFACE_POINTER, InterfacePointer),
+
+#undef COMPONENT_SUPPORTS
+#define NS_LOCAL_FILE_CLASSNAME "Local File Specification"
+ COMPONENT(LOCAL_FILE, nsLocalFile::nsLocalFileConstructor),
+#define NS_DIRECTORY_SERVICE_CLASSNAME "nsIFile Directory Service"
+ COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create),
+ COMPONENT(PROCESS, nsProcessConstructor),
+ COMPONENT(ENVIRONMENT, nsEnvironment::Create),
+
+ COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor),
+ COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor),
+
+ COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create),
+ COMPONENT(VARIANT, nsVariantConstructor),
+ COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton),
+
+ COMPONENT(RECYCLINGALLOCATOR, nsRecyclingAllocatorImplConstructor),
+
+#if 0 /// @todo later
+ { IPC_SERVICE_CLASSNAME,
+ IPC_SERVICE_CID,
+ IPC_SERVICE_CONTRACTID,
+ ipcServiceConstructor },
+ /*
+ ipcServiceRegisterProc,
+ ipcServiceUnregisterProc },
+ */
+ //
+ // extensions go here:
+ //
+ { IPC_LOCKSERVICE_CLASSNAME,
+ IPC_LOCKSERVICE_CID,
+ IPC_LOCKSERVICE_CONTRACTID,
+ ipcLockServiceConstructor },
+ { IPC_TRANSACTIONSERVICE_CLASSNAME,
+ IPC_TRANSACTIONSERVICE_CID,
+ IPC_TRANSACTIONSERVICE_CONTRACTID,
+ tmTransactionServiceConstructor },
+
+#ifdef BUILD_DCONNECT
+ { IPC_DCONNECTSERVICE_CLASSNAME,
+ IPC_DCONNECTSERVICE_CID,
+ IPC_DCONNECTSERVICE_CONTRACTID,
+ ipcDConnectServiceConstructor,
+ ipcDConnectServiceRegisterProc,
+ ipcDConnectServiceUnregisterProc },
+#endif
+#endif
+};
+
+#undef COMPONENT
+
+const int components_length = sizeof(components) / sizeof(components[0]);
+
+// gMemory will be freed during shutdown.
+static nsIMemory* gMemory = nsnull;
+nsresult NS_COM NS_GetMemoryManager(nsIMemory* *result)
+{
+ nsresult rv = NS_OK;
+ if (!gMemory)
+ {
+ rv = nsMemoryImpl::Create(nsnull,
+ NS_GET_IID(nsIMemory),
+ (void**)&gMemory);
+ }
+ NS_IF_ADDREF(*result = gMemory);
+ return rv;
+}
+
+// gDebug will be freed during shutdown.
+static nsIDebug* gDebug = nsnull;
+nsresult NS_COM NS_GetDebug(nsIDebug** result)
+{
+ nsresult rv = NS_OK;
+ if (!gDebug)
+ {
+ rv = nsDebugImpl::Create(nsnull,
+ NS_GET_IID(nsIDebug),
+ (void**)&gDebug);
+ }
+ NS_IF_ADDREF(*result = gDebug);
+ return rv;
+}
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+// gTraceRefcnt will be freed during shutdown.
+static nsITraceRefcnt* gTraceRefcnt = nsnull;
+#endif
+
+nsresult NS_COM NS_GetTraceRefcnt(nsITraceRefcnt** result)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsresult rv = NS_OK;
+ if (!gTraceRefcnt)
+ {
+ rv = nsTraceRefcntImpl::Create(nsnull,
+ NS_GET_IID(nsITraceRefcnt),
+ (void**)&gTraceRefcnt);
+ }
+ NS_IF_ADDREF(*result = gTraceRefcnt);
+ return rv;
+#else
+ return NS_ERROR_NOT_INITIALIZED;
+#endif
+}
+
+nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
+ nsIFile* binDirectory)
+{
+ return NS_InitXPCOM2(result, binDirectory, nsnull);
+}
+
+nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
+ nsIFile* binDirectory,
+ nsIDirectoryServiceProvider* appFileLocationProvider)
+{
+ nsresult rv = NS_OK;
+
+ // We are not shutting down
+ gXPCOMShuttingDown = PR_FALSE;
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::Startup();
+#endif
+
+ // Establish the main thread here.
+ rv = nsIThread::SetMainThread();
+ if (NS_FAILED(rv)) return rv;
+
+ // Set up the timer globals/timer thread
+ rv = nsTimerImpl::Startup();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Startup the memory manager
+ rv = nsMemoryImpl::Startup();
+ if (NS_FAILED(rv)) return rv;
+
+ // If the locale hasn't already been setup by our embedder,
+ // get us out of the "C" locale and into the system
+ if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
+ setlocale(LC_ALL, "");
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ NS_StartupNativeCharsetUtils();
+#endif
+ NS_StartupLocalFile();
+
+ StartupSpecialSystemDirectory();
+
+ // Start the directory service so that the component manager init can use it.
+ rv = nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ (void**)&gDirectoryService);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIDirectoryService> dirService = do_QueryInterface(gDirectoryService, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = dirService->Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Create the Component/Service Manager
+ nsComponentManagerImpl *compMgr = NULL;
+
+ if (nsComponentManagerImpl::gComponentManager == NULL)
+ {
+ compMgr = new nsComponentManagerImpl();
+ if (compMgr == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(compMgr);
+
+ nsCOMPtr<nsIFile> xpcomLib;
+
+ PRBool value;
+ if (binDirectory)
+ {
+ rv = binDirectory->IsDirectory(&value);
+
+ if (NS_SUCCEEDED(rv) && value) {
+ gDirectoryService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
+ binDirectory->Clone(getter_AddRefs(xpcomLib));
+ }
+ }
+ else {
+ gDirectoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(xpcomLib));
+ }
+
+ if (xpcomLib) {
+ xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
+ gDirectoryService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
+ }
+
+ if (appFileLocationProvider) {
+ rv = dirService->RegisterProvider(appFileLocationProvider);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ rv = compMgr->Init();
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(compMgr);
+ return rv;
+ }
+
+ nsComponentManagerImpl::gComponentManager = compMgr;
+
+ if (result) {
+ nsIServiceManager *serviceManager =
+ NS_STATIC_CAST(nsIServiceManager*, compMgr);
+
+ NS_ADDREF(*result = serviceManager);
+ }
+ }
+
+ nsCOMPtr<nsIMemory> memory;
+ NS_GetMemoryManager(getter_AddRefs(memory));
+ // dougt - these calls will be moved into a new interface when nsIComponentManager is frozen.
+ rv = compMgr->RegisterService(kMemoryCID, memory);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = compMgr->RegisterService(kComponentManagerCID, NS_STATIC_CAST(nsIComponentManager*, compMgr));
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef GC_LEAK_DETECTOR
+ rv = NS_InitLeakDetector();
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ // 2. Register the global services with the component manager so that
+ // clients can create new objects.
+
+ // Category Manager
+ {
+ nsCOMPtr<nsIFactory> categoryManagerFactory;
+ if ( NS_FAILED(rv = NS_CategoryManagerGetFactory(getter_AddRefs(categoryManagerFactory))) )
+ return rv;
+
+ NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
+
+ rv = compMgr->RegisterFactory(kCategoryManagerCID,
+ NS_CATEGORYMANAGER_CLASSNAME,
+ NS_CATEGORYMANAGER_CONTRACTID,
+ categoryManagerFactory,
+ PR_TRUE);
+ if ( NS_FAILED(rv) ) return rv;
+ }
+
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(
+ NS_STATIC_CAST(nsIComponentManager*,compMgr), &rv);
+ if (registrar) {
+ for (int i = 0; i < components_length; i++)
+ RegisterGenericFactory(registrar, &components[i]);
+ }
+ rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
+#ifdef DEBUG
+ if (NS_FAILED(rv)) {
+ printf("No Persistent Registry Found.\n");
+ }
+#endif
+
+#if 0 /// @todo later
+ rv = IPC_Init();
+ if (NS_FAILED(rv))
+ return rv;
+#endif
+
+ if ( NS_FAILED(rv) || CheckUpdateFile()) {
+ // if we find no persistent registry, we will try to autoregister
+ // the default components directory.
+ nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
+
+ // If the application is using a GRE, then,
+ // auto register components in the GRE directory as well.
+ //
+ // The application indicates that it's using an GRE by
+ // returning a valid nsIFile when queried (via appFileLocProvider)
+ // for the NS_GRE_DIR atom as shown below
+ //
+
+ if ( appFileLocationProvider ) {
+ nsCOMPtr<nsIFile> greDir;
+ PRBool persistent = PR_TRUE;
+
+ appFileLocationProvider->GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(greDir));
+
+ if (greDir) {
+#ifdef DEBUG_dougt
+ printf("start - Registering GRE components\n");
+#endif
+ rv = gDirectoryService->Get(NS_GRE_COMPONENT_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(greDir));
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Could not get GRE components directory!");
+ return rv;
+ }
+
+ // If the GRE contains any loaders, we want to know about it so that we can cause another
+ // autoregistration of the applications component directory.
+ int loaderCount = nsComponentManagerImpl::gComponentManager->GetLoaderCount();
+ rv = nsComponentManagerImpl::gComponentManager->AutoRegister(greDir);
+
+ if (loaderCount != nsComponentManagerImpl::gComponentManager->GetLoaderCount())
+ nsComponentManagerImpl::gComponentManager->AutoRegisterNonNativeComponents(nsnull);
+
+#ifdef DEBUG_dougt
+ printf("end - Registering GRE components\n");
+#endif
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Could not AutoRegister GRE components");
+ return rv;
+ }
+ }
+ }
+
+ //
+ // If additional component directories have been specified, then
+ // register them as well.
+ //
+
+ nsCOMPtr<nsISimpleEnumerator> dirList;
+ gDirectoryService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
+ NS_GET_IID(nsISimpleEnumerator),
+ getter_AddRefs(dirList));
+ if (dirList) {
+ PRBool hasMore;
+ while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> elem;
+ dirList->GetNext(getter_AddRefs(elem));
+ if (elem) {
+ nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
+ if (dir)
+ nsComponentManagerImpl::gComponentManager->AutoRegister(dir);
+
+ // XXX should we worry about new component loaders being
+ // XXX defined by this process?
+ }
+ }
+ }
+
+
+ // Make sure the compreg file's mod time is current.
+ nsCOMPtr<nsIFile> compregFile;
+ rv = gDirectoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(compregFile));
+ compregFile->SetLastModifiedTime(PR_Now() / 1000);
+ }
+
+ // Pay the cost at startup time of starting this singleton.
+ nsIInterfaceInfoManager* iim = XPTI_GetInterfaceInfoManager();
+ NS_IF_RELEASE(iim);
+#ifdef VBOX
+ // Must initialize the EventQueueService singleton before anyone is
+ // using it. The notification below creates a thread which races creating
+ // the EventQueueService creation otherwise, no matter what.
+ nsCOMPtr<nsIEventQueue> eventQ;
+ rv = NS_GetMainEventQ(getter_AddRefs(eventQ));
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Could not create event queue for main thread");
+ /* this is just a build-time hack, to reference NS_ProxyRelease */
+ if (rv == 666)
+ NS_ProxyRelease(nsnull, nsnull);
+ return rv;
+ }
+#endif /* VBOX */
+
+ // Notify observers of xpcom autoregistration start
+ NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_OBSERVER_ID,
+ nsnull,
+ NS_XPCOM_STARTUP_OBSERVER_ID);
+
+ return NS_OK;
+}
+
+
+static nsVoidArray* gExitRoutines;
+
+static void CallExitRoutines()
+{
+ if (!gExitRoutines)
+ return;
+
+ PRInt32 count = gExitRoutines->Count();
+ for (PRInt32 i = 0; i < count; i++) {
+ XPCOMExitRoutine func = (XPCOMExitRoutine) gExitRoutines->ElementAt(i);
+ func();
+ }
+ gExitRoutines->Clear();
+ delete gExitRoutines;
+ gExitRoutines = nsnull;
+}
+
+nsresult NS_COM
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
+{
+ // priority are not used right now. It will need to be implemented as more
+ // classes are moved into the glue library --dougt
+ if (!gExitRoutines) {
+ gExitRoutines = new nsVoidArray();
+ if (!gExitRoutines) {
+ NS_WARNING("Failed to allocate gExitRoutines");
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ PRBool okay = gExitRoutines->AppendElement((void*)exitRoutine);
+ return okay ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult NS_COM
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
+{
+ if (!gExitRoutines)
+ return NS_ERROR_FAILURE;
+
+ PRBool okay = gExitRoutines->RemoveElement((void*)exitRoutine);
+ return okay ? NS_OK : NS_ERROR_FAILURE;
+}
+
+
+//
+// NS_ShutdownXPCOM()
+//
+// The shutdown sequence for xpcom would be
+//
+// - Release the Global Service Manager
+// - Release all service instances held by the global service manager
+// - Release the Global Service Manager itself
+// - Release the Component Manager
+// - Release all factories cached by the Component Manager
+// - Unload Libraries
+// - Release Contractid Cache held by Component Manager
+// - Release dll abstraction held by Component Manager
+// - Release the Registry held by Component Manager
+// - Finally, release the component manager itself
+//
+nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
+{
+
+ // Notify observers of xpcom shutting down
+ nsresult rv = NS_OK;
+ {
+ // Block it so that the COMPtr will get deleted before we hit
+ // servicemanager shutdown
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ (void) observerService->NotifyObservers(mgr,
+ NS_XPCOM_SHUTDOWN_OBSERVER_ID,
+ nsnull);
+ }
+ }
+ }
+
+ // grab the event queue so that we can process events one last time before exiting
+ nsCOMPtr <nsIEventQueue> currentQ;
+ {
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+
+ if (eventQService) {
+ eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentQ));
+ }
+ }
+ // XPCOM is officially in shutdown mode NOW
+ // Set this only after the observers have been notified as this
+ // will cause servicemanager to become inaccessible.
+ gXPCOMShuttingDown = PR_TRUE;
+
+#ifdef DEBUG_dougt
+ fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n");
+#endif
+
+#if 0 /// @todo later
+ IPC_Shutdown();
+#endif
+
+ // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
+ // here again:
+ NS_IF_RELEASE(servMgr);
+
+ // Shutdown global servicemanager
+ if (nsComponentManagerImpl::gComponentManager) {
+ nsComponentManagerImpl::gComponentManager->FreeServices();
+ }
+ nsServiceManager::ShutdownGlobalServiceManager(nsnull);
+
+ if (currentQ) {
+ currentQ->ProcessPendingEvents();
+ currentQ = 0;
+ }
+
+ nsProxyObjectManager::Shutdown();
+
+ // Release the directory service
+ NS_IF_RELEASE(gDirectoryService);
+
+ // Shutdown nsLocalFile string conversion
+ NS_ShutdownLocalFile();
+#ifdef XP_UNIX
+ NS_ShutdownNativeCharsetUtils();
+#endif
+
+ // Shutdown the timer thread and all timers that might still be alive before
+ // shutting down the component manager
+ nsTimerImpl::Shutdown();
+
+ CallExitRoutines();
+
+ // Shutdown xpcom. This will release all loaders and cause others holding
+ // a refcount to the component manager to release it.
+ if (nsComponentManagerImpl::gComponentManager) {
+ rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
+ } else
+ NS_WARNING("Component Manager was never created ...");
+
+ // Release our own singletons
+ // Do this _after_ shutting down the component manager, because the
+ // JS component loader will use XPConnect to call nsIModule::canUnload,
+ // and that will spin up the InterfaceInfoManager again -- bad mojo
+ XPTI_FreeInterfaceInfoManager();
+
+ // Finally, release the component manager last because it unloads the
+ // libraries:
+ if (nsComponentManagerImpl::gComponentManager) {
+ nsrefcnt cnt;
+ NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
+ NS_WARN_IF_FALSE(cnt == 0, "Component Manager being held past XPCOM shutdown.");
+ }
+ nsComponentManagerImpl::gComponentManager = nsnull;
+
+#ifdef DEBUG
+ _FreeAutoLockStatics();
+#endif
+
+ ShutdownSpecialSystemDirectory();
+
+ EmptyEnumeratorImpl::Shutdown();
+ nsMemoryImpl::Shutdown();
+ NS_IF_RELEASE(gMemory);
+
+ nsThread::Shutdown();
+ NS_PurgeAtomTable();
+
+ NS_IF_RELEASE(gDebug);
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::DumpStatistics();
+ nsTraceRefcntImpl::ResetStatistics();
+ nsTraceRefcntImpl::Shutdown();
+#endif
+
+#ifdef GC_LEAK_DETECTOR
+ // Shutdown the Leak detector.
+ NS_ShutdownLeakDetector();
+#endif
+
+ return NS_OK;
+}
+
+#define GET_FUNC(_tag, _decl, _name) \
+ functions->_tag = (_decl) PR_FindSymbol(xpcomLib, _name); \
+ if (!functions->_tag) goto end
+
+nsresult NS_COM PR_CALLBACK
+NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* libraryPath)
+{
+ if (!functions)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (functions->version != XPCOM_GLUE_VERSION)
+ return NS_ERROR_FAILURE;
+
+ PRLibrary *xpcomLib = PR_LoadLibrary(libraryPath);
+ if (!xpcomLib)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ GET_FUNC(init, InitFunc, "VBoxNsxpNS_InitXPCOM2");
+ GET_FUNC(shutdown, ShutdownFunc, "VBoxNsxpNS_ShutdownXPCOM");
+ GET_FUNC(getServiceManager, GetServiceManagerFunc, "VBoxNsxpNS_GetServiceManager");
+ GET_FUNC(getComponentManager, GetComponentManagerFunc, "VBoxNsxpNS_GetComponentManager");
+ GET_FUNC(getComponentRegistrar, GetComponentRegistrarFunc, "VBoxNsxpNS_GetComponentRegistrar");
+ GET_FUNC(getMemoryManager, GetMemoryManagerFunc, "VBoxNsxpNS_GetMemoryManager");
+ GET_FUNC(newLocalFile, NewLocalFileFunc, "VBoxNsxpNS_NewLocalFile");
+ GET_FUNC(newNativeLocalFile, NewNativeLocalFileFunc, "VBoxNsxpNS_NewNativeLocalFile");
+ GET_FUNC(registerExitRoutine, RegisterXPCOMExitRoutineFunc, "VBoxNsxpNS_RegisterXPCOMExitRoutine");
+ GET_FUNC(unregisterExitRoutine, UnregisterXPCOMExitRoutineFunc, "VBoxNsxpNS_UnregisterXPCOMExitRoutine");
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ GET_FUNC(init, InitFunc, "NS_InitXPCOM2");
+ GET_FUNC(shutdown, ShutdownFunc, "NS_ShutdownXPCOM");
+ GET_FUNC(getServiceManager, GetServiceManagerFunc, "NS_GetServiceManager");
+ GET_FUNC(getComponentManager, GetComponentManagerFunc, "NS_GetComponentManager");
+ GET_FUNC(getComponentRegistrar, GetComponentRegistrarFunc, "NS_GetComponentRegistrar");
+ GET_FUNC(getMemoryManager, GetMemoryManagerFunc, "NS_GetMemoryManager");
+ GET_FUNC(newLocalFile, NewLocalFileFunc, "NS_NewLocalFile");
+ GET_FUNC(newNativeLocalFile, NewNativeLocalFileFunc, "NS_NewNativeLocalFile");
+ GET_FUNC(registerExitRoutine, RegisterXPCOMExitRoutineFunc, "NS_RegisterXPCOMExitRoutine");
+ GET_FUNC(unregisterExitRoutine, UnregisterXPCOMExitRoutineFunc, "NS_UnregisterXPCOMExitRoutine");
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+ // these functions were added post 1.4 (need to check size of |functions|)
+ if (functions->size > offsetof(XPCOMFunctions, getTraceRefcnt)) {
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ GET_FUNC(getDebug, GetDebugFunc, "VBoxNsxpNS_GetDebug");
+ GET_FUNC(getTraceRefcnt, GetTraceRefcntFunc, "VBoxNsxpNS_GetTraceRefcnt");
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ GET_FUNC(getDebug, GetDebugFunc, "NS_GetDebug");
+ GET_FUNC(getTraceRefcnt, GetTraceRefcntFunc, "NS_GetTraceRefcnt");
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ }
+
+ // these functions were added post 1.6 (need to check size of |functions|)
+ if (functions->size > offsetof(XPCOMFunctions, cstringCloneData)) {
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ GET_FUNC(stringContainerInit, StringContainerInitFunc, "VBoxNsxpNS_StringContainerInit");
+ GET_FUNC(stringContainerFinish, StringContainerFinishFunc, "VBoxNsxpNS_StringContainerFinish");
+ GET_FUNC(stringGetData, StringGetDataFunc, "VBoxNsxpNS_StringGetData");
+ GET_FUNC(stringSetData, StringSetDataFunc, "VBoxNsxpNS_StringSetData");
+ GET_FUNC(stringSetDataRange, StringSetDataRangeFunc, "VBoxNsxpNS_StringSetDataRange");
+ GET_FUNC(stringCopy, StringCopyFunc, "VBoxNsxpNS_StringCopy");
+ GET_FUNC(cstringContainerInit, CStringContainerInitFunc, "VBoxNsxpNS_CStringContainerInit");
+ GET_FUNC(cstringContainerFinish, CStringContainerFinishFunc, "VBoxNsxpNS_CStringContainerFinish");
+ GET_FUNC(cstringGetData, CStringGetDataFunc, "VBoxNsxpNS_CStringGetData");
+ GET_FUNC(cstringSetData, CStringSetDataFunc, "VBoxNsxpNS_CStringSetData");
+ GET_FUNC(cstringSetDataRange, CStringSetDataRangeFunc, "VBoxNsxpNS_CStringSetDataRange");
+ GET_FUNC(cstringCopy, CStringCopyFunc, "VBoxNsxpNS_CStringCopy");
+ GET_FUNC(cstringToUTF16, CStringToUTF16, "VBoxNsxpNS_CStringToUTF16");
+ GET_FUNC(utf16ToCString, UTF16ToCString, "VBoxNsxpNS_UTF16ToCString");
+ GET_FUNC(stringCloneData, StringCloneDataFunc, "VBoxNsxpNS_StringCloneData");
+ GET_FUNC(cstringCloneData, CStringCloneDataFunc, "VBoxNsxpNS_CStringCloneData");
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ GET_FUNC(stringContainerInit, StringContainerInitFunc, "NS_StringContainerInit");
+ GET_FUNC(stringContainerFinish, StringContainerFinishFunc, "NS_StringContainerFinish");
+ GET_FUNC(stringGetData, StringGetDataFunc, "NS_StringGetData");
+ GET_FUNC(stringSetData, StringSetDataFunc, "NS_StringSetData");
+ GET_FUNC(stringSetDataRange, StringSetDataRangeFunc, "NS_StringSetDataRange");
+ GET_FUNC(stringCopy, StringCopyFunc, "NS_StringCopy");
+ GET_FUNC(cstringContainerInit, CStringContainerInitFunc, "NS_CStringContainerInit");
+ GET_FUNC(cstringContainerFinish, CStringContainerFinishFunc, "NS_CStringContainerFinish");
+ GET_FUNC(cstringGetData, CStringGetDataFunc, "NS_CStringGetData");
+ GET_FUNC(cstringSetData, CStringSetDataFunc, "NS_CStringSetData");
+ GET_FUNC(cstringSetDataRange, CStringSetDataRangeFunc, "NS_CStringSetDataRange");
+ GET_FUNC(cstringCopy, CStringCopyFunc, "NS_CStringCopy");
+ GET_FUNC(cstringToUTF16, CStringToUTF16, "NS_CStringToUTF16");
+ GET_FUNC(utf16ToCString, UTF16ToCString, "NS_UTF16ToCString");
+ GET_FUNC(stringCloneData, StringCloneDataFunc, "NS_StringCloneData");
+ GET_FUNC(cstringCloneData, CStringCloneDataFunc, "NS_CStringCloneData");
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ }
+
+ rv = NS_OK;
+end:
+ PR_UnloadLibrary(xpcomLib); // the library is refcnt'ed above by the caller.
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/build/win32.order b/src/libs/xpcom18a4/xpcom/build/win32.order
new file mode 100644
index 00000000..ce6856ba
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/win32.order
@@ -0,0 +1,1514 @@
+??1nsCOMPtr_base@@QAE@XZ ; 33017395
+?ElementAt@nsVoidArray@@QBEPAXH@Z ; 14120786
+?AddRef@nsEventQueueServiceImpl@@UAGKXZ ; 13612685
+?Release@AtomImpl@@UAGKXZ ; 13067618
+?Initialize@nsStr@@SAXAAU1@W4eCharSize@@@Z ; 9860800
+?Reference@nsCWeakProxy@@QAEPAXXZ ; 9283082
+?Free@nsStr@@CAHAAU1@@Z ; 8492496
+?Destroy@nsStr@@SAXAAU1@@Z ; 8159980
+??1nsString@@UAE@XZ ; 7681847
+??0nsString@@QAE@XZ ; 7538998
+?GetWritableFragment@nsString@@MAEPAGAAU?$nsWritableFragment@G@@W4nsFragmentRequest@@I@Z ; 7387979
+?Initialize@nsStr@@SAXAAU1@PADIIW4eCharSize@@H@Z ; 7301440
+??1nsAutoString@@UAE@XZ ; 6828894
+??0nsAutoString@@QAE@XZ ; 6681318
+?normalize_forward@?$nsReadingIterator@G@@QAEXXZ ; 6469200
+?normalize_forward@?$nsWritingIterator@D@@QAEXXZ ; 4717355
+?StrTruncate@nsStr@@SAXAAU1@I@Z ; 4534497
+?assign_from_helper@nsCOMPtr_base@@QAEXABVnsCOMPtr_helper@@ABUnsID@@@Z ; 4516612
+??0nsHashKey@@IAE@XZ ; 4270805
+??1nsHashKey@@UAE@XZ ; 4268636
+??RnsQueryInterface@@UBEIABUnsID@@PAPAX@Z ; 4148520
+?SetLength@nsCString@@UAEXI@Z ; 4098410
+?Get@nsHashtable@@QAEPAXPAVnsHashKey@@@Z ; 3790063
+?GetFlatBufferHandle@nsLocalString@@UBEPBV?$nsBufferHandle@G@@XZ ; 3747888
+?BeginReading@nsACString@@QBEAAV?$nsReadingIterator@D@@AAV2@@Z ; 3649883
+?FindChar1@@YAHPBDIHGHH@Z ; 2533672
+?BeginWriting@nsACString@@QAEAAV?$nsWritingIterator@D@@AAV2@@Z ; 2226534
+?advance@?$nsWritingIterator@G@@QAEAAV1@H@Z ; 2049632
+?advance@?$nsReadingIterator@G@@QAEAAV1@H@Z ; 1995545
+?GetReadableFragment@nsAFlatCString@@MBEPBDAAU?$nsReadableFragment@D@@W4nsFragmentRequest@@I@Z ; 1948988
+?Count@nsSupportsArray@@UAGIPAI@Z ; 1839978
+?readable_distance@?$nsCharSourceTraits@V?$nsReadingIterator@G@@@@SAIABV?$nsReadingIterator@G@@0@Z ; 1802375
+?GetReadableFragment@nsCString@@MBEPBDAAU?$nsReadableFragment@D@@W4nsFragmentRequest@@I@Z ; 1763345
+??0nsQueryInterface@@QAE@PAVnsISupports@@PAI@Z ; 1655422
+?copy_string@@YAAAV?$nsWritingIterator@G@@AAV?$nsReadingIterator@G@@ABV2@AAV1@@Z ; 1487171
+?GetWritableFragment@nsAFlatString@@MAEPAGAAU?$nsWritableFragment@G@@W4nsFragmentRequest@@I@Z ; 1391163
+?advance@?$nsWritingIterator@D@@QAEAAV1@H@Z ; 1335661
+?Equals@nsAString@@QBEHABV1@@Z ; 1318787
+?move@?$nsCharTraits@G@@SAPAGPAGPBGI@Z ; 1315826
+?assign_with_AddRef@nsCOMPtr_base@@QAEXPAVnsISupports@@@Z ; 1259090
+?write@?$nsWritingIterator@G@@QAEIPBGI@Z ; 1243674
+?Get@nsSupportsHashtable@@QAEPAVnsISupports@@PAVnsHashKey@@@Z ; 1199544
+?GetUnicode@nsString@@QBEPBGXZ ; 1141413
+?StrAppend@nsStr@@SAXAAU1@ABU1@IH@Z ; 1102413
+?FindChar@nsString@@QBEHGHHH@Z ; 1090463
+?FindChar@nsStr@@SAHABU1@GHHH@Z ; 1090463
+?FindChar2@@YAHPBDIHGHH@Z ; 1056090
+?ElementAt@nsSupportsArray@@UAGPAVnsISupports@@I@Z ; 1055798
+?InsertElementAt@nsVoidArray@@QAEHPAXH@Z ; 926721
+?Compare2To2@@YAHPBD0IH@Z ; 920121
+?EnumerateForwards@nsSupportsArray@@UAGHP6AHPAVnsISupports@@PAX@Z1@Z ; 908730
+?strncasecmp@nsCRT@@SAHPBG0I@Z ; 896894
+?StrCompare@nsStr@@SAHABU1@0HH@Z ; 886450
+?Free@nsMemoryImpl@@UAGXPAX@Z ; 842646
+?Free@nsMemory@@SAXPAX@Z ; 832569
+?Distance@@YAIABV?$nsReadingIterator@G@@0@Z ; 801833
+?copy_string@@YAAAV?$CalculateLength@G@@AAV?$nsReadingIterator@G@@ABV2@AAV1@@Z ; 801833
+?Compare2To1@@YAHPBD0IH@Z ; 797802
+?Alloc@nsMemoryImpl@@UAGPAXI@Z ; 795063
+?Length@nsAFlatString@@UBEIXZ ; 789895
+?advance@?$nsReadingIterator@D@@QAEAAV1@H@Z ; 778072
+?copy_string@@YAAAV?$nsWritingIterator@D@@AAV?$nsReadingIterator@D@@ABV2@AAV1@@Z ; 738318
+?Alloc@nsMemory@@SAPAXI@Z ; 731916
+?write@?$nsWritingIterator@D@@QAEIPBDI@Z ; 724438
+?EqualsWithConversion@nsString@@QBEHABV1@HH@Z ; 680848
+?EqualsIgnoreCase@nsString@@QBEHABV1@@Z ; 680848
+?Length@nsAFlatCString@@UBEIXZ ; 674814
+?GetReadableFragment@nsSlidingSubstring@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 671287
+?do_AppendFromReadable@nsAString@@MAEXABV1@@Z ; 657779
+?Compare@@YAHABVnsAString@@0@Z ; 630913
+?do_AssignFromReadable@nsAString@@MAEXABV1@@Z ; 630139
+?CopyChars2To2@@YAXPADHPBDII@Z ; 615216
+?do_AppendFromReadable@nsACString@@MAEXABV1@@Z ; 584996
+?ObjectAt@nsDeque@@QBEPAXH@Z ; 568869
+?InsertElementAt@nsSupportsArray@@UAGHPAVnsISupports@@I@Z ; 548718
+?AssignFromReadable@nsACString@@IAEXABV1@@Z ; 534684
+??0nsLocalCString@@QAE@PBD@Z ; 525422
+?strlen@nsCRT@@SAIPBG@Z ; 517372
+?get@nsString@@UBEPBGXZ ; 500471
+?GrowCapacity@nsStr@@SAHAAU1@I@Z ; 493115
+?Realloc@nsStr@@CAHAAU1@I@Z ; 493115
+?Alloc@nsStr@@CAHAAU1@I@Z ; 493115
+?EnsureCapacity@nsStr@@SAHAAU1@I@Z ; 493115
+??0nsVoidArray@@QAE@XZ ; 490358
+?strncmp@nsCRT@@SAHPBGPBDI@Z ; 489334
+??1nsVoidArray@@UAE@XZ ; 481308
+??1nsCString@@UAE@XZ ; 478019
+?RemoveElementAt@nsVoidArray@@QAEHH@Z ; 473592
+?AppendElement@nsSupportsArray@@UAGIPAVnsISupports@@@Z ; 464186
+?AppendWithConversion@nsCString@@QAEXG@Z ; 452063
+??0nsCString@@QAE@XZ ; 449721
+?do_AppendFromElementPtr@nsACString@@MAEXPBD@Z ; 427640
+?SetArraySize@nsVoidArray@@IAEXH@Z ; 425906
+?get@nsPromiseFlatCString@@UBEPBDXZ ; 413903
+?Alloc@nsFixedSizeAllocator@@QAEPAXI@Z ; 411293
+??0nsPromiseFlatString@@IAE@ABVnsAString@@@Z ; 410015
+?Free@nsFixedSizeAllocator@@SAXPAXI@Z ; 401028
+?strcmp@nsCRT@@SAHPBG0@Z ; 400500
+??1nsPromiseFlatString@@UAE@XZ ; 398346
+??1nsCAutoString@@UAE@XZ ; 391273
+?GetFlatBufferHandle@nsCString@@MBEPBV?$nsBufferHandle@D@@XZ ; 385981
+?Push@nsDeque@@QAEAAV1@PAX@Z ; 367628
+?Equals@nsIDKey@@UBEHPBVnsHashKey@@@Z ; 358933
+?Clear@nsSupportsArray@@UAGIXZ ; 352217
+?AppendFromReadable@nsAString@@IAEXABV1@@Z ; 352181
+?strncasecmp@nsCRT@@SAHPBGPBDI@Z ; 330906
+?IsAsciiAlpha@nsCRT@@SAHG@Z ; 327047
+??0nsCAutoString@@QAE@XZ ; 311314
+?Clear@nsVoidArray@@QAEXXZ ; 287750
+?Compare1To1@@YAHPBD0IH@Z ; 276525
+?Length@nsSlidingSubstring@@UBEIXZ ; 264724
+?PopFront@nsDeque@@QAEPAXXZ ; 260861
+?AcquireNonOwningReference@Buffer@nsSharedBufferList@@QBEXXZ ; 256259
+?Distance@Position@nsSharedBufferList@@SAHABU12@0@Z ; 254042
+?DiscardUnreferencedPrefix@nsSlidingSharedBufferList@@QAEXPAVBuffer@nsSharedBufferList@@@Z ; 254040
+?ReleaseNonOwningReference@Buffer@nsSharedBufferList@@QBEXXZ ; 254040
+??1nsCStringKey@@UAE@XZ ; 253255
+?HashCode@nsCRT@@SAIPBDPAI@Z ; 251093
+?HashCode@nsCStringKey@@UBEIXZ ; 250679
+?NS_GetGlobalComponentManager@@YAIPAPAVnsIComponentManager@@@Z ; 250625
+??1nsAFlatString@@UAE@XZ ; 249908
+??0nsAFlatString@@QAE@XZ ; 243174
+?Equals@nsCStringKey@@UBEHPBVnsHashKey@@@Z ; 238528
+?IsAsciiSpace@nsCRT@@SAHG@Z ; 238314
+?CopyChars1To2@@YAXPADHPBDII@Z ; 237716
+??0nsLocalString@@QAE@PBGI@Z ; 236845
+?NS_NewAtom@@YAPAVnsIAtom@@ABVnsAString@@@Z ; 235384
+?Release@nsSupportsArray@@UAGKXZ ; 229149
+?GetParameterCount@nsProxyObjectCallInfo@@QBEIXZ ; 228843
+??0nsAutoVoidArray@@QAE@XZ ; 223605
+?do_AppendFromElementPtrLength@nsAString@@MAEXPBGI@Z ; 221664
+?AppendWithConversion@nsString@@QAEXPBDH@Z ; 216212
+?ChangeCase@nsStr@@SAXAAU1@H@Z ; 211594
+?length@?$nsCharTraits@G@@SAIPBG@Z ; 206064
+??0nsLocalString@@QAE@PBG@Z ; 205367
+?SetArrayOwner@nsVoidArray@@IAEXH@Z ; 202301
+?GetFactoryEntry@nsComponentManagerImpl@@IAEPAVnsFactoryEntry@@ABUnsID@@H@Z ; 198436
+?FindFactory@nsComponentManagerImpl@@UAGIABUnsID@@PAPAVnsIFactory@@@Z ; 198385
+?GetFactory@nsFactoryEntry@@QAEIPAPAVnsIFactory@@PAVnsComponentManagerImpl@@@Z ; 198384
+?CreateInstance@nsComponentManagerImpl@@UAGIABUnsID@@PAVnsISupports@@0PAPAX@Z ; 198351
+?ToLowerCase@nsString@@QAEXXZ ; 198180
+?Remove@nsHashtable@@QAEPAXPAVnsHashKey@@@Z ; 191685
+?ToString@AtomImpl@@UAGIAAVnsAString@@@Z ; 189337
+?First@nsAString@@QBEGXZ ; 189245
+?release_ownership_of_buffer_list@nsSlidingSubstring@@AAEXXZ ; 188763
+?IndexOf@nsVoidArray@@QBEHPAX@Z ; 175677
+?StartAssignmentByValue@nsXPIDLString@@AAEPAPAGXZ ; 173850
+?SetCapacity@nsString@@UAEXI@Z ; 170493
+?CopyChars2To1@@YAXPADHPBDII@Z ; 168065
+?Put@nsHashtable@@QAEPAXPAVnsHashKey@@PAX@Z ; 160536
+?DiscardPrefix@nsSlidingString@@QAEXABV?$nsReadingIterator@G@@@Z ; 159450
+?StrAssign@nsStr@@SAXAAU1@ABU1@IH@Z ; 154324
+?Trim@nsStr@@SAXAAU1@PBDHH@Z ; 154152
+?SetCapacity@nsCString@@UAEXI@Z ; 151535
+?GetGlobalServiceManager@nsServiceManager@@SAIPAPAVnsIServiceManager@@@Z ; 148522
+?GetService@nsServiceManagerImpl@@UAGIABUnsID@@0PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 146024
+?AddListener@nsServiceEntry@@QAEIPAVnsIShutdownListener@@@Z ; 146022
+?GetUnicode@AtomImpl@@UAGIPAPBG@Z ; 143965
+?Pop@nsDeque@@QAEPAXXZ ; 143309
+??RnsQueryReferent@@UBEIABUnsID@@PAPAX@Z ; 142474
+?normalize_backward@?$nsReadingIterator@G@@QAEXXZ ; 142302
+?QueryReferent@nsWeakReference@@UAGIABUnsID@@PAPAX@Z ; 142237
+?AddRef@nsStorageStream@@UAGKXZ ; 141846
+?Assign@nsACString@@QAEXPBD@Z ; 141606
+?FindCharInSet@nsStr@@SAHABU1@0HH@Z ; 138161
+?FindCharInSet@nsCString@@QBEHPBDH@Z ; 138161
+?CreateInstance@nsComponentManager@@SAIABUnsID@@PAVnsISupports@@0PAPAX@Z ; 137059
+??0nsCStringKey@@QAE@PBDHW4Ownership@0@@Z ; 136293
+??1nsXPIDLCString@@UAE@XZ ; 134911
+??0nsString@@QAE@ABV0@@Z ; 134194
+?do_AssignFromReadable@nsACString@@MAEXABV1@@Z ; 128929
+?ConvertCase1@@YAHPADIH@Z ; 128876
+?AssignWithConversion@nsCString@@QAEXPBGH@Z ; 122216
+?do_AppendFromElement@nsACString@@MAEXD@Z ; 120364
+?Write@FileImpl@@UAGIPBDIPAI@Z ; 120089
+?AssignWithConversion@nsCString@@QAEXABVnsString@@@Z ; 119962
+?AddRef@nsSupportsStringImpl@@UAGKXZ ; 118646
+??0nsCStringKey@@QAE@ABVnsCString@@@Z ; 117124
+?GetResolveState@xptiInterfaceInfo@@QBEEXZ ; 117066
+?AppendUnicodeTo@@YAXABV?$nsReadingIterator@G@@0AAVnsAString@@@Z ; 115792
+?AssignWithConversion@nsString@@QAEXPBD@Z ; 115695
+?Last@nsAString@@QBEGXZ ; 115018
+?ContractIDToClassID@nsComponentManagerImpl@@UAGIPBDPAUnsID@@@Z ; 112973
+?ToNewCString@nsCString@@QBEPADXZ ; 110413
+?LookupLowercasedKeyword@@YAHABVnsCString@@PAVnsHashtable@@@Z ; 110405
+?IsAsciiDigit@nsCRT@@SAHG@Z ; 107530
+?Remove@nsSupportsHashtable@@QAEHPAVnsHashKey@@PAPAVnsISupports@@@Z ; 106325
+??0nsAutoString@@QAE@ABVnsString@@@Z ; 103799
+?CompareWithConversion@nsString@@QBEHPBDHH@Z ; 102438
+?EqualsWithConversion@nsString@@QBEHPBDHH@Z ; 101441
+?Lookup@nsStaticCaseInsensitiveNameTable@@QAEHABVnsString@@@Z ; 101178
+?Trim@nsString@@QAEXPBDHHH@Z ; 100923
+?Release@nsWeakReference@@UAGKXZ ; 100809
+?GetReadableFragment@nsPromiseSubstring@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 98711
+?GetService@nsServiceManager@@SAIABUnsID@@0PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 97630
+?write@nsOutputStream@@QAEHPBXH@Z ; 96747
+?Init@nsXPTCVariant@@QAEXABUnsXPTCMiniVariant@@ABVnsXPTType@@E@Z ; 95698
+?acquire_ownership_of_buffer_list@nsSlidingString@@ABEXXZ ; 94592
+?ReleaseReference@nsSlidingSharedBufferList@@QAEXXZ ; 94590
+??1nsSlidingSubstring@@UAE@XZ ; 94580
+??0nsSlidingSubstring@@QAE@XZ ; 94173
+?RemoveElement@nsVoidArray@@QAEHPAX@Z ; 91746
+??RnsGetServiceByCID@@UBEIABUnsID@@PAPAX@Z ; 91521
+??0nsGetServiceByCID@@QAE@ABUnsID@@PAVnsISupports@@PAI@Z ; 91521
+?Release@nsEventQueueImpl@@UAGKXZ ; 87880
+?EqualsIgnoreCase@nsString@@QBEHPBDH@Z ; 86030
+?Init@NS_ConvertUTF8toUCS2@@IAEXPBDI@Z ; 85607
+?Rebind@nsSlidingSubstring@@QAEXABVnsSlidingString@@ABV?$nsReadingIterator@G@@1@Z ; 83943
+?do_AppendFromElementPtr@nsAString@@MAEXPBG@Z ; 83867
+??0nsSupportsArray@@QAE@XZ ; 83106
+?ConvertCase2@@YAHPADIH@Z ; 82718
+?DeleteArray@nsSupportsArray@@IAEXXZ ; 82548
+??1nsSupportsArray@@UAE@XZ ; 82548
+?QueryInterface@nsSupportsArray@@UAGIABUnsID@@PAPAX@Z ; 81918
+?Create@nsSupportsArray@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 81725
+?NS_NewISupportsArray@@YAIPAPAVnsISupportsArray@@@Z ; 81666
+?CopyChars1To1@@YAXPADHPBDII@Z ; 81524
+??_EnsSupportsArray@@UAEPAXI@Z ; 81168
+?GetMethodInfo@xptiInterfaceInfo@@UAGIGPAPBVnsXPTMethodInfo@@@Z ; 78229
+?Release@xptiInterfaceInfo@@UAGKXZ ; 76117
+?do_AssignFromElementPtr@nsAString@@MAEXPBG@Z ; 73811
+?copy_string@@YAAAPAGAAV?$nsReadingIterator@G@@ABV1@AAPAG@Z ; 71847
+?GetReadableFragment@nsPromiseCSubstring@@MBEPBDAAU?$nsReadableFragment@D@@W4nsFragmentRequest@@I@Z ; 71331
+?GetBuffer@ByteBufferImpl@@UBGPADXZ ; 71201
+?Read@ConverterInputStream@@UAGIPAGIIPAI@Z ; 70839
+?Read@nsPersistentProperties@@QAEHXZ ; 70367
+?do_AssignFromElementPtr@nsACString@@MAEXPBD@Z ; 62916
+?Length@nsPromiseCSubstring@@UBEIXZ ; 62793
+?CompareWithConversion@nsCString@@QBEHPBDHH@Z ; 62172
+??0NS_ConvertASCIItoUCS2@@QAE@PBD@Z ; 61750
+?CreateInstanceByContractID@nsComponentManagerImpl@@UAGIPBDPAVnsISupports@@ABUnsID@@PAPAX@Z ; 61075
+?CreateInstance@nsComponentManager@@SAIPBDPAVnsISupports@@ABUnsID@@PAPAX@Z ; 61075
+?Exit@nsAutoMonitor@@QAEXXZ ; 59293
+?Enter@nsAutoMonitor@@QAEXXZ ; 59293
+PL_GetEventOwner ; 55295
+?RefCountInInterfacePointers@nsProxyObjectCallInfo@@AAEXH@Z ; 55218
+?Clone@nsMemory@@SAPAXPBXI@Z ; 53069
+?Promises@nsAString@@UBEHABV1@@Z ; 52421
+?Promises@nsPromiseSubstring@@UBEHABVnsAString@@@Z ; 52287
+?ContractIDToClassID@nsComponentManager@@SAIPBDPAUnsID@@@Z ; 51898
+?GetStringValue@nsStaticCaseInsensitiveNameTable@@QAEABVnsCString@@H@Z ; 51863
+?CopyUnicodeTo@@YAXABV?$nsReadingIterator@G@@0AAVnsAString@@@Z ; 51424
+??RnsGetInterface@@UBEIABUnsID@@PAPAX@Z ; 51014
+?GetService@nsServiceManager@@SAIPBDABUnsID@@PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 50614
+?GetService@nsServiceManagerImpl@@UAGIPBDABUnsID@@PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 50608
+?GetElementAt@nsSupportsArray@@UAGIIPAPAVnsISupports@@@Z ; 50421
+??0nsCAutoString@@QAE@PBD@Z ; 50288
+?Release@nsGenericFactory@@UAGKXZ ; 48967
+?Release@nsLocalFile@@UAGKXZ ; 48924
+?CreateInstance@nsGenericFactory@@UAGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 47807
+?ToNewUnicode@@YAPAGABVnsAString@@@Z ; 47476
+?Equals@nsSupportsArray@@UAGHPBVnsISupportsArray@@@Z ; 47394
+?QueryInterface@nsWeakReference@@UAGIABUnsID@@PAPAX@Z ; 47232
+?ToInteger@nsString@@QBEHPAHI@Z ; 46397
+??0nsGetServiceByContractID@@QAE@PBDPAVnsISupports@@PAI@Z ; 45960
+??RnsGetServiceByContractID@@UBEIABUnsID@@PAPAX@Z ; 45960
+?Reset@nsHashtable@@QAEXP6AHPAVnsHashKey@@PAX1@Z1@Z ; 45160
+?Reset@nsHashtable@@QAEXXZ ; 44779
+?strdup@nsCRT@@SAPAGPBG@Z ; 44542
+?strndup@nsCRT@@SAPAGPBGI@Z ; 44542
+PL_InitEvent ; 42216
+PL_DestroyEvent ; 42216
+?Release@nsProxyObject@@UAGKXZ ; 42053
+?HashCode@nsCRT@@SAIPBGPAI@Z ; 41515
+?MakeDirty@nsLocalFile@@AAEXXZ ; 40921
+?CompressSet@nsStr@@SAXAAU1@PBDHH@Z ; 40756
+?FindSubstr@nsStr@@SAHABU1@0HHH@Z ; 40557
+XPTC_InvokeByIndex ; 40446
+?QueryInterface@nsEventQueueImpl@@UAGIABUnsID@@PAPAX@Z ; 40010
+?Peek@nsDeque@@QAEPAXXZ ; 39695
+?ToUpper@nsCRT@@SAGG@Z ; 39657
+?CopyStrings@nsProxyObjectCallInfo@@AAEXH@Z ; 39492
+PL_DHashTableOperate ; 39446
+??0nsDeque@@QAE@PAVnsDequeFunctor@@@Z ; 38500
+?Empty@nsDeque@@QAEAAV1@XZ ; 38489
+??1nsDeque@@QAE@XZ ; 38489
+?Erase@nsDeque@@QAEAAV1@XZ ; 38489
+?GetSegmentCount@nsSegmentedBuffer@@QAEIXZ ; 38168
+?Release@nsProxyEventObject@@UAGKXZ ; 37461
+?ReplaceElementAt@nsVoidArray@@QAEHPAXH@Z ; 37379
+??0nsAutoString@@QAE@PBG@Z ; 35740
+PL_GetEvent ; 34422
+PL_HandleEvent ; 34415
+PL_PostEvent ; 34415
+?PostEvent@nsEventQueueImpl@@UAG?AW4PRStatus@@PAUPLEvent@@@Z ; 34353
+?strncmp@nsCRT@@SAHPBG0I@Z ; 34311
+?Cut@nsAString@@UAEXII@Z ; 33933
+?Release@nsThread@@UAGKXZ ; 32675
+?GetInstance@nsProxyObjectManager@@SAPAV1@XZ ; 31747
+?EqualsWithConversion@nsCString@@QBEHPBGHH@Z ; 31327
+?CompareWithConversion@nsCString@@QBEHPBGHH@Z ; 31327
+?GetRealObject@nsProxyObject@@QBEPAVnsISupports@@XZ ; 30180
+PL_DHashStringKey ; 29743
+?QueryInterface@nsEventQueueServiceImpl@@UAGIABUnsID@@PAPAX@Z ; 29645
+?GetReadSegment@nsPipe@@QAEIIPAPBDPAI@Z ; 29618
+??1nsXPIDLString@@UAE@XZ ; 29310
+?Release@nsProxyEventClass@@UAGKXZ ; 29259
+??0nsPromiseSubstring@@QAE@ABVnsAString@@II@Z ; 29232
+?Compact@nsSupportsArray@@UAGIXZ ; 28635
+?Mid@nsAString@@QBEIAAV1@II@Z ; 28616
+?AssignFromPromise@nsAString@@IAEXABV1@@Z ; 28510
+?get@nsAFlatString@@UBEPBGXZ ; 28400
+?Equals@nsACString@@QBEHABV1@@Z ; 28339
+?convertMiniVariantToVariant@nsProxyObject@@AAEIPAVnsXPTMethodInfo@@PAUnsXPTCMiniVariant@@PAPAUnsXPTCVariant@@PAE@Z ; 27609
+??_EnsProxyObjectCallInfo@@UAEPAXI@Z ; 27609
+?Post@nsProxyObject@@QAEIIPAVnsXPTMethodInfo@@PAUnsXPTCMiniVariant@@PAVnsIInterfaceInfo@@@Z ; 27609
+??1nsProxyObjectCallInfo@@UAE@XZ ; 27609
+?CallMethod@nsProxyEventObject@@UAGIGPBVnsXPTMethodInfo@@PAUnsXPTCMiniVariant@@@Z ; 27609
+??0nsProxyObjectCallInfo@@QAE@PAVnsProxyObject@@PAVnsXPTMethodInfo@@IPAUnsXPTCVariant@@IPAUPLEvent@@@Z ; 27609
+?Append@NS_ConvertUCS2toUTF8@@IAEXPBGI@Z ; 27265
+?ReplaceChar@nsString@@QAEXPBDG@Z ; 26980
+?CompressSet@nsString@@QAEXPBDGHH@Z ; 26980
+?CompressChars2@@YAHPADIPBD@Z ; 26980
+?CompressWhitespace@nsString@@QAEXHH@Z ; 26980
+?assign_assuming_AddRef@nsCOMPtr_base@@IAEXPAVnsISupports@@@Z ; 26695
+?do_AssignFromElement@nsAString@@MAEXG@Z ; 25781
+??0nsCAutoString@@QAE@ABVCBufDescriptor@@@Z ; 25669
+??0CBufDescriptor@@QAE@PADHIH@Z ; 25623
+?RemoveElementAt@nsSupportsArray@@UAGHI@Z ; 25489
+PL_IsQueueOnCurrentThread ; 25382
+?GetInterfaceInfo@nsProxyEventObject@@UAGIPAPAVnsIInterfaceInfo@@@Z ; 25038
+?Equals@nsACString@@QBEHPBD@Z ; 24972
+?ReadSegments@nsPipeInputStream@nsPipe@@UAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 24934
+?Cut@nsACString@@UAEXII@Z ; 24343
+?RemoveElement@nsSupportsArray@@UAGHPBVnsISupports@@I@Z ; 24174
+?RemoveElement@nsSupportsArray@@UAGIPAVnsISupports@@@Z ; 24174
+??0nsPromiseCSubstring@@QAE@ABVnsACString@@II@Z ; 23764
+?Mid@nsACString@@QBEIAAV1@II@Z ; 23764
+?AssignFromPromise@nsACString@@IAEXABV1@@Z ; 23764
+?ToNewUnicode@nsString@@QBEPAGXZ ; 23688
+?Last@nsACString@@QBEDXZ ; 22996
+?AssignWithConversion@nsCString@@QAEXABVnsAString@@@Z ; 22923
+?IsQueueOnCurrentThread@nsEventQueueImpl@@UAGIPAH@Z ; 22307
+?AppendWithConversion@nsString@@QAEXD@Z ; 22276
+?Compare1To2@@YAHPBD0IH@Z ; 22272
+?GetIID@xptiInterfaceInfo@@UAGIPAPAUnsID@@@Z ; 21683
+?Find@nsString@@QBEHPBDHHH@Z ; 21620
+?AppendFromReadable@nsACString@@IAEXABV1@@Z ; 21546
+??0nsLocalCString@@QAE@PBDI@Z ; 21266
+??0nsAString@@QAE@XZ ; 20650
+?HashCode@nsProxyEventKey@@UBEIXZ ; 20409
+?QueryInterface@nsLocalFile@@UAGIABUnsID@@PAPAX@Z ; 19832
+?QueryElementAt@nsSupportsArray@@UAGIIABUnsID@@PAPAX@Z ; 19439
+?HashCode@nsStringKey@@UBEIXZ ; 19128
+??1nsStringKey@@UAE@XZ ; 18271
+??RnsCreateInstanceByContractID@@UBEIABUnsID@@PAPAX@Z ; 17842
+?GetTypelibGuts@xptiWorkingSet@@QAEPAVxptiTypelibGuts@@ABVxptiTypelib@@@Z ; 17499
+?GetInfoAtNoAddRef@xptiTypelibGuts@@QAEPAVxptiInterfaceInfo@@G@Z ; 17499
+?GetInfoForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@PAPAVnsIInterfaceInfo@@@Z ; 17441
+?GetIIDForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@PAPAUnsID@@@Z ; 17381
+?Find@nsString@@QBEHABV1@HHH@Z ; 17158
+?NS_NewAtom@@YAPAVnsIAtom@@PBG@Z ; 17124
+?Delete@nsStr@@SAXAAU1@II@Z ; 17080
+?QueryInterface@nsProxyEventObject@@UAGIABUnsID@@PAPAX@Z ; 17047
+?StripChars@nsStr@@SAXAAU1@PBD@Z ; 16392
+?StripChars@nsCString@@QAEXPBD@Z ; 16392
+?Equals@nsVoidKey@@UBEHPBVnsHashKey@@@Z ; 15797
+?StripChar@nsString@@QAEXGH@Z ; 15611
+?do_AppendFromElementPtrLength@nsACString@@MAEXPBDI@Z ; 15433
+?NS_NewAtom@@YAPAVnsIAtom@@PBD@Z ; 14915
+?strcasecmp@nsCRT@@SAHPBG0@Z ; 14605
+?GetNewOrUsedClass@nsProxyEventClass@@SAPAV1@ABUnsID@@@Z ; 14587
+?do_GetService@@YA?BVnsGetServiceByCID@@ABUnsID@@PAI@Z ; 14568
+??0nsProxyEventObject@@QAE@PAVnsIEventQueue@@HPAVnsISupports@@PAVnsProxyEventClass@@PAV0@@Z ; 14476
+??0nsProxyObject@@QAE@PAVnsIEventQueue@@HPAVnsISupports@@@Z ; 14476
+??1nsProxyEventObject@@UAE@XZ ; 14444
+??_EnsProxyObject@@UAEPAXI@Z ; 14444
+??_EnsProxyEventObject@@UAEPAXI@Z ; 14444
+??1nsProxyObject@@UAE@XZ ; 14444
+?ReleaseData@nsSimpleCharString@@IAEXXZ ; 14127
+??1?$nsSharedBufferHandle@G@@QAE@XZ ; 13784
+?CompressChars1@@YAHPADIPBD@Z ; 13776
+?CompressSet@nsCString@@QAEXPBDGHH@Z ; 13776
+?ReplaceChar@nsCString@@QAEXPBDG@Z ; 13776
+??0NS_ConvertUCS2toUTF8@@QAE@ABVnsAString@@@Z ; 13501
+??0nsCString@@QAE@ABVnsACString@@@Z ; 13490
+?Compact@nsVoidArray@@QAEXXZ ; 13069
+?ResolveAndStat@nsLocalFile@@AAEIH@Z ; 13042
+?Trim@nsCString@@QAEXPBDHHH@Z ; 12473
+?ToCString@nsString@@QBEPADPADII@Z ; 12467
+?Copy@nsXPIDLCString@@SAPADPBD@Z ; 12345
+?StripChars1@@YAHPADIPBD@Z ; 12243
+PL_ProcessPendingEvents ; 11979
+?copy_string@@YAAAV?$LossyConvertEncoding@GD@@AAV?$nsReadingIterator@G@@ABV2@AAV1@@Z ; 11800
+?ToNewCString@@YAPADABVnsAString@@@Z ; 11800
+?ToNewUTF8String@@YAPADABVnsAString@@@Z ; 11776
+?Release@nsProxyObjectManager@@UAGKXZ ; 11736
+??1nsCommonString@@UAE@XZ ; 11669
+?UnlinkBuffer@nsSharedBufferList@@QAEPAVBuffer@1@PAV21@@Z ; 11567
+?FindItem@nsAVLTree@@QBEPAXPAX@Z ; 11472
+?ReallocData@nsSimpleCharString@@IAEXI@Z ; 11366
+?ShiftCharsLeft@@YAXPADIII@Z ; 11222
+?GetYoungest@nsEventQueueImpl@@UAGIPAPAVnsIEventQueue@@@Z ; 10964
+?SetFollowLinks@nsLocalFile@@UAGIH@Z ; 10936
+?GetYoungestEventQueue@nsEventQueueServiceImpl@@AAEIPAVnsIEventQueue@@PAPAV2@@Z ; 10928
+?GetThreadEventQueue@nsEventQueueServiceImpl@@UAGIPAUPRThread@@PAPAVnsIEventQueue@@@Z ; 10925
+??0nsSharedBufferList@@QAE@PAVBuffer@0@@Z ; 10649
+?init_range_from_buffer_list@nsSlidingSubstring@@AAEXXZ ; 10649
+?DestroyBuffers@nsSharedBufferList@@IAEXXZ ; 10647
+??_EnsSlidingSharedBufferList@@UAEPAXI@Z ; 10647
+??1nsSharedBufferList@@UAE@XZ ; 10647
+??RnsCreateInstanceByCID@@UBEIABUnsID@@PAPAX@Z ; 10636
+?Put@nsSupportsHashtable@@QAEHPAVnsHashKey@@PAVnsISupports@@PAPAV3@@Z ; 10605
+?ToLowerCase@nsString@@QBEXAAV1@@Z ; 10514
+?GetPath@nsLocalFile@@UAGIPAPAD@Z ; 10449
+??0nsStringKey@@QAE@PBGHW4Ownership@0@@Z ; 10430
+?AddRef@nsPipeInputStream@nsPipe@@UAGKXZ ; 10377
+?Release@nsPipeInputStream@nsPipe@@UAGKXZ ; 10375
+?Rebind@nsSlidingSubstring@@QAEXABVnsAString@@@Z ; 10240
+?PeekFront@nsDeque@@QAEPAXXZ ; 10192
+??2AtomImpl@@SAPAXIABVnsAString@@@Z ; 10144
+??0AtomImpl@@QAE@XZ ; 10144
+?ResolveEventQueue@nsEventQueueServiceImpl@@UAGIPAVnsIEventQueue@@PAPAV2@@Z ; 10065
+?ToNewUTF8String@nsString@@QBEPADXZ ; 10047
+PL_DHashTableEnumerate ; 9813
+?AddBucket@nsFixedSizeAllocator@@IAEII@Z ; 9776
+?AppendWithConversion@nsCString@@QAEXABVnsString@@H@Z ; 9758
+?Right@nsACString@@QBEIAAV1@I@Z ; 9591
+?Lookup@nsStaticCaseInsensitiveNameTable@@QAEHABVnsCString@@@Z ; 9227
+?Enumerate@nsHashtable@@QAEXP6AHPAVnsHashKey@@PAX1@Z1@Z ; 9133
+?GetParent@xptiInterfaceInfo@@UAGIPAPAVnsIInterfaceInfo@@@Z ; 9105
+_md_EventReceiverProc@16 ; 9061
+?InitWithPath@nsLocalFile@@UAGIPBD@Z ; 8986
+??0nsLocalFile@@QAE@XZ ; 8981
+??_EnsLocalFile@@UAEPAXI@Z ; 8977
+??1nsLocalFile@@UAE@XZ ; 8977
+NS_NewLocalFile ; 8952
+?GetWriteSegment@nsPipe@@QAEIPAPADPAI@Z ; 8809
+?GetProxyForObject@nsProxyObjectManager@@UAGIPAVnsIEventQueue@@ABUnsID@@PAVnsISupports@@HPAPAX@Z ; 8762
+?GetNewOrUsedProxy@nsProxyEventObject@@SAPAV1@PAVnsIEventQueue@@HPAVnsISupports@@ABUnsID@@@Z ; 8762
+?Equals@nsProxyEventKey@@UBEHPBVnsHashKey@@@Z ; 8745
+?AddRef@nsPipeOutputStream@nsPipe@@UAGKXZ ; 8650
+?Release@nsPipeOutputStream@nsPipe@@UAGKXZ ; 8649
+?Read@nsPipeInputStream@nsPipe@@UAGIPADIPAI@Z ; 8617
+??4nsXPIDLCString@@QAEAAV0@PBD@Z ; 8570
+??1nsSimpleCharString@@QAE@XZ ; 8555
+?Equals@nsStringKey@@UBEHPBVnsHashKey@@@Z ; 8497
+?AddRefData@nsSimpleCharString@@IAEXXZ ; 8367
+?Init@nsFixedSizeAllocator@@QAEIPBDPBIHHH@Z ; 7954
+??0nsStringKey@@QAE@ABVnsAString@@@Z ; 7944
+?Release@nsArrayEnumerator@@UAGKXZ ; 7923
+?PostCompleted@nsProxyObjectCallInfo@@QAEXXZ ; 7863
+?SetCompleted@nsProxyObjectCallInfo@@QAEXXZ ; 7863
+??0nsCString@@QAE@ABV0@@Z ; 7622
+?AppendNewSegment@nsSegmentedBuffer@@QAEPADXZ ; 7622
+??_GAtomImpl@@UAEPAXI@Z ; 7566
+??1AtomImpl@@UAE@XZ ; 7566
+??0nsCString@@QAE@PBD@Z ; 7541
+??0nsAutoString@@QAE@ABVCBufDescriptor@@@Z ; 7529
+??0NS_ConvertASCIItoUCS2@@QAE@PBDI@Z ; 7452
+??0nsString@@QAE@ABVnsAString@@@Z ; 7419
+??0CBufDescriptor@@QAE@PAGHIH@Z ; 7406
+??0nsCreateInstanceByContractID@@QAE@PBDPAVnsISupports@@PAI@Z ; 7402
+?EnumerateForwards@nsVoidArray@@QAEHP6AHPAX0@Z0@Z ; 7195
+?AppendInt@nsCString@@QAEXHH@Z ; 7047
+??RnsGetWeakReference@@UBEIABUnsID@@PAPAX@Z ; 7028
+?NS_GetWeakReference@@YAPAVnsIWeakReference@@PAVnsISupports@@PAI@Z ; 7022
+?Clone@nsLocalFile@@UAGIPAPAVnsIFile@@@Z ; 6960
+?AppendRelativePath@nsLocalFile@@UAGIPBD@Z ; 6927
+?Empty@nsSegmentedBuffer@@QAEXXZ ; 6878
+??_EnsIDKey@@UAEPAXI@Z ; 6876
+?Append@nsLocalFile@@UAGIPBD@Z ; 6818
+?RFindChar@nsStr@@SAHABU1@GHHH@Z ; 6753
+?RFindChar@nsString@@QBEHGHHH@Z ; 6753
+?GetWeakReference@nsSupportsWeakReference@@UAGIPAPAVnsIWeakReference@@@Z ; 6751
+?Release@nsMemoryImpl@@UAGKXZ ; 6468
+??1nsSupportsWeakReference@@UAE@XZ ; 6428
+?SetNonBlocking@nsPipeInputStream@nsPipe@@UAGIH@Z ; 6306
+PL_DHashTableRawRemove ; 6270
+?GetNext@nsArrayEnumerator@@UAGIPAPAVnsISupports@@@Z ; 6180
+?ReleaseService@nsServiceManagerImpl@@UAGIABUnsID@@PAVnsISupports@@PAVnsIShutdownListener@@@Z ; 6156
+?RFindSubstr@nsStr@@SAHABU1@0HHH@Z ; 6056
+?RFind@nsCString@@QBEHPBDHHH@Z ; 6052
+?HasMoreElements@nsDirEnumerator@@UAGIPAH@Z ; 5962
+?QueryInterface@nsProxyObjectManager@@UAGIABUnsID@@PAPAX@Z ; 5920
+?GetReadableFragment@nsSlidingString@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 5909
+?ShiftDoubleCharsLeft@@YAXPADIII@Z ; 5858
+?Clone@nsProxyEventKey@@UBEPAVnsHashKey@@XZ ; 5832
+?IsManagerShutdown@nsProxyObjectManager@@SAHXZ ; 5823
+?ReleaseService@nsServiceManager@@SAIABUnsID@@PAVnsISupports@@PAVnsIShutdownListener@@@Z ; 5681
+??4nsSimpleCharString@@QAEXABV0@@Z ; 5572
+?Copy@nsXPIDLString@@SAPAGPBG@Z ; 5526
+??0nsString@@QAE@PBG@Z ; 5504
+?Find@nsProxyEventObject@@QAEPAV1@ABUnsID@@@Z ; 5501
+?WriteSegments@nsPipeOutputStream@nsPipe@@UAGIP6GIPAVnsIOutputStream@@PAXPADIIPAI@Z1I3@Z ; 5497
+?Read@StringUnicharInputStream@@UAGIPAGIIPAI@Z ; 5482
+?WriteFrom@nsPipeOutputStream@nsPipe@@UAGIPAVnsIInputStream@@IPAI@Z ; 5388
+?ToNewCString@nsString@@QBEPADXZ ; 5351
+?Release@nsInputStreamTee@@UAGKXZ ; 5341
+?IndexOf@nsSupportsArray@@UAGHPBVnsISupports@@@Z ; 5281
+?IndexOfStartingAt@nsSupportsArray@@UAGHPBVnsISupports@@I@Z ; 5281
+??6nsOutputStream@@QAEAAV0@PBD@Z ; 5112
+?ToInteger@nsCString@@QBEHPAHI@Z ; 5109
+?do_AssignFromElementPtrLength@nsACString@@MAEXPBDI@Z ; 5103
+?Exists@nsLocalFile@@UAGIPAH@Z ; 5085
+?PL_HashTableInit@@YA?AW4PRStatus@@PAUPLHashTable@@IP6AIPBX@ZP6AH11@Z3PBUPLHashAllocOps@@PAX@Z ; 4964
+??0nsHashtable@@QAE@IH@Z ; 4964
+?Get@nsInt2StrHashtable@@QAEPADI@Z ; 4864
+??BnsSimpleCharString@@QAEPADXZ ; 4785
+?GetConstant@xptiInterfaceInfo@@UAGIGPAPBVnsXPTConstant@@@Z ; 4716
+?PL_HashTableFinalize@@YAXPAUPLHashTable@@@Z ; 4596
+??1nsHashtable@@UAE@XZ ; 4596
+?do_AssignFromElementPtrLength@nsAString@@MAEXPBGI@Z ; 4541
+?Error@nsFileSpec@@QBEIXZ ; 4535
+?GetSpecialEventQueue@nsEventQueueServiceImpl@@UAGIHPAPAVnsIEventQueue@@@Z ; 4454
+?GetStringProperty@nsPersistentProperties@@UAGIABVnsString@@AAV2@@Z ; 4441
+?DumpStatistics@nsTraceRefcnt@@SAIW4StatisticsType@1@PAU_iobuf@@@Z ; 4434
+?GetBufferHandle@nsPrivateSharableString@@UBEPBV?$nsBufferHandle@G@@XZ ; 4434
+?Release@xptiInterfaceInfoManager@@UAGKXZ ; 4417
+?Clone@nsCStringKey@@UBEPAVnsHashKey@@XZ ; 4332
+?normalize_backward@?$nsWritingIterator@D@@QAEXXZ ; 4288
+??1nsFileSpec@@UAE@XZ ; 4256
+?AddRef@BasicStringImpl@@UAGKXZ ; 4185
+??_EnsCStringKey@@UAEPAXI@Z ; 4173
+?ToCString@nsCString@@QBEPADPADII@Z ; 4056
+?First@nsDequeIterator@@QAEAAV1@XZ ; 4049
+??_EnsSubsumeStr@@UAEPAXI@Z ; 4048
+?InsertStringAt@nsStringArray@@QAEHABVnsAString@@H@Z ; 4026
+?Release@BasicStringImpl@@UAGKXZ ; 3967
+?ReleaseValues@nsProperties@@SAHPAVnsHashKey@@PAX1@Z ; 3966
+?StripChars2@@YAHPADIPBD@Z ; 3927
+?ToFloat@nsString@@QBEMPAH@Z ; 3910
+?Release@nsThreadPool@@UAGKXZ ; 3896
+??0nsPromiseFlatCString@@IAE@ABVnsACString@@@Z ; 3888
+??1nsPromiseFlatCString@@UAE@XZ ; 3878
+?Clone@nsStringKey@@UBEPAVnsHashKey@@XZ ; 3824
+?RFindChar2@@YAHPBDIHGHH@Z ; 3738
+??_EnsStringKey@@UAEPAXI@Z ; 3721
+?Alloc@ArenaImpl@@UAGPAXI@Z ; 3688
+?DeleteFirstSegment@nsSegmentedBuffer@@QAEHXZ ; 3646
+?OpenANSIFileDesc@nsLocalFile@@UAGIPBDPAPAU_iobuf@@@Z ; 3547
+?EqualsWithConversion@nsCString@@QBEHPBDHH@Z ; 3544
+?EqualsIgnoreCase@nsCString@@QBEHPBDH@Z ; 3544
+?ResolvePath@nsLocalFile@@AAEIPBDHPAPAD@Z ; 3539
+?CopyFrom@nsSimpleCharString@@QAEXPBDI@Z ; 3498
+?FindCharInReadable@@YAHGAAV?$nsReadingIterator@G@@ABV1@@Z ; 3480
+??0nsPromiseSubstring@@QAE@ABV?$nsReadingIterator@G@@0@Z ; 3431
+?GetStringUTF8@nsRegistry@@UAGIIPBDPAPAD@Z ; 3345
+??0nsSegmentedBuffer@@QAE@XZ ; 3334
+??1nsSegmentedBuffer@@QAE@XZ ; 3333
+?GetInfoForName@xptiInterfaceInfoManager@@UAGIPBDPAPAVnsIInterfaceInfo@@@Z ; 3332
+?Init@nsSegmentedBuffer@@QAEIIIPAVnsIMemory@@@Z ; 3307
+?HasInterfaceRecord@xptiInterfaceInfo@@QBEHXZ ; 3300
+?Compare@@YAHABVnsACString@@0@Z ; 3236
+?vsmprintf@nsTextFormatter@@SAPAGPBGPAD@Z ; 3228
+?smprintf@nsTextFormatter@@SAPAGPBGZZ ; 3228
+?QueryInterface@nsMemoryImpl@@UAGIABUnsID@@PAPAX@Z ; 3156
+??0nsPipe@@QAE@XZ ; 3153
+?Close@nsPipeOutputStream@nsPipe@@UAGIXZ ; 3153
+?SetObserver@nsPipeInputStream@nsPipe@@UAGIPAVnsIInputStreamObserver@@@Z ; 3153
+?Initialize@nsPipe@@UAGIIIHHPAVnsIMemory@@@Z ; 3153
+?NS_NewPipe@@YAIPAPAVnsIInputStream@@PAPAVnsIOutputStream@@IIHHPAVnsIMemory@@@Z ; 3153
+?Close@nsPipeInputStream@nsPipe@@UAGIXZ ; 3152
+??1nsPipe@@UAE@XZ ; 3152
+??_GnsPipe@@UAEPAXI@Z ; 3152
+?GetLeafName@nsLocalFile@@UAGIPAPAD@Z ; 3138
+?Parse@nsID@@QAEHPBD@Z ; 3088
+?GetLeaf@nsSimpleCharString@@QBEPADD@Z ; 3070
+?GetLeafName@nsFileSpec@@QBEPADXZ ; 3070
+?Flush@nsPipeOutputStream@nsPipe@@UAGIXZ ; 3043
+?CheckForDeactivation@nsEventQueueImpl@@AAEXXZ ; 3018
+?RFindChar1@@YAHPBDIHGHH@Z ; 3015
+??0nsCAutoString@@QAE@ABVnsACString@@@Z ; 3014
+?GetNext@nsDirEnumerator@@UAGIPAPAVnsISupports@@@Z ; 2976
+?ProcessPendingEvents@nsEventQueueImpl@@UAGIXZ ; 2951
+?GetInterfaceInfoManagerNoAddRef@xptiInterfaceInfoManager@@SAPAV1@XZ ; 2948
+?CountChar@nsAString@@QBEIG@Z ; 2937
+?AppendInt@nsString@@QAEXHH@Z ; 2922
+?ToUpperCase@nsString@@QAEXXZ ; 2900
+nsUnescapeCount ; 2828
+nsUnescape ; 2828
+??0nsSimpleCharString@@QAE@ABV0@@Z ; 2795
+??4nsFileSpec@@QAEXABV0@@Z ; 2739
+??0nsFileSpec@@QAE@ABV0@@Z ; 2731
+?StripWhitespace@nsString@@QAEXXZ ; 2714
+XPTI_GetInterfaceInfoManager ; 2696
+?StringAt@nsStringArray@@QBEPAVnsString@@H@Z ; 2681
+??0nsArrayEnumerator@@QAE@PAVnsISupportsArray@@@Z ; 2637
+??1nsArrayEnumerator@@UAE@XZ ; 2637
+?GetPRThread@nsThread@@UAGIPAPAUPRThread@@@Z ; 2623
+?GetMainThread@nsIThread@@SAIPAPAV1@@Z ; 2622
+NS_NewArrayEnumerator ; 2582
+??_EnsArrayEnumerator@@UAEPAXI@Z ; 2582
+?CallQueryInterfaceOnProxy@nsProxyEventClass@@AAEIPAVnsProxyEventObject@@ABUnsID@@PAPAV2@@Z ; 2571
+?GetQueue@nsProxyEventObject@@QBEPAVnsIEventQueue@@XZ ; 2571
+?DelegatedQueryInterface@nsProxyEventClass@@UAGIPAVnsProxyEventObject@@ABUnsID@@PAPAX@Z ; 2571
+?GetRealObject@nsProxyEventObject@@QBEPAVnsISupports@@XZ ; 2571
+??_EnsWeakReference@@EAEPAXI@Z ; 2556
+?ReadSegments@ConstCharImpl@@MAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 2520
+?IsDone@nsRegSubtreeEnumerator@@UAGIXZ ; 2490
+?Next@nsRegSubtreeEnumerator@@UAGIXZ ; 2490
+?advance@nsRegSubtreeEnumerator@@MAGIXZ ; 2451
+?GetErrorStringBundleKey@nsErrorService@@UAGIIPAPAD@Z ; 2432
+?GetErrorStringBundle@nsErrorService@@UAGIFPAPAD@Z ; 2432
+?GetIndexOf@nsSupportsArray@@UAGIPAVnsISupports@@PAH@Z ; 2409
+?ToNewUnicode@nsCString@@QBEPAGXZ ; 2376
+?ToNewCString@@YAPADABVnsACString@@@Z ; 2364
+?copy_string@@YAAAPADAAV?$nsReadingIterator@D@@ABV1@AAPAD@Z ; 2364
+?WriteSegmentFun@nsInputStreamTee@@CGIPAVnsIInputStream@@PAXPBDIIPAI@Z ; 2346
+?CurrentItemInPlaceUTF8@nsRegSubtreeEnumerator@@UAGIPAIPAPBD@Z ; 2320
+PL_DHashAllocTable ; 2253
+?Release@nsFileSpecImpl@@UAGKXZ ; 2241
+?GetSharedBufferHandle@nsCommonCString@@MBEPBV?$nsSharedBufferHandle@D@@XZ ; 2217
+?assign@nsCommonString@@IAEXABVnsAString@@@Z ; 2217
+?ReleaseReference@?$nsSharedBufferHandle@G@@QBEXXZ ; 2217
+?NS_AllocateContiguousHandleWithData@@YAPAV?$nsSharedBufferHandle@G@@PBV1@ABVnsAString@@I@Z ; 2217
+?QueryInterface@nsFileSpecImpl@@UAGIABUnsID@@PAPAX@Z ; 2172
+?GetRequest@nsThreadPool@@QAEPAVnsIRunnable@@PAVnsIThread@@@Z ; 2147
+PL_DHashFreeTable ; 2125
+?Clear@nsCStringArray@@QAEXXZ ; 2122
+?ReadSegments@nsInputStreamTee@@UAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 2115
+?TeeSegment@nsInputStreamTee@@AAEIPBDI@Z ; 2045
+?DispatchRequest@nsThreadPool@@UAGIPAVnsIRunnable@@@Z ; 2038
+??1nsThreadPoolBusyBody@@QAE@XZ ; 2038
+??0nsThreadPoolBusyBody@@QAE@PAVnsThreadPool@@@Z ; 2038
+??0nsCreateInstanceByCID@@QAE@ABUnsID@@PAVnsISupports@@PAI@Z ; 2029
+?ReplaceChar@nsCString@@QAEXGG@Z ; 2022
+?CloseStream@nsFileSpecImpl@@UAGIXZ ; 1968
+?do_InsertFromReadable@nsACString@@MAEXABV1@I@Z ; 1965
+?do_InsertFromElement@nsACString@@MAEXDI@Z ; 1965
+??_EnsFileSpecImpl@@UAEPAXI@Z ; 1955
+??1nsFileSpecImpl@@UAE@XZ ; 1955
+??0nsSimpleCharString@@QAE@PBD@Z ; 1936
+?RFindCharInSet@nsCString@@QBEHPBDH@Z ; 1913
+?RFindCharInSet@nsStr@@SAHABU1@0HH@Z ; 1913
+?Release@ByteBufferImpl@@UAGKXZ ; 1905
+?SkipWhiteSpace@nsPersistentProperties@@QAEHH@Z ; 1898
+?First@nsACString@@QBEDXZ ; 1881
+??0nsVoidArray@@QAE@H@Z ; 1876
+?copy_string_backward@@YAAAV?$nsWritingIterator@D@@ABV?$nsReadingIterator@D@@AAV2@AAV1@@Z ; 1834
+?QueryInterface@nsPipeInputStream@nsPipe@@UAGIABUnsID@@PAPAX@Z ; 1782
+?QueryInterface@nsPipe@@UAGIABUnsID@@PAPAX@Z ; 1782
+?CountCharInReadable@@YAIABVnsAString@@G@Z ; 1767
+?IsDirectory@nsLocalFile@@UAGIPAH@Z ; 1765
+?GetFileSpec@nsFileSpecImpl@@UAGIPAVnsFileSpec@@@Z ; 1765
+?CopyUnicodeTo@@YAPAGABVnsAString@@IPAGI@Z ; 1749
+NS_QuickSort ; 1729
+??1nsStringArray@@UAE@XZ ; 1709
+??0nsStringArray@@QAE@XZ ; 1709
+?IsScriptable@xptiInterfaceInfo@@UAGIPAH@Z ; 1690
+?Find@nsCString@@QBEHPBGHHH@Z ; 1674
+?SetLeafName@nsFileSpec@@QAEXPBD@Z ; 1670
+?LeafReplace@nsSimpleCharString@@QAEXDPBD@Z ; 1670
+?NextLine@ManifestLineReader@@QAEHXZ ; 1658
+??0nsFileSpec@@QAE@XZ ; 1656
+PL_DHashTableInit ; 1622
+??4nsSimpleCharString@@QAEXPBD@Z ; 1598
+?GetInterfaceIsArgNumberForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@PAE@Z ; 1555
+?Init@nsInputStreamTee@@UAGIPAVnsIInputStream@@PAVnsIOutputStream@@@Z ; 1550
+?QueryInterface@nsInputStreamTee@@UAGIABUnsID@@PAPAX@Z ; 1550
+?Right@nsAString@@QBEIAAV1@I@Z ; 1518
+PL_DHashTableFinish ; 1494
+??0nsFileSpecImpl@@QAE@ABVnsFileSpec@@@Z ; 1446
+?MakeInterface@nsFileSpecImpl@@SAIABVnsFileSpec@@PAPAVnsIFileSpec@@@Z ; 1446
+?NS_NewFileSpecWithSpec@@YAIABVnsFileSpec@@PAPAVnsIFileSpec@@@Z ; 1437
+??0xptiInterfaceInfo@@QAE@PBDABUnsID@@ABVxptiTypelib@@PAVxptiWorkingSet@@@Z ; 1434
+?CopyName@xptiInterfaceInfo@@AAEXPBDPAVxptiWorkingSet@@@Z ; 1434
+?SetScriptableFlag@xptiInterfaceInfo@@QAEXH@Z ; 1434
+??1xptiInterfaceInfo@@UAE@XZ ; 1427
+??_GxptiInterfaceInfo@@UAEPAXI@Z ; 1427
+??1nsSupportsHashtable@@UAE@XZ ; 1406
+??0nsACString@@QAE@XZ ; 1361
+?Exists@nsHashtable@@QAEHPAVnsHashKey@@@Z ; 1348
+?SetData@nsSupportsVoidImpl@@UAGIPAX@Z ; 1337
+??0BasicStringImpl@@QAE@XZ ; 1319
+?QueryInterface@BasicStringImpl@@UAGIABUnsID@@PAPAX@Z ; 1319
+??0ConstCharImpl@@QAE@PBDH@Z ; 1319
+?NewMonitor@nsAutoMonitor@@SAPAUPRMonitor@@PBD@Z ; 1312
+??1BasicStringImpl@@UAE@XZ ; 1309
+?DestroyMonitor@nsAutoMonitor@@SAXPAUPRMonitor@@@Z ; 1309
+??_EBasicStringImpl@@UAEPAXI@Z ; 1309
+?Enter@nsAutoCMonitor@@QAEXXZ ; 1307
+?Exit@nsAutoCMonitor@@QAEXXZ ; 1307
+?StringAllocator_wchar_t@@YAAAV?$nsStringAllocator@G@@XZ ; 1306
+?get_allocator@?$nsSharedBufferHandle@G@@IBEAAV?$nsStringAllocator@G@@XZ ; 1306
+?Deallocate@?$XPCOM_StringAllocator@G@@UBEXPAG@Z ; 1306
+NS_NewCharInputStream ; 1303
+?Release@nsRegSubtreeEnumerator@@UAGKXZ ; 1289
+??0nsDequeIterator@@QAE@ABVnsDeque@@H@Z ; 1284
+??FnsDequeIterator@@QAEPAXXZ ; 1284
+?End@nsDeque@@QBE?AVnsDequeIterator@@XZ ; 1284
+?OpenNSPRFileDesc@nsLocalFile@@UAGIHHPAPAUPRFileDesc@@@Z ; 1275
+?StrInsert@nsStr@@SAXAAU1@IABU1@IH@Z ; 1266
+?InsertWithConversion@nsString@@QAEXPBDIH@Z ; 1266
+?ShiftDoubleCharsRight@@YAXPADIII@Z ; 1266
+??0nsSupportsVoidImpl@@QAE@XZ ; 1260
+??_GnsSupportsVoidImpl@@UAEPAXI@Z ; 1260
+??1nsSupportsVoidImpl@@UAE@XZ ; 1260
+?QueryInterface@nsSupportsVoidImpl@@UAGIABUnsID@@PAPAX@Z ; 1260
+?QueryInterface@ConverterInputStream@@UAGIABUnsID@@PAPAX@Z ; 1258
+?get_at_eof@nsRandomAccessInputStream@@MBEHXZ ; 1241
+?GetAtEOF@FileImpl@@UAGIPAH@Z ; 1241
+?get_at_eof@nsRandomAccessStoreClient@@MBEHXZ ; 1241
+?GetTargetArraySize@nsObserverListEnumerator@@ABEIXZ ; 1208
+??YnsSimpleCharString@@QAEXPBD@Z ; 1187
+??_EStringUnicharInputStream@@UAEPAXI@Z ; 1178
+??1StringUnicharInputStream@@UAE@XZ ; 1178
+??0StringUnicharInputStream@@QAE@PAVnsString@@@Z ; 1178
+?NS_NewStringUnicharInputStream@@YAIPAPAVnsIUnicharInputStream@@PAVnsString@@@Z ; 1178
+??0nsInputStreamTee@@QAE@XZ ; 1164
+??_GnsInputStreamTee@@UAEPAXI@Z ; 1164
+??1nsInputStreamTee@@UAE@XZ ; 1164
+?NS_NewInputStreamTee@@YAIPAPAVnsIInputStream@@PAV1@PAVnsIOutputStream@@@Z ; 1164
+?GetTypelibRecord@xptiInterfaceInfo@@QBEABVxptiTypelib@@XZ ; 1156
+?Write@nsStorageStream@@UAGIPBDIPAI@Z ; 1138
+?GetObserverList@nsObserverService@@EAGIPBGPAPAVnsIObserverList@@@Z ; 1119
+?HasMoreElements@nsArrayEnumerator@@UAGIPAH@Z ; 1100
+?GetCString@nsFileSpec@@QBEPBDXZ ; 1098
+PL_DHashVoidPtrKeyStub ; 1098
+?strtok@nsCRT@@SAPADPADPBDPAPAD@Z ; 1084
+?GetInfoForIID@xptiInterfaceInfoManager@@UAGIPBUnsID@@PAPAVnsIInterfaceInfo@@@Z ; 1081
+??_EnsSupportsArrayEnumerator@@UAEPAXI@Z ; 1065
+??0nsSupportsArrayEnumerator@@QAE@PAVnsISupportsArray@@@Z ; 1065
+??1nsSupportsArrayEnumerator@@UAE@XZ ; 1065
+?Enumerate@nsSupportsArray@@UAGIPAPAVnsIEnumerator@@@Z ; 1065
+?First@nsSupportsArrayEnumerator@@UAGIXZ ; 1065
+?WriteFully@nsBinaryOutputStream@@QAEIPBDI@Z ; 1055
+?CurrentItem@nsSupportsArrayEnumerator@@UAGIPAPAVnsISupports@@@Z ; 1053
+?GetConstantCount@xptiInterfaceInfo@@UAGIPAG@Z ; 1040
+?Clone@nsIDKey@@UBEPAVnsHashKey@@XZ ; 1035
+?SetStringProperty@nsPersistentProperties@@UAGIABVnsString@@AAV2@1@Z ; 1006
+?Next@nsSupportsArrayEnumerator@@UAGIXZ ; 993
+?Release@nsStorageInputStream@@UAGKXZ ; 981
+?GetMethodCount@xptiInterfaceInfo@@UAGIPAG@Z ; 970
+?QueryInterface@nsObserverService@@UAGIABUnsID@@PAPAX@Z ; 948
+?FindChar@nsAString@@QBEHGI@Z ; 941
+?LinkBuffer@nsSharedBufferList@@QAEXPAVBuffer@1@00@Z ; 920
+?IsIID@xptiInterfaceInfo@@UAGIPBUnsID@@PAH@Z ; 918
+?AppendBuffer@nsSlidingString@@QAEXPAG00@Z ; 900
+??1nsFilePath@@UAE@XZ ; 886
+?NativeToUnix@nsFileSpecHelpers@@YAXAAVnsSimpleCharString@@@Z ; 886
+?SetDeallocator@nsDeque@@QAEXPAVnsDequeFunctor@@@Z ; 885
+?IsASCII@@YAHABVnsAString@@@Z ; 875
+?SkipLine@nsPersistentProperties@@QAEHH@Z ; 862
+?EnumerateObserverList@nsObserverService@@UAGIPBGPAPAVnsIEnumerator@@@Z ; 855
+?EnumerateObserverList@nsObserverList@@UAGIPAPAVnsIEnumerator@@@Z ; 855
+??4nsPersistentFileDescriptor@@QAEXABVnsFileSpec@@@Z ; 849
+??1nsPersistentFileDescriptor@@UAE@XZ ; 849
+??0nsPersistentFileDescriptor@@QAE@ABVnsFileSpec@@@Z ; 849
+?GetData@nsPersistentFileDescriptor@@QBEXAAVnsSimpleCharString@@@Z ; 849
+?GetPersistentDescriptorString@nsFileSpecImpl@@UAGIPAPAD@Z ; 849
+?FindInReadable@@YAHABVnsAString@@AAV?$nsReadingIterator@G@@1@Z ; 819
+?nsCID_Destroy@@YAHPAVnsHashKey@@PAX1@Z ; 773
+?Read@nsInputStreamTee@@UAGIPADIPAI@Z ; 769
+??1nsFactoryEntry@@QAE@XZ ; 737
+?nsFactoryEntry_Destroy@@YAHPAVnsHashKey@@PAX1@Z ; 733
+??0nsFileSpecImpl@@QAE@XZ ; 726
+?NS_NewFileSpec@@YAIPAPAVnsIFileSpec@@@Z ; 726
+?Create@nsFileSpecImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 726
+?UnixToNative@nsFileSpecHelpers@@YAXAAVnsSimpleCharString@@@Z ; 719
+?Invalidate@xptiInterfaceInfo@@QAEXXZ ; 717
+?AppendWithConversion@nsCString@@QAEXPBGH@Z ; 697
+??0nsFactoryEntry@@QAE@ABUnsID@@PBD1PAVnsIComponentLoader@@@Z ; 695
+?SetInfoAt@xptiTypelibGuts@@QAEIGPAVxptiInterfaceInfo@@@Z ; 683
+PL_DHashGetKeyStub ; 678
+PL_DHashMoveEntryStub ; 678
+?GrowCapacity@nsDeque@@AAEAAV1@XZ ; 673
+?AssignWithConversion@nsString@@QAEXPBDH@Z ; 665
+??4nsFilePath@@QAEXABVnsFileSpec@@@Z ; 659
+??0nsFilePath@@QAE@ABVnsFileSpec@@@Z ; 659
+?Canonify@nsFileSpecHelpers@@YAXAAVnsSimpleCharString@@H@Z ; 653
+?FromFileSpec@nsFileSpecImpl@@UAGIPBVnsIFileSpec@@@Z ; 652
+?GetValueType@nsRegistry@@UAGIIPBDPAI@Z ; 652
+?GetBytesUTF8@nsRegistry@@UAGIIPBDPAIPAPAE@Z ; 651
+?Write32@nsBinaryOutputStream@@UAGII@Z ; 649
+?EnumerateBackwards@nsSupportsArray@@UAGHP6AHPAVnsISupports@@PAX@Z1@Z ; 648
+?SetFromFileSpec@nsFileSpecImpl@@UAGIABVnsFileSpec@@@Z ; 634
+?smprintf_free@nsTextFormatter@@SAXPAG@Z ; 623
+?nsEndl@@YAAAVnsOutputStream@@AAV1@@Z ; 615
+?QueryInterface@nsGenericFactory@@UAGIABUnsID@@PAPAX@Z ; 606
+?Equals@nsAString@@QBEHPBG@Z ; 599
+?strcasecmp@nsCRT@@SAHPBGPBD@Z ; 585
+?put@nsOutputStream@@QAEXD@Z ; 572
+?IsFile@nsLocalFile@@UAGIPAH@Z ; 570
+?ForEach@nsDeque@@QBEXAAVnsDequeFunctor@@@Z ; 558
+?Release@EmptyEnumeratorImpl@@UAGKXZ ; 553
+NS_NewEmptyEnumerator ; 553
+?HasMoreElements@EmptyEnumeratorImpl@@UAGIPAH@Z ; 552
+?AddRef@FileImpl@@UAGKXZ ; 549
+?Release@FileImpl@@UAGKXZ ; 542
+?snprintf@nsTextFormatter@@SAIPAGIPBGZZ ; 534
+?vsnprintf@nsTextFormatter@@SAIPAGIPBGPAD@Z ; 534
+?Available@nsPipeInputStream@nsPipe@@UAGIPAI@Z ; 533
+?PushFront@nsDeque@@QAEAAV1@PAX@Z ; 522
+?AddItem@nsAVLTree@@QAE?AW4eAVLStatus@@PAX@Z ; 518
+??0nsAutoString@@QAE@PBGH@Z ; 509
+?IsDone@nsObserverListEnumerator@@UAGIXZ ; 479
+?MoveToIndex@nsObserverListEnumerator@@AAEII@Z ; 479
+?ReleaseService@nsServiceManager@@SAIPBDPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 477
+?ReleaseService@nsServiceManagerImpl@@UAGIPBDPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 477
+?AppendWithConversion@nsCString@@QAEXABVnsAString@@@Z ; 467
+?CreateDll@nsNativeComponentLoader@@AAEIPAVnsIFile@@PBDPA_J2PAPAVnsDll@@@Z ; 466
+?Flush@FileImpl@@UAGIXZ ; 455
+??1nsNSPRPath@@UAE@XZ ; 444
+??BnsNSPRPath@@QBEPBDXZ ; 444
+??0nsByteArrayInputStream@@QAE@PADI@Z ; 443
+??_EnsByteArrayInputStream@@UAEPAXI@Z ; 443
+??1nsByteArrayInputStream@@UAE@XZ ; 443
+?QueryInterface@nsByteArrayInputStream@@UAGIABUnsID@@PAPAX@Z ; 443
+?NS_NewByteArrayInputStream@@YAIPAPAVnsIByteArrayInputStream@@PADK@Z ; 443
+PL_DHashMatchEntryStub ; 442
+?ScriptableFlagIsValid@xptiInterfaceInfo@@ABEHXZ ; 439
+?PartiallyResolveLocked@xptiInterfaceInfo@@QAEHPAUXPTInterfaceDescriptor@@PAVxptiWorkingSet@@@Z ; 439
+??1xptiInterfaceGuts@@QAE@XZ ; 439
+?QueryInterface@FileImpl@@UAGIABUnsID@@PAPAX@Z ; 433
+??1xptiFile@@QAE@XZ ; 424
+?QueryInterface@nsSupportsStringImpl@@UAGIABUnsID@@PAPAX@Z ; 422
+?ReplaceChar@nsString@@QAEXGG@Z ; 421
+?Notify@nsObserverService@@UAGIPAVnsISupports@@PBG1@Z ; 416
+??0nsSlidingString@@QAE@PAG00@Z ; 408
+?NewWrappingBuffer@nsSharedBufferList@@SAPAVBuffer@1@PAG00@Z ; 408
+??0nsSlidingSubstring@@IAE@PAVnsSlidingSharedBufferList@@@Z ; 408
+??0nsCStringArray@@QAE@XZ ; 394
+??1nsCStringArray@@UAE@XZ ; 393
+??EnsDirectoryIterator@@QAEAAV0@XZ ; 377
+?Reset@nsSupportsHashtable@@QAEXXZ ; 370
+?ReadSegments@nsByteArrayInputStream@@UAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 356
+?GetFileSize@nsLocalFile@@UAGIPA_J@Z ; 354
+?SetDataWithLength@nsSupportsStringImpl@@UAGIIPBD@Z ; 344
+??0nsSupportsStringImpl@@QAE@XZ ; 344
+??1nsSupportsStringImpl@@UAE@XZ ; 337
+??_EnsSupportsStringImpl@@UAEPAXI@Z ; 337
+?GetModule@nsDll@@QAEIPAVnsISupports@@PAPAVnsIModule@@@Z ; 331
+?Release@nsStorageStream@@UAGKXZ ; 328
+?Release@nsSupportsIDImpl@@UAGKXZ ; 327
+?CopyASCIItoUCS2@@YAXABVnsACString@@AAVnsAString@@@Z ; 327
+?copy_string@@YAAAV?$LossyConvertEncoding@DG@@AAV?$nsReadingIterator@D@@ABV2@AAV1@@Z ; 327
+??_EnsCString@@UAEPAXI@Z ; 324
+?StringAt@nsStringArray@@QBEXHAAVnsAString@@@Z ; 321
+?ToString@nsID@@QBEPADXZ ; 319
+?GetLength@UnicharBufferImpl@@UBGHXZ ; 316
+?Fill@ByteBufferImpl@@UAGHPAIPAVnsIInputStream@@I@Z ; 316
+?Fill@ConverterInputStream@@IAEHPAI@Z ; 316
+?copy_string_backward@@YAAAV?$nsWritingIterator@G@@ABV?$nsReadingIterator@G@@AAV2@AAV1@@Z ; 310
+?do_InsertFromReadable@nsAString@@MAEXABV1@I@Z ; 310
+??0nsFileSpec@@QAE@PBDH@Z ; 307
+?SetData@nsSupportsStringImpl@@UAGIPBD@Z ; 295
+?InsertCStringAt@nsCStringArray@@QAEHABVnsCString@@H@Z ; 288
+??YnsFileSpec@@QAEXPBD@Z ; 281
+?CompressWhitespace@nsCString@@QAEXHH@Z ; 278
+?GetFactory@nsNativeComponentLoader@@UAGIABUnsID@@PBD1PAPAVnsIFactory@@@Z ; 273
+?GetFactoryFromModule@nsNativeComponentLoader@@AAEIPAVnsDll@@ABUnsID@@PAPAVnsIFactory@@@Z ; 273
+?GetReadableFragment@nsPromiseConcatenation@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 268
+?Load@nsDll@@QAEHXZ ; 254
+?HasMoreElements@nsAdapterEnumerator@@UAGIPAH@Z ; 251
+?Next@nsObserverListEnumerator@@UAGIXZ ; 250
+??0nsSubsumeStr@@QAE@XZ ; 250
+?Subsume@nsSubsumeStr@@QAEHPAGHH@Z ; 250
+?CurrentItem@nsObserverListEnumerator@@UAGIPAPAVnsISupports@@@Z ; 250
+?Release@nsRegistryNode@@UAGKXZ ; 245
+?PrepareEncoder@nsFSStringConversion@@CAIXZ ; 241
+?UCSToNewFS@nsFSStringConversion@@SAIPBGPAPAD@Z ; 241
+?Write@nsBinaryOutputStream@@UAGIPBDIPAI@Z ; 238
+?IsDirectory@nsFileSpec@@QBEHXZ ; 236
+?QueryInterface@nsConjoiningEnumerator@@UAGIABUnsID@@PAPAX@Z ; 236
+_DllMain@12 ; 235
+??_GnsObserverListEnumerator@@UAEPAXI@Z ; 229
+?First@nsObserverListEnumerator@@UAGIXZ ; 229
+??0nsObserverListEnumerator@@QAE@PAVnsISupportsArray@@@Z ; 229
+?SetComponentInfo@nsGenericFactory@@UAGIPAUnsModuleComponentInfo@@@Z ; 228
+?NS_NewGenericFactory@@YAIPAPAVnsIGenericFactory@@PAUnsModuleComponentInfo@@@Z ; 228
+?Create@nsGenericFactory@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 228
+??0nsGenericFactory@@QAE@PAUnsModuleComponentInfo@@@Z ; 228
+?do_InsertFromElementPtrLength@nsAString@@MAEXPBGII@Z ; 227
+??1nsGenericFactory@@UAE@XZ ; 226
+?GetBufferSize@ByteBufferImpl@@UBGIXZ ; 226
+??_EnsGenericFactory@@UAEPAXI@Z ; 226
+??4nsFileSpec@@QAEXABVnsFilePath@@@Z ; 219
+?GetLastModifiedTime@nsLocalFile@@UAGIPA_J@Z ; 217
+?RFindInReadable@@YAHABVnsAString@@AAV?$nsReadingIterator@G@@1@Z ; 217
+?GetTarget@nsLocalFile@@UAGIPAPAD@Z ; 216
+?CopyFields@xptiFile@@AAEXABV1@@Z ; 212
+??0xptiFile@@QAE@XZ ; 212
+?ConvertStringLineBreaks@nsLinebreakConverter@@SAIAAVnsString@@W4ELinebreakType@1@1@Z ; 212
+??0xptiFile@@QAE@ABVnsInt64@@0PBDPAVxptiWorkingSet@@PAUXPTHeader@@@Z ; 212
+?QueryInterface@nsDirectoryService@@UAGIABUnsID@@PAPAX@Z ; 211
+?ReplaceSubstring@nsString@@QAEXABV1@0@Z ; 210
+?GetLongLong@nsRegistry@@UAGIIPBDPA_J@Z ; 210
+??0nsSimpleCharString@@QAE@ABVnsString@@@Z ; 209
+PL_DHashClearEntryStub ; 209
+??4nsSimpleCharString@@QAEXABVnsString@@@Z ; 209
+?Release@nsDirectoryService@@UAGKXZ ; 208
+?GetType@xptiFileType@@SA?AW4Type@1@PBD@Z ; 208
+?AutoRegisterComponent@nsNativeComponentLoader@@UAGIHPAVnsIFile@@PAH@Z ; 208
+?SetLeafName@nsFileSpecImpl@@UAGIPBD@Z ; 207
+?SetLeafName@nsFileSpec@@QAEXABVnsString@@@Z ; 203
+??0nsFilePath@@QAE@ABVnsString@@H@Z ; 203
+nsEscapeHTML ; 200
+?SetActivityIsLegal@nsTraceRefcnt@@SAXH@Z ; 198
+?GetProxy@nsCWeakReferent@@QAEPAVnsCWeakProxy@@XZ ; 196
+??0nsCWeakProxy@@QAE@PAXPAVnsCWeakReferent@@@Z ; 196
+??0nsCWeakReferent@@QAE@PAX@Z ; 196
+?ReleaseReference@nsCWeakProxy@@QAEXXZ ; 195
+??_EnsCWeakProxy@@UAEPAXI@Z ; 195
+??1nsCWeakProxy@@UAE@XZ ; 195
+??1nsCWeakReferent@@UAE@XZ ; 195
+nsEscape ; 178
+nsEscapeCount ; 178
+?GetIsOpen@FileImpl@@UAGIPAH@Z ; 177
+?Exists@nsFileSpec@@QBEHXZ ; 173
+?read@nsInputStream@@QAEHPAXH@Z ; 171
+?Read@FileImpl@@UAGIPADIPAI@Z ; 171
+??0nsAutoString@@QAE@G@Z ; 170
+?GetClassObject@nsGenericModule@@UAGIPAVnsIComponentManager@@ABUnsID@@1PAPAX@Z ; 169
+?Get@nsDirectoryService@@UAGIPBDABUnsID@@PAPAX@Z ; 165
+?Seek@nsStorageStream@@AAGIH@Z ; 164
+?SetLength@nsStorageStream@@UAGII@Z ; 164
+?Close@FileImpl@@UAGIXZ ; 163
+?WriteStringZ@nsBinaryOutputStream@@UAGIPBD@Z ; 163
+?AppendElements@nsSupportsArray@@UAGHPAVnsISupportsArray@@@Z ; 162
+?Write8@nsBinaryOutputStream@@UAGIE@Z ; 162
+?AddObserver@nsObserverService@@UAGIPAVnsIObserver@@PBG@Z ; 158
+?AddObserver@nsObserverList@@UAGIPAVnsIObserver@@@Z ; 158
+?read@ConstCharImpl@@MAEHPADI@Z ; 156
+?Read@BasicStringImpl@@UAGIPADIPAI@Z ; 156
+?GetGlobalMemoryService@nsMemory@@SAPAVnsIMemory@@XZ ; 155
+?GetData@nsSupportsStringImpl@@UAGIPAPAD@Z ; 153
+??0nsCAutoString@@QAE@PBDH@Z ; 152
+??0nsObjectHashtable@@QAE@P6APAXPAVnsHashKey@@PAX1@Z1P6AH011@Z1IH@Z ; 140
+??0ArenaImpl@@QAE@XZ ; 139
+?Init@ArenaImpl@@UAGII@Z ; 139
+?Create@ArenaImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 139
+?NS_NewHeapArena@@YAIPAPAVnsIArena@@I@Z ; 139
+?QueryInterface@ArenaImpl@@UAGIABUnsID@@PAPAX@Z ; 139
+??1nsObjectHashtable@@UAE@XZ ; 138
+?Reset@nsObjectHashtable@@QAEXXZ ; 138
+?ResolveLocked@xptiInterfaceInfo@@AAEHPAVxptiWorkingSet@@@Z ; 129
+?GetNext@nsAdapterEnumerator@@UAGIPAPAVnsISupports@@@Z ; 129
+?GetCompleted@nsProxyObjectCallInfo@@QAEHXZ ; 124
+??0CBufDescriptor@@QAE@PBGHIH@Z ; 123
+??0nsServiceEntry@@QAE@ABUnsID@@PAVnsISupports@@@Z ; 122
+?NotifyListeners@nsServiceEntry@@QAEIXZ ; 122
+??1nsServiceEntry@@QAE@XZ ; 122
+?Resolve@xptiInterfaceInfo@@AAEHPAVxptiWorkingSet@@@Z ; 122
+??4nsFileSpec@@QAEXPBD@Z ; 121
+?QueryInterface@nsRegistryNode@@UAGIABUnsID@@PAPAX@Z ; 114
+?RegisterThreadSelf@nsThread@@QAEIXZ ; 114
+?FindSymbol@nsDll@@QAEPAXPBD@Z ; 114
+??_GnsRegistryNode@@UAEPAXI@Z ; 114
+??0nsThread@@QAE@XZ ; 114
+??0nsRegistryNode@@QAE@PAXPADJ@Z ; 114
+?CurrentItem@nsRegSubtreeEnumerator@@UAGIPAPAVnsISupports@@@Z ; 114
+??1nsRegistryNode@@UAE@XZ ; 114
+?Init@nsThread@@UAGIPAVnsIRunnable@@IW4PRThreadPriority@@W4PRThreadScope@@W4PRThreadState@@@Z ; 113
+?NS_NewThread@@YAIPAPAVnsIThread@@PAVnsIRunnable@@IW4PRThreadState@@W4PRThreadPriority@@W4PRThreadScope@@@Z ; 113
+?WaitUntilReadyToStartMain@nsThread@@QAEXXZ ; 113
+?Main@nsThread@@SAXPAX@Z ; 113
+??1ArenaImpl@@UAE@XZ ; 112
+??_GArenaImpl@@UAEPAXI@Z ; 112
+?GetKey@nsRegistryNode@@UAGIPAI@Z ; 112
+?Exit@nsThread@@SAXPAX@Z ; 111
+??1nsThread@@UAE@XZ ; 110
+?GetCurrent@nsIThread@@SAIPAPAV1@@Z ; 110
+??_GnsThread@@UAEPAXI@Z ; 110
+?WriteToLog@xptiInterfaceInfoManager@@SAXPBDZZ ; 110
+?GetIThread@nsIThread@@SAIPAUPRThread@@PAPAV1@@Z ; 110
+?Write@nsPipeOutputStream@nsPipe@@UAGIPBDIPAI@Z ; 109
+?AddThread@nsThreadPool@@IAEIXZ ; 109
+?Run@nsThreadPoolRunnable@@UAGIXZ ; 109
+??0nsThreadPoolRunnable@@QAE@PAVnsThreadPool@@@Z ; 109
+?DeleteLastElement@nsSupportsArray@@UAGIPAVnsISupports@@@Z ; 108
+??_GnsThreadPoolRunnable@@UAEPAXI@Z ; 108
+?RemoveLastElement@nsSupportsArray@@UAGHPBVnsISupports@@@Z ; 108
+?RemoveThread@nsThreadPool@@IAEIPAVnsIThread@@@Z ; 108
+??1nsThreadPoolRunnable@@UAE@XZ ; 108
+?GetNameUTF8@nsRegistryNode@@UAGIPAPAD@Z ; 108
+?RemoveObserver@nsObserverService@@UAGIPAVnsIObserver@@PBG@Z ; 106
+?RemoveObserver@nsObserverList@@UAGIPAVnsIObserver@@@Z ; 106
+?Contains@nsLocalFile@@UAGIPAVnsIFile@@HPAH@Z ; 104
+?RegistryLocationForSpec@nsComponentManagerImpl@@UAGIPAVnsIFile@@PAPAD@Z ; 104
+?Close@ConverterInputStream@@UAGIXZ ; 103
+??1nsDll@@QAE@XZ ; 103
+?Init@nsDll@@AAEXPAVnsIFile@@@Z ; 100
+??0nsDll@@QAE@PAVnsIFile@@PBDPA_J2@Z ; 100
+?SpecForRegistryLocation@nsComponentManagerImpl@@UAGIPBDPAPAVnsIFile@@@Z ; 100
+?UnescapeKey@nsRegistry@@UAGIPAEIPAIPAPAE@Z ; 99
+?GetRegistryDllInfo@nsNativeComponentLoader@@AAEIIPA_J0@Z ; 99
+NS_NewIOFileStream ; 98
+?Open@FileImpl@@UAGIABVnsFileSpec@@HH@Z ; 98
+??1FileImpl@@UAE@XZ ; 98
+??_GFileImpl@@UAEPAXI@Z ; 98
+??0FileImpl@@QAE@ABVnsFileSpec@@HH@Z ; 98
+?HasChanged@nsDll@@QAEHXZ ; 94
+?Read@nsByteArrayInputStream@@UAGIPADIPAI@Z ; 87
+PL_DHashGetStubOps ; 86
+??0nsStorageStream@@QAE@XZ ; 83
+?NS_NewStorageStream@@YAIIIPAPAVnsIStorageStream@@@Z ; 83
+??1nsStorageStream@@UAE@XZ ; 83
+?Init@nsStorageStream@@QAGIIIPAVnsIMemory@@@Z ; 83
+??_EnsStorageStream@@UAEPAXI@Z ; 83
+?GetOutputStream@nsStorageStream@@UAGIHPAPAVnsIOutputStream@@@Z ; 82
+?WriteBytes@nsBinaryOutputStream@@UAGIPBDI@Z ; 82
+??0nsBinaryOutputStream@@QAE@PAVnsIOutputStream@@@Z ; 81
+?Write16@nsBinaryOutputStream@@UAGIG@Z ; 81
+??1nsStorageInputStream@@UAE@XZ ; 81
+?Available@nsStorageInputStream@@UAGIPAI@Z ; 81
+?NewInputStream@nsStorageStream@@UAGIHPAPAVnsIInputStream@@@Z ; 81
+??_EnsStorageInputStream@@UAEPAXI@Z ; 81
+?WriteFloat@nsBinaryOutputStream@@UAGIM@Z ; 81
+?NS_NewBinaryOutputStream@@YAIPAPAVnsIBinaryOutputStream@@PAVnsIOutputStream@@@Z ; 81
+?Release@nsBinaryOutputStream@@UAGKXZ ; 81
+??_EnsBinaryOutputStream@@UAEPAXI@Z ; 81
+?Read@nsStorageInputStream@@UAGIPADIPAI@Z ; 81
+??0nsStorageInputStream@@QAE@PAVnsStorageStream@@I@Z ; 81
+??_EConverterInputStream@@UAEPAXI@Z ; 80
+??0ByteBufferImpl@@QAE@XZ ; 80
+?QueryInterface@nsSupportsPRInt32Impl@@UAGIABUnsID@@PAPAX@Z ; 80
+?NS_NewUnicharBuffer@@YAIPAPAVnsIUnicharBuffer@@PAVnsISupports@@I@Z ; 80
+?NS_NewB2UConverter@@YAIPAPAVnsIUnicodeDecoder@@PAVnsISupports@@PAVnsString@@@Z ; 80
+?QueryInterface@UnicharBufferImpl@@UAGIABUnsID@@PAPAX@Z ; 80
+??1ByteBufferImpl@@UAE@XZ ; 80
+?Init@UnicharBufferImpl@@UAGII@Z ; 80
+??0UnicharBufferImpl@@QAE@XZ ; 80
+?Create@UnicharBufferImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 80
+?NS_NewByteBuffer@@YAIPAPAVnsIByteBuffer@@PAVnsISupports@@I@Z ; 80
+?Init@ByteBufferImpl@@UAGII@Z ; 80
+?QueryInterface@ByteBufferImpl@@UAGIABUnsID@@PAPAX@Z ; 80
+??0ConverterInputStream@@QAE@PAVnsIInputStream@@PAVnsIUnicodeDecoder@@I@Z ; 80
+??1UnicharBufferImpl@@UAE@XZ ; 80
+??_EUnicharBufferImpl@@UAEPAXI@Z ; 80
+?NS_NewConverterStream@@YAIPAPAVnsIUnicharInputStream@@PAVnsISupports@@PAVnsIInputStream@@HPAVnsString@@@Z ; 80
+??_EByteBufferImpl@@UAEPAXI@Z ; 80
+??1ConverterInputStream@@UAE@XZ ; 80
+?Create@ByteBufferImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 80
+?is_open@nsFileClient@@QBEHXZ ; 79
+?GetData@nsSupportsPRBoolImpl@@UAGIPAH@Z ; 78
+??0nsSupportsPRInt32Impl@@QAE@XZ ; 77
+?SetNativePath@nsFileSpecImpl@@UAGIPBD@Z ; 74
+?InsertFromReadable@nsAString@@IAEXABV1@I@Z ; 74
+?ToString@nsSupportsStringImpl@@UAGIPAPAD@Z ; 74
+?IsDone@nsSupportsArrayEnumerator@@UAGIXZ ; 73
+?AllocateBuffers@FileImpl@@IAEIII@Z ; 71
+??1nsOutputStream@@UAE@XZ ; 71
+??_EnsSupportsPRInt32Impl@@UAEPAXI@Z ; 70
+??1nsOutputFileStream@@UAE@XZ ; 70
+?AssignFrom@nsOutputFileStream@@IAEXPAVnsISupports@@@Z ; 70
+??0nsRandomAccessOutputStream@@IAE@XZ ; 70
+??0nsOutputStream@@QAE@PAVnsIOutputStream@@@Z ; 70
+??1nsRandomAccessOutputStream@@UAE@XZ ; 70
+??1nsSupportsPRInt32Impl@@UAE@XZ ; 70
+??0nsDirectoryIterator@@QAE@ABVnsFileSpec@@H@Z ; 68
+??1nsDirectoryIterator@@UAE@XZ ; 68
+?Promises@nsPromiseCConcatenation@@UBEHABVnsACString@@@Z ; 67
+?Length@nsPromiseConcatenation@@UBEIXZ ; 67
+?AppendFromPromise@nsAString@@IAEXABV1@@Z ; 67
+?IndexOf@nsStringArray@@QBEHABVnsAString@@@Z ; 67
+??0nsOutputFileStream@@QAE@ABVnsFileSpec@@HH@Z ; 67
+?Available@nsInputStreamTee@@UAGIPAI@Z ; 66
+?HashContractID@nsComponentManagerImpl@@IAEIPBDABUnsID@@@Z ; 65
+??0nsSubsumeCStr@@QAE@PADHH@Z ; 65
+?close@nsInputStream@@QAEIXZ ; 65
+?HandleEvent@nsEventQueueImpl@@UAGIPAUPLEvent@@@Z ; 62
+?PostAndWait@nsProxyObject@@QAEIPAVnsProxyObjectCallInfo@@@Z ; 62
+?WaitForEvent@nsEventQueueImpl@@UAGIPAPAUPLEvent@@@Z ; 62
+?SetCallersQueue@nsProxyObjectCallInfo@@QAEXPAVnsIEventQueue@@@Z ; 62
+PL_PostSynchronousEvent ; 62
+?PostSynchronousEvent@nsEventQueueImpl@@UAGIPAUPLEvent@@PAPAX@Z ; 62
+PL_WaitForEvent ; 62
+?strcmp@nsCRT@@SAHPBGPBD@Z ; 60
+?ns_file_convert_result@@YAIH@Z ; 60
+?Load@nsLocalFile@@UAGIPAPAUPRLibrary@@@Z ; 54
+?hash_enumerator@@YAHPAVnsHashKey@@PAX1@Z ; 53
+?Shutdown@nsDll@@QAEIXZ ; 53
+??1nsAdapterEnumerator@@UAE@XZ ; 51
+?IsDone@nsHashtableEnumerator@@UAGIXZ ; 51
+?CurrentItem@nsHashtableEnumerator@@UAGIPAPAVnsISupports@@@Z ; 51
+?Next@nsHashtableEnumerator@@UAGIXZ ; 51
+??0nsAdapterEnumerator@@QAE@PAVnsIEnumerator@@@Z ; 51
+??HnsFileSpec@@QBE?AV0@PBD@Z ; 50
+?Read32@nsBinaryInputStream@@UAGIPAI@Z ; 50
+?Available@nsByteArrayInputStream@@UAGIPAI@Z ; 50
+?flush@nsOutputFileStream@@UAEIXZ ; 49
+?RegisterComponentCommon@nsComponentManagerImpl@@IAEIABUnsID@@PBD11HH1@Z ; 48
+??0nsString@@QAE@AAVnsSubsumeStr@@@Z ; 47
+??0nsSubsumeStr@@QAE@PAGHH@Z ; 47
+??0CBufDescriptor@@QAE@PBDHIH@Z ; 46
+?Initialize@nsGenericModule@@IAEIXZ ; 45
+??0nsGenericModule@@QAE@PBDIPAUnsModuleComponentInfo@@P6AXPAVnsIModule@@@Z@Z ; 45
+?CanUnload@nsGenericModule@@UAGIPAVnsIComponentManager@@PAH@Z ; 45
+?Shutdown@nsGenericModule@@IAEXXZ ; 45
+?NS_NewGenericModule@@YAIPBDIPAUnsModuleComponentInfo@@P6AXPAVnsIModule@@@ZPAPAV2@@Z ; 45
+?GetLoaderForType@nsComponentManagerImpl@@IAEIPBDPAPAVnsIComponentLoader@@@Z ; 45
+?QueryInterface@nsGenericModule@@UAGIABUnsID@@PAPAX@Z ; 45
+??_EnsGenericModule@@UAEPAXI@Z ; 45
+??1nsGenericModule@@UAE@XZ ; 45
+?OnRegister@nsNativeComponentLoader@@UAGIABUnsID@@PBD111HH@Z ; 44
+?GetLeafName@nsFileSpecImpl@@UAGIPAPAD@Z ; 44
+?QueryInterface@AtomImpl@@UAGIABUnsID@@PAPAX@Z ; 44
+?find_category@nsCategoryManager@@AAEPAVCategoryNode@@PBD@Z ; 44
+?RegistryNameForLib@nsComponentManagerImpl@@IAEIPBDPAPAD@Z ; 44
+?RegisterComponentLib@nsComponentManager@@SAIABUnsID@@PBD11HH@Z ; 44
+?RegisterComponentLib@nsComponentManagerImpl@@UAGIABUnsID@@PBD11HH@Z ; 44
+?RegisterFactory@nsComponentManagerImpl@@UAGIABUnsID@@PBD1PAVnsIFactory@@H@Z ; 42
+??0nsFactoryEntry@@QAE@ABUnsID@@PAVnsIFactory@@@Z ; 42
+?copy_string@@YAAAV?$ConvertToUpperCase@G@@AAV?$nsWritingIterator@G@@ABV2@AAV1@@Z ; 40
+?ResolveSymlink@nsFileSpec@@QAEIAAH@Z ; 40
+?ToUpperCase@@YAXAAVnsAString@@@Z ; 40
+?advance@nsRegValueEnumerator@@UAGIXZ ; 39
+?Release@nsPersistentProperties@@UAGKXZ ; 39
+?ToNewString@nsString@@QBEPAV1@XZ ; 38
+?IsValid@xptiWorkingSet@@QBEHXZ ; 38
+?GetComponentsDir@xptiInterfaceInfoManager@@QAEHPAPAVnsILocalFile@@@Z ; 37
+??1xptiTypelibGuts@@QAE@XZ ; 36
+??0xptiTypelibGuts@@QAE@PAUXPTHeader@@@Z ; 36
+?LoadFile@xptiInterfaceInfoManager@@QAEHABVxptiTypelib@@PAVxptiWorkingSet@@@Z ; 36
+?SetHeader@xptiFile@@QAEHPAUXPTHeader@@@Z ; 36
+?ReadXPTFile@xptiInterfaceInfoManager@@AAEPAUXPTHeader@@PAVnsILocalFile@@PAVxptiWorkingSet@@@Z ; 36
+?ConvertBreaks@@YAPAGPBGAAHPBD2@Z ; 35
+?ConvertUnicharLineBreaksInSitu@nsLinebreakConverter@@SAIPAPAGW4ELinebreakType@1@1HPAH@Z ; 35
+?CountLinebreaks@@YAHPBGHPBD@Z ; 35
+?FindFactory@nsComponentManager@@SAIABUnsID@@PAPAVnsIFactory@@@Z ; 34
+??1nsRegistryValue@@UAE@XZ ; 32
+??_GnsRegistryValue@@UAEPAXI@Z ; 32
+?getInfo@nsRegistryValue@@IAEIXZ ; 32
+?find_leaf@CategoryNode@@QAEPAVnsCString@@PBD@Z ; 32
+??0nsRegistryValue@@QAE@PAXJK@Z ; 32
+?QueryInterface@nsRegistryValue@@UAGIABUnsID@@PAPAX@Z ; 32
+?GetNameUTF8@nsRegistryValue@@UAGIPAPAD@Z ; 32
+?AddCategoryEntry@nsCategoryManager@@UAGIPBD00HHPAPAD@Z ; 32
+?CurrentItem@nsRegValueEnumerator@@UAGIPAPAVnsISupports@@@Z ; 32
+??1nsInputFileStream@@UAE@XZ ; 29
+??YnsFileSpec@@QAEXABVnsString@@@Z ; 29
+?Release@nsAppFileLocationProvider@@UAGKXZ ; 29
+??0nsInputStream@@QAE@PAVnsIInputStream@@@Z ; 29
+??1nsRandomAccessInputStream@@UAE@XZ ; 29
+??1nsInputStream@@UAE@XZ ; 29
+?IsLowMemory@nsMemoryImpl@@UAGIPAH@Z ; 29
+??8nsFileSpec@@QBEHABV0@@Z ; 28
+?QueryInterface@nsAppFileLocationProvider@@UAGIABUnsID@@PAPAX@Z ; 27
+?copy_string@@YAAAV?$CalculateLength@D@@AAV?$nsReadingIterator@D@@ABV2@AAV1@@Z ; 26
+?Distance@@YAIABV?$nsReadingIterator@D@@0@Z ; 26
+?GetFile@nsAppFileLocationProvider@@UAGIPBDPAHPAPAVnsIFile@@@Z ; 26
+?nsLocalFileConstructor@nsLocalFile@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 26
+?GetFactoryFromNSGetFactory@nsNativeComponentLoader@@AAEIPAVnsDll@@ABUnsID@@PAVnsIServiceManager@@PAPAVnsIFactory@@@Z ; 25
+?Release@nsRegistry@@UAGKXZ ; 25
+?First@nsRegSubtreeEnumerator@@UAGIXZ ; 24
+??1nsRegSubtreeEnumerator@@UAE@XZ ; 24
+??0nsRegSubtreeEnumerator@@QAE@PAXJH@Z ; 24
+?Set@nsDirectoryService@@UAGIPBDPAVnsISupports@@@Z ; 24
+??_GnsRegSubtreeEnumerator@@UAEPAXI@Z ; 24
+??0nsPersistentProperties@@QAE@XZ ; 23
+?Load@nsPersistentProperties@@UAGIPAVnsIInputStream@@@Z ; 23
+?Create@nsPersistentProperties@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 23
+?QueryInterface@nsPersistentProperties@@UAGIABUnsID@@PAPAX@Z ; 23
+??1nsFileURL@@UAE@XZ ; 20
+?SetPersistentDescriptor@nsLocalFile@@UAGIPBD@Z ; 20
+?Close@BasicStringImpl@@UAGIXZ ; 20
+??4nsFileURL@@QAEXABVnsFilePath@@@Z ; 20
+?ReplaceElementAt@nsSupportsArray@@UAGHPAVnsISupports@@I@Z ; 20
+?NS_AllocateContiguousHandleWithData@@YAPAVBuffer@nsSharedBufferList@@PBV12@ABVnsLocalString@@I@Z ; 20
+?QueryInterface@nsRegistry@@UAGIABUnsID@@PAPAX@Z ; 19
+?SetCharAt@nsCString@@QAEHGI@Z ; 19
+??0nsSpecialSystemDirectory@@QAE@W4SystemDirectories@0@@Z ; 18
+?GetFileSize@nsFileSpec@@QBEIXZ ; 18
+?Exists@nsFileSpecImpl@@UAGIPAH@Z ; 18
+?GetSubtree@nsRegistry@@UAGIIPBDPAI@Z ; 18
+??4nsSpecialSystemDirectory@@QAEXW4SystemDirectories@0@@Z ; 18
+??1nsSpecialSystemDirectory@@UAE@XZ ; 18
+??0nsRandomAccessInputStream@@IAE@XZ ; 17
+??0nsObserverList@@QAE@XZ ; 17
+??1nsObserverList@@UAE@XZ ; 17
+?EnumerateSubtrees@nsRegistry@@UAGIIPAPAVnsIEnumerator@@@Z ; 17
+?NS_NewObserverList@@YAIPAPAVnsIObserverList@@@Z ; 17
+?AssignFrom@nsInputFileStream@@IAEXPAVnsISupports@@@Z ; 17
+??0nsInputFileStream@@QAE@ABVnsFileSpec@@HH@Z ; 17
+?QueryInterface@nsObserverList@@UAGIABUnsID@@PAPAX@Z ; 17
+??_GnsObserverList@@UAEPAXI@Z ; 17
+?Unescape@nsSimpleCharString@@QAEXXZ ; 16
+?SetCharAt@nsString@@QAEHGI@Z ; 16
+??1nsOpaqueKey@@UAE@XZ ; 16
+??1nsPersistentProperties@@UAE@XZ ; 16
+??_EnsPersistentProperties@@UAEPAXI@Z ; 16
+??0nsFilePath@@QAE@PBDH@Z ; 16
+??0nsOpaqueKey@@QAE@PBDIW4Ownership@0@@Z ; 16
+?AppendRelativeUnixPath@nsFileSpecImpl@@UAGIPBD@Z ; 15
+??0nsCString@@QAE@PBDH@Z ; 15
+?GetString@nsRegistry@@UAGIIPBGPAPAG@Z ; 15
+?SetStringUTF8@nsRegistry@@UAGIIPBD0@Z ; 15
+?SetString@nsRegistry@@UAGIIPBG0@Z ; 15
+?ReleaseElements@nsHashtableEnumerator@@EAGIXZ ; 14
+PL_GetEventQueueMonitor ; 14
+?ReadStringZ@nsBinaryInputStream@@UAGIPAPAD@Z ; 14
+?EscapeKey@nsRegistry@@UAGIPAEIPAIPAPAE@Z ; 14
+?AppendFromPromise@nsACString@@IAEXABV1@@Z ; 13
+?FindCharInReadable@@YAHDAAV?$nsReadingIterator@D@@ABV1@@Z ; 13
+??0nsPromiseCSubstring@@QAE@ABV?$nsReadingIterator@D@@0@Z ; 13
+?GetName@xptiInterfaceInfo@@UAGIPAPAD@Z ; 12
+?StartAssignmentByReference@nsXPIDLCString@@AAEPAPBDXZ ; 12
+??0nsFileURL@@QAE@ABVnsFileSpec@@@Z ; 12
+?ConvertFromFileSystemCharset@nsFileSpec@@IAEPAGPBD@Z ; 12
+?Read8@nsBinaryInputStream@@UAGIPAE@Z ; 12
+?IsHidden@nsLocalFile@@UAGIPAH@Z ; 12
+?BufferHashCode@nsCRT@@SAIPBDI@Z ; 12
+?GetFileSystemCharset@nsFileSpec@@KAXAAVnsString@@@Z ; 12
+??0nsRandomAccessStoreClient@@QAE@ABV?$nsCOMPtr@VnsIRandomAccessStore@@@@@Z ; 12
+??0nsFileClient@@QAE@ABV?$nsCOMPtr@VnsIOpenFile@@@@@Z ; 12
+?SetLongLong@nsRegistry@@UAGIIPBDPA_J@Z ; 12
+??0nsInputFileStream@@QAE@PAVnsIInputStream@@@Z ; 12
+?HashCode@nsOpaqueKey@@UBEIXZ ; 12
+??0nsRandomAccessInputStream@@QAE@PAVnsIInputStream@@@Z ; 12
+??4nsFileURL@@QAEXABVnsFileSpec@@@Z ; 12
+?AddRef@nsCategoryManager@@UAGKXZ ; 11
+?Release@nsCategoryManager@@UAGKXZ ; 11
+?GetFile@nsDirectoryService@@UAGIPBDPAHPAPAVnsIFile@@@Z ; 11
+??0nsProxyEventClass@@IAE@ABUnsID@@PAVnsIInterfaceInfo@@@Z ; 11
+?Read@nsFileSpecImpl@@UAGIPAPADHPAH@Z ; 11
+?InsertReadable@nsSlidingString@@IAEXABVnsAString@@ABV?$nsReadingIterator@G@@@Z ; 10
+NS_NewTypicalInputFileStream ; 10
+??1nsCommonCString@@UAE@XZ ; 10
+?SplitBuffer@nsSharedBufferList@@QAEXABUPosition@1@W4SplitDisposition@1@@Z ; 10
+?OpenStreamForReading@nsFileSpecImpl@@UAGIXZ ; 10
+PL_IsQueueNative ; 10
+?Release@nsRegistryFactory@@UAGKXZ ; 10
+??0ConstStringImpl@@QAE@ABVnsCString@@@Z ; 10
+?ResolveSymlink@nsFileSpecImpl@@UAGIXZ ; 10
+?IsQueueNative@nsEventQueueImpl@@UAGIPAH@Z ; 10
+??1nsACString@@UAE@XZ ; 10
+?Clone@nsVoidKey@@UBEPAVnsHashKey@@XZ ; 10
+NS_NewCStringInputStream ; 10
+?QueryInterface@nsRegSubtreeEnumerator@@UAGIABUnsID@@PAPAX@Z ; 9
+?GetFileSize@nsFileSpecImpl@@UAGIPAI@Z ; 9
+?GetTypeForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@GPAVnsXPTType@@@Z ; 9
+?Exists@nsDirectoryIteratorImpl@@UAGIPAH@Z ; 9
+?do_InsertFromElement@nsAString@@MAEXGI@Z ; 9
+?Create@nsDirectoryService@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 9
+?QueryInterface@nsCategoryManager@@UAGIABUnsID@@PAPAX@Z ; 9
+?GetFileContents@nsFileSpecImpl@@UAGIPAPAD@Z ; 9
+?GetTypeInArray@xptiInterfaceInfo@@EAGIPBVnsXPTParamInfo@@GPAPBUXPTTypeDescriptor@@@Z ; 9
+?IsOpen@nsRegistry@@UAGIPAH@Z ; 9
+?set_at_eof@nsRandomAccessStoreClient@@MAEXH@Z ; 8
+??0nsFilePath@@QAE@ABVnsFileURL@@@Z ; 8
+?GetLengthIsArgNumberForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@GPAE@Z ; 8
+?SetAtEOF@FileImpl@@UAGIH@Z ; 8
+?GetSubtreeRaw@nsRegistry@@UAGIIPBDPAI@Z ; 8
+?Delete@nsFileSpec@@QBEXH@Z ; 8
+??_EnsDirEnumerator@@UAEPAXI@Z ; 8
+??_EnsHashtable@@UAEPAXI@Z ; 8
+?ReadBytes@nsBinaryInputStream@@UAGIPAPADI@Z ; 8
+?Next@nsDirectoryIteratorImpl@@UAGIXZ ; 8
+?GetDirectoryEntries@nsLocalFile@@UAGIPAPAVnsISimpleEnumerator@@@Z ; 8
+??0nsFileURL@@QAE@PBDH@Z ; 8
+?EnumerateCategory@nsCategoryManager@@UAGIPBDPAPAVnsISimpleEnumerator@@@Z ; 8
+??0nsDirEnumerator@@QAE@XZ ; 8
+?Put@nsInt2StrHashtable@@QAEIIPBD@Z ; 8
+??0nsFileSpec@@QAE@ABVnsFileURL@@@Z ; 8
+?GetCurrentSpec@nsDirectoryIteratorImpl@@UAGIPAPAVnsIFileSpec@@@Z ; 8
+?Init@nsDirEnumerator@@QAEIPAVnsILocalFile@@@Z ; 8
+??1nsDirEnumerator@@UAE@XZ ; 8
+?MakeAllDirectories@nsFileSpecHelpers@@YAXPBDH@Z ; 8
+?NotifyObservers@nsEventQueueImpl@@AAEXPBD@Z ; 8
+?Reset@nsHashtableEnumerator@@EAGIPAVnsHashtable@@P6GIPAVnsHashKey@@PAX2PAPAVnsISupports@@@Z2@Z ; 7
+NS_NewHashtableEnumerator ; 7
+?GetLeafName@nsFileSpec@@QAEXAAVnsString@@@Z ; 7
+??1nsHashtableEnumerator@@UAE@XZ ; 7
+??0CategoryNode@@QAE@XZ ; 7
+?IsASCII@nsString@@QAEHPBG@Z ; 7
+NS_NewAdapterEnumerator ; 7
+??0nsRegValueEnumerator@@QAE@PAXJ@Z ; 7
+??1nsProxyEventClass@@MAE@XZ ; 7
+?Realloc@nsMemoryImpl@@UAGPAXPAXI@Z ; 7
+?EnterMonitor@nsEventQueueImpl@@UAGIXZ ; 7
+??_EnsHashtableEnumerator@@UAEPAXI@Z ; 7
+?First@nsHashtableEnumerator@@UAGIXZ ; 7
+?RegisterErrorStringBundleKey@nsErrorService@@UAGIIPBD@Z ; 7
+?EnumerateValues@nsRegistry@@UAGIIPAPAVnsIEnumerator@@@Z ; 7
+?GetSizeIsArgNumberForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@GPAE@Z ; 7
+??0nsHashtableEnumerator@@QAE@PAVnsHashtable@@P6GIPAVnsHashKey@@PAX2PAPAVnsISupports@@@Z2@Z ; 7
+??_EnsAdapterEnumerator@@UAEPAXI@Z ; 7
+?Release@nsComponentManagerImpl@@UAGKXZ ; 7
+??_GCategoryNode@@UAEPAXI@Z ; 7
+?Delete@nsLocalFile@@UAGIH@Z ; 7
+??_GnsProxyEventClass@@MAEPAXI@Z ; 7
+?ExitMonitor@nsEventQueueImpl@@UAGIXZ ; 7
+??0nsBinaryInputStream@@QAE@PAVnsIInputStream@@@Z ; 6
+?OpenWellKnownRegistry@nsRegistry@@UAGIH@Z ; 6
+??0nsStaticCaseInsensitiveNameTable@@QAE@XZ ; 6
+??0nsXPIDLString@@QAE@XZ ; 6
+?NS_NewBinaryInputStream@@YAIPAPAVnsIBinaryInputStream@@PAVnsIInputStream@@@Z ; 6
+?SetYounger@nsEventQueueImpl@@UAGIPAVnsPIEventQueueChain@@@Z ; 6
+?MakeUnique@nsFileSpec@@QAEXXZ ; 6
+?Release@nsBinaryInputStream@@UAGKXZ ; 6
+??_GnsBinaryInputStream@@UAEPAXI@Z ; 6
+?ConvertUnknownBreaks@@YAPADPBDAAH0@Z ; 6
+?Read16@nsBinaryInputStream@@UAGIPAG@Z ; 6
+?AddSubtreeRaw@nsRegistry@@UAGIIPBDPAI@Z ; 6
+?Init@nsStaticCaseInsensitiveNameTable@@QAEHQAPBDH@Z ; 6
+?IsFile@nsFileSpec@@QBEHXZ ; 6
+??0nsFileSpec@@QAE@ABVnsString@@H@Z ; 6
+?ConvertLineBreaks@nsLinebreakConverter@@SAPADPBDW4ELinebreakType@1@1HPAH@Z ; 6
+NS_NewByteInputStream ; 6
+?ReadFloat@nsBinaryInputStream@@UAGIPAM@Z ; 6
+?Realloc@nsMemory@@SAPAXPAXI@Z ; 6
+??1nsStaticCaseInsensitiveNameTable@@QAE@XZ ; 6
+?GetLength@nsStorageStream@@UAGIPAI@Z ; 6
+??_GnsRegistry@@UAEPAXI@Z ; 5
+??_EnsObjectHashtable@@UAEPAXI@Z ; 5
+?CloneMozBinDirectory@nsAppFileLocationProvider@@IAGIPAPAVnsILocalFile@@@Z ; 5
+?StripWhitespace@nsCString@@QAEXXZ ; 5
+??0nsRegistry@@QAE@XZ ; 5
+?MakeNewQueue@nsEventQueueServiceImpl@@EAGIPAUPRThread@@HPAPAVnsIEventQueue@@@Z ; 5
+?StopAcceptingEvents@nsEventQueueImpl@@UAGIXZ ; 5
+??1nsRegistry@@UAE@XZ ; 5
+?Create@nsEventQueueImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 5
+?Close@nsRegistry@@MAGIXZ ; 5
+?CreateInstance@nsRegistryFactory@@UAGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 5
+?InitFromPRThread@nsEventQueueImpl@@UAGIPAUPRThread@@H@Z ; 5
+??4nsFileSpec@@QAEXABVnsString@@@Z ; 5
+?NS_FileSpecToIFile@@YAIPAVnsFileSpec@@PAPAVnsILocalFile@@@Z ; 5
+?QueryInterface@nsComponentManagerImpl@@UAGIABUnsID@@PAPAX@Z ; 5
+?GetNativePathString@nsFileSpec@@QAEXAAVnsString@@@Z ; 5
+??0nsEventQueueImpl@@QAE@XZ ; 5
+?do_GetService@@YA?BVnsGetServiceByContractID@@PBDPAI@Z ; 5
+PL_EventAvailable ; 4
+?RFind@nsString@@QBEHABV1@HHH@Z ; 4
+?RegisterComponentSpec@nsComponentManagerImpl@@UAGIABUnsID@@PBD1PAVnsIFile@@HH@Z ; 4
+?FSToNewUCS@nsFSStringConversion@@SAIPBDPAPAG@Z ; 4
+?GetCategoryEntry@nsCategoryManager@@UAGIPBD0PAPAD@Z ; 4
+?RegisterComponentWithType@nsComponentManagerImpl@@UAGIABUnsID@@PBD1PAVnsIFile@@1HH1@Z ; 4
+PL_CreateNativeEventQueue ; 4
+?RemoveStringAt@nsStringArray@@QAEHH@Z ; 4
+?PrepareDecoder@nsFSStringConversion@@CAIXZ ; 4
+?GetName@nsRegistryNode@@UAGIPAPAG@Z ; 4
+?Clone@nsOpaqueKey@@UBEPAVnsHashKey@@XZ ; 4
+?SetBufferSize@nsRegistry@@QAEHH@Z ; 4
+?GetCategoryEntryRaw@nsCategoryManager@@UAGIPBD0PAPAD@Z ; 4
+?AddSubtree@nsRegistry@@UAGIIPBDPAI@Z ; 4
+??_EnsOpaqueKey@@UAEPAXI@Z ; 4
+?GetOutputStream@nsFileSpecImpl@@UAGIPAPAVnsIOutputStream@@@Z ; 3
+NS_NewTypicalOutputFileStream ; 3
+?PushThreadEventQueue@nsEventQueueServiceImpl@@UAGIPAPAVnsIEventQueue@@@Z ; 3
+?QueryInterface@nsConsoleService@@UAGIABUnsID@@PAPAX@Z ; 3
+?PopThreadEventQueue@nsEventQueueServiceImpl@@UAGIPAVnsIEventQueue@@@Z ; 3
+PL_MapEvents ; 3
+?Unlink@nsEventQueueImpl@@UAGIXZ ; 3
+?SetElder@nsEventQueueImpl@@UAGIPAVnsPIEventQueueChain@@@Z ; 3
+?AppendQueue@nsEventQueueImpl@@UAGIPAVnsIEventQueue@@@Z ; 3
+??1nsEventQueueImpl@@UAE@XZ ; 3
+?OpenStreamForWriting@nsFileSpecImpl@@UAGIXZ ; 3
+??0nsOutputFileStream@@QAE@PAVnsIFileSpec@@@Z ; 3
+?LogMessage@nsConsoleService@@UAGIPAVnsIConsoleMessage@@@Z ; 3
+PL_DestroyEventQueue ; 3
+?IsRegistered@nsComponentManagerImpl@@UAGIABUnsID@@PAH@Z ; 3
+?GetCurrentProcessDirectory@nsDirectoryService@@AAEIPAPAVnsILocalFile@@@Z ; 3
+??_EnsEventQueueImpl@@UAEPAXI@Z ; 3
+?CreateDirectory@nsFileSpec@@QAEXH@Z ; 3
+??0nsDll@@QAE@PBDH@Z ; 3
+??1nsAVLTree@@QAE@XZ ; 2
+?NewFileArray@xptiWorkingSet@@QAEHI@Z ; 2
+?ToUpper@nsCRT@@SADD@Z ; 2
+??1nsInt2StrHashtable@@UAE@XZ ; 2
+?GetUnicodeLeafName@nsLocalFile@@UAGIPAPAG@Z ; 2
+?CompareWithConversion@nsString@@QBEHABV1@HH@Z ; 2
+?Read@xptiManifest@@SAHPAVxptiInterfaceInfoManager@@PAVxptiWorkingSet@@@Z ; 2
+??0nsMemoryImpl@@QAE@XZ ; 2
+??1xptiWorkingSet@@QAE@XZ ; 2
+?Create@nsMemoryImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 2
+??0nsRegistryFactory@@QAE@XZ ; 2
+?NS_ErrorAccordingToNSPR@@YAIXZ ; 2
+?ClearHashTables@xptiWorkingSet@@QAEXXZ ; 2
+??_ExptiFile@@QAEPAXI@Z ; 2
+?AppendUnicode@nsLocalFile@@UAGIPBG@Z ; 2
+?Release@MemoryFlusher@@UAGKXZ ; 2
+??_EnsSupportsHashtable@@UAEPAXI@Z ; 2
+?CreateEventQueue@nsEventQueueServiceImpl@@EAGIPAUPRThread@@H@Z ; 2
+??1xptiAutoLog@@QAE@XZ ; 2
+NS_RegistryGetFactory ; 2
+?ClearFiles@xptiWorkingSet@@QAEXXZ ; 2
+??0xptiWorkingSet@@QAE@XZ ; 2
+?Tell@FileImpl@@UAGIPAH@Z ; 2
+?RegisterProvider@nsDirectoryService@@UAGIPAVnsIDirectoryServiceProvider@@@Z ; 2
+?GetKey@nsRegistry@@UAGIIPBGPAI@Z ; 2
+?ClearZipItems@xptiWorkingSet@@QAEXXZ ; 2
+?readline@nsRandomAccessInputStream@@QAEHPADH@Z ; 2
+??0nsAVLTree@@QAE@AAVnsAVLNodeComparitor@@PAVnsAVLNodeFunctor@@@Z ; 2
+?GetManifestDir@xptiInterfaceInfoManager@@QAEHPAPAVnsILocalFile@@@Z ; 2
+??0xptiAutoLog@@QAE@PAVxptiInterfaceInfoManager@@PAVnsILocalFile@@H@Z ; 2
+?tell@nsRandomAccessStoreClient@@QAEHXZ ; 2
+NS_NewUnicodeLocalFile ; 2
+??0nsInt2StrHashtable@@QAE@XZ ; 2
+?seek@nsRandomAccessStoreClient@@QAEXW4PRSeekWhence@@H@Z ; 2
+?Open@nsRegistry@@UAGIPBD@Z ; 2
+?QueryInterface@nsErrorService@@UAGIABUnsID@@PAPAX@Z ; 2
+?RegisterService@nsServiceManagerImpl@@UAGIABUnsID@@PAVnsISupports@@@Z ; 2
+?Seek@FileImpl@@UAGIW4PRSeekWhence@@H@Z ; 2
+?GetUnicodePath@nsLocalFile@@UAGIPAPAG@Z ; 2
+?AddRef@MemoryFlusher@@UAGKXZ ; 2
+?PrepareFSCharset@nsFSStringConversion@@CAIXZ ; 2
+??_EnsDirectoryService@@UAEPAXI@Z ; 1
+?NS_ShutdownXPCOM@@YAIPAVnsIServiceManager@@@Z ; 1
+?AutoRegister@nsComponentManagerImpl@@UAGIHPAVnsIFile@@@Z ; 1
+?OnShutdown@HandleCaseConversionShutdown3@@UAGIABUnsID@@PAVnsISupports@@@Z ; 1
+?GetParent@nsFileSpec@@QBEXAAV1@@Z ; 1
+??1nsConsoleService@@UAE@XZ ; 1
+??0nsComponentManagerImpl@@QAE@XZ ; 1
+?PlatformVersionCheck@nsComponentManagerImpl@@IAEIPAI@Z ; 1
+?PlatformInit@nsComponentManagerImpl@@IAEIXZ ; 1
+??_EnsAppFileLocationProvider@@MAEPAXI@Z ; 1
+??_EnsVoidArray@@UAEPAXI@Z ; 1
+??RnsGetServiceFromCategory@@UBEIABUnsID@@PAPAX@Z ; 1
+??0nsIOFileStream@@QAE@ABVnsFileSpec@@HH@Z ; 1
+?NS_PurgeAtomTable@@YAXXZ ; 1
+??0nsProxyObjectManager@@QAE@XZ ; 1
+?NS_NewThreadPool@@YAIPAPAVnsIThreadPool@@IIIW4PRThreadPriority@@W4PRThreadScope@@@Z ; 1
+?GetNext@EmptyEnumeratorImpl@@UAGIPAPAVnsISupports@@@Z ; 1
+??_GxptiInterfaceInfoManager@@UAEPAXI@Z ; 1
+?ReallocLastSegment@nsSegmentedBuffer@@QAEHI@Z ; 1
+??0nsNativeComponentLoader@@QAE@XZ ; 1
+?Init@nsComponentManagerImpl@@QAEIXZ ; 1
+?CreateMonitoredThreadEventQueue@nsEventQueueServiceImpl@@UAGIXZ ; 1
+?UnloadLibraries@nsComponentManagerImpl@@IAEIPAVnsIServiceManager@@H@Z ; 1
+?Run@MemoryFlusher@@UAGIXZ ; 1
+??1nsDirectoryService@@UAE@XZ ; 1
+?SetRegistryDllInfo@nsNativeComponentLoader@@AAEIPBDPA_J1@Z ; 1
+??1nsDirectoryIteratorImpl@@UAE@XZ ; 1
+?DestroyThreadEventQueue@nsEventQueueServiceImpl@@UAGIXZ ; 1
+?GetInt@nsRegistry@@UAGIIPBDPAH@Z ; 1
+??0MemoryFlusher@@IAE@PAVnsMemoryImpl@@@Z ; 1
+?EnumerateBackwards@nsCStringArray@@QAEHP6AHAAVnsCString@@PAX@Z1@Z ; 1
+?GetParent@nsFileSpecImpl@@UAGIPAPAVnsIFileSpec@@@Z ; 1
+?BuildFileList@xptiInterfaceInfoManager@@AAEHPAPAVnsISupportsArray@@@Z ; 1
+??1nsServiceManagerImpl@@MAE@XZ ; 1
+??1nsObserverService@@UAE@XZ ; 1
+?GetRegistryDllInfo@nsNativeComponentLoader@@AAEIPBDPA_J1@Z ; 1
+?Shutdown@nsMemoryImpl@@SAIXZ ; 1
+NS_CategoryManagerGetFactory ; 1
+?Create@nsProxyObjectManager@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??_EnsDirectoryIteratorImpl@@UAEPAXI@Z ; 1
+??1nsAppFileLocationProvider@@MAE@XZ ; 1
+?GetProductDirectory@nsAppFileLocationProvider@@IAGIPAPAVnsILocalFile@@@Z ; 1
+??0?$nsCOMPtr@VnsIServiceManager@@@@QAE@ABVnsCOMPtr_helper@@@Z ; 1
+??_EnsNativeComponentLoader@@UAEPAXI@Z ; 1
+?Create@nsObserverService@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??0nsCategoryManager@@AAE@XZ ; 1
+??1nsIOFileStream@@UAE@XZ ; 1
+??1nsCategoryManager@@UAE@XZ ; 1
+?InvalidateInterfaceInfos@xptiWorkingSet@@QAEXXZ ; 1
+?PlatformPrePopulateRegistry@nsComponentManagerImpl@@QAEIXZ ; 1
+?NS_InitXPCOM2@@YAIPAPAVnsIServiceManager@@PAVnsIFile@@PAVnsIDirectoryServiceProvider@@@Z ; 1
+??_EnsDirectoryIterator@@UAEPAXI@Z ; 1
+?IsValid@xptiInterfaceInfoManager@@AAEHXZ ; 1
+?Shutdown@xptiZipLoader@@SAXXZ ; 1
+?Init@nsDirectoryService@@UAGIXZ ; 1
+?Create@nsErrorService@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+?RegisterDeferredComponents@nsNativeComponentLoader@@UAGIHPAH@Z ; 1
+?Shutdown@nsComponentManagerImpl@@QAEIXZ ; 1
+?Shutdown@nsThread@@SAXXZ ; 1
+?Sync@nsDll@@QAEIXZ ; 1
+?Startup@nsMemoryImpl@@SAIXZ ; 1
+?Define@nsDirectoryService@@UAGIPBDPAVnsISupports@@@Z ; 1
+?SetMainThread@nsIThread@@SAIXZ ; 1
+?ShutdownSpecialSystemDirectory@@YAXXZ ; 1
+?Init@nsNativeComponentLoader@@UAGIPAVnsIComponentManager@@PAVnsISupports@@@Z ; 1
+??0nsCategoryManagerFactory@@QAE@XZ ; 1
+?RegisterErrorStringBundle@nsErrorService@@UAGIFPBD@Z ; 1
+??0nsDirectoryService@@QAE@XZ ; 1
+?RegisterFactory@nsComponentManager@@SAIABUnsID@@PBD1PAVnsIFactory@@H@Z ; 1
+?AutoRegisterImpl@nsComponentManagerImpl@@AAEIHPAVnsIFile@@@Z ; 1
+?DetermineAutoRegStrategy@xptiInterfaceInfoManager@@AAE?AW4AutoRegMode@1@PAVnsISupportsArray@@PAVxptiWorkingSet@@@Z ; 1
+??0nsAppFileLocationProvider@@QAE@XZ ; 1
+??1MemoryFlusher@@MAE@XZ ; 1
+?Create@nsLocalFile@@UAGIII@Z ; 1
+?Join@nsThread@@UAGIXZ ; 1
+??_GnsProxyObjectManager@@UAEPAXI@Z ; 1
+?LogStats@xptiInterfaceInfoManager@@AAEXXZ ; 1
+?Valid@nsFileSpec@@QBEHXZ ; 1
+?NS_InitXPCOM@@YAIPAPAVnsIServiceManager@@PAVnsIFile@@@Z ; 1
+?ShutdownGlobalServiceManager@nsServiceManager@@SAIPAPAVnsIServiceManager@@@Z ; 1
+??1xptiInterfaceInfoManager@@UAE@XZ ; 1
+??_GnsComponentManagerImpl@@UAEPAXI@Z ; 1
+?FreeInterfaceInfoManager@xptiInterfaceInfoManager@@SAXXZ ; 1
+?Create@MemoryFlusher@@SAIPAPAV1@PAVnsMemoryImpl@@@Z ; 1
+??_EnsErrorService@@UAEPAXI@Z ; 1
+??1nsProxyObjectManager@@UAE@XZ ; 1
+??0nsConsoleService@@QAE@XZ ; 1
+?AutoRegisterComponents@nsNativeComponentLoader@@UAGIHPAVnsIFile@@@Z ; 1
+?AutoRegister@nsComponentManager@@SAIHPAVnsIFile@@@Z ; 1
+?QueryInterface@nsDirectoryIteratorImpl@@UAGIABUnsID@@PAPAX@Z ; 1
+??_EMemoryFlusher@@MAEPAXI@Z ; 1
+?initialize@nsCategoryManager@@AAEIXZ ; 1
+?AutoRegisterInterfaces@xptiInterfaceInfoManager@@UAGIXZ ; 1
+PL_CreateMonitoredEventQueue ; 1
+??_GnsCategoryManager@@UAEPAXI@Z ; 1
+?Close@nsStorageStream@@UAGIXZ ; 1
+?Init@nsThreadPool@@UAGIIIIW4PRThreadPriority@@W4PRThreadScope@@@Z ; 1
+??0nsObserverService@@QAE@XZ ; 1
+?Create@nsEventQueueServiceImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??0xptiInterfaceInfoManager@@AAE@XZ ; 1
+?GetDllSpec@nsDll@@QAEIPAPAVnsIFile@@@Z ; 1
+??_EnsServiceManagerImpl@@MAEPAXI@Z ; 1
+?SelfRegisterDll@nsNativeComponentLoader@@AAEIPAVnsDll@@PBDH@Z ; 1
+?UnloadAll@nsNativeComponentLoader@@UAGIH@Z ; 1
+??0?$nsCOMPtr@VnsIOutputStream@@@@QAE@ABVnsCOMPtr_helper@@@Z ; 1
+?Undefine@nsDirectoryService@@UAGIPBD@Z ; 1
+??0nsDirectoryIteratorImpl@@QAE@XZ ; 1
+??0CCaseConversionServiceInitializer@@QAE@XZ ; 1
+??1nsComponentManagerImpl@@UAE@XZ ; 1
+?RegisterComponentsInDir@nsNativeComponentLoader@@MAGIHPAVnsIFile@@@Z ; 1
+??0nsEventQueueServiceImpl@@QAE@XZ ; 1
+?CreateInstance@nsCategoryManagerFactory@@UAGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??_GnsObserverService@@UAEPAXI@Z ; 1
+XPTI_FreeInterfaceInfoManager ; 1
+?Stop@MemoryFlusher@@QAEIXZ ; 1
+?CreateThreadEventQueue@nsEventQueueServiceImpl@@UAGIXZ ; 1
+??0nsServiceManagerImpl@@QAE@XZ ; 1
+??1nsNativeComponentLoader@@UAE@XZ ; 1
+??0nsThreadPool@@QAE@XZ ; 1
+?NS_ShutdownLocalFile@@YAXXZ ; 1
+??_GHandleCaseConversionShutdown3@@UAEPAXI@Z ; 1
+?Init@nsDirectoryIteratorImpl@@UAGIPAVnsIFileSpec@@H@Z ; 1
+??0nsErrorService@@QAE@XZ ; 1
+??_EnsConsoleService@@UAEPAXI@Z ; 1
+??0nsSlidingSubstring@@QAE@ABVnsAString@@@Z ; 1
+?CleanUp@nsFSStringConversion@@SAXXZ ; 1
+?Create@nsDirectoryIteratorImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
diff --git a/src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg b/src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg
new file mode 100644
index 00000000..8a32b21f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg
@@ -0,0 +1,47 @@
+[xpcom-tests]
+#if USE_SHORT_LIBNAME
+dist/bin/components/@DLLP@tdynamic@DLLS@
+dist/bin/components/@DLLP@MyServce@DLLS@
+dist/bin/components/@DLLP@xpcomsmp@DLLS@
+#else
+dist/bin/components/@DLLP@testdynamic@DLLS@
+dist/bin/components/@DLLP@MyService@DLLS@
+dist/bin/components/@DLLP@xpcomsample@DLLS@
+#endif
+dist/bin/components/nsSample.js
+!xpt dist/bin/components/xpcomsample.xpt
+dist/bin/nsTestSample@BINS@
+dist/bin/res/test.properties
+dist/bin/res/samples/xpconnect-sample.html
+!xpt dist/bin/components/proxytest.xpt
+dist/bin/proxytests@BINS@
+
+dist/bin/PrimitiveTest@BINS@
+dist/bin/SimpleTypeLib@BINS@
+dist/bin/TestInterfaceInfo@BINS@
+dist/bin/TestXPTCInvoke@BINS@
+
+dist/bin/nsIFileEnumerator@BINS@
+dist/bin/nsIFileTest@BINS@
+dist/bin/TestArray@BINS@
+dist/bin/TestAtoms@BINS@
+dist/bin/TestAutoLock@BINS@
+dist/bin/TestCallTemplates@BINS@
+dist/bin/TestCOMPtr@BINS@
+dist/bin/TestCOMPtrEq@BINS@
+dist/bin/TestCRT@BINS@
+dist/bin/TestFactory@BINS@
+dist/bin/TestHashtables@BINS@
+dist/bin/TestID@BINS@
+dist/bin/TestObserverService@BINS@
+dist/bin/TestPermanentAtoms@BINS@
+dist/bin/TestPipes@BINS@
+dist/bin/TestServMgr@BINS@
+dist/bin/TestThreads@BINS@
+dist/bin/TestXPIDLString@BINS@
+dist/bin/TestDeque@BINS@
+dist/bin/TestAutoPtr@BINS@
+
+#if OS_ARCH==WINNT
+dist/bin/TestCOM.exe
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/xpcom.pkg b/src/libs/xpcom18a4/xpcom/build/xpcom.pkg
new file mode 100644
index 00000000..eab0e19d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/xpcom.pkg
@@ -0,0 +1,106 @@
+[xpcom]
+dist/bin/@DLLP@xpcom@DLLS@
+!xpt dist/bin/components/xpcom_base.xpt
+!xpt dist/bin/components/xpcom_components.xpt
+!xpt dist/bin/components/xpcom_ds.xpt
+!xpt dist/bin/components/xpcom_io.xpt
+!xpt dist/bin/components/xpcom_xpti.xpt
+
+#if OS_ARCH==WINNT
+!xpt dist/bin/components/xpcom_thread.xpt
+!xpt dist/bin/components/proxyObject.xpt
+#else
+!xpt dist/bin/components/xpcom_threads.xpt
+!xpt dist/bin/components/proxyObjInst.xpt
+#endif
+
+[gecko-support]
+dist/bin/regxpcom@BINS@
+dist/bin/xpt_dump@BINS@
+dist/bin/xpt_link@BINS@
+#if MOZ_DEBUG
+#if OS_ARCH==WINNT
+dist/bin/windbgdlg.exe
+#endif
+#endif
+
+# xpidl.exe is not licensed MPL, so we don't include it with applications.
+# It is only included in the developer (SDK) packages.
+[gecko-devel]
+dist/bin/xpidl@BINS@
+
+# put NSPR here, because hacking the NSPR build system is too painful
+# xxxbsmedberg: this doesn't obey --with-system-nspr
+[nspr]
+dist/bin/@DLLP@nspr4@DLLS@
+dist/bin/@DLLP@plc4@DLLS@
+dist/bin/@DLLP@plds4@DLLS@
+
+[nspr-devel]
+dist/lib/@LIBP@nspr4@LIBS@
+dist/lib/@LIBP@plc4@LIBS@
+dist/lib/@LIBP@plds4@LIBS@
+dist/include/nspr/private/pprio.h
+dist/include/nspr/private/pprthred.h
+dist/include/nspr/private/prpriv.h
+dist/include/nspr/prcpucfg.h
+dist/include/nspr/obsolete/pralarm.h
+dist/include/nspr/obsolete/probslet.h
+dist/include/nspr/obsolete/protypes.h
+dist/include/nspr/obsolete/prsem.h
+dist/include/nspr/nspr.h
+dist/include/nspr/pratom.h
+dist/include/nspr/prbit.h
+dist/include/nspr/prclist.h
+dist/include/nspr/prcmon.h
+dist/include/nspr/prcountr.h
+dist/include/nspr/prcvar.h
+dist/include/nspr/prdtoa.h
+dist/include/nspr/prenv.h
+dist/include/nspr/prerr.h
+dist/include/nspr/prerror.h
+dist/include/nspr/prinet.h
+dist/include/nspr/prinit.h
+dist/include/nspr/prinrval.h
+dist/include/nspr/prio.h
+dist/include/nspr/pripcsem.h
+dist/include/nspr/prlink.h
+dist/include/nspr/prlock.h
+dist/include/nspr/prlog.h
+dist/include/nspr/prlong.h
+dist/include/nspr/prmem.h
+dist/include/nspr/prmon.h
+dist/include/nspr/prmwait.h
+dist/include/nspr/prnetdb.h
+dist/include/nspr/prolock.h
+dist/include/nspr/prpdce.h
+dist/include/nspr/prprf.h
+dist/include/nspr/prproces.h
+dist/include/nspr/prrng.h
+dist/include/nspr/prrwlock.h
+dist/include/nspr/prshma.h
+dist/include/nspr/prshm.h
+dist/include/nspr/prsystem.h
+dist/include/nspr/prthread.h
+dist/include/nspr/prtime.h
+dist/include/nspr/prtpool.h
+dist/include/nspr/prtrace.h
+dist/include/nspr/prtypes.h
+dist/include/nspr/prvrsion.h
+dist/include/nspr/prwin16.h
+dist/include/nspr/plarenas.h
+dist/include/nspr/plarena.h
+dist/include/nspr/plhash.h
+dist/include/nspr/plbase64.h
+dist/include/nspr/plerror.h
+dist/include/nspr/plgetopt.h
+dist/include/nspr/plresolv.h
+dist/include/nspr/plstr.h
+
+[unpackaged-files]
+!optional dist/bin/.autoreg
+!optional dist/bin/components/xpti.dat
+!optional dist/bin/components/compreg.dat
+#if OS_ARCH==WINNT
+dist/bin/rebasedlls.exe
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def b/src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def
new file mode 100644
index 00000000..966f2ea4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def
@@ -0,0 +1,252 @@
+LIBRARY xpcom
+DESCRIPTION "xpcom library"
+
+EXPORTS
+ ?Stub3@nsXPTCStubBase@@UAAIXZ
+ ?Stub4@nsXPTCStubBase@@UAAIXZ
+ ?Stub5@nsXPTCStubBase@@UAAIXZ
+ ?Stub6@nsXPTCStubBase@@UAAIXZ
+ ?Stub7@nsXPTCStubBase@@UAAIXZ
+ ?Stub8@nsXPTCStubBase@@UAAIXZ
+ ?Stub9@nsXPTCStubBase@@UAAIXZ
+ ?Stub10@nsXPTCStubBase@@UAAIXZ
+ ?Stub11@nsXPTCStubBase@@UAAIXZ
+ ?Stub12@nsXPTCStubBase@@UAAIXZ
+ ?Stub13@nsXPTCStubBase@@UAAIXZ
+ ?Stub14@nsXPTCStubBase@@UAAIXZ
+ ?Stub15@nsXPTCStubBase@@UAAIXZ
+ ?Stub16@nsXPTCStubBase@@UAAIXZ
+ ?Stub17@nsXPTCStubBase@@UAAIXZ
+ ?Stub18@nsXPTCStubBase@@UAAIXZ
+ ?Stub19@nsXPTCStubBase@@UAAIXZ
+ ?Stub20@nsXPTCStubBase@@UAAIXZ
+ ?Stub21@nsXPTCStubBase@@UAAIXZ
+ ?Stub22@nsXPTCStubBase@@UAAIXZ
+ ?Stub23@nsXPTCStubBase@@UAAIXZ
+ ?Stub24@nsXPTCStubBase@@UAAIXZ
+ ?Stub25@nsXPTCStubBase@@UAAIXZ
+ ?Stub26@nsXPTCStubBase@@UAAIXZ
+ ?Stub27@nsXPTCStubBase@@UAAIXZ
+ ?Stub28@nsXPTCStubBase@@UAAIXZ
+ ?Stub29@nsXPTCStubBase@@UAAIXZ
+ ?Stub30@nsXPTCStubBase@@UAAIXZ
+ ?Stub31@nsXPTCStubBase@@UAAIXZ
+ ?Stub32@nsXPTCStubBase@@UAAIXZ
+ ?Stub33@nsXPTCStubBase@@UAAIXZ
+ ?Stub34@nsXPTCStubBase@@UAAIXZ
+ ?Stub35@nsXPTCStubBase@@UAAIXZ
+ ?Stub36@nsXPTCStubBase@@UAAIXZ
+ ?Stub37@nsXPTCStubBase@@UAAIXZ
+ ?Stub38@nsXPTCStubBase@@UAAIXZ
+ ?Stub39@nsXPTCStubBase@@UAAIXZ
+ ?Stub40@nsXPTCStubBase@@UAAIXZ
+ ?Stub41@nsXPTCStubBase@@UAAIXZ
+ ?Stub42@nsXPTCStubBase@@UAAIXZ
+ ?Stub43@nsXPTCStubBase@@UAAIXZ
+ ?Stub44@nsXPTCStubBase@@UAAIXZ
+ ?Stub45@nsXPTCStubBase@@UAAIXZ
+ ?Stub46@nsXPTCStubBase@@UAAIXZ
+ ?Stub47@nsXPTCStubBase@@UAAIXZ
+ ?Stub48@nsXPTCStubBase@@UAAIXZ
+ ?Stub49@nsXPTCStubBase@@UAAIXZ
+ ?Stub50@nsXPTCStubBase@@UAAIXZ
+ ?Stub51@nsXPTCStubBase@@UAAIXZ
+ ?Stub52@nsXPTCStubBase@@UAAIXZ
+ ?Stub53@nsXPTCStubBase@@UAAIXZ
+ ?Stub54@nsXPTCStubBase@@UAAIXZ
+ ?Stub55@nsXPTCStubBase@@UAAIXZ
+ ?Stub56@nsXPTCStubBase@@UAAIXZ
+ ?Stub57@nsXPTCStubBase@@UAAIXZ
+ ?Stub58@nsXPTCStubBase@@UAAIXZ
+ ?Stub59@nsXPTCStubBase@@UAAIXZ
+ ?Stub60@nsXPTCStubBase@@UAAIXZ
+ ?Stub61@nsXPTCStubBase@@UAAIXZ
+ ?Stub62@nsXPTCStubBase@@UAAIXZ
+ ?Stub63@nsXPTCStubBase@@UAAIXZ
+ ?Stub64@nsXPTCStubBase@@UAAIXZ
+ ?Stub65@nsXPTCStubBase@@UAAIXZ
+ ?Stub66@nsXPTCStubBase@@UAAIXZ
+ ?Stub67@nsXPTCStubBase@@UAAIXZ
+ ?Stub68@nsXPTCStubBase@@UAAIXZ
+ ?Stub69@nsXPTCStubBase@@UAAIXZ
+ ?Stub70@nsXPTCStubBase@@UAAIXZ
+ ?Stub71@nsXPTCStubBase@@UAAIXZ
+ ?Stub72@nsXPTCStubBase@@UAAIXZ
+ ?Stub73@nsXPTCStubBase@@UAAIXZ
+ ?Stub74@nsXPTCStubBase@@UAAIXZ
+ ?Stub75@nsXPTCStubBase@@UAAIXZ
+ ?Stub76@nsXPTCStubBase@@UAAIXZ
+ ?Stub77@nsXPTCStubBase@@UAAIXZ
+ ?Stub78@nsXPTCStubBase@@UAAIXZ
+ ?Stub79@nsXPTCStubBase@@UAAIXZ
+ ?Stub80@nsXPTCStubBase@@UAAIXZ
+ ?Stub81@nsXPTCStubBase@@UAAIXZ
+ ?Stub82@nsXPTCStubBase@@UAAIXZ
+ ?Stub83@nsXPTCStubBase@@UAAIXZ
+ ?Stub84@nsXPTCStubBase@@UAAIXZ
+ ?Stub85@nsXPTCStubBase@@UAAIXZ
+ ?Stub86@nsXPTCStubBase@@UAAIXZ
+ ?Stub87@nsXPTCStubBase@@UAAIXZ
+ ?Stub88@nsXPTCStubBase@@UAAIXZ
+ ?Stub89@nsXPTCStubBase@@UAAIXZ
+ ?Stub90@nsXPTCStubBase@@UAAIXZ
+ ?Stub91@nsXPTCStubBase@@UAAIXZ
+ ?Stub92@nsXPTCStubBase@@UAAIXZ
+ ?Stub93@nsXPTCStubBase@@UAAIXZ
+ ?Stub94@nsXPTCStubBase@@UAAIXZ
+ ?Stub95@nsXPTCStubBase@@UAAIXZ
+ ?Stub96@nsXPTCStubBase@@UAAIXZ
+ ?Stub97@nsXPTCStubBase@@UAAIXZ
+ ?Stub98@nsXPTCStubBase@@UAAIXZ
+ ?Stub99@nsXPTCStubBase@@UAAIXZ
+ ?Stub100@nsXPTCStubBase@@UAAIXZ
+ ?Stub101@nsXPTCStubBase@@UAAIXZ
+ ?Stub102@nsXPTCStubBase@@UAAIXZ
+ ?Stub103@nsXPTCStubBase@@UAAIXZ
+ ?Stub104@nsXPTCStubBase@@UAAIXZ
+ ?Stub105@nsXPTCStubBase@@UAAIXZ
+ ?Stub106@nsXPTCStubBase@@UAAIXZ
+ ?Stub107@nsXPTCStubBase@@UAAIXZ
+ ?Stub108@nsXPTCStubBase@@UAAIXZ
+ ?Stub109@nsXPTCStubBase@@UAAIXZ
+ ?Stub110@nsXPTCStubBase@@UAAIXZ
+ ?Stub111@nsXPTCStubBase@@UAAIXZ
+ ?Stub112@nsXPTCStubBase@@UAAIXZ
+ ?Stub113@nsXPTCStubBase@@UAAIXZ
+ ?Stub114@nsXPTCStubBase@@UAAIXZ
+ ?Stub115@nsXPTCStubBase@@UAAIXZ
+ ?Stub116@nsXPTCStubBase@@UAAIXZ
+ ?Stub117@nsXPTCStubBase@@UAAIXZ
+ ?Stub118@nsXPTCStubBase@@UAAIXZ
+ ?Stub119@nsXPTCStubBase@@UAAIXZ
+ ?Stub120@nsXPTCStubBase@@UAAIXZ
+ ?Stub121@nsXPTCStubBase@@UAAIXZ
+ ?Stub122@nsXPTCStubBase@@UAAIXZ
+ ?Stub123@nsXPTCStubBase@@UAAIXZ
+ ?Stub124@nsXPTCStubBase@@UAAIXZ
+ ?Stub125@nsXPTCStubBase@@UAAIXZ
+ ?Stub126@nsXPTCStubBase@@UAAIXZ
+ ?Stub127@nsXPTCStubBase@@UAAIXZ
+ ?Stub128@nsXPTCStubBase@@UAAIXZ
+ ?Stub129@nsXPTCStubBase@@UAAIXZ
+ ?Stub130@nsXPTCStubBase@@UAAIXZ
+ ?Stub131@nsXPTCStubBase@@UAAIXZ
+ ?Stub132@nsXPTCStubBase@@UAAIXZ
+ ?Stub133@nsXPTCStubBase@@UAAIXZ
+ ?Stub134@nsXPTCStubBase@@UAAIXZ
+ ?Stub135@nsXPTCStubBase@@UAAIXZ
+ ?Stub136@nsXPTCStubBase@@UAAIXZ
+ ?Stub137@nsXPTCStubBase@@UAAIXZ
+ ?Stub138@nsXPTCStubBase@@UAAIXZ
+ ?Stub139@nsXPTCStubBase@@UAAIXZ
+ ?Stub140@nsXPTCStubBase@@UAAIXZ
+ ?Stub141@nsXPTCStubBase@@UAAIXZ
+ ?Stub142@nsXPTCStubBase@@UAAIXZ
+ ?Stub143@nsXPTCStubBase@@UAAIXZ
+ ?Stub144@nsXPTCStubBase@@UAAIXZ
+ ?Stub145@nsXPTCStubBase@@UAAIXZ
+ ?Stub146@nsXPTCStubBase@@UAAIXZ
+ ?Stub147@nsXPTCStubBase@@UAAIXZ
+ ?Stub148@nsXPTCStubBase@@UAAIXZ
+ ?Stub149@nsXPTCStubBase@@UAAIXZ
+ ?Stub150@nsXPTCStubBase@@UAAIXZ
+ ?Stub151@nsXPTCStubBase@@UAAIXZ
+ ?Stub152@nsXPTCStubBase@@UAAIXZ
+ ?Stub153@nsXPTCStubBase@@UAAIXZ
+ ?Stub154@nsXPTCStubBase@@UAAIXZ
+ ?Stub155@nsXPTCStubBase@@UAAIXZ
+ ?Stub156@nsXPTCStubBase@@UAAIXZ
+ ?Stub157@nsXPTCStubBase@@UAAIXZ
+ ?Stub158@nsXPTCStubBase@@UAAIXZ
+ ?Stub159@nsXPTCStubBase@@UAAIXZ
+ ?Stub160@nsXPTCStubBase@@UAAIXZ
+ ?Stub161@nsXPTCStubBase@@UAAIXZ
+ ?Stub162@nsXPTCStubBase@@UAAIXZ
+ ?Stub163@nsXPTCStubBase@@UAAIXZ
+ ?Stub164@nsXPTCStubBase@@UAAIXZ
+ ?Stub165@nsXPTCStubBase@@UAAIXZ
+ ?Stub166@nsXPTCStubBase@@UAAIXZ
+ ?Stub167@nsXPTCStubBase@@UAAIXZ
+ ?Stub168@nsXPTCStubBase@@UAAIXZ
+ ?Stub169@nsXPTCStubBase@@UAAIXZ
+ ?Stub170@nsXPTCStubBase@@UAAIXZ
+ ?Stub171@nsXPTCStubBase@@UAAIXZ
+ ?Stub172@nsXPTCStubBase@@UAAIXZ
+ ?Stub173@nsXPTCStubBase@@UAAIXZ
+ ?Stub174@nsXPTCStubBase@@UAAIXZ
+ ?Stub175@nsXPTCStubBase@@UAAIXZ
+ ?Stub176@nsXPTCStubBase@@UAAIXZ
+ ?Stub177@nsXPTCStubBase@@UAAIXZ
+ ?Stub178@nsXPTCStubBase@@UAAIXZ
+ ?Stub179@nsXPTCStubBase@@UAAIXZ
+ ?Stub180@nsXPTCStubBase@@UAAIXZ
+ ?Stub181@nsXPTCStubBase@@UAAIXZ
+ ?Stub182@nsXPTCStubBase@@UAAIXZ
+ ?Stub183@nsXPTCStubBase@@UAAIXZ
+ ?Stub184@nsXPTCStubBase@@UAAIXZ
+ ?Stub185@nsXPTCStubBase@@UAAIXZ
+ ?Stub186@nsXPTCStubBase@@UAAIXZ
+ ?Stub187@nsXPTCStubBase@@UAAIXZ
+ ?Stub188@nsXPTCStubBase@@UAAIXZ
+ ?Stub189@nsXPTCStubBase@@UAAIXZ
+ ?Stub190@nsXPTCStubBase@@UAAIXZ
+ ?Stub191@nsXPTCStubBase@@UAAIXZ
+ ?Stub192@nsXPTCStubBase@@UAAIXZ
+ ?Stub193@nsXPTCStubBase@@UAAIXZ
+ ?Stub194@nsXPTCStubBase@@UAAIXZ
+ ?Stub195@nsXPTCStubBase@@UAAIXZ
+ ?Stub196@nsXPTCStubBase@@UAAIXZ
+ ?Stub197@nsXPTCStubBase@@UAAIXZ
+ ?Stub198@nsXPTCStubBase@@UAAIXZ
+ ?Stub199@nsXPTCStubBase@@UAAIXZ
+ ?Stub200@nsXPTCStubBase@@UAAIXZ
+ ?Stub201@nsXPTCStubBase@@UAAIXZ
+ ?Stub202@nsXPTCStubBase@@UAAIXZ
+ ?Stub203@nsXPTCStubBase@@UAAIXZ
+ ?Stub204@nsXPTCStubBase@@UAAIXZ
+ ?Stub205@nsXPTCStubBase@@UAAIXZ
+ ?Stub206@nsXPTCStubBase@@UAAIXZ
+ ?Stub207@nsXPTCStubBase@@UAAIXZ
+ ?Stub208@nsXPTCStubBase@@UAAIXZ
+ ?Stub209@nsXPTCStubBase@@UAAIXZ
+ ?Stub210@nsXPTCStubBase@@UAAIXZ
+ ?Stub211@nsXPTCStubBase@@UAAIXZ
+ ?Stub212@nsXPTCStubBase@@UAAIXZ
+ ?Stub213@nsXPTCStubBase@@UAAIXZ
+ ?Stub214@nsXPTCStubBase@@UAAIXZ
+ ?Stub215@nsXPTCStubBase@@UAAIXZ
+ ?Stub216@nsXPTCStubBase@@UAAIXZ
+ ?Stub217@nsXPTCStubBase@@UAAIXZ
+ ?Stub218@nsXPTCStubBase@@UAAIXZ
+ ?Stub219@nsXPTCStubBase@@UAAIXZ
+ ?Stub220@nsXPTCStubBase@@UAAIXZ
+ ?Stub221@nsXPTCStubBase@@UAAIXZ
+ ?Stub222@nsXPTCStubBase@@UAAIXZ
+ ?Stub223@nsXPTCStubBase@@UAAIXZ
+ ?Stub224@nsXPTCStubBase@@UAAIXZ
+ ?Stub225@nsXPTCStubBase@@UAAIXZ
+ ?Stub226@nsXPTCStubBase@@UAAIXZ
+ ?Stub227@nsXPTCStubBase@@UAAIXZ
+ ?Stub228@nsXPTCStubBase@@UAAIXZ
+ ?Stub229@nsXPTCStubBase@@UAAIXZ
+ ?Stub230@nsXPTCStubBase@@UAAIXZ
+ ?Stub231@nsXPTCStubBase@@UAAIXZ
+ ?Stub232@nsXPTCStubBase@@UAAIXZ
+ ?Stub233@nsXPTCStubBase@@UAAIXZ
+ ?Stub234@nsXPTCStubBase@@UAAIXZ
+ ?Stub235@nsXPTCStubBase@@UAAIXZ
+ ?Stub236@nsXPTCStubBase@@UAAIXZ
+ ?Stub237@nsXPTCStubBase@@UAAIXZ
+ ?Stub238@nsXPTCStubBase@@UAAIXZ
+ ?Stub239@nsXPTCStubBase@@UAAIXZ
+ ?Stub240@nsXPTCStubBase@@UAAIXZ
+ ?Stub241@nsXPTCStubBase@@UAAIXZ
+ ?Stub242@nsXPTCStubBase@@UAAIXZ
+ ?Stub243@nsXPTCStubBase@@UAAIXZ
+ ?Stub244@nsXPTCStubBase@@UAAIXZ
+ ?Stub245@nsXPTCStubBase@@UAAIXZ
+ ?Stub246@nsXPTCStubBase@@UAAIXZ
+ ?Stub247@nsXPTCStubBase@@UAAIXZ
+ ?Stub248@nsXPTCStubBase@@UAAIXZ
+ ?Stub249@nsXPTCStubBase@@UAAIXZ
+
diff --git a/src/libs/xpcom18a4/xpcom/components/.cvsignore b/src/libs/xpcom18a4/xpcom/components/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/components/Makefile.in b/src/libs/xpcom18a4/xpcom/components/Makefile.in
new file mode 100644
index 00000000..68614854
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/Makefile.in
@@ -0,0 +1,107 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = xpcom_components
+LIBRARY_NAME = xpcomcomponents_s
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+CPPSRCS = \
+ nsCategoryManager.cpp \
+ nsComponentManager.cpp \
+ nsComponentManagerObsolete.cpp \
+ nsNativeComponentLoader.cpp \
+ nsServiceManagerObsolete.cpp \
+ xcDll.cpp \
+ $(NULL)
+
+ifdef MOZ_STATIC_COMPONENT_LOADER
+CPPSRCS += nsStaticComponentLoader.cpp
+endif
+
+EXPORTS = \
+ nsCategoryManagerUtils.h \
+ nsComponentManagerUtils.h \
+ nsComponentManagerObsolete.h \
+ nsIServiceManagerUtils.h \
+ nsIServiceManagerObsolete.h \
+ nsModule.h \
+ nsNativeComponentLoader.h \
+ nsStaticComponent.h \
+ nsObsoleteModuleLoading.h \
+ xcDll.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIComponentLoader.idl \
+ nsIComponentLoaderManager.idl \
+ nsIComponentManagerObsolete.idl \
+ nsINativeComponentLoader.idl \
+ $(NULL)
+
+SDK_XPIDLSRCS = \
+ nsIClassInfo.idl \
+ nsIComponentRegistrar.idl \
+ nsIFactory.idl \
+ nsIModule.idl \
+ nsIServiceManager.idl \
+ nsIComponentManager.idl \
+ nsICategoryManager.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+LOCAL_INCLUDES = -I$(srcdir)/../base -I$(srcdir)/../thread -I$(srcdir)/../ds -I..
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTI_API
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp
new file mode 100644
index 00000000..d7202bdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp
@@ -0,0 +1,799 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define PL_ARENA_CONST_ALIGN_MASK 7
+
+#include "nsICategoryManager.h"
+#include "nsCategoryManager.h"
+
+#include "plarena.h"
+#include "prio.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "nsCOMPtr.h"
+#include "nsTHashtable.h"
+#include "nsClassHashtable.h"
+#include "nsIFactory.h"
+#include "nsIStringEnumerator.h"
+#include "nsSupportsPrimitives.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIObserver.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsEnumeratorUtils.h"
+
+class nsIComponentLoaderManager;
+
+/*
+ CategoryDatabase
+ contains 0 or more 1-1 mappings of string to Category
+ each Category contains 0 or more 1-1 mappings of string keys to string values
+
+ In other words, the CategoryDatabase is a tree, whose root is a hashtable.
+ Internal nodes (or Categories) are hashtables. Leaf nodes are strings.
+
+ The leaf strings are allocated in an arena, because we assume they're not
+ going to change much ;)
+*/
+
+#define NS_CATEGORYMANAGER_ARENA_SIZE (1024 * 8)
+
+// pulled in from nsComponentManager.cpp
+char* ArenaStrdup(const char* s, PLArenaPool* aArena);
+
+//
+// BaseStringEnumerator is subclassed by EntryEnumerator and
+// CategoryEnumerator
+//
+class BaseStringEnumerator
+ : public nsISimpleEnumerator,
+ nsIUTF8StringEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+ NS_DECL_NSIUTF8STRINGENUMERATOR
+
+protected:
+ BaseStringEnumerator()
+ : mArray(nsnull),
+ mCount(0),
+ mSimpleCurItem(0),
+ mStringCurItem(0) { }
+
+ // A virtual destructor is needed here because subclasses of
+ // BaseStringEnumerator do not implement their own Release() method.
+
+ virtual ~BaseStringEnumerator()
+ {
+ if (mArray)
+ delete[] mArray;
+ }
+
+ const char** mArray;
+ PRUint32 mCount;
+ PRUint32 mSimpleCurItem;
+ PRUint32 mStringCurItem;
+};
+
+NS_IMPL_ISUPPORTS2(BaseStringEnumerator, nsISimpleEnumerator, nsIUTF8StringEnumerator)
+
+NS_IMETHODIMP
+BaseStringEnumerator::HasMoreElements(PRBool *_retval)
+{
+ *_retval = (mSimpleCurItem < mCount);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::GetNext(nsISupports **_retval)
+{
+ if (mSimpleCurItem >= mCount)
+ return NS_ERROR_FAILURE;
+
+ nsSupportsDependentCString* str =
+ new nsSupportsDependentCString(mArray[mSimpleCurItem++]);
+ if (!str)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = str;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::HasMore(PRBool *_retval)
+{
+ *_retval = (mStringCurItem < mCount);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::GetNext(nsACString& _retval)
+{
+ if (mStringCurItem >= mCount)
+ return NS_ERROR_FAILURE;
+
+ _retval = nsDependentCString(mArray[mStringCurItem++]);
+ return NS_OK;
+}
+
+
+//
+// EntryEnumerator is the wrapper that allows nsICategoryManager::EnumerateCategory
+//
+class EntryEnumerator
+ : public BaseStringEnumerator
+{
+public:
+ static EntryEnumerator* Create(nsTHashtable<CategoryLeaf>& aTable);
+
+private:
+ static PLDHashOperator PR_CALLBACK
+ enumfunc_createenumerator(CategoryLeaf* aLeaf, void* userArg);
+};
+
+
+PLDHashOperator PR_CALLBACK
+EntryEnumerator::enumfunc_createenumerator(CategoryLeaf* aLeaf, void* userArg)
+{
+ EntryEnumerator* mythis = NS_STATIC_CAST(EntryEnumerator*, userArg);
+ mythis->mArray[mythis->mCount++] = aLeaf->GetKey();
+
+ return PL_DHASH_NEXT;
+}
+
+EntryEnumerator*
+EntryEnumerator::Create(nsTHashtable<CategoryLeaf>& aTable)
+{
+ EntryEnumerator* enumObj = new EntryEnumerator();
+ if (!enumObj)
+ return nsnull;
+
+ enumObj->mArray = new char const* [aTable.Count()];
+ if (!enumObj->mArray) {
+ delete enumObj;
+ return nsnull;
+ }
+
+ aTable.EnumerateEntries(enumfunc_createenumerator, enumObj);
+
+ return enumObj;
+}
+
+
+//
+// CategoryNode implementations
+//
+
+CategoryNode*
+CategoryNode::Create(PLArenaPool* aArena)
+{
+ CategoryNode* node = new(aArena) CategoryNode();
+ if (!node)
+ return nsnull;
+
+ if (!node->mTable.Init()) {
+ delete node;
+ return nsnull;
+ }
+
+ node->mLock = PR_NewLock();
+ if (!node->mLock) {
+ delete node;
+ return nsnull;
+ }
+
+ return node;
+}
+
+CategoryNode::~CategoryNode()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+void*
+CategoryNode::operator new(size_t aSize, PLArenaPool* aArena)
+{
+ void* p;
+ PL_ARENA_ALLOCATE(p, aArena, aSize);
+ return p;
+}
+
+NS_METHOD
+CategoryNode::GetLeaf(const char* aEntryName,
+ char** _retval)
+{
+ PR_Lock(mLock);
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ CategoryLeaf* ent =
+ mTable.GetEntry(aEntryName);
+
+ // we only want the non-persistent value
+ if (ent && ent->nonpValue) {
+ *_retval = nsCRT::strdup(ent->nonpValue);
+ if (*_retval)
+ rv = NS_OK;
+ }
+ PR_Unlock(mLock);
+
+ return rv;
+}
+
+NS_METHOD
+CategoryNode::AddLeaf(const char* aEntryName,
+ const char* aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char** _retval,
+ PLArenaPool* aArena)
+{
+ PR_Lock(mLock);
+ CategoryLeaf* leaf =
+ mTable.GetEntry(aEntryName);
+
+ nsresult rv = NS_OK;
+ if (leaf) {
+ //if the entry was found, aReplace must be specified
+ if (!aReplace && (leaf->nonpValue || (aPersist && leaf->pValue )))
+ rv = NS_ERROR_INVALID_ARG;
+ } else {
+ const char* arenaEntryName = ArenaStrdup(aEntryName, aArena);
+ if (!arenaEntryName) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ leaf = mTable.PutEntry(arenaEntryName);
+ if (!leaf)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ const char* arenaValue = ArenaStrdup(aValue, aArena);
+ if (!arenaValue) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ leaf->nonpValue = arenaValue;
+ if (aPersist)
+ leaf->pValue = arenaValue;
+ }
+ }
+
+ PR_Unlock(mLock);
+ return rv;
+}
+
+NS_METHOD
+CategoryNode::DeleteLeaf(const char* aEntryName,
+ PRBool aDontPersist)
+{
+ // we don't throw any errors, because it normally doesn't matter
+ // and it makes JS a lot cleaner
+ PR_Lock(mLock);
+
+ if (aDontPersist) {
+ // we can just remove the entire hash entry without introspection
+ mTable.RemoveEntry(aEntryName);
+ } else {
+ // if we are keeping the persistent value, we need to look at
+ // the contents of the current entry
+ CategoryLeaf* leaf = mTable.GetEntry(aEntryName);
+ if (leaf) {
+ if (leaf->pValue) {
+ leaf->nonpValue = nsnull;
+ } else {
+ // if there is no persistent value, just remove the entry
+ mTable.RawRemoveEntry(leaf);
+ }
+ }
+ }
+ PR_Unlock(mLock);
+
+ return NS_OK;
+}
+
+NS_METHOD
+CategoryNode::Enumerate(nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ EntryEnumerator* enumObj = EntryEnumerator::Create(mTable);
+ PR_Unlock(mLock);
+
+ if (!enumObj)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = enumObj;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+struct persistent_userstruct {
+ PRFileDesc* fd;
+ const char* categoryName;
+ PRBool success;
+};
+
+PLDHashOperator PR_CALLBACK
+enumfunc_pentries(CategoryLeaf* aLeaf, void* userArg)
+{
+ persistent_userstruct* args =
+ NS_STATIC_CAST(persistent_userstruct*, userArg);
+
+ PLDHashOperator status = PL_DHASH_NEXT;
+
+ if (aLeaf->pValue) {
+ if (PR_fprintf(args->fd,
+ "%s,%s,%s\n",
+ args->categoryName,
+ aLeaf->GetKey(),
+ aLeaf->pValue) == (PRUint32) -1) {
+ args->success = PR_FALSE;
+ status = PL_DHASH_STOP;
+ }
+ }
+
+ return status;
+}
+
+PRBool
+CategoryNode::WritePersistentEntries(PRFileDesc* fd, const char* aCategoryName)
+{
+ persistent_userstruct args = {
+ fd,
+ aCategoryName,
+ PR_TRUE
+ };
+
+ PR_Lock(mLock);
+ mTable.EnumerateEntries(enumfunc_pentries, &args);
+ PR_Unlock(mLock);
+
+ return args.success;
+}
+
+
+//
+// CategoryEnumerator class
+//
+
+class CategoryEnumerator
+ : public BaseStringEnumerator
+{
+public:
+ static CategoryEnumerator* Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>& aTable);
+
+private:
+ static PLDHashOperator PR_CALLBACK
+ enumfunc_createenumerator(const char* aStr,
+ CategoryNode* aNode,
+ void* userArg);
+};
+
+CategoryEnumerator*
+CategoryEnumerator::Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>& aTable)
+{
+ CategoryEnumerator* enumObj = new CategoryEnumerator();
+ if (!enumObj)
+ return nsnull;
+
+ enumObj->mArray = new const char* [aTable.Count()];
+ if (!enumObj->mArray) {
+ delete enumObj;
+ return nsnull;
+ }
+
+ aTable.EnumerateRead(enumfunc_createenumerator, enumObj);
+
+ return enumObj;
+}
+
+PLDHashOperator PR_CALLBACK
+CategoryEnumerator::enumfunc_createenumerator(const char* aStr, CategoryNode* aNode, void* userArg)
+{
+ CategoryEnumerator* mythis = NS_STATIC_CAST(CategoryEnumerator*, userArg);
+
+ // if a category has no entries, we pretend it doesn't exist
+ if (aNode->Count())
+ mythis->mArray[mythis->mCount++] = aStr;
+
+ return PL_DHASH_NEXT;
+}
+
+
+//
+// nsCategoryManager implementations
+//
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsCategoryManager, nsICategoryManager)
+
+nsCategoryManager*
+nsCategoryManager::Create()
+{
+ nsCategoryManager* manager = new nsCategoryManager();
+
+ if (!manager)
+ return nsnull;
+
+ PL_INIT_ARENA_POOL(&(manager->mArena), "CategoryManagerArena",
+ NS_CATEGORYMANAGER_ARENA_SIZE); // this never fails
+
+ if (!manager->mTable.Init()) {
+ delete manager;
+ return nsnull;
+ }
+
+ manager->mLock = PR_NewLock();
+
+ if (!manager->mLock) {
+ delete manager;
+ return nsnull;
+ }
+
+ return manager;
+}
+
+nsCategoryManager::~nsCategoryManager()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ // the hashtable contains entries that must be deleted before the arena is
+ // destroyed, or else you will have PRLocks undestroyed and other Really
+ // Bad Stuff (TM)
+ mTable.Clear();
+
+ PL_FinishArenaPool(&mArena);
+}
+
+inline CategoryNode*
+nsCategoryManager::get_category(const char* aName) {
+ CategoryNode* node;
+ if (!mTable.Get(aName, &node)) {
+ return nsnull;
+ }
+ return node;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::GetCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ char **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult status = NS_ERROR_NOT_AVAILABLE;
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (category) {
+ status = category->GetLeaf(aEntryName, _retval);
+ }
+
+ return status;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::AddCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ const char *aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+ NS_ENSURE_ARG_POINTER(aValue);
+
+ // Before we can insert a new entry, we'll need to
+ // find the |CategoryNode| to put it in...
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+
+ if (!category) {
+ // That category doesn't exist yet; let's make it.
+ category = CategoryNode::Create(&mArena);
+
+ char* categoryName = ArenaStrdup(aCategoryName, &mArena);
+ mTable.Put(categoryName, category);
+ }
+ PR_Unlock(mLock);
+
+ if (!category)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return category->AddLeaf(aEntryName,
+ aValue,
+ aPersist,
+ aReplace,
+ _retval,
+ &mArena);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ PRBool aDontPersist)
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+
+ /*
+ Note: no errors are reported since failure to delete
+ probably won't hurt you, and returning errors seriously
+ inconveniences JS clients
+ */
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (!category)
+ return NS_OK;
+
+ return category->DeleteLeaf(aEntryName,
+ aDontPersist);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategory( const char *aCategoryName )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+
+ // the categories are arena-allocated, so we don't
+ // actually delete them. We just remove all of the
+ // leaf nodes.
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (category)
+ category->Clear();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::EnumerateCategory( const char *aCategoryName,
+ nsISimpleEnumerator **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (!category) {
+ return NS_NewEmptyEnumerator(_retval);
+ }
+
+ return category->Enumerate(_retval);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::EnumerateCategories(nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ CategoryEnumerator* enumObj = CategoryEnumerator::Create(mTable);
+ PR_Unlock(mLock);
+
+ if (!enumObj)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = enumObj;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+struct writecat_struct {
+ PRFileDesc* fd;
+ PRBool success;
+};
+
+PLDHashOperator PR_CALLBACK
+enumfunc_categories(const char* aKey, CategoryNode* aCategory, void* userArg)
+{
+ writecat_struct* args = NS_STATIC_CAST(writecat_struct*, userArg);
+
+ PLDHashOperator result = PL_DHASH_NEXT;
+
+ if (!aCategory->WritePersistentEntries(args->fd, aKey)) {
+ args->success = PR_FALSE;
+ result = PL_DHASH_STOP;
+ }
+
+ return result;
+}
+
+NS_METHOD
+nsCategoryManager::WriteCategoryManagerToRegistry(PRFileDesc* fd)
+{
+ writecat_struct args = {
+ fd,
+ PR_TRUE
+ };
+
+ PR_Lock(mLock);
+ mTable.EnumerateRead(enumfunc_categories, &args);
+ PR_Unlock(mLock);
+
+ if (!args.success) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+class nsCategoryManagerFactory : public nsIFactory
+ {
+ public:
+ nsCategoryManagerFactory() { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFACTORY
+ };
+
+NS_IMPL_ISUPPORTS1(nsCategoryManagerFactory, nsIFactory)
+
+NS_IMETHODIMP
+nsCategoryManagerFactory::CreateInstance( nsISupports* aOuter, const nsIID& aIID, void** aResult )
+ {
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = 0;
+
+ nsresult status = NS_OK;
+ if ( aOuter )
+ status = NS_ERROR_NO_AGGREGATION;
+ else
+ {
+ nsCategoryManager* raw_category_manager = nsCategoryManager::Create();
+ nsCOMPtr<nsICategoryManager> new_category_manager = raw_category_manager;
+ if ( new_category_manager )
+ status = new_category_manager->QueryInterface(aIID, aResult);
+ else
+ status = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return status;
+ }
+
+NS_IMETHODIMP
+nsCategoryManagerFactory::LockFactory( PRBool )
+ {
+ // Not implemented...
+ return NS_OK;
+ }
+
+nsresult
+NS_CategoryManagerGetFactory( nsIFactory** aFactory )
+ {
+ // assert(aFactory);
+
+ nsresult status;
+
+ *aFactory = 0;
+ nsIFactory* new_factory = NS_STATIC_CAST(nsIFactory*, new nsCategoryManagerFactory);
+ if (new_factory)
+ {
+ *aFactory = new_factory;
+ NS_ADDREF(*aFactory);
+ status = NS_OK;
+ }
+ else
+ status = NS_ERROR_OUT_OF_MEMORY;
+
+ return status;
+ }
+
+
+
+/*
+ * CreateServicesFromCategory()
+ *
+ * Given a category, this convenience functions enumerates the category and
+ * creates a service of every CID or ContractID registered under the category.
+ * If observerTopic is non null and the service implements nsIObserver,
+ * this will attempt to notify the observer with the origin, observerTopic string
+ * as parameter.
+ */
+NS_COM nsresult
+NS_CreateServicesFromCategory(const char *category,
+ nsISupports *origin,
+ const char *observerTopic)
+{
+ nsresult rv = NS_OK;
+
+ int nFailed = 0;
+ nsCOMPtr<nsICategoryManager> categoryManager =
+ do_GetService("@mozilla.org/categorymanager;1", &rv);
+ if (!categoryManager) return rv;
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ rv = categoryManager->EnumerateCategory(category,
+ getter_AddRefs(enumerator));
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
+ // From here on just skip any error we get.
+ nsCOMPtr<nsISupportsCString> catEntry = do_QueryInterface(entry, &rv);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+ nsCAutoString entryString;
+ rv = catEntry->GetData(entryString);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+ nsXPIDLCString contractID;
+ rv = categoryManager->GetCategoryEntry(category,entryString.get(), getter_Copies(contractID));
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+
+ nsCOMPtr<nsISupports> instance = do_GetService(contractID, &rv);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+
+ if (observerTopic) {
+ // try an observer, if it implements it.
+ nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance, &rv);
+ if (NS_SUCCEEDED(rv) && observer)
+ observer->Observe(origin, observerTopic, EmptyString().get());
+ }
+ }
+ return (nFailed ? NS_ERROR_FAILURE : NS_OK);
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h
new file mode 100644
index 00000000..a5cdb59a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#ifndef NSCATEGORYMANAGER_H
+#define NSCATEGORYMANAGER_H
+
+#include "prio.h"
+#include "prlock.h"
+#include "plarena.h"
+#include "nsClassHashtable.h"
+#include "nsICategoryManager.h"
+
+#define NS_CATEGORYMANAGER_CLASSNAME "Category Manager"
+
+/* 16d222a6-1dd2-11b2-b693-f38b02c021b2 */
+#define NS_CATEGORYMANAGER_CID \
+{ 0x16d222a6, 0x1dd2, 0x11b2, \
+ {0xb6, 0x93, 0xf3, 0x8b, 0x02, 0xc0, 0x21, 0xb2} }
+
+/**
+ * a "leaf-node", managed by the nsCategoryNode hashtable.
+ *
+ * we need to keep a "persistent value" (which will be written to the registry)
+ * and a non-persistent value (for the current runtime): these are usually
+ * the same, except when aPersist==PR_FALSE. The strings are permanently arena-
+ * allocated, and will never go away.
+ */
+class CategoryLeaf : public nsDepCharHashKey
+{
+public:
+ CategoryLeaf(const char* aKey)
+ : nsDepCharHashKey(aKey),
+ pValue(nsnull),
+ nonpValue(nsnull) { }
+ const char* pValue;
+ const char* nonpValue;
+};
+
+
+/**
+ * CategoryNode keeps a hashtable of it's entries.
+ * the CategoryNode itself is permanently allocated in
+ * the arena.
+ */
+class CategoryNode
+{
+public:
+ NS_METHOD GetLeaf(const char* aEntryName,
+ char** _retval);
+
+ NS_METHOD AddLeaf(const char* aEntryName,
+ const char* aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char** _retval,
+ PLArenaPool* aArena);
+
+ NS_METHOD DeleteLeaf(const char* aEntryName,
+ PRBool aDontPersist);
+
+ void Clear() {
+ PR_Lock(mLock);
+ mTable.Clear();
+ PR_Unlock(mLock);
+ }
+
+ PRUint32 Count() {
+ PR_Lock(mLock);
+ PRUint32 tCount = mTable.Count();
+ PR_Unlock(mLock);
+ return tCount;
+ }
+
+ NS_METHOD Enumerate(nsISimpleEnumerator** _retval);
+
+ PRBool WritePersistentEntries(PRFileDesc* fd, const char* aCategoryName);
+
+ // CategoryNode is arena-allocated, with the strings
+ static CategoryNode* Create(PLArenaPool* aArena);
+ ~CategoryNode();
+ void operator delete(void*) { }
+
+private:
+ CategoryNode() : mLock(nsnull) { }
+ void* operator new(size_t aSize, PLArenaPool* aArena);
+
+ nsTHashtable<CategoryLeaf> mTable;
+ PRLock* mLock;
+};
+
+
+/**
+ * The main implementation of nsICategoryManager.
+ *
+ * This implementation is thread-safe.
+ */
+class nsCategoryManager
+ : public nsICategoryManager
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICATEGORYMANAGER
+
+ /**
+ * Write the categories to the XPCOM persistent registry.
+ * This is to be used by nsComponentManagerImpl (and NO ONE ELSE).
+ */
+ NS_METHOD WriteCategoryManagerToRegistry(PRFileDesc* fd);
+
+ nsCategoryManager() : mLock(nsnull) { }
+private:
+ friend class nsCategoryManagerFactory;
+ static nsCategoryManager* Create();
+
+ ~nsCategoryManager();
+
+ CategoryNode* get_category(const char* aName);
+
+ PLArenaPool mArena;
+ nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable;
+ PRLock* mLock;
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h
new file mode 100644
index 00000000..54a9fcec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCategoryManagerUtils_h__
+#define nsCategoryManagerUtils_h__
+
+#include "nsICategoryManager.h"
+#include "nsCOMPtr.h"
+
+NS_COM nsresult
+NS_CreateServicesFromCategory(const char *category,
+ nsISupports *origin,
+ const char *observerTopic);
+
+class NS_COM nsCreateInstanceFromCategory : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceFromCategory(const char *aCategory, const char *aEntry,
+ nsISupports *aOuter, nsresult *aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do;
+ }
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aInstancePtr) const;
+
+private:
+ const char *mCategory; // Do not free. This char * is not owned.
+ const char *mEntry; // Do not free. This char * is not owned.
+
+ nsISupports *mOuter;
+ nsresult *mErrorPtr;
+
+};
+
+inline
+const nsCreateInstanceFromCategory
+do_CreateInstanceFromCategory( const char *aCategory, const char *aEntry,
+ nsresult *aErrorPtr = 0)
+{
+ return nsCreateInstanceFromCategory(aCategory, aEntry, 0, aErrorPtr);
+}
+
+inline
+const nsCreateInstanceFromCategory
+do_CreateInstanceFromCategory( const char *aCategory, const char *aEntry,
+ nsISupports *aOuter, nsresult *aErrorPtr = 0)
+{
+ return nsCreateInstanceFromCategory(aCategory, aEntry, aOuter, aErrorPtr);
+}
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp
new file mode 100644
index 00000000..980b0565
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp
@@ -0,0 +1,3794 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+#include <stdlib.h>
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nspr.h"
+#include "nsCRT.h" // for atoll
+// Arena used by component manager for storing contractid string, dll
+// location strings and small objects
+// CAUTION: Arena align mask needs to be defined before including plarena.h
+// currently from nsComponentManager.h
+#define PL_ARENA_CONST_ALIGN_MASK 7
+#define NS_CM_BLOCK_SIZE (1024 * 8)
+
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCategoryManager.h"
+#include "nsCategoryManagerUtils.h"
+#include "nsIComponentLoader.h"
+#include "nsIEnumerator.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIModule.h"
+#include "nsIObserverService.h"
+#include "nsISimpleEnumerator.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsLocalFile.h"
+#include "nsNativeComponentLoader.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "prcmon.h"
+#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
+
+#include "nsInt64.h"
+#include "nsManifestLineReader.h"
+
+#include NEW_H // for placement new
+
+
+#ifdef XP_BEOS
+#include <FindDirectory.h>
+#include <Path.h>
+#endif
+
+#include "prlog.h"
+
+PRLogModuleInfo* nsComponentManagerLog = nsnull;
+
+#if 0 || defined (DEBUG_timeless)
+ #define SHOW_DENIED_ON_SHUTDOWN
+ #define SHOW_CI_ON_EXISTING_SERVICE
+ #define XPCOM_CHECK_PENDING_CIDS
+#endif
+
+// Loader Types
+#define NS_LOADER_DATA_ALLOC_STEP 6
+
+// Bloated registry buffer size to improve startup performance -- needs to
+// be big enough to fit the entire file into memory or it'll thrash.
+// 512K is big enough to allow for some future growth in the registry.
+#define BIG_REGISTRY_BUFLEN (512*1024)
+
+// Common Key Names
+const char classIDKeyName[]="classID";
+const char classesKeyName[]="contractID";
+const char componentLoadersKeyName[]="componentLoaders";
+const char componentsKeyName[]="components";
+const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components";
+const char xpcomKeyName[]="software/mozilla/XPCOM";
+
+// Common Value Names
+const char classIDValueName[]="ClassID";
+const char classNameValueName[]="ClassName";
+const char componentCountValueName[]="ComponentsCount";
+const char componentTypeValueName[]="ComponentType";
+const char contractIDValueName[]="ContractID";
+const char fileSizeValueName[]="FileSize";
+const char inprocServerValueName[]="InprocServer";
+const char lastModValueName[]="LastModTimeStamp";
+const char nativeComponentType[]="application/x-mozilla-native";
+const char staticComponentType[]="application/x-mozilla-static";
+const char versionValueName[]="VersionString";
+
+const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
+const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
+const static char XPCOM_GRECOMPONENT_PREFIX[] = "gre:";
+
+static const char gIDFormat[] =
+ "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
+
+
+#define NS_EMPTY_IID \
+{ \
+ 0x00000000, \
+ 0x0000, \
+ 0x0000, \
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
+}
+
+NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
+NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
+
+#define UID_STRING_LENGTH 39
+
+// Set to true from NS_ShutdownXPCOM.
+extern PRBool gXPCOMShuttingDown;
+
+static void GetIDString(const nsID& aCID, char buf[UID_STRING_LENGTH])
+{
+ PR_snprintf(buf, UID_STRING_LENGTH, gIDFormat,
+ aCID.m0, (PRUint32) aCID.m1, (PRUint32) aCID.m2,
+ (PRUint32) aCID.m3[0], (PRUint32) aCID.m3[1],
+ (PRUint32) aCID.m3[2], (PRUint32) aCID.m3[3],
+ (PRUint32) aCID.m3[4], (PRUint32) aCID.m3[5],
+ (PRUint32) aCID.m3[6], (PRUint32) aCID.m3[7]);
+}
+
+nsresult
+nsCreateInstanceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+{
+ /*
+ * If I were a real man, I would consolidate this with
+ * nsGetServiceFromContractID::operator().
+ */
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsIComponentManager> compMgr;
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(kCategoryManagerCID, &rv);
+
+ if (NS_FAILED(rv)) goto error;
+
+ if (!mCategory || !mEntry) {
+ // when categories have defaults, use that for null mEntry
+ rv = NS_ERROR_NULL_POINTER;
+ goto error;
+ }
+
+ /* find the contractID for category.entry */
+ rv = catman->GetCategoryEntry(mCategory, mEntry,
+ getter_Copies(value));
+ if (NS_FAILED(rv)) goto error;
+ if (!value) {
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ goto error;
+ }
+ NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (!compMgr)
+ return NS_ERROR_FAILURE;
+ compMgr->CreateInstanceByContractID(value,
+ mOuter,
+ aIID,
+ aInstancePtr);
+ if (NS_FAILED(rv)) {
+ error:
+ *aInstancePtr = 0;
+ }
+
+ *mErrorPtr = rv;
+ return rv;
+}
+
+
+nsresult
+nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+{
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(kCategoryManagerCID, &rv);
+ if (NS_FAILED(rv)) goto error;
+ if (!mCategory || !mEntry) {
+ // when categories have defaults, use that for null mEntry
+ rv = NS_ERROR_NULL_POINTER;
+ goto error;
+ }
+ /* find the contractID for category.entry */
+ rv = catman->GetCategoryEntry(mCategory, mEntry,
+ getter_Copies(value));
+ if (NS_FAILED(rv)) goto error;
+ if (!value) {
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ goto error;
+ }
+ if (mServiceManager) {
+ rv = mServiceManager->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ rv = mgr->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
+ }
+ if (NS_FAILED(rv)) {
+ error:
+ *aInstancePtr = 0;
+ }
+ *mErrorPtr = rv;
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Arena helper functions
+////////////////////////////////////////////////////////////////////////////////
+char *
+ArenaStrndup(const char *s, PRUint32 len, PLArenaPool *arena)
+{
+ void *mem;
+ // Include trailing null in the len
+ PL_ARENA_ALLOCATE(mem, arena, len+1);
+ if (mem)
+ memcpy(mem, s, len+1);
+ return NS_STATIC_CAST(char *, mem);
+}
+
+char*
+ArenaStrdup(const char *s, PLArenaPool *arena)
+{
+ return ArenaStrndup(s, strlen(s), arena);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hashtable Callbacks
+////////////////////////////////////////////////////////////////////////////////
+
+PRBool PR_CALLBACK
+nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure);
+
+PR_STATIC_CALLBACK(const void *)
+factory_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+
+ return &entry->mFactoryEntry->mCid;
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+factory_HashKey(PLDHashTable *aTable, const void *aKey)
+{
+ const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
+
+ return cidp->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+factory_MatchEntry(PLDHashTable *aTable, const PLDHashEntryHdr *aHdr,
+ const void *aKey)
+{
+ const nsFactoryTableEntry* entry =
+ NS_STATIC_CAST(const nsFactoryTableEntry*, aHdr);
+ const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
+
+ return (entry->mFactoryEntry->mCid).Equals(*cidp);
+}
+
+PR_STATIC_CALLBACK(void)
+factory_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ entry->mFactoryEntry->~nsFactoryEntry();
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps factory_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ factory_GetKey,
+ factory_HashKey,
+ factory_MatchEntry,
+ PL_DHashMoveEntryStub,
+ factory_ClearEntry,
+ PL_DHashFinalizeStub,
+};
+
+PR_STATIC_CALLBACK(void)
+contractID_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+ if (entry->mFactoryEntry->mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY &&
+ entry->mFactoryEntry->mCid.Equals(kEmptyCID)) {
+ // this object is owned by the hash.
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ entry->mFactoryEntry->~nsFactoryEntry();
+ }
+
+ // contractIDs are arena allocated. No need to free them.
+
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps contractID_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ contractID_ClearEntry,
+ PL_DHashFinalizeStub,
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsFactoryEntry
+////////////////////////////////////////////////////////////////////////////////
+
+MOZ_DECL_CTOR_COUNTER(nsFactoryEntry)
+nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
+ const char *aLocation,
+ PRUint32 locationlen,
+ int aType,
+ class nsFactoryEntry* parent)
+: mCid(aClass), mTypeIndex(aType), mParent(parent)
+{
+ // Arena allocate the location string
+ mLocation = ArenaStrndup(aLocation, locationlen, &nsComponentManagerImpl::gComponentManager->mArena);
+}
+
+nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
+ nsIFactory *aFactory,
+ class nsFactoryEntry* parent)
+: mCid(aClass), mTypeIndex(NS_COMPONENT_TYPE_FACTORY_ONLY), mParent(parent)
+{
+ mFactory = aFactory;
+ mLocation = nsnull;
+}
+
+// nsFactoryEntry is usually arena allocated including the strings it
+// holds. So we call destructor by hand.
+nsFactoryEntry::~nsFactoryEntry(void)
+{
+ // Release the reference to the factory
+ mFactory = nsnull;
+
+ // Release any service reference
+ mServiceObject = nsnull;
+
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ if (mParent)
+ mParent->~nsFactoryEntry();
+}
+
+nsresult
+nsFactoryEntry::ReInit(const nsCID &aClass, const char *aLocation, int aType)
+{
+ NS_ENSURE_TRUE(mTypeIndex != NS_COMPONENT_TYPE_FACTORY_ONLY, NS_ERROR_INVALID_ARG);
+ // cid has to match
+ // SERVICE_ONLY entries can be promoted to an entry of another type
+ NS_ENSURE_TRUE((mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || mCid.Equals(aClass)),
+ NS_ERROR_INVALID_ARG);
+
+ // Arena allocate the location string
+ mLocation = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
+
+ mTypeIndex = aType;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hashtable Enumeration
+////////////////////////////////////////////////////////////////////////////////
+typedef NS_CALLBACK(EnumeratorConverter)(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data,
+ nsISupports **retval);
+
+class PLDHashTableEnumeratorImpl : public nsIBidirectionalEnumerator,
+ public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIENUMERATOR
+ NS_DECL_NSIBIDIRECTIONALENUMERATOR
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ PLDHashTableEnumeratorImpl(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData);
+ PRInt32 Count() { return mCount; }
+private:
+ PLDHashTableEnumeratorImpl(); /* no implementation */
+
+ ~PLDHashTableEnumeratorImpl();
+ NS_IMETHODIMP ReleaseElements();
+
+ nsVoidArray mElements;
+ PRInt32 mCount, mCurrent;
+ PRMonitor* mMonitor;
+
+ struct Closure {
+ PRBool succeeded;
+ EnumeratorConverter converter;
+ void *data;
+ PLDHashTableEnumeratorImpl *impl;
+ };
+
+ static PLDHashOperator PR_CALLBACK Enumerator(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *data);
+};
+
+// static
+PLDHashOperator PR_CALLBACK
+PLDHashTableEnumeratorImpl::Enumerator(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *data)
+{
+ Closure *c = NS_REINTERPRET_CAST(Closure *, data);
+ nsISupports *converted;
+ if (NS_FAILED(c->converter(table, hdr, c->data, &converted)) ||
+ !c->impl->mElements.AppendElement(converted)) {
+ c->succeeded = PR_FALSE;
+ return PL_DHASH_STOP;
+ }
+
+ c->succeeded = PR_TRUE;
+ return PL_DHASH_NEXT;
+}
+
+PLDHashTableEnumeratorImpl::PLDHashTableEnumeratorImpl(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData)
+: mCurrent(0)
+{
+ mMonitor = nsAutoMonitor::NewMonitor("PLDHashTableEnumeratorImpl");
+ NS_ASSERTION(mMonitor, "NULL Monitor");
+
+ nsAutoMonitor mon(mMonitor);
+
+ Closure c = { PR_FALSE, converter, converterData, this };
+ mCount = PL_DHashTableEnumerate(table, Enumerator, &c);
+ if (!c.succeeded) {
+ ReleaseElements();
+ mCount = 0;
+ }
+}
+
+NS_IMPL_ISUPPORTS3(PLDHashTableEnumeratorImpl,
+ nsIBidirectionalEnumerator,
+ nsIEnumerator,
+ nsISimpleEnumerator)
+
+PLDHashTableEnumeratorImpl::~PLDHashTableEnumeratorImpl()
+{
+ (void) ReleaseElements();
+
+ // Destroy the Lock
+ if (mMonitor)
+ nsAutoMonitor::DestroyMonitor(mMonitor);
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::ReleaseElements()
+{
+ for (PRInt32 i = 0; i < mCount; i++) {
+ nsISupports *supports = NS_REINTERPRET_CAST(nsISupports *,
+ mElements[i]);
+ NS_IF_RELEASE(supports);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PL_NewDHashTableEnumerator(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData,
+ PLDHashTableEnumeratorImpl **retval)
+{
+ PLDHashTableEnumeratorImpl *impl =
+ new PLDHashTableEnumeratorImpl(table, converter, converterData);
+
+ if (!impl)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(impl);
+
+ if (impl->Count() == -1) {
+ // conversion failed
+ NS_RELEASE(impl);
+ return NS_ERROR_FAILURE;
+ }
+
+ *retval = impl;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::First()
+{
+ if (!mCount)
+ return NS_ERROR_FAILURE;
+
+ mCurrent = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Last()
+{
+ if (!mCount)
+ return NS_ERROR_FAILURE;
+ mCurrent = mCount - 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Prev()
+{
+ if (!mCurrent)
+ return NS_ERROR_FAILURE;
+
+ mCurrent--;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Next()
+{
+ // If empty or we're past the end, or we are at the end return error
+ if (!mCount || (mCurrent == mCount) || (++mCurrent == mCount))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::CurrentItem(nsISupports **retval)
+{
+ if (!mCount || mCurrent == mCount)
+ return NS_ERROR_FAILURE;
+
+ *retval = NS_REINTERPRET_CAST(nsISupports *, mElements[mCurrent]);
+ if (*retval)
+ NS_ADDREF(*retval);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::IsDone()
+{
+ if (!mCount || (mCurrent == mCount))
+ return NS_OK;
+
+ return NS_ENUMERATOR_FALSE;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::HasMoreElements(PRBool *_retval)
+{
+ if (!mCount || (mCurrent == mCount))
+ *_retval = PR_FALSE;
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::GetNext(nsISupports **_retval)
+{
+ nsresult rv = Next();
+ if (NS_FAILED(rv)) return rv;
+
+ return CurrentItem(_retval);
+}
+
+static NS_IMETHODIMP
+ConvertFactoryEntryToCID(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data, nsISupports **retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupportsID> wrapper;
+
+ nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
+
+ rv = cm->CreateInstanceByContractID(NS_SUPPORTS_ID_CONTRACTID, nsnull,
+ NS_GET_IID(nsISupportsID), getter_AddRefs(wrapper));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const nsFactoryTableEntry *entry =
+ NS_REINTERPRET_CAST(const nsFactoryTableEntry *, hdr);
+ if (entry) {
+ nsFactoryEntry *fe = entry->mFactoryEntry;
+
+ wrapper->SetData(&fe->mCid);
+ *retval = wrapper;
+ NS_ADDREF(*retval);
+ return NS_OK;
+ }
+ *retval = nsnull;
+
+ return rv;
+}
+
+static NS_IMETHODIMP
+ConvertContractIDKeyToString(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data, nsISupports **retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupportsCString> wrapper;
+
+ nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
+
+ rv = cm->CreateInstanceByContractID(NS_SUPPORTS_CSTRING_CONTRACTID, nsnull,
+ NS_GET_IID(nsISupportsCString), getter_AddRefs(wrapper));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const nsContractIDTableEntry *entry =
+ NS_REINTERPRET_CAST(const nsContractIDTableEntry *, hdr);
+
+ wrapper->SetData(nsDependentCString(entry->mContractID,
+ entry->mContractIDLen));
+ *retval = wrapper;
+ NS_ADDREF(*retval);
+ return NS_OK;
+}
+
+// this is safe to call during InitXPCOM
+static nsresult GetLocationFromDirectoryService(const char* prop,
+ nsIFile** aDirectory)
+{
+ nsCOMPtr<nsIProperties> directoryService;
+ nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(directoryService));
+
+ if (!directoryService)
+ return NS_ERROR_FAILURE;
+
+ return directoryService->Get(prop,
+ NS_GET_IID(nsIFile),
+ (void**)aDirectory);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsComponentManagerImpl
+////////////////////////////////////////////////////////////////////////////////
+
+
+nsComponentManagerImpl::nsComponentManagerImpl()
+ :
+ mMon(NULL),
+ mNativeComponentLoader(0),
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ mStaticComponentLoader(0),
+#endif
+ mShuttingDown(NS_SHUTDOWN_NEVERHAPPENED),
+ mLoaderData(nsnull),
+ mRegistryDirty(PR_FALSE)
+{
+ mFactories.ops = nsnull;
+ mContractIDs.ops = nsnull;
+}
+
+nsresult nsComponentManagerImpl::Init(void)
+{
+ PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS);
+ if (mShuttingDown == NS_SHUTDOWN_INPROGRESS)
+ return NS_ERROR_FAILURE;
+
+ mShuttingDown = NS_SHUTDOWN_NEVERHAPPENED;
+
+ if (nsComponentManagerLog == nsnull)
+ {
+ nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
+ }
+
+ // Initialize our arena
+ PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
+
+ if (!mFactories.ops) {
+ if (!PL_DHashTableInit(&mFactories, &factory_DHashTableOps,
+ 0, sizeof(nsFactoryTableEntry),
+ 1024)) {
+ mFactories.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Minimum alpha uses k=2 because nsFactoryTableEntry saves two
+ // words compared to what a chained hash table requires.
+ PL_DHashTableSetAlphaBounds(&mFactories,
+ 0.875,
+ PL_DHASH_MIN_ALPHA(&mFactories, 2));
+ }
+
+ if (!mContractIDs.ops) {
+ if (!PL_DHashTableInit(&mContractIDs, &contractID_DHashTableOps,
+ 0, sizeof(nsContractIDTableEntry),
+ 1024)) {
+ mContractIDs.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Minimum alpha uses k=1 because nsContractIDTableEntry saves one
+ // word compared to what a chained hash table requires.
+#if 0
+ PL_DHashTableSetAlphaBounds(&mContractIDs,
+ 0.875,
+ PL_DHASH_MIN_ALPHA(&mContractIDs, 1));
+#endif
+ }
+ if (mMon == nsnull) {
+ mMon = nsAutoMonitor::NewMonitor("nsComponentManagerImpl");
+ if (mMon == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (mNativeComponentLoader == nsnull) {
+ /* Create the NativeComponentLoader */
+ mNativeComponentLoader = new nsNativeComponentLoader();
+ if (!mNativeComponentLoader)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(mNativeComponentLoader);
+
+ nsresult rv = mNativeComponentLoader->Init(this, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Add predefined loaders
+ mLoaderData = (nsLoaderdata *) PR_Malloc(sizeof(nsLoaderdata) * NS_LOADER_DATA_ALLOC_STEP);
+ if (!mLoaderData)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mMaxNLoaderData = NS_LOADER_DATA_ALLOC_STEP;
+
+ mNLoaderData = NS_COMPONENT_TYPE_NATIVE;
+ mLoaderData[mNLoaderData].type = PL_strdup(nativeComponentType);
+ mLoaderData[mNLoaderData].loader = mNativeComponentLoader;
+ NS_ADDREF(mLoaderData[mNLoaderData].loader);
+ mNLoaderData++;
+
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ if (mStaticComponentLoader == nsnull) {
+ extern nsresult NS_NewStaticComponentLoader(nsIComponentLoader **);
+ NS_NewStaticComponentLoader(&mStaticComponentLoader);
+ if (!mStaticComponentLoader)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ mLoaderData[mNLoaderData].type = PL_strdup(staticComponentType);
+ mLoaderData[mNLoaderData].loader = mStaticComponentLoader;
+ NS_ADDREF(mLoaderData[mNLoaderData].loader);
+ mNLoaderData++;
+
+ if (mStaticComponentLoader) {
+ /* Init the static loader */
+ mStaticComponentLoader->Init(this, nsnull);
+ }
+#endif
+ GetLocationFromDirectoryService(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(mComponentsDir));
+ if (!mComponentsDir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCAutoString componentDescriptor;
+ nsresult rv = mComponentsDir->GetNativePath(componentDescriptor);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mComponentsOffset = componentDescriptor.Length();
+
+ GetLocationFromDirectoryService(NS_GRE_COMPONENT_DIR, getter_AddRefs(mGREComponentsDir));
+ if (mGREComponentsDir) {
+ nsresult rv = mGREComponentsDir->GetNativePath(componentDescriptor);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("No GRE component manager");
+ return rv;
+ }
+ mGREComponentsOffset = componentDescriptor.Length();
+ }
+
+ GetLocationFromDirectoryService(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ getter_AddRefs(mRegistryFile));
+
+ if(!mRegistryFile) {
+ NS_WARNING("No Component Registry file was found in the directory service");
+ return NS_ERROR_FAILURE;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsComponentManager: Initialized."));
+
+ return NS_OK;
+}
+
+PRIntn PR_CALLBACK AutoRegEntryDestroy(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ delete (AutoRegEntry*)aData;
+ return kHashEnumerateNext;
+}
+
+nsresult nsComponentManagerImpl::Shutdown(void)
+{
+ PR_ASSERT(mShuttingDown == NS_SHUTDOWN_NEVERHAPPENED);
+ if (mShuttingDown != NS_SHUTDOWN_NEVERHAPPENED)
+ return NS_ERROR_FAILURE;
+
+ mShuttingDown = NS_SHUTDOWN_INPROGRESS;
+
+ // Shutdown the component manager
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
+
+ PRInt32 i;
+
+ // Write out our component data file.
+ if (mRegistryDirty) {
+ nsresult rv = WritePersistentRegistry();
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, ("nsComponentManager: Could not write out perisistant registry."));
+#ifdef DEBUG
+ printf("Could not write out perisistant registry!\n");
+#endif
+ }
+ }
+
+ mAutoRegEntries.Reset(AutoRegEntryDestroy);
+
+ // Release all cached factories
+ if (mContractIDs.ops) {
+ PL_DHashTableFinish(&mContractIDs);
+ mContractIDs.ops = nsnull;
+ }
+ if (mFactories.ops) {
+ PL_DHashTableFinish(&mFactories);
+ mFactories.ops = nsnull;
+ }
+ // Unload libraries
+ UnloadLibraries(nsnull, NS_Shutdown);
+
+ // delete arena for strings and small objects
+ PL_FinishArenaPool(&mArena);
+
+ mComponentsDir = 0;
+
+ mCategoryManager = 0;
+
+ // Release all the component data - loaders and type strings
+ for (i=0; i < mNLoaderData; i++) {
+ NS_IF_RELEASE(mLoaderData[i].loader);
+ PL_strfree((char *)mLoaderData[i].type);
+ }
+ PR_Free(mLoaderData);
+ mLoaderData = nsnull;
+
+ // we have an extra reference on this one, which is probably a good thing
+ NS_IF_RELEASE(mNativeComponentLoader);
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ NS_IF_RELEASE(mStaticComponentLoader);
+#endif
+
+ mShuttingDown = NS_SHUTDOWN_COMPLETE;
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete."));
+
+ return NS_OK;
+}
+
+nsComponentManagerImpl::~nsComponentManagerImpl()
+{
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
+
+ if (mShuttingDown != NS_SHUTDOWN_COMPLETE)
+ Shutdown();
+
+ if (mMon) {
+ nsAutoMonitor::DestroyMonitor(mMon);
+ }
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS8(nsComponentManagerImpl,
+ nsIComponentManager,
+ nsIServiceManager,
+ nsISupportsWeakReference,
+ nsIInterfaceRequestor,
+ nsIComponentRegistrar,
+ nsIServiceManagerObsolete,
+ nsIComponentManagerObsolete,
+ nsIComponentLoaderManager)
+
+
+nsresult
+nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
+{
+ if (uuid.Equals(NS_GET_IID(nsINativeComponentLoader)))
+ {
+ if (!mNativeComponentLoader)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ return mNativeComponentLoader->QueryInterface(uuid, result);
+ }
+
+ NS_WARNING("This isn't supported");
+ // fall through to QI as anything QIable is a superset of what can be
+ // got via the GetInterface()
+ return QueryInterface(uuid, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsComponentManagerImpl: Platform methods
+////////////////////////////////////////////////////////////////////////////////
+
+#define PERSISTENT_REGISTRY_VERSION_MINOR 5
+#define PERSISTENT_REGISTRY_VERSION_MAJOR 0
+
+
+AutoRegEntry::AutoRegEntry(const nsACString& name, PRInt64* modDate) :
+ mName(ToNewCString(name)),
+ mNameLen(name.Length()),
+ mData(nsnull),
+ mModDate(*modDate)
+{
+}
+
+AutoRegEntry::~AutoRegEntry()
+{
+ if (mName) PL_strfree(mName);
+ if (mData) PL_strfree(mData);
+}
+
+PRBool
+AutoRegEntry::Modified(PRInt64 *date)
+{
+ return !LL_EQ(*date, mModDate);
+}
+
+void
+AutoRegEntry::SetOptionalData(const char* data)
+{
+ if (mData)
+ PL_strfree(mData);
+
+ if (!data) {
+ mData = nsnull;
+ return;
+ }
+
+ mData = PL_strdup(data);
+}
+
+static
+PRBool ReadSectionHeader(nsManifestLineReader& reader, const char *token)
+{
+ while (1)
+ {
+ if (*reader.LinePtr() == '[')
+ {
+ char* p = reader.LinePtr() + (reader.LineLength() - 1);
+ if (*p != ']')
+ break;
+ *p = 0;
+
+ char* values[1];
+ int lengths[1];
+ if (2 != reader.ParseLine(values, lengths, 1))
+ break;
+
+ // ignore the leading '['
+ if (0 != PL_strcmp(values[0]+1, token))
+ break;
+
+ return PR_TRUE;
+ }
+
+ if (!reader.NextLine())
+ break;
+ }
+ return PR_FALSE;
+}
+
+nsresult
+nsComponentManagerImpl::ReadPersistentRegistry()
+{
+
+ // populate Category Manager. need to get this early so that we don't get
+ // skipped by 'goto out'
+ nsresult rv = GetService(kCategoryManagerCID,
+ NS_GET_IID(nsICategoryManager),
+ getter_AddRefs(mCategoryManager));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoMonitor mon(mMon);
+ nsManifestLineReader reader;
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED; // this should have been set by Init().
+
+ PRFileDesc* fd = nsnull;
+
+ // Set From Init
+ if (!mRegistryFile) {
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ mRegistryFile->Clone(getter_AddRefs(file));
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
+
+ rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fileSize;
+ rv = localFile->GetFileSize(&fileSize);
+ if (NS_FAILED(rv))
+ {
+ PR_Close(fd);
+ return rv;
+ }
+
+ PRInt32 flen = nsInt64(fileSize);
+ if (flen == 0)
+ {
+ PR_Close(fd);
+ NS_WARNING("Persistent Registry Empty!");
+ return NS_OK; // ERROR CONDITION
+ }
+
+ char* registry = new char[flen+1];
+ if (!registry)
+ goto out;
+
+ if (flen > PR_Read(fd, registry, flen))
+ {
+ rv = NS_ERROR_FAILURE;
+ goto out;
+ }
+ registry[flen] = '\0';
+
+ reader.Init(registry, flen);
+
+ if (ReadSectionHeader(reader, "HEADER"))
+ goto out;
+
+ if (!reader.NextLine())
+ goto out;
+
+ char* values[6];
+ int lengths[6];
+
+ // VersionLiteral,major,minor
+ if (3 != reader.ParseLine(values, lengths, 3))
+ goto out;
+
+ // VersionLiteral
+ if (!nsDependentCString(values[0], lengths[0]).EqualsLiteral("Version"))
+ goto out;
+
+ // major
+ if (PERSISTENT_REGISTRY_VERSION_MAJOR != atoi(values[1]))
+ goto out;
+
+ // minor
+ if (PERSISTENT_REGISTRY_VERSION_MINOR != atoi(values[2]))
+ goto out;
+
+ if (ReadSectionHeader(reader, "COMPONENTS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //name,last_modification_date[,optionaldata]
+ int parts = reader.ParseLine(values, lengths, 3);
+ if (2 > parts)
+ break;
+
+ PRInt64 a = nsCRT::atoll(values[1]);
+ AutoRegEntry *entry =
+ new AutoRegEntry(nsDependentCString(values[0], lengths[0]), &a);
+
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (parts == 3)
+ entry->SetOptionalData(values[2]);
+
+ nsCStringKey key((const char*)values[0]);
+ mAutoRegEntries.Put(&key, entry);
+ }
+
+ if (ReadSectionHeader(reader, "CLASSIDS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ // cid,contract_id,type,class_name,inproc_server
+ if (5 != reader.ParseLine(values, lengths, 5))
+ break;
+
+ nsCID aClass;
+ if (!aClass.Parse(values[0]))
+ continue;
+
+ int loadertype = GetLoaderType(values[2]);
+ if (loadertype < 0) {
+ rv = AddLoaderType(values[2], &loadertype);
+ if (NS_FAILED(rv))
+ continue;
+ }
+
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsFactoryEntry *entry = new (mem) nsFactoryEntry(aClass, values[4], lengths[4], loadertype);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories,
+ &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+
+ }
+
+ if (ReadSectionHeader(reader, "CONTRACTIDS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //contractID,cid
+ if (2 != reader.ParseLine(values, lengths, 2))
+ break;
+
+ nsCID aClass;
+ if (!aClass.Parse(values[1]))
+ continue;
+
+
+ //need to find the location for this cid.
+ nsFactoryEntry *cidEntry = GetFactoryEntry(aClass);
+ if (!cidEntry || cidEntry->mTypeIndex < 0)
+ continue; //what should we really do?
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs,
+ values[0],
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry) {
+ continue;
+ }
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID = ArenaStrndup(values[0], lengths[0], &mArena);
+ contractIDTableEntry->mContractIDLen = lengths[0];
+ }
+
+ contractIDTableEntry->mFactoryEntry = cidEntry;
+ }
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ {
+/*
+ * If you get Asserts when you define SHOW_CI_ON_EXISTING_SERVICE and want to
+ * track down their cause, then you should add the contracts listed by the
+ * assertion to abusedContracts. The next time you run your xpcom app, xpcom
+ * will assert the first time the object associated with the contract is
+ * instantiated (which in many cases is the source of the problem).
+ *
+ * If you're doing this then you might want to NOP and soft breakpoint the
+ * lines labeled: NOP_AND_BREAK.
+ *
+ * Otherwise XPCOM will refuse to create the object for the caller, which
+ * while reasonable at some level, will almost certainly cause the app to
+ * stop functioning normally.
+ */
+ static char abusedContracts[][128] = {
+ /*// Example contracts:
+ "@mozilla.org/rdf/container;1",
+ "@mozilla.org/intl/charsetalias;1",
+ "@mozilla.org/locale/win32-locale;1",
+ "@mozilla.org/widget/lookandfeel/win;1",
+ // */
+ { 0 }
+ };
+ for (int i=0; abusedContracts[i] && *abusedContracts[i]; i++) {
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, abusedContracts[i],
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ AddPendingCID(entry->mCid);
+ }
+ }
+ }
+#endif
+
+ if (ReadSectionHeader(reader, "CATEGORIES"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //type,name,value
+ if (3 != reader.ParseLine(values, lengths, 3))
+ break;
+
+ mCategoryManager->AddCategoryEntry(values[0],
+ values[1],
+ values[2],
+ PR_TRUE,
+ PR_TRUE,
+ 0);
+ }
+
+ mRegistryDirty = PR_FALSE;
+out:
+ if (fd)
+ PR_Close(fd);
+
+ if (registry)
+ delete [] registry;
+
+ return rv;
+}
+
+struct PersistentWriterArgs
+{
+ PRFileDesc *mFD;
+ nsLoaderdata *mLoaderData;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+ContractIDWriter(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg)
+{
+ char *contractID = ((nsContractIDTableEntry*)hdr)->mContractID;
+ nsFactoryEntry *factoryEntry = ((nsContractIDTableEntry*)hdr)->mFactoryEntry;
+
+ // for now, we only save out the top most parent.
+ while (factoryEntry->mParent)
+ factoryEntry = factoryEntry->mParent;
+
+ if (factoryEntry->mTypeIndex < 0)
+ return PL_DHASH_NEXT;
+
+ PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
+
+ char cidString[UID_STRING_LENGTH];
+ GetIDString(factoryEntry->mCid, cidString);
+ PR_fprintf(fd, "%s,%s\n", contractID, cidString); // what if this fails?
+ return PL_DHASH_NEXT;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+ClassIDWriter(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg)
+{
+ nsFactoryEntry *factoryEntry = ((nsFactoryTableEntry*)hdr)->mFactoryEntry;
+ PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
+ nsLoaderdata *loaderData = ((PersistentWriterArgs*)arg)->mLoaderData;
+
+ // for now, we only save out the top most parent.
+ while (factoryEntry->mParent)
+ factoryEntry = factoryEntry->mParent;
+
+ if (factoryEntry->mTypeIndex < 0) {
+ return PL_DHASH_NEXT;
+ }
+
+ char cidString[UID_STRING_LENGTH];
+ GetIDString(factoryEntry->mCid, cidString);
+
+ char *contractID = nsnull, *className = nsnull;
+
+ nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(factoryEntry->mFactory);
+ if (classInfo)
+ {
+ classInfo->GetContractID(&contractID);
+ classInfo->GetClassDescription(&className);
+ }
+
+ const char * loaderName = nsnull;
+ if (factoryEntry->mTypeIndex)
+ loaderName = loaderData[factoryEntry->mTypeIndex].type;
+
+ char* location = factoryEntry->mLocation;
+
+ // cid,contract_id,type,class_name,inproc_server
+ PR_fprintf(fd,
+ "%s,%s,%s,%s,%s\n",
+ cidString,
+ (contractID ? contractID : ""),
+ (loaderName ? loaderName : ""),
+ (className ? className : ""),
+ (location ? location : ""));
+
+ if (contractID)
+ PR_Free(contractID);
+ if (className)
+ PR_Free(className);
+
+ return PL_DHASH_NEXT;
+}
+
+PRIntn PR_CALLBACK
+AutoRegEntryWriter(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ PRFileDesc* fd = (PRFileDesc*) aClosure;
+ AutoRegEntry* entry = (AutoRegEntry*) aData;
+
+ const char* extraData = entry->GetOptionalData();
+ const char *fmt;
+ if (extraData)
+ fmt = "%s,%lld,%s\n";
+ else
+ fmt = "%s,%lld\n";
+ PR_fprintf(fd, fmt, entry->GetName().get(), entry->GetDate(), extraData);
+
+ return PR_TRUE;
+}
+
+nsresult
+nsComponentManagerImpl::WritePersistentRegistry()
+{
+ if (!mRegistryFile)
+ return NS_ERROR_FAILURE; // this should have been set by Init().
+
+ nsCOMPtr<nsIFile> file;
+ mRegistryFile->Clone(getter_AddRefs(file));
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
+
+ nsCAutoString originalLeafName;
+ localFile->GetNativeLeafName(originalLeafName);
+
+ nsCAutoString leafName;
+ leafName.Assign(originalLeafName + NS_LITERAL_CSTRING(".tmp"));
+
+ localFile->SetNativeLeafName(leafName);
+
+ PRFileDesc* fd = nsnull;
+ nsresult rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (PR_fprintf(fd, "Generated File. Do not edit.\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ if (PR_fprintf(fd, "\n[HEADER]\nVersion,%d,%d\n",
+ PERSISTENT_REGISTRY_VERSION_MAJOR,
+ PERSISTENT_REGISTRY_VERSION_MINOR) == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ if (PR_fprintf(fd, "\n[COMPONENTS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ mAutoRegEntries.Enumerate(AutoRegEntryWriter, (void*)fd);
+
+ PersistentWriterArgs args;
+ args.mFD = fd;
+ args.mLoaderData = mLoaderData;
+
+ if (PR_fprintf(fd, "\n[CLASSIDS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ PL_DHashTableEnumerate(&mFactories, ClassIDWriter, (void*)&args);
+
+ if (PR_fprintf(fd, "\n[CONTRACTIDS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ PL_DHashTableEnumerate(&mContractIDs, ContractIDWriter, (void*)&args);
+
+ if (PR_fprintf(fd, "\n[CATEGORIES]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ if (!mCategoryManager) {
+ NS_WARNING("Could not access category manager. Will not be able to save categories!");
+ rv = NS_ERROR_UNEXPECTED;
+ } else {
+ rv = mCategoryManager->WriteCategoryManagerToRegistry(fd);
+ }
+
+out:
+ if (fd)
+ PR_Close(fd);
+
+ // don't create the file is there was a problem????
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mRegistryFile)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ PRBool exists;
+ if(NS_FAILED(mRegistryFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(mRegistryFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> parent;
+ mRegistryFile->GetParent(getter_AddRefs(parent));
+
+ rv = localFile->MoveToNative(parent, originalLeafName);
+ mRegistryDirty = PR_FALSE;
+
+ return rv;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Hash Functions
+////////////////////////////////////////////////////////////////////////////////
+nsresult
+nsComponentManagerImpl::HashContractID(const char *aContractID,
+ PRUint32 aContractIDLen,
+ nsFactoryEntry *fe)
+{
+ if(!aContractID || !aContractIDLen)
+ return NS_ERROR_NULL_POINTER;
+
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(!contractIDTableEntry->mContractID || !strcmp(contractIDTableEntry->mContractID, aContractID), "contractid conflict");
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID = ArenaStrndup(aContractID, aContractIDLen, &mArena);
+ contractIDTableEntry->mContractIDLen = aContractIDLen;
+ }
+
+ contractIDTableEntry->mFactoryEntry = fe;
+
+ return NS_OK;
+}
+
+/**
+ * LoadFactory()
+ *
+ * Given a FactoryEntry, this loads the dll if it has to, find the NSGetFactory
+ * symbol, calls the routine to create a new factory and returns it to the
+ * caller.
+ *
+ * No attempt is made to store the factory in any form anywhere.
+ */
+nsresult
+nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
+ nsIFactory **aFactory)
+{
+
+ if (!aFactory)
+ return NS_ERROR_NULL_POINTER;
+ *aFactory = nsnull;
+
+ nsresult rv;
+ rv = aEntry->GetFactory(aFactory, this);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsComponentManager: FAILED to load factory from %s (%s)\n",
+ (const char *)aEntry->mLocation, mLoaderData[aEntry->mTypeIndex].type));
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+nsFactoryEntry *
+nsComponentManagerImpl::GetFactoryEntry(const char *aContractID,
+ PRUint32 aContractIDLen)
+{
+ nsFactoryEntry *fe = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ fe = contractIDTableEntry->mFactoryEntry;
+ }
+ } //exit monitor
+
+ return fe;
+}
+
+
+nsFactoryEntry *
+nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass)
+{
+ nsFactoryEntry *entry = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+ } // exit monitor
+
+ return entry;
+}
+
+
+/**
+ * FindFactory()
+ *
+ * Given a classID, this finds the factory for this CID by first searching the
+ * local CID<->factory mapping. Next it searches for a Dll that implements
+ * this classID and calls LoadFactory() to create the factory.
+ *
+ * Again, no attempt is made at storing the factory.
+ */
+nsresult
+nsComponentManagerImpl::FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory)
+{
+ PR_ASSERT(aFactory != nsnull);
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ return entry->GetFactory(aFactory, this);
+}
+
+
+nsresult
+nsComponentManagerImpl::FindFactory(const char *contractID,
+ PRUint32 aContractIDLen,
+ nsIFactory **aFactory)
+{
+ PR_ASSERT(aFactory != nsnull);
+
+ nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ return entry->GetFactory(aFactory, this);
+}
+
+/**
+ * GetClassObject()
+ *
+ * Given a classID, this finds the singleton ClassObject that implements the CID.
+ * Returns an interface of type aIID off the singleton classobject.
+ */
+nsresult
+nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFactory> factory;
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
+ {
+ char *buf = aClass.ToString();
+ PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ PR_ASSERT(aResult != nsnull);
+
+ rv = FindFactory(aClass, getter_AddRefs(factory));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = factory->QueryInterface(aIID, aResult);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+
+nsresult
+nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFactory> factory;
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
+ {
+ PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
+ }
+#endif
+
+ PR_ASSERT(aResult != nsnull);
+
+ rv = FindFactory(contractID, strlen(contractID), getter_AddRefs(factory));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = factory->QueryInterface(aIID, aResult);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+/**
+ * ContractIDToClassID()
+ *
+ * Mapping function from a ContractID to a classID. Directly talks to the registry.
+ *
+ */
+nsresult
+nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aClass)
+{
+ NS_PRECONDITION(aContractID != nsnull, "null ptr");
+ if (!aContractID)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aClass != nsnull, "null ptr");
+ if (!aClass)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ nsFactoryEntry *fe = GetFactoryEntry(aContractID, strlen(aContractID));
+ if (fe) {
+ *aClass = fe->mCid;
+ rv = NS_OK;
+ }
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING)) {
+ char *buf = 0;
+ if (NS_SUCCEEDED(rv))
+ buf = aClass->ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: ContractIDToClassID(%s)->%s", aContractID,
+ NS_SUCCEEDED(rv) ? buf : "[FAILED]"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ return rv;
+}
+
+/**
+ * CLSIDToContractID()
+ *
+ * Translates a classID to a {ContractID, Class Name}. Does direct registry
+ * access to do the translation.
+ *
+ * NOTE: Since this isn't heavily used, we arent caching this.
+ */
+nsresult
+nsComponentManagerImpl::CLSIDToContractID(const nsCID &aClass,
+ char* *aClassName,
+ char* *aContractID)
+{
+ NS_WARNING("Need to implement CLSIDToContractID");
+
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CLSIDToContractID(%s)->%s", buf,
+ NS_SUCCEEDED(rv) ? *aContractID : "[FAILED]"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ return rv;
+}
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+
+// This method must be called from within the mMon monitor
+nsresult
+nsComponentManagerImpl::AddPendingCID(const nsCID &aClass)
+{
+ int max = mPendingCIDs.Count();
+ for (int index = 0; index < max; index++)
+ {
+ nsCID *cidp = (nsCID*) mPendingCIDs.ElementAt(index);
+ NS_ASSERTION(cidp, "Bad CID in pending list");
+ if (cidp->Equals(aClass)) {
+ nsXPIDLCString cid;
+ cid.Adopt(aClass.ToString());
+ nsCAutoString message;
+ message = NS_LITERAL_CSTRING("Creation of \"") +
+ cid + NS_LITERAL_CSTRING("\" in progress (Reentrant GS - see bug 194568)");
+ // Note that you may see this assertion by near-simultaneous
+ // calls to GetService on multiple threads.
+ NS_WARNING(message.get());
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ }
+ mPendingCIDs.AppendElement((void*)&aClass);
+ return NS_OK;
+}
+
+// This method must be called from within the mMon monitor
+void
+nsComponentManagerImpl::RemovePendingCID(const nsCID &aClass)
+{
+ mPendingCIDs.RemoveElement((void*)&aClass);
+}
+#endif
+/**
+ * CreateInstance()
+ *
+ * Create an instance of an object that implements an interface and belongs
+ * to the implementation aClass using the factory. The factory is immediately
+ * released and not held onto for any longer.
+ */
+nsresult
+nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ // test this first, since there's no point in creating a component during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (aResult == nsnull)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aResult = nsnull;
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+#ifdef SHOW_CI_ON_EXISTING_SERVICE
+ if (entry->mServiceObject) {
+ nsXPIDLCString cid;
+ cid.Adopt(aClass.ToString());
+ nsCAutoString message;
+ message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
+ cid + NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
+ NS_ERROR(message.get());
+ }
+#endif
+
+ nsIFactory *factory = nsnull;
+ nsresult rv = entry->GetFactory(&factory, this);
+
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = factory->CreateInstance(aDelegate, aIID, aResult);
+ NS_RELEASE(factory);
+ }
+ else
+ {
+ // Translate error values
+ rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CreateInstance(%s) %s", buf,
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ return rv;
+}
+
+/**
+ * CreateInstanceByContractID()
+ *
+ * A variant of CreateInstance() that creates an instance of the object that
+ * implements the interface aIID and whose implementation has a contractID aContractID.
+ *
+ * This is only a convenience routine that turns around can calls the
+ * CreateInstance() with classid and iid.
+ */
+nsresult
+nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ // test this first, since there's no point in creating a component during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (aResult == nsnull)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aResult = nsnull;
+
+ nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID));
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+#ifdef SHOW_CI_ON_EXISTING_SERVICE
+ if (entry->mServiceObject) {
+ nsCAutoString message;
+ message =
+ NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
+ nsDependentCString(aContractID) +
+ NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
+ "Add it to abusedContracts to track down the service consumer.");
+ NS_ERROR(message.get());
+ }
+#endif
+
+ nsIFactory *factory = nsnull;
+ nsresult rv = entry->GetFactory(&factory, this);
+
+ if (NS_SUCCEEDED(rv))
+ {
+
+ rv = factory->CreateInstance(aDelegate, aIID, aResult);
+ NS_RELEASE(factory);
+ }
+ else
+ {
+ // Translate error values
+ if (rv != NS_ERROR_SOCKET_FAIL)
+ rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+// Service Manager Impl
+static
+PLDHashOperator PR_CALLBACK
+FreeServiceFactoryEntryEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ factoryEntry->mServiceObject = nsnull;
+ return PL_DHASH_NEXT;
+}
+
+static
+PLDHashOperator PR_CALLBACK
+FreeServiceContractIDEntryEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ factoryEntry->mServiceObject = nsnull;
+ return PL_DHASH_NEXT;
+}
+
+nsresult
+nsComponentManagerImpl::FreeServices()
+{
+ NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
+
+ if (!gXPCOMShuttingDown)
+ return NS_ERROR_FAILURE;
+
+ if (mContractIDs.ops) {
+ PL_DHashTableEnumerate(&mContractIDs, FreeServiceContractIDEntryEnumerate, nsnull);
+ }
+
+
+ if (mFactories.ops) {
+ PL_DHashTableEnumerate(&mFactories, FreeServiceFactoryEntryEnumerate, nsnull);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const nsCID& aClass,
+ const nsIID& aIID,
+ void* *result)
+{
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Getting service on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoMonitor mon(mMon);
+
+ nsresult rv = NS_OK;
+ nsIDKey key(aClass);
+ nsFactoryEntry* entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && entry->mServiceObject) {
+ return entry->mServiceObject->QueryInterface(aIID, result);
+ }
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ rv = AddPendingCID(aClass);
+ if (NS_FAILED(rv))
+ return rv; // NOP_AND_BREAK
+#endif
+ nsCOMPtr<nsISupports> service;
+ // We need to not be holding the service manager's monitor while calling
+ // CreateInstance, because it invokes user code which could try to re-enter
+ // the service manager:
+ mon.Exit();
+
+ rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
+
+ mon.Enter();
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ RemovePendingCID(aClass);
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!entry) { // second hash lookup for GetService
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+ NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
+ if (!entry) return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = service;
+ *result = service.get();
+ NS_ADDREF(NS_STATIC_CAST(nsISupports*, (*result)));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterService(const nsCID& aClass, nsISupports* aService)
+{
+ nsAutoMonitor mon(mMon);
+
+ // check to see if we have a factory entry for the service
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry = new (mem) nsFactoryEntry(aClass, nsnull);
+
+ entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_ADD));
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+ }
+ else {
+ if (entry->mServiceObject)
+ return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = aService;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterService(const nsCID& aClass)
+{
+ nsresult rv = NS_OK;
+
+ nsFactoryEntry* entry = nsnull;
+
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (!entry || !entry->mServiceObject)
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+
+ entry->mServiceObject = nsnull;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterService(const char* aContractID, nsISupports* aService)
+{
+
+ nsAutoMonitor mon(mMon);
+
+ // check to see if we have a factory entry for the service
+ PRUint32 contractIDLen = strlen(aContractID);
+ nsFactoryEntry *entry = GetFactoryEntry(aContractID, contractIDLen);
+
+ if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry = new (mem) nsFactoryEntry(kEmptyCID, nsnull);
+
+ entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry) {
+ delete entry;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID =
+ ArenaStrndup(aContractID, contractIDLen, &mArena);
+
+ contractIDTableEntry->mContractIDLen = contractIDLen;
+ }
+
+ contractIDTableEntry->mFactoryEntry = entry;
+ }
+ else {
+ if (entry->mServiceObject)
+ return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = aService;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
+ const nsIID& aIID,
+ PRBool *result)
+{
+ // Now we want to get the service if we already got it. If not, we dont want
+ // to create an instance of it. mmh!
+
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Checking for service on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ nsFactoryEntry* entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && entry->mServiceObject) {
+ nsCOMPtr<nsISupports> service;
+ rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
+ *result = (service!=nsnull);
+ }
+ return rv;
+
+}
+
+NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
+ const nsIID& aIID,
+ PRBool *result)
+{
+ // Now we want to get the service if we already got it. If not, we dont want
+ // to create an instance of it. mmh!
+
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Checking for service on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ nsFactoryEntry *entry = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+ } // exit monitor
+
+ if (entry && entry->mServiceObject) {
+ nsCOMPtr<nsISupports> service;
+ rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
+ *result = (service!=nsnull);
+ }
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterService(const char* aContractID)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+
+ if (!entry || !entry->mServiceObject)
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+
+ entry->mServiceObject = nsnull;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
+ const nsIID& aIID,
+ void* *result)
+{
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Getting service on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoMonitor mon(mMon);
+
+ nsresult rv = NS_OK;
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+
+ if (entry) {
+ if (entry->mServiceObject) {
+ return entry->mServiceObject->QueryInterface(aIID, result);
+ }
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ rv = AddPendingCID(entry->mCid);
+ if (NS_FAILED(rv))
+ return rv; // NOP_AND_BREAK
+#endif
+ }
+
+ nsCOMPtr<nsISupports> service;
+ // We need to not be holding the service manager's monitor while calling
+ // CreateInstance, because it invokes user code which could try to re-enter
+ // the service manager:
+ mon.Exit();
+
+ rv = CreateInstanceByContractID(aContractID, nsnull, aIID, getter_AddRefs(service));
+
+ mon.Enter();
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ if (entry)
+ RemovePendingCID(entry->mCid);
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!entry) { // second hash lookup for GetService
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+ NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
+ if (!entry) return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = service;
+ *result = service.get();
+ NS_ADDREF(NS_STATIC_CAST(nsISupports*, *result));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+ return GetService(aClass, aIID, (void**)result);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+ return GetServiceByContractID(aContractID, aIID, (void**)result);
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+/*
+ * I want an efficient way to allocate a buffer to the right size
+ * and stick the prefix and dllName in, then be able to hand that buffer
+ * off to the FactoryEntry. Is that so wrong?
+ *
+ * *regName is allocated on success.
+ *
+ * This should live in nsNativeComponentLoader.cpp, I think.
+ */
+static nsresult
+MakeRegistryName(const char *aDllName, const char *prefix, char **regName)
+{
+ char *registryName;
+
+ PRUint32 len = strlen(prefix);
+
+ PRUint32 registryNameLen = strlen(aDllName) + len;
+ registryName = (char *)nsMemory::Alloc(registryNameLen + 1);
+
+ // from here on it, we want len sans terminating NUL
+
+ if (!registryName)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ memcpy(registryName, prefix, len);
+ strcpy(registryName + len, aDllName);
+ registryName[registryNameLen] = '\0';
+ *regName = registryName;
+
+#ifdef DEBUG_shaver_off
+ fprintf(stderr, "MakeRegistryName(%s, %s, &[%s])\n",
+ aDllName, prefix, *regName);
+#endif
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec,
+ char **aRegistryName)
+{
+ nsresult rv;
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ if (!aSpec) {
+ *aRegistryName = PL_strdup("");
+ return NS_OK;
+ }
+
+
+ // First check to see if this component is in the application
+ // components directory
+ PRBool containedIn;
+ mComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
+
+ nsCAutoString nativePathString;
+
+ if (containedIn){
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* relativeLocation = nativePathString.get() + mComponentsOffset + 1;
+ return MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX, aRegistryName);
+ }
+
+ // Next check to see if this component is in the GRE
+ // components directory
+
+ mGREComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
+
+ if (containedIn){
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* relativeLocation = nativePathString.get() + mGREComponentsOffset + 1;
+ return MakeRegistryName(relativeLocation, XPCOM_GRECOMPONENT_PREFIX, aRegistryName);
+ }
+
+ /* absolute names include volume info on Mac, so persistent descriptor */
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+ return MakeRegistryName(nativePathString.get(), XPCOM_ABSCOMPONENT_PREFIX, aRegistryName);
+}
+
+nsresult
+nsComponentManagerImpl::SpecForRegistryLocation(const char *aLocation,
+ nsIFile **aSpec)
+{
+ // i18n: assuming aLocation is encoded for the current locale
+
+ nsresult rv;
+ if (!aLocation || !aSpec)
+ return NS_ERROR_NULL_POINTER;
+
+ /* abs:/full/path/to/libcomponent.so */
+ if (!strncmp(aLocation, XPCOM_ABSCOMPONENT_PREFIX, 4)) {
+
+ nsLocalFile* file = new nsLocalFile;
+ if (!file) return NS_ERROR_FAILURE;
+
+ rv = file->InitWithNativePath(nsDependentCString((char *)aLocation + 4));
+ file->QueryInterface(NS_GET_IID(nsILocalFile), (void**)aSpec);
+ return rv;
+ }
+
+ if (!strncmp(aLocation, XPCOM_RELCOMPONENT_PREFIX, 4)) {
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsILocalFile* file = nsnull;
+ rv = mComponentsDir->Clone((nsIFile**)&file);
+
+ if (NS_FAILED(rv)) return rv;
+
+ rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
+ *aSpec = file;
+ return rv;
+ }
+
+ if (!strncmp(aLocation, XPCOM_GRECOMPONENT_PREFIX, 4)) {
+
+ if (!mGREComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsILocalFile* file = nsnull;
+ rv = mGREComponentsDir->Clone((nsIFile**)&file);
+
+ if (NS_FAILED(rv)) return rv;
+
+ rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
+ *aSpec = file;
+ return rv;
+ }
+
+ *aSpec = nsnull;
+ return NS_ERROR_INVALID_ARG;
+}
+
+/**
+ * RegisterFactory()
+ *
+ * Register a factory to be responsible for creation of implementation of
+ * classID aClass. Plus creates as association of aClassName and aContractID
+ * to the classID. If replace is PR_TRUE, we replace any existing registrations
+ * with this one.
+ *
+ * Once registration is complete, we add the class to the factories cache
+ * that we maintain. The factories cache is the ONLY place where these
+ * registrations are ever kept.
+ *
+ * The other RegisterFunctions create a loader mapping and persistent
+ * location, but we just slam it into the cache here. And we don't call the
+ * loader's OnRegister function, either.
+ */
+nsresult
+nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace)
+{
+ nsAutoMonitor mon(mMon);
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: RegisterFactory(%s, %s)", buf,
+ (aContractID ? aContractID : "(null)")));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ nsFactoryEntry *entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry = NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories,
+ &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && !aReplace)
+ {
+ // Already registered
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tFactory already registered."));
+ return NS_ERROR_FACTORY_EXISTS;
+ }
+
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ entry = new (mem) nsFactoryEntry(aClass, aFactory, entry);
+
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+
+ // Update the ContractID->CLSID Map
+ if (aContractID) {
+ nsresult rv = HashContractID(aContractID, strlen(aContractID), entry);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tFactory register succeeded. "
+ "Hashing contractid (%s) FAILED.", aContractID));
+ return rv;
+ }
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tFactory register succeeded contractid=%s.",
+ aContractID ? aContractID : "<none>"));
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ return RegisterComponentCommon(aClass, aClassName,
+ aContractID,
+ aContractID ? strlen(aContractID) : 0,
+ aPersistentDescriptor,
+ aPersistentDescriptor ?
+ strlen(aPersistentDescriptor) : 0,
+ aReplace, aPersist,
+ nativeComponentType);
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponentWithType(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aSpec,
+ const char *aLocation,
+ PRBool aReplace,
+ PRBool aPersist,
+ const char *aType)
+{
+ return RegisterComponentCommon(aClass, aClassName,
+ aContractID,
+ aContractID ? strlen(aContractID) : 0,
+ aLocation,
+ aLocation ? strlen(aLocation) : 0,
+ aReplace, aPersist,
+ aType);
+}
+
+/*
+ * Register a component, using whatever they stuck in the nsIFile.
+ */
+nsresult
+nsComponentManagerImpl::RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrarySpec,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = RegisterComponentWithType(aClass, aClassName,
+ aContractID,
+ aLibrarySpec,
+ registryName,
+ aReplace, aPersist,
+ nativeComponentType);
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aDllName,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ // deprecated and obsolete.
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/*
+ * Add a component to the known universe of components.
+
+ * Once we enter this function, we own aRegistryName, and must free it
+ * or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us
+ * sane.
+ */
+
+nsresult
+nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ PRUint32 aContractIDLen,
+ const char *aRegistryName,
+ PRUint32 aRegistryNameLen,
+ PRBool aReplace,
+ PRBool aPersist,
+ const char *aType)
+{
+ nsIDKey key(aClass);
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ // Normalize proid and classname
+ const char *contractID = (aContractID && *aContractID) ? aContractID : nsnull;
+ const char *className = (aClassName && *aClassName) ? aClassName : nsnull;
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: RegisterComponentCommon(%s, %s, %s, %s)",
+ buf,
+ contractID ? contractID : "(null)",
+ aRegistryName, aType));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ if (entry && !aReplace) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tFactory already registered."));
+ return NS_ERROR_FACTORY_EXISTS;
+ }
+
+ int typeIndex = GetLoaderType(aType);
+
+ nsCOMPtr<nsIComponentLoader> loader;
+ nsresult rv = GetLoaderForType(typeIndex, getter_AddRefs(loader));
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tgetting loader for %s FAILED\n", aType));
+ return rv;
+ }
+
+ if (entry) {
+ entry->ReInit(aClass, aRegistryName, typeIndex);
+ }
+ else {
+
+ // Arena allocate the nsFactoryEntry
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mRegistryDirty = PR_TRUE;
+ entry = new (mem) nsFactoryEntry(aClass,
+ aRegistryName, aRegistryNameLen,
+ typeIndex);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+ }
+
+ // Update the ContractID->CLSID Map
+ if (contractID) {
+ rv = HashContractID(contractID, aContractIDLen, entry);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tHashContractID(%s) FAILED\n", contractID));
+ return rv;
+ }
+ }
+ return rv;
+}
+
+
+nsresult
+nsComponentManagerImpl::GetLoaderForType(int aType,
+ nsIComponentLoader **aLoader)
+{
+ nsresult rv;
+
+ // Make sure we have a valid type
+ if (aType < 0 || aType >= mNLoaderData)
+ return NS_ERROR_INVALID_ARG;
+
+ *aLoader = mLoaderData[aType].loader;
+ if (*aLoader) {
+ NS_ADDREF(*aLoader);
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIComponentLoader> loader;
+ loader = do_GetServiceFromCategory("component-loader", mLoaderData[aType].type, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = loader->Init(this, nsnull);
+
+ if (NS_SUCCEEDED(rv)) {
+ mLoaderData[aType].loader = loader;
+ NS_ADDREF(mLoaderData[aType].loader);
+ *aLoader = loader;
+ NS_ADDREF(*aLoader);
+ }
+ return rv;
+}
+
+
+
+// Convert a loader type string into an index into the component data
+// array. Empty loader types are converted to NATIVE. Returns -1 if
+// loader type cannot be determined.
+int
+nsComponentManagerImpl::GetLoaderType(const char *typeStr)
+{
+ if (!typeStr || !*typeStr) {
+ // Empty type strings are NATIVE
+ return NS_COMPONENT_TYPE_NATIVE;
+ }
+
+ for (int i=NS_COMPONENT_TYPE_NATIVE; i<mNLoaderData; i++) {
+ if (!strcmp(typeStr, mLoaderData[i].type))
+ return i;
+ }
+ // Not found
+ return NS_COMPONENT_TYPE_FACTORY_ONLY;
+}
+
+// Add a loader type if not already known. Out the typeIndex
+// if the loader type is either added or already there.
+nsresult
+nsComponentManagerImpl::AddLoaderType(const char *typeStr, int *aTypeIndex)
+{
+ int typeIndex = GetLoaderType(typeStr);
+ if (typeIndex >= 0) {
+ *aTypeIndex = typeIndex;
+ return NS_OK;
+ }
+
+ // Add the loader type
+ if (mNLoaderData >= mMaxNLoaderData) {
+ NS_ASSERTION(mNLoaderData == mMaxNLoaderData,
+ "Memory corruption. nsComponentManagerImpl::mLoaderData array overrun.");
+ // Need to increase our loader array
+ nsLoaderdata *new_mLoaderData = (nsLoaderdata *) PR_Realloc(mLoaderData, (mMaxNLoaderData + NS_LOADER_DATA_ALLOC_STEP) * sizeof(nsLoaderdata));
+ if (!new_mLoaderData)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mLoaderData = new_mLoaderData;
+ mMaxNLoaderData += NS_LOADER_DATA_ALLOC_STEP;
+ }
+
+ typeIndex = mNLoaderData;
+ mLoaderData[typeIndex].type = PL_strdup(typeStr);
+ if (!mLoaderData[typeIndex].type) {
+ // mmh! no memory. return failure.
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mLoaderData[typeIndex].loader = nsnull;
+ mNLoaderData++;
+
+ *aTypeIndex = typeIndex;
+ return NS_OK;
+}
+
+typedef struct
+{
+ const nsCID* cid;
+ const char* regName;
+ nsIFactory* factory;
+} UnregisterConditions;
+
+static PLDHashOperator PR_CALLBACK
+DeleteFoundCIDs(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ UnregisterConditions* data = (UnregisterConditions*)aData;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ if (data->cid->Equals(factoryEntry->mCid) &&
+ ((data->regName && !PL_strcasecmp(factoryEntry->mLocation, data->regName)) ||
+ (data->factory && data->factory == factoryEntry->mFactory.get())))
+ return PL_DHASH_REMOVE;
+
+ return PL_DHASH_NEXT;
+}
+
+void
+nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName)
+{
+ UnregisterConditions aData;
+ aData.cid = aClass;
+ aData.regName = registryName;
+ aData.factory = nsnull;
+ PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
+
+}
+
+void
+nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory)
+{
+ UnregisterConditions aData;
+ aData.cid = aClass;
+ aData.regName = nsnull;
+ aData.factory = factory;
+ PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory)
+{
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: UnregisterFactory(%s)", buf));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ nsFactoryEntry *old;
+
+ // first delete all contract id entries that are registered with this cid.
+ DeleteContractIDEntriesByCID(&aClass, aFactory);
+
+ // next check to see if there is a CID registered
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ old = GetFactoryEntry(aClass);
+
+ if (old && (old->mFactory.get() == aFactory))
+ {
+ nsAutoMonitor mon(mMon);
+ PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
+ rv = NS_OK;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tUnregisterFactory() %s",
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
+ const char *registryName)
+{
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: UnregisterComponent(%s)", buf));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ NS_ENSURE_ARG_POINTER(registryName);
+ nsFactoryEntry *old;
+
+ // first delete all contract id entries that are registered with this cid.
+ DeleteContractIDEntriesByCID(&aClass, registryName);
+
+ // next check to see if there is a CID registered
+ old = GetFactoryEntry(aClass);
+ if (old && old->mLocation && !PL_strcasecmp(old->mLocation, registryName))
+ {
+ nsAutoMonitor mon(mMon);
+ PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: Factory unregister(%s) succeeded.", registryName));
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
+ if (NS_FAILED(rv)) return rv;
+ return UnregisterComponent(aClass, registryName);
+}
+
+// XXX Need to pass in aWhen and servicemanager
+nsresult
+nsComponentManagerImpl::FreeLibraries(void)
+{
+ return UnloadLibraries(NS_STATIC_CAST(nsIServiceManager*, this), NS_Timer); // XXX when
+}
+
+// Private implementation of unloading libraries
+nsresult
+nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 aWhen)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoMonitor mon(mMon);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: Unloading Libraries."));
+
+ // UnloadAll the loaders
+ /* iterate over all known loaders and ask them to autoregister. */
+ // Skip mNativeComponentLoader
+ for (int i=NS_COMPONENT_TYPE_NATIVE + 1; i<mNLoaderData; i++) {
+ if (mLoaderData[i].loader) {
+ rv = mLoaderData[i].loader->UnloadAll(aWhen);
+ if (NS_FAILED(rv))
+ break;
+ }
+ }
+
+ // UnloadAll the native loader
+ rv = mNativeComponentLoader->UnloadAll(aWhen);
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * AutoRegister(RegistrationInstant, const char *directory)
+ *
+ * Given a directory in the following format, this will ensure proper registration
+ * of all components. No default directory is looked at.
+ *
+ * Directory and fullname are what NSPR will accept. For eg.
+ * WIN y:/home/dp/mozilla/dist/bin
+ * UNIX /home/dp/mozilla/dist/bin
+ * MAC /Hard drive/mozilla/dist/apprunner
+ *
+ * This will take care not loading already registered dlls, finding and
+ * registering new dlls, re-registration of modified dlls
+ *
+ */
+
+nsresult
+nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
+{
+ return AutoRegisterImpl(when, inDirSpec);
+}
+
+nsresult
+nsComponentManagerImpl::AutoRegisterImpl(PRInt32 when,
+ nsIFile *inDirSpec,
+ PRBool fileIsCompDir)
+{
+ nsCOMPtr<nsIFile> dir;
+ nsresult rv;
+
+#ifdef DEBUG
+ // testing release behaviour
+ if (getenv("XPCOM_NO_AUTOREG"))
+ return NS_OK;
+#endif
+ if (inDirSpec)
+ {
+ // Use supplied components' directory
+ dir = inDirSpec;
+ }
+ else
+ {
+ mComponentsDir->Clone(getter_AddRefs(dir));
+ if (!dir)
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim =
+ dont_AddRef(XPTI_GetInterfaceInfoManager());
+
+ if (!iim)
+ return NS_ERROR_UNEXPECTED;
+
+ // Notify observers of xpcom autoregistration start
+ NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ nsnull,
+ "start");
+
+ /* do the native loader first, so we can find other loaders */
+ rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ rv = mStaticComponentLoader->AutoRegisterComponents((PRInt32)when, inDirSpec);
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ /* do InterfaceInfoManager after native loader so it can use components. */
+ rv = iim->AutoRegisterInterfaces();
+ if (NS_FAILED(rv)) return rv;
+
+ if (!mCategoryManager) {
+ NS_WARNING("mCategoryManager is null");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> loaderEnum;
+ rv = mCategoryManager->EnumerateCategory("component-loader",
+ getter_AddRefs(loaderEnum));
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool hasMore;
+ while (NS_SUCCEEDED(loaderEnum->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> supports;
+ if (NS_FAILED(loaderEnum->GetNext(getter_AddRefs(supports))))
+ continue;
+
+ nsCOMPtr<nsISupportsCString> supStr = do_QueryInterface(supports);
+ if (!supStr)
+ continue;
+
+ nsCAutoString loaderType;
+ if (NS_FAILED(supStr->GetData(loaderType)))
+ continue;
+
+ // We depend on the loader being created. Add the loader type and
+ // create the loader object too.
+ nsCOMPtr<nsIComponentLoader> loader;
+ int typeIndex;
+ rv = AddLoaderType(loaderType.get(), &typeIndex);
+ if (NS_FAILED(rv))
+ return rv;
+ GetLoaderForType(typeIndex, getter_AddRefs(loader));
+ }
+
+ rv = AutoRegisterNonNativeComponents(dir.get());
+
+ // Notify observers of xpcom autoregistration completion
+ NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ nsnull,
+ "end");
+
+ if (mRegistryDirty)
+ FlushPersistentStore(PR_TRUE);
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::AutoRegisterNonNativeComponents(nsIFile* spec)
+{
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIFile> directory = spec;
+
+ if (!directory) {
+ mComponentsDir->Clone(getter_AddRefs(directory));
+ if (!directory)
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ for (int i = 1; i < mNLoaderData; i++) {
+ if (!mLoaderData[i].loader) {
+ rv = GetLoaderForType(i, &mLoaderData[i].loader);
+ if (NS_FAILED(rv))
+ continue;
+ }
+ rv = mLoaderData[i].loader->AutoRegisterComponents(0, directory);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ PRBool registered;
+ do {
+ registered = PR_FALSE;
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool b = PR_FALSE;
+ if (mLoaderData[i].loader) {
+ rv = mLoaderData[i].loader->RegisterDeferredComponents(0, &b);
+ if (NS_FAILED(rv))
+ continue;
+ registered |= b;
+ }
+ }
+ } while (NS_SUCCEEDED(rv) && registered);
+ }
+ return rv;
+}
+nsresult
+nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when,
+ nsIFile *component)
+{
+ nsresult rv = NS_OK, res = NS_ERROR_FACTORY_NOT_REGISTERED;
+ /*
+ * Do we have to give the native loader first crack at it?
+ * I vote ``no''.
+ */
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool didRegister;
+ if (!mLoaderData[i].loader) {
+ nsCOMPtr<nsIComponentLoader> loader;
+ rv = GetLoaderForType(i, getter_AddRefs(loader));
+ if (NS_FAILED(rv))
+ continue;
+ // |GetLoaderForType| has filled in |mLoaderData[i].loader|:
+ NS_ASSERTION(loader == mLoaderData[i].loader, "oops");
+ }
+ rv = mLoaderData[i].loader->AutoRegisterComponent((int)when, component, &didRegister);
+ if (NS_FAILED(rv)) {
+ res = rv;
+ } else if (didRegister) {
+ return rv;
+ }
+ }
+ return res;
+}
+
+nsresult
+nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component)
+{
+ nsresult rv = NS_OK;
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool didUnRegister;
+ if (!mLoaderData[i].loader) {
+ rv = GetLoaderForType(i, &mLoaderData[i].loader);
+ if (NS_FAILED(rv))
+ continue;
+ }
+ rv = mLoaderData[i].loader->AutoUnregisterComponent(when, component, &didUnRegister);
+ if (NS_SUCCEEDED(rv) && didUnRegister) {
+ // we need to remove this file from our list of known libraries.
+ RemoveFileInfo(component, nsnull);
+ mRegistryDirty = PR_TRUE;
+ break;
+ }
+ }
+ return NS_FAILED(rv) ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered)
+{
+ if (!aRegistered)
+ {
+ NS_ASSERTION(0, "null ptr");
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aRegistered = (nsnull != GetFactoryEntry(aClass));
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mFactories,
+ ConvertFactoryEntryToCID,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::EnumerateContractIDs(nsIEnumerator** aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mContractIDs,
+ ConvertContractIDKeyToString,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
+ return NS_OK;
+}
+
+// nsIComponentRegistrar
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoRegister(nsIFile *aSpec)
+{
+ if (aSpec == nsnull)
+ return AutoRegisterImpl(0, aSpec);
+
+ PRBool directory;
+ aSpec->IsDirectory(&directory);
+
+ if (directory)
+ return AutoRegisterImpl(0, aSpec, PR_FALSE);
+
+ return AutoRegisterComponent(0, aSpec);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoUnregister(nsIFile *aSpec)
+{
+ // unregistering a complete directory is not implmeneted yet...FIX
+ if (aSpec == nsnull)
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+ PRBool directory;
+ aSpec->IsDirectory(&directory);
+
+ if (directory)
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+ return AutoUnregisterComponent(0, aSpec);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactory(const nsCID & aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory)
+{
+ return RegisterFactory(aClass,
+ aClassName,
+ aContractID,
+ aFactory,
+ PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactoryLocation(const nsCID & aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aFile,
+ const char *loaderStr,
+ const char *aType)
+{
+ nsXPIDLCString registryName;
+
+ if (!loaderStr)
+ {
+ nsresult rv = RegistryLocationForSpec(aFile, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ nsresult rv;
+ rv = RegisterComponentWithType(aClass,
+ aClassName,
+ aContractID,
+ aFile,
+ (loaderStr ? loaderStr : registryName.get()),
+ PR_TRUE,
+ PR_TRUE,
+ (aType ? aType : nativeComponentType));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID & aClass,
+ nsIFile *aFile)
+{
+ return UnregisterComponentSpec(aClass, aFile);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
+ PRBool *_retval)
+{
+ return IsRegistered(aClass, _retval);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsContractIDRegistered(const char *aClass,
+ PRBool *_retval)
+{
+ nsFactoryEntry *entry = GetFactoryEntry(aClass, strlen(aClass));
+
+ if (entry)
+ *_retval = PR_TRUE;
+ else
+ *_retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+
+ if (!aEnumerator)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mFactories,
+ ConvertFactoryEntryToCID,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mContractIDs,
+ ConvertContractIDKeyToString,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
+ char **_retval)
+{
+ return CLSIDToContractID(aClass,
+ nsnull,
+ _retval);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
+ nsCID * *_retval)
+{
+ *_retval = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = ContractIDToClassID(aContractID, *_retval);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(*_retval);
+ *_retval = nsnull;
+ }
+ return rv;
+}
+
+// end nsIComponentRegistrar
+
+
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::HasFileChanged(nsIFile *file, const char *loaderString, PRInt64 modDate, PRBool *_retval)
+{
+ *_retval = PR_TRUE;
+
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+ if (entry)
+ *_retval = entry->Modified(&modDate);
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::SaveFileInfo(nsIFile *file, const char *loaderString, PRInt64 modDate)
+{
+ mRegistryDirty = PR_TRUE;
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // check to see if exists in the array before adding it so that we don't have dups.
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+
+ if (entry)
+ {
+ entry->SetDate(&modDate);
+ return NS_OK;
+ }
+
+ entry = new AutoRegEntry(registryName, &modDate);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAutoRegEntries.Put(&key, entry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RemoveFileInfo(nsIFile *file, const char *loaderString)
+{
+ mRegistryDirty = PR_TRUE;
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Remove(&key);
+ if (entry)
+ delete entry;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetOptionalData(nsIFile *file,
+ const char *loaderString,
+ char **_retval)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+ if (!entry) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ const char* opData = entry->GetOptionalData();
+
+ if (opData)
+ *_retval = ToNewCString(nsDependentCString(opData));
+ else
+ *_retval = nsnull;
+ return NS_OK;
+ }
+
+NS_IMETHODIMP
+nsComponentManagerImpl::SetOptionalData(nsIFile *file,
+ const char *loaderString,
+ const char *data)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+
+ if (!entry) {
+ PRInt64 zero = LL_Zero();
+ entry = new AutoRegEntry(registryName, &zero);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAutoRegEntries.Put(&key, entry);
+ }
+
+ entry->SetOptionalData(data);
+
+ return NS_OK;
+ }
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::FlushPersistentStore(PRBool now)
+{
+ mRegistryDirty = PR_TRUE;
+ if (now)
+ return WritePersistentRegistry();
+
+ return NS_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Static Access Functions
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_GetGlobalComponentManager(nsIComponentManager* *result)
+{
+#ifdef DEBUG_dougt
+ // NS_WARNING("DEPRECATED FUNCTION: Use NS_GetComponentManager");
+#endif
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ // NO ADDREF since this is never intended to be released.
+ // See nsComponentManagerObsolete.h for the reason for such
+ // casting uglyness
+ *result = (nsIComponentManager*)(void*)(nsIComponentManagerObsolete*) nsComponentManagerImpl::gComponentManager;
+ }
+
+ return rv;
+}
+
+NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result)
+{
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ *result = NS_STATIC_CAST(nsIComponentManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+#ifdef VBOX
+ // While XPCOM might need initialization, we're not in a position
+ // to pass the right values to this call. This is actually triggered
+ // on object destruction, so there is no point in re-initializing,
+ // and actually the attempt would lead to nested calls to
+ // xptiInterfaceInfoManager::BuildFileSearchPath, which it detects
+ // as unsafe in debug builds. Just fail, no real problem.
+#ifdef DEBUG
+ printf("NS_GetServiceManager: no current instance, suppressed XPCOM initialization!\n");
+#endif
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+#else /* !VBOX */
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+#endif /* !VBOX */
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIServiceManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+
+NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIComponentRegistrar*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+
+// nsIComponentLoaderManager is not frozen, but is defined here
+// so that I can use it internally in xpcom.
+nsresult
+NS_GetComponentLoaderManager(nsIComponentLoaderManager* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == NULL)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIComponentLoaderManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h
new file mode 100644
index 00000000..df128125
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsComponentManager_h__
+#define nsComponentManager_h__
+
+#include "nsXPCOM.h"
+
+#include "nsIComponentLoader.h"
+#include "xpcom-private.h"
+#include "nsNativeComponentLoader.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIComponentLoaderManager.h"
+#include "nsCategoryManager.h"
+#include "nsIServiceManager.h"
+#include "nsIFactory.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "pldhash.h"
+#include "prtime.h"
+#include "prmon.h"
+#include "nsCOMPtr.h"
+#include "nsWeakReference.h"
+#include "nsXPIDLString.h"
+#include "nsIFile.h"
+#include "plarena.h"
+
+class nsFactoryEntry;
+class nsDll;
+class nsIServiceManager;
+
+
+// Predefined loader types. Do not change the numbers.
+// NATIVE should be 0 as it is being used as the first array index.
+#define NS_COMPONENT_TYPE_NATIVE 0
+#define NS_COMPONENT_TYPE_FACTORY_ONLY -1
+// this define means that the factory entry only has a ContractID
+// to service mapping and has no cid mapping.
+#define NS_COMPONENT_TYPE_SERVICE_ONLY -2
+
+
+#ifdef DEBUG
+#define XPCOM_CHECK_PENDING_CIDS
+#endif
+////////////////////////////////////////////////////////////////////////////////
+
+// Array of Loaders and their type strings
+struct nsLoaderdata {
+ nsIComponentLoader *loader;
+ const char *type;
+};
+
+class nsComponentManagerImpl
+ : public nsIComponentManager,
+ public nsIServiceManager,
+ public nsIComponentRegistrar,
+ public nsSupportsWeakReference,
+ public nsIInterfaceRequestor,
+ public nsIComponentLoaderManager,
+ public nsIServiceManagerObsolete,
+ public nsIComponentManagerObsolete
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEREQUESTOR
+ // Since the nsIComponentManagerObsolete and nsIComponentManager share some of the
+ // same interface function names, we have to manually define the functions here.
+ // The only function that is in nsIComponentManagerObsolete and is in nsIComponentManager
+ // is GetClassObjectContractID.
+ //
+ // nsIComponentManager function not in nsIComponentManagerObsolete:
+ NS_IMETHOD GetClassObjectByContractID(const char *aContractID,
+ const nsIID &aIID,
+ void **_retval);
+
+
+ NS_DECL_NSICOMPONENTMANAGEROBSOLETE
+
+ // Since the nsIComponentManagerObsolete and nsIComponentRegistrar share some of the
+ // same interface function names, we have to manually define the functions here.
+ // the only function that is shared is UnregisterFactory
+ NS_IMETHOD AutoRegister(nsIFile *aSpec);
+ NS_IMETHOD AutoUnregister(nsIFile *aSpec);
+ NS_IMETHOD RegisterFactory(const nsCID & aClass, const char *aClassName, const char *aContractID, nsIFactory *aFactory);
+ // NS_IMETHOD UnregisterFactory(const nsCID & aClass, nsIFactory *aFactory);
+ NS_IMETHOD RegisterFactoryLocation(const nsCID & aClass, const char *aClassName, const char *aContractID, nsIFile *aFile, const char *loaderStr, const char *aType);
+ NS_IMETHOD UnregisterFactoryLocation(const nsCID & aClass, nsIFile *aFile);
+ NS_IMETHOD IsCIDRegistered(const nsCID & aClass, PRBool *_retval);
+ NS_IMETHOD IsContractIDRegistered(const char *aClass, PRBool *_retval);
+ NS_IMETHOD EnumerateCIDs(nsISimpleEnumerator **_retval);
+ NS_IMETHOD EnumerateContractIDs(nsISimpleEnumerator **_retval);
+ NS_IMETHOD CIDToContractID(const nsCID & aClass, char **_retval);
+ NS_IMETHOD ContractIDToCID(const char *aContractID, nsCID * *_retval);
+
+ NS_DECL_NSISERVICEMANAGER
+ NS_DECL_NSISERVICEMANAGEROBSOLETE
+ NS_DECL_NSICOMPONENTLOADERMANAGER
+
+ // nsComponentManagerImpl methods:
+ nsComponentManagerImpl();
+
+ static nsComponentManagerImpl* gComponentManager;
+ nsresult Init(void);
+
+ nsresult WritePersistentRegistry();
+ nsresult ReadPersistentRegistry();
+
+ nsresult Shutdown(void);
+
+ nsresult FreeServices();
+
+ nsresult
+ NS_GetService(const char *aContractID, const nsIID& aIID, PRBool aDontCreate, nsISupports** result);
+
+ nsresult RegisterComponentCommon(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ PRUint32 aContractIDLen,
+ const char *aRegistryName,
+ PRUint32 aRegistryNameLen,
+ PRBool aReplace, PRBool aPersist,
+ const char *aType);
+ nsresult GetLoaderForType(int aType,
+ nsIComponentLoader **aLoader);
+ nsresult FindFactory(const char *contractID, PRUint32 aContractIDLen, nsIFactory **aFactory) ;
+ nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory);
+
+ nsFactoryEntry *GetFactoryEntry(const char *aContractID,
+ PRUint32 aContractIDLen);
+ nsFactoryEntry *GetFactoryEntry(const nsCID &aClass);
+
+ nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec);
+ nsresult SelfRegisterDll(nsDll *dll);
+ nsresult SelfUnregisterDll(nsDll *dll);
+ nsresult HashContractID(const char *acontractID, PRUint32 aContractIDLen,
+ nsFactoryEntry *fe_ptr);
+
+ void DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName);
+ void DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory);
+
+ nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when);
+
+ // Convert a loader type string into an index into the loader data
+ // array. Empty loader types are converted to NATIVE. Returns -1 if
+ // loader type cannot be determined.
+ int GetLoaderType(const char *typeStr);
+
+ // Add a loader type if not already known. Out the typeIndex
+ // if the loader type is either added or already there;
+ // returns NS_OK or an error on failure.
+ nsresult AddLoaderType(const char *typeStr, int *typeIndex);
+
+ int GetLoaderCount() { return mNLoaderData + 1; }
+
+ // registers only the files in spec's location by loaders other than the
+ // native loader. This is an optimization method only.
+ nsresult AutoRegisterNonNativeComponents(nsIFile* spec);
+
+ nsresult AutoRegisterImpl(PRInt32 when, nsIFile *inDirSpec, PRBool fileIsCompDir=PR_TRUE);
+ nsresult RemoveEntries(nsIFile* file);
+
+ PLDHashTable mFactories;
+ PLDHashTable mContractIDs;
+ PRMonitor* mMon;
+
+ nsNativeComponentLoader *mNativeComponentLoader;
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ nsIComponentLoader *mStaticComponentLoader;
+#endif
+ nsCOMPtr<nsIFile> mComponentsDir;
+ PRInt32 mComponentsOffset;
+
+ nsCOMPtr<nsIFile> mGREComponentsDir;
+ PRInt32 mGREComponentsOffset;
+
+ nsCOMPtr<nsIFile> mRegistryFile;
+
+ // Shutdown
+ #define NS_SHUTDOWN_NEVERHAPPENED 0
+ #define NS_SHUTDOWN_INPROGRESS 1
+ #define NS_SHUTDOWN_COMPLETE 2
+ PRUint32 mShuttingDown;
+
+ nsLoaderdata *mLoaderData;
+ int mNLoaderData;
+ int mMaxNLoaderData;
+
+ PRBool mRegistryDirty;
+ nsHashtable mAutoRegEntries;
+ nsCOMPtr<nsCategoryManager> mCategoryManager;
+
+ PLArenaPool mArena;
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ nsresult AddPendingCID(const nsCID &aClass);
+ void RemovePendingCID(const nsCID &aClass);
+
+ nsVoidArray mPendingCIDs;
+#endif
+
+private:
+ ~nsComponentManagerImpl();
+};
+
+
+#define NS_MAX_FILENAME_LEN 1024
+
+#define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Class: nsFactoryEntry()
+ *
+ * There are two types of FactoryEntries.
+ *
+ * 1. {CID, dll} mapping.
+ * Factory is a consequence of the dll. These can be either session
+ * specific or persistent based on whether we write this
+ * to the registry or not.
+ *
+ * 2. {CID, factory} mapping
+ * These are strictly session specific and in memory only.
+ */
+
+class nsFactoryEntry {
+public:
+ nsFactoryEntry(const nsCID &aClass,
+ const char *location, PRUint32 locationlen, int aType, class nsFactoryEntry* parent = nsnull);
+ nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory, class nsFactoryEntry* parent = nsnull);
+ ~nsFactoryEntry();
+
+ nsresult ReInit(const nsCID &aClass, const char *location, int aType);
+
+ nsresult GetFactory(nsIFactory **aFactory,
+ nsComponentManagerImpl * mgr) {
+ if (mFactory) {
+ *aFactory = mFactory.get();
+ NS_ADDREF(*aFactory);
+ return NS_OK;
+ }
+
+ if (mTypeIndex < 0)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsCOMPtr<nsIComponentLoader> loader;
+ rv = mgr->GetLoaderForType(mTypeIndex, getter_AddRefs(loader));
+ if(NS_FAILED(rv))
+ return rv;
+
+ rv = loader->GetFactory(mCid, mLocation, mgr->mLoaderData[mTypeIndex].type, aFactory);
+ if (NS_SUCCEEDED(rv))
+ mFactory = do_QueryInterface(*aFactory);
+ return rv;
+ }
+
+ nsCID mCid;
+ nsCOMPtr<nsIFactory> mFactory;
+ // This is an index into the mLoaderData array that holds the type string and the loader
+ int mTypeIndex;
+ nsCOMPtr<nsISupports> mServiceObject;
+ char* mLocation;
+ class nsFactoryEntry* mParent;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct nsFactoryTableEntry : public PLDHashEntryHdr {
+ nsFactoryEntry *mFactoryEntry;
+};
+
+struct nsContractIDTableEntry : public PLDHashEntryHdr {
+ char *mContractID;
+ PRUint32 mContractIDLen;
+ nsFactoryEntry *mFactoryEntry;
+};
+
+
+class AutoRegEntry
+{
+public:
+ AutoRegEntry(const nsACString& name, PRInt64* modDate);
+ ~AutoRegEntry();
+
+ const nsDependentCString GetName()
+ { return nsDependentCString(mName, mNameLen); }
+ PRInt64 GetDate() {return mModDate;}
+ void SetDate(PRInt64 *date) { mModDate = *date;}
+ PRBool Modified(PRInt64 *date);
+
+ // this is the optional field line in the compreg.dat.
+ // it must not contain any comma's and it must be null terminated.
+ char* GetOptionalData() {return mData;};
+ void SetOptionalData(const char* data);
+
+private:
+ char* mName;
+ PRUint32 mNameLen;
+ char* mData;
+ PRInt64 mModDate;
+};
+#endif // nsComponentManager_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp
new file mode 100644
index 00000000..fca77cf7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp
@@ -0,0 +1,271 @@
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// Global Static Component Manager Methods
+// (for when you need to link with xpcom)
+
+#include "nsIComponentManagerObsolete.h"
+#include "nsComponentManagerObsolete.h"
+
+
+nsresult
+nsComponentManager::Initialize(void)
+{
+ return NS_OK;
+}
+
+nsresult
+nsComponentManager::FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->FindFactory(aClass, aFactory);
+}
+
+nsresult
+nsComponentManager::GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->GetClassObject(aClass, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::ContractIDToClassID(const char *aContractID,
+ nsCID *aClass)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->ContractIDToClassID(aContractID, aClass);
+}
+
+nsresult
+nsComponentManager::CLSIDToContractID(nsCID *aClass,
+ char* *aClassName,
+ char* *aContractID)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CLSIDToContractID(*aClass, aClassName, aContractID);
+}
+
+nsresult
+nsComponentManager::CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CreateInstance(aClass, aDelegate, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::CreateInstance(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CreateInstanceByContractID(aContractID, aDelegate, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterFactory(aClass, aClassName, aContractID,
+ aFactory, aReplace);
+}
+
+nsresult
+nsComponentManager::RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLibraryPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponent(aClass, aClassName, aContractID,
+ aLibraryPersistentDescriptor, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrary,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponentSpec(aClass, aClassName, aContractID,
+ aLibrary, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *adllName,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponentLib(aClass, aClassName, aContractID,
+ adllName, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterFactory(aClass, aFactory);
+}
+
+nsresult
+nsComponentManager::UnregisterComponent(const nsCID &aClass,
+ const char *aLibrary)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterComponent(aClass, aLibrary);
+}
+
+nsresult
+nsComponentManager::UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterComponentSpec(aClass, aLibrarySpec);
+}
+
+nsresult
+nsComponentManager::FreeLibraries(void)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->FreeLibraries();
+}
+
+nsresult
+nsComponentManager::AutoRegister(PRInt32 when, nsIFile *directory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoRegister(when, directory);
+}
+
+nsresult
+nsComponentManager::AutoRegisterComponent(PRInt32 when,
+ nsIFile *fullname)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoRegisterComponent(when, fullname);
+}
+
+nsresult
+nsComponentManager::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *fullname)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoUnregisterComponent(when, fullname);
+}
+
+nsresult
+nsComponentManager::IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->IsRegistered(aClass, aRegistered);
+}
+
+nsresult
+nsComponentManager::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->EnumerateCLSIDs(aEnumerator);
+}
+
+nsresult
+nsComponentManager::EnumerateContractIDs(nsIEnumerator** aEnumerator)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->EnumerateContractIDs(aEnumerator);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h
new file mode 100644
index 00000000..dfcde87a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsComponentManagerObsolete_h___
+#define nsComponentManagerObsolete_h___
+
+#include "nsIComponentManager.h"
+#include "nsIComponentManagerObsolete.h"
+
+class nsIEnumerator;
+class nsIFactory;
+class nsIFile;
+////////////////////////////////////////////////////////////////////
+//
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+//
+// Functions, classes, interfaces and types in this file are
+// obsolete. Use at your own risk.
+// Please see nsIComponentManager.idl for the supported interface
+// to the component manager.
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////////
+// God save me from this evilness. Below is a very bad
+// function. Its out var is really a nsIComponentManagerObsolete
+// but it has been cast to a nsIComponentManager.
+// The reason for such uglyness is that this function is require for
+// backward compatiblity of some plugins. This funciton will
+// be removed at some point.
+////////////////////////////////////////////////////////////////////
+
+extern NS_COM nsresult
+NS_GetGlobalComponentManager(nsIComponentManager* *result);
+
+
+
+
+class NS_COM nsComponentManager {
+public:
+ static nsresult Initialize(void);
+
+ // Finds a factory for a specific class ID
+ static nsresult FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory);
+
+ // Get the singleton class object that implements the CID aClass
+ static nsresult GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult);
+
+ // Finds a class ID for a specific Program ID
+ static nsresult ContractIDToClassID(const char *aContractID,
+ nsCID *aClass);
+
+ // Finds a Program ID for a specific class ID
+ // caller frees the result with delete[]
+ static nsresult CLSIDToContractID(nsCID *aClass,
+ char* *aClassName,
+ char* *aContractID);
+
+ // Creates a class instance for a specific class ID
+ static nsresult CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ // Convenience routine, creates a class instance for a specific ContractID
+ static nsresult CreateInstance(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ // Manually registry a factory for a class
+ static nsresult RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace);
+
+ // Manually register a dynamically loaded component.
+ // The libraryPersistentDescriptor is what gets passed to the library
+ // self register function from ComponentManager. The format of this string
+ // is the same as nsIFile::GetPath()
+ //
+ // This function will go away in favour of RegisterComponentSpec. In fact,
+ // it internally turns around and calls RegisterComponentSpec.
+ static nsresult RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLibraryPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist);
+
+ // Register a component using its FileSpec as its identification
+ // This is the more prevalent use.
+ static nsresult RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrary,
+ PRBool aReplace,
+ PRBool aPersist);
+
+ // Register a component using its dllName. This could be a dll name with
+ // no path so that LD_LIBRARY_PATH on unix or PATH on win can load it. Or
+ // this could be a code fragment name on the Mac.
+ static nsresult RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *adllName,
+ PRBool aReplace,
+ PRBool aPersist);
+
+
+ // Manually unregister a factory for a class
+ static nsresult UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory);
+
+ // Manually unregister a dynamically loaded component
+ static nsresult UnregisterComponent(const nsCID &aClass,
+ const char *aLibrary);
+
+ // Manually unregister a dynamically loaded component
+ static nsresult UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec);
+
+ // Unload dynamically loaded factories that are not in use
+ static nsresult FreeLibraries(void);
+ //////////////////////////////////////////////////////////////////////////////
+ // DLL registration support
+
+ // If directory is NULL, then AutoRegister will try registering components
+ // in the default components directory.
+ static nsresult AutoRegister(PRInt32 when, nsIFile* directory);
+ static nsresult AutoRegisterComponent(PRInt32 when, nsIFile *component);
+ static nsresult AutoUnregisterComponent(PRInt32 when, nsIFile *component);
+
+ // Is the given CID currently registered?
+ static nsresult IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered);
+
+ // Get an enumeration of all the CIDs
+ static nsresult EnumerateCLSIDs(nsIEnumerator** aEmumerator);
+
+ // Get an enumeration of all the ContractIDs
+ static nsresult EnumerateContractIDs(nsIEnumerator** aEmumerator);
+
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h
new file mode 100644
index 00000000..cda56416
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsComponentManagerUtils_h__
+#define nsComponentManagerUtils_h__
+
+/*
+ * Do not include this file directly. Instead,
+ * |#include "nsIComponentManager.h"|.
+ */
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+#ifndef nsComponentManagerObsolete_h___
+#include "nsComponentManagerObsolete.h"
+#endif
+
+#define NS_COMPONENTMANAGER_CID \
+{ /* 91775d60-d5dc-11d2-92fb-00e09805570f */ \
+ 0x91775d60, \
+ 0xd5dc, \
+ 0x11d2, \
+ {0x92, 0xfb, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \
+}
+
+class NS_COM nsCreateInstanceByCID : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceByCID( const nsCID& aCID, nsISupports* aOuter, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mOuter(aOuter),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+private:
+ const nsCID& mCID;
+ nsISupports* mOuter;
+ nsresult* mErrorPtr;
+};
+
+class NS_COM nsCreateInstanceByContractID : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceByContractID( const char* aContractID, nsISupports* aOuter, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mOuter(aOuter),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+private:
+ const char* mContractID;
+ nsISupports* mOuter;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsCreateInstanceByCID
+do_CreateInstance( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsCreateInstanceByCID(aCID, 0, error);
+}
+
+inline
+const nsCreateInstanceByCID
+do_CreateInstance( const nsCID& aCID, nsISupports* aOuter, nsresult* error = 0 )
+{
+ return nsCreateInstanceByCID(aCID, aOuter, error);
+}
+
+inline
+const nsCreateInstanceByContractID
+do_CreateInstance( const char* aContractID, nsresult* error = 0 )
+{
+ return nsCreateInstanceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsCreateInstanceByContractID
+do_CreateInstance( const char* aContractID, nsISupports* aOuter, nsresult* error = 0 )
+{
+ return nsCreateInstanceByContractID(aContractID, aOuter, error);
+}
+
+// type-safe shortcuts for calling |CreateInstance|
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const nsCID &aClass,
+ nsISupports *aDelegate,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aClass, aDelegate,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const nsCID &aClass,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aClass, nsnull,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const char *aContractID,
+ nsISupports *aDelegate,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aContractID,
+ aDelegate,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const char *aContractID,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aContractID, nsnull,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+/* keys for registry use */
+extern const char xpcomKeyName[];
+extern const char xpcomComponentsKeyName[];
+extern const char lastModValueName[];
+extern const char fileSizeValueName[];
+extern const char nativeComponentType[];
+extern const char staticComponentType[];
+
+#endif /* nsComponentManagerUtils_h__ */
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl b/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl
new file mode 100644
index 00000000..509f7870
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsISimpleEnumerator.idl"
+
+/*
+ * nsICategoryManager
+ * @status FROZEN
+ */
+
+[scriptable, uuid(3275b2cd-af6d-429a-80d7-f0c5120342ac)]
+interface nsICategoryManager : nsISupports
+{
+ /**
+ * Get the value for the given category's entry.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry you're looking for ("http")
+ * @return The value.
+ */
+ string getCategoryEntry(in string aCategory, in string aEntry);
+
+ /**
+ * Add an entry to a category.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry to be added ("http")
+ * @param aValue The value for the entry ("moz.httprulez.1")
+ * @param aPersist Should this data persist between invocations?
+ * @param aReplace Should we replace an existing entry?
+ * @return Previous entry, if any
+ */
+ string addCategoryEntry(in string aCategory, in string aEntry,
+ in string aValue, in boolean aPersist,
+ in boolean aReplace);
+
+ /**
+ * Delete an entry from the category.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry to be added ("http")
+ * @param aPersist Delete persistent data from registry, if present?
+ */
+ void deleteCategoryEntry(in string aCategory, in string aEntry,
+ in boolean aPersist);
+
+ /**
+ * Delete a category and all entries.
+ * @param aCategory The category to be deleted.
+ */
+ void deleteCategory(in string aCategory);
+
+ /**
+ * Enumerate the entries in a category.
+ * @param aCategory The category to be enumerated.
+ * @return a simple enumerator, each result QIs to
+ * nsISupportsCString.
+ */
+ nsISimpleEnumerator enumerateCategory(in string aCategory);
+
+ /**
+ * Enumerate all existing categories
+ * @param aCategory The category to be enumerated.
+ * @return a simple enumerator, each result QIs to
+ * nsISupportsCString.
+ */
+ nsISimpleEnumerator enumerateCategories();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl b/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl
new file mode 100644
index 00000000..e934057c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIProgrammingLanguage.idl"
+
+/**
+ * Provides information about a specific implementation class
+ * @status FROZEN
+ */
+
+[scriptable, uuid(986c11d0-f340-11d4-9075-0010a4e73d9a)]
+interface nsIClassInfo : nsISupports
+{
+ /**
+ * Get an ordered list of the interface ids that instances of the class
+ * promise to implement. Note that nsISupports is an implicit member
+ * of any such list and need not be included.
+ *
+ * Should set *count = 0 and *array = null and return NS_OK if getting the
+ * list is not supported.
+ */
+ void getInterfaces(out PRUint32 count,
+ [array, size_is(count), retval] out nsIIDPtr array);
+
+ /**
+ * Get a language mapping specific helper object that may assist in using
+ * objects of this class in a specific lanaguage. For instance, if asked
+ * for the helper for nsIProgrammingLanguage::JAVASCRIPT this might return
+ * an object that can be QI'd into the nsIXPCScriptable interface to assist
+ * XPConnect in supplying JavaScript specific behavior to callers of the
+ * instance object.
+ *
+ * see: nsIProgrammingLanguage.idl
+ *
+ * Should return null if no helper available for given language.
+ */
+ nsISupports getHelperForLanguage(in PRUint32 language);
+
+ /**
+ * A contract ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|), or null.
+ */
+ readonly attribute string contractID;
+
+ /**
+ * A human readable string naming the class, or null.
+ */
+ readonly attribute string classDescription;
+
+ /**
+ * A class ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|), or null.
+ */
+ readonly attribute nsCIDPtr classID;
+
+ /**
+ * Return language type from list in nsIProgrammingLanguage
+ */
+
+ readonly attribute PRUint32 implementationLanguage;
+
+ /**
+ * Bitflags for 'flags' attribute.
+ */
+ const PRUint32 SINGLETON = 1 << 0;
+ const PRUint32 THREADSAFE = 1 << 1;
+ const PRUint32 MAIN_THREAD_ONLY = 1 << 2;
+ const PRUint32 DOM_OBJECT = 1 << 3;
+ const PRUint32 PLUGIN_OBJECT = 1 << 4;
+ const PRUint32 EAGER_CLASSINFO = 1 << 5;
+ /**
+ * 'flags' attribute bitflag: whether objects of this type implement
+ * nsIContent.
+ */
+ const PRUint32 CONTENT_NODE = 1 << 6;
+
+ // The high order bit is RESERVED for consumers of these flags.
+ // No implementor of this interface should ever return flags
+ // with this bit set.
+ const PRUint32 RESERVED = 1 << 31;
+
+
+ readonly attribute PRUint32 flags;
+
+ /**
+ * Also a class ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|). If the class does
+ * not have a CID, it should return NS_ERROR_NOT_AVAILABLE. This attribute
+ * exists so C++ callers can avoid allocating and freeing a CID, as would
+ * happen if they used classID.
+ */
+ [notxpcom] readonly attribute nsCID classIDNoAlloc;
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl
new file mode 100644
index 00000000..d1b4be6e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIFactory.idl"
+#include "nsIFile.idl"
+#include "nsIComponentManager.idl"
+
+[object, uuid(c073cfc0-567c-11d3-aec1-0000f8e25c06)]
+interface nsIComponentLoader : nsISupports {
+
+ /**
+ * Get the factory for a given component.
+ */
+ nsIFactory getFactory(in nsIIDRef aCID, in string aLocation,
+ in string aType);
+
+ /**
+ * Initialize the loader.
+ *
+ * We use nsISupports here because nsIRegistry isn't IDLized yet.
+ */
+ void init(in nsIComponentManager aCompMgr, in nsISupports aRegistry);
+
+ /**
+ * Called when a component of the appropriate type is registered,
+ * to give the component loader an opportunity to do things like
+ * annotate the registry and such.
+ */
+ void onRegister(in nsIIDRef aCID, in string aType,
+ in string aClassName, in string aContractID,
+ in string aLocation, in boolean aReplace,
+ in boolean aPersist);
+
+ /**
+ * When is AutoRegistration occuring?
+ */
+ const long Startup = 0;
+ const long Component = 1;
+ const long Timer = 2;
+
+ /**
+ * AutoRegister components in the given directory.
+ */
+ void autoRegisterComponents(in long aWhen, in nsIFile aDirectory);
+
+ /**
+ * AutoRegister the given component.
+ *
+ * Returns true if the component was registered, false if it couldn't
+ * attempt to register the component (wrong type) and ``throws'' an
+ * NS_FAILED code if there was an error during registration.
+ */
+ boolean autoRegisterComponent(in long aWhen, in nsIFile aComponent);
+
+ /**
+ * AutoUnregister the given component.
+ * Returns true if the component was unregistered, false if it coudln't
+ * attempt to unregister the component (not found, wrong type).
+ */
+ boolean autoUnregisterComponent(in long aWhen, in nsIFile aComponent);
+
+ /**
+ * Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components.
+ * Return registered-any-components?
+ */
+ boolean registerDeferredComponents(in long aWhen);
+
+ /**
+ * Unload all components that are willing.
+ */
+ void unloadAll(in long aWhen);
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl
new file mode 100644
index 00000000..9f1784d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl
@@ -0,0 +1,72 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The nsIComponentRegistrar interface.
+ * @status EXPERIMENTAL
+ *
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+[uuid(fce83d37-a3c0-4e09-ad9f-6842a984dbdf)]
+interface nsIComponentLoaderManager : nsISupports
+{
+ boolean hasFileChanged(in nsIFile file, in string loaderString, in PRInt64 modDate);
+ void saveFileInfo(in nsIFile file, in string loaderString, in PRInt64 modDate);
+ void removeFileInfo(in nsIFile file, in string loaderString);
+ void flushPersistentStore(in boolean now);
+
+ string getOptionalData(in nsIFile file, in string loaderString);
+ void setOptionalData(in nsIFile file, in string loaderString, in string value);
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl
new file mode 100644
index 00000000..20661803
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl
@@ -0,0 +1,111 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The nsIComponentManager interface.
+ * @status FROZEN
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFactory;
+
+[scriptable, uuid(a88e5a60-205a-4bb1-94e1-2628daf51eae)]
+interface nsIComponentManager : nsISupports
+{
+ /**
+ * getClassObject
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ void getClassObject(in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * getClassObjectByContractID
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ void getClassObjectByContractID(in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+
+ /**
+ * createInstance
+ *
+ * Create an instance of the CID aClass and return the interface aIID.
+ *
+ * @param aClass : ClassID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ void createInstance(in nsCIDRef aClass,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * createInstanceByContractID
+ *
+ * Create an instance of the CID that implements aContractID and return the
+ * interface aIID.
+ *
+ * @param aContractID : aContractID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ void createInstanceByContractID(in string aContractID,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+};
+
+
+%{ C++
+#ifndef MOZILLA_STRICT_API
+#include "nsComponentManagerUtils.h"
+#include "nsComponentManagerObsolete.h"
+#endif
+%} C++
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl
new file mode 100644
index 00000000..ac5f7975
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIFactory.idl"
+
+interface nsIFile;
+interface nsIEnumerator;
+
+[scriptable, uuid(8458a740-d5dc-11d2-92fb-00e09805570f)]
+interface nsIComponentManagerObsolete : nsISupports
+{
+ /**
+ * findFactory
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ nsIFactory findFactory(in nsCIDRef aClass);
+
+ /**
+ * getClassObject
+ *
+ * @param aClass : CID of the class whose class object is requested
+ * @param aIID : IID of an interface that the class object is known to
+ * to implement. nsISupports and nsIFactory are known to
+ * be implemented by the class object.
+ */
+ [noscript] voidPtr getClassObject(in nsCIDRef aClass, in nsIIDRef aIID);
+
+ /**
+ * contractIDToClassID
+ *
+ * Get the ClassID for a given ContractID. Many ClassIDs may implement a
+ * ContractID. In such a situation, this returns the preferred ClassID, which
+ * happens to be the last registered ClassID.
+ *
+ * @param aContractID : Contractid for which ClassID is requested
+ * @return aClass : ClassID return
+ */
+ [notxpcom] nsresult contractIDToClassID(in string aContractID, out nsCID aClass);
+
+ /**
+ * classIDToContractid
+ *
+ * Get the ContractID for a given ClassID. A ClassIDs may implement multiple
+ * ContractIDs. This function return the last registered ContractID.
+ *
+ * @param aClass : ClassID for which ContractID is requested.
+ * @return aClassName : returns class name asssociated with aClass
+ * @return : ContractID last registered for aClass
+ */
+ string CLSIDToContractID(in nsCIDRef aClass, out string aClassName);
+
+ /**
+ * createInstance
+ *
+ * Create an instance of the CID aClass and return the interface aIID.
+ *
+ * @param aClass : ClassID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ [noscript] voidPtr createInstance(in nsCIDRef aClass,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID);
+
+ /**
+ * createInstanceByContractID
+ *
+ * Create an instance of the CID that implements aContractID and return the
+ * interface aIID. This is a convenience function that effectively does
+ * ContractIDToClassID() followed by CreateInstance().
+ *
+ * @param aContractID : aContractID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ [noscript] voidPtr createInstanceByContractID(in string aContractID,
+ in nsISupports aDelegate,
+ in nsIIDRef IID);
+ /**
+ * registryLocationForSpec
+ *
+ * Given a file specification, return the registry representation of
+ * the filename. Files that are found relative to the components
+ * directory will have a registry representation
+ * "rel:<relative-native-path>" while filenames that are not, will have
+ * "abs:<full-native-path>".
+ */
+ string registryLocationForSpec(in nsIFile aSpec);
+
+ /**
+ * specForRegistyLocation
+ *
+ * Create a file specification for the registry representation (rel:/abs:)
+ * got via registryLocationForSpec.
+ */
+ nsIFile specForRegistryLocation(in string aLocation);
+
+ /**
+ * registerFactory
+ *
+ * Register a factory and ContractID associated with CID aClass
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFactory : Factory that will be registered for CID aClass
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * registration for the CID aClass.
+ */
+ void registerFactory(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFactory aFactory,
+ in boolean aReplace);
+
+ /**
+ * registerComponent
+ *
+ * Register a native dll module via its registry representation as returned
+ * by registryLocationForSpec() as the container of CID implemenation
+ * aClass and associate aContractID and aClassName to the CID aClass. Native
+ * dll component type is assumed.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aLocation : Location of module (dll). Format of this is the
+ * registry representation as returned by
+ * registryLocationForSpec()
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponent(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in string aLocation,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * registerComponentWithType
+ *
+ * Register a module's location via its registry representation
+ * as returned by registryLocationForSpec() as the container of CID implemenation
+ * aClass of type aType and associate aContractID and aClassName to the CID aClass.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aSpec : Filename spec for module's location.
+ * @param aLocation : Location of module of type aType. Format of this string
+ * is the registry representation as returned by
+ * registryLocationForSpec()
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * loader registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ * @param aType : Component Type of CID aClass.
+ */
+ void registerComponentWithType(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFile aSpec,
+ in string aLocation, in boolean aReplace,
+ in boolean aPersist, in string aType);
+
+ /**
+ * registerComponentSpec
+ *
+ * Register a native dll module via its file specification as the container
+ * of CID implemenation aClass and associate aContractID and aClassName to the
+ * CID aClass. Native dll component type is assumed.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aLibrary : File specification Location of module (dll).
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponentSpec(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFile aLibrary,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * registerComponentLib
+ *
+ * Register a native dll module via its dll name (not full path) as the
+ * container of CID implemenation aClass and associate aContractID and aClassName
+ * to the CID aClass. Native dll component type is assumed and the system
+ * services will be used to load this dll.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aDllNameLocation : Dll name of module.
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponentLib(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in string aDllName,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * unregisterFactory
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : ClassID being unregistered
+ * @param aFactory : Factory previously registered to create instances of
+ * ClassID aClass.
+ */
+ void unregisterFactory(in nsCIDRef aClass, in nsIFactory aFactory);
+
+ /**
+ * unregisterComponent
+ *
+ * Disassociate module aLocation represented as registry location as returned
+ * by registryLocationForSpec() as containing ClassID aClass.
+ *
+ * @param aClass : ClassID being unregistered
+ * @param aLocation : Location of module. Format of this is the registry
+ * representation as returned by registryLocationForSpec().
+ * Components of any type will be unregistered.
+ */
+ void unregisterComponent(in nsCIDRef aClass, in string aLocation);
+
+ /**
+ * unregisterComponentSpec
+ *
+ * Disassociate module references by file specification aLibrarySpec as
+ * containing ClassID aClass.
+ */
+ void unregisterComponentSpec(in nsCIDRef aClass, in nsIFile aLibrarySpec);
+
+ /**
+ * freeLibraries
+ *
+ * Enumerates all loaded modules and unloads unused modules.
+ */
+ void freeLibraries();
+
+ /**
+ * ID values for 'when'
+ */
+ const long NS_Startup = 0;
+ const long NS_Script = 1;
+ const long NS_Timer = 2;
+ const long NS_Shutdown = 3;
+
+ /**
+ * autoRegister
+ *
+ * Enumerates directory looking for modules of all types and registers
+ * modules who have changed (modtime or size) since the last time
+ * autoRegister() was invoked.
+ *
+ * @param when : ID values of when the call is being made.
+ * @param directory : Directory the will be enumerated.
+ */
+ void autoRegister(in long when, in nsIFile directory);
+
+ /**
+ * autoRegisterComponent
+ *
+ * Loads module using appropriate loader and gives it an opportunity to
+ * register its CIDs if module's modtime or size changed since the last
+ * time this was called.
+ *
+ * @param when : ID values of when the call is being made.
+ * @param aFileLocation : File specification of module.
+ */
+ void autoRegisterComponent(in long when, in nsIFile aFileLocation);
+
+ /**
+ * autoUnregisterComponent
+ *
+ * Loads module using approriate loader and gives it an opportunity to
+ * unregister its CIDs
+ */
+ void autoUnregisterComponent(in long when, in nsIFile aFileLocation);
+
+ /**
+ * isRegistered
+ *
+ * Returns true if a factory or module is registered for CID aClass.
+ *
+ * @param aClass : ClassID queried for registeration
+ * @return : true if a factory or module is registered for CID aClass.
+ * false otherwise.
+ */
+ boolean isRegistered(in nsCIDRef aClass);
+
+ /**
+ * enumerateCLSIDs
+ *
+ * Enumerate the list of all registered ClassIDs.
+ *
+ * @return : enumerator for ClassIDs.
+ */
+ nsIEnumerator enumerateCLSIDs();
+
+ /**
+ * enumerateContractIDs
+ *
+ * Enumerate the list of all registered ContractIDs.
+ *
+ * @return : enumerator for ContractIDs.
+ */
+ nsIEnumerator enumerateContractIDs();
+};
+
+%{ C++
+/* include after the class def'n, because it needs to see it. */
+#include "nsComponentManagerUtils.h"
+%} C++
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h
new file mode 100644
index 00000000..a21ee7e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIComponentManagerUtils_h__
+#define nsIComponentManagerUtils_h__
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl
new file mode 100644
index 00000000..2a4a55db
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl
@@ -0,0 +1,243 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * The nsIComponentRegistrar interface.
+ * @status FROZEN
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+interface nsIFactory;
+interface nsISimpleEnumerator;
+
+[scriptable, uuid(2417cbfe-65ad-48a6-b4b6-eb84db174392)]
+interface nsIComponentRegistrar : nsISupports
+{
+ /**
+ * autoRegister
+ *
+ * Register a component file or all component files in a directory.
+ *
+ * Component files must have an associated loader and export the required
+ * symbols which this loader defines. For example, if the given file is a
+ * native library (which is built into XPCOM), it must export the symbol
+ * "NSGetModule". Other loaders may have different semantics.
+ *
+ * This method may only be called from the main thread.
+ *
+ * @param aSpec : Filename spec for component file's location. If aSpec
+ * is a directory, then every component file in the
+ * directory will be registered.
+ * If the aSpec is null, then the application component's
+ * directory as defined by NS_XPCOM_COMPONENT_DIR will be
+ * registered (see nsIDirectoryService.idl)
+ *
+ * @return NS_OK : Registration was successful.
+ * NS_ERROR: Method failure.
+ */
+ void autoRegister(in nsIFile aSpec);
+
+ /**
+ * autoUnregister
+ *
+ * Unregister a component file or all component files in a directory.
+ * This method may only be called from the main thread.
+ *
+ * @param aSpec : Filename spec for component file's location. If aSpec
+ * is a directory, the every component file in the directory
+ * will be registered.
+ * If aSpec is null, then the application component's
+ * directory as defined by NS_XPCOM_COMPONENT_DIR will be
+ * registered. (see nsIDirectoryService.idl)
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void autoUnregister(in nsIFile aSpec);
+
+
+ /**
+ * registerFactory
+ *
+ * Register a factory with a given ContractID, CID and Class Name.
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFactory : Factory that will be registered for CID aClass
+ *
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* method failure.
+ */
+ void registerFactory(in nsCIDRef aClass,
+ in string aClassName,
+ in string aContractID,
+ in nsIFactory aFactory);
+
+ /**
+ * unregisterFactory
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : CID being unregistered
+ * @param aFactory : Factory previously registered to create instances of
+ * CID aClass.
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void unregisterFactory(in nsCIDRef aClass,
+ in nsIFactory aFactory);
+
+ /**
+ * registerFactoryLocation
+ *
+ * Register a factory with a given ContractID, CID and Class Name
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader specifies.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aType : Component Type of CID aClass. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ *
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void registerFactoryLocation(in nsCIDRef aClass,
+ in string aClassName,
+ in string aContractID,
+ in nsIFile aFile,
+ in string aLoaderStr,
+ in string aType);
+
+ /**
+ * unregisterFactoryLocation
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : CID being unregistered
+ * @param aFile : Component File previously registered
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void unregisterFactoryLocation(in nsCIDRef aClass,
+ in nsIFile aFile);
+
+ /**
+ * isCIDRegistered
+ *
+ * Returns true if a factory is registered for the CID.
+ *
+ * @param aClass : CID queried for registeration
+ * @return : true if a factory is registered for CID
+ * false otherwise.
+ */
+ boolean isCIDRegistered(in nsCIDRef aClass);
+
+ /**
+ * isContractIDRegistered
+ *
+ * Returns true if a factory is registered for the contract id.
+ *
+ * @param aClass : contract id queried for registeration
+ * @return : true if a factory is registered for contract id
+ * false otherwise.
+ */
+ boolean isContractIDRegistered(in string aContractID);
+
+ /**
+ * enumerateCIDs
+ *
+ * Enumerate the list of all registered CIDs.
+ *
+ * @return : enumerator for CIDs. Elements of the enumeration can be QI'ed
+ * for the nsISupportsID interface. From the nsISupportsID, you
+ * can obtain the actual CID.
+ */
+ nsISimpleEnumerator enumerateCIDs();
+
+ /**
+ * enumerateContractIDs
+ *
+ * Enumerate the list of all registered ContractIDs.
+ *
+ * @return : enumerator for ContractIDs. Elements of the enumeration can be
+ * QI'ed for the nsISupportsCString interface. From the
+ * nsISupportsCString interface, you can obtain the actual
+ * Contract ID string.
+ */
+ nsISimpleEnumerator enumerateContractIDs();
+
+ /**
+ * CIDToContractID
+ *
+ * Returns the Contract ID for a given CID, if one exists and is registered.
+ *
+ * @return : Contract ID.
+ */
+ string CIDToContractID(in nsCIDRef aClass);
+
+ /**
+ * contractIDToCID
+ *
+ * Returns the CID for a given Contract ID, if one exists and is registered.
+ *
+ * @return : Contract ID.
+ */
+ nsCIDPtr contractIDToCID(in string aContractID);
+
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl b/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl
new file mode 100644
index 00000000..bda0b43a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl
@@ -0,0 +1,79 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * A class factory allows the creation of nsISupports derived
+ * components without specifying a concrete base class.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, object, uuid(00000001-0000-0000-c000-000000000046)]
+interface nsIFactory : nsISupports {
+ /**
+ * Creates an instance of a component.
+ *
+ * @param aOuter Pointer to a component that wishes to be aggregated
+ * in the resulting instance. This will be nsnull if no
+ * aggregation is requested.
+ * @param iid The IID of the interface being requested in
+ * the component which is being currently created.
+ * @param result [out] Pointer to the newly created instance, if successful.
+ * @return NS_OK - Component successfully created and the interface
+ * being requested was successfully returned in result.
+ * NS_NOINTERFACE - Interface not accessible.
+ * NS_ERROR_NO_AGGREGATION - if an 'outer' object is supplied, but the
+ * component is not aggregatable.
+ * NS_ERROR* - Method failure.
+ */
+ void createInstance(in nsISupports aOuter, in nsIIDRef iid,
+ [retval, iid_is(iid)] out nsQIResult result);
+
+ /**
+ * LockFactory provides the client a way to keep the component
+ * in memory until it is finished with it. The client can call
+ * LockFactory(PR_TRUE) to lock the factory and LockFactory(PR_FALSE)
+ * to release the factory.
+ *
+ * @param lock - Must be PR_TRUE or PR_FALSE
+ * @return NS_OK - If the lock operation was successful.
+ * NS_ERROR* - Method failure.
+ */
+ void lockFactory(in PRBool lock);
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIModule.idl b/src/libs/xpcom18a4/xpcom/components/nsIModule.idl
new file mode 100644
index 00000000..a71b9b13
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIModule.idl
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+interface nsIComponentManager;
+
+/**
+ * The nsIModule interface.
+ * @status FROZEN
+ */
+
+[scriptable, uuid(7392D032-5371-11d3-994E-00805FD26FEE)]
+interface nsIModule : nsISupports
+{
+ /**
+ * Object Instance Creation
+ *
+ * Obtains a Class Object from a nsIModule for a given CID and IID pair.
+ * This class object can either be query to a nsIFactory or a may be
+ * query to a nsIClassInfo.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aClass : ClassID of object instance requested
+ * @param aIID : IID of interface requested
+ *
+ */
+ void getClassObject(in nsIComponentManager aCompMgr,
+ in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [retval, iid_is(aIID)] out nsQIResult aResult);
+
+
+ /**
+ * One time registration callback
+ *
+ * When the nsIModule is discovered, this method will be
+ * called so that any setup registration can be preformed.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aLocation : The location of the nsIModule on disk
+ * @param aLoaderStr: Opaque loader specific string
+ * @param aType : Loader Type being used to load this module
+ */
+ void registerSelf(in nsIComponentManager aCompMgr,
+ in nsIFile aLocation,
+ in string aLoaderStr,
+ in string aType);
+ /**
+ * One time unregistration callback
+ *
+ * When the nsIModule is being unregistered, this method will be
+ * called so that any unregistration can be preformed
+ *
+ * @param aCompMgr : The global component manager
+ * @param aLocation : The location of the nsIModule on disk
+ * @param aLoaderStr : Opaque loader specific string
+ *
+ */
+ void unregisterSelf(in nsIComponentManager aCompMgr,
+ in nsIFile aLocation,
+ in string aLoaderStr);
+
+ /**
+ * Module load management
+ *
+ * @param aCompMgr : The global component manager
+ *
+ * @return indicates to the caller if the module can be unloaded.
+ * Returning PR_TRUE isn't a guarantee that the module will be
+ * unloaded. It constitues only willingness of the module to be
+ * unloaded. It is very important to ensure that no outstanding
+ * references to the module's code/data exist before returning
+ * PR_TRUE.
+ * Returning PR_FALSE guaratees that the module wont be unloaded.
+ */
+ boolean canUnload(in nsIComponentManager aCompMgr);
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl b/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl
new file mode 100644
index 00000000..c5d18111
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+[uuid(10d1a2a2-d816-458d-a4c3-0805ff0f7b31)]
+interface nsINativeComponentLoader : nsISupports
+{
+
+ /**
+ * addDependentLibrary
+ *
+ * This method informs the native component loader that the
+ * given component library referenced by |aFile| requires
+ * symbols that can be found in the library named |aLibName|.
+ *
+ * The native component loader is expected to resolve these
+ * external symobls prior to loading the component library.
+ *
+ * @param aFile
+ * The native component file location that is declaring a
+ * a dependency. This file is expected to be a DSO/DLL.
+ *
+ * @param aLibName
+ * This is a name of a library that the component requires.
+ * This file name is found in either the GRE bin directory
+ * or the application's bin directory. Full file path are
+ * also accepted. Passing nsnull for the |aLibName| will
+ * clear all dependencies. Note that non null aLibName
+ * values are expected to be in the native charset.
+ */
+
+ void addDependentLibrary(in nsIFile aFile, in string aLibName);
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl
new file mode 100644
index 00000000..200c2a69
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl
@@ -0,0 +1,119 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+
+/**
+ * The nsIServiceManager manager interface provides a means to obtain
+ * global services in an application. The service manager depends on the
+ * repository to find and instantiate factories to obtain services.
+ *
+ * Users of the service manager must first obtain a pointer to the global
+ * service manager by calling NS_GetServiceManager. After that,
+ * they can request specific services by calling GetService. When they are
+ * finished they can NS_RELEASE() the service as usual.
+ *
+ * A user of a service may keep references to particular services indefinitely
+ * and only must call Release when it shuts down.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(8bb35ed9-e332-462d-9155-4a002ab5c958)]
+interface nsIServiceManager : nsISupports
+{
+ /**
+ * getServiceByContractID
+ *
+ * Returns the instance that implements aClass or aContractID and the
+ * interface aIID. This may result in the instance being created.
+ *
+ * @param aClass or aContractID : aClass or aContractID of object
+ * instance requested
+ * @param aIID : IID of interface requested
+ * @param result : resulting service
+ */
+ void getService(in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ void getServiceByContractID(in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * isServiceInstantiated
+ *
+ * isServiceInstantiated will return a true if the service has already
+ * been created, otherwise false
+ *
+ * @param aClass or aContractID : aClass or aContractID of object
+ * instance requested
+ * @param aIID : IID of interface requested
+ * @param aIID : IID of interface requested
+ */
+ boolean isServiceInstantiated(in nsCIDRef aClass, in nsIIDRef aIID);
+ boolean isServiceInstantiatedByContractID(in string aContractID, in nsIIDRef aIID);
+};
+
+
+%{C++
+#define NS_ERROR_SERVICE_NOT_AVAILABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 22)
+/**
+ * @status DEPRECATED
+ */
+#define NS_ERROR_SERVICE_NOT_FOUND NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 22)
+/**
+ * @status DEPRECATED
+ */
+#define NS_ERROR_SERVICE_IN_USE NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 23)
+
+// Observing xpcom startup. If you component has not been created, it will be.
+#define NS_XPCOM_STARTUP_OBSERVER_ID "xpcom-startup"
+
+// Observing xpcom shutdown
+#define NS_XPCOM_SHUTDOWN_OBSERVER_ID "xpcom-shutdown"
+
+// Observing xpcom autoregistration. Topics will be 'start' and 'stop'.
+#define NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID "xpcom-autoregistration"
+
+#ifndef MOZILLA_STRICT_API
+#include "nsXPCOM.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIServiceManagerObsolete.h"
+#endif
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h
new file mode 100644
index 00000000..dc229c76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIServiceManagerObsolete_h___
+#define nsIServiceManagerObsolete_h___
+
+////////////////////////////////////////////////////////////////////
+//
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+//
+// Functions, classes, interfaces and types in this file are
+// obsolete. Use at your own risk.
+// Please see nsIServiceManager.idl for the supported interface
+// to the service manager.
+//
+////////////////////////////////////////////////////////////////////
+
+#include "nsIComponentManager.h"
+#include "nsID.h"
+
+#ifndef nsCOMPtr_h___
+#include "nsCOMPtr.h"
+#endif
+
+class nsIServiceManager;
+class nsIShutdownListener;
+class nsIDirectoryServiceProvider;
+
+class nsServiceManagerObsolete;
+
+#define NS_ISERVICEMANAGER_OBSOLETE_IID \
+{ /* cf0df3b0-3401-11d2-8163-006008119d7a */ \
+ 0xcf0df3b0, \
+ 0x3401, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+/**
+ * The nsIServiceManagerObsolete manager is obsolete. Please refer
+ * to nsIServiceManager.
+ */
+class nsIServiceManagerObsolete : public nsISupports {
+public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISERVICEMANAGER_OBSOLETE_IID);
+
+ /**
+ * RegisterService may be called explicitly to register a service
+ * with the service manager. If a service is not registered explicitly,
+ * the component manager will be used to create an instance according
+ * to the class ID specified.
+ */
+ NS_IMETHOD
+ RegisterService(const nsCID& aClass, nsISupports* aService) = 0;
+
+ /**
+ * Requests a service to be shut down, possibly unloading its DLL.
+ *
+ * @returns NS_OK - if shutdown was successful and service was unloaded,
+ * @returns NS_ERROR_SERVICE_NOT_FOUND - if shutdown failed because
+ * the service was not currently loaded
+ * @returns NS_ERROR_SERVICE_IN_USE - if shutdown failed because some
+ * user of the service wouldn't voluntarily release it by using
+ * a shutdown listener.
+ */
+ NS_IMETHOD
+ UnregisterService(const nsCID& aClass) = 0;
+
+ NS_IMETHOD
+ GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ NS_IMETHOD
+ ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // let's do it again, this time with ContractIDs...
+
+ NS_IMETHOD
+ RegisterService(const char* aContractID, nsISupports* aService) = 0;
+
+ NS_IMETHOD
+ UnregisterService(const char* aContractID) = 0;
+
+ NS_IMETHOD
+ GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ /* OBSOLETE */
+ NS_IMETHOD
+ ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+};
+
+// Interface to Global Services
+class NS_COM nsServiceManager {
+public:
+
+ static nsresult
+ RegisterService(const nsCID& aClass, nsISupports* aService);
+
+ static nsresult
+ UnregisterService(const nsCID& aClass);
+
+ static nsresult
+ GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ static nsresult
+ ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // let's do it again, this time with ContractIDs...
+
+ static nsresult
+ RegisterService(const char* aContractID, nsISupports* aService);
+
+ static nsresult
+ UnregisterService(const char* aContractID);
+
+ static nsresult
+ GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ static nsresult
+ ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // These methods return really nsIServiceManagerObsolete, but they are
+ // statically cast to nsIServiceManager to preserve backwards compatiblity.
+ static nsresult GetGlobalServiceManager(nsIServiceManager* *result);
+ static nsresult ShutdownGlobalServiceManager(nsIServiceManager* *result);
+};
+
+
+#define NS_DECL_NSISERVICEMANAGEROBSOLETE \
+ NS_IMETHOD RegisterService(const nsCID& aClass, nsISupports* aService); \
+ NS_IMETHOD UnregisterService(const nsCID& aClass);\
+ NS_IMETHOD GetService(const nsCID& aClass, const nsIID& aIID, nsISupports* *result, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD ReleaseService(const nsCID& aClass, nsISupports* service, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD RegisterService(const char* aContractID, nsISupports* aService);\
+ NS_IMETHOD UnregisterService(const char* aContractID);\
+ NS_IMETHOD GetService(const char* aContractID, const nsIID& aIID, nsISupports* *result, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD ReleaseService(const char* aContractID, nsISupports* service, nsIShutdownListener* shutdownListener);
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define NS_ISHUTDOWNLISTENER_IID \
+{ /* 56decae0-3406-11d2-8163-006008119d7a */ \
+ 0x56decae0, \
+ 0x3406, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+class nsIShutdownListener;
+
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ nsIShutdownListener* shutdownListener,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsServiceManager::GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(nsISupports**, aDestination),
+ shutdownListener);
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ nsIShutdownListener* shutdownListener,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsServiceManager::GetService(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(nsISupports**, aDestination),
+ shutdownListener);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+#endif /* nsIServiceManagerObsolete_h___ */
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h
new file mode 100644
index 00000000..b7b432af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIServiceManagerUtils_h__
+#define nsIServiceManagerUtils_h__
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Using servicemanager with COMPtrs
+class NS_COM nsGetServiceByCID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByCID( const nsCID& aCID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const nsCID& mCID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, 0, error);
+}
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, aServiceManager, error);
+}
+
+class NS_COM nsGetServiceByContractID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByContractID( const char* aContractID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+ // Implement a dummy destructor to workaround linking issue on Solaris gcc 4.8.2 (see @bugref{5838})
+ ~nsGetServiceByContractID() {}
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const char* mContractID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, aServiceManager, error);
+}
+
+class nsGetServiceFromCategory : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceFromCategory(const char* aCategory, const char* aEntry,
+ nsISupports* aServiceManager,
+ nsresult* aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+ protected:
+ const char* mCategory;
+ const char* mEntry;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceFromCategory
+do_GetServiceFromCategory( const char* category, const char* entry,
+ nsresult* error = 0)
+{
+ return nsGetServiceFromCategory(category, entry, 0, error);
+}
+
+// type-safe shortcuts for calling |GetService|
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetServiceByContractID(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsModule.h b/src/libs/xpcom18a4/xpcom/components/nsModule.h
new file mode 100644
index 00000000..56a06354
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsModule.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Marco Pesenti Gritti <marco@gnome.org>
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsModule_h__
+#define nsModule_h__
+
+#include "nsIModule.h"
+#include "nsIFile.h"
+#include "nsIComponentManager.h"
+
+// Exported Function from module dll to Create the nsIModule
+#define NS_GET_MODULE_SYMBOL "NSGetModule"
+
+extern "C" NS_EXPORT nsresult PR_CALLBACK
+NSGetModule(nsIComponentManager *aCompMgr,
+ nsIFile* location,
+ nsIModule** return_cobj);
+
+typedef nsresult (PR_CALLBACK *nsGetModuleProc)(nsIComponentManager *aCompMgr,
+ nsIFile* location,
+ nsIModule** return_cobj);
+
+
+#endif /* nsModule_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp
new file mode 100644
index 00000000..a3fd5df8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp
@@ -0,0 +1,1150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+#include "prmem.h"
+#include "prerror.h"
+#include "prsystem.h" // PR_GetDirectorySeparator
+#include "nsNativeComponentLoader.h"
+#include "nsComponentManager.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsIModule.h"
+#include "xcDll.h"
+#include "nsHashtable.h"
+#include "nsXPIDLString.h"
+#include "nsCRT.h"
+#include "nsIObserverService.h"
+
+#if defined(XP_MAC) // sdagley dougt fix
+#include <Files.h>
+#include <Errors.h>
+#include "nsILocalFileMac.h"
+#endif
+
+#include "prlog.h"
+extern PRLogModuleInfo *nsComponentManagerLog;
+
+static PRBool PR_CALLBACK
+DLLStore_Destroy(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsDll* entry = NS_STATIC_CAST(nsDll*, aData);
+ delete entry;
+ return PR_TRUE;
+}
+
+nsNativeComponentLoader::nsNativeComponentLoader() :
+ mCompMgr(nsnull),
+ mLoadedDependentLibs(16, PR_TRUE),
+ mDllStore(nsnull, nsnull, DLLStore_Destroy,
+ nsnull, 256, PR_TRUE)
+{
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsNativeComponentLoader,
+ nsIComponentLoader,
+ nsINativeComponentLoader)
+
+NS_IMETHODIMP
+nsNativeComponentLoader::GetFactory(const nsIID & aCID,
+ const char *aLocation,
+ const char *aType,
+ nsIFactory **_retval)
+{
+ nsresult rv;
+
+ if (!_retval)
+ return NS_ERROR_NULL_POINTER;
+
+ /* use a hashtable of WeakRefs to store the factory object? */
+
+ /* Should this all live in xcDll? */
+ nsDll *dll;
+ rv = CreateDll(nsnull, aLocation, &dll);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!dll)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!dll->IsLoaded()) {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: loading \"%s\"",
+ displayPath.get()));
+#endif
+ if (!dll->Load()) {
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsNativeComponentLoader: load FAILED"));
+
+ char errorMsg[1024] = "<unknown; can't get error from NSPR>";
+
+ if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
+ PR_GetErrorText(errorMsg);
+
+ DumpLoadError(dll, "GetFactory", errorMsg);
+
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ /* Get service manager for factory */
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(rv))
+ return rv; // XXX translate error code?
+
+ rv = GetFactoryFromModule(dll, aCID, _retval);
+
+ PR_LOG(nsComponentManagerLog, NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
+ ("nsNativeComponentLoader: Factory creation %s for %s",
+ (NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"),
+ aLocation));
+
+ // If the dll failed to get us a factory. But the dll registered that
+ // it would be able to create a factory for this CID. mmh!
+ // We cannot just delete the dll as the dll could be hosting
+ // other CID for which factory creation can pass.
+ // We will just let it be. The effect will be next time we try
+ // creating the object, we will query the dll again. Since the
+ // dll is loaded, this aint a big hit. So for optimized builds
+ // this is ok to limp along.
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Factory creation failed");
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
+{
+ mCompMgr = aCompMgr;
+ if (!mCompMgr)
+ return NS_ERROR_INVALID_ARG;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNativeComponentLoader::AutoRegisterComponents(PRInt32 aWhen,
+ nsIFile *aDirectory)
+{
+#ifdef DEBUG
+ /* do we _really_ want to print this every time? */
+ fprintf(stderr, "nsNativeComponentLoader: autoregistering begins.\n");
+#endif
+
+ nsresult rv = RegisterComponentsInDir(aWhen, aDirectory);
+
+#ifdef DEBUG
+ fprintf(stderr, "nsNativeComponentLoader: autoregistering %s\n",
+ NS_FAILED(rv) ? "FAILED" : "succeeded");
+#endif
+
+ return rv;
+}
+
+nsresult
+nsNativeComponentLoader::RegisterComponentsInDir(PRInt32 when,
+ nsIFile *dir)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ PRBool isDir = PR_FALSE;
+
+#if 0
+ // Going to many of these checks is a performance hit on the mac.
+ // Since these routines are called relatively infrequently and
+ // we will fail anyway down the line if a directory aint there,
+ // we are commenting this check out.
+
+ // Make sure we are dealing with a directory
+ rv = dir->IsDirectory(&isDir);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!isDir)
+ return NS_ERROR_INVALID_ARG;
+#endif /* 0 */
+
+ // Create a directory iterator
+ nsCOMPtr<nsISimpleEnumerator> dirIterator;
+ rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator));
+
+ if (NS_FAILED(rv)) return rv;
+
+ // whip through the directory to register every file
+ nsCOMPtr<nsIFile> dirEntry;
+ PRBool more = PR_FALSE;
+
+ rv = dirIterator->HasMoreElements(&more);
+ if (NS_FAILED(rv)) return rv;
+ while (more == PR_TRUE)
+ {
+ rv = dirIterator->GetNext((nsISupports**)getter_AddRefs(dirEntry));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = dirEntry->IsDirectory(&isDir);
+ if (NS_SUCCEEDED(rv))
+ {
+ if (isDir == PR_TRUE)
+ {
+ // This is a directory. Grovel for components into the directory.
+#ifdef RT_OS_DARWIN // But not if it's a debug bundle.
+ nsCAutoString leafName;
+ rv = dirEntry->GetNativeLeafName(leafName);
+ if ( NS_FAILED(rv)
+ || leafName.Length() < sizeof(".dSYM")
+ || PL_strcasecmp(leafName.get() + (leafName.Length() - sizeof(".dSYM") + 1), ".dSYM"))
+#endif
+ rv = RegisterComponentsInDir(when, dirEntry);
+ }
+ else
+ {
+ PRBool registered;
+ // This is a file. Try to register it.
+ rv = AutoRegisterComponent(when, dirEntry, &registered);
+ }
+ }
+ }
+ rv = dirIterator->HasMoreElements(&more);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return rv;
+}
+
+static nsresult PR_CALLBACK
+nsFreeLibrary(nsDll *dll, nsIServiceManager *serviceMgr, PRInt32 when)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!dll || dll->IsLoaded() == PR_FALSE)
+ {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // Get if the dll was marked for unload in an earlier round
+ PRBool dllMarkedForUnload = dll->IsMarkedForUnload();
+
+ // Reset dll marking for unload just in case we return with
+ // an error.
+ dll->MarkForUnload(PR_FALSE);
+
+ PRBool canUnload = PR_FALSE;
+
+ // Get the module object
+ nsCOMPtr<nsIModule> mobj;
+ /* XXXshaver cheat and use the global component manager */
+ rv = dll->GetModule(NS_STATIC_CAST(nsIComponentManager*, nsComponentManagerImpl::gComponentManager),
+ getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = mobj->CanUnload(nsComponentManagerImpl::gComponentManager, &canUnload);
+ }
+
+ mobj = nsnull; // Release our reference to the module object
+ // When shutting down, whether we can unload the dll or not,
+ // we will shutdown the dll to release any memory it has got
+ if (when == nsIComponentManagerObsolete::NS_Shutdown)
+ {
+ dll->Shutdown();
+ }
+
+ // Check error status on CanUnload() call
+ if (NS_FAILED(rv))
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: nsIModule::CanUnload() returned error for %s.",
+ displayPath.get()));
+#endif
+ return rv;
+ }
+
+ if (canUnload)
+ {
+ if (dllMarkedForUnload)
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + Unloading \"%s\".", displayPath.get()));
+#endif
+
+#ifdef DEBUG_dougt
+ // XXX dlls aren't counting their outstanding instances correctly
+ // XXX hence, dont unload until this gets enforced.
+ rv = dll->Unload();
+#endif /* 0 */
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: Ready for unload \"%s\".", displayPath.get()));
+#endif
+ }
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: NOT ready for unload %s", displayPath.get()));
+#endif
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+struct freeLibrariesClosure
+{
+ nsIServiceManager *serviceMgr;
+ PRInt32 when;
+};
+
+static PRBool PR_CALLBACK
+nsFreeLibraryEnum(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsDll *dll = (nsDll *) aData;
+ struct freeLibrariesClosure *callData = (struct freeLibrariesClosure *) closure;
+ nsFreeLibrary(dll,
+ (callData ? callData->serviceMgr : NULL),
+ (callData ? callData->when : nsIComponentManagerObsolete::NS_Timer));
+ return PR_TRUE;
+}
+
+/*
+ * SelfRegisterDll
+ *
+ * Given a dll abstraction, this will load, selfregister the dll and
+ * unload the dll.
+ *
+ */
+nsresult
+nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
+ const char *registryLocation,
+ PRBool deferred)
+{
+ // Precondition: dll is not loaded already, unless we're deferred
+ PR_ASSERT(deferred || dll->IsLoaded() == PR_FALSE);
+
+ nsresult res;
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(res)) return res;
+
+ if (dll->Load() == PR_FALSE)
+ {
+ // Cannot load. Probably not a dll.
+ char errorMsg[1024] = "Cannot get error from nspr. Not enough memory.";
+ if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
+ PR_GetErrorText(errorMsg);
+
+ DumpLoadError(dll, "SelfRegisterDll", errorMsg);
+
+ return NS_ERROR_FAILURE;
+ }
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: Loaded \"%s\".", displayPath.get()));
+#endif
+
+ // Tell the module to self register
+ nsCOMPtr<nsIFile> fs;
+ nsCOMPtr<nsIModule> mobj;
+ res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(res))
+ {
+ /*************************************************************
+ * WARNING: Why are use introducing 'res2' here and then *
+ * later assigning it to 'res' rather than just using 'res'? *
+ * This is because this code turns up a code-generation bug *
+ * in VC6 on NT. Assigning to 'res' on the next line causes *
+ * the value of 'dll' to get nulled out! The two seem to be *
+ * getting aliased together during compilation. *
+ *************************************************************/
+ nsresult res2 = dll->GetDllSpec(getter_AddRefs(fs)); // don't change 'res2' -- see warning, above
+ if (NS_SUCCEEDED(res2)) {
+ // in the case of re-registering a component, we want to remove
+ // any optional data that this file may have had.
+ AddDependentLibrary(fs, nsnull);
+
+ res = mobj->RegisterSelf(mCompMgr, fs, registryLocation,
+ nativeComponentType);
+ }
+ else
+ {
+ res = res2; // don't take this out -- see warning, above
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: dll->GetDllSpec() on %s FAILED.",
+ displayPath.get()));
+#endif
+ }
+ mobj = NULL; // Force a release of the Module object before unload()
+ }
+
+ // Update the timestamp and size of the dll in registry
+ // Don't enter deferred modules in the registry, because it might only be
+ // able to register on some later autoreg, after another component has been
+ // installed.
+ if (res != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ PRInt64 modTime;
+ if (!fs)
+ return res;
+
+ fs->GetLastModifiedTime(&modTime);
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ if (!manager)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> fs;
+ res = dll->GetDllSpec(getter_AddRefs(fs));
+ if (NS_FAILED(res)) return res;
+
+ manager->SaveFileInfo(fs, registryLocation, modTime);
+ }
+
+ return res;
+}
+
+//
+// MOZ_DEMANGLE_SYMBOLS is only a linux + MOZ_DEBUG thing.
+//
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include "nsTraceRefcntImpl.h" // for nsTraceRefcntImpl::DemangleSymbol()
+#endif
+
+nsresult
+nsNativeComponentLoader::DumpLoadError(nsDll *dll,
+ const char *aCallerName,
+ const char *aNsprErrorMsg)
+{
+ PR_ASSERT(aCallerName != NULL);
+
+ if (nsnull == dll || nsnull == aNsprErrorMsg)
+ return NS_OK;
+
+ nsCAutoString errorMsg(aNsprErrorMsg);
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ // Demangle undefined symbols
+ nsCAutoString undefinedMagicString("undefined symbol:");
+
+ PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE);
+
+ if (offset != kNotFound)
+ {
+ nsCAutoString symbol(errorMsg);
+ nsCAutoString demangledSymbol;
+
+ symbol.Cut(0,offset);
+
+ symbol.Cut(0,undefinedMagicString.Length());
+
+ symbol.StripWhitespace();
+
+ char demangled[4096] = "\0";
+
+ nsTraceRefcntImpl::DemangleSymbol(symbol.get(),demangled,sizeof(demangled));
+
+ if (demangled && *demangled != '\0')
+ demangledSymbol = demangled;
+
+ if (!demangledSymbol.IsEmpty())
+ {
+ nsCAutoString tmp(errorMsg);
+
+
+ tmp.Cut(offset + undefinedMagicString.Length(),
+ tmp.Length() - offset - undefinedMagicString.Length());
+
+ tmp += " \n";
+
+ tmp += demangledSymbol;
+
+ errorMsg = tmp;
+ }
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+#ifdef DEBUG
+ fprintf(stderr,
+ "nsNativeComponentLoader: %s(%s) Load FAILED with error: %s\n",
+ aCallerName,
+ displayPath.get(),
+ errorMsg.get());
+#endif
+
+ // Do NSPR log
+#ifdef PR_LOGGING
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsNativeComponentLoader: %s(%s) Load FAILED with error: %s",
+ aCallerName,
+ displayPath.get(),
+ errorMsg.get()));
+#endif
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll)
+{
+ nsresult res;
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(res)) return res;
+
+ if (dll->Load() == PR_FALSE)
+ {
+ // Cannot load. Probably not a dll.
+ return(NS_ERROR_FAILURE);
+ }
+
+ // Tell the module to self register
+ nsCOMPtr<nsIModule> mobj;
+ res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(res))
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: %s using nsIModule to unregister self.", displayPath.get()));
+#endif
+ nsCOMPtr<nsIFile> fs;
+ res = dll->GetDllSpec(getter_AddRefs(fs));
+ if (NS_FAILED(res)) return res;
+ // Get registry location for spec
+ nsXPIDLCString registryName;
+
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &res);
+ if (obsoleteManager)
+ res = obsoleteManager->RegistryLocationForSpec(fs, getter_Copies(registryName));
+
+ if (NS_FAILED(res)) return res;
+ mobj->UnregisterSelf(mCompMgr, fs, registryName);
+ }
+ return res;
+}
+
+nsresult
+nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *unregistered)
+{
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *unregistered = PR_FALSE;
+
+ nsXPIDLCString persistentDescriptor;
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->RegistryLocationForSpec(component,
+ getter_Copies(persistentDescriptor));
+ if (NS_FAILED(rv)) return rv;
+
+ // Notify observers, if any, of autoregistration work
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ (void) observerService->NotifyObservers(mgr,
+ NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ NS_LITERAL_STRING("Unregistering native component").get());
+ }
+ }
+
+ nsDll *dll = NULL;
+ rv = CreateDll(component, persistentDescriptor, &dll);
+ if (NS_FAILED(rv) || dll == NULL) return rv;
+
+ rv = SelfUnregisterDll(dll);
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
+ ("nsNativeComponentLoader: AutoUnregistration for %s %s.",
+ (NS_FAILED(rv) ? "FAILED" : "succeeded"), displayPath.get()));
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Remove any autoreg info about this dll
+ nsCStringKey key(persistentDescriptor);
+ mDllStore.RemoveAndDelete(&key);
+
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ NS_ASSERTION(manager, "Something is terribly wrong");
+
+ manager->RemoveFileInfo(component, nsnull);
+
+ *unregistered = PR_TRUE;
+ return rv;
+}
+
+nsresult
+nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *registered)
+{
+ nsresult rv;
+ if (!registered)
+ return NS_ERROR_NULL_POINTER;
+
+ *registered = PR_FALSE;
+
+#ifndef VBOX
+ /* this should be a pref or registry entry, or something */
+ static const char *ValidDllExtensions[] = {
+ ".dll", /* Windows */
+ ".so", /* Unix */
+ ".shlb", /* Mac ? */
+ ".dso", /* Unix ? */
+ ".dylib", /* Unix: Mach */
+ ".so.1.0", /* Unix: BSD */
+ ".sl", /* Unix: HP-UX */
+#if defined(VMS)
+ ".exe", /* Open VMS */
+#endif
+ ".dlm", /* new for all platforms */
+ NULL
+ };
+
+ *registered = PR_FALSE;
+
+#if 0
+ // This is a performance hit on mac. Since we have already checked
+ // this; plus is we dont, load will fail anyway later on, this
+ // is being commented out.
+
+ // Ensure we are dealing with a file as opposed to a dir
+ PRBool b = PR_FALSE;
+
+ rv = component->IsFile(&b);
+ if (NS_FAILED(rv) || !b)
+ return rv;
+#endif /* 0 */
+
+ // deal only with files that have a valid extension
+ PRBool validExtension = PR_FALSE;
+
+#if defined(XP_MAC) // sdagley dougt fix
+ // rjc - on Mac, check the file's type code (skip checking the creator code)
+
+ nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(component);
+ if (localFileMac)
+ {
+ OSType type;
+ rv = localFileMac->GetFileType(&type);
+ if (NS_SUCCEEDED(rv))
+ {
+ // on Mac, Mozilla shared libraries are of type 'shlb'
+ // Note: we don't check the creator (which for Mozilla is 'MOZZ')
+ // so that 3rd party shared libraries will be noticed!
+ validExtension = ((type == 'shlb') || (type == 'NSPL'));
+ }
+ }
+
+#else
+ nsCAutoString leafName;
+ rv = component->GetNativeLeafName(leafName);
+ if (NS_FAILED(rv)) return rv;
+ int flen = leafName.Length();
+ for (int i=0; ValidDllExtensions[i] != NULL; i++)
+ {
+ int extlen = PL_strlen(ValidDllExtensions[i]);
+
+ // Does fullname end with this extension
+ if (flen >= extlen &&
+ !PL_strcasecmp(leafName.get() + (flen - extlen), ValidDllExtensions[i])
+ )
+ {
+ validExtension = PR_TRUE;
+ break;
+ }
+ }
+#endif
+
+ if (validExtension == PR_FALSE)
+ // Skip invalid extensions
+ return NS_OK;
+
+#else /* VBOX */
+ /* VBox: Only one valid suffix exist, so dispense with the the list. */
+# ifdef RT_OS_DARWIN
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.dylib";
+# else
+ static const char s_szSuff[] = ".dylib";
+ static const char s_szSuffInvalid[] = "-x86.dylib";
+# endif
+# elif defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.dll";
+#else
+ static const char s_szSuff[] = ".dll";
+ static const char s_szSuffInvalid[] = "-x86.dll";
+# endif
+# else
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.so";
+#else
+ static const char s_szSuff[] = ".so";
+ static const char s_szSuffInvalid[] = "-x86.so";
+# endif
+# endif
+
+ nsCAutoString strLeafName;
+ rv = component->GetNativeLeafName(strLeafName);
+ if (NS_FAILED(rv))
+ return rv;
+ size_t cchLeafName = strLeafName.Length();
+ if ( cchLeafName <= sizeof(s_szSuff)
+ || PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuff) + 1, s_szSuff))
+ {
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("Skipping '%s'...", strLeafName.get()));
+ return NS_OK; /* skip */
+ }
+# ifndef VBOX_IN_32_ON_64_MAIN_API
+ if ( cchLeafName >= sizeof(s_szSuffInvalid)
+ && !PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuffInvalid) + 1, s_szSuffInvalid))
+ {
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("Skipping '%s' (#2)...", strLeafName.get()));
+ return NS_OK; /* skip */
+ }
+# endif
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("... '%s'", strLeafName.get()));
+#endif /* VBOX */
+
+ nsXPIDLCString persistentDescriptor;
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->RegistryLocationForSpec(component,
+ getter_Copies(persistentDescriptor));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(persistentDescriptor);
+
+ // Get the registry representation of the dll, if any
+ nsDll *dll;
+ rv = CreateDll(component, persistentDescriptor, &dll);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (dll != NULL)
+ {
+ // We already have seen this dll. Check if this dll changed
+ if (!dll->HasChanged())
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ // Dll hasn't changed. Skip.
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + nsDll not changed \"%s\". Skipping...",
+ displayPath.get()));
+#endif
+ *registered = PR_TRUE;
+ return NS_OK;
+ }
+
+ // Aagh! the dll has changed since the last time we saw it.
+ // re-register dll
+
+
+ // Notify observers, if any, of autoregistration work
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ // this string can't come from a string bundle, because we
+ // don't have string bundles yet.
+ NS_ConvertASCIItoUCS2 fileName("(no name)");
+
+ // get the file name
+ nsCOMPtr<nsIFile> dllSpec;
+ if (NS_SUCCEEDED(dll->GetDllSpec(getter_AddRefs(dllSpec))) && dllSpec)
+ {
+ dllSpec->GetLeafName(fileName);
+ }
+
+ // this string can't come from a string bundle, because we
+ // don't have string bundles yet.
+ (void) observerService->
+ NotifyObservers(mgr,
+ NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ PromiseFlatString(NS_LITERAL_STRING("Registering native component ") +
+ fileName).get());
+ }
+ }
+
+ if (dll->IsLoaded())
+ {
+ // We loaded the old version of the dll and now we find that the
+ // on-disk copy if newer. Try to unload the dll.
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+
+ rv = nsFreeLibrary(dll, serviceMgr, when);
+ if (NS_FAILED(rv))
+ {
+ // THIS IS THE WORST SITUATION TO BE IN.
+ // Dll doesn't want to be unloaded. Cannot re-register
+ // this dll.
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: *** Dll already loaded. "
+ "Cannot unload either. Hence cannot re-register "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return rv;
+ }
+ else {
+ // dll doesn't have a CanUnload proc. Guess it is
+ // ok to unload it.
+ dll->Unload();
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + Unloading \"%s\". (no CanUnloadProc).",
+ displayPath.get()));
+#endif
+ }
+
+ } // dll isloaded
+
+ // Sanity.
+ if (dll->IsLoaded())
+ {
+ // We went through all the above to make sure the dll
+ // is unloaded. And here we are with the dll still
+ // loaded. Whoever taught dp programming...
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: Dll still loaded. Cannot re-register "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return NS_ERROR_FAILURE;
+ }
+ } // dll != NULL
+ else
+ {
+ // Create and add the dll to the mDllStore
+ // It is ok to do this even if the creation of nsDll
+ // didnt succeed. That way we wont do this again
+ // when we encounter the same dll.
+ dll = new nsDll(component, this);
+ if (dll == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mDllStore.Put(&key, (void *) dll);
+ } // dll == NULL
+
+ // Either we are seeing the dll for the first time or the dll has
+ // changed since we last saw it and it is unloaded successfully.
+ //
+ // Now we can try register the dll for sure.
+ nsresult res = SelfRegisterDll(dll, persistentDescriptor, PR_FALSE);
+ if (NS_FAILED(res))
+ {
+ if (res == NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ /* defer for later loading */
+ mDeferredComponents.AppendElement(dll);
+ *registered = PR_TRUE;
+ return NS_OK;
+ } else {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: Autoregistration FAILED for "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: Autoregistration Passed for "
+ "\"%s\".", displayPath.get()));
+#endif
+ // Marking dll along with modified time and size in the
+ // registry happens at PlatformRegister(). No need to do it
+ // here again.
+ *registered = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
+ PRBool *aRegistered)
+{
+#ifdef DEBUG
+ fprintf(stderr, "nNCL: registering deferred (%d)\n",
+ mDeferredComponents.Count());
+#endif
+ *aRegistered = PR_FALSE;
+ if (!mDeferredComponents.Count())
+ return NS_OK;
+
+ for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
+ nsDll *dll = NS_STATIC_CAST(nsDll *, mDeferredComponents[i]);
+ nsresult rv = SelfRegisterDll(dll,
+ nsnull,
+ PR_TRUE);
+ if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ if (NS_SUCCEEDED(rv))
+ *aRegistered = PR_TRUE;
+ mDeferredComponents.RemoveElementAt(i);
+ }
+ }
+#ifdef DEBUG
+ if (*aRegistered)
+ fprintf(stderr, "nNCL: registered deferred, %d left\n",
+ mDeferredComponents.Count());
+ else
+ fprintf(stderr, "nNCL: didn't register any components, %d left\n",
+ mDeferredComponents.Count());
+#endif
+ /* are there any fatal errors? */
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::OnRegister(const nsIID &aCID, const char *aType,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLocation,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsNativeComponentLoader: Unloading...."));
+
+ struct freeLibrariesClosure callData;
+ callData.serviceMgr = NULL; // XXX need to get this as a parameter
+ callData.when = aWhen;
+
+ // Cycle through the dlls checking to see if they want to be unloaded
+ mDllStore.Enumerate(nsFreeLibraryEnum, &callData);
+ return NS_OK;
+}
+
+//
+// CreateDll
+// The only way to create a dll or get it from the dll cache. This will
+// be called in multiple situations:
+//
+// 1. Autoregister will create one for each dll it is trying to register. This
+// call will be passing a spec in.
+// {spec, NULL, 0, 0}
+//
+// 2. GetFactory() This will call CreateDll() with a null spec but will give
+// the registry represented name of the dll. If modtime and size are zero,
+// we will go the registry to find the right modtime and size.
+// {NULL, rel:libpref.so, 0, 0}
+//
+// 3. Prepopulation of dllCache A dll object created off a registry entry.
+// Specifically dll name is stored in rel: or abs: or lib: formats in the
+// registry along with its lastModTime and fileSize.
+// {NULL, rel:libpref.so, 8985659, 20987}
+nsresult
+nsNativeComponentLoader::CreateDll(nsIFile *aSpec,
+ const char *aLocation,
+ nsDll **aDll)
+{
+ nsDll *dll;
+ nsCOMPtr<nsIFile> dllSpec;
+ nsCOMPtr<nsIFile> spec;
+ nsresult rv;
+
+ nsCStringKey key(aLocation);
+ dll = (nsDll *)mDllStore.Get(&key);
+ if (dll)
+ {
+ *aDll = dll;
+ return NS_OK;
+ }
+
+ if (!aSpec)
+ {
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->SpecForRegistryLocation(aLocation,
+ getter_AddRefs(spec));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ spec = aSpec;
+ }
+
+ if (!dll)
+ {
+ dll = new nsDll(spec, this);
+ if (!dll)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ *aDll = dll;
+ mDllStore.Put(&key, dll);
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
+ nsIFactory **aFactory)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIModule> module;
+ rv = aDll->GetModule(mCompMgr, getter_AddRefs(module));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return module->GetClassObject(mCompMgr, aCID, NS_GET_IID(nsIFactory),
+ (void **)aFactory);
+}
+
+
+NS_IMETHODIMP
+nsNativeComponentLoader::AddDependentLibrary(nsIFile* aFile, const char* libName)
+{
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ if (!manager)
+ {
+ NS_WARNING("Something is terribly wrong");
+ return NS_ERROR_FAILURE;
+ }
+
+ // the native component loader uses the optional data
+ // to store a space delimited list of dependent library
+ // names
+
+ if (!libName)
+ {
+ manager->SetOptionalData(aFile, nsnull, nsnull);
+ return NS_OK;
+ }
+
+ nsXPIDLCString data;
+ manager->GetOptionalData(aFile, nsnull, getter_Copies(data));
+
+ if (!data.IsEmpty())
+ data.AppendLiteral(" ");
+
+ data.Append(nsDependentCString(libName));
+
+ manager->SetOptionalData(aFile, nsnull, data);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h
new file mode 100644
index 00000000..818596ec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.h"
+#include "nsIComponentLoader.h"
+#include "nsIComponentManager.h"
+#include "nsDirectoryService.h"
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsVoidArray.h"
+#include "xcDll.h"
+#include "nsINativeComponentLoader.h"
+
+#ifndef nsNativeComponentLoader_h__
+#define nsNativeComponentLoader_h__
+
+class nsNativeComponentLoader : public nsIComponentLoader, public nsINativeComponentLoader {
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMPONENTLOADER
+ NS_DECL_NSINATIVECOMPONENTLOADER
+
+ nsNativeComponentLoader();
+
+ nsIComponentManager* mCompMgr; // weak reference -- backpointer
+ nsHashtable mLoadedDependentLibs;
+
+ private:
+ nsObjectHashtable mDllStore;
+ nsVoidArray mDeferredComponents;
+
+ ~nsNativeComponentLoader() {}
+
+ NS_IMETHOD RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
+
+ nsresult CreateDll(nsIFile *aSpec, const char *aLocation, nsDll **aDll);
+ nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation,
+ PRBool deferred);
+ nsresult SelfUnregisterDll(nsDll *dll);
+ nsresult GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
+ nsIFactory **aFactory);
+
+ nsresult DumpLoadError(nsDll *dll,
+ const char *aCallerName,
+ const char *aNsprErrorMsg);
+};
+
+#endif /* nsNativeComponentLoader_h__ */
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h b/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h
new file mode 100644
index 00000000..da3e7a43
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h
@@ -0,0 +1,27 @@
+
+#ifndef OBSOLETE_MODULE_LOADING
+/*
+ * Prototypes for dynamic library export functions. Your DLL/DSO needs to export
+ * these methods to play in the component world.
+ *
+ * THIS IS OBSOLETE. Look at nsIModule.idl
+ */
+
+extern "C" NS_EXPORT nsresult NSGetFactory(nsISupports* aServMgr,
+ const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory **aFactory);
+extern "C" NS_EXPORT PRBool NSCanUnload(nsISupports* aServMgr);
+extern "C" NS_EXPORT nsresult NSRegisterSelf(nsISupports* aServMgr, const char *fullpath);
+extern "C" NS_EXPORT nsresult NSUnregisterSelf(nsISupports* aServMgr, const char *fullpath);
+
+typedef nsresult (*nsFactoryProc)(nsISupports* aServMgr,
+ const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory **aFactory);
+typedef PRBool (*nsCanUnloadProc)(nsISupports* aServMgr);
+typedef nsresult (*nsRegisterProc)(nsISupports* aServMgr, const char *path);
+typedef nsresult (*nsUnregisterProc)(nsISupports* aServMgr, const char *path);
+#endif /* OBSOLETE_MODULE_LOADING */
diff --git a/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp b/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp
new file mode 100644
index 00000000..dd6856d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp
@@ -0,0 +1,155 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsComponentManager.h"
+
+extern PRBool gXPCOMShuttingDown;
+
+// Global service manager interface (see nsIServiceManagerObsolete.h)
+
+nsresult
+nsServiceManager::GetGlobalServiceManager(nsIServiceManager* *result)
+{
+ if (gXPCOMShuttingDown)
+ return NS_ERROR_UNEXPECTED;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ // this method does not addref for historical reasons.
+ // we return the nsIServiceManagerObsolete interface via a cast.
+ *result = (nsIServiceManager*) NS_STATIC_CAST(nsIServiceManagerObsolete*,
+ nsComponentManagerImpl::gComponentManager);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::ShutdownGlobalServiceManager(nsIServiceManager* *result)
+{
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->GetService(aClass, aIID, (void**)result);
+}
+
+nsresult
+nsServiceManager::ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::RegisterService(const nsCID& aClass, nsISupports* aService)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->RegisterService(aClass, aService);
+}
+
+nsresult
+nsServiceManager::UnregisterService(const nsCID& aClass)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->UnregisterService(aClass);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// let's do it again, this time with ContractIDs...
+
+nsresult
+nsServiceManager::GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->GetServiceByContractID(aContractID, aIID, (void**)result);
+}
+
+nsresult
+nsServiceManager::ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_RELEASE(service);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::RegisterService(const char* aContractID, nsISupports* aService)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->RegisterService(aContractID, aService);
+}
+
+nsresult
+nsServiceManager::UnregisterService(const char* aContractID)
+{
+ // Don't create the global service manager here because we might
+ // be shutting down, and releasing all the services in its
+ // destructor
+ if (gXPCOMShuttingDown)
+ return NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->UnregisterService(aContractID);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h b/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h
new file mode 100644
index 00000000..c770afdc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIModule.h"
+#include "nsModule.h"
+
+struct nsStaticModuleInfo {
+ const char *name;
+ nsGetModuleProc getModule;
+};
+
+// Must be implemented by some part of the app, if we're building the
+// static component loader.
+extern "C" {
+typedef nsresult (PR_CALLBACK *NSGetStaticModuleInfoFunc)(nsStaticModuleInfo **info, PRUint32 *count);
+extern NS_COM NSGetStaticModuleInfoFunc NSGetStaticModuleInfo;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp b/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp
new file mode 100644
index 00000000..b17b74bb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * 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 of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsStaticComponent.h"
+#include "nsIComponentLoader.h"
+#include "nsVoidArray.h"
+#include "pldhash.h"
+#include NEW_H
+#include <stdio.h>
+
+struct StaticModuleInfo : public PLDHashEntryHdr {
+ nsStaticModuleInfo info;
+ nsCOMPtr<nsIModule> module;
+};
+
+class nsStaticComponentLoader : public nsIComponentLoader
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMPONENTLOADER
+
+ nsStaticComponentLoader() :
+ mAutoRegistered(PR_FALSE), mLoadedInfo(PR_FALSE) {
+ }
+
+ static NS_HIDDEN_(PLDHashOperator) PR_CALLBACK
+ info_RegisterSelf(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg);
+
+private:
+ ~nsStaticComponentLoader() {
+ if (mInfoHash.ops)
+ PL_DHashTableFinish(&mInfoHash);
+ }
+
+protected:
+ nsresult GetModuleInfo();
+ nsresult GetInfoFor(const char *aLocation, StaticModuleInfo **retval);
+
+ PRBool mAutoRegistered;
+ PRBool mLoadedInfo;
+ nsCOMPtr<nsIComponentManager> mComponentMgr;
+ PLDHashTable mInfoHash;
+ static PLDHashTableOps sInfoHashOps;
+ nsVoidArray mDeferredComponents;
+};
+
+PR_STATIC_CALLBACK(void)
+info_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *, entry);
+ info->module = 0;
+ info->~StaticModuleInfo();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+info_InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
+{
+ // Construct so that our nsCOMPtr is zeroed, etc.
+ new (NS_STATIC_CAST(void *, entry)) StaticModuleInfo();
+ return PR_TRUE;
+}
+
+/* static */ PLDHashTableOps nsStaticComponentLoader::sInfoHashOps = {
+ PL_DHashAllocTable, PL_DHashFreeTable,
+ PL_DHashGetKeyStub, PL_DHashStringKey, PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub, info_ClearEntry,
+ PL_DHashFinalizeStub, info_InitEntry
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsStaticComponentLoader, nsIComponentLoader)
+
+NS_COM NSGetStaticModuleInfoFunc NSGetStaticModuleInfo;
+
+nsresult
+nsStaticComponentLoader::GetModuleInfo()
+{
+ if (mLoadedInfo)
+ return NS_OK;
+
+ if (!mInfoHash.ops) { // creation failed in init, why are we here?
+ NS_WARNING("operating on uninitialized static component loader");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ if (! NSGetStaticModuleInfo) {
+ // We're a static build with no static modules to
+ // register. This can happen in shared uses (such as the GRE)
+ return NS_OK;
+ }
+
+ nsStaticModuleInfo *infoList;
+ PRUint32 count;
+ nsresult rv;
+ if (NS_FAILED(rv = (*NSGetStaticModuleInfo)(&infoList, &count)))
+ return rv;
+ for (PRUint32 i = 0; i < count; i++) {
+ StaticModuleInfo *info =
+ NS_STATIC_CAST(StaticModuleInfo *,
+ PL_DHashTableOperate(&mInfoHash, infoList[i].name,
+ PL_DHASH_ADD));
+ if (!info)
+ return NS_ERROR_OUT_OF_MEMORY;
+ info->info = infoList[i];
+ }
+
+ mLoadedInfo = PR_TRUE;
+ return NS_OK;
+}
+
+nsresult
+nsStaticComponentLoader::GetInfoFor(const char *aLocation,
+ StaticModuleInfo **retval)
+{
+ nsresult rv;
+ if (NS_FAILED(rv = GetModuleInfo()))
+ return rv;
+
+ StaticModuleInfo *info =
+ NS_STATIC_CAST(StaticModuleInfo *,
+ PL_DHashTableOperate(&mInfoHash, aLocation,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(info))
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ if (!info->module) {
+ rv = info->info.getModule(mComponentMgr, nsnull,
+ getter_AddRefs(info->module));
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: GetInfoFor(\"%s\"): %x\n", aLocation, rv);
+#endif
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ *retval = info;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::Init(nsIComponentManager *mgr, nsISupports *aReg)
+{
+ mComponentMgr = mgr;
+ if (!PL_DHashTableInit(&mInfoHash, &sInfoHashOps, nsnull,
+ sizeof(StaticModuleInfo), 1024)) {
+ mInfoHash.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsStaticComponentLoader::info_RegisterSelf(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ nsStaticComponentLoader *loader = NS_STATIC_CAST(nsStaticComponentLoader *,
+ arg);
+ nsIComponentManager *mgr = loader->mComponentMgr;
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *, hdr);
+
+ nsresult rv;
+ if (!info->module) {
+ rv = info->info.getModule(mgr, nsnull, getter_AddRefs(info->module));
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: getModule(\"%s\"): %x\n", info->info.name, rv);
+#endif
+ if (NS_FAILED(rv))
+ return PL_DHASH_NEXT; // oh well.
+ }
+
+ rv = info->module->RegisterSelf(mgr, nsnull, info->info.name,
+ staticComponentType);
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: autoreg of \"%s\": %x\n", info->info.name, rv);
+#endif
+
+ if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
+ loader->mDeferredComponents.AppendElement(info);
+
+ return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoRegisterComponents(PRInt32 when, nsIFile *dir)
+{
+ if (mAutoRegistered)
+ return NS_OK;
+
+ // if a directory has been explicitly specified, then return early. we
+ // don't load static components from disk ;)
+ if (dir)
+ return NS_OK;
+
+ nsresult rv;
+ if (NS_FAILED(rv = GetModuleInfo()))
+ return rv;
+
+ PL_DHashTableEnumerate(&mInfoHash, info_RegisterSelf, this);
+
+ mAutoRegistered = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *retval)
+{
+ *retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component,
+ PRBool *retval)
+{
+ *retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::RegisterDeferredComponents(PRInt32 when,
+ PRBool *aRegistered)
+{
+ *aRegistered = PR_FALSE;
+ if (!mDeferredComponents.Count())
+ return NS_OK;
+
+ for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *,
+ mDeferredComponents[i]);
+ nsresult rv = info->module->RegisterSelf(mComponentMgr, nsnull,
+ info->info.name,
+ staticComponentType);
+ if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ if (NS_SUCCEEDED(rv))
+ *aRegistered = PR_TRUE;
+ mDeferredComponents.RemoveElementAt(i);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::OnRegister(const nsCID &aCID, const char *aType,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLocation,
+ PRBool aReplace, PRBool aPersist)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::GetFactory(const nsCID &aCID, const char *aLocation,
+ const char *aType, nsIFactory **_retval)
+{
+ StaticModuleInfo *info;
+ nsresult rv;
+
+ if (NS_FAILED(rv = GetInfoFor(aLocation, &info)))
+ return rv;
+
+ return info->module->GetClassObject(mComponentMgr, aCID,
+ NS_GET_IID(nsIFactory),
+ (void **)_retval);
+}
+
+nsresult
+NS_NewStaticComponentLoader(nsIComponentLoader **retval)
+{
+ NS_IF_ADDREF(*retval = NS_STATIC_CAST(nsIComponentLoader *,
+ new nsStaticComponentLoader));
+ return *retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/xcDll.cpp b/src/libs/xpcom18a4/xpcom/components/xcDll.cpp
new file mode 100644
index 00000000..494cf174
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/xcDll.cpp
@@ -0,0 +1,457 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsDll
+ *
+ * Abstraction of a Dll. Stores modifiedTime and size for easy detection of
+ * change in dll.
+ *
+ * dp Suresh <dp@netscape.com>
+ */
+
+#include "xcDll.h"
+#include "nsDebug.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentLoaderManager.h"
+#include "nsIModule.h"
+#include "nsILocalFile.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "nsITimelineService.h"
+#include "nsModule.h"
+#ifdef DEBUG
+#if defined(VMS)
+#include <lib$routines.h>
+#include <ssdef.h>
+#elif defined(XP_MACOSX)
+#include <signal.h>
+#endif
+#endif /* defined(DEBUG) */
+
+#include "nsTraceRefcntImpl.h"
+
+#define UNLOAD_DEPENDENT_LIBS
+#ifdef HPUX
+#undef UNLOAD_DEPENDENT_LIBS
+#endif
+
+#include "nsNativeComponentLoader.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include "nsMemory.h"
+#endif
+
+nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
+ : m_dllSpec(do_QueryInterface(dllSpec)),
+ m_instance(NULL),
+ m_moduleObject(NULL),
+ m_loader(loader),
+ m_markForUnload(PR_FALSE)
+{
+ NS_ASSERTION(loader, "Null loader when creating a nsDLL");
+}
+
+nsDll::~nsDll(void)
+{
+ //#if DEBUG_dougt
+ // The dll gets deleted when the dllStore is destroyed. This happens on
+ // app shutdown. At that point, unloading dlls can cause crashes if we have
+ // - dll dependencies
+ // - callbacks
+ // - static dtors
+ // Hence turn it back on after all the above have been removed.
+ //Unload();
+ //#endif
+}
+
+void
+nsDll::GetDisplayPath(nsACString& aLeafName)
+{
+ m_dllSpec->GetNativeLeafName(aLeafName);
+
+ if (aLeafName.IsEmpty())
+ aLeafName.AssignLiteral("unknown!");
+}
+
+PRBool
+nsDll::HasChanged()
+{
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
+ if (!manager)
+ return PR_TRUE;
+
+ // If mod date has changed, then dll has changed
+ PRInt64 currentDate;
+ nsresult rv = m_dllSpec->GetLastModifiedTime(&currentDate);
+ if (NS_FAILED(rv))
+ return PR_TRUE;
+ PRBool changed = PR_TRUE;
+ manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
+ return changed;
+}
+
+PRBool nsDll::Load(void)
+{
+ if (m_instance != NULL)
+ {
+ // Already loaded
+ return (PR_TRUE);
+ }
+
+ if (m_dllSpec)
+ {
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+
+ // Load any library dependencies
+ // The Component Loader Manager may hold onto some extra data
+ // set by either the native component loader or the native
+ // component. We assume that this data is a space delimited
+ // listing of dependent libraries which are required to be
+ // loaded prior to us loading the given component. Once, the
+ // component is loaded into memory, we can release our hold
+ // on the dependent libraries with the assumption that the
+ // component library holds a reference via the OS so loader.
+
+#if defined(XP_UNIX)
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
+ if (!manager)
+ return PR_TRUE;
+
+ nsXPIDLCString extraData;
+ manager->GetOptionalData(m_dllSpec, nsnull, getter_Copies(extraData));
+
+#ifdef UNLOAD_DEPENDENT_LIBS
+ nsVoidArray dependentLibArray;
+#endif
+
+ // if there was any extra data, treat it as a listing of dependent libs
+ if (extraData != nsnull)
+ {
+ // all dependent libraries are suppose to be in the "gre" directory.
+ // note that the gre directory is the same as the "bin" directory,
+ // when there isn't a real "gre" found.
+
+ nsXPIDLCString path;
+ nsCOMPtr<nsIFile> file;
+ NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
+
+ if (!file)
+ return NS_ERROR_FAILURE;
+
+ // we are talking about a file in the GRE dir. Lets append something
+ // stupid right now, so that later we can just set the leaf name.
+ file->AppendNative(NS_LITERAL_CSTRING("dummy"));
+
+# ifdef VBOX_USE_IPRT_IN_XPCOM
+ char *buffer = (char *)nsMemory::Clone(extraData, strlen(extraData) + 1);
+# else
+ char *buffer = strdup(extraData);
+# endif
+ if (!buffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ char* newStr;
+ char *token = nsCRT::strtok(buffer, " ", &newStr);
+ while (token!=nsnull)
+ {
+ nsCStringKey key(token);
+ if (m_loader->mLoadedDependentLibs.Get(&key)) {
+ token = nsCRT::strtok(newStr, " ", &newStr);
+ continue;
+ }
+
+ m_loader->mLoadedDependentLibs.Put(&key, (void*)1);
+
+ nsXPIDLCString libpath;
+ file->SetNativeLeafName(nsDependentCString(token));
+ file->GetNativePath(path);
+ if (!path)
+ return NS_ERROR_FAILURE;
+
+ // Load this dependent library with the global flag and stash
+ // the result for later so that we can unload it.
+ PRLibSpec libSpec;
+ libSpec.type = PR_LibSpec_Pathname;
+
+ // if the depend library path starts with a / we are
+ // going to assume that it is a full path and should
+ // be loaded without prepending the gre diretory
+ // location. We could have short circuited the
+ // SetNativeLeafName above, but this is clearer and
+ // the common case is a relative path.
+
+ if (token[0] == '/')
+ libSpec.value.pathname = token;
+ else
+ libSpec.value.pathname = path;
+
+ PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+ // if we couldn't load the dependent library. We did the best we
+ // can. Now just let us fail later if this really was a required
+ // dependency.
+#ifdef UNLOAD_DEPENDENT_LIBS
+ if (lib)
+ dependentLibArray.AppendElement((void*)lib);
+#endif
+
+ token = nsCRT::strtok(newStr, " ", &newStr);
+ }
+# ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(buffer);
+# else
+ free(buffer);
+# endif
+ }
+#endif
+
+ // load the component
+ nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
+ NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
+ lf->Load(&m_instance);
+
+#if defined(XP_UNIX)
+ // Unload any of library dependencies we loaded earlier. The assumption
+ // here is that the component will have a "internal" reference count to
+ // the dependency library we just loaded.
+ // XXX should we unload later - or even at all?
+
+#ifdef UNLOAD_DEPENDENT_LIBS
+ if (extraData != nsnull)
+ {
+ PRInt32 arrayCount = dependentLibArray.Count();
+ for (PRInt32 index = 0; index < arrayCount; index++)
+ PR_UnloadLibrary((PRLibrary*)dependentLibArray.ElementAt(index));
+ }
+#endif
+#endif
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+ if (m_instance) {
+ // Inform refcnt tracer of new library so that calls through the
+ // new library can be traced.
+ nsXPIDLCString displayPath;
+ GetDisplayPath(displayPath);
+ nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
+ }
+#endif
+ }
+
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ // Debugging help for components. Component dlls need to have their
+ // symbols loaded before we can put a breakpoint in the debugger.
+ // This will help figureing out the point when the dll was loaded.
+ nsXPIDLCString displayPath;
+ GetDisplayPath(displayPath);
+ BreakAfterLoad(displayPath.get());
+#endif
+
+ return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
+}
+
+PRBool nsDll::Unload(void)
+{
+ if (m_instance == NULL)
+ return (PR_FALSE);
+
+ // Shutdown the dll
+ Shutdown();
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+ PRStatus ret = PR_UnloadLibrary(m_instance);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+#endif
+
+ if (ret == PR_SUCCESS)
+ {
+ m_instance = NULL;
+ return (PR_TRUE);
+ }
+ else
+ return (PR_FALSE);
+}
+
+void * nsDll::FindSymbol(const char *symbol)
+{
+ if (symbol == NULL)
+ return (NULL);
+
+ // If not already loaded, load it now.
+ if (Load() != PR_TRUE)
+ return (NULL);
+
+ return(PR_FindSymbol(m_instance, symbol));
+}
+
+
+// Component dll specific functions
+nsresult nsDll::GetDllSpec(nsIFile **fsobj)
+{
+ NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
+ NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
+
+ *fsobj = m_dllSpec;
+ NS_ADDREF(*fsobj);
+ return NS_OK;
+}
+
+nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
+{
+ // using the backpointer of the loader.
+ nsIComponentManager* compMgr = m_loader->mCompMgr;
+ NS_ASSERTION(compMgr, "Global Component Manager is null" );
+ if (!compMgr) return NS_ERROR_UNEXPECTED;
+
+ NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
+
+ if (m_moduleObject)
+ {
+ NS_ADDREF(m_moduleObject);
+ *cobj = m_moduleObject;
+ return NS_OK;
+ }
+
+ // If not already loaded, load it now.
+ if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
+
+ // We need a nsIFile for location
+ if (!m_dllSpec)
+ {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsGetModuleProc proc =
+ (nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
+
+ if (proc == NULL)
+ return NS_ERROR_FACTORY_NOT_LOADED;
+
+ nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
+ if (NS_SUCCEEDED(rv))
+ {
+ NS_ADDREF(m_moduleObject);
+ *cobj = m_moduleObject;
+ }
+ return rv;
+}
+
+
+// These are used by BreakAfterLoad, below.
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+static nsCString *sBreakList[16];
+static int sBreakListCount = 0;
+#endif
+
+nsresult nsDll::Shutdown(void)
+{
+ // Release the module object if we got one
+ nsrefcnt refcnt;
+ if (m_moduleObject)
+ {
+ NS_RELEASE2(m_moduleObject, refcnt);
+ NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
+ }
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ for (int i = 0; i < sBreakListCount; i++)
+ {
+ delete sBreakList[i];
+ sBreakList[i] = nsnull;
+ }
+ sBreakListCount = 0;
+#endif
+ return NS_OK;
+
+}
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+void nsDll::BreakAfterLoad(const char *nsprPath)
+{
+ static PRBool firstTime = PR_TRUE;
+
+ // return if invalid input
+ if (!nsprPath || !*nsprPath) return;
+
+ // return if nothing to break on
+ if (!firstTime && sBreakListCount == 0) return;
+
+ if (firstTime)
+ {
+ firstTime = PR_FALSE;
+ // Form the list of dlls to break on load
+ nsCAutoString envList(getenv("XPCOM_BREAK_ON_LOAD"));
+ if (envList.IsEmpty()) return;
+ PRInt32 ofset = 0;
+ PRInt32 start = 0;
+ do
+ {
+ ofset = envList.FindChar(':', start);
+ sBreakList[sBreakListCount] = new nsCString();
+ envList.Mid(*(sBreakList[sBreakListCount]), start, ofset);
+ sBreakListCount++;
+ start = ofset + 1;
+ }
+ while (ofset != -1 && 16 > sBreakListCount); // avoiding vc6.0 compiler issue. count < thinks it is starting a template
+ }
+
+ // Find the dllname part of the string
+ nsCString currentPath(nsprPath);
+ PRInt32 lastSep = currentPath.RFindCharInSet(":\\/");
+
+ for (int i=0; i<sBreakListCount; i++)
+ if (currentPath.Find(*(sBreakList[i]), PR_TRUE, lastSep) > 0)
+ {
+ // Loading a dll that we want to break on
+ // Put your breakpoint here
+ fprintf(stderr, "...Loading module %s\n", nsprPath);
+ // Break in the debugger here.
+#if defined(__i386) && defined(__GNUC__)
+ asm("int $3");
+#elif defined(VMS)
+ lib$signal(SS$_DEBUG);
+#elif defined(XP_MACOSX)
+ raise(SIGTRAP);
+#endif
+ }
+ return;
+}
+#endif /* SHOULD_IMPLEMENT_BREAKAFTERLOAD */
diff --git a/src/libs/xpcom18a4/xpcom/components/xcDll.h b/src/libs/xpcom18a4/xpcom/components/xcDll.h
new file mode 100644
index 00000000..5de5b0eb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/xcDll.h
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Dll
+ *
+ * Programmatic representation of a dll. Stores modifiedTime and size for
+ * easy detection of change in dll.
+ *
+ * dp Suresh <dp@netscape.com>
+ */
+
+#ifndef xcDll_h__
+#define xcDll_h__
+
+#include "prio.h"
+#include "prlink.h"
+#include "nsISupports.h"
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+class nsNativeComponentLoader;
+
+#if defined(DEBUG) && !defined(XP_BEOS)
+#define SHOULD_IMPLEMENT_BREAKAFTERLOAD
+#endif
+
+class nsIModule;
+class nsIServiceManager;
+
+typedef enum nsDllStatus
+{
+ DLL_OK = 0,
+ DLL_NO_MEM = 1,
+ DLL_STAT_ERROR = 2,
+ DLL_NOT_FILE = 3,
+ DLL_INVALID_PARAM = 4
+} nsDllStatus;
+
+class nsDll
+{
+private:
+ nsCOMPtr<nsIFile> m_dllSpec;
+ PRLibrary *m_instance;
+ nsIModule *m_moduleObject;
+ nsNativeComponentLoader *m_loader;
+ PRBool m_markForUnload;
+
+ void Init(nsIFile *dllSpec);
+
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ void BreakAfterLoad(const char *nsprPath);
+#endif
+
+public:
+
+ nsDll(nsIFile *dllSpec, nsNativeComponentLoader* loader);
+ ~nsDll(void);
+
+ // Dll Loading
+ PRBool Load(void);
+ PRBool Unload(void);
+ PRBool IsLoaded(void)
+ {
+ return ((m_instance != 0) ? PR_TRUE : PR_FALSE);
+ }
+ void MarkForUnload(PRBool mark) { m_markForUnload = mark; }
+ PRBool IsMarkedForUnload(void) { return m_markForUnload; }
+
+ // Shutdown the dll. This will call any on unload hook for the dll.
+ // This wont unload the dll. Unload() implicitly calls Shutdown().
+ nsresult Shutdown(void);
+
+ void *FindSymbol(const char *symbol);
+
+ PRBool HasChanged(void);
+
+ void GetDisplayPath(nsACString& string);
+
+ PRLibrary *GetInstance(void) { return (m_instance); }
+
+ // NS_RELEASE() is required to be done on objects returned
+ nsresult GetDllSpec(nsIFile **dllSpec);
+ nsresult GetModule(nsISupports *servMgr, nsIModule **mobj);
+};
+
+#endif /* xcDll_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/doc/README b/src/libs/xpcom18a4/xpcom/doc/README
new file mode 100644
index 00000000..edef8772
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/doc/README
@@ -0,0 +1,8 @@
+<HTML>
+<HEAD>
+ <TITLE>READ ME</TITLE>
+</HEAD>
+<BODY>
+
+<H4><P>
+XPCOM documentation can be found at <a href="http://www.mozilla.org/projects/xpcom>www.mozilla.org/projects/xpcom</a>
diff --git a/src/libs/xpcom18a4/xpcom/ds/.cvsignore b/src/libs/xpcom18a4/xpcom/ds/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/ds/Makefile.in b/src/libs/xpcom18a4/xpcom/ds/Makefile.in
new file mode 100644
index 00000000..8da8853c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/Makefile.in
@@ -0,0 +1,171 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = xpcom_ds
+LIBRARY_NAME = xpcomds_s
+GRE_MODULE = 1
+
+REQUIRES = \
+ string \
+ $(NULL)
+
+CSRCS = \
+ pldhash.c \
+ $(NULL)
+
+CPPSRCS = \
+ nsAtomTable.cpp \
+ nsAtomService.cpp \
+ nsByteBuffer.cpp \
+ nsCheapSets.cpp \
+ nsCRT.cpp \
+ nsDeque.cpp \
+ nsEmptyEnumerator.cpp \
+ nsEnumeratorUtils.cpp \
+ nsFixedSizeAllocator.cpp \
+ nsHashSets.cpp \
+ nsHashtable.cpp \
+ nsObserverList.cpp \
+ nsObserverService.cpp \
+ nsProperties.cpp \
+ nsPersistentProperties.cpp \
+ nsQuickSort.cpp \
+ nsRecyclingAllocator.cpp \
+ nsStaticNameTable.cpp \
+ nsStringEnumerator.cpp \
+ nsSupportsArray.cpp \
+ nsSupportsArrayEnumerator.cpp \
+ nsSupportsPrimitives.cpp \
+ nsTHashtable.cpp \
+ nsUnicharBuffer.cpp \
+ nsVariant.cpp \
+ nsVoidArray.cpp \
+ nsTextFormatter.cpp \
+ nsTimelineService.cpp \
+ nsValueArray.cpp \
+ nsCOMArray.cpp \
+ nsArray.cpp \
+ nsArrayEnumerator.cpp \
+ $(NULL)
+
+EXPORTS = \
+ nsAtomService.h \
+ nsBaseHashtable.h \
+ nsCheapSets.h \
+ nsClassHashtable.h \
+ nsCppSharedAllocator.h \
+ nsCRT.h \
+ nsDataHashtable.h \
+ nsDeque.h \
+ nsDoubleHashtable.h \
+ nsEnumeratorUtils.h \
+ nsFixedSizeAllocator.h \
+ nsHashSets.h \
+ nsHashKeys.h \
+ nsHashtable.h \
+ nsIByteBuffer.h \
+ nsIUnicharBuffer.h \
+ nsInt64.h \
+ nsInterfaceHashtable.h \
+ nsObserverService.h \
+ nsQuickSort.h \
+ nsRecyclingAllocator.h \
+ nsRefPtrHashtable.h \
+ nsStaticNameTable.h \
+ nsStaticAtom.h \
+ nsSupportsArray.h \
+ nsSupportsPrimitives.h \
+ nsTHashtable.h \
+ nsTime.h \
+ nsUnitConversion.h \
+ nsVariant.h \
+ nsVoidArray.h \
+ pldhash.h \
+ nsTextFormatter.h \
+ nsValueArray.h \
+ nsArray.h \
+ nsArrayEnumerator.h \
+ nsCOMArray.h \
+ nsStringEnumerator.h \
+ nsAutoBuffer.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIAtom.idl \
+ nsIAtomService.idl \
+ nsICollection.idl \
+ nsIEnumerator.idl \
+ nsIPersistentProperties2.idl \
+ nsIPropertyBag.idl \
+ nsIRecyclingAllocator.idl \
+ nsIVariant.idl \
+ nsISerializable.idl \
+ nsIStringEnumerator.idl \
+ nsISupportsArray.idl \
+ nsISupportsIterators.idl \
+ nsITimelineService.idl \
+ nsIArray.idl \
+ $(NULL)
+
+SDK_XPIDLSRCS = \
+ nsIObserverService.idl \
+ nsIObserver.idl \
+ nsIProperties.idl \
+ nsISimpleEnumerator.idl \
+ nsISupportsPrimitives.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+
+DEFINES += -D_IMPL_NS_COM
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsArray.cpp
new file mode 100644
index 00000000..9eaf7868
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArray.cpp
@@ -0,0 +1,226 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsArray.h"
+#include "nsArrayEnumerator.h"
+#include "nsWeakReference.h"
+
+// used by IndexOf()
+struct findIndexOfClosure
+{
+ nsISupports *targetElement;
+ PRUint32 startIndex;
+ PRUint32 resultIndex;
+};
+
+PR_STATIC_CALLBACK(PRBool) FindElementCallback(void* aElement, void* aClosure);
+
+
+NS_IMPL_ISUPPORTS2(nsArray, nsIArray, nsIMutableArray)
+
+nsArray::~nsArray()
+{
+ Clear();
+}
+
+NS_IMETHODIMP
+nsArray::GetLength(PRUint32* aLength)
+{
+ *aLength = mArray.Count();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsArray::QueryElementAt(PRUint32 aIndex,
+ const nsIID& aIID,
+ void ** aResult)
+{
+ nsISupports * obj = mArray.ObjectAt(aIndex);
+ if (!obj) return NS_ERROR_UNEXPECTED;
+
+ // no need to worry about a leak here, because ObjectAt() doesn't
+ // addref its result
+ return obj->QueryInterface(aIID, aResult);
+}
+
+NS_IMETHODIMP
+nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
+ PRUint32* aResult)
+{
+ // optimize for the common case by forwarding to mArray
+ if (aStartIndex == 0) {
+ *aResult = mArray.IndexOf(aElement);
+ if (*aResult == -1)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+ }
+
+ findIndexOfClosure closure = { aElement, aStartIndex, 0 };
+ PRBool notFound = mArray.EnumerateForwards(FindElementCallback, &closure);
+ if (notFound)
+ return NS_ERROR_FAILURE;
+
+ *aResult = closure.resultIndex;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsArray::Enumerate(nsISimpleEnumerator **aResult)
+{
+ return NS_NewArrayEnumerator(aResult, NS_STATIC_CAST(nsIArray*, this));
+}
+
+// nsIMutableArray implementation
+
+NS_IMETHODIMP
+nsArray::AppendElement(nsISupports* aElement, PRBool aWeak)
+{
+ PRBool result;
+ if (aWeak) {
+ nsCOMPtr<nsISupports> elementRef =
+ getter_AddRefs(NS_STATIC_CAST(nsISupports*,
+ NS_GetWeakReference(aElement)));
+ NS_ASSERTION(elementRef, "AppendElement: Trying to use weak references on an object that doesn't support it");
+ if (!elementRef)
+ return NS_ERROR_FAILURE;
+ result = mArray.AppendObject(elementRef);
+ }
+
+ else {
+ // add the object directly
+ result = mArray.AppendObject(aElement);
+ }
+ return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsArray::RemoveElementAt(PRUint32 aIndex)
+{
+ PRBool result = mArray.RemoveObjectAt(aIndex);
+ return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex, PRBool aWeak)
+{
+ nsCOMPtr<nsISupports> elementRef;
+ if (aWeak) {
+ elementRef =
+ getter_AddRefs(NS_STATIC_CAST(nsISupports*,
+ NS_GetWeakReference(aElement)));
+ NS_ASSERTION(elementRef, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
+ if (!elementRef)
+ return NS_ERROR_FAILURE;
+ } else {
+ elementRef = aElement;
+ }
+ PRBool result = mArray.InsertObjectAt(elementRef, aIndex);
+ return result ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsArray::Clear()
+{
+ mArray.Clear();
+ return NS_OK;
+}
+
+//
+// static helper routines
+//
+PRBool
+FindElementCallback(void *aElement, void* aClosure)
+{
+ findIndexOfClosure* closure =
+ NS_STATIC_CAST(findIndexOfClosure*, aClosure);
+
+ nsISupports* element =
+ NS_STATIC_CAST(nsISupports*, aElement);
+
+ // don't start searching until we're past the startIndex
+ if (closure->resultIndex >= closure->startIndex &&
+ element == closure->targetElement) {
+ return PR_FALSE; // stop! We found it
+ }
+ closure->resultIndex++;
+
+ return PR_TRUE;
+}
+
+//
+// do_QueryElementAt helper stuff
+//
+nsresult
+nsQueryArrayElementAt::operator()(const nsIID& aIID, void** aResult) const
+ {
+ nsresult status = mArray
+ ? mArray->QueryElementAt(mIndex, aIID, aResult)
+ : NS_ERROR_NULL_POINTER;
+
+ if (mErrorPtr)
+ *mErrorPtr = status;
+
+ return status;
+ }
+
+//
+// exported constructor routines
+//
+nsresult
+NS_NewArray(nsIMutableArray** aResult)
+{
+ nsArray* arr = new nsArray;
+ if (!arr) return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = NS_STATIC_CAST(nsIMutableArray*,arr);
+ NS_ADDREF(*aResult);
+
+ return NS_OK;
+}
+
+nsresult
+NS_NewArray(nsIMutableArray** aResult, const nsCOMArray_base& aBaseArray)
+{
+ nsArray* arr = new nsArray(aBaseArray);
+ if (!arr) return NS_ERROR_OUT_OF_MEMORY;
+
+ *aResult = NS_STATIC_CAST(nsIMutableArray*, arr);
+ NS_ADDREF(*aResult);
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArray.h b/src/libs/xpcom18a4/xpcom/ds/nsArray.h
new file mode 100644
index 00000000..4a4f6cf2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArray.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 ***** */
+
+#ifndef nsArray_h__
+#define nsArray_h__
+
+#include "nsIArray.h"
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+
+#define NS_ARRAY_CLASSNAME \
+ "nsIArray implementation"
+
+// {35C66FD1-95E9-4e0a-80C5-C3BD2B375481}
+#define NS_ARRAY_CID \
+{ 0x35c66fd1, 0x95e9, 0x4e0a, \
+ { 0x80, 0xc5, 0xc3, 0xbd, 0x2b, 0x37, 0x54, 0x81 } }
+
+
+// create a new, empty array
+nsresult NS_COM
+NS_NewArray(nsIMutableArray** aResult);
+
+// The resulting array will hold an owning reference to every element
+// in the original nsCOMArray<T>. This also means that any further
+// changes to the original nsCOMArray<T> will not affect the new
+// array, and that the original array can go away and the new array
+// will still hold valid elements.
+nsresult NS_COM
+NS_NewArray(nsIMutableArray** aResult, const nsCOMArray_base& base);
+
+// adapter class to map nsIArray->nsCOMArray
+// do NOT declare this as a stack or member variable, use
+// nsCOMArray instead!
+// if you need to convert a nsCOMArray->nsIArray, see NS_NewArray above
+class nsArray : public nsIMutableArray
+{
+public:
+ nsArray() { }
+ nsArray(const nsCOMArray_base& aBaseArray) : mArray(aBaseArray)
+ { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIARRAY
+ NS_DECL_NSIMUTABLEARRAY
+
+private:
+ ~nsArray();
+
+ nsCOMArray_base mArray;
+};
+
+
+// helper class for do_QueryElementAt
+class NS_COM nsQueryArrayElementAt : public nsCOMPtr_helper
+ {
+ public:
+ nsQueryArrayElementAt(nsIArray* aArray, PRUint32 aIndex,
+ nsresult* aErrorPtr)
+ : mArray(aArray),
+ mIndex(aIndex),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
+
+ private:
+ nsIArray* mArray;
+ PRUint32 mIndex;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsQueryArrayElementAt
+do_QueryElementAt(nsIArray* aArray, PRUint32 aIndex, nsresult* aErrorPtr = 0)
+ {
+ return nsQueryArrayElementAt(aArray, aIndex, aErrorPtr);
+ }
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp
new file mode 100644
index 00000000..c105622a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.cpp
@@ -0,0 +1,210 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsArrayEnumerator.h"
+
+NS_IMPL_ISUPPORTS1(nsSimpleArrayEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsSimpleArrayEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->GetLength(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ *aResult = (mIndex < cnt);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSimpleArrayEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = nsnull;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->GetLength(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ if (mIndex >= cnt)
+ return NS_ERROR_UNEXPECTED;
+
+ return mValueArray->QueryElementAt(mIndex++, NS_GET_IID(nsISupports), (void**)aResult);
+}
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsIArray* array)
+{
+ nsSimpleArrayEnumerator* enumer = new nsSimpleArrayEnumerator(array);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*result = enumer);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// enumerator implementation for nsCOMArray
+// creates a snapshot of the array in question
+// you MUST use NS_NewArrayEnumerator to create this, so that
+// allocation is done correctly
+class nsCOMArrayEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ // nsSimpleArrayEnumerator methods
+ nsCOMArrayEnumerator() : mIndex(0) {
+ }
+
+ // specialized operator to make sure we make room for mValues
+ void* operator new (size_t size, const nsCOMArray_base& aArray) CPP_THROW_NEW;
+ void operator delete(void* ptr) {
+ ::operator delete(ptr);
+ }
+
+private:
+ ~nsCOMArrayEnumerator(void);
+
+protected:
+ PRUint32 mIndex; // current position
+ PRUint32 mArraySize; // size of the array
+
+ // this is actually bigger
+ nsISupports* mValueArray[1];
+};
+
+NS_IMPL_ISUPPORTS1(nsCOMArrayEnumerator, nsISimpleEnumerator)
+
+nsCOMArrayEnumerator::~nsCOMArrayEnumerator()
+{
+ // only release the entries that we haven't visited yet
+ for (; mIndex < mArraySize; ++mIndex) {
+ NS_IF_RELEASE(mValueArray[mIndex]);
+ }
+}
+
+NS_IMETHODIMP
+nsCOMArrayEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ *aResult = (mIndex < mArraySize);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCOMArrayEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mIndex >= mArraySize)
+ return NS_ERROR_UNEXPECTED;
+
+ // pass the ownership of the reference to the caller. Since
+ // we AddRef'ed during creation of |this|, there is no need
+ // to AddRef here
+ *aResult = mValueArray[mIndex++];
+
+ // this really isn't necessary. just pretend this happens, since
+ // we'll never visit this value again!
+ // mValueArray[(mIndex-1)] = nsnull;
+
+ return NS_OK;
+}
+
+void*
+nsCOMArrayEnumerator::operator new (size_t size, const nsCOMArray_base& aArray)
+ CPP_THROW_NEW
+{
+ // create enough space such that mValueArray points to a large
+ // enough value. Note that the initial value of size gives us
+ // space for mValueArray[0], so we must subtract
+ size += (aArray.Count() - 1) * sizeof(aArray[0]);
+
+ // do the actual allocation
+ nsCOMArrayEnumerator * result =
+ NS_STATIC_CAST(nsCOMArrayEnumerator*, ::operator new(size));
+
+ // now need to copy over the values, and addref each one
+ // now this might seem like alot of work, but we're actually just
+ // doing all our AddRef's ahead of time since GetNext() doesn't
+ // need to AddRef() on the way out
+ PRUint32 i;
+ PRUint32 max = result->mArraySize = aArray.Count();
+ for (i = 0; i<max; i++) {
+ result->mValueArray[i] = aArray[i];
+ NS_IF_ADDREF(result->mValueArray[i]);
+ }
+
+ return result;
+}
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *aResult,
+ const nsCOMArray_base& aArray)
+{
+ nsCOMArrayEnumerator *enumerator = new (aArray) nsCOMArrayEnumerator();
+ if (!enumerator) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*aResult = enumerator);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h
new file mode 100644
index 00000000..e22302b5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsArrayEnumerator.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array implementation.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 ***** */
+
+#ifndef nsArrayEnumerator_h__
+#define nsArrayEnumerator_h__
+
+// enumerator implementation for nsIArray
+
+#include "nsIArray.h"
+#include "nsCOMArray.h"
+#include "nsISimpleEnumerator.h"
+#include "nsCOMPtr.h"
+
+class nsSimpleArrayEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ // nsSimpleArrayEnumerator methods
+ nsSimpleArrayEnumerator(nsIArray* aValueArray) :
+ mValueArray(aValueArray), mIndex(0) {
+ }
+
+private:
+ ~nsSimpleArrayEnumerator() {}
+
+protected:
+ nsCOMPtr<nsIArray> mValueArray;
+ PRUint32 mIndex;
+};
+
+
+// Create an enumerator for an existing nsIArray implementation
+// The enumerator holds an owning reference to the array.
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsIArray* array);
+
+
+// create an enumerator for an existing nsCOMArray<T> implementation
+// The enumerator will hold an owning reference to each ELEMENT in
+// the array. This means that the nsCOMArray<T> can safely go away
+// without its objects going away.
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *aResult,
+ const nsCOMArray_base& aArray);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp
new file mode 100644
index 00000000..f0366043
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.cpp
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAtomService.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsAtomService, nsIAtomService)
+
+nsAtomService::nsAtomService()
+{
+}
+
+nsresult
+nsAtomService::GetAtom(const PRUnichar *aString, nsIAtom ** aResult)
+{
+ *aResult = NS_NewAtom(aString);
+
+ if (!*aResult)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+nsresult
+nsAtomService::GetPermanentAtom(const PRUnichar *aString, nsIAtom ** aResult)
+{
+ *aResult = NS_NewPermanentAtom(aString);
+
+ if (!*aResult)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomService.h b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.h
new file mode 100644
index 00000000..ae036b80
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomService.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsAtomService_h
+#define __nsAtomService_h
+
+#include "nsIAtomService.h"
+
+class nsAtomService : public nsIAtomService
+{
+ public:
+ nsAtomService();
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIATOMSERVICE
+
+ private:
+ ~nsAtomService() {}
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp
new file mode 100644
index 00000000..fc92dec8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.cpp
@@ -0,0 +1,616 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:ts=2:et:sw=2:
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAtomTable.h"
+#include "nsStaticAtom.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "pldhash.h"
+#include "prenv.h"
+#include "nsVoidArray.h"
+
+#define PL_ARENA_CONST_ALIGN_MASK 3
+#include "plarena.h"
+
+class nsStaticAtomWrapper;
+
+/**
+ * The shared hash table for atom lookups.
+ *
+ * XXX This should be manipulated in a threadsafe way or we should make
+ * sure it's only manipulated from the main thread. Probably the latter
+ * is better, since the former would hurt performance.
+ *
+ * If |gAtomTable.ops| is 0, then the table is uninitialized.
+ */
+static PLDHashTable gAtomTable;
+
+// this is where we keep the nsStaticAtomWrapper objects
+
+static PLArenaPool* gStaticAtomArena = 0;
+
+class nsStaticAtomWrapper : public nsIAtom
+{
+public:
+ nsStaticAtomWrapper(const nsStaticAtom* aAtom) :
+ mStaticAtom(aAtom)
+ {
+ MOZ_COUNT_CTOR(nsStaticAtomWrapper);
+ }
+ ~nsStaticAtomWrapper() { // no subclasses -> not virtual
+ // this is arena allocated and won't be called except in debug
+ // builds. If this function ever does anything non-debug, be sure
+ // to get rid of the ifdefs in AtomTableClearEntry!
+ MOZ_COUNT_DTOR(nsStaticAtomWrapper);
+ }
+
+ NS_IMETHOD QueryInterface(REFNSIID aIID,
+ void** aInstancePtr);
+ NS_IMETHOD_(nsrefcnt) AddRef(void);
+ NS_IMETHOD_(nsrefcnt) Release(void);
+
+ NS_DECL_NSIATOM
+
+ const nsStaticAtom* GetStaticAtom() {
+ return mStaticAtom;
+ }
+private:
+ const nsStaticAtom* mStaticAtom;
+};
+
+// the atomtableentry can contain either an AtomImpl or a
+// nsStaticAtomWrapper, indicated by the first bit of PtrBits
+typedef unsigned long PtrBits;
+
+struct AtomTableEntry : public PLDHashEntryHdr {
+ // mAtom & 0x1 means (mAtom & ~0x1) points to an nsStaticAtomWrapper
+ // else it points to an nsAtomImpl
+ PtrBits mAtom;
+
+ inline PRBool IsStaticAtom() const {
+ return (mAtom & 0x1) != 0;
+ }
+
+ inline void SetAtomImpl(AtomImpl* aAtom) {
+ NS_ASSERTION(aAtom, "Setting null atom");
+ mAtom = PtrBits(aAtom);
+ }
+
+ inline void SetStaticAtomWrapper(nsStaticAtomWrapper* aAtom) {
+ NS_ASSERTION(aAtom, "Setting null atom");
+ NS_ASSERTION((PtrBits(aAtom) & ~0x1) == PtrBits(aAtom),
+ "Pointers must align or this is broken");
+
+ mAtom = PtrBits(aAtom) | 0x1;
+ }
+
+ inline void ClearAtom() {
+ mAtom = nsnull;
+ }
+
+ inline PRBool HasValue() const {
+ return (mAtom & ~0x1) != 0;
+ }
+
+ // these accessors assume that you already know the type
+ inline AtomImpl *GetAtomImpl() const {
+ NS_ASSERTION(!IsStaticAtom(), "This is a static atom, not an AtomImpl");
+ return (AtomImpl*) (mAtom & ~0x1);
+ }
+
+ inline nsStaticAtomWrapper *GetStaticAtomWrapper() const {
+ NS_ASSERTION(IsStaticAtom(), "This is an AtomImpl, not a static atom");
+ return (nsStaticAtomWrapper*) (mAtom & ~0x1);
+ }
+
+ inline const nsStaticAtom* GetStaticAtom() const {
+ return GetStaticAtomWrapper()->GetStaticAtom();
+ }
+
+ // type-agnostic accessors
+
+ // get the string buffer
+ inline const char* get() const {
+ return IsStaticAtom() ? GetStaticAtom()->mString : GetAtomImpl()->mString;
+ }
+
+ // get an addreffed nsIAtom - not using already_AddRef'ed atom
+ // because the callers are not (and should not be) using nsCOMPtr
+ inline nsIAtom* GetAtom() const {
+ nsIAtom* result;
+
+ if (IsStaticAtom())
+ result = GetStaticAtomWrapper();
+ else {
+ result = GetAtomImpl();
+ NS_ADDREF(result);
+ }
+
+ return result;
+ }
+};
+
+PR_STATIC_CALLBACK(const void *)
+AtomTableGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ AtomTableEntry *he = NS_STATIC_CAST(AtomTableEntry*, entry);
+ NS_ASSERTION(he->HasValue(), "Empty atom. how did that happen?");
+ return he->get();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+AtomTableMatchKey(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const AtomTableEntry *he = NS_STATIC_CAST(const AtomTableEntry*, entry);
+ const char* keyStr = NS_STATIC_CAST(const char*, key);
+ return nsCRT::strcmp(keyStr, he->get()) == 0;
+}
+
+PR_STATIC_CALLBACK(void)
+AtomTableClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ AtomTableEntry *he = NS_STATIC_CAST(AtomTableEntry*, entry);
+
+ he->keyHash = 0;
+
+ if (!he->IsStaticAtom()) {
+ AtomImpl *atom = he->GetAtomImpl();
+ // Normal |AtomImpl| atoms are deleted when their refcount hits 0, and
+ // they then remove themselves from the table. In other words, they
+ // are owned by the callers who own references to them.
+ // |PermanentAtomImpl| permanent atoms ignore their refcount and are
+ // deleted when they are removed from the table at table destruction.
+ // In other words, they are owned by the atom table.
+ if (atom->IsPermanent())
+ delete NS_STATIC_CAST(PermanentAtomImpl*, atom);
+ }
+ else {
+ he->GetStaticAtomWrapper()->~nsStaticAtomWrapper();
+ }
+
+ he->ClearAtom();
+}
+
+static const PLDHashTableOps AtomTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ AtomTableGetKey,
+ PL_DHashStringKey,
+ AtomTableMatchKey,
+ PL_DHashMoveEntryStub,
+ AtomTableClearEntry,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+
+#ifdef DEBUG
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+DumpAtomLeaks(PLDHashTable *table, PLDHashEntryHdr *he,
+ PRUint32 index, void *arg)
+{
+ AtomTableEntry *entry = NS_STATIC_CAST(AtomTableEntry*, he);
+
+ if (entry->IsStaticAtom())
+ return PL_DHASH_NEXT;
+
+ AtomImpl* atom = entry->GetAtomImpl();
+ if (!atom->IsPermanent()) {
+ ++*NS_STATIC_CAST(PRUint32*, arg);
+ const char *str;
+ atom->GetUTF8String(&str);
+ fputs(str, stdout);
+ fputs("\n", stdout);
+ }
+ return PL_DHASH_NEXT;
+}
+
+#endif
+
+static inline
+void PromoteToPermanent(AtomImpl* aAtom)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ {
+ nsrefcnt refcount = aAtom->GetRefCount();
+ do {
+ NS_LOG_RELEASE(aAtom, --refcount, "AtomImpl");
+ } while (refcount);
+ }
+#endif
+ aAtom = new (aAtom) PermanentAtomImpl();
+}
+
+void NS_PurgeAtomTable()
+{
+ if (gAtomTable.ops) {
+#ifdef DEBUG
+ if (PR_GetEnv("MOZ_DUMP_ATOM_LEAKS")) {
+ PRUint32 leaked = 0;
+ printf("*** %d atoms still exist (including permanent):\n",
+ gAtomTable.entryCount);
+ PL_DHashTableEnumerate(&gAtomTable, DumpAtomLeaks, &leaked);
+ printf("*** %u non-permanent atoms leaked\n", leaked);
+ }
+#endif
+ PL_DHashTableFinish(&gAtomTable);
+ gAtomTable.entryCount = 0;
+ gAtomTable.ops = nsnull;
+
+ if (gStaticAtomArena) {
+ PL_FinishArenaPool(gStaticAtomArena);
+ delete gStaticAtomArena;
+ gStaticAtomArena = nsnull;
+ }
+ }
+}
+
+AtomImpl::AtomImpl()
+{
+}
+
+AtomImpl::~AtomImpl()
+{
+ NS_PRECONDITION(gAtomTable.ops, "uninitialized atom hashtable");
+ // Permanent atoms are removed from the hashtable at shutdown, and we
+ // don't want to remove them twice. See comment above in
+ // |AtomTableClearEntry|.
+ if (!IsPermanent()) {
+ PL_DHashTableOperate(&gAtomTable, mString, PL_DHASH_REMOVE);
+ if (gAtomTable.entryCount == 0) {
+ PL_DHashTableFinish(&gAtomTable);
+ NS_ASSERTION(gAtomTable.entryCount == 0,
+ "PL_DHashTableFinish changed the entry count");
+ }
+ }
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(AtomImpl, nsIAtom)
+
+NS_IMETHODIMP_(nsrefcnt) PermanentAtomImpl::AddRef()
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt) PermanentAtomImpl::Release()
+{
+ return 1;
+}
+
+/* virtual */ PRBool
+AtomImpl::IsPermanent()
+{
+ return PR_FALSE;
+}
+
+/* virtual */ PRBool
+PermanentAtomImpl::IsPermanent()
+{
+ return PR_TRUE;
+}
+
+void* AtomImpl::operator new ( size_t size, const nsACString& aString ) CPP_THROW_NEW
+{
+ /*
+ Note: since the |size| will initially also include the |PRUnichar| member
+ |mString|, our size calculation will give us one character too many.
+ We use that extra character for a zero-terminator.
+
+ Note: this construction is not guaranteed to be possible by the C++
+ compiler. A more reliable scheme is used by |nsShared[C]String|s, see
+ http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsSharedString.h#174
+ */
+ size += aString.Length() * sizeof(char);
+ AtomImpl* ii = NS_STATIC_CAST(AtomImpl*, ::operator new(size));
+
+ char* toBegin = &ii->mString[0];
+ nsACString::const_iterator fromBegin, fromEnd;
+ *copy_string(aString.BeginReading(fromBegin), aString.EndReading(fromEnd), toBegin) = '\0';
+ return ii;
+}
+
+void* PermanentAtomImpl::operator new ( size_t size, AtomImpl* aAtom ) CPP_THROW_NEW {
+ NS_ASSERTION(!aAtom->IsPermanent(),
+ "converting atom that's already permanent");
+
+ // Just let the constructor overwrite the vtable pointer.
+ return aAtom;
+}
+
+NS_IMETHODIMP
+AtomImpl::ToString(nsAString& aBuf)
+{
+ CopyUTF8toUTF16(nsDependentCString(mString), aBuf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::ToUTF8String(nsACString& aBuf)
+{
+ aBuf.Assign(mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::GetUTF8String(const char **aResult)
+{
+ NS_PRECONDITION(aResult, "null out param");
+ *aResult = mString;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::EqualsUTF8(const nsACString& aString, PRBool* aResult)
+{
+ *aResult = aString.Equals(mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+AtomImpl::Equals(const nsAString& aString, PRBool* aResult)
+{
+ *aResult = NS_ConvertUTF16toUTF8(aString).Equals(mString);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------
+
+// wrapper class for the nsStaticAtom struct
+
+NS_IMETHODIMP_(nsrefcnt)
+nsStaticAtomWrapper::AddRef()
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsStaticAtomWrapper::Release()
+{
+ return 1;
+}
+
+NS_IMPL_QUERY_INTERFACE1(nsStaticAtomWrapper, nsIAtom)
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::GetUTF8String(const char** aResult)
+{
+ *aResult = mStaticAtom->mString;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::ToString(nsAString& aBuf)
+{
+ // static should always be always ASCII, to allow tools like gperf
+ // to generate the tables, and to avoid unnecessary conversion
+ NS_ASSERTION(nsCRT::IsAscii(mStaticAtom->mString),
+ "Data loss - atom should be ASCII");
+ CopyASCIItoUCS2(nsDependentCString(mStaticAtom->mString), aBuf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::ToUTF8String(nsACString& aBuf)
+{
+ aBuf.Assign(mStaticAtom->mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::EqualsUTF8(const nsACString& aString, PRBool* aResult)
+{
+ *aResult = aString.Equals(mStaticAtom->mString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticAtomWrapper::Equals(const nsAString& aString, PRBool* aResult)
+{
+ *aResult = NS_ConvertUCS2toUTF8(aString).Equals(mStaticAtom->mString);
+ return NS_OK;
+}
+//----------------------------------------------------------------------
+
+NS_COM nsIAtom* NS_NewAtom(const char* isolatin1)
+{
+ return NS_NewAtom(nsDependentCString(isolatin1));
+}
+
+NS_COM nsIAtom* NS_NewPermanentAtom(const char* isolatin1)
+{
+ return NS_NewPermanentAtom(NS_ConvertASCIItoUCS2(isolatin1));
+}
+
+static nsStaticAtomWrapper*
+WrapStaticAtom(const nsStaticAtom* aAtom)
+{
+ if (!gStaticAtomArena) {
+ gStaticAtomArena = new PLArenaPool;
+ if (!gStaticAtomArena)
+ return nsnull;
+
+ PL_INIT_ARENA_POOL(gStaticAtomArena, "nsStaticAtomArena", 4096);
+ }
+
+ void* mem;
+ PL_ARENA_ALLOCATE(mem, gStaticAtomArena, sizeof(nsStaticAtom));
+
+ nsStaticAtomWrapper* wrapper =
+ new (mem) nsStaticAtomWrapper(aAtom);
+
+ return wrapper;
+}
+
+static AtomTableEntry* GetAtomHashEntry(const char* aString)
+{
+ if (!gAtomTable.ops &&
+ !PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0,
+ sizeof(AtomTableEntry), 2048)) {
+ gAtomTable.ops = nsnull;
+ return nsnull;
+ }
+ return NS_STATIC_CAST(AtomTableEntry*,
+ PL_DHashTableOperate(&gAtomTable,
+ aString,
+ PL_DHASH_ADD));
+}
+
+NS_COM nsresult
+NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount)
+{
+ // this does two things:
+ // 1) wraps each static atom in a wrapper, if necessary
+ // 2) initializes the address pointed to by each mAtom slot
+
+ for (PRUint32 i=0; i<aAtomCount; i++) {
+ NS_ASSERTION(nsCRT::IsAscii(aAtoms[i].mString),
+ "Static atoms must be ASCII!");
+ AtomTableEntry *he =
+ GetAtomHashEntry(aAtoms[i].mString);
+
+ if (he->HasValue() && aAtoms[i].mAtom) {
+ // there already is an atom with this name in the table.. but we
+ // still have to update mAtom
+ if (!he->IsStaticAtom() && !he->GetAtomImpl()->IsPermanent()) {
+ // since we wanted to create a static atom but there is
+ // already one there, we convert it to a non-refcounting
+ // permanent atom
+ PromoteToPermanent(he->GetAtomImpl());
+ }
+
+ // and now, if the consumer wants to remember this value in a
+ // slot, we do so
+ if (aAtoms[i].mAtom)
+ *aAtoms[i].mAtom = he->GetAtom();
+ }
+
+ else {
+ nsStaticAtomWrapper* atom = WrapStaticAtom(&aAtoms[i]);
+ NS_ASSERTION(atom, "Failed to wrap static atom");
+
+ // but even if atom is null, no real difference in code..
+ he->SetStaticAtomWrapper(atom);
+ if (aAtoms[i].mAtom)
+ *aAtoms[i].mAtom = atom;
+ }
+ }
+ return NS_OK;
+}
+
+NS_COM nsIAtom* NS_NewAtom( const nsAString& aString )
+{
+ NS_ConvertUCS2toUTF8 utf8String(aString);
+
+ return NS_NewAtom(utf8String);
+}
+
+NS_COM
+nsIAtom*
+NS_NewAtom( const nsACString& aString )
+{
+ AtomTableEntry *he = GetAtomHashEntry(PromiseFlatCString(aString).get());
+
+ if (he->HasValue())
+ return he->GetAtom();
+
+ AtomImpl* atom = new (aString) AtomImpl();
+ he->SetAtomImpl(atom);
+ if (!atom) {
+ PL_DHashTableRawRemove(&gAtomTable, he);
+ return nsnull;
+ }
+
+ NS_ADDREF(atom);
+ return atom;
+}
+
+NS_COM nsIAtom* NS_NewPermanentAtom( const nsAString& aString )
+{
+ return NS_NewPermanentAtom(NS_ConvertUCS2toUTF8(aString));
+}
+
+NS_COM
+nsIAtom* NS_NewPermanentAtom( const nsACString& aString )
+{
+ AtomTableEntry *he = GetAtomHashEntry(PromiseFlatCString(aString).get());
+
+ if (he->HasValue() && he->IsStaticAtom())
+ return he->GetStaticAtomWrapper();
+
+ // either there is no atom and we'll create an AtomImpl,
+ // or there is an existing AtomImpl
+ AtomImpl* atom = he->GetAtomImpl();
+
+ if (atom) {
+ // ensure that it's permanent
+ if (!atom->IsPermanent()) {
+ PromoteToPermanent(atom);
+ }
+ } else {
+ // otherwise, make a new atom
+ atom = new (aString) PermanentAtomImpl();
+ he->SetAtomImpl(atom);
+ if ( !atom ) {
+ PL_DHashTableRawRemove(&gAtomTable, he);
+ return nsnull;
+ }
+ }
+
+ NS_ADDREF(atom);
+ return atom;
+}
+
+NS_COM nsIAtom* NS_NewAtom( const PRUnichar* str )
+{
+ return NS_NewAtom(NS_ConvertUCS2toUTF8(str));
+}
+
+NS_COM nsIAtom* NS_NewPermanentAtom( const PRUnichar* str )
+{
+ return NS_NewPermanentAtom(nsDependentString(str));
+}
+
+NS_COM nsrefcnt NS_GetNumberOfAtoms(void)
+{
+ return gAtomTable.entryCount;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h
new file mode 100644
index 00000000..d8971cf7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAtomTable.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAtomTable_h__
+#define nsAtomTable_h__
+
+#include "nsIAtom.h"
+
+/**
+ * A threadsafely-refcounted implementation of nsIAtom. Note that
+ * AtomImpl objects are sometimes converted into PermanentAtomImpl
+ * objects using placement new and just overwriting the vtable pointer.
+ */
+
+class AtomImpl : public nsIAtom {
+public:
+ AtomImpl();
+
+protected:
+ // We don't need a virtual destructor here because PermanentAtomImpl
+ // deletions aren't handled through Release().
+ ~AtomImpl();
+
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIATOM
+
+ virtual PRBool IsPermanent();
+
+ void* operator new(size_t size, const nsACString& aString) CPP_THROW_NEW;
+
+ void operator delete(void* ptr) {
+ ::operator delete(ptr);
+ }
+
+ // for |#ifdef NS_BUILD_REFCNT_LOGGING| access to reference count
+ nsrefcnt GetRefCount() { return mRefCnt; }
+
+ // Actually more; 0 terminated. This slot is reserved for the
+ // terminating zero.
+ char mString[1];
+};
+
+/**
+ * A non-refcounted implementation of nsIAtom.
+ */
+
+class PermanentAtomImpl : public AtomImpl {
+public:
+#ifdef AIX
+ PermanentAtomImpl() : AtomImpl() {}
+#endif
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+
+ virtual PRBool IsPermanent();
+
+ void* operator new(size_t size, const nsACString& aString) CPP_THROW_NEW {
+ return AtomImpl::operator new(size, aString);
+ }
+ void* operator new(size_t size, AtomImpl* aAtom) CPP_THROW_NEW;
+
+};
+
+void NS_PurgeAtomTable();
+
+#endif // nsAtomTable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h
new file mode 100644
index 00000000..84011369
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsAutoBuffer.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is auto buffer template.
+ *
+ * The Initial Developer of the Original Code is
+ * Conrad Carlen <ccarlen@mac.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jungshik Shin <jshin@mailaps.org>
+ *
+ * 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 nsAutoBuffer_h__
+#define nsAutoBuffer_h__
+
+#ifndef nsMemory_h__
+#include "nsMemory.h"
+#endif
+
+/**
+ * A buffer which will use stack space if the requested size will
+ * fit in the stack buffer and allocate from the heap if not.
+ *
+ * Below is a usage example :
+ *
+ * typedef nsAutoBuffer<PRUnichar, 256> nsAutoUnicharBuffer;
+ *
+ * nsAutoUnicharBuffer buffer;
+ *
+ * if (!buffer.EnsureElemCapacity(initialLength))
+ * return NS_ERROR_OUT_OF_MEMORY;
+ *
+ * PRUnichar *unicharPtr = buffer.get();
+ *
+ * // add PRUnichar's to the buffer pointed to by |unicharPtr| as long as
+ * // the number of PRUnichar's is less than |intialLength|
+ *
+ * // increase the capacity
+ * if (!buffer.AddElemCapacity(extraLength))
+ * return NS_ERROR_OUT_OF_MEMORY
+ *
+ * unicharPtr = buffer.get() + initialLength;
+ *
+ * //continue to add PRUnichar's....
+ */
+
+template <class T, PRInt32 sz>
+class nsAutoBuffer
+{
+public:
+ nsAutoBuffer() :
+ mBufferPtr(mStackBuffer),
+ mCurElemCapacity(sz)
+ {
+ }
+
+ ~nsAutoBuffer()
+ {
+ if (mBufferPtr != mStackBuffer)
+ nsMemory::Free(mBufferPtr);
+ }
+
+ PRBool EnsureElemCapacity(PRInt32 inElemCapacity)
+ {
+ if (inElemCapacity <= mCurElemCapacity)
+ return PR_TRUE;
+
+ T* newBuffer;
+
+ if (mBufferPtr != mStackBuffer)
+ newBuffer = (T*)nsMemory::Realloc((void *)mBufferPtr, inElemCapacity * sizeof(T));
+ else
+ newBuffer = (T*)nsMemory::Alloc(inElemCapacity * sizeof(T));
+
+ if (!newBuffer)
+ return PR_FALSE;
+
+ if (mBufferPtr != mStackBuffer)
+ nsMemory::Free(mBufferPtr);
+
+ mBufferPtr = newBuffer;
+ mCurElemCapacity = inElemCapacity;
+ return PR_TRUE;
+ }
+
+ PRBool AddElemCapacity(PRInt32 inElemCapacity)
+ {
+ return EnsureElemCapacity(mCurElemCapacity + inElemCapacity);
+ }
+
+ T* get() const { return mBufferPtr; }
+ PRInt32 GetElemCapacity() const { return mCurElemCapacity; }
+
+protected:
+
+ T *mBufferPtr;
+ T mStackBuffer[sz];
+ PRInt32 mCurElemCapacity;
+};
+
+#endif // nsAutoBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h
new file mode 100644
index 00000000..92300c2f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsBaseHashtable.h
@@ -0,0 +1,458 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsBaseHashtable_h__
+#define nsBaseHashtable_h__
+
+#include "nsTHashtable.h"
+#include "prlock.h"
+#include "nsDebug.h"
+
+template<class KeyClass,class DataType,class UserDataType>
+class nsBaseHashtable; // forward declaration
+
+/**
+ * the private nsTHashtable::EntryType class used by nsBaseHashtable
+ * @see nsTHashtable for the specification of this class
+ * @see nsBaseHashtable for template parameters
+ */
+template<class KeyClass,class DataType>
+class nsBaseHashtableET : public KeyClass
+{
+public:
+ DataType mData;
+ friend class nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >;
+
+private:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef typename KeyClass::KeyTypePointer KeyTypePointer;
+
+ nsBaseHashtableET(KeyTypePointer aKey);
+ nsBaseHashtableET(nsBaseHashtableET<KeyClass,DataType>& toCopy);
+ ~nsBaseHashtableET();
+};
+
+/**
+ * templated hashtable for simple data types
+ * This class manages simple data types that do not need construction or
+ * destruction. Thread-safety is optional, via a flag in Init()
+ *
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param DataType the datatype stored in the hashtable,
+ * for example, PRUint32 or nsCOMPtr. If UserDataType is not the same,
+ * DataType must implicitly cast to UserDataType
+ * @param UserDataType the user sees, for example PRUint32 or nsISupports*
+ */
+template<class KeyClass,class DataType,class UserDataType>
+class nsBaseHashtable :
+ protected nsTHashtable< nsBaseHashtableET<KeyClass,DataType> >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef nsBaseHashtableET<KeyClass,DataType> EntryType;
+
+ // default constructor+destructor are fine
+
+ /**
+ * Initialize the object.
+ * @param initSize the initial number of buckets in the hashtable,
+ * default 16
+ * @param threadSafe whether to provide read/write
+ * locking on all class methods
+ * @return PR_TRUE if the object was initialized properly.
+ */
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE)
+ { return nsTHashtable<EntryType>::Init(initSize); }
+
+ /**
+ * Check whether the table has been initialized.
+ * This function is especially useful for static hashtables.
+ * @return PR_TRUE if the table has been initialized.
+ */
+ PRBool IsInitialized() const { return this->mTable.entrySize; }
+
+ /**
+ * Return the number of entries in the table.
+ * @return number of entries
+ */
+ PRUint32 Count() const
+ { return nsTHashtable<EntryType>::Count(); }
+
+ /**
+ * retrieve the value for a key.
+ * @param aKey the key to retreive
+ * @param pData data associated with this key will be placed at this
+ * pointer. If you only need to check if the key exists, pData
+ * may be null.
+ * @return PR_TRUE if the key exists. If key does not exist, pData is not
+ * modified.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const
+ {
+ EntryType* ent = this->GetEntry(aKey);
+
+ if (!ent)
+ return PR_FALSE;
+
+ if (pData)
+ *pData = ent->mData;
+
+ return PR_TRUE;
+ }
+
+ /**
+ * put a new value for the associated key
+ * @param aKey the key to put
+ * @param aData the new data
+ * @return always PR_TRUE, unless memory allocation failed
+ */
+ PRBool Put(KeyType aKey, UserDataType aData)
+ {
+ EntryType* ent = this->PutEntry(aKey);
+
+ if (!ent)
+ return PR_FALSE;
+
+ ent->mData = aData;
+
+ return PR_TRUE;
+ }
+
+ /**
+ * remove the data for the associated key
+ * @param aKey the key to remove from the hashtable
+ */
+ void Remove(KeyType aKey) { this->RemoveEntry(aKey); }
+
+ /**
+ * function type provided by the application for enumeration.
+ * @param aKey the key being enumerated
+ * @param aData data being enumerated
+ * @parm userArg passed unchanged from Enumerate
+ * @return either
+ * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink or
+ * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
+ */
+ typedef PLDHashOperator
+ (*PR_CALLBACK EnumReadFunction)(KeyType aKey,
+ UserDataType aData,
+ void* userArg);
+
+ /**
+ * enumerate entries in the hashtable, without allowing changes
+ * this function read-locks the hashtable, so other threads may read keys
+ * at the same time in multi-thread environments.
+ * @param enumFunc enumeration callback
+ * @param userArg passed unchanged to the EnumReadFunction
+ */
+ PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const
+ {
+ NS_ASSERTION(this->mTable.entrySize,
+ "nsBaseHashtable was not initialized properly.");
+
+ s_EnumReadArgs enumData = { enumFunc, userArg };
+ return PL_DHashTableEnumerate(NS_CONST_CAST(PLDHashTable*, &this->mTable),
+ s_EnumReadStub,
+ &enumData);
+ }
+
+ /**
+ * function type provided by the application for enumeration.
+ * @param aKey the key being enumerated
+ * @param aData Reference to data being enumerated, may be altered. e.g. for
+ * nsInterfaceHashtable this is an nsCOMPtr reference...
+ * @parm userArg passed unchanged from Enumerate
+ * @return bitflag combination of
+ * @link PLDHashOperator::PL_DHASH_REMOVE @endlink,
+ * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink, or
+ * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink
+ */
+ typedef PLDHashOperator
+ (*PR_CALLBACK EnumFunction)(KeyType aKey,
+ DataType& aData,
+ void* userArg);
+
+ /**
+ * enumerate entries in the hashtable, allowing changes. This
+ * functions write-locks the hashtable.
+ * @param enumFunc enumeration callback
+ * @param userArg passed unchanged to the EnumFunction
+ */
+ PRUint32 Enumerate(EnumFunction enumFunc, void* userArg)
+ {
+ NS_ASSERTION(this->mTable.entrySize,
+ "nsBaseHashtable was not initialized properly.");
+
+ s_EnumArgs enumData = { enumFunc, userArg };
+ return PL_DHashTableEnumerate(&this->mTable,
+ s_EnumStub,
+ &enumData);
+ }
+
+ /**
+ * reset the hashtable, removing all entries
+ */
+ void Clear() { nsTHashtable<EntryType>::Clear(); }
+
+protected:
+ /**
+ * used internally during EnumerateRead. Allocated on the stack.
+ * @param func the enumerator passed to EnumerateRead
+ * @param userArg the userArg passed to EnumerateRead
+ */
+ struct s_EnumReadArgs
+ {
+ EnumReadFunction func;
+ void* userArg;
+ };
+
+ static PLDHashOperator s_EnumReadStub(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg);
+
+ struct s_EnumArgs
+ {
+ EnumFunction func;
+ void* userArg;
+ };
+
+ static PLDHashOperator s_EnumStub(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg);
+};
+
+/**
+ * This class is a thread-safe version of nsBaseHashtable.
+ */
+template<class KeyClass,class DataType,class UserDataType>
+class nsBaseHashtableMT :
+ protected nsBaseHashtable<KeyClass,DataType,UserDataType>
+{
+public:
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EntryType EntryType;
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::KeyType KeyType;
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumFunction EnumFunction;
+ typedef typename
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumReadFunction EnumReadFunction;
+
+ nsBaseHashtableMT() : mLock(nsnull) { }
+ ~nsBaseHashtableMT();
+
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
+ PRBool IsInitialized() const { return (PRBool) mLock; }
+ PRUint32 Count() const;
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+ PRBool Put(KeyType aKey, UserDataType aData);
+ void Remove(KeyType aKey);
+
+ PRUint32 EnumerateRead(EnumReadFunction enumFunc, void* userArg) const;
+ PRUint32 Enumerate(EnumFunction enumFunc, void* userArg);
+ void Clear();
+
+protected:
+ PRLock* mLock;
+};
+
+
+//
+// nsBaseHashtableET definitions
+//
+
+template<class KeyClass,class DataType>
+nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET(KeyTypePointer aKey) :
+ KeyClass(aKey)
+{ }
+
+template<class KeyClass,class DataType>
+nsBaseHashtableET<KeyClass,DataType>::nsBaseHashtableET
+ (nsBaseHashtableET<KeyClass,DataType>& toCopy) :
+ KeyClass(toCopy),
+ mData(toCopy.mData)
+{ }
+
+template<class KeyClass,class DataType>
+nsBaseHashtableET<KeyClass,DataType>::~nsBaseHashtableET()
+{ }
+
+
+//
+// nsBaseHashtable definitions
+//
+
+template<class KeyClass,class DataType,class UserDataType>
+PLDHashOperator
+nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumReadStub
+ (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
+{
+ EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
+ s_EnumReadArgs* eargs = (s_EnumReadArgs*) arg;
+
+ PLDHashOperator res = (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
+
+ NS_ASSERTION( !(res & PL_DHASH_REMOVE ),
+ "PL_DHASH_REMOVE return during const enumeration; ignoring.");
+
+ if (res & PL_DHASH_STOP)
+ return PL_DHASH_STOP;
+
+ return PL_DHASH_NEXT;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PLDHashOperator
+nsBaseHashtable<KeyClass,DataType,UserDataType>::s_EnumStub
+ (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void* arg)
+{
+ EntryType* ent = NS_STATIC_CAST(EntryType*, hdr);
+ s_EnumArgs* eargs = (s_EnumArgs*) arg;
+
+ return (eargs->func)(ent->GetKey(), ent->mData, eargs->userArg);
+}
+
+
+//
+// nsBaseHashtableMT definitions
+//
+
+template<class KeyClass,class DataType,class UserDataType>
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::~nsBaseHashtableMT()
+{
+ if (this->mLock)
+ PR_DestroyLock(this->mLock);
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRBool
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Init(PRUint32 initSize)
+{
+ if (!nsTHashtable<EntryType>::IsInitialized() && !nsTHashtable<EntryType>::Init(initSize))
+ return PR_FALSE;
+
+ this->mLock = PR_NewLock();
+ NS_WARN_IF_FALSE(this->mLock, "Error creating lock during nsBaseHashtableL::Init()");
+
+ return (this->mLock != nsnull);
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRUint32
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Count() const
+{
+ PR_Lock(this->mLock);
+ PRUint32 count = nsTHashtable<EntryType>::Count();
+ PR_Unlock(this->mLock);
+
+ return count;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRBool
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Get(KeyType aKey,
+ UserDataType* pData) const
+{
+ PR_Lock(this->mLock);
+ PRBool res =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Get(aKey, pData);
+ PR_Unlock(this->mLock);
+
+ return res;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRBool
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Put(KeyType aKey,
+ UserDataType aData)
+{
+ PR_Lock(this->mLock);
+ PRBool res =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Put(aKey, aData);
+ PR_Unlock(this->mLock);
+
+ return res;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+void
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Remove(KeyType aKey)
+{
+ PR_Lock(this->mLock);
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Remove(aKey);
+ PR_Unlock(this->mLock);
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRUint32
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::EnumerateRead
+ (EnumReadFunction fEnumCall, void* userArg) const
+{
+ PR_Lock(this->mLock);
+ PRUint32 count =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::EnumerateRead(fEnumCall, userArg);
+ PR_Unlock(this->mLock);
+
+ return count;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+PRUint32
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Enumerate
+ (EnumFunction fEnumCall, void* userArg)
+{
+ PR_Lock(this->mLock);
+ PRUint32 count =
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Enumerate(fEnumCall, userArg);
+ PR_Unlock(this->mLock);
+
+ return count;
+}
+
+template<class KeyClass,class DataType,class UserDataType>
+void
+nsBaseHashtableMT<KeyClass,DataType,UserDataType>::Clear()
+{
+ PR_Lock(this->mLock);
+ nsBaseHashtable<KeyClass,DataType,UserDataType>::Clear();
+ PR_Unlock(this->mLock);
+}
+
+#endif // nsBaseHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp
new file mode 100644
index 00000000..a51ff9d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsByteBuffer.h"
+#include "nsIInputStream.h"
+#include "nsCRT.h"
+
+#define MIN_BUFFER_SIZE 32
+
+ByteBufferImpl::ByteBufferImpl(void)
+ : mBuffer(NULL), mSpace(0), mLength(0)
+{
+}
+
+NS_IMETHODIMP
+ByteBufferImpl::Init(PRUint32 aBufferSize)
+{
+ if (aBufferSize < MIN_BUFFER_SIZE) {
+ aBufferSize = MIN_BUFFER_SIZE;
+ }
+ mSpace = aBufferSize;
+ mLength = 0;
+ mBuffer = new char[aBufferSize];
+ return mBuffer ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMPL_ISUPPORTS1(ByteBufferImpl,nsIByteBuffer)
+
+ByteBufferImpl::~ByteBufferImpl()
+{
+ if (nsnull != mBuffer) {
+ delete[] mBuffer;
+ mBuffer = nsnull;
+ }
+ mLength = 0;
+}
+
+NS_METHOD
+ByteBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ ByteBufferImpl* it = new ByteBufferImpl();
+ if (nsnull == it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(it);
+ nsresult rv = it->QueryInterface(aIID, (void**)aResult);
+ NS_RELEASE(it);
+ return rv;
+}
+
+NS_IMETHODIMP_(PRUint32)
+ByteBufferImpl::GetLength(void) const
+{
+ return mLength;
+}
+
+NS_IMETHODIMP_(PRUint32)
+ByteBufferImpl::GetBufferSize(void) const
+{
+ return mSpace;
+}
+
+NS_IMETHODIMP_(char*)
+ByteBufferImpl::GetBuffer(void) const
+{
+ return mBuffer;
+}
+
+NS_IMETHODIMP_(PRBool)
+ByteBufferImpl::Grow(PRUint32 aNewSize)
+{
+ if (aNewSize < MIN_BUFFER_SIZE) {
+ aNewSize = MIN_BUFFER_SIZE;
+ }
+ char* newbuf = new char[aNewSize];
+ if (nsnull != newbuf) {
+ if (0 != mLength) {
+ memcpy(newbuf, mBuffer, mLength);
+ }
+ delete[] mBuffer;
+ mBuffer = newbuf;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRInt32)
+ByteBufferImpl::Fill(nsresult* aErrorCode, nsIInputStream* aStream,
+ PRUint32 aKeep)
+{
+ NS_PRECONDITION(nsnull != aStream, "null stream");
+ NS_PRECONDITION(aKeep <= mLength, "illegal keep count");
+ if ((nsnull == aStream) || (PRUint32(aKeep) > PRUint32(mLength))) {
+ // whoops
+ *aErrorCode = NS_BASE_STREAM_ILLEGAL_ARGS;
+ return -1;
+ }
+
+ if (0 != aKeep) {
+ // Slide over kept data
+ memmove(mBuffer, mBuffer + (mLength - aKeep), aKeep);
+ }
+
+ // Read in some new data
+ mLength = aKeep;
+ PRUint32 nb;
+ *aErrorCode = aStream->Read(mBuffer + aKeep, mSpace - aKeep, &nb);
+ if (NS_SUCCEEDED(*aErrorCode)) {
+ mLength += nb;
+ }
+ else
+ nb = 0;
+ return nb;
+}
+
+NS_COM nsresult NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize)
+{
+ nsresult rv;
+ nsIByteBuffer* buf;
+ rv = ByteBufferImpl::Create(aOuter, NS_GET_IID(nsIByteBuffer), (void**)&buf);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = buf->Init(aBufferSize);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(buf);
+ return rv;
+ }
+ *aInstancePtrResult = buf;
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h
new file mode 100644
index 00000000..0a474570
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsByteBuffer.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsByteBuffer_h__
+#define nsByteBuffer_h__
+
+#include "nsIByteBuffer.h"
+
+class ByteBufferImpl : public nsIByteBuffer {
+public:
+ ByteBufferImpl(void);
+
+ NS_DECL_ISUPPORTS
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_IMETHOD Init(PRUint32 aBufferSize);
+ NS_IMETHOD_(PRUint32) GetLength(void) const;
+ NS_IMETHOD_(PRUint32) GetBufferSize(void) const;
+ NS_IMETHOD_(char*) GetBuffer() const;
+ NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize);
+ NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
+ PRUint32 aKeep);
+
+ char* mBuffer;
+ PRUint32 mSpace;
+ PRUint32 mLength;
+private:
+ ~ByteBufferImpl();
+};
+
+#endif // nsByteBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp
new file mode 100644
index 00000000..9a270223
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.cpp
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a COM aware array class.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsCOMArray.h"
+#include "nsCOMPtr.h"
+
+PR_STATIC_CALLBACK(PRBool) ReleaseObjects(void* aElement, void*);
+
+// implementations of non-trivial methods in nsCOMArray_base
+
+// copy constructor - we can't just memcpy here, because
+// we have to make sure we own our own array buffer, and that each
+// object gets another AddRef()
+nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
+{
+ // make sure we do only one allocation
+ mArray.SizeTo(aOther.Count());
+ AppendObjects(aOther);
+}
+
+nsCOMArray_base::~nsCOMArray_base()
+{
+ PRInt32 count = Count(), i;
+ for (i = 0; i < count; ++i) {
+ nsISupports* obj = ObjectAt(i);
+ NS_IF_RELEASE(obj);
+ }
+}
+
+PRInt32
+nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
+ NS_ENSURE_TRUE(aObject, -1);
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
+ NS_ENSURE_TRUE(supports, -1);
+
+ PRInt32 i, count;
+ PRInt32 retval = -1;
+ count = mArray.Count();
+ for (i = 0; i < count; ++i) {
+ nsCOMPtr<nsISupports> arrayItem =
+ do_QueryInterface(NS_REINTERPRET_CAST(nsISupports*,mArray.ElementAt(i)));
+ if (arrayItem == supports) {
+ retval = i;
+ break;
+ }
+ }
+ return retval;
+}
+
+PRBool
+nsCOMArray_base::InsertObjectAt(nsISupports* aObject, PRInt32 aIndex) {
+ PRBool result = mArray.InsertElementAt(aObject, aIndex);
+ if (result)
+ NS_IF_ADDREF(aObject);
+ return result;
+}
+
+PRBool
+nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, PRInt32 aIndex) {
+ PRBool result = mArray.InsertElementsAt(aObjects.mArray, aIndex);
+ if (result) {
+ // need to addref all these
+ PRInt32 count = aObjects.Count();
+ for (PRInt32 i = 0; i < count; ++i) {
+ NS_IF_ADDREF(aObjects.ObjectAt(i));
+ }
+ }
+ return result;
+}
+
+PRBool
+nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, PRInt32 aIndex)
+{
+ // its ok if oldObject is null here
+ nsISupports *oldObject =
+ NS_REINTERPRET_CAST(nsISupports*, mArray.SafeElementAt(aIndex));
+
+ PRBool result = mArray.ReplaceElementAt(aObject, aIndex);
+
+ // ReplaceElementAt could fail, such as if the array grows
+ // so only release the existing object if the replacement succeeded
+ if (result) {
+ // Make sure to addref first, in case aObject == oldObject
+ NS_IF_ADDREF(aObject);
+ NS_IF_RELEASE(oldObject);
+ }
+ return result;
+}
+
+PRBool
+nsCOMArray_base::RemoveObject(nsISupports *aObject)
+{
+ PRBool result = mArray.RemoveElement(aObject);
+ if (result)
+ NS_IF_RELEASE(aObject);
+ return result;
+}
+
+PRBool
+nsCOMArray_base::RemoveObjectAt(PRInt32 aIndex)
+{
+ nsISupports* element = ObjectAt(aIndex);
+ if (element) {
+ PRBool result = mArray.RemoveElementAt(aIndex);
+ if (result)
+ NS_IF_RELEASE(element);
+ return result;
+ }
+ return PR_FALSE;
+}
+
+// useful for destructors
+PRBool
+ReleaseObjects(void* aElement, void*)
+{
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, aElement);
+ NS_IF_RELEASE(element);
+ return PR_TRUE;
+}
+
+void
+nsCOMArray_base::Clear()
+{
+ mArray.EnumerateForwards(ReleaseObjects, nsnull);
+ mArray.Clear();
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h
new file mode 100644
index 00000000..cbb728c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCOMArray.h
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a COM aware array class.
+ *
+ * The Initial Developer of the Original Code
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 ***** */
+
+#ifndef nsCOMArray_h__
+#define nsCOMArray_h__
+
+#include "nsVoidArray.h"
+#include "nsISupports.h"
+
+// See below for the definition of nsCOMArray<T>
+
+// a class that's nsISupports-specific, so that we can contain the
+// work of this class in the XPCOM dll
+class NS_COM nsCOMArray_base
+{
+ friend class nsArray;
+protected:
+ nsCOMArray_base() {}
+ nsCOMArray_base(PRInt32 aCount) : mArray(aCount) {}
+ nsCOMArray_base(const nsCOMArray_base& other);
+ ~nsCOMArray_base();
+
+ PRInt32 IndexOf(nsISupports* aObject) const {
+ return mArray.IndexOf(aObject);
+ }
+
+ PRInt32 IndexOfObject(nsISupports* aObject) const;
+
+ PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData) {
+ return mArray.EnumerateForwards(aFunc, aData);
+ }
+
+ PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData) {
+ return mArray.EnumerateBackwards(aFunc, aData);
+ }
+
+ void Sort(nsVoidArrayComparatorFunc aFunc, void* aData) {
+ mArray.Sort(aFunc, aData);
+ }
+
+ // any method which is not a direct forward to mArray should
+ // avoid inline bodies, so that the compiler doesn't inline them
+ // all over the place
+ void Clear();
+ PRBool InsertObjectAt(nsISupports* aObject, PRInt32 aIndex);
+ PRBool InsertObjectsAt(const nsCOMArray_base& aObjects, PRInt32 aIndex);
+ PRBool ReplaceObjectAt(nsISupports* aObject, PRInt32 aIndex);
+ PRBool AppendObject(nsISupports *aObject) {
+ return InsertObjectAt(aObject, Count());
+ }
+ PRBool AppendObjects(const nsCOMArray_base& aObjects) {
+ return InsertObjectsAt(aObjects, Count());
+ }
+ PRBool RemoveObject(nsISupports *aObject);
+ PRBool RemoveObjectAt(PRInt32 aIndex);
+
+public:
+ // override nsVoidArray stuff so that they can be accessed by
+ // consumers of nsCOMArray
+ PRInt32 Count() const {
+ return mArray.Count();
+ }
+
+ nsISupports* ObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(nsISupports*, mArray.FastElementAt(aIndex));
+ }
+
+ nsISupports* SafeObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(nsISupports*, mArray.SafeElementAt(aIndex));
+ }
+
+ nsISupports* operator[](PRInt32 aIndex) const {
+ return ObjectAt(aIndex);
+ }
+
+private:
+
+ // the actual storage
+ nsVoidArray mArray;
+
+ // don't implement these, defaults will muck with refcounts!
+ nsCOMArray_base& operator=(const nsCOMArray_base& other);
+};
+
+// a non-XPCOM, refcounting array of XPCOM objects
+// used as a member variable or stack variable - this object is NOT
+// refcounted, but the objects that it holds are
+//
+// most of the read-only accessors like ObjectAt()/etc do NOT refcount
+// on the way out. This means that you can do one of two things:
+//
+// * does an addref, but holds onto a reference
+// nsCOMPtr<T> foo = array[i];
+//
+// * avoids the refcount, but foo might go stale if array[i] is ever
+// * modified/removed. Be careful not to NS_RELEASE(foo)!
+// T* foo = array[i];
+//
+// This array will accept null as an argument for any object, and will
+// store null in the array, just like nsVoidArray. But that also means
+// that methods like ObjectAt() may return null when referring to an
+// existing, but null entry in the array.
+template <class T>
+class nsCOMArray : public nsCOMArray_base
+{
+ public:
+ nsCOMArray() {}
+ nsCOMArray(PRInt32 aCount) : nsCOMArray_base(aCount) {}
+
+ // only to be used by trusted classes who are going to pass us the
+ // right type!
+ nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) { }
+
+ ~nsCOMArray() {}
+
+ // these do NOT refcount on the way out, for speed
+ T* ObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(T*,nsCOMArray_base::ObjectAt(aIndex));
+ }
+
+ // these do NOT refcount on the way out, for speed
+ T* SafeObjectAt(PRInt32 aIndex) const {
+ return NS_STATIC_CAST(T*,nsCOMArray_base::SafeObjectAt(aIndex));
+ }
+
+ // indexing operator for syntactic sugar
+ T* operator[](PRInt32 aIndex) const {
+ return ObjectAt(aIndex);
+ }
+
+ // index of the element in question.. does NOT refcount
+ // note: this does not check COM object identity. Use
+ // IndexOfObject() for that purpose
+ PRInt32 IndexOf(T* aObject) const {
+ return nsCOMArray_base::IndexOf(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // index of the element in question.. be careful!
+ // this is much slower than IndexOf() because it uses
+ // QueryInterface to determine actual COM identity of the object
+ // if you need to do this frequently then consider enforcing
+ // COM object identity before adding/comparing elements
+ PRInt32 IndexOfObject(T* aObject) const {
+ return nsCOMArray_base::IndexOfObject(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // inserts aObject at aIndex, shifting the objects at aIndex and
+ // later to make space
+ PRBool InsertObjectAt(T* aObject, PRInt32 aIndex) {
+ return nsCOMArray_base::InsertObjectAt(NS_STATIC_CAST(nsISupports*, aObject), aIndex);
+ }
+
+ // inserts the objects from aObject at aIndex, shifting the
+ // objects at aIndex and later to make space
+ PRBool InsertObjectsAt(const nsCOMArray<T>& aObjects, PRInt32 aIndex) {
+ return nsCOMArray_base::InsertObjectsAt(aObjects, aIndex);
+ }
+
+ // replaces an existing element. Warning: if the array grows,
+ // the newly created entries will all be null
+ PRBool ReplaceObjectAt(T* aObject, PRInt32 aIndex) {
+ return nsCOMArray_base::ReplaceObjectAt(NS_STATIC_CAST(nsISupports*, aObject), aIndex);
+ }
+
+ // override nsVoidArray stuff so that they can be accessed by
+ // other methods
+
+ // elements in the array (including null elements!)
+ PRInt32 Count() const {
+ return nsCOMArray_base::Count();
+ }
+
+ // remove all elements in the array, and call NS_RELEASE on each one
+ void Clear() {
+ nsCOMArray_base::Clear();
+ }
+
+ // Enumerator callback function. Return PR_FALSE to stop
+ // Here's a more readable form:
+ // PRBool PR_CALLBACK enumerate(T* aElement, void* aData)
+ typedef PRBool (* PR_CALLBACK nsCOMArrayEnumFunc)
+ (T* aElement, void *aData);
+
+ // enumerate through the array with a callback.
+ PRBool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData) {
+ return nsCOMArray_base::EnumerateForwards(nsVoidArrayEnumFunc(aFunc),
+ aData);
+ }
+
+ PRBool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData) {
+ return nsCOMArray_base::EnumerateBackwards(nsVoidArrayEnumFunc(aFunc),
+ aData);
+ }
+
+ typedef int (* PR_CALLBACK nsCOMArrayComparatorFunc)
+ (T* aElement1, T* aElement2, void* aData);
+
+ void Sort(nsCOMArrayComparatorFunc aFunc, void* aData) {
+ nsCOMArray_base::Sort(nsVoidArrayComparatorFunc(aFunc), aData);
+ }
+
+ // append an object, growing the array as necessary
+ PRBool AppendObject(T *aObject) {
+ return nsCOMArray_base::AppendObject(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // append objects, growing the array as necessary
+ PRBool AppendObjects(const nsCOMArray<T>& aObjects) {
+ return nsCOMArray_base::AppendObjects(aObjects);
+ }
+
+ // remove the first instance of the given object and shrink the
+ // array as necessary
+ // Warning: if you pass null here, it will remove the first null element
+ PRBool RemoveObject(T *aObject) {
+ return nsCOMArray_base::RemoveObject(NS_STATIC_CAST(nsISupports*, aObject));
+ }
+
+ // remove an element at a specific position, shrinking the array
+ // as necessary
+ PRBool RemoveObjectAt(PRInt32 aIndex) {
+ return nsCOMArray_base::RemoveObjectAt(aIndex);
+ }
+
+private:
+
+ // don't implement these!
+ nsCOMArray<T>& operator=(const nsCOMArray<T>& other);
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp b/src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp
new file mode 100644
index 00000000..23392f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCRT.cpp
@@ -0,0 +1,534 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/**
+ * MODULE NOTES:
+ * @update gess7/30/98
+ *
+ * Much as I hate to do it, we were using string compares wrong.
+ * Often, programmers call functions like strcmp(s1,s2), and pass
+ * one or more null strings. Rather than blow up on these, I've
+ * added quick checks to ensure that cases like this don't cause
+ * us to fail.
+ *
+ * In general, if you pass a null into any of these string compare
+ * routines, we simply return 0.
+ */
+
+
+#include "nsCRT.h"
+#include "nsIServiceManager.h"
+
+// XXX Bug: These tables don't lowercase the upper 128 characters properly
+
+// This table maps uppercase characters to lower case characters;
+// characters that are neither upper nor lower case are unaffected.
+static const unsigned char kUpper2Lower[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64,
+
+ // upper band mapped to lower [A-Z] => [a-z]
+ 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,
+
+ 91, 92, 93, 94, 95,
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+static const unsigned char kLower2Upper[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96,
+
+ // lower band mapped to upper [a-z] => [A-Z]
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+
+ 123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+};
+
+//----------------------------------------------------------------------
+
+char nsCRT::ToUpper(char aChar)
+{
+ return (char)kLower2Upper[(unsigned char)aChar];
+}
+
+char nsCRT::ToLower(char aChar)
+{
+ return (char)kUpper2Lower[(unsigned char)aChar];
+}
+
+PRBool nsCRT::IsUpper(char aChar)
+{
+ return aChar != nsCRT::ToLower(aChar);
+}
+
+PRBool nsCRT::IsLower(char aChar)
+{
+ return aChar != nsCRT::ToUpper(aChar);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// My lovely strtok routine
+
+#define IS_DELIM(m, c) ((m)[(c) >> 3] & (1 << ((c) & 7)))
+#define SET_DELIM(m, c) ((m)[(c) >> 3] |= (1 << ((c) & 7)))
+#define DELIM_TABLE_SIZE 32
+
+char* nsCRT::strtok(char* string, const char* delims, char* *newStr)
+{
+ NS_ASSERTION(string, "Unlike regular strtok, the first argument cannot be null.");
+
+ char delimTable[DELIM_TABLE_SIZE];
+ PRUint32 i;
+ char* result;
+ char* str = string;
+
+ for (i = 0; i < DELIM_TABLE_SIZE; i++)
+ delimTable[i] = '\0';
+
+ for (i = 0; delims[i]; i++) {
+ SET_DELIM(delimTable, NS_STATIC_CAST(PRUint8, delims[i]));
+ }
+ NS_ASSERTION(delims[i] == '\0', "too many delimiters");
+
+ // skip to beginning
+ while (*str && IS_DELIM(delimTable, NS_STATIC_CAST(PRUint8, *str))) {
+ str++;
+ }
+ result = str;
+
+ // fix up the end of the token
+ while (*str) {
+ if (IS_DELIM(delimTable, NS_STATIC_CAST(PRUint8, *str))) {
+ *str++ = '\0';
+ break;
+ }
+ str++;
+ }
+ *newStr = str;
+
+ return str == result ? NULL : result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+PRUint32 nsCRT::strlen(const PRUnichar* s)
+{
+ PRUint32 len = 0;
+ if(s) {
+ while (*s++ != 0) {
+ len++;
+ }
+ }
+ return len;
+}
+
+
+/**
+ * Compare unichar string ptrs, stopping at the 1st null
+ * NOTE: If both are null, we return 0.
+ * NOTE: We terminate the search upon encountering a NULL
+ *
+ * @update gess 11/10/99
+ * @param s1 and s2 both point to unichar strings
+ * @return 0 if they match, -1 if s1<s2; 1 if s1>s2
+ */
+PRInt32 nsCRT::strcmp(const PRUnichar* s1, const PRUnichar* s2) {
+ if(s1 && s2) {
+ for (;;) {
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = *s2++;
+ if (c1 != c2) {
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ if ((0==c1) || (0==c2)) break;
+ }
+ }
+ else {
+ if (s1) // s2 must have been null
+ return -1;
+ if (s2) // s1 must have been null
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Compare unichar string ptrs, stopping at the 1st null or nth char.
+ * NOTE: If either is null, we return 0.
+ * NOTE: We DO NOT terminate the search upon encountering NULL's before N
+ *
+ * @update gess 11/10/99
+ * @param s1 and s2 both point to unichar strings
+ * @return 0 if they match, -1 if s1<s2; 1 if s1>s2
+ */
+PRInt32 nsCRT::strncmp(const PRUnichar* s1, const PRUnichar* s2, PRUint32 n) {
+ if(s1 && s2) {
+ if(n != 0) {
+ do {
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = *s2++;
+ if (c1 != c2) {
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ } while (--n != 0);
+ }
+ }
+ return 0;
+}
+
+PRUnichar* nsCRT::strdup(const PRUnichar* str)
+{
+ PRUint32 len = nsCRT::strlen(str);
+ return strndup(str, len);
+}
+
+PRUnichar* nsCRT::strndup(const PRUnichar* str, PRUint32 len)
+{
+ nsCppSharedAllocator<PRUnichar> shared_allocator;
+ PRUnichar* rslt = shared_allocator.allocate(len + 1); // add one for the null
+ // PRUnichar* rslt = new PRUnichar[len + 1];
+
+ if (rslt == NULL) return NULL;
+ memcpy(rslt, str, len * sizeof(PRUnichar));
+ rslt[len] = 0;
+ return rslt;
+}
+
+ /**
+ * |nsCRT::HashCode| is identical to |PL_HashString|, which tests
+ * (http://bugzilla.mozilla.org/showattachment.cgi?attach_id=26596)
+ * show to be the best hash among several other choices.
+ *
+ * We re-implement it here rather than calling it for two reasons:
+ * (1) in this interface, we also calculate the length of the
+ * string being hashed; and (2) the narrow and wide and `buffer' versions here
+ * will hash equivalent strings to the same value, e.g., "Hello" and L"Hello".
+ */
+PRUint32 nsCRT::HashCode(const char* str, PRUint32* resultingStrLen)
+{
+ PRUint32 h = 0;
+ const char* s = str;
+
+ if (!str) return h;
+
+ unsigned char c;
+ while ( (c = *s++) )
+ h = (h>>28) ^ (h<<4) ^ c;
+
+ if ( resultingStrLen )
+ *resultingStrLen = (s-str)-1;
+ return h;
+}
+
+PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen)
+{
+ PRUint32 h = 0;
+ const PRUnichar* s = str;
+
+ if (!str) return h;
+
+ PRUnichar c;
+ while ( (c = *s++) )
+ h = (h>>28) ^ (h<<4) ^ c;
+
+ if ( resultingStrLen )
+ *resultingStrLen = (s-str)-1;
+ return h;
+}
+
+PRUint32 nsCRT::HashCodeAsUTF8(const PRUnichar* str, PRUint32* resultingStrLen)
+{
+ PRUint32 h = 0;
+ const PRUnichar* s = str;
+
+ {
+ PRUint16 W1 = 0; // the first UTF-16 word in a two word tuple
+ PRUint32 U = 0; // the current char as UCS-4
+ int code_length = 0; // the number of bytes in the UTF-8 sequence for the current char
+
+ PRUint16 W;
+ while ( (W = *s++) )
+ {
+ /*
+ * On the fly, decoding from UTF-16 (and/or UCS-2) into UTF-8 as per
+ * http://www.ietf.org/rfc/rfc2781.txt
+ * http://www.ietf.org/rfc/rfc2279.txt
+ */
+
+ if ( !W1 )
+ {
+ if ( W < 0xD800 || 0xDFFF < W )
+ {
+ U = W;
+ if ( W <= 0x007F )
+ code_length = 1;
+ else if ( W <= 0x07FF )
+ code_length = 2;
+ else
+ code_length = 3;
+ }
+ else if ( /* 0xD800 <= W1 && */ W <= 0xDBFF )
+ W1 = W;
+ }
+ else
+ {
+ // as required by the standard, this code is careful to
+ // throw out illegal sequences
+
+ if ( 0xDC00 <= W && W <= 0xDFFF )
+ {
+ U = PRUint32( (W1&0x03FF)<<10 | (W&0x3FFF) );
+ if ( U <= 0x001FFFFF )
+ code_length = 4;
+ else if ( U <= 0x3FFFFFF )
+ code_length = 5;
+ else
+ code_length = 6;
+ }
+ W1 = 0;
+ }
+
+
+ if ( code_length > 0 )
+ {
+ static const PRUint16 sBytePrefix[7] = { 0x0000, 0x0000, 0x00C0, 0x00E0, 0x00F0, 0x00F8, 0x00FC };
+ static const PRUint16 sShift[7] = { 0, 0, 6, 12, 18, 24, 30 };
+
+ /*
+ * Unlike the algorithm in http://www.ietf.org/rfc/rfc2279.txt
+ * we must calculate the bytes in left to right order so that
+ * our hash result matches what the narrow version would calculate
+ * on an already UTF-8 string.
+ */
+
+ // hash the first (and often, only, byte)
+ h = (h>>28) ^ (h<<4) ^ (sBytePrefix[code_length] | (U>>sShift[code_length]));
+
+ // an unrolled loop for hashing any remaining bytes in this sequence
+ switch ( code_length )
+ { // falling through in each case
+ case 6: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>24) & 0x003F));
+ case 5: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>18) & 0x003F));
+ case 4: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>12) & 0x003F));
+ case 3: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>6 ) & 0x003F));
+ case 2: h = (h>>28) ^ (h<<4) ^ (0x80 | ( U & 0x003F));
+ default: code_length = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( resultingStrLen )
+ *resultingStrLen = (s-str)-1;
+ return h;
+}
+
+PRUint32 nsCRT::BufferHashCode(const char* s, PRUint32 len)
+{
+ PRUint32 h = 0;
+ const char* done = s + len;
+
+ while ( s < done )
+ h = (h>>28) ^ (h<<4) ^ PRUint8(*s++); // cast to unsigned to prevent possible sign extension
+
+ return h;
+}
+
+PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len)
+{
+ PRUint32 h = 0;
+ const PRUnichar* done = s + len;
+
+ while ( s < done )
+ h = (h>>28) ^ (h<<4) ^ PRUint16(*s++); // cast to unsigned to prevent possible sign extension
+
+ return h;
+}
+
+// This should use NSPR but NSPR isn't exporting its PR_strtoll function
+// Until then...
+PRInt64 nsCRT::atoll(const char *str)
+{
+ if (!str)
+ return LL_Zero();
+
+ PRInt64 ll = LL_Zero(), digitll = LL_Zero();
+
+ while (*str && *str >= '0' && *str <= '9') {
+ LL_MUL(ll, ll, 10);
+ LL_UI2L(digitll, (*str - '0'));
+ LL_ADD(ll, ll, digitll);
+ str++;
+ }
+
+ return ll;
+}
+
+/**
+ * Determine if given char in valid ascii range
+ *
+ * @update ftang 04.27.2000
+ * @param aChar is character to be tested
+ * @return TRUE if in ASCII range
+ */
+PRBool nsCRT::IsAscii(PRUnichar aChar) {
+ return (0x0080 > aChar);
+}
+/**
+ * Determine if given char in valid ascii range
+ *
+ * @update ftang 10.02.2001
+ * @param aString is null terminated to be tested
+ * @return TRUE if all characters aare in ASCII range
+ */
+PRBool nsCRT::IsAscii(const PRUnichar *aString) {
+ while(*aString) {
+ if( 0x0080 <= *aString)
+ return PR_FALSE;
+ aString++;
+ }
+ return PR_TRUE;
+}
+/**
+ * Determine if given char in valid ascii range
+ *
+ * @update ftang 10.02.2001
+ * @param aString is null terminated to be tested
+ * @return TRUE if all characters aare in ASCII range
+ */
+PRBool nsCRT::IsAscii(const char *aString) {
+ while(*aString) {
+ if( 0x80 & *aString)
+ return PR_FALSE;
+ aString++;
+ }
+ return PR_TRUE;
+}
+/**
+ * Determine whether the given string consists of valid ascii chars
+ *
+ * @param aString is null terminated
+ * @param aLength is the number of chars to test. This must be at most
+ * the number of chars in aString before the null terminator
+ * @return PR_TRUE if all chars are valid ASCII chars, PR_FALSE otherwise
+ */
+PRBool nsCRT::IsAscii(const char* aString, PRUint32 aLength)
+{
+ const char* end = aString + aLength;
+ while (aString < end) {
+ NS_ASSERTION(*aString, "Null byte before end of data!");
+ if (0x80 & *aString)
+ return PR_FALSE;
+ ++aString;
+ }
+ return PR_TRUE;
+}
+
+/**
+ * Determine if given char in valid alpha range
+ *
+ * @update rickg 03.10.2000
+ * @param aChar is character to be tested
+ * @return TRUE if in alpha range
+ */
+PRBool nsCRT::IsAsciiAlpha(PRUnichar aChar) {
+ // XXX i18n
+ if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+/**
+ * Determine if given char is a valid space character
+ *
+ * @update rickg 03.10.2000
+ * @param aChar is character to be tested
+ * @return TRUE if is valid space char
+ */
+PRBool nsCRT::IsAsciiSpace(PRUnichar aChar) {
+ // XXX i18n
+ if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+
+
+/**
+ * Determine if given char is valid digit
+ *
+ * @update rickg 03.10.2000
+ * @param aChar is character to be tested
+ * @return TRUE if char is a valid digit
+ */
+PRBool nsCRT::IsAsciiDigit(PRUnichar aChar) {
+ // XXX i18n
+ return PRBool((aChar >= '0') && (aChar <= '9'));
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCRT.h b/src/libs/xpcom18a4/xpcom/ds/nsCRT.h
new file mode 100644
index 00000000..c168a0a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCRT.h
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsCRT_h___
+#define nsCRT_h___
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "plstr.h"
+#include "nscore.h"
+#include "prtypes.h"
+#include "nsCppSharedAllocator.h"
+
+#ifdef XP_MAC
+# define NS_LINEBREAK "\015"
+# define NS_LINEBREAK_LEN 1
+#else
+# if defined(XP_WIN) || defined(XP_OS2)
+# define NS_LINEBREAK "\015\012"
+# define NS_LINEBREAK_LEN 2
+# else
+# if defined(XP_UNIX) || defined(XP_BEOS)
+# define NS_LINEBREAK "\012"
+# define NS_LINEBREAK_LEN 1
+# endif /* XP_UNIX */
+# endif /* XP_WIN || XP_OS2 */
+#endif /* XP_MAC */
+
+extern const PRUnichar kIsoLatin1ToUCS2[256];
+
+// This macro can be used in a class declaration for classes that want
+// to ensure that their instance memory is zeroed.
+#define NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW \
+ void* operator new(size_t sz) CPP_THROW_NEW { \
+ void* rv = ::operator new(sz); \
+ if (rv) { \
+ memset(rv, 0, sz); \
+ } \
+ return rv; \
+ } \
+ void operator delete(void* ptr) { \
+ ::operator delete(ptr); \
+ }
+
+// This macro works with the next macro to declare a non-inlined
+// version of the above.
+#define NS_DECL_ZEROING_OPERATOR_NEW \
+ void* operator new(size_t sz) CPP_THROW_NEW; \
+ void operator delete(void* ptr);
+
+#define NS_IMPL_ZEROING_OPERATOR_NEW(_class) \
+ void* _class::operator new(size_t sz) CPP_THROW_NEW { \
+ void* rv = ::operator new(sz); \
+ if (rv) { \
+ memset(rv, 0, sz); \
+ } \
+ return rv; \
+ } \
+ void _class::operator delete(void* ptr) { \
+ ::operator delete(ptr); \
+ }
+
+// Freeing helper
+#define CRTFREEIF(x) if (x) { nsCRT::free(x); x = 0; }
+
+/// This is a wrapper class around all the C runtime functions.
+
+class NS_COM nsCRT {
+public:
+ enum {
+ TAB='\t' /* Horizontal Tab */,
+ LF='\n' /* Line Feed */,
+ VTAB='\v' /* Vertical Tab */,
+ FF='\f' /* Form Feed */,
+ CR='\r' /* Carriage Return */
+ };
+
+ /***
+ *** The following nsCRT::mem* functions are no longer
+ *** supported, please use the corresponding lib C
+ *** functions instead.
+ ***
+ *** nsCRT::memcpy()
+ *** nsCRT::memcmp()
+ *** nsCRT::memmove()
+ *** nsCRT::memset()
+ *** nsCRT::zero()
+ ***
+ *** Additionally, the following char* string utilities
+ *** are no longer supported, please use the
+ *** corresponding lib C functions instead.
+ ***
+ *** nsCRT::strlen()
+ ***
+ ***/
+
+ /** Compute the string length of s
+ @param s the string in question
+ @return the length of s
+ */
+ static PRUint32 strlen(const char* s) {
+ return PRUint32(::strlen(s));
+ }
+
+ /// Compare s1 and s2.
+ static PRInt32 strcmp(const char* s1, const char* s2) {
+ return PRInt32(PL_strcmp(s1, s2));
+ }
+
+ static PRInt32 strncmp(const char* s1, const char* s2,
+ PRUint32 aMaxLen) {
+ return PRInt32(PL_strncmp(s1, s2, aMaxLen));
+ }
+
+ /// Case-insensitive string comparison.
+ static PRInt32 strcasecmp(const char* s1, const char* s2) {
+ return PRInt32(PL_strcasecmp(s1, s2));
+ }
+
+ /// Case-insensitive string comparison with length
+ static PRInt32 strncasecmp(const char* s1, const char* s2, PRUint32 aMaxLen) {
+ PRInt32 result=PRInt32(PL_strncasecmp(s1, s2, aMaxLen));
+ //Egads. PL_strncasecmp is returning *very* negative numbers.
+ //Some folks expect -1,0,1, so let's temper its enthusiasm.
+ if (result<0)
+ result=-1;
+ return result;
+ }
+
+ static PRInt32 strncmp(const char* s1, const char* s2, PRInt32 aMaxLen) {
+ // inline the first test (assumes strings are not null):
+ PRInt32 diff = ((const unsigned char*)s1)[0] - ((const unsigned char*)s2)[0];
+ if (diff != 0) return diff;
+ return PRInt32(PL_strncmp(s1,s2,unsigned(aMaxLen)));
+ }
+
+ static char* strdup(const char* str) {
+ return PL_strdup(str);
+ }
+
+ static char* strndup(const char* str, PRUint32 len) {
+ return PL_strndup(str, len);
+ }
+
+ static void free(char* str) {
+ PL_strfree(str);
+ }
+
+ /**
+
+ How to use this fancy (thread-safe) version of strtok:
+
+ void main(void) {
+ printf("%s\n\nTokens:\n", string);
+ // Establish string and get the first token:
+ char* newStr;
+ token = nsCRT::strtok(string, seps, &newStr);
+ while (token != NULL) {
+ // While there are tokens in "string"
+ printf(" %s\n", token);
+ // Get next token:
+ token = nsCRT::strtok(newStr, seps, &newStr);
+ }
+ }
+ * WARNING - STRTOK WHACKS str THE FIRST TIME IT IS CALLED *
+ * MAKE A COPY OF str IF YOU NEED TO USE IT AFTER strtok() *
+ */
+ static char* strtok(char* str, const char* delims, char* *newStr);
+
+ /// Like strlen except for ucs2 strings
+ static PRUint32 strlen(const PRUnichar* s);
+
+ /// Like strcmp except for ucs2 strings
+ static PRInt32 strcmp(const PRUnichar* s1, const PRUnichar* s2);
+ /// Like strcmp except for ucs2 strings
+ static PRInt32 strncmp(const PRUnichar* s1, const PRUnichar* s2,
+ PRUint32 aMaxLen);
+
+ // You must use nsCRT::free(PRUnichar*) to free memory allocated
+ // by nsCRT::strdup(PRUnichar*).
+ static PRUnichar* strdup(const PRUnichar* str);
+
+ // You must use nsCRT::free(PRUnichar*) to free memory allocated
+ // by strndup(PRUnichar*, PRUint32).
+ static PRUnichar* strndup(const PRUnichar* str, PRUint32 len);
+
+ static void free(PRUnichar* str) {
+ nsCppSharedAllocator<PRUnichar> shared_allocator;
+ shared_allocator.deallocate(str, 0 /*we never new or kept the size*/);
+ }
+
+ // Computes the hashcode for a c-string, returns the string length as
+ // an added bonus.
+ static PRUint32 HashCode(const char* str,
+ PRUint32* resultingStrLen = nsnull);
+
+ // Computes the hashcode for a ucs2 string, returns the string length
+ // as an added bonus.
+ static PRUint32 HashCode(const PRUnichar* str,
+ PRUint32* resultingStrLen = nsnull);
+
+ // Computes a hashcode for a ucs2 string that returns the same thing
+ // as the HashCode method taking a |char*| would if the string were
+ // converted to UTF8. Returns the string length as an added bonus.
+ static PRUint32 HashCodeAsUTF8(const PRUnichar* str,
+ PRUint32* resultingStrLen = nsnull);
+
+ // Computes the hashcode for a buffer with a specified length.
+ static PRUint32 BufferHashCode(const char* str, PRUint32 strLen);
+
+ // Computes the hashcode for a buffer with a specified length.
+ static PRUint32 BufferHashCode(const PRUnichar* str, PRUint32 strLen);
+
+ // String to longlong
+ static PRInt64 atoll(const char *str);
+
+ static char ToUpper(char aChar);
+
+ static char ToLower(char aChar);
+
+ static PRBool IsUpper(char aChar);
+
+ static PRBool IsLower(char aChar);
+
+ static PRBool IsAscii(PRUnichar aChar);
+ static PRBool IsAscii(const PRUnichar* aString);
+ static PRBool IsAsciiAlpha(PRUnichar aChar);
+ static PRBool IsAsciiDigit(PRUnichar aChar);
+ static PRBool IsAsciiSpace(PRUnichar aChar);
+ static PRBool IsAscii(const char* aString);
+ static PRBool IsAscii(const char* aString, PRUint32 aLength);
+};
+
+#define FF '\014'
+#define TAB '\011'
+
+#define CRSTR "\015"
+#define LFSTR "\012"
+#define CRLF "\015\012" /* A CR LF equivalent string */
+
+
+#if defined(XP_MAC)
+ #define FILE_PATH_SEPARATOR ":"
+ #define FILE_ILLEGAL_CHARACTERS ""
+#elif defined(XP_WIN) || defined(XP_OS2)
+ #define FILE_PATH_SEPARATOR "\\"
+ #define FILE_ILLEGAL_CHARACTERS "/:*?\"<>|"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ #define FILE_PATH_SEPARATOR "/"
+ #define FILE_ILLEGAL_CHARACTERS ""
+#else
+ #error need_to_define_your_file_path_separator_and_illegal_characters
+#endif
+
+#define NS_IS_SPACE(VAL) \
+ (((((intn)(VAL)) & 0x7f) == ((intn)(VAL))) && isspace((intn)(VAL)) )
+
+#define NS_IS_CNTRL(i) ((((unsigned int) (i)) > 0x7f) ? (int) 0 : iscntrl(i))
+#define NS_IS_DIGIT(i) ((((unsigned int) (i)) > 0x7f) ? (int) 0 : isdigit(i))
+#if defined(XP_WIN) || defined(XP_OS2)
+#define NS_IS_ALPHA(VAL) (isascii((int)(VAL)) && isalpha((int)(VAL)))
+#else
+#define NS_IS_ALPHA(VAL) ((((unsigned int) (VAL)) > 0x7f) ? (int) 0 : isalpha((int)(VAL)))
+#endif
+
+
+#endif /* nsCRT_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp
new file mode 100644
index 00000000..954de2d1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.cpp
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCheapSets.h"
+
+nsCheapStringSet::~nsCheapStringSet()
+{
+ nsStringHashSet* set = GetHash();
+ if (set) {
+ delete set;
+ } else {
+ delete GetStr();
+ }
+}
+
+/**
+ * Put a string into the table
+ */
+nsresult
+nsCheapStringSet::Put(const nsAString& aVal)
+{
+ // Add the value to the hash if it is there
+ nsStringHashSet* set = GetHash();
+ if (set) {
+ return set->Put(aVal);
+ }
+
+ // If a string is already there, create a hashtable and both of these to it
+ if (GetStr()) {
+ nsAString* oldStr = GetStr();
+ nsresult rv = InitHash(&set);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = set->Put(*oldStr);
+ delete oldStr;
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return set->Put(aVal);
+ }
+
+ // Nothing exists in the hash right now, so just set the single string
+ return SetStr(aVal);
+}
+
+void
+nsCheapStringSet::Remove(const nsAString& aVal)
+{
+ // Remove from the hash if the hash is there
+ nsStringHashSet* set = GetHash();
+ if (set) {
+ set->Remove(aVal);
+ return;
+ }
+
+ // Remove the string if there is just a string
+ nsAString* str = GetStr();
+ if (str && str->Equals(aVal)) {
+ delete str;
+ mValOrHash = nsnull;
+ }
+}
+
+nsresult
+nsCheapStringSet::InitHash(nsStringHashSet** aSet)
+{
+ nsStringHashSet* newSet = new nsStringHashSet();
+ if (!newSet) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult rv = newSet->Init(10);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mValOrHash = newSet;
+ *aSet = newSet;
+ return NS_OK;
+}
+
+
+nsCheapInt32Set::~nsCheapInt32Set()
+{
+ delete GetHash();
+}
+
+nsresult
+nsCheapInt32Set::Put(PRInt32 aVal)
+{
+ // Add the value to the hash or set the pointer as an int
+ nsInt32HashSet* set = GetHash();
+ if (set) {
+ return set->Put(aVal);
+ }
+
+ // Create the hash and add the value to it if there is an int already
+ if (IsInt()) {
+ PRInt32 oldInt = GetInt();
+
+ nsresult rv = InitHash(&set);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = set->Put(oldInt);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return set->Put(aVal);
+ }
+
+ // Create the hash anyway if the int is negative (negative numbers cannot
+ // fit into our PtrBits abstraction)
+ if (aVal < 0) {
+ nsresult rv = InitHash(&set);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return set->Put(aVal);
+ }
+
+ // Finally, just set the int if we can't do anything with hashes
+ SetInt(aVal);
+ return NS_OK;
+}
+
+void
+nsCheapInt32Set::Remove(PRInt32 aVal)
+{
+ nsInt32HashSet* set = GetHash();
+ if (set) {
+ set->Remove(aVal);
+ } else if (IsInt() && GetInt() == aVal) {
+ mValOrHash = nsnull;
+ }
+}
+
+nsresult
+nsCheapInt32Set::InitHash(nsInt32HashSet** aSet)
+{
+ nsInt32HashSet* newSet = new nsInt32HashSet();
+ if (!newSet) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult rv = newSet->Init(10);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mValOrHash = newSet;
+ *aSet = newSet;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h
new file mode 100644
index 00000000..7e1c917d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCheapSets.h
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsCheapSets_h__
+#define __nsCheapSets_h__
+
+#include "nsHashSets.h"
+
+/**
+ * A string set that takes up minimal size when there are 0 or 1 strings in the
+ * set. Use for cases where sizes of 0 and 1 are even slightly common.
+ */
+class NS_COM nsCheapStringSet {
+public:
+ nsCheapStringSet() : mValOrHash(nsnull)
+ {
+ }
+ ~nsCheapStringSet();
+
+ /**
+ * Put a string into the set
+ * @param aVal the value to put in
+ */
+ nsresult Put(const nsAString& aVal);
+
+ /**
+ * Remove a string from the set
+ * @param aVal the string to remove
+ */
+ void Remove(const nsAString& aVal);
+
+ /**
+ * Check if the set contains a particular string
+ * @param aVal the string to check for
+ * @return whether the string is in the set
+ */
+ PRBool Contains(const nsAString& aVal)
+ {
+ nsStringHashSet* set = GetHash();
+ // Check the value from the hash if the hash is there
+ if (set) {
+ return set->Contains(aVal);
+ }
+
+ // Check whether the value is equal to the string if the string is there
+ nsAString* str = GetStr();
+ return str && str->Equals(aVal);
+ }
+
+private:
+ typedef PRUint64 PtrBits;
+
+ /** Get the hash pointer (or null if we're not a hash) */
+ nsStringHashSet* GetHash()
+ {
+ return (PtrBits(mValOrHash) & 0x1) ? nsnull : (nsStringHashSet*)mValOrHash;
+ }
+ /** Find out whether it is a string */
+ nsAString* GetStr()
+ {
+ return (PtrBits(mValOrHash) & 0x1)
+ ? (nsAString*)(PtrBits(mValOrHash) & ~0x1)
+ : nsnull;
+ }
+ /** Set the single string */
+ nsresult SetStr(const nsAString& aVal)
+ {
+ nsString* str = new nsString(aVal);
+ if (!str) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mValOrHash = (nsAString*)(PtrBits(str) | 0x1);
+ return NS_OK;
+ }
+ /** Initialize the hash */
+ nsresult InitHash(nsStringHashSet** aSet);
+
+private:
+ /** A hash or string ptr, depending on the lower bit (0=hash, 1=string) */
+ void* mValOrHash;
+};
+
+
+/**
+ * An integer set that takes up only 4 bytes when there are 0 or 1 integers
+ * in the set. Use for cases where sizes of 0 and 1 are even slightly common.
+ */
+class NS_COM nsCheapInt32Set {
+public:
+ nsCheapInt32Set() : mValOrHash(nsnull)
+ {
+ }
+ ~nsCheapInt32Set();
+
+ /**
+ * Put an int into the set
+ */
+ nsresult Put(PRInt32 aVal);
+
+ /**
+ * Remove a int from the set
+ * @param aVal the int to remove
+ */
+ void Remove(PRInt32 aVal);
+
+ /**
+ * Check if the set contains a particular int
+ * @param aVal the int to check for
+ * @return whether the int is in the set
+ */
+ PRBool Contains(PRInt32 aVal)
+ {
+ nsInt32HashSet* set = GetHash();
+ if (set) {
+ return set->Contains(aVal);
+ }
+ if (IsInt()) {
+ return GetInt() == aVal;
+ }
+ return PR_FALSE;
+ }
+
+private:
+ typedef PRUint64 PtrBits;
+
+ /** Get the hash pointer (or null if we're not a hash) */
+ nsInt32HashSet* GetHash()
+ {
+ return PtrBits(mValOrHash) & 0x1 ? nsnull : (nsInt32HashSet*)mValOrHash;
+ }
+ /** Find out whether it is an integer */
+ PRBool IsInt()
+ {
+ return !!(PtrBits(mValOrHash) & 0x1);
+ }
+ /** Get the single integer */
+ PRInt32 GetInt()
+ {
+ return PtrBits(mValOrHash) >> 1;
+ }
+ /** Set the single integer */
+ void SetInt(PRInt32 aInt)
+ {
+ mValOrHash = (void*)(uintptr_t)((aInt << 1) | 0x1);
+ }
+ /** Create the hash and initialize */
+ nsresult InitHash(nsInt32HashSet** aSet);
+
+private:
+ /** A hash or int, depending on the lower bit (0=hash, 1=int) */
+ void* mValOrHash;
+};
+
+
+/**
+ * XXX We may want an nsCheapVoidSet and nsCheapCStringSet at some point
+ */
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h
new file mode 100644
index 00000000..1fd73489
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsClassHashtable.h
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsClassHashtable_h__
+#define nsClassHashtable_h__
+
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsAutoPtr.h"
+
+/**
+ * templated hashtable class maps keys to C++ object pointers.
+ * See nsBaseHashtable for complete declaration.
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Class the class-type being wrapped
+ * @see nsInterfaceHashtable, nsClassHashtable
+ */
+template<class KeyClass,class T>
+class nsClassHashtable :
+ public nsBaseHashtable< KeyClass, nsAutoPtr<T>, T* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef T* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData if the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+};
+
+
+/**
+ * Thread-safe version of nsClassHashtable
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Class the class-type being wrapped
+ * @see nsInterfaceHashtable, nsClassHashtable
+ */
+template<class KeyClass,class T>
+class nsClassHashtableMT :
+ public nsBaseHashtableMT< KeyClass, nsAutoPtr<T>, T* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef T* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData if the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+};
+
+
+//
+// nsClassHashtable definitions
+//
+
+template<class KeyClass,class T>
+PRBool
+nsClassHashtable<KeyClass,T>::Get(KeyType aKey, T** retVal) const
+{
+ typename nsBaseHashtable<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (retVal)
+ *retVal = ent->mData;
+
+ return PR_TRUE;
+ }
+
+ if (retVal)
+ *retVal = nsnull;
+
+ return PR_FALSE;
+}
+
+
+//
+// nsClassHashtableMT definitions
+//
+
+template<class KeyClass,class T>
+PRBool
+nsClassHashtableMT<KeyClass,T>::Get(KeyType aKey, T** retVal) const
+{
+ PR_Lock(this->mLock);
+
+ typename nsBaseHashtableMT<KeyClass,nsAutoPtr<T>,T*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (retVal)
+ *retVal = ent->mData;
+
+ PR_Unlock(this->mLock);
+
+ return PR_TRUE;
+ }
+
+ if (retVal)
+ *retVal = nsnull;
+
+ PR_Unlock(this->mLock);
+
+ return PR_FALSE;
+}
+
+#endif // nsClassHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h
new file mode 100644
index 00000000..55f3e19d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsCppSharedAllocator.h
@@ -0,0 +1,127 @@
+#ifndef nsCppSharedAllocator_h__
+#define nsCppSharedAllocator_h__
+
+#include "nsMemory.h" // for |nsMemory|
+#include "nscore.h" // for |NS_XXX_CAST|
+#include NEW_H // to allow placement |new|
+
+
+ // under Metrowerks (Mac), we don't have autoconf yet
+#ifdef __MWERKS__
+ #define HAVE_CPP_MEMBER_TEMPLATES
+ #define HAVE_CPP_NUMERIC_LIMITS
+#endif
+
+ // under MSVC shut off copious warnings about unused in-lines
+#ifdef _MSC_VER
+ #pragma warning( disable: 4514 )
+#endif
+
+#ifdef HAVE_CPP_NUMERIC_LIMITS
+#include <limits>
+#else
+#include <limits.h>
+#endif
+
+
+template <class T>
+class nsCppSharedAllocator
+ /*
+ ...allows Standard Library containers, et al, to use our global shared
+ (XP)COM-aware allocator.
+ */
+ {
+ public:
+ typedef T value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef T* pointer;
+ typedef const T* const_pointer;
+
+ typedef T& reference;
+ typedef const T& const_reference;
+
+
+
+ nsCppSharedAllocator() { }
+
+#ifdef HAVE_CPP_MEMBER_TEMPLATES
+ template <class U>
+ nsCppSharedAllocator( const nsCppSharedAllocator<U>& ) { }
+#endif
+
+ ~nsCppSharedAllocator() { }
+
+
+ pointer
+ address( reference r ) const
+ {
+ return &r;
+ }
+
+ const_pointer
+ address( const_reference r ) const
+ {
+ return &r;
+ }
+
+ pointer
+ allocate( size_type n, const void* /*hint*/=0 )
+ {
+ return NS_REINTERPRET_CAST(pointer, nsMemory::Alloc(NS_STATIC_CAST(PRUint32, n*sizeof(T))));
+ }
+
+ void
+ deallocate( pointer p, size_type /*n*/ )
+ {
+ nsMemory::Free(p);
+ }
+
+ void
+ construct( pointer p, const T& val )
+ {
+ new (p) T(val);
+ }
+
+ void
+ destroy( pointer p )
+ {
+ p->~T();
+ }
+
+ size_type
+ max_size() const
+ {
+#ifdef HAVE_CPP_NUMERIC_LIMITS
+ return numeric_limits<size_type>::max() / sizeof(T);
+#else
+ return ULONG_MAX / sizeof(T);
+#endif
+ }
+
+#ifdef HAVE_CPP_MEMBER_TEMPLATES
+ template <class U>
+ struct rebind
+ {
+ typedef nsCppSharedAllocator<U> other;
+ };
+#endif
+ };
+
+
+template <class T>
+PRBool
+operator==( const nsCppSharedAllocator<T>&, const nsCppSharedAllocator<T>& )
+ {
+ return PR_TRUE;
+ }
+
+template <class T>
+PRBool
+operator!=( const nsCppSharedAllocator<T>&, const nsCppSharedAllocator<T>& )
+ {
+ return PR_FALSE;
+ }
+
+#endif /* !defined(nsCppSharedAllocator_h__) */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h
new file mode 100644
index 00000000..7a14f826
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDataHashtable.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDataHashtable_h__
+#define nsDataHashtable_h__
+
+#include "nsHashKeys.h"
+#include "nsBaseHashtable.h"
+
+/**
+ * templated hashtable class maps keys to simple datatypes.
+ * See nsBaseHashtable for complete declaration
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param DataType the simple datatype being wrapped
+ * @see nsInterfaceHashtable, nsClassHashtable
+ */
+template<class KeyClass,class DataType>
+class nsDataHashtable :
+ public nsBaseHashtable<KeyClass,DataType,DataType>
+{ };
+
+template<class KeyClass,class DataType>
+class nsDataHashtableMT :
+ public nsBaseHashtableMT<KeyClass,DataType,DataType>
+{ };
+
+#endif // nsDataHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp b/src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp
new file mode 100644
index 00000000..d94568bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDeque.cpp
@@ -0,0 +1,627 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDeque.h"
+#include "nsCRT.h"
+#ifdef DEBUG_rickg
+#include <stdio.h>
+#endif
+
+/**
+ * 07/02/2001 09:17p 509,104 clangref.pdf from openwatcom's site
+ * Watcom C Language Reference Edition 11.0c
+ * page 118 of 297
+ *
+ * The % symbol yields the remainder from the division of the first operand
+ * by the second operand. The operands of % must have integral type.
+ *
+ * When both operands of % are positive, the result is a positive value
+ * smaller than the second operand. When one or both operands is negative,
+ * whether the result is positive or negative is implementation-defined.
+ *
+ */
+/* Ok, so first of all, C is underspecified. joy.
+ * The following functions do not provide a correct implementation of modulus
+ * They provide functionality for x>-y.
+ * There are risks of 2*y being greater than max int, which is part of the
+ * reason no multiplication is used and other operations are avoided.
+ *
+ * modasgn
+ * @param x variable
+ * @param y expression
+ * approximately equivalent to x %= y
+ *
+ * modulus
+ * @param x expression
+ * @param y expression
+ * approximately equivalent to x % y
+ */
+#define modasgn(x,y) if (x<0) x+=y; x%=y
+#define modulus(x,y) ((x<0)?(x+y)%(y):(x)%(y))
+
+MOZ_DECL_CTOR_COUNTER(nsDeque)
+
+/**
+ * Standard constructor
+ * @param deallocator, called by Erase and ~nsDeque
+ */
+nsDeque::nsDeque(nsDequeFunctor* aDeallocator) {
+ MOZ_COUNT_CTOR(nsDeque);
+ mDeallocator=aDeallocator;
+ mOrigin=mSize=0;
+ mData=mBuffer; // don't allocate space until you must
+ mCapacity=sizeof(mBuffer)/sizeof(mBuffer[0]);
+ memset(mData, 0, mCapacity*sizeof(mBuffer[0]));
+}
+
+/**
+ * Destructor
+ */
+nsDeque::~nsDeque() {
+ MOZ_COUNT_DTOR(nsDeque);
+
+#ifdef DEBUG_rickg
+ char buffer[30];
+ printf("Capacity: %i\n", mCapacity);
+
+ static int mCaps[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ switch(mCapacity) {
+ case 4: mCaps[0]++; break;
+ case 8: mCaps[1]++; break;
+ case 16: mCaps[2]++; break;
+ case 32: mCaps[3]++; break;
+ case 64: mCaps[4]++; break;
+ case 128: mCaps[5]++; break;
+ case 256: mCaps[6]++; break;
+ case 512: mCaps[7]++; break;
+ case 1024: mCaps[8]++; break;
+ case 2048: mCaps[9]++; break;
+ case 4096: mCaps[10]++; break;
+ default:
+ break;
+ }
+#endif
+
+ Erase();
+ if (mData && (mData!=mBuffer)) {
+ delete [] mData;
+ }
+ mData=0;
+ SetDeallocator(0);
+}
+
+/**
+ * Set the functor to be called by Erase()
+ * The deque owns the functor.
+ *
+ * @param aDeallocator functor object for use by Erase()
+ */
+void nsDeque::SetDeallocator(nsDequeFunctor* aDeallocator){
+ if (mDeallocator) {
+ delete mDeallocator;
+ }
+ mDeallocator=aDeallocator;
+}
+
+/**
+ * Remove all items from container without destroying them.
+ *
+ * @return *this
+ */
+nsDeque& nsDeque::Empty() {
+ if (mSize && mData) {
+ memset(mData, 0, mCapacity*sizeof(*mData));
+ }
+ mSize=0;
+ mOrigin=0;
+ return *this;
+}
+
+/**
+ * Remove and delete all items from container
+ *
+ * @return *this
+ */
+nsDeque& nsDeque::Erase() {
+ if (mDeallocator && mSize) {
+ ForEach(*mDeallocator);
+ }
+ return Empty();
+}
+
+/**
+ * This method quadruples the size of the deque
+ * Elements in the deque are resequenced so that elements
+ * in the deque are stored sequentially
+ *
+ * If the deque actually overflows, there's very little we can do.
+ * Perhaps this function should return PRBool/nsresult indicating success/failure.
+ *
+ * @return capacity of the deque
+ * If the deque did not grow,
+ * and you knew its capacity beforehand,
+ * then this would be a way to indicate the failure.
+ */
+PRInt32 nsDeque::GrowCapacity() {
+ PRInt32 theNewSize=mCapacity<<2;
+ NS_ASSERTION(theNewSize>mCapacity, "Overflow");
+ if (theNewSize<=mCapacity)
+ return mCapacity;
+ void** temp=new void*[theNewSize];
+
+ //Here's the interesting part: You can't just move the elements
+ //directly (in situ) from the old buffer to the new one.
+ //Since capacity has changed, the old origin doesn't make
+ //sense anymore. It's better to resequence the elements now.
+
+ if (temp) {
+ PRInt32 tempi=0;
+ PRInt32 i=0;
+ PRInt32 j=0;
+ for (i=mOrigin; i<mCapacity; i++) {
+ temp[tempi++]=mData[i]; //copy the leading elements...
+ }
+ for (j=0;j<mOrigin;j++) {
+ temp[tempi++]=mData[j]; //copy the trailing elements...
+ }
+ if (mData != mBuffer) {
+ delete [] mData;
+ }
+ mCapacity=theNewSize;
+ mOrigin=0; //now realign the origin...
+ mData=temp;
+ }
+ return mCapacity;
+}
+
+/**
+ * This method adds an item to the end of the deque.
+ * This operation has the potential to cause the
+ * underlying buffer to resize.
+ *
+ * @param aItem: new item to be added to deque
+ * @return *this
+ */
+nsDeque& nsDeque::Push(void* aItem) {
+ if (mSize==mCapacity) {
+ GrowCapacity();
+ }
+ mData[modulus(mOrigin + mSize, mCapacity)]=aItem;
+ mSize++;
+ return *this;
+}
+
+/**
+ * This method adds an item to the front of the deque.
+ * This operation has the potential to cause the
+ * underlying buffer to resize.
+ *
+ * --Commments for GrowCapacity() case
+ * We've grown and shifted which means that the old
+ * final element in the deque is now the first element
+ * in the deque. This is temporary.
+ * We haven't inserted the new element at the front.
+ *
+ * To continue with the idea of having the front at zero
+ * after a grow, we move the old final item (which through
+ * the voodoo of mOrigin-- is now the first) to its final
+ * position which is conveniently the old length.
+ *
+ * Note that this case only happens when the deque is full.
+ * [And that pieces of this magic only work if the deque is full.]
+ * picture:
+ * [ABCDEFGH] @[mOrigin:3]:D.
+ * Task: PushFront("Z")
+ * shift mOrigin so, @[mOrigin:2]:C
+ * stretch and rearrange: (mOrigin:0)
+ * [CDEFGHAB ________ ________ ________]
+ * copy: (The second C is currently out of bounds)
+ * [CDEFGHAB C_______ ________ ________]
+ * later we will insert Z:
+ * [ZDEFGHAB C_______ ________ ________]
+ * and increment size: 9. (C is no longer out of bounds)
+ * --
+ * @param aItem: new item to be added to deque
+ * @return *this
+ */
+nsDeque& nsDeque::PushFront(void* aItem) {
+ mOrigin--;
+ modasgn(mOrigin,mCapacity);
+ if (mSize==mCapacity) {
+ GrowCapacity();
+ /* Comments explaining this are above*/
+ mData[mSize]=mData[mOrigin];
+ }
+ mData[mOrigin]=aItem;
+ mSize++;
+ return *this;
+}
+
+/**
+ * Remove and return the last item in the container.
+ *
+ * @return ptr to last item in container
+ */
+void* nsDeque::Pop() {
+ void* result=0;
+ if (mSize>0) {
+ --mSize;
+ PRInt32 offset=modulus(mSize + mOrigin, mCapacity);
+ result=mData[offset];
+ mData[offset]=0;
+ if (!mSize) {
+ mOrigin=0;
+ }
+ }
+ return result;
+}
+
+/**
+ * This method gets called you want to remove and return
+ * the first member in the container.
+ *
+ * @return last item in container
+ */
+void* nsDeque::PopFront() {
+ void* result=0;
+ if (mSize>0) {
+ NS_ASSERTION(mOrigin < mCapacity, "Error: Bad origin");
+ result=mData[mOrigin];
+ mData[mOrigin++]=0; //zero it out for debugging purposes.
+ mSize--;
+ // Cycle around if we pop off the end
+ // and reset origin if when we pop the last element
+ if (mCapacity==mOrigin || !mSize) {
+ mOrigin=0;
+ }
+ }
+ return result;
+}
+
+/**
+ * This method gets called you want to peek at the bottom
+ * member without removing it.
+ *
+ * @return last item in container
+ */
+void* nsDeque::Peek() {
+ void* result=0;
+ if (mSize>0) {
+ result = mData[modulus(mSize - 1 + mOrigin, mCapacity)];
+ }
+ return result;
+}
+
+/**
+ * This method gets called you want to peek at the topmost
+ * member without removing it.
+ *
+ * @return last item in container
+ */
+void* nsDeque::PeekFront() {
+ void* result=0;
+ if (mSize>0) {
+ result=mData[mOrigin];
+ }
+ return result;
+}
+
+/**
+ * Call this to retrieve the ith element from this container.
+ * Keep in mind that accessing the underlying elements is
+ * done in a relative fashion. Object 0 is not necessarily
+ * the first element (the first element is at mOrigin).
+ *
+ * @param aIndex : 0 relative offset of item you want
+ * @return void* or null
+ */
+void* nsDeque::ObjectAt(PRInt32 aIndex) const {
+ void* result=0;
+ if ((aIndex>=0) && (aIndex<mSize)) {
+ result=mData[modulus(mOrigin + aIndex, mCapacity)];
+ }
+ return result;
+}
+
+/**
+ * Create and return an iterator pointing to
+ * the beginning of the queue. Note that this
+ * takes the circular buffer semantics into account.
+ *
+ * @return new deque iterator, init'ed to 1st item
+ */
+nsDequeIterator nsDeque::Begin() const{
+ return nsDequeIterator(*this, 0);
+}
+
+/**
+ * Create and return an iterator pointing to
+ * the last item in the deque.
+ * Note that this takes the circular buffer semantics
+ * into account.
+ *
+ * @return new deque iterator, init'ed to the last item
+ */
+nsDequeIterator nsDeque::End() const{
+ return nsDequeIterator(*this, mSize - 1);
+}
+
+void* nsDeque::Last() const {
+ return End().GetCurrent();
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+void nsDeque::ForEach(nsDequeFunctor& aFunctor) const{
+ for (PRInt32 i=0; i<mSize; i++) {
+ aFunctor(ObjectAt(i));
+ }
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+const void* nsDeque::FirstThat(nsDequeFunctor& aFunctor) const{
+ for (PRInt32 i=0; i<mSize; i++) {
+ void* obj=aFunctor(ObjectAt(i));
+ if (obj) {
+ return obj;
+ }
+ }
+ return 0;
+}
+
+/******************************************************
+ * Here comes the nsDequeIterator class...
+ ******************************************************/
+
+/**
+ * DequeIterator is an object that knows how to iterate (forward and backward)
+ * through a Deque. Normally, you don't need to do this, but there are some special
+ * cases where it is pretty handy, so here you go.
+ *
+ * This is a standard dequeiterator constructor
+ *
+ * @param aQueue is the deque object to be iterated
+ * @param aIndex is the starting position for your iteration
+ */
+nsDequeIterator::nsDequeIterator(const nsDeque& aQueue, int aIndex)
+: mIndex(aIndex),
+ mDeque(aQueue)
+{
+}
+
+/**
+ * Create a copy of a DequeIterator
+ *
+ * @param aCopy is another iterator to copy from
+ */
+nsDequeIterator::nsDequeIterator(const nsDequeIterator& aCopy)
+: mIndex(aCopy.mIndex),
+ mDeque(aCopy.mDeque)
+{
+}
+
+/**
+ * Moves iterator to first element in deque
+ * @return *this
+ */
+nsDequeIterator& nsDequeIterator::First(){
+ mIndex=0;
+ return *this;
+}
+
+/**
+ * Standard assignment operator for dequeiterator
+ *
+ * @param aCopy is an iterator to be copied from
+ * @return *this
+ */
+nsDequeIterator& nsDequeIterator::operator=(const nsDequeIterator& aCopy) {
+ NS_ASSERTION(&mDeque==&aCopy.mDeque,"you can't change the deque that an interator is iterating over, sorry.");
+ mIndex=aCopy.mIndex;
+ return *this;
+}
+
+/**
+ * preform ! operation against to iterators to test for equivalence
+ * (or lack thereof)!
+ *
+ * @param aIter is the object to be compared to
+ * @return TRUE if NOT equal.
+ */
+PRBool nsDequeIterator::operator!=(nsDequeIterator& aIter) {
+ return PRBool(!this->operator==(aIter));
+}
+
+/**
+ * Compare two iterators for increasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to an element before
+ * the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over the same deque.
+ */
+PRBool nsDequeIterator::operator<(nsDequeIterator& aIter) {
+ return PRBool(((mIndex<aIter.mIndex) && (&mDeque==&aIter.mDeque)));
+}
+
+/**
+ * Compare two iterators for equivalence.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if EQUAL
+ */
+PRBool nsDequeIterator::operator==(nsDequeIterator& aIter) {
+ return PRBool(((mIndex==aIter.mIndex) && (&mDeque==&aIter.mDeque)));
+}
+
+/**
+ * Compare two iterators for non strict decreasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to the same element, or
+ * an element after the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over the same deque.
+ */
+PRBool nsDequeIterator::operator>=(nsDequeIterator& aIter) {
+ return PRBool(((mIndex>=aIter.mIndex) && (&mDeque==&aIter.mDeque)));
+}
+
+/**
+ * Pre-increment operator
+ *
+ * @return object at post-incremented index
+ */
+void* nsDequeIterator::operator++() {
+ NS_ASSERTION(mIndex<mDeque.mSize,
+ "You have reached the end of the Internet."\
+ "You have seen everything there is to see. Please go back. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex>=mDeque.mSize) return 0;
+#endif
+ return mDeque.ObjectAt(++mIndex);
+}
+
+/**
+ * Post-increment operator
+ *
+ * @param param is ignored
+ * @return object at pre-incremented index
+ */
+void* nsDequeIterator::operator++(int) {
+ NS_ASSERTION(mIndex<=mDeque.mSize,
+ "You have already reached the end of the Internet."\
+ "You have seen everything there is to see. Please go back. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex>mDeque.mSize) return 0;
+#endif
+ return mDeque.ObjectAt(mIndex++);
+}
+
+/**
+ * Pre-decrement operator
+ *
+ * @return object at pre-decremented index
+ */
+void* nsDequeIterator::operator--() {
+ NS_ASSERTION(mIndex>=0,
+ "You have reached the beginning of the Internet."\
+ "You have seen everything there is to see. Please go forward. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex<0) return 0;
+#endif
+ return mDeque.ObjectAt(--mIndex);
+}
+
+/**
+ * Post-decrement operator
+ *
+ * @param param is ignored
+ * @return object at post-decremented index
+ */
+void* nsDequeIterator::operator--(int) {
+ NS_ASSERTION(mIndex>=0,
+ "You have already reached the beginning of the Internet."\
+ "You have seen everything there is to see. Please go forward. Now."
+ );
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex<0) return 0;
+#endif
+ return mDeque.ObjectAt(mIndex--);
+}
+
+/**
+ * Dereference operator
+ * Note that the iterator floats, so you don't need to do:
+ * <code>++iter; aDeque.PopFront();</code>
+ * Unless you actually want your iterator to jump 2 spaces.
+ *
+ * Picture: [1 2I 3 4]
+ * PopFront()
+ * Picture: [2 3I 4]
+ * Note that I still happily points to object at the second index
+ *
+ * @return object at ith index
+ */
+void* nsDequeIterator::GetCurrent() {
+ NS_ASSERTION(mIndex<mDeque.mSize&&mIndex>=0,"Current is out of bounds");
+#ifndef TIMELESS_LIGHTWEIGHT
+ if (mIndex>=mDeque.mSize||mIndex<0) return 0;
+#endif
+ return mDeque.ObjectAt(mIndex);
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+void nsDequeIterator::ForEach(nsDequeFunctor& aFunctor) const{
+ mDeque.ForEach(aFunctor);
+}
+
+/**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+const void* nsDequeIterator::FirstThat(nsDequeFunctor& aFunctor) const{
+ return mDeque.FirstThat(aFunctor);
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDeque.h b/src/libs/xpcom18a4/xpcom/ds/nsDeque.h
new file mode 100644
index 00000000..7fdf7465
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDeque.h
@@ -0,0 +1,405 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * MODULE NOTES:
+ *
+ * The Deque is a very small, very efficient container object
+ * than can hold elements of type void*, offering the following features:
+ * Its interface supports pushing and popping of elements.
+ * It can iterate (via an interator class) its elements.
+ * When full, it can efficiently resize dynamically.
+ *
+ *
+ * NOTE: The only bit of trickery here is that this deque is
+ * built upon a ring-buffer. Like all ring buffers, the first
+ * element may not be at index[0]. The mOrigin member determines
+ * where the first child is. This point is quietly hidden from
+ * customers of this class.
+ *
+ */
+
+#ifndef _NSDEQUE
+#define _NSDEQUE
+
+#include "nscore.h"
+
+/**
+ * The nsDequeFunctor class is used when you want to create
+ * callbacks between the deque and your generic code.
+ * Use these objects in a call to ForEach();
+ *
+ */
+
+class nsDequeFunctor{
+public:
+ virtual void* operator()(void* anObject)=0;
+};
+
+/******************************************************
+ * Here comes the nsDeque class itself...
+ ******************************************************/
+
+/**
+ * The deque (double-ended queue) class is a common container type,
+ * whose behavior mimics a line in your favorite checkout stand.
+ * Classic CS describes the common behavior of a queue as FIFO.
+ * A deque allows insertion and removal at both ends of
+ * the container.
+ *
+ * The deque stores pointers to items.
+ */
+
+class nsDequeIterator;
+
+class NS_COM nsDeque {
+ friend class nsDequeIterator;
+ public:
+ nsDeque(nsDequeFunctor* aDeallocator);
+ ~nsDeque();
+
+ /**
+ * Returns the number of elements currently stored in
+ * this deque.
+ *
+ * @return number of elements currently in the deque
+ */
+ inline PRInt32 GetSize() const {return mSize;}
+
+ /**
+ * Appends new member at the end of the deque.
+ *
+ * @param item to store in deque
+ * @return *this
+ */
+ nsDeque& Push(void* aItem);
+
+ /**
+ * Inserts new member at the front of the deque.
+ *
+ * @param item to store in deque
+ * @return *this
+ */
+ nsDeque& PushFront(void* aItem);
+
+ /**
+ * Remove and return the last item in the container.
+ *
+ * @return the item that was the last item in container
+ */
+ void* Pop();
+
+ /**
+ * Remove and return the first item in the container.
+ *
+ * @return the item that was first item in container
+ */
+ void* PopFront();
+
+ /**
+ * Retrieve the bottom item without removing it.
+ *
+ * @return the first item in container
+ */
+
+ void* Peek();
+ /**
+ * Return topmost item without removing it.
+ *
+ * @return the first item in container
+ */
+ void* PeekFront();
+
+ /**
+ * Retrieve the i'th member from the deque without removing it.
+ *
+ * @param index of desired item
+ * @return i'th element in list
+ */
+ void* ObjectAt(int aIndex) const;
+
+ /**
+ * Remove all items from container without destroying them.
+ *
+ * @return *this
+ */
+ nsDeque& Empty();
+
+ /**
+ * Remove and delete all items from container.
+ * Deletes are handled by the deallocator nsDequeFunctor
+ * which is specified at deque construction.
+ *
+ * @return *this
+ */
+ nsDeque& Erase();
+
+ /**
+ * Creates a new iterator, pointing to the first
+ * item in the deque.
+ *
+ * @return new dequeIterator
+ */
+ nsDequeIterator Begin() const;
+
+ /**
+ * Creates a new iterator, pointing to the last
+ * item in the deque.
+ *
+ * @return new dequeIterator
+ */
+ nsDequeIterator End() const;
+
+ void* Last() const;
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+ void ForEach(nsDequeFunctor& aFunctor) const;
+
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+ const void* FirstThat(nsDequeFunctor& aFunctor) const;
+
+ void SetDeallocator(nsDequeFunctor* aDeallocator);
+
+protected:
+ PRInt32 mSize;
+ PRInt32 mCapacity;
+ PRInt32 mOrigin;
+ nsDequeFunctor* mDeallocator;
+ void* mBuffer[8];
+ void** mData;
+
+private:
+
+ /**
+ * Simple default constructor (PRIVATE)
+ */
+ nsDeque();
+
+ /**
+ * Copy constructor (PRIVATE)
+ *
+ * @param another deque
+ */
+ nsDeque(const nsDeque& other);
+
+ /**
+ * Deque assignment operator (PRIVATE)
+ *
+ * @param another deque
+ * @return *this
+ */
+ nsDeque& operator=(const nsDeque& anOther);
+
+ PRInt32 GrowCapacity();
+};
+
+/******************************************************
+ * Here comes the nsDequeIterator class...
+ ******************************************************/
+
+class nsDequeIterator {
+public:
+ /**
+ * DequeIterator is an object that knows how to iterate
+ * (forward and backward) through a Deque. Normally,
+ * you don't need to do this, but there are some special
+ * cases where it is pretty handy.
+ *
+ * One warning: the iterator is not bound to an item,
+ * it is bound to an index, so if you insert or remove
+ * from the beginning while using an iterator
+ * (which is not recommended) then the iterator will
+ * point to a different item. @see GetCurrent()
+ *
+ * Here you go.
+ *
+ * @param aQueue is the deque object to be iterated
+ * @param aIndex is the starting position for your iteration
+ */
+ nsDequeIterator(const nsDeque& aQueue, int aIndex=0);
+
+ /**
+ * Create a copy of a DequeIterator
+ *
+ * @param aCopy is another iterator to copy from
+ */
+ nsDequeIterator(const nsDequeIterator& aCopy);
+
+ /**
+ * Moves iterator to first element in the deque
+ * @return *this
+ */
+ nsDequeIterator& First();
+
+ /**
+ * Standard assignment operator for dequeiterator
+ * @param aCopy is another iterator to copy from
+ * @return *this
+ */
+ nsDequeIterator& operator=(const nsDequeIterator& aCopy);
+
+ /**
+ * preform ! operation against two iterators to test for equivalence
+ * (or lack thereof)!
+ *
+ * @param aIter is the object to be compared to
+ * @return TRUE if NOT equal.
+ */
+ PRBool operator!=(nsDequeIterator& aIter);
+
+ /**
+ * Compare two iterators for increasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to an element before
+ * the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over
+ * the same deque.
+ */
+ PRBool operator<(nsDequeIterator& aIter);
+
+ /**
+ * Compare two iterators for equivalence.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if EQUAL
+ */
+ PRBool operator==(nsDequeIterator& aIter);
+
+ /**
+ * Compare two iterators for non strict decreasing order.
+ *
+ * @param aIter is the other iterator to be compared to
+ * @return TRUE if this object points to the same element, or
+ * an element after the element pointed to by aIter.
+ * FALSE if this and aIter are not iterating over
+ * the same deque.
+ */
+ PRBool operator>=(nsDequeIterator& aIter);
+
+ /**
+ * Pre-increment operator
+ * Iterator will advance one index towards the end.
+ *
+ * @return object_at(++index)
+ */
+ void* operator++();
+
+ /**
+ * Post-increment operator
+ * Iterator will advance one index towards the end.
+ *
+ * @param param is ignored
+ * @return object_at(mIndex++)
+ */
+ void* operator++(int);
+
+ /**
+ * Pre-decrement operator
+ * Iterator will advance one index towards the beginning.
+ *
+ * @return object_at(--index)
+ */
+ void* operator--();
+
+ /**
+ * Post-decrement operator
+ * Iterator will advance one index towards the beginning.
+ *
+ * @param param is ignored
+ * @return object_at(index--)
+ */
+ void* operator--(int);
+
+ /**
+ * Retrieve the the iterator's notion of current node.
+ *
+ * Note that the iterator floats, so you don't need to do:
+ * <code>++iter; aDeque.PopFront();</code>
+ * Unless you actually want your iterator to jump 2 positions
+ * relative to its origin.
+ *
+ * Picture: [1 2i 3 4]
+ * PopFront()
+ * Picture: [2 3i 4]
+ * Note that I still happily points to object at the second index.
+ *
+ * @return object at i'th index
+ */
+ void* GetCurrent();
+
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, passing a functor along
+ * to call your code.
+ *
+ * @param aFunctor object to call for each member
+ * @return *this
+ */
+ void ForEach(nsDequeFunctor& aFunctor) const;
+
+ /**
+ * Call this method when you want to iterate all the
+ * members of the container, calling the functor you
+ * passed with each member. This process will interrupt
+ * if your function returns non 0 to this method.
+ *
+ * @param aFunctor object to call for each member
+ * @return first nonzero result of aFunctor or 0.
+ */
+ const void* FirstThat(nsDequeFunctor& aFunctor) const;
+
+ protected:
+
+ PRInt32 mIndex;
+ const nsDeque& mDeque;
+};
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h
new file mode 100644
index 00000000..27bf4ce5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsDoubleHashtable.h
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * nsDoubleHashtable.h is OBSOLETE. Use nsTHashtable or a derivative instead.
+ */
+
+#ifndef __nsDoubleHashtable_h__
+#define __nsDoubleHashtable_h__
+
+#include "pldhash.h"
+#include "nscore.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+/*
+ * This file provides several major things to make PLDHashTable easier to use:
+ * - hash class macros for you to define a hashtable
+ * - default key classes to use as superclasses for your entries
+ * - empty maps for string, cstring, int and void
+ */
+
+/*
+ * USAGE
+ *
+ * To use nsDoubleHashtable macros
+ * (1) Define an entry class
+ * (2) Create the hash class
+ * (3) Use the hash class
+ *
+ * EXAMPLE
+ *
+ * As an example, let's create a dictionary, a mapping from a string (the word)
+ * to the pronunciation and definition of those words.
+ *
+ * (1) Define an entry class
+ *
+ * What we want here is an entry class that contains the word, the
+ * pronunciation string, and the definition string. Since we have a string key
+ * we can use the standard PLDHashStringEntry class as our base, it will handle
+ * the key stuff for us automatically.
+ *
+ * #include "nsDoubleHashtable.h"
+ *
+ * // Do NOT ADD VIRTUAL METHODS INTO YOUR ENTRY. Everything will break.
+ * // This is because of the 4-byte pointer C++ magically prepends onto your
+ * // entry class. It interacts very unhappily with PLDHashTable.
+ * class DictionaryEntry : public PLDHashStringEntry {
+ * public:
+ * DictionaryEntry(const void* aKey) : PLDHashStringEntry(aKey) { }
+ * ~DictionaryEntry() { }
+ * nsString mPronunciation;
+ * nsString mDefinition;
+ * }
+ *
+ * (2) Create the hash class
+ *
+ * The final hash class you will use in step 3 is defined by 2 macros.
+ *
+ * DECL_DHASH_WRAPPER(Dictionary, DictionaryEntry, const nsAString&)
+ * DHASH_WRAPPER(Dictionary, DictionaryEntry, const nsAString&)
+ *
+ * (3) Use the hash class
+ *
+ * Here is a simple main() that might look up a string:
+ *
+ * int main(void) {
+ * Dictionary d;
+ * nsresult rv = d.Init(10);
+ * if (NS_FAILED(rv)) return 1;
+ *
+ * // Put an entry
+ * DictionaryEntry* a = d.AddEntry(NS_LITERAL_STRING("doomed"));
+ * if (!a) return 1;
+ * a->mDefinition.AssignLiteral("The state you get in when a Mozilla release is pending");
+ * a->mPronunciation.AssignLiteral("doom-d");
+ *
+ * // Get the entry
+ * DictionaryEntry* b = d.GetEntry(NS_LITERAL_STRING("doomed"));
+ * printf("doomed: %s\n", NS_ConvertUCS2toUTF8(b->mDefinition).get());
+ *
+ * // Entries will be automagically cleaned up when the Dictionary object goes away
+ * return 0;
+ * }
+ *
+ *
+ * BONUS POINTS
+ *
+ * You may wish to extend this class and add helper functions like
+ * nsDependentString* GetDefinition(nsAString& aWord). For example:
+ *
+ * class MyDictionary : public Dictionary {
+ * public:
+ * MyDictionary() { }
+ * // Make SURE you have a virtual destructor
+ * virtual ~myDictionary() { }
+ * nsDependentString* GetDefinition(const nsAString& aWord) {
+ * DictionaryEntry* e = GetEntry(aWord);
+ * if (e) {
+ * // We're returning an nsDependentString here, callers need to delete it
+ * // and it doesn't last long, but at least it doesn't create a copy
+ * return new nsDependentString(e->mDefinition.get());
+ * } else {
+ * return nsnull;
+ * }
+ * }
+ * nsresult PutDefinition(const nsAString& aWord,
+ * const nsAString& aDefinition,
+ * const nsAString& aPronunciation) {
+ * DictionaryEntry* e = AddEntry(aWord);
+ * if (!e) {
+ * return NS_ERROR_OUT_OF_MEMORY;
+ * }
+ * e->mDefinition = aDefinition;
+ * e->mPronunciation = aPronunciation;
+ * return NS_OK;
+ * }
+ * }
+ */
+
+/*
+ * ENTRY CLASS DEFINITION
+ *
+ * The simplifications of PLDHashTable all hinge upon the idea of an entry
+ * class, which is a class you define, where you store the key and values that
+ * you will place in each hash entry. You must define six methods for an entry
+ * (the standard key classes, which you can extend from, define all of these
+ * for you except the constructor and destructor):
+ *
+ * CONSTRUCTOR(const void* aKey)
+ * When your entry is constructed it will only be given a pointer to the key.
+ *
+ * DESTRUCTOR
+ * Called when the entry is destroyed (of course).
+ *
+ * const void* GetKey()
+ * Must return a pointer to the key
+ *
+ * PRBool MatchEntry(const void* aKey) - return true or false depending on
+ * whether the key pointed to by aKey matches this entry
+ *
+ * static PLDHashNumber HashKey(const void* aKey) - get a hashcode based on the
+ * key (must be the same every time for the same key, but does not have
+ * to be unique)
+ *
+ * For a small hash that just does key->value, you will often just extend a
+ * standard key class and put a value member into it, and have a destructor and
+ * constructor--nothing else necessary.
+ *
+ * See the default key entry classes as example entry classes.
+ *
+ * NOTES:
+ * - Do NOT ADD VIRTUAL METHODS INTO YOUR ENTRY. Everything will break.
+ * This is because of the 4-byte pointer C++ magically prepends onto your
+ * entry class. It interacts very unhappily with PLDHashTable.
+ */
+
+/*
+ * PRIVATE HASHTABLE MACROS
+ *
+ * These internal macros can be used to declare the callbacks for an entry
+ * class, but the wrapper class macros call these for you so don't call them.
+ */
+
+//
+// DHASH_CALLBACKS
+//
+// Define the hashtable callback functions. Do this in one place only, as you
+// will have redundant symbols otherwise.
+//
+// ENTRY_CLASS: the classname of the entry
+//
+#define DHASH_CALLBACKS(ENTRY_CLASS) \
+PR_STATIC_CALLBACK(const void *) \
+ENTRY_CLASS##GetKey(PLDHashTable* table, PLDHashEntryHdr* entry) \
+{ \
+ ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS*, entry); \
+ return e->GetKey(); \
+} \
+PR_STATIC_CALLBACK(PLDHashNumber) \
+ENTRY_CLASS##HashKey(PLDHashTable* table, const void* key) \
+{ \
+ return ENTRY_CLASS::HashKey(key); \
+} \
+PR_STATIC_CALLBACK(PRBool) \
+ENTRY_CLASS##MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *entry, \
+ const void *key) \
+{ \
+ const ENTRY_CLASS* e = NS_STATIC_CAST(const ENTRY_CLASS*, entry); \
+ return e->MatchEntry(key); \
+} \
+PR_STATIC_CALLBACK(void) \
+ENTRY_CLASS##ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) \
+{ \
+ ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS *, entry); \
+ e->~ENTRY_CLASS(); \
+} \
+PR_STATIC_CALLBACK(PRBool) \
+ENTRY_CLASS##InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, \
+ const void *key) \
+{ \
+ new (entry) ENTRY_CLASS(key); \
+ return PR_TRUE; \
+}
+
+//
+// DHASH_INIT
+//
+// Initialize hashtable to a certain class.
+//
+// HASHTABLE: the name of the PLDHashTable variable
+// ENTRY_CLASS: the classname of the entry
+// NUM_INITIAL_ENTRIES: the number of entry slots the hashtable should start
+// with
+// RV: an nsresult variable to hold the outcome of the initialization.
+// Will be NS_ERROR_OUT_OF_MEMORY if failed, NS_OK otherwise.
+//
+#define DHASH_INIT(HASHTABLE,ENTRY_CLASS,NUM_INITIAL_ENTRIES,RV) \
+PR_BEGIN_MACRO \
+ static PLDHashTableOps hash_table_ops = \
+ { \
+ PL_DHashAllocTable, \
+ PL_DHashFreeTable, \
+ ENTRY_CLASS##GetKey, \
+ ENTRY_CLASS##HashKey, \
+ ENTRY_CLASS##MatchEntry, \
+ PL_DHashMoveEntryStub, \
+ ENTRY_CLASS##ClearEntry, \
+ PL_DHashFinalizeStub, \
+ ENTRY_CLASS##InitEntry \
+ }; \
+ PRBool isLive = PL_DHashTableInit(&(HASHTABLE), \
+ &hash_table_ops, nsnull, \
+ sizeof(ENTRY_CLASS), \
+ (NUM_INITIAL_ENTRIES)); \
+ if (!isLive) { \
+ (HASHTABLE).ops = nsnull; \
+ RV = NS_ERROR_OUT_OF_MEMORY; \
+ } else { \
+ RV = NS_OK; \
+ } \
+PR_END_MACRO
+
+
+/*
+ * WRAPPER CLASS
+ *
+ * This class handles initialization and destruction of the hashtable
+ * (you must call Init() yourself). It defines these functions:
+ *
+ * Init(aNumInitialEntries)
+ * Initialize the hashtable. This must be called once, it is only separate
+ * from the constructor so that you can get the return value. You should pass
+ * in the number of entries you think the hashtable will typically hold (this
+ * will be the amount of space allocated initially so that it will not have to
+ * grow).
+ *
+ * ENTRY_CLASS* GetEntry(aKey):
+ * Get the entry referenced by aKey and return a pointer to it. THIS IS A
+ * TEMPORARY POINTER and is only guaranteed to exist until the next time you do
+ * an operation on the hashtable. But you can safely use it until then.
+ *
+ * Returns nsnull if the entry is not found.
+ *
+ * ENTRY_CLASS* AddEntry(aKey):
+ * Create a new, empty entry and return a pointer to it for you to fill values
+ * into. THIS IS A TEMPORARY POINTER and is only guaranteed to exist until the
+ * next time you do an operation on the hashtable. But you can safely fill it
+ * in.
+ *
+ * Returns nsnull if the entry cannot be created (usually a low memory
+ * constraint).
+ *
+ * void Remove(aKey)
+ * Remove the entry referenced by aKey. If the entry does not exist, nothing
+ * will happen.
+ *
+ *
+ * DECL_DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)
+ *
+ * Declare the hash class but do not define the functions.
+ *
+ * CLASSNAME: the name of the class to declare.
+ * ENTRY_CLASS: the class of the entry struct.
+ * KEY_TYPE: the name of the key type for GetEntry and AddEntry.
+ *
+ *
+ * DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE)
+ *
+ * Define the functions for the hash class.
+ *
+ * CLASSNAME: the name of the class to declare.
+ * ENTRY_CLASS: the class of the entry struct.
+ * KEY_TYPE: the name of the key type for GetEntry and AddEntry.
+ *
+ *
+ * CAVEATS:
+ * - You may have only *one* wrapper class per entry class.
+ */
+
+#define DECL_DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+class DHASH_EXPORT CLASSNAME { \
+public: \
+ CLASSNAME(); \
+ ~CLASSNAME(); \
+ nsresult Init(PRUint32 aNumInitialEntries); \
+ ENTRY_CLASS* GetEntry(const KEY_TYPE aKey); \
+ ENTRY_CLASS* AddEntry(const KEY_TYPE aKey); \
+ void Remove(const KEY_TYPE aKey); \
+ PLDHashTable mHashTable; \
+};
+
+#define DHASH_WRAPPER(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+DHASH_CALLBACKS(ENTRY_CLASS) \
+CLASSNAME::CLASSNAME() { \
+ mHashTable.ops = nsnull; \
+} \
+CLASSNAME::~CLASSNAME() { \
+ if (mHashTable.ops) { \
+ PL_DHashTableFinish(&mHashTable); \
+ } \
+} \
+nsresult CLASSNAME::Init(PRUint32 aNumInitialEntries) { \
+ if (!mHashTable.ops) { \
+ nsresult rv; \
+ DHASH_INIT(mHashTable,ENTRY_CLASS,aNumInitialEntries,rv); \
+ return rv; \
+ } \
+ return NS_OK; \
+} \
+ENTRY_CLASS* CLASSNAME::GetEntry(const KEY_TYPE aKey) { \
+ ENTRY_CLASS* e = NS_STATIC_CAST(ENTRY_CLASS*, \
+ PL_DHashTableOperate(&mHashTable, &aKey, \
+ PL_DHASH_LOOKUP)); \
+ return PL_DHASH_ENTRY_IS_BUSY(e) ? e : nsnull; \
+} \
+ENTRY_CLASS* CLASSNAME::AddEntry(const KEY_TYPE aKey) { \
+ return NS_STATIC_CAST(ENTRY_CLASS*, \
+ PL_DHashTableOperate(&mHashTable, &aKey, \
+ PL_DHASH_ADD)); \
+} \
+void CLASSNAME::Remove(const KEY_TYPE aKey) { \
+ PL_DHashTableOperate(&mHashTable, &aKey, PL_DHASH_REMOVE); \
+}
+
+/*
+ * STANDARD KEY ENTRY CLASSES
+ *
+ * We have declared some standard key classes for you to make life a little
+ * easier. These include string, int and void* keys. You can extend these
+ * and add value data members to make a working hash entry class with your
+ * values.
+ *
+ * PLDHashStringEntry: nsAString
+ * PLDHashCStringEntry: nsACString
+ * PLDHashInt32Entry: PRInt32
+ * PLDHashVoidEntry: void*
+ *
+ * As a short example, if you want to make a class that maps int to string,
+ * you could do:
+ *
+ * class MyIntStringEntry : public PLDHashInt32Entry
+ * {
+ * public:
+ * MyIntStringEntry(const void* aKey) : PLDHashInt32Entry(aKey) { }
+ * ~MyIntStringEntry() { };
+ * nsString mMyStr;
+ * };
+ *
+ * XXX It could be advisable (unless COW strings ever happens) to have a
+ * PLDHashDependentStringEntry
+ */
+
+//
+// String-key entry
+//
+class NS_COM PLDHashStringEntry : public PLDHashEntryHdr
+{
+public:
+ PLDHashStringEntry(const void* aKey) :
+ mKey(*NS_STATIC_CAST(const nsAString*, aKey)) { }
+ ~PLDHashStringEntry() { }
+
+ const void* GetKey() const {
+ return NS_STATIC_CAST(const nsAString*, &mKey);
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return HashString(*NS_STATIC_CAST(const nsAString*, key));
+ }
+ PRBool MatchEntry(const void* key) const {
+ return NS_STATIC_CAST(const nsAString*, key)->Equals(mKey);
+ }
+
+ const nsString mKey;
+};
+
+//
+// CString-key entry
+//
+class NS_COM PLDHashCStringEntry : public PLDHashEntryHdr
+{
+public:
+ PLDHashCStringEntry(const void* aKey) :
+ mKey(*NS_STATIC_CAST(const nsACString*, aKey)) { }
+ ~PLDHashCStringEntry() { }
+
+ const void* GetKey() const {
+ return NS_STATIC_CAST(const nsACString*, &mKey);
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return HashString(*NS_STATIC_CAST(const nsACString*, key));
+ }
+ PRBool MatchEntry(const void* key) const {
+ return NS_STATIC_CAST(const nsACString*, key)->Equals(mKey);
+ }
+
+ const nsCString mKey;
+};
+
+//
+// Int-key entry
+//
+class NS_COM PLDHashInt32Entry : public PLDHashEntryHdr
+{
+public:
+ PLDHashInt32Entry(const void* aKey) :
+ mKey(*(NS_STATIC_CAST(const PRInt32*, aKey))) { }
+ ~PLDHashInt32Entry() { }
+
+ const void* GetKey() const {
+ return NS_STATIC_CAST(const PRInt32*, &mKey);
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return *NS_STATIC_CAST(const PRInt32*, key);
+ }
+ PRBool MatchEntry(const void* key) const {
+ return *(NS_STATIC_CAST(const PRInt32*, key)) == mKey;
+ }
+
+ const PRInt32 mKey;
+};
+
+
+//
+// Void-key entry
+//
+class NS_COM PLDHashVoidEntry : public PLDHashEntryHdr
+{
+public:
+ PLDHashVoidEntry(const void* aKey) :
+ mKey(*(const void**)aKey) { }
+ ~PLDHashVoidEntry() { }
+
+ const void* GetKey() const {
+ return (const void**)&mKey;
+ }
+ static PLDHashNumber HashKey(const void* key) {
+ return PLDHashNumber(NS_PTR_TO_INT32(*(const void**)key)) >> 2;
+ }
+ PRBool MatchEntry(const void* key) const {
+ return *(const void**)key == mKey;
+ }
+
+ const void* mKey;
+};
+
+
+#define DHASH_EXPORT
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp
new file mode 100644
index 00000000..c00d118c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.cpp
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ An empty enumerator.
+
+ */
+
+#include "nsEmptyEnumerator.h"
+
+////////////////////////////////////////////////////////////////////////
+
+MOZ_DECL_CTOR_COUNTER(EmptyEnumeratorImpl)
+
+EmptyEnumeratorImpl::EmptyEnumeratorImpl(void)
+{
+ MOZ_COUNT_CTOR(EmptyEnumeratorImpl);
+}
+
+EmptyEnumeratorImpl::~EmptyEnumeratorImpl(void)
+{
+ MOZ_COUNT_DTOR(EmptyEnumeratorImpl);
+}
+
+// nsISupports interface
+NS_IMETHODIMP_(nsrefcnt) EmptyEnumeratorImpl::AddRef(void)
+{
+ return 2;
+}
+
+NS_IMETHODIMP_(nsrefcnt) EmptyEnumeratorImpl::Release(void)
+{
+ return 1;
+}
+
+NS_IMPL_QUERY_INTERFACE1(EmptyEnumeratorImpl, nsISimpleEnumerator)
+
+
+// nsISimpleEnumerator interface
+NS_IMETHODIMP EmptyEnumeratorImpl::HasMoreElements(PRBool* aResult)
+{
+ *aResult = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsISupports** aResult)
+{
+ return NS_ERROR_UNEXPECTED;
+}
+
+static EmptyEnumeratorImpl* gEmptyEnumerator = nsnull;
+
+extern "C" NS_COM nsresult
+NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult)
+{
+ nsresult rv = NS_OK;
+ if (!gEmptyEnumerator) {
+ gEmptyEnumerator = new EmptyEnumeratorImpl();
+ if (!gEmptyEnumerator)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aResult = gEmptyEnumerator;
+ return rv;
+}
+
+/* static */ void
+EmptyEnumeratorImpl::Shutdown()
+{
+ delete gEmptyEnumerator;
+ gEmptyEnumerator = nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h
new file mode 100644
index 00000000..4b2feabe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEmptyEnumerator.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ An empty enumerator.
+
+ */
+
+#include "nsIEnumerator.h"
+
+////////////////////////////////////////////////////////////////////////
+
+class EmptyEnumeratorImpl : public nsISimpleEnumerator
+{
+public:
+ EmptyEnumeratorImpl(void);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS_INHERITED // not really inherited, but no mRefCnt
+
+ // nsISimpleEnumerator
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ static void Shutdown();
+
+private:
+ ~EmptyEnumeratorImpl(void);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp
new file mode 100644
index 00000000..e91f68e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsEnumeratorUtils.h"
+
+
+nsArrayEnumerator::nsArrayEnumerator(nsISupportsArray* aValueArray)
+ : mValueArray(aValueArray),
+ mIndex(0)
+{
+ NS_IF_ADDREF(mValueArray);
+}
+
+nsArrayEnumerator::~nsArrayEnumerator(void)
+{
+ NS_IF_RELEASE(mValueArray);
+}
+
+NS_IMPL_ISUPPORTS1(nsArrayEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsArrayEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ *aResult = (mIndex < (PRInt32) cnt);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsArrayEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = nsnull;
+ return NS_OK;
+ }
+
+ PRUint32 cnt;
+ nsresult rv = mValueArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ if (mIndex >= (PRInt32) cnt)
+ return NS_ERROR_UNEXPECTED;
+
+ *aResult = mValueArray->ElementAt(mIndex++);
+ return NS_OK;
+}
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsISupportsArray* array)
+{
+ nsArrayEnumerator* enumer = new nsArrayEnumerator(array);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = enumer;
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue)
+ : mValue(aValue)
+{
+ NS_IF_ADDREF(mValue);
+ mConsumed = (mValue ? PR_FALSE : PR_TRUE);
+}
+
+nsSingletonEnumerator::~nsSingletonEnumerator()
+{
+ NS_IF_RELEASE(mValue);
+}
+
+NS_IMPL_ISUPPORTS1(nsSingletonEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsSingletonEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ *aResult = !mConsumed;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsSingletonEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mConsumed)
+ return NS_ERROR_UNEXPECTED;
+
+ mConsumed = PR_TRUE;
+
+ *aResult = mValue;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+extern "C" NS_COM nsresult
+NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
+ nsISupports* singleton)
+{
+ nsSingletonEnumerator* enumer = new nsSingletonEnumerator(singleton);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = enumer;
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator)
+ : mFirstEnumerator(firstEnumerator),
+ mSecondEnumerator(secondEnumerator),
+ mConsumed(PR_FALSE), mAtSecond(PR_FALSE)
+{
+}
+
+nsUnionEnumerator::~nsUnionEnumerator()
+{
+}
+
+NS_IMPL_ISUPPORTS1(nsUnionEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsUnionEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+
+ if (mConsumed) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ if (! mAtSecond) {
+ rv = mFirstEnumerator->HasMoreElements(aResult);
+ if (NS_FAILED(rv)) return rv;
+
+ if (*aResult)
+ return NS_OK;
+
+ mAtSecond = PR_TRUE;
+ }
+
+ rv = mSecondEnumerator->HasMoreElements(aResult);
+ if (NS_FAILED(rv)) return rv;
+
+ if (*aResult)
+ return NS_OK;
+
+ *aResult = PR_FALSE;
+ mConsumed = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsUnionEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mConsumed)
+ return NS_ERROR_UNEXPECTED;
+
+ if (! mAtSecond)
+ return mFirstEnumerator->GetNext(aResult);
+
+ return mSecondEnumerator->GetNext(aResult);
+}
+
+extern "C" NS_COM nsresult
+NS_NewUnionEnumerator(nsISimpleEnumerator* *result,
+ nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator)
+{
+ *result = nsnull;
+ if (! firstEnumerator) {
+ *result = secondEnumerator;
+ } else if (! secondEnumerator) {
+ *result = firstEnumerator;
+ } else {
+ nsUnionEnumerator* enumer = new nsUnionEnumerator(firstEnumerator, secondEnumerator);
+ if (enumer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = enumer;
+ }
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h
new file mode 100644
index 00000000..2d8182b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsEnumeratorUtils.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsEnumeratorUtils_h__
+#define nsEnumeratorUtils_h__
+
+#include "nsIEnumerator.h"
+#include "nsISupportsArray.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_NewSingletonEnumerator VBoxNsxpNS_NewSingletonEnumerator
+#define NS_NewUnionEnumerator VBoxNsxpNS_NewUnionEnumerator
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+class NS_COM nsArrayEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_IMETHOD HasMoreElements(PRBool* aResult);
+ NS_IMETHOD GetNext(nsISupports** aResult);
+
+ // nsArrayEnumerator methods
+ nsArrayEnumerator(nsISupportsArray* aValueArray);
+
+private:
+ ~nsArrayEnumerator(void);
+
+protected:
+ nsISupportsArray* mValueArray;
+ PRInt32 mIndex;
+};
+
+extern NS_COM nsresult
+NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
+ nsISupportsArray* array);
+
+////////////////////////////////////////////////////////////////////////////////
+
+class NS_COM nsSingletonEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator methods
+ NS_IMETHOD HasMoreElements(PRBool* aResult);
+ NS_IMETHOD GetNext(nsISupports** aResult);
+
+ nsSingletonEnumerator(nsISupports* aValue);
+
+private:
+ ~nsSingletonEnumerator();
+
+protected:
+ nsISupports* mValue;
+ PRBool mConsumed;
+};
+
+extern "C" NS_COM nsresult
+NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
+ nsISupports* singleton);
+
+////////////////////////////////////////////////////////////////////////
+
+class NS_COM nsUnionEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator methods
+ NS_IMETHOD HasMoreElements(PRBool* aResult);
+ NS_IMETHOD GetNext(nsISupports** aResult);
+
+ nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator);
+
+private:
+ ~nsUnionEnumerator();
+
+protected:
+ nsCOMPtr<nsISimpleEnumerator> mFirstEnumerator, mSecondEnumerator;
+ PRBool mConsumed;
+ PRBool mAtSecond;
+};
+
+extern "C" NS_COM nsresult
+NS_NewUnionEnumerator(nsISimpleEnumerator* *result,
+ nsISimpleEnumerator* firstEnumerator,
+ nsISimpleEnumerator* secondEnumerator);
+
+////////////////////////////////////////////////////////////////////////
+
+#endif /* nsEnumeratorUtils_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp
new file mode 100644
index 00000000..1b6232f9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Waterson <waterson@netscape.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ Implementation for nsFixedSizeAllocator
+
+*/
+
+#include "nsCRT.h"
+#include "nsFixedSizeAllocator.h"
+
+nsFixedSizeAllocator::Bucket *
+nsFixedSizeAllocator::AddBucket(size_t aSize)
+{
+ void* p;
+ PL_ARENA_ALLOCATE(p, &mPool, sizeof(Bucket));
+ if (! p)
+ return nsnull;
+
+ Bucket* bucket = NS_STATIC_CAST(Bucket*, p);
+ bucket->mSize = aSize;
+ bucket->mFirst = nsnull;
+ bucket->mNext = mBuckets;
+
+ mBuckets = bucket;
+ return bucket;
+}
+
+nsresult
+nsFixedSizeAllocator::Init(const char* aName,
+ const size_t* aBucketSizes,
+ PRInt32 aNumBuckets,
+ PRInt32 aInitialSize,
+ PRInt32 aAlign)
+{
+ NS_PRECONDITION(aNumBuckets > 0, "no buckets");
+ if (aNumBuckets <= 0)
+ return NS_ERROR_INVALID_ARG;
+
+ // Blow away the old pool if we're being re-initialized.
+ if (mBuckets)
+ PL_FinishArenaPool(&mPool);
+
+ PRInt32 bucketspace = aNumBuckets * sizeof(Bucket);
+ PL_InitArenaPool(&mPool, aName, bucketspace + aInitialSize, aAlign);
+
+ mBuckets = nsnull;
+ for (PRInt32 i = 0; i < aNumBuckets; ++i)
+ AddBucket(aBucketSizes[i]);
+
+ return NS_OK;
+}
+
+nsFixedSizeAllocator::Bucket *
+nsFixedSizeAllocator::FindBucket(size_t aSize)
+{
+ Bucket** link = &mBuckets;
+ Bucket* bucket;
+
+ while ((bucket = *link) != nsnull) {
+ if (aSize == bucket->mSize) {
+ // Promote to the head of the list, under the assumption
+ // that we'll allocate same-sized object contemporaneously.
+ *link = bucket->mNext;
+ bucket->mNext = mBuckets;
+ mBuckets = bucket;
+ return bucket;
+ }
+
+ link = &bucket->mNext;
+ }
+ return nsnull;
+}
+
+void*
+nsFixedSizeAllocator::Alloc(size_t aSize)
+{
+ Bucket* bucket = FindBucket(aSize);
+ if (! bucket) {
+ // Oops, we don't carry that size. Let's fix that.
+ bucket = AddBucket(aSize);
+ if (! bucket)
+ return nsnull;
+ }
+
+ void* next;
+ if (bucket->mFirst) {
+ next = bucket->mFirst;
+ bucket->mFirst = bucket->mFirst->mNext;
+ }
+ else {
+ PL_ARENA_ALLOCATE(next, &mPool, aSize);
+ if (!next)
+ return nsnull;
+ }
+
+#ifdef DEBUG
+ memset(next, 0xc8, aSize);
+#endif
+
+ return next;
+}
+
+void
+nsFixedSizeAllocator::Free(void* aPtr, size_t aSize)
+{
+ FreeEntry* entry = NS_REINTERPRET_CAST(FreeEntry*, aPtr);
+ Bucket* bucket = FindBucket(aSize);
+
+#ifdef DEBUG
+ NS_ASSERTION(bucket && bucket->mSize == aSize, "ack! corruption! bucket->mSize != aSize!");
+ memset(aPtr, 0xd8, bucket->mSize);
+#endif
+
+ entry->mNext = bucket->mFirst;
+ bucket->mFirst = entry;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h
new file mode 100644
index 00000000..16708cdc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Waterson <waterson@netscape.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ A simple fixed-size allocator that allocates its memory from an
+ arena.
+
+ Although the allocator can handle blocks of any size, its
+ preformance will degrade rapidly if used to allocate blocks of
+ arbitrary size. Ideally, it should be used to allocate and recycle a
+ large number of fixed-size blocks.
+
+ Here is a typical usage pattern:
+
+ #include NEW_H // You'll need this!
+ #include "nsFixedSizeAllocator.h"
+
+ // Say this is the object you want to allocate a ton of
+ class Foo {
+ public:
+ // Implement placement new & delete operators that will
+ // use the fixed size allocator.
+ static Foo *
+ Create(nsFixedSizeAllocator &aAllocator)
+ {
+ void *place = aAllocator.Alloc(sizeof(Foo));
+ return place ? ::new (place) Foo() : nsnull;
+ }
+
+ static void
+ Destroy(nsFixedSizeAllocator &aAllocator, Foo *aFoo)
+ {
+ aFoo->~Foo();
+ aAllocator.Free(aFoo, sizeof(Foo));
+ }
+
+ // ctor & dtor
+ Foo() {}
+ ~Foo() {}
+ };
+
+
+ int main(int argc, char* argv[])
+ {
+ // Somewhere in your code, you'll need to create an
+ // nsFixedSizeAllocator object and initialize it:
+ nsFixedSizeAllocator pool;
+
+ // The fixed size allocator will support multiple fixed sizes.
+ // This array lists an initial set of sizes that the allocator
+ // should be prepared to support. In our case, there's just one,
+ // which is Foo.
+ static const size_t kBucketSizes[]
+ = { sizeof(Foo) }
+
+ // This is the number of different "buckets" you'll need for
+ // fixed size objects. In our example, this will be "1".
+ static const PRInt32 kNumBuckets
+ = sizeof(kBucketSizes) / sizeof(size_t);
+
+ // This is the intial size of the allocator, in bytes. We'll
+ // assume that we want to start with space for 1024 Foo objects.
+ static const PRInt32 kInitialPoolSize =
+ NS_SIZE_IN_HEAP(sizeof(Foo)) * 1024;
+
+ // Initialize (or re-initialize) the pool
+ pool.Init("TheFooPool", kBucketSizes, kNumBuckets, kInitialPoolSize);
+
+ // Now we can use the pool.
+
+ // Create a new Foo object using the pool:
+ Foo* foo = Foo::Create(pool);
+ if (! foo) {
+ // uh oh, out of memory!
+ }
+
+ // Delete the object. The memory used by `foo' is recycled in
+ // the pool, and placed in a freelist
+ Foo::Destroy(foo);
+
+ // Create another foo: this one will be allocated from the
+ // free-list
+ foo = Foo::Create(pool);
+
+ // When pool is destroyed, all of its memory is automatically
+ // freed. N.B. it will *not* call your objects' destructors! In
+ // this case, foo's ~Foo() method would never be called.
+ }
+
+*/
+
+#ifndef nsFixedSizeAllocator_h__
+#define nsFixedSizeAllocator_h__
+
+#include "nscore.h"
+#include "nsError.h"
+#include "plarena.h"
+
+#define NS_SIZE_IN_HEAP(_size) (_size)
+
+class NS_COM nsFixedSizeAllocator
+{
+protected:
+ PLArenaPool mPool;
+
+ struct Bucket;
+ struct FreeEntry;
+
+ friend struct Bucket;
+ friend struct FreeEntry;
+
+ struct FreeEntry {
+ FreeEntry* mNext;
+ };
+
+ struct Bucket {
+ size_t mSize;
+ FreeEntry* mFirst;
+ Bucket* mNext;
+ };
+
+ Bucket* mBuckets;
+
+ Bucket *
+ AddBucket(size_t aSize);
+
+ Bucket *
+ FindBucket(size_t aSize);
+
+public:
+ nsFixedSizeAllocator() : mBuckets(nsnull) {}
+
+ ~nsFixedSizeAllocator() {
+ if (mBuckets)
+ PL_FinishArenaPool(&mPool);
+ }
+
+ /**
+ * Initialize the fixed size allocator. 'aName' is used to tag
+ * the underlying PLArena object for debugging and measurement
+ * purposes. 'aNumBuckets' specifies the number of elements in
+ * 'aBucketSizes', which is an array of integral block sizes
+ * that this allocator should be prepared to handle.
+ */
+ nsresult
+ Init(const char* aName,
+ const size_t* aBucketSizes,
+ PRInt32 aNumBuckets,
+ PRInt32 aInitialSize,
+ PRInt32 aAlign = 0);
+
+ /**
+ * Allocate a block of memory 'aSize' bytes big.
+ */
+ void* Alloc(size_t aSize);
+
+ /**
+ * Free a pointer allocated using a fixed-size allocator
+ */
+ void Free(void* aPtr, size_t aSize);
+};
+
+
+
+#endif // nsFixedSizeAllocator_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h b/src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h
new file mode 100644
index 00000000..8a6d272e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashKeys.h
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTHashKeys_h__
+#define nsTHashKeys_h__
+
+#include "nsAString.h"
+#include "nsString.h"
+#include "nsID.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+#include "nsISupports.h"
+#include "nsCOMPtr.h"
+#include "pldhash.h"
+#include NEW_H
+
+/** @file nsHashKeys.h
+ * standard HashKey classes for nsBaseHashtable and relatives. Each of these
+ * classes follows the nsTHashtable::EntryType specification
+ *
+ * Lightweight keytypes provided here:
+ * nsStringHashKey
+ * nsCStringHashKey
+ * nsUint32HashKey
+ * nsISupportsHashKey
+ * nsIDHashKey
+ * nsDepCharHashKey
+ */
+
+/**
+ * hashkey wrapper using nsAString KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsStringHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsAString& KeyType;
+ typedef const nsAString* KeyTypePointer;
+
+ nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) { }
+ nsStringHashKey(const nsStringHashKey& toCopy) : mStr(toCopy.mStr) { }
+ ~nsStringHashKey() { }
+
+ KeyType GetKey() const { return mStr; }
+ KeyTypePointer GetKeyPointer() const { return &mStr; }
+ PRBool KeyEquals(const KeyTypePointer aKey) const
+ {
+ return mStr.Equals(*aKey);
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(const KeyTypePointer aKey)
+ {
+ return HashString(*aKey);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsString mStr;
+};
+
+/**
+ * hashkey wrapper using nsACString KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsCStringHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsACString& KeyType;
+ typedef const nsACString* KeyTypePointer;
+
+ nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) { }
+ nsCStringHashKey(const nsCStringHashKey& toCopy) : mStr(toCopy.mStr) { }
+ ~nsCStringHashKey() { }
+
+ KeyType GetKey() const { return mStr; }
+ KeyTypePointer GetKeyPointer() const { return &mStr; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey)
+ {
+ return HashString(*aKey);
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsCString mStr;
+};
+
+/**
+ * hashkey wrapper using PRUint32 KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsUint32HashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const PRUint32& KeyType;
+ typedef const PRUint32* KeyTypePointer;
+
+ nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
+ nsUint32HashKey(const nsUint32HashKey& toCopy) : mValue(toCopy.mValue) { }
+ ~nsUint32HashKey() { }
+
+ KeyType GetKey() const { return mValue; }
+ KeyTypePointer GetKeyPointer() const { return &mValue; }
+ PRBool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const PRUint32 mValue;
+};
+
+/**
+ * hashkey wrapper using nsISupports* KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsISupportsHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef nsISupports* KeyType;
+ typedef const nsISupports* KeyTypePointer;
+
+ nsISupportsHashKey(const nsISupports* key) :
+ mSupports(NS_CONST_CAST(nsISupports*,key)) { }
+ nsISupportsHashKey(const nsISupportsHashKey& toCopy) :
+ mSupports(toCopy.mSupports) { }
+ ~nsISupportsHashKey() { }
+
+ KeyType GetKey() const { return mSupports; }
+ KeyTypePointer GetKeyPointer() const { return mSupports; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return aKey == mSupports; }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey)
+ {
+ return NS_PTR_TO_INT32(aKey) >>2;
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ nsCOMPtr<nsISupports> mSupports;
+};
+
+/**
+ * hashkey wrapper using void* KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsVoidPtrHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const void* KeyType;
+ typedef const void* KeyTypePointer;
+
+ nsVoidPtrHashKey(const void* key) :
+ mKey(key) { }
+ nsVoidPtrHashKey(const nsVoidPtrHashKey& toCopy) :
+ mKey(toCopy.mKey) { }
+ ~nsVoidPtrHashKey() { }
+
+ KeyType GetKey() const { return mKey; }
+ KeyTypePointer GetKeyPointer() const { return mKey; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey)
+ {
+ return NS_PTR_TO_INT32(aKey) >>2;
+ }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const void* mKey;
+};
+
+/**
+ * hashkey wrapper using nsID KeyType
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsIDHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const nsID& KeyType;
+ typedef const nsID* KeyTypePointer;
+
+ nsIDHashKey(const nsID* id) : mID(*id) { }
+ nsIDHashKey(const nsIDHashKey& toCopy) : mID(toCopy.mID) { }
+ ~nsIDHashKey() { }
+
+ KeyType GetKey() const { return mID; }
+ KeyTypePointer GetKeyPointer() const { return &mID; }
+
+ PRBool KeyEquals(KeyTypePointer aKey) const { return aKey->Equals(mID); }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey);
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const nsID mID;
+};
+
+/**
+ * hashkey wrapper for "dependent" const char*; this class does not "own"
+ * its string pointer.
+ *
+ * This class must only be used if the strings have a lifetime longer than
+ * the hashtable they occupy. This normally occurs only for static
+ * strings or strings that have been arena-allocated.
+ *
+ * @see nsTHashtable::EntryType for specification
+ */
+class NS_COM nsDepCharHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const char* KeyType;
+ typedef const char* KeyTypePointer;
+
+ nsDepCharHashKey(const char* aKey) { mKey = aKey; }
+ nsDepCharHashKey(const nsDepCharHashKey& toCopy) { mKey = toCopy.mKey; }
+ ~nsDepCharHashKey() { }
+
+ const char* GetKey() const { return mKey; }
+ const char* GetKeyPointer() const { return mKey; }
+ PRBool KeyEquals(const char* aKey) const
+ {
+ return !strcmp(mKey, aKey);
+ }
+
+ static const char* KeyToPointer(const char* aKey) { return aKey; }
+ static PLDHashNumber HashKey(const char* aKey) { return nsCRT::HashCode(aKey); }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const char* mKey;
+};
+
+/**
+ * hashkey wrapper for const char*; at construction, this class duplicates
+ * a string pointed to by the pointer so that it doesn't matter whether or not
+ * the string lives longer than the hash table.
+ */
+class NS_COM nsCharPtrHashKey : public PLDHashEntryHdr
+{
+public:
+ typedef const char* KeyType;
+ typedef const char* KeyTypePointer;
+
+ nsCharPtrHashKey(const char* aKey) : mKey(strdup(aKey)) { }
+ nsCharPtrHashKey(const nsCharPtrHashKey& toCopy) : mKey(strdup(toCopy.mKey)) { }
+ ~nsCharPtrHashKey() { if (mKey) free(NS_CONST_CAST(char *, mKey)); }
+
+ const char* GetKey() const { return mKey; }
+ const char* GetKeyPointer() const { return mKey; }
+ PRBool KeyEquals(KeyTypePointer aKey) const
+ {
+ return !strcmp(mKey, aKey);
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
+ static PLDHashNumber HashKey(KeyTypePointer aKey) { return nsCRT::HashCode(aKey); }
+
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+private:
+ const char* mKey;
+};
+
+#endif // nsTHashKeys_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp
new file mode 100644
index 00000000..3f11ba55
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.cpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nscore.h"
+#include NEW_H
+
+#include "nsHashSets.h"
+
+DHASH_SET(nsStringHashSet, PLDHashStringEntry, nsAString&)
+DHASH_SET(nsCStringHashSet,PLDHashCStringEntry,nsACString&)
+DHASH_SET(nsInt32HashSet, PLDHashInt32Entry, PRInt32)
+DHASH_SET(nsVoidHashSet, PLDHashVoidEntry, void*)
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashSets.h b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.h
new file mode 100644
index 00000000..627a6a06
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashSets.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsHashSets_h__
+#define __nsHashSets_h__
+
+#include "nsDoubleHashtable.h"
+
+/*
+ * HASH SETS
+ *
+ * These hash classes describe hashtables that contain keys without values.
+ * This is useful when you want to store things and then just test for their
+ * existence later. We have defined standard ones for string, int and void.
+ *
+ * nsStringHashSet: nsAString&
+ * nsCStringHashSet: nsACString&
+ * nsInt32HashSet: PRInt32
+ * nsVoidHashSet: void*
+ *
+ * USAGE:
+ * Put(): put a thing of the given type into the set
+ * Contains(): whether it contains a thing of the given type
+ * To use, you just do: (for example)
+ *
+ * #include "nsDoubleHashtable.h"
+ * nsInt32HashSet mySet;
+ * mySet.Init(1);
+ * mySet.Put(5);
+ * if (mySet.Contains(5)) {
+ * printf("yay\n");
+ * }
+ *
+ * There is a nice convenient macro for declaring empty map classes:
+ * DECL_DHASH_SET(CLASSNAME, ENTRY_CLASS, KEY_TYPE)
+ * - CLASSNAME: the name of the class
+ * - ENTRY_CLASS: the name of the entry class with the key in it
+ * - KEY_TYPE: the type of key for Put() and Contains()
+ *
+ * DHASH_SET(CLASSNAME, ENTRY_CLASS, KEY_TYPE) is the companion macro
+ * you must put in the .cpp (implementation) code.
+ */
+
+#define DECL_DHASH_SET(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+DECL_DHASH_WRAPPER(CLASSNAME##Super,ENTRY_CLASS,KEY_TYPE) \
+class DHASH_EXPORT CLASSNAME : public CLASSNAME##Super { \
+public: \
+ CLASSNAME() : CLASSNAME##Super() { } \
+ ~CLASSNAME() { } \
+ nsresult Put(const KEY_TYPE aKey) { \
+ return AddEntry(aKey) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; \
+ } \
+ PRBool Contains(const KEY_TYPE aKey) { \
+ return GetEntry(aKey) ? PR_TRUE : PR_FALSE; \
+ } \
+};
+
+#define DHASH_SET(CLASSNAME,ENTRY_CLASS,KEY_TYPE) \
+DHASH_WRAPPER(CLASSNAME##Super,ENTRY_CLASS,KEY_TYPE)
+
+#undef DHASH_EXPORT
+#define DHASH_EXPORT NS_COM
+
+DECL_DHASH_SET(nsStringHashSet, PLDHashStringEntry, nsAString&)
+DECL_DHASH_SET(nsCStringHashSet,PLDHashCStringEntry,nsACString&)
+DECL_DHASH_SET(nsInt32HashSet, PLDHashInt32Entry, PRInt32)
+DECL_DHASH_SET(nsVoidHashSet, PLDHashVoidEntry, void*)
+
+#undef DHASH_EXPORT
+#define DHASH_EXPORT
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp
new file mode 100644
index 00000000..ce74fb28
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.cpp
@@ -0,0 +1,896 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+#include <string.h>
+#include "prmem.h"
+#include "prlog.h"
+#include "nsHashtable.h"
+#include "nsReadableUtils.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+#include "nsCRT.h"
+
+struct HTEntry : PLDHashEntryHdr
+{
+ nsHashKey* key;
+ void* value;
+};
+
+//
+// Key operations
+//
+
+PR_STATIC_CALLBACK(PRBool)
+matchKeyEntry(PLDHashTable*, const PLDHashEntryHdr* entry,
+ const void* key)
+{
+ const HTEntry* hashEntry =
+ NS_STATIC_CAST(const HTEntry*, entry);
+
+ if (hashEntry->key == key)
+ return PR_TRUE;
+
+ const nsHashKey* otherKey = NS_REINTERPRET_CAST(const nsHashKey*, key);
+ return otherKey->Equals(hashEntry->key);
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+hashKey(PLDHashTable* table, const void* key)
+{
+ const nsHashKey* hashKey = NS_STATIC_CAST(const nsHashKey*, key);
+
+ return hashKey->HashCode();
+}
+
+PR_STATIC_CALLBACK(void)
+clearHashEntry(PLDHashTable* table, PLDHashEntryHdr* entry)
+{
+ HTEntry* hashEntry = NS_STATIC_CAST(HTEntry*, entry);
+
+ // leave it up to the nsHashKey destructor to free the "value"
+ delete hashEntry->key;
+ hashEntry->key = nsnull;
+ hashEntry->value = nsnull; // probably not necessary, but for
+ // sanity's sake
+}
+
+
+static const PLDHashTableOps hashtableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ hashKey,
+ matchKeyEntry,
+ PL_DHashMoveEntryStub,
+ clearHashEntry,
+ PL_DHashFinalizeStub,
+ nsnull,
+};
+
+
+//
+// Enumerator callback
+//
+
+struct _HashEnumerateArgs {
+ nsHashtableEnumFunc fn;
+ void* arg;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+hashEnumerate(PLDHashTable* table, PLDHashEntryHdr* hdr, PRUint32 i, void *arg)
+{
+ _HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
+ HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ switch (thunk->fn(entry->key, entry->value, thunk->arg)) {
+ case kHashEnumerateNext:
+ return PL_DHASH_NEXT;
+ case kHashEnumerateRemove:
+ return PL_DHASH_REMOVE;
+ }
+ return PL_DHASH_STOP;
+}
+
+//
+// HashKey
+//
+
+nsHashKey::~nsHashKey(void)
+{
+ MOZ_COUNT_DTOR(nsHashKey);
+}
+
+nsresult
+nsHashKey::Write(nsIObjectOutputStream* aStream) const
+{
+ NS_NOTREACHED("oops");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+MOZ_DECL_CTOR_COUNTER(nsHashtable)
+
+nsHashtable::nsHashtable(PRUint32 aInitSize, PRBool threadSafe)
+ : mLock(NULL), mEnumerating(PR_FALSE)
+{
+ MOZ_COUNT_CTOR(nsHashtable);
+
+ PRBool result = PL_DHashTableInit(&mHashtable, &hashtableOps, nsnull,
+ sizeof(HTEntry), aInitSize);
+
+ NS_ASSERTION(result, "Hashtable failed to initialize");
+
+ // make sure we detect this later
+ if (!result)
+ mHashtable.ops = nsnull;
+
+ if (threadSafe) {
+ mLock = PR_NewLock();
+ if (mLock == NULL) {
+ // Cannot create a lock. If running on a multiprocessing system
+ // we are sure to die.
+ PR_ASSERT(mLock != NULL);
+ }
+ }
+}
+
+
+nsHashtable::~nsHashtable() {
+ MOZ_COUNT_DTOR(nsHashtable);
+ if (mHashtable.ops)
+ PL_DHashTableFinish(&mHashtable);
+ if (mLock) PR_DestroyLock(mLock);
+}
+
+PRBool nsHashtable::Exists(nsHashKey *aKey)
+{
+ if (mLock) PR_Lock(mLock);
+
+ if (!mHashtable.ops)
+ return PR_FALSE;
+
+ PLDHashEntryHdr *entry =
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP);
+
+ PRBool exists = PL_DHASH_ENTRY_IS_BUSY(entry);
+
+ if (mLock) PR_Unlock(mLock);
+
+ return exists;
+}
+
+void *nsHashtable::Put(nsHashKey *aKey, void *aData)
+{
+ void *res = NULL;
+
+ if (!mHashtable.ops) return nsnull;
+
+ if (mLock) PR_Lock(mLock);
+
+ // shouldn't be adding an item during enumeration
+ PR_ASSERT(!mEnumerating);
+
+ HTEntry* entry =
+ NS_STATIC_CAST(HTEntry*,
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_ADD));
+
+ if (entry) { // don't return early, or you'll be locked!
+ if (entry->key) {
+ // existing entry, need to boot the old value
+ res = entry->value;
+ entry->value = aData;
+ } else {
+ // new entry (leave res == null)
+ entry->key = aKey->Clone();
+ entry->value = aData;
+ }
+ }
+
+ if (mLock) PR_Unlock(mLock);
+
+ return res;
+}
+
+void *nsHashtable::Get(nsHashKey *aKey)
+{
+ if (!mHashtable.ops) return nsnull;
+
+ if (mLock) PR_Lock(mLock);
+
+ HTEntry* entry =
+ NS_STATIC_CAST(HTEntry*,
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP));
+ void *ret = PL_DHASH_ENTRY_IS_BUSY(entry) ? entry->value : nsnull;
+
+ if (mLock) PR_Unlock(mLock);
+
+ return ret;
+}
+
+void *nsHashtable::Remove(nsHashKey *aKey)
+{
+ if (!mHashtable.ops) return nsnull;
+
+ if (mLock) PR_Lock(mLock);
+
+ // shouldn't be adding an item during enumeration
+ PR_ASSERT(!mEnumerating);
+
+
+ // need to see if the entry is actually there, in order to get the
+ // old value for the result
+ HTEntry* entry =
+ NS_STATIC_CAST(HTEntry*,
+ PL_DHashTableOperate(&mHashtable, aKey, PL_DHASH_LOOKUP));
+ void *res;
+
+ if (PL_DHASH_ENTRY_IS_FREE(entry)) {
+ // value wasn't in the table anyway
+ res = nsnull;
+ } else {
+ res = entry->value;
+ PL_DHashTableRawRemove(&mHashtable, entry);
+ }
+
+ if (mLock) PR_Unlock(mLock);
+
+ return res;
+}
+
+// XXX This method was called _hashEnumerateCopy, but it didn't copy the element!
+// I don't know how this was supposed to work since the elements are neither copied
+// nor refcounted.
+PR_STATIC_CALLBACK(PLDHashOperator)
+hashEnumerateShare(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 i, void *arg)
+{
+ nsHashtable *newHashtable = (nsHashtable *)arg;
+ HTEntry * entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ newHashtable->Put(entry->key, entry->value);
+ return PL_DHASH_NEXT;
+}
+
+nsHashtable * nsHashtable::Clone()
+{
+ if (!mHashtable.ops) return nsnull;
+
+ PRBool threadSafe = (mLock != nsnull);
+ nsHashtable *newHashTable = new nsHashtable(mHashtable.entryCount, threadSafe);
+
+ PL_DHashTableEnumerate(&mHashtable, hashEnumerateShare, newHashTable);
+ return newHashTable;
+}
+
+void nsHashtable::Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure)
+{
+ if (!mHashtable.ops) return;
+
+ PRBool wasEnumerating = mEnumerating;
+ mEnumerating = PR_TRUE;
+ _HashEnumerateArgs thunk;
+ thunk.fn = aEnumFunc;
+ thunk.arg = aClosure;
+ PL_DHashTableEnumerate(&mHashtable, hashEnumerate, &thunk);
+ mEnumerating = wasEnumerating;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+hashEnumerateRemove(PLDHashTable*, PLDHashEntryHdr* hdr, PRUint32 i, void *arg)
+{
+ HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
+ _HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
+ if (thunk) {
+ return thunk->fn(entry->key, entry->value, thunk->arg)
+ ? PL_DHASH_REMOVE
+ : PL_DHASH_STOP;
+ }
+ return PL_DHASH_REMOVE;
+}
+
+void nsHashtable::Reset() {
+ Reset(NULL);
+}
+
+void nsHashtable::Reset(nsHashtableEnumFunc destroyFunc, void* aClosure)
+{
+ if (!mHashtable.ops) return;
+
+ _HashEnumerateArgs thunk, *thunkp;
+ if (!destroyFunc) {
+ thunkp = nsnull;
+ } else {
+ thunkp = &thunk;
+ thunk.fn = destroyFunc;
+ thunk.arg = aClosure;
+ }
+ PL_DHashTableEnumerate(&mHashtable, hashEnumerateRemove, thunkp);
+}
+
+// nsISerializable helpers
+
+nsHashtable::nsHashtable(nsIObjectInputStream* aStream,
+ nsHashtableReadEntryFunc aReadEntryFunc,
+ nsHashtableFreeEntryFunc aFreeEntryFunc,
+ nsresult *aRetVal)
+ : mLock(nsnull),
+ mEnumerating(PR_FALSE)
+{
+ MOZ_COUNT_CTOR(nsHashtable);
+
+ PRBool threadSafe;
+ nsresult rv = aStream->ReadBoolean(&threadSafe);
+ if (NS_SUCCEEDED(rv)) {
+ if (threadSafe) {
+ mLock = PR_NewLock();
+ if (!mLock)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ PRUint32 count;
+ rv = aStream->Read32(&count);
+
+ if (NS_SUCCEEDED(rv)) {
+ PRBool status =
+ PL_DHashTableInit(&mHashtable, &hashtableOps,
+ nsnull, sizeof(HTEntry), count);
+ if (!status) {
+ mHashtable.ops = nsnull;
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ for (PRUint32 i = 0; i < count; i++) {
+ nsHashKey* key;
+ void *data;
+
+ rv = aReadEntryFunc(aStream, &key, &data);
+ if (NS_SUCCEEDED(rv)) {
+ if (!Put(key, data)) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ aFreeEntryFunc(aStream, key, data);
+ } else {
+ // XXXbe must we clone key? can't we hand off
+ aFreeEntryFunc(aStream, key, nsnull);
+ }
+ if (NS_FAILED(rv))
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ *aRetVal = rv;
+}
+
+struct WriteEntryArgs {
+ nsIObjectOutputStream* mStream;
+ nsHashtableWriteDataFunc mWriteDataFunc;
+ nsresult mRetVal;
+};
+
+PR_STATIC_CALLBACK(PRBool)
+WriteEntry(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ WriteEntryArgs* args = (WriteEntryArgs*) aClosure;
+ nsIObjectOutputStream* stream = args->mStream;
+
+ nsresult rv = aKey->Write(stream);
+ if (NS_SUCCEEDED(rv))
+ rv = args->mWriteDataFunc(stream, aData);
+
+ args->mRetVal = rv;
+ return PR_TRUE;
+}
+
+nsresult
+nsHashtable::Write(nsIObjectOutputStream* aStream,
+ nsHashtableWriteDataFunc aWriteDataFunc) const
+{
+ if (!mHashtable.ops)
+ return NS_ERROR_OUT_OF_MEMORY;
+ PRBool threadSafe = (mLock != nsnull);
+ nsresult rv = aStream->WriteBoolean(threadSafe);
+ if (NS_FAILED(rv)) return rv;
+
+ // Write the entry count first, so we know how many key/value pairs to read.
+ PRUint32 count = mHashtable.entryCount;
+ rv = aStream->Write32(count);
+ if (NS_FAILED(rv)) return rv;
+
+ // Write all key/value pairs in the table.
+ WriteEntryArgs args = {aStream, aWriteDataFunc};
+ NS_CONST_CAST(nsHashtable*, this)->Enumerate(WriteEntry, (void*) &args);
+ return args.mRetVal;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsISupportsKey::nsISupportsKey(nsIObjectInputStream* aStream, nsresult *aResult)
+ : mKey(nsnull)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->ReadObject(PR_TRUE, &mKey);
+ *aResult = rv;
+}
+
+nsresult
+nsISupportsKey::Write(nsIObjectOutputStream* aStream) const
+{
+ PRBool nonnull = (mKey != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteObject(mKey, PR_TRUE);
+ return rv;
+}
+
+nsIDKey::nsIDKey(nsIObjectInputStream* aStream, nsresult *aResult)
+{
+ *aResult = aStream->ReadID(&mID);
+}
+
+nsresult nsIDKey::Write(nsIObjectOutputStream* aStream) const
+{
+ return aStream->WriteID(mID);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Copy Constructor
+// We need to free mStr if the object is passed with mOwnership as OWN. As the
+// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
+
+nsCStringKey::nsCStringKey(const nsCStringKey& aKey)
+ : mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
+{
+ if (mOwnership != NEVER_OWN) {
+ PRUint32 len = mStrLen * sizeof(char);
+ char* str = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(len + sizeof(char)));
+ if (!str) {
+ // Pray we don't dangle!
+ mOwnership = NEVER_OWN;
+ } else {
+ // Use memcpy in case there are embedded NULs.
+ memcpy(str, mStr, len);
+ str[mStrLen] = '\0';
+ mStr = str;
+ mOwnership = OWN;
+ }
+ }
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::nsCStringKey(const nsAFlatCString& str)
+ : mStr(NS_CONST_CAST(char*, str.get())),
+ mStrLen(str.Length()),
+ mOwnership(OWN_CLONE)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::nsCStringKey(const nsACString& str)
+ : mStr(ToNewCString(str)),
+ mStrLen(str.Length()),
+ mOwnership(OWN)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::nsCStringKey(const char* str, PRInt32 strLen, Ownership own)
+ : mStr((char*)str), mStrLen(strLen), mOwnership(own)
+{
+ NS_ASSERTION(mStr, "null string key");
+ if (mStrLen == PRUint32(-1))
+ mStrLen = strlen(str);
+#ifdef DEBUG
+ mKeyType = CStringKey;
+#endif
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsCStringKey::~nsCStringKey(void)
+{
+ if (mOwnership == OWN)
+ nsMemory::Free(mStr);
+ MOZ_COUNT_DTOR(nsCStringKey);
+}
+
+PRUint32
+nsCStringKey::HashCode(void) const
+{
+ return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
+}
+
+PRBool
+nsCStringKey::Equals(const nsHashKey* aKey) const
+{
+ NS_ASSERTION(aKey->GetKeyType() == CStringKey, "mismatched key types");
+ nsCStringKey* other = (nsCStringKey*)aKey;
+ NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
+ NS_ASSERTION(other->mStrLen != PRUint32(-1), "never called HashCode");
+ if (mStrLen != other->mStrLen)
+ return PR_FALSE;
+ return memcmp(mStr, other->mStr, mStrLen * sizeof(char)) == 0;
+}
+
+nsHashKey*
+nsCStringKey::Clone() const
+{
+ if (mOwnership == NEVER_OWN)
+ return new nsCStringKey(mStr, mStrLen, NEVER_OWN);
+
+ // Since this might hold binary data OR a string, we ensure that the
+ // clone string is zero terminated, but don't assume that the source
+ // string was so terminated.
+
+ PRUint32 len = mStrLen * sizeof(char);
+ char* str = (char*)nsMemory::Alloc(len + sizeof(char));
+ if (str == NULL)
+ return NULL;
+ memcpy(str, mStr, len);
+ str[len] = 0;
+ return new nsCStringKey(str, mStrLen, OWN);
+}
+
+nsCStringKey::nsCStringKey(nsIObjectInputStream* aStream, nsresult *aResult)
+ : mStr(nsnull), mStrLen(0), mOwnership(OWN)
+{
+ nsCAutoString str;
+ nsresult rv = aStream->ReadCString(str);
+ mStr = ToNewCString(str);
+ if (NS_SUCCEEDED(rv))
+ mStrLen = str.Length();
+ *aResult = rv;
+ MOZ_COUNT_CTOR(nsCStringKey);
+}
+
+nsresult
+nsCStringKey::Write(nsIObjectOutputStream* aStream) const
+{
+ return aStream->WriteStringZ(mStr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Copy Constructor
+// We need to free mStr if the object is passed with mOwnership as OWN. As the
+// destructor here is freeing mStr in that case, mStr is NOT getting leaked here.
+
+nsStringKey::nsStringKey(const nsStringKey& aKey)
+ : mStr(aKey.mStr), mStrLen(aKey.mStrLen), mOwnership(aKey.mOwnership)
+{
+ if (mOwnership != NEVER_OWN) {
+ PRUint32 len = mStrLen * sizeof(PRUnichar);
+ PRUnichar* str = NS_REINTERPRET_CAST(PRUnichar*, nsMemory::Alloc(len + sizeof(PRUnichar)));
+ if (!str) {
+ // Pray we don't dangle!
+ mOwnership = NEVER_OWN;
+ } else {
+ // Use memcpy in case there are embedded NULs.
+ memcpy(str, mStr, len);
+ str[mStrLen] = 0;
+ mStr = str;
+ mOwnership = OWN;
+ }
+ }
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::nsStringKey(const nsAFlatString& str)
+ : mStr(NS_CONST_CAST(PRUnichar*, str.get())),
+ mStrLen(str.Length()),
+ mOwnership(OWN_CLONE)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::nsStringKey(const nsAString& str)
+ : mStr(ToNewUnicode(str)),
+ mStrLen(str.Length()),
+ mOwnership(OWN)
+{
+ NS_ASSERTION(mStr, "null string key");
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::nsStringKey(const PRUnichar* str, PRInt32 strLen, Ownership own)
+ : mStr((PRUnichar*)str), mStrLen(strLen), mOwnership(own)
+{
+ NS_ASSERTION(mStr, "null string key");
+ if (mStrLen == PRUint32(-1))
+ mStrLen = nsCRT::strlen(str);
+#ifdef DEBUG
+ mKeyType = StringKey;
+#endif
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsStringKey::~nsStringKey(void)
+{
+ if (mOwnership == OWN)
+ nsMemory::Free(mStr);
+ MOZ_COUNT_DTOR(nsStringKey);
+}
+
+PRUint32
+nsStringKey::HashCode(void) const
+{
+ return nsCRT::HashCode(mStr, (PRUint32*)&mStrLen);
+}
+
+PRBool
+nsStringKey::Equals(const nsHashKey* aKey) const
+{
+ NS_ASSERTION(aKey->GetKeyType() == StringKey, "mismatched key types");
+ nsStringKey* other = (nsStringKey*)aKey;
+ NS_ASSERTION(mStrLen != PRUint32(-1), "never called HashCode");
+ NS_ASSERTION(other->mStrLen != PRUint32(-1), "never called HashCode");
+ if (mStrLen != other->mStrLen)
+ return PR_FALSE;
+ return memcmp(mStr, other->mStr, mStrLen * sizeof(PRUnichar)) == 0;
+}
+
+nsHashKey*
+nsStringKey::Clone() const
+{
+ if (mOwnership == NEVER_OWN)
+ return new nsStringKey(mStr, mStrLen, NEVER_OWN);
+
+ PRUint32 len = (mStrLen+1) * sizeof(PRUnichar);
+ PRUnichar* str = (PRUnichar*)nsMemory::Alloc(len);
+ if (str == NULL)
+ return NULL;
+ memcpy(str, mStr, len);
+ return new nsStringKey(str, mStrLen, OWN);
+}
+
+nsStringKey::nsStringKey(nsIObjectInputStream* aStream, nsresult *aResult)
+ : mStr(nsnull), mStrLen(0), mOwnership(OWN)
+{
+ nsAutoString str;
+ nsresult rv = aStream->ReadString(str);
+ mStr = ToNewUnicode(str);
+ if (NS_SUCCEEDED(rv))
+ mStrLen = str.Length();
+ *aResult = rv;
+ MOZ_COUNT_CTOR(nsStringKey);
+}
+
+nsresult
+nsStringKey::Write(nsIObjectOutputStream* aStream) const
+{
+ return aStream->WriteWStringZ(mStr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
+// deleted
+
+nsObjectHashtable::nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
+ void* cloneElementClosure,
+ nsHashtableEnumFunc destroyElementFun,
+ void* destroyElementClosure,
+ PRUint32 aSize, PRBool threadSafe)
+ : nsHashtable(aSize, threadSafe),
+ mCloneElementFun(cloneElementFun),
+ mCloneElementClosure(cloneElementClosure),
+ mDestroyElementFun(destroyElementFun),
+ mDestroyElementClosure(destroyElementClosure)
+{
+}
+
+nsObjectHashtable::~nsObjectHashtable()
+{
+ Reset();
+}
+
+
+PLDHashOperator PR_CALLBACK
+nsObjectHashtable::CopyElement(PLDHashTable* table,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg)
+{
+ nsObjectHashtable *newHashtable = (nsObjectHashtable *)arg;
+ HTEntry *entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ void* newElement =
+ newHashtable->mCloneElementFun(entry->key, entry->value,
+ newHashtable->mCloneElementClosure);
+ if (newElement == nsnull)
+ return PL_DHASH_STOP;
+ newHashtable->Put(entry->key, newElement);
+ return PL_DHASH_NEXT;
+}
+
+nsHashtable*
+nsObjectHashtable::Clone()
+{
+ if (!mHashtable.ops) return nsnull;
+
+ PRBool threadSafe = PR_FALSE;
+ if (mLock)
+ threadSafe = PR_TRUE;
+ nsObjectHashtable* newHashTable =
+ new nsObjectHashtable(mCloneElementFun, mCloneElementClosure,
+ mDestroyElementFun, mDestroyElementClosure,
+ mHashtable.entryCount, threadSafe);
+
+ PL_DHashTableEnumerate(&mHashtable, CopyElement, newHashTable);
+ return newHashTable;
+}
+
+void
+nsObjectHashtable::Reset()
+{
+ nsHashtable::Reset(mDestroyElementFun, mDestroyElementClosure);
+}
+
+PRBool
+nsObjectHashtable::RemoveAndDelete(nsHashKey *aKey)
+{
+ void *value = Remove(aKey);
+ if (value && mDestroyElementFun)
+ return (*mDestroyElementFun)(aKey, value, mDestroyElementClosure);
+ return PR_FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
+
+PRBool PR_CALLBACK
+nsSupportsHashtable::ReleaseElement(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, aData);
+ NS_IF_RELEASE(element);
+ return PR_TRUE;
+}
+
+nsSupportsHashtable::~nsSupportsHashtable()
+{
+ Enumerate(ReleaseElement, nsnull);
+}
+
+// Return true if we overwrote something
+
+PRBool
+nsSupportsHashtable::Put(nsHashKey *aKey, nsISupports* aData, nsISupports **value)
+{
+ NS_IF_ADDREF(aData);
+ void *prev = nsHashtable::Put(aKey, aData);
+ nsISupports *old = NS_REINTERPRET_CAST(nsISupports *, prev);
+ if (value) // pass own the ownership to the caller
+ *value = old;
+ else // the caller doesn't care, we do
+ NS_IF_RELEASE(old);
+ return prev != nsnull;
+}
+
+nsISupports *
+nsSupportsHashtable::Get(nsHashKey *aKey)
+{
+ void* data = nsHashtable::Get(aKey);
+ if (!data)
+ return nsnull;
+ nsISupports* element = NS_REINTERPRET_CAST(nsISupports*, data);
+ NS_IF_ADDREF(element);
+ return element;
+}
+
+// Return true if we found something (useful for checks)
+
+PRBool
+nsSupportsHashtable::Remove(nsHashKey *aKey, nsISupports **value)
+{
+ void* data = nsHashtable::Remove(aKey);
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, data);
+ if (value) // caller wants it
+ *value = element;
+ else // caller doesn't care, we do
+ NS_IF_RELEASE(element);
+ return data != nsnull;
+}
+
+PLDHashOperator PR_CALLBACK
+nsSupportsHashtable::EnumerateCopy(PLDHashTable*,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg)
+{
+ nsHashtable *newHashtable = (nsHashtable *)arg;
+ HTEntry* entry = NS_STATIC_CAST(HTEntry*, hdr);
+
+ nsISupports* element = NS_STATIC_CAST(nsISupports*, entry->value);
+ NS_IF_ADDREF(element);
+ newHashtable->Put(entry->key, entry->value);
+ return PL_DHASH_NEXT;
+}
+
+nsHashtable*
+nsSupportsHashtable::Clone()
+{
+ if (!mHashtable.ops) return nsnull;
+
+ PRBool threadSafe = (mLock != nsnull);
+ nsSupportsHashtable* newHashTable =
+ new nsSupportsHashtable(mHashtable.entryCount, threadSafe);
+
+ PL_DHashTableEnumerate(&mHashtable, EnumerateCopy, newHashTable);
+ return newHashTable;
+}
+
+void
+nsSupportsHashtable::Reset()
+{
+ Enumerate(ReleaseElement, nsnull);
+ nsHashtable::Reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.h
new file mode 100644
index 00000000..21ce9028
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsHashtable.h
@@ -0,0 +1,454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+/**
+ * nsHashtable is OBSOLETE. Use nsTHashtable or a derivative instead.
+ */
+
+#ifndef nsHashtable_h__
+#define nsHashtable_h__
+
+#include "pldhash.h"
+#include "prlock.h"
+#include "nscore.h"
+#include "nsString.h"
+#include "nsISupportsBase.h"
+#include "nsTraceRefcnt.h"
+
+class nsIObjectInputStream;
+class nsIObjectOutputStream;
+
+class nsHashtable;
+class nsStringKey;
+
+class NS_COM nsHashKey {
+ protected:
+ nsHashKey(void) {
+#ifdef DEBUG
+ mKeyType = UnknownKey;
+#endif
+ MOZ_COUNT_CTOR(nsHashKey);
+ }
+
+
+ public:
+ // Virtual destructor because all hash keys are |delete|d via a
+ // nsHashKey pointer.
+
+ virtual ~nsHashKey(void);
+ virtual PRUint32 HashCode(void) const = 0;
+ virtual PRBool Equals(const nsHashKey *aKey) const = 0;
+ virtual nsHashKey *Clone() const = 0;
+ virtual nsresult Write(nsIObjectOutputStream* aStream) const;
+
+#ifdef DEBUG
+ public:
+ // used for verification that we're casting to the correct key type
+ enum nsHashKeyType {
+ UnknownKey,
+ SupportsKey,
+ PRUint32Key,
+ VoidKey,
+ IDKey,
+ CStringKey,
+ StringKey
+ };
+ nsHashKeyType GetKeyType() const { return mKeyType; }
+ protected:
+ nsHashKeyType mKeyType;
+#endif
+};
+
+// Enumerator and Read/Write callback functions.
+
+// Return values for nsHashtableEnumFunc
+enum {
+ kHashEnumerateStop = PR_FALSE,
+ kHashEnumerateNext = PR_TRUE,
+ kHashEnumerateRemove = 2
+};
+
+typedef PRIntn
+(*PR_CALLBACK nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* aClosure);
+
+typedef nsresult
+(*PR_CALLBACK nsHashtableReadEntryFunc)(nsIObjectInputStream *aStream,
+ nsHashKey **aKey,
+ void **aData);
+
+// NB: may be called with null aKey or aData, to free just one of the two.
+typedef void
+(*PR_CALLBACK nsHashtableFreeEntryFunc)(nsIObjectInputStream *aStream,
+ nsHashKey *aKey,
+ void *aData);
+
+typedef nsresult
+(*PR_CALLBACK nsHashtableWriteDataFunc)(nsIObjectOutputStream *aStream,
+ void *aData);
+
+class NS_COM nsHashtable {
+ protected:
+ // members
+ PRLock* mLock;
+ PLDHashTable mHashtable;
+ PRBool mEnumerating;
+
+ public:
+ nsHashtable(PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE);
+ virtual ~nsHashtable();
+
+ PRInt32 Count(void) { return mHashtable.entryCount; }
+ PRBool Exists(nsHashKey *aKey);
+ void *Put(nsHashKey *aKey, void *aData);
+ void *Get(nsHashKey *aKey);
+ void *Remove(nsHashKey *aKey);
+ nsHashtable *Clone();
+ void Enumerate(nsHashtableEnumFunc aEnumFunc, void* aClosure = NULL);
+ void Reset();
+ void Reset(nsHashtableEnumFunc destroyFunc, void* aClosure = NULL);
+
+ nsHashtable(nsIObjectInputStream* aStream,
+ nsHashtableReadEntryFunc aReadEntryFunc,
+ nsHashtableFreeEntryFunc aFreeEntryFunc,
+ nsresult *aRetVal);
+ nsresult Write(nsIObjectOutputStream* aStream,
+ nsHashtableWriteDataFunc aWriteDataFunc) const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
+// deleted
+
+typedef void* (*PR_CALLBACK nsHashtableCloneElementFunc)(nsHashKey *aKey, void *aData, void* aClosure);
+
+class NS_COM nsObjectHashtable : public nsHashtable {
+ public:
+ nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
+ void* cloneElementClosure,
+ nsHashtableEnumFunc destroyElementFun,
+ void* destroyElementClosure,
+ PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE);
+ ~nsObjectHashtable();
+
+ nsHashtable *Clone();
+ void Reset();
+ PRBool RemoveAndDelete(nsHashKey *aKey);
+
+ protected:
+ static PLDHashOperator PR_CALLBACK CopyElement(PLDHashTable* table,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg);
+
+ nsHashtableCloneElementFunc mCloneElementFun;
+ void* mCloneElementClosure;
+ nsHashtableEnumFunc mDestroyElementFun;
+ void* mDestroyElementClosure;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
+
+class nsISupports;
+
+class NS_COM nsSupportsHashtable
+ : private nsHashtable
+{
+ public:
+ typedef PRBool (* PR_CALLBACK EnumFunc) (nsHashKey *aKey, void *aData, void* aClosure);
+
+ nsSupportsHashtable(PRUint32 aSize = 16, PRBool threadSafe = PR_FALSE)
+ : nsHashtable(aSize, threadSafe) {}
+ ~nsSupportsHashtable();
+
+ PRInt32 Count(void) {
+ return nsHashtable::Count();
+ }
+ PRBool Exists(nsHashKey *aKey) {
+ return nsHashtable::Exists (aKey);
+ }
+ PRBool Put(nsHashKey *aKey,
+ nsISupports *aData,
+ nsISupports **value = nsnull);
+ nsISupports* Get(nsHashKey *aKey);
+ PRBool Remove(nsHashKey *aKey, nsISupports **value = nsnull);
+ nsHashtable *Clone();
+ void Enumerate(EnumFunc aEnumFunc, void* aClosure = NULL) {
+ nsHashtable::Enumerate(aEnumFunc, aClosure);
+ }
+ void Reset();
+
+ private:
+ static PRBool PR_CALLBACK ReleaseElement(nsHashKey *, void *, void *);
+ static PLDHashOperator PR_CALLBACK EnumerateCopy(PLDHashTable*,
+ PLDHashEntryHdr* hdr,
+ PRUint32 i, void *arg);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupportsKey: Where keys are nsISupports objects that get refcounted.
+
+#include "nsISupports.h"
+
+class NS_COM nsISupportsKey : public nsHashKey {
+ protected:
+ nsISupports* mKey;
+
+ public:
+ nsISupportsKey(const nsISupportsKey& aKey) : mKey(aKey.mKey) {
+#ifdef DEBUG
+ mKeyType = SupportsKey;
+#endif
+ NS_IF_ADDREF(mKey);
+ }
+
+ nsISupportsKey(nsISupports* key) {
+#ifdef DEBUG
+ mKeyType = SupportsKey;
+#endif
+ mKey = key;
+ NS_IF_ADDREF(mKey);
+ }
+
+ ~nsISupportsKey(void) {
+ NS_IF_RELEASE(mKey);
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mKey);
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ NS_ASSERTION(aKey->GetKeyType() == SupportsKey, "mismatched key types");
+ return (mKey == ((nsISupportsKey *) aKey)->mKey);
+ }
+
+ nsHashKey *Clone() const {
+ return new nsISupportsKey(mKey);
+ }
+
+ nsISupportsKey(nsIObjectInputStream* aStream, nsresult *aResult);
+ nsresult Write(nsIObjectOutputStream* aStream) const;
+};
+
+
+class nsPRUint32Key : public nsHashKey {
+protected:
+ PRUint32 mKey;
+public:
+ nsPRUint32Key(PRUint32 key) {
+#ifdef DEBUG
+ mKeyType = PRUint32Key;
+#endif
+ mKey = key;
+ }
+
+ PRUint32 HashCode(void) const {
+ return mKey;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ return mKey == ((const nsPRUint32Key *) aKey)->mKey;
+ }
+ nsHashKey *Clone() const {
+ return new nsPRUint32Key(mKey);
+ }
+ PRUint32 GetValue() { return mKey; }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsVoidKey: Where keys are void* objects that don't get refcounted.
+
+class nsVoidKey : public nsHashKey {
+ protected:
+ void* mKey;
+
+ public:
+ nsVoidKey(const nsVoidKey& aKey) : mKey(aKey.mKey) {
+#ifdef DEBUG
+ mKeyType = aKey.mKeyType;
+#endif
+ }
+
+ nsVoidKey(void* key) {
+#ifdef DEBUG
+ mKeyType = VoidKey;
+#endif
+ mKey = key;
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mKey);
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ NS_ASSERTION(aKey->GetKeyType() == VoidKey, "mismatched key types");
+ return (mKey == ((const nsVoidKey *) aKey)->mKey);
+ }
+
+ nsHashKey *Clone() const {
+ return new nsVoidKey(mKey);
+ }
+
+ void* GetValue() { return mKey; }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIDKey: Where keys are nsIDs (e.g. nsIID, nsCID).
+
+#include "nsID.h"
+
+class NS_COM nsIDKey : public nsHashKey {
+ protected:
+ nsID mID;
+
+ public:
+ nsIDKey(const nsIDKey& aKey) : mID(aKey.mID) {
+#ifdef DEBUG
+ mKeyType = IDKey;
+#endif
+ }
+
+ nsIDKey(const nsID &aID) {
+#ifdef DEBUG
+ mKeyType = IDKey;
+#endif
+ mID = aID;
+ }
+
+ PRUint32 HashCode(void) const {
+ return mID.m0;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ NS_ASSERTION(aKey->GetKeyType() == IDKey, "mismatched key types");
+ return (mID.Equals(((const nsIDKey *) aKey)->mID));
+ }
+
+ nsHashKey *Clone() const {
+ return new nsIDKey(mID);
+ }
+
+ nsIDKey(nsIObjectInputStream* aStream, nsresult *aResult);
+ nsresult Write(nsIObjectOutputStream* aStream) const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#include "nsString.h"
+
+// for null-terminated c-strings
+class NS_COM nsCStringKey : public nsHashKey {
+ public:
+
+ // NB: when serializing, NEVER_OWN keys are deserialized as OWN.
+ enum Ownership {
+ NEVER_OWN, // very long lived, even clones don't need to copy it.
+ OWN_CLONE, // as long lived as this key. But clones make a copy.
+ OWN // to be free'd in key dtor. Clones make their own copy.
+ };
+
+ nsCStringKey(const nsCStringKey& aStrKey);
+ nsCStringKey(const char* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
+ nsCStringKey(const nsAFlatCString& str);
+ nsCStringKey(const nsACString& str);
+ ~nsCStringKey(void);
+
+ PRUint32 HashCode(void) const;
+ PRBool Equals(const nsHashKey* aKey) const;
+ nsHashKey* Clone() const;
+ nsCStringKey(nsIObjectInputStream* aStream, nsresult *aResult);
+ nsresult Write(nsIObjectOutputStream* aStream) const;
+
+ // For when the owner of the hashtable wants to peek at the actual
+ // string in the key. No copy is made, so be careful.
+ const char* GetString() const { return mStr; }
+ PRUint32 GetStringLength() const { return mStrLen; }
+
+ protected:
+ char* mStr;
+ PRUint32 mStrLen;
+ Ownership mOwnership;
+};
+
+// for null-terminated unicode strings
+class NS_COM nsStringKey : public nsHashKey {
+ public:
+
+ // NB: when serializing, NEVER_OWN keys are deserialized as OWN.
+ enum Ownership {
+ NEVER_OWN, // very long lived, even clones don't need to copy it.
+ OWN_CLONE, // as long lived as this key. But clones make a copy.
+ OWN // to be free'd in key dtor. Clones make their own copy.
+ };
+
+ nsStringKey(const nsStringKey& aKey);
+ nsStringKey(const PRUnichar* str, PRInt32 strLen = -1, Ownership own = OWN_CLONE);
+ nsStringKey(const nsAFlatString& str);
+ nsStringKey(const nsAString& str);
+ ~nsStringKey(void);
+
+ PRUint32 HashCode(void) const;
+ PRBool Equals(const nsHashKey* aKey) const;
+ nsHashKey* Clone() const;
+ nsStringKey(nsIObjectInputStream* aStream, nsresult *aResult);
+ nsresult Write(nsIObjectOutputStream* aStream) const;
+
+ // For when the owner of the hashtable wants to peek at the actual
+ // string in the key. No copy is made, so be careful.
+ const PRUnichar* GetString() const { return mStr; }
+ PRUint32 GetStringLength() const { return mStrLen; }
+
+ protected:
+ PRUnichar* mStr;
+ PRUint32 mStrLen;
+ Ownership mOwnership;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIArray.idl b/src/libs/xpcom18a4/xpcom/ds/nsIArray.idl
new file mode 100644
index 00000000..c937ec4b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIArray.idl
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM Array interface.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsISupports.idl"
+
+interface nsISimpleEnumerator;
+
+/**
+ * nsIArray
+ *
+ * An indexed collection of elements. Provides basic functionality for
+ * retrieving elements at a specific position, searching for
+ * elements. Indexes are zero-based, such that the last element in the
+ * array is stored at the index length-1.
+ *
+ * For an array which can be modified, see nsIMutableArray below.
+ *
+ * Neither interface makes any attempt to protect the individual
+ * elements from modification. The convention is that the elements of
+ * the array should not be modified. Documentation within a specific
+ * interface should describe variations from this convention.
+ *
+ * It is also convention that if an interface provides access to an
+ * nsIArray, that the array should not be QueryInterfaced to an
+ * nsIMutableArray for modification. If the interface in question had
+ * intended the array to be modified, it would have returned an
+ * nsIMutableArray!
+ *
+ * null is a valid entry in the array, and as such any nsISupports
+ * parameters may be null, except where noted.
+ *
+ * @status UNDER_REVIEW
+ */
+[scriptable, uuid(114744d9-c369-456e-b55a-52fe52880d2d)]
+interface nsIArray : nsISupports
+{
+ /**
+ * length
+ *
+ * number of elements in the array.
+ */
+ readonly attribute unsigned long length;
+
+ /**
+ * queryElementAt()
+ *
+ * Retrieve a specific element of the array, and QueryInterface it
+ * to the specified interface. null is a valid result for
+ * this method, but exceptions are thrown in other circumstances
+ *
+ * @param index position of element
+ * @param uuid the IID of the requested interface
+ * @param result the object, QI'd to the requested interface
+ *
+ * @throws NS_ERROR_NO_INTERFACE when an entry exists at the
+ * specified index, but the requested interface is not
+ * available.
+ * @throws NS_ERROR_ILLEGAL_VALUE when index > length-1
+ *
+ */
+ void queryElementAt(in unsigned long index,
+ in nsIIDRef uuid,
+ [iid_is(uuid), retval] out nsQIResult result);
+
+ /**
+ * indexOf()
+ *
+ * Get the position of a specific element. Note that since null is
+ * a valid input, exceptions are used to indicate that an element
+ * is not found.
+ *
+ * @param startIndex The initial element to search in the array
+ * To start at the beginning, use 0 as the
+ * startIndex
+ * @param element The element you are looking for
+ * @returns a number >= startIndex which is the position of the
+ * element in the array.
+ * @throws NS_ERROR_NOT_FOUND if the element was not in the array.
+ */
+ unsigned long indexOf(in unsigned long startIndex,
+ in nsISupports element);
+
+ /**
+ * enumerate the array
+ *
+ * @returns a new enumerator positioned at the start of the array
+ * @throws NS_ERROR_FAILURE if the array is empty (to make it easy
+ * to detect errors)
+ */
+ nsISimpleEnumerator enumerate();
+
+};
+
+/**
+ * nsIMutableArray
+ * A separate set of methods that will act on the array. Consumers of
+ * nsIArray should not QueryInterface to nsIMutableArray unless they
+ * own the array.
+ *
+ * As above, it is legal to add null elements to the array. Note also
+ * that null elements can be created as a side effect of
+ * insertElementAt(). Conversely, if insertElementAt() is never used,
+ * and null elements are never explicitly added to the array, then it
+ * is guaranteed that queryElementAt() will never return a null value.
+ *
+ * Any of these methods may throw NS_ERROR_OUT_OF_MEMORY when the
+ * array must grow to complete the call, but the allocation fails.
+ *
+ * @status UNDER_REVIEW
+ */
+
+[scriptable, uuid(2cd0b2f8-d4dd-48b8-87ba-b0200501f079)]
+interface nsIMutableArray : nsIArray
+{
+ /**
+ * appendElement()
+ *
+ * Append an element at the end of the array.
+ *
+ * @param element The element to append.
+ * @param element Whether or not to store the element using a weak
+ * reference.
+ * @throws NS_ERROR_UNEXPECTED when a weak reference is requested,
+ * but the element does not support
+ * nsIWeakReference.
+ */
+ void appendElement(in nsISupports element, in boolean weak);
+
+ /**
+ * removeElementAt()
+ *
+ * Remove an element at a specific position.
+ * To remove a specific element, use indexOf() to find the index
+ * first, then call removeElementAt().
+ *
+ * @param index the position of the item
+ *
+ */
+ void removeElementAt(in unsigned long index);
+
+ /**
+ * insertElementAt()
+ *
+ * Insert an element at the given position, and move all elements
+ * stored at a higher position up one.
+ *
+ * @param element The element to insert
+ * @param index The position in the array. If the position is
+ * greater than or equal to the length of the array
+ * (@see nsIArray) then the array will grow to
+ * exactly accomadate the index, and the new length
+ * will be index+1. The newly created entries will
+ * be null.
+ *
+ * @throws NS_ERROR_FAILURE when a weak reference is requested,
+ * but the element does not support
+ * nsIWeakReference.
+ */
+ void insertElementAt(in nsISupports element, in unsigned long index, in boolean weak);
+
+ /**
+ * clear()
+ *
+ * clear the entire array, releasing all stored objects
+ */
+ void clear();
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl b/src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl
new file mode 100644
index 00000000..45eecb4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIAtom.idl
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsISupports.idl"
+
+%{C++
+#include "nsAString.h"
+#include "nsCOMPtr.h"
+%}
+
+/*
+ * Should this really be scriptable? Using atoms from script or proxies
+ * could be dangerous since double-wrapping could lead to loss of
+ * pointer identity.
+ */
+
+[scriptable, uuid(3d1b15b0-93b4-11d1-895b-006008911b81)]
+interface nsIAtom : nsISupports
+{
+ /**
+ * Get the Unicode or UTF8 value for the string
+ */
+ AString toString();
+ AUTF8String toUTF8String();
+
+ /**
+ * Return a pointer to a zero terminated UTF8 string.
+ */
+ [noscript] void getUTF8String([shared, retval] out string aResult);
+
+ /**
+ * Compare the atom to a specific string value
+ * Note that this will NEVER return/throw an error condition.
+ */
+ boolean equals(in AString aString);
+
+ boolean equalsUTF8(in AUTF8String aString);
+
+%{C++
+ // note this is NOT virtual so this won't muck with the vtable!
+ inline PRBool Equals(const nsAString& s) {
+ PRBool result;
+ Equals(s, &result);
+ return result;
+ }
+
+ inline PRBool EqualsUTF8(const nsACString& s) {
+ PRBool result;
+ EqualsUTF8(s, &result);
+ return result;
+ }
+%}
+
+};
+
+
+%{C++
+/*
+ * The three forms of NS_NewAtom and do_GetAtom (for use with
+ * |nsCOMPtr<nsIAtom>|) return the atom for the string given. At any
+ * given time there will always be one atom representing a given string.
+ * Atoms are intended to make string comparison cheaper by simplifying
+ * it to pointer equality. A pointer to the atom that does not own a
+ * reference is not guaranteed to be valid.
+ *
+ * The three forms of NS_NewPermanentAtom and do_GetPermanentAtom return
+ * the atom for the given string and ensure that the atom is permanent.
+ * An atom that is permanent will exist (occupy space at a specific
+ * location in memory) until XPCOM is shut down. The advantage of
+ * permanent atoms is that they do not need to maintain a reference
+ * count, which requires locking and hurts performance.
+ */
+
+
+/**
+ * Find an atom that matches the given UTF-8 string.
+ * The string is assumed to be zero terminated.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const char* aUTF8String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const char* aUTF8String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const char* aUTF8String)
+ { return NS_NewAtom(aUTF8String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const char* aUTF8String)
+ { return NS_NewPermanentAtom(aUTF8String); }
+
+/**
+ * Find an atom that matches the given UTF-8 string.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const nsACString& aUTF8String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsACString& aUTF8String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const nsACString& aUTF8String)
+ { return NS_NewAtom(aUTF8String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const nsACString& aUTF8String)
+ { return NS_NewPermanentAtom(aUTF8String); }
+
+/**
+ * Find an atom that matches the given UTF-16 string.
+ * The string is assumed to be zero terminated.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const PRUnichar* aUTF16String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const PRUnichar* aUTF16String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const PRUnichar* aUTF16String)
+ { return NS_NewAtom(aUTF16String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const PRUnichar* aUTF16String)
+ { return NS_NewPermanentAtom(aUTF16String); }
+
+/**
+ * Find an atom that matches the given UTF-16 string.
+ */
+extern NS_COM nsIAtom* NS_NewAtom(const nsAString& aUTF16String);
+extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsAString& aUTF16String);
+
+inline already_AddRefed<nsIAtom> do_GetAtom(const nsAString& aUTF16String)
+ { return NS_NewAtom(aUTF16String); }
+inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const nsAString& aUTF16String)
+ { return NS_NewPermanentAtom(aUTF16String); }
+
+/**
+ * Return a count of the total number of atoms currently
+ * alive in the system.
+ */
+extern NS_COM nsrefcnt NS_GetNumberOfAtoms(void);
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl b/src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl
new file mode 100644
index 00000000..b3a30358
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIAtomService.idl
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIAtom.idl"
+
+%{C++
+#define NS_ATOMSERVICE_CID \
+{ /* ed3db3fc-0168-4cab-8818-98f5475a490c */ \
+ 0xed3db3fc, \
+ 0x0168, \
+ 0x4cab, \
+ {0x88, 0x18, 0x98, 0xf5, 0x47, 0x5a, 0x49, 0x0c} }
+
+#define NS_ATOMSERVICE_CONTRACTID "@mozilla.org/atom-service;1"
+#define NS_ATOMSERVICE_CLASSNAME "Atom Service"
+%}
+
+/*
+ * Should this really be scriptable? Using atoms from script or proxies
+ * could be dangerous since double-wrapping could lead to loss of
+ * pointer identity.
+ */
+
+[scriptable, uuid(e5d0d92b-ea45-4622-ab48-302baf2094ee)]
+interface nsIAtomService : nsISupports {
+
+ /**
+ * Version of NS_NewAtom that doesn't require linking against the
+ * XPCOM library. See nsIAtom.idl.
+ */
+ nsIAtom getAtom(in wstring value);
+
+ /**
+ * Version of NS_NewPermanentAtom that doesn't require linking against
+ * the XPCOM library. See nsIAtom.idl.
+ */
+ nsIAtom getPermanentAtom(in wstring value);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h
new file mode 100644
index 00000000..5d02c9cb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIByteBuffer.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIByteBuffer_h___
+#define nsIByteBuffer_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+class nsIInputStream;
+
+#define NS_IBYTE_BUFFER_IID \
+{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
+ {0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
+#define NS_IBYTEBUFFER_IID \
+{ 0xe4a6e4b0, 0x93b4, 0x11d1, \
+ {0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
+#define NS_BYTEBUFFER_CONTRACTID "@mozilla.org/byte-buffer;1"
+#define NS_BYTEBUFFER_CLASSNAME "Byte Buffer"
+
+/** Interface to a buffer that holds bytes */
+class nsIByteBuffer : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBYTEBUFFER_IID)
+
+ NS_IMETHOD Init(PRUint32 aBufferSize) = 0;
+
+ /** @return length of buffer, i.e. how many bytes are currently in it. */
+ NS_IMETHOD_(PRUint32) GetLength(void) const = 0;
+
+ /** @return number of bytes allocated in the buffer */
+ NS_IMETHOD_(PRUint32) GetBufferSize(void) const = 0;
+
+ /** @return the buffer */
+ NS_IMETHOD_(char*) GetBuffer(void) const = 0;
+
+ /** Grow buffer to aNewSize bytes. */
+ NS_IMETHOD_(PRBool) Grow(PRUint32 aNewSize) = 0;
+
+ /** Fill the buffer with data from aStream. Don't grow the buffer, only
+ * read until length of buffer equals buffer size. */
+ NS_IMETHOD_(PRInt32) Fill(nsresult* aErrorCode, nsIInputStream* aStream,
+ PRUint32 aKeep) = 0;
+};
+
+#define NS_BYTEBUFFER_CID \
+{ /* a49d5280-0d6b-11d3-9331-00104ba0fd40 */ \
+ 0xa49d5280, \
+ 0x0d6b, \
+ 0x11d3, \
+ {0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+/** Create a new byte buffer using the given buffer size. */
+extern NS_COM nsresult
+NS_NewByteBuffer(nsIByteBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize = 0);
+
+#endif /* nsIByteBuffer_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsICollection.idl b/src/libs/xpcom18a4/xpcom/ds/nsICollection.idl
new file mode 100644
index 00000000..f97bf970
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsICollection.idl
@@ -0,0 +1,92 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org>: |do_QueryElementAt|
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISerializable.idl"
+#include "nsIEnumerator.idl"
+
+[scriptable, uuid(83b6019c-cbc4-11d2-8cca-0060b0fc14a3)]
+interface nsICollection : nsISerializable
+{
+
+ PRUint32 Count();
+ nsISupports GetElementAt(in PRUint32 index);
+ void QueryElementAt(in PRUint32 index, in nsIIDRef uuid,
+ [iid_is(uuid),retval] out nsQIResult result);
+ void SetElementAt(in PRUint32 index, in nsISupports item);
+ void AppendElement(in nsISupports item);
+ void RemoveElement(in nsISupports item);
+
+ nsIEnumerator Enumerate();
+
+ void Clear();
+
+};
+
+%{C++
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+class NS_COM nsQueryElementAt : public nsCOMPtr_helper
+ {
+ public:
+ nsQueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr )
+ : mCollection(aCollection),
+ mIndex(aIndex),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsICollection* mCollection;
+ PRUint32 mIndex;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsQueryElementAt
+do_QueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr = 0 )
+ {
+ return nsQueryElementAt(aCollection, aIndex, aErrorPtr);
+ }
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl b/src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl
new file mode 100644
index 00000000..7f8824b2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIEnumerator.idl
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISimpleEnumerator.idl"
+
+%{C++
+#define NS_ENUMERATOR_FALSE 1
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_NewEmptyEnumerator VBoxNsxpNS_NewEmptyEnumerator
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+extern "C" NS_COM nsresult
+NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult);
+%}
+/*
+ * DO NOT USE THIS INTERFACE. IT IS HORRIBLY BROKEN, USES NS_COMFALSE
+ * AND IS BASICALLY IMPOSSIBLE TO USE CORRECTLY THROUGH PROXIES OR
+ * XPCONNECT. IF YOU SEE NEW USES OF THIS INTERFACE IN CODE YOU ARE
+ * REVIEWING, YOU SHOULD INSIST ON nsISimpleEnumerator.
+ *
+ * DON'T MAKE ME COME OVER THERE.
+ */
+[scriptable, uuid(ad385286-cbc4-11d2-8cca-0060b0fc14a3)]
+interface nsIEnumerator : nsISupports {
+ /** First will reset the list. will return NS_FAILED if no items
+ */
+ void first();
+
+ /** Next will advance the list. will return failed if already at end
+ */
+ void next();
+
+ /** CurrentItem will return the CurrentItem item it will fail if the
+ * list is empty
+ */
+ nsISupports currentItem();
+
+ /** return if the collection is at the end. that is the beginning following
+ * a call to Prev and it is the end of the list following a call to next
+ */
+ void isDone();
+};
+
+[uuid(75f158a0-cadd-11d2-8cca-0060b0fc14a3)]
+interface nsIBidirectionalEnumerator : nsIEnumerator {
+
+ /** Last will reset the list to the end. will return NS_FAILED if no items
+ */
+ void last();
+
+ /** Prev will decrement the list. will return failed if already at beginning
+ */
+ void prev();
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl b/src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl
new file mode 100644
index 00000000..ca3c6598
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIHashable.idl
@@ -0,0 +1,58 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg <benjamin@smedbergs.us>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Represents an object that can be stored in a hashtable.
+ */
+
+[scriptable, uuid(17e595fa-b57a-4933-bd0f-b1812e8ab188)]
+interface nsIHashable : nsISupports
+{
+ /**
+ * Is this object the equivalent of the other object?
+ */
+ boolean equals(in nsIHashable aOther);
+
+ /**
+ * A generated hashcode for this object. Objects that are equivalent
+ * must have the same hash code. Getting this property should never
+ * throw an exception!
+ */
+ readonly attribute unsigned long hashCode;
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl b/src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl
new file mode 100644
index 00000000..d2240f2e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIObserver.idl
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * This interface is implemented by an object that wants
+ * to observe an event corresponding to a topic.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(DB242E01-E4D9-11d2-9DDE-000064657374)]
+interface nsIObserver : nsISupports {
+
+ /**
+ * Observe will be called when there is a notification for the
+ * topic |aTopic|. This assumes that the object implementing
+ * this interface has been registered with an observer service
+ * such as the nsIObserverService.
+ *
+ * If you expect multiple topics/subjects, the impl is
+ * responsible for filtering.
+ *
+ * You should not modify, add, remove, or enumerate
+ * notifications in the implemention of observe.
+ *
+ * @param aSubject : Notification specific interface pointer.
+ * @param aTopic : The notification topic or subject.
+ * @param aData : Notification specific wide string.
+ * subject event.
+ */
+ void observe( in nsISupports aSubject,
+ in string aTopic,
+ in wstring aData );
+
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl b/src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl
new file mode 100644
index 00000000..059a903a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIObserverService.idl
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIObserver;
+interface nsISimpleEnumerator;
+
+/**
+ * nsIObserverService
+ *
+ * Service allows a client listener (nsIObserver) to register and unregister for
+ * notifications of specific string referenced topic. Service also provides a
+ * way to notify registered listeners and a way to enumerate registered client
+ * listeners.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(D07F5192-E3D1-11d2-8ACD-00105A1B8860)]
+interface nsIObserverService : nsISupports
+{
+
+ /**
+ * AddObserver
+ *
+ * Registers a given listener for a notifications regarding the specified
+ * topic.
+ *
+ * @param anObserve : The interface pointer which will receive notifications.
+ * @param aTopic : The notification topic or subject.
+ * @param ownsWeak : If set to false, the nsIObserverService will hold a
+ * strong reference to |anObserver|. If set to true and
+ * |anObserver| supports the nsIWeakReference interface,
+ * a weak reference will be held. Otherwise an error will be
+ * returned.
+ */
+ void addObserver( in nsIObserver anObserver, in string aTopic, in boolean ownsWeak);
+
+ /**
+ * removeObserver
+ *
+ * Unregisters a given listener from notifications regarding the specified
+ * topic.
+ *
+ * @param anObserver : The interface pointer which will stop recieving
+ * notifications.
+ * @param aTopic : The notification topic or subject.
+ */
+ void removeObserver( in nsIObserver anObserver, in string aTopic );
+
+ /**
+ * notifyObservers
+ *
+ * Notifies all registered listeners of the given topic.
+ *
+ * @param aSubject : Notification specific interface pointer.
+ * @param aTopic : The notification topic or subject.
+ * @param someData : Notification specific wide string.
+ */
+ void notifyObservers( in nsISupports aSubject,
+ in string aTopic,
+ in wstring someData );
+
+ /**
+ * enumerateObservers
+ *
+ * Returns an enumeration of all registered listeners.
+ *
+ * @param aTopic : The notification topic or subject.
+ */
+ nsISimpleEnumerator enumerateObservers( in string aTopic );
+
+
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h
new file mode 100644
index 00000000..773a52ad
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties.h
@@ -0,0 +1,8 @@
+
+#ifndef __gen_nsIPersistentProperties_h__
+#define __gen_nsIPersistentProperties_h__
+
+// "soft" switch over to an IDL generated header file
+#include "nsIPersistentProperties2.h"
+
+#endif /* __gen_nsIPersistentProperties_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl
new file mode 100644
index 00000000..3d935621
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIPersistentProperties2.idl
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIProperties.idl"
+#include "nsISimpleEnumerator.idl"
+
+interface nsIInputStream;
+interface nsIOutputStream;
+
+[scriptable, uuid(283EE646-1AEF-11D4-98B3-00C04fA0CE9A)]
+interface nsIPropertyElement : nsISupports {
+ attribute AUTF8String key;
+ attribute AString value;
+};
+
+[scriptable, uuid(1A180F60-93B2-11d2-9B8B-00805F8A16D9)]
+interface nsIPersistentProperties : nsIProperties
+{
+ /**
+ * load a set of name/value pairs from the input stream
+ * names and values should be in UTF8
+ */
+ void load(in nsIInputStream input);
+
+ /**
+ * output the values to the stream - results will be in UTF8
+ */
+ void save(in nsIOutputStream output, in AUTF8String header);
+
+ /**
+ * call subclass() to make future calls to load() set the properties
+ * in this "superclass" instead
+ */
+ void subclass(in nsIPersistentProperties superclass);
+
+ /**
+ * get an enumeration of nsIPropertyElement objects,
+ * which are read-only (i.e. setting properties on the element will
+ * not make changes back into the source nsIPersistentProperties
+ */
+ nsISimpleEnumerator enumerate();
+
+ /**
+ * shortcut to nsIProperty's get() which retrieves a string value
+ * directly (and thus faster)
+ */
+ AString getStringProperty(in AUTF8String key);
+
+ /**
+ * shortcut to nsIProperty's set() which sets a string value
+ * directly (and thus faster)
+ */
+ AString setStringProperty(in AUTF8String key, in AString value);
+};
+
+
+%{C++
+
+//{283EE645-1AEF-11D4-98B3-00C04fA0CE9A}
+#define NS_IPROPERTYELEMENT_CID \
+{ 0x283ee645, 0x1aef, 0x11d4, \
+ { 0x98, 0xb3, 0x0, 0xc0, 0x4f, 0xa0, 0xce, 0x9a } }
+
+#define NS_IPERSISTENTPROPERTIES_CID \
+{ 0x2245e573, 0x9464, 0x11d2, \
+ { 0x9b, 0x8b, 0x0, 0x80, 0x5f, 0x8a, 0x16, 0xd9 } }
+
+#define NS_PERSISTENTPROPERTIES_CONTRACTID "@mozilla.org/persistent-properties;1"
+#define NS_PERSISTENTPROPERTIES_CLASSNAME "Persistent Properties"
+
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl b/src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl
new file mode 100644
index 00000000..32a2a057
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIProperties.idl
@@ -0,0 +1,79 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/*
+ * Simple mapping service interface.
+ * @status FROZEN
+ */
+
+[scriptable, uuid(78650582-4e93-4b60-8e85-26ebd3eb14ca)]
+interface nsIProperties : nsISupports
+{
+ /**
+ * Gets a property with a given name.
+ *
+ * @return NS_ERROR_FAILURE if a property with that name doesn't exist.
+ * @return NS_ERROR_NO_INTERFACE if the found property fails to QI to the
+ * given iid.
+ */
+ void get(in string prop, in nsIIDRef iid,
+ [iid_is(iid),retval] out nsQIResult result);
+
+ /**
+ * Sets a property with a given name to a given value.
+ */
+ void set(in string prop, in nsISupports value);
+
+ /**
+ * Returns true if the property with the given name exists.
+ */
+ boolean has(in string prop);
+
+ /**
+ * Undefines a property.
+ * @return NS_ERROR_FAILURE if a property with that name doesn't
+ * already exist.
+ */
+ void undefine(in string prop);
+
+ /**
+ * Returns an array of the keys.
+ */
+ void getKeys(out PRUint32 count, [array, size_is(count), retval] out string keys);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl b/src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl
new file mode 100644
index 00000000..b54577ff
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIPropertyBag.idl
@@ -0,0 +1,77 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsIVariant based Property Bag support. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+#include "nsISimpleEnumerator.idl"
+
+[scriptable, uuid(6dcf9030-a49f-11d5-910d-0010a4e73d9a)]
+interface nsIProperty : nsISupports
+{
+ /**
+ * Get the name of the property.
+ */
+ readonly attribute AString name;
+
+ /**
+ * Get the value of the property.
+ */
+ readonly attribute nsIVariant value;
+};
+
+[scriptable, uuid(bfcd37b0-a49f-11d5-910d-0010a4e73d9a)]
+interface nsIPropertyBag : nsISupports
+{
+ /**
+ * Get a nsISimpleEnumerator whose elements are nsIProperty objects.
+ */
+ readonly attribute nsISimpleEnumerator enumerator;
+
+ /**
+ * Get a property value for the given name.
+ * @return NS_ERROR_FAILURE if a property with that name doesn't
+ * exist.
+ */
+ nsIVariant getProperty(in AString name);
+};
+
+// We can add nsIWritableProperty and nsIWritablePropertyBag when we need them.
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl b/src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl
new file mode 100644
index 00000000..5402890e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIRecyclingAllocator.idl
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIMemory.idl"
+
+/**
+ *
+ * nsIRecyclingAllocator: A wrapper for the nsRecyclingAllocator
+ *
+ * Holds allocations and reuses them for subsequent allocs.
+ * Thread safe and uses a timer to release freelist.
+ *
+ * @status UNDER-DEVELOPMENT
+ */
+
+[scriptable, uuid(d064a04c-9cee-4319-be31-64d565bccba9)]
+interface nsIRecyclingAllocator : nsIMemory
+{
+ void init(in size_t nblocks, in size_t recycleAfter, in string id);
+};
+
+%{C++
+#define NS_RECYCLINGALLOCATOR_CID \
+{ /* ac07ed4c-bf17-4976-a15c-d2194db3b1bf */ \
+ 0xac07ed4c, \
+ 0xbf17, \
+ 0x4976, \
+ {0xa1, 0x5c, 0xd2, 0x19, 0x4d, 0xb3, 0xb1, 0xbf} }
+
+#define NS_RECYCLINGALLOCATOR_CLASSNAME "Recycling Allocator"
+
+#define NS_RECYCLINGALLOCATOR_CONTRACTID "@mozilla.org/recycling-allocator;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl b/src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl
new file mode 100644
index 00000000..907c4824
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISerializable.idl
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIObjectInputStream;
+interface nsIObjectOutputStream;
+
+[scriptable, uuid(91cca981-c26d-44a8-bebe-d9ed4891503a)]
+interface nsISerializable : nsISupports
+{
+ /**
+ * Initialize the object implementing nsISerializable, which must have
+ * been freshly constructed via CreateInstance. All data members that
+ * can't be set to default values must have been serialized by write,
+ * and should be read from aInputStream in the same order by this method.
+ */
+ void read(in nsIObjectInputStream aInputStream);
+
+ /**
+ * Serialize the object implementing nsISerializable to aOutputStream, by
+ * writing each data member that must be recovered later to reconstitute
+ * a working replica of this object, in a canonical member and byte order,
+ * to aOutputStream.
+ *
+ * NB: a class that implements nsISerializable *must* also implement
+ * nsIClassInfo, in particular nsIClassInfo::GetClassID.
+ */
+ void write(in nsIObjectOutputStream aOutputStream);
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl b/src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl
new file mode 100644
index 00000000..3f0efbf5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISimpleEnumerator.idl
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Used to enumerate over elements defined by its implementor.
+ * Although hasMoreElements() can be called independently of getNext(),
+ * getNext() must be pre-ceeded by a call to hasMoreElements(). There is
+ * no way to "reset" an enumerator, once you obtain one.
+ *
+ * @status FROZEN
+ * @version 1.0
+ */
+
+[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
+interface nsISimpleEnumerator : nsISupports {
+ /**
+ * Called to determine whether or not the enumerator has
+ * any elements that can be returned via getNext(). This method
+ * is generally used to determine whether or not to initiate or
+ * continue iteration over the enumerator, though it can be
+ * called without subsequent getNext() calls. Does not affect
+ * internal state of enumerator.
+ *
+ * @see getNext()
+ * @return PR_TRUE if there are remaining elements in the enumerator.
+ * PR_FALSE if there are no more elements in the enumerator.
+ */
+ boolean hasMoreElements();
+
+ /**
+ * Called to retrieve the next element in the enumerator. The "next"
+ * element is the first element upon the first call. Must be
+ * pre-ceeded by a call to hasMoreElements() which returns PR_TRUE.
+ * This method is generally called within a loop to iterate over
+ * the elements in the enumerator.
+ *
+ * @see hasMoreElements()
+ * @return NS_OK if the call succeeded in returning a non-null
+ * value through the out parameter.
+ * NS_ERROR_FAILURE if there are no more elements
+ * to enumerate.
+ * @return the next element in the enumeration.
+ */
+ nsISupports getNext();
+};
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl b/src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl
new file mode 100644
index 00000000..a7ac9131
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIStringEnumerator.idl
@@ -0,0 +1,58 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Enumerator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsISupports.idl"
+
+/**
+ * Used to enumerate over an ordered list of strings.
+ */
+
+[scriptable, uuid(50d3ef6c-9380-4f06-9fb2-95488f7d141c)]
+interface nsIStringEnumerator : nsISupports
+{
+ boolean hasMore();
+ AString getNext();
+};
+
+[scriptable, uuid(9bdf1010-3695-4907-95ed-83d0410ec307)]
+interface nsIUTF8StringEnumerator : nsISupports
+{
+ boolean hasMore();
+ AUTF8String getNext();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl b/src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl
new file mode 100644
index 00000000..bce9f4bf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISupportsArray.idl
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+#include "nsICollection.idl"
+
+/*
+ * This entire interface is deprecated and should not be used.
+ * See nsIArray and nsIMutableArray for the new implementations.
+ *
+ * http://groups.google.com/groups?q=nsisupportsarray+group:netscape.public.mozilla.xpcom&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=3D779491.3050506%40netscape.com&rnum=2
+ * http://groups.google.com/groups?q=nsisupportsarray+group:netscape.public.mozilla.xpcom&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=al8412%245ab2%40ripley.netscape.com&rnum=8
+ */
+
+native nsISupportsArrayEnumFunc(nsISupportsArrayEnumFunc);
+
+%{C++
+
+class nsIBidirectionalEnumerator;
+
+#define NS_SUPPORTSARRAY_CID \
+{ /* bda17d50-0d6b-11d3-9331-00104ba0fd40 */ \
+ 0xbda17d50, \
+ 0x0d6b, \
+ 0x11d3, \
+ {0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+#define NS_SUPPORTSARRAY_CONTRACTID "@mozilla.org/supports-array;1"
+#define NS_SUPPORTSARRAY_CLASSNAME "Supports Array"
+
+// Enumerator callback function. Return PR_FALSE to stop
+typedef PRBool (*nsISupportsArrayEnumFunc)(nsISupports* aElement, void *aData);
+
+%}
+
+[scriptable, uuid(791eafa0-b9e6-11d1-8031-006008159b5a)]
+interface nsISupportsArray : nsICollection {
+
+ [notxpcom] boolean Equals([const] in nsISupportsArray other);
+
+ [notxpcom] nsISupports ElementAt(in unsigned long aIndex);
+
+ [notxpcom] long IndexOf([const] in nsISupports aPossibleElement);
+ [notxpcom] long IndexOfStartingAt([const] in nsISupports aPossibleElement,
+ in unsigned long aStartIndex);
+ [notxpcom] long LastIndexOf([const] in nsISupports aPossibleElement);
+
+ // xpcom-compatible versions
+ long GetIndexOf(in nsISupports aPossibleElement);
+ long GetIndexOfStartingAt(in nsISupports aPossibleElement,
+ in unsigned long aStartIndex);
+ long GetLastIndexOf(in nsISupports aPossibleElement);
+
+ [notxpcom] boolean InsertElementAt(in nsISupports aElement,
+ in unsigned long aIndex);
+ [notxpcom] boolean ReplaceElementAt(in nsISupports aElement,
+ in unsigned long aIndex);
+
+ [notxpcom] boolean RemoveElementAt(in unsigned long aIndex);
+ [notxpcom] boolean RemoveLastElement([const] in nsISupports aElement);
+
+ // xpcom-compatible versions
+ void DeleteLastElement(in nsISupports aElement);
+ void DeleteElementAt(in unsigned long aIndex);
+
+ [notxpcom] boolean AppendElements(in nsISupportsArray aElements);
+
+ void Compact();
+
+ [notxpcom, noscript]
+ boolean EnumerateForwards(in nsISupportsArrayEnumFunc aFunc,
+ in voidPtr aData);
+ [notxpcom, noscript]
+ boolean EnumerateBackwards(in nsISupportsArrayEnumFunc aFunc,
+ in voidPtr aData);
+
+ nsISupportsArray clone();
+
+ [notxpcom] boolean MoveElement(in long aFrom,
+ in long aTo);
+
+ [notxpcom] boolean InsertElementsAt(in nsISupportsArray aOther,
+ in unsigned long aIndex);
+
+ [notxpcom] boolean RemoveElementsAt(in unsigned long aIndex,
+ in unsigned long aCount);
+
+ [notxpcom] boolean SizeTo(in long aSize);
+
+};
+
+%{C++
+
+// Construct and return a default implementation of nsISupportsArray:
+extern NS_COM nsresult
+NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult);
+
+// Construct and return a default implementation of an enumerator for nsISupportsArrays:
+extern NS_COM nsresult
+NS_NewISupportsArrayEnumerator(nsISupportsArray* array,
+ nsIBidirectionalEnumerator* *aInstancePtrResult);
+
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl b/src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl
new file mode 100644
index 00000000..f1d8bce1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISupportsIterators.idl
@@ -0,0 +1,325 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsISupportsIterators.idl --- IDL defining general purpose iterators */
+
+
+#include "nsISupports.idl"
+
+
+ /*
+ ...
+ */
+
+
+ /**
+ * ...
+ */
+[scriptable, uuid(7330650e-1dd2-11b2-a0c2-9ff86ee97bed)]
+interface nsIOutputIterator : nsISupports
+ {
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(85585e12-1dd2-11b2-a930-f6929058269a)]
+interface nsIInputIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(8da01646-1dd2-11b2-98a7-c7009045be7e)]
+interface nsIForwardIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(948defaa-1dd1-11b2-89f6-8ce81f5ebda9)]
+interface nsIBidirectionalIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Move this iterator to the previous position in the underlying container or sequence.
+ */
+ void stepBackward();
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+ /**
+ * ...
+ */
+[scriptable, uuid(9bd6fdb0-1dd1-11b2-9101-d15375968230)]
+interface nsIRandomAccessIterator : nsISupports
+ {
+ /**
+ * Retrieve (and |AddRef()|) the element this iterator currently points to.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @result a new reference to the element this iterator currently points to (if any)
+ */
+ nsISupports getElement();
+
+ /**
+ * Retrieve (and |AddRef()|) an element at some offset from where this iterator currently points.
+ * The offset may be negative. |getElementAt(0)| is equivalent to |getElement()|.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ * @result a new reference to the indicated element (if any)
+ */
+ nsISupports getElementAt( in PRInt32 anOffset );
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElement( in nsISupports anElementToPut );
+
+ /**
+ * Put |anElementToPut| into the underlying container or sequence at the position |anOffset| away from that currently pointed to by this iterator.
+ * The iterator and the underlying container or sequence cooperate to |Release()|
+ * the replaced element, if any and if necessary, and to |AddRef()| the new element.
+ * |putElementAt(0, obj)| is equivalent to |putElement(obj)|.
+ *
+ * The result is undefined if this iterator currently points outside the
+ * useful range of the underlying container or sequence.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ * @param anElementToPut the element to place into the underlying container or sequence
+ */
+ void putElementAt( in PRInt32 anOffset, in nsISupports anElementToPut );
+
+ /**
+ * Advance this iterator to the next position in the underlying container or sequence.
+ */
+ void stepForward();
+
+ /**
+ * Move this iterator by |anOffset| positions in the underlying container or sequence.
+ * |anOffset| may be negative. |stepForwardBy(1)| is equivalent to |stepForward()|.
+ * |stepForwardBy(0)| is a no-op.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ */
+ void stepForwardBy( in PRInt32 anOffset );
+
+ /**
+ * Move this iterator to the previous position in the underlying container or sequence.
+ */
+ void stepBackward();
+
+ /**
+ * Move this iterator backwards by |anOffset| positions in the underlying container or sequence.
+ * |anOffset| may be negative. |stepBackwardBy(1)| is equivalent to |stepBackward()|.
+ * |stepBackwardBy(n)| is equivalent to |stepForwardBy(-n)|. |stepBackwardBy(0)| is a no-op.
+ *
+ * @param anOffset a |0|-based offset from the position to which this iterator currently points
+ */
+ void stepBackwardBy( in PRInt32 anOffset );
+
+ /**
+ * Test if |anotherIterator| points to the same position in the underlying container or sequence.
+ *
+ * The result is undefined if |anotherIterator| was not created by or for the same underlying container or sequence.
+ *
+ * @param anotherIterator another iterator to compare against, created by or for the same underlying container or sequence
+ * @result true if |anotherIterator| points to the same position in the underlying container or sequence
+ */
+ boolean isEqualTo( in nsISupports anotherIterator );
+
+ /**
+ * Create a new iterator pointing to the same position in the underlying container or sequence to which this iterator currently points.
+ * The returned iterator is suitable for use in a subsequent call to |isEqualTo()| against this iterator.
+ *
+ * @result a new iterator pointing at the same position in the same underlying container or sequence as this iterator
+ */
+ nsISupports clone();
+ };
+
+%{C++
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl b/src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl
new file mode 100644
index 00000000..680e5599
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsISupportsPrimitives.idl
@@ -0,0 +1,304 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsISupports wrappers for single primitive pieces of data. */
+
+#include "nsISupports.idl"
+
+/**
+ * Primitive base interface.
+ *
+ * These first three are pointer types and do data copying
+ * using the nsIMemory. Be careful!
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d0d4b136-1dd1-11b2-9371-f0727ef827c0)]
+interface nsISupportsPrimitive : nsISupports
+{
+ const unsigned short TYPE_ID = 1;
+ const unsigned short TYPE_CSTRING = 2;
+ const unsigned short TYPE_STRING = 3;
+ const unsigned short TYPE_PRBOOL = 4;
+ const unsigned short TYPE_PRUINT8 = 5;
+ const unsigned short TYPE_PRUINT16 = 6;
+ const unsigned short TYPE_PRUINT32 = 7;
+ const unsigned short TYPE_PRUINT64 = 8;
+ const unsigned short TYPE_PRTIME = 9;
+ const unsigned short TYPE_CHAR = 10;
+ const unsigned short TYPE_PRINT16 = 11;
+ const unsigned short TYPE_PRINT32 = 12;
+ const unsigned short TYPE_PRINT64 = 13;
+ const unsigned short TYPE_FLOAT = 14;
+ const unsigned short TYPE_DOUBLE = 15;
+ const unsigned short TYPE_VOID = 16;
+ const unsigned short TYPE_INTERFACE_POINTER = 17;
+
+ readonly attribute unsigned short type;
+};
+
+/**
+ * Scriptable storage for nsID structures
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d18290a0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsID : nsISupportsPrimitive
+{
+ attribute nsIDPtr data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for ASCII strings
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d65ff270-4a1c-11d3-9890-006008962422)]
+interface nsISupportsCString : nsISupportsPrimitive
+{
+ attribute ACString data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for Unicode strings
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(d79dc970-4a1c-11d3-9890-006008962422)]
+interface nsISupportsString : nsISupportsPrimitive
+{
+ attribute AString data;
+ wstring toString();
+};
+
+/**
+ * The rest are truly primitive and are passed by value
+ */
+
+/**
+ * Scriptable storage for booleans
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(ddc3b490-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRBool : nsISupportsPrimitive
+{
+ attribute PRBool data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 8-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(dec2e4e0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint8 : nsISupportsPrimitive
+{
+ attribute PRUint8 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for unsigned 16-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(dfacb090-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint16 : nsISupportsPrimitive
+{
+ attribute PRUint16 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for unsigned 32-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e01dc470-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint32 : nsISupportsPrimitive
+{
+ attribute PRUint32 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 64-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e13567c0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRUint64 : nsISupportsPrimitive
+{
+ attribute PRUint64 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for NSPR date/time values
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e2563630-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRTime : nsISupportsPrimitive
+{
+ attribute PRTime data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for single character values
+ * (often used to store an ASCII character)
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e2b05e40-4a1c-11d3-9890-006008962422)]
+interface nsISupportsChar : nsISupportsPrimitive
+{
+ attribute char data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 16-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e30d94b0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRInt16 : nsISupportsPrimitive
+{
+ attribute PRInt16 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 32-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e36c5250-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRInt32 : nsISupportsPrimitive
+{
+ attribute PRInt32 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for 64-bit integers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(e3cb0ff0-4a1c-11d3-9890-006008962422)]
+interface nsISupportsPRInt64 : nsISupportsPrimitive
+{
+ attribute PRInt64 data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for floating point numbers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(abeaa390-4ac0-11d3-baea-00805f8a5dd7)]
+interface nsISupportsFloat : nsISupportsPrimitive
+{
+ attribute float data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for doubles
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(b32523a0-4ac0-11d3-baea-00805f8a5dd7)]
+interface nsISupportsDouble : nsISupportsPrimitive
+{
+ attribute double data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for generic pointers
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(464484f0-568d-11d3-baf8-00805f8a5dd7)]
+interface nsISupportsVoid : nsISupportsPrimitive
+{
+ [noscript] attribute voidPtr data;
+ string toString();
+};
+
+/**
+ * Scriptable storage for other XPCOM objects
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(995ea724-1dd1-11b2-9211-c21bdd3e7ed0)]
+interface nsISupportsInterfacePointer : nsISupportsPrimitive
+{
+ attribute nsISupports data;
+ attribute nsIDPtr dataIID;
+
+ string toString();
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl b/src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl
new file mode 100644
index 00000000..f0495a35
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsITimelineService.idl
@@ -0,0 +1,242 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#ifdef MOZ_TIMELINE
+%}
+
+/**
+ * nsITimelineService is used to constuct a timeline of program
+ * execution. The timeline is output to a file, either stderr or the
+ * value of the environment variable NS_TIMELINE_LOG_FILE. On the
+ * Mac, the timeline is output to the file named "timeline.txt". The
+ * reason it's different on the Mac is that the Mac environment
+ * initialization code happens after timeline initialization code.
+ *
+ * If NS_TIMELINE_INIT_TIME is set in the environment, that will be
+ * used as the time of startup; otherwise the current time when mark()
+ * is first called will be used.
+ *
+ * mark() is used to put marks on the timeline.
+ *
+ * indent() and outdent() are used to format the timeline a bit to
+ * show nesting. This doesn't produce perfect results in the face of
+ * asychrony and multiple threads.
+ *
+ * enter() and leave() are convenience functions that add marks to the
+ * timeline and do indentation.
+ *
+ * startTimer() and stopTimer() control named stop watches. If
+ * startTimer() is called more than once, an equal number of
+ * stopTimer() calls are needed to actually stop the timer. This
+ * makes these timers slightly useful in a threaded environment.
+ *
+ * markTimer() puts a mark on the timeline containing the total for
+ * the named timer.
+ *
+ * Don't use nsITimelineService in C++ code; use the NS_TIMELINE
+ * macros instead. nsITimelineService exists so that JavaScript code
+ * can mark the timeline.
+ */
+[scriptable, uuid(93276790-3daf-11d5-b67d-000064657374)]
+interface nsITimelineService : nsISupports
+{
+ /**
+ * mark()
+ * Print "<elapsed time>: <text>\n" in the timeline log file.
+ */
+ void mark(in string text);
+
+ /**
+ * causes subsequent marks to be indented for a more readable
+ * report.
+ */
+ void indent();
+
+ /**
+ * Causes subsequent marks to be outdented.
+ */
+ void outdent();
+
+ /**
+ * enter/leave bracket code with "<text>..." and "...<text>" as
+ * well as indentation.
+ */
+ void enter(in string text);
+ void leave(in string text);
+
+ void startTimer(in string timerName);
+
+ void stopTimer(in string timerName);
+
+ void markTimer(in string timerName);
+
+ void resetTimer(in string timerName);
+
+ // Mark a timer, plus an additional comment
+ void markTimerWithComment(in string timerName, in string comment);
+};
+
+%{C++
+#endif /* MOZ_TIMELINE */
+%}
+
+
+%{C++
+
+#ifdef MOZ_TIMELINE
+
+/*
+ * These are equivalent to the corresponding nsITimelineService
+ * methods, and can be called before XPCOM is initialized.
+ */
+extern "C" NS_COM nsresult NS_TimelineMark(const char *text, ...);
+extern "C" NS_COM nsresult NS_TimelineForceMark(const char *text, ...);
+extern "C" NS_COM nsresult NS_TimelineStartTimer(const char *timerName);
+extern "C" NS_COM nsresult NS_TimelineStopTimer(const char *timerName);
+extern "C" NS_COM nsresult NS_TimelineResetTimer(const char *timerName);
+extern "C" NS_COM nsresult NS_TimelineMarkTimer(const char *timerName, const char *str=nsnull);
+extern "C" NS_COM nsresult NS_TimelineIndent();
+extern "C" NS_COM nsresult NS_TimelineOutdent();
+extern "C" NS_COM nsresult NS_TimelineEnter(const char *text);
+extern "C" NS_COM nsresult NS_TimelineLeave(const char *text);
+
+/*
+ * Use these macros for the above calls so we can easily compile them
+ * out.
+ */
+#define NS_TIMELINE_MARK(text) NS_TimelineMark(text)
+#define NS_TIMELINE_MARKV(args) NS_TimelineMark args
+#define NS_TIMELINE_INDENT() NS_TimelineIndent()
+#define NS_TIMELINE_OUTDENT() NS_TimelineOutdent()
+#define NS_TIMELINE_ENTER(text) NS_TimelineEnter(text)
+#define NS_TIMELINE_LEAVE(text) NS_TimelineLeave(text)
+#define NS_TIMELINE_START_TIMER(timerName) NS_TimelineStartTimer(timerName)
+#define NS_TIMELINE_STOP_TIMER(timerName) NS_TimelineStopTimer(timerName)
+#define NS_TIMELINE_MARK_TIMER(timerName) NS_TimelineMarkTimer(timerName)
+#define NS_TIMELINE_RESET_TIMER(timerName) NS_TimelineResetTimer(timerName)
+#define NS_TIMELINE_MARK_TIMER1(timerName, str) NS_TimelineMarkTimer(timerName, str)
+
+/*
+ * Helper class to time functions. Use only static strings.
+ */
+class nsFunctionTimer {
+public:
+ const char *mTimer;
+ PRBool mMark;
+ const char *mMarkStr;
+ nsFunctionTimer(const char *timer, PRBool mark = PR_TRUE, const char *markStr = nsnull)
+ : mTimer(timer), mMark(mark), mMarkStr(markStr)
+ {
+ NS_TIMELINE_START_TIMER(mTimer);
+ }
+
+ ~nsFunctionTimer()
+ {
+ NS_TIMELINE_STOP_TIMER(mTimer);
+ if (mMark)
+ if (mMarkStr)
+ NS_TIMELINE_MARK_TIMER1(mTimer, mMarkStr);
+ else
+ NS_TIMELINE_MARK_TIMER(mTimer);
+ }
+};
+
+/*
+ * NS_TIMELINE_MARK_ macros for various data types. Each of these
+ * macros replaces "%s" in its "text" argument with a string
+ * representation of its last argument.
+ *
+ * Please feel free to add more NS_TIMELINE_MARK_ macros for
+ * various data types so that code using NS_TIMELINE is uncluttered.
+ * Don't forget the empty versions in the #else section below for
+ * non-timeline builds.
+ */
+#define NS_TIMELINE_MARK_URI(text, uri) \
+ { \
+ nsCAutoString spec; \
+ if (uri) { \
+ uri->GetSpec(spec); \
+ } \
+ if (!spec.IsEmpty()) { \
+ NS_TimelineMark(text, spec.get()); \
+ } else { \
+ NS_TimelineMark(text, "??"); \
+ } \
+ }
+
+#define NS_TIMELINE_MARK_CHANNEL(text, channel) \
+ { \
+ nsCOMPtr<nsIURI> uri; \
+ if (channel) { \
+ channel->GetURI(getter_AddRefs(uri)); \
+ } \
+ NS_TIMELINE_MARK_URI(text, uri); \
+ }
+
+#define NS_TIMELINE_MARK_LOADER(text, loader) \
+ { \
+ nsCOMPtr<nsIRequest> request; \
+ loader->GetRequest(getter_AddRefs(request)); \
+ nsCOMPtr<nsIChannel> channel(do_QueryInterface(request)); \
+ NS_TIMELINE_MARK_CHANNEL(text, channel); \
+ }
+#define NS_TIMELINE_MARK_FUNCTION(timer) nsFunctionTimer functionTimer(timer)
+#define NS_TIMELINE_MARK_FUNCTION1(timer, str) nsFunctionTimer functionTimer(timer, PR_TRUE, str)
+#define NS_TIMELINE_TIME_FUNCTION(timer) nsFunctionTimer functionTimer(timer, PR_FALSE) /* no mark, only time */
+
+#else /* !defined(MOZ_TIMELINE) */
+#define NS_TIMELINE_MARK(text)
+#define NS_TIMELINE_MARKV(args)
+#define NS_TIMELINE_INDENT()
+#define NS_TIMELINE_OUTDENT()
+#define NS_TIMELINE_START_TIMER(timerName)
+#define NS_TIMELINE_STOP_TIMER(timerName)
+#define NS_TIMELINE_MARK_TIMER(timerName)
+#define NS_TIMELINE_RESET_TIMER(timerName)
+#define NS_TIMELINE_MARK_TIMER1(timerName, str)
+#define NS_TIMELINE_ENTER(text)
+#define NS_TIMELINE_LEAVE(text)
+#define NS_TIMELINE_MARK_URI(text, uri)
+#define NS_TIMELINE_MARK_FUNCTION(timer)
+#define NS_TIMELINE_TIME_FUNCTION(timer)
+#define NS_TIMELINE_MARK_CHANNEL(text, channel)
+#define NS_TIMELINE_MARK_LOADER(text, loader);
+#endif /* defined(MOZ_TIMELINE) */
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h
new file mode 100644
index 00000000..dae89021
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIUnicharBuffer.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsIUnicharBuffer_h___
+#define nsIUnicharBuffer_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+#define NS_IUNICHARBUFFER_IID \
+{ 0x14cf6970, 0x93b5, 0x11d1, \
+ {0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} }
+
+/// Interface to a buffer that holds unicode characters
+class nsIUnicharBuffer : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IUNICHARBUFFER_IID);
+
+ NS_IMETHOD Init(PRUint32 aBufferSize) = 0;
+ NS_IMETHOD_(PRInt32) GetLength() const = 0;
+ NS_IMETHOD_(PRInt32) GetBufferSize() const = 0;
+ NS_IMETHOD_(PRUnichar*) GetBuffer() const = 0;
+ NS_IMETHOD_(PRBool) Grow(PRInt32 aNewSize) = 0;
+};
+
+/// Factory method for nsIUnicharBuffer.
+extern NS_COM nsresult
+NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize = 0);
+
+#define NS_UNICHARBUFFER_CID \
+{ /* c81fd8f0-0d6b-11d3-9331-00104ba0fd40 */ \
+ 0xc81fd8f0, \
+ 0x0d6b, \
+ 0x11d3, \
+ {0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+#endif /* nsIUnicharBuffer_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl b/src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl
new file mode 100644
index 00000000..2c9d9e96
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsIVariant.idl
@@ -0,0 +1,188 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The long avoided variant support for xpcom. */
+
+#include "nsISupports.idl"
+
+[scriptable,uuid(4d12e540-83d7-11d5-90ed-0010a4e73d9a)]
+interface nsIDataType : nsISupports
+{
+ // These MUST match the declarations in xpt_struct.h.
+ // Otherwise the world is likely to explode.
+ // From xpt_struct.h ...
+ const PRUint16 VTYPE_INT8 = 0; // TD_INT8 = 0,
+ const PRUint16 VTYPE_INT16 = 1; // TD_INT16 = 1,
+ const PRUint16 VTYPE_INT32 = 2; // TD_INT32 = 2,
+ const PRUint16 VTYPE_INT64 = 3; // TD_INT64 = 3,
+ const PRUint16 VTYPE_UINT8 = 4; // TD_UINT8 = 4,
+ const PRUint16 VTYPE_UINT16 = 5; // TD_UINT16 = 5,
+ const PRUint16 VTYPE_UINT32 = 6; // TD_UINT32 = 6,
+ const PRUint16 VTYPE_UINT64 = 7; // TD_UINT64 = 7,
+ const PRUint16 VTYPE_FLOAT = 8; // TD_FLOAT = 8,
+ const PRUint16 VTYPE_DOUBLE = 9; // TD_DOUBLE = 9,
+ const PRUint16 VTYPE_BOOL = 10; // TD_BOOL = 10,
+ const PRUint16 VTYPE_CHAR = 11; // TD_CHAR = 11,
+ const PRUint16 VTYPE_WCHAR = 12; // TD_WCHAR = 12,
+ const PRUint16 VTYPE_VOID = 13; // TD_VOID = 13,
+ const PRUint16 VTYPE_ID = 14; // TD_PNSIID = 14,
+ const PRUint16 VTYPE_DOMSTRING = 15; // TD_DOMSTRING = 15,
+ const PRUint16 VTYPE_CHAR_STR = 16; // TD_PSTRING = 16,
+ const PRUint16 VTYPE_WCHAR_STR = 17; // TD_PWSTRING = 17,
+ const PRUint16 VTYPE_INTERFACE = 18; // TD_INTERFACE_TYPE = 18,
+ const PRUint16 VTYPE_INTERFACE_IS = 19; // TD_INTERFACE_IS_TYPE = 19,
+ const PRUint16 VTYPE_ARRAY = 20; // TD_ARRAY = 20,
+ const PRUint16 VTYPE_STRING_SIZE_IS = 21; // TD_PSTRING_SIZE_IS = 21,
+ const PRUint16 VTYPE_WSTRING_SIZE_IS = 22; // TD_PWSTRING_SIZE_IS = 22,
+ const PRUint16 VTYPE_UTF8STRING = 23; // TD_UTF8STRING = 23,
+ const PRUint16 VTYPE_CSTRING = 24; // TD_CSTRING = 24,
+ const PRUint16 VTYPE_ASTRING = 25; // TD_ASTRING = 25,
+ const PRUint16 VTYPE_EMPTY_ARRAY = 254;
+ const PRUint16 VTYPE_EMPTY = 255;
+};
+
+
+/**
+ * XPConnect has magic to transparently convert between nsIVariant and JS types.
+ * We mark the interface [scriptable] so that JS can use methods
+ * that refer to this interface. But we mark all the methods and attributes
+ * [noscript] since any nsIVariant object will be automatically converted to a
+ * JS type anyway.
+ */
+
+[scriptable, uuid(6c9eb060-8c6a-11d5-90f3-0010a4e73d9a)]
+interface nsIVariant : nsISupports
+{
+ [noscript] readonly attribute PRUint16 dataType;
+
+ [noscript] PRUint8 getAsInt8();
+ [noscript] PRInt16 getAsInt16();
+ [noscript] PRInt32 getAsInt32();
+ [noscript] PRInt64 getAsInt64();
+ [noscript] PRUint8 getAsUint8();
+ [noscript] PRUint16 getAsUint16();
+ [noscript] PRUint32 getAsUint32();
+ [noscript] PRUint64 getAsUint64();
+ [noscript] float getAsFloat();
+ [noscript] double getAsDouble();
+ [noscript] PRBool getAsBool();
+ [noscript] char getAsChar();
+ [noscript] wchar getAsWChar();
+ [notxpcom] nsresult getAsID(out nsID retval);
+ [noscript] AString getAsAString();
+ [noscript] DOMString getAsDOMString();
+ [noscript] ACString getAsACString();
+ [noscript] AUTF8String getAsAUTF8String();
+ [noscript] string getAsString();
+ [noscript] wstring getAsWString();
+ [noscript] nsISupports getAsISupports();
+
+ [noscript] void getAsInterface(out nsIIDPtr iid,
+ [iid_is(iid), retval] out nsQIResult iface);
+
+ [notxpcom] nsresult getAsArray(out PRUint16 type, out nsIID iid,
+ out PRUint32 count, out voidPtr ptr);
+
+ [noscript] void getAsStringWithSize(out PRUint32 size,
+ [size_is(size), retval] out string str);
+
+ [noscript] void getAsWStringWithSize(out PRUint32 size,
+ [size_is(size), retval] out wstring str);
+};
+
+/**
+ * An object that implements nsIVariant may or may NOT also implement this
+ * nsIWritableVariant.
+ *
+ * If the 'writable' attribute is false then attempts to call any of the 'set'
+ * methods can be expected to fail. Setting the 'writable' attribute may or
+ * may not succeed.
+ *
+ */
+
+[scriptable, uuid(5586a590-8c82-11d5-90f3-0010a4e73d9a)]
+interface nsIWritableVariant : nsIVariant
+{
+ attribute PRBool writable;
+
+ void setAsInt8(in PRUint8 aValue);
+ void setAsInt16(in PRInt16 aValue);
+ void setAsInt32(in PRInt32 aValue);
+ void setAsInt64(in PRInt64 aValue);
+ void setAsUint8(in PRUint8 aValue);
+ void setAsUint16(in PRUint16 aValue);
+ void setAsUint32(in PRUint32 aValue);
+ void setAsUint64(in PRUint64 aValue);
+ void setAsFloat(in float aValue);
+ void setAsDouble(in double aValue);
+ void setAsBool(in PRBool aValue);
+ void setAsChar(in char aValue);
+ void setAsWChar(in wchar aValue);
+ void setAsID(in nsIDRef aValue);
+ void setAsAString(in AString aValue);
+ void setAsDOMString(in DOMString aValue);
+ void setAsACString(in ACString aValue);
+ void setAsAUTF8String(in AUTF8String aValue);
+ void setAsString(in string aValue);
+ void setAsWString(in wstring aValue);
+ void setAsISupports(in nsISupports aValue);
+
+ void setAsInterface(in nsIIDRef iid,
+ [iid_is(iid)] in nsQIResult iface);
+
+ [noscript] void setAsArray(in PRUint16 type, in nsIIDPtr iid,
+ in PRUint32 count, in voidPtr ptr);
+
+ void setAsStringWithSize(in PRUint32 size,
+ [size_is(size)] in string str);
+
+ void setAsWStringWithSize(in PRUint32 size,
+ [size_is(size)] in wstring str);
+
+ void setAsVoid();
+ void setAsEmpty();
+ void setAsEmptyArray();
+
+ void setFromVariant(in nsIVariant aValue);
+};
+
+%{C++
+// The contractID for the generic implementation built in to xpcom.
+#define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsInt64.h b/src/libs/xpcom18a4/xpcom/ds/nsInt64.h
new file mode 100644
index 00000000..c7421548
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsInt64.h
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsInt64_h__
+#define nsInt64_h__
+
+#include "prlong.h"
+#include "nscore.h"
+
+/**
+ * This class encapsulates full 64-bit integer functionality and
+ * provides simple arithmetic and conversion operations.
+ */
+
+// If you ever decide that you need to add a non-inline method to this
+// class, be sure to change the class declaration to "class NS_BASE
+// nsInt64".
+
+template<class T>
+class nsTInt64
+{
+public: //XXX should be private
+ T mValue;
+
+public:
+ /**
+ * Construct a new 64-bit integer.
+ */
+ nsTInt64(void) : mValue(LL_ZERO) {
+ }
+
+ /**
+ * Construct a new 64-bit integer from a 32-bit signed integer
+ */
+ nsTInt64(const PRInt32 aInt32) {
+ LL_I2L(mValue, aInt32);
+ }
+
+ /**
+ * Construct a new 64-bit integer from a 32-bit unsigned integer
+ */
+ nsTInt64(const PRUint32 aUint32) {
+ LL_UI2L(mValue, aUint32);
+ }
+
+ /**
+ * Construct a new 64-bit integer from a floating point value.
+ */
+ nsTInt64(const PRFloat64 aFloat64) {
+ LL_D2L(mValue, aFloat64);
+ }
+
+ /**
+ * Construct a new 64-bit integer from a native 64-bit integer
+ */
+ nsTInt64(const T aInt64) : mValue(aInt64) {
+ }
+
+ /**
+ * Construct a new 64-bit integer from another 64-bit integer
+ */
+ nsTInt64(const nsTInt64& aObject) : mValue(aObject.mValue) {
+ }
+
+ // ~nsTInt64(void) -- XXX destructor unnecessary
+
+ /**
+ * Assign a 64-bit integer to another 64-bit integer
+ */
+ const nsTInt64& operator =(const nsTInt64& aObject) {
+ mValue = aObject.mValue;
+ return *this;
+ }
+
+ /**
+ * Convert a 64-bit integer to a signed 32-bit value
+ */
+ operator PRInt32(void) const {
+ PRInt32 result;
+ LL_L2I(result, mValue);
+ return result;
+ }
+
+ /**
+ * Convert a 64-bit integer to an unsigned 32-bit value
+ */
+ operator PRUint32(void) const {
+ PRUint32 result;
+ LL_L2UI(result, mValue);
+ return result;
+ }
+
+ /**
+ * Convert a 64-bit integer to a floating point value
+ */
+ operator PRFloat64(void) const {
+ PRFloat64 result;
+ LL_L2D(result, mValue);
+ return result;
+ }
+
+ /**
+ * Convert a 64-bit integer to a native 64-bit integer.
+ */
+ operator T() const {
+ return mValue;
+ }
+
+ /**
+ * Perform unary negation on a 64-bit integer.
+ */
+ const nsTInt64 operator -(void) {
+ nsTInt64 result;
+ LL_NEG(result.mValue, mValue);
+ return result;
+ }
+
+ // Arithmetic operators
+
+ /**
+ * Increment a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator +=(const nsTInt64& aObject) {
+ LL_ADD(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Decrement a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator -=(const nsTInt64& aObject) {
+ LL_SUB(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Multiply a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator *=(const nsTInt64& aObject) {
+ LL_MUL(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Divide a 64-bit integer by a 64-bit integer amount.
+ */
+ nsTInt64& operator /=(const nsTInt64& aObject) {
+ LL_DIV(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Compute the modulus of a 64-bit integer to a 64-bit value.
+ */
+ nsTInt64& operator %=(const nsTInt64& aObject) {
+ LL_MOD(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Shift a 64-bit integer left.
+ */
+ nsTInt64& operator <<=(int aCount) {
+ LL_SHL(mValue, mValue, aCount);
+ return *this;
+ }
+
+ /**
+ * Shift a 64-bit signed integer right.
+ */
+ nsTInt64& operator >>=(int aCount) {
+ LL_SHR(mValue, mValue, aCount);
+ return *this;
+ }
+
+ // Comparison operators
+ /**
+ * Add two 64-bit integers.
+ */
+ inline const nsTInt64
+ operator +(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) += aObject2;
+ }
+
+ /**
+ * Subtract one 64-bit integer from another.
+ */
+ inline const nsTInt64
+ operator -(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) -= aObject2;
+ }
+
+ /**
+ * Multiply two 64-bit integers
+ */
+ inline const nsTInt64
+ operator *(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) *= aObject2;
+ }
+
+ /**
+ * Divide one 64-bit integer by another
+ */
+ inline const nsTInt64
+ operator /(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) /= aObject2;
+ }
+
+ /**
+ * Compute the modulus of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator %(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) %= aObject2;
+ }
+
+ /**
+ * Shift left a 64-bit integer
+ */
+ inline const nsTInt64
+ operator <<(int aCount) const {
+ return nsTInt64(*this) <<= aCount;
+ }
+
+ /**
+ * Shift right a signed 64-bit integer
+ */
+ inline const nsTInt64
+ operator >>(int aCount) const {
+ return nsTInt64(*this) >>= aCount;
+ }
+
+ /**
+ * Determine if two 64-bit integers are equal
+ */
+ inline PRBool
+ operator ==(const nsTInt64& aObject2) const {
+ return LL_EQ(mValue, aObject2.mValue);
+ }
+
+ /**
+ * Determine if two 64-bit integers are not equal
+ */
+ inline PRBool
+ operator !=(const nsTInt64& aObject2) const {
+ return LL_NE(mValue, aObject2.mValue);
+ }
+
+
+ /**
+ * Perform a bitwise AND of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator &(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) &= aObject2;
+ }
+
+ /**
+ * Perform a bitwise OR of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator |(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) |= aObject2;
+ }
+
+ /**
+ * Perform a bitwise XOR of two 64-bit integers
+ */
+ inline const nsTInt64
+ operator ^(const nsTInt64& aObject2) const {
+ return nsTInt64(*this) ^= aObject2;
+ }
+
+ // Bitwise operators
+
+ /**
+ * Compute the bitwise NOT of a 64-bit integer
+ */
+ const nsTInt64 operator ~(void) const {
+ nsTInt64 result;
+ LL_NOT(result.mValue, mValue);
+ return result;
+ }
+
+ /**
+ * Compute the bitwise AND with another 64-bit integer
+ */
+ nsTInt64& operator &=(const nsTInt64& aObject) {
+ LL_AND(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Compute the bitwise OR with another 64-bit integer
+ */
+ nsTInt64& operator |=(const nsTInt64& aObject) {
+ LL_OR(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+
+ /**
+ * Compute the bitwise XOR with another 64-bit integer
+ */
+ nsTInt64& operator ^=(const nsTInt64& aObject) {
+ LL_XOR(mValue, mValue, aObject.mValue);
+ return *this;
+ }
+};
+
+typedef nsTInt64<PRInt64> nsInt64;
+typedef nsTInt64<PRUint64> nsUint64;
+
+/**
+ * Determine if one 64-bit integer is strictly greater than another, using signed values
+ */
+inline PRBool
+operator >(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return LL_CMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+inline PRBool
+operator >(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return LL_UCMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+/**
+ * Determine if one 64-bit integer is greater than or equal to another, using signed values
+ */
+inline PRBool
+operator >=(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return ! LL_CMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+inline PRBool
+operator >=(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return ! LL_UCMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+/**
+ * Determine if one 64-bit integer is strictly less than another, using signed values
+ */
+inline PRBool
+operator <(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return LL_CMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+inline PRBool
+operator <(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return LL_UCMP(aObject1.mValue, <, aObject2.mValue);
+}
+
+/**
+ * Determine if one 64-bit integers is less than or equal to another, using signed values
+ */
+inline PRBool
+operator <=(const nsInt64& aObject1, const nsInt64& aObject2) {
+ return ! LL_CMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+inline PRBool
+operator <=(const nsUint64& aObject1, const nsUint64& aObject2) {
+ return ! LL_UCMP(aObject1.mValue, >, aObject2.mValue);
+}
+
+#endif // nsInt64_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h
new file mode 100644
index 00000000..68b06d66
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsInterfaceHashtable.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsInterfaceHashtable_h__
+#define nsInterfaceHashtable_h__
+
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsCOMPtr.h"
+
+/**
+ * templated hashtable class maps keys to interface pointers.
+ * See nsBaseHashtable for complete declaration.
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Interface the interface-type being wrapped
+ * @see nsDataHashtable, nsClassHashtable
+ */
+template<class KeyClass,class Interface>
+class nsInterfaceHashtable :
+ public nsBaseHashtable< KeyClass, nsCOMPtr<Interface> , Interface* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef Interface* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ /**
+ * Gets a weak reference to the hashtable entry.
+ * @param aFound If not nsnull, will be set to PR_TRUE if the entry is found,
+ * to PR_FALSE otherwise.
+ * @return The entry, or nsnull if not found. Do not release this pointer!
+ */
+ Interface* GetWeak(KeyType aKey, PRBool* aFound = nsnull) const;
+};
+
+/**
+ * Thread-safe version of nsInterfaceHashtable
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param Interface the interface-type being wrapped
+ */
+template<class KeyClass,class Interface>
+class nsInterfaceHashtableMT :
+ public nsBaseHashtableMT< KeyClass, nsCOMPtr<Interface> , Interface* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef Interface* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ // GetWeak does not make sense on a multi-threaded hashtable, where another
+ // thread may remove the entry (and hence release it) as soon as GetWeak
+ // returns
+};
+
+
+//
+// nsInterfaceHashtable definitions
+//
+
+template<class KeyClass,class Interface>
+PRBool
+nsInterfaceHashtable<KeyClass,Interface>::Get
+ (KeyType aKey, UserDataType* pInterface) const
+{
+ typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pInterface)
+ {
+ *pInterface = ent->mData;
+
+ NS_IF_ADDREF(*pInterface);
+ }
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pInterface to null
+ // so that it is a valid XPCOM getter
+ if (pInterface)
+ *pInterface = nsnull;
+
+ return PR_FALSE;
+}
+
+template<class KeyClass,class Interface>
+Interface*
+nsInterfaceHashtable<KeyClass,Interface>::GetWeak
+ (KeyType aKey, PRBool* aFound) const
+{
+ typename nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (aFound)
+ *aFound = PR_TRUE;
+
+ return ent->mData;
+ }
+
+ // Key does not exist, return nsnull and set aFound to PR_FALSE
+ if (aFound)
+ *aFound = PR_FALSE;
+ return nsnull;
+}
+
+//
+// nsInterfaceHashtableMT definitions
+//
+
+template<class KeyClass,class Interface>
+PRBool
+nsInterfaceHashtableMT<KeyClass,Interface>::Get
+ (KeyType aKey, UserDataType* pInterface) const
+{
+ PR_Lock(this->mLock);
+
+ typename nsBaseHashtableMT<KeyClass, nsCOMPtr<Interface>, Interface*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pInterface)
+ {
+ *pInterface = ent->mData;
+
+ NS_IF_ADDREF(*pInterface);
+ }
+
+ PR_Unlock(this->mLock);
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pInterface to null
+ // so that it is a valid XPCOM getter
+ if (pInterface)
+ *pInterface = nsnull;
+
+ PR_Unlock(this->mLock);
+
+ return PR_FALSE;
+}
+
+#endif // nsInterfaceHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h b/src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h
new file mode 100644
index 00000000..761c28c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsManifestLineReader.h
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsManifestLineReader_h__
+#define nsManifestLineReader_h__
+
+#include "nspr.h"
+#include "nsDebug.h"
+
+class nsManifestLineReader
+{
+public:
+ nsManifestLineReader() : mBase(nsnull) {}
+ ~nsManifestLineReader() {}
+
+ void Init(char* base, PRUint32 flen)
+ {
+ mBase = mCur = mNext = base;
+ mLength = 0;
+ mLimit = base + flen;
+ }
+
+ PRBool NextLine()
+ {
+ if(mNext >= mLimit)
+ return PR_FALSE;
+
+ mCur = mNext;
+ mLength = 0;
+
+ while(mNext < mLimit)
+ {
+ if(IsEOL(*mNext))
+ {
+ *mNext = '\0';
+ for(++mNext; mNext < mLimit; ++mNext)
+ if(!IsEOL(*mNext))
+ break;
+ return PR_TRUE;
+ }
+ ++mNext;
+ ++mLength;
+ }
+ return PR_FALSE;
+ }
+
+ int ParseLine(char** chunks, int* lengths, int maxChunks)
+ {
+ NS_ASSERTION(mCur && maxChunks && chunks, "bad call to ParseLine");
+ int found = 0;
+ chunks[found++] = mCur;
+
+ if(found < maxChunks)
+ {
+ char *lastchunk = mCur;
+ int *lastlength = lengths;
+ for(char* cur = mCur; *cur; cur++)
+ {
+ if(*cur == ',')
+ {
+ *cur = 0;
+ // always fill in the previous chunk's length
+ *lastlength++ = cur - lastchunk;
+ chunks[found++] = lastchunk = cur+1;
+ if(found == maxChunks)
+ break;
+ }
+ }
+ // crazy pointer math - calculate the length of the final chunk
+ *lastlength = (mCur + mLength) - lastchunk;
+ }
+ return found;
+ }
+
+ char* LinePtr() {return mCur;}
+ PRUint32 LineLength() {return mLength;}
+
+ PRBool IsEOL(char c) {return c == '\n' || c == '\r';}
+private:
+ char* mCur;
+ PRUint32 mLength;
+ char* mNext;
+ char* mBase;
+ char* mLimit;
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp
new file mode 100644
index 00000000..51fb04b5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.cpp
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define NS_WEAK_OBSERVERS
+
+#include "pratom.h"
+#include "nsString.h"
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsIWeakReference.h"
+#include "nsEnumeratorUtils.h"
+#include "nsObserverList.h"
+
+nsObserverList::nsObserverList()
+{
+ MOZ_COUNT_CTOR(nsObserverList);
+ mLock = PR_NewLock();
+}
+
+nsObserverList::~nsObserverList(void)
+{
+ MOZ_COUNT_DTOR(nsObserverList);
+ PR_DestroyLock(mLock);
+}
+
+nsresult
+nsObserverList::AddObserver(nsIObserver* anObserver, PRBool ownsWeak)
+{
+ nsresult rv;
+ PRBool inserted;
+
+ NS_ENSURE_ARG(anObserver);
+
+ nsAutoLock lock(mLock);
+
+ if (!mObserverList) {
+ rv = NS_NewISupportsArray(getter_AddRefs(mObserverList));
+ if (NS_FAILED(rv)) return rv;
+ }
+
+#ifdef NS_WEAK_OBSERVERS
+ nsCOMPtr<nsISupports> observerRef;
+ if (ownsWeak) {
+ nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(anObserver);
+ NS_ASSERTION(weakRefFactory, "AddObserver: trying weak object that doesnt support nsIWeakReference");
+ if ( weakRefFactory )
+ observerRef = getter_AddRefs(NS_STATIC_CAST(nsISupports*, NS_GetWeakReference(weakRefFactory)));
+ } else {
+#if DEBUG_dougt_xxx
+ // if you are hitting this assertion, contact dougt@netscape.com. There may be a ownership problem caused by his checkin to freeze nsIObserver
+ nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(anObserver);
+ NS_ASSERTION(!weakRefFactory, "Your object supports weak references, but is being added with a strong reference");
+#endif
+ observerRef = anObserver;
+ }
+ if (!observerRef)
+ return NS_ERROR_FAILURE;
+
+ inserted = mObserverList->AppendElement(observerRef);
+#else
+ if (*anObserver)
+ inserted = mObserverList->AppendElement(*anObserver);
+#endif
+ return inserted ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsObserverList::RemoveObserver(nsIObserver* anObserver)
+{
+ PRBool removed = PR_FALSE;
+
+ NS_ENSURE_ARG(anObserver);
+
+ nsAutoLock lock(mLock);
+
+ if (!mObserverList)
+ return NS_ERROR_FAILURE;
+
+#ifdef NS_WEAK_OBSERVERS
+ nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(anObserver);
+ nsCOMPtr<nsISupports> observerRef;
+ if (weakRefFactory) {
+ observerRef = getter_AddRefs(NS_STATIC_CAST(nsISupports*, NS_GetWeakReference(weakRefFactory)));
+ if (observerRef)
+ removed = mObserverList->RemoveElement(observerRef);
+ if (!removed)
+ observerRef = anObserver;
+ } else
+ observerRef = anObserver;
+
+ if (!removed && observerRef)
+ removed = mObserverList->RemoveElement(observerRef);
+#else
+ if (*anObserver)
+ removed = mObserverList->RemoveElement(*anObserver);
+#endif
+ return removed ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsObserverList::GetObserverList(nsISimpleEnumerator** anEnumerator)
+{
+ nsAutoLock lock(mLock);
+
+ ObserverListEnumerator * enumerator= new ObserverListEnumerator(mObserverList);
+ *anEnumerator = enumerator;
+ if (!enumerator)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(enumerator);
+ return NS_OK;
+}
+
+
+ObserverListEnumerator::ObserverListEnumerator(nsISupportsArray* aValueArray)
+ : mValueArray(aValueArray), mIndex(0)
+{
+ if (mValueArray) {
+ NS_ADDREF(mValueArray);
+ PRUint32 total;
+ mValueArray->Count(&total);
+ mIndex = PRInt32(total);
+ }
+}
+
+ObserverListEnumerator::~ObserverListEnumerator(void)
+{
+ NS_IF_RELEASE(mValueArray);
+}
+
+NS_IMPL_ISUPPORTS1(ObserverListEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+ObserverListEnumerator::HasMoreElements(PRBool* aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = PR_FALSE;
+ return NS_OK;
+ }
+
+ *aResult = (mIndex > 0);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ObserverListEnumerator::GetNext(nsISupports** aResult)
+{
+ NS_PRECONDITION(aResult != 0, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ if (!mValueArray) {
+ *aResult = nsnull;
+ return NS_OK;
+ }
+
+ if (mIndex <= 0 )
+ return NS_ERROR_UNEXPECTED;
+
+ mValueArray->GetElementAt(--mIndex, aResult);
+ if (*aResult) {
+ nsCOMPtr<nsIWeakReference> weakRefFactory = do_QueryInterface(*aResult);
+ if ( weakRefFactory ) {
+ nsCOMPtr<nsISupports> weakref = do_QueryReferent(weakRefFactory);
+ NS_RELEASE(*aResult);
+ NS_IF_ADDREF(*aResult = weakref);
+
+ return NS_OK;
+ }
+ }
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverList.h b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.h
new file mode 100644
index 00000000..521ce1c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverList.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsObserverList_h___
+#define nsObserverList_h___
+
+#include "nsIObserver.h"
+#include "nsIEnumerator.h"
+#include "nsISupportsArray.h"
+#include "nsISimpleEnumerator.h"
+
+class ObserverListEnumerator : public nsISimpleEnumerator
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ ObserverListEnumerator(nsISupportsArray* aValueArray);
+
+private:
+ ~ObserverListEnumerator(void);
+
+protected:
+ nsISupportsArray* mValueArray;
+ PRInt32 mIndex;
+};
+
+class nsObserverList
+{
+public:
+ nsObserverList();
+ ~nsObserverList();
+
+ nsresult AddObserver(nsIObserver* anObserver, PRBool ownsWeak);
+ nsresult RemoveObserver(nsIObserver* anObserver);
+ nsresult GetObserverList(nsISimpleEnumerator** anEnumerator);
+
+protected:
+ PRLock* mLock;
+ nsCOMPtr<nsISupportsArray> mObserverList;
+};
+
+
+#endif /* nsObserverList_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp
new file mode 100644
index 00000000..f4c66bcc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.cpp
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prlog.h"
+#include "prlock.h"
+#include "nsIFactory.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsIObserverService.h"
+#include "nsObserverService.h"
+#include "nsObserverList.h"
+#include "nsHashtable.h"
+#include "nsIWeakReference.h"
+
+#define NS_WEAK_OBSERVERS
+
+
+
+#if defined(PR_LOGGING)
+// Log module for nsObserverService logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=ObserverService:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+PRLogModuleInfo* observerServiceLog = nsnull;
+#endif /* PR_LOGGING */
+
+////////////////////////////////////////////////////////////////////////////////
+// nsObserverService Implementation
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsObserverService, nsIObserverService)
+
+nsObserverService::nsObserverService()
+ : mObserverTopicTable(nsnull)
+{
+}
+
+nsObserverService::~nsObserverService(void)
+{
+ if(mObserverTopicTable)
+ delete mObserverTopicTable;
+}
+
+NS_METHOD
+nsObserverService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+#if defined(PR_LOGGING)
+ if (!observerServiceLog)
+ observerServiceLog = PR_NewLogModule("ObserverService");
+#endif
+
+ nsresult rv;
+ nsObserverService* os = new nsObserverService();
+ if (os == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(os);
+ rv = os->QueryInterface(aIID, aInstancePtr);
+ NS_RELEASE(os);
+ return rv;
+}
+
+static PRBool PR_CALLBACK
+ReleaseObserverList(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsObserverList* observerList = NS_STATIC_CAST(nsObserverList*, aData);
+ delete(observerList);
+ return PR_TRUE;
+}
+
+nsresult nsObserverService::GetObserverList(const char* aTopic, nsObserverList** anObserverList)
+{
+ if (anObserverList == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ if(mObserverTopicTable == nsnull)
+ {
+ mObserverTopicTable = new nsObjectHashtable(nsnull,
+ nsnull, // should never be cloned
+ ReleaseObserverList,
+ nsnull,
+ 256,
+ PR_TRUE);
+ if (mObserverTopicTable == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ nsCStringKey key(aTopic);
+
+ nsObserverList *topicObservers;
+ topicObservers = (nsObserverList *) mObserverTopicTable->Get(&key);
+
+ if (topicObservers)
+ {
+ *anObserverList = topicObservers;
+ return NS_OK;
+ }
+
+ topicObservers = new nsObserverList();
+ if (!topicObservers)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *anObserverList = topicObservers;
+ mObserverTopicTable->Put(&key, topicObservers);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsObserverService::AddObserver(nsIObserver* anObserver, const char* aTopic, PRBool ownsWeak)
+{
+ nsObserverList* anObserverList;
+ nsresult rv;
+
+ if (anObserver == nsnull || aTopic == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ rv = GetObserverList(aTopic, &anObserverList);
+ if (NS_FAILED(rv)) return rv;
+
+ return anObserverList->AddObserver(anObserver, ownsWeak);
+}
+
+NS_IMETHODIMP nsObserverService::RemoveObserver(nsIObserver* anObserver, const char* aTopic)
+{
+ nsObserverList* anObserverList;
+ nsresult rv;
+
+ if (anObserver == nsnull || aTopic == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ rv = GetObserverList(aTopic, &anObserverList);
+ if (NS_FAILED(rv)) return rv;
+
+ return anObserverList->RemoveObserver(anObserver);
+}
+
+NS_IMETHODIMP nsObserverService::EnumerateObservers(const char* aTopic, nsISimpleEnumerator** anEnumerator)
+{
+ nsObserverList* anObserverList;
+ nsresult rv;
+
+ if (anEnumerator == nsnull || aTopic == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ rv = GetObserverList(aTopic, &anObserverList);
+ if (NS_FAILED(rv)) return rv;
+
+ return anObserverList->GetObserverList(anEnumerator);
+}
+
+// Enumerate observers of aTopic and call Observe on each.
+NS_IMETHODIMP nsObserverService::NotifyObservers( nsISupports *aSubject,
+ const char *aTopic,
+ const PRUnichar *someData ) {
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsISimpleEnumerator> observers;
+ nsCOMPtr<nsISupports> observerRef;
+
+ rv = EnumerateObservers( aTopic, getter_AddRefs(observers) );
+ if ( NS_FAILED( rv ) )
+ return rv;
+ PRBool loop = PR_TRUE;
+ while( NS_SUCCEEDED(observers->HasMoreElements(&loop)) && loop)
+ {
+ observers->GetNext(getter_AddRefs(observerRef));
+ nsCOMPtr<nsIObserver> observer = do_QueryInterface(observerRef);
+ if ( observer )
+ observer->Observe( aSubject, aTopic, someData );
+#ifdef NS_WEAK_OBSERVERS
+ else
+ { // check for weak reference.
+ nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(observerRef);
+ if ( weakRef )
+ weakRef->QueryReferent(NS_GET_IID(nsIObserver), getter_AddRefs(observer));
+
+ if ( observer )
+ observer->Observe( aSubject, aTopic, someData );
+
+ PR_LOG(observerServiceLog, PR_LOG_DEBUG, ("Notification - %s\n", aTopic ? aTopic : "undefined"));
+
+ }
+#endif
+ }
+ return NS_OK;
+}
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsObserverService.h b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.h
new file mode 100644
index 00000000..0a08f2ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsObserverService.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsObserverService_h___
+#define nsObserverService_h___
+
+#include "nsIObserverService.h"
+
+#define NS_OBSERVERSERVICE_CONTRACTID "@mozilla.org/observer-service;1"
+#define NS_OBSERVERSERVICE_CLASSNAME "Observer Service"
+
+class nsObserverList;
+class nsObjectHashtable;
+
+// {D07F5195-E3D1-11d2-8ACD-00105A1B8860}
+#define NS_OBSERVERSERVICE_CID \
+ { 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } }
+
+class nsObserverService : public nsIObserverService {
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR( NS_OBSERVERSERVICE_CID )
+
+ nsObserverService();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVERSERVICE
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsObserverService(void);
+
+ nsObjectHashtable* mObserverTopicTable;
+
+ nsresult GetObserverList(const char* aTopic, nsObserverList** anObserverList);
+
+
+};
+
+#endif /* nsObserverService_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp
new file mode 100644
index 00000000..0bdef252
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.cpp
@@ -0,0 +1,492 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsID.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+#include "nsIInputStream.h"
+#include "nsIUnicharInputStream.h"
+#include "pratom.h"
+#include "nsEnumeratorUtils.h"
+#include "nsReadableUtils.h"
+#include "nsPrintfCString.h"
+
+#define PL_ARENA_CONST_ALIGN_MASK 3
+#include "nsPersistentProperties.h"
+#include "nsIProperties.h"
+#include "nsProperties.h"
+
+struct PropertyTableEntry : public PLDHashEntryHdr
+{
+ // both of these are arena-allocated
+ const char *mKey;
+ const PRUnichar *mValue;
+};
+
+static PRUnichar*
+ArenaStrdup(const nsAFlatString& aString, PLArenaPool* aArena)
+{
+ void *mem;
+ // add one to include the null terminator
+ PRInt32 len = (aString.Length()+1) * sizeof(PRUnichar);
+ PL_ARENA_ALLOCATE(mem, aArena, len);
+ NS_ASSERTION(mem, "Couldn't allocate space!\n");
+ if (mem) {
+ memcpy(mem, aString.get(), len);
+ }
+ return NS_STATIC_CAST(PRUnichar*, mem);
+}
+
+static char*
+ArenaStrdup(const nsAFlatCString& aString, PLArenaPool* aArena)
+{
+ void *mem;
+ // add one to include the null terminator
+ PRInt32 len = (aString.Length()+1) * sizeof(char);
+ PL_ARENA_ALLOCATE(mem, aArena, len);
+ NS_ASSERTION(mem, "Couldn't allocate space!\n");
+ if (mem)
+ memcpy(mem, aString.get(), len);
+ return NS_STATIC_CAST(char*, mem);
+}
+
+static const struct PLDHashTableOps property_HashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ nsnull,
+};
+
+nsPersistentProperties::nsPersistentProperties()
+: mIn(nsnull)
+{
+ mSubclass = NS_STATIC_CAST(nsIPersistentProperties*, this);
+ mTable.ops = nsnull;
+ PL_INIT_ARENA_POOL(&mArena, "PersistentPropertyArena", 2048);
+}
+
+nsPersistentProperties::~nsPersistentProperties()
+{
+ PL_FinishArenaPool(&mArena);
+ if (mTable.ops)
+ PL_DHashTableFinish(&mTable);
+}
+
+nsresult
+nsPersistentProperties::Init()
+{
+ if (!PL_DHashTableInit(&mTable, &property_HashTableOps, nsnull,
+ sizeof(PropertyTableEntry), 20)) {
+ mTable.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+nsPersistentProperties::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+ nsPersistentProperties* props = new nsPersistentProperties();
+ if (props == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(props);
+ nsresult rv = props->Init();
+ if (NS_SUCCEEDED(rv))
+ rv = props->QueryInterface(aIID, aResult);
+
+ NS_RELEASE(props);
+ return rv;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsPersistentProperties, nsIPersistentProperties, nsIProperties)
+
+NS_IMETHODIMP
+nsPersistentProperties::Load(nsIInputStream *aIn)
+{
+ PRInt32 c;
+ nsresult ret = NS_NewUTF8ConverterStream(&mIn, aIn, 0);
+
+ if (ret != NS_OK) {
+ NS_WARNING("NS_NewUTF8ConverterStream failed");
+ return NS_ERROR_FAILURE;
+ }
+ c = Read();
+ while (1) {
+ c = SkipWhiteSpace(c);
+ if (c < 0) {
+ break;
+ }
+ else if ((c == '#') || (c == '!')) {
+ c = SkipLine(c);
+ continue;
+ }
+ else {
+ nsAutoString key;
+ while ((c >= 0) && (c != '=') && (c != ':')) {
+ key.Append(PRUnichar(c));
+ c = Read();
+ }
+ if (c < 0) {
+ break;
+ }
+ static const char trimThese[] = " \t";
+ key.Trim(trimThese, PR_FALSE, PR_TRUE);
+ c = Read();
+ nsAutoString value;
+ PRUint32 state = 0;
+ PRUnichar uchar = 0;
+ while ((c >= 0) && (c != '\r') && (c != '\n')) {
+ switch(state) {
+ case 0:
+ if (c == '\\') {
+ c = Read();
+ switch(c) {
+ case '\r':
+ case '\n':
+ // Only skip first EOL characters and then next line's
+ // whitespace characters. Skipping all EOL characters
+ // and all upcoming whitespace is too agressive.
+ if (c == '\r')
+ c = Read();
+ if (c == '\n')
+ c = Read();
+ while (c == ' ' || c == '\t')
+ c = Read();
+ continue;
+ case 'u':
+ case 'U':
+ state = 1;
+ uchar=0;
+ break;
+ case 't':
+ value.Append(PRUnichar('\t'));
+ break;
+ case 'n':
+ value.Append(PRUnichar('\n'));
+ break;
+ case 'r':
+ value.Append(PRUnichar('\r'));
+ break;
+ default:
+ value.Append((PRUnichar) c);
+ } // switch(c)
+ } else {
+ value.Append((PRUnichar) c);
+ }
+ c = Read();
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ if (('0' <= c) && (c <= '9')) {
+ uchar = (uchar << 4) | (c - '0');
+ state++;
+ c = Read();
+ } else if (('a' <= c) && (c <= 'f')) {
+ uchar = (uchar << 4) | (c - 'a' + 0x0a);
+ state++;
+ c = Read();
+ } else if (('A' <= c) && (c <= 'F')) {
+ uchar = (uchar << 4) | (c - 'A' + 0x0a);
+ state++;
+ c = Read();
+ } else {
+ value.Append((PRUnichar) uchar);
+ state = 0;
+ }
+ break;
+ case 5:
+ value.Append((PRUnichar) uchar);
+ state = 0;
+ }
+ }
+ if (state != 0) {
+ value.Append((PRUnichar) uchar);
+ state = 0;
+ }
+
+ value.Trim(trimThese, PR_TRUE, PR_TRUE);
+ nsAutoString oldValue;
+ mSubclass->SetStringProperty(NS_ConvertUCS2toUTF8(key), value, oldValue);
+ }
+ }
+ mIn->Close();
+ NS_RELEASE(mIn);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::SetStringProperty(const nsACString& aKey,
+ const nsAString& aNewValue,
+ nsAString& aOldValue)
+{
+#if 0
+ cout << "will add " << aKey.get() << "=" <<
+ NS_LossyConvertUCS2ToASCII(aNewValue).get() << endl;
+#endif
+
+ const nsAFlatCString& flatKey = PromiseFlatCString(aKey);
+ PropertyTableEntry *entry =
+ NS_STATIC_CAST(PropertyTableEntry*,
+ PL_DHashTableOperate(&mTable, flatKey.get(), PL_DHASH_ADD));
+
+ if (entry->mKey) {
+ aOldValue = entry->mValue;
+ NS_WARNING(nsPrintfCString(aKey.Length() + 30,
+ "the property %s already exists\n",
+ flatKey.get()).get());
+ }
+
+ entry->mKey = ArenaStrdup(flatKey, &mArena);
+ entry->mValue = ArenaStrdup(PromiseFlatString(aNewValue), &mArena);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Save(nsIOutputStream* aOut, const nsACString& aHeader)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Subclass(nsIPersistentProperties* aSubclass)
+{
+ if (aSubclass) {
+ mSubclass = aSubclass;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::GetStringProperty(const nsACString& aKey,
+ nsAString& aValue)
+{
+ const nsAFlatCString& flatKey = PromiseFlatCString(aKey);
+
+ PropertyTableEntry *entry =
+ NS_STATIC_CAST(PropertyTableEntry*,
+ PL_DHashTableOperate(&mTable, flatKey.get(), PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(entry))
+ return NS_ERROR_FAILURE;
+
+ aValue = entry->mValue;
+ return NS_OK;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+AddElemToArray(PLDHashTable* table, PLDHashEntryHdr *hdr,
+ PRUint32 i, void *arg)
+{
+ nsISupportsArray *propArray = (nsISupportsArray *) arg;
+ PropertyTableEntry* entry =
+ NS_STATIC_CAST(PropertyTableEntry*, hdr);
+
+ nsPropertyElement *element =
+ new nsPropertyElement(nsDependentCString(entry->mKey),
+ nsDependentString(entry->mValue));
+ if (!element)
+ return PL_DHASH_STOP;
+
+ NS_ADDREF(element);
+ propArray->InsertElementAt(element, i);
+
+ return PL_DHASH_NEXT;
+}
+
+
+NS_IMETHODIMP
+nsPersistentProperties::Enumerate(nsISimpleEnumerator** aResult)
+{
+ nsCOMPtr<nsIBidirectionalEnumerator> iterator;
+
+ nsISupportsArray* propArray;
+ nsresult rv = NS_NewISupportsArray(&propArray);
+ if (rv != NS_OK)
+ return rv;
+
+ // Step through hash entries populating a transient array
+ PRUint32 n =
+ PL_DHashTableEnumerate(&mTable, AddElemToArray, (void *)propArray);
+ if (n < mTable.entryCount)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_NewArrayEnumerator(aResult, propArray);
+}
+
+
+PRInt32
+nsPersistentProperties::Read()
+{
+ PRUnichar c;
+ PRUint32 nRead;
+ nsresult ret;
+
+ ret = mIn->Read(&c, 1, &nRead);
+ if (ret == NS_OK && nRead == 1) {
+ return c;
+ }
+
+ return -1;
+}
+
+#define IS_WHITE_SPACE(c) \
+ (((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n'))
+
+PRInt32
+nsPersistentProperties::SkipWhiteSpace(PRInt32 c)
+{
+ while (IS_WHITE_SPACE(c)) {
+ c = Read();
+ }
+
+ return c;
+}
+
+PRInt32
+nsPersistentProperties::SkipLine(PRInt32 c)
+{
+ while ((c >= 0) && (c != '\r') && (c != '\n')) {
+ c = Read();
+ }
+ if (c == '\r') {
+ c = Read();
+ }
+ if (c == '\n') {
+ c = Read();
+ }
+
+ return c;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XXX Some day we'll unify the nsIPersistentProperties interface with
+// nsIProperties, but until now...
+
+NS_IMETHODIMP
+nsPersistentProperties::Get(const char* prop, const nsIID & uuid, void* *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Set(const char* prop, nsISupports* value)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP
+nsPersistentProperties::Undefine(const char* prop)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::Has(const char* prop, PRBool *result)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPersistentProperties::GetKeys(PRUint32 *count, char ***keys)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PropertyElement
+////////////////////////////////////////////////////////////////////////////////
+
+
+NS_METHOD
+nsPropertyElement::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+ nsPropertyElement* propElem = new nsPropertyElement();
+ if (propElem == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(propElem);
+ nsresult rv = propElem->QueryInterface(aIID, aResult);
+ NS_RELEASE(propElem);
+ return rv;
+}
+
+NS_IMPL_ISUPPORTS1(nsPropertyElement, nsIPropertyElement)
+
+NS_IMETHODIMP
+nsPropertyElement::GetKey(nsACString& aReturnKey)
+{
+ aReturnKey = mKey;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPropertyElement::GetValue(nsAString& aReturnValue)
+{
+ aReturnValue = mValue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPropertyElement::SetKey(const nsACString& aKey)
+{
+ mKey = aKey;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPropertyElement::SetValue(const nsAString& aValue)
+{
+ mValue = aValue;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h
new file mode 100644
index 00000000..020ff82d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsPersistentProperties.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsPersistentProperties_h___
+#define nsPersistentProperties_h___
+
+#include "nsIPersistentProperties2.h"
+#include "pldhash.h"
+#include "plarena.h"
+#include "nsString.h"
+
+class nsIUnicharInputStream;
+
+
+class nsPersistentProperties : public nsIPersistentProperties
+{
+public:
+ nsPersistentProperties();
+ nsresult Init();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROPERTIES
+ NS_DECL_NSIPERSISTENTPROPERTIES
+
+
+ // nsPersistentProperties methods:
+ PRInt32 Read();
+ PRInt32 SkipLine(PRInt32 c);
+ PRInt32 SkipWhiteSpace(PRInt32 c);
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsPersistentProperties();
+
+protected:
+ nsIUnicharInputStream* mIn;
+ PRUint32 mBufferPos;
+ PRUint32 mBufferLength;
+ nsIPersistentProperties* mSubclass;
+ struct PLDHashTable mTable;
+ PLArenaPool mArena;
+};
+
+class nsPropertyElement : public nsIPropertyElement
+{
+public:
+ nsPropertyElement()
+ {
+ }
+
+ nsPropertyElement(const nsACString& aKey, const nsAString& aValue)
+ : mKey(aKey), mValue(aValue)
+ {
+ }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROPERTYELEMENT
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsPropertyElement() {}
+
+protected:
+ nsCString mKey;
+ nsString mValue;
+};
+
+#endif /* nsPersistentProperties_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp b/src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp
new file mode 100644
index 00000000..8276e4a5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsProperties.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsProperties.h"
+
+//#include <iostream.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsProperties::nsProperties(nsISupports* outer)
+{
+ NS_INIT_AGGREGATED(outer);
+}
+
+NS_METHOD
+nsProperties::Create(nsISupports *outer, REFNSIID aIID, void **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
+
+ nsProperties* props = new nsProperties(outer);
+ if (props == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = props->AggregatedQueryInterface(aIID, aResult);
+ if (NS_FAILED(rv))
+ delete props;
+ return rv;
+}
+
+PRBool PR_CALLBACK
+nsProperties::ReleaseValues(nsHashKey* key, void* data, void* closure)
+{
+ nsISupports* value = (nsISupports*)data;
+ NS_IF_RELEASE(value);
+ return PR_TRUE;
+}
+
+nsProperties::~nsProperties()
+{
+ Enumerate(ReleaseValues);
+}
+
+NS_IMPL_AGGREGATED(nsProperties)
+
+NS_METHOD
+nsProperties::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+
+ if (aIID.Equals(NS_GET_IID(nsISupports)))
+ *aInstancePtr = GetInner();
+ else if (aIID.Equals(NS_GET_IID(nsIProperties)))
+ *aInstancePtr = NS_STATIC_CAST(nsIProperties*, this);
+ else {
+ *aInstancePtr = nsnull;
+ return NS_NOINTERFACE;
+ }
+
+ NS_ADDREF((nsISupports*)*aInstancePtr);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::Get(const char* prop, const nsIID & uuid, void* *result)
+{
+ nsresult rv;
+ nsCStringKey key(prop);
+ nsISupports* value = (nsISupports*)nsHashtable::Get(&key);
+ if (value) {
+ rv = value->QueryInterface(uuid, result);
+ }
+ else {
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsProperties::Set(const char* prop, nsISupports* value)
+{
+ nsCStringKey key(prop);
+
+ nsISupports* prevValue = (nsISupports*)Put(&key, value);
+ NS_IF_RELEASE(prevValue);
+ NS_IF_ADDREF(value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::Undefine(const char* prop)
+{
+ nsCStringKey key(prop);
+ if (!Exists(&key))
+ return NS_ERROR_FAILURE;
+
+ nsISupports* prevValue = (nsISupports*)Remove(&key);
+ NS_IF_RELEASE(prevValue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::Has(const char* prop, PRBool *result)
+{
+ nsCStringKey key(prop);
+ *result = nsHashtable::Exists(&key);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProperties::GetKeys(PRUint32 *count, char ***keys)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsProperties.h b/src/libs/xpcom18a4/xpcom/ds/nsProperties.h
new file mode 100644
index 00000000..ee225547
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsProperties.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsProperties_h___
+#define nsProperties_h___
+
+#include "nsIProperties.h"
+#include "nsHashtable.h"
+#include "nsAgg.h"
+
+#define NS_PROPERTIES_CID \
+{ /* 4de2bc90-b1bf-11d3-93b6-00104ba0fd40 */ \
+ 0x4de2bc90, \
+ 0xb1bf, \
+ 0x11d3, \
+ {0x93, 0xb6, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+class nsIUnicharInputStream;
+
+class nsProperties : public nsIProperties, public nsHashtable {
+public:
+
+ NS_DECL_AGGREGATED
+ NS_DECL_NSIPROPERTIES
+
+ nsProperties(nsISupports* outer);
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure);
+
+private:
+ ~nsProperties();
+};
+
+#endif /* nsProperties_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp
new file mode 100644
index 00000000..0a71d25d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.cpp
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* We need this because Solaris' version of qsort is broken and
+ * causes array bounds reads.
+ */
+
+#include <stdlib.h>
+#include "prtypes.h"
+#include "nsQuickSort.h"
+
+PR_BEGIN_EXTERN_C
+
+#if !defined(DEBUG) && (defined(__cplusplus) || defined(__gcc))
+# ifndef INLINE
+# define INLINE inline
+# endif
+#else
+# define INLINE
+#endif
+
+typedef int cmp_t(const void *, const void *, void *);
+static INLINE char *med3(char *, char *, char *, cmp_t *, void *);
+static INLINE void swapfunc(char *, char *, int, int);
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ register TYPE *pi = (TYPE *) (parmi); \
+ register TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ register TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static INLINE void
+swapfunc(char *a, char *b, int n, int swaptype)
+{
+ if(swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc((char *)a, (char*)b, (int)es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc((char *)a, (char *)b, (int)n, swaptype)
+
+static INLINE char *
+med3(char *a, char *b, char *c, cmp_t* cmp, void *data)
+{
+ return cmp(a, b, data) < 0 ?
+ (cmp(b, c, data) < 0 ? b : (cmp(a, c, data) < 0 ? c : a ))
+ :(cmp(b, c, data) > 0 ? b : (cmp(a, c, data) < 0 ? a : c ));
+}
+
+void NS_QuickSort (
+ void *a,
+ unsigned int n,
+ unsigned int es,
+ cmp_t *cmp,
+ void *data
+ )
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ int d, r, swaptype, swap_cnt;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = (char *)a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, data);
+ pm = med3(pm - d, pm, pm + d, cmp, data);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, data);
+ }
+ pm = med3(pl, pm, pn, cmp, data);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (r = cmp(pb, a, data)) <= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (r = cmp(pc, a, data)) >= 0) {
+ if (r == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = PR_MIN(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = PR_MIN(pd - pc, (int)(pn - pd - es));
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > (int)es)
+ NS_QuickSort(a, r / es, es, cmp, data);
+ if ((r = pd - pc) > (int)es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* NS_QuickSort(pn - r, r / es, es, cmp, data);*/
+}
+
+PR_END_EXTERN_C
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h
new file mode 100644
index 00000000..0dd16385
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsQuickSort.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* We need this because Solaris' version of qsort is broken and
+ * causes array bounds reads.
+ */
+
+#ifndef nsQuickSort_h___
+#define nsQuickSort_h___
+
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_QuickSort VBoxNsxpNS_QuickSort
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/**
+ * Parameters:
+ * 1. the array to sort
+ * 2. the number of elements in the array
+ * 3. the size of each array element
+ * 4. comparison function taking two elements and parameter #5 and
+ * returning an integer:
+ * + less than zero if the first element should be before the second
+ * + 0 if the order of the elements does not matter
+ * + greater than zero if the second element should be before the first
+ * 5. extra data to pass to comparison function
+ */
+PR_EXTERN(void) NS_QuickSort(void *, unsigned int, unsigned int,
+ int (*)(const void *, const void *, void *),
+ void *);
+
+PR_END_EXTERN_C
+
+#endif /* nsQuickSort_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp
new file mode 100644
index 00000000..241f795c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.cpp
@@ -0,0 +1,443 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.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 ***** */
+
+/*
+ * nsRecyclingAllocator
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "nsRecyclingAllocator.h"
+#include "nsIMemory.h"
+#include "nsAutoLock.h"
+#include "prprf.h"
+#include "nsITimer.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+#define NS_SEC_TO_MS(s) ((s) * 1000)
+
+void
+nsRecyclingAllocator::nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure)
+{
+ nsRecyclingAllocator *obj = (nsRecyclingAllocator *) aClosure;
+ if (!obj->mTouched)
+ {
+ if (obj->mFreeList)
+ obj->FreeUnusedBuckets();
+
+ // If we are holding no more memory, there is no need for the timer.
+ // We will revive the timer on the next allocation.
+ // XXX Unfortunately there is no way to Cancel and restart the same timer.
+ // XXX So we pretty much kill it and create a new one later.
+ if (!obj->mFreeList && obj->mRecycleTimer)
+ {
+ obj->mRecycleTimer->Cancel();
+ NS_RELEASE(obj->mRecycleTimer);
+ }
+ }
+ else
+ {
+ // Clear touched so the next time the timer fires we can test whether
+ // the allocator was used or not.
+ obj->Untouch();
+ }
+}
+
+
+nsRecyclingAllocator::nsRecyclingAllocator(PRUint32 nbucket, PRUint32 recycleAfter, const char *id) :
+ mMaxBlocks(nbucket), mBlocks(nsnull), mFreeList(nsnull), mNotUsedList(nsnull),
+ mRecycleTimer(nsnull), mRecycleAfter(recycleAfter), mTouched(0), mId(id)
+#ifdef DEBUG
+ ,mNAllocated(0)
+#endif
+{
+ NS_ASSERTION(mMaxBlocks <= NS_MAX_BLOCKS, "Too many blocks. This will affect the allocator's performance.");
+
+ mLock = PR_NewLock();
+ NS_ASSERTION(mLock, "Recycling allocator cannot get lock");
+
+ Init(nbucket, recycleAfter, id);
+}
+
+nsresult
+nsRecyclingAllocator::Init(PRUint32 nbucket, PRUint32 recycleAfter, const char *id)
+{
+ nsAutoLock lock(mLock);
+
+ // Free all memory held, if any
+ while(mFreeList)
+ {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mFreeList->block);
+#else
+ free(mFreeList->block);
+#endif
+ mFreeList = mFreeList->next;
+ }
+ mFreeList = nsnull;
+
+ if (mBlocks)
+ delete [] mBlocks;
+
+ // Reinitialize everything
+ mMaxBlocks = nbucket;
+ if (nbucket)
+ {
+ // Create memory for our bookkeeping
+ mBlocks = new BlockStoreNode[mMaxBlocks];
+ if (!mBlocks)
+ return NS_ERROR_OUT_OF_MEMORY;
+ // Link them together
+ mNotUsedList = mBlocks;
+ for (PRUint32 i=0; i < mMaxBlocks-1; i++)
+ mBlocks[i].next = &(mBlocks[i+1]);
+ }
+
+ mRecycleAfter = recycleAfter;
+ mId = id;
+
+ return NS_OK;
+}
+
+nsRecyclingAllocator::~nsRecyclingAllocator()
+{
+ // Cancel and destroy recycle timer
+ if (mRecycleTimer)
+ {
+ mRecycleTimer->Cancel();
+ NS_RELEASE(mRecycleTimer);
+ }
+
+ // Free all memory held, if any
+ while(mFreeList)
+ {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(mFreeList->block);
+#else
+ free(mFreeList->block);
+#endif
+ mFreeList = mFreeList->next;
+ }
+ mFreeList = nsnull;
+
+ if (mBlocks)
+ delete [] mBlocks;
+
+ if (mLock)
+ {
+ PR_DestroyLock(mLock);
+ mLock = nsnull;
+ }
+}
+
+// Allocation and free routines
+void*
+nsRecyclingAllocator::Malloc(PRSize bytes, PRBool zeroit)
+{
+ // Mark that we are using. This will prevent any
+ // timer based release of unused memory.
+ Touch();
+
+ Block* freeBlock = FindFreeBlock(bytes);
+ if (freeBlock)
+ {
+ void *data = DATA(freeBlock);
+
+ if (zeroit)
+ memset(data, 0, bytes);
+ return data;
+ }
+
+ // We need to do an allocation
+ // Add 4 bytes to what we allocate to hold the bucket index
+ PRSize allocBytes = bytes + NS_ALLOCATOR_OVERHEAD_BYTES;
+
+ // We dont have that memory already. Allocate.
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ Block *ptr = (Block *) (zeroit ? RTMemAllocZ(allocBytes) : RTMemAlloc(allocBytes));
+#else
+ Block *ptr = (Block *) (zeroit ? calloc(1, allocBytes) : malloc(allocBytes));
+#endif
+
+ // Deal with no memory situation
+ if (!ptr)
+ return ptr;
+
+ // This is the first allocation we are holding.
+ // Setup timer for releasing memory
+ // If this fails, then we wont have a timer to release unused
+ // memory. We can live with that. Also, the next allocation
+ // will try again to set the timer.
+ if (mRecycleAfter && !mRecycleTimer)
+ {
+ // known only to stuff in xpcom.
+ extern nsresult NS_NewTimer(nsITimer* *aResult, nsTimerCallbackFunc aCallback, void *aClosure,
+ PRUint32 aDelay, PRUint32 aType);
+
+ (void) NS_NewTimer(&mRecycleTimer, nsRecycleTimerCallback, this,
+ NS_SEC_TO_MS(mRecycleAfter),
+ nsITimer::TYPE_REPEATING_SLACK);
+ NS_ASSERTION(mRecycleTimer, "nsRecyclingAllocator: Creating timer failed.\n");
+ }
+
+#ifdef DEBUG
+ mNAllocated++;
+#endif
+
+ // Store size and return data portion
+ ptr->bytes = bytes;
+ return DATA(ptr);
+}
+
+void
+nsRecyclingAllocator::Free(void *ptr)
+{
+ // Mark that we are using the allocator. This will prevent any
+ // timer based release of unused memory.
+ Touch();
+
+ Block* block = DATA_TO_BLOCK(ptr);
+
+ if (!AddToFreeList(block))
+ {
+ // We are holding more than max. Failover to free
+#ifdef DEBUG_dp
+ char buf[1024];
+ // Warn if we are failing over to malloc/free and not storing it
+ // This says we have a misdesigned memory pool. The intent was
+ // once the pool was full, we would never fail over to calloc.
+ PR_snprintf(buf, sizeof(buf), "nsRecyclingAllocator(%s) FAILOVER 0x%p (%d) - %d allocations, %d max\n",
+ mId, (char *)ptr, block->bytes, mNAllocated, mMaxBlocks);
+ NS_WARNING(buf);
+ mNAllocated--;
+#endif
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(block);
+#else
+ free(block);
+#endif
+ }
+}
+
+/* FreeUnusedBuckets
+ *
+ * Frees any bucket memory that isn't in use
+ */
+
+void
+nsRecyclingAllocator::FreeUnusedBuckets()
+{
+#ifdef DEBUG_dp
+ printf("DEBUG: nsRecyclingAllocator(%s) FreeUnusedBuckets: ", mId);
+#endif
+ nsAutoLock lock(mLock);
+
+ // We will run through the freelist and free all blocks
+ BlockStoreNode* node = mFreeList;
+ while (node)
+ {
+ // Free the allocated block
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(node->block);
+#else
+ free(node->block);
+#endif
+
+#ifdef DEBUG_dp
+ printf("%d ", node->bytes);
+#endif
+ // Clear Node
+ node->block = nsnull;
+ node->bytes = 0;
+ node = node->next;
+ }
+
+ // remake the lists
+ mNotUsedList = mBlocks;
+ for (PRUint32 i=0; i < mMaxBlocks-1; i++)
+ mBlocks[i].next = &(mBlocks[i+1]);
+ mBlocks[mMaxBlocks-1].next = nsnull;
+ mFreeList = nsnull;
+
+#ifdef DEBUG
+ mNAllocated = 0;
+#endif
+#ifdef DEBUG_dp
+ printf("\n");
+#endif
+}
+
+nsRecyclingAllocator::Block*
+nsRecyclingAllocator::FindFreeBlock(PRSize bytes)
+{
+ // We dont enter lock for this check. This is intentional.
+ // Here is my logic: we are checking if (!mFreeList). Doing this check
+ // without locking can lead to unpredictable results. YES. But the effect
+ // of the unpredictedness are ok. here is why:
+ //
+ // a) if the check returned NULL when there is stuff in freelist
+ // We would just end up reallocating.
+ //
+ // b) if the check returned nonNULL when our freelist is empty
+ // This is the more likely and dangerous case. The code for
+ // FindFreeBlock() will enter lock, while (null) and return null.
+ //
+ // The reason why I chose to not enter lock for this check was that when
+ // the allocator is full, we dont want to impose any more overhead than
+ // we already are for failing over to malloc/free.
+
+ if (!mFreeList)
+ return NULL;
+
+ Block *block = nsnull;
+
+ nsAutoLock lock(mLock);
+ BlockStoreNode* freeNode = mFreeList;
+ BlockStoreNode** prevp = &mFreeList;
+
+ while (freeNode)
+ {
+ if (freeNode->bytes >= bytes)
+ {
+ // Found the best fit free block
+ block = freeNode->block;
+
+ // Clear the free node
+ freeNode->block = nsnull;
+ freeNode->bytes = 0;
+
+ // Remove free node from free list
+ *prevp = freeNode->next;
+
+ // Add removed BlockStoreNode to not used list
+ freeNode->next = mNotUsedList;
+ mNotUsedList = freeNode;
+
+ break;
+ }
+
+ prevp = &(freeNode->next);
+ freeNode = freeNode->next;
+ }
+ return block;
+}
+
+PRInt32
+nsRecyclingAllocator::AddToFreeList(Block* block)
+{
+ nsAutoLock lock(mLock);
+
+ if (!mNotUsedList)
+ return PR_FALSE;
+
+ // Pick a node from the not used list
+ BlockStoreNode *node = mNotUsedList;
+ mNotUsedList = mNotUsedList->next;
+
+ // Initialize the node
+ node->bytes = block->bytes;
+ node->block = block;
+
+ // Find the right spot in the sorted list.
+ BlockStoreNode* freeNode = mFreeList;
+ BlockStoreNode** prevp = &mFreeList;
+ while (freeNode)
+ {
+ if (freeNode->bytes >= block->bytes)
+ break;
+ prevp = &(freeNode->next);
+ freeNode = freeNode->next;
+ }
+
+ // Needs to be inserted between *prevp and freeNode
+ *prevp = node;
+ node->next = freeNode;
+
+ return PR_TRUE;
+}
+
+
+// ----------------------------------------------------------------------
+// Wrapping the recyling allocator with nsIMemory
+// ----------------------------------------------------------------------
+
+// nsIMemory methods
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsRecyclingAllocatorImpl, nsIMemory, nsIRecyclingAllocator)
+
+NS_IMETHODIMP_(void *)
+nsRecyclingAllocatorImpl::Alloc(PRSize size)
+{
+ return nsRecyclingAllocatorImpl::Malloc(size, PR_FALSE);
+}
+
+NS_IMETHODIMP_(void *)
+nsRecyclingAllocatorImpl::Realloc(void *ptr, PRSize size)
+{
+ // XXX Not yet implemented
+ return NULL;
+}
+
+NS_IMETHODIMP_(void)
+nsRecyclingAllocatorImpl::Free(void *ptr)
+{
+ nsRecyclingAllocator::Free(ptr);
+}
+
+NS_IMETHODIMP
+nsRecyclingAllocatorImpl::Init(size_t nbuckets, size_t recycleAfter, const char *id)
+{
+ return nsRecyclingAllocator::Init((PRUint32) nbuckets, (PRUint32) recycleAfter, id);
+}
+
+NS_IMETHODIMP
+nsRecyclingAllocatorImpl::HeapMinimize(PRBool immediate)
+{
+ // XXX Not yet implemented
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsRecyclingAllocatorImpl::IsLowMemory(PRBool *lowmemoryb_ptr)
+{
+ // XXX Not yet implemented
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h
new file mode 100644
index 00000000..4266b1b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsRecyclingAllocator.h
@@ -0,0 +1,208 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.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 ***** */
+
+/*
+ * nsRecyclingAllocator
+ *
+ * This allocator is useful when we cycle through a small set of allocations
+ * repeatedly with minimal overlap. For eg. something we do for every gif
+ * file read (or) buffers required for decompression of every file from jar.
+ *
+ * What this does is keeps around the first set of memory allocated and
+ * reuses it subsequently. If all buckets are full, this falls back to
+ * malloc/free
+ *
+ * Uses a timer to release all memory allocated if not used for more than
+ * 10 secs automatically.
+ *
+ * Also there is a 4 byte maintenance overhead on every allocation.
+ *
+ * This allocator is thread safe.
+ *
+ * CAVEATS: As the number of buckets increases, this allocators performance
+ * will drop. As a general guideline, dont use this for more
+ * than NS_MAX_BLOCKS
+ */
+
+#ifndef nsRecyclingAllocator_h__
+#define nsRecyclingAllocator_h__
+
+#include "nscore.h"
+#include "pratom.h"
+#include "prlock.h"
+#include "nsIRecyclingAllocator.h"
+#include "nsIGenericFactory.h"
+
+#define NS_DEFAULT_RECYCLE_TIMEOUT 10 // secs
+#define NS_MAX_BLOCKS 24
+#define NS_ALLOCATOR_OVERHEAD_BYTES (sizeof(Block)) // bytes
+
+class nsITimer;
+class nsIMemory;
+
+class NS_COM nsRecyclingAllocator {
+ protected:
+ struct Block {
+ PRSize bytes;
+ };
+
+ // Make |BlockStoreNode| a |friend| so it can access |Block|.
+ struct BlockStoreNode;
+ friend struct BlockStoreNode;
+
+ struct BlockStoreNode {
+ BlockStoreNode() : bytes(0), block(nsnull), next(nsnull) {};
+ PRSize bytes;
+ Block *block;
+ BlockStoreNode *next;
+ };
+
+#define DATA(block) ((void *)(((char *)block) + NS_ALLOCATOR_OVERHEAD_BYTES))
+#define DATA_TO_BLOCK(data) ((Block *)((char *)(data) - NS_ALLOCATOR_OVERHEAD_BYTES))
+
+ // mMaxBlocks: Maximum number of blocks that can be allocated
+ PRUint32 mMaxBlocks;
+
+ // mBlocks:
+ // All blocks used or not.
+ BlockStoreNode *mBlocks;
+
+ // mFreeList
+ // A linked list of free blocks sorted by increasing order of size
+ BlockStoreNode* mFreeList;
+
+ // mNotUsedList
+ // A linked list of BlockStoreNodes that are not used to store
+ // any block information. When we add blocks into mFreeList, we
+ // take BlockStoreNode from here.
+ BlockStoreNode* mNotUsedList;
+
+ // mLock: Thread safety of mFreeList and mNotUsedList
+ PRLock *mLock;
+
+ // Timer for freeing unused memory
+ nsITimer *mRecycleTimer;
+
+ // mRecycleAfter:
+ // Allocator should be untouched for this many seconds for freeing
+ // unused Blocks.
+ PRUint32 mRecycleAfter;
+
+ // mTouched:
+ // says if the allocator touched any bucket. If allocator didn't touch
+ // any bucket over a time time interval, timer will call FreeUnusedBuckets()
+ PRInt32 mTouched;
+
+ // mId:
+ // a string for identifying the user of nsRecyclingAllocator
+ // User mainly for debug prints
+ const char *mId;
+
+#ifdef DEBUG
+ // mNAllocated: Number of blocks allocated
+ PRInt32 mNAllocated;
+#endif
+
+ public:
+
+ // nbucket : number of buckets to hold. Capped at NS_MAX_BUCKET
+ // recycleAfter : Try recycling allocated buckets after this many seconds
+ // id : a string used to identify debug prints. Will not be released.
+ nsRecyclingAllocator(PRUint32 nbucket = 0, PRUint32 recycleAfter = NS_DEFAULT_RECYCLE_TIMEOUT,
+ const char *id = NULL);
+ ~nsRecyclingAllocator();
+
+ nsresult Init(PRUint32 nbucket, PRUint32 recycleAfter, const char *id);
+
+ // Allocation and free routines
+ void* Malloc(PRSize size, PRBool zeroit = PR_FALSE);
+ void Free(void *ptr);
+
+ void* Calloc(PRUint32 items, PRSize size)
+ {
+ return Malloc(items * size, PR_TRUE);
+ }
+
+ // FreeUnusedBuckets - Frees any bucket memory that isn't in use
+ void FreeUnusedBuckets();
+
+ protected:
+
+ // Timer callback to trigger unused memory
+ static void nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure);
+
+ // Freelist management
+ // FindFreeBlock: return a free block that can hold bytes (best fit)
+ Block* FindFreeBlock(PRSize bytes);
+ // AddToFreeList: adds block into our freelist for future retrieval.
+ // Returns PR_TRUE is addition was successful. PR_FALSE otherewise.
+ PRBool AddToFreeList(Block* block);
+
+ // Touch will mark that someone used this allocator
+ // Timer based release will free unused memory only if allocator
+ // was not touched for mRecycleAfter seconds.
+ void Touch() {
+ if (!mTouched)
+ PR_AtomicSet(&mTouched, 1);
+ }
+ void Untouch() {
+ PR_AtomicSet(&mTouched, 0);
+ }
+
+ friend void nsRecycleTimerCallback(nsITimer *aTimer, void *aClosure);
+};
+
+// ----------------------------------------------------------------------
+// Wrapping the recyling allocator with nsIMemory
+// ----------------------------------------------------------------------
+
+// Wrapping the nsRecyclingAllocator with nsIMemory
+class nsRecyclingAllocatorImpl : public nsRecyclingAllocator, public nsIRecyclingAllocator {
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMEMORY
+ NS_DECL_NSIRECYCLINGALLOCATOR
+
+ nsRecyclingAllocatorImpl()
+ {
+ }
+
+private:
+ ~nsRecyclingAllocatorImpl() {}
+};
+#endif // nsRecyclingAllocator_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h
new file mode 100644
index 00000000..69cdbe88
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsRefPtrHashtable.h
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Neil Rashbrook <neil@parkwaycc.co.uk>
+ *
+ * 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 nsRefPtrHashtable_h__
+#define nsRefPtrHashtable_h__
+
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsAutoPtr.h"
+
+/**
+ * templated hashtable class maps keys to reference pointers.
+ * See nsBaseHashtable for complete declaration.
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param RefPtr the reference-type being wrapped
+ * @see nsDataHashtable, nsClassHashtable
+ */
+template<class KeyClass, class RefPtr>
+class nsRefPtrHashtable :
+ public nsBaseHashtable< KeyClass, nsRefPtr<RefPtr> , RefPtr* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef RefPtr* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ /**
+ * Gets a weak reference to the hashtable entry.
+ * @param aFound If not nsnull, will be set to PR_TRUE if the entry is found,
+ * to PR_FALSE otherwise.
+ * @return The entry, or nsnull if not found. Do not release this pointer!
+ */
+ RefPtr* GetWeak(KeyType aKey, PRBool* aFound = nsnull) const;
+};
+
+/**
+ * Thread-safe version of nsRefPtrHashtable
+ * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
+ * for a complete specification.
+ * @param RefPtr the reference-type being wrapped
+ */
+template<class KeyClass, class RefPtr>
+class nsRefPtrHashtableMT :
+ public nsBaseHashtableMT< KeyClass, nsRefPtr<RefPtr> , RefPtr* >
+{
+public:
+ typedef typename KeyClass::KeyType KeyType;
+ typedef RefPtr* UserDataType;
+
+ /**
+ * @copydoc nsBaseHashtable::Get
+ * @param pData This is an XPCOM getter, so pData is already_addrefed.
+ * If the key doesn't exist, pData will be set to nsnull.
+ */
+ PRBool Get(KeyType aKey, UserDataType* pData) const;
+
+ // GetWeak does not make sense on a multi-threaded hashtable, where another
+ // thread may remove the entry (and hence release it) as soon as GetWeak
+ // returns
+};
+
+
+//
+// nsRefPtrHashtable definitions
+//
+
+template<class KeyClass, class RefPtr>
+PRBool
+nsRefPtrHashtable<KeyClass,RefPtr>::Get
+ (KeyType aKey, UserDataType* pRefPtr) const
+{
+ typename nsBaseHashtable<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pRefPtr)
+ {
+ *pRefPtr = ent->mData;
+
+ NS_IF_ADDREF(*pRefPtr);
+ }
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pRefPtr to null
+ // so that it is a valid XPCOM getter
+ if (pRefPtr)
+ *pRefPtr = nsnull;
+
+ return PR_FALSE;
+}
+
+template<class KeyClass, class RefPtr>
+RefPtr*
+nsRefPtrHashtable<KeyClass,RefPtr>::GetWeak
+ (KeyType aKey, PRBool* aFound) const
+{
+ typename nsBaseHashtable<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (aFound)
+ *aFound = PR_TRUE;
+
+ return ent->mData;
+ }
+
+ // Key does not exist, return nsnull and set aFound to PR_FALSE
+ if (aFound)
+ *aFound = PR_FALSE;
+ return nsnull;
+}
+
+//
+// nsRefPtrHashtableMT definitions
+//
+
+template<class KeyClass, class RefPtr>
+PRBool
+nsRefPtrHashtableMT<KeyClass,RefPtr>::Get
+ (KeyType aKey, UserDataType* pRefPtr) const
+{
+ PR_Lock(this->mLock);
+
+ typename nsBaseHashtableMT<KeyClass, nsRefPtr<RefPtr>, RefPtr*>::EntryType* ent =
+ this->GetEntry(aKey);
+
+ if (ent)
+ {
+ if (pRefPtr)
+ {
+ *pRefPtr = ent->mData;
+
+ NS_IF_ADDREF(*pRefPtr);
+ }
+
+ PR_Unlock(this->mLock);
+
+ return PR_TRUE;
+ }
+
+ // if the key doesn't exist, set *pRefPtr to null
+ // so that it is a valid XPCOM getter
+ if (pRefPtr)
+ *pRefPtr = nsnull;
+
+ PR_Unlock(this->mLock);
+
+ return PR_FALSE;
+}
+
+#endif // nsRefPtrHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h b/src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h
new file mode 100644
index 00000000..6c76d016
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStaticAtom.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Static Atom classes.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 ***** */
+
+#ifndef nsStaticAtom_h__
+#define nsStaticAtom_h__
+
+#include "nsIAtom.h"
+
+// see http://www.mozilla.org/projects/xpcom/atoms.html to use this stuff
+
+// class for declaring a static list of atoms, for use with gperf
+// Keep this VERY simple
+// mString: the value of the atom - the policy is that this is only
+// ASCII, in order to avoid unnecessary conversions if
+// someone asks for this in unicode
+// mAtom: a convienience pointer - if you want to store the value of
+// the atom created by this structure somewhere, put its
+// address here
+struct nsStaticAtom {
+ const char* mString;
+ nsIAtom ** mAtom;
+};
+
+
+// register your lookup function with the atom table. Your function
+// will be called when at atom is not found in the main atom table.
+NS_COM nsresult
+NS_RegisterStaticAtoms(const nsStaticAtom*, PRUint32 aAtomCount);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp
new file mode 100644
index 00000000..35489c6a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.cpp
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Class to manage lookup of static names in a table. */
+
+#include "nsCRT.h"
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+#define PL_ARENA_CONST_ALIGN_MASK 3
+#include "nsStaticNameTable.h"
+
+struct NameTableEntry : public PLDHashEntryHdr
+{
+ // no ownership here!
+ const char *mKey;
+ PRInt32 mIndex;
+};
+
+PR_STATIC_CALLBACK(PRBool)
+matchNameKeysCaseInsensitive(PLDHashTable*, const PLDHashEntryHdr* aHdr,
+ const void* key)
+{
+ const NameTableEntry* entry =
+ NS_STATIC_CAST(const NameTableEntry *, aHdr);
+ const char *keyValue = NS_STATIC_CAST(const char*, key);
+
+ return (nsCRT::strcasecmp(entry->mKey, keyValue)==0);
+}
+
+/*
+ * caseInsensitiveHashKey is just like PL_DHashStringKey except it
+ * uses (*s & ~0x20) instead of simply *s. This means that "aFOO" and
+ * "afoo" and "aFoo" will all hash to the same thing. It also means
+ * that some strings that aren't case-insensensitively equal will hash
+ * to the same value, but it's just a hash function so it doesn't
+ * matter.
+ */
+PR_STATIC_CALLBACK(PLDHashNumber)
+caseInsensitiveStringHashKey(PLDHashTable *table, const void *key)
+{
+ PLDHashNumber h = 0;
+ for (const unsigned char* s =
+ NS_STATIC_CAST(const unsigned char*, key);
+ *s != '\0';
+ s++)
+ h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ (*s & ~0x20);
+ return h;
+}
+
+static const struct PLDHashTableOps nametable_CaseInsensitiveHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ caseInsensitiveStringHashKey,
+ matchNameKeysCaseInsensitive,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ nsnull,
+};
+
+nsStaticCaseInsensitiveNameTable::nsStaticCaseInsensitiveNameTable()
+ : mNameArray(nsnull), mNullStr("")
+{
+ MOZ_COUNT_CTOR(nsStaticCaseInsensitiveNameTable);
+ mNameTable.ops = nsnull;
+}
+
+nsStaticCaseInsensitiveNameTable::~nsStaticCaseInsensitiveNameTable()
+{
+ if (mNameArray) {
+ // manually call the destructor on placement-new'ed objects
+ for (PRUint32 index = 0; index < mNameTable.entryCount; index++) {
+ mNameArray[index].~nsDependentCString();
+ }
+ nsMemory::Free((void*)mNameArray);
+ }
+ if (mNameTable.ops)
+ PL_DHashTableFinish(&mNameTable);
+ MOZ_COUNT_DTOR(nsStaticCaseInsensitiveNameTable);
+}
+
+PRBool
+nsStaticCaseInsensitiveNameTable::Init(const char* const aNames[], PRInt32 Count)
+{
+ NS_ASSERTION(!mNameArray, "double Init");
+ NS_ASSERTION(!mNameTable.ops, "double Init");
+ NS_ASSERTION(aNames, "null name table");
+ NS_ASSERTION(Count, "0 count");
+
+ mNameArray = (nsDependentCString*)
+ nsMemory::Alloc(Count * sizeof(nsDependentCString));
+ if (!mNameArray)
+ return PR_FALSE;
+
+ if (!PL_DHashTableInit(&mNameTable,
+ &nametable_CaseInsensitiveHashTableOps,
+ nsnull, sizeof(NameTableEntry), Count)) {
+ mNameTable.ops = nsnull;
+ return PR_FALSE;
+ }
+
+ for (PRInt32 index = 0; index < Count; ++index) {
+ const char* raw = aNames[index];
+#ifdef DEBUG
+ {
+ // verify invariants of contents
+ nsCAutoString temp1(raw);
+ nsDependentCString temp2(raw);
+ ToLowerCase(temp1);
+ NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
+ NS_ASSERTION(nsCRT::IsAscii(raw),
+ "non-ascii string in table -- "
+ "case-insensitive matching won't work right");
+ }
+#endif
+ // use placement-new to initialize the string object
+ new (&mNameArray[index]) nsDependentCString(raw);
+
+ NameTableEntry *entry =
+ NS_STATIC_CAST(NameTableEntry*,
+ PL_DHashTableOperate(&mNameTable, raw, PL_DHASH_ADD));
+
+ if (!entry) continue;
+
+ NS_ASSERTION(entry->mKey == 0, "Entry already exists!");
+
+ entry->mKey = raw; // not owned!
+ entry->mIndex = index;
+ }
+ return PR_TRUE;
+}
+
+inline PRInt32
+LookupFlatKeyword(const nsAFlatCString& aKeyword,
+ PLDHashTable& aTable)
+{
+ NameTableEntry *entry =
+ NS_STATIC_CAST(NameTableEntry*,
+ PL_DHashTableOperate(&aTable, aKeyword.get(), PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(entry))
+ return nsStaticCaseInsensitiveNameTable::NOT_FOUND;
+
+ return entry->mIndex;
+}
+
+PRInt32
+nsStaticCaseInsensitiveNameTable::Lookup(const nsACString& aName)
+{
+ NS_ASSERTION(mNameArray, "not inited");
+ NS_ASSERTION(mNameTable.ops, "not inited");
+
+ return LookupFlatKeyword(PromiseFlatCString(aName), mNameTable);
+}
+
+PRInt32
+nsStaticCaseInsensitiveNameTable::Lookup(const nsAString& aName)
+{
+ NS_ASSERTION(mNameArray, "not inited");
+ NS_ASSERTION(mNameTable.ops, "not inited");
+
+ nsCAutoString cstring;
+ cstring.AssignWithConversion(aName);
+ return LookupFlatKeyword(cstring, mNameTable);
+}
+
+const nsAFlatCString&
+nsStaticCaseInsensitiveNameTable::GetStringValue(PRInt32 index)
+{
+ NS_ASSERTION(mNameArray, "not inited");
+ NS_ASSERTION(mNameTable.ops, "not inited");
+
+ if ((NOT_FOUND < index) && ((PRUint32)index < mNameTable.entryCount)) {
+ return mNameArray[index];
+ }
+ return mNullStr;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h
new file mode 100644
index 00000000..154a1c9d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStaticNameTable.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Classes to manage lookup of static names in a table. */
+
+#ifndef nsStaticNameTable_h___
+#define nsStaticNameTable_h___
+
+#include "pldhash.h"
+/* This class supports case insensitive lookup.
+ *
+ * It differs from atom tables:
+ * - It supports case insensitive lookup.
+ * - It has minimal footprint by not copying the string table.
+ * - It does no locking.
+ * - It returns zero based indexes and const nsCString& as required by its
+ * callers in the parser.
+ * - It is not an xpcom interface - meant for fast lookup in static tables.
+ *
+ * ***REQUIREMENTS***
+ * - It *requires* that all entries in the table be lowercase only.
+ * - It *requires* that the table of strings be in memory that lives at least
+ * as long as this table object - typically a static string array.
+ */
+
+class NS_COM nsStaticCaseInsensitiveNameTable
+{
+public:
+ enum { NOT_FOUND = -1 };
+
+ PRBool Init(const char* const aNames[], PRInt32 Count);
+ PRInt32 Lookup(const nsACString& aName);
+ PRInt32 Lookup(const nsAString& aName);
+ const nsAFlatCString& GetStringValue(PRInt32 index);
+
+ nsStaticCaseInsensitiveNameTable();
+ ~nsStaticCaseInsensitiveNameTable();
+
+private:
+ nsDependentCString* mNameArray;
+ PLDHashTable mNameTable;
+ nsDependentCString mNullStr;
+};
+
+#endif /* nsStaticNameTable_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp
new file mode 100644
index 00000000..8a10b18c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Enumerator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsStringEnumerator.h"
+#include "prtypes.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsISimpleEnumerator.h"
+#include "nsSupportsPrimitives.h"
+
+//
+// nsStringEnumerator
+//
+
+class nsStringEnumerator : public nsIStringEnumerator,
+ public nsIUTF8StringEnumerator,
+ public nsISimpleEnumerator
+{
+public:
+ nsStringEnumerator(const nsStringArray* aArray, PRBool aOwnsArray) :
+ mArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(PR_TRUE)
+ {}
+
+ nsStringEnumerator(const nsCStringArray* aArray, PRBool aOwnsArray) :
+ mCArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(PR_FALSE)
+ {}
+
+ nsStringEnumerator(const nsStringArray* aArray, nsISupports* aOwner) :
+ mArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(PR_FALSE), mIsUnicode(PR_TRUE)
+ {}
+
+ nsStringEnumerator(const nsCStringArray* aArray, nsISupports* aOwner) :
+ mCArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(PR_FALSE), mIsUnicode(PR_FALSE)
+ {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIUTF8STRINGENUMERATOR
+
+ // have to declare nsIStringEnumerator manually, because of
+ // overlapping method names
+ NS_IMETHOD GetNext(nsAString& aResult);
+ NS_DECL_NSISIMPLEENUMERATOR
+
+private:
+ ~nsStringEnumerator() {
+ if (mOwnsArray) {
+ // const-casting is safe here, because the NS_New*
+ // constructors make sure mOwnsArray is consistent with
+ // the constness of the objects
+ if (mIsUnicode)
+ delete NS_CONST_CAST(nsStringArray*,mArray);
+ else
+ delete NS_CONST_CAST(nsCStringArray*,mCArray);
+ }
+ }
+
+ union {
+ const nsStringArray* mArray;
+ const nsCStringArray* mCArray;
+ };
+
+ inline PRUint32 Count() {
+ return mIsUnicode ? mArray->Count() : mCArray->Count();
+ }
+
+ PRUint32 mIndex;
+
+ // the owner allows us to hold a strong reference to the object
+ // that owns the array. Having a non-null value in mOwner implies
+ // that mOwnsArray is PR_FALSE, because we rely on the real owner
+ // to release the array
+ nsCOMPtr<nsISupports> mOwner;
+ PRPackedBool mOwnsArray;
+ PRPackedBool mIsUnicode;
+};
+
+NS_IMPL_ISUPPORTS3(nsStringEnumerator,
+ nsIStringEnumerator,
+ nsIUTF8StringEnumerator,
+ nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsStringEnumerator::HasMore(PRBool* aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = mIndex < Count();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::HasMoreElements(PRBool* aResult)
+{
+ return HasMore(aResult);
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::GetNext(nsISupports** aResult)
+{
+ if (mIsUnicode) {
+ nsSupportsStringImpl* stringImpl = new nsSupportsStringImpl();
+ if (!stringImpl) return NS_ERROR_OUT_OF_MEMORY;
+
+ stringImpl->SetData(*mArray->StringAt(mIndex++));
+ *aResult = stringImpl;
+ }
+ else {
+ nsSupportsCStringImpl* cstringImpl = new nsSupportsCStringImpl();
+ if (!cstringImpl) return NS_ERROR_OUT_OF_MEMORY;
+
+ cstringImpl->SetData(*mCArray->CStringAt(mIndex++));
+ *aResult = cstringImpl;
+ }
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::GetNext(nsAString& aResult)
+{
+ NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
+
+ if (mIsUnicode)
+ aResult = *mArray->StringAt(mIndex++);
+ else
+ CopyUTF8toUTF16(*mCArray->CStringAt(mIndex++), aResult);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringEnumerator::GetNext(nsACString& aResult)
+{
+ NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
+
+ if (mIsUnicode)
+ CopyUTF16toUTF8(*mArray->StringAt(mIndex++), aResult);
+ else
+ aResult = *mCArray->CStringAt(mIndex++);
+
+ return NS_OK;
+}
+
+template<class T>
+static inline nsresult
+StringEnumeratorTail(T** aResult)
+{
+ if (!*aResult)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+//
+// constructors
+//
+
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray, nsISupports* aOwner)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, aOwner);
+ return StringEnumeratorTail(aResult);
+}
+
+
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray, nsISupports* aOwner)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, aOwner);
+ return StringEnumeratorTail(aResult);
+}
+
+NS_COM nsresult
+NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult,
+ nsStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_TRUE);
+ return StringEnumeratorTail(aResult);
+}
+
+NS_COM nsresult
+NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ nsCStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_TRUE);
+ return StringEnumeratorTail(aResult);
+}
+
+// const ones internally just forward to the non-const equivalents
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_FALSE);
+ return StringEnumeratorTail(aResult);
+}
+
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ NS_ENSURE_ARG_POINTER(aArray);
+
+ *aResult = new nsStringEnumerator(aArray, PR_FALSE);
+ return StringEnumeratorTail(aResult);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h
new file mode 100644
index 00000000..d0080005
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsStringEnumerator.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Enumerator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Alec Flett <alecf@netscape.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 "nsIStringEnumerator.h"
+#include "nsVoidArray.h"
+
+// nsIStringEnumerator/nsIUTF8StringEnumerator implementations
+//
+// Currently all implementations support both interfaces. The
+// constructors below provide the most common interface for the given
+// type (i.e. nsIStringEnumerator for PRUnichar* strings, and so
+// forth) but any resulting enumerators can be queried to the other
+// type. Internally, the enumerators will hold onto the type that was
+// passed in and do conversion if GetNext() for the other type of
+// string is called.
+
+// There are a few different types of enumerators:
+
+//
+// These enumerators hold a pointer to the array. Be careful
+// because modifying the array may confuse the iterator, especially if
+// you insert or remove elements in the middle of the array.
+//
+
+// The non-adopting enumerator requires that the array sticks around
+// at least as long as the enumerator does. These are for constant
+// string arrays that the enumerator does not own, this could be used
+// in VERY specialized cases such as when the provider KNOWS that the
+// string enumerator will be consumed immediately, or will at least
+// outlast the array.
+// For example:
+//
+// nsCStringArray array;
+// array.AppendCString("abc");
+// array.AppendCString("def");
+// NS_NewStringEnumerator(&enumerator, &array, PR_TRUE);
+//
+// // call some internal method which iterates the enumerator
+// InternalMethod(enumerator);
+// NS_RELEASE(enumerator);
+//
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray);
+
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray);
+
+// Adopting string enumerators assume ownership of the array and will
+// call |operator delete| on the array when the enumerator is destroyed
+// this is useful when the provider creates an array soley for the
+// purpose of creating the enumerator.
+// For example:
+//
+// nsCStringArray* array = new nsCStringArray;
+// array->AppendString("abcd");
+// NS_NewAdoptingStringEnumerator(&result, array);
+NS_COM nsresult
+NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult,
+ nsStringArray* aArray);
+
+NS_COM nsresult
+NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ nsCStringArray* aArray);
+
+
+// these versions take a refcounted "owner" which will be addreffed
+// when the enumerator is created, and destroyed when the enumerator
+// is released. This allows providers to give non-owning pointers to
+// ns*StringArray member variables without worrying about lifetime
+// issues
+// For example:
+//
+// nsresult MyClass::Enumerate(nsIUTF8StringEnumerator** aResult) {
+// mCategoryList->AppendString("abcd");
+// return NS_NewStringEnumerator(aResult, mCategoryList, this);
+// }
+//
+NS_COM nsresult
+NS_NewStringEnumerator(nsIStringEnumerator** aResult,
+ const nsStringArray* aArray,
+ nsISupports* aOwner);
+NS_COM nsresult
+NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
+ const nsCStringArray* aArray,
+ nsISupports* aOwner);
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp
new file mode 100644
index 00000000..e0774083
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.cpp
@@ -0,0 +1,684 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org>: |do_QueryElementAt|
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <string.h>
+#include "prbit.h"
+#include "nsSupportsArray.h"
+#include "nsSupportsArrayEnumerator.h"
+#include "nsAString.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+
+#if DEBUG_SUPPORTSARRAY
+#define MAXSUPPORTS 20
+
+class SupportsStats {
+public:
+ SupportsStats();
+ ~SupportsStats();
+
+};
+
+static int sizesUsed; // number of the elements of the arrays used
+static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted
+static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array)
+static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used)
+static int GrowInPlace[MAXSUPPORTS];
+
+// these are per-allocation
+static int MaxElements[3000];
+
+// very evil
+#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])++; break; } \
+ } \
+ if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \
+ { sizesAlloced[sizesUsed] = (size); \
+ ((x)[sizesUsed++])++; break; \
+ } \
+ } while (0);
+
+#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])--; break; } \
+ } \
+ } while (0);
+
+
+SupportsStats::SupportsStats()
+{
+ sizesUsed = 1;
+ sizesAlloced[0] = 0;
+}
+
+SupportsStats::~SupportsStats()
+{
+ int i;
+ for (i = 0; i < sizesUsed; i++)
+ {
+ printf("Size %d:\n",sizesAlloced[i]);
+ printf("\tNumber of SupportsArrays this size (max): %d\n",NumberOfSize[i]);
+ printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]);
+ printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
+ }
+ printf("Max Size of SupportsArray:\n");
+ for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
+ {
+ if (MaxElements[i])
+ printf("\t%d: %d\n",i,MaxElements[i]);
+ }
+}
+
+// Just so constructor/destructor get called
+SupportsStats gSupportsStats;
+#endif
+
+nsresult
+nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const
+ {
+ nsresult status = mCollection
+ ? mCollection->QueryElementAt(mIndex, aIID, aResult)
+ : NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+
+ return status;
+ }
+
+static const PRInt32 kGrowArrayBy = 8;
+static const PRInt32 kLinearThreshold = 16 * sizeof(nsISupports *);
+
+nsSupportsArray::nsSupportsArray()
+{
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ mCount = 0;
+#if DEBUG_SUPPORTSARRAY
+ mMaxCount = 0;
+ mMaxSize = 0;
+ ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0]));
+ MaxElements[0]++;
+#endif
+}
+
+nsSupportsArray::~nsSupportsArray()
+{
+ DeleteArray();
+}
+
+PRBool nsSupportsArray::GrowArrayBy(PRInt32 aGrowBy)
+{
+ // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller
+ // than kLinearThreshold bytes, or a power of two if we're larger.
+ // This is much more efficient with most memory allocators, especially
+ // if it's very large, or of the allocator is binned.
+ if (aGrowBy < kGrowArrayBy)
+ aGrowBy = kGrowArrayBy;
+
+ PRUint32 newCount = mArraySize + aGrowBy; // Minimum increase
+ PRUint32 newSize = sizeof(mArray[0]) * newCount;
+
+ if (newSize >= (PRUint32) kLinearThreshold)
+ {
+ // newCount includes enough space for at least kGrowArrayBy new slots.
+ // Select the next power-of-two size in bytes above that if newSize is
+ // not a power of two.
+ if (newSize & (newSize - 1))
+ newSize = PR_BIT(PR_CeilingLog2(newSize));
+
+ newCount = newSize / sizeof(mArray[0]);
+ }
+ // XXX This would be far more efficient in many allocators if we used
+ // XXX PR_Realloc(), etc
+ nsISupports** oldArray = mArray;
+
+ mArray = new nsISupports*[newCount];
+ if (!mArray) { // ran out of memory
+ mArray = oldArray;
+ return PR_FALSE;
+ }
+ mArraySize = newCount;
+
+#if DEBUG_SUPPORTSARRAY
+ if (oldArray == mArray) // can't happen without use of realloc
+ ADD_TO_STATS(GrowInPlace,mCount);
+ ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
+ if (mArraySize > mMaxSize)
+ {
+ ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0]));
+ if (oldArray != &(mAutoArray[0]))
+ SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0]));
+ mMaxSize = mArraySize;
+ }
+#endif
+ if (oldArray) { // need to move old data
+ if (0 < mCount) {
+ ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
+ }
+ if (oldArray != &(mAutoArray[0])) {
+ delete[] oldArray;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+NS_METHOD
+nsSupportsArray::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return it->QueryInterface(aIID, aResult);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsSupportsArray, nsISupportsArray, nsICollection, nsISerializable)
+
+NS_IMETHODIMP
+nsSupportsArray::Read(nsIObjectInputStream *aStream)
+{
+ nsresult rv;
+
+ PRUint32 newArraySize;
+ rv = aStream->Read32(&newArraySize);
+
+ if (newArraySize <= kAutoArraySize) {
+ if (mArray != mAutoArray) {
+ delete[] mArray;
+ mArray = mAutoArray;
+ }
+ newArraySize = kAutoArraySize;
+ }
+ else {
+ if (newArraySize <= mArraySize) {
+ // Keep non-default-size mArray, it's more than big enough.
+ newArraySize = mArraySize;
+ }
+ else {
+ nsISupports** array = new nsISupports*[newArraySize];
+ if (!array)
+ return NS_ERROR_OUT_OF_MEMORY;
+ if (mArray != mAutoArray)
+ delete[] mArray;
+ mArray = array;
+ }
+ }
+ mArraySize = newArraySize;
+
+ rv = aStream->Read32(&mCount);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!");
+ if (mCount > mArraySize)
+ mCount = mArraySize;
+
+ for (PRUint32 i = 0; i < mCount; i++) {
+ rv = aStream->ReadObject(PR_TRUE, &mArray[i]);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Write(nsIObjectOutputStream *aStream)
+{
+ nsresult rv;
+
+ rv = aStream->Write32(mArraySize);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = aStream->Write32(mCount);
+ if (NS_FAILED(rv)) return rv;
+
+ for (PRUint32 i = 0; i < mCount; i++) {
+ rv = aStream->WriteObject(mArray[i], PR_TRUE);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return NS_OK;
+}
+
+void nsSupportsArray::DeleteArray(void)
+{
+ Clear();
+ if (mArray != &(mAutoArray[0])) {
+ delete[] mArray;
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ }
+}
+
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::Equals(const nsISupportsArray* aOther)
+{
+ if (aOther) {
+ PRUint32 countOther;
+ nsISupportsArray* other = NS_CONST_CAST(nsISupportsArray*, aOther);
+ nsresult rv = other->Count(&countOther);
+ if (NS_FAILED( rv ))
+ return PR_FALSE;
+
+ if (mCount == countOther) {
+ PRUint32 index = mCount;
+ nsCOMPtr<nsISupports> otherElem;
+ while (index--) {
+ if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem))))
+ return PR_FALSE;
+ if (mArray[index] != otherElem)
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(nsISupports*)
+nsSupportsArray::ElementAt(PRUint32 aIndex)
+{
+ if (aIndex < mCount) {
+ nsISupports* element = mArray[aIndex];
+ NS_IF_ADDREF(element);
+ return element;
+ }
+ return 0;
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsSupportsArray::IndexOf(const nsISupports* aPossibleElement)
+{
+ return IndexOfStartingAt(aPossibleElement, 0);
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement,
+ PRUint32 aStartIndex)
+{
+ if (aStartIndex < mCount) {
+ const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior
+ const nsISupports** ep = (start + aStartIndex);
+ const nsISupports** end = (start + mCount);
+ while (ep < end) {
+ if (aPossibleElement == *ep) {
+ return (ep - start);
+ }
+ ep++;
+ }
+ }
+ return -1;
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement)
+{
+ if (0 < mCount) {
+ const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior
+ const nsISupports** ep = (start + mCount);
+ while (start <= --ep) {
+ if (aPossibleElement == *ep) {
+ return (ep - start);
+ }
+ }
+ }
+ return -1;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex)
+{
+ if (aIndex <= mCount) {
+ if (mArraySize < (mCount + 1)) {
+ // need to grow the array
+ if (!GrowArrayBy(1))
+ return PR_FALSE;
+ }
+
+ // Could be slightly more efficient if GrowArrayBy knew about the
+ // split, but the difference is trivial.
+ PRUint32 slide = (mCount - aIndex);
+ if (0 < slide) {
+ ::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*));
+ }
+
+ mArray[aIndex] = aElement;
+ NS_IF_ADDREF(aElement);
+ mCount++;
+
+#if DEBUG_SUPPORTSARRAY
+ if (mCount > mMaxCount &&
+ mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mCount;
+ }
+#endif
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, PRUint32 aIndex)
+{
+ if (!aElements) {
+ return PR_FALSE;
+ }
+ PRUint32 countElements;
+ if (NS_FAILED( aElements->Count( &countElements ) ))
+ return PR_FALSE;
+
+ if (aIndex <= mCount) {
+ if (mArraySize < (mCount + countElements)) {
+ // need to grow the array
+ if (!GrowArrayBy(countElements))
+ return PR_FALSE;
+ }
+
+ // Could be slightly more efficient if GrowArrayBy knew about the
+ // split, but the difference is trivial.
+ PRUint32 slide = (mCount - aIndex);
+ if (0 < slide) {
+ ::memmove(mArray + aIndex + countElements, mArray + aIndex,
+ slide * sizeof(nsISupports*));
+ }
+
+ for (PRUint32 i = 0; i < countElements; ++i, ++mCount) {
+ // use GetElementAt to copy and do AddRef for us
+ if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) ))
+ return PR_FALSE;
+ }
+
+#if DEBUG_SUPPORTSARRAY
+ if (mCount > mMaxCount &&
+ mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mCount;
+ }
+#endif
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex)
+{
+ if (aIndex < mCount) {
+ NS_IF_ADDREF(aElement); // addref first in case it's the same object!
+ NS_IF_RELEASE(mArray[aIndex]);
+ mArray[aIndex] = aElement;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount)
+{
+ if (aIndex + aCount <= mCount) {
+ for (PRUint32 i = 0; i < aCount; i++)
+ NS_IF_RELEASE(mArray[aIndex+i]);
+ mCount -= aCount;
+ PRInt32 slide = (mCount - aIndex);
+ if (0 < slide) {
+ ::memmove(mArray + aIndex, mArray + aIndex + aCount,
+ slide * sizeof(nsISupports*));
+ }
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex)
+{
+ PRInt32 theIndex = IndexOfStartingAt(aElement,aStartIndex);
+ if (theIndex >= 0)
+ return RemoveElementAt(theIndex);
+
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::RemoveLastElement(const nsISupports* aElement)
+{
+ PRInt32 theIndex = LastIndexOf(aElement);
+ if (theIndex >= 0)
+ return RemoveElementAt(theIndex);
+
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
+{
+ nsISupports *tempElement;
+
+ if (aTo == aFrom)
+ return PR_TRUE;
+
+ if (aTo < 0 || aFrom < 0 ||
+ (PRUint32) aTo >= mCount || (PRUint32) aFrom >= mCount)
+ {
+ // can't extend the array when moving an element. Also catches mImpl = null
+ return PR_FALSE;
+ }
+ tempElement = mArray[aFrom];
+
+ if (aTo < aFrom)
+ {
+ // Moving one element closer to the head; the elements inbetween move down
+ ::memmove(mArray + aTo + 1, mArray + aTo,
+ (aFrom-aTo) * sizeof(mArray[0]));
+ mArray[aTo] = tempElement;
+ }
+ else // already handled aFrom == aTo
+ {
+ // Moving one element closer to the tail; the elements inbetween move up
+ ::memmove(mArray + aFrom, mArray + aFrom + 1,
+ (aTo-aFrom) * sizeof(mArray[0]));
+ mArray[aTo] = tempElement;
+ }
+
+ return PR_TRUE;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Clear(void)
+{
+ if (0 < mCount) {
+ do {
+ --mCount;
+ NS_IF_RELEASE(mArray[mCount]);
+ } while (0 != mCount);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Compact(void)
+{
+#if DEBUG_SUPPORTSARRAY
+ PRUint32 oldArraySize = mArraySize;
+#endif
+ if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) {
+ nsISupports** oldArray = mArray;
+ if (mCount <= kAutoArraySize) {
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ }
+ else {
+ mArray = new nsISupports*[mCount];
+ if (!mArray) {
+ mArray = oldArray;
+ return NS_OK;
+ }
+ mArraySize = mCount;
+ }
+#if DEBUG_SUPPORTSARRAY
+ if (oldArray == mArray &&
+ oldArray != &(mAutoArray[0])) // can't happen without use of realloc
+ ADD_TO_STATS(GrowInPlace,oldArraySize);
+ if (oldArray != &(mAutoArray[0]))
+ ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
+#endif
+ ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
+ delete[] oldArray;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::SizeTo(PRInt32 aSize)
+{
+#if DEBUG_SUPPORTSARRAY
+ PRUint32 oldArraySize = mArraySize;
+#endif
+ NS_ASSERTION(aSize >= 0, "negative aSize!");
+
+ // XXX for aSize < mCount we could resize to mCount
+ if (mArraySize == (PRUint32) aSize || (PRUint32) aSize < mCount)
+ return PR_TRUE; // nothing to do
+
+ // switch back to autoarray if possible
+ nsISupports** oldArray = mArray;
+ if ((PRUint32) aSize <= kAutoArraySize) {
+ mArray = mAutoArray;
+ mArraySize = kAutoArraySize;
+ }
+ else {
+ mArray = new nsISupports*[aSize];
+ if (!mArray) {
+ mArray = oldArray;
+ return PR_FALSE;
+ }
+ mArraySize = aSize;
+ }
+#if DEBUG_SUPPORTSARRAY
+ if (oldArray == mArray &&
+ oldArray != &(mAutoArray[0])) // can't happen without use of realloc
+ ADD_TO_STATS(GrowInPlace,oldArraySize);
+ if (oldArray != &(mAutoArray[0]))
+ ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
+#endif
+ ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
+ if (oldArray != mAutoArray)
+ delete[] oldArray;
+
+ return PR_TRUE;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 aIndex = -1;
+ PRBool running = PR_TRUE;
+
+ while (running && (++aIndex < (PRInt32)mCount)) {
+ running = (*aFunc)(mArray[aIndex], aData);
+ }
+ return running;
+}
+
+NS_IMETHODIMP_(PRBool)
+nsSupportsArray::EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData)
+{
+ PRUint32 aIndex = mCount;
+ PRBool running = PR_TRUE;
+
+ while (running && (0 < aIndex--)) {
+ running = (*aFunc)(mArray[aIndex], aData);
+ }
+ return running;
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Enumerate(nsIEnumerator* *result)
+{
+ nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(this);
+ if (!e)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = e;
+ NS_ADDREF(e);
+ return NS_OK;
+}
+
+static PRBool
+CopyElement(nsISupports* aElement, void *aData)
+{
+ nsresult rv;
+ nsISupportsArray* newArray = (nsISupportsArray*)aData;
+ rv = newArray->AppendElement(aElement);
+ return NS_SUCCEEDED(rv);
+}
+
+NS_IMETHODIMP
+nsSupportsArray::Clone(nsISupportsArray* *result)
+{
+ nsresult rv;
+ nsISupportsArray* newArray;
+ rv = NS_NewISupportsArray(&newArray);
+ PRBool ok = EnumerateForwards(CopyElement, newArray);
+ if (!ok) return NS_ERROR_OUT_OF_MEMORY;
+ *result = newArray;
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
+{
+ nsresult rv;
+ rv = nsSupportsArray::Create(NULL, NS_GET_IID(nsISupportsArray),
+ (void**)aInstancePtrResult);
+ return rv;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h
new file mode 100644
index 00000000..0f9c9601
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArray.h
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSupportsArray_h__
+#define nsSupportsArray_h__
+
+//#define DEBUG_SUPPORTSARRAY 1
+
+#include "nsISupportsArray.h"
+
+static const PRUint32 kAutoArraySize = 8;
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+
+class NS_COM nsSupportsArray : public nsISupportsArray {
+public:
+ nsSupportsArray(void);
+ ~nsSupportsArray(void); // nonvirtual since we're not subclassed
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSISERIALIZABLE
+
+ // nsICollection methods:
+ NS_IMETHOD Count(PRUint32 *result) { *result = mCount; return NS_OK; }
+ NS_IMETHOD GetElementAt(PRUint32 aIndex, nsISupports* *result) {
+ *result = ElementAt(aIndex);
+ return NS_OK;
+ }
+ NS_IMETHOD QueryElementAt(PRUint32 aIndex, const nsIID & aIID, void * *aResult) {
+ if (aIndex < mCount) {
+ nsISupports* element = mArray[aIndex];
+ if (nsnull != element)
+ return element->QueryInterface(aIID, aResult);
+ }
+ return NS_ERROR_FAILURE;
+ }
+ NS_IMETHOD SetElementAt(PRUint32 aIndex, nsISupports* value) {
+ return ReplaceElementAt(value, aIndex) ? NS_OK : NS_ERROR_FAILURE;
+ }
+ NS_IMETHOD AppendElement(nsISupports *aElement) {
+ return InsertElementAt(aElement, mCount)/* ? NS_OK : NS_ERROR_FAILURE*/;
+ }
+ // XXX this is badly named - should be RemoveFirstElement
+ NS_IMETHOD RemoveElement(nsISupports *aElement) {
+ return RemoveElement(aElement, 0)/* ? NS_OK : NS_ERROR_FAILURE*/;
+ }
+ NS_IMETHOD_(PRBool) MoveElement(PRInt32 aFrom, PRInt32 aTo);
+ NS_IMETHOD Enumerate(nsIEnumerator* *result);
+ NS_IMETHOD Clear(void);
+
+ // nsISupportsArray methods:
+ NS_IMETHOD_(PRBool) Equals(const nsISupportsArray* aOther);
+
+ NS_IMETHOD_(nsISupports*) ElementAt(PRUint32 aIndex);
+
+ NS_IMETHOD_(PRInt32) IndexOf(const nsISupports* aPossibleElement);
+ NS_IMETHOD_(PRInt32) IndexOfStartingAt(const nsISupports* aPossibleElement,
+ PRUint32 aStartIndex = 0);
+ NS_IMETHOD_(PRInt32) LastIndexOf(const nsISupports* aPossibleElement);
+
+ NS_IMETHOD GetIndexOf(nsISupports *aPossibleElement, PRInt32 *_retval) {
+ *_retval = IndexOf(aPossibleElement);
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetIndexOfStartingAt(nsISupports *aPossibleElement,
+ PRUint32 aStartIndex, PRInt32 *_retval) {
+ *_retval = IndexOfStartingAt(aPossibleElement, aStartIndex);
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetLastIndexOf(nsISupports *aPossibleElement, PRInt32 *_retval) {
+ *_retval = LastIndexOf(aPossibleElement);
+ return NS_OK;
+ }
+
+ NS_IMETHOD_(PRBool) InsertElementAt(nsISupports* aElement, PRUint32 aIndex);
+
+ NS_IMETHOD_(PRBool) ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex);
+
+ NS_IMETHOD_(PRBool) RemoveElementAt(PRUint32 aIndex) {
+ return RemoveElementsAt(aIndex,1);
+ }
+ NS_IMETHOD_(PRBool) RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex = 0);
+ NS_IMETHOD_(PRBool) RemoveLastElement(const nsISupports* aElement);
+
+ NS_IMETHOD DeleteLastElement(nsISupports *aElement) {
+ return (RemoveLastElement(aElement) ? NS_OK : NS_ERROR_FAILURE);
+ }
+
+ NS_IMETHOD DeleteElementAt(PRUint32 aIndex) {
+ return (RemoveElementAt(aIndex) ? NS_OK : NS_ERROR_FAILURE);
+ }
+
+ NS_IMETHOD_(PRBool) AppendElements(nsISupportsArray* aElements) {
+ return InsertElementsAt(aElements,mCount);
+ }
+
+ NS_IMETHOD Compact(void);
+
+ NS_IMETHOD_(PRBool) EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData);
+ NS_IMETHOD_(PRBool) EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData);
+
+ NS_IMETHOD Clone(nsISupportsArray **_retval);
+
+ NS_IMETHOD_(PRBool) InsertElementsAt(nsISupportsArray *aOther, PRUint32 aIndex);
+
+ NS_IMETHOD_(PRBool) RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount);
+
+ NS_IMETHOD_(PRBool) SizeTo(PRInt32 aSize);
+protected:
+ void DeleteArray(void);
+
+ NS_IMETHOD_(PRBool) GrowArrayBy(PRInt32 aGrowBy);
+
+ nsISupports** mArray;
+ PRUint32 mArraySize;
+ PRUint32 mCount;
+ nsISupports* mAutoArray[kAutoArraySize];
+#if DEBUG_SUPPORTSARRAY
+ PRUint32 mMaxCount;
+ PRUint32 mMaxSize;
+#endif
+
+private:
+ // Copy constructors are not allowed
+ nsSupportsArray(const nsISupportsArray& other);
+};
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+#endif // nsSupportsArray_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp
new file mode 100644
index 00000000..38d7d728
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSupportsArrayEnumerator.h"
+#include "nsISupportsArray.h"
+
+nsSupportsArrayEnumerator::nsSupportsArrayEnumerator(nsISupportsArray* array)
+ : mArray(array), mCursor(0)
+{
+ NS_ASSERTION(array, "null array");
+ NS_ADDREF(mArray);
+}
+
+nsSupportsArrayEnumerator::~nsSupportsArrayEnumerator()
+{
+ NS_RELEASE(mArray);
+}
+
+NS_IMPL_ISUPPORTS2(nsSupportsArrayEnumerator, nsIBidirectionalEnumerator, nsIEnumerator)
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::First()
+{
+ mCursor = 0;
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 end = (PRInt32)cnt;
+ if (mCursor < end)
+ return NS_OK;
+ else
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::Next()
+{
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 end = (PRInt32)cnt;
+ if (mCursor < end) // don't count upward forever
+ mCursor++;
+ if (mCursor < end)
+ return NS_OK;
+ else
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::CurrentItem(nsISupports **aItem)
+{
+ NS_ASSERTION(aItem, "null out parameter");
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ if (mCursor >= 0 && mCursor < (PRInt32)cnt) {
+ *aItem = mArray->ElementAt(mCursor);
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::IsDone()
+{
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ return (mCursor >= 0 && mCursor < (PRInt32)cnt)
+ ? NS_ENUMERATOR_FALSE : NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::Last()
+{
+ PRUint32 cnt;
+ nsresult rv = mArray->Count(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ mCursor = cnt - 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsArrayEnumerator::Prev()
+{
+ if (mCursor >= 0)
+ --mCursor;
+ if (mCursor >= 0)
+ return NS_OK;
+ else
+ return NS_ERROR_FAILURE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_NewISupportsArrayEnumerator(nsISupportsArray* array,
+ nsIBidirectionalEnumerator* *aInstancePtrResult)
+{
+ if (aInstancePtrResult == 0)
+ return NS_ERROR_NULL_POINTER;
+ nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(array);
+ if (e == 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(e);
+ *aInstancePtrResult = e;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h
new file mode 100644
index 00000000..e987709f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsArrayEnumerator.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSupportsArrayEnumerator_h___
+#define nsSupportsArrayEnumerator_h___
+
+#include "nsIEnumerator.h"
+
+class nsISupportsArray;
+
+class nsSupportsArrayEnumerator : public nsIBidirectionalEnumerator {
+public:
+ NS_DECL_ISUPPORTS
+
+ nsSupportsArrayEnumerator(nsISupportsArray* array);
+
+ // nsIEnumerator methods:
+ NS_DECL_NSIENUMERATOR
+
+ // nsIBidirectionalEnumerator methods:
+ NS_DECL_NSIBIDIRECTIONALENUMERATOR
+
+private:
+ ~nsSupportsArrayEnumerator();
+
+protected:
+ nsISupportsArray* mArray;
+ PRInt32 mCursor;
+
+};
+
+#endif // __nsSupportsArrayEnumerator_h
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp
new file mode 100644
index 00000000..7fe5502a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.cpp
@@ -0,0 +1,880 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSupportsPrimitives.h"
+#include "nsCRT.h"
+#include "nsMemory.h"
+#include "prprf.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsDependentString.h"
+#include "nsReadableUtils.h"
+#include "nsPromiseFlatString.h"
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsIDImpl, nsISupportsID, nsISupportsPrimitive)
+
+nsSupportsIDImpl::nsSupportsIDImpl()
+ : mData(nsnull)
+{
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_ID;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::GetData(nsID **aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ if(mData)
+ {
+ *aData = (nsID*) nsMemory::Clone(mData, sizeof(nsID));
+ return *aData ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aData = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::SetData(const nsID *aData)
+{
+ if(mData)
+ nsMemory::Free(mData);
+ if(aData)
+ mData = (nsID*) nsMemory::Clone(aData, sizeof(nsID));
+ else
+ mData = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsIDImpl::ToString(char **_retval)
+{
+ char* result;
+ NS_ASSERTION(_retval, "Bad pointer");
+ if(mData)
+ {
+ result = mData->ToString();
+ }
+ else
+ {
+ static const char nullStr[] = "null";
+ result = (char*) nsMemory::Clone(nullStr, sizeof(nullStr));
+ }
+
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/*****************************************************************************
+ * nsSupportsCStringImpl
+ *****************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsCStringImpl, nsISupportsCString,
+ nsISupportsPrimitive)
+
+NS_IMETHODIMP nsSupportsCStringImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+
+ *aType = TYPE_CSTRING;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCStringImpl::GetData(nsACString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCStringImpl::ToString(char **_retval)
+{
+ *_retval = ToNewCString(mData);
+
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCStringImpl::SetData(const nsACString& aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+/*****************************************************************************
+ * nsSupportsStringImpl
+ *****************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsStringImpl, nsISupportsString,
+ nsISupportsPrimitive)
+
+NS_IMETHODIMP nsSupportsStringImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+
+ *aType = TYPE_STRING;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsStringImpl::GetData(nsAString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsStringImpl::ToString(PRUnichar **_retval)
+{
+ *_retval = ToNewUnicode(mData);
+
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsStringImpl::SetData(const nsAString& aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsSupportsPRBoolImpl, nsISupportsPRBool,
+ nsISupportsPrimitive)
+
+nsSupportsPRBoolImpl::nsSupportsPRBoolImpl()
+ : mData(PR_FALSE)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRBOOL;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::GetData(PRBool *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::SetData(PRBool aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRBoolImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ const char * str = mData ? "true" : "false";
+ char* result = (char*) nsMemory::Clone(str,
+ (strlen(str)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint8Impl, nsISupportsPRUint8,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint8Impl::nsSupportsPRUint8Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT8;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::GetData(PRUint8 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::SetData(PRUint8 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint8Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 8;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%u", (PRUint16) mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint16Impl, nsISupportsPRUint16,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint16Impl::nsSupportsPRUint16Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT16;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::GetData(PRUint16 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::SetData(PRUint16 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint16Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 8;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%u", (int) mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint32Impl, nsISupportsPRUint32,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint32Impl::nsSupportsPRUint32Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT32;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::GetData(PRUint32 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::SetData(PRUint32 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint32Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 16;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%lu", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRUint64Impl, nsISupportsPRUint64,
+ nsISupportsPrimitive)
+
+nsSupportsPRUint64Impl::nsSupportsPRUint64Impl()
+ : mData(LL_ZERO)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRUINT64;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::GetData(PRUint64 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::SetData(PRUint64 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRUint64Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%llu", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRTimeImpl, nsISupportsPRTime,
+ nsISupportsPrimitive)
+
+nsSupportsPRTimeImpl::nsSupportsPRTimeImpl()
+ : mData(LL_ZERO)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRTIME;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::GetData(PRTime *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::SetData(PRTime aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRTimeImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%llu", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsCharImpl, nsISupportsChar,
+ nsISupportsPrimitive)
+
+nsSupportsCharImpl::nsSupportsCharImpl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_CHAR;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::GetData(char *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::SetData(char aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsCharImpl::ToString(char **_retval)
+{
+ char* result;
+ NS_ASSERTION(_retval, "Bad pointer");
+
+ if(nsnull != (result = (char*) nsMemory::Alloc(2*sizeof(char))))
+ {
+ result[0] = mData;
+ result[1] = '\0';
+ }
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRInt16Impl, nsISupportsPRInt16,
+ nsISupportsPrimitive)
+
+nsSupportsPRInt16Impl::nsSupportsPRInt16Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRINT16;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::GetData(PRInt16 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::SetData(PRInt16 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt16Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 8;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%d", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRInt32Impl, nsISupportsPRInt32,
+ nsISupportsPrimitive)
+
+nsSupportsPRInt32Impl::nsSupportsPRInt32Impl()
+ : mData(0)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRINT32;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::GetData(PRInt32 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::SetData(PRInt32 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt32Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 16;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%ld", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsPRInt64Impl, nsISupportsPRInt64,
+ nsISupportsPrimitive)
+
+nsSupportsPRInt64Impl::nsSupportsPRInt64Impl()
+ : mData(LL_ZERO)
+{
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_PRINT64;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::GetData(PRInt64 *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::SetData(PRInt64 aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsPRInt64Impl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%lld", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsFloatImpl, nsISupportsFloat,
+ nsISupportsPrimitive)
+
+nsSupportsFloatImpl::nsSupportsFloatImpl()
+ : mData(float(0.0))
+{
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_FLOAT;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::GetData(float *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::SetData(float aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsFloatImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%f", (double) mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsDoubleImpl, nsISupportsDouble,
+ nsISupportsPrimitive)
+
+nsSupportsDoubleImpl::nsSupportsDoubleImpl()
+ : mData(double(0.0))
+{
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_DOUBLE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::GetData(double *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::SetData(double aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsDoubleImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+ static const int size = 32;
+ char buf[size];
+
+ PR_snprintf(buf, size, "%f", mData);
+
+ char* result = (char*) nsMemory::Clone(buf,
+ (strlen(buf)+1)*sizeof(char));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsSupportsVoidImpl, nsISupportsVoid,
+ nsISupportsPrimitive)
+
+nsSupportsVoidImpl::nsSupportsVoidImpl()
+ : mData(nsnull)
+{
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_VOID;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::GetData(void * *aData)
+{
+ NS_ASSERTION(aData, "Bad pointer");
+ *aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::SetData(void * aData)
+{
+ mData = aData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsVoidImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+
+ static const char str[] = "[raw data]";
+ char* result = (char*) nsMemory::Clone(str, sizeof(str));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsSupportsInterfacePointerImpl,
+ nsISupportsInterfacePointer,
+ nsISupportsPrimitive)
+
+nsSupportsInterfacePointerImpl::nsSupportsInterfacePointerImpl()
+ : mIID(nsnull)
+{
+}
+
+nsSupportsInterfacePointerImpl::~nsSupportsInterfacePointerImpl()
+{
+ if (mIID) {
+ nsMemory::Free(mIID);
+ }
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::GetType(PRUint16 *aType)
+{
+ NS_ASSERTION(aType, "Bad pointer");
+ *aType = TYPE_INTERFACE_POINTER;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::GetData(nsISupports **aData)
+{
+ NS_ASSERTION(aData,"Bad pointer");
+
+ *aData = mData;
+ NS_IF_ADDREF(*aData);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::SetData(nsISupports * aData)
+{
+ mData = aData;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::GetDataIID(nsID **aIID)
+{
+ NS_ASSERTION(aIID,"Bad pointer");
+
+ if(mIID)
+ {
+ *aIID = (nsID*) nsMemory::Clone(mIID, sizeof(nsID));
+ return *aIID ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aIID = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::SetDataIID(const nsID *aIID)
+{
+ if(mIID)
+ nsMemory::Free(mIID);
+ if(aIID)
+ mIID = (nsID*) nsMemory::Clone(aIID, sizeof(nsID));
+ else
+ mIID = nsnull;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsSupportsInterfacePointerImpl::ToString(char **_retval)
+{
+ NS_ASSERTION(_retval, "Bad pointer");
+
+ static const char str[] = "[interface pointer]";
+
+ // jband sez: think about asking nsIInterfaceInfoManager whether
+ // the interface has a known human-readable name
+ char* result = (char*) nsMemory::Clone(str, sizeof(str));
+ *_retval = result;
+ return result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/***************************************************************************/
+
+NS_IMPL_ISUPPORTS2(nsSupportsDependentCString,nsISupportsCString,nsISupportsPrimitive)
+
+nsSupportsDependentCString::nsSupportsDependentCString(const char* aStr)
+ : mData(aStr)
+{ }
+
+NS_IMETHODIMP
+nsSupportsDependentCString::GetType(PRUint16 *aType)
+{
+ NS_ENSURE_ARG_POINTER(aType);
+
+ *aType = TYPE_CSTRING;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsDependentCString::GetData(nsACString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsDependentCString::ToString(char **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = ToNewCString(mData);
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSupportsDependentCString::SetData(const nsACString& aData)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h
new file mode 100644
index 00000000..81e83fa3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsSupportsPrimitives.h
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Rosen <dr@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSupportsPrimitives_h__
+#define nsSupportsPrimitives_h__
+
+#include "nsISupportsPrimitives.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+
+class nsSupportsIDImpl : public nsISupportsID
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSID
+
+ nsSupportsIDImpl();
+
+private:
+ ~nsSupportsIDImpl() { }
+
+ nsID *mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsCStringImpl : public nsISupportsCString
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSCSTRING
+
+ nsSupportsCStringImpl() {}
+
+private:
+ ~nsSupportsCStringImpl() {}
+
+ nsCString mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsStringImpl : public nsISupportsString
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSSTRING
+
+ nsSupportsStringImpl() {}
+
+private:
+ ~nsSupportsStringImpl() {}
+
+ nsString mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRBoolImpl : public nsISupportsPRBool
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRBOOL
+
+ nsSupportsPRBoolImpl();
+
+private:
+ ~nsSupportsPRBoolImpl() {}
+
+ PRBool mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint8Impl : public nsISupportsPRUint8
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT8
+
+ nsSupportsPRUint8Impl();
+
+private:
+ ~nsSupportsPRUint8Impl() {}
+
+ PRUint8 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint16Impl : public nsISupportsPRUint16
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT16
+
+ nsSupportsPRUint16Impl();
+
+private:
+ ~nsSupportsPRUint16Impl() {}
+
+ PRUint16 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint32Impl : public nsISupportsPRUint32
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT32
+
+ nsSupportsPRUint32Impl();
+
+private:
+ ~nsSupportsPRUint32Impl() {}
+
+ PRUint32 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRUint64Impl : public nsISupportsPRUint64
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRUINT64
+
+ nsSupportsPRUint64Impl();
+
+private:
+ ~nsSupportsPRUint64Impl() {}
+
+ PRUint64 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRTimeImpl : public nsISupportsPRTime
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRTIME
+
+ nsSupportsPRTimeImpl();
+
+private:
+ ~nsSupportsPRTimeImpl() {}
+
+ PRTime mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsCharImpl : public nsISupportsChar
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSCHAR
+
+ nsSupportsCharImpl();
+
+private:
+ ~nsSupportsCharImpl() {}
+
+ char mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRInt16Impl : public nsISupportsPRInt16
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRINT16
+
+ nsSupportsPRInt16Impl();
+
+private:
+ ~nsSupportsPRInt16Impl() {}
+
+ PRInt16 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRInt32Impl : public nsISupportsPRInt32
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRINT32
+
+ nsSupportsPRInt32Impl();
+
+private:
+ ~nsSupportsPRInt32Impl() {}
+
+ PRInt32 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsPRInt64Impl : public nsISupportsPRInt64
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSPRINT64
+
+ nsSupportsPRInt64Impl();
+
+private:
+ ~nsSupportsPRInt64Impl() {}
+
+ PRInt64 mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsFloatImpl : public nsISupportsFloat
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSFLOAT
+
+ nsSupportsFloatImpl();
+
+private:
+ ~nsSupportsFloatImpl() {}
+
+ float mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsDoubleImpl : public nsISupportsDouble
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSDOUBLE
+
+ nsSupportsDoubleImpl();
+
+private:
+ ~nsSupportsDoubleImpl() {}
+
+ double mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsVoidImpl : public nsISupportsVoid
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSVOID
+
+ nsSupportsVoidImpl();
+
+private:
+ ~nsSupportsVoidImpl() {}
+
+ void* mData;
+};
+
+/***************************************************************************/
+
+class nsSupportsInterfacePointerImpl : public nsISupportsInterfacePointer
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSINTERFACEPOINTER
+
+ nsSupportsInterfacePointerImpl();
+
+private:
+ ~nsSupportsInterfacePointerImpl();
+
+ nsCOMPtr<nsISupports> mData;
+ nsID *mIID;
+};
+
+/***************************************************************************/
+
+/**
+ * Wraps a static const char* buffer for use with nsISupportsCString
+ *
+ * Only use this class with static buffers, or arena-allocated buffers of
+ * permanent lifetime!
+ */
+class nsSupportsDependentCString : public nsISupportsCString
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISUPPORTSPRIMITIVE
+ NS_DECL_NSISUPPORTSCSTRING
+
+ nsSupportsDependentCString(const char* aStr);
+
+private:
+ ~nsSupportsDependentCString() {}
+
+ nsDependentCString mData;
+};
+
+#endif /* nsSupportsPrimitives_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp
new file mode 100644
index 00000000..37fa998f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * 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 "nsTHashtable.h"
+#include "nsHashKeys.h"
+
+PR_IMPLEMENT(PLDHashOperator)
+PL_DHashStubEnumRemove(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 ordinal,
+ void *userarg)
+{
+ return PL_DHASH_REMOVE;
+}
+
+PRUint32 nsIDHashKey::HashKey(const nsID* id)
+{
+ PRUint32 h = id->m0;
+ PRUint32 i;
+
+ h = (h>>28) ^ (h<<4) ^ id->m1;
+ h = (h>>28) ^ (h<<4) ^ id->m2;
+
+ for (i = 0; i < 8; i++)
+ h = (h>>28) ^ (h<<4) ^ id->m3[i];
+
+ return h;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h
new file mode 100644
index 00000000..1e55ada6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTHashtable.h
@@ -0,0 +1,429 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTHashtable_h__
+#define nsTHashtable_h__
+
+#include "nscore.h"
+#include "pldhash.h"
+#include "nsDebug.h"
+#include NEW_H
+
+// helper function for nsTHashtable::Clear()
+PR_EXTERN(PLDHashOperator) PR_CALLBACK
+PL_DHashStubEnumRemove(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 ordinal,
+ void *userArg);
+
+
+/**
+ * a base class for templated hashtables.
+ *
+ * Clients will rarely need to use this class directly. Check the derived
+ * classes first, to see if they will meet your needs.
+ *
+ * @param EntryType the templated entry-type class that is managed by the
+ * hashtable. <code>EntryType</code> must extend the following declaration,
+ * and <strong>must not declare any virtual functions or derive from classes
+ * with virtual functions.</strong> Any vtable pointer would break the
+ * PLDHashTable code.
+ *<pre> class EntryType : public PLDHashEntryHdr
+ * {
+ * public: or friend nsTHashtable<EntryType>;
+ * // KeyType is what we use when Get()ing or Put()ing this entry
+ * // this should either be a simple datatype (PRUint32, nsISupports*) or
+ * // a const reference (const nsAString&)
+ * typedef something KeyType;
+ * // KeyTypePointer is the pointer-version of KeyType, because pldhash.h
+ * // requires keys to cast to <code>const void*</code>
+ * typedef const something* KeyTypePointer;
+ *
+ * EntryType(KeyTypePointer aKey);
+ *
+ * // the copy constructor must be defined, even if AllowMemMove() == true
+ * // or you will cause link errors!
+ * EntryType(const EntryType& aEnt);
+ *
+ * // the destructor must be defined... or you will cause link errors!
+ * ~EntryType();
+ *
+ * // return the key of this entry
+ * const KeyTypePointer GetKeyPointer() const;
+ *
+ * // KeyEquals(): does this entry match this key?
+ * PRBool KeyEquals(KeyTypePointer aKey) const;
+ *
+ * // KeyToPointer(): Convert KeyType to KeyTypePointer
+ * static KeyTypePointer KeyToPointer(KeyType aKey);
+ *
+ * // HashKey(): calculate the hash number
+ * static PLDHashNumber HashKey(KeyTypePointer aKey);
+ *
+ * // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
+ * // to use the copy constructor?
+ * enum { ALLOW_MEMMOVE = PR_(TRUE or FALSE) };
+ * }</pre>
+ *
+ * @see nsInterfaceHashtable
+ * @see nsDataHashtable
+ * @see nsClassHashtable
+ * @author "Benjamin Smedberg <bsmedberg@covad.net>"
+ */
+
+template<class EntryType>
+class nsTHashtable
+{
+public:
+ /**
+ * A dummy constructor; you must call Init() before using this class.
+ */
+ nsTHashtable();
+
+ /**
+ * destructor, cleans up and deallocates
+ */
+ ~nsTHashtable();
+
+ /**
+ * Initialize the table. This function must be called before any other
+ * class operations. This can fail due to OOM conditions.
+ * @param initSize the initial number of buckets in the hashtable, default 16
+ * @return PR_TRUE if the class was initialized properly.
+ */
+ PRBool Init(PRUint32 initSize = PL_DHASH_MIN_SIZE);
+
+ /**
+ * Check whether the table has been initialized. This can be useful for static hashtables.
+ * @return the initialization state of the class.
+ */
+ PRBool IsInitialized() const { return mTable.entrySize; }
+
+ /**
+ * KeyType is typedef'ed for ease of use.
+ */
+ typedef typename EntryType::KeyType KeyType;
+
+ /**
+ * KeyTypePointer is typedef'ed for ease of use.
+ */
+ typedef typename EntryType::KeyTypePointer KeyTypePointer;
+
+ /**
+ * Return the number of entries in the table.
+ * @return number of entries
+ */
+ PRUint32 Count() const { return mTable.entryCount; }
+
+ /**
+ * Get the entry associated with a key.
+ * @param aKey the key to retrieve
+ * @return pointer to the entry class, if the key exists; nsnull if the
+ * key doesn't exist
+ */
+ EntryType* GetEntry(KeyType aKey) const
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ EntryType* entry =
+ NS_REINTERPRET_CAST(EntryType*,
+ PL_DHashTableOperate(
+ NS_CONST_CAST(PLDHashTable*,&mTable),
+ EntryType::KeyToPointer(aKey),
+ PL_DHASH_LOOKUP));
+ return PL_DHASH_ENTRY_IS_BUSY(entry) ? entry : nsnull;
+ }
+
+ /**
+ * Get the entry associated with a key, or create a new entry,
+ * @param aKey the key to retrieve
+ * @return pointer to the entry class retreived; nsnull only if memory
+ can't be allocated
+ */
+ EntryType* PutEntry(KeyType aKey)
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ return NS_STATIC_CAST(EntryType*,
+ PL_DHashTableOperate(
+ &mTable,
+ EntryType::KeyToPointer(aKey),
+ PL_DHASH_ADD));
+ }
+
+ /**
+ * Remove the entry associated with a key.
+ * @param aKey of the entry to remove
+ */
+ void RemoveEntry(KeyType aKey)
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ PL_DHashTableOperate(&mTable,
+ EntryType::KeyToPointer(aKey),
+ PL_DHASH_REMOVE);
+ }
+
+ /**
+ * Remove the entry associated with a key, but don't resize the hashtable.
+ * This is a low-level method, and is not recommended unless you know what
+ * you're doing and you need the extra performance. This method can be used
+ * during enumeration, while RemoveEntry() cannot.
+ * @param aEntry the entry-pointer to remove (obtained from GetEntry or
+ * the enumerator
+ */
+ void RawRemoveEntry(EntryType* aEntry)
+ {
+ PL_DHashTableRawRemove(&mTable, aEntry);
+ }
+
+ /**
+ * client must provide an <code>Enumerator</code> function for
+ * EnumerateEntries
+ * @param aEntry the entry being enumerated
+ * @param userArg passed unchanged from <code>EnumerateEntries</code>
+ * @return combination of flags
+ * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink ,
+ * @link PLDHashOperator::PL_DHASH_STOP PL_DHASH_STOP @endlink ,
+ * @link PLDHashOperator::PL_DHASH_REMOVE PL_DHASH_REMOVE @endlink
+ */
+ typedef PLDHashOperator (*PR_CALLBACK Enumerator)(EntryType* aEntry, void* userArg);
+
+ /**
+ * Enumerate all the entries of the function.
+ * @param enumFunc the <code>Enumerator</code> function to call
+ * @param userArg a pointer to pass to the
+ * <code>Enumerator</code> function
+ * @return the number of entries actually enumerated
+ */
+ PRUint32 EnumerateEntries(Enumerator enumFunc, void* userArg)
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ s_EnumArgs args = { enumFunc, userArg };
+ return PL_DHashTableEnumerate(&mTable, s_EnumStub, &args);
+ }
+
+ /**
+ * remove all entries, return hashtable to "pristine" state ;)
+ */
+ void Clear()
+ {
+ NS_ASSERTION(mTable.entrySize, "nsTHashtable was not initialized properly.");
+
+ PL_DHashTableEnumerate(&mTable, PL_DHashStubEnumRemove, nsnull);
+ }
+
+protected:
+ PLDHashTable mTable;
+
+ static const void* PR_CALLBACK s_GetKey(PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+ static PLDHashNumber PR_CALLBACK s_HashKey(PLDHashTable *table,
+ const void *key);
+
+ static PRBool PR_CALLBACK s_MatchEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+ static void PR_CALLBACK s_CopyEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to);
+
+ static void PR_CALLBACK s_ClearEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+ static PRBool PR_CALLBACK s_InitEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ const void *key);
+
+ /**
+ * passed internally during enumeration. Allocated on the stack.
+ *
+ * @param userFunc the Enumerator function passed to
+ * EnumerateEntries by the client
+ * @param userArg the userArg passed unaltered
+ */
+ struct s_EnumArgs
+ {
+ Enumerator userFunc;
+ void* userArg;
+ };
+
+ static PLDHashOperator PR_CALLBACK s_EnumStub(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 number,
+ void *arg);
+private:
+ // copy constructor, not implemented
+ nsTHashtable(nsTHashtable<EntryType>& toCopy);
+
+ // assignment operator, not implemented
+ nsTHashtable<EntryType>& operator= (nsTHashtable<EntryType>& toEqual);
+};
+
+//
+// template definitions
+//
+
+template<class EntryType>
+nsTHashtable<EntryType>::nsTHashtable()
+{
+ // entrySize is our "I'm initialized" indicator
+ mTable.entrySize = 0;
+}
+
+template<class EntryType>
+nsTHashtable<EntryType>::~nsTHashtable()
+{
+ if (mTable.entrySize)
+ PL_DHashTableFinish(&mTable);
+}
+
+template<class EntryType>
+PRBool
+nsTHashtable<EntryType>::Init(PRUint32 initSize)
+{
+ if (mTable.entrySize)
+ {
+ NS_ERROR("nsTHashtable::Init() should not be called twice.");
+ return PR_TRUE;
+ }
+
+ static PLDHashTableOps sOps =
+ {
+ ::PL_DHashAllocTable,
+ ::PL_DHashFreeTable,
+ s_GetKey,
+ s_HashKey,
+ s_MatchEntry,
+ ::PL_DHashMoveEntryStub,
+ s_ClearEntry,
+ ::PL_DHashFinalizeStub,
+ s_InitEntry
+ };
+
+ if (!EntryType::ALLOW_MEMMOVE)
+ {
+ sOps.moveEntry = s_CopyEntry;
+ }
+
+ if (!PL_DHashTableInit(&mTable, &sOps, nsnull, sizeof(EntryType), initSize))
+ {
+ // if failed, reset "flag"
+ mTable.entrySize = 0;
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+// static definitions
+
+template<class EntryType>
+const void*
+nsTHashtable<EntryType>::s_GetKey(PLDHashTable *table,
+ PLDHashEntryHdr *entry)
+{
+ return ((EntryType*) entry)->GetKeyPointer();
+}
+
+template<class EntryType>
+PLDHashNumber
+nsTHashtable<EntryType>::s_HashKey(PLDHashTable *table,
+ const void *key)
+{
+ return EntryType::HashKey(NS_REINTERPRET_CAST(const KeyTypePointer, key));
+}
+
+template<class EntryType>
+PRBool
+nsTHashtable<EntryType>::s_MatchEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ return ((const EntryType*) entry)->KeyEquals(
+ NS_REINTERPRET_CAST(const KeyTypePointer, key));
+}
+
+template<class EntryType>
+void
+nsTHashtable<EntryType>::s_CopyEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to)
+{
+ EntryType* fromEntry =
+ NS_CONST_CAST(EntryType*, NS_REINTERPRET_CAST(const EntryType*, from));
+
+ new(to) EntryType(*fromEntry);
+
+ fromEntry->~EntryType();
+}
+
+template<class EntryType>
+void
+nsTHashtable<EntryType>::s_ClearEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry)
+{
+ NS_REINTERPRET_CAST(EntryType*,entry)->~EntryType();
+}
+
+template<class EntryType>
+PRBool
+nsTHashtable<EntryType>::s_InitEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ const void *key)
+{
+ new(entry) EntryType(NS_REINTERPRET_CAST(KeyTypePointer,key));
+ return PR_TRUE;
+}
+
+template<class EntryType>
+PLDHashOperator
+nsTHashtable<EntryType>::s_EnumStub(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ PRUint32 number,
+ void *arg)
+{
+ // dereferences the function-pointer to the user's enumeration function
+ return (* NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userFunc)(
+ NS_REINTERPRET_CAST(EntryType*,entry),
+ NS_REINTERPRET_CAST(s_EnumArgs*,arg)->userArg);
+}
+
+#endif // nsTHashtable_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp
new file mode 100644
index 00000000..a5f2dde0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.cpp
@@ -0,0 +1,1557 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Portable safe sprintf code.
+ *
+ * Code based on mozilla/nsprpub/src/io/prprf.c rev 3.7
+ *
+ * Contributor(s):
+ * Kipp E.B. Hickman <kipp@netscape.com> (original author)
+ * Frank Yung-Fong Tang <ftang@netscape.com>
+ * Daniele Nicolodi <daniele@grinta.net>
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "prdtoa.h"
+#include "prlong.h"
+#include "prlog.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "nsCRT.h"
+#include "nsTextFormatter.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+/*
+** Note: on some platforms va_list is defined as an array,
+** and requires array notation.
+*/
+
+#ifdef HAVE_VA_COPY
+#define VARARGS_ASSIGN(foo, bar) VA_COPY(foo,bar)
+#elif defined(HAVE_VA_LIST_AS_ARRAY)
+#define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
+#else
+#define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
+#endif
+
+typedef struct SprintfStateStr SprintfState;
+
+struct SprintfStateStr {
+ int (*stuff)(SprintfState *ss, const PRUnichar *sp, PRUint32 len);
+
+ PRUnichar *base;
+ PRUnichar *cur;
+ PRUint32 maxlen;
+
+ void *stuffclosure;
+};
+
+/*
+** Numbered Arguement State
+*/
+struct NumArgState{
+ int type; /* type of the current ap */
+ va_list ap; /* point to the corresponding position on ap */
+};
+
+#define NAS_DEFAULT_NUM 20 /* default number of NumberedArgumentState array */
+
+#define TYPE_INT16 0
+#define TYPE_UINT16 1
+#define TYPE_INTN 2
+#define TYPE_UINTN 3
+#define TYPE_INT32 4
+#define TYPE_UINT32 5
+#define TYPE_INT64 6
+#define TYPE_UINT64 7
+#define TYPE_STRING 8
+#define TYPE_DOUBLE 9
+#define TYPE_INTSTR 10
+#define TYPE_UNISTRING 11
+#define TYPE_UNKNOWN 20
+
+#define _LEFT 0x1
+#define _SIGNED 0x2
+#define _SPACED 0x4
+#define _ZEROS 0x8
+#define _NEG 0x10
+
+#define ELEMENTS_OF(array_) (sizeof(array_) / sizeof(array_[0]))
+
+// Warning: if aDest isn't big enough this function returns the converted
+// string in allocated memory which must be freed using PR_FREE().
+// May return nsnull if memory couldn't be allocated.
+static PRUnichar* UTF8ToUCS2(const char *aSrc, PRUint32 aSrcLen,
+ PRUnichar* aDest, PRUint32 aDestLen)
+{
+ const char *in, *inend;
+ inend = aSrc + aSrcLen;
+ PRUnichar *out;
+ PRUint32 state;
+ PRUint32 ucs4;
+ // decide the length of the UCS2 first.
+ PRUint32 needLen = 0;
+
+ for (in = aSrc, state = 0, ucs4 = 0; in < inend; in++) {
+ if (0 == state) {
+ if (0 == (0x80 & (*in))) {
+ needLen++;
+ } else if (0xC0 == (0xE0 & (*in))) {
+ needLen++;
+ state = 1;
+ } else if (0xE0 == (0xF0 & (*in))) {
+ needLen++;
+ state = 2;
+ } else if (0xF0 == (0xF8 & (*in))) {
+ needLen+=2;
+ state = 3;
+ } else if (0xF8 == (0xFC & (*in))) {
+ needLen+=2;
+ state = 4;
+ } else if (0xFC == (0xFE & (*in))) {
+ needLen+=2;
+ state = 5;
+ } else {
+ needLen++;
+ state = 0;
+ }
+ } else {
+ NS_ASSERTION((0x80 == (0xC0 & (*in))), "The input string is not in utf8");
+ if(0x80 == (0xC0 & (*in))) {
+ state--;
+ } else {
+ state = 0;
+ }
+ }
+ }
+ needLen++; // add null termination.
+
+ // allocates sufficient memory if aDest is not big enough.
+ if (needLen > aDestLen) {
+ aDest = (PRUnichar*)PR_MALLOC(sizeof(PRUnichar) * needLen);
+ }
+ if (nsnull == aDest) {
+ return nsnull;
+ }
+ out = aDest;
+
+ for (in = aSrc, state = 0, ucs4 = 0; in < inend; in++) {
+ if (0 == state) {
+ if (0 == (0x80 & (*in))) {
+ // ASCII
+ *out++ = (PRUnichar)*in;
+ } else if (0xC0 == (0xE0 & (*in))) {
+ // 2 bytes UTF8
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 6) & 0x000007C0L;
+ state=1;
+ } else if (0xE0 == (0xF0 & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 12) & 0x0000F000L;
+ state=2;
+ } else if (0xF0 == (0xF8 & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 18) & 0x001F0000L;
+ state=3;
+ } else if (0xF8 == (0xFC & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 24) & 0x03000000L;
+ state=4;
+ } else if (0xFC == (0xFE & (*in))) {
+ ucs4 = (PRUint32)(*in);
+ ucs4 = (ucs4 << 30) & 0x40000000L;
+ state=5;
+ } else {
+ NS_ASSERTION(0, "The input string is not in utf8");
+ state=0;
+ ucs4=0;
+ }
+ } else {
+ NS_ASSERTION((0x80 == (0xC0 & (*in))), "The input string is not in utf8");
+ if (0x80 == (0xC0 & (*in))) {
+ PRUint32 tmp = (*in);
+ int shift = --state * 6;
+ tmp = (tmp << shift) & (0x0000003FL << shift);
+ ucs4 |= tmp;
+ if (0 == state) {
+ if (ucs4 >= 0x00010000) {
+ if (ucs4 >= 0x00110000) {
+ *out++ = 0xFFFD;
+ } else {
+ ucs4 -= 0x00010000;
+ *out++ = 0xD800 | (0x000003FF & (ucs4 >> 10));
+ *out++ = 0xDC00 | (0x000003FF & ucs4);
+ }
+ } else {
+ *out++ = ucs4;
+ }
+ ucs4 = 0;
+ }
+ } else {
+ state = 0;
+ ucs4 = 0;
+ }
+ }
+ }
+ *out = 0x0000;
+ return aDest;
+}
+
+/*
+** Fill into the buffer using the data in src
+*/
+static int fill2(SprintfState *ss, const PRUnichar *src, int srclen,
+ int width, int flags)
+{
+ PRUnichar space = ' ';
+ int rv;
+
+ width -= srclen;
+ /* Right adjusting */
+ if ((width > 0) && ((flags & _LEFT) == 0)) {
+ if (flags & _ZEROS) {
+ space = '0';
+ }
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Copy out the source data */
+ rv = (*ss->stuff)(ss, src, srclen);
+ if (rv < 0) {
+ return rv;
+ }
+
+ /* Left adjusting */
+ if ((width > 0) && ((flags & _LEFT) != 0)) {
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Fill a number. The order is: optional-sign zero-filling conversion-digits
+*/
+static int fill_n(SprintfState *ss, const PRUnichar *src, int srclen,
+ int width, int prec, int type, int flags)
+{
+ int zerowidth = 0;
+ int precwidth = 0;
+ int signwidth = 0;
+ int leftspaces = 0;
+ int rightspaces = 0;
+ int cvtwidth;
+ int rv;
+ PRUnichar sign;
+ PRUnichar space = ' ';
+ PRUnichar zero = '0';
+
+ if ((type & 1) == 0) {
+ if (flags & _NEG) {
+ sign = '-';
+ signwidth = 1;
+ } else if (flags & _SIGNED) {
+ sign = '+';
+ signwidth = 1;
+ } else if (flags & _SPACED) {
+ sign = ' ';
+ signwidth = 1;
+ }
+ }
+ cvtwidth = signwidth + srclen;
+
+ if (prec > 0) {
+ if (prec > srclen) {
+ /* Need zero filling */
+ precwidth = prec - srclen;
+ cvtwidth += precwidth;
+ }
+ }
+
+ if ((flags & _ZEROS) && (prec < 0)) {
+ if (width > cvtwidth) {
+ /* Zero filling */
+ zerowidth = width - cvtwidth;
+ cvtwidth += zerowidth;
+ }
+ }
+
+ if (flags & _LEFT) {
+ if (width > cvtwidth) {
+ /* Space filling on the right (i.e. left adjusting) */
+ rightspaces = width - cvtwidth;
+ }
+ } else {
+ if (width > cvtwidth) {
+ /* Space filling on the left (i.e. right adjusting) */
+ leftspaces = width - cvtwidth;
+ }
+ }
+ while (--leftspaces >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ if (signwidth) {
+ rv = (*ss->stuff)(ss, &sign, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--precwidth >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--zerowidth >= 0) {
+ rv = (*ss->stuff)(ss, &zero, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ rv = (*ss->stuff)(ss, src, srclen);
+ if (rv < 0) {
+ return rv;
+ }
+ while (--rightspaces >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*
+** Convert a long into its printable form
+*/
+static int cvt_l(SprintfState *ss, long num, int width, int prec,
+ int radix, int type, int flags, const PRUnichar *hexp)
+{
+ PRUnichar cvtbuf[100];
+ PRUnichar *cvt;
+ int digits;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (num == 0)) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ cvt = &cvtbuf[0] + ELEMENTS_OF(cvtbuf);
+ digits = 0;
+ while (num) {
+ int digit = (((unsigned long)num) % radix) & 0xF;
+ *--cvt = hexp[digit];
+ digits++;
+ num = (long)(((unsigned long)num) / radix);
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a 64-bit integer into its printable form
+*/
+static int cvt_ll(SprintfState *ss, PRInt64 num, int width, int prec,
+ int radix, int type, int flags, const PRUnichar *hexp)
+{
+ PRUnichar cvtbuf[100];
+ PRUnichar *cvt;
+ int digits;
+ PRInt64 rad;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (LL_IS_ZERO(num))) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ LL_I2L(rad, radix);
+ cvt = &cvtbuf[0] + ELEMENTS_OF(cvtbuf);
+ digits = 0;
+ while (!LL_IS_ZERO(num)) {
+ PRInt32 digit;
+ PRInt64 quot, rem;
+ LL_UDIVMOD(&quot, &rem, num, rad);
+ LL_L2I(digit, rem);
+ *--cvt = hexp[digit & 0xf];
+ digits++;
+ num = quot;
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a double precision floating point number into its printable
+** form.
+*/
+static int cvt_f(SprintfState *ss, double d, int width, int prec,
+ const PRUnichar type, int flags)
+{
+ int mode = 2;
+ int decpt;
+ int sign;
+ char buf[256];
+ char * bufp = buf;
+ int bufsz = 256;
+ char num[256];
+ char * nump;
+ char * endnum;
+ int numdigits = 0;
+ char exp = 'e';
+
+ if (prec == -1) {
+ prec = 6;
+ } else if (prec > 50) {
+ // limit precision to avoid PR_dtoa bug 108335
+ // and to prevent buffers overflows
+ prec = 50;
+ }
+
+ switch (type) {
+ case 'f':
+ numdigits = prec;
+ mode = 3;
+ break;
+ case 'E':
+ exp = 'E';
+ // no break
+ case 'e':
+ numdigits = prec + 1;
+ mode = 2;
+ break;
+ case 'G':
+ exp = 'E';
+ // no break
+ case 'g':
+ if (prec == 0) {
+ prec = 1;
+ }
+ numdigits = prec;
+ mode = 2;
+ break;
+ default:
+ NS_ERROR("invalid type passed to cvt_f");
+ }
+
+ if (PR_dtoa(d, mode, numdigits, &decpt, &sign, &endnum, num, bufsz) == PR_FAILURE) {
+ buf[0] = '\0';
+ return -1;
+ }
+ numdigits = endnum - num;
+ nump = num;
+
+ if (sign) {
+ *bufp++ = '-';
+ } else if (flags & _SIGNED) {
+ *bufp++ = '+';
+ }
+
+ if (decpt == 9999) {
+ while ((*bufp++ = *nump++)) { }
+ } else {
+
+ switch (type) {
+
+ case 'E':
+ case 'e':
+
+ *bufp++ = *nump++;
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (*nump) {
+ *bufp++ = *nump++;
+ prec--;
+ }
+ while (prec-- > 0) {
+ *bufp++ = '0';
+ }
+ }
+ *bufp++ = exp;
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+03d", decpt-1);
+ break;
+
+ case 'f':
+
+ if (decpt < 1) {
+ *bufp++ = '0';
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (decpt++ && prec-- > 0) {
+ *bufp++ = '0';
+ }
+ while (*nump && prec-- > 0) {
+ *bufp++ = *nump++;
+ }
+ while (prec-- > 0) {
+ *bufp++ = '0';
+ }
+ }
+ } else {
+ while (*nump && decpt-- > 0) {
+ *bufp++ = *nump++;
+ }
+ while (decpt-- > 0) {
+ *bufp++ = '0';
+ }
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (*nump && prec-- > 0) {
+ *bufp++ = *nump++;
+ }
+ while (prec-- > 0) {
+ *bufp++ = '0';
+ }
+ }
+ }
+ *bufp = '\0';
+ break;
+
+ case 'G':
+ case 'g':
+
+ if ((decpt < -3) || ((decpt - 1) >= prec)) {
+ *bufp++ = *nump++;
+ numdigits--;
+ if (numdigits > 0) {
+ *bufp++ = '.';
+ while (*nump) {
+ *bufp++ = *nump++;
+ }
+ }
+ *bufp++ = exp;
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+03d", decpt-1);
+ } else {
+ if (decpt < 1) {
+ *bufp++ = '0';
+ if (prec > 0) {
+ *bufp++ = '.';
+ while (decpt++) {
+ *bufp++ = '0';
+ }
+ while (*nump) {
+ *bufp++ = *nump++;
+ }
+ }
+ } else {
+ while (*nump && decpt-- > 0) {
+ *bufp++ = *nump++;
+ numdigits--;
+ }
+ while (decpt-- > 0) {
+ *bufp++ = '0';
+ }
+ if (numdigits > 0) {
+ *bufp++ = '.';
+ while (*nump) {
+ *bufp++ = *nump++;
+ }
+ }
+ }
+ *bufp = '\0';
+ }
+ }
+ }
+
+ PRUnichar rbuf[256];
+ PRUnichar *rbufp = rbuf;
+ bufp = buf;
+ // cast to PRUnichar
+ while ((*rbufp++ = *bufp++)) { }
+ *rbufp = '\0';
+
+ return fill2(ss, rbuf, nsCRT::strlen(rbuf), width, flags);
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_S(SprintfState *ss, const PRUnichar *s, int width,
+ int prec, int flags)
+{
+ int slen;
+
+ if (prec == 0) {
+ return 0;
+ }
+
+ /* Limit string length by precision value */
+ slen = s ? nsCRT::strlen(s) : 6;
+ if (prec > 0) {
+ if (prec < slen) {
+ slen = prec;
+ }
+ }
+
+ /* and away we go */
+ NS_NAMED_LITERAL_STRING(nullstr, "(null)");
+
+ return fill2(ss, s ? s : nullstr.get(), slen, width, flags);
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_s(SprintfState *ss, const char *s, int width,
+ int prec, int flags)
+{
+ // convert s from UTF8 to PRUnichar*
+ // Fix me !!!
+ PRUnichar buf[256];
+ PRUnichar *retbuf = nsnull;
+
+ if (s) {
+ retbuf = UTF8ToUCS2(s, strlen(s), buf, 256);
+ if(nsnull == retbuf) {
+ return -1;
+ }
+ }
+ int ret = cvt_S(ss, retbuf, width, prec, flags);
+
+ if (retbuf != buf) {
+ PR_DELETE(retbuf);
+ }
+ return ret;
+}
+
+/*
+** BiuldArgArray stands for Numbered Argument list Sprintf
+** for example,
+** fmp = "%4$i, %2$d, %3s, %1d";
+** the number must start from 1, and no gap among them
+*/
+
+static struct NumArgState* BuildArgArray(const PRUnichar *fmt,
+ va_list ap, int * rv,
+ struct NumArgState * nasArray)
+{
+ int number = 0, cn = 0, i;
+ const PRUnichar* p;
+ PRUnichar c;
+ struct NumArgState* nas;
+
+ /*
+ ** first pass:
+ ** detemine how many legal % I have got, then allocate space
+ */
+ p = fmt;
+ *rv = 0;
+ i = 0;
+ while ((c = *p++) != 0) {
+ if (c != '%') {
+ continue;
+ }
+ /* skip %% case */
+ if ((c = *p++) == '%') {
+ continue;
+ }
+
+ while( c != 0 ){
+ if (c > '9' || c < '0') {
+ /* numbered argument csae */
+ if (c == '$') {
+ if (i > 0) {
+ *rv = -1;
+ return NULL;
+ }
+ number++;
+ break;
+
+ } else {
+ /* non-numbered argument case */
+ if (number > 0) {
+ *rv = -1;
+ return NULL;
+ }
+ i = 1;
+ break;
+ }
+ }
+ c = *p++;
+ }
+ }
+
+ if (number == 0) {
+ return NULL;
+ }
+
+ if (number > NAS_DEFAULT_NUM) {
+ nas = (struct NumArgState*)PR_MALLOC(number * sizeof(struct NumArgState));
+ if (!nas) {
+ *rv = -1;
+ return NULL;
+ }
+ } else {
+ nas = nasArray;
+ }
+
+ for (i = 0; i < number; i++) {
+ nas[i].type = TYPE_UNKNOWN;
+ }
+
+ /*
+ ** second pass:
+ ** set nas[].type
+ */
+ p = fmt;
+ while ((c = *p++) != 0) {
+ if (c != '%') {
+ continue;
+ }
+ c = *p++;
+ if (c == '%') {
+ continue;
+ }
+ cn = 0;
+ /* should imporve error check later */
+ while (c && c != '$') {
+ cn = cn*10 + c - '0';
+ c = *p++;
+ }
+
+ if (!c || cn < 1 || cn > number) {
+ *rv = -1;
+ break;
+ }
+
+ /* nas[cn] starts from 0, and make sure
+ nas[cn].type is not assigned */
+ cn--;
+ if (nas[cn].type != TYPE_UNKNOWN) {
+ continue;
+ }
+
+ c = *p++;
+
+ /* width */
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ } else {
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+
+ /* precision */
+ if (c == '.') {
+ c = *p++;
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ } else {
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+ }
+
+ /* size */
+ nas[cn].type = TYPE_INTN;
+ if (c == 'h') {
+ nas[cn].type = TYPE_INT16;
+ c = *p++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ } else if (c == 'l') {
+ nas[cn].type = TYPE_INT32;
+ c = *p++;
+ if (c == 'l') {
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ }
+ }
+
+ /* format */
+ switch (c) {
+ case 'd':
+ case 'c':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ nas[cn].type = TYPE_DOUBLE;
+ break;
+
+ case 'p':
+ /* XXX should use cpp */
+ if (sizeof(void *) == sizeof(PRInt32)) {
+ nas[cn].type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(PRInt64)) {
+ nas[cn].type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(PRIntn)) {
+ nas[cn].type = TYPE_UINTN;
+ } else {
+ nas[cn].type = TYPE_UNKNOWN;
+ }
+ break;
+
+ case 'C':
+ /* XXX not supported I suppose */
+ PR_ASSERT(0);
+ nas[cn].type = TYPE_UNKNOWN;
+ break;
+
+ case 'S':
+ nas[cn].type = TYPE_UNISTRING;
+ break;
+
+ case 's':
+ nas[cn].type = TYPE_STRING;
+ break;
+
+ case 'n':
+ nas[cn].type = TYPE_INTSTR;
+ break;
+
+ default:
+ PR_ASSERT(0);
+ nas[cn].type = TYPE_UNKNOWN;
+ break;
+ }
+
+ /* get a legal para. */
+ if (nas[cn].type == TYPE_UNKNOWN) {
+ *rv = -1;
+ break;
+ }
+ }
+
+
+ /*
+ ** third pass
+ ** fill the nas[cn].ap
+ */
+ if (*rv < 0) {
+ if( nas != nasArray ) {
+ PR_DELETE(nas);
+ }
+ return NULL;
+ }
+
+ cn = 0;
+ while (cn < number) {
+ if (nas[cn].type == TYPE_UNKNOWN) {
+ cn++;
+ continue;
+ }
+
+ VARARGS_ASSIGN(nas[cn].ap, ap);
+
+ switch (nas[cn].type) {
+ case TYPE_INT16:
+ case TYPE_UINT16:
+ case TYPE_INTN:
+ case TYPE_UINTN: (void)va_arg(ap, PRIntn); break;
+
+ case TYPE_INT32: (void)va_arg(ap, PRInt32); break;
+
+ case TYPE_UINT32: (void)va_arg(ap, PRUint32); break;
+
+ case TYPE_INT64: (void)va_arg(ap, PRInt64); break;
+
+ case TYPE_UINT64: (void)va_arg(ap, PRUint64); break;
+
+ case TYPE_STRING: (void)va_arg(ap, char*); break;
+
+ case TYPE_INTSTR: (void)va_arg(ap, PRIntn*); break;
+
+ case TYPE_DOUBLE: (void)va_arg(ap, double); break;
+
+ case TYPE_UNISTRING: (void)va_arg(ap, PRUnichar*); break;
+
+ default:
+ if( nas != nasArray ) {
+ PR_DELETE( nas );
+ }
+ *rv = -1;
+ return NULL;
+ }
+ cn++;
+ }
+ return nas;
+}
+
+/*
+** The workhorse sprintf code.
+*/
+static int dosprintf(SprintfState *ss, const PRUnichar *fmt, va_list ap)
+{
+ PRUnichar c;
+ int flags, width, prec, radix, type;
+ union {
+ PRUnichar ch;
+ int i;
+ long l;
+ PRInt64 ll;
+ double d;
+ const char *s;
+ const PRUnichar *S;
+ int *ip;
+ } u;
+ PRUnichar space = ' ';
+ const PRUnichar *fmt0;
+
+ nsAutoString hex;
+ hex.AssignLiteral("0123456789abcdef");
+
+ nsAutoString HEX;
+ HEX.AssignLiteral("0123456789ABCDEF");
+
+ const PRUnichar *hexp;
+ int rv, i;
+ struct NumArgState* nas = NULL;
+ struct NumArgState nasArray[NAS_DEFAULT_NUM];
+ /* in "%4$.2f" dolPt will point to . */
+ const PRUnichar* dolPt = NULL;
+
+
+ /*
+ ** build an argument array, IF the fmt is numbered argument
+ ** list style, to contain the Numbered Argument list pointers
+ */
+ nas = BuildArgArray (fmt, ap, &rv, nasArray);
+ if (rv < 0) {
+ /* the fmt contains error Numbered Argument format, jliu@netscape.com */
+ PR_ASSERT(0);
+ return rv;
+ }
+
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+ fmt0 = fmt - 1;
+
+ /*
+ ** Gobble up the % format string. Hopefully we have handled all
+ ** of the strange cases!
+ */
+ flags = 0;
+ c = *fmt++;
+ if (c == '%') {
+ /* quoting a % with %% */
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ if (nas != NULL) {
+ /* the fmt contains the Numbered Arguments feature */
+ i = 0;
+ /* should imporve error check later */
+ while (c && c != '$') {
+ i = (i * 10) + (c - '0');
+ c = *fmt++;
+ }
+
+ if (nas[i-1].type == TYPE_UNKNOWN) {
+ if (nas && (nas != nasArray)) {
+ PR_DELETE(nas);
+ }
+ return -1;
+ }
+
+ ap = nas[i-1].ap;
+ dolPt = fmt;
+ c = *fmt++;
+ }
+
+ /*
+ * Examine optional flags. Note that we do not implement the
+ * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is
+ * somewhat ambiguous and not ideal, which is perhaps why
+ * the various sprintf() implementations are inconsistent
+ * on this feature.
+ */
+ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
+ if (c == '-') flags |= _LEFT;
+ if (c == '+') flags |= _SIGNED;
+ if (c == ' ') flags |= _SPACED;
+ if (c == '0') flags |= _ZEROS;
+ c = *fmt++;
+ }
+ if (flags & _SIGNED) flags &= ~_SPACED;
+ if (flags & _LEFT) flags &= ~_ZEROS;
+
+ /* width */
+ if (c == '*') {
+ c = *fmt++;
+ width = va_arg(ap, int);
+ } else {
+ width = 0;
+ while ((c >= '0') && (c <= '9')) {
+ width = (width * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+
+ /* precision */
+ prec = -1;
+ if (c == '.') {
+ c = *fmt++;
+ if (c == '*') {
+ c = *fmt++;
+ prec = va_arg(ap, int);
+ } else {
+ prec = 0;
+ while ((c >= '0') && (c <= '9')) {
+ prec = (prec * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+ }
+
+ /* size */
+ type = TYPE_INTN;
+ if (c == 'h') {
+ type = TYPE_INT16;
+ c = *fmt++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ type = TYPE_INT64;
+ c = *fmt++;
+ } else if (c == 'l') {
+ type = TYPE_INT32;
+ c = *fmt++;
+ if (c == 'l') {
+ type = TYPE_INT64;
+ c = *fmt++;
+ }
+ }
+
+ /* format */
+ hexp = hex.get();
+ switch (c) {
+ case 'd':
+ case 'i': /* decimal/integer */
+ radix = 10;
+ goto fetch_and_convert;
+
+ case 'o': /* octal */
+ radix = 8;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'u': /* unsigned decimal */
+ radix = 10;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'x': /* unsigned hex */
+ radix = 16;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'X': /* unsigned HEX */
+ radix = 16;
+ hexp = HEX.get();
+ type |= 1;
+ goto fetch_and_convert;
+
+ fetch_and_convert:
+ switch (type) {
+ case TYPE_INT16:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= _NEG;
+ }
+ goto do_long;
+ case TYPE_UINT16:
+ u.l = va_arg(ap, int) & 0xffff;
+ goto do_long;
+ case TYPE_INTN:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= _NEG;
+ }
+ goto do_long;
+ case TYPE_UINTN:
+ u.l = (long)va_arg(ap, unsigned int);
+ goto do_long;
+
+ case TYPE_INT32:
+ u.l = va_arg(ap, PRInt32);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= _NEG;
+ }
+ goto do_long;
+ case TYPE_UINT32:
+ u.l = (long)va_arg(ap, PRUint32);
+ do_long:
+ rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case TYPE_INT64:
+ u.ll = va_arg(ap, PRInt64);
+ if (!LL_GE_ZERO(u.ll)) {
+ LL_NEG(u.ll, u.ll);
+ flags |= _NEG;
+ }
+ goto do_longlong;
+ case TYPE_UINT64:
+ u.ll = va_arg(ap, PRUint64);
+ do_longlong:
+ rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ u.d = va_arg(ap, double);
+ rv = cvt_f(ss, u.d, width, prec, c, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'c':
+ u.ch = va_arg(ap, int);
+ if ((flags & _LEFT) == 0) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ rv = (*ss->stuff)(ss, &u.ch, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ if (flags & _LEFT) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ break;
+
+ case 'p':
+ if (sizeof(void *) == sizeof(PRInt32)) {
+ type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(PRInt64)) {
+ type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(int)) {
+ type = TYPE_UINTN;
+ } else {
+ PR_ASSERT(0);
+ break;
+ }
+ radix = 16;
+ goto fetch_and_convert;
+
+#if 0
+ case 'C':
+ /* XXX not supported I suppose */
+ PR_ASSERT(0);
+ break;
+#endif
+
+ case 'S':
+ u.S = va_arg(ap, const PRUnichar*);
+ rv = cvt_S(ss, u.S, width, prec, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 's':
+ u.s = va_arg(ap, const char*);
+ rv = cvt_s(ss, u.s, width, prec, flags);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'n':
+ u.ip = va_arg(ap, int*);
+ if (u.ip) {
+ *u.ip = ss->cur - ss->base;
+ }
+ break;
+
+ default:
+ /* Not a % token after all... skip it */
+#if 0
+ PR_ASSERT(0);
+#endif
+ PRUnichar perct = '%';
+ rv = (*ss->stuff)(ss, &perct, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Stuff trailing NUL */
+ PRUnichar null = '\0';
+
+ rv = (*ss->stuff)(ss, &null, 1);
+
+ if( nas && ( nas != nasArray ) ){
+ PR_DELETE( nas );
+ }
+
+ return rv;
+}
+
+/************************************************************************/
+
+static int
+StringStuff(SprintfState* ss, const PRUnichar* sp, PRUint32 len)
+{
+ ptrdiff_t off = ss->cur - ss->base;
+
+ nsAString* str = NS_STATIC_CAST(nsAString*,ss->stuffclosure);
+ str->Append(sp, len);
+
+ // we can assume contiguous storage
+ nsAString::iterator begin;
+ str->BeginWriting(begin);
+ ss->base = begin.get();
+ ss->cur = ss->base + off;
+
+ return 0;
+}
+
+/*
+** Stuff routine that automatically grows the malloc'd output buffer
+** before it overflows.
+*/
+static int GrowStuff(SprintfState *ss, const PRUnichar *sp, PRUint32 len)
+{
+ ptrdiff_t off;
+ PRUnichar *newbase;
+ PRUint32 newlen;
+
+ off = ss->cur - ss->base;
+ if (off + len >= ss->maxlen) {
+ /* Grow the buffer */
+ newlen = ss->maxlen + ((len > 32) ? len : 32);
+ if (ss->base) {
+ newbase = (PRUnichar*) PR_REALLOC(ss->base, newlen*sizeof(PRUnichar));
+ } else {
+ newbase = (PRUnichar*) PR_MALLOC(newlen*sizeof(PRUnichar));
+ }
+ if (!newbase) {
+ /* Ran out of memory */
+ return -1;
+ }
+ ss->base = newbase;
+ ss->maxlen = newlen;
+ ss->cur = ss->base + off;
+ }
+
+ /* Copy data */
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ PR_ASSERT((PRUint32)(ss->cur - ss->base) <= ss->maxlen);
+ return 0;
+}
+
+/*
+** sprintf into a malloc'd buffer
+*/
+PRUnichar * nsTextFormatter::smprintf(const PRUnichar *fmt, ...)
+{
+ va_list ap;
+ PRUnichar *rv;
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vsmprintf(fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PRUint32 nsTextFormatter::ssprintf(nsAString& out, const PRUnichar* fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vssprintf(out, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+/*
+** Free memory allocated, for the caller, by smprintf
+*/
+void nsTextFormatter::smprintf_free(PRUnichar *mem)
+{
+ PR_DELETE(mem);
+}
+
+PRUint32 nsTextFormatter::vssprintf(nsAString& out, const PRUnichar* fmt, va_list ap)
+{
+ SprintfState ss;
+ ss.stuff = StringStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ ss.stuffclosure = &out;
+
+ out.Truncate();
+ int n = dosprintf(&ss, fmt, ap);
+ return n ? n - 1 : n;
+}
+
+PRUnichar * nsTextFormatter::vsmprintf(const PRUnichar *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ PR_DELETE(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
+/*
+** Stuff routine that discards overflow data
+*/
+static int LimitStuff(SprintfState *ss, const PRUnichar *sp, PRUint32 len)
+{
+ PRUint32 limit = ss->maxlen - (ss->cur - ss->base);
+
+ if (len > limit) {
+ len = limit;
+ }
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ return 0;
+}
+
+/*
+** sprintf into a fixed size buffer. Make sure there is a NUL at the end
+** when finished.
+*/
+PRUint32 nsTextFormatter::snprintf(PRUnichar *out, PRUint32 outlen, const PRUnichar *fmt, ...)
+{
+ va_list ap;
+ PRUint32 rv;
+
+ PR_ASSERT((PRInt32)outlen > 0);
+ if ((PRInt32)outlen <= 0) {
+ return 0;
+ }
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vsnprintf(out, outlen, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PRUint32 nsTextFormatter::vsnprintf(PRUnichar *out, PRUint32 outlen,const PRUnichar *fmt,
+ va_list ap)
+{
+ SprintfState ss;
+ PRUint32 n;
+
+ PR_ASSERT((PRInt32)outlen > 0);
+ if ((PRInt32)outlen <= 0) {
+ return 0;
+ }
+
+ ss.stuff = LimitStuff;
+ ss.base = out;
+ ss.cur = out;
+ ss.maxlen = outlen;
+ (void) dosprintf(&ss, fmt, ap);
+
+ /* If we added chars, and we didn't append a null, do it now. */
+ if( (ss.cur != ss.base) && (*(ss.cur - 1) != '\0') )
+ *(--ss.cur) = '\0';
+
+ n = ss.cur - ss.base;
+ return n ? n - 1 : n;
+}
+
+PRUnichar * nsTextFormatter::sprintf_append(PRUnichar *last, const PRUnichar *fmt, ...)
+{
+ va_list ap;
+ PRUnichar *rv;
+
+ va_start(ap, fmt);
+ rv = nsTextFormatter::vsprintf_append(last, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+PRUnichar * nsTextFormatter::vsprintf_append(PRUnichar *last, const PRUnichar *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ if (last) {
+ int lastlen = nsCRT::strlen(last);
+ ss.base = last;
+ ss.cur = last + lastlen;
+ ss.maxlen = lastlen;
+ } else {
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ }
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ PR_DELETE(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+#ifdef DEBUG
+PRBool nsTextFormatter::SelfTest()
+{
+ PRBool passed = PR_TRUE ;
+ nsAutoString fmt(NS_LITERAL_STRING("%3$s %4$S %1$d %2$d"));
+
+ char utf8[] = "Hello";
+ PRUnichar ucs2[]={'W', 'o', 'r', 'l', 'd', 0x4e00, 0xAc00, 0xFF45, 0x0103};
+ int d=3;
+
+
+ PRUnichar buf[256];
+ int ret;
+ ret = nsTextFormatter::snprintf(buf, 256, fmt.get(), d, 333, utf8, ucs2);
+ printf("ret = %d\n", ret);
+ nsAutoString out(buf);
+ printf("%s \n", NS_LossyConvertUCS2toASCII(out).get());
+ const PRUnichar *uout = out.get();
+ for(PRUint32 i=0;i<out.Length();i++)
+ printf("%2X ", uout[i]);
+
+ return passed;
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h
new file mode 100644
index 00000000..903ac195
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTextFormatter.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTextFormatter_h___
+#define nsTextFormatter_h___
+
+/*
+** API for PR printf like routines. Supports the following formats
+** %d - decimal
+** %u - unsigned decimal
+** %x - unsigned hex
+** %X - unsigned uppercase hex
+** %o - unsigned octal
+** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
+** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
+** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
+** %s - utf8 string
+** %S - PRUnichar string
+** %c - character
+** %p - pointer (deals with machine dependent pointer size)
+** %f - float
+** %g - float
+*/
+#include "prtypes.h"
+#include "prio.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include "nscore.h"
+#include "nsAString.h"
+
+
+class NS_COM nsTextFormatter {
+
+public:
+
+/*
+** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
+** of the buffer. Returns the length of the written output, NOT including
+** the NUL, or (PRUint32)-1 if an error occurs.
+*/
+static PRUint32 snprintf(PRUnichar *out, PRUint32 outlen, const PRUnichar *fmt, ...);
+
+/*
+** sprintf into a PR_MALLOC'd buffer. Return a pointer to the malloc'd
+** buffer on success, NULL on failure. Call "smprintf_free" to release
+** the memory returned.
+*/
+static PRUnichar* smprintf(const PRUnichar *fmt, ...);
+
+
+static PRUint32 ssprintf(nsAString& out, const PRUnichar* fmt, ...);
+/*
+** Free the memory allocated, for the caller, by smprintf
+*/
+static void smprintf_free(PRUnichar *mem);
+
+/*
+** "append" sprintf into a PR_MALLOC'd buffer. "last" is the last value of
+** the PR_MALLOC'd buffer. sprintf will append data to the end of last,
+** growing it as necessary using realloc. If last is NULL, PR_sprintf_append
+** will allocate the initial string. The return value is the new value of
+** last for subsequent calls, or NULL if there is a malloc failure.
+*/
+static PRUnichar* sprintf_append(PRUnichar *last, const PRUnichar *fmt, ...);
+
+/*
+** va_list forms of the above.
+*/
+static PRUint32 vsnprintf(PRUnichar *out, PRUint32 outlen, const PRUnichar *fmt, va_list ap);
+static PRUnichar* vsmprintf(const PRUnichar *fmt, va_list ap);
+static PRUint32 vssprintf(nsAString& out, const PRUnichar *fmt, va_list ap);
+static PRUnichar* vsprintf_append(PRUnichar *last, const PRUnichar *fmt, va_list ap);
+
+#ifdef DEBUG
+static PRBool SelfTest();
+#endif
+
+
+};
+
+#endif /* nsTextFormatter_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTime.h b/src/libs/xpcom18a4/xpcom/ds/nsTime.h
new file mode 100644
index 00000000..f5c3a0ab
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTime.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTime_h__
+#define nsTime_h__
+
+#include "prtime.h"
+#include "nsInt64.h"
+#include "nscore.h"
+
+/**
+ * This class encapsulates full 64-bit time functionality and
+ * provides simple arithmetic and conversion operations.
+ */
+
+// If you ever decide that you need to add a non-inline method to this
+// class, be sure to change the class declaration to "class NS_BASE
+// nsTime".
+
+class nsTime : public nsInt64
+{
+public:
+ /**
+ * Construct the current time.
+ */
+ nsTime(void) : nsInt64(PR_Now()) {
+ }
+
+ /**
+ * Construct the time from a string.
+ */
+ nsTime(const char* dateStr, PRBool defaultToGMT) {
+ PRInt64 theTime;
+ PRStatus status = PR_ParseTimeString(dateStr, defaultToGMT, &theTime);
+ if (status == PR_SUCCESS)
+ mValue = theTime;
+ else
+ mValue = LL_ZERO;
+ }
+
+ /**
+ * Construct a time from a PRTime.
+ */
+ nsTime(const PRTime aTime) : nsInt64(aTime) {
+ }
+
+ /**
+ * Construct a time from a 64-bit value.
+ */
+ nsTime(const nsInt64& aTime) : nsInt64(aTime) {
+ }
+
+ /**
+ * Construct a time from another time.
+ */
+ nsTime(const nsTime& aTime) : nsInt64(aTime.mValue) {
+ }
+
+ // ~nsTime(void) -- XXX destructor unnecessary
+
+ /**
+ * Assign one time to another.
+ */
+ const nsTime& operator =(const nsTime& aTime) {
+ mValue = aTime.mValue;
+ return *this;
+ }
+
+ /**
+ * Convert a nsTime object to a PRTime
+ */
+ operator PRTime(void) const {
+ return mValue;
+ }
+};
+
+/**
+ * Determine if one time is strictly less than another
+ */
+inline const PRBool
+operator <(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue < aTime2.mValue;
+}
+
+/**
+ * Determine if one time is less than or equal to another
+ */
+inline const PRBool
+operator <=(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue <= aTime2.mValue;
+}
+
+/**
+ * Determine if one time is strictly greater than another
+ */
+inline const PRBool
+operator >(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue > aTime2.mValue;
+}
+
+/**
+ * Determine if one time is greater than or equal to another
+ */
+inline const PRBool
+operator >=(const nsTime& aTime1, const nsTime& aTime2) {
+ return aTime1.mValue >= aTime2.mValue;
+}
+
+#endif // nsTime_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp
new file mode 100644
index 00000000..4974f562
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.cpp
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTimelineService.h"
+#include "prlong.h"
+#include "prprf.h"
+#include "prenv.h"
+#include "plhash.h"
+#include "prlock.h"
+#include "prinit.h"
+#include "prinrval.h"
+#include "prthread.h"
+
+#ifdef MOZ_TIMELINE
+
+#define MAXINDENT 20
+
+#ifdef XP_MAC
+static PRIntervalTime initInterval = 0;
+#endif
+
+static PRFileDesc *timelineFD = PR_STDERR;
+static PRBool gTimelineDisabled = PR_TRUE;
+
+// Notes about threading:
+// We avoid locks as we always use thread-local-storage.
+// This means every other thread has its own private copy of
+// data, and this thread can't re-enter (as our implemenation
+// doesn't call back out anywhere). Thus, we can avoid locks!
+// TLS index
+static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
+static PRUintn gTLSIndex = BAD_TLS_INDEX;
+
+class TimelineThreadData {
+public:
+ TimelineThreadData() : initTime(0), indent(0),
+ disabled(PR_TRUE), timers(nsnull) {}
+ ~TimelineThreadData() {if (timers) PL_HashTableDestroy(timers);}
+ PRTime initTime;
+ PRHashTable *timers;
+ int indent;
+ PRBool disabled;
+};
+
+/* Implementation file */
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTimelineService, nsITimelineService)
+
+static PRTime Now(void);
+
+/*
+ * Timer structure stored in a hash table to keep track of named
+ * timers.
+ */
+class nsTimelineServiceTimer {
+ public:
+ nsTimelineServiceTimer();
+ ~nsTimelineServiceTimer();
+ void start();
+
+ /*
+ * Caller passes in "now" rather than having us calculate it so
+ * that we can avoid including timer overhead in the time being
+ * measured.
+ */
+ void stop(PRTime now);
+ void reset();
+ PRTime getAccum();
+ PRTime getAccum(PRTime now);
+
+ private:
+ PRTime mAccum;
+ PRTime mStart;
+ PRInt32 mRunning;
+ PRThread *mOwnerThread; // only used for asserts - could be #if MOZ_DEBUG
+};
+
+#define TIMER_CHECK_OWNER() \
+ NS_ABORT_IF_FALSE(PR_GetCurrentThread() == mOwnerThread, \
+ "Timer used by non-owning thread")
+
+
+nsTimelineServiceTimer::nsTimelineServiceTimer()
+: mAccum(LL_ZERO), mStart(LL_ZERO), mRunning(0),
+ mOwnerThread(PR_GetCurrentThread())
+{
+}
+
+nsTimelineServiceTimer::~nsTimelineServiceTimer()
+{
+}
+
+void nsTimelineServiceTimer::start()
+{
+ TIMER_CHECK_OWNER();
+ if (!mRunning) {
+ mStart = Now();
+ }
+ mRunning++;
+}
+
+void nsTimelineServiceTimer::stop(PRTime now)
+{
+ TIMER_CHECK_OWNER();
+ mRunning--;
+ if (mRunning == 0) {
+ PRTime delta, accum;
+ LL_SUB(delta, now, mStart);
+ LL_ADD(accum, mAccum, delta);
+ mAccum = accum;
+ }
+}
+
+void nsTimelineServiceTimer::reset()
+{
+ TIMER_CHECK_OWNER();
+ mStart = 0;
+ mAccum = 0;
+}
+
+PRTime nsTimelineServiceTimer::getAccum()
+{
+ TIMER_CHECK_OWNER();
+ PRTime accum;
+
+ if (!mRunning) {
+ accum = mAccum;
+ } else {
+ PRTime delta;
+ LL_SUB(delta, Now(), mStart);
+ LL_ADD(accum, mAccum, delta);
+ }
+ return accum;
+}
+
+PRTime nsTimelineServiceTimer::getAccum(PRTime now)
+{
+ TIMER_CHECK_OWNER();
+ PRTime accum;
+
+ if (!mRunning) {
+ accum = mAccum;
+ } else {
+ PRTime delta;
+ LL_SUB(delta, now, mStart);
+ LL_ADD(accum, mAccum, delta);
+ }
+ return accum;
+}
+
+#ifdef XP_MAC
+/*
+ * PR_Now() on the Mac only gives us a resolution of seconds. Using
+ * PR_IntervalNow() gives us better resolution. with the drawback that
+ * the timeline is only good for about six hours.
+ *
+ * PR_IntervalNow() occasionally exhibits discontinuities on Windows,
+ * so we only use it on the Mac. Bleah!
+ */
+static PRTime Now(void)
+{
+ PRIntervalTime numTicks = PR_IntervalNow() - initInterval;
+ PRTime now;
+ LL_ADD(now, initTime, PR_IntervalToMilliseconds(numTicks) * 1000);
+ return now;
+}
+#else
+static PRTime Now(void)
+{
+ return PR_Now();
+}
+#endif
+
+static TimelineThreadData *GetThisThreadData()
+{
+ NS_ABORT_IF_FALSE(gTLSIndex!=BAD_TLS_INDEX, "Our TLS not initialized");
+ TimelineThreadData *new_data = nsnull;
+ TimelineThreadData *data = (TimelineThreadData *)PR_GetThreadPrivate(gTLSIndex);
+ if (data == nsnull) {
+ // First request for this thread - allocate it.
+ new_data = new TimelineThreadData();
+ if (!new_data)
+ goto done;
+
+ // Fill it
+ new_data->timers = PL_NewHashTable(100, PL_HashString, PL_CompareStrings,
+ PL_CompareValues, NULL, NULL);
+ if (new_data->timers==NULL)
+ goto done;
+ new_data->initTime = PR_Now();
+ NS_WARN_IF_FALSE(!gTimelineDisabled,
+ "Why are we creating new state when disabled?");
+ new_data->disabled = PR_FALSE;
+ data = new_data;
+ new_data = nsnull;
+ PR_SetThreadPrivate(gTLSIndex, data);
+ }
+done:
+ if (new_data) // eeek - error during creation!
+ delete new_data;
+ NS_WARN_IF_FALSE(data, "TimelineService could not get thread-local data");
+ return data;
+}
+
+extern "C" {
+ static void ThreadDestruct (void *data);
+ static PRStatus TimelineInit(void);
+};
+
+void ThreadDestruct( void *data )
+{
+ if (data)
+ delete (TimelineThreadData *)data;
+}
+
+/*
+* PRCallOnceFN that initializes stuff for the timing service.
+*/
+static PRCallOnceType initonce;
+
+PRStatus TimelineInit(void)
+{
+ char *timeStr;
+ char *fileName;
+ PRInt32 secs, msecs;
+ PRFileDesc *fd;
+ PRInt64 tmp1, tmp2;
+
+ PRStatus status = PR_NewThreadPrivateIndex( &gTLSIndex, ThreadDestruct );
+ NS_WARN_IF_FALSE(status==0, "TimelineService could not allocate TLS storage.");
+
+ timeStr = PR_GetEnv("NS_TIMELINE_INIT_TIME");
+#ifdef XP_MAC
+ initInterval = PR_IntervalNow();
+#endif
+ // NS_TIMELINE_INIT_TIME only makes sense for the main thread, so if it
+ // exists, set it there. If not, let normal thread management code take
+ // care of setting the init time.
+ if (timeStr != NULL && 2 == PR_sscanf(timeStr, "%d.%d", &secs, &msecs)) {
+ PRTime &initTime = GetThisThreadData()->initTime;
+ LL_MUL(tmp1, (PRInt64)secs, 1000000);
+ LL_MUL(tmp2, (PRInt64)msecs, 1000);
+ LL_ADD(initTime, tmp1, tmp2);
+#ifdef XP_MAC
+ initInterval -= PR_MicrosecondsToInterval(
+ (PRUint32)(PR_Now() - initTime));
+#endif
+ }
+ // Get the log file.
+#ifdef XP_MAC
+ fileName = "timeline.txt";
+#else
+ fileName = PR_GetEnv("NS_TIMELINE_LOG_FILE");
+#endif
+ if (fileName != NULL
+ && (fd = PR_Open(fileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666)) != NULL) {
+ timelineFD = fd;
+ PR_fprintf(fd,
+ "NOTE: due to asynchrony, the indentation that you see does"
+ " not necessarily correspond to nesting in the code.\n\n");
+ }
+
+ // Runtime disable of timeline
+ if (PR_GetEnv("NS_TIMELINE_ENABLE"))
+ gTimelineDisabled = PR_FALSE;
+ return PR_SUCCESS;
+}
+
+static void ParseTime(PRTime tm, PRInt32& secs, PRInt32& msecs)
+{
+ PRTime llsecs, llmsecs, tmp;
+
+ LL_DIV(llsecs, tm, 1000000);
+ LL_MOD(tmp, tm, 1000000);
+ LL_DIV(llmsecs, tmp, 1000);
+
+ LL_L2I(secs, llsecs);
+ LL_L2I(msecs, llmsecs);
+}
+
+static char *Indent(char *buf)
+{
+ int &indent = GetThisThreadData()->indent;
+ int amount = indent;
+ if (amount > MAXINDENT) {
+ amount = MAXINDENT;
+ }
+ if (amount < 0) {
+ amount = 0;
+ indent = 0;
+ PR_Write(timelineFD, "indent underflow!\n", 18);
+ }
+ while (amount--) {
+ *buf++ = ' ';
+ }
+ return buf;
+}
+
+static void PrintTime(PRTime tm, const char *text, va_list args)
+{
+ PRInt32 secs, msecs;
+ char pbuf[550], *pc, tbuf[550];
+
+ ParseTime(tm, secs, msecs);
+
+ // snprintf/write rather than fprintf because we don't want
+ // messages from multiple threads to garble one another.
+ pc = Indent(pbuf);
+ PR_vsnprintf(pc, sizeof pbuf - (pc - pbuf), text, args);
+ PR_snprintf(tbuf, sizeof tbuf, "%05d.%03d (%08p): %s\n",
+ secs, msecs, PR_GetCurrentThread(), pbuf);
+ PR_Write(timelineFD, tbuf, strlen(tbuf));
+}
+
+/*
+ * Make this public if we need it.
+ */
+static nsresult NS_TimelineMarkV(const char *text, va_list args)
+{
+ PRTime elapsed,tmp;
+
+ PR_CallOnce(&initonce, TimelineInit);
+
+ TimelineThreadData *thread = GetThisThreadData();
+
+ tmp = Now();
+ LL_SUB(elapsed, tmp, thread->initTime);
+
+ PrintTime(elapsed, text, args);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineForceMark(const char *text, ...)
+{
+ va_list args;
+ va_start(args, text);
+ NS_TimelineMarkV(text, args);
+ va_end(args);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineMark(const char *text, ...)
+{
+ va_list args;
+
+ PR_CallOnce(&initonce, TimelineInit);
+
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ va_start(args, text);
+ NS_TimelineMarkV(text, args);
+ va_end(args);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineStartTimer(const char *timerName)
+{
+ PR_CallOnce(&initonce, TimelineInit);
+
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ timer = new nsTimelineServiceTimer;
+ if (!timer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PL_HashTableAdd(thread->timers, timerName, timer);
+ }
+ timer->start();
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineStopTimer(const char *timerName)
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ /*
+ * Strange-looking now/timer->stop() interaction is to avoid
+ * including time spent in TLS and PL_HashTableLookup in the
+ * timer.
+ */
+ PRTime now = Now();
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+
+ timer->stop(now);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineMarkTimer(const char *timerName, const char *str)
+{
+ PR_CallOnce(&initonce, TimelineInit);
+
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+ PRTime accum = timer->getAccum();
+
+ char buf[500];
+ PRInt32 sec, msec;
+ ParseTime(accum, sec, msec);
+ if (!str)
+ PR_snprintf(buf, sizeof buf, "%s total: %d.%03d",
+ timerName, sec, msec);
+ else
+ PR_snprintf(buf, sizeof buf, "%s total: %d.%03d (%s)",
+ timerName, sec, msec, str);
+ NS_TimelineMark(buf);
+
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineResetTimer(const char *timerName)
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->timers == NULL)
+ return NS_ERROR_FAILURE;
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ nsTimelineServiceTimer *timer
+ = (nsTimelineServiceTimer *)PL_HashTableLookup(thread->timers, timerName);
+ if (timer == NULL) {
+ return NS_ERROR_FAILURE;
+ }
+
+ timer->reset();
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineIndent()
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ thread->indent++;
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineOutdent()
+{
+ if (gTimelineDisabled)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ TimelineThreadData *thread = GetThisThreadData();
+ if (thread->disabled)
+ return NS_ERROR_NOT_AVAILABLE;
+ thread->indent--;
+ return NS_OK;
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineEnter(const char *text)
+{
+ nsresult rv = NS_TimelineMark("%s...", text);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_TimelineIndent();
+}
+
+PR_IMPLEMENT(nsresult) NS_TimelineLeave(const char *text)
+{
+ nsresult rv = NS_TimelineOutdent();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_TimelineMark("...%s", text);
+}
+
+nsTimelineService::nsTimelineService()
+{
+ /* member initializers and constructor code */
+}
+
+/* void mark (in string text); */
+NS_IMETHODIMP nsTimelineService::Mark(const char *text)
+{
+ return NS_TimelineMark(text);
+}
+
+/* void startTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::StartTimer(const char *timerName)
+{
+ return NS_TimelineStartTimer(timerName);
+}
+
+/* void stopTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::StopTimer(const char *timerName)
+{
+ return NS_TimelineStopTimer(timerName);
+}
+
+/* void markTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::MarkTimer(const char *timerName)
+{
+ return NS_TimelineMarkTimer(timerName);
+}
+
+/* void markTimerWithComment(in string timerName, in string comment); */
+NS_IMETHODIMP nsTimelineService::MarkTimerWithComment(const char *timerName, const char *comment)
+{
+ return NS_TimelineMarkTimer(timerName, comment);
+}
+
+/* void resetTimer (in string timerName); */
+NS_IMETHODIMP nsTimelineService::ResetTimer(const char *timerName)
+{
+ return NS_TimelineResetTimer(timerName);
+}
+
+/* void indent (); */
+NS_IMETHODIMP nsTimelineService::Indent()
+{
+ return NS_TimelineIndent();
+}
+
+/* void outdent (); */
+NS_IMETHODIMP nsTimelineService::Outdent()
+{
+ return NS_TimelineOutdent();
+}
+
+/* void enter (in string text); */
+NS_IMETHODIMP nsTimelineService::Enter(const char *text)
+{
+ return NS_TimelineEnter(text);
+}
+
+/* void leave (in string text); */
+NS_IMETHODIMP nsTimelineService::Leave(const char *text)
+{
+ return NS_TimelineLeave(text);
+}
+
+#endif /* MOZ_TIMELINE */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h
new file mode 100644
index 00000000..bb579755
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsTimelineService.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsITimelineService.h"
+
+#ifdef MOZ_TIMELINE
+
+#define NS_TIMELINESERVICE_CID \
+{ /* a335edf0-3daf-11d5-b67d-000064657374 */ \
+ 0xa335edf0, \
+ 0x3daf, \
+ 0x11d5, \
+ {0xb6, 0x7d, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
+
+#define NS_TIMELINESERVICE_CONTRACTID "@mozilla.org;timeline-service;1"
+#define NS_TIMELINESERVICE_CLASSNAME "Timeline Service"
+
+class nsTimelineService : public nsITimelineService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMELINESERVICE
+
+ nsTimelineService();
+
+private:
+ ~nsTimelineService() {}
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp
new file mode 100644
index 00000000..12033da0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsUnicharBuffer.h"
+#include "nsCRT.h"
+
+#define MIN_BUFFER_SIZE 32
+
+UnicharBufferImpl::UnicharBufferImpl()
+ : mBuffer(NULL), mSpace(0), mLength(0)
+{
+}
+
+NS_METHOD
+UnicharBufferImpl::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ UnicharBufferImpl* it = new UnicharBufferImpl();
+ if (it == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(it);
+ nsresult rv = it->QueryInterface(aIID, aResult);
+ NS_RELEASE(it);
+ return rv;
+}
+
+NS_IMETHODIMP
+UnicharBufferImpl::Init(PRUint32 aBufferSize)
+{
+ if (aBufferSize < MIN_BUFFER_SIZE) {
+ aBufferSize = MIN_BUFFER_SIZE;
+ }
+ mSpace = aBufferSize;
+ mLength = 0;
+ mBuffer = new PRUnichar[aBufferSize];
+ return mBuffer ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMPL_ISUPPORTS1(UnicharBufferImpl, nsIUnicharBuffer)
+
+UnicharBufferImpl::~UnicharBufferImpl()
+{
+ if (nsnull != mBuffer) {
+ delete[] mBuffer;
+ mBuffer = nsnull;
+ }
+ mLength = 0;
+}
+
+NS_IMETHODIMP_(PRInt32)
+UnicharBufferImpl::GetLength() const
+{
+ return mLength;
+}
+
+NS_IMETHODIMP_(PRInt32)
+UnicharBufferImpl::GetBufferSize() const
+{
+ return mSpace;
+}
+
+NS_IMETHODIMP_(PRUnichar*)
+UnicharBufferImpl::GetBuffer() const
+{
+ return mBuffer;
+}
+
+NS_IMETHODIMP_(PRBool)
+UnicharBufferImpl::Grow(PRInt32 aNewSize)
+{
+ if (PRUint32(aNewSize) < MIN_BUFFER_SIZE) {
+ aNewSize = MIN_BUFFER_SIZE;
+ }
+ PRUnichar* newbuf = new PRUnichar[aNewSize];
+ if (nsnull != newbuf) {
+ if (0 != mLength) {
+ memcpy(newbuf, mBuffer, mLength * sizeof(PRUnichar));
+ }
+ delete[] mBuffer;
+ mBuffer = newbuf;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+NS_COM nsresult
+NS_NewUnicharBuffer(nsIUnicharBuffer** aInstancePtrResult,
+ nsISupports* aOuter,
+ PRUint32 aBufferSize)
+{
+ nsresult rv;
+ nsIUnicharBuffer* buf;
+ rv = UnicharBufferImpl::Create(aOuter, NS_GET_IID(nsIUnicharBuffer),
+ (void**)&buf);
+ if (NS_FAILED(rv)) return rv;
+ rv = buf->Init(aBufferSize);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(buf);
+ return rv;
+ }
+ *aInstancePtrResult = buf;
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h
new file mode 100644
index 00000000..d57a48ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsUnicharBuffer.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsUnicharBuffer_h__
+#define nsUnicharBuffer_h__
+
+#include "nsIUnicharBuffer.h"
+
+class UnicharBufferImpl : public nsIUnicharBuffer {
+public:
+ UnicharBufferImpl();
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Init(PRUint32 aBufferSize);
+ NS_IMETHOD_(PRInt32) GetLength() const;
+ NS_IMETHOD_(PRInt32) GetBufferSize() const;
+ NS_IMETHOD_(PRUnichar*) GetBuffer() const;
+ NS_IMETHOD_(PRBool) Grow(PRInt32 aNewSize);
+
+ PRUnichar* mBuffer;
+ PRUint32 mSpace;
+ PRUint32 mLength;
+
+private:
+ ~UnicharBufferImpl();
+};
+
+#endif // nsUnicharBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h b/src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h
new file mode 100644
index 00000000..07825385
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsUnitConversion.h
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsUnitConversion_h__
+#define nsUnitConversion_h__
+
+#include "nscore.h"
+#include "nsCoord.h"
+#include <math.h>
+#include <float.h>
+
+#ifndef FLT_EPSILON
+// Not an ANSI compiler... oh, well. Use an IEEE value.
+#define FLT_EPSILON 1.19209290e-7f
+#endif
+/// handy constants
+#define TWIPS_PER_POINT_INT 20
+#define TWIPS_PER_POINT_FLOAT 20.0f
+#define CEIL_CONST_FLOAT (1.0f - 0.5f*FLT_EPSILON)
+#define ROUND_EXCLUSIVE_CONST_FLOAT (0.5f*CEIL_CONST_FLOAT)
+#define ROUND_CONST_FLOAT 0.5f
+
+
+/*
+ * Coord Rounding Functions
+ */
+inline nscoord NSToCoordFloor(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue) : nscoord(aValue - CEIL_CONST_FLOAT));
+}
+
+inline nscoord NSToCoordCeil(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue + CEIL_CONST_FLOAT) : nscoord(aValue));
+}
+
+inline nscoord NSToCoordRound(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue + ROUND_CONST_FLOAT) : nscoord(aValue - ROUND_CONST_FLOAT));
+}
+
+inline nscoord NSToCoordRoundExclusive(float aValue)
+{
+ return ((0.0f <= aValue) ? nscoord(aValue + ROUND_EXCLUSIVE_CONST_FLOAT) :
+ nscoord(aValue - ROUND_EXCLUSIVE_CONST_FLOAT));
+}
+
+
+/*
+ * Int Rounding Functions
+ */
+inline PRInt32 NSToIntFloor(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue) : PRInt32(aValue - CEIL_CONST_FLOAT));
+}
+
+inline PRInt32 NSToIntCeil(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue + CEIL_CONST_FLOAT) : PRInt32(aValue));
+}
+
+inline PRInt32 NSToIntRound(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue + ROUND_CONST_FLOAT) : PRInt32(aValue - ROUND_CONST_FLOAT));
+}
+
+inline PRInt32 NSToIntRoundExclusive(float aValue)
+{
+ return ((0.0f <= aValue) ? PRInt32(aValue + ROUND_EXCLUSIVE_CONST_FLOAT) :
+ PRInt32(aValue - ROUND_EXCLUSIVE_CONST_FLOAT));
+}
+
+
+/*
+ * Twips/Points conversions
+ */
+inline nscoord NSFloatPointsToTwips(float aPoints)
+{
+ return NSToCoordRound(aPoints * TWIPS_PER_POINT_FLOAT);
+}
+
+inline nscoord NSIntPointsToTwips(PRInt32 aPoints)
+{
+ return nscoord(aPoints * TWIPS_PER_POINT_INT);
+}
+
+inline PRInt32 NSTwipsToIntPoints(nscoord aTwips)
+{
+ return NSToIntRound(aTwips / TWIPS_PER_POINT_FLOAT);
+}
+
+inline PRInt32 NSTwipsToFloorIntPoints(nscoord aTwips)
+{
+ return NSToIntFloor(aTwips / TWIPS_PER_POINT_FLOAT);
+}
+
+inline PRInt32 NSTwipsToCeilIntPoints(nscoord aTwips)
+{
+ return NSToIntCeil(aTwips / TWIPS_PER_POINT_FLOAT);
+}
+
+inline float NSTwipsToFloatPoints(nscoord aTwips)
+{
+ return (float(aTwips) / TWIPS_PER_POINT_FLOAT);
+}
+
+/*
+ * Twips/Pixel conversions
+ */
+inline nscoord NSFloatPixelsToTwips(float aPixels, float aTwipsPerPixel)
+{
+ return NSToCoordRound(aPixels * aTwipsPerPixel);
+}
+
+inline nscoord NSIntPixelsToTwips(PRInt32 aPixels, float aTwipsPerPixel)
+{
+ return NSToCoordRound(float(aPixels) * aTwipsPerPixel);
+}
+
+inline float NSTwipsToFloatPixels(nscoord aTwips, float aPixelsPerTwip)
+{
+ return (float(aTwips) * aPixelsPerTwip);
+}
+
+inline PRInt32 NSTwipsToIntPixels(nscoord aTwips, float aPixelsPerTwip)
+{
+ return NSToIntRound(float(aTwips) * aPixelsPerTwip);
+}
+
+/*
+ * Twips/unit conversions
+ */
+inline nscoord NSUnitsToTwips(float aValue, float aPointsPerUnit)
+{
+ return NSToCoordRound(aValue * aPointsPerUnit * TWIPS_PER_POINT_FLOAT);
+}
+
+inline float NSTwipsToUnits(nscoord aTwips, float aUnitsPerPoint)
+{
+ return (aTwips * (aUnitsPerPoint / TWIPS_PER_POINT_FLOAT));
+}
+
+
+/// Unit conversion macros
+//@{
+#define NS_INCHES_TO_TWIPS(x) NSUnitsToTwips((x), 72.0f) // 72 points per inch
+#define NS_FEET_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 12.0f)) // 12 inches per foot
+#define NS_MILES_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 12.0f * 5280.0f)) // 5280 feet per mile
+
+#define NS_MILLIMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 0.03937f))
+#define NS_CENTIMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 0.3937f))
+#define NS_METERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 39.37f))
+#define NS_KILOMETERS_TO_TWIPS(x) NSUnitsToTwips((x), (72.0f * 39370.0f))
+
+#define NS_PICAS_TO_TWIPS(x) NSUnitsToTwips((x), 12.0f) // 12 points per pica
+#define NS_DIDOTS_TO_TWIPS(x) NSUnitsToTwips((x), (16.0f / 15.0f)) // 15 didots per 16 points
+#define NS_CICEROS_TO_TWIPS(x) NSUnitsToTwips((x), (12.0f * (16.0f / 15.0f))) // 12 didots per cicero
+
+
+#define NS_TWIPS_TO_INCHES(x) NSTwipsToUnits((x), 1.0f / 72.0f)
+#define NS_TWIPS_TO_FEET(x) NSTwipsToUnits((x), 1.0f / (72.0f * 12.0f))
+#define NS_TWIPS_TO_MILES(x) NSTwipsToUnits((x), 1.0f / (72.0f * 12.0f * 5280.0f))
+
+#define NS_TWIPS_TO_MILLIMETERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 0.03937f))
+#define NS_TWIPS_TO_CENTIMETERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 0.3937f))
+#define NS_TWIPS_TO_METERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 39.37f))
+#define NS_TWIPS_TO_KILOMETERS(x) NSTwipsToUnits((x), 1.0f / (72.0f * 39370.0f))
+
+#define NS_TWIPS_TO_PICAS(x) NSTwipsToUnits((x), 1.0f / 12.0f)
+#define NS_TWIPS_TO_DIDOTS(x) NSTwipsToUnits((x), 1.0f / (16.0f / 15.0f))
+#define NS_TWIPS_TO_CICEROS(x) NSTwipsToUnits((x), 1.0f / (12.0f * (16.0f / 15.0f)))
+//@}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp
new file mode 100644
index 00000000..4660ccec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.cpp
@@ -0,0 +1,304 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsValueArray.h/nsValueArray.cpp code, released
+ * Dec 28, 2001.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 20-December-2001
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//
+// nsValueArray.cpp
+//
+// Implement an array class to store unsigned integer values.
+// The maximum value must be known up front. Once known, the
+// smallest memory representation will be attempted; i.e. if the
+// maximum value was 1275, then 2 bytes (uint16) would represent each value
+// in the array instead of 4 bytes (uint32).
+//
+#include "nsValueArray.h"
+#include "nsCRT.h"
+#include "prmem.h"
+#include "prbit.h"
+
+#define NSVALUEARRAY_LINEAR_GROWBY 8
+#define NSVALUEARRAY_LINEAR_THRESHOLD 128
+
+nsValueArray::nsValueArray(nsValueArrayValue aMaxValue, nsValueArrayCount aInitialCapacity) {
+ mCount = 0;
+ mCapacity = 0;
+ mValueArray = nsnull;
+
+ PRUint8 test8 = (PRUint8)aMaxValue;
+ PRUint16 test16 = (PRUint16)aMaxValue;
+ PRUint32 test32 = (PRUint32)aMaxValue;
+ if ((nsValueArrayValue)test8 == aMaxValue) {
+ mBytesPerValue = sizeof(test8);
+ }
+ else if ((nsValueArrayValue)test16 == aMaxValue) {
+ mBytesPerValue = sizeof(test16);
+ }
+ else if ((nsValueArrayValue)test32 == aMaxValue) {
+ mBytesPerValue = sizeof(test32);
+ }
+ else {
+ NS_ASSERTION(0, "not supported yet, add it yourself...");
+ mBytesPerValue = 0;
+ }
+
+ if (aInitialCapacity) {
+ mValueArray = (PRUint8*)PR_Malloc(aInitialCapacity * mBytesPerValue);
+ if (nsnull != mValueArray) {
+ mCapacity = aInitialCapacity;
+ }
+ }
+}
+
+nsValueArray::~nsValueArray() {
+ if (nsnull != mValueArray) {
+ PR_Free(mValueArray);
+ mValueArray = nsnull;
+ }
+}
+
+//
+// Copy it.
+//
+nsValueArray& nsValueArray::operator=(const nsValueArray& aOther) {
+ //
+ // Free off what you know if not enough space, or units differ.
+ //
+ if ((mBytesPerValue != aOther.mBytesPerValue || mCapacity < aOther.mCount) && nsnull != mValueArray) {
+ PR_Free(mValueArray);
+ mValueArray = nsnull;
+ mCount = mCapacity = 0;
+ }
+
+ //
+ // Copy some attribs.
+ //
+ mBytesPerValue = aOther.mBytesPerValue;
+ mCount = aOther.mCount;
+
+ //
+ // Anything to do?
+ //
+ if (0 != mCount) {
+ //
+ // May need to allocate our buffer.
+ //
+ if (0 == mCapacity) {
+ mValueArray = (PRUint8*)PR_Malloc(mCount * mBytesPerValue);
+ mCapacity = mCount;
+ }
+
+ NS_ASSERTION(nsnull != mValueArray, "loss of value array assignment and original data.");
+ if (nsnull != mValueArray) {
+ memcpy(mValueArray, aOther.mValueArray, mCount * mBytesPerValue);
+ }
+ else {
+ mCount = mCapacity = 0;
+ }
+ }
+
+ return *this;
+}
+
+//
+// Insert a value into the array.
+// No validity checking other than index is done.
+//
+PRBool nsValueArray::InsertValueAt(nsValueArrayValue aValue, nsValueArrayIndex aIndex) {
+ PRBool retval = PR_FALSE;
+
+ nsValueArrayCount count = Count();
+ if (aIndex <= count) {
+ //
+ // If we're at capacity, then we'll need to grow a little.
+ //
+ if (Capacity() == count) {
+ PRUint8* reallocRes = nsnull;
+ nsValueArrayCount growBy = NSVALUEARRAY_LINEAR_GROWBY;
+
+ //
+ // Up to a particular limit we grow in small increments.
+ // Otherwise, grow exponentially.
+ //
+ if (count >= NSVALUEARRAY_LINEAR_THRESHOLD) {
+ growBy = PR_BIT(PR_CeilingLog2(count + 1)) - count;
+ }
+
+ if (nsnull == mValueArray) {
+ reallocRes = (PRUint8*)PR_Malloc((count + growBy) * mBytesPerValue);
+ }
+ else {
+ reallocRes = (PRUint8*)PR_Realloc(mValueArray, (count + growBy) * mBytesPerValue);
+ }
+ if (nsnull != reallocRes) {
+ mValueArray = reallocRes;
+ mCapacity += growBy;
+ }
+ }
+
+ //
+ // Only if we are below capacity do we continue.
+ //
+ if (Capacity() > count) {
+ //
+ // All those at and beyond the insertion point need to move.
+ //
+ if (aIndex < count) {
+ memmove(&mValueArray[(aIndex + 1) * mBytesPerValue], &mValueArray[aIndex * mBytesPerValue], (count - aIndex) * mBytesPerValue);
+ }
+
+ //
+ // Do the assignment.
+ //
+ switch (mBytesPerValue) {
+ case sizeof(PRUint8):
+ *((PRUint8*)&mValueArray[aIndex * mBytesPerValue]) = (PRUint8)aValue;
+ NS_ASSERTION(*((PRUint8*)&mValueArray[aIndex * mBytesPerValue]) == aValue, "Lossy value array detected. Report a higher maximum upon construction!");
+ break;
+ case sizeof(PRUint16):
+ *((PRUint16*)&mValueArray[aIndex * mBytesPerValue]) = (PRUint16)aValue;
+ NS_ASSERTION(*((PRUint16*)&mValueArray[aIndex * mBytesPerValue]) == aValue, "Lossy value array detected. Report a higher maximum upon construction!");
+ break;
+ case sizeof(PRUint32):
+ *((PRUint32*)&mValueArray[aIndex * mBytesPerValue]) = (PRUint32)aValue;
+ NS_ASSERTION(*((PRUint32*)&mValueArray[aIndex * mBytesPerValue]) == aValue, "Lossy value array detected. Report a higher maximum upon construction!");
+ break;
+ default:
+ NS_ASSERTION(0, "surely you've been warned prior to this!");
+ break;
+ }
+
+ //
+ // Up the count by 1.
+ //
+ mCount++;
+ }
+ }
+
+ return retval;
+}
+
+//
+// Remove the index from the value array.
+// The array does not shrink until Compact() is invoked.
+//
+PRBool nsValueArray::RemoveValueAt(nsValueArrayIndex aIndex) {
+ PRBool retval = PR_FALSE;
+
+ nsValueArrayCount count = Count();
+ if (aIndex < count) {
+ //
+ // Move memory around if appropriate.
+ //
+ if (aIndex != (count - 1)) {
+ memmove(&mValueArray[aIndex * mBytesPerValue], &mValueArray[(aIndex + 1) * mBytesPerValue], (count - aIndex - 1) * mBytesPerValue);
+ }
+
+ //
+ // Update our count.
+ //
+ mCount--;
+ }
+
+ return retval;
+}
+
+//
+// Shrink as much as possible.
+//
+void nsValueArray::Compact() {
+ nsValueArrayCount count = Count();
+ if (Capacity() != count)
+ {
+ if (0 == count) {
+ PR_Free(mValueArray);
+ mValueArray = nsnull;
+ mCapacity = 0;
+ }
+ else {
+ PRUint8* reallocRes = (PRUint8*)PR_Realloc(mValueArray, count * mBytesPerValue);
+ if (nsnull != reallocRes) {
+ mValueArray = reallocRes;
+ mCapacity = count;
+ }
+ }
+ }
+}
+
+//
+// Return the value at the index.
+//
+nsValueArrayValue nsValueArray::ValueAt(nsValueArrayIndex aIndex) const {
+ nsValueArrayValue retval = NSVALUEARRAY_INVALID;
+
+ if (aIndex < Count()) {
+ switch (mBytesPerValue) {
+ case sizeof(PRUint8):
+ retval = (nsValueArrayIndex)*((PRUint8*)&mValueArray[aIndex * mBytesPerValue]);
+ break;
+ case sizeof(PRUint16):
+ retval = (nsValueArrayIndex)*((PRUint16*)&mValueArray[aIndex * mBytesPerValue]);
+ break;
+ case sizeof(PRUint32):
+ retval = (nsValueArrayIndex)*((PRUint32*)&mValueArray[aIndex * mBytesPerValue]);
+ break;
+ default:
+ NS_ASSERTION(0, "unexpected for sure.");
+ break;
+ }
+ }
+
+ return retval;
+}
+
+//
+// Return the first encountered index of the value.
+//
+nsValueArrayIndex nsValueArray::IndexOf(nsValueArrayValue aPossibleValue) const {
+ nsValueArrayIndex retval = NSVALUEARRAY_INVALID;
+ nsValueArrayIndex traverse;
+
+ for (traverse = 0; traverse < Count(); traverse++) {
+ if (aPossibleValue == ValueAt(traverse)) {
+ retval = traverse;
+ break;
+ }
+ }
+
+ return retval;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsValueArray.h b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.h
new file mode 100644
index 00000000..6437ca60
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsValueArray.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is nsValueArray.h/nsValueArray.cpp code, released
+ * Dec 28, 2001.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Garrett Arch Blythe, 20-December-2001
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsValueArray_h___
+#define nsValueArray_h___
+
+//
+// nsValueArray.h
+//
+// Implement an array class to store unsigned integer values.
+// The maximum value must be known up front. Once known, the
+// smallest memory representation will be attempted; i.e. if the
+// maximum value was 1275, then 2 bytes (uint16) would represent each value
+// in the array instead of 4 bytes (uint32).
+//
+#include "nscore.h"
+
+typedef PRUint32 nsValueArrayCount;
+typedef PRUint32 nsValueArrayIndex;
+typedef PRUint32 nsValueArrayValue;
+#define NSVALUEARRAY_INVALID ((nsValueArrayValue)-1)
+
+class NS_COM nsValueArray {
+ public:
+ nsValueArray(nsValueArrayValue aMaxValue,
+ nsValueArrayCount aInitialCapacity = 0);
+ ~nsValueArray();
+
+ //
+ // Assignment.
+ //
+ public:
+ nsValueArray& operator=(const nsValueArray& other);
+
+ //
+ // Array size information.
+ // Ability to add more values without growing is Capacity - Count.
+ //
+ public:
+ inline nsValueArrayCount Count() const {
+ return mCount;
+ }
+
+ inline nsValueArrayCount Capacity() const {
+ return mCapacity;
+ }
+
+ void Compact();
+
+ // Removes all elements from this array
+ inline void Clear() {
+ mCount = 0;
+ }
+
+ //
+ // Array access.
+ //
+ public:
+ nsValueArrayValue ValueAt(nsValueArrayIndex aIndex) const;
+
+ inline nsValueArrayValue operator[](nsValueArrayIndex aIndex) const {
+ return ValueAt(aIndex);
+ }
+
+ nsValueArrayIndex IndexOf(nsValueArrayValue aPossibleValue) const;
+
+ inline PRBool AppendValue(nsValueArrayValue aValue) {
+ return InsertValueAt(aValue, Count());
+ }
+
+ inline PRBool RemoveValue(nsValueArrayValue aValue) {
+ return RemoveValueAt(IndexOf(aValue));
+ }
+
+ PRBool InsertValueAt(nsValueArrayValue aValue, nsValueArrayIndex aIndex);
+
+ PRBool RemoveValueAt(nsValueArrayIndex aIndex);
+
+ //
+ // Data members.
+ //
+ private:
+ nsValueArrayCount mCount;
+ nsValueArrayCount mCapacity;
+ PRUint8* mValueArray;
+ PRUint8 mBytesPerValue;
+};
+
+#endif /* nsValueArray_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp b/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp
new file mode 100644
index 00000000..09a4cda5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp
@@ -0,0 +1,2092 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The long avoided variant support for xpcom. */
+
+#include "nsVariant.h"
+#include "nsString.h"
+#include "prprf.h"
+#include "prdtoa.h"
+#include <math.h>
+#include "nsCRT.h"
+
+/***************************************************************************/
+// Helpers for static convert functions...
+
+static nsresult String2Double(const char* aString, double* retval)
+{
+ char* next;
+ double value = PR_strtod(aString, &next);
+ if(next == aString)
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ *retval = value;
+ return NS_OK;
+}
+
+static nsresult AString2Double(const nsAString& aString, double* retval)
+{
+ char* pChars = ToNewCString(aString);
+ if(!pChars)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = String2Double(pChars, retval);
+ nsMemory::Free(pChars);
+ return rv;
+}
+
+static nsresult AUTF8String2Double(const nsAUTF8String& aString, double* retval)
+{
+ return String2Double(PromiseFlatUTF8String(aString).get(), retval);
+}
+
+static nsresult ACString2Double(const nsACString& aString, double* retval)
+{
+ return String2Double(PromiseFlatCString(aString).get(), retval);
+}
+
+// Fills outVariant with double, PRUint32, or PRInt32.
+// Returns NS_OK, an error code, or a non-NS_OK success code
+static nsresult ToManageableNumber(const nsDiscriminatedUnion& inData,
+ nsDiscriminatedUnion* outData)
+{
+ nsresult rv;
+
+ switch(inData.mType)
+ {
+ // This group results in a PRInt32...
+
+#define CASE__NUMBER_INT32(type_, member_) \
+ case nsIDataType :: type_ : \
+ outData->u.mInt32Value = inData.u. member_ ; \
+ outData->mType = nsIDataType::VTYPE_INT32; \
+ return NS_OK;
+
+ CASE__NUMBER_INT32(VTYPE_INT8, mInt8Value)
+ CASE__NUMBER_INT32(VTYPE_INT16, mInt16Value)
+ CASE__NUMBER_INT32(VTYPE_INT32, mInt32Value)
+ CASE__NUMBER_INT32(VTYPE_UINT8, mUint8Value)
+ CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
+ CASE__NUMBER_INT32(VTYPE_BOOL, mBoolValue)
+ CASE__NUMBER_INT32(VTYPE_CHAR, mCharValue)
+ CASE__NUMBER_INT32(VTYPE_WCHAR, mWCharValue)
+
+#undef CASE__NUMBER_INT32
+
+ // This group results in a PRUint32...
+
+ case nsIDataType::VTYPE_UINT32:
+ outData->u.mInt32Value = inData.u.mUint32Value;
+ outData->mType = nsIDataType::VTYPE_INT32;
+ return NS_OK;
+
+ // This group results in a double...
+
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT64:
+ // XXX Need boundary checking here.
+ // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
+ LL_L2D(outData->u.mDoubleValue, inData.u.mInt64Value);
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_FLOAT:
+ outData->u.mDoubleValue = inData.u.mFloatValue;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_DOUBLE:
+ outData->u.mDoubleValue = inData.u.mDoubleValue;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ rv = String2Double(inData.u.str.mStringValue, &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_ASTRING:
+ rv = AString2Double(*inData.u.mAStringValue, &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ rv = AUTF8String2Double(*inData.u.mUTF8StringValue,
+ &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ rv = ACString2Double(*inData.u.mCStringValue,
+ &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ rv = AString2Double(nsDependentString(inData.u.wstr.mWStringValue),
+ &outData->u.mDoubleValue);
+ if(NS_FAILED(rv))
+ return rv;
+ outData->mType = nsIDataType::VTYPE_DOUBLE;
+ return NS_OK;
+
+ // This group fails...
+
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ID:
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/***************************************************************************/
+// Array helpers...
+
+static void FreeArray(nsDiscriminatedUnion* data)
+{
+ NS_ASSERTION(data->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
+ NS_ASSERTION(data->u.array.mArrayValue, "bad array");
+ NS_ASSERTION(data->u.array.mArrayCount, "bad array count");
+
+#define CASE__FREE_ARRAY_PTR(type_, ctype_) \
+ case nsIDataType:: type_ : \
+ { \
+ ctype_ ** p = (ctype_ **) data->u.array.mArrayValue; \
+ for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--) \
+ if(*p) \
+ nsMemory::Free((char*)*p); \
+ break; \
+ }
+
+#define CASE__FREE_ARRAY_IFACE(type_, ctype_) \
+ case nsIDataType:: type_ : \
+ { \
+ ctype_ ** p = (ctype_ **) data->u.array.mArrayValue; \
+ for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--) \
+ if(*p) \
+ (*p)->Release(); \
+ break; \
+ }
+
+ switch(data->u.array.mArrayType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ case nsIDataType::VTYPE_UINT64:
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ case nsIDataType::VTYPE_BOOL:
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_WCHAR:
+ break;
+
+ // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
+ CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
+ CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
+ CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, PRUnichar)
+ CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
+ CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
+
+ // The rest are illegal.
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ default:
+ NS_ERROR("bad type in array!");
+ break;
+ }
+
+ // Free the array memory.
+ nsMemory::Free((char*)data->u.array.mArrayValue);
+
+#undef CASE__FREE_ARRAY_PTR
+#undef CASE__FREE_ARRAY_IFACE
+}
+
+static nsresult CloneArray(PRUint16 inType, const nsIID* inIID,
+ PRUint32 inCount, void* inValue,
+ PRUint16* outType, nsIID* outIID,
+ PRUint32* outCount, void** outValue)
+{
+ NS_ASSERTION(inCount, "bad param");
+ NS_ASSERTION(inValue, "bad param");
+ NS_ASSERTION(outType, "bad param");
+ NS_ASSERTION(outCount, "bad param");
+ NS_ASSERTION(outValue, "bad param");
+
+ PRUint32 allocatedValueCount = 0;
+ nsresult rv = NS_OK;
+ PRUint32 i;
+
+ // First we figure out the size of the elements for the new u.array.
+
+ size_t elementSize;
+ size_t allocSize;
+
+ switch(inType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ elementSize = sizeof(PRInt8);
+ break;
+ case nsIDataType::VTYPE_INT16:
+ elementSize = sizeof(PRInt16);
+ break;
+ case nsIDataType::VTYPE_INT32:
+ elementSize = sizeof(PRInt32);
+ break;
+ case nsIDataType::VTYPE_INT64:
+ elementSize = sizeof(PRInt64);
+ break;
+ case nsIDataType::VTYPE_UINT8:
+ elementSize = sizeof(PRUint8);
+ break;
+ case nsIDataType::VTYPE_UINT16:
+ elementSize = sizeof(PRUint16);
+ break;
+ case nsIDataType::VTYPE_UINT32:
+ elementSize = sizeof(PRUint32);
+ break;
+ case nsIDataType::VTYPE_UINT64:
+ elementSize = sizeof(PRUint64);
+ break;
+ case nsIDataType::VTYPE_FLOAT:
+ elementSize = sizeof(float);
+ break;
+ case nsIDataType::VTYPE_DOUBLE:
+ elementSize = sizeof(double);
+ break;
+ case nsIDataType::VTYPE_BOOL:
+ elementSize = sizeof(PRBool);
+ break;
+ case nsIDataType::VTYPE_CHAR:
+ elementSize = sizeof(char);
+ break;
+ case nsIDataType::VTYPE_WCHAR:
+ elementSize = sizeof(PRUnichar);
+ break;
+
+ // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
+ case nsIDataType::VTYPE_ID:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ elementSize = sizeof(void*);
+ break;
+
+ // The rest are illegal.
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ default:
+ NS_ERROR("bad type in array!");
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+
+
+ // Alloc the u.array.
+
+ allocSize = inCount * elementSize;
+ *outValue = nsMemory::Alloc(allocSize);
+ if(!*outValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Clone the elements.
+
+ switch(inType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ case nsIDataType::VTYPE_UINT64:
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ case nsIDataType::VTYPE_BOOL:
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_WCHAR:
+ memcpy(*outValue, inValue, allocSize);
+ break;
+
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ if(outIID)
+ *outIID = *inIID;
+ // fall through...
+ case nsIDataType::VTYPE_INTERFACE:
+ {
+ memcpy(*outValue, inValue, allocSize);
+
+ nsISupports** p = (nsISupports**) *outValue;
+ for(i = inCount; i > 0; p++, i--)
+ if(*p)
+ (*p)->AddRef();
+ break;
+ }
+
+ // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
+ case nsIDataType::VTYPE_ID:
+ {
+ nsID** inp = (nsID**) inValue;
+ nsID** outp = (nsID**) *outValue;
+ for(i = inCount; i > 0; i--)
+ {
+ nsID* idp = *(inp++);
+ if(idp)
+ {
+ if(nsnull == (*(outp++) = (nsID*)
+ nsMemory::Clone((char*)idp, sizeof(nsID))))
+ goto bad;
+ }
+ else
+ *(outp++) = nsnull;
+ allocatedValueCount++;
+ }
+ break;
+ }
+
+ case nsIDataType::VTYPE_CHAR_STR:
+ {
+ char** inp = (char**) inValue;
+ char** outp = (char**) *outValue;
+ for(i = inCount; i > 0; i--)
+ {
+ char* str = *(inp++);
+ if(str)
+ {
+ if(nsnull == (*(outp++) = (char*)
+ nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
+ goto bad;
+ }
+ else
+ *(outp++) = nsnull;
+ allocatedValueCount++;
+ }
+ break;
+ }
+
+ case nsIDataType::VTYPE_WCHAR_STR:
+ {
+ PRUnichar** inp = (PRUnichar**) inValue;
+ PRUnichar** outp = (PRUnichar**) *outValue;
+ for(i = inCount; i > 0; i--)
+ {
+ PRUnichar* str = *(inp++);
+ if(str)
+ {
+ if(nsnull == (*(outp++) = (PRUnichar*)
+ nsMemory::Clone(str,
+ (nsCRT::strlen(str)+1)*sizeof(PRUnichar))))
+ goto bad;
+ }
+ else
+ *(outp++) = nsnull;
+ allocatedValueCount++;
+ }
+ break;
+ }
+
+ // The rest are illegal.
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ default:
+ NS_ERROR("bad type in array!");
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+
+ *outType = inType;
+ *outCount = inCount;
+ return NS_OK;
+
+bad:
+ if(*outValue)
+ {
+ char** p = (char**) *outValue;
+ for(i = allocatedValueCount; i > 0; p++, i--)
+ if(*p)
+ nsMemory::Free(*p);
+ nsMemory::Free((char*)*outValue);
+ *outValue = nsnull;
+ }
+ return rv;
+}
+
+/***************************************************************************/
+
+#define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_) \
+ if(data_.mType == nsIDataType :: type_) { \
+ *retval_ = data_.u.member_; \
+ return NS_OK; \
+ }
+
+#define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
+/* static */ nsresult \
+nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data, \
+ Ctype_ *_retval) \
+{ \
+ TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval) \
+ nsDiscriminatedUnion tempData; \
+ nsVariant::Initialize(&tempData); \
+ nsresult rv = ToManageableNumber(data, &tempData); \
+ /* */ \
+ /* NOTE: rv may indicate a success code that we want to preserve */ \
+ /* For the final return. So all the return cases below should return */ \
+ /* this rv when indicating success. */ \
+ /* */ \
+ if(NS_FAILED(rv)) \
+ return rv; \
+ switch(tempData.mType) \
+ {
+
+#define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_) \
+ case nsIDataType::VTYPE_INT32: \
+ *_retval = ( Ctype_ ) tempData.u.mInt32Value; \
+ return rv;
+
+#define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
+ case nsIDataType::VTYPE_INT32: \
+ { \
+ PRInt32 value = tempData.u.mInt32Value; \
+ if(value < min_ || value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return rv; \
+ }
+
+#define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
+ case nsIDataType::VTYPE_UINT32: \
+ *_retval = ( Ctype_ ) tempData.u.mUint32Value; \
+ return rv;
+
+#define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
+ case nsIDataType::VTYPE_UINT32: \
+ { \
+ PRUint32 value = tempData.u.mUint32Value; \
+ if(value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return rv; \
+ }
+
+#define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
+ case nsIDataType::VTYPE_DOUBLE: \
+ *_retval = ( Ctype_ ) tempData.u.mDoubleValue; \
+ return rv;
+
+#define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_) \
+ case nsIDataType::VTYPE_DOUBLE: \
+ { \
+ double value = tempData.u.mDoubleValue; \
+ if(value < min_ || value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return rv; \
+ }
+
+#define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
+ case nsIDataType::VTYPE_DOUBLE: \
+ { \
+ double value = tempData.u.mDoubleValue; \
+ if(value < min_ || value > max_) \
+ return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
+ *_retval = ( Ctype_ ) value; \
+ return (0.0 == fmod(value,1.0)) ? \
+ rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
+ }
+
+#define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
+ CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
+ CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
+ CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
+
+#define NUMERIC_CONVERSION_METHOD_END \
+ default: \
+ NS_ERROR("bad type returned from ToManageableNumber"); \
+ return NS_ERROR_CANNOT_CONVERT_DATA; \
+ } \
+}
+
+#define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
+ NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
+ CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
+ NUMERIC_CONVERSION_METHOD_END
+
+/***************************************************************************/
+// These expand into full public methods...
+
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, PRUint8, Int8, (-127-1), 127)
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, PRInt16, Int16, (-32767-1), 32767)
+
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, PRInt32, Int32)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRInt32)
+ CASE__NUMERIC_CONVERSION_UINT32_MAX(PRInt32, 2147483647)
+ CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRInt32, (-2147483647-1), 2147483647)
+NUMERIC_CONVERSION_METHOD_END
+
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, PRUint8, Uint8, 0, 255)
+NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, PRUint16, Uint16, 0, 65535)
+
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, PRUint32, Uint32)
+ CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(PRUint32, 0, 2147483647)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUint32)
+ CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRUint32, 0, 4294967295U)
+NUMERIC_CONVERSION_METHOD_END
+
+// XXX toFloat convertions need to be fixed!
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
+NUMERIC_CONVERSION_METHOD_END
+
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
+NUMERIC_CONVERSION_METHOD_END
+
+// XXX toChar convertions need to be fixed!
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
+NUMERIC_CONVERSION_METHOD_END
+
+// XXX toWChar convertions need to be fixed!
+NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, PRUnichar, WChar)
+ CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRUnichar)
+ CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUnichar)
+ CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(PRUnichar)
+NUMERIC_CONVERSION_METHOD_END
+
+#undef NUMERIC_CONVERSION_METHOD_BEGIN
+#undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
+#undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
+#undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
+#undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
+#undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
+#undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
+#undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
+#undef CASES__NUMERIC_CONVERSION_NORMAL
+#undef NUMERIC_CONVERSION_METHOD_END
+#undef NUMERIC_CONVERSION_METHOD_NORMAL
+
+/***************************************************************************/
+
+// Just leverage a numeric converter for bool (but restrict the values).
+// XXX Is this really what we want to do?
+
+/* static */ nsresult
+nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval)
+{
+ TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
+
+ double val;
+ nsresult rv = nsVariant::ConvertToDouble(data, &val);
+ if(NS_FAILED(rv))
+ return rv;
+ *_retval = 0.0 != val;
+ return rv;
+}
+
+/***************************************************************************/
+
+/* static */ nsresult
+nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval)
+{
+ TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
+ TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
+
+ nsDiscriminatedUnion tempData;
+ nsVariant::Initialize(&tempData);
+ nsresult rv = ToManageableNumber(data, &tempData);
+ if(NS_FAILED(rv))
+ return rv;
+ switch(tempData.mType)
+ {
+ case nsIDataType::VTYPE_INT32:
+ LL_I2L(*_retval, tempData.u.mInt32Value);
+ return rv;
+ case nsIDataType::VTYPE_UINT32:
+ LL_UI2L(*_retval, tempData.u.mUint32Value);
+ return rv;
+ case nsIDataType::VTYPE_DOUBLE:
+ // XXX should check for data loss here!
+ LL_D2L(*_retval, tempData.u.mDoubleValue);
+ return rv;
+ default:
+ NS_ERROR("bad type returned from ToManageableNumber");
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval)
+{
+ return nsVariant::ConvertToInt64(data, (PRInt64 *)_retval);
+}
+
+/***************************************************************************/
+
+static PRBool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
+{
+ nsAutoString tempString;
+ nsAString* pString;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ return pid->Parse(data.u.str.mStringValue);
+ case nsIDataType::VTYPE_CSTRING:
+ return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
+ case nsIDataType::VTYPE_UTF8STRING:
+ return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ pString = data.u.mAStringValue;
+ break;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ tempString.Assign(data.u.wstr.mWStringValue);
+ pString = &tempString;
+ break;
+ default:
+ NS_ERROR("bad type in call to String2ID");
+ return PR_FALSE;
+ }
+
+ char* pChars = ToNewCString(*pString);
+ if(!pChars)
+ return PR_FALSE;
+ PRBool result = pid->Parse(pChars);
+ nsMemory::Free(pChars);
+ return result;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
+{
+ nsID id;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ID:
+ *_retval = data.u.mIDValue;
+ return NS_OK;
+ case nsIDataType::VTYPE_INTERFACE:
+ *_retval = NS_GET_IID(nsISupports);
+ return NS_OK;
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ *_retval = data.u.iface.mInterfaceID;
+ return NS_OK;
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ if(!String2ID(data, &id))
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ *_retval = id;
+ return NS_OK;
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/***************************************************************************/
+
+static nsresult ToString(const nsDiscriminatedUnion& data,
+ nsACString & outString)
+{
+ char* ptr;
+
+ switch(data.mType)
+ {
+ // all the stuff we don't handle...
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_UTF8STRING:
+ case nsIDataType::VTYPE_CSTRING:
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ case nsIDataType::VTYPE_WCHAR:
+ NS_ERROR("ToString being called for a string type - screwy logic!");
+ // fall through...
+
+ // XXX We might want stringified versions of these... ???
+
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ case nsIDataType::VTYPE_ARRAY:
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+
+ // nsID has its own text formater.
+
+ case nsIDataType::VTYPE_ID:
+ ptr = data.u.mIDValue.ToString();
+ if(!ptr)
+ return NS_ERROR_OUT_OF_MEMORY;
+ outString.Assign(ptr);
+ nsMemory::Free(ptr);
+ return NS_OK;
+
+ // the rest can be PR_smprintf'd and use common code.
+
+#define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
+ case nsIDataType :: type_ : \
+ ptr = PR_smprintf( format_ , (cast_) data.u. member_ ); \
+ break;
+
+ CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%lld", PRInt64, mInt64Value)
+
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
+ CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", PRInt64, mUint64Value)
+
+ CASE__SMPRINTF_NUMBER(VTYPE_FLOAT, "%f", float, mFloatValue)
+ CASE__SMPRINTF_NUMBER(VTYPE_DOUBLE, "%f", double, mDoubleValue)
+
+ // XXX Would we rather print "true" / "false" ?
+ CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
+
+ CASE__SMPRINTF_NUMBER(VTYPE_CHAR, "%c", char, mCharValue)
+
+#undef CASE__SMPRINTF_NUMBER
+ }
+
+ if(!ptr)
+ return NS_ERROR_OUT_OF_MEMORY;
+ outString.Assign(ptr);
+ PR_smprintf_free(ptr);
+ return NS_OK;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
+ nsAString & _retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ _retval.Assign(*data.u.mAStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ CopyASCIItoUCS2(*data.u.mCStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ _retval.Assign(data.u.wstr.mWStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ CopyASCIItoUCS2(nsDependentCString(data.u.str.mStringValue,
+ data.u.str.mStringLength),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR:
+ _retval.Assign(data.u.mWCharValue);
+ return NS_OK;
+ default:
+ {
+ nsCAutoString tempCString;
+ nsresult rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ CopyASCIItoUTF16(tempCString, _retval);
+ return NS_OK;
+ }
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
+ nsACString & _retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ CopyUCS2toASCII(*data.u.mAStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ _retval.Assign(*data.u.mCStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ // XXX This is an extra copy that should be avoided
+ // once Jag lands support for UTF8String and associated
+ // conversion methods.
+ CopyUCS2toASCII(NS_ConvertUTF8toUCS2(*data.u.mUTF8StringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ _retval.Assign(*data.u.str.mStringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ CopyUCS2toASCII(nsDependentString(data.u.wstr.mWStringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
+ return NS_OK;
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ CopyUCS2toASCII(nsDependentString(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength), _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR:
+ {
+ const PRUnichar* str = &data.u.mWCharValue;
+ CopyUCS2toASCII(Substring(str, str + 1), _retval);
+ return NS_OK;
+ }
+ default:
+ return ToString(data, _retval);
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
+ nsAUTF8String & _retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_CSTRING:
+ // XXX Extra copy, can be removed if we're sure CSTRING can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_UTF8STRING:
+ _retval.Assign(*data.u.mUTF8StringValue);
+ return NS_OK;
+ case nsIDataType::VTYPE_CHAR_STR:
+ // XXX Extra copy, can be removed if we're sure CHAR_STR can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ // XXX Extra copy, can be removed if we're sure CHAR_STR can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
+ nsDependentCString(data.u.str.mStringValue,
+ data.u.str.mStringLength)), _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength),
+ _retval);
+ return NS_OK;
+ case nsIDataType::VTYPE_WCHAR:
+ {
+ const PRUnichar* str = &data.u.mWCharValue;
+ CopyUTF16toUTF8(Substring(str, str + 1), _retval);
+ return NS_OK;
+ }
+ default:
+ {
+ nsCAutoString tempCString;
+ nsresult rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ // XXX Extra copy, can be removed if we're sure tempCString can
+ // only contain ASCII.
+ CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
+ return NS_OK;
+ }
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
+{
+ PRUint32 ignored;
+ return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
+}
+
+/* static */ nsresult
+nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval)
+{
+ PRUint32 ignored;
+ return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
+}
+
+/* static */ nsresult
+nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
+ PRUint32 *size, char **str)
+{
+ nsAutoString tempString;
+ nsCAutoString tempCString;
+ nsresult rv;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ *size = data.u.mAStringValue->Length();
+ *str = ToNewCString(*data.u.mAStringValue);
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ *size = data.u.mCStringValue->Length();
+ *str = ToNewCString(*data.u.mCStringValue);
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ {
+ // XXX This is doing 1 extra copy. Need to fix this
+ // when Jag lands UTF8String
+ // we want:
+ // *size = *data.mUTF8StringValue->Length();
+ // *str = ToNewCString(*data.mUTF8StringValue);
+ // But this will have to do for now.
+ NS_ConvertUTF8toUCS2 tempString(*data.u.mUTF8StringValue);
+ *size = tempString.Length();
+ *str = ToNewCString(tempString);
+ break;
+ }
+ case nsIDataType::VTYPE_CHAR_STR:
+ {
+ nsDependentCString cString(data.u.str.mStringValue);
+ *size = cString.Length();
+ *str = ToNewCString(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR_STR:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue);
+ *size = string.Length();
+ *str = ToNewCString(string);
+ break;
+ }
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ {
+ nsDependentCString cString(data.u.str.mStringValue,
+ data.u.str.mStringLength);
+ *size = cString.Length();
+ *str = ToNewCString(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength);
+ *size = string.Length();
+ *str = ToNewCString(string);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ tempString.Assign(data.u.mWCharValue);
+ *size = tempString.Length();
+ *str = ToNewCString(tempString);
+ break;
+ default:
+ rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ *size = tempCString.Length();
+ *str = ToNewCString(tempCString);
+ break;
+ }
+
+ return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+/* static */ nsresult
+nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
+ PRUint32 *size, PRUnichar **str)
+{
+ nsAutoString tempString;
+ nsCAutoString tempCString;
+ nsresult rv;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ *size = data.u.mAStringValue->Length();
+ *str = ToNewUnicode(*data.u.mAStringValue);
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ *size = data.u.mCStringValue->Length();
+ *str = ToNewUnicode(*data.u.mCStringValue);
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ {
+ *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
+ break;
+ }
+ case nsIDataType::VTYPE_CHAR_STR:
+ {
+ nsDependentCString cString(data.u.str.mStringValue);
+ *size = cString.Length();
+ *str = ToNewUnicode(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR_STR:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue);
+ *size = string.Length();
+ *str = ToNewUnicode(string);
+ break;
+ }
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ {
+ nsDependentCString cString(data.u.str.mStringValue,
+ data.u.str.mStringLength);
+ *size = cString.Length();
+ *str = ToNewUnicode(cString);
+ break;
+ }
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ {
+ nsDependentString string(data.u.wstr.mWStringValue,
+ data.u.wstr.mWStringLength);
+ *size = string.Length();
+ *str = ToNewUnicode(string);
+ break;
+ }
+ case nsIDataType::VTYPE_WCHAR:
+ tempString.Assign(data.u.mWCharValue);
+ *size = tempString.Length();
+ *str = ToNewUnicode(tempString);
+ break;
+ default:
+ rv = ToString(data, tempCString);
+ if(NS_FAILED(rv))
+ return rv;
+ *size = tempCString.Length();
+ *str = ToNewUnicode(tempCString);
+ break;
+ }
+
+ return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
+ nsISupports **_retval)
+{
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ if (data.u.iface.mInterfaceValue) {
+ return data.u.iface.mInterfaceValue->
+ QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
+ } else {
+ *_retval = nsnull;
+ return NS_OK;
+ }
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+}
+
+/* static */ nsresult
+nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
+ void * *iface)
+{
+ const nsIID* piid;
+
+ switch(data.mType)
+ {
+ case nsIDataType::VTYPE_INTERFACE:
+ piid = &NS_GET_IID(nsISupports);
+ break;
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ piid = &data.u.iface.mInterfaceID;
+ break;
+ default:
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+ }
+
+ *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
+ if(!*iid)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (data.u.iface.mInterfaceValue) {
+ return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
+ }
+
+ *iface = nsnull;
+ return NS_OK;
+}
+
+/* static */ nsresult
+nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type,
+ nsIID* iid, PRUint32 *count, void * *ptr)
+{
+ // XXX perhaps we'd like to add support for converting each of the various
+ // types into an array containing one element of that type. We can leverage
+ // CloneArray to do this if we want to support this.
+
+ if(data.mType == nsIDataType::VTYPE_ARRAY)
+ return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
+ data.u.array.mArrayCount, data.u.array.mArrayValue,
+ type, iid, count, ptr);
+ return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+/***************************************************************************/
+// static setter functions...
+
+#define DATA_SETTER_PROLOGUE(data_) \
+ nsVariant::Cleanup(data_);
+
+#define DATA_SETTER_EPILOGUE(data_, type_) \
+ data_->mType = nsIDataType :: type_; \
+ return NS_OK;
+
+#define DATA_SETTER(data_, type_, member_, value_) \
+ DATA_SETTER_PROLOGUE(data_) \
+ data_->u.member_ = value_; \
+ DATA_SETTER_EPILOGUE(data_, type_)
+
+#define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_) \
+ DATA_SETTER_PROLOGUE(data_) \
+ data_->u.member_ = cast_ value_; \
+ DATA_SETTER_EPILOGUE(data_, type_)
+
+
+/********************************************/
+
+#define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
+ { \
+
+#define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
+ rv = aValue->GetAs##name_ (&(data->u. member_ ));
+
+#define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
+ rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
+
+#define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
+ if(NS_SUCCEEDED(rv)) \
+ { \
+ data->mType = nsIDataType :: type_ ; \
+ } \
+ break; \
+ }
+
+#define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
+ case nsIDataType :: type_ : \
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
+ CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
+
+#define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
+ case nsIDataType :: type_ : \
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
+ CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
+
+
+/* static */ nsresult
+nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
+{
+ PRUint16 type;
+ nsresult rv;
+
+ nsVariant::Cleanup(data);
+
+ rv = aValue->GetDataType(&type);
+ if(NS_FAILED(rv))
+ return rv;
+
+ switch(type)
+ {
+ CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (PRUint8*), mInt8Value,
+ Int8)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16, mInt16Value, Int16)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32, mInt32Value, Int32)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8, mUint8Value, Uint8)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT, mFloatValue, Float)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL , mBoolValue, Bool)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR, mCharValue, Char)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR, mWCharValue, WChar)
+ CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID, mIDValue, ID)
+
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
+ data->u.mAStringValue = new nsString();
+ if(!data->u.mAStringValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = aValue->GetAsAString(*data->u.mAStringValue);
+ if(NS_FAILED(rv))
+ delete data->u.mAStringValue;
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
+
+ case nsIDataType::VTYPE_CSTRING:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
+ data->u.mCStringValue = new nsCString();
+ if(!data->u.mCStringValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = aValue->GetAsACString(*data->u.mCStringValue);
+ if(NS_FAILED(rv))
+ delete data->u.mCStringValue;
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
+
+ case nsIDataType::VTYPE_UTF8STRING:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
+ data->u.mUTF8StringValue = new nsUTF8String();
+ if(!data->u.mUTF8StringValue)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
+ if(NS_FAILED(rv))
+ delete data->u.mUTF8StringValue;
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
+
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
+ rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
+ &data->u.str.mStringValue);
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
+
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
+ // XXX This iid handling is ugly!
+ nsIID* iid;
+ rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
+ if(NS_SUCCEEDED(rv))
+ {
+ data->u.iface.mInterfaceID = *iid;
+ nsMemory::Free((char*)iid);
+ }
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
+
+ case nsIDataType::VTYPE_ARRAY:
+ CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
+ rv = aValue->GetAsArray(&data->u.array.mArrayType,
+ &data->u.array.mArrayInterfaceID,
+ &data->u.array.mArrayCount,
+ &data->u.array.mArrayValue);
+ CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
+
+ case nsIDataType::VTYPE_VOID:
+ rv = nsVariant::SetToVoid(data);
+ break;
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ rv = nsVariant::SetToEmptyArray(data);
+ break;
+ case nsIDataType::VTYPE_EMPTY:
+ rv = nsVariant::SetToEmpty(data);
+ break;
+ default:
+ NS_ERROR("bad type in variant!");
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ return rv;
+}
+
+/* static */ nsresult
+nsVariant::SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue)
+{
+ DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (PRUint8), aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue)
+{
+ DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue)
+{
+ DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue)
+{
+ DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue)
+{
+ DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
+{
+ DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
+{
+ DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromBool(nsDiscriminatedUnion* data, PRBool aValue)
+{
+ DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
+{
+ DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue)
+{
+ DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
+{
+ DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
+}
+/* static */ nsresult
+nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!(data->u.mAStringValue = new nsString(aValue)))
+ return NS_ERROR_OUT_OF_MEMORY;
+ DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
+}
+
+/* static */ nsresult
+nsVariant::SetFromACString(nsDiscriminatedUnion* data,
+ const nsACString & aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!(data->u.mCStringValue = new nsCString(aValue)))
+ return NS_ERROR_OUT_OF_MEMORY;
+ DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
+}
+
+/* static */ nsresult
+nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
+ const nsAUTF8String & aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
+ return NS_ERROR_OUT_OF_MEMORY;
+ DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
+}
+
+/* static */ nsresult
+nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ return SetFromStringWithSize(data, strlen(aValue), aValue);
+}
+/* static */ nsresult
+nsVariant::SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ return SetFromWStringWithSize(data, nsCRT::strlen(aValue), aValue);
+}
+/* static */ nsresult
+nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
+{
+ return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
+}
+/* static */ nsresult
+nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
+ nsISupports *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ NS_IF_ADDREF(aValue);
+ data->u.iface.mInterfaceValue = aValue;
+ data->u.iface.mInterfaceID = iid;
+ DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
+}
+/* static */ nsresult
+nsVariant::SetFromArray(nsDiscriminatedUnion* data, PRUint16 type,
+ const nsIID* iid, PRUint32 count, void * aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue || !count)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv = CloneArray(type, iid, count, aValue,
+ &data->u.array.mArrayType,
+ &data->u.array.mArrayInterfaceID,
+ &data->u.array.mArrayCount,
+ &data->u.array.mArrayValue);
+ if(NS_FAILED(rv))
+ return rv;
+ DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
+}
+/* static */ nsresult
+nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ if(!(data->u.str.mStringValue =
+ (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
+ return NS_ERROR_OUT_OF_MEMORY;
+ data->u.str.mStringLength = size;
+ DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
+}
+/* static */ nsresult
+nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue)
+{
+ DATA_SETTER_PROLOGUE(data);
+ if(!aValue)
+ return NS_ERROR_NULL_POINTER;
+ if(!(data->u.wstr.mWStringValue =
+ (PRUnichar*) nsMemory::Clone(aValue, (size+1)*sizeof(PRUnichar))))
+ return NS_ERROR_OUT_OF_MEMORY;
+ data->u.wstr.mWStringLength = size;
+ DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
+}
+/* static */ nsresult
+nsVariant::SetToVoid(nsDiscriminatedUnion* data)
+{
+ DATA_SETTER_PROLOGUE(data);
+ DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
+}
+/* static */ nsresult
+nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
+{
+ DATA_SETTER_PROLOGUE(data);
+ DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
+}
+/* static */ nsresult
+nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
+{
+ DATA_SETTER_PROLOGUE(data);
+ DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
+}
+
+/***************************************************************************/
+
+/* static */ nsresult
+nsVariant::Initialize(nsDiscriminatedUnion* data)
+{
+ data->mType = nsIDataType::VTYPE_EMPTY;
+ return NS_OK;
+}
+
+/* static */ nsresult
+nsVariant::Cleanup(nsDiscriminatedUnion* data)
+{
+ switch(data->mType)
+ {
+ case nsIDataType::VTYPE_INT8:
+ case nsIDataType::VTYPE_INT16:
+ case nsIDataType::VTYPE_INT32:
+ case nsIDataType::VTYPE_INT64:
+ case nsIDataType::VTYPE_UINT8:
+ case nsIDataType::VTYPE_UINT16:
+ case nsIDataType::VTYPE_UINT32:
+ case nsIDataType::VTYPE_UINT64:
+ case nsIDataType::VTYPE_FLOAT:
+ case nsIDataType::VTYPE_DOUBLE:
+ case nsIDataType::VTYPE_BOOL:
+ case nsIDataType::VTYPE_CHAR:
+ case nsIDataType::VTYPE_WCHAR:
+ case nsIDataType::VTYPE_VOID:
+ case nsIDataType::VTYPE_ID:
+ break;
+ case nsIDataType::VTYPE_ASTRING:
+ case nsIDataType::VTYPE_DOMSTRING:
+ delete data->u.mAStringValue;
+ break;
+ case nsIDataType::VTYPE_CSTRING:
+ delete data->u.mCStringValue;
+ break;
+ case nsIDataType::VTYPE_UTF8STRING:
+ delete data->u.mUTF8StringValue;
+ break;
+ case nsIDataType::VTYPE_CHAR_STR:
+ case nsIDataType::VTYPE_STRING_SIZE_IS:
+ nsMemory::Free((char*)data->u.str.mStringValue);
+ break;
+ case nsIDataType::VTYPE_WCHAR_STR:
+ case nsIDataType::VTYPE_WSTRING_SIZE_IS:
+ nsMemory::Free((char*)data->u.wstr.mWStringValue);
+ break;
+ case nsIDataType::VTYPE_INTERFACE:
+ case nsIDataType::VTYPE_INTERFACE_IS:
+ NS_IF_RELEASE(data->u.iface.mInterfaceValue);
+ break;
+ case nsIDataType::VTYPE_ARRAY:
+ FreeArray(data);
+ break;
+ case nsIDataType::VTYPE_EMPTY_ARRAY:
+ case nsIDataType::VTYPE_EMPTY:
+ break;
+ default:
+ NS_ERROR("bad type in variant!");
+ break;
+ }
+
+ data->mType = nsIDataType::VTYPE_EMPTY;
+ return NS_OK;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+// members...
+
+NS_IMPL_ISUPPORTS2(nsVariant, nsIVariant, nsIWritableVariant)
+
+nsVariant::nsVariant()
+ : mWritable(PR_TRUE)
+{
+ nsVariant::Initialize(&mData);
+
+#ifdef DEBUG
+ {
+ // Assert that the nsIDataType consts match the values #defined in
+ // xpt_struct.h. Bad things happen somewhere if they don't.
+ struct THE_TYPES {PRUint16 a; PRUint16 b;};
+ static const THE_TYPES array[] = {
+ {nsIDataType::VTYPE_INT8 , TD_INT8 },
+ {nsIDataType::VTYPE_INT16 , TD_INT16 },
+ {nsIDataType::VTYPE_INT32 , TD_INT32 },
+ {nsIDataType::VTYPE_INT64 , TD_INT64 },
+ {nsIDataType::VTYPE_UINT8 , TD_UINT8 },
+ {nsIDataType::VTYPE_UINT16 , TD_UINT16 },
+ {nsIDataType::VTYPE_UINT32 , TD_UINT32 },
+ {nsIDataType::VTYPE_UINT64 , TD_UINT64 },
+ {nsIDataType::VTYPE_FLOAT , TD_FLOAT },
+ {nsIDataType::VTYPE_DOUBLE , TD_DOUBLE },
+ {nsIDataType::VTYPE_BOOL , TD_BOOL },
+ {nsIDataType::VTYPE_CHAR , TD_CHAR },
+ {nsIDataType::VTYPE_WCHAR , TD_WCHAR },
+ {nsIDataType::VTYPE_VOID , TD_VOID },
+ {nsIDataType::VTYPE_ID , TD_PNSIID },
+ {nsIDataType::VTYPE_DOMSTRING , TD_DOMSTRING },
+ {nsIDataType::VTYPE_CHAR_STR , TD_PSTRING },
+ {nsIDataType::VTYPE_WCHAR_STR , TD_PWSTRING },
+ {nsIDataType::VTYPE_INTERFACE , TD_INTERFACE_TYPE },
+ {nsIDataType::VTYPE_INTERFACE_IS , TD_INTERFACE_IS_TYPE},
+ {nsIDataType::VTYPE_ARRAY , TD_ARRAY },
+ {nsIDataType::VTYPE_STRING_SIZE_IS , TD_PSTRING_SIZE_IS },
+ {nsIDataType::VTYPE_WSTRING_SIZE_IS , TD_PWSTRING_SIZE_IS },
+ {nsIDataType::VTYPE_UTF8STRING , TD_UTF8STRING },
+ {nsIDataType::VTYPE_CSTRING , TD_CSTRING },
+ {nsIDataType::VTYPE_ASTRING , TD_ASTRING }
+ };
+ static const int length = sizeof(array)/sizeof(array[0]);
+ static PRBool inited = PR_FALSE;
+ if(!inited)
+ {
+ for(int i = 0; i < length; i++)
+ NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
+ inited = PR_TRUE;
+ }
+ }
+#endif
+}
+
+nsVariant::~nsVariant()
+{
+ nsVariant::Cleanup(&mData);
+}
+
+// For all the data getters we just forward to the static (and sharable)
+// 'ConvertTo' functions.
+
+/* readonly attribute PRUint16 dataType; */
+NS_IMETHODIMP nsVariant::GetDataType(PRUint16 *aDataType)
+{
+ *aDataType = mData.mType;
+ return NS_OK;
+}
+
+/* PRUint8 getAsInt8 (); */
+NS_IMETHODIMP nsVariant::GetAsInt8(PRUint8 *_retval)
+{
+ return nsVariant::ConvertToInt8(mData, _retval);
+}
+
+/* PRInt16 getAsInt16 (); */
+NS_IMETHODIMP nsVariant::GetAsInt16(PRInt16 *_retval)
+{
+ return nsVariant::ConvertToInt16(mData, _retval);
+}
+
+/* PRInt32 getAsInt32 (); */
+NS_IMETHODIMP nsVariant::GetAsInt32(PRInt32 *_retval)
+{
+ return nsVariant::ConvertToInt32(mData, _retval);
+}
+
+/* PRInt64 getAsInt64 (); */
+NS_IMETHODIMP nsVariant::GetAsInt64(PRInt64 *_retval)
+{
+ return nsVariant::ConvertToInt64(mData, _retval);
+}
+
+/* PRUint8 getAsUint8 (); */
+NS_IMETHODIMP nsVariant::GetAsUint8(PRUint8 *_retval)
+{
+ return nsVariant::ConvertToUint8(mData, _retval);
+}
+
+/* PRUint16 getAsUint16 (); */
+NS_IMETHODIMP nsVariant::GetAsUint16(PRUint16 *_retval)
+{
+ return nsVariant::ConvertToUint16(mData, _retval);
+}
+
+/* PRUint32 getAsUint32 (); */
+NS_IMETHODIMP nsVariant::GetAsUint32(PRUint32 *_retval)
+{
+ return nsVariant::ConvertToUint32(mData, _retval);
+}
+
+/* PRUint64 getAsUint64 (); */
+NS_IMETHODIMP nsVariant::GetAsUint64(PRUint64 *_retval)
+{
+ return nsVariant::ConvertToUint64(mData, _retval);
+}
+
+/* float getAsFloat (); */
+NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
+{
+ return nsVariant::ConvertToFloat(mData, _retval);
+}
+
+/* double getAsDouble (); */
+NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
+{
+ return nsVariant::ConvertToDouble(mData, _retval);
+}
+
+/* PRBool getAsBool (); */
+NS_IMETHODIMP nsVariant::GetAsBool(PRBool *_retval)
+{
+ return nsVariant::ConvertToBool(mData, _retval);
+}
+
+/* char getAsChar (); */
+NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
+{
+ return nsVariant::ConvertToChar(mData, _retval);
+}
+
+/* wchar getAsWChar (); */
+NS_IMETHODIMP nsVariant::GetAsWChar(PRUnichar *_retval)
+{
+ return nsVariant::ConvertToWChar(mData, _retval);
+}
+
+/* [notxpcom] nsresult getAsID (out nsID retval); */
+NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
+{
+ return nsVariant::ConvertToID(mData, retval);
+}
+
+/* AString getAsAString (); */
+NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
+{
+ return nsVariant::ConvertToAString(mData, _retval);
+}
+
+/* DOMString getAsDOMString (); */
+NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
+{
+ // A DOMString maps to an AString internally, so we can re-use
+ // ConvertToAString here.
+ return nsVariant::ConvertToAString(mData, _retval);
+}
+
+/* ACString getAsACString (); */
+NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
+{
+ return nsVariant::ConvertToACString(mData, _retval);
+}
+
+/* AUTF8String getAsAUTF8String (); */
+NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
+{
+ return nsVariant::ConvertToAUTF8String(mData, _retval);
+}
+
+/* string getAsString (); */
+NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
+{
+ return nsVariant::ConvertToString(mData, _retval);
+}
+
+/* wstring getAsWString (); */
+NS_IMETHODIMP nsVariant::GetAsWString(PRUnichar **_retval)
+{
+ return nsVariant::ConvertToWString(mData, _retval);
+}
+
+/* nsISupports getAsISupports (); */
+NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
+{
+ return nsVariant::ConvertToISupports(mData, _retval);
+}
+
+/* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
+NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
+{
+ return nsVariant::ConvertToInterface(mData, iid, iface);
+}
+
+/* [notxpcom] nsresult getAsArray (out PRUint16 type, out nsIID iid, out PRUint32 count, out voidPtr ptr); */
+NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(PRUint16 *type, nsIID *iid, PRUint32 *count, void * *ptr)
+{
+ return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
+}
+
+/* void getAsStringWithSize (out PRUint32 size, [size_is (size), retval] out string str); */
+NS_IMETHODIMP nsVariant::GetAsStringWithSize(PRUint32 *size, char **str)
+{
+ return nsVariant::ConvertToStringWithSize(mData, size, str);
+}
+
+/* void getAsWStringWithSize (out PRUint32 size, [size_is (size), retval] out wstring str); */
+NS_IMETHODIMP nsVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
+{
+ return nsVariant::ConvertToWStringWithSize(mData, size, str);
+}
+
+/***************************************************************************/
+
+/* attribute PRBool writable; */
+NS_IMETHODIMP nsVariant::GetWritable(PRBool *aWritable)
+{
+ *aWritable = mWritable;
+ return NS_OK;
+}
+NS_IMETHODIMP nsVariant::SetWritable(PRBool aWritable)
+{
+ if(!mWritable && aWritable)
+ return NS_ERROR_FAILURE;
+ mWritable = aWritable;
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+// For all the data setters we just forward to the static (and sharable)
+// 'SetFrom' functions.
+
+/* void setAsInt8 (in PRUint8 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt8(PRUint8 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt8(&mData, aValue);
+}
+
+/* void setAsInt16 (in PRInt16 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt16(PRInt16 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt16(&mData, aValue);
+}
+
+/* void setAsInt32 (in PRInt32 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt32(PRInt32 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt32(&mData, aValue);
+}
+
+/* void setAsInt64 (in PRInt64 aValue); */
+NS_IMETHODIMP nsVariant::SetAsInt64(PRInt64 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInt64(&mData, aValue);
+}
+
+/* void setAsUint8 (in PRUint8 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint8(PRUint8 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint8(&mData, aValue);
+}
+
+/* void setAsUint16 (in PRUint16 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint16(PRUint16 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint16(&mData, aValue);
+}
+
+/* void setAsUint32 (in PRUint32 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint32(PRUint32 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint32(&mData, aValue);
+}
+
+/* void setAsUint64 (in PRUint64 aValue); */
+NS_IMETHODIMP nsVariant::SetAsUint64(PRUint64 aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromUint64(&mData, aValue);
+}
+
+/* void setAsFloat (in float aValue); */
+NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromFloat(&mData, aValue);
+}
+
+/* void setAsDouble (in double aValue); */
+NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromDouble(&mData, aValue);
+}
+
+/* void setAsBool (in PRBool aValue); */
+NS_IMETHODIMP nsVariant::SetAsBool(PRBool aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromBool(&mData, aValue);
+}
+
+/* void setAsChar (in char aValue); */
+NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromChar(&mData, aValue);
+}
+
+/* void setAsWChar (in wchar aValue); */
+NS_IMETHODIMP nsVariant::SetAsWChar(PRUnichar aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromWChar(&mData, aValue);
+}
+
+/* void setAsID (in nsIDRef aValue); */
+NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromID(&mData, aValue);
+}
+
+/* void setAsAString (in AString aValue); */
+NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromAString(&mData, aValue);
+}
+
+/* void setAsDOMString (in DOMString aValue); */
+NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+
+ // A DOMString maps to an AString internally, so we can re-use
+ // SetFromAString here.
+ return nsVariant::SetFromAString(&mData, aValue);
+}
+
+/* void setAsACString (in ACString aValue); */
+NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromACString(&mData, aValue);
+}
+
+/* void setAsAUTF8String (in AUTF8String aValue); */
+NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromAUTF8String(&mData, aValue);
+}
+
+/* void setAsString (in string aValue); */
+NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromString(&mData, aValue);
+}
+
+/* void setAsWString (in wstring aValue); */
+NS_IMETHODIMP nsVariant::SetAsWString(const PRUnichar *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromWString(&mData, aValue);
+}
+
+/* void setAsISupports (in nsISupports aValue); */
+NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromISupports(&mData, aValue);
+}
+
+/* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
+NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
+}
+
+/* [noscript] void setAsArray (in PRUint16 type, in nsIIDPtr iid, in PRUint32 count, in voidPtr ptr); */
+NS_IMETHODIMP nsVariant::SetAsArray(PRUint16 type, const nsIID * iid, PRUint32 count, void * ptr)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
+}
+
+/* void setAsStringWithSize (in PRUint32 size, [size_is (size)] in string str); */
+NS_IMETHODIMP nsVariant::SetAsStringWithSize(PRUint32 size, const char *str)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromStringWithSize(&mData, size, str);
+}
+
+/* void setAsWStringWithSize (in PRUint32 size, [size_is (size)] in wstring str); */
+NS_IMETHODIMP nsVariant::SetAsWStringWithSize(PRUint32 size, const PRUnichar *str)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromWStringWithSize(&mData, size, str);
+}
+
+/* void setAsVoid (); */
+NS_IMETHODIMP nsVariant::SetAsVoid()
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetToVoid(&mData);
+}
+
+/* void setAsEmpty (); */
+NS_IMETHODIMP nsVariant::SetAsEmpty()
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetToEmpty(&mData);
+}
+
+/* void setAsEmptyArray (); */
+NS_IMETHODIMP nsVariant::SetAsEmptyArray()
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetToEmptyArray(&mData);
+}
+
+/* void setFromVariant (in nsIVariant aValue); */
+NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
+{
+ if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
+ return nsVariant::SetFromVariant(&mData, aValue);
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVariant.h b/src/libs/xpcom18a4/xpcom/ds/nsVariant.h
new file mode 100644
index 00000000..393e745f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVariant.h
@@ -0,0 +1,203 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The long avoided variant support for xpcom. */
+
+#include "nsIVariant.h"
+#include "nsStringFwd.h"
+#include "xpt_struct.h"
+
+/**
+ * Map the nsAUTF8String, nsUTF8String classes to the nsACString and
+ * nsCString classes respectively for now. These defines need to be removed
+ * once Jag lands his nsUTF8String implementation.
+ */
+#define nsAUTF8String nsACString
+#define nsUTF8String nsCString
+#define PromiseFlatUTF8String PromiseFlatCString
+
+/**
+ * nsDiscriminatedUnion is a type that nsIVariant implementors *may* use
+ * to hold underlying data. It has no methods. So, its use requires no linkage
+ * to the xpcom module.
+ */
+
+struct nsDiscriminatedUnion
+{
+ union {
+ PRInt8 mInt8Value;
+ PRInt16 mInt16Value;
+ PRInt32 mInt32Value;
+ PRInt64 mInt64Value;
+ PRUint8 mUint8Value;
+ PRUint16 mUint16Value;
+ PRUint32 mUint32Value;
+ PRUint64 mUint64Value;
+ float mFloatValue;
+ double mDoubleValue;
+ PRBool mBoolValue;
+ char mCharValue;
+ PRUnichar mWCharValue;
+ nsIID mIDValue;
+ nsAString* mAStringValue;
+ nsAUTF8String* mUTF8StringValue;
+ nsACString* mCStringValue;
+ struct {
+ nsISupports* mInterfaceValue;
+ nsIID mInterfaceID;
+ } iface;
+ struct {
+ nsIID mArrayInterfaceID;
+ void* mArrayValue;
+ PRUint32 mArrayCount;
+ PRUint16 mArrayType;
+ } array;
+ struct {
+ char* mStringValue;
+ PRUint32 mStringLength;
+ } str;
+ struct {
+ PRUnichar* mWStringValue;
+ PRUint32 mWStringLength;
+ } wstr;
+ } u;
+ PRUint16 mType;
+};
+
+/**
+ * nsVariant implements the generic variant support. The xpcom module registers
+ * a factory (see NS_VARIANT_CONTRACTID in nsIVariant.idl) that will create
+ * these objects. They are created 'empty' and 'writable'.
+ *
+ * nsIVariant users won't usually need to see this class.
+ *
+ * This class also has static helper methods that nsIVariant *implementors* can
+ * use to help them do all the 'standard' nsIVariant data conversions.
+ */
+
+class NS_COM nsVariant : public nsIWritableVariant
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIVARIANT
+ NS_DECL_NSIWRITABLEVARIANT
+
+ nsVariant();
+
+ static nsresult Initialize(nsDiscriminatedUnion* data);
+ static nsresult Cleanup(nsDiscriminatedUnion* data);
+
+ static nsresult ConvertToInt8(const nsDiscriminatedUnion& data, PRUint8 *_retval);
+ static nsresult ConvertToInt16(const nsDiscriminatedUnion& data, PRInt16 *_retval);
+ static nsresult ConvertToInt32(const nsDiscriminatedUnion& data, PRInt32 *_retval);
+ static nsresult ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval);
+ static nsresult ConvertToUint8(const nsDiscriminatedUnion& data, PRUint8 *_retval);
+ static nsresult ConvertToUint16(const nsDiscriminatedUnion& data, PRUint16 *_retval);
+ static nsresult ConvertToUint32(const nsDiscriminatedUnion& data, PRUint32 *_retval);
+ static nsresult ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval);
+ static nsresult ConvertToFloat(const nsDiscriminatedUnion& data, float *_retval);
+ static nsresult ConvertToDouble(const nsDiscriminatedUnion& data, double *_retval);
+ static nsresult ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval);
+ static nsresult ConvertToChar(const nsDiscriminatedUnion& data, char *_retval);
+ static nsresult ConvertToWChar(const nsDiscriminatedUnion& data, PRUnichar *_retval);
+ static nsresult ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval);
+ static nsresult ConvertToAString(const nsDiscriminatedUnion& data, nsAString & _retval);
+ static nsresult ConvertToAUTF8String(const nsDiscriminatedUnion& data, nsAUTF8String & _retval);
+ static nsresult ConvertToACString(const nsDiscriminatedUnion& data, nsACString & _retval);
+ static nsresult ConvertToString(const nsDiscriminatedUnion& data, char **_retval);
+ static nsresult ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval);
+ static nsresult ConvertToISupports(const nsDiscriminatedUnion& data, nsISupports **_retval);
+ static nsresult ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid, void * *iface);
+ static nsresult ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type, nsIID* iid, PRUint32 *count, void * *ptr);
+ static nsresult ConvertToStringWithSize(const nsDiscriminatedUnion& data, PRUint32 *size, char **str);
+ static nsresult ConvertToWStringWithSize(const nsDiscriminatedUnion& data, PRUint32 *size, PRUnichar **str);
+
+ static nsresult SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue);
+
+ static nsresult SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue);
+ static nsresult SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue);
+ static nsresult SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue);
+ static nsresult SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue);
+ static nsresult SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue);
+ static nsresult SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue);
+ static nsresult SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue);
+ static nsresult SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue);
+ static nsresult SetFromFloat(nsDiscriminatedUnion* data, float aValue);
+ static nsresult SetFromDouble(nsDiscriminatedUnion* data, double aValue);
+ static nsresult SetFromBool(nsDiscriminatedUnion* data, PRBool aValue);
+ static nsresult SetFromChar(nsDiscriminatedUnion* data, char aValue);
+ static nsresult SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue);
+ static nsresult SetFromID(nsDiscriminatedUnion* data, const nsID & aValue);
+ static nsresult SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue);
+ static nsresult SetFromAUTF8String(nsDiscriminatedUnion* data, const nsAUTF8String & aValue);
+ static nsresult SetFromACString(nsDiscriminatedUnion* data, const nsACString & aValue);
+ static nsresult SetFromString(nsDiscriminatedUnion* data, const char *aValue);
+ static nsresult SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue);
+ static nsresult SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue);
+ static nsresult SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid, nsISupports *aValue);
+ static nsresult SetFromArray(nsDiscriminatedUnion* data, PRUint16 type, const nsIID* iid, PRUint32 count, void * aValue);
+ static nsresult SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue);
+ static nsresult SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue);
+
+ static nsresult SetToVoid(nsDiscriminatedUnion* data);
+ static nsresult SetToEmpty(nsDiscriminatedUnion* data);
+ static nsresult SetToEmptyArray(nsDiscriminatedUnion* data);
+
+private:
+ ~nsVariant();
+
+protected:
+ nsDiscriminatedUnion mData;
+ PRBool mWritable;
+};
+
+/**
+ * Users of nsIVariant should be using the contractID and not this CID.
+ * - see NS_VARIANT_CONTRACTID in nsIVariant.idl.
+ */
+
+#define NS_VARIANT_CID \
+{ /* 0D6EA1D0-879C-11d5-90EF-0010A4E73D9A */ \
+ 0xd6ea1d0, \
+ 0x879c, \
+ 0x11d5, \
+ {0x90, 0xef, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a}}
+
+#define NS_VARIANT_CLASSNAME "Variant"
+
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp
new file mode 100644
index 00000000..259d0bd3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.cpp
@@ -0,0 +1,1560 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsVoidArray.h"
+#include "nsQuickSort.h"
+#include "prmem.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "prbit.h"
+
+/**
+ * Grow the array by at least this many elements at a time.
+ */
+static const PRInt32 kMinGrowArrayBy = 8;
+static const PRInt32 kMaxGrowArrayBy = 1024;
+
+/**
+ * This is the threshold (in bytes) of the mImpl struct, past which
+ * we'll force the array to grow geometrically
+ */
+static const PRInt32 kLinearThreshold = 24 * sizeof(void *);
+
+/**
+ * Compute the number of bytes requires for the mImpl struct that will
+ * hold |n| elements.
+ */
+#define SIZEOF_IMPL(n_) (sizeof(Impl) + sizeof(void *) * ((n_) - 1))
+
+
+/**
+ * Compute the number of elements that an mImpl struct of |n| bytes
+ * will hold.
+ */
+#define CAPACITYOF_IMPL(n_) ((((n_) - sizeof(Impl)) / sizeof(void *)) + 1)
+
+#if DEBUG_VOIDARRAY
+#define MAXVOID 10
+
+class VoidStats {
+public:
+ VoidStats();
+ ~VoidStats();
+
+};
+
+static int sizesUsed; // number of the elements of the arrays used
+static int sizesAlloced[MAXVOID]; // sizes of the allocations. sorted
+static int NumberOfSize[MAXVOID]; // number of this allocation size (1 per array)
+static int AllocedOfSize[MAXVOID]; // number of this allocation size (each size for array used)
+static int MaxAuto[MAXVOID]; // AutoArrays that maxed out at this size
+static int GrowInPlace[MAXVOID]; // arrays this size that grew in-place via realloc
+
+// these are per-allocation
+static int MaxElements[2000]; // # of arrays that maxed out at each size.
+
+// statistics macros
+#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])++; break; } \
+ } \
+ if (i >= sizesUsed && sizesUsed < MAXVOID) \
+ { sizesAlloced[sizesUsed] = (size); \
+ ((x)[sizesUsed++])++; break; \
+ } \
+ } while (0)
+
+#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
+ { \
+ if (sizesAlloced[i] == (int)(size)) \
+ { ((x)[i])--; break; } \
+ } \
+ } while (0)
+
+
+VoidStats::VoidStats()
+{
+ sizesUsed = 1;
+ sizesAlloced[0] = 0;
+}
+
+VoidStats::~VoidStats()
+{
+ int i;
+ for (i = 0; i < sizesUsed; i++)
+ {
+ printf("Size %d:\n",sizesAlloced[i]);
+ printf("\tNumber of VoidArrays this size (max): %d\n",NumberOfSize[i]-MaxAuto[i]);
+ printf("\tNumber of AutoVoidArrays this size (max): %d\n",MaxAuto[i]);
+ printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]);
+ printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
+ }
+ printf("Max Size of VoidArray:\n");
+ for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
+ {
+ if (MaxElements[i])
+ printf("\t%d: %d\n",i,MaxElements[i]);
+ }
+}
+
+// Just so constructor/destructor's get called
+VoidStats gVoidStats;
+#endif
+
+inline void
+nsVoidArray::SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool owner)
+{
+ // old mImpl has been realloced and so we don't free/delete it
+ NS_PRECONDITION(newImpl, "can't set size");
+ mImpl = newImpl;
+ mImpl->mCount = aCount;
+ mImpl->mBits = PRUint32(aSize & kArraySizeMask) |
+ (owner ? kArrayOwnerMask : 0);
+}
+
+// This does all allocation/reallocation of the array.
+// It also will compact down to N - good for things that might grow a lot
+// at times, but usually are smaller, like JS deferred GC releases.
+PRBool nsVoidArray::SizeTo(PRInt32 aSize)
+{
+ PRUint32 oldsize = GetArraySize();
+
+ if (aSize == (PRInt32) oldsize)
+ return PR_TRUE; // no change
+
+ if (aSize <= 0)
+ {
+ // free the array if allocated
+ if (mImpl)
+ {
+ if (IsArrayOwner())
+ {
+ PR_Free(NS_REINTERPRET_CAST(char *, mImpl));
+ mImpl = nsnull;
+ }
+ else
+ {
+ mImpl->mCount = 0; // nsAutoVoidArray
+ }
+ }
+ return PR_TRUE;
+ }
+
+ if (mImpl && IsArrayOwner())
+ {
+ // We currently own an array impl. Resize it appropriately.
+ if (aSize < mImpl->mCount)
+ {
+ // XXX Note: we could also just resize to mCount
+ return PR_TRUE; // can't make it that small, ignore request
+ }
+
+ char* bytes = (char *) PR_Realloc(mImpl,SIZEOF_IMPL(aSize));
+ Impl* newImpl = NS_REINTERPRET_CAST(Impl*, bytes);
+ if (!newImpl)
+ return PR_FALSE;
+
+#if DEBUG_VOIDARRAY
+ if (mImpl == newImpl)
+ ADD_TO_STATS(GrowInPlace,oldsize);
+ ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize));
+ if (aSize > mMaxSize)
+ {
+ ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize));
+ if (oldsize)
+ SUB_FROM_STATS(NumberOfSize,oldsize);
+ mMaxSize = aSize;
+ if (mIsAuto)
+ {
+ ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize));
+ SUB_FROM_STATS(MaxAuto,oldsize);
+ }
+ }
+#endif
+ SetArray(newImpl,aSize,newImpl->mCount,PR_TRUE);
+ return PR_TRUE;
+ }
+
+ // just allocate an array
+ // allocate the exact size requested
+ char* bytes = (char *) PR_Malloc(SIZEOF_IMPL(aSize));
+ Impl* newImpl = NS_REINTERPRET_CAST(Impl*, bytes);
+ if (!newImpl)
+ return PR_FALSE;
+
+#if DEBUG_VOIDARRAY
+ ADD_TO_STATS(AllocedOfSize,SIZEOF_IMPL(aSize));
+ if (aSize > mMaxSize)
+ {
+ ADD_TO_STATS(NumberOfSize,SIZEOF_IMPL(aSize));
+ if (oldsize && !mImpl)
+ SUB_FROM_STATS(NumberOfSize,oldsize);
+ mMaxSize = aSize;
+ }
+#endif
+ if (mImpl)
+ {
+#if DEBUG_VOIDARRAY
+ ADD_TO_STATS(MaxAuto,SIZEOF_IMPL(aSize));
+ SUB_FROM_STATS(MaxAuto,0);
+ SUB_FROM_STATS(NumberOfSize,0);
+ mIsAuto = PR_TRUE;
+#endif
+ // We must be growing an nsAutoVoidArray - copy since we didn't
+ // realloc.
+ memcpy(newImpl->mArray, mImpl->mArray,
+ mImpl->mCount * sizeof(mImpl->mArray[0]));
+ }
+
+ SetArray(newImpl,aSize,mImpl ? mImpl->mCount : 0,PR_TRUE);
+ // no memset; handled later in ReplaceElementAt if needed
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::GrowArrayBy(PRInt32 aGrowBy)
+{
+ // We have to grow the array. Grow by kMinGrowArrayBy slots if we're
+ // smaller than kLinearThreshold bytes, or a power of two if we're
+ // larger. This is much more efficient with most memory allocators,
+ // especially if it's very large, or of the allocator is binned.
+ if (aGrowBy < kMinGrowArrayBy)
+ aGrowBy = kMinGrowArrayBy;
+
+ PRUint32 newCapacity = GetArraySize() + aGrowBy; // Minimum increase
+ PRUint32 newSize = SIZEOF_IMPL(newCapacity);
+
+ if (newSize >= (PRUint32) kLinearThreshold)
+ {
+ // newCount includes enough space for at least kMinGrowArrayBy new
+ // slots. Select the next power-of-two size in bytes above or
+ // equal to that.
+ // Also, limit the increase in size to about a VM page or two.
+ if (GetArraySize() >= kMaxGrowArrayBy)
+ {
+ newCapacity = GetArraySize() + PR_MAX(kMaxGrowArrayBy,aGrowBy);
+ newSize = SIZEOF_IMPL(newCapacity);
+ }
+ else
+ {
+ newSize = PR_BIT(PR_CeilingLog2(newSize));
+ newCapacity = CAPACITYOF_IMPL(newSize);
+ }
+ }
+ // frees old mImpl IF this succeeds
+ if (!SizeTo(newCapacity))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+nsVoidArray::nsVoidArray()
+ : mImpl(nsnull)
+{
+ MOZ_COUNT_CTOR(nsVoidArray);
+#if DEBUG_VOIDARRAY
+ mMaxCount = 0;
+ mMaxSize = 0;
+ mIsAuto = PR_FALSE;
+ ADD_TO_STATS(NumberOfSize,0);
+ MaxElements[0]++;
+#endif
+}
+
+nsVoidArray::nsVoidArray(PRInt32 aCount)
+ : mImpl(nsnull)
+{
+ MOZ_COUNT_CTOR(nsVoidArray);
+#if DEBUG_VOIDARRAY
+ mMaxCount = 0;
+ mMaxSize = 0;
+ mIsAuto = PR_FALSE;
+ MaxElements[0]++;
+#endif
+ SizeTo(aCount);
+}
+
+nsVoidArray& nsVoidArray::operator=(const nsVoidArray& other)
+{
+ PRInt32 otherCount = other.Count();
+ PRInt32 maxCount = GetArraySize();
+ if (otherCount)
+ {
+ if (otherCount > maxCount)
+ {
+ // frees old mImpl IF this succeeds
+ if (!GrowArrayBy(otherCount-maxCount))
+ return *this; // XXX The allocation failed - don't do anything
+
+ memcpy(mImpl->mArray, other.mImpl->mArray, otherCount * sizeof(mImpl->mArray[0]));
+ mImpl->mCount = otherCount;
+ }
+ else
+ {
+ // the old array can hold the new array
+ memcpy(mImpl->mArray, other.mImpl->mArray, otherCount * sizeof(mImpl->mArray[0]));
+ mImpl->mCount = otherCount;
+ // if it shrank a lot, compact it anyways
+ if ((otherCount*2) < maxCount && maxCount > 100)
+ {
+ Compact(); // shrank by at least 50 entries
+ }
+ }
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+ }
+ else
+ {
+ if (mImpl && IsArrayOwner())
+ PR_Free(NS_REINTERPRET_CAST(char*, mImpl));
+
+ mImpl = nsnull;
+ }
+
+ return *this;
+}
+
+nsVoidArray::~nsVoidArray()
+{
+ MOZ_COUNT_DTOR(nsVoidArray);
+ if (mImpl && IsArrayOwner())
+ PR_Free(NS_REINTERPRET_CAST(char*, mImpl));
+}
+
+PRInt32 nsVoidArray::IndexOf(void* aPossibleElement) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ if (*ap == aPossibleElement)
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRBool nsVoidArray::InsertElementAt(void* aElement, PRInt32 aIndex)
+{
+ PRInt32 oldCount = Count();
+ NS_ASSERTION(aIndex >= 0,"InsertElementAt(negative index)");
+ if (PRUint32(aIndex) > PRUint32(oldCount))
+ {
+ // An invalid index causes the insertion to fail
+ // Invalid indexes are ones that add more than one entry to the
+ // array (i.e., they can append).
+ return PR_FALSE;
+ }
+
+ if (oldCount >= GetArraySize())
+ {
+ if (!GrowArrayBy(1))
+ return PR_FALSE;
+ }
+ // else the array is already large enough
+
+ PRInt32 slide = oldCount - aIndex;
+ if (0 != slide)
+ {
+ // Slide data over to make room for the insertion
+ memmove(mImpl->mArray + aIndex + 1, mImpl->mArray + aIndex,
+ slide * sizeof(mImpl->mArray[0]));
+ }
+
+ mImpl->mArray[aIndex] = aElement;
+ mImpl->mCount++;
+
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::InsertElementsAt(const nsVoidArray& other, PRInt32 aIndex)
+{
+ PRInt32 oldCount = Count();
+ PRInt32 otherCount = other.Count();
+
+ NS_ASSERTION(aIndex >= 0,"InsertElementsAt(negative index)");
+ if (PRUint32(aIndex) > PRUint32(oldCount))
+ {
+ // An invalid index causes the insertion to fail
+ // Invalid indexes are ones that are more than one entry past the end of
+ // the array (i.e., they can append).
+ return PR_FALSE;
+ }
+
+ if (oldCount + otherCount > GetArraySize())
+ {
+ if (!GrowArrayBy(otherCount))
+ return PR_FALSE;;
+ }
+ // else the array is already large enough
+
+ PRInt32 slide = oldCount - aIndex;
+ if (0 != slide)
+ {
+ // Slide data over to make room for the insertion
+ memmove(mImpl->mArray + aIndex + otherCount, mImpl->mArray + aIndex,
+ slide * sizeof(mImpl->mArray[0]));
+ }
+
+ for (PRInt32 i = 0; i < otherCount; i++)
+ {
+ // copy all the elements (destroys aIndex)
+ mImpl->mArray[aIndex++] = other.mImpl->mArray[i];
+ mImpl->mCount++;
+ }
+
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::ReplaceElementAt(void* aElement, PRInt32 aIndex)
+{
+ NS_ASSERTION(aIndex >= 0,"ReplaceElementAt(negative index)");
+ if (aIndex < 0)
+ return PR_FALSE;
+
+ // Unlike InsertElementAt, ReplaceElementAt can implicitly add more
+ // than just the one element to the array.
+ if (PRUint32(aIndex) >= PRUint32(GetArraySize()))
+ {
+ PRInt32 oldCount = Count();
+ PRInt32 requestedCount = aIndex + 1;
+ PRInt32 growDelta = requestedCount - oldCount;
+
+ // frees old mImpl IF this succeeds
+ if (!GrowArrayBy(growDelta))
+ return PR_FALSE;
+ }
+
+ mImpl->mArray[aIndex] = aElement;
+ if (aIndex >= mImpl->mCount)
+ {
+ // Make sure that any entries implicitly added to the array by this
+ // ReplaceElementAt are cleared to 0. Some users of this assume that.
+ // This code means we don't have to memset when we allocate an array.
+ if (aIndex > mImpl->mCount) // note: not >=
+ {
+ // For example, if mCount is 2, and we do a ReplaceElementAt for
+ // element[5], then we need to set three entries ([2], [3], and [4])
+ // to 0.
+ memset(&mImpl->mArray[mImpl->mCount], 0,
+ (aIndex - mImpl->mCount) * sizeof(mImpl->mArray[0]));
+ }
+
+ mImpl->mCount = aIndex + 1;
+
+#if DEBUG_VOIDARRAY
+ if (mImpl->mCount > mMaxCount &&
+ mImpl->mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
+ {
+ MaxElements[mImpl->mCount]++;
+ MaxElements[mMaxCount]--;
+ mMaxCount = mImpl->mCount;
+ }
+#endif
+ }
+
+ return PR_TRUE;
+}
+
+// useful for doing LRU arrays
+PRBool nsVoidArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
+{
+ void *tempElement;
+
+ if (aTo == aFrom)
+ return PR_TRUE;
+
+ NS_ASSERTION(aTo >= 0 && aFrom >= 0,"MoveElement(negative index)");
+ if (aTo >= Count() || aFrom >= Count())
+ {
+ // can't extend the array when moving an element. Also catches mImpl = null
+ return PR_FALSE;
+ }
+ tempElement = mImpl->mArray[aFrom];
+
+ if (aTo < aFrom)
+ {
+ // Moving one element closer to the head; the elements inbetween move down
+ memmove(mImpl->mArray + aTo + 1, mImpl->mArray + aTo,
+ (aFrom-aTo) * sizeof(mImpl->mArray[0]));
+ mImpl->mArray[aTo] = tempElement;
+ }
+ else // already handled aFrom == aTo
+ {
+ // Moving one element closer to the tail; the elements inbetween move up
+ memmove(mImpl->mArray + aFrom, mImpl->mArray + aFrom + 1,
+ (aTo-aFrom) * sizeof(mImpl->mArray[0]));
+ mImpl->mArray[aTo] = tempElement;
+ }
+
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount)
+{
+ PRInt32 oldCount = Count();
+ NS_ASSERTION(aIndex >= 0,"RemoveElementsAt(negative index)");
+ if (PRUint32(aIndex) >= PRUint32(oldCount))
+ {
+ // An invalid index causes the replace to fail
+ return PR_FALSE;
+ }
+ // Limit to available entries starting at aIndex
+ if (aCount + aIndex > oldCount)
+ aCount = oldCount - aIndex;
+
+ // We don't need to move any elements if we're removing the
+ // last element in the array
+ if (aIndex < (oldCount - aCount))
+ {
+ memmove(mImpl->mArray + aIndex, mImpl->mArray + aIndex + aCount,
+ (oldCount - (aIndex + aCount)) * sizeof(mImpl->mArray[0]));
+ }
+
+ mImpl->mCount -= aCount;
+ return PR_TRUE;
+}
+
+PRBool nsVoidArray::RemoveElement(void* aElement)
+{
+ PRInt32 theIndex = IndexOf(aElement);
+ if (theIndex != -1)
+ return RemoveElementAt(theIndex);
+
+ return PR_FALSE;
+}
+
+void nsVoidArray::Clear()
+{
+ if (mImpl)
+ {
+ mImpl->mCount = 0;
+ }
+}
+
+void nsVoidArray::Compact()
+{
+ if (mImpl)
+ {
+ // XXX NOTE: this is quite inefficient in many cases if we're only
+ // compacting by a little, but some callers care more about memory use.
+ if (GetArraySize() > Count())
+ {
+ SizeTo(Count());
+ }
+ }
+}
+
+// Needed because we want to pass the pointer to the item in the array
+// to the comparator function, not a pointer to the pointer in the array.
+struct VoidArrayComparatorContext {
+ nsVoidArrayComparatorFunc mComparatorFunc;
+ void* mData;
+};
+
+PR_STATIC_CALLBACK(int)
+VoidArrayComparator(const void* aElement1, const void* aElement2, void* aData)
+{
+ VoidArrayComparatorContext* ctx = NS_STATIC_CAST(VoidArrayComparatorContext*, aData);
+ return (*ctx->mComparatorFunc)(*NS_STATIC_CAST(void* const*, aElement1),
+ *NS_STATIC_CAST(void* const*, aElement2),
+ ctx->mData);
+}
+
+void nsVoidArray::Sort(nsVoidArrayComparatorFunc aFunc, void* aData)
+{
+ if (mImpl && mImpl->mCount > 1)
+ {
+ VoidArrayComparatorContext ctx = {aFunc, aData};
+ NS_QuickSort(mImpl->mArray, mImpl->mCount, sizeof(mImpl->mArray[0]),
+ VoidArrayComparator, &ctx);
+ }
+}
+
+PRBool nsVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 index = -1;
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ while (running && (++index < mImpl->mCount))
+ {
+ running = (*aFunc)(mImpl->mArray[index], aData);
+ }
+ }
+ return running;
+}
+
+PRBool nsVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ PRInt32 index = Count();
+ while (running && (0 <= --index))
+ {
+ running = (*aFunc)(mImpl->mArray[index], aData);
+ }
+ }
+ return running;
+}
+
+//----------------------------------------------------------------
+// nsAutoVoidArray
+
+nsAutoVoidArray::nsAutoVoidArray()
+ : nsVoidArray()
+{
+ // Don't need to clear it. Some users just call ReplaceElementAt(),
+ // but we'll clear it at that time if needed to save CPU cycles.
+#if DEBUG_VOIDARRAY
+ mIsAuto = PR_TRUE;
+ ADD_TO_STATS(MaxAuto,0);
+#endif
+ SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
+}
+
+void nsAutoVoidArray::Clear()
+{
+ // We don't have to free on Clear, but since we have a built-in buffer,
+ // it's worth considering.
+ nsVoidArray::Clear();
+ if (IsArrayOwner() && GetArraySize() > 4*kAutoBufSize)
+ SizeTo(0); // we override CompactTo - delete and repoint at auto array
+}
+
+PRBool nsAutoVoidArray::SizeTo(PRInt32 aSize)
+{
+ if (!nsVoidArray::SizeTo(aSize))
+ return PR_FALSE;
+
+ if (!mImpl)
+ {
+ // reset the array to point to our autobuf
+ SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
+ }
+ return PR_TRUE;
+}
+
+void nsAutoVoidArray::Compact()
+{
+ nsVoidArray::Compact();
+ if (!mImpl)
+ {
+ // reset the array to point to our autobuf
+ SetArray(NS_REINTERPRET_CAST(Impl*, mAutoBuf),kAutoBufSize,0,PR_FALSE);
+ }
+}
+
+//----------------------------------------------------------------
+// nsStringArray
+
+nsStringArray::nsStringArray(void)
+ : nsVoidArray()
+{
+}
+
+nsStringArray::nsStringArray(PRInt32 aCount)
+ : nsVoidArray(aCount)
+{
+}
+
+nsStringArray::~nsStringArray(void)
+{
+ Clear();
+}
+
+nsStringArray&
+nsStringArray::operator=(const nsStringArray& other)
+{
+ // Copy the pointers
+ nsVoidArray::operator=(other);
+
+ // Now copy the strings
+ for (PRInt32 i = Count() - 1; i >= 0; --i)
+ {
+ nsString* oldString = NS_STATIC_CAST(nsString*, other.ElementAt(i));
+ mImpl->mArray[i] = new nsString(*oldString);
+ }
+
+ return *this;
+}
+
+void
+nsStringArray::StringAt(PRInt32 aIndex, nsAString& aString) const
+{
+ nsString* string = NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ aString.Assign(*string);
+ }
+ else
+ {
+ aString.Truncate();
+ }
+}
+
+nsString*
+nsStringArray::StringAt(PRInt32 aIndex) const
+{
+ return NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
+}
+
+PRInt32
+nsStringArray::IndexOf(const nsAString& aPossibleString) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ nsString* string = NS_STATIC_CAST(nsString*, *ap);
+ if (string->Equals(aPossibleString))
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRBool
+nsStringArray::InsertStringAt(const nsAString& aString, PRInt32 aIndex)
+{
+ nsString* string = new nsString(aString);
+ if (nsVoidArray::InsertElementAt(string, aIndex))
+ {
+ return PR_TRUE;
+ }
+ delete string;
+ return PR_FALSE;
+}
+
+PRBool
+nsStringArray::ReplaceStringAt(const nsAString& aString,
+ PRInt32 aIndex)
+{
+ nsString* string = NS_STATIC_CAST(nsString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ *string = aString;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsStringArray::RemoveString(const nsAString& aString)
+{
+ PRInt32 index = IndexOf(aString);
+ if (-1 < index)
+ {
+ return RemoveStringAt(index);
+ }
+ return PR_FALSE;
+}
+
+PRBool nsStringArray::RemoveStringAt(PRInt32 aIndex)
+{
+ nsString* string = StringAt(aIndex);
+ if (nsnull != string)
+ {
+ nsVoidArray::RemoveElementAt(aIndex);
+ delete string;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+void
+nsStringArray::Clear(void)
+{
+ PRInt32 index = Count();
+ while (0 <= --index)
+ {
+ nsString* string = NS_STATIC_CAST(nsString*, mImpl->mArray[index]);
+ delete string;
+ }
+ nsVoidArray::Clear();
+}
+
+PR_STATIC_CALLBACK(int)
+CompareString(const nsString* aString1, const nsString* aString2, void*)
+{
+ return Compare(*aString1, *aString2);
+}
+
+void nsStringArray::Sort(void)
+{
+ Sort(CompareString, nsnull);
+}
+
+void nsStringArray::Sort(nsStringArrayComparatorFunc aFunc, void* aData)
+{
+ nsVoidArray::Sort(NS_REINTERPRET_CAST(nsVoidArrayComparatorFunc, aFunc), aData);
+}
+
+PRBool
+nsStringArray::EnumerateForwards(nsStringArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 index = -1;
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ while (running && (++index < mImpl->mCount))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+PRBool
+nsStringArray::EnumerateBackwards(nsStringArrayEnumFunc aFunc, void* aData)
+{
+ PRInt32 index = Count();
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ while (running && (0 <= --index))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+
+
+//----------------------------------------------------------------
+// nsCStringArray
+
+nsCStringArray::nsCStringArray(void)
+ : nsVoidArray()
+{
+}
+
+// Parses a given string using the delimiter passed in and appends items
+// parsed to the array.
+void
+nsCStringArray::ParseString(const char* string, const char* delimiter)
+{
+ if (string && *string && delimiter && *delimiter) {
+ char *newStr;
+ char *rest = nsCRT::strdup(string);
+ char *token = nsCRT::strtok(rest, delimiter, &newStr);
+
+ while (token) {
+ if (*token) {
+ /* calling AppendElement(void*) to avoid extra nsCString copy */
+ AppendElement(new nsCString(token));
+ }
+ token = nsCRT::strtok(newStr, delimiter, &newStr);
+ }
+ PR_FREEIF(rest);
+ }
+}
+
+nsCStringArray::nsCStringArray(PRInt32 aCount)
+ : nsVoidArray(aCount)
+{
+}
+
+nsCStringArray::~nsCStringArray(void)
+{
+ Clear();
+}
+
+nsCStringArray&
+nsCStringArray::operator=(const nsCStringArray& other)
+{
+ // Copy the pointers
+ nsVoidArray::operator=(other);
+
+ // Now copy the strings
+ for (PRInt32 i = Count() - 1; i >= 0; --i)
+ {
+ nsCString* oldString = NS_STATIC_CAST(nsCString*, other.ElementAt(i));
+ mImpl->mArray[i] = new nsCString(*oldString);
+ }
+
+ return *this;
+}
+
+void
+nsCStringArray::CStringAt(PRInt32 aIndex, nsACString& aCString) const
+{
+ nsCString* string = NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ aCString = *string;
+ }
+ else
+ {
+ aCString.Truncate();
+ }
+}
+
+nsCString*
+nsCStringArray::CStringAt(PRInt32 aIndex) const
+{
+ return NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
+}
+
+PRInt32
+nsCStringArray::IndexOf(const nsACString& aPossibleString) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ nsCString* string = NS_STATIC_CAST(nsCString*, *ap);
+ if (string->Equals(aPossibleString))
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRInt32
+nsCStringArray::IndexOfIgnoreCase(const nsACString& aPossibleString) const
+{
+ if (mImpl)
+ {
+ void** ap = mImpl->mArray;
+ void** end = ap + mImpl->mCount;
+ while (ap < end)
+ {
+ nsCString* string = NS_STATIC_CAST(nsCString*, *ap);
+ if (string->Equals(aPossibleString, nsCaseInsensitiveCStringComparator()))
+ {
+ return ap - mImpl->mArray;
+ }
+ ap++;
+ }
+ }
+ return -1;
+}
+
+PRBool
+nsCStringArray::InsertCStringAt(const nsACString& aCString, PRInt32 aIndex)
+{
+ nsCString* string = new nsCString(aCString);
+ if (nsVoidArray::InsertElementAt(string, aIndex))
+ {
+ return PR_TRUE;
+ }
+ delete string;
+ return PR_FALSE;
+}
+
+PRBool
+nsCStringArray::ReplaceCStringAt(const nsACString& aCString, PRInt32 aIndex)
+{
+ nsCString* string = NS_STATIC_CAST(nsCString*, nsVoidArray::ElementAt(aIndex));
+ if (nsnull != string)
+ {
+ *string = aCString;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsCStringArray::RemoveCString(const nsACString& aCString)
+{
+ PRInt32 index = IndexOf(aCString);
+ if (-1 < index)
+ {
+ return RemoveCStringAt(index);
+ }
+ return PR_FALSE;
+}
+
+PRBool
+nsCStringArray::RemoveCStringIgnoreCase(const nsACString& aCString)
+{
+ PRInt32 index = IndexOfIgnoreCase(aCString);
+ if (-1 < index)
+ {
+ return RemoveCStringAt(index);
+ }
+ return PR_FALSE;
+}
+
+PRBool nsCStringArray::RemoveCStringAt(PRInt32 aIndex)
+{
+ nsCString* string = CStringAt(aIndex);
+ if (nsnull != string)
+ {
+ nsVoidArray::RemoveElementAt(aIndex);
+ delete string;
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+void
+nsCStringArray::Clear(void)
+{
+ PRInt32 index = Count();
+ while (0 <= --index)
+ {
+ nsCString* string = NS_STATIC_CAST(nsCString*, mImpl->mArray[index]);
+ delete string;
+ }
+ nsVoidArray::Clear();
+}
+
+PR_STATIC_CALLBACK(int)
+CompareCString(const nsCString* aCString1, const nsCString* aCString2, void*)
+{
+ return Compare(*aCString1, *aCString2);
+}
+
+PR_STATIC_CALLBACK(int)
+CompareCStringIgnoreCase(const nsCString* aCString1, const nsCString* aCString2, void*)
+{
+ return Compare(*aCString1, *aCString2, nsCaseInsensitiveCStringComparator());
+}
+
+void nsCStringArray::Sort(void)
+{
+ Sort(CompareCString, nsnull);
+}
+
+void nsCStringArray::SortIgnoreCase(void)
+{
+ Sort(CompareCStringIgnoreCase, nsnull);
+}
+
+void nsCStringArray::Sort(nsCStringArrayComparatorFunc aFunc, void* aData)
+{
+ nsVoidArray::Sort(NS_REINTERPRET_CAST(nsVoidArrayComparatorFunc, aFunc), aData);
+}
+
+PRBool
+nsCStringArray::EnumerateForwards(nsCStringArrayEnumFunc aFunc, void* aData)
+{
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ PRInt32 index = -1;
+ while (running && (++index < mImpl->mCount))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsCString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+PRBool
+nsCStringArray::EnumerateBackwards(nsCStringArrayEnumFunc aFunc, void* aData)
+{
+ PRBool running = PR_TRUE;
+
+ if (mImpl)
+ {
+ PRInt32 index = Count();
+ while (running && (0 <= --index))
+ {
+ running = (*aFunc)(*NS_STATIC_CAST(nsCString*, mImpl->mArray[index]), aData);
+ }
+ }
+ return running;
+}
+
+
+//----------------------------------------------------------------------
+// NOTE: nsSmallVoidArray elements MUST all have the low bit as 0.
+// This means that normally it's only used for pointers, and in particular
+// structures or objects.
+nsSmallVoidArray::nsSmallVoidArray()
+{
+ mChildren = nsnull;
+}
+
+nsSmallVoidArray::~nsSmallVoidArray()
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ delete vector;
+ }
+}
+
+nsSmallVoidArray&
+nsSmallVoidArray::operator=(nsSmallVoidArray& other)
+{
+ nsVoidArray* ourArray = GetChildVector();
+ nsVoidArray* otherArray = other.GetChildVector();
+
+ if (HasVector())
+ {
+ if (other.HasVector())
+ {
+ // if both are real arrays, just use array= */
+ *ourArray = *otherArray;
+ }
+ else
+ {
+ // we have an array, but the other doesn't.
+ otherArray = other.SwitchToVector();
+ if (otherArray)
+ *ourArray = *otherArray;
+ }
+ }
+ else
+ {
+ if (other.HasVector())
+ {
+ // we have no array, but other does
+ ourArray = SwitchToVector();
+ if (ourArray)
+ *ourArray = *otherArray;
+ }
+ else
+ {
+ // neither has an array (either may have 0 or 1 items)
+ SetSingleChild(other.GetSingleChild());
+ }
+ }
+ return *this;
+}
+
+PRInt32
+nsSmallVoidArray::GetArraySize() const
+{
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->GetArraySize();
+
+ return 1;
+}
+
+PRInt32
+nsSmallVoidArray::Count() const
+{
+ if (HasSingleChild())
+ {
+ return 1;
+ }
+ else {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->Count();
+ }
+
+ return 0;
+}
+
+void*
+nsSmallVoidArray::ElementAt(PRInt32 aIndex) const
+{
+ if (HasSingleChild())
+ {
+ if (0 == aIndex)
+ return (void*)GetSingleChild();
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->ElementAt(aIndex);
+ }
+
+ return nsnull;
+}
+
+PRInt32
+nsSmallVoidArray::IndexOf(void* aPossibleElement) const
+{
+ if (HasSingleChild())
+ {
+ if (aPossibleElement == (void*)GetSingleChild())
+ return 0;
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->IndexOf(aPossibleElement);
+ }
+
+ return -1;
+}
+
+PRBool
+nsSmallVoidArray::InsertElementAt(void* aElement, PRInt32 aIndex)
+{
+ nsVoidArray* vector;
+ NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+
+ if (HasSingleChild())
+ {
+ vector = SwitchToVector();
+ }
+ else
+ {
+ vector = GetChildVector();
+ if (!vector)
+ {
+ if (0 == aIndex)
+ {
+ SetSingleChild(aElement);
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+ }
+ }
+
+ return vector->InsertElementAt(aElement, aIndex);
+}
+
+PRBool nsSmallVoidArray::InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex)
+{
+ nsVoidArray* vector;
+ PRInt32 count = other.Count();
+ if (count == 0)
+ return PR_TRUE;
+
+#ifdef DEBUG
+ for (int i = 0; i < count; i++)
+ {
+ NS_ASSERTION(!(PtrBits(other.ElementAt(i)) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(other.ElementAt(i) != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+ }
+#endif
+
+ if (!HasVector())
+ {
+ if (HasSingleChild() || count > 1 || aIndex > 0)
+ {
+ vector = SwitchToVector();
+ }
+ else
+ {
+ // count == 1, aIndex == 0, no elements already
+ SetSingleChild(other[0]);
+ return PR_TRUE;
+ }
+ }
+ else
+ {
+ vector = GetChildVector();
+ }
+
+ if (vector)
+ {
+ return vector->InsertElementsAt(other,aIndex);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+nsSmallVoidArray::ReplaceElementAt(void* aElement, PRInt32 aIndex)
+{
+ NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+
+ if (HasSingleChild())
+ {
+ if (aIndex == 0)
+ {
+ SetSingleChild(aElement);
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->ReplaceElementAt(aElement, aIndex);
+
+ return PR_FALSE;
+ }
+}
+
+PRBool
+nsSmallVoidArray::AppendElement(void* aElement)
+{
+ NS_ASSERTION(!(PtrBits(aElement) & 0x1),"Attempt to add element with 0x1 bit set to nsSmallVoidArray");
+ NS_ASSERTION(aElement != nsnull,"Attempt to add a NULL element to an nsSmallVoidArray");
+
+ nsVoidArray* vector;
+ if (HasSingleChild())
+ {
+ vector = SwitchToVector();
+ }
+ else
+ {
+ vector = GetChildVector();
+ if (!vector)
+ {
+ SetSingleChild(aElement);
+ return PR_TRUE;
+ }
+ }
+
+ return vector->AppendElement(aElement);
+}
+
+PRBool
+nsSmallVoidArray::RemoveElement(void* aElement)
+{
+ if (HasSingleChild())
+ {
+ if (aElement == GetSingleChild())
+ {
+ SetSingleChild(nsnull);
+ return PR_TRUE;
+ }
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ return vector->RemoveElement(aElement);
+ }
+
+ return PR_FALSE;
+}
+
+PRBool
+nsSmallVoidArray::RemoveElementAt(PRInt32 aIndex)
+{
+ if (HasSingleChild())
+ {
+ if (0 == aIndex)
+ {
+ SetSingleChild(nsnull);
+ return PR_TRUE;
+ }
+ }
+ else
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ {
+ return vector->RemoveElementAt(aIndex);
+ }
+ }
+
+ return PR_FALSE;
+}
+
+PRBool
+nsSmallVoidArray::RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount)
+{
+ nsVoidArray* vector = GetChildVector();
+
+ if (aCount == 0)
+ return PR_TRUE;
+
+ if (HasSingleChild())
+ {
+ if (aIndex == 0)
+ SetSingleChild(nsnull);
+ return PR_TRUE;
+ }
+
+ if (!vector)
+ return PR_TRUE;
+
+ // complex case; remove entries from an array
+ return vector->RemoveElementsAt(aIndex,aCount);
+}
+
+void
+nsSmallVoidArray::Clear()
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ vector->Clear();
+ }
+ else
+ {
+ SetSingleChild(nsnull);
+ }
+}
+
+PRBool
+nsSmallVoidArray::SizeTo(PRInt32 aMin)
+{
+ nsVoidArray* vector;
+ if (!HasVector())
+ {
+ if (aMin <= 1)
+ return PR_TRUE;
+ vector = SwitchToVector();
+ }
+ else
+ {
+ vector = GetChildVector();
+ if (aMin <= 1)
+ {
+ void *prev = nsnull;
+ if (vector->Count() == 1)
+ {
+ prev = vector->ElementAt(0);
+ }
+ delete vector;
+ SetSingleChild(prev);
+ return PR_TRUE;
+ }
+ }
+ return vector->SizeTo(aMin);
+}
+
+void
+nsSmallVoidArray::Compact()
+{
+ if (!HasSingleChild())
+ {
+ nsVoidArray* vector = GetChildVector();
+ if (vector)
+ vector->Compact();
+ }
+}
+
+void
+nsSmallVoidArray::Sort(nsVoidArrayComparatorFunc aFunc, void* aData)
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ vector->Sort(aFunc,aData);
+ }
+}
+
+PRBool
+nsSmallVoidArray::EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ return vector->EnumerateForwards(aFunc,aData);
+ }
+ if (HasSingleChild())
+ {
+ return (*aFunc)(GetSingleChild(), aData);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+nsSmallVoidArray::EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData)
+{
+ if (HasVector())
+ {
+ nsVoidArray* vector = GetChildVector();
+ return vector->EnumerateBackwards(aFunc,aData);
+ }
+ if (HasSingleChild())
+ {
+ return (*aFunc)(GetSingleChild(), aData);
+ }
+ return PR_TRUE;
+}
+
+void
+nsSmallVoidArray::SetSingleChild(void* aChild)
+{
+ if (aChild)
+ mChildren = (void*)(PtrBits(aChild) | 0x1);
+ else
+ mChildren = nsnull;
+}
+
+nsVoidArray*
+nsSmallVoidArray::SwitchToVector()
+{
+ void* child = GetSingleChild();
+
+ mChildren = (void*)new nsAutoVoidArray();
+ nsVoidArray* vector = GetChildVector();
+ if (vector && child)
+ vector->AppendElement(child);
+
+ return vector;
+}
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h
new file mode 100644
index 00000000..28d950e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/nsVoidArray.h
@@ -0,0 +1,410 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; c-file-offsets: ((substatement-open . 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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsVoidArray_h___
+#define nsVoidArray_h___
+
+//#define DEBUG_VOIDARRAY 1
+
+#include "nscore.h"
+#include "nsAString.h"
+
+// Comparator callback function for sorting array values.
+typedef int (* PR_CALLBACK nsVoidArrayComparatorFunc)
+ (const void* aElement1, const void* aElement2, void* aData);
+
+// Enumerator callback function. Return PR_FALSE to stop
+typedef PRBool (* PR_CALLBACK nsVoidArrayEnumFunc)(void* aElement, void *aData);
+
+/// A basic zero-based array of void*'s that manages its own memory
+class NS_COM nsVoidArray {
+public:
+ nsVoidArray();
+ nsVoidArray(PRInt32 aCount); // initial count of aCount elements set to nsnull
+ virtual ~nsVoidArray();
+
+ nsVoidArray& operator=(const nsVoidArray& other);
+
+ inline PRInt32 Count() const {
+ return mImpl ? mImpl->mCount : 0;
+ }
+ // returns the max number that can be held without allocating
+ inline PRInt32 GetArraySize() const {
+ return mImpl ? (PRInt32(mImpl->mBits) & kArraySizeMask) : 0;
+ }
+
+ void* FastElementAt(PRInt32 aIndex) const
+ {
+ NS_ASSERTION(0 <= aIndex && aIndex < Count(), "index out of range");
+ return mImpl->mArray[aIndex];
+ }
+
+ // This both asserts and bounds-checks, because (1) we don't want
+ // people to write bad code, but (2) we don't want to change it to
+ // crashing for backwards compatibility. See bug 96108.
+ void* ElementAt(PRInt32 aIndex) const
+ {
+ NS_ASSERTION(0 <= aIndex && aIndex < Count(), "index out of range");
+ return SafeElementAt(aIndex);
+ }
+
+ // bounds-checked version
+ void* SafeElementAt(PRInt32 aIndex) const
+ {
+ if (PRUint32(aIndex) >= PRUint32(Count())) // handles aIndex < 0 too
+ {
+ return nsnull;
+ }
+ // The bounds check ensures mImpl is non-null.
+ return mImpl->mArray[aIndex];
+ }
+
+ void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
+
+ PRInt32 IndexOf(void* aPossibleElement) const;
+
+ PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
+ PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
+
+ PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
+
+ // useful for doing LRU arrays, sorting, etc
+ PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
+
+ PRBool AppendElement(void* aElement) {
+ return InsertElementAt(aElement, Count());
+ }
+
+ PRBool AppendElements(nsVoidArray& aElements) {
+ return InsertElementsAt(aElements, Count());
+ }
+
+ PRBool RemoveElement(void* aElement);
+ PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
+ PRBool RemoveElementAt(PRInt32 aIndex) { return RemoveElementsAt(aIndex,1); }
+
+ virtual void Clear();
+
+ virtual PRBool SizeTo(PRInt32 aMin);
+ // Subtly different - Compact() tries to be smart about whether we
+ // should reallocate the array; SizeTo() just does it.
+ virtual void Compact();
+
+ void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
+
+protected:
+ virtual PRBool GrowArrayBy(PRInt32 aGrowBy);
+
+ struct Impl {
+ /**
+ * Packed bits. The low 31 bits are the array's size.
+ * The highest bit is a flag that indicates
+ * whether or not we "own" mArray, and must free() it when
+ * destroyed.
+ */
+ PRUint32 mBits;
+
+ /**
+ * The number of elements in the array
+ */
+ PRInt32 mCount;
+
+ /**
+ * Array data, padded out to the actual size of the array.
+ */
+ void* mArray[1];
+ };
+
+ Impl* mImpl;
+#if DEBUG_VOIDARRAY
+ PRInt32 mMaxCount;
+ PRInt32 mMaxSize;
+ PRBool mIsAuto;
+#endif
+
+ enum {
+ kArrayOwnerMask = 1 << 31,
+ kArraySizeMask = ~kArrayOwnerMask
+ };
+
+
+ // bit twiddlers
+ void SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool owner);
+ inline PRBool IsArrayOwner() const {
+ return mImpl ? (PRBool(mImpl->mBits) & kArrayOwnerMask) : PR_FALSE;
+ }
+
+private:
+ /// Copy constructors are not allowed
+ nsVoidArray(const nsVoidArray& other);
+};
+
+
+// A zero-based array with a bit of automatic internal storage
+class NS_COM nsAutoVoidArray : public nsVoidArray {
+public:
+ nsAutoVoidArray();
+ void Clear();
+
+ virtual PRBool SizeTo(PRInt32 aMin);
+ virtual void Compact();
+
+protected:
+ // The internal storage
+ enum { kAutoBufSize = 8 };
+ char mAutoBuf[sizeof(Impl) + (kAutoBufSize - 1) * sizeof(void*)];
+};
+
+
+class nsString;
+
+typedef int (* PR_CALLBACK nsStringArrayComparatorFunc)
+ (const nsString* aElement1, const nsString* aElement2, void* aData);
+
+typedef PRBool (*nsStringArrayEnumFunc)(nsString& aElement, void *aData);
+
+class NS_COM nsStringArray: protected nsVoidArray
+{
+public:
+ nsStringArray(void);
+ nsStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
+ virtual ~nsStringArray(void);
+
+ nsStringArray& operator=(const nsStringArray& other);
+
+ PRInt32 Count(void) const {
+ return nsVoidArray::Count();
+ }
+
+ void StringAt(PRInt32 aIndex, nsAString& aString) const;
+ nsString* StringAt(PRInt32 aIndex) const;
+ nsString* operator[](PRInt32 aIndex) const { return StringAt(aIndex); }
+
+ PRInt32 IndexOf(const nsAString& aPossibleString) const;
+
+ PRBool InsertStringAt(const nsAString& aString, PRInt32 aIndex);
+
+ PRBool ReplaceStringAt(const nsAString& aString, PRInt32 aIndex);
+
+ PRBool AppendString(const nsAString& aString) {
+ return InsertStringAt(aString, Count());
+ }
+
+ PRBool RemoveString(const nsAString& aString);
+ PRBool RemoveStringAt(PRInt32 aIndex);
+ void Clear(void);
+
+ void Compact(void) {
+ nsVoidArray::Compact();
+ }
+
+ void Sort(void);
+ void Sort(nsStringArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsStringArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsStringArrayEnumFunc aFunc, void* aData);
+
+private:
+ /// Copy constructors are not allowed
+ nsStringArray(const nsStringArray& other);
+};
+
+
+class nsCString;
+
+typedef int (* PR_CALLBACK nsCStringArrayComparatorFunc)
+ (const nsCString* aElement1, const nsCString* aElement2, void* aData);
+
+typedef PRBool (*nsCStringArrayEnumFunc)(nsCString& aElement, void *aData);
+
+class NS_COM nsCStringArray: protected nsVoidArray
+{
+public:
+ nsCStringArray(void);
+ nsCStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
+ virtual ~nsCStringArray(void);
+
+ nsCStringArray& operator=(const nsCStringArray& other);
+
+ // Parses a given string using the delimiter passed in. If the array
+ // already has some elements, items parsed from string will be appended
+ // to array. For example, array.ParseString("a,b,c", ","); will add strings
+ // "a", "b" and "c" to the array. Parsing process has the same tokenizing
+ // behavior as strtok().
+ void ParseString(const char* string, const char* delimiter);
+
+ PRInt32 Count(void) const {
+ return nsVoidArray::Count();
+ }
+
+ void CStringAt(PRInt32 aIndex, nsACString& aCString) const;
+ nsCString* CStringAt(PRInt32 aIndex) const;
+ nsCString* operator[](PRInt32 aIndex) const { return CStringAt(aIndex); }
+
+ PRInt32 IndexOf(const nsACString& aPossibleString) const;
+ PRInt32 IndexOfIgnoreCase(const nsACString& aPossibleString) const;
+
+ PRBool InsertCStringAt(const nsACString& aCString, PRInt32 aIndex);
+
+ PRBool ReplaceCStringAt(const nsACString& aCString, PRInt32 aIndex);
+
+ PRBool AppendCString(const nsACString& aCString) {
+ return InsertCStringAt(aCString, Count());
+ }
+
+ PRBool RemoveCString(const nsACString& aCString);
+ PRBool RemoveCStringIgnoreCase(const nsACString& aCString);
+ PRBool RemoveCStringAt(PRInt32 aIndex);
+ void Clear(void);
+
+ void Compact(void) {
+ nsVoidArray::Compact();
+ }
+
+ void Sort(void);
+ void SortIgnoreCase(void);
+ void Sort(nsCStringArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsCStringArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsCStringArrayEnumFunc aFunc, void* aData);
+
+private:
+ /// Copy constructors are not allowed
+ nsCStringArray(const nsCStringArray& other);
+};
+
+
+//===================================================================
+// nsSmallVoidArray is not a general-purpose replacement for
+// ns(Auto)VoidArray because there is (some) extra CPU overhead for arrays
+// larger than 1 element, though not a lot. It is appropriate for
+// space-sensitive uses where sizes of 0 or 1 are moderately common or
+// more, and where we're NOT storing arbitrary integers or arbitrary
+// pointers.
+
+// NOTE: nsSmallVoidArray can ONLY be used for holding items that always
+// have the low bit as a 0 - i.e. element & 1 == 0. This happens to be
+// true for allocated and object pointers for all the architectures we run
+// on, but conceivably there might be some architectures/compilers for
+// which it is NOT true. We know this works for all existing architectures
+// because if it didn't then nsCheapVoidArray would have failed. Also note
+// that we will ASSERT if this assumption is violated in DEBUG builds.
+
+// XXX we're really re-implementing the whole nsVoidArray interface here -
+// some form of abstract class would be useful
+
+// I disagree on the abstraction here. If the point of this class is to be
+// as small as possible, and no one will ever derive from it, as I found
+// today, there should not be any virtualness to it to avoid the vtable
+// ptr overhead.
+
+class NS_COM nsSmallVoidArray
+{
+public:
+ nsSmallVoidArray();
+ ~nsSmallVoidArray();
+
+ nsSmallVoidArray& operator=(nsSmallVoidArray& other);
+ void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
+
+ PRInt32 GetArraySize() const;
+
+ PRInt32 Count() const;
+ void* ElementAt(PRInt32 aIndex) const;
+ void* SafeElementAt(PRInt32 aIndex) const {
+ // let compiler inline; it may be able to remove these checks
+ if (aIndex < 0 || aIndex >= Count())
+ return nsnull;
+ return ElementAt(aIndex);
+ }
+ PRInt32 IndexOf(void* aPossibleElement) const;
+ PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
+ PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
+ PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
+ PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
+ PRBool AppendElement(void* aElement);
+ PRBool AppendElements(nsVoidArray& aElements) {
+ return InsertElementsAt(aElements, Count());
+ }
+ PRBool RemoveElement(void* aElement);
+ PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
+ PRBool RemoveElementAt(PRInt32 aIndex);
+
+ void Clear();
+ PRBool SizeTo(PRInt32 aMin);
+ void Compact();
+ void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
+
+ PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData);
+ PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
+
+private:
+#ifdef RT_OS_OS2 /* shut up a million warnings */
+ typedef PRUint32 PtrBits;
+#else
+ typedef PRUint64 PtrBits;
+#endif
+
+ PRBool HasSingleChild() const
+ {
+ return (mChildren && (PtrBits(mChildren) & 0x1));
+ }
+ PRBool HasVector() const
+ {
+ return (mChildren && !(PtrBits(mChildren) & 0x1));
+ }
+ void* GetSingleChild() const
+ {
+ return (mChildren ? ((void*)(PtrBits(mChildren) & ~0x1)) : nsnull);
+ }
+ void SetSingleChild(void *aChild);
+ nsVoidArray* GetChildVector() const
+ {
+ return (nsVoidArray*)mChildren;
+ }
+ nsVoidArray* SwitchToVector();
+
+ // A tagged pointer that's either a pointer to a single child
+ // or a pointer to a vector of multiple children. This is a space
+ // optimization since a large number of containers have only a
+ // single child.
+ void *mChildren;
+};
+
+#endif /* nsVoidArray_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/ds/pldhash.c b/src/libs/xpcom18a4/xpcom/ds/pldhash.c
new file mode 100644
index 00000000..74f8cd0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/pldhash.c
@@ -0,0 +1,826 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ * Chris Waterson <waterson@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Double hashing implementation.
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "prbit.h"
+#include "pldhash.h"
+#include "prlog.h" /* for PR_ASSERT */
+
+#ifdef PL_DHASHMETER
+# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan
+# include "nsTraceMalloc.h"
+# endif
+# define METER(x) x
+#else
+# define METER(x) /* nothing */
+#endif
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+PR_IMPLEMENT(void *)
+PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes)
+{
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ return RTMemAlloc(nbytes);
+#else
+ return malloc(nbytes);
+#endif
+}
+
+PR_IMPLEMENT(void)
+PL_DHashFreeTable(PLDHashTable *table, void *ptr)
+{
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+PR_IMPLEMENT(PLDHashNumber)
+PL_DHashStringKey(PLDHashTable *table, const void *key)
+{
+ PLDHashNumber h;
+ const unsigned char *s;
+
+ h = 0;
+ for (s = key; *s != '\0'; s++)
+ h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ *s;
+ return h;
+}
+
+PR_IMPLEMENT(const void *)
+PL_DHashGetKeyStub(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ PLDHashEntryStub *stub = (PLDHashEntryStub *)entry;
+
+ return stub->key;
+}
+
+PR_IMPLEMENT(PLDHashNumber)
+PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key)
+{
+ return (PLDHashNumber)(uintptr_t)key >> 2;
+}
+
+PR_IMPLEMENT(PRBool)
+PL_DHashMatchEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry;
+
+ return stub->key == key;
+}
+
+PR_IMPLEMENT(PRBool)
+PL_DHashMatchStringKey(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry;
+
+ /* XXX tolerate null keys on account of sloppy Mozilla callers. */
+ return stub->key == key ||
+ (stub->key && key && strcmp(stub->key, key) == 0);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashMoveEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to)
+{
+ memcpy(to, from, table->entrySize);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ memset(entry, 0, table->entrySize);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ const PLDHashEntryStub *stub = (const PLDHashEntryStub *)entry;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree((void *) stub->key);
+#else
+ free((void *) stub->key);
+#endif
+ memset(entry, 0, table->entrySize);
+}
+
+PR_IMPLEMENT(void)
+PL_DHashFinalizeStub(PLDHashTable *table)
+{
+}
+
+static const PLDHashTableOps stub_ops = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashVoidPtrKeyStub,
+ PL_DHashMatchEntryStub,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+PR_IMPLEMENT(const PLDHashTableOps *)
+PL_DHashGetStubOps(void)
+{
+ return &stub_ops;
+}
+
+PR_IMPLEMENT(PLDHashTable *)
+PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize,
+ PRUint32 capacity)
+{
+ PLDHashTable *table;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ table = (PLDHashTable *) RTMemAlloc(sizeof *table);
+#else
+ table = (PLDHashTable *) malloc(sizeof *table);
+#endif
+ if (!table)
+ return NULL;
+ if (!PL_DHashTableInit(table, ops, data, entrySize, capacity)) {
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(table);
+#else
+ free(table);
+#endif
+ return NULL;
+ }
+ return table;
+}
+
+PR_IMPLEMENT(void)
+PL_DHashTableDestroy(PLDHashTable *table)
+{
+ PL_DHashTableFinish(table);
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(table);
+#else
+ free(table);
+#endif
+}
+
+PR_IMPLEMENT(PRBool)
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
+ PRUint32 entrySize, PRUint32 capacity)
+{
+ int log2;
+ PRUint32 nbytes;
+
+#ifdef DEBUG
+ if (entrySize > 10 * sizeof(void *)) {
+ fprintf(stderr,
+ "pldhash: for the table at address %p, the given entrySize"
+ " of %lu %s favors chaining over double hashing.\n",
+ (void *)table,
+ (unsigned long) entrySize,
+ (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably");
+ }
+#endif
+
+ table->ops = ops;
+ table->data = data;
+ if (capacity < PL_DHASH_MIN_SIZE)
+ capacity = PL_DHASH_MIN_SIZE;
+ log2 = PR_CeilingLog2(capacity);
+ capacity = PR_BIT(log2);
+ if (capacity >= PL_DHASH_SIZE_LIMIT)
+ return PR_FALSE;
+ table->hashShift = PL_DHASH_BITS - log2;
+ table->maxAlphaFrac = 0xC0; /* .75 */
+ table->minAlphaFrac = 0x40; /* .25 */
+ table->entrySize = entrySize;
+ table->entryCount = table->removedCount = 0;
+ table->generation = 0;
+ nbytes = capacity * entrySize;
+
+ table->entryStore = ops->allocTable(table, nbytes);
+ if (!table->entryStore)
+ return PR_FALSE;
+ memset(table->entryStore, 0, nbytes);
+ METER(memset(&table->stats, 0, sizeof table->stats));
+ return PR_TRUE;
+}
+
+/*
+ * Compute max and min load numbers (entry counts) from table params.
+ */
+#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8)
+#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8)
+
+PR_IMPLEMENT(void)
+PL_DHashTableSetAlphaBounds(PLDHashTable *table,
+ float maxAlpha,
+ float minAlpha)
+{
+ PRUint32 size;
+
+ /*
+ * Reject obviously insane bounds, rather than trying to guess what the
+ * buggy caller intended.
+ */
+ PR_ASSERT(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha);
+ if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0)
+ return;
+
+ /*
+ * Ensure that at least one entry will always be free. If maxAlpha at
+ * minimum size leaves no entries free, reduce maxAlpha based on minimum
+ * size and the precision limit of maxAlphaFrac's fixed point format.
+ */
+ PR_ASSERT(PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) >= 1);
+ if (PL_DHASH_MIN_SIZE - (maxAlpha * PL_DHASH_MIN_SIZE) < 1) {
+ maxAlpha = (float)
+ (PL_DHASH_MIN_SIZE - PR_MAX(PL_DHASH_MIN_SIZE / 256, 1))
+ / PL_DHASH_MIN_SIZE;
+ }
+
+ /*
+ * Ensure that minAlpha is strictly less than half maxAlpha. Take care
+ * not to truncate an entry's worth of alpha when storing in minAlphaFrac
+ * (8-bit fixed point format).
+ */
+ PR_ASSERT(minAlpha < maxAlpha / 2);
+ if (minAlpha >= maxAlpha / 2) {
+ size = PL_DHASH_TABLE_SIZE(table);
+ minAlpha = (size * maxAlpha - PR_MAX(size / 256, 1)) / (2 * size);
+ }
+
+ table->maxAlphaFrac = (uint8)(maxAlpha * 256);
+ table->minAlphaFrac = (uint8)(minAlpha * 256);
+}
+
+/*
+ * Double hashing needs the second hash code to be relatively prime to table
+ * size, so we simply make hash2 odd.
+ */
+#define HASH1(hash0, shift) ((hash0) >> (shift))
+#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
+
+/*
+ * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note
+ * that a removed-entry sentinel need be stored only if the removed entry had
+ * a colliding entry added after it. Therefore we can use 1 as the collision
+ * flag in addition to the removed-entry sentinel value. Multiplicative hash
+ * uses the high order bits of keyHash, so this least-significant reservation
+ * should not hurt the hash function's effectiveness much.
+ *
+ * If you change any of these magic numbers, also update PL_DHASH_ENTRY_IS_LIVE
+ * in pldhash.h. It used to be private to pldhash.c, but then became public to
+ * assist iterator writers who inspect table->entryStore directly.
+ */
+#define COLLISION_FLAG ((PLDHashNumber) 1)
+#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0)
+#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1)
+#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1)
+#define ENTRY_IS_LIVE(entry) PL_DHASH_ENTRY_IS_LIVE(entry)
+#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0
+
+/* Match an entry's keyHash against an unstored one computed from a key. */
+#define MATCH_ENTRY_KEYHASH(entry,hash0) \
+ (((entry)->keyHash & ~COLLISION_FLAG) == (hash0))
+
+/* Compute the address of the indexed entry in table. */
+#define ADDRESS_ENTRY(table, index) \
+ ((PLDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize))
+
+PR_IMPLEMENT(void)
+PL_DHashTableFinish(PLDHashTable *table)
+{
+ char *entryAddr, *entryLimit;
+ PRUint32 entrySize;
+ PLDHashEntryHdr *entry;
+
+#ifdef DEBUG_XXXbrendan
+ static FILE *dumpfp = NULL;
+ if (!dumpfp) dumpfp = fopen("/tmp/pldhash.bigdump", "w");
+ if (dumpfp) {
+#ifdef MOZILLA_CLIENT
+ NS_TraceStack(1, dumpfp);
+#endif
+ PL_DHashTableDumpMeter(table, NULL, dumpfp);
+ fputc('\n', dumpfp);
+ }
+#endif
+
+ /* Call finalize before clearing entries, so it can enumerate them. */
+ table->ops->finalize(table);
+
+ /* Clear any remaining live entries. */
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ entryLimit = entryAddr + PL_DHASH_TABLE_SIZE(table) * entrySize;
+ while (entryAddr < entryLimit) {
+ entry = (PLDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ METER(table->stats.removeEnums++);
+ table->ops->clearEntry(table, entry);
+ }
+ entryAddr += entrySize;
+ }
+
+ /* Free entry storage last. */
+ table->ops->freeTable(table, table->entryStore);
+}
+
+static PLDHashEntryHdr * PL_DHASH_FASTCALL
+SearchTable(PLDHashTable *table, const void *key, PLDHashNumber keyHash,
+ PLDHashOperator op)
+{
+ PLDHashNumber hash1, hash2;
+ int hashShift, sizeLog2;
+ PLDHashEntryHdr *entry, *firstRemoved;
+ PLDHashMatchEntry matchEntry;
+ PRUint32 sizeMask;
+
+ METER(table->stats.searches++);
+ PR_ASSERT(!(keyHash & COLLISION_FLAG));
+
+ /* Compute the primary hash address. */
+ hashShift = table->hashShift;
+ hash1 = HASH1(keyHash, hashShift);
+ entry = ADDRESS_ENTRY(table, hash1);
+
+ /* Miss: return space for a new entry. */
+ if (PL_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+
+ /* Hit: return entry. */
+ matchEntry = table->ops->matchEntry;
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = PL_DHASH_BITS - table->hashShift;
+ hash2 = HASH2(keyHash, sizeLog2, hashShift);
+ sizeMask = PR_BITMASK(sizeLog2);
+
+ /* Save the first removed entry pointer so PL_DHASH_ADD can recycle it. */
+ if (ENTRY_IS_REMOVED(entry)) {
+ firstRemoved = entry;
+ } else {
+ firstRemoved = NULL;
+ if (op == PL_DHASH_ADD)
+ entry->keyHash |= COLLISION_FLAG;
+ }
+
+ for (;;) {
+ METER(table->stats.steps++);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+
+ entry = ADDRESS_ENTRY(table, hash1);
+ if (PL_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return (firstRemoved && op == PL_DHASH_ADD) ? firstRemoved : entry;
+ }
+
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) &&
+ matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+
+ if (ENTRY_IS_REMOVED(entry)) {
+ if (!firstRemoved)
+ firstRemoved = entry;
+ } else {
+ if (op == PL_DHASH_ADD)
+ entry->keyHash |= COLLISION_FLAG;
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+static PRBool
+ChangeTable(PLDHashTable *table, int deltaLog2)
+{
+ int oldLog2, newLog2;
+ PRUint32 oldCapacity, newCapacity;
+ char *newEntryStore, *oldEntryStore, *oldEntryAddr;
+ PRUint32 entrySize, i, nbytes;
+ PLDHashEntryHdr *oldEntry, *newEntry;
+ PLDHashGetKey getKey;
+ PLDHashMoveEntry moveEntry;
+
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ PR_ASSERT(table->generation != PR_UINT32_MAX);
+ if (table->generation == PR_UINT32_MAX)
+ return PR_FALSE;
+#endif
+
+ /* Look, but don't touch, until we succeed in getting new entry store. */
+ oldLog2 = PL_DHASH_BITS - table->hashShift;
+ newLog2 = oldLog2 + deltaLog2;
+ oldCapacity = PR_BIT(oldLog2);
+ newCapacity = PR_BIT(newLog2);
+ if (newCapacity >= PL_DHASH_SIZE_LIMIT)
+ return PR_FALSE;
+ entrySize = table->entrySize;
+ nbytes = newCapacity * entrySize;
+
+ newEntryStore = table->ops->allocTable(table, nbytes);
+ if (!newEntryStore)
+ return PR_FALSE;
+
+ /* We can't fail from here on, so update table parameters. */
+ table->hashShift = PL_DHASH_BITS - newLog2;
+ table->removedCount = 0;
+ table->generation++;
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ if (table->generation == PR_UINT32_MAX)
+ table->generation++;
+#endif
+
+ /* Assign the new entry store to table. */
+ memset(newEntryStore, 0, nbytes);
+ oldEntryAddr = oldEntryStore = table->entryStore;
+ table->entryStore = newEntryStore;
+ getKey = table->ops->getKey;
+ moveEntry = table->ops->moveEntry;
+
+ /* Copy only live entries, leaving removed ones behind. */
+ for (i = 0; i < oldCapacity; i++) {
+ oldEntry = (PLDHashEntryHdr *)oldEntryAddr;
+ if (ENTRY_IS_LIVE(oldEntry)) {
+ oldEntry->keyHash &= ~COLLISION_FLAG;
+ newEntry = SearchTable(table, getKey(table, oldEntry),
+ oldEntry->keyHash, PL_DHASH_ADD);
+ PR_ASSERT(PL_DHASH_ENTRY_IS_FREE(newEntry));
+ moveEntry(table, oldEntry, newEntry);
+ newEntry->keyHash = oldEntry->keyHash;
+ }
+ oldEntryAddr += entrySize;
+ }
+
+ table->ops->freeTable(table, oldEntryStore);
+ return PR_TRUE;
+}
+
+PR_IMPLEMENT(PLDHashEntryHdr *) PL_DHASH_FASTCALL
+PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op)
+{
+ PLDHashNumber keyHash;
+ PLDHashEntryHdr *entry;
+ PRUint32 size;
+ int deltaLog2;
+
+ keyHash = table->ops->hashKey(table, key);
+ keyHash *= PL_DHASH_GOLDEN_RATIO;
+
+ /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */
+ ENSURE_LIVE_KEYHASH(keyHash);
+ keyHash &= ~COLLISION_FLAG;
+
+ switch (op) {
+ case PL_DHASH_LOOKUP:
+ METER(table->stats.lookups++);
+ entry = SearchTable(table, key, keyHash, op);
+ break;
+
+ case PL_DHASH_ADD:
+ /*
+ * If alpha is >= .75, grow or compress the table. If key is already
+ * in the table, we may grow once more than necessary, but only if we
+ * are on the edge of being overloaded.
+ */
+ size = PL_DHASH_TABLE_SIZE(table);
+ if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) {
+ /* Compress if a quarter or more of all entries are removed. */
+ if (table->removedCount >= size >> 2) {
+ METER(table->stats.compresses++);
+ deltaLog2 = 0;
+ } else {
+ METER(table->stats.grows++);
+ deltaLog2 = 1;
+ }
+
+ /*
+ * Grow or compress table, returning null if ChangeTable fails and
+ * falling through might claim the last free entry.
+ */
+ if (!ChangeTable(table, deltaLog2) &&
+ table->entryCount + table->removedCount == size - 1) {
+ METER(table->stats.addFailures++);
+ return NULL;
+ }
+ }
+
+ /*
+ * Look for entry after possibly growing, so we don't have to add it,
+ * then skip it while growing the table and re-add it after.
+ */
+ entry = SearchTable(table, key, keyHash, op);
+ if (!ENTRY_IS_LIVE(entry)) {
+ /* Initialize the entry, indicating that it's no longer free. */
+ METER(table->stats.addMisses++);
+ if (ENTRY_IS_REMOVED(entry)) {
+ METER(table->stats.addOverRemoved++);
+ table->removedCount--;
+ keyHash |= COLLISION_FLAG;
+ }
+ if (table->ops->initEntry &&
+ !table->ops->initEntry(table, entry, key)) {
+ /* We haven't claimed entry yet; fail with null return. */
+ memset(entry + 1, 0, table->entrySize - sizeof *entry);
+ return NULL;
+ }
+ entry->keyHash = keyHash;
+ table->entryCount++;
+ }
+ METER(else table->stats.addHits++);
+ break;
+
+ case PL_DHASH_REMOVE:
+ entry = SearchTable(table, key, keyHash, op);
+ if (ENTRY_IS_LIVE(entry)) {
+ /* Clear this entry and mark it as "removed". */
+ METER(table->stats.removeHits++);
+ PL_DHashTableRawRemove(table, entry);
+
+ /* Shrink if alpha is <= .25 and table isn't too small already. */
+ size = PL_DHASH_TABLE_SIZE(table);
+ if (size > PL_DHASH_MIN_SIZE &&
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ /** @todo This is where IPC screws up, avoid the assertion in ChangeTable until it's fixed. */
+ table->generation != PR_UINT32_MAX &&
+#endif
+ table->entryCount <= MIN_LOAD(table, size)) {
+ METER(table->stats.shrinks++);
+ (void) ChangeTable(table, -1);
+ }
+ }
+ METER(else table->stats.removeMisses++);
+ entry = NULL;
+ break;
+
+ default:
+ PR_ASSERT(0);
+ entry = NULL;
+ }
+
+ return entry;
+}
+
+PR_IMPLEMENT(void)
+PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ PLDHashNumber keyHash; /* load first in case clearEntry goofs it */
+
+ PR_ASSERT(PL_DHASH_ENTRY_IS_LIVE(entry));
+ keyHash = entry->keyHash;
+ table->ops->clearEntry(table, entry);
+ if (keyHash & COLLISION_FLAG) {
+ MARK_ENTRY_REMOVED(entry);
+ table->removedCount++;
+ } else {
+ METER(table->stats.removeFrees++);
+ MARK_ENTRY_FREE(entry);
+ }
+ table->entryCount--;
+}
+
+PR_IMPLEMENT(PRUint32)
+PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg)
+{
+ char *entryAddr, *entryLimit;
+ PRUint32 i, capacity, entrySize;
+ PRBool didRemove;
+ PLDHashEntryHdr *entry;
+ PLDHashOperator op;
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ PRUint32 generation;
+
+ /*
+ * The hack! Set generation to PR_UINT32_MAX during the enumeration so
+ * we can prevent ChangeTable from being called.
+ *
+ * This happens during ipcDConnectService::OnClientStateChange()
+ * / ipcDConnectService::DeleteInstance() now when running
+ * java clienttest list hostinfo and vboxwebsrv crashes. It's quite
+ * likely that the IPC code isn't following the rules here, but it
+ * looks more difficult to fix that just hacking this hash code.
+ */
+ generation = table->generation;
+ table->generation = PR_UINT32_MAX;
+#endif /* VBOX */
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ capacity = PL_DHASH_TABLE_SIZE(table);
+ entryLimit = entryAddr + capacity * entrySize;
+ i = 0;
+ didRemove = PR_FALSE;
+ while (entryAddr < entryLimit) {
+ entry = (PLDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ op = etor(table, entry, i++, arg);
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ PR_ASSERT(table->generation == PR_UINT32_MAX);
+#endif
+ if (op & PL_DHASH_REMOVE) {
+ METER(table->stats.removeEnums++);
+ PL_DHashTableRawRemove(table, entry);
+ didRemove = PR_TRUE;
+ }
+ if (op & PL_DHASH_STOP)
+ break;
+ }
+ entryAddr += entrySize;
+ }
+#ifdef VBOX /* HACK ALERT! generation == PR_UINT32_MAX during enumeration. */
+ table->generation = generation;
+#endif
+
+ /*
+ * Shrink or compress if a quarter or more of all entries are removed, or
+ * if the table is underloaded according to the configured minimum alpha,
+ * and is not minimal-size already. Do this only if we removed above, so
+ * non-removing enumerations can count on stable table->entryStore until
+ * the next non-lookup-Operate or removing-Enumerate.
+ */
+ if (didRemove &&
+ (table->removedCount >= capacity >> 2 ||
+ (capacity > PL_DHASH_MIN_SIZE &&
+ table->entryCount <= MIN_LOAD(table, capacity)))) {
+ METER(table->stats.enumShrinks++);
+ capacity = table->entryCount;
+ capacity += capacity >> 1;
+ if (capacity < PL_DHASH_MIN_SIZE)
+ capacity = PL_DHASH_MIN_SIZE;
+ (void) ChangeTable(table,
+ PR_CeilingLog2(capacity)
+ - (PL_DHASH_BITS - table->hashShift));
+ }
+ return i;
+}
+
+#ifdef PL_DHASHMETER
+#include <math.h>
+
+PR_IMPLEMENT(void)
+PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp)
+{
+ char *entryAddr;
+ PRUint32 entrySize, entryCount;
+ int hashShift, sizeLog2;
+ PRUint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount;
+ PLDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2;
+ double sqsum, mean, variance, sigma;
+ PLDHashEntryHdr *entry, *probe;
+
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ hashShift = table->hashShift;
+ sizeLog2 = PL_DHASH_BITS - hashShift;
+ tableSize = PL_DHASH_TABLE_SIZE(table);
+ sizeMask = PR_BITMASK(sizeLog2);
+ chainCount = maxChainLen = 0;
+ hash2 = 0;
+ sqsum = 0;
+
+ for (i = 0; i < tableSize; i++) {
+ entry = (PLDHashEntryHdr *)entryAddr;
+ entryAddr += entrySize;
+ if (!ENTRY_IS_LIVE(entry))
+ continue;
+ hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift);
+ saveHash1 = hash1;
+ probe = ADDRESS_ENTRY(table, hash1);
+ chainLen = 1;
+ if (probe == entry) {
+ /* Start of a (possibly unit-length) chain. */
+ chainCount++;
+ } else {
+ hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2,
+ hashShift);
+ do {
+ chainLen++;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ probe = ADDRESS_ENTRY(table, hash1);
+ } while (probe != entry);
+ }
+ sqsum += chainLen * chainLen;
+ if (chainLen > maxChainLen) {
+ maxChainLen = chainLen;
+ maxChainHash1 = saveHash1;
+ maxChainHash2 = hash2;
+ }
+ }
+
+ entryCount = table->entryCount;
+ if (entryCount && chainCount) {
+ mean = (double)entryCount / chainCount;
+ variance = chainCount * sqsum - entryCount * entryCount;
+ if (variance < 0 || chainCount == 1)
+ variance = 0;
+ else
+ variance /= chainCount * (chainCount - 1);
+ sigma = sqrt(variance);
+ } else {
+ mean = sigma = 0;
+ }
+
+ fprintf(fp, "Double hashing statistics:\n");
+ fprintf(fp, " table size (in entries): %u\n", tableSize);
+ fprintf(fp, " number of entries: %u\n", table->entryCount);
+ fprintf(fp, " number of removed entries: %u\n", table->removedCount);
+ fprintf(fp, " number of searches: %u\n", table->stats.searches);
+ fprintf(fp, " number of hits: %u\n", table->stats.hits);
+ fprintf(fp, " number of misses: %u\n", table->stats.misses);
+ fprintf(fp, " mean steps per search: %g\n", table->stats.searches ?
+ (double)table->stats.steps
+ / table->stats.searches :
+ 0.);
+ fprintf(fp, " mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " maximum hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " number of lookups: %u\n", table->stats.lookups);
+ fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses);
+ fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved);
+ fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits);
+ fprintf(fp, " add failures: %u\n", table->stats.addFailures);
+ fprintf(fp, " useful removes: %u\n", table->stats.removeHits);
+ fprintf(fp, " useless removes: %u\n", table->stats.removeMisses);
+ fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees);
+ fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums);
+ fprintf(fp, " number of grows: %u\n", table->stats.grows);
+ fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks);
+ fprintf(fp, " number of compresses: %u\n", table->stats.compresses);
+ fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks);
+
+ if (dump && maxChainLen && hash2) {
+ fputs("Maximum hash chain:\n", fp);
+ hash1 = maxChainHash1;
+ hash2 = maxChainHash2;
+ entry = ADDRESS_ENTRY(table, hash1);
+ i = 0;
+ do {
+ if (dump(table, entry, i++, fp) != PL_DHASH_NEXT)
+ break;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ entry = ADDRESS_ENTRY(table, hash1);
+ } while (PL_DHASH_ENTRY_IS_BUSY(entry));
+ }
+}
+#endif /* PL_DHASHMETER */
diff --git a/src/libs/xpcom18a4/xpcom/ds/pldhash.h b/src/libs/xpcom18a4/xpcom/ds/pldhash.h
new file mode 100644
index 00000000..8c4347c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/ds/pldhash.h
@@ -0,0 +1,603 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef pldhash_h___
+#define pldhash_h___
+/*
+ * Double hashing, a la Knuth 6.
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+ */
+#include "prtypes.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_DHashTableInit VBoxNsplPL_DHashTableInit
+#define PL_DHashTableFinish VBoxNsplPL_DHashTableFinish
+#define PL_DHashTableOperate VBoxNsplPL_DHashTableOperate
+#define PL_DHashTableEnumerate VBoxNsplPL_DHashTableEnumerate
+#define PL_DHashAllocTable VBoxNsplPL_DHashAllocTable
+#define PL_DHashFreeTable VBoxNsplPL_DHashFreeTable
+#define PL_DHashMoveEntryStub VBoxNsplPL_DHashMoveEntryStub
+#define PL_DHashFinalizeStub VBoxNsplPL_DHashFinalizeStub
+#define PL_DHashClearEntryStub VBoxNsplPL_DHashClearEntryStub
+#define PL_DHashFreeStringKey VBoxNsplPL_DHashFreeStringKey
+#define PL_DHashGetKeyStub VBoxNsplPL_DHashGetKeyStub
+#define PL_DHashGetStubOps VBoxNsplPL_DHashGetStubOps
+#define PL_DHashMatchEntryStub VBoxNsplPL_DHashMatchEntryStub
+#define PL_DHashMatchStringKey VBoxNsplPL_DHashMatchStringKey
+#define PL_DHashStringKey VBoxNsplPL_DHashStringKey
+#define PL_DHashTableDestroy VBoxNsplPL_DHashTableDestroy
+#define PL_DHashTableRawRemove VBoxNsplPL_DHashTableRawRemove
+#define PL_DHashTableSetAlphaBounds VBoxNsplPL_DHashTableSetAlphaBounds
+#define PL_DHashVoidPtrKeyStub VBoxNsplPL_DHashVoidPtrKeyStub
+#define PL_NewDHashTable VBoxNsplPL_NewDHashTable
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+#ifdef DEBUG_XXXbrendan
+#define PL_DHASHMETER 1
+#endif
+
+#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
+#define PL_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
+#else
+#define PL_DHASH_FASTCALL
+#endif
+
+/* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */
+#undef PL_DHASH_SIZE_LIMIT
+#define PL_DHASH_SIZE_LIMIT PR_BIT(24)
+
+/* Minimum table size, or gross entry count (net is at most .75 loaded). */
+#ifndef PL_DHASH_MIN_SIZE
+#define PL_DHASH_MIN_SIZE 16
+#elif (PL_DHASH_MIN_SIZE & (PL_DHASH_MIN_SIZE - 1)) != 0
+#error "PL_DHASH_MIN_SIZE must be a power of two!"
+#endif
+
+/*
+ * Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
+ * expressed as a fixed-point 32-bit fraction.
+ */
+#define PL_DHASH_BITS 32
+#define PL_DHASH_GOLDEN_RATIO 0x9E3779B9U
+
+/* Primitive and forward-struct typedefs. */
+typedef PRUint32 PLDHashNumber;
+typedef struct PLDHashEntryHdr PLDHashEntryHdr;
+typedef struct PLDHashEntryStub PLDHashEntryStub;
+typedef struct PLDHashTable PLDHashTable;
+typedef struct PLDHashTableOps PLDHashTableOps;
+
+/*
+ * Table entry header structure.
+ *
+ * In order to allow in-line allocation of key and value, we do not declare
+ * either here. Instead, the API uses const void *key as a formal parameter,
+ * and asks each entry for its key when necessary via a getKey callback, used
+ * when growing or shrinking the table. Other callback types are defined
+ * below and grouped into the PLDHashTableOps structure, for single static
+ * initialization per hash table sub-type.
+ *
+ * Each hash table sub-type should nest the PLDHashEntryHdr structure at the
+ * front of its particular entry type. The keyHash member contains the result
+ * of multiplying the hash code returned from the hashKey callback (see below)
+ * by PL_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0
+ * and 1 values. The stored keyHash value is table size invariant, and it is
+ * maintained automatically by PL_DHashTableOperate -- users should never set
+ * it, and its only uses should be via the entry macros below.
+ *
+ * The PL_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor
+ * removed. An entry may be either busy or free; if busy, it may be live or
+ * removed. Consumers of this API should not access members of entries that
+ * are not live.
+ *
+ * However, use PL_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
+ * returned by PL_DHashTableOperate, as PL_DHashTableOperate never returns a
+ * non-live, busy (i.e., removed) entry pointer to its caller. See below for
+ * more details on PL_DHashTableOperate's calling rules.
+ */
+struct PLDHashEntryHdr {
+ PLDHashNumber keyHash; /* every entry must begin like this */
+};
+
+#define PL_DHASH_ENTRY_IS_FREE(entry) ((entry)->keyHash == 0)
+#define PL_DHASH_ENTRY_IS_BUSY(entry) (!PL_DHASH_ENTRY_IS_FREE(entry))
+#define PL_DHASH_ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2)
+
+/*
+ * A PLDHashTable is currently 8 words (without the PL_DHASHMETER overhead)
+ * on most architectures, and may be allocated on the stack or within another
+ * structure or class (see below for the Init and Finish functions to use).
+ *
+ * To decide whether to use double hashing vs. chaining, we need to develop a
+ * trade-off relation, as follows:
+ *
+ * Let alpha be the load factor, esize the entry size in words, count the
+ * entry count, and pow2 the power-of-two table size in entries.
+ *
+ * (PLDHashTable overhead) > (PLHashTable overhead)
+ * (unused table entry space) > (malloc and .next overhead per entry) +
+ * (buckets overhead)
+ * (1 - alpha) * esize * pow2 > 2 * count + pow2
+ *
+ * Notice that alpha is by definition (count / pow2):
+ *
+ * (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2
+ * (1 - alpha) * esize > 2 * alpha + 1
+ *
+ * esize > (1 + 2 * alpha) / (1 - alpha)
+ *
+ * This assumes both tables must keep keyHash, key, and value for each entry,
+ * where key and value point to separately allocated strings or structures.
+ * If key and value can be combined into one pointer, then the trade-off is:
+ *
+ * esize > (1 + 3 * alpha) / (1 - alpha)
+ *
+ * If the entry value can be a subtype of PLDHashEntryHdr, rather than a type
+ * that must be allocated separately and referenced by an entry.value pointer
+ * member, and provided key's allocation can be fused with its entry's, then
+ * k (the words wasted per entry with chaining) is 4.
+ *
+ * To see these curves, feed gnuplot input like so:
+ *
+ * gnuplot> f(x,k) = (1 + k * x) / (1 - x)
+ * gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4)
+ *
+ * For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4
+ * words for chaining to be more space-efficient than double hashing.
+ *
+ * Solving for alpha helps us decide when to shrink an underloaded table:
+ *
+ * esize > (1 + k * alpha) / (1 - alpha)
+ * esize - alpha * esize > 1 + k * alpha
+ * esize - 1 > (k + esize) * alpha
+ * (esize - 1) / (k + esize) > alpha
+ *
+ * alpha < (esize - 1) / (esize + k)
+ *
+ * Therefore double hashing should keep alpha >= (esize - 1) / (esize + k),
+ * assuming esize is not too large (in which case, chaining should probably be
+ * used for any alpha). For esize=2 and k=3, we want alpha >= .2; for esize=3
+ * and k=2, we want alpha >= .4. For k=4, esize could be 6, and alpha >= .5
+ * would still obtain. See the PL_DHASH_MIN_ALPHA macro further below.
+ *
+ * The current implementation uses a configurable lower bound on alpha, which
+ * defaults to .25, when deciding to shrink the table (while still respecting
+ * PL_DHASH_MIN_SIZE).
+ *
+ * Note a qualitative difference between chaining and double hashing: under
+ * chaining, entry addresses are stable across table shrinks and grows. With
+ * double hashing, you can't safely hold an entry pointer and use it after an
+ * ADD or REMOVE operation, unless you sample table->generation before adding
+ * or removing, and compare the sample after, dereferencing the entry pointer
+ * only if table->generation has not changed.
+ *
+ * The moral of this story: there is no one-size-fits-all hash table scheme,
+ * but for small table entry size, and assuming entry address stability is not
+ * required, double hashing wins.
+ */
+struct PLDHashTable {
+ const PLDHashTableOps *ops; /* virtual operations, see below */
+ void *data; /* ops- and instance-specific data */
+ PRInt16 hashShift; /* multiplicative hash shift */
+ uint8 maxAlphaFrac; /* 8-bit fixed point max alpha */
+ uint8 minAlphaFrac; /* 8-bit fixed point min alpha */
+ PRUint32 entrySize; /* number of bytes in an entry */
+ PRUint32 entryCount; /* number of entries in table */
+ PRUint32 removedCount; /* removed entry sentinels in table */
+ PRUint32 generation; /* entry storage generation number */
+ char *entryStore; /* entry storage */
+#ifdef PL_DHASHMETER
+ struct PLDHashStats {
+ PRUint32 searches; /* total number of table searches */
+ PRUint32 steps; /* hash chain links traversed */
+ PRUint32 hits; /* searches that found key */
+ PRUint32 misses; /* searches that didn't find key */
+ PRUint32 lookups; /* number of PL_DHASH_LOOKUPs */
+ PRUint32 addMisses; /* adds that miss, and do work */
+ PRUint32 addOverRemoved; /* adds that recycled a removed entry */
+ PRUint32 addHits; /* adds that hit an existing entry */
+ PRUint32 addFailures; /* out-of-memory during add growth */
+ PRUint32 removeHits; /* removes that hit, and do work */
+ PRUint32 removeMisses; /* useless removes that miss */
+ PRUint32 removeFrees; /* removes that freed entry directly */
+ PRUint32 removeEnums; /* removes done by Enumerate */
+ PRUint32 grows; /* table expansions */
+ PRUint32 shrinks; /* table contractions */
+ PRUint32 compresses; /* table compressions */
+ PRUint32 enumShrinks; /* contractions after Enumerate */
+ } stats;
+#endif
+};
+
+/*
+ * Size in entries (gross, not net of free and removed sentinels) for table.
+ * We store hashShift rather than sizeLog2 to optimize the collision-free case
+ * in SearchTable.
+ */
+#define PL_DHASH_TABLE_SIZE(table) PR_BIT(PL_DHASH_BITS - (table)->hashShift)
+
+/*
+ * Table space at entryStore is allocated and freed using these callbacks.
+ * The allocator should return null on error only (not if called with nbytes
+ * equal to 0; but note that pldhash.c code will never call with 0 nbytes).
+ */
+typedef void *
+(* PR_CALLBACK PLDHashAllocTable)(PLDHashTable *table, PRUint32 nbytes);
+
+typedef void
+(* PR_CALLBACK PLDHashFreeTable) (PLDHashTable *table, void *ptr);
+
+/*
+ * When a table grows or shrinks, each entry is queried for its key using this
+ * callback. NB: in that event, entry is not in table any longer; it's in the
+ * old entryStore vector, which is due to be freed once all entries have been
+ * moved via moveEntry callbacks.
+ */
+typedef const void *
+(* PR_CALLBACK PLDHashGetKey) (PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+/*
+ * Compute the hash code for a given key to be looked up, added, or removed
+ * from table. A hash code may have any PLDHashNumber value.
+ */
+typedef PLDHashNumber
+(* PR_CALLBACK PLDHashHashKey) (PLDHashTable *table, const void *key);
+
+/*
+ * Compare the key identifying entry in table with the provided key parameter.
+ * Return PR_TRUE if keys match, PR_FALSE otherwise.
+ */
+typedef PRBool
+(* PR_CALLBACK PLDHashMatchEntry)(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Copy the data starting at from to the new entry storage at to. Do not add
+ * reference counts for any strong references in the entry, however, as this
+ * is a "move" operation: the old entry storage at from will be freed without
+ * any reference-decrementing callback shortly.
+ */
+typedef void
+(* PR_CALLBACK PLDHashMoveEntry)(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to);
+
+/*
+ * Clear the entry and drop any strong references it holds. This callback is
+ * invoked during a PL_DHASH_REMOVE operation (see below for operation codes),
+ * but only if the given key is found in the table.
+ */
+typedef void
+(* PR_CALLBACK PLDHashClearEntry)(PLDHashTable *table,
+ PLDHashEntryHdr *entry);
+
+/*
+ * Called when a table (whether allocated dynamically by itself, or nested in
+ * a larger structure, or allocated on the stack) is finished. This callback
+ * allows table->ops-specific code to finalize table->data.
+ */
+typedef void
+(* PR_CALLBACK PLDHashFinalize) (PLDHashTable *table);
+
+/*
+ * Initialize a new entry, apart from keyHash. This function is called when
+ * PL_DHashTableOperate's PL_DHASH_ADD case finds no existing entry for the
+ * given key, and must add a new one. At that point, entry->keyHash is not
+ * set yet, to avoid claiming the last free entry in a severely overloaded
+ * table.
+ */
+typedef PRBool
+(* PR_CALLBACK PLDHashInitEntry)(PLDHashTable *table,
+ PLDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Finally, the "vtable" structure for PLDHashTable. The first eight hooks
+ * must be provided by implementations; they're called unconditionally by the
+ * generic pldhash.c code. Hooks after these may be null.
+ *
+ * Summary of allocation-related hook usage with C++ placement new emphasis:
+ * allocTable Allocate raw bytes with malloc, no ctors run.
+ * freeTable Free raw bytes with free, no dtors run.
+ * initEntry Call placement new using default key-based ctor.
+ * Return PR_TRUE on success, PR_FALSE on error.
+ * moveEntry Call placement new using copy ctor, run dtor on old
+ * entry storage.
+ * clearEntry Run dtor on entry.
+ * finalize Stub unless table->data was initialized and needs to
+ * be finalized.
+ *
+ * Note the reason why initEntry is optional: the default hooks (stubs) clear
+ * entry storage: On successful PL_DHashTableOperate(tbl, key, PL_DHASH_ADD),
+ * the returned entry pointer addresses an entry struct whose keyHash member
+ * has been set non-zero, but all other entry members are still clear (null).
+ * PL_DHASH_ADD callers can test such members to see whether the entry was
+ * newly created by the PL_DHASH_ADD call that just succeeded. If placement
+ * new or similar initialization is required, define an initEntry hook. Of
+ * course, the clearEntry hook must zero or null appropriately.
+ *
+ * XXX assumes 0 is null for pointer types.
+ */
+struct PLDHashTableOps {
+ /* Mandatory hooks. All implementations must provide these. */
+ PLDHashAllocTable allocTable;
+ PLDHashFreeTable freeTable;
+ PLDHashGetKey getKey;
+ PLDHashHashKey hashKey;
+ PLDHashMatchEntry matchEntry;
+ PLDHashMoveEntry moveEntry;
+ PLDHashClearEntry clearEntry;
+ PLDHashFinalize finalize;
+
+ /* Optional hooks start here. If null, these are not called. */
+ PLDHashInitEntry initEntry;
+};
+
+/*
+ * Default implementations for the above ops.
+ */
+PR_EXTERN(void *)
+PL_DHashAllocTable(PLDHashTable *table, PRUint32 nbytes);
+
+PR_EXTERN(void)
+PL_DHashFreeTable(PLDHashTable *table, void *ptr);
+
+PR_EXTERN(PLDHashNumber)
+PL_DHashStringKey(PLDHashTable *table, const void *key);
+
+/* A minimal entry contains a keyHash header and a void key pointer. */
+struct PLDHashEntryStub {
+ PLDHashEntryHdr hdr;
+ const void *key;
+};
+
+PR_EXTERN(const void *)
+PL_DHashGetKeyStub(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+PR_EXTERN(PLDHashNumber)
+PL_DHashVoidPtrKeyStub(PLDHashTable *table, const void *key);
+
+PR_EXTERN(PRBool)
+PL_DHashMatchEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+PR_EXTERN(PRBool)
+PL_DHashMatchStringKey(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key);
+
+PR_EXTERN(void)
+PL_DHashMoveEntryStub(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to);
+
+PR_EXTERN(void)
+PL_DHashClearEntryStub(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+PR_EXTERN(void)
+PL_DHashFreeStringKey(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+PR_EXTERN(void)
+PL_DHashFinalizeStub(PLDHashTable *table);
+
+/*
+ * If you use PLDHashEntryStub or a subclass of it as your entry struct, and
+ * if your entries move via memcpy and clear via memset(0), you can use these
+ * stub operations.
+ */
+PR_EXTERN(const PLDHashTableOps *)
+PL_DHashGetStubOps(void);
+
+/*
+ * Dynamically allocate a new PLDHashTable using malloc, initialize it using
+ * PL_DHashTableInit, and return its address. Return null on malloc failure.
+ * Note that the entry storage at table->entryStore will be allocated using
+ * the ops->allocTable callback.
+ */
+PR_EXTERN(PLDHashTable *)
+PL_NewDHashTable(const PLDHashTableOps *ops, void *data, PRUint32 entrySize,
+ PRUint32 capacity);
+
+/*
+ * Finalize table's data, free its entry storage (via table->ops->freeTable),
+ * and return the memory starting at table to the malloc heap.
+ */
+PR_EXTERN(void)
+PL_DHashTableDestroy(PLDHashTable *table);
+
+/*
+ * Initialize table with ops, data, entrySize, and capacity. Capacity is a
+ * guess for the smallest table size at which the table will usually be less
+ * than 75% loaded (the table will grow or shrink as needed; capacity serves
+ * only to avoid inevitable early growth from PL_DHASH_MIN_SIZE).
+ */
+PR_EXTERN(PRBool)
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
+ PRUint32 entrySize, PRUint32 capacity);
+
+/*
+ * Set maximum and minimum alpha for table. The defaults are 0.75 and .25.
+ * maxAlpha must be in [0.5, 0.9375] for the default PL_DHASH_MIN_SIZE; or if
+ * MinSize=PL_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or
+ * else in [0.5, 255.0/256]. minAlpha must be in [0, maxAlpha / 2), so that
+ * we don't shrink on the very next remove after growing a table upon adding
+ * an entry that brings entryCount past maxAlpha * tableSize.
+ */
+PR_IMPLEMENT(void)
+PL_DHashTableSetAlphaBounds(PLDHashTable *table,
+ float maxAlpha,
+ float minAlpha);
+
+/*
+ * Call this macro with k, the number of pointer-sized words wasted per entry
+ * under chaining, to compute the minimum alpha at which double hashing still
+ * beats chaining.
+ */
+#define PL_DHASH_MIN_ALPHA(table, k) \
+ ((float)((table)->entrySize / sizeof(void *) - 1) \
+ / ((table)->entrySize / sizeof(void *) + (k)))
+
+/*
+ * Finalize table's data, free its entry storage using table->ops->freeTable,
+ * and leave its members unchanged from their last live values (which leaves
+ * pointers dangling). If you want to burn cycles clearing table, it's up to
+ * your code to call memset.
+ */
+PR_EXTERN(void)
+PL_DHashTableFinish(PLDHashTable *table);
+
+/*
+ * To consolidate keyHash computation and table grow/shrink code, we use a
+ * single entry point for lookup, add, and remove operations. The operation
+ * codes are declared here, along with codes returned by PLDHashEnumerator
+ * functions, which control PL_DHashTableEnumerate's behavior.
+ */
+typedef enum PLDHashOperator {
+ PL_DHASH_LOOKUP = 0, /* lookup entry */
+ PL_DHASH_ADD = 1, /* add entry */
+ PL_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
+ PL_DHASH_NEXT = 0, /* enumerator says continue */
+ PL_DHASH_STOP = 1 /* enumerator says stop */
+} PLDHashOperator;
+
+/*
+ * To lookup a key in table, call:
+ *
+ * entry = PL_DHashTableOperate(table, key, PL_DHASH_LOOKUP);
+ *
+ * If PL_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies
+ * entry. If PL_DHASH_ENTRY_IS_FREE(entry) is true, key was not found.
+ *
+ * To add an entry identified by key to table, call:
+ *
+ * entry = PL_DHashTableOperate(table, key, PL_DHASH_ADD);
+ *
+ * If entry is null upon return, then either the table is severely overloaded,
+ * and memory can't be allocated for entry storage via table->ops->allocTable;
+ * Or if table->ops->initEntry is non-null, the table->ops->initEntry op may
+ * have returned false.
+ *
+ * Otherwise, entry->keyHash has been set so that PL_DHASH_ENTRY_IS_BUSY(entry)
+ * is true, and it is up to the caller to initialize the key and value parts
+ * of the entry sub-type, if they have not been set already (i.e. if entry was
+ * not already in the table, and if the optional initEntry hook was not used).
+ *
+ * To remove an entry identified by key from table, call:
+ *
+ * (void) PL_DHashTableOperate(table, key, PL_DHASH_REMOVE);
+ *
+ * If key's entry is found, it is cleared (via table->ops->clearEntry) and
+ * the entry is marked so that PL_DHASH_ENTRY_IS_FREE(entry). This operation
+ * returns null unconditionally; you should ignore its return value.
+ */
+PR_EXTERN(PLDHashEntryHdr *) PL_DHASH_FASTCALL
+PL_DHashTableOperate(PLDHashTable *table, const void *key, PLDHashOperator op);
+
+/*
+ * Remove an entry already accessed via LOOKUP or ADD.
+ *
+ * NB: this is a "raw" or low-level routine, intended to be used only where
+ * the inefficiency of a full PL_DHashTableOperate (which rehashes in order
+ * to find the entry given its key) is not tolerable. This function does not
+ * shrink the table if it is underloaded. It does not update stats #ifdef
+ * PL_DHASHMETER, either.
+ */
+PR_EXTERN(void)
+PL_DHashTableRawRemove(PLDHashTable *table, PLDHashEntryHdr *entry);
+
+/*
+ * Enumerate entries in table using etor:
+ *
+ * count = PL_DHashTableEnumerate(table, etor, arg);
+ *
+ * PL_DHashTableEnumerate calls etor like so:
+ *
+ * op = etor(table, entry, number, arg);
+ *
+ * where number is a zero-based ordinal assigned to live entries according to
+ * their order in table->entryStore.
+ *
+ * The return value, op, is treated as a set of flags. If op is PL_DHASH_NEXT,
+ * then continue enumerating. If op contains PL_DHASH_REMOVE, then clear (via
+ * table->ops->clearEntry) and free entry. Then we check whether op contains
+ * PL_DHASH_STOP; if so, stop enumerating and return the number of live entries
+ * that were enumerated so far. Return the total number of live entries when
+ * enumeration completes normally.
+ *
+ * If etor calls PL_DHashTableOperate on table with op != PL_DHASH_LOOKUP, it
+ * must return PL_DHASH_STOP; otherwise undefined behavior results.
+ *
+ * If any enumerator returns PL_DHASH_REMOVE, table->entryStore may be shrunk
+ * or compressed after enumeration, but before PL_DHashTableEnumerate returns.
+ * Such an enumerator therefore can't safely set aside entry pointers, but an
+ * enumerator that never returns PL_DHASH_REMOVE can set pointers to entries
+ * aside, e.g., to avoid copying live entries into an array of the entry type.
+ * Copying entry pointers is cheaper, and safe so long as the caller of such a
+ * "stable" Enumerate doesn't use the set-aside pointers after any call either
+ * to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
+ * grow or shrink entryStore.
+ *
+ * If your enumerator wants to remove certain entries, but set aside pointers
+ * to other entries that it retains, it can use PL_DHashTableRawRemove on the
+ * entries to be removed, returning PL_DHASH_NEXT to skip them. Likewise, if
+ * you want to remove entries, but for some reason you do not want entryStore
+ * to be shrunk or compressed, you can call PL_DHashTableRawRemove safely on
+ * the entry being enumerated, rather than returning PL_DHASH_REMOVE.
+ */
+typedef PLDHashOperator
+(* PR_CALLBACK PLDHashEnumerator)(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg);
+
+PR_EXTERN(PRUint32)
+PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg);
+
+#ifdef PL_DHASHMETER
+#include <stdio.h>
+
+PR_EXTERN(void)
+PL_DHashTableDumpMeter(PLDHashTable *table, PLDHashEnumerator dump, FILE *fp);
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* pldhash_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/.cvsignore b/src/libs/xpcom18a4/xpcom/glue/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/glue/Makefile.in b/src/libs/xpcom18a4/xpcom/glue/Makefile.in
new file mode 100644
index 00000000..a3b1f24d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/Makefile.in
@@ -0,0 +1,86 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+include $(srcdir)/objs.mk
+
+DIRS = standalone
+
+MODULE = xpcom
+LIBRARY_NAME = xpcomglue_s
+
+REQUIRES = $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../build \
+ $(NULL)
+
+CPPSRCS = \
+ $(XPCOM_GLUE_SRC_LCSRCS) \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsIGenericFactory.h \
+ nsIInterfaceRequestorUtils.h \
+ nsISupportsImpl.h \
+ nsISupportsUtils.h \
+ nsIWeakReferenceUtils.h \
+ $(XPCOM_GLUE_SRC_LEXPORTS) \
+ $(NULL)
+
+SDK_LIBRARY = \
+ $(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+# hack to work around objdir bustage
+export::
+ rm -f $(XPCOM_GLUE_SRC_CSRCS:.cpp=.$(OBJ_SUFFIX))
+
+DEFINES += \
+ -D_IMPL_NS_COM
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp
new file mode 100644
index 00000000..cac3c6d4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+
+nsresult
+nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mRawPtr )
+ {
+ status = mRawPtr->QueryInterface(aIID, answer);
+#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+#endif
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ return status;
+ }
+
+nsresult
+nsQueryInterfaceWithError::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mRawPtr )
+ {
+ status = mRawPtr->QueryInterface(aIID, answer);
+#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+#endif
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+
+nsCOMPtr_base::~nsCOMPtr_base()
+ {
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ if ( mRawPtr )
+ NSCAP_RELEASE(this, mRawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_with_AddRef( nsISupports* rawPtr )
+ {
+ if ( rawPtr )
+ NSCAP_ADDREF(this, rawPtr);
+ assign_assuming_AddRef(rawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_from_qi( const nsQueryInterface qi, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( qi(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( qi(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+void**
+nsCOMPtr_base::begin_assignment()
+ {
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h
new file mode 100644
index 00000000..b5a0fd78
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h
@@ -0,0 +1,1405 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCOMPtr_h___
+#define nsCOMPtr_h___
+
+/*
+ Having problems?
+
+ See the User Manual at:
+ http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
+
+
+ nsCOMPtr
+ better than a raw pointer
+ for owning objects
+ -- scc
+*/
+
+
+ // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+ // for |NS_PRECONDITION|
+#endif
+
+#ifndef nsISupportsUtils_h__
+#include "nsISupportsUtils.h"
+ // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
+#endif
+
+#ifndef nscore_h___
+#include "nscore.h"
+ // for |NS_..._CAST|, |NS_COM|
+#endif
+
+
+/*
+ WARNING:
+ This file defines several macros for internal use only. These macros begin with the
+ prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
+ only for cross-platform compatibility, and are subject to change without notice.
+*/
+
+
+#ifdef _MSC_VER
+ #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ // under VC++, we win by inlining StartAssignment
+
+ // Also under VC++, at the highest warning level, we are overwhelmed with warnings
+ // about (unused) inline functions being removed. This is to be expected with
+ // templates, so we disable the warning.
+ #pragma warning( disable: 4514 )
+#endif
+
+#define NSCAP_FEATURE_USE_BASE
+
+#ifdef NS_DEBUG
+ #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
+ #undef NSCAP_FEATURE_USE_BASE
+//#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+#endif
+
+ /*
+ |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is
+ problematic on a select few of our platforms, e.g., QNX. Therefore, I'm providing
+ a mechanism by which these features can be explicitly disabled from the command-line.
+ */
+
+#ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
+ #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
+#endif
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+ // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
+ // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
+ // don't reorder instructions based on aliasing assumptions for
+ // this variable. Fortunately, gcc versions < 3.3 do not do any
+ // optimizations that break nsCOMPtr.
+
+ #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
+#else
+ #define NS_MAY_ALIAS_PTR(t) t*
+#endif
+
+#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
+ #define NSCAP_FEATURE_USE_BASE
+#endif
+
+
+#ifdef HAVE_CPP_BOOL
+ typedef bool NSCAP_BOOL;
+#else
+ typedef PRBool NSCAP_BOOL;
+#endif
+
+
+
+
+ /*
+ The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
+ allow external clients the ability to add logging or other interesting debug facilities.
+ In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
+ provide (e.g., in "nsTraceRefcnt.h") suitable definitions
+
+ #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
+ #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
+ */
+
+#ifndef NSCAP_ADDREF
+ #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
+#endif
+
+#ifndef NSCAP_RELEASE
+ #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
+#endif
+
+ // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
+#ifdef NSCAP_LOG_ASSIGNMENT
+ // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
+ // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
+ // the |nsCOMPtr|.
+ #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
+#else
+ // ...otherwise, just strip it out of the code
+ #define NSCAP_LOG_ASSIGNMENT(this, ptr)
+#endif
+
+#ifndef NSCAP_LOG_RELEASE
+ #define NSCAP_LOG_RELEASE(this, ptr)
+#endif
+
+
+
+
+ /*
+ WARNING:
+ VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
+ in an order that satisfies:
+
+ nsDerivedSafe < nsCOMPtr
+ already_AddRefed < nsCOMPtr
+ nsCOMPtr < nsGetterAddRefs
+
+ The other compilers probably won't complain, so please don't reorder these
+ classes, on pain of breaking 4.2 compatibility.
+ */
+
+
+template <class T>
+class nsDerivedSafe : public T
+ /*
+ No client should ever see or have to type the name of this class. It is the
+ artifact that makes it a compile-time error to call |AddRef| and |Release|
+ on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
+
+ See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
+
+ This type should be a nested class inside |nsCOMPtr<T>|.
+ */
+ {
+ private:
+#ifdef HAVE_CPP_ACCESS_CHANGING_USING
+ using T::AddRef;
+ using T::Release;
+#else
+ nsrefcnt AddRef(void);
+ nsrefcnt Release(void);
+#endif
+
+#if !defined(AIX) && !defined(IRIX)
+ void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED
+ // declaring |operator delete| private makes calling delete on an interface pointer a compile error
+#endif
+
+ nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLEMENTED
+ // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
+
+ /*
+ Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
+ If you see that, that means somebody checked in a [XP]COM interface class that declares an
+ |operator=()|, and that's _bad_. So bad, in fact, that this declaration exists explicitly
+ to stop people from doing it.
+ */
+
+ protected:
+ nsDerivedSafe(); // NOT TO BE IMPLEMENTED
+ /*
+ This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
+ default ctor but inheriting classes without an empty ctor. See bug 209667.
+ */
+ };
+
+#if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
+template <class T>
+nsrefcnt
+nsDerivedSafe<T>::AddRef()
+ {
+ return 0;
+ }
+
+template <class T>
+nsrefcnt
+nsDerivedSafe<T>::Release()
+ {
+ return 0;
+ }
+
+#endif
+
+
+
+template <class T>
+struct already_AddRefed
+ /*
+ ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
+ |AddRef|ing it. You might want to use this as a return type from a function
+ that produces an already |AddRef|ed pointer as a result.
+
+ See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
+
+ This type should be a nested class inside |nsCOMPtr<T>|.
+
+ Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
+ avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
+ case, and perhaps worth the savings in time and space that its specific
+ implementation affords over the more general solution offered by
+ |nsCOMPtr_helper|.
+ */
+ {
+ already_AddRefed( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ {
+ // nothing else to do here
+ }
+
+ T* get() const { return mRawPtr; }
+
+ T* mRawPtr;
+ };
+
+template <class T>
+inline
+const already_AddRefed<T>
+getter_AddRefs( T* aRawPtr )
+ /*
+ ...makes typing easier, because it deduces the template type, e.g.,
+ you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
+ */
+ {
+ return already_AddRefed<T>(aRawPtr);
+ }
+
+template <class T>
+inline
+const already_AddRefed<T>
+getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
+ {
+ return aAlreadyAddRefedPtr;
+ }
+
+template <class T>
+inline
+const already_AddRefed<T>
+dont_AddRef( T* aRawPtr )
+ {
+ return already_AddRefed<T>(aRawPtr);
+ }
+
+template <class T>
+inline
+const already_AddRefed<T>
+dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
+ {
+ return aAlreadyAddRefedPtr;
+ }
+
+
+
+class nsCOMPtr_helper
+ /*
+ An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
+ that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
+ Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
+
+ Here are the rules for a helper:
+ - it implements |operator()| to produce an interface pointer
+ - (except for its name) |operator()| is a valid [XP]COM `getter'
+ - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
+ - it matches the type requested with the supplied |nsIID| argument
+ - its constructor provides an optional |nsresult*| that |operator()| can fill
+ in with an error when it is executed
+
+ See |class nsGetInterface| for an example.
+ */
+ {
+ public:
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
+ };
+
+/*
+ |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
+ avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
+ is called often enough that the codesize savings are big enough to
+ warrant the specialcasing.
+*/
+
+class NS_COM nsQueryInterface
+ {
+ public:
+ nsQueryInterface( nsISupports* aRawPtr )
+ : mRawPtr(aRawPtr)
+ {
+ // nothing else to do here
+ }
+
+ nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsISupports* mRawPtr;
+ };
+
+class NS_COM nsQueryInterfaceWithError
+ {
+ public:
+ nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
+ : mRawPtr(aRawPtr),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsISupports* mRawPtr;
+ nsresult* mErrorPtr;
+ };
+
+inline
+nsQueryInterface
+do_QueryInterface( nsISupports* aRawPtr )
+ {
+ return nsQueryInterface(aRawPtr);
+ }
+
+inline
+nsQueryInterfaceWithError
+do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
+ {
+ return nsQueryInterfaceWithError(aRawPtr, error);
+ }
+
+template <class T>
+inline
+void
+do_QueryInterface( already_AddRefed<T>& )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+template <class T>
+inline
+void
+do_QueryInterface( already_AddRefed<T>&, nsresult* )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+
+
+class nsCOMPtr_base
+ /*
+ ...factors implementation for all template versions of |nsCOMPtr|.
+
+ This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
+ because unlike the
+
+ Here's the way people normally do things like this
+
+ template <class T> class Foo { ... };
+ template <> class Foo<void*> { ... };
+ template <class T> class Foo<T*> : private Foo<void*> { ... };
+ */
+ {
+ public:
+
+ nsCOMPtr_base( nsISupports* rawPtr = 0 )
+ : mRawPtr(rawPtr)
+ {
+ // nothing else to do here
+ }
+
+ NS_COM NS_FASTCALL ~nsCOMPtr_base();
+
+ NS_COM void NS_FASTCALL assign_with_AddRef( nsISupports* );
+ NS_COM void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
+ NS_COM void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
+ NS_COM void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
+ NS_COM void** NS_FASTCALL begin_assignment();
+
+ protected:
+ NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
+
+ void
+ assign_assuming_AddRef( nsISupports* newPtr )
+ {
+ /*
+ |AddRef()|ing the new value (before entering this function) before
+ |Release()|ing the old lets us safely ignore the self-assignment case.
+ We must, however, be careful only to |Release()| _after_ doing the
+ assignment, in case the |Release()| leads to our _own_ destruction,
+ which would, in turn, cause an incorrect second |Release()| of our old
+ pointer. Thank <waterson@netscape.com> for discovering this.
+ */
+ nsISupports* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ NSCAP_LOG_ASSIGNMENT(this, newPtr);
+ NSCAP_LOG_RELEASE(this, oldPtr);
+ if ( oldPtr )
+ NSCAP_RELEASE(this, oldPtr);
+ }
+ };
+
+// template <class T> class nsGetterAddRefs;
+
+template <class T>
+class nsCOMPtr
+#ifdef NSCAP_FEATURE_USE_BASE
+ : private nsCOMPtr_base
+#endif
+ {
+
+#ifdef NSCAP_FEATURE_USE_BASE
+ #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
+#else
+ #define NSCAP_CTOR_BASE(x) mRawPtr(x)
+
+ private:
+ void assign_with_AddRef( nsISupports* );
+ void assign_from_qi( const nsQueryInterface, const nsIID& );
+ void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
+ void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
+ void** begin_assignment();
+
+ void
+ assign_assuming_AddRef( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ NSCAP_LOG_ASSIGNMENT(this, newPtr);
+ NSCAP_LOG_RELEASE(this, oldPtr);
+ if ( oldPtr )
+ NSCAP_RELEASE(this, oldPtr);
+ }
+
+ private:
+ T* mRawPtr;
+#endif
+
+ public:
+ typedef T element_type;
+
+#ifndef NSCAP_FEATURE_USE_BASE
+ ~nsCOMPtr()
+ {
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ if ( mRawPtr )
+ NSCAP_RELEASE(this, mRawPtr);
+ }
+#endif
+
+#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
+ void
+ Assert_NoQueryNeeded()
+ {
+ if ( mRawPtr )
+ {
+ nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
+ NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
+ }
+ }
+
+ #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
+#else
+ #define NSCAP_ASSERT_NO_QUERY_NEEDED()
+#endif
+
+
+ // Constructors
+
+ nsCOMPtr()
+ : NSCAP_CTOR_BASE(0)
+ // default constructor
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ }
+
+ nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
+ : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
+ // copy-constructor
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ }
+
+ nsCOMPtr( T* aRawPtr )
+ : NSCAP_CTOR_BASE(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+ nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
+ : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
+ // construct from |dont_AddRef(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+ nsCOMPtr( const nsQueryInterface qi )
+ : NSCAP_CTOR_BASE(0)
+ // construct from |do_QueryInterface(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi(qi, NS_GET_IID(T));
+ }
+
+ nsCOMPtr( const nsQueryInterfaceWithError& qi )
+ : NSCAP_CTOR_BASE(0)
+ // construct from |do_QueryInterface(expr, &rv)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi_with_error(qi, NS_GET_IID(T));
+ }
+
+ nsCOMPtr( const nsCOMPtr_helper& helper )
+ : NSCAP_CTOR_BASE(0)
+ // ...and finally, anything else we might need to construct from
+ // can exploit the |nsCOMPtr_helper| facility
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_helper(helper, NS_GET_IID(T));
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+
+ // Assignment operators
+
+ nsCOMPtr<T>&
+ operator=( const nsCOMPtr<T>& rhs )
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const already_AddRefed<T>& rhs )
+ // assign from |dont_AddRef(expr)|
+ {
+ assign_assuming_AddRef(rhs.mRawPtr);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const nsQueryInterface rhs )
+ // assign from |do_QueryInterface(expr)|
+ {
+ assign_from_qi(rhs, NS_GET_IID(T));
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const nsQueryInterfaceWithError& rhs )
+ // assign from |do_QueryInterface(expr, &rv)|
+ {
+ assign_from_qi_with_error(rhs, NS_GET_IID(T));
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const nsCOMPtr_helper& rhs )
+ // ...and finally, anything else we might need to assign from
+ // can exploit the |nsCOMPtr_helper| facility.
+ {
+ assign_from_helper(rhs, NS_GET_IID(T));
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ return *this;
+ }
+
+ void
+ swap( nsCOMPtr<T>& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+#ifdef NSCAP_FEATURE_USE_BASE
+ nsISupports* temp = rhs.mRawPtr;
+#else
+ T* temp = rhs.mRawPtr;
+#endif
+ NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ NSCAP_LOG_RELEASE(&rhs, temp);
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
+ }
+
+ void
+ swap( T*& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+#ifdef NSCAP_FEATURE_USE_BASE
+ nsISupports* temp = rhs;
+#else
+ T* temp = rhs;
+#endif
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
+ mRawPtr = temp;
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+
+ // Other pointer operators
+
+ nsDerivedSafe<T>*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
+ Use |get()| _only_ to resolve ambiguity.
+
+ Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
+ */
+ {
+ return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
+ }
+
+ operator nsDerivedSafe<T>*() const
+ /*
+ ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
+ and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
+ that makes an |nsCOMPtr| substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ nsDerivedSafe<T>*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsCOMPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsCOMPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsCOMPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsCOMPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ nsDerivedSafe<T>&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
+ return *get();
+ }
+
+#if 0
+ private:
+ friend class nsGetterAddRefs<T>;
+#endif
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+
+
+ /*
+ Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
+ same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
+ to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
+ to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
+ querying ensues. Clients need to be able to pass around arbitrary interface pointers,
+ without hassles, through intermediary code that doesn't know the exact type.
+ */
+
+NS_SPECIALIZE_TEMPLATE
+class nsCOMPtr<nsISupports>
+ : private nsCOMPtr_base
+ {
+ public:
+ typedef nsISupports element_type;
+
+ // Constructors
+
+ nsCOMPtr()
+ : nsCOMPtr_base(0)
+ // default constructor
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ }
+
+ nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
+ : nsCOMPtr_base(aSmartPtr.mRawPtr)
+ // copy constructor
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ }
+
+ nsCOMPtr( nsISupports* aRawPtr )
+ : nsCOMPtr_base(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
+ }
+
+ nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
+ : nsCOMPtr_base(aSmartPtr.mRawPtr)
+ // construct from |dont_AddRef(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ }
+
+ nsCOMPtr( const nsQueryInterface qi )
+ : nsCOMPtr_base(0)
+ // assign from |do_QueryInterface(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi(qi, NS_GET_IID(nsISupports));
+ }
+
+ nsCOMPtr( const nsQueryInterfaceWithError& qi )
+ : nsCOMPtr_base(0)
+ // assign from |do_QueryInterface(expr, &rv)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
+ }
+
+ nsCOMPtr( const nsCOMPtr_helper& helper )
+ : nsCOMPtr_base(0)
+ // ...and finally, anything else we might need to construct from
+ // can exploit the |nsCOMPtr_helper| facility
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_helper(helper, NS_GET_IID(nsISupports));
+ }
+
+
+ // Assignment operators
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsCOMPtr<nsISupports>& rhs )
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( nsISupports* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const already_AddRefed<nsISupports>& rhs )
+ // assign from |dont_AddRef(expr)|
+ {
+ assign_assuming_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsQueryInterface rhs )
+ // assign from |do_QueryInterface(expr)|
+ {
+ assign_from_qi(rhs, NS_GET_IID(nsISupports));
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsQueryInterfaceWithError& rhs )
+ // assign from |do_QueryInterface(expr, &rv)|
+ {
+ assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsCOMPtr_helper& rhs )
+ // ...and finally, anything else we might need to assign from
+ // can exploit the |nsCOMPtr_helper| facility.
+ {
+ assign_from_helper(rhs, NS_GET_IID(nsISupports));
+ return *this;
+ }
+
+ void
+ swap( nsCOMPtr<nsISupports>& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ nsISupports* temp = rhs.mRawPtr;
+ NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ NSCAP_LOG_RELEASE(&rhs, temp);
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ }
+
+ void
+ swap( nsISupports*& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ nsISupports* temp = rhs;
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ rhs = mRawPtr;
+ mRawPtr = temp;
+ }
+
+
+ // Other pointer operators
+
+ nsDerivedSafe<nsISupports>*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
+ Use |get()| _only_ to resolve ambiguity.
+
+ Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
+ */
+ {
+ return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
+ }
+
+ operator nsDerivedSafe<nsISupports>*() const
+ /*
+ ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
+ and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
+ that makes an |nsCOMPtr| substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ nsDerivedSafe<nsISupports>*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsCOMPtr<nsISupports>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsCOMPtr<nsISupports>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsCOMPtr<nsISupports>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+
+ nsDerivedSafe<nsISupports>&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
+ return *get();
+ }
+
+#if 0
+ private:
+ friend class nsGetterAddRefs<nsISupports>;
+#endif
+
+ nsISupports**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifndef NSCAP_FEATURE_USE_BASE
+template <class T>
+void
+nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
+ {
+ if ( rawPtr )
+ NSCAP_ADDREF(this, rawPtr);
+ assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
+ }
+
+template <class T>
+void
+nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
+ {
+ T* newRawPtr;
+ if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+template <class T>
+void
+nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
+ {
+ T* newRawPtr;
+ if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+template <class T>
+void
+nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
+ {
+ T* newRawPtr;
+ if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+template <class T>
+void**
+nsCOMPtr<T>::begin_assignment()
+ {
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+#endif
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsCOMPtr<T>*
+address_of( const nsCOMPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsCOMPtr<T>*
+address_of( nsCOMPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsCOMPtr<T>*
+address_of( const nsCOMPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsGetterAddRefs
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsCOMPtr<IFoo> fooP;
+ ...->QueryInterface(iid, getter_AddRefs(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
+
+ When initialized with a |nsCOMPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
+ case) can fill in.
+
+ This type should be a nested class inside |nsCOMPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
+ ~nsGetterAddRefs()
+ {
+#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
+ NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
+#endif
+
+#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
+ mTargetSmartPtr.Assert_NoQueryNeeded();
+#endif
+ }
+#endif
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator nsISupports**()
+ {
+ return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsCOMPtr<T>& mTargetSmartPtr;
+ };
+
+
+NS_SPECIALIZE_TEMPLATE
+class nsGetterAddRefs<nsISupports>
+ {
+ public:
+ explicit
+ nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
+ ~nsGetterAddRefs()
+ {
+ NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
+ }
+#endif
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator nsISupports**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ nsISupports*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsCOMPtr<nsISupports>& mTargetSmartPtr;
+ };
+
+
+template <class T>
+inline
+nsGetterAddRefs<T>
+getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsCOMPtr| when
+ ...makes the class |nsGetterAddRefs<T>| invisible.
+ */
+ {
+ return nsGetterAddRefs<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsCOMPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsCOMPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return lhs == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return lhs != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+// This is defined by an autoconf test, but VC++ also has a bug that
+// prevents us from using these. (It also, fortunately, has the bug
+// that we don't need them either.)
+#if defined(_MSC_VER) && (_MSC_VER < 1310)
+#define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+#endif
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsCOMPtr| to |0|
+
+class NSCAP_Zero;
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsCOMPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+ // Comparing any two [XP]COM objects for identity
+
+inline
+NSCAP_BOOL
+SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
+ {
+ return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
+ }
+
+
+
+template <class SourceType, class DestinationType>
+inline
+nsresult
+CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
+ {
+ return CallQueryInterface(aSourcePtr.get(), aDestPtr);
+ }
+
+#endif // !defined(nsCOMPtr_h___)
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp b/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp
new file mode 100644
index 00000000..5733fc36
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsXPCOM_h__
+#include "nsXPCOM.h"
+#endif
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+#include "nsComponentManagerUtils.h"
+#include "nsIServiceManagerUtils.h"
+
+nsresult
+nsCreateInstanceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsCOMPtr<nsIComponentManager> compMgr;
+ nsresult status = NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (compMgr)
+ status = compMgr->CreateInstance(mCID, mOuter, aIID, aInstancePtr);
+ else if (NS_SUCCEEDED(status))
+ status = NS_ERROR_UNEXPECTED;
+
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+nsresult
+nsCreateInstanceByContractID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status;
+ if ( mContractID ) {
+ nsCOMPtr<nsIComponentManager> compMgr;
+ status = NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (compMgr)
+ status = compMgr->CreateInstanceByContractID(mContractID, mOuter,
+ aIID, aInstancePtr);
+ else if (NS_SUCCEEDED(status))
+ status = NS_ERROR_UNEXPECTED;
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if (NS_FAILED(status))
+ *aInstancePtr = 0;
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+
+nsresult
+nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status = NS_ERROR_FAILURE;
+ if ( mServiceManager ) {
+ status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetService(mCID, aIID, (void**)aInstancePtr);
+ }
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+nsresult
+nsGetServiceByContractID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status = NS_ERROR_FAILURE;
+ if ( mServiceManager ) {
+ status = mServiceManager->GetServiceByContractID(mContractID, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetServiceByContractID(mContractID, aIID, (void**)aInstancePtr);
+ }
+
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp b/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp
new file mode 100644
index 00000000..9e947f30
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp
@@ -0,0 +1,119 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsDebug.h"
+#include "nsDebugImpl.h"
+
+static nsIDebug* gDebugObject = nsnull;
+
+// Note: Although the machinery here is similar to nsMemory.cpp, we cannot use
+// NS_ASSERTION macros below because they end up in nsDebug::Assertion and
+// therefore may produce endless recursion.
+
+static NS_METHOD FreeDebugObject(void)
+{
+ NS_IF_RELEASE(gDebugObject);
+ return NS_OK;
+}
+
+#define ENSURE_DEBUGOBJECT \
+ (gDebugObject ? PR_TRUE : (PRBool)(SetupDebugObject() != nsnull))
+
+static nsIDebug* SetupDebugObject()
+{
+ if (!gDebugObject)
+ {
+ NS_GetDebug(&gDebugObject);
+ if (gDebugObject)
+ NS_RegisterXPCOMExitRoutine(FreeDebugObject, 0);
+ }
+ return gDebugObject;
+}
+
+#ifdef XPCOM_GLUE
+nsresult GlueStartupDebug()
+{
+ if (!gDebugObject)
+ {
+ NS_GetDebug(&gDebugObject);
+ if (!gDebugObject)
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+void GlueShutdownDebug()
+{
+ NS_IF_RELEASE(gDebugObject);
+}
+#endif
+
+NS_COM void nsDebug::Abort(const char* aFile, PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+
+ gDebugObject->Abort(aFile, aLine);
+}
+
+NS_COM void nsDebug::Break(const char* aFile, PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+
+ gDebugObject->Break(aFile, aLine);
+}
+
+NS_COM void nsDebug::Warning(const char* aStr,
+ const char* aFile,
+ PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+ gDebugObject->Warning(aStr, aFile, aLine);
+}
+
+NS_COM void nsDebug::Assertion(const char* aStr, const char* aExpr,
+ const char* aFile, PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+ gDebugObject->Assertion(aStr, aExpr, aFile, aLine);
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsDebug.h b/src/libs/xpcom18a4/xpcom/glue/nsDebug.h
new file mode 100644
index 00000000..f2ed4c56
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsDebug.h
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDebug_h___
+#define nsDebug_h___
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsError_h__
+#include "nsError.h"
+#endif
+
+#ifdef DEBUG
+#define NS_DEBUG
+#endif
+
+/**
+ * Namespace for debugging methods. Note that your code must use the
+ * macros defined later in this file so that the debug code can be
+ * conditionally compiled out.
+ */
+
+/* in case this is included by a C file */
+#ifdef __cplusplus
+
+class nsDebug {
+public:
+
+ /**
+ * Log a warning message to the debug log.
+ */
+ static NS_COM void Warning(const char* aMessage,
+ const char* aFile, PRIntn aLine);
+
+ /**
+ * Abort the executing program. This works on all architectures.
+ */
+ static NS_COM void Abort(const char* aFile, PRIntn aLine);
+
+ /**
+ * Break the executing program into the debugger.
+ */
+ static NS_COM void Break(const char* aFile, PRIntn aLine);
+
+ /**
+ * Log an assertion message to the debug log
+ */
+ static NS_COM void Assertion(const char* aStr, const char* aExpr,
+ const char* aFile, PRIntn aLine);
+};
+
+#ifdef DEBUG
+
+/**
+ * Abort the execution of the program if the expression evaluates to
+ * false.
+ *
+ * There is no status value returned from the macro.
+ *
+ * Note that the non-debug version of this macro does <b>not</b>
+ * evaluate the expression argument. Hence side effect statements
+ * as arguments to the macro will yield improper execution in a
+ * non-debug build. For example:
+ *
+ * NS_ABORT_IF_FALSE(0 == foo++, "yikes foo should be zero");
+ *
+ * Note also that the non-debug version of this macro does <b>not</b>
+ * evaluate the message argument.
+ */
+#define NS_ABORT_IF_FALSE(_expr, _msg) \
+ PR_BEGIN_MACRO \
+ if (!(_expr)) { \
+ nsDebug::Assertion(_msg, #_expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Warn if a given condition is false.
+ *
+ * Program execution continues past the usage of this macro.
+ *
+ * Note also that the non-debug version of this macro does <b>not</b>
+ * evaluate the message argument.
+ */
+#define NS_WARN_IF_FALSE(_expr,_msg) \
+ PR_BEGIN_MACRO \
+ if (!(_expr)) { \
+ nsDebug::Assertion(_msg, #_expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Test a precondition for truth. If the expression is not true then
+ * trigger a program failure.
+ */
+#define NS_PRECONDITION(expr, str) \
+ PR_BEGIN_MACRO \
+ if (!(expr)) { \
+ nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Test an assertion for truth. If the expression is not true then
+ * trigger a program failure.
+ */
+#define NS_ASSERTION(expr, str) \
+ PR_BEGIN_MACRO \
+ if (!(expr)) { \
+ nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Test a post-condition for truth. If the expression is not true then
+ * trigger a program failure.
+ */
+#define NS_POSTCONDITION(expr, str) \
+ PR_BEGIN_MACRO \
+ if (!(expr)) { \
+ nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * This macros triggers a program failure if executed. It indicates that
+ * an attempt was made to execute some unimplimented functionality.
+ */
+#define NS_NOTYETIMPLEMENTED(str) \
+ nsDebug::Assertion(str, "NotYetImplemented", __FILE__, __LINE__)
+
+/**
+ * This macros triggers a program failure if executed. It indicates that
+ * an attempt was made to execute some unimplimented functionality.
+ */
+#define NS_NOTREACHED(str) \
+ nsDebug::Assertion(str, "Not Reached", __FILE__, __LINE__)
+
+/**
+ * Log an error message.
+ */
+#define NS_ERROR(str) \
+ nsDebug::Assertion(str, "Error", __FILE__, __LINE__)
+
+/**
+ * Log a warning message.
+ */
+#define NS_WARNING(str) \
+ nsDebug::Warning(str, __FILE__, __LINE__)
+
+/**
+ * Trigger an abort
+ */
+#define NS_ABORT() \
+ nsDebug::Abort(__FILE__, __LINE__)
+
+/**
+ * Cause a break
+ */
+#define NS_BREAK() \
+ nsDebug::Break(__FILE__, __LINE__)
+
+#else /* NS_DEBUG */
+
+/**
+ * The non-debug version of these macros do not evaluate the
+ * expression or the message arguments to the macro.
+ */
+#define NS_ABORT_IF_FALSE(_expr, _msg) /* nothing */
+#define NS_WARN_IF_FALSE(_expr, _msg) /* nothing */
+#define NS_PRECONDITION(expr, str) /* nothing */
+#define NS_ASSERTION(expr, str) /* nothing */
+#define NS_POSTCONDITION(expr, str) /* nothing */
+#define NS_NOTYETIMPLEMENTED(str) /* nothing */
+#define NS_NOTREACHED(str) /* nothing */
+#define NS_ERROR(str) /* nothing */
+#define NS_WARNING(str) /* nothing */
+#define NS_ABORT() /* nothing */
+#define NS_BREAK() /* nothing */
+
+#endif /* ! NS_DEBUG */
+#endif /* __cplusplus */
+
+// Macros for checking the trueness of an expression passed in within an
+// interface implementation. These need to be compiled regardless of the
+// NS_DEBUG flag
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_ENSURE_TRUE(x, ret) \
+ PR_BEGIN_MACRO \
+ if (NS_UNLIKELY(!(x))) { \
+ NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
+ return ret; \
+ } \
+ PR_END_MACRO
+
+#define NS_ENSURE_FALSE(x, ret) \
+ NS_ENSURE_TRUE(!(x), ret)
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for checking results
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_ENSURE_SUCCESS(res, ret) \
+ NS_ENSURE_TRUE(NS_SUCCEEDED(res), ret)
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for checking state and arguments upon entering interface boundaries
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_ENSURE_ARG(arg) \
+ NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_ARG_POINTER(arg) \
+ NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER)
+
+#define NS_ENSURE_ARG_MIN(arg, min) \
+ NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_ARG_MAX(arg, max) \
+ NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_ARG_RANGE(arg, min, max) \
+ NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_STATE(state) \
+ NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED)
+
+#define NS_ENSURE_NO_AGGREGATION(outer) \
+ NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION)
+
+#define NS_ENSURE_PROPER_AGGREGATION(outer, iid) \
+ NS_ENSURE_FALSE(outer && !iid.Equals(NS_GET_IID(nsISupports)), NS_ERROR_INVALID_ARG)
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_CheckThreadSafe(owningThread, msg) \
+ NS_ASSERTION(owningThread == PR_GetCurrentThread(), msg)
+
+#endif /* nsDebug_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp
new file mode 100644
index 00000000..2d791943
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp
@@ -0,0 +1,547 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+// DO NOT COPY THIS CODE INTO YOUR SOURCE! USE NS_IMPL_NSGETMODULE()
+
+#include "nsGenericFactory.h"
+#include "nsMemory.h"
+#include "nsCOMPtr.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+
+#ifdef XPCOM_GLUE
+#include "nsXPCOMGlue.h"
+#include "nsXPCOMPrivate.h"
+#else
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsINativeComponentLoader.h"
+#endif
+
+nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info)
+ : mInfo(info)
+{
+ if (mInfo && mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this);
+}
+
+nsGenericFactory::~nsGenericFactory()
+{
+ if (mInfo) {
+ if (mInfo->mFactoryDestructor)
+ mInfo->mFactoryDestructor();
+ if (mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = 0;
+ }
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsGenericFactory,
+ nsIGenericFactory,
+ nsIFactory,
+ nsIClassInfo)
+
+NS_IMETHODIMP nsGenericFactory::CreateInstance(nsISupports *aOuter,
+ REFNSIID aIID, void **aResult)
+{
+ if (mInfo->mConstructor) {
+ return mInfo->mConstructor(aOuter, aIID, aResult);
+ }
+
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+}
+
+NS_IMETHODIMP nsGenericFactory::LockFactory(PRBool aLock)
+{
+ // XXX do we care if (mInfo->mFlags & THREADSAFE)?
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetInterfaces(PRUint32 *countp,
+ nsIID* **array)
+{
+ if (!mInfo->mGetInterfacesProc) {
+ *countp = 0;
+ *array = nsnull;
+ return NS_OK;
+ }
+ return mInfo->mGetInterfacesProc(countp, array);
+}
+
+NS_IMETHODIMP nsGenericFactory::GetHelperForLanguage(PRUint32 language,
+ nsISupports **helper)
+{
+ if (mInfo->mGetLanguageHelperProc)
+ return mInfo->mGetLanguageHelperProc(language, helper);
+ *helper = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetContractID(char **aContractID)
+{
+ if (mInfo->mContractID) {
+ *aContractID = (char *)nsMemory::Alloc(strlen(mInfo->mContractID) + 1);
+ if (!*aContractID)
+ return NS_ERROR_OUT_OF_MEMORY;
+ strcpy(*aContractID, mInfo->mContractID);
+ } else {
+ *aContractID = nsnull;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetClassDescription(char * *aClassDescription)
+{
+ if (mInfo->mDescription) {
+ *aClassDescription = (char *)
+ nsMemory::Alloc(strlen(mInfo->mDescription) + 1);
+ if (!*aClassDescription)
+ return NS_ERROR_OUT_OF_MEMORY;
+ strcpy(*aClassDescription, mInfo->mDescription);
+ } else {
+ *aClassDescription = nsnull;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetClassID(nsCID * *aClassID)
+{
+ *aClassID =
+ NS_REINTERPRET_CAST(nsCID*,
+ nsMemory::Clone(&mInfo->mCID, sizeof mInfo->mCID));
+ if (! *aClassID)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetClassIDNoAlloc(nsCID *aClassID)
+{
+ *aClassID = mInfo->mCID;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetImplementationLanguage(PRUint32 *langp)
+{
+ *langp = nsIProgrammingLanguage::CPLUSPLUS;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetFlags(PRUint32 *flagsp)
+{
+ *flagsp = mInfo->mFlags;
+ return NS_OK;
+}
+
+// nsIGenericFactory: component-info accessors
+NS_IMETHODIMP nsGenericFactory::SetComponentInfo(const nsModuleComponentInfo *info)
+{
+ if (mInfo && mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = 0;
+ mInfo = info;
+ if (mInfo && mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetComponentInfo(const nsModuleComponentInfo **infop)
+{
+ *infop = mInfo;
+ return NS_OK;
+}
+
+NS_METHOD nsGenericFactory::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ // sorry, aggregation not spoken here.
+ nsresult res = NS_ERROR_NO_AGGREGATION;
+ if (outer == NULL) {
+ nsGenericFactory* factory = new nsGenericFactory;
+ if (factory != NULL) {
+ res = factory->QueryInterface(aIID, aInstancePtr);
+ if (res != NS_OK)
+ delete factory;
+ } else {
+ res = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ return res;
+}
+
+NS_COM nsresult
+NS_NewGenericFactory(nsIGenericFactory* *result,
+ const nsModuleComponentInfo *info)
+{
+ nsresult rv;
+ nsIGenericFactory* fact;
+ rv = nsGenericFactory::Create(NULL, NS_GET_IID(nsIGenericFactory), (void**)&fact);
+ if (NS_FAILED(rv)) return rv;
+ rv = fact->SetComponentInfo(info);
+ if (NS_FAILED(rv)) goto error;
+ *result = fact;
+ return rv;
+
+ error:
+ NS_RELEASE(fact);
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsGenericModule::nsGenericModule(const char* moduleName, PRUint32 componentCount,
+ const nsModuleComponentInfo* components,
+ nsModuleConstructorProc ctor,
+ nsModuleDestructorProc dtor,
+ const char** aLibDepends)
+ : mInitialized(PR_FALSE),
+ mModuleName(moduleName),
+ mComponentCount(componentCount),
+ mComponents(components),
+ mFactoriesNotToBeRegistered(nsnull),
+ mCtor(ctor),
+ mDtor(dtor),
+ mLibraryDependencies(aLibDepends)
+{
+}
+
+nsGenericModule::~nsGenericModule()
+{
+ Shutdown();
+
+#ifdef XPCOM_GLUE
+ XPCOMGlueShutdown();
+#endif
+
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsGenericModule, nsIModule)
+
+nsresult
+nsGenericModule::AddFactoryNode(nsIGenericFactory* fact)
+{
+ if (!fact)
+ return NS_ERROR_FAILURE;
+
+ FactoryNode *node = new FactoryNode(fact, mFactoriesNotToBeRegistered);
+ if (!node)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mFactoriesNotToBeRegistered = node;
+ return NS_OK;
+}
+
+
+// Perform our one-time intialization for this module
+nsresult
+nsGenericModule::Initialize(nsIComponentManager *compMgr)
+{
+ nsresult rv;
+
+ if (mInitialized) {
+ return NS_OK;
+ }
+
+ if (mCtor) {
+ rv = mCtor(this);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+
+#ifdef XPCOM_GLUE
+ rv = XPCOMGlueStartup(".");
+ if (NS_FAILED(rv))
+ return rv;
+#endif
+
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(compMgr, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Eagerly populate factory/class object hash for entries
+ // without constructors. If we didn't, the class object would
+ // never get created. Also create the factory, which doubles
+ // as the class object, if the EAGER_CLASSINFO flag was given.
+ // This allows objects to be created (within their modules)
+ // via operator new rather than CreateInstance, yet still be
+ // QI'able to nsIClassInfo.
+ const nsModuleComponentInfo* desc = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ if (!desc->mConstructor ||
+ (desc->mFlags & nsIClassInfo::EAGER_CLASSINFO)) {
+ nsCOMPtr<nsIGenericFactory> fact;
+ nsresult rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
+ if (NS_FAILED(rv)) return rv;
+
+ // if we don't have a mConstructor, then we should not populate
+ // the component manager.
+ if (!desc->mConstructor) {
+ rv = AddFactoryNode(fact);
+ } else {
+ rv = registrar->RegisterFactory(desc->mCID,
+ desc->mDescription,
+ desc->mContractID,
+ fact);
+ }
+ if (NS_FAILED(rv)) return rv;
+ }
+ desc++;
+ }
+
+ mInitialized = PR_TRUE;
+ return NS_OK;
+}
+
+// Shutdown this module, releasing all of the module resources
+void
+nsGenericModule::Shutdown()
+{
+ // Free cached factories that were not registered.
+ FactoryNode* node;
+ while (mFactoriesNotToBeRegistered)
+ {
+ node = mFactoriesNotToBeRegistered->mNext;
+ delete mFactoriesNotToBeRegistered;
+ mFactoriesNotToBeRegistered = node;
+ }
+
+ if (mInitialized) {
+ mInitialized = PR_FALSE;
+
+ if (mDtor)
+ mDtor(this);
+ }
+}
+
+// Create a factory object for creating instances of aClass.
+NS_IMETHODIMP
+nsGenericModule::GetClassObject(nsIComponentManager *aCompMgr,
+ const nsCID& aClass,
+ const nsIID& aIID,
+ void** r_classObj)
+{
+ nsresult rv;
+
+ // Defensive programming: Initialize *r_classObj in case of error below
+ if (!r_classObj) {
+ return NS_ERROR_INVALID_POINTER;
+ }
+ *r_classObj = NULL;
+
+ // Do one-time-only initialization if necessary
+ if (!mInitialized) {
+ rv = Initialize(aCompMgr);
+ if (NS_FAILED(rv)) {
+ // Initialization failed! yikes!
+ return rv;
+ }
+ }
+
+ // Choose the appropriate factory, based on the desired instance
+ // class type (aClass).
+ const nsModuleComponentInfo* desc = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ if (desc->mCID.Equals(aClass)) {
+ nsCOMPtr<nsIGenericFactory> fact;
+ rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
+ if (NS_FAILED(rv)) return rv;
+ return fact->QueryInterface(aIID, r_classObj);
+ }
+ desc++;
+ }
+ // not found in descriptions
+#ifndef XPCOM_GLUE
+#ifdef DEBUG
+ char* cs = aClass.ToString();
+ fprintf(stderr, "+++ nsGenericModule %s: unable to create factory for %s\n", mModuleName, cs);
+ // leak until we resolve the nsID Allocator.
+ // nsCRT::free(cs);
+#endif // XXX put in stop-gap so that we don't search for this one again
+#endif
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+}
+
+NS_IMETHODIMP
+nsGenericModule::RegisterSelf(nsIComponentManager *aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation,
+ const char* componentType)
+{
+ nsresult rv = NS_OK;
+
+#ifdef DEBUG
+ fprintf(stderr, "*** Registering %s components (all right -- a generic module!)\n", mModuleName);
+#endif
+
+ const nsModuleComponentInfo* cp = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ // Register the component only if it has a constructor
+ if (cp->mConstructor) {
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
+ if (registrar)
+ rv = registrar->RegisterFactoryLocation(cp->mCID,
+ cp->mDescription,
+ cp->mContractID,
+ aPath,
+ registryLocation,
+ componentType);
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ fprintf(stderr, "nsGenericModule %s: unable to register %s component => %x\n",
+ mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
+#endif
+ break;
+ }
+ }
+ // Call the registration hook of the component, if any
+ if (cp->mRegisterSelfProc)
+ {
+ rv = cp->mRegisterSelfProc(aCompMgr, aPath, registryLocation,
+ componentType, cp);
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ fprintf(stderr, "nsGenericModule %s: Register hook for %s component returned error => %x\n",
+ mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
+#endif
+ break;
+ }
+ }
+ cp++;
+ }
+
+#ifndef XPCOM_GLUE
+ // We want to tell the component loader of any dependencies
+ // we have so that the loader can resolve them for us.
+
+ nsCOMPtr<nsINativeComponentLoader> loader = do_GetInterface(aCompMgr);
+ if (loader && mLibraryDependencies)
+ {
+ for(int i=0; mLibraryDependencies[i] != nsnull &&
+ mLibraryDependencies[i][0] != '\0'; i++)
+ {
+ loader->AddDependentLibrary(aPath,
+ mLibraryDependencies[i]);
+ }
+ loader = nsnull;
+ }
+#endif
+
+
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsGenericModule::UnregisterSelf(nsIComponentManager* aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation)
+{
+#ifdef DEBUG
+ fprintf(stderr, "*** Unregistering %s components (all right -- a generic module!)\n", mModuleName);
+#endif
+ const nsModuleComponentInfo* cp = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ // Call the unregistration hook of the component, if any
+ if (cp->mUnregisterSelfProc)
+ {
+ cp->mUnregisterSelfProc(aCompMgr, aPath, registryLocation, cp);
+ }
+
+ // Unregister the component
+ nsresult rv;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
+ if (registrar)
+ rv = registrar->UnregisterFactoryLocation(cp->mCID, aPath);
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ fprintf(stderr, "nsGenericModule %s: unable to unregister %s component => %x\n",
+ mModuleName, cp->mDescription, rv);
+#endif
+ }
+ cp++;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
+{
+ if (!okToUnload) {
+ return NS_ERROR_INVALID_POINTER;
+ }
+ *okToUnload = PR_FALSE;
+ return NS_ERROR_FAILURE;
+}
+
+NS_COM nsresult
+NS_NewGenericModule2(nsModuleInfo* info, nsIModule* *result)
+{
+ nsresult rv = NS_OK;
+
+ // Create and initialize the module instance
+ nsGenericModule *m =
+ new nsGenericModule(info->mModuleName, info->mCount, info->mComponents,
+ info->mCtor, info->mDtor, info->mLibraryDependencies);
+
+ if (!m)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Increase refcnt and store away nsIModule interface to m in result
+ NS_ADDREF(*result = m);
+ return rv;
+}
+
+NS_COM nsresult
+NS_NewGenericModule(const char* moduleName,
+ PRUint32 componentCount,
+ nsModuleComponentInfo* components,
+ nsModuleDestructorProc dtor,
+ nsIModule* *result)
+{
+ nsModuleInfo info;
+ memset(&info, 0, sizeof(info));
+
+ info.mVersion = NS_MODULEINFO_VERSION;
+ info.mModuleName = moduleName;
+ info.mComponents = components;
+ info.mCount = componentCount;
+ info.mDtor = dtor;
+ info.mLibraryDependencies = nsnull;
+
+ return NS_NewGenericModule2(&info, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h
new file mode 100644
index 00000000..64afd0de
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsGenericFactory_h___
+#define nsGenericFactory_h___
+
+#include "nsCOMPtr.h"
+#include "nsIGenericFactory.h"
+#include "nsIClassInfo.h"
+
+/**
+ * Most factories follow this simple pattern, so why not just use a function
+ * pointer for most creation operations?
+ */
+class nsGenericFactory : public nsIGenericFactory, public nsIClassInfo {
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_GENERICFACTORY_CID);
+
+ nsGenericFactory(const nsModuleComponentInfo *info = NULL);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICLASSINFO
+
+ /* nsIGenericFactory methods */
+ NS_IMETHOD SetComponentInfo(const nsModuleComponentInfo *info);
+ NS_IMETHOD GetComponentInfo(const nsModuleComponentInfo **infop);
+
+ NS_IMETHOD CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_IMETHOD LockFactory(PRBool aLock);
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+private:
+ ~nsGenericFactory();
+
+ const nsModuleComponentInfo *mInfo;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#include "nsIModule.h"
+#include "plhash.h"
+
+class nsGenericModule : public nsIModule
+{
+public:
+ nsGenericModule(const char* moduleName,
+ PRUint32 componentCount,
+ const nsModuleComponentInfo* components,
+ nsModuleConstructorProc ctor,
+ nsModuleDestructorProc dtor,
+ const char** alibDepends);
+
+private:
+ ~nsGenericModule();
+
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIMODULE
+
+ struct FactoryNode
+ {
+ FactoryNode(nsIGenericFactory* fact, FactoryNode* next)
+ {
+ mFactory = fact;
+ mNext = next;
+ }
+ ~FactoryNode(){}
+
+ nsCOMPtr<nsIGenericFactory> mFactory;
+ FactoryNode* mNext;
+ };
+
+
+
+
+protected:
+ nsresult Initialize(nsIComponentManager* compMgr);
+
+ void Shutdown();
+ nsresult AddFactoryNode(nsIGenericFactory* fact);
+
+ PRBool mInitialized;
+ const char* mModuleName;
+ PRUint32 mComponentCount;
+ const nsModuleComponentInfo* mComponents;
+ FactoryNode* mFactoriesNotToBeRegistered;
+ nsModuleConstructorProc mCtor;
+ nsModuleDestructorProc mDtor;
+ const char** mLibraryDependencies;
+};
+
+#endif /* nsGenericFactory_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h b/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h
new file mode 100644
index 00000000..82506e8e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h
@@ -0,0 +1,480 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIGenericFactory_h___
+#define nsIGenericFactory_h___
+
+#include "nsIFactory.h"
+#include "nsIModule.h"
+#include "nsIClassInfo.h"
+#ifdef HAVE_DEPENDENT_LIBS
+#include "dependentLibs.h"
+#endif
+
+// {3bc97f01-ccdf-11d2-bab8-b548654461fc}
+#define NS_GENERICFACTORY_CID \
+ { 0x3bc97f01, 0xccdf, 0x11d2, \
+ { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } }
+
+// {3bc97f00-ccdf-11d2-bab8-b548654461fc}
+#define NS_IGENERICFACTORY_IID \
+ { 0x3bc97f00, 0xccdf, 0x11d2, \
+ { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } }
+
+#define NS_GENERICFACTORY_CONTRACTID "@mozilla.org/generic-factory;1"
+#define NS_GENERICFACTORY_CLASSNAME "Generic Factory"
+
+struct nsModuleComponentInfo; // forward declaration
+
+/**
+ * Provides a Generic nsIFactory implementation that can be used by
+ * DLLs with very simple factory needs.
+ */
+class nsIGenericFactory : public nsIFactory {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IGENERICFACTORY_IID)
+
+ NS_IMETHOD SetComponentInfo(const nsModuleComponentInfo *info) = 0;
+ NS_IMETHOD GetComponentInfo(const nsModuleComponentInfo **infop) = 0;
+};
+
+NS_COM nsresult
+NS_NewGenericFactory(nsIGenericFactory **result,
+ const nsModuleComponentInfo *info);
+
+
+/** Component Callbacks **/
+
+ /**
+ * NSConstructorProcPtr
+ *
+ * This function will be used by the generic factory to create an
+ * instance of the given CID.
+ *
+ * @param aOuter : Pointer to a component that wishes to be aggregated
+ * in the resulting instance. This will be nsnull if no
+ * aggregation is requested.
+ * @param iid : The IID of the interface being requested in
+ * the component which is being currently created.
+ * @param result : [out] Pointer to the newly created instance, if successful.
+ *
+ * @return NS_OK Component successfully created and the interface
+ * being requested was successfully returned in result.
+ * NS_NOINTERFACE Interface not accessible.
+ * NS_ERROR_NO_AGGREGATION if an 'outer' object is supplied, but the
+ * component is not aggregatable.
+ * NS_ERROR* Method failure.
+ **/
+typedef NS_CALLBACK(NSConstructorProcPtr)(nsISupports *aOuter,
+ REFNSIID aIID,
+ void **aResult);
+
+/**
+ * NSRegisterSelfProcPtr
+ *
+ * One time registration call back. Allows you to perform registration
+ * specific activity like adding yourself to a category.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader defines.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aType : Component Type of CID aClass. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aInfo : Pointer to array of nsModuleComponentInfo
+ *
+ * @param aInfo
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+ **/
+typedef NS_CALLBACK(NSRegisterSelfProcPtr)(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *aLoaderStr,
+ const char *aType,
+ const nsModuleComponentInfo *aInfo);
+
+/**
+ * NSUnregisterSelfProcPtr
+ *
+ * One time unregistration call back. Allows you to perform unregistration
+ * specific activity like removing yourself from a category.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader defines.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location
+ * @param aInfo : Pointer to array of nsModuleComponentInfo
+ *
+ * @param aInfo
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+
+ **/
+typedef NS_CALLBACK(NSUnregisterSelfProcPtr)(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *aLoaderStr,
+ const nsModuleComponentInfo *aInfo);
+
+/**
+ * NSFactoryDestructorProcPtr
+ *
+ * This function will be called when the factory is being destroyed.
+ *
+ **/
+typedef NS_CALLBACK(NSFactoryDestructorProcPtr)(void);
+
+
+/**
+ * NSGetInterfacesProcPtr
+ *
+ * This function is used to implement class info.
+ *
+ * Get an ordered list of the interface ids that instances of the class
+ * promise to implement. Note that nsISupports is an implicit member
+ * of any such list and need not be included.
+ *
+ * Should set *count = 0 and *array = null and return NS_OK if getting the
+ * list is not supported.
+ *
+ * @see nsIClassInfo.idl
+ **/
+typedef NS_CALLBACK(NSGetInterfacesProcPtr)(PRUint32 *countp,
+ nsIID* **array);
+
+/**
+ * NSGetLanguageHelperProcPtr
+ *
+ * This function is used to implement class info.
+ *
+ * Get a language mapping specific helper object that may assist in using
+ * objects of this class in a specific lanaguage. For instance, if asked
+ * for the helper for nsIProgrammingLanguage::JAVASCRIPT this might return
+ * an object that can be QI'd into the nsIXPCScriptable interface to assist
+ * XPConnect in supplying JavaScript specific behavior to callers of the
+ * instance object.
+ *
+ * @see: nsIClassInfo.idl, nsIProgrammingLanguage.idl
+ *
+ * Should return null if no helper available for given language.
+ **/
+typedef NS_CALLBACK(NSGetLanguageHelperProcPtr)(PRUint32 language,
+ nsISupports **helper);
+
+/**
+ * nsModuleComponentInfo
+ *
+ * Use this type to define a list of module component info to pass to
+ * NS_NewGenericModule.
+ *
+ * @param mDescription : Class Name of given object
+ * @param mCID : CID of given object
+ * @param mContractID : Contract ID of given object
+ * @param mConstructor : Constructor of given object
+ * @param mRegisterSelfProc : (optional) Registration Callback
+ * @param mUnregisterSelfProc : (optional) Unregistration Callback
+ * @param mFactoryDestructor : (optional) Destruction Callback
+ * @param mGetInterfacesProc : (optional) Interfaces Callback
+ * @param mGetLanguageHelperProc : (optional) Language Helper Callback
+ * @param mClassInfoGlobal : (optional) Global Class Info of given object
+ * @param mFlags : (optional) Class Info Flags @see nsIClassInfo
+ *
+ * E.g.:
+ * static nsModuleComponentInfo components[] = { ... };
+ *
+ * See xpcom/sample/nsSampleModule.cpp for more info.
+ */
+struct nsModuleComponentInfo {
+ const char* mDescription;
+ nsCID mCID;
+ const char* mContractID;
+ NSConstructorProcPtr mConstructor;
+ NSRegisterSelfProcPtr mRegisterSelfProc;
+ NSUnregisterSelfProcPtr mUnregisterSelfProc;
+ NSFactoryDestructorProcPtr mFactoryDestructor;
+ NSGetInterfacesProcPtr mGetInterfacesProc;
+ NSGetLanguageHelperProcPtr mGetLanguageHelperProc;
+ nsIClassInfo ** mClassInfoGlobal;
+ PRUint32 mFlags;
+};
+
+
+/** Module Callbacks **/
+
+
+/**
+ * nsModuleConstructorProc
+ *
+ * This function is called when the module is first being constructed.
+ * @param self module which is being constructed.
+ *
+ * @return NS_OK Construction successful.
+ * NS_ERROR* Method failure which will result in module not being
+ * loaded.
+ **/
+typedef nsresult (PR_CALLBACK *nsModuleConstructorProc) (nsIModule *self);
+
+
+/**
+ * nsModuleDestructorProc
+ *
+ * This function is called when the module is being destroyed.
+ * @param self module which is being destroyed.
+ *
+ **/
+typedef void (PR_CALLBACK *nsModuleDestructorProc) (nsIModule *self);
+
+/**
+ * nsModuleInfo
+ *
+ * Use this structure to define meta-information about the module
+ * itself, including the name, its components, and an optional
+ * module-level initialization or shutdown routine.
+ *
+ * @param mVersion : Module Info Version
+ * @param mModuleName : Module Name
+ * @param mComponents : Array of Components
+ * @param mCount : Count of mComponents
+ * @param mCtor : Module user defined constructor
+ * @param mDtor : Module user defined destructor
+ * @param mLibraryDependencies : array of library which this module is
+ * dependent on.
+ *
+ **/
+
+struct nsModuleInfo {
+ PRUint32 mVersion;
+ const char* mModuleName;
+ const nsModuleComponentInfo* mComponents;
+ PRUint32 mCount;
+ nsModuleConstructorProc mCtor;
+ nsModuleDestructorProc mDtor;
+ const char** mLibraryDependencies;
+};
+
+/**
+ * Rev this if you change the nsModuleInfo, and are worried about
+ * binary compatibility. (Ostensibly fix NS_NewGenericModule2() to deal
+ * with older rev's at the same time.)
+ */
+#define NS_MODULEINFO_VERSION 0x00015000UL // 1.5
+
+/**
+ * Create a new generic module. Use the NS_IMPL_NSGETMODULE macro, or
+ * one of its relatives, rather than using this directly.
+ */
+NS_COM nsresult
+NS_NewGenericModule2(nsModuleInfo *info, nsIModule* *result);
+
+/**
+ * Obsolete. Use NS_NewGenericModule2() instead.
+ */
+NS_COM nsresult
+NS_NewGenericModule(const char* moduleName,
+ PRUint32 componentCount,
+ nsModuleComponentInfo* components,
+ nsModuleDestructorProc dtor,
+ nsIModule* *result);
+
+#if defined(XPCOM_TRANSLATE_NSGM_ENTRY_POINT)
+# define NS_MODULEINFO nsModuleInfo
+# define NSMODULEINFO(_name) _name##_gModuleInfo
+# define NSGETMODULE_ENTRY_POINT(_info)
+# define NSDEPENDENT_LIBS(_name) const char* _name##_gDependlibs[]={DEPENDENT_LIBS "\0"};
+# define NSDEPENDENT_LIBS_NAME(_name) _name##_gDependlibs
+#else
+# define NS_MODULEINFO static nsModuleInfo
+# define NSMODULEINFO(_name) gModuleInfo
+# define NSDEPENDENT_LIBS(_name) static const char* gDependlibs[]={DEPENDENT_LIBS "\0"};
+# define NSDEPENDENT_LIBS_NAME(_name) gDependlibs
+# define NSGETMODULE_ENTRY_POINT(_info) \
+extern "C" NS_EXPORT nsresult \
+NSGetModule(nsIComponentManager *servMgr, \
+ nsIFile* location, \
+ nsIModule** result) \
+{ \
+ (void)servMgr; \
+ (void)location; \
+ return NS_NewGenericModule2(&(_info), result); \
+}
+#endif
+
+/**
+ * Ease of use Macros which define NSGetModule for your component.
+ * See xpcom/sample/nsSampleModule.cpp for more info.
+ *
+ **/
+
+#define NS_IMPL_NSGETMODULE(_name, _components) \
+ NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, nsnull, nsnull)
+
+#define NS_IMPL_NSGETMODULE_WITH_CTOR(_name, _components, _ctor) \
+ NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, nsnull)
+
+#define NS_IMPL_NSGETMODULE_WITH_DTOR(_name, _components, _dtor) \
+ NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, nsnull, _dtor)
+
+#ifndef DEPENDENT_LIBS
+
+#define NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, _dtor) \
+NS_MODULEINFO NSMODULEINFO(_name) = { \
+ NS_MODULEINFO_VERSION, \
+ (#_name), \
+ (_components), \
+ (sizeof(_components) / sizeof(_components[0])), \
+ (_ctor), \
+ (_dtor), \
+ (nsnull) \
+}; \
+NSGETMODULE_ENTRY_POINT(NSMODULEINFO(_name))
+
+#else // DEPENDENT_LIBS
+
+#define NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, _dtor) \
+NSDEPENDENT_LIBS(_name) \
+NS_MODULEINFO NSMODULEINFO(_name) = { \
+ NS_MODULEINFO_VERSION, \
+ (#_name), \
+ (_components), \
+ (sizeof(_components) / sizeof(_components[0])), \
+ (_ctor), \
+ (_dtor), \
+ (NSDEPENDENT_LIBS_NAME(_name)) \
+}; \
+NSGETMODULE_ENTRY_POINT(NSMODULEINFO(_name))
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define NS_GENERIC_FACTORY_CONSTRUCTOR(_InstanceClass) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ NS_NEWXPCOM(inst, _InstanceClass); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ NS_ADDREF(inst); \
+ rv = inst->QueryInterface(aIID, aResult); \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+} \
+
+
+#define NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ NS_NEWXPCOM(inst, _InstanceClass); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ NS_ADDREF(inst); \
+ rv = inst->_InitMethod(); \
+ if(NS_SUCCEEDED(rv)) { \
+ rv = inst->QueryInterface(aIID, aResult); \
+ } \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+} \
+
+// 'Constructor' that uses an existing getter function that gets a singleton.
+// NOTE: assumes that getter does an AddRef - so additional AddRef is not done.
+#define NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(_InstanceClass, _GetterProc) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ inst = _GetterProc(); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ /* NS_ADDREF(inst); */ \
+ rv = inst->QueryInterface(aIID, aResult); \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+} \
+
+#endif /* nsIGenericFactory_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp
new file mode 100644
index 00000000..b440c342
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+
+nsresult
+nsGetInterface::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status;
+
+ if ( mSource )
+ {
+ nsCOMPtr<nsIInterfaceRequestor> factoryPtr = do_QueryInterface(mSource, &status);
+ NS_ASSERTION(factoryPtr, "Did you know you were calling |do_GetInterface()| on an object that doesn't support the |nsIInterfaceRequestor| interface?");
+
+ if ( factoryPtr )
+ status = factoryPtr->GetInterface(aIID, aInstancePtr);
+
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h
new file mode 100644
index 00000000..e971dd4b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h
@@ -0,0 +1,83 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsInterfaceRequestorUtils_h
+#define __nsInterfaceRequestorUtils_h
+
+#include "nsCOMPtr.h"
+
+// a type-safe shortcut for calling the |GetInterface()| member function
+// T must inherit from nsIInterfaceRequestor, but the cast may be ambiguous.
+template <class T, class DestinationType>
+inline
+nsresult
+CallGetInterface( T* aSource, DestinationType** aDestination )
+ {
+ NS_PRECONDITION(aSource, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return aSource->GetInterface(NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+ }
+
+class NS_COM nsGetInterface : public nsCOMPtr_helper
+ {
+ public:
+ nsGetInterface( nsISupports* aSource, nsresult* error )
+ : mSource(aSource),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ nsCOMPtr<nsISupports> mSource;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsGetInterface
+do_GetInterface( nsISupports* aSource, nsresult* error = 0 )
+ {
+ return nsGetInterface(aSource, error);
+ }
+
+#endif // __nsInterfaceRequestorUtils_h
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h b/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h
new file mode 100644
index 00000000..588a2c73
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h
@@ -0,0 +1,1246 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#ifndef nsISupportsImpl_h__
+#define nsISupportsImpl_h__
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsISupportsBase_h__
+#include "nsISupportsBase.h"
+#endif
+
+#include "prthread.h" /* needed for thread-safety checks */
+#include "pratom.h" /* needed for PR_AtomicIncrement and PR_AtomicDecrement */
+
+#include "nsDebug.h"
+#include "nsTraceRefcnt.h"
+#ifdef VBOX
+# include "iprt/asm.h"
+# include "iprt/assert.h"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Macros to help detect thread-safety:
+
+#if defined(NS_DEBUG)
+
+class nsAutoOwningThread {
+public:
+ nsAutoOwningThread() { mThread = PR_GetCurrentThread(); }
+ void *GetThread() const { return mThread; }
+
+private:
+ void *mThread;
+};
+
+#define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread;
+#define NS_ASSERT_OWNINGTHREAD(_class) \
+ NS_CheckThreadSafe(_mOwningThread.GetThread(), #_class " not thread-safe")
+
+#else // !(defined(NS_DEBUG))
+
+#define NS_DECL_OWNINGTHREAD /* nothing */
+#define NS_ASSERT_OWNINGTHREAD(_class) ((void)0)
+
+#endif // !(defined(NS_DEBUG))
+
+class nsAutoRefCnt {
+
+ public:
+ nsAutoRefCnt() : mValue(0)
+#ifdef VBOX
+ , mState(0)
+#endif
+ {}
+ nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
+
+ // only support prefix increment/decrement
+ nsrefcnt operator++() { return ++mValue; }
+ nsrefcnt operator--() { return --mValue; }
+
+ nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
+ operator nsrefcnt() const { return mValue; }
+ nsrefcnt get() const { return mValue; }
+#ifdef VBOX
+ nsrefcnt *ref() { return &mValue; }
+ PRUint32 getState() const { return mState; }
+ PRUint32 *refState() { return &mState; }
+#endif
+ private:
+ // do not define these to enforce the faster prefix notation
+ nsrefcnt operator++(int);
+ nsrefcnt operator--(int);
+ nsrefcnt mValue;
+#ifdef VBOX
+ PRUint32 mState;
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Declare the reference count variable and the implementations of the
+ * AddRef and QueryInterface methods.
+ */
+
+#define NS_DECL_ISUPPORTS \
+public: \
+ NS_IMETHOD QueryInterface(REFNSIID aIID, \
+ void** aInstancePtr); \
+ NS_IMETHOD_(nsrefcnt) AddRef(void); \
+ NS_IMETHOD_(nsrefcnt) Release(void); \
+protected: \
+ nsAutoRefCnt mRefCnt; \
+ NS_DECL_OWNINGTHREAD \
+public:
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Previously used to initialize the reference count, but no longer needed.
+ *
+ * DEPRECATED.
+ */
+#define NS_INIT_ISUPPORTS() ((void)0)
+
+/**
+ * Use this macro to implement the AddRef method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ */
+#define NS_IMPL_ADDREF(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
+ NS_ASSERT_OWNINGTHREAD(_class); \
+ ++mRefCnt; \
+ NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
+ return mRefCnt; \
+}
+
+/**
+ * Use this macro to implement the AddRef method for a given <i>_class</i>
+ * implemented as a wholly owned aggregated object intended to implement
+ * interface(s) for its owner
+ * @param _class The name of the class implementing the method
+ * @param _aggregator the owning/containing object
+ */
+#define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ NS_PRECONDITION(_aggregator, "null aggregator"); \
+ return (_aggregator)->AddRef(); \
+}
+
+/**
+ * Use this macro to implement the Release method for a given
+ * <i>_class</i>.
+ * @param _class The name of the class implementing the method
+ * @param _destroy A statement that is executed when the object's
+ * refcount drops to zero.
+ *
+ * For example,
+ *
+ * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
+ *
+ * will cause
+ *
+ * Destroy(this);
+ *
+ * to be invoked when the object's refcount drops to zero. This
+ * allows for arbitrary teardown activity to occur (e.g., deallocation
+ * of object allocated with placement new).
+ */
+#define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ NS_ASSERT_OWNINGTHREAD(_class); \
+ --mRefCnt; \
+ NS_LOG_RELEASE(this, mRefCnt, #_class); \
+ if (mRefCnt == 0) { \
+ mRefCnt = 1; /* stabilize */ \
+ _destroy; \
+ return 0; \
+ } \
+ return mRefCnt; \
+}
+
+/**
+ * Use this macro to implement the Release method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ *
+ * A note on the 'stabilization' of the refcnt to one. At that point,
+ * the object's refcount will have gone to zero. The object's
+ * destructor may trigger code that attempts to QueryInterface() and
+ * Release() 'this' again. Doing so will temporarily increment and
+ * decrement the refcount. (Only a logic error would make one try to
+ * keep a permanent hold on 'this'.) To prevent re-entering the
+ * destructor, we make sure that no balanced refcounting can return
+ * the refcount to |0|.
+ */
+#define NS_IMPL_RELEASE(_class) \
+ NS_IMPL_RELEASE_WITH_DESTROY(_class, NS_DELETEXPCOM(this))
+
+/**
+ * Use this macro to implement the Release method for a given <i>_class</i>
+ * implemented as a wholly owned aggregated object intended to implement
+ * interface(s) for its owner
+ * @param _class The name of the class implementing the method
+ * @param _aggregator the owning/containing object
+ */
+#define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(_aggregator, "null aggregator"); \
+ return (_aggregator)->Release(); \
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Some convenience macros for implementing QueryInterface
+ */
+
+/**
+ * This implements query interface with two assumptions: First, the
+ * class in question implements nsISupports and its own interface and
+ * nothing else. Second, the implementation of the class's primary
+ * inheritance chain leads to its own interface.
+ *
+ * @param _class The name of the class implementing the method
+ * @param _classiiddef The name of the #define symbol that defines the IID
+ * for the class (e.g. NS_ISUPPORTS_IID)
+ */
+
+#define NS_IMPL_QUERY_HEAD(_class) \
+NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
+{ \
+ NS_ASSERTION(aInstancePtr, \
+ "QueryInterface requires a non-NULL destination!"); \
+ nsISupports* foundInterface;
+
+#define NS_IMPL_QUERY_BODY(_interface) \
+ if ( aIID.Equals(NS_GET_IID(_interface)) ) \
+ foundInterface = NS_STATIC_CAST(_interface*, this); \
+ else
+
+#define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \
+ if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \
+ foundInterface = NS_STATIC_CAST(_interface*, this); \
+ else
+
+#define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \
+ if ( aIID.Equals(NS_GET_IID(_interface)) ) \
+ foundInterface = NS_STATIC_CAST(_interface*, \
+ NS_STATIC_CAST(_implClass*, this)); \
+ else
+
+#define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \
+ if ( aIID.Equals(NS_GET_IID(_interface)) ) \
+ foundInterface = NS_STATIC_CAST(_interface*, _aggregate); \
+ else
+
+#define NS_IMPL_QUERY_TAIL_GUTS \
+ foundInterface = 0; \
+ nsresult status; \
+ if ( !foundInterface ) \
+ status = NS_NOINTERFACE; \
+ else \
+ { \
+ NS_ADDREF(foundInterface); \
+ status = NS_OK; \
+ } \
+ *aInstancePtr = foundInterface; \
+ return status; \
+}
+
+#define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \
+ foundInterface = 0; \
+ nsresult status; \
+ if ( !foundInterface ) \
+ status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \
+ else \
+ { \
+ NS_ADDREF(foundInterface); \
+ status = NS_OK; \
+ } \
+ *aInstancePtr = foundInterface; \
+ return status; \
+}
+
+#define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \
+ foundInterface = 0; \
+ nsresult status; \
+ if ( !foundInterface ) { \
+ NS_ASSERTION(_aggregator, "null aggregator"); \
+ status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \
+ } else \
+ { \
+ NS_ADDREF(foundInterface); \
+ status = NS_OK; \
+ } \
+ *aInstancePtr = foundInterface; \
+ return status; \
+}
+
+#define NS_IMPL_QUERY_TAIL(_supports_interface) \
+ NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \
+ NS_IMPL_QUERY_TAIL_GUTS
+
+
+ /*
+ This is the new scheme. Using this notation now will allow us to switch to
+ a table driven mechanism when it's ready. Note the difference between this
+ and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must
+ explicitly mention |nsISupports| when using the interface maps.
+ */
+#define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass)
+#define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface)
+#define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \
+ NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
+#define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \
+ NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
+
+#define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS
+#define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \
+ NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
+#define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \
+ NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
+#define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \
+ NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
+
+#define NS_IMPL_QUERY_INTERFACE0(_class) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(nsISupports) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE1(_class, _i1) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY(_i11) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE0 NS_IMPL_QUERY_INTERFACE0
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE1 NS_IMPL_QUERY_INTERFACE1
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE2 NS_IMPL_QUERY_INTERFACE2
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE3 NS_IMPL_QUERY_INTERFACE3
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE4 NS_IMPL_QUERY_INTERFACE4
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE5 NS_IMPL_QUERY_INTERFACE5
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE6 NS_IMPL_QUERY_INTERFACE6
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE7 NS_IMPL_QUERY_INTERFACE7
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE8 NS_IMPL_QUERY_INTERFACE8
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE9 NS_IMPL_QUERY_INTERFACE9
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE10 NS_IMPL_QUERY_INTERFACE10
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE11 NS_IMPL_QUERY_INTERFACE11
+
+/**
+ * Declare that you're going to inherit from something that already
+ * implements nsISupports, but also implements an additional interface, thus
+ * causing an ambiguity. In this case you don't need another mRefCnt, you
+ * just need to forward the definitions to the appropriate superclass. E.g.
+ *
+ * class Bar : public Foo, public nsIBar { // both provide nsISupports
+ * public:
+ * NS_DECL_ISUPPORTS_INHERITED
+ * ...other nsIBar and Bar methods...
+ * };
+ */
+#define NS_DECL_ISUPPORTS_INHERITED \
+public: \
+ NS_IMETHOD QueryInterface(REFNSIID aIID, \
+ void** aInstancePtr); \
+ NS_IMETHOD_(nsrefcnt) AddRef(void); \
+ NS_IMETHOD_(nsrefcnt) Release(void); \
+
+/**
+ * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
+ * to implement the nsISupports methods, forwarding the invocations to a
+ * superclass that already implements nsISupports.
+ *
+ * Note that I didn't make these inlined because they're virtual methods.
+ */
+
+#define NS_IMPL_ADDREF_INHERITED(Class, Super) \
+NS_IMETHODIMP_(nsrefcnt) Class::AddRef(void) \
+{ \
+ return Super::AddRef(); \
+} \
+
+#define NS_IMPL_RELEASE_INHERITED(Class, Super) \
+NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \
+{ \
+ return Super::Release(); \
+} \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED5(Class,Super,i1,i2,i3,i4,i5) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_BODY(i5) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED6(Class,Super,i1,i2,i3,i4,i5,i6) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_BODY(i5) \
+ NS_IMPL_QUERY_BODY(i6) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+/**
+ * Convenience macros for implementing all nsISupports methods for
+ * a simple class.
+ * @param _class The name of the class implementing the method
+ * @param _classiiddef The name of the #define symbol that defines the IID
+ * for the class (e.g. NS_ISUPPORTS_IID)
+ */
+
+#define NS_IMPL_ISUPPORTS0(_class) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE0(_class)
+
+#define NS_IMPL_ISUPPORTS1(_class, _interface) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE1(_class, _interface)
+
+#define NS_IMPL_ISUPPORTS2(_class, _i1, _i2) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2)
+
+#define NS_IMPL_ISUPPORTS3(_class, _i1, _i2, _i3) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3)
+
+#define NS_IMPL_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4)
+
+#define NS_IMPL_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5)
+
+#define NS_IMPL_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
+
+#define NS_IMPL_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7)
+
+#define NS_IMPL_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)
+
+#define NS_IMPL_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9)
+
+#define NS_IMPL_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10)
+
+#define NS_IMPL_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11)
+
+#define NS_IMPL_ISUPPORTS_INHERITED0(Class, Super) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED1(Class, Super, i1) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED2(Class, Super, i1, i2) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED3(Class, Super, i1, i2, i3) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED4(Class, Super, i1, i2, i3, i4) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+///////////////////////////////////////////////////////////////////////////////
+/**
+ *
+ * Threadsafe implementations of the ISupports convenience macros
+ *
+ */
+
+/**
+ * Use this macro to implement the AddRef method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ */
+
+#ifdef VBOX
+#define NS_IMPL_THREADSAFE_ADDREF(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ nsrefcnt count = mRefCnt.get(); \
+ PRUint32 state = mRefCnt.getState(); \
+ AssertReleaseMsg( state <= 1 \
+ && ( (state == 0 && count == 0) \
+ || (state == 1 && count < PR_UINT32_MAX/2)), \
+ ("AddRef: illegal refcnt=%u state=%d\n", count, state)); \
+ switch (state) \
+ { \
+ case 0: \
+ if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 1, 0)) \
+ AssertReleaseMsgFailed(("AddRef: racing for first increment\n")); \
+ count = ASMAtomicIncU32(mRefCnt.ref()); \
+ AssertReleaseMsg(count == 1, \
+ ("AddRef: unexpected refcnt=%u\n", count)); \
+ break; \
+ case 1: \
+ count = ASMAtomicIncU32(mRefCnt.ref()); \
+ AssertReleaseMsg(count <= PR_UINT32_MAX/2, \
+ ("AddRef: unexpected refcnt=%u\n", count)); \
+ break; \
+ case 2: \
+ AssertReleaseMsgFailed(("AddRef: freed object\n")); \
+ break; \
+ default: \
+ AssertReleaseMsgFailed(("AddRef: garbage object\n")); \
+ } \
+ NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
+ return count; \
+}
+#else
+#define NS_IMPL_THREADSAFE_ADDREF(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
+ nsrefcnt count; \
+ count = PR_AtomicIncrement((PRInt32*)&mRefCnt); \
+ NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
+ return count; \
+}
+#endif
+
+/**
+ * Use this macro to implement the Release method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ */
+
+#ifdef VBOX
+#define NS_IMPL_THREADSAFE_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ nsrefcnt count = mRefCnt.get(); \
+ PRUint32 state = mRefCnt.getState(); \
+ AssertReleaseMsg(state == 1 && count <= PR_UINT32_MAX/2, \
+ ("Release: illegal refcnt=%u state=%d\n", count, state)); \
+ switch (state) \
+ { \
+ case 0: \
+ AssertReleaseMsgFailed(("Release: new object\n")); \
+ break; \
+ case 1: \
+ count = ASMAtomicDecU32(mRefCnt.ref()); \
+ AssertReleaseMsg(count < PR_UINT32_MAX/2, \
+ ("Release: unexpected refcnt=%u\n", count)); \
+ if (count == 0) \
+ { \
+ if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 2, 1)) \
+ AssertReleaseMsgFailed(("Release: racing for state free\n")); \
+ /* Use better stabilization: reserve everything with top bit set. */ \
+ if (!ASMAtomicCmpXchgU32(mRefCnt.ref(), PR_UINT32_MAX/4*3, 0)) \
+ AssertReleaseMsgFailed(("Release: racing for refcnt stabilize\n")); \
+ NS_DELETEXPCOM(this); \
+ } \
+ break; \
+ case 2: \
+ AssertReleaseMsgFailed(("Release: freed object\n")); \
+ break; \
+ default: \
+ AssertReleaseMsgFailed(("Release: garbage object\n")); \
+ } \
+ NS_LOG_RELEASE(this, count, #_class); \
+ return count; \
+}
+#else
+#define NS_IMPL_THREADSAFE_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ nsrefcnt count; \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \
+ NS_LOG_RELEASE(this, count, #_class); \
+ if (0 == count) { \
+ mRefCnt = 1; /* stabilize */ \
+ /* enable this to find non-threadsafe destructors: */ \
+ /* NS_ASSERT_OWNINGTHREAD(_class); */ \
+ NS_DELETEXPCOM(this); \
+ return 0; \
+ } \
+ return count; \
+}
+#endif
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS0(_class) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE0(_class)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS1(_class, _interface) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE1(_class, _interface)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS2(_class, _i1, _i2) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE2(_class, _i1, _i2)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS3(_class, _i1, _i2, _i3) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE3(_class, _i1, _i2, _i3)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11)
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for implementing nsIClassInfo-related stuff.
+///////////////////////////////////////////////////////////////////////////////
+
+// include here instead of at the top because it requires the nsISupport decl
+#include "nsIClassInfo.h"
+
+#define NS_CLASSINFO_NAME(_class) _class##_classInfoGlobal
+#define NS_CI_INTERFACE_GETTER_NAME(_class) _class##_GetInterfacesHelper
+
+#define NS_DECL_CI_INTERFACE_GETTER(_class) \
+ extern NS_IMETHODIMP NS_CI_INTERFACE_GETTER_NAME(_class)(PRUint32 *, \
+ nsIID ***);
+
+#define NS_DECL_CLASSINFO(_class) \
+ NS_DECL_CI_INTERFACE_GETTER(_class) \
+ nsIClassInfo *NS_CLASSINFO_NAME(_class);
+
+#define NS_IMPL_QUERY_CLASSINFO(_class) \
+ if ( aIID.Equals(NS_GET_IID(nsIClassInfo)) ) { \
+ extern nsIClassInfo *NS_CLASSINFO_NAME(_class); \
+ foundInterface = NS_STATIC_CAST(nsIClassInfo*, NS_CLASSINFO_NAME(_class));\
+ } else
+
+#define NS_CLASSINFO_HELPER_BEGIN(_class, _c) \
+NS_IMETHODIMP \
+NS_CI_INTERFACE_GETTER_NAME(_class)(PRUint32 *count, nsIID ***array) \
+{ \
+ *count = _c; \
+ *array = (nsIID **)nsMemory::Alloc(sizeof (nsIID *) * _c);
+
+#define NS_CLASSINFO_HELPER_ENTRY(_i, _interface) \
+ (*array)[_i] = (nsIID *)nsMemory::Clone(&NS_GET_IID(_interface), \
+ sizeof(nsIID));
+
+#define NS_CLASSINFO_HELPER_END \
+ return NS_OK; \
+}
+
+#define NS_IMPL_CI_INTERFACE_GETTER1(_class, _interface) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 1) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _interface) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE1_CI(_class, _i1) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS1_CI(_class, _interface) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE1_CI(_class, _interface) \
+ NS_IMPL_CI_INTERFACE_GETTER1(_class, _interface)
+
+#define NS_IMPL_CI_INTERFACE_GETTER2(_class, _i1, _i2) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 2) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE2_CI(_class, _i1, _i2) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS2_CI(_class, _i1, _i2) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE2_CI(_class, _i1, _i2) \
+ NS_IMPL_CI_INTERFACE_GETTER2(_class, _i1, _i2)
+
+#define NS_IMPL_CI_INTERFACE_GETTER3(_class, _i1, _i2, _i3) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 3) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE3_CI(_class, _i1, _i2, _i3) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS3_CI(_class, _i1, _i2, _i3) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE3_CI(_class, _i1, _i2, _i3) \
+ NS_IMPL_CI_INTERFACE_GETTER3(_class, _i1, _i2, _i3)
+
+#define NS_IMPL_CI_INTERFACE_GETTER4(_class, _i1, _i2, _i3, _i4) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 4) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE4_CI(_class, _i1, _i2, _i3, _i4) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS4_CI(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE4_CI(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_CI_INTERFACE_GETTER4(_class, _i1, _i2, _i3, _i4)
+
+#define NS_IMPL_CI_INTERFACE_GETTER5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 5) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE5_CI(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS5_CI(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE5_CI(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_CI_INTERFACE_GETTER5(_class, _i1, _i2, _i3, _i4, _i5)
+
+#define NS_IMPL_CI_INTERFACE_GETTER6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 6) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_CI_INTERFACE_GETTER6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
+
+#define NS_IMPL_CI_INTERFACE_GETTER7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 7) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_IMPL_CI_INTERFACE_GETTER7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7)
+
+#define NS_IMPL_CI_INTERFACE_GETTER8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 8) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
+ NS_IMPL_CI_INTERFACE_GETTER8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)
+
+#define NS_IMPL_CI_INTERFACE_GETTER9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 9) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_ENTRY(8, _i9) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9) \
+ NS_IMPL_CI_INTERFACE_GETTER9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9)
+
+#define NS_IMPL_CI_INTERFACE_GETTER10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 10) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_ENTRY(8, _i9) \
+ NS_CLASSINFO_HELPER_ENTRY(9, _i10) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_CI_INTERFACE_GETTER11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 10) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_ENTRY(8, _i9) \
+ NS_CLASSINFO_HELPER_ENTRY(9, _i10) \
+ NS_CLASSINFO_HELPER_ENTRY(10, _i11) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY(_i11) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10) \
+ NS_IMPL_CI_INTERFACE_GETTER10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10)
+
+#define NS_IMPL_ISUPPORTS11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11) \
+ NS_IMPL_CI_INTERFACE_GETTER11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11)
+
+#define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h
new file mode 100644
index 00000000..d8d002b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Scott Collins <scc@ScottCollins.net>
+ * Dan Mosedale <dmose@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsISupportsUtils_h__
+#define nsISupportsUtils_h__
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsISupportsBase_h__
+#include "nsISupportsBase.h"
+#endif
+
+#ifndef nsError_h__
+#include "nsError.h"
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+#ifndef nsISupportsImpl_h__
+#include "nsISupportsImpl.h"
+#endif
+
+/**
+ * Macro for instantiating a new object that implements nsISupports.
+ * Note that you can only use this if you adhere to the no arguments
+ * constructor com policy (which you really should!).
+ * @param _result Where the new instance pointer is stored
+ * @param _type The type of object to call "new" with.
+ */
+#define NS_NEWXPCOM(_result,_type) \
+ PR_BEGIN_MACRO \
+ _result = new _type(); \
+ PR_END_MACRO
+
+/**
+ * Macro for deleting an object that implements nsISupports.
+ * @param _ptr The object to delete.
+ */
+#define NS_DELETEXPCOM(_ptr) \
+ PR_BEGIN_MACRO \
+ delete (_ptr); \
+ PR_END_MACRO
+
+/**
+ * Macro for adding a reference to an interface.
+ * @param _ptr The interface pointer.
+ */
+#define NS_ADDREF(_ptr) \
+ (_ptr)->AddRef()
+
+/**
+ * Macro for adding a reference to this. This macro should be used
+ * because NS_ADDREF (when tracing) may require an ambiguous cast
+ * from the pointers primary type to nsISupports. This macro sidesteps
+ * that entire problem.
+ */
+#define NS_ADDREF_THIS() \
+ AddRef()
+
+
+extern "C++" {
+// ...because some one is accidentally including this file inside
+// an |extern "C"|
+
+
+// Making this a |inline| |template| allows |expr| to be evaluated only once,
+// yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
+template <class T>
+inline
+nsrefcnt
+ns_if_addref( T expr )
+{
+ return expr ? expr->AddRef() : 0;
+}
+
+} /* extern "C++" */
+
+/**
+ * Macro for adding a reference to an interface that checks for NULL.
+ * @param _expr The interface pointer.
+ */
+#define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
+
+/*
+ * Given these declarations, it explicitly OK and efficient to end a `getter' with:
+ *
+ * NS_IF_ADDREF(*result = mThing);
+ *
+ * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still
+ * _illegal_ to say |NS_IF_ADDREF(mThing)|.
+ */
+
+/**
+ * Macro for releasing a reference to an interface.
+ * @param _ptr The interface pointer.
+ */
+#define NS_RELEASE(_ptr) \
+ PR_BEGIN_MACRO \
+ (_ptr)->Release(); \
+ (_ptr) = 0; \
+ PR_END_MACRO
+
+/**
+ * Macro for releasing a reference to an interface.
+ * @param _ptr The interface pointer.
+ */
+#define NS_RELEASE_THIS() \
+ Release()
+
+/**
+ * Macro for releasing a reference to an interface, except that this
+ * macro preserves the return value from the underlying Release call.
+ * The interface pointer argument will only be NULLed if the reference count
+ * goes to zero.
+ *
+ * @param _ptr The interface pointer.
+ */
+#define NS_RELEASE2(_ptr,_rv) \
+ PR_BEGIN_MACRO \
+ _rv = (_ptr)->Release(); \
+ if (0 == (_rv)) (_ptr) = 0; \
+ PR_END_MACRO
+
+/**
+ * Macro for releasing a reference to an interface that checks for NULL;
+ * @param _ptr The interface pointer.
+ */
+#define NS_IF_RELEASE(_ptr) \
+ PR_BEGIN_MACRO \
+ if (_ptr) { \
+ (_ptr)->Release(); \
+ (_ptr) = 0; \
+ } \
+ PR_END_MACRO
+
+/*
+ * Often you have to cast an implementation pointer, e.g., |this|, to an
+ * |nsISupports*|, but because you have multiple inheritance, a simple cast
+ * is ambiguous. One could simply say, e.g., (given a base |nsIBase|),
+ * |NS_STATIC_CAST(nsIBase*, this)|; but that disguises the fact that what
+ * you are really doing is disambiguating the |nsISupports|. You could make
+ * that more obvious with a double cast, e.g., |NS_STATIC_CAST(nsISupports*,
+ * NS_STATIC_CAST(nsIBase*, this))|, but that is bulky and harder to read...
+ *
+ * The following macro is clean, short, and obvious. In the example above,
+ * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|.
+ */
+
+#define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
+ NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(__unambiguousBase, __expr))
+
+extern "C++" {
+// ...because some one is accidentally including this file inside
+// an |extern "C"|
+
+class nsISupports;
+
+template <class T>
+struct nsCOMTypeInfo
+{
+ static const nsIID& GetIID() { return T::GetIID(); }
+};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCOMTypeInfo<nsISupports>
+{
+ static const nsIID& GetIID() {
+ static const nsIID iid_NS_ISUPPORTS_IID = NS_ISUPPORTS_IID; return iid_NS_ISUPPORTS_IID;
+ }
+};
+
+#define NS_GET_IID(T) nsCOMTypeInfo<T>::GetIID()
+
+// a type-safe shortcut for calling the |QueryInterface()| member function
+template <class T, class DestinationType>
+inline
+nsresult
+CallQueryInterface( T* aSource, DestinationType** aDestination )
+{
+ NS_PRECONDITION(aSource, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return aSource->QueryInterface(NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+} // extern "C++"
+
+#endif /* __nsISupportsUtils_h */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h
new file mode 100644
index 00000000..17d1bd79
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h
@@ -0,0 +1,162 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIWeakReferenceUtils_h__
+#define nsIWeakReferenceUtils_h__
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+typedef nsCOMPtr<nsIWeakReference> nsWeakPtr;
+
+/**
+ *
+ */
+
+// a type-safe shortcut for calling the |QueryReferent()| member function
+// T must inherit from nsIWeakReference, but the cast may be ambiguous.
+template <class T, class DestinationType>
+inline
+nsresult
+CallQueryReferent( T* aSource, DestinationType** aDestination )
+ {
+ NS_PRECONDITION(aSource, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return aSource->QueryReferent(NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+ }
+
+
+class NS_COM nsQueryReferent : public nsCOMPtr_helper
+ {
+ public:
+ nsQueryReferent( nsIWeakReference* aWeakPtr, nsresult* error )
+ : mWeakPtr(aWeakPtr),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsIWeakReference* mWeakPtr;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsQueryReferent
+do_QueryReferent( nsIWeakReference* aRawPtr, nsresult* error = 0 )
+ {
+ return nsQueryReferent(aRawPtr, error);
+ }
+
+
+
+class NS_COM nsGetWeakReference : public nsCOMPtr_helper
+ {
+ public:
+ nsGetWeakReference( nsISupports* aRawPtr, nsresult* error )
+ : mRawPtr(aRawPtr),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ nsISupports* mRawPtr;
+ nsresult* mErrorPtr;
+ };
+
+ /**
+ * |do_GetWeakReference| is a convenience function that bundles up all the work needed
+ * to get a weak reference to an arbitrary object, i.e., the |QueryInterface|, test, and
+ * call through to |GetWeakReference|, and put it into your |nsCOMPtr|.
+ * It is specifically designed to cooperate with |nsCOMPtr| (or |nsWeakPtr|) like so:
+ * |nsWeakPtr myWeakPtr = do_GetWeakReference(aPtr);|.
+ */
+inline
+const nsGetWeakReference
+do_GetWeakReference( nsISupports* aRawPtr, nsresult* error = 0 )
+ {
+ return nsGetWeakReference(aRawPtr, error);
+ }
+
+inline
+void
+do_GetWeakReference( nsIWeakReference* aRawPtr, nsresult* error = 0 )
+ {
+ // This signature exists soley to _stop_ you from doing a bad thing.
+ // Saying |do_GetWeakReference()| on a weak reference itself,
+ // is very likely to be a programmer error.
+ }
+
+template <class T>
+inline
+void
+do_GetWeakReference( already_AddRefed<T>& )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_GetWeakReference()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+template <class T>
+inline
+void
+do_GetWeakReference( already_AddRefed<T>&, nsresult* )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_GetWeakReference()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+
+
+ /**
+ * Deprecated, use |do_GetWeakReference| instead.
+ */
+extern NS_COM
+nsIWeakReference*
+NS_GetWeakReference( nsISupports* , nsresult* aResult=0 );
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp b/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp
new file mode 100644
index 00000000..2449c58e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsMemory.h"
+#include "nsXPCOMPrivate.h"
+
+static nsIMemory* gMemory = nsnull;
+
+static NS_METHOD FreeGlobalMemory(void)
+{
+ NS_ASSERTION(gMemory, "must be not null after SetupGlobalMemory");
+ NS_IF_RELEASE(gMemory);
+ return NS_OK;
+}
+
+#define ENSURE_ALLOCATOR \
+ (gMemory ? PR_TRUE : (PRBool)(SetupGlobalMemory() != nsnull))
+
+static nsIMemory*
+SetupGlobalMemory()
+{
+ NS_ASSERTION(!gMemory, "must be called once");
+ if (!gMemory)
+ {
+ NS_GetMemoryManager(&gMemory);
+ NS_ASSERTION(gMemory, "can't get memory manager!");
+ if (gMemory)
+ NS_RegisterXPCOMExitRoutine(FreeGlobalMemory, 0);
+ }
+ return gMemory;
+}
+
+#ifdef XPCOM_GLUE
+nsresult GlueStartupMemory()
+{
+ NS_ASSERTION(!gMemory, "must be called once");
+ if (!gMemory)
+ {
+ NS_GetMemoryManager(&gMemory);
+ NS_ASSERTION(gMemory, "can't get memory manager!");
+ if (!gMemory)
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+void GlueShutdownMemory()
+{
+ NS_IF_RELEASE(gMemory);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// nsMemory static helper routines
+
+NS_COM void*
+nsMemory::Alloc(PRSize size)
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ return gMemory->Alloc(size);
+}
+
+NS_COM void*
+nsMemory::Realloc(void* ptr, PRSize size)
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ return gMemory->Realloc(ptr, size);
+}
+
+NS_COM void
+nsMemory::Free(void* ptr)
+{
+ if (!ENSURE_ALLOCATOR)
+ return;
+
+ gMemory->Free(ptr);
+}
+
+NS_COM nsresult
+nsMemory::HeapMinimize(PRBool aImmediate)
+{
+ if (!ENSURE_ALLOCATOR)
+ return NS_ERROR_FAILURE;
+
+ return gMemory->HeapMinimize(aImmediate);
+}
+
+NS_COM void*
+nsMemory::Clone(const void* ptr, PRSize size)
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ void* newPtr = gMemory->Alloc(size);
+ if (newPtr)
+ memcpy(newPtr, ptr, size);
+ return newPtr;
+}
+
+NS_COM nsIMemory*
+nsMemory::GetGlobalMemoryService()
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ nsIMemory* result = gMemory;
+ NS_IF_ADDREF(result);
+ return result;
+}
+
+//----------------------------------------------------------------------
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsMemory.h b/src/libs/xpcom18a4/xpcom/glue/nsMemory.h
new file mode 100644
index 00000000..4ee48bf0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsMemory.h
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsMemory_h__
+#define nsMemory_h__
+
+#include "nsIMemory.h"
+
+#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
+#define NS_MEMORY_CLASSNAME "Global Memory Service"
+#define NS_MEMORY_CID \
+{ /* 30a04e40-38e7-11d4-8cf5-0060b0fc14a3 */ \
+ 0x30a04e40, \
+ 0x38e7, \
+ 0x11d4, \
+ {0x8c, 0xf5, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
+}
+
+
+/**
+ * Static helper routines to manage memory. These routines allow easy access
+ * to xpcom's built-in (global) nsIMemory implementation, without needing
+ * to go through the service manager to get it. However this requires clients
+ * to link with the xpcom DLL.
+ *
+ * This class is not threadsafe and is intented for use only on the main
+ * thread.
+ */
+class nsMemory
+{
+public:
+ static NS_COM void* Alloc(size_t size);
+ static NS_COM void* Realloc(void* ptr, size_t size);
+ static NS_COM void Free(void* ptr);
+ static NS_COM nsresult HeapMinimize(PRBool aImmediate);
+ static NS_COM void* Clone(const void* ptr, size_t size);
+ static NS_COM nsIMemory* GetGlobalMemoryService(); // AddRefs
+};
+
+/**
+ * Macro to free all elements of an XPCOM array of a given size using
+ * freeFunc, then frees the array itself using nsMemory::Free().
+ *
+ * Note that this macro (and its wrappers) can be used to deallocate a
+ * partially- or completely-built array while unwinding an error
+ * condition inside the XPCOM routine that was going to return the
+ * array. For this to work on a partially-built array, your code
+ * needs to be building the array from index 0 upwards, and simply
+ * pass the number of elements that have already been built (and thus
+ * need to be freed) as |size|.
+ *
+ * Thanks to <alecf@netscape.com> for suggesting this form, which
+ * allows the macro to be used with NS_RELEASE / NS_RELEASE_IF in
+ * addition to nsMemory::Free.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ * @param freeFunc The function or macro to be used to free it.
+ * For arrays of nsISupports (or any class derived
+ * from it), NS_IF_RELEASE (or NS_RELEASE) should be
+ * passed as freeFunc. For most (all?) other pointer
+ * types (including XPCOM strings and wstrings),
+ * nsMemory::Free should be used, since the
+ * shared-allocator (nsMemory) is what will have been
+ * used to allocate the memory.
+ */
+#define NS_FREE_XPCOM_POINTER_ARRAY(size, array, freeFunc) \
+ PR_BEGIN_MACRO \
+ PRInt32 iter_ = PRInt32(size); \
+ while (--iter_ >= 0) \
+ freeFunc((array)[iter_]); \
+ nsMemory::Free((array)); \
+ PR_END_MACRO
+
+// convenience macros for commonly used calls. mmmmm. syntactic sugar.
+
+/**
+ * Macro to free arrays of non-refcounted objects allocated by the
+ * shared allocator (nsMemory) such as strings and wstrings. A
+ * convenience wrapper around NS_FREE_XPCOM_POINTER_ARRAY.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ */
+#define NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(size, array) \
+ NS_FREE_XPCOM_POINTER_ARRAY((size), (array), nsMemory::Free)
+
+/**
+ * Macro to free an array of pointers to nsISupports (or classes
+ * derived from it). A convenience wrapper around
+ * NS_FREE_XPCOM_POINTER_ARRAY.
+ *
+ * Note that if you know that none of your nsISupports pointers are
+ * going to be 0, you can gain a bit of speed by calling
+ * NS_FREE_XPCOM_POINTER_ARRAY directly and using NS_RELEASE as your
+ * free function.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ */
+#define NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(size, array) \
+ NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_IF_RELEASE)
+
+/**
+ * Helpful array length function for calculating the length of a
+ * statically declared array.
+ */
+
+#define NS_ARRAY_LENGTH(array_) \
+ (sizeof(array_)/sizeof(array_[0]))
+
+
+#endif // nsMemory_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h
new file mode 100644
index 00000000..b225b6a2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIServiceManagerUtils_h__
+#define nsIServiceManagerUtils_h__
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Using servicemanager with COMPtrs
+class NS_COM nsGetServiceByCID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByCID( const nsCID& aCID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const nsCID& mCID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, 0, error);
+}
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, aServiceManager, error);
+}
+
+class NS_COM nsGetServiceByContractID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByContractID( const char* aContractID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const char* mContractID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, aServiceManager, error);
+}
+
+class nsGetServiceFromCategory : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceFromCategory(const char* aCategory, const char* aEntry,
+ nsISupports* aServiceManager,
+ nsresult* aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+ protected:
+ const char* mCategory;
+ const char* mEntry;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceFromCategory
+do_GetServiceFromCategory( const char* category, const char* entry,
+ nsresult* error = 0)
+{
+ return nsGetServiceFromCategory(category, entry, 0, error);
+}
+
+// type-safe shortcuts for calling |GetService|
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetServiceByContractID(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp
new file mode 100644
index 00000000..14e9469b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp
@@ -0,0 +1,125 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is XPCOM
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsTraceRefcnt.h"
+#include "nsTraceRefcntImpl.h"
+
+static nsITraceRefcnt* gTraceRefcntObject = nsnull;
+
+static NS_METHOD FreeTraceRefcntObject(void)
+{
+ NS_IF_RELEASE(gTraceRefcntObject);
+ return NS_OK;
+}
+
+#define ENSURE_TRACEOBJECT \
+ (gTraceRefcntObject || SetupTraceRefcntObject() != nsnull)
+
+static nsITraceRefcnt* SetupTraceRefcntObject()
+{
+ NS_GetTraceRefcnt(&gTraceRefcntObject);
+ if (gTraceRefcntObject)
+ NS_RegisterXPCOMExitRoutine(FreeTraceRefcntObject, 0);
+ return gTraceRefcntObject;
+}
+
+#ifdef XPCOM_GLUE
+nsresult GlueStartupTraceRefcnt()
+{
+ NS_GetTraceRefcnt(&gTraceRefcntObject);
+ if (!gTraceRefcntObject)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+void GlueShutdownTraceRefcnt()
+{
+ NS_IF_RELEASE(gTraceRefcntObject);
+}
+#endif
+
+NS_COM void
+nsTraceRefcnt::LogAddRef(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName, PRUint32 aInstanceSize)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogAddRef(aPtr, aNewRefcnt, aTypeName, aInstanceSize);
+}
+
+NS_COM void
+nsTraceRefcnt::LogRelease(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogRelease(aPtr, aNewRefcnt, aTypeName);
+}
+
+NS_COM void
+nsTraceRefcnt::LogCtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogCtor(aPtr, aTypeName, aInstanceSize);
+}
+
+NS_COM void
+nsTraceRefcnt::LogDtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogDtor(aPtr, aTypeName, aInstanceSize);
+}
+
+NS_COM void
+nsTraceRefcnt::LogAddCOMPtr(void * aPtr, nsISupports *aObject)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogAddCOMPtr(aPtr, aObject);
+}
+
+NS_COM void
+nsTraceRefcnt::LogReleaseCOMPtr(void * aPtr, nsISupports *aObject)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogReleaseCOMPtr(aPtr, aObject);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h
new file mode 100644
index 00000000..afafda4b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsTraceRefcnt_h___
+#define nsTraceRefcnt_h___
+
+#include "nscore.h"
+
+class nsISupports;
+
+// By default refcnt logging is not part of the build.
+#undef NS_BUILD_REFCNT_LOGGING
+
+#if (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+// Make refcnt logging part of the build. This doesn't mean that
+// actual logging will occur (that requires a separate enable; see
+// nsTraceRefcnt.h for more information).
+#define NS_BUILD_REFCNT_LOGGING 1
+#endif
+
+// If NO_BUILD_REFCNT_LOGGING is defined then disable refcnt logging
+// in the build. This overrides FORCE_BUILD_REFCNT_LOGGING.
+#if defined(NO_BUILD_REFCNT_LOGGING)
+#undef NS_BUILD_REFCNT_LOGGING
+#endif
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+
+#define NS_LOG_ADDREF(_p, _rc, _type, _size) \
+ nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32) (_size))
+
+#define NS_LOG_RELEASE(_p, _rc, _type) \
+ nsTraceRefcnt::LogRelease((_p), (_rc), (_type))
+
+#define MOZ_DECL_CTOR_COUNTER(_type)
+
+#define MOZ_COUNT_CTOR(_type) \
+PR_BEGIN_MACRO \
+ nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this)); \
+PR_END_MACRO
+
+#define MOZ_COUNT_DTOR(_type) \
+PR_BEGIN_MACRO \
+ nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this)); \
+PR_END_MACRO
+
+#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR // from autoconf (XXX needs to be
+ // set for non-autoconf platforms)
+
+// nsCOMPtr.h allows these macros to be defined by clients
+// These logging functions require dynamic_cast<void *>, so we don't
+// define these macros if we don't have dynamic_cast.
+#define NSCAP_LOG_ASSIGNMENT(_c, _p) \
+ if (_p) \
+ nsTraceRefcnt::LogAddCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p))
+
+#define NSCAP_LOG_RELEASE(_c, _p) \
+ if (_p) \
+ nsTraceRefcnt::LogReleaseCOMPtr((_c), NS_STATIC_CAST(nsISupports*,_p))
+
+#endif /* HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR */
+
+#else /* !NS_BUILD_REFCNT_LOGGING */
+
+#define NS_LOG_ADDREF(_p, _rc, _type, _size)
+#define NS_LOG_RELEASE(_p, _rc, _type)
+#define MOZ_DECL_CTOR_COUNTER(_type)
+#define MOZ_COUNT_CTOR(_type)
+#define MOZ_COUNT_DTOR(_type)
+
+#endif /* NS_BUILD_REFCNT_LOGGING */
+
+//----------------------------------------------------------------------
+
+/**
+ * Note: The implementations for these methods are no-ops in a build
+ * where NS_BUILD_REFCNT_LOGGING is disabled.
+ */
+class nsTraceRefcnt {
+public:
+ static NS_COM void LogAddRef(void* aPtr,
+ nsrefcnt aNewRefCnt,
+ const char* aTypeName,
+ PRUint32 aInstanceSize);
+
+ static NS_COM void LogRelease(void* aPtr,
+ nsrefcnt aNewRefCnt,
+ const char* aTypeName);
+
+ static NS_COM void LogCtor(void* aPtr, const char* aTypeName,
+ PRUint32 aInstanceSize);
+
+ static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
+ PRUint32 aInstanceSize);
+
+ static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
+
+ static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
+
+};
+#endif /* nsTraceRefcnt_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp
new file mode 100644
index 00000000..76d9f593
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// nsWeakReference.cpp
+
+#include "nsWeakReference.h"
+#include "nsCOMPtr.h"
+
+nsresult
+nsQueryReferent::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mWeakPtr )
+ {
+ if ( NS_FAILED(status = mWeakPtr->QueryReferent(aIID, answer)) )
+ *answer = 0;
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+
+nsresult
+nsGetWeakReference::operator()( const nsIID&, void** aResult ) const
+ {
+ nsresult status;
+ // nsIWeakReference** result = &NS_STATIC_CAST(nsIWeakReference*, *aResult);
+ *aResult = 0;
+
+ if ( mRawPtr )
+ {
+ nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(mRawPtr, &status);
+ NS_ASSERTION(factoryPtr, "Oops! You're asking for a weak reference to an object that doesn't support that.");
+ if ( factoryPtr )
+ {
+ nsIWeakReference* temp;
+ status = factoryPtr->GetWeakReference(&temp);
+ *aResult = temp;
+ }
+ // else, |status| has already been set by |do_QueryInterface|
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+
+
+NS_COM nsIWeakReference* // or else |already_AddRefed<nsIWeakReference>|
+NS_GetWeakReference( nsISupports* aInstancePtr, nsresult* aErrorPtr )
+ {
+ void* result = 0;
+ nsGetWeakReference(aInstancePtr, aErrorPtr)(NS_GET_IID(nsIWeakReference), &result);
+ return NS_STATIC_CAST(nsIWeakReference*, result);
+ }
+
+NS_COM nsresult
+nsSupportsWeakReference::GetWeakReference( nsIWeakReference** aInstancePtr )
+ {
+ if ( !aInstancePtr )
+ return NS_ERROR_NULL_POINTER;
+
+ if ( !mProxy )
+ mProxy = new nsWeakReference(this);
+ *aInstancePtr = mProxy;
+
+ nsresult status;
+ if ( !*aInstancePtr )
+ status = NS_ERROR_OUT_OF_MEMORY;
+ else
+ {
+ NS_ADDREF(*aInstancePtr);
+ status = NS_OK;
+ }
+
+ return status;
+ }
+
+NS_IMETHODIMP_(nsrefcnt)
+nsWeakReference::AddRef()
+ {
+ return ++mRefCount;
+ }
+
+NS_IMETHODIMP_(nsrefcnt)
+nsWeakReference::Release()
+ {
+ nsrefcnt temp = --mRefCount;
+ if ( !mRefCount )
+ delete this;
+ return temp;
+ }
+
+NS_IMETHODIMP
+nsWeakReference::QueryInterface( const nsIID& aIID, void** aInstancePtr )
+ {
+ NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
+
+ if ( !aInstancePtr )
+ return NS_ERROR_NULL_POINTER;
+
+ nsISupports* foundInterface;
+ if ( aIID.Equals(NS_GET_IID(nsIWeakReference)) )
+ foundInterface = NS_STATIC_CAST(nsIWeakReference*, this);
+ else if ( aIID.Equals(NS_GET_IID(nsISupports)) )
+ foundInterface = NS_STATIC_CAST(nsISupports*, this);
+ else
+ foundInterface = 0;
+
+ nsresult status;
+ if ( !foundInterface )
+ status = NS_NOINTERFACE;
+ else
+ {
+ NS_ADDREF(foundInterface);
+ status = NS_OK;
+ }
+
+ *aInstancePtr = foundInterface;
+ return status;
+ }
+
+NS_IMETHODIMP
+nsWeakReference::QueryReferent( const nsIID& aIID, void** aInstancePtr )
+ {
+ return mReferent ? mReferent->QueryInterface(aIID, aInstancePtr) : NS_ERROR_NULL_POINTER;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h
new file mode 100644
index 00000000..96e63f22
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsWeakReference_h__
+#define nsWeakReference_h__
+
+// nsWeakReference.h
+
+#include "nsIWeakReference.h"
+
+class nsWeakReference;
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+
+class NS_COM nsSupportsWeakReference : public nsISupportsWeakReference
+ {
+ public:
+ nsSupportsWeakReference()
+ : mProxy(0)
+ {
+ // nothing else to do here
+ }
+
+ NS_DECL_NSISUPPORTSWEAKREFERENCE
+
+ protected:
+ inline ~nsSupportsWeakReference();
+
+ private:
+ friend class nsWeakReference;
+
+ void
+ NoticeProxyDestruction()
+ // ...called (only) by an |nsWeakReference| from _its_ dtor.
+ {
+ mProxy = 0;
+ }
+
+ nsWeakReference* mProxy;
+
+ protected:
+
+ inline void ClearWeakReferences();
+ PRBool HasWeakReferences() const {return mProxy != 0;}
+ };
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+class NS_COM nsWeakReference : public nsIWeakReference
+ {
+ public:
+ // nsISupports...
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+ // nsIWeakReference...
+ NS_DECL_NSIWEAKREFERENCE
+
+ private:
+ friend class nsSupportsWeakReference;
+
+ nsWeakReference( nsSupportsWeakReference* referent )
+ : mRefCount(0),
+ mReferent(referent)
+ // ...I can only be constructed by an |nsSupportsWeakReference|
+ {
+ // nothing else to do here
+ }
+
+ ~nsWeakReference()
+ // ...I will only be destroyed by calling |delete| myself.
+ {
+ if ( mReferent )
+ mReferent->NoticeProxyDestruction();
+ }
+
+ void
+ NoticeReferentDestruction()
+ // ...called (only) by an |nsSupportsWeakReference| from _its_ dtor.
+ {
+ mReferent = 0;
+ }
+
+ nsrefcnt mRefCount;
+ nsSupportsWeakReference* mReferent;
+ };
+
+inline
+void
+nsSupportsWeakReference::ClearWeakReferences()
+ /*
+ Usually being called from |nsSupportsWeakReference::~nsSupportsWeakReference|
+ will be good enough, but you may have a case where you need to call disconnect
+ your weak references in an outer destructor (to prevent some client holding a
+ weak reference from re-entering your destructor).
+ */
+ {
+ if ( mProxy )
+ {
+ mProxy->NoticeReferentDestruction();
+ mProxy = 0;
+ }
+ }
+
+inline
+nsSupportsWeakReference::~nsSupportsWeakReference()
+ {
+ ClearWeakReferences();
+ }
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/objs.mk b/src/libs/xpcom18a4/xpcom/glue/objs.mk
new file mode 100644
index 00000000..d6d04a5a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/objs.mk
@@ -0,0 +1,60 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# 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 *****
+
+XPCOM_GLUE_SRC_LCSRCS = \
+ nsCOMPtr.cpp \
+ nsComponentManagerUtils.cpp \
+ nsDebug.cpp \
+ nsGenericFactory.cpp \
+ nsIInterfaceRequestorUtils.cpp \
+ nsMemory.cpp \
+ nsTraceRefcnt.cpp \
+ nsWeakReference.cpp \
+ $(NULL) \
+
+XPCOM_GLUE_SRC_LEXPORTS = \
+ nsCOMPtr.h \
+ nsDebug.h \
+ nsGenericFactory.h \
+ nsIGenericFactory.h \
+ nsMemory.h \
+ nsTraceRefcnt.h \
+ nsWeakReference.h \
+ $(NULL)
+
+
+
+XPCOM_GLUE_SRC_CSRCS := $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCSRCS))
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore b/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore
new file mode 100644
index 00000000..a0182c1f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+nsCOMPtr.cpp
+nsDebug.cpp
+nsGenericFactory.cpp
+nsIInterfaceRequestorUtils.cpp
+nsMemory.cpp
+nsWeakReference.cpp
+nsComponentManagerUtils.cpp
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in b/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in
new file mode 100644
index 00000000..ae23d8e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in
@@ -0,0 +1,88 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2002
+# 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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+include $(srcdir)/../objs.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xpcomglue
+
+REQUIRES = string \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../build \
+ $(NULL)
+
+CPPSRCS = \
+ $(XPCOM_GLUE_SRC_LCSRCS) \
+ nsXPCOMGlue.cpp \
+ nsGREDirServiceProvider.cpp \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsXPCOMGlue.h \
+ $(NULL)
+
+SDK_LIBRARY = \
+ $(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+GARBAGE += $(XPCOM_GLUE_SRC_LCSRCS) $(wildcard *.$(OBJ_SUFFIX))
+
+ifeq ($(OS_ARCH),WINNT)
+GARBAGE += $(addprefix $(srcdir)/,$(XPCOM_GLUE_SRC_LCSRCS))
+endif
+
+SRCS_IN_OBJDIR = 1
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(XPCOM_GLUE_SRC_CSRCS)
+ $(INSTALL) $^ .
+
+DEFINES += -DXPCOM_GLUE
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp
new file mode 100644
index 00000000..4a1247eb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp
@@ -0,0 +1,596 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sean Su <ssu@netscape.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 "nsBuildID.h"
+
+#include "nsEmbedString.h"
+#include "nsXPCOMPrivate.h"
+#include "nsXPCOMGlue.h"
+#include "nsILocalFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCOMPtr.h"
+
+#include "nspr.h"
+#include "plstr.h"
+
+#ifdef XP_WIN32
+#include <windows.h>
+#include <stdlib.h>
+#elif defined(XP_OS2)
+#define INCL_DOS
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "prenv.h"
+#elif defined(XP_MACOSX)
+#include <Processes.h>
+#include <CFBundle.h>
+#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <dlfcn.h>
+#include "prenv.h"
+#elif defined(XP_BEOS)
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+#endif
+
+#include <sys/stat.h>
+
+#include "nsGREDirServiceProvider.h"
+
+PRBool GRE_GetCurrentProcessDirectory(char* buffer);
+PRBool GRE_GetPathFromConfigDir(const char* dirname, char* buffer);
+PRBool GRE_GetPathFromConfigFile(const char* dirname, char* buffer);
+
+//*****************************************************************************
+// nsGREDirServiceProvider::nsISupports
+//*****************************************************************************
+
+NS_IMPL_ISUPPORTS1(nsGREDirServiceProvider, nsIDirectoryServiceProvider)
+
+//*****************************************************************************
+// nsGREDirServiceProvider::nsIDirectoryServiceProvider
+//*****************************************************************************
+
+NS_IMETHODIMP
+nsGREDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
+{
+ *_retval = nsnull;
+ *persistant = PR_TRUE;
+
+ //---------------------------------------------------------------
+ // Note that by returning a valid localFile's for NS_GRE_DIR,
+ // your app is indicating to XPCOM that it found a GRE version
+ // with which it's compatible with and intends to be "run against"
+ // that GRE.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/GRE.html
+ // for more info on GRE.
+ //---------------------------------------------------------------
+ if(strcmp(prop, NS_GRE_DIR) == 0)
+ {
+ nsILocalFile* lfile = nsnull;
+ nsresult rv = GRE_GetGREDirectory(&lfile);
+ *_retval = lfile;
+ return rv;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+//*****************************************************************************
+// Implementations from nsXPCOMGlue.h and helper functions.
+//*****************************************************************************
+
+PRBool
+GRE_GetCurrentProcessDirectory(char* buffer)
+{
+ *buffer = '\0';
+
+#ifdef XP_WIN
+ if ( ::GetModuleFileName(0, buffer, MAXPATHLEN) ) {
+ // chop of the executable name by finding the rightmost backslash
+ char* lastSlash = PL_strrchr(buffer, '\\');
+ if (lastSlash) {
+ *(lastSlash) = '\0';
+ return PR_TRUE;
+ }
+ }
+
+#elif defined(XP_MACOSX)
+ // Works even if we're not bundled.
+ CFBundleRef appBundle = CFBundleGetMainBundle();
+ if (appBundle != nsnull)
+ {
+ CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
+ if (bundleURL != nsnull)
+ {
+ CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL);
+ if (parentURL)
+ {
+ CFStringRef path = CFURLCopyFileSystemPath(parentURL, kCFURLPOSIXPathStyle);
+ if (path)
+ {
+ CFStringGetCString(path, buffer, MAXPATHLEN, kCFStringEncodingUTF8);
+ CFRelease(path);
+ }
+ CFRelease(parentURL);
+ }
+ CFRelease(bundleURL);
+ }
+#if 0 /* bird: Causes crashes in objc_msgSend() later if released. I dunno why really.
+ Something could be seriously screwed up somewhere else, but this'll have
+ to do for now. (appBundle isn't released in the other place it's used.) */
+ CFRelease(appBundle);
+#endif
+ }
+ if (*buffer) return PR_TRUE;
+
+#elif defined(XP_UNIX)
+
+#if 0 /* we need .so location. */
+ // Actually we have a way on linux.
+ static volatile bool fPathSet = false;
+ static char szPath[MAXPATHLEN];
+ if (!fPathSet)
+ {
+ char buf2[MAXPATHLEN + 3];
+ buf2[0] = '\0';
+
+ /*
+ * Env.var. VBOX_XPCOM_HOME first.
+ */
+ char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (psz)
+ {
+ if (strlen(psz) < MAXPATHLEN)
+ {
+ if (!realpath(psz, buf2))
+ strcpy(buf2, psz);
+ strcat(buf2, "/x"); /* for the filename stripping */
+ }
+ }
+
+ /*
+ * The dynamic loader.
+ */
+ if (!buf2[0])
+ {
+ Dl_info DlInfo = {0};
+ if ( !dladdr((const void *)GRE_GetCurrentProcessDirectory, &DlInfo)
+ && DlInfo.dli_fname)
+ {
+ if (!realpath(DlInfo.dli_fname, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Executable location.
+ */
+ if (!buf2[0])
+ {
+ char buf[MAXPATHLEN];
+ int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (cchLink > 0 || cchLink != sizeof(buf) - 1)
+ {
+ buf[cchLink] = '\0';
+ if (!realpath(buf, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Copy to static buffer on success.
+ */
+ if (buf2[0])
+ {
+ char *p = strrchr(buf2, '/');
+ if (p)
+ {
+ p[p == buf2] = '\0';
+ #ifdef DEBUG
+ printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
+ #endif
+ strcpy(szPath, buf2);
+ fPathSet = true;
+ }
+ }
+ }
+ if (fPathSet)
+ {
+ strcpy(buffer, szPath);
+ return PR_TRUE;
+ }
+#endif
+
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ // - else give the current directory
+
+ // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
+ // a --with-default-mozilla-five-home=foo autoconf flag.
+ //
+ // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
+ // regardless of the environment. This makes it easier to write apps that
+ // embed mozilla without having to worry about setting up the environment
+ //
+ // We do this py putenv()ing the default value into the environment. Note that
+ // we only do this if it is not already set.
+#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
+ if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
+ {
+ putenv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
+ }
+#endif
+
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+
+ if (moz5 && *moz5)
+ {
+ if (!realpath(moz5, buffer))
+ strcpy(buffer, moz5);
+
+ return PR_TRUE;
+ }
+ else
+ {
+#if defined(DEBUG)
+ static PRBool firstWarning = PR_TRUE;
+
+ if(firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+#endif /* DEBUG */
+
+ // Fall back to current directory.
+ if (getcwd(buffer, MAXPATHLEN))
+ {
+ return PR_TRUE;
+ }
+ }
+
+#elif defined(XP_OS2)
+ PPIB ppib;
+ PTIB ptib;
+ char* p;
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, buffer);
+ p = strrchr( buffer, '\\'); // XXX DBCS misery
+ if (p) {
+ *p = '\0';
+ return PR_TRUE;
+ }
+
+#elif defined(XP_BEOS)
+
+ char *moz5 = getenv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ strcpy(buffer, moz5);
+ return PR_TRUE;
+ }
+ else
+ {
+ int32 cookie = 0;
+ image_info info;
+ char *p;
+ *buffer = 0;
+ if(get_next_image_info(0, &cookie, &info) == B_OK)
+ {
+ strcpy(buffer, info.name);
+ if((p = strrchr(buffer, '/')) != 0)
+ {
+ *p = 0;
+
+ return PR_TRUE;
+ }
+ }
+ }
+
+#endif
+
+ return PR_FALSE;
+}
+
+/**
+ * the GRE location is stored in a static buffer so that we don't have
+ * to compute it multiple times.
+ */
+
+static char sGRELocation[MAXPATHLEN] = "";
+
+extern "C" char const *
+GRE_GetGREPath()
+{
+ // we've already done this...
+ if (*sGRELocation)
+ return sGRELocation;
+
+ char buffer[MAXPATHLEN];
+
+ // If the xpcom library exists in the current process directory,
+ // then we will not use any GRE. The assumption here is that the
+ // GRE is in the same directory as the executable.
+ if (GRE_GetCurrentProcessDirectory(buffer)) {
+ PRUint32 pathlen = strlen(buffer);
+ strcpy(buffer + pathlen, XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL);
+
+ struct stat libStat;
+ int statResult = stat(buffer, &libStat);
+
+ if (statResult != -1) {
+ //found our xpcom lib in the current process directory
+ buffer[pathlen] = '\0';
+ strcpy(sGRELocation, buffer);
+ return sGRELocation;
+ }
+ }
+
+ // if GRE_HOME is in the environment, use that GRE
+ const char* env = PR_GetEnv("GRE_HOME");
+ if (env && *env) {
+#if XP_UNIX
+ if (!realpath(env, sGRELocation))
+ strcpy(sGRELocation, env);
+#elif XP_WIN32
+ if (!_fullpath(sGRELocation, env, MAXPATHLEN))
+ strcpy(sGRELocation, env);
+#endif
+ // xxxbsmedberg: it would help that other platforms had a "make absolute" function
+ return sGRELocation;
+ }
+
+ // the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH
+ env = PR_GetEnv("USE_LOCAL_GRE");
+ if (env && *env)
+ return nsnull;
+
+#if XP_UNIX
+ // check in the HOME directory
+ env = PR_GetEnv("HOME");
+ if (env && *env) {
+# ifdef VBOX
+ snprintf(buffer, sizeof(buffer), "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
+# else
+ sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
+# endif
+
+ if (GRE_GetPathFromConfigFile(buffer, sGRELocation)) {
+ return sGRELocation;
+ }
+ }
+#endif
+
+ env = PR_GetEnv("MOZ_GRE_CONF");
+ if (env) {
+ if (GRE_GetPathFromConfigFile(env, sGRELocation)) {
+ return sGRELocation;
+ }
+ }
+
+#if XP_UNIX
+ // Look for a group of config files in /etc/gre.d/
+ if (GRE_GetPathFromConfigDir(GRE_CONF_DIR, sGRELocation)) {
+ return sGRELocation;
+ }
+
+ // Look for a global /etc/gre.conf file
+ if (GRE_GetPathFromConfigFile(GRE_CONF_PATH, sGRELocation)) {
+ return sGRELocation;
+ }
+#endif
+
+#if XP_WIN32
+ char szKey[256];
+ HKEY hRegKey = NULL;
+ DWORD dwLength = MAXPATHLEN;
+
+ // A couple of key points here:
+ // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows
+ // us to have multiple versions of GREs on the same machine by having
+ // subkeys such as 1.0, 1.1, 2.0 etc. under it.
+ // 2. In this sample below we're looking for the location of GRE version 1.2
+ // i.e. we're compatible with GRE 1.2 and we're trying to find it's install
+ // location.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/GRE.html for
+ // more info.
+ //
+ strcpy(szKey, GRE_WIN_REG_LOC GRE_BUILD_ID);
+
+ if (::RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
+ if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
+ *sGRELocation = '\0';
+ }
+ ::RegCloseKey(hRegKey);
+
+ if (*sGRELocation)
+ return sGRELocation;
+ }
+
+ if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
+ if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
+ *sGRELocation = '\0';
+ }
+ ::RegCloseKey(hRegKey);
+
+ if (*sGRELocation)
+ return sGRELocation;
+ }
+#endif
+
+ return nsnull;
+}
+
+PRBool
+GRE_GetPathFromConfigDir(const char* dirname, char* buffer)
+{
+ // Open the directory provided and try to read any files in that
+ // directory that end with .conf. We look for an entry that might
+ // point to the GRE that we're interested in.
+ PRDir *dir = PR_OpenDir(dirname);
+ if (!dir)
+ return nsnull;
+
+ PRBool found = PR_FALSE;
+ PRDirEntry *entry;
+
+ while (!found && (entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
+
+ // Only look for files that end in .conf
+ char *offset = PL_strrstr(entry->name, ".conf");
+ if (!offset)
+ continue;
+
+ if (offset != entry->name + strlen(entry->name) - 5)
+ continue;
+
+ nsEmbedCString fullPath;
+ NS_CStringAppendData(fullPath, dirname);
+ NS_CStringAppendData(fullPath, XPCOM_FILE_PATH_SEPARATOR);
+ NS_CStringAppendData(fullPath, entry->name);
+
+ found = GRE_GetPathFromConfigFile(fullPath.get(), buffer);
+ }
+
+ PR_CloseDir(dir);
+
+ return found;
+}
+
+PRBool
+GRE_GetPathFromConfigFile(const char* filename, char* pathBuffer)
+{
+ *pathBuffer = '\0';
+ char buffer[1024];
+ FILE *cfg;
+ PRBool foundHeader = PR_FALSE;
+ PRInt32 versionLen = sizeof(GRE_BUILD_ID)-1;
+
+ if((cfg=fopen(filename,"r"))==nsnull) {
+ return nsnull;
+ }
+
+ while (fgets(buffer, 1024, cfg) != nsnull) {
+ // skip over comment lines and blank lines
+ if (buffer[0] == '#' || buffer[0] == '\n') {
+ continue;
+ }
+
+ // we found a section heading, check to see if it is the one we are intersted in.
+ if (buffer[0] == '[') {
+ if (!strncmp (buffer+1, GRE_BUILD_ID, versionLen)) {
+ foundHeader = PR_TRUE;
+ }
+ continue;
+ }
+
+ if (foundHeader && !strncmp (buffer, "GRE_PATH=", 9)) {
+ strcpy(pathBuffer, buffer + 9);
+ // kill the line feed if any
+ PRInt32 len = strlen(pathBuffer);
+ len--;
+
+ if (pathBuffer[len] == '\n')
+ pathBuffer[len] = '\0';
+ break;
+ }
+ }
+ fclose(cfg);
+ return (*pathBuffer != '\0');
+}
+
+extern "C" nsresult
+GRE_GetGREDirectory(nsILocalFile* *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ nsresult rv = NS_ERROR_FAILURE;
+
+ // Get the path of the GRE which is compatible with our embedding application
+ // from the registry
+
+ const char *pGREDir = GRE_GetGREPath();
+ if(pGREDir) {
+ nsCOMPtr<nsILocalFile> tempLocal;
+ nsEmbedCString leaf;
+ NS_CStringSetData(leaf, pGREDir);
+ rv = NS_NewNativeLocalFile(leaf, PR_TRUE, getter_AddRefs(tempLocal));
+
+ if (NS_SUCCEEDED(rv)) {
+ *_retval = tempLocal;
+ NS_ADDREF(*_retval);
+ }
+ }
+ return rv;
+}
+
+static char sXPCOMPath[MAXPATHLEN];
+
+extern "C" const char*
+GRE_GetXPCOMPath()
+{
+ const char* grePath = GRE_GetGREPath();
+
+ if (!grePath) {
+ grePath = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (!grePath || !*grePath) {
+ return nsnull;
+ }
+ }
+
+#ifdef VBOX
+ snprintf(sXPCOMPath, sizeof(sXPCOMPath), "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
+#else
+ sprintf(sXPCOMPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
+#endif
+
+ return sXPCOMPath;
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h
new file mode 100644
index 00000000..0638a127
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h
@@ -0,0 +1,68 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sean Su <ssu@netscape.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 ***** */
+
+#ifndef nsGREDirServiceProvider_h_
+#define nsGREDirServiceProvider_h_
+
+#include "nsIDirectoryService.h"
+
+#ifndef MAXPATHLEN
+#ifdef _MAX_PATH
+#define MAXPATHLEN _MAX_PATH
+#elif defined(CCHMAXPATH)
+#define MAXPATHLEN CCHMAXPATH
+#else
+#define MAXPATHLEN 1024
+#endif
+#endif
+
+/**
+ * the directoryserviceprovider used by GRE_Startup when calling NS_InitXPCOM2
+ */
+class nsGREDirServiceProvider : public nsIDirectoryServiceProvider
+{
+public:
+ nsGREDirServiceProvider() { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+
+private:
+ ~nsGREDirServiceProvider() { }
+};
+
+#endif // nsGREDirServiceProvider.h
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp
new file mode 100644
index 00000000..091538fa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -0,0 +1,524 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOMGlue.h"
+
+#include "nspr.h"
+#include "nsMemory.h"
+#include "nsGREDirServiceProvider.h"
+#include "nsXPCOMPrivate.h"
+#include <stdlib.h>
+#ifdef VBOX
+# include <limits.h>
+#endif
+
+#if XP_WIN32
+#include <windows.h>
+#endif
+
+void GRE_AddGREToEnvironment();
+
+// functions provided by nsMemory.cpp and nsDebug.cpp
+nsresult GlueStartupMemory();
+void GlueShutdownMemory();
+nsresult GlueStartupDebug();
+void GlueShutdownDebug();
+
+static PRLibrary *xpcomLib;
+static XPCOMFunctions xpcomFunctions;
+
+extern "C"
+nsresult XPCOMGlueStartup(const char* xpcomFile)
+{
+#ifdef XPCOM_GLUE_NO_DYNAMIC_LOADING
+ return NS_OK;
+#else
+ nsresult rv = NS_OK;
+ GetFrozenFunctionsFunc function = nsnull;
+
+ xpcomFunctions.version = XPCOM_GLUE_VERSION;
+ xpcomFunctions.size = sizeof(XPCOMFunctions);
+
+ //
+ // if xpcomFile == ".", then we assume xpcom is already loaded, and we'll
+ // use NSPR to find NS_GetFrozenFunctions from the list of already loaded
+ // libraries.
+ //
+ // otherwise, we try to load xpcom and then look for NS_GetFrozenFunctions.
+ // if xpcomFile == NULL, then we try to load xpcom by name w/o a fully
+ // qualified path.
+ //
+
+ if (xpcomFile && (xpcomFile[0] == '.' && xpcomFile[1] == '\0')) {
+ function = (GetFrozenFunctionsFunc)
+ PR_FindSymbolAndLibrary("NS_GetFrozenFunctions", &xpcomLib);
+ if (!function) {
+ // The symbol was not found, so failover to loading XPCOM_DLL,
+ // and look for the symbol there. See bug 240986 for details.
+ xpcomFile = nsnull;
+ }
+ else {
+ char *libPath = PR_GetLibraryFilePathname(XPCOM_DLL, (PRFuncPtr) function);
+ if (!libPath)
+ rv = NS_ERROR_FAILURE;
+ else {
+ rv = (*function)(&xpcomFunctions, libPath);
+ PR_Free(libPath);
+ }
+ }
+ }
+
+ if (!function) {
+ PRLibSpec libSpec;
+
+ libSpec.type = PR_LibSpec_Pathname;
+ if (!xpcomFile)
+ libSpec.value.pathname = XPCOM_DLL;
+ else
+ libSpec.value.pathname = xpcomFile;
+
+ xpcomLib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+#ifdef RT_OS_DARWIN /* vbox */
+ /* works around bundle problem. */
+ if (!xpcomLib) {
+ const char *home = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (home) {
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/%s", home, libSpec.value.pathname);
+ libSpec.value.pathname = path;
+ xpcomLib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+ }
+ }
+#endif
+ if (!xpcomLib)
+ return NS_ERROR_FAILURE;
+
+ function = (GetFrozenFunctionsFunc) PR_FindSymbol(xpcomLib, "NS_GetFrozenFunctions");
+
+ if (!function)
+ rv = NS_ERROR_FAILURE;
+ else
+ rv = (*function)(&xpcomFunctions, libSpec.value.pathname);
+ }
+
+ if (NS_FAILED(rv))
+ goto bail;
+
+ rv = GlueStartupDebug();
+ if (NS_FAILED(rv))
+ goto bail;
+
+ // startup the nsMemory
+ rv = GlueStartupMemory();
+ if (NS_FAILED(rv)) {
+ GlueShutdownDebug();
+ goto bail;
+ }
+
+ GRE_AddGREToEnvironment();
+ return NS_OK;
+
+bail:
+ PR_UnloadLibrary(xpcomLib);
+ xpcomLib = nsnull;
+ memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
+ return NS_ERROR_FAILURE;
+#endif
+}
+
+extern "C"
+nsresult XPCOMGlueShutdown()
+{
+#ifdef XPCOM_GLUE_NO_DYNAMIC_LOADING
+ return NS_OK;
+#else
+
+ GlueShutdownMemory();
+
+ GlueShutdownDebug();
+
+ if (xpcomLib) {
+ PR_UnloadLibrary(xpcomLib);
+ xpcomLib = nsnull;
+ }
+
+ memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
+ return NS_OK;
+#endif
+}
+
+#ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING
+extern "C" NS_COM nsresult
+NS_InitXPCOM2(nsIServiceManager* *result,
+ nsIFile* binDirectory,
+ nsIDirectoryServiceProvider* appFileLocationProvider)
+{
+ if (!xpcomFunctions.init)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.init(result, binDirectory, appFileLocationProvider);
+}
+
+extern "C" NS_COM nsresult
+NS_ShutdownXPCOM(nsIServiceManager* servMgr)
+{
+ if (!xpcomFunctions.shutdown)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.shutdown(servMgr);
+}
+
+extern "C" NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result)
+{
+ if (!xpcomFunctions.getServiceManager)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getServiceManager(result);
+}
+
+extern "C" NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result)
+{
+ if (!xpcomFunctions.getComponentManager)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getComponentManager(result);
+}
+
+extern "C" NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
+{
+ if (!xpcomFunctions.getComponentRegistrar)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getComponentRegistrar(result);
+}
+
+extern "C" NS_COM nsresult
+NS_GetMemoryManager(nsIMemory* *result)
+{
+ if (!xpcomFunctions.getMemoryManager)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getMemoryManager(result);
+}
+
+extern "C" NS_COM nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ if (!xpcomFunctions.newLocalFile)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.newLocalFile(path, followLinks, result);
+}
+
+extern "C" NS_COM nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ if (!xpcomFunctions.newNativeLocalFile)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.newNativeLocalFile(path, followLinks, result);
+}
+
+extern "C" NS_COM nsresult
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
+{
+ if (!xpcomFunctions.registerExitRoutine)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.registerExitRoutine(exitRoutine, priority);
+}
+
+extern "C" NS_COM nsresult
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
+{
+ if (!xpcomFunctions.unregisterExitRoutine)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.unregisterExitRoutine(exitRoutine);
+}
+
+extern "C" NS_COM nsresult
+NS_GetDebug(nsIDebug* *result)
+{
+ if (!xpcomFunctions.getDebug)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getDebug(result);
+}
+
+
+extern "C" NS_COM nsresult
+NS_GetTraceRefcnt(nsITraceRefcnt* *result)
+{
+ if (!xpcomFunctions.getTraceRefcnt)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getTraceRefcnt(result);
+}
+
+
+extern "C" NS_COM nsresult
+NS_StringContainerInit(nsStringContainer &aStr)
+{
+ if (!xpcomFunctions.stringContainerInit)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.stringContainerInit(aStr);
+}
+
+extern "C" NS_COM void
+NS_StringContainerFinish(nsStringContainer &aStr)
+{
+ if (xpcomFunctions.stringContainerFinish)
+ xpcomFunctions.stringContainerFinish(aStr);
+}
+
+extern "C" NS_COM PRUint32
+NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, PRBool *aTerm)
+{
+ if (!xpcomFunctions.stringGetData) {
+ *aBuf = nsnull;
+ return 0;
+ }
+ return xpcomFunctions.stringGetData(aStr, aBuf, aTerm);
+}
+
+extern "C" NS_COM PRUnichar *
+NS_StringCloneData(const nsAString &aStr)
+{
+ if (!xpcomFunctions.stringCloneData)
+ return nsnull;
+ return xpcomFunctions.stringCloneData(aStr);
+}
+
+extern "C" NS_COM nsresult
+NS_StringSetData(nsAString &aStr, const PRUnichar *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.stringSetData)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ return xpcomFunctions.stringSetData(aStr, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_StringSetDataRange(nsAString &aStr, PRUint32 aCutStart, PRUint32 aCutLength,
+ const PRUnichar *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.stringSetDataRange)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.stringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
+{
+ if (!xpcomFunctions.stringCopy)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.stringCopy(aDest, aSrc);
+}
+
+
+extern "C" NS_COM nsresult
+NS_CStringContainerInit(nsCStringContainer &aStr)
+{
+ if (!xpcomFunctions.cstringContainerInit)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringContainerInit(aStr);
+}
+
+extern "C" NS_COM void
+NS_CStringContainerFinish(nsCStringContainer &aStr)
+{
+ if (xpcomFunctions.cstringContainerFinish)
+ xpcomFunctions.cstringContainerFinish(aStr);
+}
+
+extern "C" NS_COM PRUint32
+NS_CStringGetData(const nsACString &aStr, const char **aBuf, PRBool *aTerm)
+{
+ if (!xpcomFunctions.cstringGetData) {
+ *aBuf = nsnull;
+ return 0;
+ }
+ return xpcomFunctions.cstringGetData(aStr, aBuf, aTerm);
+}
+
+extern "C" NS_COM char *
+NS_CStringCloneData(const nsACString &aStr)
+{
+ if (!xpcomFunctions.cstringCloneData)
+ return nsnull;
+ return xpcomFunctions.cstringCloneData(aStr);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringSetData(nsACString &aStr, const char *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.cstringSetData)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringSetData(aStr, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringSetDataRange(nsACString &aStr, PRUint32 aCutStart, PRUint32 aCutLength,
+ const char *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.cstringSetDataRange)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
+{
+ if (!xpcomFunctions.cstringCopy)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringCopy(aDest, aSrc);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest)
+{
+ if (!xpcomFunctions.cstringToUTF16)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest);
+}
+
+extern "C" NS_COM nsresult
+NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest)
+{
+ if (!xpcomFunctions.utf16ToCString)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest);
+}
+
+#endif // #ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING
+
+
+static char sEnvString[MAXPATHLEN*10];
+static char* spEnvString = 0;
+
+void
+GRE_AddGREToEnvironment()
+{
+ const char* grePath = GRE_GetGREPath();
+ char szPath[MAXPATHLEN];
+ if (!grePath)
+ return;
+
+ const char* path = PR_GetEnv(XPCOM_SEARCH_KEY);
+ if (!path)
+ path = "";
+#ifdef VBOX
+ else
+ {
+ /* sEnvString is part of the environment because of putenv().
+ * path is only temporarily used and not argument of putenv() itself */
+ snprintf(szPath, sizeof(szPath), "%s", path);
+ path = szPath;
+ }
+#endif
+
+ if (spEnvString) PR_smprintf_free(spEnvString);
+
+ /**
+ * if the PATH string is longer than our static buffer, allocate a
+ * buffer for the environment string. This buffer will be leaked at shutdown!
+ */
+ if (strlen(grePath) + strlen(path) +
+ sizeof(XPCOM_SEARCH_KEY) + sizeof(XPCOM_ENV_PATH_SEPARATOR) > MAXPATHLEN*10) {
+ if (PR_smprintf(XPCOM_SEARCH_KEY "=%s" XPCOM_ENV_PATH_SEPARATOR "%s",
+ grePath,
+ path)) {
+ PR_SetEnv(spEnvString);
+ }
+ } else {
+ if (sprintf(sEnvString,
+ XPCOM_SEARCH_KEY "=%s" XPCOM_ENV_PATH_SEPARATOR "%s",
+ grePath,
+ path) > 0) {
+ PR_SetEnv(sEnvString);
+ }
+ }
+
+#if XP_WIN32
+ // On windows, the current directory is searched before the
+ // PATH environment variable. This is a very bad thing
+ // since libraries in the cwd will be picked up before
+ // any that are in either the application or GRE directory.
+
+ if (grePath) {
+ SetCurrentDirectory(grePath);
+ }
+#endif
+}
+
+
+// Default GRE startup/shutdown code
+
+extern "C"
+nsresult GRE_Startup()
+{
+ const char* xpcomLocation = GRE_GetXPCOMPath();
+
+ // Startup the XPCOM Glue that links us up with XPCOM.
+ nsresult rv = XPCOMGlueStartup(xpcomLocation);
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("gre: XPCOMGlueStartup failed");
+ return rv;
+ }
+
+ nsGREDirServiceProvider *provider = new nsGREDirServiceProvider();
+ if ( !provider ) {
+ NS_WARNING("GRE_Startup failed");
+ XPCOMGlueShutdown();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_ADDREF( provider );
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, provider);
+ NS_RELEASE(provider);
+
+ if ( NS_FAILED(rv) || !servMan) {
+ NS_WARNING("gre: NS_InitXPCOM failed");
+ XPCOMGlueShutdown();
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+extern "C"
+nsresult GRE_Shutdown()
+{
+ NS_ShutdownXPCOM(nsnull);
+ XPCOMGlueShutdown();
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h
new file mode 100644
index 00000000..6044e084
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nscore.h"
+
+class nsILocalFile;
+
+/**
+ * Initialize the XPCOM glue by dynamically linking against the XPCOM
+ * shared library indicated by xpcomFile.
+ */
+
+extern "C"
+nsresult XPCOMGlueStartup(const char* xpcomFile);
+
+
+/**
+ * Finish the XPCOM glue after it is no longer needed.
+ */
+
+extern "C"
+nsresult XPCOMGlueShutdown();
+
+
+/**
+ * Locate the path of a compatible GRE.
+ *
+ * @return string buffer pointing to the GRE path (without a trailing
+ * directory separator). Callers do no need to free this buffer.
+ */
+
+extern "C"
+char const * GRE_GetGREPath();
+
+
+/**
+ * Locate the path of a compatible GRE. This is returned as an
+ * nsILocalFile instead of a char*.
+ *
+ * @param _retval Ordinary XPCOM getter, returns an addrefed interface.
+ */
+
+extern "C"
+nsresult GRE_GetGREDirectory(nsILocalFile* *_retval);
+
+
+/**
+ * Locate the path of the XPCOM binary of a compatible GRE.
+ * The result of this function is normally passed directly to
+ * XPCOMGlueStartup.
+ *
+ * @return string buffer pointing to the XPCOM DLL path. Callers do
+ * not need to free this buffer.
+ */
+
+extern "C"
+char const * GRE_GetXPCOMPath();
+
+
+/**
+ * Embedding applications which don't need a custom
+ * directoryserviceprovider may use GRE_Startup to start the XPCOM
+ * glue and initialize the GRE in one step.
+ */
+
+extern "C"
+nsresult GRE_Startup();
+
+
+/**
+ * Shut down XPCOM and the XPCOM glue in one step.
+ */
+
+extern "C"
+nsresult GRE_Shutdown();
diff --git a/src/libs/xpcom18a4/xpcom/io/.cvsignore b/src/libs/xpcom18a4/xpcom/io/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/io/Makefile.in b/src/libs/xpcom18a4/xpcom/io/Makefile.in
new file mode 100644
index 00000000..ed2f3f6d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/Makefile.in
@@ -0,0 +1,175 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = xpcom_io
+LIBRARY_NAME = xpcomio_s
+GRE_MODULE = 1
+REQUIRES = string \
+ $(NULL)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += macmorefiles
+endif
+
+CPPSRCS = \
+ nsAppFileLocationProvider.cpp \
+ nsBinaryStream.cpp \
+ nsByteArrayInputStream.cpp \
+ nsDirectoryService.cpp \
+ nsEscape.cpp \
+ nsFastLoadFile.cpp \
+ nsFastLoadService.cpp \
+ nsInputStreamTee.cpp \
+ nsLinebreakConverter.cpp \
+ nsLocalFileCommon.cpp \
+ nsMultiplexInputStream.cpp \
+ nsPipe3.cpp \
+ nsStreamUtils.cpp \
+ nsScriptableInputStream.cpp \
+ nsSegmentedBuffer.cpp \
+ SpecialSystemDirectory.cpp \
+ nsStorageStream.cpp \
+ nsStringStream.cpp \
+ nsUnicharInputStream.cpp \
+ nsNativeCharsetUtils.cpp \
+ $(NULL)
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
+CPPSRCS += nsLocalFileOS2.cpp
+else
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+CPPSRCS += nsLocalFileOSX.cpp
+else
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+CPPSRCS += nsLocalFileWin.cpp
+else
+CPPSRCS += nsLocalFileUnix.cpp
+endif # windows
+endif # mac
+endif # OS2
+
+EXPORTS = \
+ nsAppDirectoryServiceDefs.h \
+ nsDirectoryService.h \
+ nsDirectoryServiceUtils.h \
+ nsEscape.h \
+ nsFastLoadPtr.h \
+ nsFastLoadService.h \
+ nsIUnicharInputStream.h \
+ nsLinebreakConverter.h \
+ nsLocalFile.h \
+ nsMultiplexInputStream.h \
+ nsScriptableInputStream.h \
+ nsStorageStream.h \
+ nsStringIO.h \
+ nsStringStream.h \
+ nsStreamUtils.h \
+ nsNativeCharsetUtils.h \
+ $(NULL)
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
+EXPORTS += nsLocalFileOS2.h
+else
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+EXPORTS += nsLocalFileOSX.h
+else
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+EXPORTS += nsLocalFileWin.h
+else
+EXPORTS += nsLocalFileUnix.h
+endif # windows
+endif # mac
+endif # os2
+
+XPIDLSRCS = \
+ nsIBinaryInputStream.idl \
+ nsIBinaryOutputStream.idl \
+ nsIByteArrayInputStream.idl \
+ nsIFastLoadFileControl.idl \
+ nsIFastLoadService.idl \
+ nsIInputStreamTee.idl \
+ nsILineInputStream.idl \
+ nsIMultiplexInputStream.idl \
+ nsIObjectInputStream.idl \
+ nsIObjectOutputStream.idl \
+ nsIPipe.idl \
+ nsISeekableStream.idl \
+ nsIStorageStream.idl \
+ nsIStringStream.idl \
+ nsIStreamBufferAccess.idl \
+ nsIAsyncInputStream.idl \
+ nsIAsyncOutputStream.idl \
+ $(NULL)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+XPIDLSRCS += nsILocalFileMac.idl
+endif
+
+SDK_XPIDLSRCS = \
+ nsIDirectoryService.idl \
+ nsIFile.idl \
+ nsILocalFile.idl \
+ nsIInputStream.idl \
+ nsIOutputStream.idl \
+ nsIScriptableInputStream.idl \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsDirectoryServiceDefs.h \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM
+
+LOCAL_INCLUDES = -I..
diff --git a/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp
new file mode 100644
index 00000000..5d1bc4fd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp
@@ -0,0 +1,770 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "SpecialSystemDirectory.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+
+
+#ifdef XP_MAC
+
+#include <Folders.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#include "nsIInternetConfigService.h"
+
+
+#if UNIVERSAL_INTERFACES_VERSION < 0x0340
+ enum {
+ kSystemDomain = -32766, /* Read-only system hierarchy.*/
+ kLocalDomain = -32765, /* All users of a single machine have access to these resources.*/
+ kNetworkDomain = -32764, /* All users configured to use a common network server has access to these resources.*/
+ kUserDomain = -32763, /* Read/write. Resources that are private to the user.*/
+ kClassicDomain = -32762, /* Domain referring to the currently configured Classic System Folder*/
+
+ kDomainLibraryFolderType = FOUR_CHAR_CODE('dlib')
+ };
+#endif
+
+#elif defined(XP_WIN)
+
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#elif defined(XP_OS2)
+
+#define MAX_PATH _MAX_PATH
+#define INCL_WINWORKPLACE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSPROCESS
+#define INCL_WINSHELLDATA
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "prenv.h"
+
+#elif defined(XP_UNIX)
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "prenv.h"
+# if defined(XP_MACOSX) && defined(VBOX_WITH_NEWER_OSX_SDK)
+# include <Folders.h>
+# endif
+
+#elif defined(XP_BEOS)
+
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+
+#endif
+
+#if defined(VMS)
+#include <unixlib.h>
+#endif
+
+
+
+#if defined (XP_WIN)
+typedef BOOL (WINAPI * GetSpecialPathProc) (HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+GetSpecialPathProc gGetSpecialPathProc = NULL;
+static HINSTANCE gShell32DLLInst = NULL;
+#endif
+NS_COM void StartupSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ /* On windows, the old method to get file locations is incredibly slow.
+ As of this writing, 3 calls to GetWindowsFolder accounts for 3% of mozilla
+ startup. Replacing these older calls with a single call to SHGetSpecialFolderPath
+ effectively removes these calls from the performace radar. We need to
+ support the older way of file location lookup on systems that do not have
+ IE4. (Note: gets the ansi version: SHGetSpecialFolderPathA).
+ */
+ gShell32DLLInst = LoadLibrary("Shell32.dll");
+ if(gShell32DLLInst)
+ {
+ gGetSpecialPathProc = (GetSpecialPathProc) GetProcAddress(gShell32DLLInst,
+ "SHGetSpecialFolderPathA");
+ }
+#endif
+}
+
+NS_COM void ShutdownSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ if (gShell32DLLInst)
+ {
+ FreeLibrary(gShell32DLLInst);
+ gShell32DLLInst = NULL;
+ gGetSpecialPathProc = NULL;
+ }
+#endif
+}
+
+#if defined (XP_WIN)
+
+//----------------------------------------------------------------------------------------
+static nsresult GetWindowsFolder(int folder, nsILocalFile** aFile)
+//----------------------------------------------------------------------------------------
+{
+ if (gGetSpecialPathProc) {
+ TCHAR path[MAX_PATH];
+ HRESULT result = gGetSpecialPathProc(NULL, path, folder, true);
+
+ if (!SUCCEEDED(result))
+ return NS_ERROR_FAILURE;
+
+ // Append the trailing slash
+ int len = strlen(path);
+ if (len>1 && path[len-1] != '\\')
+ {
+ path[len] = '\\';
+ path[len + 1] = '\0';
+ }
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ nsresult rv = NS_ERROR_FAILURE;
+ LPMALLOC pMalloc = NULL;
+ LPSTR pBuffer = NULL;
+ LPITEMIDLIST pItemIDList = NULL;
+ int len;
+
+ // Get the shell's allocator.
+ if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
+ return NS_ERROR_FAILURE;
+
+ // Allocate a buffer
+ if ((pBuffer = (LPSTR) pMalloc->Alloc(MAX_PATH + 2)) == NULL)
+ return NS_ERROR_FAILURE;
+
+ // Get the PIDL for the folder.
+ if (!SUCCEEDED(SHGetSpecialFolderLocation(
+ NULL, folder, &pItemIDList)))
+ goto Clean;
+
+ if (!SUCCEEDED(SHGetPathFromIDList(pItemIDList, pBuffer)))
+ goto Clean;
+
+ // Append the trailing slash
+ len = strlen(pBuffer);
+ pBuffer[len] = '\\';
+ pBuffer[len + 1] = '\0';
+
+ // Assign the directory
+ rv = NS_NewNativeLocalFile(nsDependentCString(pBuffer),
+ PR_TRUE,
+ aFile);
+
+Clean:
+ // Clean up.
+ if (pItemIDList)
+ pMalloc->Free(pItemIDList);
+ if (pBuffer)
+ pMalloc->Free(pBuffer);
+
+ pMalloc->Release();
+
+ return rv;
+}
+
+#endif // XP_WIN
+
+
+
+
+nsresult
+GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
+ nsILocalFile** aFile)
+{
+#ifdef XP_MAC
+ OSErr err;
+ short vRefNum;
+ long dirID;
+#endif
+
+ switch (aSystemSystemDirectory)
+ {
+ case OS_DriveDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+ if (len)
+ {
+ if ( path[1] == ':' && path[2] == '\\' )
+ path[3] = 0;
+ }
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_OS2)
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_MAC)
+ {
+ return nsIFileFromOSType(kVolumeRootFolderType, aFile);
+ }
+#else
+ return NS_NewNativeLocalFile(nsDependentCString("/"),
+ PR_TRUE,
+ aFile);
+
+#endif
+
+ case OS_TemporaryDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ DWORD len = GetTempPath(_MAX_PATH, path);
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_OS2)
+ {
+ char buffer[CCHMAXPATH] = "";
+ char *c = getenv( "TMP");
+ if( c) strcpy( buffer, c);
+ else
+ {
+ c = getenv( "TEMP");
+ if( c) strcpy( buffer, c);
+ }
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_MAC)
+ return nsIFileFromOSType(kTemporaryFolderType, aFile);
+
+#elif defined(XP_MACOSX)
+ {
+ return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
+ }
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ {
+ static const char *tPath = nsnull;
+ if (!tPath) {
+ tPath = PR_GetEnv("TMPDIR");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TMP");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TEMP");
+ if (!tPath || !*tPath) {
+ tPath = "/tmp/";
+ }
+ }
+ }
+ }
+ return NS_NewNativeLocalFile(nsDependentCString(tPath),
+ PR_TRUE,
+ aFile);
+ }
+#else
+ break;
+#endif
+
+#if defined(XP_MAC)
+ case Mac_SystemDirectory:
+ return nsIFileFromOSType(kSystemFolderType, aFile);
+
+ case Mac_DesktopDirectory:
+ return nsIFileFromOSType(kDesktopFolderType, aFile);
+
+ case Mac_TrashDirectory:
+ return nsIFileFromOSType(kTrashFolderType, aFile);
+
+ case Mac_StartupDirectory:
+ return nsIFileFromOSType(kStartupFolderType, aFile);
+
+ case Mac_ShutdownDirectory:
+ return nsIFileFromOSType(kShutdownFolderType, aFile);
+
+ case Mac_AppleMenuDirectory:
+ return nsIFileFromOSType(kAppleMenuFolderType, aFile);
+
+ case Mac_ControlPanelDirectory:
+ return nsIFileFromOSType(kControlPanelFolderType, aFile);
+
+ case Mac_ExtensionDirectory:
+ return nsIFileFromOSType(kExtensionFolderType, aFile);
+
+ case Mac_FontsDirectory:
+ return nsIFileFromOSType(kFontsFolderType, aFile);
+
+ case Mac_ClassicPreferencesDirectory:
+ {
+ // whether Mac OS X or pre-Mac OS X, return Classic's Prefs folder
+ short domain;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ domain = (!err && response >= 0x00001000) ? kClassicDomain : kOnSystemDisk;
+ err = ::FindFolder(domain, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ return NS_FILE_RESULT(err);
+ }
+
+ case Mac_PreferencesDirectory:
+ {
+ // if Mac OS X, return Mac OS X's Prefs folder
+ // if pre-Mac OS X, return Mac OS's Prefs folder
+ err = ::FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ return NS_FILE_RESULT(err);
+ }
+
+ case Mac_DocumentsDirectory:
+ return nsIFileFromOSType(kDocumentsFolderType, aFile);
+
+ case Mac_InternetSearchDirectory:
+ return nsIFileFromOSType(kInternetSearchSitesFolderType, aFile);
+
+ case Mac_DefaultDownloadDirectory:
+ return nsIFileFromOSType(kDefaultDownloadFolderType, aFile);
+
+ case Mac_UserLibDirectory:
+ {
+ FSSpec spec;
+ err = ::FindFolder(kUserDomain, kDomainLibraryFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &spec);
+ }
+
+ return NS_NewLocalFileWithFSSpec(&spec, PR_FALUE, aFile);
+ }
+#endif
+
+#if defined (XP_WIN)
+ case Win_SystemDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetSystemDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case Win_WindowsDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case Win_HomeDirectory:
+ {
+ char path[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOME"), path, _MAX_PATH) > 0)
+ {
+ PRInt32 len = strlen(path);
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ if (GetEnvironmentVariable(TEXT("HOMEDRIVE"), path, _MAX_PATH) > 0)
+ {
+ char temp[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOMEPATH"), temp, _MAX_PATH) > 0)
+ strncat(path, temp, _MAX_PATH);
+
+ PRInt32 len = strlen(path);
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+ }
+ case Win_Desktop:
+ {
+ return GetWindowsFolder(CSIDL_DESKTOP, aFile);
+ }
+ case Win_Programs:
+ {
+ return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
+ }
+ case Win_Controls:
+ {
+ return GetWindowsFolder(CSIDL_CONTROLS, aFile);
+ }
+ case Win_Printers:
+ {
+ return GetWindowsFolder(CSIDL_PRINTERS, aFile);
+ }
+ case Win_Personal:
+ {
+ return GetWindowsFolder(CSIDL_PERSONAL, aFile);
+ }
+ case Win_Favorites:
+ {
+ return GetWindowsFolder(CSIDL_FAVORITES, aFile);
+ }
+ case Win_Startup:
+ {
+ return GetWindowsFolder(CSIDL_STARTUP, aFile);
+ }
+ case Win_Recent:
+ {
+ return GetWindowsFolder(CSIDL_RECENT, aFile);
+ }
+ case Win_Sendto:
+ {
+ return GetWindowsFolder(CSIDL_SENDTO, aFile);
+ }
+ case Win_Bitbucket:
+ {
+ return GetWindowsFolder(CSIDL_BITBUCKET, aFile);
+ }
+ case Win_Startmenu:
+ {
+ return GetWindowsFolder(CSIDL_STARTMENU, aFile);
+ }
+ case Win_Desktopdirectory:
+ {
+ return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Drives:
+ {
+ return GetWindowsFolder(CSIDL_DRIVES, aFile);
+ }
+ case Win_Network:
+ {
+ return GetWindowsFolder(CSIDL_NETWORK, aFile);
+ }
+ case Win_Nethood:
+ {
+ return GetWindowsFolder(CSIDL_NETHOOD, aFile);
+ }
+ case Win_Fonts:
+ {
+ return GetWindowsFolder(CSIDL_FONTS, aFile);
+ }
+ case Win_Templates:
+ {
+ return GetWindowsFolder(CSIDL_TEMPLATES, aFile);
+ }
+ case Win_Common_Startmenu:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_STARTMENU, aFile);
+ }
+ case Win_Common_Programs:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_PROGRAMS, aFile);
+ }
+ case Win_Common_Startup:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_STARTUP, aFile);
+ }
+ case Win_Common_Desktopdirectory:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Appdata:
+ {
+ return GetWindowsFolder(CSIDL_APPDATA, aFile);
+ }
+ case Win_Printhood:
+ {
+ return GetWindowsFolder(CSIDL_PRINTHOOD, aFile);
+ }
+ case Win_Cookies:
+ {
+ return GetWindowsFolder(CSIDL_COOKIES, aFile);
+ }
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+ case Unix_LocalDirectory:
+ return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
+ PR_TRUE,
+ aFile);
+ case Unix_LibDirectory:
+ return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"),
+ PR_TRUE,
+ aFile);
+
+ case Unix_HomeDirectory:
+#ifdef VMS
+ {
+ char *pHome;
+ pHome = getenv("HOME");
+ if (*pHome == '/') {
+ return NS_NewNativeLocalFile(nsDependentCString(pHome),
+ PR_TRUE,
+ aFile);
+
+ }
+ else
+ {
+ return NS_NewNativeLocalFile(nsDependentCString(decc$translate_vms(pHome)),
+ PR_TRUE,
+ aFile);
+ }
+ }
+#else
+ return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
+ PR_TRUE,
+ aFile);
+
+#endif
+
+#endif
+
+#ifdef XP_BEOS
+ case BeOS_SettingsDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_SETTINGS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case BeOS_HomeDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case BeOS_DesktopDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_DESKTOP_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case BeOS_SystemDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_BEOS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+#endif
+#ifdef XP_OS2
+ case OS2_SystemDirectory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\System\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+
+ case OS2_OS2Directory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+
+ case OS2_HomeDirectory:
+ {
+ nsresult rv;
+ char *tPath = PR_GetEnv("MOZILLA_HOME");
+ char buffer[CCHMAXPATH];
+ /* If MOZILLA_HOME is not set, use GetCurrentProcessDirectory */
+ /* To ensure we get a long filename system */
+ if (!tPath || !*tPath) {
+ PPIB ppib;
+ PTIB ptib;
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, CCHMAXPATH, buffer);
+ *strrchr( buffer, '\\') = '\0'; // XXX DBCS misery
+ tPath = buffer;
+ }
+ rv = NS_NewNativeLocalFile(nsDependentCString(tPath),
+ PR_TRUE,
+ aFile);
+
+ PrfWriteProfileString(HINI_USERPROFILE, "Mozilla", "Home", tPath);
+ return rv;
+ }
+
+ case OS2_DesktopDirectory:
+ {
+ char szPath[CCHMAXPATH + 1];
+ BOOL fSuccess;
+ fSuccess = WinQueryActiveDesktopPathname (szPath, sizeof(szPath));
+ int len = strlen (szPath);
+ if (len > CCHMAXPATH -1)
+ break;
+ szPath[len] = '\\';
+ szPath[len + 1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(szPath),
+ PR_TRUE,
+ aFile);
+ }
+#endif
+ default:
+ break;
+ }
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+#if defined (XP_MACOSX)
+nsresult
+GetOSXFolderType(short aDomain, OSType aFolderType, nsILocalFile **localFile)
+{
+ OSErr err;
+ FSRef fsRef;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
+ if (err == noErr)
+ {
+ NS_NewLocalFile(EmptyString(), PR_TRUE, localFile);
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*localFile));
+ if (localMacFile)
+ rv = localMacFile->InitWithFSRef(&fsRef);
+ }
+ return rv;
+}
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h
new file mode 100644
index 00000000..b4aaf30e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _SPECIALSYSTEMDIRECTORY_H_
+#define _SPECIALSYSTEMDIRECTORY_H_
+
+#include "nscore.h"
+#include "nsILocalFile.h"
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+# ifndef VBOX_WITH_NEWER_OSX_SDK
+# include <Types.h>
+# endif
+#include "nsILocalFileMac.h"
+#include "prenv.h"
+#endif
+
+
+extern NS_COM void StartupSpecialSystemDirectory();
+extern NS_COM void ShutdownSpecialSystemDirectory();
+
+
+enum SystemDirectories {
+ OS_DriveDirectory = 1,
+ OS_TemporaryDirectory = 2,
+ OS_CurrentProcessDirectory= 3,
+ OS_CurrentWorkingDirectory= 4,
+ XPCOM_CurrentProcessComponentDirectory= 5,
+ XPCOM_CurrentProcessComponentRegistry= 6,
+
+ Moz_BinDirectory = 100 ,
+ Mac_SystemDirectory = 101,
+ Mac_DesktopDirectory = 102,
+ Mac_TrashDirectory = 103,
+ Mac_StartupDirectory = 104,
+ Mac_ShutdownDirectory = 105,
+ Mac_AppleMenuDirectory = 106,
+ Mac_ControlPanelDirectory = 107,
+ Mac_ExtensionDirectory = 108,
+ Mac_FontsDirectory = 109,
+ Mac_ClassicPreferencesDirectory = 110,
+ Mac_DocumentsDirectory = 111,
+ Mac_InternetSearchDirectory = 112,
+ Mac_DefaultDownloadDirectory = 113,
+ Mac_UserLibDirectory = 114,
+ Mac_PreferencesDirectory = 115,
+
+ Win_SystemDirectory = 201,
+ Win_WindowsDirectory = 202,
+ Win_HomeDirectory = 203,
+ Win_Desktop = 204,
+ Win_Programs = 205,
+ Win_Controls = 206,
+ Win_Printers = 207,
+ Win_Personal = 208,
+ Win_Favorites = 209,
+ Win_Startup = 210,
+ Win_Recent = 211,
+ Win_Sendto = 212,
+ Win_Bitbucket = 213,
+ Win_Startmenu = 214,
+ Win_Desktopdirectory = 215,
+ Win_Drives = 216,
+ Win_Network = 217,
+ Win_Nethood = 218,
+ Win_Fonts = 219,
+ Win_Templates = 220,
+ Win_Common_Startmenu = 221,
+ Win_Common_Programs = 222,
+ Win_Common_Startup = 223,
+ Win_Common_Desktopdirectory = 224,
+ Win_Appdata = 225,
+ Win_Printhood = 226,
+ Win_Cookies = 227,
+
+ Unix_LocalDirectory = 301,
+ Unix_LibDirectory = 302,
+ Unix_HomeDirectory = 303,
+
+ BeOS_SettingsDirectory = 401,
+ BeOS_HomeDirectory = 402,
+ BeOS_DesktopDirectory = 403,
+ BeOS_SystemDirectory = 404,
+
+ OS2_SystemDirectory = 501,
+ OS2_OS2Directory = 502,
+ OS2_DesktopDirectory = 503,
+ OS2_HomeDirectory = 504
+};
+
+nsresult
+GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
+ nsILocalFile** aFile);
+#if defined(XP_MACOSX)
+nsresult
+GetOSXFolderType(short aDomain, OSType aFolderType, nsILocalFile **localFile);
+#endif
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c
new file mode 100644
index 00000000..838dffa2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c
@@ -0,0 +1,784 @@
+/*
+** Apple Macintosh Developer Technical Support
+**
+** DirectoryCopy: A robust, general purpose directory copy routine.
+**
+** by Jim Luther, Apple Developer Technical Support Emeritus
+**
+** File: DirectoryCopy.c
+**
+** Copyright © 1992-1998 Apple Computer, Inc.
+** All rights reserved.
+**
+** You may incorporate this sample code into your applications without
+** restriction, though the sample code has been provided "AS IS" and the
+** responsibility for its operation is 100% yours. However, what you are
+** not permitted to do is to redistribute the source as "DSC Sample Code"
+** after having made changes. If you're going to re-distribute the source,
+** we require that you make it clear in the source that the code was
+** descended from Apple Sample Code, but that you've made changes.
+*/
+
+// Modified to allow renaming the destination folder
+
+#include <Types.h>
+#include <Errors.h>
+#include <Memory.h>
+#include <Files.h>
+#include <Script.h>
+
+#define __COMPILINGMOREFILES
+
+#include "MoreFiles.h"
+#include "MoreFilesExtras.h"
+#include "MoreDesktopMgr.h"
+#include "FileCopy.h"
+#include "MacDirectoryCopy.h"
+#include <string.h>
+
+
+/*****************************************************************************/
+
+enum
+{
+ getNextItemOp = 1, /* couldn't access items in this directory - no access privileges */
+ copyDirCommentOp = 2, /* couldn't copy directory's Finder comment */
+ copyDirAccessPrivsOp = 3, /* couldn't copy directory's AFP access privileges */
+ copyDirFMAttributesOp = 4, /* couldn't copy directory's File Manager attributes */
+ dirCreateOp = 5, /* couldn't create destination directory */
+ fileCopyOp = 6 /* couldn't copy file */
+};
+
+/*****************************************************************************/
+
+
+
+#define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \
+ (*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName))
+
+/*****************************************************************************/
+
+typedef pascal Boolean (*CopyFilterProcPtr) (const CInfoPBRec * const cpbPtr);
+
+/* ¦ Prototype for the CopyFilterProc function.
+ This is the prototype for the CopyFilterProc function called by
+ FilteredDirectoryCopy and GetLevelSize. If true is returned,
+ the file/folder is included in the copy, otherwise it is excluded.
+
+ pb input: Points to the CInfoPBRec for the item under consideration.
+
+ __________
+
+ Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy
+*/
+
+#define CallCopyFilterProc(userRoutine, cpbPtr) (*(userRoutine))((cpbPtr))
+
+
+
+/*****************************************************************************/
+
+/* local constants */
+
+enum
+{
+ dirCopyBigCopyBuffSize = 0x00004000,
+ dirCopyMinCopyBuffSize = 0x00000200
+};
+
+
+/*****************************************************************************/
+
+/* local data structures */
+
+/* The EnumerateGlobals structure is used to minimize the amount of
+** stack space used when recursively calling CopyLevel and to hold
+** global information that might be needed at any time. */
+
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=mac68k
+#endif
+struct EnumerateGlobals
+{
+ Ptr copyBuffer; /* pointer to buffer used for file copy operations */
+ long bufferSize; /* the size of the copy buffer */
+ CopyErrProcPtr errorHandler; /* pointer to error handling function */
+ CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
+ OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */
+ Boolean bailout; /* set to true to by error handling function if fatal error */
+ short destinationVRefNum; /* the destination vRefNum */
+ Str63 itemName; /* the name of the current item */
+ CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
+};
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=reset
+#endif
+
+typedef struct EnumerateGlobals EnumerateGlobals;
+typedef EnumerateGlobals *EnumerateGlobalsPtr;
+
+
+/* The PreflightGlobals structure is used to minimize the amount of
+** stack space used when recursively calling GetLevelSize and to hold
+** global information that might be needed at any time. */
+
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=mac68k
+#endif
+struct PreflightGlobals
+{
+ OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
+ Str63 itemName; /* the name of the current item */
+ CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
+
+ unsigned long dstBlksPerAllocBlk; /* the number of 512 byte blocks per allocation block on destination */
+
+ unsigned long allocBlksNeeded; /* the total number of allocation blocks needed */
+
+ unsigned long tempBlocks; /* temporary storage for calculations (save some stack space) */
+ CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
+};
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=reset
+#endif
+
+typedef struct PreflightGlobals PreflightGlobals;
+typedef PreflightGlobals *PreflightGlobalsPtr;
+
+/*****************************************************************************/
+
+/* static prototypes */
+
+static void GetLevelSize(long currentDirID,
+ PreflightGlobals *theGlobals);
+
+static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
+ long srcDirID,
+ short dstVRefNum,
+ CopyFilterProcPtr copyFilterProc,
+ Boolean *spaceOK);
+
+static void CopyLevel(long sourceDirID,
+ long dstDirID,
+ EnumerateGlobals *theGlobals);
+
+/*****************************************************************************/
+
+static void GetLevelSize(long currentDirID,
+ PreflightGlobals *theGlobals)
+{
+ short index = 1;
+
+ do
+ {
+ theGlobals->myCPB.dirInfo.ioFDirIndex = index;
+ theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID; /* we need to do this every time */
+ /* through, since GetCatInfo */
+ /* returns ioFlNum in this field */
+ theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB);
+ if ( theGlobals->result == noErr )
+ {
+ if ( (theGlobals->copyFilterProc == NULL) ||
+ CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
+ {
+ /* Either there's no filter proc OR the filter proc says to use this item */
+ if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ /* we have a directory */
+
+ GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */
+ theGlobals->result = noErr; /* clear error return on way back */
+ }
+ else
+ {
+ /* We have a file - add its allocation blocks to allocBlksNeeded. */
+ /* Since space on Mac OS disks is always allocated in allocation blocks, */
+ /* this takes into account rounding up to the end of an allocation block. */
+
+ /* get number of 512-byte blocks needed for data fork */
+ if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 )
+ {
+ theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1;
+ }
+ else
+ {
+ theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9;
+ }
+ /* now, calculate number of new allocation blocks needed for the data fork and add it to the total */
+ if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
+ {
+ theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
+ }
+ else
+ {
+ theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
+ }
+
+ /* get number of 512-byte blocks needed for resource fork */
+ if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 )
+ {
+ theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1;
+ }
+ else
+ {
+ theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9;
+ }
+ /* now, calculate number of new allocation blocks needed for the resource fork and add it to the total */
+ if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
+ {
+ theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
+ }
+ else
+ {
+ theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
+ }
+ }
+ }
+ }
+ ++index;
+ } while ( theGlobals->result == noErr );
+}
+
+/*****************************************************************************/
+
+static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
+ long srcDirID,
+ short dstVRefNum,
+ CopyFilterProcPtr copyFilterProc,
+ Boolean *spaceOK)
+{
+ XVolumeParam pb;
+ OSErr error;
+ unsigned long dstFreeBlocks;
+ PreflightGlobals theGlobals;
+
+ error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb);
+ if ( error == noErr )
+ {
+ /* Convert freeBytes to free disk blocks (512-byte blocks) */
+#if (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
+ dstFreeBlocks = (pb.ioVFreeBytes >> 9);
+#else
+ dstFreeBlocks = (pb.ioVFreeBytes.hi << 23) + (pb.ioVFreeBytes.lo >> 9);
+#endif
+ /* get allocation block size (always multiple of 512) and divide by 512
+ to get number of 512-byte blocks per allocation block */
+ theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9);
+
+ theGlobals.allocBlksNeeded = 0;
+
+ theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
+ theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
+
+ theGlobals.copyFilterProc = copyFilterProc;
+
+ GetLevelSize(srcDirID, &theGlobals);
+
+ /* Is there enough room on the destination volume for the source file? */
+ /* Note: This will work because the largest number of disk blocks supported */
+ /* on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk) */
+ /* will always be less than 0xffffffff. */
+ *spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks);
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+static void CopyLevel(long sourceDirID,
+ long dstDirID,
+ EnumerateGlobals *theGlobals)
+{
+ long currentSrcDirID;
+ long newDirID;
+ short index = 1;
+
+ do
+ {
+ /* Get next source item at the current directory level */
+
+ theGlobals->myCPB.dirInfo.ioFDirIndex = index;
+ theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID;
+ theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB);
+
+ if ( theGlobals->error == noErr )
+ {
+ if ( (theGlobals->copyFilterProc == NULL) ||
+ CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
+ {
+ /* Either there's no filter proc OR the filter proc says to use this item */
+
+ /* We have an item. Is it a file or directory? */
+ if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ /* We have a directory */
+
+ /* Create a new directory at the destination. No errors allowed! */
+ theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID);
+ if ( theGlobals->error == noErr )
+ {
+ /* Save the current source directory ID where we can get it when we come back
+ ** from recursion land. */
+ currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID;
+
+ /* Dive again (copy the directory level we just found below this one) */
+ CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals);
+
+ if ( !theGlobals->bailout )
+ {
+ /* Copy comment from old to new directory. */
+ /* Ignore the result because we really don't care if it worked or not. */
+ (void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL);
+
+ /* Copy directory attributes (dates, etc.) to newDirID. */
+ /* No errors allowed */
+ theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true);
+
+ /* handle any errors from CopyFileMgrAttributes */
+ if ( theGlobals->error != noErr )
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp,
+ theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
+ theGlobals->destinationVRefNum, newDirID, NULL);
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+ }
+ }
+ else /* error handling for DirCreate */
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp,
+ theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
+ theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName);
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+
+ if ( !theGlobals->bailout )
+ {
+ /* clear error return on way back if we aren't bailing out */
+ theGlobals->error = noErr;
+ }
+ }
+ else
+ {
+ /* We have a file, so copy it */
+
+ theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum,
+ theGlobals->myCPB.hFileInfo.ioFlParID,
+ theGlobals->itemName,
+ theGlobals->destinationVRefNum,
+ dstDirID,
+ NULL,
+ NULL,
+ theGlobals->copyBuffer,
+ theGlobals->bufferSize,
+ false);
+
+ /* handle any errors from FileCopy */
+ if ( theGlobals->error != noErr )
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp,
+ theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName,
+ theGlobals->destinationVRefNum, dstDirID, NULL);
+ if ( !theGlobals->bailout )
+ {
+ /* If the CopyErrProc handled the problem, clear the error here */
+ theGlobals->error = noErr;
+ }
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+ }
+ }
+ }
+ else
+ { /* error handling for PBGetCatInfo */
+ /* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */
+ if ( theGlobals->error != fnfErr )
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp,
+ theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL);
+ if ( !theGlobals->bailout )
+ {
+ /* If the CopyErrProc handled the problem, clear the error here */
+ theGlobals->error = noErr;
+ }
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+ }
+ ++index; /* prepare to get next item */
+ } while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */
+}
+
+/*****************************************************************************/
+
+pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
+ long srcDirID,
+ ConstStr255Param srcName,
+ short dstVRefNum,
+ long dstDirID,
+ ConstStr255Param dstName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler,
+ CopyFilterProcPtr copyFilterProc, ConstStr255Param newName );
+/* ¦ Make a copy of a directory structure in a new location with item filtering.
+ The FilteredDirectoryCopy function makes a copy of a directory
+ structure in a new location. If copyBufferPtr <> NIL, it points to
+ a buffer of copyBufferSize that is used to copy files data. The
+ larger the supplied buffer, the faster the copy. If
+ copyBufferPtr = NIL, then this routine allocates a buffer in the
+ application heap. If you pass a copy buffer to this routine, make
+ its size a multiple of 512 ($200) bytes for optimum performance.
+
+ The optional copyFilterProc parameter lets a routine you define
+ decide what files or directories are copied to the destination.
+
+ FilteredDirectoryCopy normally creates a new directory *in* the
+ specified destination directory and copies the source directory's
+ content into the new directory. However, if root parent directory
+ (fsRtParID) is passed as the dstDirID parameter and NULL is
+ passed as the dstName parameter, DirectoryCopy renames the
+ destination volume to the source directory's name (truncating
+ if the name is longer than 27 characters) and copies the source
+ directory's content into the destination volume's root directory.
+ This special case is supported by FilteredDirectoryCopy, but
+ not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy,
+ the dstName parameter can not be NULL.
+
+ srcVRefNum input: Source volume specification.
+ srcDirID input: Source directory ID.
+ srcName input: Source directory name, or nil if
+ srcDirID specifies the directory.
+ dstVRefNum input: Destination volume specification.
+ dstDirID input: Destination directory ID.
+ dstName input: Destination directory name, or nil if
+ dstDirID specifies the directory.
+ copyBufferPtr input: Points to a buffer of copyBufferSize that
+ is used the i/o buffer for the copy or
+ nil if you want DirectoryCopy to allocate its
+ own buffer in the application heap.
+ copyBufferSize input: The size of the buffer pointed to
+ by copyBufferPtr.
+ preflight input: If true, DirectoryCopy makes sure there are
+ enough allocation blocks on the destination
+ volume to hold the directory's files before
+ starting the copy.
+ copyErrHandler input: A pointer to the routine you want called if an
+ error condition is detected during the copy, or
+ nil if you don't want to handle error conditions.
+ If you don't handle error conditions, the first
+ error will cause the copy to quit and
+ DirectoryCopy will return the error.
+ Error handling is recommended...
+ copyFilterProc input: A pointer to the filter routine you want called
+ for each item in the source directory, or NULL
+ if you don't want to filter.
+
+ Result Codes
+ noErr 0 No error
+ readErr Ð19 Driver does not respond to read requests
+ writErr Ð20 Driver does not respond to write requests
+ badUnitErr Ð21 Driver reference number does not
+ match unit table
+ unitEmptyErr Ð22 Driver reference number specifies a
+ nil handle in unit table
+ abortErr Ð27 Request aborted by KillIO
+ notOpenErr Ð28 Driver not open
+ dskFulErr -34 Destination volume is full
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ tmfoErr -42 Too many files open
+ fnfErr -43 Source file not found, or destination
+ directory does not exist
+ wPrErr -44 Volume locked by hardware
+ fLckdErr -45 File is locked
+ vLckdErr -46 Destination volume is read-only
+ fBsyErr -47 The source or destination file could
+ not be opened with the correct access
+ modes
+ dupFNErr -48 Destination file already exists
+ opWrErr -49 File already open for writing
+ paramErr -50 No default volume or function not
+ supported by volume
+ permErr -54 File is already open and cannot be opened using specified deny modes
+ memFullErr -108 Copy buffer could not be allocated
+ dirNFErr -120 Directory not found or incomplete pathname
+ wrgVolTypErr -123 Function not supported by volume
+ afpAccessDenied -5000 User does not have the correct access
+ afpDenyConflict -5006 The source or destination file could
+ not be opened with the correct access
+ modes
+ afpObjectTypeErr -5025 Source is a directory, directory not found
+ or incomplete pathname
+
+ __________
+
+ Also see: CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy,
+ DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
+ long srcDirID,
+ ConstStr255Param srcName,
+ short dstVRefNum,
+ long dstDirID,
+ ConstStr255Param dstName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler,
+ CopyFilterProcPtr copyFilterProc, ConstStr255Param newName)
+{
+ EnumerateGlobals theGlobals;
+ Boolean isDirectory;
+ OSErr error;
+ Boolean ourCopyBuffer = false;
+ Str63 srcDirName, oldDiskName;
+ Boolean spaceOK;
+
+ /* Make sure a copy buffer is allocated. */
+ if ( copyBufferPtr == NULL )
+ {
+ /* The caller didn't supply a copy buffer so grab one from the application heap.
+ ** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
+ ** If 512 bytes aren't available, we're in trouble. */
+ copyBufferSize = dirCopyBigCopyBuffSize;
+ copyBufferPtr = NewPtr(copyBufferSize);
+ if ( copyBufferPtr == NULL )
+ {
+ copyBufferSize = dirCopyMinCopyBuffSize;
+ copyBufferPtr = NewPtr(copyBufferSize);
+ if ( copyBufferPtr == NULL )
+ {
+ return ( memFullErr );
+ }
+ }
+ ourCopyBuffer = true;
+ }
+
+ /* Get the real dirID where we're copying from and make sure it is a directory. */
+ error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ if ( !isDirectory )
+ {
+ error = dirNFErr;
+ goto ErrorExit;
+ }
+
+ /* Special case destination if it is the root parent directory. */
+ /* Since you can't create the root directory, this is needed if */
+ /* you want to copy a directory's content to a disk's root directory. */
+ if ( (dstDirID == fsRtParID) && (dstName == NULL) )
+ {
+ dstDirID = fsRtParID;
+ isDirectory = true;
+ error = noErr;
+ }
+ else
+ {
+ /* Get the real dirID where we're going to put the copy and make sure it is a directory. */
+ error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ if ( !isDirectory )
+ {
+ error = dirNFErr;
+ goto ErrorExit;
+ }
+ }
+
+ /* Get the real vRefNum of both the source and destination */
+ error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+
+ if ( preflight )
+ {
+ error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ if ( !spaceOK )
+ {
+ error = dskFulErr; /* not enough room on destination */
+ goto ErrorExit;
+ }
+ }
+
+ /* Create the new directory in the destination directory with the */
+ /* same name as the source directory. */
+ /*
+ if newName is not empty use it rather than the original dir name.
+ */
+ if ( newName[0] == 0 )
+ {
+ error = GetDirName(srcVRefNum, srcDirID, srcDirName);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ }
+ else
+ {
+ memcpy(srcDirName, newName, 32 );
+
+ }
+ /* Again, special case destination if the destination is the */
+ /* root parent directory. This time, we'll rename the disk to */
+ /* the source directory name. */
+ if ( dstDirID == fsRtParID )
+ {
+ /* Get the current name of the destination disk */
+ error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName);
+ if ( error == noErr )
+ {
+ /* Shorten the name if it's too long to be the volume name */
+ TruncPString(srcDirName, srcDirName, 27);
+
+ /* Rename the disk */
+ error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName);
+ /* and copy to the root directory */
+ dstDirID = fsRtDirID;
+ }
+ }
+ else
+ {
+ error = DirCreate(dstVRefNum, dstDirID, srcDirName, &dstDirID);
+ }
+ if ( error != noErr )
+ {
+ /* handle any errors from DirCreate */
+ if ( copyErrHandler != NULL )
+ {
+ if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp,
+ srcVRefNum, srcDirID, NULL,
+ dstVRefNum, dstDirID, srcDirName) )
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ /* If the CopyErrProc handled the problem, clear the error here */
+ /* and continue */
+ error = noErr;
+ }
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ goto ErrorExit;
+ }
+ }
+
+ /* dstDirID is now the newly created directory! */
+
+ /* Set up the globals we need to access from the recursive routine. */
+ theGlobals.copyBuffer = (Ptr)copyBufferPtr;
+ theGlobals.bufferSize = copyBufferSize;
+ theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */
+ theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
+ theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum;
+ theGlobals.errorHandler = copyErrHandler;
+ theGlobals.bailout = false;
+ theGlobals.copyFilterProc = copyFilterProc;
+
+ /* Here we go into recursion land... */
+ CopyLevel(srcDirID, dstDirID, &theGlobals);
+ error = theGlobals.error; /* get the result */
+
+ if ( !theGlobals.bailout )
+ {
+ /* Copy comment from source to destination directory. */
+ /* Ignore the result because we really don't care if it worked or not. */
+ (void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL);
+
+ /* Copy the File Manager attributes */
+ error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL,
+ dstVRefNum, dstDirID, NULL, true);
+
+ /* handle any errors from CopyFileMgrAttributes */
+ if ( (error != noErr) && (copyErrHandler != NULL) )
+ {
+ theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp,
+ srcVRefNum, srcDirID, NULL,
+ dstVRefNum, dstDirID, NULL);
+ }
+ }
+
+ErrorExit:
+ /* Get rid of the copy buffer if we allocated it. */
+ if ( ourCopyBuffer )
+ {
+ DisposePtr((Ptr)copyBufferPtr);
+ }
+
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+
+pascal OSErr MacFSpDirectoryCopyRename(const FSSpec *srcSpec,
+ const FSSpec *dstSpec,
+ ConstStr255Param newName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler)
+{
+ return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
+ dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
+ copyBufferPtr, copyBufferSize, preflight,
+ copyErrHandler, NULL, newName) );
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h
new file mode 100644
index 00000000..361c820e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h
@@ -0,0 +1,158 @@
+/*
+** Apple Macintosh Developer Technical Support
+**
+** DirectoryCopy: A robust, general purpose directory copy routine.
+**
+** by Jim Luther, Apple Developer Technical Support Emeritus
+**
+** File: DirectoryCopy.h
+**
+** Copyright © 1992-1998 Apple Computer, Inc.
+** All rights reserved.
+**
+** You may incorporate this sample code into your applications without
+** restriction, though the sample code has been provided "AS IS" and the
+** responsibility for its operation is 100% yours. However, what you are
+** not permitted to do is to redistribute the source as "DSC Sample Code"
+** after having made changes. If you're going to re-distribute the source,
+** we require that you make it clear in the source that the code was
+** descended from Apple Sample Code, but that you've made changes.
+*/
+
+// Modified to allow renaming the destination folder
+
+#ifndef __MACDIRECTORYCOPY__
+#define __MACDIRECTORYCOPY__
+
+#include <Types.h>
+#include <Files.h>
+
+#include "Optimization.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef pascal Boolean (*CopyErrProcPtr) (OSErr error,
+ short failedOperation,
+ short srcVRefNum,
+ long srcDirID,
+ ConstStr255Param srcName,
+ short dstVRefNum,
+ long dstDirID,
+ ConstStr255Param dstName);
+/* ¦ Prototype for the CopyErrProc function DirectoryCopy calls.
+ This is the prototype for the CopyErrProc function DirectoryCopy
+ calls if an error condition is detected sometime during the copy. If
+ CopyErrProc returns false, then DirectoryCopy attempts to continue with
+ the directory copy operation. If CopyErrProc returns true, then
+ DirectoryCopy stops the directory copy operation.
+
+ error input: The error result code that caused CopyErrProc to
+ be called.
+ failedOperation input: The operation that returned an error to
+ DirectoryCopy.
+ srcVRefNum input: Source volume specification.
+ srcDirID input: Source directory ID.
+ srcName input: Source file or directory name, or nil if
+ srcDirID specifies the directory.
+ dstVRefNum input: Destination volume specification.
+ dstDirID input: Destination directory ID.
+ dstName input: Destination file or directory name, or nil if
+ dstDirID specifies the directory.
+
+ __________
+
+ Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy
+*/
+
+pascal OSErr MacFSpDirectoryCopyRename(const FSSpec *srcSpec,
+ const FSSpec *dstSpec,
+ ConstStr255Param newName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler);
+/* ¦ Make a copy of a directory structure in a new location.
+ The FSpDirectoryCopy function makes a copy of a directory structure in a
+ new location. If copyBufferPtr <> NIL, it points to a buffer of
+ copyBufferSize that is used to copy files data. The larger the
+ supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
+ routine allocates a buffer in the application heap. If you pass a
+ copy buffer to this routine, make its size a multiple of 512
+ ($200) bytes for optimum performance.
+
+ srcSpec input: An FSSpec record specifying the directory to copy.
+ dstSpec input: An FSSpec record specifying destination directory
+ of the copy.
+ copyBufferPtr input: Points to a buffer of copyBufferSize that
+ is used the i/o buffer for the copy or
+ nil if you want DirectoryCopy to allocate its
+ own buffer in the application heap.
+ copyBufferSize input: The size of the buffer pointed to
+ by copyBufferPtr.
+ preflight input: If true, FSpDirectoryCopy makes sure there are
+ enough allocation blocks on the destination
+ volume to hold the directory's files before
+ starting the copy.
+ copyErrHandler input: A pointer to the routine you want called if an
+ error condition is detected during the copy, or
+ nil if you don't want to handle error conditions.
+ If you don't handle error conditions, the first
+ error will cause the copy to quit and
+ DirectoryCopy will return the error.
+ Error handling is recommended...
+
+ Result Codes
+ noErr 0 No error
+ readErr Ð19 Driver does not respond to read requests
+ writErr Ð20 Driver does not respond to write requests
+ badUnitErr Ð21 Driver reference number does not
+ match unit table
+ unitEmptyErr Ð22 Driver reference number specifies a
+ nil handle in unit table
+ abortErr Ð27 Request aborted by KillIO
+ notOpenErr Ð28 Driver not open
+ dskFulErr -34 Destination volume is full
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ tmfoErr -42 Too many files open
+ fnfErr -43 Source file not found, or destination
+ directory does not exist
+ wPrErr -44 Volume locked by hardware
+ fLckdErr -45 File is locked
+ vLckdErr -46 Destination volume is read-only
+ fBsyErr -47 The source or destination file could
+ not be opened with the correct access
+ modes
+ dupFNErr -48 Destination file already exists
+ opWrErr -49 File already open for writing
+ paramErr -50 No default volume or function not
+ supported by volume
+ permErr -54 File is already open and cannot be opened using specified deny modes
+ memFullErr -108 Copy buffer could not be allocated
+ dirNFErr -120 Directory not found or incomplete pathname
+ wrgVolTypErr -123 Function not supported by volume
+ afpAccessDenied -5000 User does not have the correct access
+ afpDenyConflict -5006 The source or destination file could
+ not be opened with the correct access
+ modes
+ afpObjectTypeErr -5025 Source is a directory, directory not found
+ or incomplete pathname
+
+ __________
+
+ Also see: CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy,
+ FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
+*/
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "OptimizationEnd.h"
+
+#endif /* __DIRECTORYCOPY__ */
diff --git a/src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h b/src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h
new file mode 100644
index 00000000..768cb38f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen conrad@ingress.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAppDirectoryServiceDefs_h___
+#define nsAppDirectoryServiceDefs_h___
+
+//========================================================================================
+//
+// Defines property names for directories available from standard nsIDirectoryServiceProviders.
+// These keys are not guaranteed to exist because the nsIDirectoryServiceProviders which
+// provide them are optional.
+//
+// Keys whose definition ends in "DIR" or "FILE" return a single nsIFile (or subclass).
+// Keys whose definition ends in "LIST" return an nsISimpleEnumerator which enumerates a
+// list of file objects.
+//
+// System and XPCOM level properties are defined in nsDirectoryServiceDefs.h.
+//
+//========================================================================================
+
+
+// --------------------------------------------------------------------------------------
+// Files and directories which exist on a per-product basis
+// --------------------------------------------------------------------------------------
+
+#define NS_APP_APPLICATION_REGISTRY_FILE "AppRegF"
+#define NS_APP_APPLICATION_REGISTRY_DIR "AppRegD"
+
+#define NS_APP_DEFAULTS_50_DIR "DefRt" // The root dir of all defaults dirs
+#define NS_APP_PREF_DEFAULTS_50_DIR "PrfDef"
+#define NS_APP_PROFILE_DEFAULTS_50_DIR "profDef" // The profile defaults of the "current"
+ // locale. Should be first choice.
+#define NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR "ProfDefNoLoc" // The profile defaults of the "default"
+ // installed locale. Second choice
+ // when above is not available.
+
+#define NS_APP_USER_PROFILES_ROOT_DIR "DefProfRt" // The dir where user profile dirs get created.
+
+#define NS_APP_RES_DIR "ARes"
+#define NS_APP_CHROME_DIR "AChrom"
+#define NS_APP_PLUGINS_DIR "APlugns" // Deprecated - use NS_APP_PLUGINS_DIR_LIST
+#define NS_APP_SEARCH_DIR "SrchPlugns"
+
+#define NS_APP_CHROME_DIR_LIST "AChromDL"
+#define NS_APP_PLUGINS_DIR_LIST "APluginsDL"
+
+// --------------------------------------------------------------------------------------
+// Files and directories which exist on a per-profile basis
+// These locations are typically provided by the profile mgr
+// --------------------------------------------------------------------------------------
+
+// In a shared profile environment, prefixing a profile-relative
+// key with NS_SHARED returns a location that is shared by
+// other users of the profile. Without this prefix, the consumer
+// has exclusive access to this location.
+
+#define NS_SHARED "SHARED"
+
+#define NS_APP_PREFS_50_DIR "PrefD" // Directory which contains user prefs
+#define NS_APP_PREFS_50_FILE "PrefF"
+#define NS_APP_PREFS_DEFAULTS_DIR_LIST "PrefDL"
+
+#define NS_APP_USER_PROFILE_50_DIR "ProfD"
+
+#define NS_APP_USER_CHROME_DIR "UChrm"
+
+#define NS_APP_LOCALSTORE_50_FILE "LclSt"
+#define NS_APP_HISTORY_50_FILE "UHist"
+#define NS_APP_USER_PANELS_50_FILE "UPnls"
+#define NS_APP_USER_MIMETYPES_50_FILE "UMimTyp"
+#define NS_APP_CACHE_PARENT_DIR "cachePDir"
+
+#define NS_APP_BOOKMARKS_50_FILE "BMarks"
+
+#define NS_APP_DOWNLOADS_50_FILE "DLoads"
+
+#define NS_APP_SEARCH_50_FILE "SrchF"
+
+#define NS_APP_MAIL_50_DIR "MailD"
+#define NS_APP_IMAP_MAIL_50_DIR "IMapMD"
+#define NS_APP_NEWS_50_DIR "NewsD"
+#define NS_APP_MESSENGER_FOLDER_CACHE_50_DIR "MFCaD"
+
+#define NS_APP_INSTALL_CLEANUP_DIR "XPIClnupD" //location of xpicleanup.dat xpicleanup.exe
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp
new file mode 100644
index 00000000..9d4f785d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp
@@ -0,0 +1,608 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <conrad@ingress.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAppFileLocationProvider.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsIAtom.h"
+#include "nsILocalFile.h"
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "nsISimpleEnumerator.h"
+#include "prenv.h"
+#include "nsCRT.h"
+
+#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+#include <Folders.h>
+#include <Script.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#include "nsILocalFileMac.h"
+#elif defined(XP_OS2)
+#define INCL_DOSPROCESS
+#define INCL_DOSMODULEMGR
+#include <os2.h>
+#elif defined(XP_WIN)
+#include <windows.h>
+#include <shlobj.h>
+#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#elif defined(XP_BEOS)
+#include <sys/param.h>
+#include <kernel/image.h>
+#include <storage/FindDirectory.h>
+#endif
+
+
+// WARNING: These hard coded names need to go away. They need to
+// come from localizable resources
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#define APP_REGISTRY_NAME NS_LITERAL_CSTRING("Application Registry")
+#define ESSENTIAL_FILES NS_LITERAL_CSTRING("Essential Files")
+#elif defined(XP_WIN) || defined(XP_OS2)
+#define APP_REGISTRY_NAME NS_LITERAL_CSTRING("registry.dat")
+#else
+#define APP_REGISTRY_NAME NS_LITERAL_CSTRING("appreg")
+#endif
+
+// define default product directory
+#ifdef XP_MAC
+#define DEFAULT_PRODUCT_DIR NS_LITERAL_CSTRING("Mozilla")
+#else
+#define DEFAULT_PRODUCT_DIR NS_LITERAL_CSTRING(MOZ_USER_DIR)
+#endif
+
+// Locally defined keys used by nsAppDirectoryEnumerator
+#define NS_ENV_PLUGINS_DIR "EnvPlugins" // env var MOZ_PLUGIN_PATH
+#define NS_USER_PLUGINS_DIR "UserPlugins"
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#define NS_MACOSX_USER_PLUGIN_DIR "OSXUserPlugins"
+#define NS_MACOSX_LOCAL_PLUGIN_DIR "OSXLocalPlugins"
+#define NS_MAC_CLASSIC_PLUGIN_DIR "MacSysPlugins"
+#endif
+
+#if defined(XP_MAC)
+#define DEFAULTS_DIR_NAME NS_LITERAL_CSTRING("Defaults")
+#define DEFAULTS_PREF_DIR_NAME NS_LITERAL_CSTRING("Pref")
+#define DEFAULTS_PROFILE_DIR_NAME NS_LITERAL_CSTRING("Profile")
+#define RES_DIR_NAME NS_LITERAL_CSTRING("Res")
+#define CHROME_DIR_NAME NS_LITERAL_CSTRING("Chrome")
+#define PLUGINS_DIR_NAME NS_LITERAL_CSTRING("Plug-ins")
+#define SEARCH_DIR_NAME NS_LITERAL_CSTRING("Search Plugins")
+#else
+#define DEFAULTS_DIR_NAME NS_LITERAL_CSTRING("defaults")
+#define DEFAULTS_PREF_DIR_NAME NS_LITERAL_CSTRING("pref")
+#define DEFAULTS_PROFILE_DIR_NAME NS_LITERAL_CSTRING("profile")
+#define RES_DIR_NAME NS_LITERAL_CSTRING("res")
+#define CHROME_DIR_NAME NS_LITERAL_CSTRING("chrome")
+#define PLUGINS_DIR_NAME NS_LITERAL_CSTRING("plugins")
+#define SEARCH_DIR_NAME NS_LITERAL_CSTRING("searchplugins")
+#endif
+
+//*****************************************************************************
+// nsAppFileLocationProvider::Constructor/Destructor
+//*****************************************************************************
+
+nsAppFileLocationProvider::nsAppFileLocationProvider()
+{
+}
+
+//*****************************************************************************
+// nsAppFileLocationProvider::nsISupports
+//*****************************************************************************
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsAppFileLocationProvider, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2)
+
+//*****************************************************************************
+// nsAppFileLocationProvider::nsIDirectoryServiceProvider
+//*****************************************************************************
+
+NS_IMETHODIMP
+nsAppFileLocationProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
+{
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ NS_ENSURE_ARG(prop);
+ *_retval = nsnull;
+ *persistant = PR_TRUE;
+
+#if (defined (XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ short foundVRefNum;
+ SInt32 foundDirID;
+ FSSpec fileSpec;
+ nsCOMPtr<nsILocalFileMac> macFile;
+#endif
+
+ if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_DIR) == 0)
+ {
+ rv = GetProductDirectory(getter_AddRefs(localFile));
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_FILE) == 0)
+ {
+ rv = GetProductDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendNative(APP_REGISTRY_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_DEFAULTS_50_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_PREF_DEFAULTS_50_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv)) {
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_PREF_DIR_NAME);
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_PROFILE_DEFAULTS_50_DIR) == 0 ||
+ nsCRT::strcmp(prop, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv)) {
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_PROFILE_DIR_NAME);
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_USER_PROFILES_ROOT_DIR) == 0)
+ {
+ rv = GetDefaultUserProfileRoot(getter_AddRefs(localFile));
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_RES_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(RES_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_CHROME_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(CHROME_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+ }
+#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ else if (nsCRT::strcmp(prop, NS_MACOSX_USER_PLUGIN_DIR) == 0)
+ {
+ if (!(::FindFolder(kUserDomain,
+ kInternetPlugInFolderType,
+ kDontCreateFolder, &foundVRefNum, &foundDirID)) &&
+ !(::FSMakeFSSpec(foundVRefNum, foundDirID, "\p", &fileSpec))) {
+ rv = NS_NewLocalFileWithFSSpec(&fileSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(rv))
+ localFile = macFile;
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_MACOSX_LOCAL_PLUGIN_DIR) == 0)
+ {
+ if (!(::FindFolder(kLocalDomain,
+ kInternetPlugInFolderType,
+ kDontCreateFolder, &foundVRefNum, &foundDirID)) &&
+ !(::FSMakeFSSpec(foundVRefNum, foundDirID, "\p", &fileSpec))) {
+ rv = NS_NewLocalFileWithFSSpec(&fileSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(rv))
+ localFile = macFile;
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_MAC_CLASSIC_PLUGIN_DIR) == 0)
+ {
+ if (!(::FindFolder(kOnAppropriateDisk,
+ kInternetPlugInFolderType,
+ kDontCreateFolder, &foundVRefNum, &foundDirID)) &&
+ !(::FSMakeFSSpec(foundVRefNum, foundDirID, "\p", &fileSpec))) {
+ rv = NS_NewLocalFileWithFSSpec(&fileSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(rv))
+ localFile = macFile;
+ }
+ }
+#else
+ else if (nsCRT::strcmp(prop, NS_ENV_PLUGINS_DIR) == 0)
+ {
+ NS_ERROR("Don't use nsAppFileLocationProvider::GetFile(NS_ENV_PLUGINS_DIR, ...). "
+ "Use nsAppFileLocationProvider::GetFiles(...).");
+ const char *pathVar = PR_GetEnv("VBOX_XPCOM_PLUGIN_PATH");
+ if (pathVar)
+ rv = NS_NewNativeLocalFile(nsDependentCString(pathVar), PR_TRUE, getter_AddRefs(localFile));
+ }
+ else if (nsCRT::strcmp(prop, NS_USER_PLUGINS_DIR) == 0)
+ {
+ rv = GetProductDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+ }
+#endif
+ else if (nsCRT::strcmp(prop, NS_APP_SEARCH_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(SEARCH_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_INSTALL_CLEANUP_DIR) == 0)
+ {
+ // This is cloned so that embeddors will have a hook to override
+ // with their own cleanup dir. See bugzilla bug #105087
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+#ifdef XP_MAC
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendNative(ESSENTIAL_FILES);
+#endif
+
+ }
+
+ if (localFile && NS_SUCCEEDED(rv))
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+
+ return rv;
+}
+
+
+NS_METHOD nsAppFileLocationProvider::CloneMozBinDirectory(nsILocalFile **aLocalFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+ nsresult rv;
+
+ if (!mMozBinDirectory)
+ {
+ // Get the mozilla bin directory
+ // 1. Check the directory service first for NS_XPCOM_CURRENT_PROCESS_DIR
+ // This will be set if a directory was passed to NS_InitXPCOM
+ // 2. If that doesn't work, set it to be the current process directory
+ nsCOMPtr<nsIProperties>
+ directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
+ if (NS_FAILED(rv)) {
+ rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ nsCOMPtr<nsIFile> aFile;
+ rv = mMozBinDirectory->Clone(getter_AddRefs(aFile));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsILocalFile> lfile = do_QueryInterface (aFile);
+ if (!lfile)
+ return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aLocalFile = lfile);
+ return NS_OK;
+}
+
+
+//----------------------------------------------------------------------------------------
+// GetProductDirectory - Gets the directory which contains the application data folder
+//
+// UNIX : ~/.mozilla/
+// WIN : <Application Data folder on user's machine>\Mozilla
+// Mac : :Documents:Mozilla:
+//----------------------------------------------------------------------------------------
+NS_METHOD nsAppFileLocationProvider::GetProductDirectory(nsILocalFile **aLocalFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+
+ nsresult rv;
+ PRBool exists;
+ nsCOMPtr<nsILocalFile> localDir;
+
+#if defined(XP_MAC)
+ nsCOMPtr<nsIProperties> directoryService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ OSErr err;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ const char *prop = (!err && response >= 0x00001000) ? NS_MAC_USER_LIB_DIR : NS_MAC_DOCUMENTS_DIR;
+ rv = directoryService->Get(prop, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_MACOSX) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ FSRef fsRef;
+ OSErr err = ::FSFindFolder(kUserDomain, kDomainLibraryFolderType, kCreateFolder, &fsRef);
+ if (err) return NS_ERROR_FAILURE;
+ NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localDir));
+ if (!localDir) return NS_ERROR_FAILURE;
+ nsCOMPtr<nsILocalFileMac> localDirMac(do_QueryInterface(localDir));
+ rv = localDirMac->InitWithFSRef(&fsRef);
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_OS2)
+ nsCOMPtr<nsIProperties> directoryService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = directoryService->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_WIN)
+ nsCOMPtr<nsIProperties> directoryService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = directoryService->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ if (NS_SUCCEEDED(rv))
+ rv = localDir->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ {
+ // On some Win95 machines, NS_WIN_APPDATA_DIR does not exist - revert to NS_WIN_WINDOWS_DIR
+ localDir = nsnull;
+ rv = directoryService->Get(NS_WIN_WINDOWS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ }
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_UNIX)
+ rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), PR_TRUE, getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_BEOS)
+ char path[MAXPATHLEN];
+ find_directory(B_USER_SETTINGS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ return NS_ERROR_FAILURE;
+ path[len] = '/';
+ path[len+1] = '\0';
+ rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE, getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#else
+#error dont_know_how_to_get_product_dir_on_your_platform
+#endif
+
+ rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
+ if (NS_FAILED(rv)) return rv;
+ rv = localDir->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists)
+ rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+ if (NS_FAILED(rv)) return rv;
+
+ *aLocalFile = localDir;
+ NS_ADDREF(*aLocalFile);
+
+ return rv;
+}
+
+
+//----------------------------------------------------------------------------------------
+// GetDefaultUserProfileRoot - Gets the directory which contains each user profile dir
+//
+// UNIX : ~/.mozilla/
+// WIN : <Application Data folder on user's machine>\Mozilla\Profiles
+// Mac : :Documents:Mozilla:Profiles:
+//----------------------------------------------------------------------------------------
+NS_METHOD nsAppFileLocationProvider::GetDefaultUserProfileRoot(nsILocalFile **aLocalFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> localDir;
+
+ rv = GetProductDirectory(getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+
+#if defined(XP_MAC) || defined(XP_MACOSX) || defined(XP_OS2) || defined(XP_WIN)
+ // These 3 platforms share this part of the path - do them as one
+ rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("Profiles"));
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool exists;
+ rv = localDir->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists)
+ rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ *aLocalFile = localDir;
+ NS_ADDREF(*aLocalFile);
+
+ return rv;
+}
+
+//*****************************************************************************
+// nsAppFileLocationProvider::nsIDirectoryServiceProvider2
+//*****************************************************************************
+
+class nsAppDirectoryEnumerator : public nsISimpleEnumerator
+{
+ public:
+ NS_DECL_ISUPPORTS
+
+ /**
+ * aKeyList is a null-terminated list of properties which are provided by aProvider
+ * They do not need to be publicly defined keys.
+ */
+ nsAppDirectoryEnumerator(nsIDirectoryServiceProvider *aProvider,
+ const char* aKeyList[]) :
+ mProvider(aProvider),
+ mCurrentKey(aKeyList)
+ {
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ while (!mNext && *mCurrentKey)
+ {
+ PRBool dontCare;
+ nsCOMPtr<nsIFile> testFile;
+ (void)mProvider->GetFile(*mCurrentKey++, &dontCare, getter_AddRefs(testFile));
+ // Don't return a file which does not exist.
+ PRBool exists;
+ if (testFile && NS_SUCCEEDED(testFile->Exists(&exists)) && exists)
+ mNext = testFile;
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = nsnull;
+
+ PRBool hasMore;
+ HasMoreElements(&hasMore);
+ if (!hasMore)
+ return NS_ERROR_FAILURE;
+
+ *result = mNext;
+ NS_IF_ADDREF(*result);
+ mNext = nsnull;
+
+ return *result ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ // Virtual destructor since subclass nsPathsDirectoryEnumerator
+ // does not re-implement Release()
+
+ virtual ~nsAppDirectoryEnumerator()
+ {
+ }
+
+ protected:
+ nsIDirectoryServiceProvider *mProvider;
+ const char** mCurrentKey;
+ nsCOMPtr<nsIFile> mNext;
+};
+
+NS_IMPL_ISUPPORTS1(nsAppDirectoryEnumerator, nsISimpleEnumerator)
+
+/* nsPathsDirectoryEnumerator and PATH_SEPARATOR
+ * are not used on MacOS/X. */
+
+#if defined(XP_WIN) || defined(XP_OS2)/* Win32, Win16, and OS/2 */
+#define PATH_SEPARATOR ';'
+#else /*if defined(XP_UNIX) || defined(XP_BEOS)*/
+#define PATH_SEPARATOR ':'
+#endif
+
+class nsPathsDirectoryEnumerator : public nsAppDirectoryEnumerator
+{
+ public:
+ /**
+ * aKeyList is a null-terminated list.
+ * The first element is a path list.
+ * The remainder are properties provided by aProvider.
+ * They do not need to be publicly defined keys.
+ */
+ nsPathsDirectoryEnumerator(nsIDirectoryServiceProvider *aProvider,
+ const char* aKeyList[]) :
+ nsAppDirectoryEnumerator(aProvider, aKeyList+1),
+ mEndPath(aKeyList[0])
+ {
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ if (mEndPath)
+ while (!mNext && *mEndPath)
+ {
+ const char *pathVar = mEndPath;
+ do { ++mEndPath; } while (*mEndPath && *mEndPath != PATH_SEPARATOR);
+
+ nsCOMPtr<nsILocalFile> localFile;
+ NS_NewNativeLocalFile(Substring(pathVar, mEndPath),
+ PR_TRUE,
+ getter_AddRefs(localFile));
+ if (*mEndPath == PATH_SEPARATOR)
+ ++mEndPath;
+ // Don't return a "file" (directory) which does not exist.
+ PRBool exists;
+ if (localFile &&
+ NS_SUCCEEDED(localFile->Exists(&exists)) &&
+ exists)
+ mNext = localFile;
+ }
+ if (mNext)
+ *result = PR_TRUE;
+ else
+ nsAppDirectoryEnumerator::HasMoreElements(result);
+
+ return NS_OK;
+ }
+
+ protected:
+ const char *mEndPath;
+};
+
+NS_IMETHODIMP
+nsAppFileLocationProvider::GetFiles(const char *prop, nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR_LIST))
+ {
+#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ static const char* osXKeys[] = { NS_APP_PLUGINS_DIR, NS_MACOSX_USER_PLUGIN_DIR, NS_MACOSX_LOCAL_PLUGIN_DIR, nsnull };
+ static const char* os9Keys[] = { NS_APP_PLUGINS_DIR, NS_MAC_CLASSIC_PLUGIN_DIR, nsnull };
+ static const char** keys;
+
+ if (!keys) {
+ OSErr err;
+ SInt32 response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ keys = (!err && response >= 0x00001000) ? osXKeys : os9Keys;
+ }
+
+ *_retval = new nsAppDirectoryEnumerator(this, keys);
+#else
+ static const char* keys[] = { nsnull, NS_APP_PLUGINS_DIR, nsnull };
+ if (!keys[0] && !(keys[0] = PR_GetEnv("VBOX_XPCOM_PLUGIN_PATH"))) {
+ static const char nullstr = 0;
+ keys[0] = &nullstr;
+ }
+ *_retval = new nsPathsDirectoryEnumerator(this, keys);
+#endif
+ NS_IF_ADDREF(*_retval);
+ rv = *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h
new file mode 100644
index 00000000..677ae00e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <conrad@ingress.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDirectoryService.h"
+#include "nsILocalFile.h"
+
+class nsIFile;
+
+//*****************************************************************************
+// class nsAppFileLocationProvider
+//*****************************************************************************
+
+class nsAppFileLocationProvider : public nsIDirectoryServiceProvider2
+{
+public:
+ nsAppFileLocationProvider();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+private:
+ ~nsAppFileLocationProvider() {}
+
+protected:
+ NS_METHOD CloneMozBinDirectory(nsILocalFile **aLocalFile);
+ NS_METHOD GetProductDirectory(nsILocalFile **aLocalFile);
+ NS_METHOD GetDefaultUserProfileRoot(nsILocalFile **aLocalFile);
+
+ nsCOMPtr<nsILocalFile> mMozBinDirectory;
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp
new file mode 100644
index 00000000..bc60eea3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp
@@ -0,0 +1,663 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * This file contains implementations of the nsIBinaryInputStream and
+ * nsIBinaryOutputStream interfaces. Together, these interfaces allows reading
+ * and writing of primitive data types (integers, floating-point values,
+ * booleans, etc.) to a stream in a binary, untagged, fixed-endianness format.
+ * This might be used, for example, to implement network protocols or to
+ * produce architecture-neutral binary disk files, i.e. ones that can be read
+ * and written by both big-endian and little-endian platforms. Output is
+ * written in big-endian order (high-order byte first), as this is traditional
+ * network order.
+ *
+ * @See nsIBinaryInputStream
+ * @See nsIBinaryOutputStream
+ */
+#include <string.h>
+#include "nsBinaryStream.h"
+#include "nsCRT.h"
+#include "nsIStreamBufferAccess.h"
+#include "nsMemory.h"
+#include "prlong.h"
+#include "nsGenericFactory.h"
+
+NS_IMPL_ISUPPORTS3(nsBinaryOutputStream, nsIObjectOutputStream, nsIBinaryOutputStream, nsIOutputStream)
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Flush() { return mOutputStream->Flush(); }
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Close() { return mOutputStream->Close(); }
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes)
+{
+ return mOutputStream->Write(aBuf, aCount, aActualBytes);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteFrom");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ return mOutputStream->IsNonBlocking(aNonBlocking);
+}
+
+nsresult
+nsBinaryOutputStream::WriteFully(const char *aBuf, PRUint32 aCount)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ rv = mOutputStream->Write(aBuf, aCount, &bytesWritten);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesWritten != aCount)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::SetOutputStream(nsIOutputStream *aOutputStream)
+{
+ NS_ENSURE_ARG_POINTER(aOutputStream);
+ mOutputStream = aOutputStream;
+ mBufferAccess = do_QueryInterface(aOutputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteBoolean(PRBool aBoolean)
+{
+ return Write8(aBoolean);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write8(PRUint8 aByte)
+{
+ return WriteFully((const char*)&aByte, sizeof aByte);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write16(PRUint16 a16)
+{
+ a16 = NS_SWAP16(a16);
+ return WriteFully((const char*)&a16, sizeof a16);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write32(PRUint32 a32)
+{
+ a32 = NS_SWAP32(a32);
+ return WriteFully((const char*)&a32, sizeof a32);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write64(PRUint64 a64)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ a64 = NS_SWAP64(a64);
+ rv = Write(NS_REINTERPRET_CAST(char*, &a64), sizeof a64, &bytesWritten);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesWritten != sizeof a64)
+ return NS_ERROR_FAILURE;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteFloat(float aFloat)
+{
+ NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
+ "False assumption about sizeof(float)");
+ return Write32(*NS_REINTERPRET_CAST(PRUint32*, &aFloat));
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteDouble(double aDouble)
+{
+ NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
+ "False assumption about sizeof(double)");
+ return Write64(*NS_REINTERPRET_CAST(PRUint64*, &aDouble));
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteStringZ(const char *aString)
+{
+ PRUint32 length;
+ nsresult rv;
+
+ length = strlen(aString);
+ rv = Write32(length);
+ if (NS_FAILED(rv)) return rv;
+ return WriteFully(aString, length);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteWStringZ(const PRUnichar* aString)
+{
+ PRUint32 length, byteCount;
+ nsresult rv;
+
+ length = nsCRT::strlen(aString);
+ rv = Write32(length);
+ if (NS_FAILED(rv)) return rv;
+
+ if (length == 0)
+ return NS_OK;
+ byteCount = length * sizeof(PRUnichar);
+
+#ifdef IS_BIG_ENDIAN
+ rv = WriteBytes(NS_REINTERPRET_CAST(const char*, aString), byteCount);
+#else
+ // XXX use WriteSegments here to avoid copy!
+ PRUnichar *copy, temp[64];
+ if (length <= 64) {
+ copy = temp;
+ } else {
+ copy = NS_REINTERPRET_CAST(PRUnichar*, nsMemory::Alloc(byteCount));
+ if (!copy)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ NS_ASSERTION((PRUptrdiff(aString) & 0x1) == 0, "aString not properly aligned");
+ for (PRUint32 i = 0; i < length; i++)
+ copy[i] = NS_SWAP16(aString[i]);
+ rv = WriteBytes(NS_REINTERPRET_CAST(const char*, copy), byteCount);
+ if (copy != temp)
+ nsMemory::Free(copy);
+#endif
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteUtf8Z(const PRUnichar* aString)
+{
+ NS_NOTREACHED("WriteUtf8Z");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteBytes(const char *aString, PRUint32 aLength)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ rv = Write(aString, aLength, &bytesWritten);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesWritten != aLength)
+ return NS_ERROR_FAILURE;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteByteArray(PRUint8 *aBytes, PRUint32 aLength)
+{
+ return WriteBytes(NS_REINTERPRET_CAST(char *, aBytes), aLength);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteObject(nsISupports* aObject, PRBool aIsStrongRef)
+{
+ NS_NOTREACHED("WriteObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteSingleRefObject(nsISupports* aObject)
+{
+ NS_NOTREACHED("WriteSingleRefObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteCompoundObject(nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef)
+{
+ NS_NOTREACHED("WriteCompoundObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteID(const nsIID& aIID)
+{
+ NS_NOTREACHED("WriteID");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP_(char*)
+nsBinaryOutputStream::GetBuffer(PRUint32 aLength, PRUint32 aAlignMask)
+{
+ if (mBufferAccess)
+ return mBufferAccess->GetBuffer(aLength, aAlignMask);
+ return nsnull;
+}
+
+NS_IMETHODIMP_(void)
+nsBinaryOutputStream::PutBuffer(char* aBuffer, PRUint32 aLength)
+{
+ if (mBufferAccess)
+ mBufferAccess->PutBuffer(aBuffer, aLength);
+}
+
+NS_IMPL_ISUPPORTS3(nsBinaryInputStream, nsIObjectInputStream, nsIBinaryInputStream, nsIInputStream)
+
+NS_IMETHODIMP
+nsBinaryInputStream::Available(PRUint32* aResult)
+{
+ return mInputStream->Available(aResult);
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ return mInputStream->Read(aBuffer, aCount, aNumRead);
+}
+
+
+// when forwarding ReadSegments to mInputStream, we need to make sure
+// 'this' is being passed to the writer each time. To do this, we need
+// a thunking function which keeps the real input stream around.
+
+// the closure wrapper
+struct ReadSegmentsClosure {
+ nsIInputStream* mRealInputStream;
+ void* mRealClosure;
+ nsWriteSegmentFun mRealWriter;
+};
+
+// the thunking function
+static NS_METHOD
+ReadSegmentForwardingThunk(nsIInputStream* aStream,
+ void *aClosure,
+ const char* aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ ReadSegmentsClosure* thunkClosure =
+ NS_REINTERPRET_CAST(ReadSegmentsClosure*, aClosure);
+
+ return thunkClosure->mRealWriter(thunkClosure->mRealInputStream,
+ thunkClosure->mRealClosure,
+ aFromSegment, aToOffset,
+ aCount, aWriteCount);
+}
+
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ ReadSegmentsClosure thunkClosure = { this, closure, writer };
+
+ return mInputStream->ReadSegments(ReadSegmentForwardingThunk, &thunkClosure, count, _retval);
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ return mInputStream->IsNonBlocking(aNonBlocking);
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Close() { return mInputStream->Close(); }
+
+NS_IMETHODIMP
+nsBinaryInputStream::SetInputStream(nsIInputStream *aInputStream)
+{
+ NS_ENSURE_ARG_POINTER(aInputStream);
+ mInputStream = aInputStream;
+ mBufferAccess = do_QueryInterface(aInputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadBoolean(PRBool* aBoolean)
+{
+ PRUint8 byteResult;
+ nsresult rv = Read8(&byteResult);
+ *aBoolean = byteResult;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read8(PRUint8* aByte)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, aByte), sizeof(*aByte), &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != 1)
+ return NS_ERROR_FAILURE;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read16(PRUint16* a16)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, a16), sizeof *a16, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != sizeof *a16)
+ return NS_ERROR_FAILURE;
+ *a16 = NS_SWAP16(*a16);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read32(PRUint32* a32)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, a32), sizeof *a32, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != sizeof *a32)
+ return NS_ERROR_FAILURE;
+ *a32 = NS_SWAP32(*a32);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read64(PRUint64* a64)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, a64), sizeof *a64, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != sizeof *a64)
+ return NS_ERROR_FAILURE;
+ *a64 = NS_SWAP64(*a64);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadFloat(float* aFloat)
+{
+ NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
+ "False assumption about sizeof(float)");
+ return Read32(NS_REINTERPRET_CAST(PRUint32*, aFloat));
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadDouble(double* aDouble)
+{
+ NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
+ "False assumption about sizeof(double)");
+ return Read64(NS_REINTERPRET_CAST(PRUint64*, aDouble));
+}
+
+static NS_METHOD
+WriteSegmentToCString(nsIInputStream* aStream,
+ void *aClosure,
+ const char* aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ nsACString* outString = NS_STATIC_CAST(nsACString*,aClosure);
+
+ outString->Append(aFromSegment, aCount);
+
+ *aWriteCount = aCount;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadCString(nsACString& aString)
+{
+ nsresult rv;
+ PRUint32 length, bytesRead;
+
+ rv = Read32(&length);
+ if (NS_FAILED(rv)) return rv;
+
+ aString.Truncate();
+ rv = ReadSegments(WriteSegmentToCString, &aString, length, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+
+ if (bytesRead != length)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+// sometimes, WriteSegmentToString will be handed an odd-number of
+// bytes, which means we only have half of the last PRUnichar
+struct WriteStringClosure {
+ PRUnichar *mWriteCursor;
+ PRPackedBool mHasCarryoverByte;
+ char mCarryoverByte;
+};
+
+// there are a few cases we have to account for here:
+// * even length buffer, no carryover - easy, just append
+// * odd length buffer, no carryover - the last byte needs to be saved
+// for carryover
+// * odd length buffer, with carryover - first byte needs to be used
+// with the carryover byte, and
+// the rest of the even length
+// buffer is appended as normal
+// * even length buffer, with carryover - the first byte needs to be
+// used with the previous carryover byte.
+// this gives you an odd length buffer,
+// so you have to save the last byte for
+// the next carryover
+
+
+// same version of the above, but with correct casting and endian swapping
+static NS_METHOD
+WriteSegmentToString(nsIInputStream* aStream,
+ void *aClosure,
+ const char* aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ NS_PRECONDITION(aCount > 0, "Why are we being told to write 0 bytes?");
+ NS_PRECONDITION(sizeof(PRUnichar) == 2, "We can't handle other sizes!");
+
+ WriteStringClosure* closure = NS_STATIC_CAST(WriteStringClosure*,aClosure);
+ PRUnichar *cursor = closure->mWriteCursor;
+
+ // we're always going to consume the whole buffer no matter what
+ // happens, so take care of that right now.. that allows us to
+ // tweak aCount later. Do NOT move this!
+ *aWriteCount = aCount;
+
+ // if the last Write had an odd-number of bytes read, then
+ if (closure->mHasCarryoverByte) {
+ // re-create the two-byte sequence we want to work with
+ char bytes[2] = { closure->mCarryoverByte, *aFromSegment };
+ *cursor = *(PRUnichar*)bytes;
+ // Now the little endianness dance
+#ifdef IS_LITTLE_ENDIAN
+ *cursor = (PRUnichar) NS_SWAP16(*cursor);
+#endif
+ ++cursor;
+
+ // now skip past the first byte of the buffer.. code from here
+ // can assume normal operations, but should not assume aCount
+ // is relative to the ORIGINAL buffer
+ ++aFromSegment;
+ --aCount;
+
+ closure->mHasCarryoverByte = PR_FALSE;
+ }
+
+ // this array is possibly unaligned... be careful how we access it!
+ const PRUnichar *unicodeSegment =
+ NS_REINTERPRET_CAST(const PRUnichar*, aFromSegment);
+
+ // calculate number of full characters in segment (aCount could be odd!)
+ PRUint32 segmentLength = aCount / sizeof(PRUnichar);
+
+ // copy all data into our aligned buffer. byte swap if necessary.
+ memcpy(cursor, unicodeSegment, segmentLength * sizeof(PRUnichar));
+ PRUnichar *end = cursor + segmentLength;
+#ifdef IS_LITTLE_ENDIAN
+ for (; cursor < end; ++cursor)
+ *cursor = (PRUnichar) NS_SWAP16(*cursor);
+#endif
+ closure->mWriteCursor = end;
+
+ // remember this is the modifed aCount and aFromSegment,
+ // so that will take into account the fact that we might have
+ // skipped the first byte in the buffer
+ if (aCount % sizeof(PRUnichar) != 0) {
+ // we must have had a carryover byte, that we'll need the next
+ // time around
+ closure->mCarryoverByte = aFromSegment[aCount - 1];
+ closure->mHasCarryoverByte = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadString(nsAString& aString)
+{
+ nsresult rv;
+ PRUint32 length, bytesRead;
+
+ rv = Read32(&length);
+ if (NS_FAILED(rv)) return rv;
+
+ // pre-allocate output buffer, and get direct access to buffer...
+ aString.SetLength(length);
+ nsAString::iterator start;
+ aString.BeginWriting(start);
+
+ WriteStringClosure closure;
+ closure.mWriteCursor = start.get();
+ closure.mHasCarryoverByte = PR_FALSE;
+
+ rv = ReadSegments(WriteSegmentToString, &closure,
+ length*sizeof(PRUnichar), &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ASSERTION(!closure.mHasCarryoverByte, "some strange stream corruption!");
+
+ if (bytesRead != length*sizeof(PRUnichar))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadBytes(PRUint32 aLength, char* *_rval)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+ char* s;
+
+ s = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(aLength));
+ if (!s)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = Read(s, aLength, &bytesRead);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(s);
+ return rv;
+ }
+ if (bytesRead != aLength) {
+ nsMemory::Free(s);
+ return NS_ERROR_FAILURE;
+ }
+
+ *_rval = s;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadByteArray(PRUint32 aLength, PRUint8* *_rval)
+{
+ return ReadBytes(aLength, NS_REINTERPRET_CAST(char **, _rval));
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject)
+{
+ NS_NOTREACHED("ReadObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadID(nsID *aResult)
+{
+ NS_NOTREACHED("ReadID");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP_(char*)
+nsBinaryInputStream::GetBuffer(PRUint32 aLength, PRUint32 aAlignMask)
+{
+ if (mBufferAccess)
+ return mBufferAccess->GetBuffer(aLength, aAlignMask);
+ return nsnull;
+}
+
+NS_IMETHODIMP_(void)
+nsBinaryInputStream::PutBuffer(char* aBuffer, PRUint32 aLength)
+{
+ if (mBufferAccess)
+ mBufferAccess->PutBuffer(aBuffer, aLength);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h
new file mode 100644
index 00000000..7be46dc7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsBinaryStream_h___
+#define nsBinaryStream_h___
+
+#include "nsCOMPtr.h"
+#include "nsAString.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+#include "nsIStreamBufferAccess.h"
+
+#define NS_BINARYOUTPUTSTREAM_CID \
+{ /* 86c37b9a-74e7-4672-844e-6e7dd83ba484 */ \
+ 0x86c37b9a, \
+ 0x74e7, \
+ 0x4672, \
+ {0x84, 0x4e, 0x6e, 0x7d, 0xd8, 0x3b, 0xa4, 0x84} \
+}
+
+#define NS_BINARYOUTPUTSTREAM_CONTRACTID "@mozilla.org/binaryoutputstream;1"
+#define NS_BINARYOUTPUTSTREAM_CLASSNAME "Binary Output Stream"
+
+// Derive from nsIObjectOutputStream so this class can be used as a superclass
+// by nsObjectOutputStream.
+class nsBinaryOutputStream : public nsIObjectOutputStream
+{
+public:
+ nsBinaryOutputStream() {};
+ // virtual dtor since subclasses call our Release()
+ virtual ~nsBinaryOutputStream() {};
+
+protected:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIOutputStream methods
+ NS_DECL_NSIOUTPUTSTREAM
+
+ // nsIBinaryOutputStream methods
+ NS_DECL_NSIBINARYOUTPUTSTREAM
+
+ // nsIObjectOutputStream methods
+ NS_DECL_NSIOBJECTOUTPUTSTREAM
+
+ // Call Write(), ensuring that all proffered data is written
+ nsresult WriteFully(const char *aBuf, PRUint32 aCount);
+
+ nsCOMPtr<nsIOutputStream> mOutputStream;
+ nsCOMPtr<nsIStreamBufferAccess> mBufferAccess;
+};
+
+#define NS_BINARYINPUTSTREAM_CID \
+{ /* c521a612-2aad-46db-b6ab-3b821fb150b1 */ \
+ 0xc521a612, \
+ 0x2aad, \
+ 0x46db, \
+ {0xb6, 0xab, 0x3b, 0x82, 0x1f, 0xb1, 0x50, 0xb1} \
+}
+
+#define NS_BINARYINPUTSTREAM_CONTRACTID "@mozilla.org/binaryinputstream;1"
+#define NS_BINARYINPUTSTREAM_CLASSNAME "Binary Input Stream"
+
+// Derive from nsIObjectInputStream so this class can be used as a superclass
+// by nsObjectInputStream.
+class nsBinaryInputStream : public nsIObjectInputStream
+{
+public:
+ nsBinaryInputStream() {};
+ // virtual dtor since subclasses call our Release()
+ virtual ~nsBinaryInputStream() {};
+
+protected:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIInputStream methods
+ NS_DECL_NSIINPUTSTREAM
+
+ // nsIBinaryInputStream methods
+ NS_DECL_NSIBINARYINPUTSTREAM
+
+ // nsIObjectInputStream methods
+ NS_DECL_NSIOBJECTINPUTSTREAM
+
+ nsCOMPtr<nsIInputStream> mInputStream;
+ nsCOMPtr<nsIStreamBufferAccess> mBufferAccess;
+};
+
+#endif // nsBinaryStream_h___
diff --git a/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp
new file mode 100644
index 00000000..364f71d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsByteArrayInputStream.h"
+#include "nsMemory.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsByteArrayInputStream, nsIInputStream, nsIByteArrayInputStream)
+
+nsByteArrayInputStream::nsByteArrayInputStream (char *buffer, PRUint32 bytes)
+ : _buffer (buffer), _nbytes (bytes), _pos (0)
+{
+}
+
+nsByteArrayInputStream::~nsByteArrayInputStream ()
+{
+ if (_buffer != NULL)
+ nsMemory::Free (_buffer);
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::Available (PRUint32* aResult)
+{
+ if (aResult == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ if (_nbytes == 0 || _buffer == NULL)
+ *aResult = 0;
+ else
+ *aResult = _nbytes - _pos;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::Read (char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ if (aBuffer == NULL || aNumRead == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ if (_nbytes == 0)
+ return NS_ERROR_FAILURE;
+
+ if (aCount == 0 || _pos == _nbytes)
+ *aNumRead = 0;
+ else
+ {
+ NS_ASSERTION (_buffer != NULL, "Stream buffer has been released - there's an ownership problem somewhere!");
+ if (_buffer == NULL)
+ *aNumRead = 0;
+ else
+ if (aCount > _nbytes - _pos)
+ {
+ memcpy (aBuffer, &_buffer[_pos], *aNumRead = _nbytes - _pos);
+ _pos = _nbytes;
+ }
+ else
+ {
+ memcpy (aBuffer, &_buffer[_pos], *aNumRead = aCount);
+ _pos += aCount;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::ReadSegments(nsWriteSegmentFun writer, void * aClosure, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ if (aNumRead == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ if (_nbytes == 0)
+ return NS_ERROR_FAILURE;
+
+ if (aCount == 0 || _pos == _nbytes)
+ *aNumRead = 0;
+ else {
+ NS_ASSERTION (_buffer != NULL, "Stream buffer has been released - there's an ownership problem somewhere!");
+ PRUint32 readCount = PR_MIN(aCount, (_nbytes - _pos));
+ if (_buffer == NULL)
+ *aNumRead = 0;
+ else {
+ nsresult rv = writer (this, aClosure, &_buffer[_pos],
+ _pos, readCount, aNumRead);
+ if (NS_SUCCEEDED(rv))
+ _pos += *aNumRead;
+ }
+ }
+
+ // do not propogate errors returned from writer!
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::Close ()
+{
+ if (_buffer != NULL)
+ {
+ nsMemory::Free (_buffer);
+ _buffer = NULL;
+ _nbytes = 0;
+ }
+ else
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewByteArrayInputStream (nsIByteArrayInputStream* *aResult, char * buffer, unsigned long bytes)
+{
+ if (aResult == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsIByteArrayInputStream * stream = new nsByteArrayInputStream (buffer, bytes);
+
+ if (!stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF (stream);
+ *aResult = stream;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h
new file mode 100644
index 00000000..2999eb5f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIByteArrayInputStream.h"
+#include "nsCOMPtr.h"
+
+class nsByteArrayInputStream : public nsIByteArrayInputStream
+{
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIInputStream methods
+ NS_DECL_NSIINPUTSTREAM
+
+public:
+ nsByteArrayInputStream (char *buffer, PRUint32 nbytes);
+
+private:
+ ~nsByteArrayInputStream ();
+
+ char *_buffer;
+ PRUint32 _nbytes;
+ PRUint32 _pos;
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp
new file mode 100644
index 00000000..60b16eda
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp
@@ -0,0 +1,1241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsLocalFile.h"
+#include "nsDebug.h"
+#include "nsStaticAtom.h"
+
+#if defined(XP_MAC)
+#include <Folders.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#elif defined(XP_WIN)
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#elif defined(XP_UNIX) || defined(XP_MACOSX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <dlfcn.h>
+#include "prenv.h"
+#ifdef XP_MACOSX
+#include <CoreServices/CoreServices.h>
+#include <Folders.h>
+#include <Files.h>
+# ifndef VBOX_WITH_NEWER_OSX_SDK
+# include <Memory.h>
+# endif
+#include <Processes.h>
+#include <Gestalt.h>
+#include <CFURL.h>
+#include <InternetConfig.h>
+#endif
+#elif defined(XP_OS2)
+#define MAX_PATH _MAX_PATH
+#elif defined(XP_BEOS)
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+#endif
+
+#include "SpecialSystemDirectory.h"
+#include "nsAppFileLocationProvider.h"
+
+#if defined(XP_MAC)
+#define COMPONENT_REGISTRY_NAME NS_LITERAL_CSTRING("Component Registry")
+#define COMPONENT_DIRECTORY NS_LITERAL_CSTRING("Components")
+#else
+#define COMPONENT_REGISTRY_NAME NS_LITERAL_CSTRING("compreg.dat")
+#define COMPONENT_DIRECTORY NS_LITERAL_CSTRING("components")
+#endif
+
+#define XPTI_REGISTRY_NAME NS_LITERAL_CSTRING("xpti.dat")
+
+// define home directory
+// For Windows platform, We are choosing Appdata folder as HOME
+#if defined (XP_WIN)
+#define HOME_DIR NS_WIN_APPDATA_DIR
+#elif defined (XP_MAC) || defined (XP_MACOSX)
+#define HOME_DIR NS_OSX_HOME_DIR
+#elif defined (XP_UNIX)
+#define HOME_DIR NS_UNIX_HOME_DIR
+#elif defined (XP_OS2)
+#define HOME_DIR NS_OS2_HOME_DIR
+#elif defined (XP_BEOS)
+#define HOME_DIR NS_BEOS_HOME_DIR
+#endif
+
+//----------------------------------------------------------------------------------------
+nsresult
+nsDirectoryService::GetCurrentProcessDirectory(nsILocalFile** aFile)
+//----------------------------------------------------------------------------------------
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+ *aFile = nsnull;
+
+ // Set the component registry location:
+ if (!mService)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv;
+
+ nsCOMPtr<nsIProperties> dirService;
+ rv = nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(dirService)); // needs to be around for life of product
+
+ if (dirService)
+ {
+ nsCOMPtr <nsILocalFile> aLocalFile;
+ dirService->Get(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(aLocalFile));
+ if (aLocalFile)
+ {
+ *aFile = aLocalFile;
+ NS_ADDREF(*aFile);
+ return NS_OK;
+ }
+ }
+
+ nsLocalFile* localFile = new nsLocalFile;
+
+ if (localFile == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(localFile);
+
+
+
+#ifdef XP_WIN
+ char buf[MAX_PATH];
+ if ( ::GetModuleFileName(0, buf, sizeof(buf)) ) {
+ // chop of the executable name by finding the rightmost backslash
+ char* lastSlash = PL_strrchr(buf, '\\');
+ if (lastSlash)
+ *(lastSlash + 1) = '\0';
+
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+
+#elif defined(XP_MAC)
+ // get info for the the current process to determine the directory
+ // its located in
+ OSErr err;
+ ProcessSerialNumber psn = {kNoProcess, kCurrentProcess};
+ ProcessInfoRec pInfo;
+ FSSpec tempSpec;
+
+ // initialize ProcessInfoRec before calling
+ // GetProcessInformation() or die horribly.
+ pInfo.processName = nil;
+ pInfo.processAppSpec = &tempSpec;
+ pInfo.processInfoLength = sizeof(ProcessInfoRec);
+
+ err = GetProcessInformation(&psn, &pInfo);
+ if (!err)
+ {
+ // create an FSSpec from the volume and dirid of the app.
+ FSSpec appFSSpec;
+ ::FSMakeFSSpec(pInfo.processAppSpec->vRefNum, pInfo.processAppSpec->parID, 0, &appFSSpec);
+
+ nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface((nsIFile*)localFile);
+ if (localFileMac)
+ {
+ localFileMac->InitWithFSSpec(&appFSSpec);
+ *aFile = localFile;
+ return NS_OK;
+ }
+ }
+#elif defined(XP_MACOSX)
+# ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
+ rv = localFile->InitWithNativePath(nsDependentCString(MOZ_DEFAULT_VBOX_XPCOM_HOME));
+ if (NS_SUCCEEDED(rv))
+ *aFile = localFile;
+# else
+ // Works even if we're not bundled.
+ CFBundleRef appBundle = CFBundleGetMainBundle();
+ if (appBundle != nsnull)
+ {
+ CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
+ if (bundleURL != nsnull)
+ {
+ CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL);
+ if (parentURL)
+ {
+ // Pass PR_TRUE for the "resolveAgainstBase" arg to CFURLGetFileSystemRepresentation.
+ // This will resolve the relative portion of the CFURL against it base, giving a full
+ // path, which CFURLCopyFileSystemPath doesn't do.
+ char buffer[PATH_MAX];
+ if (CFURLGetFileSystemRepresentation(parentURL, PR_TRUE, (UInt8 *)buffer, sizeof(buffer)))
+ {
+#ifdef DEBUG_conrad
+ printf("nsDirectoryService - CurrentProcessDir is: %s\n", buffer);
+#endif
+ rv = localFile->InitWithNativePath(nsDependentCString(buffer));
+ if (NS_SUCCEEDED(rv))
+ *aFile = localFile;
+ }
+ CFRelease(parentURL);
+ }
+ CFRelease(bundleURL);
+ }
+ }
+#endif
+
+ NS_ASSERTION(*aFile, "nsDirectoryService - Could not determine CurrentProcessDir.\n");
+ if (*aFile)
+ return NS_OK;
+
+#elif defined(XP_UNIX)
+
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ // - else give the current directory
+ char buf[MAXPATHLEN];
+
+#if 0 /* we need .so location. */
+ // Actually we have a way on linux.
+ static volatile bool fPathSet = false;
+ static char szPath[MAXPATHLEN];
+ if (!fPathSet)
+ {
+ char buf2[MAXPATHLEN + 3];
+ buf2[0] = '\0';
+
+ /*
+ * Env.var. VBOX_XPCOM_HOME first.
+ */
+ char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (psz)
+ {
+ if (strlen(psz) < MAXPATHLEN)
+ {
+ if (!realpath(psz, buf2))
+ strcpy(buf2, psz);
+ strcat(buf2, "/x"); /* for the filename stripping */
+ }
+ }
+
+ /*
+ * The dynamic loader.
+ */
+ if (!buf2[0])
+ {
+ Dl_info DlInfo = {0};
+ if ( !dladdr((void *)nsDirectoryService::mService, &DlInfo)
+ && DlInfo.dli_fname)
+ {
+ if (!realpath(DlInfo.dli_fname, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Executable location.
+ */
+ if (!buf2[0])
+ {
+ char buf[MAXPATHLEN];
+ int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (cchLink > 0 || cchLink != sizeof(buf) - 1)
+ {
+ buf[cchLink] = '\0';
+ if (!realpath(buf, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Copy to static buffer on success.
+ */
+ if (buf2[0])
+ {
+ char *p = strrchr(buf2, '/');
+ if (p)
+ {
+ p[p == buf2] = '\0';
+ #ifdef DEBUG
+ printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
+ #endif
+ strcpy(szPath, buf2);
+ fPathSet = true;
+ }
+ }
+ }
+ if (fPathSet)
+ {
+ localFile->InitWithNativePath(nsDependentCString(szPath));
+ *aFile = localFile;
+ return NS_OK;
+ }
+
+#endif
+
+
+ // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
+ // a --with-default-mozilla-five-home=foo autoconf flag.
+ //
+ // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
+ // regardless of the environment. This makes it easier to write apps that
+ // embed mozilla without having to worry about setting up the environment
+ //
+ // We do this py putenv()ing the default value into the environment. Note that
+ // we only do this if it is not already set.
+#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
+ if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
+ PR_SetEnv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
+#endif
+
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+
+ if (moz5)
+ {
+ if (realpath(moz5, buf)) {
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+ }
+#if defined(DEBUG)
+ static PRBool firstWarning = PR_TRUE;
+
+ if(!moz5 && firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+#endif /* DEBUG */
+
+ // Fall back to current directory.
+ if (getcwd(buf, sizeof(buf)))
+ {
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+
+#elif defined(XP_OS2)
+ PPIB ppib;
+ PTIB ptib;
+ char buffer[CCHMAXPATH];
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, CCHMAXPATH, buffer);
+ *strrchr( buffer, '\\') = '\0'; // XXX DBCS misery
+ localFile->InitWithNativePath(nsDependentCString(buffer));
+ *aFile = localFile;
+ return NS_OK;
+
+#elif defined(XP_BEOS)
+
+ char *moz5 = getenv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ localFile->InitWithNativePath(nsDependentCString(moz5));
+ localFile->Normalize();
+ *aFile = localFile;
+ return NS_OK;
+ }
+ else
+ {
+ static char buf[MAXPATHLEN];
+ int32 cookie = 0;
+ image_info info;
+ char *p;
+ *buf = 0;
+ if(get_next_image_info(0, &cookie, &info) == B_OK)
+ {
+ strcpy(buf, info.name);
+ if((p = strrchr(buf, '/')) != 0)
+ {
+ *p = 0;
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+ }
+ }
+
+#endif
+
+ NS_RELEASE(localFile);
+
+ NS_ERROR("unable to get current process directory");
+ return NS_ERROR_FAILURE;
+} // GetCurrentProcessDirectory()
+
+
+nsIAtom* nsDirectoryService::sCurrentProcess = nsnull;
+nsIAtom* nsDirectoryService::sComponentRegistry = nsnull;
+nsIAtom* nsDirectoryService::sXPTIRegistry = nsnull;
+nsIAtom* nsDirectoryService::sComponentDirectory = nsnull;
+nsIAtom* nsDirectoryService::sGRE_Directory = nsnull;
+nsIAtom* nsDirectoryService::sGRE_ComponentDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_DriveDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_TemporaryDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_CurrentProcessDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_CurrentWorkingDirectory = nsnull;
+#if defined (XP_MACOSX)
+nsIAtom* nsDirectoryService::sDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sTrashDirectory = nsnull;
+nsIAtom* nsDirectoryService::sStartupDirectory = nsnull;
+nsIAtom* nsDirectoryService::sShutdownDirectory = nsnull;
+nsIAtom* nsDirectoryService::sAppleMenuDirectory = nsnull;
+nsIAtom* nsDirectoryService::sControlPanelDirectory = nsnull;
+nsIAtom* nsDirectoryService::sExtensionDirectory = nsnull;
+nsIAtom* nsDirectoryService::sFontsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sPreferencesDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sInternetSearchDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserLibDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDefaultDownloadDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserApplicationsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalApplicationsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserInternetPlugInDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalInternetPlugInDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserFrameworksDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalFrameworksDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserPreferencesDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalPreferencesDirectory = nsnull;
+nsIAtom* nsDirectoryService::sPictureDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sMovieDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sMusicDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sInternetSitesDirectory = nsnull;
+#elif defined (XP_WIN)
+nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
+nsIAtom* nsDirectoryService::sWindowsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktop = nsnull;
+nsIAtom* nsDirectoryService::sPrograms = nsnull;
+nsIAtom* nsDirectoryService::sControls = nsnull;
+nsIAtom* nsDirectoryService::sPrinters = nsnull;
+nsIAtom* nsDirectoryService::sPersonal = nsnull;
+nsIAtom* nsDirectoryService::sFavorites = nsnull;
+nsIAtom* nsDirectoryService::sStartup = nsnull;
+nsIAtom* nsDirectoryService::sRecent = nsnull;
+nsIAtom* nsDirectoryService::sSendto = nsnull;
+nsIAtom* nsDirectoryService::sBitbucket = nsnull;
+nsIAtom* nsDirectoryService::sStartmenu = nsnull;
+nsIAtom* nsDirectoryService::sDesktopdirectory = nsnull;
+nsIAtom* nsDirectoryService::sDrives = nsnull;
+nsIAtom* nsDirectoryService::sNetwork = nsnull;
+nsIAtom* nsDirectoryService::sNethood = nsnull;
+nsIAtom* nsDirectoryService::sFonts = nsnull;
+nsIAtom* nsDirectoryService::sTemplates = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Startmenu = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Programs = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Startup = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Desktopdirectory = nsnull;
+nsIAtom* nsDirectoryService::sAppdata = nsnull;
+nsIAtom* nsDirectoryService::sPrinthood = nsnull;
+nsIAtom* nsDirectoryService::sWinCookiesDirectory = nsnull;
+#elif defined (XP_UNIX)
+nsIAtom* nsDirectoryService::sLocalDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLibDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+#elif defined (XP_OS2)
+nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS2Directory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktopDirectory = nsnull;
+#elif defined (XP_BEOS)
+nsIAtom* nsDirectoryService::sSettingsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
+#endif
+
+
+nsDirectoryService* nsDirectoryService::mService = nsnull;
+
+nsDirectoryService::nsDirectoryService() :
+ mHashtable(256, PR_TRUE)
+{
+}
+
+NS_METHOD
+nsDirectoryService::Create(nsISupports *outer, REFNSIID aIID, void **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ if (!mService)
+ {
+ mService = new nsDirectoryService();
+ if (!mService)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return mService->QueryInterface(aIID, aResult);
+}
+
+static const nsStaticAtom directory_atoms[] = {
+ { NS_XPCOM_CURRENT_PROCESS_DIR, &nsDirectoryService::sCurrentProcess },
+ { NS_XPCOM_COMPONENT_REGISTRY_FILE, &nsDirectoryService::sComponentRegistry },
+ { NS_XPCOM_COMPONENT_DIR, &nsDirectoryService::sComponentDirectory },
+ { NS_XPCOM_XPTI_REGISTRY_FILE, &nsDirectoryService::sXPTIRegistry },
+ { NS_GRE_DIR, &nsDirectoryService::sGRE_Directory },
+ { NS_GRE_COMPONENT_DIR, &nsDirectoryService::sGRE_ComponentDirectory },
+ { NS_OS_DRIVE_DIR, &nsDirectoryService::sOS_DriveDirectory },
+ { NS_OS_TEMP_DIR, &nsDirectoryService::sOS_TemporaryDirectory },
+ { NS_OS_CURRENT_PROCESS_DIR, &nsDirectoryService::sOS_CurrentProcessDirectory },
+ { NS_OS_CURRENT_WORKING_DIR, &nsDirectoryService::sOS_CurrentWorkingDirectory },
+ { NS_XPCOM_INIT_CURRENT_PROCESS_DIR, nsnull },
+#if defined (XP_MACOSX)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sDirectory },
+ { NS_MAC_DESKTOP_DIR, &nsDirectoryService::sDesktopDirectory },
+ { NS_MAC_TRASH_DIR, &nsDirectoryService::sTrashDirectory },
+ { NS_MAC_STARTUP_DIR, &nsDirectoryService::sStartupDirectory },
+ { NS_MAC_SHUTDOWN_DIR, &nsDirectoryService::sShutdownDirectory },
+ { NS_MAC_APPLE_MENU_DIR, &nsDirectoryService::sAppleMenuDirectory },
+ { NS_MAC_CONTROL_PANELS_DIR, &nsDirectoryService::sControlPanelDirectory },
+ { NS_MAC_EXTENSIONS_DIR, &nsDirectoryService::sExtensionDirectory },
+ { NS_MAC_FONTS_DIR, &nsDirectoryService::sFontsDirectory },
+ { NS_MAC_PREFS_DIR, &nsDirectoryService::sPreferencesDirectory },
+ { NS_MAC_DOCUMENTS_DIR, &nsDirectoryService::sDocumentsDirectory },
+ { NS_MAC_INTERNET_SEARCH_DIR, &nsDirectoryService::sInternetSearchDirectory },
+ { NS_MAC_USER_LIB_DIR, &nsDirectoryService::sUserLibDirectory },
+ { NS_OSX_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_OSX_DEFAULT_DOWNLOAD_DIR, &nsDirectoryService::sDefaultDownloadDirectory },
+ { NS_OSX_USER_DESKTOP_DIR, &nsDirectoryService::sUserDesktopDirectory },
+ { NS_OSX_LOCAL_DESKTOP_DIR, &nsDirectoryService::sLocalDesktopDirectory },
+ { NS_OSX_USER_APPLICATIONS_DIR, &nsDirectoryService::sUserApplicationsDirectory },
+ { NS_OSX_LOCAL_APPLICATIONS_DIR, &nsDirectoryService::sLocalApplicationsDirectory },
+ { NS_OSX_USER_DOCUMENTS_DIR, &nsDirectoryService::sUserDocumentsDirectory },
+ { NS_OSX_LOCAL_DOCUMENTS_DIR, &nsDirectoryService::sLocalDocumentsDirectory },
+ { NS_OSX_USER_INTERNET_PLUGIN_DIR, &nsDirectoryService::sUserInternetPlugInDirectory },
+ { NS_OSX_LOCAL_INTERNET_PLUGIN_DIR, &nsDirectoryService::sLocalInternetPlugInDirectory },
+ { NS_OSX_USER_FRAMEWORKS_DIR, &nsDirectoryService::sUserFrameworksDirectory },
+ { NS_OSX_LOCAL_FRAMEWORKS_DIR, &nsDirectoryService::sLocalFrameworksDirectory },
+ { NS_OSX_USER_PREFERENCES_DIR, &nsDirectoryService::sUserPreferencesDirectory },
+ { NS_OSX_LOCAL_PREFERENCES_DIR, &nsDirectoryService::sLocalPreferencesDirectory },
+ { NS_OSX_PICTURE_DOCUMENTS_DIR, &nsDirectoryService::sPictureDocumentsDirectory },
+ { NS_OSX_MOVIE_DOCUMENTS_DIR, &nsDirectoryService::sMovieDocumentsDirectory },
+ { NS_OSX_MUSIC_DOCUMENTS_DIR, &nsDirectoryService::sMusicDocumentsDirectory },
+ { NS_OSX_INTERNET_SITES_DIR, &nsDirectoryService::sInternetSitesDirectory },
+#elif defined (XP_WIN)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory },
+ { NS_WIN_WINDOWS_DIR, &nsDirectoryService::sWindowsDirectory },
+ { NS_WIN_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_WIN_DESKTOP_DIR, &nsDirectoryService::sDesktop },
+ { NS_WIN_PROGRAMS_DIR, &nsDirectoryService::sPrograms },
+ { NS_WIN_CONTROLS_DIR, &nsDirectoryService::sControls },
+ { NS_WIN_PRINTERS_DIR, &nsDirectoryService::sPrinters },
+ { NS_WIN_PERSONAL_DIR, &nsDirectoryService::sPersonal },
+ { NS_WIN_FAVORITES_DIR, &nsDirectoryService::sFavorites },
+ { NS_WIN_STARTUP_DIR, &nsDirectoryService::sStartup },
+ { NS_WIN_RECENT_DIR, &nsDirectoryService::sRecent },
+ { NS_WIN_SEND_TO_DIR, &nsDirectoryService::sSendto },
+ { NS_WIN_BITBUCKET_DIR, &nsDirectoryService::sBitbucket },
+ { NS_WIN_STARTMENU_DIR, &nsDirectoryService::sStartmenu },
+ { NS_WIN_DESKTOP_DIRECTORY, &nsDirectoryService::sDesktopdirectory },
+ { NS_WIN_DRIVES_DIR, &nsDirectoryService::sDrives },
+ { NS_WIN_NETWORK_DIR, &nsDirectoryService::sNetwork },
+ { NS_WIN_NETHOOD_DIR, &nsDirectoryService::sNethood },
+ { NS_WIN_FONTS_DIR, &nsDirectoryService::sFonts },
+ { NS_WIN_TEMPLATES_DIR, &nsDirectoryService::sTemplates },
+ { NS_WIN_COMMON_STARTMENU_DIR, &nsDirectoryService::sCommon_Startmenu },
+ { NS_WIN_COMMON_PROGRAMS_DIR, &nsDirectoryService::sCommon_Programs },
+ { NS_WIN_COMMON_STARTUP_DIR, &nsDirectoryService::sCommon_Startup },
+ { NS_WIN_COMMON_DESKTOP_DIRECTORY, &nsDirectoryService::sCommon_Desktopdirectory },
+ { NS_WIN_APPDATA_DIR, &nsDirectoryService::sAppdata },
+ { NS_WIN_PRINTHOOD, &nsDirectoryService::sPrinthood },
+ { NS_WIN_COOKIES_DIR, &nsDirectoryService::sWinCookiesDirectory },
+#elif defined (XP_UNIX)
+ { NS_UNIX_LOCAL_DIR, &nsDirectoryService::sLocalDirectory },
+ { NS_UNIX_LIB_DIR, &nsDirectoryService::sLibDirectory },
+ { NS_UNIX_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+#elif defined (XP_OS2)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory },
+ { NS_OS2_DIR, &nsDirectoryService::sOS2Directory },
+ { NS_OS2_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_OS2_DESKTOP_DIR, &nsDirectoryService::sDesktopDirectory },
+#elif defined (XP_BEOS)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory },
+ { NS_BEOS_SETTINGS_DIR, &nsDirectoryService::sSettingsDirectory },
+ { NS_BEOS_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_BEOS_DESKTOP_DIR, &nsDirectoryService::sDesktopDirectory },
+#endif
+};
+
+nsresult
+nsDirectoryService::Init()
+{
+ nsresult rv;
+
+ rv = NS_NewISupportsArray(getter_AddRefs(mProviders));
+ if (NS_FAILED(rv)) return rv;
+
+ NS_RegisterStaticAtoms(directory_atoms, NS_ARRAY_LENGTH(directory_atoms));
+
+ // Let the list hold the only reference to the provider.
+ nsAppFileLocationProvider *defaultProvider = new nsAppFileLocationProvider;
+ if (!defaultProvider)
+ return NS_ERROR_OUT_OF_MEMORY;
+ // AppendElement returns PR_TRUE for success.
+ rv = mProviders->AppendElement(defaultProvider) ? NS_OK : NS_ERROR_FAILURE;
+
+ return rv;
+}
+
+PRBool
+nsDirectoryService::ReleaseValues(nsHashKey* key, void* data, void* closure)
+{
+ nsISupports* value = (nsISupports*)data;
+ NS_IF_RELEASE(value);
+ return PR_TRUE;
+}
+
+nsDirectoryService::~nsDirectoryService()
+{
+ // clear the global
+ mService = nsnull;
+
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsDirectoryService, nsIProperties, nsIDirectoryService, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2)
+
+
+NS_IMETHODIMP
+nsDirectoryService::Undefine(const char* prop)
+{
+ nsCStringKey key(prop);
+ if (!mHashtable.Exists(&key))
+ return NS_ERROR_FAILURE;
+
+ mHashtable.Remove (&key);
+ return NS_OK;
+ }
+
+NS_IMETHODIMP
+nsDirectoryService::GetKeys(PRUint32 *count, char ***keys)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+struct FileData
+{
+ FileData(const char* aProperty,
+ const nsIID& aUUID) :
+ property(aProperty),
+ data(nsnull),
+ persistent(PR_TRUE),
+ uuid(aUUID) {}
+
+ const char* property;
+ nsISupports* data;
+ PRBool persistent;
+ const nsIID& uuid;
+};
+
+static PRBool FindProviderFile(nsISupports* aElement, void *aData)
+{
+ nsresult rv;
+ FileData* fileData = (FileData*)aData;
+ if (fileData->uuid.Equals(NS_GET_IID(nsISimpleEnumerator)))
+ {
+ // Not all providers implement this iface
+ nsCOMPtr<nsIDirectoryServiceProvider2> prov2 = do_QueryInterface(aElement);
+ if (prov2)
+ {
+ rv = prov2->GetFiles(fileData->property, (nsISimpleEnumerator **)&fileData->data);
+ if (NS_SUCCEEDED(rv) && fileData->data) {
+ fileData->persistent = PR_FALSE; // Enumerators can never be peristent
+ return PR_FALSE;
+ }
+ }
+ }
+ else
+ {
+ nsCOMPtr<nsIDirectoryServiceProvider> prov = do_QueryInterface(aElement);
+ if (!prov)
+ return PR_FALSE;
+ rv = prov->GetFile(fileData->property, &fileData->persistent, (nsIFile **)&fileData->data);
+ if (NS_SUCCEEDED(rv) && fileData->data)
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::Get(const char* prop, const nsIID & uuid, void* *result)
+{
+ nsCStringKey key(prop);
+
+ nsCOMPtr<nsISupports> value = dont_AddRef(mHashtable.Get(&key));
+
+ if (value)
+ {
+ nsCOMPtr<nsIFile> cloneFile;
+ nsCOMPtr<nsIFile> cachedFile = do_QueryInterface(value);
+ NS_ASSERTION(cachedFile, "nsIFile expected");
+
+ cachedFile->Clone(getter_AddRefs(cloneFile));
+ return cloneFile->QueryInterface(uuid, result);
+ }
+
+ // it is not one of our defaults, lets check any providers
+ FileData fileData(prop, uuid);
+
+ mProviders->EnumerateBackwards(FindProviderFile, &fileData);
+ if (fileData.data)
+ {
+ if (fileData.persistent)
+ {
+ Set(prop, NS_STATIC_CAST(nsIFile*, fileData.data));
+ }
+ nsresult rv = (fileData.data)->QueryInterface(uuid, result);
+ NS_RELEASE(fileData.data); // addref occurs in FindProviderFile()
+ return rv;
+ }
+
+ FindProviderFile(NS_STATIC_CAST(nsIDirectoryServiceProvider*, this), &fileData);
+ if (fileData.data)
+ {
+ if (fileData.persistent)
+ {
+ Set(prop, NS_STATIC_CAST(nsIFile*, fileData.data));
+ }
+ nsresult rv = (fileData.data)->QueryInterface(uuid, result);
+ NS_RELEASE(fileData.data); // addref occurs in FindProviderFile()
+ return rv;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::Set(const char* prop, nsISupports* value)
+{
+ nsCStringKey key(prop);
+ if (mHashtable.Exists(&key) || value == nsnull)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> ourFile;
+ value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile));
+ if (ourFile)
+ {
+ nsCOMPtr<nsIFile> cloneFile;
+ ourFile->Clone (getter_AddRefs (cloneFile));
+ mHashtable.Put(&key, cloneFile);
+
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::Has(const char *prop, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+ nsCOMPtr<nsIFile> value;
+ nsresult rv = Get(prop, NS_GET_IID(nsIFile), getter_AddRefs(value));
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (value)
+ {
+ *_retval = PR_TRUE;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::RegisterProvider(nsIDirectoryServiceProvider *prov)
+{
+ nsresult rv;
+ if (!prov)
+ return NS_ERROR_FAILURE;
+ if (!mProviders)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(prov, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // AppendElement returns PR_TRUE for success.
+ return mProviders->AppendElement(supports) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::UnregisterProvider(nsIDirectoryServiceProvider *prov)
+{
+ nsresult rv;
+ if (!prov)
+ return NS_ERROR_FAILURE;
+ if (!mProviders)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(prov, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // RemoveElement returns PR_TRUE for success.
+ return mProviders->RemoveElement(supports) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+// DO NOT ADD ANY LOCATIONS TO THIS FUNCTION UNTIL YOU TALK TO: dougt@netscape.com.
+// This is meant to be a place of xpcom or system specific file locations, not
+// application specific locations. If you need the later, register a callback for
+// your application.
+
+NS_IMETHODIMP
+nsDirectoryService::GetFile(const char *prop, PRBool *persistent, nsIFile **_retval)
+{
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *_retval = nsnull;
+ *persistent = PR_TRUE;
+
+ nsIAtom* inAtom = NS_NewAtom(prop);
+
+ // check to see if it is one of our defaults
+
+ if (inAtom == nsDirectoryService::sCurrentProcess ||
+ inAtom == nsDirectoryService::sOS_CurrentProcessDirectory )
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sComponentRegistry)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ if (!localFile)
+ return NS_ERROR_FAILURE;
+
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ localFile->AppendNative(COMPONENT_REGISTRY_NAME);
+ }
+ else if (inAtom == nsDirectoryService::sXPTIRegistry)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ if (!localFile)
+ return NS_ERROR_FAILURE;
+
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ localFile->AppendNative(XPTI_REGISTRY_NAME);
+ }
+
+ // Unless otherwise set, the core pieces of the GRE exist
+ // in the current process directory.
+ else if (inAtom == nsDirectoryService::sGRE_Directory)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ }
+ // the GRE components directory is relative to the GRE directory
+ // by default; applications may override this behavior in special
+ // cases
+ else if (inAtom == nsDirectoryService::sGRE_ComponentDirectory)
+ {
+ rv = Get(NS_GRE_DIR, nsILocalFile::GetIID(), getter_AddRefs(localFile));
+ if (localFile)
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ }
+ else if (inAtom == nsDirectoryService::sComponentDirectory)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ if (localFile)
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ }
+ else if (inAtom == nsDirectoryService::sOS_DriveDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_DriveDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS_TemporaryDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS_CurrentProcessDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_CurrentProcessDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS_CurrentWorkingDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_CurrentWorkingDirectory, getter_AddRefs(localFile));
+ }
+
+#if defined(XP_MACOSX)
+ else if (inAtom == nsDirectoryService::sDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kSystemFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sTrashDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kTrashFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sStartupDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kStartupFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sShutdownDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kShutdownFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sAppleMenuDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kAppleMenuFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sControlPanelDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kControlPanelFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sExtensionDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kExtensionFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sFontsDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kFontsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPreferencesDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kPreferencesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sInternetSearchDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kInternetSearchSitesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserLibDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDomainLibraryFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDomainTopLevelFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDefaultDownloadDirectory)
+ {
+ NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localFile));
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(localFile));
+
+ if (localMacFile)
+ {
+ OSErr err;
+ ICInstance icInstance;
+
+ err = ::ICStart(&icInstance, 'XPCM');
+ if (err == noErr)
+ {
+ ICAttr attrs;
+ ICFileSpec icFileSpec;
+ long size = kICFileSpecHeaderSize;
+ err = ::ICGetPref(icInstance, kICDownloadFolder, &attrs, &icFileSpec, &size);
+ if (err == noErr || (err == icTruncatedErr && size >= kICFileSpecHeaderSize))
+ {
+ rv = localMacFile->InitWithFSSpec(&icFileSpec.fss);
+ }
+ ::ICStop(icInstance);
+ }
+
+ if (NS_FAILED(rv))
+ {
+ // We got an error getting the DL folder from IC so try finding the user's Desktop folder
+ rv = GetOSXFolderType(kUserDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ }
+
+ // Don't cache the DL directory as the user may change it while we're running.
+ // Negligible perf hit as this directory is only requested for downloads
+ *persistent = PR_FALSE;
+ }
+ else if (inAtom == nsDirectoryService::sUserDesktopDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalDesktopDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserApplicationsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kApplicationsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalApplicationsDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kApplicationsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserInternetPlugInDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kInternetPlugInFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalInternetPlugInDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kInternetPlugInFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserFrameworksDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kFrameworksFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalFrameworksDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kFrameworksFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserPreferencesDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kPreferencesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalPreferencesDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kPreferencesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPictureDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kPictureDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sMovieDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kMovieDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sMusicDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kMusicDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sInternetSitesDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kInternetSitesFolderType, getter_AddRefs(localFile));
+ }
+#elif defined (XP_WIN)
+ else if (inAtom == nsDirectoryService::sSystemDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_SystemDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sWindowsDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_WindowsDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_HomeDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktop)
+ {
+ rv = GetSpecialSystemDirectory(Win_Desktop, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPrograms)
+ {
+ rv = GetSpecialSystemDirectory(Win_Programs, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sControls)
+ {
+ rv = GetSpecialSystemDirectory(Win_Controls, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPrinters)
+ {
+ rv = GetSpecialSystemDirectory(Win_Printers, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPersonal)
+ {
+ rv = GetSpecialSystemDirectory(Win_Personal, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sFavorites)
+ {
+ rv = GetSpecialSystemDirectory(Win_Favorites, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sStartup)
+ {
+ rv = GetSpecialSystemDirectory(Win_Startup, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sRecent)
+ {
+ rv = GetSpecialSystemDirectory(Win_Recent, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sSendto)
+ {
+ rv = GetSpecialSystemDirectory(Win_Sendto, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sBitbucket)
+ {
+ rv = GetSpecialSystemDirectory(Win_Bitbucket, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sStartmenu)
+ {
+ rv = GetSpecialSystemDirectory(Win_Startmenu, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopdirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_Desktopdirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDrives)
+ {
+ rv = GetSpecialSystemDirectory(Win_Drives, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sNetwork)
+ {
+ rv = GetSpecialSystemDirectory(Win_Network, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sNethood)
+ {
+ rv = GetSpecialSystemDirectory(Win_Nethood, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sFonts)
+ {
+ rv = GetSpecialSystemDirectory(Win_Fonts, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sTemplates)
+ {
+ rv = GetSpecialSystemDirectory(Win_Templates, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Startmenu)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Startmenu, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Programs)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Programs, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Startup)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Startup, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Desktopdirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Desktopdirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sAppdata)
+ {
+ rv = GetSpecialSystemDirectory(Win_Appdata, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPrinthood)
+ {
+ rv = GetSpecialSystemDirectory(Win_Printhood, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sWinCookiesDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_Cookies, getter_AddRefs(localFile));
+ }
+#elif defined (XP_UNIX)
+
+ else if (inAtom == nsDirectoryService::sLocalDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Unix_LocalDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLibDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Unix_LibDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(localFile));
+ }
+#elif defined (XP_OS2)
+ else if (inAtom == nsDirectoryService::sSystemDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_SystemDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS2Directory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_OS2Directory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_HomeDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_DesktopDirectory, getter_AddRefs(localFile));
+ }
+#elif defined (XP_BEOS)
+ else if (inAtom == nsDirectoryService::sSettingsDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_SettingsDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_HomeDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_DesktopDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sSystemDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_SystemDirectory, getter_AddRefs(localFile));
+ }
+#endif
+
+
+ NS_RELEASE(inAtom);
+
+ if (localFile && NS_SUCCEEDED(rv))
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+#ifdef DEBUG_dougt
+ printf("Failed to find directory for key: %s\n", prop);
+#endif
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::GetFiles(const char *prop, nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+
+ return NS_ERROR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h
new file mode 100644
index 00000000..67e6e371
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDirectoryService_h___
+#define nsDirectoryService_h___
+
+#include "nsIDirectoryService.h"
+#include "nsHashtable.h"
+#include "nsILocalFile.h"
+#include "nsISupportsArray.h"
+#include "nsIAtom.h"
+
+#define NS_XPCOM_INIT_CURRENT_PROCESS_DIR "MozBinD" // Can be used to set NS_XPCOM_CURRENT_PROCESS_DIR
+ // CANNOT be used to GET a location
+
+class nsDirectoryService : public nsIDirectoryService,
+ public nsIProperties,
+ public nsIDirectoryServiceProvider2
+{
+ public:
+
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_DIRECTORY_SERVICE_CID);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIPROPERTIES
+
+ NS_DECL_NSIDIRECTORYSERVICE
+
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+ nsDirectoryService();
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsDirectoryService();
+
+ nsresult GetCurrentProcessDirectory(nsILocalFile** aFile);
+
+ static nsDirectoryService* mService;
+ static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure);
+ nsSupportsHashtable mHashtable;
+ nsCOMPtr<nsISupportsArray> mProviders;
+
+public:
+ static nsIAtom *sCurrentProcess;
+ static nsIAtom *sComponentRegistry;
+ static nsIAtom *sComponentDirectory;
+ static nsIAtom *sXPTIRegistry;
+ static nsIAtom *sGRE_Directory;
+ static nsIAtom *sGRE_ComponentDirectory;
+ static nsIAtom *sOS_DriveDirectory;
+ static nsIAtom *sOS_TemporaryDirectory;
+ static nsIAtom *sOS_CurrentProcessDirectory;
+ static nsIAtom *sOS_CurrentWorkingDirectory;
+#if defined (XP_MACOSX)
+ static nsIAtom *sDirectory;
+ static nsIAtom *sDesktopDirectory;
+ static nsIAtom *sTrashDirectory;
+ static nsIAtom *sStartupDirectory;
+ static nsIAtom *sShutdownDirectory;
+ static nsIAtom *sAppleMenuDirectory;
+ static nsIAtom *sControlPanelDirectory;
+ static nsIAtom *sExtensionDirectory;
+ static nsIAtom *sFontsDirectory;
+ static nsIAtom *sPreferencesDirectory;
+ static nsIAtom *sDocumentsDirectory;
+ static nsIAtom *sInternetSearchDirectory;
+ static nsIAtom *sUserLibDirectory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDefaultDownloadDirectory;
+ static nsIAtom *sUserDesktopDirectory;
+ static nsIAtom *sLocalDesktopDirectory;
+ static nsIAtom *sUserApplicationsDirectory;
+ static nsIAtom *sLocalApplicationsDirectory;
+ static nsIAtom *sUserDocumentsDirectory;
+ static nsIAtom *sLocalDocumentsDirectory;
+ static nsIAtom *sUserInternetPlugInDirectory;
+ static nsIAtom *sLocalInternetPlugInDirectory;
+ static nsIAtom *sUserFrameworksDirectory;
+ static nsIAtom *sLocalFrameworksDirectory;
+ static nsIAtom *sUserPreferencesDirectory;
+ static nsIAtom *sLocalPreferencesDirectory;
+ static nsIAtom *sPictureDocumentsDirectory;
+ static nsIAtom *sMovieDocumentsDirectory;
+ static nsIAtom *sMusicDocumentsDirectory;
+ static nsIAtom *sInternetSitesDirectory;
+#elif defined (XP_WIN)
+ static nsIAtom *sSystemDirectory;
+ static nsIAtom *sWindowsDirectory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDesktop;
+ static nsIAtom *sPrograms;
+ static nsIAtom *sControls;
+ static nsIAtom *sPrinters;
+ static nsIAtom *sPersonal;
+ static nsIAtom *sFavorites;
+ static nsIAtom *sStartup;
+ static nsIAtom *sRecent;
+ static nsIAtom *sSendto;
+ static nsIAtom *sBitbucket;
+ static nsIAtom *sStartmenu;
+ static nsIAtom *sDesktopdirectory;
+ static nsIAtom *sDrives;
+ static nsIAtom *sNetwork;
+ static nsIAtom *sNethood;
+ static nsIAtom *sFonts;
+ static nsIAtom *sTemplates;
+ static nsIAtom *sCommon_Startmenu;
+ static nsIAtom *sCommon_Programs;
+ static nsIAtom *sCommon_Startup;
+ static nsIAtom *sCommon_Desktopdirectory;
+ static nsIAtom *sAppdata;
+ static nsIAtom *sPrinthood;
+ static nsIAtom *sWinCookiesDirectory;
+#elif defined (XP_UNIX)
+ static nsIAtom *sLocalDirectory;
+ static nsIAtom *sLibDirectory;
+ static nsIAtom *sHomeDirectory;
+#elif defined (XP_OS2)
+ static nsIAtom *sSystemDirectory;
+ static nsIAtom *sOS2Directory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDesktopDirectory;
+#elif defined (XP_BEOS)
+ static nsIAtom *sSettingsDirectory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDesktopDirectory;
+ static nsIAtom *sSystemDirectory;
+#endif
+
+
+};
+
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h
new file mode 100644
index 00000000..6b3c8ba4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen conrad@ingress.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Defines the property names for directories available from
+ * nsIDirectoryService. These dirs are always available even if no
+ * nsIDirectoryServiceProviders have been registered with the service.
+ * Application level keys are defined in nsAppDirectoryServiceDefs.h.
+ *
+ * Keys whose definition ends in "DIR" or "FILE" return a single nsIFile (or
+ * subclass). Keys whose definition ends in "LIST" return an nsISimpleEnumerator
+ * which enumerates a list of file objects.
+ *
+ * Defines listed in this file are FROZEN. This list may grow.
+ */
+
+#ifndef nsDirectoryServiceDefs_h___
+#define nsDirectoryServiceDefs_h___
+
+/* General OS specific locations */
+
+#define NS_OS_HOME_DIR "Home"
+#define NS_OS_TEMP_DIR "TmpD"
+#define NS_OS_CURRENT_WORKING_DIR "CurWorkD"
+
+/* Property returns the directory in which the procces was started from.
+ * On Unix this will be the path in the VBOX_XPCOM_HOME env var and if
+ * unset will be the current working directory.
+ */
+#define NS_OS_CURRENT_PROCESS_DIR "CurProcD"
+
+/* This location is similar to NS_OS_CURRENT_PROCESS_DIR, however,
+ * NS_XPCOM_CURRENT_PROCESS_DIR can be overriden by passing a "bin
+ * directory" to NS_InitXPCOM2().
+ */
+#define NS_XPCOM_CURRENT_PROCESS_DIR "XCurProcD"
+
+/* Property will return the location of the application components
+ * directory. By default, this directory will be contained in the
+ * NS_XPCOM_CURRENT_PROCESS_DIR.
+ */
+#define NS_XPCOM_COMPONENT_DIR "ComsD"
+
+/* Property will return a list of components directories that will
+ * will be registered after the application components directory.
+ */
+#define NS_XPCOM_COMPONENT_DIR_LIST "ComsDL"
+
+/* Property will return the location of the application components
+ * registry file.
+ */
+#define NS_XPCOM_COMPONENT_REGISTRY_FILE "ComRegF"
+
+/* Property will return the location of the application XPTI
+ * registry file.
+ */
+#define NS_XPCOM_XPTI_REGISTRY_FILE "XptiRegF"
+
+/* Property will return the location of the the XPCOM Shared Library.
+ */
+#define NS_XPCOM_LIBRARY_FILE "XpcomLib"
+
+/* Property will return the current location of the the GRE directory.
+ * If no GRE is used, this propery will behave like
+ * NS_XPCOM_CURRENT_PROCESS_DIR.
+ */
+#define NS_GRE_DIR "GreD"
+
+/* Property will return the current location of the the GRE component
+ * directory. If no GRE is used, this propery will behave like
+ * NS_XPCOM_COMPONENT_DIR.
+ */
+#define NS_GRE_COMPONENT_DIR "GreComsD"
+
+
+/* Platform Specific Locations */
+
+#if !defined (XP_UNIX) || defined(XP_MACOSX)
+ #define NS_OS_SYSTEM_DIR "SysD"
+#endif
+
+#if defined (XP_MACOSX)
+ #define NS_MAC_DESKTOP_DIR "Desk"
+ #define NS_MAC_TRASH_DIR "Trsh"
+ #define NS_MAC_STARTUP_DIR "Strt"
+ #define NS_MAC_SHUTDOWN_DIR "Shdwn"
+ #define NS_MAC_APPLE_MENU_DIR "ApplMenu"
+ #define NS_MAC_CONTROL_PANELS_DIR "CntlPnl"
+ #define NS_MAC_EXTENSIONS_DIR "Exts"
+ #define NS_MAC_FONTS_DIR "Fnts"
+ #define NS_MAC_PREFS_DIR "Prfs"
+ #define NS_MAC_DOCUMENTS_DIR "Docs"
+ #define NS_MAC_INTERNET_SEARCH_DIR "ISrch"
+ #define NS_OSX_HOME_DIR "Home"
+ #define NS_MAC_HOME_DIR NS_OSX_HOME_DIR
+ #define NS_MAC_DEFAULT_DOWNLOAD_DIR "DfltDwnld"
+ #define NS_MAC_USER_LIB_DIR "ULibDir" // Only available under OS X
+ #define NS_OSX_DEFAULT_DOWNLOAD_DIR NS_MAC_DEFAULT_DOWNLOAD_DIR
+ #define NS_OSX_USER_DESKTOP_DIR "UsrDsk"
+ #define NS_OSX_LOCAL_DESKTOP_DIR "LocDsk"
+ #define NS_OSX_USER_APPLICATIONS_DIR "UsrApp"
+ #define NS_OSX_LOCAL_APPLICATIONS_DIR "LocApp"
+ #define NS_OSX_USER_DOCUMENTS_DIR "UsrDocs"
+ #define NS_OSX_LOCAL_DOCUMENTS_DIR "LocDocs"
+ #define NS_OSX_USER_INTERNET_PLUGIN_DIR "UsrIntrntPlgn"
+ #define NS_OSX_LOCAL_INTERNET_PLUGIN_DIR "LoclIntrntPlgn"
+ #define NS_OSX_USER_FRAMEWORKS_DIR "UsrFrmwrks"
+ #define NS_OSX_LOCAL_FRAMEWORKS_DIR "LocFrmwrks"
+ #define NS_OSX_USER_PREFERENCES_DIR "UsrPrfs"
+ #define NS_OSX_LOCAL_PREFERENCES_DIR "LocPrfs"
+ #define NS_OSX_PICTURE_DOCUMENTS_DIR "Pct"
+ #define NS_OSX_MOVIE_DOCUMENTS_DIR "Mov"
+ #define NS_OSX_MUSIC_DOCUMENTS_DIR "Music"
+ #define NS_OSX_INTERNET_SITES_DIR "IntrntSts"
+#elif defined (XP_WIN)
+ #define NS_WIN_WINDOWS_DIR "WinD"
+ #define NS_WIN_HOME_DIR "Home"
+ #define NS_WIN_DESKTOP_DIR "DeskV" // virtual folder at the root of the namespace
+ #define NS_WIN_PROGRAMS_DIR "Progs"
+ #define NS_WIN_CONTROLS_DIR "Cntls"
+ #define NS_WIN_PRINTERS_DIR "Prnts"
+ #define NS_WIN_PERSONAL_DIR "Pers"
+ #define NS_WIN_FAVORITES_DIR "Favs"
+ #define NS_WIN_STARTUP_DIR "Strt"
+ #define NS_WIN_RECENT_DIR "Rcnt"
+ #define NS_WIN_SEND_TO_DIR "SndTo"
+ #define NS_WIN_BITBUCKET_DIR "Buckt"
+ #define NS_WIN_STARTMENU_DIR "Strt"
+ #define NS_WIN_DESKTOP_DIRECTORY "DeskP" // file sys dir which physically stores objects on desktop
+ #define NS_WIN_DRIVES_DIR "Drivs"
+ #define NS_WIN_NETWORK_DIR "NetW"
+ #define NS_WIN_NETHOOD_DIR "netH"
+ #define NS_WIN_FONTS_DIR "Fnts"
+ #define NS_WIN_TEMPLATES_DIR "Tmpls"
+ #define NS_WIN_COMMON_STARTMENU_DIR "CmStrt"
+ #define NS_WIN_COMMON_PROGRAMS_DIR "CmPrgs"
+ #define NS_WIN_COMMON_STARTUP_DIR "CmStrt"
+ #define NS_WIN_COMMON_DESKTOP_DIRECTORY "CmDeskP"
+ #define NS_WIN_APPDATA_DIR "AppData"
+ #define NS_WIN_PRINTHOOD "PrntHd"
+ #define NS_WIN_COOKIES_DIR "CookD"
+#elif defined (XP_UNIX)
+ #define NS_UNIX_LOCAL_DIR "Locl"
+ #define NS_UNIX_LIB_DIR "LibD"
+ #define NS_UNIX_HOME_DIR "Home"
+#elif defined (XP_OS2)
+ #define NS_OS2_DIR "OS2Dir"
+ #define NS_OS2_HOME_DIR "Home"
+ #define NS_OS2_DESKTOP_DIR "Desk"
+#elif defined (XP_BEOS)
+ #define NS_BEOS_SETTINGS_DIR "Setngs"
+ #define NS_BEOS_HOME_DIR "Home"
+ #define NS_BEOS_DESKTOP_DIR "Desk"
+#endif
+
+/* Deprecated */
+
+#define NS_OS_DRIVE_DIR "DrvD"
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h
new file mode 100644
index 00000000..f2482c76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsDirectoryServiceUtils_h___
+#define nsDirectoryServiceUtils_h___
+
+#include "nsIServiceManager.h"
+#include "nsIProperties.h"
+#include "nsCOMPtr.h"
+
+#define NS_DIRECTORY_SERVICE_CID {0xf00152d0,0xb40b,0x11d3,{0x8c, 0x9c, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
+
+inline nsresult
+NS_GetSpecialDirectory(const char* specialDirName, nsIFile* *result)
+{
+ nsresult rv;
+ static NS_DEFINE_CID(kDirectoryServiceCID, NS_DIRECTORY_SERVICE_CID);
+ nsCOMPtr<nsIProperties> serv(do_GetService(kDirectoryServiceCID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ return serv->Get(specialDirName, NS_GET_IID(nsIFile),
+ NS_REINTERPRET_CAST(void**, result));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsEscape.cpp b/src/libs/xpcom18a4/xpcom/io/nsEscape.cpp
new file mode 100644
index 00000000..758339e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsEscape.cpp
@@ -0,0 +1,491 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// First checked in on 98/12/03 by John R. McMullen, derived from net.h/mkparse.c.
+
+#include "nsEscape.h"
+#include "nsMemory.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+
+const int netCharType[256] =
+/* Bit 0 xalpha -- the alphas
+** Bit 1 xpalpha -- as xalpha but
+** converts spaces to plus and plus to %2B
+** Bit 3 ... path -- as xalphas but doesn't escape '/'
+*/
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
+ 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
+ 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
+ /* bits for '@' changed from 7 to 0 so '@' can be escaped */
+ /* in usernames and passwords in publishing. */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */
+ 0, };
+
+/* decode % escaped hex codes into character values
+ */
+#define UNHEX(C) \
+ ((C >= '0' && C <= '9') ? C - '0' : \
+ ((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \
+ ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))
+
+
+#define IS_OK(C) (netCharType[((unsigned int) (C))] & (mask))
+#define HEX_ESCAPE '%'
+
+//----------------------------------------------------------------------------------------
+static char* nsEscapeCount(
+ const char * str,
+ PRInt32 len,
+ nsEscapeMask mask,
+ PRInt32* out_len)
+//----------------------------------------------------------------------------------------
+{
+ if (!str)
+ return 0;
+
+ int i, extra = 0;
+ static const char hexChars[] = "0123456789ABCDEF";
+
+ register const unsigned char* src = (const unsigned char *) str;
+ for (i = 0; i < len; i++)
+ {
+ if (!IS_OK(*src++))
+ extra += 2; /* the escape, plus an extra byte for each nibble */
+ }
+
+ char* result = (char *)nsMemory::Alloc(len + extra + 1);
+ if (!result)
+ return 0;
+
+ register unsigned char* dst = (unsigned char *) result;
+ src = (const unsigned char *) str;
+ if (mask == url_XPAlphas)
+ {
+ for (i = 0; i < len; i++)
+ {
+ unsigned char c = *src++;
+ if (IS_OK(c))
+ *dst++ = c;
+ else if (c == ' ')
+ *dst++ = '+'; /* convert spaces to pluses */
+ else
+ {
+ *dst++ = HEX_ESCAPE;
+ *dst++ = hexChars[c >> 4]; /* high nibble */
+ *dst++ = hexChars[c & 0x0f]; /* low nibble */
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ {
+ unsigned char c = *src++;
+ if (IS_OK(c))
+ *dst++ = c;
+ else
+ {
+ *dst++ = HEX_ESCAPE;
+ *dst++ = hexChars[c >> 4]; /* high nibble */
+ *dst++ = hexChars[c & 0x0f]; /* low nibble */
+ }
+ }
+ }
+
+ *dst = '\0'; /* tack on eos */
+ if(out_len)
+ *out_len = dst - (unsigned char *) result;
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM char* nsEscape(const char * str, nsEscapeMask mask)
+//----------------------------------------------------------------------------------------
+{
+ if(!str)
+ return NULL;
+ return nsEscapeCount(str, (PRInt32)strlen(str), mask, NULL);
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM char* nsUnescape(char * str)
+//----------------------------------------------------------------------------------------
+{
+ nsUnescapeCount(str);
+ return str;
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM PRInt32 nsUnescapeCount(char * str)
+//----------------------------------------------------------------------------------------
+{
+ register char *src = str;
+ register char *dst = str;
+ static const char hexChars[] = "0123456789ABCDEFabcdef";
+
+ char c1[] = " ";
+ char c2[] = " ";
+ char* const pc1 = c1;
+ char* const pc2 = c2;
+
+ while (*src)
+ {
+ c1[0] = *(src+1);
+ if (*(src+1) == '\0')
+ c2[0] = '\0';
+ else
+ c2[0] = *(src+2);
+
+ if (*src != HEX_ESCAPE || PL_strpbrk(pc1, hexChars) == 0 ||
+ PL_strpbrk(pc2, hexChars) == 0 )
+ *dst++ = *src++;
+ else
+ {
+ src++; /* walk over escape */
+ if (*src)
+ {
+ *dst = UNHEX(*src) << 4;
+ src++;
+ }
+ if (*src)
+ {
+ *dst = (*dst + UNHEX(*src));
+ src++;
+ }
+ dst++;
+ }
+ }
+
+ *dst = 0;
+ return (int)(dst - str);
+
+} /* NET_UnEscapeCnt */
+
+
+NS_COM char *
+nsEscapeHTML(const char * string)
+{
+ /* XXX Hardcoded max entity len. The +1 is for the trailing null. */
+ char *rv = (char *) nsMemory::Alloc(strlen(string) * 6 + 1);
+ char *ptr = rv;
+
+ if(rv)
+ {
+ for(; *string != '\0'; string++)
+ {
+ if(*string == '<')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'l';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ }
+ else if(*string == '>')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'g';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ }
+ else if(*string == '&')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'a';
+ *ptr++ = 'm';
+ *ptr++ = 'p';
+ *ptr++ = ';';
+ }
+ else if (*string == '"')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'q';
+ *ptr++ = 'u';
+ *ptr++ = 'o';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ }
+ else if (*string == '\'')
+ {
+ *ptr++ = '&';
+ *ptr++ = '#';
+ *ptr++ = '3';
+ *ptr++ = '9';
+ *ptr++ = ';';
+ }
+ else
+ {
+ *ptr++ = *string;
+ }
+ }
+ *ptr = '\0';
+ }
+
+ return(rv);
+}
+
+NS_COM PRUnichar *
+nsEscapeHTML2(const PRUnichar *aSourceBuffer, PRInt32 aSourceBufferLen)
+{
+ // if the caller didn't calculate the length
+ if (aSourceBufferLen == -1) {
+ aSourceBufferLen = nsCRT::strlen(aSourceBuffer); // ...then I will
+ }
+
+ /* XXX Hardcoded max entity len. */
+ PRUnichar *resultBuffer = (PRUnichar *)nsMemory::Alloc(aSourceBufferLen *
+ 6 * sizeof(PRUnichar) + sizeof(PRUnichar('\0')));
+ PRUnichar *ptr = resultBuffer;
+
+ if (resultBuffer) {
+ PRInt32 i;
+
+ for(i = 0; i < aSourceBufferLen; i++) {
+ if(aSourceBuffer[i] == '<') {
+ *ptr++ = '&';
+ *ptr++ = 'l';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ } else if(aSourceBuffer[i] == '>') {
+ *ptr++ = '&';
+ *ptr++ = 'g';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ } else if(aSourceBuffer[i] == '&') {
+ *ptr++ = '&';
+ *ptr++ = 'a';
+ *ptr++ = 'm';
+ *ptr++ = 'p';
+ *ptr++ = ';';
+ } else if (aSourceBuffer[i] == '"') {
+ *ptr++ = '&';
+ *ptr++ = 'q';
+ *ptr++ = 'u';
+ *ptr++ = 'o';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ } else if (aSourceBuffer[i] == '\'') {
+ *ptr++ = '&';
+ *ptr++ = '#';
+ *ptr++ = '3';
+ *ptr++ = '9';
+ *ptr++ = ';';
+ } else {
+ *ptr++ = aSourceBuffer[i];
+ }
+ }
+ *ptr = 0;
+ }
+
+ return resultBuffer;
+}
+
+//----------------------------------------------------------------------------------------
+
+const int EscapeChars[256] =
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ 0,1023, 0, 512,1023, 0,1023,1023,1023,1023,1023,1023,1023,1023, 953, 784, /* 2x !"#$%&'()*+,-./ */
+ 1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1008, 912, 0,1008, 0, 768, /* 3x 0123456789:;<=>? */
+ 1008,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, /* 4x @ABCDEFGHIJKLMNO */
+ 1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, 896, 896, 896, 896,1023, /* 5x PQRSTUVWXYZ[\]^_ */
+ 0,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, /* 6x `abcdefghijklmno */
+ 1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, 896,1012, 896,1023, 0, /* 7x pqrstuvwxyz{|}~ */
+ 0 /* 8x DEL */
+};
+
+#define NO_NEED_ESC(C) (EscapeChars[((unsigned int) (C))] & (mask))
+
+//----------------------------------------------------------------------------------------
+
+/* returns an escaped string */
+
+/* use the following masks to specify which
+ part of an URL you want to escape:
+
+ esc_Scheme = 1
+ esc_Username = 2
+ esc_Password = 4
+ esc_Host = 8
+ esc_Directory = 16
+ esc_FileBaseName = 32
+ esc_FileExtension = 64
+ esc_Param = 128
+ esc_Query = 256
+ esc_Ref = 512
+*/
+
+/* by default this function will not escape parts of a string
+ that already look escaped, which means it already includes
+ a valid hexcode. This is done to avoid multiple escapes of
+ a string. Use the following mask to force escaping of a
+ string:
+
+ esc_Forced = 1024
+*/
+
+NS_COM PRBool NS_EscapeURL(const char *part,
+ PRInt32 partLen,
+ PRInt16 mask,
+ nsACString &result)
+{
+ if (!part) {
+ NS_NOTREACHED("null pointer");
+ return PR_FALSE;
+ }
+
+ int i = 0;
+ static const char hexChars[] = "0123456789ABCDEF";
+ if (partLen < 0)
+ partLen = strlen(part);
+ PRBool forced = (mask & esc_Forced);
+ PRBool ignoreNonAscii = (mask & esc_OnlyASCII);
+ PRBool ignoreAscii = (mask & esc_OnlyNonASCII);
+ PRBool writing = (mask & esc_AlwaysCopy);
+ PRBool colon = (mask & esc_Colon);
+
+ register const unsigned char* src = (const unsigned char *) part;
+
+ char tempBuffer[100];
+ unsigned int tempBufferPos = 0;
+
+ for (i = 0; i < partLen; i++)
+ {
+ unsigned char c = *src++;
+
+ // if the char has not to be escaped or whatever follows % is
+ // a valid escaped string, just copy the char.
+ //
+ // Also the % will not be escaped until forced
+ // See bugzilla bug 61269 for details why we changed this
+ //
+ // And, we will not escape non-ascii characters if requested.
+ // On special request we will also escape the colon even when
+ // not covered by the matrix.
+ // ignoreAscii is not honored for control characters (C0 and DEL)
+ if ((NO_NEED_ESC(c) || (c == HEX_ESCAPE && !forced)
+ || (c > 0x7f && ignoreNonAscii)
+ || (c > 0x1f && c < 0x7f && ignoreAscii))
+ && !(c == ':' && colon))
+ {
+ if (writing)
+ tempBuffer[tempBufferPos++] = c;
+ }
+ else /* do the escape magic */
+ {
+ if (!writing)
+ {
+ result.Append(part, i);
+ writing = PR_TRUE;
+ }
+ tempBuffer[tempBufferPos++] = HEX_ESCAPE;
+ tempBuffer[tempBufferPos++] = hexChars[c >> 4]; /* high nibble */
+ tempBuffer[tempBufferPos++] = hexChars[c & 0x0f]; /* low nibble */
+ }
+
+ if (tempBufferPos >= sizeof(tempBuffer) - 4)
+ {
+ NS_ASSERTION(writing, "should be writing");
+ tempBuffer[tempBufferPos] = '\0';
+ result += tempBuffer;
+ tempBufferPos = 0;
+ }
+ }
+ if (writing) {
+ tempBuffer[tempBufferPos] = '\0';
+ result += tempBuffer;
+ }
+ return writing;
+}
+
+#define ISHEX(c) memchr(hexChars, c, sizeof(hexChars)-1)
+
+NS_COM PRBool NS_UnescapeURL(const char *str, PRInt32 len, PRInt16 flags, nsACString &result)
+{
+ if (!str) {
+ NS_NOTREACHED("null pointer");
+ return PR_FALSE;
+ }
+
+ if (len < 0)
+ len = strlen(str);
+
+ PRBool ignoreNonAscii = (flags & esc_OnlyASCII);
+ PRBool writing = (flags & esc_AlwaysCopy);
+ PRBool skipControl = (flags & esc_SkipControl);
+
+ static const char hexChars[] = "0123456789ABCDEFabcdef";
+
+ const char *last = str;
+ const char *p = str;
+
+ for (int i=0; i<len; ++i, ++p) {
+ //printf("%c [i=%d of len=%d]\n", *p, i, len);
+ if (*p == HEX_ESCAPE && i < len-2) {
+ unsigned char *p1 = ((unsigned char *) p) + 1;
+ unsigned char *p2 = ((unsigned char *) p) + 2;
+ if (ISHEX(*p1) && ISHEX(*p2) && !(ignoreNonAscii && *p1 >= '8') &&
+ !(skipControl &&
+ (*p1 < '2' || (*p1 == '7' && (*p2 == 'f' || *p2 == 'F'))))) {
+ //printf("- p1=%c p2=%c\n", *p1, *p2);
+ writing = PR_TRUE;
+ if (p > last) {
+ //printf("- p=%p, last=%p\n", p, last);
+ result.Append(last, p - last);
+ last = p;
+ }
+ char u = (UNHEX(*p1) << 4) + UNHEX(*p2);
+ //printf("- u=%c\n", u);
+ result.Append(u);
+ i += 2;
+ p += 2;
+ last += 3;
+ }
+ }
+ }
+ if (writing && last < str + len)
+ result.Append(last, str + len - last);
+
+ return writing;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsEscape.h b/src/libs/xpcom18a4/xpcom/io/nsEscape.h
new file mode 100644
index 00000000..aaf56738
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsEscape.h
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* First checked in on 98/12/03 by John R. McMullen, derived from net.h/mkparse.c. */
+
+#ifndef _ESCAPE_H_
+#define _ESCAPE_H_
+
+#include "prtypes.h"
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define nsEscape VBoxNsxpnsEscape
+#define nsUnescape VBoxNsxpnsUnescape
+#define nsUnescapeCount VBoxNsxpnsUnescapeCount
+#define nsEscapeHTML VBoxNsxpnsEscapeHTML
+#define nsEscapeHTML2 VBoxNsxpnsEscapeHTML2
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/**
+ * Valid mask values for nsEscape
+ */
+typedef enum {
+ url_XAlphas = PR_BIT(0) /**< Normal escape - leave alphas intact, escape the rest */
+, url_XPAlphas = PR_BIT(1) /**< As url_XAlphas, but convert spaces (0x20) to '+' and plus to %2B */
+, url_Path = PR_BIT(2) /**< As url_XAlphas, but don't escape slash ('/') */
+} nsEscapeMask;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Escape the given string according to mask
+ * @param str The string to escape
+ * @param mask How to escape the string
+ * @return A newly allocated escaped string that must be free'd with
+ * nsCRT::free, or null on failure
+ */
+NS_COM char * nsEscape(const char * str, nsEscapeMask mask);
+
+NS_COM char * nsUnescape(char * str);
+ /* decode % escaped hex codes into character values,
+ * modifies the parameter, returns the same buffer
+ */
+
+NS_COM PRInt32 nsUnescapeCount (char * str);
+ /* decode % escaped hex codes into character values,
+ * modifies the parameter buffer, returns the length of the result
+ * (result may contain \0's).
+ */
+
+NS_COM char *
+nsEscapeHTML(const char * string);
+
+NS_COM PRUnichar *
+nsEscapeHTML2(const PRUnichar *aSourceBuffer,
+ PRInt32 aSourceBufferLen = -1);
+ /*
+ * Escape problem char's for HTML display
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/**
+ * NS_EscapeURL/NS_UnescapeURL constants for |flags| parameter:
+ */
+enum EscapeMask {
+ /** url components **/
+ esc_Scheme = PR_BIT(0),
+ esc_Username = PR_BIT(1),
+ esc_Password = PR_BIT(2),
+ esc_Host = PR_BIT(3),
+ esc_Directory = PR_BIT(4),
+ esc_FileBaseName = PR_BIT(5),
+ esc_FileExtension = PR_BIT(6),
+ esc_FilePath = esc_Directory | esc_FileBaseName | esc_FileExtension,
+ esc_Param = PR_BIT(7),
+ esc_Query = PR_BIT(8),
+ esc_Ref = PR_BIT(9),
+ /** special flags **/
+ esc_Minimal = esc_Scheme | esc_Username | esc_Password | esc_Host | esc_FilePath | esc_Param | esc_Query | esc_Ref,
+ esc_Forced = PR_BIT(10), /* forces escaping of existing escape sequences */
+ esc_OnlyASCII = PR_BIT(11), /* causes non-ascii octets to be skipped */
+ esc_OnlyNonASCII = PR_BIT(12), /* causes _graphic_ ascii octets (0x20-0x7E)
+ * to be skipped when escaping. causes all
+ * ascii octets to be skipped when unescaping */
+ esc_AlwaysCopy = PR_BIT(13), /* copy input to result buf even if escaping is unnecessary */
+ esc_Colon = PR_BIT(14), /* forces escape of colon */
+ esc_SkipControl = PR_BIT(15) /* skips C0 and DEL from unescaping */
+};
+
+/**
+ * NS_EscapeURL
+ *
+ * Escapes invalid char's in an URL segment. Has no side-effect if the URL
+ * segment is already escaped. Otherwise, the escaped URL segment is appended
+ * to |result|.
+ *
+ * @param str url segment string
+ * @param len url segment string length (-1 if unknown)
+ * @param flags url segment type flag
+ * @param result result buffer, untouched if part is already escaped
+ *
+ * @return TRUE if escaping was performed, FALSE otherwise.
+ */
+NS_COM PRBool NS_EscapeURL(const char *str,
+ PRInt32 len,
+ PRInt16 flags,
+ nsACString &result);
+
+/**
+ * Expands URL escape sequences... beware embedded null bytes!
+ *
+ * @param str url string to unescape
+ * @param len length of |str|
+ * @param flags only esc_OnlyNonASCII, esc_SkipControl and esc_AlwaysCopy
+ * are recognized
+ * @param result result buffer, untouched if |str| is already unescaped
+ *
+ * @return TRUE if unescaping was performed, FALSE otherwise.
+ */
+NS_COM PRBool NS_UnescapeURL(const char *str,
+ PRInt32 len,
+ PRInt16 flags,
+ nsACString &result);
+
+/** returns resultant string length **/
+inline PRInt32 NS_UnescapeURL(char *str) { return nsUnescapeCount(str); }
+
+/**
+ * string friendly versions...
+ */
+inline const nsACString &
+NS_EscapeURL(const nsASingleFragmentCString &part, PRInt16 partType, nsACString &result) {
+ const char *temp;
+ if (NS_EscapeURL(part.BeginReading(temp), part.Length(), partType, result))
+ return result;
+ return part;
+}
+inline const nsACString &
+NS_UnescapeURL(const nsASingleFragmentCString &str, PRInt16 flags, nsACString &result) {
+ const char *temp;
+ if (NS_UnescapeURL(str.BeginReading(temp), str.Length(), flags, result))
+ return result;
+ return str;
+}
+// inline unescape
+inline nsAFlatCString &
+NS_UnescapeURL(nsAFlatCString &str)
+{
+ str.SetLength(nsUnescapeCount(str.BeginWriting()));
+ return str;
+}
+
+#endif // _ESCAPE_H_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp
new file mode 100644
index 00000000..56b09d22
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp
@@ -0,0 +1,2581 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <string.h>
+#include "prtypes.h"
+#include "nscore.h"
+#include "nsDebug.h"
+#include "nsEnumeratorUtils.h"
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+#include "nsIComponentManager.h"
+#include "nsIFile.h"
+#include "nsILocalFile.h"
+#include "nsISeekableStream.h"
+#include "nsISerializable.h"
+#include "nsIStreamBufferAccess.h"
+
+#include "nsBinaryStream.h"
+#include "nsFastLoadFile.h"
+#include "nsInt64.h"
+
+#ifdef DEBUG_brendan
+# define METERING
+# define DEBUG_MUX
+#endif
+
+#ifdef METERING
+# define METER(x) x
+#else
+# define METER(x) /* nothing */
+#endif
+
+#ifdef DEBUG_MUX
+# include <stdio.h>
+# include <stdarg.h>
+
+static void trace_mux(char mode, const char *format, ...)
+{
+ va_list ap;
+ static FILE *tfp;
+ if (!tfp) {
+ char tfn[16];
+ sprintf(tfn, "/tmp/mux.%ctrace", mode);
+ tfp = fopen(tfn, "w");
+ if (!tfp)
+ return;
+ setvbuf(tfp, NULL, _IOLBF, 0);
+ }
+ va_start(ap, format);
+ vfprintf(tfp, format, ap);
+ va_end(ap);
+}
+
+# define TRACE_MUX(args) trace_mux args
+#else
+# define TRACE_MUX(args) /* nothing */
+#endif
+
+/*
+ * Fletcher's 16-bit checksum, using 32-bit two's-complement arithmetic.
+ */
+#define FOLD_ONES_COMPLEMENT_CARRY(X) ((X) = ((X) & 0xffff) + ((X) >> 16))
+#define ONES_COMPLEMENT_ACCUMULATE(X,Y) (X) += (Y); if ((X) & 0x80000000) \
+ FOLD_ONES_COMPLEMENT_CARRY(X)
+#define FLETCHER_ACCUMULATE(A,B,U) ONES_COMPLEMENT_ACCUMULATE(A, U); \
+ ONES_COMPLEMENT_ACCUMULATE(B, A)
+
+PR_IMPLEMENT(PRUint32)
+NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum,
+ const PRUint8* aBuffer,
+ PRUint32 aLength,
+ PRBool aLastBuffer)
+{
+ PRUint32 C = *aChecksum;
+ PRUint32 A = C & 0xffff;
+ PRUint32 B = C >> 16;
+
+ PRUint16 U = 0;
+ if (aLength >= 4) {
+ PRBool odd = PRWord(aBuffer) & 1;
+ switch (PRWord(aBuffer) & 3) {
+ case 3:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = aBuffer[2];
+ aBuffer += 3;
+ aLength -= 3;
+ break;
+
+ case 2:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = 0;
+ aBuffer += 2;
+ aLength -= 2;
+ break;
+
+ case 1:
+ U = *aBuffer++;
+ aLength--;
+ break;
+ }
+
+ PRUint32 W;
+ if (odd) {
+ while (aLength > 3) {
+ W = *NS_REINTERPRET_CAST(const PRUint32*, aBuffer);
+ U <<= 8;
+#ifdef IS_BIG_ENDIAN
+ U |= W >> 24;
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = PRUint16(W >> 8);
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = W & 0xff;
+#else
+ U |= W & 0xff;
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = PRUint16(W >> 8);
+ U = NS_SWAP16(U);
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = W >> 24;
+#endif
+ aBuffer += 4;
+ aLength -= 4;
+ }
+ aBuffer--; // we're odd, we didn't checksum the last byte
+ aLength++;
+ } else {
+ while (aLength > 3) {
+ W = *NS_REINTERPRET_CAST(const PRUint32*, aBuffer);
+#ifdef IS_BIG_ENDIAN
+ U = W >> 16;
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = PRUint16(W);
+ FLETCHER_ACCUMULATE(A, B, U);
+#else
+ U = NS_SWAP16(W);
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = W >> 16;
+ U = NS_SWAP16(W);
+ FLETCHER_ACCUMULATE(A, B, U);
+#endif
+ aBuffer += 4;
+ aLength -= 4;
+ }
+ }
+ }
+
+ if (aLastBuffer) {
+ NS_ASSERTION(aLength <= 4, "aLength botch");
+ switch (aLength) {
+ case 4:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = (aBuffer[2] << 8) | aBuffer[3];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+
+ case 3:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = aBuffer[2];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+
+ case 2:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+
+ case 1:
+ U = aBuffer[0];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+ }
+
+ aLength = 0;
+ }
+
+ while (A >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(A);
+ while (B >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(B);
+
+ *aChecksum = (B << 16) | A;
+ return aLength;
+}
+
+PR_IMPLEMENT(PRUint32)
+NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount)
+{
+ PRUint32 A1 = sum1 & 0xffff;
+ PRUint32 B1 = sum1 >> 16;
+
+ PRUint32 A2 = sum2 & 0xffff;
+ PRUint32 B2 = sum2 >> 16;
+
+ PRUint32 A = A1 + A2;
+ while (A >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(A);
+
+ PRUint32 B = B2;
+ for (PRUint32 n = (sum2ByteCount + 1) / 2; n != 0; n--)
+ ONES_COMPLEMENT_ACCUMULATE(B, B1);
+ while (B >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(B);
+
+ return (B << 16) | A;
+}
+
+#undef FOLD_ONES_COMPLEMENT_CARRY
+#undef ONES_COMPLEMENT_ACCUMULATE
+#undef FLETCHER_ACCUMULATE
+
+static const char magic[] = MFL_FILE_MAGIC;
+
+// -------------------------- nsFastLoadFileReader --------------------------
+
+nsID nsFastLoadFileReader::nsFastLoadFooter::gDummyID;
+nsFastLoadFileReader::nsObjectMapEntry
+ nsFastLoadFileReader::nsFastLoadFooter::gDummySharpObjectEntry;
+
+NS_IMPL_ISUPPORTS_INHERITED5(nsFastLoadFileReader,
+ nsBinaryInputStream,
+ nsIObjectInputStream,
+ nsIFastLoadFileControl,
+ nsIFastLoadReadControl,
+ nsISeekableStream,
+ nsIFastLoadFileReader)
+
+MOZ_DECL_CTOR_COUNTER(nsFastLoadFileReader)
+
+nsresult
+nsFastLoadFileReader::ReadHeader(nsFastLoadHeader *aHeader)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, aHeader), sizeof *aHeader, &bytesRead);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesRead != sizeof *aHeader ||
+ memcmp(aHeader->mMagic, magic, MFL_FILE_MAGIC_SIZE)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ aHeader->mChecksum = NS_SWAP32(aHeader->mChecksum);
+ aHeader->mVersion = NS_SWAP32(aHeader->mVersion);
+ aHeader->mFooterOffset = NS_SWAP32(aHeader->mFooterOffset);
+ aHeader->mFileSize = NS_SWAP32(aHeader->mFileSize);
+
+ return NS_OK;
+}
+
+// nsIFastLoadFileControl methods:
+
+NS_IMETHODIMP
+nsFastLoadFileReader::GetChecksum(PRUint32 *aChecksum)
+{
+ *aChecksum = mHeader.mChecksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::SetChecksum(PRUint32 aChecksum)
+{
+ mHeader.mChecksum = aChecksum;
+ return NS_OK;
+}
+
+struct nsStringMapEntry : public PLDHashEntryHdr {
+ const char* mString; // key, must come first
+ nsISupports* mURI; // for SelectMuxedDocument return value
+};
+
+struct nsDocumentMapEntry : public nsStringMapEntry {
+ PRUint32 mInitialSegmentOffset; // offset of URI's first segment in file
+};
+
+struct nsDocumentMapReadEntry : public nsDocumentMapEntry {
+ PRUint32 mNextSegmentOffset; // offset of URI's next segment to read
+ PRUint32 mBytesLeft : 31, // bytes remaining in current segment
+ mNeedToSeek : 1; // flag to defer Seek from Select to
+ // Read, in case there is no Read before
+ // another entry is Selected (to improve
+ // input stream buffer utilization)
+ PRInt64 mSaveOffset; // in case demux schedule differs from
+ // mux schedule
+};
+
+PR_STATIC_CALLBACK(void)
+strmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsStringMapEntry* entry = NS_STATIC_CAST(nsStringMapEntry*, aHdr);
+
+ if (entry->mString)
+ nsMemory::Free((void*) entry->mString);
+ NS_IF_RELEASE(entry->mURI);
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps strmap_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ strmap_ClearEntry,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+// An nsObjectMapEntry holds a strong reference to an XPCOM object, unless the
+// mObject member, when cast to NSFastLoadOID, has its MFL_OBJECT_DEF_TAG bit
+// set. NB: we rely on the fact that an nsISupports* is never an odd pointer.
+struct nsObjectMapEntry : public PLDHashEntryHdr {
+ nsISupports* mObject; // key, must come first
+};
+
+// Fast mapping from URI object pointer back to spec-indexed document info.
+struct nsURIMapReadEntry : public nsObjectMapEntry {
+ nsDocumentMapReadEntry* mDocMapEntry;
+};
+
+PR_STATIC_CALLBACK(void)
+objmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsObjectMapEntry* entry = NS_STATIC_CAST(nsObjectMapEntry*, aHdr);
+
+ // Ignore tagged object ids stored as object pointer keys (the updater
+ // code does this).
+ if ((NS_PTR_TO_INT32(entry->mObject) & MFL_OBJECT_DEF_TAG) == 0)
+ NS_IF_RELEASE(entry->mObject);
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps objmap_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashVoidPtrKeyStub,
+ PL_DHashMatchEntryStub,
+ PL_DHashMoveEntryStub,
+ objmap_ClearEntry,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+NS_IMETHODIMP
+nsFastLoadFileReader::HasMuxedDocument(const char* aURISpec, PRBool *aResult)
+{
+ nsDocumentMapReadEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec,
+ PL_DHASH_LOOKUP));
+
+ *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::StartMuxedDocument(nsISupports* aURI, const char* aURISpec)
+{
+ nsDocumentMapReadEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec,
+ PL_DHASH_LOOKUP));
+
+ // If the spec isn't in the map, return NS_ERROR_NOT_AVAILABLE so the
+ // FastLoad service can try for a file update.
+ if (PL_DHASH_ENTRY_IS_FREE(docMapEntry))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapReadEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mURIMap, key,
+ PL_DHASH_ADD));
+ if (!uriMapEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(uriMapEntry->mDocMapEntry == nsnull,
+ "URI mapped to two different specs?");
+ if (uriMapEntry->mDocMapEntry)
+ return NS_ERROR_UNEXPECTED;
+
+ docMapEntry->mURI = aURI;
+ NS_ADDREF(docMapEntry->mURI);
+ uriMapEntry->mObject = key;
+ NS_ADDREF(uriMapEntry->mObject);
+ uriMapEntry->mDocMapEntry = docMapEntry;
+ TRACE_MUX(('r', "start %p (%p) %s\n", aURI, key.get(), aURISpec));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI,
+ nsISupports** aResult)
+{
+ nsresult rv;
+
+ // Find the given URI's entry and select it for more reading.
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapReadEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mURIMap, key,
+ PL_DHASH_LOOKUP));
+
+ // If the URI isn't in the map, return NS_ERROR_NOT_AVAILABLE so the
+ // FastLoad service can try selecting the file updater.
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ // If we're interrupting another document's segment, save its offset so
+ // we can seek back when it's reselected. If prevDocMapEntry->mNeedToSeek
+ // is set, that means the stream is not positioned for prevDocMapEntry, to
+ // avoid buffer thrashing. See below in this function for more.
+ nsDocumentMapReadEntry* prevDocMapEntry = mCurrentDocumentMapEntry;
+ if (prevDocMapEntry &&
+ prevDocMapEntry->mBytesLeft &&
+ !prevDocMapEntry->mNeedToSeek) {
+ rv = Tell(&prevDocMapEntry->mSaveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // It turns out we get a fair amount of redundant select calls, thanks to
+ // non-blocking hunks of data from the parser that are devoid of scripts.
+ // As more data gets FastLoaded, the number of these useless selects will
+ // decline.
+ nsDocumentMapReadEntry* docMapEntry = uriMapEntry->mDocMapEntry;
+ if (docMapEntry == prevDocMapEntry) {
+ TRACE_MUX(('r', "select prev %s same as current!\n",
+ docMapEntry->mString));
+ }
+
+ // Invariant: docMapEntry->mBytesLeft implies docMapEntry->mSaveOffset has
+ // been set non-zero by the Tell call above.
+ else if (docMapEntry->mBytesLeft) {
+ NS_ASSERTION(docMapEntry->mSaveOffset != 0,
+ "reselecting from multiplex at unsaved offset?");
+
+ // Defer Seek till Read, in case of "ping-pong" Selects without any
+ // intervening Reads, to avoid dumping the underlying mInputStream's
+ // input buffer for cases where alternate "pongs" fall in the same
+ // buffer.
+ docMapEntry->mNeedToSeek = PR_TRUE;
+ }
+
+ *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull;
+ NS_IF_ADDREF(*aResult);
+
+ mCurrentDocumentMapEntry = docMapEntry;
+#ifdef DEBUG_MUX
+ PRInt64 currentSegmentOffset;
+ Tell(&currentSegmentOffset);
+ trace_mux('r', "select %p (%p) offset %ld\n",
+ aURI, key.get(), (long) currentSegmentOffset);
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::EndMuxedDocument(nsISupports* aURI)
+{
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapReadEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mURIMap, key,
+ PL_DHASH_LOOKUP));
+
+ // If the URI isn't in the map, return NS_ERROR_NOT_AVAILABLE so the
+ // FastLoad service can try to end a select on its file updater.
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ // Drop our ref to the URI object that was passed to StartMuxedDocument,
+ // we no longer need it, and we do not want to extend its lifetime.
+ if (uriMapEntry->mDocMapEntry)
+ NS_RELEASE(uriMapEntry->mDocMapEntry->mURI);
+
+ // Shrink the table if half the entries are removed sentinels.
+ PRUint32 size = PL_DHASH_TABLE_SIZE(&mFooter.mURIMap);
+ if (mFooter.mURIMap.removedCount >= (size >> 2))
+ PL_DHashTableOperate(&mFooter.mURIMap, key, PL_DHASH_REMOVE);
+ else
+ PL_DHashTableRawRemove(&mFooter.mURIMap, uriMapEntry);
+
+ TRACE_MUX(('r', "end %p (%p)\n", aURI, key.get()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead)
+{
+ nsresult rv;
+
+ nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry;
+ if (entry) {
+ // Don't call our Seek wrapper, as it clears mCurrentDocumentMapEntry.
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ if (entry->mNeedToSeek) {
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mSaveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ entry->mNeedToSeek = PR_FALSE;
+ }
+
+ // Loop to handle empty segments, which may be generated by the
+ // writer, given Start A; Start B; Select A; Select B; write B data;
+ // multiplexing schedules, which do tend to occur given non-blocking
+ // i/o with LIFO scheduling. XXXbe investigate LIFO issues
+ while (entry->mBytesLeft == 0) {
+ // Check for unexpected end of multiplexed stream.
+ NS_ASSERTION(entry->mNextSegmentOffset != 0,
+ "document demuxed from FastLoad file more than once?");
+ if (entry->mNextSegmentOffset == 0)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mNextSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Clear mCurrentDocumentMapEntry temporarily to avoid recursion.
+ mCurrentDocumentMapEntry = nsnull;
+
+ rv = Read32(&entry->mNextSegmentOffset);
+ if (NS_SUCCEEDED(rv)) {
+ PRUint32 bytesLeft = 0;
+ rv = Read32(&bytesLeft);
+ entry->mBytesLeft = bytesLeft;
+ }
+
+ mCurrentDocumentMapEntry = entry;
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(entry->mBytesLeft >= 8, "demux segment length botch!");
+ entry->mBytesLeft -= 8;
+ }
+ }
+
+ rv = mInputStream->Read(aBuffer, aCount, aBytesRead);
+
+ if (NS_SUCCEEDED(rv) && entry) {
+ NS_ASSERTION(entry->mBytesLeft >= *aBytesRead, "demux Read underflow!");
+ entry->mBytesLeft -= *aBytesRead;
+
+#ifdef NS_DEBUG
+ // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0.
+ if (entry->mBytesLeft == 0)
+ entry->mSaveOffset = 0;
+#endif
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ PRUint32 aCount, PRUint32 *aResult)
+{
+ nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry;
+
+ NS_ASSERTION(!entry || (!entry->mNeedToSeek && entry->mBytesLeft != 0),
+ "ReadSegments called from above nsFastLoadFileReader layer?!");
+
+ nsresult rv = nsBinaryInputStream::ReadSegments(aWriter, aClosure, aCount,
+ aResult);
+ if (NS_SUCCEEDED(rv) && entry) {
+ NS_ASSERTION(entry->mBytesLeft >= *aResult,
+ "demux ReadSegments underflow!");
+ entry->mBytesLeft -= *aResult;
+
+#ifdef NS_DEBUG
+ // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0.
+ if (entry->mBytesLeft == 0)
+ entry->mSaveOffset = 0;
+#endif
+ }
+ return rv;
+}
+
+/**
+ * XXX tuneme
+ */
+#define MFL_CHECKSUM_BUFSIZE 8192
+
+NS_IMETHODIMP
+nsFastLoadFileReader::ComputeChecksum(PRUint32 *aResult)
+{
+ nsCOMPtr<nsIInputStream> stream = mInputStream;
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(stream));
+ PRInt64 saveOffset;
+ nsresult rv = seekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIStreamBufferAccess> bufferAccess(do_QueryInterface(stream));
+ if (bufferAccess) {
+ rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(stream));
+ if (NS_FAILED(rv))
+ return rv;
+
+ seekable = do_QueryInterface(stream);
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ char buf[MFL_CHECKSUM_BUFSIZE];
+ PRUint32 len, rem;
+
+ rem = offsetof(nsFastLoadHeader, mChecksum);
+ rv = stream->Read(buf, rem, &len);
+ if (NS_FAILED(rv))
+ return rv;
+ if (len != rem)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_CUR, 4);
+ if (NS_FAILED(rv))
+ return rv;
+ memset(buf + rem, 0, 4);
+ rem += 4;
+
+ PRUint32 checksum = 0;
+ while (NS_SUCCEEDED(rv = stream->Read(buf + rem, sizeof buf - rem, &len)) &&
+ len) {
+ len += rem;
+ rem = NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*, buf),
+ len,
+ PR_FALSE);
+ if (rem)
+ memcpy(buf, buf + len - rem, rem);
+ }
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (rem) {
+ NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*, buf),
+ rem,
+ PR_TRUE);
+ }
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = checksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::GetDependencies(nsISimpleEnumerator* *aDependencies)
+{
+ return NS_NewArrayEnumerator(aDependencies, mFooter.mDependencies);
+}
+
+nsresult
+nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter)
+{
+ nsresult rv;
+
+ rv = ReadFooterPrefix(aFooter);
+ if (NS_FAILED(rv))
+ return rv;
+
+ aFooter->mIDMap = new nsID[aFooter->mNumIDs];
+ if (!aFooter->mIDMap)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32 i, n;
+ for (i = 0, n = aFooter->mNumIDs; i < n; i++) {
+ rv = ReadSlowID(&aFooter->mIDMap[i]);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ aFooter->mObjectMap = new nsObjectMapEntry[aFooter->mNumSharpObjects];
+ if (!aFooter->mObjectMap)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (i = 0, n = aFooter->mNumSharpObjects; i < n; i++) {
+ nsObjectMapEntry* entry = &aFooter->mObjectMap[i];
+
+ rv = ReadSharpObjectInfo(entry);
+ if (NS_FAILED(rv))
+ return rv;
+
+ entry->mReadObject = nsnull;
+ entry->mSkipOffset = 0;
+ entry->mSaveStrongRefCnt = entry->mStrongRefCnt;
+ entry->mSaveWeakRefCnt = entry->mWeakRefCnt;
+ }
+
+ if (!PL_DHashTableInit(&aFooter->mDocumentMap, &strmap_DHashTableOps,
+ (void *)this, sizeof(nsDocumentMapReadEntry),
+ aFooter->mNumMuxedDocuments)) {
+ aFooter->mDocumentMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&aFooter->mURIMap, &objmap_DHashTableOps,
+ (void *)this, sizeof(nsURIMapReadEntry),
+ aFooter->mNumMuxedDocuments)) {
+ aFooter->mURIMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i = 0, n = aFooter->mNumMuxedDocuments; i < n; i++) {
+ nsFastLoadMuxedDocumentInfo info;
+
+ rv = ReadMuxedDocumentInfo(&info);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsDocumentMapReadEntry* entry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*,
+ PL_DHashTableOperate(&aFooter->mDocumentMap,
+ info.mURISpec,
+ PL_DHASH_ADD));
+ if (!entry) {
+ nsMemory::Free((void*) info.mURISpec);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ASSERTION(!entry->mString, "duplicate URISpec in MuxedDocumentMap");
+ entry->mString = info.mURISpec;
+ entry->mURI = nsnull;
+ entry->mInitialSegmentOffset = info.mInitialSegmentOffset;
+ entry->mNextSegmentOffset = info.mInitialSegmentOffset;
+ entry->mBytesLeft = 0;
+ entry->mNeedToSeek = PR_FALSE;
+ entry->mSaveOffset = 0;
+ }
+
+ nsCOMPtr<nsISupportsArray> readDeps;
+ rv = NS_NewISupportsArray(getter_AddRefs(readDeps));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString filename;
+ for (i = 0, n = aFooter->mNumDependencies; i < n; i++) {
+ rv = ReadCString(filename);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fastLoadMtime;
+ rv = Read64(NS_REINTERPRET_CAST(PRUint64*, &fastLoadMtime));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsILocalFile> file;
+ rv = NS_NewNativeLocalFile(filename, PR_TRUE, getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 currentMtime;
+ rv = file->GetLastModifiedTime(&currentMtime);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (LL_NE(fastLoadMtime, currentMtime)) {
+#ifdef DEBUG
+ nsCAutoString path;
+ file->GetNativePath(path);
+ printf("%s mtime changed, invalidating FastLoad file\n",
+ path.get());
+#endif
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = readDeps->AppendElement(file);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ aFooter->mDependencies = readDeps;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix)
+{
+ nsresult rv;
+
+ rv = Read32(&aFooterPrefix->mNumIDs);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aFooterPrefix->mNumSharpObjects);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aFooterPrefix->mNumMuxedDocuments);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aFooterPrefix->mNumDependencies);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadSlowID(nsID *aID)
+{
+ nsresult rv;
+
+ rv = Read32(&aID->m0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read16(&aID->m1);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read16(&aID->m2);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 bytesRead;
+ rv = Read(NS_REINTERPRET_CAST(char*, aID->m3), sizeof aID->m3, &bytesRead);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesRead != sizeof aID->m3)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadFastID(NSFastLoadID *aID)
+{
+ nsresult rv = Read32(aID);
+ if (NS_SUCCEEDED(rv))
+ *aID ^= MFL_ID_XOR_KEY;
+ return rv;
+}
+
+nsresult
+nsFastLoadFileReader::ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo)
+{
+ nsresult rv;
+
+ rv = Read32(&aInfo->mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(aInfo->mCIDOffset != 0,
+ "fastload reader: mCIDOffset cannot be zero!");
+
+ rv = Read16(&aInfo->mStrongRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read16(&aInfo->mWeakRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo)
+{
+ nsresult rv;
+
+ nsCAutoString spec;
+ rv = ReadCString(spec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aInfo->mInitialSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ aInfo->mURISpec = ToNewCString(spec);
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::Open()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+
+ // Don't bother buffering the header, as we immediately seek to EOF.
+ nsCOMPtr<nsIStreamBufferAccess>
+ bufferAccess(do_QueryInterface(mInputStream));
+ if (bufferAccess)
+ bufferAccess->DisableBuffering();
+
+ rv = ReadHeader(&mHeader);
+
+ if (bufferAccess)
+ bufferAccess->EnableBuffering();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (mHeader.mVersion != MFL_FILE_VERSION)
+ return NS_ERROR_UNEXPECTED;
+ if (mHeader.mFooterOffset == 0)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_END, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fileSize;
+ rv = seekable->Tell(&fileSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsInt64 fileSize64 = fileSize;
+ const nsInt64 maxUint32 = PR_UINT32_MAX;
+ NS_ASSERTION(fileSize64 <= maxUint32, "fileSize must fit in 32 bits");
+ if ((PRUint32) fileSize64 != mHeader.mFileSize)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ PRInt32(mHeader.mFooterOffset));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = ReadFooter(&mFooter);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ sizeof(nsFastLoadHeader));
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Close()
+{
+ // Give up our strong "keepalive" references, in case not all objects that
+ // were deserialized were fully re-connected.
+ //
+ // This happens for sure when an nsFastLoadFileUpdater is created and wraps
+ // an nsFastLoadFileReader whose data was already deserialized by an earlier
+ // FastLoad episode. The reader is useful in the second such episode during
+ // a session not so much for reading objects as for its footer information,
+ // which primes the updater's tables so that after the update completes, the
+ // FastLoad file has a superset footer.
+
+ for (PRUint32 i = 0, n = mFooter.mNumSharpObjects; i < n; i++) {
+ nsObjectMapEntry* entry = &mFooter.mObjectMap[i];
+ entry->mReadObject = nsnull;
+ }
+
+ return mInputStream->Close();
+}
+
+nsresult
+nsFastLoadFileReader::DeserializeObject(nsISupports* *aObject)
+{
+ nsresult rv;
+ NSFastLoadID fastCID;
+
+ rv = ReadFastID(&fastCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const nsID& slowCID = mFooter.GetID(fastCID);
+ nsCOMPtr<nsISupports> object(do_CreateInstance(slowCID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsISerializable> serializable(do_QueryInterface(object));
+ if (!serializable)
+ return NS_ERROR_FAILURE;
+
+ rv = serializable->Read(this);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aObject = object;
+ NS_ADDREF(*aObject);
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject)
+{
+ nsresult rv;
+ NSFastLoadOID oid;
+
+ rv = Read32(&oid);
+ if (NS_FAILED(rv))
+ return rv;
+ oid ^= MFL_OID_XOR_KEY;
+
+ nsCOMPtr<nsISupports> object;
+
+ if (oid == MFL_DULL_OBJECT_OID) {
+ // A very dull object, defined at point of single (strong) reference.
+ NS_ASSERTION(aIsStrongRef, "dull object read via weak ref!");
+
+ rv = DeserializeObject(getter_AddRefs(object));
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ NS_ASSERTION((oid & MFL_WEAK_REF_TAG) ==
+ (aIsStrongRef ? 0 : MFL_WEAK_REF_TAG),
+ "strong vs. weak ref deserialization mismatch!");
+
+ nsObjectMapEntry* entry = &mFooter.GetSharpObjectEntry(oid);
+
+ // Check whether we've already deserialized the object for this OID.
+ object = entry->mReadObject;
+ if (!object) {
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ PRInt64 saveOffset;
+ nsDocumentMapReadEntry* saveDocMapEntry = nsnull;
+
+ rv = seekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 saveOffset32 = saveOffset;
+ if (entry->mCIDOffset != saveOffset32) {
+ // We skipped deserialization of this object from its position
+ // earlier in the input stream, presumably due to the reference
+ // there being an nsFastLoadPtr, or (more likely) because the
+ // object was muxed in another document, and deserialization
+ // order does not match serialization order. So we must seek
+ // back and read it now.
+ NS_ASSERTION(entry->mCIDOffset < saveOffset32,
+ "out of order object?!");
+
+ // Ape our Seek wrapper by clearing mCurrentDocumentMapEntry.
+ // This allows for a skipped object to be referenced from two
+ // or more multiplexed documents in the FastLoad file.
+ saveDocMapEntry = mCurrentDocumentMapEntry;
+ mCurrentDocumentMapEntry = nsnull;
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ rv = DeserializeObject(getter_AddRefs(object));
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (entry->mCIDOffset != saveOffset32) {
+ // Save the "skip offset" in case we need to skip this object
+ // definition when reading forward, later on.
+ rv = seekable->Tell(&entry->mSkipOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Restore stream offset and mCurrentDocumentMapEntry in case
+ // we're still reading forward through a part of the multiplex
+ // to get object definitions eagerly.
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ mCurrentDocumentMapEntry = saveDocMapEntry;
+ }
+
+ // Save object until all refs have been deserialized.
+ entry->mReadObject = object;
+ } else {
+ // What if we are at a definition that's already been read? This
+ // case arises when a sharp object's def is serialized before its
+ // refs, while a non-defining ref is deserialized before the def.
+ // We must skip over the object definition.
+ if (oid & MFL_OBJECT_DEF_TAG) {
+ NS_ASSERTION(entry->mSkipOffset != 0, "impossible! see above");
+ nsCOMPtr<nsISeekableStream>
+ seekable(do_QueryInterface(mInputStream));
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mSkipOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ if (aIsStrongRef) {
+ NS_ASSERTION(entry->mStrongRefCnt != 0,
+ "mStrongRefCnt underflow!");
+ --entry->mStrongRefCnt;
+ } else {
+ NS_ASSERTION(MFL_GET_WEAK_REFCNT(entry) != 0,
+ "mWeakRefCnt underflow!");
+ MFL_DROP_WEAK_REFCNT(entry);
+ }
+
+ if (entry->mStrongRefCnt == 0 && MFL_GET_WEAK_REFCNT(entry) == 0)
+ entry->mReadObject = nsnull;
+ }
+
+ if (oid & MFL_QUERY_INTERFACE_TAG) {
+ NSFastLoadID iid;
+ rv = ReadFastID(&iid);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = object->QueryInterface(mFooter.GetID(iid),
+ NS_REINTERPRET_CAST(void**, aObject));
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ *aObject = object;
+ NS_ADDREF(*aObject);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::ReadID(nsID *aResult)
+{
+ nsresult rv;
+ NSFastLoadID fastID;
+
+ rv = ReadFastID(&fastID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = mFooter.GetID(fastID);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ mCurrentDocumentMapEntry = nsnull;
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ return seekable->Seek(aWhence, aOffset);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Tell(PRInt64 *aResult)
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ return seekable->Tell(aResult);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::SetEOF()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ return seekable->SetEOF();
+}
+
+NS_COM nsresult
+NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult,
+ nsIInputStream* aSrcStream)
+{
+ nsFastLoadFileReader* reader = new nsFastLoadFileReader(aSrcStream);
+ if (!reader)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Stabilize reader's refcnt.
+ nsCOMPtr<nsIObjectInputStream> stream(reader);
+
+ nsresult rv = reader->Open();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+// -------------------------- nsFastLoadFileWriter --------------------------
+
+NS_IMPL_ISUPPORTS_INHERITED4(nsFastLoadFileWriter,
+ nsBinaryOutputStream,
+ nsIObjectOutputStream,
+ nsIFastLoadFileControl,
+ nsIFastLoadWriteControl,
+ nsISeekableStream)
+
+MOZ_DECL_CTOR_COUNTER(nsFastLoadFileWriter)
+
+struct nsIDMapEntry : public PLDHashEntryHdr {
+ NSFastLoadID mFastID; // 1 + nsFastLoadFooter::mIDMap index
+ nsID mSlowID; // key, used by PLDHashTableOps below
+};
+
+PR_STATIC_CALLBACK(const void *)
+idmap_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsIDMapEntry* entry = NS_STATIC_CAST(nsIDMapEntry*, aHdr);
+
+ return &entry->mSlowID;
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+idmap_HashKey(PLDHashTable *aTable, const void *aKey)
+{
+ const nsID *idp = NS_REINTERPRET_CAST(const nsID*, aKey);
+
+ return idp->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+idmap_MatchEntry(PLDHashTable *aTable,
+ const PLDHashEntryHdr *aHdr,
+ const void *aKey)
+{
+ const nsIDMapEntry* entry = NS_STATIC_CAST(const nsIDMapEntry*, aHdr);
+ const nsID *idp = NS_REINTERPRET_CAST(const nsID*, aKey);
+
+ return memcmp(&entry->mSlowID, idp, sizeof(nsID)) == 0;
+}
+
+static const PLDHashTableOps idmap_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ idmap_GetKey,
+ idmap_HashKey,
+ idmap_MatchEntry,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+nsresult
+nsFastLoadFileWriter::MapID(const nsID& aSlowID, NSFastLoadID *aResult)
+{
+ nsIDMapEntry* entry =
+ NS_STATIC_CAST(nsIDMapEntry*,
+ PL_DHashTableOperate(&mIDMap, &aSlowID, PL_DHASH_ADD));
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (entry->mFastID == 0) {
+ entry->mFastID = mIDMap.entryCount;
+ entry->mSlowID = aSlowID;
+ }
+
+ *aResult = entry->mFastID;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteHeader(nsFastLoadHeader *aHeader)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ rv = Write(aHeader->mMagic, MFL_FILE_MAGIC_SIZE, &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesWritten != MFL_FILE_MAGIC_SIZE)
+ return NS_ERROR_FAILURE;
+
+ rv = Write32(aHeader->mChecksum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aHeader->mVersion);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aHeader->mFooterOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aHeader->mFileSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+// nsIFastLoadFileControl methods:
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::GetChecksum(PRUint32 *aChecksum)
+{
+ if (mHeader.mChecksum == 0)
+ return NS_ERROR_NOT_AVAILABLE;
+ *aChecksum = mHeader.mChecksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::SetChecksum(PRUint32 aChecksum)
+{
+ mHeader.mChecksum = aChecksum;
+ return NS_OK;
+}
+
+struct nsDocumentMapWriteEntry : public nsDocumentMapEntry {
+ PRUint32 mCurrentSegmentOffset; // last written segment's offset
+};
+
+// Fast mapping from URI object pointer back to spec-indexed document info.
+// We also may need the slow mapping from mURISpec to nsDocumentMapWriteEntry,
+// because the writer's mDocumentMap double hash table may grow "behind the
+// back of" each mURIMap entry's mDocMapEntry member.
+struct nsURIMapWriteEntry : public nsObjectMapEntry {
+ nsDocumentMapWriteEntry* mDocMapEntry;
+ PRUint32 mGeneration;
+ const char* mURISpec;
+};
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::HasMuxedDocument(const char* aURISpec, PRBool *aResult)
+{
+ nsDocumentMapWriteEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap, aURISpec,
+ PL_DHASH_LOOKUP));
+
+ *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::StartMuxedDocument(nsISupports* aURI,
+ const char* aURISpec)
+{
+ // Save mDocumentMap table generation and mCurrentDocumentMapEntry key in
+ // case the hash table grows during the PL_DHASH_ADD operation.
+ PRUint32 saveGeneration = mDocumentMap.generation;
+ const char* saveURISpec = mCurrentDocumentMapEntry
+ ? mCurrentDocumentMapEntry->mString
+ : nsnull;
+
+ nsDocumentMapWriteEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap, aURISpec,
+ PL_DHASH_ADD));
+ if (!docMapEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // If the generation number changed, refresh mCurrentDocumentMapEntry.
+ if (mCurrentDocumentMapEntry && mDocumentMap.generation != saveGeneration) {
+ mCurrentDocumentMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap, saveURISpec,
+ PL_DHASH_LOOKUP));
+ NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(mCurrentDocumentMapEntry),
+ "mCurrentDocumentMapEntry lost during table growth?!");
+
+ // Refresh saveGeneration for use below when initializing uriMapEntry.
+ saveGeneration = mDocumentMap.generation;
+ }
+
+ NS_ASSERTION(docMapEntry->mString == nsnull,
+ "redundant multiplexed document?");
+ if (docMapEntry->mString)
+ return NS_ERROR_UNEXPECTED;
+
+ void* spec = nsMemory::Clone(aURISpec, strlen(aURISpec) + 1);
+ if (!spec)
+ return NS_ERROR_OUT_OF_MEMORY;
+ docMapEntry->mString = NS_REINTERPRET_CAST(const char*, spec);
+ docMapEntry->mURI = aURI;
+ NS_ADDREF(docMapEntry->mURI);
+
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapWriteEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapWriteEntry*,
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_ADD));
+ if (!uriMapEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(uriMapEntry->mDocMapEntry == nsnull,
+ "URI mapped to two different specs?");
+ if (uriMapEntry->mDocMapEntry)
+ return NS_ERROR_UNEXPECTED;
+
+ uriMapEntry->mObject = key;
+ NS_ADDREF(uriMapEntry->mObject);
+ uriMapEntry->mDocMapEntry = docMapEntry;
+ uriMapEntry->mGeneration = saveGeneration;
+ uriMapEntry->mURISpec = NS_REINTERPRET_CAST(const char*, spec);
+ TRACE_MUX(('w', "start %p (%p) %s\n", aURI, key.get(), aURISpec));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI,
+ nsISupports** aResult)
+{
+ // Avoid repeatedly QI'ing to nsISeekableStream as we tell and seek.
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+
+ // Capture the current file offset (XXXbe maintain our own via Write?)
+ nsresult rv;
+ PRInt64 currentSegmentOffset;
+ rv = seekable->Tell(&currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 currentSegmentOffset32 = currentSegmentOffset;
+ // Look for an existing entry keyed by aURI, added by StartMuxedDocument.
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapWriteEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapWriteEntry*,
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP));
+ NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(uriMapEntry),
+ "SelectMuxedDocument without prior StartMuxedDocument?");
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
+ return NS_ERROR_UNEXPECTED;
+
+ // Beware that uriMapEntry->mDocMapEntry may be stale, if an mDocumentMap
+ // addition caused that table to grow. We save the mDocumentMap generation
+ // in each uriMapEntry and compare it to the current generation, rehashing
+ // uriMapEntry->mURISpec if necessary.
+
+ nsDocumentMapWriteEntry* docMapEntry = uriMapEntry->mDocMapEntry;
+ if (uriMapEntry->mGeneration != mDocumentMap.generation) {
+ docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap,
+ uriMapEntry->mURISpec,
+ PL_DHASH_LOOKUP));
+ NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(docMapEntry), "lost mDocMapEntry!?");
+ uriMapEntry->mDocMapEntry = docMapEntry;
+ uriMapEntry->mGeneration = mDocumentMap.generation;
+ }
+ docMapEntry = uriMapEntry->mDocMapEntry;
+
+ // If there is a muxed document segment open, close it now by setting its
+ // length, stored in the second PRUint32 of the segment.
+ nsDocumentMapWriteEntry* prevDocMapEntry = mCurrentDocumentMapEntry;
+ if (prevDocMapEntry) {
+ if (prevDocMapEntry == docMapEntry) {
+ TRACE_MUX(('w', "select prev %s same as current!\n",
+ prevDocMapEntry->mString));
+ *aResult = docMapEntry->mURI;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+ }
+
+ PRUint32 prevSegmentOffset = prevDocMapEntry->mCurrentSegmentOffset;
+ TRACE_MUX(('w', "select prev %s offset %lu\n",
+ prevDocMapEntry->mString, prevSegmentOffset));
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ prevSegmentOffset + 4);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // The length counts all bytes in the segment, including the header
+ // that contains [nextSegmentOffset, length].
+ rv = Write32(currentSegmentOffset32 - prevSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Seek back to the current offset only if we are not going to seek
+ // back to *this* entry's last "current" segment offset and write its
+ // next segment offset at the first PRUint32 of the segment.
+ if (!docMapEntry->mInitialSegmentOffset) {
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ // If this entry was newly added, set its key and initial segment offset.
+ // Otherwise, seek back to write the next segment offset of the previous
+ // segment for this document in the multiplex.
+ if (!docMapEntry->mInitialSegmentOffset) {
+ docMapEntry->mInitialSegmentOffset = currentSegmentOffset32;
+ } else {
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ docMapEntry->mCurrentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(currentSegmentOffset32);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Update this document's current segment offset so we can later fix its
+ // next segment offset (unless it is last, in which case we leave the zero
+ // placeholder as a terminator).
+ docMapEntry->mCurrentSegmentOffset = currentSegmentOffset32;
+
+ rv = Write32(0); // nextSegmentOffset placeholder
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(0); // length placeholder
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull;
+ NS_IF_ADDREF(*aResult);
+
+ mCurrentDocumentMapEntry = docMapEntry;
+ TRACE_MUX(('w', "select %p (%p) offset %lu\n",
+ aURI, key.get(), currentSegmentOffset));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::EndMuxedDocument(nsISupports* aURI)
+{
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapWriteEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapWriteEntry*,
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP));
+
+ // If the URI isn't in the map, nsFastLoadFileWriter::StartMuxedDocument
+ // must have been called with a redundant URI, *and* its caller must have
+ // ignored the NS_ERROR_UNEXPECTED it returned in that case.
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry)) {
+ TRACE_MUX(('w', "bad end %p (%p)\n", aURI, key.get()));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Drop our ref to the URI object that was passed to StartMuxedDocument,
+ // we no longer need it, and we do not want to extend its lifetime.
+ if (uriMapEntry->mDocMapEntry)
+ NS_RELEASE(uriMapEntry->mDocMapEntry->mURI);
+
+ // Shrink the table if half the entries are removed sentinels.
+ PRUint32 size = PL_DHASH_TABLE_SIZE(&mURIMap);
+ if (mURIMap.removedCount >= (size >> 2))
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_REMOVE);
+ else
+ PL_DHashTableRawRemove(&mURIMap, uriMapEntry);
+
+ TRACE_MUX(('w', "end %p (%p)\n", aURI, key.get()));
+ return NS_OK;
+}
+
+struct nsDependencyMapEntry : public nsStringMapEntry {
+ PRInt64 mLastModified;
+};
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::AddDependency(nsIFile* aFile)
+{
+ nsCAutoString path;
+ nsresult rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsDependencyMapEntry* entry =
+ NS_STATIC_CAST(nsDependencyMapEntry*,
+ PL_DHashTableOperate(&mDependencyMap, path.get(),
+ PL_DHASH_ADD));
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!entry->mString) {
+ const char *tmp = ToNewCString(path);
+ if (!tmp)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry->mString = tmp;
+
+ // If we can't get the last modified time from aFile, assume it does
+ // not exist, or is otherwise inaccessible to us (due to permissions),
+ // remove the dependency, and suppress the failure.
+ //
+ // Otherwise, we would end up aborting the fastload process due to a
+ // missing .js or .xul or other file on every startup.
+
+ rv = aFile->GetLastModifiedTime(&entry->mLastModified);
+ if (NS_FAILED(rv)) {
+ PL_DHashTableOperate(&mDependencyMap, path.get(), PL_DHASH_REMOVE);
+ rv = NS_OK;
+ }
+ }
+ return rv;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix)
+{
+ nsresult rv;
+
+ rv = Write32(aFooterPrefix.mNumIDs);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aFooterPrefix.mNumSharpObjects);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aFooterPrefix.mNumMuxedDocuments);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aFooterPrefix.mNumDependencies);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteSlowID(const nsID& aID)
+{
+ nsresult rv;
+
+ rv = Write32(aID.m0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aID.m1);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aID.m2);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 bytesWritten;
+ rv = Write(NS_REINTERPRET_CAST(const char*, aID.m3), sizeof aID.m3,
+ &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesWritten != sizeof aID.m3)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteFastID(NSFastLoadID aID)
+{
+ return Write32(aID ^ MFL_ID_XOR_KEY);
+}
+
+nsresult
+nsFastLoadFileWriter::WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo)
+{
+ nsresult rv;
+
+ NS_ASSERTION(aInfo.mCIDOffset != 0,
+ "fastload writer: mCIDOffset cannot be zero!");
+
+ rv = Write32(aInfo.mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aInfo.mStrongRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aInfo.mWeakRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo)
+{
+ nsresult rv;
+
+ rv = WriteStringZ(aInfo.mURISpec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aInfo.mInitialSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::IDMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsIDMapEntry* entry = NS_STATIC_CAST(nsIDMapEntry*, aHdr);
+ PRUint32 index = entry->mFastID - 1;
+ nsID* vector = NS_REINTERPRET_CAST(nsID*, aData);
+
+ NS_ASSERTION(index < aTable->entryCount, "bad nsIDMap index!");
+ vector[index] = entry->mSlowID;
+ return PL_DHASH_NEXT;
+}
+
+struct nsSharpObjectMapEntry : public nsObjectMapEntry {
+ NSFastLoadOID mOID;
+ nsFastLoadSharpObjectInfo mInfo;
+};
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::ObjectMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsSharpObjectMapEntry* entry = NS_STATIC_CAST(nsSharpObjectMapEntry*, aHdr);
+ PRUint32 index = MFL_OID_TO_SHARP_INDEX(entry->mOID);
+ nsFastLoadSharpObjectInfo* vector =
+ NS_REINTERPRET_CAST(nsFastLoadSharpObjectInfo*, aData);
+
+ NS_ASSERTION(index < aTable->entryCount, "bad nsObjectMap index!");
+ vector[index] = entry->mInfo;
+
+ NS_ASSERTION(entry->mInfo.mStrongRefCnt, "no strong ref in serialization!");
+
+ // Ignore tagged object ids stored as object pointer keys (the updater
+ // code does this).
+ if ((NS_PTR_TO_INT32(entry->mObject) & MFL_OBJECT_DEF_TAG) == 0)
+ NS_RELEASE(entry->mObject);
+
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::DocumentMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFastLoadFileWriter* writer =
+ NS_REINTERPRET_CAST(nsFastLoadFileWriter*, aTable->data);
+ nsDocumentMapWriteEntry* entry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*, aHdr);
+ nsresult* rvp = NS_REINTERPRET_CAST(nsresult*, aData);
+
+ nsFastLoadMuxedDocumentInfo info;
+ info.mURISpec = entry->mString;
+ info.mInitialSegmentOffset = entry->mInitialSegmentOffset;
+ *rvp = writer->WriteMuxedDocumentInfo(info);
+
+ return NS_FAILED(*rvp) ? PL_DHASH_STOP : PL_DHASH_NEXT;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::DependencyMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFastLoadFileWriter* writer =
+ NS_REINTERPRET_CAST(nsFastLoadFileWriter*, aTable->data);
+ nsDependencyMapEntry* entry = NS_STATIC_CAST(nsDependencyMapEntry*, aHdr);
+ nsresult* rvp = NS_REINTERPRET_CAST(nsresult*, aData);
+
+ *rvp = writer->WriteStringZ(entry->mString);
+ if (NS_SUCCEEDED(*rvp))
+ *rvp = writer->Write64(entry->mLastModified);
+
+ return NS_FAILED(*rvp) ? PL_DHASH_STOP :PL_DHASH_NEXT;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteFooter()
+{
+ nsresult rv;
+ PRUint32 i, count;
+
+ nsFastLoadFooterPrefix footerPrefix;
+ footerPrefix.mNumIDs = mIDMap.entryCount;
+ footerPrefix.mNumSharpObjects = mObjectMap.entryCount;
+ footerPrefix.mNumMuxedDocuments = mDocumentMap.entryCount;
+ footerPrefix.mNumDependencies = mDependencyMap.entryCount;
+
+ rv = WriteFooterPrefix(footerPrefix);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Enumerate mIDMap into a vector indexed by mFastID and write it.
+ nsID* idvec = new nsID[footerPrefix.mNumIDs];
+ if (!idvec)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ count = PL_DHashTableEnumerate(&mIDMap, IDMapEnumerate, idvec);
+ NS_ASSERTION(count == footerPrefix.mNumIDs, "bad mIDMap enumeration!");
+ for (i = 0; i < count; i++) {
+ rv = WriteSlowID(idvec[i]);
+ if (NS_FAILED(rv)) break;
+ }
+
+ delete[] idvec;
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Enumerate mObjectMap into a vector indexed by mOID and write it.
+ nsFastLoadSharpObjectInfo* objvec =
+ new nsFastLoadSharpObjectInfo[footerPrefix.mNumSharpObjects];
+ if (!objvec)
+ return NS_ERROR_OUT_OF_MEMORY;
+#ifdef NS_DEBUG
+ memset(objvec, 0, footerPrefix.mNumSharpObjects *
+ sizeof(nsFastLoadSharpObjectInfo));
+#endif
+
+ count = PL_DHashTableEnumerate(&mObjectMap, ObjectMapEnumerate, objvec);
+ NS_ASSERTION(count == footerPrefix.mNumSharpObjects,
+ "bad mObjectMap enumeration!");
+ for (i = 0; i < count; i++) {
+ rv = WriteSharpObjectInfo(objvec[i]);
+ if (NS_FAILED(rv)) break;
+ }
+
+ delete[] objvec;
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Enumerate mDocumentMap, writing nsFastLoadMuxedDocumentInfo records
+ count = PL_DHashTableEnumerate(&mDocumentMap, DocumentMapEnumerate, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(count == footerPrefix.mNumMuxedDocuments,
+ "bad mDocumentMap enumeration!");
+
+ // Write out make-like file dependencies.
+ count = PL_DHashTableEnumerate(&mDependencyMap, DependencyMapEnumerate, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::Init()
+{
+ if (!PL_DHashTableInit(&mIDMap, &idmap_DHashTableOps, (void *)this,
+ sizeof(nsIDMapEntry), PL_DHASH_MIN_SIZE)) {
+ mIDMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mObjectMap, &objmap_DHashTableOps, (void *)this,
+ sizeof(nsSharpObjectMapEntry), PL_DHASH_MIN_SIZE)) {
+ mObjectMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mDocumentMap, &strmap_DHashTableOps, (void *)this,
+ sizeof(nsDocumentMapWriteEntry),
+ PL_DHASH_MIN_SIZE)) {
+ mDocumentMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mURIMap, &objmap_DHashTableOps, (void *)this,
+ sizeof(nsURIMapWriteEntry), PL_DHASH_MIN_SIZE)) {
+ mURIMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mDependencyMap, &strmap_DHashTableOps, (void *)this,
+ sizeof(nsDependencyMapEntry), PL_DHASH_MIN_SIZE)) {
+ mDependencyMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::Open()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ sizeof(nsFastLoadHeader));
+ if (NS_FAILED(rv))
+ return rv;
+
+ return Init();
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::Close()
+{
+ nsresult rv;
+
+ memcpy(mHeader.mMagic, magic, MFL_FILE_MAGIC_SIZE);
+ mHeader.mChecksum = 0;
+ mHeader.mVersion = MFL_FILE_VERSION;
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+
+ PRInt64 footerOffset;
+ rv = seekable->Tell(&footerOffset);
+
+ LL_L2UI(mHeader.mFooterOffset, footerOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // If there is a muxed document segment open, close it now by setting its
+ // length, stored in the second PRUint32 of the segment.
+ if (mCurrentDocumentMapEntry) {
+ PRUint32 currentSegmentOffset =
+ mCurrentDocumentMapEntry->mCurrentSegmentOffset;
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ currentSegmentOffset + 4);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(mHeader.mFooterOffset - currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Seek back to the current offset to write the footer.
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ mHeader.mFooterOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mCurrentDocumentMapEntry = nsnull;
+ }
+
+ rv = WriteFooter();
+ if (NS_FAILED(rv))
+ return rv;
+ PRInt64 fileSize;
+ rv = seekable->Tell(&fileSize);
+ LL_L2UI(mHeader.mFileSize, fileSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = WriteHeader(&mHeader);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Now compute the checksum, using mFileIO to get an input stream on the
+ // underlying FastLoad file.
+ if (mFileIO) {
+ // Get the unbuffered output stream, which flushes the buffered header
+ // so we can read and checksum it along with the rest of the file, and
+ // which allows us to write the checksum directly.
+ nsCOMPtr<nsIStreamBufferAccess>
+ bufferAccess(do_QueryInterface(mOutputStream));
+ nsCOMPtr<nsIOutputStream> output;
+ rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(output));
+ if (NS_FAILED(rv) || !output)
+ return NS_ERROR_UNEXPECTED;
+
+ nsCOMPtr<nsIInputStream> input;
+ rv = mFileIO->GetInputStream(getter_AddRefs(input));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Get the unbuffered input stream, to avoid copying overhead and to
+ // keep our view of the file coherent with the writer -- we don't want
+ // to hit a stale buffer in the reader's underlying stream.
+ bufferAccess = do_QueryInterface(input);
+ rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(input));
+ if (NS_FAILED(rv) || !input)
+ return NS_ERROR_UNEXPECTED;
+
+ // Seek the input stream to offset 0, in case it's a reader who has
+ // already been used to consume some of the FastLoad file.
+ seekable = do_QueryInterface(input);
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ char buf[MFL_CHECKSUM_BUFSIZE];
+ PRUint32 len, rem = 0;
+ PRUint32 checksum = 0;
+
+ // Ok, we're finally ready to checksum the FastLoad file we just wrote!
+ while (NS_SUCCEEDED(rv =
+ input->Read(buf + rem, sizeof buf - rem, &len)) &&
+ len) {
+ len += rem;
+ rem = NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*,
+ buf),
+ len,
+ PR_FALSE);
+ if (rem)
+ memcpy(buf, buf + len - rem, rem);
+ }
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (rem) {
+ NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*, buf),
+ rem,
+ PR_TRUE);
+ }
+
+ // Store the checksum in the FastLoad file header and remember it via
+ // mHeader.mChecksum, for GetChecksum.
+ seekable = do_QueryInterface(output);
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ offsetof(nsFastLoadHeader, mChecksum));
+ if (NS_FAILED(rv))
+ return rv;
+
+ mHeader.mChecksum = checksum;
+ checksum = NS_SWAP32(checksum);
+ PRUint32 bytesWritten;
+ rv = output->Write(NS_REINTERPRET_CAST(char*, &checksum),
+ sizeof checksum,
+ &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+ if (bytesWritten != sizeof checksum)
+ return NS_ERROR_FAILURE;
+ }
+
+ return mOutputStream->Close();
+}
+
+// Psuedo-tag used as flag between WriteSingleRefObject and WriteObjectCommon.
+#define MFL_SINGLE_REF_PSEUDO_TAG PR_BIT(MFL_OBJECT_TAG_BITS)
+
+nsresult
+nsFastLoadFileWriter::WriteObjectCommon(nsISupports* aObject,
+ PRBool aIsStrongRef,
+ PRUint32 aTags)
+{
+ nsrefcnt rc;
+ nsresult rv;
+
+ NS_ASSERTION((NS_PTR_TO_INT32(aObject) & MFL_OBJECT_DEF_TAG) == 0,
+ "odd nsISupports*, oh no!");
+
+ // Here be manual refcounting dragons!
+ rc = aObject->AddRef();
+ NS_ASSERTION(rc != 0, "bad refcnt when writing aObject!");
+
+ NSFastLoadOID oid;
+ nsCOMPtr<nsIClassInfo> classInfo;
+
+ if (rc == 2 && (aTags & MFL_SINGLE_REF_PSEUDO_TAG)) {
+ // Dull object: only one strong ref and no weak refs in serialization.
+ // Conservative: we don't trust the caller if there are more than two
+ // refs (one from the AddRef above, one from the data structure that's
+ // being serialized).
+ oid = MFL_DULL_OBJECT_OID;
+ aObject->Release();
+ } else {
+ // Object is presumed to be multiply connected through some combo of
+ // strong and weak refs. Hold onto it via mObjectMap.
+ nsSharpObjectMapEntry* entry =
+ NS_STATIC_CAST(nsSharpObjectMapEntry*,
+ PL_DHashTableOperate(&mObjectMap, aObject,
+ PL_DHASH_ADD));
+ if (!entry) {
+ aObject->Release();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!entry->mObject) {
+ // First time we've seen this object address: add it to mObjectMap
+ // and serialize the object at the current stream offset.
+ PRInt64 thisOffset;
+ rv = Tell(&thisOffset);
+ if (NS_FAILED(rv)) {
+ aObject->Release();
+ return rv;
+ }
+
+ // NB: aObject was already held, and mObject is a raw nsISupports*.
+ entry->mObject = aObject;
+
+ oid = (mObjectMap.entryCount << MFL_OBJECT_TAG_BITS);
+ entry->mOID = oid;
+
+ // NB: the (32-bit, fast) CID and object data follow the OID.
+ entry->mInfo.mCIDOffset = thisOffset + sizeof(oid);
+ entry->mInfo.mStrongRefCnt = aIsStrongRef ? 1 : 0;
+ entry->mInfo.mWeakRefCnt = aIsStrongRef ? 0 : 1;
+
+ // Record in oid the fact that we're defining this object in the
+ // stream, and get the object's class info here, so we can take
+ // note of singletons in order to avoid reserializing them when
+ // updating after reading.
+ oid |= MFL_OBJECT_DEF_TAG;
+ classInfo = do_QueryInterface(aObject);
+ if (!classInfo)
+ return NS_ERROR_FAILURE;
+
+ PRUint32 flags;
+ if (NS_SUCCEEDED(classInfo->GetFlags(&flags)) &&
+ (flags & nsIClassInfo::SINGLETON)) {
+ MFL_SET_SINGLETON_FLAG(&entry->mInfo);
+ }
+ } else {
+ // Already serialized, recover oid and update the desired refcnt.
+ oid = entry->mOID;
+ if (aIsStrongRef) {
+ ++entry->mInfo.mStrongRefCnt;
+ NS_ASSERTION(entry->mInfo.mStrongRefCnt != 0,
+ "mStrongRefCnt overflow");
+ } else {
+ MFL_BUMP_WEAK_REFCNT(&entry->mInfo);
+ NS_ASSERTION(MFL_GET_WEAK_REFCNT(&entry->mInfo) != 0,
+ "mWeakRefCnt overflow");
+ }
+
+ aObject->Release();
+ }
+ }
+
+ if (!aIsStrongRef)
+ oid |= MFL_WEAK_REF_TAG;
+ oid |= (aTags & MFL_QUERY_INTERFACE_TAG);
+
+ rv = Write32(oid ^ MFL_OID_XOR_KEY);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (oid & MFL_OBJECT_DEF_TAG) {
+ nsCOMPtr<nsISerializable> serializable(do_QueryInterface(aObject));
+ if (!serializable)
+ return NS_ERROR_FAILURE;
+
+ nsCID slowCID;
+ rv = classInfo->GetClassIDNoAlloc(&slowCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NSFastLoadID fastCID;
+ rv = MapID(slowCID, &fastCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = WriteFastID(fastCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = serializable->Write(this);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteObject(nsISupports* aObject, PRBool aIsStrongRef)
+{
+#ifdef NS_DEBUG
+ nsCOMPtr<nsISupports> rootObject(do_QueryInterface(aObject));
+
+ NS_ASSERTION(rootObject.get() == aObject,
+ "bad call to WriteObject -- call WriteCompoundObject!");
+#endif
+
+ return WriteObjectCommon(aObject, aIsStrongRef, 0);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteSingleRefObject(nsISupports* aObject)
+{
+#ifdef NS_DEBUG
+ nsCOMPtr<nsISupports> rootObject(do_QueryInterface(aObject));
+
+ NS_ASSERTION(rootObject.get() == aObject,
+ "bad call to WriteSingleRefObject -- call WriteCompoundObject!");
+#endif
+
+ return WriteObjectCommon(aObject, PR_TRUE, MFL_SINGLE_REF_PSEUDO_TAG);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteCompoundObject(nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupports> rootObject(do_QueryInterface(aObject));
+
+#ifdef NS_DEBUG
+ nsCOMPtr<nsISupports> roundtrip;
+ rootObject->QueryInterface(aIID, getter_AddRefs(roundtrip));
+
+ NS_ASSERTION(rootObject.get() != aObject,
+ "wasteful call to WriteCompoundObject -- call WriteObject!");
+ NS_ASSERTION(roundtrip.get() == aObject,
+ "bad aggregation or multiple inheritance detected by call to "
+ "WriteCompoundObject!");
+#endif
+
+ rv = WriteObjectCommon(rootObject, aIsStrongRef, MFL_QUERY_INTERFACE_TAG);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NSFastLoadID iid;
+ rv = MapID(aIID, &iid);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return WriteFastID(iid);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteID(const nsID& aID)
+{
+ nsresult rv;
+ NSFastLoadID fastID;
+
+ rv = MapID(aID, &fastID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return WriteFastID(fastID);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ mCurrentDocumentMapEntry = nsnull;
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ return seekable->Seek(aWhence, aOffset);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::Tell(PRInt64 *aResult)
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ return seekable->Tell(aResult);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::SetEOF()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ return seekable->SetEOF();
+}
+
+NS_COM nsresult
+NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aDestStream,
+ nsIFastLoadFileIO* aFileIO)
+{
+ nsFastLoadFileWriter* writer =
+ new nsFastLoadFileWriter(aDestStream, aFileIO);
+ if (!writer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Stabilize writer's refcnt.
+ nsCOMPtr<nsIObjectOutputStream> stream(writer);
+
+ nsresult rv = writer->Open();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+// -------------------------- nsFastLoadFileUpdater --------------------------
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsFastLoadFileUpdater,
+ nsFastLoadFileWriter,
+ nsIFastLoadFileIO)
+
+NS_IMETHODIMP
+nsFastLoadFileUpdater::GetInputStream(nsIInputStream** aResult)
+{
+ *aResult = mInputStream;
+ NS_IF_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileUpdater::GetOutputStream(nsIOutputStream** aResult)
+{
+ *aResult = nsnull;
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileUpdater::CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsDocumentMapReadEntry* readEntry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*, aHdr);
+ nsFastLoadFileUpdater* updater =
+ NS_REINTERPRET_CAST(nsFastLoadFileUpdater*, aData);
+
+ void* spec = nsMemory::Clone(readEntry->mString,
+ strlen(readEntry->mString) + 1);
+ if (!spec)
+ return PL_DHASH_STOP;
+
+ nsDocumentMapWriteEntry* writeEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&updater->mDocumentMap, spec,
+ PL_DHASH_ADD));
+ if (!writeEntry) {
+ nsMemory::Free(spec);
+ return PL_DHASH_STOP;
+ }
+
+ writeEntry->mString = NS_REINTERPRET_CAST(const char*, spec);
+ writeEntry->mURI = nsnull;
+ writeEntry->mInitialSegmentOffset = readEntry->mInitialSegmentOffset;
+ writeEntry->mCurrentSegmentOffset = 0;
+ return PL_DHASH_NEXT;
+}
+
+nsresult
+nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader)
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+ rv = nsFastLoadFileWriter::Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 i, n;
+
+ // Map from dense, zero-based, uint32 NSFastLoadID in reader to 16-byte
+ // nsID in updater.
+ nsID* readIDMap = aReader->mFooter.mIDMap;
+ for (i = 0, n = aReader->mFooter.mNumIDs; i < n; i++) {
+ NSFastLoadID fastID;
+ rv = MapID(readIDMap[i], &fastID);
+ NS_ASSERTION(fastID == i + 1, "huh?");
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Map from reader dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp
+ // object offset and refcnt information in updater.
+ nsFastLoadFileReader::nsObjectMapEntry* readObjectMap =
+ aReader->mFooter.mObjectMap;
+
+ // Prepare to save aReader state in case we need to seek back and read a
+ // singleton object that might otherwise get written by this updater.
+ nsDocumentMapReadEntry* saveDocMapEntry = nsnull;
+ nsCOMPtr<nsISeekableStream> inputSeekable;
+ PRInt64 saveOffset = 0;
+
+ for (i = 0, n = aReader->mFooter.mNumSharpObjects; i < n; i++) {
+ nsFastLoadFileReader::nsObjectMapEntry* readEntry = &readObjectMap[i];
+
+ NS_ASSERTION(readEntry->mCIDOffset != 0,
+ "fastload updater: mCIDOffset cannot be zero!");
+
+ // If the reader didn't read this object but it's a singleton, we must
+ // "deserialize" it now, to discover its one and only root nsISupports
+ // address. The object already exists in memory if it was created at
+ // startup without resort to the FastLoad file. The canonical example
+ // is the system principal object held by all XUL JS scripts.
+
+ nsISupports* obj = readEntry->mReadObject;
+ if (!obj && MFL_GET_SINGLETON_FLAG(readEntry)) {
+ if (!saveDocMapEntry) {
+ inputSeekable = do_QueryInterface(aReader->mInputStream);
+ rv = inputSeekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ saveDocMapEntry = aReader->mCurrentDocumentMapEntry;
+ aReader->mCurrentDocumentMapEntry = nsnull;
+ }
+
+ rv = inputSeekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ readEntry->mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aReader
+ ->DeserializeObject(getter_AddRefs(readEntry->mReadObject));
+ if (NS_FAILED(rv))
+ return rv;
+ obj = readEntry->mReadObject;
+
+ // Don't forget to set mSkipOffset in case someone calls the reader
+ // to "deserialize" (yet again) the object we just read.
+ //
+ // Say the singleton is the system principal, and the FastLoad file
+ // contains data for navigator.xul including scripts and functions.
+ // If we update the FastLoad file to contain data for messenger.xul
+ // in a separate session started via mozilla -mail, *and during the
+ // same FastLoad episode in this session* race to open a navigator
+ // window, we will attempt to read all objects serialized in the
+ // navigator.xul portion of the FastLoad file.
+ //
+ // mSkipOffset must be set in such a case so the reader can skip
+ // the system principal's serialized data, because the updater for
+ // messenger.xul being opened here has already read it.
+
+ rv = inputSeekable->Tell(&readEntry->mSkipOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ NSFastLoadOID oid = MFL_SHARP_INDEX_TO_OID(i);
+ void* key = obj
+ ? NS_REINTERPRET_CAST(void*, obj)
+ : NS_REINTERPRET_CAST(void*, (oid | MFL_OBJECT_DEF_TAG));
+
+ nsSharpObjectMapEntry* writeEntry =
+ NS_STATIC_CAST(nsSharpObjectMapEntry*,
+ PL_DHashTableOperate(&mObjectMap, key,
+ PL_DHASH_ADD));
+ if (!writeEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Hold the object if there is one, so that objmap_ClearEntry can
+ // release the reference.
+ NS_IF_ADDREF(obj);
+ writeEntry->mObject = NS_REINTERPRET_CAST(nsISupports*, key);
+ writeEntry->mOID = oid;
+ writeEntry->mInfo.mCIDOffset = readEntry->mCIDOffset;
+ writeEntry->mInfo.mStrongRefCnt = readEntry->mSaveStrongRefCnt;
+ writeEntry->mInfo.mWeakRefCnt = readEntry->mSaveWeakRefCnt;
+ }
+
+ // If we had to read any singletons, restore aReader's saved state.
+ if (saveDocMapEntry) {
+ rv = inputSeekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ aReader->mCurrentDocumentMapEntry = saveDocMapEntry;
+ }
+
+ // Copy URI spec string and initial segment offset in FastLoad file from
+ // nsDocumentMapReadEntry in reader to nsDocumentMapWriteEntry in updater.
+ // If we didn't enumerate all entries, we ran out of memory.
+ n = PL_DHashTableEnumerate(&aReader->mFooter.mDocumentMap,
+ CopyReadDocumentMapEntryToUpdater,
+ this);
+ if (n != aReader->mFooter.mDocumentMap.entryCount)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Copy source filename dependencies from reader to updater.
+ nsISupportsArray* readDeps = aReader->mFooter.mDependencies;
+ rv = readDeps->Count(&n);
+ if (NS_FAILED(rv))
+ return rv;
+
+ for (i = 0; i < n; i++) {
+ nsCOMPtr<nsIFile> file;
+ rv = readDeps->GetElementAt(i, getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = AddDependency(file);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Seek to the reader's footer offset so we overwrite the footer. First,
+ // update the header to have a zero mFooterOffset, which will invalidate
+ // the FastLoad file on next startup read attempt, should we crash before
+ // completing this update.
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ offsetof(nsFastLoadHeader, mFooterOffset));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ aReader->mHeader.mFooterOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Avoid creating yet another object by implementing nsIFastLoadFileIO on
+ // this updater, and save aReader's input stream so it can be returned by
+ // GetInputStream called from nsFastLoadFileWriter::Close. This requires
+ // that we override Close to break the resulting zero-length cycle.
+ mFileIO = this;
+ mInputStream = aReader->mInputStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileUpdater::Close()
+{
+ // Call base-class Close implementation, which uses mFileIO.
+ nsresult rv = nsFastLoadFileWriter::Close();
+
+ // Break degenerate cycle from this->mFileIO to this.
+ mFileIO = nsnull;
+ return rv;
+}
+
+NS_COM nsresult
+NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aOutputStream,
+ nsIObjectInputStream* aReaderAsStream)
+{
+ // Make sure that aReaderAsStream is an nsFastLoadFileReader.
+ nsCOMPtr<nsIFastLoadFileReader> reader(do_QueryInterface(aReaderAsStream));
+ if (!reader)
+ return NS_ERROR_UNEXPECTED;
+
+ nsFastLoadFileUpdater* updater = new nsFastLoadFileUpdater(aOutputStream);
+ if (!updater)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Stabilize updater's refcnt.
+ nsCOMPtr<nsIObjectOutputStream> stream(updater);
+
+ nsresult rv = updater->Open(NS_STATIC_CAST(nsFastLoadFileReader*,
+ aReaderAsStream));
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h
new file mode 100644
index 00000000..9f6f061a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h
@@ -0,0 +1,566 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsFastLoadFile_h___
+#define nsFastLoadFile_h___
+
+/**
+ * Mozilla FastLoad file format and helper types.
+ */
+
+#include "prtypes.h"
+#include "pldhash.h"
+
+#include "nsBinaryStream.h"
+#include "nsCOMPtr.h"
+#include "nsDebug.h"
+#include "nsID.h"
+#include "nsMemory.h"
+#include "nsVoidArray.h"
+
+#include "nsIFastLoadFileControl.h"
+#include "nsIFastLoadService.h"
+#include "nsISeekableStream.h"
+#include "nsISupportsArray.h"
+
+/**
+ * FastLoad file Object ID (OID) is an identifier for multiply and cyclicly
+ * connected objects in the serialized graph of all reachable objects.
+ *
+ * Holy Mixed Metaphors: JS, after Common Lisp, uses #n= to define a "sharp
+ * variable" naming an object that's multiply or cyclicly connected, and #n#
+ * to stand for a connection to an already-defined object. We too call any
+ * object with multiple references "sharp", and (here it comes) any object
+ * with only one reference "dull".
+ *
+ * Note that only sharp objects require a mapping from OID to FastLoad file
+ * offset and other information. Dull objects can be serialized _in situ_
+ * (where they are referenced) and deserialized when their (singular, shared)
+ * OID is scanned.
+ *
+ * We also compress 16-byte XPCOM IDs into 32-bit dense identifiers to save
+ * space. See nsFastLoadFooter, below, for the mapping data structure used to
+ * compute an nsID given an NSFastLoadID.
+ */
+typedef PRUint32 NSFastLoadID; // nsFastLoadFooter::mIDMap index
+typedef PRUint32 NSFastLoadOID; // nsFastLoadFooter::mObjectMap index
+
+/**
+ * A Mozilla FastLoad file is an untagged (in general) stream of objects and
+ * primitive-type data. Small integers are fairly common, and could easily be
+ * confused for NSFastLoadIDs and NSFastLoadOIDs. To help catch bugs where
+ * reader and writer code fail to match, we XOR unlikely 32-bit numbers with
+ * NSFastLoad*IDs when storing and fetching. The following unlikely values are
+ * irrational numbers ((sqrt(5)-1)/2, sqrt(2)-1) represented in fixed point.
+ *
+ * The reader XORs, converts the ID to an index, and bounds-checks all array
+ * accesses that use the index. Array access code asserts that the index is in
+ * bounds, and returns a dummy array element if it isn't.
+ */
+#define MFL_ID_XOR_KEY 0x9E3779B9 // key XOR'd with ID when serialized
+#define MFL_OID_XOR_KEY 0x6A09E667 // key XOR'd with OID when serialized
+
+/**
+ * An OID can be tagged to introduce the serialized definition of the object,
+ * or to stand for a strong or weak reference to that object. Thus the high
+ * 29 bits actually identify the object, and the low three bits tell whether
+ * the object is being defined or just referenced -- and via what inheritance
+ * chain or inner object, if necessary.
+ *
+ * The MFL_QUERY_INTERFACE_TAG bit helps us cope with aggregation and multiple
+ * inheritance: object identity follows the XPCOM rule, but a deserializer may
+ * need to query for an interface not on the primary inheritance chain ending
+ * in the nsISupports whose address uniquely identifies the XPCOM object being
+ * referenced or defined.
+ */
+#define MFL_OBJECT_TAG_BITS 3
+#define MFL_OBJECT_TAG_MASK PR_BITMASK(MFL_OBJECT_TAG_BITS)
+
+#define MFL_OBJECT_DEF_TAG 1U // object definition follows this OID
+#define MFL_WEAK_REF_TAG 2U // OID weakly refers to a prior object
+ // NB: do not confuse with nsWeakPtr!
+#define MFL_QUERY_INTERFACE_TAG 4U // QI object to the ID follows this OID
+ // NB: an NSFastLoadID, not an nsIID!
+
+/**
+ * The dull object identifier introduces the definition of all objects that
+ * have only one (necessarily strong) ref in the serialization. The definition
+ * appears at the point of reference.
+ */
+#define MFL_DULL_OBJECT_OID MFL_OBJECT_DEF_TAG
+
+/**
+ * Convert an OID to an index into nsFastLoadFooter::mObjectMap.
+ */
+#define MFL_OID_TO_SHARP_INDEX(oid) (((oid) >> MFL_OBJECT_TAG_BITS) - 1)
+#define MFL_SHARP_INDEX_TO_OID(index) (((index) + 1) << MFL_OBJECT_TAG_BITS)
+
+/**
+ * Magic "number" at start of a FastLoad file. Inspired by the PNG "magic"
+ * string, which inspired XPCOM's typelib (.xpt) file magic. Guaranteed to be
+ * corrupted by FTP-as-ASCII and other likely errors, meaningful to clued-in
+ * humans, and ending in ^Z to terminate erroneous text input on Windows.
+ */
+#define MFL_FILE_MAGIC "XPCOM\nMozFASL\r\n\032"
+#define MFL_FILE_MAGIC_SIZE 16
+
+#define MFL_FILE_VERSION_0 0
+#define MFL_FILE_VERSION_1 1000
+#define MFL_FILE_VERSION 4 // fix to note singletons in object map
+
+/**
+ * Compute Fletcher's 16-bit checksum over aLength bytes starting at aBuffer,
+ * with the initial accumulators seeded from *aChecksum, and final checksum
+ * returned in *aChecksum. The return value is the number of unchecked bytes,
+ * which may be non-zero if aBuffer is misaligned or aLength is odd. Callers
+ * should copy any remaining bytes to the front of the next buffer.
+ *
+ * If aLastBuffer is false, do not check any bytes remaining due to misaligned
+ * aBuffer or odd aLength, instead returning the remaining byte count. But if
+ * aLastBuffer is true, treat aBuffer as the last buffer in the file and check
+ * every byte, returning 0. Here's a read-loop checksumming sketch:
+ *
+ * char buf[BUFSIZE];
+ * PRUint32 len, rem = 0;
+ * PRUint32 checksum = 0;
+ *
+ * while (NS_SUCCEEDED(rv = Read(buf + rem, sizeof buf - rem, &len)) && len) {
+ * len += rem;
+ * rem = NS_AccumulateFastLoadChecksum(&checksum,
+ * NS_REINTERPRET_CAST(PRUint8*, buf),
+ * len,
+ * PR_FALSE);
+ * if (rem)
+ * memcpy(buf, buf + len - rem, rem);
+ * }
+ *
+ * if (rem) {
+ * NS_AccumulateFastLoadChecksum(&checksum,
+ * NS_REINTERPRET_CAST(PRUint8*, buf),
+ * rem,
+ * PR_TRUE);
+ * }
+ *
+ * After this, if NS_SUCCEEDED(rv), checksum contains a valid FastLoad sum.
+ */
+PR_EXTERN(PRUint32)
+NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum,
+ const PRUint8* aBuffer,
+ PRUint32 aLength,
+ PRBool aLastBuffer);
+
+PR_EXTERN(PRUint32)
+NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount);
+
+/**
+ * Header at the start of a FastLoad file.
+ */
+struct nsFastLoadHeader {
+ char mMagic[MFL_FILE_MAGIC_SIZE];
+ PRUint32 mChecksum;
+ PRUint32 mVersion;
+ PRUint32 mFooterOffset;
+ PRUint32 mFileSize;
+};
+
+/**
+ * Footer prefix structure (footer header, ugh), after which come arrays of
+ * structures or strings counted by these members.
+ */
+struct nsFastLoadFooterPrefix {
+ PRUint32 mNumIDs;
+ PRUint32 mNumSharpObjects;
+ PRUint32 mNumMuxedDocuments;
+ PRUint32 mNumDependencies;
+};
+
+struct nsFastLoadSharpObjectInfo {
+ PRUint32 mCIDOffset; // offset of object's NSFastLoadID and data
+ PRUint16 mStrongRefCnt;
+ PRUint16 mWeakRefCnt; // high bit is singleton flag, see below
+};
+
+#define MFL_SINGLETON_FLAG 0x8000
+#define MFL_WEAK_REFCNT_MASK 0x7fff
+
+#define MFL_GET_SINGLETON_FLAG(ip) ((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG)
+#define MFL_GET_WEAK_REFCNT(ip) ((ip)->mWeakRefCnt & MFL_WEAK_REFCNT_MASK)
+
+#define MFL_SET_SINGLETON_FLAG(ip) \
+ ((ip)->mWeakRefCnt |= MFL_SINGLETON_FLAG)
+#define MFL_SET_WEAK_REFCNT(ip,rc) \
+ ((ip)->mWeakRefCnt = (((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG) | (rc)))
+
+#define MFL_BUMP_WEAK_REFCNT(ip) (++(ip)->mWeakRefCnt)
+#define MFL_DROP_WEAK_REFCNT(ip) (--(ip)->mWeakRefCnt)
+
+struct nsFastLoadMuxedDocumentInfo {
+ const char* mURISpec;
+ PRUint32 mInitialSegmentOffset;
+};
+
+// forward declarations of opaque types defined in nsFastLoadFile.cpp
+struct nsDocumentMapReadEntry;
+struct nsDocumentMapWriteEntry;
+
+// So nsFastLoadFileUpdater can verify that its nsIObjectInputStream parameter
+// is an nsFastLoadFileReader.
+#define NS_FASTLOADFILEREADER_IID \
+ {0x7d37d1bb,0xcef3,0x4c5f,{0x97,0x68,0x0f,0x89,0x7f,0x1a,0xe1,0x40}}
+
+struct nsIFastLoadFileReader : public nsISupports {
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_FASTLOADFILEREADER_IID)
+};
+
+/**
+ * Inherit from the concrete class nsBinaryInputStream, which inherits from
+ * abstract nsIObjectInputStream but does not implement its direct methods.
+ * Though the names are not as clear as I'd like, this seems to be the best
+ * way to share nsBinaryStream.cpp code.
+ */
+class nsFastLoadFileReader
+ : public nsBinaryInputStream,
+ public nsIFastLoadReadControl,
+ public nsISeekableStream,
+ public nsIFastLoadFileReader
+{
+ public:
+ nsFastLoadFileReader(nsIInputStream *aStream)
+ : mCurrentDocumentMapEntry(nsnull) {
+ SetInputStream(aStream);
+ MOZ_COUNT_CTOR(nsFastLoadFileReader);
+ }
+
+ virtual ~nsFastLoadFileReader() {
+ MOZ_COUNT_DTOR(nsFastLoadFileReader);
+ }
+
+ private:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // overridden nsIObjectInputStream methods
+ NS_IMETHOD ReadObject(PRBool aIsStrongRef, nsISupports* *_retval);
+ NS_IMETHOD ReadID(nsID *aResult);
+
+ // nsIFastLoadFileControl methods
+ NS_DECL_NSIFASTLOADFILECONTROL
+
+ // nsIFastLoadReadControl methods
+ NS_DECL_NSIFASTLOADREADCONTROL
+
+ // nsISeekableStream methods
+ NS_DECL_NSISEEKABLESTREAM
+
+ // Override Read so we can demultiplex a document interleaved with others.
+ NS_IMETHOD Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead);
+
+ // Override ReadSegments too, as nsBinaryInputStream::ReadSegments does
+ // not call through our overridden Read method -- it calls directly into
+ // the underlying input stream.
+ NS_IMETHODIMP ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ PRUint32 aCount, PRUint32 *aResult);
+
+ nsresult ReadHeader(nsFastLoadHeader *aHeader);
+
+ /**
+ * In-memory representation of an indexed nsFastLoadSharpObjectInfo record.
+ */
+ struct nsObjectMapEntry : public nsFastLoadSharpObjectInfo {
+ nsCOMPtr<nsISupports> mReadObject;
+ PRInt64 mSkipOffset;
+ PRUint16 mSaveStrongRefCnt; // saved for an Update
+ PRUint16 mSaveWeakRefCnt; // after a Read
+ };
+
+ /**
+ * In-memory representation of the FastLoad file footer.
+ */
+ struct nsFastLoadFooter : public nsFastLoadFooterPrefix {
+ nsFastLoadFooter()
+ : mIDMap(nsnull),
+ mObjectMap(nsnull) {
+ mDocumentMap.ops = mURIMap.ops = nsnull;
+ }
+
+ ~nsFastLoadFooter() {
+ delete[] mIDMap;
+ delete[] mObjectMap;
+ if (mDocumentMap.ops)
+ PL_DHashTableFinish(&mDocumentMap);
+ if (mURIMap.ops)
+ PL_DHashTableFinish(&mURIMap);
+ }
+
+ // These can't be static within GetID and GetSharpObjectEntry or the
+ // toolchains on HP-UX 10.20's, RH 7.0, and Mac OS X all barf at link
+ // time ("common symbols not allowed with MY_DHLIB output format", to
+ // quote the OS X rev of gcc).
+ static nsID gDummyID;
+ static nsObjectMapEntry gDummySharpObjectEntry;
+
+ const nsID& GetID(NSFastLoadID aFastId) const {
+ PRUint32 index = aFastId - 1;
+ NS_ASSERTION(index < mNumIDs, "aFastId out of range");
+ if (index >= mNumIDs)
+ return gDummyID;
+ return mIDMap[index];
+ }
+
+ nsObjectMapEntry&
+ GetSharpObjectEntry(NSFastLoadOID aOID) const {
+ PRUint32 index = MFL_OID_TO_SHARP_INDEX(aOID);
+ NS_ASSERTION(index < mNumSharpObjects, "aOID out of range");
+ if (index >= mNumSharpObjects)
+ return gDummySharpObjectEntry;
+ return mObjectMap[index];
+ }
+
+ // Map from dense, zero-based, uint32 NSFastLoadID to 16-byte nsID.
+ nsID* mIDMap;
+
+ // Map from dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp
+ // object offset and refcnt information.
+ nsObjectMapEntry* mObjectMap;
+
+ // Map from URI spec string to nsDocumentMapReadEntry, which helps us
+ // demultiplex a document's objects from among the interleaved object
+ // stream segments in the FastLoad file.
+ PLDHashTable mDocumentMap;
+
+ // Fast mapping from URI object pointer to mDocumentMap entry, valid
+ // only while the muxed document is loading.
+ PLDHashTable mURIMap;
+
+ // List of source filename dependencies that should trigger regeneration
+ // of the FastLoad file.
+ nsCOMPtr<nsISupportsArray> mDependencies;
+ };
+
+ nsresult ReadFooter(nsFastLoadFooter *aFooter);
+ nsresult ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix);
+ nsresult ReadSlowID(nsID *aID);
+ nsresult ReadFastID(NSFastLoadID *aID);
+ nsresult ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo);
+ nsresult ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo);
+ nsresult DeserializeObject(nsISupports* *aObject);
+
+ nsresult Open();
+ NS_IMETHOD Close();
+
+ protected:
+ nsFastLoadHeader mHeader;
+ nsFastLoadFooter mFooter;
+
+ nsDocumentMapReadEntry* mCurrentDocumentMapEntry;
+
+ friend class nsFastLoadFileUpdater;
+};
+
+NS_COM nsresult
+NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult,
+ nsIInputStream* aSrcStream);
+
+/**
+ * Inherit from the concrete class nsBinaryInputStream, which inherits from
+ * abstract nsIObjectInputStream but does not implement its direct methods.
+ * Though the names are not as clear as I'd like, this seems to be the best
+ * way to share nsBinaryStream.cpp code.
+ */
+class nsFastLoadFileWriter
+ : public nsBinaryOutputStream,
+ public nsIFastLoadWriteControl,
+ public nsISeekableStream
+{
+ public:
+ nsFastLoadFileWriter(nsIOutputStream *aStream, nsIFastLoadFileIO* aFileIO)
+ : mCurrentDocumentMapEntry(nsnull),
+ mFileIO(aFileIO)
+ {
+ SetOutputStream(aStream);
+ mHeader.mChecksum = 0;
+ mIDMap.ops = mObjectMap.ops = mDocumentMap.ops = mURIMap.ops = nsnull;
+ mDependencyMap.ops = nsnull;
+ MOZ_COUNT_CTOR(nsFastLoadFileWriter);
+ }
+
+ virtual ~nsFastLoadFileWriter()
+ {
+ if (mIDMap.ops)
+ PL_DHashTableFinish(&mIDMap);
+ if (mObjectMap.ops)
+ PL_DHashTableFinish(&mObjectMap);
+ if (mDocumentMap.ops)
+ PL_DHashTableFinish(&mDocumentMap);
+ if (mURIMap.ops)
+ PL_DHashTableFinish(&mURIMap);
+ if (mDependencyMap.ops)
+ PL_DHashTableFinish(&mDependencyMap);
+ MOZ_COUNT_DTOR(nsFastLoadFileWriter);
+ }
+
+ private:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // overridden nsIObjectOutputStream methods
+ NS_IMETHOD WriteObject(nsISupports* aObject, PRBool aIsStrongRef);
+ NS_IMETHOD WriteSingleRefObject(nsISupports* aObject);
+ NS_IMETHOD WriteCompoundObject(nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef);
+ NS_IMETHOD WriteID(const nsID& aID);
+
+ // nsIFastLoadFileControl methods
+ NS_DECL_NSIFASTLOADFILECONTROL
+
+ // nsIFastLoadWriteControl methods
+ NS_DECL_NSIFASTLOADWRITECONTROL
+
+ // nsISeekableStream methods
+ NS_DECL_NSISEEKABLESTREAM
+
+ nsresult MapID(const nsID& aSlowID, NSFastLoadID *aResult);
+
+ nsresult WriteHeader(nsFastLoadHeader *aHeader);
+ nsresult WriteFooter();
+ nsresult WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix);
+ nsresult WriteSlowID(const nsID& aID);
+ nsresult WriteFastID(NSFastLoadID aID);
+ nsresult WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo);
+ nsresult WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo);
+
+ nsresult Init();
+ nsresult Open();
+ NS_IMETHOD Close();
+
+ nsresult WriteObjectCommon(nsISupports* aObject,
+ PRBool aIsStrongRef,
+ PRUint32 aQITag);
+
+ static PLDHashOperator PR_CALLBACK
+ IDMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ static PLDHashOperator PR_CALLBACK
+ ObjectMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ static PLDHashOperator PR_CALLBACK
+ DocumentMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ static PLDHashOperator PR_CALLBACK
+ DependencyMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ protected:
+ nsFastLoadHeader mHeader;
+
+ PLDHashTable mIDMap;
+ PLDHashTable mObjectMap;
+ PLDHashTable mDocumentMap;
+ PLDHashTable mURIMap;
+ PLDHashTable mDependencyMap;
+
+ nsDocumentMapWriteEntry* mCurrentDocumentMapEntry;
+ nsCOMPtr<nsIFastLoadFileIO> mFileIO;
+};
+
+NS_COM nsresult
+NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aDestStream,
+ nsIFastLoadFileIO* aFileIO);
+
+/**
+ * Subclass of nsFastLoadFileWriter, friend of nsFastLoadFileReader which it
+ * wraps when a FastLoad file needs to be updated. The wrapped reader can be
+ * used to demulitplex data for documents already in the FastLoad file, while
+ * the updater writes new data over the old footer, then writes a new footer
+ * that maps all data on Close.
+ */
+class nsFastLoadFileUpdater
+ : public nsFastLoadFileWriter,
+ nsIFastLoadFileIO
+{
+ public:
+ nsFastLoadFileUpdater(nsIOutputStream* aOutputStream)
+ : nsFastLoadFileWriter(aOutputStream, nsnull) {
+ MOZ_COUNT_CTOR(nsFastLoadFileUpdater);
+ }
+
+ virtual ~nsFastLoadFileUpdater() {
+ MOZ_COUNT_DTOR(nsFastLoadFileUpdater);
+ }
+
+ private:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIFastLoadFileIO methods
+ NS_DECL_NSIFASTLOADFILEIO
+
+ nsresult Open(nsFastLoadFileReader* aReader);
+ NS_IMETHOD Close();
+
+ static PLDHashOperator PR_CALLBACK
+ CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ friend class nsFastLoadFileReader;
+
+ protected:
+ nsCOMPtr<nsIInputStream> mInputStream;
+};
+
+NS_COM nsresult
+NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aOutputStream,
+ nsIObjectInputStream* aReaderAsStream);
+
+#endif // nsFastLoadFile_h___
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h b/src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h
new file mode 100644
index 00000000..0c832357
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsFastLoadPtr_h___
+#define nsFastLoadPtr_h___
+
+/**
+ * Mozilla FastLoad file object pointer template type.
+ *
+ * Use nsFastLoadPtr<T> rather than nsCOMPtr<T> when declaring a strong XPCOM
+ * ref member of a data structure that's conditionally loaded at application
+ * startup. You must be willing to tolerate the null mRawPtr test on every
+ * dereference of this member pointer, or else copy it to a local to optimize
+ * away the cost.
+ */
+
+#ifndef nsCOMPtr_h___
+#include "nsCOMPtr.h"
+#endif
+
+#ifndef nsIFastLoadService_h___
+#include "nsIFastLoadService.h"
+#endif
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define gFastLoadService_ VBoxNsxpgFastLoadService_
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/**
+ * nsFastLoadPtr is a template class, so we don't want a class static service
+ * pointer member declared in nsFastLoadPtr, above. Plus, we need special
+ * declaration magic to export data across DLL/DSO boundaries. So we use an
+ * old-fashioned global variable that refers weakly to the one true FastLoad
+ * service. This pointer is maintained by that singleton's ctor and dtor.
+ */
+PR_EXPORT_DATA(nsIFastLoadService*) gFastLoadService_;
+
+template <class T>
+class nsFastLoadPtr : public nsCOMPtr<T> {
+ public:
+ nsDerivedSafe<T>* get() const {
+ if (!this->mRawPtr) {
+ gFastLoadService_->GetFastLoadReferent(
+ NS_REINTERPRET_CAST(nsISupports**,
+ &this->mRawPtr));
+ }
+ return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, this->mRawPtr);
+ }
+
+ /**
+ * Deserialize an nsFastLoadPtr from aInputStream, skipping the referent
+ * object, but saving the object's offset for later deserialization.
+ *
+ * Lowercase name _a la_ get, because it's called the same way -- not via
+ * operator->().
+ */
+ nsresult read(nsIObjectInputStream* aInputStream) {
+ return gFastLoadService_->ReadFastLoadPtr(aInputStream,
+ NS_REINTERPRET_CAST(nsISupports**,
+ &this->mRawPtr));
+ }
+
+ /**
+ * Serialize an nsFastLoadPtr reference and possibly the referent object,
+ * if that object has not yet been serialized.
+ *
+ * Lowercase name _a la_ get, because it's called the same way -- not via
+ * operator->().
+ */
+ nsresult write(nsIObjectOutputStream* aOutputStream) {
+ return gFastLoadService_->WriteFastLoadPtr(aOutputStream,
+ NS_REINTERPRET_CAST(nsISupports*,
+ this->mRawPtr));
+ }
+};
+
+#endif // nsFastLoadPtr_h___
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp
new file mode 100644
index 00000000..4df187c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp
@@ -0,0 +1,571 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prtypes.h"
+#include "prio.h"
+#include "prtime.h"
+#include "pldhash.h"
+
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsFastLoadFile.h"
+#include "nsFastLoadPtr.h"
+#include "nsFastLoadService.h"
+#include "nsString.h"
+
+#include "nsIComponentManager.h"
+#include "nsIEnumerator.h"
+#include "nsIFastLoadFileControl.h"
+#include "nsIFile.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+#include "nsISeekableStream.h"
+#include "nsISupports.h"
+
+PR_IMPLEMENT_DATA(nsIFastLoadService*) gFastLoadService_ = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFastLoadService, nsIFastLoadService)
+
+nsFastLoadService::nsFastLoadService()
+ : mLock(nsnull),
+ mFastLoadPtrMap(nsnull),
+ mDirection(0)
+{
+ NS_ASSERTION(gFastLoadService_ == nsnull, "double FastLoadService init?");
+ gFastLoadService_ = this;
+}
+
+nsFastLoadService::~nsFastLoadService()
+{
+ gFastLoadService_ = nsnull;
+
+ if (mInputStream)
+ mInputStream->Close();
+ if (mOutputStream)
+ mOutputStream->Close();
+
+ if (mFastLoadPtrMap)
+ PL_DHashTableDestroy(mFastLoadPtrMap);
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+NS_IMETHODIMP
+nsFastLoadService::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ *aResult = nsnull;
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsFastLoadService* fastLoadService = new nsFastLoadService();
+ if (!fastLoadService)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ fastLoadService->mLock = PR_NewLock();
+ if (!fastLoadService->mLock) {
+ delete fastLoadService;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(fastLoadService);
+ nsresult rv = fastLoadService->QueryInterface(aIID, aResult);
+ NS_RELEASE(fastLoadService);
+ return rv;
+}
+
+#if defined XP_MAC
+
+// Mac format: "<Basename> FastLoad File" with <basename> capitalized.
+# include "nsCRT.h"
+
+# define MASSAGE_BASENAME(bn) (bn.SetCharAt(nsCRT::ToUpper(bn.CharAt(0)), 0))
+# define PLATFORM_FASL_SUFFIX " FastLoad File"
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+
+// Unix format: "<basename>.mfasl".
+# define MASSAGE_BASENAME(bn) /* nothing */
+# define PLATFORM_FASL_SUFFIX ".mfasl"
+
+#elif defined(XP_WIN) || defined(XP_OS2)
+
+// Windows format: "<basename>.mfl".
+# define MASSAGE_BASENAME(bn) /* nothing */
+# define PLATFORM_FASL_SUFFIX ".mfl"
+
+#endif
+
+nsresult
+nsFastLoadService::NewFastLoadFile(const char* aBaseName, nsIFile* *aResult)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> file;
+
+ rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
+ getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString name(aBaseName);
+ MASSAGE_BASENAME(name);
+ name += PLATFORM_FASL_SUFFIX;
+ rv = file->AppendNative(name);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = file;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::NewInputStream(nsIInputStream* aSrcStream,
+ nsIObjectInputStream* *aResult)
+{
+ nsAutoLock lock(mLock);
+
+ nsCOMPtr<nsIObjectInputStream> stream;
+ nsresult rv = NS_NewFastLoadFileReader(getter_AddRefs(stream), aSrcStream);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::NewOutputStream(nsIOutputStream* aDestStream,
+ nsIObjectOutputStream* *aResult)
+{
+ nsAutoLock lock(mLock);
+
+ return NS_NewFastLoadFileWriter(aResult, aDestStream, mFileIO);
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetInputStream(nsIObjectInputStream* *aResult)
+{
+ NS_IF_ADDREF(*aResult = mInputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SetInputStream(nsIObjectInputStream* aStream)
+{
+ nsAutoLock lock(mLock);
+ mInputStream = aStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetOutputStream(nsIObjectOutputStream* *aResult)
+{
+ NS_IF_ADDREF(*aResult = mOutputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SetOutputStream(nsIObjectOutputStream* aStream)
+{
+ nsAutoLock lock(mLock);
+ mOutputStream = aStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetFileIO(nsIFastLoadFileIO* *aResult)
+{
+ NS_IF_ADDREF(*aResult = mFileIO);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SetFileIO(nsIFastLoadFileIO* aFileIO)
+{
+ nsAutoLock lock(mLock);
+ mFileIO = aFileIO;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetDirection(PRInt32 *aResult)
+{
+ *aResult = mDirection;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::HasMuxedDocument(const char* aURISpec, PRBool *aResult)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+
+ *aResult = PR_FALSE;
+ nsAutoLock lock(mLock);
+
+ if (mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control)
+ rv = control->HasMuxedDocument(aURISpec, aResult);
+ }
+
+ if (! *aResult && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control)
+ rv = control->HasMuxedDocument(aURISpec, aResult);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::StartMuxedDocument(nsISupports* aURI, const char* aURISpec,
+ PRInt32 aDirectionFlags)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+ nsAutoLock lock(mLock);
+
+ // Try for an input stream first, in case aURISpec's data is multiplexed
+ // in the current FastLoad file.
+ if ((aDirectionFlags & NS_FASTLOAD_READ) && mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control) {
+ // If aURISpec is not in the multiplex, control->StartMuxedDocument
+ // will return NS_ERROR_NOT_AVAILABLE.
+ rv = control->StartMuxedDocument(aURI, aURISpec);
+ if (NS_SUCCEEDED(rv) || rv != NS_ERROR_NOT_AVAILABLE)
+ return rv;
+
+ // Ok, aURISpec is not in the existing mux. If we have no output
+ // stream yet, wrap the reader with a FastLoad file updater.
+ if (!mOutputStream && mFileIO) {
+ nsCOMPtr<nsIOutputStream> output;
+ rv = mFileIO->GetOutputStream(getter_AddRefs(output));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // NB: mInputStream must be an nsFastLoadFileReader!
+ rv = NS_NewFastLoadFileUpdater(getter_AddRefs(mOutputStream),
+ output,
+ mInputStream);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (aDirectionFlags == NS_FASTLOAD_READ) {
+ // Tell our caller to re-start multiplexing, rather than attempt
+ // to select and deserialize now.
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ }
+ }
+
+ if ((aDirectionFlags & NS_FASTLOAD_WRITE) && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control)
+ rv = control->StartMuxedDocument(aURI, aURISpec);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SelectMuxedDocument(nsISupports* aURI, nsISupports** aResult)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+ nsAutoLock lock(mLock);
+
+ // Try to select the reader, if any; then only if the URI was not in the
+ // file already, select the writer/updater.
+ if (mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control) {
+ rv = control->SelectMuxedDocument(aURI, aResult);
+ if (NS_SUCCEEDED(rv))
+ mDirection = NS_FASTLOAD_READ;
+ }
+ }
+
+ if (rv == NS_ERROR_NOT_AVAILABLE && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control) {
+ rv = control->SelectMuxedDocument(aURI, aResult);
+ if (NS_SUCCEEDED(rv))
+ mDirection = NS_FASTLOAD_WRITE;
+ }
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::EndMuxedDocument(nsISupports* aURI)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+ nsAutoLock lock(mLock);
+
+ // Try to end the document identified by aURI in the reader, if any; then
+ // only if the URI was not in the file already, end the writer/updater.
+ if (mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control)
+ rv = control->EndMuxedDocument(aURI);
+ }
+
+ if (rv == NS_ERROR_NOT_AVAILABLE && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control)
+ rv = control->EndMuxedDocument(aURI);
+ }
+
+ mDirection = 0;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::AddDependency(nsIFile* aFile)
+{
+ nsAutoLock lock(mLock);
+
+ nsCOMPtr<nsIFastLoadWriteControl> control(do_QueryInterface(mOutputStream));
+ if (!control)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ return control->AddDependency(aFile);
+}
+
+NS_IMETHODIMP
+nsFastLoadService::ComputeChecksum(nsIFile* aFile,
+ nsIFastLoadReadControl* aControl,
+ PRUint32 *aChecksum)
+{
+ nsCAutoString path;
+ nsresult rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(path);
+ PRUint32 checksum = NS_PTR_TO_INT32(mChecksumTable.Get(&key));
+ if (checksum) {
+ *aChecksum = checksum;
+ return NS_OK;
+ }
+
+ rv = aControl->ComputeChecksum(&checksum);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifndef VBOX
+ mChecksumTable.Put(&key, NS_INT32_TO_PTR(checksum));
+#else /* VBOX */
+ mChecksumTable.Put(&key, (void *)(uintptr_t)checksum);
+#endif /* VBOX */
+ *aChecksum = checksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::CacheChecksum(nsIFile* aFile, nsIObjectOutputStream *aStream)
+{
+ nsCOMPtr<nsIFastLoadFileControl> control(do_QueryInterface(aStream));
+ if (!control)
+ return NS_ERROR_FAILURE;
+
+ PRUint32 checksum;
+ nsresult rv = control->GetChecksum(&checksum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString path;
+ rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(path);
+#ifndef VBOX
+ mChecksumTable.Put(&key, NS_INT32_TO_PTR(checksum));
+#else /* VBOX */
+ mChecksumTable.Put(&key, (void *)(uintptr_t)checksum);
+#endif /* VBOX */
+ return NS_OK;
+}
+
+struct nsFastLoadPtrEntry : public PLDHashEntryHdr {
+ nsISupports** mPtrAddr; // key, must come first for PL_DHashGetStubOps
+ PRUint32 mOffset;
+};
+
+NS_IMETHODIMP
+nsFastLoadService::GetFastLoadReferent(nsISupports* *aPtrAddr)
+{
+ NS_ASSERTION(*aPtrAddr == nsnull,
+ "aPtrAddr doesn't point to null nsFastLoadPtr<T>::mRawAddr?");
+
+ nsAutoLock lock(mLock);
+ if (!mFastLoadPtrMap || !mInputStream)
+ return NS_OK;
+
+ nsFastLoadPtrEntry* entry =
+ NS_STATIC_CAST(nsFastLoadPtrEntry*,
+ PL_DHashTableOperate(mFastLoadPtrMap, aPtrAddr,
+ PL_DHASH_LOOKUP));
+ if (PL_DHASH_ENTRY_IS_FREE(entry))
+ return NS_OK;
+
+ nsresult rv;
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, entry->mOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mInputStream->ReadObject(PR_TRUE, aPtrAddr);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Shrink the table if half the entries are removed sentinels.
+ PRUint32 size = PL_DHASH_TABLE_SIZE(mFastLoadPtrMap);
+ if (mFastLoadPtrMap->removedCount >= (size >> 2))
+ PL_DHashTableOperate(mFastLoadPtrMap, entry, PL_DHASH_REMOVE);
+ else
+ PL_DHashTableRawRemove(mFastLoadPtrMap, entry);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::ReadFastLoadPtr(nsIObjectInputStream* aInputStream,
+ nsISupports* *aPtrAddr)
+{
+ // nsFastLoadPtrs self-construct to null, so if we have a non-null value
+ // in our inout parameter, we must have been read already, alright!
+ if (*aPtrAddr)
+ return NS_OK;
+
+ nsresult rv;
+ PRUint32 nextOffset;
+ nsAutoLock lock(mLock);
+
+ rv = aInputStream->Read32(&nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(aInputStream));
+ if (!seekable)
+ return NS_ERROR_FAILURE;
+
+ PRInt64 thisOffset;
+ rv = seekable->Tell(&thisOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!mFastLoadPtrMap) {
+ mFastLoadPtrMap = PL_NewDHashTable(PL_DHashGetStubOps(), this,
+ sizeof(nsFastLoadPtrEntry),
+ PL_DHASH_MIN_SIZE);
+ if (!mFastLoadPtrMap)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsFastLoadPtrEntry* entry =
+ NS_STATIC_CAST(nsFastLoadPtrEntry*,
+ PL_DHashTableOperate(mFastLoadPtrMap, aPtrAddr,
+ PL_DHASH_ADD));
+ NS_ASSERTION(entry->mPtrAddr == nsnull, "duplicate nsFastLoadPtr?!");
+
+ entry->mPtrAddr = aPtrAddr;
+
+ LL_L2UI(entry->mOffset, thisOffset);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::WriteFastLoadPtr(nsIObjectOutputStream* aOutputStream,
+ nsISupports* aObject)
+{
+ NS_ASSERTION(aObject != nsnull, "writing an unread nsFastLoadPtr?!");
+ if (!aObject)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+ nsAutoLock lock(mLock); // serialize writes to aOutputStream
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(aOutputStream));
+ if (!seekable)
+ return NS_ERROR_FAILURE;
+
+ PRInt64 saveOffset;
+ rv = seekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aOutputStream->Write32(0); // nextOffset placeholder
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aOutputStream->WriteObject(aObject, PR_TRUE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 nextOffset;
+ rv = seekable->Tell(&nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aOutputStream->Write32(nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h
new file mode 100644
index 00000000..8f1aa6ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "prtypes.h"
+#include "pldhash.h"
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsIFastLoadService.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+
+class nsFastLoadFileReader;
+class nsFastLoadFileWriter;
+
+class nsFastLoadService : public nsIFastLoadService
+{
+ public:
+ nsFastLoadService();
+ private:
+ ~nsFastLoadService();
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFASTLOADSERVICE
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ private:
+ PRLock* mLock;
+ PLDHashTable* mFastLoadPtrMap;
+ nsCOMPtr<nsIObjectInputStream> mInputStream;
+ nsCOMPtr<nsIObjectOutputStream> mOutputStream;
+ nsCOMPtr<nsIFastLoadFileIO> mFileIO;
+ PRInt32 mDirection;
+ nsHashtable mChecksumTable;
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl
new file mode 100644
index 00000000..6ce0bb30
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl
@@ -0,0 +1,136 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsIInputStream.idl"
+
+interface nsIInputStreamCallback;
+interface nsIEventTarget;
+
+/**
+ * If an input stream is non-blocking, it may return NS_BASE_STREAM_WOULD_BLOCK
+ * when read. The caller must then wait for the stream to have some data to
+ * read. If the stream implements nsIAsyncInputStream, then the caller can use
+ * this interface to request an asynchronous notification when the stream
+ * becomes readable or closed (via the AsyncWait method).
+ *
+ * While this interface is almost exclusively used with non-blocking streams, it
+ * is not necessary that nsIInputStream::isNonBlocking return true. Nor is it
+ * necessary that a non-blocking nsIInputStream implementation also implement
+ * nsIAsyncInputStream.
+ */
+[scriptable, uuid(15a15329-00de-44e8-ab06-0d0b0d43dc5b)]
+interface nsIAsyncInputStream : nsIInputStream
+{
+ /**
+ * This method closes the stream and sets its internal status. If the
+ * stream is already closed, then this method is ignored. Once the stream
+ * is closed, the stream's status cannot be changed. Any successful status
+ * code passed to this method is treated as NS_BASE_STREAM_CLOSED, which
+ * has an effect equivalent to nsIInputStream::close.
+ *
+ * NOTE: this method exists in part to support pipes, which have both an
+ * input end and an output end. If the input end of a pipe is closed, then
+ * writes to the output end of the pipe will fail. The error code returned
+ * when an attempt is made to write to a "broken" pipe corresponds to the
+ * status code passed in when the input end of the pipe was closed, which
+ * greatly simplifies working with pipes in some cases.
+ *
+ * @param aStatus
+ * The error that will be reported if this stream is accessed after
+ * it has been closed.
+ */
+ void closeWithStatus(in nsresult aStatus);
+
+ /**
+ * Asynchronously wait for the stream to be readable or closed. The
+ * notification is one-shot, meaning that each asyncWait call will result
+ * in exactly one notification callback. After the OnInputStreamReady event
+ * is dispatched, the stream releases its reference to the
+ * nsIInputStreamCallback object. It is safe to call asyncWait again from the
+ * notification handler.
+ *
+ * This method may be called at any time (even if read has not been called).
+ * In other words, this method may be called when the stream already has
+ * data to read. It may also be called when the stream is closed. If the
+ * stream is already readable or closed when AsyncWait is called, then the
+ * OnInputStreamReady event will be dispatched immediately. Otherwise, the
+ * event will be dispatched when the stream becomes readable or closed.
+ *
+ * @param aCallback
+ * This object is notified when the stream becomes ready.
+ * @param aFlags
+ * This parameter specifies optional flags passed in to configure
+ * the behavior of this method. Pass zero to specify no flags.
+ * @param aRequestedCount
+ * Wait until at least this many bytes can be read. This is only
+ * a suggestion to the underlying stream; it may be ignored. The
+ * caller may pass zero to indicate no preference.
+ * @param aEventTarget
+ * Specify NULL to receive notification on ANY thread (possibly even
+ * recursively on the calling thread -- i.e., synchronously), or
+ * specify that the notification be delivered to a specific event
+ * target.
+ */
+ void asyncWait(in nsIInputStreamCallback aCallback,
+ in unsigned long aFlags,
+ in unsigned long aRequestedCount,
+ in nsIEventTarget aEventTarget);
+
+ /**
+ * If passed to asyncWait, this flag overrides the default behavior,
+ * causing the OnInputStreamReady notification to be suppressed until the
+ * stream becomes closed (either as a result of closeWithStatus/close being
+ * called on the stream or possibly due to some error in the underlying
+ * stream).
+ */
+ const unsigned long WAIT_CLOSURE_ONLY = (1<<0);
+};
+
+/**
+ * This is a companion interface for nsIAsyncInputStream::asyncWait.
+ */
+[scriptable, uuid(d1f28e94-3a6e-4050-a5f5-2e81b1fc2a43)]
+interface nsIInputStreamCallback : nsISupports
+{
+ /**
+ * Called to indicate that the stream is either readable or closed.
+ *
+ * @param aStream
+ * The stream whose asyncWait method was called.
+ */
+ void onInputStreamReady(in nsIAsyncInputStream aStream);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl
new file mode 100644
index 00000000..b0dd9ec0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl
@@ -0,0 +1,136 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsIOutputStream.idl"
+
+interface nsIOutputStreamCallback;
+interface nsIEventTarget;
+
+/**
+ * If an output stream is non-blocking, it may return NS_BASE_STREAM_WOULD_BLOCK
+ * when written to. The caller must then wait for the stream to become
+ * writable. If the stream implements nsIAsyncOutputStream, then the caller can
+ * use this interface to request an asynchronous notification when the stream
+ * becomes writable or closed (via the AsyncWait method).
+ *
+ * While this interface is almost exclusively used with non-blocking streams, it
+ * is not necessary that nsIOutputStream::isNonBlocking return true. Nor is it
+ * necessary that a non-blocking nsIOutputStream implementation also implement
+ * nsIAsyncOutputStream.
+ */
+[scriptable, uuid(10dc9c94-8aff-49c6-8af9-d7fdb7339dae)]
+interface nsIAsyncOutputStream : nsIOutputStream
+{
+ /**
+ * This method closes the stream and sets its internal status. If the
+ * stream is already closed, then this method is ignored. Once the stream
+ * is closed, the stream's status cannot be changed. Any successful status
+ * code passed to this method is treated as NS_BASE_STREAM_CLOSED, which
+ * is equivalent to nsIInputStream::close.
+ *
+ * NOTE: this method exists in part to support pipes, which have both an
+ * input end and an output end. If the output end of a pipe is closed, then
+ * reads from the input end of the pipe will fail. The error code returned
+ * when an attempt is made to read from a "closed" pipe corresponds to the
+ * status code passed in when the output end of the pipe is closed, which
+ * greatly simplifies working with pipes in some cases.
+ *
+ * @param aStatus
+ * The error that will be reported if this stream is accessed after
+ * it has been closed.
+ */
+ void closeWithStatus(in nsresult reason);
+
+ /**
+ * Asynchronously wait for the stream to be writable or closed. The
+ * notification is one-shot, meaning that each asyncWait call will result
+ * in exactly one notification callback. After the OnOutputStreamReady event
+ * is dispatched, the stream releases its reference to the
+ * nsIOutputStreamCallback object. It is safe to call asyncWait again from the
+ * notification handler.
+ *
+ * This method may be called at any time (even if write has not been called).
+ * In other words, this method may be called when the stream already has
+ * room for more data. It may also be called when the stream is closed. If
+ * the stream is already writable or closed when AsyncWait is called, then the
+ * OnOutputStreamReady event will be dispatched immediately. Otherwise, the
+ * event will be dispatched when the stream becomes writable or closed.
+ *
+ * @param aCallback
+ * This object is notified when the stream becomes ready.
+ * @param aFlags
+ * This parameter specifies optional flags passed in to configure
+ * the behavior of this method. Pass zero to specify no flags.
+ * @param aRequestedCount
+ * Wait until at least this many bytes can be written. This is only
+ * a suggestion to the underlying stream; it may be ignored. The
+ * caller may pass zero to indicate no preference.
+ * @param aEventTarget
+ * Specify NULL to receive notification on ANY thread (possibly even
+ * recursively on the calling thread -- i.e., synchronously), or
+ * specify that the notification be delivered to a specific event
+ * target.
+ */
+ void asyncWait(in nsIOutputStreamCallback aCallback,
+ in unsigned long aFlags,
+ in unsigned long aRequestedCount,
+ in nsIEventTarget aEventTarget);
+
+ /**
+ * If passed to asyncWait, this flag overrides the default behavior,
+ * causing the OnOutputStreamReady notification to be suppressed until the
+ * stream becomes closed (either as a result of closeWithStatus/close being
+ * called on the stream or possibly due to some error in the underlying
+ * stream).
+ */
+ const unsigned long WAIT_CLOSURE_ONLY = (1<<0);
+};
+
+/**
+ * This is a companion interface for nsIAsyncOutputStream::asyncWait.
+ */
+[scriptable, uuid(40dbcdff-9053-42c5-a57c-3ec910d0f148)]
+interface nsIOutputStreamCallback : nsISupports
+{
+ /**
+ * Called to indicate that the stream is either writable or closed.
+ *
+ * @param aStream
+ * The stream whose asyncWait method was called.
+ */
+ void onOutputStreamReady(in nsIAsyncOutputStream aStream);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl
new file mode 100644
index 00000000..12e4c5f0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(6ccb17a0-e95e-11d1-beae-00805f8a66dc)]
+interface nsIBaseStream : nsISupports
+{
+ /** Close the stream. */
+ void close();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl
new file mode 100644
index 00000000..bc9ea0b5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIInputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * This interface allows consumption of primitive data types from a "binary
+ * stream" containing untagged, big-endian binary data, i.e. as produced by an
+ * implementation of nsIBinaryOutputStream. This might be used, for example,
+ * to implement network protocols or to read from architecture-neutral disk
+ * files, i.e. ones that can be read and written by both big-endian and
+ * little-endian platforms.
+ *
+ * @See nsIBinaryOutputStream
+ */
+
+[scriptable, uuid(7b456cb0-8772-11d3-90cf-0040056a906e)]
+interface nsIBinaryInputStream : nsIInputStream {
+ void setInputStream(in nsIInputStream aInputStream);
+
+ PRBool readBoolean();
+
+ PRUint8 read8();
+ PRUint16 read16();
+ PRUint32 read32();
+ PRUint64 read64();
+
+ float readFloat();
+ double readDouble();
+
+ /**
+ * Read a NUL-terminated 8-bit char* string from a binary stream.
+ */
+ ACString readCString();
+
+ /**
+ * Read a NUL-terminated 16-bit PRUnichar* string from a binary stream.
+ */
+ AString readString();
+
+ /**
+ * Read an opaque byte array from a binary stream.
+ */
+ void readBytes(in PRUint32 aLength,
+ [size_is(aLength), retval] out string aString);
+
+ /**
+ * Read an opaque byte array from a binary stream, storing the results
+ * as an array of PRUint8s.
+ */
+ void readByteArray(in PRUint32 aLength,
+ [array, size_is(aLength), retval] out PRUint8 aBytes);
+};
+
+%{C++
+
+inline nsresult
+NS_ReadOptionalCString(nsIBinaryInputStream* aStream, nsACString& aResult)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv)) {
+ if (nonnull)
+ rv = aStream->ReadCString(aResult);
+ else
+ aResult.Truncate();
+ }
+ return rv;
+}
+
+inline nsresult
+NS_ReadOptionalString(nsIBinaryInputStream* aStream, nsAString& aResult)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv)) {
+ if (nonnull)
+ rv = aStream->ReadString(aResult);
+ else
+ aResult.Truncate();
+ }
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl
new file mode 100644
index 00000000..16a100b7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIOutputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * This interface allows writing of primitive data types (integers,
+ * floating-point values, booleans, etc.) to a stream in a binary, untagged,
+ * fixed-endianness format. This might be used, for example, to implement
+ * network protocols or to produce architecture-neutral binary disk files,
+ * i.e. ones that can be read and written by both big-endian and little-endian
+ * platforms. Output is written in big-endian order (high-order byte first),
+ * as this is traditional network order.
+ *
+ * @See nsIBinaryInputStream
+ */
+
+[scriptable, uuid(204ee610-8765-11d3-90cf-0040056a906e)]
+interface nsIBinaryOutputStream : nsIOutputStream {
+ void setOutputStream(in nsIOutputStream aOutputStream);
+
+ void writeBoolean(in PRBool aBoolean);
+
+ void write8(in PRUint8 aByte);
+ void write16(in PRUint16 a16);
+ void write32(in PRUint32 a32);
+ void write64(in PRUint64 a64);
+
+ void writeFloat(in float aFloat);
+ void writeDouble(in double aDouble);
+
+ /**
+ * Write a NUL-terminated 8-bit char* string to a binary stream.
+ */
+ void writeStringZ(in string aString);
+
+ /**
+ * Write a NUL-terminated 16-bit PRUnichar* string to a binary stream.
+ */
+ void writeWStringZ(in wstring aString);
+
+ /**
+ * Write a NUL-terminated UTF8-encoded string to a binary stream, produced
+ * from a NUL-terminated 16-bit PRUnichar* string argument.
+ */
+ void writeUtf8Z(in wstring aString);
+
+ /**
+ * Write an opaque byte array to a binary stream.
+ */
+ void writeBytes([size_is(aLength)] in string aString, in PRUint32 aLength);
+
+ /**
+ * Write an opaque byte array to a binary stream.
+ */
+ void writeByteArray([array, size_is(aLength)] in PRUint8 aBytes,
+ in PRUint32 aLength);
+
+};
+
+%{C++
+
+inline nsresult
+NS_WriteOptionalStringZ(nsIBinaryOutputStream* aStream, const char* aString)
+{
+ PRBool nonnull = (aString != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteStringZ(aString);
+ return rv;
+}
+
+inline nsresult
+NS_WriteOptionalWStringZ(nsIBinaryOutputStream* aStream, const PRUnichar* aString)
+{
+ PRBool nonnull = (aString != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteWStringZ(aString);
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl
new file mode 100644
index 00000000..a124e923
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIInputStream.idl"
+
+[scriptable, uuid(b5a21556-35fc-4815-aff1-f9142639686e)]
+interface nsIByteArrayInputStream : nsIInputStream
+{
+};
+
+%{C++
+extern NS_COM nsresult
+NS_NewByteArrayInputStream (nsIByteArrayInputStream ** aResult, char * buffer, unsigned long size);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl
new file mode 100644
index 00000000..b32a7f62
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Directory Enumerator Interface.
+ *
+ * The Initial Developer of the Original Code is Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben Goodger <ben@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+/**
+ * This interface provides a means for enumerating the contents of a directory.
+ * It is similar to nsISimpleEnumerator except the retrieved entries are QI'ed
+ * to nsIFile, and there is a mechanism for closing the directory when the
+ * enumeration is complete.
+ *
+ * @status UNDER_REVIEW
+ */
+[scriptable, uuid(31f7f4ae-6916-4f2d-a81e-926a4e3022ee)]
+interface nsIDirectoryEnumerator : nsISupports
+{
+ /**
+ * Retrieves the next file in the sequence. The "nextFile" element is the
+ * first element upon the first call. This attribute is null if there is no
+ * next element.
+ */
+ readonly attribute nsIFile nextFile;
+
+ /**
+ * Closes the directory being enumerated, releasing the system resource.
+ * @throws NS_OK if the call succeeded and the directory was closed.
+ * NS_ERROR_FAILURE if the directory close failed.
+ * It is safe to call this function many times.
+ */
+ void close();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl
new file mode 100644
index 00000000..c34b7aa9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIFile.idl"
+
+/**
+ * nsIDirectoryServiceProvider
+ *
+ * Used by Directory Service to get file locations.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(bbf8cab0-d43a-11d3-8cc2-00609792278c)]
+interface nsIDirectoryServiceProvider: nsISupports
+{
+ /**
+ * getFile
+ *
+ * Directory Service calls this when it gets the first request for
+ * a prop or on every request if the prop is not persistent.
+ *
+ * @param prop The symbolic name of the file.
+ * @param persistent TRUE - The returned file will be cached by Directory
+ * Service. Subsequent requests for this prop will
+ * bypass the provider and use the cache.
+ * FALSE - The provider will be asked for this prop
+ * each time it is requested.
+ *
+ * @return The file represented by the property.
+ *
+ */
+ nsIFile getFile(in string prop, out PRBool persistent);
+};
+
+/**
+ * nsIDirectoryServiceProvider2
+ *
+ * An extension of nsIDirectoryServiceProvider which allows
+ * multiple files to be returned for the given key.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(2f977d4b-5485-11d4-87e2-0010a4e75ef2)]
+interface nsIDirectoryServiceProvider2: nsIDirectoryServiceProvider
+{
+ /**
+ * getFiles
+ *
+ * Directory Service calls this when it gets a request for
+ * a prop and the requested type is nsISimpleEnumerator.
+ *
+ * @param prop The symbolic name of the file list.
+ *
+ * @return An enumerator for a list of file locations.
+ * The elements in the enumeration are nsIFile
+ *
+ */
+ nsISimpleEnumerator getFiles(in string prop);
+};
+
+/**
+ * nsIDirectoryService
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(57a66a60-d43a-11d3-8cc2-00609792278c)]
+interface nsIDirectoryService: nsISupports
+{
+ /**
+ * init
+ *
+ * Must be called. Used internally by XPCOM initialization.
+ *
+ */
+ void init();
+
+ /**
+ * registerProvider
+ *
+ * Register a provider with the service.
+ *
+ * @param prov The service will keep a strong reference
+ * to this object. It will be released when
+ * the service is released.
+ *
+ */
+ void registerProvider(in nsIDirectoryServiceProvider prov);
+
+ /**
+ * unregisterProvider
+ *
+ * Unregister a provider with the service.
+ *
+ * @param prov
+ *
+ */
+ void unregisterProvider(in nsIDirectoryServiceProvider prov);
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl
new file mode 100644
index 00000000..99f5a287
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsrootidl.idl"
+
+interface nsIFile;
+interface nsISimpleEnumerator;
+
+/**
+ * The nsIFastLoadFileControl interface and its subinterfaces are mix-ins for
+ * classes implementing nsIObjectInputStream and nsIObjectOutputStream, so that
+ * those stream types can be used with nsIFastLoadService to access and compute
+ * FastLoad file checksums, update and check FastLoad file dependencies, and
+ * multiplex documents loaded via non-blocking i/o.
+ *
+ * If an nsIObjectInputStream class doesn't support nsIFastLoadReadControl, or
+ * an nsIObjectOutputStream class doesn't support nsIFastLoadWriteControl, that
+ * implementation may still be useful for object serialization, but it can't be
+ * used to read or write a Mozilla FastLoad file.
+ */
+[scriptable, uuid(8a1e2c63-af50-4147-af7e-26289dc180dd)]
+interface nsIFastLoadFileControl : nsISupports
+{
+ /**
+ * Get and set the recorded checksum value from the FastLoad file header.
+ */
+ attribute PRUint32 checksum;
+
+ /**
+ * Multiplexed document control methods. A FastLoad file may contain
+ * multiple interleaved documents identified by a URI specifier string,
+ * and indexed for fast multiplexor select by an opaque URI object key.
+ * You StartMuxedDocument when initiating a document load, then Select
+ * before every batch of calls to (de)serialize document data, and End
+ * when the load completes.
+ *
+ * Document multiplexing is necessary to support incremental FastLoad
+ * development in a non-blocking i/o architecture such as Mozilla, where
+ * some (but not all, at first, or for a while during development) of the
+ * results of parsing and compiling various inputs can be multiplexed to
+ * or from a FastLoad file.
+ *
+ * Note: Select returns the previously selected URI object in case the
+ * caller is synchronously selecting and writing data to the FastLoad
+ * file, so the caller can reselect the previous URI and return to code
+ * the continues to write FastLoad data for the previous URI, unaware of
+ * the nested select/write/reselect.
+ */
+ void startMuxedDocument(in nsISupports aURI, in string aURISpec);
+ nsISupports selectMuxedDocument(in nsISupports aURI);
+ void endMuxedDocument(in nsISupports aURI);
+
+ /**
+ * Return true if aURISpec identifies a muxed document in the FastLoad
+ * file, false otherwise.
+ */
+ boolean hasMuxedDocument(in string aURISpec);
+};
+
+[scriptable, uuid(652ecec6-d40b-45b6-afef-641d6c63a35b)]
+interface nsIFastLoadReadControl : nsIFastLoadFileControl
+{
+ /**
+ * Computes the correct checksum of the FastLoad file, independent of the
+ * header's checksum value. The header checksum field is treated as zero
+ * when computing the checksum.
+ */
+ PRUint32 computeChecksum();
+
+ /**
+ * Get the collection of dependency nsIFile instances recorded during the
+ * FastLoad file write or read/update process, and checked during the read
+ * process to invalidate the FastLoad file if any dependencies are newer.
+ */
+ readonly attribute nsISimpleEnumerator dependencies;
+};
+
+[scriptable, uuid(2ad6e9e6-1379-4e45-a899-a54b27ff915c)]
+interface nsIFastLoadWriteControl : nsIFastLoadFileControl
+{
+ /**
+ * Add a file dependency of the FastLoad file (e.g., a .jar file) to the
+ * set of dependencies that trigger regeneration if any dependency has a
+ * last-modified-time greater than the FastLoad file's mtime.
+ */
+ void addDependency(in nsIFile aFile);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl
new file mode 100644
index 00000000..0b177463
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsrootidl.idl"
+
+interface nsIFastLoadReadControl;
+interface nsIFile;
+interface nsIInputStream;
+interface nsIOutputStream;
+interface nsIObjectInputStream;
+interface nsIObjectOutputStream;
+
+[scriptable, uuid(715577db-d9c5-464a-a32e-0a40c29b22d4)]
+interface nsIFastLoadFileIO : nsISupports
+{
+ readonly attribute nsIInputStream inputStream;
+ readonly attribute nsIOutputStream outputStream;
+};
+
+[scriptable, uuid(759e475e-0c23-4dbf-b1b8-78c9369e3072)]
+interface nsIFastLoadService : nsISupports
+{
+ nsIFile newFastLoadFile(in string aBaseName);
+
+ nsIObjectInputStream newInputStream(in nsIInputStream aSrcStream);
+ nsIObjectOutputStream newOutputStream(in nsIOutputStream aDestStream);
+
+ // Flag values for the direction attribute and the aDirectionFlags
+ // parameter to startMuxedDocument.
+ const PRInt32 NS_FASTLOAD_READ = 1;
+ const PRInt32 NS_FASTLOAD_WRITE = 2;
+
+ attribute nsIObjectInputStream inputStream;
+ attribute nsIObjectOutputStream outputStream;
+ attribute nsIFastLoadFileIO fileIO;
+ readonly attribute PRInt32 direction;
+
+ /**
+ * These methods associate a URI object with its spec, for faster select
+ * using the object pointer as a key, rather than the spec string. The
+ * selectMuxedDocument method returns the previously selected URI object,
+ * in case a caller needs to reselect the previous after muxing data for
+ * a given URI synchronously. For the non-blocking or "asynchronous" i/o
+ * case, the caller must select the source URI from the FastLoad multiplex
+ * before writing a new burst of data parsed from the slow-loaded source.
+ *
+ * Clients of inputStream and outputStream should try to demultiplex data
+ * from the input stream only if fastLoadService->StartMuxedDocument(uri,
+ * urispec, NS_FASTLOAD_READ) succeeds. If StartMuxedDocument fails with
+ * NS_ERROR_NOT_AVAILABLE, callers should slow-load the documents, muxing
+ * their data to the current output stream.
+ */
+ void startMuxedDocument(in nsISupports aURI,
+ in string aURISpec,
+ in PRInt32 aDirectionFlags);
+ nsISupports selectMuxedDocument(in nsISupports aURI);
+ void endMuxedDocument(in nsISupports aURI);
+
+ void addDependency(in nsIFile aFile);
+
+ PRUint32 computeChecksum(in nsIFile aFile,
+ in nsIFastLoadReadControl aControl);
+ void cacheChecksum(in nsIFile aFile,
+ in nsIObjectOutputStream aStream);
+
+ [noscript] void getFastLoadReferent(inout nsISupports aPtr);
+
+ [noscript] void readFastLoadPtr(in nsIObjectInputStream aInputStream,
+ inout nsISupports aPtr);
+
+ [noscript] void writeFastLoadPtr(in nsIObjectOutputStream aOutputStream,
+ in nsISupports aPtr);
+
+ /**
+ * Return true if aURISpec identifies a muxed document in the FastLoad
+ * file, false otherwise.
+ */
+ boolean hasMuxedDocument(in string aURISpec);
+};
+
+%{C++
+#define NS_FASTLOADSERVICE_CLASSNAME "Mozilla FastLoad Service"
+
+#define NS_FASTLOADSERVICE_CID \
+ {0xc943093c,0xac94,0x4bee,{0x84,0x0b,0x8b,0x5a,0x6e,0x31,0x4f,0xa7}}
+
+#define NS_FASTLOADSERVICE_CONTRACTID \
+ "@mozilla.org/fast-load-service;1"
+
+#ifndef nsCOMPtr_h___
+# include "nsCOMPtr.h"
+#endif
+#ifndef __gen_nsIFile_h__
+# include "nsIFile.h"
+#endif
+#ifndef nsIServiceManager_h___
+# include "nsIServiceManager.h"
+#endif
+
+inline const nsGetServiceByCID
+do_GetFastLoadService(nsresult *aResultCode = 0)
+{
+ static NS_DEFINE_CID(kFastLoadServiceCID, NS_FASTLOADSERVICE_CID);
+ return nsGetServiceByCID(kFastLoadServiceCID, nsnull, aResultCode);
+}
+
+inline nsresult
+NS_AddFastLoadDependency(nsIFile* aFile)
+{
+ nsCOMPtr<nsIFastLoadService> fastLoadService(do_GetFastLoadService());
+ if (fastLoadService) {
+ nsresult rv = fastLoadService->AddDependency(aFile);
+ if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
+ return rv;
+ }
+ return NS_OK;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIFile.idl b/src/libs/xpcom18a4/xpcom/io/nsIFile.idl
new file mode 100644
index 00000000..1d70858e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIFile.idl
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsISimpleEnumerator;
+
+/**
+ * This is the only correct cross-platform way to specify a file.
+ * Strings are not such a way. If you grew up on windows or unix, you
+ * may think they are. Welcome to reality.
+ *
+ * All methods with string parameters have two forms. The preferred
+ * form operates on UCS-2 encoded characters strings. An alternate
+ * form operates on characters strings encoded in the "native" charset.
+ *
+ * A string containing characters encoded in the native charset cannot
+ * be safely passed to javascript via xpconnect. Therefore, the "native
+ * methods" are not scriptable.
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(c8c0a080-0868-11d3-915f-d9d889d48e3c)]
+interface nsIFile : nsISupports
+{
+ /**
+ * Create Types
+ *
+ * NORMAL_FILE_TYPE - A normal file.
+ * DIRECTORY_TYPE - A directory/folder.
+ */
+ const unsigned long NORMAL_FILE_TYPE = 0;
+ const unsigned long DIRECTORY_TYPE = 1;
+
+ /**
+ * append[Native]
+ *
+ * This function is used for constructing a descendent of the
+ * current nsIFile.
+ *
+ * @param node
+ * A string which is intended to be a child node of the nsIFile.
+ * For the |appendNative| method, the node must be in the native
+ * filesystem charset.
+ */
+ void append(in AString node);
+ [noscript] void appendNative(in ACString node);
+
+ /**
+ * Normalize the pathName (e.g. removing .. and . components on Unix).
+ */
+ void normalize();
+
+ /**
+ * create
+ *
+ * This function will create a new file or directory in the
+ * file system. Any nodes that have not been created or
+ * resolved, will be. If the file or directory already
+ * exists create() will return NS_ERROR_FILE_ALREADY_EXISTS.
+ *
+ * @param type
+ * This specifies the type of file system object
+ * to be made. The only two types at this time
+ * are file and directory which are defined above.
+ * If the type is unrecongnized, we will return an
+ * error (NS_ERROR_FILE_UNKNOWN_TYPE).
+ *
+ * @param permissions
+ * The unix style octal permissions. This may
+ * be ignored on systems that do not need to do
+ * permissions.
+ */
+ void create(in unsigned long type, in unsigned long permissions);
+
+ /**
+ * Accessor to the leaf name of the file itself.
+ * For the |nativeLeafName| method, the nativeLeafName must
+ * be in the native filesystem charset.
+ */
+ attribute AString leafName;
+ [noscript] attribute ACString nativeLeafName;
+
+ /**
+ * copyTo[Native]
+ *
+ * This will copy this file to the specified newParentDir.
+ * If a newName is specified, the file will be renamed.
+ * If 'this' is not created we will return an error
+ * (NS_ERROR_FILE_TARGET_DOES_NOT_EXIST).
+ *
+ * copyTo may fail if the file already exists in the destination
+ * directory.
+ *
+ * copyTo will NOT resolve aliases/shortcuts during the copy.
+ *
+ * @param newParentDir
+ * This param is the destination directory. If the
+ * newParentDir is null, copyTo() will use the parent
+ * directory of this file. If the newParentDir is not
+ * empty and is not a directory, an error will be
+ * returned (NS_ERROR_FILE_DESTINATION_NOT_DIR). For the
+ * |CopyToNative| method, the newName must be in the
+ * native filesystem charset.
+ *
+ * @param newName
+ * This param allows you to specify a new name for
+ * the file to be copied. This param may be empty, in
+ * which case the current leaf name will be used.
+ */
+ void copyTo(in nsIFile newParentDir, in AString newName);
+ [noscript] void CopyToNative(in nsIFile newParentDir, in ACString newName);
+
+ /**
+ * copyToFollowingLinks[Native]
+ *
+ * This function is identical to copyTo with the exception that,
+ * as the name implies, it follows symbolic links. The XP_UNIX
+ * implementation always follow symbolic links when copying. For
+ * the |CopyToFollowingLinks| method, the newName must be in the
+ * native filesystem charset.
+ */
+ void copyToFollowingLinks(in nsIFile newParentDir, in AString newName);
+ [noscript] void copyToFollowingLinksNative(in nsIFile newParentDir, in ACString newName);
+
+ /**
+ * moveTo[Native]
+ *
+ * A method to move this file or directory to newParentDir.
+ * If a newName is specified, the file or directory will be renamed.
+ * If 'this' is not created we will return an error
+ * (NS_ERROR_FILE_TARGET_DOES_NOT_EXIST).
+ * If 'this' is a file, and the destination file already exists, moveTo
+ * will replace the old file.
+ *
+ * moveTo will NOT resolve aliases/shortcuts during the copy.
+ * moveTo will do the right thing and allow copies across volumes.
+ * moveTo will return an error (NS_ERROR_FILE_DIR_NOT_EMPTY) if 'this' is
+ * a directory and the destination directory is not empty.
+ * moveTo will return an error (NS_ERROR_FILE_ACCESS_DENIED) if 'this' is
+ * a directory and the destination directory is not writable.
+ *
+ * @param newParentDir
+ * This param is the destination directory. If the
+ * newParentDir is empty, moveTo() will rename the file
+ * within its current directory. If the newParentDir is
+ * not empty and does not name a directory, an error will
+ * be returned (NS_ERROR_FILE_DESTINATION_NOT_DIR). For
+ * the |moveToNative| method, the newName must be in the
+ * native filesystem charset.
+ *
+ * @param newName
+ * This param allows you to specify a new name for
+ * the file to be moved. This param may be empty, in
+ * which case the current leaf name will be used.
+ */
+ void moveTo(in nsIFile newParentDir, in AString newName);
+ [noscript] void moveToNative(in nsIFile newParentDir, in ACString newName);
+
+ /**
+ * This will try to delete this file. The 'recursive' flag
+ * must be PR_TRUE to delete directories which are not empty.
+ *
+ * This will not resolve any symlinks.
+ */
+ void remove(in boolean recursive);
+
+ /**
+ * Attributes of nsIFile.
+ */
+
+ attribute unsigned long permissions;
+ attribute unsigned long permissionsOfLink;
+
+ /**
+ * File Times are to be in milliseconds from
+ * midnight (00:00:00), January 1, 1970 Greenwich Mean
+ * Time (GMT).
+ */
+ attribute PRInt64 lastModifiedTime;
+ attribute PRInt64 lastModifiedTimeOfLink;
+
+ /**
+ * WARNING! On the Mac, getting/setting the file size with nsIFile
+ * only deals with the size of the data fork. If you need to
+ * know the size of the combined data and resource forks use the
+ * GetFileSizeWithResFork() method defined on nsILocalFileMac.
+ */
+ attribute PRInt64 fileSize;
+ readonly attribute PRInt64 fileSizeOfLink;
+
+ /**
+ * target & path
+ *
+ * Accessor to the string path. The native version of these
+ * strings are not guaranteed to be a usable path to pass to
+ * NSPR or the C stdlib. There are problems that affect
+ * platforms on which a path does not fully specify a file
+ * because two volumes can have the same name (e.g., XP_MAC).
+ * This is solved by holding "private", native data in the
+ * nsIFile implementation. This native data is lost when
+ * you convert to a string.
+ *
+ * DO NOT PASS TO USE WITH NSPR OR STDLIB!
+ *
+ * target
+ * Find out what the symlink points at. Will give error
+ * (NS_ERROR_FILE_INVALID_PATH) if not a symlink.
+ *
+ * path
+ * Find out what the nsIFile points at.
+ *
+ * Note that the ACString attributes are returned in the
+ * native filesystem charset.
+ *
+ */
+ readonly attribute AString target;
+ [noscript] readonly attribute ACString nativeTarget;
+ readonly attribute AString path;
+ [noscript] readonly attribute ACString nativePath;
+
+ boolean exists();
+ boolean isWritable();
+ boolean isReadable();
+ boolean isExecutable();
+ boolean isHidden();
+ boolean isDirectory();
+ boolean isFile();
+ boolean isSymlink();
+ /**
+ * Not a regular file, not a directory, not a symlink.
+ */
+ boolean isSpecial();
+
+ /**
+ * createUnique
+ *
+ * This function will create a new file or directory in the
+ * file system. Any nodes that have not been created or
+ * resolved, will be. If this file already exists, we try
+ * variations on the leaf name "suggestedName" until we find
+ * one that did not already exist.
+ *
+ * If the search for nonexistent files takes too long
+ * (thousands of the variants already exist), we give up and
+ * return NS_ERROR_FILE_TOO_BIG.
+ *
+ * @param type
+ * This specifies the type of file system object
+ * to be made. The only two types at this time
+ * are file and directory which are defined above.
+ * If the type is unrecongnized, we will return an
+ * error (NS_ERROR_FILE_UNKNOWN_TYPE).
+ *
+ * @param permissions
+ * The unix style octal permissions. This may
+ * be ignored on systems that do not need to do
+ * permissions.
+ */
+ void createUnique(in unsigned long type, in unsigned long permissions);
+
+ /**
+ * clone()
+ *
+ * This function will allocate and initialize a nsIFile object to the
+ * exact location of the |this| nsIFile.
+ *
+ * @param file
+ * A nsIFile which this object will be initialize
+ * with.
+ *
+ */
+ nsIFile clone();
+
+ /**
+ * Will determine if the inFile equals this.
+ */
+ boolean equals(in nsIFile inFile);
+
+ /**
+ * Will determine if inFile is a descendant of this file
+ * If |recur| is true, look in subdirectories too
+ */
+ boolean contains(in nsIFile inFile, in boolean recur);
+
+ /**
+ * Parent will be null when this is at the top of the volume.
+ */
+ readonly attribute nsIFile parent;
+
+ /**
+ * Returns an enumeration of the elements in a directory. Each
+ * element in the enumeration is an nsIFile.
+ *
+ * @return NS_ERROR_FILE_NOT_DIRECTORY if the current nsIFile does
+ * not specify a directory.
+ */
+ readonly attribute nsISimpleEnumerator directoryEntries;
+};
+
+%{C++
+#ifndef MOZILLA_STRICT_API
+#include "nsDirectoryServiceUtils.h"
+#endif
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl
new file mode 100644
index 00000000..827f6363
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Warren Harris <warren@netscape.com>
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIInputStream;
+
+%{C++
+/**
+ * The signature of the writer function passed to ReadSegments. This
+ * is the "consumer" of data that gets read from the stream's buffer.
+ *
+ * @param aInStream stream being read
+ * @param aClosure opaque parameter passed to ReadSegments
+ * @param aFromSegment pointer to memory owned by the input stream
+ * @param aToOffset amount already read (since ReadSegments was called)
+ * @param aCount length of fromSegment
+ * @param aWriteCount number of bytes read
+ *
+ * Implementers should return the following:
+ *
+ * @return NS_OK and (*aWriteCount > 0) if consumed some data
+ * @return <any-error> if not interested in consuming any data
+ *
+ * Errors are never passed to the caller of ReadSegments.
+ *
+ * NOTE: returning NS_OK and (*aWriteCount = 0) has undefined behavior.
+ *
+ * @status FROZEN
+ */
+typedef NS_CALLBACK(nsWriteSegmentFun)(nsIInputStream *aInStream,
+ void *aClosure,
+ const char *aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount);
+%}
+
+native nsWriteSegmentFun(nsWriteSegmentFun);
+
+/**
+ * nsIInputStream
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(fa9c7f6c-61b3-11d4-9877-00c04fa0cf4a)]
+interface nsIInputStream : nsISupports
+{
+ /**
+ * Close the stream.
+ */
+ void close();
+
+ /**
+ * @return number of bytes currently available in the stream
+ */
+ unsigned long available();
+
+ /**
+ * Read data from the stream.
+ *
+ * @param aBuf the buffer into which the data is to be read
+ * @param aCount the maximum number of bytes to be read
+ *
+ * @return number of bytes read (may be less than aCount).
+ * @return 0 if reached end of file
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ */
+ [noscript] unsigned long read(in charPtr aBuf, in unsigned long aCount);
+
+ /**
+ * Low-level read method that has access to the stream's underlying buffer.
+ * The writer function may be called multiple times for segmented buffers.
+ * ReadSegments is expected to keep calling the writer until either there is
+ * nothing left to read or the writer returns an error. ReadSegments should
+ * not call the writer with zero bytes to consume.
+ *
+ * @param aWriter the "consumer" of the data to be read
+ * @param aClosure opaque parameter passed to writer
+ * @param aCount the maximum number of bytes to be read
+ *
+ * @return number of bytes read (may be less than aCount)
+ * @return 0 if reached end of file (or if aWriter refused to consume data)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ *
+ * NOTE: this function may be unimplemented if a stream has no underlying
+ * buffer (e.g., socket input stream).
+ */
+ [noscript] unsigned long readSegments(in nsWriteSegmentFun aWriter,
+ in voidPtr aClosure,
+ in unsigned long aCount);
+
+ /**
+ * @return true if stream is non-blocking
+ */
+ boolean isNonBlocking();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl b/src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl
new file mode 100644
index 00000000..524e7ee2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIInputStream.idl"
+
+interface nsIOutputStream;
+
+/**
+ * A nsIInputStreamTee is a wrapper for an input stream, that when read
+ * reads the specified amount of data from its |source| and copies that
+ * data to its |sink|. |sink| must be a blocking output stream.
+ */
+[scriptable, uuid(44e8b2c8-1ecb-4a63-8b23-3e3500c34f32)]
+interface nsIInputStreamTee : nsIInputStream
+{
+ attribute nsIInputStream source;
+ attribute nsIOutputStream sink;
+};
+
+%{C++
+// factory method
+extern NS_COM nsresult
+NS_NewInputStreamTee(nsIInputStream **tee, // read from this input stream
+ nsIInputStream *source,
+ nsIOutputStream *sink);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl
new file mode 100644
index 00000000..23781dc4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Boris Zbarsky <bzbarsky@mit.edu>.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsILineInputStream;
+
+[scriptable, uuid(c97b466c-1e6e-4773-a4ab-2b2b3190a7a6)]
+interface nsILineInputStream : nsISupports
+{
+ /**
+ * Read a single line from the stream, where a line is a
+ * possibly zero length sequence of 8bit chars terminated by a
+ * CR, LF, CRLF, LFCR, or eof.
+ * The line terminator is not returned.
+ * Return false for end of file, true otherwise
+ */
+ boolean readLine(out ACString aLine);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl b/src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl
new file mode 100644
index 00000000..8d7a1dda
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIFile.idl"
+
+%{C++
+#include "prio.h"
+#include "prlink.h"
+#include <stdio.h>
+%}
+
+[ptr] native PRFileDescStar(PRFileDesc);
+[ptr] native PRLibraryStar(PRLibrary);
+[ptr] native FILE(FILE);
+
+/**
+ * This interface adds methods to nsIFile that are particular to a file
+ * that is accessible via the local file system.
+ *
+ * It follows the same string conventions as nsIFile.
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(aa610f20-a889-11d3-8c81-000064657374)]
+interface nsILocalFile : nsIFile
+{
+ /**
+ * initWith[Native]Path
+ *
+ * This function will initialize the nsILocalFile object. Any
+ * internal state information will be reset.
+ *
+ * NOTE: This function has a known bug on the macintosh and
+ * other OSes which do not represent file locations as paths.
+ * If you do use this function, be very aware of this problem!
+ *
+ * @param filePath
+ * A string which specifies a full file path to a
+ * location. Relative paths will be treated as an
+ * error (NS_ERROR_FILE_UNRECOGNIZED_PATH). For
+ * initWithNativePath, the filePath must be in the native
+ * filesystem charset.
+ */
+ void initWithPath(in AString filePath);
+ [noscript] void initWithNativePath(in ACString filePath);
+
+ /**
+ * initWithFile
+ *
+ * Initialize this object with another file
+ *
+ * @param aFile
+ * the file this becomes equivalent to
+ */
+ void initWithFile(in nsILocalFile aFile);
+
+ /**
+ * followLinks
+ *
+ * This attribute will determine if the nsLocalFile will auto
+ * resolve symbolic links. By default, this value will be false
+ * on all non unix systems. On unix, this attribute is effectively
+ * a noop.
+ */
+ attribute PRBool followLinks;
+
+ [noscript] PRFileDescStar openNSPRFileDesc(in long flags, in long mode);
+ [noscript] FILE openANSIFileDesc(in string mode);
+
+ [noscript] PRLibraryStar load();
+
+ readonly attribute PRInt64 diskSpaceAvailable;
+
+ /**
+ * appendRelative[Native]Path
+ *
+ * Append a relative path to the current path of the nsILocalFile object.
+ *
+ * @param relativeFilePath
+ * relativeFilePath is a native relative path. For security reasons,
+ * this cannot contain .. or cannot start with a directory separator.
+ * For the |appendRelativeNativePath| method, the relativeFilePath
+ * must be in the native filesystem charset.
+ */
+ void appendRelativePath(in AString relativeFilePath);
+ [noscript] void appendRelativeNativePath(in ACString relativeFilePath);
+
+ /**
+ * Accessor to a null terminated string which will specify
+ * the file in a persistent manner for disk storage.
+ *
+ * The character set of this attribute is undefined. DO NOT TRY TO
+ * INTERPRET IT AS HUMAN READABLE TEXT!
+ */
+ attribute ACString persistentDescriptor;
+
+ /**
+ * reveal
+ *
+ * Ask the operating system to open the folder which contains
+ * this file or folder. This routine only works on platforms which
+ * support the ability to open a folder...
+ */
+ void reveal();
+
+ /**
+ * launch
+ *
+ * Ask the operating system to attempt to open the file.
+ * this really just simulates "double clicking" the file on your platform.
+ * This routine only works on platforms which support this functionality.
+ */
+ void launch();
+
+ /**
+ * getRelativeDescriptor
+ *
+ * Returns a relative file path in an opaque, XP format. It is therefore
+ * not a native path.
+ *
+ * The character set of the string returned from this function is
+ * undefined. DO NOT TRY TO INTERPRET IT AS HUMAN READABLE TEXT!
+ *
+ * @param fromFile
+ * the file from which the descriptor is relative.
+ * There is no defined result if this param is null.
+ */
+ ACString getRelativeDescriptor(in nsILocalFile fromFile);
+
+ /**
+ * setRelativeDescriptor
+ *
+ * Initializes the file to the location relative to fromFile using
+ * a string returned by getRelativeDescriptor.
+ *
+ * @param fromFile
+ * the file to which the descriptor is relative
+ * @param relative
+ * the relative descriptor obtained from getRelativeDescriptor
+ */
+ void setRelativeDescriptor(in nsILocalFile fromFile, in ACString relativeDesc);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl b/src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl
new file mode 100644
index 00000000..e04ea7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.com>
+ * Mark Mentovai <mark@moxienet.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 "nsILocalFile.idl"
+
+%{C++
+#include <Files.h>
+#include <CFURL.h>
+%}
+
+ native OSType(OSType);
+ native FSSpec(FSSpec);
+[ptr] native FSSpecPtr(FSSpec);
+ native FSRef(FSRef);
+[ptr] native FSRefPtr(FSRef);
+ native CFURLRef(CFURLRef);
+
+[scriptable, uuid(748f3ffe-27d9-4402-9de9-494badbeebf4)]
+interface nsILocalFileMac : nsILocalFile
+{
+ /**
+ * initWithCFURL
+ *
+ * Init this object with a CFURLRef
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ * NOTE: If the path of the CFURL is /a/b/c, at least a/b must exist beforehand.
+ *
+ * @param aCFURL the CoreFoundation URL
+ *
+ */
+ [noscript] void initWithCFURL(in CFURLRef aCFURL);
+
+ /**
+ * initWithFSRef
+ *
+ * Init this object with an FSRef
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ *
+ * @param aFSRef the native file spec
+ *
+ */
+ [noscript] void initWithFSRef([const] in FSRefPtr aFSRef);
+
+ /**
+ * initWithFSSpec
+ *
+ * Init this object with an FSSpec
+ * Legacy method - leaving in place for now
+ *
+ * @param aFileSpec the native file spec
+ *
+ */
+ [noscript] void initWithFSSpec([const] in FSSpecPtr aFileSpec);
+
+ /**
+ * initToAppWithCreatorCode
+ *
+ * Init this object to point to an application having the given
+ * creator code. If this app is missing, this will fail. It will first
+ * look for running application with the given creator.
+ *
+ * @param aAppCreator the signature of the app
+ *
+ */
+ [noscript] void initToAppWithCreatorCode(in OSType aAppCreator);
+
+ /**
+ * getCFURL
+ *
+ * Returns the CFURLRef of the file object. The caller is
+ * responsible for calling CFRelease() on it.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ *
+ * @return
+ *
+ */
+ [noscript] CFURLRef getCFURL();
+
+ /**
+ * getFSRef
+ *
+ * Returns the FSRef of the file object.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ *
+ * @return
+ *
+ */
+ [noscript] FSRef getFSRef();
+
+ /**
+ * getFSSpec
+ *
+ * Returns the FSSpec of the file object.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * @return
+ *
+ */
+ [noscript] FSSpec getFSSpec();
+
+ /**
+ * fileSizeWithResFork
+ *
+ * Returns the combined size of both the data fork and the resource
+ * fork (if present) rather than just the size of the data fork
+ * as returned by GetFileSize()
+ *
+ */
+ readonly attribute PRInt64 fileSizeWithResFork;
+
+ /**
+ * Use with SetFileType() to specify the signature of current process
+ */
+ const unsigned long CURRENT_PROCESS_CREATOR = 0x8000000;
+
+ /**
+ * fileType, creator
+ *
+ * File type and creator attributes
+ *
+ */
+ [noscript] attribute OSType fileType;
+ [noscript] attribute OSType fileCreator;
+
+ /**
+ * setFileTypeAndCreatorFromMIMEType
+ *
+ * Sets the file type and creator code from a MIME type.
+ * Internet Config is used to determine the mapping.
+ *
+ * @param aMIMEType
+ *
+ */
+ void setFileTypeAndCreatorFromMIMEType(in string aMIMEType);
+
+ /**
+ * setFileTypeAndCreatorFromExtension
+ *
+ * Sets the file type and creator code from a file extension
+ * Internet Config is used to determine the mapping.
+ *
+ * @param aExtension
+ *
+ */
+ void setFileTypeAndCreatorFromExtension(in string aExtension);
+
+ /**
+ * launchWithDoc
+ *
+ * Launch the application that this file points to with a document.
+ *
+ * @param aDocToLoad Must not be NULL. If no document, use nsILocalFile::launch
+ * @param aLaunchInBackground TRUE if the application should not come to the front.
+ *
+ */
+ void launchWithDoc(in nsILocalFile aDocToLoad, in boolean aLaunchInBackground);
+
+ /**
+ * openDocWithApp
+ *
+ * Open the document that this file points to with the given application.
+ *
+ * @param aAppToOpenWith The application with which to open the document.
+ * If NULL, the creator code of the document is used
+ * to determine the application.
+ * @param aLaunchInBackground TRUE if the application should not come to the front.
+ *
+ */
+ void openDocWithApp(in nsILocalFile aAppToOpenWith, in boolean aLaunchInBackground);
+
+ /**
+ * isPackage
+ *
+ * returns true if a directory is determined to be a package under Mac OS 9/X
+ *
+ */
+ boolean isPackage();
+
+ /**
+ * bundleDisplayName
+ *
+ * returns the display name of the application bundle (usually the human
+ * readable name of the application)
+ */
+ readonly attribute AString bundleDisplayName;
+
+ /**
+ * bundleIdentifier
+ *
+ * returns the identifier of the bundle
+ */
+ readonly attribute AUTF8String bundleIdentifier;
+};
+
+%{C++
+extern "C"
+{
+
+#ifndef XP_MACOSX
+NS_EXPORT const char* NS_TruncNodeName(const char *aNode, char *outBuf);
+#endif
+
+NS_EXPORT nsresult NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followSymlinks, nsILocalFileMac* *result);
+
+// NS_NewLocalFileWithFSRef is available since Mozilla 1.8.1.
+NS_EXPORT nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowSymlinks, nsILocalFileMac** result);
+}
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl b/src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl
new file mode 100644
index 00000000..95b4177b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Richard L. Walsh.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Rich Walsh <dragtext@e-vertise.com> (Original Author)
+ *
+ * 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 "nsILocalFile.idl"
+
+interface nsIArray;
+
+[scriptable, uuid(26de2089-239d-4697-818b-bae1fe8e8e0d)]
+interface nsILocalFileOS2 : nsILocalFile
+{
+ /**
+ * getFileTypes
+ *
+ * Returns the file's .TYPE extended attribute as an array of
+ * nsISupportsCStrings.
+ *
+ */
+ nsIArray getFileTypes( );
+
+ /**
+ * setFileTypes
+ *
+ * Sets the file's .TYPE extended attribute from a comma-separated
+ * list of types (this format is used because clients are unlikely
+ * to write more than a single type).
+ * @param fileTypes
+ * a string in the filesystem's native character set
+ *
+ */
+ void setFileTypes( in ACString fileTypes );
+
+ /**
+ * isFileType
+ *
+ * Returns TRUE if the file has a .TYPE extended attribute that
+ * matches the string passed in. The comparison is case-sensitive.
+ * @param fileType
+ * a string in the filesystem's native character set
+ *
+ */
+ PRBool isFileType( in ACString fileType );
+
+ /**
+ * setFileSource
+ *
+ * Identifies the origin of a downloaded file by writing the
+ * source URI's spec to the .SUBJECT extended attribute.
+ *
+ * @param aURI
+ * the source URI
+ *
+ */
+ void setFileSource( in AUTF8String aURI );
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl
new file mode 100644
index 00000000..ec309ecd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is frightening to behold.
+ *
+ * The Initial Developer of the Original Code is
+ * Jonas Sicking.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jonas Sicking <sicking@bigfoot.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 "nsIInputStream.idl"
+
+/**
+ * The multiplex stream concatinates a list of input streams into a single
+ * stream.
+ */
+
+[scriptable, uuid(a076fd12-1dd1-11b2-b19a-d53b5dffaade)]
+interface nsIMultiplexInputStream : nsIInputStream
+{
+ /**
+ * Number of streams in this multiplex-stream
+ */
+ readonly attribute unsigned long count;
+
+ /**
+ * Appends a stream to the end of the streams. The cursor of the stream
+ * should be located at the beginning of the stream if the implementation
+ * of this nsIMultiplexInputStream also is used as an nsISeekableStream.
+ * @param stream stream to append
+ */
+ void appendStream(in nsIInputStream stream);
+
+ /**
+ * Insert a stream at specified index. If the cursor of this stream is at
+ * the beginning of the stream at index, the cursor will be placed at the
+ * beginning of the inserted stream instead.
+ * The cursor of the new stream should be located at the beginning of the
+ * stream if the implementation of this nsIMultiplexInputStream also is
+ * used as an nsISeekableStream.
+ * @param stream stream to insert
+ * @param index index to insert stream at, must be <= count
+ */
+ void insertStream(in nsIInputStream stream, in unsigned long index);
+
+ /**
+ * Remove stream at specified index. If this stream is the one currently
+ * being read the readcursor is moved to the beginning of the next
+ * stream
+ * @param index remove stream at this index, must be < count
+ */
+ void removeStream(in unsigned long index);
+
+ /**
+ * Get stream at specified index.
+ * @param index return stream at this index, must be < count
+ * @return stream at specified index
+ */
+ nsIInputStream getStream(in unsigned long index);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl
new file mode 100644
index 00000000..97c0ca6e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIBinaryInputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * @see nsIObjectOutputStream
+ * @see nsIBinaryInputStream
+ */
+
+[scriptable, uuid(6c248606-4eae-46fa-9df0-ba58502368eb)]
+interface nsIObjectInputStream : nsIBinaryInputStream
+{
+ /**
+ * Read an object from this stream to satisfy a strong or weak reference
+ * to one of its interfaces. If the interface was not along the primary
+ * inheritance chain ending in the "root" or XPCOM-identity nsISupports,
+ * readObject will QueryInterface from the deserialized object root to the
+ * correct interface, which was specified when the object was serialized.
+ *
+ * @see nsIObjectOutputStream
+ */
+ nsISupports readObject(in PRBool aIsStrongRef);
+
+ [notxpcom] nsresult readID(out nsID aID);
+
+ /**
+ * Optimized deserialization support -- see nsIStreamBufferAccess.idl.
+ */
+ [notxpcom] charPtr getBuffer(in PRUint32 aLength, in PRUint32 aAlignMask);
+ [notxpcom] void putBuffer(in charPtr aBuffer, in PRUint32 aLength);
+};
+
+%{C++
+
+inline nsresult
+NS_ReadOptionalObject(nsIObjectInputStream* aStream, PRBool aIsStrongRef,
+ nsISupports* *aResult)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv)) {
+ if (nonnull)
+ rv = aStream->ReadObject(aIsStrongRef, aResult);
+ else
+ *aResult = nsnull;
+ }
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl
new file mode 100644
index 00000000..b8072127
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIBinaryOutputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * @See nsIObjectInputStream
+ * @See nsIBinaryOutputStream
+ */
+
+[scriptable, uuid(92c898ac-5fde-4b99-87b3-5d486422094b)]
+interface nsIObjectOutputStream : nsIBinaryOutputStream
+{
+ /**
+ * Write the object whose "root" or XPCOM-identity nsISupports is aObject.
+ * The cause for writing this object is a strong or weak reference, so the
+ * aIsStrongRef argument must tell which kind of pointer is being followed
+ * here during serialization.
+ *
+ * If the object has only one strong reference in the serialization and no
+ * weak refs, use writeSingleRefObject. This is a valuable optimization:
+ * it saves space in the stream, and cycles on both ends of the process.
+ *
+ * If the reference being serialized is a pointer to an interface not on
+ * the primary inheritance chain ending in the root nsISupports, you must
+ * call writeCompoundObject instead of this method.
+ */
+ void writeObject(in nsISupports aObject, in PRBool aIsStrongRef);
+
+ /**
+ * Write an object referenced singly and strongly via its root nsISupports
+ * or a subclass of its root nsISupports. There must not be other refs to
+ * aObject in memory, or in the serialization.
+ */
+ void writeSingleRefObject(in nsISupports aObject);
+
+ /**
+ * Write the object referenced by an interface pointer at aObject that
+ * inherits from a non-primary nsISupports, i.e., a reference to one of
+ * the multiply inherited interfaces derived from an nsISupports other
+ * than the root or XPCOM-identity nsISupports; or a reference to an
+ * inner object in the case of true XPCOM aggregation. aIID identifies
+ * this interface.
+ */
+ void writeCompoundObject(in nsISupports aObject,
+ in nsIIDRef aIID,
+ in PRBool aIsStrongRef);
+
+ void writeID(in nsIDRef aID);
+
+ /**
+ * Optimized serialization support -- see nsIStreamBufferAccess.idl.
+ */
+ [notxpcom] charPtr getBuffer(in PRUint32 aLength, in PRUint32 aAlignMask);
+ [notxpcom] void putBuffer(in charPtr aBuffer, in PRUint32 aLength);
+};
+
+%{C++
+
+inline nsresult
+NS_WriteOptionalObject(nsIObjectOutputStream* aStream, nsISupports* aObject,
+ PRBool aIsStrongRef)
+{
+ PRBool nonnull = (aObject != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteObject(aObject, aIsStrongRef);
+ return rv;
+}
+
+inline nsresult
+NS_WriteOptionalSingleRefObject(nsIObjectOutputStream* aStream,
+ nsISupports* aObject)
+{
+ PRBool nonnull = (aObject != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteSingleRefObject(aObject);
+ return rv;
+}
+
+inline nsresult
+NS_WriteOptionalCompoundObject(nsIObjectOutputStream* aStream,
+ nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef)
+{
+ PRBool nonnull = (aObject != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteCompoundObject(aObject, aIID, aIsStrongRef);
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl
new file mode 100644
index 00000000..66b2d6e6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Darin Fisher <darin@netscape.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 "nsISupports.idl"
+
+interface nsIInputStream;
+interface nsIInputStreamObserver;
+
+[scriptable, uuid(6f489efe-1dd2-11b2-af78-fb84ae21591b)]
+interface nsIObservableInputStream : nsISupports
+{
+ /**
+ * Allows users to set an observer on an input stream to receive notifications
+ * about the consumer emptying the input stream's underlying buffer, or closing the
+ * stream. This is necessary for non-blocking streams so that the producer can suspend
+ * itself until more data can be written.
+ */
+ attribute nsIInputStreamObserver observer;
+};
+
+[scriptable, uuid(019d67cc-61b4-11d4-9877-00c04fa0cf4a)]
+interface nsIInputStreamObserver : nsISupports
+{
+ /**
+ * Called when the input stream's consumer has read all the existing data from the stream.
+ */
+ void onEmpty(in nsIInputStream inStr);
+
+ /**
+ * Called when the consumer closes its end of the stream.
+ */
+ void onClose(in nsIInputStream inStr);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl
new file mode 100644
index 00000000..4cdab3c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Darin Fisher <darin@netscape.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 "nsISupports.idl"
+
+interface nsIOutputStream;
+interface nsIOutputStreamObserver;
+
+[scriptable, uuid(15b374f8-1dd2-11b2-87ab-c3299d704fd3)]
+interface nsIObservableOutputStream : nsISupports
+{
+ /**
+ * Allows users to set an observer on an input stream to receive notifications
+ * about the consumer emptying the input stream's underlying buffer, or closing the
+ * stream. This is necessary for non-blocking streams so that the producer can suspend
+ * itself until more data can be written.
+ */
+ attribute nsIOutputStreamObserver observer;
+};
+
+[scriptable, uuid(12314194-61b4-11d4-9877-00c04fa0cf4a)]
+interface nsIOutputStreamObserver : nsISupports
+{
+ /**
+ * Called when the output stream's producer has written more data into the stream.
+ */
+ void onWrite(in nsIOutputStream outStr, in unsigned long amount);
+
+ /**
+ * Called when the stream's underlying buffer becomes full.
+ */
+ void onFull(in nsIOutputStream outStr);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl
new file mode 100644
index 00000000..ec5035c6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Warren Harris <warren@netscape.com>
+ * Darin Fisher <darin@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIOutputStream;
+interface nsIInputStream;
+
+%{C++
+/**
+ * The signature for the reader function passed to WriteSegments. This
+ * is the "provider" of data that gets written into the stream's buffer.
+ *
+ * @param aOutStream stream being written to
+ * @param aClosure opaque parameter passed to WriteSegments
+ * @param aToSegment pointer to memory owned by the output stream
+ * @param aFromOffset amount already written (since WriteSegments was called)
+ * @param aCount length of toSegment
+ * @param aReadCount number of bytes written
+ *
+ * Implementers should return the following:
+ *
+ * @return NS_OK and (*aReadCount > 0) if successfully provided some data
+ * @return NS_OK and (*aReadCount = 0) or
+ * @return <any-error> if not interested in providing any data
+ *
+ * Errors are never passed to the caller of WriteSegments.
+ *
+ * @status FROZEN
+ */
+typedef NS_CALLBACK(nsReadSegmentFun)(nsIOutputStream *aOutStream,
+ void *aClosure,
+ char *aToSegment,
+ PRUint32 aFromOffset,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+%}
+
+native nsReadSegmentFun(nsReadSegmentFun);
+
+/**
+ * nsIOutputStream
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(0d0acd2a-61b4-11d4-9877-00c04fa0cf4a)]
+interface nsIOutputStream : nsISupports
+{
+ /**
+ * Close the stream. Forces the output stream to flush any buffered data.
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if unable to flush without blocking
+ * the calling thread (non-blocking mode only)
+ */
+ void close();
+
+ /**
+ * Flush the stream.
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if unable to flush without blocking
+ * the calling thread (non-blocking mode only)
+ */
+ void flush();
+
+ /**
+ * Write data into the stream.
+ *
+ * @param aBuf the buffer containing the data to be written
+ * @param aCount the maximum number of bytes to be written
+ *
+ * @return number of bytes written (may be less than aCount)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ */
+ unsigned long write(in string aBuf, in unsigned long aCount);
+
+ /**
+ * Writes data into the stream from an input stream.
+ *
+ * @param aFromStream the stream containing the data to be written
+ * @param aCount the maximum number of bytes to be written
+ *
+ * @return number of bytes written (may be less than aCount)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ *
+ * NOTE: This method is defined by this interface in order to allow the
+ * output stream to efficiently copy the data from the input stream into
+ * its internal buffer (if any). If this method was provided as an external
+ * facility, a separate char* buffer would need to be used in order to call
+ * the output stream's other Write method.
+ */
+ unsigned long writeFrom(in nsIInputStream aFromStream,
+ in unsigned long aCount);
+
+ /**
+ * Low-level write method that has access to the stream's underlying buffer.
+ * The reader function may be called multiple times for segmented buffers.
+ * WriteSegments is expected to keep calling the reader until either there
+ * is nothing left to write or the reader returns an error. WriteSegments
+ * should not call the reader with zero bytes to provide.
+ *
+ * @param aReader the "provider" of the data to be written
+ * @param aClosure opaque parameter passed to reader
+ * @param aCount the maximum number of bytes to be written
+ *
+ * @return number of bytes written (may be less than aCount)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ *
+ * NOTE: this function may be unimplemented if a stream has no underlying
+ * buffer (e.g., socket output stream).
+ */
+ [noscript] unsigned long writeSegments(in nsReadSegmentFun aReader,
+ in voidPtr aClosure,
+ in unsigned long aCount);
+
+ /**
+ * @return true if stream is non-blocking
+ *
+ * NOTE: writing to a blocking output stream will block the calling thread
+ * until all given data can be consumed by the stream.
+ */
+ boolean isNonBlocking();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIPipe.idl b/src/libs/xpcom18a4/xpcom/io/nsIPipe.idl
new file mode 100644
index 00000000..bbe3d978
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIPipe.idl
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIAsyncInputStream.idl"
+#include "nsIAsyncOutputStream.idl"
+
+interface nsIMemory;
+
+/**
+ * nsIPipe represents an in-process buffer that can be read using nsIInputStream
+ * and written using nsIOutputStream. The reader and writer of a pipe do not
+ * have to be on the same thread. As a result, the pipe is an ideal mechanism
+ * to bridge data exchange between two threads. For example, a worker thread
+ * might write data to a pipe from which the main thread will read.
+ *
+ * Each end of the pipe can be either blocking or non-blocking. Recall that a
+ * non-blocking stream will return NS_BASE_STREAM_WOULD_BLOCK if it cannot be
+ * read or written to without blocking the calling thread. For example, if you
+ * try to read from an empty pipe that has not yet been closed, then if that
+ * pipe's input end is non-blocking, then the read call will fail immediately
+ * with NS_BASE_STREAM_WOULD_BLOCK as the error condition. However, if that
+ * pipe's input end is blocking, then the read call will not return until the
+ * pipe has data or until the pipe is closed. This example presumes that the
+ * pipe is being filled asynchronously on some background thread.
+ *
+ * The pipe supports nsIAsyncInputStream and nsIAsyncOutputStream, which give
+ * the user of a non-blocking pipe the ability to wait for the pipe to become
+ * ready again. For example, in the case of an empty non-blocking pipe, the
+ * user can call AsyncWait on the input end of the pipe to be notified when
+ * the pipe has data to read (or when the pipe becomes closed).
+ *
+ * NS_NewPipe2 and NS_NewPipe provide convenient pipe constructors. In most
+ * cases nsIPipe is not actually used. It is usually enough to just get
+ * references to the pipe's input and output end. In which case, the pipe is
+ * automatically closed when the respective pipe ends are released.
+ */
+[scriptable, uuid(f4211abc-61b3-11d4-9877-00c04fa0cf4a)]
+interface nsIPipe : nsISupports
+{
+ /**
+ * initialize this pipe
+ */
+ void init(in boolean nonBlockingInput,
+ in boolean nonBlockingOutput,
+ in unsigned long segmentSize,
+ in unsigned long segmentCount,
+ in nsIMemory segmentAllocator);
+
+ /**
+ * The pipe's input end, which also implements nsISearchableInputStream.
+ */
+ readonly attribute nsIAsyncInputStream inputStream;
+
+ /**
+ * The pipe's output end.
+ */
+ readonly attribute nsIAsyncOutputStream outputStream;
+};
+
+/**
+ * XXX this interface doesn't really belong in here. It is here because
+ * currently nsPipeInputStream is the only implementation of this interface.
+ */
+[scriptable, uuid(8C39EF62-F7C9-11d4-98F5-001083010E9B)]
+interface nsISearchableInputStream : nsISupports
+{
+ /**
+ * Searches for a string in the input stream. Since the stream has a notion
+ * of EOF, it is possible that the string may at some time be in the
+ * buffer, but is is not currently found up to some offset. Consequently,
+ * both the found and not found cases return an offset:
+ * if found, return offset where it was found
+ * if not found, return offset of the first byte not searched
+ * In the case the stream is at EOF and the string is not found, the first
+ * byte not searched will correspond to the length of the buffer.
+ */
+ void search(in string forString,
+ in boolean ignoreCase,
+ out boolean found,
+ out unsigned long offsetSearchedTo);
+};
+
+%{C++
+
+/**
+ * NS_NewPipe2
+ *
+ * This function supercedes NS_NewPipe. It differs from NS_NewPipe in two
+ * major ways:
+ * (1) returns nsIAsyncInputStream and nsIAsyncOutputStream, so it is
+ * not necessary to QI in order to access these interfaces.
+ * (2) the size of the pipe is determined by the number of segments
+ * times the size of each segment.
+ *
+ * @param pipeIn
+ * resulting input end of the pipe
+ * @param pipeOut
+ * resulting output end of the pipe
+ * @param nonBlockingInput
+ * true specifies non-blocking input stream behavior
+ * @param nonBlockingOutput
+ * true specifies non-blocking output stream behavior
+ * @param segmentSize
+ * specifies the segment size in bytes (pass 0 to use default value)
+ * @param segmentCount
+ * specifies the max number of segments (pass 0 to use default value)
+ * passing PR_UINT32_MAX here causes the pipe to have "infinite" space.
+ * this mode can be useful in some cases, but should always be used with
+ * caution. the default value for this parameter is a finite value.
+ * @param segmentAlloc
+ * pass reference to nsIMemory to have all pipe allocations use this
+ * allocator (pass null to use the default allocator)
+ */
+extern NS_COM nsresult
+NS_NewPipe2(nsIAsyncInputStream **pipeIn,
+ nsIAsyncOutputStream **pipeOut,
+ PRBool nonBlockingInput = PR_FALSE,
+ PRBool nonBlockingOutput = PR_FALSE,
+ PRUint32 segmentSize = 0,
+ PRUint32 segmentCount = 0,
+ nsIMemory *segmentAlloc = nsnull);
+
+/**
+ * NS_NewPipe
+ *
+ * Preserved for backwards compatibility. Plus, this interface is more
+ * amiable in certain contexts (e.g., when you don't need the pipe's async
+ * capabilities).
+ *
+ * @param pipeIn
+ * resulting input end of the pipe
+ * @param pipeOut
+ * resulting output end of the pipe
+ * @param segmentSize
+ * specifies the segment size in bytes (pass 0 to use default value)
+ * @param maxSize
+ * specifies the max size of the pipe (pass 0 to use default value)
+ * number of segments is maxSize / segmentSize, and maxSize must be a
+ * multiple of segmentSize. passing PR_UINT32_MAX here causes the
+ * pipe to have "infinite" space. this mode can be useful in some
+ * cases, but should always be used with caution. the default value
+ * for this parameter is a finite value.
+ * @param nonBlockingInput
+ * true specifies non-blocking input stream behavior
+ * @param nonBlockingOutput
+ * true specifies non-blocking output stream behavior
+ * @param segmentAlloc
+ * pass reference to nsIMemory to have all pipe allocations use this
+ * allocator (pass null to use the default allocator)
+ */
+inline nsresult
+NS_NewPipe(nsIInputStream **pipeIn,
+ nsIOutputStream **pipeOut,
+ PRUint32 segmentSize = 0,
+ PRUint32 maxSize = 0,
+ PRBool nonBlockingInput = PR_FALSE,
+ PRBool nonBlockingOutput = PR_FALSE,
+ nsIMemory *segmentAlloc = nsnull)
+{
+ PRUint32 segmentCount;
+ if (segmentSize == 0)
+ segmentCount = 0; // use default
+ else
+ segmentCount = maxSize / segmentSize;
+
+ nsIAsyncInputStream *in;
+ nsIAsyncOutputStream *out;
+ nsresult rv = NS_NewPipe2(&in, &out, nonBlockingInput, nonBlockingOutput,
+ segmentSize, segmentCount, segmentAlloc);
+ if (NS_FAILED(rv)) return rv;
+
+ *pipeIn = in;
+ *pipeOut = out;
+ return NS_OK;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl
new file mode 100644
index 00000000..9a21b1d0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl
@@ -0,0 +1,73 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIInputStream;
+
+/**
+ * nsIScriptableInputStream provides scriptable access to the nsIInputStream.
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(a2a32f90-9b90-11d3-a189-0050041caf44)]
+interface nsIScriptableInputStream : nsISupports
+{
+ /**
+ * Closes the stream.
+ */
+ void close();
+
+ /** Wrap the given nsIInputStream with this nsIScriptableInputStream.
+ * @param aInputStream [in] parameter providing the stream to wrap
+ */
+ void init(in nsIInputStream aInputStream);
+
+ /** Return the number of bytes currently available in the stream
+ * @param _retval [out] parameter to hold the number of bytes
+ * if an error occurs, the parameter will be undefined
+ * @return error status
+ */
+ unsigned long available();
+
+ /** Read data from the stream.
+ * @param aCount [in] the maximum number of bytes to read
+ * @param _retval [out] the data
+ */
+ string read(in unsigned long aCount);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl b/src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl
new file mode 100644
index 00000000..b2827c12
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/*
+ * nsISeekableStream
+ *
+ * Note that a stream might not implement all methods (e.g., a readonly stream
+ * won't implement setEOF)
+ *
+ * @status UNDER_REVIEW
+ */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(8429d350-1040-4661-8b71-f2a6ba455980)]
+interface nsISeekableStream : nsISupports
+{
+ /*
+ * Sets the stream pointer to the value of the 'offset' parameter
+ */
+ const PRInt32 NS_SEEK_SET = 0;
+
+ /*
+ * Sets the stream pointer to its current location plus the value
+ * of the offset parameter.
+ */
+ const PRInt32 NS_SEEK_CUR = 1;
+
+ /*
+ * Sets the stream pointer to the size of the stream plus the value
+ * of the offset parameter.
+ */
+ const PRInt32 NS_SEEK_END = 2;
+
+ /**
+ * seek
+ *
+ * This method moves the stream offset of the steam implementing this
+ * interface.
+ *
+ * @param whence specifies how to interpret the 'offset' parameter in
+ * setting the stream offset associated with the implementing
+ * stream.
+ *
+ * @param offset specifies a value, in bytes, that is used in conjunction
+ * with the 'whence' parameter to set the stream offset of the
+ * implementing stream. A negative value causes seeking in
+ * the reverse direction.
+ */
+ void seek(in long whence, in long long offset);
+
+ /**
+ * tell
+ *
+ * This method reports the current offset, in bytes, from the start of the
+ * stream.
+ */
+ long long tell();
+
+
+ /**
+ * setEOF
+ *
+ * This method truncates the stream at the current offset.
+ */
+ void setEOF();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl
new file mode 100644
index 00000000..148136b9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsrootidl.idl"
+
+interface nsIMemory;
+interface nsIInputStream;
+interface nsIOutputStream;
+
+/**
+ * The nsIStorageStream interface maintains an internal data buffer that can be
+ * filled using a single output stream. One or more independent input streams
+ * can be created to read the data from the buffer non-destructively.
+ */
+
+[scriptable, uuid(604ad9d0-753e-11d3-90ca-34278643278f)]
+interface nsIStorageStream : nsISupports
+{
+ /**
+ *
+ * Initialize the stream, setting up the amount of space that will be
+ * allocated for the stream's backing-store.
+ *
+ * @param segmentSize
+ * Size of each segment. Must be a power of two.
+ * @param maxSize
+ * Maximum total size of this stream. length will always be less
+ * than or equal to this value. Passing PR_UINT32_MAX is safe.
+ * @param segmentAllocator
+ * Which allocator to use for the segments. May be null, in which
+ * case a default allocator will be used.
+ */
+ void init(in PRUint32 segmentSize, in PRUint32 maxSize, in nsIMemory segmentAllocator);
+
+ /**
+ * Get a reference to the one and only output stream for this instance.
+ * The zero-based startPosition argument is used is used to set the initial
+ * write cursor position. The startPosition cannot be set larger than the
+ * current buffer length. Calling this method has the side-effect of
+ * truncating the internal buffer to startPosition bytes.
+ */
+ nsIOutputStream getOutputStream(in PRInt32 startPosition);
+
+ /**
+ * Create a new input stream to read data (written by the singleton output
+ * stream) from the internal buffer. Multiple, independent input streams
+ * can be created.
+ */
+ nsIInputStream newInputStream(in PRInt32 startPosition);
+
+ /**
+ * The length attribute indicates the total number of bytes stored in the
+ * nsIStorageStream internal buffer, regardless of any consumption by input
+ * streams. Assigning to the length field can be used to truncate the
+ * buffer data, but can not be used when either the instance's output
+ * stream is in use.
+ *
+ * @See #writeInProgress */
+ attribute PRUint32 length;
+
+ /**
+ * True, when output stream has not yet been Close'ed
+ */
+ readonly attribute boolean writeInProgress;
+};
+
+%{C++
+// Factory method
+NS_COM nsresult
+NS_NewStorageStream(PRUint32 segmentSize, PRUint32 maxSize, nsIStorageStream **result);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl b/src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl
new file mode 100644
index 00000000..dc41585f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla FastLoad code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsrootidl.idl"
+
+/**
+ * An interface for access to a buffering stream implementation's underlying
+ * memory buffer.
+ *
+ * Stream implementations that QueryInterface to nsIStreamBufferAccess must
+ * ensure that all buffers are aligned on the most restrictive type size for
+ * the current architecture (e.g., sizeof(double) for RISCy CPUs). malloc(3)
+ * satisfies this requirement.
+ */
+[uuid(ac923b72-ac87-4892-ac7a-ca385d429435)]
+interface nsIStreamBufferAccess : nsISupports
+{
+ /**
+ * Get access to a contiguous, aligned run of bytes in the stream's buffer.
+ * Exactly one successful getBuffer call must occur before a putBuffer call
+ * taking the non-null pointer returned by the successful getBuffer.
+ *
+ * The run of bytes are the next bytes (modulo alignment padding) to read
+ * for an input stream, and the next bytes (modulo alignment padding) to
+ * store before (eventually) writing buffered data to an output stream.
+ * There can be space beyond this run of bytes in the buffer for further
+ * accesses before the fill or flush point is reached.
+ *
+ * @param aLength
+ * Count of contiguous bytes requested at the address A that satisfies
+ * (A & aAlignMask) == 0 in the buffer, starting from the current stream
+ * position, mapped to a buffer address B. The stream implementation
+ * must pad from B to A by skipping bytes (if input stream) or storing
+ * zero bytes (if output stream).
+ *
+ * @param aAlignMask
+ * Bit-mask computed by subtracting 1 from the power-of-two alignment
+ * modulus (e.g., 3 or sizeof(PRUint32)-1 for PRUint32 alignment).
+ *
+ * @return
+ * The aligned pointer to aLength bytes in the buffer, or null if the
+ * buffer has no room for aLength bytes starting at the next address A
+ * after the current position that satisfies (A & aAlignMask) == 0.
+ */
+ [notxpcom] charPtr getBuffer(in PRUint32 aLength, in PRUint32 aAlignMask);
+
+ /**
+ * Relinquish access to the stream's buffer, filling if at end of an input
+ * buffer, flushing if completing an output buffer. After a getBuffer call
+ * that returns non-null, putBuffer must be called.
+ *
+ * @param aBuffer
+ * A non-null pointer returned by getBuffer on the same stream buffer
+ * access object.
+ *
+ * @param aLength
+ * The same count of contiguous bytes passed to the getBuffer call that
+ * returned aBuffer.
+ */
+ [notxpcom] void putBuffer(in charPtr aBuffer, in PRUint32 aLength);
+
+ /**
+ * Disable and enable buffering on the stream implementing this interface.
+ * DisableBuffering flushes an output stream's buffer, and invalidates an
+ * input stream's buffer.
+ */
+ void disableBuffering();
+ void enableBuffering();
+
+ /**
+ * The underlying, unbuffered input or output stream.
+ */
+ readonly attribute nsISupports unbufferedStream;
+};
+
+%{C++
+
+// Swap macros, used to convert to/from canonical (big-endian) format
+#if defined IS_LITTLE_ENDIAN
+
+# define NS_SWAP16(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
+# define NS_SWAP32(x) ((NS_SWAP16((x) & 0xffff) << 16) | (NS_SWAP16((x) >> 16)))
+
+// We want to avoid casting to 32-bit types if possible, since that violates
+// aliasing rules (a standard compiler may assume that pointers of two types
+// do not address overlapping storage).
+//
+// XXX What if we have a compiler that follows aliasing rules strictly but
+// doesn't have a 64-bit int type?
+//
+// XXXbe shouldn't NSPR's LL_INIT work for non-constant arguments in all cases?
+
+# if defined HAVE_LONG_LONG
+# if PR_BYTES_PER_LONG == 8
+# define ULL_(x) x ## UL
+# elif (defined WIN32 || defined WIN16) && !defined __GNUC__
+# define ULL_(x) ((uint64) x ## i64)
+# else
+# define ULL_(x) x ## ULL
+# endif
+
+# define NS_SWAP64(x) ((((x) & ULL_(0xff00000000000000)) >> 56) | \
+ (((x) & ULL_(0x00ff000000000000)) >> 40) | \
+ (((x) & ULL_(0x0000ff0000000000)) >> 24) | \
+ (((x) & ULL_(0x000000ff00000000)) >> 8) | \
+ (((x) & ULL_(0x00000000ff000000)) << 8) | \
+ (((x) & ULL_(0x0000000000ff0000)) << 24) | \
+ (((x) & ULL_(0x000000000000ff00)) << 40) | \
+ (((x) /* & ULL_(0x00000000000000ff) */) << 56))
+# else
+# define NS_SWAP64(x) LL_INIT((((x).lo /* & 0xff000000ul */) >> 24) | \
+ (((x).lo & 0x00ff0000ul) >> 8) | \
+ (((x).lo & 0x0000ff00ul) << 8) | \
+ (((x).lo /* & 0x000000fful */) << 24), \
+ (((x).hi /* & 0xff000000ul */) >> 24) | \
+ (((x).hi & 0x00ff0000ul) >> 8) | \
+ (((x).hi & 0x0000ff00ul) << 8) | \
+ (((x).hi /* & 0x000000fful */) << 24))
+# endif
+
+#elif defined IS_BIG_ENDIAN
+
+# define NS_SWAP16(x) (x)
+# define NS_SWAP32(x) (x)
+# define NS_SWAP64(x) (x)
+
+#else
+
+# error "Unknown byte order"
+
+#endif
+
+/**
+ * These macros get and put a buffer given either an sba parameter that may
+ * point to an object implementing nsIStreamBufferAccess, nsIObjectInputStream,
+ * or nsIObjectOutputStream.
+ */
+#define NS_GET_BUFFER(sba,n,a) ((sba)->GetBuffer(n, a))
+#define NS_PUT_BUFFER(sba,p,n) ((sba)->PutBuffer(p, n))
+
+#define NS_GET8(p) (*(PRUint8*)(p))
+#define NS_GET16(p) NS_SWAP16(*(PRUint16*)(p))
+#define NS_GET32(p) NS_SWAP32(*(PRUint32*)(p))
+#define NS_GET64(p) NS_SWAP64(*(PRUint64*)(p))
+#define NS_GET_FLOAT(p) ((float)NS_SWAP32(*(PRUint32*)(p)))
+#define NS_GET_DOUBLE(p) ((double)NS_SWAP64(*(PRUint64*)(p)))
+
+#define NS_PUT8(p,x) (*(PRUint8*)(p) = (x))
+#define NS_PUT16(p,x) (*(PRUint16*)(p) = NS_SWAP16(x))
+#define NS_PUT32(p,x) (*(PRUint32*)(p) = NS_SWAP32(x))
+#define NS_PUT64(p,x) (*(PRUint64*)(p) = NS_SWAP64(x))
+#define NS_PUT_FLOAT(p,x) (*(PRUint32*)(p) = NS_SWAP32(*(PRUint32*)&(x)))
+#define NS_PUT_DOUBLE(p,x) (*(PRUint64*)(p) = NS_SWAP64(*(PRUint64*)&(x)))
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl
new file mode 100644
index 00000000..09a90548
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * mcmullen@netscape.com (original author)
+ * scc@mozilla.org
+ * davidm@netscape.com
+ * darin@netscape.com
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Based on original code from nsIStringStream.h
+ */
+
+#include "nsIInputStream.idl"
+
+/**
+ * nsIStringInputStream
+ *
+ * Provides scriptable and specialized C++ only methods for initializing a
+ * nsIInputStream implementation with a simple character array.
+ */
+[scriptable, uuid(450cd2d4-f0fd-424d-b365-b1251f80fd53)]
+interface nsIStringInputStream : nsIInputStream
+{
+ /**
+ * SetData - assign data to the input stream (copied on assignment).
+ *
+ * @param data - stream data
+ * @param dataLen - stream data length (-1 if length should be computed)
+ *
+ * NOTE: C++ code should consider using AdoptData or ShareData to avoid
+ * making an extra copy of the stream data.
+ */
+ void setData(in string data, in long dataLen);
+
+ /**
+ * NOTE: the following methods are designed to give C++ code added control
+ * over the ownership and lifetime of the stream data. Use with care :-)
+ */
+
+ /**
+ * AdoptData - assign data to the input stream. the input stream takes
+ * ownership of the given data buffer and will nsMemory::Free it when
+ * the input stream is destroyed.
+ *
+ * @param data - stream data
+ * @param dataLen - stream data length (-1 if length should be computed)
+ */
+ [noscript] void adoptData(in charPtr data, in long dataLen);
+
+ /**
+ * ShareData - assign data to the input stream. the input stream references
+ * the given data buffer until the input stream is destroyed. the given
+ * data buffer must outlive the input stream.
+ *
+ * @param data - stream data
+ * @param dataLen - stream data length (-1 if length should be computed)
+ */
+ [noscript] void shareData(in string data, in long dataLen);
+};
+
+%{C++
+
+//-----------------------------------------------------------------------------
+// C++ factory methods
+//-----------------------------------------------------------------------------
+
+#include "nsIInputStream.h"
+#include "nsString.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_NewByteInputStream VBoxNsxpNS_NewByteInputStream
+#define NS_NewCStringInputStream VBoxNsxpNS_NewCStringInputStream
+#define NS_NewCharInputStream VBoxNsxpNS_NewCharInputStream
+#define NS_NewStringInputStream VBoxNsxpNS_NewStringInputStream
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from an nsAString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewStringInputStream(nsIInputStream** aStreamResult,
+ const nsAString& aStringToRead);
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from an nsACString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCStringInputStream(nsIInputStream** aStreamResult,
+ const nsACString& aStringToRead);
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from a string. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCharInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead);
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from a byte buffer. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewByteInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead,
+ PRInt32 aLength);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h
new file mode 100644
index 00000000..7232249d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsIUnicharInputStream_h___
+#define nsIUnicharInputStream_h___
+
+#include "nsIInputStream.h"
+#include "nsString.h"
+#include "nscore.h"
+
+class nsIUnicharInputStream;
+
+typedef NS_CALLBACK(nsWriteUnicharSegmentFun)(nsIUnicharInputStream *aInStream,
+ void *aClosure,
+ const PRUnichar *aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount);
+/* c4bcf6ee-3a79-4d77-8d48-f17be3199b3b */
+#define NS_IUNICHAR_INPUT_STREAM_IID \
+{ 0xc4bcf6ee, 0x3a79, 0x4d77, \
+ {0x8d, 0x48, 0xf1, 0x7b, 0xe3, 0x19, 0x9b, 0x3b} }
+
+/** Abstract unicode character input stream
+ * @see nsIInputStream
+ */
+class NS_NO_VTABLE nsIUnicharInputStream : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IUNICHAR_INPUT_STREAM_IID)
+
+ NS_IMETHOD Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount) = 0;
+ NS_IMETHOD Close() = 0;
+ NS_IMETHOD ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount,
+ PRUint32 *aReadCount) = 0;
+};
+
+/**
+ * Create a nsIUnicharInputStream that wraps up a string. Data is fed
+ * from the string out until the done. When this object is destroyed
+ * it destroyes the string (so make a copy if you don't want it doing
+ * that)
+ */
+extern NS_COM nsresult
+ NS_NewStringUnicharInputStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsString* aString);
+
+/** Create a new nsUnicharInputStream that provides a converter for the
+ * byte input stream aStreamToWrap. If no converter can be found then
+ * nsnull is returned and the error code is set to
+ * NS_INPUTSTREAM_NO_CONVERTER.
+ */
+extern NS_COM nsresult
+ NS_NewUTF8ConverterStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsIInputStream* aStreamToWrap,
+ PRInt32 aBufferSize = 0);
+
+#endif /* nsUnicharInputStream_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp b/src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp
new file mode 100644
index 00000000..b0651ad1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp
@@ -0,0 +1,224 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIInputStreamTee.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsCOMPtr.h"
+
+class nsInputStreamTee : public nsIInputStreamTee
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIINPUTSTREAMTEE
+
+ nsInputStreamTee();
+
+private:
+ ~nsInputStreamTee() {}
+
+ nsresult TeeSegment(const char *buf, PRUint32 count);
+
+ static NS_METHOD WriteSegmentFun(nsIInputStream *, void *, const char *,
+ PRUint32, PRUint32, PRUint32 *);
+
+private:
+ nsCOMPtr<nsIInputStream> mSource;
+ nsCOMPtr<nsIOutputStream> mSink;
+ nsWriteSegmentFun mWriter; // for implementing ReadSegments
+ void *mClosure; // for implementing ReadSegments
+};
+
+nsInputStreamTee::nsInputStreamTee()
+{
+}
+
+nsresult
+nsInputStreamTee::TeeSegment(const char *buf, PRUint32 count)
+{
+ if (!mSink)
+ return NS_OK; // nothing to do
+ nsresult rv;
+ PRUint32 bytesWritten = 0;
+ while (count) {
+ rv = mSink->Write(buf + bytesWritten, count, &bytesWritten);
+ if (NS_FAILED(rv)) {
+ // ok, this is not a fatal error... just drop our reference to mSink
+ // and continue on as if nothing happened.
+ NS_WARNING("Write failed (non-fatal)");
+ // catch possible misuse of the input stream tee
+ NS_ASSERTION(rv != NS_BASE_STREAM_WOULD_BLOCK, "sink must be a blocking stream");
+ mSink = 0;
+ break;
+ }
+ NS_ASSERTION(bytesWritten <= count, "wrote too much");
+ count -= bytesWritten;
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+nsInputStreamTee::WriteSegmentFun(nsIInputStream *in, void *closure, const char *fromSegment,
+ PRUint32 offset, PRUint32 count, PRUint32 *writeCount)
+{
+ nsInputStreamTee *tee = NS_REINTERPRET_CAST(nsInputStreamTee *, closure);
+
+ nsresult rv = tee->mWriter(in, tee->mClosure, fromSegment, offset, count, writeCount);
+ if (NS_FAILED(rv) || (*writeCount == 0)) {
+ NS_ASSERTION((NS_FAILED(rv) ? (*writeCount == 0) : PR_TRUE),
+ "writer returned an error with non-zero writeCount");
+ return rv;
+ }
+
+ return tee->TeeSegment(fromSegment, *writeCount);
+}
+
+NS_IMPL_ISUPPORTS2(nsInputStreamTee,
+ nsIInputStreamTee,
+ nsIInputStream)
+
+NS_IMETHODIMP
+nsInputStreamTee::Close()
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+ nsresult rv = mSource->Close();
+ mSource = 0;
+ mSink = 0;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::Available(PRUint32 *avail)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+ return mSource->Available(avail);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::Read(char *buf, PRUint32 count, PRUint32 *bytesRead)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+
+ nsresult rv = mSource->Read(buf, count, bytesRead);
+ if (NS_FAILED(rv) || (*bytesRead == 0))
+ return rv;
+
+ return TeeSegment(buf, *bytesRead);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::ReadSegments(nsWriteSegmentFun writer,
+ void *closure,
+ PRUint32 count,
+ PRUint32 *bytesRead)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+
+ mWriter = writer;
+ mClosure = closure;
+
+ return mSource->ReadSegments(WriteSegmentFun, this, count, bytesRead);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::IsNonBlocking(PRBool *result)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+ return mSource->IsNonBlocking(result);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::SetSource(nsIInputStream *source)
+{
+ mSource = source;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::GetSource(nsIInputStream **source)
+{
+ NS_IF_ADDREF(*source = mSource);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::SetSink(nsIOutputStream *sink)
+{
+#ifdef DEBUG
+ if (sink) {
+ PRBool nonBlocking;
+ nsresult rv = sink->IsNonBlocking(&nonBlocking);
+ if (NS_FAILED(rv) || nonBlocking)
+ NS_ERROR("sink should be a blocking stream");
+ }
+#endif
+ mSink = sink;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::GetSink(nsIOutputStream **sink)
+{
+ NS_IF_ADDREF(*sink = mSink);
+ return NS_OK;
+}
+
+// factory method
+
+NS_COM nsresult
+NS_NewInputStreamTee(nsIInputStream **result,
+ nsIInputStream *source,
+ nsIOutputStream *sink)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIInputStreamTee> tee;
+ NS_NEWXPCOM(tee, nsInputStreamTee);
+ if (!tee)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = tee->SetSource(source);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = tee->SetSink(sink);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ADDREF(*result = tee);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp
new file mode 100644
index 00000000..88905f97
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsLinebreakConverter.h"
+
+#include "nsMemory.h"
+#include "nsCRT.h"
+
+
+#if defined(XP_WIN) && defined(_MSC_VER) && (_MSC_VER <= 1100)
+#define LOSER_CHAR_CAST(t) (char *)(t)
+#define LOSER_UNICHAR_CAST(t) (PRUnichar *)(t)
+#else
+#define LOSER_CHAR_CAST(t) (t)
+#define LOSER_UNICHAR_CAST(t) (t)
+#endif
+
+/*----------------------------------------------------------------------------
+ GetLinebreakString
+
+ Could make this inline
+----------------------------------------------------------------------------*/
+static const char* GetLinebreakString(nsLinebreakConverter::ELinebreakType aBreakType)
+{
+ static const char* const sLinebreaks[] = {
+ "", // any
+ NS_LINEBREAK, // platform
+ LFSTR, // content
+ CRLF, // net
+ CRSTR, // Mac
+ LFSTR, // Unix
+ CRLF, // Windows
+ nsnull
+ };
+
+ return sLinebreaks[aBreakType];
+}
+
+
+/*----------------------------------------------------------------------------
+ AppendLinebreak
+
+ Wee inline method to append a line break. Modifies ioDest.
+----------------------------------------------------------------------------*/
+template<class T>
+void AppendLinebreak(T*& ioDest, const char* lineBreakStr)
+{
+ *ioDest++ = *lineBreakStr;
+
+ if (lineBreakStr[1])
+ *ioDest++ = lineBreakStr[1];
+}
+
+/*----------------------------------------------------------------------------
+ CountChars
+
+ Counts occurrences of breakStr in aSrc
+----------------------------------------------------------------------------*/
+template<class T>
+PRInt32 CountLinebreaks(const T* aSrc, PRInt32 inLen, const char* breakStr)
+{
+ const T* src = aSrc;
+ const T* srcEnd = aSrc + inLen;
+ PRInt32 theCount = 0;
+
+ while (src < srcEnd)
+ {
+ if (*src == *breakStr)
+ {
+ src ++;
+ if (src < srcEnd && breakStr[1] && *src == breakStr[1])
+ src ++;
+
+ theCount ++;
+ }
+ else
+ {
+ src ++;
+ }
+ }
+
+ return theCount;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertBreaks
+
+ ioLen *includes* a terminating null, if any
+----------------------------------------------------------------------------*/
+template<class T>
+static T* ConvertBreaks(const T* inSrc, PRInt32& ioLen, const char* srcBreak, const char* destBreak)
+{
+ NS_ASSERTION(inSrc && srcBreak && destBreak, "Got a null string");
+
+ T* resultString = nsnull;
+
+ // handle the no conversion case
+ if (nsCRT::strcmp(srcBreak, destBreak) == 0)
+ {
+ resultString = (T *)nsMemory::Alloc(sizeof(T) * ioLen);
+ if (!resultString) return nsnull;
+ memcpy(resultString, inSrc, sizeof(T) * ioLen); // includes the null, if any
+ return resultString;
+ }
+
+ PRInt32 srcBreakLen = strlen(srcBreak);
+ PRInt32 destBreakLen = strlen(destBreak);
+
+ // handle the easy case, where the string length does not change, and the
+ // breaks are only 1 char long, i.e. CR <-> LF
+ if (srcBreakLen == destBreakLen && srcBreakLen == 1)
+ {
+ resultString = (T *)nsMemory::Alloc(sizeof(T) * ioLen);
+ if (!resultString) return nsnull;
+
+ const T* src = inSrc;
+ const T* srcEnd = inSrc + ioLen; // includes null, if any
+ T* dst = resultString;
+
+ char srcBreakChar = *srcBreak; // we know it's one char long already
+ char dstBreakChar = *destBreak;
+
+ while (src < srcEnd)
+ {
+ if (*src == srcBreakChar)
+ {
+ *dst++ = dstBreakChar;
+ src++;
+ }
+ else
+ {
+ *dst++ = *src++;
+ }
+ }
+
+ // ioLen does not change
+ }
+ else
+ {
+ // src and dest termination is different length. Do it a slower way.
+
+ // count linebreaks in src. Assumes that chars in 2-char linebreaks are unique.
+ PRInt32 numLinebreaks = CountLinebreaks(inSrc, ioLen, srcBreak);
+
+ PRInt32 newBufLen = ioLen - (numLinebreaks * srcBreakLen) + (numLinebreaks * destBreakLen);
+ resultString = (T *)nsMemory::Alloc(sizeof(T) * newBufLen);
+ if (!resultString) return nsnull;
+
+ const T* src = inSrc;
+ const T* srcEnd = inSrc + ioLen; // includes null, if any
+ T* dst = resultString;
+
+ while (src < srcEnd)
+ {
+ if (*src == *srcBreak)
+ {
+ *dst++ = *destBreak;
+ if (destBreak[1])
+ *dst++ = destBreak[1];
+
+ src ++;
+ if (src < srcEnd && srcBreak[1] && *src == srcBreak[1])
+ src ++;
+ }
+ else
+ {
+ *dst++ = *src++;
+ }
+ }
+
+ ioLen = newBufLen;
+ }
+
+ return resultString;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertBreaksInSitu
+
+ Convert breaks in situ. Can only do this if the linebreak length
+ does not change.
+----------------------------------------------------------------------------*/
+template<class T>
+static void ConvertBreaksInSitu(T* inSrc, PRInt32 inLen, char srcBreak, char destBreak)
+{
+ T* src = inSrc;
+ T* srcEnd = inSrc + inLen;
+
+ while (src < srcEnd)
+ {
+ if (*src == srcBreak)
+ *src = destBreak;
+
+ src ++;
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertUnknownBreaks
+
+ Convert unknown line breaks to the specified break.
+
+ This will convert CRLF pairs to one break, and single CR or LF to a break.
+----------------------------------------------------------------------------*/
+template<class T>
+static T* ConvertUnknownBreaks(const T* inSrc, PRInt32& ioLen, const char* destBreak)
+{
+ const T* src = inSrc;
+ const T* srcEnd = inSrc + ioLen; // includes null, if any
+
+ PRInt32 destBreakLen = strlen(destBreak);
+ PRInt32 finalLen = 0;
+
+ while (src < srcEnd)
+ {
+ if (*src == nsCRT::CR)
+ {
+ if (src < srcEnd && src[1] == nsCRT::LF)
+ {
+ // CRLF
+ finalLen += destBreakLen;
+ src ++;
+ }
+ else
+ {
+ // Lone CR
+ finalLen += destBreakLen;
+ }
+ }
+ else if (*src == nsCRT::LF)
+ {
+ // Lone LF
+ finalLen += destBreakLen;
+ }
+ else
+ {
+ finalLen ++;
+ }
+ src ++;
+ }
+
+ T* resultString = (T *)nsMemory::Alloc(sizeof(T) * finalLen);
+ if (!resultString) return nsnull;
+
+ src = inSrc;
+ srcEnd = inSrc + ioLen; // includes null, if any
+
+ T* dst = resultString;
+
+ while (src < srcEnd)
+ {
+ if (*src == nsCRT::CR)
+ {
+ if (src < srcEnd && src[1] == nsCRT::LF)
+ {
+ // CRLF
+ AppendLinebreak(dst, destBreak);
+ src ++;
+ }
+ else
+ {
+ // Lone CR
+ AppendLinebreak(dst, destBreak);
+ }
+ }
+ else if (*src == nsCRT::LF)
+ {
+ // Lone LF
+ AppendLinebreak(dst, destBreak);
+ }
+ else
+ {
+ *dst++ = *src;
+ }
+ src ++;
+ }
+
+ ioLen = finalLen;
+ return resultString;
+}
+
+
+#ifdef XP_MAC
+#pragma mark -
+#endif
+
+
+/*----------------------------------------------------------------------------
+ ConvertLineBreaks
+
+----------------------------------------------------------------------------*/
+char* nsLinebreakConverter::ConvertLineBreaks(const char* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+ if (!aSrc) return nsnull;
+
+ PRInt32 sourceLen = (aSrcLen == kIgnoreLen) ? strlen(aSrc) + 1 : aSrcLen;
+
+ char* resultString;
+ if (aSrcBreaks == eLinebreakAny)
+ resultString = ConvertUnknownBreaks(LOSER_CHAR_CAST(aSrc), sourceLen, GetLinebreakString(aDestBreaks));
+ else
+ resultString = ConvertBreaks(LOSER_CHAR_CAST(aSrc), sourceLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks));
+
+ if (outLen)
+ *outLen = sourceLen;
+ return resultString;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertLineBreaksInSitu
+
+----------------------------------------------------------------------------*/
+nsresult nsLinebreakConverter::ConvertLineBreaksInSitu(char **ioBuffer, ELinebreakType aSrcBreaks,
+ ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(ioBuffer && *ioBuffer, "Null pointer passed");
+ if (!ioBuffer || !*ioBuffer) return NS_ERROR_NULL_POINTER;
+
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+
+ PRInt32 sourceLen = (aSrcLen == kIgnoreLen) ? strlen(*ioBuffer) + 1 : aSrcLen;
+
+ // can we convert in-place?
+ const char* srcBreaks = GetLinebreakString(aSrcBreaks);
+ const char* dstBreaks = GetLinebreakString(aDestBreaks);
+
+ if ( (aSrcBreaks != eLinebreakAny) &&
+ (strlen(srcBreaks) == 1) &&
+ (strlen(dstBreaks) == 1) )
+ {
+ ConvertBreaksInSitu(*ioBuffer, sourceLen, *srcBreaks, *dstBreaks);
+ if (outLen)
+ *outLen = sourceLen;
+ }
+ else
+ {
+ char* destBuffer;
+
+ if (aSrcBreaks == eLinebreakAny)
+ destBuffer = ConvertUnknownBreaks(*ioBuffer, sourceLen, dstBreaks);
+ else
+ destBuffer = ConvertBreaks(*ioBuffer, sourceLen, srcBreaks, dstBreaks);
+
+ if (!destBuffer) return NS_ERROR_OUT_OF_MEMORY;
+ *ioBuffer = destBuffer;
+ if (outLen)
+ *outLen = sourceLen;
+ }
+
+ return NS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertUnicharLineBreaks
+
+----------------------------------------------------------------------------*/
+PRUnichar* nsLinebreakConverter::ConvertUnicharLineBreaks(const PRUnichar* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+ if (!aSrc) return nsnull;
+
+ PRInt32 bufLen = (aSrcLen == kIgnoreLen) ? nsCRT::strlen(aSrc) + 1 : aSrcLen;
+
+ PRUnichar* resultString;
+ if (aSrcBreaks == eLinebreakAny)
+ resultString = ConvertUnknownBreaks(LOSER_UNICHAR_CAST(aSrc), bufLen, GetLinebreakString(aDestBreaks));
+ else
+ resultString = ConvertBreaks(LOSER_UNICHAR_CAST(aSrc), bufLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks));
+
+ if (outLen)
+ *outLen = bufLen;
+ return resultString;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertStringLineBreaks
+
+----------------------------------------------------------------------------*/
+nsresult nsLinebreakConverter::ConvertUnicharLineBreaksInSitu(PRUnichar **ioBuffer,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(ioBuffer && *ioBuffer, "Null pointer passed");
+ if (!ioBuffer || !*ioBuffer) return NS_ERROR_NULL_POINTER;
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+
+ PRInt32 sourceLen = (aSrcLen == kIgnoreLen) ? nsCRT::strlen(*ioBuffer) + 1 : aSrcLen;
+
+ // can we convert in-place?
+ const char* srcBreaks = GetLinebreakString(aSrcBreaks);
+ const char* dstBreaks = GetLinebreakString(aDestBreaks);
+
+ if ( (aSrcBreaks != eLinebreakAny) &&
+ (strlen(srcBreaks) == 1) &&
+ (strlen(dstBreaks) == 1) )
+ {
+ ConvertBreaksInSitu(*ioBuffer, sourceLen, *srcBreaks, *dstBreaks);
+ if (outLen)
+ *outLen = sourceLen;
+ }
+ else
+ {
+ PRUnichar* destBuffer;
+
+ if (aSrcBreaks == eLinebreakAny)
+ destBuffer = ConvertUnknownBreaks(*ioBuffer, sourceLen, dstBreaks);
+ else
+ destBuffer = ConvertBreaks(*ioBuffer, sourceLen, srcBreaks, dstBreaks);
+
+ if (!destBuffer) return NS_ERROR_OUT_OF_MEMORY;
+ *ioBuffer = destBuffer;
+ if (outLen)
+ *outLen = sourceLen;
+ }
+
+ return NS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ ConvertStringLineBreaks
+
+----------------------------------------------------------------------------*/
+nsresult nsLinebreakConverter::ConvertStringLineBreaks(nsString& ioString,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks)
+{
+
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+
+ // nothing to do
+ if (ioString.IsEmpty()) return NS_OK;
+
+ nsresult rv;
+
+ // remember the old buffer in case
+ // we blow it away later
+ nsString::char_iterator stringBuf;
+ ioString.BeginWriting(stringBuf);
+
+ PRInt32 newLen;
+
+ rv = ConvertUnicharLineBreaksInSitu(&stringBuf,
+ aSrcBreaks, aDestBreaks,
+ ioString.Length() + 1, &newLen);
+ if (NS_FAILED(rv)) return rv;
+
+ if (stringBuf != ioString.get())
+ ioString.Adopt(stringBuf);
+
+ return NS_OK;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h
new file mode 100644
index 00000000..ec4bce57
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsLinebreakConverter_h_
+#define nsLinebreakConverter_h_
+
+
+#include "nscore.h"
+#include "nsString.h"
+
+// utility class for converting between different line breaks.
+
+class NS_COM nsLinebreakConverter
+{
+public:
+
+ // Note: enum must match char* array in GetLinebreakString
+ typedef enum {
+ eLinebreakAny, // any kind of linebreak (i.e. "don't care" source)
+
+ eLinebreakPlatform, // platform linebreak
+ eLinebreakContent, // Content model linebreak (LF)
+ eLinebreakNet, // Form submission linebreak (CRLF)
+
+ eLinebreakMac, // CR
+ eLinebreakUnix, // LF
+ eLinebreakWindows // CRLF
+
+ } ELinebreakType;
+
+ enum {
+ kIgnoreLen = -1
+ };
+
+ /* ConvertLineBreaks
+ * Convert line breaks in the supplied string, allocating and returning
+ * a new buffer. Returns nsnull on failure.
+ * @param aSrc: the source string. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static char* ConvertLineBreaks(const char* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+
+ /* ConvertUnicharLineBreaks
+ * Convert line breaks in the supplied string, allocating and returning
+ * a new buffer. Returns nsnull on failure.
+ * @param aSrc: the source string. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source, in characters. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static PRUnichar* ConvertUnicharLineBreaks(const PRUnichar* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+
+ /* ConvertStringLineBreaks
+ * Convert line breaks in the supplied string, changing the string buffer (i.e. in-place conversion)
+ * @param ioString: the string to be converted.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source, in characters. If -1, the source is assumed to be a null-
+ * terminated string.
+ */
+ static nsresult ConvertStringLineBreaks(nsString& ioString, ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks);
+
+
+ /* ConvertLineBreaksInSitu
+ * Convert line breaks in place if possible. NOTE: THIS MAY REALLOCATE THE BUFFER,
+ * BUT IT WON'T FREE THE OLD BUFFER (because it doesn't know how). So be prepared
+ * to keep a copy of the old pointer, and free it if this passes back a new pointer.
+ * ALSO NOTE: DON'T PASS A STATIC STRING POINTER TO THIS FUNCTION.
+ *
+ * @param ioBuffer: the source buffer. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static nsresult ConvertLineBreaksInSitu(char **ioBuffer, ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+
+ /* ConvertUnicharLineBreaksInSitu
+ * Convert line breaks in place if possible. NOTE: THIS MAY REALLOCATE THE BUFFER,
+ * BUT IT WON'T FREE THE OLD BUFFER (because it doesn't know how). So be prepared
+ * to keep a copy of the old pointer, and free it if this passes back a new pointer.
+ *
+ * @param ioBuffer: the source buffer. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source in characters. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static nsresult ConvertUnicharLineBreaksInSitu(PRUnichar **ioBuffer, ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+};
+
+
+
+
+#endif // nsLinebreakConverter_h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFile.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFile.h
new file mode 100644
index 00000000..8201affb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFile.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation. Modifications made by IBM
+ * described herein are Copyright (c) International Business Machines Corporation, 2000.
+ * Modifications to Mozilla code or documentation identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. OS/2 build.
+ */
+
+#ifndef _NS_LOCAL_FILE_H_
+#define _NS_LOCAL_FILE_H_
+
+#define NS_LOCAL_FILE_CID {0x2e23e220, 0x60be, 0x11d3, {0x8c, 0x4a, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
+
+#define NS_DECL_NSLOCALFILE_UNICODE_METHODS \
+ nsresult AppendUnicode(const PRUnichar *aNode); \
+ nsresult GetUnicodeLeafName(PRUnichar **aLeafName); \
+ nsresult SetUnicodeLeafName(const PRUnichar *aLeafName); \
+ nsresult CopyToUnicode(nsIFile *aNewParentDir, const PRUnichar *aNewLeafName); \
+ nsresult CopyToFollowingLinksUnicode(nsIFile *aNewParentDir, const PRUnichar *aNewLeafName); \
+ nsresult MoveToUnicode(nsIFile *aNewParentDir, const PRUnichar *aNewLeafName); \
+ nsresult GetUnicodeTarget(PRUnichar **aTarget); \
+ nsresult GetUnicodePath(PRUnichar **aPath); \
+ nsresult InitWithUnicodePath(const PRUnichar *aPath); \
+ nsresult AppendRelativeUnicodePath(const PRUnichar *aRelativePath);
+
+// nsXPComInit needs to know about how we are implemented,
+// so here we will export it. Other users should not depend
+// on this.
+
+#include <errno.h>
+#include "nsILocalFile.h"
+
+#ifdef XP_WIN
+#include "nsLocalFileWin.h"
+#elif defined(XP_MACOSX) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+#include "nsLocalFileOSX.h"
+#elif defined(XP_MAC)
+#include "nsLocalFileMac.h"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+#include "nsLocalFileUnix.h"
+#elif defined(XP_OS2)
+#include "nsLocalFileOS2.h"
+#else
+#error NOT_IMPLEMENTED
+#endif
+
+#define NSRESULT_FOR_RETURN(ret) (((ret) < 0) ? NSRESULT_FOR_ERRNO() : NS_OK)
+
+inline nsresult
+nsresultForErrno(int err)
+{
+ switch (err) {
+ case 0:
+ return NS_OK;
+ case ENOENT:
+ return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
+ case ENOTDIR:
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+#ifdef ENOLINK
+ case ENOLINK:
+ return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
+#endif /* ENOLINK */
+ case EEXIST:
+ return NS_ERROR_FILE_ALREADY_EXISTS;
+#ifdef EPERM
+ case EPERM:
+#endif /* EPERM */
+ case EACCES:
+ return NS_ERROR_FILE_ACCESS_DENIED;
+ default:
+ return NS_ERROR_FAILURE;
+ }
+}
+
+#define NSRESULT_FOR_ERRNO() nsresultForErrno(errno)
+
+void NS_StartupLocalFile();
+void NS_ShutdownLocalFile();
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp
new file mode 100644
index 00000000..664c5304
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp
@@ -0,0 +1,278 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsIServiceManager.h"
+
+#include "nsLocalFile.h" // includes platform-specific headers
+#include "nsLocalFileUnicode.h"
+
+#include "nsString.h"
+#include "nsCOMPtr.h"
+#include "nsReadableUtils.h"
+#include "nsPrintfCString.h"
+#include "nsCRT.h"
+
+#ifdef XP_WIN
+#include <string.h>
+#endif
+
+
+void NS_StartupLocalFile()
+{
+ nsLocalFile::GlobalInit();
+}
+
+void NS_ShutdownLocalFile()
+{
+ nsLocalFile::GlobalShutdown();
+}
+
+#if (!defined(XP_MAC) && !defined(XP_MACOSX)) || defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+NS_IMETHODIMP
+nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+ NS_ENSURE_ARG(aFile);
+
+ nsCAutoString path;
+ aFile->GetNativePath(path);
+ if (path.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+ return InitWithNativePath(path);
+}
+#endif
+
+#if defined(XP_MAC)
+#define kMaxFilenameLength 31
+#else
+#define kMaxFilenameLength 255
+#endif
+
+NS_IMETHODIMP
+nsLocalFile::CreateUnique(PRUint32 type, PRUint32 attributes)
+{
+ nsresult rv = Create(type, attributes);
+
+ if (NS_SUCCEEDED(rv)) return NS_OK;
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
+
+ nsCAutoString leafName;
+ rv = GetNativeLeafName(leafName);
+
+ if (NS_FAILED(rv)) return rv;
+
+ const char* lastDot = strrchr(leafName.get(), '.');
+ char suffix[kMaxFilenameLength + 1] = "";
+ if (lastDot)
+ {
+ strncpy(suffix, lastDot, kMaxFilenameLength); // include '.'
+ suffix[kMaxFilenameLength] = 0; // make sure it's null terminated
+ leafName.SetLength(lastDot - leafName.get()); // strip suffix and dot.
+ }
+
+ const int maxRootLength = (kMaxFilenameLength - 4) - strlen(suffix) - 1;
+
+ if ((int)leafName.Length() > (int)maxRootLength)
+ leafName.SetLength(maxRootLength);
+
+ for (short indx = 1; indx < 10000; indx++)
+ {
+ // start with "Picture-1.jpg" after "Picture.jpg" exists
+ SetNativeLeafName(leafName +
+ nsPrintfCString("-%d", indx) +
+ nsDependentCString(suffix));
+
+ rv = Create(type, attributes);
+
+ if (NS_SUCCEEDED(rv) || rv != NS_ERROR_FILE_ALREADY_EXISTS)
+ {
+ return rv;
+ }
+ }
+
+ // The disk is full, sort of
+ return NS_ERROR_FILE_TOO_BIG;
+}
+
+#if defined(XP_MAC)
+static const PRUnichar kPathSeparatorChar = ':';
+#elif defined(XP_WIN) || defined(XP_OS2)
+static const PRUnichar kPathSeparatorChar = '\\';
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+static const PRUnichar kPathSeparatorChar = '/';
+#else
+#error Need to define file path separator for your platform
+#endif
+
+#if defined(XP_MAC)
+static const char kSlashStr[] = "/";
+static const char kESCSlashStr[] = "%2F";
+#endif
+
+static PRInt32 SplitPath(PRUnichar *path, PRUnichar **nodeArray, PRInt32 arrayLen)
+{
+ if (*path == 0)
+ return 0;
+
+ PRUnichar **nodePtr = nodeArray;
+ if (*path == kPathSeparatorChar)
+ path++;
+ *nodePtr++ = path;
+
+ for (PRUnichar *cp = path; *cp != 0; cp++) {
+ if (*cp == kPathSeparatorChar) {
+ *cp++ = 0;
+ if (*cp == 0)
+ break;
+ if (nodePtr - nodeArray >= arrayLen)
+ return -1;
+ *nodePtr++ = cp;
+ }
+ }
+ return nodePtr - nodeArray;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetRelativeDescriptor(nsILocalFile *fromFile, nsACString& _retval)
+{
+ NS_ENSURE_ARG_POINTER(fromFile);
+ const PRInt32 kMaxNodesInPath = 32;
+
+ //
+ // _retval will be UTF-8 encoded
+ //
+
+ nsresult rv;
+ _retval.Truncate(0);
+
+ nsAutoString thisPath, fromPath;
+ PRUnichar *thisNodes[kMaxNodesInPath], *fromNodes[kMaxNodesInPath];
+ PRInt32 thisNodeCnt, fromNodeCnt, nodeIndex;
+
+ rv = GetPath(thisPath);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = fromFile->GetPath(fromPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get raw pointer to mutable string buffer
+ PRUnichar *thisPathPtr; thisPath.BeginWriting(thisPathPtr);
+ PRUnichar *fromPathPtr; fromPath.BeginWriting(fromPathPtr);
+
+ thisNodeCnt = SplitPath(thisPathPtr, thisNodes, kMaxNodesInPath);
+ fromNodeCnt = SplitPath(fromPathPtr, fromNodes, kMaxNodesInPath);
+ if (thisNodeCnt < 0 || fromNodeCnt < 0)
+ return NS_ERROR_FAILURE;
+
+ for (nodeIndex = 0; nodeIndex < thisNodeCnt && nodeIndex < fromNodeCnt; ++nodeIndex) {
+#ifdef XP_WIN
+ if (_wcsicmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
+ break;
+#else
+ if (nsCRT::strcmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
+ break;
+#endif
+ }
+
+ PRInt32 branchIndex = nodeIndex;
+ for (nodeIndex = branchIndex; nodeIndex < fromNodeCnt; nodeIndex++)
+ _retval.AppendLiteral("../");
+ for (nodeIndex = branchIndex; nodeIndex < thisNodeCnt; nodeIndex++) {
+ NS_ConvertUCS2toUTF8 nodeStr(thisNodes[nodeIndex]);
+#ifdef XP_MAC
+ nodeStr.ReplaceSubstring(kSlashStr, kESCSlashStr);
+#endif
+ _retval.Append(nodeStr);
+ if (nodeIndex + 1 < thisNodeCnt)
+ _retval.Append('/');
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetRelativeDescriptor(nsILocalFile *fromFile, const nsACString& relativeDesc)
+{
+ NS_NAMED_LITERAL_CSTRING(kParentDirStr, "../");
+
+ nsCOMPtr<nsIFile> targetFile;
+ nsresult rv = fromFile->Clone(getter_AddRefs(targetFile));
+ if (NS_FAILED(rv))
+ return rv;
+
+ //
+ // relativeDesc is UTF-8 encoded
+ //
+
+ nsCString::const_iterator strBegin, strEnd;
+ relativeDesc.BeginReading(strBegin);
+ relativeDesc.EndReading(strEnd);
+
+ nsCString::const_iterator nodeBegin(strBegin), nodeEnd(strEnd);
+ nsCString::const_iterator pos(strBegin);
+
+ nsCOMPtr<nsIFile> parentDir;
+ while (FindInReadable(kParentDirStr, nodeBegin, nodeEnd)) {
+ rv = targetFile->GetParent(getter_AddRefs(parentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ targetFile = parentDir;
+
+ nodeBegin = nodeEnd;
+ pos = nodeEnd;
+ nodeEnd = strEnd;
+ }
+
+ nodeBegin = nodeEnd = pos;
+ while (nodeEnd != strEnd) {
+ FindCharInReadable('/', nodeEnd, strEnd);
+#ifdef XP_MAC
+ nsCAutoString nodeString(Substring(nodeBegin, nodeEnd));
+ nodeString.ReplaceSubstring(kESCSlashStr, kSlashStr);
+ targetFile->Append(NS_ConvertUTF8toUCS2(nodeString));
+#else
+ targetFile->Append(NS_ConvertUTF8toUCS2(Substring(nodeBegin, nodeEnd)));
+#endif
+ if (nodeEnd != strEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
+ ++nodeEnd;
+ nodeBegin = nodeEnd;
+ }
+
+ nsCOMPtr<nsILocalFile> targetLocalFile(do_QueryInterface(targetFile));
+ return InitWithFile(targetLocalFile);
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp
new file mode 100644
index 00000000..bebc76c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp
@@ -0,0 +1,3554 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Steve Dagley <sdagley@netscape.com>
+ * John R. McMullen
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+
+#include "nsLocalFile.h"
+#include "nsNativeCharsetUtils.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIComponentManager.h"
+#include "nsIInternetConfigService.h"
+#include "nsIMIMEInfo.h"
+#include "prtypes.h"
+#include "prerror.h"
+
+#include "nsReadableUtils.h"
+#include "nsITimelineService.h"
+
+#ifdef XP_MACOSX
+#include "nsXPIDLString.h"
+
+#include "private/pprio.h"
+#else
+#include "pprio.h" // Include this rather than prio.h so we get def of PR_ImportFile
+#endif
+#include "prmem.h"
+#include "plbase64.h"
+
+#include "FullPath.h"
+#include "FileCopy.h"
+#include "MoreFilesExtras.h"
+#include "DirectoryCopy.h"
+#include <Script.h>
+#include <Processes.h>
+#include <StringCompare.h>
+#include <Resources.h>
+
+#include <AppleEvents.h>
+#include <AEDataModel.h>
+#include <AERegistry.h>
+#include <Gestalt.h>
+
+#include <Math64.h>
+#include <Aliases.h>
+#include <Folders.h>
+#include <Gestalt.h>
+#include "macDirectoryCopy.h"
+
+#include <limits.h>
+
+// Stupid @#$% header looks like its got extern mojo but it doesn't really
+extern "C"
+{
+#ifndef XP_MACOSX
+// BADPINK - this MSL header doesn't exist under macosx :-(
+#include <FSp_fopen.h>
+#endif
+}
+
+#if TARGET_CARBON
+#include <CodeFragments.h> // Needed for definition of kUnresolvedCFragSymbolAddress
+#include <LaunchServices.h>
+#endif
+
+#pragma mark [Constants]
+
+const OSType kDefaultCreator = 'MOSS';
+
+#pragma mark -
+#pragma mark [nsPathParser]
+
+class nsPathParser
+{
+public:
+ nsPathParser(const nsACString &path);
+
+ ~nsPathParser()
+ {
+ if (mAllocatedBuffer)
+ nsMemory::Free(mAllocatedBuffer);
+ }
+
+ const char* First()
+ {
+ return nsCRT::strtok(mBuffer, ":", &mNewString);
+ }
+ const char* Next()
+ {
+ return nsCRT::strtok(mNewString, ":", &mNewString);
+ }
+ const char* Remainder()
+ {
+ return mNewString;
+ }
+
+private:
+ char mAutoBuffer[512];
+ char *mAllocatedBuffer;
+ char *mBuffer, *mNewString;
+};
+
+nsPathParser::nsPathParser(const nsACString &inPath) :
+ mAllocatedBuffer(nsnull), mNewString(nsnull)
+{
+ PRUint32 inPathLen = inPath.Length();
+ if (inPathLen >= sizeof(mAutoBuffer)) {
+ mAllocatedBuffer = (char *)nsMemory::Alloc(inPathLen + 1);
+ mBuffer = mAllocatedBuffer;
+ }
+ else
+ mBuffer = mAutoBuffer;
+
+ // copy inPath into mBuffer
+ nsACString::const_iterator start, end;
+ inPath.BeginReading(start);
+ inPath.EndReading(end);
+
+ PRUint32 size, offset = 0;
+ for ( ; start != end; start.advance(size)) {
+ const char* buf = start.get();
+ size = start.size_forward();
+ memcpy(mBuffer + offset, buf, size);
+ offset += size;
+ }
+ mBuffer[offset] = '\0';
+}
+
+#pragma mark -
+#pragma mark [static util funcs]
+
+static inline void ClearFSSpec(FSSpec& aSpec)
+{
+ aSpec.vRefNum = 0;
+ aSpec.parID = 0;
+ aSpec.name[0] = 0;
+}
+
+
+// Simple func to map Mac OS errors into nsresults
+static nsresult MacErrorMapper(OSErr inErr)
+{
+ nsresult outErr;
+
+ switch (inErr)
+ {
+ case noErr:
+ outErr = NS_OK;
+ break;
+
+ case fnfErr:
+ outErr = NS_ERROR_FILE_NOT_FOUND;
+ break;
+
+ case dupFNErr:
+ outErr = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+
+ case dskFulErr:
+ outErr = NS_ERROR_FILE_DISK_FULL;
+ break;
+
+ case fLckdErr:
+ outErr = NS_ERROR_FILE_IS_LOCKED;
+ break;
+
+ // Can't find good map for some
+ case bdNamErr:
+ outErr = NS_ERROR_FAILURE;
+ break;
+
+ default:
+ outErr = NS_ERROR_FAILURE;
+ break;
+ }
+ return outErr;
+}
+
+
+
+/*----------------------------------------------------------------------------
+ IsEqualFSSpec
+
+ Compare two canonical FSSpec records.
+
+ Entry: file1 = pointer to first FSSpec record.
+ file2 = pointer to second FSSpec record.
+
+ Exit: function result = true if the FSSpec records are equal.
+----------------------------------------------------------------------------*/
+
+static PRBool IsEqualFSSpec(const FSSpec& file1, const FSSpec& file2)
+{
+ return
+ file1.vRefNum == file2.vRefNum &&
+ file1.parID == file2.parID &&
+ EqualString(file1.name, file2.name, false, true);
+}
+
+
+/*----------------------------------------------------------------------------
+ GetParentFolderSpec
+
+ Given an FSSpec to a (possibly non-existent) file, get an FSSpec for its
+ parent directory.
+
+----------------------------------------------------------------------------*/
+
+static OSErr GetParentFolderSpec(const FSSpec& fileSpec, FSSpec& parentDirSpec)
+{
+ CInfoPBRec pBlock = {0};
+ OSErr err = noErr;
+
+ parentDirSpec.name[0] = 0;
+
+ pBlock.dirInfo.ioVRefNum = fileSpec.vRefNum;
+ pBlock.dirInfo.ioDrDirID = fileSpec.parID;
+ pBlock.dirInfo.ioNamePtr = (StringPtr)parentDirSpec.name;
+ pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
+ err = PBGetCatInfoSync(&pBlock);
+ if (err != noErr) return err;
+
+ parentDirSpec.vRefNum = fileSpec.vRefNum;
+ parentDirSpec.parID = pBlock.dirInfo.ioDrParID;
+
+ return err;
+}
+
+
+/*----------------------------------------------------------------------------
+ VolHasDesktopDB
+
+ Check to see if a volume supports the new desktop database.
+
+ Entry: vRefNum = vol ref num of volumn
+
+ Exit: function result = error code.
+ *hasDesktop = true if volume has the new desktop database.
+----------------------------------------------------------------------------*/
+
+static OSErr VolHasDesktopDB (short vRefNum, Boolean *hasDesktop)
+{
+ HParamBlockRec pb;
+ GetVolParmsInfoBuffer info;
+ OSErr err = noErr;
+
+ pb.ioParam.ioCompletion = nil;
+ pb.ioParam.ioNamePtr = nil;
+ pb.ioParam.ioVRefNum = vRefNum;
+ pb.ioParam.ioBuffer = (Ptr)&info;
+ pb.ioParam.ioReqCount = sizeof(info);
+ err = PBHGetVolParmsSync(&pb);
+ *hasDesktop = err == noErr && (info.vMAttrib & (1L << bHasDesktopMgr)) != 0;
+ return err;
+}
+
+
+/*----------------------------------------------------------------------------
+ GetLastModDateTime
+
+ Get the last mod date and time of a file.
+
+ Entry: fSpec = pointer to file spec.
+
+ Exit: function result = error code.
+ *lastModDateTime = last mod date and time.
+----------------------------------------------------------------------------*/
+
+static OSErr GetLastModDateTime(const FSSpec *fSpec, unsigned long *lastModDateTime)
+{
+ CInfoPBRec pBlock;
+ OSErr err = noErr;
+
+ pBlock.hFileInfo.ioNamePtr = (StringPtr)fSpec->name;
+ pBlock.hFileInfo.ioVRefNum = fSpec->vRefNum;
+ pBlock.hFileInfo.ioFDirIndex = 0;
+ pBlock.hFileInfo.ioDirID = fSpec->parID;
+ err = PBGetCatInfoSync(&pBlock);
+ if (err != noErr) return err;
+ *lastModDateTime = pBlock.hFileInfo.ioFlMdDat;
+ return noErr;
+}
+
+
+/*----------------------------------------------------------------------------
+ FindAppOnVolume
+
+ Find an application on a volume.
+
+ Entry: sig = application signature.
+ vRefNum = vol ref num
+
+ Exit: function result = error code
+ = afpItemNotFound if app not found on vol.
+ *file = file spec for application on volume.
+----------------------------------------------------------------------------*/
+
+static OSErr FindAppOnVolume (OSType sig, short vRefNum, FSSpec *file)
+{
+ DTPBRec pb;
+ OSErr err = noErr;
+ short ioDTRefNum, i;
+ FInfo fInfo;
+ FSSpec candidate;
+ unsigned long lastModDateTime, maxLastModDateTime;
+
+ memset(&pb, 0, sizeof(DTPBRec));
+ pb.ioCompletion = nil;
+ pb.ioVRefNum = vRefNum;
+ pb.ioNamePtr = nil;
+ err = PBDTGetPath(&pb);
+ if (err != noErr) return err;
+ ioDTRefNum = pb.ioDTRefNum;
+
+ memset(&pb, 0, sizeof(DTPBRec));
+ pb.ioCompletion = nil;
+ pb.ioIndex = 0;
+ pb.ioFileCreator = sig;
+ pb.ioNamePtr = file->name;
+ pb.ioDTRefNum = ioDTRefNum;
+ err = PBDTGetAPPLSync(&pb);
+
+ if (err == fnfErr || err == paramErr) return afpItemNotFound;
+ if (err != noErr) return err;
+
+ file->vRefNum = vRefNum;
+ file->parID = pb.ioAPPLParID;
+
+ err = FSpGetFInfo(file, &fInfo);
+ if (err == noErr) return noErr;
+
+ i = 1;
+ maxLastModDateTime = 0;
+ while (true)
+ {
+ memset(&pb, 0, sizeof(DTPBRec));
+ pb.ioCompletion = nil;
+ pb.ioIndex = i;
+ pb.ioFileCreator = sig;
+ pb.ioNamePtr = candidate.name;
+ pb.ioDTRefNum = ioDTRefNum;
+ err = PBDTGetAPPLSync(&pb);
+ if (err != noErr) break;
+ candidate.vRefNum = vRefNum;
+ candidate.parID = pb.ioAPPLParID;
+ err = GetLastModDateTime(file, &lastModDateTime);
+ if (err == noErr) {
+ if (lastModDateTime > maxLastModDateTime) {
+ maxLastModDateTime = lastModDateTime;
+ *file = candidate;
+ }
+ }
+ i++;
+ }
+
+ return maxLastModDateTime > 0 ? noErr : afpItemNotFound;
+}
+
+
+/*----------------------------------------------------------------------------
+ GetIndVolume
+
+ Get a volume reference number by volume index.
+
+ Entry: index = volume index
+
+ Exit: function result = error code.
+ *vRefNum = vol ref num of indexed volume.
+----------------------------------------------------------------------------*/
+
+static OSErr GetIndVolume(short index, short *vRefNum)
+{
+ HParamBlockRec pb;
+ Str63 volumeName;
+ OSErr err = noErr;
+
+ pb.volumeParam.ioCompletion = nil;
+ pb.volumeParam.ioNamePtr = volumeName;
+ pb.volumeParam.ioVolIndex = index;
+
+ err = PBHGetVInfoSync(&pb);
+
+ *vRefNum = pb.volumeParam.ioVRefNum;
+ return err;
+}
+
+
+// Private NSPR functions
+static unsigned long gJanuaryFirst1970Seconds = 0;
+/*
+ * The geographic location and time zone information of a Mac
+ * are stored in extended parameter RAM. The ReadLocation
+ * produdure uses the geographic location record, MachineLocation,
+ * to read the geographic location and time zone information in
+ * extended parameter RAM.
+ *
+ * Because serial port and SLIP conflict with ReadXPram calls,
+ * we cache the call here.
+ *
+ * Caveat: this caching will give the wrong result if a session
+ * extend across the DST changeover time.
+ */
+
+static void MyReadLocation(MachineLocation *loc)
+{
+ static MachineLocation storedLoc;
+ static Boolean didReadLocation = false;
+
+ if (!didReadLocation) {
+ ReadLocation(&storedLoc);
+ didReadLocation = true;
+ }
+ *loc = storedLoc;
+}
+
+static long GMTDelta(void)
+{
+ MachineLocation loc;
+ long gmtDelta;
+
+ MyReadLocation(&loc);
+ gmtDelta = loc.u.gmtDelta & 0x00ffffff;
+ if (gmtDelta & 0x00800000) { /* test sign extend bit */
+ gmtDelta |= 0xff000000;
+ }
+ return gmtDelta;
+}
+
+static void MacintoshInitializeTime(void)
+{
+ /*
+ * The NSPR epoch is midnight, Jan. 1, 1970 GMT.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ * midnight Jan. 1, 1970 + GMTDelta().
+ *
+ * Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
+ * = 2082844800 seconds since the Mac epoch.
+ * (There were 17 leap years from 1904 to 1970.)
+ *
+ * So the NSPR epoch is 2082844800 + GMTDelta() seconds since
+ * the Mac epoch. Whew! :-)
+ */
+ gJanuaryFirst1970Seconds = 2082844800 + GMTDelta();
+}
+
+static nsresult ConvertMacTimeToMilliseconds( PRInt64* aLastModifiedTime, PRUint32 timestamp )
+{
+ if ( gJanuaryFirst1970Seconds == 0)
+ MacintoshInitializeTime();
+ timestamp -= gJanuaryFirst1970Seconds;
+ PRTime usecPerSec, dateInMicroSeconds;
+ LL_I2L(dateInMicroSeconds, timestamp);
+ LL_I2L(usecPerSec, PR_MSEC_PER_SEC);
+ LL_MUL(*aLastModifiedTime, usecPerSec, dateInMicroSeconds);
+ return NS_OK;
+}
+
+static nsresult ConvertMillisecondsToMacTime(PRInt64 aTime, PRUint32 *aOutMacTime)
+{
+ NS_ENSURE_ARG( aOutMacTime );
+
+ PRTime usecPerSec, dateInSeconds;
+ dateInSeconds = LL_ZERO;
+
+ LL_I2L(usecPerSec, PR_MSEC_PER_SEC);
+ LL_DIV(dateInSeconds, aTime, usecPerSec); // dateInSeconds = aTime/1,000
+ LL_L2UI(*aOutMacTime, dateInSeconds);
+ *aOutMacTime += 2082844800; // date + Mac epoch
+
+ return NS_OK;
+}
+
+static void myPLstrcpy(Str255 dst, const char* src)
+{
+ int srcLength = strlen(src);
+ NS_ASSERTION(srcLength <= 255, "Oops, Str255 can't hold >255 chars");
+ if (srcLength > 255)
+ srcLength = 255;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+static void myPLstrncpy(Str255 dst, const char* src, int inMax)
+{
+ int srcLength = strlen(src);
+ if (srcLength > inMax)
+ srcLength = inMax;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+/*
+ NS_TruncNodeName
+
+ Utility routine to do a mid-trunc on a potential file name so that it is
+ no longer than 31 characters. Until we move to the HFS+ APIs we need this
+ to come up with legal Mac file names.
+
+ Entry: aNode = initial file name
+ outBuf = scratch buffer for the truncated name (MUST be >= 32 characters)
+
+ Exit: function result = pointer to truncated name. Will be either aNode or outBuf.
+
+*/
+const char* NS_TruncNodeName(const char *aNode, char *outBuf)
+{
+ PRUint32 nodeLen;
+ if ((nodeLen = strlen(aNode)) > 31)
+ {
+ static PRBool sInitialized = PR_FALSE;
+ static CharByteTable sTable;
+ // Init to "..." in case we fail to get the ellipsis token
+ static char sEllipsisTokenStr[4] = { '.', '.', '.', 0 };
+ static PRUint8 sEllipsisTokenLen = 3;
+
+ if (!sInitialized)
+ {
+ // Entries in the table are:
+ // 0 == 1 byte char
+ // 1 == 2 byte char
+ FillParseTable(sTable, smSystemScript);
+
+ Handle itl4ResHandle = nsnull;
+ long offset, len;
+ ::GetIntlResourceTable(smSystemScript, smUnTokenTable, &itl4ResHandle, &offset, &len);
+ if (itl4ResHandle)
+ {
+ UntokenTable *untokenTableRec = (UntokenTable *)(*itl4ResHandle + offset);
+ if (untokenTableRec->lastToken >= tokenEllipsis)
+ {
+ offset += untokenTableRec->index[tokenEllipsis];
+ char *tokenStr = (*itl4ResHandle + offset);
+ sEllipsisTokenLen = tokenStr[0];
+ memcpy(sEllipsisTokenStr, &tokenStr[1], sEllipsisTokenLen);
+ }
+ ::ReleaseResource(itl4ResHandle);
+ }
+ sInitialized = PR_TRUE;
+ }
+
+ PRInt32 halfLen = (31 - sEllipsisTokenLen) / 2;
+ PRInt32 charSize = 0, srcPos, destPos;
+ for (srcPos = 0; srcPos + charSize <= halfLen; srcPos += charSize)
+ charSize = sTable[aNode[srcPos]] ? 2 : 1;
+
+ memcpy(outBuf, aNode, srcPos);
+ memcpy(outBuf + srcPos, sEllipsisTokenStr, sEllipsisTokenLen);
+ destPos = srcPos + sEllipsisTokenLen;
+
+ for (; srcPos < nodeLen - halfLen; srcPos += charSize)
+ charSize = sTable[aNode[srcPos]] ? 2 : 1;
+
+ memcpy(outBuf + destPos, aNode + srcPos, nodeLen - srcPos);
+ destPos += (nodeLen - srcPos);
+ outBuf[destPos] = '\0';
+ return outBuf;
+ }
+ return aNode;
+}
+
+/**
+ * HFSPlusGetRawPath returns the path for an FSSpec as a unicode string.
+ *
+ * The reason for this routine instead of just calling FSRefMakePath is
+ * (1) inSpec does not have to exist
+ * (2) FSRefMakePath uses '/' as the separator under OSX and ':' under OS9
+ */
+static OSErr HFSPlusGetRawPath(const FSSpec& inSpec, nsAString& outStr)
+{
+ OSErr err;
+ nsAutoString ucPathString;
+
+ outStr.Truncate(0);
+
+ FSRef nodeRef;
+ FSCatalogInfo catalogInfo;
+ catalogInfo.parentDirID = 0;
+ err = ::FSpMakeFSRef(&inSpec, &nodeRef);
+
+ if (err == fnfErr) {
+ FSSpec parentDirSpec;
+ err = GetParentFolderSpec(inSpec, parentDirSpec);
+ if (err == noErr) {
+ const char *startPtr = (const char*)&inSpec.name[1];
+ NS_CopyNativeToUnicode(Substring(startPtr, startPtr + PRUint32(inSpec.name[0])), outStr);
+ err = ::FSpMakeFSRef(&parentDirSpec, &nodeRef);
+ }
+ }
+
+ while (err == noErr && catalogInfo.parentDirID != fsRtParID) {
+ HFSUniStr255 nodeName;
+ FSRef parentRef;
+ err = ::FSGetCatalogInfo(&nodeRef,
+ kFSCatInfoNodeFlags + kFSCatInfoParentDirID,
+ &catalogInfo,
+ &nodeName,
+ nsnull,
+ &parentRef);
+ if (err == noErr)
+ {
+ if (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask)
+ nodeName.unicode[nodeName.length++] = PRUnichar(':');
+ const PRUnichar* nodeNameUni = (const PRUnichar*) nodeName.unicode;
+ outStr.Insert(Substring(nodeNameUni, nodeNameUni + nodeName.length), 0);
+ nodeRef = parentRef;
+ }
+ }
+ return err;
+}
+
+
+// The R**co FSSpec resolver -
+// it slices, it dices, it juliannes fries and it even creates FSSpecs out of whatever you feed it
+// This function will take a path and a starting FSSpec and generate a FSSpec to represent
+// the target of the two. If the intial FSSpec is null the path alone will be resolved
+static OSErr ResolvePathAndSpec(const char * filePath, FSSpec *inSpec, PRBool createDirs, FSSpec *outSpec)
+{
+ OSErr err = noErr;
+ size_t inLength = strlen(filePath);
+ Boolean isRelative = (filePath && inSpec);
+ FSSpec tempSpec;
+ Str255 ppath;
+ Boolean isDirectory;
+
+ if (isRelative && inSpec)
+ {
+ outSpec->vRefNum = inSpec->vRefNum;
+ outSpec->parID = inSpec->parID;
+
+ if (inSpec->name[0] != 0)
+ {
+ long theDirID;
+
+ err = FSpGetDirectoryID(inSpec, &theDirID, &isDirectory);
+
+ if (err == noErr && isDirectory)
+ outSpec->parID = theDirID;
+ else if (err == fnfErr && createDirs)
+ {
+ err = FSpDirCreate(inSpec, smCurrentScript, &theDirID);
+ if (err == noErr)
+ outSpec->parID = theDirID;
+ else if (err == fnfErr)
+ err = dirNFErr;
+ }
+ }
+ }
+ else
+ {
+ outSpec->vRefNum = 0;
+ outSpec->parID = 0;
+ }
+
+ if (err)
+ return err;
+
+ // Try making an FSSpec from the path
+ if (inLength < 255)
+ {
+ // Use tempSpec as dest because if FSMakeFSSpec returns dirNFErr, it
+ // will reset the dest spec and we'll lose what we determined above.
+
+ myPLstrcpy(ppath, filePath);
+ err = ::FSMakeFSSpec(outSpec->vRefNum, outSpec->parID, ppath, &tempSpec);
+ if (err == noErr || err == fnfErr)
+ *outSpec = tempSpec;
+ }
+ else if (!isRelative)
+ {
+ err = ::FSpLocationFromFullPath(inLength, filePath, outSpec);
+ }
+ else
+ { // If the path is relative and >255 characters we need to manually walk the
+ // path appending each node to the initial FSSpec so to reach that code we
+ // set the err to bdNamErr and fall into the code below
+ err = bdNamErr;
+ }
+
+ // If we successfully created a spec then leave
+ if (err == noErr)
+ return err;
+
+ // We get here when the directory hierarchy needs to be created or we're resolving
+ // a relative path >255 characters long
+ if (err == dirNFErr || err == bdNamErr)
+ {
+ const char* path = filePath;
+
+ if (!isRelative) // If path is relative, we still need vRefNum & parID.
+ {
+ outSpec->vRefNum = 0;
+ outSpec->parID = 0;
+ }
+
+ do
+ {
+ // Locate the colon that terminates the node.
+ // But if we've a partial path (starting with a colon), find the second one.
+ const char* nextColon = strchr(path + (*path == ':'), ':');
+ // Well, if there are no more colons, point to the end of the string.
+ if (!nextColon)
+ nextColon = path + strlen(path);
+
+ // Make a pascal string out of this node. Include initial
+ // and final colon, if any!
+ myPLstrncpy(ppath, path, nextColon - path + 1);
+
+ // Use this string as a relative path using the directory created
+ // on the previous round (or directory 0,0 on the first round).
+ err = ::FSMakeFSSpec(outSpec->vRefNum, outSpec->parID, ppath, outSpec);
+
+ // If this was the leaf node, then we are done.
+ if (!*nextColon)
+ break;
+
+ // Since there's more to go, we have to get the directory ID, which becomes
+ // the parID for the next round.
+ if (err == noErr)
+ {
+ // The directory (or perhaps a file) exists. Find its dirID.
+ long dirID;
+ err = ::FSpGetDirectoryID(outSpec, &dirID, &isDirectory);
+ if (!isDirectory)
+ err = dupFNErr; // oops! a file exists with that name.
+ if (err != noErr)
+ break; // bail if we've got an error
+ outSpec->parID = dirID;
+ }
+ else if ((err == fnfErr) && createDirs)
+ {
+ // If we got "file not found" and we're allowed to create directories
+ // then we need to create one
+ err = ::FSpDirCreate(outSpec, smCurrentScript, &outSpec->parID);
+ // For some reason, this usually returns fnfErr, even though it works.
+ if (err == fnfErr)
+ err = noErr;
+ }
+ if (err != noErr)
+ break;
+ path = nextColon; // next round
+ } while (true);
+ }
+
+ return err;
+}
+
+
+#pragma mark -
+#pragma mark [StFollowLinksState]
+class StFollowLinksState
+{
+ public:
+ StFollowLinksState(nsILocalFile *aFile) :
+ mFile(aFile)
+ {
+ NS_ASSERTION(mFile, "StFollowLinksState passed a NULL file.");
+ if (mFile)
+ mFile->GetFollowLinks(&mSavedState);
+ }
+
+ StFollowLinksState(nsILocalFile *aFile, PRBool followLinksState) :
+ mFile(aFile)
+ {
+ NS_ASSERTION(mFile, "StFollowLinksState passed a NULL file.");
+ if (mFile) {
+ mFile->GetFollowLinks(&mSavedState);
+ mFile->SetFollowLinks(followLinksState);
+ }
+ }
+
+ ~StFollowLinksState()
+ {
+ if (mFile)
+ mFile->SetFollowLinks(mSavedState);
+ }
+
+ private:
+ nsCOMPtr<nsILocalFile> mFile;
+ PRBool mSavedState;
+};
+
+#pragma mark -
+#pragma mark [nsDirEnumerator]
+class nsDirEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator()
+ {
+ }
+
+ nsresult Init(nsILocalFileMac* parent)
+ {
+ NS_ENSURE_ARG(parent);
+ nsresult rv;
+ FSSpec fileSpec;
+
+ rv = parent->GetFSSpec(&fileSpec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err;
+ Boolean isDirectory;
+
+ err = ::FSpGetDirectoryID(&fileSpec, &mDirID, &isDirectory);
+ if (err || !isDirectory)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ mCatInfo.hFileInfo.ioNamePtr = mItemName;
+ mCatInfo.hFileInfo.ioVRefNum = fileSpec.vRefNum;
+ mItemIndex = 1;
+
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ nsresult rv = NS_OK;
+ if (mNext == nsnull)
+ {
+ mItemName[0] = 0;
+ mCatInfo.dirInfo.ioFDirIndex = mItemIndex;
+ mCatInfo.dirInfo.ioDrDirID = mDirID;
+
+ OSErr err = ::PBGetCatInfoSync(&mCatInfo);
+ if (err == fnfErr)
+ {
+ // end of dir entries
+ *result = PR_FALSE;
+ return NS_OK;
+ }
+
+ // Make a new nsILocalFile for the new element
+ FSSpec tempSpec;
+ tempSpec.vRefNum = mCatInfo.hFileInfo.ioVRefNum;
+ tempSpec.parID = mDirID;
+ ::BlockMoveData(mItemName, tempSpec.name, mItemName[0] + 1);
+
+ rv = NS_NewLocalFileWithFSSpec(&tempSpec, PR_TRUE, getter_AddRefs(mNext));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = nsnull;
+
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ ++mItemIndex;
+ return NS_OK;
+ }
+
+ private:
+ ~nsDirEnumerator() {}
+
+ protected:
+ nsCOMPtr<nsILocalFileMac> mNext;
+
+ CInfoPBRec mCatInfo;
+ short mItemIndex;
+ long mDirID;
+ Str63 mItemName;
+};
+
+NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
+
+#pragma mark -
+
+OSType nsLocalFile::sCurrentProcessSignature = 0;
+PRBool nsLocalFile::sHasHFSPlusAPIs = PR_FALSE;
+PRBool nsLocalFile::sRunningOSX = PR_FALSE;
+
+#pragma mark [CTOR/DTOR]
+nsLocalFile::nsLocalFile() :
+ mFollowLinks(PR_TRUE),
+ mFollowLinksDirty(PR_TRUE),
+ mSpecDirty(PR_TRUE),
+ mCatInfoDirty(PR_TRUE),
+ mType('TEXT'),
+ mCreator(kDefaultCreator)
+{
+ ClearFSSpec(mSpec);
+ ClearFSSpec(mTargetSpec);
+
+ InitClassStatics();
+ if (sCurrentProcessSignature != 0)
+ mCreator = sCurrentProcessSignature;
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& srcFile)
+{
+ *this = srcFile;
+}
+
+nsLocalFile::nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath) :
+ mFollowLinks(PR_TRUE),
+ mFollowLinksDirty(PR_TRUE),
+ mSpecDirty(PR_TRUE),
+ mSpec(aSpec),
+ mAppendedPath(aAppendedPath),
+ mCatInfoDirty(PR_TRUE),
+ mType('TEXT'),
+ mCreator(kDefaultCreator)
+{
+ ClearFSSpec(mTargetSpec);
+
+ InitClassStatics();
+ if (sCurrentProcessSignature != 0)
+ mCreator = sCurrentProcessSignature;
+}
+
+nsLocalFile& nsLocalFile::operator=(const nsLocalFile& rhs)
+{
+ mFollowLinks = rhs.mFollowLinks;
+ mFollowLinksDirty = rhs.mFollowLinksDirty;
+ mSpecDirty = rhs.mSpecDirty;
+ mSpec = rhs.mSpec;
+ mAppendedPath = rhs.mAppendedPath;
+ mTargetSpec = rhs.mTargetSpec;
+ mCatInfoDirty = rhs.mCatInfoDirty;
+ mType = rhs.mType;
+ mCreator = rhs.mCreator;
+
+ if (!rhs.mCatInfoDirty)
+ mCachedCatInfo = rhs.mCachedCatInfo;
+
+ return *this;
+}
+
+#pragma mark -
+#pragma mark [nsISupports interface implementation]
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile,
+ nsILocalFileMac,
+ nsILocalFile,
+ nsIFile)
+
+NS_METHOD
+nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+// This function resets any cached information about the file.
+void
+nsLocalFile::MakeDirty()
+{
+ mSpecDirty = PR_TRUE;
+ mFollowLinksDirty = PR_TRUE;
+ mCatInfoDirty = PR_TRUE;
+
+ ClearFSSpec(mTargetSpec);
+}
+
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ NS_ENSURE_ARG_POINTER(aFollowLinks);
+ *aFollowLinks = mFollowLinks;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ if (aFollowLinks != mFollowLinks)
+ {
+ mFollowLinks = aFollowLinks;
+ mFollowLinksDirty = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::ResolveAndStat()
+{
+ OSErr err = noErr;
+ FSSpec resolvedSpec;
+
+ // fnfErr means target spec is valid but doesn't exist.
+ // If the end result is fnfErr, we're cleanly resolved.
+
+ if (mSpecDirty)
+ {
+ if (mAppendedPath.Length())
+ {
+ err = ResolvePathAndSpec(mAppendedPath.get(), &mSpec, PR_FALSE, &resolvedSpec);
+ if (err == noErr)
+ mAppendedPath.Truncate(0);
+ }
+ else
+ err = ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &resolvedSpec);
+ if (err == noErr)
+ {
+ mSpec = resolvedSpec;
+ mSpecDirty = PR_FALSE;
+ }
+ mFollowLinksDirty = PR_TRUE;
+ }
+ if (mFollowLinksDirty && (err == noErr))
+ {
+ if (mFollowLinks)
+ {
+ // Resolve the alias to the original file.
+ resolvedSpec = mSpec;
+ Boolean resolvedWasFolder, resolvedWasAlias;
+ err = ::ResolveAliasFile(&resolvedSpec, TRUE, &resolvedWasFolder, &resolvedWasAlias);
+ if (err == noErr || err == fnfErr) {
+ err = noErr;
+ mTargetSpec = resolvedSpec;
+ mFollowLinksDirty = PR_FALSE;
+ }
+ }
+ else
+ {
+ mTargetSpec = mSpec;
+ mFollowLinksDirty = PR_FALSE;
+ }
+ mCatInfoDirty = PR_TRUE;
+ }
+
+ return (MacErrorMapper(err));
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ // The incoming path must be a FULL path
+
+ if (filePath.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ MakeDirty();
+
+ // If it starts with a colon, it's invalid
+ if (filePath.First() == ':')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ nsPathParser parser(filePath);
+ OSErr err;
+ Str255 pascalNode;
+ FSSpec nodeSpec;
+
+ const char *root = parser.First();
+ if (root == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // The first component must be an existing volume
+ myPLstrcpy(pascalNode, root);
+ pascalNode[++pascalNode[0]] = ':';
+ err = ::FSMakeFSSpec(0, 0, pascalNode, &nodeSpec);
+ if (err)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // Build as much of a spec as possible from the rest of the path
+ // What doesn't exist will be left over in mAppendedPath
+ const char *nextNode;
+ while ((nextNode = parser.Next()) != nsnull) {
+ long dirID;
+ Boolean isDir;
+ err = ::FSpGetDirectoryID(&nodeSpec, &dirID, &isDir);
+ if (err || !isDir)
+ break;
+ myPLstrcpy(pascalNode, nextNode);
+ err = ::FSMakeFSSpec(nodeSpec.vRefNum, dirID, pascalNode, &nodeSpec);
+ if (err == fnfErr)
+ break;
+ }
+ mSpec = nodeSpec;
+ mAppendedPath = parser.Remainder();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(filePath, fsStr)))
+ rv = InitWithNativePath(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+ NS_ENSURE_ARG(aFile);
+ nsLocalFile *asLocalFile = dynamic_cast<nsLocalFile*>(aFile);
+ if (!asLocalFile)
+ return NS_ERROR_NO_INTERFACE; // Well, sort of.
+ *this = *asLocalFile;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+// Macintosh doesn't really have mode bits, just drop them
+#pragma unused (mode)
+
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = NS_OK;
+ FSSpec spec;
+ OSErr err = noErr;
+
+ rv = ResolveAndStat();
+ if (rv == NS_ERROR_FILE_NOT_FOUND && (flags & PR_CREATE_FILE))
+ rv = NS_OK;
+
+ if (flags & PR_CREATE_FILE) {
+ rv = Create(nsIFile::NORMAL_FILE_TYPE, 0);
+ /* If opening with the PR_EXCL flag the existence of the file prior to opening is an error */
+ if ((flags & PR_EXCL) && (rv == NS_ERROR_FILE_ALREADY_EXISTS))
+ return rv;
+ }
+
+ rv = GetFSSpec(&spec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ SInt8 perm;
+ if (flags & PR_RDWR)
+ perm = fsRdWrPerm;
+ else if (flags & PR_WRONLY)
+ perm = fsWrPerm;
+ else
+ perm = fsRdPerm;
+
+ short refnum;
+ err = ::FSpOpenDF(&spec, perm, &refnum);
+
+ if (err == noErr && (flags & PR_TRUNCATE))
+ err = ::SetEOF(refnum, 0);
+ if (err == noErr && (flags & PR_APPEND))
+ err = ::SetFPos(refnum, fsFromLEOF, 0);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ if ((*_retval = PR_ImportFile(refnum)) == 0)
+ return NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,(PR_GetError() & 0xFFFF));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
+{
+ NS_ENSURE_ARG(mode);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult rv;
+ FSSpec spec;
+
+ rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ if (mode[0] == 'w' || mode[0] == 'a') // Create if it doesn't exist
+ {
+ if (rv == NS_ERROR_FILE_NOT_FOUND) {
+ mType = (mode[1] == 'b') ? 'BiNA' : 'TEXT';
+ rv = Create(nsIFile::NORMAL_FILE_TYPE, 0);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ rv = GetFSSpec(&spec);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef MACOSX
+ // FSp_fopen() doesn't exist under macosx :-(
+ nsXPIDLCString ourPath;
+ rv = GetPath(getter_Copies(ourPath));
+ if (NS_FAILED(rv))
+ return rv;
+ *_retval = fopen(ourPath, mode);
+#else
+ *_retval = FSp_fopen(&spec, mode);
+#endif
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_FAILURE;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
+{
+ OSErr err;
+
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ FSSpec newSpec;
+
+ if (mAppendedPath.Length())
+ { // We've got an FSSpec and an appended path so pass 'em both to ResolvePathAndSpec
+ err = ResolvePathAndSpec(mAppendedPath.get(), &mSpec, PR_TRUE, &newSpec);
+ }
+ else
+ {
+ err = ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &newSpec);
+ }
+
+ if (err != noErr && err != fnfErr)
+ return (MacErrorMapper(err));
+
+ switch (type)
+ {
+ case NORMAL_FILE_TYPE:
+ SetOSTypeAndCreatorFromExtension();
+ err = ::FSpCreate(&newSpec, mCreator, mType, smCurrentScript);
+ break;
+
+ case DIRECTORY_TYPE:
+ {
+ long newDirID;
+ err = ::FSpDirCreate(&newSpec, smCurrentScript, &newDirID);
+ // For some reason, this usually returns fnfErr, even though it works.
+ if (err == fnfErr)
+ err = noErr;
+ }
+ break;
+
+ default:
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+ break;
+ }
+
+ if (err == noErr)
+ {
+ mSpec = mTargetSpec = newSpec;
+ mAppendedPath.Truncate(0);
+ }
+
+ return (MacErrorMapper(err));
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &aNode)
+{
+ if (aNode.IsEmpty())
+ return NS_OK;
+
+ nsACString::const_iterator start, end;
+ aNode.BeginReading(start);
+ aNode.EndReading(end);
+ if (FindCharInReadable(':', start, end))
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ MakeDirty();
+
+ char truncBuffer[32];
+ const char *node = NS_TruncNodeName(PromiseFlatCString(aNode).get(), truncBuffer);
+
+ if (!mAppendedPath.Length())
+ {
+ OSErr err;
+ Boolean resolvedWasFolder, resolvedWasAlias;
+ err = ::ResolveAliasFile(&mSpec, TRUE, &resolvedWasFolder, &resolvedWasAlias);
+ if (err == noErr)
+ {
+ long dirID;
+ Boolean isDir;
+
+ if (!resolvedWasFolder)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+ if ((err = ::FSpGetDirectoryID(&mSpec, &dirID, &isDir)) != noErr)
+ return MacErrorMapper(err);
+
+ FSSpec childSpec;
+ Str255 pascalNode;
+ myPLstrcpy(pascalNode, node);
+ err = ::FSMakeFSSpec(mSpec.vRefNum, dirID, pascalNode, &childSpec);
+ if (err && err != fnfErr)
+ return MacErrorMapper(err);
+ mSpec = childSpec;
+ }
+ else if (err == fnfErr)
+ mAppendedPath.Assign(node);
+ else
+ return MacErrorMapper(err);
+ }
+ else
+ {
+ if (mAppendedPath.First() != ':')
+ mAppendedPath.Insert(':', 0);
+ mAppendedPath.Append(":");
+ mAppendedPath.Append(node);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Append(const nsAString &node)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(node, fsStr)))
+ rv = AppendNative(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &relPath)
+{
+ if (relPath.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ nsresult rv;
+ nsPathParser parser(relPath);
+ const char* node = parser.First();
+
+ while (node)
+ {
+ if (NS_FAILED(rv = AppendNative(nsDependentCString(node))))
+ return rv;
+ node = parser.Next();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativePath(const nsAString &relPath)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(relPath, fsStr)))
+ rv = AppendRelativeNativePath(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ aLeafName.Truncate();
+
+ // See if we've had a path appended
+ if (mAppendedPath.Length())
+ {
+ const char* temp = mAppendedPath.get();
+ if (temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ const char* leaf = strrchr(temp, ':');
+
+ // if the working path is just a node without any directory delimeters.
+ if (leaf == nsnull)
+ leaf = temp;
+ else
+ leaf++;
+
+ aLeafName = leaf;
+ }
+ else
+ {
+ // We don't have an appended path so grab the leaf name from the FSSpec
+ // Convert the Pascal string to a C string
+ PRInt32 len = mSpec.name[0];
+ char* leafName = (char *)malloc(len + 1);
+ if (!leafName) return NS_ERROR_OUT_OF_MEMORY;
+ ::BlockMoveData(&mSpec.name[1], leafName, len);
+ leafName[len] = '\0';
+ aLeafName = leafName;
+ free(leafName);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(fsStr)))
+ rv = NS_CopyNativeToUnicode(fsStr, aLeafName);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ if (aLeafName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ MakeDirty();
+
+ char truncBuffer[32];
+ const char *leafName = NS_TruncNodeName(PromiseFlatCString(aLeafName).get(), truncBuffer);
+
+ if (mAppendedPath.Length())
+ { // Lop off the end of the appended path and replace it with the new leaf name
+ PRInt32 offset = mAppendedPath.RFindChar(':');
+ if (offset || ((!offset) && (1 < mAppendedPath.Length())))
+ {
+ mAppendedPath.Truncate(offset + 1);
+ }
+ mAppendedPath.Append(leafName);
+ }
+ else
+ {
+ // We don't have an appended path so directly modify the FSSpec
+ myPLstrcpy(mSpec.name, leafName);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(aLeafName, fsStr)))
+ rv = SetNativeLeafName(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval.Truncate();
+
+ nsCAutoString fsCharSetPathStr;
+
+#if TARGET_CARBON
+ if (sHasHFSPlusAPIs) // should always be true under Carbon, but in case...
+ {
+ OSErr err;
+ nsresult rv;
+ nsAutoString ucPathString;
+
+ if ((err = HFSPlusGetRawPath(mSpec, ucPathString)) != noErr)
+ return MacErrorMapper(err);
+ rv = NS_CopyUnicodeToNative(ucPathString, fsCharSetPathStr);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+#endif
+ {
+ // Now would be a good time to call the code that makes an FSSpec into a path
+ short fullPathLen;
+ Handle fullPathHandle;
+ (void)::FSpGetFullPath(&mSpec, &fullPathLen, &fullPathHandle);
+ if (!fullPathHandle)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ ::HLock(fullPathHandle);
+ fsCharSetPathStr.Assign(*fullPathHandle, fullPathLen);
+ ::DisposeHandle(fullPathHandle);
+ }
+
+ // We need to make sure that even if we have a path to a
+ // directory we don't return the trailing colon. It breaks
+ // the component manager. (Bugzilla bug #26102)
+ if (fsCharSetPathStr.Last() == ':')
+ fsCharSetPathStr.Truncate(fsCharSetPathStr.Length() - 1);
+
+ // Now, tack on mAppendedPath. It never ends in a colon.
+ if (mAppendedPath.Length())
+ {
+ if (mAppendedPath.First() != ':')
+ fsCharSetPathStr.Append(":");
+ fsCharSetPathStr.Append(mAppendedPath);
+ }
+
+ _retval = fsCharSetPathStr;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ nsresult rv = NS_OK;
+
+#if TARGET_CARBON
+ if (sHasHFSPlusAPIs) // should always be true under Carbon, but in case...
+ {
+ OSErr err;
+ nsAutoString ucPathString;
+
+ if ((err = HFSPlusGetRawPath(mSpec, ucPathString)) != noErr)
+ return MacErrorMapper(err);
+
+ // We need to make sure that even if we have a path to a
+ // directory we don't return the trailing colon. It breaks
+ // the component manager. (Bugzilla bug #26102)
+ if (ucPathString.Last() == PRUnichar(':'))
+ ucPathString.Truncate(ucPathString.Length() - 1);
+
+ // Now, tack on mAppendedPath. It never ends in a colon.
+ if (mAppendedPath.Length())
+ {
+ nsAutoString ucAppendage;
+ if (mAppendedPath.First() != ':')
+ ucPathString.Append(PRUnichar(':'));
+ rv = NS_CopyNativeToUnicode(mAppendedPath, ucAppendage);
+ if (NS_FAILED(rv))
+ return rv;
+ ucPathString.Append(ucAppendage);
+ }
+
+ _retval = ucPathString;
+ }
+ else
+#endif
+ {
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = GetNativePath(fsStr))) {
+ rv = NS_CopyNativeToUnicode(fsStr, _retval);
+ }
+ }
+ return rv;
+}
+
+nsresult nsLocalFile::MoveCopy( nsIFile* newParentDir, const nsACString &newName, PRBool isCopy, PRBool followLinks )
+{
+ OSErr macErr;
+ FSSpec srcSpec;
+ Str255 newPascalName;
+ nsresult rv;
+
+ StFollowLinksState srcFollowState(this, followLinks);
+ rv = GetFSSpec(&srcSpec);
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ // If newParentDir == nsnull, it's a simple rename
+ if ( !newParentDir )
+ {
+ myPLstrncpy( newPascalName, PromiseFlatCString(newName).get(), 255 );
+ macErr = ::FSpRename( &srcSpec, newPascalName );
+ return MacErrorMapper( macErr );
+ }
+
+ nsCOMPtr<nsILocalFileMac> destDir(do_QueryInterface( newParentDir ));
+ StFollowLinksState destFollowState(destDir, followLinks);
+ FSSpec destSpec;
+ rv = destDir->GetFSSpec(&destSpec);
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ long dirID;
+ Boolean isDirectory;
+ macErr = ::FSpGetDirectoryID(&destSpec, &dirID, &isDirectory);
+ if ( macErr || !isDirectory )
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+
+ if ( !newName.IsEmpty() )
+ myPLstrncpy( newPascalName, PromiseFlatCString(newName).get(), 255);
+ else
+ memcpy(newPascalName, srcSpec.name, srcSpec.name[0] + 1);
+ if ( isCopy )
+ {
+ macErr = ::FSpGetDirectoryID(&srcSpec, &dirID, &isDirectory);
+ if (macErr == noErr)
+ {
+ const PRInt32 kCopyBufferSize = (1024 * 512); // allocate our own buffer to speed file copies. Bug #103202
+ OSErr tempErr;
+ Handle copyBufferHand = ::TempNewHandle(kCopyBufferSize, &tempErr);
+ void* copyBuffer = nsnull;
+ PRInt32 copyBufferSize = 0;
+
+ // it's OK if the allocated failed; FSpFileCopy will just fall back on its own internal 16k buffer
+ if (copyBufferHand)
+ {
+ ::HLock(copyBufferHand);
+ copyBuffer = *copyBufferHand;
+ copyBufferSize = kCopyBufferSize;
+ }
+
+ if ( isDirectory )
+ macErr = MacFSpDirectoryCopyRename( &srcSpec, &destSpec, newPascalName, copyBuffer, copyBufferSize, true, NULL );
+ else
+ macErr = ::FSpFileCopy( &srcSpec, &destSpec, newPascalName, copyBuffer, copyBufferSize, true );
+
+ if (copyBufferHand)
+ ::DisposeHandle(copyBufferHand);
+ }
+ }
+ else
+ {
+ macErr= ::FSpMoveRenameCompat(&srcSpec, &destSpec, newPascalName);
+ if ( macErr == diffVolErr)
+ {
+ // On a different Volume so go for Copy and then delete
+ rv = CopyToNative( newParentDir, newName );
+ if ( NS_FAILED ( rv ) )
+ return rv;
+ return Remove( PR_TRUE );
+ }
+ }
+ return MacErrorMapper( macErr );
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return MoveCopy( newParentDir, newName, PR_TRUE, PR_FALSE );
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToNative(newParentDir, nsCString());
+
+ nsresult rv;
+ nsCAutoString fsStr;
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr)))
+ rv = CopyToNative(newParentDir, fsStr);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return MoveCopy( newParentDir, newName, PR_TRUE, PR_TRUE );
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToFollowingLinksNative(newParentDir, nsCString());
+
+ nsresult rv;
+ nsCAutoString fsStr;
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr)))
+ rv = CopyToFollowingLinksNative(newParentDir, fsStr);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return MoveCopy( newParentDir, newName, PR_FALSE, PR_FALSE );
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return MoveToNative(newParentDir, nsCString());
+
+ nsresult rv;
+ nsCAutoString fsStr;
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr)))
+ rv = MoveToNative(newParentDir, fsStr);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary * *_retval)
+{
+ PRBool isFile;
+ nsresult rv = IsFile(&isFile);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (! isFile)
+ return NS_ERROR_FILE_IS_DIRECTORY;
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+
+#if !TARGET_CARBON
+ // This call to SystemTask is here to give the OS time to grow its
+ // FCB (file control block) list, which it seems to be unable to
+ // do unless we yield some time to the OS. See bugs 64978 & 70543
+ // for the whole story.
+ ::SystemTask();
+#endif
+
+ // Use the new PR_LoadLibraryWithFlags which allows us to use a FSSpec
+ PRLibSpec libSpec;
+ libSpec.type = PR_LibSpec_MacIndexedFragment;
+ libSpec.value.mac_indexed_fragment.fsspec = &mTargetSpec;
+ libSpec.value.mac_indexed_fragment.index = 0;
+ *_retval = PR_LoadLibraryWithFlags(libSpec, 0);
+
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER("PR_LoadLibrary");
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ OSErr err;
+ nsresult rv;
+ FSSpec specToDelete;
+ PRBool isDir;
+
+ StFollowLinksState(this, PR_FALSE);
+
+ rv = IsDirectory(&isDir); // Calls ResolveAndStat()
+ if (NS_FAILED(rv))
+ return rv;
+ rv = GetFSSpec(&specToDelete);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (isDir && recursive)
+ err = ::DeleteDirectory( specToDelete.vRefNum, specToDelete.parID, specToDelete.name );
+ else
+ err = ::HDelete( specToDelete.vRefNum, specToDelete.parID, specToDelete.name );
+
+ return MacErrorMapper( err );
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+ *aLastModifiedTime = 0;
+
+ nsresult rv = ResolveAndStat();
+ if ( NS_FAILED( rv ) )
+ return rv;
+ rv = UpdateCachedCatInfo(PR_TRUE);
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ // The mod date is in the same spot for files and dirs.
+ return ConvertMacTimeToMilliseconds( aLastModifiedTime, mCachedCatInfo.hFileInfo.ioFlMdDat );
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ nsresult rv = ResolveAndStat();
+ if ( NS_FAILED(rv) )
+ return rv;
+
+ PRUint32 macTime = 0;
+ OSErr err = noErr;
+
+ ConvertMillisecondsToMacTime(aLastModifiedTime, &macTime);
+
+ if (NS_SUCCEEDED(rv = UpdateCachedCatInfo(PR_TRUE)))
+ {
+ if (mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask)
+ {
+ mCachedCatInfo.dirInfo.ioDrMdDat = macTime;
+ mCachedCatInfo.dirInfo.ioDrParID = mFollowLinks ? mTargetSpec.parID : mSpec.parID;
+ }
+ else
+ {
+ mCachedCatInfo.hFileInfo.ioFlMdDat = macTime;
+ mCachedCatInfo.hFileInfo.ioDirID = mFollowLinks ? mTargetSpec.parID : mSpec.parID;
+ }
+
+ err = ::PBSetCatInfoSync(&mCachedCatInfo);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ nsresult rv;
+ PRBool isLink;
+
+ rv = IsSymlink(&isLink);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isLink)
+ return NS_ERROR_FAILURE;
+
+ StFollowLinksState followState(this, PR_FALSE);
+ return GetLastModifiedTime(aLastModifiedTime);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
+{
+ nsresult rv;
+ PRBool isLink;
+
+ rv = IsSymlink(&isLink);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isLink)
+ return NS_ERROR_FAILURE;
+
+ StFollowLinksState followState(this, PR_FALSE);
+ return SetLastModifiedTime(aLastModifiedTime);
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+ nsresult rv;
+
+ *aFileSize = LL_Zero();
+
+ if (NS_SUCCEEDED(rv = ResolveAndStat()) && NS_SUCCEEDED(rv = UpdateCachedCatInfo(PR_TRUE)))
+ {
+ if (!(mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask))
+ {
+ long dataSize = mCachedCatInfo.hFileInfo.ioFlLgLen;
+ long resSize = mCachedCatInfo.hFileInfo.ioFlRLgLen;
+
+ // For now we've only got 32 bits of file size info
+ PRInt64 dataInt64 = LL_Zero();
+ PRInt64 resInt64 = LL_Zero();
+
+ // WARNING!!!!!!
+ //
+ // For now we do NOT add the data and resource fork sizes as there are several
+ // assumptions in the code (notably in form submit) that only the data fork is
+ // used.
+ // LL_I2L(resInt64, resSize);
+
+ LL_I2L(dataInt64, dataSize);
+
+ LL_ADD((*aFileSize), dataInt64, resInt64);
+ }
+ // leave size at zero for dirs
+ }
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ short refNum;
+ OSErr err;
+ PRInt32 aNewLength;
+
+ LL_L2I(aNewLength, aFileSize);
+
+ // Need to open the file to set the size
+ if (::FSpOpenDF(&mTargetSpec, fsWrPerm, &refNum) != noErr)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ err = ::SetEOF(refNum, aNewLength);
+
+ // Close the file unless we got an error that it was already closed
+ if (err != fnOpnErr)
+ (void)::FSClose(refNum);
+
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return MacErrorMapper(err);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ StFollowLinksState followState(this, PR_FALSE);
+ return GetFileSize(aFileSize);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG(aDiskSpaceAvailable);
+
+ PRInt64 space64Bits;
+
+ LL_I2L(space64Bits , LONG_MAX);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ XVolumeParam pb;
+ pb.ioCompletion = nsnull;
+ pb.ioVolIndex = 0;
+ pb.ioNamePtr = nsnull;
+ pb.ioVRefNum = mFollowLinks ? mTargetSpec.vRefNum : mSpec.vRefNum;
+
+ // we should check if this call is available
+ OSErr err = ::PBXGetVolInfoSync(&pb);
+
+ if (err == noErr)
+ {
+ const UnsignedWide& freeBytes = UInt64ToUnsignedWide(pb.ioVFreeBytes);
+#ifdef HAVE_LONG_LONG
+ space64Bits = UnsignedWideToUInt64(freeBytes);
+#else
+ space64Bits.lo = freeBytes.lo;
+ space64Bits.hi = freeBytes.hi;
+#endif
+ }
+
+ *aDiskSpaceAvailable = space64Bits;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nsnull;
+
+ nsresult rv = NS_OK;
+ PRInt32 offset;
+
+ nsCOMPtr<nsILocalFileMac> localFile;
+ PRInt32 appendedLen = mAppendedPath.Length();
+ OSErr err;
+
+ if (!appendedLen || (appendedLen == 1 && mAppendedPath.CharAt(0) == ':'))
+ {
+ rv = ResolveAndStat();
+ //if the file does not exist, does not mean that the parent does not.
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ CInfoPBRec pBlock = {0};
+ FSSpec parentFolderSpec;
+ parentFolderSpec.name[0] = 0;
+
+ pBlock.dirInfo.ioVRefNum = mSpec.vRefNum;
+ pBlock.dirInfo.ioDrDirID = mSpec.parID;
+ pBlock.dirInfo.ioNamePtr = (StringPtr)parentFolderSpec.name;
+ pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
+ err = PBGetCatInfoSync(&pBlock);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ parentFolderSpec.vRefNum = mSpec.vRefNum;
+ parentFolderSpec.parID = pBlock.dirInfo.ioDrParID;
+
+ localFile = new nsLocalFile;
+ if (!localFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = localFile->InitWithFSSpec(&parentFolderSpec);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // trim off the last component of the appended path
+ // construct a new file from our spec + trimmed path
+
+ nsCAutoString parentAppendage(mAppendedPath);
+
+ if (parentAppendage.Last() == ':')
+ parentAppendage.Truncate(appendedLen - 1);
+ if ((offset = parentAppendage.RFindChar(':')) != -1)
+ parentAppendage.Truncate(offset);
+ else
+ parentAppendage.Truncate(0);
+
+ localFile = new nsLocalFile(mSpec, parentAppendage);
+ if (!localFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aParent = localFile;
+ NS_ADDREF(*aParent);
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(UpdateCachedCatInfo(PR_TRUE)))
+ *_retval = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsPackage(PRBool *outIsPackage)
+{
+ NS_ENSURE_ARG(outIsPackage);
+ *outIsPackage = PR_FALSE;
+
+ // Note: IsDirectory() calls ResolveAndStat() & UpdateCachedCatInfo
+ PRBool isDir;
+ nsresult rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsPackage = ((mCachedCatInfo.dirInfo.ioFlAttrib & kioFlAttribDirMask) &&
+ (mCachedCatInfo.dirInfo.ioDrUsrWds.frFlags & kHasBundle));
+
+ if ((!*outIsPackage) && isDir)
+ {
+ // Believe it or not, folders ending with ".app" are also considered
+ // to be packages, even if the top-level folder doesn't have bundle set
+ nsCAutoString name;
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(name)))
+ {
+ const char *extPtr = strrchr(name.get(), '.');
+ if (extPtr)
+ {
+ if (!nsCRT::strcasecmp(extPtr, ".app"))
+ {
+ *outIsPackage = PR_TRUE;
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *outIsWritable)
+{
+ NS_ENSURE_ARG(outIsWritable);
+ *outIsWritable = PR_TRUE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_TRUE);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsWritable = !(mCachedCatInfo.hFileInfo.ioFlAttrib & kioFlAttribLockedMask);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ // is it ever not readable on Mac?
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *outIsExecutable)
+{
+ NS_ENSURE_ARG(outIsExecutable);
+ *outIsExecutable = PR_FALSE; // Assume failure
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+#if TARGET_CARBON
+ // If we're running under OS X ask LaunchServices if we're executable
+ if (sRunningOSX)
+ {
+ if ( (UInt32)LSCopyItemInfoForRef != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef theRef;
+ LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
+ LSItemInfoRecord theInfo;
+
+ if (::FSpMakeFSRef(&mTargetSpec, &theRef) == noErr)
+ {
+ if (::LSCopyItemInfoForRef(&theRef, theInfoRequest, &theInfo) == noErr)
+ {
+ if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
+ *outIsExecutable = PR_TRUE;
+ }
+ }
+ }
+ }
+ else
+#endif
+ {
+ OSType fileType;
+ rv = GetFileType(&fileType);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsExecutable = (fileType == 'APPL' || fileType == 'appe' || fileType == 'FNDR');
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *outIsDir)
+{
+ NS_ENSURE_ARG(outIsDir);
+ *outIsDir = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_FALSE);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsDir = (mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask) != 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *outIsFile)
+{
+ NS_ENSURE_ARG(outIsFile);
+ *outIsFile = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_FALSE);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsFile = (mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask) == 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_FALSE);
+ if (NS_FAILED(rv)) return rv;
+
+ *_retval = (mCachedCatInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) != 0;
+
+ if (sRunningOSX)
+ {
+ // on Mac OS X, also follow Unix "convention" where files
+ // beginning with a period are considered to be hidden
+ nsCAutoString name;
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(name)))
+ {
+ if (name.First() == '.')
+ {
+ *_retval = PR_TRUE;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ Boolean isAlias, isFolder;
+ if (::IsAliasFile(&mSpec, &isAlias, &isFolder) == noErr)
+ *_retval = isAlias;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ // Building paths is expensive. If we can get the FSSpecs of
+ // both (they or their parents exist) just compare the specs.
+ nsCOMPtr<nsILocalFileMac> inMacFile(do_QueryInterface(inFile));
+ FSSpec fileSpec, inFileSpec;
+ if (NS_SUCCEEDED(GetFSSpec(&fileSpec)) && inMacFile && NS_SUCCEEDED(inMacFile->GetFSSpec(&inFileSpec)))
+ *_retval = IsEqualFSSpec(fileSpec, inFileSpec);
+ else
+ {
+ nsCAutoString filePath;
+ GetNativePath(filePath);
+
+ nsXPIDLCString inFilePath;
+ inFile->GetNativePath(inFilePath);
+
+ if (nsCRT::strcasecmp(inFilePath.get(), filePath.get()) == 0)
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *outContains)
+{
+ /* Note here that we make no attempt to deal with the problem
+ of folder aliases. Doing a 'Contains' test and dealing with
+ folder aliases is Hard. Think about it.
+ */
+ *outContains = PR_FALSE;
+
+ PRBool isDir;
+ nsresult rv = IsDirectory(&isDir); // need to cache this
+ if (NS_FAILED(rv)) return rv;
+ if (!isDir) return NS_OK; // must be a dir to contain someone
+
+ nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(inFile));
+ if (!macFile) return NS_OK; // trying to compare non-local with local file
+
+ FSSpec mySpec = mSpec;
+ FSSpec compareSpec;
+
+ // NOTE: we're not resolving inFile if it was an alias
+ StFollowLinksState followState(macFile, PR_FALSE);
+ rv = macFile->GetFSSpec(&compareSpec);
+ if (NS_FAILED(rv)) return rv;
+
+ // if they are on different volumes, bail
+ if (mSpec.vRefNum != compareSpec.vRefNum)
+ return NS_OK;
+
+ // if recur == true, test every parent, otherwise just test the first one
+ // (yes, recur does not get set in this loop)
+ OSErr err = noErr;
+ do
+ {
+ FSSpec parentFolderSpec;
+ err = GetParentFolderSpec(compareSpec, parentFolderSpec);
+ if (err != noErr) break; // we reached the top
+
+ if (IsEqualFSSpec(parentFolderSpec, mySpec))
+ {
+ *outContains = PR_TRUE;
+ break;
+ }
+
+ compareSpec = parentFolderSpec;
+ } while (recur);
+
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ _retval.Truncate();
+
+ PRBool symLink;
+
+ nsresult rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!symLink)
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ StFollowLinksState followState(this, PR_TRUE);
+ return GetNativePath(_retval);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = GetNativeTarget(fsStr))) {
+ rv = NS_CopyNativeToUnicode(fsStr, _retval);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
+{
+ nsresult rv;
+
+ *entries = nsnull;
+
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+
+ *entries = dirEnum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ aPersistentDescriptor.Truncate();
+
+ nsresult rv = ResolveAndStat();
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ AliasHandle aliasH;
+ OSErr err = ::NewAlias(nil, &mTargetSpec, &aliasH);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
+ HLock((Handle) aliasH);
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull); // Passing nsnull for dest makes NULL-term string
+ ::DisposeHandle((Handle) aliasH);
+ NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
+
+ aPersistentDescriptor = buf;
+ PR_Free(buf);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ if (aPersistentDescriptor.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ nsresult rv = NS_OK;
+
+ PRUint32 dataSize = aPersistentDescriptor.Length();
+ char* decodedData = PL_Base64Decode(PromiseFlatCString(aPersistentDescriptor).get(), dataSize, nsnull);
+ // Cast to an alias record and resolve.
+ AliasHandle aliasH = nsnull;
+ if (::PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4) != noErr)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ PR_Free(decodedData);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ Boolean changed;
+ FSSpec resolvedSpec;
+ OSErr err;
+ err = ::ResolveAlias(nsnull, aliasH, &resolvedSpec, &changed);
+ if (err == fnfErr) // resolvedSpec is valid in this case
+ err = noErr;
+ rv = MacErrorMapper(err);
+ DisposeHandle((Handle) aliasH);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return InitWithFSSpec(&resolvedSpec);
+}
+
+#pragma mark -
+
+// a stack-based, exception safe class for an AEDesc
+
+#pragma mark
+class StAEDesc: public AEDesc
+{
+public:
+ StAEDesc()
+ {
+ descriptorType = typeNull;
+ dataHandle = nil;
+ }
+
+ ~StAEDesc()
+ {
+ ::AEDisposeDesc(this);
+ }
+
+ void Clear()
+ {
+ ::AEDisposeDesc(this);
+ descriptorType = typeNull;
+ dataHandle = nil;
+ }
+
+private:
+ // disallow copies and assigns
+ StAEDesc(const StAEDesc& rhs); // copy constructor
+ StAEDesc& operator= (const StAEDesc&rhs); // throws OSErrs
+
+};
+
+#pragma mark -
+#pragma mark [Utility methods]
+
+
+nsresult nsLocalFile::UpdateCachedCatInfo(PRBool forceUpdate)
+{
+ if (!mCatInfoDirty && !forceUpdate)
+ return NS_OK;
+
+ FSSpec spectoUse = mFollowLinks ? mTargetSpec : mSpec;
+ mCachedCatInfo.hFileInfo.ioCompletion = nsnull;
+ mCachedCatInfo.hFileInfo.ioFDirIndex = 0; // use dirID and name
+ mCachedCatInfo.hFileInfo.ioVRefNum = spectoUse.vRefNum;
+ mCachedCatInfo.hFileInfo.ioDirID = spectoUse.parID;
+ mCachedCatInfo.hFileInfo.ioNamePtr = spectoUse.name;
+
+ OSErr err = ::PBGetCatInfoSync(&mCachedCatInfo);
+ if (err == noErr)
+ {
+ mCatInfoDirty = PR_FALSE;
+ return NS_OK;
+ }
+ return MacErrorMapper(err);
+}
+
+
+nsresult nsLocalFile::FindRunningAppBySignature (OSType aAppSig, FSSpec& outSpec, ProcessSerialNumber& outPsn)
+{
+ ProcessInfoRec info;
+ FSSpec tempFSSpec;
+ OSErr err = noErr;
+
+ outPsn.highLongOfPSN = 0;
+ outPsn.lowLongOfPSN = kNoProcess;
+
+ while (PR_TRUE)
+ {
+ err = ::GetNextProcess(&outPsn);
+ if (err == procNotFound) break;
+ if (err != noErr) return NS_ERROR_FAILURE;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = &tempFSSpec;
+ err = ::GetProcessInformation(&outPsn, &info);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (info.processSignature == aAppSig)
+ {
+ outSpec = tempFSSpec;
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_FILE_NOT_FOUND; // really process not found
+}
+
+
+nsresult nsLocalFile::FindRunningAppByFSSpec(const FSSpec& appSpec, ProcessSerialNumber& outPsn)
+{
+ ProcessInfoRec info;
+ FSSpec tempFSSpec;
+ OSErr err = noErr;
+
+ outPsn.highLongOfPSN = 0;
+ outPsn.lowLongOfPSN = kNoProcess;
+
+ while (PR_TRUE)
+ {
+ err = ::GetNextProcess(&outPsn);
+ if (err == procNotFound) break;
+ if (err != noErr) return NS_ERROR_FAILURE;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = &tempFSSpec;
+ err = ::GetProcessInformation(&outPsn, &info);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (IsEqualFSSpec(appSpec, *info.processAppSpec))
+ {
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_FILE_NOT_FOUND; // really process not found
+}
+
+
+nsresult nsLocalFile::FindAppOnLocalVolumes(OSType sig, FSSpec &outSpec)
+{
+ OSErr err;
+
+ // get the system volume
+ long systemFolderDirID;
+ short sysVRefNum;
+ err = FindFolder(kOnSystemDisk, kSystemFolderType, false, &sysVRefNum, &systemFolderDirID);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ short vRefNum = sysVRefNum;
+ short index = 0;
+
+ while (true)
+ {
+ if (index == 0 || vRefNum != sysVRefNum)
+ {
+ // should we avoid AppleShare volumes?
+
+ Boolean hasDesktopDB;
+ err = VolHasDesktopDB(vRefNum, &hasDesktopDB);
+ if (err != noErr) return err;
+ if (hasDesktopDB)
+ {
+ err = FindAppOnVolume(sig, vRefNum, &outSpec);
+ if (err != afpItemNotFound) return err;
+ }
+ }
+ index++;
+ err = GetIndVolume(index, &vRefNum);
+ if (err == nsvErr) return fnfErr;
+ if (err != noErr) return err;
+ }
+
+ return NS_OK;
+}
+
+#define aeSelectionKeyword 'fsel'
+#define kAEOpenSelection 'sope'
+#define kAERevealSelection 'srev'
+#define kFinderType 'FNDR'
+
+NS_IMETHODIMP nsLocalFile::Launch()
+{
+ AppleEvent aeEvent = {0, nil};
+ AppleEvent aeReply = {0, nil};
+ StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
+ FSSpec dirSpec, appSpec;
+ AliasHandle DirAlias, FileAlias;
+ OSErr errorResult = noErr;
+ ProcessSerialNumber process;
+
+ // for launching a file, we'll use mTargetSpec (which is both a resolved spec and a resolved alias)
+ ResolveAndStat();
+
+#if TARGET_CARBON
+ if (sRunningOSX)
+ { // We're running under Mac OS X, LaunchServices here we come
+
+ // First we make sure the LaunchServices routine we want is implemented
+ if ( (UInt32)LSOpenFSRef != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef theRef;
+ if (::FSpMakeFSRef(&mTargetSpec, &theRef) == noErr)
+ {
+ (void)::LSOpenFSRef(&theRef, NULL);
+ }
+ }
+ }
+ else
+#endif
+ { // We're running under Mac OS 8.x/9.x, use the Finder Luke
+ nsresult rv = FindRunningAppBySignature ('MACS', appSpec, process);
+ if (NS_SUCCEEDED(rv))
+ {
+ errorResult = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
+ if (errorResult == noErr)
+ {
+ /* Create the FinderEvent */
+ errorResult = AECreateAppleEvent(kFinderType, kAEOpenSelection, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
+ &aeEvent);
+ if (errorResult == noErr)
+ {
+ errorResult = FSMakeFSSpec(mTargetSpec.vRefNum, mTargetSpec.parID, nil, &dirSpec);
+ NewAlias(nil, &dirSpec, &DirAlias);
+ /* Create alias for file */
+ NewAlias(nil, &mTargetSpec, &FileAlias);
+
+ /* Create the file list */
+ errorResult = AECreateList(nil, 0, false, &fileList);
+ /* create the folder descriptor */
+ HLock((Handle)DirAlias);
+ errorResult = AECreateDesc(typeAlias, (Ptr)*DirAlias, GetHandleSize((Handle)DirAlias), &aeDirDesc);
+ HUnlock((Handle)DirAlias);
+ if (errorResult == noErr)
+ {
+ errorResult = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDirDesc);
+ if ( errorResult == noErr)
+ {
+ /* create the file descriptor and add to aliasList */
+ HLock((Handle)FileAlias);
+ errorResult = AECreateDesc(typeAlias, (Ptr)*FileAlias, GetHandleSize((Handle)FileAlias), &listElem);
+ HLock((Handle)FileAlias);
+ if (errorResult == noErr)
+ {
+ errorResult = AEPutDesc(&fileList, 0, &listElem);
+ if (errorResult == noErr)
+ {
+ /* Add the file alias list to the event */
+ errorResult = AEPutParamDesc(&aeEvent, aeSelectionKeyword, &fileList);
+ if (errorResult == noErr)
+ AESend(&aeEvent, &aeReply, kAEWaitReply + kAENeverInteract
+ + kAECanSwitchLayer, kAEHighPriority, kAEDefaultTimeout, nil, nil);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::Reveal()
+{
+ FSSpec specToReveal;
+ AppleEvent aeEvent = {0, nil};
+ AppleEvent aeReply = {0, nil};
+ StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
+ OSErr errorResult = noErr;
+ ProcessSerialNumber process;
+ FSSpec appSpec;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+ rv = GetFSSpec(&specToReveal); // Pay attention to followLinks
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = FindRunningAppBySignature ('MACS', appSpec, process);
+ if (NS_SUCCEEDED(rv))
+ {
+ errorResult = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
+ if (errorResult == noErr)
+ {
+ /* Create the FinderEvent */
+#if TARGET_CARBON
+ // The Finder under OS X uses a different event to reveal
+ if (sRunningOSX)
+ errorResult = AECreateAppleEvent(kAEMiscStandards, kAEMakeObjectsVisible, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
+ &aeEvent);
+ else
+#endif
+ errorResult = AECreateAppleEvent(kFinderType, kAERevealSelection, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
+ &aeEvent);
+ if (errorResult == noErr)
+ {
+ /* Create the file list */
+ errorResult = AECreateList(nil, 0, false, &fileList);
+ if (errorResult == noErr)
+ {
+ errorResult = AEPutPtr(&fileList, 0, typeFSS, &specToReveal, sizeof(FSSpec));
+
+ if (errorResult == noErr)
+ {
+#if TARGET_CARBON
+ // When we're sending the event under OS X the FSSpec must be a keyDirectObject
+ if (sRunningOSX)
+ errorResult = AEPutParamDesc(&aeEvent, keyDirectObject, &fileList);
+ else
+#endif
+ errorResult = AEPutParamDesc(&aeEvent,keySelection, &fileList);
+
+ if (errorResult == noErr)
+ {
+ errorResult = AESend(&aeEvent, &aeReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
+ if (errorResult == noErr)
+ SetFrontProcess(&process);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult nsLocalFile::MyLaunchAppWithDoc(const FSSpec& appSpec, const FSSpec* aDocToLoad, PRBool aLaunchInBackground)
+{
+ ProcessSerialNumber thePSN = {0};
+ StAEDesc target;
+ StAEDesc docDesc;
+ StAEDesc launchDesc;
+ StAEDesc docList;
+ AppleEvent theEvent = {0, nil};
+ AppleEvent theReply = {0, nil};
+ OSErr err = noErr;
+ Boolean autoParamValue = false;
+ Boolean running = false;
+ nsresult rv = NS_OK;
+
+#if TARGET_CARBON
+ if (sRunningOSX)
+ { // Under Mac OS X we'll use LaunchServices
+
+ // First we make sure the LaunchServices routine we want is implemented
+ if ( (UInt32)LSOpenFromRefSpec != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef appRef;
+ FSRef docRef;
+ LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+ LSLaunchFSRefSpec thelaunchSpec;
+
+ if (::FSpMakeFSRef(&appSpec, &appRef) != noErr)
+ return NS_ERROR_FAILURE;
+
+ if (aDocToLoad)
+ if (::FSpMakeFSRef(aDocToLoad, &docRef) != noErr)
+ return NS_ERROR_FAILURE;
+
+ if (aLaunchInBackground)
+ theLaunchFlags |= kLSLaunchDontSwitch;
+
+ memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+ thelaunchSpec.appRef = &appRef;
+ if (aDocToLoad)
+ {
+ thelaunchSpec.numDocs = 1;
+ thelaunchSpec.itemRefs = &docRef;
+ }
+ thelaunchSpec.launchFlags = theLaunchFlags;
+
+ err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+ NS_ASSERTION((err != noErr), "Error calling LSOpenFromRefSpec");
+ if (err != noErr) return NS_ERROR_FAILURE;
+ }
+ }
+ else
+#endif
+ { // The old fashioned way for Mac OS 8.x/9.x
+ rv = FindRunningAppByFSSpec(appSpec, thePSN);
+ running = NS_SUCCEEDED(rv);
+
+ err = AECreateDesc(typeProcessSerialNumber, &thePSN, sizeof(thePSN), &target);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AECreateAppleEvent(kCoreEventClass, aDocToLoad ? kAEOpenDocuments : kAEOpenApplication, &target,
+ kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (aDocToLoad)
+ {
+ err = AECreateList(nil, 0, false, &docList);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AECreateDesc(typeFSS, aDocToLoad, sizeof(FSSpec), &docDesc);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AEPutDesc(&docList, 0, &docDesc);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AEPutParamDesc(&theEvent, keyDirectObject, &docList);
+ if (err != noErr) return NS_ERROR_FAILURE;
+ }
+
+ if (running)
+ {
+ err = AESend(&theEvent, &theReply, kAENoReply, kAENormalPriority, kNoTimeOut, nil, nil);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (!aLaunchInBackground)
+ {
+ err = ::SetFrontProcess(&thePSN);
+ if (err != noErr) return NS_ERROR_FAILURE;
+ }
+ }
+ else
+ {
+ LaunchParamBlockRec launchThis = {0};
+ PRUint16 launchControlFlags = (launchContinue | launchNoFileFlags);
+ if (aLaunchInBackground)
+ launchControlFlags |= launchDontSwitch;
+
+ err = AECoerceDesc(&theEvent, typeAppParameters, &launchDesc);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ launchThis.launchAppSpec = (FSSpecPtr)&appSpec;
+#if TARGET_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS
+ ::AEGetDescData(&launchDesc, &launchThis.launchAppParameters, sizeof(launchThis.launchAppParameters));
+#else
+ // no need to lock this handle.
+ launchThis.launchAppParameters = (AppParametersPtr) *(launchDesc.dataHandle);
+#endif
+ launchThis.launchBlockID = extendedBlock;
+ launchThis.launchEPBLength = extendedBlockLen;
+ launchThis.launchFileFlags = 0;
+ launchThis.launchControlFlags = launchControlFlags;
+ err = ::LaunchApplication(&launchThis);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ // let's be nice and wait until it's running
+ const PRUint32 kMaxTimeToWait = 60; // wait 1 sec max
+ PRUint32 endTicks = ::TickCount() + kMaxTimeToWait;
+
+ PRBool foundApp = PR_FALSE;
+
+ do
+ {
+ EventRecord theEvent;
+ (void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);
+
+ ProcessSerialNumber psn;
+ foundApp = NS_SUCCEEDED(FindRunningAppByFSSpec(appSpec, psn));
+
+ } while (!foundApp && (::TickCount() <= endTicks));
+
+ NS_ASSERTION(foundApp, "Failed to find app after launching it");
+ }
+
+ if (theEvent.dataHandle != nil) AEDisposeDesc(&theEvent);
+ if (theReply.dataHandle != nil) AEDisposeDesc(&theReply);
+ }
+
+ return NS_OK;
+}
+
+
+#pragma mark -
+#pragma mark [Methods that will not be implemented on Mac]
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#pragma mark -
+#pragma mark [nsILocalFileMac]
+// Implementation of Mac specific finctions from nsILocalFileMac
+
+
+NS_IMETHODIMP nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG(aCFURL);
+
+ // CFURLGetFSRef can only succeed if the entire path exists.
+ FSRef fsRef;
+ if (::CFURLGetFSRef(aCFURL, &fsRef) == PR_TRUE)
+ rv = InitWithFSRef(&fsRef);
+ else
+ {
+ CFURLRef parentURL = ::CFURLCreateCopyDeletingLastPathComponent(NULL, aCFURL);
+ if (!parentURL)
+ return NS_ERROR_FAILURE;
+
+ // Get the FSRef from the parent and the FSSpec from that
+ FSRef parentFSRef;
+ FSSpec parentFSSpec;
+ if ((::CFURLGetFSRef(parentURL, &parentFSRef) == PR_TRUE) &&
+ (::FSGetCatalogInfo(&parentFSRef, kFSCatInfoNone,
+ nsnull, nsnull, &parentFSSpec, nsnull) == noErr))
+ {
+ // Get the leaf name of the file and turn it into a string HFS can use.
+ CFStringRef fileNameRef = ::CFURLCopyLastPathComponent(aCFURL);
+ if (fileNameRef)
+ {
+ TextEncoding theEncoding;
+ if (::UpgradeScriptInfoToTextEncoding(smSystemScript,
+ kTextLanguageDontCare,
+ kTextRegionDontCare,
+ NULL,
+ &theEncoding) != noErr)
+ theEncoding = kTextEncodingMacRoman;
+
+ char origName[256];
+ char truncBuf[32];
+ if (::CFStringGetCString(fileNameRef, origName, sizeof(origName), theEncoding))
+ {
+ MakeDirty();
+ mSpec = parentFSSpec;
+ mAppendedPath = NS_TruncNodeName(origName, truncBuf);
+ rv = NS_OK;
+ }
+ ::CFRelease(fileNameRef);
+ }
+ }
+ ::CFRelease(parentURL);
+ }
+#endif
+
+ return rv;
+}
+
+
+NS_IMETHODIMP nsLocalFile::InitWithFSRef(const FSRef * aFSRef)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG(aFSRef);
+
+ FSSpec fsSpec;
+ OSErr err = ::FSGetCatalogInfo(aFSRef, kFSCatInfoNone, nsnull,
+ nsnull, &fsSpec, nsnull);
+ if (err == noErr)
+ rv = InitWithFSSpec(&fsSpec);
+ else
+ rv = MacErrorMapper(err);
+#endif
+
+ return rv;
+}
+
+
+NS_IMETHODIMP nsLocalFile::InitWithFSSpec(const FSSpec *fileSpec)
+{
+ MakeDirty();
+ mSpec = *fileSpec;
+ mTargetSpec = *fileSpec;
+ mAppendedPath = "";
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator)
+{
+ FSSpec appSpec;
+ ProcessSerialNumber psn;
+
+#if TARGET_CARBON
+ if (sRunningOSX)
+ { // If we're running under OS X use LaunchServices to determine the app
+ // corresponding to the creator code
+ if ( (UInt32)LSFindApplicationForInfo != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef theRef;
+ if (::LSFindApplicationForInfo(aAppCreator, NULL, NULL, &theRef, NULL) == noErr)
+ {
+ FSCatalogInfoBitmap whichInfo = kFSCatInfoNone;
+
+ if (::FSGetCatalogInfo(&theRef, whichInfo, NULL, NULL, &appSpec, NULL) == noErr)
+ return InitWithFSSpec(&appSpec);
+ }
+
+ // If we get here we didn't find an app
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+ }
+#endif
+
+ // is the app running?
+ nsresult rv = FindRunningAppBySignature(aAppCreator, appSpec, psn);
+ if (rv == NS_ERROR_FILE_NOT_FOUND)
+ {
+ // we have to look on disk
+ rv = FindAppOnLocalVolumes(aAppCreator, appSpec);
+ if (NS_FAILED(rv)) return rv;
+ }
+ else if (NS_FAILED(rv))
+ return rv;
+
+ // init with the spec here
+ return InitWithFSSpec(&appSpec);
+}
+
+NS_IMETHODIMP nsLocalFile::GetCFURL(CFURLRef *_retval)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+
+ PRBool exists;
+ if (NS_SUCCEEDED(Exists(&exists)) && exists)
+ {
+ FSRef fsRef;
+ FSSpec fsSpec = mFollowLinks ? mTargetSpec : mSpec;
+ if (::FSpMakeFSRef(&fsSpec, &fsRef) == noErr)
+ {
+ *_retval = ::CFURLCreateFromFSRef(NULL, &fsRef);
+ if (*_retval)
+ return NS_OK;
+ }
+ }
+ else
+ {
+ nsCAutoString tempPath;
+ if (NS_SUCCEEDED(GetNativePath(tempPath)))
+ {
+ CFStringRef pathStrRef = ::CFStringCreateWithCString(NULL, tempPath.get(), kCFStringEncodingMacRoman);
+ if (!pathStrRef)
+ return NS_ERROR_FAILURE;
+ *_retval = ::CFURLCreateWithFileSystemPath(NULL, pathStrRef, kCFURLHFSPathStyle, false);
+ ::CFRelease(pathStrRef);
+ if (*_retval)
+ return NS_OK;
+ }
+ }
+#endif
+
+ return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFSRef(FSRef *_retval)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ FSSpec fsSpec;
+ rv = GetFSSpec(&fsSpec);
+ if (NS_SUCCEEDED(rv))
+ rv = MacErrorMapper(::FSpMakeFSRef(&fsSpec, _retval));
+#endif
+
+ return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFSSpec(FSSpec *fileSpec)
+{
+ NS_ENSURE_ARG(fileSpec);
+ nsresult rv = ResolveAndStat();
+ if (rv == NS_ERROR_FILE_NOT_FOUND)
+ rv = NS_OK;
+ if (NS_SUCCEEDED(rv))
+ *fileSpec = mFollowLinks ? mTargetSpec : mSpec;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFileType(OSType *aFileType)
+{
+ NS_ENSURE_ARG(aFileType);
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ {
+ *aFileType = mType;
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ *aFileType = info.fdType;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileType(OSType aFileType)
+{
+ mType = aFileType;
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ info.fdType = aFileType;
+ err = ::FSpSetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFileCreator(OSType *aCreator)
+{
+ NS_ENSURE_ARG(aCreator);
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ {
+ *aCreator = mCreator;
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ *aCreator = info.fdCreator;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileCreator(OSType aCreator)
+{
+ if (aCreator == CURRENT_PROCESS_CREATOR)
+ aCreator = sCurrentProcessSignature;
+
+ mCreator = aCreator;
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ info.fdCreator = aCreator;
+ err = ::FSpSetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromExtension(const char *aExtension)
+{
+ NS_ENSURE_ARG(aExtension);
+ return SetOSTypeAndCreatorFromExtension(aExtension);
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromMIMEType(const char *aMIMEType)
+{
+ NS_ENSURE_ARG(aMIMEType);
+
+ nsresult rv;
+ nsCOMPtr<nsIInternetConfigService> icService(do_GetService
+ (NS_INTERNETCONFIGSERVICE_CONTRACTID, &rv));
+
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIMIMEInfo> mimeInfo;
+ PRUint32 fileType = 'TEXT';
+ PRUint32 fileCreator = nsILocalFileMac::CURRENT_PROCESS_CREATOR;
+
+ rv = icService->FillInMIMEInfo(aMIMEType,
+ nsnull, getter_AddRefs(mimeInfo));
+ if (NS_SUCCEEDED(rv))
+ rv = mimeInfo->GetMacType(&fileType);
+ if (NS_SUCCEEDED(rv))
+ rv = mimeInfo->GetMacCreator(&fileCreator);
+ if (NS_SUCCEEDED(rv))
+ rv = SetFileType(fileType);
+ if (NS_SUCCEEDED(rv))
+ rv = SetFileCreator(fileCreator);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ *aFileSize = LL_Zero();
+
+ ResolveAndStat();
+
+ long dataSize = 0;
+ long resSize = 0;
+
+ OSErr err = FSpGetFileSize(&mTargetSpec, &dataSize, &resSize);
+
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ // For now we've only got 32 bits of file size info
+ PRInt64 dataInt64 = LL_Zero();
+ PRInt64 resInt64 = LL_Zero();
+
+ // Combine the size of the resource and data forks
+ LL_I2L(resInt64, resSize);
+ LL_I2L(dataInt64, dataSize);
+ LL_ADD((*aFileSize), dataInt64, resInt64);
+
+ return NS_OK;
+}
+
+
+// this nsLocalFile points to the app. We want to launch it, optionally with the document.
+NS_IMETHODIMP
+nsLocalFile::LaunchWithDoc(nsILocalFile* aDocToLoad, PRBool aLaunchInBackground)
+{
+ // are we launchable?
+ PRBool isExecutable;
+ nsresult rv = IsExecutable(&isExecutable);
+ if (NS_FAILED(rv)) return rv;
+ if (!isExecutable) return NS_ERROR_FILE_EXECUTION_FAILED;
+
+ FSSpec docSpec;
+ FSSpecPtr docSpecPtr = nsnull;
+
+ nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
+ if (macDoc)
+ {
+ rv = macDoc->GetFSSpec(&docSpec); // XXX GetTargetFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ docSpecPtr = &docSpec;
+ }
+
+ FSSpec appSpec;
+ rv = GetFSSpec(&appSpec); // XXX GetResolvedFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ rv = MyLaunchAppWithDoc(appSpec, docSpecPtr, aLaunchInBackground);
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::OpenDocWithApp(nsILocalFile* aAppToOpenWith, PRBool aLaunchInBackground)
+{
+ // if aAppToOpenWith is nil, we have to find the app from the creator code
+ // of the document
+ nsresult rv = NS_OK;
+
+ FSSpec appSpec;
+
+ if (aAppToOpenWith)
+ {
+ nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
+ if (!appFileMac) return rv;
+
+ rv = appFileMac->GetFSSpec(&appSpec); // XXX GetTargetFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ // is it launchable?
+ PRBool isExecutable;
+ rv = aAppToOpenWith->IsExecutable(&isExecutable);
+ if (NS_FAILED(rv)) return rv;
+ if (!isExecutable) return NS_ERROR_FILE_EXECUTION_FAILED;
+ }
+ else
+ {
+ // look for one
+ OSType fileCreator;
+ rv = GetFileCreator(&fileCreator);
+ if (NS_FAILED(rv)) return rv;
+
+ // just make one on the stack
+ nsLocalFile localAppFile;
+ rv = localAppFile.InitToAppWithCreatorCode(fileCreator);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = localAppFile.GetFSSpec(&appSpec); // GetTargetFSSpec
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ FSSpec docSpec;
+ rv = GetFSSpec(&docSpec); // XXX GetResolvedFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ rv = MyLaunchAppWithDoc(appSpec, &docSpec, aLaunchInBackground);
+ return rv;
+}
+
+nsresult nsLocalFile::SetOSTypeAndCreatorFromExtension(const char* extension)
+{
+ nsresult rv;
+
+ nsCAutoString localExtBuf;
+ const char *extPtr;
+
+ if (!extension)
+ {
+ rv = GetNativeLeafName(localExtBuf);
+ extPtr = strrchr(localExtBuf.get(), '.');
+ if (!extPtr)
+ return NS_ERROR_FAILURE;
+ ++extPtr;
+ }
+ else
+ {
+ extPtr = extension;
+ if (*extPtr == '.')
+ ++extPtr;
+ }
+
+ nsCOMPtr<nsIInternetConfigService> icService =
+ do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIMIMEInfo> mimeInfo;
+ rv = icService->GetMIMEInfoFromExtension(extPtr, getter_AddRefs(mimeInfo));
+ if (NS_SUCCEEDED(rv))
+ {
+ PRUint32 osType;
+ rv = mimeInfo->GetMacType(&osType);
+ if (NS_SUCCEEDED(rv))
+ mType = osType;
+ PRBool skip;
+ rv = ExtensionIsOnExceptionList(extPtr, &skip);
+ if (NS_SUCCEEDED(rv) && !skip)
+ {
+ rv = mimeInfo->GetMacCreator(&osType);
+ if (NS_SUCCEEDED(rv))
+ mCreator = osType;
+ }
+ }
+ }
+ return rv;
+}
+
+nsresult nsLocalFile::ExtensionIsOnExceptionList(const char *extension, PRBool *onList)
+{
+ // Probably want to make a global list somewhere in the future
+ // for now, just check for "html" and "htm"
+
+ *onList = PR_FALSE;
+
+ if (!nsCRT::strcasecmp(extension, "html") ||
+ !nsCRT::strcasecmp(extension, "htm"))
+ *onList = PR_TRUE;
+ return NS_OK;
+}
+
+
+void nsLocalFile::InitClassStatics()
+{
+ OSErr err;
+
+
+ if (sCurrentProcessSignature == 0)
+ {
+ ProcessSerialNumber psn;
+ ProcessInfoRec info;
+
+ psn.highLongOfPSN = 0;
+ psn.lowLongOfPSN = kCurrentProcess;
+
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = nil;
+ err = ::GetProcessInformation(&psn, &info);
+ if (err == noErr)
+ sCurrentProcessSignature = info.processSignature;
+ // Try again next time if error
+ }
+
+ static PRBool didHFSPlusCheck = PR_FALSE;
+ if (!didHFSPlusCheck)
+ {
+ long response;
+ err = ::Gestalt(gestaltFSAttr, &response);
+ sHasHFSPlusAPIs = (err == noErr && (response & (1 << gestaltHasHFSPlusAPIs)) != 0);
+ didHFSPlusCheck = PR_TRUE;
+ }
+
+ static PRBool didOSXCheck = PR_FALSE;
+ if (!didOSXCheck)
+ {
+ long version;
+ sRunningOSX = (::Gestalt(gestaltSystemVersion, &version) == noErr && version >= 0x00001000);
+ didOSXCheck = PR_TRUE;
+ }
+}
+
+
+#pragma mark -
+
+// Handy dandy utility create routine for something or the other
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+ *result = file;
+ return NS_OK;
+}
+
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString fsCharSetStr;
+ nsresult rv = NS_CopyUnicodeToNative(path, fsCharSetStr);
+ if (NS_FAILED(rv))
+ return rv;
+ return NS_NewNativeLocalFile(fsCharSetStr, followLinks, result);
+}
+
+nsresult
+NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followLinks, nsILocalFileMac* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ nsresult rv = file->InitWithFSSpec(inSpec);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ *result = file;
+ return NS_OK;
+}
+
+void
+nsLocalFile::GlobalInit()
+{
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h
new file mode 100644
index 00000000..42eb2556
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Steve Dagley <sdagley@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _nsLocalFileMAC_H_
+#define _nsLocalFileMAC_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsILocalFileMac.h"
+#include "nsIFactory.h"
+
+#include <Processes.h>
+
+class NS_COM nsLocalFile : public nsILocalFileMac
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIFile interface
+ NS_DECL_NSIFILE
+
+ // nsILocalFile interface
+ NS_DECL_NSILOCALFILE
+
+ // nsILocalFileMac interface
+ NS_DECL_NSILOCALFILEMAC
+
+public:
+
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ ~nsLocalFile() {}
+
+protected:
+ void MakeDirty();
+ nsresult ResolveAndStat();
+ nsresult UpdateCachedCatInfo(PRBool forceUpdate);
+
+ nsresult FindAppOnLocalVolumes(OSType sig, FSSpec &outSpec);
+
+ nsresult FindRunningAppBySignature(OSType sig, FSSpec& outSpec, ProcessSerialNumber& outPsn);
+ nsresult FindRunningAppByFSSpec(const FSSpec& appSpec, ProcessSerialNumber& outPsn);
+
+ nsresult MyLaunchAppWithDoc(const FSSpec& appSpec, const FSSpec* aDocToLoad, PRBool aLaunchInBackground);
+
+ nsresult TestFinderFlag(PRUint16 flagMask, PRBool *outFlagSet, PRBool testTargetSpec = PR_TRUE);
+
+ nsresult MoveCopy( nsIFile* newParentDir, const nsACString &newName, PRBool isCopy, PRBool followLinks );
+
+ // Passing nsnull for the extension uses leaf name
+ nsresult SetOSTypeAndCreatorFromExtension(const char* extension = nsnull);
+
+ nsresult ExtensionIsOnExceptionList(const char *extension, PRBool *onList);
+
+private:
+ nsLocalFile(const nsLocalFile& srcFile);
+ nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath);
+
+ // Copies all members except mRefCnt, copies mCachedCatInfo only if it's valid.
+ nsLocalFile& operator=(const nsLocalFile& rhs);
+
+ PRPackedBool mFollowLinks;
+ PRPackedBool mFollowLinksDirty;
+
+ // The object we specify is always: mSpec + mAppendedPath.
+ // mSpec is a valid spec in that its parent is known to exist.
+ // Appending nodes with Append() will update mSpec immediately
+ // if the appended node exists. If not, appended nodes are stored
+ // in mAppendedPath.
+
+ PRPackedBool mSpecDirty;
+ FSSpec mSpec;
+ nsCString mAppendedPath;
+ FSSpec mTargetSpec; // If mSpec is an alias, this is the resolved alias.
+
+ CInfoPBRec mCachedCatInfo; // cached file info, for the GetFSSpec() spec
+ PRPackedBool mCatInfoDirty; // does this need to be updated?
+
+ OSType mType, mCreator;
+
+ static void InitClassStatics();
+
+ static OSType sCurrentProcessSignature;
+ static PRBool sHasHFSPlusAPIs;
+ static PRBool sRunningOSX;
+};
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp
new file mode 100644
index 00000000..269a13d0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp
@@ -0,0 +1,1742 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.com>
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+
+#include "nsLocalFile.h"
+#include "nsNativeCharsetUtils.h"
+
+#include "nsISimpleEnumerator.h"
+#include "nsIComponentManager.h"
+#include "prtypes.h"
+#include "prio.h"
+
+#include <ctype.h> // needed for toupper
+#include <string.h>
+
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+#include "prproces.h"
+#include "prthread.h"
+
+
+static unsigned char* PR_CALLBACK
+_mbschr( const unsigned char* stringToSearch, int charToSearchFor);
+extern unsigned char*
+_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor);
+static nsresult PR_CALLBACK
+CreateDirectoryA( PSZ path, PEAOP2 ppEABuf);
+static int isleadbyte(int c);
+
+#include <unistd.h>
+#include <io.h>
+
+
+static nsresult ConvertOS2Error(int err)
+{
+ nsresult rv;
+
+ switch (err)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ rv = NS_ERROR_FILE_NOT_FOUND;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NOT_SAME_DEVICE:
+ rv = NS_ERROR_FILE_ACCESS_DENIED;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_INVALID_HANDLE:
+ case ERROR_ARENA_TRASHED:
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ case ERROR_CURRENT_DIRECTORY:
+ rv = NS_ERROR_FILE_DIR_NOT_EMPTY;
+ break;
+ case ERROR_WRITE_PROTECT:
+ rv = NS_ERROR_FILE_READ_ONLY;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ rv = NS_ERROR_FILE_TOO_BIG;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_CANNOT_MAKE:
+ rv = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+ case 0:
+ rv = NS_OK;
+ break;
+ default:
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ return rv;
+}
+
+static void
+myLL_L2II(PRInt64 result, PRInt32 *hi, PRInt32 *lo )
+{
+ PRInt64 a64, b64; // probably could have been done with
+ // only one PRInt64, but these are macros,
+ // and I am a wimp.
+
+ // shift the hi word to the low word, then push it into a long.
+ LL_SHR(a64, result, 32);
+ LL_L2I(*hi, a64);
+
+ // shift the low word to the hi word first, then shift it back.
+ LL_SHL(b64, result, 32);
+ LL_SHR(a64, b64, 32);
+ LL_L2I(*lo, a64);
+}
+
+
+class nsDirEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator() : mDir(nsnull)
+ {
+ }
+
+ nsresult Init(nsILocalFile* parent)
+ {
+ nsCAutoString filepath;
+ parent->GetNativeTarget(filepath);
+
+ if (filepath.IsEmpty())
+ {
+ parent->GetNativePath(filepath);
+ }
+
+ if (filepath.IsEmpty())
+ {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mDir = PR_OpenDir(filepath.get());
+ if (mDir == nsnull) // not a directory?
+ return NS_ERROR_FAILURE;
+
+ mParent = parent;
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ nsresult rv;
+ if (mNext == nsnull && mDir)
+ {
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
+ if (entry == nsnull)
+ {
+ // end of dir entries
+
+ PRStatus status = PR_CloseDir(mDir);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FAILURE;
+ mDir = nsnull;
+
+ *result = PR_FALSE;
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ rv = mParent->Clone(getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = file->AppendNative(nsDependentCString(entry->name));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // make sure the thing exists. If it does, try the next one.
+ PRBool exists;
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ {
+ return HasMoreElements(result);
+ }
+
+ mNext = do_QueryInterface(file);
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ private:
+ ~nsDirEnumerator()
+ {
+ if (mDir)
+ {
+ PRStatus status = PR_CloseDir(mDir);
+ NS_ASSERTION(status == PR_SUCCESS, "close failed");
+ }
+ }
+
+ protected:
+ PRDir* mDir;
+ nsCOMPtr<nsILocalFile> mParent;
+ nsCOMPtr<nsILocalFile> mNext;
+};
+
+NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
+
+
+nsLocalFile::nsLocalFile()
+{
+ MakeDirty();
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& other)
+ : mDirty(other.mDirty)
+ , mWorkingPath(other.mWorkingPath)
+ , mFileInfo64(other.mFileInfo64)
+{
+}
+
+/* nsISupports interface implementation. */
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile)
+
+NS_METHOD
+nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+// This function resets any cached information about the file.
+void
+nsLocalFile::MakeDirty()
+{
+ mDirty = PR_TRUE;
+}
+
+nsresult
+nsLocalFile::Stat()
+{
+ if (!mDirty)
+ return NS_OK;
+
+ char temp[4];
+ const char* workingFilePath = mWorkingPath.get();
+ const char* nsprPath = workingFilePath;
+
+ if (mWorkingPath.Length() == 2 && mWorkingPath.CharAt(1) == ':') {
+ temp[0] = workingFilePath[0];
+ temp[1] = workingFilePath[1];
+ temp[2] = '\\';
+ temp[3] = '\0';
+ nsprPath = temp;
+ }
+
+ DosError(FERR_DISABLEHARDERR);
+ PRStatus status = PR_GetFileInfo64(nsprPath, &mFileInfo64);
+ DosError(FERR_ENABLEHARDERR);
+ if ( status == PR_SUCCESS )
+ return NS_OK;
+
+ return NS_ERROR_FILE_NOT_FOUND;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ MakeDirty();
+
+ nsACString::const_iterator begin, end;
+ filePath.BeginReading(begin);
+ filePath.EndReading(end);
+
+ // input string must not be empty
+ if (begin == end)
+ return NS_ERROR_FAILURE;
+
+ char firstChar = *begin;
+ char secondChar = *(++begin);
+
+ // just do a sanity check. if it has any forward slashes, it is not a Native path
+ // on windows. Also, it must have a colon at after the first char.
+
+ char *path = nsnull;
+ PRInt32 pathLen = 0;
+
+ if ( ( (secondChar == ':') && !FindCharInReadable('/', begin, end) ) || // normal path
+ ( (firstChar == '\\') && (secondChar == '\\') ) ) // network path
+ {
+ // This is a native path
+ path = ToNewCString(filePath);
+ pathLen = filePath.Length();
+ }
+
+ if (path == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // kill any trailing '\' provided it isn't the second char of DBCS
+ PRInt32 len = pathLen - 1;
+ if (path[len] == '\\' && !::isleadbyte(path[len-1]))
+ {
+ path[len] = '\0';
+ pathLen = len;
+ }
+
+ mWorkingPath.Adopt(path, pathLen);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ nsresult rv = Stat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = PR_Open(mWorkingPath.get(), flags, mode);
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ErrorAccordingToNSPR();
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
+{
+ nsresult rv = Stat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = fopen(mWorkingPath.get(), mode);
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_FAILURE;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ // create nested directories to target
+ unsigned char* slash = _mbschr((const unsigned char*) mWorkingPath.get(), '\\');
+
+
+ if (slash)
+ {
+ // skip the first '\\'
+ ++slash;
+ slash = _mbschr(slash, '\\');
+
+ while (slash)
+ {
+ *slash = '\0';
+
+ rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
+ if (rv) {
+ rv = ConvertOS2Error(rv);
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
+ }
+ *slash = '\\';
+ ++slash;
+ slash = _mbschr(slash, '\\');
+ }
+ }
+
+ if (type == NORMAL_FILE_TYPE)
+ {
+ PRFileDesc* file = PR_Open(mWorkingPath.get(), PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL, attributes);
+ if (!file) return NS_ERROR_FILE_ALREADY_EXISTS;
+
+ PR_Close(file);
+ return NS_OK;
+ }
+
+ if (type == DIRECTORY_TYPE)
+ {
+ rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
+ if (rv)
+ return ConvertOS2Error(rv);
+ else
+ return NS_OK;
+ }
+
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &node)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ // Append only one component. Check for subdirs.
+ // XXX can we avoid the PromiseFlatCString call?
+ if (_mbschr((const unsigned char*) PromiseFlatCString(node).get(), '\\') != nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ return AppendRelativeNativePath(node);
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &node)
+{
+ // Cannot start with a / or have .. or have / anywhere
+ nsACString::const_iterator begin, end;
+ node.BeginReading(begin);
+ node.EndReading(end);
+ if (node.IsEmpty() || FindCharInReadable('/', begin, end))
+ {
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ }
+ MakeDirty();
+ mWorkingPath.Append(NS_LITERAL_CSTRING("\\") + node);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ aLeafName.Truncate();
+
+ const char* temp = mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp, '\\');
+
+ // if the working path is just a node without any lashes.
+ if (leaf == nsnull)
+ leaf = temp;
+ else
+ leaf++;
+
+ aLeafName.Assign(leaf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ MakeDirty();
+
+ const unsigned char* temp = (const unsigned char*) mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr(temp, '\\') - temp);
+ if (offset)
+ {
+ mWorkingPath.Truncate(offset+1);
+ }
+ mWorkingPath.Append(aLeafName);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval = mWorkingPath;
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const nsACString &newName, PRBool move)
+{
+ nsresult rv;
+ nsCAutoString filePath;
+
+ nsCAutoString destPath;
+ destParent->GetNativeTarget(destPath);
+
+ destPath.Append("\\");
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ sourceFile->GetNativeLeafName(aFileName);
+ destPath.Append(aFileName);
+ }
+ else
+ {
+ destPath.Append(newName);
+ }
+
+ rv = sourceFile->GetNativePath(filePath);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ APIRET rc = NO_ERROR;
+
+ if( move )
+ {
+ rc = DosMove(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()));
+ }
+
+ if (!move || rc == ERROR_NOT_SAME_DEVICE || rc == ERROR_ACCESS_DENIED) {
+ /* will get an error if the destination and source files aren't on the
+ * same drive. "MoveFile()" on Windows will go ahead and move the
+ * file without error, so we need to do the same IBM-AKR
+ */
+ do {
+ rc = DosCopy(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()), DCPY_EXISTING);
+ if (rc == ERROR_TOO_MANY_OPEN_FILES) {
+ ULONG CurMaxFH = 0;
+ LONG ReqCount = 20;
+ APIRET rc2;
+ rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
+ if (rc2 != NO_ERROR) {
+ break;
+ }
+ }
+ } while (rc == ERROR_TOO_MANY_OPEN_FILES);
+
+ /* WSOD2 HACK */
+ if (rc == 65) { // NETWORK_ACCESS_DENIED
+ CHAR achProgram[CCHMAXPATH]; // buffer for program name, parameters
+ RESULTCODES rescResults; // buffer for results of dosexecpgm
+
+ strcpy(achProgram, "CMD.EXE /C ");
+ strcat(achProgram, """COPY ");
+ strcat(achProgram, filePath.get());
+ strcat(achProgram, " ");
+ strcat(achProgram, (PSZ)NS_CONST_CAST(char*, destPath.get()));
+ strcat(achProgram, """");
+ achProgram[strlen(achProgram) + 1] = '\0';
+ achProgram[7] = '\0';
+ DosExecPgm(NULL, 0,
+ EXEC_SYNC, achProgram, (PSZ)NULL,
+ &rescResults, achProgram);
+ rc = 0; // Assume it worked
+
+ } /* rc == 65 */
+ /* moving the file is supposed to act like a rename, so delete the
+ * original file if we got this far without error
+ */
+ if( move && (rc == NO_ERROR) )
+ {
+ DosDelete( filePath.get() );
+ }
+ } /* !move or ERROR */
+
+ if (rc)
+ rv = ConvertOS2Error(rc);
+
+ return rv;
+}
+
+
+nsresult
+nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, PRBool move)
+{
+ nsCOMPtr<nsIFile> newParentDir = aParentDir;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!newParentDir)
+ {
+ // no parent was specified. We must rename.
+
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ rv = GetParent(getter_AddRefs(newParentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (!newParentDir)
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+
+ // make sure it exists and is a directory. Create it if not there.
+ PRBool exists;
+ newParentDir->Exists(&exists);
+ if (exists == PR_FALSE)
+ {
+ rv = newParentDir->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ PRBool isDir;
+ newParentDir->IsDirectory(&isDir);
+ if (isDir == PR_FALSE)
+ {
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+ }
+ }
+
+ // check to see if we are a directory, if so enumerate it.
+
+ PRBool isDir;
+ IsDirectory(&isDir);
+
+ if (!isDir)
+ {
+ rv = CopySingleFile(this, newParentDir, newName, move);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // create a new target destination in the new parentDir;
+ nsCOMPtr<nsIFile> target;
+ rv = newParentDir->Clone(getter_AddRefs(target));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString allocatedNewName;
+ if (newName.IsEmpty())
+ {
+ GetNativeLeafName(allocatedNewName);// this should be the leaf name of the
+ }
+ else
+ {
+ allocatedNewName = newName;
+ }
+
+ rv = target->AppendNative(allocatedNewName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ allocatedNewName.Truncate();
+
+ target->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (!dirEnum)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = dirEnum->Init(this);
+
+ nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
+
+ PRBool more;
+ iterator->HasMoreElements(&more);
+ while (more)
+ {
+ nsCOMPtr<nsISupports> item;
+ nsCOMPtr<nsIFile> file;
+ iterator->GetNext(getter_AddRefs(item));
+ file = do_QueryInterface(item);
+ PRBool isDir, isLink;
+
+ file->IsDirectory(&isDir);
+
+ if (move)
+ {
+ rv = file->MoveToNative(target, nsCString());
+ }
+ else
+ {
+ rv = file->CopyToNative(target, nsCString());
+ }
+
+ iterator->HasMoreElements(&more);
+ }
+ // we've finished moving all the children of this directory
+ // in the new directory. so now delete the directory
+ // note, we don't need to do a recursive delete.
+ // MoveTo() is recursive. At this point,
+ // we've already moved the children of the current folder
+ // to the new location. nothing should be left in the folder.
+ if (move)
+ {
+ rv = Remove(PR_FALSE);
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ }
+
+
+ // If we moved, we want to adjust this.
+ if (move)
+ {
+ MakeDirty();
+
+ nsCAutoString newParentPath;
+ newParentDir->GetNativePath(newParentPath);
+
+ if (newParentPath.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ GetNativeLeafName(aFileName);
+
+ InitWithNativePath(newParentPath);
+ AppendNative(aFileName);
+ }
+ else
+ {
+ InitWithNativePath(newParentPath);
+ AppendNative(newName);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary * *_retval)
+{
+ PRBool isFile;
+ nsresult rv = IsFile(&isFile);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (! isFile)
+ return NS_ERROR_FILE_IS_DIRECTORY;
+
+ *_retval = PR_LoadLibrary(mWorkingPath.get());
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ PRBool isDir;
+
+ nsresult rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+ if (isDir)
+ {
+ if (recursive)
+ {
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = dirEnum->Init(this);
+
+ nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
+
+ PRBool more;
+ iterator->HasMoreElements(&more);
+ while (more)
+ {
+ nsCOMPtr<nsISupports> item;
+ nsCOMPtr<nsIFile> file;
+ iterator->GetNext(getter_AddRefs(item));
+ file = do_QueryInterface(item);
+
+ file->Remove(recursive);
+
+ iterator->HasMoreElements(&more);
+ }
+ }
+ rv = rmdir(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
+ }
+ else
+ {
+ rv = remove(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
+ }
+
+ MakeDirty();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ *aLastModifiedTime = 0;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ // microseconds -> milliseconds
+ *aLastModifiedTime = mFileInfo64.modifyTime / PR_USEC_PER_MSEC;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ return nsLocalFile::SetModDate(aLastModifiedTime);
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsLocalFile::SetModDate(PRInt64 aLastModifiedTime)
+{
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+ PRExplodedTime pret;
+ FILESTATUS3 pathInfo;
+
+ rv = DosQueryPathInfo(filePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (NS_FAILED(rv))
+ {
+ rv = ConvertOS2Error(rv);
+ return rv;
+ }
+
+ // PR_ExplodeTime expects usecs...
+ PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_LocalTimeParameters, &pret);
+ /* fdateLastWrite.year is based off of 1980 */
+ if (pret.tm_year >= 1980)
+ pathInfo.fdateLastWrite.year = pret.tm_year-1980;
+ else
+ pathInfo.fdateLastWrite.year = pret.tm_year;
+ pathInfo.fdateLastWrite.month = pret.tm_month + 1; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
+// ???? OS2TODO st.wDayOfWeek = pret.tm_wday;
+ pathInfo.fdateLastWrite.day = pret.tm_mday;
+ pathInfo.ftimeLastWrite.hours = pret.tm_hour;
+ pathInfo.ftimeLastWrite.minutes = pret.tm_min;
+ pathInfo.ftimeLastWrite.twosecs = pret.tm_sec / 2; // adjust for twosecs?
+// ??? OS2TODO st.wMilliseconds = pret.tm_usec/1000;
+
+ rv = DosSetPathInfo(filePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo),
+ 0UL);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ MakeDirty();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+ if( chmod(filePath, aPermissions) == -1 )
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ *aFileSize = 0;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+
+ *aFileSize = mFileInfo64.size;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+
+ APIRET rc;
+ HFILE hFile;
+ ULONG actionTaken;
+
+ rc = DosOpen(filePath,
+ &hFile,
+ &actionTaken,
+ 0,
+ FILE_NORMAL,
+ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
+ NULL);
+
+ if (rc != NO_ERROR)
+ {
+ MakeDirty();
+ return NS_ERROR_FAILURE;
+ }
+
+ // Seek to new, desired end of file
+ PRInt32 hi, lo;
+ myLL_L2II(aFileSize, &hi, &lo );
+
+ rc = DosSetFileSize(hFile, lo);
+ if (rc == NO_ERROR)
+ DosClose(hFile);
+ else
+ goto error;
+
+ MakeDirty();
+ return NS_OK;
+
+ error:
+ MakeDirty();
+ DosClose(hFile);
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG(aDiskSpaceAvailable);
+
+ ULONG ulDriveNo = toupper(mWorkingPath.CharAt(0)) + 1 - 'A';
+ FSALLOCATE fsAllocate;
+ APIRET rc = DosQueryFSInfo(ulDriveNo,
+ FSIL_ALLOC,
+ &fsAllocate,
+ sizeof(fsAllocate));
+
+ if (rc != NO_ERROR)
+ return NS_ERROR_FAILURE;
+
+ *aDiskSpaceAvailable = fsAllocate.cUnitAvail;
+ *aDiskSpaceAvailable *= fsAllocate.cSectorUnit;
+ *aDiskSpaceAvailable *= fsAllocate.cbSector;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+
+ nsCAutoString parentPath(mWorkingPath);
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr((const unsigned char *) parentPath.get(), '\\')
+ - (const unsigned char *) parentPath.get());
+ if (offset < 0)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ parentPath.Truncate(offset);
+
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_NewNativeLocalFile(parentPath, PR_TRUE, getter_AddRefs(localFile));
+
+ if(NS_SUCCEEDED(rv) && localFile)
+ {
+ return CallQueryInterface(localFile, aParent);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ MakeDirty();
+ *_retval = NS_SUCCEEDED(Stat());
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *workingFilePath = mWorkingPath.get();
+
+ APIRET rc;
+ FILESTATUS3 pathInfo;
+
+ rc = DosQueryPathInfo(workingFilePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (rc != NO_ERROR)
+ {
+ rc = ConvertOS2Error(rc);
+ return rc;
+ }
+
+ *_retval = !((pathInfo.attrFile & FILE_READONLY) != 0);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString path;
+ GetNativeTarget(path);
+
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) path.get(), '\\');
+
+ if ( (strstr(leaf, ".bat") != nsnull) ||
+ (strstr(leaf, ".exe") != nsnull) ||
+ (strstr(leaf, ".cmd") != nsnull) ||
+ (strstr(leaf, ".com") != nsnull) ) {
+ *_retval = PR_TRUE;
+ } else {
+ *_retval = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_DIRECTORY);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_FILE);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *workingFilePath = mWorkingPath.get();
+
+ APIRET rc;
+ FILESTATUS3 pathInfo;
+
+ rc = DosQueryPathInfo(workingFilePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (rc != NO_ERROR)
+ {
+ rc = ConvertOS2Error(rc);
+ return rc;
+ }
+
+ *_retval = ((pathInfo.attrFile & FILE_HIDDEN) != 0);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ // No Symlinks on OS/2
+ *_retval = PR_FALSE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *workingFilePath = mWorkingPath.get();
+
+ APIRET rc;
+ FILESTATUS3 pathInfo;
+
+ rc = DosQueryPathInfo(workingFilePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (rc != NO_ERROR)
+ {
+ rc = ConvertOS2Error(rc);
+ return rc;
+ }
+
+ *_retval = ((pathInfo.attrFile & FILE_SYSTEM) != 0);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsCAutoString inFilePath;
+ inFile->GetNativePath(inFilePath);
+
+ *_retval = inFilePath.Equals(mWorkingPath);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ nsCAutoString myFilePath;
+ if ( NS_FAILED(GetNativeTarget(myFilePath)))
+ GetNativePath(myFilePath);
+
+ PRInt32 myFilePathLen = myFilePath.Length();
+
+ nsCAutoString inFilePath;
+ if ( NS_FAILED(inFile->GetNativeTarget(inFilePath)))
+ inFile->GetNativePath(inFilePath);
+
+ if ( strnicmp( myFilePath.get(), inFilePath.get(), myFilePathLen) == 0)
+ {
+ // now make sure that the |inFile|'s path has a trailing
+ // separator.
+
+ if (inFilePath[myFilePathLen] == '\\')
+ {
+ *_retval = PR_TRUE;
+ }
+
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ _retval = mWorkingPath;
+ return NS_OK;
+}
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ *aFollowLinks = PR_TRUE;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
+{
+ nsresult rv;
+
+ *entries = nsnull;
+
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+
+ *entries = dirEnum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ return GetNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ return InitWithNativePath(aPersistentDescriptor);
+}
+
+#ifndef OPEN_DEFAULT
+#define OPEN_DEFAULT 0
+#define OPEN_CONTENTS 1
+#endif
+
+
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ PRBool isDirectory = PR_FALSE;
+ nsCAutoString path;
+
+ IsDirectory(&isDirectory);
+ if (isDirectory)
+ {
+ GetNativePath(path);
+ }
+ else
+ {
+ nsCOMPtr<nsIFile> parent;
+ GetParent(getter_AddRefs(parent));
+ if (parent)
+ parent->GetNativePath(path);
+ }
+
+ HOBJECT hobject = WinQueryObject(path.get());
+ WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
+ WinOpenObject( hobject, OPEN_CONTENTS, TRUE);
+
+ // we don't care if it succeeded or failed.
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ HOBJECT hobject = WinQueryObject(mWorkingPath.get());
+ WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
+ WinOpenObject( hobject, OPEN_DEFAULT, TRUE);
+
+ // we don't care if it succeeded or failed.
+ return NS_OK;
+}
+
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+
+ *result = file;
+ return NS_OK;
+}
+
+// Locates the first occurrence of charToSearchFor in the stringToSearch
+static unsigned char* PR_CALLBACK
+_mbschr( const unsigned char* stringToSearch, int charToSearchFor)
+{
+ const unsigned char* p = stringToSearch;
+ do {
+ if (*p == charToSearchFor)
+ break;
+ p = (const unsigned char*)WinNextChar(0,0,0,(char*)p);
+ } while (*p); /* enddo */
+ // Result is p or NULL
+ return *p ? (unsigned char*)p : NULL;
+}
+
+// Locates last occurence of charToSearchFor in the stringToSearch
+extern unsigned char*
+_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor)
+{
+ int length = strlen((const char*)stringToSearch);
+ const unsigned char* p = stringToSearch+length;
+ do {
+ if (*p == charToSearchFor)
+ break;
+ p = (const unsigned char*)WinPrevChar(0,0,0,(char*)stringToSearch,(char*)p);
+ } while (p > stringToSearch); /* enddo */
+ // Result is p or NULL
+ return (*p == charToSearchFor) ? (unsigned char*)p : NULL;
+}
+
+// Implement equivalent of Win32 CreateDirectoryA
+static nsresult PR_CALLBACK
+CreateDirectoryA( PSZ path, PEAOP2 ppEABuf)
+{
+ APIRET rc;
+ nsresult rv;
+ FILESTATUS3 pathInfo;
+
+ rc = DosCreateDir( path, ppEABuf );
+ if (rc != NO_ERROR) {
+ rv = ConvertOS2Error(rc);
+
+ // Check if directory already exists and if so, reflect that in the return value
+ rc = DosQueryPathInfo(path,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+ if (rc == NO_ERROR)
+ rv = ERROR_FILE_EXISTS;
+ }
+ else
+ rv = rc;
+
+ return rv;
+}
+
+static int isleadbyte(int c)
+{
+ static BOOL bDBCSFilled=FALSE;
+ static BYTE DBCSInfo[12] = { 0 }; /* According to the Control Program Guide&Ref,
+ 12 bytes is sufficient */
+ BYTE *curr;
+ BOOL retval = FALSE;
+
+ if( !bDBCSFilled ) {
+ COUNTRYCODE ctrycodeInfo = { 0 };
+ APIRET rc = NO_ERROR;
+ ctrycodeInfo.country = 0; /* Current Country */
+ ctrycodeInfo.codepage = 0; /* Current Codepage */
+
+ rc = DosQueryDBCSEnv( sizeof( DBCSInfo ),
+ &ctrycodeInfo,
+ DBCSInfo );
+ if( rc != NO_ERROR ) {
+ /* we had an error, do something? */
+ return FALSE;
+ }
+ bDBCSFilled=TRUE;
+ }
+
+ curr = DBCSInfo;
+ /* DBCSInfo returned by DosQueryDBCSEnv is terminated with two '0' bytes in a row */
+ while(( *curr != 0 ) && ( *(curr+1) != 0)) {
+ if(( c >= *curr ) && ( c <= *(curr+1) )) {
+ retval=TRUE;
+ break;
+ }
+ curr+=2;
+ }
+
+ return retval;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ if (filePath.IsEmpty())
+ return InitWithNativePath(nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(filePath, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return InitWithNativePath(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Append(const nsAString &node)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return AppendNative(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativePath(const nsAString &node)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return AppendRelativeNativePath(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeLeafName(tmp);
+
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, aLeafName);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ if (aLeafName.IsEmpty())
+ return SetNativeLeafName(nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return SetNativeLeafName(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ return NS_CopyNativeToUnicode(mWorkingPath, _retval);
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return CopyToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToFollowingLinksNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return CopyToFollowingLinksNative(newParentDir, tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return MoveToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return MoveToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeTarget(tmp);
+
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, _retval);
+
+ return rv;
+}
+
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString buf;
+ nsresult rv = NS_CopyUnicodeToNative(path, buf);
+ if (NS_FAILED(rv)) {
+ *result = nsnull;
+ return rv;
+ }
+ return NS_NewNativeLocalFile(buf, followLinks, result);
+}
+
+//----------------------------------------------------------------------------
+// global init/shutdown
+//----------------------------------------------------------------------------
+
+void
+nsLocalFile::GlobalInit()
+{
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h
new file mode 100644
index 00000000..72f3127a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation. Modifications made by IBM
+ * described herein are Copyright (c) International Business Machines Corporation, 2000.
+ * Modifications to Mozilla code or documentation identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 05/26/2000 IBM Corp. Make more like Windows.
+ */
+
+#ifndef _nsLocalFileOS2_H_
+#define _nsLocalFileOS2_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsIFactory.h"
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#define INCL_DOSPROCESS
+#define INCL_DOSSESMGR
+#define INCL_DOSMODULEMGR
+#define INCL_DOSNLS
+#define INCL_DOSMISC
+#define INCL_WINCOUNTRY
+#define INCL_WINWORKPLACE
+
+#include <os2.h>
+
+class NS_COM nsLocalFile : public nsILocalFile
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIFile interface
+ NS_DECL_NSIFILE
+
+ // nsILocalFile interface
+ NS_DECL_NSILOCALFILE
+
+public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ ~nsLocalFile() {}
+
+ nsLocalFile(const nsLocalFile& other);
+
+ // this is the flag which indicates if I can used cached information about the file
+ PRPackedBool mDirty;
+
+ // this string will alway be in native format!
+ nsCString mWorkingPath;
+
+ PRFileInfo64 mFileInfo64;
+
+ void MakeDirty();
+ nsresult Stat();
+
+ nsresult CopyMove(nsIFile *newParentDir, const nsACString &newName, PRBool move);
+ nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const nsACString &newName, PRBool move);
+
+ nsresult SetModDate(PRInt64 aLastModifiedTime);
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp
new file mode 100644
index 00000000..dfc431d8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp
@@ -0,0 +1,2542 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.com>
+ * Jungshik Shin <jshin@mailaps.org>
+ * Asaf Romano <mozilla.mano@sent.com>
+ * Mark Mentovai <mark@moxienet.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 "nsLocalFile.h"
+#include "nsDirectoryServiceDefs.h"
+
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsIDirectoryEnumerator.h"
+#include "nsISimpleEnumerator.h"
+#include "nsITimelineService.h"
+#include "nsVoidArray.h"
+
+#include "plbase64.h"
+#include "prmem.h"
+#include "nsCRT.h"
+#include "nsHashKeys.h"
+
+#include "MoreFilesX.h"
+#include "FSCopyObject.h"
+#include "nsAutoBuffer.h"
+#include "nsTraceRefcntImpl.h"
+
+// Mac Includes
+#include <Carbon/Carbon.h>
+
+// Unix Includes
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#if !defined(MAC_OS_X_VERSION_10_4) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
+#define GetAliasSizeFromRecord(aliasRecord) aliasRecord.aliasSize
+#else
+#define GetAliasSizeFromRecord(aliasRecord) GetAliasSizeFromPtr(&aliasRecord)
+#endif
+
+#define CHECK_mBaseRef() \
+ PR_BEGIN_MACRO \
+ if (!mBaseRef) \
+ return NS_ERROR_NOT_INITIALIZED; \
+ PR_END_MACRO
+
+//*****************************************************************************
+// Static Function Prototypes
+//*****************************************************************************
+
+static nsresult MacErrorMapper(OSErr inErr);
+static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn);
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
+
+//*****************************************************************************
+// Local Helper Classes
+//*****************************************************************************
+
+#pragma mark -
+#pragma mark [FSRef operator==]
+
+bool operator==(const FSRef& lhs, const FSRef& rhs)
+{
+ return (::FSCompareFSRefs(&lhs, &rhs) == noErr);
+}
+
+#pragma mark -
+#pragma mark [StFollowLinksState]
+
+class StFollowLinksState
+{
+ public:
+ StFollowLinksState(nsLocalFile& aFile) :
+ mFile(aFile)
+ {
+ mFile.GetFollowLinks(&mSavedState);
+ }
+
+ StFollowLinksState(nsLocalFile& aFile, PRBool followLinksState) :
+ mFile(aFile)
+ {
+ mFile.GetFollowLinks(&mSavedState);
+ mFile.SetFollowLinks(followLinksState);
+ }
+
+ ~StFollowLinksState()
+ {
+ mFile.SetFollowLinks(mSavedState);
+ }
+
+ private:
+ nsLocalFile& mFile;
+ PRBool mSavedState;
+};
+
+#pragma mark -
+#pragma mark [nsDirEnumerator]
+
+class nsDirEnumerator : public nsISimpleEnumerator,
+ public nsIDirectoryEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator() :
+ mIterator(nsnull),
+ mFSRefsArray(nsnull),
+ mArrayCnt(0), mArrayIndex(0)
+ {
+ }
+
+ nsresult Init(nsILocalFileMac* parent)
+ {
+ NS_ENSURE_ARG(parent);
+
+ OSErr err;
+ nsresult rv;
+ FSRef parentRef;
+
+ rv = parent->GetFSRef(&parentRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mFSRefsArray = (FSRef *)nsMemory::Alloc(sizeof(FSRef)
+ * kRequestCountPerIteration);
+ if (!mFSRefsArray)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ err = ::FSOpenIterator(&parentRef, kFSIterateFlat, &mIterator);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ if (mNext == nsnull) {
+ if (mArrayIndex >= mArrayCnt) {
+ ItemCount actualCnt;
+ OSErr err = ::FSGetCatalogInfoBulk(mIterator,
+ kRequestCountPerIteration,
+ &actualCnt,
+ nsnull,
+ kFSCatInfoNone,
+ nsnull,
+ mFSRefsArray,
+ nsnull,
+ nsnull);
+
+ if (err == noErr || err == errFSNoMoreItems) {
+ mArrayCnt = actualCnt;
+ mArrayIndex = 0;
+ }
+ }
+ if (mArrayIndex < mArrayCnt) {
+ nsLocalFile *newFile = new nsLocalFile;
+ if (!newFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+ FSRef fsRef = mFSRefsArray[mArrayIndex];
+ if (NS_FAILED(newFile->InitWithFSRef(&fsRef)))
+ return NS_ERROR_FAILURE;
+ mArrayIndex++;
+ mNext = newFile;
+ }
+ }
+ *result = mNext != nsnull;
+ if (!*result)
+ Close();
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = nsnull;
+
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNextFile(nsIFile **result)
+ {
+ *result = nsnull;
+ PRBool hasMore = PR_FALSE;
+ nsresult rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv) || !hasMore)
+ return rv;
+ *result = mNext;
+ NS_IF_ADDREF(*result);
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD Close()
+ {
+ if (mIterator) {
+ ::FSCloseIterator(mIterator);
+ mIterator = nsnull;
+ }
+ if (mFSRefsArray) {
+ nsMemory::Free(mFSRefsArray);
+ mFSRefsArray = nsnull;
+ }
+ return NS_OK;
+ }
+
+ private:
+ ~nsDirEnumerator()
+ {
+ Close();
+ }
+
+ protected:
+ // According to Apple doc, request the number of objects
+ // per call that will fit in 4 VM pages.
+ enum {
+ kRequestCountPerIteration = ((4096 * 4) / sizeof(FSRef))
+ };
+
+ nsCOMPtr<nsILocalFileMac> mNext;
+
+ FSIterator mIterator;
+ FSRef *mFSRefsArray;
+ PRInt32 mArrayCnt, mArrayIndex;
+};
+
+NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
+
+#pragma mark -
+#pragma mark [StAEDesc]
+
+class StAEDesc: public AEDesc
+{
+public:
+ StAEDesc()
+ {
+ descriptorType = typeNull;
+ dataHandle = nil;
+ }
+
+ ~StAEDesc()
+ {
+ ::AEDisposeDesc(this);
+ }
+};
+
+#define FILENAME_BUFFER_SIZE 512
+
+//*****************************************************************************
+// nsLocalFile
+//*****************************************************************************
+
+const char nsLocalFile::kPathSepChar = '/';
+const PRUnichar nsLocalFile::kPathSepUnichar = '/';
+
+// The HFS+ epoch is Jan. 1, 1904 GMT - differs from HFS in which times were local
+// The NSPR epoch is Jan. 1, 1970 GMT
+// 2082844800 is the difference in seconds between those dates
+const PRInt64 nsLocalFile::kJanuaryFirst1970Seconds = 2082844800LL;
+
+#pragma mark -
+#pragma mark [CTORs/DTOR]
+
+nsLocalFile::nsLocalFile() :
+ mBaseRef(nsnull),
+ mTargetRef(nsnull),
+ mCachedFSRefValid(PR_FALSE),
+ mFollowLinks(PR_TRUE),
+ mFollowLinksDirty(PR_TRUE)
+{
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& src) :
+ mBaseRef(src.mBaseRef),
+ mTargetRef(src.mTargetRef),
+ mCachedFSRef(src.mCachedFSRef),
+ mCachedFSRefValid(src.mCachedFSRefValid),
+ mFollowLinks(src.mFollowLinks),
+ mFollowLinksDirty(src.mFollowLinksDirty)
+{
+ // A CFURLRef is immutable so no need to copy, just retain.
+ if (mBaseRef)
+ ::CFRetain(mBaseRef);
+ if (mTargetRef)
+ ::CFRetain(mTargetRef);
+}
+
+nsLocalFile::~nsLocalFile()
+{
+ if (mBaseRef)
+ ::CFRelease(mBaseRef);
+ if (mTargetRef)
+ ::CFRelease(mTargetRef);
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsISupports
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsISupports]
+
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
+ nsILocalFileMac,
+ nsILocalFile,
+ nsIFile,
+ nsIHashable)
+
+NS_METHOD nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsIFile
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsIFile]
+
+/* void append (in AString node); */
+NS_IMETHODIMP nsLocalFile::Append(const nsAString& aNode)
+{
+ return AppendNative(NS_ConvertUTF16toUTF8(aNode));
+}
+
+/* [noscript] void appendNative (in ACString node); */
+NS_IMETHODIMP nsLocalFile::AppendNative(const nsACString& aNode)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsACString::const_iterator start, end;
+ aNode.BeginReading(start);
+ aNode.EndReading(end);
+ if (FindCharInReadable(kPathSepChar, start, end))
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ PromiseFlatCString(aNode).get(),
+ kCFStringEncodingUTF8);
+ if (nodeStrRef) {
+ CFURLRef newRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
+ mBaseRef, nodeStrRef, PR_FALSE);
+ ::CFRelease(nodeStrRef);
+ if (newRef) {
+ SetBaseRef(newRef);
+ ::CFRelease(newRef);
+ return NS_OK;
+ }
+ }
+ return NS_ERROR_FAILURE;
+}
+
+/* void normalize (); */
+NS_IMETHODIMP nsLocalFile::Normalize()
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ // CFURL doesn't doesn't seem to resolve paths containing relative
+ // components, so we'll nick the stdlib code from nsLocalFileUnix
+ UInt8 path[PATH_MAX] = "";
+ Boolean success;
+ success = ::CFURLGetFileSystemRepresentation(mBaseRef, true, path, PATH_MAX);
+ if (!success)
+ return NS_ERROR_FAILURE;
+
+ char resolved_path[PATH_MAX] = "";
+ char *resolved_path_ptr = nsnull;
+ resolved_path_ptr = realpath((char*)path, resolved_path);
+
+ // if there is an error, the return is null.
+ if (!resolved_path_ptr)
+ return NSRESULT_FOR_ERRNO();
+
+ // Need to know whether we're a directory to create a new CFURLRef
+ PRBool isDirectory;
+ nsresult rv = IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_ERROR_FAILURE;
+ CFStringRef pathStrRef =
+ ::CFStringCreateWithCString(kCFAllocatorDefault,
+ resolved_path,
+ kCFStringEncodingUTF8);
+ if (pathStrRef) {
+ CFURLRef newURLRef =
+ ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pathStrRef,
+ kCFURLPOSIXPathStyle, isDirectory);
+ if (newURLRef) {
+ SetBaseRef(newURLRef);
+ ::CFRelease(newURLRef);
+ rv = NS_OK;
+ }
+ ::CFRelease(pathStrRef);
+ }
+
+ return rv;
+}
+
+/* void create (in unsigned long type, in unsigned long permissions); */
+NS_IMETHODIMP nsLocalFile::Create(PRUint32 type, PRUint32 permissions)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsStringArray nonExtantNodes;
+ CFURLRef pathURLRef = mBaseRef;
+ FSRef pathFSRef;
+ CFStringRef leafStrRef = nsnull;
+ nsAutoBuffer<UniChar, FILENAME_BUFFER_SIZE> buffer;
+ Boolean success;
+
+ // Work backwards through the path to find the last node which
+ // exists. Place the nodes which don't exist in an array and we'll
+ // create those below.
+ while ((success = ::CFURLGetFSRef(pathURLRef, &pathFSRef)) == false) {
+ leafStrRef = ::CFURLCopyLastPathComponent(pathURLRef);
+ if (!leafStrRef)
+ break;
+ CFIndex leafLen = ::CFStringGetLength(leafStrRef);
+ if (!buffer.EnsureElemCapacity(leafLen + 1))
+ break;
+ ::CFStringGetCharacters(leafStrRef, CFRangeMake(0, leafLen), buffer.get());
+ buffer.get()[leafLen] = '\0';
+ nonExtantNodes.AppendString(nsString(nsDependentString(buffer.get())));
+ ::CFRelease(leafStrRef);
+ leafStrRef = nsnull;
+
+ // Get the parent of the leaf for the next go round
+ CFURLRef parent = ::CFURLCreateCopyDeletingLastPathComponent(NULL, pathURLRef);
+ if (!parent)
+ break;
+ if (pathURLRef != mBaseRef)
+ ::CFRelease(pathURLRef);
+ pathURLRef = parent;
+ }
+ if (pathURLRef != mBaseRef)
+ ::CFRelease(pathURLRef);
+ if (leafStrRef != nsnull)
+ ::CFRelease(leafStrRef);
+ if (!success)
+ return NS_ERROR_FAILURE;
+ PRInt32 nodesToCreate = nonExtantNodes.Count();
+ if (nodesToCreate == 0)
+ return NS_ERROR_FILE_ALREADY_EXISTS;
+
+ OSErr err;
+ nsAutoString nextNodeName;
+ for (PRInt32 i = nodesToCreate - 1; i > 0; i--) {
+ nonExtantNodes.StringAt(i, nextNodeName);
+ err = ::FSCreateDirectoryUnicode(&pathFSRef,
+ nextNodeName.Length(),
+ (const UniChar *)nextNodeName.get(),
+ kFSCatInfoNone,
+ nsnull, &pathFSRef, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ }
+ nonExtantNodes.StringAt(0, nextNodeName);
+ if (type == NORMAL_FILE_TYPE) {
+ err = ::FSCreateFileUnicode(&pathFSRef,
+ nextNodeName.Length(),
+ (const UniChar *)nextNodeName.get(),
+ kFSCatInfoNone,
+ nsnull, nsnull, nsnull);
+ }
+ else {
+ err = ::FSCreateDirectoryUnicode(&pathFSRef,
+ nextNodeName.Length(),
+ (const UniChar *)nextNodeName.get(),
+ kFSCatInfoNone,
+ nsnull, nsnull, nsnull, nsnull);
+ }
+
+ return MacErrorMapper(err);
+}
+
+/* attribute AString leafName; */
+NS_IMETHODIMP nsLocalFile::GetLeafName(nsAString& aLeafName)
+{
+ nsCAutoString nativeString;
+ nsresult rv = GetNativeLeafName(nativeString);
+ if (NS_FAILED(rv))
+ return rv;
+ CopyUTF8toUTF16NFC(nativeString, aLeafName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetLeafName(const nsAString& aLeafName)
+{
+ return SetNativeLeafName(NS_ConvertUTF16toUTF8(aLeafName));
+}
+
+/* [noscript] attribute ACString nativeLeafName; */
+NS_IMETHODIMP nsLocalFile::GetNativeLeafName(nsACString& aNativeLeafName)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsresult rv = NS_ERROR_FAILURE;
+ CFStringRef leafStrRef = ::CFURLCopyLastPathComponent(mBaseRef);
+ if (leafStrRef) {
+ rv = CFStringReftoUTF8(leafStrRef, aNativeLeafName);
+ ::CFRelease(leafStrRef);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::SetNativeLeafName(const nsACString& aNativeLeafName)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsresult rv = NS_ERROR_FAILURE;
+ CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
+ if (parentURLRef) {
+ CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ PromiseFlatCString(aNativeLeafName).get(),
+ kCFStringEncodingUTF8);
+
+ if (nodeStrRef) {
+ CFURLRef newURLRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
+ parentURLRef, nodeStrRef, PR_FALSE);
+ if (newURLRef) {
+ SetBaseRef(newURLRef);
+ ::CFRelease(newURLRef);
+ rv = NS_OK;
+ }
+ ::CFRelease(nodeStrRef);
+ }
+ ::CFRelease(parentURLRef);
+ }
+ return rv;
+}
+
+/* void copyTo (in nsIFile newParentDir, in AString newName); */
+NS_IMETHODIMP nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString& newName)
+{
+ return CopyInternal(newParentDir, newName, PR_FALSE);
+}
+
+/* [noscrpit] void CopyToNative (in nsIFile newParentDir, in ACString newName); */
+NS_IMETHODIMP nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString& newName)
+{
+ return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_FALSE);
+}
+
+/* void copyToFollowingLinks (in nsIFile newParentDir, in AString newName); */
+NS_IMETHODIMP nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString& newName)
+{
+ return CopyInternal(newParentDir, newName, PR_TRUE);
+}
+
+/* [noscript] void copyToFollowingLinksNative (in nsIFile newParentDir, in ACString newName); */
+NS_IMETHODIMP nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString& newName)
+{
+ return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_TRUE);
+}
+
+/* void moveTo (in nsIFile newParentDir, in AString newName); */
+NS_IMETHODIMP nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString& newName)
+{
+ return MoveToNative(newParentDir, NS_ConvertUTF16toUTF8(newName));
+}
+
+/* [noscript] void moveToNative (in nsIFile newParentDir, in ACString newName); */
+NS_IMETHODIMP nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString& newName)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ StFollowLinksState followLinks(*this, PR_FALSE);
+
+ PRBool isDirectory;
+ nsresult rv = IsDirectory(&isDirectory);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Get the source path.
+ nsCAutoString srcPath;
+ rv = GetNativePath(srcPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Build the destination path.
+ nsCOMPtr<nsIFile> parentDir = newParentDir;
+ if (!parentDir) {
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+ rv = GetParent(getter_AddRefs(parentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else {
+ PRBool exists;
+ rv = parentDir->Exists(&exists);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!exists) {
+ rv = parentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ nsCAutoString destPath;
+ rv = parentDir->GetNativePath(destPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!newName.IsEmpty())
+ destPath.Append(NS_LITERAL_CSTRING("/") + newName);
+ else {
+ nsCAutoString leafName;
+ rv = GetNativeLeafName(leafName);
+ if (NS_FAILED(rv))
+ return rv;
+ destPath.Append(NS_LITERAL_CSTRING("/") + leafName);
+ }
+
+ // Perform the move.
+ if (rename(srcPath.get(), destPath.get()) != 0) {
+ if (errno == EXDEV) {
+ // Can't move across volume (device) boundaries. Copy and remove.
+ rv = CopyToNative(parentDir, newName);
+ if (NS_SUCCEEDED(rv)) {
+ // Permit removal failure.
+ Remove(PR_TRUE);
+ }
+ }
+ else
+ rv = NSRESULT_FOR_ERRNO();
+
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Update |this| to refer to the moved file.
+ CFURLRef newBaseRef =
+ ::CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)destPath.get(),
+ destPath.Length(), isDirectory);
+ if (!newBaseRef)
+ return NS_ERROR_FAILURE;
+ SetBaseRef(newBaseRef);
+ ::CFRelease(newBaseRef);
+
+ return rv;
+}
+
+/* void remove (in boolean recursive); */
+NS_IMETHODIMP nsLocalFile::Remove(PRBool recursive)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ // XXX If we're an alias, never remove target
+ StFollowLinksState followLinks(*this, PR_FALSE);
+
+ PRBool isDirectory;
+ nsresult rv = IsDirectory(&isDirectory);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (recursive && isDirectory) {
+ FSRef fsRef;
+ rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Call MoreFilesX to do a recursive removal.
+ OSStatus err = ::FSDeleteContainer(&fsRef);
+ rv = MacErrorMapper(err);
+ }
+ else {
+ nsCAutoString path;
+ rv = GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* pathPtr = path.get();
+ int status;
+ if (isDirectory)
+ status = rmdir(pathPtr);
+ else
+ status = unlink(pathPtr);
+
+ if (status != 0)
+ rv = NSRESULT_FOR_ERRNO();
+ }
+
+ mCachedFSRefValid = PR_FALSE;
+ return rv;
+}
+
+/* attribute unsigned long permissions; */
+NS_IMETHODIMP nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG_POINTER(aPermissions);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ FSPermissionInfo *permPtr = (FSPermissionInfo*)catalogInfo.permissions;
+ *aPermissions = permPtr->mode;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ FSPermissionInfo *permPtr = (FSPermissionInfo*)catalogInfo.permissions;
+ permPtr->mode = (UInt16)aPermissions;
+ err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo);
+ return MacErrorMapper(err);
+}
+
+/* attribute unsigned long permissionsOfLink; */
+NS_IMETHODIMP nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissionsOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute PRInt64 lastModifiedTime; */
+NS_IMETHODIMP nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(aLastModifiedTime);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *aLastModifiedTime = HFSPlustoNSPRTime(catalogInfo.contentModDate);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ OSErr err;
+ nsresult rv;
+ FSRef fsRef;
+ FSCatalogInfo catalogInfo;
+
+ rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSRef parentRef;
+ PRBool notifyParent;
+
+ /* Get the node flags, the content modification date and time, and the parent ref */
+ err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoContentMod,
+ &catalogInfo, NULL, NULL, &parentRef);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ /* Notify the parent if this is a file */
+ notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
+
+ NSPRtoHFSPlusTime(aLastModifiedTime, catalogInfo.contentModDate);
+ err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ /* Send a notification for the parent of the file, or for the directory */
+ err = FNNotify(notifyParent ? &parentRef : &fsRef, kFNDirectoryModifiedMessage, kNilOptions);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+}
+
+/* attribute PRInt64 lastModifiedTimeOfLink; */
+NS_IMETHODIMP nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTimeOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTimeOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute PRInt64 fileSize; */
+NS_IMETHODIMP nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG_POINTER(aFileSize);
+ *aFileSize = 0;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoDataSizes, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ // FSGetCatalogInfo can return a bogus size for directories sometimes, so only
+ // rely on the answer for files
+ if ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0)
+ *aFileSize = catalogInfo.dataLogicalSize;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ SInt16 refNum;
+ OSErr err = ::FSOpenFork(&fsRef, 0, nsnull, fsWrPerm, &refNum);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ err = ::FSSetForkSize(refNum, fsFromStart, aFileSize);
+ ::FSCloseFork(refNum);
+
+ return MacErrorMapper(err);
+}
+
+/* readonly attribute PRInt64 fileSizeOfLink; */
+NS_IMETHODIMP nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSizeOfLink)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(aFileSizeOfLink);
+
+ StFollowLinksState followLinks(*this, PR_FALSE);
+ return GetFileSize(aFileSizeOfLink);
+}
+
+/* readonly attribute AString target; */
+NS_IMETHODIMP nsLocalFile::GetTarget(nsAString& aTarget)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* [noscript] readonly attribute ACString nativeTarget; */
+NS_IMETHODIMP nsLocalFile::GetNativeTarget(nsACString& aNativeTarget)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute AString path; */
+NS_IMETHODIMP nsLocalFile::GetPath(nsAString& aPath)
+{
+ nsCAutoString nativeString;
+ nsresult rv = GetNativePath(nativeString);
+ if (NS_FAILED(rv))
+ return rv;
+ CopyUTF8toUTF16NFC(nativeString, aPath);
+ return NS_OK;
+}
+
+/* [noscript] readonly attribute ACString nativePath; */
+NS_IMETHODIMP nsLocalFile::GetNativePath(nsACString& aNativePath)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsresult rv = NS_ERROR_FAILURE;
+ CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseRef, kCFURLPOSIXPathStyle);
+ if (pathStrRef) {
+ rv = CFStringReftoUTF8(pathStrRef, aNativePath);
+ ::CFRelease(pathStrRef);
+ }
+ return rv;
+}
+
+/* boolean exists (); */
+NS_IMETHODIMP nsLocalFile::Exists(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ if (NS_SUCCEEDED(GetFSRefInternal(fsRef, PR_TRUE))) {
+ *_retval = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+/* boolean isWritable (); */
+NS_IMETHODIMP nsLocalFile::IsWritable(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+ if (::FSCheckLock(&fsRef) == noErr) {
+ PRUint32 permissions;
+ rv = GetPermissions(&permissions);
+ if (NS_FAILED(rv))
+ return rv;
+ *_retval = ((permissions & S_IWUSR) != 0);
+ }
+ return NS_OK;
+}
+
+/* boolean isReadable (); */
+NS_IMETHODIMP nsLocalFile::IsReadable(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ PRUint32 permissions;
+ nsresult rv = GetPermissions(&permissions);
+ if (NS_FAILED(rv))
+ return rv;
+ *_retval = ((permissions & S_IRUSR) != 0);
+ return NS_OK;
+}
+
+/* boolean isExecutable (); */
+NS_IMETHODIMP nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
+ LSItemInfoRecord theInfo;
+ if (::LSCopyItemInfoForRef(&fsRef, theInfoRequest, &theInfo) == noErr) {
+ if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+/* boolean isHidden (); */
+NS_IMETHODIMP nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ HFSUniStr255 leafName;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catalogInfo,
+ &leafName, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ FileInfo *fInfoPtr = (FileInfo *)(catalogInfo.finderInfo); // Finder flags are in the same place whether we use FileInfo or FolderInfo
+ if ((fInfoPtr->finderFlags & kIsInvisible) != 0) {
+ *_retval = PR_TRUE;
+ }
+ else {
+ // If the leaf name begins with a '.', consider it invisible
+ if (leafName.length >= 1 && leafName.unicode[0] == UniChar('.'))
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+/* boolean isDirectory (); */
+NS_IMETHODIMP nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef, PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *_retval = ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0);
+ return NS_OK;
+}
+
+/* boolean isFile (); */
+NS_IMETHODIMP nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef, PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *_retval = ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0);
+ return NS_OK;
+}
+
+/* boolean isSymlink (); */
+NS_IMETHODIMP nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ FSRef fsRef;
+ if (::CFURLGetFSRef(mBaseRef, &fsRef)) {
+ Boolean isAlias, isFolder;
+ if (::FSIsAliasFile(&fsRef, &isAlias, &isFolder) == noErr)
+ *_retval = isAlias;
+ }
+ return NS_OK;
+}
+
+/* boolean isSpecial (); */
+NS_IMETHODIMP nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIFile clone (); */
+NS_IMETHODIMP nsLocalFile::Clone(nsIFile **_retval)
+{
+ // Just copy-construct ourselves
+ *_retval = new nsLocalFile(*this);
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*_retval);
+
+ return NS_OK;
+}
+
+/* boolean equals (in nsIFile inFile); */
+NS_IMETHODIMP nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ return EqualsInternal(inFile, PR_TRUE, _retval);
+}
+
+nsresult
+nsLocalFile::EqualsInternal(nsISupports* inFile, PRBool aUpdateCache,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ nsCOMPtr<nsILocalFileMac> inMacFile(do_QueryInterface(inFile));
+ if (!inFile)
+ return NS_OK;
+
+ nsLocalFile* inLF =
+ static_cast<nsLocalFile*>((nsILocalFileMac*) inMacFile);
+
+ // If both exist, compare FSRefs
+ FSRef thisFSRef, inFSRef;
+ nsresult rv1 = GetFSRefInternal(thisFSRef, aUpdateCache);
+ nsresult rv2 = inLF->GetFSRefInternal(inFSRef, aUpdateCache);
+ if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
+ *_retval = (thisFSRef == inFSRef);
+ return NS_OK;
+ }
+ // If one exists and the other doesn't, not equal
+ if (rv1 != rv2)
+ return NS_OK;
+
+ // Arg, we have to get their paths and compare
+ nsCAutoString thisPath, inPath;
+ if (NS_FAILED(GetNativePath(thisPath)))
+ return NS_ERROR_FAILURE;
+ if (NS_FAILED(inMacFile->GetNativePath(inPath)))
+ return NS_ERROR_FAILURE;
+ *_retval = thisPath.Equals(inPath);
+
+ return NS_OK;
+}
+
+/* boolean contains (in nsIFile inFile, in boolean recur); */
+NS_IMETHODIMP nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ PRBool isDir;
+ nsresult rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_OK; // must be a dir to contain someone
+
+ nsCAutoString thisPath, inPath;
+ if (NS_FAILED(GetNativePath(thisPath)) || NS_FAILED(inFile->GetNativePath(inPath)))
+ return NS_ERROR_FAILURE;
+ size_t thisPathLen = thisPath.Length();
+ if ((inPath.Length() > thisPathLen + 1) && (strncasecmp(thisPath.get(), inPath.get(), thisPathLen) == 0)) {
+ // Now make sure that the |inFile|'s path has a separator at thisPathLen,
+ // and there's at least one more character after that.
+ if (inPath[thisPathLen] == kPathSepChar)
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+/* readonly attribute nsIFile parent; */
+NS_IMETHODIMP nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nsnull;
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsLocalFile *newFile = nsnull;
+
+ // If it can be determined without error that a file does not
+ // have a parent, return nsnull for the parent and NS_OK as the result.
+ // See bug 133617.
+ nsresult rv = NS_OK;
+ CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
+ if (parentURLRef) {
+ // If the parent path is longer than file's path then
+ // CFURLCreateCopyDeletingLastPathComponent must have simply added
+ // two dots at the end - in this case indicate that there is no parent.
+ // See bug 332389.
+ CFStringRef path = ::CFURLGetString(mBaseRef);
+ CFStringRef newPath = ::CFURLGetString(parentURLRef);
+ if (::CFStringGetLength(newPath) < ::CFStringGetLength(path)) {
+ rv = NS_ERROR_FAILURE;
+ newFile = new nsLocalFile;
+ if (newFile) {
+ rv = newFile->InitWithCFURL(parentURLRef);
+ if (NS_SUCCEEDED(rv)) {
+ NS_ADDREF(*aParent = newFile);
+ rv = NS_OK;
+ }
+ }
+ }
+ ::CFRelease(parentURLRef);
+ }
+ return rv;
+}
+
+/* readonly attribute nsISimpleEnumerator directoryEntries; */
+NS_IMETHODIMP nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **aDirectoryEntries)
+{
+ NS_ENSURE_ARG_POINTER(aDirectoryEntries);
+ *aDirectoryEntries = nsnull;
+
+ nsresult rv;
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator;
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+ *aDirectoryEntries = dirEnum;
+
+ return NS_OK;
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsILocalFile
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsILocalFile]
+
+/* void initWithPath (in AString filePath); */
+NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString& filePath)
+{
+ return InitWithNativePath(NS_ConvertUTF16toUTF8(filePath));
+}
+
+/* [noscript] void initWithNativePath (in ACString filePath); */
+NS_IMETHODIMP nsLocalFile::InitWithNativePath(const nsACString& filePath)
+{
+ nsCAutoString fixedPath;
+ if (Substring(filePath, 0, 2).EqualsLiteral("~/")) {
+ nsCOMPtr<nsIFile> homeDir;
+ nsCAutoString homePath;
+ nsresult rv = NS_GetSpecialDirectory(NS_OS_HOME_DIR,
+ getter_AddRefs(homeDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = homeDir->GetNativePath(homePath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ fixedPath = homePath + Substring(filePath, 1, filePath.Length() - 1);
+ }
+ else if (filePath.IsEmpty() || filePath.First() != '/')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ else
+ fixedPath.Assign(filePath);
+
+ // A path with consecutive '/'s which are not between
+ // nodes crashes CFURLGetFSRef(). Consecutive '/'s which
+ // are between actual nodes are OK. So, convert consecutive
+ // '/'s to a single one.
+ fixedPath.ReplaceSubstring("//", "/");
+
+#if 1 // bird: hack to fix RegistryLocationForSpec issues with /path/to/./components
+ fixedPath.ReplaceSubstring("/./", "/");
+ size_t len = fixedPath.Length();
+ while (len > 2)
+ {
+ size_t choplen = 0;
+ if (!strcmp(fixedPath.get() + len - 2, "/."))
+ choplen = 2;
+ else if (!strcmp(fixedPath.get() + len - 1, "/"))
+ choplen = 1;
+ else
+ break;
+ fixedPath = StringHead(fixedPath, len - choplen);
+ }
+ // bird: another hack for the issue with VirtualBoxVM and symlinks...
+ char tmpBuf[PATH_MAX];
+ if (realpath(fixedPath.get(), tmpBuf))
+ fixedPath = tmpBuf;
+#endif
+
+ // On 10.2, huge paths also crash CFURLGetFSRef()
+ if (fixedPath.Length() > PATH_MAX)
+ return NS_ERROR_FILE_NAME_TOO_LONG;
+
+ CFStringRef pathAsCFString;
+ CFURLRef pathAsCFURL;
+
+ pathAsCFString = ::CFStringCreateWithCString(nsnull, fixedPath.get(), kCFStringEncodingUTF8);
+ if (!pathAsCFString)
+ return NS_ERROR_FAILURE;
+ pathAsCFURL = ::CFURLCreateWithFileSystemPath(nsnull, pathAsCFString, kCFURLPOSIXPathStyle, PR_FALSE);
+ if (!pathAsCFURL) {
+ ::CFRelease(pathAsCFString);
+ return NS_ERROR_FAILURE;
+ }
+ SetBaseRef(pathAsCFURL);
+ ::CFRelease(pathAsCFURL);
+ ::CFRelease(pathAsCFString);
+ return NS_OK;
+}
+
+/* void initWithFile (in nsILocalFile aFile); */
+NS_IMETHODIMP nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+ NS_ENSURE_ARG(aFile);
+
+ nsCOMPtr<nsILocalFileMac> aFileMac(do_QueryInterface(aFile));
+ if (!aFileMac)
+ return NS_ERROR_UNEXPECTED;
+ CFURLRef urlRef;
+ nsresult rv = aFileMac->GetCFURL(&urlRef);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = InitWithCFURL(urlRef);
+ ::CFRelease(urlRef);
+ return rv;
+}
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ NS_ENSURE_ARG_POINTER(aFollowLinks);
+
+ *aFollowLinks = mFollowLinks;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ if (aFollowLinks != mFollowLinks) {
+ mFollowLinks = aFollowLinks;
+ UpdateTargetRef();
+ }
+ return NS_OK;
+}
+
+/* [noscript] PRFileDescStar openNSPRFileDesc (in long flags, in long mode); */
+NS_IMETHODIMP nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCAutoString path;
+ nsresult rv = GetPathInternal(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = PR_Open(path.get(), flags, mode);
+ if (! *_retval)
+ return NS_ErrorAccordingToNSPR();
+
+ return NS_OK;
+}
+
+/* [noscript] FILE openANSIFileDesc (in string mode); */
+NS_IMETHODIMP nsLocalFile::OpenANSIFileDesc(const char *mode, FILE **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCAutoString path;
+ nsresult rv = GetPathInternal(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = fopen(path.get(), mode);
+ if (! *_retval)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+/* [noscript] PRLibraryStar load (); */
+NS_IMETHODIMP nsLocalFile::Load(PRLibrary **_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+
+ nsCAutoString path;
+ nsresult rv = GetPathInternal(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+
+ *_retval = PR_LoadLibrary(path.get());
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+#endif
+
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", path.get());
+
+ if (!*_retval)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+/* readonly attribute PRInt64 diskSpaceAvailable; */
+NS_IMETHODIMP nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(aDiskSpaceAvailable);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err;
+ FSCatalogInfo catalogInfo;
+ err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoVolume, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ FSVolumeInfo volumeInfo;
+ err = ::FSGetVolumeInfo(catalogInfo.volume, 0, nsnull, kFSVolInfoSizes,
+ &volumeInfo, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ *aDiskSpaceAvailable = volumeInfo.freeBytes;
+ return NS_OK;
+}
+
+/* void appendRelativePath (in AString relativeFilePath); */
+NS_IMETHODIMP nsLocalFile::AppendRelativePath(const nsAString& relativeFilePath)
+{
+ return AppendRelativeNativePath(NS_ConvertUTF16toUTF8(relativeFilePath));
+}
+
+/* [noscript] void appendRelativeNativePath (in ACString relativeFilePath); */
+NS_IMETHODIMP nsLocalFile::AppendRelativeNativePath(const nsACString& relativeFilePath)
+{
+ if (relativeFilePath.IsEmpty())
+ return NS_OK;
+ // No leading '/'
+ if (relativeFilePath.First() == '/')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // Parse the nodes and call Append() for each
+ nsACString::const_iterator nodeBegin, pathEnd;
+ relativeFilePath.BeginReading(nodeBegin);
+ relativeFilePath.EndReading(pathEnd);
+ nsACString::const_iterator nodeEnd(nodeBegin);
+
+ while (nodeEnd != pathEnd) {
+ FindCharInReadable(kPathSepChar, nodeEnd, pathEnd);
+ nsresult rv = AppendNative(Substring(nodeBegin, nodeEnd));
+ if (NS_FAILED(rv))
+ return rv;
+ if (nodeEnd != pathEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
+ ++nodeEnd;
+ nodeBegin = nodeEnd;
+ }
+ return NS_OK;
+}
+
+/* attribute ACString persistentDescriptor; */
+NS_IMETHODIMP nsLocalFile::GetPersistentDescriptor(nsACString& aPersistentDescriptor)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ AliasHandle aliasH;
+ OSErr err = ::FSNewAlias(nsnull, &fsRef, &aliasH);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
+ ::HLock((Handle) aliasH);
+ // Passing nsnull for dest makes NULL-term string
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
+ ::DisposeHandle((Handle) aliasH);
+ NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
+
+ aPersistentDescriptor = buf;
+ PR_Free(buf);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetPersistentDescriptor(const nsACString& aPersistentDescriptor)
+{
+ if (aPersistentDescriptor.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ // Support pathnames as user-supplied descriptors if they begin with '/'
+ // or '~'. These characters do not collide with the base64 set used for
+ // encoding alias records.
+ char first = aPersistentDescriptor.First();
+ if (first == '/' || first == '~')
+ return InitWithNativePath(aPersistentDescriptor);
+
+ nsresult rv = NS_OK;
+
+ PRUint32 dataSize = aPersistentDescriptor.Length();
+ char* decodedData = PL_Base64Decode(PromiseFlatCString(aPersistentDescriptor).get(), dataSize, nsnull);
+ if (!decodedData) {
+ NS_ERROR("SetPersistentDescriptor was given bad data");
+ return NS_ERROR_FAILURE;
+ }
+
+ // Cast to an alias record and resolve.
+ AliasRecord aliasHeader = *(AliasPtr)decodedData;
+ PRInt32 aliasSize = GetAliasSizeFromRecord(aliasHeader);
+ if (aliasSize > ((PRInt32)dataSize * 3) / 4) { // be paranoid about having too few data
+ PR_Free(decodedData);
+ return NS_ERROR_FAILURE;
+ }
+
+ // Move the now-decoded data into the Handle.
+ // The size of the decoded data is 3/4 the size of the encoded data. See plbase64.h
+ Handle newHandle = nsnull;
+ if (::PtrToHand(decodedData, &newHandle, aliasSize) != noErr)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ PR_Free(decodedData);
+ if (NS_FAILED(rv))
+ return rv;
+
+ Boolean changed;
+ FSRef resolvedFSRef;
+ OSErr err = ::FSResolveAlias(nsnull, (AliasHandle)newHandle, &resolvedFSRef, &changed);
+
+ rv = MacErrorMapper(err);
+ DisposeHandle(newHandle);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return InitWithFSRef(&resolvedFSRef);
+}
+
+/* void reveal (); */
+NS_IMETHODIMP nsLocalFile::Reveal()
+{
+ FSRef fsRefToReveal;
+ AppleEvent aeEvent = {0, nil};
+ AppleEvent aeReply = {0, nil};
+ StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
+ OSErr err;
+ ProcessSerialNumber process;
+
+ nsresult rv = GetFSRefInternal(fsRefToReveal);
+ if (NS_FAILED(rv))
+ return rv;
+
+ err = ::FindRunningAppBySignature ('MACS', process);
+ if (err == noErr) {
+ err = ::AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
+ if (err == noErr) {
+ // Create the FinderEvent
+ err = ::AECreateAppleEvent(kAEMiscStandards, kAEMakeObjectsVisible, &myAddressDesc,
+ kAutoGenerateReturnID, kAnyTransactionID, &aeEvent);
+ if (err == noErr) {
+ // Create the file list
+ err = ::AECreateList(nil, 0, false, &fileList);
+ if (err == noErr) {
+ FSSpec fsSpecToReveal;
+ err = ::FSRefMakeFSSpec(&fsRefToReveal, &fsSpecToReveal);
+ if (err == noErr) {
+ err = ::AEPutPtr(&fileList, 0, typeFSS, &fsSpecToReveal, sizeof(FSSpec));
+ if (err == noErr) {
+ err = ::AEPutParamDesc(&aeEvent, keyDirectObject, &fileList);
+ if (err == noErr) {
+ err = ::AESend(&aeEvent, &aeReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
+ if (err == noErr)
+ ::SetFrontProcess(&process);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+/* void launch (); */
+NS_IMETHODIMP nsLocalFile::Launch()
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err = ::LSOpenFSRef(&fsRef, NULL);
+ return MacErrorMapper(err);
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsILocalFileMac
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsILocalFileMac]
+
+/* void initWithCFURL (in CFURLRef aCFURL); */
+NS_IMETHODIMP nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
+{
+ NS_ENSURE_ARG(aCFURL);
+
+ SetBaseRef(aCFURL);
+ return NS_OK;
+}
+
+/* void initWithFSRef ([const] in FSRefPtr aFSRef); */
+NS_IMETHODIMP nsLocalFile::InitWithFSRef(const FSRef *aFSRef)
+{
+ NS_ENSURE_ARG(aFSRef);
+ nsresult rv = NS_ERROR_FAILURE;
+
+ CFURLRef newURLRef = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aFSRef);
+ if (newURLRef) {
+ SetBaseRef(newURLRef);
+ ::CFRelease(newURLRef);
+ rv = NS_OK;
+ }
+ return rv;
+}
+
+/* void initWithFSSpec ([const] in FSSpecPtr aFileSpec); */
+NS_IMETHODIMP nsLocalFile::InitWithFSSpec(const FSSpec *aFileSpec)
+{
+ NS_ENSURE_ARG(aFileSpec);
+
+ FSRef fsRef;
+ OSErr err = ::FSpMakeFSRef(aFileSpec, &fsRef);
+ if (err == noErr)
+ return InitWithFSRef(&fsRef);
+ else if (err == fnfErr) {
+ CInfoPBRec pBlock;
+ FSSpec parentDirSpec;
+
+ memset(&pBlock, 0, sizeof(CInfoPBRec));
+ parentDirSpec.name[0] = 0;
+ pBlock.dirInfo.ioVRefNum = aFileSpec->vRefNum;
+ pBlock.dirInfo.ioDrDirID = aFileSpec->parID;
+ pBlock.dirInfo.ioNamePtr = (StringPtr)parentDirSpec.name;
+ pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
+ err = ::PBGetCatInfoSync(&pBlock);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ parentDirSpec.vRefNum = aFileSpec->vRefNum;
+ parentDirSpec.parID = pBlock.dirInfo.ioDrParID;
+ err = ::FSpMakeFSRef(&parentDirSpec, &fsRef);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ HFSUniStr255 unicodeName;
+ err = ::HFSNameGetUnicodeName(aFileSpec->name, kTextEncodingUnknown, &unicodeName);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ nsresult rv = InitWithFSRef(&fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+ return Append(nsDependentString(unicodeName.unicode, unicodeName.length));
+ }
+ return MacErrorMapper(err);
+}
+
+/* void initToAppWithCreatorCode (in OSType aAppCreator); */
+NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator)
+{
+ FSRef fsRef;
+ OSErr err = ::LSFindApplicationForInfo(aAppCreator, nsnull, nsnull, &fsRef, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ return InitWithFSRef(&fsRef);
+}
+
+/* CFURLRef getCFURL (); */
+NS_IMETHODIMP nsLocalFile::GetCFURL(CFURLRef *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
+ if (whichURLRef)
+ ::CFRetain(whichURLRef);
+ *_retval = whichURLRef;
+ return whichURLRef ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/* FSRef getFSRef (); */
+NS_IMETHODIMP nsLocalFile::GetFSRef(FSRef *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ return GetFSRefInternal(*_retval);
+}
+
+/* FSSpec getFSSpec (); */
+NS_IMETHODIMP nsLocalFile::GetFSSpec(FSSpec *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ OSErr err;
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_SUCCEEDED(rv)) {
+ // If the leaf node exists, things are simple.
+ err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNone,
+ nsnull, nsnull, _retval, nsnull);
+ return MacErrorMapper(err);
+ }
+ else if (rv == NS_ERROR_FILE_NOT_FOUND) {
+ // If the parent of the leaf exists, make an FSSpec from that.
+ CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
+ if (!parentURLRef)
+ return NS_ERROR_FAILURE;
+
+ err = fnfErr;
+ if (::CFURLGetFSRef(parentURLRef, &fsRef)) {
+ FSCatalogInfo catalogInfo;
+ if ((err = ::FSGetCatalogInfo(&fsRef,
+ kFSCatInfoVolume + kFSCatInfoNodeID + kFSCatInfoTextEncoding,
+ &catalogInfo, nsnull, nsnull, nsnull)) == noErr) {
+ nsAutoString leafName;
+ if (NS_SUCCEEDED(GetLeafName(leafName))) {
+ Str31 hfsName;
+ if ((err = ::UnicodeNameGetHFSName(leafName.Length(),
+ leafName.get(),
+ catalogInfo.textEncodingHint,
+ catalogInfo.nodeID == fsRtDirID,
+ hfsName)) == noErr)
+ err = ::FSMakeFSSpec(catalogInfo.volume, catalogInfo.nodeID, hfsName, _retval);
+ }
+ }
+ }
+ ::CFRelease(parentURLRef);
+ rv = MacErrorMapper(err);
+ }
+ return rv;
+}
+
+/* readonly attribute PRInt64 fileSizeWithResFork; */
+NS_IMETHODIMP nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSizeWithResFork)
+{
+ NS_ENSURE_ARG_POINTER(aFileSizeWithResFork);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoDataSizes + kFSCatInfoRsrcSizes,
+ &catalogInfo, nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ *aFileSizeWithResFork = catalogInfo.dataLogicalSize + catalogInfo.rsrcLogicalSize;
+ return NS_OK;
+}
+
+/* attribute OSType fileType; */
+NS_IMETHODIMP nsLocalFile::GetFileType(OSType *aFileType)
+{
+ NS_ENSURE_ARG_POINTER(aFileType);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FinderInfo fInfo;
+ OSErr err = ::FSGetFinderInfo(&fsRef, &fInfo, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *aFileType = fInfo.file.fileType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileType(OSType aFileType)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err = ::FSChangeCreatorType(&fsRef, 0, aFileType);
+ return MacErrorMapper(err);
+}
+
+/* attribute OSType fileCreator; */
+NS_IMETHODIMP nsLocalFile::GetFileCreator(OSType *aFileCreator)
+{
+ NS_ENSURE_ARG_POINTER(aFileCreator);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FinderInfo fInfo;
+ OSErr err = ::FSGetFinderInfo(&fsRef, &fInfo, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *aFileCreator = fInfo.file.fileCreator;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileCreator(OSType aFileCreator)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err = ::FSChangeCreatorType(&fsRef, aFileCreator, 0);
+ return MacErrorMapper(err);
+}
+
+/* void setFileTypeAndCreatorFromMIMEType (in string aMIMEType); */
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromMIMEType(const char *aMIMEType)
+{
+ // XXX - This should be cut from the API. Would create an evil dependency.
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void setFileTypeAndCreatorFromExtension (in string aExtension); */
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromExtension(const char *aExtension)
+{
+ // XXX - This should be cut from the API. Would create an evil dependency.
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void launchWithDoc (in nsILocalFile aDocToLoad, in boolean aLaunchInBackground); */
+NS_IMETHODIMP nsLocalFile::LaunchWithDoc(nsILocalFile *aDocToLoad, PRBool aLaunchInBackground)
+{
+ PRBool isExecutable;
+ nsresult rv = IsExecutable(&isExecutable);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isExecutable)
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+
+ FSRef appFSRef, docFSRef;
+ rv = GetFSRefInternal(appFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (aDocToLoad) {
+ nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
+ rv = macDoc->GetFSRef(&docFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+ LSLaunchFSRefSpec thelaunchSpec;
+
+ if (aLaunchInBackground)
+ theLaunchFlags |= kLSLaunchDontSwitch;
+ memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+ thelaunchSpec.appRef = &appFSRef;
+ if (aDocToLoad) {
+ thelaunchSpec.numDocs = 1;
+ thelaunchSpec.itemRefs = &docFSRef;
+ }
+ thelaunchSpec.launchFlags = theLaunchFlags;
+
+ OSErr err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+}
+
+/* void openDocWithApp (in nsILocalFile aAppToOpenWith, in boolean aLaunchInBackground); */
+NS_IMETHODIMP nsLocalFile::OpenDocWithApp(nsILocalFile *aAppToOpenWith, PRBool aLaunchInBackground)
+{
+ nsresult rv;
+ OSErr err;
+
+ FSRef docFSRef, appFSRef;
+ rv = GetFSRefInternal(docFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (aAppToOpenWith) {
+ nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
+ if (!appFileMac)
+ return rv;
+
+ PRBool isExecutable;
+ rv = appFileMac->IsExecutable(&isExecutable);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isExecutable)
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+
+ rv = appFileMac->GetFSRef(&appFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else {
+ OSType fileCreator;
+ rv = GetFileCreator(&fileCreator);
+ if (NS_FAILED(rv))
+ return rv;
+
+ err = ::LSFindApplicationForInfo(fileCreator, nsnull, nsnull, &appFSRef, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ }
+
+ LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+ LSLaunchFSRefSpec thelaunchSpec;
+
+ if (aLaunchInBackground)
+ theLaunchFlags |= kLSLaunchDontSwitch;
+ memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+ thelaunchSpec.appRef = &appFSRef;
+ thelaunchSpec.numDocs = 1;
+ thelaunchSpec.itemRefs = &docFSRef;
+ thelaunchSpec.launchFlags = theLaunchFlags;
+
+ err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+}
+
+/* boolean isPackage (); */
+NS_IMETHODIMP nsLocalFile::IsPackage(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo,
+ &catalogInfo, nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ if ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
+ FileInfo *fInfoPtr = (FileInfo *)(catalogInfo.finderInfo);
+ if ((fInfoPtr->finderFlags & kHasBundle) != 0) {
+ *_retval = PR_TRUE;
+ }
+ else {
+ // Folders ending with ".app" are also considered to
+ // be packages, even if the top-level folder doesn't have bundle set
+ nsCAutoString name;
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(name))) {
+ const char *extPtr = strrchr(name.get(), '.');
+ if (extPtr) {
+ if ((nsCRT::strcasecmp(extPtr, ".app") == 0))
+ *_retval = PR_TRUE;
+ }
+ }
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetBundleDisplayName(nsAString& outBundleName)
+{
+ PRBool isPackage = PR_FALSE;
+ nsresult rv = IsPackage(&isPackage);
+ if (NS_FAILED(rv) || !isPackage)
+ return NS_ERROR_FAILURE;
+
+ nsAutoString name;
+ rv = GetLeafName(name);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt32 length = name.Length();
+ if (Substring(name, length - 4, length).EqualsLiteral(".app")) {
+ // 4 characters in ".app"
+ outBundleName = Substring(name, 0, length - 4);
+ }
+ else
+ outBundleName = name;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetBundleIdentifier(nsACString& outBundleIdentifier)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ CFURLRef urlRef;
+ if (NS_SUCCEEDED(GetCFURL(&urlRef))) {
+ CFBundleRef bundle = ::CFBundleCreate(NULL, urlRef);
+ if (bundle) {
+ CFStringRef bundleIdentifier = ::CFBundleGetIdentifier(bundle);
+ if (bundleIdentifier)
+ rv = CFStringReftoUTF8(bundleIdentifier, outBundleIdentifier);
+
+ ::CFRelease(bundle);
+ }
+ ::CFRelease(urlRef);
+ }
+
+ return rv;
+}
+
+
+//*****************************************************************************
+// nsLocalFile Methods
+//*****************************************************************************
+#pragma mark -
+#pragma mark [Protected Methods]
+
+nsresult nsLocalFile::SetBaseRef(CFURLRef aCFURLRef)
+{
+ NS_ENSURE_ARG(aCFURLRef);
+
+ ::CFRetain(aCFURLRef);
+ if (mBaseRef)
+ ::CFRelease(mBaseRef);
+ mBaseRef = aCFURLRef;
+
+ mFollowLinksDirty = PR_TRUE;
+ UpdateTargetRef();
+ mCachedFSRefValid = PR_FALSE;
+ return NS_OK;
+}
+
+nsresult nsLocalFile::UpdateTargetRef()
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ if (mFollowLinksDirty) {
+ if (mTargetRef) {
+ ::CFRelease(mTargetRef);
+ mTargetRef = nsnull;
+ }
+ if (mFollowLinks) {
+ mTargetRef = mBaseRef;
+ ::CFRetain(mTargetRef);
+
+ FSRef fsRef;
+ if (::CFURLGetFSRef(mBaseRef, &fsRef)) {
+ Boolean targetIsFolder, wasAliased;
+ if (FSResolveAliasFile(&fsRef, true /*resolveAliasChains*/,
+ &targetIsFolder, &wasAliased) == noErr && wasAliased) {
+ ::CFRelease(mTargetRef);
+ mTargetRef = CFURLCreateFromFSRef(NULL, &fsRef);
+ if (!mTargetRef)
+ return NS_ERROR_FAILURE;
+ }
+ }
+ mFollowLinksDirty = PR_FALSE;
+ }
+ }
+ return NS_OK;
+}
+
+nsresult nsLocalFile::GetFSRefInternal(FSRef& aFSRef, PRBool bForceUpdateCache)
+{
+ if (bForceUpdateCache || !mCachedFSRefValid) {
+ mCachedFSRefValid = PR_FALSE;
+ CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
+ NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
+ if (::CFURLGetFSRef(whichURLRef, &mCachedFSRef))
+ mCachedFSRefValid = PR_TRUE;
+ }
+ if (mCachedFSRefValid) {
+ aFSRef = mCachedFSRef;
+ return NS_OK;
+ }
+ // CFURLGetFSRef only returns a Boolean for success,
+ // so we have to assume what the error was. This is
+ // the only probable cause.
+ return NS_ERROR_FILE_NOT_FOUND;
+}
+
+nsresult nsLocalFile::GetPathInternal(nsACString& path)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
+ NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
+
+ CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(whichURLRef, kCFURLPOSIXPathStyle);
+ if (pathStrRef) {
+ rv = CFStringReftoUTF8(pathStrRef, path);
+ ::CFRelease(pathStrRef);
+ }
+ return rv;
+}
+
+nsresult nsLocalFile::CopyInternal(nsIFile* aParentDir,
+ const nsAString& newName,
+ PRBool followLinks)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ StFollowLinksState srcFollowState(*this, followLinks);
+
+ nsresult rv;
+ OSErr err;
+ FSRef srcFSRef, newFSRef;
+
+ rv = GetFSRefInternal(srcFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIFile> newParentDir = aParentDir;
+
+ if (!newParentDir) {
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+ rv = GetParent(getter_AddRefs(newParentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // If newParentDir does not exist, create it
+ PRBool exists;
+ rv = newParentDir->Exists(&exists);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!exists) {
+ rv = newParentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ FSRef destFSRef;
+ nsCOMPtr<nsILocalFileMac> newParentDirMac(do_QueryInterface(newParentDir));
+ if (!newParentDirMac)
+ return NS_ERROR_NO_INTERFACE;
+ rv = newParentDirMac->GetFSRef(&destFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ err =
+ ::FSCopyObject(&srcFSRef, &destFSRef, newName.Length(),
+ newName.Length() ? PromiseFlatString(newName).get() : NULL,
+ 0, kFSCatInfoNone, false, false, NULL, NULL, &newFSRef);
+
+ return MacErrorMapper(err);
+}
+
+const PRInt64 kMillisecsPerSec = 1000LL;
+const PRInt64 kUTCDateTimeFractionDivisor = 65535LL;
+
+PRInt64 nsLocalFile::HFSPlustoNSPRTime(const UTCDateTime& utcTime)
+{
+ // Start with seconds since Jan. 1, 1904 GMT
+ PRInt64 result = ((PRInt64)utcTime.highSeconds << 32) + (PRInt64)utcTime.lowSeconds;
+ // Subtract to convert to NSPR epoch of 1970
+ result -= kJanuaryFirst1970Seconds;
+ // Convert to millisecs
+ result *= kMillisecsPerSec;
+ // Convert the fraction to millisecs and add it
+ result += ((PRInt64)utcTime.fraction * kMillisecsPerSec) / kUTCDateTimeFractionDivisor;
+
+ return result;
+}
+
+void nsLocalFile::NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime)
+{
+ PRInt64 fraction = nsprTime % kMillisecsPerSec;
+ PRInt64 seconds = (nsprTime / kMillisecsPerSec) + kJanuaryFirst1970Seconds;
+ utcTime.highSeconds = (UInt16)((PRUint64)seconds >> 32);
+ utcTime.lowSeconds = (UInt32)seconds;
+ utcTime.fraction = (UInt16)((fraction * kUTCDateTimeFractionDivisor) / kMillisecsPerSec);
+}
+
+nsresult nsLocalFile::CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef);
+ CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+ kCFStringEncodingUTF8, 0, PR_FALSE, nsnull, 0, &usedBufLen);
+ if (charsConverted == inStrLen) {
+#if 0 /* bird: too new? */
+ aOutStr.SetLength(usedBufLen);
+ if (aOutStr.Length() != (unsigned int)usedBufLen)
+ return NS_ERROR_OUT_OF_MEMORY;
+ UInt8 *buffer = (UInt8*) aOutStr.BeginWriting();
+
+ ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+ kCFStringEncodingUTF8, 0, false, buffer, usedBufLen, &usedBufLen);
+ rv = NS_OK;
+#else
+ nsAutoBuffer<UInt8, FILENAME_BUFFER_SIZE> buffer;
+ if (buffer.EnsureElemCapacity(usedBufLen + 1)) {
+ ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+ kCFStringEncodingUTF8, 0, false, buffer.get(), usedBufLen, &usedBufLen);
+ buffer.get()[usedBufLen] = '\0';
+ aOutStr.Assign(nsDependentCString((char*)buffer.get()));
+ rv = NS_OK;
+ }
+#endif
+ }
+ return rv;
+}
+
+// nsIHashable
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIHashable* aOther, PRBool *aResult)
+{
+ return EqualsInternal(aOther, PR_FALSE, aResult);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetHashCode(PRUint32 *aResult)
+{
+ CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseRef, kCFURLPOSIXPathStyle);
+ nsCAutoString path;
+ CFStringReftoUTF8(pathStrRef, path);
+ ::CFRelease(pathStrRef);
+ *aResult = HashString(path);
+ return NS_OK;
+}
+
+//*****************************************************************************
+// Global Functions
+//*****************************************************************************
+#pragma mark -
+#pragma mark [Global Functions]
+
+void nsLocalFile::GlobalInit()
+{
+}
+
+void nsLocalFile::GlobalShutdown()
+{
+}
+
+nsresult NS_NewLocalFile(const nsAString& path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile;
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithPath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+ *result = file;
+ return NS_OK;
+}
+
+nsresult NS_NewNativeLocalFile(const nsACString& path, PRBool followLinks, nsILocalFile **result)
+{
+ return NS_NewLocalFile(NS_ConvertUTF8toUTF16(path), followLinks, result);
+}
+
+nsresult NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followLinks, nsILocalFileMac **result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ nsresult rv = file->InitWithFSSpec(inSpec);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ *result = file;
+ return NS_OK;
+}
+
+nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowLinks, nsILocalFileMac** result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(aFollowLinks);
+
+ nsresult rv = file->InitWithFSRef(aFSRef);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ *result = file;
+ return NS_OK;
+}
+
+//*****************************************************************************
+// Static Functions
+//*****************************************************************************
+
+static nsresult MacErrorMapper(OSErr inErr)
+{
+ nsresult outErr;
+
+ switch (inErr)
+ {
+ case noErr:
+ outErr = NS_OK;
+ break;
+
+ case fnfErr:
+ case afpObjectNotFound:
+ case afpDirNotFound:
+ outErr = NS_ERROR_FILE_NOT_FOUND;
+ break;
+
+ case dupFNErr:
+ case afpObjectExists:
+ outErr = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+
+ case dskFulErr:
+ case afpDiskFull:
+ outErr = NS_ERROR_FILE_DISK_FULL;
+ break;
+
+ case fLckdErr:
+ case afpVolLocked:
+ outErr = NS_ERROR_FILE_IS_LOCKED;
+ break;
+
+ case afpAccessDenied:
+ outErr = NS_ERROR_FILE_ACCESS_DENIED;
+ break;
+
+ case afpDirNotEmpty:
+ outErr = NS_ERROR_FILE_DIR_NOT_EMPTY;
+ break;
+
+ // Can't find good map for some
+ case bdNamErr:
+ outErr = NS_ERROR_FAILURE;
+ break;
+
+ default:
+ outErr = NS_ERROR_FAILURE;
+ break;
+ }
+ return outErr;
+}
+
+static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn)
+{
+ ProcessInfoRec info;
+ OSErr err = noErr;
+
+ outPsn.highLongOfPSN = 0;
+ outPsn.lowLongOfPSN = kNoProcess;
+
+ while (PR_TRUE)
+ {
+ err = ::GetNextProcess(&outPsn);
+ if (err == procNotFound)
+ break;
+ if (err != noErr)
+ return err;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = nil;
+ err = ::GetProcessInformation(&outPsn, &info);
+ if (err != noErr)
+ return err;
+
+ if (info.processSignature == aAppSig)
+ return noErr;
+ }
+ return procNotFound;
+}
+
+// Convert a UTF-8 string to a UTF-16 string while normalizing to
+// Normalization Form C (composed Unicode). We need this because
+// Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode)
+// while most other OS', server-side programs usually expect NFC.
+
+typedef void (*UnicodeNormalizer) (CFMutableStringRef, CFStringNormalizationForm);
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult)
+{
+ static PRBool sChecked = PR_FALSE;
+ static UnicodeNormalizer sUnicodeNormalizer = NULL;
+
+ // CFStringNormalize was not introduced until Mac OS 10.2
+ if (!sChecked) {
+ CFBundleRef carbonBundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon"));
+ if (carbonBundle)
+ sUnicodeNormalizer = (UnicodeNormalizer)
+ ::CFBundleGetFunctionPointerForName(carbonBundle,
+ CFSTR("CFStringNormalize"));
+ sChecked = PR_TRUE;
+ }
+
+ if (!sUnicodeNormalizer) { // OS X 10.2 or earlier
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc);
+
+ // The number of 16bit code units in a UTF-16 string will never be
+ // larger than the number of bytes in the corresponding UTF-8 string.
+ CFMutableStringRef inStr =
+ ::CFStringCreateMutable(NULL, inFlatSrc.Length());
+
+ if (!inStr) {
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8);
+
+ sUnicodeNormalizer(inStr, kCFStringNormalizationFormC);
+
+ CFIndex length = CFStringGetLength(inStr);
+ const UniChar* chars = CFStringGetCharactersPtr(inStr);
+
+ if (chars)
+ aResult.Assign(chars, length);
+ else {
+ nsAutoBuffer<UniChar, FILENAME_BUFFER_SIZE> buffer;
+ if (!buffer.EnsureElemCapacity(length))
+ CopyUTF8toUTF16(aSrc, aResult);
+ else {
+ CFStringGetCharacters(inStr, CFRangeMake(0, length), buffer.get());
+ aResult.Assign(buffer.get(), length);
+ }
+ }
+ CFRelease(inStr);
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h
new file mode 100644
index 00000000..b6d74521
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.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 ***** */
+
+#ifndef nsLocalFileMac_h__
+#define nsLocalFileMac_h__
+
+#include "nsILocalFileMac.h"
+#include "nsString.h"
+#include "nsIHashable.h"
+
+class nsDirEnumerator;
+
+//*****************************************************************************
+// nsLocalFile
+//
+// The native charset of this implementation is UTF-8. The Unicode used by the
+// Mac OS file system is decomposed, so "Native" versions of these routines will
+// always use decomposed Unicode (NFD). Their "non-Native" counterparts are
+// intended to be simple wrappers which call the "Native" version and convert
+// between UTF-8 and UTF-16. All the work is done on the "Native" side except
+// for the conversion to NFC (composed Unicode) done in "non-Native" getters.
+//*****************************************************************************
+
+class NS_COM nsLocalFile : public nsILocalFileMac,
+ public nsIHashable
+{
+ friend class nsDirEnumerator;
+
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFILE
+ NS_DECL_NSILOCALFILE
+ NS_DECL_NSILOCALFILEMAC
+ NS_DECL_NSIHASHABLE
+
+public:
+
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ ~nsLocalFile();
+
+protected:
+ nsLocalFile(const nsLocalFile& src);
+
+ nsresult SetBaseRef(CFURLRef aCFURLRef); // Does CFRetain on aCFURLRef
+ nsresult UpdateTargetRef();
+
+ nsresult GetFSRefInternal(FSRef& aFSSpec, PRBool bForceUpdateCache = PR_TRUE);
+ nsresult GetPathInternal(nsACString& path); // Returns path WRT mFollowLinks
+ nsresult EqualsInternal(nsISupports* inFile,
+ PRBool aUpdateCache, PRBool *_retval);
+
+ nsresult CopyInternal(nsIFile* newParentDir,
+ const nsAString& newName,
+ PRBool followLinks);
+
+ static PRInt64 HFSPlustoNSPRTime(const UTCDateTime& utcTime);
+ static void NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime);
+ static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr);
+
+protected:
+ CFURLRef mBaseRef; // The FS object we represent
+ CFURLRef mTargetRef; // If mBaseRef is an alias, its target
+
+ FSRef mCachedFSRef;
+ PRPackedBool mCachedFSRefValid;
+
+ PRPackedBool mFollowLinks;
+ PRPackedBool mFollowLinksDirty;
+
+ static const char kPathSepChar;
+ static const PRUnichar kPathSepUnichar;
+ static const PRInt64 kJanuaryFirst1970Seconds;
+};
+
+#endif // nsLocalFileMac_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h
new file mode 100644
index 00000000..90bc9c07
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _NS_LOCALFILEUNICODE_H_
+
+extern void NS_ShutdownLocalFileUnicode();
+
+extern "C" NS_EXPORT nsresult
+NS_NewUnicodeLocalFile(const PRUnichar *, PRBool, nsILocalFile **);
+
+#endif // _NS_LOCALFILEUNICODE_H_
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp
new file mode 100644
index 00000000..eef17bde
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp
@@ -0,0 +1,1724 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike Shaver <shaver@mozilla.org>
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Jason Eager <jce2@po.cwru.edu>
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Brendan Eich <brendan@mozilla.org>
+ * Pete Collins <petejc@mozdev.org>
+ * Paul Ashford <arougthopher@lizardland.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Implementation of nsIFile for ``Unixy'' systems.
+ */
+
+// We're going to need some autoconf loving, I can just tell.
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <utime.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <locale.h>
+#ifdef XP_BEOS
+ #include <Path.h>
+ #include <Entry.h>
+ #include <Roster.h>
+#endif
+#if defined(VMS)
+ #include <fabdef.h>
+#endif
+
+#include "nsDirectoryServiceDefs.h"
+#include "nsCRT.h"
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsIFile.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsLocalFile.h"
+#include "nsIComponentManager.h"
+#include "nsXPIDLString.h"
+#include "prproces.h"
+#include "nsISimpleEnumerator.h"
+#include "nsITimelineService.h"
+
+#include "nsNativeCharsetUtils.h"
+
+// On some platforms file/directory name comparisons need to
+// be case-blind.
+#if defined(VMS)
+ #define FILE_STRCMP strcasecmp
+ #define FILE_STRNCMP strncasecmp
+#else
+ #define FILE_STRCMP strcmp
+ #define FILE_STRNCMP strncmp
+#endif
+
+#define VALIDATE_STAT_CACHE() \
+ PR_BEGIN_MACRO \
+ if (!mHaveCachedStat) { \
+ FillStatCache(); \
+ if (!mHaveCachedStat) \
+ return NSRESULT_FOR_ERRNO(); \
+ } \
+ PR_END_MACRO
+
+#define CHECK_mPath() \
+ PR_BEGIN_MACRO \
+ if (mPath.IsEmpty()) \
+ return NS_ERROR_NOT_INITIALIZED; \
+ PR_END_MACRO
+
+/* directory enumerator */
+class NS_COM
+nsDirEnumeratorUnix : public nsISimpleEnumerator
+{
+ public:
+ nsDirEnumeratorUnix();
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ NS_IMETHOD Init(nsLocalFile *parent, PRBool ignored);
+
+ private:
+ ~nsDirEnumeratorUnix();
+
+ protected:
+ NS_IMETHOD GetNextEntry();
+
+ DIR *mDir;
+ struct dirent *mEntry;
+ nsCString mParentPath;
+};
+
+nsDirEnumeratorUnix::nsDirEnumeratorUnix() :
+ mDir(nsnull),
+ mEntry(nsnull)
+{
+}
+
+nsDirEnumeratorUnix::~nsDirEnumeratorUnix()
+{
+ if (mDir)
+ closedir(mDir);
+}
+
+NS_IMPL_ISUPPORTS1(nsDirEnumeratorUnix, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::Init(nsLocalFile *parent, PRBool resolveSymlinks /*ignored*/)
+{
+ nsCAutoString dirPath;
+ if (NS_FAILED(parent->GetNativePath(dirPath)) ||
+ dirPath.IsEmpty()) {
+ return NS_ERROR_FILE_INVALID_PATH;
+ }
+
+ if (NS_FAILED(parent->GetNativePath(mParentPath)))
+ return NS_ERROR_FAILURE;
+
+ mDir = opendir(dirPath.get());
+ if (!mDir)
+ return NSRESULT_FOR_ERRNO();
+ return GetNextEntry();
+}
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::HasMoreElements(PRBool *result)
+{
+ *result = mDir && mEntry;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::GetNext(nsISupports **_retval)
+{
+ nsresult rv;
+ if (!mDir || !mEntry) {
+ *_retval = nsnull;
+ return NS_OK;
+ }
+
+ nsLocalFile* file = new nsLocalFile();
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (NS_FAILED(rv = file->InitWithNativePath(mParentPath)) ||
+ NS_FAILED(rv = file->AppendNative(nsDependentCString(mEntry->d_name)))) {
+ return rv;
+ }
+ *_retval = NS_STATIC_CAST(nsISupports *, file);
+ NS_ADDREF(*_retval);
+ return GetNextEntry();
+}
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::GetNextEntry()
+{
+ do {
+ errno = 0;
+ mEntry = readdir(mDir);
+
+ // end of dir or error
+ if (!mEntry)
+ return NSRESULT_FOR_ERRNO();
+
+ // keep going past "." and ".."
+ } while (mEntry->d_name[0] == '.' &&
+ (mEntry->d_name[1] == '\0' || // .\0
+ (mEntry->d_name[1] == '.' &&
+ mEntry->d_name[2] == '\0'))); // ..\0
+ return NS_OK;
+}
+
+nsLocalFile::nsLocalFile() :
+ mHaveCachedStat(PR_FALSE)
+{
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& other)
+ : mCachedStat(other.mCachedStat)
+ , mPath(other.mPath)
+ , mHaveCachedStat(other.mHaveCachedStat)
+{
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile,
+ nsIFile,
+ nsILocalFile)
+
+nsresult
+nsLocalFile::nsLocalFileConstructor(nsISupports *outer,
+ const nsIID &aIID,
+ void **aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ *aInstancePtr = nsnull;
+
+ nsCOMPtr<nsIFile> inst = new nsLocalFile();
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return inst->QueryInterface(aIID, aInstancePtr);
+}
+
+nsresult
+nsLocalFile::FillStatCache() {
+ if (stat(mPath.get(), &mCachedStat) == -1) {
+ // try lstat it may be a symlink
+ if (lstat(mPath.get(), &mCachedStat) == -1) {
+ return NSRESULT_FOR_ERRNO();
+ }
+ }
+ mHaveCachedStat = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ if (Substring(filePath, 0, 2).EqualsLiteral("~/")) {
+ nsCOMPtr<nsIFile> homeDir;
+ nsCAutoString homePath;
+ if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_HOME_DIR,
+ getter_AddRefs(homeDir))) ||
+ NS_FAILED(homeDir->GetNativePath(homePath))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mPath = homePath + Substring(filePath, 1, filePath.Length() - 1);
+ } else if (filePath.IsEmpty() || filePath.First() != '/') {
+ NS_ERROR("Relative paths not allowed");
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ } else {
+ mPath = filePath;
+ }
+
+ // trim off trailing slashes
+ ssize_t len = mPath.Length();
+ while ((len > 1) && (mPath[len - 1] == '/'))
+ --len;
+ mPath.SetLength(len);
+
+ InvalidateCache();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CreateAllAncestors(PRUint32 permissions)
+{
+ // <jband> I promise to play nice
+ char *buffer = mPath.BeginWriting(),
+ *slashp = buffer;
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: before: %s\n", buffer);
+#endif
+
+ while ((slashp = strchr(slashp + 1, '/'))) {
+ /*
+ * Sequences of '/' are equivalent to a single '/'.
+ */
+ if (slashp[1] == '/')
+ continue;
+
+ /*
+ * If the path has a trailing slash, don't make the last component,
+ * because we'll get EEXIST in Create when we try to build the final
+ * component again, and it's easier to condition the logic here than
+ * there.
+ */
+ if (slashp[1] == '\0')
+ break;
+
+ /* Temporarily NUL-terminate here */
+ *slashp = '\0';
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: mkdir(\"%s\")\n", buffer);
+#endif
+ int mkdir_result = mkdir(buffer, permissions);
+ int mkdir_errno = errno;
+ if (mkdir_result == -1) {
+ /*
+ * Always set |errno| to EEXIST if the dir already exists
+ * (we have to do this here since the errno value is not consistent
+ * in all cases - various reasons like different platform,
+ * automounter-controlled dir, etc. can affect it (see bug 125489
+ * for details)).
+ */
+ if (access(buffer, F_OK) == 0) {
+ mkdir_errno = EEXIST;
+ }
+ }
+
+ /* Put the / back before we (maybe) return */
+ *slashp = '/';
+
+ /*
+ * We could get EEXIST for an existing file -- not directory --
+ * with the name of one of our ancestors, but that's OK: we'll get
+ * ENOTDIR when we try to make the next component in the path,
+ * either here on back in Create, and error out appropriately.
+ */
+ if (mkdir_result == -1 && mkdir_errno != EEXIST)
+ return nsresultForErrno(mkdir_errno);
+ }
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: after: %s\n", buffer);
+#endif
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ *_retval = PR_Open(mPath.get(), flags, mode);
+ if (! *_retval)
+ return NS_ErrorAccordingToNSPR();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE **_retval)
+{
+ *_retval = fopen(mPath.get(), mode);
+ if (! *_retval)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+static int
+do_create(const char *path, PRIntn flags, mode_t mode, PRFileDesc **_retval)
+{
+ *_retval = PR_Open(path, flags, mode);
+ return *_retval ? 0 : -1;
+}
+
+static int
+do_mkdir(const char *path, PRIntn flags, mode_t mode, PRFileDesc **_retval)
+{
+ *_retval = nsnull;
+ return mkdir(path, mode);
+}
+
+nsresult
+nsLocalFile::CreateAndKeepOpen(PRUint32 type, PRIntn flags,
+ PRUint32 permissions, PRFileDesc **_retval)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ int result;
+ int (*createFunc)(const char *, PRIntn, mode_t, PRFileDesc **) =
+ (type == NORMAL_FILE_TYPE) ? do_create : do_mkdir;
+
+ result = createFunc(mPath.get(), flags, permissions, _retval);
+ if (result == -1 && errno == ENOENT) {
+ /*
+ * If we failed because of missing ancestor components, try to create
+ * them and then retry the original creation.
+ *
+ * Ancestor directories get the same permissions as the file we're
+ * creating, with the X bit set for each of (user,group,other) with
+ * an R bit in the original permissions. If you want to do anything
+ * fancy like setgid or sticky bits, do it by hand.
+ */
+ int dirperm = permissions;
+ if (permissions & S_IRUSR)
+ dirperm |= S_IXUSR;
+ if (permissions & S_IRGRP)
+ dirperm |= S_IXGRP;
+ if (permissions & S_IROTH)
+ dirperm |= S_IXOTH;
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: perm = %o, dirperm = %o\n", permissions,
+ dirperm);
+#endif
+
+ if (NS_FAILED(CreateAllAncestors(dirperm)))
+ return NS_ERROR_FAILURE;
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: Create(\"%s\") again\n", mPath.get());
+#endif
+ result = createFunc(mPath.get(), flags, permissions, _retval);
+ }
+
+ return NSRESULT_FOR_RETURN(result);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 permissions)
+{
+ PRFileDesc *junk = nsnull;
+ nsresult rv = CreateAndKeepOpen(type,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE |
+ PR_EXCL,
+ permissions,
+ &junk);
+ if (junk)
+ PR_Close(junk);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &fragment)
+{
+ if (fragment.IsEmpty())
+ return NS_OK;
+
+ // only one component of path can be appended
+ nsACString::const_iterator begin, end;
+ if (FindCharInReadable('/', fragment.BeginReading(begin),
+ fragment.EndReading(end)))
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ return AppendRelativeNativePath(fragment);
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &fragment)
+{
+ if (fragment.IsEmpty())
+ return NS_OK;
+
+ // No leading '/'
+ if (fragment.First() == '/')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ if (mPath.EqualsLiteral("/"))
+ mPath.Append(fragment);
+ else
+ mPath.Append(NS_LITERAL_CSTRING("/") + fragment);
+
+ InvalidateCache();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ char resolved_path[PATH_MAX] = "";
+ char *resolved_path_ptr = nsnull;
+
+#ifdef XP_BEOS
+ BEntry be_e(mPath.get(), true);
+ BPath be_p;
+ status_t err;
+ if ((err = be_e.GetPath(&be_p)) == B_OK) {
+ resolved_path_ptr = (char *)be_p.Path();
+ PL_strncpyz(resolved_path, resolved_path_ptr, PATH_MAX - 1);
+ }
+#else
+ resolved_path_ptr = realpath(mPath.get(), resolved_path);
+#endif
+ // if there is an error, the return is null.
+ if (!resolved_path_ptr)
+ return NSRESULT_FOR_ERRNO();
+
+ mPath = resolved_path;
+ return NS_OK;
+}
+
+void
+nsLocalFile::LocateNativeLeafName(nsACString::const_iterator &begin,
+ nsACString::const_iterator &end)
+{
+ // XXX perhaps we should cache this??
+
+ mPath.BeginReading(begin);
+ mPath.EndReading(end);
+
+ nsACString::const_iterator it = end;
+ nsACString::const_iterator stop = begin;
+ --stop;
+ while (--it != stop) {
+ if (*it == '/') {
+ begin = ++it;
+ return;
+ }
+ }
+ // else, the entire path is the leaf name (which means this
+ // isn't an absolute path... unexpected??)
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ nsACString::const_iterator begin, end;
+ LocateNativeLeafName(begin, end);
+ aLeafName = Substring(begin, end);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ nsACString::const_iterator begin, end;
+ LocateNativeLeafName(begin, end);
+ mPath.Replace(begin.get() - mPath.get(), Distance(begin, end), aLeafName);
+ InvalidateCache();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval = mPath;
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::GetNativeTargetPathName(nsIFile *newParent,
+ const nsACString &newName,
+ nsACString &_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> oldParent;
+
+ if (!newParent) {
+ if (NS_FAILED(rv = GetParent(getter_AddRefs(oldParent))))
+ return rv;
+ newParent = oldParent.get();
+ } else {
+ // check to see if our target directory exists
+ PRBool targetExists;
+ if (NS_FAILED(rv = newParent->Exists(&targetExists)))
+ return rv;
+
+ if (!targetExists) {
+ // XXX create the new directory with some permissions
+ rv = newParent->Create(DIRECTORY_TYPE, 0700);
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ // make sure that the target is actually a directory
+ PRBool targetIsDirectory;
+ if (NS_FAILED(rv = newParent->IsDirectory(&targetIsDirectory)))
+ return rv;
+ if (!targetIsDirectory)
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+ }
+ }
+
+ nsACString::const_iterator nameBegin, nameEnd;
+ if (!newName.IsEmpty()) {
+ newName.BeginReading(nameBegin);
+ newName.EndReading(nameEnd);
+ }
+ else
+ LocateNativeLeafName(nameBegin, nameEnd);
+
+ nsCAutoString dirName;
+ if (NS_FAILED(rv = newParent->GetNativePath(dirName)))
+ return rv;
+
+ _retval = dirName
+ + NS_LITERAL_CSTRING("/")
+ + Substring(nameBegin, nameEnd);
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::CopyDirectoryTo(nsIFile *newParent)
+{
+ nsresult rv;
+ /*
+ * dirCheck is used for various boolean test results such as from Equals,
+ * Exists, isDir, etc.
+ */
+ PRBool dirCheck, isSymlink;
+ PRUint32 oldPerms;
+
+ if (NS_FAILED((rv = IsDirectory(&dirCheck))))
+ return rv;
+ if (!dirCheck)
+ return CopyToNative(newParent, EmptyCString());
+
+ if (NS_FAILED(rv = Equals(newParent, &dirCheck)))
+ return rv;
+ if (dirCheck) {
+ // can't copy dir to itself
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (NS_FAILED(rv = newParent->Exists(&dirCheck)))
+ return rv;
+ // get the dirs old permissions
+ if (NS_FAILED(rv = GetPermissions(&oldPerms)))
+ return rv;
+ if (!dirCheck) {
+ if (NS_FAILED(rv = newParent->Create(DIRECTORY_TYPE, oldPerms)))
+ return rv;
+ } else { // dir exists lets try to use leaf
+ nsCAutoString leafName;
+ if (NS_FAILED(rv = GetNativeLeafName(leafName)))
+ return rv;
+ if (NS_FAILED(rv = newParent->AppendNative(leafName)))
+ return rv;
+ if (NS_FAILED(rv = newParent->Exists(&dirCheck)))
+ return rv;
+ if (dirCheck)
+ return NS_ERROR_FILE_ALREADY_EXISTS; // dest exists
+ if (NS_FAILED(rv = newParent->Create(DIRECTORY_TYPE, oldPerms)))
+ return rv;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> dirIterator;
+ if (NS_FAILED(rv = GetDirectoryEntries(getter_AddRefs(dirIterator))))
+ return rv;
+
+ PRBool hasMore = PR_FALSE;
+ while (dirIterator->HasMoreElements(&hasMore), hasMore) {
+ nsCOMPtr<nsIFile> entry;
+ rv = dirIterator->GetNext((nsISupports**)getter_AddRefs(entry));
+ if (NS_FAILED(rv))
+ continue;
+ if (NS_FAILED(rv = entry->IsSymlink(&isSymlink)))
+ return rv;
+ if (NS_FAILED(rv = entry->IsDirectory(&dirCheck)))
+ return rv;
+ if (dirCheck && !isSymlink) {
+ nsCOMPtr<nsIFile> destClone;
+ rv = newParent->Clone(getter_AddRefs(destClone));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsILocalFile> newDir(do_QueryInterface(destClone));
+ if (NS_FAILED(rv = entry->CopyToNative(newDir, EmptyCString()))) {
+#ifdef DEBUG
+ nsresult rv2;
+ nsCAutoString pathName;
+ if (NS_FAILED(rv2 = entry->GetNativePath(pathName)))
+ return rv2;
+ printf("Operation not supported: %s\n", pathName.get());
+#endif
+ if (rv == NS_ERROR_OUT_OF_MEMORY)
+ return rv;
+ continue;
+ }
+ }
+ } else {
+ if (NS_FAILED(rv = entry->CopyToNative(newParent, EmptyCString()))) {
+#ifdef DEBUG
+ nsresult rv2;
+ nsCAutoString pathName;
+ if (NS_FAILED(rv2 = entry->GetNativePath(pathName)))
+ return rv2;
+ printf("Operation not supported: %s\n", pathName.get());
+#endif
+ if (rv == NS_ERROR_OUT_OF_MEMORY)
+ return rv;
+ continue;
+ }
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParent, const nsACString &newName)
+{
+ nsresult rv;
+ // check to make sure that this has been initialized properly
+ CHECK_mPath();
+
+ // we copy the parent here so 'newParent' remains immutable
+ nsCOMPtr <nsIFile> workParent;
+ if (newParent) {
+ if (NS_FAILED(rv = newParent->Clone(getter_AddRefs(workParent))))
+ return rv;
+ } else {
+ if (NS_FAILED(rv = GetParent(getter_AddRefs(workParent))))
+ return rv;
+ }
+
+ // check to see if we are a directory or if we are a file
+ PRBool isDirectory;
+ if (NS_FAILED(rv = IsDirectory(&isDirectory)))
+ return rv;
+
+ nsCAutoString newPathName;
+ if (isDirectory) {
+ if (!newName.IsEmpty()) {
+ if (NS_FAILED(rv = workParent->AppendNative(newName)))
+ return rv;
+ } else {
+ if (NS_FAILED(rv = GetNativeLeafName(newPathName)))
+ return rv;
+ if (NS_FAILED(rv = workParent->AppendNative(newPathName)))
+ return rv;
+ }
+ if (NS_FAILED(rv = CopyDirectoryTo(workParent)))
+ return rv;
+ } else {
+ rv = GetNativeTargetPathName(workParent, newName, newPathName);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef DEBUG_blizzard
+ printf("nsLocalFile::CopyTo() %s -> %s\n", mPath.get(), newPathName.get());
+#endif
+
+ // actually create the file.
+ nsLocalFile *newFile = new nsLocalFile();
+ if (!newFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> fileRef(newFile); // release on exit
+
+ rv = newFile->InitWithNativePath(newPathName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the old permissions
+ PRUint32 myPerms;
+ GetPermissions(&myPerms);
+
+ // Create the new file with the old file's permissions, even if write
+ // permission is missing. We can't create with write permission and
+ // then change back to myPerm on all filesystems (FAT on Linux, e.g.).
+ // But we can write to a read-only file on all Unix filesystems if we
+ // open it successfully for writing.
+
+ PRFileDesc *newFD;
+ rv = newFile->CreateAndKeepOpen(NORMAL_FILE_TYPE,
+ PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,
+ myPerms,
+ &newFD);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // open the old file, too
+ PRBool specialFile;
+ if (NS_FAILED(rv = IsSpecial(&specialFile))) {
+ PR_Close(newFD);
+ return rv;
+ }
+ if (specialFile) {
+#ifdef DEBUG
+ printf("Operation not supported: %s\n", mPath.get());
+#endif
+ // make sure to clean up properly
+ PR_Close(newFD);
+ return NS_OK;
+ }
+
+ PRFileDesc *oldFD;
+ rv = OpenNSPRFileDesc(PR_RDONLY, myPerms, &oldFD);
+ if (NS_FAILED(rv)) {
+ // make sure to clean up properly
+ PR_Close(newFD);
+ return rv;
+ }
+
+#ifdef DEBUG_blizzard
+ PRInt32 totalRead = 0;
+ PRInt32 totalWritten = 0;
+#endif
+ char buf[BUFSIZ];
+ PRInt32 bytesRead;
+
+ while ((bytesRead = PR_Read(oldFD, buf, BUFSIZ)) > 0) {
+#ifdef DEBUG_blizzard
+ totalRead += bytesRead;
+#endif
+
+ // PR_Write promises never to do a short write
+ PRInt32 bytesWritten = PR_Write(newFD, buf, bytesRead);
+ if (bytesWritten < 0) {
+ bytesRead = -1;
+ break;
+ }
+ NS_ASSERTION(bytesWritten == bytesRead, "short PR_Write?");
+
+#ifdef DEBUG_blizzard
+ totalWritten += bytesWritten;
+#endif
+ }
+
+#ifdef DEBUG_blizzard
+ printf("read %d bytes, wrote %d bytes\n",
+ totalRead, totalWritten);
+#endif
+
+ // close the files
+ PR_Close(newFD);
+ PR_Close(oldFD);
+
+ // check for read (or write) error after cleaning up
+ if (bytesRead < 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParent, const nsACString &newName)
+{
+ return CopyToNative(newParent, newName);
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParent, const nsACString &newName)
+{
+ nsresult rv;
+
+ // check to make sure that this has been initialized properly
+ CHECK_mPath();
+
+ // check to make sure that we have a new parent
+ nsCAutoString newPathName;
+ rv = GetNativeTargetPathName(newParent, newName, newPathName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // try for atomic rename, falling back to copy/delete
+ if (rename(mPath.get(), newPathName.get()) < 0) {
+#ifdef VMS
+ if (errno == EXDEV || errno == ENXIO) {
+#else
+ if (errno == EXDEV) {
+#endif
+ rv = CopyToNative(newParent, newName);
+ if (NS_SUCCEEDED(rv))
+ rv = Remove(PR_TRUE);
+ } else {
+ rv = NSRESULT_FOR_ERRNO();
+ }
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ CHECK_mPath();
+
+ VALIDATE_STAT_CACHE();
+ PRBool isSymLink, isDir;
+
+ nsresult rv = IsSymlink(&isSymLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!recursive && isSymLink)
+ return NSRESULT_FOR_RETURN(unlink(mPath.get()));
+
+ isDir = S_ISDIR(mCachedStat.st_mode);
+ InvalidateCache();
+ if (isDir) {
+ if (recursive) {
+ nsDirEnumeratorUnix *dir = new nsDirEnumeratorUnix();
+ if (!dir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsISimpleEnumerator> dirRef(dir); // release on exit
+
+ rv = dir->Init(this, PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool more;
+ while (dir->HasMoreElements(&more), more) {
+ nsCOMPtr<nsISupports> item;
+ rv = dir->GetNext(getter_AddRefs(item));
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(item, &rv);
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+ if (NS_FAILED(rv = file->Remove(recursive)))
+ return rv;
+ }
+ }
+
+ if (rmdir(mPath.get()) == -1)
+ return NSRESULT_FOR_ERRNO();
+ } else {
+ if (unlink(mPath.get()) == -1)
+ return NSRESULT_FOR_ERRNO();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModTime)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aLastModTime);
+
+ PRFileInfo64 info;
+ if (PR_GetFileInfo64(mPath.get(), &info) != PR_SUCCESS)
+ return NSRESULT_FOR_ERRNO();
+
+ // PRTime is a 64 bit value
+ // microseconds -> milliseconds
+ PRInt64 usecPerMsec;
+ LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
+ LL_DIV(*aLastModTime, info.modifyTime, usecPerMsec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModTime)
+{
+ CHECK_mPath();
+
+ int result;
+ if (! LL_IS_ZERO(aLastModTime)) {
+ VALIDATE_STAT_CACHE();
+ struct utimbuf ut;
+ ut.actime = mCachedStat.st_atime;
+
+ // convert milliseconds to seconds since the unix epoch
+ double dTime;
+ LL_L2D(dTime, aLastModTime);
+ ut.modtime = (time_t) (dTime / PR_MSEC_PER_SEC);
+ result = utime(mPath.get(), &ut);
+ } else {
+ result = utime(mPath.get(), nsnull);
+ }
+ InvalidateCache();
+ return NSRESULT_FOR_RETURN(result);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModTimeOfLink)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aLastModTimeOfLink);
+
+ struct stat sbuf;
+ if (lstat(mPath.get(), &sbuf) == -1)
+ return NSRESULT_FOR_ERRNO();
+ LL_I2L(*aLastModTimeOfLink, (PRInt32)sbuf.st_mtime);
+
+ // lstat returns st_mtime in seconds
+ PRInt64 msecPerSec;
+ LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
+ LL_MUL(*aLastModTimeOfLink, *aLastModTimeOfLink, msecPerSec);
+
+ return NS_OK;
+}
+
+/*
+ * utime(2) may or may not dereference symlinks, joy.
+ */
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModTimeOfLink)
+{
+ return SetLastModifiedTime(aLastModTimeOfLink);
+}
+
+/*
+ * Only send back permissions bits: maybe we want to send back the whole
+ * mode_t to permit checks against other file types?
+ */
+
+#define NORMALIZE_PERMS(mode) ((mode)& (S_IRWXU | S_IRWXG | S_IRWXO))
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG(aPermissions);
+ VALIDATE_STAT_CACHE();
+ *aPermissions = NORMALIZE_PERMS(mCachedStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aPermissionsOfLink);
+
+ struct stat sbuf;
+ if (lstat(mPath.get(), &sbuf) == -1)
+ return NSRESULT_FOR_ERRNO();
+ *aPermissionsOfLink = NORMALIZE_PERMS(sbuf.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ CHECK_mPath();
+
+ InvalidateCache();
+
+ /*
+ * Race condition here: we should use fchmod instead, there's no way to
+ * guarantee the name still refers to the same file.
+ */
+ if (chmod(mPath.get(), aPermissions) < 0)
+ return NSRESULT_FOR_ERRNO();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ return SetPermissions(aPermissions);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG_POINTER(aFileSize);
+ *aFileSize = LL_ZERO;
+ VALIDATE_STAT_CACHE();
+
+#if defined(VMS)
+ /* Only two record formats can report correct file content size */
+ if ((mCachedStat.st_fab_rfm != FAB$C_STMLF) &&
+ (mCachedStat.st_fab_rfm != FAB$C_STMCR)) {
+ return NS_ERROR_FAILURE;
+ }
+#endif
+
+ /* XXX autoconf for and use stat64 if available */
+ if (!S_ISDIR(mCachedStat.st_mode)) {
+ LL_UI2L(*aFileSize, (PRUint32)mCachedStat.st_size);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ CHECK_mPath();
+
+ PRInt32 size;
+ LL_L2I(size, aFileSize);
+ /* XXX truncate64? */
+ InvalidateCache();
+ if (truncate(mPath.get(), (off_t)size) == -1)
+ return NSRESULT_FOR_ERRNO();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aFileSize);
+
+ struct stat sbuf;
+ if (lstat(mPath.get(), &sbuf) == -1)
+ return NSRESULT_FOR_ERRNO();
+ /* XXX autoconf for and use lstat64 if available */
+ LL_UI2L(*aFileSize, (PRUint32)sbuf.st_size);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG_POINTER(aDiskSpaceAvailable);
+
+ // These systems have the operations necessary to check disk space.
+
+#if defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_STATVFS_H)
+
+ // check to make sure that mPath is properly initialized
+ CHECK_mPath();
+
+ struct STATFS fs_buf;
+
+ /*
+ * Members of the STATFS struct that you should know about:
+ * f_bsize = block size on disk.
+ * f_bavail = number of free blocks available to a non-superuser.
+ * f_bfree = number of total free blocks in file system.
+ */
+
+ if (STATFS(mPath.get(), &fs_buf) < 0) {
+ // The call to STATFS failed.
+#ifdef DEBUG
+ printf("ERROR: GetDiskSpaceAvailable: STATFS call FAILED. \n");
+#endif
+ return NS_ERROR_FAILURE;
+ }
+#ifdef DEBUG_DISK_SPACE
+ printf("DiskSpaceAvailable: %d bytes\n",
+ fs_buf.f_bsize * (fs_buf.f_bavail - 1));
+#endif
+
+ /*
+ * The number of bytes free == The number of free blocks available to
+ * a non-superuser, minus one as a fudge factor, multiplied by the size
+ * of the aforementioned blocks.
+ */
+ PRInt64 bsize, bavail;
+
+ LL_I2L(bsize, fs_buf.f_bsize);
+ LL_I2L(bavail, fs_buf.f_bavail - 1);
+ LL_MUL(*aDiskSpaceAvailable, bsize, bavail);
+ return NS_OK;
+
+#else
+ /*
+ * This platform doesn't have statfs or statvfs. I'm sure that there's
+ * a way to check for free disk space on platforms that don't have statfs
+ * (I'm SURE they have df, for example).
+ *
+ * Until we figure out how to do that, lets be honest and say that this
+ * command isn't implemented properly for these platforms yet.
+ */
+#ifdef DEBUG
+ printf("ERROR: GetDiskSpaceAvailable: Not implemented for plaforms without statfs.\n");
+#endif
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+#endif /* HAVE_SYS_STATFS_H or HAVE_SYS_STATVFS_H */
+
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile **aParent)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nsnull;
+
+ // if '/' we are at the top of the volume, return null
+ if (mPath.Equals("/"))
+ return NS_OK;
+
+ // <brendan, after jband> I promise to play nice
+ char *buffer = mPath.BeginWriting(),
+ *slashp = buffer;
+
+ // find the last significant slash in buffer
+ slashp = strrchr(buffer, '/');
+ NS_ASSERTION(slashp, "non-canonical mPath?");
+ if (!slashp)
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ // for the case where we are at '/'
+ if (slashp == buffer)
+ slashp++;
+
+ // temporarily terminate buffer at the last significant slash
+ char c = *slashp;
+ *slashp = '\0';
+
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_NewNativeLocalFile(nsDependentCString(buffer), PR_TRUE,
+ getter_AddRefs(localFile));
+
+ // make buffer whole again
+ *slashp = c;
+
+ if (NS_SUCCEEDED(rv) && localFile)
+ rv = CallQueryInterface(localFile, aParent);
+ return rv;
+}
+
+/*
+ * The results of Exists, isWritable and isReadable are not cached.
+ */
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), F_OK) == 0);
+ return NS_OK;
+}
+
+#ifdef XP_BEOS
+// access() is buggy in BeOS POSIX implementation, at least for BFS, using stat() instead
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+ struct stat buf;
+ *_retval = (stat(mPath.get(), &buf) == 0);
+ *_retval = *_retval && (buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH ));
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+ struct stat buf;
+ *_retval = (stat(mPath.get(), &buf) == 0);
+ *_retval = *_retval && (buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH ));
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+ struct stat buf;
+ *_retval = (stat(mPath.get(), &buf) == 0);
+ *_retval = *_retval && (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH ));
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+#else
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), W_OK) == 0);
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), R_OK) == 0);
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), X_OK) == 0);
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+#endif
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+ VALIDATE_STAT_CACHE();
+ *_retval = S_ISDIR(mCachedStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+ VALIDATE_STAT_CACHE();
+ *_retval = S_ISREG(mCachedStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ nsACString::const_iterator begin, end;
+ LocateNativeLeafName(begin, end);
+ *_retval = (*begin == '.');
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ CHECK_mPath();
+
+ struct stat symStat;
+ lstat(mPath.get(), &symStat);
+ *_retval=S_ISLNK(symStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ VALIDATE_STAT_CACHE();
+ *_retval = S_ISCHR(mCachedStat.st_mode) ||
+ S_ISBLK(mCachedStat.st_mode) ||
+#ifdef S_ISSOCK
+ S_ISSOCK(mCachedStat.st_mode) ||
+#endif
+ S_ISFIFO(mCachedStat.st_mode);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv;
+ nsCAutoString inPath;
+
+ if (NS_FAILED(rv = inFile->GetNativePath(inPath)))
+ return rv;
+
+ *_retval = !FILE_STRCMP(inPath.get(), mPath.get());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCAutoString inPath;
+ nsresult rv;
+
+ if (NS_FAILED(rv = inFile->GetNativePath(inPath)))
+ return rv;
+
+ *_retval = PR_FALSE;
+
+ ssize_t len = mPath.Length();
+ if (FILE_STRNCMP(mPath.get(), inPath.get(), len) == 0) {
+ // Now make sure that the |inFile|'s path has a separator at len,
+ // which implies that it has more components after len.
+ if (inPath[len] == '/')
+ *_retval = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ CHECK_mPath();
+ _retval.Truncate();
+
+ struct stat symStat;
+ lstat(mPath.get(), &symStat);
+ if (!S_ISLNK(symStat.st_mode))
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ PRInt64 targetSize64;
+ if (NS_FAILED(GetFileSizeOfLink(&targetSize64)))
+ return NS_ERROR_FAILURE;
+
+ PRInt32 size;
+ LL_L2I(size, targetSize64);
+ char *target = (char *)nsMemory::Alloc(size + 1);
+ if (!target)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (readlink(mPath.get(), target, (size_t)size) < 0) {
+ nsMemory::Free(target);
+ return NSRESULT_FOR_ERRNO();
+ }
+ target[size] = '\0';
+
+ nsresult rv;
+ PRBool isSymlink;
+ nsCOMPtr<nsIFile> self(this);
+ nsCOMPtr<nsIFile> parent;
+ while (NS_SUCCEEDED(rv = self->GetParent(getter_AddRefs(parent)))) {
+ NS_ASSERTION(parent != nsnull, "no parent?!");
+
+ if (target[0] != '/') {
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(parent, &rv));
+ if (NS_FAILED(rv))
+ break;
+ if (NS_FAILED(rv = localFile->AppendRelativeNativePath(nsDependentCString(target))))
+ break;
+ if (NS_FAILED(rv = localFile->GetNativePath(_retval)))
+ break;
+ if (NS_FAILED(rv = parent->IsSymlink(&isSymlink)))
+ break;
+ self = parent;
+ } else {
+ nsCOMPtr<nsILocalFile> localFile;
+ rv = NS_NewNativeLocalFile(nsDependentCString(target), PR_TRUE,
+ getter_AddRefs(localFile));
+ if (NS_FAILED(rv))
+ break;
+ if (NS_FAILED(rv = localFile->IsSymlink(&isSymlink)))
+ break;
+ _retval = target; // XXX can we avoid this buffer copy?
+ self = do_QueryInterface(localFile);
+ }
+ if (NS_FAILED(rv) || !isSymlink)
+ break;
+
+ const nsPromiseFlatCString &flatRetval = PromiseFlatCString(_retval);
+
+ // strip off any and all trailing '/'
+ PRInt32 len = strlen(target);
+ while (target[len-1] == '/' && len > 1)
+ target[--len] = '\0';
+ if (lstat(flatRetval.get(), &symStat) < 0) {
+ rv = NSRESULT_FOR_ERRNO();
+ break;
+ }
+ if (!S_ISLNK(symStat.st_mode)) {
+ rv = NS_ERROR_FILE_INVALID_PATH;
+ break;
+ }
+ size = symStat.st_size;
+ if (readlink(flatRetval.get(), target, size) < 0) {
+ rv = NSRESULT_FOR_ERRNO();
+ break;
+ }
+ target[size] = '\0';
+
+ _retval.Truncate();
+ }
+
+ nsMemory::Free(target);
+
+ if (NS_FAILED(rv))
+ _retval.Truncate();
+ return rv;
+}
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ *aFollowLinks = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **entries)
+{
+ nsDirEnumeratorUnix *dir = new nsDirEnumeratorUnix();
+ if (!dir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(dir);
+ nsresult rv = dir->Init(this, PR_FALSE);
+ if (NS_FAILED(rv)) {
+ *entries = nsnull;
+ NS_RELEASE(dir);
+ } else {
+ *entries = dir; // transfer reference
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary **_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+
+ *_retval = PR_LoadLibrary(mPath.get());
+
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", mPath.get());
+
+ if (!*_retval)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ return GetNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ return InitWithNativePath(aPersistentDescriptor);
+}
+
+#ifdef XP_BEOS
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ BPath bPath(mPath.get());
+ bPath.GetParent(&bPath);
+ entry_ref ref;
+ get_ref_for_path(bPath.Path(),&ref);
+ BMessage message(B_REFS_RECEIVED);
+ message.AddRef("refs",&ref);
+ BMessenger messenger("application/x-vnd.Be-TRAK");
+ messenger.SendMessage(&message);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ entry_ref ref;
+ get_ref_for_path (mPath.get(), &ref);
+ be_roster->Launch (&ref);
+
+ return NS_OK;
+}
+#else
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ return NS_ERROR_FAILURE;
+}
+#endif
+
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followSymlinks, nsILocalFile **result)
+{
+ nsLocalFile *file = new nsLocalFile();
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+ *result = file;
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// unicode support
+//-----------------------------------------------------------------------------
+
+#define SET_UCS(func, ucsArg) \
+ { \
+ nsCAutoString buf; \
+ nsresult rv = NS_CopyUnicodeToNative(ucsArg, buf); \
+ if (NS_FAILED(rv)) \
+ return rv; \
+ return (func)(buf); \
+ }
+
+#define GET_UCS(func, ucsArg) \
+ { \
+ nsCAutoString buf; \
+ nsresult rv = (func)(buf); \
+ if (NS_FAILED(rv)) return rv; \
+ return NS_CopyNativeToUnicode(buf, ucsArg); \
+ }
+
+#define SET_UCS_2ARGS_2(func, opaqueArg, ucsArg) \
+ { \
+ nsCAutoString buf; \
+ nsresult rv = NS_CopyUnicodeToNative(ucsArg, buf); \
+ if (NS_FAILED(rv)) \
+ return rv; \
+ return (func)(opaqueArg, buf); \
+ }
+
+// Unicode interface Wrapper
+nsresult
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ SET_UCS(InitWithNativePath, filePath);
+}
+nsresult
+nsLocalFile::Append(const nsAString &node)
+{
+ SET_UCS(AppendNative, node);
+}
+nsresult
+nsLocalFile::AppendRelativePath(const nsAString &node)
+{
+ SET_UCS(AppendRelativeNativePath, node);
+}
+nsresult
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ GET_UCS(GetNativeLeafName, aLeafName);
+}
+nsresult
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ SET_UCS(SetNativeLeafName, aLeafName);
+}
+nsresult
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ return NS_CopyNativeToUnicode(mPath, _retval);
+}
+nsresult
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ SET_UCS_2ARGS_2(CopyToNative , newParentDir, newName);
+}
+nsresult
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ SET_UCS_2ARGS_2(CopyToFollowingLinksNative , newParentDir, newName);
+}
+nsresult
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ SET_UCS_2ARGS_2(MoveToNative, newParentDir, newName);
+}
+nsresult
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ GET_UCS(GetNativeTarget, _retval);
+}
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString buf;
+ nsresult rv = NS_CopyUnicodeToNative(path, buf);
+ if (NS_FAILED(rv))
+ return rv;
+ return NS_NewNativeLocalFile(buf, followLinks, result);
+}
+
+//-----------------------------------------------------------------------------
+// global init/shutdown
+//-----------------------------------------------------------------------------
+
+void
+nsLocalFile::GlobalInit()
+{
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h
new file mode 100644
index 00000000..a994e1a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike Shaver <shaver@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Implementation of nsIFile for ``Unixy'' systems.
+ */
+
+#ifndef _nsLocalFileUNIX_H_
+#define _nsLocalFileUNIX_H_
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+/**
+ * we need these for statfs()
+ */
+#ifdef HAVE_SYS_STATVFS_H
+ #if defined(__osf__) && defined(__DECCXX)
+ extern "C" int statvfs(const char *, struct statvfs *);
+ #endif
+ #include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+ #include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_STATVFS
+ #define STATFS statvfs
+#else
+ #define STATFS statfs
+#endif
+
+// so we can statfs on freebsd
+#if defined(__FreeBSD__)
+ #define HAVE_SYS_STATFS_H
+ #define STATFS statfs
+ #include <sys/param.h>
+ #include <sys/mount.h>
+#endif
+
+class NS_COM nsLocalFile : public nsILocalFile
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports
+ NS_DECL_ISUPPORTS
+
+ // nsIFile
+ NS_DECL_NSIFILE
+
+ // nsILocalFile
+ NS_DECL_NSILOCALFILE
+
+public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ nsLocalFile(const nsLocalFile& other);
+ ~nsLocalFile() {}
+
+protected:
+ struct stat mCachedStat;
+ nsCString mPath;
+ PRPackedBool mHaveCachedStat;
+
+ void LocateNativeLeafName(nsACString::const_iterator &,
+ nsACString::const_iterator &);
+
+ nsresult CopyDirectoryTo(nsIFile *newParent);
+ nsresult CreateAllAncestors(PRUint32 permissions);
+ nsresult GetNativeTargetPathName(nsIFile *newParent,
+ const nsACString &newName,
+ nsACString &_retval);
+
+ void InvalidateCache() {
+ mHaveCachedStat = PR_FALSE;
+ }
+ nsresult FillStatCache();
+
+ nsresult CreateAndKeepOpen(PRUint32 type, PRIntn flags,
+ PRUint32 permissions, PRFileDesc **_retval);
+};
+
+#endif /* _nsLocalFileUNIX_H_ */
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp
new file mode 100644
index 00000000..63414fc3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp
@@ -0,0 +1,2440 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * Dean Tessman <dean_tessman@hotmail.com>
+ * Brodie Thiesfield <brofield@jellycan.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+
+#include "nsLocalFile.h"
+#include "nsNativeCharsetUtils.h"
+
+#include "nsISimpleEnumerator.h"
+#include "nsIComponentManager.h"
+#include "prtypes.h"
+#include "prio.h"
+
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+
+#include <direct.h>
+#include <windows.h>
+
+#include "shellapi.h"
+#include "shlguid.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mbstring.h>
+
+#include "nsXPIDLString.h"
+#include "prproces.h"
+#include "nsITimelineService.h"
+
+#include "nsAutoLock.h"
+#include "SpecialSystemDirectory.h"
+
+// _mbsstr isn't declared in w32api headers but it's there in the libs
+#ifdef __MINGW32__
+extern "C" {
+unsigned char *_mbsstr( const unsigned char *str,
+ const unsigned char *substr );
+}
+#endif
+
+class nsDriveEnumerator : public nsISimpleEnumerator
+{
+public:
+ nsDriveEnumerator();
+ virtual ~nsDriveEnumerator();
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+ nsresult Init();
+private:
+ /* mDrives and mLetter share data
+ * Init sets them.
+ * HasMoreElements reads mLetter.
+ * GetNext advances mLetter.
+ */
+ nsCString mDrives;
+ const char *mLetter;
+};
+
+//----------------------------------------------------------------------------
+// short cut resolver
+//----------------------------------------------------------------------------
+
+class ShortcutResolver
+{
+public:
+ ShortcutResolver();
+ // nonvirtual since we're not subclassed
+ ~ShortcutResolver();
+
+ nsresult Init();
+ nsresult Resolve(const WCHAR* in, char* out);
+
+private:
+ PRLock* mLock;
+ IPersistFile* mPersistFile;
+ IShellLink* mShellLink;
+};
+
+ShortcutResolver::ShortcutResolver()
+{
+ mLock = nsnull;
+ mPersistFile = nsnull;
+ mShellLink = nsnull;
+}
+
+ShortcutResolver::~ShortcutResolver()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ // Release the pointer to the IPersistFile interface.
+ if (mPersistFile)
+ mPersistFile->Release();
+
+ // Release the pointer to the IShellLink interface.
+ if(mShellLink)
+ mShellLink->Release();
+
+ CoUninitialize();
+}
+
+nsresult
+ShortcutResolver::Init()
+{
+ CoInitialize(NULL); // FIX: we should probably move somewhere higher up during startup
+
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_FAILURE;
+
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IShellLink,
+ (void**)&mShellLink);
+ if (SUCCEEDED(hres))
+ {
+ // Get a pointer to the IPersistFile interface.
+ hres = mShellLink->QueryInterface(IID_IPersistFile, (void**)&mPersistFile);
+ }
+
+ if (mPersistFile == nsnull || mShellLink == nsnull)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+// |out| must be an allocated buffer of size MAX_PATH
+nsresult
+ShortcutResolver::Resolve(const WCHAR* in, char* out)
+{
+ nsAutoLock lock(mLock);
+
+ // see if we can Load the path.
+ HRESULT hres = mPersistFile->Load(in, STGM_READ);
+
+ if (FAILED(hres))
+ return NS_ERROR_FAILURE;
+
+ // Resolve the link.
+ hres = mShellLink->Resolve(nsnull, SLR_NO_UI );
+
+ if (FAILED(hres))
+ return NS_ERROR_FAILURE;
+
+ WIN32_FIND_DATA wfd;
+ // Get the path to the link target.
+ hres = mShellLink->GetPath( out, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
+ if (FAILED(hres))
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+static ShortcutResolver * gResolver = nsnull;
+
+static nsresult NS_CreateShortcutResolver()
+{
+ gResolver = new ShortcutResolver();
+ if (!gResolver)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return gResolver->Init();
+}
+
+static void NS_DestroyShortcutResolver()
+{
+ delete gResolver;
+ gResolver = nsnull;
+}
+
+
+//-----------------------------------------------------------------------------
+// static helper functions
+//-----------------------------------------------------------------------------
+
+// certainly not all the error that can be
+// encountered, but many of them common ones
+static nsresult ConvertWinError(DWORD winErr)
+{
+ nsresult rv;
+
+ switch (winErr)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ rv = NS_ERROR_FILE_NOT_FOUND;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NOT_SAME_DEVICE:
+ rv = NS_ERROR_FILE_ACCESS_DENIED;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_INVALID_HANDLE:
+ case ERROR_ARENA_TRASHED:
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ case ERROR_CURRENT_DIRECTORY:
+ rv = NS_ERROR_FILE_DIR_NOT_EMPTY;
+ break;
+ case ERROR_WRITE_PROTECT:
+ rv = NS_ERROR_FILE_READ_ONLY;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ rv = NS_ERROR_FILE_TOO_BIG;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_CANNOT_MAKE:
+ rv = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+ case 0:
+ rv = NS_OK;
+ break;
+ default:
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ return rv;
+}
+
+// definition of INVALID_SET_FILE_POINTER from VC.NET header files
+// it doesn't appear to be defined by VC6
+#ifndef INVALID_SET_FILE_POINTER
+# define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+// same goes for INVALID_FILE_ATTRIBUTES
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+
+// as suggested in the MSDN documentation on SetFilePointer
+static __int64
+MyFileSeek64(HANDLE aHandle, __int64 aDistance, DWORD aMoveMethod)
+{
+ LARGE_INTEGER li;
+
+ li.QuadPart = aDistance;
+ li.LowPart = SetFilePointer(aHandle, li.LowPart, &li.HighPart, aMoveMethod);
+ if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
+ {
+ li.QuadPart = -1;
+ }
+
+ return li.QuadPart;
+}
+
+static PRBool
+IsShortcutPath(const char *path)
+{
+ // Under Windows, the shortcuts are just files with a ".lnk" extension.
+ // Note also that we don't resolve links in the middle of paths.
+ // i.e. "c:\foo.lnk\bar.txt" is invalid.
+ NS_ABORT_IF_FALSE(path, "don't pass nulls");
+ const char * ext = (const char *) _mbsrchr((const unsigned char *)path, '.');
+ if (!ext || 0 != stricmp(ext + 1, "lnk"))
+ return PR_FALSE;
+ return PR_TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// nsDirEnumerator
+//-----------------------------------------------------------------------------
+
+class nsDirEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator() : mDir(nsnull)
+ {
+ }
+
+ nsresult Init(nsILocalFile* parent)
+ {
+ nsCAutoString filepath;
+ parent->GetNativeTarget(filepath);
+
+ if (filepath.IsEmpty())
+ {
+ parent->GetNativePath(filepath);
+ }
+
+ if (filepath.IsEmpty())
+ {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mDir = PR_OpenDir(filepath.get());
+ if (mDir == nsnull) // not a directory?
+ return NS_ERROR_FAILURE;
+
+ mParent = parent;
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ nsresult rv;
+ if (mNext == nsnull && mDir)
+ {
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
+ if (entry == nsnull)
+ {
+ // end of dir entries
+
+ PRStatus status = PR_CloseDir(mDir);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FAILURE;
+ mDir = nsnull;
+
+ *result = PR_FALSE;
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ rv = mParent->Clone(getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = file->AppendNative(nsDependentCString(entry->name));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // make sure the thing exists. If it does, try the next one.
+ PRBool exists;
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ {
+ return HasMoreElements(result);
+ }
+
+ mNext = do_QueryInterface(file);
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ // dtor can be non-virtual since there are no subclasses, but must be
+ // public to use the class on the stack.
+ ~nsDirEnumerator()
+ {
+ if (mDir)
+ {
+ PRStatus status = PR_CloseDir(mDir);
+ NS_ASSERTION(status == PR_SUCCESS, "close failed");
+ }
+ }
+
+ protected:
+ PRDir* mDir;
+ nsCOMPtr<nsILocalFile> mParent;
+ nsCOMPtr<nsILocalFile> mNext;
+};
+
+NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile <public>
+//-----------------------------------------------------------------------------
+
+nsLocalFile::nsLocalFile()
+ : mFollowSymlinks(PR_FALSE)
+{
+ MakeDirty();
+ memset(&mFileInfo64, 0, sizeof(mFileInfo64));
+}
+
+NS_METHOD
+nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile::nsISupports
+//-----------------------------------------------------------------------------
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile)
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile <private>
+//-----------------------------------------------------------------------------
+
+nsLocalFile::nsLocalFile(const nsLocalFile& other)
+ : mDirty(other.mDirty)
+ , mFollowSymlinks(other.mFollowSymlinks)
+ , mWorkingPath(other.mWorkingPath)
+ , mResolvedPath(other.mResolvedPath)
+ , mFileInfo64(other.mFileInfo64)
+{
+}
+
+// Resolve the shortcut file from mWorkingPath and write the path
+// it points to into mResolvedPath.
+nsresult
+nsLocalFile::ResolveShortcut()
+{
+ // we can't do anything without the resolver
+ if (!gResolver)
+ return NS_ERROR_FAILURE;
+
+ // allocate the memory for the result of the resolution
+ nsAutoString ucsBuf;
+ NS_CopyNativeToUnicode(mWorkingPath, ucsBuf);
+
+ mResolvedPath.SetLength(MAX_PATH);
+ char *resolvedPath = mResolvedPath.BeginWriting();
+
+ // resolve this shortcut
+ nsresult rv = gResolver->Resolve(ucsBuf.get(), resolvedPath);
+
+ size_t len = NS_FAILED(rv) ? 0 : strlen(resolvedPath);
+ mResolvedPath.SetLength(len);
+
+ return rv;
+}
+
+// Resolve any shortcuts and stat the resolved path. After a successful return
+// the path is guaranteed valid and the members of mFileInfo64 can be used.
+nsresult
+nsLocalFile::ResolveAndStat()
+{
+ // if we aren't dirty then we are already done
+ if (!mDirty)
+ return NS_OK;
+
+ // we can't resolve/stat anything that isn't a valid NSPR addressable path
+ if (mWorkingPath.IsEmpty())
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ // this is usually correct
+ mResolvedPath.Assign(mWorkingPath);
+
+ // slutty hack designed to work around bug 134796 until it is fixed
+ char temp[4];
+ const char *nsprPath = mWorkingPath.get();
+ if (mWorkingPath.Length() == 2 && mWorkingPath.CharAt(1) == ':')
+ {
+ temp[0] = mWorkingPath[0];
+ temp[1] = mWorkingPath[1];
+ temp[2] = '\\';
+ temp[3] = '\0';
+ nsprPath = temp;
+ }
+
+ // first we will see if the working path exists. If it doesn't then
+ // there is nothing more that can be done
+ PRStatus status = PR_GetFileInfo64(nsprPath, &mFileInfo64);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ // if this isn't a shortcut file or we aren't following symlinks then we're done
+ if (!mFollowSymlinks
+ || mFileInfo64.type != PR_FILE_FILE
+ || !IsShortcutPath(mWorkingPath.get()))
+ {
+ mDirty = PR_FALSE;
+ return NS_OK;
+ }
+
+ // we need to resolve this shortcut to what it points to, this will
+ // set mResolvedPath. Even if it fails we need to have the resolved
+ // path equal to working path for those functions that always use
+ // the resolved path.
+ nsresult rv = ResolveShortcut();
+ if (NS_FAILED(rv))
+ {
+ mResolvedPath.Assign(mWorkingPath);
+ return rv;
+ }
+
+ // get the details of the resolved path
+ status = PR_GetFileInfo64(mResolvedPath.get(), &mFileInfo64);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ mDirty = PR_FALSE;
+ return NS_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile::nsIFile,nsILocalFile
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ MakeDirty();
+
+ nsACString::const_iterator begin, end;
+ filePath.BeginReading(begin);
+ filePath.EndReading(end);
+
+ // input string must not be empty
+ if (begin == end)
+ return NS_ERROR_FAILURE;
+
+ char firstChar = *begin;
+ char secondChar = *(++begin);
+
+ // just do a sanity check. if it has any forward slashes, it is not a Native path
+ // on windows. Also, it must have a colon at after the first char.
+
+ char *path = nsnull;
+ PRInt32 pathLen = 0;
+
+ if ( ( (secondChar == ':') && !FindCharInReadable('/', begin, end) ) || // normal path
+ ( (firstChar == '\\') && (secondChar == '\\') ) ) // network path
+ {
+ // This is a native path
+ path = ToNewCString(filePath);
+ pathLen = filePath.Length();
+ }
+
+ if (path == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // kill any trailing '\' provided it isn't the second char of DBCS
+ PRInt32 len = pathLen - 1;
+ if (path[len] == '\\' &&
+ (!::IsDBCSLeadByte(path[len-1]) ||
+ _mbsrchr((const unsigned char *)path, '\\') == (const unsigned char *)path+len))
+ {
+ path[len] = '\0';
+ pathLen = len;
+ }
+
+ mWorkingPath.Adopt(path, pathLen);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = PR_Open(mResolvedPath.get(), flags, mode);
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ErrorAccordingToNSPR();
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = fopen(mResolvedPath.get(), mode);
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_FAILURE;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ // create directories to target
+ //
+ // A given local file can be either one of these forms:
+ //
+ // - normal: X:\some\path\on\this\drive
+ // ^--- start here
+ //
+ // - UNC path: \\machine\volume\some\path\on\this\drive
+ // ^--- start here
+ //
+ // Skip the first 'X:\' for the first form, and skip the first full
+ // '\\machine\volume\' segment for the second form.
+
+ const unsigned char* path = (const unsigned char*) mResolvedPath.get();
+ if (path[0] == '\\' && path[1] == '\\')
+ {
+ // dealing with a UNC path here; skip past '\\machine\'
+ path = _mbschr(path + 2, '\\');
+ if (!path)
+ return NS_ERROR_FILE_INVALID_PATH;
+ ++path;
+ }
+
+ // search for first slash after the drive (or volume) name
+ unsigned char* slash = _mbschr(path, '\\');
+
+ if (slash)
+ {
+ // skip the first '\\'
+ ++slash;
+ slash = _mbschr(slash, '\\');
+
+ while (slash)
+ {
+ *slash = '\0';
+
+ if (!CreateDirectoryA(mResolvedPath.get(), NULL)) {
+ rv = ConvertWinError(GetLastError());
+ // perhaps the base path already exists, or perhaps we don't have
+ // permissions to create the directory. NOTE: access denied could
+ // occur on a parent directory even though it exists.
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS &&
+ rv != NS_ERROR_FILE_ACCESS_DENIED)
+ return rv;
+ }
+ *slash = '\\';
+ ++slash;
+ slash = _mbschr(slash, '\\');
+ }
+ }
+
+ if (type == NORMAL_FILE_TYPE)
+ {
+ PRFileDesc* file = PR_Open(mResolvedPath.get(), PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL, attributes);
+ if (!file) return NS_ERROR_FILE_ALREADY_EXISTS;
+
+ PR_Close(file);
+ return NS_OK;
+ }
+
+ if (type == DIRECTORY_TYPE)
+ {
+ if (!CreateDirectoryA(mResolvedPath.get(), NULL))
+ return ConvertWinError(GetLastError());
+ else
+ return NS_OK;
+ }
+
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &node)
+{
+ // append this path, multiple components are not permitted
+ return AppendNativeInternal(PromiseFlatCString(node), PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &node)
+{
+ // append this path, multiple components are permitted
+ return AppendNativeInternal(PromiseFlatCString(node), PR_TRUE);
+}
+
+nsresult
+nsLocalFile::AppendNativeInternal(const nsAFlatCString &node, PRBool multipleComponents)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ // check the relative path for validity
+ const unsigned char * nodePath = (const unsigned char *) node.get();
+ if (*nodePath == '\\' // can't start with an '\'
+ || _mbschr(nodePath, '/') // can't contain /
+ || node.Equals("..")) // can't be ..
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ if (multipleComponents)
+ {
+ // can't contain .. as a path component. Ensure that the valid components
+ // "foo..foo", "..foo", and "foo.." are not falsely detected, but the invalid
+ // paths "..\", "foo\..", "foo\..\foo", "..\foo", etc are.
+ unsigned char * doubleDot = _mbsstr(nodePath, (unsigned char *)"\\..");
+ while (doubleDot)
+ {
+ doubleDot += 3;
+ if (*doubleDot == '\0' || *doubleDot == '\\')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ doubleDot = _mbsstr(doubleDot, (unsigned char *)"\\..");
+ }
+ if (0 == _mbsncmp(nodePath, (unsigned char *)"..\\", 3)) // catches the remaining cases of prefixes
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ }
+ else if (_mbschr(nodePath, '\\')) // single components can't contain '\'
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ MakeDirty();
+
+ mWorkingPath.Append(NS_LITERAL_CSTRING("\\") + node);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ // XXX See bug 187957 comment 18 for possible problems with this implementation.
+
+ if (mWorkingPath.IsEmpty())
+ return NS_OK;
+
+ // work in unicode for ease
+ nsAutoString path;
+ NS_CopyNativeToUnicode(mWorkingPath, path);
+
+ // find the index of the root backslash for the path. Everything before
+ // this is considered fully normalized and cannot be ascended beyond
+ // using ".." For a local drive this is the first slash (e.g. "c:\").
+ // For a UNC path it is the slash following the share name
+ // (e.g. "\\server\share\").
+ PRInt32 rootIdx = 2; // default to local drive
+ if (path.First() == '\\') // if a share then calculate the rootIdx
+ {
+ rootIdx = path.FindChar('\\', 2); // skip \\ in front of the server
+ if (rootIdx == kNotFound)
+ return NS_OK; // already normalized
+ rootIdx = path.FindChar('\\', rootIdx+1);
+ if (rootIdx == kNotFound)
+ return NS_OK; // already normalized
+ }
+ else if (path.CharAt(rootIdx) != '\\')
+ {
+ // The path has been specified relative to the current working directory
+ // for that drive. To normalize it, the current working directory for
+ // that drive needs to be inserted before the supplied relative path
+ // which will provide an absolute path (and the rootIdx will still be 2).
+ char cwd[MAX_PATH];
+ char * pcwd = cwd;
+ int drive = toupper(path.First()) - 'A' + 1;
+ if (!_getdcwd(drive, pcwd, MAX_PATH))
+ pcwd = _getdcwd(drive, 0, 0);
+ if (!pcwd)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsAutoString currentDir;
+ NS_CopyNativeToUnicode(nsDependentCString(pcwd), currentDir);
+ if (pcwd != cwd)
+ free(pcwd);
+
+ if (currentDir.Last() == '\\')
+ path.Replace(0, 2, currentDir);
+ else
+ path.Replace(0, 2, currentDir + NS_LITERAL_STRING("\\"));
+ }
+ NS_POSTCONDITION(0 < rootIdx && rootIdx < (PRInt32)path.Length(), "rootIdx is invalid");
+ NS_POSTCONDITION(path.CharAt(rootIdx) == '\\', "rootIdx is invalid");
+
+ // if there is nothing following the root path then it is already normalized
+ if (rootIdx + 1 == (PRInt32)path.Length())
+ return NS_OK;
+
+ // assign the root
+ nsAutoString normal;
+ const PRUnichar * pathBuffer = path.get(); // simplify access to the buffer
+ normal.SetCapacity(path.Length()); // it won't ever grow longer
+ normal.Assign(pathBuffer, rootIdx);
+
+ // Normalize the path components. The actions taken are:
+ //
+ // "\\" condense to single backslash
+ // "." remove from path
+ // ".." up a directory
+ // "..." remove from path (any number of dots > 2)
+ //
+ // The last form is something that Windows 95 and 98 supported and
+ // is a shortcut for changing up multiple directories. Windows XP
+ // and ilk ignore it in a path, as is done here.
+ PRInt32 len, begin, end = rootIdx;
+ while (end < (PRInt32)path.Length())
+ {
+ // find the current segment (text between the backslashes) to
+ // be examined, this will set the following variables:
+ // begin == index of first char in segment
+ // end == index 1 char after last char in segment
+ // len == length of segment
+ begin = end + 1;
+ end = path.FindChar('\\', begin);
+ if (end == kNotFound)
+ end = path.Length();
+ len = end - begin;
+
+ // ignore double backslashes
+ if (len == 0)
+ continue;
+
+ // len != 0, and interesting paths always begin with a dot
+ if (pathBuffer[begin] == '.')
+ {
+ // ignore single dots
+ if (len == 1)
+ continue;
+
+ // handle multiple dots
+ if (len >= 2 && pathBuffer[begin+1] == '.')
+ {
+ // back up a path component on double dot
+ if (len == 2)
+ {
+ PRInt32 prev = normal.RFindChar('\\');
+ if (prev >= rootIdx)
+ normal.Truncate(prev);
+ continue;
+ }
+
+ // length is > 2 and the first two characters are dots.
+ // if the rest of the string is dots, then ignore it.
+ int idx = len - 1;
+ for (; idx >= 2; --idx)
+ {
+ if (pathBuffer[begin+idx] != '.')
+ break;
+ }
+
+ // this is true if the loop above didn't break
+ // and all characters in this segment are dots.
+ if (idx < 2)
+ continue;
+ }
+ }
+
+ // add the current component to the path, including the preceding backslash
+ normal.Append(pathBuffer + begin - 1, len + 1);
+ }
+
+ NS_CopyUnicodeToNative(normal, mWorkingPath);
+ MakeDirty();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ aLeafName.Truncate();
+
+ const char* temp = mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp, '\\');
+
+ // if the working path is just a node without any lashes.
+ if (leaf == nsnull)
+ leaf = temp;
+ else
+ leaf++;
+
+ aLeafName.Assign(leaf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ MakeDirty();
+
+ const unsigned char* temp = (const unsigned char*) mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr(temp, '\\') - temp);
+ if (offset)
+ {
+ mWorkingPath.Truncate(offset+1);
+ }
+ mWorkingPath.Append(aLeafName);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval = mWorkingPath;
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const nsACString &newName,
+ PRBool followSymlinks, PRBool move)
+{
+ nsresult rv;
+ nsCAutoString filePath;
+
+ // get the path that we are going to copy to.
+ // Since windows does not know how to auto
+ // resolve shortcuts, we must work with the
+ // target.
+ nsCAutoString destPath;
+ destParent->GetNativeTarget(destPath);
+
+ destPath.Append("\\");
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ sourceFile->GetNativeLeafName(aFileName);
+ destPath.Append(aFileName);
+ }
+ else
+ {
+ destPath.Append(newName);
+ }
+
+
+ if (followSymlinks)
+ {
+ rv = sourceFile->GetNativeTarget(filePath);
+ if (filePath.IsEmpty())
+ rv = sourceFile->GetNativePath(filePath);
+ }
+ else
+ {
+ rv = sourceFile->GetNativePath(filePath);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ int copyOK;
+
+ if (!move)
+ copyOK = CopyFile(filePath.get(), destPath.get(), PR_TRUE);
+ else
+ {
+ // What we have to do is check to see if the destPath exists. If it
+ // does, we have to move it out of the say so that MoveFile will
+ // succeed. However, we don't want to just remove it since MoveFile
+ // can fail leaving us without a file.
+
+ nsCAutoString backup;
+ PRFileInfo64 fileInfo64;
+ PRStatus status = PR_GetFileInfo64(destPath.get(), &fileInfo64);
+ if (status == PR_SUCCESS)
+ {
+
+ // the file exists. Check to make sure it is not a directory,
+ // then move it out of the way.
+ if (fileInfo64.type == PR_FILE_FILE)
+ {
+ backup.Append(destPath);
+ backup.Append(".moztmp");
+
+ // remove any existing backup file that we may already have.
+ // maybe we should be doing some kind of unique naming here,
+ // but why bother.
+ remove(backup.get());
+
+ // move destination file to backup file
+ copyOK = MoveFile(destPath.get(), backup.get());
+ if (!copyOK)
+ {
+ // I guess we can't do the backup copy, so return.
+ rv = ConvertWinError(GetLastError());
+ return rv;
+ }
+ }
+ }
+ // move source file to destination file
+ copyOK = MoveFile(filePath.get(), destPath.get());
+
+ if (!backup.IsEmpty())
+ {
+ if (copyOK)
+ {
+ // remove the backup copy.
+ remove(backup.get());
+ }
+ else
+ {
+ // restore backup
+ int backupOk = MoveFile(backup.get(), destPath.get());
+ NS_ASSERTION(backupOk, "move backup failed");
+ }
+ }
+ }
+ if (!copyOK) // CopyFile and MoveFile returns non-zero if succeeds (backward if you ask me).
+ rv = ConvertWinError(GetLastError());
+
+ return rv;
+}
+
+
+nsresult
+nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, PRBool followSymlinks, PRBool move)
+{
+ nsCOMPtr<nsIFile> newParentDir = aParentDir;
+ // check to see if this exists, otherwise return an error.
+ // we will check this by resolving. If the user wants us
+ // to follow links, then we are talking about the target,
+ // hence we can use the |followSymlinks| parameter.
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!newParentDir)
+ {
+ // no parent was specified. We must rename.
+
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ rv = GetParent(getter_AddRefs(newParentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (!newParentDir)
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+
+ // make sure it exists and is a directory. Create it if not there.
+ PRBool exists;
+ newParentDir->Exists(&exists);
+ if (!exists)
+ {
+ rv = newParentDir->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ PRBool isDir;
+ newParentDir->IsDirectory(&isDir);
+ if (isDir == PR_FALSE)
+ {
+ if (followSymlinks)
+ {
+ PRBool isLink;
+ newParentDir->IsSymlink(&isLink);
+ if (isLink)
+ {
+ nsCAutoString target;
+ newParentDir->GetNativeTarget(target);
+
+ nsCOMPtr<nsILocalFile> realDest = new nsLocalFile();
+ if (realDest == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = realDest->InitWithNativePath(target);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return CopyMove(realDest, newName, followSymlinks, move);
+ }
+ }
+ else
+ {
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+ }
+ }
+ }
+
+ // check to see if we are a directory, if so enumerate it.
+
+ PRBool isDir;
+ IsDirectory(&isDir);
+ PRBool isSymlink;
+ IsSymlink(&isSymlink);
+
+ if (!isDir || (isSymlink && !followSymlinks))
+ {
+ rv = CopySingleFile(this, newParentDir, newName, followSymlinks, move);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // create a new target destination in the new parentDir;
+ nsCOMPtr<nsIFile> target;
+ rv = newParentDir->Clone(getter_AddRefs(target));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString allocatedNewName;
+ if (newName.IsEmpty())
+ {
+ PRBool isLink;
+ IsSymlink(&isLink);
+ if (isLink)
+ {
+ nsCAutoString temp;
+ GetNativeTarget(temp);
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp.get(), '\\');
+ if (leaf[0] == '\\')
+ leaf++;
+ allocatedNewName = leaf;
+ }
+ else
+ {
+ GetNativeLeafName(allocatedNewName);// this should be the leaf name of the
+ }
+ }
+ else
+ {
+ allocatedNewName = newName;
+ }
+
+ rv = target->AppendNative(allocatedNewName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ allocatedNewName.Truncate();
+
+ // check if the destination directory already exists
+ target->Exists(&exists);
+ if (!exists)
+ {
+ // if the destination directory cannot be created, return an error
+ rv = target->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // check if the destination directory is writable and empty
+ PRBool isWritable;
+
+ target->IsWritable(&isWritable);
+ if (!isWritable)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ nsCOMPtr<nsISimpleEnumerator> targetIterator;
+ rv = target->GetDirectoryEntries(getter_AddRefs(targetIterator));
+
+ PRBool more;
+ targetIterator->HasMoreElements(&more);
+ // return error if target directory is not empty
+ if (more)
+ return NS_ERROR_FILE_DIR_NOT_EMPTY;
+ }
+
+ nsDirEnumerator dirEnum;
+
+ rv = dirEnum.Init(this);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("dirEnum initalization failed");
+ return rv;
+ }
+
+ PRBool more;
+ while (NS_SUCCEEDED(dirEnum.HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsISupports> item;
+ nsCOMPtr<nsIFile> file;
+ dirEnum.GetNext(getter_AddRefs(item));
+ file = do_QueryInterface(item);
+ if (file)
+ {
+ PRBool isDir, isLink;
+
+ file->IsDirectory(&isDir);
+ file->IsSymlink(&isLink);
+
+ if (move)
+ {
+ if (followSymlinks)
+ return NS_ERROR_FAILURE;
+
+ rv = file->MoveToNative(target, nsCString());
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ else
+ {
+ if (followSymlinks)
+ rv = file->CopyToFollowingLinksNative(target, nsCString());
+ else
+ rv = file->CopyToNative(target, nsCString());
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ }
+ }
+ // we've finished moving all the children of this directory
+ // in the new directory. so now delete the directory
+ // note, we don't need to do a recursive delete.
+ // MoveTo() is recursive. At this point,
+ // we've already moved the children of the current folder
+ // to the new location. nothing should be left in the folder.
+ if (move)
+ {
+ rv = Remove(PR_FALSE /* recursive */);
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ }
+
+
+ // If we moved, we want to adjust this.
+ if (move)
+ {
+ MakeDirty();
+
+ nsCAutoString newParentPath;
+ newParentDir->GetNativePath(newParentPath);
+
+ if (newParentPath.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ GetNativeLeafName(aFileName);
+
+ InitWithNativePath(newParentPath);
+ AppendNative(aFileName);
+ }
+ else
+ {
+ InitWithNativePath(newParentPath);
+ AppendNative(newName);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_TRUE, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE, PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary * *_retval)
+{
+ PRBool isFile;
+ nsresult rv = IsFile(&isFile);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (! isFile)
+ return NS_ERROR_FILE_IS_DIRECTORY;
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+ *_retval = PR_LoadLibrary(mResolvedPath.get());
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", mResolvedPath.get());
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ // NOTE:
+ //
+ // if the working path points to a shortcut, then we will only
+ // delete the shortcut itself. even if the shortcut points to
+ // a directory, we will not recurse into that directory or
+ // delete that directory itself. likewise, if the shortcut
+ // points to a normal file, we will not delete the real file.
+ // this is done to be consistent with the other platforms that
+ // behave this way. we do this even if the followLinks attribute
+ // is set to true. this helps protect against misuse that could
+ // lead to security bugs (e.g., bug 210588).
+ //
+ // Since shortcut files are no longer permitted to be used as unix-like
+ // symlinks interspersed in the path (e.g. "c:/file.lnk/foo/bar.txt")
+ // this processing is a lot simpler. Even if the shortcut file is
+ // pointing to a directory, only the mWorkingPath value is used and so
+ // only the shortcut file will be deleted.
+
+ PRBool isDir, isLink;
+ nsresult rv;
+
+ isDir = PR_FALSE;
+ rv = IsSymlink(&isLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // only check to see if we have a directory if it isn't a link
+ if (!isLink)
+ {
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (isDir)
+ {
+ if (recursive)
+ {
+ nsDirEnumerator dirEnum;
+
+ rv = dirEnum.Init(this);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool more;
+ while (NS_SUCCEEDED(dirEnum.HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsISupports> item;
+ dirEnum.GetNext(getter_AddRefs(item));
+ nsCOMPtr<nsIFile> file = do_QueryInterface(item);
+ if (file)
+ file->Remove(recursive);
+ }
+ }
+ rv = rmdir(mWorkingPath.get());
+ }
+ else
+ {
+ rv = remove(mWorkingPath.get());
+ }
+
+ // fixup error code if necessary...
+ if (rv == (nsresult)-1)
+ rv = NSRESULT_FOR_ERRNO();
+
+ MakeDirty();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ // get the modified time of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as GetLastModifiedTimeOfLink)
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // microseconds -> milliseconds
+ PRInt64 usecPerMsec;
+ LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
+ LL_DIV(*aLastModifiedTime, mFileInfo64.modifyTime, usecPerMsec);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ PRFileInfo64 info;
+ if (PR_GetFileInfo64(mWorkingPath.get(), &info) != PR_SUCCESS)
+ return NSRESULT_FOR_ERRNO();
+
+ // microseconds -> milliseconds
+ PRInt64 usecPerMsec;
+ LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
+ LL_DIV(*aLastModifiedTime, info.modifyTime, usecPerMsec);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // set the modified time of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as SetLastModifiedTimeOfLink)
+
+ rv = SetModDate(aLastModifiedTime, mResolvedPath.get());
+ if (NS_SUCCEEDED(rv))
+ MakeDirty();
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
+{
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ nsresult rv = SetModDate(aLastModifiedTime, mWorkingPath.get());
+ if (NS_SUCCEEDED(rv))
+ MakeDirty();
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::SetModDate(PRInt64 aLastModifiedTime, const char *filePath)
+{
+ HANDLE file = CreateFile(filePath, // pointer to name of the file
+ GENERIC_WRITE, // access (write) mode
+ 0, // share mode
+ NULL, // pointer to security attributes
+ OPEN_EXISTING, // how to create
+ 0, // file attributes
+ NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ return ConvertWinError(GetLastError());
+ }
+
+ FILETIME lft, ft;
+ SYSTEMTIME st;
+ PRExplodedTime pret;
+
+ // PR_ExplodeTime expects usecs...
+ PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_LocalTimeParameters, &pret);
+ st.wYear = pret.tm_year;
+ st.wMonth = pret.tm_month + 1; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
+ st.wDayOfWeek = pret.tm_wday;
+ st.wDay = pret.tm_mday;
+ st.wHour = pret.tm_hour;
+ st.wMinute = pret.tm_min;
+ st.wSecond = pret.tm_sec;
+ st.wMilliseconds = pret.tm_usec/1000;
+
+ nsresult rv = NS_OK;
+ if ( 0 != SystemTimeToFileTime(&st, &lft)
+ || 0 != LocalFileTimeToFileTime(&lft, &ft)
+ || 0 != SetFileTime(file, NULL, &ft, &ft) )
+ {
+ rv = ConvertWinError(GetLastError());
+ }
+
+ CloseHandle(file);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG(aPermissions);
+
+ // get the permissions of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as GetPermissionsOfLink)
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool isWritable, isExecutable;
+ IsWritable(&isWritable);
+ IsExecutable(&isExecutable);
+
+ *aPermissions = PR_IRUSR|PR_IRGRP|PR_IROTH; // all read
+ if (isWritable)
+ *aPermissions |= PR_IWUSR|PR_IWGRP|PR_IWOTH; // all write
+ if (isExecutable)
+ *aPermissions |= PR_IXUSR|PR_IXGRP|PR_IXOTH; // all execute
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG(aPermissions);
+
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link. It is not
+ // possible for a link file to be executable.
+
+ DWORD word = GetFileAttributes(mWorkingPath.get());
+ if (word == INVALID_FILE_ATTRIBUTES)
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ PRBool isWritable = !(word & FILE_ATTRIBUTE_READONLY);
+ *aPermissions = PR_IRUSR|PR_IRGRP|PR_IROTH; // all read
+ if (isWritable)
+ *aPermissions |= PR_IWUSR|PR_IWGRP|PR_IWOTH; // all write
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ // set the permissions of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as SetPermissionsOfLink)
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // windows only knows about the following permissions
+ int mode = 0;
+ if (aPermissions & (PR_IRUSR|PR_IRGRP|PR_IROTH)) // any read
+ mode |= _S_IREAD;
+ if (aPermissions & (PR_IWUSR|PR_IWGRP|PR_IWOTH)) // any write
+ mode |= _S_IWRITE;
+
+ if (chmod(mResolvedPath.get(), mode) == -1)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ // windows only knows about the following permissions
+ int mode = 0;
+ if (aPermissions & (PR_IRUSR|PR_IRGRP|PR_IROTH)) // any read
+ mode |= _S_IREAD;
+ if (aPermissions & (PR_IWUSR|PR_IWGRP|PR_IWOTH)) // any write
+ mode |= _S_IWRITE;
+
+ if (chmod(mWorkingPath.get(), mode) == -1)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aFileSize = mFileInfo64.size;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ PRFileInfo64 info;
+ if (!PR_GetFileInfo64(mWorkingPath.get(), &info))
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ *aFileSize = info.size;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ HANDLE hFile = CreateFile(mResolvedPath.get(), // pointer to name of the file
+ GENERIC_WRITE, // access (write) mode
+ FILE_SHARE_READ, // share mode
+ NULL, // pointer to security attributes
+ OPEN_EXISTING, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return ConvertWinError(GetLastError());
+ }
+
+ // seek the file pointer to the new, desired end of file
+ // and then truncate the file at that position
+ rv = NS_ERROR_FAILURE;
+ aFileSize = MyFileSeek64(hFile, aFileSize, FILE_BEGIN);
+ if (aFileSize != -1 && SetEndOfFile(hFile))
+ {
+ MakeDirty();
+ rv = NS_OK;
+ }
+
+ CloseHandle(hFile);
+ return rv;
+}
+
+typedef BOOL (WINAPI *fpGetDiskFreeSpaceExA)(LPCTSTR lpDirectoryName,
+ PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+ PULARGE_INTEGER lpTotalNumberOfBytes,
+ PULARGE_INTEGER lpTotalNumberOfFreeBytes);
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG(aDiskSpaceAvailable);
+
+ ResolveAndStat();
+
+ // Attempt to check disk space using the GetDiskFreeSpaceExA function.
+ // --- FROM MSDN ---
+ // The GetDiskFreeSpaceEx function is available beginning with Windows 95 OEM Service
+ // Release 2 (OSR2). To determine whether GetDiskFreeSpaceEx is available, call
+ // GetModuleHandle to get the handle to Kernel32.dll. Then you can call GetProcAddress.
+ // It is not necessary to call LoadLibrary on Kernel32.dll because it is already loaded
+ // into every process address space.
+ fpGetDiskFreeSpaceExA pGetDiskFreeSpaceExA = (fpGetDiskFreeSpaceExA)
+ GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
+ if (pGetDiskFreeSpaceExA)
+ {
+ ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes;
+ if (pGetDiskFreeSpaceExA(mResolvedPath.get(), &liFreeBytesAvailableToCaller,
+ &liTotalNumberOfBytes, NULL))
+ {
+ *aDiskSpaceAvailable = liFreeBytesAvailableToCaller.QuadPart;
+ return NS_OK;
+ }
+ }
+
+ // use the old method of getting available disk space
+ char aDrive[_MAX_DRIVE + 2];
+ _splitpath( mResolvedPath.get(), aDrive, NULL, NULL, NULL);
+ strcat(aDrive, "\\");
+
+ DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
+ if (GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
+ {
+ __int64 bytes = dwFreeClus;
+ bytes *= dwSecPerClus;
+ bytes *= dwBytesPerSec;
+
+ *aDiskSpaceAvailable = bytes;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+
+ nsCAutoString parentPath(mWorkingPath);
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr((const unsigned char *) parentPath.get(), '\\')
+ - (const unsigned char *) parentPath.get());
+ // adding this offset check that was removed in bug 241708 fixes mail
+ // directories that aren't relative to/underneath the profile dir.
+ // e.g., on a different drive. Before you remove them, please make
+ // sure local mail directories that aren't underneath the profile dir work.
+ if (offset < 0)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ if (offset == 1 && parentPath[0] == '\\') {
+ aParent = nsnull;
+ return NS_OK;
+ }
+ if (offset > 0)
+ parentPath.Truncate(offset);
+ else
+ parentPath.AssignLiteral("\\\\.");
+
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_NewNativeLocalFile(parentPath, mFollowSymlinks, getter_AddRefs(localFile));
+
+ if(NS_SUCCEEDED(rv) && localFile)
+ {
+ return CallQueryInterface(localFile, aParent);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ MakeDirty();
+ nsresult rv = ResolveAndStat();
+ *_retval = NS_SUCCEEDED(rv);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *aIsWritable)
+{
+ //TODO: extend to support NTFS file permissions
+
+ // The read-only attribute on a FAT directory only means that it can't
+ // be deleted. It is still possible to modify the contents of the directory.
+ nsresult rv = IsDirectory(aIsWritable);
+ if (NS_FAILED(rv))
+ return rv;
+ if (*aIsWritable)
+ return NS_OK;
+
+ // writable if the file doesn't have the readonly attribute
+ rv = HasFileAttribute(FILE_ATTRIBUTE_READONLY, aIsWritable);
+ if (NS_FAILED(rv))
+ return rv;
+ *aIsWritable = !*aIsWritable;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv;
+
+ // only files can be executables
+ PRBool isFile;
+ rv = IsFile(&isFile);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isFile)
+ return NS_OK;
+
+ //TODO: shouldn't we be checking mFollowSymlinks here?
+ PRBool symLink;
+ rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString path;
+ if (symLink)
+ GetNativeTarget(path);
+ else
+ GetNativePath(path);
+
+ // Get extension.
+ char * ext = (char *) _mbsrchr((unsigned char *)path.BeginWriting(), '.');
+ if ( ext ) {
+ // Convert extension to lower case.
+ for( unsigned char *p = (unsigned char *)ext; *p; p++ )
+ *p = _mbctolower( *p );
+
+ // Search for any of the set of executable extensions.
+ const char * const executableExts[] = {
+ ".ad",
+ ".adp",
+ ".asp",
+ ".bas",
+ ".bat",
+ ".chm",
+ ".cmd",
+ ".com",
+ ".cpl",
+ ".crt",
+ ".exe",
+ ".hlp",
+ ".hta",
+ ".inf",
+ ".ins",
+ ".isp",
+ ".js",
+ ".jse",
+ ".lnk",
+ ".mdb",
+ ".mde",
+ ".msc",
+ ".msi",
+ ".msp",
+ ".mst",
+ ".pcd",
+ ".pif",
+ ".reg",
+ ".scr",
+ ".sct",
+ ".shb",
+ ".shs",
+ ".url",
+ ".vb",
+ ".vbe",
+ ".vbs",
+ ".vsd",
+ ".vss",
+ ".vst",
+ ".vsw",
+ ".ws",
+ ".wsc",
+ ".wsf",
+ ".wsh",
+ 0 };
+ for ( int i = 0; executableExts[i]; i++ ) {
+ if ( ::strcmp( executableExts[i], ext ) == 0 ) {
+ // Found a match. Set result and quit.
+ *_retval = PR_TRUE;
+ break;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_DIRECTORY);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_FILE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ return HasFileAttribute(FILE_ATTRIBUTE_HIDDEN, _retval);
+}
+
+nsresult
+nsLocalFile::HasFileAttribute(DWORD fileAttrib, PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the file attributes for the correct item depending on following symlinks
+ const char *filePath = mFollowSymlinks ? mResolvedPath.get() : mWorkingPath.get();
+ DWORD word = GetFileAttributes(filePath);
+
+ *_retval = ((word & fileAttrib) != 0);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ // unless it is a valid shortcut path it's not a symlink
+ if (!IsShortcutPath(mWorkingPath.get()))
+ {
+ *_retval = PR_FALSE;
+ return NS_OK;
+ }
+
+ // we need to know if this is a file or directory
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // it's only a shortcut if it is a file
+ *_retval = (mFileInfo64.type == PR_FILE_FILE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ return HasFileAttribute(FILE_ATTRIBUTE_SYSTEM, _retval);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG(_retval);
+
+ nsCAutoString inFilePath;
+ inFile->GetNativePath(inFilePath);
+
+ *_retval = inFilePath.Equals(mWorkingPath);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ nsCAutoString myFilePath;
+ if ( NS_FAILED(GetNativeTarget(myFilePath)))
+ GetNativePath(myFilePath);
+
+ PRInt32 myFilePathLen = myFilePath.Length();
+
+ nsCAutoString inFilePath;
+ if ( NS_FAILED(inFile->GetNativeTarget(inFilePath)))
+ inFile->GetNativePath(inFilePath);
+
+ if ( strnicmp( myFilePath.get(), inFilePath.get(), myFilePathLen) == 0)
+ {
+ // now make sure that the |inFile|'s path has a trailing
+ // separator.
+
+ if (inFilePath[myFilePathLen] == '\\')
+ {
+ *_retval = PR_TRUE;
+ }
+
+ }
+
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ _retval.Truncate();
+#if STRICT_FAKE_SYMLINKS
+ PRBool symLink;
+
+ nsresult rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!symLink)
+ {
+ return NS_ERROR_FILE_INVALID_PATH;
+ }
+#endif
+ ResolveAndStat();
+
+ _retval = mResolvedPath;
+ return NS_OK;
+}
+
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ *aFollowLinks = mFollowSymlinks;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ MakeDirty();
+ mFollowSymlinks = aFollowLinks;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
+{
+ nsresult rv;
+
+ *entries = nsnull;
+ if (mWorkingPath.EqualsLiteral("\\\\.")) {
+ nsDriveEnumerator *drives = new nsDriveEnumerator;
+ if (!drives)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(drives);
+ rv = drives->Init();
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(drives);
+ return rv;
+ }
+ *entries = drives;
+ return NS_OK;
+ }
+
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+
+ *entries = dirEnum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ return GetNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ return InitWithNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ // make sure mResolvedPath is set
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ // use the full path to explorer for security
+ nsCOMPtr<nsILocalFile> winDir;
+ rv = GetSpecialSystemDirectory(Win_WindowsDirectory, getter_AddRefs(winDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCAutoString explorerPath;
+ rv = winDir->GetNativePath(explorerPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+ explorerPath.Append("\\explorer.exe");
+
+ // Always open a new window for files because Win2K doesn't appear to select
+ // the file if a window showing that folder was already open. If the resolved
+ // path is a directory then instead of opening the parent and selecting it,
+ // we open the directory itself.
+ nsCAutoString explorerParams;
+ if (mFileInfo64.type != PR_FILE_DIRECTORY) // valid because we ResolveAndStat above
+ explorerParams.Append("/n,/select,");
+ explorerParams.Append('\"');
+ explorerParams.Append(mResolvedPath);
+ explorerParams.Append('\"');
+
+ if (::ShellExecute(NULL, "open", explorerPath.get(), explorerParams.get(),
+ NULL, SW_SHOWNORMAL) <= (HINSTANCE) 32)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ const nsCString &path = mWorkingPath;
+
+ // use the app registry name to launch a shell execute....
+ LONG r = (LONG) ::ShellExecute( NULL, NULL, path.get(), NULL, NULL, SW_SHOWNORMAL);
+
+ // if the file has no association, we launch windows' "what do you want to do" dialog
+ if (r == SE_ERR_NOASSOC) {
+ nsCAutoString shellArg;
+ shellArg.Assign(NS_LITERAL_CSTRING("shell32.dll,OpenAs_RunDLL ") + path);
+ r = (LONG) ::ShellExecute(NULL, NULL, "RUNDLL32.EXE", shellArg.get(),
+ NULL, SW_SHOWNORMAL);
+ }
+ if (r < 32) {
+ switch (r) {
+ case 0:
+ case SE_ERR_OOM:
+ return NS_ERROR_OUT_OF_MEMORY;
+ case ERROR_FILE_NOT_FOUND:
+ return NS_ERROR_FILE_NOT_FOUND;
+ case ERROR_PATH_NOT_FOUND:
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ case ERROR_BAD_FORMAT:
+ return NS_ERROR_FILE_CORRUPTED;
+ case SE_ERR_ACCESSDENIED:
+ return NS_ERROR_FILE_ACCESS_DENIED;
+ case SE_ERR_ASSOCINCOMPLETE:
+ case SE_ERR_NOASSOC:
+ return NS_ERROR_UNEXPECTED;
+ case SE_ERR_DDEBUSY:
+ case SE_ERR_DDEFAIL:
+ case SE_ERR_DDETIMEOUT:
+ return NS_ERROR_NOT_AVAILABLE;
+ case SE_ERR_DLLNOTFOUND:
+ return NS_ERROR_FAILURE;
+ case SE_ERR_SHARE:
+ return NS_ERROR_FILE_IS_LOCKED;
+ default:
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+ }
+ }
+ return NS_OK;
+}
+
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+
+ *result = file;
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// UCS2 interface
+//-----------------------------------------------------------------------------
+
+nsresult
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(filePath, tmp);
+ if (NS_SUCCEEDED(rv))
+ return InitWithNativePath(tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::Append(const nsAString &node)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+ if (NS_SUCCEEDED(rv))
+ return AppendNative(tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::AppendRelativePath(const nsAString &node)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+ if (NS_SUCCEEDED(rv))
+ return AppendRelativeNativePath(tmp);
+ return rv;
+}
+
+nsresult
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeLeafName(tmp);
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, aLeafName);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return SetNativeLeafName(tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ return NS_CopyNativeToUnicode(mWorkingPath, _retval);
+}
+
+nsresult
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return CopyToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToFollowingLinksNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return CopyToFollowingLinksNative(newParentDir, tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return MoveToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return MoveToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeTarget(tmp);
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, _retval);
+
+ return rv;
+}
+
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString buf;
+ nsresult rv = NS_CopyUnicodeToNative(path, buf);
+ if (NS_FAILED(rv)) {
+ *result = nsnull;
+ return rv;
+ }
+ return NS_NewNativeLocalFile(buf, followLinks, result);
+}
+
+//-----------------------------------------------------------------------------
+// nsLocalFile <static members>
+//-----------------------------------------------------------------------------
+
+void
+nsLocalFile::GlobalInit()
+{
+ nsresult rv = NS_CreateShortcutResolver();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Shortcut resolver could not be created");
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+ NS_DestroyShortcutResolver();
+}
+
+NS_IMPL_ISUPPORTS1(nsDriveEnumerator, nsISimpleEnumerator)
+
+nsDriveEnumerator::nsDriveEnumerator()
+ : mLetter(0)
+{
+}
+
+nsDriveEnumerator::~nsDriveEnumerator()
+{
+}
+
+nsresult nsDriveEnumerator::Init()
+{
+ /* If the length passed to GetLogicalDriveStrings is smaller
+ * than the length of the string it would return, it returns
+ * the length required for the string. */
+ DWORD length = GetLogicalDriveStrings(0, 0);
+ /* The string is null terminated */
+ mDrives.SetLength(length+1);
+ if (!GetLogicalDriveStrings(length, mDrives.BeginWriting()))
+ return NS_ERROR_FAILURE;
+ mLetter = mDrives.get();
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsDriveEnumerator::HasMoreElements(PRBool *aHasMore)
+{
+ *aHasMore = *mLetter != '\0';
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsDriveEnumerator::GetNext(nsISupports **aNext)
+{
+ /* GetLogicalDrives stored in mLetter is a concatenation
+ * of null terminated strings, followed by a null terminator. */
+ if (!*mLetter) {
+ *aNext = nsnull;
+ return NS_OK;
+ }
+ const char *drive = mLetter;
+ mLetter += strlen(drive) + 1;
+ nsILocalFile *file;
+ nsresult rv =
+ NS_NewNativeLocalFile(nsDependentCString(drive), PR_FALSE, &file);
+
+ *aNext = file;
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h
new file mode 100644
index 00000000..0ef1d9f0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * Brodie Thiesfield <brofield@jellycan.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _nsLocalFileWIN_H_
+#define _nsLocalFileWIN_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsIFactory.h"
+
+#include "windows.h"
+
+// For older version (<6.0) of the VC Compiler
+#if (_MSC_VER == 1100)
+#include <objbase.h>
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
+#endif
+
+#include "shlobj.h"
+
+#include <sys/stat.h>
+
+class nsLocalFile : public nsILocalFile
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIFile interface
+ NS_DECL_NSIFILE
+
+ // nsILocalFile interface
+ NS_DECL_NSILOCALFILE
+
+public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ nsLocalFile(const nsLocalFile& other);
+ ~nsLocalFile() {}
+
+ PRPackedBool mDirty; // cached information can only be used when this is PR_FALSE
+ PRPackedBool mFollowSymlinks; // should we follow symlinks when working on this file
+
+ // this string will always be in native format!
+ nsCString mWorkingPath;
+
+ // this will be the resolved path of shortcuts, it will *NEVER* be returned to the user
+ nsCString mResolvedPath;
+
+ PRFileInfo64 mFileInfo64;
+
+ void MakeDirty() { mDirty = PR_TRUE; }
+
+ nsresult ResolveAndStat();
+ nsresult ResolveShortcut();
+
+ nsresult CopyMove(nsIFile *newParentDir, const nsACString &newName, PRBool followSymlinks, PRBool move);
+ nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const nsACString &newName, PRBool followSymlinks, PRBool move);
+
+ nsresult SetModDate(PRInt64 aLastModifiedTime, const char *filePath);
+ nsresult HasFileAttribute(DWORD fileAttrib, PRBool *_retval);
+ nsresult AppendNativeInternal(const nsAFlatCString &node, PRBool multipleComponents);
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp
new file mode 100644
index 00000000..ba04a842
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is frightening to behold.
+ *
+ * The Initial Developer of the Original Code is
+ * Jonas Sicking.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jonas Sicking <sicking@bigfoot.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 ***** */
+
+/**
+ * The multiplex stream concatenates a list of input streams into a single
+ * stream.
+ */
+
+#include "nsMultiplexInputStream.h"
+#include "nsIMultiplexInputStream.h"
+#include "nsISeekableStream.h"
+#include "nsSupportsArray.h"
+#include "nsInt64.h"
+
+class nsMultiplexInputStream : public nsIMultiplexInputStream,
+ public nsISeekableStream
+{
+public:
+ nsMultiplexInputStream();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIMULTIPLEXINPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+
+ static NS_METHOD Create(nsISupports *outer, REFNSIID iid, void **result);
+
+private:
+ ~nsMultiplexInputStream() {}
+
+
+ struct ReadSegmentsState {
+ nsIInputStream* mThisStream;
+ PRUint32 mOffset;
+ nsWriteSegmentFun mWriter;
+ void* mClosure;
+ PRBool mDone;
+ };
+
+ static NS_METHOD ReadSegCb(nsIInputStream* aIn, void* aClosure,
+ const char* aFromRawSegment, PRUint32 aToOffset,
+ PRUint32 aCount, PRUint32 *aWriteCount);
+
+ nsSupportsArray mStreams;
+ PRUint32 mCurrentStream;
+ PRBool mStartedReadingCurrent;
+};
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsMultiplexInputStream,
+ nsIMultiplexInputStream,
+ nsIInputStream,
+ nsISeekableStream)
+
+nsMultiplexInputStream::nsMultiplexInputStream()
+ : mCurrentStream(0),
+ mStartedReadingCurrent(PR_FALSE)
+{
+}
+
+/* readonly attribute unsigned long count; */
+NS_IMETHODIMP
+nsMultiplexInputStream::GetCount(PRUint32 *aCount)
+{
+ mStreams.Count(aCount);
+ return NS_OK;
+}
+
+/* void appendStream (in nsIInputStream stream); */
+NS_IMETHODIMP
+nsMultiplexInputStream::AppendStream(nsIInputStream *aStream)
+{
+ return mStreams.AppendElement(aStream);
+}
+
+/* void insertStream (in nsIInputStream stream, in unsigned long index); */
+NS_IMETHODIMP
+nsMultiplexInputStream::InsertStream(nsIInputStream *aStream, PRUint32 aIndex)
+{
+ nsresult rv = mStreams.InsertElementAt(aStream, aIndex);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (mCurrentStream > aIndex ||
+ (mCurrentStream == aIndex && mStartedReadingCurrent))
+ ++mCurrentStream;
+ return rv;
+}
+
+/* void removeStream (in unsigned long index); */
+NS_IMETHODIMP
+nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
+{
+ nsresult rv = mStreams.RemoveElementAt(aIndex);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (mCurrentStream > aIndex)
+ --mCurrentStream;
+ else if (mCurrentStream == aIndex)
+ mStartedReadingCurrent = PR_FALSE;
+
+ return rv;
+}
+
+/* nsIInputStream getStream (in unsigned long index); */
+NS_IMETHODIMP
+nsMultiplexInputStream::GetStream(PRUint32 aIndex, nsIInputStream **_retval)
+{
+ return mStreams.QueryElementAt(aIndex,
+ NS_GET_IID(nsIInputStream),
+ (void**)_retval);
+}
+
+/* void close (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Close()
+{
+ PRUint32 len, i;
+ nsresult rv = NS_OK;
+
+ mStreams.Count(&len);
+ for (i = 0; i < len; ++i) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
+ nsresult rv2 = stream->Close();
+ // We still want to close all streams, but we should return an error
+ if (NS_FAILED(rv2))
+ rv = rv2;
+ }
+ return rv;
+}
+
+/* unsigned long available (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Available(PRUint32 *_retval)
+{
+ nsresult rv;
+ PRUint32 i, len, avail = 0;
+
+ mStreams.Count(&len);
+ for (i = mCurrentStream; i < len; i++) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
+
+ PRUint32 streamAvail;
+ rv = stream->Available(&streamAvail);
+ NS_ENSURE_SUCCESS(rv, rv);
+ avail += streamAvail;
+ }
+ *_retval = avail;
+ return NS_OK;
+}
+
+/* [noscript] unsigned long read (in charPtr buf, in unsigned long count); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
+{
+ nsresult rv = NS_OK;
+ PRUint32 len, read;
+
+ *_retval = 0;
+
+ mStreams.Count(&len);
+ while (mCurrentStream < len && aCount) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
+ mCurrentStream));
+ rv = stream->Read(aBuf, aCount, &read);
+
+ // XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ rv = NS_OK;
+ read = 0;
+ }
+ else if (NS_FAILED(rv))
+ break;
+
+ if (read == 0) {
+ ++mCurrentStream;
+ mStartedReadingCurrent = PR_FALSE;
+ }
+ else {
+ NS_ASSERTION(aCount >= read, "Read more than requested");
+ *_retval += read;
+ aCount -= read;
+ aBuf += read;
+ mStartedReadingCurrent = PR_TRUE;
+ }
+ }
+ return *_retval ? NS_OK : rv;
+}
+
+/* [noscript] unsigned long readSegments (in nsWriteSegmentFun writer,
+ * in voidPtr closure,
+ * in unsigned long count); */
+NS_IMETHODIMP
+nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
+ PRUint32 aCount, PRUint32 *_retval)
+{
+ NS_ASSERTION(aWriter, "missing aWriter");
+
+ nsresult rv = NS_OK;
+ ReadSegmentsState state;
+ state.mThisStream = this;
+ state.mOffset = 0;
+ state.mWriter = aWriter;
+ state.mClosure = aClosure;
+ state.mDone = PR_FALSE;
+
+ PRUint32 len;
+ mStreams.Count(&len);
+ while (mCurrentStream < len && aCount) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
+ mCurrentStream));
+ PRUint32 read;
+ rv = stream->ReadSegments(ReadSegCb, &state, aCount, &read);
+
+ // XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ rv = NS_OK;
+ read = 0;
+ }
+
+ // if |aWriter| decided to stop reading segments...
+ if (state.mDone || NS_FAILED(rv))
+ break;
+
+ // if stream is empty, then advance to the next stream.
+ if (read == 0) {
+ ++mCurrentStream;
+ mStartedReadingCurrent = PR_FALSE;
+ }
+ else {
+ NS_ASSERTION(aCount >= read, "Read more than requested");
+ state.mOffset += read;
+ aCount -= read;
+ mStartedReadingCurrent = PR_TRUE;
+ }
+ }
+
+ // if we successfully read some data, then this call succeeded.
+ *_retval = state.mOffset;
+ return state.mOffset ? NS_OK : rv;
+}
+
+NS_METHOD
+nsMultiplexInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
+ const char* aFromRawSegment,
+ PRUint32 aToOffset, PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ nsresult rv;
+ ReadSegmentsState* state = (ReadSegmentsState*)aClosure;
+ rv = (state->mWriter)(state->mThisStream,
+ state->mClosure,
+ aFromRawSegment,
+ aToOffset + state->mOffset,
+ aCount,
+ aWriteCount);
+ if (NS_FAILED(rv))
+ state->mDone = PR_TRUE;
+ return rv;
+}
+
+/* readonly attribute boolean nonBlocking; */
+NS_IMETHODIMP
+nsMultiplexInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ nsresult rv;
+ PRUint32 i, len;
+
+ mStreams.Count(&len);
+ for (i = 0; i < len; ++i) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
+ rv = stream->IsNonBlocking(aNonBlocking);
+ NS_ENSURE_SUCCESS(rv, rv);
+ // If one is non-blocking the entire stream becomes non-blocking
+ if (*aNonBlocking)
+ return NS_OK;
+ }
+ return NS_OK;
+}
+
+/* void seek (in PRInt32 whence, in PRInt32 offset); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ nsresult rv;
+
+ // rewinding to start is easy, and should be the most common case
+ if (aWhence == NS_SEEK_SET && aOffset == 0)
+ {
+ PRUint32 i, last;
+ last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
+ for (i = 0; i < last; ++i) {
+ nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
+ NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
+
+ rv = stream->Seek(NS_SEEK_SET, 0);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ mCurrentStream = 0;
+ mStartedReadingCurrent = PR_FALSE;
+ return NS_OK;
+ }
+
+ // other Seeks not implemented yet
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 tell (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Tell(PRInt64 *_retval)
+{
+ nsresult rv;
+ nsInt64 ret64 = 0;
+ PRUint32 i, last;
+ last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
+ for (i = 0; i < last; ++i) {
+ nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
+ NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
+
+ PRInt64 pos;
+ rv = stream->Tell(&pos);
+ NS_ENSURE_SUCCESS(rv, rv);
+ ret64 += pos;
+ }
+ *_retval = ret64;
+
+ return NS_OK;
+}
+
+/* void setEOF (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::SetEOF()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD
+nsMultiplexInputStreamConstructor(nsISupports *outer,
+ REFNSIID iid,
+ void **result)
+{
+ *result = nsnull;
+
+ if (outer)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsMultiplexInputStream *inst;
+ NS_NEWXPCOM(inst, nsMultiplexInputStream);
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(inst);
+ nsresult rv = inst->QueryInterface(iid, result);
+ NS_RELEASE(inst);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h
new file mode 100644
index 00000000..32d3026d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is frightening to behold.
+ *
+ * The Initial Developer of the Original Code is
+ * Jonas Sicking.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jonas Sicking <sicking@bigfoot.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 ***** */
+
+/**
+ * The multiplex stream concatinates a list of input streams into a single
+ * stream.
+ */
+
+#ifndef _nsMultiplexInputStream_h_
+#define _nsMultiplexInputStream_h_
+
+#include "nsIMultiplexInputStream.h"
+
+#define NS_MULTIPLEXINPUTSTREAM_CLASSNAME "nsMultiplexInputStream"
+#define NS_MULTIPLEXINPUTSTREAM_CONTRACTID "@mozilla.org/io/multiplex-input-stream;1"
+#define NS_MULTIPLEXINPUTSTREAM_CID \
+{ /* 565e3a2c-1dd2-11b2-8da1-b4cef17e568d */ \
+ 0x565e3a2c, \
+ 0x1dd2, \
+ 0x11b2, \
+ {0x8d, 0xa1, 0xb4, 0xce, 0xf1, 0x7e, 0x56, 0x8d} \
+}
+
+extern NS_METHOD nsMultiplexInputStreamConstructor(nsISupports *outer,
+ REFNSIID iid,
+ void **result);
+
+#endif // _nsMultiplexInputStream_h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp
new file mode 100644
index 00000000..55b5c63c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp
@@ -0,0 +1,1280 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com>
+ * Brian Stell <bstell@ix.netcom.com>
+ * Frank Tang <ftang@netscape.com>
+ * Brendan Eich <brendan@mozilla.org>
+ * Sergei Dolgov <sergei_d@fi.fi.tartu.ee>
+ *
+ * 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 "xpcom-private.h"
+
+//-----------------------------------------------------------------------------
+// XP_UNIX
+//-----------------------------------------------------------------------------
+#if defined(XP_UNIX)
+
+#include <stdlib.h> // mbtowc, wctomb
+#include <locale.h> // setlocale
+#include "nscore.h"
+#include "prlock.h"
+#include "nsAString.h"
+#include "nsReadableUtils.h"
+
+//
+// choose a conversion library. we used to use mbrtowc/wcrtomb under Linux,
+// but that doesn't work for non-BMP characters whether we use '-fshort-wchar'
+// or not (see bug 206811 and
+// news://news.mozilla.org:119/bajml3$fvr1@ripley.netscape.com). we now use
+// iconv for all platforms where nltypes.h and nllanginfo.h are present
+// along with iconv.
+//
+#if defined(HAVE_ICONV) && defined(HAVE_NL_TYPES_H) && defined(HAVE_LANGINFO_CODESET)
+#define USE_ICONV 1
+#else
+#define USE_STDCONV 1
+#endif
+
+static void
+isolatin1_to_utf16(const char **input, PRUint32 *inputLeft, PRUnichar **output, PRUint32 *outputLeft)
+{
+ while (*inputLeft && *outputLeft) {
+ **output = (unsigned char) **input;
+ (*input)++;
+ (*inputLeft)--;
+ (*output)++;
+ (*outputLeft)--;
+ }
+}
+
+static void
+utf16_to_isolatin1(const PRUnichar **input, PRUint32 *inputLeft, char **output, PRUint32 *outputLeft)
+{
+ while (*inputLeft && *outputLeft) {
+ **output = (unsigned char) **input;
+ (*input)++;
+ (*inputLeft)--;
+ (*output)++;
+ (*outputLeft)--;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// conversion using iconv
+//-----------------------------------------------------------------------------
+#if defined(USE_ICONV)
+#include <nl_types.h> // CODESET
+#include <langinfo.h> // nl_langinfo
+#include <iconv.h> // iconv_open, iconv, iconv_close
+#include <errno.h>
+
+#if defined(HAVE_ICONV_WITH_CONST_INPUT)
+#define ICONV_INPUT(x) (x)
+#else
+#define ICONV_INPUT(x) ((char **)x)
+#endif
+
+// solaris definitely needs this, but we'll enable it by default
+// just in case... but we know for sure that iconv(3) in glibc
+// doesn't need this.
+#if !defined(__GLIBC__)
+#define ENABLE_UTF8_FALLBACK_SUPPORT
+#endif
+
+#define INVALID_ICONV_T ((iconv_t) -1)
+
+static inline size_t
+xp_iconv(iconv_t converter,
+ const char **input,
+ size_t *inputLeft,
+ char **output,
+ size_t *outputLeft)
+{
+ size_t res, outputAvail = outputLeft ? *outputLeft : 0;
+ res = iconv(converter, ICONV_INPUT(input), inputLeft, output, outputLeft);
+ if (res == (size_t) -1) {
+ // on some platforms (e.g., linux) iconv will fail with
+ // E2BIG if it cannot convert _all_ of its input. it'll
+ // still adjust all of the in/out params correctly, so we
+ // can ignore this error. the assumption is that we will
+ // be called again to complete the conversion.
+ if ((errno == E2BIG) && (*outputLeft < outputAvail))
+ res = 0;
+ }
+ return res;
+}
+
+static inline void
+xp_iconv_reset(iconv_t converter)
+{
+ // NOTE: the man pages on Solaris claim that you can pass NULL
+ // for all parameter to reset the converter, but beware the
+ // evil Solaris crash if you go down this route >:-)
+
+ const char *zero_char_in_ptr = NULL;
+ char *zero_char_out_ptr = NULL;
+ size_t zero_size_in = 0,
+ zero_size_out = 0;
+
+ xp_iconv(converter, &zero_char_in_ptr,
+ &zero_size_in,
+ &zero_char_out_ptr,
+ &zero_size_out);
+}
+
+static inline iconv_t
+xp_iconv_open(const char **to_list, const char **from_list)
+{
+ iconv_t res;
+ const char **from_name;
+ const char **to_name;
+
+ // try all possible combinations to locate a converter.
+ to_name = to_list;
+ while (*to_name) {
+ if (**to_name) {
+ from_name = from_list;
+ while (*from_name) {
+ if (**from_name) {
+ res = iconv_open(*to_name, *from_name);
+ if (res != INVALID_ICONV_T)
+ return res;
+ }
+ from_name++;
+ }
+ }
+ to_name++;
+ }
+
+ return INVALID_ICONV_T;
+}
+
+/*
+ * PRUnichar[] is NOT a UCS-2 array BUT a UTF-16 string. Therefore, we
+ * have to use UTF-16 with iconv(3) on platforms where it's supported.
+ * However, the way UTF-16 and UCS-2 are interpreted varies across platforms
+ * and implementations of iconv(3). On Tru64, it also depends on the environment
+ * variable. To avoid the trouble arising from byte-swapping
+ * (bug 208809), we have to try UTF-16LE/BE and UCS-2LE/BE before falling
+ * back to UTF-16 and UCS-2 and variants. We assume that UTF-16 and UCS-2
+ * on systems without UTF-16LE/BE and UCS-2LE/BE have the native endianness,
+ * which isn't the case of glibc 2.1.x, for which we use 'UNICODELITTLE'
+ * and 'UNICODEBIG'. It's also not true of Tru64 V4 when the environment
+ * variable ICONV_BYTEORDER is set to 'big-endian', about which not much
+ * can be done other than adding a note in the release notes. (bug 206811)
+ */
+static const char *UTF_16_NAMES[] = {
+#if defined(IS_LITTLE_ENDIAN)
+ "UTF-16LE",
+#if defined(__GLIBC__)
+ "UNICODELITTLE",
+#endif
+ "UCS-2LE",
+#else
+ "UTF-16BE",
+#if defined(__GLIBC__)
+ "UNICODEBIG",
+#endif
+ "UCS-2BE",
+#endif
+ "UTF-16",
+ "UCS-2",
+ "UCS2",
+ "UCS_2",
+ "ucs-2",
+ "ucs2",
+ "ucs_2",
+ NULL
+};
+
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+static const char *UTF_8_NAMES[] = {
+ "UTF-8",
+ "UTF8",
+ "UTF_8",
+ "utf-8",
+ "utf8",
+ "utf_8",
+ NULL
+};
+#endif
+
+static const char *ISO_8859_1_NAMES[] = {
+ "ISO-8859-1",
+#if !defined(__GLIBC__)
+ "ISO8859-1",
+ "ISO88591",
+ "ISO_8859_1",
+ "ISO8859_1",
+ "iso-8859-1",
+ "iso8859-1",
+ "iso88591",
+ "iso_8859_1",
+ "iso8859_1",
+#endif
+ NULL
+};
+
+class nsNativeCharsetConverter
+{
+public:
+ nsNativeCharsetConverter();
+ ~nsNativeCharsetConverter();
+
+ nsresult NativeToUnicode(const char **input , PRUint32 *inputLeft,
+ PRUnichar **output, PRUint32 *outputLeft);
+ nsresult UnicodeToNative(const PRUnichar **input , PRUint32 *inputLeft,
+ char **output, PRUint32 *outputLeft);
+
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ static iconv_t gNativeToUnicode;
+ static iconv_t gUnicodeToNative;
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ static iconv_t gNativeToUTF8;
+ static iconv_t gUTF8ToNative;
+ static iconv_t gUnicodeToUTF8;
+ static iconv_t gUTF8ToUnicode;
+#endif
+ static PRLock *gLock;
+ static PRBool gInitialized;
+
+ static void LazyInit();
+
+ static void Lock() { if (gLock) PR_Lock(gLock); }
+ static void Unlock() { if (gLock) PR_Unlock(gLock); }
+};
+
+iconv_t nsNativeCharsetConverter::gNativeToUnicode = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUnicodeToNative = INVALID_ICONV_T;
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+iconv_t nsNativeCharsetConverter::gNativeToUTF8 = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUTF8ToNative = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUnicodeToUTF8 = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUTF8ToUnicode = INVALID_ICONV_T;
+#endif
+PRLock *nsNativeCharsetConverter::gLock = nsnull;
+PRBool nsNativeCharsetConverter::gInitialized = PR_FALSE;
+
+void
+nsNativeCharsetConverter::LazyInit()
+{
+ const char *blank_list[] = { "", NULL };
+ const char **native_charset_list = blank_list;
+ const char *native_charset = nl_langinfo(CODESET);
+ if (native_charset == nsnull) {
+ NS_ERROR("native charset is unknown");
+ // fallback to ISO-8859-1
+ native_charset_list = ISO_8859_1_NAMES;
+ }
+ else
+ native_charset_list[0] = native_charset;
+
+ gNativeToUnicode = xp_iconv_open(UTF_16_NAMES, native_charset_list);
+ gUnicodeToNative = xp_iconv_open(native_charset_list, UTF_16_NAMES);
+
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gNativeToUnicode == INVALID_ICONV_T) {
+ gNativeToUTF8 = xp_iconv_open(UTF_8_NAMES, native_charset_list);
+ gUTF8ToUnicode = xp_iconv_open(UTF_16_NAMES, UTF_8_NAMES);
+ NS_ASSERTION(gNativeToUTF8 != INVALID_ICONV_T, "no native to utf-8 converter");
+ NS_ASSERTION(gUTF8ToUnicode != INVALID_ICONV_T, "no utf-8 to utf-16 converter");
+ }
+ if (gUnicodeToNative == INVALID_ICONV_T) {
+ gUnicodeToUTF8 = xp_iconv_open(UTF_8_NAMES, UTF_16_NAMES);
+ gUTF8ToNative = xp_iconv_open(native_charset_list, UTF_8_NAMES);
+ NS_ASSERTION(gUnicodeToUTF8 != INVALID_ICONV_T, "no utf-16 to utf-8 converter");
+ NS_ASSERTION(gUTF8ToNative != INVALID_ICONV_T, "no utf-8 to native converter");
+ }
+#else
+ NS_ASSERTION(gNativeToUnicode != INVALID_ICONV_T, "no native to utf-16 converter");
+ NS_ASSERTION(gUnicodeToNative != INVALID_ICONV_T, "no utf-16 to native converter");
+#endif
+
+ /*
+ * On Solaris 8 (and newer?), the iconv modules converting to UCS-2
+ * prepend a byte order mark unicode character (BOM, u+FEFF) during
+ * the first use of the iconv converter. The same is the case of
+ * glibc 2.2.9x and Tru64 V5 (see bug 208809) when 'UTF-16' is used.
+ * However, we use 'UTF-16LE/BE' in both cases, instead so that we
+ * should be safe. But just in case...
+ *
+ * This dummy conversion gets rid of the BOMs and fixes bug 153562.
+ */
+ char dummy_input[1] = { ' ' };
+ char dummy_output[4];
+
+ if (gNativeToUnicode != INVALID_ICONV_T) {
+ const char *input = dummy_input;
+ size_t input_left = sizeof(dummy_input);
+ char *output = dummy_output;
+ size_t output_left = sizeof(dummy_output);
+
+ xp_iconv(gNativeToUnicode, &input, &input_left, &output, &output_left);
+ }
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gUTF8ToUnicode != INVALID_ICONV_T) {
+ const char *input = dummy_input;
+ size_t input_left = sizeof(dummy_input);
+ char *output = dummy_output;
+ size_t output_left = sizeof(dummy_output);
+
+ xp_iconv(gUTF8ToUnicode, &input, &input_left, &output, &output_left);
+ }
+#endif
+
+ gInitialized = PR_TRUE;
+}
+
+void
+nsNativeCharsetConverter::GlobalInit()
+{
+ gLock = PR_NewLock();
+ NS_ASSERTION(gLock, "lock creation failed");
+}
+
+void
+nsNativeCharsetConverter::GlobalShutdown()
+{
+ if (gLock) {
+ PR_DestroyLock(gLock);
+ gLock = nsnull;
+ }
+
+ if (gNativeToUnicode != INVALID_ICONV_T) {
+ iconv_close(gNativeToUnicode);
+ gNativeToUnicode = INVALID_ICONV_T;
+ }
+
+ if (gUnicodeToNative != INVALID_ICONV_T) {
+ iconv_close(gUnicodeToNative);
+ gUnicodeToNative = INVALID_ICONV_T;
+ }
+
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gNativeToUTF8 != INVALID_ICONV_T) {
+ iconv_close(gNativeToUTF8);
+ gNativeToUTF8 = INVALID_ICONV_T;
+ }
+ if (gUTF8ToNative != INVALID_ICONV_T) {
+ iconv_close(gUTF8ToNative);
+ gUTF8ToNative = INVALID_ICONV_T;
+ }
+ if (gUnicodeToUTF8 != INVALID_ICONV_T) {
+ iconv_close(gUnicodeToUTF8);
+ gUnicodeToUTF8 = INVALID_ICONV_T;
+ }
+ if (gUTF8ToUnicode != INVALID_ICONV_T) {
+ iconv_close(gUTF8ToUnicode);
+ gUTF8ToUnicode = INVALID_ICONV_T;
+ }
+#endif
+
+ gInitialized = PR_FALSE;
+}
+
+nsNativeCharsetConverter::nsNativeCharsetConverter()
+{
+ Lock();
+ if (!gInitialized)
+ LazyInit();
+}
+
+nsNativeCharsetConverter::~nsNativeCharsetConverter()
+{
+ // reset converters for next time
+ if (gNativeToUnicode != INVALID_ICONV_T)
+ xp_iconv_reset(gNativeToUnicode);
+ if (gUnicodeToNative != INVALID_ICONV_T)
+ xp_iconv_reset(gUnicodeToNative);
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gNativeToUTF8 != INVALID_ICONV_T)
+ xp_iconv_reset(gNativeToUTF8);
+ if (gUTF8ToNative != INVALID_ICONV_T)
+ xp_iconv_reset(gUTF8ToNative);
+ if (gUnicodeToUTF8 != INVALID_ICONV_T)
+ xp_iconv_reset(gUnicodeToUTF8);
+ if (gUTF8ToUnicode != INVALID_ICONV_T)
+ xp_iconv_reset(gUTF8ToUnicode);
+#endif
+ Unlock();
+}
+
+nsresult
+nsNativeCharsetConverter::NativeToUnicode(const char **input,
+ PRUint32 *inputLeft,
+ PRUnichar **output,
+ PRUint32 *outputLeft)
+{
+ size_t res = 0;
+ size_t inLeft = (size_t) *inputLeft;
+ size_t outLeft = (size_t) *outputLeft * 2;
+
+ if (gNativeToUnicode != INVALID_ICONV_T) {
+
+ res = xp_iconv(gNativeToUnicode, input, &inLeft, (char **) output, &outLeft);
+
+ *inputLeft = inLeft;
+ *outputLeft = outLeft / 2;
+ if (res != (size_t) -1)
+ return NS_OK;
+
+ NS_WARNING("conversion from native to utf-16 failed");
+
+ // reset converter
+ xp_iconv_reset(gNativeToUnicode);
+ }
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ else if ((gNativeToUTF8 != INVALID_ICONV_T) &&
+ (gUTF8ToUnicode != INVALID_ICONV_T)) {
+ // convert first to UTF8, then from UTF8 to UCS2
+ const char *in = *input;
+
+ char ubuf[1024];
+
+ // we assume we're always called with enough space in |output|,
+ // so convert many chars at a time...
+ while (inLeft) {
+ char *p = ubuf;
+ size_t n = sizeof(ubuf);
+ res = xp_iconv(gNativeToUTF8, &in, &inLeft, &p, &n);
+ if (res == (size_t) -1) {
+ NS_ERROR("conversion from native to utf-8 failed");
+ break;
+ }
+ NS_ASSERTION(outLeft > 0, "bad assumption");
+ p = ubuf;
+ n = sizeof(ubuf) - n;
+ res = xp_iconv(gUTF8ToUnicode, (const char **) &p, &n, (char **) output, &outLeft);
+ if (res == (size_t) -1) {
+ NS_ERROR("conversion from utf-8 to utf-16 failed");
+ break;
+ }
+ }
+
+ (*input) += (*inputLeft - inLeft);
+ *inputLeft = inLeft;
+ *outputLeft = outLeft / 2;
+
+ if (res != (size_t) -1)
+ return NS_OK;
+
+ // reset converters
+ xp_iconv_reset(gNativeToUTF8);
+ xp_iconv_reset(gUTF8ToUnicode);
+ }
+#endif
+
+ // fallback: zero-pad and hope for the best
+ // XXX This is lame and we have to do better.
+ isolatin1_to_utf16(input, inputLeft, output, outputLeft);
+
+ return NS_OK;
+}
+
+nsresult
+nsNativeCharsetConverter::UnicodeToNative(const PRUnichar **input,
+ PRUint32 *inputLeft,
+ char **output,
+ PRUint32 *outputLeft)
+{
+ size_t res = 0;
+ size_t inLeft = (size_t) *inputLeft * 2;
+ size_t outLeft = (size_t) *outputLeft;
+
+ if (gUnicodeToNative != INVALID_ICONV_T) {
+ res = xp_iconv(gUnicodeToNative, (const char **) input, &inLeft, output, &outLeft);
+
+ if (res != (size_t) -1) {
+ *inputLeft = inLeft / 2;
+ *outputLeft = outLeft;
+ return NS_OK;
+ }
+
+ NS_ERROR("iconv failed");
+
+ // reset converter
+ xp_iconv_reset(gUnicodeToNative);
+ }
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ else if ((gUnicodeToUTF8 != INVALID_ICONV_T) &&
+ (gUTF8ToNative != INVALID_ICONV_T)) {
+ const char *in = (const char *) *input;
+
+ char ubuf[6]; // max utf-8 char length (really only needs to be 4 bytes)
+
+ // convert one uchar at a time...
+ while (inLeft && outLeft) {
+ char *p = ubuf;
+ size_t n = sizeof(ubuf), one_uchar = sizeof(PRUnichar);
+ res = xp_iconv(gUnicodeToUTF8, &in, &one_uchar, &p, &n);
+ if (res == (size_t) -1) {
+ NS_ERROR("conversion from utf-16 to utf-8 failed");
+ break;
+ }
+ p = ubuf;
+ n = sizeof(ubuf) - n;
+ res = xp_iconv(gUTF8ToNative, (const char **) &p, &n, output, &outLeft);
+ if (res == (size_t) -1) {
+ if (errno == E2BIG) {
+ // not enough room for last uchar... back up and return.
+ in -= sizeof(PRUnichar);
+ res = 0;
+ }
+ else
+ NS_ERROR("conversion from utf-8 to native failed");
+ break;
+ }
+ inLeft -= sizeof(PRUnichar);
+ }
+
+ if (res != (size_t) -1) {
+ (*input) += (*inputLeft - inLeft/2);
+ *inputLeft = inLeft/2;
+ *outputLeft = outLeft;
+ return NS_OK;
+ }
+
+ // reset converters
+ xp_iconv_reset(gUnicodeToUTF8);
+ xp_iconv_reset(gUTF8ToNative);
+ }
+#endif
+
+ // fallback: truncate and hope for the best
+ utf16_to_isolatin1(input, inputLeft, output, outputLeft);
+
+ return NS_OK;
+}
+
+#endif // USE_ICONV
+
+//-----------------------------------------------------------------------------
+// conversion using mb[r]towc/wc[r]tomb
+//-----------------------------------------------------------------------------
+#if defined(USE_STDCONV)
+#if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
+#include <wchar.h> // mbrtowc, wcrtomb
+#endif
+
+class nsNativeCharsetConverter
+{
+public:
+ nsNativeCharsetConverter();
+
+ nsresult NativeToUnicode(const char **input , PRUint32 *inputLeft,
+ PRUnichar **output, PRUint32 *outputLeft);
+ nsresult UnicodeToNative(const PRUnichar **input , PRUint32 *inputLeft,
+ char **output, PRUint32 *outputLeft);
+
+ static void GlobalInit();
+ static void GlobalShutdown() { }
+
+private:
+ static PRBool gWCharIsUnicode;
+
+#if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
+ mbstate_t ps;
+#endif
+};
+
+PRBool nsNativeCharsetConverter::gWCharIsUnicode = PR_FALSE;
+
+nsNativeCharsetConverter::nsNativeCharsetConverter()
+{
+#if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
+ memset(&ps, 0, sizeof(ps));
+#endif
+}
+
+void
+nsNativeCharsetConverter::GlobalInit()
+{
+ // verify that wchar_t for the current locale is actually unicode.
+ // if it is not, then we should avoid calling mbtowc/wctomb and
+ // just fallback on zero-pad/truncation conversion.
+ //
+ // this test cannot be done at build time because the encoding of
+ // wchar_t may depend on the runtime locale. sad, but true!!
+ //
+ // so, if wchar_t is unicode then converting an ASCII character
+ // to wchar_t should not change its numeric value. we'll just
+ // check what happens with the ASCII 'a' character.
+ //
+ // this test is not perfect... obviously, it could yield false
+ // positives, but then at least ASCII text would be converted
+ // properly (or maybe just the 'a' character) -- oh well :(
+
+ char a = 'a';
+ unsigned int w = 0;
+
+ int res = mbtowc((wchar_t *) &w, &a, 1);
+
+ gWCharIsUnicode = (res != -1 && w == 'a');
+
+#ifdef DEBUG
+ if (!gWCharIsUnicode)
+ NS_WARNING("wchar_t is not unicode (unicode conversion will be lossy)");
+#endif
+}
+
+nsresult
+nsNativeCharsetConverter::NativeToUnicode(const char **input,
+ PRUint32 *inputLeft,
+ PRUnichar **output,
+ PRUint32 *outputLeft)
+{
+ if (gWCharIsUnicode) {
+ int incr;
+
+ // cannot use wchar_t here since it may have been redefined (e.g.,
+ // via -fshort-wchar). hopefully, sizeof(tmp) is sufficient XP.
+ unsigned int tmp = 0;
+ while (*inputLeft && *outputLeft) {
+#ifdef HAVE_MBRTOWC
+ incr = (int) mbrtowc((wchar_t *) &tmp, *input, *inputLeft, &ps);
+#else
+ // XXX is this thread-safe?
+ incr = (int) mbtowc((wchar_t *) &tmp, *input, *inputLeft);
+#endif
+ if (incr < 0) {
+ NS_WARNING("mbtowc failed: possible charset mismatch");
+ // zero-pad and hope for the best
+ tmp = (unsigned char) **input;
+ incr = 1;
+ }
+ **output = (PRUnichar) tmp;
+ (*input) += incr;
+ (*inputLeft) -= incr;
+ (*output)++;
+ (*outputLeft)--;
+ }
+ }
+ else {
+ // wchar_t isn't unicode, so the best we can do is treat the
+ // input as if it is isolatin1 :(
+ isolatin1_to_utf16(input, inputLeft, output, outputLeft);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsNativeCharsetConverter::UnicodeToNative(const PRUnichar **input,
+ PRUint32 *inputLeft,
+ char **output,
+ PRUint32 *outputLeft)
+{
+ if (gWCharIsUnicode) {
+ int incr;
+
+ while (*inputLeft && *outputLeft >= MB_CUR_MAX) {
+#ifdef HAVE_WCRTOMB
+ incr = (int) wcrtomb(*output, (wchar_t) **input, &ps);
+#else
+ // XXX is this thread-safe?
+ incr = (int) wctomb(*output, (wchar_t) **input);
+#endif
+ if (incr < 0) {
+ NS_WARNING("mbtowc failed: possible charset mismatch");
+ **output = (unsigned char) **input; // truncate
+ incr = 1;
+ }
+ // most likely we're dead anyways if this assertion should fire
+ NS_ASSERTION(PRUint32(incr) <= *outputLeft, "wrote beyond end of string");
+ (*output) += incr;
+ (*outputLeft) -= incr;
+ (*input)++;
+ (*inputLeft)--;
+ }
+ }
+ else {
+ // wchar_t isn't unicode, so the best we can do is treat the
+ // input as if it is isolatin1 :(
+ utf16_to_isolatin1(input, inputLeft, output, outputLeft);
+ }
+
+ return NS_OK;
+}
+
+#endif // USE_STDCONV
+
+//-----------------------------------------------------------------------------
+// API implementation
+//-----------------------------------------------------------------------------
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ output.Truncate();
+
+ PRUint32 inputLen = input.Length();
+
+ nsACString::const_iterator iter;
+ input.BeginReading(iter);
+
+ //
+ // OPTIMIZATION: preallocate space for largest possible result; convert
+ // directly into the result buffer to avoid intermediate buffer copy.
+ //
+ // this will generally result in a larger allocation, but that seems
+ // better than an extra buffer copy.
+ //
+ output.SetLength(inputLen);
+ nsAString::iterator out_iter;
+ output.BeginWriting(out_iter);
+
+ PRUnichar *result = out_iter.get();
+ PRUint32 resultLeft = inputLen;
+
+ const char *buf = iter.get();
+ PRUint32 bufLeft = inputLen;
+
+ nsNativeCharsetConverter conv;
+ nsresult rv = conv.NativeToUnicode(&buf, &bufLeft, &result, &resultLeft);
+ if (NS_SUCCEEDED(rv)) {
+ NS_ASSERTION(bufLeft == 0, "did not consume entire input buffer");
+ output.SetLength(inputLen - resultLeft);
+ }
+ return rv;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ output.Truncate();
+
+ nsAString::const_iterator iter, end;
+ input.BeginReading(iter);
+ input.EndReading(end);
+
+ // cannot easily avoid intermediate buffer copy.
+ char temp[4096];
+
+ nsNativeCharsetConverter conv;
+
+ const PRUnichar *buf = iter.get();
+ PRUint32 bufLeft = Distance(iter, end);
+ while (bufLeft) {
+ char *p = temp;
+ PRUint32 tempLeft = sizeof(temp);
+
+ nsresult rv = conv.UnicodeToNative(&buf, &bufLeft, &p, &tempLeft);
+ if (NS_FAILED(rv)) return rv;
+
+ if (tempLeft < sizeof(temp))
+ output.Append(temp, sizeof(temp) - tempLeft);
+ }
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+ //
+ // need to initialize the locale or else charset conversion will fail.
+ // better not delay this in case some other component alters the locale
+ // settings.
+ //
+ // XXX we assume that we are called early enough that we should
+ // always be the first to care about the locale's charset.
+ //
+ setlocale(LC_CTYPE, "");
+
+ nsNativeCharsetConverter::GlobalInit();
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+ nsNativeCharsetConverter::GlobalShutdown();
+}
+
+//-----------------------------------------------------------------------------
+// XP_BEOS
+//-----------------------------------------------------------------------------
+#elif defined(XP_BEOS)
+
+#include "nsAString.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ CopyUTF8toUTF16(input, output);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ CopyUTF16toUTF8(input, output);
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+}
+
+//-----------------------------------------------------------------------------
+// XP_WIN
+//-----------------------------------------------------------------------------
+#elif defined(XP_WIN)
+
+#include <windows.h>
+#include "nsAString.h"
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ PRUint32 inputLen = input.Length();
+
+ nsACString::const_iterator iter;
+ input.BeginReading(iter);
+
+ const char *buf = iter.get();
+
+ // determine length of result
+ PRUint32 resultLen = 0;
+ int n = ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, NULL, 0);
+ if (n > 0)
+ resultLen += n;
+
+ // allocate sufficient space
+ output.SetLength(resultLen);
+ if (resultLen > 0) {
+ nsAString::iterator out_iter;
+ output.BeginWriting(out_iter);
+
+ PRUnichar *result = out_iter.get();
+
+ ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, result, resultLen);
+ }
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ PRUint32 inputLen = input.Length();
+
+ nsAString::const_iterator iter;
+ input.BeginReading(iter);
+
+ const PRUnichar *buf = iter.get();
+
+ // determine length of result
+ PRUint32 resultLen = 0;
+
+ int n = ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, NULL, 0, NULL, NULL);
+ if (n > 0)
+ resultLen += n;
+
+ // allocate sufficient space
+ output.SetLength(resultLen);
+ if (resultLen > 0) {
+ nsACString::iterator out_iter;
+ output.BeginWriting(out_iter);
+
+ // default "defaultChar" is '?', which is an illegal character on windows
+ // file system. That will cause file uncreatable. Change it to '_'
+ const char defaultChar = '_';
+
+ char *result = out_iter.get();
+
+ ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, result, resultLen,
+ &defaultChar, NULL);
+ }
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+}
+
+//-----------------------------------------------------------------------------
+// XP_OS2
+//-----------------------------------------------------------------------------
+#elif defined(XP_OS2)
+
+#define INCL_DOS
+#include <os2.h>
+#include <uconv.h>
+#include "nsAString.h"
+#include <ulserrno.h>
+#include "nsNativeCharsetUtils.h"
+
+static UconvObject UnicodeConverter = NULL;
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ PRUint32 inputLen = input.Length();
+
+ nsACString::const_iterator iter;
+ input.BeginReading(iter);
+ const char *inputStr = iter.get();
+
+ // determine length of result
+ PRUint32 resultLen = inputLen;
+ output.SetLength(resultLen);
+
+ nsAString::iterator out_iter;
+ output.BeginWriting(out_iter);
+ UniChar *result = (UniChar*)out_iter.get();
+
+ size_t cSubs = 0;
+ size_t resultLeft = resultLen;
+
+ if (!UnicodeConverter)
+ NS_StartupNativeCharsetUtils();
+
+ int unirc = ::UniUconvToUcs(UnicodeConverter, (void**)&inputStr, &inputLen,
+ &result, &resultLeft, &cSubs);
+
+ NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big");
+
+ if (unirc != ULS_SUCCESS) {
+ output.Truncate();
+ return NS_ERROR_FAILURE;
+ }
+
+ // Need to update string length to reflect how many bytes were actually
+ // written.
+ output.Truncate(resultLen - resultLeft);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ size_t inputLen = input.Length();
+
+ nsAString::const_iterator iter;
+ input.BeginReading(iter);
+ UniChar* inputStr = (UniChar*) NS_CONST_CAST(PRUnichar*, iter.get());
+
+ // maximum length of unicode string of length x converted to native
+ // codepage is x*2
+ size_t resultLen = inputLen * 2;
+ output.SetLength(resultLen);
+
+ nsACString::iterator out_iter;
+ output.BeginWriting(out_iter);
+ char *result = out_iter.get();
+
+ size_t cSubs = 0;
+ size_t resultLeft = resultLen;
+
+ if (!UnicodeConverter)
+ NS_StartupNativeCharsetUtils();
+
+ int unirc = ::UniUconvFromUcs(UnicodeConverter, &inputStr, &inputLen,
+ (void**)&result, &resultLeft, &cSubs);
+
+ NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big");
+
+ if (unirc != ULS_SUCCESS) {
+ output.Truncate();
+ return NS_ERROR_FAILURE;
+ }
+
+ // Need to update string length to reflect how many bytes were actually
+ // written.
+ output.Truncate(resultLen - resultLeft);
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+ ULONG ulLength;
+ ULONG ulCodePage;
+ DosQueryCp(sizeof(ULONG), &ulCodePage, &ulLength);
+
+ UniChar codepage[20];
+ int unirc = ::UniMapCpToUcsCp(ulCodePage, codepage, 20);
+ if (unirc == ULS_SUCCESS) {
+ unirc = ::UniCreateUconvObject(codepage, &UnicodeConverter);
+ if (unirc == ULS_SUCCESS) {
+ uconv_attribute_t attr;
+ ::UniQueryUconvObject(UnicodeConverter, &attr, sizeof(uconv_attribute_t),
+ NULL, NULL, NULL);
+ attr.options = UCONV_OPTION_SUBSTITUTE_BOTH;
+ attr.subchar_len=1;
+ attr.subchar[0]='_';
+ ::UniSetUconvObject(UnicodeConverter, &attr);
+ }
+ }
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+ ::UniFreeUconvObject(UnicodeConverter);
+}
+
+//-----------------------------------------------------------------------------
+// XP_MAC
+//-----------------------------------------------------------------------------
+#elif defined(XP_MAC)
+
+#include <UnicodeConverter.h>
+#include <TextCommon.h>
+#include <Script.h>
+#include <MacErrors.h>
+#include "nsAString.h"
+
+class nsFSStringConversionMac {
+public:
+ static nsresult UCSToFS(const nsAString& aIn, nsACString& aOut);
+ static nsresult FSToUCS(const nsACString& ain, nsAString& aOut);
+
+ static void CleanUp();
+
+private:
+ static TextEncoding GetSystemEncoding();
+ static nsresult PrepareEncoder();
+ static nsresult PrepareDecoder();
+
+ static UnicodeToTextInfo sEncoderInfo;
+ static TextToUnicodeInfo sDecoderInfo;
+};
+
+UnicodeToTextInfo nsFSStringConversionMac::sEncoderInfo = nsnull;
+TextToUnicodeInfo nsFSStringConversionMac::sDecoderInfo = nsnull;
+
+nsresult nsFSStringConversionMac::UCSToFS(const nsAString& aIn, nsACString& aOut)
+{
+ nsresult rv = PrepareEncoder();
+ if (NS_FAILED(rv)) return rv;
+
+ OSStatus err = noErr;
+ char stackBuffer[512];
+
+ aOut.Truncate();
+
+ // for each chunk of |aIn|...
+ nsReadingIterator<PRUnichar> iter;
+ aIn.BeginReading(iter);
+
+ PRUint32 fragmentLength = PRUint32(iter.size_forward());
+ UInt32 bytesLeft = fragmentLength * sizeof(UniChar);
+
+ do {
+ UInt32 bytesRead = 0, bytesWritten = 0;
+ err = ::ConvertFromUnicodeToText(sEncoderInfo,
+ bytesLeft,
+ (const UniChar*)iter.get(),
+ kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask,
+ 0, nsnull, nsnull, nsnull,
+ sizeof(stackBuffer),
+ &bytesRead,
+ &bytesWritten,
+ stackBuffer);
+ if (err == kTECUsedFallbacksStatus)
+ err = noErr;
+ else if (err == kTECOutputBufferFullStatus) {
+ bytesLeft -= bytesRead;
+ iter.advance(bytesRead / sizeof(UniChar));
+ }
+ aOut.Append(stackBuffer, bytesWritten);
+ }
+ while (err == kTECOutputBufferFullStatus);
+
+ return (err == noErr) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult nsFSStringConversionMac::FSToUCS(const nsACString& aIn, nsAString& aOut)
+{
+ nsresult rv = PrepareDecoder();
+ if (NS_FAILED(rv)) return rv;
+
+ OSStatus err = noErr;
+ UniChar stackBuffer[512];
+
+ aOut.Truncate(0);
+
+ // for each chunk of |aIn|...
+ nsReadingIterator<char> iter;
+ aIn.BeginReading(iter);
+
+ PRUint32 fragmentLength = PRUint32(iter.size_forward());
+ UInt32 bytesLeft = fragmentLength;
+
+ do {
+ UInt32 bytesRead = 0, bytesWritten = 0;
+ err = ::ConvertFromTextToUnicode(sDecoderInfo,
+ bytesLeft,
+ iter.get(),
+ kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask,
+ 0, nsnull, nsnull, nsnull,
+ sizeof(stackBuffer),
+ &bytesRead,
+ &bytesWritten,
+ stackBuffer);
+ if (err == kTECUsedFallbacksStatus)
+ err = noErr;
+ else if (err == kTECOutputBufferFullStatus) {
+ bytesLeft -= bytesRead;
+ iter.advance(bytesRead);
+ }
+ aOut.Append((PRUnichar *)stackBuffer, bytesWritten / sizeof(PRUnichar));
+ }
+ while (err == kTECOutputBufferFullStatus);
+
+ return (err == noErr) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+void nsFSStringConversionMac::CleanUp()
+{
+ if (sDecoderInfo) {
+ ::DisposeTextToUnicodeInfo(&sDecoderInfo);
+ sDecoderInfo = nsnull;
+ }
+ if (sEncoderInfo) {
+ ::DisposeUnicodeToTextInfo(&sEncoderInfo);
+ sEncoderInfo = nsnull;
+ }
+}
+
+TextEncoding nsFSStringConversionMac::GetSystemEncoding()
+{
+ OSStatus err;
+ TextEncoding theEncoding;
+
+ err = ::UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &theEncoding);
+
+ if (err != noErr)
+ theEncoding = kTextEncodingMacRoman;
+
+ return theEncoding;
+}
+
+nsresult nsFSStringConversionMac::PrepareEncoder()
+{
+ nsresult rv = NS_OK;
+ if (!sEncoderInfo) {
+ OSStatus err;
+ err = ::CreateUnicodeToTextInfoByEncoding(GetSystemEncoding(), &sEncoderInfo);
+ if (err)
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+nsresult nsFSStringConversionMac::PrepareDecoder()
+{
+ nsresult rv = NS_OK;
+ if (!sDecoderInfo) {
+ OSStatus err;
+ err = ::CreateTextToUnicodeInfoByEncoding(GetSystemEncoding(), &sDecoderInfo);
+ if (err)
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ return nsFSStringConversionMac::FSToUCS(input, output);
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ return nsFSStringConversionMac::UCSToFS(input, output);
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+ nsFSStringConversionMac::CleanUp();
+}
+
+//-----------------------------------------------------------------------------
+// default : truncate/zeropad
+//-----------------------------------------------------------------------------
+#else
+
+#include "nsReadableUtils.h"
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ CopyASCIItoUCS2(input, output);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ CopyUCS2toASCII(input, output);
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h
new file mode 100644
index 00000000..539fa37f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h
@@ -0,0 +1,66 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef nsNativeCharsetUtils_h__
+#define nsNativeCharsetUtils_h__
+
+
+/*****************************************************************************\
+ * *
+ * **** NOTICE **** *
+ * *
+ * *** THESE ARE NOT GENERAL PURPOSE CONVERTERS *** *
+ * *
+ * NS_CopyNativeToUnicode / NS_CopyUnicodeToNative should only be used *
+ * for converting *FILENAMES* between native and unicode. They are not *
+ * designed or tested for general encoding converter use. *
+ * *
+\*****************************************************************************/
+
+/**
+ * thread-safe conversion routines that do not depend on uconv libraries.
+ */
+NS_COM nsresult NS_CopyNativeToUnicode(const nsACString &input, nsAString &output);
+NS_COM nsresult NS_CopyUnicodeToNative(const nsAString &input, nsACString &output);
+
+/**
+ * internal
+ */
+void NS_StartupNativeCharsetUtils();
+void NS_ShutdownNativeCharsetUtils();
+
+#endif // nsNativeCharsetUtils_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp b/src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp
new file mode 100644
index 00000000..be06179f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp
@@ -0,0 +1,1276 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsIPipe.h"
+#include "nsIEventTarget.h"
+#include "nsISeekableStream.h"
+#include "nsSegmentedBuffer.h"
+#include "nsStreamUtils.h"
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include "prlog.h"
+#include "nsInt64.h"
+
+#if defined(PR_LOGGING)
+//
+// set NSPR_LOG_MODULES=nsPipe:5
+//
+static PRLogModuleInfo *gPipeLog = nsnull;
+#define LOG(args) PR_LOG(gPipeLog, PR_LOG_DEBUG, args)
+#else
+#define LOG(args)
+#endif
+
+#define DEFAULT_SEGMENT_SIZE 4096
+#define DEFAULT_SEGMENT_COUNT 16
+
+class nsPipe;
+class nsPipeEvents;
+class nsPipeInputStream;
+class nsPipeOutputStream;
+
+//-----------------------------------------------------------------------------
+
+// this class is used to delay notifications until the end of a particular
+// scope. it helps avoid the complexity of issuing callbacks while inside
+// a critical section.
+class nsPipeEvents
+{
+public:
+ nsPipeEvents() { }
+ ~nsPipeEvents();
+
+ inline void NotifyInputReady(nsIAsyncInputStream *stream,
+ nsIInputStreamCallback *callback)
+ {
+ NS_ASSERTION(!mInputCallback, "already have an input event");
+ mInputStream = stream;
+ mInputCallback = callback;
+ }
+
+ inline void NotifyOutputReady(nsIAsyncOutputStream *stream,
+ nsIOutputStreamCallback *callback)
+ {
+ NS_ASSERTION(!mOutputCallback, "already have an output event");
+ mOutputStream = stream;
+ mOutputCallback = callback;
+ }
+
+private:
+ nsCOMPtr<nsIAsyncInputStream> mInputStream;
+ nsCOMPtr<nsIInputStreamCallback> mInputCallback;
+ nsCOMPtr<nsIAsyncOutputStream> mOutputStream;
+ nsCOMPtr<nsIOutputStreamCallback> mOutputCallback;
+};
+
+//-----------------------------------------------------------------------------
+
+// the input end of a pipe (allocated as a member of the pipe).
+class nsPipeInputStream : public nsIAsyncInputStream
+ , public nsISeekableStream
+ , public nsISearchableInputStream
+{
+public:
+ // since this class will be allocated as a member of the pipe, we do not
+ // need our own ref count. instead, we share the lifetime (the ref count)
+ // of the entire pipe. this macro is just convenience since it does not
+ // declare a mRefCount variable; however, don't let the name fool you...
+ // we are not inheriting from nsPipe ;-)
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIASYNCINPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSISEARCHABLEINPUTSTREAM
+
+ nsPipeInputStream(nsPipe *pipe)
+ : mPipe(pipe)
+ , mReaderRefCnt(0)
+ , mLogicalOffset(0)
+ , mBlocking(PR_TRUE)
+ , mBlocked(PR_FALSE)
+ , mAvailable(0)
+ , mCallbackFlags(0)
+ { }
+
+ nsresult Fill();
+ void SetNonBlocking(PRBool aNonBlocking) { mBlocking = !aNonBlocking; }
+
+ PRUint32 Available() { return mAvailable; }
+ void ReduceAvailable(PRUint32 avail) { mAvailable -= avail; }
+
+ // synchronously wait for the pipe to become readable.
+ nsresult Wait();
+
+ // these functions return true to indicate that the pipe's monitor should
+ // be notified, to wake up a blocked reader if any.
+ PRBool OnInputReadable(PRUint32 bytesWritten, nsPipeEvents &);
+ PRBool OnInputException(nsresult, nsPipeEvents &);
+
+private:
+ nsPipe *mPipe;
+
+ // separate refcnt so that we know when to close the consumer
+ nsrefcnt mReaderRefCnt;
+ nsInt64 mLogicalOffset;
+ PRPackedBool mBlocking;
+
+ // these variables can only be accessed while inside the pipe's monitor
+ PRPackedBool mBlocked;
+ PRUint32 mAvailable;
+ nsCOMPtr<nsIInputStreamCallback> mCallback;
+ PRUint32 mCallbackFlags;
+};
+
+//-----------------------------------------------------------------------------
+
+// the output end of a pipe (allocated as a member of the pipe).
+class nsPipeOutputStream : public nsIAsyncOutputStream
+ , public nsISeekableStream
+{
+public:
+ // since this class will be allocated as a member of the pipe, we do not
+ // need our own ref count. instead, we share the lifetime (the ref count)
+ // of the entire pipe. this macro is just convenience since it does not
+ // declare a mRefCount variable; however, don't let the name fool you...
+ // we are not inheriting from nsPipe ;-)
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_NSIOUTPUTSTREAM
+ NS_DECL_NSIASYNCOUTPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+
+ nsPipeOutputStream(nsPipe *pipe)
+ : mPipe(pipe)
+ , mWriterRefCnt(0)
+ , mLogicalOffset(0)
+ , mBlocking(PR_TRUE)
+ , mBlocked(PR_FALSE)
+ , mWritable(PR_TRUE)
+ , mCallbackFlags(0)
+ { }
+
+ void SetNonBlocking(PRBool aNonBlocking) { mBlocking = !aNonBlocking; }
+ void SetWritable(PRBool writable) { mWritable = writable; }
+
+ // synchronously wait for the pipe to become writable.
+ nsresult Wait();
+
+ // these functions return true to indicate that the pipe's monitor should
+ // be notified, to wake up a blocked writer if any.
+ PRBool OnOutputWritable(nsPipeEvents &);
+ PRBool OnOutputException(nsresult, nsPipeEvents &);
+
+private:
+ nsPipe *mPipe;
+
+ // separate refcnt so that we know when to close the producer
+ nsrefcnt mWriterRefCnt;
+ nsInt64 mLogicalOffset;
+ PRPackedBool mBlocking;
+
+ // these variables can only be accessed while inside the pipe's monitor
+ PRPackedBool mBlocked;
+ PRPackedBool mWritable;
+ nsCOMPtr<nsIOutputStreamCallback> mCallback;
+ PRUint32 mCallbackFlags;
+};
+
+//-----------------------------------------------------------------------------
+
+class nsPipe : public nsIPipe
+{
+public:
+ friend class nsPipeInputStream;
+ friend class nsPipeOutputStream;
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPIPE
+
+ // nsPipe methods:
+ nsPipe();
+
+private:
+ ~nsPipe();
+
+public:
+ //
+ // methods below may only be called while inside the pipe's monitor
+ //
+
+ void PeekSegment(PRUint32 n, char *&cursor, char *&limit);
+
+ //
+ // methods below may be called while outside the pipe's monitor
+ //
+
+ nsresult GetReadSegment(const char *&segment, PRUint32 &segmentLen);
+ void AdvanceReadCursor(PRUint32 count);
+
+ nsresult GetWriteSegment(char *&segment, PRUint32 &segmentLen);
+ void AdvanceWriteCursor(PRUint32 count);
+
+ void OnPipeException(nsresult reason, PRBool outputOnly = PR_FALSE);
+
+protected:
+ // We can't inherit from both nsIInputStream and nsIOutputStream
+ // because they collide on their Close method. Consequently we nest their
+ // implementations to avoid the extra object allocation.
+ nsPipeInputStream mInput;
+ nsPipeOutputStream mOutput;
+
+ PRMonitor* mMonitor;
+ nsSegmentedBuffer mBuffer;
+
+ char* mReadCursor;
+ char* mReadLimit;
+
+ PRInt32 mWriteSegment;
+ char* mWriteCursor;
+ char* mWriteLimit;
+
+ nsresult mStatus;
+};
+
+//
+// NOTES on buffer architecture:
+//
+// +-----------------+ - - mBuffer.GetSegment(0)
+// | |
+// + - - - - - - - - + - - mReadCursor
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// +-----------------+ - - mReadLimit
+// |
+// +-----------------+
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// +-----------------+
+// |
+// +-----------------+ - - mBuffer.GetSegment(mWriteSegment)
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// + - - - - - - - - + - - mWriteCursor
+// | |
+// | |
+// +-----------------+ - - mWriteLimit
+//
+// (shaded region contains data)
+//
+// NOTE: on some systems (notably OS/2), the heap allocator uses an arena for
+// small allocations (e.g., 64 byte allocations). this means that buffers may
+// be allocated back-to-back. in the diagram above, for example, mReadLimit
+// would actually be pointing at the beginning of the next segment. when
+// making changes to this file, please keep this fact in mind.
+//
+
+//-----------------------------------------------------------------------------
+// nsPipe methods:
+//-----------------------------------------------------------------------------
+
+nsPipe::nsPipe()
+ : mInput(this)
+ , mOutput(this)
+ , mMonitor(nsnull)
+ , mReadCursor(nsnull)
+ , mReadLimit(nsnull)
+ , mWriteSegment(-1)
+ , mWriteCursor(nsnull)
+ , mWriteLimit(nsnull)
+ , mStatus(NS_OK)
+{
+}
+
+nsPipe::~nsPipe()
+{
+ if (mMonitor)
+ PR_DestroyMonitor(mMonitor);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsPipe, nsIPipe)
+
+NS_IMETHODIMP
+nsPipe::Init(PRBool nonBlockingIn,
+ PRBool nonBlockingOut,
+ PRUint32 segmentSize,
+ PRUint32 segmentCount,
+ nsIMemory *segmentAlloc)
+{
+ mMonitor = PR_NewMonitor();
+ if (!mMonitor)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (segmentSize == 0)
+ segmentSize = DEFAULT_SEGMENT_SIZE;
+ if (segmentCount == 0)
+ segmentCount = DEFAULT_SEGMENT_COUNT;
+
+ // protect against overflow
+ PRUint32 maxCount = PRUint32(-1) / segmentSize;
+ if (segmentCount > maxCount)
+ segmentCount = maxCount;
+
+ nsresult rv = mBuffer.Init(segmentSize, segmentSize * segmentCount, segmentAlloc);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mInput.SetNonBlocking(nonBlockingIn);
+ mOutput.SetNonBlocking(nonBlockingOut);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipe::GetInputStream(nsIAsyncInputStream **aInputStream)
+{
+ NS_ADDREF(*aInputStream = &mInput);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipe::GetOutputStream(nsIAsyncOutputStream **aOutputStream)
+{
+ NS_ADDREF(*aOutputStream = &mOutput);
+ return NS_OK;
+}
+
+void
+nsPipe::PeekSegment(PRUint32 index, char *&cursor, char *&limit)
+{
+ if (index == 0) {
+ NS_ASSERTION(!mReadCursor || mBuffer.GetSegmentCount(), "unexpected state");
+ cursor = mReadCursor;
+ limit = mReadLimit;
+ }
+ else {
+ PRUint32 numSegments = mBuffer.GetSegmentCount();
+ if (index >= numSegments)
+ cursor = limit = nsnull;
+ else {
+ cursor = mBuffer.GetSegment(index);
+ if (mWriteSegment == (PRInt32) index)
+ limit = mWriteCursor;
+ else
+ limit = cursor + mBuffer.GetSegmentSize();
+ }
+ }
+}
+
+nsresult
+nsPipe::GetReadSegment(const char *&segment, PRUint32 &segmentLen)
+{
+ nsAutoMonitor mon(mMonitor);
+
+ if (mReadCursor == mReadLimit)
+ return NS_FAILED(mStatus) ? mStatus : NS_BASE_STREAM_WOULD_BLOCK;
+
+ segment = mReadCursor;
+ segmentLen = mReadLimit - mReadCursor;
+ return NS_OK;
+}
+
+void
+nsPipe::AdvanceReadCursor(PRUint32 bytesRead)
+{
+ NS_ASSERTION(bytesRead, "dont call if no bytes read");
+
+ nsPipeEvents events;
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ LOG(("III advancing read cursor by %u\n", bytesRead));
+ NS_ASSERTION(bytesRead <= mBuffer.GetSegmentSize(), "read too much");
+
+ mReadCursor += bytesRead;
+ NS_ASSERTION(mReadCursor <= mReadLimit, "read cursor exceeds limit");
+
+ mInput.ReduceAvailable(bytesRead);
+
+ if (mReadCursor == mReadLimit) {
+ // we've reached the limit of how much we can read from this segment.
+ // if at the end of this segment, then we must discard this segment.
+
+ // if still writing in this segment then bail because we're not done
+ // with the segment and have to wait for now...
+ if (mWriteSegment == 0 && mWriteLimit > mWriteCursor) {
+ NS_ASSERTION(mReadLimit == mWriteCursor, "unexpected state");
+ return;
+ }
+
+ // shift write segment index (-1 indicates an empty buffer).
+ --mWriteSegment;
+
+ // done with this segment
+ mBuffer.DeleteFirstSegment();
+ LOG(("III deleting first segment\n"));
+
+ if (mWriteSegment == -1) {
+ // buffer is completely empty
+ mReadCursor = nsnull;
+ mReadLimit = nsnull;
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+ }
+ else {
+ // advance read cursor and limit to next buffer segment
+ mReadCursor = mBuffer.GetSegment(0);
+ if (mWriteSegment == 0)
+ mReadLimit = mWriteCursor;
+ else
+ mReadLimit = mReadCursor + mBuffer.GetSegmentSize();
+ }
+
+ // we've free'd up a segment, so notify output stream that pipe has
+ // room for a new segment.
+ if (mOutput.OnOutputWritable(events))
+ mon.Notify();
+ }
+ }
+}
+
+nsresult
+nsPipe::GetWriteSegment(char *&segment, PRUint32 &segmentLen)
+{
+ nsAutoMonitor mon(mMonitor);
+
+ if (NS_FAILED(mStatus))
+ return mStatus;
+
+ // write cursor and limit may both be null indicating an empty buffer.
+ if (mWriteCursor == mWriteLimit) {
+ char *seg = mBuffer.AppendNewSegment();
+ // pipe is full
+ if (seg == nsnull)
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ LOG(("OOO appended new segment\n"));
+ mWriteCursor = seg;
+ mWriteLimit = mWriteCursor + mBuffer.GetSegmentSize();
+ ++mWriteSegment;
+ }
+
+ // make sure read cursor is initialized
+ if (mReadCursor == nsnull) {
+ NS_ASSERTION(mWriteSegment == 0, "unexpected null read cursor");
+ mReadCursor = mReadLimit = mWriteCursor;
+ }
+
+ // check to see if we can roll-back our read and write cursors to the
+ // beginning of the current/first segment. this is purely an optimization.
+ if (mReadCursor == mWriteCursor && mWriteSegment == 0) {
+ char *head = mBuffer.GetSegment(0);
+ LOG(("OOO rolling back write cursor %u bytes\n", mWriteCursor - head));
+ mWriteCursor = mReadCursor = mReadLimit = head;
+ }
+
+ segment = mWriteCursor;
+ segmentLen = mWriteLimit - mWriteCursor;
+ return NS_OK;
+}
+
+void
+nsPipe::AdvanceWriteCursor(PRUint32 bytesWritten)
+{
+ NS_ASSERTION(bytesWritten, "dont call if no bytes written");
+
+ nsPipeEvents events;
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ LOG(("OOO advancing write cursor by %u\n", bytesWritten));
+
+ char *newWriteCursor = mWriteCursor + bytesWritten;
+ NS_ASSERTION(newWriteCursor <= mWriteLimit, "write cursor exceeds limit");
+
+ // update read limit if reading in the same segment
+ if (mWriteSegment == 0 && mReadLimit == mWriteCursor)
+ mReadLimit = newWriteCursor;
+
+ mWriteCursor = newWriteCursor;
+
+ NS_ASSERTION(mReadCursor != mWriteCursor, "read cursor is bad");
+
+ // update the writable flag on the output stream
+ if (mWriteCursor == mWriteLimit) {
+ if (mBuffer.GetSize() >= mBuffer.GetMaxSize())
+ mOutput.SetWritable(PR_FALSE);
+ }
+
+ // notify input stream that pipe now contains additional data
+ if (mInput.OnInputReadable(bytesWritten, events))
+ mon.Notify();
+ }
+}
+
+void
+nsPipe::OnPipeException(nsresult reason, PRBool outputOnly)
+{
+ LOG(("PPP nsPipe::OnPipeException [reason=%x output-only=%d]\n",
+ reason, outputOnly));
+
+ nsPipeEvents events;
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ // if we've already hit an exception, then ignore this one.
+ if (NS_FAILED(mStatus))
+ return;
+
+ mStatus = reason;
+
+ // an output-only exception applies to the input end if the pipe has
+ // zero bytes available.
+ if (outputOnly && !mInput.Available())
+ outputOnly = PR_FALSE;
+
+ if (!outputOnly)
+ if (mInput.OnInputException(reason, events))
+ mon.Notify();
+
+ if (mOutput.OnOutputException(reason, events))
+ mon.Notify();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// nsPipeEvents methods:
+//-----------------------------------------------------------------------------
+
+nsPipeEvents::~nsPipeEvents()
+{
+ // dispatch any pending events
+
+ if (mInputCallback) {
+ mInputCallback->OnInputStreamReady(mInputStream);
+ mInputCallback = 0;
+ mInputStream = 0;
+ }
+ if (mOutputCallback) {
+ mOutputCallback->OnOutputStreamReady(mOutputStream);
+ mOutputCallback = 0;
+ mOutputStream = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// nsPipeInputStream methods:
+//-----------------------------------------------------------------------------
+
+nsresult
+nsPipeInputStream::Wait()
+{
+ NS_ASSERTION(mBlocking, "wait on non-blocking pipe input stream");
+
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ while (NS_SUCCEEDED(mPipe->mStatus) && (mAvailable == 0)) {
+ LOG(("III pipe input: waiting for data\n"));
+
+ mBlocked = PR_TRUE;
+ mon.Wait();
+ mBlocked = PR_FALSE;
+
+ LOG(("III pipe input: woke up [pipe-status=%x available=%u]\n",
+ mPipe->mStatus, mAvailable));
+ }
+
+ return mPipe->mStatus == NS_BASE_STREAM_CLOSED ? NS_OK : mPipe->mStatus;
+}
+
+PRBool
+nsPipeInputStream::OnInputReadable(PRUint32 bytesWritten, nsPipeEvents &events)
+{
+ PRBool result = PR_FALSE;
+
+ mAvailable += bytesWritten;
+
+ if (mCallback && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) {
+ events.NotifyInputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+PRBool
+nsPipeInputStream::OnInputException(nsresult reason, nsPipeEvents &events)
+{
+ LOG(("nsPipeInputStream::OnInputException [this=%x reason=%x]\n",
+ this, reason));
+
+ PRBool result = PR_FALSE;
+
+ NS_ASSERTION(NS_FAILED(reason), "huh? successful exception");
+
+ // force count of available bytes to zero.
+ mAvailable = 0;
+
+ if (mCallback) {
+ events.NotifyInputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeInputStream::AddRef(void)
+{
+ ++mReaderRefCnt;
+ return mPipe->AddRef();
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeInputStream::Release(void)
+{
+ if (--mReaderRefCnt == 0)
+ Close();
+ return mPipe->Release();
+}
+
+NS_IMPL_QUERY_INTERFACE4(nsPipeInputStream,
+ nsIInputStream,
+ nsIAsyncInputStream,
+ nsISeekableStream,
+ nsISearchableInputStream)
+
+NS_IMETHODIMP
+nsPipeInputStream::CloseWithStatus(nsresult reason)
+{
+ LOG(("III CloseWithStatus [this=%x reason=%x]\n", this, reason));
+
+ if (NS_SUCCEEDED(reason))
+ reason = NS_BASE_STREAM_CLOSED;
+
+ mPipe->OnPipeException(reason);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Close()
+{
+ return CloseWithStatus(NS_BASE_STREAM_CLOSED);
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Available(PRUint32 *result)
+{
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ // return error if pipe closed
+ if (!mAvailable && NS_FAILED(mPipe->mStatus))
+ return mPipe->mStatus;
+
+ *result = mAvailable;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
+ void *closure,
+ PRUint32 count,
+ PRUint32 *readCount)
+{
+ LOG(("III ReadSegments [this=%x count=%u]\n", this, count));
+
+ nsresult rv = NS_OK;
+
+ const char *segment;
+ PRUint32 segmentLen;
+
+ *readCount = 0;
+ while (count) {
+ rv = mPipe->GetReadSegment(segment, segmentLen);
+ if (NS_FAILED(rv)) {
+ // ignore this error if we've already read something.
+ if (*readCount > 0) {
+ rv = NS_OK;
+ break;
+ }
+ if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+ // pipe is empty
+ if (!mBlocking)
+ break;
+ // wait for some data to be written to the pipe
+ rv = Wait();
+ if (NS_SUCCEEDED(rv))
+ continue;
+ }
+ // ignore this error, just return.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ rv = NS_OK;
+ break;
+ }
+ mPipe->OnPipeException(rv);
+ break;
+ }
+
+ // read no more than count
+ if (segmentLen > count)
+ segmentLen = count;
+
+ PRUint32 writeCount, originalLen = segmentLen;
+ while (segmentLen) {
+ writeCount = 0;
+
+ rv = writer(this, closure, segment, *readCount, segmentLen, &writeCount);
+
+ if (NS_FAILED(rv) || writeCount == 0) {
+ count = 0;
+ // any errors returned from the writer end here: do not
+ // propogate to the caller of ReadSegments.
+ rv = NS_OK;
+ break;
+ }
+
+ NS_ASSERTION(writeCount <= segmentLen, "wrote more than expected");
+ segment += writeCount;
+ segmentLen -= writeCount;
+ count -= writeCount;
+ *readCount += writeCount;
+ mLogicalOffset += writeCount;
+ }
+
+ if (segmentLen < originalLen)
+ mPipe->AdvanceReadCursor(originalLen - segmentLen);
+ }
+
+ return rv;
+}
+
+static NS_METHOD
+nsWriteToRawBuffer(nsIInputStream* inStr,
+ void *closure,
+ const char *fromRawSegment,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ char *toBuf = (char*)closure;
+ memcpy(&toBuf[offset], fromRawSegment, count);
+ *writeCount = count;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount)
+{
+ return ReadSegments(nsWriteToRawBuffer, toBuf, bufLen, readCount);
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = !mBlocking;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::AsyncWait(nsIInputStreamCallback *callback,
+ PRUint32 flags,
+ PRUint32 requestedCount,
+ nsIEventTarget *target)
+{
+ LOG(("III AsyncWait [this=%x]\n", this));
+
+ nsPipeEvents pipeEvents;
+ {
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ // replace a pending callback
+ mCallback = 0;
+ mCallbackFlags = 0;
+
+ nsCOMPtr<nsIInputStreamCallback> proxy;
+ if (target) {
+ nsresult rv = NS_NewInputStreamReadyEvent(getter_AddRefs(proxy),
+ callback, target);
+ if (NS_FAILED(rv)) return rv;
+ callback = proxy;
+ }
+
+ if (NS_FAILED(mPipe->mStatus) ||
+ (mAvailable && !(flags & WAIT_CLOSURE_ONLY))) {
+ // stream is already closed or readable; post event.
+ pipeEvents.NotifyInputReady(this, callback);
+ }
+ else {
+ // queue up callback object to be notified when data becomes available
+ mCallback = callback;
+ mCallbackFlags = flags;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ NS_NOTREACHED("nsPipeInputStream::Seek");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Tell(PRInt64 *offset)
+{
+ *offset = mLogicalOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::SetEOF()
+{
+ NS_NOTREACHED("nsPipeInputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#define COMPARE(s1, s2, i) \
+ (ignoreCase \
+ ? nsCRT::strncasecmp((const char *)s1, (const char *)s2, (PRUint32)i) \
+ : nsCRT::strncmp((const char *)s1, (const char *)s2, (PRUint32)i))
+
+NS_IMETHODIMP
+nsPipeInputStream::Search(const char *forString,
+ PRBool ignoreCase,
+ PRBool *found,
+ PRUint32 *offsetSearchedTo)
+{
+ LOG(("III Search [for=%s ic=%u]\n", forString, ignoreCase));
+
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ char *cursor1, *limit1;
+ PRUint32 index = 0, offset = 0;
+ PRUint32 strLen = strlen(forString);
+
+ mPipe->PeekSegment(0, cursor1, limit1);
+ if (cursor1 == limit1) {
+ *found = PR_FALSE;
+ *offsetSearchedTo = 0;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+
+ while (PR_TRUE) {
+ PRUint32 i, len1 = limit1 - cursor1;
+
+ // check if the string is in the buffer segment
+ for (i = 0; i < len1 - strLen + 1; i++) {
+ if (COMPARE(&cursor1[i], forString, strLen) == 0) {
+ *found = PR_TRUE;
+ *offsetSearchedTo = offset + i;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+ }
+
+ // get the next segment
+ char *cursor2, *limit2;
+ PRUint32 len2;
+
+ index++;
+ offset += len1;
+
+ mPipe->PeekSegment(index, cursor2, limit2);
+ if (cursor2 == limit2) {
+ *found = PR_FALSE;
+ *offsetSearchedTo = offset - strLen + 1;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+ len2 = limit2 - cursor2;
+
+ // check if the string is straddling the next buffer segment
+ PRUint32 lim = PR_MIN(strLen, len2 + 1);
+ for (i = 0; i < lim; ++i) {
+ PRUint32 strPart1Len = strLen - i - 1;
+ PRUint32 strPart2Len = strLen - strPart1Len;
+ const char* strPart2 = &forString[strLen - strPart2Len];
+ PRUint32 bufSeg1Offset = len1 - strPart1Len;
+ if (COMPARE(&cursor1[bufSeg1Offset], forString, strPart1Len) == 0 &&
+ COMPARE(cursor2, strPart2, strPart2Len) == 0) {
+ *found = PR_TRUE;
+ *offsetSearchedTo = offset - strPart1Len;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+ }
+
+ // finally continue with the next buffer
+ cursor1 = cursor2;
+ limit1 = limit2;
+ }
+
+ NS_NOTREACHED("can't get here");
+ return NS_ERROR_UNEXPECTED; // keep compiler happy
+}
+
+//-----------------------------------------------------------------------------
+// nsPipeOutputStream methods:
+//-----------------------------------------------------------------------------
+
+nsresult
+nsPipeOutputStream::Wait()
+{
+ NS_ASSERTION(mBlocking, "wait on non-blocking pipe output stream");
+
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ if (NS_SUCCEEDED(mPipe->mStatus) && !mWritable) {
+ LOG(("OOO pipe output: waiting for space\n"));
+ mBlocked = PR_TRUE;
+ mon.Wait();
+ mBlocked = PR_FALSE;
+ LOG(("OOO pipe output: woke up [pipe-status=%x writable=%u]\n",
+ mPipe->mStatus, mWritable == PR_TRUE));
+ }
+
+ return mPipe->mStatus == NS_BASE_STREAM_CLOSED ? NS_OK : mPipe->mStatus;
+}
+
+PRBool
+nsPipeOutputStream::OnOutputWritable(nsPipeEvents &events)
+{
+ PRBool result = PR_FALSE;
+
+ mWritable = PR_TRUE;
+
+ if (mCallback && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) {
+ events.NotifyOutputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+PRBool
+nsPipeOutputStream::OnOutputException(nsresult reason, nsPipeEvents &events)
+{
+ LOG(("nsPipeOutputStream::OnOutputException [this=%x reason=%x]\n",
+ this, reason));
+
+ nsresult result = PR_FALSE;
+
+ NS_ASSERTION(NS_FAILED(reason), "huh? successful exception");
+ mWritable = PR_FALSE;
+
+ if (mCallback) {
+ events.NotifyOutputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeOutputStream::AddRef()
+{
+ mWriterRefCnt++;
+ return mPipe->AddRef();
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeOutputStream::Release()
+{
+ if (--mWriterRefCnt == 0)
+ Close();
+ return mPipe->Release();
+}
+
+NS_IMPL_QUERY_INTERFACE2(nsPipeOutputStream,
+ nsIOutputStream,
+ nsIAsyncOutputStream)
+
+NS_IMETHODIMP
+nsPipeOutputStream::CloseWithStatus(nsresult reason)
+{
+ LOG(("OOO CloseWithStatus [this=%x reason=%x]\n", this, reason));
+
+ if (NS_SUCCEEDED(reason))
+ reason = NS_BASE_STREAM_CLOSED;
+
+ // input stream may remain open
+ mPipe->OnPipeException(reason, PR_TRUE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Close()
+{
+ return CloseWithStatus(NS_BASE_STREAM_CLOSED);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
+ void* closure,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ LOG(("OOO WriteSegments [this=%x count=%u]\n", this, count));
+
+ nsresult rv = NS_OK;
+
+ char *segment;
+ PRUint32 segmentLen;
+
+ *writeCount = 0;
+ while (count) {
+ rv = mPipe->GetWriteSegment(segment, segmentLen);
+ if (NS_FAILED(rv)) {
+ if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+ // pipe is full
+ if (!mBlocking) {
+ // ignore this error if we've already written something
+ if (*writeCount > 0)
+ rv = NS_OK;
+ break;
+ }
+ // wait for the pipe to have an empty segment.
+ rv = Wait();
+ if (NS_SUCCEEDED(rv))
+ continue;
+ }
+ mPipe->OnPipeException(rv);
+ break;
+ }
+
+ // write no more than count
+ if (segmentLen > count)
+ segmentLen = count;
+
+ PRUint32 readCount, originalLen = segmentLen;
+ while (segmentLen) {
+ readCount = 0;
+
+ rv = reader(this, closure, segment, *writeCount, segmentLen, &readCount);
+
+ if (NS_FAILED(rv) || readCount == 0) {
+ count = 0;
+ // any errors returned from the reader end here: do not
+ // propogate to the caller of WriteSegments.
+ rv = NS_OK;
+ break;
+ }
+
+ NS_ASSERTION(readCount <= segmentLen, "read more than expected");
+ segment += readCount;
+ segmentLen -= readCount;
+ count -= readCount;
+ *writeCount += readCount;
+ mLogicalOffset += readCount;
+ }
+
+ if (segmentLen < originalLen)
+ mPipe->AdvanceWriteCursor(originalLen - segmentLen);
+ }
+
+ return rv;
+}
+
+static NS_METHOD
+nsReadFromRawBuffer(nsIOutputStream* outStr,
+ void* closure,
+ char* toRawSegment,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *readCount)
+{
+ const char* fromBuf = (const char*)closure;
+ memcpy(toRawSegment, &fromBuf[offset], count);
+ *readCount = count;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Write(const char* fromBuf,
+ PRUint32 bufLen,
+ PRUint32 *writeCount)
+{
+ return WriteSegments(nsReadFromRawBuffer, (void*)fromBuf, bufLen, writeCount);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Flush(void)
+{
+ // nothing to do
+ return NS_OK;
+}
+
+static NS_METHOD
+nsReadFromInputStream(nsIOutputStream* outStr,
+ void* closure,
+ char* toRawSegment,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *readCount)
+{
+ nsIInputStream* fromStream = (nsIInputStream*)closure;
+ return fromStream->Read(toRawSegment, count, readCount);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::WriteFrom(nsIInputStream* fromStream,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ return WriteSegments(nsReadFromInputStream, fromStream, count, writeCount);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = !mBlocking;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
+ PRUint32 flags,
+ PRUint32 requestedCount,
+ nsIEventTarget *target)
+{
+ LOG(("OOO AsyncWait [this=%x]\n", this));
+
+ nsPipeEvents pipeEvents;
+ {
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ // replace a pending callback
+ mCallback = 0;
+ mCallbackFlags = 0;
+
+ nsCOMPtr<nsIOutputStreamCallback> proxy;
+ if (target) {
+ nsresult rv = NS_NewOutputStreamReadyEvent(getter_AddRefs(proxy),
+ callback, target);
+ if (NS_FAILED(rv)) return rv;
+ callback = proxy;
+ }
+
+ if (NS_FAILED(mPipe->mStatus) ||
+ (mWritable && !(flags & WAIT_CLOSURE_ONLY))) {
+ // stream is already closed or writable; post event.
+ pipeEvents.NotifyOutputReady(this, callback);
+ }
+ else {
+ // queue up callback object to be notified when data becomes available
+ mCallback = callback;
+ mCallbackFlags = flags;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ NS_NOTREACHED("nsPipeOutputStream::Seek");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Tell(PRInt64 *offset)
+{
+ *offset = mLogicalOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::SetEOF()
+{
+ NS_NOTREACHED("nsPipeOutputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_NewPipe2(nsIAsyncInputStream **pipeIn,
+ nsIAsyncOutputStream **pipeOut,
+ PRBool nonBlockingInput,
+ PRBool nonBlockingOutput,
+ PRUint32 segmentSize,
+ PRUint32 segmentCount,
+ nsIMemory *segmentAlloc)
+{
+ nsresult rv;
+
+#if defined(PR_LOGGING)
+ if (!gPipeLog)
+ gPipeLog = PR_NewLogModule("nsPipe");
+#endif
+
+ nsPipe *pipe = new nsPipe();
+ if (!pipe)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = pipe->Init(nonBlockingInput,
+ nonBlockingOutput,
+ segmentSize,
+ segmentCount,
+ segmentAlloc);
+ if (NS_FAILED(rv)) {
+ NS_ADDREF(pipe);
+ NS_RELEASE(pipe);
+ return rv;
+ }
+
+ pipe->GetInputStream(pipeIn);
+ pipe->GetOutputStream(pipeOut);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp
new file mode 100644
index 00000000..5458b1b7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsScriptableInputStream.h"
+#include "nsMemory.h"
+
+NS_IMPL_ISUPPORTS1(nsScriptableInputStream, nsIScriptableInputStream)
+
+// nsIBaseStream methods
+NS_IMETHODIMP
+nsScriptableInputStream::Close(void) {
+ if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
+ return mInputStream->Close();
+}
+
+// nsIScriptableInputStream methods
+NS_IMETHODIMP
+nsScriptableInputStream::Init(nsIInputStream *aInputStream) {
+ if (!aInputStream) return NS_ERROR_NULL_POINTER;
+ mInputStream = aInputStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptableInputStream::Available(PRUint32 *_retval) {
+ if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
+ return mInputStream->Available(_retval);
+}
+
+NS_IMETHODIMP
+nsScriptableInputStream::Read(PRUint32 aCount, char **_retval) {
+ nsresult rv = NS_OK;
+ PRUint32 count = 0;
+ char *buffer = nsnull;
+
+ if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
+
+ rv = mInputStream->Available(&count);
+ if (NS_FAILED(rv)) return rv;
+
+ count = PR_MIN(count, aCount);
+ buffer = (char*)nsMemory::Alloc(count+1); // make room for '\0'
+ if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32 amtRead = 0;
+ rv = mInputStream->Read(buffer, count, &amtRead);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(buffer);
+ return rv;
+ }
+
+ buffer[amtRead] = '\0';
+ *_retval = buffer;
+ return NS_OK;
+}
+
+NS_METHOD
+nsScriptableInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
+ if (aOuter) return NS_ERROR_NO_AGGREGATION;
+
+ nsScriptableInputStream *sis = new nsScriptableInputStream();
+ if (!sis) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(sis);
+ nsresult rv = sis->QueryInterface(aIID, aResult);
+ NS_RELEASE(sis);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h
new file mode 100644
index 00000000..b9976176
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h
@@ -0,0 +1,71 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ___nsscriptableinputstream___h_
+#define ___nsscriptableinputstream___h_
+
+#include "nsIScriptableInputStream.h"
+#include "nsIInputStream.h"
+#include "nsCOMPtr.h"
+
+#define NS_SCRIPTABLEINPUTSTREAM_CID \
+{ 0x7225c040, 0xa9bf, 0x11d3, { 0xa1, 0x97, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44 } }
+
+#define NS_SCRIPTABLEINPUTSTREAM_CONTRACTID "@mozilla.org/scriptableinputstream;1"
+#define NS_SCRIPTABLEINPUTSTREAM_CLASSNAME "Scriptable Input Stream"
+
+class nsScriptableInputStream : public nsIScriptableInputStream {
+public:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIScriptableInputStream methods
+ NS_DECL_NSISCRIPTABLEINPUTSTREAM
+
+ // nsScriptableInputStream methods
+ nsScriptableInputStream() {};
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsScriptableInputStream() {};
+
+ nsCOMPtr<nsIInputStream> mInputStream;
+};
+
+#endif // ___nsscriptableinputstream___h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp
new file mode 100644
index 00000000..f6a1c15d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSegmentedBuffer.h"
+#include "nsCRT.h"
+
+nsresult
+nsSegmentedBuffer::Init(PRUint32 segmentSize, PRUint32 maxSize,
+ nsIMemory* allocator)
+{
+ if (mSegmentArrayCount != 0)
+ return NS_ERROR_FAILURE; // initialized more than once
+ mSegmentSize = segmentSize;
+ mMaxSize = maxSize;
+ mSegAllocator = allocator;
+ if (mSegAllocator == nsnull) {
+ mSegAllocator = nsMemory::GetGlobalMemoryService();
+ }
+ else {
+ NS_ADDREF(mSegAllocator);
+ }
+#if 0 // testing...
+ mSegmentArrayCount = 2;
+#else
+ mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
+#endif
+ return NS_OK;
+}
+
+char*
+nsSegmentedBuffer::AppendNewSegment()
+{
+ if (GetSize() >= mMaxSize)
+ return nsnull;
+
+ if (mSegmentArray == nsnull) {
+ PRUint32 bytes = mSegmentArrayCount * sizeof(char*);
+ mSegmentArray = (char**)nsMemory::Alloc(bytes);
+ if (mSegmentArray == nsnull)
+ return nsnull;
+ memset(mSegmentArray, 0, bytes);
+ }
+
+ if (IsFull()) {
+ PRUint32 newArraySize = mSegmentArrayCount * 2;
+ PRUint32 bytes = newArraySize * sizeof(char*);
+ char** newSegArray = (char**)nsMemory::Realloc(mSegmentArray, bytes);
+ if (newSegArray == nsnull)
+ return nsnull;
+ mSegmentArray = newSegArray;
+ // copy wrapped content to new extension
+ if (mFirstSegmentIndex > mLastSegmentIndex) {
+ // deal with wrap around case
+ memcpy(&mSegmentArray[mSegmentArrayCount],
+ mSegmentArray,
+ mLastSegmentIndex * sizeof(char*));
+ memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*));
+ mLastSegmentIndex += mSegmentArrayCount;
+ memset(&mSegmentArray[mLastSegmentIndex], 0,
+ (newArraySize - mLastSegmentIndex) * sizeof(char*));
+ }
+ else {
+ memset(&mSegmentArray[mLastSegmentIndex], 0,
+ (newArraySize - mLastSegmentIndex) * sizeof(char*));
+ }
+ mSegmentArrayCount = newArraySize;
+ }
+
+ char* seg = (char*)mSegAllocator->Alloc(mSegmentSize);
+ if (seg == nsnull) {
+ return nsnull;
+ }
+ mSegmentArray[mLastSegmentIndex] = seg;
+ mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1);
+ return seg;
+}
+
+PRBool
+nsSegmentedBuffer::DeleteFirstSegment()
+{
+ NS_ASSERTION(mSegmentArray[mFirstSegmentIndex] != nsnull, "deleting bad segment");
+ (void)mSegAllocator->Free(mSegmentArray[mFirstSegmentIndex]);
+ mSegmentArray[mFirstSegmentIndex] = nsnull;
+ PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
+ if (mFirstSegmentIndex == last) {
+ mLastSegmentIndex = last;
+ return PR_TRUE;
+ }
+ else {
+ mFirstSegmentIndex = ModSegArraySize(mFirstSegmentIndex + 1);
+ return PR_FALSE;
+ }
+}
+
+PRBool
+nsSegmentedBuffer::DeleteLastSegment()
+{
+ PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
+ NS_ASSERTION(mSegmentArray[last] != nsnull, "deleting bad segment");
+ (void)mSegAllocator->Free(mSegmentArray[last]);
+ mSegmentArray[last] = nsnull;
+ mLastSegmentIndex = last;
+ return (PRBool)(mLastSegmentIndex == mFirstSegmentIndex);
+}
+
+PRBool
+nsSegmentedBuffer::ReallocLastSegment(size_t newSize)
+{
+ PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
+ NS_ASSERTION(mSegmentArray[last] != nsnull, "realloc'ing bad segment");
+ char *newSegment =
+ (char*)mSegAllocator->Realloc(mSegmentArray[last], newSize);
+ if (newSegment) {
+ mSegmentArray[last] = newSegment;
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+void
+nsSegmentedBuffer::Empty()
+{
+ if (mSegmentArray) {
+ for (PRUint32 i = 0; i < mSegmentArrayCount; i++) {
+ if (mSegmentArray[i])
+ mSegAllocator->Free(mSegmentArray[i]);
+ }
+ nsMemory::Free(mSegmentArray);
+ mSegmentArray = nsnull;
+ }
+ mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
+ mFirstSegmentIndex = mLastSegmentIndex = 0;
+}
+
+#ifdef DEBUG
+NS_COM void
+TestSegmentedBuffer()
+{
+ nsSegmentedBuffer* buf = new nsSegmentedBuffer();
+ NS_ASSERTION(buf, "out of memory");
+ buf->Init(4, 16);
+ char* seg;
+ PRBool empty;
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(empty, "DeleteFirstSegment failed");
+ delete buf;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h
new file mode 100644
index 00000000..43620632
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsSegmentedBuffer_h__
+#define nsSegmentedBuffer_h__
+
+#include "nsMemory.h"
+#include "prclist.h"
+
+class nsSegmentedBuffer
+{
+public:
+ nsSegmentedBuffer()
+ : mSegmentSize(0), mMaxSize(0),
+ mSegAllocator(nsnull), mSegmentArray(nsnull),
+ mSegmentArrayCount(0),
+ mFirstSegmentIndex(0), mLastSegmentIndex(0) {}
+
+ ~nsSegmentedBuffer() {
+ Empty();
+ NS_IF_RELEASE(mSegAllocator);
+ }
+
+
+ NS_COM nsresult Init(PRUint32 segmentSize, PRUint32 maxSize,
+ nsIMemory* allocator = nsnull);
+
+ NS_COM char* AppendNewSegment(); // pushes at end
+
+ // returns true if no more segments remain:
+ PRBool DeleteFirstSegment(); // pops from beginning
+
+ // returns true if no more segments remain:
+ PRBool DeleteLastSegment(); // pops from beginning
+
+ // Call Realloc() on last segment. This is used to reduce memory
+ // consumption when data is not an exact multiple of segment size.
+ PRBool ReallocLastSegment(size_t newSize);
+
+ NS_COM void Empty(); // frees all segments
+
+ inline PRUint32 GetSegmentCount() {
+ if (mFirstSegmentIndex <= mLastSegmentIndex)
+ return mLastSegmentIndex - mFirstSegmentIndex;
+ else
+ return mSegmentArrayCount + mLastSegmentIndex - mFirstSegmentIndex;
+ }
+
+ inline PRUint32 GetSegmentSize() { return mSegmentSize; }
+ inline PRUint32 GetMaxSize() { return mMaxSize; }
+ inline PRUint32 GetSize() { return GetSegmentCount() * mSegmentSize; }
+
+ inline char* GetSegment(PRUint32 indx) {
+ NS_ASSERTION(indx < GetSegmentCount(), "index out of bounds");
+ PRInt32 i = ModSegArraySize(mFirstSegmentIndex + (PRInt32)indx);
+ return mSegmentArray[i];
+ }
+
+protected:
+ inline PRInt32 ModSegArraySize(PRInt32 n) {
+ PRUint32 result = n & (mSegmentArrayCount - 1);
+ NS_ASSERTION(result == n % mSegmentArrayCount,
+ "non-power-of-2 mSegmentArrayCount");
+ return result;
+ }
+
+ inline PRBool IsFull() {
+ return ModSegArraySize(mLastSegmentIndex + 1) == mFirstSegmentIndex;
+ }
+
+protected:
+ PRUint32 mSegmentSize;
+ PRUint32 mMaxSize;
+ nsIMemory* mSegAllocator;
+ char** mSegmentArray;
+ PRUint32 mSegmentArrayCount;
+ PRInt32 mFirstSegmentIndex;
+ PRInt32 mLastSegmentIndex;
+};
+
+// NS_SEGMENTARRAY_INITIAL_SIZE: This number needs to start out as a
+// power of 2 given how it gets used. We double the segment array
+// when we overflow it, and use that fact that it's a power of 2
+// to compute a fast modulus operation in IsFull.
+//
+// 32 segment array entries can accommodate 128k of data if segments
+// are 4k in size. That seems like a reasonable amount that will avoid
+// needing to grow the segment array.
+#define NS_SEGMENTARRAY_INITIAL_COUNT 32
+
+#endif // nsSegmentedBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp
new file mode 100644
index 00000000..2a6b0166
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp
@@ -0,0 +1,563 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * The storage stream provides an internal buffer that can be filled by a
+ * client using a single output stream. One or more independent input streams
+ * can be created to read the data out non-destructively. The implementation
+ * uses a segmented buffer internally to avoid realloc'ing of large buffers,
+ * with the attendant performance loss and heap fragmentation.
+ */
+
+#include "nsStorageStream.h"
+#include "nsSegmentedBuffer.h"
+#include "nsCOMPtr.h"
+#include "prbit.h"
+#include "nsIInputStream.h"
+#include "nsISeekableStream.h"
+#include "prlog.h"
+#include "nsInt64.h"
+#if defined(PR_LOGGING)
+//
+// Log module for StorageStream logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=StorageStreamLog:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+//
+PRLogModuleInfo* StorageStreamLog = nsnull;
+
+#endif /* PR_LOGGING */
+
+nsStorageStream::nsStorageStream()
+ : mSegmentedBuffer(0), mSegmentSize(0), mWriteInProgress(PR_FALSE),
+ mLastSegmentNum(-1), mWriteCursor(0), mSegmentEnd(0), mLogicalLength(0)
+{
+#if defined(PR_LOGGING)
+ //
+ // Initialize the global PRLogModule for socket transport logging
+ // if necessary...
+ //
+ if (nsnull == StorageStreamLog) {
+ StorageStreamLog = PR_NewLogModule("StorageStreamLog");
+ }
+#endif /* PR_LOGGING */
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("Creating nsStorageStream [%x].\n", this));
+}
+
+nsStorageStream::~nsStorageStream()
+{
+ if (mSegmentedBuffer)
+ delete mSegmentedBuffer;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageStream,
+ nsIStorageStream,
+ nsIOutputStream)
+
+NS_IMETHODIMP
+nsStorageStream::Init(PRUint32 segmentSize, PRUint32 maxSize,
+ nsIMemory *segmentAllocator)
+{
+ mSegmentedBuffer = new nsSegmentedBuffer();
+ if (!mSegmentedBuffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mSegmentSize = segmentSize;
+ mSegmentSizeLog2 = PR_FloorLog2(segmentSize);
+
+ // Segment size must be a power of two
+ if (mSegmentSize != ((PRUint32)1 << mSegmentSizeLog2))
+ return NS_ERROR_INVALID_ARG;
+
+ return mSegmentedBuffer->Init(segmentSize, maxSize, segmentAllocator);
+}
+
+NS_IMETHODIMP
+nsStorageStream::GetOutputStream(PRInt32 aStartingOffset,
+ nsIOutputStream * *aOutputStream)
+{
+ NS_ENSURE_ARG(aOutputStream);
+ if (mWriteInProgress)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsresult rv = Seek(aStartingOffset);
+ if (NS_FAILED(rv)) return rv;
+
+ // Enlarge the last segment in the buffer so that it is the same size as
+ // all the other segments in the buffer. (It may have been realloc'ed
+ // smaller in the Close() method.)
+ if (mLastSegmentNum >= 0)
+ mSegmentedBuffer->ReallocLastSegment(mSegmentSize);
+
+ // Need to re-Seek, since realloc might have changed segment base pointer
+ rv = Seek(aStartingOffset);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ADDREF(this);
+ *aOutputStream = NS_STATIC_CAST(nsIOutputStream*, this);
+ mWriteInProgress = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::Close()
+{
+ mWriteInProgress = PR_FALSE;
+
+ PRInt32 segmentOffset = SegOffset(mLogicalLength);
+
+ // Shrink the final segment in the segmented buffer to the minimum size
+ // needed to contain the data, so as to conserve memory.
+ if (segmentOffset)
+ mSegmentedBuffer->ReallocLastSegment(segmentOffset);
+
+ mWriteCursor = 0;
+ mSegmentEnd = 0;
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Close mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::Flush()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
+{
+ const char* readCursor;
+ PRUint32 count, availableInSegment, remaining;
+ nsresult rv = NS_OK;
+
+ NS_ENSURE_ARG_POINTER(aNumWritten);
+ NS_ENSURE_ARG(aBuffer);
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Write mWriteCursor=%x mSegmentEnd=%x aCount=%d\n",
+ this, mWriteCursor, mSegmentEnd, aCount));
+
+ remaining = aCount;
+ readCursor = aBuffer;
+ while (remaining) {
+ availableInSegment = mSegmentEnd - mWriteCursor;
+ if (!availableInSegment) {
+ mWriteCursor = mSegmentedBuffer->AppendNewSegment();
+ if (!mWriteCursor) {
+ mSegmentEnd = 0;
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ mLastSegmentNum++;
+ mSegmentEnd = mWriteCursor + mSegmentSize;
+ availableInSegment = mSegmentEnd - mWriteCursor;
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Write (new seg) mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+ }
+
+ count = PR_MIN(availableInSegment, remaining);
+ memcpy(mWriteCursor, readCursor, count);
+ remaining -= count;
+ readCursor += count;
+ mWriteCursor += count;
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Writing mWriteCursor=%x mSegmentEnd=%x count=%d\n",
+ this, mWriteCursor, mSegmentEnd, count));
+ };
+
+ out:
+ *aNumWritten = aCount - remaining;
+ mLogicalLength += *aNumWritten;
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Wrote mWriteCursor=%x mSegmentEnd=%x numWritten=%d\n",
+ this, mWriteCursor, mSegmentEnd, *aNumWritten));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsStorageStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteFrom");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsStorageStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsStorageStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::GetLength(PRUint32 *aLength)
+{
+ NS_ENSURE_ARG(aLength);
+ *aLength = mLogicalLength;
+ return NS_OK;
+}
+
+// Truncate the buffer by deleting the end segments
+NS_IMETHODIMP
+nsStorageStream::SetLength(PRUint32 aLength)
+{
+ if (mWriteInProgress)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ if (aLength > mLogicalLength)
+ return NS_ERROR_INVALID_ARG;
+
+ PRInt32 newLastSegmentNum = SegNum(aLength);
+ PRInt32 segmentOffset = SegOffset(aLength);
+ if (segmentOffset == 0)
+ newLastSegmentNum--;
+
+ while (newLastSegmentNum < mLastSegmentNum) {
+ mSegmentedBuffer->DeleteLastSegment();
+ mLastSegmentNum--;
+ }
+
+ mLogicalLength = aLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::GetWriteInProgress(PRBool *aWriteInProgress)
+{
+ NS_ENSURE_ARG(aWriteInProgress);
+
+ *aWriteInProgress = mWriteInProgress;
+ return NS_OK;
+}
+
+NS_METHOD
+nsStorageStream::Seek(PRInt32 aPosition)
+{
+ // An argument of -1 means "seek to end of stream"
+ if (aPosition == -1)
+ aPosition = mLogicalLength;
+
+ // Seeking beyond the buffer end is illegal
+ if ((PRUint32)aPosition > mLogicalLength)
+ return NS_ERROR_INVALID_ARG;
+
+ // Seeking backwards in the write stream results in truncation
+ SetLength(aPosition);
+
+ // Special handling for seek to start-of-buffer
+ if (aPosition == 0) {
+ mWriteCursor = 0;
+ mSegmentEnd = 0;
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Seek mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+ return NS_OK;
+ }
+
+ // Segment may have changed, so reset pointers
+ mWriteCursor = mSegmentedBuffer->GetSegment(mLastSegmentNum);
+ NS_ASSERTION(mWriteCursor, "null mWriteCursor");
+ mSegmentEnd = mWriteCursor + mSegmentSize;
+ PRInt32 segmentOffset = SegOffset(aPosition);
+ mWriteCursor += segmentOffset;
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Seek mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// There can be many nsStorageInputStreams for a single nsStorageStream
+class nsStorageInputStream : public nsIInputStream
+ , public nsISeekableStream
+{
+public:
+ nsStorageInputStream(nsStorageStream *aStorageStream, PRUint32 aSegmentSize)
+ : mStorageStream(aStorageStream), mReadCursor(0),
+ mSegmentEnd(0), mSegmentNum(0),
+ mSegmentSize(aSegmentSize), mLogicalCursor(0)
+ {
+ NS_ADDREF(mStorageStream);
+ }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+
+private:
+ ~nsStorageInputStream()
+ {
+ NS_IF_RELEASE(mStorageStream);
+ }
+
+protected:
+ NS_METHOD Seek(PRUint32 aPosition);
+
+ friend class nsStorageStream;
+
+private:
+ nsStorageStream* mStorageStream;
+ const char* mReadCursor; // Next memory location to read byte, or NULL
+ const char* mSegmentEnd; // One byte past end of current buffer segment
+ PRUint32 mSegmentNum; // Segment number containing read cursor
+ PRUint32 mSegmentSize; // All segments, except the last, are of this size
+ PRUint32 mLogicalCursor; // Logical offset into stream
+
+ PRUint32 SegNum(PRUint32 aPosition) {return aPosition >> mStorageStream->mSegmentSizeLog2;}
+ PRUint32 SegOffset(PRUint32 aPosition) {return aPosition & (mSegmentSize - 1);}
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageInputStream,
+ nsIInputStream,
+ nsISeekableStream)
+
+NS_IMETHODIMP
+nsStorageStream::NewInputStream(PRInt32 aStartingOffset, nsIInputStream* *aInputStream)
+{
+ nsStorageInputStream *inputStream = new nsStorageInputStream(this, mSegmentSize);
+ if (!inputStream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(inputStream);
+
+ nsresult rv = inputStream->Seek(aStartingOffset);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(inputStream);
+ return rv;
+ }
+
+ *aInputStream = inputStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Close()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Available(PRUint32 *aAvailable)
+{
+ *aAvailable = mStorageStream->mLogicalLength - mLogicalCursor;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ char* writeCursor;
+ PRUint32 count, availableInSegment, remainingCapacity;
+
+ remainingCapacity = aCount;
+ writeCursor = aBuffer;
+ while (remainingCapacity) {
+ availableInSegment = mSegmentEnd - mReadCursor;
+ if (!availableInSegment) {
+ PRUint32 available = mStorageStream->mLogicalLength - mLogicalCursor;
+ if (!available)
+ goto out;
+
+ mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(++mSegmentNum);
+ mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize, available);
+ }
+
+ count = PR_MIN(availableInSegment, remainingCapacity);
+ memcpy(writeCursor, mReadCursor, count);
+ remainingCapacity -= count;
+ mReadCursor += count;
+ writeCursor += count;
+ mLogicalCursor += count;
+ };
+
+ out:
+ *aNumRead = aCount - remainingCapacity;
+
+ PRBool isWriteInProgress = PR_FALSE;
+ if (NS_FAILED(mStorageStream->GetWriteInProgress(&isWriteInProgress)))
+ isWriteInProgress = PR_FALSE;
+
+ if (*aNumRead == 0 && isWriteInProgress)
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ else
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ PRUint32 count, availableInSegment, remainingCapacity, bytesConsumed;
+ nsresult rv;
+
+ remainingCapacity = aCount;
+ while (remainingCapacity) {
+ availableInSegment = mSegmentEnd - mReadCursor;
+ if (!availableInSegment) {
+ PRUint32 available = mStorageStream->mLogicalLength - mLogicalCursor;
+ if (!available)
+ goto out;
+
+ mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(++mSegmentNum);
+ mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize, available);
+ availableInSegment = mSegmentEnd - mReadCursor;
+ }
+
+ count = PR_MIN(availableInSegment, remainingCapacity);
+ rv = writer(this, closure, mReadCursor, mLogicalCursor, count, &bytesConsumed);
+ if (NS_FAILED(rv) || (bytesConsumed == 0))
+ break;
+ remainingCapacity -= bytesConsumed;
+ mReadCursor += bytesConsumed;
+ mLogicalCursor += bytesConsumed;
+ };
+
+ out:
+ *aNumRead = aCount - remainingCapacity;
+
+ PRBool isWriteInProgress = PR_FALSE;
+ if (NS_FAILED(mStorageStream->GetWriteInProgress(&isWriteInProgress)))
+ isWriteInProgress = PR_FALSE;
+
+ if (*aNumRead == 0 && isWriteInProgress)
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ else
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ nsInt64 pos = aOffset;
+
+ switch (aWhence) {
+ case NS_SEEK_SET:
+ break;
+ case NS_SEEK_CUR:
+ pos += mLogicalCursor;
+ break;
+ case NS_SEEK_END:
+ pos += mStorageStream->mLogicalLength;
+ break;
+ default:
+ NS_NOTREACHED("unexpected whence value");
+ return NS_ERROR_UNEXPECTED;
+ }
+ nsInt64 logicalCursor(mLogicalCursor);
+ if (pos == logicalCursor)
+ return NS_OK;
+
+ return Seek(pos);
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Tell(PRInt64 *aResult)
+{
+ LL_UI2L(*aResult, mLogicalCursor);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::SetEOF()
+{
+ NS_NOTREACHED("nsStorageInputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD
+nsStorageInputStream::Seek(PRUint32 aPosition)
+{
+ PRUint32 length = mStorageStream->mLogicalLength;
+ if (aPosition >= length)
+ return NS_ERROR_INVALID_ARG;
+
+ mSegmentNum = SegNum(aPosition);
+ PRUint32 segmentOffset = SegOffset(aPosition);
+ mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(mSegmentNum) +
+ segmentOffset;
+ PRUint32 available = length - aPosition;
+ mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize - segmentOffset, available);
+ mLogicalCursor = aPosition;
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewStorageStream(PRUint32 segmentSize, PRUint32 maxSize, nsIStorageStream **result)
+{
+ NS_ENSURE_ARG(result);
+
+ nsStorageStream* storageStream = new nsStorageStream();
+ if (!storageStream) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(storageStream);
+ nsresult rv = storageStream->Init(segmentSize, maxSize, nsnull);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(storageStream);
+ return rv;
+ }
+ *result = storageStream;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStorageStream.h b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.h
new file mode 100644
index 00000000..0729c01c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * The storage stream provides an internal buffer that can be filled by a
+ * client using a single output stream. One or more independent input streams
+ * can be created to read the data out non-destructively. The implementation
+ * uses a segmented buffer internally to avoid realloc'ing of large buffers,
+ * with the attendant performance loss and heap fragmentation.
+ */
+
+#ifndef _nsStorageStream_h_
+#define _nsStorageStream_h_
+
+#include "nsIStorageStream.h"
+#include "nsIOutputStream.h"
+#include "nsMemory.h"
+
+#define NS_STORAGESTREAM_CID \
+{ /* 669a9795-6ff7-4ed4-9150-c34ce2971b63 */ \
+ 0x669a9795, \
+ 0x6ff7, \
+ 0x4ed4, \
+ {0x91, 0x50, 0xc3, 0x4c, 0xe2, 0x97, 0x1b, 0x63} \
+}
+
+#define NS_STORAGESTREAM_CONTRACTID "@mozilla.org/storagestream;1"
+#define NS_STORAGESTREAM_CLASSNAME "Storage Stream"
+
+class nsSegmentedBuffer;
+
+class nsStorageStream : public nsIStorageStream,
+ public nsIOutputStream
+{
+public:
+ nsStorageStream();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTORAGESTREAM
+ NS_DECL_NSIOUTPUTSTREAM
+
+ friend class nsStorageInputStream;
+
+private:
+ ~nsStorageStream();
+
+ nsSegmentedBuffer* mSegmentedBuffer;
+ PRUint32 mSegmentSize; // All segments, except possibly the last, are of this size
+ // Must be power-of-2
+ PRUint32 mSegmentSizeLog2; // log2(mSegmentSize)
+ PRBool mWriteInProgress; // true, if an un-Close'ed output stream exists
+ PRInt32 mLastSegmentNum; // Last segment # in use, -1 initially
+ char* mWriteCursor; // Pointer to next byte to be written
+ char* mSegmentEnd; // Pointer to one byte after end of segment
+ // containing the write cursor
+ PRUint32 mLogicalLength; // Number of bytes written to stream
+
+ NS_METHOD Seek(PRInt32 aPosition);
+ PRUint32 SegNum(PRUint32 aPosition) {return aPosition >> mSegmentSizeLog2;}
+ PRUint32 SegOffset(PRUint32 aPosition) {return aPosition & (mSegmentSize - 1);}
+};
+
+#endif // _nsStorageStream_h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp
new file mode 100644
index 00000000..aeb52b2a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp
@@ -0,0 +1,583 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 "nsStreamUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIPipe.h"
+#include "nsIEventTarget.h"
+#include "nsAutoLock.h"
+
+//-----------------------------------------------------------------------------
+
+class nsInputStreamReadyEvent : public PLEvent
+ , public nsIInputStreamCallback
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ nsInputStreamReadyEvent(nsIInputStreamCallback *callback,
+ nsIEventTarget *target)
+ : mCallback(callback)
+ , mTarget(target)
+ {
+ }
+
+private:
+ ~nsInputStreamReadyEvent()
+ {
+ if (mCallback) {
+ nsresult rv;
+ //
+ // whoa!! looks like we never posted this event. take care to
+ // release mCallback on the correct thread. if mTarget lives on the
+ // calling thread, then we are ok. otherwise, we have to try to
+ // proxy the Release over the right thread. if that thread is dead,
+ // then there's nothing we can do... better to leak than crash.
+ //
+ PRBool val;
+ rv = mTarget->IsOnCurrentThread(&val);
+ if (NS_FAILED(rv) || !val) {
+ nsCOMPtr<nsIInputStreamCallback> event;
+ NS_NewInputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget);
+ mCallback = 0;
+ if (event) {
+ rv = event->OnInputStreamReady(nsnull);
+ if (NS_FAILED(rv)) {
+ NS_NOTREACHED("leaking stream event");
+ nsISupports *sup = event;
+ NS_ADDREF(sup);
+ }
+ }
+ }
+ }
+ }
+
+public:
+ NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *stream)
+ {
+ mStream = stream;
+
+ // will be released when event is handled
+ NS_ADDREF_THIS();
+
+ PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
+
+ if (NS_FAILED(mTarget->PostEvent(this))) {
+ NS_WARNING("PostEvent failed");
+ NS_RELEASE_THIS();
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+ }
+
+private:
+ nsCOMPtr<nsIAsyncInputStream> mStream;
+ nsCOMPtr<nsIInputStreamCallback> mCallback;
+ nsCOMPtr<nsIEventTarget> mTarget;
+
+ PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent)
+ {
+ nsInputStreamReadyEvent *ev = (nsInputStreamReadyEvent *) plevent;
+ // bypass event delivery if this is a cleanup event...
+ if (ev->mCallback)
+ ev->mCallback->OnInputStreamReady(ev->mStream);
+ ev->mCallback = 0;
+ return NULL;
+ }
+
+ PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *plevent)
+ {
+ nsInputStreamReadyEvent *ev = (nsInputStreamReadyEvent *) plevent;
+ NS_RELEASE(ev);
+ }
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsInputStreamReadyEvent,
+ nsIInputStreamCallback)
+
+//-----------------------------------------------------------------------------
+
+class nsOutputStreamReadyEvent : public PLEvent
+ , public nsIOutputStreamCallback
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ nsOutputStreamReadyEvent(nsIOutputStreamCallback *callback,
+ nsIEventTarget *target)
+ : mCallback(callback)
+ , mTarget(target)
+ {
+ }
+
+private:
+ ~nsOutputStreamReadyEvent()
+ {
+ if (mCallback) {
+ nsresult rv;
+ //
+ // whoa!! looks like we never posted this event. take care to
+ // release mCallback on the correct thread. if mTarget lives on the
+ // calling thread, then we are ok. otherwise, we have to try to
+ // proxy the Release over the right thread. if that thread is dead,
+ // then there's nothing we can do... better to leak than crash.
+ //
+ PRBool val;
+ rv = mTarget->IsOnCurrentThread(&val);
+ if (NS_FAILED(rv) || !val) {
+ nsCOMPtr<nsIOutputStreamCallback> event;
+ NS_NewOutputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget);
+ mCallback = 0;
+ if (event) {
+ rv = event->OnOutputStreamReady(nsnull);
+ if (NS_FAILED(rv)) {
+ NS_NOTREACHED("leaking stream event");
+ nsISupports *sup = event;
+ NS_ADDREF(sup);
+ }
+ }
+ }
+ }
+ }
+
+public:
+ void Init(nsIOutputStreamCallback *callback, nsIEventTarget *target)
+ {
+ mCallback = callback;
+ mTarget = target;
+
+ PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
+ }
+
+ NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *stream)
+ {
+ mStream = stream;
+
+ // this will be released when the event is handled
+ NS_ADDREF_THIS();
+
+ PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
+
+ if (NS_FAILED(mTarget->PostEvent(this))) {
+ NS_WARNING("PostEvent failed");
+ NS_RELEASE_THIS();
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+ }
+
+private:
+ nsCOMPtr<nsIAsyncOutputStream> mStream;
+ nsCOMPtr<nsIOutputStreamCallback> mCallback;
+ nsCOMPtr<nsIEventTarget> mTarget;
+
+ PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent)
+ {
+ nsOutputStreamReadyEvent *ev = (nsOutputStreamReadyEvent *) plevent;
+ if (ev->mCallback)
+ ev->mCallback->OnOutputStreamReady(ev->mStream);
+ ev->mCallback = 0;
+ return NULL;
+ }
+
+ PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *ev)
+ {
+ nsOutputStreamReadyEvent *event = (nsOutputStreamReadyEvent *) ev;
+ NS_RELEASE(event);
+ }
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsOutputStreamReadyEvent,
+ nsIOutputStreamCallback)
+
+//-----------------------------------------------------------------------------
+
+NS_COM nsresult
+NS_NewInputStreamReadyEvent(nsIInputStreamCallback **event,
+ nsIInputStreamCallback *callback,
+ nsIEventTarget *target)
+{
+ nsInputStreamReadyEvent *ev = new nsInputStreamReadyEvent(callback, target);
+ if (!ev)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*event = ev);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **event,
+ nsIOutputStreamCallback *callback,
+ nsIEventTarget *target)
+{
+ nsOutputStreamReadyEvent *ev = new nsOutputStreamReadyEvent(callback, target);
+ if (!ev)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*event = ev);
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// NS_AsyncCopy implementation
+
+// abstract stream copier...
+class nsAStreamCopier : public nsIInputStreamCallback
+ , public nsIOutputStreamCallback
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ nsAStreamCopier()
+ : mLock(nsnull)
+ , mCallback(nsnull)
+ , mClosure(nsnull)
+ , mChunkSize(0)
+ , mEventInProcess(PR_FALSE)
+ , mEventIsPending(PR_FALSE)
+ {
+ }
+
+ // virtual since subclasses call superclass Release()
+ virtual ~nsAStreamCopier()
+ {
+ if (mLock)
+ PR_DestroyLock(mLock);
+ }
+
+ // kick off the async copy...
+ nsresult Start(nsIInputStream *source,
+ nsIOutputStream *sink,
+ nsIEventTarget *target,
+ nsAsyncCopyCallbackFun callback,
+ void *closure,
+ PRUint32 chunksize)
+ {
+ mSource = source;
+ mSink = sink;
+ mTarget = target;
+ mCallback = callback;
+ mClosure = closure;
+ mChunkSize = chunksize;
+
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAsyncSource = do_QueryInterface(mSource);
+ mAsyncSink = do_QueryInterface(mSink);
+
+ return PostContinuationEvent();
+ }
+
+ // implemented by subclasses, returns number of bytes copied and
+ // sets source and sink condition before returning.
+ virtual PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition) = 0;
+
+ void Process()
+ {
+ if (!mSource || !mSink)
+ return;
+
+ nsresult sourceCondition, sinkCondition;
+
+ // ok, copy data from source to sink.
+ for (;;) {
+ PRUint32 n = DoCopy(&sourceCondition, &sinkCondition);
+ if (NS_FAILED(sourceCondition) || NS_FAILED(sinkCondition) || n == 0) {
+ if (sourceCondition == NS_BASE_STREAM_WOULD_BLOCK && mAsyncSource) {
+ // need to wait for more data from source. while waiting for
+ // more source data, be sure to observe failures on output end.
+ mAsyncSource->AsyncWait(this, 0, 0, nsnull);
+
+ if (mAsyncSink)
+ mAsyncSink->AsyncWait(this,
+ nsIAsyncOutputStream::WAIT_CLOSURE_ONLY,
+ 0, nsnull);
+ }
+ else if (sinkCondition == NS_BASE_STREAM_WOULD_BLOCK && mAsyncSink) {
+ // need to wait for more room in the sink. while waiting for
+ // more room in the sink, be sure to observer failures on the
+ // input end.
+ mAsyncSink->AsyncWait(this, 0, 0, nsnull);
+
+ if (mAsyncSource)
+ mAsyncSource->AsyncWait(this,
+ nsIAsyncInputStream::WAIT_CLOSURE_ONLY,
+ 0, nsnull);
+ }
+ else {
+ // close source
+ if (mAsyncSource)
+ mAsyncSource->CloseWithStatus(sinkCondition);
+ else
+ mSource->Close();
+ mAsyncSource = nsnull;
+ mSource = nsnull;
+
+ // close sink
+ if (mAsyncSink)
+ mAsyncSink->CloseWithStatus(sourceCondition);
+ else
+ mSink->Close();
+ mAsyncSink = nsnull;
+ mSink = nsnull;
+
+ // notify state complete...
+ if (mCallback) {
+ nsresult status = sourceCondition;
+ if (NS_SUCCEEDED(status))
+ status = sinkCondition;
+ if (status == NS_BASE_STREAM_CLOSED)
+ status = NS_OK;
+ mCallback(mClosure, status);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *source)
+ {
+ PostContinuationEvent();
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *sink)
+ {
+ PostContinuationEvent();
+ return NS_OK;
+ }
+
+ PR_STATIC_CALLBACK(void*) HandleContinuationEvent(PLEvent *event)
+ {
+ nsAStreamCopier *self = (nsAStreamCopier *) event->owner;
+ self->Process();
+
+ // clear "in process" flag and post any pending continuation event
+ nsAutoLock lock(self->mLock);
+ self->mEventInProcess = PR_FALSE;
+ if (self->mEventIsPending) {
+ self->mEventIsPending = PR_FALSE;
+ self->PostContinuationEvent_Locked();
+ }
+ return nsnull;
+ }
+
+ PR_STATIC_CALLBACK(void) DestroyContinuationEvent(PLEvent *event)
+ {
+ nsAStreamCopier *self = (nsAStreamCopier *) event->owner;
+ NS_RELEASE(self);
+ delete event;
+ }
+
+ nsresult PostContinuationEvent()
+ {
+ // we cannot post a continuation event if there is currently
+ // an event in process. doing so could result in Process being
+ // run simultaneously on multiple threads, so we mark the event
+ // as pending, and if an event is already in process then we
+ // just let that existing event take care of posting the real
+ // continuation event.
+
+ nsAutoLock lock(mLock);
+ return PostContinuationEvent_Locked();
+ }
+
+ nsresult PostContinuationEvent_Locked()
+ {
+ nsresult rv = NS_OK;
+ if (mEventInProcess)
+ mEventIsPending = PR_TRUE;
+ else {
+ PLEvent *event = new PLEvent;
+ if (!event)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ else {
+ NS_ADDREF_THIS();
+ PL_InitEvent(event, this,
+ HandleContinuationEvent,
+ DestroyContinuationEvent);
+
+ rv = mTarget->PostEvent(event);
+ if (NS_SUCCEEDED(rv))
+ mEventInProcess = PR_TRUE;
+ else {
+ NS_ERROR("unable to post continuation event");
+ PL_DestroyEvent(event);
+ }
+ }
+ }
+ return rv;
+ }
+
+protected:
+ nsCOMPtr<nsIInputStream> mSource;
+ nsCOMPtr<nsIOutputStream> mSink;
+ nsCOMPtr<nsIAsyncInputStream> mAsyncSource;
+ nsCOMPtr<nsIAsyncOutputStream> mAsyncSink;
+ nsCOMPtr<nsIEventTarget> mTarget;
+ PRLock *mLock;
+ nsAsyncCopyCallbackFun mCallback;
+ void *mClosure;
+ PRUint32 mChunkSize;
+ PRPackedBool mEventInProcess;
+ PRPackedBool mEventIsPending;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsAStreamCopier,
+ nsIInputStreamCallback,
+ nsIOutputStreamCallback)
+
+class nsStreamCopierIB : public nsAStreamCopier
+{
+public:
+ nsStreamCopierIB() : nsAStreamCopier() {}
+ virtual ~nsStreamCopierIB() {}
+
+ struct ReadSegmentsState {
+ nsIOutputStream *mSink;
+ nsresult mSinkCondition;
+ };
+
+ static NS_METHOD ConsumeInputBuffer(nsIInputStream *inStr,
+ void *closure,
+ const char *buffer,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *countWritten)
+ {
+ ReadSegmentsState *state = (ReadSegmentsState *) closure;
+
+ nsresult rv = state->mSink->Write(buffer, count, countWritten);
+ if (NS_FAILED(rv))
+ state->mSinkCondition = rv;
+ else if (*countWritten == 0)
+ state->mSinkCondition = NS_BASE_STREAM_CLOSED;
+
+ return state->mSinkCondition;
+ }
+
+ PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition)
+ {
+ ReadSegmentsState state;
+ state.mSink = mSink;
+ state.mSinkCondition = NS_OK;
+
+ PRUint32 n;
+ *sourceCondition =
+ mSource->ReadSegments(ConsumeInputBuffer, &state, mChunkSize, &n);
+ *sinkCondition = state.mSinkCondition;
+ return n;
+ }
+};
+
+class nsStreamCopierOB : public nsAStreamCopier
+{
+public:
+ nsStreamCopierOB() : nsAStreamCopier() {}
+ virtual ~nsStreamCopierOB() {}
+
+ struct WriteSegmentsState {
+ nsIInputStream *mSource;
+ nsresult mSourceCondition;
+ };
+
+ static NS_METHOD FillOutputBuffer(nsIOutputStream *outStr,
+ void *closure,
+ char *buffer,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *countRead)
+ {
+ WriteSegmentsState *state = (WriteSegmentsState *) closure;
+
+ nsresult rv = state->mSource->Read(buffer, count, countRead);
+ if (NS_FAILED(rv))
+ state->mSourceCondition = rv;
+ else if (*countRead == 0)
+ state->mSourceCondition = NS_BASE_STREAM_CLOSED;
+
+ return state->mSourceCondition;
+ }
+
+ PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition)
+ {
+ WriteSegmentsState state;
+ state.mSource = mSource;
+ state.mSourceCondition = NS_OK;
+
+ PRUint32 n;
+ *sinkCondition =
+ mSink->WriteSegments(FillOutputBuffer, &state, mChunkSize, &n);
+ *sourceCondition = state.mSourceCondition;
+ return n;
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+NS_COM nsresult
+NS_AsyncCopy(nsIInputStream *source,
+ nsIOutputStream *sink,
+ nsIEventTarget *target,
+ nsAsyncCopyMode mode,
+ PRUint32 chunkSize,
+ nsAsyncCopyCallbackFun callback,
+ void *closure)
+{
+ NS_ASSERTION(target, "non-null target required");
+
+ nsresult rv;
+ nsAStreamCopier *copier;
+
+ if (mode == NS_ASYNCCOPY_VIA_READSEGMENTS)
+ copier = new nsStreamCopierIB();
+ else
+ copier = new nsStreamCopierOB();
+
+ if (!copier)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Start() takes an owning ref to the copier...
+ NS_ADDREF(copier);
+ rv = copier->Start(source, sink, target, callback, closure, chunkSize);
+ NS_RELEASE(copier);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h
new file mode 100644
index 00000000..3d33f1c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h
@@ -0,0 +1,111 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef nsStreamUtils_h__
+#define nsStreamUtils_h__
+
+#include "nscore.h"
+
+class nsIInputStream;
+class nsIOutputStream;
+class nsIInputStreamCallback;
+class nsIOutputStreamCallback;
+class nsIEventTarget;
+
+/**
+ * A "one-shot" proxy of the OnInputStreamReady callback. The resulting
+ * proxy object's OnInputStreamReady function may only be called once! The
+ * proxy object ensures that the real notify object will be free'd on the
+ * thread corresponding to the given event target regardless of what thread
+ * the proxy object is destroyed on.
+ *
+ * This function is designed to be used to implement AsyncWait when the
+ * aEventTarget parameter is non-null.
+ */
+extern NS_COM nsresult
+NS_NewInputStreamReadyEvent(nsIInputStreamCallback **aEvent,
+ nsIInputStreamCallback *aNotify,
+ nsIEventTarget *aEventTarget);
+
+/**
+ * A "one-shot" proxy of the OnOutputStreamReady callback. The resulting
+ * proxy object's OnOutputStreamReady function may only be called once! The
+ * proxy object ensures that the real notify object will be free'd on the
+ * thread corresponding to the given event target regardless of what thread
+ * the proxy object is destroyed on.
+ *
+ * This function is designed to be used to implement AsyncWait when the
+ * aEventTarget parameter is non-null.
+ */
+extern NS_COM nsresult
+NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **aEvent,
+ nsIOutputStreamCallback *aNotify,
+ nsIEventTarget *aEventTarget);
+
+/* ------------------------------------------------------------------------- */
+
+enum nsAsyncCopyMode {
+ NS_ASYNCCOPY_VIA_READSEGMENTS,
+ NS_ASYNCCOPY_VIA_WRITESEGMENTS
+};
+
+/**
+ * This function is called when the async copy process completes. The reported
+ * status is NS_OK on success and some error code on failure.
+ */
+typedef void (* nsAsyncCopyCallbackFun)(void *closure, nsresult status);
+
+/**
+ * This function asynchronously copies data from the source to the sink. All
+ * data transfer occurs on the thread corresponding to the given event target.
+ * A null event target is not permitted.
+ *
+ * The copier handles blocking or non-blocking streams transparently. If a
+ * stream operation returns NS_BASE_STREAM_WOULD_BLOCK, then the stream will
+ * be QI'd to nsIAsync{In,Out}putStream and its AsyncWait method will be used
+ * to determine when to resume copying.
+ */
+extern NS_COM nsresult
+NS_AsyncCopy(nsIInputStream *aSource,
+ nsIOutputStream *aSink,
+ nsIEventTarget *aEventTarget,
+ nsAsyncCopyMode aMode = NS_ASYNCCOPY_VIA_READSEGMENTS,
+ PRUint32 aChunkSize = 4096,
+ nsAsyncCopyCallbackFun aCallbackFun = nsnull,
+ void *aCallbackClosure = nsnull);
+
+#endif // !nsStreamUtils_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStringIO.h b/src/libs/xpcom18a4/xpcom/io/nsStringIO.h
new file mode 100644
index 00000000..beca1d19
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStringIO.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsStringIO_h___
+#define nsStringIO_h___
+
+#include "nsAString.h"
+#include <stdio.h>
+
+
+template <class CharT>
+class nsFileCharSink
+ {
+ public:
+ typedef CharT value_type;
+
+ public:
+ nsFileCharSink( FILE* aOutputFile ) : mOutputFile(aOutputFile) { }
+
+ PRUint32
+ write( const value_type* s, PRUint32 n )
+ {
+ return fwrite(s, sizeof(CharT), n, mOutputFile);
+ }
+
+ private:
+ FILE* mOutputFile;
+ };
+
+
+template <class CharT>
+inline
+void
+fprint_string( FILE* aFile, const basic_nsAString<CharT>& aString )
+ {
+ nsReadingIterator<CharT> fromBegin, fromEnd;
+ nsFileCharSink<CharT> toBegin(aFile);
+ copy_string(aString.BeginReading(fromBegin), aString.EndReading(fromEnd), toBegin);
+ }
+
+
+template <class CharT>
+inline
+void
+print_string( const basic_nsAString<CharT>& aString )
+ {
+ fprint_string(stdout, aString);
+ }
+
+
+#endif // !defined(nsStringIO_h___)
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp
new file mode 100644
index 00000000..536eab11
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp
@@ -0,0 +1,457 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * mcmullen@netscape.com (original author)
+ * warren@netscape.com
+ * alecf@netscape.com
+ * scc@mozilla.org
+ * david.gardiner@unisa.edu.au
+ * fur@netscape.com
+ * norris@netscape.com
+ * pinkerton@netscape.com
+ * davidm@netscape.com
+ * sfraser@netscape.com
+ * darin@netscape.com
+ * bzbarsky@mit.edu
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Based on original code from nsIStringStream.cpp
+ */
+
+#include "nsStringStream.h"
+
+#include "prerror.h"
+#include "plstr.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsISeekableStream.h"
+#include "nsInt64.h"
+
+#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
+#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
+
+static nsresult ns_file_convert_result(PRInt32 nativeErr)
+{
+ return nativeErr ?
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
+ : NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// nsIStringInputStream implementation
+//-----------------------------------------------------------------------------
+
+class nsStringInputStream : public nsIStringInputStream
+ , public nsIRandomAccessStore
+
+{
+public:
+ nsStringInputStream()
+ : mOffset(0)
+ , mLastResult(NS_OK)
+ , mEOF(PR_FALSE)
+ , mOwned(PR_FALSE)
+ , mConstString(nsnull)
+ , mLength(0)
+ {}
+
+private:
+ ~nsStringInputStream()
+ {
+ if (mOwned)
+ nsMemory::Free((char*)mConstString);
+ }
+
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSISTRINGINPUTSTREAM
+ NS_DECL_NSIINPUTSTREAM
+
+ // nsIRandomAccessStore interface
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF);
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF);
+
+ NS_DECL_NSISEEKABLESTREAM
+
+protected:
+ PRInt32 LengthRemaining() const
+ {
+ return mLength - mOffset;
+ }
+
+ void Clear()
+ {
+ NS_ASSERTION(mConstString || !mOwned,
+ "Can't have mOwned set and have a null string!");
+ if (mOwned)
+ nsMemory::Free((char*)mConstString);
+
+ // We're about to get a new string; clear the members that
+ // would no longer have valid values.
+ mOffset = 0;
+ mLastResult = NS_OK;
+ mEOF = PR_FALSE;
+ }
+
+ PRInt32 mOffset;
+ nsresult mLastResult;
+ PRPackedBool mEOF;
+ PRPackedBool mOwned;
+ const char* mConstString;
+ PRInt32 mLength;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsStringInputStream,
+ nsIStringInputStream,
+ nsIInputStream,
+ nsIRandomAccessStore,
+ nsISeekableStream)
+
+/////////
+// nsIStringInputStream implementation
+/////////
+NS_IMETHODIMP
+nsStringInputStream::SetData(const char *data, PRInt32 dataLen)
+{
+ if (dataLen < 0)
+ dataLen = strlen(data);
+
+ return AdoptData(nsCRT::strndup(data, dataLen), dataLen);
+}
+
+NS_IMETHODIMP
+nsStringInputStream::AdoptData(char *data, PRInt32 dataLen)
+{
+ NS_ENSURE_ARG_POINTER(data);
+
+ if (dataLen < 0)
+ dataLen = strlen(data);
+
+ Clear();
+
+ mConstString = (const char *) data;
+ mLength = dataLen;
+ mOwned = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringInputStream::ShareData(const char *data, PRInt32 dataLen)
+{
+ NS_ENSURE_ARG_POINTER(data);
+
+ if (dataLen < 0)
+ dataLen = strlen(data);
+
+ Clear();
+
+ mConstString = data;
+ mLength = dataLen;
+ mOwned = PR_FALSE;
+ return NS_OK;
+}
+
+/////////
+// nsIInputStream implementation
+/////////
+NS_IMETHODIMP nsStringInputStream::Close()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::Available(PRUint32 *aLength)
+{
+ NS_PRECONDITION(aLength != nsnull, "null ptr");
+ if (!aLength)
+ return NS_ERROR_NULL_POINTER;
+ *aLength = LengthRemaining();
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::Read(char* aBuf, PRUint32 aCount,
+ PRUint32 *aReadCount)
+{
+ NS_PRECONDITION(aBuf != nsnull, "null ptr");
+ if (!aBuf)
+ return NS_ERROR_NULL_POINTER;
+ NS_PRECONDITION(aReadCount != nsnull, "null ptr");
+ if (!aReadCount)
+ return NS_ERROR_NULL_POINTER;
+ if (NS_FAILED(mLastResult))
+ return mLastResult;
+
+ PRInt32 bytesRead;
+ PRInt32 maxCount = mLength - mOffset;
+ if ((PRInt32)aCount > maxCount)
+ bytesRead = maxCount;
+ else
+ bytesRead = aCount;
+
+ memcpy(aBuf, mConstString + mOffset, bytesRead);
+ mOffset += bytesRead;
+
+ *aReadCount = bytesRead;
+ if (bytesRead < (PRInt32)aCount)
+ SetAtEOF(PR_TRUE);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsStringInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure,
+ PRUint32 aCount, PRUint32 * result)
+{
+ nsresult rv;
+ PRInt32 maxCount = mLength - mOffset;
+ if (maxCount == 0) {
+ *result = 0;
+ return NS_OK;
+ }
+ if ((PRInt32)aCount > maxCount)
+ aCount = maxCount;
+ rv = writer(this, closure, mConstString + mOffset,
+ 0, aCount, result);
+ if (NS_SUCCEEDED(rv))
+ mOffset += *result;
+ // errors returned from the writer end here!
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+
+/////////
+// nsISeekableStream implementation
+/////////
+NS_IMETHODIMP nsStringInputStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ mLastResult = NS_OK; // reset on a seek.
+ const nsInt64 maxUint32 = PR_UINT32_MAX;
+ nsInt64 offset64(offset);
+ PRInt32 offset32;
+ LL_L2I(offset32, offset);
+
+ NS_ASSERTION(maxUint32 > offset64, "string streams only support 32 bit offsets");
+ mEOF = PR_FALSE; // reset on a seek.
+ PRInt32 fileSize = LengthRemaining();
+ PRInt32 newPosition=-1;
+ switch (whence)
+ {
+ case NS_SEEK_CUR: newPosition = mOffset + offset32; break;
+ case NS_SEEK_SET: newPosition = offset32; break;
+ case NS_SEEK_END: newPosition = fileSize + offset32; break;
+ }
+ if (newPosition < 0)
+ {
+ newPosition = 0;
+ mLastResult = NS_FILE_RESULT(PR_FILE_SEEK_ERROR);
+ }
+ if (newPosition >= fileSize)
+ {
+ newPosition = fileSize;
+ mEOF = PR_TRUE;
+ }
+ mOffset = newPosition;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsStringInputStream::Tell(PRInt64* outWhere)
+{
+ *outWhere = mOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::SetEOF()
+{
+ NS_NOTYETIMPLEMENTED("nsStringInputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/////////
+// nsIRandomAccessStore implementation
+/////////
+NS_IMETHODIMP nsStringInputStream::GetAtEOF(PRBool* outAtEOF)
+{
+ *outAtEOF = mEOF;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::SetAtEOF(PRBool inAtEOF)
+{
+ mEOF = inAtEOF;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from an nsAString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewStringInputStream(nsIInputStream** aStreamResult,
+ const nsAString& aStringToRead)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ char* data = ToNewCString(aStringToRead);
+ if (!data)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream) {
+ nsMemory::Free(data);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->AdoptData(data, aStringToRead.Length());
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(data);
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from an nsACString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCStringInputStream(nsIInputStream** aStreamResult,
+ const nsACString& aStringToRead)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ char* data = ToNewCString(aStringToRead);
+ if (!data)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream) {
+ nsMemory::Free(data);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->AdoptData(data, aStringToRead.Length());
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(data);
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from a C string. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCharInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->ShareData(aStringToRead, -1);
+
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from a byte array. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewByteInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead,
+ PRInt32 aLength)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->ShareData(aStringToRead, aLength);
+
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// factory method for constructing a nsStringInputStream object
+NS_METHOD
+nsStringInputStreamConstructor(nsISupports *outer, REFNSIID iid, void **result)
+{
+ *result = nsnull;
+
+ if (outer)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsStringInputStream *inst;
+ NS_NEWXPCOM(inst, nsStringInputStream);
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(inst);
+ nsresult rv = inst->QueryInterface(iid, result);
+ NS_RELEASE(inst);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStringStream.h b/src/libs/xpcom18a4/xpcom/io/nsStringStream.h
new file mode 100644
index 00000000..6f2f7f20
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStringStream.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * darin@netscape.com (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsStringStream_h__
+#define nsStringStream_h__
+
+#include "nsISeekableStream.h"
+
+/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
+#define NS_IRANDOMACCESS_IID \
+{ 0xa6cf90eb, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIRandomAccessStore
+// Supports Seek, Tell etc.
+//========================================================================================
+: public nsISeekableStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IRANDOMACCESS_IID)
+
+/* "PROTECTED" */
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF) = 0;
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF) = 0;
+}; // class nsIRandomAccessStore
+
+#include "nsIStringStream.h"
+
+/**
+ * nsStringInputStream : nsIStringInputStream
+ * , nsIInputStream
+ * , nsISeekableStream
+ * , nsIRandomAccessStore
+ */
+#define NS_STRINGINPUTSTREAM_CLASSNAME "nsStringInputStream"
+#define NS_STRINGINPUTSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
+#define NS_STRINGINPUTSTREAM_CID \
+{ /* 0abb0835-5000-4790-af28-61b3ba17c295 */ \
+ 0x0abb0835, \
+ 0x5000, \
+ 0x4790, \
+ {0xaf, 0x28, 0x61, 0xb3, 0xba, 0x17, 0xc2, 0x95} \
+}
+extern NS_METHOD nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **);
+
+
+
+#endif // nsStringStream_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp
new file mode 100644
index 00000000..99e9364a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp
@@ -0,0 +1,415 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsIUnicharInputStream.h"
+#include "nsIByteBuffer.h"
+#include "nsIUnicharBuffer.h"
+#include "nsIServiceManager.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsUTF8Utils.h"
+#include <fcntl.h>
+#if defined(NS_WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+class StringUnicharInputStream : public nsIUnicharInputStream {
+public:
+ StringUnicharInputStream(nsString* aString);
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+ NS_IMETHOD ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount, PRUint32* aReadCount);
+ NS_IMETHOD Close();
+
+ nsString* mString;
+ PRUint32 mPos;
+ PRUint32 mLen;
+
+private:
+ ~StringUnicharInputStream();
+};
+
+StringUnicharInputStream::StringUnicharInputStream(nsString* aString)
+{
+ mString = aString;
+ mPos = 0;
+ mLen = aString->Length();
+}
+
+StringUnicharInputStream::~StringUnicharInputStream()
+{
+ if (nsnull != mString) {
+ delete mString;
+ }
+}
+
+NS_IMETHODIMP
+StringUnicharInputStream::Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount)
+{
+ if (mPos >= mLen) {
+ *aReadCount = 0;
+ return NS_OK;
+ }
+ const PRUnichar* us = mString->get();
+ NS_ASSERTION(mLen >= mPos, "unsigned madness");
+ PRUint32 amount = mLen - mPos;
+ if (amount > aCount) {
+ amount = aCount;
+ }
+ memcpy(aBuf, us + mPos, sizeof(PRUnichar) * amount);
+ mPos += amount;
+ *aReadCount = amount;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+StringUnicharInputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount, PRUint32 *aReadCount)
+{
+ PRUint32 bytesWritten;
+ PRUint32 totalBytesWritten = 0;
+
+ nsresult rv;
+ aCount = PR_MIN(mString->Length() - mPos, aCount);
+
+ while (aCount) {
+ rv = aWriter(this, aClosure, mString->get() + mPos,
+ totalBytesWritten, aCount, &bytesWritten);
+
+ if (NS_FAILED(rv)) {
+ // don't propagate errors to the caller
+ break;
+ }
+
+ aCount -= bytesWritten;
+ totalBytesWritten += bytesWritten;
+ mPos += bytesWritten;
+ }
+
+ *aReadCount = totalBytesWritten;
+
+ return NS_OK;
+}
+
+nsresult StringUnicharInputStream::Close()
+{
+ mPos = mLen;
+ if (nsnull != mString) {
+ delete mString;
+ mString = 0;
+ }
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(StringUnicharInputStream, nsIUnicharInputStream)
+
+NS_COM nsresult
+NS_NewStringUnicharInputStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsString* aString)
+{
+ NS_PRECONDITION(nsnull != aString, "null ptr");
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
+ if ((nsnull == aString) || (nsnull == aInstancePtrResult)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ StringUnicharInputStream* it = new StringUnicharInputStream(aString);
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return it->QueryInterface(NS_GET_IID(nsIUnicharInputStream),
+ (void**) aInstancePtrResult);
+}
+
+//----------------------------------------------------------------------
+
+class UTF8InputStream : public nsIUnicharInputStream {
+public:
+ UTF8InputStream();
+ nsresult Init(nsIInputStream* aStream, PRUint32 aBufSize);
+
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+ NS_IMETHOD ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+ NS_IMETHOD Close();
+
+private:
+ ~UTF8InputStream();
+
+protected:
+ PRInt32 Fill(nsresult * aErrorCode);
+
+ static void CountValidUTF8Bytes(const char *aBuf, PRUint32 aMaxBytes, PRUint32& aValidUTF8bytes, PRUint32& aValidUCS2bytes);
+
+ nsCOMPtr<nsIInputStream> mInput;
+ nsCOMPtr<nsIByteBuffer> mByteData;
+ nsCOMPtr<nsIUnicharBuffer> mUnicharData;
+
+ PRUint32 mByteDataOffset;
+ PRUint32 mUnicharDataOffset;
+ PRUint32 mUnicharDataLength;
+};
+
+UTF8InputStream::UTF8InputStream() :
+ mByteDataOffset(0),
+ mUnicharDataOffset(0),
+ mUnicharDataLength(0)
+{
+}
+
+nsresult
+UTF8InputStream::Init(nsIInputStream* aStream, PRUint32 aBufferSize)
+{
+ if (aBufferSize == 0) {
+ aBufferSize = 8192;
+ }
+
+ nsresult rv = NS_NewByteBuffer(getter_AddRefs(mByteData), nsnull, aBufferSize);
+ if (NS_FAILED(rv)) return rv;
+ rv = NS_NewUnicharBuffer(getter_AddRefs(mUnicharData), nsnull, aBufferSize);
+ if (NS_FAILED(rv)) return rv;
+
+ mInput = aStream;
+
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(UTF8InputStream,nsIUnicharInputStream)
+
+UTF8InputStream::~UTF8InputStream()
+{
+ Close();
+}
+
+nsresult UTF8InputStream::Close()
+{
+ mInput = nsnull;
+ mByteData = nsnull;
+ mUnicharData = nsnull;
+
+ return NS_OK;
+}
+
+nsresult UTF8InputStream::Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount)
+{
+ NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
+ PRUint32 rv = mUnicharDataLength - mUnicharDataOffset;
+ nsresult errorCode;
+ if (0 == rv) {
+ // Fill the unichar buffer
+ rv = Fill(&errorCode);
+ if (rv <= 0) {
+ *aReadCount = 0;
+ return errorCode;
+ }
+ }
+ if (rv > aCount) {
+ rv = aCount;
+ }
+ memcpy(aBuf, mUnicharData->GetBuffer() + mUnicharDataOffset,
+ rv * sizeof(PRUnichar));
+ mUnicharDataOffset += rv;
+ *aReadCount = rv;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+UTF8InputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount, PRUint32 *aReadCount)
+{
+ NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
+ PRUint32 bytesToWrite = mUnicharDataLength - mUnicharDataOffset;
+ nsresult rv = NS_OK;
+ if (0 == bytesToWrite) {
+ // Fill the unichar buffer
+ bytesToWrite = Fill(&rv);
+ if (bytesToWrite <= 0) {
+ *aReadCount = 0;
+ return rv;
+ }
+ }
+
+ if (bytesToWrite > aCount)
+ bytesToWrite = aCount;
+
+ PRUint32 bytesWritten;
+ PRUint32 totalBytesWritten = 0;
+
+ while (bytesToWrite) {
+ rv = aWriter(this, aClosure,
+ mUnicharData->GetBuffer() + mUnicharDataOffset,
+ totalBytesWritten, bytesToWrite, &bytesWritten);
+
+ if (NS_FAILED(rv)) {
+ // don't propagate errors to the caller
+ break;
+ }
+
+ bytesToWrite -= bytesWritten;
+ totalBytesWritten += bytesWritten;
+ mUnicharDataOffset += bytesWritten;
+ }
+
+ *aReadCount = totalBytesWritten;
+
+ return NS_OK;
+}
+
+PRInt32 UTF8InputStream::Fill(nsresult * aErrorCode)
+{
+ if (nsnull == mInput) {
+ // We already closed the stream!
+ *aErrorCode = NS_BASE_STREAM_CLOSED;
+ return -1;
+ }
+
+ NS_ASSERTION(mByteData->GetLength() >= mByteDataOffset, "unsigned madness");
+ PRUint32 remainder = mByteData->GetLength() - mByteDataOffset;
+ mByteDataOffset = remainder;
+ PRInt32 nb = mByteData->Fill(aErrorCode, mInput, remainder);
+ if (nb <= 0) {
+ // Because we assume a many to one conversion, the lingering data
+ // in the byte buffer must be a partial conversion
+ // fragment. Because we know that we have recieved no more new
+ // data to add to it, we can't convert it. Therefore, we discard
+ // it.
+ return nb;
+ }
+ NS_ASSERTION(remainder + nb == mByteData->GetLength(), "bad nb");
+
+ // Now convert as much of the byte buffer to unicode as possible
+ PRUint32 srcLen, dstLen;
+ CountValidUTF8Bytes(mByteData->GetBuffer(),remainder + nb, srcLen, dstLen);
+
+ // the number of UCS2 characters should always be <= the number of
+ // UTF8 chars
+ NS_ASSERTION( (remainder+nb >= srcLen), "cannot be longer than out buffer");
+ NS_ASSERTION(PRInt32(dstLen) <= mUnicharData->GetBufferSize(),
+ "Ouch. I would overflow my buffer if I wasn't so careful.");
+ if (PRInt32(dstLen) > mUnicharData->GetBufferSize()) return 0;
+
+ ConvertUTF8toUTF16 converter(mUnicharData->GetBuffer());
+
+ nsASingleFragmentCString::const_char_iterator start = mByteData->GetBuffer();
+ nsASingleFragmentCString::const_char_iterator end = mByteData->GetBuffer() + srcLen;
+
+ copy_string(start, end, converter);
+ NS_ASSERTION(converter.Length() == dstLen, "length mismatch");
+
+ mUnicharDataOffset = 0;
+ mUnicharDataLength = dstLen;
+ mByteDataOffset = srcLen;
+
+ return dstLen;
+}
+
+void
+UTF8InputStream::CountValidUTF8Bytes(const char* aBuffer, PRUint32 aMaxBytes, PRUint32& aValidUTF8bytes, PRUint32& aValidUCS2chars)
+{
+ const char *c = aBuffer;
+ const char *end = aBuffer + aMaxBytes;
+ const char *lastchar = c; // pre-initialize in case of 0-length buffer
+ PRUint32 ucs2bytes = 0;
+ while (c < end && *c) {
+ lastchar = c;
+ ucs2bytes++;
+
+ if (UTF8traits::isASCII(*c))
+ c++;
+ else if (UTF8traits::is2byte(*c))
+ c += 2;
+ else if (UTF8traits::is3byte(*c))
+ c += 3;
+ else if (UTF8traits::is4byte(*c))
+ c += 4;
+ else if (UTF8traits::is5byte(*c))
+ c += 5;
+ else if (UTF8traits::is6byte(*c))
+ c += 6;
+ else {
+ NS_WARNING("Unrecognized UTF8 string in UTF8InputStream::CountValidUTF8Bytes()");
+ break; // Otherwise we go into an infinite loop. But what happens now?
+ }
+ }
+ if (c > end) {
+ c = lastchar;
+ ucs2bytes--;
+ }
+
+ aValidUTF8bytes = c - aBuffer;
+ aValidUCS2chars = ucs2bytes;
+}
+
+NS_COM nsresult
+NS_NewUTF8ConverterStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsIInputStream* aStreamToWrap,
+ PRInt32 aBufferSize)
+{
+ // Create converter input stream
+ UTF8InputStream* it = new UTF8InputStream();
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult rv = it->Init(aStreamToWrap, aBufferSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return it->QueryInterface(NS_GET_IID(nsIUnicharInputStream),
+ (void **) aInstancePtrResult);
+}
diff --git a/src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html
new file mode 100644
index 00000000..38cadb40
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Document Moved!</title>
+</head>
+<body bgcolor = "white">
+<center>The xptcall porting document has been moved to:
+<P>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html">http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html</a>
+<P>
+Please update your links.
+</center>
+</body>
+</html> \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html
new file mode 100644
index 00000000..22532119
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Document Moved!</title>
+</head>
+<body bgcolor = "white">
+<center>The xptcall status document has been moved to:
+<P>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html</a>
+<P>
+Please update your links.
+</center>
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/Makefile.in b/src/libs/xpcom18a4/xpcom/obsolete/Makefile.in
new file mode 100644
index 00000000..5f8cd041
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/Makefile.in
@@ -0,0 +1,130 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom_obsolete
+LIBRARY_NAME = xpcom_compat
+ifneq ($(OS_ARCH),WINNT)
+SHORT_LIBNAME = xpcomct
+endif
+
+GRE_MODULE = 1
+PACKAGE_FILE = xpcomobsolete.pkg
+
+DIRS = component
+
+REQUIRES = xpcom \
+ string \
+ $(NULL)
+
+# pull in MoreFiles for MacOSX
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += macmorefiles
+endif
+
+CPPSRCS = \
+ nsFileSpec.cpp \
+ nsFileStream.cpp \
+ nsIFileStream.cpp \
+ nsFileSpecImpl.cpp \
+ nsSpecialSystemDirectory.cpp \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+REQUIRES += libreg
+CPPSRCS += dlldeps.cpp
+endif
+
+EXPORTS = \
+ xpcomobsolete.h \
+ nsFileSpec.h \
+ nsFileStream.h \
+ nsIFileStream.h \
+ nsSpecialSystemDirectory.h \
+ nsIRegistryUtils.h \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I.. \
+ -I$(srcdir)/../io \
+ $(NULL)
+
+XPIDLSRCS = nsIFileSpec.idl \
+ nsIRegistry.idl \
+ $(NULL)
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)mozreg_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+# due to symbol conflicts on win32, this needs to be shared
+FORCE_SHARED_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM_OBSOLETE
+
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+CXXFLAGS += $(TK_CFLAGS)
+EXTRA_DSO_LDOPTS += $(TK_LIBS)
+endif
+
+ifeq ($(OS_ARCH),BeOS)
+EXTRA_DSO_LDOPTS += -lbe
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, shell32 ole32)
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, imagehlp)
+endif
+ifdef GNU_CXX
+DSO_LDOPTS += -Wl,--export-all-symbols
+endif
+endif # WINNT
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in b/src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in
new file mode 100644
index 00000000..a8bec32d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in
@@ -0,0 +1,81 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom_compat_c
+MODULE_NAME = xpcomObsoleteModule
+LIBRARY_NAME = xpcom_compat_c
+ifneq ($(OS_ARCH),WINNT)
+SHORT_LIBNAME = xpcomctc
+endif
+
+ifndef MINIMO
+EXPORT_LIBRARY = 1
+endif
+IS_COMPONENT = 1
+GRE_MODULE = 1
+
+PACKAGE_FILE = xpcomobsoletec.pkg
+
+REQUIRES = xpcom \
+ xpcom_obsolete \
+ string \
+ libreg \
+ $(NULL)
+
+CPPSRCS = \
+ nsXPCOMObsolete.cpp \
+ nsRegistry.cpp \
+ $(NULL)
+
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../ \
+ $(NULL)
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) \
+ $(MOZ_XPCOM_OBSOLETE_LIBS) \
+ $(NULL)
+
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp
new file mode 100644
index 00000000..7f51cdca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp
@@ -0,0 +1,857 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsFileSpecImpl.h"// Always first, to ensure that it compiles alone.
+
+#include "nsIFileStream.h"
+#include "nsFileStream.h"
+
+#include "nsILocalFile.h"
+
+#include "prmem.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileSpecImpl, nsIFileSpec)
+
+#ifdef NS_DEBUG
+#define TEST_OUT_PTR(p) \
+ if (!(p)) \
+ return NS_ERROR_NULL_POINTER;
+#else
+#define TEST_OUT_PTR(p)
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+ : mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+ : mFileSpec(inSpec)
+ , mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::~nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+{
+ CloseStream();
+}
+
+//----------------------------------------------------------------------------------------
+/* static */
+nsresult nsFileSpecImpl::MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ nsFileSpecImpl* it = new nsFileSpecImpl(inSpec);
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return it->QueryInterface(NS_GET_IID(nsIFileSpec), (void **) result);
+} // nsFileSpecImpl::MakeInterface
+
+#define FILESPEC(ifilespec) ((nsFileSpecImpl*)ifilespec)->mFileSpec
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::FromFileSpec(const nsIFileSpec *original)
+//----------------------------------------------------------------------------------------
+{
+ if (original) {
+ nsresult rv = ((nsIFileSpec *)original)->GetFileSpec( &mFileSpec);
+ if (NS_SUCCEEDED( rv))
+ return mFileSpec.Error();
+ else
+ return( rv);
+ }
+ else
+ return( NS_ERROR_FAILURE);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsChildOf(nsIFileSpec *possibleParent,
+ PRBool *_retval)
+{
+ *_retval = mFileSpec.IsChildOf(FILESPEC(possibleParent));
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetURLString(char * *aURLString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aURLString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFileURL url(mFileSpec);
+ *aURLString = nsCRT::strdup(url.GetURLString());
+ if (!*aURLString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+} // nsFileSpecImpl::GetURLString
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetURLString(const char * aURLString)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFileURL(aURLString);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetUnixStyleFilePath(char * *aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aUnixStyleFilePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFilePath path(mFileSpec);
+ *aUnixStyleFilePath = nsCRT::strdup((const char*) path);
+ if (!*aUnixStyleFilePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetUnixStyleFilePath(const char * aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFilePath(aUnixStyleFilePath);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetPersistentDescriptorString(char * *aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aPersistentDescriptorString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsPersistentFileDescriptor desc(mFileSpec);
+ nsCAutoString data;
+ desc.GetData(data);
+ *aPersistentDescriptorString = ToNewCString(data);
+ if (!*aPersistentDescriptorString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetPersistentDescriptorString(const char * aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ nsPersistentFileDescriptor desc(mFileSpec);
+ desc.SetData(nsDependentCString(aPersistentDescriptorString));
+ mFileSpec = desc;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNativePath(char * *aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNativePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ *aNativePath = nsCRT::strdup(mFileSpec.GetNativePathCString());
+ if (!*aNativePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetNativePath(const char * aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aNativePath;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNSPRPath(char * *aNSPRPath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNSPRPath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsNSPRPath path(mFileSpec);
+ *aNSPRPath = nsCRT::strdup((const char*) path);
+ if (!*aNSPRPath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Error()
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsValid(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Valid();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Failed(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ *_retval = mFileSpec.Failed();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetLeafName(char * *aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aLeafName)
+ *aLeafName = mFileSpec.GetLeafName();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetLeafName(const char * aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.SetLeafName(aLeafName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetParent(nsIFileSpec * *aParent)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aParent)
+ nsFileSpec parent;
+ mFileSpec.GetParent(parent);
+ return MakeInterface(parent, aParent);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUnique()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUniqueWithSuggestedName(const char *suggestedName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique(suggestedName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetModDate(PRUint32 *aModDate)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aModDate)
+ nsFileSpec::TimeStamp stamp;
+ mFileSpec.GetModDate(stamp);
+ *aModDate = stamp;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ModDateChanged(PRUint32 oldStamp, PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.ModDateChanged(oldStamp);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsDirectory(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsDirectory();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsFile(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsFile();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Exists();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsHidden(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsHidden();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsSymlink(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsSymlink();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ResolveSymlink()
+//----------------------------------------------------------------------------------------
+{
+ PRBool ignore;
+ return mFileSpec.ResolveSymlink(ignore);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSize(PRUint32 *aFileSize)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSize)
+ *aFileSize = mFileSpec.GetFileSize();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aDiskSpaceAvailable)
+ *aDiskSpaceAvailable = mFileSpec.GetDiskSpaceAvailable();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::AppendRelativeUnixPath(const char *relativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec += relativePath;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Touch()
+//----------------------------------------------------------------------------------------
+{
+ // create an empty file, like the UNIX touch command.
+ nsresult rv;
+ rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ rv = CloseStream();
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CreateDir()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.CreateDir();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Delete(PRBool aRecursive)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.Delete(aRecursive);
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Truncate(PRInt32 aNewLength)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Truncate(aNewLength);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Rename(const char *newLeafName)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Rename(newLeafName);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CopyToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.CopyToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MoveToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.MoveToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Execute(const char *args)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Execute(args);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReading()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReadingAndWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ nsresult result = NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+ if (NS_SUCCEEDED(result))
+ result = NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CloseStream()
+//----------------------------------------------------------------------------------------
+{
+ NS_IF_RELEASE(mInputStream);
+ NS_IF_RELEASE(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsStreamOpen(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = (mInputStream || mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetInputStream(nsIInputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mInputStream;
+ NS_IF_ADDREF(mInputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetOutputStream(nsIOutputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mOutputStream;
+ NS_IF_ADDREF(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFileContents(const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 count;
+ rv = Write(inString, PL_strlen(inString), &count);
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileContents(char** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = nsnull;
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 theSize;
+ rv = GetFileSize((PRUint32*)&theSize);
+ if (NS_SUCCEEDED(rv))
+ rv = Read(_retval, theSize, &theSize);
+ if (NS_SUCCEEDED(rv))
+ (*_retval)[theSize] = 0;
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSpec(nsFileSpec *aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSpec)
+ *aFileSpec = mFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Equals(nsIFileSpec *spec, PRBool *result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv;
+
+ if (!result || !spec) return NS_ERROR_NULL_POINTER;
+
+ nsFileSpec otherSpec;
+
+ rv = spec->GetFileSpec(&otherSpec);
+ if (NS_FAILED(rv)) return rv;
+
+ if (mFileSpec == otherSpec) {
+ *result = PR_TRUE;
+ }
+ else {
+ *result = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFromFileSpec(const nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Eof(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.eof();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Read(char** buffer, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ TEST_OUT_PTR(buffer)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*buffer)
+ *buffer = (char*)PR_Malloc(requestedCount + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.read(*buffer, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ReadLine(char** line, PRInt32 bufferSize, PRBool *wasTruncated)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(wasTruncated)
+ TEST_OUT_PTR(line)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*line)
+ *line = (char*)PR_Malloc(bufferSize + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *wasTruncated = !s.readline(*line, bufferSize);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Write(const char * data, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ //if (!mOutputStream)
+ // return NS_ERROR_NULL_POINTER;
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ nsOutputFileStream s(mOutputStream);
+ *_retval = s.write(data, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Flush()
+//----------------------------------------------------------------------------------------
+{
+ if (!mOutputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsOutputFileStream s(mOutputStream);
+ s.flush();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Seek(PRInt32 offset)
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_OK;
+ if (mOutputStream)
+ {
+ nsOutputFileStream os(mOutputStream);
+ os.seek(offset);
+ result = os.error();
+ }
+ if (NS_SUCCEEDED(result) && mInputStream)
+ {
+ nsInputFileStream is(mInputStream);
+ is.seek(offset);
+ result = is.error();
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Tell(PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.tell();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::EndLine()
+//----------------------------------------------------------------------------------------
+{
+ nsOutputFileStream s(mOutputStream);
+ s << nsEndl;
+ return s.error();
+}
+
+NS_IMPL_ISUPPORTS1(nsDirectoryIteratorImpl, nsIDirectoryIterator)
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+ : mDirectoryIterator(nsnull)
+{
+}
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::~nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Init(nsIFileSpec *parent, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+ mDirectoryIterator = new nsDirectoryIterator(FILESPEC(parent), resolveSymlink);
+ if (!mDirectoryIterator)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ *_retval = mDirectoryIterator->Exists();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Next()
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ (*mDirectoryIterator)++;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::GetCurrentSpec(nsIFileSpec * *aCurrentSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ return nsFileSpecImpl::MakeInterface(mDirectoryIterator->Spec(), aCurrentSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsDirectoryIteratorImpl* it = new nsDirectoryIteratorImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsFileSpecImpl* it = new nsFileSpecImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecWithSpec(const nsFileSpec& aSrcFileSpec, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ if (!result)
+ return NS_ERROR_NULL_POINTER;
+
+ return nsFileSpecImpl::MakeInterface(aSrcFileSpec, result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpec(nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecFromIFile(nsIFile *aFile, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCAutoString path;
+ rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = (*result)->SetNativePath(path.get());
+ if (NS_FAILED(rv))
+ NS_RELEASE(*result);
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewDirectoryIterator(nsIDirectoryIterator** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsDirectoryIteratorImpl::Create(nsnull, NS_GET_IID(nsIDirectoryIterator), (void**)result);
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h
new file mode 100644
index 00000000..502e254f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _FILESPECIMPL_H_
+#define _FILESPECIMPL_H_
+
+#include "nscore.h"
+#include "nsIFileSpec.h"
+#include "nsFileSpec.h"
+
+//========================================================================================
+class nsFileSpecImpl
+//========================================================================================
+ : public nsIFileSpec
+{
+
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIFILESPEC
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+ //----------------------
+ // Implementation
+ //----------------------
+
+ nsFileSpecImpl();
+ nsFileSpecImpl(const nsFileSpec& inSpec);
+ static nsresult MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** outSpec);
+
+ //----------------------
+ // Data
+ //----------------------
+
+ nsFileSpec mFileSpec;
+ nsIInputStream* mInputStream;
+ nsIOutputStream* mOutputStream;
+
+private:
+ ~nsFileSpecImpl();
+}; // class nsFileSpecImpl
+
+//========================================================================================
+class nsDirectoryIteratorImpl
+//========================================================================================
+ : public nsIDirectoryIterator
+{
+
+public:
+
+ nsDirectoryIteratorImpl();
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Init(nsIFileSpec *parent, PRBool resolveSymlink);
+
+ NS_IMETHOD Exists(PRBool *_retval);
+
+ NS_IMETHOD Next();
+
+ NS_IMETHOD GetCurrentSpec(nsIFileSpec * *aCurrentSpec);
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+private:
+ ~nsDirectoryIteratorImpl();
+
+protected:
+ nsDirectoryIterator* mDirectoryIterator;
+}; // class nsDirectoryIteratorImpl
+
+#endif // _FILESPECIMPL_H_
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl
new file mode 100644
index 00000000..bc9990e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl
@@ -0,0 +1,186 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsISupports.idl"
+#include "nsIEnumerator.idl"
+
+interface nsIFile;
+
+typedef PRUint32 nsRegistryKey;
+typedef long nsWellKnownRegistry;
+
+[scriptable,uuid(5D41A440-8E37-11d2-8059-00600811A9C3)]
+interface nsIRegistry : nsISupports
+{
+ const long None = 0;
+ const long Users = 1;
+ const long Common = 2;
+ const long CurrentUser = 3;
+
+ const long ApplicationComponentRegistry = 1;
+ const long ApplicationRegistry = 2;
+
+ // Dont use this one. This for internal use only.
+ const long ApplicationCustomRegistry = -1;
+
+ void open(in nsIFile regFile);
+ void openWellKnownRegistry(in nsWellKnownRegistry regid);
+
+ void flush();
+ boolean isOpen();
+
+ nsRegistryKey addKey(in nsRegistryKey baseKey, in wstring keyname);
+ nsRegistryKey getKey(in nsRegistryKey baseKey, in wstring keyname);
+ void removeKey(in nsRegistryKey baseKey, in wstring keyname);
+
+ wstring getString(in nsRegistryKey baseKey, in wstring valname);
+ void setString(in nsRegistryKey baseKey, in wstring valname, in wstring value);
+
+ string getStringUTF8(in nsRegistryKey baseKey, in string path);
+ void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
+
+ void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
+ void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
+ PRInt32 getInt(in nsRegistryKey baseKey, in string path);
+ void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
+ PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
+ void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
+
+ /**
+ * addSubtree() and friends need to be renamed to addKeyUTF8().
+ * If you are using these forms make sure you pass UTF8 data
+ */
+ nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
+ void removeSubtree(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
+
+ nsRegistryKey addSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ void removeSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtreeRaw(in nsRegistryKey baseKey, in string path);
+
+ nsIEnumerator enumerateSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateAllSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateValues(in nsRegistryKey baseKey);
+
+ const unsigned long String = 1;
+ const unsigned long Int32 = 2;
+ const unsigned long Bytes = 3;
+ const unsigned long File = 4;
+
+ unsigned long getValueType(in nsRegistryKey baseKey, in string path);
+ PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
+ void deleteValue(in nsRegistryKey baseKey, in string path);
+
+ /**
+ * escapeKey() takes arbitrary binary data and converts it into
+ * valid ASCII which can be used as registry key or value names
+ */
+ void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
+ void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
+
+ attribute string currentUserName;
+
+ void pack();
+};
+
+[scriptable, uuid(8cecf236-1dd2-11b2-893c-f9848956eaec)]
+interface nsIRegistryEnumerator : nsIEnumerator
+{
+ void currentItemInPlaceUTF8(out nsRegistryKey key,
+ [shared, retval] out string item);
+};
+
+[scriptable, uuid(D1B54831-AC07-11d2-805E-00600811A9C3)]
+interface nsIRegistryNode : nsISupports
+{
+ readonly attribute string nameUTF8;
+ readonly attribute wstring name;
+ readonly attribute nsRegistryKey key;
+};
+
+[scriptable,uuid(5316C380-B2F8-11d2-A374-0080C6F80E4B)]
+interface nsIRegistryValue : nsISupports
+{
+ readonly attribute wstring name;
+ readonly attribute string nameUTF8;
+ readonly attribute unsigned long type;
+ readonly attribute PRUint32 length;
+};
+
+[uuid(3A15FC88-7A61-4Ab4-8E58-31E95fAB3DA8)]
+/**
+ * It sucks that nsIRegistry has to always allocate and return
+ * strings. nsIRegistryGetter adds in interfaces for non allocating getters
+ * to registry values.
+ */
+interface nsIRegistryGetter : nsISupports
+{
+ /**
+ * Get a string value of attribute valname in widestring or utf8 format
+ *
+ * @return
+ * NS_OK on success.
+ * buf has the string value copied into it. length is NOT changed.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in chars including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various failure codes otherwise. buf and length wont be updated.
+ */
+ void getStringUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout char buf, inout PRUint32 length);
+
+ /**
+ * Get a a byte array value of attribute valname
+ *
+ * @return
+ * NS_OK on success. buf has the string value copied into it.
+ * length is updated to actual number of bytes copied into buf.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in PRUint8s including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various other failure codes otherwise. buf and length wont be updated.
+ */
+ void getBytesUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout PRUint8 buf, inout PRUint32 length);
+};
+
+%{ C++
+#include "nsIRegistryUtils.h"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h
new file mode 100644
index 00000000..a3d74d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef __nsIRegistryUtils_h
+#define __nsIRegistryUtils_h
+
+#define NS_REGISTRY_CONTRACTID "@mozilla.org/registry;1"
+#define NS_REGISTRY_CLASSNAME "Mozilla Registry"
+/* be761f00-a3b0-11d2-996c-0080c7cb1081 */
+#define NS_REGISTRY_CID \
+{ \
+ 0xbe761f00, \
+ 0xa3b0, \
+ 0x11d2, \
+ {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x81} \
+}
+
+/*------------------------------- Error Codes ----------------------------------
+------------------------------------------------------------------------------*/
+#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
+#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
+#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
+#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
+#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
+#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
+#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
+#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
+#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp
new file mode 100644
index 00000000..d3ecfe62
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp
@@ -0,0 +1,2019 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef MOZ_LOGGING
+#define FORCE_PR_LOG /* Allow logging in the release build */
+#endif
+
+#include "nsIGenericFactory.h"
+
+#include "nsRegistry.h"
+#include "nsIEnumerator.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "NSReg.h"
+#include "prmem.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsCOMPtr.h"
+#include "nsILocalFile.h"
+#include "nsIServiceManager.h"
+#include "nsTextFormatter.h"
+
+#ifdef XP_BEOS
+#include <FindDirectory.h>
+#include <Path.h>
+#endif
+
+/* extra locking for the paranoid */
+/* #define EXTRA_THREADSAFE */
+#ifndef EXTRA_THREADSAFE
+#define PR_Lock(x) (void)0
+#define PR_Unlock(x) (void)0
+#endif
+
+// Logging of debug output
+extern PRLogModuleInfo *nsComponentManagerLog;
+
+PRUnichar widestrFormat[] = { PRUnichar('%'),PRUnichar('s'),PRUnichar(0)};
+
+/*-------------------------------- nsRegistry ----------------------------------
+| This class implements the nsIRegistry interface using the functions |
+| provided by libreg (as declared in mozilla/modules/libreg/include/NSReg.h). |
+| |
+| Since that interface is designed to match the libreg function, this class |
+| is implemented with each member function being a simple wrapper for the |
+| corresponding libreg function. |
+| |
+| #define EXTRA_THREADSAFE if you are worried about libreg thread safety. |
+| It should not be necessary, but I'll leave in the code for the paranoid. |
+------------------------------------------------------------------------------*/
+
+#define NS_MOZILLA_DIR_PERMISSION 00700
+
+#include "nsRegistry.h"
+/*
+struct nsRegistry : public nsIRegistry {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistry interface functions.
+ NS_DECL_NSIREGISTRY
+
+ // ctor/dtor
+ nsRegistry();
+
+private:
+ ~nsRegistry();
+
+protected:
+ HREG mReg; // Registry handle.
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
+#endif
+ char *mCurRegFile; // these are to prevent open from opening the registry again
+ nsWellKnownRegistry mCurRegID;
+
+ NS_IMETHOD Close();
+}; // nsRegistry
+*/
+
+#include "nsIFactory.h"
+/*----------------------------- nsRegistryFactory ------------------------------
+| Class factory for nsRegistry objects. |
+------------------------------------------------------------------------------*/
+struct nsRegistryFactory : public nsIFactory {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // nsIFactory methods
+ NS_IMETHOD CreateInstance(nsISupports *,const nsIID &,void **);
+ NS_IMETHOD LockFactory(PRBool aLock);
+
+ // ctor
+ nsRegistryFactory();
+};
+
+
+/*--------------------------- nsRegSubtreeEnumerator ---------------------------
+| This class implements the nsIEnumerator interface and is used to implement |
+| the nsRegistry EnumerateSubtrees and EnumerateAllSubtrees functions. |
+------------------------------------------------------------------------------*/
+struct nsRegSubtreeEnumerator : public nsIRegistryEnumerator {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIEnumerator interface functions.
+ NS_DECL_NSIENUMERATOR
+
+ // And our magic behind-the-back fast-path thing.
+ NS_DECL_NSIREGISTRYENUMERATOR
+
+ // ctor/dtor
+ nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all );
+ // virtual dtor since subclasses call our Release()
+ virtual ~nsRegSubtreeEnumerator();
+
+protected:
+ NS_IMETHOD advance(); // Implementation file; does appropriate NR_RegEnum call.
+ HREG mReg; // Handle to registry we're affiliated with.
+ RKEY mKey; // Base key being enumerated.
+ char mName[MAXREGPATHLEN]; // The name of the current key which is in mNext
+ REGENUM mEnum; // Corresponding libreg "enumerator".
+ REGENUM mNext; // Lookahead value.
+ PRUint32 mStyle; // Style (indicates all or some);
+ PRBool mDone; // Done flag.
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock;
+#endif
+}; // nsRegSubtreeEnumerator
+
+
+/*--------------------------- nsRegValueEnumerator -----------------------------
+| This class is a variation on nsRegSubtreeEnumerator that allocates |
+| nsRegistryValue objects rather than nsRegistryNode objects. It also |
+| overrides certain functions to make sure the "value" oriented libreg |
+| functions used rather than the subtree oriented ones. |
+------------------------------------------------------------------------------*/
+struct nsRegValueEnumerator : public nsRegSubtreeEnumerator {
+ // Override CurrentItem to allocate nsRegistryValue objects.
+ NS_IMETHOD CurrentItem( nsISupports **result );
+
+ // Override advance() to use proper NR_RegEnumEntries.
+ NS_IMETHOD advance();
+
+ // ctor/dtor
+ nsRegValueEnumerator( HREG hReg, RKEY rKey );
+}; // nsRegValueEnumerator
+
+/*------------------------------ nsRegistryNode --------------------------------
+| This class implements the nsIRegistryNode interface. Instances are |
+| allocated by nsRegSubtreeEnumerator::CurrentItem. |
+------------------------------------------------------------------------------*/
+struct nsRegistryNode : public nsIRegistryNode {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistryNode interface functions.
+ NS_DECL_NSIREGISTRYNODE
+
+ // ctor
+ nsRegistryNode( HREG hReg, char *name, RKEY childKey );
+
+private:
+ ~nsRegistryNode();
+
+protected:
+ HREG mReg; // Handle to registry this node is part of.
+ char mName[MAXREGPATHLEN]; // Buffer to hold name.
+ RKEY mChildKey; // Key corresponding to mName
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock;
+#endif
+}; // nsRegistryNode
+
+
+/*------------------------------ nsRegistryValue -------------------------------
+| This class implements the nsIRegistryValue interface. Instances are |
+| allocated by nsRegValueEnumerator::CurrentItem. |
+------------------------------------------------------------------------------*/
+struct nsRegistryValue : public nsIRegistryValue {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistryValue interface functions.
+ NS_DECL_NSIREGISTRYVALUE
+
+ // ctor
+ nsRegistryValue( HREG hReg, RKEY key, REGENUM slot );
+
+private:
+ ~nsRegistryValue();
+
+protected:
+ nsresult getInfo(); // Get registry info.
+ HREG mReg; // Handle to registry this node is part of.
+ RKEY mKey; // Key this node is under.
+ REGENUM mEnum; // Copy of corresponding content of parent enumerator.
+ REGINFO mInfo; // Value info.
+ char mName[MAXREGNAMELEN]; // Buffer to hold name.
+ REGERR mErr; // XXX This causes this class to be NON THREAD SAFE
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock;
+#endif
+}; // nsRegistryValue
+
+
+/*----------------------------- regerr2nsresult --------------------------------
+| This utility function maps a REGERR value to a corresponding nsresult |
+| error code. |
+------------------------------------------------------------------------------*/
+static nsresult regerr2nsresult( REGERR err ) {
+ nsresult rv = NS_ERROR_UNEXPECTED;
+ switch( err ) {
+ case REGERR_OK:
+ rv = NS_OK;
+ break;
+
+ case REGERR_FAIL:
+ rv = NS_ERROR_FAILURE;
+ break;
+
+ case REGERR_NOMORE:
+ rv = NS_ERROR_REG_NO_MORE;
+ break;
+
+ case REGERR_NOFIND:
+ rv = NS_ERROR_REG_NOT_FOUND;
+ break;
+
+ case REGERR_PARAM:
+ case REGERR_BADTYPE:
+ case REGERR_BADNAME:
+ rv = NS_ERROR_INVALID_ARG;
+ break;
+
+ case REGERR_NOFILE:
+ rv = NS_ERROR_REG_NOFILE;
+ break;
+
+ case REGERR_MEMORY:
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+
+ case REGERR_BUFTOOSMALL:
+ rv = NS_ERROR_REG_BUFFER_TOO_SMALL;
+ break;
+
+ case REGERR_NAMETOOLONG:
+ rv = NS_ERROR_REG_NAME_TOO_LONG;
+ break;
+
+ case REGERR_NOPATH:
+ rv = NS_ERROR_REG_NO_PATH;
+ break;
+
+ case REGERR_READONLY:
+ rv = NS_ERROR_REG_READ_ONLY;
+ break;
+
+ case REGERR_BADUTF8:
+ rv = NS_ERROR_REG_BAD_UTF8;
+ break;
+
+ }
+ return rv;
+}
+
+/*----------------------------- reginfo2DataType -------------------------------
+| This utility function converts the type field in the REGINFO structure to |
+| the corresponding nsIRegistry::DataType value. |
+------------------------------------------------------------------------------*/
+static void reginfo2DataType( const REGINFO &in, PRUint32 &out ) {
+ // Transfer information, based on entry type.
+ switch( in.entryType ) {
+ case REGTYPE_ENTRY_STRING_UTF:
+ out = nsIRegistry::String;
+ //out.length = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_INT32_ARRAY:
+ out = nsIRegistry::Int32;
+ // Convert length in bytes to array dimension.
+ //out.length = in.entryLength / sizeof(PRInt32);
+ break;
+
+ case REGTYPE_ENTRY_BYTES:
+ out = nsIRegistry::Bytes;
+ //out.length = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_FILE:
+ out = nsIRegistry::File;
+ //out.length = in.entryLength;
+ break;
+ }
+}
+
+/*----------------------------- reginfo2DataType -------------------------------
+| This utility function converts the length field in the REGINFO structure to |
+| the proper units (if type==Int32 array, we divide by sizeof(PRInt32)). |
+------------------------------------------------------------------------------*/
+static void reginfo2Length( const REGINFO &in, PRUint32 &out ) {
+ // Transfer information, based on entry type.
+ switch( in.entryType ) {
+ case REGTYPE_ENTRY_STRING_UTF:
+ out = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_INT32_ARRAY:
+ // Convert length in bytes to array dimension.
+ out = in.entryLength / sizeof(PRInt32);
+ break;
+
+ case REGTYPE_ENTRY_BYTES:
+ out = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_FILE:
+ out = in.entryLength;
+ break;
+ }
+}
+
+/*------------------------ nsISupports Implementation --------------------------
+| This code generates the implementation of the nsISupports member functions |
+| for each class implemented in this file. |
+------------------------------------------------------------------------------*/
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsRegistry, nsIRegistry, nsIRegistryGetter)
+NS_IMPL_ISUPPORTS2( nsRegSubtreeEnumerator, nsIEnumerator,
+ nsIRegistryEnumerator)
+NS_IMPL_ISUPPORTS1( nsRegistryNode, nsIRegistryNode )
+NS_IMPL_ISUPPORTS1( nsRegistryValue, nsIRegistryValue )
+
+/*-------------------------- nsRegistry::nsRegistry ----------------------------
+| Vanilla nsRegistry constructor. |
+------------------------------------------------------------------------------*/
+nsRegistry::nsRegistry()
+ : mReg(0), mCurRegID(0) {
+#ifdef EXTRA_THREADSAFE
+ mregLock = PR_NewLock();
+#endif
+ NR_StartupRegistry();
+ return;
+}
+
+/*------------------------- nsRegistry::~nsRegistry ----------------------------
+| The dtor closes the registry file(if open). |
+------------------------------------------------------------------------------*/
+nsRegistry::~nsRegistry() {
+ if( mReg ) {
+ Close();
+ }
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+ NR_ShutdownRegistry();
+ return;
+}
+
+/*----------------------------- nsRegistry::Open -------------------------------
+| If the argument is null, delegate to OpenDefault, else open the registry |
+| file. We first check to see if a registry file is already open and close |
+| it if so. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Open( nsIFile *regFile ) {
+ REGERR err = REGERR_OK;
+
+ // Check for default.
+ if( !regFile ) {
+ return OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry);
+ }
+
+ nsCAutoString regPath;
+ nsresult rv = regFile->GetNativePath(regPath);
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef DEBUG_dp
+ printf("nsRegistry: Opening registry %s\n", regPath.get());
+#endif /* DEBUG_dp */
+
+ if (mCurRegID != nsIRegistry::None && mCurRegID != nsIRegistry::ApplicationCustomRegistry)
+ {
+ // Cant open another registry without closing explictly.
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // Do we have an open registry ?
+ if (mCurRegID != nsIRegistry::None)
+ {
+ PRBool equals;
+ if (mCurRegFile && NS_SUCCEEDED(mCurRegFile->Equals(regFile, &equals)) && equals)
+ {
+ // The right one is already open
+ return NS_OK;
+ }
+ else
+ {
+ // Opening a new registry without closing an already open one.
+ // This is an error.
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // Open specified registry.
+ PR_Lock(mregLock);
+ err = NR_RegOpen(NS_CONST_CAST(char*,regPath.get()), &mReg);
+ PR_Unlock(mregLock);
+
+ mCurRegID = nsIRegistry::ApplicationCustomRegistry;
+
+ // No error checking for no mem. Trust me.
+ if (NS_FAILED(regFile->Clone(getter_AddRefs(mCurRegFile))))
+ mCurRegFile = nsnull; // not fatal
+
+ // Convert the result.
+ return regerr2nsresult( err );
+}
+
+static void
+EnsureDefaultRegistryDirectory() {
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ // Create ~/.mozilla as that is the default place for the registry file
+
+ /* The default registry on the unix system is $HOME/.mozilla/registry per
+ * vr_findGlobalRegName(). vr_findRegFile() will create the registry file
+ * if it doesn't exist. But it wont create directories.
+ *
+ * Hence we need to create the directory if it doesn't exist already.
+ *
+ * Why create it here as opposed to the app ?
+ * ------------------------------------------
+ * The app cannot create the directory in main() as most of the registry
+ * and initialization happens due to use of static variables.
+ * And we dont want to be dependent on the order in which
+ * these static stuff happen.
+ *
+ * Permission for the $HOME/.mozilla will be Read,Write,Execute
+ * for user only. Nothing to group and others.
+ */
+ char *home = getenv("HOME");
+ if (home != NULL)
+ {
+ char dotMozillaDir[1024];
+ PR_snprintf(dotMozillaDir, sizeof(dotMozillaDir),
+ "%s/" MOZ_USER_DIR, home);
+ if (PR_Access(dotMozillaDir, PR_ACCESS_EXISTS) != PR_SUCCESS)
+ {
+ PR_MkDir(dotMozillaDir, NS_MOZILLA_DIR_PERMISSION);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsComponentManager: Creating Directory %s", dotMozillaDir));
+ }
+ }
+#endif /* XP_UNIX */
+
+#ifdef XP_BEOS
+ BPath p;
+ const char *settings = "/boot/home/config/settings";
+ if(find_directory(B_USER_SETTINGS_DIRECTORY, &p) == B_OK)
+ settings = p.Path();
+ char settingsMozillaDir[1024];
+ PR_snprintf(settingsMozillaDir, sizeof(settingsMozillaDir),
+ "%s/" MOZ_USER_DIR, settings);
+ if (PR_Access(settingsMozillaDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_MkDir(settingsMozillaDir, NS_MOZILLA_DIR_PERMISSION);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsComponentManager: Creating Directory %s", settingsMozillaDir));
+ }
+#endif
+}
+
+/*----------------------------- nsRegistry::OpenWellKnownRegistry --------------
+| Takes a registry id and maps that to a file name for opening. We first check |
+| to see if a registry file is already open and close it if so. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::OpenWellKnownRegistry( nsWellKnownRegistry regid )
+{
+ REGERR err = REGERR_OK;
+
+ if (mCurRegID != nsIRegistry::None && mCurRegID != regid)
+ {
+ // Cant open another registry without closing explictly.
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (mCurRegID == regid)
+ {
+ // Already opened.
+ return NS_OK;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> registryLocation;
+
+ PRBool foundReg = PR_FALSE;
+ nsCAutoString regFile;
+
+ switch ( (nsWellKnownRegistry) regid ) {
+ case ApplicationComponentRegistry:
+ NS_WARNING("ApplicationComponentRegistry is unsupported!");
+ break;
+ case ApplicationRegistry:
+ {
+ EnsureDefaultRegistryDirectory();
+ nsCOMPtr<nsIProperties> directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ directoryService->Get(NS_APP_APPLICATION_REGISTRY_FILE, NS_GET_IID(nsIFile),
+ getter_AddRefs(registryLocation));
+
+ if (registryLocation)
+ {
+ foundReg = PR_TRUE;
+ rv = registryLocation->GetNativePath(regFile); // dougt fix...
+ // dveditz needs to fix his registry so that I can pass an
+ // nsIFile interface and not hack
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (foundReg == PR_FALSE) {
+ return NS_ERROR_REG_BADTYPE;
+ }
+
+#ifdef DEBUG_dp
+ printf("nsRegistry: Opening std registry %s\n", regFile.get());
+#endif /* DEBUG_dp */
+
+ PR_Lock(mregLock);
+ err = NR_RegOpen(NS_CONST_CAST(char*, regFile.get()), &mReg );
+ PR_Unlock(mregLock);
+
+ // Store the registry that was opened for optimizing future opens.
+ mCurRegID = regid;
+
+ // Convert the result.
+ return regerr2nsresult( err );
+}
+
+#if 0
+/*-------------------------- nsRegistry::OpenDefault ---------------------------
+| Open the "default" registry; in the case of this libreg-based implementation |
+| that is done by passing a null file name pointer to NR_RegOpen. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::OpenDefault() {
+ return OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry);
+}
+#endif
+
+/*----------------------------- nsRegistry::Close ------------------------------
+| Tests the mReg handle and if non-null, closes the registry via NR_RegClose. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Close() {
+ REGERR err = REGERR_OK;
+ if( mReg ) {
+ PR_Lock(mregLock);
+ err = NR_RegClose( mReg );
+ PR_Unlock(mregLock);
+ mReg = 0;
+ mCurRegFile = nsnull;
+ mCurRegID = 0;
+ }
+ return regerr2nsresult( err );
+}
+
+/*----------------------------- nsRegistry::Flush ------------------------------
+| Flushes the registry via NR_RegFlush. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Flush() {
+ REGERR err = REGERR_FAIL;
+ if( mReg ) {
+ PR_Lock(mregLock);
+ err = NR_RegFlush( mReg );
+ PR_Unlock(mregLock);
+ }
+ return regerr2nsresult( err );
+}
+
+/*----------------------------- nsRegistry::IsOpen -----------------------------
+| Tests the mReg handle and returns whether the registry is open or not. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::IsOpen( PRBool *result ) {
+ *result = ( mReg != 0 );
+ return NS_OK;
+}
+
+
+/*--------------------------- nsRegistry::AddKey -------------------------------
+| Add a key into the registry or find an existing one. This is generally used |
+| instead of GetKey unless it's an error for the key not to exist already i
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::AddKey( nsRegistryKey baseKey, const PRUnichar *keyname, nsRegistryKey *_retval)
+{
+ if ( !keyname )
+ return NS_ERROR_NULL_POINTER;
+
+ return AddSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get(), _retval );
+}
+
+/*--------------------------- nsRegistry::GetKey -------------------------------
+| returns the nsRegistryKey associated with a given node in the registry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetKey(nsRegistryKey baseKey, const PRUnichar *keyname, nsRegistryKey *_retval)
+{
+ if ( !keyname || !_retval )
+ return NS_ERROR_NULL_POINTER;
+
+ return GetSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get(), _retval );
+}
+
+/*--------------------------- nsRegistry::RemoveKey ----------------------------
+| Delete a key from the registry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::RemoveKey(nsRegistryKey baseKey, const PRUnichar *keyname)
+{
+ if ( !keyname )
+ return NS_ERROR_NULL_POINTER;
+
+ return RemoveSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get() );
+}
+
+NS_IMETHODIMP nsRegistry::GetString(nsRegistryKey baseKey, const PRUnichar *valname, PRUnichar **_retval)
+{
+ // Make sure caller gave us place for result.
+ if ( !valname || !_retval )
+ return NS_ERROR_NULL_POINTER;
+
+ // initialize the return value
+ *_retval = nsnull;
+ nsXPIDLCString tmpstr;
+
+ nsresult rv = GetStringUTF8( baseKey, NS_ConvertUCS2toUTF8(valname).get(), getter_Copies(tmpstr) );
+
+ if (NS_SUCCEEDED(rv))
+ {
+ *_retval = nsTextFormatter::smprintf( widestrFormat, tmpstr.get() );
+ if ( *_retval == nsnull )
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP nsRegistry::SetString(nsRegistryKey baseKey, const PRUnichar *valname, const PRUnichar *value)
+{
+ if ( !valname || ! value )
+ return NS_ERROR_NULL_POINTER;
+
+ return SetStringUTF8( baseKey,
+ NS_ConvertUCS2toUTF8(valname).get(),
+ NS_ConvertUCS2toUTF8(value).get() );
+}
+
+/*--------------------------- nsRegistry::GetString ----------------------------
+| First, look for the entry using GetValueInfo. If found, and it's a string, |
+| allocate space for it and fetch the value. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path, char **result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // Make sure caller gave us place for result.
+ if ( !result )
+ return NS_ERROR_NULL_POINTER;
+
+ char regStr[MAXREGPATHLEN];
+
+ // initialize the return value
+ *result = 0;
+
+ // Attempt to get string into our fixed buffer
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr,
+ sizeof(regStr) );
+ PR_Unlock(mregLock);
+
+ if ( err == REGERR_OK )
+ {
+ *result = nsCRT::strdup(regStr);
+ if (!*result)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ else if ( err == REGERR_BUFTOOSMALL )
+ {
+ // find the real size and malloc it
+ PRUint32 length;
+ rv = GetValueLength( baseKey, path, &length );
+ // See if that worked.
+ if( rv == NS_OK )
+ {
+ *result =(char*)nsMemory::Alloc( length + 1 );
+ if( *result )
+ {
+ // Get string from registry into result buffer.
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, *result, length+1 );
+ PR_Unlock(mregLock);
+
+ // Convert status.
+ rv = regerr2nsresult( err );
+ if ( rv != NS_OK )
+ {
+ // Didn't get result, free buffer
+ nsCRT::free( *result );
+ *result = 0;
+ }
+ }
+ else
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+ else
+ {
+ // Convert status.
+ rv = regerr2nsresult( err );
+ NS_ASSERTION(NS_FAILED(rv), "returning success code on failure");
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsRegistry::GetStringUTF8IntoBuffer( nsRegistryKey baseKey, const char *path,
+ char *buf, PRUint32 *length )
+{
+ REGERR err = REGERR_OK;
+
+ // Attempt to get string into our fixed buffer
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, buf, *length );
+ PR_Unlock(mregLock);
+
+ // Convert status.
+ nsresult rv = regerr2nsresult( err );
+
+ if (rv == NS_ERROR_REG_BUFFER_TOO_SMALL) {
+ // fill length with the actual length
+ nsresult rv1 = GetValueLength( baseKey, path, length );
+ if(NS_FAILED(rv1))
+ return rv1;
+ }
+
+ return rv;
+}
+
+/*--------------------------- nsRegistry::SetString ----------------------------
+| Simply sets the registry contents using NR_RegSetEntryString. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path, const char *value ) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+ err = NR_RegSetEntryString( mReg,(RKEY)baseKey,(char*)path,(char*)value );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------
+| This function is just shorthand for fetching a char array. We |
+| implement it "manually" using NR_RegGetEntry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ if ( !result )
+ return NS_ERROR_NULL_POINTER;
+
+ char regStr[MAXREGPATHLEN];
+
+ // initialize the return value
+ *length = 0;
+ *result = 0;
+
+ // Get info about the requested entry.
+ PRUint32 type;
+ rv = GetValueType( baseKey, path, &type );
+ // See if that worked.
+ if( rv == NS_OK )
+ {
+ // Make sure the entry is an PRInt8 array.
+ if( type == Bytes )
+ {
+ // Attempt to get string into our fixed buffer
+ PR_Lock(mregLock);
+ uint32 length2 = sizeof regStr;
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2);
+ PR_Unlock(mregLock);
+
+ if ( err == REGERR_OK )
+ {
+ *length = length2;
+ *result = (PRUint8*)(nsCRT::strdup(regStr));
+ if (!*result)
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ *length = 0;
+ }
+ else
+ {
+ *length = length2;
+ }
+ }
+ else if ( err == REGERR_BUFTOOSMALL )
+ {
+ // find the real size and malloc it
+ rv = GetValueLength( baseKey, path, length );
+ // See if that worked.
+ if( rv == NS_OK )
+ {
+ *result = NS_REINTERPRET_CAST(PRUint8*,nsMemory::Alloc( *length ));
+ if( *result )
+ {
+ // Get bytes from registry into result field.
+ PR_Lock(mregLock);
+ length2 = *length;
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2);
+ *length = length2;
+ PR_Unlock(mregLock);
+ // Convert status.
+ rv = regerr2nsresult( err );
+ if ( rv != NS_OK )
+ {
+ // Didn't get result, free buffer
+ nsCRT::free( NS_REINTERPRET_CAST(char*, *result) );
+ *result = 0;
+ *length = 0;
+ }
+ }
+ else
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+ }
+ else
+ {
+ // They asked for the wrong type of value.
+ rv = NS_ERROR_REG_BADTYPE;
+ }
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsRegistry::GetBytesUTF8IntoBuffer( nsRegistryKey baseKey, const char *path,
+ PRUint8 *buf, PRUint32* length )
+{
+ REGERR err = REGERR_OK;
+
+ // Get info about the requested entry.
+ PRUint32 type;
+ nsresult rv = GetValueType( baseKey, path, &type );
+ // See if that worked.
+ if(NS_FAILED(rv))
+ return rv;
+ // Make sure we are dealing with bytes
+ if (type != Bytes)
+ return NS_ERROR_REG_BADTYPE;
+
+ // Attempt to get bytes into our fixed buffer
+ PR_Lock(mregLock);
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path),
+ buf, (uint32 *)length );
+ PR_Unlock(mregLock);
+
+ rv = regerr2nsresult(rv);
+
+ if (rv == NS_ERROR_REG_BUFFER_TOO_SMALL) {
+ // fill length with the actual length
+ nsresult rv1 = GetValueLength( baseKey, path, length );
+ if(NS_FAILED(rv1))
+ return rv1;
+ }
+
+
+ return rv;
+}
+
+/*---------------------------- nsRegistry::GetInt ------------------------------
+| This function is just shorthand for fetching a 1-element PRInt32 array. We |
+| implement it "manually" using NR_RegGetEntry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetInt( nsRegistryKey baseKey, const char *path, PRInt32 *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // Make sure caller gave us place for result.
+ if( result ) {
+ // Get info about the requested entry.
+ PRUint32 type;
+ rv = GetValueType( baseKey, path, &type );
+ // See if that worked.
+ if( rv == NS_OK ) {
+ // Make sure the entry is an PRInt32 array.
+ if( type == Int32 ) {
+ uint32 len = sizeof *result;
+ // Get int from registry into result field.
+ PR_Lock(mregLock);
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, &len );
+ PR_Unlock(mregLock);
+ // Convert status.
+ rv = regerr2nsresult( err );
+ } else {
+ // They asked for the wrong type of value.
+ rv = NS_ERROR_REG_BADTYPE;
+ }
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+
+/*---------------------------- nsRegistry::GetLongLong--------------------------
+| This function is just shorthand for fetching a 1-element PRInt64 array. We |
+| implement it "manually" using NR_RegGetEntry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path, PRInt64 *result ) {
+ REGERR err = REGERR_OK;
+
+ PR_Lock(mregLock);
+
+ uint32 length = sizeof(PRInt64);
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path,(void*)result,&length);
+
+ PR_Unlock(mregLock);
+
+ // Convert status.
+ return regerr2nsresult( err );
+}
+/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------
+| Write out the value as a char array, using NR_RegSetEntry. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+ err = NR_RegSetEntry( mReg,
+ (RKEY)baseKey,
+ (char*)path,
+ REGTYPE_ENTRY_BYTES,
+ (char*)value,
+ length);
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*---------------------------- nsRegistry::SetInt ------------------------------
+| Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetInt( nsRegistryKey baseKey, const char *path, PRInt32 value ) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+ err = NR_RegSetEntry( mReg,
+ (RKEY)baseKey,
+ (char*)path,
+ REGTYPE_ENTRY_INT32_ARRAY,
+ &value,
+ sizeof value );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+
+
+/*---------------------------- nsRegistry::SetLongLong---------------------------
+| Write out the value as a one-element PRInt64 array, using NR_RegSetEntry. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetLongLong( nsRegistryKey baseKey, const char *path, PRInt64* value ) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+
+ err = NR_RegSetEntry( mReg,
+ (RKEY)baseKey,
+ (char*)path,
+ REGTYPE_ENTRY_BYTES,
+ (void*)value,
+ sizeof(PRInt64) );
+
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*-------------------------- nsRegistry::AddSubtree ----------------------------
+| Add a new registry subkey with the specified name, using NR_RegAddKey. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::AddSubtree( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ REGERR err = REGERR_OK;
+ // Add the subkey.
+ PR_Lock(mregLock);
+ err = NR_RegAddKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*-------------------------- nsRegistry::AddSubtreeRaw--------------------------
+| Add a new registry subkey with the specified name, using NR_RegAddKeyRaw |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::AddSubtreeRaw( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ REGERR err = REGERR_OK;
+ // Add the subkey.
+ PR_Lock(mregLock);
+ err = NR_RegAddKeyRaw( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+
+/*------------------------- nsRegistry::RemoveSubtree --------------------------
+| Deletes the subtree at a given location using NR_RegDeleteKey. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // libreg doesn't delete keys if there are subkeys under the key
+ // Hence we have to recurse through to delete the subtree
+
+ RKEY key;
+
+ PR_Lock(mregLock);
+ err = NR_RegGetKey(mReg, baseKey, (char *)path, &key);
+ PR_Unlock(mregLock);
+ if (err != REGERR_OK)
+ {
+ rv = regerr2nsresult( err );
+ return rv;
+ }
+
+ // Now recurse through and delete all keys under hierarchy
+
+ char subkeyname[MAXREGPATHLEN+1];
+ REGENUM state = 0;
+ subkeyname[0] = '\0';
+ while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, sizeof(subkeyname),
+ REGENUM_NORMAL) == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...recursing into %s\n", subkeyname);
+#endif /* DEBUG_dp */
+ // Even though this is not a "Raw" API the subkeys may still, in fact,
+ // *be* raw. Since we're recursively deleting this will work either way.
+ // If we were guaranteed none would be raw then a depth-first enumeration
+ // would be much more efficient.
+ err = RemoveSubtreeRaw(key, subkeyname);
+ if (err != REGERR_OK) break;
+ }
+
+ // If success in deleting all subkeys, delete this key too
+ if (err == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...deleting %s\n", path);
+#endif /* DEBUG_dp */
+ PR_Lock(mregLock);
+ err = NR_RegDeleteKey(mReg, baseKey, (char *)path);
+ PR_Unlock(mregLock);
+ }
+
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+
+
+/*------------------------- nsRegistry::RemoveSubtreeRaw -----------------------
+| Deletes the subtree at a given location using NR_RegDeleteKeyRaw |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *keyname ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // libreg doesn't delete keys if there are subkeys under the key
+ // Hence we have to recurse through to delete the subtree
+
+ RKEY key;
+ char subkeyname[MAXREGPATHLEN+1];
+ int n = sizeof(subkeyname);
+ REGENUM state = 0;
+
+ PR_Lock(mregLock);
+ err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key);
+ PR_Unlock(mregLock);
+ if (err != REGERR_OK)
+ {
+ rv = regerr2nsresult( err );
+ return rv;
+ }
+
+ // Now recurse through and delete all keys under hierarchy
+
+ subkeyname[0] = '\0';
+ while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...recursing into %s\n", subkeyname);
+#endif /* DEBUG_dp */
+ err = RemoveSubtreeRaw(key, subkeyname);
+ if (err != REGERR_OK) break;
+ }
+
+ // If success in deleting all subkeys, delete this key too
+ if (err == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...deleting %s\n", keyname);
+#endif /* DEBUG_dp */
+ PR_Lock(mregLock);
+ err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname);
+ PR_Unlock(mregLock);
+ }
+
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+/*-------------------------- nsRegistry::GetSubtree ----------------------------
+| Returns a nsRegistryKey(RKEY) for a given key/path. The key is |
+| obtained using NR_RegGetKey. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetSubtree( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place for the result.
+ if( result ) {
+ // Get key.
+ PR_Lock(mregLock);
+ err = NR_RegGetKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*-------------------------- nsRegistry::GetSubtreeRaw--------------------------
+| Returns a nsRegistryKey(RKEY) for a given key/path. The key is |
+| obtained using NR_RegGetKeyRaw. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetSubtreeRaw( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place for the result.
+ if( result ) {
+ // Get key.
+ PR_Lock(mregLock);
+ err = NR_RegGetKeyRaw( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+
+/*----------------------- nsRegistry::EnumerateSubtrees ------------------------
+| Allocate a nsRegSubtreeEnumerator object and return it to the caller. |
+| We construct the enumerator using the registry handle from this registry |
+| object, the user-specified registry key, and indicate that we don't want |
+| to recurse down subtrees. No libreg functions are invoked at this point |
+|(that will happen when the enumerator member functions are called). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::EnumerateSubtrees( nsRegistryKey baseKey, nsIEnumerator **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_FALSE );
+ // Check for success.
+ if( *result ) {
+ // Bump refcnt on behalf of caller.
+ NS_ADDREF(*result);
+ } else {
+ // Unable to allocate space for the enumerator object.
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*--------------------- nsRegistry::EnumerateAllSubtrees -----------------------
+| Same as EnumerateSubtrees but we pass PR_TRUE to request that the |
+| enumerator object descend subtrees when it is used. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::EnumerateAllSubtrees( nsRegistryKey baseKey, nsIEnumerator **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_TRUE );
+ // Check for success.
+ if( *result ) {
+ // Bump refcnt on behalf of caller.
+ NS_ADDREF(*result);
+ } else {
+ // Unable to allocate space for the enumerator object.
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------- nsRegistry::GetValueType ---------------------------
+| Gets the type from the registry using the NR_GetEntryInfo libreg API. |
+| The result is transferred to the PRUint32 value passed in (with conversion |
+| to the appropriate nsIRegistry::DataType value). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetValueType( nsRegistryKey baseKey, const char *path, PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Get registry info into local structure.
+ REGINFO info = { sizeof info, 0, 0 };
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info );
+ PR_Unlock(mregLock);
+ if( err == REGERR_OK ) {
+ // Copy info to user's result value.
+ reginfo2DataType( info, *result );
+ } else {
+ rv = regerr2nsresult( err );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------ nsRegistry::GetValueLength --------------------------
+| Gets the registry value info via NR_RegGetEntryInfo. The length is |
+| converted to the proper "units" via reginfo2Length. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetValueLength( nsRegistryKey baseKey, const char *path, PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Get registry info into local structure.
+ REGINFO info = { sizeof info, 0, 0 };
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info );
+ PR_Unlock(mregLock);
+ if( err == REGERR_OK ) {
+ // Copy info to user's result value.
+ reginfo2Length( info, *result );
+ } else {
+ rv = regerr2nsresult( err );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*-------------------------- nsRegistry::DeleteValue ---------------------------
+| Remove the registry value with the specified name |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::DeleteValue( nsRegistryKey baseKey, const char *path)
+{
+ REGERR err = REGERR_OK;
+ // Delete the value
+ PR_Lock(mregLock);
+ err = NR_RegDeleteEntry( mReg,(RKEY)baseKey,(char*)path );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*------------------------ nsRegistry::EnumerateValues -------------------------
+| Allocates and returns an instance of nsRegValueEnumerator constructed in |
+| a similar fashion as the nsRegSubtreeEnumerator is allocated/returned by |
+| EnumerateSubtrees. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::EnumerateValues( nsRegistryKey baseKey, nsIEnumerator **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ *result = new nsRegValueEnumerator( mReg,(RKEY)baseKey );
+ // Check for success.
+ if( *result ) {
+ // Bump refcnt on behalf of caller.
+ NS_ADDREF(*result);
+ } else {
+ // Unable to allocate space for the enumerator object.
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*---------------------- nsRegistry::GetCurrentUserName ------------------------
+| Simple wrapper for NR_RegGetUsername. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetCurrentUserName( char **result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Get the user name.
+ PR_Lock(mregLock);
+ err = NR_RegGetUsername( result );
+ PR_Unlock(mregLock);
+ // Convert the result.
+ rv = regerr2nsresult( err );
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*---------------------- nsRegistry::SetCurrentUserName ------------------------
+| Simple wrapper for NR_RegSetUsername. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetCurrentUserName( const char *name ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Set the user name.
+ PR_Lock(mregLock);
+ err = NR_RegSetUsername( name );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+
+/*----------------------------- nsRegistry::Pack -------------------------------
+| Simple wrapper for NR_RegPack. We don't set up any callback. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Pack() {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Pack the registry.
+ PR_Lock(mregLock);
+ err = NR_RegPack( mReg, 0, 0 );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+
+/*----------------------------- nsRegistry::EscapeKey -------------------------------
+| Escape a binary key so that the registry works OK, since it expects UTF8
+| with no slashes or control characters. This is probably better than raw.
+| If no escaping is required, then the method is successful and a null is
+| returned, indicating that the caller should use the original string.
+------------------------------------------------------------------------------*/
+static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF";
+NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped)
+{
+ nsresult rv = NS_OK;
+ char* value = (char*)key;
+ char* b = value;
+ char* e = b + *length;
+ int escapees = 0;
+ while (b < e) // Count characters outside legal range or slash
+ {
+ int c = *b++;
+ if (c <= ' '
+ || c > '~'
+ || c == '/'
+ || c == '%')
+ {
+ escapees++;
+ }
+ }
+ if (escapees == 0) // If no escapees, then no results
+ {
+ *length = 0;
+ *escaped = nsnull;
+ return NS_OK;
+ }
+ // New length includes two extra chars for escapees.
+ *length += escapees * 2;
+ *escaped = (PRUint8*)nsMemory::Alloc(*length + termination);
+ if (*escaped == nsnull)
+ {
+ *length = 0;
+ *escaped = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ char* n = (char*)*escaped;
+ b = value;
+ while (escapees && b < e)
+ {
+ char c = *b++;
+ if (c < ' '
+ || c > '~'
+ || c == '/'
+ || c == '%')
+ {
+ *(n++) = '%';
+ *(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ];
+ *(n++) = sEscapeKeyHex[ 0xF & c ];
+ escapees--;
+ }
+ else
+ {
+ *(n++) = c;
+ }
+ }
+ e += termination;
+ if (b < e)
+ {
+ strncpy(n, b, e - b);
+ }
+ return rv;
+}
+
+/*----------------------------- nsRegistry::UnescapeKey -------------------------------
+| Unscape a binary key so that the registry works OK, since it expects UTF8
+| with no slashes or control characters. This is probably better than raw.
+| If no escaping is required, then the method is successful and a null is
+| returned, indicating that the caller should use the original string.
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key)
+{
+ nsresult rv = NS_OK;
+ char* value = (char*)escaped;
+ char* b = value;
+ char* e = b + *length;
+ int escapees = 0;
+ while (b < e) // Count characters outside legal range or slash
+ {
+ if (*b++ == '%')
+ {
+ escapees++;
+ }
+ }
+ if (escapees == 0) // If no escapees, then no results
+ {
+ *length = 0;
+ *key = nsnull;
+ return NS_OK;
+ }
+ // New length includes two extra chars for escapees.
+ *length -= escapees * 2;
+ *key = (PRUint8*)nsMemory::Alloc(*length + termination);
+ if (*key == nsnull)
+ {
+ *length = 0;
+ *key = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ char* n = (char*)*key;
+ b = value;
+ while (escapees && b < e)
+ {
+ char c = *(b++);
+ if (c == '%')
+ {
+ if (e - b >= 2)
+ {
+ const char* c1 = strchr(sEscapeKeyHex, *(b++));
+ const char* c2 = strchr(sEscapeKeyHex, *(b++));
+ if (c1 != nsnull
+ && c2 != nsnull)
+ {
+ *(n++) = ((c2 - sEscapeKeyHex) & 0xF)
+ | (((c1 - sEscapeKeyHex) & 0xF) << 4);
+ }
+ else
+ {
+ escapees = -1;
+ }
+ }
+ else
+ {
+ escapees = -1;
+ }
+ escapees--;
+ }
+ else
+ {
+ *(n++) = c;
+ }
+ }
+ if (escapees < 0)
+ {
+ nsMemory::Free(*key);
+ *length = 0;
+ *key = nsnull;
+ return NS_ERROR_INVALID_ARG;
+ }
+ e += termination;
+ if (b < e)
+ {
+ strncpy(n, b, e - b);
+ }
+ return rv;
+}
+
+
+/*-------------- nsRegistry::SetBufferSize-------------------------------------
+| Sets the size of the file used for the registry's buffer size. |
+------------------------------------------------------------------------------*/
+int nsRegistry::SetBufferSize( int bufsize )
+{
+ int newSize;
+ // set the file buffer size
+ PR_Lock(mregLock);
+ newSize = NR_RegSetBufferSize( mReg, bufsize );
+ PR_Unlock(mregLock);
+ return newSize;
+}
+
+
+/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ----------------
+| The ctor simply stashes all the information that will be needed to enumerate |
+| the subkeys. |
+------------------------------------------------------------------------------*/
+nsRegSubtreeEnumerator::nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all )
+ : mReg( hReg ), mKey( rKey ), mEnum( 0 ), mNext( 0 ),
+ mStyle( all ? REGENUM_DESCEND : REGENUM_CHILDREN ), mDone( PR_FALSE ) {
+
+ mName[0] = '\0';
+
+#ifdef EXTRA_THREADSAFE
+ // Create a registry lock
+ mregLock = PR_NewLock();
+#endif
+ return;
+}
+
+nsRegSubtreeEnumerator::~nsRegSubtreeEnumerator()
+{
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+}
+
+/*----------------------- nsRegSubtreeEnumerator::First ------------------------
+| Set mEnum to 0; this will cause the next NR_RegEnum call to go to |
+| the beginning. We then do a Next() call in order to do a "lookahead" to |
+| properly detect an empty list (i.e., set the mDone flag). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::First() {
+ nsresult rv = NS_OK;
+ // Reset "done" flag.
+ mDone = PR_FALSE;
+ // Clear Name
+ mName[0] = '\0';
+ // Go to beginning.
+ mEnum = mNext = 0;
+ // Lookahead so mDone flag gets set for empty list.
+ rv = Next();
+ return rv;
+}
+
+/*----------------------- nsRegSubtreeEnumerator::Next -------------------------
+| First, we check if we've already advanced to the end by checking the mDone |
+| flag. |
+| |
+| We advance mEnum to the next enumeration value which is in the mNext |
+| lookahead buffer. We must then call advance to lookahead and properly set |
+| the isDone flag. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::Next() {
+ nsresult rv = NS_OK;
+ // Check for at end.
+ if ( !mDone ) {
+ // Advance to next spot.
+ mEnum = mNext;
+ // Lookahead so mDone is properly set (and to update mNext).
+ rv = advance();
+ } else {
+ // Set result accordingly.
+ rv = regerr2nsresult( REGERR_NOMORE );
+ }
+ return rv;
+}
+
+/*---------------------- nsRegSubtreeEnumerator::advance -----------------------
+| Advance mNext to next subkey using NR_RegEnumSubkeys. We set mDone if |
+| there are no more subkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegSubtreeEnumerator::advance() {
+ REGERR err = REGERR_OK;
+ PR_Lock(mregLock);
+ err = NR_RegEnumSubkeys( mReg, mKey, &mNext, mName, sizeof mName, mStyle );
+ // See if we ran off end.
+ if( err == REGERR_NOMORE ) {
+ // Remember we've run off end.
+ mDone = PR_TRUE;
+ }
+ PR_Unlock(mregLock);
+ // Convert result.
+ nsresult rv = regerr2nsresult( err );
+ return rv;
+}
+
+/*-------------------- nsRegSubtreeEnumerator::CurrentItem ---------------------
+| Allocates and returns a new instance of class nsRegistryNode. The node |
+| object will hold the curent mEnum value so it can obtain its name from |
+| the registry when asked. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::CurrentItem( nsISupports **result) {
+ nsresult rv = NS_OK;
+ // Make sure there is a place to put the result.
+ if( result ) {
+ *result = new nsRegistryNode( mReg, mName, (RKEY) mNext );
+ if( *result ) {
+ NS_ADDREF(*result);
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*--------------nsRegSubtreeEnumerator::CurrentItemInPlaceUTF8-----------------
+| An ugly name for an ugly function. Hands back a shared pointer to the |
+| name (encoded as UTF-8), and the subkey identifier. |
+-----------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::CurrentItemInPlaceUTF8( nsRegistryKey *childKey ,
+ const char **name )
+{
+ *childKey = mNext;
+ /* [shared] */
+ *name = mName;
+ return NS_OK;
+}
+
+/*---------------------- nsRegSubtreeEnumerator::IsDone ------------------------
+| Simply return mDone. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::IsDone() {
+ nsresult rv = mDone ? NS_OK : NS_ENUMERATOR_FALSE;
+ return rv;
+}
+
+
+/*---------------- nsRegValueEnumerator::nsRegValueEnumerator ------------------
+| Delegates everything to the base class constructor. |
+------------------------------------------------------------------------------*/
+nsRegValueEnumerator::nsRegValueEnumerator( HREG hReg, RKEY rKey )
+ : nsRegSubtreeEnumerator( hReg, rKey, PR_FALSE ) {
+ return;
+}
+
+
+/*--------------------- nsRegValueEnumerator::CurrentItem ----------------------
+| As the nsRegSubtreeEnumerator counterpart, but allocates an object of |
+| class nsRegistryValue. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegValueEnumerator::CurrentItem( nsISupports **result ) {
+ nsresult rv = NS_OK;
+ // Make sure there is a place to put the result.
+ if( result ) {
+ *result = new nsRegistryValue( mReg, mKey, mEnum );
+ if( *result ) {
+ NS_ADDREF(*result);
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*----------------------- nsRegValueEnumerator::advance ------------------------
+| Advance mNext to next subkey using NR_RegEnumEntries. We set mDone if |
+| there are no more entries. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegValueEnumerator::advance() {
+ REGERR err = REGERR_OK;
+ char name[MAXREGNAMELEN];
+ PRUint32 len = sizeof name;
+ REGINFO info = { sizeof info, 0, 0 };
+ PR_Lock(mregLock);
+ err = NR_RegEnumEntries( mReg, mKey, &mNext, name, len, &info );
+ // See if we ran off end.
+ if( err == REGERR_NOMORE ) {
+ // Remember we've run off end.
+ mDone = PR_TRUE;
+ }
+ PR_Unlock(mregLock);
+ // Convert result.
+ nsresult rv = regerr2nsresult( err );
+ return rv;
+}
+
+
+/*---------------------- nsRegistryNode::nsRegistryNode ------------------------
+| Store the arguments in the corresponding data members and initialize |
+| the other data members. We defer the libreg calls till we're asked for |
+| our name. We use mErr==-1 to indicate we haven't fetched the name yet. |
+------------------------------------------------------------------------------*/
+nsRegistryNode::nsRegistryNode( HREG hReg, char *name, RKEY childKey )
+ : mReg( hReg ), mChildKey( childKey ) {
+
+ PR_ASSERT(name != nsnull);
+ strcpy(mName, name);
+
+#ifdef EXTRA_THREADSAFE
+ mregLock = PR_NewLock();
+#endif
+
+ return;
+}
+
+nsRegistryNode::~nsRegistryNode()
+{
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+}
+
+/*-------------------------- nsRegistryNode::GetName ---------------------------
+| If we haven't fetched it yet, get the name of the corresponding subkey now, |
+| using NR_RegEnumSubkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryNode::GetName( PRUnichar **result ) {
+ if (result == nsnull) return NS_ERROR_NULL_POINTER;
+ // Make sure there is a place to put the result.
+ *result = nsTextFormatter::smprintf( widestrFormat, mName );
+ if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/*-------------------------- nsRegistryNode::GetNameUTF8 -----------------------
+| If we haven't fetched it yet, get the name of the corresponding subkey now, |
+| using NR_RegEnumSubkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) {
+ if (result == nsnull) return NS_ERROR_NULL_POINTER;
+ // Make sure there is a place to put the result.
+ *result = nsCRT::strdup( mName );
+ if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/*-------------------------- nsRegistryNode::GetKey ----------------------------
+| Get the subkey corresponding to this node |
+| using NR_RegEnumSubkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) {
+ nsresult rv = NS_OK;
+ if (r_key == nsnull) return NS_ERROR_NULL_POINTER;
+ *r_key = mChildKey;
+ return rv;
+}
+
+
+
+/*--------------------- nsRegistryValue::nsRegistryValue -----------------------
+| Implemented the same way as the nsRegistryNode ctor. |
+------------------------------------------------------------------------------*/
+nsRegistryValue::nsRegistryValue( HREG hReg, RKEY key, REGENUM slot )
+ : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) {
+#ifdef EXTRA_THREADSAFE
+ mregLock = PR_NewLock();
+#endif
+ mInfo.size = sizeof(REGINFO);
+}
+
+nsRegistryValue::~nsRegistryValue()
+{
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+}
+
+/*------------------------- nsRegistryValue::GetName ---------------------------
+| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetName( PRUnichar **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Ensure we've got the info we need.
+ rv = getInfo();
+ if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
+ // worked, return actual result.
+ *result = nsTextFormatter::smprintf( widestrFormat, mName );
+ if ( *result ) {
+ rv = NS_OK;
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------- nsRegistryValue::GetNameUTF8 -----------------------
+| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetNameUTF8( char **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Ensure we've got the info we need.
+ rv = getInfo();
+ if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
+ // worked, return actual result.
+ *result = nsCRT::strdup( mName );
+ if ( *result ) {
+ rv = NS_OK;
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*----------------------- nsRegistryValue::GetType ------------------------
+| We test if we've got the info already. If not, we git it by calling |
+| getInfo. We calculate the result by converting the REGINFO type field to |
+| a nsIRegistry::DataType value (using reginfo2DataType). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetType( PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have room for th result.
+ if( result ) {
+ // Make sure we've got the info we need.
+ rv = getInfo();
+ // Check if it worked.
+ if( rv == NS_OK ) {
+ // Convert result from REGINFO to nsIRegistry::ValueInfo.
+ reginfo2DataType( mInfo, *result );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*---------------------- nsRegistryValue::GetLength -----------------------
+| We test if we've got the info already. If not, we git it by calling |
+| getInfo. We calculate the result by converting the REGINFO type field to |
+| a nsIRegistry::DataType value (using reginfo2Length). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetLength( PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have room for th result.
+ if( result ) {
+ // Make sure we've got the info we need.
+ rv = getInfo();
+ // Check if it worked.
+ if( rv == NS_OK ) {
+ // Convert result from REGINFO to length.
+ reginfo2Length( mInfo, *result );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------- nsRegistryValue::getInfo ---------------------------
+| Call NR_RegEnumEntries to set the mInfo/mName data members. |
+------------------------------------------------------------------------------*/
+nsresult nsRegistryValue::getInfo() {
+ nsresult rv = NS_OK;
+ // Test whether we haven't tried to get it yet.
+ if( mErr == -1 ) {
+ REGENUM temp = mEnum;
+ // Get name and info.
+ PR_Lock(mregLock);
+ mErr = NR_RegEnumEntries( mReg, mKey, &temp, mName, sizeof mName, &mInfo );
+ // Convert result.
+ rv = regerr2nsresult( mErr );
+ PR_Unlock(mregLock);
+ }
+ return rv;
+}
+
+
+nsRegistryFactory::nsRegistryFactory() {
+}
+
+NS_IMPL_ISUPPORTS1(nsRegistryFactory, nsIFactory)
+
+NS_IMETHODIMP
+nsRegistryFactory::CreateInstance(nsISupports *aOuter,
+ const nsIID &aIID,
+ void **aResult) {
+ nsresult rv = NS_OK;
+ nsRegistry* newRegistry;
+
+ if(aResult == nsnull) {
+ return NS_ERROR_NULL_POINTER;
+ } else {
+ *aResult = nsnull;
+ }
+
+ if(0 != aOuter) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ NS_NEWXPCOM(newRegistry, nsRegistry);
+
+ if(newRegistry == nsnull) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(newRegistry);
+ rv = newRegistry->QueryInterface(aIID, aResult);
+ NS_RELEASE(newRegistry);
+
+ return rv;
+}
+
+nsresult
+nsRegistryFactory::LockFactory(PRBool aLock)
+{
+ // Not implemented in simplest case.
+ return NS_OK;
+}
+
+// This is a temporary hack; needs work to support dynamic binding
+// via nsComponentManager and support for multiple factories per DLL.
+extern "C" NS_EXPORT nsresult
+NS_RegistryGetFactory(nsIFactory** aFactory ) {
+ nsresult rv = NS_OK;
+
+ if( aFactory == 0 ) {
+ return NS_ERROR_NULL_POINTER;
+ } else {
+ *aFactory = 0;
+ }
+
+ nsIFactory* inst = new nsRegistryFactory();
+ if(0 == inst) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ NS_ADDREF(inst);
+ *aFactory = inst;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h
new file mode 100644
index 00000000..8b59db36
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Edward Kandrot <kandrot@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#ifndef nsRegistry_h__
+#define nsRegistry_h__
+
+#include "nsIRegistry.h"
+#include "NSReg.h"
+#include "nsIFile.h"
+#include "nsCOMPtr.h"
+
+struct nsRegistry : public nsIRegistry, nsIRegistryGetter {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistry interface functions.
+ NS_DECL_NSIREGISTRY
+
+ // Fast registry getters
+ NS_DECL_NSIREGISTRYGETTER
+
+ int SetBufferSize( int bufsize ); // changes the file buffer size for this registry
+
+ // ctor/dtor
+ nsRegistry();
+
+private:
+ ~nsRegistry();
+
+protected:
+ HREG mReg; // Registry handle.
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
+#endif
+ nsCOMPtr<nsIFile> mCurRegFile; // these are to prevent open from opening the registry again
+ nsWellKnownRegistry mCurRegID;
+
+ NS_IMETHOD Close();
+}; // nsRegistry
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp
new file mode 100644
index 00000000..9a71a916
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsIGenericFactory.h"
+
+#include "nsFileSpecImpl.h"
+#include "nsRegistry.h"
+
+#define COMPONENT(NAME, Ctor) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsRegistry)
+
+static const nsModuleComponentInfo components[] =
+{
+ COMPONENT(FILESPEC, nsFileSpecImpl::Create),
+ COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create),
+ COMPONENT(REGISTRY, nsRegistryConstructor),
+};
+
+NS_IMPL_NSGETMODULE(xpcomObsoleteModule, components)
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp
new file mode 100644
index 00000000..d1b2f85e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp
@@ -0,0 +1,357 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsCOMPtr.h"
+#include "nsIRegistry.h"
+#include "nsIEnumerator.h"
+#include "nsILocalFile.h"
+#include "nsDependentString.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "nsMemory.h"
+
+static void display( nsIRegistry *reg, nsRegistryKey root, const char *name );
+static void displayValues( nsIRegistry *reg, nsRegistryKey root );
+static void printString( const char *value, int indent );
+
+int main( int argc, char *argv[] ) {
+
+
+#ifdef __MWERKS__
+ // Hack in some arguments. A NULL registry name is supposed to tell libreg
+ // to use the default registry (which does seem to work).
+ argc = 1;
+ const char* myArgs[] =
+ {
+ "regExport"
+ };
+ argv = const_cast<char**>(myArgs);
+#endif
+
+ nsresult rv;
+
+ // Initialize XPCOM
+ nsIServiceManager *servMgr = NULL;
+ rv = NS_InitXPCOM2(&servMgr, NULL, NULL);
+ if (NS_FAILED(rv))
+ {
+ // Cannot initialize XPCOM
+ printf("Cannot initialize XPCOM. Exit. [rv=0x%08X]\n", (int)rv);
+ exit(-1);
+ }
+ {
+ // Get the component manager
+ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
+ nsCOMPtr<nsIComponentManager> compMgr = do_GetService(kComponentManagerCID, &rv);
+ if (NS_FAILED(rv))
+ {
+ // Cant get component manager
+ printf("Cannot get component manager from service manager.. Exit. [rv=0x%08X]\n", (int)rv);
+ exit(-1);
+ }
+
+ nsIRegistry *reg;
+
+ if (argc>1) {
+ // Create the registry
+ rv = compMgr->CreateInstanceByContractID(NS_REGISTRY_CONTRACTID, NULL,
+ NS_GET_IID(nsIRegistry),
+ (void **) &reg);
+ // Check result.
+ if ( NS_FAILED(rv) )
+ {
+ printf( "Error opening registry file %s, rv=0x%08X\n", argv[1] , (int)rv );
+ return rv;
+ }
+ // Open it against the input file name.
+ nsCOMPtr<nsILocalFile> regFile;
+ rv = NS_NewNativeLocalFile( nsDependentCString(argv[1]), PR_FALSE, getter_AddRefs(regFile) );
+ if ( NS_FAILED(rv) ) {
+ printf( "Error instantiating local file for %s, rv=0x%08X\n", argv[1], (int)rv );
+ return rv;
+ }
+
+ rv = reg->Open( regFile );
+
+ if ( rv == NS_OK )
+ {
+ printf( "Registry %s opened OK.\n", argv[1] );
+
+ // Recurse over all 3 branches.
+ display( reg, nsIRegistry::Common, "nsRegistry::Common" );
+ display( reg, nsIRegistry::Users, "nsRegistry::Users" );
+ }
+ NS_RELEASE(reg);
+ }
+ else
+ {
+ // Called with no arguments. Print both the default registry and
+ // the components registry. We already printed the default regsitry.
+ // So just do the component registry.
+ rv = compMgr->CreateInstanceByContractID(NS_REGISTRY_CONTRACTID, NULL,
+ NS_GET_IID(nsIRegistry),
+ (void **) &reg);
+
+ // Check result.
+ if ( NS_FAILED(rv) )
+ {
+ printf( "Error opening creating registry instance, rv=0x%08X\n", (int)rv );
+ return rv;
+ }
+ rv = reg->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry);
+ if ( rv == NS_ERROR_REG_BADTYPE ) {
+ printf( "\n\n\nThere is no <Application Component Registry>\n" );
+ }
+ else if ( rv == NS_OK ) {
+
+ printf( "\n\n\nRegistry %s opened OK.\n", "<Application Component Registry>\n" );
+
+ // Recurse over all 3 branches.
+ display( reg, nsIRegistry::Common, "nsRegistry::Common" );
+ display( reg, nsIRegistry::Users, "nsRegistry::Users" );
+ }
+ NS_RELEASE(reg);
+ }
+ }
+ NS_ShutdownXPCOM( servMgr );
+
+ return rv;
+}
+
+void display( nsIRegistry *reg, nsRegistryKey root, const char *rootName ) {
+ // Print out key name.
+ printf( "%s\n", rootName );
+
+ // Make sure it isn't a "root" key.
+ if ( root != nsIRegistry::Common
+ &&
+ root != nsIRegistry::Users
+ &&
+ root != nsIRegistry::CurrentUser ) {
+ // Print values stored under this key.
+ displayValues( reg, root );
+ }
+
+ // Enumerate all subkeys (immediately) under the given node.
+ nsIEnumerator *keys;
+ nsresult rv = reg->EnumerateSubtrees( root, &keys );
+
+ // Check result.
+ if ( rv == NS_OK ) {
+ // Set enumerator to beginning.
+ rv = keys->First();
+ // Enumerate subkeys till done.
+ while( NS_SUCCEEDED( rv ) && (NS_OK != keys->IsDone()) ) {
+ nsISupports *base;
+ rv = keys->CurrentItem( &base );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Get specific interface.
+ nsIRegistryNode *node;
+ nsIID nodeIID = NS_IREGISTRYNODE_IID;
+ rv = base->QueryInterface( nodeIID, (void**)&node );
+ // Test that result.
+ if ( rv == NS_OK ) {
+ // Get node name.
+ char *name;
+ rv = node->GetNameUTF8( &name );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Build complete name.
+ char *fullName = new char[ PL_strlen(rootName) + PL_strlen(name) + 5 ];
+ PL_strcpy( fullName, rootName );
+ PL_strcat( fullName, " - " );
+ PL_strcat( fullName, name );
+ // Display contents under this subkey.
+ nsRegistryKey key;
+ rv = reg->GetSubtreeRaw( root, name, &key );
+ if ( rv == NS_OK ) {
+ display( reg, key, fullName );
+ printf( "\n" );
+ } else {
+ printf( "Error getting key, rv=0x%08X\n", (int)rv );
+ }
+ delete [] fullName;
+ } else {
+ printf( "Error getting subtree name, rv=0x%08X\n", (int)rv );
+ }
+ // Release node.
+ node->Release();
+ } else {
+ printf( "Error converting base node ptr to nsIRegistryNode, rv=0x%08X\n", (int)rv );
+ }
+ // Release item.
+ base->Release();
+
+ // Advance to next key.
+ rv = keys->Next();
+ // Check result.
+ if ( NS_SUCCEEDED( rv ) ) {
+ } else {
+ printf( "Error advancing enumerator, rv=0x%08X\n", (int)rv );
+ }
+ } else {
+ printf( "Error getting current item, rv=0x%08X\n", (int)rv );
+ }
+ }
+ // Release key enumerator.
+ keys->Release();
+ } else {
+ printf( "Error creating enumerator for %s, root=0x%08X, rv=0x%08X\n",
+ rootName, (int)root, (int)rv );
+ }
+ return;
+}
+
+static void displayValues( nsIRegistry *reg, nsRegistryKey root ) {
+ // Emumerate values at this registry location.
+ nsIEnumerator *values;
+ nsresult rv = reg->EnumerateValues( root, &values );
+
+ // Check result.
+ if ( rv == NS_OK ) {
+ // Go to beginning.
+ rv = values->First();
+
+ // Enumerate values till done.
+ while( rv == NS_OK && (NS_OK != values->IsDone()) ) {
+ nsISupports *base;
+ rv = values->CurrentItem( &base );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Get specific interface.
+ nsIRegistryValue *value;
+ nsIID valueIID = NS_IREGISTRYVALUE_IID;
+ rv = base->QueryInterface( valueIID, (void**)&value );
+ // Test that result.
+ if ( rv == NS_OK ) {
+ // Get node name.
+ char *name;
+ rv = value->GetNameUTF8( &name );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Print name:
+ printf( "\t\t%s", name );
+ // Get info about this value.
+ PRUint32 type;
+ rv = reg->GetValueType( root, name, &type );
+ if ( rv == NS_OK ) {
+ // Print value contents.
+ switch ( type ) {
+ case nsIRegistry::String: {
+ char *strValue;
+ rv = reg->GetStringUTF8( root, name, &strValue );
+ if ( rv == NS_OK ) {
+ printString( strValue, strlen(name) );
+ nsMemory::Free( strValue );
+ } else {
+ printf( "\t Error getting string value, rv=0x%08X", (int)rv );
+ }
+ }
+ break;
+
+ case nsIRegistry::Int32:
+ {
+ PRInt32 val = 0;
+ rv = reg->GetInt( root, name, &val );
+ if (NS_SUCCEEDED(rv)) {
+ printf( "\t= Int32 [%d, 0x%x]", val, val);
+ }
+ else {
+ printf( "\t Error getting int32 value, rv=%08X", (int)rv);
+ }
+ }
+ break;
+
+ case nsIRegistry::Bytes:
+ printf( "\t= Bytes" );
+ break;
+
+ case nsIRegistry::File:
+ printf( "\t= File (?)" );
+ break;
+
+ default:
+ printf( "\t= ? (unknown type=0x%02X)", (int)type );
+ break;
+ }
+ } else {
+ printf( "\t= ? (error getting value, rv=0x%08X)", (int)rv );
+ }
+ printf("\n");
+ nsMemory::Free( name );
+ } else {
+ printf( "Error getting value name, rv=0x%08X\n", (int)rv );
+ }
+ // Release node.
+ value->Release();
+ } else {
+ printf( "Error converting base node ptr to nsIRegistryNode, rv=0x%08X\n", (int)rv );
+ }
+ // Release item.
+ base->Release();
+
+ // Advance to next key.
+ rv = values->Next();
+ // Check result.
+ if ( NS_SUCCEEDED( rv ) ) {
+ } else {
+ printf( "Error advancing enumerator, rv=0x%08X\n", (int)rv );
+ break;
+ }
+ } else {
+ printf( "Error getting current item, rv=0x%08X\n", (int)rv );
+ break;
+ }
+ }
+
+ values->Release();
+ } else {
+ printf( "\t\tError enumerating values, rv=0x%08X\n", (int)rv );
+ }
+ return;
+}
+
+static void printString( const char *value, int /*indent*/ ) {
+ // For now, just dump contents.
+ printf( "\t = %s", value );
+ return;
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg b/src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg
new file mode 100644
index 00000000..88cbf236
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg
@@ -0,0 +1,6 @@
+[gecko xpi-bootstrap]
+#if SHARED_LIBRARY
+dist/bin/components/@SHARED_LIBRARY@
+#else
+!staticcomp @LIBRARY@ @MODULE_NAME@
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp b/src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp
new file mode 100644
index 00000000..d904e071
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Force references to all of the symbols that we want exported from
+// the dll that are located in the .lib files we link with
+
+#include "nsFileSpec.h"
+#include "NSReg.h"
+
+void XXXNeverCalled()
+{
+ nsFileURL(NULL);
+ nsFileSpec s;
+
+ NR_RegSetBufferSize(NULL, 0);
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp
new file mode 100644
index 00000000..9be29eb9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp
@@ -0,0 +1,1367 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsFileSpec.h"
+
+#include "nsDebug.h"
+#include "nsEscape.h"
+#include "nsMemory.h"
+
+#include "prtypes.h"
+#include "plstr.h"
+#include "plbase64.h"
+#include "prmem.h"
+
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#if defined(XP_WIN)
+#include <mbstring.h>
+#endif
+
+#ifdef XP_OS2
+extern unsigned char* _mbsrchr( const unsigned char*, int);
+#endif
+
+// return pointer to last instance of the given separator
+static inline char *GetLastSeparator(const char *str, char sep)
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ return (char*) _mbsrchr((const unsigned char *) str, sep);
+#else
+ return (char*) strrchr(str, sep);
+#endif
+}
+
+#if defined(XP_MACOSX)
+#include <sys/stat.h>
+#endif
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#include <Aliases.h>
+#include <TextUtils.h>
+#endif
+
+//========================================================================================
+// class nsSimpleCharString
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString()
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const char* inString)
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+ if (inString)
+ CopyFrom(inString, strlen(inString));
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const nsString& inString)
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+ *this = inString;
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const nsSimpleCharString& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mData = inOther.mData;
+ AddRefData();
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const char* inData, PRUint32 inLength)
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+ CopyFrom(inData, inLength);
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::~nsSimpleCharString()
+//----------------------------------------------------------------------------------------
+{
+ ReleaseData();
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ if (inString)
+ CopyFrom(inString, strlen(inString));
+ else
+ SetToEmpty();
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator = (const nsString& inString)
+//----------------------------------------------------------------------------------------
+{
+ PRUint32 len = inString.Length();
+ ReallocData(len);
+ if (!mData)
+ return;
+ inString.ToCString(mData->mString, len + 1);
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator = (const nsSimpleCharString& inOther)
+//----------------------------------------------------------------------------------------
+{
+ if (mData == inOther.mData)
+ return;
+ ReleaseData();
+ mData = inOther.mData;
+ AddRefData();
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator += (const char* inOther)
+//----------------------------------------------------------------------------------------
+{
+ if (!inOther)
+ return;
+ int newLength = Length() + strlen(inOther);
+ ReallocData(newLength);
+ strcat(mData->mString, inOther);
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString nsSimpleCharString::operator + (const char* inOther) const
+//----------------------------------------------------------------------------------------
+{
+ nsSimpleCharString result(*this);
+ result += inOther;
+ return result;
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::Catenate(const char* inString1, const char* inString2)
+//----------------------------------------------------------------------------------------
+{
+ if (!inString2)
+ {
+ *this += inString1;
+ return;
+ }
+ int newLength = Length() + strlen(inString1) + strlen(inString2);
+ ReallocData(newLength);
+ strcat(mData->mString, inString1);
+ strcat(mData->mString, inString2);
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::CopyFrom(const char* inData, PRUint32 inLength)
+//----------------------------------------------------------------------------------------
+{
+ if (!inData)
+ return;
+ ReallocData(inLength);
+ if (!mData)
+ return;
+ if (inLength != 0) {
+ memcpy(mData->mString, inData, inLength);
+ }
+ mData->mString[inLength] = '\0';
+} // nsSimpleCharString::CopyFrom
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::SetToEmpty()
+//----------------------------------------------------------------------------------------
+{
+ ReleaseData();
+} // nsSimpleCharString::SetToEmpty
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::Unescape()
+//----------------------------------------------------------------------------------------
+{
+ if (!mData)
+ return;
+ ReallocData(mData->mLength);
+ if (!mData)
+ return;
+ nsUnescape(mData->mString);
+ mData->mLength = strlen(mData->mString);
+} // nsSimpleCharString::Unescape
+
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::AddRefData()
+//----------------------------------------------------------------------------------------
+{
+ if (mData)
+ ++mData->mRefCount;
+} // nsSimpleCharString::AddRefData
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::ReleaseData()
+//----------------------------------------------------------------------------------------
+{
+ if (!mData)
+ return;
+ NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
+ if (--mData->mRefCount == 0)
+ PR_Free(mData);
+ mData = nsnull;
+} // nsSimpleCharString::ReleaseData
+
+//----------------------------------------------------------------------------------------
+inline PRUint32 CalculateAllocLength(PRUint32 logicalLength)
+// Round up to the next multiple of 256.
+//----------------------------------------------------------------------------------------
+{
+ return ((1 + (logicalLength >> 8)) << 8);
+}
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::ReallocData(PRUint32 inLength)
+// Reallocate mData to a new length. Since this presumably precedes a change to the string,
+// we want to detach ourselves if the data is shared by another string, even if the length
+// requested would not otherwise require a reallocation.
+//----------------------------------------------------------------------------------------
+{
+ PRUint32 newAllocLength = CalculateAllocLength(inLength);
+ PRUint32 oldAllocLength = CalculateAllocLength(Length());
+ if (mData)
+ {
+ NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
+ if (mData->mRefCount == 1)
+ {
+ // We are the sole owner, so just change its length, if necessary.
+ if (newAllocLength > oldAllocLength)
+ mData = (Data*)PR_Realloc(mData, newAllocLength + sizeof(Data));
+ mData->mLength = inLength;
+ mData->mString[inLength] = '\0'; // we may be truncating
+ return;
+ }
+ }
+ PRUint32 copyLength = Length();
+ if (inLength < copyLength)
+ copyLength = inLength;
+ Data* newData = (Data*)PR_Malloc(newAllocLength + sizeof(Data));
+ // If data was already allocated when we get to here, then we are cloning the data
+ // from a shared pointer.
+ if (mData)
+ {
+ memcpy(newData, mData, sizeof(Data) + copyLength);
+ mData->mRefCount--; // Say goodbye
+ }
+ else
+ newData->mString[0] = '\0';
+
+ mData = newData;
+ mData->mRefCount = 1;
+ mData->mLength = inLength;
+} // nsSimpleCharString::ReleaseData
+
+
+//========================================================================================
+NS_NAMESPACE nsFileSpecHelpers
+//========================================================================================
+{
+ enum
+ { kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
+ , kMaxAltDigitLength = 5
+ , kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
+ };
+#if !defined(XP_MAC)
+ NS_NAMESPACE_PROTOTYPE void Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs);
+ NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
+#endif
+#if defined(XP_WIN) || defined(XP_OS2)
+ NS_NAMESPACE_PROTOTYPE void NativeToUnix(nsSimpleCharString& ioPath);
+ NS_NAMESPACE_PROTOTYPE void UnixToNative(nsSimpleCharString& ioPath);
+#endif
+} NS_NAMESPACE_END
+
+//----------------------------------------------------------------------------------------
+nsresult ns_file_convert_result(PRInt32 nativeErr)
+//----------------------------------------------------------------------------------------
+{
+ return nativeErr ?
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
+ : NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::LeafReplace(char inSeparator, const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ // Find the existing leaf name
+ if (IsEmpty())
+ return;
+ if (!inLeafName)
+ {
+ SetToEmpty();
+ return;
+ }
+ char* chars = mData->mString;
+ char* lastSeparator = GetLastSeparator(chars, inSeparator);
+ int oldLength = Length();
+ PRBool trailingSeparator = (lastSeparator + 1 == chars + oldLength);
+ if (trailingSeparator)
+ {
+ char savedCh = *lastSeparator;
+ char *savedLastSeparator = lastSeparator;
+ *lastSeparator = '\0';
+ lastSeparator = GetLastSeparator(chars, inSeparator);
+ *savedLastSeparator = savedCh;
+ }
+ if (lastSeparator)
+ lastSeparator++; // point at the trailing string
+ else
+ lastSeparator = chars; // the full monty
+
+ PRUint32 savedLastSeparatorOffset = (lastSeparator - chars);
+ int newLength =
+ (lastSeparator - chars) + strlen(inLeafName) + (trailingSeparator != 0);
+ ReallocData(newLength);
+
+ chars = mData->mString; // it might have moved.
+ chars[savedLastSeparatorOffset] = '\0'; // strip the current leaf name
+
+ strcat(chars, inLeafName);
+ if (trailingSeparator)
+ {
+ // If the original ended in a slash, then the new one should, too.
+ char sepStr[2] = "/";
+ *sepStr = inSeparator;
+ strcat(chars, sepStr);
+ }
+} // nsSimpleCharString::LeafReplace
+
+//----------------------------------------------------------------------------------------
+char* nsSimpleCharString::GetLeaf(char inSeparator) const
+// Returns a pointer to an allocated string representing the leaf.
+//----------------------------------------------------------------------------------------
+{
+ if (IsEmpty())
+ return nsnull;
+
+ char* chars = mData->mString;
+ const char* lastSeparator = GetLastSeparator(chars, inSeparator);
+ // If there was no separator, then return a copy of our path.
+ if (!lastSeparator)
+ return nsCRT::strdup(*this);
+
+ // So there's at least one separator. What's just after it?
+ // If the separator was not the last character, return the trailing string.
+ const char* leafPointer = lastSeparator + 1;
+ if (*leafPointer)
+ return nsCRT::strdup(leafPointer);
+
+ // So now, separator was the last character. Poke in a null instead.
+ *(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler.
+ leafPointer = GetLastSeparator(chars, inSeparator);
+ char* result = leafPointer ? nsCRT::strdup(++leafPointer) : nsCRT::strdup(chars);
+ // Restore the poked null before returning.
+ *(char*)lastSeparator = inSeparator;
+#if defined(XP_WIN) || defined(XP_OS2)
+ // If it's a drive letter use the colon notation.
+ if (!leafPointer && result[1] == '|' && result[2] == 0)
+ result[1] = ':';
+#endif
+ return result;
+} // nsSimpleCharString::GetLeaf
+
+
+#if 0
+#pragma mark -
+#endif
+
+#if (defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS))
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
+// Make the path a valid one by creating all the intermediate directories. Does NOT
+// make the leaf into a directory. This should be a unix path.
+//----------------------------------------------------------------------------------------
+{
+ if (!inPath)
+ return;
+
+ char* pathCopy = nsCRT::strdup( inPath );
+ if (!pathCopy)
+ return;
+
+ const char kSeparator = '/'; // I repeat: this should be a unix-style path.
+ const int kSkipFirst = 1;
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ // Either this is a relative path, or we ensure that it has
+ // a drive letter specifier.
+ NS_ASSERTION( pathCopy[0] != '/' || (pathCopy[1] && (pathCopy[2] == '|' || pathCopy[2] == '/')),
+ "Not a UNC path and no drive letter!" );
+#endif
+ char* currentStart = pathCopy;
+ char* currentEnd = strchr(currentStart + kSkipFirst, kSeparator);
+ if (currentEnd)
+ {
+ nsFileSpec spec;
+ *currentEnd = '\0';
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ /*
+ if we have a drive letter path, we must make sure that the inital path has a '/' on it, or
+ Canonify will turn "/c|" into a path relative to the running executable.
+ */
+ if (pathCopy[0] == '/' && pathCopy[1] && pathCopy[2] == '|')
+ {
+ char* startDir = (char*)PR_Malloc(strlen(pathCopy) + 2);
+ strcpy(startDir, pathCopy);
+ strcat(startDir, "/");
+
+ spec = nsFilePath(startDir, PR_FALSE);
+
+ PR_Free(startDir);
+ }
+ else
+ {
+ // move after server name and share name in UNC path
+ if (pathCopy[0] == '/' &&
+ currentEnd == currentStart+kSkipFirst)
+ {
+ *currentEnd = '/';
+ currentStart = strchr(pathCopy+2, kSeparator);
+ currentStart = strchr(currentStart+1, kSeparator);
+ currentEnd = strchr(currentStart+1, kSeparator);
+ if (currentEnd)
+ *currentEnd = '\0';
+ }
+ spec = nsFilePath(pathCopy, PR_FALSE);
+ }
+#else
+ spec = nsFilePath(pathCopy, PR_FALSE);
+#endif
+ do
+ {
+ // If the node doesn't exist, and it is not the initial node in a full path,
+ // then make a directory (We cannot make the initial (volume) node).
+ if (!spec.Exists() && *currentStart != kSeparator)
+ spec.CreateDirectory(mode);
+
+ currentStart = ++currentEnd;
+ currentEnd = strchr(currentStart, kSeparator);
+ if (!currentEnd)
+ break;
+
+ *currentEnd = '\0';
+
+ spec += currentStart; // "lengthen" the path, adding the next node.
+ } while (currentEnd);
+ }
+ nsCRT::free(pathCopy);
+} // nsFileSpecHelpers::MakeAllDirectories
+
+#endif // XP_UNIX || XP_WIN || XP_OS2 || XP_BEOS
+
+#if 0
+#pragma mark -
+#endif
+
+#if defined(XP_WIN)
+#include "nsFileSpecWin.cpp" // Windows-specific implementations
+#elif defined(XP_MAC)
+//#include "nsFileSpecMac.cpp" // Macintosh-specific implementations
+// we include the .cpp file in the project now.
+#elif defined(XP_BEOS)
+#include "nsFileSpecBeOS.cpp" // BeOS-specific implementations
+#elif defined(XP_UNIX) || defined(XP_MACOSX)
+#include "nsFileSpecUnix.cpp" // Unix-specific implementations
+#elif defined(XP_OS2)
+#include "nsFileSpecOS2.cpp" // OS/2-specific implementations
+#endif
+
+//========================================================================================
+// nsFileURL implementation
+//========================================================================================
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ if (!inString)
+ return;
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+ // Make canonical and absolute. Since it's a parameter to this constructor,
+ // inString is escaped. We want to make an nsFilePath, which requires
+ // an unescaped string.
+ nsSimpleCharString unescapedPath(inString + kFileURLPrefixLength);
+ unescapedPath.Unescape();
+ nsFilePath path(unescapedPath, inCreateDirs);
+ *this = path;
+} // nsFileURL::nsFileURL
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ NS_LossyConvertUCS2toASCII cstring(inString);
+ if (!inString.Length())
+ return;
+ NS_ASSERTION(strstr(cstring.get(), kFileURLPrefix) == cstring.get(),
+ "Not a URL!");
+ // Make canonical and absolute. Since it's a parameter to this constructor,
+ // inString is escaped. We want to make an nsFilePath, which requires
+ // an unescaped string.
+ nsSimpleCharString unescapedPath(cstring.get() + kFileURLPrefixLength);
+ unescapedPath.Unescape();
+ nsFilePath path(unescapedPath, inCreateDirs);
+ *this = path;
+} // nsFileURL::nsFileURL
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+: mURL(inOther.mURL)
+#if defined(XP_MAC)
+, mFileSpec(inOther.GetFileSpec())
+#endif
+{
+} // nsFileURL::nsFileURL
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+} // nsFileURL::nsFileURL
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+} // nsFileURL::nsFileURL
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileURL::~nsFileURL()
+//----------------------------------------------------------------------------------------
+{
+}
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ // XXX is this called by nsFileSpecImpl.cpp::SetURLString?
+ // if so, there's a bug...
+
+ mURL = inString;
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+} // nsFileURL::operator =
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator +=(const char* inRelativeUnixPath)
+//----------------------------------------------------------------------------------------
+{
+ char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
+ mURL += escapedPath;
+ nsCRT::free(escapedPath);
+#if defined(XP_MAC)
+ mFileSpec += inRelativeUnixPath;
+#endif
+} // nsFileURL::operator +=
+
+//----------------------------------------------------------------------------------------
+nsFileURL nsFileURL::operator +(const char* inRelativeUnixPath) const
+//----------------------------------------------------------------------------------------
+{
+ nsFileURL result(*this);
+ result += inRelativeUnixPath;
+ return result;
+} // nsFileURL::operator +
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mURL = inOther.mURL;
+#if defined(XP_MAC)
+ mFileSpec = inOther.GetFileSpec();
+#endif
+} // nsFileURL::operator =
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mURL = kFileURLPrefix;
+ char* original = (char*)(const char*)inOther; // we shall modify, but restore.
+ if (!original || !*original) return;
+#if defined(XP_WIN) || defined(XP_OS2)
+ // because we don't want to escape the '|' character, change it to a letter.
+ // Note that a UNC path will not have a '|' character.
+ char oldchar = original[2];
+ original[2] = 'x';
+ char* escapedPath = nsEscape(original, url_Path);
+ original[2] = escapedPath[2] = oldchar; // restore it
+#else
+ char* escapedPath = nsEscape(original, url_Path);
+#endif
+ if (escapedPath)
+ mURL += escapedPath;
+ nsCRT::free(escapedPath);
+} // nsFileURL::operator =
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = nsFilePath(inOther);
+ if (mURL[mURL.Length() - 1] != '/' && inOther.IsDirectory())
+ mURL += "/";
+} // nsFileURL::operator =
+#endif
+
+#if 0
+#pragma mark -
+#endif
+
+//========================================================================================
+// nsFilePath implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+ : mPath(inPath.mPath)
+#if defined(XP_MAC)
+ , mFileSpec(inPath.mFileSpec)
+#endif
+{
+}
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+{
+ if (mPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::UnixToNative(mPath);
+#endif
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+#if defined(XP_WIN) || defined(XP_OS2)
+ // Assert native path is of one of these forms:
+ // - regular: X:\some\path
+ // - UNC: \\some_machine\some\path
+ NS_ASSERTION( mPath[1] == ':' || (mPath[0] == '\\' && mPath[1] == '\\'),
+ "unexpected canonical path" );
+ nsFileSpecHelpers::NativeToUnix(mPath);
+#endif
+}
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+{
+ if (mPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strstr((const char*)mPath, kFileURLPrefix) != (const char*)mPath, "URL passed as path");
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::UnixToNative(mPath);
+#endif
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+#if defined(XP_WIN) || defined(XP_OS2)
+ NS_ASSERTION( mPath[1] == ':' || (mPath[0] == '\\' && mPath[1] == '\\'),
+ "unexpected canonical path" );
+ nsFileSpecHelpers::NativeToUnix(mPath);
+#endif
+}
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inOther.mURL + kFileURLPrefixLength;
+ mPath.Unescape();
+}
+#endif
+
+#if (defined XP_UNIX || defined XP_BEOS)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+: mPath(inOther.mPath)
+{
+}
+#endif // XP_UNIX
+
+//----------------------------------------------------------------------------------------
+nsFilePath::~nsFilePath()
+//----------------------------------------------------------------------------------------
+{
+}
+
+#if (defined XP_UNIX || defined XP_BEOS)
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ // XXX bug here, again if.
+
+ mPath = inOther.mPath;
+}
+#endif // XP_UNIX
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
+ mPath = inString;
+ if (mPath.IsEmpty())
+ return;
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::UnixToNative(mPath);
+#endif
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::NativeToUnix(mPath);
+#endif
+}
+#endif // XP_MAC
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)nsFilePath(inOther);
+}
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inOther.mPath;
+#if defined(XP_MAC)
+ mFileSpec = inOther.GetFileSpec();
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator +=(const char* inRelativeUnixPath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
+
+ char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
+ mPath += escapedPath;
+ nsCRT::free(escapedPath);
+#if defined(XP_MAC)
+ mFileSpec += inRelativeUnixPath;
+#endif
+} // nsFilePath::operator +=
+
+//----------------------------------------------------------------------------------------
+nsFilePath nsFilePath::operator +(const char* inRelativeUnixPath) const
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
+
+ nsFilePath resultPath(*this);
+ resultPath += inRelativeUnixPath;
+ return resultPath;
+} // nsFilePath::operator +
+
+
+#if 0
+#pragma mark -
+#endif
+
+//========================================================================================
+// nsFileSpec implementation
+//========================================================================================
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec()
+//----------------------------------------------------------------------------------------
+: mError(NS_OK) // XXX shouldn't this be NS_ERROR_NOT_INITIALIZED?
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Clear()
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mError = NS_ERROR_NOT_INITIALIZED;
+}
+
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::~nsFileSpec()
+//----------------------------------------------------------------------------------------
+{
+ // mPath cleans itself up
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
+//----------------------------------------------------------------------------------------
+{
+ *this = inDescriptor;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFileURL& inURL)
+//----------------------------------------------------------------------------------------
+{
+ *this = nsFilePath(inURL); // convert to unix path first
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
+//----------------------------------------------------------------------------------------
+{
+ if (inSuggestedLeafName && *inSuggestedLeafName)
+ SetLeafName(inSuggestedLeafName);
+
+ MakeUnique();
+} // nsFileSpec::MakeUnique
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeUnique()
+//----------------------------------------------------------------------------------------
+{
+ if (!Exists())
+ return;
+
+ char* leafName = GetLeafName();
+ if (!leafName)
+ return;
+
+ char* lastDot = strrchr(leafName, '.');
+ char* suffix = "";
+ if (lastDot)
+ {
+ suffix = nsCRT::strdup(lastDot); // include '.'
+ *lastDot = '\0'; // strip suffix and dot.
+ }
+ const int kMaxRootLength
+ = nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
+ if ((int)strlen(leafName) > (int)kMaxRootLength)
+ leafName[kMaxRootLength] = '\0';
+ for (short indx = 1; indx < 1000 && Exists(); indx++)
+ {
+ // start with "Picture-1.jpg" after "Picture.jpg" exists
+ char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
+ sprintf(newName, "%s-%d%s", leafName, indx, suffix);
+ SetLeafName(newName);
+ }
+ if (*suffix)
+ nsCRT::free(suffix);
+ nsCRT::free(leafName);
+} // nsFileSpec::MakeUnique
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFileURL& inURL)
+//----------------------------------------------------------------------------------------
+{
+ *this = nsFilePath(inURL); // convert to unix path first
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
+//----------------------------------------------------------------------------------------
+{
+
+ nsCAutoString data;
+ inDescriptor.GetData(data);
+
+#if defined (XP_MAC) || defined(XP_MACOSX)
+ // Decode descriptor into a Handle (which is actually an AliasHandle)
+ char* decodedData = PL_Base64Decode(data.get(), data.Length(), nsnull);
+ Handle aliasH = nsnull;
+ mError = NS_FILE_RESULT(::PtrToHand(decodedData, &aliasH, (data.Length() * 3) / 4));
+ PR_Free(decodedData);
+ if (NS_FAILED(mError))
+ return; // not enough memory?
+#endif
+
+#if defined(XP_MAC)
+ Boolean changed;
+ mError = NS_FILE_RESULT(::ResolveAlias(nsnull, (AliasHandle)aliasH, &mSpec, &changed));
+ DisposeHandle((Handle) aliasH);
+ mPath.SetToEmpty();
+#elif defined(XP_MACOSX)
+ Boolean changed;
+ FSRef fileRef;
+ mError = NS_FILE_RESULT(::FSResolveAlias(nsnull, (AliasHandle)aliasH, &fileRef, &changed));
+ ::DisposeHandle(aliasH);
+
+ UInt8 pathBuf[PATH_MAX];
+ mError = NS_FILE_RESULT(::FSRefMakePath(&fileRef, pathBuf, PATH_MAX));
+ if (NS_FAILED(mError))
+ return;
+ mPath = (const char*)pathBuf;
+#else
+ mPath = data.get();
+ mError = NS_OK;
+#endif
+}
+
+//========================================================================================
+// UNIX & WIN nsFileSpec implementation
+//========================================================================================
+
+#if (defined XP_UNIX || defined XP_BEOS)
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+: mPath((const char*)inPath)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inPath;
+ mError = NS_OK;
+}
+#endif //XP_UNIX
+
+#if (defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS))
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+: mPath(inSpec.mPath)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inSpec.mPath;
+ mError = inSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inString;
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
+ mError = NS_OK;
+}
+#endif //XP_UNIX,XP_WIN,XP_OS2,XP_BEOS
+
+//----------------------------------------------------------------------------------------
+nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to append name with a null string");
+
+ nsFileSpec resultSpec = *this;
+ resultSpec += inRelativePath;
+ return resultSpec;
+} // nsFileSpec::operator +
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const
+//----------------------------------------------------------------------------------------
+{
+
+#if defined(XP_MAC)
+ if ( inOther.mSpec.vRefNum == mSpec.vRefNum &&
+ inOther.mSpec.parID == mSpec.parID &&
+ EqualString(inOther.mSpec.name, mSpec.name, false, true))
+ return PR_TRUE;
+#else
+ PRBool amEmpty = mPath.IsEmpty();
+ PRBool heEmpty = inOther.mPath.IsEmpty();
+ if (amEmpty) // we're the same if he's empty...
+ return heEmpty;
+ if (heEmpty) // ('cuz I'm not...)
+ return PR_FALSE;
+
+ nsSimpleCharString str = mPath;
+ nsSimpleCharString inStr = inOther.mPath;
+
+ // Length() is size of buffer, not length of string
+ PRUint32 strLast = str.Length() - 1, inLast = inStr.Length() - 1;
+#if defined(XP_WIN) || defined(XP_OS2)
+#define DIR_SEPARATOR '\\' // XXX doesn't NSPR have this?
+ /* windows does not care about case. */
+#ifdef XP_OS2
+#define DIR_STRCMP strcmp
+#else
+#define DIR_STRCMP _stricmp
+#endif
+#else
+#define DIR_SEPARATOR '/'
+#if defined(VMS)
+#define DIR_STRCMP strcasecmp
+#else
+#define DIR_STRCMP strcmp
+#endif
+#endif
+
+ if(str[strLast] == DIR_SEPARATOR)
+ str[strLast] = '\0';
+
+ if(inStr[inLast] == DIR_SEPARATOR)
+ inStr[inLast] = '\0';
+
+ if (DIR_STRCMP(str, inStr ) == 0)
+ return PR_TRUE;
+#undef DIR_SEPARATOR
+#undef DIR_STRCMP
+#endif
+ return PR_FALSE;
+}
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const
+//----------------------------------------------------------------------------------------
+{
+ return (! (*this == inOther) );
+}
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+// This is the only automatic conversion to const char*
+// that is provided, and it allows the
+// path to be "passed" to NSPR file routines. This practice
+// is VERY EVIL and should only be used to support legacy
+// code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do
+// not even think of deleting (or freeing) it.
+const char* nsFileSpec::GetCString() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath;
+}
+#endif
+
+//----------------------------------------------------------------------------------------
+// Is our spec a child of the provided parent?
+PRBool nsFileSpec::IsChildOf(nsFileSpec &possibleParent)
+//----------------------------------------------------------------------------------------
+{
+ nsFileSpec iter = *this, parent;
+#ifdef DEBUG
+ int depth = 0;
+#endif
+ while (1) {
+#ifdef DEBUG
+ // sanity
+ NS_ASSERTION(depth < 100, "IsChildOf has lost its little mind");
+ if (depth > 100)
+ return PR_FALSE;
+#endif
+ if (iter == possibleParent)
+ return PR_TRUE;
+
+ iter.GetParent(parent); // shouldn't this be an error on parent?
+ if (iter.Failed())
+ return PR_FALSE;
+
+ if (iter == parent) // hit bottom
+ return PR_FALSE;
+
+ iter = parent;
+#ifdef DEBUG
+ depth++;
+#endif
+ }
+
+ // not reached, but I bet some compiler will whine
+ return PR_FALSE;
+}
+
+#if 0
+#pragma mark -
+#endif
+
+//========================================================================================
+// class nsPersistentFileDescriptor
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
+//----------------------------------------------------------------------------------------
+ : mDescriptorString(inDesc.mDescriptorString)
+{
+} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
+//----------------------------------------------------------------------------------------
+{
+ mDescriptorString = inDesc.mDescriptorString;
+} // nsPersistentFileDescriptor::operator =
+
+//----------------------------------------------------------------------------------------
+nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_MAC)
+ if (inSpec.Error())
+ return;
+ AliasHandle aliasH;
+ OSErr err = NewAlias(nil, inSpec.GetFSSpecPtr(), &aliasH);
+ if (err != noErr)
+ return;
+
+ PRUint32 bytes = GetHandleSize((Handle) aliasH);
+ HLock((Handle) aliasH);
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
+ DisposeHandle((Handle) aliasH);
+
+ mDescriptorString = buf;
+ PR_Free(buf);
+#elif defined(XP_MACOSX)
+ if (inSpec.Error())
+ return;
+
+ FSRef fileRef;
+ Boolean isDir;
+ OSErr err = ::FSPathMakeRef((const UInt8*)inSpec.GetCString(), &fileRef, &isDir);
+ if (err != noErr)
+ return;
+
+ AliasHandle aliasH;
+ err = ::FSNewAlias(nsnull, &fileRef, &aliasH);
+ if (err != noErr)
+ return;
+
+ PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
+ ::HLock((Handle)aliasH);
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
+ ::DisposeHandle((Handle) aliasH);
+
+ mDescriptorString = buf;
+ PR_Free(buf);
+#else
+ mDescriptorString = inSpec.GetCString();
+#endif // XP_MAC
+} // nsPersistentFileDescriptor::operator =
+
+//----------------------------------------------------------------------------------------
+nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
+//----------------------------------------------------------------------------------------
+{
+} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::GetData(nsAFlatCString& outData) const
+//----------------------------------------------------------------------------------------
+{
+ outData.Assign(mDescriptorString, mDescriptorString.Length());
+}
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::SetData(const nsAFlatCString& inData)
+//----------------------------------------------------------------------------------------
+{
+ mDescriptorString.CopyFrom(inData.get(), inData.Length());
+}
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::SetData(const char* inData, PRInt32 inSize)
+//----------------------------------------------------------------------------------------
+{
+ mDescriptorString.CopyFrom(inData, inSize);
+}
+
+//========================================================================================
+// class nsNSPRPath
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsNSPRPath::operator const char*() const
+// NSPR expects a UNIX path on unix and Macintosh, but a native path on windows. NSPR
+// cannot be changed, so we have to do the dirty work.
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ if (!modifiedNSPRPath)
+ {
+ // If this is the first call, initialize modifiedNSPRPath. Start by cloning
+ // mFilePath, but strip the leading separator, if present
+ const char* unixPath = (const char*)mFilePath;
+ if (!unixPath)
+ return nsnull;
+
+ ((nsNSPRPath*)this)->modifiedNSPRPath
+ = nsCRT::strdup(*unixPath == '/' ? unixPath + 1: unixPath);
+
+ // Replace the bar
+ if (modifiedNSPRPath[1] == '|')
+ modifiedNSPRPath[1] = ':';
+
+ // Remove the ending separator only if it is not the last separator
+ int len = strlen(modifiedNSPRPath);
+ if (modifiedNSPRPath[len - 1 ] == '/' && modifiedNSPRPath[len - 2 ] != ':')
+ modifiedNSPRPath[len - 1 ] = '\0';
+ }
+ return modifiedNSPRPath;
+#else
+ return (const char*)mFilePath;
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+nsNSPRPath::~nsNSPRPath()
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ if (modifiedNSPRPath)
+ nsCRT::free(modifiedNSPRPath);
+#endif
+}
+
+
+nsresult
+NS_FileSpecToIFile(nsFileSpec* fileSpec, nsILocalFile* *result)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!file) return NS_ERROR_FAILURE;
+
+#if defined(XP_MAC)
+ {
+ FSSpec spec = fileSpec->GetFSSpec();
+ nsCOMPtr<nsILocalFileMac> psmAppMacFile = do_QueryInterface(file, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = psmAppMacFile->InitWithFSSpec(&spec);
+ if (NS_FAILED(rv)) return rv;
+ file = do_QueryInterface(psmAppMacFile, &rv);
+ }
+#else
+ // XP_MACOSX: do this for OS X to preserve long filenames
+ rv = file->InitWithNativePath(nsDependentCString(fileSpec->GetNativePathCString()));
+#endif
+ if (NS_FAILED(rv)) return rv;
+
+ *result = file;
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h
new file mode 100644
index 00000000..53fa6c1a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h
@@ -0,0 +1,782 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ THESE CLASSES ARE DEPRECATED AND UNSUPPORTED! USE |nsIFile| and |nsILocalFile|.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+
+
+
+
+
+
+
+
+// First checked in on 98/11/20 by John R. McMullen in the wrong directory.
+// Checked in again 98/12/04.
+// Polished version 98/12/08.
+
+//========================================================================================
+//
+// Classes defined:
+//
+// nsFilePath, nsFileURL, nsFileSpec, nsPersistentFileDescriptor
+// nsDirectoryIterator.
+//
+// Q. How should I represent files at run time?
+// A. Use nsFileSpec. Using char* will lose information on some platforms.
+//
+// Q. Then what are nsFilePath and nsFileURL for?
+// A. Only when you need a char* parameter for legacy code.
+//
+// Q. How should I represent files in a persistent way (eg, in a disk file)?
+// A. Use nsPersistentFileDescriptor. Convert to and from nsFileSpec at run time.
+//
+// This suite provides the following services:
+//
+// 1. Encapsulates all platform-specific file details, so that files can be
+// described correctly without any platform #ifdefs
+//
+// 2. Type safety. This will fix the problems that used to occur because people
+// confused file paths. They used to use const char*, which could mean three
+// or four different things. Bugs were introduced as people coded, right up
+// to the moment Communicator 4.5 shipped.
+//
+// 3. Used in conjunction with nsFileStream.h (q.v.), this supports all the power
+// and readability of the ansi stream syntax.
+//
+// Basic example:
+//
+// nsFilePath myPath("/Development/iotest.txt");
+//
+// nsOutputFileStream testStream(nsFileSpec(myPath));
+// testStream << "Hello World" << nsEndl;
+//
+// 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(),
+// SetLeafName(), Exists().
+//
+// 5. Easy cross-conversion.
+//
+// Examples:
+//
+// Initialize a URL from a string
+//
+// nsFileURL fileURL("file:///Development/MPW/MPW%20Shell");
+//
+// Initialize a Unix-style path from a URL
+//
+// nsFilePath filePath(fileURL);
+//
+// Initialize a file spec from a URL
+//
+// nsFileSpec fileSpec(fileURL);
+//
+// Make the spec unique.
+//
+// fileSpec.MakeUnique();
+//
+// Assign the spec to a URL (causing conversion)
+//
+// fileURL = fileSpec;
+//
+// Assign a unix path using a string
+//
+// filePath = "/Development/MPW/SysErrs.err";
+//
+// Assign to a file spec using a unix path (causing conversion).
+//
+// fileSpec = filePath;
+//
+// Make this unique.
+//
+// fileSpec.MakeUnique();
+//
+// 6. Fixes a bug that have been there for a long time, and
+// is inevitable if you use NSPR alone, where files are described as paths.
+//
+// The problem affects platforms (Macintosh) in which a path does not fully
+// specify a file, because two volumes can have the same name. This
+// is solved by holding a "private" native file spec inside the
+// nsFilePath and nsFileURL classes, which is used when appropriate.
+//
+//========================================================================================
+
+#ifndef _FILESPEC_H_
+#define _FILESPEC_H_
+
+#include "xpcomobsolete.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "prtypes.h"
+
+//========================================================================================
+// Compiler-specific macros, as needed
+//========================================================================================
+#if !defined(NS_USING_NAMESPACE) && (defined(__MWERKS__) || defined(_MSC_VER))
+#define NS_USING_NAMESPACE
+#endif
+
+#ifdef NS_USING_NAMESPACE
+
+#define NS_NAMESPACE_PROTOTYPE
+#define NS_NAMESPACE namespace
+#define NS_NAMESPACE_END
+#define NS_EXPLICIT explicit
+#else
+
+#define NS_NAMESPACE_PROTOTYPE static
+#define NS_NAMESPACE struct
+#define NS_NAMESPACE_END ;
+#define NS_EXPLICIT
+
+#endif
+//=========================== End Compiler-specific macros ===============================
+
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+
+#if defined(XP_MAC)
+#include <Files.h>
+#include "nsILocalFileMac.h"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+#include <dirent.h>
+#elif defined(XP_WIN)
+
+// This clashes with some of the Win32 system headers (specifically,
+// winbase.h). Hopefully they'll have been included first; else we may
+// have problems. We could include winbase.h before doing this;
+// unfortunately, it's bring in too much crap and'd slow stuff down
+// more than it's worth doing.
+#ifdef CreateDirectory
+#undef CreateDirectory
+#endif
+
+#include "prio.h"
+#elif defined(XP_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#define INCL_GPI
+#include <os2.h>
+#include "prio.h"
+#endif
+
+//========================================================================================
+// Here are the allowable ways to describe a file.
+//========================================================================================
+
+class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream
+class nsFilePath;
+class nsFileURL;
+class nsNSPRPath; // This can be passed to NSPR file I/O routines, if you must.
+class nsPersistentFileDescriptor; // Used for storage across program launches.
+
+#define kFileURLPrefix "file://"
+#define kFileURLPrefixLength (7)
+
+class nsOutputStream;
+class nsInputStream;
+class nsIOutputStream;
+class nsIInputStream;
+class nsOutputFileStream;
+class nsInputFileStream;
+class nsOutputConsoleStream;
+
+class nsIUnicodeEncoder;
+class nsIUnicodeDecoder;
+
+//========================================================================================
+// Conversion of native file errors to nsresult values. These are really only for use
+// in the file module, clients of this interface shouldn't really need them.
+// Error results returned from this interface have, in the low-order 16 bits,
+// native errors that are masked to 16 bits. Assumption: a native error of 0 is success
+// on all platforms. Note the way we define this using an inline function. This
+// avoids multiple evaluation if people go NS_FILE_RESULT(function_call()).
+#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
+nsresult ns_file_convert_result(PRInt32 nativeErr);
+#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
+
+//========================================================================================
+class nsSimpleCharString
+// An envelope for char*: reference counted. Used internally by all the nsFileSpec
+// classes below.
+//========================================================================================
+{
+public:
+ nsSimpleCharString();
+ nsSimpleCharString(const char*);
+ nsSimpleCharString(const nsString&);
+ nsSimpleCharString(const nsSimpleCharString&);
+ nsSimpleCharString(const char* inData, PRUint32 inLength);
+
+ ~nsSimpleCharString();
+
+ void operator = (const char*);
+ void operator = (const nsString&);
+ void operator = (const nsSimpleCharString&);
+
+ operator const char*() const { return mData ? mData->mString : 0; }
+ operator char* ()
+ {
+ ReallocData(Length()); // requires detaching if shared...
+ return mData ? mData->mString : 0;
+ }
+ PRBool operator == (const char*);
+ PRBool operator == (const nsString&);
+ PRBool operator == (const nsSimpleCharString&);
+
+ void operator += (const char* inString);
+ nsSimpleCharString operator + (const char* inString) const;
+
+ char operator [](int i) const { return mData ? mData->mString[i] : '\0'; }
+ char& operator [](int i)
+ {
+ if (i >= (int)Length())
+ ReallocData((PRUint32)i + 1);
+ return mData->mString[i]; // caveat appelator
+ }
+ char& operator [](unsigned int i) { return (*this)[(int)i]; }
+
+ void Catenate(const char* inString1, const char* inString2);
+
+ void SetToEmpty();
+ PRBool IsEmpty() const { return Length() == 0; }
+
+ PRUint32 Length() const { return mData ? mData->mLength : 0; }
+ void SetLength(PRUint32 inLength) { ReallocData(inLength); }
+ void CopyFrom(const char* inData, PRUint32 inLength);
+ void LeafReplace(char inSeparator, const char* inLeafName);
+ char* GetLeaf(char inSeparator) const; // use PR_Free()
+ void Unescape();
+
+protected:
+
+ void AddRefData();
+ void ReleaseData();
+ void ReallocData(PRUint32 inLength);
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+protected:
+
+ struct Data {
+ int mRefCount;
+ PRUint32 mLength;
+ char mString[1];
+ };
+ Data* mData;
+}; // class nsSimpleCharString
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileSpec
+// This is whatever each platform really prefers to describe files as. Declared first
+// because the other two types have an embedded nsFileSpec object.
+//========================================================================================
+{
+ public:
+ nsFileSpec();
+
+ // These two meathods take *native* file paths.
+ NS_EXPLICIT nsFileSpec(const char* inNativePath, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFileSpec(const nsString& inNativePath, PRBool inCreateDirs = PR_FALSE);
+
+
+ NS_EXPLICIT nsFileSpec(const nsFilePath& inPath);
+ NS_EXPLICIT nsFileSpec(const nsFileURL& inURL);
+ nsFileSpec(const nsFileSpec& inPath);
+ virtual ~nsFileSpec();
+
+ // These two operands take *native* file paths.
+ void operator = (const char* inNativePath);
+
+ void operator = (const nsFilePath& inPath);
+ void operator = (const nsFileURL& inURL);
+ void operator = (const nsFileSpec& inOther);
+ void operator = (const nsPersistentFileDescriptor& inOther);
+
+ PRBool operator ==(const nsFileSpec& inOther) const;
+ PRBool operator !=(const nsFileSpec& inOther) const;
+
+
+ // Returns a native path, and allows the
+ // path to be "passed" to legacy code. This practice
+ // is VERY EVIL and should only be used to support legacy
+ // code. Using it guarantees bugs on Macintosh.
+ // The path is cached and freed by the nsFileSpec destructor
+ // so do not delete (or free) it. See also nsNSPRPath below,
+ // if you really must pass a string to PR_OpenFile().
+ // Doing so will introduce two automatic bugs.
+ const char* GetCString() const;
+
+ // Same as GetCString (please read the comments).
+ // Do not try to free this!
+ operator const char* () const { return GetCString(); }
+
+ // Same as GetCString (please read the comments).
+ // Do not try to free this!
+ const char* GetNativePathCString() const { return GetCString(); }
+
+ PRBool IsChildOf(nsFileSpec &possibleParent);
+
+#if defined(XP_MAC)
+ // For Macintosh people, this is meant to be useful in its own right as a C++ version
+ // of the FSSpec struct.
+ nsFileSpec(
+ short vRefNum,
+ long parID,
+ ConstStr255Param name,
+ PRBool resolveAlias = PR_TRUE);
+
+ nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias = PR_TRUE);
+ void operator = (const FSSpec& inSpec);
+
+ operator FSSpec* () { return &mSpec; }
+ operator const FSSpec* const () { return &mSpec; }
+ operator FSSpec& () { return mSpec; }
+ operator const FSSpec& () const { return mSpec; }
+
+ const FSSpec& GetFSSpec() const { return mSpec; }
+ FSSpec& GetFSSpec() { return mSpec; }
+ ConstFSSpecPtr GetFSSpecPtr() const { return &mSpec; }
+ FSSpecPtr GetFSSpecPtr() { return &mSpec; }
+ void MakeAliasSafe();
+ void MakeUnique(ConstStr255Param inSuggestedLeafName);
+ StringPtr GetLeafPName() { return mSpec.name; }
+ ConstStr255Param GetLeafPName() const { return mSpec.name; }
+
+ OSErr GetCatInfo(CInfoPBRec& outInfo) const;
+
+ OSErr SetFileTypeAndCreator(OSType type, OSType creator);
+ OSErr GetFileTypeAndCreator(OSType* type, OSType* creator);
+
+#endif // end of Macintosh utility methods.
+
+ PRBool Valid() const { return NS_SUCCEEDED(Error()); }
+ nsresult Error() const
+ {
+#if !defined(XP_MAC)
+ if (mPath.IsEmpty() && NS_SUCCEEDED(mError))
+ ((nsFileSpec*)this)->mError = NS_ERROR_NOT_INITIALIZED;
+#endif
+ return mError;
+ }
+ PRBool Failed() const { return (PRBool)NS_FAILED(Error()); }
+
+ //--------------------------------------------------
+ // Queries and path algebra. These do not modify the disk.
+ //--------------------------------------------------
+
+ char* GetLeafName() const; // Allocated. Use nsCRT::free().
+ // inLeafName can be a relative path, so this allows
+ // one kind of concatenation of "paths".
+ void SetLeafName(const char* inLeafName);
+
+ // Return the filespec of the parent directory. Used
+ // in conjunction with GetLeafName(), this lets you
+ // parse a path into a list of node names. Beware,
+ // however, that the top node is still not a name,
+ // but a spec. Volumes on Macintosh can have identical
+ // names. Perhaps could be used for an operator --() ?
+ void GetParent(nsFileSpec& outSpec) const;
+
+
+ // ie nsFileSpec::TimeStamp. This is 32 bits now,
+ // but might change, eg, to a 64-bit class. So use the
+ // typedef, and use a streaming operator to convert
+ // to a string, so that your code won't break. It's
+ // none of your business what the number means. Don't
+ // rely on the implementation.
+ typedef PRUint32 TimeStamp;
+
+ // This will return different values on different
+ // platforms, even for the same file (eg, on a server).
+ // But if the platform is constant, it will increase after
+ // every file modification.
+ void GetModDate(TimeStamp& outStamp) const;
+
+ PRBool ModDateChanged(const TimeStamp& oldStamp) const
+ {
+ TimeStamp newStamp;
+ GetModDate(newStamp);
+ return newStamp != oldStamp;
+ }
+
+ PRUint32 GetFileSize() const;
+ PRInt64 GetDiskSpaceAvailable() const;
+
+ nsFileSpec operator + (const char* inRelativeUnixPath) const;
+
+ // Concatenate the relative path to this directory.
+ // Used for constructing the filespec of a descendant.
+ // This must be a directory for this to work. This differs
+ // from SetLeafName(), since the latter will work
+ // starting with a sibling of the directory and throws
+ // away its leaf information, whereas this one assumes
+ // this is a directory, and the relative path starts
+ // "below" this.
+ void operator += (const char* inRelativeUnixPath);
+
+
+ void MakeUnique();
+ void MakeUnique(const char* inSuggestedLeafName);
+
+
+ PRBool IsDirectory() const; // More stringent than Exists()
+ PRBool IsFile() const; // More stringent than Exists()
+ PRBool Exists() const;
+
+ PRBool IsHidden() const;
+
+ PRBool IsSymlink() const;
+
+ //--------------------------------------------------
+ // Creation and deletion of objects. These can modify the disk.
+ //--------------------------------------------------
+
+ // Called for the spec of an alias. Modifies the spec to
+ // point to the original. Sets mError.
+ nsresult ResolveSymlink(PRBool& wasSymlink);
+
+ void CreateDirectory(int mode = 0775 /* for unix */);
+ void CreateDir(int mode = 0775) { CreateDirectory(mode); }
+ // workaround for yet another VC++ bug with long identifiers.
+ void Delete(PRBool inRecursive) const;
+ nsresult Truncate(PRInt32 aNewLength) const;
+ void RecursiveCopy(nsFileSpec newDir) const;
+
+ nsresult Rename(const char* inNewName); // not const: gets updated
+ nsresult CopyToDir(const nsFileSpec& inNewParentDirectory) const;
+ nsresult MoveToDir(const nsFileSpec& inNewParentDirectory);
+ nsresult Execute(const char* args) const;
+
+ protected:
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ protected:
+
+ // Clear the nsFileSpec contents, resetting it
+ // to the uninitialized state;
+ void Clear();
+
+ friend class nsFilePath;
+ friend class nsFileURL;
+ friend class nsDirectoryIterator;
+#if defined(XP_MAC)
+ FSSpec mSpec;
+#endif
+ nsSimpleCharString mPath;
+ nsresult mError;
+
+private:
+ NS_EXPLICIT nsFileSpec(const nsPersistentFileDescriptor& inURL);
+
+}; // class nsFileSpec
+
+// FOR HISTORICAL REASONS:
+
+typedef nsFileSpec nsNativeFileSpec;
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileURL
+// This is an escaped string that looks like "file:///foo/bar/mumble%20fish". Since URLs
+// are the standard way of doing things in mozilla, this allows a string constructor,
+// which just stashes the string with no conversion.
+//========================================================================================
+{
+ public:
+ nsFileURL(const nsFileURL& inURL);
+ NS_EXPLICIT nsFileURL(const char* inURLString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFileURL(const nsString& inURLString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFileURL(const nsFilePath& inPath);
+ NS_EXPLICIT nsFileURL(const nsFileSpec& inPath);
+ virtual ~nsFileURL();
+
+// nsString GetString() const { return mPath; }
+ // may be needed for implementation reasons,
+ // but should not provide a conversion constructor.
+
+ void operator = (const nsFileURL& inURL);
+ void operator = (const char* inURLString);
+ void operator = (const nsString& inURLString)
+ {
+ *this = NS_LossyConvertUCS2toASCII(inURLString).get();
+ }
+ void operator = (const nsFilePath& inOther);
+ void operator = (const nsFileSpec& inOther);
+
+ void operator +=(const char* inRelativeUnixPath);
+ nsFileURL operator +(const char* inRelativeUnixPath) const;
+ operator const char* () const { return (const char*)mURL; } // deprecated.
+ const char* GetURLString() const { return (const char*)mURL; }
+ // Not allocated, so don't free it.
+ const char* GetAsString() const { return (const char*)mURL; }
+ // Not allocated, so don't free it.
+
+#if defined(XP_MAC)
+ // Accessor to allow quick assignment to a mFileSpec
+ const nsFileSpec& GetFileSpec() const { return mFileSpec; }
+#endif
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ protected:
+ friend class nsFilePath; // to allow construction of nsFilePath
+ nsSimpleCharString mURL;
+
+#if defined(XP_MAC)
+ // Since the path on the macintosh does not uniquely specify a file (volumes
+ // can have the same name), stash the secret nsFileSpec, too.
+ nsFileSpec mFileSpec;
+#endif
+}; // class nsFileURL
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFilePath
+// This is a string that looks like "/foo/bar/mumble fish". Same as nsFileURL, but
+// without the "file:// prefix", and NOT %20 ENCODED! Strings passed in must be
+// valid unix-style paths in this format.
+//========================================================================================
+{
+ public:
+ nsFilePath(const nsFilePath& inPath);
+ NS_EXPLICIT nsFilePath(const char* inUnixPathString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFilePath(const nsString& inUnixPathString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFilePath(const nsFileURL& inURL);
+ NS_EXPLICIT nsFilePath(const nsFileSpec& inPath);
+ virtual ~nsFilePath();
+
+
+ operator const char* () const { return mPath; }
+ // This will return a UNIX string. If you
+ // need a string that can be passed into
+ // NSPR, take a look at the nsNSPRPath class.
+
+ void operator = (const nsFilePath& inPath);
+ void operator = (const char* inUnixPathString);
+ void operator = (const nsString& inUnixPathString)
+ {
+ *this = NS_LossyConvertUCS2toASCII(inUnixPathString).get();
+ }
+ void operator = (const nsFileURL& inURL);
+ void operator = (const nsFileSpec& inOther);
+
+ void operator +=(const char* inRelativeUnixPath);
+ nsFilePath operator +(const char* inRelativeUnixPath) const;
+
+#if defined(XP_MAC)
+ public:
+ // Accessor to allow quick assignment to a mFileSpec
+ const nsFileSpec& GetFileSpec() const { return mFileSpec; }
+#endif
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ private:
+
+ nsSimpleCharString mPath;
+#if defined(XP_MAC)
+ // Since the path on the macintosh does not uniquely specify a file (volumes
+ // can have the same name), stash the secret nsFileSpec, too.
+ nsFileSpec mFileSpec;
+#endif
+}; // class nsFilePath
+
+//========================================================================================
+class nsPersistentFileDescriptor
+// To save information about a file's location in another file, initialize
+// one of these from your nsFileSpec, and then write this out to your output stream.
+// To retrieve the info, create one of these, read its value from an input stream.
+// and then make an nsFileSpec from it.
+//========================================================================================
+{
+ public:
+ nsPersistentFileDescriptor() {}
+ // For use prior to reading in from a stream
+ nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inEncodedData);
+ virtual ~nsPersistentFileDescriptor();
+ void operator = (const nsPersistentFileDescriptor& inEncodedData);
+
+ // Conversions
+ NS_EXPLICIT nsPersistentFileDescriptor(const nsFileSpec& inSpec);
+ void operator = (const nsFileSpec& inSpec);
+
+ // The following four functions are declared here (as friends). Their implementations
+ // are in mozilla/base/src/nsFileSpecStreaming.cpp.
+
+ friend nsresult Read(nsIInputStream* aStream, nsPersistentFileDescriptor&);
+ friend nsresult Write(nsIOutputStream* aStream, const nsPersistentFileDescriptor&);
+ // writes the data to a file
+ friend NS_COM_OBSOLETE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&);
+ // reads the data from a file
+ friend NS_COM_OBSOLETE nsOutputStream& operator << (nsOutputStream&, const nsPersistentFileDescriptor&);
+ // writes the data to a file
+ friend class nsFileSpec;
+
+ void GetData(nsAFlatCString& outData) const;
+ void SetData(const nsAFlatCString& inData);
+ void SetData(const char* inData, PRInt32 inSize);
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ protected:
+
+ nsSimpleCharString mDescriptorString;
+
+}; // class nsPersistentFileDescriptor
+
+//========================================================================================
+class NS_COM_OBSOLETE nsDirectoryIterator
+// Example:
+//
+// nsFileSpec parentDir(...); // directory over whose children we shall iterate
+// for (nsDirectoryIterator i(parentDir, PR_FALSE); i.Exists(); i++)
+// {
+// // do something with i.Spec()
+// }
+//
+// - or -
+//
+// for (nsDirectoryIterator i(parentDir, PR_TRUE); i.Exists(); i--)
+// {
+// // do something with i.Spec()
+// }
+// This one passed the PR_TRUE flag which will resolve any symlink encountered.
+//========================================================================================
+{
+ public:
+ nsDirectoryIterator( const nsFileSpec& parent,
+ PRBool resoveSymLinks);
+#if !defined(XP_MAC)
+ // Macintosh currently doesn't allocate, so needn't clean up.
+ virtual ~nsDirectoryIterator();
+#endif
+ PRBool Exists() const { return mExists; }
+ nsDirectoryIterator& operator ++(); // moves to the next item, if any.
+ nsDirectoryIterator& operator ++(int) { return ++(*this); } // post-increment.
+ nsDirectoryIterator& operator --(); // moves to the previous item, if any.
+ nsDirectoryIterator& operator --(int) { return --(*this); } // post-decrement.
+ operator nsFileSpec&() { return mCurrent; }
+
+ nsFileSpec& Spec() { return mCurrent; }
+
+ private:
+
+#if defined(XP_MAC)
+ OSErr SetToIndex();
+#endif
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ private:
+
+ nsFileSpec mCurrent;
+ PRBool mExists;
+ PRBool mResoveSymLinks;
+
+#if (defined(XP_UNIX) || defined(XP_BEOS) || defined (XP_WIN) || defined(XP_OS2))
+ nsFileSpec mStarting;
+#endif
+
+#if defined(XP_MAC)
+ short mVRefNum;
+ long mParID;
+ short mIndex;
+ short mMaxIndex;
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ DIR* mDir;
+#elif defined(XP_WIN) || defined(XP_OS2)
+ PRDir* mDir; // XXX why not use PRDir for Unix too?
+#endif
+}; // class nsDirectoryIterator
+
+//========================================================================================
+class NS_COM_OBSOLETE nsNSPRPath
+// This class will allow you to pass any one of the nsFile* classes directly into NSPR
+// without the need to worry about whether you have the right kind of filepath or not.
+// It will also take care of cleaning up any allocated memory.
+//========================================================================================
+{
+public:
+ NS_EXPLICIT nsNSPRPath(const nsFileSpec& inSpec)
+ : mFilePath(inSpec), modifiedNSPRPath(nsnull) {}
+ NS_EXPLICIT nsNSPRPath(const nsFileURL& inURL)
+ : mFilePath(inURL), modifiedNSPRPath(nsnull) {}
+ NS_EXPLICIT nsNSPRPath(const nsFilePath& inUnixPath)
+ : mFilePath(inUnixPath), modifiedNSPRPath(nsnull) {}
+
+ virtual ~nsNSPRPath();
+
+ operator const char*() const;
+ // Returns the path
+ // that NSPR file routines expect on each platform.
+ // Concerning constness, this can modify
+ // modifiedNSPRPath, but it's really just "mutable".
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+private:
+
+ nsFilePath mFilePath;
+ char* modifiedNSPRPath; // Currently used only on XP_WIN,XP_OS2
+}; // class nsNSPRPath
+
+
+NS_COM_OBSOLETE nsresult NS_FileSpecToIFile(nsFileSpec* fileSpec, nsILocalFile* *result);
+
+#endif // _FILESPEC_H_
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp
new file mode 100644
index 00000000..20a38f5e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp
@@ -0,0 +1,547 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file is included by nsFileSpec.cpp, and includes the Unix-specific
+// implementations.
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "nsError.h"
+#include "prio.h" /* for PR_Rename */
+
+// BeOS specific headers
+#include <Entry.h>
+#include <Path.h>
+#include <Volume.h>
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+ if (inMakeDirs)
+ {
+ const mode_t mode = 0700;
+ nsFileSpecHelpers::MakeAllDirectories((const char*)ioPath, mode);
+ }
+ char buffer[MAXPATHLEN];
+ errno = 0;
+ *buffer = '\0';
+ BEntry e((const char *)ioPath, true);
+ BPath p;
+ e.GetPath(&p);
+ ioPath = p.Path();
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mPath.LeafReplace('/', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath.GetLeaf('/');
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISREG(st.st_mode);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_TRUE;
+ char *leafname = GetLeafName();
+ if (nsnull != leafname)
+ {
+ if ((!strcmp(leafname, ".")) || (!strcmp(leafname, "..")))
+ {
+ hidden = PR_FALSE;
+ }
+ nsCRT::free(leafname);
+ }
+ return hidden;
+} // nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISLNK(st.st_mode))
+ return PR_TRUE;
+
+ return PR_FALSE;
+} // nsFileSpec::IsSymlink
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ wasAliased = PR_FALSE;
+
+ char resolvedPath[MAXPATHLEN];
+ int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN);
+ if (0 < charCount)
+ {
+ if (MAXPATHLEN > charCount)
+ resolvedPath[charCount] = '\0';
+
+ wasAliased = PR_TRUE;
+ /* if it's not an absolute path,
+ replace the leaf with what got resolved */
+ if (resolvedPath[0] != '/') {
+ SetLeafName(resolvedPath);
+ }
+ else {
+ mPath = (char*)resolvedPath;
+ }
+
+ BEntry e((const char *)mPath, true); // traverse symlink
+ BPath p;
+ status_t err;
+ err = e.GetPath(&p);
+ NS_ASSERTION(err == B_OK, "realpath failed");
+
+ const char* canonicalPath = p.Path();
+ if(err == B_OK)
+ mPath = (char*)canonicalPath;
+ else
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+} // nsFileSpec::ResolveSymlink
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '/');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ char endChar = mPath[(int)(strlen(mPath) - 1)];
+ if (endChar == '/')
+ mPath += "x";
+ else
+ mPath += "/x";
+ SetLeafName(inRelativePath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int mode)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (mPath.IsEmpty())
+ return;
+ mkdir(mPath, mode);
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+// To check if this worked, call Exists() afterwards, see?
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+ child.Delete(inRecursive);
+ }
+ }
+ rmdir(mPath);
+ }
+ else if (!mPath.IsEmpty())
+ remove(mPath);
+} // nsFileSpec::Delete
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Truncate(PRInt32 offset) const
+//----------------------------------------------------------------------------------------
+{
+ char* Path = nsCRT::strdup(mPath);
+
+ int rv = truncate(Path, offset) ;
+
+ nsCRT::free(Path) ;
+
+ if(!rv)
+ return NS_OK ;
+ else
+ return NS_ERROR_FAILURE ;
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ // This function should not be used to move a file on disk.
+ if (mPath.IsEmpty() || strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+static int CrudeFileCopy(const char* in, const char* out)
+//----------------------------------------------------------------------------------------
+{
+ struct stat in_stat;
+ int stat_result = -1;
+
+ char buf [1024];
+ FILE *ifp, *ofp;
+ int rbytes, wbytes;
+
+ if (!in || !out)
+ return -1;
+
+ stat_result = stat (in, &in_stat);
+
+ ifp = fopen (in, "r");
+ if (!ifp)
+ {
+ return -1;
+ }
+
+ ofp = fopen (out, "w");
+ if (!ofp)
+ {
+ fclose (ifp);
+ return -1;
+ }
+
+ while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0)
+ {
+ while (rbytes > 0)
+ {
+ if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 )
+ {
+ fclose (ofp);
+ fclose (ifp);
+ unlink(out);
+ return -1;
+ }
+ rbytes -= wbytes;
+ }
+ }
+ fclose (ofp);
+ fclose (ifp);
+
+ if (stat_result == 0)
+ chmod (out, in_stat.st_mode & 0777);
+
+ return 0;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath));
+ }
+ return result;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inNewParentDirectory.IsDirectory() && !IsDirectory())
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), (const char*)destPath));
+ if (result == NS_OK)
+ {
+ // cast to fix const-ness
+ ((nsFileSpec*)this)->Delete(PR_FALSE);
+
+ *this = inNewParentDirectory + GetLeafName();
+ }
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_FILE_FAILURE;
+
+ if (!mPath.IsEmpty() && !IsDirectory())
+ {
+ nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;
+ result = NS_FILE_RESULT(system(fileNameWithArgs));
+ }
+
+ return result;
+
+} // nsFileSpec::Execute
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ char curdir [MAXPATHLEN];
+ if (!mPath || !*mPath)
+ {
+ (void) getcwd(curdir, MAXPATHLEN);
+ if (!curdir)
+ return ULONGLONG_MAX; /* hope for the best as we did in cheddar */
+ }
+ else
+ sprintf(curdir, "%.200s", (const char*)mPath);
+
+ BEntry e(curdir);
+ if(e.InitCheck() != B_OK)
+ return ULONGLONG_MAX; /* hope for the best as we did in cheddar */
+ entry_ref ref;
+ e.GetRef(&ref);
+ BVolume v(ref.device);
+
+#ifdef DEBUG_DISK_SPACE
+ printf("DiskSpaceAvailable: %d bytes\n", space);
+#endif
+ return v.FreeBytes();
+} // nsFileSpec::GetDiskSpace()
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(
+ const nsFileSpec& inDirectory
+, PRBool resolveSymlinks)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mStarting(inDirectory)
+ , mExists(PR_FALSE)
+ , mDir(nsnull)
+ , mResoveSymLinks(resolveSymlinks)
+{
+ mStarting += "sysygy"; // save off the starting directory
+ mCurrent += "sysygy"; // prepare the path for SetLeafName
+ mDir = opendir((const char*)nsFilePath(inDirectory));
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ closedir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ char* dot = ".";
+ char* dotdot = "..";
+ struct dirent* entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dot) == 0)
+ entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dotdot) == 0)
+ entry = readdir(mDir);
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting; // restore mCurrent to be the starting directory. ResolveSymlink() may have taken us to another directory
+ mCurrent.SetLeafName(entry->d_name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp
new file mode 100644
index 00000000..b0e3cc15
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp
@@ -0,0 +1,879 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsFileSpecImpl.h"// Always first, to ensure that it compiles alone.
+
+#include "nsIFileStream.h"
+#include "nsFileStream.h"
+
+#include "nsILocalFile.h"
+#include "nsNativeCharsetUtils.h"
+
+#include "prmem.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileSpecImpl, nsIFileSpec)
+
+#ifdef NS_DEBUG
+#define TEST_OUT_PTR(p) \
+ if (!(p)) \
+ return NS_ERROR_NULL_POINTER;
+#else
+#define TEST_OUT_PTR(p)
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+ : mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+ : mFileSpec(inSpec)
+ , mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::~nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+{
+ CloseStream();
+}
+
+//----------------------------------------------------------------------------------------
+/* static */
+nsresult nsFileSpecImpl::MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ nsFileSpecImpl* it = new nsFileSpecImpl(inSpec);
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return it->QueryInterface(NS_GET_IID(nsIFileSpec), (void **) result);
+} // nsFileSpecImpl::MakeInterface
+
+#define FILESPEC(ifilespec) ((nsFileSpecImpl*)ifilespec)->mFileSpec
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::FromFileSpec(const nsIFileSpec *original)
+//----------------------------------------------------------------------------------------
+{
+ if (original) {
+ nsresult rv = ((nsIFileSpec *)original)->GetFileSpec( &mFileSpec);
+ if (NS_SUCCEEDED( rv))
+ return mFileSpec.Error();
+ else
+ return( rv);
+ }
+ else
+ return( NS_ERROR_FAILURE);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsChildOf(nsIFileSpec *possibleParent,
+ PRBool *_retval)
+{
+ *_retval = mFileSpec.IsChildOf(FILESPEC(possibleParent));
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetURLString(char * *aURLString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aURLString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFileURL url(mFileSpec);
+ *aURLString = nsCRT::strdup(url.GetURLString());
+ if (!*aURLString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+} // nsFileSpecImpl::GetURLString
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetURLString(const char * aURLString)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFileURL(aURLString);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetUnixStyleFilePath(char * *aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aUnixStyleFilePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFilePath path(mFileSpec);
+ *aUnixStyleFilePath = nsCRT::strdup((const char*) path);
+ if (!*aUnixStyleFilePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetUnixStyleFilePath(const char * aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFilePath(aUnixStyleFilePath);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetPersistentDescriptorString(char * *aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aPersistentDescriptorString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsPersistentFileDescriptor desc(mFileSpec);
+ nsCAutoString data;
+ desc.GetData(data);
+ *aPersistentDescriptorString = ToNewCString(data);
+ if (!*aPersistentDescriptorString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetPersistentDescriptorString(const char * aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ nsPersistentFileDescriptor desc(mFileSpec);
+ desc.SetData(nsDependentCString(aPersistentDescriptorString));
+ mFileSpec = desc;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNativePath(char * *aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNativePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ *aNativePath = nsCRT::strdup(mFileSpec.GetNativePathCString());
+ if (!*aNativePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetNativePath(const char * aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aNativePath;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetUnicodePath(nsAString & aUnicodePath)
+//----------------------------------------------------------------------------------------
+{
+ nsCAutoString native;
+ native = mFileSpec.GetNativePathCString();
+ NS_CopyNativeToUnicode(native, aUnicodePath);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetUnicodePath(const nsAString & aUnicodePath)
+//----------------------------------------------------------------------------------------
+{
+ nsCAutoString native;
+
+ NS_CopyUnicodeToNative(aUnicodePath, native);
+ mFileSpec = native.get();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNSPRPath(char * *aNSPRPath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNSPRPath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsNSPRPath path(mFileSpec);
+ *aNSPRPath = nsCRT::strdup((const char*) path);
+ if (!*aNSPRPath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Error()
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsValid(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Valid();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Failed(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ *_retval = mFileSpec.Failed();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetLeafName(char * *aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aLeafName)
+ *aLeafName = mFileSpec.GetLeafName();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetLeafName(const char * aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.SetLeafName(aLeafName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetParent(nsIFileSpec * *aParent)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aParent)
+ nsFileSpec parent;
+ mFileSpec.GetParent(parent);
+ return MakeInterface(parent, aParent);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUnique()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUniqueWithSuggestedName(const char *suggestedName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique(suggestedName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetModDate(PRUint32 *aModDate)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aModDate)
+ nsFileSpec::TimeStamp stamp;
+ mFileSpec.GetModDate(stamp);
+ *aModDate = stamp;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ModDateChanged(PRUint32 oldStamp, PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.ModDateChanged(oldStamp);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsDirectory(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsDirectory();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsFile(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsFile();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Exists();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsHidden(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsHidden();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsSymlink(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsSymlink();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ResolveSymlink()
+//----------------------------------------------------------------------------------------
+{
+ PRBool ignore;
+ return mFileSpec.ResolveSymlink(ignore);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSize(PRUint32 *aFileSize)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSize)
+ *aFileSize = mFileSpec.GetFileSize();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aDiskSpaceAvailable)
+ *aDiskSpaceAvailable = mFileSpec.GetDiskSpaceAvailable();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::AppendRelativeUnixPath(const char *relativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec += relativePath;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Touch()
+//----------------------------------------------------------------------------------------
+{
+ // create an empty file, like the UNIX touch command.
+ nsresult rv;
+ rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ rv = CloseStream();
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CreateDir()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.CreateDir();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Delete(PRBool aRecursive)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.Delete(aRecursive);
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Truncate(PRInt32 aNewLength)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Truncate(aNewLength);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Rename(const char *newLeafName)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Rename(newLeafName);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CopyToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.CopyToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MoveToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.MoveToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Execute(const char *args)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Execute(args);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReading()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReadingAndWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ nsresult result = NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+ if (NS_SUCCEEDED(result))
+ result = NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CloseStream()
+//----------------------------------------------------------------------------------------
+{
+ NS_IF_RELEASE(mInputStream);
+ NS_IF_RELEASE(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsStreamOpen(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = (mInputStream || mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetInputStream(nsIInputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mInputStream;
+ NS_IF_ADDREF(mInputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetOutputStream(nsIOutputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mOutputStream;
+ NS_IF_ADDREF(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFileContents(const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 count;
+ rv = Write(inString, PL_strlen(inString), &count);
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileContents(char** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = nsnull;
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 theSize;
+ rv = GetFileSize((PRUint32*)&theSize);
+ if (NS_SUCCEEDED(rv))
+ rv = Read(_retval, theSize, &theSize);
+ if (NS_SUCCEEDED(rv))
+ (*_retval)[theSize] = 0;
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSpec(nsFileSpec *aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSpec)
+ *aFileSpec = mFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Equals(nsIFileSpec *spec, PRBool *result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv;
+
+ if (!result || !spec) return NS_ERROR_NULL_POINTER;
+
+ nsFileSpec otherSpec;
+
+ rv = spec->GetFileSpec(&otherSpec);
+ if (NS_FAILED(rv)) return rv;
+
+ if (mFileSpec == otherSpec) {
+ *result = PR_TRUE;
+ }
+ else {
+ *result = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFromFileSpec(const nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Eof(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.eof();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Read(char** buffer, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ TEST_OUT_PTR(buffer)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*buffer)
+ *buffer = (char*)PR_Malloc(requestedCount + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.read(*buffer, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ReadLine(char** line, PRInt32 bufferSize, PRBool *wasTruncated)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(wasTruncated)
+ TEST_OUT_PTR(line)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*line)
+ *line = (char*)PR_Malloc(bufferSize + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *wasTruncated = !s.readline(*line, bufferSize);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Write(const char * data, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ //if (!mOutputStream)
+ // return NS_ERROR_NULL_POINTER;
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ nsOutputFileStream s(mOutputStream);
+ *_retval = s.write(data, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Flush()
+//----------------------------------------------------------------------------------------
+{
+ if (!mOutputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsOutputFileStream s(mOutputStream);
+ s.flush();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Seek(PRInt32 offset)
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_OK;
+ if (mOutputStream)
+ {
+ nsOutputFileStream os(mOutputStream);
+ os.seek(offset);
+ result = os.error();
+ }
+ if (NS_SUCCEEDED(result) && mInputStream)
+ {
+ nsInputFileStream is(mInputStream);
+ is.seek(offset);
+ result = is.error();
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Tell(PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.tell();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::EndLine()
+//----------------------------------------------------------------------------------------
+{
+ nsOutputFileStream s(mOutputStream);
+ s << nsEndl;
+ return s.error();
+}
+
+NS_IMPL_ISUPPORTS1(nsDirectoryIteratorImpl, nsIDirectoryIterator)
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+ : mDirectoryIterator(nsnull)
+{
+}
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::~nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Init(nsIFileSpec *parent, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+ mDirectoryIterator = new nsDirectoryIterator(FILESPEC(parent), resolveSymlink);
+ if (!mDirectoryIterator)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ *_retval = mDirectoryIterator->Exists();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Next()
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ (*mDirectoryIterator)++;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::GetCurrentSpec(nsIFileSpec * *aCurrentSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ return nsFileSpecImpl::MakeInterface(mDirectoryIterator->Spec(), aCurrentSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsDirectoryIteratorImpl* it = new nsDirectoryIteratorImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsFileSpecImpl* it = new nsFileSpecImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecWithSpec(const nsFileSpec& aSrcFileSpec, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ if (!result)
+ return NS_ERROR_NULL_POINTER;
+
+ return nsFileSpecImpl::MakeInterface(aSrcFileSpec, result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpec(nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecFromIFile(nsIFile *aFile, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCAutoString path;
+ rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = (*result)->SetNativePath(path.get());
+ if (NS_FAILED(rv))
+ NS_RELEASE(*result);
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewDirectoryIterator(nsIDirectoryIterator** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsDirectoryIteratorImpl::Create(nsnull, NS_GET_IID(nsIDirectoryIterator), (void**)result);
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h
new file mode 100644
index 00000000..811749cb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _FILESPECIMPL_H_
+#define _FILESPECIMPL_H_
+
+#include "nscore.h"
+#include "nsIFileSpec.h"
+#include "nsFileSpec.h"
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileSpecImpl
+//========================================================================================
+ : public nsIFileSpec
+{
+
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIFILESPEC
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+ //----------------------
+ // Implementation
+ //----------------------
+
+ nsFileSpecImpl();
+ nsFileSpecImpl(const nsFileSpec& inSpec);
+ static nsresult MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** outSpec);
+
+ //----------------------
+ // Data
+ //----------------------
+
+ nsFileSpec mFileSpec;
+ nsIInputStream* mInputStream;
+ nsIOutputStream* mOutputStream;
+
+private:
+ ~nsFileSpecImpl();
+}; // class nsFileSpecImpl
+
+//========================================================================================
+class NS_COM_OBSOLETE nsDirectoryIteratorImpl
+//========================================================================================
+ : public nsIDirectoryIterator
+{
+
+public:
+
+ nsDirectoryIteratorImpl();
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Init(nsIFileSpec *parent, PRBool resolveSymlink);
+
+ NS_IMETHOD Exists(PRBool *_retval);
+
+ NS_IMETHOD Next();
+
+ NS_IMETHOD GetCurrentSpec(nsIFileSpec * *aCurrentSpec);
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+private:
+ ~nsDirectoryIteratorImpl();
+
+protected:
+ nsDirectoryIterator* mDirectoryIterator;
+}; // class nsDirectoryIteratorImpl
+
+#endif // _FILESPECIMPL_H_
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp
new file mode 100644
index 00000000..fd208fb7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp
@@ -0,0 +1,1471 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file is included by nsFile.cp, and includes the Macintosh-specific
+// implementations.
+
+
+#include <string.h>
+
+#include "prtypes.h"
+#include "nscore.h"
+
+#include "FullPath.h"
+#include "FileCopy.h"
+#include "MoreFilesExtras.h"
+
+#include <Aliases.h>
+#include <Folders.h>
+#include <Math64.h>
+#include <TextUtils.h>
+#include <Processes.h>
+#include <limits.h> // ULONG_MAX
+
+#include "nsFileSpec.h"
+#include "nsEscape.h"
+#include "nsXPIDLString.h"
+
+
+const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven";
+
+//========================================================================================
+namespace MacFileHelpers
+//========================================================================================
+{
+ inline void PLstrcpy(Str255 dst, ConstStr255Param src)
+ {
+ memcpy(dst, src, 1 + src[0]);
+ }
+
+ void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255);
+ void PLstrncpy(Str255 dst, const char* src, int inMaxLen);
+
+ void SwapSlashColon(char * s);
+ OSErr FSSpecFromUnixPath(
+ const char * unixPath,
+ FSSpec& ioSpec,
+ Boolean hexDecode,
+ Boolean resolveAlias,
+ Boolean allowPartial = false,
+ Boolean createDirs = false);
+ char* MacPathFromUnixPath(
+ const char* unixPath,
+ Boolean hexDecode);
+ char* EncodeMacPath(
+ char* inPath, // NOT const - gets clobbered
+ Boolean prependSlash,
+ Boolean doEscape );
+ OSErr FSSpecFromPathname(
+ const char* inPathNamePtr,
+ FSSpec& ioSpec,
+ Boolean inCreateDirs);
+ char* PathNameFromFSSpec(
+ const FSSpec& inSpec );
+ OSErr CreateFolderInFolder(
+ short refNum, // Parent directory/volume
+ long dirID,
+ ConstStr255Param folderName, // Name of the new folder
+ short& outRefNum, // Volume of the created folder
+ long& outDirID); //
+
+ // Some routines to support an "alias haven" directory. Aliases in this directory
+ // are never resolved. There is a ResolveAlias here that respects that. This is
+ // to support attaching of aliases in mail.
+ void EnsureAliasHaven();
+ void SetNoResolve(Boolean inResolve);
+ PRBool IsAliasSafe(const FSSpec& inSpec);
+ OSErr MakeAliasSafe(FSSpec& inOutSpec);
+ OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased);
+
+ Boolean sNoResolve = false;
+ long sAliasHavenDirID = 0;
+ short sAliasHavenVRefNum = 0;
+} // namespace MacFileHelpers
+
+//----------------------------------------------------------------------------------------
+void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
+//----------------------------------------------------------------------------------------
+{
+ int srcLength = strlen(src);
+ NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!");
+ if (srcLength > inMax)
+ srcLength = inMax;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+//----------------------------------------------------------------------------------------
+void MacFileHelpers::PLstrncpy(Str255 dst, const char* src, int inMax)
+//----------------------------------------------------------------------------------------
+{
+ int srcLength = strlen(src);
+ if (srcLength > inMax)
+ srcLength = inMax;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+//-----------------------------------
+void MacFileHelpers::SwapSlashColon(char * s)
+//-----------------------------------
+
+{
+ while (*s)
+ {
+ if (*s == '/')
+ *s++ = ':';
+ else if (*s == ':')
+ *s++ = '/';
+ else
+ *s++;
+ }
+} // MacFileHelpers::SwapSlashColon
+
+//-----------------------------------
+char* MacFileHelpers::EncodeMacPath(
+ char* inPath, // NOT const, gets clobbered
+ Boolean prependSlash,
+ Boolean doEscape )
+// Transforms Macintosh style path into Unix one
+// Method: Swap ':' and '/', hex escape the result
+//-----------------------------------
+{
+ if (inPath == nsnull)
+ return nsnull;
+ int pathSize = strlen(inPath);
+
+ // XP code sometimes chokes if there's a final slash in the unix path.
+ // Since correct mac paths to folders and volumes will end in ':', strip this
+ // first.
+ char* c = inPath + pathSize - 1;
+ if (*c == ':')
+ {
+ *c = 0;
+ pathSize--;
+ }
+
+ char * newPath = nsnull;
+ char * finalPath = nsnull;
+
+ if (prependSlash)
+ {
+ newPath = new char[pathSize + 2];
+ newPath[0] = ':'; // It will be converted to '/'
+ memcpy(&newPath[1], inPath, pathSize + 1);
+ }
+ else
+ {
+ newPath = new char[pathSize + 1];
+ strcpy(newPath, inPath);
+ }
+ if (newPath)
+ {
+ SwapSlashColon( newPath );
+ if (doEscape)
+ {
+ finalPath = nsEscape(newPath, url_Path);
+ delete [] newPath;
+ }
+ else
+ finalPath = newPath;
+ }
+ delete [] inPath;
+ return finalPath;
+} // MacFileHelpers::EncodeMacPath
+
+//----------------------------------------------------------------------------------------
+inline void MacFileHelpers::SetNoResolve(Boolean inResolve)
+//----------------------------------------------------------------------------------------
+{
+ sNoResolve = inResolve;
+} // MacFileHelpers::SetNoResolve
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec)
+// Pass in the spec of an alias. This copies the file to the safe haven folder, and
+// returns the spec of the copy to the caller
+//----------------------------------------------------------------------------------------
+{
+ EnsureAliasHaven();
+ nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
+
+ // Make sure its name is unique
+ nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
+ if (havenSpec.Valid())
+ havenSpec.MakeUnique(inOutSpec.name);
+ // Copy the file into the haven directory
+ if (havenSpec.Valid())
+ {
+ OSErr err = ::FSpFileCopy(
+ &inOutSpec,
+ dstDirSpec,
+ havenSpec.GetLeafPName(),
+ nil, 0, true);
+ // Return the spec of the copy to the caller.
+ if (err != noErr)
+ return err;
+ inOutSpec = havenSpec;
+ }
+ return noErr;
+} // MacFileHelpers::MakeAliasSafe
+
+//----------------------------------------------------------------------------------------
+char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath, Boolean hexDecode)
+//----------------------------------------------------------------------------------------
+{
+ // Relying on the fact that the unix path is always longer than the mac path:
+ size_t len = strlen(unixPath);
+ char* result = new char[len + 2]; // ... but allow for the initial colon in a partial name
+ // REMEMBER: at the end we call SwapSlashColon, so bear that in mind when you see
+ // this code using '/' as a separator in what is supposed to be a Macintosh path!
+ if (result)
+ {
+ char* dst = result;
+ const char* src = unixPath;
+ if (*src == '/') // * full path
+ src++;
+ else if (strchr(src, '/') && *src != '.')
+ {
+ // * partial path, and not just a leaf name. The '.' test is there because
+ // the loop below will add sufficient colons in that case.
+ *dst++ = '/';
+ }
+ // Copy src to dst, but watch out for .. and .
+ char c = '/';
+ do
+ {
+ char cprev = c; // remember the previous char (initially /)
+ c = *src++;
+ if (c == '.' && cprev == '/')
+ {
+ char* dstSaved = dst;
+ // Special cases: "." and "..". Convert to ':' and '::'
+ *dst++ = '/'; // . becomes :
+ c = *src++;
+ if (c == '.')
+ {
+ *dst++ = '/'; // .. becomes ::
+ c = *src++;
+ }
+ if (c == '/')
+ {
+ // ../ becomes :: so just skip the slash
+ // ./ becomes : " " " " "
+ src++;
+ }
+ else if (c)
+ {
+ // Oh. A file called ".foo" or "..foo"
+ // Back up and just do the normal thing.
+ src -= (dst - dstSaved);
+ dst = dstSaved;
+ // Since c is not '/', we won't do this stuff on the
+ // next iteration.
+ }
+ continue;
+ }
+ else if (c == '/' && cprev == '/')
+ {
+ // Hmm. A 'run on' path with two slashes right next to each other.
+ // This is an illegal path, but, hey, we'll be tough and try to
+ // deal with it (especially since '::' has loaded semantics in
+ // a Mac path)
+ continue;
+ }
+ *dst++ = c;
+ } while (c);
+ if (hexDecode)
+ nsUnescape(result); // Hex Decode
+ MacFileHelpers::SwapSlashColon(result);
+ }
+ return result;
+} // MacFileHelpers::MacPathFromUnixPath
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::FSSpecFromPathname(
+ const char* inPathNamePtr,
+ FSSpec& ioSpec, // used as in-parameter for a relative path.
+ Boolean inCreateDirs)
+// FSSpecFromPathname reverses PathNameFromFSSpec.
+// It returns a FSSpec given a c string which is a mac pathname.
+//----------------------------------------------------------------------------------------
+{
+ OSErr err;
+ // Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles
+ // routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames.
+
+ short inVRefNum = ioSpec.vRefNum;
+ long inParID = ioSpec.parID;
+
+ size_t inLength = strlen(inPathNamePtr);
+ bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':');
+#ifdef NS_DEBUG
+ // Attempt to catch people sending unix paths in to routines that expect native ones.
+ NS_ASSERTION(strchr(inPathNamePtr, '/') == 0,
+ "Possible unix path where native path is required");
+#endif
+ if (inLength < 255)
+ {
+ Str255 pascalpath;
+ MacFileHelpers::PLstrcpy(pascalpath, inPathNamePtr);
+ if (isRelative)
+ err = ::FSMakeFSSpec(inVRefNum, inParID, pascalpath, &ioSpec);
+ else
+ err = ::FSMakeFSSpec(0, 0, pascalpath, &ioSpec);
+ }
+ else if (!isRelative)
+ err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec);
+ else
+ err = bdNamErr;
+
+ if ((err == dirNFErr || err == bdNamErr) && inCreateDirs)
+ {
+ const char* path = inPathNamePtr;
+ if (isRelative)
+ {
+ ioSpec.vRefNum = inVRefNum;
+ ioSpec.parID = inParID;
+ }
+ else
+ {
+ ioSpec.vRefNum = 0;
+ ioSpec.parID = 0;
+ }
+ do {
+ // Locate the colon that terminates the node.
+ // But if we've a partial path (starting with a colon), find the second one.
+ const char* nextColon = strchr(path + (*path == ':'), ':');
+ // Well, if there are no more colons, point to the end of the string.
+ if (!nextColon)
+ nextColon = path + strlen(path);
+
+ // Make a pascal string out of this node. Include initial
+ // and final colon, if any!
+ Str255 ppath;
+ MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1);
+
+ // Use this string as a relative path using the directory created
+ // on the previous round (or directory 0,0 on the first round).
+ err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec);
+
+ // If this was the leaf node, then we are done.
+ if (!*nextColon)
+ break;
+
+ // Since there's more to go, we have to get the directory ID, which becomes
+ // the parID for the next round.
+ if (err == noErr)
+ {
+ // The directory (or perhaps a file) exists. Find its dirID.
+ long dirID;
+ Boolean isDirectory;
+ err = ::FSpGetDirectoryID(&ioSpec, &dirID, &isDirectory);
+ if (!isDirectory)
+ return dupFNErr; // oops! a file exists with that name.
+ if (err)
+ return err;
+ ioSpec.parID = dirID;
+ }
+ else if (err == fnfErr)
+ {
+ // If we got "file not found", then
+ // we need to create a directory.
+ err = ::FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID);
+ // For some reason, this usually returns fnfErr, even though it works.
+ if (err == fnfErr)
+ err = noErr;
+ }
+ if (err != noErr)
+ return err;
+ path = nextColon; // next round
+ } while (1);
+ }
+ return err;
+} // MacFileHelpers::FSSpecFromPathname
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::CreateFolderInFolder(
+ short refNum, // Parent directory/volume
+ long dirID,
+ ConstStr255Param folderName, // Name of the new folder
+ short& outRefNum, // Volume of the created folder
+ long& outDirID) //
+// Creates a folder named 'folderName' inside a folder.
+// The errors returned are same as PBDirCreate
+//----------------------------------------------------------------------------------------
+{
+ HFileParam hpb;
+ hpb.ioVRefNum = refNum;
+ hpb.ioDirID = dirID;
+ hpb.ioNamePtr = (StringPtr)&folderName;
+
+ OSErr err = PBDirCreateSync((HParmBlkPtr)&hpb);
+ if (err == noErr)
+ {
+ outRefNum = hpb.ioVRefNum;
+ outDirID = hpb.ioDirID;
+ }
+ else
+ {
+ outRefNum = 0;
+ outDirID = 0;
+ }
+ return err;
+} // MacFileHelpers::CreateFolderInFolder
+
+//----------------------------------------------------------------------------------------
+void MacFileHelpers::EnsureAliasHaven()
+//----------------------------------------------------------------------------------------
+{
+ // Alias Haven is a directory in which we never resolve aliases.
+ if (sAliasHavenVRefNum != 0)
+ return;
+
+
+ FSSpec temp;
+ if (FindFolder(0, kTemporaryFolderType, true, & temp.vRefNum, &temp.parID) == noErr)
+ {
+ CreateFolderInFolder(
+ temp.vRefNum, // Parent directory/volume
+ temp.parID,
+ kAliasHavenFolderName, // Name of the new folder
+ sAliasHavenVRefNum, // Volume of the created folder
+ sAliasHavenDirID);
+ }
+} // MacFileHelpers::EnsureAliasHaven
+
+//----------------------------------------------------------------------------------------
+PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
+// Returns true if the alias is in the alias haven directory, or if alias resolution
+// has been turned off.
+//----------------------------------------------------------------------------------------
+{
+ return sNoResolve
+ || (inSpec.parID == sAliasHavenDirID && inSpec.vRefNum == sAliasHavenVRefNum);
+} // MacFileHelpers::IsAliasSafe
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ wasAliased = false;
+ if (IsAliasSafe(inOutSpec))
+ return noErr;
+ Boolean dummy;
+ return ::ResolveAliasFile(&inOutSpec, TRUE, &dummy, &wasAliased);
+} // MacFileHelpers::ResolveAliasFile
+
+//-----------------------------------
+OSErr MacFileHelpers::FSSpecFromUnixPath(
+ const char * unixPath,
+ FSSpec& ioSpec,
+ Boolean hexDecode,
+ Boolean resolveAlias,
+ Boolean allowPartial,
+ Boolean createDirs)
+// File spec from URL. Reverses GetURLFromFileSpec
+// Its input is only the <path> part of the URL
+// JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'),
+// then it is combined with inOutSpec's vRefNum and parID to form a new spec.
+//-----------------------------------
+{
+ if (unixPath == nsnull)
+ return badFidErr;
+ char* macPath = MacPathFromUnixPath(unixPath, hexDecode);
+ if (!macPath)
+ return memFullErr;
+
+ OSErr err = noErr;
+ if (!allowPartial)
+ {
+ NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!");
+ }
+ err = FSSpecFromPathname(macPath, ioSpec, createDirs);
+ if (err == fnfErr)
+ err = noErr;
+ Boolean dummy;
+ if (err == noErr && resolveAlias) // Added
+ err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy);
+ delete [] macPath;
+ NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!");
+ return err;
+} // MacFileHelpers::FSSpecFromLocalUnixPath
+
+//-----------------------------------
+char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec )
+// Returns a full pathname to the given file
+// Returned value is allocated with new [], and must be freed with delete []
+// For consistency and to work under OS X this creates an nsILocalFileMac and has it do the work.
+//-----------------------------------
+{
+ char* result = nil;
+ nsresult rv;
+
+ FSSpec nonConstSpec = inSpec;
+ nsCAutoString path;
+ nsCOMPtr<nsILocalFileMac> macFile;
+
+ rv = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_FAILED(rv)) return nsnull;
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(macFile, &rv));
+ if (NS_FAILED(rv)) return nsnull;
+ rv = localFile->GetNativePath(path);
+ if (NS_FAILED(rv)) return nsnull;
+ PRInt32 strLen = path.Length();
+ result = new char [strLen + 1];
+ if (!result) return nsnull;
+ memcpy(result, path.get(), strLen);
+ result[ strLen ] = 0;
+
+ return result;
+} // MacFileHelpers::PathNameFromFSSpec
+
+
+#pragma mark -
+
+//========================================================================================
+// Macintosh nsFileSpec implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec()
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ Clear();
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias)
+//----------------------------------------------------------------------------------------
+: mSpec(inSpec)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ if (resolveAlias)
+ {
+ PRBool dummy;
+ ResolveSymlink(dummy);
+ }
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const FSSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mSpec = inSpec;
+ mError = NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+: mSpec(inSpec.mSpec)
+, mError(inSpec.Error())
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
+
+ if (inNativePathString)
+ {
+ mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(
+ inNativePathString, mSpec, inCreateDirs));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+ }
+
+} // nsFileSpec::nsFileSpec
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
+
+ mError = NS_FILE_RESULT(
+ MacFileHelpers::FSSpecFromPathname(
+ NS_LossyConvertUCS2toASCII(inNativePathString).get(),
+ mSpec, inCreateDirs));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+
+} // nsFileSpec::nsFileSpec
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param fileName, PRBool resolveAlias)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, fileName, &mSpec));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+
+ if (resolveAlias)
+ {
+ PRBool dummy;
+ ResolveSymlink(dummy);
+ }
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ *this = inPath.GetFileSpec();
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
+
+ if (inString)
+ {
+ mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inString, mSpec, true));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+ }
+
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mSpec.vRefNum = inSpec.mSpec.vRefNum;
+ mSpec.parID = inSpec.mSpec.parID;
+
+ PRInt32 copySize = inSpec.mSpec.name[0] + 1;
+ if (copySize > sizeof(inSpec.mSpec.name))
+ copySize = sizeof(inSpec.mSpec.name);
+ memcpy(mSpec.name, inSpec.mSpec.name, copySize);
+ mError = inSpec.Error(); // note that the error is propagated
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ *this = inPath.GetFileSpec();
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+inline void nsFileSpec::Clear()
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mSpec.vRefNum = 0;
+ mSpec.parID = 0;
+ mSpec.name[0] = 0;
+ mError = NS_ERROR_NOT_INITIALIZED;
+}
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ if (NS_FAILED(mError)) return PR_FALSE;
+ FSSpec temp;
+ return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr;
+} // nsFileSpec::Exists()
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec pb;
+ if (GetCatInfo(pb) == noErr)
+ outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs.
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec pb;
+ if (noErr == GetCatInfo(pb))
+ return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+// In leaf name can actually be a partial path...
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inLeafName, "Attempt to set leaf name with a null string");
+
+ mPath.SetToEmpty();
+
+ if (inLeafName)
+ {
+ // what about long relative paths? Hmm? We don't have a routine for this anywhere.
+ Str255 partialPath;
+ MacFileHelpers::PLstrcpy(partialPath, inLeafName);
+ mError = NS_FILE_RESULT(
+ ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+ }
+
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+// Result needs to be nsCRT::free()ed.
+//----------------------------------------------------------------------------------------
+{
+ char leaf[sizeof(mSpec.name)];
+ memcpy(leaf, &mSpec.name[1], mSpec.name[0]);
+ leaf[mSpec.name[0]] = '\0';
+ return nsCRT::strdup(leaf);
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeAliasSafe()
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec));
+} // nsFileSpec::MakeAliasSafe
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ if (inSuggestedLeafName[0] > 0)
+ MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName);
+
+ MakeUnique();
+} // nsFileSpec::MakeUnique
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ long dirID;
+ Boolean isDirectory;
+ return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ long dirID;
+ Boolean isDirectory;
+ return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cInfo;
+ PRBool hidden = PR_FALSE;
+
+ if (noErr == GetCatInfo(cInfo))
+ if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible)
+ hidden = PR_TRUE;
+
+ return hidden;
+} // nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cInfo;
+ PRBool hidden = PR_FALSE;
+
+ if (noErr == GetCatInfo(cInfo))
+ if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias)
+ hidden = PR_TRUE;
+
+ return hidden;
+} // nsFileSpec::IsSymlink
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ Boolean wasAliased2; // Type conversion Boolean <--> PRBool
+ OSErr err = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2);
+ if (wasAliased2)
+ {
+ mError = NS_FILE_RESULT(err);
+ wasAliased = PR_TRUE;
+ }
+ else
+ wasAliased = PR_FALSE;
+
+ return mError;
+} // nsFileSpec::ResolveSymlink
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ if (NS_SUCCEEDED(mError))
+ outSpec.mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec));
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to append relative path with null path");
+
+ // Invalidate the path cache string, since we're changing ourselves.
+ mPath.SetToEmpty();
+
+ // if we are already bad, don't allow appendage
+ if (NS_FAILED(Error()))
+ {
+ NS_WARNING("trying to append to a bad nsFileSpec");
+ return;
+ }
+
+ // Find the dirID of the directory described by this spec
+ long dirID;
+ Boolean isDirectory;
+ mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory));
+ if (NS_FAILED(mError) || !isDirectory || !inRelativePath)
+ return;
+ // mSpec.vRefNum is already correct.
+ mSpec.parID = dirID;
+
+ // Next, determine if it is a UNIX or Mac style path. Now, Macintosh relative paths
+ // are either leaf names (in which the distinction between unix and macintosh
+ // relative paths disappears) or they start with a colon. If we find an initial colon,
+ // then assume it's a macintosh path.
+ // If it is a UNIX path (including just a leaf name), we will also look for ':' and
+ // assert if we find one.
+ if (*inRelativePath != ':')
+ {
+ // Looks like a UNIX path (including possibly just a leaf name)
+ NS_ASSERTION(strchr(inRelativePath, ':') == nsnull, "Can not determine path type");
+ // Convert unix path (which is unencoded) to a spec
+ mError = NS_FILE_RESULT(
+ MacFileHelpers::FSSpecFromUnixPath(inRelativePath, mSpec, false, false, true, true));
+ }
+ else
+ {
+ // We must be a mac path!
+ mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inRelativePath, mSpec, true));
+ }
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int /* unix mode */)
+//----------------------------------------------------------------------------------------
+{
+ long ignoredDirID;
+ OSErr err = ::FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
+ // it's OK if the dir already exists
+ if (err != noErr && IsDirectory())
+ err = noErr;
+
+ mError = NS_FILE_RESULT(err);
+
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+//----------------------------------------------------------------------------------------
+{
+ OSErr anErr;
+
+ nsresult& mutableError = const_cast<nsFileSpec*>(this)->mError;
+ if (inRecursive)
+ {
+ // MoreFilesExtras
+ anErr = ::DeleteDirectory(
+ mSpec.vRefNum,
+ mSpec.parID,
+ const_cast<unsigned char*>(mSpec.name));
+ }
+ else
+ anErr = ::FSpDelete(&mSpec);
+
+ if (anErr == fnfErr) // deleting a file that doesn't exist isn't an error!
+ anErr = noErr;
+
+ mutableError = NS_FILE_RESULT(anErr);
+
+} // nsFileSpec::Delete
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Truncate(PRInt32 aNewLength) const
+//----------------------------------------------------------------------------------------
+{
+ short refNum;
+ OSErr err;
+
+ // First see if we have an internal error set
+ if (NS_FAILED(mError))
+ return mError;
+
+ // Need to open the file to trunc
+ if (::FSpOpenDF(&mSpec, fsWrPerm, &refNum) != noErr)
+ return NS_FILE_FAILURE;
+
+ err = ::SetEOF(refNum, aNewLength);
+
+ // Close the file unless we got an error that it was already closed
+ if (err != fnOpnErr)
+ (void)::FSClose(refNum);
+
+ if (err != noErr)
+ return NS_FILE_FAILURE;
+
+ return NS_OK;
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to rename with null new name");
+
+ if (strchr(inNewName, '/'))
+ return NS_FILE_FAILURE; // no relative paths here!
+
+ Str255 pName;
+ MacFileHelpers::PLstrcpy(pName, inNewName);
+ if (::FSpRename(&mSpec, pName) != noErr)
+ return NS_FILE_FAILURE;
+ SetLeafName(inNewName);
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& newParentDir) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+
+ if (!newParentDir.IsDirectory() || (IsDirectory() ) )
+ return NS_FILE_FAILURE;
+
+ nsresult rv = NS_FILE_RESULT(::FSpFileCopy(&mSpec,
+ &newParentDir.mSpec,
+ const_cast<StringPtr>(GetLeafPName()),
+ nsnull,
+ 0,
+ true));
+
+ return rv;
+
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ // We can only move into a directory
+
+ if (!newParentDir.IsDirectory())
+ return NS_FILE_FAILURE;
+
+ nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec,
+ &newParentDir.mSpec,
+ const_cast<StringPtr>(GetLeafPName())));
+
+ if ( NS_SUCCEEDED(result) )
+ {
+ char* leafName = GetLeafName();
+ *this = newParentDir + leafName;
+ nsCRT::free(leafName);
+ }
+ return result;
+} // nsFileSpec::MoveToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ return NS_FILE_FAILURE;
+
+ LaunchParamBlockRec launchThis;
+ launchThis.launchAppSpec = const_cast<FSSpec*>(&mSpec);
+ launchThis.launchAppParameters = nsnull; // args;
+ /* launch the thing */
+ launchThis.launchBlockID = extendedBlock;
+ launchThis.launchEPBLength = extendedBlockLen;
+ launchThis.launchFileFlags = nsnull;
+ launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
+ launchThis.launchControlFlags += launchDontSwitch;
+
+ nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis));
+ return result;
+
+} // nsFileSpec::Execute
+
+//----------------------------------------------------------------------------------------
+OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const
+//----------------------------------------------------------------------------------------
+{
+ DirInfo *dipb=(DirInfo *)&outInfo;
+ dipb->ioCompletion = nsnull;
+ dipb->ioFDirIndex = 0; // use dirID and name
+ dipb->ioVRefNum = mSpec.vRefNum;
+ dipb->ioDrDirID = mSpec.parID;
+ dipb->ioNamePtr = const_cast<nsFileSpec*>(this)->mSpec.name;
+ return PBGetCatInfoSync(&outInfo);
+} // nsFileSpec::GetCatInfo()
+
+//----------------------------------------------------------------------------------------
+OSErr nsFileSpec::SetFileTypeAndCreator(OSType type, OSType creator)
+//----------------------------------------------------------------------------------------
+{
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&mSpec, &info);
+ if (err != noErr)
+ return err;
+ info.fdType = type;
+ info.fdCreator = creator;
+ err = ::FSpSetFInfo(&mSpec, &info);
+ return err;
+}
+
+//----------------------------------------------------------------------------------------
+OSErr nsFileSpec::GetFileTypeAndCreator(OSType* type, OSType* creator)
+//----------------------------------------------------------------------------------------
+{
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&mSpec, &info);
+ if (err != noErr)
+ return err;
+ *type = info.fdType;
+ *creator = info.fdCreator;
+ return noErr;
+}
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 space64Bits;
+
+ LL_I2L(space64Bits , LONG_MAX);
+
+ XVolumeParam pb;
+ pb.ioCompletion = nsnull;
+ pb.ioVolIndex = 0;
+ pb.ioNamePtr = nsnull;
+ pb.ioVRefNum = mSpec.vRefNum;
+
+ // PBXGetVolInfoSync works on HFS+ volumes too!
+ OSErr err = ::PBXGetVolInfoSync(&pb);
+
+ if (err == noErr)
+ {
+#ifdef HAVE_LONG_LONG
+ space64Bits = pb.ioVFreeBytes;
+#else
+ const UnsignedWide& freeBytes = UInt64ToUnsignedWide(pb.ioVFreeBytes);
+ space64Bits.lo = freeBytes.lo;
+ space64Bits.hi = freeBytes.hi;
+#endif
+ }
+
+ return space64Bits;
+} // nsFileSpec::GetDiskSpace()
+
+//----------------------------------------------------------------------------------------
+const char* nsFileSpec::GetCString() const
+// This is the only conversion to const char* that is provided, and it allows the
+// path to be "passed" to NSPR file routines. This practice is VERY EVIL and should only
+// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is
+// cached and freed by the nsFileSpec destructor, so do not delete (or free) it.
+//----------------------------------------------------------------------------------------
+{
+ if (mPath.IsEmpty())
+ {
+ char* path = MacFileHelpers::PathNameFromFSSpec(mSpec);
+ if (path != NULL) {
+ const_cast<nsFileSpec*>(this)->mPath = path; // operator =() copies the string!!!
+ delete[] path;
+ } else {
+ const_cast<nsFileSpec*>(this)->mError = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ return mPath;
+}
+
+#pragma mark -
+
+//========================================================================================
+// Macintosh nsFilePath implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+static void AssignFromPath(nsFilePath& ioPath, const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inString, "AssignFromPath called with null inString");
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
+
+ FSSpec spec;
+ spec.vRefNum = 0;
+ spec.parID = 0;
+ spec.name[0] = 0;
+ MacFileHelpers::FSSpecFromUnixPath(
+ inString,
+ spec,
+ false,
+ true, // resolve alias
+ true,
+ inCreateDirs);
+ // Now we have a spec,
+ // Invoke operator = (const nsFileSpec&) to do the rest.
+ // Why didn't we just say mPath = inString to get the path? Well, we want it to be
+ // canonical and absolute.
+ ioPath = spec;
+}
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ AssignFromPath(*this, inString, inCreateDirs);
+} //nsFilePath::nsFilePath
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ AssignFromPath(*this, NS_LossyConvertUCS2toASCII(inString).get(),
+ inCreateDirs);
+}
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ AssignFromPath(*this, inString, PR_FALSE);
+}
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+}
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+}
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ char * path = MacFileHelpers::PathNameFromFSSpec(inSpec);
+ path = MacFileHelpers::EncodeMacPath(path, true, false);
+ mPath = path;
+ nsCRT::free(path);
+ mFileSpec = inSpec;
+} // nsFilePath::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec);
+ path = MacFileHelpers::EncodeMacPath(path, true, false);
+ mPath = path;
+ nsCRT::free(path);
+ mFileSpec = inOther.GetFileSpec();
+}
+
+#pragma mark -
+
+//========================================================================================
+// nsFileURL implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mURL(inString)
+{
+ NS_ASSERTION(inString, "nsFileURL constructed with null inString");
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+ mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
+ inString + kFileURLPrefixLength,
+ mFileSpec.mSpec,
+ true, // need to decode
+ false, // resolve alias
+ false, // must be a full path
+ inCreateDirs));
+ if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
+ mFileSpec.mError = NS_OK;
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mURL(nsnull)
+{
+ NS_LossyConvertUCS2toASCII cstring(inString);
+ mURL = cstring.get();
+ NS_ASSERTION(strstr(cstring.get(), kFileURLPrefix) == cstring.get(),
+ "Not a URL!");
+ mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
+ cstring.get() + kFileURLPrefixLength,
+ mFileSpec.mSpec,
+ true, // need to decode
+ false, // resolve alias
+ false, // must be a full path
+ inCreateDirs));
+ if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
+ mFileSpec.mError = NS_OK;
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther.GetFileSpec();
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther.GetFileSpec();
+} // nsFileURL::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = inOther;
+ char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec );
+ char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true);
+ nsSimpleCharString encodedURL(kFileURLPrefix);
+ encodedURL += encodedPath;
+ nsCRT::free(encodedPath);
+ mURL = encodedURL;
+ if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory())
+ mURL += "/";
+} // nsFileURL::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inString, "nsFileURL operator= constructed with null inString");
+
+ mURL = inString;
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+ mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
+ inString + kFileURLPrefixLength,
+ mFileSpec.mSpec,
+ true, // need to decode
+ true, // resolve alias
+ false, // must be a full path
+ false)); // don't create dirs.
+ if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
+ mFileSpec.mError = NS_OK;
+} // nsFileURL::operator =
+
+#pragma mark -
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(
+ const nsFileSpec& inDirectory
+, PRBool resolveSymLinks)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mExists(false)
+ , mResoveSymLinks(resolveSymLinks)
+ , mIndex(-1)
+{
+ CInfoPBRec pb;
+ OSErr err = inDirectory.GetCatInfo(pb);
+
+ // test that we have got a directory back, not a file
+ DirInfo* dipb = (DirInfo*)&pb;
+ if (err != noErr || !( dipb->ioFlAttrib & 0x0010))
+ return;
+ // Sorry about this, there seems to be a bug in CWPro 4:
+ FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
+ mVRefNum = currentSpec.vRefNum;
+ mParID = dipb->ioDrDirID;
+ mMaxIndex = pb.dirInfo.ioDrNmFls;
+ mIndex = 0; // ready to increment
+ ++(*this); // the pre-increment operator
+
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+OSErr nsDirectoryIterator::SetToIndex()
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cipb;
+ DirInfo *dipb=(DirInfo *)&cipb;
+ Str255 objectName;
+ dipb->ioCompletion = nsnull;
+ dipb->ioFDirIndex = mIndex;
+ // Sorry about this, there seems to be a bug in CWPro 4:
+ FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
+ dipb->ioVRefNum = mVRefNum; /* Might need to use vRefNum, not sure*/
+ dipb->ioDrDirID = mParID;
+ dipb->ioNamePtr = objectName;
+ OSErr err = PBGetCatInfoSync(&cipb);
+ FSSpec temp;
+ if (err == noErr)
+ err = FSMakeFSSpec(mVRefNum, mParID, objectName, &temp);
+ mCurrent = temp; // use the operator: it clears the string cache.
+ mExists = err == noErr;
+
+ if (mExists && mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ return err;
+} // nsDirectoryIterator::SetToIndex()
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = false;
+ while (--mIndex > 0)
+ {
+ OSErr err = SetToIndex();
+ if (err == noErr)
+ break;
+ }
+ return *this;
+} // nsDirectoryIterator::operator --
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = false;
+ if (mIndex >= 0) // probably trying to use a file as a directory!
+ while (++mIndex <= mMaxIndex)
+ {
+ OSErr err = SetToIndex();
+ if (err == noErr)
+ break;
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp
new file mode 100644
index 00000000..4621d8b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp
@@ -0,0 +1,840 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla OS/2 libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * John Fairhurst, <john_fairhurst@iname.com>.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.com>
+ * 00/01/06: general review and update against Win/Unix versions;
+ * replaced nsFileSpec::Execute implementation with system() call
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 03/23/2000 IBM Corp. Fixed bug where 2 char or less profile names treated as drive letters.
+ * 06/20/2000 IBM Corp. Make it more like Windows version.
+ */
+
+#define INCL_DOSERRORS
+#define INCL_DOS
+#define INCL_WINWORKPLACE
+#include <os2.h>
+
+#ifdef XP_OS2_VACPP
+#include <direct.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <ctype.h>
+#include <io.h>
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist. This
+// takes a (possibly relative) native path and converts it into a
+// fully qualified native path.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
+ "This smells like a Unix path. Native path expected! "
+ "Please fix.");
+ if (inMakeDirs)
+ {
+ const int mode = 0700;
+ nsSimpleCharString unixStylePath = ioPath;
+ nsFileSpecHelpers::NativeToUnix(unixStylePath);
+ nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
+ }
+ char buffer[_MAX_PATH];
+ errno = 0;
+ *buffer = '\0';
+#ifdef XP_OS2
+ PRBool removedBackslash = PR_FALSE;
+ PRUint32 lenstr = ioPath.Length();
+ char &lastchar = ioPath[lenstr -1];
+
+ // Strip off any trailing backslash UNLESS it's the backslash that
+ // comes after "X:". Note also that "\" is valid. Sheesh.
+ //
+ if( lastchar == '\\' && (lenstr != 3 || ioPath[1] != ':') && lenstr != 1)
+ {
+ lastchar = '\0';
+ removedBackslash = PR_TRUE;
+ }
+
+ char canonicalPath[CCHMAXPATH] = "";
+
+ DosQueryPathInfo( (char*) ioPath,
+ FIL_QUERYFULLNAME,
+ canonicalPath,
+ CCHMAXPATH);
+#else
+ char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
+#endif
+
+ if (canonicalPath)
+ {
+ NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
+ if (canonicalPath[0] == '\0')
+ return;
+#ifdef XP_OS2
+ // If we removed that backslash, add it back onto the fullpath
+ if (removedBackslash)
+ strcat( canonicalPath, "\\");
+#endif
+ }
+ ioPath = canonicalPath;
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything
+//----------------------------------------------------------------------------------------
+{
+ // Allow for relative or absolute. We can do this in place, because the
+ // native path is never longer.
+
+ if (ioPath.IsEmpty())
+ return;
+
+ // Strip initial slash for an absolute path
+ char* src = (char*)ioPath;
+ if (*src == '/') {
+ if (!src[1]) {
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ return;
+ }
+ // Since it was an absolute path, check for the drive letter
+ char* colonPointer = src + 2;
+ if (strstr(src, "|/") == colonPointer)
+ *colonPointer = ':';
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ }
+
+ src = (char*)ioPath;
+
+ if (*src) {
+ // Convert '/' to '\'.
+ while (*++src)
+ {
+ if (*src == '/')
+ *src = '\\';
+ }
+ }
+} // nsFileSpecHelpers::UnixToNative
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything. The unix path is longer, so we can't do it in place.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ // Convert the drive-letter separator, if present
+ nsSimpleCharString temp("/");
+
+ char* cp = (char*)ioPath + 1;
+ if (strstr(cp, ":\\") == cp)
+ *cp = '|'; // absolute path
+ else
+ temp[0] = '\0'; // relative path
+
+ // Convert '\' to '/'
+ for (; *cp; cp++)
+ {
+#ifdef XP_OS2
+ // OS2TODO - implement equivalent of IsDBCSLeadByte
+#else
+ if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
+ {
+ cp++;
+ continue;
+ }
+#endif
+ if (*cp == '\\')
+ *cp = '/';
+ }
+ // Add the slash in front.
+ temp += ioPath;
+ ioPath = temp;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ *this = inPath;
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inPath;
+ nsFileSpecHelpers::UnixToNative(mPath);
+ mError = NS_OK;
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+} // nsFilePath::nsFilePath
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inSpec.mPath;
+ nsFileSpecHelpers::NativeToUnix(mPath);
+} // nsFilePath::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
+ mPath.LeafReplace('\\', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath.GetLeaf('\\');
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+#ifdef XP_OS2
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && ( S_IFREG & st.st_mode);
+#else
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
+#endif
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+#ifdef XP_OS2
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && ( S_IFDIR & st.st_mode);
+#else
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
+#endif
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_FALSE;
+ if (!mPath.IsEmpty())
+ {
+#ifdef XP_OS2
+ FILESTATUS3 fs3;
+ APIRET rc;
+
+ rc = DosQueryPathInfo( mPath,
+ FIL_STANDARD,
+ &fs3,
+ sizeof fs3);
+ if(!rc)
+ hidden = fs3.attrFile & FILE_HIDDEN ? PR_TRUE : PR_FALSE;
+#else
+ DWORD attr = GetFileAttributes(mPath);
+ if (FILE_ATTRIBUTE_HIDDEN & attr)
+ hidden = PR_TRUE;
+#endif
+ }
+ return hidden;
+}
+// nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+#ifdef XP_OS2
+ return PR_FALSE; // No symlinks on OS/2
+#else
+ HRESULT hres;
+ IShellLink* psl;
+
+ PRBool isSymlink = PR_FALSE;
+
+ CoInitialize(NULL);
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WORD wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ isSymlink = PR_TRUE;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ return isSymlink;
+#endif
+}
+
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
+//----------------------------------------------------------------------------------------
+{
+#ifdef XP_OS2
+ return NS_OK; // no symlinks on OS/2
+#else
+ wasSymlink = PR_FALSE; // assume failure
+
+ if (Exists())
+ return NS_OK;
+
+
+ HRESULT hres;
+ IShellLink* psl;
+
+ CoInitialize(NULL);
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WORD wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ wasSymlink = PR_TRUE;
+
+ // Resolve the link.
+ hres = psl->Resolve(nsnull, SLR_NO_UI );
+ if (SUCCEEDED(hres))
+ {
+ char szGotPath[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+
+ // Get the path to the link target.
+ hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
+
+ if (SUCCEEDED(hres))
+ {
+ // Here we modify the nsFileSpec;
+ mPath = szGotPath;
+ mError = NS_OK;
+ }
+ }
+ }
+ else {
+ // It wasn't a shortcut. Oh well. Leave it like it was.
+ hres = 0;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ if (SUCCEEDED(hres))
+ return NS_OK;
+
+ return NS_FILE_FAILURE;
+#endif
+}
+
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '\\');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
+
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ if (mPath[mPath.Length() - 1] == '\\')
+ mPath += "x";
+ else
+ mPath += "\\x";
+
+ // If it's a (unix) relative path, make it native
+ nsSimpleCharString dosPath = inRelativePath;
+ nsFileSpecHelpers::UnixToNative(dosPath);
+ SetLeafName(dosPath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int /*mode*/)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (!mPath.IsEmpty())
+#ifdef XP_OS2
+ // OS2TODO - vacpp complains about mkdir but PR_MkDir should be ok?
+ PR_MkDir(nsNSPRPath(*this), PR_CREATE_FILE);
+#else
+ mkdir(nsNSPRPath(*this));
+#endif
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = i.Spec();
+ child.Delete(inRecursive);
+ }
+ }
+#ifdef XP_OS2
+ // OS2TODO - vacpp complains if use rmdir but PR_RmDir should be ok?
+ PR_RmDir(nsNSPRPath(*this));
+#else
+ rmdir(nsNSPRPath(*this));
+#endif
+ }
+ else if (!mPath.IsEmpty())
+ {
+ remove(nsNSPRPath(*this));
+ }
+} // nsFileSpec::Delete
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = i.Spec();
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult
+nsFileSpec::Truncate(PRInt32 aNewFileLength) const
+//----------------------------------------------------------------------------------------
+{
+#ifdef XP_OS2
+ APIRET rc;
+ HFILE hFile;
+ ULONG actionTaken;
+
+ rc = DosOpen(mPath,
+ &hFile,
+ &actionTaken,
+ 0,
+ FILE_NORMAL,
+ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
+ NULL);
+
+ if (rc != NO_ERROR)
+ return NS_FILE_FAILURE;
+
+ rc = DosSetFileSize(hFile, aNewFileLength);
+
+ if (rc == NO_ERROR)
+ DosClose(hFile);
+ else
+ goto error;
+#else
+ DWORD status;
+ HANDLE hFile;
+
+ // Leave it to Microsoft to open an existing file with a function
+ // named "CreateFile".
+ hFile = CreateFile(mPath,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NS_FILE_FAILURE;
+
+ // Seek to new, desired end of file
+ status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
+ if (status == 0xffffffff)
+ goto error;
+
+ // Truncate file at current cursor position
+ if (!SetEndOfFile(hFile))
+ goto error;
+
+ if (!CloseHandle(hFile))
+ return NS_FILE_FAILURE;
+#endif
+
+ return NS_OK;
+
+ error:
+#ifdef XP_OS2
+ DosClose(hFile);
+#else
+ CloseHandle(hFile);
+#endif
+ return NS_FILE_FAILURE;
+
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
+
+ // This function should not be used to move a file on disk.
+ if (strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ // CopyFile returns non-zero if succeeds
+#ifdef XP_OS2
+ APIRET rc;
+ PRBool copyOK;
+
+ rc = DosCopy(GetCString(), (PSZ)destPath, DCPY_EXISTING);
+
+ if (rc == NO_ERROR)
+ copyOK = PR_TRUE;
+ else
+ copyOK = PR_FALSE;
+#else
+ int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
+#endif
+ if (copyOK)
+ return NS_OK;
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ if (DosMove(GetCString(), destPath) == NO_ERROR)
+ {
+ *this = inNewParentDirectory + GetLeafName();
+ return NS_OK;
+ }
+
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::MoveToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ if (!IsDirectory())
+ {
+#ifdef XP_OS2
+ nsresult result = NS_FILE_FAILURE;
+
+ if (!mPath.IsEmpty())
+ {
+ nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;
+ result = NS_FILE_RESULT(system(fileNameWithArgs));
+ }
+ return result;
+#else
+ nsSimpleCharString fileNameWithArgs = "\"";
+ fileNameWithArgs += mPath + "\" " + inArgs;
+ int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
+ if (execResult > 31)
+ return NS_OK;
+#endif
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::Execute
+
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 nBytes = 0;
+ ULONG ulDriveNo = toupper(mPath[0]) + 1 - 'A';
+ FSALLOCATE fsAllocate;
+ APIRET rc = DosQueryFSInfo(ulDriveNo,
+ FSIL_ALLOC,
+ &fsAllocate,
+ sizeof(fsAllocate));
+
+ if (rc == NO_ERROR) {
+ nBytes = fsAllocate.cUnitAvail;
+ nBytes *= fsAllocate.cSectorUnit;
+ nBytes *= fsAllocate.cbSector;
+ }
+
+ return nBytes;
+}
+
+
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mDir(nsnull)
+ , mStarting(inDirectory)
+ , mExists(PR_FALSE)
+ , mResoveSymLinks(resolveSymlink)
+{
+ mDir = PR_OpenDir(inDirectory);
+ mCurrent += "dummy";
+ mStarting += "dummy";
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ PR_CloseDir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting;
+ mCurrent.SetLeafName(entry->name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp
new file mode 100644
index 00000000..8acb6330
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp
@@ -0,0 +1,703 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file is included by nsFileSpec.cpp, and includes the Unix-specific
+// implementations.
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "xpcom-private.h"
+#include "nsError.h"
+#include "prio.h" /* for PR_Rename */
+#include "nsAutoBuffer.h"
+
+#if defined(_SCO_DS)
+#define _SVID3 /* for statvfs.h */
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#undef Free
+#endif
+
+#ifdef HAVE_STATVFS
+#define STATFS statvfs
+#else
+#define STATFS statfs
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024 /* Guessing this is okay. Works for SCO. */
+#endif
+
+#if defined(__QNX__)
+#include <unix.h> /* for realpath */
+#define f_bavail f_bfree
+extern "C" int truncate(const char *, off_t);
+#endif
+
+#if defined(SUNOS4)
+extern "C" int statfs(char *, struct statfs *);
+#endif
+
+#if defined(OSF1)
+extern "C" int statvfs(const char *, struct statvfs *);
+#endif
+
+#ifdef XP_MACOSX
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+ if (inMakeDirs)
+ {
+ const mode_t mode = 0700;
+ nsFileSpecHelpers::MakeAllDirectories((const char*)ioPath, mode);
+ }
+
+ errno = 0; // needed?
+
+ if (ioPath[0] != '/')
+ {
+ // the ioPath that was passed in is relative. We must cat it to the cwd.
+ char buffer[MAXPATHLEN];
+
+ (void) getcwd(buffer, MAXPATHLEN);
+
+ strcat(buffer, "/");
+ strcat(buffer, ioPath);
+
+ ioPath = buffer;
+ }
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mPath.LeafReplace('/', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+#ifndef XP_MACOSX
+ return mPath.GetLeaf('/');
+#else
+ char *name = mPath.GetLeaf('/');
+ if (!name || !*name)
+ return name;
+ nsAutoString nameInNFC;
+ CopyUTF8toUTF16NFC(nsDependentCString(name), nameInNFC);
+ nsCRT::free(name);
+ return nsCRT::strdup(NS_ConvertUTF16toUTF8(nameInNFC).get());
+#endif
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISREG(st.st_mode);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_FALSE;
+ char *leafname = GetLeafName();
+ if (nsnull != leafname)
+ {
+ // rjc: don't return ".", "..", or any file/directory that begins with a "."
+
+ /* if ((!strcmp(leafname, ".")) || (!strcmp(leafname, ".."))) */
+ if (leafname[0] == '.')
+ {
+ hidden = PR_TRUE;
+ }
+ nsCRT::free(leafname);
+ }
+ return hidden;
+} // nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISLNK(st.st_mode))
+ return PR_TRUE;
+
+ return PR_FALSE;
+} // nsFileSpec::IsSymlink
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ wasAliased = PR_FALSE;
+
+ char resolvedPath[MAXPATHLEN];
+ int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN);
+ if (0 < charCount)
+ {
+ if (MAXPATHLEN > charCount)
+ resolvedPath[charCount] = '\0';
+
+ wasAliased = PR_TRUE;
+
+ /* if it's not an absolute path,
+ replace the leaf with what got resolved */
+ if (resolvedPath[0] != '/') {
+ SetLeafName(resolvedPath);
+ }
+ else {
+ mPath = (char*)&resolvedPath;
+ }
+
+ char* canonicalPath = realpath((const char *)mPath, resolvedPath);
+ NS_ASSERTION(canonicalPath, "realpath failed");
+ if (canonicalPath) {
+ mPath = (char*)&resolvedPath;
+ }
+ else {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ return NS_OK;
+} // nsFileSpec::ResolveSymlink
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '/');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
+
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ char endChar = mPath[(int)(strlen(mPath) - 1)];
+ if (endChar == '/')
+ mPath += "x";
+ else
+ mPath += "/x";
+ SetLeafName(inRelativePath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int mode)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (mPath.IsEmpty())
+ return;
+ mkdir(mPath, mode);
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+// To check if this worked, call Exists() afterwards, see?
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+ child.Delete(inRecursive);
+ }
+ }
+ rmdir(mPath);
+ }
+ else if (!mPath.IsEmpty())
+ remove(mPath);
+} // nsFileSpec::Delete
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Truncate(PRInt32 offset) const
+//----------------------------------------------------------------------------------------
+{
+ char* Path = nsCRT::strdup(mPath);
+
+ int rv = truncate(Path, offset) ;
+
+ nsCRT::free(Path) ;
+
+ if(!rv)
+ return NS_OK ;
+ else
+ return NS_ERROR_FAILURE ;
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
+
+ // This function should not be used to move a file on disk.
+ if (mPath.IsEmpty() || strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+static int CrudeFileCopy(const char* in, const char* out)
+//----------------------------------------------------------------------------------------
+{
+ struct stat in_stat;
+ int stat_result = -1;
+
+ char buf [1024];
+ FILE *ifp, *ofp;
+ int rbytes, wbytes;
+
+ if (!in || !out)
+ return -1;
+
+ stat_result = stat (in, &in_stat);
+
+ ifp = fopen (in, "r");
+ if (!ifp)
+ {
+ return -1;
+ }
+
+ ofp = fopen (out, "w");
+ if (!ofp)
+ {
+ fclose (ifp);
+ return -1;
+ }
+
+ while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0)
+ {
+ while (rbytes > 0)
+ {
+ if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 )
+ {
+ fclose (ofp);
+ fclose (ifp);
+ unlink(out);
+ return -1;
+ }
+ rbytes -= wbytes;
+ }
+ }
+ fclose (ofp);
+ fclose (ifp);
+
+ if (stat_result == 0)
+ chmod (out, in_stat.st_mode & 0777);
+
+ return 0;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath));
+ }
+ return result;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inNewParentDirectory.IsDirectory() && !IsDirectory())
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), (const char*)destPath));
+ if (result == NS_OK)
+ {
+ // cast to fix const-ness
+ ((nsFileSpec*)this)->Delete(PR_FALSE);
+
+ *this = inNewParentDirectory + GetLeafName();
+ }
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_FILE_FAILURE;
+
+ if (!mPath.IsEmpty() && !IsDirectory())
+ {
+ nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;
+ result = NS_FILE_RESULT(system(fileNameWithArgs));
+ }
+
+ return result;
+
+} // nsFileSpec::Execute
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 bytes; /* XXX dougt needs to fix this */
+ LL_I2L(bytes , LONG_MAX); // initialize to all the space in the world?
+
+
+#if defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_STATVFS_H)
+
+ char curdir [MAXPATHLEN];
+ if (mPath.IsEmpty())
+ {
+ (void) getcwd(curdir, MAXPATHLEN);
+ if (!curdir)
+ return bytes; /* hope for the best as we did in cheddar */
+ }
+ else
+ sprintf(curdir, "%.200s", (const char*)mPath);
+
+ struct STATFS fs_buf;
+#if defined(__QNX__) && !defined(HAVE_STATVFS) /* Maybe this should be handled differently? */
+ if (STATFS(curdir, &fs_buf, 0, 0) < 0)
+#else
+ if (STATFS(curdir, &fs_buf) < 0)
+#endif
+ return bytes; /* hope for the best as we did in cheddar */
+
+#ifdef DEBUG_DISK_SPACE
+ printf("DiskSpaceAvailable: %d bytes\n",
+ fs_buf.f_bsize * (fs_buf.f_bavail - 1));
+#endif
+
+ PRInt64 bsize,bavail;
+ LL_I2L( bsize, fs_buf.f_bsize );
+ LL_I2L( bavail, fs_buf.f_bavail - 1 );
+ LL_MUL( bytes, bsize, bavail );
+ return bytes;
+
+#else
+ /*
+ ** This platform doesn't have statfs or statvfs, so we don't have much
+ ** choice but to "hope for the best as we did in cheddar".
+ */
+ return bytes;
+#endif /* HAVE_SYS_STATFS_H or HAVE_SYS_STATVFS_H */
+
+} // nsFileSpec::GetDiskSpace()
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymLinks)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mExists(PR_FALSE)
+ , mResoveSymLinks(resolveSymLinks)
+ , mStarting(inDirectory)
+ , mDir(nsnull)
+
+{
+ mStarting += "sysygy"; // save off the starting directory
+ mCurrent += "sysygy"; // prepare the path for SetLeafName
+ mDir = opendir((const char*)nsFilePath(inDirectory));
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ closedir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ const char dot[] = ".";
+ const char dotdot[] = "..";
+ struct dirent* entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dot) == 0)
+ entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dotdot) == 0)
+ entry = readdir(mDir);
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting; // restore mCurrent to be the starting directory. ResolveSymlink() may have taken us to another directory
+ mCurrent.SetLeafName(entry->d_name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
+
+// Convert a UTF-8 string to a UTF-16 string while normalizing to
+// Normalization Form C (composed Unicode). We need this because
+// Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode)
+// while most other OS', server-side programs usually expect NFC.
+
+#ifdef XP_MACOSX
+typedef void (*UnicodeNormalizer) (CFMutableStringRef, CFStringNormalizationForm);
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult)
+{
+ static PRBool sChecked = PR_FALSE;
+ static UnicodeNormalizer sUnicodeNormalizer = NULL;
+
+ // CFStringNormalize was not introduced until Mac OS 10.2
+ if (!sChecked) {
+ CFBundleRef carbonBundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon"));
+ if (carbonBundle)
+ sUnicodeNormalizer = (UnicodeNormalizer)
+ ::CFBundleGetFunctionPointerForName(carbonBundle,
+ CFSTR("CFStringNormalize"));
+ sChecked = PR_TRUE;
+ }
+
+ if (!sUnicodeNormalizer) { // OS X 10.1 or earlier
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc);
+
+ // The number of 16bit code units in a UTF-16 string will never be
+ // larger than the number of bytes in the corresponding UTF-8 string.
+ CFMutableStringRef inStr =
+ ::CFStringCreateMutable(NULL, inFlatSrc.Length());
+
+ if (!inStr) {
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8);
+
+ sUnicodeNormalizer(inStr, kCFStringNormalizationFormC);
+
+ CFIndex length = CFStringGetLength(inStr);
+ const UniChar* chars = CFStringGetCharactersPtr(inStr);
+
+ if (chars)
+ aResult.Assign(chars, length);
+ else {
+ nsAutoBuffer<UniChar, 512> buffer;
+ if (buffer.EnsureElemCapacity(length)) {
+ CFStringGetCharacters(inStr, CFRangeMake(0, length), buffer.get());
+ aResult.Assign(buffer.get(), length);
+ }
+ else
+ CopyUTF8toUTF16(aSrc, aResult);
+ }
+ CFRelease(inStr);
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp
new file mode 100644
index 00000000..7d7e863d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp
@@ -0,0 +1,766 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file is included by nsFileSpec.cp, and includes the Windows-specific
+// implementations.
+
+#include <sys/stat.h>
+#include <direct.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "prio.h"
+#include "nsError.h"
+
+#include <windows.h>
+
+#if (_MSC_VER == 1100) || defined(__GNUC__)
+#define INITGUID
+#include <objbase.h>
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
+#endif
+
+#include <shlobj.h>
+#include <shellapi.h>
+#include <shlguid.h>
+
+#ifdef UNICODE
+#define CreateDirectoryW CreateDirectory
+#else
+#define CreateDirectoryA CreateDirectory
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist. This
+// takes a (possibly relative) native path and converts it into a
+// fully qualified native path.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
+ "This smells like a Unix path. Native path expected! "
+ "Please fix.");
+ if (inMakeDirs)
+ {
+ const int mode = 0755;
+ nsSimpleCharString unixStylePath = ioPath;
+ nsFileSpecHelpers::NativeToUnix(unixStylePath);
+ nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
+ }
+ char buffer[_MAX_PATH];
+ errno = 0;
+ *buffer = '\0';
+ char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
+
+ if (canonicalPath)
+ {
+ NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
+ if (canonicalPath[0] == '\0')
+ return;
+ }
+ ioPath = canonicalPath;
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything
+//----------------------------------------------------------------------------------------
+{
+ // Allow for relative or absolute. We can do this in place, because the
+ // native path is never longer.
+
+ if (ioPath.IsEmpty())
+ return;
+
+ // Strip initial slash for an absolute path
+ char* src = (char*)ioPath;
+ if (*src == '/') {
+ if (!src[1]) {
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ return;
+ }
+ // Since it was an absolute path, check for the drive letter
+ char* colonPointer = src + 2;
+ if (strstr(src, "|/") == colonPointer)
+ *colonPointer = ':';
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ }
+
+ // Convert '/' to '\'. (Must check EVERY character: consider UNC path
+ // case.)
+ for (src = (char*)ioPath; *src; ++src)
+ {
+ if (*src == '/')
+ *src = '\\';
+ }
+
+} // nsFileSpecHelpers::UnixToNative
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything. The unix path is longer, so we can't do it in place.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ // Convert the drive-letter separator, if present
+ nsSimpleCharString temp("/");
+
+ char* cp = (char*)ioPath + 1;
+ if (strstr(cp, ":\\") == cp)
+ *cp = '|'; // absolute path
+ else
+ if (cp[0] == '\\') // unc path
+ cp--;
+ else
+ temp[0] = '\0'; // relative path
+
+ // Convert '\' to '/'
+ for (; *cp; cp++)
+ {
+ if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
+ {
+ cp++;
+ continue;
+ }
+ if (*cp == '\\')
+ *cp = '/';
+ }
+ // Add the slash in front.
+ temp += ioPath;
+ ioPath = temp;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ *this = inPath;
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inPath;
+ nsFileSpecHelpers::UnixToNative(mPath);
+ mError = NS_OK;
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+} // nsFilePath::nsFilePath
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inSpec.mPath;
+ nsFileSpecHelpers::NativeToUnix(mPath);
+} // nsFilePath::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
+ mPath.LeafReplace('\\', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath.GetLeaf('\\');
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_FALSE;
+ if (!mPath.IsEmpty())
+ {
+ DWORD attr = GetFileAttributes(mPath);
+ if (FILE_ATTRIBUTE_HIDDEN & attr)
+ hidden = PR_TRUE;
+ }
+ return hidden;
+}
+// nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ HRESULT hres;
+ IShellLink* psl;
+
+ PRBool isSymlink = PR_FALSE;
+
+ CoInitialize(NULL);
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WCHAR wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ isSymlink = PR_TRUE;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ return isSymlink;
+}
+
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
+//----------------------------------------------------------------------------------------
+{
+ wasSymlink = PR_FALSE; // assume failure
+
+ if (Exists())
+ return NS_OK;
+
+
+ HRESULT hres;
+ IShellLink* psl;
+
+ CoInitialize(NULL);
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WCHAR wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ wasSymlink = PR_TRUE;
+
+ // Resolve the link.
+ hres = psl->Resolve(nsnull, SLR_NO_UI );
+ if (SUCCEEDED(hres))
+ {
+ char szGotPath[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+
+ // Get the path to the link target.
+ hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
+
+ if (SUCCEEDED(hres))
+ {
+ // Here we modify the nsFileSpec;
+ mPath = szGotPath;
+ mError = NS_OK;
+ }
+ }
+ }
+ else {
+ // It wasn't a shortcut. Oh well. Leave it like it was.
+ hres = 0;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ if (SUCCEEDED(hres))
+ return NS_OK;
+
+ return NS_FILE_FAILURE;
+}
+
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '\\');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
+
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ if (mPath[mPath.Length() - 1] == '\\')
+ mPath += "x";
+ else
+ mPath += "\\x";
+
+ // If it's a (unix) relative path, make it native
+ nsSimpleCharString dosPath = inRelativePath;
+ nsFileSpecHelpers::UnixToNative(dosPath);
+ SetLeafName(dosPath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int /*mode*/)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (!mPath.IsEmpty())
+ mkdir(nsNSPRPath(*this));
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+ child.Delete(inRecursive);
+ }
+ }
+ rmdir(nsNSPRPath(*this));
+ }
+ else if (!mPath.IsEmpty())
+ {
+ remove(nsNSPRPath(*this));
+ }
+} // nsFileSpec::Delete
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult
+nsFileSpec::Truncate(PRInt32 aNewFileLength) const
+//----------------------------------------------------------------------------------------
+{
+ DWORD status;
+ HANDLE hFile;
+
+ // Leave it to Microsoft to open an existing file with a function
+ // named "CreateFile".
+ hFile = CreateFile(mPath,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NS_FILE_FAILURE;
+
+ // Seek to new, desired end of file
+ status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
+ if (status == 0xffffffff)
+ goto error;
+
+ // Truncate file at current cursor position
+ if (!SetEndOfFile(hFile))
+ goto error;
+
+ if (!CloseHandle(hFile))
+ return NS_FILE_FAILURE;
+
+ return NS_OK;
+
+ error:
+ CloseHandle(hFile);
+ return NS_FILE_FAILURE;
+
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
+
+ // This function should not be used to move a file on disk.
+ if (strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ // CopyFile returns non-zero if succeeds
+ int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
+ if (copyOK)
+ return NS_OK;
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ // MoveFile returns non-zero if succeeds
+ int copyOK = MoveFile(GetCString(), destPath);
+
+ if (copyOK)
+ {
+ *this = inNewParentDirectory + GetLeafName();
+ return NS_OK;
+ }
+
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::MoveToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ if (!IsDirectory())
+ {
+ nsSimpleCharString fileNameWithArgs = "\"";
+ fileNameWithArgs += mPath + "\" " + inArgs;
+ int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
+ if (execResult > 31)
+ return NS_OK;
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::Execute
+
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 int64;
+
+ LL_I2L(int64 , LONG_MAX);
+
+ char aDrive[_MAX_DRIVE + 2];
+ _splitpath( (const char*)mPath, aDrive, NULL, NULL, NULL);
+
+ if (aDrive[0] == '\0')
+ {
+ // The back end is always trying to pass us paths that look
+ // like /c|/netscape/mail. See if we've got one of them
+ if (mPath.Length() > 2 && mPath[0] == '/' && mPath[2] == '|')
+ {
+ aDrive[0] = mPath[1];
+ aDrive[1] = ':';
+ aDrive[2] = '\0';
+ }
+ else
+ {
+ // Return bogus large number and hope for the best
+ return int64;
+ }
+ }
+
+ strcat(aDrive, "\\");
+
+ // Check disk space
+ DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
+ ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes, liTotalNumberOfFreeBytes;
+ double nBytes = 0;
+
+ BOOL (WINAPI* getDiskFreeSpaceExA)(LPCTSTR lpDirectoryName,
+ PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+ PULARGE_INTEGER lpTotalNumberOfBytes,
+ PULARGE_INTEGER lpTotalNumberOfFreeBytes) = NULL;
+
+ HINSTANCE hInst = LoadLibrary("KERNEL32.DLL");
+ NS_ASSERTION(hInst != NULL, "COULD NOT LOAD KERNEL32.DLL");
+ if (hInst != NULL)
+ {
+ getDiskFreeSpaceExA = (BOOL (WINAPI*)(LPCTSTR lpDirectoryName,
+ PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+ PULARGE_INTEGER lpTotalNumberOfBytes,
+ PULARGE_INTEGER lpTotalNumberOfFreeBytes))
+ GetProcAddress(hInst, "GetDiskFreeSpaceExA");
+ FreeLibrary(hInst);
+ }
+
+ if (getDiskFreeSpaceExA && (*getDiskFreeSpaceExA)(aDrive,
+ &liFreeBytesAvailableToCaller,
+ &liTotalNumberOfBytes,
+ &liTotalNumberOfFreeBytes))
+ {
+ nBytes = (double)(signed __int64)liFreeBytesAvailableToCaller.QuadPart;
+ }
+ else if ( GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
+ {
+ nBytes = (double)dwFreeClus*(double)dwSecPerClus*(double) dwBytesPerSec;
+ }
+ return (PRInt64)nBytes;
+}
+
+
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mDir(nsnull)
+ , mStarting(inDirectory)
+ , mExists(PR_FALSE)
+ , mResoveSymLinks(resolveSymlink)
+{
+ mDir = PR_OpenDir(inDirectory);
+ mCurrent += "dummy";
+ mStarting += "dummy";
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ PR_CloseDir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting;
+ mCurrent.SetLeafName(entry->name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp
new file mode 100644
index 00000000..f20c60e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp
@@ -0,0 +1,392 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// First checked in on 98/12/08 by John R. McMullen.
+// Since nsFileStream.h is entirely templates, common code (such as open())
+// which does not actually depend on the charT, can be placed here.
+
+#include "nsFileStream.h"
+#include "nsFileSpec.h"
+#include "nsIFileSpec.h"
+#include "nsIStringStream.h"
+#include "nsInt64.h"
+#include <string.h>
+#include <stdio.h>
+
+
+//========================================================================================
+// nsInputStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsInputStream::~nsInputStream()
+//----------------------------------------------------------------------------------------
+{
+}
+
+//----------------------------------------------------------------------------------------
+char nsInputStream::get()
+//----------------------------------------------------------------------------------------
+{
+ char c;
+ if (read(&c, sizeof(c)) == sizeof(c))
+ return c;
+ return 0;
+}
+
+//----------------------------------------------------------------------------------------
+PRInt32 nsInputStream::read(void* s, PRInt32 n)
+//----------------------------------------------------------------------------------------
+{
+ if (!mInputStream)
+ return 0;
+ PRInt32 result = 0;
+ mInputStream->Read((char*)s, n, (PRUint32*)&result);
+ if (result == 0)
+ set_at_eof(PR_TRUE);
+ return result;
+} // nsInputStream::read
+
+//----------------------------------------------------------------------------------------
+static void TidyEndOfLine(char*& cp)
+// Assumes that cp is pointing at \n or \r. Nulls out the character, checks for
+// a second terminator (of the opposite persuasion), and returns cp pointing past the
+// entire eol construct (one or two characters).
+//----------------------------------------------------------------------------------------
+{
+ char ch = *cp;
+ *cp++ = '\0'; // terminate at the newline, then skip past it
+ if ((ch == '\n' && *cp == '\r') || (ch == '\r' && *cp == '\n'))
+ cp++; // possibly a pair.
+}
+
+//----------------------------------------------------------------------------------------
+nsInputStream& nsInputStream::operator >> (char& c)
+//----------------------------------------------------------------------------------------
+{
+ c = get();
+ return *this;
+}
+
+//========================================================================================
+// nsOutputStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsOutputStream::~nsOutputStream()
+//----------------------------------------------------------------------------------------
+{
+}
+
+//----------------------------------------------------------------------------------------
+void nsOutputStream::put(char c)
+//----------------------------------------------------------------------------------------
+{
+ write(&c, sizeof(c));
+}
+
+//----------------------------------------------------------------------------------------
+PRInt32 nsOutputStream::write(const void* s, PRInt32 n)
+//----------------------------------------------------------------------------------------
+{
+ if (!mOutputStream)
+ return 0;
+ PRInt32 result = 0;
+ mWriteStatus = mOutputStream->Write((char*)s, n, (PRUint32*)&result);
+ return result;
+} // nsOutputStream::write
+
+//----------------------------------------------------------------------------------------
+nsresult nsOutputStream::flush()
+//----------------------------------------------------------------------------------------
+{
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsOutputStream::lastWriteStatus()
+//----------------------------------------------------------------------------------------
+{
+ return mWriteStatus;
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (char c)
+//----------------------------------------------------------------------------------------
+{
+ put(c);
+ return *this;
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (const char* s)
+//----------------------------------------------------------------------------------------
+{
+ if (s)
+ write(s, strlen(s));
+ return *this;
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (short val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%hd", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (unsigned short val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%hu", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (long val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%ld", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (unsigned long val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%lu", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (int val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%d", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (unsigned int val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%u", val);
+ return (*this << buf);
+}
+
+//========================================================================================
+// nsRandomAccessInputStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+PRBool nsRandomAccessInputStream::readline(char* s, PRInt32 n)
+// This will truncate if the buffer is too small. Result will always be null-terminated.
+//----------------------------------------------------------------------------------------
+{
+ PRBool bufferLargeEnough = PR_TRUE; // result
+ if (!s || !n)
+ return PR_TRUE;
+
+ nsInt64 position = tell();
+ const nsInt64 zero(0);
+ if (position < zero)
+ return PR_FALSE;
+ PRInt32 bytesRead = read(s, n - 1);
+ if (failed())
+ return PR_FALSE;
+ s[bytesRead] = '\0'; // always terminate at the end of the buffer
+ char* tp = strpbrk(s, "\n\r");
+ if (tp)
+ {
+ TidyEndOfLine(tp);
+ bytesRead = (tp - s);
+ }
+ else if (!eof() && n-1 == bytesRead)
+ bufferLargeEnough = PR_FALSE;
+ position += bytesRead;
+ seek(position);
+ return bufferLargeEnough;
+} // nsRandomAccessInputStream::readline
+
+//========================================================================================
+// nsInputStringStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsInputStringStream::nsInputStringStream(const char* stringToRead)
+//----------------------------------------------------------------------------------------
+{
+ nsCOMPtr<nsIInputStream> stream;
+ if (NS_FAILED(NS_NewCharInputStream(getter_AddRefs(stream), stringToRead)))
+ return;
+ mInputStream = stream;
+ mStore = do_QueryInterface(stream);
+}
+
+//----------------------------------------------------------------------------------------
+nsInputStringStream::nsInputStringStream(const nsString& stringToRead)
+//----------------------------------------------------------------------------------------
+{
+ if (NS_FAILED(NS_NewStringInputStream(getter_AddRefs(mInputStream), stringToRead)))
+ return;
+ mStore = do_QueryInterface(mInputStream);
+}
+
+
+//========================================================================================
+// nsInputFileStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsInputFileStream::nsInputFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode)
+//----------------------------------------------------------------------------------------
+{
+ nsISupports* stream;
+ if (NS_FAILED(NS_NewIOFileStream(&stream, inFile, nsprMode, accessMode)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+} // nsInputFileStream::nsInputFileStream
+
+//----------------------------------------------------------------------------------------
+nsInputFileStream::nsInputFileStream(nsIFileSpec* inSpec)
+//----------------------------------------------------------------------------------------
+{
+ nsIInputStream* stream;
+ if (NS_FAILED(inSpec->GetInputStream(&stream)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+} // nsInputFileStream::nsInputFileStream
+
+//----------------------------------------------------------------------------------------
+nsInputFileStream::~nsInputFileStream()
+//----------------------------------------------------------------------------------------
+{
+// if (is_open())
+// close();
+}
+
+//----------------------------------------------------------------------------------------
+void nsInputFileStream::AssignFrom(nsISupports* stream)
+//----------------------------------------------------------------------------------------
+{
+ mFile = do_QueryInterface(stream);
+ mInputStream = do_QueryInterface(stream);
+ mStore = do_QueryInterface(stream);
+ mFileInputStream = do_QueryInterface(stream);
+}
+
+//========================================================================================
+// nsOutputFileStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsOutputFileStream::nsOutputFileStream(nsIFileSpec* inSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (!inSpec)
+ return;
+ nsIOutputStream* stream;
+ if (NS_FAILED(inSpec->GetOutputStream(&stream)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputFileStream::~nsOutputFileStream()
+//----------------------------------------------------------------------------------------
+{
+// if (is_open())
+// close();
+}
+//----------------------------------------------------------------------------------------
+void nsOutputFileStream::AssignFrom(nsISupports* stream)
+//----------------------------------------------------------------------------------------
+{
+ mFile = do_QueryInterface(stream);
+ mOutputStream = do_QueryInterface(stream);
+ mStore = do_QueryInterface(stream);
+ mFileOutputStream = do_QueryInterface(stream);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsOutputFileStream::flush()
+//----------------------------------------------------------------------------------------
+{
+ if (mFileOutputStream)
+ mFileOutputStream->Flush();
+ return error();
+}
+
+//----------------------------------------------------------------------------------------
+void nsOutputFileStream::abort()
+//----------------------------------------------------------------------------------------
+{
+ mResult = NS_FILE_FAILURE;
+ close();
+}
+
+//========================================================================================
+// Manipulators
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsEndl(nsOutputStream& os)
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ os.write("\r\n", 2);
+#elif defined (XP_MAC)
+ os.put('\r');
+#else
+ os.put('\n');
+#endif
+ //os.flush();
+ return os;
+} // nsEndl
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h
new file mode 100644
index 00000000..b0cd5e8a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h
@@ -0,0 +1,772 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// First checked in on 98/11/20 by John R. McMullen in the wrong directory.
+// Checked in again 98/12/04.
+// Polished version 98/12/08.
+// Completely rewritten to integrate with nsIInputStream and nsIOutputStream (the
+// xpcom stream objects.
+
+//========================================================================================
+//
+// Classes defined:
+//
+// nsInputStream, nsOutputStream
+// These are the lightweight STATICALLY LINKED wrappers for
+// the xpcom objects nsIInputStream and nsIOutputstream.
+// Possible uses:
+// If you are implementing a function that accepts one of these xpcom
+// streams, just make one of these little jobbies on the stack, and
+// the handy << or >> notation can be yours.
+//
+// nsInputFileStream, nsOutputFileStream
+// These are the STATICALLY LINKED wrappers for the file-related
+// versions of the above.
+// nsIOFileStream
+// An input and output file stream attached to the same file.
+//
+// This suite provide the following services:
+//
+// 1. Encapsulates all platform-specific file details, so that file i/o
+// can be done correctly without any platform #ifdefs
+//
+// 2. Uses NSPR file services (NOT ansi file I/O), in order to get best
+// native performance. This performance difference is especially large on
+// macintosh.
+//
+// 3. Allows all the power of the ansi stream syntax.
+//
+// Basic example:
+//
+// nsFileSpec myPath("/Development/iotest.txt");
+//
+// nsOutputFileStream testStream(myPath);
+// testStream << "Hello World" << nsEndl;
+//
+// 4. Requires streams to be constructed using typesafe nsFileSpec specifier
+// (not the notorious and bug prone const char*), namely nsFileSpec. See
+// nsFileSpec.h for more details.
+//
+// 5. Fixes a bug that have been there for a long time, and
+// is inevitable if you use NSPR alone:
+//
+// The problem on platforms (Macintosh) in which a path does not fully
+// specify a file, because two volumes can have the same name.
+//
+// Not yet provided:
+//
+// Endian-awareness for reading and writing crossplatform binary files. At this
+// time there seems to be no demand for this.
+//
+//========================================================================================
+
+#ifndef _FILESTREAM_H_
+#define _FILESTREAM_H_
+
+#include "xpcomobsolete.h"
+#include "nsStringFwd.h"
+
+#ifdef XP_MAC
+#include "pprio.h" // To get PR_ImportFile
+#else
+#include "prio.h"
+#endif
+
+#include "nsCOMPtr.h"
+#include "nsIFileStream.h"
+
+// Defined elsewhere
+class nsFileSpec;
+class nsIInputStream;
+class nsIOutputStream;
+class nsIFileSpec;
+
+//========================================================================================
+// Compiler-specific macros, as needed
+//========================================================================================
+#if !defined(NS_USING_NAMESPACE) && (defined(__MWERKS__) || defined(_MSC_VER))
+#define NS_USING_NAMESPACE
+#endif
+
+#ifdef NS_USING_NAMESPACE
+
+#define NS_NAMESPACE_PROTOTYPE
+#define NS_NAMESPACE namespace
+#define NS_NAMESPACE_END
+
+#else
+
+#define NS_NAMESPACE_PROTOTYPE static
+#define NS_NAMESPACE struct
+#define NS_NAMESPACE_END ;
+
+#endif // NS_USING_NAMESPACE
+
+#if !defined(XP_MAC) && !defined(__KCC)
+// PR_STDOUT and PR_STDIN are fatal on Macintosh. So for console i/o, we must use the std
+// stream stuff instead. However, we have to require that cout and cin are passed in
+// to the constructor because in the current build, there is a copy in the base.shlb,
+// and another in the caller's file. Passing it in as a parameter ensures that the
+// caller and this library are using the same global object. Groan.
+//
+// Unix currently does not support iostreams at all. Their compilers do not support
+// ANSI C++, or even ARM C++.
+//
+// Windows supports them, but only if you turn on the -GX compile flag, to support
+// exceptions.
+
+// Catch 22.
+#define NS_USE_PR_STDIO
+#endif
+
+#ifdef NS_USE_PR_STDIO
+class istream;
+class ostream;
+#define CONSOLE_IN 0
+#define CONSOLE_OUT 0
+#else
+#include <iostream>
+using std::istream;
+using std::ostream;
+#define CONSOLE_IN &std::cin
+#define CONSOLE_OUT &std::cout
+#endif
+
+//=========================== End Compiler-specific macros ===============================
+
+//========================================================================================
+class NS_COM_OBSOLETE nsInputStream
+// This is a convenience class, for use on the STACK ("new" junkies: get detoxed first).
+// Given a COM-style stream, this allows you to use the >> operators. It also acquires and
+// reference counts its stream.
+// Please read the comments at the top of this file
+//========================================================================================
+{
+public:
+ nsInputStream(nsIInputStream* inStream)
+ : mInputStream(do_QueryInterface(inStream))
+ , mEOF(PR_FALSE)
+ {}
+ virtual ~nsInputStream();
+
+ nsCOMPtr<nsIInputStream> GetIStream() const
+ {
+ return mInputStream;
+ }
+ PRBool eof() const { return get_at_eof(); }
+ char get();
+ nsresult close()
+ {
+ NS_ASSERTION(mInputStream, "mInputStream is null!");
+ if (mInputStream) {
+ return mInputStream->Close();
+ }
+ return NS_OK;
+ }
+ PRInt32 read(void* s, PRInt32 n);
+
+ // Input streamers. Add more as needed (int&, unsigned int& etc). (but you have to
+ // add delegators to the derived classes, too, because these operators don't inherit).
+ nsInputStream& operator >> (char& ch);
+
+ // Support manipulators
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ {
+ return pf(*this);
+ }
+
+protected:
+
+ // These certainly need to be overridden, they give the best shot we can at detecting
+ // eof in a simple nsIInputStream.
+ virtual void set_at_eof(PRBool atEnd)
+ {
+ mEOF = atEnd;
+ }
+ virtual PRBool get_at_eof() const
+ {
+ return mEOF;
+ }
+private:
+
+ nsInputStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
+
+ // private and unimplemented to disallow copies and assigns
+ nsInputStream(const nsInputStream& rhs);
+ nsInputStream& operator=(const nsInputStream& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIInputStream> mInputStream;
+ PRBool mEOF;
+}; // class nsInputStream
+
+typedef nsInputStream nsBasicInStream; // historic support for this name
+
+//========================================================================================
+class NS_COM_OBSOLETE nsOutputStream
+// This is a convenience class, for use on the STACK ("new" junkies, get detoxed first).
+// Given a COM-style stream, this allows you to use the << operators. It also acquires and
+// reference counts its stream.
+// Please read the comments at the top of this file
+//========================================================================================
+{
+public:
+ nsOutputStream() {}
+ nsOutputStream(nsIOutputStream* inStream)
+ : mOutputStream(do_QueryInterface(inStream))
+ {}
+
+ virtual ~nsOutputStream();
+
+ nsCOMPtr<nsIOutputStream> GetIStream() const
+ {
+ return mOutputStream;
+ }
+ nsresult close()
+ {
+ if (mOutputStream)
+ return mOutputStream->Close();
+ return NS_OK;
+ }
+ void put(char c);
+ PRInt32 write(const void* s, PRInt32 n);
+ virtual nsresult flush();
+ nsresult lastWriteStatus();
+
+ // Output streamers. Add more as needed (but you have to add delegators to the derived
+ // classes, too, because these operators don't inherit).
+ nsOutputStream& operator << (const char* buf);
+ nsOutputStream& operator << (char ch);
+ nsOutputStream& operator << (short val);
+ nsOutputStream& operator << (unsigned short val);
+ nsOutputStream& operator << (long val);
+ nsOutputStream& operator << (unsigned long val);
+ nsOutputStream& operator << (int val);
+ nsOutputStream& operator << (unsigned int val);
+
+ // Support manipulators
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ {
+ return pf(*this);
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsOutputStream(const nsOutputStream& rhs);
+ nsOutputStream& operator=(const nsOutputStream& rhs);
+
+ nsresult mWriteStatus;
+
+// DATA
+protected:
+ nsCOMPtr<nsIOutputStream> mOutputStream;
+}; // class nsOutputStream
+
+typedef nsOutputStream nsBasicOutStream; // Historic support for this name
+
+//========================================================================================
+class NS_COM_OBSOLETE nsErrorProne
+// Common (virtual) base class for remembering errors on demand
+//========================================================================================
+{
+public:
+ nsErrorProne() // for delayed opening
+ : mResult(NS_OK)
+ {
+ }
+ PRBool failed() const
+ {
+ return NS_FAILED(mResult);
+ }
+ nsresult error() const
+ {
+ return mResult;
+ }
+
+// DATA
+protected:
+ nsresult mResult;
+}; // class nsErrorProne
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileClient
+// Because COM does not allow us to write functions which return a boolean value etc,
+// this class is here to take care of the tedious "declare variable then call with
+// the address of the variable" chores.
+//========================================================================================
+: public virtual nsErrorProne
+{
+public:
+ nsFileClient(const nsCOMPtr<nsIOpenFile>& inFile)
+ : mFile(do_QueryInterface(inFile))
+ {
+ }
+ virtual ~nsFileClient() {}
+
+ void open(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode)
+ {
+ if (mFile)
+ mResult = mFile->Open(inFile, nsprMode, accessMode);
+ }
+ PRBool is_open() const
+ {
+ PRBool result = PR_FALSE;
+ if (mFile)
+ mFile->GetIsOpen(&result);
+ return result;
+ }
+ PRBool is_file() const
+ {
+ return mFile ? PR_TRUE : PR_FALSE;
+ }
+
+protected:
+
+ nsFileClient() // for delayed opening
+ {
+ }
+// DATA
+protected:
+ nsCOMPtr<nsIOpenFile> mFile;
+}; // class nsFileClient
+
+//========================================================================================
+class NS_COM_OBSOLETE nsRandomAccessStoreClient
+// Because COM does not allow us to write functions which return a boolean value etc,
+// this class is here to take care of the tedious "declare variable then call with
+// the address of the variable" chores.
+//========================================================================================
+: public virtual nsErrorProne
+{
+public:
+ nsRandomAccessStoreClient() // for delayed opening
+ {
+ }
+ nsRandomAccessStoreClient(const nsCOMPtr<nsIRandomAccessStore>& inStore)
+ : mStore(do_QueryInterface(inStore))
+ {
+ }
+ virtual ~nsRandomAccessStoreClient() {}
+
+ void seek(PRInt64 offset)
+ {
+ seek(PR_SEEK_SET, offset);
+ }
+
+ void seek(PRSeekWhence whence, PRInt64 offset)
+ {
+ set_at_eof(PR_FALSE);
+ if (mStore)
+ mResult = mStore->Seek(whence, offset);
+ }
+ PRInt64 tell()
+ {
+ PRInt64 result;
+ LL_I2L(result, -1);
+ if (mStore)
+ mResult = mStore->Tell(&result);
+ return result;
+ }
+
+protected:
+
+ virtual PRBool get_at_eof() const
+ {
+ PRBool result = PR_TRUE;
+ if (mStore)
+ mStore->GetAtEOF(&result);
+ return result;
+ }
+
+ virtual void set_at_eof(PRBool atEnd)
+ {
+ if (mStore)
+ mStore->SetAtEOF(atEnd);
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsRandomAccessStoreClient(const nsRandomAccessStoreClient& rhs);
+ nsRandomAccessStoreClient& operator=(const nsRandomAccessStoreClient& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIRandomAccessStore> mStore;
+}; // class nsRandomAccessStoreClient
+
+//========================================================================================
+class NS_COM_OBSOLETE nsRandomAccessInputStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessStoreClient
+, public nsInputStream
+{
+public:
+ nsRandomAccessInputStream(nsIInputStream* inStream)
+ : nsRandomAccessStoreClient(do_QueryInterface(inStream))
+ , nsInputStream(inStream)
+ {
+ }
+ PRBool readline(char* s, PRInt32 n);
+ // Result always null-terminated.
+ // Check eof() before each call.
+ // CAUTION: false result only indicates line was truncated
+ // to fit buffer, or an error occurred (OTHER THAN eof).
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+protected:
+ nsRandomAccessInputStream()
+ : nsInputStream(nsnull)
+ {
+ }
+
+ virtual PRBool get_at_eof() const
+ {
+ return nsRandomAccessStoreClient::get_at_eof();
+ }
+
+ virtual void set_at_eof(PRBool atEnd)
+ {
+ nsRandomAccessStoreClient::set_at_eof(atEnd);
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsRandomAccessInputStream(const nsRandomAccessInputStream& rhs);
+ nsRandomAccessInputStream& operator=(const nsRandomAccessInputStream& rhs);
+
+}; // class nsRandomAccessInputStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsInputStringStream
+//========================================================================================
+: public nsRandomAccessInputStream
+{
+public:
+ nsInputStringStream(const char* stringToRead);
+ nsInputStringStream(const nsString& stringToRead);
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsInputStringStream(const nsInputStringStream& rhs);
+ nsInputStringStream& operator=(const nsInputStringStream& rhs);
+
+
+}; // class nsInputStringStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsInputFileStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessInputStream
+, public nsFileClient
+{
+public:
+ enum { kDefaultMode = PR_RDONLY };
+ nsInputFileStream(nsIInputStream* inStream)
+ : nsRandomAccessInputStream(inStream)
+ , nsFileClient(do_QueryInterface(inStream))
+ , mFileInputStream(do_QueryInterface(inStream))
+ {
+ }
+ nsInputFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666);
+ nsInputFileStream(nsIFileSpec* inFile);
+ virtual ~nsInputFileStream();
+
+ void Open(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666)
+ {
+ if (mFile)
+ mFile->Open(inFile, nsprMode, accessMode);
+ }
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+protected:
+ void AssignFrom(nsISupports* stream);
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsInputFileStream(const nsInputFileStream& rhs);
+ nsInputFileStream& operator=(const nsInputFileStream& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIFileSpecInputStream> mFileInputStream;
+}; // class nsInputFileStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsRandomAccessOutputStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessStoreClient
+, public nsOutputStream
+{
+public:
+ nsRandomAccessOutputStream(nsIOutputStream* inStream)
+ : nsRandomAccessStoreClient(do_QueryInterface(inStream))
+ , nsOutputStream(inStream)
+ {
+ }
+
+ // Output streamers. Unfortunately, they don't inherit!
+ nsOutputStream& operator << (const char* buf)
+ { return nsOutputStream::operator << (buf); }
+ nsOutputStream& operator << (char ch)
+ { return nsOutputStream::operator << (ch); }
+ nsOutputStream& operator << (short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ { return nsOutputStream::operator << (pf); }
+
+protected:
+ nsRandomAccessOutputStream()
+ : nsOutputStream(nsnull)
+ {
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsRandomAccessOutputStream(const nsRandomAccessOutputStream& rhs);
+ nsRandomAccessOutputStream& operator=(const nsRandomAccessOutputStream& rhs);
+
+}; // class nsRandomAccessOutputStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsOutputFileStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessOutputStream
+, public nsFileClient
+{
+public:
+ enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
+
+ nsOutputFileStream() {}
+ nsOutputFileStream(nsIOutputStream* inStream)
+ {
+ AssignFrom(inStream);
+ }
+ nsOutputFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666)
+ {
+ nsISupports* stream;
+ if (NS_FAILED(NS_NewIOFileStream(
+ &stream,
+ inFile, nsprMode, accessMode)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+ }
+ nsOutputFileStream(nsIFileSpec* inFile);
+ virtual ~nsOutputFileStream();
+
+ virtual nsresult flush();
+ virtual void abort();
+
+ // Output streamers. Unfortunately, they don't inherit!
+ nsOutputStream& operator << (const char* buf)
+ { return nsOutputStream::operator << (buf); }
+ nsOutputStream& operator << (char ch)
+ { return nsOutputStream::operator << (ch); }
+ nsOutputStream& operator << (short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ { return nsOutputStream::operator << (pf); }
+
+protected:
+ void AssignFrom(nsISupports* stream);
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsOutputFileStream(const nsOutputFileStream& rhs);
+ nsOutputFileStream& operator=(const nsOutputFileStream& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIFileSpecOutputStream> mFileOutputStream;
+}; // class nsOutputFileStream
+
+
+//========================================================================================
+class nsIOFileStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsInputFileStream
+, public nsOutputStream
+{
+public:
+ enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) };
+
+ nsIOFileStream(
+ nsIInputStream* inInputStream
+ , nsIOutputStream* inOutputStream)
+ : nsInputFileStream(inInputStream)
+ , nsOutputStream(inOutputStream)
+ , mFileOutputStream(do_QueryInterface(inOutputStream))
+ {
+ }
+ nsIOFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666)
+ : nsInputFileStream((nsIInputStream*)nsnull)
+ , nsOutputStream(nsnull)
+ {
+ nsISupports* stream;
+ if (NS_FAILED(NS_NewIOFileStream(
+ &stream,
+ inFile, nsprMode, accessMode)))
+ return;
+ mFile = do_QueryInterface(stream);
+ mStore = do_QueryInterface(stream);
+ mInputStream = do_QueryInterface(stream);
+ mOutputStream = do_QueryInterface(stream);
+ mFileInputStream = do_QueryInterface(stream);
+ mFileOutputStream = do_QueryInterface(stream);
+ NS_RELEASE(stream);
+ }
+
+ virtual nsresult close()
+ {
+ // Doesn't matter which of the two we close:
+ // they're hooked up to the same file.
+ return nsInputFileStream::close();
+ }
+
+ // Output streamers. Unfortunately, they don't inherit!
+ nsOutputStream& operator << (const char* buf)
+ { return nsOutputStream::operator << (buf); }
+ nsOutputStream& operator << (char ch)
+ { return nsOutputStream::operator << (ch); }
+ nsOutputStream& operator << (short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ { return nsOutputStream::operator << (pf); }
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+ virtual nsresult flush() {if (mFileOutputStream) mFileOutputStream->Flush(); return error(); }
+
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsIOFileStream(const nsIOFileStream& rhs);
+ nsIOFileStream& operator=(const nsIOFileStream& rhs);
+
+ // DATA
+protected:
+ nsCOMPtr<nsIFileSpecOutputStream> mFileOutputStream;
+}; // class nsIOFileStream
+
+//========================================================================================
+// Manipulators
+//========================================================================================
+
+NS_COM_OBSOLETE nsOutputStream& nsEndl(nsOutputStream& os); // outputs and FLUSHES.
+
+//========================================================================================
+#endif /* _FILESTREAM_H_ */
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl
new file mode 100644
index 00000000..78abd9e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ THIS INTERFACE IS DEPRECATED AND UNSUPPORTED! USE |nsIFile| and |nsILocalFile|.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+// This is the only correct cross-platform way to specify a file.
+// Strings are not such a way. If you grew up on windows or unix, you
+// may think they are. Welcome to reality.
+
+#include "nsISupports.idl"
+
+%{C++
+#include "nsFileSpec.h" // for factory method
+%}
+
+interface nsIFileURL;
+interface nsIFilePath;
+interface nsIOutputStream;
+interface nsIInputStream;
+
+// Define Contractid and CID
+%{C++
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ THIS INTERFACE IS DEPRECATED AND UNSUPPORTED! USE |nsIFile| and |nsILocalFile|.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// {A5740FA2-146E-11d3-B00D-00C04FC2E79B}
+#define NS_FILESPEC_CID \
+{ 0xa5740fa2, 0x146e, 0x11d3, { 0xb0, 0xd, 0x0, 0xc0, 0x4f, 0xc2, 0xe7, 0x9b } }
+
+#define NS_FILESPEC_CONTRACTID "@mozilla.org/filespec;1"
+#define NS_FILESPEC_CLASSNAME "File Spec"
+
+%}
+
+ native nsFileSpec(nsFileSpec);
+[ref] native nsFileSpecRef(nsFileSpec);
+[ptr] native nsFileSpecPtr(nsFileSpec);
+
+[scriptable, uuid(d8c0a080-0868-11d3-915f-d9d889d48e3c)]
+interface nsIFileSpec : nsISupports
+{
+ void fromFileSpec([const] in nsIFileSpec original);
+
+ attribute string URLString;
+ attribute string unixStyleFilePath;
+ attribute string persistentDescriptorString;
+ attribute string nativePath;
+
+ readonly attribute string NSPRPath;
+
+ void error();
+
+ boolean isValid();
+ boolean failed();
+
+ attribute string leafName;
+
+ readonly attribute nsIFileSpec parent;
+ readonly attribute nsIInputStream inputStream;
+ readonly attribute nsIOutputStream outputStream;
+ boolean isChildOf(in nsIFileSpec possibleParent);
+ [noscript] readonly attribute nsFileSpec fileSpec;
+ [noscript] void setFromFileSpec([const] in nsFileSpecRef spec);
+
+ attribute string fileContents;
+
+ void makeUnique();
+ void makeUniqueWithSuggestedName(in string suggestedName);
+
+ readonly attribute unsigned long modDate;
+ boolean modDateChanged(in unsigned long oldStamp);
+
+ boolean isDirectory();
+ boolean isFile();
+ boolean exists();
+ boolean isHidden();
+
+ boolean equals(in nsIFileSpec spec);
+
+ readonly attribute unsigned long fileSize;
+ readonly attribute long long diskSpaceAvailable;
+
+ void appendRelativeUnixPath(in string relativePath);
+
+ void createDir();
+ void touch();
+
+ boolean isSymlink();
+ void resolveSymlink();
+
+ void delete(in boolean recursive);
+ void truncate(in long aNewLength);
+ void rename([const] in string newLeafName);
+ void copyToDir([const] in nsIFileSpec newParentDir);
+ void moveToDir([const] in nsIFileSpec newParentDir);
+ void execute([const] in string args);
+
+ void openStreamForReading();
+ void openStreamForWriting();
+ void openStreamForReadingAndWriting();
+ void closeStream();
+ boolean isStreamOpen();
+
+ boolean eof();
+ long read(inout string buffer, in long requestedCount);
+ void readLine(inout string line, in long bufferSize, out boolean wasTruncated);
+
+ /** Check eof() before each call.
+ * CAUTION: false result only indicates line was truncated
+ * to fit buffer, or an error occurred (OTHER THAN eof).
+ */
+ long write(in string data, in long requestedCount);
+ void flush();
+
+ void seek(in long offset);
+ long tell();
+ void endLine();
+ attribute AString unicodePath;
+
+};
+
+// Define Contractid and CID
+%{C++
+// {a3020981-2018-11d3-915f-a957795b7ebc}
+#define NS_DIRECTORYITERATOR_CID \
+{ 0xa3020981, 0x2018, 0x11d3, { 0x91, 0x5f, 0xa9, 0x57, 0x79, 0x5b, 0x7e, 0xbc } }
+
+#define NS_DIRECTORYITERATOR_CONTRACTID "@mozilla.org/directoryiterator;1"
+#define NS_DIRECTORYITERATOR_CLASSNAME "nsIDirectoryIterator"
+%}
+
+[scriptable, uuid(d8c0a083-0868-11d3-915f-d9d889d48e3c)]
+interface nsIDirectoryIterator : nsISupports
+{
+ void init(in nsIFileSpec parent, in boolean resolveSymlink);
+ boolean exists();
+ void next();
+ readonly attribute nsIFileSpec currentSpec;
+};
+
+%{C++
+// Factory methods if you link with xpcom
+NS_COM_OBSOLETE nsresult NS_NewFileSpecWithSpec(const nsFileSpec& aSrcFileSpec, nsIFileSpec **result);
+NS_COM_OBSOLETE nsresult NS_NewFileSpec(nsIFileSpec** result);
+NS_COM_OBSOLETE nsresult NS_NewDirectoryIterator(nsIDirectoryIterator** result);
+
+// Convert from nsIFile to nsIFileSpec
+//
+// XXX This function is here only to assist with the migration from nsIFileSpec
+// to nsIFile. This function will dissappear in future mozilla releases.
+//
+// ...ripped from nsPrefService.cpp:
+//
+// "So discouraged is the use of nsIFileSpec, nobody wanted to have this routine be
+// public - It might lead to continued use of nsIFileSpec. Right now, [mozilla] has
+// such a need for it, here it is. Let's stop having to use it though."
+//
+NS_COM_OBSOLETE nsresult NS_NewFileSpecFromIFile(nsIFile *aFile, nsIFileSpec **result);
+
+#define NS_BOOL_ACCESSOR(_method) { PRBool yes; return NS_SUCCEEDED(f->_method(&yes)) && yes; }
+inline PRBool Exists(nsIFileSpec* f) NS_BOOL_ACCESSOR(Exists)
+inline PRBool Exists(nsIDirectoryIterator* f) NS_BOOL_ACCESSOR(Exists)
+inline PRBool IsDirectory(nsIFileSpec* f) NS_BOOL_ACCESSOR(IsDirectory)
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp
new file mode 100644
index 00000000..011bcdaa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp
@@ -0,0 +1,727 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIFileStream.h"
+#include "nsFileSpec.h"
+#include "nsCOMPtr.h"
+
+#include "prerror.h"
+
+#include "nsSegmentedBuffer.h"
+#include "nsInt64.h"
+
+#ifdef XP_MAC
+#include "pprio.h" // To get PR_ImportFile
+#else
+#include "prio.h"
+#endif
+
+#ifdef XP_MAC
+#include <Errors.h>
+#include <iostream>
+#endif
+
+//========================================================================================
+class FileImpl
+ : public nsIRandomAccessStore
+ , public nsIFileSpecOutputStream
+ , public nsIFileSpecInputStream
+ , public nsIOpenFile
+//========================================================================================
+{
+ public:
+ FileImpl(PRFileDesc* inDesc);
+ FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIOpenFile interface
+ NS_IMETHOD Open(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode);
+ NS_IMETHOD Close();
+ NS_IMETHOD GetIsOpen(PRBool* outOpen);
+
+ // nsIInputStream interface
+ NS_IMETHOD Available(PRUint32 *aLength);
+ NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount);
+ NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking);
+
+ // nsIOutputStream interface
+ NS_IMETHOD Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount);
+ NS_IMETHOD Flush();
+ NS_IMETHOD WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval);
+
+ // nsIRandomAccessStore interface
+ NS_DECL_NSISEEKABLESTREAM
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF);
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF);
+
+ private:
+
+ ~FileImpl();
+
+ protected:
+
+ enum {
+ kOuputBufferSegmentSize = 4096,
+ kOuputBufferMaxSize = 4096
+ };
+
+ nsresult InternalFlush(PRBool syncFile);
+ nsresult AllocateBuffers(PRUint32 segmentSize, PRUint32 maxSize);
+
+ PRFileDesc* mFileDesc;
+ int mNSPRMode;
+ PRBool mFailed;
+ PRBool mEOF;
+ PRInt32 mLength;
+
+ PRBool mGotBuffers;
+ nsSegmentedBuffer mOutBuffer;
+ char* mWriteCursor;
+ char* mWriteLimit;
+
+}; // class FileImpl
+
+NS_IMPL_RELEASE(FileImpl)
+NS_IMPL_ADDREF(FileImpl)
+
+NS_IMPL_QUERY_HEAD(FileImpl)
+ NS_IMPL_QUERY_BODY(nsIOpenFile)
+ NS_IMPL_QUERY_BODY(nsISeekableStream)
+ NS_IMPL_QUERY_BODY(nsIRandomAccessStore)
+ NS_IMPL_QUERY_BODY(nsIOutputStream)
+ NS_IMPL_QUERY_BODY(nsIInputStream)
+ NS_IMPL_QUERY_BODY(nsIFileSpecInputStream)
+ NS_IMPL_QUERY_BODY(nsIFileSpecOutputStream)
+NS_IMPL_QUERY_TAIL(nsIOutputStream)
+
+
+//----------------------------------------------------------------------------------------
+FileImpl::FileImpl(PRFileDesc* inDesc)
+//----------------------------------------------------------------------------------------
+: mFileDesc(inDesc)
+, mNSPRMode(0)
+, mFailed(PR_FALSE)
+, mEOF(PR_FALSE)
+, mLength(-1)
+, mGotBuffers(PR_FALSE)
+{
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+}
+
+
+//----------------------------------------------------------------------------------------
+FileImpl::FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode)
+//----------------------------------------------------------------------------------------
+: mFileDesc(nsnull)
+, mNSPRMode(-1)
+, mEOF(PR_FALSE)
+, mLength(-1)
+, mGotBuffers(PR_FALSE)
+{
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+
+ nsresult rv = Open(inFile, nsprMode, accessMode); // this sets nsprMode
+
+ if (NS_FAILED(rv))
+ {
+ mFailed = PR_TRUE;
+#if DEBUG
+ char *fileName = inFile.GetLeafName();
+ printf("Opening file %s failed\n", fileName);
+ nsCRT::free(fileName);
+#endif
+ }
+ else
+ {
+ mFailed = PR_FALSE;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+FileImpl::~FileImpl()
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = Close();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Close failed");
+}
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Open(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode)
+//----------------------------------------------------------------------------------------
+{
+ if (mFileDesc)
+ if ((nsprMode & mNSPRMode) == nsprMode)
+ return NS_OK;
+ else
+ return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
+
+ const int nspr_modes[]={
+ PR_WRONLY | PR_CREATE_FILE,
+ PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ PR_RDONLY,
+ PR_RDONLY | PR_APPEND,
+ PR_RDWR | PR_CREATE_FILE,
+ PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
+// "wb",
+// "ab",
+// "wb",
+// "rb",
+// "r+b",
+// "w+b",
+ 0 };
+ const int* currentLegalMode = nspr_modes;
+ while (*currentLegalMode && nsprMode != *currentLegalMode)
+ ++currentLegalMode;
+ if (!*currentLegalMode)
+ return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
+
+#ifdef XP_MAC
+ // Use the file spec to open the file, because one path can be common to
+ // several files on the Macintosh (you can have several volumes with the
+ // same name, see).
+ mFileDesc = 0;
+ OSErr err = inFile.Error();
+ if (err != noErr)
+ if (err != fnfErr || !(nsprMode & PR_CREATE_FILE))
+ return NS_FILE_RESULT(inFile.Error());
+ err = noErr;
+#if DEBUG
+ const OSType kCreator = 'CWIE';
+#else
+ const OSType kCreator = 'MOSS';
+#endif
+ // Resolve the alias to the original file.
+ nsFileSpec original = inFile;
+ PRBool ignoredResult;
+ original.ResolveSymlink(ignoredResult);
+ const FSSpec& spec = original.operator const FSSpec&();
+ if (nsprMode & PR_CREATE_FILE) {
+ // In order to get the right file type/creator, do it with an nsILocalFileMac
+ // Don't propagate any errors in doing this. If any error, just use FSpCreate.
+ FSSpec nonConstSpec = spec;
+ nsCOMPtr<nsILocalFileMac> macFile;
+ nsresult res = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_FALSE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(res)) {
+ nsCOMPtr<nsIFile> asFile(do_QueryInterface(macFile, &res));
+ if (NS_SUCCEEDED(res)) {
+ res = asFile->Create(nsIFile::NORMAL_FILE_TYPE, 0);
+ if (res == NS_ERROR_FILE_ALREADY_EXISTS)
+ res = NS_OK;
+ }
+ }
+ if (NS_FAILED(res))
+ err = FSpCreate(&spec, kCreator, 'TEXT', 0);
+ }
+
+ if (err == dupFNErr)
+ err = noErr;
+ if (err != noErr)
+ return NS_FILE_RESULT(err);
+
+ SInt8 perm;
+ if (nsprMode & PR_RDWR)
+ perm = fsRdWrPerm;
+ else if (nsprMode & PR_WRONLY)
+ perm = fsWrPerm;
+ else
+ perm = fsRdPerm;
+
+ short refnum;
+ err = FSpOpenDF(&spec, perm, &refnum);
+
+ if (err == noErr && (nsprMode & PR_TRUNCATE))
+ err = ::SetEOF(refnum, 0);
+ if (err == noErr && (nsprMode & PR_APPEND))
+ err = SetFPos(refnum, fsFromLEOF, 0);
+ if (err != noErr)
+ return NS_FILE_RESULT(err);
+
+ if ((mFileDesc = PR_ImportFile(refnum)) == 0)
+ return NS_FILE_RESULT(PR_GetError());
+#else
+ // Platforms other than Macintosh...
+ // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
+ // a windows path.
+ if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0)
+ return NS_FILE_RESULT(PR_GetError());
+#endif
+ mNSPRMode = nsprMode;
+ mLength = PR_Available(mFileDesc);
+ return NS_OK;
+} // FileImpl::Open
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Available(PRUint32 *aLength)
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aLength != nsnull, "null ptr");
+ if (!aLength)
+ return NS_ERROR_NULL_POINTER;
+ if (mLength < 0)
+ return NS_ERROR_UNEXPECTED;
+ *aLength = mLength;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::GetIsOpen(PRBool* outOpen)
+//----------------------------------------------------------------------------------------
+{
+ *outOpen = (mFileDesc != nsnull && !mFailed);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Seek(PRInt32 whence, PRInt64 offset)
+//----------------------------------------------------------------------------------------
+{
+ if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ mFailed = PR_FALSE; // reset on a seek.
+ mEOF = PR_FALSE; // reset on a seek.
+
+ // To avoid corruption, we flush during a seek. see bug number 18949
+ InternalFlush(PR_FALSE);
+
+ nsInt64 position = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR);
+ nsInt64 available = PR_Available64(mFileDesc);
+ nsInt64 fileSize = position + available;
+ nsInt64 newPosition = offset;
+ switch (whence)
+ {
+ case NS_SEEK_CUR: newPosition += position; break;
+ case NS_SEEK_SET: ; break;
+ case NS_SEEK_END: newPosition += fileSize; break;
+ }
+ const nsInt64 zero = 0;
+ if (newPosition < zero)
+ {
+ newPosition = 0;
+ mFailed = PR_TRUE;
+ }
+ if (newPosition >= fileSize) // nb: not "else if".
+ {
+ newPosition = fileSize;
+ mEOF = PR_TRUE;
+ }
+ if (PR_Seek64(mFileDesc, newPosition, PR_SEEK_SET) < 0)
+ mFailed = PR_TRUE;
+ return NS_OK;
+} // FileImpl::Seek
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aBuf != nsnull, "null ptr");
+ if (!aBuf)
+ return NS_ERROR_NULL_POINTER;
+ NS_PRECONDITION(aReadCount != nsnull, "null ptr");
+ if (!aReadCount)
+ return NS_ERROR_NULL_POINTER;
+ if (!mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ if (mFailed)
+ return NS_ERROR_FAILURE;
+ PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount);
+ if (bytesRead < 0)
+ {
+ *aReadCount = 0;
+ mFailed = PR_TRUE;
+ return NS_FILE_RESULT(PR_GetError());
+ }
+ else if (bytesRead == 0)
+ {
+ mEOF = PR_TRUE;
+ }
+ *aReadCount = bytesRead;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileImpl::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("ReadSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount)
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aBuf != nsnull, "null ptr");
+ NS_PRECONDITION(aWriteCount != nsnull, "null ptr");
+
+ *aWriteCount = 0;
+
+#ifdef XP_MAC
+ // Calling PR_Write on stdout is sure suicide.
+ if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
+ {
+ std::cout.write(aBuf, aCount);
+ *aWriteCount = aCount;
+ return NS_OK;
+ }
+#endif
+ if (!mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ if (mFailed)
+ return NS_ERROR_FAILURE;
+
+ if (!mGotBuffers)
+ {
+ nsresult rv = AllocateBuffers(kOuputBufferSegmentSize, kOuputBufferMaxSize);
+ if (NS_FAILED(rv))
+ return rv; // try to write non-buffered?
+ }
+
+ PRUint32 bufOffset = 0;
+ PRUint32 currentWrite = 0;
+ while (aCount > 0)
+ {
+ if (mWriteCursor == nsnull || mWriteCursor == mWriteLimit)
+ {
+ char* seg = mOutBuffer.AppendNewSegment();
+ if (seg == nsnull)
+ {
+ // buffer is full, try again
+ InternalFlush(PR_FALSE);
+ seg = mOutBuffer.AppendNewSegment();
+ if (seg == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mWriteCursor = seg;
+ mWriteLimit = seg + mOutBuffer.GetSegmentSize();
+ }
+
+ // move
+ currentWrite = mWriteLimit - mWriteCursor;
+
+ if (aCount < currentWrite)
+ currentWrite = aCount;
+
+ memcpy(mWriteCursor, (aBuf + bufOffset), currentWrite);
+
+ mWriteCursor += currentWrite;
+
+ aCount -= currentWrite;
+ bufOffset += currentWrite;
+ *aWriteCount += currentWrite;
+ }
+
+ return NS_OK;
+}
+
+static NS_METHOD
+nsWriteSegmentToFile(nsIInputStream* in,
+ void* closure,
+ const char* fromRawSegment,
+ PRUint32 toOffset,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ NS_NOTREACHED("nsWriteSegmentToFile");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+FileImpl::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *result)
+{
+ return inStr->ReadSegments(nsWriteSegmentToFile, nsnull, count, result);
+}
+
+NS_IMETHODIMP
+FileImpl::WriteSegments(nsReadSegmentFun reader, void * closure,
+ PRUint32 count, PRUint32 *result)
+{
+ NS_NOTREACHED("WriteSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+FileImpl::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_FALSE;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Tell(PRInt64* outWhere)
+//----------------------------------------------------------------------------------------
+{
+ if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ *outWhere = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR);
+ return NS_OK;
+} // FileImpl::Tell
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Close()
+//----------------------------------------------------------------------------------------
+{
+ if ((mNSPRMode & PR_RDONLY) == 0)
+ InternalFlush(PR_FALSE);
+
+ if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
+ return NS_OK;
+ if (PR_Close(mFileDesc) == PR_SUCCESS)
+ mFileDesc = 0;
+ else
+ return NS_FILE_RESULT(PR_GetError());
+ return NS_OK;
+} // FileImpl::close
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Flush()
+//----------------------------------------------------------------------------------------
+{
+ // for external callers, this will do a Sync as well as flush buffers.
+ return InternalFlush(PR_TRUE);
+} // FileImpl::flush
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::GetAtEOF(PRBool* outAtEOF)
+//----------------------------------------------------------------------------------------
+{
+ *outAtEOF = mEOF;
+ return NS_OK;
+}
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::SetAtEOF(PRBool inAtEOF)
+//----------------------------------------------------------------------------------------
+{
+ mEOF = inAtEOF;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::SetEOF()
+//----------------------------------------------------------------------------------------
+{
+ NS_NOTYETIMPLEMENTED("FileImpl::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult FileImpl::AllocateBuffers(PRUint32 segmentSize, PRUint32 maxBufSize)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = mOutBuffer.Init(segmentSize, maxBufSize);
+ if (NS_SUCCEEDED(rv))
+ mGotBuffers = PR_TRUE;
+
+ return rv;
+}
+
+// external callers of Flush will have sync get called,
+// but internal callers just want to flush the buffers to disk.
+nsresult FileImpl::InternalFlush(PRBool syncFile)
+{
+#ifdef XP_MAC
+ if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
+ {
+ std::cout.flush();
+ return NS_OK;
+ }
+#endif
+ if (!mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+
+ PRInt32 segCount = mOutBuffer.GetSegmentCount();
+ PRUint32 segSize = mOutBuffer.GetSegmentSize();
+
+ for (PRInt32 i = 0; i < segCount; i++)
+ {
+ char* seg = mOutBuffer.GetSegment(i);
+
+ // if it is the last buffer, it may not be completely full.
+ if(i == (segCount-1))
+ segSize = (mWriteCursor - seg);
+
+ PRInt32 bytesWrit = PR_Write(mFileDesc, seg, segSize);
+ if (bytesWrit != (PRInt32)segSize)
+ {
+ mFailed = PR_TRUE;
+ return NS_FILE_RESULT(PR_GetError());
+ }
+ }
+
+ if (mGotBuffers)
+ mOutBuffer.Empty();
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+
+ // On unix, it seems to fail always.
+ if (syncFile && PR_Sync(mFileDesc) != PR_SUCCESS)
+ mFailed = PR_TRUE;
+
+ return NS_OK;
+}
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalInputFileStream(
+ nsISupports** aResult,
+ const nsFileSpec& inFile
+ /*Default nsprMode == PR_RDONLY*/
+ /*Default accessmode = 0666 (octal)*/)
+// Factory method to get an nsInputStream from a file, using most common options
+//----------------------------------------------------------------------------------------
+{
+ // This QueryInterface was needed because NS_NewIOFileStream
+ // does a cast from (void *) to (nsISupports *) thus causing a
+ // vtable problem on Windows, where we really didn't have the proper pointer
+ // to an nsIInputStream, this ensures that we do
+ nsISupports * supports;
+ nsIInputStream * inStr;
+
+ nsresult rv = NS_NewIOFileStream(&supports, inFile, PR_RDONLY, 0666);
+
+ *aResult = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inStr))) {
+ *aResult = inStr;
+ }
+ NS_RELEASE(supports);
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalOutputFileStream(
+ nsISupports** aResult,
+ const nsFileSpec& inFile
+ /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
+ /*Default accessMode= 0666 (octal)*/)
+// Factory method to get an nsOutputStream to a file - most common case.
+//----------------------------------------------------------------------------------------
+{
+ // This QueryInterface was needed because NS_NewIOFileStream
+ // does a cast from (void *) to (nsISupports *) thus causing a
+ // vtable problem on Windows, where we really didn't have the proper pointer
+ // to an nsIOutputStream, this ensures that we do
+#if 1
+/* nsISupports * supports;
+ nsIOutputStream * outStr;
+
+ nsresult rv = NS_NewIOFileStream(
+ &supports,
+ inFile,
+ (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
+ 0666);
+
+ *aResult = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)&outStr))) {
+ *aResult = outStr;
+ }
+ NS_RELEASE(supports);
+ }
+ return rv;
+ */
+
+ nsCOMPtr<nsISupports> supports;
+ nsIOutputStream * outStr;
+
+ nsresult rv = NS_NewIOFileStream(
+ getter_AddRefs(supports),
+ inFile,
+ (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
+ 0666);
+
+ *aResult = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)&outStr))) {
+ *aResult = outStr;
+ }
+ }
+ return rv;
+#else
+ return NS_NewIOFileStream(
+ aResult,
+ inFile,
+ (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
+ 0666);
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM_OBSOLETE nsresult NS_NewIOFileStream(
+ nsISupports** aResult,
+ const nsFileSpec& inFile,
+ PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/,
+ PRInt32 accessMode /*Default = 0666 (octal)*/)
+ // Factory method to get an object that implements both nsIInputStream
+ // and nsIOutputStream, associated with a file.
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode);
+ if (! stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(stream);
+ PRBool isOpened = PR_FALSE;
+ stream->GetIsOpen(&isOpened);
+ if (!isOpened)
+ {
+ NS_RELEASE(stream);
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = (nsISupports*)(void*)stream;
+ return NS_OK;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h
new file mode 100644
index 00000000..251b3ffc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsIFileStream_h___
+#define nsIFileStream_h___
+
+#include "xpcomobsolete.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsISeekableStream.h"
+#include "prio.h"
+
+class nsFileSpec;
+
+/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
+#define NS_IOPENFILE_IID \
+{ 0xa6cf90e8, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIOpenFile
+// Represents a file, and supports Open.
+//========================================================================================
+: public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IOPENFILE_IID)
+
+ NS_IMETHOD Open(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode) = 0;
+ // Note: Open() is only needed after
+ // an explicit Close(). All file streams
+ // are automatically opened on construction.
+ NS_IMETHOD GetIsOpen(PRBool* outOpen) = 0;
+
+}; // class nsIOpenFile
+
+/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
+#define NS_IRANDOMACCESS_IID \
+{ 0xa6cf90eb, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIRandomAccessStore
+// Supports Seek, Tell etc.
+//========================================================================================
+: public nsISeekableStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IRANDOMACCESS_IID)
+
+/* "PROTECTED" */
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF) = 0;
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF) = 0;
+}; // class nsIRandomAccessStore
+
+
+#ifndef NO_XPCOM_FILE_STREAMS // hack to work around duplicate class definitions in here
+ // and mozilla/netwerks/base/nsIFileStreams.idl
+
+/* a6cf90e6-15b3-11d2-932e-00805f8add32 */
+#define NS_IFILESPECINPUTSTREAM_IID \
+{ 0xa6cf90e6, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIFileSpecInputStream
+// These are additional file-specific methods that files have, above what
+// nsIInputStream supports. The current implementation supports both
+// interfaces.
+//========================================================================================
+: public nsIInputStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILESPECINPUTSTREAM_IID)
+}; // class nsIFileSpecInputStream
+
+/* a6cf90e7-15b3-11d2-932e-00805f8add32 */
+#define NS_IFILESPECOUTPUTSTREAM_IID \
+{ 0xa6cf90e7, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIFileSpecOutputStream
+// These are additional file-specific methods that files have, above what
+// nsIOutputStream supports. The current implementation supports both
+// interfaces.
+//========================================================================================
+: public nsIOutputStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILESPECOUTPUTSTREAM_IID)
+}; // class nsIFileSpecOutputStream
+
+#endif // NO_XPCOM_FILE_STREAMS
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalInputFileStream(
+ nsISupports** aStreamResult,
+ const nsFileSpec& inFile
+ /*Default nsprMode == PR_RDONLY*/
+ /*Default accessmode = 0700 (octal)*/);
+// Factory method to get an nsInputStream from a file, using most common options
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalOutputFileStream(
+ nsISupports** aStreamResult, // will implement all the above interfaces
+ const nsFileSpec& inFile
+ /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
+ /*Default accessMode= 0700 (octal)*/);
+ // Factory method to get an nsOutputStream to a file - most common case.
+
+//----------------------------------------------------------------------------------------
+extern "C" NS_COM_OBSOLETE nsresult NS_NewIOFileStream(
+ nsISupports** aStreamResult, // will implement all the above interfaces
+ const nsFileSpec& inFile,
+ PRInt32 nsprMode,
+ PRInt32 accessMode);
+ // Factory method to get an object that implements both nsIInputStream
+ // and nsIOutputStream, associated with a single file.
+
+#endif /* nsIFileSpecStream_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl
new file mode 100644
index 00000000..bc9990e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl
@@ -0,0 +1,186 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsISupports.idl"
+#include "nsIEnumerator.idl"
+
+interface nsIFile;
+
+typedef PRUint32 nsRegistryKey;
+typedef long nsWellKnownRegistry;
+
+[scriptable,uuid(5D41A440-8E37-11d2-8059-00600811A9C3)]
+interface nsIRegistry : nsISupports
+{
+ const long None = 0;
+ const long Users = 1;
+ const long Common = 2;
+ const long CurrentUser = 3;
+
+ const long ApplicationComponentRegistry = 1;
+ const long ApplicationRegistry = 2;
+
+ // Dont use this one. This for internal use only.
+ const long ApplicationCustomRegistry = -1;
+
+ void open(in nsIFile regFile);
+ void openWellKnownRegistry(in nsWellKnownRegistry regid);
+
+ void flush();
+ boolean isOpen();
+
+ nsRegistryKey addKey(in nsRegistryKey baseKey, in wstring keyname);
+ nsRegistryKey getKey(in nsRegistryKey baseKey, in wstring keyname);
+ void removeKey(in nsRegistryKey baseKey, in wstring keyname);
+
+ wstring getString(in nsRegistryKey baseKey, in wstring valname);
+ void setString(in nsRegistryKey baseKey, in wstring valname, in wstring value);
+
+ string getStringUTF8(in nsRegistryKey baseKey, in string path);
+ void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
+
+ void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
+ void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
+ PRInt32 getInt(in nsRegistryKey baseKey, in string path);
+ void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
+ PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
+ void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
+
+ /**
+ * addSubtree() and friends need to be renamed to addKeyUTF8().
+ * If you are using these forms make sure you pass UTF8 data
+ */
+ nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
+ void removeSubtree(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
+
+ nsRegistryKey addSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ void removeSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtreeRaw(in nsRegistryKey baseKey, in string path);
+
+ nsIEnumerator enumerateSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateAllSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateValues(in nsRegistryKey baseKey);
+
+ const unsigned long String = 1;
+ const unsigned long Int32 = 2;
+ const unsigned long Bytes = 3;
+ const unsigned long File = 4;
+
+ unsigned long getValueType(in nsRegistryKey baseKey, in string path);
+ PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
+ void deleteValue(in nsRegistryKey baseKey, in string path);
+
+ /**
+ * escapeKey() takes arbitrary binary data and converts it into
+ * valid ASCII which can be used as registry key or value names
+ */
+ void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
+ void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
+
+ attribute string currentUserName;
+
+ void pack();
+};
+
+[scriptable, uuid(8cecf236-1dd2-11b2-893c-f9848956eaec)]
+interface nsIRegistryEnumerator : nsIEnumerator
+{
+ void currentItemInPlaceUTF8(out nsRegistryKey key,
+ [shared, retval] out string item);
+};
+
+[scriptable, uuid(D1B54831-AC07-11d2-805E-00600811A9C3)]
+interface nsIRegistryNode : nsISupports
+{
+ readonly attribute string nameUTF8;
+ readonly attribute wstring name;
+ readonly attribute nsRegistryKey key;
+};
+
+[scriptable,uuid(5316C380-B2F8-11d2-A374-0080C6F80E4B)]
+interface nsIRegistryValue : nsISupports
+{
+ readonly attribute wstring name;
+ readonly attribute string nameUTF8;
+ readonly attribute unsigned long type;
+ readonly attribute PRUint32 length;
+};
+
+[uuid(3A15FC88-7A61-4Ab4-8E58-31E95fAB3DA8)]
+/**
+ * It sucks that nsIRegistry has to always allocate and return
+ * strings. nsIRegistryGetter adds in interfaces for non allocating getters
+ * to registry values.
+ */
+interface nsIRegistryGetter : nsISupports
+{
+ /**
+ * Get a string value of attribute valname in widestring or utf8 format
+ *
+ * @return
+ * NS_OK on success.
+ * buf has the string value copied into it. length is NOT changed.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in chars including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various failure codes otherwise. buf and length wont be updated.
+ */
+ void getStringUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout char buf, inout PRUint32 length);
+
+ /**
+ * Get a a byte array value of attribute valname
+ *
+ * @return
+ * NS_OK on success. buf has the string value copied into it.
+ * length is updated to actual number of bytes copied into buf.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in PRUint8s including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various other failure codes otherwise. buf and length wont be updated.
+ */
+ void getBytesUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout PRUint8 buf, inout PRUint32 length);
+};
+
+%{ C++
+#include "nsIRegistryUtils.h"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h
new file mode 100644
index 00000000..a3d74d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef __nsIRegistryUtils_h
+#define __nsIRegistryUtils_h
+
+#define NS_REGISTRY_CONTRACTID "@mozilla.org/registry;1"
+#define NS_REGISTRY_CLASSNAME "Mozilla Registry"
+/* be761f00-a3b0-11d2-996c-0080c7cb1081 */
+#define NS_REGISTRY_CID \
+{ \
+ 0xbe761f00, \
+ 0xa3b0, \
+ 0x11d2, \
+ {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x81} \
+}
+
+/*------------------------------- Error Codes ----------------------------------
+------------------------------------------------------------------------------*/
+#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
+#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
+#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
+#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
+#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
+#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
+#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
+#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
+#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp
new file mode 100644
index 00000000..f120cd43
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp
@@ -0,0 +1,1189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSpecialSystemDirectory.h"
+#include "nsDebug.h"
+
+#ifdef XP_MAC
+#include <Folders.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#include "nsIInternetConfigService.h"
+#ifdef DEBUG
+#include "prenv.h" // For PR_Getenv
+#endif
+#elif defined(XP_WIN)
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#elif defined(XP_OS2)
+#define MAX_PATH _MAX_PATH
+#define INCL_WINWORKPLACE
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "prenv.h"
+#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "prenv.h"
+#elif defined(XP_BEOS)
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+#endif
+
+#if defined(VMS)
+#include <unixlib.h>
+#endif
+
+#include "plstr.h"
+
+#include "nsHashtable.h"
+#include "prlog.h"
+
+#if defined (XP_MAC) && UNIVERSAL_INTERFACES_VERSION < 0x0340
+ enum {
+ kSystemDomain = -32766, /* Read-only system hierarchy.*/
+ kLocalDomain = -32765, /* All users of a single machine have access to these resources.*/
+ kNetworkDomain = -32764, /* All users configured to use a common network server has access to these resources.*/
+ kUserDomain = -32763, /* Read/write. Resources that are private to the user.*/
+ kClassicDomain = -32762, /* Domain referring to the currently configured Classic System Folder*/
+
+ kDomainLibraryFolderType = FOUR_CHAR_CODE('dlib')
+ };
+#endif
+
+
+class SystemDirectoriesKey : public nsHashKey {
+public:
+
+ SystemDirectoriesKey(nsSpecialSystemDirectory::SystemDirectories newKey) : sdKey(newKey) {}
+
+ virtual PRUint32 HashCode(void) const
+ {
+ return PRUint32(sdKey);
+ }
+
+ virtual PRBool Equals(const nsHashKey *aKey) const
+ {
+ nsSpecialSystemDirectory::SystemDirectories other =
+ ((SystemDirectoriesKey*)aKey)->sdKey;
+ return other == sdKey;
+ }
+
+ virtual nsHashKey *Clone(void) const
+ {
+ return new SystemDirectoriesKey(sdKey);
+ }
+
+private:
+ nsSpecialSystemDirectory::SystemDirectories sdKey; // sd for SystemDirectories
+};
+
+PR_STATIC_CALLBACK(PRBool) DeleteSystemDirKeys(nsHashKey *aKey, void *aData, void* closure)
+{
+ delete ((nsFileSpec *)aData);
+ return PR_TRUE;
+}
+
+#define NS_SYSTEMDIR_HASH_NUM (10)
+static nsHashtable *systemDirectoriesLocations = NULL;
+#if defined (XP_WIN)
+typedef BOOL (WINAPI * GetSpecialPathProc) (HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+GetSpecialPathProc gGetSpecialPathProc = NULL;
+static HINSTANCE gShell32DLLInst = NULL;
+#endif
+NS_COM_OBSOLETE void StartupSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ /* On windows, the old method to get file locations is incredibly slow.
+ As of this writing, 3 calls to GetWindowsFolder accounts for 3% of mozilla
+ startup. Replacing these older calls with a single call to SHGetSpecialFolderPath
+ effectively removes these calls from the performace radar. We need to
+ support the older way of file location lookup on systems that do not have
+ IE4. (Note: gets the ansi version: SHGetSpecialFolderPathA).
+ */
+ gShell32DLLInst = LoadLibrary("Shell32.dll");
+ if(gShell32DLLInst)
+ {
+ gGetSpecialPathProc = (GetSpecialPathProc) GetProcAddress(gShell32DLLInst,
+ "SHGetSpecialFolderPathA");
+ }
+#endif
+}
+
+NS_COM_OBSOLETE void ShutdownSpecialSystemDirectory()
+{
+ if (systemDirectoriesLocations)
+ {
+ systemDirectoriesLocations->Reset(DeleteSystemDirKeys);
+ delete systemDirectoriesLocations;
+ }
+#if defined (XP_WIN)
+ if (gShell32DLLInst)
+ {
+ FreeLibrary(gShell32DLLInst);
+ gShell32DLLInst = NULL;
+ gGetSpecialPathProc = NULL;
+ }
+#endif
+}
+
+#if defined (XP_WIN)
+
+static PRBool gGlobalOSInitialized = PR_FALSE;
+static PRBool gGlobalDBCSEnabledOS = PR_FALSE;
+
+//----------------------------------------------------------------------------------------
+static char* MakeUpperCase(char* aPath)
+//----------------------------------------------------------------------------------------
+{
+ // check if the Windows is DBCSEnabled once.
+ if (PR_FALSE == gGlobalOSInitialized) {
+ if (GetSystemMetrics(SM_DBCSENABLED))
+ gGlobalDBCSEnabledOS = PR_TRUE;
+ gGlobalOSInitialized = PR_TRUE;
+ }
+
+ // windows does not care about case. pu sh to uppercase:
+ int length = strlen(aPath);
+ int i = 0; /* C++ portability guide #20 */
+ if (!gGlobalDBCSEnabledOS) {
+ // for non-DBCS windows
+ for (i = 0; i < length; i++)
+ if (islower(aPath[i]))
+ aPath[i] = _toupper(aPath[i]);
+ }
+ else {
+ // for DBCS windows
+ for (i = 0; i < length; i++) {
+ if (IsDBCSLeadByte(aPath[i])) {
+ // begining of the double bye char
+ i++;
+ }
+ else {
+ if ( islower(aPath[i]))
+ aPath[i] = _toupper(aPath[i]);
+ }
+ } //end of for loop
+ }
+ return aPath;
+}
+
+//----------------------------------------------------------------------------------------
+static void GetWindowsFolder(int folder, nsFileSpec& outDirectory)
+//----------------------------------------------------------------------------------------
+{
+
+ if (gGetSpecialPathProc) {
+ TCHAR path[MAX_PATH];
+ HRESULT result = gGetSpecialPathProc(NULL, path, folder, true);
+
+ if (!SUCCEEDED(result))
+ return;
+
+ // Append the trailing slash
+ int len = PL_strlen(path);
+ if (len>1 && path[len-1] != '\\')
+ {
+ path[len] = '\\';
+ path[len + 1] = '\0';
+ }
+ outDirectory = path;
+ return;
+ }
+
+ LPMALLOC pMalloc = NULL;
+ LPSTR pBuffer = NULL;
+ LPITEMIDLIST pItemIDList = NULL;
+ int len;
+
+ // Get the shell's allocator.
+ if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
+ return;
+
+ // Allocate a buffer
+ if ((pBuffer = (LPSTR) pMalloc->Alloc(MAX_PATH + 2)) == NULL)
+ return;
+
+ // Get the PIDL for the folder.
+ if (!SUCCEEDED(SHGetSpecialFolderLocation(
+ NULL, folder, &pItemIDList)))
+ goto Clean;
+
+ if (!SUCCEEDED(SHGetPathFromIDList(pItemIDList, pBuffer)))
+ goto Clean;
+
+ // Append the trailing slash
+ len = PL_strlen(pBuffer);
+ pBuffer[len] = '\\';
+ pBuffer[len + 1] = '\0';
+
+ // Assign the directory
+ outDirectory = pBuffer;
+
+Clean:
+ // Clean up.
+ if (pItemIDList)
+ pMalloc->Free(pItemIDList);
+ if (pBuffer)
+ pMalloc->Free(pBuffer);
+
+ pMalloc->Release();
+} // GetWindowsFolder
+#endif // XP_WIN
+
+//----------------------------------------------------------------------------------------
+static void GetCurrentWorkingDirectory(nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ aFileSpec = ".";
+ return;
+} // GetCurrentWorkingDirectory
+
+//----------------------------------------------------------------------------------------
+static void GetCurrentProcessDirectory(nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+#if defined (XP_WIN)
+ char buf[MAX_PATH];
+ if ( ::GetModuleFileName(0, buf, sizeof(buf)) ) {
+ // chop of the executable name by finding the rightmost backslash
+ char* lastSlash = PL_strrchr(buf, '\\');
+ if (lastSlash)
+ *(lastSlash + 1) = '\0';
+
+ aFileSpec = buf;
+ return;
+ }
+
+#elif defined(XP_OS2)
+ PPIB ppib;
+ PTIB ptib;
+ char buffer[CCHMAXPATH];
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, CCHMAXPATH, buffer);
+ *strrchr( buffer, '\\') = '\0'; // XXX DBCS misery
+ aFileSpec = buffer;
+ return;
+
+
+#elif defined(XP_MAC)
+ // get info for the the current process to determine the directory
+ // its located in
+ OSErr err;
+ ProcessSerialNumber psn = {kNoProcess, kCurrentProcess};
+ ProcessInfoRec pInfo;
+ FSSpec tempSpec;
+
+ // initialize ProcessInfoRec before calling
+ // GetProcessInformation() or die horribly.
+ pInfo.processName = nil;
+ pInfo.processAppSpec = &tempSpec;
+ pInfo.processInfoLength = sizeof(ProcessInfoRec);
+
+ if (!(err = GetProcessInformation(&psn, &pInfo)))
+ {
+ FSSpec appFSSpec = *(pInfo.processAppSpec);
+ long theDirID = appFSSpec.parID;
+
+ Str255 name;
+ CInfoPBRec catInfo;
+ catInfo.dirInfo.ioCompletion = NULL;
+ catInfo.dirInfo.ioNamePtr = (StringPtr)&name;
+ catInfo.dirInfo.ioVRefNum = appFSSpec.vRefNum;
+ catInfo.dirInfo.ioDrDirID = theDirID;
+ catInfo.dirInfo.ioFDirIndex = -1; // -1 = query dir in ioDrDirID
+
+ if (!(err = PBGetCatInfoSync(&catInfo)))
+ {
+ aFileSpec = nsFileSpec(appFSSpec.vRefNum,
+ catInfo.dirInfo.ioDrParID,
+ name,
+ PR_TRUE);
+ return;
+ }
+ }
+#if defined(DEBUG)
+ else
+ {
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ printf( "nsSpecialSystemDirectory::VBOX_XPCOM_HOME is set to %s\n", moz5 );
+ aFileSpec = moz5;
+ return;
+ }
+ else
+ {
+ static PRBool firstWarning = PR_TRUE;
+
+ if(firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("***Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+ }
+ }
+#endif /* DEBUG */
+
+#elif defined(XP_UNIX)
+
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ // - else give the current directory
+ char buf[MAXPATHLEN];
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ aFileSpec = moz5;
+ return;
+ }
+ else
+ {
+#if defined(DEBUG)
+ static PRBool firstWarning = PR_TRUE;
+
+ if(firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+#endif /* DEBUG */
+
+ // Fall back to current directory.
+ if (getcwd(buf, sizeof(buf)))
+ {
+ aFileSpec = buf;
+ return;
+ }
+ }
+
+#elif defined(XP_BEOS)
+
+ char *moz5 = getenv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ aFileSpec = moz5;
+ return;
+ }
+ else
+ {
+ static char buf[MAXPATHLEN];
+ int32 cookie = 0;
+ image_info info;
+ char *p;
+ *buf = 0;
+ if(get_next_image_info(0, &cookie, &info) == B_OK)
+ {
+ strcpy(buf, info.name);
+ if((p = strrchr(buf, '/')) != 0)
+ {
+ *p = 0;
+ aFileSpec = buf;
+ return;
+ }
+ }
+ }
+
+#endif
+
+ NS_ERROR("unable to get current process directory");
+} // GetCurrentProcessDirectory()
+
+//nsSpecialSystemDirectory::nsSpecialSystemDirectory()
+//: nsFileSpec(nsnull)
+//{
+//}
+
+//----------------------------------------------------------------------------------------
+nsSpecialSystemDirectory::nsSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory)
+//----------------------------------------------------------------------------------------
+: nsFileSpec(nsnull)
+{
+ *this = aSystemSystemDirectory;
+}
+
+//----------------------------------------------------------------------------------------
+nsSpecialSystemDirectory::~nsSpecialSystemDirectory()
+//----------------------------------------------------------------------------------------
+{
+}
+
+//----------------------------------------------------------------------------------------
+void nsSpecialSystemDirectory::operator = (SystemDirectories aSystemSystemDirectory)
+//----------------------------------------------------------------------------------------
+{
+ SystemDirectoriesKey dirKey(aSystemSystemDirectory);
+ SystemDirectoriesKey mozBinDirKey(Moz_BinDirectory);
+
+ // This flag is used to tell whether or not we need to append something
+ // onto the *this. Search for needToAppend to how it's used.
+ // IT's VERY IMPORTANT that needToAppend is initialized to PR_TRUE.
+ PRBool needToAppend = PR_TRUE;
+
+#ifdef XP_MAC
+ OSErr err;
+ short vRefNum;
+ long dirID;
+#endif
+
+ *this = (const char*)nsnull;
+ switch (aSystemSystemDirectory)
+ {
+
+ case OS_DriveDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+ if (len)
+ {
+ if ( path[1] == ':' && path[2] == '\\' )
+ path[3] = 0;
+ }
+ *this = MakeUpperCase(path);
+ }
+#elif defined(XP_OS2)
+ {
+ // printf( "*** Warning warning OS_DriveDirectory called for");
+
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+ *this = buffer;
+#ifdef DEBUG
+ printf( "Got OS_DriveDirectory: %s\n", buffer);
+#endif
+ }
+#elif defined(XP_MAC)
+ {
+ *this = kVolumeRootFolderType;
+ }
+#else
+ *this = "/";
+#endif
+ break;
+
+
+ case OS_TemporaryDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ DWORD len = GetTempPath(_MAX_PATH, path);
+ *this = MakeUpperCase(path);
+ }
+#elif defined(XP_OS2)
+ {
+ char buffer[CCHMAXPATH] = "";
+ char *c = getenv( "TMP");
+ if( c) strcpy( buffer, c);
+ else
+ {
+ c = getenv( "TEMP");
+ if( c) strcpy( buffer, c);
+ }
+ if( c) *this = buffer;
+ // use exe's directory if not set
+ else GetCurrentProcessDirectory(*this);
+ }
+#elif defined(XP_MAC)
+ *this = kTemporaryFolderType;
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ {
+ static const char *tPath = nsnull;
+ if (!tPath) {
+ tPath = PR_GetEnv("TMPDIR");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TMP");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TEMP");
+ if (!tPath || !*tPath) {
+ tPath = "/tmp/";
+ }
+ }
+ }
+ }
+
+ *this = tPath;
+ }
+#endif
+ break;
+
+ case OS_CurrentProcessDirectory:
+ GetCurrentProcessDirectory(*this);
+ break;
+
+ case OS_CurrentWorkingDirectory:
+ GetCurrentWorkingDirectory(*this);
+ break;
+
+ case XPCOM_CurrentProcessComponentRegistry:
+ {
+ nsFileSpec *dirSpec = NULL;
+
+ // if someone has called nsSpecialSystemDirectory::Set()
+ if (systemDirectoriesLocations) {
+ // look for the value for the argument key
+ if (!(dirSpec = (nsFileSpec *)systemDirectoriesLocations->Get(&dirKey))) {
+ // if not found, try Moz_BinDirectory
+ dirSpec = (nsFileSpec *)
+ systemDirectoriesLocations->Get(&mozBinDirKey);
+ }
+ else {
+ // if the value is found for the argument key,
+ // we don't need to append.
+ needToAppend = PR_FALSE;
+ }
+ }
+
+ if (dirSpec)
+ {
+ *this = *dirSpec;
+ }
+ else
+ {
+ GetCurrentProcessDirectory(*this);
+ }
+
+ if (needToAppend) {
+ // XXX We need to unify these names across all platforms
+#if defined(XP_MAC)
+ *this += "Component Registry";
+#else
+ *this += "component.reg";
+#endif /* XP_MAC */
+ }
+ }
+ break;
+
+ case XPCOM_CurrentProcessComponentDirectory:
+ {
+ nsFileSpec *dirSpec = NULL;
+ // if someone has called nsSpecialSystemDirectory::Set()
+ if (systemDirectoriesLocations) {
+ // look for the value for the argument key
+ if (!(dirSpec = (nsFileSpec *)systemDirectoriesLocations->Get(&dirKey))) {
+ // if not found, try Moz_BinDirectory
+ dirSpec = (nsFileSpec *)
+ systemDirectoriesLocations->Get(&mozBinDirKey);
+ }
+ else {
+ // if the value is found for the argument key,
+ // we don't need to append.
+ needToAppend = PR_FALSE;
+ }
+ }
+ if (dirSpec)
+ {
+ *this = *dirSpec;
+ }
+ else
+ {
+ // <exedir>/Components
+ GetCurrentProcessDirectory(*this);
+ }
+
+ if (needToAppend) {
+ // XXX We need to unify these names across all platforms
+#if defined(XP_MAC)
+ *this += "Components";
+#else
+ *this += "components";
+#endif /* XP_MAC */
+ }
+ }
+ break;
+
+ case Moz_BinDirectory:
+ {
+ nsFileSpec *dirSpec = NULL;
+ // if someone has called nsSpecialSystemDirectory::Set()
+ if (systemDirectoriesLocations) {
+ // look for the value for the argument key
+ dirSpec = (nsFileSpec *)
+ systemDirectoriesLocations->Get(&dirKey);
+ }
+ if (dirSpec) {
+ *this = *dirSpec;
+ }
+ else {
+ GetCurrentProcessDirectory(*this);
+ }
+ }
+ break;
+
+#if defined(XP_MAC)
+ case Mac_SystemDirectory:
+ *this = kSystemFolderType;
+ break;
+
+ case Mac_DesktopDirectory:
+ *this = kDesktopFolderType;
+ break;
+
+ case Mac_TrashDirectory:
+ *this = kTrashFolderType;
+ break;
+
+ case Mac_StartupDirectory:
+ *this = kStartupFolderType;
+ break;
+
+ case Mac_ShutdownDirectory:
+ *this = kShutdownFolderType;
+ break;
+
+ case Mac_AppleMenuDirectory:
+ *this = kAppleMenuFolderType;
+ break;
+
+ case Mac_ControlPanelDirectory:
+ *this = kControlPanelFolderType;
+ break;
+
+ case Mac_ExtensionDirectory:
+ *this = kExtensionFolderType;
+ break;
+
+ case Mac_FontsDirectory:
+ *this = kFontsFolderType;
+ break;
+
+ case Mac_ClassicPreferencesDirectory:
+ {
+ // whether Mac OS X or pre-Mac OS X, return Classic's Prefs folder
+ short domain;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ domain = (!err && response >= 0x00001000) ? kClassicDomain : kOnSystemDisk;
+ err = ::FindFolder(domain, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ mError = NS_FILE_RESULT(err);
+ break;
+ }
+
+ case Mac_PreferencesDirectory:
+ {
+ // if Mac OS X, return Mac OS X's Prefs folder
+ // if pre-Mac OS X, return Mac OS's Prefs folder
+ err = ::FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ mError = NS_FILE_RESULT(err);
+ break;
+ }
+
+ case Mac_DocumentsDirectory:
+ *this = kDocumentsFolderType;
+ break;
+
+ case Mac_InternetSearchDirectory:
+ *this = kInternetSearchSitesFolderType;
+ break;
+
+ case Mac_DefaultDownloadDirectory:
+ *this = kDefaultDownloadFolderType;
+ break;
+
+ case Mac_UserLibDirectory:
+ {
+ err = ::FindFolder(kUserDomain, kDomainLibraryFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ mError = NS_FILE_RESULT(err);
+ break;
+ }
+#endif
+
+#if defined (XP_WIN)
+ case Win_SystemDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetSystemDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+
+ break;
+ }
+
+ case Win_WindowsDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+ break;
+ }
+
+ case Win_HomeDirectory:
+ {
+ char path[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOME"), path, _MAX_PATH) > 0)
+ {
+ PRInt32 len = PL_strlen(path);
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+ break;
+ }
+
+ if (GetEnvironmentVariable(TEXT("HOMEDRIVE"), path, _MAX_PATH) > 0)
+ {
+ char temp[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOMEPATH"), temp, _MAX_PATH) > 0)
+ PL_strcatn(path, _MAX_PATH, temp);
+
+ PRInt32 len = PL_strlen(path);
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+ break;
+ }
+ }
+ case Win_Desktop:
+ {
+ GetWindowsFolder(CSIDL_DESKTOP, *this);
+ break;
+ }
+ case Win_Programs:
+ {
+ GetWindowsFolder(CSIDL_PROGRAMS, *this);
+ break;
+ }
+ case Win_Controls:
+ {
+ GetWindowsFolder(CSIDL_CONTROLS, *this);
+ break;
+ }
+ case Win_Printers:
+ {
+ GetWindowsFolder(CSIDL_PRINTERS, *this);
+ break;
+ }
+ case Win_Personal:
+ {
+ GetWindowsFolder(CSIDL_PERSONAL, *this);
+ break;
+ }
+ case Win_Favorites:
+ {
+ GetWindowsFolder(CSIDL_FAVORITES, *this);
+ break;
+ }
+ case Win_Startup:
+ {
+ GetWindowsFolder(CSIDL_STARTUP, *this);
+ break;
+ }
+ case Win_Recent:
+ {
+ GetWindowsFolder(CSIDL_RECENT, *this);
+ break;
+ }
+ case Win_Sendto:
+ {
+ GetWindowsFolder(CSIDL_SENDTO, *this);
+ break;
+ }
+ case Win_Bitbucket:
+ {
+ GetWindowsFolder(CSIDL_BITBUCKET, *this);
+ break;
+ }
+ case Win_Startmenu:
+ {
+ GetWindowsFolder(CSIDL_STARTMENU, *this);
+ break;
+ }
+ case Win_Desktopdirectory:
+ {
+ GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, *this);
+ break;
+ }
+ case Win_Drives:
+ {
+ GetWindowsFolder(CSIDL_DRIVES, *this);
+ break;
+ }
+ case Win_Network:
+ {
+ GetWindowsFolder(CSIDL_NETWORK, *this);
+ break;
+ }
+ case Win_Nethood:
+ {
+ GetWindowsFolder(CSIDL_NETHOOD, *this);
+ break;
+ }
+ case Win_Fonts:
+ {
+ GetWindowsFolder(CSIDL_FONTS, *this);
+ break;
+ }
+ case Win_Templates:
+ {
+ GetWindowsFolder(CSIDL_TEMPLATES, *this);
+ break;
+ }
+ case Win_Common_Startmenu:
+ {
+ GetWindowsFolder(CSIDL_COMMON_STARTMENU, *this);
+ break;
+ }
+ case Win_Common_Programs:
+ {
+ GetWindowsFolder(CSIDL_COMMON_PROGRAMS, *this);
+ break;
+ }
+ case Win_Common_Startup:
+ {
+ GetWindowsFolder(CSIDL_COMMON_STARTUP, *this);
+ break;
+ }
+ case Win_Common_Desktopdirectory:
+ {
+ GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, *this);
+ break;
+ }
+ case Win_Appdata:
+ {
+ GetWindowsFolder(CSIDL_APPDATA, *this);
+ break;
+ }
+ case Win_Printhood:
+ {
+ GetWindowsFolder(CSIDL_PRINTHOOD, *this);
+ break;
+ }
+ case Win_Cookies:
+ {
+ GetWindowsFolder(CSIDL_COOKIES, *this);
+ break;
+ }
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+ case Unix_LocalDirectory:
+ *this = "/usr/local/netscape/";
+ break;
+
+ case Unix_LibDirectory:
+ *this = "/usr/local/lib/netscape/";
+ break;
+
+ case Unix_HomeDirectory:
+#ifdef VMS
+ {
+ char *pHome;
+ pHome = getenv("HOME");
+ if (*pHome == '/')
+ *this = pHome;
+ else
+ *this = decc$translate_vms(pHome);
+ }
+#else
+ *this = PR_GetEnv("HOME");
+#endif
+ break;
+
+#endif
+
+#ifdef XP_BEOS
+ case BeOS_SettingsDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_SETTINGS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+
+ case BeOS_HomeDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+
+ case BeOS_DesktopDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_DESKTOP_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+
+ case BeOS_SystemDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_BEOS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+#endif
+#ifdef XP_OS2
+ case OS2_SystemDirectory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\System\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+ *this = buffer;
+#ifdef DEBUG
+ printf( "Got OS2_SystemDirectory: %s\n", buffer);
+#endif
+ break;
+ }
+
+ case OS2_OS2Directory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+ *this = buffer;
+#ifdef DEBUG
+ printf( "Got OS2_OS2Directory: %s\n", buffer);
+#endif
+ break;
+ }
+
+ case OS2_HomeDirectory:
+ {
+ char *tPath = PR_GetEnv("MOZILLA_HOME");
+ /* If MOZILLA_HOME is not set, use GetCurrentProcessDirectory */
+ /* To ensure we get a long filename system */
+ if (!tPath || !*tPath)
+ GetCurrentProcessDirectory(*this);
+ else
+ *this = tPath;
+ PrfWriteProfileString(HINI_USERPROFILE, "Mozilla", "Home", *this);
+ break;
+ }
+
+ case OS2_DesktopDirectory:
+ {
+ char szPath[CCHMAXPATH + 1];
+ BOOL fSuccess;
+ fSuccess = WinQueryActiveDesktopPathname (szPath, sizeof(szPath));
+ int len = strlen (szPath);
+ if (len > CCHMAXPATH -1)
+ break;
+ szPath[len] = '\\';
+ szPath[len + 1] = '\0';
+#ifdef DEBUG
+ if (fSuccess) {
+ printf ("Got OS2_DesktopDirectory: %s\n", szPath);
+ } else {
+ printf ("Failed getting OS2_DesktopDirectory: %s\n", szPath);
+ }
+#endif
+ break;
+ }
+
+#endif
+ default:
+ break;
+ }
+}
+
+void
+nsSpecialSystemDirectory::Set(SystemDirectories dirToSet, nsFileSpec *dirSpec)
+{
+ SystemDirectoriesKey dirKey(dirToSet);
+
+ PR_ASSERT(NULL != dirSpec);
+
+ if (NULL == systemDirectoriesLocations) {
+ systemDirectoriesLocations = new nsHashtable(NS_SYSTEMDIR_HASH_NUM);
+ }
+ PR_ASSERT(NULL != systemDirectoriesLocations);
+
+ nsFileSpec *newSpec = new nsFileSpec(*dirSpec);
+ if (NULL != newSpec) {
+ systemDirectoriesLocations->Put(&dirKey, newSpec);
+ }
+
+ return;
+}
+
+#if defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsSpecialSystemDirectory::nsSpecialSystemDirectory(OSType folderType)
+//----------------------------------------------------------------------------------------
+{
+ *this = folderType;
+}
+
+//----------------------------------------------------------------------------------------
+void nsSpecialSystemDirectory::operator = (OSType folderType)
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cinfo;
+ DirInfo *dipb=(DirInfo *)&cinfo;
+
+ // hack: first check for kDefaultDownloadFolderType
+ // if it is, get Internet Config Download folder, if that's
+ // not availble use desktop folder
+ if (folderType == kDefaultDownloadFolderType)
+ {
+ nsCOMPtr<nsIInternetConfigService> icService (do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID));
+ if (icService)
+ {
+ if (NS_SUCCEEDED(icService->GetDownloadFolder(&mSpec)))
+ return;
+ else
+ folderType = kDesktopFolderType;
+ }
+ else
+ {
+ folderType = kDesktopFolderType;
+ }
+ }
+ // Call FindFolder to fill in the vrefnum and dirid
+ for (int attempts = 0; attempts < 2; attempts++)
+ {
+ mError = NS_FILE_RESULT(
+ FindFolder(
+ kOnSystemDisk,
+ folderType,
+ true,
+ &dipb->ioVRefNum,
+ &dipb->ioDrDirID));
+ if (NS_SUCCEEDED(mError))
+ break;
+ if (attempts > 0)
+ return;
+ switch (folderType)
+ {
+ case kDocumentsFolderType:
+ // Find folder will find this, as long as it exists.
+ // The "create" parameter, however, is sadly ignored.
+ // How do we internationalize this?
+ *this = kVolumeRootFolderType;
+ *this += "Documents";
+ CreateDirectory();
+ break;
+ } // switch
+ } // for
+ StrFileName filename;
+ filename[0] = '\0';
+ dipb->ioNamePtr = (StringPtr)&filename;
+ dipb->ioFDirIndex = -1;
+
+ mError = NS_FILE_RESULT(PBGetCatInfoSync(&cinfo));
+ if (NS_SUCCEEDED(mError))
+ {
+ mError = NS_FILE_RESULT(FSMakeFSSpec(dipb->ioVRefNum, dipb->ioDrParID, filename, &mSpec));
+ }
+}
+#endif // XP_MAC
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h
new file mode 100644
index 00000000..577cd0c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h
@@ -0,0 +1,167 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _NSSPECIALSYSTEMDIRECTORY_H_
+#define _NSSPECIALSYSTEMDIRECTORY_H_
+
+#include "xpcomobsolete.h"
+#include "nsFileSpec.h"
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#include <Types.h>
+#endif
+
+
+extern NS_COM_OBSOLETE void StartupSpecialSystemDirectory();
+extern NS_COM_OBSOLETE void ShutdownSpecialSystemDirectory();
+
+
+// SEE ALSO:
+// mozilla/xpfe/appshell/public/nsFileLocations.h
+
+class NS_COM_OBSOLETE nsSpecialSystemDirectory : public nsFileSpec
+{
+
+ public:
+ enum SystemDirectories
+ {
+ OS_DriveDirectory = 1
+ , OS_TemporaryDirectory = 2
+ , OS_CurrentProcessDirectory= 3
+ , OS_CurrentWorkingDirectory= 4
+
+ , XPCOM_CurrentProcessComponentDirectory= 5
+ , XPCOM_CurrentProcessComponentRegistry= 6
+
+ , Moz_BinDirectory = 10
+
+ , Mac_SystemDirectory = 101
+ , Mac_DesktopDirectory = 102
+ , Mac_TrashDirectory = 103
+ , Mac_StartupDirectory = 104
+ , Mac_ShutdownDirectory = 105
+ , Mac_AppleMenuDirectory = 106
+ , Mac_ControlPanelDirectory = 107
+ , Mac_ExtensionDirectory = 108
+ , Mac_FontsDirectory = 109
+ , Mac_ClassicPreferencesDirectory = 110
+ , Mac_DocumentsDirectory = 111
+ , Mac_InternetSearchDirectory = 112
+ , Mac_DefaultDownloadDirectory = 113
+ , Mac_UserLibDirectory = 114
+ , Mac_PreferencesDirectory = 115
+
+ , Win_SystemDirectory = 201
+ , Win_WindowsDirectory = 202
+
+ , Win_HomeDirectory = 203
+ , Win_Desktop = 204
+ , Win_Programs = 205
+ , Win_Controls = 206
+ , Win_Printers = 207
+ , Win_Personal = 208
+ , Win_Favorites = 209
+ , Win_Startup = 210
+ , Win_Recent = 211
+ , Win_Sendto = 212
+ , Win_Bitbucket = 213
+ , Win_Startmenu = 214
+ , Win_Desktopdirectory = 215
+ , Win_Drives = 216
+ , Win_Network = 217
+ , Win_Nethood = 218
+ , Win_Fonts = 219
+ , Win_Templates = 220
+ , Win_Common_Startmenu = 221
+ , Win_Common_Programs = 222
+ , Win_Common_Startup = 223
+ , Win_Common_Desktopdirectory = 224
+ , Win_Appdata = 225
+ , Win_Printhood = 226
+ , Win_Cookies = 227
+
+ , Unix_LocalDirectory = 301
+ , Unix_LibDirectory = 302
+ , Unix_HomeDirectory = 303
+
+ , BeOS_SettingsDirectory = 401
+ , BeOS_HomeDirectory = 402
+ , BeOS_DesktopDirectory = 403
+ , BeOS_SystemDirectory = 404
+
+ , OS2_SystemDirectory = 501
+ , OS2_OS2Directory = 502
+ , OS2_DesktopDirectory = 503
+ , OS2_HomeDirectory = 504
+ };
+
+ //nsSpecialSystemDirectory();
+ nsSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory);
+
+ virtual ~nsSpecialSystemDirectory();
+
+ void operator = (SystemDirectories aSystemSystemDirectory);
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+ void operator = (OSType folderType);
+ nsSpecialSystemDirectory(OSType folderType);
+ enum {
+ kDefaultDownloadFolderType = FOUR_CHAR_CODE('DfDÄ') /* Default Download Folder */
+ };
+#endif
+
+ /**
+
+ * @param: dirToSet, the value to set for this safeLocation
+
+ * @param: dirSpec, the directory specified as a filespec
+
+ */
+
+ static void Set(SystemDirectories dirToSet, nsFileSpec *dirSpec);
+
+
+private:
+ void operator = (const char* inPath) { *(nsFileSpec*)this = inPath; }
+
+}; // class NS_COM_OBSOLETE nsSpecialSystemDirectory
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp
new file mode 100644
index 00000000..45391c0f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsIGenericFactory.h"
+
+#include "nsFileSpecImpl.h"
+
+#define COMPONENT(NAME, Ctor) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
+
+
+static const nsModuleComponentInfo components[] =
+{
+ COMPONENT(FILESPEC, nsFileSpecImpl::Create),
+ COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create),
+};
+
+NS_IMPL_NSGETMODULE(xpcomObsoleteModule, components)
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h
new file mode 100644
index 00000000..13914115
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 xpcomobsolete_h___
+#define xpcomobsolete_h___
+
+#include "nscore.h"
+
+#ifdef _IMPL_NS_COM_OBSOLETE
+#define NS_COM_OBSOLETE NS_EXPORT
+#else
+#define NS_COM_OBSOLETE NS_IMPORT
+#endif
+
+#endif /* !defined(xpcomobsolete_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg
new file mode 100644
index 00000000..d44a8939
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg
@@ -0,0 +1,7 @@
+[gecko xpi-bootstrap]
+#if SHARED_LIBRARY
+dist/bin/@SHARED_LIBRARY@
+#endif
+
+[gecko]
+!xpt dist/bin/components/xpcom_obsolete.xpt
diff --git a/src/libs/xpcom18a4/xpcom/proxy/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/Makefile.in
new file mode 100644
index 00000000..c30f214f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org Code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in
new file mode 100644
index 00000000..d6950b9a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in
@@ -0,0 +1,63 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+ifeq ($(OS_ARCH),WINNT)
+XPIDL_MODULE = proxyObject
+else
+XPIDL_MODULE = proxyObjInst
+endif
+
+EXPORTS = \
+ nsProxyEvent.h \
+ nsProxyRelease.h \
+ nsProxiedService.h \
+ $(NULL)
+
+XPIDLSRCS = nsIProxyCreateInstance.idl \
+ nsIProxyObjectManager.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl
new file mode 100644
index 00000000..cd576f7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(948c2080-0398-11d3-915e-0000863011c4)]
+interface nsIProxyCreateInstance : nsISupports
+{
+ [noscript] void CreateInstanceByIID(in nsIIDRef cid,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ out voidPtr result);
+
+ [noscript] void CreateInstanceByContractID(in string aContractID,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ out voidPtr result);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl
new file mode 100644
index 00000000..5b2cfd4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com> (Original Author)
+ * Dan Mosedale <dmose@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsISupports.idl"
+interface nsIEventQueue;
+
+[scriptable, uuid(eea90d43-b059-11d2-915e-c12b696c9333)]
+interface nsIProxyObjectManager : nsISupports
+{
+ void getProxyForObject(in nsIEventQueue destQueue,
+ in nsIIDRef iid,
+ in nsISupports object,
+ in PRInt32 proxyType,
+ [iid_is(iid),retval] out nsQIResult result);
+
+ void getProxy(in nsIEventQueue destQueue,
+ in nsIIDRef cid,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ in PRInt32 proxyType,
+ [iid_is(iid),retval] out nsQIResult result);
+
+};
+
+
+%{C++
+#include "nsProxyEvent.h"
+
+#define NS_XPCOMPROXY_CONTRACTID "@mozilla.org/xpcomproxy;1"
+#define NS_XPCOMPROXY_CLASSNAME "XPCom Proxy"
+
+#define NS_PROXYEVENT_MANAGER_CID \
+{ 0xeea90d41, \
+ 0xb059, \
+ 0x11d2, \
+ {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\
+}
+
+/**
+ * Helper function for code that already has a link-time dependency on
+ * libxpcom and needs to get proxies in a bunch of different places.
+ * This way, the caller isn't forced to get the proxy object manager
+ * themselves every single time, thus making the calling code more
+ * readable.
+ */
+extern NS_COM nsresult
+NS_GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h
new file mode 100644
index 00000000..3a39ade1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsProxiedServiceManager_h_
+#define __nsProxiedServiceManager_h_
+
+#include "nsIServiceManager.h"
+#include "nsIProxyObjectManager.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// NS_WITH_PROXIED_SERVICE: macro to make using services that need to be proxied
+// before using them easier.
+// Now you can replace this:
+// {
+// nsresult rv;
+// nsCOMPtr<nsIMyService> pIMyService =
+// do_GetService(kMyServiceCID, &rv);
+// if(NS_FAILED(rv))
+// return;
+// nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
+// do_GetService(kProxyObjectManagerCID, &rv);
+// if(NS_FAILED(rv))
+// return;
+// nsIMyService pIProxiedObject = NULL;
+// rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue,
+// NS_GET_IID(nsIMyService),
+// pIMyService, PROXY_SYNC,
+// (void**)&pIProxiedObject);
+// pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue
+// ...
+// pIProxiedObject->Release(); // Must be done as not managed for you.
+// }
+// with this:
+// {
+// nsresult rv;
+// NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID,
+// pIProxyQueue, &rv);
+// if(NS_FAILED(rv))
+// return;
+// pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue
+// }
+// and the automatic destructor will take care of releasing the service and
+// the proxied object for you.
+//
+// Note that this macro requires you to link with the xpcom DLL to pick up the
+// static member functions from nsServiceManager.
+
+#define NS_WITH_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
+ nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, PR_FALSE, rvAddr); \
+ T* var = (T*)(nsISupports*)_serv##var;
+
+#define NS_WITH_ALWAYS_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
+ nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, PR_TRUE, rvAddr); \
+ T* var = (T*)(nsISupports*)_serv##var;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsProxiedService
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxiedService
+{
+ public:
+
+ nsProxiedService(const nsCID &aClass, const nsIID &aIID,
+ nsIEventQueue* pIProxyQueue, PRBool always, nsresult*rv)
+ {
+ *rv = nsServiceManager::GetService(aClass,
+ aIID,
+ getter_AddRefs(mService));
+ if (NS_FAILED(*rv)) return;
+ InitProxy(aIID, pIProxyQueue, always, rv);
+ }
+
+ nsProxiedService(const char* aContractID, const nsIID &aIID,
+ nsIEventQueue* pIProxyQueue, PRBool always, nsresult*rv)
+ {
+ *rv = nsServiceManager::GetService(aContractID,
+ aIID,
+ getter_AddRefs(mService));
+ if (NS_FAILED(*rv)) return;
+ InitProxy(aIID, pIProxyQueue, always, rv);
+ }
+
+ void InitProxy(const nsIID &aIID, nsIEventQueue* pIProxyQueue,
+ PRBool always, nsresult*rv)
+ {
+ static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
+
+ nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
+ do_GetService(kProxyObjectManagerCID, rv);
+ if (NS_FAILED(*rv)) return;
+
+ PRInt32 proxyType = PROXY_SYNC;
+ if (always) proxyType |= PROXY_ALWAYS;
+ *rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue,
+ aIID,
+ mService,
+ proxyType,
+ getter_AddRefs(mProxiedService));
+ }
+
+ ~nsProxiedService()
+ {
+ }
+
+ nsISupports* operator->() const
+ {
+ NS_PRECONDITION(mProxiedService != 0, "Your code should test the error result from the constructor.");
+ return mProxiedService;
+ }
+
+ PRBool operator==(const nsISupports* other)
+ {
+ return ((mProxiedService == other) || (mService == other));
+ }
+
+ operator nsISupports*() const
+ {
+ return mProxiedService;
+ }
+
+ protected:
+ nsCOMPtr<nsISupports> mProxiedService;
+ nsCOMPtr<nsISupports> mService;
+
+ };
+
+
+#endif //__nsProxiedServiceManager_h_
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h
new file mode 100644
index 00000000..c718bbdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsProxyEvent_h_
+#define __nsProxyEvent_h_
+
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIFactory.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIEventQueue.h"
+#include "plevent.h"
+#include "prtypes.h"
+#include "xptcall.h"
+#include "xptinfo.h"
+
+class nsProxyObjectCallInfo;
+
+#define PROXY_SYNC 0x0001 // acts just like a function call.
+#define PROXY_ASYNC 0x0002 // fire and forget. This will return immediately and you will lose all return information.
+#define PROXY_ALWAYS 0x0004 // ignore check to see if the eventQ is on the same thread as the caller, and alway return a proxied object.
+
+//#define AUTOPROXIFICATION
+
+// WARNING about PROXY_ASYNC:
+//
+// If the calling thread goes away, any function which accesses the calling stack
+// will blow up.
+//
+// example:
+//
+// myFoo->bar(&x)
+//
+// ... thread goes away ...
+//
+// bar(PRInt32 *x)
+// {
+// *x = 0; <----- You will blow up here.
+//
+//
+// So what gets saved?
+//
+// You can safely pass base types by value. You can also pass interface pointers.
+// I will make sure that the interface pointers are addrefed while they are being
+// proxied. You can also pass string and wstring. These I will copy and free.
+//
+// I do **NOT** copy arrays or strings with size. If you are using these either
+// change your interface, or contact me about this feature request.
+
+
+
+
+class nsProxyObject
+{
+public:
+ nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject);
+ nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID);
+
+ void AddRef();
+ void Release();
+
+ ~nsProxyObject();
+
+ nsresult Post( PRUint32 methodIndex,
+ nsXPTMethodInfo * info,
+ nsXPTCMiniVariant * params,
+ nsIInterfaceInfo * interfaceInfo);
+
+ nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo);
+ nsISupports* GetRealObject() const { return mRealObject; }
+ nsIEventQueue* GetQueue() const { return mDestQueue; }
+ PRInt32 GetProxyType() const { return mProxyType; }
+
+ friend class nsProxyEventObject;
+private:
+
+ nsAutoRefCnt mRefCnt;
+
+ PRInt32 mProxyType;
+
+ nsCOMPtr<nsIEventQueue> mDestQueue; /* destination queue */
+
+ nsCOMPtr<nsISupports> mRealObject; /* the non-proxy object that this event is referring to.
+ This is a strong ref. */
+ nsCOMPtr<nsIEventQueueService> mEventQService;
+
+ nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo,
+ nsXPTCMiniVariant * params,
+ nsXPTCVariant **fullParam,
+ uint8 *paramCount);
+
+};
+
+
+class nsProxyObjectCallInfo
+{
+public:
+
+ nsProxyObjectCallInfo(nsProxyObject* owner,
+ nsXPTMethodInfo *methodInfo,
+ PRUint32 methodIndex,
+ nsXPTCVariant* parameterList,
+ PRUint32 parameterCount,
+ PLEvent *event);
+
+ ~nsProxyObjectCallInfo();
+
+ PRUint32 GetMethodIndex() const { return mMethodIndex; }
+ nsXPTCVariant* GetParameterList() const { return mParameterList; }
+ PRUint32 GetParameterCount() const { return mParameterCount; }
+ PLEvent* GetPLEvent() const { return mEvent; }
+ nsresult GetResult() const { return mResult; }
+ nsProxyObject* GetProxyObject() const { return mOwner; }
+
+ PRBool GetCompleted();
+ void SetCompleted();
+ void PostCompleted();
+
+ void SetResult(nsresult rv) {mResult = rv; }
+
+ nsIEventQueue* GetCallersQueue();
+ void SetCallersQueue(nsIEventQueue* queue);
+
+private:
+
+ nsresult mResult; /* this is the return result of the called function */
+ nsXPTMethodInfo *mMethodInfo;
+ PRUint32 mMethodIndex; /* which method to be called? */
+ nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */
+ PRUint32 mParameterCount; /* number of params */
+ PLEvent *mEvent; /* the current plevent */
+ PRInt32 mCompleted; /* is true when the method has been called. */
+
+ nsCOMPtr<nsIEventQueue> mCallersEventQ; /* this is the eventQ that we must post a message back to
+ when we are done invoking the method (only PROXY_SYNC).
+ */
+
+ nsRefPtr<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
+
+ void RefCountInInterfacePointers(PRBool addRef);
+ void CopyStrings(PRBool copy);
+
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h
new file mode 100644
index 00000000..413a3d0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsProxyRelease_h__
+#define nsProxyRelease_h__
+
+#include "nsIEventQueueService.h"
+#include "pratom.h"
+#include "prmem.h"
+
+/**
+ * Ensures that the delete of a nsISupports object occurs on the target thread.
+ *
+ * @param target
+ * the target thread where the doomed object should be released.
+ * @param doomed
+ * the doomed object; the object to be released on the target thread.
+ * @param alwaysProxy
+ * normally, if NS_ProxyRelease is called on the target thread, then the
+ * doomed object will released directly. however, if this parameter is
+ * true, then a PLEvent will always be posted to the target thread and
+ * the release will happen when that PLEvent is handled.
+ */
+NS_COM nsresult NS_ProxyRelease
+ (nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE);
+
+
+#define NS_IMPL_PROXY_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \
+ NS_LOG_RELEASE(this, count, #_class); \
+ \
+ if (count == 0) \
+ { \
+ mRefCnt = 1; /* stabilize */ \
+ PRBool callDirectly = PR_TRUE; \
+ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); \
+ nsCOMPtr<nsIEventQueueService> eventQService \
+ = do_GetService(kEventQueueServiceCID); \
+ NS_ASSERTION(eventQService, "event queue service is unavailable"); \
+ \
+ nsCOMPtr<nsIEventQueue> eventQ; \
+ if (eventQService) { \
+ eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eventQ)); \
+ if (eventQ) \
+ eventQ->IsOnCurrentThread(&callDirectly); \
+ } \
+ \
+ if (callDirectly) \
+ { \
+ NS_RELEASE(this); \
+ return 0; \
+ } \
+ PLEvent *event = new PLEvent; \
+ if (event == nsnull) \
+ { \
+ NS_ASSERTION(0, "Could not create a plevent. Deleting on wrong thread!"); \
+ NS_DELETEXPCOM(this); \
+ return 0; \
+ } \
+ \
+ PL_InitEvent(event, \
+ NS_STATIC_CAST(nsISupports*, this), \
+ ReleaseDestructorEventHandler, \
+ ReleaseDestructorDestroyHandler); \
+ \
+ eventQ->PostEvent(event); \
+ return 0; \
+ } \
+ return count; \
+} \
+
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in
new file mode 100644
index 00000000..3d46f60b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in
@@ -0,0 +1,67 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xpcomproxy_s
+REQUIRES = string \
+ $(NULL)
+
+
+CPPSRCS = \
+ nsProxyEvent.cpp \
+ nsProxyEventClass.cpp \
+ nsProxyEventObject.cpp \
+ nsProxyObjectManager.cpp \
+ nsProxyRelease.cpp \
+ $(NULL)
+
+DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTC_API -DEXPORT_XPTI_API
+
+# No shared lib; Force creation of static lib
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h b/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h
new file mode 100644
index 00000000..13755d74
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h
@@ -0,0 +1,39 @@
+/*
+ * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIProxyCreateInstance.idl
+ */
+
+#ifndef __gen_nsIProxyCreateInstance_h__
+#define __gen_nsIProxyCreateInstance_h__
+
+#include "nsISupports.h" /* interface nsISupports */
+#include "nsrootidl.h" /* interface nsrootidl */
+
+#ifdef XPIDL_JS_STUBS
+#include "jsapi.h"
+#endif
+
+/* starting interface: nsIProxyCreateInstance */
+
+/* {948c2080-0398-11d3-915e-0000863011c4} */
+#define NS_IPROXYCREATEINSTANCE_IID_STR "948c2080-0398-11d3-915e-0000863011c4"
+#define NS_IPROXYCREATEINSTANCE_IID \
+ {0x948c2080, 0x0398, 0x11d3, \
+ { 0x91, 0x5e, 0x00, 0x00, 0x86, 0x30, 0x11, 0xc4 }}
+
+class nsIProxyCreateInstance : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPROXYCREATEINSTANCE_IID)
+
+ /* void CreateInstanceByIID (in nsIIDRef cid, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */
+ NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result) = 0;
+
+ /* void CreateInstanceByContractID (in string aContractID, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */
+ NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result) = 0;
+
+#ifdef XPIDL_JS_STUBS
+ static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx);
+ static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIProxyCreateInstance *priv);
+#endif
+};
+
+#endif /* __gen_nsIProxyCreateInstance_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp
new file mode 100644
index 00000000..561c2fdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+#include "nsProxyEvent.h"
+#include "nsProxyEventPrivate.h"
+#include "nsIProxyObjectManager.h"
+#include "nsCRT.h"
+
+#include "pratom.h"
+#include "prmem.h"
+#include "xptcall.h"
+
+#include "nsIComponentManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsIServiceManager.h"
+#include "nsMemory.h"
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+#include "nsIAtom.h" //hack! Need a way to define a component as threadsafe (ie. sta).
+
+/**
+ * Map the nsAUTF8String, nsUTF8String classes to the nsACString and
+ * nsCString classes respectively for now. These defines need to be removed
+ * once Jag lands his nsUTF8String implementation.
+ */
+#define nsAUTF8String nsACString
+#define nsUTF8String nsCString
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+static void* PR_CALLBACK EventHandler(PLEvent *self);
+static void PR_CALLBACK DestroyHandler(PLEvent *self);
+static void* PR_CALLBACK CompletedEventHandler(PLEvent *self);
+static void PR_CALLBACK CompletedDestroyHandler(PLEvent *self) ;
+static void* PR_CALLBACK ProxyDestructorEventHandler(PLEvent *self);
+static void PR_CALLBACK ProxyDestructorDestroyHandler(PLEvent *self) ;
+
+nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner,
+ nsXPTMethodInfo *methodInfo,
+ PRUint32 methodIndex,
+ nsXPTCVariant* parameterList,
+ PRUint32 parameterCount,
+ PLEvent *event)
+{
+ NS_ASSERTION(owner, "No nsProxyObject!");
+ NS_ASSERTION(methodInfo, "No nsXPTMethodInfo!");
+ NS_ASSERTION(event, "No PLEvent!");
+
+ mCompleted = 0;
+ mMethodIndex = methodIndex;
+ mParameterList = parameterList;
+ mParameterCount = parameterCount;
+ mEvent = event;
+ mMethodInfo = methodInfo;
+ mCallersEventQ = nsnull;
+
+ mOwner = owner;
+
+ RefCountInInterfacePointers(PR_TRUE);
+ if (mOwner->GetProxyType() & PROXY_ASYNC)
+ CopyStrings(PR_TRUE);
+}
+
+
+nsProxyObjectCallInfo::~nsProxyObjectCallInfo()
+{
+ RefCountInInterfacePointers(PR_FALSE);
+ if (mOwner->GetProxyType() & PROXY_ASYNC)
+ CopyStrings(PR_FALSE);
+
+ mOwner = nsnull;
+
+ PR_FREEIF(mEvent);
+
+ if (mParameterList)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free((void*) mParameterList);
+#else
+ free( (void*) mParameterList);
+#endif
+}
+
+void
+nsProxyObjectCallInfo::RefCountInInterfacePointers(PRBool addRef)
+{
+ for (PRUint32 i = 0; i < mParameterCount; i++)
+ {
+ nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
+
+ if (paramInfo.GetType().IsInterfacePointer() )
+ {
+ nsISupports* anInterface = nsnull;
+
+ if (paramInfo.IsIn())
+ {
+ anInterface = ((nsISupports*)mParameterList[i].val.p);
+
+ if (anInterface)
+ {
+ if(addRef)
+ anInterface->AddRef();
+ else
+ anInterface->Release();
+
+ }
+ }
+ }
+ }
+}
+
+void
+nsProxyObjectCallInfo::CopyStrings(PRBool copy)
+{
+ for (PRUint32 i = 0; i < mParameterCount; i++)
+ {
+ const nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
+
+ if(paramInfo.IsIn())
+ {
+ const nsXPTType& type = paramInfo.GetType();
+ uint8 type_tag = type.TagPart();
+ void *ptr = mParameterList[i].val.p;
+
+ if (!ptr)
+ continue;
+
+ if (copy)
+ {
+ switch (type_tag)
+ {
+ case nsXPTType::T_CHAR_STR:
+ mParameterList[i].val.p =
+ PL_strdup((const char *)ptr);
+ break;
+ case nsXPTType::T_WCHAR_STR:
+ mParameterList[i].val.p =
+ nsCRT::strdup((const PRUnichar *)ptr);
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING:
+ mParameterList[i].val.p =
+ new nsString(*((nsAString*) ptr));
+ break;
+ case nsXPTType::T_CSTRING:
+ mParameterList[i].val.p =
+ new nsCString(*((nsACString*) ptr));
+ break;
+ case nsXPTType::T_UTF8STRING:
+ mParameterList[i].val.p =
+ new nsUTF8String(*((nsAUTF8String*) ptr));
+ break;
+ default:
+ // Other types are ignored
+ break;
+ }
+ }
+ else
+ {
+ switch (type_tag)
+ {
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ PL_strfree((char*) ptr);
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING:
+ delete (nsString*) ptr;
+ break;
+ case nsXPTType::T_CSTRING:
+ delete (nsCString*) ptr;
+ break;
+ case nsXPTType::T_UTF8STRING:
+ delete (nsUTF8String*) ptr;
+ break;
+ default:
+ // Other types are ignored
+ break;
+ }
+ }
+ }
+ }
+}
+
+PRBool
+nsProxyObjectCallInfo::GetCompleted()
+{
+ return (PRBool)mCompleted;
+}
+
+void
+nsProxyObjectCallInfo::SetCompleted()
+{
+ PR_AtomicSet(&mCompleted, 1);
+}
+
+void
+nsProxyObjectCallInfo::PostCompleted()
+{
+ if (mCallersEventQ)
+ {
+ PLEvent *event = PR_NEW(PLEvent);
+
+ PL_InitEvent(event,
+ this,
+ CompletedEventHandler,
+ CompletedDestroyHandler);
+
+ mCallersEventQ->PostSynchronousEvent(event, nsnull);
+ PR_FREEIF(event);
+ }
+ else
+ {
+ // caller does not have an eventQ? This is an error!
+ SetCompleted();
+ }
+}
+
+nsIEventQueue*
+nsProxyObjectCallInfo::GetCallersQueue()
+{
+ return mCallersEventQ;
+}
+void
+nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue)
+{
+ mCallersEventQ = queue;
+}
+
+
+nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject)
+{
+ mEventQService = do_GetService(kEventQueueServiceCID);
+
+ mRealObject = realObject;
+ mDestQueue = do_QueryInterface(destQueue);
+ mProxyType = proxyType;
+}
+
+
+nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID)
+{
+ mEventQService = do_GetService(kEventQueueServiceCID);
+
+ nsComponentManager::CreateInstance(aClass,
+ aDelegate,
+ aIID,
+ getter_AddRefs(mRealObject));
+
+ mDestQueue = do_QueryInterface(destQueue);
+ mProxyType = proxyType;
+}
+
+nsProxyObject::~nsProxyObject()
+{
+ // I am worried about order of destruction here.
+ // do not remove assignments.
+
+ mRealObject = 0;
+ mDestQueue = 0;
+}
+
+
+void
+nsProxyObject::AddRef()
+{
+ PR_AtomicIncrement((PRInt32 *)&mRefCnt);
+ NS_LOG_ADDREF(this, mRefCnt, "nsProxyObject", sizeof(*this));
+}
+
+void
+nsProxyObject::Release(void)
+{
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsProxyObject");
+
+ if (count == 0)
+ {
+ mRefCnt = 1; /* stabilize */
+
+ PRBool callDirectly;
+ mDestQueue->IsOnCurrentThread(&callDirectly);
+
+ if (callDirectly)
+ {
+ delete this;
+ return;
+ }
+
+ // need to do something special here so that
+ // the real object will always be deleted on
+ // the correct thread..
+
+ PLEvent *event = PR_NEW(PLEvent);
+ if (event == nsnull)
+ {
+ NS_ASSERTION(0, "Could not create a plevent. Leaking nsProxyObject!");
+ return; // if this happens we are going to leak.
+ }
+
+ PL_InitEvent(event,
+ this,
+ ProxyDestructorEventHandler,
+ ProxyDestructorDestroyHandler);
+
+ mDestQueue->PostEvent(event);
+ }
+}
+
+
+nsresult
+nsProxyObject::PostAndWait(nsProxyObjectCallInfo *proxyInfo)
+{
+ if (proxyInfo == nsnull || mEventQService == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ PRBool eventLoopCreated = PR_FALSE;
+ nsresult rv;
+
+ nsCOMPtr<nsIEventQueue> eventQ;
+ rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
+ if (NS_FAILED(rv))
+ {
+ rv = mEventQService->CreateMonitoredThreadEventQueue();
+ eventLoopCreated = PR_TRUE;
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ proxyInfo->SetCallersQueue(eventQ);
+
+ PLEvent* event = proxyInfo->GetPLEvent();
+ if (!event)
+ return NS_ERROR_NULL_POINTER;
+
+ mDestQueue->PostEvent(event);
+
+ while (! proxyInfo->GetCompleted())
+ {
+ PLEvent *nextEvent;
+ rv = eventQ->WaitForEvent(&nextEvent);
+ if (NS_FAILED(rv)) break;
+
+ eventQ->HandleEvent(nextEvent);
+ }
+
+ if (eventLoopCreated)
+ {
+ mEventQService->DestroyThreadEventQueue();
+ eventQ = 0;
+ }
+
+ return rv;
+}
+
+
+nsresult
+nsProxyObject::convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo,
+ nsXPTCMiniVariant * params,
+ nsXPTCVariant **fullParam,
+ uint8 *outParamCount)
+{
+ uint8 paramCount = methodInfo->GetParamCount();
+ *outParamCount = paramCount;
+ *fullParam = nsnull;
+
+ if (!paramCount) return NS_OK;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ *fullParam = (nsXPTCVariant*)nsMemory::Alloc(sizeof(nsXPTCVariant) * paramCount);
+#else
+ *fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount);
+#endif
+
+ if (*fullParam == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (int i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
+ if ((mProxyType & PROXY_ASYNC) && paramInfo.IsDipper())
+ {
+ NS_WARNING("Async proxying of out parameters is not supported");
+ return NS_ERROR_PROXY_INVALID_OUT_PARAMETER;
+ }
+ uint8 flags = paramInfo.IsOut() ? nsXPTCVariant::PTR_IS_DATA : 0;
+ (*fullParam)[i].Init(params[i], paramInfo.GetType(), flags);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsProxyObject::Post( PRUint32 methodIndex,
+ nsXPTMethodInfo *methodInfo,
+ nsXPTCMiniVariant * params,
+ nsIInterfaceInfo *interfaceInfo)
+{
+ nsresult rv = NS_OK;
+
+ if (! mDestQueue || ! mRealObject)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (methodInfo->IsNotXPCOM())
+ return NS_ERROR_PROXY_INVALID_IN_PARAMETER;
+
+ nsXPTCVariant *fullParam;
+ uint8 paramCount;
+ rv = convertMiniVariantToVariant(methodInfo, params, &fullParam, &paramCount);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool callDirectly;
+
+ // see if we should call into the method directly. Either it is a QI function call
+ // (methodIndex == 0), or it is a sync proxy and this code is running on the same thread
+ // as the destination event queue.
+ if ( (methodIndex == 0) ||
+ (mProxyType & PROXY_SYNC &&
+ NS_SUCCEEDED(mDestQueue->IsOnCurrentThread(&callDirectly)) &&
+ callDirectly))
+ {
+
+ // invoke the magic of xptc...
+ nsresult rv = XPTC_InvokeByIndex( mRealObject,
+ methodIndex,
+ paramCount,
+ fullParam);
+
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return rv;
+ }
+
+ PLEvent *event = PR_NEW(PLEvent);
+
+ if (event == nsnull) {
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this,
+ methodInfo,
+ methodIndex,
+ fullParam, // will be deleted by ~()
+ paramCount,
+ event); // will be deleted by ~()
+
+ if (proxyInfo == nsnull) {
+ PR_DELETE(event);
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PL_InitEvent(event,
+ proxyInfo,
+ EventHandler,
+ DestroyHandler);
+
+ if (mProxyType & PROXY_SYNC)
+ {
+ rv = PostAndWait(proxyInfo);
+
+ if (NS_SUCCEEDED(rv))
+ rv = proxyInfo->GetResult();
+ delete proxyInfo;
+ return rv;
+ }
+
+ if (mProxyType & PROXY_ASYNC)
+ {
+ mDestQueue->PostEvent(event);
+ return NS_OK;
+ }
+ return NS_ERROR_UNEXPECTED;
+}
+
+
+
+static void DestroyHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ nsProxyObject* proxyObject = owner->GetProxyObject();
+
+ if (proxyObject == nsnull)
+ return;
+
+ if (proxyObject->GetProxyType() & PROXY_ASYNC)
+ {
+ delete owner;
+ }
+ else
+ {
+ owner->PostCompleted();
+ }
+
+}
+
+static void* EventHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ NS_ASSERTION(info, "No nsProxyObjectCallInfo!");
+
+ nsProxyObject *proxyObject = info->GetProxyObject();
+
+ if (proxyObject)
+ {
+ // invoke the magic of xptc...
+ nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(),
+ info->GetMethodIndex(),
+ info->GetParameterCount(),
+ info->GetParameterList());
+ info->SetResult(rv);
+ }
+ else
+ {
+ info->SetResult(NS_ERROR_OUT_OF_MEMORY);
+ }
+ return NULL;
+}
+
+static void CompletedDestroyHandler(PLEvent *self)
+{
+}
+
+static void* CompletedEventHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ owner->SetCompleted();
+ return nsnull;
+}
+
+static void* ProxyDestructorEventHandler(PLEvent *self)
+{
+ nsProxyObject* owner = (nsProxyObject*) PL_GetEventOwner(self);
+ NS_DELETEXPCOM(owner);
+ return nsnull;
+}
+
+static void ProxyDestructorDestroyHandler(PLEvent *self)
+{
+ PR_DELETE(self);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp
new file mode 100644
index 00000000..8e221afa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp
@@ -0,0 +1,367 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+#include "nsMemory.h"
+#include "nsHashtable.h"
+
+#include "nsAutoLock.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptcall.h"
+
+// LIFETIME_CACHE will cache class for the entire cyle of the application.
+#define LIFETIME_CACHE
+
+static uint32 zero_methods_descriptor;
+
+
+/* ssc@netscape.com wishes he could get rid of this instance of
+ * |NS_DEFINE_IID|, but |ProxyEventClassIdentity| is not visible from
+ * here.
+ */
+static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+// nsProxyEventClass
+//////////////////////////////////////////////////////////////////////////////////////////////////
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyEventClass, nsProxyEventClass)
+
+// static
+nsProxyEventClass*
+nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
+{
+ /* find in our hash table */
+
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull) return nsnull;
+
+ // dont need to lock the map, because this is only called
+ // by nsProxyEventClass::GetNewOrUsed which locks it for us.
+
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap == nsnull)
+ {
+ return nsnull;
+ }
+
+ nsProxyEventClass* clazz = nsnull;
+ nsIDKey key(aIID);
+
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+
+ clazz = (nsProxyEventClass*) iidToClassMap->Get(&key);
+ if(clazz)
+ {
+ NS_ADDREF(clazz);
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s hit\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+ else
+ {
+ nsCOMPtr<nsIInterfaceInfoManager> iimgr = getter_AddRefs(XPTI_GetInterfaceInfoManager());
+ if(iimgr)
+ {
+ nsCOMPtr<nsIInterfaceInfo> info;
+ if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
+ {
+ /*
+ Check to see if isISupportsDescendent
+ */
+ nsCOMPtr<nsIInterfaceInfo> oldest = info;
+ nsCOMPtr<nsIInterfaceInfo> parent;
+
+ while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent)))&&
+ parent)
+ {
+ oldest = parent;
+ }
+
+ PRBool isISupportsDescendent = PR_FALSE;
+ nsID* iid;
+ if(NS_SUCCEEDED(oldest->GetInterfaceIID(&iid)))
+ {
+ isISupportsDescendent = iid->Equals(NS_GET_IID(nsISupports));
+ nsMemory::Free(iid);
+ }
+
+ NS_ASSERTION(isISupportsDescendent, "!isISupportsDescendent");
+
+ if (isISupportsDescendent)
+ {
+ clazz = new nsProxyEventClass(aIID, info);
+ if(!clazz->mDescriptors)
+ NS_RELEASE(clazz); // sets clazz to NULL
+ }
+ }
+ }
+ }
+ return clazz;
+}
+
+nsProxyEventClass::nsProxyEventClass()
+{
+ NS_WARNING("This constructor should never be called");
+}
+
+nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo)
+: mIID(aIID),
+ mDescriptors(NULL)
+{
+ NS_ADDREF_THIS();
+
+ mInfo = aInfo;
+
+ /* add use to the used classes */
+ nsIDKey key(aIID);
+
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull) return;
+ // dont need to lock the map, because this is only called
+ // by GetNewOrUsed which locks it for us.
+
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap != nsnull)
+ {
+ iidToClassMap->Put(&key, this);
+#ifdef LIFETIME_CACHE
+ // extra addref to hold it in the cache
+ NS_ADDREF_THIS();
+#endif
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s put\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+
+ uint16 methodCount;
+ if(NS_SUCCEEDED(mInfo->GetMethodCount(&methodCount)))
+ {
+ if(methodCount)
+ {
+ int wordCount = (methodCount/32)+1;
+ if(NULL != (mDescriptors = new uint32[wordCount]))
+ {
+ memset(mDescriptors, 0, wordCount * sizeof(uint32));
+ }
+ }
+ else
+ {
+ mDescriptors = &zero_methods_descriptor;
+ }
+ }
+}
+
+nsProxyEventClass::~nsProxyEventClass()
+{
+ if(mDescriptors && mDescriptors != &zero_methods_descriptor)
+ delete [] mDescriptors;
+
+ if (nsProxyObjectManager::IsManagerShutdown())
+ return;
+
+#ifndef LIFETIME_CACHE
+ nsIDKey key(mIID);
+
+ nsCOMPtr<nsProxyObjectManager> manager = getter_AddRefs(nsProxyObjectManager::GetInstance());
+ if (manager == nsnull) return;
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap != nsnull)
+ {
+ iidToClassMap->Remove(&key);
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = mIID.ToString();
+ printf("GetNewOrUsedClass %s remove\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+#endif
+}
+
+nsresult
+nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID, nsProxyEventObject** aInstancePtr)
+{
+ NS_PRECONDITION(aInstancePtr, "Requires non-null result");
+
+ nsresult rv;
+
+ *aInstancePtr = nsnull; // in case of error.
+
+
+ // The functions we will call: QueryInterface(REFNSIID aIID, void** aInstancePtr)
+
+ nsXPTCMiniVariant var[2];
+
+ var[0].val.p = (void*)&aIID;
+ var[1].val.p = (void*)aInstancePtr;
+
+ nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
+ const nsXPTMethodInfo *mi;
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim = getter_AddRefs(XPTI_GetInterfaceInfoManager());
+
+ if (!iim) return NS_NOINTERFACE;
+ iim->GetInfoForName("nsISupports", getter_AddRefs(interfaceInfo));
+ interfaceInfo->GetMethodInfo(0, &mi); // 0 is QueryInterface
+
+ rv = self->CallMethod(0, mi, var);
+
+ if (NS_SUCCEEDED(rv))
+ {
+ nsISupports *aIdentificationObject;
+
+ rv = (*aInstancePtr)->QueryInterface(kProxyObject_Identity_Class_IID, (void**)&aIdentificationObject);
+
+ if (NS_FAILED(rv))
+ {
+ // okay, aInstancePtr was not a proxy. Lets create one.
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull)
+ {
+ NS_IF_RELEASE((*aInstancePtr));
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = manager->GetProxyForObject(self->GetQueue(),
+ aIID,
+ self->GetRealObject(),
+ self->GetProxyType(),
+ (void**) &aIdentificationObject);
+ }
+
+ NS_IF_RELEASE((*aInstancePtr));
+ (*aInstancePtr) = NS_STATIC_CAST(nsProxyEventObject*, aIdentificationObject);
+ }
+ return rv;
+}
+
+
+/***************************************************************************/
+// This 'ProxyEventClassIdentity' class and singleton allow us to figure out if
+// any given nsISupports* is implemented by a nsProxy object. This is done
+// using a QueryInterface call on the interface pointer with our ID. If
+// that call returns NS_OK and the pointer is to a nsProxyEventObject. It must
+// be released when done.
+
+// NS_PROXYEVENT_IDENTITY_CLASS_IID defined in nsProxyEventPrivate.h
+class ProxyEventClassIdentity
+{
+ // no instance methods...
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_IDENTITY_CLASS_IID)
+
+ static void* GetSingleton()
+ {
+ static ProxyEventClassIdentity* singleton = NULL;
+ if(!singleton)
+ singleton = new ProxyEventClassIdentity();
+ return (void*) singleton;
+ }
+};
+
+NS_IMETHODIMP
+nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self,
+ REFNSIID aIID,
+ void** aInstancePtr)
+{
+
+ if(aIID.Equals(NS_GET_IID(ProxyEventClassIdentity)))
+ {
+ *aInstancePtr = NS_STATIC_CAST(void*, self);
+ NS_ADDREF(self);
+ return NS_OK;
+ }
+
+ nsProxyEventObject* sibling;
+ {
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsAutoMonitor mon(manager->GetMonitor());
+
+ // This includes checking for nsISupports and the iid of self.
+ // And it also checks for other wrappers that have been constructed
+ // for this object.
+ if(nsnull != (sibling = self->LockedFind(aIID)))
+ {
+ NS_ADDREF(sibling);
+ *aInstancePtr = (void*) sibling;
+ return NS_OK;
+ }
+
+ // check if asking for an interface that we inherit from
+ nsCOMPtr<nsIInterfaceInfo> current = GetInterfaceInfo();
+ nsCOMPtr<nsIInterfaceInfo> parent;
+
+ while(NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent)
+ {
+ current = parent;
+
+ nsIID* iid;
+ if(NS_SUCCEEDED(current->GetInterfaceIID(&iid)) && iid)
+ {
+ PRBool found = aIID.Equals(*iid);
+ nsMemory::Free(iid);
+ if(found)
+ {
+ *aInstancePtr = (void*) self;
+ NS_ADDREF(self);
+ return NS_OK;
+ }
+ }
+ }
+ }
+
+ return CallQueryInterfaceOnProxy(self, aIID, (nsProxyEventObject**)aInstancePtr);
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp
new file mode 100644
index 00000000..d529fc05
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp
@@ -0,0 +1,555 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prprf.h"
+#include "prmem.h"
+
+#include "nscore.h"
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsHashtable.h"
+
+#include "nsIInterfaceInfoManager.h"
+#include "xptcall.h"
+
+#include "nsAutoLock.h"
+
+static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxyEventKey : public nsHashKey
+{
+public:
+ nsProxyEventKey(void* rootObjectKey, void* destQueueKey, PRInt32 proxyType)
+ : mRootObjectKey(rootObjectKey), mDestQueueKey(destQueueKey), mProxyType(proxyType) {
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mRootObjectKey) ^
+ NS_PTR_TO_INT32(mDestQueueKey) ^ mProxyType;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ const nsProxyEventKey* other = (const nsProxyEventKey*)aKey;
+ return mRootObjectKey == other->mRootObjectKey
+ && mDestQueueKey == other->mDestQueueKey
+ && mProxyType == other->mProxyType;
+ }
+
+ nsHashKey *Clone() const {
+ return new nsProxyEventKey(mRootObjectKey, mDestQueueKey, mProxyType);
+ }
+
+protected:
+ void* mRootObjectKey;
+ void* mDestQueueKey;
+ PRInt32 mProxyType;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG_xpcom_proxy
+static PRMonitor* mon = nsnull;
+static PRUint32 totalProxyObjects = 0;
+static PRUint32 outstandingProxyObjects = 0;
+
+void
+nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey)
+{
+
+ if (mon == nsnull)
+ {
+ mon = PR_NewMonitor();
+ }
+
+ PR_EnterMonitor(mon);
+
+ if (message)
+ {
+ printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+ printf("%s\n", message);
+
+ if(strcmp(message, "Create") == 0)
+ {
+ totalProxyObjects++;
+ outstandingProxyObjects++;
+ }
+ else if(strcmp(message, "Delete") == 0)
+ {
+ outstandingProxyObjects--;
+ }
+ }
+ printf("nsProxyEventObject @ %x with mRefCnt = %d\n", this, mRefCnt);
+
+ PRBool isRoot = mRoot == nsnull;
+ printf("%s wrapper around @ %x\n", isRoot ? "ROOT":"non-root\n", GetRealObject());
+
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(mProxyObject->mRealObject);
+ nsCOMPtr<nsISupports> rootQueue = do_QueryInterface(mProxyObject->mDestQueue);
+ nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType);
+ printf("Hashkey: %d\n", key.HashCode());
+
+ char* name;
+ GetClass()->GetInterfaceInfo()->GetName(&name);
+ printf("interface name is %s\n", name);
+ if(name)
+ nsMemory::Free(name);
+ char * iid = GetClass()->GetProxiedIID().ToString();
+ printf("IID number is %s\n", iid);
+ delete iid;
+ printf("nsProxyEventClass @ %x\n", mClass);
+
+ if(mNext)
+ {
+ if(isRoot)
+ {
+ printf("Additional wrappers for this object...\n");
+ }
+ mNext->DebugDump(nsnull, 0);
+ }
+
+ printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects);
+
+ if (message)
+ printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+
+ PR_ExitMonitor(mon);
+}
+#endif
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// nsProxyEventObject
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////
+nsProxyEventObject*
+nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports *aObj,
+ REFNSIID aIID)
+{
+ nsresult rv;
+
+ if (!aObj)
+ return nsnull;
+
+ nsISupports* rawObject = aObj;
+
+ //
+ // make sure that the object pass in is not a proxy...
+ // if the object *is* a proxy, then be nice and build the proxy
+ // for the real object...
+ //
+ nsCOMPtr<nsProxyEventObject> identificationObject;
+
+ rv = rawObject->QueryInterface(kProxyObject_Identity_Class_IID,
+ getter_AddRefs(identificationObject));
+ if (NS_SUCCEEDED(rv)) {
+ //
+ // ATTENTION!!!!
+ //
+ // If you are hitting any of the assertions in this block of code,
+ // please contact dougt@netscape.com.
+ //
+
+ // if you hit this assertion, you might want to check out how
+ // you are using proxies. You shouldn't need to be creating
+ // a proxy from a proxy. -- dougt@netscape.com
+ NS_ASSERTION(0, "Someone is building a proxy from a proxy");
+
+ NS_ASSERTION(identificationObject, "where did my identification object go!");
+ if (!identificationObject) {
+ return nsnull;
+ }
+
+ // someone is asking us to create a proxy for a proxy. Lets get
+ // the real object and build aproxy for that!
+ rawObject = identificationObject->GetRealObject();
+
+ NS_ASSERTION(rawObject, "where did my real object go!");
+ if (!rawObject) {
+ return nsnull;
+ }
+ }
+
+ //
+ // Get the root nsISupports of the |real| object.
+ //
+ nsCOMPtr<nsISupports> rootObject;
+
+ rootObject = do_QueryInterface(rawObject, &rv);
+ if (NS_FAILED(rv) || !rootObject) {
+ NS_ASSERTION(NS_FAILED(rv), "where did my root object go!");
+ return nsnull;
+ }
+
+ // Get the root nsISupports of the event queue... This is used later,
+ // as part of the hashtable key...
+ nsCOMPtr<nsISupports> destQRoot = do_QueryInterface(destQueue, &rv);
+ if (NS_FAILED(rv) || !destQRoot) {
+ return nsnull;
+ }
+
+ //
+ // Enter the proxy object creation lock.
+ //
+ // This lock protects thev linked list which chains proxies together
+ // (ie. mRoot and mNext) and ensures that there is no hashtable contention
+ // between the time that a proxy is looked up (and not found) in the
+ // hashtable and then added...
+ //
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (!manager) {
+ return nsnull;
+ }
+
+ nsAutoMonitor mon(manager->GetMonitor());
+
+ // Get the hash table containing root proxy objects...
+ nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
+ if (!realToProxyMap) {
+ return nsnull;
+ }
+
+ // Now, lookup the root nsISupports of the raw object in the hashtable
+ // The key consists of 3 pieces of information:
+ // - root nsISupports of the raw object
+ // - event queue of the current thread
+ // - type of proxy being constructed...
+ //
+ nsProxyEventKey rootkey(rootObject.get(), destQRoot.get(), proxyType);
+
+ nsCOMPtr<nsProxyEventObject> rootProxy;
+ nsCOMPtr<nsProxyEventObject> proxy;
+ nsProxyEventObject* peo;
+
+ // find in our hash table
+ rootProxy = (nsProxyEventObject*) realToProxyMap->Get(&rootkey);
+
+ if(rootProxy) {
+ //
+ // At least one proxy has already been created for this raw object...
+ //
+ // Look for the specific interface proxy in the list off of
+ // the root proxy...
+ //
+ peo = rootProxy->LockedFind(aIID);
+
+ if(peo) {
+ // An existing proxy is available... So use it.
+ NS_ADDREF(peo);
+ return peo;
+ }
+ }
+ else {
+ // build the root proxy
+ nsCOMPtr<nsProxyEventClass> rootClazz;
+
+ rootClazz = dont_AddRef(nsProxyEventClass::GetNewOrUsedClass(
+ NS_GET_IID(nsISupports)));
+ if (!rootClazz) {
+ return nsnull;
+ }
+
+ peo = new nsProxyEventObject(destQueue,
+ proxyType,
+ rootObject,
+ rootClazz,
+ nsnull);
+ if(!peo) {
+ // Ouch... Out of memory!
+ return nsnull;
+ }
+
+ // Add this root proxy into the hash table...
+ realToProxyMap->Put(&rootkey, peo);
+
+ if(aIID.Equals(NS_GET_IID(nsISupports))) {
+ //
+ // Since the requested proxy is for the nsISupports interface of
+ // the raw object, use the new root proxy as the specific proxy
+ // too...
+ //
+ NS_ADDREF(peo);
+ return peo;
+ }
+
+ // This assignment is an owning reference to the new ProxyEventObject.
+ // So, it will automatically get deleted if any subsequent early
+ // returns are taken...
+ rootProxy = do_QueryInterface(peo);
+ }
+
+ //
+ // at this point we have a proxy for the root nsISupports (ie. rootProxy)
+ // but we need to build the specific proxy for this interface...
+ //
+ NS_ASSERTION(rootProxy, "What happened to the root proxy!");
+
+ // Get a class for this IID.
+ nsCOMPtr<nsProxyEventClass> proxyClazz;
+
+ proxyClazz = dont_AddRef(nsProxyEventClass::GetNewOrUsedClass(aIID));
+ if(!proxyClazz) {
+ return nsnull;
+ }
+
+ // Get the raw interface for this IID
+ nsCOMPtr<nsISupports> rawInterface;
+
+ rv = rawObject->QueryInterface(aIID, getter_AddRefs(rawInterface));
+ if (NS_FAILED(rv) || !rawInterface) {
+ NS_ASSERTION(NS_FAILED(rv), "where did my rawInterface object go!");
+ return nsnull;
+ }
+
+ peo = new nsProxyEventObject(destQueue,
+ proxyType,
+ rawInterface,
+ proxyClazz,
+ rootProxy);
+ if (!peo) {
+ // Ouch... Out of memory!
+ return nsnull;
+ }
+
+ //
+ // Add the new specific proxy to the head of the list of proxies hanging
+ // off of the rootProxy...
+ //
+ peo->mNext = rootProxy->mNext;
+ rootProxy->mNext = peo;
+
+ NS_ADDREF(peo);
+ return peo;
+
+}
+
+nsProxyEventObject* nsProxyEventObject::LockedFind(REFNSIID aIID)
+{
+ if(aIID.Equals(mClass->GetProxiedIID())) {
+ return this;
+ }
+
+ if(aIID.Equals(NS_GET_IID(nsISupports))) {
+ return this;
+ }
+
+ nsProxyEventObject* cur = (mRoot ? mRoot : mNext);
+ while(cur) {
+ if(aIID.Equals(cur->GetClass()->GetProxiedIID())) {
+ return cur;
+ }
+ cur = cur->mNext;
+ }
+
+ return nsnull;
+}
+
+nsProxyEventObject::nsProxyEventObject()
+: mNext(nsnull)
+{
+ NS_WARNING("This constructor should never be called");
+}
+
+nsProxyEventObject::nsProxyEventObject(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports* aObj,
+ nsProxyEventClass* aClass,
+ nsProxyEventObject* root)
+ : mClass(aClass),
+ mRoot(root),
+ mNext(nsnull)
+{
+ NS_IF_ADDREF(mRoot);
+
+ mProxyObject = new nsProxyObject(destQueue, proxyType, aObj);
+
+#ifdef DEBUG_xpcom_proxy
+ DebugDump("Create", 0);
+#endif
+}
+
+nsProxyEventObject::~nsProxyEventObject()
+{
+#ifdef DEBUG_xpcom_proxy
+ DebugDump("Delete", 0);
+#endif
+ if (mRoot) {
+ //
+ // This proxy is not the root interface so it must be removed
+ // from the chain of proxies...
+ //
+ nsProxyEventObject* cur = mRoot;
+ while(cur) {
+ if(cur->mNext == this) {
+ cur->mNext = mNext;
+ mNext = nsnull;
+ break;
+ }
+ cur = cur->mNext;
+ }
+ NS_ASSERTION(cur, "failed to find wrapper in its own chain");
+ }
+ else {
+ //
+ // This proxy is for the root interface. Each proxy in the chain
+ // has a strong reference to the root... So, when its refcount goes
+ // to zero, it safe to remove it because no proxies are in its chain.
+ //
+ if (! nsProxyObjectManager::IsManagerShutdown()) {
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
+
+ NS_ASSERTION(!mNext, "There are still proxies in the chain!");
+
+ if (realToProxyMap != nsnull) {
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(mProxyObject->mRealObject);
+ nsCOMPtr<nsISupports> rootQueue = do_QueryInterface(mProxyObject->mDestQueue);
+ nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType);
+#ifdef DEBUG_dougt
+ void* value =
+#endif
+ realToProxyMap->Remove(&key);
+#ifdef DEBUG_dougt
+ NS_ASSERTION(value, "failed to remove from realToProxyMap");
+#endif
+ }
+ }
+ }
+
+ // I am worried about ordering.
+ // do not remove assignments.
+ mProxyObject = nsnull;
+ mClass = nsnull;
+ NS_IF_RELEASE(mRoot);
+}
+
+//
+// nsISupports implementation...
+//
+
+NS_IMPL_THREADSAFE_ADDREF(nsProxyEventObject)
+
+NS_IMETHODIMP_(nsrefcnt)
+nsProxyEventObject::Release(void)
+{
+ //
+ // Be pessimistic about whether the manager or even the monitor exist...
+ // This is to protect against shutdown issues where a proxy object could
+ // be destroyed after (or while) the Proxy Manager is being destroyed...
+ //
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsAutoMonitor mon(manager ? manager->GetMonitor() : nsnull);
+
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ // Decrement atomically - in case the Proxy Object Manager has already
+ // been deleted and the monitor is unavailable...
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsProxyEventObject");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+ //
+ // Remove the proxy from the hashtable (if necessary) or its
+ // proxy chain. This must be done inside of the proxy lock to
+ // prevent GetNewOrUsedProxy(...) from ressurecting it...
+ //
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return count;
+}
+
+NS_IMETHODIMP
+nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if( aIID.Equals(GetIID()) )
+ {
+ *aInstancePtr = NS_STATIC_CAST(nsISupports*, this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
+}
+
+//
+// nsXPTCStubBase implementation...
+//
+
+NS_IMETHODIMP
+nsProxyEventObject::GetInterfaceInfo(nsIInterfaceInfo** info)
+{
+ NS_ENSURE_ARG_POINTER(info);
+
+ *info = mClass->GetInterfaceInfo();
+
+ NS_ASSERTION(*info, "proxy class without interface");
+ if (!*info) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ NS_ADDREF(*info);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProxyEventObject::CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant * params)
+{
+ nsresult rv;
+
+ if (mProxyObject) {
+ rv = mProxyObject->Post(methodIndex,
+ (nsXPTMethodInfo*)info,
+ params,
+ mClass->GetInterfaceInfo());
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h
new file mode 100644
index 00000000..ee34927e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __nsProxyEventPrivate_h_
+#define __nsProxyEventPrivate_h_
+
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIFactory.h"
+#include "nsHashtable.h"
+
+#include "plevent.h"
+#include "xptcall.h" // defines nsXPTCVariant
+#include "nsIEventQueue.h"
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+
+class nsProxyEventObject;
+class nsProxyEventClass;
+
+#define NS_PROXYEVENT_CLASS_IID \
+{ 0xeea90d42, \
+ 0xb059, \
+ 0x11d2, \
+ {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\
+}
+
+#define NS_PROXYEVENT_IDENTITY_CLASS_IID \
+{ 0xeea90d45, 0xb059, 0x11d2, \
+ { 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } }
+
+
+#define NS_PROXYEVENT_OBJECT_IID \
+{ 0xec373590, 0x9164, 0x11d3, \
+{0x8c, 0x73, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
+
+
+class nsProxyEventClass : public nsISupports
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_CLASS_IID)
+ static nsProxyEventClass* GetNewOrUsedClass(REFNSIID aIID);
+
+ NS_IMETHOD DelegatedQueryInterface( nsProxyEventObject* self,
+ REFNSIID aIID,
+ void** aInstancePtr);
+
+
+ nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
+ const nsIID& GetProxiedIID() const {return mIID; }
+protected:
+ nsProxyEventClass();
+ nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo);
+
+private:
+ ~nsProxyEventClass();
+
+ nsIID mIID;
+ nsCOMPtr<nsIInterfaceInfo> mInfo;
+ uint32* mDescriptors;
+
+ nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self,
+ REFNSIID aIID,
+ nsProxyEventObject** aInstancePtr);
+};
+
+
+
+class nsProxyEventObject : public nsXPTCStubBase
+{
+public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_OBJECT_IID)
+
+ static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports *aObj,
+ REFNSIID aIID);
+
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params);
+
+
+ nsProxyEventClass* GetClass() const { return mClass; }
+ nsIEventQueue* GetQueue() const { return (mProxyObject ? mProxyObject->GetQueue() : nsnull);}
+ nsISupports* GetRealObject() const { return (mProxyObject ? mProxyObject->GetRealObject(): nsnull);}
+ PRInt32 GetProxyType() const { return (mProxyObject ? mProxyObject->GetProxyType() : nsnull);}
+
+ nsProxyEventObject();
+ nsProxyEventObject(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports* aObj,
+ nsProxyEventClass* aClass,
+ nsProxyEventObject* root);
+
+ nsProxyEventObject* LockedFind(REFNSIID aIID);
+
+#ifdef DEBUG_xpcom_proxy
+ void DebugDump(const char * message, PRUint32 hashKey);
+#endif
+
+private:
+ ~nsProxyEventObject();
+
+protected:
+ void LockedRemoveProxy();
+
+protected:
+ nsCOMPtr<nsProxyEventClass> mClass;
+ nsRefPtr<nsProxyObject> mProxyObject;
+
+ // Owning reference...
+ nsProxyEventObject *mRoot;
+
+ // Weak reference...
+ nsProxyEventObject *mNext;
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsProxyObjectManager
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxyObjectManager: public nsIProxyObjectManager
+{
+public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROXYOBJECTMANAGER
+
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ nsProxyObjectManager();
+
+ static nsProxyObjectManager *GetInstance();
+ static PRBool IsManagerShutdown();
+
+ static void Shutdown();
+
+ nsHashtable* GetRealObjectToProxyObjectMap() { return &mProxyObjectMap;}
+ nsHashtable* GetIIDToProxyClassMap() { return &mProxyClassMap; }
+
+ PRMonitor* GetMonitor() const { return mProxyCreationMonitor; }
+
+private:
+ ~nsProxyObjectManager();
+
+ static nsProxyObjectManager* mInstance;
+ nsHashtable mProxyObjectMap;
+ nsHashtable mProxyClassMap;
+ PRMonitor *mProxyCreationMonitor;
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp
new file mode 100644
index 00000000..0602bcd7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com> (Original Author)
+ * Judson Valeski <valeski@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Scott Collins <scc@netscape.com>
+ * Heikki Toivonen <heiki@citec.fi>
+ * Patrick Beard <beard@netscape.com>
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Warren Harris <warren@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ * Chris Waterson <waterson@netscape.com>
+ * Dan Mosedale <dmose@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsIProxyCreateInstance.h"
+
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+/***************************************************************************/
+/* nsProxyCreateInstance */
+/* This private class will allow us to create Instances on another thread */
+/***************************************************************************/
+class nsProxyCreateInstance : public nsIProxyCreateInstance
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result);
+ NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result);
+
+ nsProxyCreateInstance() {}
+
+private:
+ ~nsProxyCreateInstance() {}
+};
+
+NS_IMPL_ISUPPORTS1(nsProxyCreateInstance, nsIProxyCreateInstance)
+
+NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result)
+{
+ return nsComponentManager::CreateInstance( cid,
+ aOuter,
+ iid,
+ result);
+}
+
+
+NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result)
+{
+ return nsComponentManager::CreateInstance( aContractID,
+ aOuter,
+ iid,
+ result);
+}
+
+/////////////////////////////////////////////////////////////////////////
+// nsProxyObjectManager
+/////////////////////////////////////////////////////////////////////////
+
+nsProxyObjectManager* nsProxyObjectManager::mInstance = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyObjectManager, nsIProxyObjectManager)
+
+nsProxyObjectManager::nsProxyObjectManager()
+ : mProxyObjectMap(256, PR_TRUE),
+ mProxyClassMap(256, PR_TRUE)
+{
+ mProxyCreationMonitor = PR_NewMonitor();
+}
+
+static PRBool PurgeProxyClasses(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsProxyEventClass* ptr = NS_REINTERPRET_CAST(nsProxyEventClass*, aData);
+ NS_RELEASE(ptr);
+ return PR_TRUE;
+}
+
+nsProxyObjectManager::~nsProxyObjectManager()
+{
+ mProxyClassMap.Reset((nsHashtableEnumFunc)PurgeProxyClasses, nsnull);
+
+ if (mProxyCreationMonitor) {
+ PR_DestroyMonitor(mProxyCreationMonitor);
+ }
+
+ nsProxyObjectManager::mInstance = nsnull;
+}
+
+PRBool
+nsProxyObjectManager::IsManagerShutdown()
+{
+ if (mInstance)
+ return PR_FALSE;
+ return PR_TRUE;
+}
+
+nsProxyObjectManager *
+nsProxyObjectManager::GetInstance()
+{
+ if (! mInstance)
+ {
+ mInstance = new nsProxyObjectManager();
+ }
+ return mInstance;
+}
+
+
+void
+nsProxyObjectManager::Shutdown()
+{
+ mInstance = nsnull;
+}
+
+
+// Helpers
+NS_IMETHODIMP
+nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ nsProxyObjectManager *proxyObjectManager = GetInstance();
+
+ if (proxyObjectManager == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return proxyObjectManager->QueryInterface(aIID, aInstancePtr);
+}
+
+
+NS_IMETHODIMP
+nsProxyObjectManager::GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ if (!aObj) return NS_ERROR_NULL_POINTER;
+ if (!aProxyObject) return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> postQ;
+
+
+ *aProxyObject = nsnull;
+
+ // check to see if the destination Q is a special case.
+
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = eventQService->ResolveEventQueue(destQueue, getter_AddRefs(postQ));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // check to see if the eventQ is on our thread. If so, just return the real object.
+
+ if (postQ && !(proxyType & PROXY_ASYNC) && !(proxyType & PROXY_ALWAYS))
+ {
+ PRBool aResult;
+ postQ->IsOnCurrentThread(&aResult);
+
+ if (aResult)
+ {
+ return aObj->QueryInterface(aIID, aProxyObject);
+ }
+ }
+
+ // check to see if proxy is there or not.
+ *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, aObj, aIID);
+
+ if (*aProxyObject == nsnull)
+ return NS_ERROR_NO_INTERFACE; //fix error code?
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsProxyObjectManager::GetProxy( nsIEventQueue *destQueue,
+ const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ if (!aProxyObject) return NS_ERROR_NULL_POINTER;
+ *aProxyObject = nsnull;
+
+ // 1. Create a proxy for creating an instance on another thread.
+
+ nsIProxyCreateInstance* ciProxy = nsnull;
+
+ nsProxyCreateInstance* ciObject = new nsProxyCreateInstance();
+
+ if (ciObject == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_ADDREF(ciObject);
+
+ nsresult rv = GetProxyForObject(destQueue,
+ NS_GET_IID(nsIProxyCreateInstance),
+ ciObject,
+ PROXY_SYNC,
+ (void**)&ciProxy);
+
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(ciObject);
+ return rv;
+ }
+
+ // 2. now create a new instance of the request object via our proxy.
+
+ nsISupports* aObj;
+
+ rv = ciProxy->CreateInstanceByIID(aClass,
+ aDelegate,
+ aIID,
+ (void**)&aObj);
+
+
+ // 3. Delete the create instance proxy and its real object.
+
+ NS_RELEASE(ciProxy);
+ NS_RELEASE(ciObject);
+
+ // 4. Check to see if creating the requested instance failed.
+ if ( NS_FAILED(rv))
+ {
+ return rv;
+ }
+
+ // 5. Now create a proxy object for the requested object.
+
+ rv = GetProxyForObject(destQueue, aIID, aObj, proxyType, aProxyObject);
+
+ // 6. release ownership of aObj so that aProxyObject owns it.
+
+ NS_RELEASE(aObj);
+
+ // 7. return the error returned from GetProxyForObject. Either way, we our out of here.
+
+ return rv;
+}
+
+/**
+ * Helper function for code that already has a link-time dependency on
+ * libxpcom and needs to get proxies in a bunch of different places.
+ * This way, the caller isn't forced to get the proxy object manager
+ * themselves every single time, thus making the calling code more
+ * readable.
+ */
+NS_COM nsresult
+NS_GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ static NS_DEFINE_CID(proxyObjMgrCID, NS_PROXYEVENT_MANAGER_CID);
+
+ nsresult rv; // temp for return value
+
+ // get the proxy object manager
+ //
+ nsCOMPtr<nsIProxyObjectManager> proxyObjMgr =
+ do_GetService(proxyObjMgrCID, &rv);
+
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+
+ // and try to get the proxy object
+ //
+ return proxyObjMgr->GetProxyForObject(destQueue, aIID, aObj,
+ proxyType, aProxyObject);
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp
new file mode 100644
index 00000000..3ceeb667
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp
@@ -0,0 +1,55 @@
+#include "nsProxyRelease.h"
+
+PR_STATIC_CALLBACK(void*)
+HandleProxyReleaseEvent(PLEvent *self)
+{
+ nsISupports* owner = (nsISupports*) self->owner;
+ NS_RELEASE(owner);
+ return nsnull;
+}
+
+PR_STATIC_CALLBACK(void)
+DestroyProxyReleaseEvent(PLEvent *self)
+{
+ delete self;
+}
+
+NS_COM nsresult
+NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy)
+{
+ nsresult rv;
+
+ if (!target) {
+ NS_RELEASE(doomed);
+ return NS_OK;
+ }
+
+ if (!alwaysProxy) {
+ PRBool onCurrentThread = PR_FALSE;
+ rv = target->IsOnCurrentThread(&onCurrentThread);
+ if (NS_SUCCEEDED(rv) && onCurrentThread) {
+ NS_RELEASE(doomed);
+ return NS_OK;
+ }
+ }
+
+ PLEvent *ev = new PLEvent;
+ if (!ev) {
+ // we do not release doomed here since it may cause a delete on the
+ // wrong thread. better to leak than crash.
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PL_InitEvent(ev, doomed,
+ HandleProxyReleaseEvent,
+ DestroyProxyReleaseEvent);
+
+ rv = target->PostEvent(ev);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("failed to post proxy release event");
+ PL_DestroyEvent(ev);
+ // again, it is better to leak the doomed object than risk crashing as
+ // a result of deleting it on the wrong thread.
+ }
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore
new file mode 100644
index 00000000..b7457ff6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+proxytests
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in
new file mode 100644
index 00000000..e5e908f1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = proxytest
+REQUIRES = $(NULL)
+
+CPPSRCS = proxytests.cpp
+XPIDLSRCS = nsITestProxy.idl
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl b/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl
new file mode 100644
index 00000000..98cb3f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl
@@ -0,0 +1,9 @@
+#include "nsISupports.idl"
+
+[uuid(1979e980-1cfd-11d3-915e-0000863011c4)]
+interface nsITestProxy : nsISupports
+{
+ long Test(in long p1, in long p2);
+ void Test2();
+ void Test3(in nsISupports p1, out nsISupports p2);
+};
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp b/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp
new file mode 100644
index 00000000..20693463
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp
@@ -0,0 +1,553 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+#include "nsXPCOM.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+#include "nscore.h"
+#include "nspr.h"
+#include "prmon.h"
+
+#include "nsITestProxy.h"
+
+#include "nsIProxyObjectManager.h"
+#include "nsIEventQueueService.h"
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+/***************************************************************************/
+/* nsTestXPCFoo */
+/***************************************************************************/
+class nsTestXPCFoo : public nsITestProxy
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD Test2();
+ NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
+
+ nsTestXPCFoo();
+};
+
+nsTestXPCFoo::nsTestXPCFoo()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy)
+
+NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ printf("Thread (%d) Test Called successfully! Party on...\n", p1);
+ *retval = p1+p2;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo::Test2()
+{
+ printf("The quick brown netscape jumped over the old lazy ie..\n");
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2)
+{
+ if (p1 != nsnull)
+ {
+ nsITestProxy *test;
+
+ p1->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
+
+ test->Test2();
+ PRInt32 a;
+ test->Test( 1, 2, &a);
+ printf("\n1+2=%d\n",a);
+ }
+
+
+ *p2 = new nsTestXPCFoo();
+ return NS_OK;
+}
+
+/***************************************************************************/
+/* nsTestXPCFoo2 */
+/***************************************************************************/
+class nsTestXPCFoo2 : public nsITestProxy
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD Test2();
+ NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
+
+ nsTestXPCFoo2();
+};
+
+nsTestXPCFoo2::nsTestXPCFoo2()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy)
+
+NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+printf("calling back to caller!\n\n");
+
+ nsIProxyObjectManager* manager;
+ nsITestProxy * proxyObject;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ manager->GetProxyForObject((nsIEventQueue*)p1, NS_GET_IID(nsITestProxy), this, PROXY_SYNC, (void**)&proxyObject);
+ proxyObject->Test3(nsnull, nsnull);
+
+ printf("Deleting Proxy Object\n");
+ NS_RELEASE(proxyObject);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo2::Test2()
+{
+ printf("nsTestXPCFoo2::Test2() called\n");
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2)
+{
+ printf("Got called");
+ return NS_OK;
+}
+
+
+
+typedef struct _ArgsStruct
+{
+ nsIEventQueue* queue;
+ PRInt32 threadNumber;
+}ArgsStruct;
+
+
+
+// This will create two objects both descendants of a single IID.
+void TestCase_TwoClassesOneInterface(void *arg)
+{
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsITestProxy *proxyObject2;
+
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+ nsTestXPCFoo2* foo2 = new nsTestXPCFoo2();
+
+ PR_ASSERT(foo);
+ PR_ASSERT(foo2);
+
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo2, PROXY_SYNC, (void**)&proxyObject2);
+
+
+
+ if (proxyObject && proxyObject2)
+ {
+ // release ownership of the real object.
+
+ PRInt32 a;
+ nsresult rv;
+ PRInt32 threadNumber = argsStruct->threadNumber;
+
+ printf("Deleting real Object (%d)\n", threadNumber);
+ NS_RELEASE(foo);
+
+ printf("Deleting real Object 2 (%d)\n", threadNumber);
+ NS_RELEASE(foo2);
+
+
+ printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
+ rv = proxyObject->Test(threadNumber, 0, &a);
+ printf("Thread (%d) error: %d.\n", threadNumber, rv);
+
+
+ printf("Thread (%d) Prior to calling proxyObject->Test2.\n", threadNumber);
+ rv = proxyObject->Test2();
+ printf("Thread (%d) error: %d.\n", threadNumber, rv);
+
+ printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber);
+ rv = proxyObject2->Test2();
+ printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
+
+ printf("Deleting Proxy Object (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject);
+
+ printf("Deleting Proxy Object 2 (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject2);
+ }
+
+ PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
+}
+
+
+
+void TestCase_NestedLoop(void *arg)
+{
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo2* foo = new nsTestXPCFoo2();
+
+ PR_ASSERT(foo);
+
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ if (proxyObject)
+ {
+ // release ownership of the real object.
+
+ nsresult rv;
+ PRInt32 threadNumber = argsStruct->threadNumber;
+
+ printf("Deleting real Object (%d)\n", threadNumber);
+ NS_RELEASE(foo);
+
+ PRInt32 retval;
+
+ printf("Getting EventQueue...\n");
+
+ nsIEventQueue* eventQ;
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ if (NS_FAILED(rv))
+ rv = eventQService->CreateThreadEventQueue();
+ if (NS_FAILED(rv))
+ return;
+ else
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+
+ printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
+ rv = proxyObject->Test(NS_PTR_TO_INT32(eventQ), 0, &retval);
+ printf("Thread (%d) proxyObject error: %d.\n", threadNumber, rv);
+
+ printf("Deleting Proxy Object (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject);
+ }
+
+ PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
+ }
+}
+
+
+
+void TestCase_2(void *arg)
+{
+
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+
+ manager->GetProxy(argsStruct->queue,
+ NS_GET_IID(nsITestProxy), // should be CID!
+ nsnull,
+ NS_GET_IID(nsITestProxy),
+ PROXY_SYNC,
+ (void**)&proxyObject);
+
+ if (proxyObject != nsnull)
+ {
+ NS_RELEASE(proxyObject);
+ }
+}
+
+
+
+void TestCase_nsISupports(void *arg)
+{
+
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+
+ PR_ASSERT(foo);
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ if (proxyObject != nsnull)
+ {
+ nsISupports *bISupports = nsnull, *cISupports = nsnull;
+
+ proxyObject->Test3(foo, &bISupports);
+ proxyObject->Test3(bISupports, &cISupports);
+
+ nsITestProxy *test;
+ bISupports->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
+
+ test->Test2();
+
+ NS_RELEASE(foo);
+ NS_RELEASE(proxyObject);
+ }
+}
+
+
+
+
+
+/***************************************************************************/
+/* ProxyTest */
+/***************************************************************************/
+
+static void PR_CALLBACK ProxyTest( void *arg )
+{
+ //TestCase_TwoClassesOneInterface(arg);
+ // TestCase_2(arg);
+ //TestCase_nsISupports(arg);
+ TestCase_NestedLoop(arg);
+
+ NS_RELEASE( ((ArgsStruct*) arg)->queue);
+ free((void*) arg);
+}
+
+nsIEventQueue *gEventQueue = nsnull;
+
+static void PR_CALLBACK EventLoop( void *arg )
+{
+ nsresult rv;
+ printf("Creating EventQueue...\n");
+
+ nsIEventQueue* eventQ;
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ if (NS_FAILED(rv))
+ rv = eventQService->CreateThreadEventQueue();
+ if (NS_FAILED(rv))
+ return;
+ else
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ }
+ if (NS_FAILED(rv)) return;
+
+ rv = eventQ->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&gEventQueue);
+ if (NS_FAILED(rv)) return;
+
+
+ printf("Verifing calling Proxy on eventQ thread.\n");
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+
+ PR_ASSERT(foo);
+
+ manager->GetProxyForObject(gEventQueue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ PRInt32 a;
+ proxyObject->Test(1, 2, &a);
+ proxyObject->Test2();
+
+
+ NS_RELEASE(proxyObject);
+ delete foo;
+
+ printf("End of Verification calling Proxy on eventQ thread.\n");
+
+
+ printf("Looping for events.\n");
+
+ PLEvent* event = nsnull;
+
+ while ( PR_SUCCESS == PR_Sleep( PR_MillisecondsToInterval(1)) )
+ {
+ rv = gEventQueue->GetEvent(&event);
+ if (NS_FAILED(rv))
+ return;
+ gEventQueue->HandleEvent(event);
+ }
+
+ gEventQueue->ProcessPendingEvents();
+
+ printf("Closing down Event Queue.\n");
+ delete gEventQueue;
+ gEventQueue = nsnull;
+
+ printf("End looping for events.\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ int numberOfThreads = 1;
+
+ if (argc > 1)
+ numberOfThreads = atoi(argv[1]);
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ static PRThread** threads = (PRThread**) calloc(sizeof(PRThread*), numberOfThreads);
+ static PRThread* aEventThread;
+
+ aEventThread = PR_CreateThread(PR_USER_THREAD,
+ EventLoop,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+
+
+ PR_Sleep(PR_MillisecondsToInterval(1000));
+
+ NS_ASSERTION(gEventQueue, "no main event queue"); // BAD BAD BAD. EVENT THREAD DID NOT CREATE QUEUE. This may be a timing issue, set the
+ // sleep about longer, and try again.
+
+ printf("Spawn Threads:\n");
+ for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++)
+ {
+
+ ArgsStruct *args = (ArgsStruct *) malloc (sizeof(ArgsStruct));
+
+ args->queue = gEventQueue;
+ NS_ADDREF(args->queue);
+ args->threadNumber = spawn;
+
+ threads[spawn] = PR_CreateThread(PR_USER_THREAD,
+ ProxyTest,
+ args,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+
+ printf("\tThread (%d) spawned\n", spawn);
+
+ PR_Sleep( PR_MillisecondsToInterval(250) );
+ }
+
+ printf("All Threads Spawned.\n\n");
+
+
+
+ printf("Wait for threads.\n");
+ for (PRInt32 i = 0; i < numberOfThreads; i++)
+ {
+ PRStatus rv;
+ printf("Thread (%d) Join...\n", i);
+ rv = PR_JoinThread(threads[i]);
+ printf("Thread (%d) Joined. (error: %d).\n", i, rv);
+ }
+
+ PR_Interrupt(aEventThread);
+ PR_JoinThread(aEventThread);
+
+
+ printf("Calling Cleanup.\n");
+ PR_Cleanup();
+
+ printf("Return zero.\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/Makefile.in
new file mode 100644
index 00000000..171900b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = xptinfo xptcall
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore
new file mode 100644
index 00000000..a1af50c2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore
@@ -0,0 +1,4 @@
+Makefile
+mk.bat
+set_env.bat
+none.pdb
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in
new file mode 100644
index 00000000..e3173730
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/README b/src/libs/xpcom18a4/xpcom/reflect/xptcall/README
new file mode 100644
index 00000000..0c401fe8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/README
@@ -0,0 +1,6 @@
+see:
+
+http://www.mozilla.org/scriptable/xptcall-faq.html
+and
+http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html b/src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html
new file mode 100644
index 00000000..b8b204a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html
@@ -0,0 +1,212 @@
+<html>
+<head>
+<title>xptcall Porting Guide</title>
+</head>
+<body bgcolor = "white">
+<h2><center>xptcall Porting Guide</center></h2>
+
+<h3>Overview</h3>
+
+<blockquote>
+
+<a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> is a
+library that supports both invoking methods on arbitrary xpcom objects and
+implementing classes whose objects can impersonate any xpcom interface. It does
+this using platform specific assembly language code. This code needs to be
+ported to all platforms that want to support xptcall (and thus mozilla).
+
+</blockquote>
+
+<h3>The tree</h3>
+
+<blockquote>
+<pre>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a>
+ +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers
+ +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source
+ | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md">md</a> // platform specific parts
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/mac">mac</a> // mac ppc
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> // all unix
+ | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a> // win32
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">test</a> // simple tests to get started
+ \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api
+</pre>
+
+Porters are free to create subdirectories under the base <code>md</code>
+directory for their given platforms and to integrate into the build system as
+appropriate for their platform.
+
+</blockquote>
+
+<h3>Theory of operation</h3>
+
+<blockquote>
+
+There are really two pieces of functionality: <i>invoke</i> and <i>stubs</i>...
+
+<p>
+
+The <b><i>invoke</i></b> functionality requires the implementation of the
+following on each platform (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h#131">xptcall/public/xptcall.h</a>):
+
+<pre>
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+</pre>
+
+Calling code is expected to supply an array of <code>nsXPTCVariant</code>
+structs. These are discriminated unions describing the type and value of each
+parameter of the target function. The platform specific code then builds a call
+frame and invokes the method indicated by the index <code>methodIndex</code> on
+the xpcom interface <code>that</code>.
+
+<p>
+
+Here are examples of this implementation for
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp">Win32</a>
+and
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
+
+Both of these implementations use the basic strategy of: figure out how much
+stack space is needed for the params, make the space in a new frame, copy the
+params to that space, invoke the method, cleanup and return. C++ is used where
+appropriate, Assembly language is used where necessary. Inline assembly language is used here,
+but it is equally valid to use separate assembly language source files. Porters
+can decide how best to do this for their platforms.
+
+<p>
+
+The <b><i>stubs</i></b> functionality is more complex. The goal here is a class
+whose vtbl can look like the vtbl of any arbitrary xpcom interface. Objects of
+this class can then be built to impersonate any xpcom object. The base interface
+for this is (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h#109">xptcall/public/xptcall.h</a>):
+
+<pre>
+class nsXPTCStubBase : public nsISupports
+{
+public:
+ // Include generated vtbl stub declarations.
+ // These are virtual and *also* implemented by this class..
+#include "xptcstubsdecl.inc"
+
+ // The following methods must be provided by inheritor of this class.
+
+ // return a refcounted pointer to the InterfaceInfo for this object
+ // NOTE: on some platforms this MUST not fail or we crash!
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0;
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params) = 0;
+};
+</pre>
+
+Code that wishes to make use of this <i>stubs</i> functionality (such as
+<a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a class
+which inherits from <code>nsXPTCStubBase</code> and implements the
+<code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the
+platform specific code know how to get interface information and how to dispatch methods
+once their parameters have been pulled out of the platform specific calling
+frame.
+
+<p>
+
+Porters of this functionality implement the platform specific code for the
+<i>stub</i> methods that fill the vtbl for this class. The idea here is that the
+class has a vtbl full of a large number of generic stubs. All instances of this
+class share that vtbl and the same stubs. The stubs forward calls to a platform
+specific method that uses the interface information supplied by
+the overridden <code>GetInterfaceInfo</code> to extract the parameters and build
+an array of platform independent <code>nsXPTCMiniVariant</code> structs which
+are in turn passed on to the overridden <code>CallMethod</code>. The
+platform dependent code is responsible for doing any cleanup and returning.
+
+<p>
+
+The stub methods are declared in <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdecl.inc">xptcall/public/xptcstubsdecl.inc</a>.
+These are '#included' into the declaration of <code>nsXPTCStubBase</code>. A
+similar include file (<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdef.inc">xptcall/public/xptcstubsdef.inc</a>)
+is expanded using platform specific macros to define the stub functions. These
+'.inc' files are checked into cvs. However, they can be regenerated as necessary
+(i.e. to change the number of stubs or to change their specific declaration)
+using the Perl script <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/genstubs.pl">xptcall/public/genstubs.pl</a>.
+
+<p>
+
+Here are examples of this implementation for <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp">Win32</a>
+and <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
+Both of these examples use inline assembly language. That is just how I
+decided to do it. You can do it as you choose.
+
+<p>
+
+The Win32 version is somewhat tighter because the __declspec(naked) feature
+allows for very small stubs. However, the __stdcall requires the callee to clean
+up the stack, so it is imperative that the interface information scheme allow
+the code to determine the correct stack pointer fixup for return without fail,
+else the process will crash.
+
+<p>
+
+I opted to use inline assembler for the gcc Linux x86 port. I ended up with
+larger stubs than I would have preferred rather than battle the compiler over
+what would happen to the stack before my asm code began running.
+
+<p>
+
+I believe that the non-assembly parts of these files can be copied and reused
+with minimal (but not zero) platform specific tweaks. Feel free to copy and
+paste as necessary. Please remember that safety and reliability are more
+important than speed optimizations. This code is primarily used to connect XPCOM
+components with JavaScript; function call overhead is a <b>tiny</b> part of the
+time involved.
+
+<p>
+
+I put together
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">xptcall/src/md/test
+</a> as a place to evolve the basic functionality as a port is coming together.
+Not all of the functionality is exercised, but it is a place to get started.
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">xptcall/tests
+</a> has an api level test for <code>XPTC_InvokeByIndex</code>, but no tests for
+the <i>stubs</i> functionality. Such a test ought to be written, but this has not
+yet been done.
+
+<p>
+
+A full 'test' at this point requires building the client and running the
+XPConnect test called <i>TestXPC</i> in
+<a
+href="http://lxr.mozilla.org/mozilla/source/js/src/xpconnect/tests">mozilla/js/src/xpconnect/tests
+</a>.
+
+<p>
+
+Getting these ports done is very important. Please let <a
+href="mailto:jband@netscape.com">me</a> know if you are interested in doing one.
+I'll answer any questions as I get them.
+
+<p>
+
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">
+Porting Status
+</a>
+
+</blockquote>
+
+<hr>
+<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<b>Last modified:</b> 31 May 1999
+
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in
new file mode 100644
index 00000000..ac8432af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+EXPORTS = \
+ xptcall.h \
+ xptcstubsdecl.inc \
+ xptcstubsdef.inc \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl
new file mode 100755
index 00000000..b8962930
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl
@@ -0,0 +1,78 @@
+#!/usr/local/bin/perl
+
+# This is used to generate stub entry points. We generate a file to
+# be included in the declaraion and a file to be used for expanding macros
+# to represent the implementation of the stubs.
+
+#
+# if "$entry_count" is ever changed and the .inc files regenerated then
+# the following issues need to be addressed:
+#
+# 1) Alpha NT has a .def file that lists exports by symbol. It will need
+# updating.
+# 2) The current Linux ARM code has a limitation of only having 256-3 stubs
+#
+# more dependencies???
+#
+
+# 3 entries are already 'used' by the 3 methods of nsISupports.
+# 3+247+5=255 This should get us in under the Linux ARM limitation
+$entry_count = 247;
+$sentinel_count = 5;
+
+$decl_name = "xptcstubsdecl.inc";
+$def_name = "xptcstubsdef.inc";
+
+##
+## Write the declarations include file
+##
+
+die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name");
+
+print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
+print OUTFILE "/* includes ",$entry_count," stub entries, and ",
+ $sentinel_count," sentinel entries */\n\n";
+print OUTFILE "/*\n";
+print OUTFILE "* declarations of normal stubs...\n";
+print OUTFILE "* 0 is QueryInterface\n";
+print OUTFILE "* 1 is AddRef\n";
+print OUTFILE "* 2 is Release\n";
+print OUTFILE "*/\n";
+print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__))\n";
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n";
+}
+print OUTFILE "#else\n";
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "NS_IMETHOD Stub",$i+3,"(PRUint64,\n";
+ print OUTFILE " PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);\n";
+
+}
+print OUTFILE "#endif\n";
+
+print OUTFILE "\n/* declarations of sentinel stubs */\n";
+
+for($i = 0; $i < $sentinel_count; $i++) {
+ print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n";
+}
+close(OUTFILE);
+
+
+##
+## Write the definitions include file. This assumes a macro will be used to
+## expand the entries written...
+##
+
+die "Can't open $def_name" if !open(OUTFILE, ">$def_name");
+
+print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
+print OUTFILE "/* includes ",$entry_count," stub entries, and ",
+ $sentinel_count," sentinel entries */\n\n";
+
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "STUB_ENTRY(",$i+3,")\n";
+}
+
+for($i = 0; $i < $sentinel_count; $i++) {
+ print OUTFILE "SENTINEL_ENTRY(",$i,")\n";
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h
new file mode 100644
index 00000000..153a047e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h
@@ -0,0 +1,271 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Public declarations for xptcall. */
+
+#ifndef xptcall_h___
+#define xptcall_h___
+
+#include "prtypes.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "xpt_struct.h"
+#include "xptinfo.h"
+#include "nsIInterfaceInfo.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPTC_InvokeByIndex VBoxNsxpXPTC_InvokeByIndex
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/***************************************************************************/
+/*
+ * The linkage of XPTC API functions differs depending on whether the file is
+ * used within the XPTC library or not. Any source file within the XPTC
+ * library should define EXPORT_XPTC_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPTC_API
+#define XPTC_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPTC_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#if defined(_WIN32)
+# define XPTC_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTC_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2_VACPP)
+# define XPTC_EXPORT extern
+#else
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define XPTC_EXPORT __attribute__((visibility("default")))
+# else
+# define XPTC_EXPORT
+# endif
+#endif
+#else
+#if defined(_WIN32)
+# define XPTC_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTC_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTC_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTC_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTC_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTC_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2_VACPP)
+# define XPTC_PUBLIC_API(t) extern t
+# define XPTC_PUBLIC_DATA(t) extern t
+# define XPTC_EXPORT extern
+#else
+# define XPTC_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPTC_PUBLIC_DATA(t) t
+# define XPTC_EXPORT
+#endif
+#endif
+#define XPTC_FRIEND_API(t) XPTC_PUBLIC_API(t)
+#define XPTC_FRIEND_DATA(t) XPTC_PUBLIC_DATA(t)
+/***************************************************************************/
+
+struct nsXPTCMiniVariant
+{
+// No ctors or dtors so that we can use arrays of these on the stack
+// with no penalty.
+ union
+ {
+ PRInt8 i8;
+ PRInt16 i16;
+ PRInt32 i32;
+ PRInt64 i64;
+ PRUint8 u8;
+ PRUint16 u16;
+ PRUint32 u32;
+ PRUint64 u64;
+ float f;
+ double d;
+ PRBool b;
+ char c;
+ PRUnichar wc;
+ void* p;
+ } val;
+};
+
+struct nsXPTCVariant : public nsXPTCMiniVariant
+{
+// No ctors or dtors so that we can use arrays of these on the stack
+// with no penalty.
+
+ // inherits 'val' here
+ void* ptr;
+ nsXPTType type;
+ PRUint8 flags;
+
+ enum
+ {
+ // these are bitflags!
+ PTR_IS_DATA = 0x1, // ptr points to 'real' data in val
+ VAL_IS_ALLOCD = 0x2, // val.p holds alloc'd ptr that must be freed
+ VAL_IS_IFACE = 0x4, // val.p holds interface ptr that must be released
+ VAL_IS_ARRAY = 0x8, // val.p holds a pointer to an array needing cleanup
+ VAL_IS_DOMSTR = 0x10, // val.p holds a pointer to domstring needing cleanup
+ VAL_IS_UTF8STR = 0x20, // val.p holds a pointer to utf8string needing cleanup
+ VAL_IS_CSTR = 0x40 // val.p holds a pointer to cstring needing cleanup
+ };
+
+ /* VBox: Added to prevent -Wclass-memaccess warnings (nsXPTType has a constructor) in python/src/VariantUtils.cpp */
+ nsXPTCVariant() : ptr(NULL), flags(0)
+ {
+ val.p = NULL;
+ type.flags = 0; /* stupid nsXPTType constructor only do random bytes (documented) */
+ }
+
+ void ClearFlags() {flags = 0;}
+ void SetPtrIsData() {flags |= PTR_IS_DATA;}
+ void SetValIsAllocated() {flags |= VAL_IS_ALLOCD;}
+ void SetValIsInterface() {flags |= VAL_IS_IFACE;}
+ void SetValIsArray() {flags |= VAL_IS_ARRAY;}
+ void SetValIsDOMString() {flags |= VAL_IS_DOMSTR;}
+ void SetValIsUTF8String() {flags |= VAL_IS_UTF8STR;}
+ void SetValIsCString() {flags |= VAL_IS_CSTR;}
+
+ PRBool IsPtrData() const {return 0 != (flags & PTR_IS_DATA);}
+ PRBool IsValAllocated() const {return 0 != (flags & VAL_IS_ALLOCD);}
+ PRBool IsValInterface() const {return 0 != (flags & VAL_IS_IFACE);}
+ PRBool IsValArray() const {return 0 != (flags & VAL_IS_ARRAY);}
+ PRBool IsValDOMString() const {return 0 != (flags & VAL_IS_DOMSTR);}
+ PRBool IsValUTF8String() const {return 0 != (flags & VAL_IS_UTF8STR);}
+ PRBool IsValCString() const {return 0 != (flags & VAL_IS_CSTR);}
+#ifdef VBOX
+ PRBool MustFreeVal() const {return 0 != (flags & ( VAL_IS_ALLOCD
+ | VAL_IS_IFACE
+ | VAL_IS_DOMSTR
+ | VAL_IS_UTF8STR
+ | VAL_IS_CSTR)); }
+#endif
+
+ void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, PRUint8 f)
+ {
+ type = t;
+ flags = f;
+
+ if(f & PTR_IS_DATA)
+ {
+ ptr = mv.val.p;
+ val.p = nsnull;
+ }
+ else
+ {
+ ptr = nsnull;
+ switch(t.TagPart()) {
+ case nsXPTType::T_I8: val.i8 = mv.val.i8; break;
+ case nsXPTType::T_I16: val.i16 = mv.val.i16; break;
+ case nsXPTType::T_I32: val.i32 = mv.val.i32; break;
+ case nsXPTType::T_I64: val.i64 = mv.val.i64; break;
+ case nsXPTType::T_U8: val.u8 = mv.val.u8; break;
+ case nsXPTType::T_U16: val.u16 = mv.val.u16; break;
+ case nsXPTType::T_U32: val.u32 = mv.val.u32; break;
+ case nsXPTType::T_U64: val.u64 = mv.val.u64; break;
+ case nsXPTType::T_FLOAT: val.f = mv.val.f; break;
+ case nsXPTType::T_DOUBLE: val.d = mv.val.d; break;
+ case nsXPTType::T_BOOL: val.b = mv.val.b; break;
+ case nsXPTType::T_CHAR: val.c = mv.val.c; break;
+ case nsXPTType::T_WCHAR: val.wc = mv.val.wc; break;
+ case nsXPTType::T_VOID: /* fall through */
+ case nsXPTType::T_IID: /* fall through */
+ case nsXPTType::T_DOMSTRING: /* fall through */
+ case nsXPTType::T_CHAR_STR: /* fall through */
+ case nsXPTType::T_WCHAR_STR: /* fall through */
+ case nsXPTType::T_INTERFACE: /* fall through */
+ case nsXPTType::T_INTERFACE_IS: /* fall through */
+ case nsXPTType::T_ARRAY: /* fall through */
+ case nsXPTType::T_PSTRING_SIZE_IS: /* fall through */
+ case nsXPTType::T_PWSTRING_SIZE_IS: /* fall through */
+ case nsXPTType::T_UTF8STRING: /* fall through */
+ case nsXPTType::T_CSTRING: /* fall through */
+ default: val.p = mv.val.p; break;
+ }
+ }
+ }
+};
+
+/***************************************************************************/
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+
+class XPTC_EXPORT nsXPTCStubBase : public nsISupports
+{
+public:
+ // We are going to implement this to force the compiler to generate a
+ // vtbl for this class. Since this is overridden in the inheriting class
+ // we expect it to never be called.
+ // *This is needed by the Irix implementation.*
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
+ // Implement dummy constructor, destructor to workaround Solaris gcc 4.8.2
+ // linking issue (see @bugref{5838}).
+ nsXPTCStubBase() {}
+ ~nsXPTCStubBase() {}
+
+ // Include generated vtbl stub declarations.
+ // These are virtual and *also* implemented by this class..
+#include "xptcstubsdecl.inc"
+
+ // The following methods must be provided by inheritor of this class.
+
+ // return a refcounted pointer to the InterfaceInfo for this object
+ // NOTE: on some platforms this MUST not fail or we crash!
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0;
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params) = 0;
+};
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+PR_BEGIN_EXTERN_C
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+// Used to force linking of these obj for the static library into the dll
+extern void xptc_dummy();
+extern void xptc_dummy2();
+
+PR_END_EXTERN_C
+
+#endif /* xptcall_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc
new file mode 100644
index 00000000..99116d68
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc
@@ -0,0 +1,761 @@
+/* generated file - DO NOT EDIT */
+
+/* includes 247 stub entries, and 5 sentinel entries */
+
+/*
+* declarations of normal stubs...
+* 0 is QueryInterface
+* 1 is AddRef
+* 2 is Release
+*/
+#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__))
+NS_IMETHOD Stub3();
+NS_IMETHOD Stub4();
+NS_IMETHOD Stub5();
+NS_IMETHOD Stub6();
+NS_IMETHOD Stub7();
+NS_IMETHOD Stub8();
+NS_IMETHOD Stub9();
+NS_IMETHOD Stub10();
+NS_IMETHOD Stub11();
+NS_IMETHOD Stub12();
+NS_IMETHOD Stub13();
+NS_IMETHOD Stub14();
+NS_IMETHOD Stub15();
+NS_IMETHOD Stub16();
+NS_IMETHOD Stub17();
+NS_IMETHOD Stub18();
+NS_IMETHOD Stub19();
+NS_IMETHOD Stub20();
+NS_IMETHOD Stub21();
+NS_IMETHOD Stub22();
+NS_IMETHOD Stub23();
+NS_IMETHOD Stub24();
+NS_IMETHOD Stub25();
+NS_IMETHOD Stub26();
+NS_IMETHOD Stub27();
+NS_IMETHOD Stub28();
+NS_IMETHOD Stub29();
+NS_IMETHOD Stub30();
+NS_IMETHOD Stub31();
+NS_IMETHOD Stub32();
+NS_IMETHOD Stub33();
+NS_IMETHOD Stub34();
+NS_IMETHOD Stub35();
+NS_IMETHOD Stub36();
+NS_IMETHOD Stub37();
+NS_IMETHOD Stub38();
+NS_IMETHOD Stub39();
+NS_IMETHOD Stub40();
+NS_IMETHOD Stub41();
+NS_IMETHOD Stub42();
+NS_IMETHOD Stub43();
+NS_IMETHOD Stub44();
+NS_IMETHOD Stub45();
+NS_IMETHOD Stub46();
+NS_IMETHOD Stub47();
+NS_IMETHOD Stub48();
+NS_IMETHOD Stub49();
+NS_IMETHOD Stub50();
+NS_IMETHOD Stub51();
+NS_IMETHOD Stub52();
+NS_IMETHOD Stub53();
+NS_IMETHOD Stub54();
+NS_IMETHOD Stub55();
+NS_IMETHOD Stub56();
+NS_IMETHOD Stub57();
+NS_IMETHOD Stub58();
+NS_IMETHOD Stub59();
+NS_IMETHOD Stub60();
+NS_IMETHOD Stub61();
+NS_IMETHOD Stub62();
+NS_IMETHOD Stub63();
+NS_IMETHOD Stub64();
+NS_IMETHOD Stub65();
+NS_IMETHOD Stub66();
+NS_IMETHOD Stub67();
+NS_IMETHOD Stub68();
+NS_IMETHOD Stub69();
+NS_IMETHOD Stub70();
+NS_IMETHOD Stub71();
+NS_IMETHOD Stub72();
+NS_IMETHOD Stub73();
+NS_IMETHOD Stub74();
+NS_IMETHOD Stub75();
+NS_IMETHOD Stub76();
+NS_IMETHOD Stub77();
+NS_IMETHOD Stub78();
+NS_IMETHOD Stub79();
+NS_IMETHOD Stub80();
+NS_IMETHOD Stub81();
+NS_IMETHOD Stub82();
+NS_IMETHOD Stub83();
+NS_IMETHOD Stub84();
+NS_IMETHOD Stub85();
+NS_IMETHOD Stub86();
+NS_IMETHOD Stub87();
+NS_IMETHOD Stub88();
+NS_IMETHOD Stub89();
+NS_IMETHOD Stub90();
+NS_IMETHOD Stub91();
+NS_IMETHOD Stub92();
+NS_IMETHOD Stub93();
+NS_IMETHOD Stub94();
+NS_IMETHOD Stub95();
+NS_IMETHOD Stub96();
+NS_IMETHOD Stub97();
+NS_IMETHOD Stub98();
+NS_IMETHOD Stub99();
+NS_IMETHOD Stub100();
+NS_IMETHOD Stub101();
+NS_IMETHOD Stub102();
+NS_IMETHOD Stub103();
+NS_IMETHOD Stub104();
+NS_IMETHOD Stub105();
+NS_IMETHOD Stub106();
+NS_IMETHOD Stub107();
+NS_IMETHOD Stub108();
+NS_IMETHOD Stub109();
+NS_IMETHOD Stub110();
+NS_IMETHOD Stub111();
+NS_IMETHOD Stub112();
+NS_IMETHOD Stub113();
+NS_IMETHOD Stub114();
+NS_IMETHOD Stub115();
+NS_IMETHOD Stub116();
+NS_IMETHOD Stub117();
+NS_IMETHOD Stub118();
+NS_IMETHOD Stub119();
+NS_IMETHOD Stub120();
+NS_IMETHOD Stub121();
+NS_IMETHOD Stub122();
+NS_IMETHOD Stub123();
+NS_IMETHOD Stub124();
+NS_IMETHOD Stub125();
+NS_IMETHOD Stub126();
+NS_IMETHOD Stub127();
+NS_IMETHOD Stub128();
+NS_IMETHOD Stub129();
+NS_IMETHOD Stub130();
+NS_IMETHOD Stub131();
+NS_IMETHOD Stub132();
+NS_IMETHOD Stub133();
+NS_IMETHOD Stub134();
+NS_IMETHOD Stub135();
+NS_IMETHOD Stub136();
+NS_IMETHOD Stub137();
+NS_IMETHOD Stub138();
+NS_IMETHOD Stub139();
+NS_IMETHOD Stub140();
+NS_IMETHOD Stub141();
+NS_IMETHOD Stub142();
+NS_IMETHOD Stub143();
+NS_IMETHOD Stub144();
+NS_IMETHOD Stub145();
+NS_IMETHOD Stub146();
+NS_IMETHOD Stub147();
+NS_IMETHOD Stub148();
+NS_IMETHOD Stub149();
+NS_IMETHOD Stub150();
+NS_IMETHOD Stub151();
+NS_IMETHOD Stub152();
+NS_IMETHOD Stub153();
+NS_IMETHOD Stub154();
+NS_IMETHOD Stub155();
+NS_IMETHOD Stub156();
+NS_IMETHOD Stub157();
+NS_IMETHOD Stub158();
+NS_IMETHOD Stub159();
+NS_IMETHOD Stub160();
+NS_IMETHOD Stub161();
+NS_IMETHOD Stub162();
+NS_IMETHOD Stub163();
+NS_IMETHOD Stub164();
+NS_IMETHOD Stub165();
+NS_IMETHOD Stub166();
+NS_IMETHOD Stub167();
+NS_IMETHOD Stub168();
+NS_IMETHOD Stub169();
+NS_IMETHOD Stub170();
+NS_IMETHOD Stub171();
+NS_IMETHOD Stub172();
+NS_IMETHOD Stub173();
+NS_IMETHOD Stub174();
+NS_IMETHOD Stub175();
+NS_IMETHOD Stub176();
+NS_IMETHOD Stub177();
+NS_IMETHOD Stub178();
+NS_IMETHOD Stub179();
+NS_IMETHOD Stub180();
+NS_IMETHOD Stub181();
+NS_IMETHOD Stub182();
+NS_IMETHOD Stub183();
+NS_IMETHOD Stub184();
+NS_IMETHOD Stub185();
+NS_IMETHOD Stub186();
+NS_IMETHOD Stub187();
+NS_IMETHOD Stub188();
+NS_IMETHOD Stub189();
+NS_IMETHOD Stub190();
+NS_IMETHOD Stub191();
+NS_IMETHOD Stub192();
+NS_IMETHOD Stub193();
+NS_IMETHOD Stub194();
+NS_IMETHOD Stub195();
+NS_IMETHOD Stub196();
+NS_IMETHOD Stub197();
+NS_IMETHOD Stub198();
+NS_IMETHOD Stub199();
+NS_IMETHOD Stub200();
+NS_IMETHOD Stub201();
+NS_IMETHOD Stub202();
+NS_IMETHOD Stub203();
+NS_IMETHOD Stub204();
+NS_IMETHOD Stub205();
+NS_IMETHOD Stub206();
+NS_IMETHOD Stub207();
+NS_IMETHOD Stub208();
+NS_IMETHOD Stub209();
+NS_IMETHOD Stub210();
+NS_IMETHOD Stub211();
+NS_IMETHOD Stub212();
+NS_IMETHOD Stub213();
+NS_IMETHOD Stub214();
+NS_IMETHOD Stub215();
+NS_IMETHOD Stub216();
+NS_IMETHOD Stub217();
+NS_IMETHOD Stub218();
+NS_IMETHOD Stub219();
+NS_IMETHOD Stub220();
+NS_IMETHOD Stub221();
+NS_IMETHOD Stub222();
+NS_IMETHOD Stub223();
+NS_IMETHOD Stub224();
+NS_IMETHOD Stub225();
+NS_IMETHOD Stub226();
+NS_IMETHOD Stub227();
+NS_IMETHOD Stub228();
+NS_IMETHOD Stub229();
+NS_IMETHOD Stub230();
+NS_IMETHOD Stub231();
+NS_IMETHOD Stub232();
+NS_IMETHOD Stub233();
+NS_IMETHOD Stub234();
+NS_IMETHOD Stub235();
+NS_IMETHOD Stub236();
+NS_IMETHOD Stub237();
+NS_IMETHOD Stub238();
+NS_IMETHOD Stub239();
+NS_IMETHOD Stub240();
+NS_IMETHOD Stub241();
+NS_IMETHOD Stub242();
+NS_IMETHOD Stub243();
+NS_IMETHOD Stub244();
+NS_IMETHOD Stub245();
+NS_IMETHOD Stub246();
+NS_IMETHOD Stub247();
+NS_IMETHOD Stub248();
+NS_IMETHOD Stub249();
+#else
+NS_IMETHOD Stub3(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub4(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub5(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub6(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub7(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub8(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub9(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub10(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub11(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub12(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub13(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub14(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub15(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub16(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub17(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub18(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub19(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub20(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub21(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub22(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub23(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub24(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub25(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub26(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub27(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub28(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub29(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub30(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub31(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub32(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub33(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub34(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub35(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub36(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub37(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub38(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub39(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub40(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub41(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub42(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub43(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub44(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub45(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub46(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub47(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub48(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub49(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub50(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub51(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub52(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub53(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub54(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub55(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub56(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub57(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub58(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub59(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub60(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub61(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub62(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub63(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub64(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub65(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub66(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub67(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub68(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub69(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub70(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub71(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub72(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub73(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub74(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub75(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub76(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub77(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub78(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub79(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub80(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub81(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub82(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub83(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub84(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub85(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub86(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub87(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub88(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub89(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub90(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub91(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub92(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub93(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub94(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub95(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub96(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub97(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub98(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub99(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub100(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub101(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub102(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub103(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub104(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub105(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub106(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub107(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub108(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub109(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub110(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub111(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub112(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub113(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub114(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub115(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub116(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub117(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub118(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub119(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub120(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub121(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub122(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub123(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub124(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub125(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub126(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub127(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub128(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub129(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub130(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub131(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub132(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub133(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub134(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub135(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub136(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub137(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub138(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub139(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub140(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub141(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub142(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub143(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub144(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub145(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub146(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub147(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub148(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub149(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub150(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub151(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub152(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub153(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub154(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub155(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub156(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub157(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub158(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub159(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub160(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub161(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub162(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub163(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub164(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub165(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub166(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub167(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub168(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub169(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub170(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub171(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub172(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub173(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub174(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub175(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub176(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub177(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub178(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub179(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub180(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub181(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub182(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub183(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub184(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub185(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub186(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub187(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub188(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub189(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub190(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub191(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub192(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub193(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub194(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub195(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub196(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub197(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub198(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub199(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub200(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub201(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub202(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub203(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub204(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub205(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub206(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub207(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub208(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub209(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub210(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub211(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub212(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub213(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub214(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub215(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub216(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub217(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub218(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub219(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub220(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub221(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub222(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub223(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub224(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub225(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub226(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub227(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub228(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub229(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub230(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub231(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub232(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub233(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub234(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub235(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub236(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub237(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub238(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub239(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub240(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub241(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub242(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub243(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub244(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub245(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub246(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub247(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub248(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub249(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+#endif
+
+/* declarations of sentinel stubs */
+NS_IMETHOD Sentinel0();
+NS_IMETHOD Sentinel1();
+NS_IMETHOD Sentinel2();
+NS_IMETHOD Sentinel3();
+NS_IMETHOD Sentinel4();
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc
new file mode 100644
index 00000000..780e2f52
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc
@@ -0,0 +1,256 @@
+/* generated file - DO NOT EDIT */
+
+/* includes 247 stub entries, and 5 sentinel entries */
+
+STUB_ENTRY(3)
+STUB_ENTRY(4)
+STUB_ENTRY(5)
+STUB_ENTRY(6)
+STUB_ENTRY(7)
+STUB_ENTRY(8)
+STUB_ENTRY(9)
+STUB_ENTRY(10)
+STUB_ENTRY(11)
+STUB_ENTRY(12)
+STUB_ENTRY(13)
+STUB_ENTRY(14)
+STUB_ENTRY(15)
+STUB_ENTRY(16)
+STUB_ENTRY(17)
+STUB_ENTRY(18)
+STUB_ENTRY(19)
+STUB_ENTRY(20)
+STUB_ENTRY(21)
+STUB_ENTRY(22)
+STUB_ENTRY(23)
+STUB_ENTRY(24)
+STUB_ENTRY(25)
+STUB_ENTRY(26)
+STUB_ENTRY(27)
+STUB_ENTRY(28)
+STUB_ENTRY(29)
+STUB_ENTRY(30)
+STUB_ENTRY(31)
+STUB_ENTRY(32)
+STUB_ENTRY(33)
+STUB_ENTRY(34)
+STUB_ENTRY(35)
+STUB_ENTRY(36)
+STUB_ENTRY(37)
+STUB_ENTRY(38)
+STUB_ENTRY(39)
+STUB_ENTRY(40)
+STUB_ENTRY(41)
+STUB_ENTRY(42)
+STUB_ENTRY(43)
+STUB_ENTRY(44)
+STUB_ENTRY(45)
+STUB_ENTRY(46)
+STUB_ENTRY(47)
+STUB_ENTRY(48)
+STUB_ENTRY(49)
+STUB_ENTRY(50)
+STUB_ENTRY(51)
+STUB_ENTRY(52)
+STUB_ENTRY(53)
+STUB_ENTRY(54)
+STUB_ENTRY(55)
+STUB_ENTRY(56)
+STUB_ENTRY(57)
+STUB_ENTRY(58)
+STUB_ENTRY(59)
+STUB_ENTRY(60)
+STUB_ENTRY(61)
+STUB_ENTRY(62)
+STUB_ENTRY(63)
+STUB_ENTRY(64)
+STUB_ENTRY(65)
+STUB_ENTRY(66)
+STUB_ENTRY(67)
+STUB_ENTRY(68)
+STUB_ENTRY(69)
+STUB_ENTRY(70)
+STUB_ENTRY(71)
+STUB_ENTRY(72)
+STUB_ENTRY(73)
+STUB_ENTRY(74)
+STUB_ENTRY(75)
+STUB_ENTRY(76)
+STUB_ENTRY(77)
+STUB_ENTRY(78)
+STUB_ENTRY(79)
+STUB_ENTRY(80)
+STUB_ENTRY(81)
+STUB_ENTRY(82)
+STUB_ENTRY(83)
+STUB_ENTRY(84)
+STUB_ENTRY(85)
+STUB_ENTRY(86)
+STUB_ENTRY(87)
+STUB_ENTRY(88)
+STUB_ENTRY(89)
+STUB_ENTRY(90)
+STUB_ENTRY(91)
+STUB_ENTRY(92)
+STUB_ENTRY(93)
+STUB_ENTRY(94)
+STUB_ENTRY(95)
+STUB_ENTRY(96)
+STUB_ENTRY(97)
+STUB_ENTRY(98)
+STUB_ENTRY(99)
+STUB_ENTRY(100)
+STUB_ENTRY(101)
+STUB_ENTRY(102)
+STUB_ENTRY(103)
+STUB_ENTRY(104)
+STUB_ENTRY(105)
+STUB_ENTRY(106)
+STUB_ENTRY(107)
+STUB_ENTRY(108)
+STUB_ENTRY(109)
+STUB_ENTRY(110)
+STUB_ENTRY(111)
+STUB_ENTRY(112)
+STUB_ENTRY(113)
+STUB_ENTRY(114)
+STUB_ENTRY(115)
+STUB_ENTRY(116)
+STUB_ENTRY(117)
+STUB_ENTRY(118)
+STUB_ENTRY(119)
+STUB_ENTRY(120)
+STUB_ENTRY(121)
+STUB_ENTRY(122)
+STUB_ENTRY(123)
+STUB_ENTRY(124)
+STUB_ENTRY(125)
+STUB_ENTRY(126)
+STUB_ENTRY(127)
+STUB_ENTRY(128)
+STUB_ENTRY(129)
+STUB_ENTRY(130)
+STUB_ENTRY(131)
+STUB_ENTRY(132)
+STUB_ENTRY(133)
+STUB_ENTRY(134)
+STUB_ENTRY(135)
+STUB_ENTRY(136)
+STUB_ENTRY(137)
+STUB_ENTRY(138)
+STUB_ENTRY(139)
+STUB_ENTRY(140)
+STUB_ENTRY(141)
+STUB_ENTRY(142)
+STUB_ENTRY(143)
+STUB_ENTRY(144)
+STUB_ENTRY(145)
+STUB_ENTRY(146)
+STUB_ENTRY(147)
+STUB_ENTRY(148)
+STUB_ENTRY(149)
+STUB_ENTRY(150)
+STUB_ENTRY(151)
+STUB_ENTRY(152)
+STUB_ENTRY(153)
+STUB_ENTRY(154)
+STUB_ENTRY(155)
+STUB_ENTRY(156)
+STUB_ENTRY(157)
+STUB_ENTRY(158)
+STUB_ENTRY(159)
+STUB_ENTRY(160)
+STUB_ENTRY(161)
+STUB_ENTRY(162)
+STUB_ENTRY(163)
+STUB_ENTRY(164)
+STUB_ENTRY(165)
+STUB_ENTRY(166)
+STUB_ENTRY(167)
+STUB_ENTRY(168)
+STUB_ENTRY(169)
+STUB_ENTRY(170)
+STUB_ENTRY(171)
+STUB_ENTRY(172)
+STUB_ENTRY(173)
+STUB_ENTRY(174)
+STUB_ENTRY(175)
+STUB_ENTRY(176)
+STUB_ENTRY(177)
+STUB_ENTRY(178)
+STUB_ENTRY(179)
+STUB_ENTRY(180)
+STUB_ENTRY(181)
+STUB_ENTRY(182)
+STUB_ENTRY(183)
+STUB_ENTRY(184)
+STUB_ENTRY(185)
+STUB_ENTRY(186)
+STUB_ENTRY(187)
+STUB_ENTRY(188)
+STUB_ENTRY(189)
+STUB_ENTRY(190)
+STUB_ENTRY(191)
+STUB_ENTRY(192)
+STUB_ENTRY(193)
+STUB_ENTRY(194)
+STUB_ENTRY(195)
+STUB_ENTRY(196)
+STUB_ENTRY(197)
+STUB_ENTRY(198)
+STUB_ENTRY(199)
+STUB_ENTRY(200)
+STUB_ENTRY(201)
+STUB_ENTRY(202)
+STUB_ENTRY(203)
+STUB_ENTRY(204)
+STUB_ENTRY(205)
+STUB_ENTRY(206)
+STUB_ENTRY(207)
+STUB_ENTRY(208)
+STUB_ENTRY(209)
+STUB_ENTRY(210)
+STUB_ENTRY(211)
+STUB_ENTRY(212)
+STUB_ENTRY(213)
+STUB_ENTRY(214)
+STUB_ENTRY(215)
+STUB_ENTRY(216)
+STUB_ENTRY(217)
+STUB_ENTRY(218)
+STUB_ENTRY(219)
+STUB_ENTRY(220)
+STUB_ENTRY(221)
+STUB_ENTRY(222)
+STUB_ENTRY(223)
+STUB_ENTRY(224)
+STUB_ENTRY(225)
+STUB_ENTRY(226)
+STUB_ENTRY(227)
+STUB_ENTRY(228)
+STUB_ENTRY(229)
+STUB_ENTRY(230)
+STUB_ENTRY(231)
+STUB_ENTRY(232)
+STUB_ENTRY(233)
+STUB_ENTRY(234)
+STUB_ENTRY(235)
+STUB_ENTRY(236)
+STUB_ENTRY(237)
+STUB_ENTRY(238)
+STUB_ENTRY(239)
+STUB_ENTRY(240)
+STUB_ENTRY(241)
+STUB_ENTRY(242)
+STUB_ENTRY(243)
+STUB_ENTRY(244)
+STUB_ENTRY(245)
+STUB_ENTRY(246)
+STUB_ENTRY(247)
+STUB_ENTRY(248)
+STUB_ENTRY(249)
+SENTINEL_ENTRY(0)
+SENTINEL_ENTRY(1)
+SENTINEL_ENTRY(2)
+SENTINEL_ENTRY(3)
+SENTINEL_ENTRY(4)
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in
new file mode 100644
index 00000000..987fc505
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in
@@ -0,0 +1,62 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xptcall
+
+
+DIRS = md
+
+CPPSRCS = xptcall.cpp
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in
new file mode 100644
index 00000000..dd70cabf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in
@@ -0,0 +1,56 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
+DIRS = os2
+else
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+DIRS = win32
+else
+DIRS = unix
+endif
+endif
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp
new file mode 100644
index 00000000..29343c08
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef XP_MAC
+#error "This code is for Macintosh only"
+#endif
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+ PRUint32 fpCount = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt32*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt32*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.d;
+ break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRInt32*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRUint32*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+#pragma export on
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
+
+#pragma export off
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s
new file mode 100644
index 00000000..47544dd3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s
@@ -0,0 +1,128 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is mozilla.org code.
+ #
+ # The Initial Developer of the Original Code is Netscape
+ # Communications Corporation. Portions created by Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+ csect CODE{PR}
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+ import .invoke_count_words
+ import .invoke_copy_to_stack
+ import .__ptr_glue
+
+._XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-144(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers,
+ # 8 to keep stack 16-byte aligned.
+
+# set up for and call 'invoke_count_words' to get new stack size
+#
+ mr r3,r5
+ mr r4,r6
+ bl .invoke_count_words
+ nop
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,176(sp) # paramCount
+ lwz r5,180(sp) # params
+# addi r6,sp,128 # fprData
+ mr r6,sp # fprData
+ slwi r3,r3,2 # number of bytes of stack required
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ sub sp,sp,r3 # bump the stack
+ clrrwi sp,sp,4 # keep the stack 16-byte aligned.
+ lwz r3,0(r31) # act like real alloca, so 0(sp) always points back to
+ stw r3,0(sp) # previous stack frame.
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31)
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,168(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,172(r31) # methodIndex
+ slwi r5,r5,2 # methodIndex * 4
+ addi r5,r5,8 # step over junk at start of vTable !
+ lwzx r12,r5,r4 # get function pointer
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl .__ptr_glue
+ nop
+
+
+ mr sp,r31
+ lwz r0,152(sp)
+ addi sp,sp,144
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+# traceback table.
+ traceback:
+ dc.l 0
+ dc.l 0x00002040
+ dc.l 0
+ dc.l (traceback - ._XPTC_InvokeByIndex) # size of the code.
+ dc.w 20 # short length of identifier.
+ dc.b '._XPTC_InvokeByIndex'
+
+ csect DATA
+ import TOC
+ export ._XPTC_InvokeByIndex
+
+ dc.l ._XPTC_InvokeByIndex
+ dc.l TOC
+ \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp
new file mode 100644
index 00000000..3fea7d51
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp
@@ -0,0 +1,265 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#pragma export on
+
+#include "xptcprivate.h"
+
+#if defined(XP_MAC)
+
+/*
+ For mac, the first 8 integral and the first 13 f.p. parameters arrive
+ in a separate chunk of data that has been loaded from the registers. The
+ args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args, PRUint32 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+ case nsXPTType::T_I64 :
+#ifdef HAVE_LONG_LONG
+ PRUint64 tempu64;
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT)
+ {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else
+ {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+#else
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRInt32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+#endif
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U64 :
+#ifdef HAVE_LONG_LONG
+ // PRUint64 tempu64; // declared above and still in scope
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT)
+ {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else
+ {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+#else
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRUint32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+#endif
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" void SharedStub();
+
+#define STUB_ENTRY(n) \
+asm nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ addi r12,r0,n; \
+ b SharedStub \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+
+#include "xptcstubsdef.inc"
+
+#pragma export off
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s
new file mode 100644
index 00000000..d2f7185b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s
@@ -0,0 +1,78 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is mozilla.org code.
+ #
+ # The Initial Developer of the Original Code is Netscape
+ # Communications Corporation. Portions created by Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+ csect CODE{PR}
+#
+# on entry SharedStub has the method selector in r12, the rest of the original
+# parameters are in r3 thru r10 and f1 thru f13
+#
+ import .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ stw r0,8(sp)
+
+ stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28)
+ # outgoing params to PrepareAndDispatch (20)
+
+ stw r4,44(sp)
+ stw r5,48(sp)
+ stw r6,52(sp)
+ stw r7,56(sp)
+ stw r8,60(sp)
+ stw r9,64(sp)
+ stw r10,68(sp)
+ stfd f1,72(sp)
+ stfd f2,80(sp)
+ stfd f3,88(sp)
+ stfd f4,96(sp)
+ stfd f5,104(sp)
+ stfd f6,112(sp)
+ stfd f7,120(sp)
+ stfd f8,128(sp)
+ stfd f9,136(sp)
+ stfd f10,144(sp)
+ stfd f11,152(sp)
+ stfd f12,156(sp)
+ stfd f13,164(sp)
+
+ addi r6,sp,44 # gprData
+ addi r7,sp,72 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector
+ addi r5,sp,232 # pointer to callers args area, beyond r3-r10 mapped range
+
+ bl .PrepareAndDispatch
+ nop
+
+ lwz r0,184(sp)
+ addi sp,sp,176
+ mtlr r0
+ blr
+
+ csect DATA
+ import TOC
+ export .SharedStub
+
+ dc.l .SharedStub
+ dc.l TOC
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in
new file mode 100644
index 00000000..cfd57c83
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in
@@ -0,0 +1,72 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xptcmd
+
+ifdef GNU_CXX
+CPPSRCS = \
+ ../unix/xptcinvoke_gcc_x86_unix.cpp \
+ ../unix/xptcstubs_gcc_x86_unix.cpp \
+ $(NULL)
+LOCAL_INCLUDES = -I$(srcdir)/../unix
+DEFINES += -DMOZ_NEED_LEADING_UNDERSCORE
+else
+CPPSRCS = xptcstubs_os2.cpp
+ASFILES = xptcinvoke_vacpp.asm xptcstubs_vacpp.asm
+endif
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/config.mk
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API
+
+INCLUDES += -I$(srcdir)/../..
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp
new file mode 100644
index 00000000..17fcadfe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Fairhurst <john_fairhurst@iname.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 03/22/2000 IBM Corp. Fixed multiple inheritance bug in XPTC_InvokeByIndex to adjust the
+ * "that" (this) pointer appropriately.
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+// This is 80% copied directly from other platforms; the assembler
+// stuff is all my fault, though. (jmf)
+
+#if !defined(__EMX__)
+#error "This code is for OS/2 EMX only"
+#endif
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32-bit DWORDs
+static PRUint32
+invoke_count_words( PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ result++;
+
+ else {
+
+ switch(s->type)
+ {
+ // 64-bit types
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+
+ // all others are dwords
+ default:
+ result++;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+
+static void
+invoke_copy_to_stack( PRUint32* d, uint32 paramCount, nsXPTCVariant* s)
+{
+ for( PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ *((void**)d) = s->ptr;
+
+ else {
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16*) d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64*) d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*)d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex( nsISupports *that, PRUint32 index,
+ PRUint32 paramcount, nsXPTCVariant* params)
+{
+ int ibytes;
+ void *pStack;
+ int result = NS_OK;
+
+ // Find size in bytes necessary for call
+ ibytes = 4 * invoke_count_words( paramcount, params);
+
+ __asm__ __volatile__(
+ "movl %1, %%eax\n" /* load |ibytes| into eax */
+ "subl %%eax, %%esp\n" /* make room on stack */
+ "movl %%esp, %0" /* store base in |pStack| */
+ : "=g" (pStack) /* %0 */
+ : "g" (ibytes) /* %1 */
+ : "ax", "memory", "sp"
+ );
+
+ // Fill in that gap in the stack with the params to the method
+ invoke_copy_to_stack( (PRUint32*) pStack, paramcount, params);
+
+ // push the hidden 'this' parameter, traverse the vtable,
+ // and then call the method.
+
+ __asm__ __volatile__(
+ "movl %2, %%eax\n" /* |that| ptr -> eax */
+ "movl (%%eax), %%edx\n" /* vptr -> edx */
+ "movl %3, %%ebx\n"
+ "shl $3, %%ebx\n" /* 8 bytes per method.. */
+ "addl $8, %%ebx\n" /* ..plus 8 to skip over 1st 8 bytes of vtbl */
+
+ "addl %%ebx, %%edx\n" /* find appropriate vtbl entry */
+ "movswl (%%edx),%%ecx\n" /* get possible |that| ptr adjustment value */
+ "addl %%ecx, %%eax\n" /* adjust the |that| ptr (needed for multiple inheritance) */
+ "pushl %%eax\n" /* enstack the possibly-adjusted |that| */
+
+ "addl $4, %%edx\n" /* ..add 4 more to get to the method's entry point */
+
+ "call (%%edx)\n" /* call method */
+ "movl %%eax, %0\n" /* save rc in |result| */
+ "movl %1, %%ebx\n" /* clear up stack */
+ "addl $4, %%ebx\n"
+ "addl %%ebx, %%esp"
+ : "=g" (result) /* %0 */
+ : "g" (ibytes), /* %1 */
+ "g" (that), /* %2 */
+ "g" (index) /* %3 */
+ : "ax", "bx", "dx", "memory", "sp"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp
new file mode 100644
index 00000000..6bbb93b0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+/* This file is basically a copy of xptcinvoke_gcc_x86_unix.cpp with some
+ * irrelevant parts stipped off and some OS/2 specific modifications added,
+ * so it needs to be kept in sync with the original. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static
+void ATTRIBUTE_USED __attribute__ ((regparm(3)))
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ default : *((void**)d) = s->val.p; break;
+ }
+ }
+}
+} // extern "C"
+
+/*
+ XPTC_PUBLIC_API(nsresult)
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+ NOTE NOTE NOTE:
+ As of 2002-04-29 this function references no global variables nor does
+ it call non-static functions so preserving and loading the PIC register
+ is unnecessary. Define MOZ_PRESERVE_PIC if this changes. See mozilla
+ bug 140412 for details. However, avoid this if you can. It's slower.
+*/
+
+#if defined(__declspec)
+#define SYMBOL_EXPORT(sym) \
+ ".stabs \"" sym ",0=" sym ",code\", 0x6c,0,0,-42\n\t"
+#else
+#define SYMBOL_EXPORT(sym)
+#endif
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+ ".globl " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex,@function\n"
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "XPTC_InvokeByIndex")
+ SYMBOL_UNDERSCORE "XPTC_InvokeByIndex:\n\t"
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "pushl %ebx\n\t"
+ "call 0f\n\t"
+ ".subsection 1\n"
+ "0:\n\t"
+ "movl (%esp), %ebx\n\t"
+ "ret\n\t"
+ ".previous\n\t"
+ "addl $_GLOBAL_OFFSET_TABLE_, %ebx\n\t"
+#endif
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+ "movl %esp, %ecx\n\t"
+ "subl %edx, %ecx\n\t"
+/* Since there may be 64-bit data, it occurs to me that aligning this
+ space might be a performance gain. However, I don't think the rest
+ of mozilla worries about such things. In any event, do it here.
+ "andl $0xfffffff8, %ecx\n\t"
+ */
+ "movl %ecx, %esp\n\t" /* make stack space */
+ "movl 0x14(%ebp), %edx\n\t"
+ "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "shll $3, %eax\n\t" /* *= 8 */
+ "addl $8, %eax\n\t" /* += 8 skip first entry */
+ "addl %eax, %edx\n\t"
+ "movswl (%edx), %eax\n\t" /* 'this' offset */
+ "addl %eax, %ecx\n\t"
+ "pushl %ecx\n\t"
+ "addl $4, %edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %ecx\n\t"
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "leal (%edx,%eax,4), %edx\n\t"
+#endif
+ "call *(%edx)\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "movl -4(%ebp), %ebx\n\t"
+#endif
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+ ".size " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+);
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm
new file mode 100644
index 00000000..4d013fdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm
@@ -0,0 +1,268 @@
+COMMENT | -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
+
+ ***** BEGIN LICENSE BLOCK *****
+ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+ The contents of this file are subject to the Mozilla Public License Version
+ 1.1 (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the
+ License.
+
+ The Original Code is mozilla.org Code.
+
+ The Initial Developer of the Original Code is
+ Netscape Communications Corporation.
+ Portions created by the Initial Developer are Copyright (C) 2001
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+ Henry Sobotka <sobotka@axess.com>
+
+ Alternatively, the contents of this file may be used under the terms of
+ either of the GNU General Public License Version 2 or later (the "GPL"),
+ or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ in which case the provisions of the GPL or the LGPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of either the GPL or the LGPL, and not to allow others to
+ use your version of this file under the terms of the MPL, indicate your
+ decision by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL or the LGPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the MPL, the GPL or the LGPL.
+
+ ***** END LICENSE BLOCK *****
+ 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.
+
+ Contributor: Henry Sobotka <sobotka@axess.com>
+
+ This Original Code has been modified by IBM Corporation.
+ Modifications made by IBM described herein are
+ Copyright (c) International Business Machines
+ Corporation, 2000
+
+ Modifications to Mozilla code or documentation
+ identified per MPL Section 3.3
+
+ Date Modified by Description of modification
+ 03/23/2000 IBM Corp. Various fixes for parameter passing and adjusting the 'this'
+ pointer for multiply inherited objects.
+
+ xptcall_vacpp.asm: ALP assembler procedures for VAC++ build of xptcall
+
+ We use essentially the same algorithm as the other platforms, except
+ Optlink as calling convention. This means loading the three leftmost
+ conforming (<= 4 bytes, enum or pointer) parameters into eax, edx and ecx,
+ and the four leftmost float types atop the FP stack. As "this" goes into
+ eax, we only have to load edx and ecx (if there are two parameters).
+ Nonconforming parameters go on the stack. As the right-size space has
+ to be allocated at the proper place (order of parameters) in the stack
+ for each conforming parameter, we simply copy them all. |
+
+
+ .486P
+ .MODEL FLAT, OPTLINK
+ .STACK
+
+ .CODE
+
+t_Int4Bytes equ 001004h
+t_Int8Bytes equ 001008h
+t_Float4Bytes equ 000104h
+t_Float8Bytes equ 000108h
+
+TypesArray dd t_Int4Bytes ; nsXPTType::T_I8
+ dd t_Int4Bytes ; nsXPTType::T_I16
+ dd t_Int4Bytes ; nsXPTType::T_I32
+ dd t_Int8Bytes ; nsXPTType::T_I64 (***)
+ dd t_Int4Bytes ; nsXPTType::T_U8
+ dd t_Int4Bytes ; nsXPTType::T_U16
+ dd t_Int4Bytes ; nsXPTType::T_U32
+ dd t_Int8Bytes ; nsXPTType::T_U64 (***)
+ dd t_Float4Bytes ; nsXPTType::T_FLOAT (***)
+ dd t_Float8Bytes ; nsXPTType::T_DOUBLE (***)
+ dd t_Int4Bytes ; nsXPTType::T_BOOL
+ dd t_Int4Bytes ; nsXPTType::T_CHAR
+ dd t_Int4Bytes ; nsXPTType::T_WCHAR
+ dd t_Int4Bytes ; TD_VOID
+ dd t_Int4Bytes ; TD_PNSIID
+ dd t_Int4Bytes ; TD_DOMSTRING
+ dd t_Int4Bytes ; TD_PSTRING
+ dd t_Int4Bytes ; TD_PWSTRING
+ dd t_Int4Bytes ; TD_INTERFACE_TYPE
+ dd t_Int4Bytes ; TD_INTERFACE_IS_TYPE
+ dd t_Int4Bytes ; TD_ARRAY
+ dd t_Int4Bytes ; TD_PSTRING_SIZE_IS
+ dd t_Int4Bytes ; TD_PWSTRING_SIZE_IS
+ dd t_Int4Bytes ; TD_UTF8STRING
+ dd t_Int4Bytes ; TD_CSTRING
+ dd t_Int4Bytes ; TD_ASTRING
+ ; All other values default to 4 byte int/ptr
+
+
+
+ ; Optlink puts 'that' in eax, 'index' in edx, 'paramcount' in ecx
+ ; 'params' is on the stack...
+XPTC_InvokeByIndex PROC OPTLINK EXPORT USES ebx edi esi, that, index, paramcount, params
+
+ LOCAL cparams:dword, fparams:dword, reg_edx:dword, reg_ecx:dword, count:dword
+
+ mov dword ptr [that], eax ; that
+ mov dword ptr [index], edx ; index
+ mov dword ptr [paramcount], ecx ; paramcount
+ mov dword ptr [count], ecx ; save a copy of count
+
+; #define FOURBYTES 4
+; #define EIGHTBYTES 8
+; #define FLOAT 0x00000100
+; #define INT 0x00001000
+; #define LENGTH 0x000000ff
+;
+;types[ ] = {
+; FOURBYES | INT, // int/uint/ptr/etc
+; EIGHTBYTES | INT, // long long
+; FOURBYES | FLOAT, // float
+; EIGHTBYTES | FLOAT // double
+;};
+; params+00h = val // double
+; params+08h = ptr
+; params+0ch = type
+; params+0dh = flags
+; PTR_IS_DATA = 0x01
+; ecx = params
+; edx = src
+; edi = dst
+; ebx = type (bh = int/float, bl = byte count)
+
+ xor eax, eax
+ mov dword ptr [cparams],eax ; cparams = 0;
+ mov dword ptr [fparams],eax ; fparams = 0;
+
+ shl ecx, 03h
+ sub esp, ecx ; dst/esp = add esp, paramCount * 8
+ mov edi, esp
+
+ push eax ; push 0 // "end" of floating point register stack...
+
+ mov ecx, dword ptr [params] ; // params is a "register" variable
+@While1:
+ mov eax, dword ptr [count] ; while( count-- )
+ or eax, eax ; // (test for zero)
+ je @EndWhile1
+ dec eax
+ mov dword ptr [count], eax
+ ; {
+
+ test byte ptr [ecx+0dh],01h ; if ( params->flags & PTR_IS_DATA ) {
+ je @IfElse1
+ lea edx, dword ptr [ecx+08h] ; src = &params->ptr;
+ mov ebx, 01004h ; type = INT | FOURBYTES;
+ jmp @EndIf1
+@IfElse1: ; } else {
+ mov edx, ecx ; src = &params->val
+ movzx eax, byte ptr [ecx+0ch] ; type = types[params->type];
+ cmp eax, 22 ; // range check params->type... (0 to 22)
+ jle @TypeOK
+ mov eax,2 ; // all others default to 4 byte int
+@TypeOK:
+ mov ebx, dword ptr [TypesArray+eax*4]
+@EndIf1: ; }
+
+ test bh, 001h ; if ( type & FLOAT ) {
+ je @EndIf2
+ cmp dword ptr [fparams], 4 ; if ( fparams < 4 ) {
+ jge @EndIf3
+ push edx ; push src;
+ push ebx ; push type
+ inc dword ptr [fparams] ; fparams++;
+;;; movzx eax, bl ; // dst += (type & LENGTH);
+;;; add edi, eax ;
+;;; xor ebx, ebx ; // type = 0; // "handled"
+@EndIf3: ; }
+@EndIf2: ; }
+
+ ; // copy bytes...
+@While2: or bl, bl ; while( type & LENGTH ) {
+ je @EndWhile2
+ test bh, 010h ; if( type & INT ) {
+ je @EndIf4
+ cmp dword ptr [cparams], 8 ; if( cparams < 8 ) {
+ jge @EndIf5
+ lea eax, dword ptr [reg_edx] ; (&reg_edx)[cparams] = *src;
+ sub eax, dword ptr [cparams]
+ mov esi, dword ptr [edx]
+ mov dword ptr [eax], esi
+ add dword ptr [cparams], 4 ; cparams += 4;
+;;; jmp @NoCopy ; // goto nocopy;
+@EndIf5: ; }
+@EndIf4: ; }
+ mov eax, dword ptr [edx] ; *dst = *src;
+ mov dword ptr [edi], eax
+@NoCopy: ;nocopy:
+ add edi, 4 ; dst++;
+ add edx, 4 ; src++;
+ sub bl, 4 ; type -= 4;
+ jmp @While2
+@EndWhile2: ; }
+ add ecx, 010h ; params++;
+ jmp @While1
+@EndWhile1: ; }
+
+ ; // Set up fpu and regs can make the call...
+@While3: pop ebx ; while ( pop type ) {
+ or ebx, ebx
+ je @EndWhile3
+ pop edx ; pop src
+ cmp bl, 08h ; if( type & EIGHTBYTES ) {
+ jne @IfElse6
+ fld qword ptr [edx] ; fld qword ptr [src]
+ jmp @EndIf6
+@IfElse6: ; } else {
+ fld dword ptr [edx] ; fld dword ptr [src]
+@EndIf6: ; }
+ jmp @While3
+@EndWhile3: ; }
+
+ ; make the call
+ mov eax, dword ptr [that] ; get 'that' ("this" ptr)
+ mov ebx, dword ptr [index] ; get index
+ shl ebx, 03h ; index *= 8 bytes per method
+ add ebx, 08h ; += 8 at head of vtable
+ add ebx, [eax] ; calculate address
+
+ mov ecx, dword ptr [ebx+04h]
+ add eax, ecx
+ sub esp, 04h ; make room for 'this' ptr on stack
+
+ mov edx, dword ptr [reg_edx]
+ mov ecx, dword ptr [reg_ecx]
+
+ call dword ptr [ebx] ; call method
+
+ mov ecx, dword ptr [paramcount]
+ shl ecx, 03h
+ add esp, ecx ; remove space on stack for params
+ add esp, 04h ; remove space on stack for 'this' ptr
+ ret
+
+ ENDP
+
+ END
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp
new file mode 100644
index 00000000..6cde9231
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods */
+
+// This is a 98% copy of other implementations; see comment at top of
+// xptcinvoke_emx.cpp for why this file exists.
+//
+
+#include "xptcprivate.h"
+
+#if !defined(__EMX__)
+#error "This code is for OS/2 EMX only"
+#endif
+
+static nsresult
+PrepareAndDispatch( nsXPTCStubBase *self, PRUint32 methodIndex,
+ PRUint32 *args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register void* method = PrepareAndDispatch; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx" /* PrepareAndDispatch */ \
+ : "=a" (result) /* %0 */ \
+ : "d" (method) /* %1 */ \
+ : "ax", "dx", "cx", "memory" ); \
+ return result; \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPCWrappedJS::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp
new file mode 100644
index 00000000..6304b67a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+/* This file is basically a copy of xptcinvoke_gcc_x86_unix.cpp with some
+ * irrelevant parts stipped off and some OS/2 specific modifications added,
+ * so it needs to be kept in sync with the original. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static nsresult ATTRIBUTE_USED
+__attribute__ ((regparm (3)))
+PrepareAndDispatch(uint32 methodIndex, nsXPTCStubBase* self, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+} // extern "C"
+
+#if defined(__declspec)
+#define SYMBOL_EXPORT(sym) \
+ ".stabs \"" sym ",0=" sym ",code\", 0x6c,0,0,-42\n\t"
+#else
+#define SYMBOL_EXPORT(sym)
+#endif
+
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev") \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev") \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev") \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+
+// static nsresult SharedStub(PRUint32 methodIndex) __attribute__((regparm(1)))
+asm(".text\n\t"
+ ".align 2\n\t"
+ ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
+ SYMBOL_UNDERSCORE "SharedStub:\n\t"
+ "leal 0x08(%esp), %ecx\n\t"
+ "movl 0x04(%esp), %edx\n\t"
+ "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
+ ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp
new file mode 100644
index 00000000..33e8574a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp
@@ -0,0 +1,195 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Fairhurst <john_fairhurst@iname.com>
+ * Henry Sobotka <sobotka@axess.com> added VAC++ support
+ * and fixed emx asm to work with gcc 2.95.2 (Jan. 2000)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods */
+
+#include "xptcprivate.h"
+
+#if !defined (__EMX__) && !defined(__IBMCPP__)
+#error "This code is only for OS/2"
+#endif
+
+// Procedure in xptcall_vacpp.asm
+#ifdef XP_OS2_VACPP
+extern nsresult SetEntryFromIndex(int stubidx);
+#endif
+
+#ifdef XP_OS2_VACPP
+nsresult
+PrepareAndDispatch( nsXPTCStubBase *self, PRUint32 methodIndex,
+ PRUint32 *args)
+#else
+static nsresult
+PrepareAndDispatch( nsXPTCStubBase *self, PRUint32 methodIndex,
+ PRUint32 *args)
+#endif
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+#ifdef XP_OS2_VACPP
+ /* If paramCount is > 0, write out the EDX pointer to the
+ space on the stack args[0]. args[-4] is the space on
+ the stack where it was pushed */
+ if (paramCount) {
+ args[0] = args[-4];
+
+ /* If this is the second parameter, or if the first parameter is an
+ 8 byte long long, write out the ECX pointer to the space on the
+ stack args[1]. args[-3] is the space on the stack where it was
+ pushed */
+ nsXPTType type = info->GetParam(0).GetType();
+ if( paramCount > 1 ||
+ type == nsXPTType::T_I64 || type == nsXPTType::T_U64 )
+ {
+ args[1] = args[-3];
+ }
+ }
+#endif
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#ifdef XP_OS2_VACPP
+
+#define STUB_ENTRY(n)
+
+#else
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult (*method) (nsXPTCStubBase *, PRUint32, PRUint32 *) = PrepareAndDispatch; \
+ int temp0, temp1; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx\n\t" /* PrepareAndDispatch */ \
+ "addl $12, %%esp" \
+ : "=a" (result), /* %0 */ \
+ "=&c" (temp0), /* %1 */ \
+ "=d" (temp1) /* %2 */ \
+ : "2" (method) /* %2 */ \
+ : "memory" ); \
+ return result; \
+}
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPCWrappedJS::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm
new file mode 100644
index 00000000..3464a1f9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm
@@ -0,0 +1,1563 @@
+COMMENT | -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
+
+ ***** BEGIN LICENSE BLOCK *****
+ Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+ The contents of this file are subject to the Mozilla Public License Version
+ 1.1 (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the
+ License.
+
+ The Original Code is mozilla.org Code.
+
+ The Initial Developer of the Original Code is
+ Netscape Communications Corporation.
+ Portions created by the Initial Developer are Copyright (C) 2001
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+ John Fairhurst <john_fairhurst@iname.com>
+ Henry Sobotka <sobotka@axess.com>
+
+ Alternatively, the contents of this file may be used under the terms of
+ either of the GNU General Public License Version 2 or later (the "GPL"),
+ or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ in which case the provisions of the GPL or the LGPL are applicable instead
+ of those above. If you wish to allow use of your version of this file only
+ under the terms of either the GPL or the LGPL, and not to allow others to
+ use your version of this file under the terms of the MPL, indicate your
+ decision by deleting the provisions above and replace them with the notice
+ and other provisions required by the GPL or the LGPL. If you do not delete
+ the provisions above, a recipient may use your version of this file under
+ the terms of any one of the MPL, the GPL or the LGPL.
+
+ ***** END LICENSE BLOCK *****
+ 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.
+
+ Contributor: Henry Sobotka <sobotka@axess.com>
+
+ xptcallstub_vacpp.asm: ALP assembler procedure for VAC++ build of xptcall
+ |
+
+ .486P
+ .MODEL FLAT, OPTLINK
+ .STACK
+
+ .CODE
+
+ EXTERN OPTLINK PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi:PROC
+
+setentidx MACRO index
+
+ push ecx ; Save parameters
+ push edx ; Save parameters - don't need to save eax - it is the "this" ptr
+ lea ecx, dword ptr [esp+10h] ; Load pointer to "args" into ecx
+ mov edx, index ; Move vtable index into edx
+ sub esp, 0ch ; Make room for three parameters on the stack
+ call PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi
+ add esp, 14h ; Reset stack pointer
+ ret
+ ENDM
+
+; 251 STUB_ENTRY(249)
+
+Stub249__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f9h
+Stub249__14nsXPTCStubBaseFv endp
+
+; 250 STUB_ENTRY(248)
+
+Stub248__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f8h
+Stub248__14nsXPTCStubBaseFv endp
+
+; 249 STUB_ENTRY(247)
+
+Stub247__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f7h
+Stub247__14nsXPTCStubBaseFv endp
+
+; 248 STUB_ENTRY(246)
+
+Stub246__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f6h
+Stub246__14nsXPTCStubBaseFv endp
+
+; 247 STUB_ENTRY(245)
+
+Stub245__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f5h
+Stub245__14nsXPTCStubBaseFv endp
+
+; 246 STUB_ENTRY(244)
+
+Stub244__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f4h
+Stub244__14nsXPTCStubBaseFv endp
+
+; 245 STUB_ENTRY(243)
+
+Stub243__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f3h
+Stub243__14nsXPTCStubBaseFv endp
+
+; 244 STUB_ENTRY(242)
+
+Stub242__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f2h
+Stub242__14nsXPTCStubBaseFv endp
+
+; 243 STUB_ENTRY(241)
+
+Stub241__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f1h
+Stub241__14nsXPTCStubBaseFv endp
+
+; 242 STUB_ENTRY(240)
+
+Stub240__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f0h
+Stub240__14nsXPTCStubBaseFv endp
+
+; 241 STUB_ENTRY(239)
+
+Stub239__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0efh
+Stub239__14nsXPTCStubBaseFv endp
+
+; 240 STUB_ENTRY(238)
+
+Stub238__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0eeh
+Stub238__14nsXPTCStubBaseFv endp
+
+; 239 STUB_ENTRY(237)
+
+Stub237__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0edh
+Stub237__14nsXPTCStubBaseFv endp
+
+; 238 STUB_ENTRY(236)
+
+Stub236__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ech
+Stub236__14nsXPTCStubBaseFv endp
+
+; 237 STUB_ENTRY(235)
+
+Stub235__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ebh
+Stub235__14nsXPTCStubBaseFv endp
+
+; 236 STUB_ENTRY(234)
+
+Stub234__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0eah
+Stub234__14nsXPTCStubBaseFv endp
+
+; 235 STUB_ENTRY(233)
+
+Stub233__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e9h
+Stub233__14nsXPTCStubBaseFv endp
+
+; 234 STUB_ENTRY(232)
+
+Stub232__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e8h
+Stub232__14nsXPTCStubBaseFv endp
+
+; 233 STUB_ENTRY(231)
+
+Stub231__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e7h
+Stub231__14nsXPTCStubBaseFv endp
+
+; 232 STUB_ENTRY(230)
+
+Stub230__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e6h
+Stub230__14nsXPTCStubBaseFv endp
+
+; 231 STUB_ENTRY(229)
+
+Stub229__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e5h
+Stub229__14nsXPTCStubBaseFv endp
+
+; 230 STUB_ENTRY(228)
+
+Stub228__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e4h
+Stub228__14nsXPTCStubBaseFv endp
+
+; 229 STUB_ENTRY(227)
+
+Stub227__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e3h
+Stub227__14nsXPTCStubBaseFv endp
+
+; 228 STUB_ENTRY(226)
+
+Stub226__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e2h
+Stub226__14nsXPTCStubBaseFv endp
+
+; 227 STUB_ENTRY(225)
+
+Stub225__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e1h
+Stub225__14nsXPTCStubBaseFv endp
+
+; 226 STUB_ENTRY(224)
+
+Stub224__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e0h
+Stub224__14nsXPTCStubBaseFv endp
+
+; 225 STUB_ENTRY(223)
+
+Stub223__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dfh
+Stub223__14nsXPTCStubBaseFv endp
+
+; 224 STUB_ENTRY(222)
+
+Stub222__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0deh
+Stub222__14nsXPTCStubBaseFv endp
+
+; 223 STUB_ENTRY(221)
+
+Stub221__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ddh
+Stub221__14nsXPTCStubBaseFv endp
+
+; 222 STUB_ENTRY(220)
+
+Stub220__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dch
+Stub220__14nsXPTCStubBaseFv endp
+
+; 221 STUB_ENTRY(219)
+
+Stub219__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dbh
+Stub219__14nsXPTCStubBaseFv endp
+
+; 220 STUB_ENTRY(218)
+
+Stub218__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dah
+Stub218__14nsXPTCStubBaseFv endp
+
+; 219 STUB_ENTRY(217)
+
+Stub217__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d9h
+Stub217__14nsXPTCStubBaseFv endp
+
+; 218 STUB_ENTRY(216)
+
+Stub216__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d8h
+Stub216__14nsXPTCStubBaseFv endp
+
+; 217 STUB_ENTRY(215)
+
+Stub215__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d7h
+Stub215__14nsXPTCStubBaseFv endp
+
+; 216 STUB_ENTRY(214)
+
+Stub214__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d6h
+Stub214__14nsXPTCStubBaseFv endp
+
+; 215 STUB_ENTRY(213)
+
+Stub213__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d5h
+Stub213__14nsXPTCStubBaseFv endp
+
+; 214 STUB_ENTRY(212)
+
+Stub212__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d4h
+Stub212__14nsXPTCStubBaseFv endp
+
+; 213 STUB_ENTRY(211)
+
+Stub211__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d3h
+Stub211__14nsXPTCStubBaseFv endp
+
+; 212 STUB_ENTRY(210)
+
+Stub210__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d2h
+Stub210__14nsXPTCStubBaseFv endp
+
+; 211 STUB_ENTRY(209)
+
+Stub209__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d1h
+Stub209__14nsXPTCStubBaseFv endp
+
+; 210 STUB_ENTRY(208)
+
+Stub208__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d0h
+Stub208__14nsXPTCStubBaseFv endp
+
+; 209 STUB_ENTRY(207)
+
+Stub207__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cfh
+Stub207__14nsXPTCStubBaseFv endp
+
+; 208 STUB_ENTRY(206)
+
+Stub206__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ceh
+Stub206__14nsXPTCStubBaseFv endp
+
+; 207 STUB_ENTRY(205)
+
+Stub205__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cdh
+Stub205__14nsXPTCStubBaseFv endp
+
+; 206 STUB_ENTRY(204)
+
+Stub204__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cch
+Stub204__14nsXPTCStubBaseFv endp
+
+; 205 STUB_ENTRY(203)
+
+Stub203__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cbh
+Stub203__14nsXPTCStubBaseFv endp
+
+; 204 STUB_ENTRY(202)
+
+Stub202__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cah
+Stub202__14nsXPTCStubBaseFv endp
+
+; 203 STUB_ENTRY(201)
+
+Stub201__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c9h
+Stub201__14nsXPTCStubBaseFv endp
+
+; 202 STUB_ENTRY(200)
+
+Stub200__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c8h
+Stub200__14nsXPTCStubBaseFv endp
+
+; 201 STUB_ENTRY(199)
+
+Stub199__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c7h
+Stub199__14nsXPTCStubBaseFv endp
+
+; 200 STUB_ENTRY(198)
+
+Stub198__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c6h
+Stub198__14nsXPTCStubBaseFv endp
+
+; 199 STUB_ENTRY(197)
+
+Stub197__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c5h
+Stub197__14nsXPTCStubBaseFv endp
+
+; 198 STUB_ENTRY(196)
+
+Stub196__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c4h
+Stub196__14nsXPTCStubBaseFv endp
+
+; 197 STUB_ENTRY(195)
+
+Stub195__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c3h
+Stub195__14nsXPTCStubBaseFv endp
+
+; 196 STUB_ENTRY(194)
+
+Stub194__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c2h
+Stub194__14nsXPTCStubBaseFv endp
+
+; 195 STUB_ENTRY(193)
+
+Stub193__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c1h
+Stub193__14nsXPTCStubBaseFv endp
+
+; 194 STUB_ENTRY(192)
+
+Stub192__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c0h
+Stub192__14nsXPTCStubBaseFv endp
+
+; 193 STUB_ENTRY(191)
+
+Stub191__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bfh
+Stub191__14nsXPTCStubBaseFv endp
+
+; 192 STUB_ENTRY(190)
+
+Stub190__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0beh
+Stub190__14nsXPTCStubBaseFv endp
+
+; 191 STUB_ENTRY(189)
+
+Stub189__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bdh
+Stub189__14nsXPTCStubBaseFv endp
+
+; 190 STUB_ENTRY(188)
+
+Stub188__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bch
+Stub188__14nsXPTCStubBaseFv endp
+
+; 189 STUB_ENTRY(187)
+
+Stub187__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bbh
+Stub187__14nsXPTCStubBaseFv endp
+
+; 188 STUB_ENTRY(186)
+
+Stub186__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bah
+Stub186__14nsXPTCStubBaseFv endp
+
+; 187 STUB_ENTRY(185)
+
+Stub185__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b9h
+Stub185__14nsXPTCStubBaseFv endp
+
+; 186 STUB_ENTRY(184)
+
+Stub184__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b8h
+Stub184__14nsXPTCStubBaseFv endp
+
+; 185 STUB_ENTRY(183)
+
+Stub183__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b7h
+Stub183__14nsXPTCStubBaseFv endp
+
+; 184 STUB_ENTRY(182)
+
+Stub182__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b6h
+Stub182__14nsXPTCStubBaseFv endp
+
+; 183 STUB_ENTRY(181)
+
+Stub181__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b5h
+Stub181__14nsXPTCStubBaseFv endp
+
+; 182 STUB_ENTRY(180)
+
+Stub180__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b4h
+Stub180__14nsXPTCStubBaseFv endp
+
+; 181 STUB_ENTRY(179)
+
+Stub179__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b3h
+Stub179__14nsXPTCStubBaseFv endp
+
+; 180 STUB_ENTRY(178)
+
+Stub178__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b2h
+Stub178__14nsXPTCStubBaseFv endp
+
+; 179 STUB_ENTRY(177)
+
+Stub177__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b1h
+Stub177__14nsXPTCStubBaseFv endp
+
+; 178 STUB_ENTRY(176)
+
+Stub176__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b0h
+Stub176__14nsXPTCStubBaseFv endp
+
+; 177 STUB_ENTRY(175)
+
+Stub175__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0afh
+Stub175__14nsXPTCStubBaseFv endp
+
+; 176 STUB_ENTRY(174)
+
+Stub174__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0aeh
+Stub174__14nsXPTCStubBaseFv endp
+
+; 175 STUB_ENTRY(173)
+
+Stub173__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0adh
+Stub173__14nsXPTCStubBaseFv endp
+
+; 174 STUB_ENTRY(172)
+
+Stub172__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ach
+Stub172__14nsXPTCStubBaseFv endp
+
+; 173 STUB_ENTRY(171)
+
+Stub171__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0abh
+Stub171__14nsXPTCStubBaseFv endp
+
+; 172 STUB_ENTRY(170)
+
+Stub170__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0aah
+Stub170__14nsXPTCStubBaseFv endp
+
+; 171 STUB_ENTRY(169)
+
+Stub169__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a9h
+Stub169__14nsXPTCStubBaseFv endp
+
+; 170 STUB_ENTRY(168)
+
+Stub168__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a8h
+Stub168__14nsXPTCStubBaseFv endp
+
+; 169 STUB_ENTRY(167)
+
+Stub167__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a7h
+Stub167__14nsXPTCStubBaseFv endp
+
+; 168 STUB_ENTRY(166)
+
+Stub166__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a6h
+Stub166__14nsXPTCStubBaseFv endp
+
+; 167 STUB_ENTRY(165)
+
+Stub165__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a5h
+Stub165__14nsXPTCStubBaseFv endp
+
+; 166 STUB_ENTRY(164)
+
+Stub164__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a4h
+Stub164__14nsXPTCStubBaseFv endp
+
+; 165 STUB_ENTRY(163)
+
+Stub163__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a3h
+Stub163__14nsXPTCStubBaseFv endp
+
+; 164 STUB_ENTRY(162)
+
+Stub162__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a2h
+Stub162__14nsXPTCStubBaseFv endp
+
+; 163 STUB_ENTRY(161)
+
+Stub161__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a1h
+Stub161__14nsXPTCStubBaseFv endp
+
+; 162 STUB_ENTRY(160)
+
+Stub160__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a0h
+Stub160__14nsXPTCStubBaseFv endp
+
+; 161 STUB_ENTRY(159)
+
+Stub159__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09fh
+Stub159__14nsXPTCStubBaseFv endp
+
+; 160 STUB_ENTRY(158)
+
+Stub158__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09eh
+Stub158__14nsXPTCStubBaseFv endp
+
+; 159 STUB_ENTRY(157)
+
+Stub157__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09dh
+Stub157__14nsXPTCStubBaseFv endp
+
+; 158 STUB_ENTRY(156)
+
+Stub156__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09ch
+Stub156__14nsXPTCStubBaseFv endp
+
+; 157 STUB_ENTRY(155)
+
+Stub155__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09bh
+Stub155__14nsXPTCStubBaseFv endp
+
+; 156 STUB_ENTRY(154)
+
+Stub154__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09ah
+Stub154__14nsXPTCStubBaseFv endp
+
+; 155 STUB_ENTRY(153)
+
+Stub153__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 099h
+Stub153__14nsXPTCStubBaseFv endp
+
+; 154 STUB_ENTRY(152)
+
+Stub152__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 098h
+Stub152__14nsXPTCStubBaseFv endp
+
+; 153 STUB_ENTRY(151)
+
+Stub151__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 097h
+Stub151__14nsXPTCStubBaseFv endp
+
+; 152 STUB_ENTRY(150)
+
+Stub150__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 096h
+Stub150__14nsXPTCStubBaseFv endp
+
+; 151 STUB_ENTRY(149)
+
+Stub149__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 095h
+Stub149__14nsXPTCStubBaseFv endp
+
+; 150 STUB_ENTRY(148)
+
+Stub148__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 094h
+Stub148__14nsXPTCStubBaseFv endp
+
+; 149 STUB_ENTRY(147)
+
+Stub147__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 093h
+Stub147__14nsXPTCStubBaseFv endp
+
+; 148 STUB_ENTRY(146)
+
+Stub146__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 092h
+Stub146__14nsXPTCStubBaseFv endp
+
+; 147 STUB_ENTRY(145)
+
+Stub145__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 091h
+Stub145__14nsXPTCStubBaseFv endp
+
+; 146 STUB_ENTRY(144)
+
+Stub144__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 090h
+Stub144__14nsXPTCStubBaseFv endp
+
+; 145 STUB_ENTRY(143)
+
+Stub143__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08fh
+Stub143__14nsXPTCStubBaseFv endp
+
+; 144 STUB_ENTRY(142)
+
+Stub142__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08eh
+Stub142__14nsXPTCStubBaseFv endp
+
+; 143 STUB_ENTRY(141)
+
+Stub141__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08dh
+Stub141__14nsXPTCStubBaseFv endp
+
+; 142 STUB_ENTRY(140)
+
+Stub140__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08ch
+Stub140__14nsXPTCStubBaseFv endp
+
+; 141 STUB_ENTRY(139)
+
+Stub139__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08bh
+Stub139__14nsXPTCStubBaseFv endp
+
+; 140 STUB_ENTRY(138)
+
+Stub138__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08ah
+Stub138__14nsXPTCStubBaseFv endp
+
+; 139 STUB_ENTRY(137)
+
+Stub137__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 089h
+Stub137__14nsXPTCStubBaseFv endp
+
+; 138 STUB_ENTRY(136)
+
+Stub136__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 088h
+Stub136__14nsXPTCStubBaseFv endp
+
+; 137 STUB_ENTRY(135)
+
+Stub135__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 087h
+Stub135__14nsXPTCStubBaseFv endp
+
+; 136 STUB_ENTRY(134)
+
+Stub134__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 086h
+Stub134__14nsXPTCStubBaseFv endp
+
+; 135 STUB_ENTRY(133)
+
+Stub133__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 085h
+Stub133__14nsXPTCStubBaseFv endp
+
+; 134 STUB_ENTRY(132)
+
+Stub132__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 084h
+Stub132__14nsXPTCStubBaseFv endp
+
+; 133 STUB_ENTRY(131)
+
+Stub131__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 083h
+Stub131__14nsXPTCStubBaseFv endp
+
+; 132 STUB_ENTRY(130)
+
+Stub130__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 082h
+Stub130__14nsXPTCStubBaseFv endp
+
+; 131 STUB_ENTRY(129)
+
+Stub129__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 081h
+Stub129__14nsXPTCStubBaseFv endp
+
+; 130 STUB_ENTRY(128)
+
+Stub128__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 080h
+Stub128__14nsXPTCStubBaseFv endp
+
+; 129 STUB_ENTRY(127)
+
+Stub127__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07fh
+Stub127__14nsXPTCStubBaseFv endp
+
+; 128 STUB_ENTRY(126)
+
+Stub126__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07eh
+Stub126__14nsXPTCStubBaseFv endp
+
+; 127 STUB_ENTRY(125)
+
+Stub125__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07dh
+Stub125__14nsXPTCStubBaseFv endp
+
+; 126 STUB_ENTRY(124)
+
+Stub124__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07ch
+Stub124__14nsXPTCStubBaseFv endp
+
+; 125 STUB_ENTRY(123)
+
+Stub123__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07bh
+Stub123__14nsXPTCStubBaseFv endp
+
+; 124 STUB_ENTRY(122)
+
+Stub122__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07ah
+Stub122__14nsXPTCStubBaseFv endp
+
+; 123 STUB_ENTRY(121)
+
+Stub121__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 079h
+Stub121__14nsXPTCStubBaseFv endp
+
+; 122 STUB_ENTRY(120)
+
+Stub120__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 078h
+Stub120__14nsXPTCStubBaseFv endp
+
+; 121 STUB_ENTRY(119)
+
+Stub119__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 077h
+Stub119__14nsXPTCStubBaseFv endp
+
+; 120 STUB_ENTRY(118)
+
+Stub118__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 076h
+Stub118__14nsXPTCStubBaseFv endp
+
+; 119 STUB_ENTRY(117)
+
+Stub117__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 075h
+Stub117__14nsXPTCStubBaseFv endp
+
+; 118 STUB_ENTRY(116)
+
+Stub116__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 074h
+Stub116__14nsXPTCStubBaseFv endp
+
+; 117 STUB_ENTRY(115)
+
+Stub115__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 073h
+Stub115__14nsXPTCStubBaseFv endp
+
+; 116 STUB_ENTRY(114)
+
+Stub114__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 072h
+Stub114__14nsXPTCStubBaseFv endp
+
+; 115 STUB_ENTRY(113)
+
+Stub113__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 071h
+Stub113__14nsXPTCStubBaseFv endp
+
+; 114 STUB_ENTRY(112)
+
+Stub112__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 070h
+Stub112__14nsXPTCStubBaseFv endp
+
+; 113 STUB_ENTRY(111)
+
+Stub111__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06fh
+Stub111__14nsXPTCStubBaseFv endp
+
+; 112 STUB_ENTRY(110)
+
+Stub110__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06eh
+Stub110__14nsXPTCStubBaseFv endp
+
+; 111 STUB_ENTRY(109)
+
+Stub109__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06dh
+Stub109__14nsXPTCStubBaseFv endp
+
+; 110 STUB_ENTRY(108)
+
+Stub108__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06ch
+Stub108__14nsXPTCStubBaseFv endp
+
+; 109 STUB_ENTRY(107)
+
+Stub107__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06bh
+Stub107__14nsXPTCStubBaseFv endp
+
+; 108 STUB_ENTRY(106)
+
+Stub106__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06ah
+Stub106__14nsXPTCStubBaseFv endp
+
+; 107 STUB_ENTRY(105)
+
+Stub105__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 069h
+Stub105__14nsXPTCStubBaseFv endp
+
+; 106 STUB_ENTRY(104)
+
+Stub104__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 068h
+Stub104__14nsXPTCStubBaseFv endp
+
+; 105 STUB_ENTRY(103)
+
+Stub103__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 067h
+Stub103__14nsXPTCStubBaseFv endp
+
+; 104 STUB_ENTRY(102)
+
+Stub102__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 066h
+Stub102__14nsXPTCStubBaseFv endp
+
+; 103 STUB_ENTRY(101)
+
+Stub101__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 065h
+Stub101__14nsXPTCStubBaseFv endp
+
+; 102 STUB_ENTRY(100)
+
+Stub100__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 064h
+Stub100__14nsXPTCStubBaseFv endp
+
+; 101 STUB_ENTRY(99)
+
+Stub99__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 063h
+Stub99__14nsXPTCStubBaseFv endp
+
+; 100 STUB_ENTRY(98)
+
+Stub98__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 062h
+Stub98__14nsXPTCStubBaseFv endp
+
+; 99 STUB_ENTRY(97)
+
+Stub97__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 061h
+Stub97__14nsXPTCStubBaseFv endp
+
+; 98 STUB_ENTRY(96)
+
+Stub96__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 060h
+Stub96__14nsXPTCStubBaseFv endp
+
+; 97 STUB_ENTRY(95)
+
+Stub95__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05fh
+Stub95__14nsXPTCStubBaseFv endp
+
+; 96 STUB_ENTRY(94)
+
+Stub94__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05eh
+Stub94__14nsXPTCStubBaseFv endp
+
+; 95 STUB_ENTRY(93)
+
+Stub93__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05dh
+Stub93__14nsXPTCStubBaseFv endp
+
+; 94 STUB_ENTRY(92)
+
+Stub92__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05ch
+Stub92__14nsXPTCStubBaseFv endp
+
+; 93 STUB_ENTRY(91)
+
+Stub91__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05bh
+Stub91__14nsXPTCStubBaseFv endp
+
+; 92 STUB_ENTRY(90)
+
+Stub90__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05ah
+Stub90__14nsXPTCStubBaseFv endp
+
+; 91 STUB_ENTRY(89)
+
+Stub89__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 059h
+Stub89__14nsXPTCStubBaseFv endp
+
+; 90 STUB_ENTRY(88)
+
+Stub88__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 058h
+Stub88__14nsXPTCStubBaseFv endp
+
+; 89 STUB_ENTRY(87)
+
+Stub87__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 057h
+Stub87__14nsXPTCStubBaseFv endp
+
+; 88 STUB_ENTRY(86)
+
+Stub86__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 056h
+Stub86__14nsXPTCStubBaseFv endp
+
+; 87 STUB_ENTRY(85)
+
+Stub85__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 055h
+Stub85__14nsXPTCStubBaseFv endp
+
+; 86 STUB_ENTRY(84)
+
+Stub84__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 054h
+Stub84__14nsXPTCStubBaseFv endp
+
+; 85 STUB_ENTRY(83)
+
+Stub83__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 053h
+Stub83__14nsXPTCStubBaseFv endp
+
+; 84 STUB_ENTRY(82)
+
+Stub82__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 052h
+Stub82__14nsXPTCStubBaseFv endp
+
+; 83 STUB_ENTRY(81)
+
+Stub81__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 051h
+Stub81__14nsXPTCStubBaseFv endp
+
+; 82 STUB_ENTRY(80)
+
+Stub80__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 050h
+Stub80__14nsXPTCStubBaseFv endp
+
+; 81 STUB_ENTRY(79)
+
+Stub79__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04fh
+Stub79__14nsXPTCStubBaseFv endp
+
+; 80 STUB_ENTRY(78)
+
+Stub78__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04eh
+Stub78__14nsXPTCStubBaseFv endp
+
+; 79 STUB_ENTRY(77)
+
+Stub77__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04dh
+Stub77__14nsXPTCStubBaseFv endp
+
+; 78 STUB_ENTRY(76)
+
+Stub76__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04ch
+Stub76__14nsXPTCStubBaseFv endp
+
+; 77 STUB_ENTRY(75)
+
+Stub75__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04bh
+Stub75__14nsXPTCStubBaseFv endp
+
+; 76 STUB_ENTRY(74)
+
+Stub74__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04ah
+Stub74__14nsXPTCStubBaseFv endp
+
+; 75 STUB_ENTRY(73)
+
+Stub73__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 049h
+Stub73__14nsXPTCStubBaseFv endp
+
+; 74 STUB_ENTRY(72)
+
+Stub72__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 048h
+Stub72__14nsXPTCStubBaseFv endp
+
+; 73 STUB_ENTRY(71)
+
+Stub71__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 047h
+Stub71__14nsXPTCStubBaseFv endp
+
+; 72 STUB_ENTRY(70)
+
+Stub70__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 046h
+Stub70__14nsXPTCStubBaseFv endp
+
+; 71 STUB_ENTRY(69)
+
+Stub69__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 045h
+Stub69__14nsXPTCStubBaseFv endp
+
+; 70 STUB_ENTRY(68)
+
+Stub68__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 044h
+Stub68__14nsXPTCStubBaseFv endp
+
+; 69 STUB_ENTRY(67)
+
+Stub67__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 043h
+Stub67__14nsXPTCStubBaseFv endp
+
+; 68 STUB_ENTRY(66)
+
+Stub66__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 042h
+Stub66__14nsXPTCStubBaseFv endp
+
+; 67 STUB_ENTRY(65)
+
+Stub65__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 041h
+Stub65__14nsXPTCStubBaseFv endp
+
+; 66 STUB_ENTRY(64)
+
+Stub64__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 040h
+Stub64__14nsXPTCStubBaseFv endp
+
+; 65 STUB_ENTRY(63)
+
+Stub63__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03fh
+Stub63__14nsXPTCStubBaseFv endp
+
+; 64 STUB_ENTRY(62)
+
+Stub62__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03eh
+Stub62__14nsXPTCStubBaseFv endp
+
+; 63 STUB_ENTRY(61)
+
+Stub61__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03dh
+Stub61__14nsXPTCStubBaseFv endp
+
+; 62 STUB_ENTRY(60)
+
+Stub60__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03ch
+Stub60__14nsXPTCStubBaseFv endp
+
+; 61 STUB_ENTRY(59)
+
+Stub59__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03bh
+Stub59__14nsXPTCStubBaseFv endp
+
+; 60 STUB_ENTRY(58)
+
+Stub58__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03ah
+Stub58__14nsXPTCStubBaseFv endp
+
+; 59 STUB_ENTRY(57)
+
+Stub57__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 039h
+Stub57__14nsXPTCStubBaseFv endp
+
+; 58 STUB_ENTRY(56)
+
+Stub56__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 038h
+Stub56__14nsXPTCStubBaseFv endp
+
+; 57 STUB_ENTRY(55)
+
+Stub55__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 037h
+Stub55__14nsXPTCStubBaseFv endp
+
+; 56 STUB_ENTRY(54)
+
+Stub54__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 036h
+Stub54__14nsXPTCStubBaseFv endp
+
+; 55 STUB_ENTRY(53)
+
+Stub53__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 035h
+Stub53__14nsXPTCStubBaseFv endp
+
+; 54 STUB_ENTRY(52)
+
+Stub52__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 034h
+Stub52__14nsXPTCStubBaseFv endp
+
+; 53 STUB_ENTRY(51)
+
+Stub51__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 033h
+Stub51__14nsXPTCStubBaseFv endp
+
+; 52 STUB_ENTRY(50)
+
+Stub50__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 032h
+Stub50__14nsXPTCStubBaseFv endp
+
+; 51 STUB_ENTRY(49)
+
+Stub49__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 031h
+Stub49__14nsXPTCStubBaseFv endp
+
+; 50 STUB_ENTRY(48)
+
+Stub48__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 030h
+Stub48__14nsXPTCStubBaseFv endp
+
+; 49 STUB_ENTRY(47)
+
+Stub47__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02fh
+Stub47__14nsXPTCStubBaseFv endp
+
+; 48 STUB_ENTRY(46)
+
+Stub46__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02eh
+Stub46__14nsXPTCStubBaseFv endp
+
+; 47 STUB_ENTRY(45)
+
+Stub45__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02dh
+Stub45__14nsXPTCStubBaseFv endp
+
+; 46 STUB_ENTRY(44)
+
+Stub44__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02ch
+Stub44__14nsXPTCStubBaseFv endp
+
+; 45 STUB_ENTRY(43)
+
+Stub43__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02bh
+Stub43__14nsXPTCStubBaseFv endp
+
+; 44 STUB_ENTRY(42)
+
+Stub42__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02ah
+Stub42__14nsXPTCStubBaseFv endp
+
+; 43 STUB_ENTRY(41)
+
+Stub41__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 029h
+Stub41__14nsXPTCStubBaseFv endp
+
+; 42 STUB_ENTRY(40)
+
+Stub40__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 028h
+Stub40__14nsXPTCStubBaseFv endp
+
+; 41 STUB_ENTRY(39)
+
+Stub39__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 027h
+Stub39__14nsXPTCStubBaseFv endp
+
+; 40 STUB_ENTRY(38)
+
+Stub38__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 026h
+Stub38__14nsXPTCStubBaseFv endp
+
+; 39 STUB_ENTRY(37)
+
+Stub37__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 025h
+Stub37__14nsXPTCStubBaseFv endp
+
+; 38 STUB_ENTRY(36)
+
+Stub36__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 024h
+Stub36__14nsXPTCStubBaseFv endp
+
+; 37 STUB_ENTRY(35)
+
+Stub35__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 023h
+Stub35__14nsXPTCStubBaseFv endp
+
+; 36 STUB_ENTRY(34)
+
+Stub34__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 022h
+Stub34__14nsXPTCStubBaseFv endp
+
+; 35 STUB_ENTRY(33)
+
+Stub33__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 021h
+Stub33__14nsXPTCStubBaseFv endp
+
+; 34 STUB_ENTRY(32)
+
+Stub32__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 020h
+Stub32__14nsXPTCStubBaseFv endp
+
+; 33 STUB_ENTRY(31)
+
+Stub31__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01fh
+Stub31__14nsXPTCStubBaseFv endp
+
+; 32 STUB_ENTRY(30)
+
+Stub30__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01eh
+Stub30__14nsXPTCStubBaseFv endp
+
+; 31 STUB_ENTRY(29)
+
+Stub29__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01dh
+Stub29__14nsXPTCStubBaseFv endp
+
+; 30 STUB_ENTRY(28)
+
+Stub28__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01ch
+Stub28__14nsXPTCStubBaseFv endp
+
+; 29 STUB_ENTRY(27)
+
+Stub27__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01bh
+Stub27__14nsXPTCStubBaseFv endp
+
+; 28 STUB_ENTRY(26)
+
+Stub26__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01ah
+Stub26__14nsXPTCStubBaseFv endp
+
+; 27 STUB_ENTRY(25)
+
+Stub25__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 019h
+Stub25__14nsXPTCStubBaseFv endp
+
+; 26 STUB_ENTRY(24)
+
+Stub24__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 018h
+Stub24__14nsXPTCStubBaseFv endp
+
+; 25 STUB_ENTRY(23)
+
+Stub23__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 017h
+Stub23__14nsXPTCStubBaseFv endp
+
+; 24 STUB_ENTRY(22)
+
+Stub22__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 016h
+Stub22__14nsXPTCStubBaseFv endp
+
+; 23 STUB_ENTRY(21)
+
+Stub21__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 015h
+Stub21__14nsXPTCStubBaseFv endp
+
+; 22 STUB_ENTRY(20)
+
+Stub20__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 014h
+Stub20__14nsXPTCStubBaseFv endp
+
+; 21 STUB_ENTRY(19)
+
+Stub19__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 013h
+Stub19__14nsXPTCStubBaseFv endp
+
+; 20 STUB_ENTRY(18)
+
+Stub18__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 012h
+Stub18__14nsXPTCStubBaseFv endp
+
+; 19 STUB_ENTRY(17)
+
+Stub17__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 011h
+Stub17__14nsXPTCStubBaseFv endp
+
+; 18 STUB_ENTRY(16)
+
+Stub16__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 010h
+Stub16__14nsXPTCStubBaseFv endp
+
+; 17 STUB_ENTRY(15)
+
+Stub15__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0fh
+Stub15__14nsXPTCStubBaseFv endp
+
+; 16 STUB_ENTRY(14)
+
+Stub14__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0eh
+Stub14__14nsXPTCStubBaseFv endp
+
+; 15 STUB_ENTRY(13)
+
+Stub13__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dh
+Stub13__14nsXPTCStubBaseFv endp
+
+; 14 STUB_ENTRY(12)
+
+Stub12__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ch
+Stub12__14nsXPTCStubBaseFv endp
+
+; 13 STUB_ENTRY(11)
+
+Stub11__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bh
+Stub11__14nsXPTCStubBaseFv endp
+
+; 12 STUB_ENTRY(10)
+
+Stub10__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ah
+Stub10__14nsXPTCStubBaseFv endp
+
+; 11 STUB_ENTRY(9)
+
+Stub9__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09h
+Stub9__14nsXPTCStubBaseFv endp
+
+; 10 STUB_ENTRY(8)
+
+Stub8__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08h
+Stub8__14nsXPTCStubBaseFv endp
+
+; 9 STUB_ENTRY(7)
+
+Stub7__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07h
+Stub7__14nsXPTCStubBaseFv endp
+
+; 8 STUB_ENTRY(6)
+
+Stub6__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06h
+Stub6__14nsXPTCStubBaseFv endp
+
+; 7 STUB_ENTRY(5)
+
+Stub5__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05h
+Stub5__14nsXPTCStubBaseFv endp
+
+; 6 STUB_ENTRY(4)
+
+Stub4__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04h
+Stub4__14nsXPTCStubBaseFv endp
+
+; 5 STUB_ENTRY(3)
+
+Stub3__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03h
+Stub3__14nsXPTCStubBaseFv endp
+
+
+ END
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore
new file mode 100644
index 00000000..055e647f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+invoke_test
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in
new file mode 100644
index 00000000..dbf0f64d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in
@@ -0,0 +1,50 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+CPPSRCS = stub_test.cpp #invoke_test.cpp
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README
new file mode 100644
index 00000000..04850b2e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README
@@ -0,0 +1,6 @@
+These are just simple test programs in which stripped down versions of the
+XPConnect invoke and stubs code can be built and tested as the code is brought
+up on various platforms. These probrams do not test the param sizing and copying
+functionality of the routines. However, they do supply a place where the lowest
+level assembly language code can be developed and debugged in the simplest of
+contexts before it is moved into the real routines. \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat
new file mode 100644
index 00000000..f320e222
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat
@@ -0,0 +1,5 @@
+@echo off
+echo deleting intermediate files
+if exist *.obj del *.obj > NUL
+if exist *.ilk del *.ilk > NUL
+if exist *.pdb del *.pdb > NUL \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp
new file mode 100644
index 00000000..376ba58f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp
@@ -0,0 +1,239 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned PRUint32;
+typedef unsigned nsXPCVariant;
+
+
+#if defined(WIN32)
+#define NS_IMETHOD virtual nsresult __stdcall
+#define NS_IMETHODIMP nsresult __stdcall
+#else
+#define NS_IMETHOD virtual nsresult
+#define NS_IMETHODIMP nsresult
+#endif
+
+
+class base{
+public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo{
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+/*
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+*/
+
+NS_IMETHODIMP bar::ignored(){return 0;}
+
+NS_IMETHODIMP bar::callme1(int i, int j)
+{
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j)
+{
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j)
+{
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 5;
+}
+
+void docall(foo* f, int i, int j){
+ f->callme1(i, j);
+}
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static PRUint32 __stdcall
+invoke_count_words(PRUint32 paramCount, nsXPCVariant* s)
+{
+ return paramCount;
+}
+
+static void __stdcall
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ *((PRUint32*)d) = *((PRUint32*)s);
+ }
+}
+
+static nsresult __stdcall
+DoInvoke(void* that, PRUint32 index,
+ PRUint32 paramCount, nsXPCVariant* params)
+{
+ __asm {
+ push params
+ push paramCount
+ call invoke_count_words // stdcall, result in eax
+ shl eax,2 // *= 4
+ sub esp,eax // make space for params
+ mov edx,esp
+ push params
+ push paramCount
+ push edx
+ call invoke_copy_to_stack // stdcall
+ mov ecx,that // instance in ecx
+ push ecx // push this
+ mov edx,[ecx] // vtable in edx
+ mov eax,index
+ shl eax,2 // *= 4
+ add edx,eax
+ call [edx] // stdcall, i.e. callee cleans up stack.
+ }
+}
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPCVariant* s)
+{
+ return paramCount;
+}
+
+static void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ *((PRUint32*)d) = *((PRUint32*)s);
+ }
+}
+
+static nsresult
+DoInvoke(void* that, PRUint32 index,
+ PRUint32 paramCount, nsXPCVariant* params)
+{
+ PRUint32 result;
+ void* fn_count = invoke_count_words;
+ void* fn_copy = invoke_copy_to_stack;
+
+ __asm__ __volatile__(
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "movl %5, %%eax\n\t"
+ "call *%%eax\n\t" /* count words */
+ "addl $0x8, %%esp\n\t"
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "subl %%eax, %%esp\n\t" /* make room for params */
+ "movl %%esp, %%edx\n\t"
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "pushl %%edx\n\t"
+ "movl %6, %%eax\n\t"
+ "call *%%eax\n\t" /* copy params */
+ "addl $0xc, %%esp\n\t"
+ "movl %1, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %2, %%eax\n\t" /* function index */
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "addl $8, %%eax\n\t" /* += 8 */
+ "addl %%eax, %%edx\n\t"
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+ "movl %%eax, %0"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (index), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "g" (fn_count), /* %5 */
+ "g" (fn_copy) /* %6 */
+ : "ax", "cx", "dx", "memory"
+ );
+
+ return result;
+}
+
+#endif
+/***************************************************************************/
+
+int main()
+{
+ nsXPCVariant params1[2] = {1,2};
+ nsXPCVariant params2[2] = {2,4};
+ nsXPCVariant params3[2] = {3,6};
+
+ foo* a = new bar();
+
+// printf("calling via C++...\n");
+// docall(a, 12, 24);
+
+ printf("calling via ASM...\n");
+ DoInvoke(a, 1, 2, params1);
+ DoInvoke(a, 2, 2, params2);
+ DoInvoke(a, 3, 2, params3);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat
new file mode 100644
index 00000000..10a9be51
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist invoke_test.obj del invoke_test.obj > NUL
+if exist invoke_test.ilk del invoke_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist invoke_test.exe del invoke_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 invoke_test.cpp \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat
new file mode 100644
index 00000000..f9af17af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist stub_test.obj del stub_test.obj > NUL
+if exist stub_test.ilk del stub_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist stub_test.exe del stub_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 stub_test.cpp \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp
new file mode 100644
index 00000000..10935299
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp
@@ -0,0 +1,210 @@
+
+#include <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned PRUint32;
+typedef unsigned nsXPCVariant;
+
+
+#if defined(WIN32)
+#define NS_IMETHOD virtual nsresult __stdcall
+#define NS_IMETHODIMP nsresult __stdcall
+#else
+#define NS_IMETHOD virtual nsresult
+#define NS_IMETHODIMP nsresult
+#endif
+
+
+class base{
+public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo{
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+
+NS_IMETHODIMP bar::ignored(){return 0;}
+
+NS_IMETHODIMP bar::callme1(int i, int j)
+{
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 15;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j)
+{
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 25;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j)
+{
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 35;
+}
+
+void docall(foo* f, int i, int j){
+ f->callme1(i, j);
+}
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static int __stdcall
+PrepareAndDispatch(baz* self, PRUint32 methodIndex,
+ PRUint32* args, PRUint32* stackBytesToPop)
+{
+ fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n",
+ (void*)self, methodIndex, (void*)args);
+ foo* a = self->other;
+ int p1 = (int) *args;
+ int p2 = (int) *(args+1);
+ int out = 0;
+ switch(methodIndex)
+ {
+ case 1: out = a->callme1(p1, p2); break;
+ case 2: out = a->callme2(p1, p2); break;
+ case 3: out = a->callme3(p1, p2); break;
+ }
+ *stackBytesToPop = 2*4;
+ return out;
+}
+
+#ifndef __GNUC__
+static __declspec(naked) void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea ecx, [ebp+16] // pointer to args
+ push ecx
+ mov edx, [ebp+4] // vtbl_index
+ push edx
+ mov eax, [ebp+12] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+8] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 12 // for this, the index, and ret address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+__declspec(naked) nsresult __stdcall baz::callme##n() \
+{ __asm push n __asm jmp SharedStub }
+
+#else /* __GNUC__ */
+
+#define STUB_ENTRY(n) \
+nsresult __stdcall baz::callme##n() \
+{ \
+ PRUint32 *args, stackBytesToPop; \
+ int result = 0; \
+ baz *obj; \
+ __asm__ __volatile__ ( \
+ "leal 0x0c(%%ebp), %0\n\t" /* args */ \
+ "movl 0x08(%%ebp), %1\n\t" /* this */ \
+ : "=r" (args), \
+ "=r" (obj)); \
+ result = PrepareAndDispatch(obj, n, args,&stackBytesToPop); \
+ fprintf(stdout, "stub returning: %d\n", result); \
+ fprintf(stdout, "bytes to pop: %d\n", stackBytesToPop); \
+ return result; \
+}
+
+#endif /* ! __GNUC__ */
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static int
+PrepareAndDispatch(baz* self, PRUint32 methodIndex, PRUint32* args)
+{
+ foo* a = self->other;
+ int p1 = (int) *args;
+ int p2 = (int) *(args+1);
+ switch(methodIndex)
+ {
+ case 1: a->callme1(p1, p2); break;
+ case 2: a->callme2(p1, p2); break;
+ case 3: a->callme3(p1, p2); break;
+ }
+ return 1;
+}
+
+#define STUB_ENTRY(n) \
+nsresult baz::callme##n() \
+{ \
+ register void* method = PrepareAndDispatch; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx" /* PrepareAndDispatch */ \
+ : "=a" (result) /* %0 */ \
+ : "d" (method) /* %1 */ \
+ : "memory" ); \
+ return result; \
+}
+
+#endif
+/***************************************************************************/
+
+STUB_ENTRY(1)
+STUB_ENTRY(2)
+STUB_ENTRY(3)
+
+int main()
+{
+ foo* a = new bar();
+ baz* b = new baz();
+
+ /* here we make the global 'check for alloc failure' checker happy */
+ if(!a || !b)
+ return 1;
+
+ foo* c = (foo*)b;
+
+ b->setfoo(a);
+ c->callme1(1,2);
+ c->callme2(2,4);
+ c->callme3(3,6);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore
new file mode 100644
index 00000000..ff6fd9bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+xptcstubs_asm_mips.s
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in
new file mode 100644
index 00000000..78bf1f92
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in
@@ -0,0 +1,416 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xptcmd
+
+#
+# The default is this buildable, but non-functioning code.
+#
+CPPSRCS := xptcinvoke_unsupported.cpp xptcstubs_unsupported.cpp
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/config.mk
+
+######################################################################
+# i386 and beyond
+######################################################################
+#
+# Lots of Unixish x86 flavors
+#
+ifneq (,$(filter FreeBSD NetBSD OpenBSD BSD_OS Darwin,$(OS_ARCH)))
+ifeq (86,$(findstring 86,$(OS_TEST)))
+CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
+endif
+endif
+#
+# New code for Linux, et. al., with gcc
+# Migrate other platforms here after testing
+#
+ifneq (,$(filter Linux,$(OS_ARCH)))
+# Linux/x86-64
+ifeq (x86_64,$(OS_TEST))
+CPPSRCS := xptcinvoke_x86_64_linux.cpp xptcstubs_x86_64_linux.cpp
+else
+ifeq (86,$(findstring 86,$(OS_TEST)))
+CPPSRCS := xptcinvoke_gcc_x86_unix.cpp xptcstubs_gcc_x86_unix.cpp
+endif
+endif
+endif
+# IA64 Linux
+ifneq (,$(filter Linux,$(OS_ARCH)))
+ifneq (,$(findstring ia64,$(OS_TEST)))
+CPPSRCS := xptcinvoke_ipf64.cpp xptcstubs_ipf64.cpp
+ASFILES := xptcstubs_asm_ipf64.s xptcinvoke_asm_ipf64.s
+endif
+endif
+#
+# BeOS/Intel (uses the same unixish_x86 code)
+#
+ifeq ($(OS_ARCH)$(OS_TEST),BeOSBePC)
+CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
+endif
+#
+# Neutrino/Intel (uses the same unixish_x86 code)
+#
+ifeq ($(OS_TARGET)$(OS_TEST),NTOx86)
+CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
+endif
+
+######################################################################
+# Solaris/Intel
+######################################################################
+#
+# Solaris/Intel
+#
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_TEST),i86pc)
+CPPSRCS := xptcinvoke_x86_solaris.cpp xptcstubs_x86_solaris.cpp
+# 28817: if Solaris Intel OS, and native compiler, always build optimised.
+ifndef GNU_CC
+CXXFLAGS += -O
+endif
+endif
+endif
+
+######################################################################
+# Alpha
+######################################################################
+#
+# Tru64/Alpha
+#
+ifeq ($(OS_ARCH)$(OS_TEST),OSF1alpha)
+CPPSRCS := xptcinvoke_osf1_alpha.cpp xptcstubs_osf1_alpha.cpp
+ASFILES := xptcinvoke_asm_osf1_alpha.s xptcstubs_asm_osf1_alpha.s
+endif
+#
+# Linux/Alpha
+#
+ifneq (,$(filter Linuxalpha FreeBSDalpha NetBSDalpha,$(OS_ARCH)$(OS_TEST)))
+CPPSRCS := xptcinvoke_linux_alpha.cpp xptcstubs_linux_alpha.cpp
+endif
+#
+# OpenVMS/Alpha
+#
+ifeq ($(OS_ARCH)$(CPU_ARCH),OpenVMSAlpha)
+CPPSRCS := xptcinvoke_openvms_alpha.cpp xptcstubs_openvms_alpha.cpp
+ASFILES := xptcinvoke_asm_openvms_alpha.s xptcstubs_asm_openvms_alpha.s
+endif
+
+######################################################################
+# ARM
+######################################################################
+#
+# Linux/ARM
+#
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(filter arm% sa110,$(OS_TEST)))
+CPPSRCS := xptcinvoke_arm.cpp xptcstubs_arm.cpp
+CXXFLAGS += -O2
+endif
+endif
+#
+# NetBSD/ARM
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter arm% sa110,$(OS_TEST)))
+CPPSRCS := xptcinvoke_arm_netbsd.cpp xptcstubs_arm_netbsd.cpp
+endif
+endif
+
+######################################################################
+# HPPA
+######################################################################
+#
+# HP-UX/PA32
+#
+# for gas and gcc, check comment in xptcinvoke_asm_pa32.s
+ifeq ($(OS_ARCH),HP-UX)
+ifneq ($(CC),gcc)
+ifneq ($(OS_TEST),ia64)
+CPPSRCS := xptcinvoke_pa32.cpp xptcstubs_pa32.cpp
+ASFILES := xptcstubs_asm_pa32.s xptcinvoke_asm_pa32.s
+else
+CPPSRCS := xptcinvoke_ipf32.cpp xptcstubs_ipf32.cpp
+ASFILES := xptcstubs_asm_ipf32.s xptcinvoke_asm_ipf32.s
+endif
+
+# #18875 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+endif
+
+######################################################################
+# M68k
+######################################################################
+#
+# NetBSD/m68k
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter amiga atari hp300 mac68k mvme68k next68k sun3 sun3x x68k,$(OS_TEST)))
+CPPSRCS := xptcinvoke_netbsd_m68k.cpp xptcstubs_netbsd_m68k.cpp
+endif
+endif
+
+#
+# Linux/m68k
+#
+ifeq ($(OS_ARCH),Linux)
+ifeq ($(OS_TEST),m68k)
+CPPSRCS := xptcinvoke_linux_m68k.cpp xptcstubs_linux_m68k.cpp
+endif
+endif
+
+######################################################################
+# MIPS
+######################################################################
+#
+# IRIX/MIPS
+#
+ifeq ($(OS_ARCH),IRIX)
+ifneq ($(basename $(OS_RELEASE)),5)
+CPPSRCS := xptcinvoke_irix.cpp xptcstubs_irix.cpp
+ASFILES := xptcinvoke_asm_irix.s xptcstubs_asm_irix.s
+ifdef GNU_CC
+ASFLAGS += -Wa,-D__GNUC__
+else
+CXXFLAGS := $(shell echo $(CXXFLAGS) | sed 's/-O\(3\|fast\)/-O2/g')
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring mips, $(OS_TEST)))
+CPPSRCS := xptcinvoke_mips.cpp xptcstubs_mips.cpp
+ASFILES := xptcinvoke_asm_mips.s xptcstubs_asm_mips.s
+#xptcstubs_mips.cpp
+# xptcstubs_asm_mips.s
+ifdef GNU_CC
+ASFLAGS += $(INCLUDES) -x assembler-with-cpp -D__GNUC__
+endif
+endif
+endif
+
+######################################################################
+# PowerPC
+######################################################################
+#
+# AIX/PPC
+#
+ifeq ($(OS_ARCH),AIX)
+ifdef HAVE_64BIT_OS
+CPPSRCS := xptcinvoke_ppc_aix64.cpp xptcstubs_ppc_aix64.cpp
+ASFILES := xptcinvoke_asm_ppc_aix64.s xptcstubs_asm_ppc_aix64.s
+else
+ifeq ($(AIX_OBJMODEL),ibm)
+CPPSRCS := xptcinvoke_ppc_aix.cpp xptcstubs_ppc_aix.cpp
+ASFILES := xptcinvoke_asm_ppc_ibmobj_aix.s xptcstubs_asm_ppc_aix.s
+else
+CPPSRCS := xptcinvoke_ppc_aix.cpp xptcstubs_ppc_aix.cpp
+ASFILES := xptcinvoke_asm_ppc_aix.s xptcstubs_asm_ppc_aix.s
+endif
+endif
+
+# #24617 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+
+#
+# Linux/PPC
+#
+ifeq ($(OS_ARCH)$(OS_TEST),Linuxppc)
+CPPSRCS := xptcinvoke_ppc_linux.cpp xptcstubs_ppc_linux.cpp
+ASFILES := xptcinvoke_asm_ppc_linux.s xptcstubs_asm_ppc_linux.s
+AS := $(CC) -c -x assembler-with-cpp
+endif
+
+#
+# NetBSD/PPC
+#
+ifneq (,$(filter NetBSDmacppc NetBSDbebox NetBSDofppc NetBSDprep NetBSDamigappc,$(OS_ARCH)$(OS_TEST)))
+CPPSRCS := xptcinvoke_ppc_netbsd.cpp xptcstubs_ppc_netbsd.cpp
+ASFILES := xptcinvoke_asm_ppc_netbsd.s xptcstubs_asm_ppc_netbsd.s
+endif
+
+#
+# Darwin/PPC
+#
+ifeq ($(OS_ARCH),Darwin)
+ifeq ($(TARGET_CPU), powerpc)
+ASFLAGS += -x assembler-with-cpp # assumes $(AS) == $(CC)
+ifdef HAVE_GCC3_ABI
+ASFLAGS += -DHAVE_GCC3_ABI
+endif
+CPPSRCS := xptcinvoke_ppc_rhapsody.cpp xptcstubs_ppc_rhapsody.cpp
+ASFILES := xptcinvoke_asm_ppc_rhapsody.s xptcstubs_asm_ppc_darwin.s
+endif
+endif
+
+######################################################################
+# SPARC
+######################################################################
+#
+# BSD_OS/SPARC
+#
+ifeq ($(OS_ARCH),BSD_OS)
+ifneq (,$(findstring sparc,$(OS_TEST)))
+CPPSRCS := xptcinvoke_sparc_solaris.cpp xptcstubs_sparc_solaris.cpp
+ASFILES := xptcinvoke_asm_sparc_bsdos.s xptcstubs_asm_sparc_solaris.s
+endif
+endif
+#
+# Linux/SPARC
+#
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring sparc,$(OS_TEST)))
+CPPSRCS := xptcinvoke_sparc_solaris.cpp xptcstubs_sparc_solaris.cpp
+ifdef HAVE_GCC3_ABI
+ASFILES := xptcinvoke_asm_sparc_linux_GCC3.s xptcstubs_asm_sparc_solaris.s
+else
+ASFILES := xptcinvoke_asm_sparc_linux.s xptcstubs_asm_sparc_solaris.s
+endif
+endif
+endif
+#
+# NetBSD/SPARC
+#
+ifeq ($(OS_ARCH)$(OS_TEST),NetBSDsparc)
+CPPSRCS := xptcinvoke_sparc_netbsd.cpp xptcstubs_sparc_netbsd.cpp
+ASFILES := xptcinvoke_asm_sparc_netbsd.s xptcstubs_asm_sparc_netbsd.s
+endif
+#
+# Solaris/SPARC
+#
+ifeq ($(OS_ARCH),SunOS)
+ifneq (86,$(findstring 86,$(OS_TEST)))
+ifdef HAVE_64BIT_OS
+CPPSRCS := xptcinvoke_sparcv9_solaris.cpp xptcstubs_sparcv9_solaris.cpp
+else
+CPPSRCS := xptcinvoke_sparc_solaris.cpp xptcstubs_sparc_solaris.cpp
+endif
+
+ifeq ($(GNU_CC),1)
+ifdef HAVE_GCC3_ABI
+ASFILES := xptcinvoke_asm_sparc_solaris_GCC3.s xptcstubs_asm_sparc_solaris.s
+else
+ASFILES := xptcinvoke_asm_sparc_solaris_GCC.s xptcstubs_asm_sparc_solaris.s
+endif
+else
+ifdef HAVE_64BIT_OS
+ASFILES := xptcinvoke_asm_sparcv9_solaris_SUNW.s xptcstubs_asm_sparcv9_solaris.s
+else
+ASFILES := xptcinvoke_asm_sparc_solaris_SUNW.s xptcstubs_asm_sparc_solaris.s
+endif
+endif
+
+endif
+endif
+
+######################################################################
+# S/390
+######################################################################
+#
+# Linux for S/390
+#
+ifeq ($(OS_ARCH)$(OS_TEST),Linuxs390)
+CPPSRCS := xptcinvoke_linux_s390.cpp xptcstubs_linux_s390.cpp
+endif
+
+ifeq ($(OS_ARCH)$(OS_TEST),Linuxs390x)
+CPPSRCS := xptcinvoke_linux_s390x.cpp xptcstubs_linux_s390x.cpp
+endif
+
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API
+
+INCLUDES += -I$(srcdir)/../..
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring mips, $(OS_TEST)))
+xptcstubs_asm_mips.o: xptcstubs_asm_mips.s.m4 $(PUBLIC)/xptcstubsdef.inc
+ m4 $(INCLUDES) $< > ./xptcstubs_asm_mips.s && \
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_mips.s
+ $(RM) -f ./xptcstubs_asm_mips.s
+endif
+endif
+
+ifeq ($(OS_ARCH),Darwin)
+xptcstubs_asm_ppc_darwin.o: xptcstubs_asm_ppc_darwin.s.m4 $(PUBLIC)/xptcstubsdef.inc Makefile
+ gm4 $(INCLUDES) $< > ./xptcstubs_asm_ppc_darwin.s && \
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_ppc_darwin.s
+ $(RM) -f ./xptcstubs_asm_ppc_darwin.s
+endif
+
+ifeq ($(OS_ARCH),IRIX)
+# The assembler on IRIX (6.3 only?) seems to have trouble with the default command,
+# but works fine if we first copy the header and source file into the current dir.
+xptcstubs_asm_irix.o: $(PUBLIC)/xptcstubsdef.inc $(srcdir)/xptcstubs_asm_irix.s
+ @rm -f ./xptcstubsdef.inc
+ @cp $(PUBLIC)/xptcstubsdef.inc .
+ @if test ! -f ./Makefile.in; then rm -f ./xptcstubs_asm_irix.s; cp $(srcdir)/xptcstubs_asm_irix.s .; else true; fi
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_irix.s
+ @rm -f ./xptcstubsdef.inc
+ @if test ! -f ./Makefile.in; then rm -f ./xptcstubs_asm_irix.s; else true; fi
+endif
+
+ifeq ($(OS_ARCH),OpenVMS)
+# Our assembler wants the include file to be of assembler syntax, not C/C++
+# syntax, so we have to massage it slightly.
+
+xptcstubs_asm_openvms_alpha.o: $(PUBLIC)/xptcstubsdef.inc $(srcdir)/xptcstubs_asm_openvms_alpha.s
+ sed \
+ -e 's/^\(.*_ENTRY\)(\([0-9]*\))/ \1 \2/' \
+ -e 's/\/\*\(.*\)\*\//; \1/' \
+ $(PUBLIC)/xptcstubsdef.inc > ./xptcstubsdef_asm.vms
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(srcdir)/xptcstubs_asm_openvms_alpha.s
+ @rm -f ./xptcstubsdef_asm.vms
+endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp
new file mode 100644
index 00000000..912f50e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp
@@ -0,0 +1,62 @@
+/* this code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */
+
+#include <stdio.h>
+
+// Try to determine the vtable layout generated by G++
+// Produces the offset at which the first vtable entry can be
+// found, and the factor to apply for subsequent entries on stdout.
+// Example output:
+// #define GCC_VTABLE_START 0xc
+// #define GCC_VTABLE_FACTOR 0x8
+
+class test {
+public:
+ virtual int t1(void);
+ virtual int t2(void);
+ int x;
+};
+
+test::test() { this->x = 0x12121212; };
+
+int test::t1(void) { return 1; }
+int test::t2(void) { return 2; }
+
+void die(char *x) {
+ fprintf(stderr, "%s\n", x);
+ exit(1);
+}
+
+int
+main()
+{
+ int i;
+ test *t = new test();
+ int *tp = (int *) t;
+ int off1 = -1;
+ int off2 = -1;
+ int factor;
+ int factorshift;
+
+ if (*tp++ != 0x12121212)
+ die("Integer element test::x not found!");
+ tp = (int *) *tp;
+ for (i = 0; i < 10; i++) {
+ if (tp[i] == (int) t->t1)
+ off1 = i;
+ if (tp[i] == (int) t->t2)
+ off2 = i;
+ }
+ if (off1 == -1 || off2 == -1)
+ die("Could not determine offset into vtable!");
+ factor = (off2 - off1) * 4;
+ factorshift = -1;
+ while (factor) {
+ factorshift++;
+ factor >>= 1;
+ }
+ printf("/* Automatically generated by vtable_layout_x86.cpp */\n");
+ printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4);
+ printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4);
+ printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift);
+ exit(0);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h
new file mode 100644
index 00000000..707352aa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Special include file for xptc*_gcc_x86_unix.cpp */
+
+//
+// this may improve the static function calls, but may not.
+//
+
+// #define MOZ_USE_STDCALL
+
+#ifdef MOZ_USE_STDCALL
+#define ATTRIBUTE_STDCALL __attribute__ ((__stdcall__))
+#else
+#define ATTRIBUTE_STDCALL
+#endif
+
+#ifdef MOZ_NEED_LEADING_UNDERSCORE
+#define SYMBOL_UNDERSCORE "_"
+#else
+#define SYMBOL_UNDERSCORE
+#endif
+
+/*
+ What are those keeper functions?
+
+ The problem: gcc doesn't know that the assembler routines call
+ static functions so gcc may not emit the definition (i.e., the
+ code) for these functions. In gcc 3.1 and up
+ "__attribute__ ((used))" exists and solves the problem.
+ For older gcc versions it's not so easy. One could use the
+ -fkeep-inline-functions but that keeps a surprising number of
+ functions which bloats the compiled library. It seems otherwise
+ harmless, though. Alternatively, one could use
+ -fno-inline-functions which works right now but might cause a
+ slowdown under some circumstances. The problem with these methods
+ is that they do not automatically adapt to the compiler used.
+
+ The best solution seems to be to create dummy functions that
+ reference the appropriate static functions. It's then necessary
+ to "use" these functions in a way that gcc will not optimize
+ away. The keeper functions use assembly code to confuse gcc.
+
+ One drawback is that the keeper functions are externally visible
+ so they shouldn't do anything harmful.
+
+ With the right linker, one could make the keeper functions local
+ so they wouldn't be visible.
+ */
+
+
+// gcc 3.1 and up
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#define ATTRIBUTE_USED __attribute__ ((__used__))
+#else
+#define ATTRIBUTE_USED
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h
new file mode 100644
index 00000000..23eb23ee
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific #defines to be shared by the various platforms sharing
+* the unixish_86 code
+*/
+
+/*
+* The goal here is to clearly define the binary compatibility parameters for
+* the platforms that will use this code. Rather than switch at compile time
+* based on the compiler that happens to be in use we are forcing implementors
+* to make a conscious decision.
+*
+* For some of these platforms the community may choose to have more than one
+* binary model in effect. In that case I suggest that there be explicit sub
+* defines for that platform specifying 'TYPE1', 'TYPE2', etc. The decision on
+* which 'TYPE' to use would be triggered by a setting passed through from the
+* config system.
+*
+* For example we might end up with something like:
+*
+* #elif defined(NTO)
+* # if defined(TYPE1)
+* # define CFRONT_STYLE_THIS_ADJUST
+* # elif defined(TYPE1)
+* # define THUNK_BASED_THIS_ADJUST
+* # else
+* # error "need TYPE1 or TYPE2 for NTO"
+* # endif
+* #elif defined(__BEOS__)
+*
+* and so on....
+*
+*/
+
+#if defined(LINUX)
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)
+/* Old gcc 2.7.x.x. What does gcc 2.8.x do?? */
+#define CFRONT_STYLE_THIS_ADJUST
+#else
+/* egcs and later */
+#define THUNK_BASED_THIS_ADJUST
+#endif
+
+#elif defined(__FreeBSD__)
+/* System versions of gcc on FreeBSD don't use thunks. On 3.x, the system
+ * compiler is gcc 2.7.2.3, which doesn't use thunks by default. On 4.x and
+ * 5.x, /usr/src/contrib/gcc/config/freebsd.h explicitly undef's
+ * DEFAULT_VTABLE_THUNKS. (The one exception is a brief period (September
+ * 1999 - Jan 2000) during 4.0-CURRENT, after egcs was merged --
+ * this was changed before 4.0-RELEASE, but we can handle it anyway.)
+ *
+ * Versions of gcc from the ports collection (/usr/ports/lang/egcs),
+ * however, have DEFAULT_VTABLE_THUNKS #defined to 1, at least
+ * in all ports collections since the 2.95 merge. (Supporting optional
+ * compilers from FreeBSD 3.2 or earlier seems unnecessary).
+ *
+ * The easiest way to distinguish the ports collection gcc from the system
+ * gcc is that the system gcc defines __FreeBSD_cc_version. This variable
+ * can also identify versions that use thunks. This includes some 4.x versions
+ * and now newer 5.x versions.
+ */
+#if defined(__FreeBSD_cc_version) && \
+ (__FreeBSD_cc_version < 500003) && \
+ (__FreeBSD_cc_version < 400002 || __FreeBSD_cc_version > 400003)
+#define CFRONT_STYLE_THIS_ADJUST
+#else
+#define THUNK_BASED_THIS_ADJUST
+#endif
+
+#elif defined(__NetBSD__)
+#define THUNK_BASED_THIS_ADJUST
+
+#elif defined(__OpenBSD__)
+/* OpenBSD instroduces GCC 2.95.x in late May 1999 */
+#include <sys/param.h>
+#if OpenBSD <= 199905
+#define THUNK_BASED_THIS_ADJUST
+#else
+#define CFRONT_STYLE_THIS_ADJUST
+#endif
+
+#elif defined(__bsdi__)
+#include <sys/param.h>
+#if _BSDI_VERSION >= 199910
+/* BSDI/4.1 ships with egcs, ergo thunk-based */
+#define THUNK_BASED_THIS_ADJUST
+#else
+#define CFRONT_STYLE_THIS_ADJUST
+#endif
+
+#elif defined(NTO)
+#define CFRONT_STYLE_THIS_ADJUST
+
+#elif defined(__BEOS__)
+#define CFRONT_STYLE_THIS_ADJUST
+
+#elif defined(__sun__) || defined(__sun)
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+#define THUNK_BASED_THIS_ADJUST
+#else
+#define CFRONT_STYLE_THIS_ADJUST
+#endif
+
+#elif defined(_WIN32)
+#define THUNK_BASED_THIS_ADJUST
+
+#elif defined(__EMX__)
+#define THUNK_BASED_THIS_ADJUST
+
+#elif defined (__APPLE__) && (__MACH__)
+#define THUNK_BASED_THIS_ADJUST
+
+#else
+#error "need a platform define if using unixish x86 code"
+#endif
+
+/***************************************************************************/
+
+#if !defined(THUNK_BASED_THIS_ADJUST) && !defined(CFRONT_STYLE_THIS_ADJUST)
+#error "need to define 'this' adjust scheme"
+#endif
+
+#if defined(THUNK_BASED_THIS_ADJUST) && defined(CFRONT_STYLE_THIS_ADJUST)
+#error "need to define only ONE 'this' adjust scheme"
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp
new file mode 100644
index 00000000..af2919d8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp
@@ -0,0 +1,218 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+// 6 integral parameters are passed in registers
+const PRUint32 GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const PRUint32 FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint32 & nr_gpr, PRUint32 & nr_fpr, PRUint32 & nr_stack)
+{
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(PRUint64 * d, PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint64 * gpregs, double * fpregs)
+{
+ PRUint32 nr_gpr = 1; // skip one GP register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (PRUint64) s->ptr;
+ else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: value = s->val.i8; break;
+ case nsXPTType::T_I16: value = s->val.i16; break;
+ case nsXPTType::T_I32: value = s->val.i32; break;
+ case nsXPTType::T_I64: value = s->val.i64; break;
+ case nsXPTType::T_U8: value = s->val.u8; break;
+ case nsXPTType::T_U16: value = s->val.u16; break;
+ case nsXPTType::T_U32: value = s->val.u32; break;
+ case nsXPTType::T_U64: value = s->val.u64; break;
+ case nsXPTType::T_BOOL: value = s->val.b; break;
+ case nsXPTType::T_CHAR: value = s->val.c; break;
+ case nsXPTType::T_WCHAR: value = s->val.wc; break;
+ default: value = (PRUint64) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports * that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant * params)
+{
+ PRUint32 nr_gpr, nr_fpr, nr_stack;
+ invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+ // Load parameters to stack, if necessary
+ PRUint64 *stack = (PRUint64 *) __builtin_alloca(nr_stack * 8);
+ PRUint64 gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+
+ // disable the warning about sometimes not initialized variables which is hit
+ // when we pass less than 8 XMM or less than 6 GPR registers.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsometimes-uninitialized"
+
+ // Load FPR registers from fpregs[]
+ register double d0 asm("xmm0");
+ register double d1 asm("xmm1");
+ register double d2 asm("xmm2");
+ register double d3 asm("xmm3");
+ register double d4 asm("xmm4");
+ register double d5 asm("xmm5");
+ register double d6 asm("xmm6");
+ register double d7 asm("xmm7");
+
+ switch (nr_fpr) {
+#define ARG_FPR(N) \
+ case N+1: d##N = fpregs[N];
+ ARG_FPR(7);
+ ARG_FPR(6);
+ ARG_FPR(5);
+ ARG_FPR(4);
+ ARG_FPR(3);
+ ARG_FPR(2);
+ ARG_FPR(1);
+ ARG_FPR(0);
+ case 0:;
+#undef ARG_FPR
+ }
+
+ // Load GPR registers from gpregs[]
+ register PRUint64 a0 asm("rdi");
+ register PRUint64 a1 asm("rsi");
+ register PRUint64 a2 asm("rdx");
+ register PRUint64 a3 asm("rcx");
+ register PRUint64 a4 asm("r8");
+ register PRUint64 a5 asm("r9");
+
+ switch (nr_gpr) {
+#define ARG_GPR(N) \
+ case N+1: a##N = gpregs[N];
+ ARG_GPR(5);
+ ARG_GPR(4);
+ ARG_GPR(3);
+ ARG_GPR(2);
+ ARG_GPR(1);
+ case 1: a0 = (PRUint64) that;
+ case 0:;
+#undef ARG_GPR
+ }
+
+ // Ensure that assignments to SSE registers won't be optimized away
+ asm("" ::
+ "x" (d0), "x" (d1), "x" (d2), "x" (d3),
+ "x" (d4), "x" (d5), "x" (d6), "x" (d7));
+
+ // Get pointer to method
+ PRUint64 methodAddress = *((PRUint64 *)that);
+ methodAddress += 8 * methodIndex;
+ methodAddress = *((PRUint64 *)methodAddress);
+
+ typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64);
+ PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5);
+ return result;
+
+#pragma clang diagnostic pop
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm
new file mode 100644
index 00000000..aaeaf84a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm
@@ -0,0 +1,403 @@
+; $Id: xptcinvoke_amd64_vbox.asm $
+;; @file
+; XPCOM - Implementation XPTC_InvokeByIndex in assembly.
+;
+; This solves the problem of Clang and gcc (sometimes) not playing along with
+; the alloca() based trick to pass stack parameters. We first had trouble
+; when enabling asan with gcc 8.2, then Clang 11 on mac had similar issues
+; (at least for profile builds).
+;
+
+;
+; Copyright (C) 2020-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+
+;*********************************************************************************************************************************
+;* Internal Functions *
+;*********************************************************************************************************************************
+%include "iprt/asmdefs.mac"
+
+
+;*********************************************************************************************************************************
+;* Structures and Typedefs *
+;*********************************************************************************************************************************
+struc nsXPTCVariant
+ .val resq 1
+ .ptr resq 1
+ .type resb 1
+ .flags resb 1
+ alignb 8
+endstruc
+
+
+;*********************************************************************************************************************************
+;* Defined Constants And Macros *
+;*********************************************************************************************************************************
+;; @name Selected nsXPTCVariant::flags values.
+;; @{
+%define PTR_IS_DATA 1
+;; @}
+
+;; @name Selected nsXPTType (nsXPTCVariant::type) values.
+;; @{
+%define T_FLOAT 8
+%define T_DOUBLE 9
+;; @}
+
+;; Error code we use if there are too many parameters.
+%define DISP_E_BADPARAMCOUNT 0x8002000e
+
+;; Effect name mangling.
+%ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ %define XPTC_InvokeByIndex VBoxNsxpXPTC_InvokeByIndex
+%endif
+
+
+BEGINCODE
+
+;;
+;
+; @cproto nsresult XPTC_InvokeByIndex(nsISupports *pThat, PRUint32 idxMethod, PRUint32 cParams, nsXPTCVariant *paParams)
+;
+; @param pThat Pointer to the object we're invoking a method on. register:rdi
+; @param idxMethod The VTable method index. register:esi
+; @param cParams Number of parameters in addition to pThat. register:edx
+; @param paParams Array of parameter values and info. register:rcx
+;
+BEGINPROC_EXPORTED XPTC_InvokeByIndex
+ push rbp
+ mov rbp, rsp
+ push rbx
+ push r12
+
+ ;
+ ; Move essential input parameters into non-parameter registers.
+ ;
+ mov rbx, rcx ; rbx = first / current parameter
+ mov r12d, edx ; r12 = parameter count / left
+
+ ; Look up the method address in the vtable and store it in r11 (freeing up rsi).
+ mov r11, [rdi] ; r11 = vtable
+ mov esi, esi ; zero extend vtable index.
+ mov r11, [r11 + rsi * 8] ; r11 = method to call.
+
+%define WITH_OPTIMIZATION
+%ifdef WITH_OPTIMIZATION
+ ;
+ ; If there are 5 or fewer parameters and they are all suitable for GREGs,
+ ; we can try optimize the processing here.
+ ;
+ ; Switch on count, using fall-thought-to-smaller-value logic, default
+ ; case goes to generic (slow) code path.
+ ;
+ dec edx ; we can still use edx for the parameter count here as a throwaway.
+ jz .fast_1
+ dec edx
+ jz .fast_2
+ dec edx
+ jz .fast_3
+ dec edx
+ jz .fast_4
+ dec edx
+ jnz .slow_or_zero
+%macro fast_case 4
+%1:
+ mov eax, [rbx + nsXPTCVariant_size * %3 + nsXPTCVariant.type] ; ASSUMES 'type' and 'flags' are adjacent byte fields.
+ test ah, PTR_IS_DATA
+ mov %4, [rbx + nsXPTCVariant_size * %3 + nsXPTCVariant.ptr]
+ jnz %2
+ sub al, T_FLOAT
+ sub al, 2
+ jl .fast_bailout
+ mov %4, [rbx + nsXPTCVariant_size * %3 + nsXPTCVariant.val]
+%endmacro
+ fast_case .fast_5, .fast_4, 4, r9
+ fast_case .fast_4, .fast_3, 3, r8
+ fast_case .fast_3, .fast_2, 2, rcx
+ fast_case .fast_2, .fast_1, 1, rdx
+ fast_case .fast_1, .fast_0, 0, rsi
+.fast_0:
+ xor eax, eax
+ call r11 ; note! stack is aligned here.
+
+.fast_return:
+ lea rsp, [rbp - 8*2]
+ pop r12
+ pop rbx
+ leave
+ ret
+
+.slow_or_zero:
+ cmp r12d, 0
+ je .fast_0
+ %if 0
+ jmp .slow
+.fast_bailout:
+ int3
+ %else
+.fast_bailout:
+ %endif
+.slow:
+%endif
+ ; One more push.
+ push r13
+
+ ;
+ ; Check that there aren't unreasonably many parameters
+ ; (we could do ~255, but 64 is more reasonable number).
+ ;
+ cmp r12d, 64
+ je .too_many_parameters
+
+ ;
+ ; For simplicity reserve stack space for all parameters and point r10 at it.
+ ;
+ lea edx, [r12d * 8]
+ sub rsp, rdx
+ and rsp, byte 0ffffffffffffffe0h ; 32 byte aligned stack.
+ mov r10, rsp ; r10 = next stack parameter.
+
+ ;
+ ; Set up parameter pointer and register distribution counts.
+ ;
+ mov eax, 1 ; al = greg count, ah = fpreg count.
+
+ ;
+ ; Anything to do here?
+ ;
+%ifndef WITH_OPTIMIZATION
+ test r12d,r12d
+ jz .make_call
+%endif
+ jmp .param_loop
+
+ ;
+ ; The loop.
+ ;
+ ALIGNCODE(64)
+.param_loop_advance:
+ add rbx, nsXPTCVariant_size
+.param_loop:
+ ; First test for pointers using 'flags' then work 'type' for the rest.
+ test byte [rbx + nsXPTCVariant.flags], PTR_IS_DATA
+ jnz .is_ptr
+ cmp byte [rbx + nsXPTCVariant.type], T_FLOAT
+ jge .maybe_in_fpreg
+
+ ;
+ ; nsXPTCVariant.val belongs in a GREG or on the stack.
+ ; Note! Hope we can get away with not zero extending the value here.
+ ;
+.in_greg:
+ inc al
+ cmp al, 1+1
+ je .in_greg_rsi
+ cmp al, 2+1
+ je .in_greg_rdx
+ cmp al, 3+1
+ je .in_greg_rcx
+ cmp al, 4+1
+ je .in_greg_r8
+ cmp al, 5+1
+ ja .on_stack
+.in_greg_r9:
+ mov r9, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_r8:
+ mov r8, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_rcx:
+ mov rcx, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_rdx:
+ mov rdx, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_rsi:
+ mov rsi, [rbx + nsXPTCVariant.val]
+ jmp .next
+
+ ;
+ ; Pointers are loaded from the 'ptr' rather than the 'val' member.
+ ;
+ ALIGNCODE(64)
+.is_ptr:
+ inc al
+ cmp al, 1+1
+ je .ptr_in_greg_rsi
+ cmp al, 2+1
+ je .ptr_in_greg_rdx
+ cmp al, 3+1
+ je .ptr_in_greg_rcx
+ cmp al, 4+1
+ je .ptr_in_greg_r8
+ cmp al, 5+1
+ je .ptr_in_greg_r9
+ mov r13, [rbx + nsXPTCVariant.ptr]
+ jmp .r13_on_stack
+
+.ptr_in_greg_r9:
+ mov r9, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_r8:
+ mov r8, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_rcx:
+ mov rcx, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_rdx:
+ mov rdx, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_rsi:
+ mov rsi, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+
+ ;
+ ; Maybe we've got a float or double type here...
+ ;
+.maybe_in_fpreg:
+ je .float_in_fpreg
+ cmp byte [rbx + nsXPTCVariant.type], T_DOUBLE
+ jne .in_greg
+
+.double_in_fpreg:
+ cmp ah, 8 ; Ensure max AL value of 8 when making call.
+ jge .on_stack
+ inc ah
+ cmp ah, 0+1
+ je .double_in_xmm0
+ cmp ah, 1+1
+ je .double_in_xmm1
+ cmp ah, 2+1
+ je .double_in_xmm2
+ cmp ah, 3+1
+ je .double_in_xmm3
+ cmp ah, 4+1
+ je .double_in_xmm4
+ cmp ah, 5+1
+ je .double_in_xmm5
+ cmp ah, 6+1
+ je .double_in_xmm6
+.double_in_xmm7:
+ movsd xmm7, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm6:
+ movsd xmm6, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm5:
+ movsd xmm5, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm4:
+ movsd xmm4, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm3:
+ movsd xmm3, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm2:
+ movsd xmm2, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm1:
+ movsd xmm1, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm0:
+ movsd xmm0, [rbx + nsXPTCVariant.val]
+ jmp .next
+
+.float_in_fpreg:
+ cmp ah, 8 ; Ensure max AL value of 8 when making call.
+ jge .on_stack
+ inc ah
+ cmp ah, 0+1
+ je .float_in_xmm0
+ cmp ah, 1+1
+ je .float_in_xmm1
+ cmp ah, 2+1
+ je .float_in_xmm2
+ cmp ah, 3+1
+ je .float_in_xmm3
+ cmp ah, 4+1
+ je .float_in_xmm4
+ cmp ah, 5+1
+ je .float_in_xmm5
+ cmp ah, 6+1
+ je .float_in_xmm6
+.float_in_xmm7:
+ movss xmm7, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm6:
+ movss xmm6, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm5:
+ movss xmm5, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm4:
+ movss xmm4, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm3:
+ movss xmm3, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm2:
+ movss xmm2, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm1:
+ movss xmm1, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm0:
+ movss xmm0, [rbx + nsXPTCVariant.val]
+ jmp .next
+
+ ;
+ ; Put the value onto the stack via r13.
+ ;
+ ALIGNCODE(64)
+.on_stack:
+ mov r13, [rbx + nsXPTCVariant.val]
+.r13_on_stack:
+ mov [r10], r13
+ lea r10, [r10 + 8]
+
+ ;
+ ; Update parameter pointer and count and maybe loop again.
+ ;
+.next:
+ dec r12d
+ jnz .param_loop_advance
+
+ ;
+ ; Call the method and return.
+ ;
+.make_call:
+ movzx eax, ah ; AL = number of parameters in XMM registers (variadict only, but easy to do).
+.make_just_call:
+ call r11
+
+.return:
+ lea rsp, [rbp - 8*3]
+ pop r13
+ pop r12
+ pop rbx
+ leave
+ ret
+
+.too_many_parameters:
+ mov eax, DISP_E_BADPARAMCOUNT
+ jmp .return
+ENDPROC XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp
new file mode 100644
index 00000000..1b2c5c67
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(LINUX) || !defined(__arm__)
+#error "This code is for Linux ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent."
+#endif
+
+// Remember that these 'words' are 32bit DWORDS
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint16*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" {
+ struct my_params_struct {
+ nsISupports* that;
+ PRUint32 Index;
+ PRUint32 Count;
+ nsXPTCVariant* params;
+ PRUint32 fn_count;
+ PRUint32 fn_copy;
+ };
+};
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (PRUint32) &invoke_copy_to_stack;
+ my_params.fn_count = (PRUint32) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "mov r2, r2, lsl #2 \n\t" /* a vtable_entry(x)=8 + (4 bytes * x) */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */
+#else /* non G++ V3 ABI */
+ "add r2, r2, #8 \n\t" /* with this compilers */
+ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */
+#endif
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "ldr r0, [%1, #0] \n\t" /* get (self) */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp
new file mode 100644
index 00000000..d8334583
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp
@@ -0,0 +1,296 @@
+/* $Id: xptcinvoke_arm64_vbox.cpp $ */
+/** @file
+ * XPCOM - Implementation XPTC_InvokeByIndex for arm64.
+ */
+
+/*
+ * Copyright (C) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "xptcprivate.h"
+#include <iprt/cdefs.h>
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#define NUM_ARGS_IN_GPRS 8 /**< Number of arguments passed in general purpose registers (starting with x0). */
+#define NUM_ARGS_IN_FPRS 8 /**< Number of arguments passed in floating point registers (starting with d0). */
+
+#define MY_MAX_ARGS 64 /**< Limit ourselves to 64 arguments. */
+
+
+
+AssertCompileMemberOffset(nsXPTCVariant, val, 0);
+
+extern "C" __attribute__((naked)) nsresult
+arm64AsmInvoker(uintptr_t pfnMethod /*x0*/, uint32_t cParams /*w1*/, nsXPTCVariant *paParams /*x2*/, uint64_t cbStack /*x3*/,
+ uint8_t *acbStackArgs /*x4*/, uint64_t *pauGprArgs /*x5*/, uint64_t *pauFprArgs /*x6*/, uint32_t cFprArgs /*x7*/)
+{
+ __asm__ __volatile__(
+ /* Prologue - create the frame. */ "\
+ sub sp, sp, 16 \n\
+ stp x29, x30, [sp] \n\
+ mov x29, sp \n\
+ .cfi_def_cfa x29, 16 \n\
+ .cfi_rel_offset x30, -8 \n\
+ .cfi_rel_offset x29, -16 \n\
+\n\
+" /* Move pfnMethod to x16 and pauGprArgs to x7 free up x0 and x5: */ "\
+ mov x16, x0 \n\
+ mov x17, x5 \n\
+\n\
+" /* Load FPU registers first so we free up x6 & x7 early: */ "\
+ cmp w7, #0 \n\
+ b.eq Lno_fprs\n\
+ ldp d0, d1, [x6] \n\
+ ldp d2, d3, [x6, #16] \n\
+ ldp d4, d5, [x6, #32] \n\
+ ldp d6, d7, [x6, #48] \n\
+Lno_fprs:\n\
+\n\
+" /* Do argument passing by stack (if any). We align the stack to 16 bytes. */ "\
+ cmp x3, #0 \n\
+ beq Lno_stack_args \n\
+ sub x3, sp, x3 \n\
+ bic x3, x3, #15 \n\
+ mov sp, x3 \n\
+Lnext_parameter: \n\
+ ldrb w7, [x4] \n\
+ cmp w7, #0 \n\
+ beq Ladvance\n\
+\n\
+ cmp w7, #4 \n\
+ bgt Lstore_64bits\n\
+ cmp w7, #1 \n\
+ beq Lstore_8bits\n\
+ cmp w7, #2 \n\
+ beq Lstore_16bits\n\
+\n\
+Lstore_32bits:\n\
+ ldr w0, [x2] \n\
+ add x3, x3, #3 \n\
+ bic x3, x3, #3 \n\
+ str w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #4 \n"
+#endif
+" b Ladvance \n\
+\n\
+Lstore_8bits:\n\
+ ldrb w0, [x2] \n\
+ strb w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #1 \n"
+#endif
+" b Ladvance \n\
+\n\
+Lstore_16bits:\n\
+ ldrh w0, [x2] \n\
+ add x3, x3, #1 \n\
+ bic x3, x3, #1 \n\
+ strh w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #2 \n"
+#endif
+" b Ladvance \n\
+\n\
+Lstore_64bits_ptr:\n\
+ ldr x0, [x2, %[offPtrInXPTCVariant]] \n\
+ b Lstore_64bits_common \n\
+Lstore_64bits:\n\
+ tst w7, #0x80 \n\
+ bne Lstore_64bits_ptr \n\
+ ldr x0, [x2] \n\
+Lstore_64bits_common:\n\
+ add x3, x3, #7 \n\
+ bic x3, x3, #7 \n\
+ str x0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #8 \n"
+#endif
+"\n\
+Ladvance:\n"
+#ifndef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #8 \n"
+#endif
+" add x4, x4, #1 \n\
+ add x2, x2, %[cbXPTCVariant] \n\
+ sub w1, w1, #1 \n\
+ cmp w1, #0 \n\
+ bne Lnext_parameter \n\
+\n\
+" /* reserve stack space for the integer and floating point registers and save them: */ "\
+Lno_stack_args: \n\
+\n\
+" /* Load general purpose argument registers: */ "\
+ ldp x0, x1, [x17] \n\
+ ldp x2, x3, [x17, #16] \n\
+ ldp x4, x5, [x17, #32] \n\
+ ldp x6, x7, [x17, #48] \n\
+\n\
+" /* Make the call: */ "\
+ blr x16 \n\
+\n\
+" /* Epilogue (clang does not emit the .cfi's here, so drop them too?): */ "\
+ mov sp, x29 \n\
+ ldp x29, x30, [sp] \n\
+ add sp, sp, #16 \n\
+ .cfi_def_cfa sp, 0 \n\
+ .cfi_restore x29 \n\
+ .cfi_restore x30 \n\
+ ret \n\
+" :
+ : [cbXPTCVariant] "i" (sizeof(nsXPTCVariant))
+ , [offPtrInXPTCVariant] "i" (offsetof(nsXPTCVariant, ptr))
+ :);
+}
+
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports *pThis, PRUint32 idxMethod, PRUint32 cParams, nsXPTCVariant *paParams)
+{
+ AssertMsgReturn(cParams <= MY_MAX_ARGS, ("cParams=%#x idxMethod=%#x\n", cParams, idxMethod), NS_ERROR_UNEXPECTED);
+
+ /*
+ * Prepare
+ */
+ uint64_t auGprArgs[NUM_ARGS_IN_GPRS] = {0};
+ uint64_t auFprArgs[NUM_ARGS_IN_GPRS] = {0};
+ uint8_t acbStackArgs[MY_MAX_ARGS]; /* The number of value bytes to copy onto the stack. Zero if in register. */
+ uint32_t cbStackArgs = 0;
+ uint32_t cFprArgs = 0;
+ uint32_t cGprArgs = 0;
+
+ /* First argument is always 'pThis'. The 'pThis' argument is not accounted
+ for in cParams or acbStackArgs. */
+ auGprArgs[cGprArgs++] = (uintptr_t)pThis;
+
+ /* Do the other arguments. */
+ for (PRUint32 i = 0; i < cParams; i++)
+ {
+ if (paParams[i].IsPtrData())
+ {
+ if (cGprArgs < NUM_ARGS_IN_GPRS)
+ {
+ auGprArgs[cGprArgs++] = (uintptr_t)paParams[i].ptr;
+ acbStackArgs[i] = 0;
+ }
+ else
+ {
+ acbStackArgs[i] = sizeof(paParams[i].ptr) | UINT8_C(0x80);
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ cbStackArgs = RT_ALIGN_32(cbStackArgs, sizeof(paParams[i].ptr)) + sizeof(paParams[i].ptr);
+#else
+ cbStackArgs += sizeof(uint64_t);
+#endif
+ }
+ }
+ else
+ {
+ if ( paParams[i].type != nsXPTType::T_FLOAT
+ && paParams[i].type != nsXPTType::T_DOUBLE)
+ {
+ if (cGprArgs < NUM_ARGS_IN_GPRS)
+ {
+ switch (paParams[i].type)
+ {
+ case nsXPTType::T_I8: auGprArgs[cGprArgs++] = paParams[i].val.i8; break;
+ case nsXPTType::T_I16: auGprArgs[cGprArgs++] = paParams[i].val.i16; break;
+ case nsXPTType::T_I32: auGprArgs[cGprArgs++] = paParams[i].val.i32; break;
+ case nsXPTType::T_I64: auGprArgs[cGprArgs++] = paParams[i].val.i64; break;
+ case nsXPTType::T_U8: auGprArgs[cGprArgs++] = paParams[i].val.u8; break;
+ case nsXPTType::T_U16: auGprArgs[cGprArgs++] = paParams[i].val.u16; break;
+ case nsXPTType::T_U32: auGprArgs[cGprArgs++] = paParams[i].val.u32; break;
+ default:
+ case nsXPTType::T_U64: auGprArgs[cGprArgs++] = paParams[i].val.u64; break;
+ case nsXPTType::T_BOOL: auGprArgs[cGprArgs++] = paParams[i].val.b; break;
+ case nsXPTType::T_CHAR: auGprArgs[cGprArgs++] = paParams[i].val.c; break;
+ case nsXPTType::T_WCHAR: auGprArgs[cGprArgs++] = paParams[i].val.wc; break;
+ }
+ acbStackArgs[i] = 0;
+ }
+ else
+ {
+ uint8_t cbStack;
+ switch (paParams[i].type)
+ {
+ case nsXPTType::T_I8: cbStack = sizeof(paParams[i].val.i8); break;
+ case nsXPTType::T_I16: cbStack = sizeof(paParams[i].val.i16); break;
+ case nsXPTType::T_I32: cbStack = sizeof(paParams[i].val.i32); break;
+ case nsXPTType::T_I64: cbStack = sizeof(paParams[i].val.i64); break;
+ case nsXPTType::T_U8: cbStack = sizeof(paParams[i].val.u8); break;
+ case nsXPTType::T_U16: cbStack = sizeof(paParams[i].val.u16); break;
+ case nsXPTType::T_U32: cbStack = sizeof(paParams[i].val.u32); break;
+ default:
+ case nsXPTType::T_U64: cbStack = sizeof(paParams[i].val.u64); break;
+ case nsXPTType::T_BOOL: cbStack = sizeof(paParams[i].val.b); break;
+ case nsXPTType::T_CHAR: cbStack = sizeof(paParams[i].val.c); break;
+ case nsXPTType::T_WCHAR: cbStack = sizeof(paParams[i].val.wc); break;
+ }
+ acbStackArgs[i] = cbStack;
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ cbStackArgs = RT_ALIGN_32(cbStackArgs, cbStack) + cbStack;
+#else
+ cbStackArgs += sizeof(uint64_t);
+#endif
+ }
+ }
+ else if (cFprArgs < NUM_ARGS_IN_FPRS)
+ {
+ AssertCompile(sizeof(paParams[i].val.f) == 4);
+ AssertCompile(sizeof(paParams[i].val.d) == 8);
+ if (paParams[i].type == nsXPTType::T_FLOAT)
+ auFprArgs[cFprArgs++] = paParams[i].val.u32;
+ else
+ auFprArgs[cFprArgs++] = paParams[i].val.u64;
+ acbStackArgs[i] = 0;
+ }
+ else
+ {
+ uint8_t cbStack;
+ if (paParams[i].type == nsXPTType::T_FLOAT)
+ cbStack = sizeof(paParams[i].val.f);
+ else
+ cbStack = sizeof(paParams[i].val.d);
+ acbStackArgs[i] = cbStack;
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ cbStackArgs = RT_ALIGN_32(cbStackArgs, cbStack) + cbStack;
+#else
+ cbStackArgs += sizeof(uint64_t);
+#endif
+ }
+ }
+ }
+
+ /*
+ * Pass it on to a naked wrapper function that does the nitty gritty work.
+ */
+ uintptr_t *pauVtable = *(uintptr_t **)pThis;
+ return arm64AsmInvoker(pauVtable[idxMethod], cParams, paParams, cbStackArgs, acbStackArgs, auGprArgs, auFprArgs, cFprArgs);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp
new file mode 100644
index 00000000..0213bd76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp
@@ -0,0 +1,213 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint16*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C"
+struct my_params_struct {
+ nsISupports* that;
+ PRUint32 Index;
+ PRUint32 Count;
+ nsXPTCVariant* params;
+ PRUint32 fn_count;
+ PRUint32 fn_copy;
+};
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (PRUint32) &invoke_copy_to_stack;
+ my_params.fn_count = (PRUint32) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */
+ "add r2, r2, #8 \n\t" /* with this compilers */
+ "ldr r3, [r2] \n\t" /* get virtual offset from vtable */
+ "mov r3, r3, lsl #16 \n\t"
+ "add r0, r0, r3, asr #16\n\t"
+ "ldr ip, [r2, #4] \n\t" /* get method address from vtable */
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
new file mode 100644
index 00000000..c846b1f4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
@@ -0,0 +1,145 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi32
+// big endian
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'XPTC_InvokeByIndex'
+ .proc XPTC_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" PRUint32
+// invoke_copy_to_stack(uint64_t* d,
+// const PRUint32 paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass XPTC_InvokeByIndex, @fullyvisible
+ .type XPTC_InvokeByIndex,@function
+
+// XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+// PRUint32 paramCount, nsXPTCVariant* params);
+XPTC_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ addp4 r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 32 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld4 r8 = [r8] ;; // M
+ addp4 r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ addp4 r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
new file mode 100644
index 00000000..5e1b1a23
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
@@ -0,0 +1,145 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi64
+// little endian
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'XPTC_InvokeByIndex'
+ .proc XPTC_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" PRUint32
+// invoke_copy_to_stack(uint64_t* d,
+// const PRUint32 paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass XPTC_InvokeByIndex, @fullyvisible
+ .type XPTC_InvokeByIndex,@function
+
+// XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+// PRUint32 paramCount, nsXPTCVariant* params);
+XPTC_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ add r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 64 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld8 r8 = [r8] ;; // M
+ add r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ add r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s
new file mode 100644
index 00000000..4e8e0895
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s
@@ -0,0 +1,149 @@
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+RAOFF=FRAMESZ-(1*SZREG)
+A0OFF=FRAMESZ-(2*SZREG)
+A1OFF=FRAMESZ-(3*SZREG)
+A2OFF=FRAMESZ-(4*SZREG)
+A3OFF=FRAMESZ-(5*SZREG)
+S0OFF=FRAMESZ-(6*SZREG)
+GPOFF=FRAMESZ-(7*SZREG)
+
+ #
+ # _XPTC_InvokeByIndex(that, methodIndex, paramCount, params)
+ # a0 a1 a2 a3
+
+NESTED(_XPTC_InvokeByIndex, FRAMESZ, ra)
+ SETUP_GP
+ PTR_SUBU sp, FRAMESZ
+ SETUP_GP64(GPOFF, _XPTC_InvokeByIndex)
+ SAVE_GP(GPOFF)
+
+ REG_S ra, RAOFF(sp)
+ REG_S a0, A0OFF(sp)
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S s0, S0OFF(sp)
+ REG_S gp, GPOFF(sp)
+
+ # invoke_count_words(paramCount, params)
+ move a0, a2
+ move a1, a3
+ jal invoke_count_words
+
+ # invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+ # nsXPTCVariant* s, PRUint32 *reg)
+
+ REG_L a1, A2OFF(sp) # a1 - paramCount
+ REG_L a2, A3OFF(sp) # a2 - params
+
+ # save sp before we copy the params to the stack
+ move t0, sp
+
+ # assume full size of 8 bytes per param to be safe
+ sll v0, 4 # 8 bytes * num params
+ subu sp, sp, v0 # make room
+ move a0, sp # a0 - param stack address
+
+ # create temporary stack space to write int and fp regs
+ subu sp, 64 # 64 = 8 regs of 8 bytes
+
+ move a3, sp
+
+ # save the old sp and save the arg stack
+ subu sp, sp, 16
+ REG_S t0, 0(sp)
+ REG_S a0, 8(sp)
+
+ # copy the param into the stack areas
+ jal invoke_copy_to_stack
+
+ REG_L t3, 8(sp) # get previous a0
+ REG_L sp, 0(sp) # get orig sp back
+
+ REG_L a0, A0OFF(sp) # a0 - that
+ REG_L a1, A1OFF(sp) # a1 - methodIndex
+
+#ifdef __GNUC__
+ # t1 = methodIndex * 8
+ # (use shift instead of mult)
+ sll t1, a1, 3
+#else
+ # t1 = methodIndex * 12
+ # (use shift and subtract trick instead of mult)
+ sll t1, a1, 2
+ subu t1, t1, a1
+ sll t1, t1, 2
+#endif
+
+ # calculate the function we need to jump to,
+ # which must then be saved in t9
+ lw t9, 0(a0)
+ addu t9, t9, t1
+#ifdef __GNUC__
+ lw t9, 12(t9) # t9 = *(that+t1+12)
+#else
+ li t2, 20
+ addu t9, t9, t2
+ lw t9, 0(t9) # t9 = *(that+t1+20)
+#endif
+
+ # calculate the proper "this" pointer for the
+ # function that they asked for
+ lw t0, 0(a0)
+ addu t0, t1
+#ifdef __GNUC__
+ lh t0, 8(t0)
+#else
+ lw t0, 12(t0)
+#endif
+
+ addu a0, a0, t0
+
+ # get register save area from invoke_copy_to_stack
+ subu t1, t3, 64
+
+ # a1..a7 and f13..f19 should now be set to what
+ # invoke_copy_to_stack told us. skip a0 and f12
+ # because that's the "this" pointer
+
+ REG_L a1, 0(t1)
+ REG_L a2, 8(t1)
+ REG_L a3, 16(t1)
+ REG_L a4, 24(t1)
+ REG_L a5, 32(t1)
+ REG_L a6, 40(t1)
+ REG_L a7, 48(t1)
+
+ l.d $f13, 0(t1)
+ l.d $f14, 8(t1)
+ l.d $f15, 16(t1)
+ l.d $f16, 24(t1)
+ l.d $f17, 32(t1)
+ l.d $f18, 40(t1)
+ l.d $f19, 48(t1)
+
+ # save away our stack pointer and create
+ # the stack pointer for the function
+ move s0, sp
+ move sp, t3
+
+ jalr ra, t9
+
+ move sp, s0
+
+ RESTORE_GP64
+ REG_L ra, RAOFF(sp)
+ REG_L s0, S0OFF(sp)
+ PTR_ADDU sp, FRAMESZ
+ j ra
+.end _XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
new file mode 100644
index 00000000..f011aaf5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
@@ -0,0 +1,166 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ * Stuart Parmenter <pavlov@netscape.com>
+ */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+# We need a variable number of words allocated from the stack for copies of
+# the params, and this space must come between the high frame (where ra, gp,
+# and s0 are saved) and the low frame (where a0-a3 are saved by the callee
+# functions we invoke).
+
+LOCALSZ=4 # s0, s1, ra, gp
+NARGSAVE=4 # a0, a1, a2, a3
+HIFRAMESZ=(LOCALSZ*SZREG)
+LOFRAMESZ=(NARGSAVE*SZREG)
+FRAMESZ=(HIFRAMESZ+LOFRAMESZ+ALSZ)&ALMASK
+
+# XXX these 2*SZREG, etc. are very magic -- we *know* that ALSZ&ALMASK cause
+# FRAMESZ to be 0 mod 8, in this case to be 16 and not 12.
+RAOFF=FRAMESZ - (2*SZREG)
+GPOFF=FRAMESZ - (3*SZREG)
+S0OFF=FRAMESZ - (4*SZREG)
+S1OFF=FRAMESZ - (5*SZREG)
+
+# These are not magic -- they are just our argsave slots in the caller frame.
+A0OFF=FRAMESZ
+A1OFF=FRAMESZ + (1*SZREG)
+A2OFF=FRAMESZ + (2*SZREG)
+A3OFF=FRAMESZ + (3*SZREG)
+
+ #
+ # _XPTC_InvokeByIndex(that, methodIndex, paramCount, params)
+ # a0 a1 a2 a3
+
+NESTED(_XPTC_InvokeByIndex, FRAMESZ, ra)
+
+ .set noreorder
+ .cpload t9
+ .set reorder
+
+ subu sp, FRAMESZ
+
+ # specify the save register mask -- XXX do we want the a0-a3 here, given
+ # our "split" frame where the args are saved below a dynamicly allocated
+ # region under the high frame?
+ #
+ # 10010000000000010000000011110000
+ .mask 0x900100F0, -((NARGSAVE+LOCALSZ)*SZREG)
+
+ # thou shalt not use .cprestore if yer frame has variable size...
+ # .cprestore GPOFF
+
+ REG_S ra, RAOFF(sp)
+
+ # this happens automatically with .cprestore, but we cannot use that op...
+ REG_S gp, GPOFF(sp)
+ REG_S s0, S0OFF(sp)
+ REG_S s1, S1OFF(sp)
+
+ REG_S a0, A0OFF(sp)
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+
+ # invoke_count_words(paramCount, params)
+ move a0, a2
+ move a1, a3
+
+ jal invoke_count_words
+ lw gp, GPOFF(sp)
+
+ # save the old sp so we can pop the param area and any "low frame"
+ # needed as an argsave area below the param block for callees that
+ # we invoke.
+ move s0, sp
+
+ REG_L a1, A2OFF(sp) # a1 = paramCount
+ REG_L a2, A3OFF(sp) # a2 = params
+
+ # we define a word as 4 bytes, period end of story!
+ sll v0, 2 # 4 bytes * result of invoke_copy_words
+ subu v0, LOFRAMESZ # but we take back the argsave area built into
+ # our stack frame -- SWEET!
+ subu sp, sp, v0 # make room
+ move a0, sp # a0 = param stack address
+ move s1, a0 # save it for later -- it should be safe here
+
+ # the old sp is still saved in s0, but we now need another argsave
+ # area ("low frame") for the invoke_copy_to_stack call.
+ subu sp, sp, LOFRAMESZ
+
+ # copy the param into the stack areas
+ # invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+ # nsXPTCVariant* s)
+ jal invoke_copy_to_stack
+ lw gp, GPOFF(s0)
+
+ move sp, s0 # get orig sp back, popping params and argsave
+
+ REG_L a0, A0OFF(sp) # a0 = set "that" to be "this"
+ REG_L a1, A1OFF(sp) # a1 = methodIndex
+
+ # t1 = methodIndex * 4
+ # (use shift instead of mult)
+ sll t1, a1, 2
+
+ # calculate the function we need to jump to,
+ # which must then be saved in t9
+ lw t9, 0(a0)
+ addu t9, t9, t1
+ lw t9, 8(t9)
+
+ # a1..a3 and f13..f14 should now be set to what
+ # invoke_copy_to_stack told us. skip a0 and f12
+ # because that is the "this" pointer
+
+ REG_L a1, 1*SZREG(s1)
+ REG_L a2, 2*SZREG(s1)
+ REG_L a3, 3*SZREG(s1)
+
+ l.d $f13, 8(s1)
+ l.d $f14, 16(s1)
+
+ # Create the stack pointer for the function, which must have 4 words
+ # of space for callee-saved args. invoke_count_words allocated space
+ # for a0 starting at s1, so we just move s1 into sp.
+ move sp, s1
+
+ jalr ra, t9
+ lw gp, GPOFF(s0)
+
+ move sp, s0
+
+ REG_L ra, RAOFF(sp)
+ REG_L s0, S0OFF(sp)
+ addu sp, FRAMESZ
+ j ra
+.end _XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s
new file mode 100644
index 00000000..d37a91d2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s
@@ -0,0 +1,99 @@
+;* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+;*
+;* The contents of this file are subject to the Netscape 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/NPL/
+;*
+;* Software distributed under the License is distributed on an "AS
+;* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+;* implied. See the License for the specific language governing
+;* rights and limitations under the License.
+;*
+;* The Original Code is mozilla.org code.
+;*
+;* The Initial Developer of the Original Code is Netscape
+;* Communications Corporation. Portions created by Netscape are
+;* Copyright (C) 1998 Netscape Communications Corporation. All
+;* Rights Reserved.
+;*
+;* Contributor(s):
+;*/
+
+;
+; XPTC_PUBLIC_API(nsresult)
+; XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+; PRUint32 paramCount, nsXPTCVariant* params)
+;
+
+ .title "INVOKE" "Invoke By Index"
+
+ $routine XPTC_InvokeByIndex, kind=stack, saved_regs=<R2,R3,R4>
+
+ mov r27,r2 ; Need to set up a base register...
+ .base r2,$LS ; ...for the LINKAGE_PAIR call
+
+ mov r17,r3 ; save methodIndex in r3
+ mov r18,r4 ; save paramCount in r4
+
+;
+; Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+; parameters. (+1 for "this" pointer) Room for at least 6 parameters
+; is required for storage of those passed via registers.
+;
+
+ cmplt R18,5,R1 ; paramCount = MAX(5, "paramCount")
+ cmovne R1,5,R18
+ s8addq R18,16,R1 ; room for "paramCount"+1 params (8 bytes each)
+ bic R1,15,R1 ; stack space is rounded up to 0 % 16
+ subq SP,R1,SP
+
+ stq R16,0(SP) ; save "that" (as "this" pointer)
+ addq SP,8,R16 ; pass stack pointer
+ mov R4,R17 ; pass original "paramCount
+ mov R19,R18 ; pass "params"
+ mov 4,r25 ; argument count
+
+ $LINKAGE_PAIR invoke_copy_to_stack
+ ldq r26,$LP ; get entry point address from linkage pair
+ ldq r27,$LP+8 ; get procedure descriptor address from lp
+ jsr r26,r26 ; and call the routine
+
+;
+; Copy the first 6 parameters to registers and remove from stack frame.
+; Both the integer and floating point registers are set for each parameter
+; except the first which is the "this" pointer. (integer only)
+; The floating point registers are all set as doubles since the
+; invoke_copy_to_stack function should have converted the floats.
+;
+ ldq R16,0(SP) ; integer registers
+ ldq R17,8(SP)
+ ldq R18,16(SP)
+ ldq R19,24(SP)
+ ldq R20,32(SP)
+ ldq R21,40(SP)
+ ldt F17,8(SP) ; floating point registers
+ ldt F18,16(SP)
+ ldt F19,24(SP)
+ ldt F20,32(SP)
+ ldt F21,40(SP)
+
+ addq SP,48,SP ; remove params from stack
+
+;
+; Call the virtual function with the constructed stack frame.
+; First three methods are always QueryInterface, AddRef and Release.
+;
+ addq r4,1,r25 ; argument count now includes "this"
+ mov R16,R1 ; load "this"
+ ldl R1,0(R1) ; load vtable
+ s4addq r3,0,r28 ; vtable index = "methodIndex" * 4
+ addq r1,r28,r1
+ ldl r27,0(r1) ; load procedure value
+ ldq r26,8(r27) ; load entry point address
+ jsr r26,r26 ; call virtual function
+
+ $return
+
+ $end_routine XPTC_InvokeByIndex
+ .end
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s
new file mode 100644
index 00000000..ad7b2f82
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s
@@ -0,0 +1,83 @@
+/*
+ * XPTC_PUBLIC_API(nsresult)
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params)
+ */
+.text
+.align 4
+.globl XPTC_InvokeByIndex
+.ent XPTC_InvokeByIndex
+XPTC_InvokeByIndex:
+.frame $15,32,$26,0
+.mask 0x4008000,-32
+ldgp $29,0($27)
+XPTC_InvokeByIndexXv:
+subq $30,32,$30
+stq $26,0($30)
+stq $15,8($30)
+bis $30,$30,$15
+.prologue 1
+
+/*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+bis $31,5,$2 /* count = MAX(5, "paramCount") */
+cmplt $2,$18,$1
+cmovne $1,$18,$2
+s8addq $2,16,$1 /* room for count+1 params (8 bytes each) */
+bic $1,15,$1 /* stack space is rounded up to 0 % 16 */
+subq $30,$1,$30
+
+stq $16,0($30) /* save "that" (as "this" pointer) */
+stq $17,16($15) /* save "methodIndex" */
+
+addq $30,8,$16 /* pass stack pointer */
+bis $18,$18,$17 /* pass "paramCount" */
+bis $19,$19,$18 /* pass "params" */
+jsr $26,invoke_copy_to_stack /* call invoke_copy_to_stack */
+ldgp $29,0($26)
+
+/*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ldq $16,0($30) /* integer registers */
+ldq $17,8($30)
+ldq $18,16($30)
+ldq $19,24($30)
+ldq $20,32($30)
+ldq $21,40($30)
+ldt $f17,8($30) /* floating point registers */
+ldt $f18,16($30)
+ldt $f19,24($30)
+ldt $f20,32($30)
+ldt $f21,40($30)
+
+addq $30,48,$30 /* remove params from stack */
+
+/*
+ * Call the virtual function with the constructed stack frame.
+ */
+bis $16,$16,$1 /* load "this" */
+ldq $2,16($15) /* load "methodIndex" */
+ldq $1,0($1) /* load vtable */
+s8addq $2,0,$2 /* vtable index = "methodIndex" * 8 + 16 */
+addq $1,$2,$1
+ldq $27,0($1) /* load address of function */
+jsr $26,($27),0 /* call virtual function */
+ldgp $29,0($26)
+
+bis $15,$15,$30
+ldq $26,0($30)
+ldq $15,8($30)
+addq $30,32,$30
+ret $31,($26),1
+.end XPTC_InvokeByIndex
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s
new file mode 100644
index 00000000..8ce8f17f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s
@@ -0,0 +1,131 @@
+ .LEVEL 1.1
+framesz .EQU 128
+
+; XPTC_InvokeByIndex(nsISuppots* that, PRUint32 methodIndex,
+; PRUint32 paramCount, nsXPTCVariant* params);
+
+; g++ need to compile everything with -fvtable-thunks !
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+XPTC_InvokeByIndex
+ .PROC
+ .CALLINFO CALLER,FRAME=72,ENTRY_GR=%r3,SAVE_RP,SAVE_SP,ARGS_SAVED,ALLOCA_FRAME
+
+ ; frame marker takes 48 bytes,
+ ; register spill area takes 8 bytes,
+ ; local stack area takes 72 bytes result in 128 bytes total
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ STW,MA %r3,128(%sp)
+
+ LDO -framesz(%r30),%r28
+ STW %r28,-4(%r30) ; save previous sp
+ STW %r19,-32(%r30)
+
+ STW %r26,-36-framesz(%r30) ; save argument registers in
+ STW %r25,-40-framesz(%r30) ; in PREVIOUS frame
+ STW %r24,-44-framesz(%r30) ;
+ STW %r23,-48-framesz(%r30) ;
+
+ B,L .+8,%r2
+ ADDIL L'invoke_count_bytes-$PIC_pcrel$1+4,%r2,%r1
+ LDO R'invoke_count_bytes-$PIC_pcrel$2+8(%r1),%r1
+$PIC_pcrel$1
+ LDSID (%r1),%r31
+$PIC_pcrel$2
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ CMPIB,>= 0,%r28, .+76
+ COPY %r30,%r3 ; copy stack ptr to saved stack ptr
+ ADD %r30,%r28,%r30 ; extend stack frame
+ LDW -4(%r3),%r28 ; move frame
+ STW %r28,-4(%r30)
+ LDW -8(%r3),%r28
+ STW %r28,-8(%r30)
+ LDW -12(%r3),%r28
+ STW %r28,-12(%r30)
+ LDW -16(%r3),%r28
+ STW %r28,-16(%r30)
+ LDW -20(%r3),%r28
+ STW %r28,-20(%r30)
+ LDW -24(%r3),%r28
+ STW %r28,-24(%r30)
+ LDW -28(%r3),%r28
+ STW %r28,-28(%r30)
+ LDW -32(%r3),%r28
+ STW %r28,-32(%r30)
+
+ LDO -40(%r30),%r26 ; load copy address
+ LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments
+ LDW -48-framesz(%r3),%r24 ;
+
+ LDW -32(%r30),%r19 ; shared lib call destroys r19; reload
+ B,L .+8,%r2
+ ADDIL L'invoke_copy_to_stack-$PIC_pcrel$3+4,%r2,%r1
+ LDO R'invoke_copy_to_stack-$PIC_pcrel$4+8(%r1),%r1
+$PIC_pcrel$3
+ LDSID (%r1),%r31
+$PIC_pcrel$4
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDO -48(%r30),%r20
+ EXTRW,U,= %r28,31,1,%r22
+ FLDD 0(%r20),%fr7 ; load double arg 1
+ EXTRW,U,= %r28,30,1,%r22
+ FLDW 8(%r20),%fr5L ; load float arg 1
+ EXTRW,U,= %r28,29,1,%r22
+ FLDW 4(%r20),%fr6L ; load float arg 2
+ EXTRW,U,= %r28,28,1,%r22
+ FLDW 0(%r20),%fr7L ; load float arg 3
+
+ LDW -36-framesz(%r3),%r26 ; load ptr to 'that'
+ LDW -40(%r30),%r25 ; load the rest of dispatch argument registers
+ LDW -44(%r30),%r24
+ LDW -48(%r30),%r23
+
+ LDW -36-framesz(%r3),%r20 ; load vtable addr
+ LDW -40-framesz(%r3),%r28 ; load index
+ LDW 0(%r20),%r20 ; follow vtable
+ LDO 16(%r20),%r20 ; offset vtable by 16 bytes (g++: 8, aCC: 16)
+ SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry
+ LDW 0(%r28),%r22 ; load vtable entry
+
+ B,L .+8,%r2
+ ADDIL L'$$dyncall_external-$PIC_pcrel$5+4,%r2,%r1
+ LDO R'$$dyncall_external-$PIC_pcrel$6+8(%r1),%r1
+$PIC_pcrel$5
+ LDSID (%r1),%r31
+$PIC_pcrel$6
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=22-26;out=28;
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+ COPY %r3,%r30 ; restore saved stack ptr
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDW,MB -128(%sp),%r3
+
+ .PROCEND ;in=23,24,25,26;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT $$dyncall_external,MILLICODE
+ .IMPORT invoke_count_bytes,CODE
+ .IMPORT invoke_copy_to_stack,CODE
+ .EXPORT XPTC_InvokeByIndex,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
new file mode 100644
index 00000000..3684d154
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
@@ -0,0 +1,146 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is mozilla.org code.
+ #
+ # The Initial Developer of the Original Code is Netscape
+ # Communications Corporation. Portions created by Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ # IBM Corporation
+ #
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.XPTC_InvokeByIndex{TC},"XPTC_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .XPTC_InvokeByIndex
+ .globl XPTC_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,3 # methodIndex * 8
+ addi r5,r5,8 # step over junk at start of vTable !
+ lwzx r11,r5,r4 # get function pointer
+
+ addi r5,r5,4 # We need to manually adjust the 'that' pointer, this is CFRONT based
+ lwzx r5,r4,r5 # offset = r4(vtable) + r5(methodIndex offset) - 4
+ add r3,r5,r3 # adjust 'that' r3 = r3 + r5
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.XPTC_InvokeByIndex:
+ .tc H.18.XPTC_InvokeByIndex{TC},XPTC_InvokeByIndex{DS}
+
+ .csect XPTC_InvokeByIndex{DS}
+ .long .XPTC_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect XPTC_InvokeByIndex{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
new file mode 100644
index 00000000..a174e424
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
@@ -0,0 +1,161 @@
+# ***** BEGIN LICENSE BLOCK *****
+#
+# Version: MPL 1.1/LGPL 2.1/GPL 2.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 mozilla.org code.
+#
+# The Initial Developer of the Original Code is IBM Corporation.
+# Portions created by IBM are
+# Copyright (C) 2002, International Business Machines Corporation.
+# All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the LGPL or the GPL. 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 *****
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.XPTC_InvokeByIndex{TC},"XPTC_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .XPTC_InvokeByIndex
+ .globl XPTC_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.XPTC_InvokeByIndex:
+ mflr r0
+ std r31,-8(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ std r3,48(sp) # that
+ std r4,56(sp) # methodIndex
+ std r5,64(sp) # paramCount
+ std r6,72(sp) # params
+ std r0,16(sp)
+ stdu sp,-168(sp) # 2*24=48 for linkage area,
+ # 8*13=104 for fprData area
+ # 16 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ ld r4,232(sp) # paramCount (168+8+56)
+ ld r5,240(sp) # params
+ mr r6,sp # fprData
+ sldi r3,r4,3 # number of bytes of stack required
+ # is at most numParams*8
+ addi r3,r3,56 # linkage area (48) + this (8)
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,56 # parameter pointer excludes linkage area
+ # size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ ld r3,216(r31) # that (168+48)
+ ld r4,0(r3) # get vTable from 'that'
+ ld r5,224(r31) # methodIndex (168+56)
+ sldi r5,r5,3 # methodIndex * 8
+ # No junk at the start of 64bit vtable !!!
+ ldx r11,r5,r4 # get function pointer (this jumps
+ # either to the function if no adjustment
+ # is needed (displacement = 0), or it
+ # jumps to the thunk code, which will jump
+ # to the function at the end)
+
+ # No adjustment of the that pointer in 64bit mode, this is done
+ # by the thunk code
+
+ ld r4,56(sp)
+ ld r5,64(sp)
+ ld r6,72(sp)
+ ld r7,80(sp)
+ ld r8,88(sp)
+ ld r9,96(sp)
+ ld r10,104(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ ld r0,184(sp) # 168+16
+ addi sp,sp,168
+ mtlr r0
+ ld r31,-8(sp)
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.XPTC_InvokeByIndex:
+ .tc H.18.XPTC_InvokeByIndex{TC},XPTC_InvokeByIndex{DS}
+
+ .csect XPTC_InvokeByIndex{DS}
+ .llong .XPTC_InvokeByIndex # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect XPTC_InvokeByIndex{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
new file mode 100644
index 00000000..064a73ab
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
@@ -0,0 +1,140 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is mozilla.org code.
+ #
+ # The Initial Developer of the Original Code is IBM Corporation.
+ # Portions created by IBM are
+ # Copyright (C) 2004, International Business Machines Corporation.
+ # All Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.XPTC_InvokeByIndex{TC},"XPTC_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .XPTC_InvokeByIndex
+ .globl XPTC_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,2 # methodIndex * 4
+ lwzx r11,r5,r4 # get function pointer
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.XPTC_InvokeByIndex:
+ .tc H.18.XPTC_InvokeByIndex{TC},XPTC_InvokeByIndex{DS}
+
+ .csect XPTC_InvokeByIndex{DS}
+ .long .XPTC_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect XPTC_InvokeByIndex{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
new file mode 100644
index 00000000..b9aaa997
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
@@ -0,0 +1,113 @@
+// -*- Mode: Asm -*-
+//
+// The contents of this file are subject to the Netscape 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/NPL/
+//
+// Software distributed under the License is distributed on an "AS
+// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// rights and limitations under the License.
+//
+// The Original Code is mozilla.org code.
+//
+// The Initial Developer of the Original Code is Netscape
+// Communications Corporation. Portions created by Netscape are
+// Copyright (C) 1999 Netscape Communications Corporation. All
+// Rights Reserved.
+//
+// Contributor(s):
+// Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+// beard@netscape.com (Patrick Beard)
+// waterson@netscape.com (Chris Waterson)
+//
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex,@function
+
+//
+// XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+// PRUint32 paramCount, nsXPTCVariant* params)
+//
+
+XPTC_InvokeByIndex:
+ stwu sp,-32(sp) // setup standard stack frame
+ mflr r0 // save LR
+ stw r3,8(sp) // r3 <= that
+ stw r4,12(sp) // r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) // store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) // r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 // reserve stack space and save SP backchain
+
+ addi r3,sp,8 // r3 <= args
+ mr r4,r5 // r4 <= paramCount
+ mr r5,r6 // r5 <= params
+ add r6,r3,r10 // r6 <= gpregs ( == args + r10 )
+ mr r30,r6 // store in r30 for use later...
+ addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) // load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) // r3 <= that
+ lwz r4,12(r31) // r4 <= methodIndex
+ lwz r5,0(r3) // r5 <= vtable ( == *that )
+#if !((__GNUC__ == 3 && __GNUC_MINOR__ < 2) || __GXX_ABI_VERSION >= 100) // G++ pre-V3 ABI
+ addi r4,r4,2 // skip first two vtable entries
+#endif
+ slwi r4,r4,2 // convert to offset ( *= 4 )
+ lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) // load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 // copy methodpointer to LR
+ blrl // call method
+
+ lwz r30,16(r31) // restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) // clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s
new file mode 100644
index 00000000..18c775a9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s
@@ -0,0 +1,114 @@
+# -*- Mode: Asm -*-
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1999 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+# beard@netscape.com (Patrick Beard)
+# waterson@netscape.com (Chris Waterson)
+#
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex,@function
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+XPTC_InvokeByIndex:
+ stwu sp,-32(sp) # setup standard stack frame
+ mflr r0 # save LR
+ stw r3,8(sp) # r3 <= that
+ stw r4,12(sp) # r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) # store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 # r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 # reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) # r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 # reserve stack sapce and save SP backchain
+
+ addi r3,sp,8 # r3 <= args
+ mr r4,r5 # r4 <= paramCount
+ mr r5,r6 # r5 <= params
+ add r6,r3,r10 # r6 <= gpregs ( == args + r10 )
+ mr r30,r6 # store in r30 for use later...
+ addi r7,r6,32 # r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local # (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) # load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) # r3 <= that
+ lwz r4,12(r31) # r4 <= methodIndex
+ lwz r5,0(r3) # r5 <= vtable ( == *that )
+ slwi r4,r4,3 # convert to offset ( *= 8 )
+ addi r4,r4,8 # skip first two vtable entries
+ add r4,r4,r5
+ lhz r0,0(r4) # virtual base offset
+ extsh r0,r0
+ add r3,r3,r0
+ lwz r0,4(r4) # r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) # load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 # copy methodpointer to LR
+ blrl # call method
+
+ lwz r30,16(r31) # restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) # clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
new file mode 100644
index 00000000..8a5c9afb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
@@ -0,0 +1,162 @@
+#
+# -*- Mode: Asm -*-
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1999 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Patrick C. Beard <beard@netscape.com>
+#
+
+#
+# ** Assumed vtable layout (obtained by disassembling with gdb):
+# ** 4 bytes per vtable entry, skip 0th and 1st entries, so the mapping
+# ** from index to entry is (4 * index) + 8.
+#
+
+.text
+ .align 2
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.globl __XPTC_InvokeByIndex
+__XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(r1)
+#
+# save off the incoming values in the callers parameter area
+#
+ stw r3,24(r1) ; that
+ stw r4,28(r1) ; methodIndex
+ stw r5,32(r1) ; paramCount
+ stw r6,36(r1) ; params
+ stw r0,8(r1)
+ stwu r1,-144(r1) ; 24 for linkage area,
+ ; 8*13 for fprData area,
+ ; 8 for saved registers,
+ ; 8 to keep stack 16-byte aligned
+
+# set up for and call 'invoke_count_words' to get new stack size
+#
+ mr r3,r5
+ mr r4,r6
+
+ stwu r1,-24(r1)
+ bl L_invoke_count_words$stub
+ lwz r1,0(r1)
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,176(r1) ; paramCount
+ lwz r5,180(r1) ; params
+ mr r6,r1 ; fprData
+ slwi r3,r3,2 ; number of stack bytes required
+ addi r3,r3,28 ; linkage area
+ mr r31,r1 ; save original stack top
+ sub r1,r1,r3 ; bump the stack
+ clrrwi r1,r1,4 ; keep the stack 16-byte aligned
+ addi r3,r31,144 ; act like real alloca, so 0(sp) always
+ stw r3,0(r1) ; points back to previous stack frame
+ addi r3,r1,28 ; parameter pointer excludes linkage area size + 'this'
+
+# create "temporary" stack frame for _invoke_copy_to_stack to operate in.
+ stwu r1,-40(r1)
+ bl L_invoke_copy_to_stack$stub
+# remove temporary stack frame.
+ lwz r1,0(r1)
+
+ lfd f1,0(r31)
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,168(r31) ; that
+ lwz r4,0(r3) ; get vTable from 'that'
+ lwz r5,172(r31) ; methodIndex
+ slwi r5,r5,2 ; methodIndex * 4
+#ifndef HAVE_GCC3_ABI
+ addi r5,r5,8 ; (methodIndex * 4) + 8
+#endif
+ lwzx r12,r5,r4 ; get function pointer
+
+ lwz r4,28(r1)
+ lwz r5,32(r1)
+ lwz r6,36(r1)
+ lwz r7,40(r1)
+ lwz r8,44(r1)
+ lwz r9,48(r1)
+ lwz r10,52(r1)
+
+ mtlr r12
+ blrl
+
+ mr r1,r31
+ lwz r0,152(r1)
+ addi r1,r1,144
+ mtlr r0
+ lwz r31,-4(r1)
+
+ blr
+
+.picsymbol_stub
+L_invoke_count_words$stub:
+ .indirect_symbol _invoke_count_words
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _invoke_count_words
+ .long dyld_stub_binding_helper
+
+
+.picsymbol_stub
+L_invoke_copy_to_stack$stub:
+ .indirect_symbol _invoke_copy_to_stack
+ mflr r0
+ bcl 20,31,L2$pb
+L2$pb:
+ mflr r11
+ addis r11,r11,ha16(L2$lz-L2$pb)
+ mtlr r0
+ lwz r12,lo16(L2$lz-L2$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L2$lz-L2$pb)
+ bctr
+.lazy_symbol_pointer
+L2$lz:
+ .indirect_symbol _invoke_copy_to_stack
+ .long dyld_stub_binding_helper
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s
new file mode 100644
index 00000000..b744ee9b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s
@@ -0,0 +1,121 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s): Chris Torek (torek@bsdi.com), Kurt Lidl (lidl@pix.net)
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ /* regular C/C++ stack frame -- see <machine/frame.h> */
+ save %sp, -96, %sp
+
+ /*
+ * invoke_count_words(paramCount, params) apparently tells us
+ * how many "32-bit words" are involved in passing the given
+ * parameters to the target function.
+ */
+ mov %i2, %o0
+ call invoke_count_words ! invoke_count_words(paramCount, params)
+ mov %i3, %o1
+
+ /*
+ * ??? Torek wonders: does invoke_count_words always force its
+ * return value to be even? If not, we would have to adjust
+ * the return value ... should make it a multiple of 8 anyway,
+ * for efficiency (32 byte cache lines); will do that here thus:
+ *
+ * We already have room (in our callee's "argument dump" area,
+ * sp->fr_argd) for six parameters, and we are going to use
+ * five of those (fr_argd[1] through fr_argd[5]) in a moment.
+ * This space is followed by fr_argx[1], room for a seventh.
+ * Thus, if invoke_count_words returns a value between 0 and 6
+ * inclusive, we do not need any stack adjustment. For values
+ * from 7 through (7+8) we want to make room for another 8
+ * parameters, and so on. Thus, we want to calculate:
+ *
+ * n_extra_words = (wordcount + 1) & ~7
+ *
+ * and then make room for that many more 32-bit words. (Normally
+ * it would be ((w+7)&~7; we just subtract off the room-for-6 we
+ * already have.)
+ */
+ inc %o0
+ andn %o0, 7, %o0
+ sll %o0, 2, %o0 ! convert to bytes
+ sub %sp, %o0, %sp ! and make room for arguments
+
+ /*
+ * Copy all the arguments to the stack, starting at the argument
+ * dump area at [%sp + 68], even though the first six arguments
+ * go in the six %o registers. We will just load up those
+ * arguments after the copy is done. The first argument to
+ * any C++ member function is always the "this" parameter so
+ * we actually start with what will go in %o1, at [%sp + 72].
+ */
+ add %sp, 72, %o0 ! invoke_copy_to_stack(addr,
+ mov %i2, %o1 ! paramCount,
+ call invoke_copy_to_stack
+ mov %i3, %o2 ! params);
+
+ /*
+ * This is the only really tricky (compiler-dependent) part
+ * (everything else here relies only on the V8 SPARC calling
+ * conventions). "methodIndex" (%i1) is an index into a C++
+ * vtable. The word at "*that" points to the vtable, but for
+ * some reason, the first function (index=0) is at vtable[2*4],
+ * the second (index 1) at vtable[3*4], the third at vtable[4*4],
+ * and so on. Thus, we want, in effect:
+ *
+ * that->vTable[index + 2]
+ */
+ ld [%i0], %l0 ! vTable = *that
+ add %i1, 2, %l1
+ sll %l1, 2, %l1
+ ld [%l0 + %l1], %l0 ! fn = vTable[index + 2]
+
+ /*
+ * Now load up the various function parameters. We do not know,
+ * nor really care, how many there are -- we just load five words
+ * from the stack (there are always at least five such words to
+ * load, even if some of them are junk) into %o1 through %o5,
+ * and set %o0 = %i0, to pass "that" to the target member function
+ * as its C++ "this" parameter.
+ *
+ * If there are more than five parameters, any extras go on our
+ * stack starting at sp->fr_argx ([%sp + 92]), which is of course
+ * where we have just copied them.
+ */
+ ld [%sp + 72], %o1
+ ld [%sp + 76], %o2
+ ld [%sp + 80], %o3
+ ld [%sp + 84], %o4
+ ld [%sp + 88], %o5
+ call %l0 ! fn(that, %o1, %o2, %o3, %o4, %o5)
+ mov %i0, %o0
+
+ ! return whatever fn() returned
+ ret
+ restore %o0, 0, %o0
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s
new file mode 100644
index 00000000..c23fd1e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! 32 bit pointer
+ add %i1,%l1,%l1 ! vTable[index * 4], l1 now points to vTable entry
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
new file mode 100644
index 00000000..9a6b02ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * David S. Miller <davem@redhat.com> (ported to gcc3)
+ *
+ * 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.
+ */
+
+/*
+ * Platform specific code to invoke XPCOM methods on native objects for
+ * Linux/Sparc with gcc 3 ABI.
+ */
+ .global XPTC_InvokeByIndex
+/*
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params);
+ *
+ */
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s
new file mode 100644
index 00000000..be0e34a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s
new file mode 100644
index 00000000..be0e34a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s
new file mode 100644
index 00000000..203e3f1c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
new file mode 100644
index 00000000..6a2e9606
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * David Baron <dbaron@dbaron.org> (ported to
+ * gcc 3/sparc-sun-solaris from gcc 2.x/sparc-sun-solaris)
+ */
+
+/*
+ * Platform specific code to invoke XPCOM methods on native objects for
+ * solaris/sparc with gcc 3 ABI.
+ */
+ .global XPTC_InvokeByIndex
+/*
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params);
+ */
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
new file mode 100644
index 00000000..b70f1b46
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+ .global XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex, #function
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ sll %i2,3,%l0 ! assume the worst case
+ ! paramCount * 2 * 4 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+!
+ ld [%sp + 72],%o1
+ ld [%sp + 76],%o2
+ ld [%sp + 80],%o3
+ ld [%sp + 84],%o4
+ ld [%sp + 88],%o5
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,2,%l0 ! index *= 4
+ add %l0,8,%l0 ! there are 2 extra entries in the vTable
+ ld [%i0],%l1 ! *that --> address of vtable
+ ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size XPTC_InvokeByIndex, .-XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
new file mode 100644
index 00000000..232ed6bd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
@@ -0,0 +1,103 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2001 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ */
+
+/*
+ Platform specific code to invoke XPCOM methods on native objects
+ for sparcv9 Solaris.
+
+ See the SPARC Compliance Definition (SCD) Chapter 3
+ for more information about what is going on here, including
+ the use of BIAS (0x7ff).
+ The SCD is available from http://www.sparc.com/.
+*/
+
+ .global XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex, #function
+
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+ sll %i2,4,%l0 ! assume the worst case
+ ! paramCount * 2 * 8 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,0x7ff+136,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+! BIAS is 0x7ff (2047)
+!
+
+! load the %o1..5 64bit (extended word) output registers registers
+ ldx [%sp + 0x7ff + 136],%o1 ! %i1
+ ldx [%sp + 0x7ff + 144],%o2 ! %i2
+ ldx [%sp + 0x7ff + 152],%o3 ! %i3
+ ldx [%sp + 0x7ff + 160],%o4 ! %i4
+ ldx [%sp + 0x7ff + 168],%o5 ! %i5
+
+! load the even number double registers starting with %d2
+ ldd [%sp + 0x7ff + 136],%d2
+ ldd [%sp + 0x7ff + 144],%d4
+ ldd [%sp + 0x7ff + 152],%d6
+ ldd [%sp + 0x7ff + 160],%d8
+ ldd [%sp + 0x7ff + 168],%d10
+ ldd [%sp + 0x7ff + 176],%d12
+ ldd [%sp + 0x7ff + 184],%d14
+ ldd [%sp + 0x7ff + 192],%d16
+ ldd [%sp + 0x7ff + 200],%d18
+ ldd [%sp + 0x7ff + 208],%d20
+ ldd [%sp + 0x7ff + 216],%d22
+ ldd [%sp + 0x7ff + 224],%d24
+ ldd [%sp + 0x7ff + 232],%d26
+ ldd [%sp + 0x7ff + 240],%d28
+ ldd [%sp + 0x7ff + 248],%d30
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,3,%l0 ! index *= 8
+ add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
+ ldx [%i0],%l1 ! *that --> address of vtable
+ ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size XPTC_InvokeByIndex, .-XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
new file mode 100644
index 00000000..79b17ae3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
@@ -0,0 +1,215 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#ifdef __GNUC__ /* Gnu compiler. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+#ifndef XP_WIN32
+static
+#endif
+void ATTRIBUTE_USED __attribute__ ((regparm(3)))
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ default : *((void**)d) = s->val.p; break;
+ }
+ }
+}
+} // extern "C"
+
+// NOTE! See xptc_gcc_x86_unix.h for the reason why this function exists.
+#if (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ == 0))
+PRUint32
+xptc_invoke_copy_to_stack_keeper (void)
+{
+ PRUint32 dummy1;
+ void ATTRIBUTE_USED __attribute__ ((regparm(3))) (*dummy2)
+ (PRUint32, nsXPTCVariant*, PRUint32*) = invoke_copy_to_stack;
+
+// dummy2 references invoke_copy_to_stack, now we have to "use" it
+ __asm__ __volatile__ (
+ ""
+ : "=&a" (dummy1)
+ : "g" (dummy2)
+ );
+
+ return dummy1 & 0xF0F00000;
+}
+#endif
+
+
+/*
+ XPTC_PUBLIC_API(nsresult)
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+ NOTE NOTE NOTE:
+ As of 2002-04-29 this function references no global variables nor does
+ it call non-static functions so preserving and loading the PIC register
+ is unnecessary. Define MOZ_PRESERVE_PIC if this changes. See mozilla
+ bug 140412 for details. However, avoid this if you can. It's slower.
+*/
+/*
+ * Hack for gcc for win32. Functions used externally must be
+ * explicitly dllexported.
+ * Bug 226609
+ */
+#ifdef XP_WIN32
+extern "C" {
+ nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+ XPTC_PUBLIC_API(nsresult)
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params) {
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+ }
+}
+#endif
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+#ifdef XP_WIN32
+ ".globl " SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex,@function\n"
+ SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex:\n\t"
+#else
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ ".globl " SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex,@function\n"
+ SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex:\n\t"
+#else
+ ".globl " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex,@function\n"
+ SYMBOL_UNDERSCORE "XPTC_InvokeByIndex:\n\t"
+#endif
+#endif
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "pushl %ebx\n\t"
+ "call 0f\n\t"
+ ".subsection 1\n"
+ "0:\n\t"
+ "movl (%esp), %ebx\n\t"
+ "ret\n\t"
+ ".previous\n\t"
+ "addl $_GLOBAL_OFFSET_TABLE_, %ebx\n\t"
+#endif
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+ "movl %esp, %ecx\n\t"
+ "subl %edx, %ecx\n\t"
+/* Since there may be 64-bit data, it occurs to me that aligning this
+ space might be a performance gain. However, I don't think the rest
+ of mozilla worries about such things. In any event, do it here.
+ "andl $0xfffffff8, %ecx\n\t"
+ */
+ "movl %ecx, %esp\n\t" /* make stack space */
+ "movl 0x14(%ebp), %edx\n\t"
+ "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "shll $3, %eax\n\t" /* *= 8 */
+ "addl $8, %eax\n\t" /* += 8 skip first entry */
+ "addl %eax, %edx\n\t"
+ "movswl (%edx), %eax\n\t" /* 'this' offset */
+ "addl %eax, %ecx\n\t"
+ "pushl %ecx\n\t"
+ "addl $4, %edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %ecx\n\t"
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "leal (%edx,%eax,4), %edx\n\t"
+#else /* not G++ V3 ABI */
+ "leal 8(%edx,%eax,4), %edx\n\t"
+#endif /* G++ V3 ABI */
+#endif
+ "call *(%edx)\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "movl -4(%ebp), %ebx\n\t"
+#endif
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+#ifdef XP_WIN32
+ ".size " SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex\n\t"
+#else
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ ".size " SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex\n\t"
+#else
+ ".size " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+#endif
+#endif
+);
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp
new file mode 100644
index 00000000..5a959317
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp
@@ -0,0 +1,164 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+
+#include <iostream.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const PRUint32 paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ PRUint32 len = paramCount;
+ nsXPTCVariant* source = s;
+
+ PRUint32 indx;
+ PRUint32 endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp
new file mode 100644
index 00000000..356c2c7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp
@@ -0,0 +1,133 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+
+#include <stdint.h>
+#include <iostream.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const PRUint32 paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ PRUint32 len = paramCount;
+ nsXPTCVariant* source = s;
+
+ PRUint32 indx;
+ PRUint32 endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp
new file mode 100644
index 00000000..67aa6144
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if (_MIPS_SIM != _ABIN32)
+#error "This code is for IRIX N32 only"
+#endif
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return(paramCount*2);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount,
+ nsXPTCVariant* s, PRUint64 *regs)
+{
+#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */
+
+ for (PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if (s->IsPtrData()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint64)s->ptr;
+ else
+ *d++ = (PRUint64)s->ptr;
+ continue;
+ }
+ switch (s->type) {
+ //
+ // signed types first
+ //
+ case nsXPTType::T_I8:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i8;
+ else
+ *d++ = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i16;
+ else
+ *d++ = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i32;
+ else
+ *d++ = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i64;
+ else
+ *d++ = s->val.i64;
+ break;
+ //
+ // unsigned types next
+ //
+ case nsXPTType::T_U8:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u8;
+ else
+ *d++ = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u16;
+ else
+ *d++ = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u32;
+ else
+ *d++ = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u64;
+ else
+ *d++ = s->val.u64;
+ break;
+ case nsXPTType::T_FLOAT:
+ if (i < N_ARG_REGS)
+ // Place a float in least significant bytes.
+ *(float*)(((char*)&regs[i+1]) - sizeof(float)) = s->val.f;
+ else
+ *(float*)d++ = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (i < N_ARG_REGS)
+ *(double*)&regs[i] = s->val.d;
+ else
+ *(double*)d++ = s->val.d;
+ break;
+ case nsXPTType::T_BOOL:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.b;
+ else
+ *d++ = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.c;
+ else
+ *d++ = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.wc;
+ else
+ *d++ = s->val.wc;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint64)s->val.p;
+ else
+ *d++ = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
new file mode 100644
index 00000000..7f7d84c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Glen Nakamura <glen@imodulo.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+__asm__("invoke_copy_to_stack") __attribute__((unused));
+
+static void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (PRUint64)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (PRUint64)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (PRUint64)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (PRUint64)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (PRUint64)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (PRUint64)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (PRUint64)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { PRUint64 u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (PRUint64)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (PRUint64)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (PRUint64)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (PRUint64)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
+
+/*
+ * XPTC_PUBLIC_API(nsresult)
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params)
+ */
+__asm__(
+ "#### XPTC_InvokeByIndex ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".globl XPTC_InvokeByIndex\n\t"
+ ".ent XPTC_InvokeByIndex\n"
+"XPTC_InvokeByIndex:\n\t"
+ ".frame $15,32,$26,0\n\t"
+ ".mask 0x4008000,-32\n\t"
+ "ldgp $29,0($27)\n"
+"$XPTC_InvokeByIndex..ng:\n\t"
+ "subq $30,32,$30\n\t"
+ "stq $26,0($30)\n\t"
+ "stq $15,8($30)\n\t"
+ "bis $30,$30,$15\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+ "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */
+ "cmplt $2,$18,$1\n\t"
+ "cmovne $1,$18,$2\n\t"
+ "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */
+ "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */
+ "subq $30,$1,$30\n\t"
+
+ "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */
+ "stq $17,16($15)\n\t" /* save "methodIndex" */
+
+ "addq $30,8,$16\n\t" /* pass stack pointer */
+ "bis $18,$18,$17\n\t" /* pass "paramCount" */
+ "bis $19,$19,$18\n\t" /* pass "params" */
+ "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */
+
+ /*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ "ldq $16,0($30)\n\t" /* integer registers */
+ "ldq $17,8($30)\n\t"
+ "ldq $18,16($30)\n\t"
+ "ldq $19,24($30)\n\t"
+ "ldq $20,32($30)\n\t"
+ "ldq $21,40($30)\n\t"
+ "ldt $f17,8($30)\n\t" /* floating point registers */
+ "ldt $f18,16($30)\n\t"
+ "ldt $f19,24($30)\n\t"
+ "ldt $f20,32($30)\n\t"
+ "ldt $f21,40($30)\n\t"
+
+ "addq $30,48,$30\n\t" /* remove params from stack */
+
+ /*
+ * Call the virtual function with the constructed stack frame.
+ */
+ "bis $16,$16,$1\n\t" /* load "this" */
+ "ldq $2,16($15)\n\t" /* load "methodIndex" */
+ "ldq $1,0($1)\n\t" /* load vtable */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */
+#else /* not G++ V3 ABI */
+ "s8addq $2,16,$2\n\t" /* vtable index = "methodIndex" * 8 + 16 */
+#endif /* G++ V3 ABI */
+ "addq $1,$2,$1\n\t"
+ "ldq $27,0($1)\n\t" /* load address of function */
+ "jsr $26,($27),0\n\t" /* call virtual function */
+ "ldgp $29,0($26)\n\t"
+
+ "bis $15,$15,$30\n\t"
+ "ldq $26,0($30)\n\t"
+ "ldq $15,8($30)\n\t"
+ "addq $30,32,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end XPTC_InvokeByIndex"
+ );
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
new file mode 100644
index 00000000..363e45e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+extern "C" {
+ static PRUint32
+ invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+ }
+
+ void
+ invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((PRUint32*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRUint32*)d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint32*)d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result, n;
+
+ n = invoke_count_words(paramCount, params) * 4;
+
+ __asm__ __volatile__(
+ "subl %5, %/sp\n\t" /* make room for params */
+ "movl %/sp, %/a0\n\t"
+ "movl %4, %/sp@-\n\t"
+ "movl %3, %/sp@-\n\t"
+ "movl %/a0, %/sp@-\n\t"
+ "jbsr invoke_copy_to_stack\n\t" /* copy params */
+ "addl #12, %/sp\n\t"
+ "movl %1, %/a0\n\t"
+ "movl %/a0, %/sp@-\n\t"
+ "movl %/a0@, %/a0\n\t"
+ "movl %2, %/d0\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "movl %/a0@(%/d0:l:4), %/a0\n\t"
+#else /* not V3 */
+ "movl %/a0@(8,%/d0:l:4), %/a0\n\t"
+#endif
+ "jbsr %/a0@\n\t" /* safe to not cleanup sp */
+ "movl %/d0, %0\n\t"
+ "addql #4, %/sp\n\t"
+ "addl %5, %/sp"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "g" (n) /* %5 */
+ : "a0", "a1", "d0", "d1", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
new file mode 100644
index 00000000..5da035ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
@@ -0,0 +1,254 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2) fpr++; else overflow+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d_ov, PRUint32 overflow)
+{
+ PRUint32 *d_gpr = d_ov + overflow;
+ PRUint64 *d_fpr = (PRUint64 *)(d_gpr + 4);
+ PRUint32 gpr = 1 /*this*/, fpr = 0;
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((PRInt32*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((PRInt32*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((PRInt32*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((PRInt32*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((PRInt32*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((PRInt32*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ *((PRInt64*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2;
+ else
+ *((PRInt64*) d_ov ) = s->val.i64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((PRUint32*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((PRUint32*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ *((PRUint64*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2;
+ else
+ *((PRUint64*)d_ov ) = s->val.u64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *((float*) d_ov ) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 *vtable = *(PRUint32 **)that;
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ PRUint32 method = vtable[methodIndex];
+#else /* not G++ V3 ABI */
+ PRUint32 method = vtable[methodIndex + 2];
+#endif /* G++ V3 ABI */
+ PRUint32 overflow = invoke_count_words (paramCount, params);
+ PRUint32 result;
+
+ __asm__ __volatile__
+ (
+ "lr 7,15\n\t"
+ "ahi 7,-32\n\t"
+
+ "lr 3,%3\n\t"
+ "sll 3,2\n\t"
+ "lcr 3,3\n\t"
+ "l 2,0(15)\n\t"
+ "la 15,0(3,7)\n\t"
+ "st 2,0(15)\n\t"
+
+ "lr 2,%1\n\t"
+ "lr 3,%2\n\t"
+ "la 4,96(15)\n\t"
+ "lr 5,%3\n\t"
+ "basr 14,%4\n\t"
+
+ "lr 2,%5\n\t"
+ "ld 0,112(7)\n\t"
+ "ld 2,120(7)\n\t"
+ "lm 3,6,96(7)\n\t"
+ "basr 14,%6\n\t"
+
+ "la 15,32(7)\n\t"
+
+ "lr %0,2\n\t"
+ : "=r" (result)
+ : "r" (paramCount),
+ "r" (params),
+ "r" (overflow),
+ "a" (invoke_copy_to_stack),
+ "a" (that),
+ "a" (method)
+ : "2", "3", "4", "5", "6", "7", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp
new file mode 100644
index 00000000..5a4268b6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp
@@ -0,0 +1,250 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ case nsXPTType::T_I64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ case nsXPTType::T_U64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_FLOAT :
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint64* d_ov, PRUint32 overflow)
+{
+ PRUint64 *d_gpr = d_ov + overflow;
+ PRUint64 *d_fpr = (PRUint64 *)(d_gpr + 4);
+ PRUint32 gpr = 1 /*this*/, fpr = 0;
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i64, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i64, d_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((PRUint64*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((PRUint64*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.u64, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.u64, d_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *(((float*) d_ov )+1) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint64 *vtable = *(PRUint64 **)that;
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ PRUint64 method = vtable[methodIndex];
+#else /* not G++ V3 ABI */
+ PRUint64 method = vtable[methodIndex + 2];
+#endif /* G++ V3 ABI */
+ PRUint64 overflow = invoke_count_words (paramCount, params);
+ PRUint64 result;
+
+ __asm__ __volatile__
+ (
+ "lgr 7,15\n\t"
+ "aghi 7,-64\n\t"
+
+ "lgr 3,%3\n\t"
+ "sllg 3,3,3\n\t"
+ "lcgr 3,3\n\t"
+ "lg 2,0(15)\n\t"
+ "la 15,0(3,7)\n\t"
+ "stg 2,0(15)\n\t"
+
+ "lgr 2,%1\n\t"
+ "lgr 3,%2\n\t"
+ "la 4,160(15)\n\t"
+ "lgr 5,%3\n\t"
+ "basr 14,%4\n\t"
+
+ "lgr 2,%5\n\t"
+ "ld 0,192(7)\n\t"
+ "ld 2,200(7)\n\t"
+ "ld 4,208(7)\n\t"
+ "ld 6,216(7)\n\t"
+ "lmg 3,6,160(7)\n\t"
+ "basr 14,%6\n\t"
+
+ "la 15,64(7)\n\t"
+
+ "lgr %0,2\n\t"
+ : "=r" (result)
+ : "r" ((PRUint64)paramCount),
+ "r" (params),
+ "r" (overflow),
+ "a" (invoke_copy_to_stack),
+ "a" (that),
+ "a" (method)
+ : "2", "3", "4", "5", "6", "7", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
new file mode 100644
index 00000000..a73e4327
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* This code is for MIPS using the O32 ABI. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ // Count a word for a0 even though it's never stored or loaded
+ // We do this only for alignment of register pairs.
+ PRUint32 result = 1;
+ for (PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ result++;
+
+ if (s->IsPtrData())
+ continue;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ if (result & 1)
+ result++;
+ result++;
+ break;
+ }
+ }
+ return (result + 1) & ~(PRUint32)1;
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+ nsXPTCVariant* s)
+{
+ // Skip the unused a0 slot, which we keep only for register pair alignment.
+ d++;
+
+ for (PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if (s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ if ((PRWord)d & 4) d++;
+ *((PRInt64*) d) = s->val.i64; d++;
+ break;
+ case nsXPTType::T_U64 :
+ if ((PRWord)d & 4) d++;
+ *((PRUint64*) d) = s->val.u64; d++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if ((PRWord)d & 4) d++;
+ *((double*) d) = s->val.d; d++;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount,
+ nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp
new file mode 100644
index 00000000..65bf8f0c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp
@@ -0,0 +1,175 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static PRUint32
+ invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+ }
+
+ static void
+ invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((PRUint32*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRUint32*)d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint32*)d) = s->val.c; break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result;
+
+ __asm__ __volatile__(
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "jbsr _invoke_count_words\n\t" /* count words */
+ "addql #8, sp\n\t"
+ "lsll #2, d0\n\t" /* *= 4 */
+ "movl sp, a2\n\t" /* save original sp */
+ "subl d0, sp\n\t" /* make room for params */
+ "movl sp, a0\n\t"
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "movl a0, sp@-\n\t"
+ "jbsr _invoke_copy_to_stack\n\t" /* copy params */
+ "addl #12, sp\n\t"
+ "movl %1, a0\n\t"
+ "movl a0@, a1\n\t"
+ "movl %2, d0\n\t" /* function index */
+ "movl a0, d1\n\t"
+ "movw a1@(8,d0:l:8), a0\n\t"
+ "addl a0, d1\n\t"
+ "movl a1@(12,d0:l:8), a1\n\t"
+ "movl d1, sp@-\n\t"
+ "jbsr a1@\n\t"
+ "movl a2, sp\n\t" /* restore original sp */
+ "movl d0, %0\n\t"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params) /* %4 */
+ : "a0", "a1", "a2", "d0", "d1", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp
new file mode 100644
index 00000000..ae22a48c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" {
+
+/* This is in the ASM file */
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+
+void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (PRUint64)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ /*
+ ** The line for T_U32 may look wrong (we use signed value for an
+ ** unsigned data type), but it is right. Why? The Alpha calling
+ ** standard is defined to sign extend all 32-bit values, regardless
+ ** of whether they are int, unsigned int, or 32-bit pointer. The
+ ** caller must "sign-extend" it by replicating bit 31 in bits 32
+ ** thru 63 (yes, even for unsigned). This is the format that results
+ ** naturally from the LDL instruction, the ADDL instruction, etc.
+ */
+ case nsXPTType::T_I8 : *d = (PRUint64)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (PRUint64)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (PRUint64)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (PRUint64)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (PRUint64)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_U64 : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { PRUint64 u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (PRUint64)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (PRUint64)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (PRUint64)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (PRUint64)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
+
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp
new file mode 100644
index 00000000..13c3b23d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+/* contributed by Steve Streeter <Stephen.Streeter@Compaq.com> */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name */
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s);
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (PRUint64)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (PRUint64)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (PRUint64)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (PRUint64)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (PRUint64)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (PRUint64)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (PRUint64)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { PRUint64 u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (PRUint64)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (PRUint64)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (PRUint64)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (PRUint64)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp
new file mode 100644
index 00000000..c6208a50
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp
@@ -0,0 +1,181 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+#include <alloca.h>
+
+typedef unsigned nsXPCVariant;
+
+extern "C" PRInt32
+invoke_count_bytes(nsISupports* that, const PRUint32 methodIndex,
+ const PRUint32 paramCount, const nsXPTCVariant* s)
+{
+ PRInt32 result = 4; /* variant records do not include self pointer */
+
+ /* counts the number of bytes required by the argument stack,
+ 64 bit integer, and double requires 8 bytes. All else requires
+ 4 bytes.
+ */
+
+ {
+ PRUint32 indx;
+ for (indx = paramCount; indx > 0; --indx, ++s)
+ {
+ if (! s->IsPtrData())
+ {
+ if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 ||
+ s->type == nsXPTType::T_DOUBLE)
+ {
+ /* 64 bit integer and double aligned on 8 byte boundaries */
+ result += (result & 4) + 8;
+ continue;
+ }
+ }
+ result += 4; /* all other cases use 4 bytes */
+ }
+ }
+ result -= 72; /* existing stack buffer is 72 bytes */
+ if (result < 0)
+ return 0;
+ {
+ /* round up to 64 bytes boundary */
+ PRInt32 remainder = result & 63;
+ return (remainder == 0) ? result : (result + 64 - remainder);
+ }
+}
+
+extern "C" PRUint32
+invoke_copy_to_stack(PRUint32* d,
+ const PRUint32 paramCount, nsXPTCVariant* s)
+{
+
+ typedef struct
+ {
+ PRUint32 hi;
+ PRUint32 lo;
+ } DU;
+
+ PRUint32* dest = d;
+ nsXPTCVariant* source = s;
+ /* we clobber param vars by copying stuff on stack, have to use local var */
+
+ PRUint32 floatflags = 0;
+ /* flag indicating which floating point registers to load */
+
+ PRUint32 regwords = 1; /* register 26 is reserved for ptr to 'that' */
+ PRUint32 indx;
+
+ for (indx = paramCount; indx > 0; --indx, --dest, ++source)
+ {
+ if (source->IsPtrData())
+ {
+ *((void**) dest) = source->ptr;
+ ++regwords;
+ continue;
+ }
+ switch (source->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt32*) dest) = source->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt32*) dest) = source->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) dest) = source->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ *((uint32*) dest) = ((DU *) source)->lo;
+ *((uint32*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ switch (regwords) /* load double precision float register */
+ {
+ case 2:
+ floatflags |= 1;
+ }
+ *((uint32*) dest) = ((DU *) source)->lo;
+ *((uint32*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ switch (regwords) /* load single precision float register */
+ {
+ case 1:
+ floatflags |= 2;
+ break;
+ case 2:
+ floatflags |= 4;
+ break;
+ case 3:
+ floatflags |= 8;
+ }
+ *((float*) dest) = source->val.f;
+ break;
+ case nsXPTType::T_U8 : *((PRUint32*) (dest)) = source->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*) (dest)) = source->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*) (dest)) = source->val.u32; break;
+ case nsXPTType::T_BOOL : *((PRBool*) (dest)) = source->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint32*) (dest)) = source->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRInt32*) (dest)) = source->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**) dest) = source->val.p;
+ }
+ ++regwords;
+ }
+ return floatflags;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp
new file mode 100644
index 00000000..d353063c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp
@@ -0,0 +1,106 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef AIX
+#error "This code is for PowerPC only"
+#endif
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ PRUint32 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ PRUint32 l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_DOUBLE :
+ *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_U8 : *((uint32*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT :
+ *((float*) l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ case nsXPTType::T_BOOL : *((PRBool*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp
new file mode 100644
index 00000000..a42611b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp
@@ -0,0 +1,95 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/LGPL 2.1/GPL 2.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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM are
+ * Copyright (C) 2002, International Business Machines Corporation.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the LGPL or the GPL. 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifdef _AIX
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ PRUint64 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ PRUint32 l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ for(PRUint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *l_d = (PRUint64)l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8: *l_d = (PRUint64)l_s->val.i8; break;
+ case nsXPTType::T_I16: *l_d = (PRUint64)l_s->val.i16; break;
+ case nsXPTType::T_I32: *l_d = (PRUint64)l_s->val.i32; break;
+ case nsXPTType::T_I64: *l_d = (PRUint64)l_s->val.i64; break;
+ case nsXPTType::T_U8: *l_d = (PRUint64)l_s->val.u8; break;
+ case nsXPTType::T_U16: *l_d = (PRUint64)l_s->val.u16; break;
+ case nsXPTType::T_U32: *l_d = (PRUint64)l_s->val.u32; break;
+ case nsXPTType::T_U64: *l_d = (PRUint64)l_s->val.u64; break;
+ case nsXPTType::T_BOOL: *l_d = (PRUint64)l_s->val.b; break;
+ case nsXPTType::T_CHAR: *l_d = (PRUint64)l_s->val.c; break;
+ case nsXPTType::T_WCHAR: *l_d = (PRUint64)l_s->val.wc; break;
+
+ case nsXPTType::T_DOUBLE:
+ *((double*)l_d) = l_s->val.d;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_FLOAT:
+ *((float*)l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ default:
+ // all the others are plain pointer types
+ *l_d = (PRUint64)l_s->val.p;
+ break;
+ }
+ }
+}
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
new file mode 100644
index 00000000..7303045a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+// The purpose of XPTC_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// XPTC_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return PRUint32(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d,
+ PRUint32 paramCount,
+ nsXPTCVariant* s,
+ PRUint32* gpregs,
+ double* fpregs)
+{
+ PRUint32 gpr = 1; // skip one GP reg for 'that'
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(uint32 i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData())
+ tempu32 = (PRUint32) s->ptr;
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (PRUint32) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((PRUint32) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else
+ *((float*) d++) = s->val.f;
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((PRUint64*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((PRUint64*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp
new file mode 100644
index 00000000..0de8ea62
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+// The purpose of XPTC_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// XPTC_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return PRUint32(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d,
+ PRUint32 paramCount,
+ nsXPTCVariant* s,
+ PRUint32* gpregs,
+ double* fpregs)
+{
+ PRUint32 gpr = 1; // skip one GP reg for 'that'
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(uint32 i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData())
+ tempu32 = (PRUint32) s->ptr;
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (PRUint32) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((PRUint32) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ if (gpr < GPR_COUNT)
+ gpr += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else {
+ *((float*) d) = s->val.f;
+ d += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((PRUint64*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((PRUint64*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
new file mode 100644
index 00000000..9a08acfd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ /* fprintf(stderr,"invoke_count_words(%d,%p)\n",paramCount, s);*/
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+ PRUint32 fpCount = 0;
+
+ /* fprintf(stderr,"invoke_copy_to_stack(%p, %d, %p, %p)\n", d, paramCount, s, fprData);*/
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt32*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt32*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.d;
+ break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRInt32*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRUint32*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp
new file mode 100644
index 00000000..fb2af366
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" PRUint32
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32 l_paramCount = paramCount;
+ uint32 regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((PRBool*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32*)l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp
new file mode 100644
index 00000000..fb2af366
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" PRUint32
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32 l_paramCount = paramCount;
+ uint32 regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((PRBool*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32*)l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp
new file mode 100644
index 00000000..83b28ebb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+/* Prototype specifies unmangled function name */
+extern "C" PRUint64
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s);
+
+extern "C" PRUint64
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ /*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+ */
+ PRUint64 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ PRUint64 l_paramCount = paramCount;
+ PRUint64 regCount = 0; // return the number of registers to load from the stack
+
+ for(PRUint64 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+
+ if (l_s->IsPtrData())
+ {
+ *l_d = (PRUint64)l_s->ptr;
+ continue;
+ }
+ switch (l_s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt64*)l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt64*)l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt64*)l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*)l_d) = l_s->val.i64; break;
+
+ case nsXPTType::T_U8 : *((PRUint64*)l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint64*)l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint64*)l_d) = l_s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)l_d) = l_s->val.u64; break;
+
+ /* in the case of floats, we want to put the bits in to the
+ 64bit space right justified... floats in the paramter array on
+ sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip
+ the space that would be occupied by %f0, %f2, etc.
+ */
+ case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break;
+ case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break;
+ case nsXPTType::T_BOOL : *((PRBool*)l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint64*)l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRInt64*)l_d) = l_s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+
+ return regCount;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp
new file mode 100644
index 00000000..76445fa4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp
@@ -0,0 +1,187 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Mentovai <mark@moxienet.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+
+extern "C" {
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+/* XXX: the following line is here (rather than as the default clause in
+ * the following switch statement) so that the Sun native compiler
+ * will generate the correct assembly code on the Solaris Intel
+ * platform. See the comments in bug #28817 for more details.
+ */
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ }
+ }
+}
+
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+#ifdef __GNUC__ /* Gnu compiler. */
+ PRUint32 result;
+ /* Each param takes at most 2, 4-byte words
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time. */
+ PRUint32 n = paramCount << 3;
+ void (*fn_copy) (unsigned int, nsXPTCVariant *, PRUint32 *) = invoke_copy_to_stack;
+ int temp1, temp2;
+
+ /* These are only significant when KEEP_STACK_16_BYTE_ALIGNED is
+ defined. Otherwise, they're just placeholders to keep the parameter
+ indices the same for aligned and unaligned users in the inline asm
+ block. */
+ unsigned int saved_esp;
+
+ __asm__ __volatile__(
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ "movl %%esp, %3\n\t"
+#endif
+ "subl %8, %%esp\n\t" /* make room for params */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ /* For the second CALL, there will be one parameter before the ones
+ copied by invoke_copy_to_stack. Make sure that the stack will be
+ aligned for that CALL. */
+ "subl $4, %%esp\n\t"
+ "andl $0xfffffff0, %%esp\n\t"
+ /* For the first CALL, there are three parameters. Leave padding to
+ ensure alignment. */
+ "subl $4, %%esp\n\t"
+ /* The third parameter to invoke_copy_to_stack is the destination pointer.
+ It needs to point into the parameter area prepared for the second CALL,
+ leaving room for the |that| parameter. This reuses |n|, which was
+ the stack space to reserve, but that's OK because it's no longer needed
+ if the stack is being kept aligned. */
+ "leal 8(%%esp), %8\n\t"
+ "pushl %8\n\t"
+#else
+ "pushl %%esp\n\t"
+#endif
+ "pushl %7\n\t"
+ "pushl %6\n\t"
+ "call *%9\n\t" /* copy params */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ /* The stack is still aligned from the first CALL. Keep it aligned for
+ the next one by popping past the parameters from the first CALL and
+ leaving space for the first (|that|) parameter for the second CALL. */
+ "addl $0x14, %%esp\n\t"
+#else
+ "addl $0xc, %%esp\n\t"
+#endif
+ "movl %4, %%ecx\n\t"
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+ "shl $3, %%eax\n\t" /* *= 8 */
+ "addl $8, %%eax\n\t" /* += 8 skip first entry */
+ "addl %%eax, %%edx\n\t"
+ "movswl (%%edx), %%eax\n\t" /* 'this' offset */
+ "addl %%eax, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "addl $4, %%edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "leal (%%edx,%%eax,4), %%edx\n\t"
+#else /* not G++ V3 ABI */
+ "leal 8(%%edx,%%eax,4), %%edx\n\t"
+#endif /* G++ V3 ABI */
+#endif
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ "movl %3, %%esp\n\t"
+#else
+ "addl $4, %%esp\n\t"
+ "addl %8, %%esp"
+#endif
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2), /* %2 */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ "=&g" (saved_esp) /* %3 */
+#else
+ /* Don't waste a register, this isn't used if alignment is unimportant */
+ "=m" (saved_esp) /* %3 */
+#endif
+ : "g" (that), /* %4 */
+ "g" (methodIndex), /* %5 */
+ "1" (paramCount), /* %6 */
+ "2" (params), /* %7 */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ /* Must be in a register, it's the target of an LEA instruction */
+ "r" (n), /* %8 */
+#else
+ "g" (n), /* %8 */
+#endif
+ "0" (fn_copy) /* %9 */
+ : "memory"
+ );
+
+ return result;
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp
new file mode 100644
index 00000000..88219d8d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ NS_ASSERTION(0,"XPTC_InvokeByIndex called on unsupported platform");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp
new file mode 100644
index 00000000..b017c741
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp
@@ -0,0 +1,227 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+// 6 integral parameters are passed in registers
+const PRUint32 GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const PRUint32 FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint32 & nr_gpr, PRUint32 & nr_fpr, PRUint32 & nr_stack)
+{
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(PRUint64 * d, PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint64 * gpregs, double * fpregs)
+{
+ PRUint32 nr_gpr = 1; // skip one GP register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (PRUint64) s->ptr;
+ else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: value = s->val.i8; break;
+ case nsXPTType::T_I16: value = s->val.i16; break;
+ case nsXPTType::T_I32: value = s->val.i32; break;
+ case nsXPTType::T_I64: value = s->val.i64; break;
+ case nsXPTType::T_U8: value = s->val.u8; break;
+ case nsXPTType::T_U16: value = s->val.u16; break;
+ case nsXPTType::T_U32: value = s->val.u32; break;
+ case nsXPTType::T_U64: value = s->val.u64; break;
+ case nsXPTType::T_BOOL: value = s->val.b; break;
+ case nsXPTType::T_CHAR: value = s->val.c; break;
+ case nsXPTType::T_WCHAR: value = s->val.wc; break;
+ default: value = (PRUint64) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports * that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant * params)
+{
+ PRUint32 nr_gpr, nr_fpr, nr_stack;
+ invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+#ifndef VBOX_WITH_GCC_SANITIZER
+ // Load parameters to stack, if necessary
+ PRUint64 *stack = (PRUint64 *) __builtin_alloca(nr_stack * 8);
+#else
+ typedef struct { PRUint64 stack[20]; } methodStack;
+ if (nr_stack > 20)
+ return NS_ERROR_CALL_FAILED;
+ methodStack stack;
+#endif
+ PRUint64 gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+#ifndef VBOX_WITH_GCC_SANITIZER
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+#else
+ invoke_copy_to_stack(stack.stack, paramCount, params, gpregs, fpregs);
+#endif
+
+ // Load FPR registers from fpregs[]
+ register double d0 asm("xmm0");
+ register double d1 asm("xmm1");
+ register double d2 asm("xmm2");
+ register double d3 asm("xmm3");
+ register double d4 asm("xmm4");
+ register double d5 asm("xmm5");
+ register double d6 asm("xmm6");
+ register double d7 asm("xmm7");
+
+ switch (nr_fpr) {
+#define ARG_FPR(N) \
+ case N+1: d##N = fpregs[N];
+ ARG_FPR(7);
+ ARG_FPR(6);
+ ARG_FPR(5);
+ ARG_FPR(4);
+ ARG_FPR(3);
+ ARG_FPR(2);
+ ARG_FPR(1);
+ ARG_FPR(0);
+ case 0:;
+#undef ARG_FPR
+ }
+
+ // Load GPR registers from gpregs[]
+ register PRUint64 a0 asm("rdi");
+ register PRUint64 a1 asm("rsi");
+ register PRUint64 a2 asm("rdx");
+ register PRUint64 a3 asm("rcx");
+ register PRUint64 a4 asm("r8");
+ register PRUint64 a5 asm("r9");
+
+ switch (nr_gpr) {
+#define ARG_GPR(N) \
+ case N+1: a##N = gpregs[N];
+ ARG_GPR(5);
+ ARG_GPR(4);
+ ARG_GPR(3);
+ ARG_GPR(2);
+ ARG_GPR(1);
+ case 1: a0 = (PRUint64) that;
+ case 0:;
+#undef ARG_GPR
+ }
+
+ // Ensure that assignments to SSE registers won't be optimized away
+ asm("" ::
+ "x" (d0), "x" (d1), "x" (d2), "x" (d3),
+ "x" (d4), "x" (d5), "x" (d6), "x" (d7));
+
+ // Get pointer to method
+ PRUint64 methodAddress = *((PRUint64 *)that);
+ methodAddress += 8 * methodIndex;
+ methodAddress = *((PRUint64 *)methodAddress);
+
+#ifndef VBOX_WITH_GCC_SANITIZER
+ typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64);
+ PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5);
+#else
+ typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, methodStack);
+ PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5, stack);
+#endif
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp
new file mode 100644
index 00000000..14ecb2d8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp
@@ -0,0 +1,285 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#ifdef VBOX
+# include <iprt/alloca.h>
+#endif
+
+extern "C" {
+
+// Remember that these 'words' are 32bit DWORDS
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ result++;
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+/* XXX: the following line is here (rather than as the default clause in
+ * the following switch statement) so that the Sun native compiler
+ * will generate the correct assembly code on the Solaris Intel
+ * platform. See the comments in bug #28817 for more details.
+ */
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ }
+ }
+}
+
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+#ifdef __GNUC__ /* Gnu compiler. */
+ PRUint32 result;
+ PRUint32 n = invoke_count_words (paramCount, params) * 4;
+ int temp1, temp2, temp3;
+
+# ifdef VBOX
+ /* This is for dealing with gcc 4.5.2 not using registers for 'g' parameters
+ and instead trying to get things like 'that' via %esp after we've changed it. */
+# if 1 /* safe version. */
+ void (*fn_copy) (unsigned int, nsXPTCVariant *, PRUint32 *) = invoke_copy_to_stack;
+ struct Combined
+ {
+ PRUint32 that; /* offset: 0 */
+ PRUint32 pfn; /* offset: 4 */
+ PRUint32 savedEsp; /* offset: 8 */
+ PRUint32 paramCount; /* offset: 12 */
+ PRUint32 params; /* offset: 16 */
+ } Combined;
+# ifdef CFRONT_STYLE_THIS_ADJUST
+ struct CFRONTVTE { uintptr_t off, pfn } *pVtab = *(struct CFRONTVTE **)that;
+ Combined.that = (uintptr_t)that + pVtab[methodIndex + 1].off;
+ Combined.pfn = pVtab[methodIndex + 1].pfn;
+# elif defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ Combined.that = (uintptr_t)that;
+ Combined.pfn = (*(uintptr_t **)that)[methodIndex];
+# else /* not G++ V3 ABI */
+ Combined.that = (uintptr_t)that;
+ Combined.pfn = (*(uintptr_t **)that)[2 + methodIndex];
+# endif /* G++ V3 ABI */
+ Combined.paramCount = paramCount;
+ Combined.params = (uintptr_t)params;
+
+ __asm__ __volatile__(
+ "mov %%esp, 8(%%esi)\n\t" /* savedEsp = %esp */
+ "subl %1, %%esp\n\t" /* make room for params */
+
+ /* Call invoke_count_words to copy the parameters. */
+ "pushl %%esp\n\t" /* arg2: dest */
+ "pushl 16(%%esi)\n\t" /* arg1: params */
+ "pushl 12(%%esi)\n\t" /* arg0: paramCount */
+ "call *%0\n\t"
+ "addl $0xc, %%esp\n\t"
+
+ /* Push the this pointer. */
+ "pushl (%%esi)\n\t" /* that */
+ "call *4(%%esi)\n\t"
+ "mov 8(%%esi), %%esp\n\t"
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2) /* %2 */
+ : "S" (&Combined), /* %3 */
+ "0" (fn_copy),
+ "1" (n)
+ : "memory"
+ );
+
+# else /* Small version; ASSUMES nothing important gets put on the stack after the the alloca. */
+ uintptr_t *pauStack = (uintptr_t *)alloca(n + sizeof(uintptr_t));
+ invoke_copy_to_stack(paramCount, params, &pauStack[1]);
+# ifdef CFRONT_STYLE_THIS_ADJUST
+ struct CFRONTVTE { uintptr_t off, pfn } *pVtab = *(struct CFRONTVTE **)that;
+ pauStack[0] = (uintptr_t)that + pVtab[methodIndex + 1].off;
+ uintptr_t pfn = pVtab[methodIndex + 1].pfn;
+# elif defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ pauStack[0] = (uintptr_t)that;
+ uintptr_t pfn = (*(uintptr_t **)that)[methodIndex];
+# else /* not G++ V3 ABI */
+ pauStack[0] = (uintptr_t)that;
+ uintptr_t pfn = (*(uintptr_t **)that)[2 + methodIndex];
+# endif /* G++ V3 ABI */
+
+ __asm__ __volatile__(
+ "xchg %%esp, %3\n\t" /* save+load %esp */
+ "call *%0\n\t"
+ "xchg %%esp, %3\n\t" /* restore %esp */
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2) /* %2 */
+ : "S" (pauStack), /* %3 */
+ "0" (pfn)
+ : "memory"
+ );
+# endif
+
+# else /* !VBOX */
+ void (*fn_copy) (unsigned int, nsXPTCVariant *, PRUint32 *) = invoke_copy_to_stack;
+ __asm__ __volatile__(
+ "subl %8, %%esp\n\t" /* make room for params */
+ "pushl %%esp\n\t"
+ "pushl %7\n\t"
+ "pushl %6\n\t"
+ "call *%0\n\t" /* copy params */
+ "addl $0xc, %%esp\n\t"
+ "movl %4, %%ecx\n\t"
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+ "shl $3, %%eax\n\t" /* *= 8 */
+ "addl $8, %%eax\n\t" /* += 8 skip first entry */
+ "addl %%eax, %%edx\n\t"
+ "movswl (%%edx), %%eax\n\t" /* 'this' offset */
+ "addl %%eax, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "addl $4, %%edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "leal (%%edx,%%eax,4), %%edx\n\t"
+#else /* not G++ V3 ABI */
+ "leal 8(%%edx,%%eax,4), %%edx\n\t"
+#endif /* G++ V3 ABI */
+#endif
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+ "addl $4, %%esp\n\t"
+ "addl %8, %%esp"
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2), /* %2 */
+ "=g" (temp3) /* %3 */
+ : "g" (that), /* %4 */
+ "g" (methodIndex), /* %5 */
+ "1" (paramCount), /* %6 */
+ "2" (params), /* %7 */
+ "g" (n), /* %8 */
+ "0" (fn_copy) /* %3 */
+ : "memory"
+ );
+# endif /* !VBOX */
+
+ return result;
+#elif defined(__SUNPRO_CC) /* Sun Workshop Compiler. */
+
+asm(
+ "\n\t /: PRUint32 n = invoke_count_words (paramCount, params) * 4;"
+
+ "\n\t pushl %ebx / preserve ebx"
+ "\n\t pushl %esi / preserve esi"
+ "\n\t movl %esp, %ebx / save address of pushed esi and ebx"
+
+ "\n\t pushl 20(%ebp) / \"params\""
+ "\n\t pushl 16(%ebp) / \"paramCount\""
+ "\n\t call invoke_count_words"
+ "\n\t mov %ebx, %esp / restore esp"
+
+ "\n\t sall $2,%eax"
+ "\n\t subl %eax, %esp / make room for arguments"
+ "\n\t movl %esp, %esi / save new esp"
+
+ "\n\t pushl %esp"
+ "\n\t pushl 20(%ebp) / \"params\""
+ "\n\t pushl 16(%ebp) / \"paramCount\""
+ "\n\t call invoke_copy_to_stack / copy params"
+ "\n\t movl %esi, %esp / restore new esp"
+
+ "\n\t movl 8(%ebp),%ecx / \"that\""
+ "\n\t pushl %ecx / \"that\""
+ "\n\t movl (%ecx), %edx"
+ "\n\t movl 12(%ebp), %eax / function index: \"methodIndex\""
+ "\n\t movl 8(%edx,%eax,4), %edx"
+
+ "\n\t call *%edx"
+ "\n\t mov %ebx, %esp"
+ "\n\t popl %esi"
+ "\n\t popl %ebx"
+);
+
+/* result == %eax */
+ if(0) /* supress "*** is expected to return a value." error */
+ return 0;
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp
new file mode 100644
index 00000000..5b55c930
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const PRUint32 PARAM_BUFFER_COUNT = 16;
+const PRUint32 GPR_COUNT = 6;
+const PRUint32 FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex,
+ PRUint64 * args, PRUint64 * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint64* ap = args;
+ PRUint32 nr_gpr = 1; // skip one GPR register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = *(double*) ap++;
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// Darwin/AMD64 uses gcc >= 3.1
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ /*".type __ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n"*/ \
+ "__ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ /*".type __ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n"*/ \
+ "__ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ /*".type __ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n"*/ \
+ "__ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ /*".size __ZN14nsXPTCStubBase5Stub" #n "Ev,.-__ZN14nsXPTCStubBase5Stub" #n "Ev\n\t"*/ \
+ ".elseif " #n " < 100\n\t" \
+ /*".size __ZN14nsXPTCStubBase6Stub" #n "Ev,.-__ZN14nsXPTCStubBase6Stub" #n "Ev\n\t"*/ \
+ ".else\n\t" \
+ /*".size __ZN14nsXPTCStubBase7Stub" #n "Ev,.-__ZN14nsXPTCStubBase7Stub" #n "Ev\n\t"*/ \
+ ".endif");
+
+// static nsresult SharedStub(PRUint32 methodIndex) [methodIndex is in eax].
+asm(".text\n\t"
+ ".align 2\n\t"
+/* ".type SharedStub,@function\n\t" */
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call _PrepareAndDispatch\n\t"
+ "leave\n\t"
+ "ret\n\t"
+/* ".size SharedStub,.-SharedStub" */
+ );
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#else
+#error "Unsupported compiler. Use gcc >= 3.1 for Darwin/AMD64."
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp
new file mode 100644
index 00000000..fc90ecea
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp
@@ -0,0 +1,244 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Russell King <rmk@arm.linux.org.uk>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if !defined(LINUX) || !defined(__arm__)
+#error "This code is for Linux ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour."
+#endif
+
+/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */
+static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args) asm("_PrepareAndDispatch");
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * This is our shared stub.
+ *
+ * r0 = Self.
+ *
+ * The Rules:
+ * We pass an (undefined) number of arguments into this function.
+ * The first 3 C++ arguments are in r1 - r3, the rest are built
+ * by the calling function on the stack.
+ *
+ * We are allowed to corrupt r0 - r3, ip, and lr.
+ *
+ * Other Info:
+ * We pass the stub number in using `ip'.
+ *
+ * Implementation:
+ * - We save r1 to r3 inclusive onto the stack, which will be
+ * immediately below the caller saved arguments.
+ * - setup r2 (PrepareAndDispatch's args pointer) to point at
+ * the base of all these arguments
+ * - Save LR (for the return address)
+ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
+ * - r0 is passed through (self)
+ * - Call PrepareAndDispatch
+ * - When the call returns, we return by loading the PC off the
+ * stack, and undoing the stack (one instruction)!
+ *
+ */
+__asm__ ("\n\
+SharedStub: \n\
+ stmfd sp!, {r1, r2, r3} \n\
+ mov r2, sp \n\
+ str lr, [sp, #-4]! \n\
+ mov r1, ip \n\
+ bl _PrepareAndDispatch \n\
+ ldr pc, [sp], #16");
+
+/*
+ * Create sets of stubs to call the SharedStub.
+ * We don't touch the stack here, nor any registers, other than IP.
+ * IP is defined to be corruptable by a called function, so we are
+ * safe to use it.
+ *
+ * This will work with or without optimisation.
+ */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+/*
+ * Note : As G++3 ABI contains the length of the functionname in the
+ * mangled name, it is difficult to get a generic assembler mechanism like
+ * in the G++ 2.95 case.
+ * Create names would be like :
+ * _ZN14nsXPTCStubBase5Stub9Ev
+ * _ZN14nsXPTCStubBase6Stub13Ev
+ * _ZN14nsXPTCStubBase7Stub144Ev
+ * Use the assembler directives to get the names right...
+ */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".section \".text\"\n" \
+" .align 2\n" \
+" .iflt ("#n" - 10)\n" \
+" .globl _ZN14nsXPTCStubBase5Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 100)\n" \
+" .globl _ZN14nsXPTCStubBase6Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 1000)\n" \
+" .globl _ZN14nsXPTCStubBase7Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \
+" .else\n" \
+" .err \"stub number "#n"> 1000 not yet supported\"\n" \
+" .endif\n" \
+" .endif\n" \
+" .endif\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#if 0
+/*
+ * This part is left in as comment : this is how the method definition
+ * should look like.
+ */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n () \
+{ \
+ __asm__ ( \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t"); \
+ return 0; /* avoid warnings */ \
+}
+#endif
+
+#else /* G++2.95 ABI */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".section \".text\"\n" \
+" .align\n" \
+" .globl Stub"#n"__14nsXPTCStubBase\n" \
+" .type Stub"#n"__14nsXPTCStubBase,#function\n\n" \
+"Stub"#n"__14nsXPTCStubBase:\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
new file mode 100644
index 00000000..b6e1a9e8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
@@ -0,0 +1,272 @@
+/* $Id: xptcstubs_arm64_vbox.cpp $ */
+/** @file
+ * XPCOM - XPTC stubs for arm64.
+ */
+
+/*
+ * Copyright (C) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "xptcprivate.h"
+#include <iprt/cdefs.h>
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#if defined(RT_OS_DARWIN)
+# define NAME_PREFIX _
+# define NAME_PREFIX_STR "_"
+#else
+# define NAME_PREFIX
+# define NAME_PREFIX_STR ""
+#endif
+#define ASMNAME(a_Name) NAME_PREFIX ## a_Name
+#define NUM_ARGS_IN_GPRS 8 /**< Number of arguments passed in general purpose registers (starting with x0). */
+#define NUM_ARGS_IN_FPRS 8 /**< Number of arguments passed in floating point registers (starting with d0). */
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+extern "C" __attribute__((naked)) nsresult CommonXPTCStub(void);
+DECL_NO_INLINE(extern "C", nsresult)
+CommonXPTCStubCWorker(nsXPTCStubBase *pThis, uint32_t idxMethod, uint64_t *pauGprArgs, uint64_t *pauFprArgs, uint64_t *puStackArgs);
+
+
+/**
+ * All the stubs call this shared code w/ method index in w17.
+ *
+ * The naked attribute means pure inline assembly function. clang complains
+ * if we put C statements in it. So, this exacty what we need here and for the
+ * stubs.
+ *
+ * @note This could be static if we weren't afraid the compile would optimize it
+ * out.
+ */
+extern "C" __attribute__((naked)) nsresult CommonXPTCStub(void)
+{
+ __asm__ __volatile__(
+ /* Prologue - reserve space for frame+link reg spill and the GPR and FPR arrays. */ "\
+ sub sp, sp, %[cbGPRandFPRs] + 16 \n\
+ stp x29, x30, [sp, %[cbGPRandFPRs]] \n\
+ add x29, sp, %[cbGPRandFPRs] \n\
+ .cfi_def_cfa x29, 16 \n\
+ .cfi_rel_offset x30, -8 \n\
+ .cfi_rel_offset x29, -16 \n\
+"
+ /* reserve stack space for the integer and floating point registers and save them: */ "\
+ \n\
+ stp x0, x1, [sp, #0] \n\
+ stp x2, x3, [sp, #16] \n\
+ stp x4, x5, [sp, #32] \n\
+ stp x6, x7, [sp, #48] \n\
+ \n\
+ stp d0, d1, [sp, %[cbGPRs]] \n\
+ stp d2, d3, [sp, %[cbGPRs] + 16] \n\
+ stp d4, d5, [sp, %[cbGPRs] + 32] \n\
+ stp d6, d7, [sp, %[cbGPRs] + 48] \n\
+\n"
+ /* Call the C worker. We keep x0 as is.
+ Set w1 to the w17 method index from the stubs. */ "\
+ mov w1, w17 \n\
+ mov x2, sp \n\
+ add x3, sp, %[cbGPRs] \n\
+ add x4, sp, %[cbGPRandFPRs] + 16 \n\
+ bl " NAME_PREFIX_STR "CommonXPTCStubCWorker \n\
+"
+ /* Epilogue (clang does not emit the .cfi's here, so drop them too?): */ "\
+ ldp x29, x30, [sp, %[cbGPRandFPRs]] \n\
+ add sp, sp, %[cbGPRandFPRs] + 16 \n\
+ .cfi_def_cfa sp, 0 \n\
+ .cfi_restore x29 \n\
+ .cfi_restore x30 \n\
+ ret \n\
+" :
+ : [cbGPRandFPRs] "i" (NUM_ARGS_IN_GPRS * 8 + NUM_ARGS_IN_FPRS * 8)
+ , [cbGPRs] "i" (NUM_ARGS_IN_GPRS * 8)
+ :);
+}
+
+#define STUB_ENTRY(n) \
+ __attribute__((naked)) nsresult nsXPTCStubBase::Stub##n() \
+ { \
+ __asm__ __volatile__ ("mov w17, #" #n "\n\t" \
+ "b " NAME_PREFIX_STR "CommonXPTCStub\n\t"); \
+ }
+
+#define SENTINEL_ENTRY(n) \
+ nsresult nsXPTCStubBase::Sentinel##n() \
+ { \
+ AssertMsgFailed(("nsXPTCStubBase::Sentinel" #n " called!\n")); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+ }
+
+/* Instantiate the stubs and sentinels */
+#include "xptcstubsdef.inc"
+
+
+
+/*
+ * Function templates for fetching arguments
+ */
+
+template<typename Type> static inline void fetchStack(Type *pRet, uint64_t *&rpuStackArgs)
+{
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ Type *pStackTmp = RT_ALIGN_PT(rpuStackArgs, sizeof(Type), Type *);
+ *pRet = *pStackTmp;
+ rpuStackArgs = (uint64_t *)(pStackTmp + 1);
+#else
+ *pRet = (Type)*rpuStackArgs++;
+#endif
+}
+
+template<typename Type> static inline void fetchFpr(Type *pRet, uint64_t *pauFprArgs, unsigned &ridxFpr, uint64_t *&rpuStackArgs)
+{
+ if (ridxFpr < NUM_ARGS_IN_FPRS)
+ *pRet = (Type)pauFprArgs[ridxFpr++];
+ else
+ fetchStack(pRet, rpuStackArgs);
+}
+
+
+template<typename Type> static inline void fetchGpr(Type *pRet, uint64_t *pauGprArgs, unsigned &ridxGpr, uint64_t *&rpuStackArgs)
+{
+ if (ridxGpr < NUM_ARGS_IN_GPRS)
+ *pRet = (Type)pauGprArgs[ridxGpr++];
+ else
+ fetchStack(pRet, rpuStackArgs);
+}
+
+
+/**
+ * Called by CommonXPTCStub below after it dumps registers and locates
+ * arguments on the stack (if any).
+ */
+DECL_NO_INLINE(extern "C", nsresult)
+CommonXPTCStubCWorker(nsXPTCStubBase *pThis, uint32_t idxMethod, uint64_t *pauGprArgs, uint64_t *pauFprArgs, uint64_t *puStackArgs)
+{
+ AssertReturn(pThis, NS_ERROR_UNEXPECTED);
+
+ /* Get method information: */
+ nsIInterfaceInfo *pInterfaceInfo = NULL;
+ nsresult hrc = pThis->GetInterfaceInfo(&pInterfaceInfo);
+ AssertReturn(NS_SUCCEEDED(hrc), hrc);
+ AssertReturn(pInterfaceInfo, NS_ERROR_UNEXPECTED);
+
+ const nsXPTMethodInfo *pMethodInfo;
+ hrc = pInterfaceInfo->GetMethodInfo((PRUint16)idxMethod, &pMethodInfo);
+ AssertReturn(NS_SUCCEEDED(hrc), hrc);
+ AssertReturn(pMethodInfo, NS_ERROR_UNEXPECTED);
+
+ /* Allocate dispatcher parameter array. */
+ PRUint8 const cParams = pMethodInfo->GetParamCount();
+ nsXPTCMiniVariant aParamsStatic[8];
+ nsXPTCMiniVariant *paParams;
+ if (cParams <= RT_ELEMENTS(aParamsStatic))
+ paParams = aParamsStatic;
+ else
+ {
+ paParams = (nsXPTCMiniVariant *)alloca(sizeof(paParams[0]) * cParams);
+ AssertReturn(paParams, NS_ERROR_UNEXPECTED);
+ }
+
+ /*
+ * Populate the dispatcher parameter array.
+ */
+ unsigned idxGprArgs = 1; /* The 'pThis' pointer (x0) is not included in cParams. */
+ unsigned idxFprArgs = 0;
+ for (PRUint8 i = 0; i < cParams; i++)
+ {
+ const nsXPTParamInfo &rParam = pMethodInfo->GetParam(i);
+ if (rParam.IsOut())
+ fetchGpr(&paParams[i].val.p, pauGprArgs, idxGprArgs, puStackArgs);
+ else
+ {
+ const nsXPTType Type = rParam.GetType();
+ switch (Type)
+ {
+ case nsXPTType::T_I8: fetchGpr(&paParams[i].val.i8, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_I16: fetchGpr(&paParams[i].val.i16, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_I32: fetchGpr(&paParams[i].val.i32, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_I64: fetchGpr(&paParams[i].val.i64, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U8: fetchGpr(&paParams[i].val.u8, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U16: fetchGpr(&paParams[i].val.u16, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U32: fetchGpr(&paParams[i].val.u32, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U64: fetchGpr(&paParams[i].val.u64, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_BOOL: fetchGpr(&paParams[i].val.b, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_CHAR: fetchGpr(&paParams[i].val.c, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_WCHAR: fetchGpr(&paParams[i].val.wc, pauGprArgs, idxGprArgs, puStackArgs); break;
+
+ case nsXPTType::T_FLOAT: fetchFpr(&paParams[i].val.f, pauFprArgs, idxFprArgs, puStackArgs); break;
+ case nsXPTType::T_DOUBLE: fetchFpr(&paParams[i].val.d, pauFprArgs, idxFprArgs, puStackArgs); break;
+
+ default:
+ if (!Type.IsArithmetic())
+ fetchGpr(&paParams[i].val.p, pauGprArgs, idxGprArgs, puStackArgs);
+ else
+ AssertMsgFailedReturn(("%#x idxMethod=%#x\n",(unsigned)Type, idxMethod), NS_ERROR_UNEXPECTED);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Dispatch the method call.
+ */
+ hrc = pThis->CallMethod((PRUint16)idxMethod, pMethodInfo, paParams);
+
+ NS_RELEASE(pInterfaceInfo);
+ return hrc;
+
+}
+
+#if 0
+extern "C" nsresult CommonXPTCStubTest(uint64_t x0,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ uint64_t x5,
+ uint64_t x6,
+ uint64_t x7)
+{
+ uint64_t aGprs[8];
+ aGprs[0] = x0;
+ aGprs[1] = x1;
+ aGprs[2] = x2;
+ aGprs[3] = x3;
+ aGprs[4] = x4;
+ aGprs[5] = x5;
+ aGprs[6] = x6;
+ aGprs[7] = x7;
+
+ return CommonXPTCStubCWorker((nsXPTCStubBase *)x0, x1, aGprs, aGprs, aGprs);
+}
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp
new file mode 100644
index 00000000..47c09a42
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * These stubs move just move the values passed in registers onto the stack,
+ * so they are contiguous with values passed on the stack, and then calls
+ * PrepareAndDispatch() to do the dirty work.
+ */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "stmfd sp!, {r1, r2, r3} \n\t" \
+ "mov ip, sp \n\t" \
+ "stmfd sp!, {fp, ip, lr, pc} \n\t" \
+ "sub fp, ip, #4 \n\t" \
+ "mov r1, #"#n" \n\t" /* = methodIndex */ \
+ "add r2, sp, #16 \n\t" \
+ "bl _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \
+ "ldmea fp, {fp, sp, lr} \n\t" \
+ "add sp, sp, #12 \n\t" \
+ "mov pc, lr \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s
new file mode 100644
index 00000000..591e88e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s
@@ -0,0 +1,124 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi32
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 9 arguments, first 8 are the input arguments of previous
+// function call. The last one is methodIndex, and is passed in memory
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ nop.i 0 ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// current frame is 144 bytes, previous frame is 112 bytes
+// restarg is at 144 + 112 + 16 bytes away from current sp
+// (current frame + previous frame + previous previous frame header)
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ add out4 = 192, sp // A restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s
new file mode 100644
index 00000000..177b2646
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s
@@ -0,0 +1,124 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi64
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 9 arguments, first 8 are the input arguments of previous
+// function call. The last one is methodIndex, and is passed in memory
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ nop.i 0 ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// current frame is 144 bytes, previous frame is 112 bytes
+// restarg is at 144 + 112 + 16 bytes away from current sp
+// (current frame + previous frame + previous previous frame header)
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ add out4 = 192, sp // A restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s
new file mode 100644
index 00000000..4ca1e542
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s
@@ -0,0 +1,97 @@
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+ .text
+ .globl PrepareAndDispatch
+
+LOCALSZ=16
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+A1OFF=FRAMESZ-(9*SZREG)
+A2OFF=FRAMESZ-(8*SZREG)
+A3OFF=FRAMESZ-(7*SZREG)
+A4OFF=FRAMESZ-(6*SZREG)
+A5OFF=FRAMESZ-(5*SZREG)
+A6OFF=FRAMESZ-(4*SZREG)
+A7OFF=FRAMESZ-(3*SZREG)
+GPOFF=FRAMESZ-(2*SZREG)
+RAOFF=FRAMESZ-(1*SZREG)
+
+F13OFF=FRAMESZ-(16*SZREG)
+F14OFF=FRAMESZ-(15*SZREG)
+F15OFF=FRAMESZ-(14*SZREG)
+F16OFF=FRAMESZ-(13*SZREG)
+F17OFF=FRAMESZ-(12*SZREG)
+F18OFF=FRAMESZ-(11*SZREG)
+F19OFF=FRAMESZ-(10*SZREG)
+
+#define SENTINEL_ENTRY(nn) /* defined in cpp file, not here */
+
+#ifdef __GNUC__
+#define STUB_ENTRY(nn) MAKE_STUB(nn, Stub/**/nn/**/__14nsXPTCStubBase)
+#else
+#define STUB_ENTRY(nn) MAKE_STUB(nn, Stub/**/nn/**/__14nsXPTCStubBaseGv)
+#endif
+
+#define MAKE_STUB(nn, name) \
+NESTED(name, FRAMESZ, ra); \
+ SETUP_GP; \
+ PTR_SUBU sp, FRAMESZ; \
+ SETUP_GP64(GPOFF, name); \
+ SAVE_GP(GPOFF); \
+ li t0, nn; \
+ b sharedstub; \
+.end name; \
+
+#include "xptcstubsdef.inc"
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S a4, A4OFF(sp)
+ REG_S a5, A5OFF(sp)
+ REG_S a6, A6OFF(sp)
+ REG_S a7, A7OFF(sp)
+ REG_S ra, RAOFF(sp)
+
+ s.d $f13, F13OFF(sp)
+ s.d $f14, F14OFF(sp)
+ s.d $f15, F15OFF(sp)
+ s.d $f16, F16OFF(sp)
+ s.d $f17, F17OFF(sp)
+ s.d $f18, F18OFF(sp)
+ s.d $f19, F19OFF(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # a2 is stack address where extra function params
+ # are stored that do not fit in registers
+ move a2, sp
+ addi a2, FRAMESZ
+
+ # a3 is stack address of a1..a7
+ move a3, sp
+ addi a3, A1OFF
+
+ # a4 is stack address of f13..f19
+ move a4, sp
+ addi a4, F13OFF
+
+ # PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
+ # a0 a1 a2 a3 a4
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, RAOFF(sp)
+ REG_L gp, GPOFF(sp)
+
+ PTR_ADDU sp, FRAMESZ
+ j ra
+
+.end sharedstub
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4 b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4
new file mode 100644
index 00000000..f327adfb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4
@@ -0,0 +1,109 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Waterson <waterson@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+ .text
+ .globl PrepareAndDispatch
+
+NARGSAVE=4 # extra space for the callee to use. gccism
+ # we can put our a0-a3 in our callers space.
+LOCALSZ=2 # gp, ra
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+define(STUB_NAME, `Stub'$1`__14nsXPTCStubBase')
+
+define(STUB_ENTRY,
+` .globl 'STUB_NAME($1)`
+ .align 2
+ .type 'STUB_NAME($1)`,@function
+ .ent 'STUB_NAME($1)`, 0
+'STUB_NAME($1)`:
+ .frame sp, FRAMESZ, ra
+ .set noreorder
+ .cpload t9
+ .set reorder
+ subu sp, FRAMESZ
+ .cprestore 16
+ li t0, '$1`
+ b sharedstub
+.end 'STUB_NAME($1)`
+
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+
+ REG_S ra, 20(sp)
+
+ REG_S a0, 24(sp)
+ REG_S a1, 28(sp)
+ REG_S a2, 32(sp)
+ REG_S a3, 36(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # put the start of a1, a2, a3, and stack
+ move a2, sp
+ addi a2, 24 # have a2 point to sp + 24 (where a0 is)
+
+ # PrepareAndDispatch(that, methodIndex, args)
+ # a0 a1 a2
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, 20(sp)
+ REG_L a1, 28(sp)
+ REG_L a2, 32(sp)
+
+ addu sp, FRAMESZ
+ j ra
+
+.end sharedstub
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s
new file mode 100644
index 00000000..9f04d4c4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s
@@ -0,0 +1,115 @@
+;* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+;*
+;* The contents of this file are subject to the Netscape 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/NPL/
+;*
+;* Software distributed under the License is distributed on an "AS
+;* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+;* implied. See the License for the specific language governing
+;* rights and limitations under the License.
+;*
+;* The Original Code is mozilla.org code.
+;*
+;* The Initial Developer of the Original Code is Netscape
+;* Communications Corporation. Portions created by Netscape are
+;* Copyright (C) 1999 Netscape Communications Corporation. All
+;* Rights Reserved.
+;*
+;* Contributor(s):
+;*/
+
+; Implement shared vtbl methods.
+
+ .title "STUBS" "Stub Code"
+
+ MBIT = "__14nsXPTCStubBasexv" ; this is the mangled part of the name
+
+; The layout of the linkage section is important. First comes
+; PrepareAndDispatch, and then the Procedure Descriptors for the stubs. Each
+; is known to be 16 bytes long, and we use this fact to be able to locate the
+; PrepareAndDispatch linkage pair from any of the stubs.
+
+ .PSECT $LINK$, OCTA, NOPIC, CON, REL, LCL, NOSHR, NOEXE, RD, NOWRT
+ .LINKAGE_PAIR PrepareAndDispatch
+ LINKOFF = 16 ; first stub lp will be 16 bytes away
+
+; STUB_ENTRY createa a routine nsXPTCStubBase::Stub<n>() where n is the
+; argument passed in to STUB_ENTRY. It puts its stub number into R1 and then
+; jumps into SharedStub. It does it this way because we don't want to mess
+; up the arguments that may be on the stack. In order that we can find
+; our way around the linkage section, we subtract our offset from the
+; start of the linkage section (LINKOFF) from our own PV, thus giving
+; us the PV os the first entry in the linkage section (this should be
+; PrepareAndDispatch);
+
+ .macro STUB_ENTRY n
+ $routine Stub'n%MBIT%, kind=null
+ mov LINKOFF, r1 ; distance from lp for PrepareAndDispatch
+ subq r27,r1,r27 ; subtract it from address of our proc desc
+ mov n,r1 ; stub number is passed in r1
+ br SharedStub ; off to common code
+ $end_routine
+ LINKOFF = LINKOFF + 16 ; we just put 16 bytes into linkage section
+ .endm STUB_ENTRY
+
+; SENTINEL_ENTRY is in the C++ module. We need to define a empty macro
+; here to keep the assembler happy.
+ .macro SENTINEL_ENTRY n
+ .endm SENTINEL_ENTRY
+
+ .PSECT $CODE$, OCTA, PIC, CON, REL, LCL, SHR, EXE, NORD, NOWRT
+
+;
+; SharedStub()
+; Collects arguments and calls PrepareAndDispatch.
+;
+; r1 - The "methodIndex"
+; r27 - points to the first entry in the linkage section, which by design
+; is the linkage pair for PrepareAndDispatch.
+;
+; Arguments are passed in a non-standard way so that we don't disturb the
+; original arguments that were passed in to the stub. Since some args (if
+; there were more than 6) will already be on the stack, the stub had to not
+; only preserve R16-R21, but also preserve the stack too.
+;
+
+SharedStub::
+ subq sp,96,sp ; get some stack space for the args and saves
+ stq r26,0(sp) ; save r26 (the return address)
+
+ ;
+ ; Store arguments passed via registers to the stack.
+ ; Floating point registers are stored as doubles and converted
+ ; to floats in PrepareAndDispatch if necessary.
+ ;
+ stt f17,16(sp) ; floating point registers
+ stt f18,24(sp)
+ stt f19,32(sp)
+ stt f20,40(sp)
+ stt f21,48(sp)
+ stq r17,56(sp) ; integer registers
+ stq r18,64(sp)
+ stq r19,72(sp)
+ stq r20,80(sp)
+ stq r21,88(sp)
+
+ ;
+ ; Call PrepareAndDispatch function.
+ ;
+ mov r1,r17 ; pass "methodIndex"
+ addq sp,16,r18 ; pass "args"
+ mov 3,r25 ; number of args into AI
+
+ LDQ R26, 0(R27) ; get entry point address from linkage pair
+ LDQ R27, 8(R27) ; get procedure descriptor address from lp
+ JSR R26, R26
+
+ ldq r26, 0(sp) ; restore return address
+ addq sp,96,sp ; return stack space
+ ret r26 ; and we're outta here
+
+ .include "xptcstubsdef_asm.vms"
+
+ .end
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s
new file mode 100644
index 00000000..3bef9b1b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s
@@ -0,0 +1,75 @@
+ .text
+ .align 5
+ .globl SharedStub
+ .ent SharedStub
+SharedStub:
+ .frame $30, 96, $26, 0
+ .mask 0x4000000,-96
+ ldgp $29,0($27)
+SharedStubXv:
+ subq $30,96,$30
+ stq $26,0($30)
+ .prologue 1
+ stt $f17,16($30)
+ stt $f18,24($30)
+ stt $f19,32($30)
+ stt $f20,40($30)
+ stt $f21,48($30)
+ stq $17,56($30)
+ stq $18,64($30)
+ stq $19,72($30)
+ stq $20,80($30)
+ stq $21,88($30)
+ bis $1,$1,$17
+ addq $30,16,$18
+ bsr $26,PrepareAndDispatch
+ ldq $26,0($30)
+ addq $30,96,$30
+ ret $31,($26),1
+ .end SharedStub
+
+/*
+ The C preprocessor doesn't handle # and ## if run with -std or -std0.
+
+ If -std then __STDC__ is 0 [default] (K&R behavior)
+ If -std0 then __STDC__ is undefined (K&R behavior)
+ If -std1 then __STDC__ is 1 (ANSI preprocessor)
+*/
+
+#if __STDC__
+#define STUB_ENTRY(n) ;\
+ .text ;\
+ .align 5 ;\
+ .globl Stub##n##__14nsXPTCStubBase ;\
+ .globl Stub##n##__14nsXPTCStubBaseXv ;\
+ .ent Stub##n##__14nsXPTCStubBase ;\
+Stub##n##__14nsXPTCStubBase: ;\
+ .frame $30,0,$26,0 ;\
+ ldgp $29,0($27) ;\
+ .prologue 1 ;\
+Stub##n##__14nsXPTCStubBaseXv: ;\
+ lda $1,n ;\
+ br $31,SharedStubXv ;\
+ .end Stub##n##__14nsXPTCStubBase \
+
+#else
+#define STUB_ENTRY(n) ;\
+ .text ;\
+ .align 5 ;\
+ .globl Stub/**/n/**/__14nsXPTCStubBase ;\
+ .globl Stub/**/n/**/__14nsXPTCStubBaseXv ;\
+ .ent Stub/**/n/**/__14nsXPTCStubBase ;\
+Stub/**/n/**/__14nsXPTCStubBase: ;\
+ .frame $30,0,$26,0 ;\
+ ldgp $29,0($27) ;\
+ .prologue 1 ;\
+Stub/**/n/**/__14nsXPTCStubBaseXv: ;\
+ lda $1,n ;\
+ br $31,SharedStubXv ;\
+ .end Stub/**/n/**/__14nsXPTCStubBase \
+
+#endif
+
+#define SENTINEL_ENTRY(n) \
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s
new file mode 100644
index 00000000..9e86848f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s
@@ -0,0 +1,68 @@
+ .LEVEL 1.1
+
+curframesz .EQU 128
+; SharedStub has stack size of 128 bytes
+
+lastframesz .EQU 64
+; the StubN C++ function has a small stack size of 64 bytes
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+SharedStub
+ .PROC
+ .CALLINFO CALLER,FRAME=80,SAVE_RP,ARGS_SAVED
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ LDO 128(%sp),%sp
+
+ STW %r19,-32(%r30)
+ STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame
+
+ LDO -80(%r30),%r28
+ FSTD,MA %fr5,8(%r28) ; save darg0
+ FSTD,MA %fr7,8(%r28) ; save darg1
+ FSTW,MA %fr4L,4(%r28) ; save farg0
+ FSTW,MA %fr5L,4(%r28) ; save farg1
+ FSTW,MA %fr6L,4(%r28) ; save farg2
+ FSTW,MA %fr7L,4(%r28) ; save farg3
+
+ ; Former value of register 26 is already properly saved by StubN,
+ ; but register 25-23 are not because of the arguments mismatch
+ STW %r25,-40-curframesz-lastframesz(%r30) ; save r25
+ STW %r24,-44-curframesz-lastframesz(%r30) ; save r24
+ STW %r23,-48-curframesz-lastframesz(%r30) ; save r23
+ COPY %r26,%r25 ; method index is arg1
+ LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0
+ LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2
+ LDO -80(%r30),%r23 ; floating args is arg3
+
+ BL .+8,%r2
+ ADDIL L'PrepareAndDispatch-$PIC_pcrel$0+4,%r2
+ LDO R'PrepareAndDispatch-$PIC_pcrel$1+8(%r1),%r1
+$PIC_pcrel$0
+ LDSID (%r1),%r31
+$PIC_pcrel$1
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=23-26;out=28;
+ BLE 0(%sr0,%r1)
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDO -128(%sp),%sp
+
+
+ .PROCEND ;in=26;out=28;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT PrepareAndDispatch,CODE
+ .EXPORT SharedStub,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s
new file mode 100644
index 00000000..667da705
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s
@@ -0,0 +1,117 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # Software distributed under the License is distributed on an "AS
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ # implied. See the License for the specific language governing
+ # rights and limitations under the License.
+ #
+ # The Original Code is mozilla.org code.
+ #
+ # The Initial Developer of the Original Code is Netscape
+ # Communications Corporation. Portions created by Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+
+
+#jimbo csect CODE{PR}
+#
+# on entry SharedStub has the method selector in r12, the rest of the original
+# parameters are in r3 thru r10 and f1 thru f13
+#
+#jimbo import .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ stw r0,8(sp)
+
+ mr r12,r3 # Move methodIndex into r12 for LATER
+ lwz r3,104(sp) # Get the 'original' r3
+
+ stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28)
+ # outgoing params to PrepareAndDispatch (20)
+
+ stw r4,44(sp)
+ stw r5,48(sp)
+ stw r6,52(sp)
+ stw r7,56(sp)
+ stw r8,60(sp)
+ stw r9,64(sp)
+ stw r10,68(sp)
+ stfd f1,72(sp)
+ stfd f2,80(sp)
+ stfd f3,88(sp)
+ stfd f4,96(sp)
+ stfd f5,104(sp)
+ stfd f6,112(sp)
+ stfd f7,120(sp)
+ stfd f8,128(sp)
+ stfd f9,136(sp)
+ stfd f10,144(sp)
+ stfd f11,152(sp)
+ stfd f12,156(sp)
+ stfd f13,164(sp)
+
+ addi r6,sp,44 # gprData
+ addi r7,sp,72 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,312 # pointer to callers args area, beyond r3-r10 mapped range
+
+ bl .PrepareAndDispatch
+ nop
+
+ lwz r0,184(sp)
+ addi sp,sp,176
+ mtlr r0
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+
+ .csect SharedStub{DS}
+ .long .SharedStub # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s
new file mode 100644
index 00000000..94245d5e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s
@@ -0,0 +1,137 @@
+# ***** BEGIN LICENSE BLOCK *****
+#
+# Version: MPL 1.1/LGPL 2.1/GPL 2.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 mozilla.org code.
+#
+# The Initial Developer of the Original Code is IBM Corporation.
+# Portions created by IBM are
+# Copyright (C) 2002, International Business Machines Corporation.
+# All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the LGPL or the GPL. 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 *****
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+
+
+#jimbo csect CODE{PR}
+#
+# on entry SharedStub has the method selector in r12, the rest of the original
+# parameters are in r3 thru r10 and f1 thru f13
+#
+#jimbo import .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ std r0,16(sp)
+
+ mr r12,r3 # Move methodIndex into r12 for LATER
+ ld r3,176(sp) # Get the 'original' r3 (load 'this' into r3)
+
+ stdu sp,-248(sp) # room for linkage (24*2), fprData (104),
+ # gprData(28*2), outgoing params to
+ # PrepareAndDispatch (40)
+
+ std r4,88(sp) # link area (48) + PrepareAndDispatch parms (40)
+ std r5,96(sp)
+ std r6,104(sp)
+ std r7,112(sp)
+ std r8,120(sp)
+ std r9,128(sp)
+ std r10,136(sp)
+ stfd f1,144(sp)
+ stfd f2,152(sp)
+ stfd f3,160(sp)
+ stfd f4,168(sp)
+ stfd f5,176(sp)
+ stfd f6,184(sp)
+ stfd f7,192(sp)
+ stfd f8,200(sp)
+ stfd f9,208(sp)
+ stfd f10,216(sp)
+ stfd f11,224(sp)
+ stfd f12,232(sp)
+ stfd f13,240(sp)
+
+ addi r6,sp,88 # gprData
+ addi r7,sp,144 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,488 # pointer to callers args area, beyond r3-r10
+ # mapped range
+ # 32bit: 176 (stack-distance) 64bit: 248 (stack-distance)
+ # 104 (this ptr offset) 176
+ # 32 (8*4 for r3-r10) 64 (8*8)
+ # --- ---
+ # 312 488
+
+ bl .PrepareAndDispatch
+ nop
+
+ ld r0,264(sp) # 248+16
+ addi sp,sp,248
+ mtlr r0
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+
+ .csect SharedStub{DS}
+ .llong .SharedStub # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4 b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4
new file mode 100644
index 00000000..60dbd7c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4
@@ -0,0 +1,126 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License") ; you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2002
+ * 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 ***** */
+
+ .text
+ .globl _SharedStub
+
+define(STUB_MANGLED_ENTRY,
+` .globl '$2`
+ .align 2
+'$2`:
+ addi r12, 0, '$1`
+ b _SharedStub
+')
+
+define(STUB_ENTRY,
+`#ifdef HAVE_GCC3_ABI
+ .if '$1` < 10
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase5Stub'$1`Ev')
+ .elseif '$1` < 100
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase6Stub'$1`Ev')
+ .elseif '$1` < 1000
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase7Stub'$1`Ev')
+ .else
+ .err "Stub'$1` >= 1000 not yet supported."
+ .endif
+#else /* !defined(HAVE_GCC3_ABI) */
+STUB_MANGLED_ENTRY('$1`, `_Stub'$1`__14nsXPTCStubBase')
+#endif /* !defined(HAVE_GCC3_ABI) */
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+_SharedStub:
+ mflr r0
+ stw r0,8(r1)
+
+ stwu r1,-176(r1)
+
+ stw r4,44(r1)
+ stw r5,48(r1)
+ stw r6,52(r1)
+ stw r7,56(r1)
+ stw r8,60(r1)
+ stw r9,64(r1)
+ stw r10,68(r1)
+ stfd f1,72(r1)
+ stfd f2,80(r1)
+ stfd f3,88(r1)
+ stfd f4,96(r1)
+ stfd f5,104(r1)
+ stfd f6,112(r1)
+ stfd f7,120(r1)
+ stfd f8,128(r1)
+ stfd f9,136(r1)
+ stfd f10,144(r1)
+ stfd f11,152(r1)
+ stfd f12,156(r1)
+ stfd f13,164(r1)
+
+ addi r6,r1,44
+ addi r7,r1,72
+
+ mr r4,r12
+ addi r5,r1,232
+
+ bl L_PrepareAndDispatch$stub
+ nop
+
+ lwz r0,184(r1)
+ addi r1,r1,176
+ mtlr r0
+ blr
+
+.picsymbol_stub
+L_PrepareAndDispatch$stub:
+ .indirect_symbol _PrepareAndDispatch
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _PrepareAndDispatch
+ .long dyld_stub_binding_helper
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s
new file mode 100644
index 00000000..fc85bdb9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s
@@ -0,0 +1,89 @@
+// -*- Mode: Asm -*-
+//
+// The contents of this file are subject to the Netscape 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/NPL/
+//
+// Software distributed under the License is distributed on an "AS
+// IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+// implied. See the License for the specific language governing
+// rights and limitations under the License.
+//
+// The Original Code is mozilla.org code.
+//
+// The Initial Developer of the Original Code is Netscape
+// Communications Corporation. Portions created by Netscape are
+// Copyright (C) 1999 Netscape Communications Corporation. All
+// Rights Reserved.
+//
+// Contributor(s):
+// Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+// beard@netscape.com (Patrick Beard)
+// waterson@netscape.com (Chris Waterson)
+//
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) // room for
+ // linkage (8),
+ // gprData (32),
+ // fprData (64),
+ // stack alignment(8)
+ mflr r0
+ stw r0,116(sp) // save LR backchain
+
+ stw r4,12(sp) // save GP registers
+ stw r5,16(sp) // (n.b. that we don't save r3
+ stw r6,20(sp) // because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) // save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ // r3 has the 'self' pointer already
+
+ mr r4,r11 // r4 <= methodIndex selector, passed
+ // via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 // r5 <= pointer to callers args area,
+ // beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 // r6 <= gprData
+ addi r7,sp,40 // r7 <= fprData
+
+ bl PrepareAndDispatch@local // Go!
+
+ lwz r0,116(sp) // restore LR
+ mtlr r0
+ la sp,112(sp) // clean up the stack
+ blr
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s
new file mode 100644
index 00000000..f94aac4f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s
@@ -0,0 +1,89 @@
+# -*- Mode: Asm -*-
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1999 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+# beard@netscape.com (Patrick Beard)
+# waterson@netscape.com (Chris Waterson)
+#
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) # room for
+ # linkage (8),
+ # gprData (32),
+ # fprData (64),
+ # stack alignment(8)
+ mflr r0
+ stw r0,116(sp) # save LR backchain
+
+ stw r4,12(sp) # save GP registers
+ stw r5,16(sp) # (n.b. that we don't save r3
+ stw r6,20(sp) # because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) # save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ # r3 has the 'self' pointer already
+
+ mr r4,r11 # r4 <= methodIndex selector, passed
+ # via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 # r5 <= pointer to callers args area,
+ # beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 # r6 <= gprData
+ addi r7,sp,40 # r7 <= fprData
+
+ bl PrepareAndDispatch@local # Go!
+
+ lwz r0,116(sp) # restore LR
+ mtlr r0
+ la sp,112(sp) # clean up the stack
+ blr
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s
new file mode 100644
index 00000000..4a8a4698
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1999 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, PRUint32 index, PRUint32* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s
new file mode 100644
index 00000000..4a8a4698
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1999 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, PRUint32 index, PRUint32* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s
new file mode 100644
index 00000000..e3bbcf8b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s
@@ -0,0 +1,67 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 2001 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ stx %i1, [%fp + 0x7ff + 136]
+ stx %i2, [%fp + 0x7ff + 144]
+ stx %i3, [%fp + 0x7ff + 152]
+ stx %i4, [%fp + 0x7ff + 160]
+ stx %i5, [%fp + 0x7ff + 168]
+! now we can build our own stack frame
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, PRUint32 index, PRUint32* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp
new file mode 100644
index 00000000..351ee512
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#ifdef __GNUC__ /* Gnu Compiler. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static nsresult ATTRIBUTE_USED
+__attribute__ ((regparm (3)))
+PrepareAndDispatch(uint32 methodIndex, nsXPTCStubBase* self, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+} // extern "C"
+
+// NOTE! See xptc_gcc_x86_unix.h for the reason this function exists.
+#if (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ == 0))
+PRUint32
+xptc_PrepareAndDispatch_keeper (void)
+{
+ PRUint32 dummy1;
+ nsresult ATTRIBUTE_USED __attribute__ ((regparm (3))) (*dummy2)
+ (uint32, nsXPTCStubBase *, PRUint32*) = PrepareAndDispatch;
+// dummy2 references PrepareAndDispatch, now "use" it
+ __asm__ __volatile__ (
+ ""
+ : "=&a" (dummy1)
+ : "g" (dummy2)
+ );
+ return dummy1 & 0xF0F00000;
+}
+#endif
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// gcc3 mangling tends to insert the length of the method name
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+#else
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase\n\t" \
+ ".type " SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase,@function\n" \
+ SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase:\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".size " SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase,.-" SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase");
+#endif
+
+// static nsresult SharedStub(PRUint32 methodIndex) __attribute__((regparm(1)))
+asm(".text\n\t"
+ ".align 2\n\t"
+ ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
+ SYMBOL_UNDERSCORE "SharedStub:\n\t"
+ "leal 0x08(%esp), %ecx\n\t"
+ "movl 0x04(%esp), %edx\n\t"
+ "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
+ ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp
new file mode 100644
index 00000000..844f55dd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp
@@ -0,0 +1,185 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "xptcprivate.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ PRUint8 paramCount;
+ PRUint8 i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(PRUint64,PRUint64,PRUint64,PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(PRUint64 a1, \
+PRUint64 a2,PRUint64 a3,PRUint64 a4,PRUint64 a5,PRUint64 a6,PRUint64 a7) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(PRUint64) n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp
new file mode 100644
index 00000000..6a11f692
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp
@@ -0,0 +1,186 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "xptcprivate.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ PRUint8 paramCount;
+ PRUint8 i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(PRUint64,PRUint64,PRUint64,PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(PRUint64 a1, \
+PRUint64 a2,PRUint64 a3,PRUint64 a4,PRUint64 a5,PRUint64 a6,PRUint64 a7) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(PRUint64) n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp
new file mode 100644
index 00000000..556b5bbe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp
@@ -0,0 +1,226 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+
+#if defined(IRIX)
+
+#if (_MIPS_SIM != _ABIN32)
+#error "This code is for IRIX N32 only"
+#endif
+
+/*
+ * This is for IRIX N32 ABI
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. There are 8 regs
+ * available which coorespond to the first 7 parameters of the
+ * function and the "this" pointer. If there are additional parms,
+ * they are stored on the stack at address "args".
+ *
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint64* args,
+ PRUint64 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+#define PARAM_FPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ PRUint32 iCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8)gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8)*ap++;
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16)gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16)*ap++;
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32)gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32)*ap++;
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (PRInt64)gprData[iCount++];
+ else
+ dp->val.i64 = (PRInt64)*ap++;
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8)gprData[iCount++];
+ else
+ dp->val.u8 = (PRUint8)*ap++;
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16)gprData[iCount++];
+ else
+ dp->val.u16 = (PRUint16)*ap++;
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32)gprData[iCount++];
+ else
+ dp->val.u32 = (PRUint32)*ap++;
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (PRUint64)gprData[iCount++];
+ else
+ dp->val.u64 = (PRUint64)*ap++;
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = (double)fprData[iCount++];
+ else
+ dp->val.f = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool)gprData[iCount++];
+ else
+ dp->val.b = (PRBool)*ap++;
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = (char)*ap++;
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t)*ap++;
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp
new file mode 100644
index 00000000..e5b1c642
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp
@@ -0,0 +1,236 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Glen Nakamura <glen@imodulo.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+__asm__("PrepareAndDispatch") __attribute__((unused));
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+{
+ const PRUint8 PARAM_BUFFER_COUNT = 16;
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ PRUint64* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (PRInt8) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (PRInt16) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (PRInt32) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (PRInt64) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (PRUint8) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (PRUint16) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (PRUint32) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (PRUint64) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (PRUint64) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (PRUint32) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (PRBool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (PRUnichar) *ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * SharedStub()
+ * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is
+ * passed to this function via $1 to preserve the argument registers.
+ */
+__asm__(
+ "#### SharedStub ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".ent SharedStub\n"
+"SharedStub:\n\t"
+ ".frame $30,96,$26,0\n\t"
+ ".mask 0x4000000,-96\n\t"
+ "ldgp $29,0($27)\n"
+"$SharedStub..ng:\n\t"
+ "subq $30,96,$30\n\t"
+ "stq $26,0($30)\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Store arguments passed via registers to the stack.
+ * Floating point registers are stored as doubles and converted
+ * to floats in PrepareAndDispatch if necessary.
+ */
+ "stt $f17,16($30)\n\t" /* floating point registers */
+ "stt $f18,24($30)\n\t"
+ "stt $f19,32($30)\n\t"
+ "stt $f20,40($30)\n\t"
+ "stt $f21,48($30)\n\t"
+ "stq $17,56($30)\n\t" /* integer registers */
+ "stq $18,64($30)\n\t"
+ "stq $19,72($30)\n\t"
+ "stq $20,80($30)\n\t"
+ "stq $21,88($30)\n\t"
+
+ /*
+ * Call PrepareAndDispatch function.
+ */
+ "bis $1,$1,$17\n\t" /* pass "methodIndex" */
+ "addq $30,16,$18\n\t" /* pass "args" */
+ "bsr $26,$PrepareAndDispatch..ng\n\t"
+
+ "ldq $26,0($30)\n\t"
+ "addq $30,96,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end SharedStub"
+ );
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n()
+ * Sets register $1 to "methodIndex" and jumps to SharedStub.
+ */
+#define STUB_MANGLED_ENTRY(n, symbol) \
+ "#### Stub"#n" ####" "\n\t" \
+ ".text" "\n\t" \
+ ".align 5" "\n\t" \
+ ".globl " symbol "\n\t" \
+ ".ent " symbol "\n" \
+symbol ":" "\n\t" \
+ ".frame $30,0,$26,0" "\n\t" \
+ "ldgp $29,0($27)" "\n" \
+"$" symbol "..ng:" "\n\t" \
+ ".prologue 1" "\n\t" \
+ "lda $1,"#n "\n\t" \
+ "br $31,$SharedStub..ng" "\n\t" \
+ ".end " symbol
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".if "#n" < 10" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 100" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 1000" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \
+ ".else" "\n\t" \
+ ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \
+ ".endif" \
+ );
+
+#else /* not G++ V3 ABI */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ STUB_MANGLED_ENTRY(n, "Stub"#n"__14nsXPTCStubBase") \
+ );
+
+#endif /* G++ V3 ABI */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp
new file mode 100644
index 00000000..eb094762
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+extern "C" {
+ nsresult
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((PRInt8*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((PRInt16*) ap) + 1); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(((PRUint8*) ap) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((PRUint16*)ap) + 1); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "lea %/a6@(12), %/a0\n\t" /* args */ \
+ "movl %/a0, %/sp@-\n\t" \
+ "movl #"#n", %/sp@-\n\t" /* method index */ \
+ "movl %/a6@(8), %/sp@-\n\t" /* this */ \
+ "jbsr PrepareAndDispatch\n\t" \
+ "movl %/d0, %0\n\t" \
+ "addl #12, %/sp" \
+ : "=d" (result) /* %0 */ \
+ : \
+ : "a0", "a1", "d0", "d1", "memory" ); \
+ return result; \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp
new file mode 100644
index 00000000..0f8502cd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex,
+ PRUint32* a_gpr, PRUint64 *a_fpr, PRUint32 *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32 gpr = 1, fpr = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((PRInt32*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((PRInt32*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((PRInt32*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((PRInt32*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((PRInt32*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((PRInt32*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ dp->val.i64 = *((PRInt64*) a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.i64 = *((PRInt64*) a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ dp->val.u64 = *((PRUint64*)a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.u64 = *((PRUint64*)a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *((float*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ PRUint32 a_gpr[4]; \
+ PRUint64 a_fpr[2]; \
+ PRUint32 *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "l %0,0(15)\n\t" \
+ "ahi %0,96\n\t" \
+ "stm 3,6,0(%3)\n\t" \
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp
new file mode 100644
index 00000000..9a645dd1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp
@@ -0,0 +1,224 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex,
+ PRUint64* a_gpr, PRUint64 *a_fpr, PRUint64 *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32 gpr = 1, fpr = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ dp->val.i64 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i64 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ dp->val.u64 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u64 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *(((float*) a_ov )+1), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ PRUint64 a_gpr[4]; \
+ PRUint64 a_fpr[4]; \
+ PRUint64 *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "lg %0,0(15)\n\t" \
+ "aghi %0,160\n\t" \
+ "stmg 3,6,0(%5)\n\t"\
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ "std 4,%3\n\t" \
+ "std 6,%4\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]), \
+ "=m" (a_fpr[2]), \
+ "=m" (a_fpr[3]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
new file mode 100644
index 00000000..4d60f7be
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
@@ -0,0 +1,131 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xptcprivate.h"
+
+/*
+ * This is for MIPS O32 ABI
+ * Args contains a0-3 and then the stack.
+ * Because a0 is 'this', we want to skip it
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args)
+{
+ args++; // always skip over a0
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ dp->val.p = (void*) *ap;
+
+ switch(type)
+ {
+ case nsXPTType::T_I64 :
+ if ((PRWord)ap & 4) ap++;
+ dp->val.i64 = *((PRInt64*) ap); ap++;
+ break;
+ case nsXPTType::T_U64 :
+ if ((PRWord)ap & 4) ap++;
+ dp->val.u64 = *((PRInt64*) ap); ap++;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((PRWord)ap & 4) ap++;
+ dp->val.d = *((double*) ap); ap++;
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) // done in the .s file
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp
new file mode 100644
index 00000000..4069a6bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static nsresult
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((PRInt8*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((PRInt16*) ap) + 1); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(((PRUint8*) ap) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((PRUint16*)ap) + 1); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "link a6,#0 \n\t" \
+ "lea a6@(12), a0 \n\t" /* pointer to args */ \
+ "movl a0, sp@- \n\t" \
+ "movl #"#n", sp@- \n\t" /* method index */ \
+ "movl a6@(8), sp@- \n\t" /* this */ \
+ "jbsr _PrepareAndDispatch \n\t" \
+ "unlk a6 \n\t" \
+ "rts \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp
new file mode 100644
index 00000000..c4d1b364
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+extern "C" {
+
+nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+{
+ const PRUint8 PARAM_BUFFER_COUNT = 16;
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ PRUint64* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (PRInt8) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (PRInt16) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (PRInt32) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (PRInt64) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (PRUint8) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (PRUint16) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (PRUint32) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (PRUint64) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (PRUint64) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (PRUint32) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (PRBool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (PRUnichar) *ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+}
+
+#define STUB_ENTRY(n) /* This is in the ASM file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp
new file mode 100644
index 00000000..cd8fe40b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+/* contributed by Glen Nakamura <glen.nakamura@usa.net> */
+
+#include "xptcprivate.h"
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+{
+ const PRUint8 PARAM_BUFFER_COUNT = 16;
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ PRUint64* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (PRInt8) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (PRInt16) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (PRInt32) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (PRInt64) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (PRUint8) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (PRUint16) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (PRUint32) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (PRUint64) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (PRUint64) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (PRUint32) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (PRBool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (PRUnichar) *ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n() ;\
+ * Sets arguments to registers and calls PrepareAndDispatch.
+ * This is defined in the ASM file.
+ */
+#define STUB_ENTRY(n) \
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp
new file mode 100644
index 00000000..b3a42442
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp
@@ -0,0 +1,176 @@
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ PRUint32* args, PRUint32* floatargs)
+{
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU;
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRInt32 regwords = 1; /* self pointer is not in the variant records */
+ nsresult result = NS_ERROR_FAILURE;
+ PRUint8 paramCount;
+ PRUint8 i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; ++i, --args)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *args;
+ ++regwords;
+ continue;
+ }
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) args); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) args); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) args); break;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ if (regwords == 0 || regwords == 2)
+ {
+ dp->val.d=*((double*) (floatargs + regwords));
+ --args;
+ }
+ else
+ {
+ dp->val.d = *((double*) --args);
+ }
+ regwords += 2;
+ continue;
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ ((DU *)dp)->lo = *((PRUint32*) args);
+ ((DU *)dp)->hi = *((PRUint32*) --args);
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ if (regwords >= 4)
+ dp->val.f = *((float*) args);
+ else
+ dp->val.f = *((float*) floatargs+4+regwords);
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) args); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*) args); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*) args); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) args); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) args); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) args); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ ++regwords;
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp
new file mode 100644
index 00000000..870669d7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp
@@ -0,0 +1,228 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args, PRUint32 *gprData, double *fprData)
+{
+ typedef struct {
+ uint32 hi;
+ uint32 lo; // have to move 64 bit entities as 32 bit halves since
+ } DU; // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (PRInt32) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (PRInt32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (PRUint32) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.u8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.u16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.u32 = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (PRUint32) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (PRUint32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (PRUint32) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+} \
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp
new file mode 100644
index 00000000..cf2ddba9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp
@@ -0,0 +1,215 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/LGPL 2.1/GPL 2.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 mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM are
+ * Copyright (C) 2002, International Business Machines Corporation.
+ * All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the LGPL or the GPL. 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint64 methodIndex, PRUint64* args, PRUint64 *gprData, double *fprData)
+{
+
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (PRInt64) gprData[iCount++];
+ else
+ dp->val.i64 = (PRInt64) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.u8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.u16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.u32 = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (PRUint64) gprData[iCount++];
+ else
+ dp->val.u64 = (PRUint64) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+} \
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp
new file mode 100644
index 00000000..b1c98571
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self,
+ PRUint32 methodIndex,
+ PRUint32* args,
+ PRUint32 *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (! iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ PRUint32 gpr = 1; // skip one GPR register
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((PRUint32) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+#if __GXX_ABI_VERSION < 100
+// gcc-2 version
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".globl Stub"#n"__14nsXPTCStubBase \n\t" \
+ ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \
+ \
+"Stub"#n"__14nsXPTCStubBase: \n\t" \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+#else
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp
new file mode 100644
index 00000000..68d572ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp
@@ -0,0 +1,217 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self,
+ PRUint32 methodIndex,
+ PRUint32* args,
+ PRUint32 *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (! iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ PRUint32 gpr = 1; // skip one GPR register
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((PRUint32) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ if (gpr < GPR_COUNT)
+ gpr += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else {
+ dp->val.f = *(float*) ap;
+ ap += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+#define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".globl Stub"#n"__14nsXPTCStubBase \n\t" \
+ ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \
+ \
+"Stub"#n"__14nsXPTCStubBase: \n\t" \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp
new file mode 100644
index 00000000..fcf96d4f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp
@@ -0,0 +1,254 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/*
+ For mac, the first 8 integral and the first 13 f.p. parameters arrive
+ in a separate chunk of data that has been loaded from the registers. The
+ args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args, PRUint32 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ // fprintf(stderr, "PrepareAndDispatch %p, %d, %p, %p, %p\n", self, methodIndex, args, gprData, fprData);
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+
+ case nsXPTType::T_I64 :
+ {
+ PRUint64 tempu64;
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+ }
+ break;
+
+#if 0
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRInt32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+ break;
+#endif
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRUint32) *ap++;
+ break;
+
+ case nsXPTType::T_U64 :
+#if 0
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRUint32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+#endif
+ {
+ PRUint64 tempu64;
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+ }
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+
+#define STUB_ENTRY(n)
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp
new file mode 100644
index 00000000..cbed6041
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+{
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp
new file mode 100644
index 00000000..cbed6041
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+{
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp
new file mode 100644
index 00000000..f64b309e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint64 methodIndex, PRUint64* args)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp
new file mode 100644
index 00000000..91c5c5db
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp
@@ -0,0 +1,188 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+/*#include "xptiprivate.h"*/
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#ifdef __GNUC__ /* Gnu Compiler. */
+
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+/* Make sure the stack is 16-byte aligned. Do that by aligning to 16 bytes and
+ * then subtracting 4 so the three subsequent pushes result in a 16-byte aligned
+ * stack. */
+#define ALIGN_STACK_DECL \
+ unsigned int saved_esp = 0; /* VBOX: Initialize it to shut up half a million gcc warnings on darwin.
+ * ALIGN_STACK_REGS_OUT/IN are a bit bogus, so the warning is probably correct. */
+
+#define ALIGN_STACK_SAVE \
+ "movl %%esp, %3\n\t"
+
+#define ALIGN_STACK_ALIGN \
+ "addl $0x4, %%esp\n\t" \
+ "andl $0xfffffff0, %%esp\n\t" \
+ "subl $0x4, %%esp\n\t"
+
+#define STACK_RESTORE \
+ "movl %3, %%esp\n"
+
+#define ALIGN_STACK_REGS_IN \
+ , "=r"(saved_esp) /* 3 */
+
+#define ALIGN_STACK_REGS_OUT \
+ , "3"(saved_esp)
+
+#else
+#define ALIGN_STACK_DECL
+#define ALIGN_STACK_SAVE
+#define ALIGN_STACK_ALIGN
+#define STACK_RESTORE \
+ "addl $12, %%esp\n"
+#define ALIGN_STACK_REGS_IN
+#define ALIGN_STACK_REGS_OUT
+#endif
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult (*method) (nsXPTCStubBase *, uint32, PRUint32 *) = PrepareAndDispatch; \
+ int temp0, temp1; \
+ register nsresult result; \
+ ALIGN_STACK_DECL \
+ __asm__ __volatile__( \
+ ALIGN_STACK_SAVE \
+ ALIGN_STACK_ALIGN \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx\n\t" /* PrepareAndDispatch */ \
+ STACK_RESTORE /* "addl $12, %%esp" or restore saved */ \
+ : "=a" (result), /* %0 */ \
+ "=&c" (temp0), /* %1 */ \
+ "=d" (temp1) /* %2 */ \
+ ALIGN_STACK_REGS_IN \
+ : "2" (method) /* %2 */ \
+ ALIGN_STACK_REGS_OUT \
+ : "memory" \
+ ); \
+ return result; \
+}
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp
new file mode 100644
index 00000000..0eea6567
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Stub called on unsupported platform"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
new file mode 100644
index 00000000..3381c48e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
@@ -0,0 +1,242 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const PRUint32 PARAM_BUFFER_COUNT = 16;
+const PRUint32 GPR_COUNT = 6;
+const PRUint32 FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex,
+ PRUint64 * args, PRUint64 * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint64* ap = args;
+ PRUint32 nr_gpr = 1; // skip one GPR register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = *(double*) ap++;
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// Linux/x86-64 uses gcc >= 3.1
+#define STUB_ENTRY(n) \
+asm(".section \".text\"\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size _ZN14nsXPTCStubBase5Stub" #n "Ev,.-_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size _ZN14nsXPTCStubBase6Stub" #n "Ev,.-_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size _ZN14nsXPTCStubBase7Stub" #n "Ev,.-_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+
+// static nsresult SharedStub(PRUint32 methodIndex)
+asm(".section \".text\"\n\t"
+ ".align 2\n\t"
+ ".type SharedStub,@function\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call PrepareAndDispatch@plt\n\t"
+ "leave\n\t"
+ "ret\n\t"
+ ".size SharedStub,.-SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#else
+#error "Unsupported compiler. Use gcc >= 3.1 for Linux/x86-64."
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp
new file mode 100644
index 00000000..59e0202f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp
@@ -0,0 +1,271 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+// Solaris does the same, just the assembler may differ.
+
+const PRUint32 PARAM_BUFFER_COUNT = 16;
+const PRUint32 GPR_COUNT = 6;
+const PRUint32 FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex,
+ PRUint64 * args, PRUint64 * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint64* ap = args;
+ PRUint32 nr_gpr = 1; // skip one GPR register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = *(double*) ap++;
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#include <iprt/cdefs.h>
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// Solaris/x86-64 uses gcc >= 3.1
+#define STUB_ENTRY(n,m) \
+asm(".section .text\n\t" \
+ ".align 2\n\t" \
+ ".globl _ZN14nsXPTCStubBase" #m "Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase" #m "Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase" #m "Stub" #n "Ev:\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".size _ZN14nsXPTCStubBase" #m "Stub" #n "Ev,.-_ZN14nsXPTCStubBase" #m "Stub" #n "Ev\n\t" \
+ )
+
+#define STUB_ENTRY_10(n10,m) \
+ STUB_ENTRY(n10##0,m); \
+ STUB_ENTRY(n10##1,m); \
+ STUB_ENTRY(n10##2,m); \
+ STUB_ENTRY(n10##3,m); \
+ STUB_ENTRY(n10##4,m); \
+ STUB_ENTRY(n10##5,m); \
+ STUB_ENTRY(n10##6,m); \
+ STUB_ENTRY(n10##7,m); \
+ STUB_ENTRY(n10##8,m); \
+ STUB_ENTRY(n10##9,m)
+STUB_ENTRY_10(,5);
+STUB_ENTRY_10(1,6);
+STUB_ENTRY_10(2,6);
+STUB_ENTRY_10(3,6);
+STUB_ENTRY_10(4,6);
+STUB_ENTRY_10(5,6);
+STUB_ENTRY_10(6,6);
+STUB_ENTRY_10(7,6);
+STUB_ENTRY_10(8,6);
+STUB_ENTRY_10(9,6);
+STUB_ENTRY_10(10,7);
+STUB_ENTRY_10(11,7);
+STUB_ENTRY_10(12,7);
+STUB_ENTRY_10(13,7);
+STUB_ENTRY_10(14,7);
+STUB_ENTRY_10(15,7);
+STUB_ENTRY_10(16,7);
+STUB_ENTRY_10(17,7);
+STUB_ENTRY_10(18,7);
+STUB_ENTRY_10(19,7);
+STUB_ENTRY_10(20,7);
+STUB_ENTRY_10(21,7);
+STUB_ENTRY_10(22,7);
+STUB_ENTRY_10(23,7);
+STUB_ENTRY_10(24,7);
+
+
+// static nsresult SharedStub(PRUint32 methodIndex)
+asm(".section .text\n\t"
+ ".align 2\n\t"
+ ".type SharedStub,@function\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call PrepareAndDispatch@plt\n\t"
+ "leave\n\t"
+ "ret\n\t"
+ ".size SharedStub,.-SharedStub");
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+SENTINEL_ENTRY(0)
+SENTINEL_ENTRY(1)
+SENTINEL_ENTRY(2)
+SENTINEL_ENTRY(3)
+SENTINEL_ENTRY(4)
+
+#else
+#error "Unsupported compiler. Use gcc >= 3.1 for Linux/x86-64."
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp
new file mode 100644
index 00000000..d4ae7667
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp
@@ -0,0 +1,165 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#ifdef __GNUC__ /* Gnu Compiler. */
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult (*method) (nsXPTCStubBase *, uint32, PRUint32 *) = PrepareAndDispatch; \
+ int temp0, temp1; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx\n\t" /* PrepareAndDispatch */ \
+ "addl $12, %%esp" \
+ : "=a" (result), /* %0 */ \
+ "=&c" (temp0), /* %1 */ \
+ "=d" (temp1) /* %2 */ \
+ : "2" (method) /* %2 */ \
+ : "memory" ); \
+ return result; \
+}
+
+#elif defined(__SUNPRO_CC) /* Sun Workshop Compiler. */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ asm ( \
+ "\n\t leal 0x0c(%ebp), %ecx\t / args" \
+ "\n\t pushl %ecx" \
+ "\n\t pushl $"#n"\t / method index" \
+ "\n\t movl 0x08(%ebp), %ecx\t / this" \
+ "\n\t pushl %ecx" \
+ "\n\t call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_\t / PrepareAndDispatch" \
+ "\n\t addl $12, %esp" \
+ ); \
+/* result == %eax */ \
+ if(0) /* supress "*** is expected to return a value." error */ \
+ return 0; \
+}
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in
new file mode 100644
index 00000000..0de74ee2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in
@@ -0,0 +1,82 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xptcmd
+
+#
+# The default is this buildable, but non-functioning code.
+#
+ifdef GNU_CXX
+CPPSRCS = \
+ ../unix/xptcinvoke_gcc_x86_unix.cpp \
+ xptcstubs.cpp \
+ $(NULL)
+LOCAL_INCLUDES = -I$(srcdir)/../unix
+DEFINES += -DMOZ_USE_STDCALL -DMOZ_NEED_LEADING_UNDERSCORE
+else
+CPPSRCS = xptcinvoke.cpp xptcstubs.cpp
+endif
+
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(CPU),ALPHA)
+CPPSRCS := xptcinvoke_alpha.cpp xptcstubs_alpha.cpp
+ASFILES := xptcinvoke_asm_alpha.s xptcstubs_asm_alpha.s
+AS := asaxp
+ASFLAGS += /I../../..public
+endif
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
+LOCAL_INCLUDES += -I$(srcdir)/../..
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
new file mode 100644
index 00000000..9fbf2f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+static void __fastcall
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ for(; paramCount > 0; paramCount--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint16*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+#pragma warning(disable : 4035) // OK to have no return value
+__declspec(naked) XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ __asm {
+ push ebp
+ mov ebp,esp
+ mov edx,paramCount // Save paramCount for later
+ test edx,edx // maybe we don't have any params to copy
+ jz noparams
+ mov eax,edx
+ shl eax,3 // *= 8 (max possible param size)
+ sub esp,eax // make space for params
+ mov ecx,esp
+ push params
+ call invoke_copy_to_stack // fastcall, ecx = d, edx = paramCount, params is on the stack
+noparams:
+ mov ecx,that // instance in ecx
+ push ecx // push this
+ mov edx,[ecx] // vtable in edx
+ mov eax,methodIndex
+ call [edx][eax*4] // stdcall, i.e. callee cleans up stack.
+ mov esp,ebp
+ pop ebp
+ ret
+ }
+}
+#pragma warning(default : 4035) // restore default
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp
new file mode 100644
index 00000000..06334ac0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp
@@ -0,0 +1,171 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+/* contributed by bob meader <bob@guiduck.com> */
+
+#include "xptcprivate.h"
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return(paramCount*2);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount,
+ nsXPTCVariant* s, PRUint64 *regs)
+{
+#define N_ARG_REGS 5 /* 6 regs minus 1 for "this" ptr */
+
+ for (PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if (s->IsPtrData()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint32)s->ptr;
+ else
+ *((PRUint32*)d++) = (PRUint32)s->ptr;
+ continue;
+ }
+ switch (s->type) {
+ //
+ // signed types first
+ //
+ case nsXPTType::T_I8:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i8;
+ else
+ *((PRInt8 *)d++) = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i16;
+ else
+ *((PRInt16 *)d++) = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i32;
+ else
+ *((PRUint32*)d++) = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i64;
+ else
+ *((PRInt64*)d++) = s->val.i64;
+ break;
+ //
+ // unsigned types next
+ //
+ case nsXPTType::T_U8:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u8;
+ else
+ *((PRUint8 *)d++) = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u16;
+ else
+ *((PRUint16 *)d++) = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u32;
+ else
+ *((PRUint32*)d++) = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u64;
+ else
+ *((PRUint64*)d++) = s->val.u64;
+ break;
+ case nsXPTType::T_FLOAT:
+ if (i < N_ARG_REGS)
+ ((double*)regs)[i] = s->val.f;
+ else
+ *((float*)d++) = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (i < N_ARG_REGS)
+ ((double*)regs)[i] = s->val.d;
+ else
+ *((double*)d++) = s->val.d;
+ break;
+ case nsXPTType::T_BOOL:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.b;
+ else
+ *((PRBool*)d++) = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.c;
+ else
+ *((char*)d++) = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.wc;
+ else
+ *((wchar_t*)d++) = s->val.wc;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint32)s->val.p;
+ else
+ *((PRUint32*)d++) = (PRUint32)s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult XPTC__InvokebyIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return XPTC__InvokebyIndex(that, methodIndex, paramCount, params);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s
new file mode 100644
index 00000000..7f8b343b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s
@@ -0,0 +1,128 @@
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+#define v0 $0
+#define t0 $1
+#define t1 $2
+#define t2 $3
+#define t3 $4
+#define s0 $9
+#define fp $15
+#define a0 $16
+#define a1 $17
+#define a2 $18
+#define a3 $19
+#define a4 $20
+#define a5 $21
+#define t9 $23
+#define ra $26
+#define gp $29
+#define sp $30
+#define zero $31
+#define f0 $f0
+
+#define LOCALSZ 7
+#define NARG 2
+#define SZREG 8
+#define FRAMESZ ((NARG+LOCALSZ)*SZREG)
+RAOFF=FRAMESZ-(1*SZREG)
+A0OFF=FRAMESZ-(2*SZREG)
+A1OFF=FRAMESZ-(3*SZREG)
+A2OFF=FRAMESZ-(4*SZREG)
+A3OFF=FRAMESZ-(5*SZREG)
+S0OFF=FRAMESZ-(6*SZREG)
+GPOFF=FRAMESZ-(7*SZREG)
+
+//
+// Nested
+// XPTC__InvokebyIndex( that, methodIndex, paramCount, params)
+// a0 a1 a2 a3
+//
+ .text
+ .align 4
+ .globl XPTC__InvokebyIndex
+ .ent XPTC__InvokebyIndex,0
+XPTC__InvokebyIndex:
+ .frame sp, FRAMESZ, ra
+ subl sp,FRAMESZ,sp // allocate stack space for structure
+ stq ra, RAOFF(sp)
+ stq a0, A0OFF(sp)
+ stq a1, A1OFF(sp)
+ stq a2, A2OFF(sp)
+ stq a3, A3OFF(sp)
+ stq s0, S0OFF(sp)
+// stq gp, GPOFF(sp) Don't think I am to save gp
+
+ // invoke_count_words(paramCount, params)
+ bis a2,zero,a0 // move a2 into a0
+ bis a3,zero,a1 // move a3 into a1
+ bsr ra,invoke_count_words
+
+ // invoke_copy_to_stack
+ ldq a1, A2OFF(sp) // a1 = paramCount
+ ldq a2, A3OFF(sp) // a2 = params
+
+ // save sp before we copy the params to the stack
+ bis sp,zero,t0 // t0 = sp
+
+ // assume full size of 8 bytes per param to be safe
+ sll v0,4,v0 //v0 = 8 bytes * num params
+ subl sp,v0,sp //sp = sp - v0
+ bis sp,zero,a0 //a0 = param stack address
+
+ // create temporary stack space to write int and fp regs
+ subl sp,64,sp //sp = sp -64 // (64 = 8 regs of eight bytes)
+ bis sp,zero,a3 // a3 = sp
+
+ // save the old sp and save the arg stack
+ subl sp,16,sp //sp = sp -16
+ stq t0,0(sp)
+ stq a0,8(sp)
+ // copy the param into the stack areas
+ bsr ra,invoke_copy_to_stack
+
+ ldq t3,8(sp) // get previous a0
+ ldq sp,0(sp) // get orig sp back
+
+ ldq a0,A0OFF(sp) // a0 = that
+ ldq a1,A1OFF(sp) // a1 = methodIndex
+
+ // calculate jmp address from method index
+ ldl t1,0(a0) // t1 = *that
+ sll a1,2,a1 // a1 = 4*index
+ addl t1,a1,t9
+ ldl t9,0(t9) // t9=*(that + 4*index)
+
+ // get register save area from invoke_copy_to_stack
+ subl t3,64,t1
+
+ // a1..a5 and f17..f21 should now be set to what
+ // invoke_copy_to_stack told us. skip a0 and f16
+ // because that's the "this" pointer
+
+ ldq a1,0(t1)
+ ldq a2,8(t1)
+ ldq a3,16(t1)
+ ldq a4,24(t1)
+ ldq a5,32(t1)
+
+ ldt $f17,0(t1)
+ ldt $f18,8(t1)
+ ldt $f19,16(t1)
+ ldt $f20,24(t1)
+ ldt $f21,32(t1)
+
+ // save away our stack point and create
+ // the stack pointer for the function
+ bis sp,zero,s0
+ bis t3,zero,sp
+ jsr ra,(t9)
+ bis s0,zero,sp
+ ldq ra,RAOFF(sp)
+ ldq s0,S0OFF(sp)
+ addl sp,FRAMESZ,sp
+ ret
+
+.end XPTC__InvokebyIndex
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp
new file mode 100644
index 00000000..bd5ab975
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" {
+
+static nsresult __stdcall
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ PRUint32* args, PRUint32* stackBytesToPop)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+ *stackBytesToPop = ((PRUint32)ap) - ((PRUint32)args);
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+} // extern "C"
+
+// declspec(naked) is broken in gcc
+#ifndef __GNUC__
+static
+__declspec(naked)
+void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea eax, [ebp+12] // pointer to args
+ push eax
+ push ecx // vtbl_index
+ mov eax, [ebp+8] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+4] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 8 // for 'this' and return address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+__declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ __asm mov ecx, n __asm jmp SharedStub }
+
+#else
+
+#define STUB_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ \
+ PRUint32 *args, stackBytesToPop = 0; \
+ nsresult result = 0; \
+ nsXPTCStubBase *obj; \
+ __asm__ __volatile__ ( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "movl 0x08(%%ebp), %%edx\n\t" /* this */ \
+ : "=c" (args), \
+ "=d" (obj)); \
+ result = PrepareAndDispatch(obj, n, args, &stackBytesToPop); \
+ return result; \
+}
+
+#endif /* __GNUC__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4035) // OK to have no return value
+#endif
+#include "xptcstubsdef.inc"
+#ifdef _MSC_VER
+#pragma warning(default : 4035) // restore default
+#endif
+
+void
+#ifdef __GNUC__
+__cdecl
+#endif
+xptc_dummy()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp
new file mode 100644
index 00000000..69a10e70
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp
@@ -0,0 +1,228 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/* contributed by bob meader <bob@guiduck.com> */
+
+/*
+ * This is for Alpha /NT 32 bits
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. There are 6 regs
+ * available which coorespond to the first 5 parameters of the
+ * function and the "this" pointer. If there are additional parms,
+ * they are stored on the stack at address "args".
+ *
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint64* args,
+ PRUint64 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 5
+#define PARAM_FPR_COUNT 5
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ PRUint32 iCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8)gprData[iCount++];
+ else
+ dp->val.i8 = *((PRInt8*)ap++);
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16)gprData[iCount++];
+ else
+ dp->val.i16 = *((PRInt16*)ap++);
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32)gprData[iCount++];
+ else
+ dp->val.i32 = *((PRInt32*)ap++);
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (PRInt64)gprData[iCount++];
+ else
+ dp->val.i64 = *((PRInt64*)ap++);
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8)gprData[iCount++];
+ else
+ dp->val.u8 = *((PRUint8*)ap++);
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16)gprData[iCount++];
+ else
+ dp->val.u16 = *((PRUint16*)ap++);
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32)gprData[iCount++];
+ else
+ dp->val.u32 = *((PRUint32*)ap++);
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (PRUint64)gprData[iCount++];
+ else
+ dp->val.u64 = (PRUint64)*ap++;
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = (float)fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool)gprData[iCount++];
+ else
+ dp->val.b = *((PRBool*)ap++);
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = *((char*)ap++);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = *((wchar_t*)ap++);
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s
new file mode 100644
index 00000000..5f8f861d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s
@@ -0,0 +1,120 @@
+
+#define v0 $0 // return value register
+#define t0 $1 // caller saved (temporary) registers
+#define t1 $2 //
+#define t2 $3 //
+#define t3 $4 //
+#define t4 $5 //
+#define t5 $6 //
+#define t6 $7 //
+#define t7 $8 //
+#define s0 $9 // callee saved (nonvolatile) registers
+#define a0 $16 // argument registers
+#define a1 $17 //
+#define a2 $18 //
+#define a3 $19 //
+#define a4 $20 //
+#define a5 $21 //
+#define t8 $22 // caller saved (temporary) registers
+#define t9 $23 //
+#define t10 $24 //
+#define t11 $25 //
+#define ra $26 // return address register
+#define sp $30 // stack pointer register
+#define zero $31 // zero register
+#define f16 $f16 // argument registers
+#define f17 $f17 //
+#define f18 $f18 //
+#define f19 $f19 //
+#define f20 $f20 //
+#define f21 $f21 //
+
+#define NARGSAVE 2
+#define LOCALSZ 16
+#define SZREG 8
+#define FRAMESZ (NARGSAVE+LOCALSZ)*SZREG
+
+ .text
+ .globl PrepareAndDispatch
+
+A1OFF=FRAMESZ-(9*SZREG)
+A2OFF=FRAMESZ-(8*SZREG)
+A3OFF=FRAMESZ-(7*SZREG)
+A4OFF=FRAMESZ-(6*SZREG)
+A5OFF=FRAMESZ-(5*SZREG)
+A6OFF=FRAMESZ-(4*SZREG) //not used
+A7OFF=FRAMESZ-(3*SZREG) //not used
+GPOFF=FRAMESZ-(2*SZREG) //not used
+RAOFF=FRAMESZ-(1*SZREG)
+
+F16OFF=FRAMESZ-(16*SZREG) //not used
+F17OFF=FRAMESZ-(15*SZREG)
+F18OFF=FRAMESZ-(14*SZREG)
+F19OFF=FRAMESZ-(13*SZREG)
+F20OFF=FRAMESZ-(12*SZREG)
+F21OFF=FRAMESZ-(11*SZREG)
+F22OFF=FRAMESZ-(10*SZREG) // not used
+
+#define NESTED_ENTRY(Name, fsize, retrg) \
+ .text; \
+ .align 4; \
+ .globl Name; \
+ .ent Name, 0; \
+Name:; \
+ .frame sp, fsize, retrg;
+
+#define SENTINEL_ENTRY(nn)
+#define STUB_ENTRY(nn) MAKE_PART(nn,@nsXPTCStubBase@@UAAIXZ )
+
+#define MAKE_PART(aa, bb) MAKE_STUB(aa, ?Stub##aa##bb )
+
+#define MAKE_STUB(nn, name) \
+NESTED_ENTRY(name, FRAMESZ,ra); \
+ subl sp,FRAMESZ,sp; \
+ mov nn,t0; \
+ jmp sharedstub; \
+.end name;
+
+#include "xptcstubsdef.inc"
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+ stq a1,A1OFF(sp)
+ stq a2,A2OFF(sp)
+ stq a3,A3OFF(sp)
+ stq a4,A4OFF(sp)
+ stq a5,A5OFF(sp)
+ stq ra,RAOFF(sp)
+
+ stt f17,F17OFF(sp)
+ stt f18,F18OFF(sp)
+ stt f19,F19OFF(sp)
+ stt f20,F20OFF(sp)
+ stt f21,F21OFF(sp)
+
+ // t0 is methodIndex
+ bis t0,zero,a1 // a1 = methodIndex
+
+ // a2 is stack address where extra function params
+ // are stored that do not fit in registers
+ bis sp,zero,a2 //a2 = sp
+ addl a2,FRAMESZ,a2 //a2+=FRAMESZ
+
+ // a3 is stack addrss of a1..a5
+ bis sp,zero,a3 //a3 = sp
+ addl a3,A1OFF,a3 //a3+=A1OFF
+
+ // a4 is stack address of f17..f21
+ bis sp,zero,a4 //a4 = sp
+ addl a4,F17OFF,a4 //a4+=F17OFF
+
+ // PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
+ // a0 a1 a2 a3 a4
+ bsr PrepareAndDispatch
+ ldq ra,RAOFF(sp)
+ addl sp,FRAMESZ,sp
+ ret
+
+.end sharedstub
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp
new file mode 100644
index 00000000..f25a94e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* entry point wrappers. */
+
+#if defined(XP_MAC)
+#pragma export on
+#endif
+
+#include "xptcprivate.h"
+
+// This method is never called and is only here so the compiler
+// will generate a vtbl for this class.
+// *Needed by the Irix implementation.*
+NS_IMETHODIMP nsXPTCStubBase::QueryInterface(REFNSIID aIID,
+ void** aInstancePtr)
+{
+ NS_ASSERTION(0,"wowa! nsXPTCStubBase::QueryInterface called");
+ return NS_ERROR_FAILURE;
+}
+#if defined(XP_MAC)
+#pragma export off
+#endif
+
+void
+xptc_dummy2()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h
new file mode 100644
index 00000000..3691fa0a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* All the xptcall private declarations - only include locally. */
+
+#ifndef xptcprivate_h___
+#define xptcprivate_h___
+
+#include "xptcall.h"
+
+#endif /* xptcprivate_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html b/src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html
new file mode 100644
index 00000000..e3686999
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html
@@ -0,0 +1,404 @@
+<html>
+<head>
+<title>xptcall Porting Status</title>
+</head>
+<body bgcolor = "white">
+<h2><center>xptcall Porting Status</center></h2>
+
+<h3>What is this?</h3>
+
+This is a status page for the multiplatform porting of xptcall.
+xptcall has a
+<a href="http://www.mozilla.org/scriptable/xptcall-faq.html">FAQ</a>
+and a
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html">Porting Guide</a>.
+
+<p>
+
+This is being maintained by <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a>.
+Feel free to email me with questions or to volunteer to contribute xptcall code for any platform.
+
+<p>
+
+<a href="mailto:shaver@mozilla.org">Mike Shaver &lt;shaver@mozilla.org&gt;</a>
+is the best contact regarding 'nix (Unix, Linux, Finux, etc.) ports of xptcall.
+
+<h3>Status</h3>
+
+<table BORDER="1">
+<TR align="left" BGCOLOR="yellow">
+<TH>Status</TH>
+<TH>Platform</TH>
+<TH><img src="http://tinderbox.mozilla.org/star.gif">Contributors and <font color="red"><b>?</b></font> Possible Contributors</TH>
+<TH>Notes</TH>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Win32 x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a>
+</TD>
+<TD>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a></TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:drepper@cygnus.com">Ulrich Drepper &lt;drepper@cygnus.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>FreeBSD and NetBSD x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:toshok@hungry.com">Christoph Toshok &lt;toshok@hungry.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a></TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> (same as Linux 86 code)</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>BSD/OS x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:bert_driehuis@nl.compuware.com">Bert Driehuis &lt;bert_driehuis@nl.compuware.com&gt;</a></TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> (same as Linux 86 code)
+Bert contributed patches that *should* do the right thing for all the unixish-x86
+versions of this code for GCC 2.7 or 2.8 vs. EGCS 1.1. He notes that the vtbl
+scheme is different. He is hoping that others will help test the changes using
+these two compilers on the various platforms where this same code is used.
+<a href="news://news.mozilla.org/372DD257.4248C821%40nl.compuware.com">Bert's details</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Mac PPC</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+ <a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:beard@netscape.com">Patrick Beard &lt;beard@netscape.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/mac">mac</a> (passing tests and checked in)</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Solaris Sparc</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mcafee@netscape.com">Chris McAfee &lt;mcafee@netscape.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> This is checked in and working.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Solaris Sparc v9 (64bit)</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:pavlov@netscape.com">Stuart Parmenter &lt;pavlov@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:cls@seawood.org">Chris Seawood &lt;cls@seawood.org&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> This is checked in and (pavlov claims!) working.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>OS/2</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mjf35@cam.ac.uk">John Fairhurst &lt;mjf35@cam.ac.uk&gt;</a></TD>
+<TD>I never heard exactly who did what. But mozilla has been working on OS/2
+for a long time now.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>OpenVMS Alpha</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:colin@theblakes.com">Colin R. Blake &lt;colin@theblakes.com&gt;</a></TD>
+<TD>
+Colin says this is passing all the tests on OpenVMS Alpha!
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>NT Alpha</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:bob@guiduck.com">bob meader &lt;bob@guiduck.com&gt;</a></TD>
+<TD>
+bob writes:<br>
+Enclosed is xptcall for alpha/nt target..
+<p>
+It is a variation of the IRIS port (only targeted for win32).
+<p>
+Notice the last 2 files (the change to mozilla\xpcom\build\makefile.win and
+mozilla\xpcom\build) are needed because I was unable to figure how to do a
+"declspecexport" from the assembler ASAXP ... if some knows how to do that then
+those last 2 files won't be needed.
+<p>
+I have had someone look over this code at bridge.com (the entry point to
+compaq/gem compiler team) and this code was given the OK. I consider it "done".
+<p>
+This code lives in the files where the name includes 'alpha' in the <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a> directory.<BR>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux ARM</TD>
+<TD><img alt="Started" title="Started" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:sh990154@mail.uni-greifswald.de">Stefan Hanske&lt;sh990154@mail.uni-greifswald.de&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:willy@bofh.ai">Matthew Wilcox &lt;willy@bofh.ai&gt;</a></TD>
+<TD>
+Stefan's code is checked in and he says it is working.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux Sparc</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:anton@progsoc.uts.edu.au">Anton Blanchard &lt;anton@progsoc.uts.edu.au&gt;</a>,
+<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,
+<BR>
+<img alt="Maybe" title="Maybe" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:ehle.3@osu.eduehle.3@osu.edu">Brandon Ehle &lt;ehle.3@osu.edu&gt;</a>
+</TD>
+<TD>
+Anton contributed patches to Roger's Sparc code. Anton says it works and passes the tests!<b>
+(24-Aug-1999) Brandon writes: I've finished testing XPTCALL Sparc Linux on 12 different Sparc machines and it checks out good.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux PPC</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:beard@netscape.com">Patrick Beard &lt;beard@netscape.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:waterson@netscape.com">Chris Waterson &lt;waterson@netscape.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:Franz.Sirl-kernel@lauterbach.com">Franz Sirl &lt;Franz.Sirl-kernel@lauterbach.com&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:jsproul@condor.fddi.wesleyan.edu">Jason Y. Sproul &lt;jsproul@condor.fddi.wesleyan.edu&gt;</a><BR>
+ <font color="red"><b>?</b></font>
+ <a href="mailto:darkmane@w-link.net">Sean Chitwood &lt;darkmane@w-link.net&gt;</a></TD>
+<TD>
+waterson said: <b>Mozilla runs on Linux/PPC</b>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux Alpha</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:glen.nakamura@usa.net">Glen Nakamura &lt;glen.nakamura@usa.net&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:morrildl@nycap.rr.com">Dan Morril &lt;morrildl@nycap.rr.com&gt;</a><BR>
+</TD>
+<TD>
+Glen writes:
+<p>
+I am attaching a patch which contains my Linux Alpha xptcall code.
+It passes TestXPTCInvoke and TestXPC on my machine which runs
+kernel 2.2.7, glibc 2.1.1, and egcs 1.1.2. I have not tested it
+with older GNU compilers such as gcc 2.8.x. From looking at the
+Linux x86 code, I gather that the vtable layout is a little different
+for those compilers and the code will need minor modifications
+in order to work properly.
+<p>
+I am not sure how much of the code can be used for OpenVMS Alpha
+and/or Digital UNIX. Currently the code is dependent on the g++
+name mangling convention and a few GNU extensions so I'm not sure
+how useful it will be for the other systems. Hopefully the
+comments in the code are detailed enough to help people attempting
+a port.
+<p>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>SunOS x86</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:aljones@lbl.gov">Arthur Jones &lt;aljones@lbl.gov&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:ppokorny@mindspring.com">Philip Pokorny &lt;ppokorny@mindspring.com&gt;</a><BR>
+</TD>
+<TD>
+The word I hear is that this is working and done
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>HP-UX</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:wang@cup.hp.com">Thomas Wang &lt;wang@cup.hp.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mgleeson1@netscape.com">Mike Gleeson &lt;mgleeson1@netscape.com&gt;</a>
+</TD>
+<TD>I hear that this code is checked in and working. Though, there is some
+doubt - see bug
+#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=17997">17997</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>AIX PPC</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jdunn@netscape.com">Jim Dunn &lt;jdunn@netscape.com&gt;</a></TD>
+<TD>Philip K. Warren writes: <BR>
+
+We have gone through several releases of AIX without any problems.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Irix</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jasonh@m7.engr.sgi.com">Jason Heirtzler &lt;jasonh@m7.engr.sgi.com&gt;</a><BR>
+</TD>
+<TD>Jason has declared this done. Jason is no longer working at SGI and will
+not be maintaining this code. There is some doubt as to whether or not this is
+working for everyone - see bug
+#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=10061">10061</a>.
+<a href="mailto:shaver@mozilla.org">Mike&nbsp;Shaver&nbsp;&lt;shaver@mozilla.org&gt;</a>
+is the interim maintainer until someone more suitable can be found.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>BeOS x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:duncan@be.com">Duncan Wilcox &lt;duncan@be.com&gt;</a><BR>
+</TD>
+<TD>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> (yet another reuse of the Linux 86 code!)<BR>
+Duncan says this is all working. He did the code for old cfront style 'this' adjustment for others to use too!
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>BeOS PPC</TD>
+<TD align="center">-</TD>
+<TD align="center">-</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Compaq Tru64 UNIX (Digital UNIX)</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:streeter@zk3.dec.com">Steve Streeter &lt;streeter@zk3.dec.com&gt;</a><BR>
+</TD>
+<TD>Code passes the tests and is checked in.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Working</b></font></TD>
+<TD>Neutrio x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:Jerry.Kirk@Nexwarecorp.com">Jerry L. Kirk &lt;Jerry.Kirk@Nexwarecorp.com&gt;</a><BR>
+</TD>
+<TD>
+Patches for xptc*_unixish_x86.cpp checked in. Waiting for verification that this is really finished.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Investigating</b></font></TD>
+<TD>SCO UW7 and OSR5</TD>
+<TD>
+<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jkj@sco.com">J. Kean Johnston &lt;jkj@sco.com&gt;</a><BR>
+<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:evanh@sco.com">Evan Hunt &lt;evanh@sco.com&gt;</a><BR>
+</TD>
+<TD>Recent (Feb-2001) email from jkj@sco.com suggests that work will be occuring soon.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Works</b></font></TD>
+<TD>NetBSD/m68k</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:khym@bga.com">Dave Huang &lt;khym@bga.com&gt;</a><BR>
+</TD>
+<TD>
+Dave's changes are in the tree. Waiting for verification that it is really finished.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Partially Working</b></font></TD>
+<TD>NetBSD/arm32</TD>
+<TD><img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mpumford@black-star.demon.co.uk">Mike Pumford &lt;mpumford@black-star.demon.co.uk&gt;</a>
+</TD>
+<TD>Mike writes:<BR>
+I have started porting to the platform based on the code for Linux ARM. The
+InvokeByIndex code works correctly when used with TestXPTCInvoke. I am
+currently working on making TestXPC function correctly.
+<P>
+I am doing the porting work with egcs-1.1.2 on NetBSD 1.4P (NetBSD-current
+snapshot from a couple of days ago).
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>linux/ia64</TD>
+<TD align="center">-</TD>
+<TD>bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=40950">40950</a></TD>
+</TR>
+
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>All others!</TD>
+<TD align="center">-</TD>
+<TD align="center">-</TD>
+</TR>
+
+
+</table>
+
+<p>
+
+<b>Note:</b> I've used the symbol (<font color="red"><b>?</b></font>) to
+indicate people who have expressed an interest in <i>possibly</i> contributing code.
+Just because these people are listed here does not mean that they have commited
+themselves to do the work. If <b>you</b> would like to contribute then let me
+know. Feel free to email these folks and offer to help or find out what's going
+on. We're all in this together.
+
+<p>
+
+<hr>
+<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<b>Last modified:</b> 3 February 2003
+
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore
new file mode 100644
index 00000000..177fd905
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+TestXPTCInvoke
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in
new file mode 100644
index 00000000..a1bf16ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in
@@ -0,0 +1,64 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = TestXPTC
+SIMPLE_PROGRAMS = TestXPTCInvoke$(BIN_SUFFIX)
+REQUIRES = xpcom \
+ $(NULL)
+
+CPPSRCS = TestXPTCInvoke.cpp
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+# For _write().
+ifeq ($(OS_ARCH),BSD_OS)
+OS_LIBS += -lgcc
+endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp
new file mode 100644
index 00000000..79e4bc08
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp
@@ -0,0 +1,1464 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Invoke tests xptcall. */
+
+#include <stdio.h>
+#include "xptcall.h"
+#include "prlong.h"
+#include "prinrval.h"
+#include "nsMemory.h"
+
+// forward declration
+static int DoMultipleInheritenceTest(int rcExit);
+static int DoMultipleInheritenceTest2(int rcExit);
+static void DoSpeedTest();
+
+
+#include <iprt/string.h>
+
+static char g_szDirect[16384];
+static char g_szInvoke[16384];
+static char *g_pszBuffer = NULL;
+static void bufprintf(const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ vprintf(pszFormat, va);
+ va_end(va);
+ if (g_pszBuffer)
+ {
+ size_t cchBuf = strlen(g_pszBuffer);
+ ssize_t cbLeft = (ssize_t)sizeof(g_szDirect) - (ssize_t)cchBuf;
+ if (cbLeft > 0)
+ {
+ va_list va;
+ va_start(va, pszFormat);
+ vsnprintf(&g_pszBuffer[cchBuf], (size_t)cbLeft, pszFormat, va);
+ va_end(va);
+ }
+ }
+}
+
+static void setbuffer(bool fDirect)
+{
+ g_pszBuffer = fDirect ? g_szDirect : g_szInvoke;
+ *g_pszBuffer = '\0';
+}
+
+static int comparebuffers(int rcExit)
+{
+ if (strcmp(g_szDirect, g_szInvoke) == 0)
+ return rcExit;
+ size_t offLine = 0;
+ unsigned iLine = 1;
+ for (size_t off = 0; ; off++)
+ {
+ char chDirect = g_szDirect[off];
+ char chInvoke = g_szInvoke[off];
+ if (chDirect == chInvoke)
+ {
+ if (!chDirect)
+ return rcExit;
+ if (chDirect == '\n')
+ {
+ offLine = off + 1;
+ iLine++;
+ }
+ }
+ else
+ {
+ size_t cchDirectLine = RTStrOffCharOrTerm(&g_szDirect[offLine], '\n');
+ size_t cchInvokeLine = RTStrOffCharOrTerm(&g_szInvoke[offLine], '\n');
+ printf("direct and invoke runs differs on line %u!\n", iLine);
+ printf("direct: %*.*s\n", (int)cchDirectLine, (int)cchDirectLine, &g_szDirect[offLine]);
+ printf("invoke: %*.*s\n", (int)cchInvokeLine, (int)cchInvokeLine, &g_szInvoke[offLine]);
+
+ return 1;
+ }
+
+ }
+ printf("direct and invoke runs differs!\n");
+ return 1;
+}
+
+
+// {AAC1FB90-E099-11d2-984E-006008962422}
+#define INVOKETESTTARGET_IID \
+{ 0xaac1fb90, 0xe099, 0x11d2, \
+ { 0x98, 0x4e, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+
+
+class InvokeTestTargetInterface : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(INVOKETESTTARGET_IID)
+ NS_IMETHOD AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval) = 0;
+ NS_IMETHOD MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval) = 0;
+ NS_IMETHOD AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval) = 0;
+ NS_IMETHOD MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval) = 0;
+
+ NS_IMETHOD AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
+ PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
+ PRInt32 p9, PRInt32 p10, PRInt32* retval) = 0;
+
+ NS_IMETHOD AddTwoFloats(float p1, float p2, float* retval) = 0;
+
+ NS_IMETHOD AddManyDoubles(double p1, double p2, double p3, double p4,
+ double p5, double p6, double p7, double p8,
+ double p9, double p10, double* retval) = 0;
+
+ NS_IMETHOD AddManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float* retval) = 0;
+
+ NS_IMETHOD AddManyManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float p11, float p12,
+ float p13, float p14, float p15, float p16,
+ float p17, float p18, float p19, float p20,
+ float *retval) = 0;
+
+ NS_IMETHOD AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
+ PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
+ PRInt64 p9, PRInt32 p10, PRInt64* retval) = 0;
+
+ NS_IMETHOD AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
+ PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
+ PRInt32 p9, PRInt64 p10, PRInt64* retval) = 0;
+
+ NS_IMETHOD AddMixedFloats(float p1, float p2, double p3, double p4,
+ float p5, float p6, double p7, double p8,
+ float p9, double p10, float p11,
+ double *retval) = 0;
+
+ NS_IMETHOD PassTwoStrings(const char* s1, const char* s2, char** retval) = 0;
+
+};
+
+class InvokeTestTarget : public InvokeTestTargetInterface
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval);
+ NS_IMETHOD MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval);
+
+ NS_IMETHOD AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
+ PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
+ PRInt32 p9, PRInt32 p10, PRInt32* retval);
+
+ NS_IMETHOD AddTwoFloats(float p1, float p2, float* retval);
+
+ NS_IMETHOD AddManyDoubles(double p1, double p2, double p3, double p4,
+ double p5, double p6, double p7, double p8,
+ double p9, double p10, double* retval);
+
+ NS_IMETHOD AddManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float* retval);
+
+ NS_IMETHOD AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
+ PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
+ PRInt64 p9, PRInt32 p10, PRInt64* retval);
+
+ NS_IMETHOD AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
+ PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
+ PRInt32 p9, PRInt64 p10, PRInt64* retval);
+
+ NS_IMETHOD AddMixedFloats(float p1, float p2, double p3, double p4,
+ float p5, float p6, double p7, double p8,
+ float p9, double p10, float p11,
+ double *retval);
+
+ NS_IMETHOD AddManyManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float p11, float p12,
+ float p13, float p14, float p15, float p16,
+ float p17, float p18, float p19, float p20,
+ float *retval);
+
+ NS_IMETHOD PassTwoStrings(const char* s1, const char* s2, char** retval);
+
+ InvokeTestTarget();
+};
+
+NS_IMPL_ISUPPORTS1(InvokeTestTarget, InvokeTestTargetInterface)
+
+InvokeTestTarget::InvokeTestTarget()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ *retval = p1 + p2;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ *retval = p1 * p2;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval)
+{
+ LL_ADD(*retval, p1, p2);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval)
+{
+ LL_MUL(*retval, p1, p2);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
+ PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
+ PRInt32 p9, PRInt32 p10, PRInt32* retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddTwoFloats(float p1, float p2, float *retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f\n", p1, p2);
+#endif
+ *retval = p1 + p2;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyDoubles(double p1, double p2, double p3, double p4,
+ double p5, double p6, double p7, double p8,
+ double p9, double p10, double* retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float* retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddMixedFloats(float p1, float p2, double p3, double p4,
+ float p5, float p6, double p7, double p8,
+ float p9, double p10, float p11,
+ double *retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f, %lf, %lf, %f, %f, %lf, %lf, %f, %lf, %f\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float p11, float p12,
+ float p13, float p14, float p15, float p16,
+ float p17, float p18, float p19, float p20,
+ float *retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, "
+ "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11, p12, p13, p14, p15, p16, p17, p18, p19, p20);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 +
+ p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
+ PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
+ PRInt64 p9, PRInt32 p10, PRInt64* retval)
+{
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
+ PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
+ PRInt32 p9, PRInt64 p10, PRInt64* retval)
+{
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::PassTwoStrings(const char* s1, const char* s2, char** retval)
+{
+ const char milk[] = "milk";
+ char *ret = (char*)nsMemory::Alloc(sizeof(milk));
+ if (!ret)
+ return NS_ERROR_OUT_OF_MEMORY;
+ strncpy(ret, milk, sizeof(milk));
+ printf("\t%s %s", s1, s2);
+ *retval = ret;
+ return NS_OK;
+}
+
+int main()
+{
+ InvokeTestTarget *test = new InvokeTestTarget();
+
+ /* here we make the global 'check for alloc failure' checker happy */
+ if(!test)
+ return 1;
+
+ PRInt32 out, tmp32 = 0;
+ PRInt64 out64;
+ printf("calling direct:\n");
+ setbuffer(true);
+ if(NS_SUCCEEDED(test->AddTwoInts(1,1,&out)))
+ bufprintf("\t1 + 1 = %d\n", out);
+ else
+ bufprintf("\tFAILED");
+ PRInt64 one, two;
+ LL_I2L(one, 1);
+ LL_I2L(two, 2);
+ if(NS_SUCCEEDED(test->AddTwoLLs(one,one,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t1L + 1L = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+ if(NS_SUCCEEDED(test->MultTwoInts(2,2,&out)))
+ bufprintf("\t2 * 2 = %d\n", out);
+ else
+ bufprintf("\tFAILED");
+ if(NS_SUCCEEDED(test->MultTwoLLs(two,two,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t2L * 2L = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+
+ double outD;
+ float outF;
+ PRInt32 outI;
+ char *outS;
+
+ if(NS_SUCCEEDED(test->AddManyInts(1,2,3,4,5,6,7,8,9,10,&outI)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", outI);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddTwoFloats(1,2,&outF)))
+ bufprintf("\t1 + 2 = %ff\n", (double)outF);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddManyDoubles(1,2,3,4,5,6,7,8,9,10,&outD)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %f\n", outD);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddManyFloats(1,2,3,4,5,6,7,8,9,10,&outF)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %ff\n", (double)outF);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddManyManyFloats(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,&outF)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 = %ff\n", (double)outF);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddMixedInts(1,2,3,4,5,6,7,8,9,10,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddMixedInts2(1,2,3,4,5,6,7,8,9,10,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddMixedFloats(1,2,3,4,5,6,7,8,9,10,11,&outD)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = %f\n", (double)outD);
+ else
+ bufprintf("\tFAILED");
+
+ if (NS_SUCCEEDED(test->PassTwoStrings("moo","cow",&outS))) {
+ bufprintf(" = %s\n", outS);
+ nsMemory::Free(outS);
+ } else
+ bufprintf("\tFAILED");
+
+ printf("calling via invoke:\n");
+ setbuffer(false);
+
+ nsXPTCVariant var[21];
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 1;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 0;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i32;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 3, 3, var)))
+ bufprintf("\t1 + 1 = %d\n", var[2].val.i32);
+ else
+ bufprintf("\tFAILED");
+
+ LL_I2L(var[0].val.i64, 1);
+ var[0].type = nsXPTType::T_I64;
+ var[0].flags = 0;
+
+ LL_I2L(var[1].val.i64, 1);
+ var[1].type = nsXPTType::T_I64;
+ var[1].flags = 0;
+
+ LL_I2L(var[2].val.i64, 0);
+ var[2].type = nsXPTType::T_I64;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 5, 3, var)))
+ bufprintf("\t1L + 1L = %d\n", (int)var[2].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 2;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 0;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i32;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 4, 3, var)))
+ bufprintf("\t2 * 2 = %d\n", var[2].val.i32);
+ else
+ bufprintf("\tFAILED");
+
+ LL_I2L(var[0].val.i64,2);
+ var[0].type = nsXPTType::T_I64;
+ var[0].flags = 0;
+
+ LL_I2L(var[1].val.i64,2);
+ var[1].type = nsXPTType::T_I64;
+ var[1].flags = 0;
+
+ LL_I2L(var[2].val.i64,0);
+ var[2].type = nsXPTType::T_I64;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 6, 3, var)))
+ bufprintf("\t2L * 2L = %d\n", (int)var[2].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 2;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 3;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = 0;
+
+ var[3].val.i32 = 4;
+ var[3].type = nsXPTType::T_I32;
+ var[3].flags = 0;
+
+ var[4].val.i32 = 5;
+ var[4].type = nsXPTType::T_I32;
+ var[4].flags = 0;
+
+ var[5].val.i32 = 6;
+ var[5].type = nsXPTType::T_I32;
+ var[5].flags = 0;
+
+ var[6].val.i32 = 7;
+ var[6].type = nsXPTType::T_I32;
+ var[6].flags = 0;
+
+ var[7].val.i32 = 8;
+ var[7].type = nsXPTType::T_I32;
+ var[7].flags = 0;
+
+ var[8].val.i32 = 9;
+ var[8].type = nsXPTType::T_I32;
+ var[8].flags = 0;
+
+ var[9].val.i32 = 10;
+ var[9].type = nsXPTType::T_I32;
+ var[9].flags = 0;
+
+ var[10].val.i32 = 0;
+ var[10].type = nsXPTType::T_I32;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.i32;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 7, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
+ var[10].val.i32);
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.f = 0.0f;
+ var[2].type = nsXPTType::T_FLOAT;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.f;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 8, 3, var)))
+ bufprintf("\t1 + 2 = %ff\n",
+ (double) var[2].val.f);
+
+
+ var[0].val.d = 1.0;
+ var[0].type = nsXPTType::T_DOUBLE;
+ var[0].flags = 0;
+
+ var[1].val.d = 2.0;
+ var[1].type = nsXPTType::T_DOUBLE;
+ var[1].flags = 0;
+
+ var[2].val.d = 3.0;
+ var[2].type = nsXPTType::T_DOUBLE;
+ var[2].flags = 0;
+
+ var[3].val.d = 4.0;
+ var[3].type = nsXPTType::T_DOUBLE;
+ var[3].flags = 0;
+
+ var[4].val.d = 5.0;
+ var[4].type = nsXPTType::T_DOUBLE;
+ var[4].flags = 0;
+
+ var[5].val.d = 6.0;
+ var[5].type = nsXPTType::T_DOUBLE;
+ var[5].flags = 0;
+
+ var[6].val.d = 7.0;
+ var[6].type = nsXPTType::T_DOUBLE;
+ var[6].flags = 0;
+
+ var[7].val.d = 8.0;
+ var[7].type = nsXPTType::T_DOUBLE;
+ var[7].flags = 0;
+
+ var[8].val.d = 9.0;
+ var[8].type = nsXPTType::T_DOUBLE;
+ var[8].flags = 0;
+
+ var[9].val.d = 10.0;
+ var[9].type = nsXPTType::T_DOUBLE;
+ var[9].flags = 0;
+
+ var[10].val.d = 0.0;
+ var[10].type = nsXPTType::T_DOUBLE;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.d;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 9, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %f\n",
+ var[10].val.d);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.f = 3.0f;
+ var[2].type = nsXPTType::T_FLOAT;
+ var[2].flags = 0;
+
+ var[3].val.f = 4.0f;
+ var[3].type = nsXPTType::T_FLOAT;
+ var[3].flags = 0;
+
+ var[4].val.f = 5.0f;
+ var[4].type = nsXPTType::T_FLOAT;
+ var[4].flags = 0;
+
+ var[5].val.f = 6.0f;
+ var[5].type = nsXPTType::T_FLOAT;
+ var[5].flags = 0;
+
+ var[6].val.f = 7.0f;
+ var[6].type = nsXPTType::T_FLOAT;
+ var[6].flags = 0;
+
+ var[7].val.f = 8.0f;
+ var[7].type = nsXPTType::T_FLOAT;
+ var[7].flags = 0;
+
+ var[8].val.f = 9.0f;
+ var[8].type = nsXPTType::T_FLOAT;
+ var[8].flags = 0;
+
+ var[9].val.f = 10.0f;
+ var[9].type = nsXPTType::T_FLOAT;
+ var[9].flags = 0;
+
+ var[10].val.f = 0.0f;
+ var[10].type = nsXPTType::T_FLOAT;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.f;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 10, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %ff\n",
+ (double) var[10].val.f);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.f = 3.0f;
+ var[2].type = nsXPTType::T_FLOAT;
+ var[2].flags = 0;
+
+ var[3].val.f = 4.0f;
+ var[3].type = nsXPTType::T_FLOAT;
+ var[3].flags = 0;
+
+ var[4].val.f = 5.0f;
+ var[4].type = nsXPTType::T_FLOAT;
+ var[4].flags = 0;
+
+ var[5].val.f = 6.0f;
+ var[5].type = nsXPTType::T_FLOAT;
+ var[5].flags = 0;
+
+ var[6].val.f = 7.0f;
+ var[6].type = nsXPTType::T_FLOAT;
+ var[6].flags = 0;
+
+ var[7].val.f = 8.0f;
+ var[7].type = nsXPTType::T_FLOAT;
+ var[7].flags = 0;
+
+ var[8].val.f = 9.0f;
+ var[8].type = nsXPTType::T_FLOAT;
+ var[8].flags = 0;
+
+ var[9].val.f = 10.0f;
+ var[9].type = nsXPTType::T_FLOAT;
+ var[9].flags = 0;
+
+ var[10].val.f = 11.0f;
+ var[10].type = nsXPTType::T_FLOAT;
+ var[10].flags = 0;
+
+ var[11].val.f = 12.0f;
+ var[11].type = nsXPTType::T_FLOAT;
+ var[11].flags = 0;
+
+ var[12].val.f = 13.0f;
+ var[12].type = nsXPTType::T_FLOAT;
+ var[12].flags = 0;
+
+ var[13].val.f = 14.0f;
+ var[13].type = nsXPTType::T_FLOAT;
+ var[13].flags = 0;
+
+ var[14].val.f = 15.0f;
+ var[14].type = nsXPTType::T_FLOAT;
+ var[14].flags = 0;
+
+ var[15].val.f = 16.0f;
+ var[15].type = nsXPTType::T_FLOAT;
+ var[15].flags = 0;
+
+ var[16].val.f = 17.0f;
+ var[16].type = nsXPTType::T_FLOAT;
+ var[16].flags = 0;
+
+ var[17].val.f = 18.0f;
+ var[17].type = nsXPTType::T_FLOAT;
+ var[17].flags = 0;
+
+ var[18].val.f = 19.0f;
+ var[18].type = nsXPTType::T_FLOAT;
+ var[18].flags = 0;
+
+ var[19].val.f = 20.0f;
+ var[19].type = nsXPTType::T_FLOAT;
+ var[19].flags = 0;
+
+ var[20].val.f = 0.0f;
+ var[20].type = nsXPTType::T_FLOAT;
+ var[20].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[20].ptr = &var[20].val.f;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 11, 21, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 = %ff\n",
+ (double) var[20].val.f);
+
+ var[0].val.i64 = 1;
+ var[0].type = nsXPTType::T_I64;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 2;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i64 = 3;
+ var[2].type = nsXPTType::T_I64;
+ var[2].flags = 0;
+
+ var[3].val.i32 = 4;
+ var[3].type = nsXPTType::T_I32;
+ var[3].flags = 0;
+
+ var[4].val.i32 = 5;
+ var[4].type = nsXPTType::T_I32;
+ var[4].flags = 0;
+
+ var[5].val.i64 = 6;
+ var[5].type = nsXPTType::T_I64;
+ var[5].flags = 0;
+
+ var[6].val.i32 = 7;
+ var[6].type = nsXPTType::T_I32;
+ var[6].flags = 0;
+
+ var[7].val.i32 = 8;
+ var[7].type = nsXPTType::T_I32;
+ var[7].flags = 0;
+
+ var[8].val.i64 = 9;
+ var[8].type = nsXPTType::T_I64;
+ var[8].flags = 0;
+
+ var[9].val.i32 = 10;
+ var[9].type = nsXPTType::T_I32;
+ var[9].flags = 0;
+
+ var[10].val.i64 = 0;
+ var[10].type = nsXPTType::T_I64;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 12, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
+ (int)var[10].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i64 = 2;
+ var[1].type = nsXPTType::T_I64;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 3;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = 0;
+
+ var[3].val.i64 = 4;
+ var[3].type = nsXPTType::T_I64;
+ var[3].flags = 0;
+
+ var[4].val.i64 = 5;
+ var[4].type = nsXPTType::T_I64;
+ var[4].flags = 0;
+
+ var[5].val.i32 = 6;
+ var[5].type = nsXPTType::T_I32;
+ var[5].flags = 0;
+
+ var[6].val.i64 = 7;
+ var[6].type = nsXPTType::T_I64;
+ var[6].flags = 0;
+
+ var[7].val.i64 = 8;
+ var[7].type = nsXPTType::T_I64;
+ var[7].flags = 0;
+
+ var[8].val.i32 = 9;
+ var[8].type = nsXPTType::T_I32;
+ var[8].flags = 0;
+
+ var[9].val.i64 = 10;
+ var[9].type = nsXPTType::T_I64;
+ var[9].flags = 0;
+
+ var[10].val.i64 = 0;
+ var[10].type = nsXPTType::T_I64;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 13, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
+ (int)var[10].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.d = 3.0;
+ var[2].type = nsXPTType::T_DOUBLE;
+ var[2].flags = 0;
+
+ var[3].val.d = 4.0;
+ var[3].type = nsXPTType::T_DOUBLE;
+ var[3].flags = 0;
+
+ var[4].val.f = 5.0f;
+ var[4].type = nsXPTType::T_FLOAT;
+ var[4].flags = 0;
+
+ var[5].val.f = 6.0f;
+ var[5].type = nsXPTType::T_FLOAT;
+ var[5].flags = 0;
+
+ var[6].val.d = 7.0;
+ var[6].type = nsXPTType::T_DOUBLE;
+ var[6].flags = 0;
+
+ var[7].val.d = 8.0;
+ var[7].type = nsXPTType::T_DOUBLE;
+ var[7].flags = 0;
+
+ var[8].val.f = 9.0f;
+ var[8].type = nsXPTType::T_FLOAT;
+ var[8].flags = 0;
+
+ var[9].val.d = 10.0;
+ var[9].type = nsXPTType::T_DOUBLE;
+ var[9].flags = 0;
+
+ var[10].val.f = 11.0f;
+ var[10].type = nsXPTType::T_FLOAT;
+ var[10].flags = 0;
+
+ var[11].val.d = 0.0;
+ var[11].type = nsXPTType::T_DOUBLE;
+ var[11].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[11].ptr = &var[11].val.d;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 14, 12, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = %f\n",
+ var[11].val.d);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.p = (void*)"moo";
+ var[0].type = nsXPTType::T_CHAR_STR;
+ var[0].flags = 0;
+
+ var[1].val.p = (void*)"cow";
+ var[1].type = nsXPTType::T_CHAR_STR;
+ var[1].flags = 0;
+
+ var[2].val.p = 0;
+ var[2].type = nsXPTType::T_CHAR_STR;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.p;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 15, 3, var)))
+ {
+ bufprintf(" = %s\n", var[2].val.p);
+ nsMemory::Free(var[2].val.p);
+ }
+ else
+ bufprintf("\tFAILED");
+ int rcExit = comparebuffers(0);
+
+ rcExit = DoMultipleInheritenceTest(rcExit);
+ rcExit = DoMultipleInheritenceTest2(rcExit);
+ // Disabled by default - takes too much time on slow machines
+ //DoSpeedTest();
+
+ NS_RELEASE(test);
+
+ return rcExit;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+
+// {491C65A0-3317-11d3-9885-006008962422}
+#define FOO_IID \
+{ 0x491c65a0, 0x3317, 0x11d3, \
+ { 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+
+// {491C65A1-3317-11d3-9885-006008962422}
+#define BAR_IID \
+{ 0x491c65a1, 0x3317, 0x11d3, \
+ { 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+
+/***************************/
+
+class nsIFoo : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(FOO_IID)
+ NS_IMETHOD FooMethod1(PRInt32 i) = 0;
+ NS_IMETHOD FooMethod2(PRInt32 i) = 0;
+};
+
+class nsIBar : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(BAR_IID)
+ NS_IMETHOD BarMethod1(PRInt32 i) = 0;
+ NS_IMETHOD BarMethod2(PRInt32 i) = 0;
+};
+
+/***************************/
+
+class FooImpl : public nsIFoo
+{
+public:
+ NS_IMETHOD FooMethod1(PRInt32 i);
+ NS_IMETHOD FooMethod2(PRInt32 i);
+
+ FooImpl();
+
+protected:
+ ~FooImpl() {}
+
+public:
+ virtual const char* ImplName() = 0;
+
+ int SomeData1;
+ int SomeData2;
+ const char* Name;
+};
+
+class BarImpl : public nsIBar
+{
+public:
+ NS_IMETHOD BarMethod1(PRInt32 i);
+ NS_IMETHOD BarMethod2(PRInt32 i);
+
+ BarImpl();
+
+protected:
+ ~BarImpl() {}
+
+public:
+ virtual const char * ImplName() = 0;
+
+ int SomeData1;
+ int SomeData2;
+ const char* Name;
+};
+
+/***************************/
+
+FooImpl::FooImpl() : Name("FooImpl")
+{
+}
+
+NS_IMETHODIMP FooImpl::FooMethod1(PRInt32 i)
+{
+ bufprintf("\tFooImpl::FooMethod1 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooImpl::FooMethod2(PRInt32 i)
+{
+ bufprintf("\tFooImpl::FooMethod2 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+/***************************/
+
+BarImpl::BarImpl() : Name("BarImpl")
+{
+}
+
+NS_IMETHODIMP BarImpl::BarMethod1(PRInt32 i)
+{
+ bufprintf("\tBarImpl::BarMethod1 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+NS_IMETHODIMP BarImpl::BarMethod2(PRInt32 i)
+{
+ bufprintf("\tBarImpl::BarMethod2 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+/***************************/
+
+class FooBarImpl : public FooImpl, public BarImpl
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ const char* ImplName();
+
+ FooBarImpl();
+
+private:
+ ~FooBarImpl() {}
+
+public:
+ const char* MyName;
+};
+
+FooBarImpl::FooBarImpl() : MyName("FooBarImpl")
+{
+ NS_ADDREF_THIS();
+}
+
+const char* FooBarImpl::ImplName()
+{
+ return MyName;
+}
+
+NS_IMETHODIMP
+FooBarImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aInstancePtr = NULL;
+
+
+ if (aIID.Equals(NS_GET_IID(nsIFoo))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIFoo*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(NS_GET_IID(nsIBar))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIBar*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ if (aIID.Equals(NS_GET_IID(nsISupports))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsISupports*,
+ NS_STATIC_CAST(nsIFoo*,this));
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ return NS_NOINTERFACE;
+}
+
+NS_IMPL_ADDREF(FooBarImpl)
+NS_IMPL_RELEASE(FooBarImpl)
+
+
+static int DoMultipleInheritenceTest(int rcExit)
+{
+ FooBarImpl* impl = new FooBarImpl();
+ if(!impl)
+ return 1;
+
+ nsIFoo* foo;
+ nsIBar* bar;
+
+ nsXPTCVariant var[1];
+
+ printf("\n");
+ if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) &&
+ NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar)))
+ {
+ printf("impl == %p\n", impl);
+ printf("foo == %p\n", foo);
+ printf("bar == %p\n", bar);
+
+ printf("Calling Foo...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ foo->FooMethod1(1);
+ foo->FooMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ printf("Calling Bar...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ bar->BarMethod1(1);
+ bar->BarMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ NS_RELEASE(foo);
+ NS_RELEASE(bar);
+ }
+ else
+ rcExit = 1;
+ NS_RELEASE(impl);
+ return rcExit;
+}
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+/* This is a variation on the theme submitted by duncan@be.com (Duncan Wilcox).
+* He was seeing the other test work and this test not work. They should both
+* Work on any given platform
+*/
+
+class nsIFoo2 : public nsISupports
+{
+public:
+ NS_IMETHOD FooMethod1(PRInt32 i) = 0;
+ NS_IMETHOD FooMethod2(PRInt32 i) = 0;
+};
+
+class nsIBar2 : public nsISupports
+{
+public:
+ NS_IMETHOD BarMethod1(PRInt32 i) = 0;
+ NS_IMETHOD BarMethod2(PRInt32 i) = 0;
+};
+
+class FooBarImpl2 : public nsIFoo2, public nsIBar2
+{
+public:
+ // Foo interface
+ NS_IMETHOD FooMethod1(PRInt32 i);
+ NS_IMETHOD FooMethod2(PRInt32 i);
+
+ // Bar interface
+ NS_IMETHOD BarMethod1(PRInt32 i);
+ NS_IMETHOD BarMethod2(PRInt32 i);
+
+ NS_DECL_ISUPPORTS
+
+ FooBarImpl2();
+
+private:
+ ~FooBarImpl2() {}
+
+public:
+ PRInt32 value;
+};
+
+FooBarImpl2::FooBarImpl2() : value(0x12345678)
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMETHODIMP FooBarImpl2::FooMethod1(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::FooMethod1 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooBarImpl2::FooMethod2(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::FooMethod2 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooBarImpl2::BarMethod1(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::BarMethod1 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooBarImpl2::BarMethod2(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::BarMethod2 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FooBarImpl2::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aInstancePtr = NULL;
+
+
+ if (aIID.Equals(NS_GET_IID(nsIFoo))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIFoo2*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(NS_GET_IID(nsIBar))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIBar2*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ if (aIID.Equals(NS_GET_IID(nsISupports))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsISupports*,
+ NS_STATIC_CAST(nsIFoo2*,this));
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ return NS_NOINTERFACE;
+}
+
+NS_IMPL_ADDREF(FooBarImpl2)
+NS_IMPL_RELEASE(FooBarImpl2)
+
+static int DoMultipleInheritenceTest2(int rcExit)
+{
+ FooBarImpl2* impl = new FooBarImpl2();
+ if(!impl)
+ return 1;
+
+ nsIFoo2* foo;
+ nsIBar2* bar;
+
+ nsXPTCVariant var[1];
+
+ printf("\n");
+ if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) &&
+ NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar)))
+ {
+ printf("impl == %p\n", impl);
+ printf("foo == %p\n", foo);
+ printf("bar == %p\n", bar);
+
+ printf("Calling Foo...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ foo->FooMethod1(1);
+ foo->FooMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ printf("Calling Bar...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ bar->BarMethod1(1);
+ bar->BarMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ NS_RELEASE(foo);
+ NS_RELEASE(bar);
+ }
+ else
+ rcExit = 1;
+ NS_RELEASE(impl);
+ return rcExit;
+}
+
+static void DoSpeedTest()
+{
+ InvokeTestTarget *test = new InvokeTestTarget();
+
+ nsXPTCVariant var[3];
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 1;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 0;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i32;
+
+ PRInt32 in1 = 1;
+ PRInt32 in2 = 1;
+ PRInt32 out;
+
+ // Crank this number down if your platform is slow :)
+ static const int count = 100000000;
+ int i;
+ PRIntervalTime start;
+ PRIntervalTime interval_direct;
+ PRIntervalTime interval_invoke;
+
+ printf("Speed test...\n\n");
+ printf("Doing %d direct call iterations...\n", count);
+ start = PR_IntervalNow();
+ for(i = count; i; i--)
+ (void)test->AddTwoInts(in1, in2, &out);
+ interval_direct = PR_IntervalNow() - start;
+
+ printf("Doing %d invoked call iterations...\n", count);
+ start = PR_IntervalNow();
+ for(i = count; i; i--)
+ (void)XPTC_InvokeByIndex(test, 3, 3, var);
+ interval_invoke = PR_IntervalNow() - start;
+
+ printf(" direct took %0.2f seconds\n",
+ (double)interval_direct/(double)PR_TicksPerSecond());
+ printf(" invoke took %0.2f seconds\n",
+ (double)interval_invoke/(double)PR_TicksPerSecond());
+ printf(" So, invoke overhead was ~ %0.2f seconds (~ %0.0f%%)\n",
+ (double)(interval_invoke-interval_direct)/(double)PR_TicksPerSecond(),
+ (double)(interval_invoke-interval_direct)/(double)interval_invoke*100);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in
new file mode 100644
index 00000000..d7e3b9c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in
new file mode 100644
index 00000000..dbf13d8b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in
@@ -0,0 +1,66 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+XPIDL_MODULE = xpcom_xpti
+
+GRE_MODULE = 1
+
+EXPORTS = \
+ xptinfo.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIInterfaceInfo.idl \
+ nsIInterfaceInfoManager.idl \
+ nsIXPTLoader.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+include $(topsrcdir)/config/rules.mk
+
+CFLAGS += -DEXPORT_XPCI_API
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl
new file mode 100644
index 00000000..f77dbcfc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The nsIInterfaceInfo public declaration. */
+
+
+#include "nsISupports.idl"
+
+// forward declaration of non-XPCOM types
+
+[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo);
+[ptr] native nsXPTConstantPtr(nsXPTConstant);
+[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo);
+ native nsXPTType(nsXPTType);
+
+// We bend the rules to do a [shared] nsIID (but this is never scriptable)
+[ptr] native nsIIDPtrShared(nsIID);
+
+%{C++
+class nsXPTMethodInfo;
+class nsXPTConstant;
+class nsXPTParamInfo;
+class nsXPTType;
+%}
+
+/* this is NOT intended to be scriptable */
+[uuid(215DBE04-94A7-11d2-BA58-00805F8A5DD7)]
+interface nsIInterfaceInfo : nsISupports
+{
+ readonly attribute string name;
+ readonly attribute nsIIDPtr InterfaceIID;
+
+ PRBool isScriptable();
+
+ readonly attribute nsIInterfaceInfo parent;
+
+ /**
+ * These include counts for parent (and all ancestors).
+ */
+ readonly attribute PRUint16 methodCount;
+ readonly attribute PRUint16 constantCount;
+
+ /**
+ * These include methods and constants for parent (and all ancestors).
+ *
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ void getMethodInfo(in PRUint16 index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getMethodInfoForName(in string methodName, out PRUint16 index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getConstant(in PRUint16 index,
+ [shared, retval] out nsXPTConstantPtr constant);
+
+
+ /**
+ * Get the interface information or iid associated with a param of some
+ * method in this interface.
+ */
+
+ nsIInterfaceInfo getInfoForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ nsIIDPtr getIIDForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+
+ /**
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ nsXPTType getTypeForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getSizeIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getLengthIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getInterfaceIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ PRBool isIID(in nsIIDPtr IID);
+
+ void getNameShared([shared,retval] out string name);
+ void getIIDShared([shared,retval] out nsIIDPtrShared iid);
+
+ PRBool isFunction();
+
+ PRBool hasAncestor(in nsIIDPtr iid);
+
+ [notxpcom] nsresult getIIDForParamNoAlloc(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ out nsIID iid);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl
new file mode 100644
index 00000000..48277691
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* The nsIInterfaceInfoManager public declaration. */
+
+
+#include "nsISupports.idl"
+#include "nsIInterfaceInfo.idl"
+#include "nsIEnumerator.idl"
+#include "nsISimpleEnumerator.idl"
+
+/* this is NOT intended to be scriptable */
+[uuid(8B161900-BE2B-11d2-9831-006008962422)]
+interface nsIInterfaceInfoManager : nsISupports
+{
+ nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid);
+ nsIInterfaceInfo getInfoForName(in string name);
+
+ nsIIDPtr getIIDForName(in string name);
+ string getNameForIID(in nsIIDPtr iid);
+
+ nsIEnumerator enumerateInterfaces();
+
+ void autoRegisterInterfaces();
+
+ nsIEnumerator enumerateInterfacesWhoseNamesStartWith(in string prefix);
+};
+
+[uuid(0ee22850-bc6a-11d5-9134-0010a4e73d9a)]
+interface nsIInterfaceInfoSuperManager : nsIInterfaceInfoManager
+{
+ void addAdditionalManager(in nsIInterfaceInfoManager manager);
+ void removeAdditionalManager(in nsIInterfaceInfoManager manager);
+
+ PRBool hasAdditionalManagers();
+ nsISimpleEnumerator enumerateAdditionalManagers();
+};
+
+%{C++
+#define NS_INTERFACEINFOMANAGER_SERVICE_CLASSNAME \
+ "Interface Information Manager Service"
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CID \
+ { /* 13bef784-f8e0-4f96-85c1-09f9ef4f9a19 */ \
+ 0x13bef784, 0xf8e0, 0x4f96, \
+ {0x85, 0xc1, 0x09, 0xf9, 0xef, 0x4f, 0x9a, 0x19} }
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID \
+ "@mozilla.org/xpti/interfaceinfomanager-service;1"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl
new file mode 100644
index 00000000..8918daa3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl
@@ -0,0 +1,100 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the external XPT loader interface.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ * Alec Flett <alecf@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+#include "nsILocalFile.idl"
+#include "nsIInputStream.idl"
+
+/**
+ * Implement nsIXPTLoaderSink if you want to enumerate the entries in
+ * an XPT archive of some kind
+ */
+[scriptable, uuid(6E48C500-8682-4730-ADD6-7DB693B9E7BA)]
+interface nsIXPTLoaderSink : nsISupports {
+
+ /**
+ * called by the loader for each entry in the archive
+ * @param itemName the name of this particular item in the archive
+ * @param index the index of the item inthe archive
+ * @param stream contains the contents of the xpt file
+ */
+ void foundEntry(in string itemName,
+ in long index,
+ in nsIInputStream xptData);
+};
+
+/**
+ * The XPT loader interface: implemented by a loader to grab an input
+ * stream which will be consumed by the interface loader.
+ */
+[scriptable, uuid(368A15D9-17A9-4c2b-AC3D-A35B3A22B876)]
+interface nsIXPTLoader : nsISupports {
+ /**
+ * enumerate entries in the given archive
+ * for each entry found, the loader will call the sink's
+ * foundEntry() method with the appropriate information and a
+ * stream that the consumer can read from
+ * @param file the file to read from
+ * @param sink an object which will be called with each file found
+ * in the file
+ */
+ void enumerateEntries(in nsILocalFile file,
+ in nsIXPTLoaderSink sink );
+
+ /**
+ * Load a specific entry from the archive
+ * @param file the file to read from
+ * @param name the name of the xpt within the file
+ * @return an input stream that will read the raw xpt data from
+ * the file
+ */
+ nsIInputStream loadEntry(in nsILocalFile file,
+ in string name);
+};
+
+
+%{C++
+
+// the first part of the contractID for any loader
+// append the type of loader that you need, such as "zip"
+#define NS_XPTLOADER_CONTRACTID_PREFIX \
+ "@mozilla.org/xptinfo/loader;1&type="
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h
new file mode 100644
index 00000000..076482a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* XPTI_PUBLIC_API and XPTI_GetInterfaceInfoManager declarations. */
+
+#ifndef xptiinfo_h___
+#define xptiinfo_h___
+
+#include "prtypes.h"
+#include "xpt_struct.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPTI_GetInterfaceInfoManager VBoxNsxpXPTI_GetInterfaceInfoManager
+#define XPTI_FreeInterfaceInfoManager VBoxNsxpXPTI_FreeInterfaceInfoManager
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*
+ * The linkage of XPTI API functions differs depending on whether the file is
+ * used within the XPTI library or not. Any source file within the XPTI
+ * library should define EXPORT_XPTI_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPTI_API
+#define XPTI_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPTI_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#if defined(_WIN32)
+# define XPTI_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTI_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2_VACPP)
+# define XPTI_EXPORT extern
+#else
+# define XPTI_EXPORT
+#endif
+#else
+#if defined(_WIN32)
+# define XPTI_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTI_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTI_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTI_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTI_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTI_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2_VACPP)
+# define XPTI_PUBLIC_API(t) extern t
+# define XPTI_PUBLIC_DATA(t) extern t
+# define XPTI_EXPORT extern
+#else
+# define XPTI_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPTI_PUBLIC_DATA(t) t
+# define XPTI_EXPORT
+#endif
+#endif
+#define XPTI_FRIEND_API(t) XPTI_PUBLIC_API(t)
+#define XPTI_FRIEND_DATA(t) XPTI_PUBLIC_DATA(t)
+
+class nsIInterfaceInfoManager;
+PR_BEGIN_EXTERN_C
+// Even if this is a service, it is cool to provide a direct accessor
+XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
+XPTI_GetInterfaceInfoManager();
+
+// Even if this is a service, it is cool to provide a direct accessor
+XPTI_PUBLIC_API(void)
+XPTI_FreeInterfaceInfoManager();
+PR_END_EXTERN_C
+
+
+
+// Flyweight wrapper classes for xpt_struct.h structs.
+// Everything here is dependent upon - and sensitive to changes in -
+// xpcom/typelib/xpt/public/xpt_struct.h!
+
+class nsXPTType : public XPTTypeDescriptorPrefix
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTType()
+ {} // random contents
+ nsXPTType(const XPTTypeDescriptorPrefix& prefix)
+ {*(XPTTypeDescriptorPrefix*)this = prefix;}
+
+ nsXPTType(const uint8& prefix)
+ {*(uint8*)this = prefix;}
+
+ nsXPTType& operator=(uint8 val)
+ {flags = val; return *this;}
+
+ nsXPTType& operator=(const nsXPTType& other)
+ {flags = other.flags; return *this;}
+
+ operator uint8() const
+ {return flags;}
+
+ PRBool IsPointer() const
+ {return 0 != (XPT_TDP_IS_POINTER(flags));}
+
+ PRBool IsUniquePointer() const
+ {return 0 != (XPT_TDP_IS_UNIQUE_POINTER(flags));}
+
+ PRBool IsReference() const
+ {return 0 != (XPT_TDP_IS_REFERENCE(flags));}
+
+ PRBool IsArithmetic() const // terminology from Harbison/Steele
+ {return flags <= T_WCHAR;}
+
+ PRBool IsInterfacePointer() const
+ { switch (TagPart()) {
+ default:
+ return PR_FALSE;
+ case T_INTERFACE:
+ case T_INTERFACE_IS:
+ return PR_TRUE;
+ }
+ }
+
+ PRBool IsArray() const
+ {return (PRBool) TagPart() == T_ARRAY;}
+
+ // 'Dependent' means that params of this type are dependent upon other
+ // params. e.g. an T_INTERFACE_IS is dependent upon some other param at
+ // runtime to say what the interface type of this param really is.
+ PRBool IsDependent() const
+ { switch (TagPart()) {
+ default:
+ return PR_FALSE;
+ case T_INTERFACE_IS:
+ case TD_ARRAY:
+ case T_PSTRING_SIZE_IS:
+ case T_PWSTRING_SIZE_IS:
+ return PR_TRUE;
+ }
+ }
+
+ uint8 TagPart() const
+ {return (uint8) (flags & XPT_TDP_TAGMASK);}
+
+ enum
+ {
+ T_I8 = TD_INT8 ,
+ T_I16 = TD_INT16 ,
+ T_I32 = TD_INT32 ,
+ T_I64 = TD_INT64 ,
+ T_U8 = TD_UINT8 ,
+ T_U16 = TD_UINT16 ,
+ T_U32 = TD_UINT32 ,
+ T_U64 = TD_UINT64 ,
+ T_FLOAT = TD_FLOAT ,
+ T_DOUBLE = TD_DOUBLE ,
+ T_BOOL = TD_BOOL ,
+ T_CHAR = TD_CHAR ,
+ T_WCHAR = TD_WCHAR ,
+ T_VOID = TD_VOID ,
+ T_IID = TD_PNSIID ,
+ T_DOMSTRING = TD_DOMSTRING ,
+ T_CHAR_STR = TD_PSTRING ,
+ T_WCHAR_STR = TD_PWSTRING ,
+ T_INTERFACE = TD_INTERFACE_TYPE ,
+ T_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
+ T_ARRAY = TD_ARRAY ,
+ T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS ,
+ T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
+ T_UTF8STRING = TD_UTF8STRING ,
+ T_CSTRING = TD_CSTRING ,
+ T_ASTRING = TD_ASTRING
+ };
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTParamInfo : public XPTParamDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTParamInfo(const XPTParamDescriptor& desc)
+ {*(XPTParamDescriptor*)this = desc;}
+
+
+ PRBool IsIn() const {return 0 != (XPT_PD_IS_IN(flags));}
+ PRBool IsOut() const {return 0 != (XPT_PD_IS_OUT(flags));}
+ PRBool IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));}
+ PRBool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
+ PRBool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(flags));}
+ const nsXPTType GetType() const {return type.prefix;}
+
+ // NOTE: other activities on types are done via methods on nsIInterfaceInfo
+
+private:
+ nsXPTParamInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTMethodInfo : public XPTMethodDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTMethodInfo(const XPTMethodDescriptor& desc)
+ {*(XPTMethodDescriptor*)this = desc;}
+
+ PRBool IsGetter() const {return 0 != (XPT_MD_IS_GETTER(flags) );}
+ PRBool IsSetter() const {return 0 != (XPT_MD_IS_SETTER(flags) );}
+ PRBool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));}
+ PRBool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );}
+ PRBool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
+ const char* GetName() const {return name;}
+ uint8 GetParamCount() const {return num_args;}
+ /* idx was index before I got _sick_ of the warnings on Unix, sorry jband */
+ const nsXPTParamInfo GetParam(uint8 idx) const
+ {
+ NS_PRECONDITION(idx < GetParamCount(),"bad arg");
+ return params[idx];
+ }
+ const nsXPTParamInfo GetResult() const
+ {return *result;}
+private:
+ nsXPTMethodInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+
+// forward declaration
+struct nsXPTCMiniVariant;
+
+class nsXPTConstant : public XPTConstDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTConstant(const XPTConstDescriptor& desc)
+ {*(XPTConstDescriptor*)this = desc;}
+
+ const char* GetName() const
+ {return name;}
+
+ const nsXPTType GetType() const
+ {return type.prefix;}
+
+ // XXX this is ugly. But sometimes you gotta do what you gotta do.
+ // A reinterpret_cast won't do the trick here. And this plain C cast
+ // works correctly and is safe enough.
+ // See http://bugzilla.mozilla.org/show_bug.cgi?id=49641
+ const nsXPTCMiniVariant* GetValue() const
+ {return (nsXPTCMiniVariant*) &value;}
+private:
+ nsXPTConstant(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+#endif /* xptiinfo_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in
new file mode 100644
index 00000000..de5fd9b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in
@@ -0,0 +1,75 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xptinfo
+REQUIRES = \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ xptiFile.cpp \
+ xptiInterfaceInfo.cpp \
+ xptiInterfaceInfoManager.cpp \
+ xptiManifest.cpp \
+ xptiMisc.cpp \
+ xptiTypelibGuts.cpp \
+ xptiWorkingSet.cpp \
+ xptiZipItem.cpp \
+ xptiZipLoader.cpp \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+# For nsManifestLineReader class.
+LOCAL_INCLUDES = -I$(srcdir)/../../../ds
+
+DEFINES += -DEXPORT_XPTI_API -DEXPORT_XPT_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO
new file mode 100644
index 00000000..c5bb1c64
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO
@@ -0,0 +1,20 @@
+/* jband - 03/24/00 - */
+
+- DOCS
+- improve error handling
+ - should some errors really be warnings?
+ - should autoreg support additional channel to recieve warnings so that
+ an installer can decide whether or not to accept the consequences of
+ leaving the newly installed files in place?
+- verification of interfaces (warnings and/or errors)
+ - verify that repeated interfaces are identical in all ways
+ - verify that interface names are always one-to-one with iids
+- check for truncated xpt files and version problems
+ - http://bugzilla.mozilla.org/show_bug.cgi?id=33193
+- TESTS!
+ - e.g. verify the merge stuff really works for various inputs.
+ - we really need a set of .xpt and .zip files and code that does an array
+ of autoreg and interfaceinof use activitities to test various corners
+ of the system.
+- better autoreg logging
+- use only 32 bits for file size?
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp
new file mode 100644
index 00000000..50362c75
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiFile. */
+
+#include "xptiprivate.h"
+
+MOZ_DECL_CTOR_COUNTER(xptiFile)
+
+xptiFile::xptiFile()
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(nsnull),
+#endif
+ mSize(),
+ mDate(),
+ mName(nsnull),
+ mGuts(nsnull),
+ mDirectory(0)
+{
+ // empty
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mSize(aSize),
+ mDate(aDate),
+ mName(aName),
+ mGuts(nsnull),
+ mDirectory(aDirectory)
+{
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
+
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mSize(r.mSize),
+ mDate(r.mDate),
+ mName(nsnull),
+ mGuts(nsnull),
+ mDirectory(r.mDirectory)
+{
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
+
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::~xptiFile()
+{
+ MOZ_COUNT_DTOR(xptiFile);
+}
+
+PRBool
+xptiFile::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(!mGuts,"bad state");
+ NS_ASSERTION(aHeader,"bad param");
+ NS_ASSERTION(aWorkingSet,"bad param");
+
+ mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
+ return mGuts != nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp
new file mode 100644
index 00000000..69bf86df
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp
@@ -0,0 +1,819 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
+
+#include "xptiprivate.h"
+
+/***************************************************************************/
+// Debug Instrumentation...
+
+#ifdef SHOW_INFO_COUNT_STATS
+static int DEBUG_TotalInfos = 0;
+static int DEBUG_CurrentInfos = 0;
+static int DEBUG_MaxInfos = 0;
+static int DEBUG_MonitorEntryCount = 0;
+
+#define LOG_INFO_CREATE(t) \
+ DEBUG_TotalInfos++; \
+ DEBUG_CurrentInfos++; \
+ if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \
+ DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */
+
+#define LOG_INFO_DESTROY(t) \
+ DEBUG_CurrentInfos-- /* no ';' */
+
+#define LOG_INFO_MONITOR_ENTRY \
+ DEBUG_MonitorEntryCount++ /* no ';' */
+
+#else /* SHOW_INFO_COUNT_STATS */
+
+#define LOG_INFO_CREATE(t) ((void)0)
+#define LOG_INFO_DESTROY(t) ((void)0)
+#define LOG_INFO_MONITOR_ENTRY ((void)0)
+#endif /* SHOW_INFO_COUNT_STATS */
+
+#ifdef DEBUG
+// static
+void xptiInterfaceInfo::DEBUG_ShutdownNotification()
+{
+#ifdef SHOW_INFO_COUNT_STATS
+ printf("iiii %d total xptiInterfaceInfos created\n", DEBUG_TotalInfos);
+ printf("iiii %d max xptiInterfaceInfos alive at one time\n", DEBUG_MaxInfos);
+ printf("iiii %d xptiInterfaceInfos still alive\n", DEBUG_CurrentInfos);
+ printf("iiii %d times locked\n", DEBUG_MonitorEntryCount);
+#endif
+}
+#endif /* DEBUG */
+
+/***************************************************************************/
+
+// static
+xptiInterfaceEntry*
+xptiInterfaceEntry::NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet)
+{
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceEntry) + nameLength);
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceEntry(name, nameLength, iid, typelib);
+}
+
+// static
+xptiInterfaceEntry*
+xptiInterfaceEntry::NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet)
+{
+ size_t nameLength = PL_strlen(r.mName);
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceEntry) + nameLength);
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceEntry(r, nameLength, typelib);
+}
+
+
+xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib)
+ : mIID(iid),
+ mTypelib(typelib),
+ mInfo(nsnull),
+ mFlags(uint8(0))
+{
+ memcpy(mName, name, nameLength);
+}
+
+xptiInterfaceEntry::xptiInterfaceEntry(const xptiInterfaceEntry& r,
+ size_t nameLength,
+ const xptiTypelib& typelib)
+ : mIID(r.mIID),
+ mTypelib(typelib),
+ mInfo(nsnull),
+ mFlags(r.mFlags)
+{
+ SetResolvedState(NOT_RESOLVED);
+ memcpy(mName, r.mName, nameLength);
+}
+
+PRBool
+xptiInterfaceEntry::Resolve(xptiWorkingSet* aWorkingSet /* = nsnull */)
+{
+ nsAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
+ return ResolveLocked(aWorkingSet);
+}
+
+PRBool
+xptiInterfaceEntry::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
+{
+ int resolvedState = GetResolveState();
+
+ if(resolvedState == FULLY_RESOLVED)
+ return PR_TRUE;
+ if(resolvedState == RESOLVE_FAILED)
+ return PR_FALSE;
+
+ xptiInterfaceInfoManager* mgr =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+
+ if(!mgr)
+ return PR_FALSE;
+
+ if(!aWorkingSet)
+ {
+ aWorkingSet = mgr->GetWorkingSet();
+ }
+
+ if(resolvedState == NOT_RESOLVED)
+ {
+ LOG_RESOLVE(("! begin resolve of %s\n", mName));
+ // Make a copy of mTypelib because the underlying memory will change!
+ xptiTypelib typelib = mTypelib;
+
+ // We expect our PartiallyResolveLocked() to get called before
+ // this returns.
+ if(!mgr->LoadFile(typelib, aWorkingSet))
+ {
+ SetResolvedState(RESOLVE_FAILED);
+ return PR_FALSE;
+ }
+ // The state was changed by LoadFile to PARTIALLY_RESOLVED, so this
+ // ...falls through...
+ }
+
+ NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
+
+ // Finish out resolution by finding parent and Resolving it so
+ // we can set the info we get from it.
+
+ PRUint16 parent_index = mInterface->mDescriptor->parent_interface;
+
+ if(parent_index)
+ {
+ xptiInterfaceEntry* parent =
+ aWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
+ GetEntryAt(parent_index - 1);
+
+ if(!parent || !parent->EnsureResolvedLocked())
+ {
+ xptiTypelib aTypelib = mInterface->mTypelib;
+ mInterface = nsnull;
+ mTypelib = aTypelib;
+ SetResolvedState(RESOLVE_FAILED);
+ return PR_FALSE;
+ }
+
+ mInterface->mParent = parent;
+
+ mInterface->mMethodBaseIndex =
+ parent->mInterface->mMethodBaseIndex +
+ parent->mInterface->mDescriptor->num_methods;
+
+ mInterface->mConstantBaseIndex =
+ parent->mInterface->mConstantBaseIndex +
+ parent->mInterface->mDescriptor->num_constants;
+
+ }
+ LOG_RESOLVE(("+ complete resolve of %s\n", mName));
+
+ SetResolvedState(FULLY_RESOLVED);
+ return PR_TRUE;
+}
+
+// This *only* gets called by xptiInterfaceInfoManager::LoadFile (while locked).
+PRBool
+xptiInterfaceEntry::PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(GetResolveState() == NOT_RESOLVED, "bad state");
+
+ LOG_RESOLVE(("~ partial resolve of %s\n", mName));
+
+ xptiInterfaceGuts* iface =
+ xptiInterfaceGuts::NewGuts(aDescriptor, mTypelib, aWorkingSet);
+
+ if(!iface)
+ return PR_FALSE;
+
+ mInterface = iface;
+
+#ifdef DEBUG
+ if(!DEBUG_ScriptableFlagIsValid())
+ {
+ NS_ERROR("unexpected scriptable flag!");
+ SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags));
+ }
+#endif
+
+ SetResolvedState(PARTIALLY_RESOLVED);
+ return PR_TRUE;
+}
+
+/**************************************************/
+// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+nsresult
+xptiInterfaceEntry::GetName(char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
+ return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::GetIID(nsIID **iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
+ return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::IsScriptable(PRBool* result)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ NS_ASSERTION(DEBUG_ScriptableFlagIsValid(), "scriptable flag out of sync!");
+ *result = GetScriptableFlag();
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::IsFunction(PRBool* result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *result = XPT_ID_IS_FUNCTION(GetInterfaceGuts()->mDescriptor->flags);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodCount(uint16* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetConstantCount(uint16* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mInterface->mConstantBaseIndex +
+ mInterface->mDescriptor->num_constants;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->GetMethodInfo(index, info);
+
+ if(index >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ *info = NULL;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
+ &mInterface->mDescriptor->
+ method_descriptors[index -
+ mInterface->mMethodBaseIndex]);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16 *index,
+ const nsXPTMethodInfo** result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ // This is a slow algorithm, but this is not expected to be called much.
+ for(uint16 i = 0; i < mInterface->mDescriptor->num_methods; ++i)
+ {
+ const nsXPTMethodInfo* info;
+ info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
+ &mInterface->mDescriptor->
+ method_descriptors[i]);
+ if (PL_strcmp(methodName, info->GetName()) == 0) {
+ *index = i + mInterface->mMethodBaseIndex;
+ *result = info;
+ return NS_OK;
+ }
+ }
+
+ if(mInterface->mParent)
+ return mInterface->mParent->GetMethodInfoForName(methodName, index, result);
+ else
+ {
+ *index = 0;
+ *result = 0;
+ return NS_ERROR_INVALID_ARG;
+ }
+}
+
+nsresult
+xptiInterfaceEntry::GetConstant(uint16 index, const nsXPTConstant** constant)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mInterface->mConstantBaseIndex)
+ return mInterface->mParent->GetConstant(index, constant);
+
+ if(index >= mInterface->mConstantBaseIndex +
+ mInterface->mDescriptor->num_constants)
+ {
+ NS_PRECONDITION(0, "bad param");
+ *constant = NULL;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *constant =
+ NS_REINTERPRET_CAST(nsXPTConstant*,
+ &mInterface->mDescriptor->
+ const_descriptors[index -
+ mInterface->mConstantBaseIndex]);
+ return NS_OK;
+}
+
+// this is a private helper
+
+nsresult
+xptiInterfaceEntry::GetEntryForParam(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->GetEntryForParam(methodIndex, param, entry);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mInterface->mDescriptor->additional_types[td->type.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
+ NS_ERROR("not an interface");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ xptiInterfaceEntry* theEntry =
+ mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
+ GetEntryAt(td->type.iface - 1);
+
+ // This can happen if a declared interface is not available at runtime.
+ if(!theEntry)
+ {
+ NS_WARNING("Declared InterfaceInfo not found");
+ *entry = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ *entry = theEntry;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInfoForParam(uint16 methodIndex,
+ const nsXPTParamInfo *param,
+ nsIInterfaceInfo** info)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+
+ xptiInterfaceInfo* theInfo;
+ rv = entry->GetInterfaceInfo(&theInfo);
+ if(NS_FAILED(rv))
+ return rv;
+
+ *info = NS_STATIC_CAST(nsIInterfaceInfo*, theInfo);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param, nsIID** iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+ return entry->GetIID(iid);
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParamNoAlloc(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ nsIID *iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+ *iid = entry->mIID;
+ return NS_OK;
+}
+
+// this is a private helper
+nsresult
+xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
+ uint16 dimension,
+ const XPTTypeDescriptor** type)
+{
+ NS_ASSERTION(IsFullyResolved(), "bad state");
+
+ const XPTTypeDescriptor *td = &param->type;
+ const XPTTypeDescriptor *additional_types =
+ mInterface->mDescriptor->additional_types;
+
+ for (uint16 i = 0; i < dimension; i++) {
+ if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
+ NS_ERROR("bad dimension");
+ return NS_ERROR_INVALID_ARG;
+ }
+ td = &additional_types[td->type.additional_type];
+ }
+
+ *type = td;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetTypeForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ nsXPTType* type)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetTypeForParam(methodIndex, param, dimension, type);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ *type = nsXPTType(td->prefix);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has size_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ break;
+ default:
+ NS_ERROR("not a size_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetLengthIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetLengthIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has length_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ break;
+ default:
+ NS_ERROR("not a length_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum2;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mInterface->mDescriptor->
+ additional_types[td->type.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
+ NS_ERROR("not an iid_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum;
+ return NS_OK;
+}
+
+/* PRBool isIID (in nsIIDPtr IID); */
+nsresult
+xptiInterfaceEntry::IsIID(const nsIID * IID, PRBool *_retval)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *_retval = mIID.Equals(*IID);
+ return NS_OK;
+}
+
+/* void getNameShared ([shared, retval] out string name); */
+nsresult
+xptiInterfaceEntry::GetNameShared(const char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = mName;
+ return NS_OK;
+}
+
+/* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */
+nsresult
+xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = &mIID;
+ return NS_OK;
+}
+
+/* PRBool hasAncestor (in nsIIDPtr iid); */
+nsresult
+xptiInterfaceEntry::HasAncestor(const nsIID * iid, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ for(xptiInterfaceEntry* current = this;
+ current;
+ current = current->mInterface->mParent)
+ {
+ if(current->mIID.Equals(*iid))
+ {
+ *_retval = PR_TRUE;
+ break;
+ }
+ if(!current->EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+/***************************************************/
+
+nsresult
+xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
+{
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ LOG_INFO_MONITOR_ENTRY;
+
+#ifdef SHOW_INFO_COUNT_STATS
+ static int callCount = 0;
+ if(!(++callCount%100))
+ printf("iiii %d xptiInterfaceInfos currently alive\n", DEBUG_CurrentInfos);
+#endif
+
+ if(!mInfo)
+ {
+ mInfo = new xptiInterfaceInfo(this);
+ if(!mInfo)
+ {
+ *info = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ NS_ADDREF(*info = mInfo);
+ return NS_OK;
+}
+
+void
+xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
+{
+ if(mInfo)
+ {
+ mInfo->Invalidate();
+ mInfo = nsnull;
+ }
+}
+
+/***************************************************************************/
+
+NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
+
+xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
+ : mEntry(entry), mParent(nsnull)
+{
+ LOG_INFO_CREATE(this);
+}
+
+xptiInterfaceInfo::~xptiInterfaceInfo()
+{
+ LOG_INFO_DESTROY(this);
+ NS_IF_RELEASE(mParent);
+ NS_ASSERTION(!mEntry, "bad state in dtor");
+}
+
+nsrefcnt
+xptiInterfaceInfo::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
+ return cnt;
+}
+
+nsrefcnt
+xptiInterfaceInfo::Release(void)
+{
+ xptiInterfaceEntry* entry = mEntry;
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+ NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
+ if(!cnt)
+ {
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ LOG_INFO_MONITOR_ENTRY;
+
+ // If GetInterfaceInfo added and *released* a reference before we
+ // acquired the monitor then 'this' might already be dead. In that
+ // case we would not want to try to access any instance data. We
+ // would want to bail immediately. If 'this' is already dead then the
+ // entry will no longer have a pointer to 'this'. So, we can protect
+ // ourselves from danger without more aggressive locking.
+ if(entry && !entry->InterfaceInfoEquals(this))
+ return 0;
+
+ // If GetInterfaceInfo added a reference before we acquired the monitor
+ // then we want to bail out of here without destorying the object.
+ if(mRefCnt)
+ return 1;
+
+ if(mEntry)
+ {
+ mEntry->LockedInterfaceInfoDeathNotification();
+ mEntry = nsnull;
+ }
+
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return cnt;
+}
+
+/***************************************************************************/
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
new file mode 100644
index 00000000..5ae06914
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
@@ -0,0 +1,2126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiInterfaceInfoManager. */
+
+#include "xptiprivate.h"
+#include "nsDependentString.h"
+#include "nsString.h"
+
+#define NS_ZIPLOADER_CONTRACTID NS_XPTLOADER_CONTRACTID_PREFIX "zip"
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(xptiInterfaceInfoManager,
+ nsIInterfaceInfoManager,
+ nsIInterfaceInfoSuperManager)
+
+static xptiInterfaceInfoManager* gInterfaceInfoManager = nsnull;
+#ifdef DEBUG
+static int gCallCount = 0;
+#endif
+
+// static
+xptiInterfaceInfoManager*
+xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef()
+{
+ if(!gInterfaceInfoManager)
+ {
+ nsCOMPtr<nsISupportsArray> searchPath;
+ BuildFileSearchPath(getter_AddRefs(searchPath));
+ if(!searchPath)
+ {
+ NS_ERROR("can't get xpt search path!");
+ return nsnull;
+ }
+
+ gInterfaceInfoManager = new xptiInterfaceInfoManager(searchPath);
+ if(gInterfaceInfoManager)
+ NS_ADDREF(gInterfaceInfoManager);
+ if(!gInterfaceInfoManager->IsValid())
+ {
+ NS_RELEASE(gInterfaceInfoManager);
+ }
+ else
+ {
+ PRBool mustAutoReg =
+ !xptiManifest::Read(gInterfaceInfoManager,
+ &gInterfaceInfoManager->mWorkingSet);
+#ifdef DEBUG
+ {
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(gInterfaceInfoManager,
+ gInterfaceInfoManager->mAutoRegLogFile, PR_TRUE);
+ LOG_AUTOREG(("debug build forced autoreg after %s load of manifest\n", mustAutoReg ? "FAILED" : "successful"));
+
+ mustAutoReg = PR_TRUE;
+ }
+#endif // DEBUG
+ if(mustAutoReg)
+ gInterfaceInfoManager->AutoRegisterInterfaces();
+ }
+ }
+ return gInterfaceInfoManager;
+}
+
+void
+xptiInterfaceInfoManager::FreeInterfaceInfoManager()
+{
+ if(gInterfaceInfoManager)
+ gInterfaceInfoManager->LogStats();
+
+ NS_IF_RELEASE(gInterfaceInfoManager);
+}
+
+PRBool
+xptiInterfaceInfoManager::IsValid()
+{
+ return mWorkingSet.IsValid() &&
+ mResolveLock &&
+ mAutoRegLock &&
+ mInfoMonitor &&
+ mAdditionalManagersLock;
+}
+
+xptiInterfaceInfoManager::xptiInterfaceInfoManager(nsISupportsArray* aSearchPath)
+ : mWorkingSet(aSearchPath),
+ mOpenLogFile(nsnull),
+ mResolveLock(PR_NewLock()),
+ mAutoRegLock(PR_NewLock()),
+ mInfoMonitor(nsAutoMonitor::NewMonitor("xptiInfoMonitor")),
+ mAdditionalManagersLock(PR_NewLock()),
+ mSearchPath(aSearchPath)
+{
+ const char* statsFilename = PR_GetEnv("MOZILLA_XPTI_STATS");
+ if(statsFilename)
+ {
+ mStatsLogFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if(mStatsLogFile &&
+ NS_SUCCEEDED(mStatsLogFile->InitWithNativePath(nsDependentCString(statsFilename))))
+ {
+ printf("* Logging xptinfo stats to: %s\n", statsFilename);
+ }
+ else
+ {
+ printf("* Failed to create xptinfo stats file: %s\n", statsFilename);
+ mStatsLogFile = nsnull;
+ }
+ }
+
+ const char* autoRegFilename = PR_GetEnv("MOZILLA_XPTI_REGLOG");
+ if(autoRegFilename)
+ {
+ mAutoRegLogFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if(mAutoRegLogFile &&
+ NS_SUCCEEDED(mAutoRegLogFile->InitWithNativePath(nsDependentCString(autoRegFilename))))
+ {
+ printf("* Logging xptinfo autoreg to: %s\n", autoRegFilename);
+ }
+ else
+ {
+ printf("* Failed to create xptinfo autoreg file: %s\n", autoRegFilename);
+ mAutoRegLogFile = nsnull;
+ }
+ }
+}
+
+xptiInterfaceInfoManager::~xptiInterfaceInfoManager()
+{
+ // We only do this on shutdown of the service.
+ mWorkingSet.InvalidateInterfaceInfos();
+
+ if(mResolveLock)
+ PR_DestroyLock(mResolveLock);
+ if(mAutoRegLock)
+ PR_DestroyLock(mAutoRegLock);
+ if(mInfoMonitor)
+ nsAutoMonitor::DestroyMonitor(mInfoMonitor);
+ if(mAdditionalManagersLock)
+ PR_DestroyLock(mAdditionalManagersLock);
+
+ gInterfaceInfoManager = nsnull;
+#ifdef DEBUG
+ xptiInterfaceInfo::DEBUG_ShutdownNotification();
+ gCallCount = 0;
+#endif
+}
+
+static nsresult
+GetDirectoryFromDirService(const char* codename, nsILocalFile** aDir)
+{
+ NS_ASSERTION(codename,"loser!");
+ NS_ASSERTION(aDir,"loser!");
+
+ nsresult rv;
+ nsCOMPtr<nsIProperties> dirService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ return dirService->Get(codename, NS_GET_IID(nsILocalFile), (void**) aDir);
+}
+
+static PRBool
+AppendFromDirServiceList(const char* codename, nsISupportsArray* aPath)
+{
+ NS_ASSERTION(codename,"loser!");
+ NS_ASSERTION(aPath,"loser!");
+
+ nsCOMPtr<nsIProperties> dirService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+ if(!dirService)
+ return PR_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> fileList;
+ dirService->Get(codename, NS_GET_IID(nsISimpleEnumerator),
+ getter_AddRefs(fileList));
+ if(!fileList)
+ return PR_FALSE;
+
+ PRBool more;
+ while(NS_SUCCEEDED(fileList->HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ fileList->GetNext(getter_AddRefs(dir));
+ if(!dir || !aPath->AppendElement(dir))
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+// static
+PRBool xptiInterfaceInfoManager::BuildFileSearchPath(nsISupportsArray** aPath)
+{
+#ifdef DEBUG
+ NS_ASSERTION(!gCallCount++, "Expected only one call!");
+#endif
+
+ nsCOMPtr<nsISupportsArray> searchPath;
+ NS_NewISupportsArray(getter_AddRefs(searchPath));
+ if(!searchPath)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> compDir;
+
+ // Always put components directory first
+
+ if(NS_FAILED(GetDirectoryFromDirService(NS_XPCOM_COMPONENT_DIR,
+ getter_AddRefs(compDir))) ||
+ !searchPath->AppendElement(compDir))
+ {
+ return PR_FALSE;
+ }
+
+ // Add additional plugins dirs
+ // No error checking here since this is optional in some embeddings
+
+ // Add the GRE's component directory to searchPath if the
+ // application is using an GRE.
+ // An application indicates that it's using an GRE by returning
+ // a valid nsIFile via it's directory service provider interface.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/MRE.html
+ // for more info. on GREs
+ //
+ nsCOMPtr<nsILocalFile> greComponentDirectory;
+ nsresult rv = GetDirectoryFromDirService(NS_GRE_COMPONENT_DIR,
+ getter_AddRefs(greComponentDirectory));
+ if(NS_SUCCEEDED(rv) && greComponentDirectory)
+ {
+ // make sure we only append a directory if its a different one
+ PRBool equalsCompDir = PR_FALSE;
+ greComponentDirectory->Equals(compDir, &equalsCompDir);
+
+ if(!equalsCompDir)
+ searchPath->AppendElement(greComponentDirectory);
+ }
+
+ (void)AppendFromDirServiceList(NS_XPCOM_COMPONENT_DIR_LIST, searchPath);
+ (void)AppendFromDirServiceList(NS_APP_PLUGINS_DIR_LIST, searchPath);
+
+ NS_ADDREF(*aPath = searchPath);
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::GetCloneOfManifestLocation(nsILocalFile** aFile)
+{
+ // We *trust* that this will not change!
+ nsCOMPtr<nsILocalFile> lf;
+ nsresult rv = GetDirectoryFromDirService(NS_XPCOM_XPTI_REGISTRY_FILE,
+ getter_AddRefs(lf));
+
+ if (NS_FAILED(rv)) return PR_FALSE;
+
+ rv = xptiCloneLocalFile(lf, aFile);
+ if (NS_FAILED(rv)) return PR_FALSE;
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::GetApplicationDir(nsILocalFile** aDir)
+{
+ // We *trust* that this will not change!
+ return NS_SUCCEEDED(GetDirectoryFromDirService(NS_XPCOM_CURRENT_PROCESS_DIR, aDir));
+}
+
+PRBool
+xptiInterfaceInfoManager::BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList)
+{
+ NS_ASSERTION(aFileList, "loser!");
+
+ nsresult rv;
+
+ nsCOMPtr<nsISupportsArray> fileList =
+ do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
+ if(!fileList)
+ return PR_FALSE;
+
+ PRUint32 pathCount;
+ if(NS_FAILED(aSearchPath->Count(&pathCount)))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < pathCount; i++)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ rv = xptiCloneElementAsLocalFile(aSearchPath, i, getter_AddRefs(dir));
+ if(NS_FAILED(rv) || !dir)
+ return PR_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
+ if(NS_FAILED(rv) || !entries)
+ continue;
+
+ PRUint32 count = 0;
+ PRBool hasMore;
+ while(NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> sup;
+ entries->GetNext(getter_AddRefs(sup));
+ if(!sup)
+ return PR_FALSE;
+ nsCOMPtr<nsILocalFile> file = do_QueryInterface(sup);
+ if(!file)
+ return PR_FALSE;
+
+ PRBool isFile;
+ if(NS_FAILED(file->IsFile(&isFile)) || !isFile)
+ {
+ continue;
+ }
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ if(xptiFileType::IsUnknown(name.get()))
+ continue;
+
+ LOG_AUTOREG(("found file: %s\n", name.get()));
+
+ if(!fileList->InsertElementAt(file, count))
+ return PR_FALSE;
+ ++count;
+ }
+ }
+
+ NS_ADDREF(*aFileList = fileList);
+ return PR_TRUE;
+}
+
+XPTHeader*
+xptiInterfaceInfoManager::ReadXPTFile(nsILocalFile* aFile,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aFile, "loser!");
+
+ XPTHeader *header = nsnull;
+ char *whole = nsnull;
+ PRFileDesc* fd = nsnull;
+ XPTState *state = nsnull;
+ XPTCursor cursor;
+ PRInt32 flen;
+ PRInt64 fileSize;
+
+ PRBool saveFollowLinks;
+ aFile->GetFollowLinks(&saveFollowLinks);
+ aFile->SetFollowLinks(PR_TRUE);
+
+ if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
+ {
+ aFile->SetFollowLinks(saveFollowLinks);
+ return nsnull;
+ }
+
+ whole = new char[flen];
+ if (!whole)
+ {
+ aFile->SetFollowLinks(saveFollowLinks);
+ return nsnull;
+ }
+
+ // all exits from on here should be via 'goto out'
+
+ if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
+ {
+ goto out;
+ }
+
+ if(flen > PR_Read(fd, whole, flen))
+ {
+ goto out;
+ }
+
+ if(!(state = XPT_NewXDRState(XPT_DECODE, whole, flen)))
+ {
+ goto out;
+ }
+
+ if(!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor))
+ {
+ goto out;
+ }
+
+ if (!XPT_DoHeader(aWorkingSet->GetStructArena(), &cursor, &header))
+ {
+ header = nsnull;
+ goto out;
+ }
+
+ out:
+ if(fd)
+ PR_Close(fd);
+ if(state)
+ XPT_DestroyXDRState(state);
+ if(whole)
+ delete [] whole;
+ aFile->SetFollowLinks(saveFollowLinks);
+ return header;
+}
+
+PRBool
+xptiInterfaceInfoManager::LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet)
+{
+ if(!aWorkingSet)
+ aWorkingSet = &mWorkingSet;
+
+ if(!aWorkingSet->IsValid())
+ return PR_FALSE;
+
+ xptiFile* fileRecord = &aWorkingSet->GetFileAt(aTypelibRecord.GetFileIndex());
+ xptiZipItem* zipItem = nsnull;
+
+ nsCOMPtr<nsILocalFile> file;
+ if(NS_FAILED(aWorkingSet->GetCloneOfDirectoryAt(fileRecord->GetDirectory(),
+ getter_AddRefs(file))) || !file)
+ return PR_FALSE;
+
+ if(NS_FAILED(file->AppendNative(nsDependentCString(fileRecord->GetName()))))
+ return PR_FALSE;
+
+ XPTHeader* header;
+
+ if(aTypelibRecord.IsZip())
+ {
+ zipItem = &aWorkingSet->GetZipItemAt(aTypelibRecord.GetZipItemIndex());
+
+ // See the big comment below in the 'non-zip' case...
+ if(zipItem->GetGuts())
+ {
+ NS_ERROR("Trying to load an xpt file from a zip twice");
+
+ // Force an autoreg on next run
+ (void) xptiManifest::Delete(this);
+
+ return PR_FALSE;
+ }
+
+ LOG_LOAD(("# loading zip item %s::%s\n", fileRecord->GetName(), zipItem->GetName()));
+
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIInputStream> stream;
+ rv = loader->LoadEntry(file, zipItem->GetName(),
+ getter_AddRefs(stream));
+
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+
+ header =
+ xptiZipLoader::ReadXPTFileFromInputStream(stream, aWorkingSet);
+ } else {
+ header = nsnull;
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ else
+ {
+ // The file would only have guts already if we previously failed to
+ // find an interface info in a file where the manifest claimed it was
+ // going to be.
+ //
+ // Normally, when the file gets loaded (and the guts set) then all
+ // interfaces would also be resolved. So, if we are here again for
+ // the same file then there must have been some interface that was
+ // expected but not present. Now we are explicitly trying to find it
+ // and it isn't going to be there this time either.
+ //
+ // This is an assertion style error in a DEBUG build because it shows
+ // that we failed to detect this in autoreg. For release builds (where
+ // autoreg is not run on every startup) it is just bad. But by returning
+ // PR_FALSE we mark this interface as RESOLVE_FAILED and get on with
+ // things without crashing or anything.
+ //
+ // We don't want to do an autoreg here because this is too much of an
+ // edge case (and in that odd case it might autoreg multiple times if
+ // many interfaces had been removed). But, by deleting the manifest we
+ // force the system to get it right on the next run.
+
+ if(fileRecord->GetGuts())
+ {
+ NS_ERROR("Trying to load an xpt file twice");
+
+ // Force an autoreg on next run
+ (void) xptiManifest::Delete(this);
+
+ return PR_FALSE;
+ }
+
+ LOG_LOAD(("^ loading file %s\n", fileRecord->GetName()));
+ header = ReadXPTFile(file, aWorkingSet);
+ }
+
+ if(!header)
+ return PR_FALSE;
+
+
+ if(aTypelibRecord.IsZip())
+ {
+ // This also allocs zipItem.GetGuts() used below.
+ if(!zipItem->SetHeader(header, aWorkingSet))
+ return PR_FALSE;
+ }
+ else
+ {
+ // This also allocs fileRecord.GetGuts() used below.
+ if(!fileRecord->SetHeader(header, aWorkingSet))
+ return PR_FALSE;
+ }
+
+ // For each interface in the header we want to find the xptiInterfaceInfo
+ // object and set its resolution info.
+
+ for(PRUint16 i = 0; i < header->num_interfaces; i++)
+ {
+ static const nsID zeroIID =
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+ XPTInterfaceDirectoryEntry* iface = header->interface_directory + i;
+
+ xptiHashEntry* hashEntry;
+
+ if(!iface->iid.Equals(zeroIID))
+ {
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ &iface->iid, PL_DHASH_LOOKUP);
+ }
+ else
+ {
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ iface->name, PL_DHASH_LOOKUP);
+ }
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ // This one is just not resolved anywhere!
+ continue;
+ }
+
+ if(aTypelibRecord.IsZip())
+ zipItem->GetGuts()->SetEntryAt(i, entry);
+ else
+ fileRecord->GetGuts()->SetEntryAt(i, entry);
+
+ XPTInterfaceDescriptor* descriptor = iface->interface_descriptor;
+
+ if(descriptor && aTypelibRecord.Equals(entry->GetTypelibRecord()))
+ entry->PartiallyResolveLocked(descriptor, aWorkingSet);
+ }
+ return PR_TRUE;
+}
+
+static int
+IndexOfFileWithName(const char* aName, const xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aName, "loser!");
+
+ for(PRUint32 i = 0; i < aWorkingSet->GetFileCount(); ++i)
+ {
+ if(0 == PL_strcmp(aName, aWorkingSet->GetFileAt(i).GetName()))
+ return i;
+ }
+ return -1;
+}
+
+static int
+IndexOfDirectoryOfFile(nsISupportsArray* aSearchPath, nsILocalFile* aFile)
+{
+ nsCOMPtr<nsIFile> parent;
+ aFile->GetParent(getter_AddRefs(parent));
+ if(parent)
+ {
+ PRUint32 count = 0;
+ aSearchPath->Count(&count);
+ NS_ASSERTION(count, "broken search path! bad count");
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIFile> current;
+ aSearchPath->QueryElementAt(i, NS_GET_IID(nsIFile),
+ getter_AddRefs(current));
+ NS_ASSERTION(current, "broken search path! bad element");
+ PRBool same;
+ if(NS_SUCCEEDED(parent->Equals(current, &same)) && same)
+ return (int) i;
+ }
+ }
+ NS_ERROR("file not in search directory!");
+ return -1;
+}
+
+struct SortData
+{
+ nsISupportsArray* mSearchPath;
+ xptiWorkingSet* mWorkingSet;
+};
+
+PR_STATIC_CALLBACK(int)
+xptiSortFileList(const void * p1, const void *p2, void * closure)
+{
+ nsILocalFile* pFile1 = *((nsILocalFile**) p1);
+ nsILocalFile* pFile2 = *((nsILocalFile**) p2);
+ SortData* data = (SortData*) closure;
+
+ nsCAutoString name1;
+ nsCAutoString name2;
+
+ if(NS_FAILED(pFile1->GetNativeLeafName(name1)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+ if(NS_FAILED(pFile2->GetNativeLeafName(name2)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+
+ int index1 = IndexOfFileWithName(name1.get(), data->mWorkingSet);
+ int index2 = IndexOfFileWithName(name2.get(), data->mWorkingSet);
+
+ // Get these now in case we need them later.
+ PRBool isXPT1 = xptiFileType::IsXPT(name1.get());
+ PRBool isXPT2 = xptiFileType::IsXPT(name2.get());
+ int nameOrder = Compare(name1, name2);
+
+ // both in workingSet, preserve old order
+ if(index1 != -1 && index2 != -1)
+ return index1 - index2;
+
+ if(index1 != -1)
+ return 1;
+
+ if(index2 != -1)
+ return -1;
+
+ // neither is in workingset
+
+ // check how they compare in search path order
+
+ int dirIndex1 = IndexOfDirectoryOfFile(data->mSearchPath, pFile1);
+ int dirIndex2 = IndexOfDirectoryOfFile(data->mSearchPath, pFile2);
+
+ if(dirIndex1 != dirIndex2)
+ return dirIndex1 - dirIndex2;
+
+ // .xpt files come before archives (.zip, .jar, etc)
+ if(isXPT1 &&!isXPT2)
+ return -1;
+
+ if(!isXPT1 && isXPT2)
+ return 1;
+
+ // neither element is in the workingSet and both are same type and in
+ // the same directory, sort by size
+
+ PRInt64 size1;
+ PRInt64 size2;
+
+ if(NS_FAILED(pFile1->GetFileSize(&size1)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+ if(NS_FAILED(pFile2->GetFileSize(&size2)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+
+ // by size with largest first, or by name if size is the same
+ int sizeDiff = int(PRInt32(nsInt64(size2) - nsInt64(size1)));
+ return sizeDiff != 0 ? sizeDiff : nameOrder;
+}
+
+nsILocalFile**
+xptiInterfaceInfoManager::BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ // We want to end up with a file list that starts with the files from
+ // aWorkingSet (but only those that are in aFileList) in the order in
+ // which they appeared in aWorkingSet-> Following those files will be those
+ // files in aFileList which are not in aWorkingSet-> These additional
+ // files will be ordered by file size (larger first) but all .xpt files
+ // will preceed all zipfile of those files not already in the working set.
+ // To do this we will do a fancy sort on a copy of aFileList.
+
+ nsILocalFile** orderedFileList = nsnull;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)) ||
+ 0 == countOfFilesInFileList)
+ return nsnull;
+
+ orderedFileList = (nsILocalFile**)
+ XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(nsILocalFile*) * countOfFilesInFileList);
+
+ if(!orderedFileList)
+ return nsnull;
+
+ // fill our list for sorting
+ for(i = 0; i < countOfFilesInFileList; ++i)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ // Intentionally NOT addref'd cuz we know these are pinned in aFileList.
+ orderedFileList[i] = file.get();
+ }
+
+ // sort the filelist
+
+ SortData sortData = {aSearchPath, aWorkingSet};
+ NS_QuickSort(orderedFileList, countOfFilesInFileList, sizeof(nsILocalFile*),
+ xptiSortFileList, &sortData);
+
+ return orderedFileList;
+}
+
+xptiInterfaceInfoManager::AutoRegMode
+xptiInterfaceInfoManager::DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ PRUint32 countOfFilesInWorkingSet = aWorkingSet->GetFileCount();
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+ PRUint32 k;
+
+ if(0 == countOfFilesInWorkingSet)
+ {
+ // Loading manifest might have failed. Better safe...
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ if(countOfFilesInFileList == countOfFilesInWorkingSet)
+ {
+ // try to determine if *no* files are new or changed.
+
+ PRBool same = PR_TRUE;
+ for(i = 0; i < countOfFilesInFileList && same; ++i)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ PRInt64 size;
+ PRInt64 date;
+ nsCAutoString name;
+ PRUint32 directory;
+
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &directory))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ for(k = 0; k < countOfFilesInWorkingSet; ++k)
+ {
+ xptiFile& target = aWorkingSet->GetFileAt(k);
+
+ if(directory == target.GetDirectory() &&
+ name.Equals(target.GetName()))
+ {
+ if(nsInt64(size) != target.GetSize() ||
+ nsInt64(date) != target.GetDate())
+ same = PR_FALSE;
+ break;
+ }
+ }
+ // failed to find our file in the workingset?
+ if(k == countOfFilesInWorkingSet)
+ same = PR_FALSE;
+ }
+ if(same)
+ return NO_FILES_CHANGED;
+ }
+ else if(countOfFilesInFileList > countOfFilesInWorkingSet)
+ {
+ // try to determine if the only changes are additional new files
+ // XXX Wimping out and doing this as a separate walk through the lists.
+
+ PRBool same = PR_TRUE;
+
+ for(i = 0; i < countOfFilesInWorkingSet && same; ++i)
+ {
+ xptiFile& target = aWorkingSet->GetFileAt(i);
+
+ for(k = 0; k < countOfFilesInFileList; ++k)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(k, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ PRBool sameName = name.Equals(target.GetName());
+ if(sameName)
+ {
+ if(nsInt64(size) != target.GetSize() ||
+ nsInt64(date) != target.GetDate())
+ same = PR_FALSE;
+ break;
+ }
+ }
+ // failed to find our file in the file list?
+ if(k == countOfFilesInFileList)
+ same = PR_FALSE;
+ }
+ if(same)
+ return FILES_ADDED_ONLY;
+ }
+
+ return FULL_VALIDATION_REQUIRED;
+}
+
+PRBool
+xptiInterfaceInfoManager::AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ nsILocalFile** orderedFileArray;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ return PR_FALSE;
+ NS_ASSERTION(countOfFilesInFileList, "loser!");
+ NS_ASSERTION(countOfFilesInFileList > aWorkingSet->GetFileCount(), "loser!");
+
+ orderedFileArray = BuildOrderedFileArray(aSearchPath, aFileList, aWorkingSet);
+
+ if(!orderedFileArray)
+ return PR_FALSE;
+
+ // Make enough space in aWorkingset for additions to xptiFile array.
+
+ if(!aWorkingSet->ExtendFileArray(countOfFilesInFileList))
+ return PR_FALSE;
+
+ // For each file that is not already in our working set, add any valid
+ // interfaces that don't conflict with previous interfaces added.
+ for(i = 0; i < countOfFilesInFileList; i++)
+ {
+ nsILocalFile* file = orderedFileArray[i];
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ PRUint32 dir;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &dir))
+ {
+ return PR_FALSE;
+ }
+
+
+ if(xptiWorkingSet::NOT_FOUND != aWorkingSet->FindFile(dir, name.get()))
+ {
+ // This file was found in the working set, so skip it.
+ continue;
+ }
+
+ LOG_AUTOREG((" finding interfaces in new file: %s\n", name.get()));
+
+ xptiFile fileRecord;
+ fileRecord = xptiFile(nsInt64(size), nsInt64(date), dir,
+ name.get(), aWorkingSet);
+
+ if(xptiFileType::IsXPT(fileRecord.GetName()))
+ {
+ XPTHeader* header = ReadXPTFile(file, aWorkingSet);
+ if(!header)
+ {
+ // XXX do something!
+ NS_ERROR("");
+ continue;
+ }
+
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount());
+
+ PRBool AddedFile = PR_FALSE;
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this file then
+ // setup the fileRecord for the header and infos.
+ if(!AddedFile)
+ {
+ if(!fileRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ AddedFile = PR_TRUE;
+ }
+ fileRecord.GetGuts()->SetEntryAt(k, entry);
+ }
+
+ // This will correspond to typelibRecord above.
+ aWorkingSet->AppendFile(fileRecord);
+ }
+ else // its another kind of archive
+ {
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIXPTLoaderSink> sink =
+ new xptiZipLoaderSink(this, aWorkingSet);
+ if (!sink)
+ return PR_FALSE;
+
+ rv = loader->EnumerateEntries(file, sink);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+ // This will correspond to typelibRecord used in
+ // xptiInterfaceInfoManager::FoundEntry.
+ aWorkingSet->AppendFile(fileRecord);
+ } else {
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ nsILocalFile** orderedFileArray;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+
+ if(!aWorkingSet->IsValid())
+ return PR_FALSE;
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ return PR_FALSE;
+
+ if(!countOfFilesInFileList)
+ {
+ // maybe there are no xpt files to register.
+ // a minimal install would have this case.
+ return PR_TRUE;
+ }
+
+ orderedFileArray = BuildOrderedFileArray(aSearchPath, aFileList, aWorkingSet);
+
+ if(!orderedFileArray)
+ return PR_FALSE;
+
+ // DEBUG_DumpFileArray(orderedFileArray, countOfFilesInFileList);
+
+ // Make space in aWorkingset for a new xptiFile array.
+
+ if(!aWorkingSet->NewFileArray(countOfFilesInFileList))
+ return PR_FALSE;
+
+ aWorkingSet->ClearZipItems();
+ aWorkingSet->ClearHashTables();
+
+ // For each file, add any valid interfaces that don't conflict with
+ // previous interfaces added.
+ for(i = 0; i < countOfFilesInFileList; i++)
+ {
+ nsILocalFile* file = orderedFileArray[i];
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ PRUint32 dir;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &dir))
+ {
+ return PR_FALSE;
+ }
+
+ LOG_AUTOREG((" finding interfaces in file: %s\n", name.get()));
+
+ xptiFile fileRecord;
+ fileRecord = xptiFile(nsInt64(size), nsInt64(date), dir,
+ name.get(), aWorkingSet);
+
+// printf("* found %s\n", fileRecord.GetName());
+
+
+ if(xptiFileType::IsXPT(fileRecord.GetName()))
+ {
+ XPTHeader* header = ReadXPTFile(file, aWorkingSet);
+ if(!header)
+ {
+ // XXX do something!
+ NS_ERROR("Unable to read an XPT file, turn logging on to see which file");
+ LOG_AUTOREG((" unable to read file\n"));
+ continue;
+ }
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount());
+
+ PRBool AddedFile = PR_FALSE;
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this file then
+ // setup the fileRecord for the header and infos.
+ if(!AddedFile)
+ {
+ if(!fileRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ AddedFile = PR_TRUE;
+ }
+ fileRecord.GetGuts()->SetEntryAt(k, entry);
+ }
+
+ // This will correspond to typelibRecord above.
+ aWorkingSet->AppendFile(fileRecord);
+ }
+
+ else
+ {
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIXPTLoaderSink> sink =
+ new xptiZipLoaderSink(this, aWorkingSet);
+ if (!sink)
+ return PR_FALSE;
+
+ rv = loader->EnumerateEntries(file, sink);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+ // This will correspond to typelibRecord used in
+ // xptiInterfaceInfoManager::FoundEntry.
+ aWorkingSet->AppendFile(fileRecord);
+ } else {
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ }
+ return PR_TRUE;
+}
+
+NS_IMPL_ISUPPORTS1(xptiZipLoaderSink, nsIXPTLoaderSink)
+
+// implement nsIXPTLoader
+NS_IMETHODIMP
+xptiZipLoaderSink::FoundEntry(const char* entryName,
+ PRInt32 index,
+ nsIInputStream *aStream)
+{
+ XPTHeader *header =
+ xptiZipLoader::ReadXPTFileFromInputStream(aStream, mWorkingSet);
+ if (!header)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!mManager->FoundZipEntry(entryName, index, header, mWorkingSet))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+// implement xptiEntrySink
+PRBool
+xptiInterfaceInfoManager::FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet)
+{
+
+ NS_ASSERTION(entryName, "loser!");
+ NS_ASSERTION(header, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+
+ int countOfInterfacesAddedForItem = 0;
+ xptiZipItem zipItemRecord(entryName, aWorkingSet);
+
+ LOG_AUTOREG((" finding interfaces in file: %s\n", entryName));
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d. Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ if(!header->num_interfaces)
+ {
+ // We are not interested in files without interfaces.
+ return PR_TRUE;
+ }
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount(),
+ aWorkingSet->GetZipItemCount());
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this item
+ // then setup the zipItemRecord for the header and infos.
+ if(!countOfInterfacesAddedForItem)
+ {
+ // XXX fix this!
+ if(!zipItemRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ }
+
+ // zipItemRecord.GetGuts()->SetEntryAt(k, entry);
+ ++countOfInterfacesAddedForItem;
+ }
+
+ if(countOfInterfacesAddedForItem)
+ {
+ if(!aWorkingSet->GetZipItemFreeSpace())
+ {
+ if(!aWorkingSet->ExtendZipItemArray(
+ aWorkingSet->GetZipItemCount() + 20))
+ {
+ // out of space!
+ return PR_FALSE;
+ }
+ }
+ aWorkingSet->AppendZipItem(zipItemRecord);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded)
+{
+ NS_ASSERTION(iface, "loser!");
+ NS_ASSERTION(entryAdded, "loser!");
+
+ *entryAdded = nsnull;
+
+ if(!iface->interface_descriptor)
+ {
+ // Not resolved, ignore this one.
+ // XXX full logging might note this...
+ return PR_TRUE;
+ }
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable, &iface->iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(entry)
+ {
+ // XXX validate this info to find possible inconsistencies
+ LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name));
+ return PR_TRUE;
+ }
+
+ // Build a new xptiInterfaceEntry object and hook it up.
+
+ entry = xptiInterfaceEntry::NewEntry(iface->name, strlen(iface->name),
+ iface->iid,
+ typelibRecord, aWorkingSet);
+ if(!entry)
+ {
+ // XXX bad!
+ return PR_FALSE;
+ }
+
+ //XXX We should SetHeader too as part of the validation, no?
+ entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ entry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ entry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ *entryAdded = entry;
+
+ LOG_AUTOREG((" added interface: %s\n", iface->name));
+
+ return PR_TRUE;
+}
+
+// local struct used to pass two pointers as one pointer
+struct TwoWorkingSets
+{
+ TwoWorkingSets(xptiWorkingSet* src, xptiWorkingSet* dest)
+ : aSrcWorkingSet(src), aDestWorkingSet(dest) {}
+
+ xptiWorkingSet* aSrcWorkingSet;
+ xptiWorkingSet* aDestWorkingSet;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Merger(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* srcEntry = ((xptiHashEntry*)hdr)->value;
+ xptiWorkingSet* aSrcWorkingSet = ((TwoWorkingSets*)arg)->aSrcWorkingSet;
+ xptiWorkingSet* aDestWorkingSet = ((TwoWorkingSets*)arg)->aDestWorkingSet;
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
+ srcEntry->GetTheIID(), PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* destEntry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(destEntry)
+ {
+ // Let's see if this is referring to the same exact typelib
+
+ const char* destFilename =
+ aDestWorkingSet->GetTypelibFileName(destEntry->GetTypelibRecord());
+
+ const char* srcFilename =
+ aSrcWorkingSet->GetTypelibFileName(srcEntry->GetTypelibRecord());
+
+ if(0 == PL_strcmp(destFilename, srcFilename) &&
+ (destEntry->GetTypelibRecord().GetZipItemIndex() ==
+ srcEntry->GetTypelibRecord().GetZipItemIndex()))
+ {
+ // This is the same item.
+ // But... Let's make sure they didn't change the interface name.
+ // There are wacky developers that do stuff like that!
+ if(0 == PL_strcmp(destEntry->GetTheName(), srcEntry->GetTheName()))
+ return PL_DHASH_NEXT;
+ }
+ }
+
+ // Clone the xptiInterfaceEntry into our destination WorkingSet.
+
+ xptiTypelib typelibRecord;
+
+ uint16 fileIndex = srcEntry->GetTypelibRecord().GetFileIndex();
+ uint16 zipItemIndex = srcEntry->GetTypelibRecord().GetZipItemIndex();
+
+ fileIndex += aDestWorkingSet->mFileMergeOffsetMap[fileIndex];
+
+ // If it is not a zipItem, then the original index is fine.
+ if(srcEntry->GetTypelibRecord().IsZip())
+ zipItemIndex += aDestWorkingSet->mZipItemMergeOffsetMap[zipItemIndex];
+
+ typelibRecord.Init(fileIndex, zipItemIndex);
+
+ destEntry = xptiInterfaceEntry::NewEntry(*srcEntry, typelibRecord,
+ aDestWorkingSet);
+ if(!destEntry)
+ {
+ // XXX bad! should log
+ return PL_DHASH_NEXT;
+ }
+
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mNameTable,
+ destEntry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = destEntry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
+ destEntry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = destEntry;
+
+ return PL_DHASH_NEXT;
+}
+
+PRBool
+xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet)
+{
+
+ PRUint32 i;
+
+ // Combine file lists.
+
+ PRUint32 originalFileCount = aDestWorkingSet->GetFileCount();
+ PRUint32 additionalFileCount = aSrcWorkingSet->GetFileCount();
+
+ // Create a new array big enough to hold both lists and copy existing files
+
+ if(additionalFileCount)
+ {
+ if(!aDestWorkingSet->ExtendFileArray(originalFileCount +
+ additionalFileCount))
+ return PR_FALSE;
+
+ // Now we are where we started, but we know we have enough space.
+
+ // Prepare offset array for later fixups.
+ // NOTE: Storing with dest, but alloc'ing from src. This is intentional.
+ aDestWorkingSet->mFileMergeOffsetMap = (PRUint32*)
+ XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
+ additionalFileCount * sizeof(PRUint32));
+ if(!aDestWorkingSet->mFileMergeOffsetMap)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < additionalFileCount; ++i)
+ {
+ xptiFile& srcFile = aSrcWorkingSet->GetFileAt(i);
+ PRUint32 k;
+ for(k = 0; k < originalFileCount; ++k)
+ {
+ // If file (with same name, date, and time) is in both lists
+ // then reuse that record.
+ xptiFile& destFile = aDestWorkingSet->GetFileAt(k);
+ if(srcFile.Equals(destFile))
+ {
+ aDestWorkingSet->mFileMergeOffsetMap[i] = k - i;
+ break;
+ }
+ }
+ if(k == originalFileCount)
+ {
+ // No match found, tack it on the end.
+
+ PRUint32 newIndex = aDestWorkingSet->GetFileCount();
+
+ aDestWorkingSet->AppendFile(xptiFile(srcFile, aDestWorkingSet));
+
+ // Fixup the merge offset map.
+ aDestWorkingSet->mFileMergeOffsetMap[i] = newIndex - i;
+ }
+ }
+
+ // Combine ZipItem lists.
+
+ PRUint32 originalZipItemCount = aDestWorkingSet->GetZipItemCount();
+ PRUint32 additionalZipItemCount = aSrcWorkingSet->GetZipItemCount();
+
+ // Create a new array big enough to hold both lists and copy existing ZipItems
+
+ if(additionalZipItemCount)
+ {
+ if(!aDestWorkingSet->ExtendZipItemArray(originalZipItemCount +
+ additionalZipItemCount))
+ return PR_FALSE;
+
+ // Now we are where we started, but we know we have enough space.
+
+ // Prepare offset array for later fixups.
+ // NOTE: Storing with dest, but alloc'ing from src. This is intentional.
+ aDestWorkingSet->mZipItemMergeOffsetMap = (PRUint32*)
+ XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
+ additionalZipItemCount * sizeof(PRUint32));
+ if(!aDestWorkingSet->mZipItemMergeOffsetMap)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < additionalZipItemCount; ++i)
+ {
+ xptiZipItem& srcZipItem = aSrcWorkingSet->GetZipItemAt(i);
+ PRUint32 k;
+ for(k = 0; k < originalZipItemCount; ++k)
+ {
+ // If ZipItem (with same name) is in both lists
+ // then reuse that record.
+ xptiZipItem& destZipItem = aDestWorkingSet->GetZipItemAt(k);
+ if(srcZipItem.Equals(destZipItem))
+ {
+ aDestWorkingSet->mZipItemMergeOffsetMap[i] = k - i;
+ break;
+ }
+ }
+ if(k == originalZipItemCount)
+ {
+ // No match found, tack it on the end.
+
+ PRUint32 newIndex = aDestWorkingSet->GetZipItemCount();
+
+ aDestWorkingSet->AppendZipItem(
+ xptiZipItem(srcZipItem, aDestWorkingSet));
+
+ // Fixup the merge offset map.
+ aDestWorkingSet->mZipItemMergeOffsetMap[i] = newIndex - i;
+ }
+ }
+
+ // Migrate xptiInterfaceInfos
+
+ TwoWorkingSets sets(aSrcWorkingSet, aDestWorkingSet);
+
+ PL_DHashTableEnumerate(aSrcWorkingSet->mNameTable, xpti_Merger, &sets);
+
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileList(nsISupportsArray* aFileList)
+{
+ PRUint32 count;
+
+ if(NS_FAILED(aFileList->Count(&count)))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ if(!file)
+ return PR_FALSE;
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ printf("* found %s\n", name.get());
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet)
+{
+ for(PRUint16 i = 0; i < aWorkingSet->GetFileCount(); ++i)
+ {
+ xptiFile& record = aWorkingSet->GetFileAt(i);
+
+ printf("! has %s\n", record.GetName());
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileArray(nsILocalFile** aFileArray,
+ PRUint32 count)
+{
+ // dump the sorted list
+ for(PRUint32 i = 0; i < count; ++i)
+ {
+ nsILocalFile* file = aFileArray[i];
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ printf("found file: %s\n", name.get());
+ }
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+
+// static
+void
+xptiInterfaceInfoManager::WriteToLog(const char *fmt, ...)
+{
+ if(!gInterfaceInfoManager)
+ return;
+
+ PRFileDesc* fd = gInterfaceInfoManager->GetOpenLogFile();
+ if(fd)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ PR_vfprintf(fd, fmt, ap);
+ va_end(ap);
+ }
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ResolvedFileNameLogger(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ xptiInterfaceInfoManager* mgr = (xptiInterfaceInfoManager*) arg;
+
+ if(entry->IsFullyResolved())
+ {
+ xptiWorkingSet* aWorkingSet = mgr->GetWorkingSet();
+ PRFileDesc* fd = mgr->GetOpenLogFile();
+
+ const xptiTypelib& typelib = entry->GetTypelibRecord();
+ const char* filename =
+ aWorkingSet->GetFileAt(typelib.GetFileIndex()).GetName();
+
+ if(typelib.IsZip())
+ {
+ const char* zipItemName =
+ aWorkingSet->GetZipItemAt(typelib.GetZipItemIndex()).GetName();
+ PR_fprintf(fd, "xpti used interface: %s from %s::%s\n",
+ entry->GetTheName(), filename, zipItemName);
+ }
+ else
+ {
+ PR_fprintf(fd, "xpti used interface: %s from %s\n",
+ entry->GetTheName(), filename);
+ }
+ }
+ return PL_DHASH_NEXT;
+}
+
+void
+xptiInterfaceInfoManager::LogStats()
+{
+ PRUint32 i;
+
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(this, mStatsLogFile, PR_FALSE);
+
+ PRFileDesc* fd = GetOpenLogFile();
+ if(!fd)
+ return;
+
+ // Show names of xpt (only) files from which at least one interface
+ // was resolved.
+
+ PRUint32 fileCount = mWorkingSet.GetFileCount();
+ for(i = 0; i < fileCount; ++i)
+ {
+ xptiFile& f = mWorkingSet.GetFileAt(i);
+ if(f.GetGuts())
+ PR_fprintf(fd, "xpti used file: %s\n", f.GetName());
+ }
+
+ PR_fprintf(fd, "\n");
+
+ // Show names of xptfiles loaded from zips from which at least
+ // one interface was resolved.
+
+ PRUint32 zipItemCount = mWorkingSet.GetZipItemCount();
+ for(i = 0; i < zipItemCount; ++i)
+ {
+ xptiZipItem& zi = mWorkingSet.GetZipItemAt(i);
+ if(zi.GetGuts())
+ PR_fprintf(fd, "xpti used file from zip: %s\n", zi.GetName());
+ }
+
+ PR_fprintf(fd, "\n");
+
+ // Show name of each interface that was fully resolved and the name
+ // of the file and (perhaps) zip from which it was loaded.
+
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable,
+ xpti_ResolvedFileNameLogger, this);
+
+}
+
+/***************************************************************************/
+
+// this is a private helper
+static nsresult
+EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
+{
+ xptiInterfaceInfo* info;
+ nsresult rv;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = entry->GetInterfaceInfo(&info);
+ if(NS_FAILED(rv))
+ return rv;
+
+ // Transfer the AddRef done by GetInterfaceInfo.
+ *_retval = NS_STATIC_CAST(nsIInterfaceInfo*, info);
+ return NS_OK;
+}
+
+/* nsIInterfaceInfo getInfoForIID (in nsIIDPtr iid); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ return EntryToInfo(entry, _retval);
+}
+
+/* nsIInterfaceInfo getInfoForName (in string name); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ return EntryToInfo(entry, _retval);
+}
+
+/* nsIIDPtr getIIDForName (in string name); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetIIDForName(const char *name, nsIID * *_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ return entry->GetIID(_retval);
+}
+
+/* string getNameForIID (in nsIIDPtr iid); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ return entry->GetName(_retval);
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ArrayAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ nsISupportsArray* array = (nsISupportsArray*) arg;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
+ array->AppendElement(ii);
+ return PL_DHASH_NEXT;
+}
+
+/* nsIEnumerator enumerateInterfaces (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator **_retval)
+{
+ // I didn't want to incur the size overhead of using nsHashtable just to
+ // make building an enumerator easier. So, this code makes a snapshot of
+ // the table using an nsISupportsArray and builds an enumerator for that.
+ // We can afford this transient cost.
+
+ nsCOMPtr<nsISupportsArray> array;
+ NS_NewISupportsArray(getter_AddRefs(array));
+ if(!array)
+ return NS_ERROR_UNEXPECTED;
+
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayAppender, array);
+
+ return array->Enumerate(_retval);
+}
+
+struct ArrayAndPrefix
+{
+ nsISupportsArray* array;
+ const char* prefix;
+ PRUint32 length;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ArrayPrefixAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ ArrayAndPrefix* args = (ArrayAndPrefix*) arg;
+
+ const char* name = entry->GetTheName();
+ if(name != PL_strnstr(name, args->prefix, args->length))
+ return PL_DHASH_NEXT;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
+ args->array->AppendElement(ii);
+ return PL_DHASH_NEXT;
+}
+
+/* nsIEnumerator enumerateInterfacesWhoseNamesStartWith (in string prefix); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(const char *prefix, nsIEnumerator **_retval)
+{
+ nsCOMPtr<nsISupportsArray> array;
+ NS_NewISupportsArray(getter_AddRefs(array));
+ if(!array)
+ return NS_ERROR_UNEXPECTED;
+
+ ArrayAndPrefix args = {array, prefix, PL_strlen(prefix)};
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayPrefixAppender, &args);
+
+ return array->Enumerate(_retval);
+}
+
+/* void autoRegisterInterfaces (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
+{
+ nsCOMPtr<nsISupportsArray> fileList;
+ AutoRegMode mode;
+ PRBool ok;
+
+ nsAutoLock lock(xptiInterfaceInfoManager::GetAutoRegLock(this));
+
+ xptiWorkingSet workingSet(mSearchPath);
+ if(!workingSet.IsValid())
+ return NS_ERROR_UNEXPECTED;
+
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(this, mAutoRegLogFile, PR_TRUE);
+
+ LOG_AUTOREG(("start AutoRegister\n"));
+
+ // We re-read the manifest rather than muck with the 'live' one.
+ // It is OK if this fails.
+ // XXX But we should track failure as a warning.
+ ok = xptiManifest::Read(this, &workingSet);
+
+ LOG_AUTOREG(("read of manifest %s\n", ok ? "successful" : "FAILED"));
+
+ // Grovel for all the typelibs we can find (in .xpt or .zip, .jar,...).
+ if(!BuildFileList(mSearchPath, getter_AddRefs(fileList)) || !fileList)
+ return NS_ERROR_UNEXPECTED;
+
+ // DEBUG_DumpFileList(fileList);
+
+ // Check to see how much work we need to do.
+ mode = DetermineAutoRegStrategy(mSearchPath, fileList, &workingSet);
+
+ switch(mode)
+ {
+ case NO_FILES_CHANGED:
+ LOG_AUTOREG(("autoreg strategy: no files changed\n"));
+ LOG_AUTOREG(("successful end of AutoRegister\n"));
+ return NS_OK;
+ case FILES_ADDED_ONLY:
+ LOG_AUTOREG(("autoreg strategy: files added only\n"));
+ if(!AddOnlyNewFilesFromFileList(mSearchPath, fileList, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to add new files\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ break;
+ case FULL_VALIDATION_REQUIRED:
+ LOG_AUTOREG(("autoreg strategy: doing full validation merge\n"));
+ if(!DoFullValidationMergeFromFileList(mSearchPath, fileList, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to do full validation\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ break;
+ default:
+ NS_ERROR("switch missing a case");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Failure to write the manifest is not fatal in production builds.
+ // However, this would require the next startup to find and read all the
+ // xpt files. This will make that startup slower. If this ever becomes a
+ // chronic problem for anyone, then we'll want to figure out why!
+
+ if(!xptiManifest::Write(this, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to write manifest\n"));
+ NS_ERROR("Failed to write xpti manifest!");
+ }
+
+ if(!MergeWorkingSets(&mWorkingSet, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to merge into live workingset\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+// DEBUG_DumpFileListInWorkingSet(mWorkingSet);
+
+ LOG_AUTOREG(("successful end of AutoRegister\n"));
+
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+class xptiAdditionalManagersEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ xptiAdditionalManagersEnumerator();
+
+ PRBool SizeTo(PRUint32 likelyCount) {return mArray.SizeTo(likelyCount);}
+ PRBool AppendElement(nsIInterfaceInfoManager* element);
+
+private:
+ ~xptiAdditionalManagersEnumerator() {}
+
+ nsSupportsArray mArray;
+ PRUint32 mIndex;
+ PRUint32 mCount;
+};
+
+NS_IMPL_ISUPPORTS1(xptiAdditionalManagersEnumerator, nsISimpleEnumerator)
+
+xptiAdditionalManagersEnumerator::xptiAdditionalManagersEnumerator()
+ : mIndex(0), mCount(0)
+{
+}
+
+PRBool xptiAdditionalManagersEnumerator::AppendElement(nsIInterfaceInfoManager* element)
+{
+ if(!mArray.AppendElement(NS_STATIC_CAST(nsISupports*, element)))
+ return PR_FALSE;
+ mCount++;
+ return PR_TRUE;
+}
+
+/* boolean hasMoreElements (); */
+NS_IMETHODIMP xptiAdditionalManagersEnumerator::HasMoreElements(PRBool *_retval)
+{
+ *_retval = mIndex < mCount;
+ return NS_OK;
+}
+
+/* nsISupports getNext (); */
+NS_IMETHODIMP xptiAdditionalManagersEnumerator::GetNext(nsISupports **_retval)
+{
+ if(!(mIndex < mCount))
+ {
+ NS_ERROR("Bad nsISimpleEnumerator caller!");
+ return NS_ERROR_FAILURE;
+ }
+
+ *_retval = mArray.ElementAt(mIndex++);
+ return *_retval ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/***************************************************************************/
+
+/* void addAdditionalManager (in nsIInterfaceInfoManager manager); */
+NS_IMETHODIMP xptiInterfaceInfoManager::AddAdditionalManager(nsIInterfaceInfoManager *manager)
+{
+ nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(manager);
+ nsISupports* ptrToAdd = weakRef ?
+ NS_STATIC_CAST(nsISupports*, weakRef) :
+ NS_STATIC_CAST(nsISupports*, manager);
+ { // scoped lock...
+ nsAutoLock lock(mAdditionalManagersLock);
+ PRInt32 index;
+ nsresult rv = mAdditionalManagers.GetIndexOf(ptrToAdd, &index);
+ if(NS_FAILED(rv) || -1 != index)
+ return NS_ERROR_FAILURE;
+ if(!mAdditionalManagers.AppendElement(ptrToAdd))
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+/* void removeAdditionalManager (in nsIInterfaceInfoManager manager); */
+NS_IMETHODIMP xptiInterfaceInfoManager::RemoveAdditionalManager(nsIInterfaceInfoManager *manager)
+{
+ nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(manager);
+ nsISupports* ptrToRemove = weakRef ?
+ NS_STATIC_CAST(nsISupports*, weakRef) :
+ NS_STATIC_CAST(nsISupports*, manager);
+ { // scoped lock...
+ nsAutoLock lock(mAdditionalManagersLock);
+ if(!mAdditionalManagers.RemoveElement(ptrToRemove))
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+/* PRBool hasAdditionalManagers (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::HasAdditionalManagers(PRBool *_retval)
+{
+ PRUint32 count;
+ nsresult rv = mAdditionalManagers.Count(&count);
+ *_retval = count != 0;
+ return rv;
+}
+
+/* nsISimpleEnumerator enumerateAdditionalManagers (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateAdditionalManagers(nsISimpleEnumerator **_retval)
+{
+ nsAutoLock lock(mAdditionalManagersLock);
+
+ PRUint32 count;
+ nsresult rv = mAdditionalManagers.Count(&count);
+ if(NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<xptiAdditionalManagersEnumerator> enumerator =
+ new xptiAdditionalManagersEnumerator();
+ if(!enumerator)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ enumerator->SizeTo(count);
+
+ for(PRUint32 i = 0; i < count; /* i incremented in the loop body */)
+ {
+ nsCOMPtr<nsISupports> raw =
+ dont_AddRef(mAdditionalManagers.ElementAt(i++));
+ if(!raw)
+ return NS_ERROR_FAILURE;
+ nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(raw);
+ if(weakRef)
+ {
+ nsCOMPtr<nsIInterfaceInfoManager> manager =
+ do_QueryReferent(weakRef);
+ if(manager)
+ {
+ if(!enumerator->AppendElement(manager))
+ return NS_ERROR_FAILURE;
+ }
+ else
+ {
+ // The manager is no more. Remove the element.
+ if(!mAdditionalManagers.RemoveElementAt(--i))
+ return NS_ERROR_FAILURE;
+ count--;
+ }
+ }
+ else
+ {
+ // We *know* we put a pointer to either a nsIWeakReference or
+ // an nsIInterfaceInfoManager into the array, so we can avoid an
+ // extra QI here and just do a cast.
+ if(!enumerator->AppendElement(
+ NS_REINTERPRET_CAST(nsIInterfaceInfoManager*, raw.get())))
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ NS_ADDREF(*_retval = enumerator);
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
+XPTI_GetInterfaceInfoManager()
+{
+ nsIInterfaceInfoManager* iim =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+ NS_IF_ADDREF(iim);
+ return iim;
+}
+
+XPTI_PUBLIC_API(void)
+XPTI_FreeInterfaceInfoManager()
+{
+ xptiInterfaceInfoManager::FreeInterfaceInfoManager();
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp
new file mode 100644
index 00000000..03ab7029
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp
@@ -0,0 +1,710 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiManifest. */
+
+#include "xptiprivate.h"
+#include "nsManifestLineReader.h"
+#include "nsString.h"
+
+static const char g_Disclaimer[] = "# Generated file. ** DO NOT EDIT! **";
+
+static const char g_TOKEN_Files[] = "Files";
+static const char g_TOKEN_ArchiveItems[] = "ArchiveItems";
+static const char g_TOKEN_Interfaces[] = "Interfaces";
+static const char g_TOKEN_Header[] = "Header";
+static const char g_TOKEN_Version[] = "Version";
+static const char g_TOKEN_AppDir[] = "AppDir";
+static const char g_TOKEN_Directories[] = "Directories";
+
+static const int g_VERSION_MAJOR = 2;
+static const int g_VERSION_MINOR = 0;
+
+/***************************************************************************/
+
+static PRBool
+GetCurrentAppDirString(xptiInterfaceInfoManager* aMgr, nsACString &aStr)
+{
+ nsCOMPtr<nsILocalFile> appDir;
+ aMgr->GetApplicationDir(getter_AddRefs(appDir));
+ if(appDir)
+ return NS_SUCCEEDED(appDir->GetPersistentDescriptor(aStr));
+ return PR_FALSE;
+}
+
+static PRBool
+CurrentAppDirMatchesPersistentDescriptor(xptiInterfaceInfoManager* aMgr,
+ const char *inStr)
+{
+ nsCOMPtr<nsILocalFile> appDir;
+ aMgr->GetApplicationDir(getter_AddRefs(appDir));
+
+ nsCOMPtr<nsILocalFile> descDir;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ rv = descDir->SetPersistentDescriptor(nsDependentCString(inStr));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ PRBool matches;
+ rv = appDir->Equals(descDir, &matches);
+ return NS_SUCCEEDED(rv) && matches;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_InterfaceWriter(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ PRFileDesc* fd = (PRFileDesc*) arg;
+
+ char* iidStr = entry->GetTheIID()->ToString();
+ if(!iidStr)
+ return PL_DHASH_STOP;
+
+ const xptiTypelib& typelib = entry->GetTypelibRecord();
+
+ PRBool success = PR_fprintf(fd, "%d,%s,%s,%d,%d,%d\n",
+ (int) number,
+ entry->GetTheName(),
+ iidStr,
+ (int) typelib.GetFileIndex(),
+ (int) (typelib.IsZip() ?
+ typelib.GetZipItemIndex() : -1),
+ (int) entry->GetScriptableFlag());
+
+ nsCRT::free(iidStr);
+
+ return success ? PL_DHASH_NEXT : PL_DHASH_STOP;
+}
+
+
+// static
+PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet)
+{
+
+ PRBool succeeded = PR_FALSE;
+ PRFileDesc* fd = nsnull;
+ PRUint32 i;
+ PRUint32 size32;
+ PRIntn interfaceCount = 0;
+ nsCAutoString appDirString;
+
+ nsCOMPtr<nsILocalFile> tempFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(tempFile)) || !tempFile)
+ return PR_FALSE;
+
+ nsCAutoString originalLeafName;
+ tempFile->GetNativeLeafName(originalLeafName);
+
+ nsCAutoString leafName;
+ leafName.Assign(originalLeafName + NS_LITERAL_CSTRING(".tmp"));
+
+ tempFile->SetNativeLeafName(leafName);
+
+ // All exits via "goto out;" from here on...
+ if(NS_FAILED(tempFile->
+ OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0600, &fd)) || !fd)
+ {
+ goto out;
+ }
+
+ // write file header comments
+
+ if(!PR_fprintf(fd, "%s\n", g_Disclaimer))
+ goto out;
+
+ // write the [Header] block, version number, and appdir.
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n", g_TOKEN_Header, 2))
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s,%d,%d\n",
+ 0, g_TOKEN_Version, g_VERSION_MAJOR, g_VERSION_MINOR))
+ goto out;
+
+ GetCurrentAppDirString(aMgr, appDirString);
+ if(appDirString.IsEmpty())
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s,%s\n",
+ 1, g_TOKEN_AppDir, appDirString.get()))
+ goto out;
+
+ // write Directories list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Directories,
+ (int) aWorkingSet->GetDirectoryCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetDirectoryCount(); i++)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ nsCAutoString str;
+
+ aWorkingSet->GetDirectoryAt(i, getter_AddRefs(dir));
+ if(!dir)
+ goto out;
+
+ dir->GetPersistentDescriptor(str);
+ if(str.IsEmpty())
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s\n", (int) i, str.get()))
+ goto out;
+ }
+
+ // write Files list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Files,
+ (int) aWorkingSet->GetFileCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetFileCount(); i++)
+ {
+ const xptiFile& file = aWorkingSet->GetFileAt(i);
+
+ LL_L2UI(size32, file.GetSize());
+
+ if(!PR_fprintf(fd, "%d,%s,%d,%u,%lld\n",
+ (int) i,
+ file.GetName(),
+ (int) file.GetDirectory(),
+ size32, PRInt64(file.GetDate())))
+ goto out;
+ }
+
+ // write ArchiveItems list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_ArchiveItems,
+ (int) aWorkingSet->GetZipItemCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetZipItemCount(); i++)
+ {
+ if(!PR_fprintf(fd, "%d,%s\n",
+ (int) i,
+ aWorkingSet->GetZipItemAt(i).GetName()))
+ goto out;
+ }
+
+ // write the Interfaces list
+
+ interfaceCount = aWorkingSet->mNameTable->entryCount;
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Interfaces,
+ (int) interfaceCount))
+ goto out;
+
+ if(interfaceCount != (PRIntn)
+ PL_DHashTableEnumerate(aWorkingSet->mNameTable,
+ xpti_InterfaceWriter, fd))
+ goto out;
+
+
+ if(PR_SUCCESS == PR_Close(fd))
+ {
+ succeeded = PR_TRUE;
+ }
+ fd = nsnull;
+
+out:
+ if(fd)
+ PR_Close(fd);
+
+ if(succeeded)
+ {
+ // delete the old file and rename this
+ nsCOMPtr<nsILocalFile> mainFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(mainFile)) || !mainFile)
+ return PR_FALSE;
+
+ PRBool exists;
+ if(NS_FAILED(mainFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(mainFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> parent;
+ mainFile->GetParent(getter_AddRefs(parent));
+
+ // MoveTo means rename.
+ if(NS_FAILED(tempFile->MoveToNative(parent, originalLeafName)))
+ return PR_FALSE;
+ }
+
+ return succeeded;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+
+static char*
+ReadManifestIntoMemory(xptiInterfaceInfoManager* aMgr,
+ PRUint32* pLength)
+{
+ PRFileDesc* fd = nsnull;
+ PRInt32 flen;
+ PRInt64 fileSize;
+ char* whole = nsnull;
+ PRBool success = PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> aFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(aFile)) || !aFile)
+ return nsnull;
+
+#ifdef DEBUG
+ {
+ static PRBool shown = PR_FALSE;
+
+ nsCAutoString path;
+ if(!shown && NS_SUCCEEDED(aFile->GetNativePath(path)) && !path.IsEmpty())
+ {
+ fprintf(stderr, "Type Manifest File: %s\n", path.get());
+ shown = PR_TRUE;
+ }
+ }
+#endif
+
+ if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
+ return nsnull;
+
+ whole = new char[flen];
+ if (!whole)
+ return nsnull;
+
+ // All exits from on here should be via 'goto out'
+
+ if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
+ goto out;
+
+ if(flen > PR_Read(fd, whole, flen))
+ goto out;
+
+ success = PR_TRUE;
+
+ out:
+ if(fd)
+ PR_Close(fd);
+
+ if(!success)
+ {
+ delete [] whole;
+ return nsnull;
+ }
+
+ *pLength = flen;
+ return whole;
+}
+
+static
+PRBool ReadSectionHeader(nsManifestLineReader& reader,
+ const char *token, int minCount, int* count)
+{
+ while(1)
+ {
+ if(!reader.NextLine())
+ break;
+ if(*reader.LinePtr() == '[')
+ {
+ char* p = reader.LinePtr() + (reader.LineLength() - 1);
+ if(*p != ']')
+ break;
+ *p = 0;
+
+ char* values[2];
+ int lengths[2];
+ if(2 != reader.ParseLine(values, lengths, 2))
+ break;
+
+ // ignore the leading '['
+ if(0 != PL_strcmp(values[0]+1, token))
+ break;
+
+ if((*count = atoi(values[1])) < minCount)
+ break;
+
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+
+// static
+PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet)
+{
+ int i;
+ char* whole = nsnull;
+ PRBool succeeded = PR_FALSE;
+ PRUint32 flen = 0;
+ nsManifestLineReader reader;
+ xptiHashEntry* hashEntry;
+ int headerCount = 0;
+ int dirCount = 0;
+ int fileCount = 0;
+ int zipItemCount = -1;
+ int interfaceCount = 0;
+ int dir;
+ int flags;
+ char* values[6]; // 6 is currently the max items we need to parse
+ int lengths[6];
+ PRUint32 size32;
+ PRInt64 size;
+ PRInt64 date;
+
+ whole = ReadManifestIntoMemory(aMgr, &flen);
+ if(!whole)
+ return PR_FALSE;
+
+ reader.Init(whole, flen);
+
+ // All exits from here on should be via 'goto out'
+
+ // Look for "Header" section
+
+ // This version accepts only version 1,0. We also freak if the header
+ // has more than one entry. The rationale is that we want to force an
+ // autoreg if the xpti.dat file was written by *any* other version of
+ // the software. Future versions may wish to support updating older
+ // manifests in some interesting way.
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Header, 2, &headerCount))
+ goto out;
+
+ if(headerCount != 2)
+ goto out;
+
+ // Verify the version number
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,VersionLiteral,major,minor
+ if(4 != reader.ParseLine(values, lengths, 4))
+ goto out;
+
+ // index
+ if(0 != atoi(values[0]))
+ goto out;
+
+ // VersionLiteral
+ if(0 != PL_strcmp(values[1], g_TOKEN_Version))
+ goto out;
+
+ // major
+ if(g_VERSION_MAJOR != atoi(values[2]))
+ goto out;
+
+ // minor
+ if(g_VERSION_MINOR != atoi(values[3]))
+ goto out;
+
+ // Verify the application directory
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,AppDirLiteral,directoryname
+ if(3 != reader.ParseLine(values, lengths, 3))
+ goto out;
+
+ // index
+ if(1 != atoi(values[0]))
+ goto out;
+
+ // AppDirLiteral
+ if(0 != PL_strcmp(values[1], g_TOKEN_AppDir))
+ goto out;
+
+ if(!CurrentAppDirMatchesPersistentDescriptor(aMgr, values[2]))
+ goto out;
+
+ // Look for "Directories" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Directories, 1, &dirCount))
+ goto out;
+ else
+ {
+ // To validate that the directory list matches the current search path
+ // we first confirm that the list lengths match.
+
+ nsCOMPtr<nsISupportsArray> searchPath;
+ aMgr->GetSearchPath(getter_AddRefs(searchPath));
+
+ PRUint32 searchPathCount;
+ searchPath->Count(&searchPathCount);
+
+ if(dirCount != (int) searchPathCount)
+ goto out;
+ }
+
+ // Read the directory records
+
+ for(i = 0; i < dirCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,directoryname
+ if(2 != reader.ParseLine(values, lengths, 2))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // directoryname
+ if(!aWorkingSet->DirectoryAtMatchesPersistentDescriptor(i, values[1]))
+ goto out;
+ }
+
+ // Look for "Files" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Files, 1, &fileCount))
+ goto out;
+
+
+ // Alloc room in the WorkingSet for the filearray.
+
+ if(!aWorkingSet->NewFileArray(fileCount))
+ goto out;
+
+ // Read the file records
+
+ for(i = 0; i < fileCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,filename,dirIndex,dilesSize,filesDate
+ if(5 != reader.ParseLine(values, lengths, 5))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // filename
+ if(!*values[1])
+ goto out;
+
+ // dirIndex
+ dir = atoi(values[2]);
+ if(dir < 0 || dir > dirCount)
+ goto out;
+
+ // fileSize
+ size32 = atoi(values[3]);
+ if(size32 <= 0)
+ goto out;
+ LL_UI2L(size, size32);
+
+ // fileDate
+ date = nsCRT::atoll(values[4]);
+ if(LL_IS_ZERO(date))
+ goto out;
+
+ // Append a new file record to the array.
+
+ aWorkingSet->AppendFile(
+ xptiFile(nsInt64(size), nsInt64(date), dir, values[1], aWorkingSet));
+ }
+
+ // Look for "ZipItems" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_ArchiveItems, 0, &zipItemCount))
+ goto out;
+
+ // Alloc room in the WorkingSet for the zipItemarray.
+
+ if(zipItemCount)
+ if(!aWorkingSet->NewZipItemArray(zipItemCount))
+ goto out;
+
+ // Read the zipItem records
+
+ for(i = 0; i < zipItemCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,filename
+ if(2 != reader.ParseLine(values, lengths, 2))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // filename
+ if(!*values[1])
+ goto out;
+
+ // Append a new zipItem record to the array.
+
+ aWorkingSet->AppendZipItem(xptiZipItem(values[1], aWorkingSet));
+ }
+
+ // Look for "Interfaces" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Interfaces, 1, &interfaceCount))
+ goto out;
+
+ // Read the interface records
+
+ for(i = 0; i < interfaceCount; ++i)
+ {
+ int fileIndex;
+ int zipItemIndex;
+ nsIID iid;
+ xptiInterfaceEntry* entry;
+ xptiTypelib typelibRecord;
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,interfaceName,iid,fileIndex,zipIndex,flags
+ if(6 != reader.ParseLine(values, lengths, 6))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // interfaceName
+ if(!*values[1])
+ goto out;
+
+ // iid
+ if(!iid.Parse(values[2]))
+ goto out;
+
+ // fileIndex
+ fileIndex = atoi(values[3]);
+ if(fileIndex < 0 || fileIndex >= fileCount)
+ goto out;
+
+ // zipIndex (NOTE: -1 is a valid value)
+ zipItemIndex = atoi(values[4]);
+ if(zipItemIndex < -1 || zipItemIndex >= zipItemCount)
+ goto out;
+
+ // flags
+ flags = atoi(values[5]);
+ if(flags != 0 && flags != 1)
+ goto out;
+
+ // Build an InterfaceInfo and hook it in.
+
+ if(zipItemIndex == -1)
+ typelibRecord.Init(fileIndex);
+ else
+ typelibRecord.Init(fileIndex, zipItemIndex);
+
+ entry = xptiInterfaceEntry::NewEntry(values[1], lengths[1],
+ iid, typelibRecord,
+ aWorkingSet);
+ if(!entry)
+ goto out;
+
+ entry->SetScriptableFlag(flags==1);
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ entry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ entry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+ }
+
+ // success!
+
+ succeeded = PR_TRUE;
+
+ out:
+ if(whole)
+ delete [] whole;
+
+ if(!succeeded)
+ {
+ // Cleanup the WorkingSet on failure.
+ aWorkingSet->InvalidateInterfaceInfos();
+ aWorkingSet->ClearHashTables();
+ aWorkingSet->ClearFiles();
+ }
+ return succeeded;
+}
+
+// static
+PRBool xptiManifest::Delete(xptiInterfaceInfoManager* aMgr)
+{
+ nsCOMPtr<nsILocalFile> aFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(aFile)) || !aFile)
+ return PR_FALSE;
+
+ PRBool exists;
+ if(NS_FAILED(aFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(aFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp
new file mode 100644
index 00000000..a1dbf5c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of misc. xpti stuff. */
+
+#include "xptiprivate.h"
+
+struct xptiFileTypeEntry
+{
+ const char* name;
+ int len;
+ xptiFileType::Type type;
+};
+
+static const xptiFileTypeEntry g_Entries[] =
+ {
+ {".xpt", 4, xptiFileType::XPT},
+ {".zip", 4, xptiFileType::ZIP},
+ {".jar", 4, xptiFileType::ZIP},
+ {nsnull, 0, xptiFileType::UNKNOWN}
+ };
+
+// static
+xptiFileType::Type xptiFileType::GetType(const char* name)
+{
+ NS_ASSERTION(name, "loser!");
+ int len = PL_strlen(name);
+ for(const xptiFileTypeEntry* p = g_Entries; p->name; p++)
+ {
+ if(len > p->len && 0 == PL_strcasecmp(p->name, &(name[len - p->len])))
+ return p->type;
+ }
+ return UNKNOWN;
+}
+
+/***************************************************************************/
+
+MOZ_DECL_CTOR_COUNTER(xptiAutoLog)
+
+xptiAutoLog::xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append)
+ : mMgr(nsnull), mOldFileDesc(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiAutoLog);
+
+ if(mgr && logfile)
+ {
+ PRFileDesc* fd;
+ if(NS_SUCCEEDED(logfile->
+ OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_APPEND |
+ (append ? 0 : PR_TRUNCATE),
+ 0600, &fd)) && fd)
+ {
+#ifdef DEBUG
+ m_DEBUG_FileDesc = fd;
+#endif
+ mMgr = mgr;
+ mOldFileDesc = mMgr->SetOpenLogFile(fd);
+ if(append)
+ PR_Seek(fd, 0, PR_SEEK_END);
+ WriteTimestamp(fd, "++++ start logging ");
+
+ }
+ else
+ {
+#ifdef DEBUG
+ printf("xpti failed to open log file for writing\n");
+#endif
+ }
+ }
+}
+
+xptiAutoLog::~xptiAutoLog()
+{
+ MOZ_COUNT_DTOR(xptiAutoLog);
+
+ if(mMgr)
+ {
+ PRFileDesc* fd = mMgr->SetOpenLogFile(mOldFileDesc);
+ NS_ASSERTION(fd == m_DEBUG_FileDesc, "bad unravel");
+ if(fd)
+ {
+ WriteTimestamp(fd, "---- end logging ");
+ PR_Close(fd);
+ }
+ }
+}
+
+void xptiAutoLog::WriteTimestamp(PRFileDesc* fd, const char* msg)
+{
+ PRExplodedTime expTime;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &expTime);
+ char time[128];
+ PR_FormatTimeUSEnglish(time, 128, "%Y-%m-%d-%H:%M:%S", &expTime);
+ PR_fprintf(fd, "\n%s %s\n\n", msg, time);
+}
+
+/***************************************************************************/
+
+nsresult
+xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> cloneRaw;
+
+ rv = aLocalFile->Clone(getter_AddRefs(cloneRaw));
+ if(NS_FAILED(rv))
+ return rv;
+
+ return CallQueryInterface(cloneRaw, aCloneLocalFile);
+}
+
+
+nsresult
+xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> original;
+
+ rv = aArray->QueryElementAt(aIndex, NS_GET_IID(nsILocalFile),
+ getter_AddRefs(original));
+ if(NS_FAILED(rv))
+ return rv;
+
+ return xptiCloneLocalFile(original, aLocalFile);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp
new file mode 100644
index 00000000..50956585
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiTypelibGuts. */
+
+#include "xptiprivate.h"
+
+// static
+xptiTypelibGuts*
+xptiTypelibGuts::NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aHeader, "bad param");
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiTypelibGuts) +
+ (sizeof(xptiInterfaceEntry*) *
+ (aHeader->num_interfaces - 1)));
+ if(!place)
+ return nsnull;
+ return new(place) xptiTypelibGuts(aHeader);
+}
+
+xptiTypelibGuts::xptiTypelibGuts(XPTHeader* aHeader)
+ : mHeader(aHeader)
+{
+ // empty
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp
new file mode 100644
index 00000000..b9602726
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp
@@ -0,0 +1,432 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiWorkingSet. */
+
+#include "xptiprivate.h"
+#include "nsString.h"
+
+#define XPTI_STRING_ARENA_BLOCK_SIZE (1024 * 1)
+#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1)
+#define XPTI_HASHTABLE_SIZE 128
+
+/***************************************************************************/
+
+PR_STATIC_CALLBACK(const void*)
+IIDGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ return ((xptiHashEntry*)entry)->value->GetTheIID();
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+IIDHash(PLDHashTable *table, const void *key)
+{
+ return (PLDHashNumber) ((const nsIID*)key)->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+IIDMatch(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const nsIID* iid1 = ((xptiHashEntry*)entry)->value->GetTheIID();
+ const nsIID* iid2 = (const nsIID*)key;
+
+ return iid1 == iid2 || iid1->Equals(*iid2);
+}
+
+const static struct PLDHashTableOps IIDTableOps =
+{
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ IIDGetKey,
+ IIDHash,
+ IIDMatch,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub
+};
+
+/***************************************************************************/
+
+PR_STATIC_CALLBACK(const void*)
+NameGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ return ((xptiHashEntry*)entry)->value->GetTheName();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+NameMatch(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const char* str1 = ((xptiHashEntry*)entry)->value->GetTheName();
+ const char* str2 = (const char*) key;
+ return str1 == str2 || 0 == PL_strcmp(str1, str2);
+}
+
+static const struct PLDHashTableOps NameTableOps =
+{
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ NameGetKey,
+ PL_DHashStringKey,
+ NameMatch,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub
+};
+
+/***************************************************************************/
+
+MOZ_DECL_CTOR_COUNTER(xptiWorkingSet)
+
+xptiWorkingSet::xptiWorkingSet(nsISupportsArray* aDirectories)
+ : mFileCount(0),
+ mMaxFileCount(0),
+ mFileArray(nsnull),
+ mZipItemCount(0),
+ mMaxZipItemCount(0),
+ mZipItemArray(nsnull),
+ mStringArena(XPT_NewArena(XPTI_STRING_ARENA_BLOCK_SIZE, sizeof(char),
+ "xptiWorkingSet strings")),
+ mStructArena(XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double),
+ "xptiWorkingSet structs")),
+ mDirectories(aDirectories),
+ mNameTable(PL_NewDHashTable(&NameTableOps, nsnull, sizeof(xptiHashEntry),
+ XPTI_HASHTABLE_SIZE)),
+ mIIDTable(PL_NewDHashTable(&IIDTableOps, nsnull, sizeof(xptiHashEntry),
+ XPTI_HASHTABLE_SIZE)),
+ mFileMergeOffsetMap(nsnull),
+ mZipItemMergeOffsetMap(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiWorkingSet);
+ // do nothing else...
+}
+
+PRBool
+xptiWorkingSet::IsValid() const
+{
+ return (mFileCount == 0 || mFileArray) &&
+ (mZipItemCount == 0 || mZipItemArray) &&
+ mStringArena &&
+ mStructArena &&
+ mNameTable &&
+ mIIDTable;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Remover(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ return PL_DHASH_REMOVE;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Invalidator(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ entry->LockedInvalidateInterfaceInfo();
+ return PL_DHASH_NEXT;
+}
+
+void
+xptiWorkingSet::InvalidateInterfaceInfos()
+{
+ if(mNameTable)
+ {
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ PL_DHashTableEnumerate(mNameTable, xpti_Invalidator, nsnull);
+ }
+}
+
+void
+xptiWorkingSet::ClearHashTables()
+{
+ if(mNameTable)
+ PL_DHashTableEnumerate(mNameTable, xpti_Remover, nsnull);
+
+ if(mIIDTable)
+ PL_DHashTableEnumerate(mIIDTable, xpti_Remover, nsnull);
+}
+
+void
+xptiWorkingSet::ClearFiles()
+{
+ if(mFileArray)
+ delete [] mFileArray;
+ mFileArray = nsnull;
+ mMaxFileCount = 0;
+ mFileCount = 0;
+}
+
+void
+xptiWorkingSet::ClearZipItems()
+{
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+ mZipItemArray = nsnull;
+ mMaxZipItemCount = 0;
+ mZipItemCount = 0;
+}
+
+xptiWorkingSet::~xptiWorkingSet()
+{
+ MOZ_COUNT_DTOR(xptiWorkingSet);
+
+ ClearFiles();
+ ClearZipItems();
+ ClearHashTables();
+
+ if(mNameTable)
+ PL_DHashTableDestroy(mNameTable);
+
+ if(mIIDTable)
+ PL_DHashTableDestroy(mIIDTable);
+
+ if(mFileArray)
+ delete [] mFileArray;
+
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+
+ // Destroy arenas last in case they are referenced in other members' dtors.
+
+ if(mStringArena)
+ {
+#ifdef DEBUG
+ XPT_DumpStats(mStringArena);
+#endif
+ XPT_DestroyArena(mStringArena);
+ }
+
+ if(mStructArena)
+ {
+#ifdef DEBUG
+ XPT_DumpStats(mStructArena);
+#endif
+ XPT_DestroyArena(mStructArena);
+ }
+}
+
+PRUint32
+xptiWorkingSet::FindFile(PRUint32 dir, const char* name)
+{
+ if(mFileArray)
+ {
+ for(PRUint32 i = 0; i < mFileCount;++i)
+ {
+ xptiFile& file = mFileArray[i];
+ if(file.GetDirectory() == dir &&
+ 0 == PL_strcmp(name, file.GetName()))
+ {
+ return i;
+ }
+ }
+ }
+ return NOT_FOUND;
+}
+
+PRBool
+xptiWorkingSet::NewFileArray(PRUint32 count)
+{
+ if(mFileArray)
+ delete [] mFileArray;
+ mFileCount = 0;
+ mFileArray = new xptiFile[count];
+ if(!mFileArray)
+ {
+ mMaxFileCount = 0;
+ return PR_FALSE;
+ }
+ mMaxFileCount = count;
+ return PR_TRUE;
+}
+
+PRBool
+xptiWorkingSet::ExtendFileArray(PRUint32 count)
+{
+ if(mFileArray && count < mMaxFileCount)
+ return PR_TRUE;
+
+ xptiFile* newArray = new xptiFile[count];
+ if(!newArray)
+ return PR_FALSE;
+
+ if(mFileArray)
+ {
+ for(PRUint32 i = 0; i < mFileCount; ++i)
+ newArray[i] = mFileArray[i];
+ delete [] mFileArray;
+ }
+ mFileArray = newArray;
+ mMaxFileCount = count;
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+
+PRUint32
+xptiWorkingSet::FindZipItemWithName(const char* name)
+{
+ if(mZipItemArray)
+ {
+ for(PRUint32 i = 0; i < mZipItemCount;++i)
+ if(0 == PL_strcmp(name, mZipItemArray[i].GetName()))
+ return i;
+ }
+ return NOT_FOUND;
+}
+
+PRBool
+xptiWorkingSet::NewZipItemArray(PRUint32 count)
+{
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+ mZipItemCount = 0;
+ mZipItemArray = new xptiZipItem[count];
+ if(!mZipItemArray)
+ {
+ mMaxZipItemCount = 0;
+ return PR_FALSE;
+ }
+ mMaxZipItemCount = count;
+ return PR_TRUE;
+}
+
+PRBool
+xptiWorkingSet::ExtendZipItemArray(PRUint32 count)
+{
+ if(mZipItemArray && count < mMaxZipItemCount)
+ return PR_TRUE;
+
+ xptiZipItem* newArray = new xptiZipItem[count];
+ if(!newArray)
+ return PR_FALSE;
+
+ if(mZipItemArray)
+ {
+ for(PRUint32 i = 0; i < mZipItemCount; ++i)
+ newArray[i] = mZipItemArray[i];
+ delete [] mZipItemArray;
+ }
+ mZipItemArray = newArray;
+ mMaxZipItemCount = count;
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+// Directory stuff...
+
+PRUint32 xptiWorkingSet::GetDirectoryCount()
+{
+ PRUint32 count = 0;
+ mDirectories->Count(&count);
+ return count;
+}
+
+nsresult xptiWorkingSet::GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir)
+{
+ return xptiCloneElementAsLocalFile(mDirectories, i, dir);
+}
+
+nsresult xptiWorkingSet::GetDirectoryAt(PRUint32 i, nsILocalFile** dir)
+{
+ return mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile), (void**)dir);
+}
+
+PRBool xptiWorkingSet::FindDirectory(nsILocalFile* dir, PRUint32* index)
+{
+ PRUint32 count;
+ nsresult rv = mDirectories->Count(&count);
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ PRBool same;
+ nsCOMPtr<nsILocalFile> current;
+ mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile),
+ getter_AddRefs(current));
+ if(!current || NS_FAILED(current->Equals(dir, &same)))
+ break;
+ if(same)
+ {
+ *index = i;
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool xptiWorkingSet::FindDirectoryOfFile(nsILocalFile* file, PRUint32* index)
+{
+ nsCOMPtr<nsIFile> dirAbstract;
+ file->GetParent(getter_AddRefs(dirAbstract));
+ if(!dirAbstract)
+ return PR_FALSE;
+ nsCOMPtr<nsILocalFile> dir = do_QueryInterface(dirAbstract);
+ if(!dir)
+ return PR_FALSE;
+ return FindDirectory(dir, index);
+}
+
+PRBool xptiWorkingSet::DirectoryAtMatchesPersistentDescriptor(PRUint32 i,
+ const char* inDesc)
+{
+ nsCOMPtr<nsILocalFile> dir;
+ GetDirectoryAt(i, getter_AddRefs(dir));
+ if(!dir)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> descDir;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ rv = descDir->SetPersistentDescriptor(nsDependentCString(inDesc));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ PRBool matches;
+ rv = dir->Equals(descDir, &matches);
+ return NS_SUCCEEDED(rv) && matches;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp
new file mode 100644
index 00000000..c9a6178b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiZipItem. */
+
+#include "xptiprivate.h"
+
+MOZ_DECL_CTOR_COUNTER(xptiZipItem)
+
+xptiZipItem::xptiZipItem()
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(nsnull),
+#endif
+ mName(nsnull),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+ // empty
+}
+
+xptiZipItem::xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet)
+
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mName(aName),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
+}
+
+xptiZipItem::xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mName(nsnull),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
+}
+
+xptiZipItem::~xptiZipItem()
+{
+ MOZ_COUNT_DTOR(xptiZipItem);
+}
+
+PRBool
+xptiZipItem::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(!mGuts,"bad state");
+ NS_ASSERTION(aHeader,"bad param");
+ NS_ASSERTION(aWorkingSet,"bad param");
+
+ mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
+ return mGuts != nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
new file mode 100644
index 00000000..caba49d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of xptiZipLoader. */
+
+#include "xptiprivate.h"
+
+XPTHeader*
+xptiZipLoader::ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet)
+{
+ XPTCursor cursor;
+ PRUint32 totalRead = 0;
+ XPTState *state = nsnull;
+ XPTHeader *header = nsnull;
+
+ PRUint32 flen;
+ stream->Available(&flen);
+
+ char *whole = new char[flen];
+ if (!whole)
+ {
+ return nsnull;
+ }
+
+ // all exits from on here should be via 'goto out'
+
+ while(flen - totalRead)
+ {
+ PRUint32 avail;
+ PRUint32 read;
+
+ if(NS_FAILED(stream->Available(&avail)))
+ {
+ goto out;
+ }
+
+ if(avail > flen)
+ {
+ goto out;
+ }
+
+ if(NS_FAILED(stream->Read(whole+totalRead, avail, &read)))
+ {
+ goto out;
+ }
+
+ totalRead += read;
+ }
+
+ // Go ahead and close the stream now.
+ stream = nsnull;
+
+ if(!(state = XPT_NewXDRState(XPT_DECODE, whole, flen)))
+ {
+ goto out;
+ }
+
+ if(!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor))
+ {
+ goto out;
+ }
+
+ if (!XPT_DoHeader(aWorkingSet->GetStructArena(), &cursor, &header))
+ {
+ header = nsnull;
+ goto out;
+ }
+
+ out:
+ if(state)
+ XPT_DestroyXDRState(state);
+ if(whole)
+ delete [] whole;
+ return header;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
new file mode 100644
index 00000000..3d159c2c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
@@ -0,0 +1,981 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Library-private header for Interface Info system. */
+
+#ifndef xptiprivate_h___
+#define xptiprivate_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+// this after nsISupports, to pick up IID
+// so that xpt stuff doesn't try to define it itself...
+#include "xpt_struct.h"
+#include "xpt_xdr.h"
+
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+#include "nsIXPTLoader.h"
+
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIWeakReference.h"
+
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsISupportsArray.h"
+#include "nsSupportsArray.h"
+#include "nsInt64.h"
+
+#include "nsQuickSort.h"
+
+#include "nsXPIDLString.h"
+
+#include "nsIInputStream.h"
+
+#include "nsAutoLock.h"
+
+#include "pldhash.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prio.h"
+#include "prtime.h"
+#include "prenv.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/***************************************************************************/
+
+#if 0 && defined(DEBUG_jband)
+#define LOG_RESOLVE(x) printf x
+#define LOG_LOAD(x) printf x
+#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
+#else
+#define LOG_RESOLVE(x) ((void)0)
+#define LOG_LOAD(x) ((void)0)
+#define LOG_AUTOREG(x) xptiInterfaceInfoManager::WriteToLog x
+#endif
+
+#if 1 && defined(DEBUG_jband)
+#define SHOW_INFO_COUNT_STATS
+#endif
+
+/***************************************************************************/
+
+class xptiFile;
+class xptiInterfaceInfo;
+class xptiInterfaceInfoManager;
+class xptiInterfaceEntry;
+class xptiInterfaceGuts;
+class xptiTypelibGuts;
+class xptiWorkingSet;
+
+/***************************************************************************/
+
+class xptiTypelib
+{
+public:
+ // No ctors or dtors so that we can be in a union in xptiInterfaceInfo.
+ // Allow automatic shallow copies.
+
+ uint16 GetFileIndex() const {return mFileIndex;}
+ uint16 GetZipItemIndex() const {return mZipItemIndex;}
+
+ enum {NOT_ZIP = 0xffff};
+
+ PRBool IsZip() const {return mZipItemIndex != NOT_ZIP;}
+
+ void Init(uint16 aFileIndex, uint16 aZipItemIndex = NOT_ZIP)
+ {mFileIndex = aFileIndex; mZipItemIndex = aZipItemIndex;}
+
+ PRBool Equals(const xptiTypelib& r) const
+ {return mFileIndex == r.mFileIndex &&
+ mZipItemIndex == r.mZipItemIndex;}
+
+private:
+ uint16 mFileIndex;
+ uint16 mZipItemIndex;
+};
+
+/***************************************************************************/
+
+// No virtuals.
+// These are always constructed in the struct arena using placement new.
+// dtor need not be called.
+
+class xptiTypelibGuts
+{
+public:
+ static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* GetHeader() {return mHeader;}
+ PRUint16 GetEntryCount() const {return mHeader->num_interfaces;}
+
+ void SetEntryAt(PRUint16 i, xptiInterfaceEntry* ptr)
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ mEntryArray[i] = ptr;
+ }
+
+ xptiInterfaceEntry* GetEntryAt(PRUint16 i) const
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ return mEntryArray[i];
+ }
+
+private:
+ xptiTypelibGuts(); // not implemented
+ xptiTypelibGuts(XPTHeader* aHeader);
+ ~xptiTypelibGuts() {}
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+private:
+ XPTHeader* mHeader; // hold pointer into arena
+ xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
+};
+
+/***************************************************************************/
+
+class xptiFile
+{
+public:
+ const nsInt64& GetSize() const {return mSize;}
+ const nsInt64& GetDate() const {return mDate;}
+ const char* GetName() const {return mName;}
+ /*const*/ PRUint32 GetDirectory() const {return mDirectory;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiFile();
+
+ xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiFile();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiFile& r) const
+ {
+ return mDirectory == r.mDirectory &&
+ mSize == r.mSize &&
+ mDate == r.mDate &&
+ 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiFile(const xptiFile& r) {CopyFields(r);}
+ xptiFile& operator= (const xptiFile& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+private:
+ void CopyFields(const xptiFile& r)
+ {
+#ifdef DEBUG
+ // If 'this' has a workingset then it better match that of the assigner.
+ NS_ASSERTION(!mDEBUG_WorkingSet ||
+ mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
+ "illegal xptiFile assignment");
+ mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
+#endif
+
+ mSize = r.mSize;
+ mDate = r.mDate;
+ mName = r.mName;
+ mDirectory = r.mDirectory;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ nsInt64 mSize;
+ nsInt64 mDate;
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+ PRUint32 mDirectory;
+};
+
+/***************************************************************************/
+
+class xptiZipItem
+{
+public:
+ const char* GetName() const {return mName;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiZipItem();
+
+ xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiZipItem();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiZipItem& r) const
+ {
+ return 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiZipItem(const xptiZipItem& r) {CopyFields(r);}
+ xptiZipItem& operator= (const xptiZipItem& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+private:
+ void CopyFields(const xptiZipItem& r)
+ {
+#ifdef DEBUG
+ // If 'this' has a workingset then it better match that of the assigner.
+ NS_ASSERTION(!mDEBUG_WorkingSet ||
+ mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
+ "illegal xptiFile assignment");
+ mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
+#endif
+
+ mName = r.mName;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+};
+
+/***************************************************************************/
+
+class xptiWorkingSet
+{
+public:
+ xptiWorkingSet(); // not implmented
+ xptiWorkingSet(nsISupportsArray* aDirectories);
+ ~xptiWorkingSet();
+
+ PRBool IsValid() const;
+
+ void InvalidateInterfaceInfos();
+ void ClearHashTables();
+ void ClearFiles();
+ void ClearZipItems();
+
+ // utility methods...
+
+ xptiTypelibGuts* GetTypelibGuts(const xptiTypelib& typelib)
+ {
+ return typelib.IsZip() ?
+ GetZipItemAt(typelib.GetZipItemIndex()).GetGuts() :
+ GetFileAt(typelib.GetFileIndex()).GetGuts();
+ }
+
+ enum {NOT_FOUND = 0xffffffff};
+
+ // FileArray stuff...
+
+ PRUint32 GetFileCount() const {return mFileCount;}
+ PRUint32 GetFileFreeSpace()
+ {return mFileArray ? mMaxFileCount - mFileCount : 0;}
+
+ PRUint32 FindFile(PRUint32 dir, const char* name);
+
+ PRUint32 GetTypelibDirectoryIndex(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetDirectory();
+ }
+
+ const char* GetTypelibFileName(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetName();
+ }
+
+ xptiFile& GetFileAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ return mFileArray[i];
+ }
+
+ void SetFileAt(PRUint32 i, const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ mFileArray[i] = r;
+ }
+
+ void AppendFile(const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(mFileCount < mMaxFileCount, "bad param!");
+ mFileArray[mFileCount++] = r;
+ }
+
+ PRBool NewFileArray(PRUint32 count);
+ PRBool ExtendFileArray(PRUint32 count);
+
+ // ZipItemArray stuff...
+
+ PRUint32 GetZipItemCount() const {return mZipItemCount;}
+ PRUint32 GetZipItemFreeSpace()
+ {return mZipItemArray ? mMaxZipItemCount - mZipItemCount : 0;}
+
+ PRUint32 FindZipItemWithName(const char* name);
+
+ xptiZipItem& GetZipItemAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ return mZipItemArray[i];
+ }
+
+ void SetZipItemAt(PRUint32 i, const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ mZipItemArray[i] = r;
+ }
+
+ void AppendZipItem(const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(mZipItemCount < mMaxZipItemCount, "bad param!");
+ mZipItemArray[mZipItemCount++] = r;
+ }
+
+ PRBool NewZipItemArray(PRUint32 count);
+ PRBool ExtendZipItemArray(PRUint32 count);
+
+ // Directory stuff...
+
+ PRUint32 GetDirectoryCount();
+ nsresult GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ nsresult GetDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ PRBool FindDirectory(nsILocalFile* dir, PRUint32* index);
+ PRBool FindDirectoryOfFile(nsILocalFile* file, PRUint32* index);
+ PRBool DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc);
+
+ // Arena stuff...
+
+ XPTArena* GetStringArena() {return mStringArena;}
+ XPTArena* GetStructArena() {return mStructArena;}
+
+
+private:
+ PRUint32 mFileCount;
+ PRUint32 mMaxFileCount;
+ xptiFile* mFileArray; // using new[] and delete[]
+
+ PRUint32 mZipItemCount;
+ PRUint32 mMaxZipItemCount;
+ xptiZipItem* mZipItemArray; // using new[] and delete[]
+
+ XPTArena* mStringArena;
+ XPTArena* mStructArena;
+
+ nsCOMPtr<nsISupportsArray> mDirectories;
+
+public:
+ // XXX make these private with accessors
+ PLDHashTable* mNameTable;
+ PLDHashTable* mIIDTable;
+ PRUint32* mFileMergeOffsetMap; // always in an arena
+ PRUint32* mZipItemMergeOffsetMap; // always in an arena
+};
+
+/***************************************************************************/
+
+class xptiInterfaceGuts
+{
+public:
+ uint16 mMethodBaseIndex;
+ uint16 mConstantBaseIndex;
+ xptiInterfaceEntry* mParent;
+ XPTInterfaceDescriptor* mDescriptor;
+ xptiTypelib mTypelib;
+ xptiWorkingSet* mWorkingSet;
+
+ static xptiInterfaceGuts* NewGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ {
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceGuts));
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceGuts(aDescriptor, aTypelib, aWorkingSet);
+ }
+
+private:
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+ xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ : mMethodBaseIndex(0),
+ mConstantBaseIndex(0),
+ mParent(nsnull),
+ mDescriptor(aDescriptor),
+ mTypelib(aTypelib),
+ mWorkingSet(aWorkingSet) {}
+
+ ~xptiInterfaceGuts() {}
+};
+
+/***************************************************************************/
+
+// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
+// and a set of bitflags in one 8bit value. See below.
+
+class xptiInfoFlags
+{
+ enum {STATE_MASK = 3};
+public:
+ xptiInfoFlags(uint8 n) : mData(n) {}
+ xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
+
+ static uint8 GetStateMask()
+ {return uint8(STATE_MASK);}
+
+ void Clear()
+ {mData = 0;}
+
+ uint8 GetData() const
+ {return mData;}
+
+ uint8 GetState() const
+ {return mData & GetStateMask();}
+
+ void SetState(uint8 state)
+ {mData &= ~GetStateMask(); mData |= state;}
+
+ void SetFlagBit(uint8 flag, PRBool on)
+ {if(on)
+ mData |= ~GetStateMask() & flag;
+ else
+ mData &= GetStateMask() | ~flag;}
+
+ PRBool GetFlagBit(uint8 flag) const
+ {return (mData & flag) ? PR_TRUE : PR_FALSE;}
+
+private:
+ uint8 mData;
+};
+
+/****************************************************/
+
+// No virtual methods.
+// We always create in the struct arena and construct using "placement new".
+// No members need dtor calls.
+
+class xptiInterfaceEntry
+{
+public:
+ static xptiInterfaceEntry* NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ enum {
+ NOT_RESOLVED = 0,
+ PARTIALLY_RESOLVED = 1,
+ FULLY_RESOLVED = 2,
+ RESOLVE_FAILED = 3
+ };
+
+ // Additional bit flags...
+ enum {SCRIPTABLE = 4};
+
+ uint8 GetResolveState() const {return mFlags.GetState();}
+
+ PRBool IsFullyResolved() const
+ {return GetResolveState() == (uint8) FULLY_RESOLVED;}
+
+ PRBool HasInterfaceRecord() const
+ {int s = (int) GetResolveState();
+ return (s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface;}
+
+ const xptiTypelib& GetTypelibRecord() const
+ {return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
+
+ xptiInterfaceGuts* GetInterfaceGuts() const
+ {return HasInterfaceRecord() ? mInterface : nsnull;}
+
+#ifdef DEBUG
+ PRBool DEBUG_ScriptableFlagIsValid() const
+ {int s = (int) GetResolveState();
+ if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
+ {
+ if(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags))
+ return GetScriptableFlag();
+ return !GetScriptableFlag();
+ }
+ return PR_TRUE;
+ }
+#endif
+
+ void SetScriptableFlag(PRBool on)
+ {mFlags.SetFlagBit(uint8(SCRIPTABLE),on);}
+ PRBool GetScriptableFlag() const
+ {return mFlags.GetFlagBit(uint8(SCRIPTABLE));}
+
+ const nsID* GetTheIID() const {return &mIID;}
+ const char* GetTheName() const {return mName;}
+
+ PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
+ {return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
+
+ PRBool PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
+ xptiWorkingSet* aWorkingSet);
+
+ nsresult GetInterfaceInfo(xptiInterfaceInfo** info);
+ PRBool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
+ {return info == mInfo;}
+
+ void LockedInvalidateInterfaceInfo();
+ void LockedInterfaceInfoDeathNotification() {mInfo = nsnull;}
+
+ //////////////////////
+ // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+ nsresult GetName(char * *aName);
+ nsresult GetIID(nsIID * *aIID);
+ nsresult IsScriptable(PRBool *_retval);
+ // Except this one.
+ //nsresult GetParent(nsIInterfaceInfo * *aParent);
+ nsresult GetMethodCount(PRUint16 *aMethodCount);
+ nsresult GetConstantCount(PRUint16 *aConstantCount);
+ nsresult GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info);
+ nsresult GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info);
+ nsresult GetConstant(PRUint16 index, const nsXPTConstant * *constant);
+ nsresult GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
+ nsresult GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
+ nsresult GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval);
+ nsresult GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
+ nsresult GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
+ nsresult GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
+ nsresult IsIID(const nsIID * IID, PRBool *_retval);
+ nsresult GetNameShared(const char **name);
+ nsresult GetIIDShared(const nsIID * *iid);
+ nsresult IsFunction(PRBool *_retval);
+ nsresult HasAncestor(const nsIID * iid, PRBool *_retval);
+ nsresult GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid);
+
+ //////////////////////
+
+private:
+ xptiInterfaceEntry(); // not implemented
+
+ xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib);
+
+ xptiInterfaceEntry(const xptiInterfaceEntry& r,
+ size_t nameLength,
+ const xptiTypelib& typelib);
+ ~xptiInterfaceEntry();
+
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+ void SetResolvedState(int state)
+ {mFlags.SetState(uint8(state));}
+
+ PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
+
+ // We only call these "*Locked" variants after locking. This is done to
+ // allow reentrace as files are loaded and various interfaces resolved
+ // without having to worry about the locked state.
+
+ PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
+ {return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
+ PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
+
+ // private helpers
+
+ nsresult GetEntryForParam(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry);
+
+ nsresult GetTypeInArray(const nsXPTParamInfo* param,
+ uint16 dimension,
+ const XPTTypeDescriptor** type);
+
+private:
+ nsID mIID;
+ union {
+ xptiTypelib mTypelib; // Valid only until resolved.
+ xptiInterfaceGuts* mInterface; // Valid only after resolved.
+ };
+ xptiInterfaceInfo* mInfo; // May come and go.
+ xptiInfoFlags mFlags;
+ char mName[1]; // Always last. Sized to fit.
+};
+
+struct xptiHashEntry : public PLDHashEntryHdr
+{
+ xptiInterfaceEntry* value;
+};
+
+/****************************************************/
+
+class xptiInterfaceInfo : public nsIInterfaceInfo
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // Use delegation to implement (most!) of nsIInterfaceInfo.
+ NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
+ NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
+ NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
+ // Except this one.
+ NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent)
+ {
+ if(!EnsureResolved() || !EnsureParent())
+ return NS_ERROR_UNEXPECTED;
+ NS_IF_ADDREF(*aParent = mParent);
+ return NS_OK;
+ }
+ NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
+ NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
+ NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
+ NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); }
+ NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetLengthIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
+ NS_IMETHOD IsIID(const nsIID * IID, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
+ NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
+ NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
+ NS_IMETHOD IsFunction(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
+ NS_IMETHOD HasAncestor(const nsIID * iid, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
+ NS_IMETHOD GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
+
+public:
+ xptiInterfaceInfo(xptiInterfaceEntry* entry);
+
+ void Invalidate()
+ {NS_IF_RELEASE(mParent); mEntry = nsnull;}
+
+#ifdef DEBUG
+ static void DEBUG_ShutdownNotification();
+#endif
+
+private:
+
+ ~xptiInterfaceInfo();
+
+ // Note that mParent might still end up as nsnull if we don't have one.
+ PRBool EnsureParent(xptiWorkingSet* aWorkingSet = nsnull)
+ {
+ NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
+ return mParent || !mEntry->GetInterfaceGuts()->mParent || BuildParent();
+ }
+
+ PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
+ {
+ return mEntry && mEntry->EnsureResolved(aWorkingSet);
+ }
+
+ PRBool BuildParent()
+ {
+ NS_ASSERTION(mEntry &&
+ mEntry->IsFullyResolved() &&
+ !mParent &&
+ mEntry->GetInterfaceGuts()->mParent,
+ "bad BuildParent call");
+ return NS_SUCCEEDED(mEntry->GetInterfaceGuts()->mParent->
+ GetInterfaceInfo(&mParent));
+ }
+
+ xptiInterfaceInfo(); // not implemented
+
+private:
+ xptiInterfaceEntry* mEntry;
+ xptiInterfaceInfo* mParent;
+};
+
+/***************************************************************************/
+
+class xptiManifest
+{
+public:
+ static PRBool Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Delete(xptiInterfaceInfoManager* aMgr);
+
+private:
+ xptiManifest(); // no implementation
+};
+
+/***************************************************************************/
+
+class xptiZipLoaderSink : public nsIXPTLoaderSink
+{
+public:
+ xptiZipLoaderSink(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet) :
+ mManager(aMgr),
+ mWorkingSet(aWorkingSet) {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIXPTLOADERSINK
+
+private:
+ ~xptiZipLoaderSink() {}
+
+ xptiInterfaceInfoManager* mManager;
+ xptiWorkingSet* mWorkingSet;
+
+};
+
+class xptiZipLoader
+{
+public:
+ xptiZipLoader(); // not implemented
+
+ static XPTHeader*
+ ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet);
+
+};
+
+
+/***************************************************************************/
+
+class xptiFileType
+{
+public:
+ enum Type {UNKNOWN = -1, XPT = 0, ZIP = 1 };
+
+ static Type GetType(const char* name);
+
+ static PRBool IsUnknown(const char* name)
+ {return GetType(name) == UNKNOWN;}
+
+ static PRBool IsXPT(const char* name)
+ {return GetType(name) == XPT;}
+
+ static PRBool IsZip(const char* name)
+ {return GetType(name) == ZIP;}
+private:
+ xptiFileType(); // no implementation
+};
+
+/***************************************************************************/
+
+// We use this is as a fancy way to open a logfile to be used within the scope
+// of some given function where it is instantiated.
+
+class xptiAutoLog
+{
+public:
+ xptiAutoLog(); // not implemented
+ xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append);
+ ~xptiAutoLog();
+private:
+ void WriteTimestamp(PRFileDesc* fd, const char* msg);
+
+ xptiInterfaceInfoManager* mMgr;
+ PRFileDesc* mOldFileDesc;
+#ifdef DEBUG
+ PRFileDesc* m_DEBUG_FileDesc;
+#endif
+};
+
+/***************************************************************************/
+
+class xptiInterfaceInfoManager
+ : public nsIInterfaceInfoSuperManager
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEINFOMANAGER
+ NS_DECL_NSIINTERFACEINFOSUPERMANAGER
+
+ // helper
+ PRBool
+ FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet);
+
+public:
+ static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
+ static void FreeInterfaceInfoManager();
+
+ xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;}
+ PRFileDesc* GetOpenLogFile() {return mOpenLogFile;}
+ PRFileDesc* SetOpenLogFile(PRFileDesc* fd)
+ {PRFileDesc* temp = mOpenLogFile; mOpenLogFile = fd; return temp;}
+
+ PRBool LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet = nsnull);
+
+ PRBool GetApplicationDir(nsILocalFile** aDir);
+ PRBool GetCloneOfManifestLocation(nsILocalFile** aDir);
+
+ void GetSearchPath(nsISupportsArray** aSearchPath)
+ {NS_ADDREF(*aSearchPath = mSearchPath);}
+
+ static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mResolveLock;}
+
+ static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mAutoRegLock;}
+
+ static PRMonitor* GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mInfoMonitor;}
+
+ static void WriteToLog(const char *fmt, ...);
+
+private:
+ ~xptiInterfaceInfoManager();
+ xptiInterfaceInfoManager(); // not implmented
+ xptiInterfaceInfoManager(nsISupportsArray* aSearchPath);
+
+ enum AutoRegMode {
+ NO_FILES_CHANGED = 0,
+ FILES_ADDED_ONLY,
+ FULL_VALIDATION_REQUIRED
+ };
+
+ PRBool IsValid();
+
+ PRBool BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList);
+
+ nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet* aWorkingSet);
+
+ AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded);
+
+ PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet);
+
+ void LogStats();
+
+ PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
+ PRBool DEBUG_DumpFileArray(nsILocalFile** aFileArray, PRUint32 count);
+ PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet);
+
+ static PRBool BuildFileSearchPath(nsISupportsArray** aPath);
+
+private:
+ xptiWorkingSet mWorkingSet;
+ nsCOMPtr<nsILocalFile> mStatsLogFile;
+ nsCOMPtr<nsILocalFile> mAutoRegLogFile;
+ PRFileDesc* mOpenLogFile;
+ PRLock* mResolveLock;
+ PRLock* mAutoRegLock;
+ PRMonitor* mInfoMonitor;
+ PRLock* mAdditionalManagersLock;
+ nsSupportsArray mAdditionalManagers;
+ nsCOMPtr<nsISupportsArray> mSearchPath;
+};
+
+/***************************************************************************/
+// utilities...
+
+nsresult xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile);
+
+nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile);
+
+#endif /* xptiprivate_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore
new file mode 100644
index 00000000..f29041e6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+TestInterfaceInfo
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in
new file mode 100644
index 00000000..9b7f1ed4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in
@@ -0,0 +1,58 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+SIMPLE_PROGRAMS = TestInterfaceInfo$(BIN_SUFFIX)
+
+CPPSRCS = TestInterfaceInfo.cpp
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTI_API
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp
new file mode 100644
index 00000000..75005c50
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Some simple smoke tests of the typelib loader. */
+
+#include "nscore.h"
+
+#include "nsISupports.h"
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+
+#include <stdio.h>
+
+// This file expects the nsInterfaceInfoManager to be able to discover
+// .xpt files corresponding to those in xpcom/idl. Currently this
+// means setting XPTDIR in the environment to some directory
+// containing these files.
+
+int main (int argc, char **argv) {
+ int i;
+ nsIID *iid1, *iid2, *iid3;
+ char *name1, *name2, *name3;
+ nsIInterfaceInfo *info2, *info3, *info4, *info5;
+
+ nsIInterfaceInfoManager *iim = XPTI_GetInterfaceInfoManager();
+
+ fprintf(stderr, "\ngetting iid for 'nsISupports'\n");
+ iim->GetIIDForName("nsISupports", &iid1);
+ iim->GetNameForIID(iid1, &name1);
+ fprintf(stderr, "%s iid %s\n", name1, iid1->ToString());
+
+ fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
+ iim->GetIIDForName("nsIInputStream", &iid2);
+ iim->GetNameForIID(iid2, &name2);
+ fprintf(stderr, "%s iid %s\n", name2, iid2->ToString());
+
+ fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1);
+ fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2);
+
+ fprintf(stderr, "\ngetting info for iid2 from above\n");
+ iim->GetInfoForIID(iid2, &info2);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info2)->print(stderr);
+#endif
+
+ fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
+ iim->GetIIDForName("nsIInputStream", &iid3);
+ iim->GetNameForIID(iid3, &name3);
+ fprintf(stderr, "%s iid %s\n", name3, iid2->ToString());
+ iim->GetInfoForIID(iid3, &info3);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info3)->print(stderr);
+#endif
+
+ fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n");
+ iim->GetInfoForName("nsIBidirectionalEnumerator", &info4);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info4)->print(stderr);
+#endif
+
+ fprintf(stderr, "\nparams work?\n");
+ fprintf(stderr, "\ngetting info for name 'nsIServiceManager'\n");
+ iim->GetInfoForName("nsIServiceManager", &info5);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info5)->print(stderr);
+#endif
+
+ // XXX: nsIServiceManager is no more; what do we test with?
+ if (info5 == NULL) {
+ fprintf(stderr, "\nNo nsIServiceManager; cannot continue.\n");
+ return 1;
+ }
+
+ uint16 methodcount;
+ info5->GetMethodCount(&methodcount);
+ const nsXPTMethodInfo *mi;
+ for (i = 0; i < methodcount; i++) {
+ info5->GetMethodInfo(i, &mi);
+ fprintf(stderr, "method %d, name %s\n", i, mi->GetName());
+ }
+
+ // 7 is GetServiceWithListener, which has juicy params.
+ info5->GetMethodInfo(7, &mi);
+// uint8 paramcount = mi->GetParamCount();
+
+ nsXPTParamInfo param2 = mi->GetParam(2);
+ // should be IID for nsIShutdownListener
+ nsIID *nsISL;
+ info5->GetIIDForParam(7, &param2, &nsISL);
+// const nsIID *nsISL = param2.GetInterfaceIID(info5);
+ fprintf(stderr, "iid assoc'd with param 2 of method 7 of GetServiceWithListener - %s\n", nsISL->ToString());
+ // if we look up the name?
+ char *nsISLname;
+ iim->GetNameForIID(nsISL, &nsISLname);
+ fprintf(stderr, "which is called %s\n", nsISLname);
+
+ fprintf(stderr, "\nhow about one defined in a different typelib\n");
+ nsXPTParamInfo param3 = mi->GetParam(3);
+ // should be IID for nsIShutdownListener
+ nsIID *nsISS;
+ info5->GetIIDForParam(7, &param3, &nsISS);
+// const nsIID *nsISS = param3.GetInterfaceIID(info5);
+ fprintf(stderr, "iid assoc'd with param 3 of method 7 of GetServiceWithListener - %s\n", nsISS->ToString());
+ // if we look up the name?
+ char *nsISSname;
+ iim->GetNameForIID(nsISS, &nsISSname);
+ fprintf(stderr, "which is called %s\n", nsISSname);
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/.cvsignore b/src/libs/xpcom18a4/xpcom/sample/.cvsignore
new file mode 100644
index 00000000..d1f93146
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+nsTestSample
diff --git a/src/libs/xpcom18a4/xpcom/sample/Makefile.in b/src/libs/xpcom18a4/xpcom/sample/Makefile.in
new file mode 100644
index 00000000..5510e795
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/Makefile.in
@@ -0,0 +1,113 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcomsample
+XPIDL_MODULE = xpcomsample
+LIBRARY_NAME = xpcomsample
+SHORT_LIBNAME = xpcomsmp
+
+IS_COMPONENT = 1
+MODULE_NAME = nsSampleModule
+
+# Ensure that the xpcom classes that we build
+# do not export themselves
+DEFINES += -DXPCOM_GLUE
+
+
+REQUIRES = string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ nsSample.cpp \
+ nsSampleModule.cpp \
+ $(NULL)
+
+XPIDLSRCS = nsISample.idl
+
+TESTCPPSRCS = nsTestSample.cpp
+
+CPPSRCS += $(TESTCPPSRCS)
+
+SIMPLE_PROGRAMS = $(TESTCPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+EXTRA_COMPONENTS = nsSample.js
+
+# separate libraries linked in.
+EXTRA_DSO_LDOPTS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# Needed to resolve __yylex (?)
+ifeq ($(OS_ARCH)$(OS_RELEASE),FreeBSD2)
+LIBS += -lpcap
+endif
+
+# Need to link with CoreFoundation on Mac
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+EXTRA_DSO_LDOPTS += \
+ $(TK_LIBS) \
+ $(NULL)
+
+LIBS += \
+ $(TK_LIBS) \
+ $(NULL)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+libs:: $(TARGETS)
+ $(INSTALL) $(srcdir)/xpconnect-sample.html $(DIST)/bin/res/samples
+
+install:: $(TARGETS)
+ $(SYSINSTALL) $(IFLAGS1) $(srcdir)/xpconnect-sample.html $(DESTDIR)$(mozappdir)/res/samples
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsISample.idl b/src/libs/xpcom18a4/xpcom/sample/nsISample.idl
new file mode 100644
index 00000000..22454e7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsISample.idl
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * A sample of XPConnect. This file contains a sample interface.
+ *
+ */
+
+#include "nsISupports.idl"
+
+/**
+ * The uuid is a unique number identifying the interface normally
+ * called IID. It can be generated as follows:
+ *
+ * Windows: guidgen.exe
+ * Unix: uuidgen which comes with e2fsprogs package
+ * Mac: ???
+ * All platform: Using irc, connect to irc.mozilla.org and type in
+ * /join #mozilla
+ * /msg mozbot uuid
+ *
+ */
+[scriptable, uuid(7CB5B7A1-07D7-11d3-BDE2-000064657374)]
+interface nsISample : nsISupports
+{
+ attribute string value;
+ void writeValue(in string aPrefix);
+ void poke(in string aValue);
+};
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSample.cpp b/src/libs/xpcom18a4/xpcom/sample/nsSample.cpp
new file mode 100644
index 00000000..ac3d8449
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSample.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/**
+ *
+ * A sample of XPConnect. This file contains an implementation nsSample
+ * of the interface nsISample.
+ *
+ */
+#include <stdio.h>
+
+#include "nsSample.h"
+#include "nsMemory.h"
+
+#include "nsEmbedString.h"
+////////////////////////////////////////////////////////////////////////
+
+nsSampleImpl::nsSampleImpl() : mValue(nsnull)
+{
+ mValue = (char*)nsMemory::Clone("initial value", 14);
+}
+
+nsSampleImpl::~nsSampleImpl()
+{
+ if (mValue)
+ nsMemory::Free(mValue);
+}
+
+/**
+ * NS_IMPL_ISUPPORTS1 expands to a simple implementation of the nsISupports
+ * interface. This includes a proper implementation of AddRef, Release,
+ * and QueryInterface. If this class supported more interfaces than just
+ * nsISupports,
+ * you could use NS_IMPL_ADDREF() and NS_IMPL_RELEASE() to take care of the
+ * simple stuff, but you would have to create QueryInterface on your own.
+ * nsSampleFactory.cpp is an example of this approach.
+ * Notice that the second parameter to the macro is name of the interface, and
+ * NOT the #defined IID.
+ *
+ * The _CI variant adds support for nsIClassInfo, which permits introspection
+ * and interface flattening.
+ */
+NS_IMPL_ISUPPORTS1_CI(nsSampleImpl, nsISample)
+
+/**
+ * Notice that in the protoype for this function, the NS_IMETHOD macro was
+ * used to declare the return type. For the implementation, the return
+ * type is declared by NS_IMETHODIMP
+ */
+NS_IMETHODIMP
+nsSampleImpl::GetValue(char** aValue)
+{
+ NS_PRECONDITION(aValue != nsnull, "null ptr");
+ if (! aValue)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mValue) {
+ /**
+ * GetValue's job is to return data known by an instance of
+ * nsSampleImpl to the outside world. If we were to simply return
+ * a pointer to data owned by this instance, and the client were to
+ * free it, bad things would surely follow.
+ * On the other hand, if we create a new copy of the data for our
+ * client, and it turns out that client is implemented in JavaScript,
+ * there would be no way to free the buffer. The solution to the
+ * buffer ownership problem is the nsMemory singleton. Any buffer
+ * returned by an XPCOM method should be allocated by the nsMemory.
+ * This convention lets things like JavaScript reflection do their
+ * job, and simplifies the way C++ clients deal with returned buffers.
+ */
+ *aValue = (char*) nsMemory::Clone(mValue, strlen(mValue) + 1);
+ if (! *aValue)
+ return NS_ERROR_NULL_POINTER;
+ }
+ else {
+ *aValue = nsnull;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSampleImpl::SetValue(const char* aValue)
+{
+ NS_PRECONDITION(aValue != nsnull, "null ptr");
+ if (! aValue)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mValue) {
+ nsMemory::Free(mValue);
+ }
+
+ /**
+ * Another buffer passing convention is that buffers passed INTO your
+ * object ARE NOT YOURS. Keep your hands off them, unless they are
+ * declared "inout". If you want to keep the value for posterity,
+ * you will have to make a copy of it.
+ */
+ mValue = (char*) nsMemory::Clone(aValue, strlen(aValue) + 1);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSampleImpl::Poke(const char* aValue)
+{
+ return SetValue((char*) aValue);
+}
+
+
+static void GetStringValue(nsACString& aValue)
+{
+ NS_CStringSetData(aValue, "GetValue");
+}
+
+NS_IMETHODIMP
+nsSampleImpl::WriteValue(const char* aPrefix)
+{
+ NS_PRECONDITION(aPrefix != nsnull, "null ptr");
+ if (! aPrefix)
+ return NS_ERROR_NULL_POINTER;
+
+ printf("%s %s\n", aPrefix, mValue);
+
+ // This next part illustrates the nsEmbedString:
+ nsEmbedString foopy;
+ foopy.Append(PRUnichar('f'));
+ foopy.Append(PRUnichar('o'));
+ foopy.Append(PRUnichar('o'));
+ foopy.Append(PRUnichar('p'));
+ foopy.Append(PRUnichar('y'));
+
+ const PRUnichar* f = foopy.get();
+ PRUint32 l = foopy.Length();
+ printf("%c%c%c%c%c %d\n", char(f[0]), char(f[1]), char(f[2]), char(f[3]), char(f[4]), l);
+
+ nsEmbedCString foopy2;
+ GetStringValue(foopy2);
+
+ //foopy2.AppendLiteral("foopy");
+ const char* f2 = foopy2.get();
+ PRUint32 l2 = foopy2.Length();
+
+ printf("%s %d\n", f2, l2);
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSample.h b/src/libs/xpcom18a4/xpcom/sample/nsSample.h
new file mode 100644
index 00000000..40dec0b3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSample.h
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * A sample of XPConnect. This file is the header of an implementation
+ * nsSample of the nsISample interface.
+ *
+ */
+
+#include "nsISample.h"
+
+/**
+ * SampleImpl is an implementation of the nsISample interface. In XPCOM,
+ * there can be more than one implementation of an given interface. Class
+ * IDs (CIDs) uniquely identify a particular implementation of an interface.
+ * Interface IDs (IIDs) uniquely identify an interface.
+ *
+ * The CID is also a unique number that looks just like an IID
+ * and uniquely identifies an implementation
+ * {7CB5B7A0-07D7-11d3-BDE2-000064657374}
+ */
+
+#define NS_SAMPLE_CID \
+{ 0x7cb5b7a0, 0x7d7, 0x11d3, { 0xbd, 0xe2, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
+
+#define NS_SAMPLE_CONTRACTID "@mozilla.org/sample;1"
+
+
+class nsSampleImpl : public nsISample
+{
+public:
+ nsSampleImpl();
+
+ /**
+ * This macro expands into a declaration of the nsISupports interface.
+ * Every XPCOM component needs to implement nsISupports, as it acts
+ * as the gateway to other interfaces this component implements. You
+ * could manually declare QueryInterface, AddRef, and Release instead
+ * of using this macro, but why?
+ */
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ /**
+ * This macro is defined in the nsISample.h file, and is generated
+ * automatically by the xpidl compiler. It expands to
+ * declarations of all of the methods required to implement the
+ * interface. xpidl will generate a NS_DECL_[INTERFACENAME] macro
+ * for each interface that it processes.
+ *
+ * The methods of nsISample are discussed individually below, but
+ * commented out (because this macro already defines them.)
+ */
+ NS_DECL_NSISAMPLE
+
+ /**
+ * The following is an explanation of how the interface header
+ * file expands to for a c++ implementation. NS_DELC_NSISAMPLE
+ * takes care of defining the right c++ implementation.
+ *
+ * The following if provided for more understanding.
+ *
+ * NS_IMETHOD expands to the standard XPCOM return type. XPCOM methods
+ * should never return any other type. The return value is used
+ * behind the scenes by the XPConnect runtime to figure out if the call
+ * failed in any way.
+ * These methods were generated by "attribute string Value" in
+ * nsISample.idl. When reflected into JavaScript, XPCOM will use these
+ * calls as Getter/Setter ops, so that they can be called transparently
+ * as "sample.Value='foo';" and "var val = sample.Value"
+ */
+ /* NS_IMETHOD GetValue(char * *aValue); */
+ /* NS_IMETHOD SetValue(char * aValue); */
+
+ /**
+ * The const came from the "in" specifier in nsISample.idl. "in"
+ * specifies that the value of this parameter is used only for input,
+ * this method is not allowed to modify the contents of the buffer.
+ */
+ /* NS_IMETHOD WriteValue(const char *aPrefix); */
+
+ /**
+ * nsISample.idl specifies all of it's string types as string, instead
+ * of wstring (wide string), the Unicode type. If the world were a
+ * perfect place, all normal strings in XPCOM interfaces would be unicode.
+ * If this type had been specified as wstring, it would appear as
+ * PRUnichar * in C++, which is the NSPR type for unicode characters.
+ */
+ /* NS_IMETHOD Poke(const char* aValue); */
+
+private:
+ ~nsSampleImpl();
+
+ char* mValue;
+};
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSample.js b/src/libs/xpcom18a4/xpcom/sample/nsSample.js
new file mode 100644
index 00000000..1cc9a091
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSample.js
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * No magic constructor behaviour, as is de rigeur for XPCOM.
+ * If you must perform some initialization, and it could possibly fail (even
+ * due to an out-of-memory condition), you should use an Init method, which
+ * can convey failure appropriately (thrown exception in JS,
+ * NS_FAILED(nsresult) return in C++).
+ *
+ * In JS, you can actually cheat, because a thrown exception will cause the
+ * CreateInstance call to fail in turn, but not all languages are so lucky.
+ * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
+ * for portability reasons -- and even when you're building completely
+ * platform-specific code, you can't throw across an XPCOM method boundary.)
+ */
+function mySample() { /* big comment for no code, eh? */ }
+
+/* decorate prototype to provide ``class'' methods and property accessors */
+mySample.prototype = {
+ /*
+ * get and set are new Magic in JS1.5, borrowing the intent -- if not
+ * the exact syntax -- from the JS2 design. They define accessors for
+ * properties on the JS object, follow the expected rules for prototype
+ * delegation, and make a mean cup of coffee.
+ */
+ get value() { return this.val; },
+ set value(newval) { return this.val = newval; },
+
+ writeValue: function (aPrefix) {
+ debug("mySample::writeValue => " + aPrefix + this.val + "\n");
+ },
+ poke: function (aValue) { this.val = aValue; },
+
+ QueryInterface: function (iid) {
+ if (iid.equals(Components.interfaces.nsISample) ||
+ iid.equals(Components.interfaces.nsISupports))
+ return this;
+
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ },
+
+ val: "<default value>"
+}
+
+var myModule = {
+ firstTime: true,
+
+ /*
+ * RegisterSelf is called at registration time (component installation
+ * or the only-until-release startup autoregistration) and is responsible
+ * for notifying the component manager of all components implemented in
+ * this module. The fileSpec, location and type parameters are mostly
+ * opaque, and should be passed on to the registerComponent call
+ * unmolested.
+ */
+ registerSelf: function (compMgr, fileSpec, location, type) {
+ if (this.firstTime) {
+ debug("*** Deferring registration of sample JS components\n");
+ this.firstTime = false;
+ throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
+ }
+ debug("*** Registering sample JS components\n");
+ compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+ compMgr.registerFactoryLocation(this.myCID,
+ "Sample JS Component",
+ this.myProgID,
+ fileSpec,
+ location,
+ type);
+ },
+
+ /*
+ * The GetClassObject method is responsible for producing Factory objects
+ */
+ getClassObject: function (compMgr, cid, iid) {
+ if (!cid.equals(this.myCID))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+
+ if (!iid.equals(Components.interfaces.nsIFactory))
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+
+ return this.myFactory;
+ },
+
+ /* CID for this class */
+ myCID: Components.ID("{dea98e50-1dd1-11b2-9344-8902b4805a2e}"),
+
+ /* ProgID for this class */
+ myProgID: "@mozilla.org/jssample;1",
+
+ /* factory object */
+ myFactory: {
+ /*
+ * Construct an instance of the interface specified by iid, possibly
+ * aggregating it with the provided outer. (If you don't know what
+ * aggregation is all about, you don't need to. It reduces even the
+ * mightiest of XPCOM warriors to snivelling cowards.)
+ */
+ createInstance: function (outer, iid) {
+ debug("CI: " + iid + "\n");
+ if (outer != null)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+
+ return (new mySample()).QueryInterface(iid);
+ }
+ },
+
+ /*
+ * The canUnload method signals that the component is about to be unloaded.
+ * C++ components can return false to indicate that they don't wish to be
+ * unloaded, but the return value from JS components' canUnload is ignored:
+ * mark-and-sweep will keep everything around until it's no longer in use,
+ * making unconditional ``unload'' safe.
+ *
+ * You still need to provide a (likely useless) canUnload method, though:
+ * it's part of the nsIModule interface contract, and the JS loader _will_
+ * call it.
+ */
+ canUnload: function(compMgr) {
+ debug("*** Unloading sample JS components\n");
+ return true;
+ }
+};
+
+function NSGetModule(compMgr, fileSpec) {
+ return myModule;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp b/src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp
new file mode 100644
index 00000000..f02b9a5c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddu <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsIGenericFactory.h"
+
+#include "nsSample.h"
+
+////////////////////////////////////////////////////////////////////////
+// NOTE this file supercedes nsSampleFactory.cpp. nsSampleFactory has
+// extensive comments, but it has been CVS removed to reduce clutter
+// in this sample. It's available to the interested via CVS history:
+// cvs up nsSampleFactory.cpp -r 1.10
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// With the below sample, you can define an implementation glue
+// that talks with xpcom for creation of component nsSampleImpl
+// that implement the interface nsISample. This can be extended for
+// any number of components.
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// Define the contructor function for the object nsSampleImpl
+//
+// What this does is defines a function nsSampleImplConstructor which we
+// will specific in the nsModuleComponentInfo table. This function will
+// be used by the generic factory to create an instance of nsSampleImpl.
+//
+// NOTE: This creates an instance of nsSampleImpl by using the default
+// constructor nsSampleImpl::nsSampleImpl()
+//
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleImpl)
+
+////////////////////////////////////////////////////////////////////////
+// Define a table of CIDs implemented by this module along with other
+// information like the function to create an instance, contractid, and
+// class name.
+//
+// The Registration and Unregistration proc are optional in the structure.
+//
+static NS_METHOD nsSampleRegistrationProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const char *componentType,
+ const nsModuleComponentInfo *info)
+{
+ // Do any registration specific activity like adding yourself to a
+ // category. The Generic Module will take care of registering your
+ // component with xpcom. You dont need to do that. Only any component
+ // specific additional activity needs to be done here.
+
+ // This functions is optional. If you dont need it, dont add it to the structure.
+
+ return NS_OK;
+}
+
+static NS_METHOD nsSampleUnregistrationProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const nsModuleComponentInfo *info)
+{
+ // Undo any component specific registration like adding yourself to a
+ // category here. The Generic Module will take care of unregistering your
+ // component from xpcom. You dont need to do that. Only any component
+ // specific additional activity needs to be done here.
+
+ // This functions is optional. If you dont need it, dont add it to the structure.
+
+ // Return value is not used from this function.
+ return NS_OK;
+}
+
+// For each class that wishes to support nsIClassInfo, add a line like this
+NS_DECL_CLASSINFO(nsSampleImpl)
+
+static const nsModuleComponentInfo components[] =
+{
+ { "Sample Component", NS_SAMPLE_CID, NS_SAMPLE_CONTRACTID, nsSampleImplConstructor,
+ nsSampleRegistrationProc /* NULL if you dont need one */,
+ nsSampleUnregistrationProc /* NULL if you dont need one */,
+ NULL /* no factory destructor */,
+ NS_CI_INTERFACE_GETTER_NAME(nsSampleImpl),
+ NULL /* no language helper */,
+ &NS_CLASSINFO_NAME(nsSampleImpl)
+ }
+};
+
+////////////////////////////////////////////////////////////////////////
+// Implement the NSGetModule() exported function for your module
+// and the entire implementation of the module object.
+//
+// NOTE: If you want to use the module shutdown to release any
+// module specific resources, use the macro
+// NS_IMPL_NSGETMODULE_WITH_DTOR() instead of the vanilla
+// NS_IMPL_NSGETMODULE()
+//
+NS_IMPL_NSGETMODULE(nsSampleModule, components)
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp b/src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp
new file mode 100644
index 00000000..edf9ce78
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/**
+ * A Test application that exercises the sample moudule. This is intented
+ * to be a sample application for using xpcom standalone.
+ */
+
+#include <stdio.h>
+
+#include "nsISample.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentRegistrar.h"
+
+#ifdef XPCOM_GLUE
+#include "nsXPCOMGlue.h"
+#include "nsMemory.h"
+#else
+#include "nsXPIDLString.h"
+#endif
+
+#define NS_SAMPLE_CONTRACTID "@mozilla.org/sample;1"
+
+int
+main(void)
+{
+ nsresult rv;
+
+#ifdef XPCOM_GLUE
+ XPCOMGlueStartup(nsnull);
+#endif
+
+ // Initialize XPCOM
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: XPCOM intialization error [%x].\n", rv);
+ return -1;
+ }
+ // register all components in our default component directory
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ nsCOMPtr<nsIComponentManager> manager = do_QueryInterface(registrar);
+ NS_ASSERTION(registrar, "Null nsIComponentManager");
+
+ // Create an instance of our component
+ nsCOMPtr<nsISample> mysample;
+ rv = manager->CreateInstanceByContractID(NS_SAMPLE_CONTRACTID,
+ nsnull,
+ NS_GET_IID(nsISample),
+ getter_AddRefs(mysample));
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Cannot create instance of component " NS_SAMPLE_CONTRACTID " [%x].\n"
+ "Debugging hint:\n"
+ "\tsetenv NSPR_LOG_MODULES nsComponentManager:5\n"
+ "\tsetenv NSPR_LOG_FILE xpcom.log\n"
+ "\t./nsTestSample\n"
+ "\t<check the contents for xpcom.log for possible cause of error>.\n",
+ rv);
+ return -2;
+ }
+
+ // Call methods on our sample to test it out.
+ rv = mysample->WriteValue("Inital print:");
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Calling nsISample::WriteValue() [%x]\n", rv);
+ return -3;
+ }
+
+ const char *testValue = "XPCOM defies gravity";
+ rv = mysample->SetValue(testValue);
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Calling nsISample::SetValue() [%x]\n", rv);
+ return -3;
+ }
+ printf("Set value to: %s\n", testValue);
+#ifndef XPCOM_GLUE
+ nsXPIDLCString str;
+ rv = mysample->GetValue(getter_Copies(str));
+#else
+ char *str;
+ rv = mysample->GetValue(&str);
+#endif
+
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Calling nsISample::GetValue() [%x]\n", rv);
+ return -3;
+ }
+ if (strcmp(str, testValue))
+ {
+ printf("Test FAILED.\n");
+ return -4;
+ }
+
+#ifdef XPCOM_GLUE
+ nsMemory::Free(str);
+#endif
+ rv = mysample->WriteValue("Final print :");
+ printf("Test passed.\n");
+
+ // All nsCOMPtr's must be deleted prior to calling shutdown XPCOM
+ // as we should not hold references passed XPCOM Shutdown.
+ servMan = 0;
+ registrar = 0;
+ manager = 0;
+ mysample = 0;
+
+ // Shutdown XPCOM
+ NS_ShutdownXPCOM(nsnull);
+
+#ifdef XPCOM_GLUE
+ XPCOMGlueShutdown();
+#endif
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/sample/win32.order b/src/libs/xpcom18a4/xpcom/sample/win32.order
new file mode 100644
index 00000000..bf181a81
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/win32.order
@@ -0,0 +1 @@
+_NSGetModule ; 1
diff --git a/src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html b/src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html
new file mode 100644
index 00000000..78e91be1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html
@@ -0,0 +1,220 @@
+
+<center><b><font size=+2>XPConnect Sample</font></b>
+
+<p>
+<a href="mailto:arielb@rice.edu">Ariel Blackenroth &lt;arielb@rice.edu&gt;</a>
+<br>
+<a href="mailto:mang@subcarrier.org">Michael Ang &lt;mang@subcarrier.org&gt;</a>
+<br>
+Last modified
+<script>
+document.write(document.lastModified);
+</script>
+</center>
+
+<p>In the spirit of "worse is better" this somewhat rough guide is being
+released to the world. It will be expanded upon and improved.
+
+<p>XPConnect allows JavaScript
+to transparantly access and manipulate XPCOM objects; this communication
+between JavaScript and
+native code is done by having their interfaces defined in the XPIDL interface
+definition language. See the <a href="http://www.mozilla.org/scriptable/roadmap.html">Roadmap
+for documentation on XPCOM, XPConnect, XPTCall and XPIDL</a> for more information.
+
+<p><b>Overview</b>
+
+<p>
+This sample demonstrates accessing a XPCOM object through XPConnect.
+The JavaScript executed when this page loads creates an instance
+of the object by
+using the <tt>Components</tt> object, then accesses it through
+the <a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsISample.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>:
+<br>
+<pre>
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["@mozilla.org/sample;1"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+</pre>
+
+<p>
+The buttons on the form are connected to JavaScript event handlers which
+call the methods defined in C++.
+
+
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsISample.idl">nsISample.idl</a></b>
+<p>This is the interface declaration for the XPCOM object. It defines
+two functions, their parameters, and one attribute. It also defines
+the interface's id. The idl file is compiled by the xpidl compiler
+into a C++ header, nsISample.h and a .xpt file which is a binary representation
+of the interface used at runtime.
+<br><tt>attribute string value;</tt>
+<br><tt>void writeValue(in string aPrefix);</tt>
+<br><tt>void poke(in string aValue);</tt><b></b>
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.cpp">nsSample.cpp</a></b>
+<p>This contains the implementation of nsISample.idl. SampleImpl
+inherits from nsISample.h, the header dynamically created by the xpidl
+compiler. The attribute Value has been expanded into a get and set
+and the return values have been modified to NS_IMETHOD, a success status
+for the method. The macro NS_DECL_ISUPPORTS, defined in <a href="http://lxr.mozilla.org/mozilla/source/xpcom/base/nsISupportsUtils.h">mozilla/xpcom/public/nsISupportsUtils.h</a>
+defines the inherited methods from nsISupports.h.
+<br><tt>NS_IMPL_ISUPPORTS1(SampleImpl, nsISample)</tt>
+<br>In the constructor, the macro NS_INIT_REFCNT is called which sets the
+reference count to 0.<p>
+Note that the methods in the C++ bindings use InterCaps style, while the IDL
+and JavaScript versions should use interCaps naming. The JavaScript binding
+matches the case of the IDL, <b>except</b> <a
+href="http://bugzilla.mozilla.org/show_bug.cgi?id=14460">QueryInterface</a>.
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSampleFactory.cpp">nsSampleFactory.cpp</a></b>
+<p>This is the class which builds the instance of the nsSample class.
+The COM framework uses factories to create instance of implementations
+rather than having the implementations instatiate themselves in order to
+increase portability of code. This factory inherits from nsFactory,
+which is also an XPCOM object. To gain more knowledge of factories
+see the <a href="http://www.mozilla.org/projects/xpcom/generic-factory.html">generic
+factory document</a> or the <a href="http://www.mozilla.org/docs/modunote.htm#Basics">Modularization techniques document</a>.
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.js">nsSample.js</a></b>
+<p>This file implements the nsISample interface, and associated factory glue,
+in JavaScript.
+
+<p><b>Compiling the idl</b>
+
+<p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac)
+is compiled at build time (except on Mac) thus
+you will have to build mozilla in order to test this out. If you
+have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>.
+
+<p>Once you have the XPIDL compiler enter the following command at your
+prompt:
+<br><tt>D:\mozilla\xpcom\sample>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I
+d:\mozilla\dist\idl -m header nsISample.idl</tt>
+
+<p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder
+containing the other idl files, needed because nsISample.idl inherits from
+nsISupports.idl. The <tt>-m header</tt> instruction tells the compiler
+to build the C++ header. To build the .xpt file substitute <tt>-m
+typelib</tt>.
+
+<p>
+For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl
+compiler page</a>.
+
+<p><b>Building the Sample</b>
+
+<p>To build the Sample just enter
+<br><tt>d:\mozilla\xpcom\sample>nmake /f makefile.win</tt>
+
+<p>In order to do this you need to have your environment variables set
+correctly. See the <a href="http://www.mozilla.org/build/">Build</a>
+page for more information.
+
+<p><b>Running the sample</b>
+<p>Using Mozilla, load
+<a href="resource://res/samples/xpconnect-sample.html">resource://res/samples/xpconnect-sample.html</a> (i.e. what
+you're reading now). Pay attention
+to the console when clicking "write". Notice that the value
+printed is calculated in C++ code defined in <a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsSample.cpp">nsSample.cpp</a>.
+
+<!-- XXX keep in sync with stuff in pre tag below -->
+<script>
+/* to use nsSample.js version, use "@mozilla.org/jssample;1" */
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["@mozilla.org/sample;1"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var field = document.getElementById('Value');
+ field.value = sample.value;
+}
+
+function set()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var field = document.getElementById('Value');
+ sample.value = field.value;
+}
+
+function poke()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var field = document.getElementById('Value');
+ sample.poke(field.value);
+}
+
+function sampleWrite()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ sample.writeValue("here is what I'm writing: ");
+}
+</script>
+
+<p>
+<form name="form">
+<input type="button" value="Get" onclick="get();">
+<input type="button" value="Set" onclick="set();">
+<input type="button" value="Poke" onclick="poke();">
+<input type="text" id="Value">
+<input type="button" value="Write" onclick="sampleWrite();">
+<form>
+
+<hr>
+
+<p>
+JavaScript and form source:
+
+<!-- XXX keep in sync with actual script -->
+<pre>
+&lt;script&gt;
+/* to use nsSample.js version, use "@mozilla.org/jssample;1" */
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["@mozilla.org/sample;1"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value');
+ field.value = sample.value;
+}
+
+function set()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value');
+ sample.value = field.value;
+}
+
+function poke()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value');
+ sample.poke(field.value);
+}
+
+function sampleWrite()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ sample.writeValue("here is what I'm writing: ");
+}
+&lt;/script&gt;
+
+&lt;form name=&quot;form&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Get&quot; onclick=&quot;get();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Set&quot; onclick=&quot;set();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Poke&quot; onclick=&quot;poke();&quot;&gt;
+&lt;input type=&quot;text&quot; id=&quot;Value&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Write&quot; onclick=&quot;sampleWrite();&quot;&gt;
+&lt;form>
+
+</pre>
+
+<p>
+<hr>
+<b>Resources:</b>
+<ul>
+<li><a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/">mozilla/xpcom/sample source directory</a>
+</ul>
+<hr>
+<b>Comments to:</b>
+<a href="mailto:mang@subcarrier.org?Subject=XPCOM sample documentation">Michael Ang &lt;mang@subcarrier.org&gt;</a>
diff --git a/src/libs/xpcom18a4/xpcom/string/.cvsignore b/src/libs/xpcom18a4/xpcom/string/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/string/Makefile.in b/src/libs/xpcom18a4/xpcom/string/Makefile.in
new file mode 100644
index 00000000..6a664cb9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Johnny Stenback <jst@netscape.com> (original author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = string
+DIRS = public src
+
+#ifdef ENABLE_TESTS
+#DIRS += \
+# tests
+#endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/string/README.html b/src/libs/xpcom18a4/xpcom/string/README.html
new file mode 100644
index 00000000..1fdcfdd1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/README.html
@@ -0,0 +1,44 @@
+<html>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Scott Collins <scc@mozilla.org> (original author)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+<body>
+ <h1><span class="LXRSHORTDESC">managing sequences of characters</span></h1>
+<p>
+ <span class="LXRLONGDESC"></span>
+</p>
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/string/doc/README.html b/src/libs/xpcom18a4/xpcom/string/doc/README.html
new file mode 100644
index 00000000..154b7969
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/doc/README.html
@@ -0,0 +1,44 @@
+<html>
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Scott Collins <scc@mozilla.org> (original author)
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+<body>
+ <h1><span class="LXRSHORTDESC">documentation aimed at programmers who are clients of the string library</span></h1>
+<p>
+ <span class="LXRLONGDESC"></span>
+</p>
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html b/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html
new file mode 100644
index 00000000..41dbd217
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html
@@ -0,0 +1,2508 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+ <head>
+ <title>an incomplete guide to mozilla/string</title>
+
+ <link rel="stylesheet" href="http://www.mozilla.org/projects/string/string-guide.css" title="remote stylesheet" type="text/css">
+ <link rel="alternate stylesheet" href="string-guide.css" title="local stylesheet" type="text/css">
+ </head>
+ <body>
+<!-- ----|---------|---------|---------|---------|---------|---------|---------| -->
+<!-- ...............................................................Front Matter -->
+<h1>an incomplete guide to <a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/string/">mozilla/string</a></h1>
+ <h1><font color="red">This document is now deprecated in favor of <a href="http://www.mozilla.org/projects/xpcom/string-guide.html">The new string guide</a>.</font></h1>
+<div class="author-note">
+ <p>by <a href="http://ScottCollins.net/">Scott Collins</a><!-- /p -->
+ <p>last modified 8 April 2001<!-- /p -->
+</div>
+
+<div class="abstract">
+ <p>
+ <h1>Abstract</h1>
+ This document <span class="LXRSHORTDESC">provides
+ an <a href="#users_guide">introduction</a> to the design and use of the string classes in mozilla,
+ <a href="#implementors_guide">detailed information</a> on their implementation and how one may extend them,
+ and <a href="#faq">answers</a> to frequently asked questions about strings</span>.
+ </p>
+</div>
+
+
+
+<h2><a name="contents">contents</a></h2>
+
+<div class="contents">
+ <ul>
+ <li><a href="#users_guide" >user's guide</a></li>
+ <li><a href="#implementors_guide">implementor's guide</a></li>
+ <li><a href="#faq" >frequently asked questions</a></li>
+ </ul>
+</div>
+
+<p>
+ Please direct all comments, requests, and contributions to,
+ in order of preference,
+ the tracking bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=70076">#70076</a> for this document,
+ the author <a class="exact-uri" href="mailto:scc@mozilla.org?subject=string-guide">scc@mozilla.org</a>, and/or
+ the newsgroup <a class="exact-uri" href="news:netscape.public.mozilla.xpcom">news:netscape.public.mozilla.xpcom</a>
+ (should there be a strings newsgroup?)
+</p>
+
+<div class="author-note">
+ <p>
+ A note to potential editors:
+ don't even <strong>consider</strong> modifying this document with an HTML editor.
+ That would destroy the internal formatting,
+ and make patches unmanagable.
+ </p>
+</div>
+
+
+
+
+<!-- ...............................................................User's Guide -->
+<hr>
+<h1><a name="users_guide">user's guide</a></h1>
+
+<div class="author-note">
+ <p>
+ Strings in mozilla are a world apart from <span class="code">char*</span>s.
+ If you don't know why they are different,
+ this section is the place for you to start.
+ If you're already familiar with the hierarchy of string classes in mozilla,
+ then you might want to skip ahead to the <a href="#implementors_guide">implementor's guide</a>
+ or the <a href="#faq">FAQ</a>.
+ </p>
+</div>
+
+<div class="contents">
+ <ul>
+ <li><a href="#users_guide_introduction">introduction</a></li>
+ <li><a href="#users_guide_how_to" >using the string classes correctly; using the correct string class</a></li>
+ <li><a href="#users_guide_iterators" >using string iterators</a></li>
+ <li><a href="#users_guide_summary" >summary</a></li>
+ </ul>
+</div>
+
+<h2><a name="users_guide_introduction">introduction</a></h2>
+ <h3>what and what isn't a string?</h3>
+<p>
+ A string is an opaque container holding a, possibly zero length, linear sequence of characters.
+ Understanding the implications of this statement is the foundation for understanding all mozilla's string classes.
+</p>
+
+ <h3>readable and writable</h3>
+ <h3>dependent strings</h3>
+ <h3>flat strings</h3>
+ <h3>encoding</h3>
+ <h3>sharing</h3>
+
+<h2><a name="users_guide_how_to">using the string classes correctly; using the correct string class</a></h2>
+ <h3>basic string operations</h3>
+ <h4>comparison</h4>
+ <h4>concatenation</h4>
+ <h4>substrings</h4>
+ <h4>find and replace</h4>
+ <h3>conversions</h3>
+ <h4>calling a function that expects a different kind of string</h4>
+ <h4>converting between string classes</h4>
+ <h4>converting between encodings</h4>
+ <h3>selecting the right string class</h3>
+ <h4>user string classes</h4>
+ <h4>selecting the right string class for a parameter</h4>
+ <h4>selecting the right string class for a local variable</h4>
+ <h4>selecting the right string class for a member variable</h4>
+ <h4>selecting the right string class for a return value</h4>
+ <h4>selecting the right string class in IDL</h4>
+ <h3>dont's</h3>
+
+<h2><a name="users_guide_iterators">using string iterators</a></h2>
+ <h3>what is an iterator?</h3>
+ <h3>reading iterators and writing iterators</h3>
+ <h3>`chunky' iterating for efficiency</h3>
+ <h3><span class="code">copy_string</span>, character sources and sinks</h3>
+ <h3>encoding conversion iterators</h3>
+
+<h2><a name="users_guide_summary">summary</a></h2>
+
+
+<!-- ........................................................Implementor's Guide -->
+<hr>
+<h1><a name="implementors_guide">implementor's guide</a></h1>
+
+<div class="author-note">
+ <p>
+
+ </p>
+</div>
+
+<div class="contents">
+ <ul>
+ <!-- li></li -->
+ </ul>
+</div>
+
+
+
+<!-- ........................................................................FAQ -->
+<hr>
+<h1><a name="faq">frequently asked questions</a></h1>
+
+<div class="author-note">
+</div>
+
+<div class="contents">
+ <ul>
+<!--
+ <li>
+ I have a wide string, i.e., an instance of a class derived from <span class="code">nsAString</span>
+ <ul>
+ <li>I want a pointer to the characters</span>
+ <li>I want a narrow string</li>
+ <li>I want to <span class="code">printf</span> it</li>
+ </ul>
+ </li>
+ <li>
+ I have a <span class="code">PRUnichar*</span>
+ <ul>
+ <li>I want a wide string</span>
+ <li>I want a narrow string</span>
+ <li>I want to <span class="code">printf</span> it</li>
+ </ul>
+ </li>
+ <li>
+ I have a narrow string, i.e., an instance of a class derived from <span class="code">nsACString</span>
+ <ul>
+ <li>I want a pointer to the characters</span>
+ <li>I want a narrow string</li>
+ <li>I want to <span class="code">printf</span> it</li>
+ </ul>
+ </li>
+ <li>
+ I have a <span class="code">char*</span>
+ <ul>
+ <li>I want a wide string</span>
+ <li>I want a narrow string</span>
+ </ul>
+ </li>
+ <li>
+ I have a literal character sequence, e.g., <span class="code">"Hello, World!\n"</span>
+ <ul>
+ <li>I want a wide string</span>
+ <li>I want a narrow string</span>
+ </ul>
+ </li>
+ <li>What's the best way to return a string?</li>
+ <li>How can I get a pointer to the characters in a string?</li>
+ <li>How can I <span class="code">printf</span> a string?</li>
+ </ul>
+-->
+</div>
+
+
+<table class="chart">
+ <tr>
+ <th></th>
+ <th colspan="5">you have some <span class="code">char</span>s</th>
+ </tr>
+ <tr>
+ <th>you want</th>
+ <th><span class="code">'x'</span></th>
+ <th><span class="code">char c</span></th>
+ <th><span class="code">"foo"</span></th>
+ <th><span class="code">char* cp</span></th>
+ <th><span class="code">nsACString& cs</span></th>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char</span></th>
+ <td colspan="2">.</td>
+<!-- "foo" --> <td><span class="code">[]</span></td>
+<!-- char* cp --> <td><span class="code">[]</span></td>
+<!-- nsACString& cs --> <td><a href="#faq_how_to_extract_a_character">extract a character</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar</span></th>
+<!-- 'x' --> <td><span class="code">PRUnichar('x')</span></td>
+<!-- char c --> <td><span class="code">PRUnichar(c)</span></td>
+ <td colspan="3"><a href="#faq_how_to_convert_encoding">convert encoding</a>, <a href="#faq_how_to_extract_a_character">extract a character</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char*</span></th>
+<!-- 'x' --> <td><span class="code">&amp;</span></td>
+<!-- char c --> <td><span class="code">&amp;</span></td>
+<!-- "foo" --> <td><span class="code">&amp;</span></td>
+<!-- char* cp --> <td>.</td>
+<!-- nsACString& cs --> <td><a href="#faq_how_to_get_a_pointer">get a pointer</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar*</span></th>
+ <td colspan="5"><a href="#faq_how_to_convert_encoding">convert encoding</a>, <a href="#faq_how_to_get_a_pointer">get a pointer</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsACString</span></th>
+<!-- 'x' --> <td><span class="code">NS_LITERAL_CSTRING("x")</span></td>
+<!-- char c --> <td><a href="#faq_how_to_make_a_string">make a string</a></td>
+<!-- "foo" --> <td><span class="code">NS_LITERAL_CSTRING("foo")</td>
+<!-- char* cp --> <td><a href="#faq_how_to_make_a_string">make a string</a></td>
+<!-- nsACString& cs --> <td>.</td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsAString</span></th>
+<!-- 'x' --> <td><span class="code">NS_LITERAL_STRING("x")</span></td>
+<!-- char c --> <td><a href="#faq_how_to_convert_encoding">convert encoding</a></td>
+<!-- "foo" --> <td><span class="code">NS_LITERAL_STRING("foo")</span></td>
+ <td colspan="2"><a href="#faq_how_to_convert_encoding">convert encoding</a></td>
+ </tr>
+ <tr>
+ <th class="row-label">to call <span class="code">printf</span></th>
+ <td colspan="4">.</td>
+<!-- nsACString& cs --> <td><a href="#faq_how_to_call_printf">call <span class="code">printf</span></a></td>
+ </tr>
+</table>
+
+<table class="chart">
+ <tr>
+ <th></th>
+ <th colspan="3">you have some <span class="code">PRUnichar</span>s</th>
+ </tr>
+ <tr>
+ <th>you want</th>
+ <th><span class="code">PRUnichar w</span></th>
+ <th><span class="code">PRUnichar* wp</span></th>
+ <th><span class="code">nsAString& s</span></th>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td><span class="code">[]</span></td>
+<!-- nsAString& s --> <td><a href="#faq_how_to_extract_a_character">extract a character</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char*</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar*</span></th>
+<!-- PRUnichar w --> <td><span class="code">&amp;</span></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td><a href="#faq_how_to_get_a_pointer">get a pointer</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsACString</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsAString</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label">to call <span class="code">printf</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td><a href="#faq_how_to_call_printf">call <span class="code">printf</span></a></td>
+ </tr>
+</table>
+
+<div class="faq">
+ <dl>
+ <dt>
+ is there any string doc?
+ </dt>
+ <dd>
+ Yes, you're soaking in it!
+ </dd>
+
+
+
+<!-- getting a pointer -->
+ <dt>
+ <a name="faq_how_to_get_a_pointer">I have a string, how do I get a pointer to the characters?</a>
+ </dt>
+ <dd>
+ You want to avoid this situation.
+ In your own interfaces, prefer string types over raw pointers.
+ Any interface that wants to process a string using a single pointer is making two expensive assumptions.
+ First, that the string is stored in one contiguous hunk; and
+ second, that the string is zero-terminated.
+ If this isn't the case,
+ then to get a pointer, storage must be allocated and the entire string must be copied to it and zero-terminated.
+ You may not be able to avoid needing a pointer when interacting with system calls.
+ </dd>
+ <dd>
+ Some string classes guarantee that they are `flat'.
+ That is, that their data is stored in one contiguous zero-terminated hunk.
+ This <strong>does not</strong> imply that there are no embedded nulls. Caveat emptor.
+ All strings that explicitly promise flatness
+ inherit from the class <span class="code">nsAFlatString</span>
+ or <span class="code">nsAFlatCString</span>
+ and can produce a constant pointer to their data with the <span class="code">get()</span> member function.
+ Even strings that don't explicitly promise to be flat
+ may happen to be flat.
+ The helper function <span class="code">PromiseFlatString</span> will produce
+ a <span class="code">const</span> dependent string that is guaranteed to be flat.
+ If you use this on a string that already happens to be flat,
+ the result is simply a reference through to that string.
+ Otherwise,
+ <span class="code">PromiseFlatString</span> does the work to allocate, copy, terminate, and manage
+ a temporary flat string.
+ Since the result of <span class="code">PromiseFlatString</span> is a temporary,
+ you must be careful not to get and hold a pointer to its data for longer than the temporary itself lives.
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* I have a string, how do I get a pointer to the characters? */
+
+extern void EvilNarrowOSFunction( const char* ); // evil OS routines that want a pointers
+extern void EvilWideOSFunction( const PRUnichar* );
+
+void func( const nsAString&amp; aString, const nsACString&amp; aCString )
+ {
+ EvilWideOSFunction( NS_LITERAL_STRING("Hello, World!").<span class="notice">get()</span> );
+ // literal strings are flat already (as are |nsString|s, et al), just use |.get()|
+
+ EvilWideOSFunction( <span class="notice">PromiseFlatString(</span>aString<span class="notice">).get()</span> );
+ // for strings that don't explicitly guarantee flatness, use |PromiseFlatString|
+
+
+ // beware holding the pointer for longer than the life of the promise
+ <span class="warning">const PRUnichar* wp = PromiseFlatString(aString).get(); // BAD! |wp| dangles
+ EvilWideOSFunction(wp);</span>
+
+ // if you really need to use the pointer from |PromiseFlatString| in more than one expression...
+ const nsAFlatString&amp; flat = <span class="notice">PromiseFlatString(</span>aString<span class="notice">)</span>;
+ EvilWideOSFunction(flat.<span class="notice">get()</span>);
+ SomeOtherFunction(flat.<span class="notice">get()</span>);
+
+ // similarly for |char| strings
+ EvilNarrowOSFunction( <span class="notice">PromiseFlatCString(</span>aCString<span class="notice">).get()</span> );
+ }
+</pre>
+</div>
+ </dd>
+
+
+
+<!-- extracting a character -->
+ <dt>
+ <a name="faq_how_to_extract_a_character">How do I get a particular character out of a string?</a>
+ </dt>
+ <dd>
+ Flat strings provide <span class="code">operator[]</span> and <span class="code">CharAt()</span>.
+ All strings provide <span class="code">First()</span>, <span class="code">Last()</span>, and access with iterators.
+ <strong>Don't</strong> promise a string flat just to do character indexing.
+ Prefer, instead, to get an iterator and <span class="code">advance</span> it to the position you care about.
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* How do I get a particular character out of a string? */
+
+PRUnichar Get5thCharacterOf( const nsAString& aString )
+ {
+ if ( aString.Length() >= 5 )
+ {
+ nsAString::const_iterator iter;
+ aString.BeginReading(iter); // make |iter| point to the beginning of |aString|
+ iter.advance(5);
+ return *iter;
+ }
+
+ return PRUnichar(0);
+ }
+</pre>
+</div>
+ </dd>
+ <dd>
+ Using iterators isn't as bad as the example above makes it feel.
+ The typical use is for advancing through a string, examining many characters.
+ </dd>
+
+
+
+<!-- how to convert encoding -->
+ <dt>
+ <a name="faq_how_to_convert_encoding">How do I convert from one encoding to another?</a>
+ </dt>
+ <dd>
+ </dd>
+
+
+
+<!-- how to make a string -->
+ <dt>
+ <a name="faq_how_to_make_a_string">How do I create a string?</a>
+ </dt>
+ <dd>
+ </dd>
+
+
+<!-- how to return a string -->
+ <dt>
+ What is the best way to return a string?
+ </dt>
+ <dd>
+ <p>
+ There are several reasonable ways to produce a string result from a function.
+ If you are already holding the answer as a sharable string,
+ you can simply return that string (pass-by-value).
+ Otherwise,
+ the most efficient and flexible way to return a string is
+ to assign your result into a non-<span class="code">const</span> reference parameter.
+ Don't bother to create a sharable string from scratch with your generated result.
+ </p>
+ <p>
+ Why?
+ The two things you want to minimize in string manipulation are,
+ in order of importance,
+ heap allocation, and
+ moving characters around.
+ </p>
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* What is the best way to return a string? */
+
+class foo
+ {
+ public:
+ // ...
+ void GetShortName( nsAString&amp; aResult ) const;
+ nsCommonString GetFullName() const;
+
+ private:
+ nsCommonString mFullName;
+
+ const PRUnichar* mShortName;
+ PRUint32 mShortNameLength;
+
+ };
+
+nsCommonString
+foo::GetFullName() const
+ {
+ return mFullName;
+ }
+
+void
+foo::GetShortName( nsAString&amp; aResult ) const
+ {
+ aResult = DependentString(mShortName, mShortNameLength);
+ }
+</pre>
+</div>
+ </dd>
+
+
+ <dt>
+ <a name="faq_how_to_call_printf">How do I <span class="code">printf</span> a string, e.g., for debugging.</a>
+ </dt>
+ <dd>
+ If your string is already narrow, you just have to worry about <a href="#faq_how_to_get_a_pointer">making it flat, and then getting a pointer</a>.
+ </dd>
+ <dd>
+ If your string happens to be wide,
+ you'll need to convert it before you can <span class="code">printf</span> something reasonable.
+ If it's just for debugging,
+ you probably wouldn't care if something odd was printed in the case of a Unicode character that didn't have
+ an ASCII equivalent. (If you have a UTF-8 terminal, the result is
+ perfectly legible and nothing odd is printed.)
+ The simplest thing in this case is to make a temporary conversion using <span class="code">NS_ConvertUTF16toUTF8</span>.
+ The result is conveniently flat already, so getting the pointer is simple.
+ Remember not to hold onto the pointer you get out of this beyond the lifetime of temporary.
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* How do I |printf| a string? */
+
+
+void PrintSomeStrings( const nsAString& aString, const PRUnichar* aKey, const nsACString& aCString )
+ {
+ // |printf|ing a narrow string is easy
+ printf("%s\n", <span class="notice">PromiseFlatCString(</span>aCString<span class="notice">).get()</span>); // GOOD
+
+ // the simplest way to get a |printf|-able |const char*| out of a string
+ printf("%s\n", <span class="notice">NS_ConvertUTF16toUTF8(</span>aKey<span class="notice">).get()</span>); // GOOD
+
+ // works just as well with an formal wide string type...
+ printf("%s\n", <span class="notice">NS_ConvertUTF16toUTF8(</span>aString<span class="notice">).get()</span>);
+
+
+ // But don't hold onto the pointer longer than the lifetime of the temporary!
+ <span class="warning">const char* cstring = NS_ConvertUTF16toUTF8(aKey).get(); // BAD! |cstring| is dangling
+ printf("%s\n", cstring);</span>
+ }
+</pre>
+</div>
+ </dd>
+
+ </dl>
+
+<p>
+ Here are the email answers I have yet to format into the FAQ.
+ Some of the URLs may be out-dated or moved.
+ The messages are in order from oldest to newest.
+</p>
+<p class="editnote">[Note : In June, 2003, these emails were modified
+to better reflect what is stored in 'wide' string
+classes (UTF-16 string instead of UCS-2) and what
+related methods do as a part of the patch for <a href=
+"http://bugzilla.mozilla.org/show_bug.cgi?id=183156"
+title="replace UCS2 in function/class/method names with UTF16">bug 183156</a>.
+Therefore, they're a little different from the original emails
+written by <a href="http://ScottCollins.net/">Scott Collins</a>]
+</p>
+<hr>
+<pre>
+Date: Thu, 13 Apr 2000 19:41:47 -0400
+</pre>
+
+<p>Encoding Wars
+
+<p>This message is all about strings and the various encodings that might
+be used to interpret their contents, the ramifications of that, and
+where we're heading. The point of this message is to say what we're
+currently thinking, and get feedback. I apologize in advance for the
+rambling, and for the fact that this message may accidentally mix
+discussion of how things <strong>are</strong> and how they will be.
+
+<p>There are many different possible encodings. Three in common use in
+the Mozilla source base are: ASCII, UTF-16, and UTF-8. In ASCII, every
+<!--the Mozilla source base are: ASCII, UCS2, and UTF8. In ASCII, every-->
+character fits in 7-bits and is typically stored in an 8-bit byte. We
+usually represent ASCII strings with <span class="code">nsCString</span>s, <span class="code">nsXPIDLCString</span>s,
+or <span class="code">char</span> string literals. In UTF-16, characters occupy one 16-bit code unit (
+<a href="http://www.unicode.org/glossary/index.html#BMP_character">
+<abbr title="Basic Multilingual Plane">BMP</abbr>characters</a>)
+or two 16-bit code units
+(<a href="http://www.unicode.org/glossary/index.html#supplementary_character">
+<abbr title="Supplementary Plane : Plane 1 through 16">non-BMP</abbr> characters</a>).
+We usually represent UTF-16 strings as <span class="code">nsString</span>s, etc., i.e., two-byte
+or `wide' strings. UTF-8 is a multi-byte encoding. A character might
+occupy one, two, three, or four bytes. It is easiest to store and
+manipulate such a string within a single-byte or `narrow' string
+implementation.
+
+<p>None of our current string implementations know the encoding of the
+data they hold at any given moment. An <span class="code">nsCString</span> might legitimately
+hold data encoded in ASCII, UTF-8 or even EBCDIC for that matter.
+
+<p>Operations that convert from one encoding to another, or operations
+that are encoding sensitive (e.g., <span class="code">to_upper</span>), rightly belong in
+i18n. The fact that our current string interfaces automatically and
+implicitly convert between wide and narrow strings is actually the
+source of many errors in two particular categories: (1) unintended
+extra work, (2) mistaken re-encoding, e.g., accidentally `converting'
+a UTF-8 string to UTF-16 by pretending the UTF-8 string is ASCII and then
+padding with <span class="code">'\0'</span>s.
+
+<p>We've known these were bad for a long time, and have been trying to
+find the right way to fix them. The current thinking is to just byte
+the bullet and eliminate implicit conversions. That has interesting
+ramifications.
+
+<div class="source-code">
+<pre>
+void foo( const nsString&amp; aUTF16string );
+
+foo("hello"); // works! constructs a temporary |nsString| by
+ // converting the ASCII literal with padding.
+ // Note: this requires an allocation
+</pre>
+</div>
+
+<p>Though we've always hated this form since it requires a heap
+allocation. In current code, we recommend
+
+<div class="source-code">
+<pre>
+foo( nsAutoString("hello") );
+</pre>
+</div>
+
+<p>which still copy/converts, but at least it probably doesn't need to do
+a heap allocation. In the best of all worlds, no conversion, copying,
+or allocation would be necessary. To do that, you would need to be
+able to directly specify a UTF-16 string, e.g., with the <span class="code">L"hello"</span>
+notation, and wrap that in an interface that just held a pointer.
+E.g., something like
+
+<div class="source-code">
+<pre>
+void foo( const nsAReadableString&amp; aUTF16string );
+
+foo( nsLiteralString(L"hello") );
+</pre>
+</div>
+
+<p>There are problems with this example, however. The <span class="code">L</span> notation
+specifically makes objects that are arrays of <span class="code">wchar_t</span>, which under
+GCC is a 4-byte element. This leads to incompatibility with JS, and
+the annoyance of possibly bloated storage (I'm sort of minimizing the
+situation here. It's worse that I make it sound). More about tricks
+to get around this in a bit, but first, let me talk about what to do
+in the meantime while we're just getting rid of implicit constructors.
+ Initially to get around this problem (what problem? The problem that
+<span class="code">foo("hello")</span> stopped compiling on my machine when I threw the
+switch) I made a routine called <span class="code">NS_ConvertToString</span> which looked like
+this
+
+<div class="source-code">
+<pre>
+inline
+nsAutoString
+NS_ConvertToString( const char* anASCIIstring )
+ {
+ nsAutoString aUCS2string;
+ aUCS2string.AssignWithConversion(anASCIIstring);
+ return aUCS2string;
+ }
+</pre>
+</div>
+
+<p>Which lets me write
+
+<div class="source-code">
+<pre>
+foo( NS_ConvertToString("hello") );
+</pre>
+</div>
+
+<p>This was <strong>OK</strong>, but in discussion there were concerns about performance
+on machines that didn't <span class="code">inline</span> well, and issues about naming. In
+that meeting we came up with an alternate naming strategy that we
+think has room for growth and an implementation more likely to be
+efficient on every platform. The implementation is to define a new
+class that derives from <span class="code">nsAutoString</span>, but allows construction from a
+<span class="code">char*</span>
+
+<div class="source-code">
+<pre>
+class NS_ConvertASCIItoUTF16 : public nsAutoString
+ {
+ public:
+ NS_ConvertASCIItoUTF16( const char* );
+ // ...
+ };
+</pre>
+</div>
+
+<p>Which gives identical (though renamed) notation for calling <span class="code">foo</span>:
+
+<div class="source-code">
+<pre>
+foo( NS_ConvertASCIItoUTF16("hello") );
+</pre>
+</div>
+
+<p>It looks like a function call to an explicit encoding conversion. It
+acts like a function call to an explicit encoding conversion. It <strong>is</strong>
+a function call to an explicit encoding conversion. We think that
+this naming pattern has room for growth. In the meeting, we concluded
+that the best representation for encoding conversions is a family of
+functions, and <span class="code">NS_ConvertASCIItoUTF16</span> fits right in. We think that
+XPCOM probably can't live without the ASCII to UTF-16 conversion (though
+as explicit as possible) but that all others rightly belong in i18n
+land.
+
+<p>You can probably deduce from the clues in <span class="code">NS_ConvertToString</span>, above,
+that constructors weren't the only thing that became explicit.
+Assignment, appending, comparison, et al, got renamed so that when
+assigning, appending, or comparing to a value in a different encoding
+the `WithConversion' form must be used. E.g.,
+
+<div class="source-code">
+<pre>
+nsString aUTF16string;
+nsCString anASCIIstring;
+// ...
+
+aUTF16string += anASCIIstring; // Currently legal, but not for long
+aUTF16string.Append(anASCIIstring); // same
+
+aUTF16string.AppendWithConversion(anASCIIstring); // the new way
+
+if ( aUTF16string == anASCIIstring ) // Sorry, this is going away too
+ // ...
+
+if ( aUTF16string.EqualsWithConversion(anASCIIstring) )
+ // ...
+</pre>
+</div>
+
+<p>Yes, it's long and annoying. Just like the extra work you were
+implicitly asking to have done, perhaps incorrectly. There are other
+reasons to rename these functions. When <span class="code">nsString</span> and <span class="code">nsCString</span>
+defined a ton of, e.g., <span class="code">Append</span>s each there was no problem, because
+nobody wanted to override <span class="code">Append</span>. Now, with strings inheriting from
+abstract base classes we immediately run into the problem that
+overriding and overloading don't mix very well in C++. Because of a
+feature of C++ called name hiding, it is problematic to override only
+a single signature of a name overloaded in a base class. The base
+<span class="code">nsAWritableString</span> provides several <span class="code">Append</span>s, all for objects of
+(hopefully) the same encoding. <span class="code">nsString</span> can't easily add a bunch of
+new <span class="code">Append</span>s (the converting ones) without running face first into
+the name hiding problem. The discussion of the fix for this is mostly
+unrelated to encoding issues, so I'll defer it to another post.
+
+<p>In hindsight, after the meeting, it seemed clear that all the
+`WithConversion' forms would be better named
+
+<div class="source-code">
+<pre>
+xxxConvertingASCIItoUTF16
+xxxConvertingUTF16toASCII
+</pre>
+</div>
+
+<p>however, the <strong>real</strong> goal (probably) is to move most such conversions
+into i18n. Just bringing attention to the previously implicit
+conversions is a good first step. Renaming these conversions as just
+suggested is probably the right thing to do, though it sort of
+validates them, which I'm not sure we really want. This is a decision
+we need to discuss further.
+
+<p>Now, back to the string literal problem above. One possible solution
+is to use a macro. Imagine
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("Hello")
+</pre>
+</div>
+
+<p>which on a machine where the <span class="code">L</span> trick works, turns into
+
+<div class="source-code">
+<pre>
+nsLiteralString(L"Hello")
+</pre>
+</div>
+
+<p>but on a machine where there is trouble, turns into something less
+appealing, but more likely to work, like
+
+<div class="source-code">
+<pre>
+NS_ConvertASCIItoUTF16("Hello")
+</pre>
+</div>
+
+<p>Another solution is to add a compilation step that fixes <span class="code">L</span> strings
+on bad platforms to be non-<span class="code">L</span> strings, but padded with <span class="code">\0</span>s. E.g.,
+<span class="code">L"Hello"</span> gets preprocessed into <span class="code">"\000H\000e\000l\000l\000o\000"</span>.
+This solution is more annoying to the developer, where the prior
+solution is more annoying during the runtime.
+
+<p>Before we go to too much trouble on this specific feature, we will
+probably want to do more measurement to see just how much and how
+often we are converting constant literal strings, and why.
+
+
+<p>I'm currently ripping through the tree fixing things to use the
+`WithConversion' forms where appropriate. I was also converting
+things to use <span class="code">NS_ConvertToString</span> where appropriate; unless I get
+talked out of it, I want to switch midstream to
+<span class="code">NS_ConvertASCIItoUTF16</span>, then go back and fix up the
+<span class="code">NS_ConvertToString</span> instances later. I've set things up so I can
+check in as I go. After all these conversions have been done, I'll be
+able to throw the switch (what switch? NEW_STRING_APIS) which will
+make <span class="code">nsString</span> inherit from <span class="code">nsAWritableString</span>, etc. and allow us to
+start exploiting these other opportunities (e.g., for literal strings,
+shared strings, etc. See
+<a class="exact-uri" href="http://bugzilla.mozilla.org/show_bug.cgi?id=28221">http://bugzilla.mozilla.org/show_bug.cgi?id=28221</a> for details and
+reasoning.)
+
+<p>I guess I'm expecting comments on:
+
+<ul>
+ <li>how really annoying this whole topic is
+ <li>how bad <span class="code">L"xxx"</span> is
+ <li>whether to move forward with <span class="code">NS_ConvertASCIItoUTF16</span>
+ <li>whether we should move to xxxConvertingASCIItoUTF16 etc instead
+ of `WithConverting'
+ <li>arguments about where encoding conversions should live
+ <li>arguments about whether going between 1 and 2 byte storage is an
+ encoding conversion
+ <li>questions about stuff I didn't mention or didn't explain well
+ <li>pointing out stuff I'm just plain wrong about, or things I forgot
+ <li>etc
+</ul>
+
+<p>So as not to jumble the discussion, I'll be separately posting other
+requests for comments about specific features of the design of the new
+string hierarchy.
+
+<p>I hope this helps keep everybody filled in on what we're thinking and
+able to point out what we're forgetting or screwing up :-)
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 19 Apr 2000 21:12:47 -0400
+Subject: more string info
+</pre>
+
+<p> <a class="exact-uri" href="news://news.mozilla.org/scc-705460.16423913042000@news.mozilla.org">news://news.mozilla.org/scc-705460.16423913042000@news.mozilla.org</a>
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 26 May 2000 15:31:37 -0400
+Subject: Re: Question on ==
+</pre>
+
+<p>I would prefer you compare with <span class="code">Equals</span> (which should really be named
+<span class="code">IsEqualTo</span>) rather than <span class="code">operator==()</span> because of this:
+
+<div class="source-code">
+<pre>
+char* a;
+char* b;
+
+// ...
+
+if ( a == b )
+ // ...
+</pre>
+</div>
+
+<p>Comparing two raw `string' pointers doesn't compare the characters
+they point to, but instead compares the bits of the pointers. For
+this reason, I may eventually make comparison of a string with a
+pointer using operators just go away.
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 14 Jun 2000 14:38:55 -0400
+Subject: Re: Fix to XprtDefs.h
+</pre>
+
+<p>Yes, we're aware that turning off <span class="code">wchar_t</span> support makes <span class="code">wchar_t</span> be
+a synonym for <span class="code">unsigned short</span> under Metrowerks. We know that the
+current version of VC++ also makes these types equivalent. In theory,
+though, the types are distinct even when they are the same size and
+shape. By using real <span class="code">wchar_t</span> support, we are forced to recognize
+the distinction and navigate it appropriately with <span class="code">reinterpret_cast</span>
+(via <span class="code">NS_REINTERPRET_CAST</span>). The win here is that we aren't caught by
+compiler changes that suddenly make some set of compilers compliant
+and therefore break our code. We will add an autoconf test that lets
+UNIX compilers opt in to our string scheme when they have an
+appropriately shaped <span class="code">wchar_t</span>. If these happen to be compliant
+compilers, all will be well. If they don't, the casts don't hurt,
+because they are type correct. We are writing our code to meet the
+standard as we move forward.
+
+<p>The win for us is realized by the following macros
+
+<div class="source-code">
+<pre>
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ #define NS_LITERAL_STRING(s) nsLiteralString(L##s, \
+ (sizeof(L##s)/sizeof(wchar_t))-1)
+#else
+ #define NS_LITERAL_STRING(s) NS_ConvertASCIItoUTF16(s, \
+ sizeof(s)-1)
+#endif
+</pre>
+</div>
+
+<p>An <span class="code">nsLiteralString</span> points directly to the literal characters. No
+copying, no conversion, and the length calculation happens at compile
+time. This has turned out to be as large a savings as 15% of code
+space and 8% of data space, net, in our string test harness It's
+faster as well, again by eliminating the copying, conversion, and
+length calculation. We don't know yet what those numbers translate
+into in our real code base, but we have high hopes.
+
+<p>I don't want to be in the position to ask you to change your code. I
+don't think it's appropriate for me to do so. The AIM application
+that is your client is our client as well. They need to resolve this
+difference between us in whatever way they think best. That may mean
+asking you if changing your apis is the right thing to do. Or it may
+mean applying the casts. Our code-base and yours, Justin, are more
+like cousins. I don't think you should have to change just to conform
+to us. You may think my arguments for using real <span class="code">wchar_t</span> have
+merit, and adopt similar usage just because you agree; but I think the
+only obligation you have is to follow the technical solution you think
+is right for your code.
+
+<p>If you decide to make this api change, it will mean shipping a new
+binary (on Mac) for your library to clients who want to switch over to
+the new api (since the name mangling will be different, and therefore,
+the link requirements will change).
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 15 Jun 2000 19:36:55 -0400
+Subject: Re: Checkin approval for bug 32336
+</pre>
+
+<div class="source-code">
+<pre>
+S.Equals(NS_LITERAL_STRING("bar"), PR_TRUE, 3)
+</pre>
+</div>
+
+<p>doesn't compile because there is no three parameter form for <span class="code">Equals</span>.
+ For all definitions of <span class="code">Equals</span> on strings, see "nsAReadableString.h"
+
+<p><a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a>
+
+<p>There is an <span class="code">EqualsWithConversion</span> that takes three parameters.
+
+<p> <a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsString2.h#731">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsString2.h#731</a>
+
+<p>It is ``EqualsWithConversion'' because it admits the possibility of an
+encoding specific transformation, in this case to provide
+case-insensitive comparison. This also wouldn't compile, however,
+since, at the moment, an <span class="code">nsLiteralString</span> doesn't provide an operator
+to produce a <span class="code">const PRUnichar*</span> (though perhaps it should), and it
+doesn't satisfy the other interfaces that match this call, e.g., a
+<span class="code">const nsString&</span>.
+
+<p>Perhaps I need to move case-insensitive comparison up out of
+<span class="code">nsString</span> into a global encoding specific transformations and
+algorithms file (which was on its way anyway as Waterson, knows); this
+use is one bit of evidence to support this. In the short term, this
+can be fixed (if we think the current behavior is wrong) by providing
+<span class="code">operator const CharT*() const</span> on literal string.
+
+<p>If you can live with out case-folding, the earlier form is preferred
+
+<div class="source-code">
+<pre>
+S == NS_LITERAL_STRING("bar")
+</pre>
+</div>
+
+<p>if you can't, then one of the fixes I mentioned is in order.
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 15 Jun 2000 19:47:12 -0400
+Subject: Re: [Fwd: how to use nsString ?]
+</pre>
+
+<pre class="email-quote">
+ >I see these same examples time and again in the embedding
+ >samples/docs, but I can't compile them.
+</pre>
+
+<p>Apologies. Documentation mentioning strings is getting out of date.
+Here are some specific answers.
+
+
+<pre class="email-quote">
+ >nsString URLString("http://www.mozilla.org");
+</pre>
+
+<p>...is now perhaps best expressed as
+
+ nsString URLString( NS_LITERAL_STRING("http://www.mozilla.org") );
+
+<p>since an <span class="code">nsString</span> is a sequence of 2-byte wide characters, and the
+routines that implicitly convert 1-byte sequences (like the literal
+sequence you specified, "http:...") are now gone.
+
+<p>Up until not too long ago, one would have had to say
+
+<div class="source-code">
+<pre>
+nsString URLString;
+URLString.AssignWithConversion("http://www.mozilla.org");
+</pre>
+</div>
+
+<p>The <span class="code">NS_LITERAL_STRING</span> construction is new machinery that has the
+potential to make many operations much more efficient.
+
+<pre class="email-quote">
+ >nsString URLString;
+ >URLString.SetString("www.mozilla.org");
+</pre>
+
+<p><span class="code">SetString</span> was a synonym for <span class="code">Assign</span> or assignment with
+<span class="code">operator=()</span>, it too went away. The equivalent is the second
+example I gave above, that is, the one with <span class="code">AssignWithConversion</span>.
+
+<p><span class="code">Assign</span> still exists. <span class="code">AssignWithConversion</span> takes on that
+functionality for assignments that require encoding transformations
+(e.g., from ASCII to UTF16). <span class="code">SetString</span> is gone, since it was always
+a synonym for <span class="code">Assign</span>.
+
+<p>Learn more about the general APIs for strings that we are trying to
+move to by examining
+
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a>
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h</a>
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 15 Jun 2000 21:26:51 -0400
+Subject: Re: Checkin approval for bug 32336
+</pre>
+
+<pre class="email-quote">
+ >I *need* the count attribute, because I need to compare only the first
+ >chars (that's inherent to the logic).
+</pre>
+
+<p>This is what substrings are for. In that case, you could use
+
+<div class="source-code">
+<pre>
+Substring(S, 0, 3) == NS_LITERAL_STRING("bar")
+</pre>
+</div>
+
+<p>As for case-folding, it's best if you can case-fold everything up
+front, instead of doing it repeatedly. I'll have to get back to you
+on a general solution to that problem, or what my schedule for getting
+it checked in would be. I'm sorry, I know that's not what you needed
+to hear. If the source string is an <span class="code">nsString</span>, you can continue to
+exploit its implementation of these routines, e.g., <span class="code">ToLower</span> all
+up-front.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Mon, 19 Jun 2000 14:23:47 -0400
+Subject: Re: string fu
+</pre>
+
+<pre class="email-quote">
+ >It seems less convenient to have to first check path.IsEmpty, and
+ >then if false get path.Last and test it.
+</pre>
+
+<p>What would you prefer? That extracting a character not in the string
+always return <span class="code">CharT(0)</span>? Can't do it for two reasons: (1) <span class="code">0</span> may be
+a valid character in a particular encoding, so it can't be used in
+general as a ``no character at that position'' marker; and (2) I can't
+control what an individual string implementation does when asked to
+get an out-of-bounds fragment, it's explicitly undefined. That means
+the result of <span class="code">CharAt</span> is explicitly undefined for indexes outside the
+defined contents of the string. As a debugging convenience, I have
+made this assert, but it has always been the case that retrieving such
+a character had undefined results ... even in [the old] code.
+
+<p>OK, you might say, well at least let me ask for a character that is
+only off the end by one. E.g., <span class="code">Last</span> of an empty string. Reason (1)
+from above still applies. How bad is it to say, for the case you gave
+
+<div class="source-code">
+<pre>
+PRBool needsDelim = PR_FALSE;
+if ( !path.IsEmpty() )
+ {
+ PRUnichar last = path.Last();
+ needsDelim = !(last == '/' || last == '\\');
+ }
+</pre>
+</div>
+
+<p>In general, you probably want to opt out of a whole lot of work when
+the source string is empty. It is slightly less convenient, but it
+doesn't tie us to a bunch of implementation specific mojo.
+
+
+<pre class="email-quote">
+ >Can we fix GetUnicode in this case?
+</pre>
+
+<p>This is an annoying property of auto strings, e.g., that they always
+have an allocated buffer. I'm happy to fix this bug, however, be
+aware that <span class="code">GetUnicode</span> and <span class="code">GetBuffer</span> are artifacts of [the old]
+implementation that we don't want to support. They are not part of
+the abstract interface. We will keep them no longer than we have to.
+They don't support our multi-fragment paradigm. People who require a
+contiguous hunk of characters in the future, and are unwilling to
+switch over to chunky-iterators, may be forced to copy the string to
+their own buffer. There will be an implementation of narrow character
+string that guarantees contiguous allocation and a zero-terminator,
+much as <span class="code">nsCString</span> does now, for compatibility with platform uses,
+but this won't be the default string class.
+
+
+
+
+
+<hr>
+<pre>
+Date: Mon, 19 Jun 2000 17:22:31 -0400
+</pre>
+
+<p>Clarifying String Sematics
+
+<p>Recently, I added an assert to the string operations that extract
+characters, namely <span class="code">First()</span>, <span class="code">Last()</span>, <span class="code">CharAt()</span>, and
+<span class="code">operator[]()</span>. This assert fires when any of these routines are used
+to access a character outside the defined contents of the string. For
+<span class="code">First()</span> and <span class="code">Last()</span> that means whenever they are applied to an
+empty string. For <span class="code">CharAt()</span> and <span class="code">operator[]()</span>, that means whenever
+they are used to access an index outside the range of
+<span class="code">0</span>..<span class="code">Length()-1</span>. There have been some complaints, however, the
+result was always undefined. What follows is extracted from an email
+exchange between me and warren on this topic. I hope it clarifies
+strings semantics
+
+<p>Warren writes:
+<pre class="email-quote">
+ >I hit your funky CharAt assertion tonight in this piece of code:
+
+ >NS_IMETHODIMP
+ >nsIOService::ResolveRelativePath(
+ > const char *relativePath,
+ > const char* basePath,
+ > char **result )
+ > {
+ > nsCAutoString name;
+ > nsCAutoString path(basePath);
+ >
+ > PRUnichar last = path.Last();
+ > PRBool needsDelim = !(last == '/' || last == '\\' || last ==
+ > '\0');
+ > ...
+
+ >where basePath is null. It seems less convenient to have to first
+ >check path.IsEmpty, and then if false get path.Last and test it.
+</pre>
+
+<p>I replied:
+<pre class="email-quote">
+ >What would you prefer? That extracting a character not in the
+ >string always return <span class="code">CharT(0)</span>? Can't do it for two reasons:
+ >(1) <span class="code">0</span> may be a valid character in a particular encoding, so it
+ >can't be used in general as a ``no character at that position''
+ >marker; and (2) I can't control what an individual string
+ >implementation does when asked to get an out-of-bounds fragment,
+ >it's explicitly undefined. That means the result of <span class="code">CharAt</span> is
+ >explicitly undefined for indexes outside the defined contents of
+ >the string. As a debugging convenience, I have made this assert,
+ >but it has always been the case that retrieving such a character
+ >had undefined results ... even in [the old] code.
+
+ >OK, you might say, well at least let me ask for a character that
+ >is only off the end by one. E.g., <span class="code">Last</span> of an empty string.
+ >Reason (1) from above still applies. How bad is it to say, for the
+ >case you gave
+
+ > PRBool needsDelim = PR_FALSE;
+ > if ( !path.IsEmpty() )
+ > {
+ > PRUnichar last = path.Last();
+ > needsDelim = !(last == '/' || last == '\\');
+ > }
+
+ >In general, you probably want to opt out of a whole lot of work
+ >when the source string is empty. It is slightly less convenient,
+ >but it doesn't tie us to a bunch of implementation specific mojo.
+</pre>
+
+<p>Warren also asks:
+<pre class="email-quote">
+ >Here's another issue, perhaps more serious. If I say this:
+
+ > foo(const PRUnichar* s) {
+ > nsAutoString str(s);
+ > bar(str.get());
+ > }
+
+ >where s is null, bar will get passed a zero-length PRUnichar
+ >sequence instead of null. This makes it so that you can't just
+ >test for the argument == null. You have to nsCRT::strlen(arg) == 0
+ >which is much less efficient. Can we fix GetUnicode in this case?
+</pre>
+
+<p>And I reply:
+<pre class="email-quote">
+ >This is an annoying property of auto strings, e.g., that they
+ >always have an allocated buffer. I'm happy to fix this bug,
+ >however, be aware that <span class="code">GetUnicode</span> and <span class="code">GetBuffer</span> are artifacts
+ >of [the old] implementation that we don't want to support. They
+ >are not part of the abstract interface. We will keep them no
+ >longer than we have to. They don't support our multi-fragment
+ >paradigm. People who require a contiguous hunk of characters in
+ >the future, and are unwilling to switch over to chunky-iterators,
+ >may be forced to copy the string to their own buffer. There will
+ >be an implementation of narrow character string that guarantees
+ >contiguous allocation and a zero-terminator, much as <span class="code">nsCString</span>
+ >does now, for compatibility with platform uses, but this won't be
+ >the default string class.
+</pre>
+
+<p>In a later message, Chris Waterson asks a related question
+<pre class="email-quote">
+ >scc: should we add <span class="code">operator PRUnichar*()</span> to
+ >NS_ConvertASCIItoUTF16?
+</pre>
+
+<p>And I reply:
+<pre class="email-quote">
+ >It seems reasonable. A lot more reasonable that forcing people to
+ >call <span class="code">GetUnicode()</span>. I alluded to platform specific classes in an
+ >earlier message to warren that you were cc'd on, Chris. I imagine
+ >that the <span class="code">...Convert...</span> routines would be required to produce
+ >contiguous allocation 0-terminated strings (though the as yet
+ >unimplemented <span class="code">...Copy...</span> forms, of course wouldn't. So <span class="code">operator
+ >const PRUnichar*() const</span> makes perfect sense to me here.
+</pre>
+
+<p>Hope this makes sense,
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 20 Jun 2000 04:05:31 -0400
+Subject: Re: NS_LITERAL_STRING is broken
+</pre>
+
+<p>The behavior you describe sounds exactly like when you say
+
+<div class="source-code">
+<pre>
+const char* foobar = "foobar";
+
+... NS_LITERAL_STRING(foobar).get() ...
+</pre>
+</div>
+
+<p>because in this case, the thing passed in is a <span class="code">const char*</span>.
+<span class="code">NS_LITERAL_STRING</span> is not meant to be used in this way. It is only
+meant to be used around a <span class="code">"</span> delimited string. The type of such is
+<span class="code">const char[N]</span> where N is the number of characters in the string + 1
+for the zero terminator it helpfully adds. <span class="code">sizeof</span> such a type is
+<span class="code">N</span>.
+
+<p>Are you sure you had the actual string as an argument, as in your
+example to me? Or could the actual code have been like my sample,
+above?
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 29 Jun 2000 13:35:10 -0400
+Subject: Re: a fix
+</pre>
+
+<pre class="email-quote">
+ > + if (Length() == 0) { return nsnull; }
+</pre>
+
+
+<p>Dave,
+
+<p>please read
+
+ <a class="exact-uri" href="news://news.mozilla.org/scc-314ABF.14261619062000@news.mozilla.org">news://news.mozilla.org/scc-314ABF.14261619062000@news.mozilla.org</a>
+
+<p>It's just plain wrong to let people try to index into a string outside
+its defined contents. I can't just return <span class="code">'\0'</span> or <span class="code">PRUnichar('\0')</span>
+there as that <strong>could</strong> be a legal value to have somewhere in your
+string for some encodings ... and the encoding is not specified. So
+your patch has the basic problem of defeating my plan to stop people
+from doing this bad thing.
+
+<p>The second problem with your patch is that you use the symbolic
+constant <span class="code">nsnull</span>, which is ostensibly a pointer value; <span class="code">Last</span> returns
+a character. <span class="code">nsnull</span> is not appropriate for that purpose. In fact,
+C++ gurus pretty much eschew the use of symbolic constants for <span class="code">0</span>.
+<span class="code">NULL</span> is to be avoided. <span class="code">nsnull</span> is wrong-headed in that it presumes
+we could have some <strong>other</strong> application specific value for <span class="code">NULL</span>. We
+can't, it would never work. It's just wasted brain-print. Always use
+<span class="code">0</span> for these situations, and if you want to communicate the fact that
+something is a pointer type, either use a comment or a
+(construction-style) cast, like so (graded examples from worst to
+best:)
+
+<ul>
+ <li>F: FindChildByNameWithHint("Chuck", nsnull);
+
+ <li>D: FindChildByNameWithHint("Chuck", NULL);
+
+ <li>C: FindChildByNameWithHint("Chuck", /* Child* */ 0);
+
+ <li>B: typedef Child* Child_ptr;
+ FindChildByNameWithHint("Chuck", Child_ptr(0));
+
+ <li>A: FindChildByNameWithHint("Chuck", 0);
+</ul>
+
+<p>Don't let this discourage you; keep up the good work :-)
+
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 8 Aug 2000 23:47:16 -0400
+Subject: Re: nsWritingIterator?
+</pre>
+
+<pre class="email-quote">
+ >Can you give me any pointers to examples, or docs, or just some
+ >general advice?
+</pre>
+
+ <a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_iterators.html">http://ScottCollins.net/Journal/discussion/string_iterators.html</a>
+
+<p>does this help?
+
+<p>I can personally walk you through any specific scenario you need.
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 9 Aug 2000 02:35:03 -0400
+Subject: Re: nsWritingIterator?
+</pre>
+
+<p>You got it right... it's <span class="code">nsWritingIterator<CharT></span> for whichever
+character type you care about, either <span class="code">char</span> or <span class="code">PRUnichar</span>. You
+_can_ use this iterator like a character pointer ... that is, you can
+dereference it, assign into its dereference, etc. It is more
+efficient, though, to directly address a particular range of
+characters around where it points by asking it for its actual
+character pointer with <span class="code">get</span>, and knowing that there are
+<span class="code">size_forward()</span> characters available ahead of that pointer and
+<span class="code">size_backward()</span> characters available behind it. After examining
+those characters by hand, you can advance the iterator beyond the
+characters you have examined (and possibly into the next chunk, should
+one exist) by adding into it (with +=) the count of the characters you
+have processed.
+
+<p>Here are three examples of running through a string and modifying some
+of the characters in it. All use <span class="code">nsWritingIterator</span>s.
+
+
+<div class="source-code">
+<pre>
+ // inefficient, but works in a pinch:
+ // iterators can hide all details of chunks by acting like
+ // a raw character pointer
+
+nsWritingIterator&lt;PRUnichar&gt; s = S.BeginWriting();
+nsWritingIterator&lt;PRUnichar&gt; done_with_string = S.EndWriting();
+
+ // for each character in the string |S|
+while ( s != done_with_string )
+ {
+ // if the character is lower case, capitalize it
+ if ( 'a' &lt;= *s &amp;&amp; *s &lt;= 'z' )
+ *s = *s -'a' + 'A';
+ }
+
+
+
+
+ // efficient
+ // iterators provide a mechanism by which you can process
+ // a chunk-at-a-time
+
+nsWritingIterator&lt;PRUnichar&gt; iter = S.BeginWriting();
+nsWritingIterator&lt;PRUnichar&gt; done_with_string = S.EndWriting();
+
+ // for each chunk of the string
+while ( iter != done_with_string )
+ {
+ size_t N = iter.size_forward(); // # of chars in this chunk
+ PRUnichar* s = iter.get();
+ PRUnichar* done_with_chunk = s + N;
+
+ // for each character in this chunk
+ for ( ; s &lt; done_with_chunk; ++s )
+ {
+ // if the character is lower case, capitalize it
+ if ( 'a' &lt;= *s &amp;&amp; *s &lt;= 'z' )
+ *s = *s - 'a' + 'A';
+ }
+
+ // advance the iterator past characters
+ // we examined (and into the next chunk, if any)
+ s += N;
+ }
+
+
+
+ // elegant
+ // pull your transformation into a `sink', and |copy_string|
+ // will efficiently pump any kind of string into it
+
+struct Capitalize
+ {
+ // inline
+ PRUint32
+ write( PRUnichar* s, PRUint32 N )
+ // processes one chunk, called repeatedly by |copy_string|
+ {
+ PRUnichar* done_with_chunk = s + N;
+
+ // for each character in this chunk
+ for ( ; s &lt; done_with_chunk; ++s )
+ {
+ // if the character is lower case, capitalize it
+ if ( 'a' &lt;= *s &amp;&amp; *s &lt;= 'z' )
+ *s = *s - 'a' + 'A';
+ }
+ }
+ };
+
+copy_string(S.BeginWriting(), S.EndWriting(), Capitalize());
+</pre>
+</div>
+
+
+
+<p>Does this show it better?
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 17 Aug 2000 18:23:22 -0400
+</pre>
+
+<pre class="email-quote">
+ >I tried looking at the string header files but they
+ >are awfully complicated.
+</pre>
+
+<p>I'll explain things in a little <strong>more</strong> detail than you need, then so
+that some of the stuff you see in these headers will make more sense.
+I'll also answer your questions out of order.
+
+<p>First: the string hierarchy looks like this
+
+<a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_hierarchy.gif">http://ScottCollins.net/Journal/discussion/string_hierarchy.gif</a>
+
+<p>The two most important headers are:
+
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a>
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h</a>
+
+<p>These abstract classes, <span class="code">nsAReadable[C]String</span>, and
+<span class="code">nsAWritable[C]String</span> are typically what you will want to use in the
+interfaces of new code. If you write a piece of code that takes a
+string for input, consider, e.g.,
+
+<div class="source-code">
+<pre>
+void consumes_a_string( const nsAReadableString&amp; aInput );
+</pre>
+</div>
+
+<p>If you write a piece of code that modifies a string, consider
+
+<div class="source-code">
+<pre>
+void modifies_a_string( nsAWritableString&amp; aResult );
+</pre>
+</div>
+
+
+<p>When creating your own classes, member strings will typically be
+<span class="code">nsString</span>s. When you can't avoid creating a short string that you
+need only temporarily during a function, you will typically use
+<span class="code">nsAutoString</span>. When someone passes you a raw pointer, or a raw
+pointer and a length, representing a buffer of characters that you may
+examine, but won't own, you can treat it like a string by wrapping it
+in an <span class="code">nsLiteralString</span>, e.g.,
+
+<div class="source-code">
+<pre>
+void
+reads_a_buffer( const PRUnichar* aInput, PRUint32 aInputLength )
+ {
+ nsLiteralString input(aInput, aInputLength);
+ // doesn't allocate or copy
+
+ // ...
+ }
+</pre>
+</div>
+
+<p>You will use <span class="code">nsLiteralString</span> around quoted constant strings as well,
+though typically through the <span class="code">NS_LITERAL_STRING</span> macro, to avoid doing
+a length calculation
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("x")
+</pre>
+</div>
+
+<p>expands to
+
+<div class="source-code">
+<pre>
+nsLiteralString(L"x", (sizeof(L"x")/sizeof(PRUnichar) - 1))
+</pre>
+</div>
+
+<p>if <span class="code">L</span> notation works as needed on your platform.
+
+Those are the basics. Now onto your questions:
+
+
+<pre class="email-quote">
+ >For example this won't compile. [...]
+
+ >str1 += L"abc " + str2 + L"def";
+</pre>
+
+
+<p><span class="code">L"abc "</span> makes a an object that is a <span class="code">const wchar_t[5]</span>, and none of
+the string code knows about <span class="code">wchar_t</span>. The main reason is that
+<span class="code">wchar_t</span> is not necessarily the right size (it can be 4 bytes under
+gcc). If you wrap these constant expressions in <span class="code">NS_LITERAL_STRING</span>,
+as described above, you should get the right thing, e.g.,
+
+<div class="source-code">
+<pre>
+str1 += NS_LITERAL_STRING("abc ") + str2 + NS_LITERAL_STRING("def");
+</pre>
+</div>
+
+
+<pre class="email-quote">
+ >Another one is:
+ >function(const PRUnichar *foo);
+ >call function(L"abc " + str2);
+
+ >It won't create a temporary nsString.
+</pre>
+
+<p>This one, I have a quick and easy explanation for. If <span class="code">function</span> was
+declared like this
+
+<div class="source-code">
+<pre>
+function( const nsAReadableString&amp; )
+</pre>
+</div>
+
+<p>then, no problem, since a <span class="code">nsPromiseConcatenation</span> (which was the
+result of adding those two things together) <strong>is</strong> a readable string.
+No other objects need to be created; no copying needs to be performed.
+
+<p>In all cases, we want the creation of <span class="code">nsString</span>s et al, to be
+<span class="code">explicit</span>, since creation is unbelievably expensive, requiring heap
+allocation, locks, copying, etc.
+
+<p>I hope this answers both your posts,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 17 Aug 2000 20:57:08 -0400
+Subject: re our conversation
+</pre>
+
+ return ToNewUnicode( nsLiteralCString(buffer) );
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 18 Aug 2000 02:52:45 -0400
+Subject: Re: More questions and new string API
+</pre>
+
+<pre class="email-quote">
+ >1) How do I return a static string?
+
+ >const nsAReadableString&amp; foo() {return NS_LITERAL_STRING("x");}
+ >errors on taking the address of a temporary variable.
+</pre>
+
+<p>Unfortunately, <span class="code">NS_LITERAL_STRING</span>s definition is not particularly
+amenable to this use. Instead, you would have to say something like
+this:
+
+<div class="source-code">
+<pre>
+const nsAReadableString&
+foo()
+ {
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ static nsLiteralString static_foo(L"x", 1);
+#else
+ static nsLiteralString static_foo;
+ static PRBool initialized = PR_FALSE;
+ if ( !initialized )
+ {
+ static_foo.AssignWithConversion("x", 1);
+ initialized = PR_TRUE;
+ }
+#endif
+ return static_foo;
+ }
+</pre>
+</div>
+
+
+<pre class="email-quote">
+ >2) I'm using these with the STL library in an XPCOM component.
+ >What type should I use with map? This doesn't work...
+
+ >typedef map<const nsAReadableString&, myType*> mapStringMyType;
+ >mapStringMyType foo;
+ >foo.find(nsAReadableString); - I want to find on a ReadableString
+</pre>
+
+<p>I don't know what errors you are getting; but it probably doesn't work
+because a reference isn't an assignable type. This is just a guess.
+You may need to use
+
+<div class="source-code">
+<pre>
+map<const nsAReadableString*, myType*>
+</pre>
+</div>
+
+<p>If you actually want the map to manage ownership of the keys, then
+you'll want to use a concrete type, e.g.,
+
+<div class="source-code">
+<pre>
+map<nsString, myType*>
+</pre>
+</div>
+
+<p>or perhaps
+
+<div class="source-code">
+<pre>
+map<nsSharedStringPtr, myType*>
+</pre>
+</div>
+
+<p>Or maybe there's something else wrong. Send me the error messages.
+If you end up using a pointer, then of course you'll have to supply a
+comparison function to the <span class="code">map</span> template. You won't be satisfied
+with the default comparison of pointers :-) Sorry I couldn't answer
+this one more completely.
+
+
+<pre class="email-quote">
+ >3) How do a get a raw PRUnichar pointer out of nsAReadableString
+ >when I need to call something that wants 'unsigned short *'?
+</pre>
+
+<p>The problem with this scenario is that an <span class="code">nsAReadableString</span> doesn't
+promise that all its data is contiguous, nor that it is
+zero-terminated, which is what I suspect you want in this case. If
+the function you want to call can take {pointer, length} tuples, and
+can consume the string in hunks without zero termination ... then you
+can use <span class="code">copy_string</span> to pump the string into your function, see
+
+ <a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_iterators.html">http://ScottCollins.net/Journal/discussion/string_iterators.html</a>
+
+<p>If not, and you absolutely have to have a contiguous zero-terminated
+buffer, then there is a new facility (part of the DOMAPI branch) that
+does what you need. It's not checked in on the trunk; it should
+be in early next week. It is <span class="code">nsPromiseFlatString</span>. This class
+promises a contiguous zero-terminated buffer; and has an <span class="code">operator
+PRUnichar*</span> to produce a pointer to that buffer automatically. If the
+underlying class <strong>is</strong> one that happens to be a single fragment and
+zero-terminated, then, like <span class="code">nsPromiseSubstring</span> and
+<span class="code">nsPromiseConcatenation</span>, this class merely holds a reference into the
+original data. If, however, the underlying string is multi-fragment
+or not zero-terminated, then <span class="code">nsPromiseFlatString</span> allocates a
+contiguous buffer of appropriate size and copies the fragmented string
+data to it. So given
+
+<div class="source-code">
+<pre>
+void ReadBuffer( PRUnichar* );
+</pre>
+</div>
+
+<p>You can call this as efficiently as possible with an arbitrary string
+like so
+
+<div class="source-code">
+<pre>
+ReadBuffer( nsPromiseFlatString(aString) );
+</pre>
+</div>
+
+
+<p>If the function you are calling needs to take ownership of the buffer
+you hand it, then you will probably call <span class="code">ToNewUnicode</span> like so
+
+<div class="source-code">
+<pre>
+void ConsumeBuffer( PRUnichar* );
+
+ConsumeBuffer( ToNewUnicode(aString) );
+</pre>
+</div>
+
+<p>The global function <span class="code">ToNewUnicode</span> is declared in "nsReadableUtils.h",
+and was only recently added to the build. It is currently being used
+in the DOMAPI branch. It is part of the build, but the file
+"dlldeps.c" in XPCOM may need to be modified to ensure it is exported
+on your platform if you are building the tip.
+
+Needless to say, you want to avoid functions that require bare
+pointers for several reasons: (a) they typically assume
+zero-termination, which is not guaranteed by the normal encodings; (b)
+they require contiguous allocation, which may not be possible; (c)
+they scan for the end of the string, at linear cost (if the encoding
+makes it possible at all), when the length could be known in advance.
+If you have to do it, the above mechanisms work, but be aware of the
+cost and the potential need to copy.
+
+
+<pre class="email-quote">
+ >4) How do I declare a local variable to hold a nsAReadableString?
+ >and a member variable?
+</pre>
+
+<p><span class="code">nsAReadableString</span> is an abstract type. So you can't have a concrete
+instance of it. All strings in the hierarchy are readable strings.
+If you just want a reference to a readable string, you can say, e.g.,
+
+<div class="source-code">
+<pre>
+struct foo
+ {
+ const nsAReadableString&amp; mString;
+ // ...
+
+ foo( const nsAReadableString&amp; aString ) : mString(aString) { }
+ };
+</pre>
+</div>
+
+<p>...similarly with pointers; but I suspect you are looking for
+something more concrete. An <span class="code">nsString</span> is a <span class="code">nsAReadableString</span>, and
+is the typical thing you want as a member variable. An <span class="code">nsAutoString</span>
+is also an <span class="code">nsAReadableString</span> and is typically what you would use for
+a short (in length) temporary (in lifetime) local variable, as I
+mentioned in my previous post.
+
+
+<pre class="email-quote">
+ >5) If I call a function that returns a PRUnichar* and I want t
+ >use it as a nsAReadableString should I wrap it in a
+ >nsLiteralString?
+</pre>
+
+<p>Yes, though remember, an <span class="code">nsLiteralString</span> assumes the lifetime of the
+underlying data is under someone else's control. If the called
+function gives you a buffer that you need to <span class="code">delete</span>, you will have
+to manage that yourself. Currently, people often use <span class="code">nsXPIDLString</span>
+to handle that. XPIDL strings are <strong>not</strong> part of the hierarchy. They
+are only used as a sort of string-<span class="code">auto_ptr</span>. However, I'm
+integrating their functionality into <span class="code">nsString</span>. There is no problem
+in wrapping the same pointer in both as two separate local variables,
+one to give you the readable interface, and one to manage the
+lifetime.
+
+<p>If it's OK with you, I'd like to post this reply (including your
+quoted questions) to n.p.m.xpcom and also put a copy near the string
+iterator discussion I provided a link to above, so that other people
+with similar questions can see these answers.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Sun, 3 Sep 2000 03:52:17 -0400
+</pre>
+
+<p>In article <8nu9m2$eo14@secnews.netscape.com>, "Jon Smirl"
+<jonsmirl@mediaone.com> wrote:
+
+> I have the new strings up and running in my app. They work as
+> advertised and
+> I haven't found any bugs. Thanks for the good job in designing and
+> implementing them. Here's are a summary of issues I've encountered
+> so far...
+
+<p>Thanks, and I appreciate your comments and insights.
+
+
+>
+> 1) Should there be a nsSegmentedString derived from nsString instead
+> of building segment support into nsString? None of my strings are
+> segmented but
+> I keep executing code that is supports it. nsPromiseFlatString would
+> be trivial in the non-segmented case.
+
+<p>The general case is that a string does not promise to have contiguous
+data. A specific case is that, for some implementations, it does.
+You couldn't do it the other way around, because a segmented string
+couldn't satisfy all the promises of a flat string. However, through
+the use of chunky iterators, operating on strings that happen to be
+flat is very efficient. In fact, <span class="code">nsPromiseFlatString</span> is trivial in
+the non-segmented case. In addition, I'll be adding an abstract flat
+class into the hierarchy, which will present additional interface ...
+in your local routines where you actually have declared a concrete
+string instance that happens to be flat, the compiler will give you
+the benefit of using the flat specific routines (e.g., a substring
+object over a flat string is simpler than the general purpose
+substring). I need to be cautious about this, though, since I don't
+automatically want people propagating the flat type through their
+interfaces. That would put us in the same boat we're in right now ...
+where routines only work on a specific kind of string, which denies
+other parts of the code the opportunity to use an implementation
+beneficial to its specific needs, and typically for no good reason.
+
+>
+> 2) Should nsAWritableString have a way to get the buffer and then
+> return it?
+> I need to get the buffer to pass it to OS calls. I'm doing this now
+> by passing around nsStrings instead of the interface. If I just use
+> the interface I encur an extra copy since I have to use a temporary
+> buffer.
+
+<p>A specific string implementation could promise this, but in general, a
+writable could not. After all, a writable doesn't even guarantee
+contiguous storage. To some degree, this is what
+<span class="code">nsPromiseFlatString</span> is for. However, this is a readable promise
+only. It will also be the case that <span class="code">ns[C]String</span>s, in the very near
+future will be able to just assume ownership of an arbitrary buffer
+allocated on the free store with the XPCOM allocators ... getting one
+to give up its buffer, on the other hand, presents some problems. Do
+you have a lot of places where the system writes into your string
+buffer space? Or do you have a lot of system routines that return you
+new buffers? I can imagine using <span class="code">nsPromiseFlatString</span> for this, but
+what happens when the OS alters the underlying data? If the promise
+had generated that flat data on behalf of a multi-fragment string,
+should it now put the changes back? It's possible to do, I just want
+to know if it's correct to allow this situation to happen.
+
+
+
+>
+> 3) There needs to be a NS_LITERAL_CHAR() to go along with
+> NS_LITERAL_STRING().
+
+<p>OK.
+
+
+
+> Having NS_LITERAL_STRING() all over the code clutters
+> it up and makes it hard to tell what the code is doing, could we
+> have a standard short alias for this?
+
+<p>Yes, I'll try to think of something ... perhaps <span class="code">NS_LSTR</span>?
+
+
+> 4) nsLiteralString should support n.ToInteger(&error);
+
+<p><span class="code">ToInteger</span> is actually a bad interface. It's only good if your
+entire string is the number; this encourages you to edit your string
+until it is one, or perhaps copy the numeric part to another string.
+Better if you just <span class="code">sscanf</span> a string (don't know if I can provide
+that in the general case, but I'm thinking about it), or else use
+regular C++ extractors (which wouldn't be too hard for me to
+provide), or else I could give you a <span class="code">ToInteger</span> that works on a pair
+of iterators, extracting the integer from the digits between them.
+
+>
+> 5) There should be a global define for an interface to a readonly
+> empty string.
+
+<p>Yes, there will be.
+
+
+>
+> 6) Something is wrong with concatenation....
+
+<p>Hopefully I've fixed this now.
+
+
+
+> 8) A forward definition is missing in the h files
+
+<p>I'll check it out.
+
+
+
+<p>My understanding is that you have already found the answers to your
+other questions.
+
+<p>I hope this helps,
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 20 Sep 2000 17:32:13 -0400
+Subject: Re: how to free an nsString::ToNewCString
+</pre>
+
+<pre class="email-quote">
+ >What's the current approved way to free an nsString::ToNewCString?
+</pre>
+
+<p><span class="code">nsMemory::Free</span>
+
+
+
+
+
+<hr>
+
+<p>You use several <span class="code">NS_ConvertASCIItoUTF16("...").get()</span>, these should be
+
+ NS_LITERAL_STRING("...").get()
+
+<p>Don't do this to the very first case where you aren't wrapping an actual literal string.
+The first instance would should exploit <span class="code">NS_LITERAL_STRING</span> technology as well,
+around the initial declarations of the strings ... probably want to do this with
+<span class="code">NS_NAMED_LITERAL_STRING</span>.
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 00:57:28 -0400
+Subject: string answers
+</pre>
+
+<div class="source-code">
+<pre>
+nsresult
+DoSomething( nsAWritableString&amp; answer )
+ {
+ nsresult rv;
+
+ nsXPIDLString registry_data;
+ Fetch("key", getter_Shares(registry_data));
+
+ nsLiteralString path(not_my_string);
+
+ PRInt32 first_colon = path.FindChar(PRUnichar(':'));
+ if ( first_colon != -1 )
+ {
+ // convert ... extract path from |path|
+ nsCOMPtr<nsILocalFile> localFile( do_CreateInstance(CID, &rv)
+);
+ if ( localFile )
+ {
+
+localFile->SetPersistentDescriptor(NS_ConvertUTF16toUTF8(path));
+
+ nsXPIDLString converted_path;
+ localFile->GetUnicodePath(getter_Copies(converted_path));
+ answer = converted_path.get();
+ }
+ }
+ else
+ {
+ answer = path;
+ }
+
+
+ return rv;
+ }
+</pre>
+</div>
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 02:03:49 -0400
+Subject: Re: and the answer is ...
+</pre>
+
+<p>You can see from the line of code that you're on, that this should
+have been fine. <span class="code">nsMemory::Alloc</span> would be asked to allocate a 1 byte
+object. But it failed trying to allocate that. Which suggests that
+the allocator was busy and non-reentrant and the debugger tried to
+misuse it. Yes?
+
+<p>Of course, this doesn't solve your problem. Perhaps we need to go
+back to the idea of a function that returns a pointer to the first
+hunk of the string.
+
+<div class="source-code">
+<pre>
+const char*
+debug_string( const nsAReadableCString& aCString )
+ {
+ nsReadingIterator&lt;char&gt; iter;
+ aCString.BeginReading(iter);
+ return aCString.IsEmpty() ? "" : iter.get();
+ }
+</pre>
+</div>
+
+<p>This code should work regardless of what the allocator is doing. The
+downsides are (a) it only returns the first hunk of the string, in the
+case of a multi-fragment string; and (b) that hunk <strong>might</strong> not be
+zero-terminated.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 08:30:32 -0400
+Subject: Re: Self healing the cache :-)
+</pre>
+
+<p>At 3:04 PM -0400 10/11/00, Mike Shaver wrote:
+<pre class="email-quote">
+ >NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+</pre>
+
+<p>Macro ugliness makes <span class="code">NS_LITERAL_STRING</span> inappropriate for use over
+other macros. In other words:
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("foo")
+</pre>
+</div>
+
+<p>is <strong>good</strong>.
+
+<div class="source-code">
+<pre>
+#define FOO "foo"
+NS_LITERAL_STRING(FOO)
+</pre>
+</div>
+
+<p>is <strong>bad</strong>. Why? Because it turns into
+
+<div class="source-code">
+<pre>
+nsLiteralString(LFOO, sizeof(LFOO)...
+</pre>
+</div>
+
+<p>and there is no <span class="code">LFOO</span>. Sorry. If you have to do this to a
+macro-ized string, do the magic by hand, e.g.,
+
+<div class="source-code">
+<pre>
+nsLiteralString(FOO, sizeof(FOO)/sizeof(PRUnichar)
+ + sizeof(PRUnichar('\0')))
+</pre>
+</div>
+
+<p>or else if you don't care that <span class="code">nsLiteralString</span> will scan for the
+length, just say
+
+<div class="source-code">
+<pre>
+nsLiteralString(FOO)
+</pre>
+</div>
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 08:36:14 -0400
+Subject: Re: Self healing the cache :-)
+</pre>
+
+<p>Actually, I'm not even sure you can do it by hand, since you didn't
+
+<div class="source-code">
+<pre>
+#define FOO L"foo"
+</pre>
+</div>
+
+<p>and <strong>can't</strong> do that cross-platform. The other way around this is to
+define a global instead of a macro, that is, instead of saying
+
+<div class="source-code">
+<pre>
+#define FOO "foo"
+</pre>
+</div>
+
+<p>at the top of your file, say
+
+<div class="source-code">
+<pre>
+NS_NAMED_LITERAL_STRING(FOO, "foo")
+</pre>
+</div>
+
+<p>or else, if the macro was used only in one spot ... perhaps you could
+just eliminate the macro in favor of <span class="code">NS_NAMED_LITERAL</span> in situ.
+
+<p>Arghh. In this case, you may be stuck with the extra work of
+<span class="code">AssignWithConversion</span>.
+
+
+
+
+
+<hr>
+<pre>
+Date: Sun, 3 Dec 2000 16:38:07 -0400
+Subject: Re: another copy_string question
+</pre>
+
+<pre class="email-quote">
+ >Is there a way to tell, inside the write() sink, if one is in the
+ >final hunk? I need to do some special processing at the end.
+</pre>
+
+<p>No, there isn't. But you could move such special processing into the
+destructor of the sink. Remember, the sink is passed by reference, so
+you can exactly control its lifetime.
+
+<div class="source-code">
+<pre>
+{
+ MySink sink;
+ nsReadingIterator&lt;PRUnichar&gt; sourceStart = aStr.BeginReading();
+ nsReadingIterator&lt;PRUnichar&gt; sourceEnd = aStr.EndReading();
+ copy_string(sourceStart, sourceEnd, sink);
+ // |sink| destructor executed here
+}
+</pre>
+</div>
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 15 Dec 2000 20:02:08 -0400
+Subject: fragment of code
+</pre>
+
+<div class="source-code">
+<pre>
+nsPromiseFlatString flatKey(aReadable);
+
+flatKey.get()
+</pre>
+</div>
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 16 Jan 2001 16:47:37 -0400
+Subject: Re: a few string questions...
+</pre>
+
+>I've accumulated a few questions I've been wanting to ask you, mostly
+>about string stuff. Nothing urgent, but I want to ask them before I
+>forget. So here goes...:
+>
+>1) Is it acceptable to use nsLiteralCString or nsLiteralString on
+>something that's not a literal? This can be useful in some places,
+>for example, to convert a char* to PRUnichar*:
+>
+>PRUnichar* new = ToNewUnicode(nsLiteralCString(myCharPtr));
+
+<p>This is explicitly allowed. That's why I'm proposing to change the
+names of those classes to <span class="code">nsLocal[C]String</span>.
+
+
+>2) Should nsString2x.h and nsString2x.cpp go away? They look like a
+>never-completed rewrite or something...
+
+<p>Yes. They should go away. They are uncompleted [old] bullshit,
+exactly as you diagnosed.
+
+<p>I'll look into the other two questions.
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 1 Feb 2001 15:12:41 -0400
+Subject: Re: [Fwd: bad string, bad string]
+</pre>
+
+<p>We've been removing implicit conversion operators because they
+_always_ lead to trouble. Usually they make it harder to pick the
+right function when overloading is involved and in the past they have
+led to huge performance suckage because we ended up doing conversions
+when we didn't need to because the implicit operator made us pick the
+wrong function.
+
+<p>It's borderline when the class implements something that is <strong>so</strong>
+close, as with a guaranteed flat string or an <span class="code">nsCOMPtr</span> ... but the
+general recommendation is to avoid implicit conversions.
+
+<p>See bug #53057.
+
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 6 Feb 2001 18:52:23 -0400
+Subject: seeking review for bug #57087
+</pre>
+
+<p> bug:
+ <a class="exact-uri" href="http://bugzilla.mozilla.org/show_bug.cgi?id=57087">http://bugzilla.mozilla.org/show_bug.cgi?id=57087</a>
+
+ patch:
+ <a class="exact-uri" href="http://bugzilla.mozilla.org/showattachment.cgi?attach_id=24576">http://bugzilla.mozilla.org/showattachment.cgi?attach_id=24576</a>
+
+<p>This patch is supposed to add the ability to define very long literal
+strings more easily by breaking lines, e.g.,
+
+<div class="source-code">
+<pre>
+NS_MULTILINE_LITERAL( NS_L("This is the start of a very long line")
+ NS_L(" which actually continues across")
+ NS_L(" a couple more.") )
+</pre>
+</div>
+
+<p>The main danger in this scheme is callers who omit the inner <span class="code">NS_L</span>
+wrapping. Though I believe this will be caught at compile time as the
+wrong type initializer.
+
+<p>Seeking input from everybody, and waterson in particular.
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 14 Feb 2001 16:09:10 -0400
+Subject: Re: Question...
+</pre>
+
+<p>There are some utilities in "xpcom/ds/nsReadableUtils.h". In
+particular, if you want to get back a new heap-allocated ASCII string
+with the minimal work, you would say
+
+<div class="source-code">
+<pre>
+PRUnichar* sourceChars = ...;
+
+char* destChars = ToNewCString(nsLiteralString(sourceChars));
+</pre>
+</div>
+
+
+<p>It's more efficient if you happen to already know the length. If you
+don't, don't bother counting, that's what I'll do in the constructor
+for <span class="code">nsLiteralString</span>. If you do, then call like this
+
+<div class="source-code">
+<pre>
+destChars = ToNewCString( nsLiteralString(sourceChars, length) );
+</pre>
+</div>
+
+<p>Other routines in that file will help you if, for instance, you wanted
+to translate into a buffer you had already allocated.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 23 Feb 2001 03:12:58 -0400
+Subject: string snippet
+</pre>
+
+<div class="source-code">
+<pre>
+nsCString aInput;
+
+
+
+nsReadingIterator&lt;char&gt; search_start;
+aInput.BeginReading(search_start);
+
+nsReadingIterator&lt;char&gt; search_end;
+aInput.EndReading(search_end);
+
+if ( FindCharInReadable(':', search_start, search_end) )
+ {
+ ++search_start;
+ return ToNewCString( Substring(aInput, search_start, search_end)
+);
+ }
+</pre>
+</div>
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 7 Mar 2001 19:44:08 -0400
+Subject: string help
+</pre>
+
+<p>Here you go, Mike:
+
+ http://scottcollins.net/journal/discussion/mjudge-scratch.cpp
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 9 Mar 2001 20:56:07 -0400
+Subject: Re: string assertions
+</pre>
+
+<p>If you get an iterator into a string and you advance it all the way to
+the end of the string, and then <strong>keep</strong> trying to advance it, you hit
+this assert. This could happen, for example if you tried to copy 10
+characters out of a 9 character string. I've tried to make this
+impossible to get to. As far as I know, all my routines trim requests
+in advance of manipulating iterators. When you see this, you should
+get the stack. That will take you right to the bad spot.
+
+
+
+
+
+<hr>
+<pre>
+Date: Sat, 31 Mar 2001 11:04:03 -0400
+Subject: Re: Sun bustage and string advice
+</pre>
+
+<p>You do know you are comparing two pointers now? It seems unlikely
+those two pointers would ever be the same pointer. You probably want
+to say something like
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("foo").Equals(aTopic) // or
+
+NS_LITERAL_STRING("foo") == nsLiteralString(aTopic)
+</pre>
+</div>
+
+<p>...so that you compare the <strong>contents</strong> of two strings. Right now,
+you're just testing to see if two pointers both point to the same
+location in memory. A lot of people make this mistake. I would like
+to make it obvious to people that comparing two pointers does not
+compare strings. Can you tell me what gave you that impression so
+that I can figure out how to better educate people not to do this? By
+the way, it's not that I don't <strong>want</strong> to make this compare two
+strings; it's that in C++, you can't override operations for built-in
+types. And pointers are built-in types. So I can't make
+<span class="code">operator==(const PRUnichar*, const PRUnichar*)</span> do anything different
+than it already does, which is the same thing it does for any other
+pointer.
+
+
+
+
+
+
+</div>
+
+
+
+<!-- .................................................................End Matter -->
+
+
+
+ </body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/string/public/.cvsignore b/src/libs/xpcom18a4/xpcom/string/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/string/public/Makefile.in b/src/libs/xpcom18a4/xpcom/string/public/Makefile.in
new file mode 100644
index 00000000..d3582bcc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/Makefile.in
@@ -0,0 +1,86 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Johnny Stenback <jst@netscape.com> (original author)
+# Scott Collins <scc@mozilla.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = string
+
+EXPORTS = \
+ nsAString.h \
+ nsAlgorithm.h \
+ nsCharTraits.h \
+ nsDependentString.h \
+ nsDependentSubstring.h \
+ nsLiteralString.h \
+ nsObsoleteAString.h \
+ nsPrintfCString.h \
+ nsPromiseFlatString.h \
+ nsReadableUtils.h \
+ nsString.h \
+ nsStringFwd.h \
+ nsStringIterator.h \
+ nsSubstring.h \
+ nsSubstringTuple.h \
+ nsTAString.h \
+ nsTDependentString.h \
+ nsTDependentSubstring.h \
+ nsTObsoleteAString.h \
+ nsTPromiseFlatString.h \
+ nsTString.h \
+ nsTSubstring.h \
+ nsTSubstringTuple.h \
+ nsUTF8Utils.h \
+ nsXPIDLString.h \
+ string-template-def-unichar.h \
+ string-template-def-char.h \
+ string-template-undef.h \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsStringAPI.h \
+ nsEmbedString.h \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsAString.h
new file mode 100644
index 00000000..3675989c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsAString.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsAString_h___
+#define nsAString_h___
+
+#ifndef nsStringFwd_h___
+#include "nsStringFwd.h"
+#endif
+
+#ifndef nsStringIterator_h___
+#include "nsStringIterator.h"
+#endif
+
+#ifndef nsObsoleteAString_h___
+#include "nsObsoleteAString.h"
+#endif
+
+// If some platform(s) can't handle our template that matches literal strings,
+// then we'll disable it on those platforms.
+#ifndef NS_DISABLE_LITERAL_TEMPLATE
+# if (defined(_MSC_VER) && (_MSC_VER < 1310)) || (defined(__SUNPRO_CC) & (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100))
+# define NS_DISABLE_LITERAL_TEMPLATE
+# endif
+#endif /* !NS_DISABLE_LITERAL_TEMPLATE */
+
+#include <string.h>
+
+ // declare nsAString
+#include "string-template-def-unichar.h"
+#include "nsTAString.h"
+#include "string-template-undef.h"
+
+
+ // declare nsACString
+#include "string-template-def-char.h"
+#include "nsTAString.h"
+#include "string-template-undef.h"
+
+
+ /**
+ * ASCII case-insensitive comparator. (for Unicode case-insensitive
+ * comparision, see nsUnicharUtils.h)
+ */
+class NS_COM nsCaseInsensitiveCStringComparator
+ : public nsCStringComparator
+ {
+ public:
+ typedef char char_type;
+
+ virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const;
+ virtual int operator()( char_type, char_type ) const;
+ };
+
+
+ // included here for backwards compatibility
+#ifndef nsSubstringTuple_h___
+#include "nsSubstringTuple.h"
+#endif
+
+#endif // !defined(nsAString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h b/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h
new file mode 100644
index 00000000..e81e6f57
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAlgorithm_h___
+#define nsAlgorithm_h___
+
+#ifndef nsCharTraits_h___
+#include "nsCharTraits.h"
+ // for |nsCharSourceTraits|, |nsCharSinkTraits|
+#endif
+
+#ifndef prtypes_h___
+#include "prtypes.h"
+ // for |PRUint32|...
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+ // for NS_ASSERTION
+#endif
+
+template <class T>
+inline
+const T&
+NS_MIN( const T& a, const T& b )
+ {
+ return b < a ? b : a;
+ }
+
+template <class T>
+inline
+const T&
+NS_MAX( const T& a, const T& b )
+ {
+ return a > b ? a : b;
+ }
+
+template <class InputIterator, class T>
+inline
+PRUint32
+NS_COUNT( InputIterator& first, const InputIterator& last, const T& value )
+ {
+ PRUint32 result = 0;
+ for ( ; first != last; ++first )
+ if ( *first == value )
+ ++result;
+ return result;
+ }
+
+template <class InputIterator, class OutputIterator>
+inline
+OutputIterator&
+copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result )
+ {
+ typedef nsCharSourceTraits<InputIterator> source_traits;
+ typedef nsCharSinkTraits<OutputIterator> sink_traits;
+
+ while ( first != last )
+ {
+ PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last)));
+ NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate");
+ source_traits::advance(first, count_copied);
+ }
+
+ return result;
+ }
+
+template <class InputIterator, class OutputIterator>
+OutputIterator&
+copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result )
+ {
+ while ( first != last )
+ {
+ last.normalize_backward();
+ result.normalize_backward();
+ PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) );
+ if ( first.fragment().mStart == last.fragment().mStart )
+ lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get()));
+
+ NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate");
+
+#ifdef _MSC_VER
+ // XXX Visual C++ can't stomach 'typename' where it rightfully should
+ nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
+#else
+ nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
+#endif
+
+ last.advance( -PRInt32(lengthToCopy) );
+ result.advance( -PRInt32(lengthToCopy) );
+ }
+
+ return result;
+ }
+
+#endif // !defined(nsAlgorithm_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h b/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h
new file mode 100644
index 00000000..e7713c95
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h
@@ -0,0 +1,784 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCharTraits_h___
+#define nsCharTraits_h___
+
+#include <ctype.h>
+ // for |EOF|, |WEOF|
+
+#define FORCED_CPP_2BYTE_WCHAR_T
+ // disable special optimizations for now through this hack
+
+#if defined(HAVE_CPP_2BYTE_WCHAR_T) && !defined(FORCED_CPP_2BYTE_WCHAR_T)
+#define USE_CPP_WCHAR_FUNCS
+#endif
+
+#ifdef USE_CPP_WCHAR_FUNCS
+#include <wchar.h>
+ // for |wmemset|, et al
+#endif
+
+#include <string.h>
+ // for |memcpy|, et al
+
+#ifndef nscore_h___
+#include "nscore.h"
+ // for |PRUnichar|
+#endif
+
+#ifndef nsDebug_h__
+#include "nsDebug.h"
+ // for NS_ASSERTION
+#endif
+
+#ifdef HAVE_CPP_BOOL
+ typedef bool nsCharTraits_bool;
+#else
+ typedef PRBool nsCharTraits_bool;
+#endif
+
+template <class CharT> struct nsCharTraits {};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharTraits<PRUnichar>
+ {
+ typedef PRUnichar char_type;
+ typedef PRUint16 unsigned_char_type;
+ typedef char incompatible_char_type;
+
+ NS_COM static const char_type *sEmptyBuffer;
+
+ static
+ void
+ assign( char_type& lhs, char_type rhs )
+ {
+ lhs = rhs;
+ }
+
+
+ // integer representation of characters:
+
+#ifdef USE_CPP_WCHAR_FUNCS
+ typedef wint_t int_type;
+#else
+ typedef int int_type;
+#endif
+
+ static
+ char_type
+ to_char_type( int_type c )
+ {
+ return char_type(c);
+ }
+
+ static
+ int_type
+ to_int_type( char_type c )
+ {
+ return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
+ }
+
+ static
+ nsCharTraits_bool
+ eq_int_type( int_type lhs, int_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+
+ // |char_type| comparisons:
+
+ static
+ nsCharTraits_bool
+ eq( char_type lhs, char_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+ static
+ nsCharTraits_bool
+ lt( char_type lhs, char_type rhs )
+ {
+ return lhs < rhs;
+ }
+
+
+ // operations on s[n] arrays:
+
+ static
+ char_type*
+ move( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copy( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copyASCII( char_type* s1, const char* s2, size_t n )
+ {
+ for (char_type* s = s1; n--; ++s, ++s2) {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ *s = *s2;
+ }
+ return s1;
+ }
+
+ static
+ char_type*
+ assign( char_type* s, size_t n, char_type c )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return NS_STATIC_CAST(char_type*, wmemset(s, to_int_type(c), n));
+#else
+ char_type* result = s;
+ while ( n-- )
+ assign(*s++, c);
+ return result;
+#endif
+ }
+
+ static
+ int
+ compare( const char_type* s1, const char_type* s2, size_t n )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return wmemcmp(s1, s2, n);
+#else
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !eq(*s1, *s2) )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ return 0;
+#endif
+ }
+
+ static
+ int
+ compareASCII( const char_type* s1, const char* s2, size_t n )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ return 0;
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ /**
+ * Convert c to its lower-case form, but only if the lower-case form is
+ * ASCII. Otherwise leave it alone.
+ *
+ * There are only two non-ASCII Unicode characters whose lowercase
+ * equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH
+ * DOT ABOVE. So it's a simple matter to handle those explicitly.
+ */
+ static
+ char_type
+ ASCIIToLower( char_type c )
+ {
+ if (c < 0x100)
+ return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
+ else
+ {
+ if (c == 0x212A) // KELVIN SIGN
+ return 'k';
+ if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE
+ return 'i';
+ return c;
+ }
+ }
+
+ static
+ int
+ compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != to_char_type(*s2) )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+
+ return 0;
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != to_char_type(*s2) )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ static
+ size_t
+ length( const char_type* s )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return wcslen(s);
+#else
+ size_t result = 0;
+ while ( !eq(*s++, char_type(0)) )
+ ++result;
+ return result;
+#endif
+ }
+
+ static
+ const char_type*
+ find( const char_type* s, size_t n, char_type c )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return NS_REINTERPRET_CAST(const char_type*, wmemchr(s, to_int_type(c), n));
+#else
+ while ( n-- )
+ {
+ if ( eq(*s, c) )
+ return s;
+ ++s;
+ }
+
+ return 0;
+#endif
+ }
+
+#if 0
+ // I/O related:
+
+ typedef streamoff off_type;
+ typedef streampos pos_type;
+ typedef mbstate_t state_type;
+
+ static
+ int_type
+ eof()
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return WEOF;
+#else
+ return EOF;
+#endif
+ }
+
+ static
+ int_type
+ not_eof( int_type c )
+ {
+ return eq_int_type(c, eof()) ? ~eof() : c;
+ }
+
+ // static state_type get_state( pos_type );
+#endif
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharTraits<char>
+ {
+ typedef char char_type;
+ typedef unsigned char unsigned_char_type;
+ typedef PRUnichar incompatible_char_type;
+
+ NS_COM static const char_type *sEmptyBuffer;
+
+ static
+ void
+ assign( char_type& lhs, char_type rhs )
+ {
+ lhs = rhs;
+ }
+
+
+ // integer representation of characters:
+
+ typedef int int_type;
+
+ static
+ char_type
+ to_char_type( int_type c )
+ {
+ return char_type(c);
+ }
+
+ static
+ int_type
+ to_int_type( char_type c )
+ {
+ return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
+ }
+
+ static
+ nsCharTraits_bool
+ eq_int_type( int_type lhs, int_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+
+ // |char_type| comparisons:
+
+ static
+ nsCharTraits_bool
+ eq( char_type lhs, char_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+ static
+ nsCharTraits_bool
+ lt( char_type lhs, char_type rhs )
+ {
+ return lhs < rhs;
+ }
+
+
+ // operations on s[n] arrays:
+
+ static
+ char_type*
+ move( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copy( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copyASCII( char_type* s1, const char* s2, size_t n )
+ {
+ return copy(s1, s2, n);
+ }
+
+ static
+ char_type*
+ assign( char_type* s, size_t n, char_type c )
+ {
+ return NS_STATIC_CAST(char_type*, memset(s, to_int_type(c), n));
+ }
+
+ static
+ int
+ compare( const char_type* s1, const char_type* s2, size_t n )
+ {
+ return memcmp(s1, s2, n);
+ }
+
+ static
+ int
+ compareASCII( const char_type* s1, const char* s2, size_t n )
+ {
+#ifdef DEBUG
+ for (size_t i = 0; i < n; ++i)
+ {
+ NS_ASSERTION(!(s2[i] & ~0x7F), "Unexpected non-ASCII character");
+ }
+#endif
+ return compare(s1, s2, n);
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ // can't use strcmp here because we don't want to stop when s1
+ // contains a null
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ if ( *s1 != *s2 )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ /**
+ * Convert c to its lower-case form, but only if c is ASCII.
+ */
+ static
+ char_type
+ ASCIIToLower( char_type c )
+ {
+ return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
+ }
+
+ static
+ int
+ compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != *s2 )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+ return 0;
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != *s2 )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ static
+ size_t
+ length( const char_type* s )
+ {
+ return strlen(s);
+ }
+
+ static
+ const char_type*
+ find( const char_type* s, size_t n, char_type c )
+ {
+ return NS_REINTERPRET_CAST(const char_type*, memchr(s, to_int_type(c), n));
+ }
+
+#if 0
+ // I/O related:
+
+ typedef streamoff off_type;
+ typedef streampos pos_type;
+ typedef mbstate_t state_type;
+
+ static
+ int_type
+ eof()
+ {
+ return EOF;
+ }
+
+ static
+ int_type
+ not_eof( int_type c )
+ {
+ return eq_int_type(c, eof()) ? ~eof() : c;
+ }
+
+ // static state_type get_state( pos_type );
+#endif
+ };
+
+template <class InputIterator>
+struct nsCharSourceTraits
+ {
+ typedef typename InputIterator::difference_type difference_type;
+
+ static
+ PRUint32
+ readable_distance( const InputIterator& first, const InputIterator& last )
+ {
+ // assumes single fragment
+ return last.get() - first.get();
+ }
+
+ static
+ const typename InputIterator::value_type*
+ read( const InputIterator& iter )
+ {
+ return iter.get();
+ }
+
+ static
+ void
+ advance( InputIterator& s, difference_type n )
+ {
+ s.advance(n);
+ }
+ };
+
+#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
+
+template <class CharT>
+struct nsCharSourceTraits<CharT*>
+ {
+ typedef ptrdiff_t difference_type;
+
+ static
+ PRUint32
+ readable_distance( CharT* s )
+ {
+ return PRUint32(nsCharTraits<CharT>::length(s));
+// return numeric_limits<PRUint32>::max();
+ }
+
+ static
+ PRUint32
+ readable_distance( CharT* first, CharT* last )
+ {
+ return PRUint32(last-first);
+ }
+
+ static
+ const CharT*
+ read( CharT* s )
+ {
+ return s;
+ }
+
+ static
+ void
+ advance( CharT*& s, difference_type n )
+ {
+ s += n;
+ }
+ };
+
+#else
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSourceTraits<const char*>
+ {
+ typedef ptrdiff_t difference_type;
+
+ static
+ PRUint32
+ readable_distance( const char* s )
+ {
+ return PRUint32(nsCharTraits<char>::length(s));
+// return numeric_limits<PRUint32>::max();
+ }
+
+ static
+ PRUint32
+ readable_distance( const char* first, const char* last )
+ {
+ return PRUint32(last-first);
+ }
+
+ static
+ const char*
+ read( const char* s )
+ {
+ return s;
+ }
+
+ static
+ void
+ advance( const char*& s, difference_type n )
+ {
+ s += n;
+ }
+ };
+
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSourceTraits<const PRUnichar*>
+ {
+ typedef ptrdiff_t difference_type;
+
+ static
+ PRUint32
+ readable_distance( const PRUnichar* s )
+ {
+ return PRUint32(nsCharTraits<PRUnichar>::length(s));
+// return numeric_limits<PRUint32>::max();
+ }
+
+ static
+ PRUint32
+ readable_distance( const PRUnichar* first, const PRUnichar* last )
+ {
+ return PRUint32(last-first);
+ }
+
+ static
+ const PRUnichar*
+ read( const PRUnichar* s )
+ {
+ return s;
+ }
+
+ static
+ void
+ advance( const PRUnichar*& s, difference_type n )
+ {
+ s += n;
+ }
+ };
+
+#endif
+
+
+template <class OutputIterator>
+struct nsCharSinkTraits
+ {
+ static
+ PRUint32
+ write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
+ {
+ return iter.write(s, n);
+ }
+ };
+
+#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
+
+template <class CharT>
+struct nsCharSinkTraits<CharT*>
+ {
+ static
+ PRUint32
+ write( CharT*& iter, const CharT* s, PRUint32 n )
+ {
+ nsCharTraits<CharT>::move(iter, s, n);
+ iter += n;
+ return n;
+ }
+ };
+
+#else
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSinkTraits<char*>
+ {
+ static
+ PRUint32
+ write( char*& iter, const char* s, PRUint32 n )
+ {
+ nsCharTraits<char>::move(iter, s, n);
+ iter += n;
+ return n;
+ }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSinkTraits<PRUnichar*>
+ {
+ static
+ PRUint32
+ write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
+ {
+ nsCharTraits<PRUnichar>::move(iter, s, n);
+ iter += n;
+ return n;
+ }
+ };
+
+#endif
+
+#endif // !defined(nsCharTraits_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h b/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h
new file mode 100644
index 00000000..22e05b31
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsDependentString_h___
+#define nsDependentString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+ // declare nsDependentString
+#include "string-template-def-unichar.h"
+#include "nsTDependentString.h"
+#include "string-template-undef.h"
+
+ // declare nsDependentCString
+#include "string-template-def-char.h"
+#include "nsTDependentString.h"
+#include "string-template-undef.h"
+
+#endif /* !defined(nsDependentString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h
new file mode 100644
index 00000000..c6459436
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsDependentSubstring_h___
+#define nsDependentSubstring_h___
+
+#ifndef nsSubstring_h___
+#include "nsSubstring.h"
+#endif
+
+ // declare nsDependentSubstring
+#include "string-template-def-unichar.h"
+#include "nsTDependentSubstring.h"
+#include "string-template-undef.h"
+
+ // declare nsDependentCSubstring
+#include "string-template-def-char.h"
+#include "nsTDependentSubstring.h"
+#include "string-template-undef.h"
+
+#endif /* !defined(nsDependentSubstring_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h b/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h
new file mode 100644
index 00000000..7af03ee3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a small implementation of the nsAString and nsACString.
+ *
+ * The Initial Developer of the Original Code is
+ * Peter Annema <jaggernaut@netscape.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsEmbedString_h___
+#define nsEmbedString_h___
+
+#include "nsStringAPI.h"
+
+class nsEmbedString : public nsStringContainer
+ {
+ public:
+ typedef nsEmbedString self_type;
+ typedef nsAString abstract_string_type;
+
+ nsEmbedString()
+ {
+ NS_StringContainerInit(*this);
+ }
+
+ nsEmbedString(const self_type& aString)
+#ifdef VBOX
+ : nsStringContainer()
+#endif
+ {
+ NS_StringContainerInit(*this);
+ NS_StringCopy(*this, aString);
+ }
+
+ explicit
+ nsEmbedString(const abstract_string_type& aReadable)
+ {
+ NS_StringContainerInit(*this);
+ NS_StringCopy(*this, aReadable);
+ }
+
+ explicit
+ nsEmbedString(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+ {
+ NS_StringContainerInit(*this);
+ NS_StringSetData(*this, aData, aLength);
+ }
+
+ ~nsEmbedString()
+ {
+ NS_StringContainerFinish(*this);
+ }
+
+ const char_type* get() const
+ {
+ const char_type* data;
+ NS_StringGetData(*this, &data);
+ return data;
+ }
+
+ self_type& operator=(const self_type& aString) { Assign(aString); return *this; }
+ self_type& operator=(const abstract_string_type& aReadable) { Assign(aReadable); return *this; }
+ self_type& operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ self_type& operator=(char_type aChar) { Assign(aChar); return *this; }
+ };
+
+class nsEmbedCString : public nsCStringContainer
+ {
+ public:
+ typedef nsEmbedCString self_type;
+ typedef nsACString abstract_string_type;
+
+ nsEmbedCString()
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ }
+
+ nsEmbedCString(const self_type& aString)
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ NS_CStringCopy(*this, aString);
+ }
+
+ explicit
+ nsEmbedCString(const abstract_string_type& aReadable)
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ NS_CStringCopy(*this, aReadable);
+ }
+
+ explicit
+ nsEmbedCString(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ NS_CStringSetData(*this, aData, aLength);
+ }
+
+ ~nsEmbedCString()
+ {
+ NS_CStringContainerFinish(*this);
+ }
+
+ const char_type* get() const
+ {
+ const char_type* data;
+ NS_CStringGetData(*this, &data);
+ return data;
+ }
+
+ self_type& operator=(const self_type& aString) { Assign(aString); return *this; }
+ self_type& operator=(const abstract_string_type& aReadable) { Assign(aReadable); return *this; }
+ self_type& operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ self_type& operator=(char_type aChar) { Assign(aChar); return *this; }
+ };
+
+#endif // !defined(nsEmbedString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h b/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h
new file mode 100644
index 00000000..ba536297
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsLiteralString_h___
+#define nsLiteralString_h___
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsDependentString_h___
+#include "nsDependentString.h"
+#endif
+
+
+#if 0
+inline
+const nsDependentString
+literal_string( const nsAString::char_type* aPtr )
+ {
+ return nsDependentString(aPtr);
+ }
+
+inline
+const nsDependentString
+literal_string( const nsAString::char_type* aPtr, PRUint32 aLength )
+ {
+ return nsDependentString(aPtr, aLength);
+ }
+
+inline
+const nsDependentCString
+literal_string( const nsACString::char_type* aPtr )
+ {
+ return nsDependentCString(aPtr);
+ }
+
+inline
+const nsDependentCString
+literal_string( const nsACString::char_type* aPtr, PRUint32 aLength )
+ {
+ return nsDependentCString(aPtr, aLength);
+ }
+#endif
+
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ #define NS_LL(s) L##s
+ #define NS_MULTILINE_LITERAL_STRING(s) nsDependentString(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
+ #define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
+ #define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const nsDependentString n(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
+ typedef nsDependentString nsLiteralString;
+#else
+ #define NS_LL(s) s
+ #define NS_MULTILINE_LITERAL_STRING(s) NS_ConvertASCIItoUTF16(s, PRUint32(sizeof(s)-1))
+ #define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(s, PRUint32(sizeof(s)-1))
+ #define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const NS_ConvertASCIItoUTF16 n(s, PRUint32(sizeof(s)-1))
+ typedef NS_ConvertASCIItoUTF16 nsLiteralString;
+#endif
+
+/*
+ * Macro arguments used in concatenation or stringification won't be expanded.
+ * Therefore, in order for |NS_L(FOO)| to work as expected (which is to expand
+ * |FOO| before doing whatever |NS_L| needs to do to it) a helper macro needs
+ * to be inserted in between to allow the macro argument to expand.
+ * See "3.10.6 Separate Expansion of Macro Arguments" of the CPP manual for a
+ * more accurate and precise explanation.
+ */
+
+#define NS_L(s) NS_LL(s)
+
+#define NS_LITERAL_STRING(s) NS_STATIC_CAST(const nsAFlatString&, NS_MULTILINE_LITERAL_STRING(NS_LL(s)))
+#define NS_LITERAL_STRING_INIT(n,s) NS_MULTILINE_LITERAL_STRING_INIT(n, NS_LL(s))
+#define NS_NAMED_LITERAL_STRING(n,s) NS_NAMED_MULTILINE_LITERAL_STRING(n, NS_LL(s))
+
+#define NS_LITERAL_CSTRING(s) NS_STATIC_CAST(const nsDependentCString&, nsDependentCString(s, PRUint32(sizeof(s)-1)))
+#define NS_LITERAL_CSTRING_INIT(n,s) n(s, PRUint32(sizeof(s)-1))
+#define NS_NAMED_LITERAL_CSTRING(n,s) const nsDependentCString n(s, PRUint32(sizeof(s)-1))
+
+typedef nsDependentCString nsLiteralCString;
+
+#endif /* !defined(nsLiteralString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h
new file mode 100644
index 00000000..00d5892e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsObsoleteAString_h___
+#define nsObsoleteAString_h___
+
+/*
+ STRING INTERNALS
+
+ This file defines nsObsoleteAString and nsObsoleteACString. These are
+ abstract classes (interfaces), containing only virtual functions
+ corresponding to the FROZEN nsA[C]String classes. They exist to provide
+ the new non-abstract nsA[C]String classes with a mechanism to maintain
+ backwards binary compatability.
+
+ From a binary point-of-view, the new nsA[C]String classes appear to have a
+ vtable pointer to the vtable of nsObsoleteA[C]StringThunk.
+ nsObsoleteA[C]StringThunk is a subclass of nsObsoleteA[C]String that serves
+ as a simple bridge between the virtual functions that make up the FROZEN
+ nsA[C]String contract and the new ns[C]Substring, which is now our only
+ subclass of nsA[C]String.
+
+ The methods on the new nsA[C]String are now all non-virtual. This reduces
+ codesize at the callsite, and reduces the number of memory dereferences and
+ jumps required to invoke a method on nsA[C]String. The result is improved
+ performance and reduced codesize. However, to maintain binary
+ compatibility, each method on nsA[C]String must check the value of its
+ vtable to determine if it corresponds to the built-in implementation of
+ nsObsoleteA[C]String (i.e., the address of the canonical vtable). If it
+ does, then the vtable can be ignored, and the nsA[C]String object (i.e.,
+ |this|) can be cast to ns[C]Substring directly. In which case, the
+ nsA[C]String methods can be satisfied by invoking the corresponding methods
+ directly on ns[C]Substring. If the vtable address does not correspond to
+ the built-in implementation, then the virtual functions on
+ nsObsoleteA[C]String must be invoked instead.
+
+ So, if a nsA[C]String reference corresponds to an external implementation
+ (such as the old nsEmbed[C]String that shipped with previous versions of
+ Mozilla), then methods invoked on that nsA[C]String will still act like
+ virtual function calls. This ensures binary compatibility while avoiding
+ virtual function calls in most cases.
+
+ Finally, nsObsoleteA[C]String (i.e., the FROZEN nsA[C]String vtable) is
+ now a DEPRECATED interface. See nsStringAPI.h and nsEmbedString.h for
+ the new preferred way to access nsA[C]String references in an external
+ component or Gecko embedding application.
+ */
+
+#ifndef nsStringFwd_h___
+#include "nsStringFwd.h"
+#endif
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+ // declare nsObsoleteAString
+#include "string-template-def-unichar.h"
+#include "nsTObsoleteAString.h"
+#include "string-template-undef.h"
+
+ // declare nsObsoleteACString
+#include "string-template-def-char.h"
+#include "nsTObsoleteAString.h"
+#include "string-template-undef.h"
+
+#endif // !defined(nsObsoleteAString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h b/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h
new file mode 100644
index 00000000..3f3d04d3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsPrintfCString_h___
+#define nsPrintfCString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+
+ /**
+ * |nsPrintfCString| lets you use a formated |printf| string as an |const nsACString|.
+ *
+ * myCStr += nsPrintfCString("%f", 13.917);
+ * // ...a general purpose substitute for |AppendFloat|
+ *
+ * For longer patterns, you'll want to use the constructor that takes a length
+ *
+ * nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1);
+ *
+ * Exceding the default size (which you must specify in the constructor, it is not determined)
+ * causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is
+ * cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs).
+ * This class is intended to be useful for numbers and short
+ * strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no
+ * wide version of this class, since wide |printf| is not generally available. That means
+ * to get a wide version of your formatted data, you must, e.g.,
+ *
+ * CopyASCIItoUTF16(nsPrintfCString("%f", 13.917"), myStr);
+ *
+ * That's another good reason to avoid this class for anything but numbers ... as strings can be
+ * much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|.
+ */
+
+class NS_COM nsPrintfCString : public nsCString
+ {
+ typedef nsCString string_type;
+
+ enum { kLocalBufferSize=15 };
+ // ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask)
+ // pinkerton suggests 7. We should measure and decide what's appropriate
+
+ public:
+ // XXX don't these need to be declared CDECL ??
+ explicit nsPrintfCString( const char_type* format, ... );
+ nsPrintfCString( size_type n, const char_type* format, ...);
+
+ private:
+ char_type mLocalBuffer[ kLocalBufferSize + 1 ];
+ };
+
+#endif // !defined(nsPrintfCString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h b/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h
new file mode 100644
index 00000000..b98aa1a2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsPromiseFlatString_h___
+#define nsPromiseFlatString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+ // declare nsPromiseFlatString
+#include "string-template-def-unichar.h"
+#include "nsTPromiseFlatString.h"
+#include "string-template-undef.h"
+
+ // declare nsPromiseFlatCString
+#include "string-template-def-char.h"
+#include "nsTPromiseFlatString.h"
+#include "string-template-undef.h"
+
+#endif /* !defined(nsPromiseFlatString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h b/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h
new file mode 100644
index 00000000..13f94c09
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h
@@ -0,0 +1,370 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Johnny Stenbeck <jst@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsReadableUtils_h___
+#define nsReadableUtils_h___
+
+ /**
+ * I guess all the routines in this file are all mis-named.
+ * According to our conventions, they should be |NS_xxx|.
+ */
+
+#ifndef nsAString_h___
+#include "nsAString.h"
+#endif
+
+inline size_t Distance( const nsReadingIterator<PRUnichar>& start, const nsReadingIterator<PRUnichar>& end )
+ {
+ return end.get() - start.get();
+ }
+inline size_t Distance( const nsReadingIterator<char>& start, const nsReadingIterator<char>& end )
+ {
+ return end.get() - start.get();
+ }
+
+NS_COM void LossyCopyUTF16toASCII( const nsAString& aSource, nsACString& aDest );
+NS_COM void CopyASCIItoUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void LossyCopyUTF16toASCII( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void CopyASCIItoUTF16( const char* aSource, nsAString& aDest );
+
+NS_COM void CopyUTF16toUTF8( const nsAString& aSource, nsACString& aDest );
+NS_COM void CopyUTF8toUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void CopyUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void CopyUTF8toUTF16( const char* aSource, nsAString& aDest );
+
+NS_COM void LossyAppendUTF16toASCII( const nsAString& aSource, nsACString& aDest );
+NS_COM void AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void LossyAppendUTF16toASCII( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void AppendASCIItoUTF16( const char* aSource, nsAString& aDest );
+
+NS_COM void AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest );
+NS_COM void AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void AppendUTF8toUTF16( const char* aSource, nsAString& aDest );
+
+// Backward compatibility
+inline
+NS_COM void CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest )
+{ LossyCopyUTF16toASCII(aSource, aDest); }
+inline
+NS_COM void CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest )
+{ CopyASCIItoUTF16(aSource, aDest); }
+
+ /**
+ * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
+ * Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
+ * This conversion is not well defined; but it reproduces legacy string behavior.
+ * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource a 16-bit wide string
+ * @return a new |char| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM char* ToNewCString( const nsAString& aSource );
+
+
+ /**
+ * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
+ * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource an 8-bit wide string
+ * @return a new |char| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM char* ToNewCString( const nsACString& aSource );
+
+ /**
+ * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with
+ * |nsMemory::Free|.
+ * Performs an encoding conversion from a UTF-16 string to a UTF-8 string
+ * copying |aSource| to your new buffer.
+ * The new buffer is zero-terminated, but that may not help you if |aSource|
+ * contains embedded nulls.
+ *
+ * @param aSource a UTF-16 string (made of PRUnichar's)
+ * @param aUTF8Count the number of 8-bit units that was returned
+ * @return a new |char| buffer you must free with |nsMemory::Free|.
+ */
+
+NS_COM char* ToNewUTF8String( const nsAString& aSource, PRUint32 *aUTF8Count = nsnull );
+
+
+ /**
+ * Returns a new |PRUnichar| buffer containing a zero-terminated copy of
+ * |aSource|.
+ *
+ * Allocates and returns a new |PRUnichar| buffer which you must free with
+ * |nsMemory::Free|.
+ * The new buffer is zero-terminated, but that may not help you if |aSource|
+ * contains embedded nulls.
+ *
+ * @param aSource a UTF-16 string
+ * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM PRUnichar* ToNewUnicode( const nsAString& aSource );
+
+
+ /**
+ * Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |PRUnichar| buffer which you must free with |nsMemory::Free|.
+ * Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer.
+ * This conversion is not well defined; but it reproduces legacy string behavior.
+ * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource an 8-bit wide string (a C-string, NOT UTF-8)
+ * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM PRUnichar* ToNewUnicode( const nsACString& aSource );
+
+ /**
+ * Returns a new |PRUnichar| buffer containing a zero-terminated copy
+ * of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with
+ * |nsMemory::Free|. Performs an encoding conversion from UTF-8 to UTF-16
+ * while copying |aSource| to your new buffer. This conversion is well defined
+ * for a valid UTF-8 string. The new buffer is zero-terminated, but that
+ * may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource an 8-bit wide string, UTF-8 encoded
+ * @param aUTF16Count the number of 16-bit units that was returned
+ * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
+ * (UTF-16 encoded)
+ */
+NS_COM PRUnichar* UTF8ToNewUnicode( const nsACString& aSource, PRUint32 *aUTF16Count = nsnull );
+
+ /**
+ * Copies |aLength| 16-bit code units from the start of |aSource| to the
+ * |PRUnichar| buffer |aDest|.
+ *
+ * After this operation |aDest| is not null terminated.
+ *
+ * @param aSource a UTF-16 string
+ * @param aSrcOffset start offset in the source string
+ * @param aDest a |PRUnichar| buffer
+ * @param aLength the number of 16-bit code units to copy
+ * @return pointer to destination buffer - identical to |aDest|
+ */
+NS_COM PRUnichar* CopyUnicodeTo( const nsAString& aSource,
+ PRUint32 aSrcOffset,
+ PRUnichar* aDest,
+ PRUint32 aLength );
+
+
+ /**
+ * Copies 16-bit characters between iterators |aSrcStart| and
+ * |aSrcEnd| to the writable string |aDest|. Similar to the
+ * |nsString::Mid| method.
+ *
+ * After this operation |aDest| is not null terminated.
+ *
+ * @param aSrcStart start source iterator
+ * @param aSrcEnd end source iterator
+ * @param aDest destination for the copy
+ */
+NS_COM void CopyUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest );
+
+ /**
+ * Appends 16-bit characters between iterators |aSrcStart| and
+ * |aSrcEnd| to the writable string |aDest|.
+ *
+ * After this operation |aDest| is not null terminated.
+ *
+ * @param aSrcStart start source iterator
+ * @param aSrcEnd end source iterator
+ * @param aDest destination for the copy
+ */
+NS_COM void AppendUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest );
+
+ /**
+ * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
+ *
+ * @param aString a 16-bit wide string to scan
+ */
+NS_COM PRBool IsASCII( const nsAString& aString );
+
+ /**
+ * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
+ *
+ * @param aString a 8-bit wide string to scan
+ */
+NS_COM PRBool IsASCII( const nsACString& aString );
+
+
+ /**
+ * Returns |PR_TRUE| if |aString| is a valid UTF-8 string.
+ * XXX This is not bullet-proof and nor an all-purpose UTF-8 validator.
+ * It is mainly written to replace and roughly equivalent to
+ *
+ * str.Equals(NS_ConvertUTF16toUTF8(NS_ConvertUTF8toUTF16(str)))
+ *
+ * (see bug 191541)
+ * As such, it does not check for non-UTF-8 7bit encodings such as
+ * ISO-2022-JP and HZ. However, it filters out UTF-8 representation
+ * of surrogate codepoints and non-characters ( 0xFFFE and 0xFFFF
+ * in planes 0 through 16.) as well as overlong UTF-8 sequences.
+ * Also note that it regards UTF-8 sequences corresponding to
+ * codepoints above 0x10FFFF as invalid in accordance with
+ * http://www.ietf.org/internet-drafts/draft-yergeau-rfc2279bis-04.txt
+ *
+ * @param aString an 8-bit wide string to scan
+ */
+NS_COM PRBool IsUTF8( const nsACString& aString );
+
+
+ /**
+ * Converts case in place in the argument string.
+ */
+NS_COM void ToUpperCase( nsACString& );
+
+NS_COM void ToLowerCase( nsACString& );
+
+NS_COM void ToUpperCase( nsCSubstring& );
+
+NS_COM void ToLowerCase( nsCSubstring& );
+
+ /**
+ * Converts case from string aSource to aDest.
+ */
+NS_COM void ToUpperCase( const nsACString& aSource, nsACString& aDest );
+
+NS_COM void ToLowerCase( const nsACString& aSource, nsACString& aDest );
+
+ /**
+ * Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|.
+ *
+ * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
+ * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
+ *
+ * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
+ * If we need something faster, then we can implement that later.
+ */
+
+NS_COM PRBool FindInReadable( const nsAString& aPattern, nsAString::const_iterator&, nsAString::const_iterator&, const nsStringComparator& = nsDefaultStringComparator() );
+NS_COM PRBool FindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator&, const nsCStringComparator& = nsDefaultCStringComparator() );
+
+/* sometimes we don't care about where the string was, just that we
+ * found it or not */
+inline PRBool FindInReadable( const nsAString& aPattern, const nsAString& aSource, const nsStringComparator& compare = nsDefaultStringComparator() )
+{
+ nsAString::const_iterator start, end;
+ aSource.BeginReading(start);
+ aSource.EndReading(end);
+ return FindInReadable(aPattern, start, end, compare);
+}
+
+inline PRBool FindInReadable( const nsACString& aPattern, const nsACString& aSource, const nsCStringComparator& compare = nsDefaultCStringComparator() )
+{
+ nsACString::const_iterator start, end;
+ aSource.BeginReading(start);
+ aSource.EndReading(end);
+ return FindInReadable(aPattern, start, end, compare);
+}
+
+
+NS_COM PRBool CaseInsensitiveFindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator& );
+
+ /**
+ * Finds the rightmost occurance of |aPattern|
+ * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
+ * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
+ *
+ * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
+ * If we need something faster, then we can implement that later.
+ */
+NS_COM PRBool RFindInReadable( const nsAString& aPattern, nsAString::const_iterator&, nsAString::const_iterator&, const nsStringComparator& = nsDefaultStringComparator() );
+NS_COM PRBool RFindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator&, const nsCStringComparator& = nsDefaultCStringComparator() );
+
+ /**
+ * Finds the leftmost occurance of |aChar|, if any in the range
+ * |aSearchStart|..|aSearchEnd|.
+ *
+ * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to
+ * point to the match. If no match was found, returns |PR_FALSE| and
+ * makes |aSearchStart == aSearchEnd|.
+ */
+NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsAString::const_iterator& aSearchStart, const nsAString::const_iterator& aSearchEnd );
+NS_COM PRBool FindCharInReadable( char aChar, nsACString::const_iterator& aSearchStart, const nsACString::const_iterator& aSearchEnd );
+
+ /**
+ * Finds the number of occurences of |aChar| in the string |aStr|
+ */
+NS_COM PRUint32 CountCharInReadable( const nsAString& aStr,
+ PRUnichar aChar );
+NS_COM PRUint32 CountCharInReadable( const nsACString& aStr,
+ char aChar );
+
+NS_COM PRBool
+StringBeginsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator =
+ nsDefaultStringComparator() );
+NS_COM PRBool
+StringBeginsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator =
+ nsDefaultCStringComparator() );
+NS_COM PRBool
+StringEndsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator =
+ nsDefaultStringComparator() );
+NS_COM PRBool
+StringEndsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator =
+ nsDefaultCStringComparator() );
+
+NS_COM PRUint32 HashString( const nsAString& aStr );
+NS_COM PRUint32 HashString( const nsACString& aStr );
+
+NS_COM const nsAFlatString& EmptyString();
+NS_COM const nsAFlatCString& EmptyCString();
+
+
+#endif // !defined(nsReadableUtils_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsString.h b/src/libs/xpcom18a4/xpcom/string/public/nsString.h
new file mode 100644
index 00000000..67376d19
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsString.h
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsString_h___
+#define nsString_h___
+
+
+#ifndef nsSubstring_h___
+#include "nsSubstring.h"
+#endif
+
+#ifndef nsDependentSubstring_h___
+#include "nsDependentSubstring.h"
+#endif
+
+#ifndef nsReadableUtils_h___
+#include "nsReadableUtils.h"
+#endif
+
+#include NEW_H
+
+ // enable support for the obsolete string API if not explicitly disabled
+#ifndef MOZ_STRING_WITH_OBSOLETE_API
+#define MOZ_STRING_WITH_OBSOLETE_API 1
+#endif
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+ // radix values for ToInteger/AppendInt
+#define kRadix10 (10)
+#define kRadix16 (16)
+#define kAutoDetect (100)
+#define kRadixUnknown (kAutoDetect+1)
+#define IGNORE_CASE (PR_TRUE)
+#endif
+
+
+ // declare nsString, et. al.
+#include "string-template-def-unichar.h"
+#include "nsTString.h"
+#include "string-template-undef.h"
+
+ // declare nsCString, et. al.
+#include "string-template-def-char.h"
+#include "nsTString.h"
+#include "string-template-undef.h"
+
+
+ /**
+ * A helper class that converts a UTF-16 string to ASCII in a lossy manner
+ */
+class NS_LossyConvertUTF16toASCII : public nsCAutoString
+ {
+ public:
+ explicit
+ NS_LossyConvertUTF16toASCII( const PRUnichar* aString )
+ {
+ LossyAppendUTF16toASCII(aString, *this);
+ }
+
+ NS_LossyConvertUTF16toASCII( const PRUnichar* aString, PRUint32 aLength )
+ {
+ LossyAppendUTF16toASCII(Substring(aString, aString + aLength), *this);
+ }
+
+ explicit
+ NS_LossyConvertUTF16toASCII( const nsAString& aString )
+ {
+ LossyAppendUTF16toASCII(aString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_LossyConvertUTF16toASCII( char );
+ };
+
+
+class NS_ConvertASCIItoUTF16 : public nsAutoString
+ {
+ public:
+ explicit
+ NS_ConvertASCIItoUTF16( const char* aCString )
+ {
+ AppendASCIItoUTF16(aCString, *this);
+ }
+
+ NS_ConvertASCIItoUTF16( const char* aCString, PRUint32 aLength )
+ {
+ AppendASCIItoUTF16(Substring(aCString, aCString + aLength), *this);
+ }
+
+ explicit
+ NS_ConvertASCIItoUTF16( const nsACString& aCString )
+ {
+ AppendASCIItoUTF16(aCString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_ConvertASCIItoUTF16( PRUnichar );
+ };
+
+
+ /**
+ * A helper class that converts a UTF-16 string to UTF-8
+ */
+class NS_ConvertUTF16toUTF8 : public nsCAutoString
+ {
+ public:
+ explicit
+ NS_ConvertUTF16toUTF8( const PRUnichar* aString )
+ {
+ AppendUTF16toUTF8(aString, *this);
+ }
+
+ NS_ConvertUTF16toUTF8( const PRUnichar* aString, PRUint32 aLength )
+ {
+ AppendUTF16toUTF8(Substring(aString, aString + aLength), *this);
+ }
+
+ explicit
+ NS_ConvertUTF16toUTF8( const nsAString& aString )
+ {
+ AppendUTF16toUTF8(aString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_ConvertUTF16toUTF8( char );
+ };
+
+
+class NS_ConvertUTF8toUTF16 : public nsAutoString
+ {
+ public:
+ explicit
+ NS_ConvertUTF8toUTF16( const char* aCString )
+ {
+ AppendUTF8toUTF16(aCString, *this);
+ }
+
+ NS_ConvertUTF8toUTF16( const char* aCString, PRUint32 aLength )
+ {
+ AppendUTF8toUTF16(Substring(aCString, aCString + aLength), *this);
+ }
+
+ explicit
+ NS_ConvertUTF8toUTF16( const nsACString& aCString )
+ {
+ AppendUTF8toUTF16(aCString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_ConvertUTF8toUTF16( PRUnichar );
+ };
+
+
+// the following are included/declared for backwards compatibility
+
+typedef NS_ConvertUTF16toUTF8 NS_ConvertUCS2toUTF8;
+typedef NS_LossyConvertUTF16toASCII NS_LossyConvertUCS2toASCII;
+typedef NS_ConvertASCIItoUTF16 NS_ConvertASCIItoUCS2;
+typedef NS_ConvertUTF8toUTF16 NS_ConvertUTF8toUCS2;
+typedef nsAutoString nsVoidableString;
+
+#ifndef nsDependentString_h___
+#include "nsDependentString.h"
+#endif
+
+#ifndef nsLiteralString_h___
+#include "nsLiteralString.h"
+#endif
+
+#ifndef nsPromiseFlatString_h___
+#include "nsPromiseFlatString.h"
+#endif
+
+// need to include these for backwards compatibility
+#include "nsMemory.h"
+#include <string.h>
+#include <stdio.h>
+#include "plhash.h"
+
+inline PRInt32 MinInt(PRInt32 x, PRInt32 y)
+ {
+ return NS_MIN(x, y);
+ }
+
+inline PRInt32 MaxInt(PRInt32 x, PRInt32 y)
+ {
+ return NS_MAX(x, y);
+ }
+
+/**
+ * Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
+ *
+ * Return the given buffer to the heap manager. Calls allocator::Free()
+ */
+inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
+inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
+
+#endif // !defined(nsString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h
new file mode 100644
index 00000000..cc0818b6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h
@@ -0,0 +1,853 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsStringAPI_h__
+#define nsStringAPI_h__
+
+/**
+ * nsStringAPI.h
+ *
+ * This file describes a minimal API for working with XPCOM's abstract
+ * string classes. It divorces the consumer from having any run-time
+ * dependency on the implementation details of the abstract string types.
+ */
+
+#include "nscore.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_CStringContainerInit VBoxNsxpNS_CStringContainerInit
+#define NS_CStringContainerFinish VBoxNsxpNS_CStringContainerFinish
+#define NS_CStringCloneData VBoxNsxpNS_CStringCloneData
+#define NS_CStringCopy VBoxNsxpNS_CStringCopy
+#define NS_CStringGetData VBoxNsxpNS_CStringGetData
+#define NS_CStringSetData VBoxNsxpNS_CStringSetData
+#define NS_CStringSetDataRange VBoxNsxpNS_CStringSetDataRange
+#define NS_UTF16ToCString VBoxNsxpNS_UTF16ToCString
+#define NS_CStringToUTF16 VBoxNsxpNS_CStringToUTF16
+#define NS_StringContainerInit VBoxNsxpNS_StringContainerInit
+#define NS_StringContainerFinish VBoxNsxpNS_StringContainerFinish
+#define NS_StringCloneData VBoxNsxpNS_StringCloneData
+#define NS_StringCopy VBoxNsxpNS_StringCopy
+#define NS_StringGetData VBoxNsxpNS_StringGetData
+#define NS_StringSetData VBoxNsxpNS_StringSetData
+#define NS_StringSetDataRange VBoxNsxpNS_StringSetDataRange
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+#define NS_STRINGAPI(x) extern "C" NS_COM x
+
+/* The base string types */
+class nsAString;
+class nsACString;
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * nsStringContainer
+ *
+ * This is an opaque data type that is large enough to hold the canonical
+ * implementation of nsAString. The binary structure of this class is an
+ * implementation detail.
+ *
+ * The string data stored in a string container is always single fragment
+ * and null-terminated.
+ *
+ * Typically, string containers are allocated on the stack for temporary
+ * use. However, they can also be malloc'd if necessary. In either case,
+ * a string container is not useful until it has been initialized with a
+ * call to NS_StringContainerInit. The following example shows how to use
+ * a string container to call a function that takes a |nsAString &| out-param.
+ *
+ * NS_METHOD GetBlah(nsAString &aBlah);
+ *
+ * nsresult MyCode()
+ * {
+ * nsresult rv;
+ *
+ * nsStringContainer sc;
+ * rv = NS_StringContainerInit(sc);
+ * if (NS_FAILED(rv))
+ * return rv;
+ *
+ * rv = GetBlah(sc);
+ * if (NS_SUCCEEDED(rv))
+ * {
+ * const PRUnichar *data;
+ * NS_StringGetData(sc, &data);
+ * //
+ * // |data| now points to the result of the GetBlah function
+ * //
+ * }
+ *
+ * NS_StringContainerFinish(sc);
+ * return rv;
+ * }
+ *
+ * The following example show how to use a string container to pass a string
+ * parameter to a function taking a |const nsAString &| in-param.
+ *
+ * NS_METHOD SetBlah(const nsAString &aBlah);
+ *
+ * nsresult MyCode()
+ * {
+ * nsresult rv;
+ *
+ * nsStringContainer sc;
+ * rv = NS_StringContainerInit(sc);
+ * if (NS_FAILED(rv))
+ * return rv;
+ *
+ * const PRUnichar kData[] = {'x','y','z','\0'};
+ * rv = NS_StringSetData(sc, kData, sizeof(kData)/2 - 1);
+ * if (NS_SUCCEEDED(rv))
+ * rv = SetBlah(sc);
+ *
+ * NS_StringContainerFinish(sc);
+ * return rv;
+ * }
+ */
+class nsStringContainer;
+
+/**
+ * NS_StringContainerInit
+ *
+ * @param aContainer string container reference
+ * @return NS_OK if string container successfully initialized
+ *
+ * This function may allocate additional memory for aContainer. When
+ * aContainer is no longer needed, NS_StringContainerFinish should be called.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringContainerInit(nsStringContainer &aContainer);
+
+/**
+ * NS_StringContainerFinish
+ *
+ * @param aContainer string container reference
+ *
+ * This function frees any memory owned by aContainer.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(void)
+NS_StringContainerFinish(nsStringContainer &aContainer);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * NS_StringGetData
+ *
+ * This function returns a const character pointer to the string's internal
+ * buffer, the length of the string, and a boolean value indicating whether
+ * or not the buffer is null-terminated.
+ *
+ * @param aStr abstract string reference
+ * @param aData out param that will hold the address of aStr's
+ * internal buffer
+ * @param aTerminated if non-null, this out param will be set to indicate
+ * whether or not aStr's internal buffer is null-
+ * terminated
+ * @return length of aStr's internal buffer
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(PRUint32)
+NS_StringGetData
+ (const nsAString &aStr, const PRUnichar **aData,
+ PRBool *aTerminated = nsnull);
+
+/**
+ * NS_StringCloneData
+ *
+ * This function returns a null-terminated copy of the string's
+ * internal buffer.
+ *
+ * @param aStr abstract string reference
+ * @return null-terminated copy of the string's internal buffer
+ * (it must be free'd using using nsMemory::Free)
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(PRUnichar *)
+NS_StringCloneData
+ (const nsAString &aStr);
+
+/**
+ * NS_StringSetData
+ *
+ * This function copies aData into aStr.
+ *
+ * @param aStr abstract string reference
+ * @param aData character buffer
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringSetData
+ (nsAString &aStr, const PRUnichar *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_StringSetDataRange
+ *
+ * This function copies aData into a section of aStr. As a result it can be
+ * used to insert new characters into the string.
+ *
+ * @param aStr abstract string reference
+ * @param aCutOffset starting index where the string's existing data
+ * is to be overwritten (pass PR_UINT32_MAX to cause
+ * aData to be appended to the end of aStr, in which
+ * case the value of aCutLength is ignored).
+ * @param aCutLength number of characters to overwrite starting at
+ * aCutOffset (pass PR_UINT32_MAX to overwrite until the
+ * end of aStr).
+ * @param aData character buffer (pass null to cause this function
+ * to simply remove the "cut" range)
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringSetDataRange
+ (nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength,
+ const PRUnichar *aData, PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_StringCopy
+ *
+ * This function makes aDestStr have the same value as aSrcStr. It is
+ * provided as an optimization.
+ *
+ * @param aDestStr abstract string reference to be modified
+ * @param aSrcStr abstract string reference containing source string
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aDestStr after copying
+ * data from aSrcStr. The behavior depends on the implementation of the
+ * abstract string, aDestStr. If aDestStr is a reference to a
+ * nsStringContainer, then its data will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringCopy
+ (nsAString &aDestStr, const nsAString &aSrcStr);
+
+/**
+ * NS_StringAppendData
+ *
+ * This function appends data to the existing value of aStr.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_StringAppendData(nsAString &aStr, const PRUnichar *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_StringSetDataRange(aStr, PR_UINT32_MAX, 0, aData, aDataLength);
+}
+
+/**
+ * NS_StringInsertData
+ *
+ * This function inserts data into the existing value of aStr at the specified
+ * offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aOffset specifies where in the string to insert aData
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_StringInsertData(nsAString &aStr, PRUint32 aOffset, const PRUnichar *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_StringSetDataRange(aStr, aOffset, 0, aData, aDataLength);
+}
+
+/**
+ * NS_StringCutData
+ *
+ * This function shortens the existing value of aStr, by removing characters
+ * at the specified offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aCutOffset specifies where in the string to insert aData
+ * @param aCutLength number of characters to remove
+ * @return NS_OK if function succeeded
+ */
+inline NS_HIDDEN_(nsresult)
+NS_StringCutData(nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
+{
+ return NS_StringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * nsCStringContainer
+ *
+ * This is an opaque data type that is large enough to hold the canonical
+ * implementation of nsACString. The binary structure of this class is an
+ * implementation detail.
+ *
+ * The string data stored in a string container is always single fragment
+ * and null-terminated.
+ *
+ * @see nsStringContainer for use cases and further documentation.
+ */
+class nsCStringContainer;
+
+/**
+ * NS_CStringContainerInit
+ *
+ * @param aContainer string container reference
+ * @return NS_OK if string container successfully initialized
+ *
+ * This function may allocate additional memory for aContainer. When
+ * aContainer is no longer needed, NS_CStringContainerFinish should be called.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringContainerInit(nsCStringContainer &aContainer);
+
+/**
+ * NS_CStringContainerFinish
+ *
+ * @param aContainer string container reference
+ *
+ * This function frees any memory owned by aContainer.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(void)
+NS_CStringContainerFinish(nsCStringContainer &aContainer);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * NS_CStringGetData
+ *
+ * This function returns a const character pointer to the string's internal
+ * buffer, the length of the string, and a boolean value indicating whether
+ * or not the buffer is null-terminated.
+ *
+ * @param aStr abstract string reference
+ * @param aData out param that will hold the address of aStr's
+ * internal buffer
+ * @param aTerminated if non-null, this out param will be set to indicate
+ * whether or not aStr's internal buffer is null-
+ * terminated
+ * @return length of aStr's internal buffer
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(PRUint32)
+NS_CStringGetData
+ (const nsACString &aStr, const char **aData,
+ PRBool *aTerminated = nsnull);
+
+/**
+ * NS_CStringCloneData
+ *
+ * This function returns a null-terminated copy of the string's
+ * internal buffer.
+ *
+ * @param aStr abstract string reference
+ * @return null-terminated copy of the string's internal buffer
+ * (it must be free'd using using nsMemory::Free)
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(char *)
+NS_CStringCloneData
+ (const nsACString &aStr);
+
+/**
+ * NS_CStringSetData
+ *
+ * This function copies aData into aStr.
+ *
+ * @param aStr abstract string reference
+ * @param aData character buffer
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringSetData
+ (nsACString &aStr, const char *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_CStringSetDataRange
+ *
+ * This function copies aData into a section of aStr. As a result it can be
+ * used to insert new characters into the string.
+ *
+ * @param aStr abstract string reference
+ * @param aCutOffset starting index where the string's existing data
+ * is to be overwritten (pass PR_UINT32_MAX to cause
+ * aData to be appended to the end of aStr, in which
+ * case the value of aCutLength is ignored).
+ * @param aCutLength number of characters to overwrite starting at
+ * aCutOffset (pass PR_UINT32_MAX to overwrite until the
+ * end of aStr).
+ * @param aData character buffer (pass null to cause this function
+ * to simply remove the "cut" range)
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringSetDataRange
+ (nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength,
+ const char *aData, PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_CStringCopy
+ *
+ * This function makes aDestStr have the same value as aSrcStr. It is
+ * provided as an optimization.
+ *
+ * @param aDestStr abstract string reference to be modified
+ * @param aSrcStr abstract string reference containing source string
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aDestStr after copying
+ * data from aSrcStr. The behavior depends on the implementation of the
+ * abstract string, aDestStr. If aDestStr is a reference to a
+ * nsStringContainer, then its data will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringCopy
+ (nsACString &aDestStr, const nsACString &aSrcStr);
+
+/**
+ * NS_CStringAppendData
+ *
+ * This function appends data to the existing value of aStr.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_CStringAppendData(nsACString &aStr, const char *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_CStringSetDataRange(aStr, PR_UINT32_MAX, 0, aData, aDataLength);
+}
+
+/**
+ * NS_CStringInsertData
+ *
+ * This function inserts data into the existing value of aStr at the specified
+ * offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aOffset specifies where in the string to insert aData
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_CStringInsertData(nsACString &aStr, PRUint32 aOffset, const char *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_CStringSetDataRange(aStr, aOffset, 0, aData, aDataLength);
+}
+
+/**
+ * NS_CStringCutData
+ *
+ * This function shortens the existing value of aStr, by removing characters
+ * at the specified offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aCutOffset specifies where in the string to insert aData
+ * @param aCutLength number of characters to remove
+ * @return NS_OK if function succeeded
+ */
+inline NS_HIDDEN_(nsresult)
+NS_CStringCutData(nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
+{
+ return NS_CStringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Encodings that can be used with the following conversion routines.
+ */
+enum nsCStringEncoding {
+ /* Conversion between ASCII and UTF-16 assumes that all bytes in the source
+ * string are 7-bit ASCII and can be inflated to UTF-16 by inserting null
+ * bytes. Reverse conversion is done by truncating every other byte. The
+ * conversion may result in loss and/or corruption of information if the
+ * strings do not strictly contain ASCII data. */
+ NS_CSTRING_ENCODING_ASCII = 0,
+
+ /* Conversion between UTF-8 and UTF-16 is non-lossy. */
+ NS_CSTRING_ENCODING_UTF8 = 1,
+
+ /* Conversion from UTF-16 to the native filesystem charset may result in a
+ * loss of information. No attempt is made to protect against data loss in
+ * this case. The native filesystem charset applies to strings passed to
+ * the "Native" method variants on nsIFile and nsILocalFile. */
+ NS_CSTRING_ENCODING_NATIVE_FILESYSTEM = 2
+};
+
+/**
+ * NS_CStringToUTF16
+ *
+ * This function converts the characters in a nsACString to an array of UTF-16
+ * characters, in the platform endianness. The result is stored in a nsAString
+ * object.
+ *
+ * @param aSource abstract string reference containing source string
+ * @param aSrcEncoding character encoding of the source string
+ * @param aDest abstract string reference to hold the result
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringToUTF16(const nsACString &aSource, nsCStringEncoding aSrcEncoding,
+ nsAString &aDest);
+
+/**
+ * NS_UTF16ToCString
+ *
+ * This function converts the UTF-16 characters in a nsAString to a single-byte
+ * encoding. The result is stored in a nsACString object. In some cases this
+ * conversion may be lossy. In such cases, the conversion may succeed with a
+ * return code indicating loss of information. The exact behavior is not
+ * specified at this time.
+ *
+ * @param aSource abstract string reference containing source string
+ * @param aDestEncoding character encoding of the resulting string
+ * @param aDest abstract string reference to hold the result
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_UTF16ToCString(const nsAString &aSource, nsCStringEncoding aDestEncoding,
+ nsACString &aDest);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Below we define nsAString and nsACString. The "_external" suffix is an
+ * implementation detail. nsAString_external is the name of the external
+ * representation of nsAString from the point of view of the Mozilla codebase.
+ * To a user of this API, nsAString_external is exactly nsAString.
+ *
+ * These classes should be treated as abstract classes with unspecified
+ * structure. The inline methods are provided as helper functions around the
+ * C-style API provided above.
+ *
+ * Do not try to mix these definitions of nsAString and nsACString with the
+ * internal definition of these classes from nsAString.h in the Mozilla tree.
+ */
+
+#ifndef NS_STRINGAPI_IMPL
+#define nsAString_external nsAString
+#define nsACString_external nsACString
+#endif
+
+class nsAString_external
+{
+#ifndef NS_STRINGAPI_IMPL
+
+public:
+ typedef PRUnichar char_type;
+ typedef nsAString_external self_type;
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ NS_HIDDEN_(const char_type*) BeginReading() const
+ {
+ const char_type *data;
+ NS_StringGetData(*this, &data);
+ return data;
+ }
+
+ NS_HIDDEN_(const char_type*) EndReading() const
+ {
+ const char_type *data;
+ PRUint32 len = NS_StringGetData(*this, &data);
+ return data + len;
+ }
+
+ NS_HIDDEN_(size_type) Length() const
+ {
+ const char_type* data;
+ return NS_StringGetData(*this, &data);
+ }
+
+ NS_HIDDEN_(void) Assign(const self_type& aString)
+ {
+ NS_StringCopy(*this, aString);
+ }
+ NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+ {
+ NS_StringSetData(*this, aData, aLength);
+ }
+ NS_HIDDEN_(void) Assign(char_type aChar)
+ {
+ NS_StringSetData(*this, &aChar, 1);
+ }
+
+ NS_HIDDEN_(self_type&) operator=(const self_type& aString) { Assign(aString); return *this; }
+ NS_HIDDEN_(self_type&) operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ NS_HIDDEN_(self_type&) operator=(char_type aChar) { Assign(aChar); return *this; }
+
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) )
+ {
+ NS_StringSetDataRange(*this, cutStart, cutLength, data, length);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, char_type c )
+ {
+ Replace(cutStart, cutLength, &c, 1);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const self_type& readable )
+ {
+ const char_type* data;
+ PRUint32 dataLen = NS_StringGetData(readable, &data);
+ NS_StringSetDataRange(*this, cutStart, cutLength, data, dataLen);
+ }
+
+ NS_HIDDEN_(void) Append( char_type c ) { Replace(size_type(-1), 0, c); }
+ NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) ) { Replace(size_type(-1), 0, data, length); }
+ NS_HIDDEN_(void) Append( const self_type& readable ) { Replace(size_type(-1), 0, readable); }
+
+ NS_HIDDEN_(self_type&) operator+=( char_type c ) { Append(c); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const char_type* data ) { Append(data); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const self_type& readable ) { Append(readable); return *this; }
+
+ NS_HIDDEN_(void) Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
+ NS_HIDDEN_(void) Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
+ NS_HIDDEN_(void) Insert( const self_type& readable, index_type pos ) { Replace(pos, 0, readable); }
+
+ NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); }
+
+#endif // NS_STRINGAPI_IMPL
+
+private:
+ void *v;
+};
+
+class nsACString_external
+{
+#ifndef NS_STRINGAPI_IMPL
+
+public:
+ typedef char char_type;
+ typedef nsACString_external self_type;
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ NS_HIDDEN_(const char_type*) BeginReading() const
+ {
+ const char_type *data;
+ NS_CStringGetData(*this, &data);
+ return data;
+ }
+
+ NS_HIDDEN_(const char_type*) EndReading() const
+ {
+ const char_type *data;
+ PRUint32 len = NS_CStringGetData(*this, &data);
+ return data + len;
+ }
+
+ NS_HIDDEN_(size_type) Length() const
+ {
+ const char_type* data;
+ return NS_CStringGetData(*this, &data);
+ }
+
+ NS_HIDDEN_(void) Assign(const self_type& aString)
+ {
+ NS_CStringCopy(*this, aString);
+ }
+ NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+ {
+ NS_CStringSetData(*this, aData, aLength);
+ }
+ NS_HIDDEN_(void) Assign(char_type aChar)
+ {
+ NS_CStringSetData(*this, &aChar, 1);
+ }
+
+ NS_HIDDEN_(self_type&) operator=(const self_type& aString) { Assign(aString); return *this; }
+ NS_HIDDEN_(self_type&) operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ NS_HIDDEN_(self_type&) operator=(char_type aChar) { Assign(aChar); return *this; }
+
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) )
+ {
+ NS_CStringSetDataRange(*this, cutStart, cutLength, data, length);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, char_type c )
+ {
+ Replace(cutStart, cutLength, &c, 1);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const self_type& readable )
+ {
+ const char_type* data;
+ PRUint32 dataLen = NS_CStringGetData(readable, &data);
+ NS_CStringSetDataRange(*this, cutStart, cutLength, data, dataLen);
+ }
+
+ NS_HIDDEN_(void) Append( char_type c ) { Replace(size_type(-1), 0, c); }
+ NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) ) { Replace(size_type(-1), 0, data, length); }
+ NS_HIDDEN_(void) Append( const self_type& readable ) { Replace(size_type(-1), 0, readable); }
+
+ NS_HIDDEN_(self_type&) operator+=( char_type c ) { Append(c); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const char_type* data ) { Append(data); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const self_type& readable ) { Append(readable); return *this; }
+
+ NS_HIDDEN_(void) Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
+ NS_HIDDEN_(void) Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
+ NS_HIDDEN_(void) Insert( const self_type& readable, index_type pos ) { Replace(pos, 0, readable); }
+
+ NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); }
+
+#endif // NS_STRINGAPI_IMPL
+
+private:
+ void *v;
+};
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Below we define nsStringContainer and nsCStringContainer. These classes
+ * have unspecified structure. In most cases, your code should use
+ * nsEmbedString instead of these classes; however, if you prefer C-style
+ * programming, then look no further...
+ */
+
+class nsStringContainer : public nsAString_external
+{
+private:
+ void *d1;
+ PRUint32 d2;
+ void *d3;
+
+public:
+ nsStringContainer() {} // MSVC6 needs this
+};
+
+class nsCStringContainer : public nsACString_external
+{
+private:
+ void *d1;
+ PRUint32 d2;
+ void *d3;
+
+public:
+ nsCStringContainer() {} // MSVC6 needs this
+};
+
+#endif // nsStringAPI_h__
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h
new file mode 100644
index 00000000..4c664011
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* nsStringFwd.h --- forward declarations for string classes */
+
+#ifndef nsStringFwd_h___
+#define nsStringFwd_h___
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+
+ /**
+ * double-byte (PRUnichar) string types
+ */
+
+class nsAString;
+class nsObsoleteAString;
+class nsSubstring;
+class nsSubstringTuple;
+class nsString;
+class nsAutoString;
+class nsDependentString;
+class nsDependentSubstring;
+class nsPromiseFlatString;
+class nsStringComparator;
+class nsDefaultStringComparator;
+class nsXPIDLString;
+
+
+ /**
+ * single-byte (char) string types
+ */
+
+class nsACString;
+class nsObsoleteACString;
+class nsCSubstring;
+class nsCSubstringTuple;
+class nsCString;
+class nsCAutoString;
+class nsDependentCString;
+class nsDependentCSubstring;
+class nsPromiseFlatCString;
+class nsCStringComparator;
+class nsDefaultCStringComparator;
+class nsXPIDLCString;
+
+
+ /**
+ * typedefs for backwards compatibility
+ */
+
+typedef nsString nsAFlatString;
+typedef nsSubstring nsASingleFragmentString;
+
+typedef nsCString nsAFlatCString;
+typedef nsCSubstring nsASingleFragmentCString;
+
+
+#endif /* !defined(nsStringFwd_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h
new file mode 100644
index 00000000..1848594c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h
@@ -0,0 +1,373 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsStringIterator_h___
+#define nsStringIterator_h___
+
+#ifndef nsCharTraits_h___
+#include "nsCharTraits.h"
+#endif
+
+#ifndef nsAlgorithm_h___
+#include "nsAlgorithm.h"
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+ /**
+ * @see nsTAString
+ */
+
+template <class CharT>
+class nsReadingIterator
+ {
+ public:
+ typedef nsReadingIterator<CharT> self_type;
+ typedef ptrdiff_t difference_type;
+ typedef CharT value_type;
+ typedef const CharT* pointer;
+ typedef const CharT& reference;
+
+ private:
+ friend class nsAString;
+ friend class nsACString;
+ friend class nsSubstring;
+ friend class nsCSubstring;
+
+ // unfortunately, the API for nsReadingIterator requires that the
+ // iterator know its start and end positions. this was needed when
+ // we supported multi-fragment strings, but now it is really just
+ // extra baggage. we should remove mStart and mEnd at some point.
+
+ const CharT* mStart;
+ const CharT* mEnd;
+ const CharT* mPosition;
+
+ public:
+ nsReadingIterator() { }
+ // nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
+ // nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK
+
+ inline void normalize_forward() {}
+ inline void normalize_backward() {}
+
+ pointer
+ start() const
+ {
+ return mStart;
+ }
+
+ pointer
+ end() const
+ {
+ return mEnd;
+ }
+
+ pointer
+ get() const
+ {
+ return mPosition;
+ }
+
+ CharT
+ operator*() const
+ {
+ return *get();
+ }
+
+#if 0
+ // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
+ // don't like this when |CharT| is a type without members.
+ pointer
+ operator->() const
+ {
+ return get();
+ }
+#endif
+
+ self_type&
+ operator++()
+ {
+ ++mPosition;
+ return *this;
+ }
+
+ self_type
+ operator++( int )
+ {
+ self_type result(*this);
+ ++mPosition;
+ return result;
+ }
+
+ self_type&
+ operator--()
+ {
+ --mPosition;
+ return *this;
+ }
+
+ self_type
+ operator--( int )
+ {
+ self_type result(*this);
+ --mPosition;
+ return result;
+ }
+
+ difference_type
+ size_forward() const
+ {
+ return mEnd - mPosition;
+ }
+
+ difference_type
+ size_backward() const
+ {
+ return mPosition - mStart;
+ }
+
+ self_type&
+ advance( difference_type n )
+ {
+ if (n > 0)
+ {
+ difference_type step = NS_MIN(n, size_forward());
+
+ NS_ASSERTION(step>0, "can't advance a reading iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ else if (n < 0)
+ {
+ difference_type step = NS_MAX(n, -size_backward());
+
+ NS_ASSERTION(step<0, "can't advance (backward) a reading iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ return *this;
+ }
+ };
+
+ /**
+ * @see nsTAString
+ */
+
+template <class CharT>
+class nsWritingIterator
+ {
+ public:
+ typedef nsWritingIterator<CharT> self_type;
+ typedef ptrdiff_t difference_type;
+ typedef CharT value_type;
+ typedef CharT* pointer;
+ typedef CharT& reference;
+
+ private:
+ friend class nsAString;
+ friend class nsACString;
+ friend class nsSubstring;
+ friend class nsCSubstring;
+
+ // unfortunately, the API for nsWritingIterator requires that the
+ // iterator know its start and end positions. this was needed when
+ // we supported multi-fragment strings, but now it is really just
+ // extra baggage. we should remove mStart and mEnd at some point.
+
+ CharT* mStart;
+ CharT* mEnd;
+ CharT* mPosition;
+
+ public:
+ nsWritingIterator() { }
+ // nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
+ // nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
+
+ inline void normalize_forward() {}
+ inline void normalize_backward() {}
+
+ pointer
+ start() const
+ {
+ return mStart;
+ }
+
+ pointer
+ end() const
+ {
+ return mEnd;
+ }
+
+ pointer
+ get() const
+ {
+ return mPosition;
+ }
+
+ reference
+ operator*() const
+ {
+ return *get();
+ }
+
+#if 0
+ // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
+ // don't like this when |CharT| is a type without members.
+ pointer
+ operator->() const
+ {
+ return get();
+ }
+#endif
+
+ self_type&
+ operator++()
+ {
+ ++mPosition;
+ return *this;
+ }
+
+ self_type
+ operator++( int )
+ {
+ self_type result(*this);
+ ++mPosition;
+ return result;
+ }
+
+ self_type&
+ operator--()
+ {
+ --mPosition;
+ return *this;
+ }
+
+ self_type
+ operator--( int )
+ {
+ self_type result(*this);
+ --mPosition;
+ return result;
+ }
+
+ difference_type
+ size_forward() const
+ {
+ return mEnd - mPosition;
+ }
+
+ difference_type
+ size_backward() const
+ {
+ return mPosition - mStart;
+ }
+
+ self_type&
+ advance( difference_type n )
+ {
+ if (n > 0)
+ {
+ difference_type step = NS_MIN(n, size_forward());
+
+ NS_ASSERTION(step>0, "can't advance a writing iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ else if (n < 0)
+ {
+ difference_type step = NS_MAX(n, -size_backward());
+
+ NS_ASSERTION(step<0, "can't advance (backward) a writing iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ return *this;
+ }
+
+ PRUint32
+ write( const value_type* s, PRUint32 n )
+ {
+ NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
+
+ nsCharTraits<value_type>::move(mPosition, s, n);
+ advance( difference_type(n) );
+ return n;
+ }
+ };
+
+template <class CharT>
+inline
+PRBool
+operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
+ {
+ return lhs.get() == rhs.get();
+ }
+
+template <class CharT>
+inline
+PRBool
+operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
+ {
+ return lhs.get() != rhs.get();
+ }
+
+
+ //
+ // |nsWritingIterator|s
+ //
+
+template <class CharT>
+inline
+PRBool
+operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
+ {
+ return lhs.get() == rhs.get();
+ }
+
+template <class CharT>
+inline
+PRBool
+operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
+ {
+ return lhs.get() != rhs.get();
+ }
+
+#endif /* !defined(nsStringIterator_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h
new file mode 100644
index 00000000..35a1a568
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsSubstring_h___
+#define nsSubstring_h___
+
+#ifndef nsAString_h___
+#include "nsAString.h"
+#endif
+
+#define kNotFound -1
+
+// If some platform(s) can't handle our template that matches literal strings,
+// then we'll disable it on those platforms.
+#ifndef NS_DISABLE_LITERAL_TEMPLATE
+# if (defined(_MSC_VER) && (_MSC_VER < 1310)) || (defined(__SUNPRO_CC) & (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100))
+# define NS_DISABLE_LITERAL_TEMPLATE
+# endif
+#endif /* !NS_DISABLE_LITERAL_TEMPLATE */
+
+#include <string.h>
+
+ // declare nsSubstring
+#include "string-template-def-unichar.h"
+#include "nsTSubstring.h"
+#include "string-template-undef.h"
+
+
+ // declare nsCSubstring
+#include "string-template-def-char.h"
+#include "nsTSubstring.h"
+#include "string-template-undef.h"
+
+
+#ifndef nsSubstringTuple_h___
+#include "nsSubstringTuple.h"
+#endif
+
+#endif // !defined(nsSubstring_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h b/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h
new file mode 100644
index 00000000..8cf6f803
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsSubstringTuple_h___
+#define nsSubstringTuple_h___
+
+#ifndef nsSubstring_h___
+#include "nsSubstring.h"
+#endif
+
+ // declare nsSubstringTuple
+#include "string-template-def-unichar.h"
+#include "nsTSubstringTuple.h"
+#include "string-template-undef.h"
+
+ // declare nsCSubstringTuple
+#include "string-template-def-char.h"
+#include "nsTSubstringTuple.h"
+#include "string-template-undef.h"
+
+#endif // !defined(nsSubstringTuple_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h
new file mode 100644
index 00000000..93b88443
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h
@@ -0,0 +1,618 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * The base for string comparators
+ */
+class NS_COM nsTStringComparator_CharT
+ {
+ public:
+ typedef CharT char_type;
+
+ nsTStringComparator_CharT() {}
+
+ virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const = 0;
+ virtual int operator()( char_type, char_type ) const = 0;
+ };
+
+
+ /**
+ * The default string comparator (case-sensitive comparision)
+ */
+class NS_COM nsTDefaultStringComparator_CharT
+ : public nsTStringComparator_CharT
+ {
+ public:
+ typedef CharT char_type;
+
+ nsTDefaultStringComparator_CharT() {}
+
+ virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const;
+ virtual int operator()( char_type, char_type ) const;
+ };
+
+
+ /**
+ * nsTAString is the most abstract class in the string hierarchy.
+ *
+ * In its original inception, nsTAString was designed to allow the data
+ * storage for a string to be separated into multiple fragments. This was
+ * intended to enable lazy string flattening or avoid string flattening
+ * altogether in some cases. This abstraction, however, meant that every
+ * single string operation (including simple operations such as IsEmpty() and
+ * BeginReading()) required virtual function calls. A virtual destructor was
+ * also required. This not only meant additional overhead for invoking
+ * string methods but also added to additional codesize at every callsite (to
+ * load the virtual function address).
+ *
+ * Today nsTAString exists mainly for backwards compatibility of the string
+ * API. It is restricted to representing a contiguous array of characters,
+ * where the character array is not necessarily null-terminated. Moreover,
+ * since nsTAString's virtual function table was frozen for Mozilla 1.0,
+ * nsTAString necessarily maintains ABI compatibility with older versions of
+ * Gecko. (nsTObsoleteAString provides that frozen ABI. See
+ * nsObsoleteAString.h for a description of how we solve the ABI
+ * compatibility requirement while eliminating virtual function calls on
+ * nsTAString.)
+ *
+ * XPIDL still generates C++ header files with references to nsTAStrings, so
+ * nsTAString will still be heavily used in real code.
+ *
+ * If the opportunity to break ABI compatibility with Mozilla 1.0 were to
+ * ever arise, our first move should be to make nsTAString equate to
+ * nsTSubstring. This may in fact be an option today for some Gecko-based
+ * products.
+ */
+class nsTAString_CharT
+ {
+ public:
+
+ typedef CharT char_type;
+ typedef nsCharTraits<char_type> char_traits;
+
+ typedef char_traits::incompatible_char_type incompatible_char_type;
+
+ typedef nsTAString_CharT self_type;
+ typedef nsTAString_CharT abstract_string_type;
+ typedef nsTObsoleteAString_CharT obsolete_string_type;
+ typedef nsTSubstring_CharT substring_type;
+ typedef nsTSubstringTuple_CharT substring_tuple_type;
+
+ typedef nsReadingIterator<char_type> const_iterator;
+ typedef nsWritingIterator<char_type> iterator;
+
+ typedef nsTStringComparator_CharT comparator_type;
+
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ public:
+
+ // this acts like a virtual destructor
+ NS_COM NS_FASTCALL ~nsTAString_CharT();
+
+
+ /**
+ * BeginReading/EndReading can be used to get immutable access to the
+ * string's underlying buffer. EndReading returns a pointer to the
+ * end of the string's buffer. nsReadableUtils.h provides a collection
+ * of utility functions that work with these iterators.
+ */
+
+ inline const_iterator& BeginReading( const_iterator& iter ) const
+ {
+ size_type len = GetReadableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ inline const_iterator& EndReading( const_iterator& iter ) const
+ {
+ size_type len = GetReadableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+
+ /**
+ * BeginWriting/EndWriting can be used to get mutable access to the
+ * string's underlying buffer. EndWriting returns a pointer to the
+ * end of the string's buffer. This iterator API cannot be used to
+ * grow a buffer. Use SetLength to resize the string's buffer.
+ */
+
+ inline iterator& BeginWriting( iterator& iter )
+ {
+ size_type len = GetWritableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ inline iterator& EndWriting( iterator& iter )
+ {
+ size_type len = GetWritableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+
+ /**
+ * Length checking functions. IsEmpty is a helper function to avoid
+ * writing code like: |if (str.Length() == 0)|
+ */
+
+ NS_COM size_type NS_FASTCALL Length() const;
+ PRBool IsEmpty() const { return Length() == 0; }
+
+
+ /**
+ * String equality tests. Pass a string comparator if you want to
+ * control how the strings are compared. By default, a binary
+ * "case-sensitive" comparision is performed.
+ */
+
+ NS_COM PRBool NS_FASTCALL Equals( const self_type& ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const char_type* ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const char_type*, const comparator_type& ) const;
+
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when you know the
+ * length of 'data'.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const;
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when 'data' is
+ * null-terminated.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data ) const;
+
+ // EqualsLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable.
+ // The template trick to acquire the array length at compile time without
+ // using a macro is due to Corey Kosak, with much thanks.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool EqualsLiteral( const char* str ) const
+ {
+ return EqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool EqualsLiteral( const char (&str)[N] ) const
+ {
+ return EqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool EqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return EqualsASCII(s, N-1);
+ }
+#endif
+
+ // The LowerCaseEquals methods compare the lower case version of
+ // this string to some ASCII/Literal string. The ASCII string is
+ // *not* lowercased for you. If you compare to an ASCII or literal
+ // string that contains an uppercase character, it is guaranteed to
+ // return false. We will throw assertions too.
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;
+
+ // LowerCaseEqualsLiteral must ONLY be applied to an actual
+ // literal string. Do not attempt to use it with a regular char*
+ // pointer, or with a char array variable. Use
+ // LowerCaseEqualsASCII for them.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool LowerCaseEqualsLiteral( const char* str ) const
+ {
+ return LowerCaseEqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( const char (&str)[N] ) const
+ {
+ return LowerCaseEqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return LowerCaseEqualsASCII(s, N-1);
+ }
+#endif
+
+ /**
+ * A string always references a non-null data pointer. In some
+ * applications (e.g., the DOM) it is necessary for a string class
+ * to have some way to distinguish an empty string from a null (or
+ * void) string. These methods enable support for the concept of
+ * a void string.
+ */
+
+ NS_COM PRBool NS_FASTCALL IsVoid() const;
+ NS_COM void NS_FASTCALL SetIsVoid( PRBool );
+
+
+ /**
+ * This method returns true if the string's underlying buffer is
+ * null-terminated. This should rarely be needed by applications.
+ * The PromiseFlatTString method should be used to ensure that a
+ * string's underlying buffer is null-terminated.
+ */
+
+ NS_COM PRBool NS_FASTCALL IsTerminated() const;
+
+
+ /**
+ * These are contant time since nsTAString uses flat storage
+ */
+ NS_COM char_type NS_FASTCALL First() const;
+ NS_COM char_type NS_FASTCALL Last() const;
+
+
+ /**
+ * Returns the number of occurances of the given character.
+ */
+ NS_COM size_type NS_FASTCALL CountChar( char_type ) const;
+
+
+ /**
+ * Locates the offset of the first occurance of the character. Pass a
+ * non-zero offset to control where the search begins.
+ */
+
+ NS_COM PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const;
+
+
+ /**
+ * SetCapacity is not required to do anything; however, it can be used
+ * as a hint to the implementation to reduce allocations.
+ *
+ * SetCapacity(0) is a suggestion to discard all associated storage.
+ */
+ NS_COM void NS_FASTCALL SetCapacity( size_type );
+
+
+ /**
+ * XXX talk to dbaron about this comment. we do need a method that
+ * XXX allows someone to resize a string's buffer so that it can be
+ * XXX populated using writing iterators. SetLength seems to be the
+ * XXX right method for the job, and we do use it in this capacity
+ * XXX in certain places.
+ *
+ * SetLength is used in two ways:
+ * 1) to |Cut| a suffix of the string;
+ * 2) to prepare to |Append| or move characters around.
+ *
+ * External callers are not allowed to use |SetLength| in this
+ * latter capacity, and should prefer |Truncate| for the former.
+ * In other words, |SetLength| is deprecated for all use outside
+ * of the string library and the internal use may at some point
+ * be replaced as well.
+ *
+ * This distinction makes me think the two different uses should
+ * be split into two distinct functions.
+ */
+ NS_COM void NS_FASTCALL SetLength( size_type );
+
+
+ /**
+ * Can't use |Truncate| to make a string longer!
+ */
+ void Truncate( size_type aNewLength=0 )
+ {
+ NS_ASSERTION(aNewLength <= Length(), "Truncate cannot make string longer");
+ SetLength(aNewLength);
+ }
+
+
+ /**
+ * |Assign| and |operator=| make |this| equivalent to the string or
+ * buffer given as an argument. If possible, they do this by sharing
+ * a reference counted buffer (see |nsTSubstring|). If not, they copy
+ * the buffer into their own buffer.
+ */
+
+ NS_COM void NS_FASTCALL Assign( const self_type& readable );
+ NS_COM void NS_FASTCALL Assign( const substring_tuple_type& tuple );
+ NS_COM void NS_FASTCALL Assign( const char_type* data );
+ NS_COM void NS_FASTCALL Assign( const char_type* data, size_type length );
+ NS_COM void NS_FASTCALL Assign( char_type c );
+
+ NS_COM void NS_FASTCALL AssignASCII( const char* data, size_type length );
+ NS_COM void NS_FASTCALL AssignASCII( const char* data );
+
+ // AssignLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AssignASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AssignLiteral( const char* str )
+ { AssignASCII(str); }
+#else
+ template<int N>
+ void AssignLiteral( const char (&str)[N] )
+ { AssignASCII(str, N-1); }
+ template<int N>
+ void AssignLiteral( char (&str)[N] )
+ { AssignASCII(str, N-1); }
+#endif
+
+ // copy-assignment operator. I must define my own if I don't want the compiler to make me one
+ self_type& operator=( const self_type& readable ) { Assign(readable); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+
+
+
+ /**
+ * |Append|, |operator+=| are used to add characters to the end of this string.
+ */
+
+ NS_COM void NS_FASTCALL Append( const self_type& readable );
+ NS_COM void NS_FASTCALL Append( const substring_tuple_type& tuple );
+ NS_COM void NS_FASTCALL Append( const char_type* data );
+ NS_COM void NS_FASTCALL Append( const char_type* data, size_type length );
+ NS_COM void NS_FASTCALL Append( char_type c );
+
+ NS_COM void NS_FASTCALL AppendASCII( const char* data, size_type length );
+ NS_COM void NS_FASTCALL AppendASCII( const char* data );
+
+ // AppendLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AppendASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AppendLiteral( const char* str )
+ { AppendASCII(str); }
+#else
+ template<int N>
+ void AppendLiteral( const char (&str)[N] )
+ { AppendASCII(str, N-1); }
+ template<int N>
+ void AppendLiteral( char (&str)[N] )
+ { AppendASCII(str, N-1); }
+#endif
+
+ self_type& operator+=( const self_type& readable ) { Append(readable); return *this; }
+ self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; }
+ self_type& operator+=( const char_type* data ) { Append(data); return *this; }
+ self_type& operator+=( char_type c ) { Append(c); return *this; }
+
+
+ /**
+ * |Insert| is used to add characters into this string at a given position.
+ * NOTE: It's a shame the |pos| parameter isn't at the front of the arg list.
+ */
+
+ NS_COM void NS_FASTCALL Insert( const self_type& readable, index_type pos );
+ NS_COM void NS_FASTCALL Insert( const substring_tuple_type& tuple, index_type pos );
+ NS_COM void NS_FASTCALL Insert( const char_type* data, index_type pos );
+ NS_COM void NS_FASTCALL Insert( const char_type* data, index_type pos, size_type length );
+ NS_COM void NS_FASTCALL Insert( char_type c, index_type pos );
+
+
+ /**
+ * |Cut| is used to remove a range of characters from this string.
+ */
+
+ NS_COM void NS_FASTCALL Cut( index_type cutStart, size_type cutLength );
+
+
+ /**
+ * |Replace| is used overwrite a range of characters from this string.
+ */
+
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const self_type& readable );
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& readable );
+
+
+ /**
+ * this is public to support automatic conversion of tuple to abstract
+ * string, which is necessary to support our API.
+ */
+ nsTAString_CharT(const substring_tuple_type& tuple)
+ : mVTable(obsolete_string_type::sCanonicalVTable)
+ , mData(nsnull)
+ , mLength(0)
+ , mFlags(0)
+ {
+ Assign(tuple);
+ }
+
+ protected:
+
+ friend class nsTSubstringTuple_CharT;
+
+ // GCC 3.2 erroneously needs these (even though they are subclasses!)
+ friend class nsTSubstring_CharT;
+ friend class nsTDependentSubstring_CharT;
+ friend class nsTPromiseFlatString_CharT;
+
+ /**
+ * the address of our virtual function table. required for backwards
+ * compatibility with Mozilla 1.0 frozen nsAC?String interface.
+ */
+ const void* mVTable;
+
+ /**
+ * these fields are "here" only when mVTable == sCanonicalVTable.
+ *
+ * they exist to support automatic construction of a nsTAString
+ * from a nsTSubstringTuple.
+ */
+ char_type* mData;
+ size_type mLength;
+ PRUint32 mFlags;
+
+ /**
+ * nsTAString must be subclassed before it can be instantiated.
+ */
+ nsTAString_CharT(char_type* data, size_type length, PRUint32 flags)
+ : mVTable(obsolete_string_type::sCanonicalVTable)
+ , mData(data)
+ , mLength(length)
+ , mFlags(flags)
+ {}
+
+ /**
+ * optional ctor for use by subclasses.
+ *
+ * NOTE: mData and mLength are intentionally left uninitialized.
+ */
+ explicit
+ nsTAString_CharT(PRUint32 flags)
+ : mVTable(obsolete_string_type::sCanonicalVTable)
+ , mFlags(flags)
+ {}
+
+ /**
+ * get pointer to internal string buffer (may not be null terminated).
+ * return length of buffer.
+ */
+ NS_COM size_type NS_FASTCALL GetReadableBuffer( const char_type **data ) const;
+ NS_COM size_type NS_FASTCALL GetWritableBuffer( char_type **data );
+
+ /**
+ * returns true if this tuple is dependent on (i.e., overlapping with)
+ * the given char sequence.
+ */
+ PRBool NS_FASTCALL IsDependentOn(const char_type *start, const char_type *end) const;
+
+ /**
+ * we can be converted to a const nsTSubstring (dependent on this)
+ */
+ const substring_type NS_FASTCALL ToSubstring() const;
+
+ /**
+ * type cast helpers
+ */
+
+ const obsolete_string_type* AsObsoleteString() const
+ {
+ return NS_REINTERPRET_CAST(const obsolete_string_type*, this);
+ }
+
+ obsolete_string_type* AsObsoleteString()
+ {
+ return NS_REINTERPRET_CAST(obsolete_string_type*, this);
+ }
+
+ const substring_type* AsSubstring() const
+ {
+ return NS_REINTERPRET_CAST(const substring_type*, this);
+ }
+
+ substring_type* AsSubstring()
+ {
+ return NS_REINTERPRET_CAST(substring_type*, this);
+ }
+
+ private:
+
+ // GCC 2.95.3, EGCS-2.91.66, Sun Workshop/Forte, and IBM VisualAge C++
+ // require a public copy-constructor in order to support automatic
+ // construction of a nsTAString from a nsTSubstringTuple. I believe
+ // enabling the default copy-constructor is harmless, but I do not want
+ // it to be enabled by default because that might tempt people into
+ // using it (where it would be invalid).
+#if !defined(__SUNPRO_CC) && \
+ !(defined(_AIX) && defined(__IBMCPP__)) && \
+ (!defined(__GNUC__) || __GNUC__ > 2 || __GNUC_MINOR__ > 95)
+
+ // NOT TO BE IMPLEMENTED
+ nsTAString_CharT( const self_type& );
+
+#endif
+
+ // NOT TO BE IMPLEMENTED
+ void operator= ( incompatible_char_type );
+ void Assign ( incompatible_char_type );
+ void operator+= ( incompatible_char_type );
+ void Append ( incompatible_char_type );
+ void Insert ( incompatible_char_type, index_type );
+ };
+
+
+NS_COM
+int NS_FASTCALL Compare( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs, const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT() );
+
+
+inline
+PRBool operator!=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return !lhs.Equals(rhs);
+ }
+
+inline
+PRBool operator< ( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)< 0;
+ }
+
+inline
+PRBool operator<=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)<=0;
+ }
+
+inline
+PRBool operator==( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return lhs.Equals(rhs);
+ }
+
+inline
+PRBool operator>=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)>=0;
+ }
+
+inline
+PRBool operator> ( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)> 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h
new file mode 100644
index 00000000..91a2b53e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTDependentString_CharT
+ *
+ * Stores a null-terminated, immutable sequence of characters.
+ *
+ * Subclass of nsTString that restricts string value to an immutable
+ * character sequence. This class does not own its data, so the creator
+ * of objects of this type must take care to ensure that a
+ * nsTDependentString continues to reference valid memory for the
+ * duration of its use.
+ */
+class nsTDependentString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTDependentString_CharT self_type;
+
+ public:
+
+ /**
+ * verify restrictions
+ */
+ void AssertValid()
+ {
+ NS_ASSERTION(mData, "nsTDependentString must wrap a non-NULL buffer");
+ NS_ASSERTION(mLength != size_type(-1), "nsTDependentString has bogus length");
+ NS_ASSERTION(mData[mLength] == 0, "nsTDependentString must wrap only null-terminated strings");
+ }
+
+
+ /**
+ * constructors
+ */
+
+ nsTDependentString_CharT( const char_type* start, const char_type* end )
+ : string_type(NS_CONST_CAST(char_type*, start), end - start, F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ nsTDependentString_CharT( const char_type* data, PRUint32 length )
+ : string_type(NS_CONST_CAST(char_type*, data), length, F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ explicit
+ nsTDependentString_CharT( const char_type* data )
+ : string_type(NS_CONST_CAST(char_type*, data), char_traits::length(data), F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ explicit
+ nsTDependentString_CharT( const substring_type& str )
+ : string_type(NS_CONST_CAST(char_type*, str.Data()), str.Length(), F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ // XXX are you sure??
+ // auto-generated copy-constructor OK
+ // auto-generated copy-assignment operator OK
+ // auto-generated destructor OK
+
+
+ /**
+ * allow this class to be bound to a different string...
+ */
+
+ void Rebind( const char_type* data )
+ {
+ mData = NS_CONST_CAST(char_type*, data);
+ mLength = char_traits::length(data);
+ SetDataFlags(F_TERMINATED);
+ AssertValid();
+ }
+
+ void Rebind( const char_type* data, size_type length )
+ {
+ mData = NS_CONST_CAST(char_type*, data);
+ mLength = length;
+ SetDataFlags(F_TERMINATED);
+ AssertValid();
+ }
+
+ void Rebind( const char_type* start, const char_type* end )
+ {
+ Rebind(start, end - start);
+ }
+
+ private:
+
+ // NOT USED
+ nsTDependentString_CharT( const substring_tuple_type& );
+ nsTDependentString_CharT( const abstract_string_type& );
+ };
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h
new file mode 100644
index 00000000..00e5f189
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTDependentSubstring_CharT
+ */
+class nsTDependentSubstring_CharT : public nsTSubstring_CharT
+ {
+ public:
+
+ typedef nsTDependentSubstring_CharT self_type;
+
+ public:
+
+ NS_COM void Rebind( const abstract_string_type&, PRUint32 startPos, PRUint32 length = size_type(-1) );
+ NS_COM void Rebind( const substring_type&, PRUint32 startPos, PRUint32 length = size_type(-1) );
+
+ void Rebind( const char_type* start, const char_type* end )
+ {
+ NS_ASSERTION(start && end, "nsTDependentSubstring must wrap a non-NULL buffer");
+ mData = NS_CONST_CAST(char_type*, start);
+ mLength = end - start;
+ SetDataFlags(F_NONE);
+ }
+
+ nsTDependentSubstring_CharT( const abstract_string_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) )
+ : substring_type(F_NONE)
+ {
+ Rebind(str, startPos, length);
+ }
+
+ nsTDependentSubstring_CharT( const substring_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) )
+ : substring_type(F_NONE)
+ {
+ Rebind(str, startPos, length);
+ }
+
+ nsTDependentSubstring_CharT( const char_type* start, const char_type* end )
+ : substring_type(NS_CONST_CAST(char_type*, start), end - start, F_NONE) {}
+
+ nsTDependentSubstring_CharT( const const_iterator& start, const const_iterator& end )
+ : substring_type(NS_CONST_CAST(char_type*, start.get()), end.get() - start.get(), F_NONE) {}
+
+ // auto-generated copy-constructor OK (XXX really?? what about base class copy-ctor?)
+
+ private:
+ // we're immutable, you can't assign into a substring
+ void operator=( const self_type& ) NS_DELETE;
+
+ };
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const nsTAString_CharT& str, PRUint32 startPos, PRUint32 length = PRUint32(-1) )
+ {
+ return nsTDependentSubstring_CharT(str, startPos, length);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const nsTSubstring_CharT& str, PRUint32 startPos, PRUint32 length = PRUint32(-1) )
+ {
+ return nsTDependentSubstring_CharT(str, startPos, length);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const nsReadingIterator<CharT>& start, const nsReadingIterator<CharT>& end )
+ {
+ return nsTDependentSubstring_CharT(start.get(), end.get());
+ }
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const CharT* start, const CharT* end )
+ {
+ return nsTDependentSubstring_CharT(start, end);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringHead( const nsTAString_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, 0, count);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringHead( const nsTSubstring_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, 0, count);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringTail( const nsTAString_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, str.Length() - count, count);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringTail( const nsTSubstring_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, str.Length() - count, count);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h
new file mode 100644
index 00000000..82d5f56c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTObsoleteAString_CharT : binary compatible with old nsAC?String vtable
+ *
+ * @status FROZEN
+ */
+class nsTObsoleteAString_CharT
+ {
+ public:
+ /**
+ * This is holds the address of the vtable for the canonical string
+ * implementation (i.e., nsTString).
+ */
+ NS_COM static const void *sCanonicalVTable;
+
+ /**
+ * An |nsFragmentRequest| is used to tell |GetReadableFragment| and
+ * |GetWritableFragment| what to do.
+ *
+ * @see GetReadableFragment
+ */
+ enum nsFragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt };
+
+ /**
+ * A |nsReadableFragment| provides |const| access to a contiguous hunk of
+ * string of homogenous units, e.g., bytes (|char|). This doesn't mean it
+ * represents a flat hunk. It could be a variable length encoding, for
+ * instance UTF-8. And the fragment itself need not be zero-terminated.
+ *
+ * An |nsReadableFragment| is the underlying machinery that lets
+ * |nsReadingIterator|s work.
+ *
+ * @see nsReadingIterator
+ * @status FROZEN
+ */
+ struct nsReadableFragment
+ {
+ const CharT* mStart;
+ const CharT* mEnd;
+ const void* mFragmentIdentifier;
+
+ nsReadableFragment() : mStart(0), mEnd(0), mFragmentIdentifier(0) {}
+ };
+
+
+ /**
+ * A |nsWritableFragment| provides non-|const| access to a contiguous hunk of
+ * string of homogenous units, e.g., bytes (|char|). This doesn't mean it
+ * represents a flat hunk. It could be a variable length encoding, for
+ * instance UTF-8. And the fragment itself need not be zero-terminated.
+ *
+ * An |nsWritableFragment| is the underlying machinery that lets
+ * |nsWritingIterator|s work.
+ *
+ * @see nsWritingIterator
+ * @status FROZEN
+ */
+ struct nsWritableFragment
+ {
+ CharT* mStart;
+ CharT* mEnd;
+ void* mFragmentIdentifier;
+
+ nsWritableFragment() : mStart(0), mEnd(0), mFragmentIdentifier(0) {}
+ };
+
+ protected:
+
+ typedef CharT char_type;
+
+ typedef void buffer_handle_type;
+ typedef void shared_buffer_handle_type;
+ typedef nsReadableFragment const_fragment_type;
+ typedef nsWritableFragment fragment_type;
+
+ typedef nsTAString_CharT abstract_string_type;
+
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ protected:
+
+ friend class nsTAString_CharT;
+ friend class nsTSubstring_CharT;
+
+ /** here's the old nsAC?String vtable **/
+
+ virtual ~nsTObsoleteAString_CharT() { }
+
+ virtual PRUint32 GetImplementationFlags() const = 0;
+ virtual const buffer_handle_type* GetFlatBufferHandle() const = 0;
+ virtual const buffer_handle_type* GetBufferHandle() const = 0;
+ virtual const shared_buffer_handle_type* GetSharedBufferHandle() const = 0;
+
+ virtual size_type Length() const = 0;
+
+ virtual PRBool IsVoid() const = 0;
+ virtual void SetIsVoid( PRBool ) = 0;
+
+ virtual void SetCapacity( size_type ) = 0;
+ virtual void SetLength( size_type ) = 0;
+
+ virtual void Cut( index_type cutStart, size_type cutLength ) = 0;
+
+ virtual void do_AssignFromReadable( const abstract_string_type& ) = 0;
+ virtual void do_AssignFromElementPtr( const char_type* ) = 0;
+ virtual void do_AssignFromElementPtrLength( const char_type*, size_type ) = 0;
+ virtual void do_AssignFromElement( char_type ) = 0;
+
+ virtual void do_AppendFromReadable( const abstract_string_type& ) = 0;
+ virtual void do_AppendFromElementPtr( const char_type* ) = 0;
+ virtual void do_AppendFromElementPtrLength( const char_type*, size_type ) = 0;
+ virtual void do_AppendFromElement( char_type ) = 0;
+
+ virtual void do_InsertFromReadable( const abstract_string_type&, index_type ) = 0;
+ virtual void do_InsertFromElementPtr( const char_type*, index_type ) = 0;
+ virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type ) = 0;
+ virtual void do_InsertFromElement( char_type, index_type ) = 0;
+
+ virtual void do_ReplaceFromReadable( index_type, size_type, const abstract_string_type& ) = 0;
+
+ virtual const char_type* GetReadableFragment( const_fragment_type&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
+ virtual char_type* GetWritableFragment( fragment_type&, nsFragmentRequest, PRUint32 = 0 ) = 0;
+ };
+
+ // forward declare implementation
+class nsTObsoleteAStringThunk_CharT;
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h
new file mode 100644
index 00000000..6899df7c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * NOTE:
+ *
+ * Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last
+ * resort, and this may be necessary when dealing with legacy or OS calls,
+ * but in general, requiring a null-terminated array of characters kills many
+ * of the performance wins the string classes offer. Write your own code to
+ * use |nsA[C]String&|s for parameters. Write your string proccessing
+ * algorithms to exploit iterators. If you do this, you will benefit from
+ * being able to chain operations without copying or allocating and your code
+ * will be significantly more efficient. Remember, a function that takes an
+ * |const nsA[C]String&| can always be passed a raw character pointer by
+ * wrapping it (for free) in a |nsDependent[C]String|. But a function that
+ * takes a character pointer always has the potential to force allocation and
+ * copying.
+ *
+ *
+ * How to use it:
+ *
+ * A |nsPromiseFlat[C]String| doesn't necessarily own the characters it
+ * promises. You must never use it to promise characters out of a string
+ * with a shorter lifespan. The typical use will be something like this:
+ *
+ * SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD
+ *
+ * Here's a BAD use:
+ *
+ * const char* buffer = PromiseFlatCString(aCString).get();
+ * SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer
+ *
+ * The only way to make one is with the function |PromiseFlat[C]String|,
+ * which produce a |const| instance. ``What if I need to keep a promise
+ * around for a little while?'' you might ask. In that case, you can keep a
+ * reference, like so
+ *
+ * const nsPromiseFlatString& flat = PromiseFlatString(aString);
+ * // this reference holds the anonymous temporary alive, but remember,
+ * // it must _still_ have a lifetime shorter than that of |aString|
+ *
+ * SomeOSFunction(flat.get());
+ * SomeOtherOSFunction(flat.get());
+ *
+ *
+ * How does it work?
+ *
+ * A |nsPromiseFlat[C]String| is just a wrapper for another string. If you
+ * apply it to a string that happens to be flat, your promise is just a
+ * dependent reference to the string's data. If you apply it to a non-flat
+ * string, then a temporary flat string is created for you, by allocating and
+ * copying. In the event that you end up assigning the result into a sharing
+ * string (e.g., |nsTString|), the right thing happens.
+ */
+
+class nsTPromiseFlatString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTPromiseFlatString_CharT self_type;
+
+ private:
+
+ NS_COM void Init( const substring_type& );
+ NS_COM void Init( const abstract_string_type& );
+
+ // NOT TO BE IMPLEMENTED
+ void operator=( const self_type& ) NS_DELETE;
+
+ // NOT TO BE IMPLEMENTED
+ nsTPromiseFlatString_CharT() NS_DELETE;
+
+ public:
+
+ explicit
+ nsTPromiseFlatString_CharT( const substring_type& str )
+ : string_type()
+ {
+ Init(str);
+ }
+
+ explicit
+ nsTPromiseFlatString_CharT( const abstract_string_type& readable )
+ : string_type()
+ {
+ Init(readable);
+ }
+
+ explicit
+ nsTPromiseFlatString_CharT( const substring_tuple_type& tuple )
+ : string_type()
+ {
+ // nothing else to do here except assign the value of the tuple
+ // into ourselves.
+ Assign(tuple);
+ }
+ };
+
+inline
+const nsTPromiseFlatString_CharT
+TPromiseFlatString_CharT( const nsTAString_CharT& str )
+ {
+ return nsTPromiseFlatString_CharT(str);
+ }
+
+ // e.g., PromiseFlatCString(Substring(s))
+inline
+const nsTPromiseFlatString_CharT
+TPromiseFlatString_CharT( const nsTSubstring_CharT& frag )
+ {
+ return nsTPromiseFlatString_CharT(frag);
+ }
+
+ // e.g., PromiseFlatCString(a + b)
+inline
+const nsTPromiseFlatString_CharT
+TPromiseFlatString_CharT( const nsTSubstringTuple_CharT& tuple )
+ {
+ return nsTPromiseFlatString_CharT(tuple);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTString.h
new file mode 100644
index 00000000..2ef241b2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTString.h
@@ -0,0 +1,721 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Rick Gessner <rickg@netscape.com> (original author)
+ * Scott Collins <scc@mozilla.org>
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * This is the canonical null-terminated string class. All subclasses
+ * promise null-terminated storage. Instances of this class allocate
+ * strings on the heap.
+ *
+ * This class is also known as nsAFlat[C]String, where "flat" is used
+ * to denote a null-terminated string.
+ */
+class nsTString_CharT : public nsTSubstring_CharT
+ {
+ public:
+
+ typedef nsTString_CharT self_type;
+
+ public:
+
+ /**
+ * constructors
+ */
+
+ nsTString_CharT()
+ : substring_type() {}
+
+ explicit
+ nsTString_CharT( char_type c )
+ : substring_type()
+ {
+ Assign(c);
+ }
+
+ explicit
+ nsTString_CharT( const char_type* data, size_type length = size_type(-1) )
+ : substring_type()
+ {
+ Assign(data, length);
+ }
+
+ nsTString_CharT( const self_type& str )
+ : substring_type()
+ {
+ Assign(str);
+ }
+
+ nsTString_CharT( const substring_tuple_type& tuple )
+ : substring_type()
+ {
+ Assign(tuple);
+ }
+
+ explicit
+ nsTString_CharT( const abstract_string_type& readable )
+ : substring_type()
+ {
+ Assign(readable);
+ }
+
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+
+ /**
+ * returns the null-terminated string
+ */
+
+ const char_type* get() const
+ {
+ return mData;
+ }
+
+
+ /**
+ * returns character at specified index.
+ *
+ * NOTE: unlike nsTSubstring::CharAt, this function allows you to index
+ * the null terminator character.
+ */
+
+ char_type CharAt( index_type i ) const
+ {
+ NS_ASSERTION(i <= mLength, "index exceeds allowable range");
+ return mData[i];
+ }
+
+ char_type operator[]( index_type i ) const
+ {
+ return CharAt(i);
+ }
+
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+
+
+ /**
+ * Search for the given substring within this string.
+ *
+ * @param aString is substring to be sought in this
+ * @param aIgnoreCase selects case sensitivity
+ * @param aOffset tells us where in this string to start searching
+ * @param aCount tells us how far from the offset we are to search. Use
+ * -1 to search the whole string.
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 Find( const nsCString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 Find( const char* aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+
+#ifdef CharT_is_PRUnichar
+ NS_COM PRInt32 Find( const nsAFlatString& aString, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 Find( const PRUnichar* aString, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+#endif
+
+
+ /**
+ * This methods scans the string backwards, looking for the given string
+ *
+ * @param aString is substring to be sought in this
+ * @param aIgnoreCase tells us whether or not to do caseless compare
+ * @param aOffset tells us where in this string to start searching.
+ * Use -1 to search from the end of the string.
+ * @param aCount tells us how many iterations to make starting at the
+ * given offset.
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 RFind( const nsCString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 RFind( const char* aCString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+
+#ifdef CharT_is_PRUnichar
+ NS_COM PRInt32 RFind( const nsAFlatString& aString, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 RFind( const PRUnichar* aString, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+#endif
+
+
+ /**
+ * Search for given char within this string
+ *
+ * @param aChar is the character to search for
+ * @param aOffset tells us where in this strig to start searching
+ * @param aCount tells us how far from the offset we are to search.
+ * Use -1 to search the whole string.
+ * @return offset in string, or kNotFound
+ */
+
+ // PRInt32 FindChar( PRUnichar aChar, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 RFindChar( PRUnichar aChar, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+
+
+ /**
+ * This method searches this string for the first character found in
+ * the given string.
+ *
+ * @param aString contains set of chars to be found
+ * @param aOffset tells us where in this string to start searching
+ * (counting from left)
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 FindCharInSet( const char* aString, PRInt32 aOffset=0 ) const;
+ PRInt32 FindCharInSet( const self_type& aString, PRInt32 aOffset=0 ) const
+ {
+ return FindCharInSet(aString.get(), aOffset);
+ }
+
+#ifdef CharT_is_PRUnichar
+ NS_COM PRInt32 FindCharInSet( const PRUnichar* aString, PRInt32 aOffset=0 ) const;
+#endif
+
+
+ /**
+ * This method searches this string for the last character found in
+ * the given string.
+ *
+ * @param aString contains set of chars to be found
+ * @param aOffset tells us where in this string to start searching
+ * (counting from left)
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 RFindCharInSet( const char_type* aString, PRInt32 aOffset=-1 ) const;
+ PRInt32 RFindCharInSet( const self_type& aString, PRInt32 aOffset=-1 ) const
+ {
+ return RFindCharInSet(aString.get(), aOffset);
+ }
+
+
+ /**
+ * Compares a given string to this string.
+ *
+ * @param aString is the string to be compared
+ * @param aIgnoreCase tells us how to treat case
+ * @param aCount tells us how many chars to compare
+ * @return -1,0,1
+ */
+
+#ifdef CharT_is_char
+ NS_COM PRInt32 Compare( const char* aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1 ) const;
+#endif
+
+
+ /**
+ * Equality check between given string and this string.
+ *
+ * @param aString is the string to check
+ * @param aIgnoreCase tells us how to treat case
+ * @param aCount tells us how many chars to compare
+ * @return boolean
+ */
+#ifdef CharT_is_char
+ PRBool EqualsIgnoreCase( const char* aString, PRInt32 aCount=-1 ) const {
+ return Compare(aString, PR_TRUE, aCount) == 0;
+ }
+#else
+ NS_COM PRBool EqualsIgnoreCase( const char* aString, PRInt32 aCount=-1 ) const;
+
+
+ /**
+ * Copies data from internal buffer onto given char* buffer
+ *
+ * NOTE: This only copies as many chars as will fit in given buffer (clips)
+ * @param aBuf is the buffer where data is stored
+ * @param aBuflength is the max # of chars to move to buffer
+ * @param aOffset is the offset to copy from
+ * @return ptr to given buffer
+ */
+
+ NS_COM char* ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset=0 ) const;
+
+#endif // !CharT_is_PRUnichar
+
+ /**
+ * Perform string to float conversion.
+ *
+ * @param aErrorCode will contain error if one occurs
+ * @return float rep of string value
+ */
+ NS_COM float ToFloat( PRInt32* aErrorCode ) const;
+
+
+ /**
+ * Perform string to int conversion.
+ * @param aErrorCode will contain error if one occurs
+ * @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
+ * @return int rep of string value, and possible (out) error code
+ */
+ NS_COM PRInt32 ToInteger( PRInt32* aErrorCode, PRUint32 aRadix=kRadix10 ) const;
+
+
+ /**
+ * |Left|, |Mid|, and |Right| are annoying signatures that seem better almost
+ * any _other_ way than they are now. Consider these alternatives
+ *
+ * aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
+ * aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
+ * Left(aReadable, 17, aWritable); // ...a global function that does the assignment
+ *
+ * as opposed to the current signature
+ *
+ * aReadable.Left(aWritable, 17); // ...a member function that does the assignment
+ *
+ * or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
+ *
+ * aWritable = Substring(aReadable, 0, 17);
+ */
+
+ NS_COM size_type Mid( self_type& aResult, PRUint32 aStartPos, PRUint32 aCount ) const;
+
+ size_type Left( self_type& aResult, size_type aCount ) const
+ {
+ return Mid(aResult, 0, aCount);
+ }
+
+ size_type Right( self_type& aResult, size_type aCount ) const
+ {
+ aCount = NS_MIN(mLength, aCount);
+ return Mid(aResult, mLength - aCount, aCount);
+ }
+
+
+ /**
+ * Set a char inside this string at given index
+ *
+ * @param aChar is the char you want to write into this string
+ * @param anIndex is the ofs where you want to write the given char
+ * @return TRUE if successful
+ */
+
+ NS_COM PRBool SetCharAt( PRUnichar aChar, PRUint32 aIndex );
+
+
+ /**
+ * These methods are used to remove all occurances of the
+ * characters found in aSet from this string.
+ *
+ * @param aSet -- characters to be cut from this
+ */
+ NS_COM void StripChars( const char* aSet );
+
+
+ /**
+ * This method is used to remove all occurances of aChar from this
+ * string.
+ *
+ * @param aChar -- char to be stripped
+ * @param aOffset -- where in this string to start stripping chars
+ */
+
+ NS_COM void StripChar( char_type aChar, PRInt32 aOffset=0 );
+
+
+ /**
+ * This method strips whitespace throughout the string.
+ */
+ NS_COM void StripWhitespace();
+
+
+ /**
+ * swaps occurence of 1 string for another
+ */
+
+ NS_COM void ReplaceChar( char_type aOldChar, char_type aNewChar );
+ NS_COM void ReplaceChar( const char* aSet, char_type aNewChar );
+ NS_COM void ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue);
+ NS_COM void ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue);
+
+
+ /**
+ * This method trims characters found in aTrimSet from
+ * either end of the underlying string.
+ *
+ * @param aSet -- contains chars to be trimmed from both ends
+ * @param aEliminateLeading
+ * @param aEliminateTrailing
+ * @param aIgnoreQuotes -- if true, causes surrounding quotes to be ignored
+ * @return this
+ */
+ NS_COM void Trim( const char* aSet, PRBool aEliminateLeading=PR_TRUE, PRBool aEliminateTrailing=PR_TRUE, PRBool aIgnoreQuotes=PR_FALSE );
+
+ /**
+ * This method strips whitespace from string.
+ * You can control whether whitespace is yanked from start and end of
+ * string as well.
+ *
+ * @param aEliminateLeading controls stripping of leading ws
+ * @param aEliminateTrailing controls stripping of trailing ws
+ */
+ NS_COM void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE, PRBool aEliminateTrailing=PR_TRUE );
+
+
+ /**
+ * assign/append/insert with _LOSSY_ conversion
+ */
+
+ NS_COM void AssignWithConversion( const nsTAString_IncompatibleCharT& aString );
+ NS_COM void AssignWithConversion( const incompatible_char_type* aData, PRInt32 aLength=-1 );
+
+ NS_COM void AppendWithConversion( const nsTAString_IncompatibleCharT& aString );
+ NS_COM void AppendWithConversion( const incompatible_char_type* aData, PRInt32 aLength=-1 );
+
+ /**
+ * Append the given integer to this string
+ */
+ NS_COM void AppendInt( PRInt32 aInteger, PRInt32 aRadix=kRadix10 ); //radix=8,10 or 16
+
+ /**
+ * Append the given unsigned integer to this string
+ */
+ inline void AppendInt( PRUint32 aInteger, PRInt32 aRadix = kRadix10 )
+ {
+ AppendInt(PRInt32(aInteger), aRadix);
+ }
+
+ /**
+ * Append the given 64-bit integer to this string.
+ * @param aInteger The integer to append
+ * @param aRadix The radix to use; can be 8, 10 or 16.
+ */
+ NS_COM void AppendInt( PRInt64 aInteger, PRInt32 aRadix=kRadix10 );
+
+ /**
+ * Append the given float to this string
+ */
+
+ NS_COM void AppendFloat( double aFloat );
+
+#endif // !MOZ_STRING_WITH_OBSOLETE_API
+
+
+ protected:
+
+ explicit
+ nsTString_CharT( PRUint32 flags )
+ : substring_type(flags) {}
+
+ // allow subclasses to initialize fields directly
+ nsTString_CharT( char_type* data, size_type length, PRUint32 flags )
+ : substring_type(data, length, flags) {}
+ };
+
+
+class nsTFixedString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTFixedString_CharT self_type;
+ typedef nsTFixedString_CharT fixed_string_type;
+
+ public:
+
+ /**
+ * @param data
+ * fixed-size buffer to be used by the string (the contents of
+ * this buffer may be modified by the string)
+ * @param storageSize
+ * the size of the fixed buffer
+ * @param length (optional)
+ * the length of the string already contained in the buffer
+ */
+
+ nsTFixedString_CharT( char_type* data, size_type storageSize )
+ : string_type(data, char_traits::length(data), F_TERMINATED | F_FIXED | F_CLASS_FIXED)
+ , mFixedCapacity(storageSize - 1)
+ , mFixedBuf(data)
+ {}
+
+ nsTFixedString_CharT( char_type* data, size_type storageSize, size_type length )
+ : string_type(data, length, F_TERMINATED | F_FIXED | F_CLASS_FIXED)
+ , mFixedCapacity(storageSize - 1)
+ , mFixedBuf(data)
+ {
+ // null-terminate
+ mFixedBuf[length] = char_type(0);
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ protected:
+
+ friend class nsTSubstring_CharT;
+
+ size_type mFixedCapacity;
+ char_type *mFixedBuf;
+ };
+
+
+ /**
+ * nsTAutoString_CharT
+ *
+ * Subclass of nsTString_CharT that adds support for stack-based string
+ * allocation. Do not allocate this class on the heap! ;-)
+ */
+class nsTAutoString_CharT : public nsTFixedString_CharT
+ {
+ public:
+
+ typedef nsTAutoString_CharT self_type;
+
+ public:
+
+ /**
+ * constructors
+ */
+
+ nsTAutoString_CharT()
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {}
+
+ explicit
+ nsTAutoString_CharT( char_type c )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(c);
+ }
+
+ explicit
+ nsTAutoString_CharT( const char_type* data, size_type length = size_type(-1) )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(data, length);
+ }
+
+ nsTAutoString_CharT( const self_type& str )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(str);
+ }
+
+ explicit
+ nsTAutoString_CharT( const substring_type& str )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(str);
+ }
+
+ nsTAutoString_CharT( const substring_tuple_type& tuple )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(tuple);
+ }
+
+ explicit
+ nsTAutoString_CharT( const abstract_string_type& readable )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(readable);
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ enum { kDefaultStorageSize = 64 };
+
+ private:
+
+ char_type mStorage[kDefaultStorageSize];
+ };
+
+
+ /**
+ * nsTXPIDLString extends nsTString such that:
+ *
+ * (1) mData can be null
+ * (2) objects of this type can be automatically cast to |const CharT*|
+ * (3) getter_Copies method is supported to adopt data
+ */
+class nsTXPIDLString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTXPIDLString_CharT self_type;
+
+ public:
+
+ nsTXPIDLString_CharT()
+ : string_type(NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED | F_VOIDED) {}
+
+ // copy-constructor required to avoid default
+ nsTXPIDLString_CharT( const self_type& str )
+ : string_type(NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED | F_VOIDED)
+ {
+ Assign(str);
+ }
+
+ // return nsnull if we are voided
+ const char_type* get() const
+ {
+ return (mFlags & F_VOIDED) ? nsnull : mData;
+ }
+
+ // this case operator is the reason why this class cannot just be a
+ // typedef for nsTString
+ operator const char_type*() const
+ {
+ return get();
+ }
+
+ // need this to diambiguous operator[int]
+ char_type operator[]( PRInt32 i ) const
+ {
+ return CharAt(index_type(i));
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+ };
+
+
+ /**
+ * getter_Copies support for use with raw string out params:
+ *
+ * NS_IMETHOD GetBlah(char**);
+ *
+ * void some_function()
+ * {
+ * nsXPIDLCString blah;
+ * GetBlah(getter_Copies(blah));
+ * // ...
+ * }
+ */
+class nsTGetterCopies_CharT
+ {
+ public:
+ typedef CharT char_type;
+
+ nsTGetterCopies_CharT(nsTXPIDLString_CharT& str)
+ : mString(str), mData(nsnull) {}
+
+ ~nsTGetterCopies_CharT()
+ {
+ mString.Adopt(mData); // OK if mData is null
+ }
+
+ operator char_type**()
+ {
+ return &mData;
+ }
+
+ private:
+ nsTXPIDLString_CharT& mString;
+ char_type* mData;
+ };
+
+inline
+nsTGetterCopies_CharT
+getter_Copies( nsTXPIDLString_CharT& aString )
+ {
+ return nsTGetterCopies_CharT(aString);
+ }
+
+
+ /**
+ * nsTAdoptingString extends nsTXPIDLString such that:
+ *
+ * (1) Adopt given string on construction or assignment, i.e. take
+ * the value of what's given, and make what's given forget its
+ * value. Note that this class violates constness in a few
+ * places. Be careful!
+ */
+class nsTAdoptingString_CharT : public nsTXPIDLString_CharT
+ {
+ public:
+
+ typedef nsTAdoptingString_CharT self_type;
+
+ public:
+
+ explicit nsTAdoptingString_CharT() {}
+ explicit nsTAdoptingString_CharT(char_type* str, size_type length = size_type(-1))
+ {
+ Adopt(str, length);
+ }
+
+ // copy-constructor required to adopt on copy. Note that this
+ // will violate the constness of |str| in the operator=()
+ // call. |str| will be truncated as a side-effect of this
+ // constructor.
+ nsTAdoptingString_CharT( const self_type& str )
+#ifdef VBOX /* bird: shut up annoying warnings */
+ : nsTXPIDLString_CharT()
+#endif
+ {
+ *this = str;
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ // Adopt(), if possible, when assigning to a self_type&. Note
+ // that this violates the constness of str, str is always
+ // truncated when this operator is called.
+ NS_COM self_type& operator=( const self_type& str );
+
+ private:
+ // NOT TO BE IMPLEMENTED.
+ self_type& operator=( const char_type* data );
+ self_type& operator=( char_type* data );
+ };
+
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h
new file mode 100644
index 00000000..aaaf5a64
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h
@@ -0,0 +1,575 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTSubstring
+ *
+ * The base string type. This type is not instantiated directly. A sub-
+ * class is instantiated instead. For example, see nsTString.
+ *
+ * This type works like nsTAString except that it does not have the ABI
+ * requirements of that interface. Like nsTAString, nsTSubstring
+ * represents a single contiguous array of characters that may or may not
+ * be null-terminated.
+ *
+ * Many of the accessors on nsTSubstring are inlined as an optimization.
+ *
+ * This class is also known as "nsASingleFragmentC?String".
+ */
+class nsTSubstring_CharT : public nsTAString_CharT
+ {
+ public:
+
+ typedef nsTSubstring_CharT self_type;
+ typedef nsTString_CharT string_type;
+
+ typedef char_type* char_iterator;
+ typedef const char_type* const_char_iterator;
+
+ public:
+
+ /**
+ * reading iterators
+ */
+
+ const_char_iterator BeginReading() const { return mData; }
+ const_char_iterator EndReading() const { return mData + mLength; }
+
+ /**
+ * deprecated reading iterators
+ */
+
+ const_iterator& BeginReading( const_iterator& iter ) const
+ {
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ const_iterator& EndReading( const_iterator& iter ) const
+ {
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+ const_char_iterator& BeginReading( const_char_iterator& iter ) const
+ {
+ return iter = mData;
+ }
+
+ const_char_iterator& EndReading( const_char_iterator& iter ) const
+ {
+ return iter = mData + mLength;
+ }
+
+
+ /**
+ * writing iterators
+ */
+
+ char_iterator BeginWriting() { EnsureMutable(); return mData; }
+ char_iterator EndWriting() { EnsureMutable(); return mData + mLength; }
+
+ /**
+ * deprecated writing iterators
+ */
+
+ iterator& BeginWriting( iterator& iter )
+ {
+ EnsureMutable();
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ iterator& EndWriting( iterator& iter )
+ {
+ EnsureMutable();
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+ char_iterator& BeginWriting( char_iterator& iter )
+ {
+ EnsureMutable();
+ return iter = mData;
+ }
+
+ char_iterator& EndWriting( char_iterator& iter )
+ {
+ EnsureMutable();
+ return iter = mData + mLength;
+ }
+
+
+ /**
+ * accessors
+ */
+
+ // returns pointer to string data (not necessarily null-terminated)
+ const char_type *Data() const
+ {
+ return mData;
+ }
+
+ size_type Length() const
+ {
+ return mLength;
+ }
+
+ PRBool IsEmpty() const
+ {
+ return mLength == 0;
+ }
+
+ PRBool IsVoid() const
+ {
+ return mFlags & F_VOIDED;
+ }
+
+ PRBool IsTerminated() const
+ {
+ return mFlags & F_TERMINATED;
+ }
+
+ char_type CharAt( index_type i ) const
+ {
+ NS_ASSERTION(i < mLength, "index exceeds allowable range");
+ return mData[i];
+ }
+
+ char_type operator[]( index_type i ) const
+ {
+ return CharAt(i);
+ }
+
+ char_type First() const
+ {
+ NS_ASSERTION(mLength > 0, "|First()| called on an empty string");
+ return mData[0];
+ }
+
+ inline
+ char_type Last() const
+ {
+ NS_ASSERTION(mLength > 0, "|Last()| called on an empty string");
+ return mData[mLength - 1];
+ }
+
+ NS_COM size_type NS_FASTCALL CountChar( char_type ) const;
+ NS_COM PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const;
+
+
+ /**
+ * equality
+ */
+
+ NS_COM PRBool NS_FASTCALL Equals( const self_type& ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
+
+ NS_COM PRBool NS_FASTCALL Equals( const abstract_string_type& readable ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const abstract_string_type& readable, const comparator_type& comp ) const;
+
+ NS_COM PRBool NS_FASTCALL Equals( const char_type* data ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const;
+
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when you know the
+ * length of 'data'.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const;
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when 'data' is
+ * null-terminated.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data ) const;
+
+ // EqualsLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable.
+ // The template trick to acquire the array length at compile time without
+ // using a macro is due to Corey Kosak, with much thanks.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool EqualsLiteral( const char* str ) const
+ {
+ return EqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool EqualsLiteral( const char (&str)[N] ) const
+ {
+ return EqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool EqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return EqualsASCII(s, N-1);
+ }
+#endif
+
+ // The LowerCaseEquals methods compare the lower case version of
+ // this string to some ASCII/Literal string. The ASCII string is
+ // *not* lowercased for you. If you compare to an ASCII or literal
+ // string that contains an uppercase character, it is guaranteed to
+ // return false. We will throw assertions too.
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;
+
+ // LowerCaseEqualsLiteral must ONLY be applied to an actual
+ // literal string. Do not attempt to use it with a regular char*
+ // pointer, or with a char array variable. Use
+ // LowerCaseEqualsASCII for them.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool LowerCaseEqualsLiteral( const char* str ) const
+ {
+ return LowerCaseEqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( const char (&str)[N] ) const
+ {
+ return LowerCaseEqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return LowerCaseEqualsASCII(s, N-1);
+ }
+#endif
+
+ /**
+ * assignment
+ */
+
+ void Assign( char_type c ) { Assign(&c, 1); }
+ NS_COM void NS_FASTCALL Assign( const char_type* data, size_type length = size_type(-1) );
+ NS_COM void NS_FASTCALL Assign( const self_type& );
+ NS_COM void NS_FASTCALL Assign( const substring_tuple_type& );
+ NS_COM void NS_FASTCALL Assign( const abstract_string_type& );
+
+ NS_COM void NS_FASTCALL AssignASCII( const char* data, size_type length );
+ NS_COM void NS_FASTCALL AssignASCII( const char* data );
+
+ // AssignLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AssignASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AssignLiteral( const char* str )
+ { AssignASCII(str); }
+#else
+ template<int N>
+ void AssignLiteral( const char (&str)[N] )
+ { AssignASCII(str, N-1); }
+ template<int N>
+ void AssignLiteral( char (&str)[N] )
+ { AssignASCII(str, N-1); }
+#endif
+
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ NS_COM void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) );
+
+
+ /**
+ * buffer manipulation
+ */
+
+ void Replace( index_type cutStart, size_type cutLength, char_type c ) { Replace(cutStart, cutLength, &c, 1); }
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) );
+ void Replace( index_type cutStart, size_type cutLength, const self_type& str ) { Replace(cutStart, cutLength, str.Data(), str.Length()); }
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple );
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable );
+
+ NS_COM void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) );
+
+ void Append( char_type c ) { Replace(mLength, 0, c); }
+ void Append( const char_type* data, size_type length = size_type(-1) ) { Replace(mLength, 0, data, length); }
+ void Append( const self_type& str ) { Replace(mLength, 0, str); }
+ void Append( const substring_tuple_type& tuple ) { Replace(mLength, 0, tuple); }
+ void Append( const abstract_string_type& readable ) { Replace(mLength, 0, readable); }
+
+ void AppendASCII( const char* data, size_type length = size_type(-1) ) { ReplaceASCII(mLength, 0, data, length); }
+
+ // AppendLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AppendASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AppendLiteral( const char* str )
+ { AppendASCII(str); }
+#else
+ template<int N>
+ void AppendLiteral( const char (&str)[N] )
+ { AppendASCII(str, N-1); }
+ template<int N>
+ void AppendLiteral( char (&str)[N] )
+ { AppendASCII(str, N-1); }
+#endif
+
+ self_type& operator+=( char_type c ) { Append(c); return *this; }
+ self_type& operator+=( const char_type* data ) { Append(data); return *this; }
+ self_type& operator+=( const self_type& str ) { Append(str); return *this; }
+ self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; }
+ self_type& operator+=( const abstract_string_type& readable ) { Append(readable); return *this; }
+
+ void Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
+ void Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
+ void Insert( const self_type& str, index_type pos ) { Replace(pos, 0, str); }
+ void Insert( const substring_tuple_type& tuple, index_type pos ) { Replace(pos, 0, tuple); }
+ void Insert( const abstract_string_type& readable, index_type pos ) { Replace(pos, 0, readable); }
+
+ void Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); }
+
+
+ /**
+ * buffer sizing
+ */
+
+ NS_COM void NS_FASTCALL SetCapacity( size_type capacity );
+
+ NS_COM void NS_FASTCALL SetLength( size_type );
+
+ void Truncate( size_type newLength = 0 )
+ {
+ NS_ASSERTION(newLength <= mLength, "Truncate cannot make string longer");
+ SetLength(newLength);
+ }
+
+
+ /**
+ * string data is never null, but can be marked void. if true, the
+ * string will be truncated. @see nsTSubstring::IsVoid
+ */
+
+ NS_COM void NS_FASTCALL SetIsVoid( PRBool );
+
+
+ public:
+
+ /**
+ * this is public to support automatic conversion of tuple to string
+ * base type, which helps avoid converting to nsTAString.
+ */
+ nsTSubstring_CharT(const substring_tuple_type& tuple)
+ : abstract_string_type(nsnull, 0, F_NONE)
+ {
+ Assign(tuple);
+ }
+
+ protected:
+
+ friend class nsTObsoleteAStringThunk_CharT;
+ friend class nsTAString_CharT;
+ friend class nsTSubstringTuple_CharT;
+
+ // XXX GCC 3.4 needs this :-(
+ friend class nsTPromiseFlatString_CharT;
+
+ // default initialization
+ nsTSubstring_CharT()
+ : abstract_string_type(
+ NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED) {}
+
+ // allow subclasses to initialize fields directly
+ nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags )
+ : abstract_string_type(data, length, flags) {}
+
+ // version of constructor that leaves mData and mLength uninitialized
+ explicit
+ nsTSubstring_CharT( PRUint32 flags )
+ : abstract_string_type(flags) {}
+
+ // copy-constructor, constructs as dependent on given object
+ // (NOTE: this is for internal use only)
+ nsTSubstring_CharT( const self_type& str )
+ : abstract_string_type(
+ str.mData, str.mLength, str.mFlags & (F_TERMINATED | F_VOIDED)) {}
+
+ /**
+ * this function releases mData and does not change the value of
+ * any of its member variables. inotherwords, this function acts
+ * like a destructor.
+ */
+ void NS_FASTCALL Finalize();
+
+ /**
+ * this function prepares mData to be mutated.
+ *
+ * @param capacity specifies the required capacity of mData
+ * @param old_data returns null or the old value of mData
+ * @param old_flags returns 0 or the old value of mFlags
+ *
+ * if mData is already mutable and of sufficient capacity, then this
+ * function will return immediately. otherwise, it will either resize
+ * mData or allocate a new shared buffer. if it needs to allocate a
+ * new buffer, then it will return the old buffer and the corresponding
+ * flags. this allows the caller to decide when to free the old data.
+ *
+ * XXX we should expose a way for subclasses to free old_data.
+ */
+ PRBool NS_FASTCALL MutatePrep( size_type capacity, char_type** old_data, PRUint32* old_flags );
+
+ /**
+ * this function prepares a section of mData to be modified. if
+ * necessary, this function will reallocate mData and possibly move
+ * existing data to open up the specified section.
+ *
+ * @param cutStart specifies the starting offset of the section
+ * @param cutLength specifies the length of the section to be replaced
+ * @param newLength specifies the length of the new section
+ *
+ * for example, suppose mData contains the string "abcdef" then
+ *
+ * ReplacePrep(2, 3, 4);
+ *
+ * would cause mData to look like "ab____f" where the characters
+ * indicated by '_' have an unspecified value and can be freely
+ * modified. this function will null-terminate mData upon return.
+ */
+ void NS_FASTCALL ReplacePrep( index_type cutStart, size_type cutLength, size_type newLength );
+
+ /**
+ * returns the number of writable storage units starting at mData.
+ * the value does not include space for the null-terminator character.
+ *
+ * NOTE: this function returns size_type(-1) if mData is immutable.
+ */
+ size_type NS_FASTCALL Capacity() const;
+
+ /**
+ * this helper function can be called prior to directly manipulating
+ * the contents of mData. see, for example, BeginWriting.
+ */
+ NS_COM void NS_FASTCALL EnsureMutable();
+
+ /**
+ * returns true if this string overlaps with the given string fragment.
+ */
+ PRBool IsDependentOn( const char_type *start, const char_type *end ) const
+ {
+ /**
+ * if it _isn't_ the case that one fragment starts after the other ends,
+ * or ends before the other starts, then, they conflict:
+ *
+ * !(f2.begin >= f1.end || f2.end <= f1.begin)
+ *
+ * Simplified, that gives us:
+ */
+ return ( start < (mData + mLength) && end > mData );
+ }
+
+ /**
+ * this helper function stores the specified dataFlags in mFlags
+ */
+ void SetDataFlags(PRUint32 dataFlags)
+ {
+ NS_ASSERTION((dataFlags & 0xFFFF0000) == 0, "bad flags");
+ mFlags = dataFlags | (mFlags & 0xFFFF0000);
+ }
+
+ public:
+
+ // mFlags is a bitwise combination of the following flags. the meaning
+ // and interpretation of these flags is an implementation detail.
+ //
+ // NOTE: these flags are declared public _only_ for convenience inside
+ // the string implementation.
+
+ enum
+ {
+ F_NONE = 0, // no flags
+
+ // data flags are in the lower 16-bits
+ F_TERMINATED = 1 << 0, // IsTerminated returns true
+ F_VOIDED = 1 << 1, // IsVoid returns true
+ F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer
+ F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer
+ F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer
+
+ // class flags are in the upper 16-bits
+ F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString
+ };
+
+ //
+ // Some terminology:
+ //
+ // "dependent buffer" A dependent buffer is one that the string class
+ // does not own. The string class relies on some
+ // external code to ensure the lifetime of the
+ // dependent buffer.
+ //
+ // "shared buffer" A shared buffer is one that the string class
+ // allocates. When it allocates a shared string
+ // buffer, it allocates some additional space at
+ // the beginning of the buffer for additional
+ // fields, including a reference count and a
+ // buffer length. See nsStringHeader.
+ //
+ // "adopted buffer" An adopted buffer is a raw string buffer
+ // allocated on the heap (using nsMemory::Alloc)
+ // of which the string class subsumes ownership.
+ //
+ // Some comments about the string flags:
+ //
+ // F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They
+ // indicate the allocation type of mData. If none of these flags
+ // are set, then the string buffer is dependent.
+ //
+ // F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because
+ // the string classes always allocate null-terminated buffers, and
+ // non-terminated substrings are always dependent.
+ //
+ // F_VOIDED implies F_TERMINATED, and moreover it implies that mData
+ // points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is
+ // mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
+ //
+ };
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h
new file mode 100644
index 00000000..2ded17d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTSubstringTuple_CharT
+ *
+ * Represents a tuple of string fragments. Built as a recursive binary tree.
+ * It is used to implement the concatenation of two or more string objects.
+ *
+ * NOTE: This class is a private implementation detail and should never be
+ * referenced outside the string code.
+ */
+class nsTSubstringTuple_CharT
+ {
+ public:
+
+ typedef CharT char_type;
+ typedef nsCharTraits<char_type> char_traits;
+
+ typedef nsTSubstringTuple_CharT self_type;
+ typedef nsTSubstring_CharT substring_type;
+ typedef nsTString_CharT string_type;
+ typedef nsTAString_CharT abstract_string_type;
+ typedef nsTObsoleteAString_CharT obsolete_string_type;
+
+ typedef PRUint32 size_type;
+
+ public:
+
+ nsTSubstringTuple_CharT(const abstract_string_type* a, const abstract_string_type* b)
+ : mHead(nsnull)
+ , mFragA(a)
+ , mFragB(b) {}
+
+ nsTSubstringTuple_CharT(const self_type& head, const abstract_string_type* b)
+ : mHead(&head)
+ , mFragA(nsnull) // this fragment is ignored when head != nsnull
+ , mFragB(b) {}
+
+ /**
+ * computes the aggregate string length
+ */
+ NS_COM size_type Length() const;
+
+ /**
+ * writes the aggregate string to the given buffer. bufLen is assumed
+ * to be equal to or greater than the value returned by the Length()
+ * method. the string written to |buf| is not null-terminated.
+ */
+ NS_COM void WriteTo(char_type *buf, PRUint32 bufLen) const;
+
+ /**
+ * returns true if this tuple is dependent on (i.e., overlapping with)
+ * the given char sequence.
+ */
+ NS_COM PRBool IsDependentOn(const char_type *start, const char_type *end) const;
+
+ private:
+
+ const self_type* mHead;
+ const abstract_string_type* mFragA;
+ const abstract_string_type* mFragB;
+ };
+
+inline
+const nsTSubstringTuple_CharT
+operator+(const nsTAString_CharT& a, const nsTAString_CharT& b)
+ {
+ return nsTSubstringTuple_CharT(&a, &b);
+ }
+
+inline
+const nsTSubstringTuple_CharT
+operator+(const nsTSubstringTuple_CharT& head, const nsTAString_CharT& b)
+ {
+ return nsTSubstringTuple_CharT(head, &b);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h b/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h
new file mode 100644
index 00000000..c91079c2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Peter Annema <jaggernaut@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsUTF8Utils_h_
+#define nsUTF8Utils_h_
+
+class UTF8traits
+ {
+ public:
+ static PRBool isASCII(char c) { return (c & 0x80) == 0x00; }
+ static PRBool isInSeq(char c) { return (c & 0xC0) == 0x80; }
+ static PRBool is2byte(char c) { return (c & 0xE0) == 0xC0; }
+ static PRBool is3byte(char c) { return (c & 0xF0) == 0xE0; }
+ static PRBool is4byte(char c) { return (c & 0xF8) == 0xF0; }
+ static PRBool is5byte(char c) { return (c & 0xFC) == 0xF8; }
+ static PRBool is6byte(char c) { return (c & 0xFE) == 0xFC; }
+ };
+
+#define PLANE1_BASE 0x00010000
+#define UCS2_REPLACEMENT_CHAR 0xfffd
+
+#ifdef __GNUC__
+#define NS_ALWAYS_INLINE __attribute__((always_inline))
+#else
+#define NS_ALWAYS_INLINE
+#endif
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for converting
+ * UTF-8 to UTF-16
+ */
+class ConvertUTF8toUTF16
+ {
+ public:
+ typedef nsACString::char_type value_type;
+ typedef nsAString::char_type buffer_type;
+
+ ConvertUTF8toUTF16( buffer_type* aBuffer )
+ : mStart(aBuffer), mBuffer(aBuffer), mErrorEncountered(PR_FALSE) {}
+
+ size_t Length() const { return mBuffer - mStart; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ if ( mErrorEncountered )
+ return N;
+
+ // algorithm assumes utf8 units won't
+ // be spread across fragments
+ const value_type* p = start;
+ const value_type* end = start + N;
+ buffer_type* out = mBuffer;
+ for ( ; p != end /* && *p */; )
+ {
+ char c = *p++;
+
+ if ( UTF8traits::isASCII(c) )
+ {
+ *out++ = buffer_type(c);
+ continue;
+ }
+
+ PRUint32 ucs4;
+ PRUint32 minUcs4;
+ PRInt32 state = 0;
+
+ if ( UTF8traits::is2byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 6) & 0x000007C0L;
+ state = 1;
+ minUcs4 = 0x00000080;
+ }
+ else if ( UTF8traits::is3byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 12) & 0x0000F000L;
+ state = 2;
+ minUcs4 = 0x00000800;
+ }
+ else if ( UTF8traits::is4byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 18) & 0x001F0000L;
+ state = 3;
+ minUcs4 = 0x00010000;
+ }
+ else if ( UTF8traits::is5byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 24) & 0x03000000L;
+ state = 4;
+ minUcs4 = 0x00200000;
+ }
+ else if ( UTF8traits::is6byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 30) & 0x40000000L;
+ state = 5;
+ minUcs4 = 0x04000000;
+ }
+ else
+ {
+ NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings.");
+ mErrorEncountered = PR_TRUE;
+ mBuffer = out;
+ return N;
+ }
+
+ while ( state-- )
+ {
+ c = *p++;
+
+ if ( UTF8traits::isInSeq(c) )
+ {
+ PRInt32 shift = state * 6;
+ ucs4 |= (PRUint32(c) & 0x3F) << shift;
+ }
+ else
+ {
+ NS_ERROR("not a UTF8 string");
+ mErrorEncountered = PR_TRUE;
+ mBuffer = out;
+ return N;
+ }
+ }
+
+ if ( ucs4 < minUcs4 )
+ {
+ // Overlong sequence
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ }
+ else if ( ucs4 <= 0xD7FF )
+ {
+ *out++ = ucs4;
+ }
+ else if ( /* ucs4 >= 0xD800 && */ ucs4 <= 0xDFFF )
+ {
+ // Surrogates
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ }
+ else if ( ucs4 == 0xFFFE || ucs4 == 0xFFFF )
+ {
+ // Prohibited characters
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ }
+ else if ( ucs4 >= PLANE1_BASE )
+ {
+ if ( ucs4 >= 0x00110000 )
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ else {
+ // surrogate, see unicode specification 3.7 for following math.
+ ucs4 -= PLANE1_BASE;
+ *out++ = (PRUnichar)(ucs4 >> 10) | 0xd800u;
+ *out++ = (PRUnichar)(ucs4 & 0x3ff) | 0xdc00u;
+ }
+ }
+ else
+ {
+ *out++ = ucs4;
+ }
+ }
+ mBuffer = out;
+ return p - start;
+ }
+
+ void write_terminator()
+ {
+ *mBuffer = buffer_type(0);
+ }
+
+ private:
+ buffer_type* const mStart;
+ buffer_type* mBuffer;
+ PRBool mErrorEncountered;
+ };
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for computing
+ * the length of the UTF-16 string equivalent to a UTF-8 string.
+ */
+class CalculateUTF8Length
+ {
+ public:
+ typedef nsACString::char_type value_type;
+
+ CalculateUTF8Length() : mLength(0), mErrorEncountered(PR_FALSE) { }
+
+ size_t Length() const { return mLength; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ // ignore any further requests
+ if ( mErrorEncountered )
+ return N;
+
+ // algorithm assumes utf8 units won't
+ // be spread across fragments
+ const value_type* p = start;
+ const value_type* end = start + N;
+ for ( ; p < end /* && *p */; ++mLength )
+ {
+ if ( UTF8traits::isASCII(*p) )
+ p += 1;
+ else if ( UTF8traits::is2byte(*p) )
+ p += 2;
+ else if ( UTF8traits::is3byte(*p) )
+ p += 3;
+ else if ( UTF8traits::is4byte(*p) ) {
+ p += 4;
+ // Because a UTF-8 sequence of 4 bytes represents a codepoint
+ // greater than 0xFFFF, it will become a surrogate pair in the
+ // UTF-16 string, so add 1 more to mLength.
+ // This doesn't happen with is5byte and is6byte because they
+ // are illegal UTF-8 sequences (greater than 0x10FFFF) so get
+ // converted to a single replacement character.
+ //
+ // XXX: if the 4-byte sequence is an illegal non-shortest form,
+ // it also gets converted to a replacement character, so
+ // mLength will be off by one in this case.
+ ++mLength;
+ }
+ else if ( UTF8traits::is5byte(*p) )
+ p += 5;
+ else if ( UTF8traits::is6byte(*p) )
+ p += 6;
+ else
+ {
+ break;
+ }
+ }
+ if ( p != end )
+ {
+ NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings.");
+ mErrorEncountered = PR_TRUE;
+ mLength = 0;
+ return N;
+ }
+ return p - start;
+ }
+
+ private:
+ size_t mLength;
+ PRBool mErrorEncountered;
+ };
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for converting
+ * UTF-16 to UTF-8.
+ */
+class ConvertUTF16toUTF8
+ {
+ public:
+ typedef nsAString::char_type value_type;
+ typedef nsACString::char_type buffer_type;
+
+ // The error handling here is more lenient than that in
+ // |ConvertUTF8toUTF16|, but it's that way for backwards
+ // compatibility.
+
+ ConvertUTF16toUTF8( buffer_type* aBuffer )
+ : mStart(aBuffer), mBuffer(aBuffer) {}
+
+ size_t Size() const { return mBuffer - mStart; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ buffer_type *out = mBuffer; // gcc isn't smart enough to do this!
+
+ for (const value_type *p = start, *end = start + N; p < end; ++p )
+ {
+ value_type c = *p;
+ if (! (c & 0xFF80)) // U+0000 - U+007F
+ {
+ *out++ = (char)c;
+ }
+ else if (! (c & 0xF800)) // U+0100 - U+07FF
+ {
+ *out++ = 0xC0 | (char)(c >> 6);
+ *out++ = 0x80 | (char)(0x003F & c);
+ }
+ else if (0xD800 != (0xF800 & c)) // U+0800 - U+D7FF,U+E000 - U+FFFF
+ {
+ *out++ = 0xE0 | (char)(c >> 12);
+ *out++ = 0x80 | (char)(0x003F & (c >> 6));
+ *out++ = 0x80 | (char)(0x003F & c );
+ }
+ else if (0xD800 == (0xFC00 & c)) // U+D800 - U+DBFF
+ {
+ // D800- DBFF - High Surrogate
+ // N = (H- D800) *400 + 10000 + ...
+ PRUint32 ucs4 = 0x10000 + ((0x03FF & c) << 10);
+
+ ++p;
+ if (p == end)
+ {
+ NS_ERROR("Surrogate pair split between fragments");
+ mBuffer = out;
+ return N;
+ }
+ c = *p;
+
+ if (0xDC00 == (0xFC00 & c))
+ {
+ // DC00- DFFF - Low Surrogate
+ // N += ( L - DC00 )
+ ucs4 |= (0x03FF & c);
+
+ // 0001 0000-001F FFFF
+ *out++ = 0xF0 | (char)(ucs4 >> 18);
+ *out++ = 0x80 | (char)(0x003F & (ucs4 >> 12));
+ *out++ = 0x80 | (char)(0x003F & (ucs4 >> 6));
+ *out++ = 0x80 | (char)(0x003F & ucs4);
+ }
+ else
+ {
+ NS_ERROR("got a High Surrogate but no low surrogate");
+ // output nothing.
+ }
+ }
+ else // U+DC00 - U+DFFF
+ {
+ // DC00- DFFF - Low Surrogate
+ NS_ERROR("got a low Surrogate but no high surrogate");
+ // output nothing.
+ }
+ }
+
+ mBuffer = out;
+ return N;
+ }
+
+ void write_terminator()
+ {
+ *mBuffer = buffer_type(0);
+ }
+
+ private:
+ buffer_type* const mStart;
+ buffer_type* mBuffer;
+ };
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for computing
+ * the number of bytes a UTF-16 would occupy in UTF-8.
+ */
+class CalculateUTF8Size
+ {
+ public:
+ typedef nsAString::char_type value_type;
+
+ CalculateUTF8Size()
+ : mSize(0) { }
+
+ size_t Size() const { return mSize; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ // Assume UCS2 surrogate pairs won't be spread across fragments.
+ for (const value_type *p = start, *end = start + N; p < end; ++p )
+ {
+ value_type c = *p;
+ if (! (c & 0xFF80)) // U+0000 - U+007F
+ mSize += 1;
+ else if (! (c & 0xF800)) // U+0100 - U+07FF
+ mSize += 2;
+ else if (0xD800 != (0xF800 & c)) // U+0800 - U+D7FF,U+E000 - U+FFFF
+ mSize += 3;
+ else if (0xD800 == (0xFC00 & c)) // U+D800 - U+DBFF
+ {
+ ++p;
+ if (p == end)
+ {
+ NS_ERROR("Surrogate pair split between fragments");
+ return N;
+ }
+ c = *p;
+
+ if (0xDC00 == (0xFC00 & c))
+ mSize += 4;
+ else
+ NS_ERROR("got a high Surrogate but no low surrogate");
+ }
+ else // U+DC00 - U+DFFF
+ NS_ERROR("got a low Surrogate but no high surrogate");
+ }
+
+ return N;
+ }
+
+ private:
+ size_t mSize;
+ };
+
+/**
+ * A character sink that performs a |reinterpret_cast| style conversion
+ * between character types.
+ */
+template <class FromCharT, class ToCharT>
+class LossyConvertEncoding
+ {
+ public:
+ typedef FromCharT value_type;
+
+ typedef FromCharT input_type;
+ typedef ToCharT output_type;
+
+ typedef typename nsCharTraits<FromCharT>::unsigned_char_type unsigned_input_type;
+
+ public:
+ LossyConvertEncoding( output_type* aDestination ) : mDestination(aDestination) { }
+
+ PRUint32
+ write( const input_type* aSource, PRUint32 aSourceLength )
+ {
+ const input_type* done_writing = aSource + aSourceLength;
+ while ( aSource < done_writing )
+ *mDestination++ = (output_type)(unsigned_input_type)(*aSource++); // use old-style cast to mimic old |ns[C]String| behavior
+ return aSourceLength;
+ }
+
+ void
+ write_terminator()
+ {
+ *mDestination = output_type(0);
+ }
+
+ private:
+ output_type* mDestination;
+ };
+
+#endif /* !defined(nsUTF8Utils_h_) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h b/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h
new file mode 100644
index 00000000..c66a2d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsXPIDLString_h___
+#define nsXPIDLString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+#endif /* !defined(nsXPIDLString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h
new file mode 100644
index 00000000..d0f3a907
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#define CharT char
+#define CharT_is_char 1
+#define nsTObsoleteAString_CharT nsObsoleteACString
+#define nsTObsoleteAStringThunk_CharT nsObsoleteACStringThunk
+#define nsTAString_CharT nsACString
+#define nsTAString_IncompatibleCharT nsAString
+#define nsTString_CharT nsCString
+#define nsTFixedString_CharT nsFixedCString
+#define nsTAutoString_CharT nsCAutoString
+#define nsTSubstring_CharT nsCSubstring
+#define nsTSubstringTuple_CharT nsCSubstringTuple
+#define nsTStringComparator_CharT nsCStringComparator
+#define nsTDefaultStringComparator_CharT nsDefaultCStringComparator
+#define nsTDependentString_CharT nsDependentCString
+#define nsTDependentSubstring_CharT nsDependentCSubstring
+#define nsTXPIDLString_CharT nsXPIDLCString
+#define nsTGetterCopies_CharT nsCGetterCopies
+#define nsTAdoptingString_CharT nsAdoptingCString
+#define nsTPromiseFlatString_CharT nsPromiseFlatCString
+#define TPromiseFlatString_CharT PromiseFlatCString
diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h
new file mode 100644
index 00000000..c966dfbe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#define CharT PRUnichar
+#define CharT_is_PRUnichar 1
+#define nsTObsoleteAString_CharT nsObsoleteAString
+#define nsTObsoleteAStringThunk_CharT nsObsoleteAStringThunk
+#define nsTAString_CharT nsAString
+#define nsTAString_IncompatibleCharT nsACString
+#define nsTString_CharT nsString
+#define nsTFixedString_CharT nsFixedString
+#define nsTAutoString_CharT nsAutoString
+#define nsTSubstring_CharT nsSubstring
+#define nsTSubstringTuple_CharT nsSubstringTuple
+#define nsTStringComparator_CharT nsStringComparator
+#define nsTDefaultStringComparator_CharT nsDefaultStringComparator
+#define nsTDependentString_CharT nsDependentString
+#define nsTDependentSubstring_CharT nsDependentSubstring
+#define nsTXPIDLString_CharT nsXPIDLString
+#define nsTGetterCopies_CharT nsGetterCopies
+#define nsTAdoptingString_CharT nsAdoptingString
+#define nsTPromiseFlatString_CharT nsPromiseFlatString
+#define TPromiseFlatString_CharT PromiseFlatString
diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h
new file mode 100644
index 00000000..45344370
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#undef CharT
+#undef CharT_is_PRUnichar
+#undef CharT_is_char
+#undef nsTObsoleteAString_CharT
+#undef nsTObsoleteAStringThunk_CharT
+#undef nsTAString_CharT
+#undef nsTAString_IncompatibleCharT
+#undef nsTString_CharT
+#undef nsTFixedString_CharT
+#undef nsTAutoString_CharT
+#undef nsTSubstring_CharT
+#undef nsTSubstringTuple_CharT
+#undef nsTStringComparator_CharT
+#undef nsTDefaultStringComparator_CharT
+#undef nsTDependentString_CharT
+#undef nsTDependentSubstring_CharT
+#undef nsTXPIDLString_CharT
+#undef nsTGetterCopies_CharT
+#undef nsTAdoptingString_CharT
+#undef nsTPromiseFlatString_CharT
+#undef TPromiseFlatString_CharT
diff --git a/src/libs/xpcom18a4/xpcom/string/src/.cvsignore b/src/libs/xpcom18a4/xpcom/string/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/string/src/Makefile.in b/src/libs/xpcom18a4/xpcom/string/src/Makefile.in
new file mode 100644
index 00000000..81033c6c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/Makefile.in
@@ -0,0 +1,77 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Johnny Stenback <jst@netscape.com> (original author)
+# Scott Collins <scc@mozilla.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = string
+LIBRARY_NAME = string_s
+
+REQUIRES = xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ nsAString.cpp \
+ nsDependentSubstring.cpp \
+ nsObsoleteAStringThunk.cpp \
+ nsPrintfCString.cpp \
+ nsPromiseFlatString.cpp \
+ nsReadableUtils.cpp \
+ nsSubstring.cpp \
+ nsSubstringTuple.cpp \
+ nsString.cpp \
+ nsStringComparator.cpp \
+ nsStringObsolete.cpp \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a
+# static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp
new file mode 100644
index 00000000..5b481662
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsAString.h"
+#include "nsObsoleteAString.h"
+#include "nsString.h"
+
+ // define nsAString
+#include "string-template-def-unichar.h"
+#include "nsTAString.cpp"
+#include "string-template-undef.h"
+
+ // define nsACString
+#include "string-template-def-char.h"
+#include "nsTAString.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp
new file mode 100644
index 00000000..971defc8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsDependentSubstring.h"
+#include "nsAlgorithm.h"
+
+ // define nsDependentSubstring
+#include "string-template-def-unichar.h"
+#include "nsTDependentSubstring.cpp"
+#include "string-template-undef.h"
+
+ // define nsDependentCSubstring
+#include "string-template-def-char.h"
+#include "nsTDependentSubstring.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp
new file mode 100644
index 00000000..8b511d1e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsObsoleteAString.h"
+#include "nsString.h"
+
+
+ // define nsObsoleteAStringThunk
+#include "string-template-def-unichar.h"
+#include "nsTObsoleteAStringThunk.cpp"
+#include "string-template-undef.h"
+
+
+ // define nsObsoleteACStringThunk
+#include "string-template-def-char.h"
+#include "nsTObsoleteAStringThunk.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp
new file mode 100644
index 00000000..8bb06da6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsPrintfCString.h"
+#include <stdarg.h>
+#include "prprf.h"
+
+
+// though these classes define a fixed buffer, they do not set the F_FIXED
+// flag. this is because they are not intended to be modified after they have
+// been constructed. we could change this but it would require adding a new
+// class to the hierarchy, one that both this class and nsCAutoString would
+// inherit from. for now, we populate the fixed buffer, and then let the
+// nsCString code treat the buffer as if it were a dependent buffer.
+
+nsPrintfCString::nsPrintfCString( const char_type* format, ... )
+ : string_type(mLocalBuffer, 0, F_TERMINATED)
+ {
+ va_list ap;
+
+ size_type logical_capacity = kLocalBufferSize;
+ size_type physical_capacity = logical_capacity + 1;
+
+ va_start(ap, format);
+ mLength = PR_vsnprintf(mData, physical_capacity, format, ap);
+ va_end(ap);
+ }
+
+nsPrintfCString::nsPrintfCString( size_type n, const char_type* format, ... )
+ : string_type(mLocalBuffer, 0, F_TERMINATED)
+ {
+ va_list ap;
+
+ // make sure there's at least |n| space
+ size_type logical_capacity = kLocalBufferSize;
+ if ( n > logical_capacity )
+ {
+ SetCapacity(n);
+ if (Capacity() < n)
+ return; // out of memory !!
+ logical_capacity = n;
+ }
+ size_type physical_capacity = logical_capacity + 1;
+
+ va_start(ap, format);
+ mLength = PR_vsnprintf(mData, physical_capacity, format, ap);
+ va_end(ap);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp
new file mode 100644
index 00000000..aab4f209
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsPromiseFlatString.h"
+
+ // define nsPromiseFlatString
+#include "string-template-def-unichar.h"
+#include "nsTPromiseFlatString.cpp"
+#include "string-template-undef.h"
+
+ // define nsPromiseFlatCString
+#include "string-template-def-char.h"
+#include "nsTPromiseFlatString.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp
new file mode 100644
index 00000000..24305b6a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp
@@ -0,0 +1,1122 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsReadableUtils.h"
+#include "nsMemory.h"
+#include "nsString.h"
+#include "nsUTF8Utils.h"
+
+NS_COM
+void
+LossyCopyUTF16toASCII( const nsAString& aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ LossyAppendUTF16toASCII(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyASCIItoUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ AppendASCIItoUTF16(aSource, aDest);
+ }
+
+NS_COM
+void
+LossyCopyUTF16toASCII( const PRUnichar* aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ if (aSource) {
+ LossyAppendUTF16toASCII(nsDependentString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+CopyASCIItoUTF16( const char* aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ if (aSource) {
+ AppendASCIItoUTF16(nsDependentCString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+CopyUTF16toUTF8( const nsAString& aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF16toUTF8(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyUTF8toUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF8toUTF16(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF16toUTF8(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyUTF8toUTF16( const char* aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF8toUTF16(aSource, aDest);
+ }
+
+NS_COM
+void
+LossyAppendUTF16toASCII( const nsAString& aSource, nsACString& aDest )
+ {
+ PRUint32 old_dest_length = aDest.Length();
+ aDest.SetLength(old_dest_length + aSource.Length());
+
+ nsAString::const_iterator fromBegin, fromEnd;
+
+ nsACString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ // right now, this won't work on multi-fragment destinations
+ LossyConvertEncoding<PRUnichar, char> converter(dest.get());
+
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+NS_COM
+void
+AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ PRUint32 old_dest_length = aDest.Length();
+ aDest.SetLength(old_dest_length + aSource.Length());
+
+ nsACString::const_iterator fromBegin, fromEnd;
+
+ nsAString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ // right now, this won't work on multi-fragment destinations
+ LossyConvertEncoding<char, PRUnichar> converter(dest.get());
+
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+NS_COM
+void
+LossyAppendUTF16toASCII( const PRUnichar* aSource, nsACString& aDest )
+ {
+ if (aSource) {
+ LossyAppendUTF16toASCII(nsDependentString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+AppendASCIItoUTF16( const char* aSource, nsAString& aDest )
+ {
+ if (aSource) {
+ AppendASCIItoUTF16(nsDependentCString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest )
+ {
+ nsAString::const_iterator source_start, source_end;
+ CalculateUTF8Size calculator;
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), calculator);
+
+ PRUint32 count = calculator.Size();
+
+ if (count)
+ {
+ PRUint32 old_dest_length = aDest.Length();
+
+ // Grow the buffer if we need to.
+ aDest.SetLength(old_dest_length + count);
+
+ nsACString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ if (count <= (PRUint32)dest.size_forward())
+ {
+ // aDest has enough room in the fragment just past the end
+ // of its old data that it can hold what we're about to
+ // append. Append using copy_string().
+
+ // All ready? Time to convert
+
+ ConvertUTF16toUTF8 converter(dest.get());
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), converter);
+
+ if (converter.Size() != count)
+ {
+ NS_ERROR("Input invalid or incorrect length was calculated");
+
+ aDest.SetLength(old_dest_length);
+ }
+ }
+ else
+ {
+ // This isn't the fastest way to do this, but it gets
+ // complicated to convert UTF16 into a fragmented UTF8
+ // string, so we'll take the easy way out here in this
+ // rare situation.
+
+ aDest.Replace(old_dest_length, count,
+ NS_ConvertUTF16toUTF8(aSource));
+ }
+ }
+ }
+
+NS_COM
+void
+AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ nsACString::const_iterator source_start, source_end;
+ CalculateUTF8Length calculator;
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), calculator);
+
+ PRUint32 count = calculator.Length();
+
+ if (count)
+ {
+ PRUint32 old_dest_length = aDest.Length();
+
+ // Grow the buffer if we need to.
+ aDest.SetLength(old_dest_length + count);
+
+ nsAString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ if (count <= (PRUint32)dest.size_forward())
+ {
+ // aDest has enough room in the fragment just past the end
+ // of its old data that it can hold what we're about to
+ // append. Append using copy_string().
+
+ // All ready? Time to convert
+
+ ConvertUTF8toUTF16 converter(dest.get());
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), converter);
+
+ if (converter.Length() != count)
+ {
+ NS_ERROR("Input wasn't UTF8 or incorrect length was calculated");
+ aDest.SetLength(old_dest_length);
+ }
+ }
+ else
+ {
+ // This isn't the fastest way to do this, but it gets
+ // complicated to convert parts of a UTF8 string into a
+ // UTF16 string, so we'll take the easy way out here in
+ // this rare situation.
+
+ aDest.Replace(old_dest_length, count,
+ NS_ConvertUTF8toUTF16(aSource));
+ }
+ }
+ }
+
+NS_COM
+void
+AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest )
+ {
+ if (aSource) {
+ AppendUTF16toUTF8(nsDependentString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+AppendUTF8toUTF16( const char* aSource, nsAString& aDest )
+ {
+ if (aSource) {
+ AppendUTF8toUTF16(nsDependentCString(aSource), aDest);
+ }
+ }
+
+
+ /**
+ * A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator).
+ *
+ * @param aSource an string you will eventually be making a copy of
+ * @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|.
+ *
+ */
+template <class FromStringT, class ToCharT>
+inline
+ToCharT*
+AllocateStringCopy( const FromStringT& aSource, ToCharT* )
+ {
+ return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
+ }
+
+
+NS_COM
+char*
+ToNewCString( const nsAString& aSource )
+ {
+ char* result = AllocateStringCopy(aSource, (char*)0);
+
+ nsAString::const_iterator fromBegin, fromEnd;
+ LossyConvertEncoding<PRUnichar, char> converter(result);
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
+ return result;
+ }
+
+NS_COM
+char*
+ToNewUTF8String( const nsAString& aSource, PRUint32 *aUTF8Count )
+ {
+ nsAString::const_iterator start, end;
+ CalculateUTF8Size calculator;
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ calculator);
+
+ if (aUTF8Count)
+ *aUTF8Count = calculator.Size();
+
+ char *result = NS_STATIC_CAST(char*,
+ nsMemory::Alloc(calculator.Size() + 1));
+
+ ConvertUTF16toUTF8 converter(result);
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ converter).write_terminator();
+ NS_ASSERTION(calculator.Size() == converter.Size(), "length mismatch");
+
+ return result;
+ }
+
+NS_COM
+char*
+ToNewCString( const nsACString& aSource )
+ {
+ // no conversion needed, just allocate a buffer of the correct length and copy into it
+
+ char* result = AllocateStringCopy(aSource, (char*)0);
+
+ nsACString::const_iterator fromBegin, fromEnd;
+ char* toBegin = result;
+ *copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = char(0);
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+ToNewUnicode( const nsAString& aSource )
+ {
+ // no conversion needed, just allocate a buffer of the correct length and copy into it
+
+ PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
+
+ nsAString::const_iterator fromBegin, fromEnd;
+ PRUnichar* toBegin = result;
+ *copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = PRUnichar(0);
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+ToNewUnicode( const nsACString& aSource )
+ {
+ PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
+
+ nsACString::const_iterator fromBegin, fromEnd;
+ LossyConvertEncoding<char, PRUnichar> converter(result);
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+UTF8ToNewUnicode( const nsACString& aSource, PRUint32 *aUTF16Count )
+ {
+ nsACString::const_iterator start, end;
+ CalculateUTF8Length calculator;
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ calculator);
+
+ if (aUTF16Count)
+ *aUTF16Count = calculator.Length();
+
+ PRUnichar *result = NS_STATIC_CAST(PRUnichar*,
+ nsMemory::Alloc(sizeof(PRUnichar) * (calculator.Length() + 1)));
+
+ ConvertUTF8toUTF16 converter(result);
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ converter).write_terminator();
+ NS_ASSERTION(calculator.Length() == converter.Length(), "length mismatch");
+
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+CopyUnicodeTo( const nsAString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength )
+ {
+ nsAString::const_iterator fromBegin, fromEnd;
+ PRUnichar* toBegin = aDest;
+ copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin);
+ return aDest;
+ }
+
+NS_COM
+void
+CopyUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest )
+ {
+ nsAString::iterator writer;
+ aDest.SetLength(Distance(aSrcStart, aSrcEnd));
+ aDest.BeginWriting(writer);
+ nsAString::const_iterator fromBegin(aSrcStart);
+
+ copy_string(fromBegin, aSrcEnd, writer);
+ }
+
+NS_COM
+void
+AppendUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest )
+ {
+ nsAString::iterator writer;
+ PRUint32 oldLength = aDest.Length();
+ aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd));
+ aDest.BeginWriting(writer).advance(oldLength);
+ nsAString::const_iterator fromBegin(aSrcStart);
+
+ copy_string(fromBegin, aSrcEnd, writer);
+ }
+
+NS_COM
+PRBool
+IsASCII( const nsAString& aString )
+ {
+ static const PRUnichar NOT_ASCII = PRUnichar(~0x007F);
+
+
+ // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
+
+ nsAString::const_iterator done_reading;
+ aString.EndReading(done_reading);
+
+ // for each chunk of |aString|...
+ PRUint32 fragmentLength = 0;
+ nsAString::const_iterator iter;
+ for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
+ {
+ fragmentLength = PRUint32(iter.size_forward());
+ const PRUnichar* c = iter.get();
+ const PRUnichar* fragmentEnd = c + fragmentLength;
+
+ // for each character in this chunk...
+ while ( c < fragmentEnd )
+ if ( *c++ & NOT_ASCII )
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+NS_COM
+PRBool
+IsASCII( const nsACString& aString )
+ {
+ static const char NOT_ASCII = char(~0x7F);
+
+
+ // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
+
+ nsACString::const_iterator done_reading;
+ aString.EndReading(done_reading);
+
+ // for each chunk of |aString|...
+ PRUint32 fragmentLength = 0;
+ nsACString::const_iterator iter;
+ for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
+ {
+ fragmentLength = PRUint32(iter.size_forward());
+ const char* c = iter.get();
+ const char* fragmentEnd = c + fragmentLength;
+
+ // for each character in this chunk...
+ while ( c < fragmentEnd )
+ if ( *c++ & NOT_ASCII )
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+NS_COM
+PRBool
+IsUTF8( const nsACString& aString )
+ {
+ nsReadingIterator<char> done_reading;
+ aString.EndReading(done_reading);
+
+ PRInt32 state = 0;
+ PRBool overlong = PR_FALSE;
+ PRBool surrogate = PR_FALSE;
+ PRBool nonchar = PR_FALSE;
+ PRUint16 olupper = 0; // overlong byte upper bound.
+ PRUint16 slower = 0; // surrogate byte lower bound.
+
+ // for each chunk of |aString|...
+ PRUint32 fragmentLength = 0;
+ nsReadingIterator<char> iter;
+
+ for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
+ {
+ fragmentLength = PRUint32(iter.size_forward());
+ const char* ptr = iter.get();
+ const char* fragmentEnd = ptr + fragmentLength;
+
+ // for each character in this chunk...
+ while ( ptr < fragmentEnd )
+ {
+ PRUint8 c;
+
+ if (0 == state)
+ {
+ c = *ptr++;
+
+ if ( UTF8traits::isASCII(c) )
+ continue;
+
+ if ( c <= 0xC1 ) // [80-BF] where not expected, [C0-C1] for overlong.
+ return PR_FALSE;
+ else if ( UTF8traits::is2byte(c) )
+ state = 1;
+ else if ( UTF8traits::is3byte(c) )
+ {
+ state = 2;
+ if ( c == 0xE0 ) // to exclude E0[80-9F][80-BF]
+ {
+ overlong = PR_TRUE;
+ olupper = 0x9F;
+ }
+ else if ( c == 0xED ) // ED[A0-BF][80-BF] : surrogate codepoint
+ {
+ surrogate = PR_TRUE;
+ slower = 0xA0;
+ }
+ else if ( c == 0xEF ) // EF BF [BE-BF] : non-character
+ nonchar = PR_TRUE;
+ }
+ else if ( c <= 0xF4 ) // XXX replace /w UTF8traits::is4byte when it's updated to exclude [F5-F7].(bug 199090)
+ {
+ state = 3;
+ nonchar = PR_TRUE;
+ if ( c == 0xF0 ) // to exclude F0[80-8F][80-BF]{2}
+ {
+ overlong = PR_TRUE;
+ olupper = 0x8F;
+ }
+ else if ( c == 0xF4 ) // to exclude F4[90-BF][80-BF]
+ {
+ // actually not surrogates but codepoints beyond 0x10FFFF
+ surrogate = PR_TRUE;
+ slower = 0x90;
+ }
+ }
+ else
+ return PR_FALSE; // Not UTF-8 string
+ }
+
+ while (ptr < fragmentEnd && state)
+ {
+ c = *ptr++;
+ --state;
+
+ // non-character : EF BF [BE-BF] or F[0-7] [89AB]F BF [BE-BF]
+ if ( nonchar && ( (!state && c < 0xBE) ||
+ (state == 1 && c != 0xBF) ||
+ (state == 2 && 0x0F != (0x0F & c)) ))
+ nonchar = PR_FALSE;
+
+ if ( !UTF8traits::isInSeq(c) || (overlong && c <= olupper) ||
+ (surrogate && slower <= c) || (nonchar && !state) )
+ return PR_FALSE; // Not UTF-8 string
+ overlong = surrogate = PR_FALSE;
+ }
+ }
+ }
+ return !state; // state != 0 at the end indicates an invalid UTF-8 seq.
+ }
+
+ /**
+ * A character sink for in-place case conversion.
+ */
+class ConvertToUpperCase
+ {
+ public:
+ typedef char value_type;
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ char* cp = NS_CONST_CAST(char*,aSource);
+ const char* end = aSource + aSourceLength;
+ while (cp != end) {
+ char ch = *cp;
+ if ((ch >= 'a') && (ch <= 'z'))
+ *cp = ch - ('a' - 'A');
+ ++cp;
+ }
+ return aSourceLength;
+ }
+ };
+
+NS_COM
+void
+ToUpperCase( nsACString& aCString )
+ {
+ nsACString::iterator fromBegin, fromEnd;
+ ConvertToUpperCase converter;
+ copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
+ }
+
+NS_COM
+void
+ToUpperCase( nsCSubstring& aCString )
+ {
+ ConvertToUpperCase converter;
+ char* start;
+ converter.write(aCString.BeginWriting(start), aCString.Length());
+ }
+
+ /**
+ * A character sink for copying with case conversion.
+ */
+class CopyToUpperCase
+ {
+ public:
+ typedef char value_type;
+
+ CopyToUpperCase( nsACString::iterator& aDestIter )
+ : mIter(aDestIter)
+ {
+ }
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ PRUint32 len = PR_MIN(PRUint32(mIter.size_forward()), aSourceLength);
+ char* cp = mIter.get();
+ const char* end = aSource + len;
+ while (aSource != end) {
+ char ch = *aSource;
+ if ((ch >= 'a') && (ch <= 'z'))
+ *cp = ch - ('a' - 'A');
+ else
+ *cp = ch;
+ ++aSource;
+ ++cp;
+ }
+ mIter.advance(len);
+ return len;
+ }
+
+ protected:
+ nsACString::iterator& mIter;
+ };
+
+NS_COM
+void
+ToUpperCase( const nsACString& aSource, nsACString& aDest )
+ {
+ nsACString::const_iterator fromBegin, fromEnd;
+ nsACString::iterator toBegin;
+ aDest.SetLength(aSource.Length());
+ CopyToUpperCase converter(aDest.BeginWriting(toBegin));
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+ /**
+ * A character sink for case conversion.
+ */
+class ConvertToLowerCase
+ {
+ public:
+ typedef char value_type;
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ char* cp = NS_CONST_CAST(char*,aSource);
+ const char* end = aSource + aSourceLength;
+ while (cp != end) {
+ char ch = *cp;
+ if ((ch >= 'A') && (ch <= 'Z'))
+ *cp = ch + ('a' - 'A');
+ ++cp;
+ }
+ return aSourceLength;
+ }
+ };
+
+NS_COM
+void
+ToLowerCase( nsACString& aCString )
+ {
+ nsACString::iterator fromBegin, fromEnd;
+ ConvertToLowerCase converter;
+ copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
+ }
+
+NS_COM
+void
+ToLowerCase( nsCSubstring& aCString )
+ {
+ ConvertToLowerCase converter;
+ char* start;
+ converter.write(aCString.BeginWriting(start), aCString.Length());
+ }
+
+ /**
+ * A character sink for copying with case conversion.
+ */
+class CopyToLowerCase
+ {
+ public:
+ typedef char value_type;
+
+ CopyToLowerCase( nsACString::iterator& aDestIter )
+ : mIter(aDestIter)
+ {
+ }
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ PRUint32 len = PR_MIN(PRUint32(mIter.size_forward()), aSourceLength);
+ char* cp = mIter.get();
+ const char* end = aSource + len;
+ while (aSource != end) {
+ char ch = *aSource;
+ if ((ch >= 'A') && (ch <= 'Z'))
+ *cp = ch + ('a' - 'A');
+ else
+ *cp = ch;
+ ++aSource;
+ ++cp;
+ }
+ mIter.advance(len);
+ return len;
+ }
+
+ protected:
+ nsACString::iterator& mIter;
+ };
+
+NS_COM
+void
+ToLowerCase( const nsACString& aSource, nsACString& aDest )
+ {
+ nsACString::const_iterator fromBegin, fromEnd;
+ nsACString::iterator toBegin;
+ aDest.SetLength(aSource.Length());
+ CopyToLowerCase converter(aDest.BeginWriting(toBegin));
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+template <class StringT, class IteratorT, class Comparator>
+PRBool
+FindInReadable_Impl( const StringT& aPattern, IteratorT& aSearchStart, IteratorT& aSearchEnd, const Comparator& compare )
+ {
+ PRBool found_it = PR_FALSE;
+
+ // only bother searching at all if we're given a non-empty range to search
+ if ( aSearchStart != aSearchEnd )
+ {
+ IteratorT aPatternStart, aPatternEnd;
+ aPattern.BeginReading(aPatternStart);
+ aPattern.EndReading(aPatternEnd);
+
+ // outer loop keeps searching till we find it or run out of string to search
+ while ( !found_it )
+ {
+ // fast inner loop (that's what it's called, not what it is) looks for a potential match
+ while ( aSearchStart != aSearchEnd &&
+ compare(*aPatternStart, *aSearchStart) )
+ ++aSearchStart;
+
+ // if we broke out of the `fast' loop because we're out of string ... we're done: no match
+ if ( aSearchStart == aSearchEnd )
+ break;
+
+ // otherwise, we're at a potential match, let's see if we really hit one
+ IteratorT testPattern(aPatternStart);
+ IteratorT testSearch(aSearchStart);
+
+ // slow inner loop verifies the potential match (found by the `fast' loop) at the current position
+ for(;;)
+ {
+ // we already compared the first character in the outer loop,
+ // so we'll advance before the next comparison
+ ++testPattern;
+ ++testSearch;
+
+ // if we verified all the way to the end of the pattern, then we found it!
+ if ( testPattern == aPatternEnd )
+ {
+ found_it = PR_TRUE;
+ aSearchEnd = testSearch; // return the exact found range through the parameters
+ break;
+ }
+
+ // if we got to end of the string we're searching before we hit the end of the
+ // pattern, we'll never find what we're looking for
+ if ( testSearch == aSearchEnd )
+ {
+ aSearchStart = aSearchEnd;
+ break;
+ }
+
+ // else if we mismatched ... it's time to advance to the next search position
+ // and get back into the `fast' loop
+ if ( compare(*testPattern, *testSearch) )
+ {
+ ++aSearchStart;
+ break;
+ }
+ }
+ }
+ }
+
+ return found_it;
+ }
+
+
+NS_COM
+PRBool
+FindInReadable( const nsAString& aPattern, nsAString::const_iterator& aSearchStart, nsAString::const_iterator& aSearchEnd, const nsStringComparator& aComparator )
+ {
+ return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, aComparator);
+ }
+
+NS_COM
+PRBool
+FindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd, const nsCStringComparator& aComparator)
+ {
+ return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, aComparator);
+ }
+
+NS_COM
+PRBool
+CaseInsensitiveFindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd )
+ {
+ return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, nsCaseInsensitiveCStringComparator());
+ }
+
+ /**
+ * This implementation is simple, but does too much work.
+ * It searches the entire string from left to right, and returns the last match found, if any.
+ * This implementation will be replaced when I get |reverse_iterator|s working.
+ */
+NS_COM
+PRBool
+RFindInReadable( const nsAString& aPattern, nsAString::const_iterator& aSearchStart, nsAString::const_iterator& aSearchEnd, const nsStringComparator& aComparator)
+ {
+ PRBool found_it = PR_FALSE;
+
+ nsAString::const_iterator savedSearchEnd(aSearchEnd);
+ nsAString::const_iterator searchStart(aSearchStart), searchEnd(aSearchEnd);
+
+ while ( searchStart != searchEnd )
+ {
+ if ( FindInReadable(aPattern, searchStart, searchEnd, aComparator) )
+ {
+ found_it = PR_TRUE;
+
+ // this is the best match so far, so remember it
+ aSearchStart = searchStart;
+ aSearchEnd = searchEnd;
+
+ // ...and get ready to search some more
+ // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns)
+ ++searchStart;
+ searchEnd = savedSearchEnd;
+ }
+ }
+
+ // if we never found it, return an empty range
+ if ( !found_it )
+ aSearchStart = aSearchEnd;
+
+ return found_it;
+ }
+
+NS_COM
+PRBool
+RFindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd, const nsCStringComparator& aComparator)
+ {
+ PRBool found_it = PR_FALSE;
+
+ nsACString::const_iterator savedSearchEnd(aSearchEnd);
+ nsACString::const_iterator searchStart(aSearchStart), searchEnd(aSearchEnd);
+
+ while ( searchStart != searchEnd )
+ {
+ if ( FindInReadable(aPattern, searchStart, searchEnd, aComparator) )
+ {
+ found_it = PR_TRUE;
+
+ // this is the best match so far, so remember it
+ aSearchStart = searchStart;
+ aSearchEnd = searchEnd;
+
+ // ...and get ready to search some more
+ // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns)
+ ++searchStart;
+ searchEnd = savedSearchEnd;
+ }
+ }
+
+ // if we never found it, return an empty range
+ if ( !found_it )
+ aSearchStart = aSearchEnd;
+
+ return found_it;
+ }
+
+NS_COM
+PRBool
+FindCharInReadable( PRUnichar aChar, nsAString::const_iterator& aSearchStart, const nsAString::const_iterator& aSearchEnd )
+ {
+ PRInt32 fragmentLength = aSearchEnd.get() - aSearchStart.get();
+
+ const PRUnichar* charFoundAt = nsCharTraits<PRUnichar>::find(aSearchStart.get(), fragmentLength, aChar);
+ if ( charFoundAt ) {
+ aSearchStart.advance( charFoundAt - aSearchStart.get() );
+ return PR_TRUE;
+ }
+
+ aSearchStart.advance(fragmentLength);
+ return PR_FALSE;
+ }
+
+NS_COM
+PRBool
+FindCharInReadable( char aChar, nsACString::const_iterator& aSearchStart, const nsACString::const_iterator& aSearchEnd )
+ {
+ PRInt32 fragmentLength = aSearchEnd.get() - aSearchStart.get();
+
+ const char* charFoundAt = nsCharTraits<char>::find(aSearchStart.get(), fragmentLength, aChar);
+ if ( charFoundAt ) {
+ aSearchStart.advance( charFoundAt - aSearchStart.get() );
+ return PR_TRUE;
+ }
+
+ aSearchStart.advance(fragmentLength);
+ return PR_FALSE;
+ }
+
+NS_COM
+PRUint32
+CountCharInReadable( const nsAString& aStr,
+ PRUnichar aChar )
+{
+ PRUint32 count = 0;
+ nsAString::const_iterator begin, end;
+
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+
+ while (begin != end) {
+ if (*begin == aChar) {
+ ++count;
+ }
+ ++begin;
+ }
+
+ return count;
+}
+
+NS_COM
+PRUint32
+CountCharInReadable( const nsACString& aStr,
+ char aChar )
+{
+ PRUint32 count = 0;
+ nsACString::const_iterator begin, end;
+
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+
+ while (begin != end) {
+ if (*begin == aChar) {
+ ++count;
+ }
+ ++begin;
+ }
+
+ return count;
+}
+
+NS_COM PRBool
+StringBeginsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator )
+ {
+ nsAString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
+ }
+
+NS_COM PRBool
+StringBeginsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator )
+ {
+ nsACString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
+ }
+
+NS_COM PRBool
+StringEndsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator )
+ {
+ nsAString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring,
+ aComparator);
+ }
+
+NS_COM PRBool
+StringEndsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator )
+ {
+ nsACString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring,
+ aComparator);
+ }
+
+
+
+template <class CharT>
+class CalculateHashCode
+ {
+ public:
+ typedef CharT char_type;
+ typedef PRUint32 hashcode_type;
+ typedef CharT value_type;
+
+ CalculateHashCode() : mHashCode(0) { }
+ hashcode_type GetHashCode() const { return mHashCode; }
+
+ PRUint32 write( const CharT* chars, PRUint32 N )
+ {
+ for ( const CharT *end = chars + N; chars < end; ++chars)
+ mHashCode = (mHashCode>>28) ^ (mHashCode<<4) ^ PRUint32(*chars);
+ return N;
+ }
+
+ private:
+ hashcode_type mHashCode;
+ };
+
+NS_COM PRUint32 HashString( const nsAString& aStr )
+ {
+ CalculateHashCode<nsAString::char_type> sink;
+ nsAString::const_iterator begin, end;
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+ copy_string(begin, end, sink);
+ return sink.GetHashCode();
+ }
+
+NS_COM PRUint32 HashString( const nsACString& aStr )
+ {
+ CalculateHashCode<nsACString::char_type> sink;
+ nsACString::const_iterator begin, end;
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+ copy_string(begin, end, sink);
+ return sink.GetHashCode();
+ }
+
+static const PRUnichar empty_buffer[1] = { '\0' };
+
+NS_COM const nsAFlatString& EmptyString()
+ {
+ static const nsDependentString sEmpty(empty_buffer);
+
+ return sEmpty;
+ }
+
+NS_COM const nsAFlatCString& EmptyCString()
+ {
+ static const nsDependentCString sEmpty((const char *)empty_buffer);
+
+ return sEmpty;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp
new file mode 100644
index 00000000..aedf3295
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+
+ // define nsString
+#include "string-template-def-unichar.h"
+#include "nsTString.cpp"
+#include "string-template-undef.h"
+
+ // define nsCString
+#include "string-template-def-char.h"
+#include "nsTString.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp
new file mode 100644
index 00000000..ced75c73
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 <ctype.h>
+#include "nsAString.h"
+#include "plstr.h"
+
+
+ // define nsStringComparator
+#include "string-template-def-unichar.h"
+#include "nsTStringComparator.cpp"
+#include "string-template-undef.h"
+
+ // define nsCStringComparator
+#include "string-template-def-char.h"
+#include "nsTStringComparator.cpp"
+#include "string-template-undef.h"
+
+
+int
+nsCaseInsensitiveCStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
+ {
+ PRInt32 result=PRInt32(PL_strncasecmp(lhs, rhs, aLength));
+ //Egads. PL_strncasecmp is returning *very* negative numbers.
+ //Some folks expect -1,0,1, so let's temper its enthusiasm.
+ if (result<0)
+ result=-1;
+ return result;
+ }
+
+int
+nsCaseInsensitiveCStringComparator::operator()( char lhs, char rhs ) const
+ {
+ if (lhs == rhs) return 0;
+
+ lhs = tolower(lhs);
+ rhs = tolower(rhs);
+
+ return lhs - rhs;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
new file mode 100644
index 00000000..76106a27
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
@@ -0,0 +1,1327 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+
+
+ /**
+ * nsTString obsolete API support
+ */
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+
+#include "nsDependentString.h"
+#include "nsDependentSubstring.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsUTF8Utils.h"
+#include "prdtoa.h"
+#include "prprf.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+/* ***** BEGIN RICKG BLOCK *****
+ *
+ * NOTE: This section of code was extracted from rickg's bufferRoutines.h file.
+ * For the most part it remains unmodified. We want to eliminate (or at
+ * least clean up) this code at some point. If you find the formatting
+ * in this section somewhat inconsistent, don't blame me! ;-)
+ */
+
+// XXXdarin what is wrong with STDC's tolower?
+inline char
+ascii_tolower(char aChar)
+{
+ if (aChar >= 'A' && aChar <= 'Z')
+ return aChar + ('a' - 'A');
+ return aChar;
+}
+
+//-----------------------------------------------------------------------------
+//
+// This set of methods is used to search a buffer looking for a char.
+//
+
+
+/**
+ * This methods cans the given buffer for the given char
+ *
+ * @update gess 02/17/00
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+static PRInt32
+FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=0;
+
+ if(aCount < 0)
+ aCount = (PRInt32)aDestLength;
+
+ if((aChar < 256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ //We'll only search if the given aChar is within the normal ascii a range,
+ //(Since this string is definitely within the ascii range).
+
+ if(0<aCount) {
+
+ const char* left= aDest+anOffset;
+ const char* last= left+aCount;
+ const char* max = aDest+aDestLength;
+ const char* end = (last<max) ? last : max;
+
+ PRInt32 theMax = end-left;
+ if(0<theMax) {
+
+ unsigned char theChar = (unsigned char) aChar;
+ const char* result=(const char*)memchr(left, (int)theChar, theMax);
+
+ if(result)
+ return result-aDest;
+
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+
+/**
+ * This methods cans the given buffer for the given char
+ *
+ * @update gess 3/25/98
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+static PRInt32
+FindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=0;
+
+ if(aCount < 0)
+ aCount = (PRInt32)aDestLength;
+
+ if((0<aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ if(0<aCount) {
+
+ const PRUnichar* root = aDest;
+ const PRUnichar* left = root+anOffset;
+ const PRUnichar* last = left+aCount;
+ const PRUnichar* max = root+aDestLength;
+ const PRUnichar* end = (last<max) ? last : max;
+
+ while(left<end){
+
+ if(*left==aChar)
+ return (left-root);
+
+ ++left;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+
+/**
+ * This methods cans the given buffer (in reverse) for the given char
+ *
+ * @update gess 02/17/00
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+
+static PRInt32
+RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=(PRInt32)aDestLength-1;
+
+ if(aCount < 0)
+ aCount = PRInt32(aDestLength);
+
+ if((aChar<256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ //We'll only search if the given aChar is within the normal ascii a range,
+ //(Since this string is definitely within the ascii range).
+
+ if(0 < aCount) {
+
+ const char* rightmost = aDest + anOffset;
+ const char* min = rightmost - aCount + 1;
+ const char* leftmost = (min<aDest) ? aDest: min;
+
+ char theChar=(char)aChar;
+ while(leftmost <= rightmost){
+
+ if((*rightmost) == theChar)
+ return rightmost - aDest;
+
+ --rightmost;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+
+/**
+ * This methods cans the given buffer for the given char
+ *
+ * @update gess 3/25/98
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+static PRInt32
+RFindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=(PRInt32)aDestLength-1;
+
+ if(aCount < 0)
+ aCount = PRInt32(aDestLength);
+
+ if((0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ if(0 < aCount) {
+
+ const PRUnichar* root = aDest;
+ const PRUnichar* rightmost = root + anOffset;
+ const PRUnichar* min = rightmost - aCount + 1;
+ const PRUnichar* leftmost = (min<root) ? root: min;
+
+ while(leftmost <= rightmost){
+
+ if((*rightmost) == aChar)
+ return rightmost - root;
+
+ --rightmost;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+//-----------------------------------------------------------------------------
+//
+// This set of methods is used to compare one buffer onto another. The
+// functions are differentiated by the size of source and dest character
+// sizes. WARNING: Your destination buffer MUST be big enough to hold all the
+// source bytes. We don't validate these ranges here (this should be done in
+// higher level routines).
+//
+
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ PRInt32 result=0;
+ if(aIgnoreCase)
+ result=PRInt32(PL_strncasecmp(aStr1, aStr2, aCount));
+ else
+ result=nsCharTraits<char>::compare(aStr1,aStr2,aCount);
+
+ // alien comparisons may return out-of-bound answers
+ // instead of the -1, 0, 1 expected by most clients
+ if ( result < -1 )
+ result = -1;
+ else if ( result > 1 )
+ result = 1;
+ return result;
+}
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare2To2(const PRUnichar* aStr1,const PRUnichar* aStr2,PRUint32 aCount){
+ PRInt32 result;
+
+ if ( aStr1 && aStr2 )
+ result = nsCharTraits<PRUnichar>::compare(aStr1, aStr2, aCount);
+
+ // The following cases are rare and survivable caller errors.
+ // Two null pointers are equal, but any string, even 0 length
+ // is greater than a null pointer. It might not really matter,
+ // but we pick something reasonable anyway.
+ else if ( !aStr1 && !aStr2 )
+ result = 0;
+ else if ( aStr1 )
+ result = 1;
+ else
+ result = -1;
+
+ // alien comparisons may give answers outside the -1, 0, 1 expected by callers
+ if ( result < -1 )
+ result = -1;
+ else if ( result > 1 )
+ result = 1;
+ return result;
+}
+
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare2To1(const PRUnichar* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ const PRUnichar* s1 = aStr1;
+ const char *s2 = aStr2;
+
+ if (aStr1 && aStr2) {
+ if (aCount != 0) {
+ do {
+
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = PRUnichar((unsigned char)*s2++);
+
+ if (c1 != c2) {
+#ifdef NS_DEBUG
+ // we won't warn on c1>=128 (the 2-byte value) because often
+ // it is just fine to compare an constant, ascii value (i.e. "body")
+ // against some non-ascii value (i.e. a unicode string that
+ // was downloaded from a web page)
+ if (aIgnoreCase && c2>=128)
+ NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!");
+#endif
+
+ // can't do case conversion on characters out of our range
+ if (aIgnoreCase && c1<128 && c2<128) {
+
+ c1 = ascii_tolower(char(c1));
+ c2 = ascii_tolower(char(c2));
+
+ if (c1 == c2) continue;
+ }
+
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ } while (--aCount);
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+inline PRInt32
+Compare1To2(const char* aStr1,const PRUnichar* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// This set of methods is used compress char sequences in a buffer...
+//
+
+
+/**
+ * This method compresses duplicate runs of a given char from the given buffer
+ *
+ * @update rickg 03.23.2000
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
+
+ char* from = aString;
+ char* end = aString + aLength;
+ char* to = from;
+
+ //this code converts /n, /t, /r into normal space ' ';
+ //it also compresses runs of whitespace down to a single char...
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+
+ while (from < end) {
+ char theChar = *from++;
+
+ *to++=theChar; //always copy this char...
+
+ if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
+ while (from < end) {
+ theChar = *from++;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ break;
+ }
+ } //while
+ } //if
+ } //if
+ *to = 0;
+ }
+ return to - aString;
+}
+
+
+
+/**
+ * This method compresses duplicate runs of a given char from the given buffer
+ *
+ * @update rickg 03.23.2000
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+CompressChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
+
+ PRUnichar* from = aString;
+ PRUnichar* end = from + aLength;
+ PRUnichar* to = from;
+
+ //this code converts /n, /t, /r into normal space ' ';
+ //it also compresses runs of whitespace down to a single char...
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+
+ while (from < end) {
+ PRUnichar theChar = *from++;
+
+ *to++=theChar; //always copy this char...
+
+ if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
+ while (from < end) {
+ theChar = *from++;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ break;
+ }
+ } //while
+ } //if
+ } //if
+ *to = 0;
+ }
+ return to - (PRUnichar*)aString;
+}
+
+/**
+ * This method strips chars in a given set from the given buffer
+ *
+ * @update gess 01/04/99
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+StripChars1(char* aString,PRUint32 aLength,const char* aSet){
+
+ // XXXdarin this code should defer writing until necessary.
+
+ char* to = aString;
+ char* from = aString-1;
+ char* end = aString + aLength;
+
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+ while (++from < end) {
+ char theChar = *from;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ }
+ }
+ *to = 0;
+ }
+ return to - (char*)aString;
+}
+
+
+/**
+ * This method strips chars in a given set from the given buffer
+ *
+ * @update gess 01/04/99
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+StripChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
+
+ // XXXdarin this code should defer writing until necessary.
+
+ PRUnichar* to = aString;
+ PRUnichar* from = aString-1;
+ PRUnichar* end = to + aLength;
+
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+ while (++from < end) {
+ PRUnichar theChar = *from;
+ //Note the test for ascii range below. If you have a real unicode char,
+ //and you're searching for chars in the (given) ascii string, there's no
+ //point in doing the real search since it's out of the ascii range.
+ if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
+ *to++ = theChar;
+ }
+ }
+ *to = 0;
+ }
+ return to - (PRUnichar*)aString;
+}
+
+/* ***** END RICKG BLOCK ***** */
+
+static const char* kWhitespace="\b\t\r\n ";
+
+// This function is used to implement FindCharInSet and friends
+template <class CharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+CharT
+GetFindInSetFilter( const CharT* set)
+ {
+ CharT filter = ~CharT(0); // All bits set
+ while (*set) {
+ filter &= ~(*set);
+ ++set;
+ }
+ return filter;
+ }
+
+// This template class is used by our code to access rickg's buffer routines.
+template <class CharT> struct nsBufferRoutines {};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsBufferRoutines<char>
+ {
+ static
+ PRInt32 compare( const char* a, const char* b, PRUint32 max, PRBool ic )
+ {
+ return Compare1To1(a, b, max, ic);
+ }
+
+ static
+ PRInt32 compare( const char* a, const PRUnichar* b, PRUint32 max, PRBool ic )
+ {
+ return Compare1To2(a, b, max, ic);
+ }
+
+ static
+ PRInt32 find_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return FindChar1(s, max, offset, c, count);
+ }
+
+ static
+ PRInt32 rfind_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return RFindChar1(s, max, offset, c, count);
+ }
+
+ static
+ char get_find_in_set_filter( const char* set )
+ {
+ return GetFindInSetFilter(set);
+ }
+
+ static
+ PRInt32 strip_chars( char* s, PRUint32 len, const char* set )
+ {
+ return StripChars1(s, len, set);
+ }
+
+ static
+ PRInt32 compress_chars( char* s, PRUint32 len, const char* set )
+ {
+ return CompressChars1(s, len, set);
+ }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsBufferRoutines<PRUnichar>
+ {
+ static
+ PRInt32 compare( const PRUnichar* a, const PRUnichar* b, PRUint32 max, PRBool ic )
+ {
+ NS_ASSERTION(!ic, "no case-insensitive compare here");
+ return Compare2To2(a, b, max);
+ }
+
+ static
+ PRInt32 compare( const PRUnichar* a, const char* b, PRUint32 max, PRBool ic )
+ {
+ return Compare2To1(a, b, max, ic);
+ }
+
+ static
+ PRInt32 find_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return FindChar2(s, max, offset, c, count);
+ }
+
+ static
+ PRInt32 rfind_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return RFindChar2(s, max, offset, c, count);
+ }
+
+ static
+ PRUnichar get_find_in_set_filter( const PRUnichar* set )
+ {
+ return GetFindInSetFilter(set);
+ }
+
+ static
+ PRUnichar get_find_in_set_filter( const char* set )
+ {
+ return (~PRUnichar(0)^~char(0)) | GetFindInSetFilter(set);
+ }
+
+ static
+ PRInt32 strip_chars( PRUnichar* s, PRUint32 max, const char* set )
+ {
+ return StripChars2(s, max, set);
+ }
+
+ static
+ PRInt32 compress_chars( PRUnichar* s, PRUint32 len, const char* set )
+ {
+ return CompressChars2(s, len, set);
+ }
+ };
+
+//-----------------------------------------------------------------------------
+
+template <class L, class R>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+FindSubstring( const L* big, PRUint32 bigLen,
+ const R* little, PRUint32 littleLen,
+ PRBool ignoreCase )
+ {
+ if (littleLen > bigLen)
+ return kNotFound;
+
+ PRInt32 i, max = PRInt32(bigLen - littleLen);
+ for (i=0; i<=max; ++i, ++big)
+ {
+ if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0)
+ return i;
+ }
+
+ return kNotFound;
+ }
+
+template <class L, class R>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+RFindSubstring( const L* big, PRUint32 bigLen,
+ const R* little, PRUint32 littleLen,
+ PRBool ignoreCase )
+ {
+ if (littleLen > bigLen)
+ return kNotFound;
+
+ PRInt32 i, max = PRInt32(bigLen - littleLen);
+
+ const L* iter = big + max;
+ for (i=max; iter >= big; --i, --iter)
+ {
+ if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0)
+ return i;
+ }
+
+ return kNotFound;
+ }
+
+template <class CharT, class SetCharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+FindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
+ {
+ CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
+
+ const CharT* end = data + dataLen;
+ for (const CharT* iter = data; iter < end; ++iter)
+ {
+ CharT currentChar = *iter;
+ if (currentChar & filter)
+ continue; // char is not in filter set; go on with next char.
+
+ // test all chars
+ const SetCharT* charInSet = set;
+ CharT setChar = CharT(*charInSet);
+ while (setChar)
+ {
+ if (setChar == currentChar)
+ return iter - data; // found it! return index of the found char.
+
+ setChar = CharT(*(++charInSet));
+ }
+ }
+ return kNotFound;
+ }
+
+template <class CharT, class SetCharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+RFindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
+ {
+ CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
+
+ for (const CharT* iter = data + dataLen - 1; iter >= data; --iter)
+ {
+ CharT currentChar = *iter;
+ if (currentChar & filter)
+ continue; // char is not in filter set; go on with next char.
+
+ // test all chars
+ const CharT* charInSet = set;
+ CharT setChar = *charInSet;
+ while (setChar)
+ {
+ if (setChar == currentChar)
+ return iter - data; // found it! return index of the found char.
+
+ setChar = *(++charInSet);
+ }
+ }
+ return kNotFound;
+ }
+
+/**
+ * This is a copy of |PR_cnvtf| with a bug fixed. (The second argument
+ * of PR_dtoa is 2 rather than 1.)
+ *
+ * XXXdarin if this is the right thing, then why wasn't it fixed in NSPR?!?
+ */
+void
+Modified_cnvtf(char *buf, int bufsz, int prcsn, double fval)
+{
+ PRIntn decpt, sign, numdigits;
+ char *num, *nump;
+ char *bufp = buf;
+ char *endnum;
+
+ /* If anything fails, we store an empty string in 'buf' */
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ num = (char*)RTMemAlloc(bufsz);
+#else
+ num = (char*)malloc(bufsz);
+#endif
+ if (num == NULL) {
+ buf[0] = '\0';
+ return;
+ }
+ if (PR_dtoa(fval, 2, prcsn, &decpt, &sign, &endnum, num, bufsz)
+ == PR_FAILURE) {
+ buf[0] = '\0';
+ goto done;
+ }
+ numdigits = endnum - num;
+ nump = num;
+
+ /*
+ * The NSPR code had a fancy way of checking that we weren't dealing
+ * with -0.0 or -NaN, but I'll just use < instead.
+ * XXX Should we check !isnan(fval) as well? Is it portable? We
+ * probably don't need to bother since NAN isn't portable.
+ */
+ if (sign && fval < 0.0f) {
+ *bufp++ = '-';
+ }
+
+ if (decpt == 9999) {
+ while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */
+ goto done;
+ }
+
+ if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) {
+ *bufp++ = *nump++;
+ if (numdigits != 1) {
+ *bufp++ = '.';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = 'e';
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+d", decpt-1);
+ }
+ else if (decpt >= 0) {
+ if (decpt == 0) {
+ *bufp++ = '0';
+ }
+ else {
+ while (decpt--) {
+ if (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ else {
+ *bufp++ = '0';
+ }
+ }
+ }
+ if (*nump != '\0') {
+ *bufp++ = '.';
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ }
+ *bufp++ = '\0';
+ }
+ else if (decpt < 0) {
+ *bufp++ = '0';
+ *bufp++ = '.';
+ while (decpt++) {
+ *bufp++ = '0';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = '\0';
+ }
+done:
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(num);
+#else
+ free(num);
+#endif
+}
+
+ /**
+ * this method changes the meaning of |offset| and |count|:
+ *
+ * upon return,
+ * |offset| specifies start of search range
+ * |count| specifies length of search range
+ */
+static void
+Find_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
+ {
+ // |count| specifies how many iterations to make from |offset|
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+ else if (PRUint32(offset) > bigLen)
+ {
+ count = 0;
+ return;
+ }
+
+ PRInt32 maxCount = bigLen - offset;
+ if (count < 0 || count > maxCount)
+ {
+ count = maxCount;
+ }
+ else
+ {
+ count += littleLen;
+ if (count > maxCount)
+ count = maxCount;
+ }
+ }
+
+ /**
+ * this method changes the meaning of |offset| and |count|:
+ *
+ * upon entry,
+ * |offset| specifies the end point from which to search backwards
+ * |count| specifies the number of iterations from |offset|
+ *
+ * upon return,
+ * |offset| specifies start of search range
+ * |count| specifies length of search range
+ *
+ *
+ * EXAMPLE
+ *
+ * + -- littleLen=4 -- +
+ * : :
+ * |____|____|____|____|____|____|____|____|____|____|____|____|
+ * : :
+ * offset=5 bigLen=12
+ *
+ * if count = 4, then we expect this function to return offset = 2 and
+ * count = 7.
+ *
+ */
+static void
+RFind_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
+ {
+ if (littleLen > bigLen)
+ {
+ offset = 0;
+ count = 0;
+ return;
+ }
+
+ if (offset < 0)
+ offset = bigLen - littleLen;
+ if (count < 0)
+ count = offset + 1;
+
+ PRInt32 start = offset - count + 1;
+ if (start < 0)
+ start = 0;
+
+ count = offset + littleLen - start;
+ offset = start;
+ }
+
+//-----------------------------------------------------------------------------
+
+ // define nsString obsolete methods
+#include "string-template-def-unichar.h"
+#include "nsTStringObsolete.cpp"
+#include "string-template-undef.h"
+
+ // define nsCString obsolete methods
+#include "string-template-def-char.h"
+#include "nsTStringObsolete.cpp"
+#include "string-template-undef.h"
+
+//-----------------------------------------------------------------------------
+
+// specialized methods:
+
+PRInt32
+nsString::Find( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsString::Find( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ return Find(nsDependentString(aString), aOffset, aCount);
+ }
+
+PRInt32
+nsString::RFind( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsString::RFind( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ return RFind(nsDependentString(aString), aOffset, aCount);
+ }
+
+PRInt32
+nsString::FindCharInSet( const PRUnichar* aSet, PRInt32 aOffset ) const
+ {
+ if (aOffset < 0)
+ aOffset = 0;
+ else if (aOffset >= PRInt32(mLength))
+ return kNotFound;
+
+ PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+
+ /**
+ * nsTString::Compare,CompareWithConversion,etc.
+ */
+
+PRInt32
+nsCString::Compare( const char* aString, PRBool aIgnoreCase, PRInt32 aCount ) const
+ {
+ PRUint32 strLen = char_traits::length(aString);
+
+ PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
+
+ PRInt32 compareCount;
+ if (aCount < 0 || aCount > maxCount)
+ compareCount = maxCount;
+ else
+ compareCount = aCount;
+
+ PRInt32 result =
+ nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase);
+
+ if (result == 0 &&
+ (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
+ {
+ // Since the caller didn't give us a length to test, or strings shorter
+ // than aCount, and compareCount characters matched, we have to assume
+ // that the longer string is greater.
+
+ if (mLength != strLen)
+ result = (mLength < strLen) ? -1 : 1;
+ }
+ return result;
+ }
+
+PRBool
+nsString::EqualsIgnoreCase( const char* aString, PRInt32 aCount ) const
+ {
+ PRUint32 strLen = nsCharTraits<char>::length(aString);
+
+ PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
+
+ PRInt32 compareCount;
+ if (aCount < 0 || aCount > maxCount)
+ compareCount = maxCount;
+ else
+ compareCount = aCount;
+
+ PRInt32 result =
+ nsBufferRoutines<PRUnichar>::compare(mData, aString, compareCount, PR_TRUE);
+
+ if (result == 0 &&
+ (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
+ {
+ // Since the caller didn't give us a length to test, or strings shorter
+ // than aCount, and compareCount characters matched, we have to assume
+ // that the longer string is greater.
+
+ if (mLength != strLen)
+ result = 1; // Arbitrarily using any number != 0
+ }
+ return result == 0;
+ }
+
+ /**
+ * ToCString, ToFloat, ToInteger
+ */
+
+char*
+nsString::ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset ) const
+ {
+ // because the old implementation checked aBuf
+ if (!(aBuf && aBufLength > 0 && aOffset <= mLength))
+ return nsnull;
+
+ PRUint32 maxCount = NS_MIN(aBufLength-1, mLength - aOffset);
+
+ LossyConvertEncoding<PRUnichar, char> converter(aBuf);
+ converter.write(mData + aOffset, maxCount);
+ converter.write_terminator();
+ return aBuf;
+ }
+
+float
+nsCString::ToFloat(PRInt32* aErrorCode) const
+ {
+ float res = 0.0f;
+ if (mLength > 0)
+ {
+ char *conv_stopped;
+ const char *str = mData;
+ // Use PR_strtod, not strtod, since we don't want locale involved.
+ res = (float)PR_strtod(str, &conv_stopped);
+ if (conv_stopped == str+mLength)
+ *aErrorCode = (PRInt32) NS_OK;
+ else // Not all the string was scanned
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ else
+ {
+ // The string was too short (0 characters)
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ return res;
+ }
+
+float
+nsString::ToFloat(PRInt32* aErrorCode) const
+ {
+ float res = 0.0f;
+ char buf[100];
+ if (mLength > 0 && mLength < sizeof(buf))
+ {
+ char *conv_stopped;
+ const char *str = ToCString(buf, sizeof(buf));
+ // Use PR_strtod, not strtod, since we don't want locale involved.
+ res = (float)PR_strtod(str, &conv_stopped);
+ if (conv_stopped == str+mLength)
+ *aErrorCode = (PRInt32) NS_OK;
+ else // Not all the string was scanned
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ else
+ {
+ // The string was too short (0 characters) or too long (sizeof(buf))
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ return res;
+ }
+
+
+ /**
+ * nsTString::AssignWithConversion
+ */
+
+void
+nsCString::AssignWithConversion( const nsAString& aData )
+ {
+ LossyCopyUTF16toASCII(aData, *this);
+ }
+
+void
+nsString::AssignWithConversion( const nsACString& aData )
+ {
+ CopyASCIItoUTF16(aData, *this);
+ }
+
+
+ /**
+ * nsTString::AppendWithConversion
+ */
+
+void
+nsCString::AppendWithConversion( const nsAString& aData )
+ {
+ LossyAppendUTF16toASCII(aData, *this);
+ }
+
+void
+nsString::AppendWithConversion( const nsACString& aData )
+ {
+ AppendASCIItoUTF16(aData, *this);
+ }
+
+
+ /**
+ * nsTString::AppendInt
+ */
+
+void
+nsCString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
+ {
+ char buf[20];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%o";
+ break;
+ case 10:
+ fmt = "%d";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%x";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ Append(buf);
+ }
+
+void
+nsString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
+ {
+ char buf[20];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%o";
+ break;
+ case 10:
+ fmt = "%d";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%x";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ AppendASCIItoUTF16(buf, *this);
+ }
+
+void
+nsCString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
+ {
+ char buf[30];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%llo";
+ break;
+ case 10:
+ fmt = "%lld";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%llx";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ Append(buf);
+ }
+
+void
+nsString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
+ {
+ char buf[30];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%llo";
+ break;
+ case 10:
+ fmt = "%lld";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%llx";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ AppendASCIItoUTF16(buf, *this);
+ }
+
+ /**
+ * nsTString::AppendFloat
+ */
+
+void
+nsCString::AppendFloat( double aFloat )
+ {
+ char buf[40];
+ // Use Modified_cnvtf, which is locale-insensitive, instead of the
+ // locale-sensitive PR_snprintf or sprintf(3)
+ Modified_cnvtf(buf, sizeof(buf), 6, aFloat);
+ Append(buf);
+ }
+
+void
+nsString::AppendFloat( double aFloat )
+ {
+ char buf[40];
+ // Use Modified_cnvtf, which is locale-insensitive, instead of the
+ // locale-sensitive PR_snprintf or sprintf(3)
+ Modified_cnvtf(buf, sizeof(buf), 6, aFloat);
+ AppendWithConversion(buf);
+ }
+
+#endif // !MOZ_STRING_WITH_OBSOLETE_API
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp
new file mode 100644
index 00000000..6ed0c5c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#ifdef DEBUG
+#define ENABLE_STRING_STATS
+#endif
+
+#ifdef ENABLE_STRING_STATS
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+#include "nsSubstring.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+#include "nsMemory.h"
+#include "pratom.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+// ---------------------------------------------------------------------------
+
+static const PRUnichar gNullChar = 0;
+
+const char* nsCharTraits<char> ::sEmptyBuffer = (const char*) &gNullChar;
+const PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer = &gNullChar;
+
+// ---------------------------------------------------------------------------
+
+#ifdef ENABLE_STRING_STATS
+class nsStringStats
+ {
+ public:
+ nsStringStats()
+ : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {}
+
+ ~nsStringStats()
+ {
+ // this is a hack to suppress duplicate string stats printing
+ // in seamonkey as a result of the string code being linked
+ // into seamonkey and libxpcom! :-(
+ if (!mAllocCount && !mAdoptCount)
+ return;
+
+#ifndef VBOX
+ printf("nsStringStats\n");
+ printf(" => mAllocCount: % 10d\n", mAllocCount);
+ printf(" => mReallocCount: % 10d\n", mReallocCount);
+ printf(" => mFreeCount: % 10d", mFreeCount);
+ if (mAllocCount > mFreeCount)
+ printf(" -- LEAKED %d !!!\n", mAllocCount - mFreeCount);
+ else
+ printf("\n");
+ printf(" => mShareCount: % 10d\n", mShareCount);
+ printf(" => mAdoptCount: % 10d\n", mAdoptCount);
+ printf(" => mAdoptFreeCount: % 10d", mAdoptFreeCount);
+ if (mAdoptCount > mAdoptFreeCount)
+ printf(" -- LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount);
+ else
+ printf("\n");
+#endif
+ }
+
+ PRInt32 mAllocCount;
+ PRInt32 mReallocCount;
+ PRInt32 mFreeCount;
+ PRInt32 mShareCount;
+ PRInt32 mAdoptCount;
+ PRInt32 mAdoptFreeCount;
+ };
+static nsStringStats gStringStats;
+#define STRING_STAT_INCREMENT(_s) PR_AtomicIncrement(&gStringStats.m ## _s ## Count)
+#else
+#define STRING_STAT_INCREMENT(_s)
+#endif
+
+// ---------------------------------------------------------------------------
+
+ /**
+ * This structure precedes the string buffers "we" allocate. It may be the
+ * case that nsTSubstring::mData does not point to one of these special
+ * buffers. The mFlags member variable distinguishes the buffer type.
+ *
+ * When this header is in use, it enables reference counting, and capacity
+ * tracking. NOTE: A string buffer can be modified only if its reference
+ * count is 1.
+ */
+class nsStringHeader
+ {
+ private:
+
+ PRInt32 mRefCount;
+ PRUint32 mStorageSize;
+
+ public:
+
+ void AddRef()
+ {
+ PR_AtomicIncrement(&mRefCount);
+ STRING_STAT_INCREMENT(Share);
+ }
+
+ void Release()
+ {
+ if (PR_AtomicDecrement(&mRefCount) == 0)
+ {
+ STRING_STAT_INCREMENT(Free);
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(this); // we were allocated with |malloc|
+#else
+ free(this); // we were allocated with |malloc|
+#endif
+ }
+ }
+
+ /**
+ * Alloc returns a pointer to a new string header with set capacity.
+ */
+ static nsStringHeader* Alloc(size_t size)
+ {
+ STRING_STAT_INCREMENT(Alloc);
+
+ NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
+
+ nsStringHeader *hdr =
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ (nsStringHeader *) RTMemAlloc(sizeof(nsStringHeader) + size);
+#else
+ (nsStringHeader *) malloc(sizeof(nsStringHeader) + size);
+#endif
+ if (hdr)
+ {
+ hdr->mRefCount = 1;
+ hdr->mStorageSize = size;
+ }
+ return hdr;
+ }
+
+ static nsStringHeader* Realloc(nsStringHeader* hdr, size_t size)
+ {
+ STRING_STAT_INCREMENT(Realloc);
+
+ NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
+
+ // no point in trying to save ourselves if we hit this assertion
+ NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ hdr = (nsStringHeader*) RTMemRealloc(hdr, sizeof(nsStringHeader) + size);
+#else
+ hdr = (nsStringHeader*) realloc(hdr, sizeof(nsStringHeader) + size);
+#endif
+ if (hdr)
+ hdr->mStorageSize = size;
+
+ return hdr;
+ }
+
+ static nsStringHeader* FromData(void* data)
+ {
+ return (nsStringHeader*) ( ((char*) data) - sizeof(nsStringHeader) );
+ }
+
+ void* Data() const
+ {
+ return (void*) ( ((char*) this) + sizeof(nsStringHeader) );
+ }
+
+ PRUint32 StorageSize() const
+ {
+ return mStorageSize;
+ }
+
+ /**
+ * Because nsTSubstring allows only single threaded access, if this
+ * method returns FALSE, then the caller can be sure that it has
+ * exclusive access to the nsStringHeader and associated data.
+ * However, if this function returns TRUE, then other strings may
+ * rely on the data in this buffer being constant and other threads
+ * may access this buffer simultaneously.
+ */
+ PRBool IsReadonly() const
+ {
+ return mRefCount > 1;
+ }
+ };
+
+// ---------------------------------------------------------------------------
+
+inline void
+ReleaseData( void* data, PRUint32 flags )
+ {
+ if (flags & nsSubstring::F_SHARED)
+ {
+ nsStringHeader::FromData(data)->Release();
+ }
+ else if (flags & nsSubstring::F_OWNED)
+ {
+ nsMemory::Free(data);
+ STRING_STAT_INCREMENT(AdoptFree);
+ }
+ // otherwise, nothing to do.
+ }
+
+
+ // define nsSubstring
+#include "string-template-def-unichar.h"
+#include "nsTSubstring.cpp"
+#include "string-template-undef.h"
+
+ // define nsCSubstring
+#include "string-template-def-char.h"
+#include "nsTSubstring.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp
new file mode 100644
index 00000000..a5445d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsSubstringTuple.h"
+
+#if 0
+ // convert fragment to |const string_base_type&|
+#define TO_SUBSTRING(_v) \
+ ( (ptrdiff_t(_v) & 0x1) \
+ ? NS_REINTERPRET_CAST(const abstract_string_type*, \
+ ((unsigned long)_v & ~0x1))->ToSubstring() \
+ : *NS_REINTERPRET_CAST(const substring_type*, (_v)) )
+#endif
+
+ // convert fragment to |const substring_type&|
+#define TO_SUBSTRING(_v) \
+ ( (_v)->mVTable == obsolete_string_type::sCanonicalVTable \
+ ? *(_v)->AsSubstring() \
+ : (_v)->ToSubstring() )
+
+ // define nsSubstringTuple
+#include "string-template-def-unichar.h"
+#include "nsTSubstringTuple.cpp"
+#include "string-template-undef.h"
+
+ // define nsCSubstringTuple
+#include "string-template-def-char.h"
+#include "nsTSubstringTuple.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp
new file mode 100644
index 00000000..ffd75fe8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp
@@ -0,0 +1,509 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * Some comments on this implementation...
+ *
+ * This class is a bridge between the old string implementation and the new
+ * string implementation. If mVTable points to the canonical vtable for the
+ * new string implementation, then we can cast directly to the new string
+ * classes (helped by the AsSubstring() methods). However, if mVTable is not
+ * ours, then we need to call through the vtable to satisfy the nsTAString
+ * methods.
+ *
+ * In most cases we will avoid the vtable.
+ */
+
+
+nsTAString_CharT::~nsTAString_CharT()
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Finalize();
+ else
+ AsObsoleteString()->~nsTObsoleteAString_CharT();
+ }
+
+
+nsTAString_CharT::size_type
+nsTAString_CharT::Length() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Length();
+
+ return AsObsoleteString()->Length();
+ }
+
+PRBool
+nsTAString_CharT::Equals( const self_type& readable ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(readable);
+
+ return ToSubstring().Equals(readable);
+ }
+
+PRBool
+nsTAString_CharT::Equals( const self_type& readable, const comparator_type& comparator ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(readable, comparator);
+
+ return ToSubstring().Equals(readable, comparator);
+ }
+
+PRBool
+nsTAString_CharT::Equals( const char_type* data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(data);
+
+ return ToSubstring().Equals(data);
+ }
+
+PRBool
+nsTAString_CharT::Equals( const char_type* data, const comparator_type& comparator ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(data, comparator);
+
+ return ToSubstring().Equals(data, comparator);
+ }
+
+PRBool
+nsTAString_CharT::EqualsASCII( const char* data, size_type len ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->EqualsASCII(data, len);
+
+ return ToSubstring().EqualsASCII(data, len);
+ }
+
+PRBool
+nsTAString_CharT::EqualsASCII( const char* data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->EqualsASCII(data);
+
+ return ToSubstring().EqualsASCII(data);
+ }
+
+PRBool
+nsTAString_CharT::LowerCaseEqualsASCII( const char* data, size_type len ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->LowerCaseEqualsASCII(data, len);
+
+ return ToSubstring().LowerCaseEqualsASCII(data, len);
+ }
+
+PRBool
+nsTAString_CharT::LowerCaseEqualsASCII( const char* data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->LowerCaseEqualsASCII(data);
+
+ return ToSubstring().LowerCaseEqualsASCII(data);
+ }
+
+PRBool
+nsTAString_CharT::IsVoid() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->IsVoid();
+
+ return AsObsoleteString()->IsVoid();
+ }
+
+void
+nsTAString_CharT::SetIsVoid( PRBool val )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->SetIsVoid(val);
+ else
+ AsObsoleteString()->SetIsVoid(val);
+ }
+
+PRBool
+nsTAString_CharT::IsTerminated() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->IsTerminated();
+
+ return AsObsoleteString()->GetFlatBufferHandle() != nsnull;
+ }
+
+CharT
+nsTAString_CharT::First() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->First();
+
+ return ToSubstring().First();
+ }
+
+CharT
+nsTAString_CharT::Last() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Last();
+
+ return ToSubstring().Last();
+ }
+
+nsTAString_CharT::size_type
+nsTAString_CharT::CountChar( char_type c ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->CountChar(c);
+
+ return ToSubstring().CountChar(c);
+ }
+
+PRInt32
+nsTAString_CharT::FindChar( char_type c, index_type offset ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->FindChar(c, offset);
+
+ return ToSubstring().FindChar(c, offset);
+ }
+
+void
+nsTAString_CharT::SetCapacity( size_type size )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->SetCapacity(size);
+ else
+ AsObsoleteString()->SetCapacity(size);
+ }
+
+void
+nsTAString_CharT::SetLength( size_type size )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->SetLength(size);
+ else
+ AsObsoleteString()->SetLength(size);
+ }
+
+void
+nsTAString_CharT::Assign( const self_type& readable )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(readable);
+ else
+ AsObsoleteString()->do_AssignFromReadable(readable);
+ }
+
+void
+nsTAString_CharT::Assign( const substring_tuple_type& tuple )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(tuple);
+ else
+ AsObsoleteString()->do_AssignFromReadable(nsTAutoString_CharT(tuple));
+ }
+
+void
+nsTAString_CharT::Assign( const char_type* data )
+ {
+ // null check and SetLength(0) cases needed for backwards compat
+
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(data);
+ else if (data)
+ AsObsoleteString()->do_AssignFromElementPtr(data);
+ else
+ AsObsoleteString()->SetLength(0);
+ }
+
+void
+nsTAString_CharT::Assign( const char_type* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(data, length);
+ else
+ AsObsoleteString()->do_AssignFromElementPtrLength(data, length);
+ }
+
+void
+nsTAString_CharT::AssignASCII( const char* data )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AssignASCII(data);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AssignFromElementPtr(data);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data);
+ AsObsoleteString()->do_AssignFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::AssignASCII( const char* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AssignASCII(data, length);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AssignFromElementPtrLength(data, length);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data, length);
+ AsObsoleteString()->do_AssignFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::Assign( char_type c )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(c);
+ else
+ AsObsoleteString()->do_AssignFromElement(c);
+ }
+
+void
+nsTAString_CharT::Append( const self_type& readable )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(readable);
+ else
+ AsObsoleteString()->do_AppendFromReadable(readable);
+ }
+
+void
+nsTAString_CharT::Append( const substring_tuple_type& tuple )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(tuple);
+ else
+ AsObsoleteString()->do_AppendFromReadable(nsTAutoString_CharT(tuple));
+ }
+
+void
+nsTAString_CharT::Append( const char_type* data )
+ {
+ // null check case needed for backwards compat
+
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(data);
+ else if (data)
+ AsObsoleteString()->do_AppendFromElementPtr(data);
+ }
+
+void
+nsTAString_CharT::Append( const char_type* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(data, length);
+ else
+ AsObsoleteString()->do_AppendFromElementPtrLength(data, length);
+ }
+
+void
+nsTAString_CharT::AppendASCII( const char* data )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AppendASCII(data);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AppendFromElementPtr(data);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data);
+ AsObsoleteString()->do_AppendFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::AppendASCII( const char* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AppendASCII(data, length);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AppendFromElementPtrLength(data, length);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data, length);
+ AsObsoleteString()->do_AppendFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::Append( char_type c )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(c);
+ else
+ AsObsoleteString()->do_AppendFromElement(c);
+ }
+
+void
+nsTAString_CharT::Insert( const self_type& readable, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(readable, pos);
+ else
+ AsObsoleteString()->do_InsertFromReadable(readable, pos);
+ }
+
+void
+nsTAString_CharT::Insert( const substring_tuple_type& tuple, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(tuple, pos);
+ else
+ AsObsoleteString()->do_InsertFromReadable(nsTAutoString_CharT(tuple), pos);
+ }
+
+void
+nsTAString_CharT::Insert( const char_type* data, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(data, pos);
+ else
+ AsObsoleteString()->do_InsertFromElementPtr(data, pos);
+ }
+
+void
+nsTAString_CharT::Insert( const char_type* data, index_type pos, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(data, pos, length);
+ else
+ AsObsoleteString()->do_InsertFromElementPtrLength(data, pos, length);
+ }
+
+void
+nsTAString_CharT::Insert( char_type c, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(c, pos);
+ else
+ AsObsoleteString()->do_InsertFromElement(c, pos);
+ }
+
+void
+nsTAString_CharT::Cut( index_type cutStart, size_type cutLength )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Cut(cutStart, cutLength);
+ else
+ AsObsoleteString()->Cut(cutStart, cutLength);
+ }
+
+void
+nsTAString_CharT::Replace( index_type cutStart, size_type cutLength, const self_type& readable )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Replace(cutStart, cutLength, readable);
+ else
+ AsObsoleteString()->do_ReplaceFromReadable(cutStart, cutLength, readable);
+ }
+
+void
+nsTAString_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Replace(cutStart, cutLength, tuple);
+ else
+ AsObsoleteString()->do_ReplaceFromReadable(cutStart, cutLength, nsTAutoString_CharT(tuple));
+ }
+
+nsTAString_CharT::size_type
+nsTAString_CharT::GetReadableBuffer( const char_type **data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ {
+ const substring_type* str = AsSubstring();
+ *data = str->mData;
+ return str->mLength;
+ }
+
+ obsolete_string_type::const_fragment_type frag;
+ AsObsoleteString()->GetReadableFragment(frag, obsolete_string_type::kFirstFragment, 0);
+ *data = frag.mStart;
+ return (frag.mEnd - frag.mStart);
+ }
+
+nsTAString_CharT::size_type
+nsTAString_CharT::GetWritableBuffer(char_type **data)
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ {
+ substring_type* str = AsSubstring();
+ str->BeginWriting(*data);
+ return str->Length();
+ }
+
+ obsolete_string_type::fragment_type frag;
+ AsObsoleteString()->GetWritableFragment(frag, obsolete_string_type::kFirstFragment, 0);
+ *data = frag.mStart;
+ return (frag.mEnd - frag.mStart);
+ }
+
+PRBool
+nsTAString_CharT::IsDependentOn(const char_type* start, const char_type *end) const
+ {
+ // this is an optimization...
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->IsDependentOn(start, end);
+
+ return ToSubstring().IsDependentOn(start, end);
+ }
+
+const nsTAString_CharT::substring_type
+nsTAString_CharT::ToSubstring() const
+ {
+ const char_type* data;
+ size_type length = GetReadableBuffer(&data);
+ return substring_type(NS_CONST_CAST(char_type*, data), length, 0);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp
new file mode 100644
index 00000000..8421ecc0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+void
+nsTDependentSubstring_CharT::Rebind( const abstract_string_type& readable, PRUint32 startPos, PRUint32 length )
+ {
+ size_type strLength = readable.GetReadableBuffer((const char_type**) &mData);
+
+ if (startPos > strLength)
+ startPos = strLength;
+
+ mData += startPos;
+ mLength = NS_MIN(length, strLength - startPos);
+
+ SetDataFlags(F_NONE);
+ }
+
+void
+nsTDependentSubstring_CharT::Rebind( const substring_type& str, PRUint32 startPos, PRUint32 length )
+ {
+ size_type strLength = str.Length();
+
+ if (startPos > strLength)
+ startPos = strLength;
+
+ mData = NS_CONST_CAST(char_type*, str.Data()) + startPos;
+ mLength = NS_MIN(length, strLength - startPos);
+
+ SetDataFlags(F_NONE);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp
new file mode 100644
index 00000000..3d1590a8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp
@@ -0,0 +1,235 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+class nsTObsoleteAStringThunk_CharT : public nsTObsoleteAString_CharT
+ {
+ public:
+ typedef nsTObsoleteAStringThunk_CharT self_type;
+ typedef nsTSubstring_CharT substring_type;
+
+ public:
+
+ nsTObsoleteAStringThunk_CharT() {}
+
+
+ static const void* get_vptr()
+ {
+ const void* result;
+ new (&result) self_type();
+ return result;
+ }
+
+
+ /**
+ * we are a nsTSubstring in disguise!
+ */
+
+ substring_type* concrete_self() { return NS_REINTERPRET_CAST( substring_type*, this); }
+ const substring_type* concrete_self() const { return NS_REINTERPRET_CAST(const substring_type*, this); }
+
+
+ /**
+ * all virtual methods need to be redirected to appropriate nsString methods
+ */
+
+ virtual ~nsTObsoleteAStringThunk_CharT()
+ {
+ concrete_self()->Finalize();
+ }
+
+ virtual PRUint32 GetImplementationFlags() const
+ {
+ return 0;
+ }
+
+ virtual const buffer_handle_type* GetFlatBufferHandle() const
+ {
+ return (const buffer_handle_type*) (concrete_self()->IsTerminated() != PR_FALSE);
+ }
+
+ virtual const buffer_handle_type* GetBufferHandle() const
+ {
+ return 0;
+ }
+
+ virtual const shared_buffer_handle_type* GetSharedBufferHandle() const
+ {
+ return 0;
+ }
+
+ virtual size_type Length() const
+ {
+ return concrete_self()->Length();
+ }
+
+ virtual PRBool IsVoid() const
+ {
+ return concrete_self()->IsVoid();
+ }
+
+ virtual void SetIsVoid(PRBool val)
+ {
+ concrete_self()->SetIsVoid(val);
+ }
+
+ virtual void SetCapacity(size_type size)
+ {
+ concrete_self()->SetCapacity(size);
+ }
+
+ virtual void SetLength(size_type size)
+ {
+ concrete_self()->SetLength(size);
+ }
+
+ virtual void Cut(index_type cutStart, size_type cutLength)
+ {
+ concrete_self()->Cut(cutStart, cutLength);
+ }
+
+ virtual void do_AssignFromReadable(const abstract_string_type &s)
+ {
+ concrete_self()->Assign(s);
+ }
+
+ virtual void do_AssignFromElementPtr(const char_type *data)
+ {
+ concrete_self()->Assign(data);
+ }
+
+ virtual void do_AssignFromElementPtrLength(const char_type *data, size_type length)
+ {
+ concrete_self()->Assign(data, length);
+ }
+
+ virtual void do_AssignFromElement(char_type c)
+ {
+ concrete_self()->Assign(c);
+ }
+
+ virtual void do_AppendFromReadable(const abstract_string_type &s)
+ {
+ concrete_self()->Append(s);
+ }
+
+ virtual void do_AppendFromElementPtr(const char_type *data)
+ {
+ concrete_self()->Append(data);
+ }
+
+ virtual void do_AppendFromElementPtrLength(const char_type *data, size_type length)
+ {
+ concrete_self()->Append(data, length);
+ }
+
+ virtual void do_AppendFromElement(char_type c)
+ {
+ concrete_self()->Append(c);
+ }
+
+ virtual void do_InsertFromReadable(const abstract_string_type &s, index_type pos)
+ {
+ concrete_self()->Insert(s, pos);
+ }
+
+ virtual void do_InsertFromElementPtr(const char_type *data, index_type pos)
+ {
+ concrete_self()->Insert(data, pos);
+ }
+
+ virtual void do_InsertFromElementPtrLength(const char_type *data, index_type pos, size_type length)
+ {
+ concrete_self()->Insert(data, pos, length);
+ }
+
+ virtual void do_InsertFromElement(char_type c, index_type pos)
+ {
+ concrete_self()->Insert(c, pos);
+ }
+
+ virtual void do_ReplaceFromReadable(index_type cutStart, size_type cutLength, const abstract_string_type &s)
+ {
+ concrete_self()->Replace(cutStart, cutLength, s);
+ }
+
+ virtual const char_type *GetReadableFragment(const_fragment_type& frag, nsFragmentRequest which, PRUint32 offset) const
+ {
+ const substring_type* s = concrete_self();
+ switch (which)
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ frag.mStart = s->Data();
+ frag.mEnd = frag.mStart + s->Length();
+ return frag.mStart + offset;
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+
+ virtual char_type *GetWritableFragment(fragment_type& frag, nsFragmentRequest which, PRUint32 offset)
+ {
+ substring_type* s = concrete_self();
+ switch (which)
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ char_type* start;
+ s->BeginWriting(start);
+ frag.mStart = start;
+ frag.mEnd = start + s->Length();
+ return frag.mStart + offset;
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+ };
+
+
+ /**
+ * initialize the pointer to the canonical vtable...
+ */
+
+const void *nsTObsoleteAString_CharT::sCanonicalVTable = nsTObsoleteAStringThunk_CharT::get_vptr();
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp
new file mode 100644
index 00000000..bf0bfc32
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+void
+nsTPromiseFlatString_CharT::Init(const substring_type& str)
+ {
+ // we have to manually set this here since we are being called on an
+ // unitialized object.
+ mVTable = nsTObsoleteAString_CharT::sCanonicalVTable;
+
+ if (str.IsTerminated())
+ {
+ mData = NS_CONST_CAST(char_type*, str.Data());
+ mLength = str.Length();
+ mFlags = F_TERMINATED; // does not promote F_VOIDED
+ }
+ else
+ {
+ Assign(str);
+ }
+ }
+
+ // this function is non-inline to minimize codesize
+void
+nsTPromiseFlatString_CharT::Init(const abstract_string_type& readable)
+ {
+ if (readable.mVTable == nsTObsoleteAString_CharT::sCanonicalVTable)
+ Init(*readable.AsSubstring());
+ else
+ Init(readable.ToSubstring());
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp
new file mode 100644
index 00000000..84911f5f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ * Johnny Stenback <jst@mozilla.jstenback.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 ***** */
+
+NS_COM nsTAdoptingString_CharT&
+nsTAdoptingString_CharT::operator=( const self_type& str )
+ {
+ // This'll violate the constness of this argument, that's just
+ // the nature of this class...
+ self_type* mutable_str = NS_CONST_CAST(self_type*, &str);
+
+ if (str.mFlags & F_OWNED)
+ {
+ Adopt(str.mData, str.mLength);
+
+ // Make str forget the buffer we just took ownership of.
+ new (mutable_str) self_type();
+ }
+ else
+ {
+ Assign(str);
+
+ mutable_str->Truncate();
+ }
+
+ return *this;
+ }
+
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp
new file mode 100644
index 00000000..6d2645a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+NS_COM int
+Compare( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs, const nsTStringComparator_CharT& comp )
+ {
+ typedef nsTAString_CharT::size_type size_type;
+
+ if ( &lhs == &rhs )
+ return 0;
+
+ nsTAString_CharT::const_iterator leftIter, rightIter;
+ lhs.BeginReading(leftIter);
+ rhs.BeginReading(rightIter);
+
+ size_type lLength = leftIter.size_forward();
+ size_type rLength = rightIter.size_forward();
+ size_type lengthToCompare = NS_MIN(lLength, rLength);
+
+ int result;
+ if ( (result = comp(leftIter.get(), rightIter.get(), lengthToCompare)) == 0 )
+ {
+ if ( lLength < rLength )
+ result = -1;
+ else if ( rLength < lLength )
+ result = 1;
+ else
+ result = 0;
+ }
+
+ return result;
+ }
+
+int
+nsTDefaultStringComparator_CharT::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
+ {
+ return nsCharTraits<CharT>::compare(lhs, rhs, aLength);
+ }
+
+int
+nsTDefaultStringComparator_CharT::operator()( char_type lhs, char_type rhs) const
+ {
+ return lhs - rhs;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp
new file mode 100644
index 00000000..5ed065ad
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp
@@ -0,0 +1,518 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+
+ /**
+ * nsTString::Find
+ *
+ * aOffset specifies starting index
+ * aCount specifies number of string compares (iterations)
+ */
+
+PRInt32
+nsTString_CharT::Find( const nsCString& aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsTString_CharT::Find( const char* aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ return Find(nsDependentCString(aString), aIgnoreCase, aOffset, aCount);
+ }
+
+
+ /**
+ * nsTString::RFind
+ *
+ * aOffset specifies starting index
+ * aCount specifies number of string compares (iterations)
+ */
+
+PRInt32
+nsTString_CharT::RFind( const nsCString& aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsTString_CharT::RFind( const char* aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ return RFind(nsDependentCString(aString), aIgnoreCase, aOffset, aCount);
+ }
+
+
+ /**
+ * nsTString::RFindChar
+ */
+
+PRInt32
+nsTString_CharT::RFindChar( PRUnichar aChar, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ return nsBufferRoutines<CharT>::rfind_char(mData, mLength, aOffset, aChar, aCount);
+ }
+
+
+ /**
+ * nsTString::FindCharInSet
+ */
+
+PRInt32
+nsTString_CharT::FindCharInSet( const char* aSet, PRInt32 aOffset ) const
+ {
+ if (aOffset < 0)
+ aOffset = 0;
+ else if (aOffset >= PRInt32(mLength))
+ return kNotFound;
+
+ PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+
+ /**
+ * nsTString::RFindCharInSet
+ */
+
+PRInt32
+nsTString_CharT::RFindCharInSet( const CharT* aSet, PRInt32 aOffset ) const
+ {
+ // We want to pass a "data length" to ::RFindCharInSet
+ if (aOffset < 0 || aOffset > PRInt32(mLength))
+ aOffset = mLength;
+ else
+ ++aOffset;
+
+ return ::RFindCharInSet(mData, aOffset, aSet);
+ }
+
+
+ // it's a shame to replicate this code. it was done this way in the past
+ // to help performance. this function also gets to keep the rickg style
+ // indentation :-/
+PRInt32
+nsTString_CharT::ToInteger( PRInt32* aErrorCode, PRUint32 aRadix ) const
+{
+ CharT* cp=mData;
+ PRInt32 theRadix=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
+ PRInt32 result=0;
+ PRBool negate=PR_FALSE;
+ CharT theChar=0;
+
+ //initial value, override if we find an integer
+ *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
+
+ if(cp) {
+
+ //begin by skipping over leading chars that shouldn't be part of the number...
+
+ CharT* endcp=cp+mLength;
+ PRBool done=PR_FALSE;
+
+ while((cp<endcp) && (!done)){
+ switch(*cp++) {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ theRadix=16;
+ done=PR_TRUE;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ done=PR_TRUE;
+ break;
+ case '-':
+ negate=PR_TRUE; //fall through...
+ break;
+ case 'X': case 'x':
+ theRadix=16;
+ break;
+ default:
+ break;
+ } //switch
+ }
+
+ if (done) {
+
+ //integer found
+ *aErrorCode = NS_OK;
+
+ if (aRadix!=kAutoDetect) theRadix = aRadix; // override
+
+ //now iterate the numeric chars and build our result
+ CharT* first=--cp; //in case we have to back up.
+ PRBool haveValue = PR_FALSE;
+
+ while(cp<endcp){
+ theChar=*cp++;
+ if(('0'<=theChar) && (theChar<='9')){
+ result = (theRadix * result) + (theChar-'0');
+ haveValue = PR_TRUE;
+ }
+ else if((theChar>='A') && (theChar<='F')) {
+ if(10==theRadix) {
+ if(kAutoDetect==aRadix){
+ theRadix=16;
+ cp=first; //backup
+ result=0;
+ haveValue = PR_FALSE;
+ }
+ else {
+ *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
+ result=0;
+ break;
+ }
+ }
+ else {
+ result = (theRadix * result) + ((theChar-'A')+10);
+ haveValue = PR_TRUE;
+ }
+ }
+ else if((theChar>='a') && (theChar<='f')) {
+ if(10==theRadix) {
+ if(kAutoDetect==aRadix){
+ theRadix=16;
+ cp=first; //backup
+ result=0;
+ haveValue = PR_FALSE;
+ }
+ else {
+ *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
+ result=0;
+ break;
+ }
+ }
+ else {
+ result = (theRadix * result) + ((theChar-'a')+10);
+ haveValue = PR_TRUE;
+ }
+ }
+ else if((('X'==theChar) || ('x'==theChar)) && (!haveValue || result == 0)) {
+ continue;
+ }
+ else if((('#'==theChar) || ('+'==theChar)) && !haveValue) {
+ continue;
+ }
+ else {
+ //we've encountered a char that's not a legal number or sign
+ break;
+ }
+ } //while
+ if(negate)
+ result=-result;
+ } //if
+ }
+ return result;
+}
+
+
+ /**
+ * nsTString::Mid
+ */
+
+PRUint32
+nsTString_CharT::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
+ {
+ if (aStartPos == 0 && aLengthToCopy >= mLength)
+ aResult = *this;
+ else
+ aResult = Substring(*this, aStartPos, aLengthToCopy);
+
+ return aResult.mLength;
+ }
+
+
+ /**
+ * nsTString::SetCharAt
+ */
+
+PRBool
+nsTString_CharT::SetCharAt( PRUnichar aChar, PRUint32 aIndex )
+ {
+ if (aIndex >= mLength)
+ return PR_FALSE;
+
+ EnsureMutable();
+
+ mData[aIndex] = CharT(aChar);
+ return PR_TRUE;
+ }
+
+
+ /**
+ * nsTString::StripChars,StripChar,StripWhitespace
+ */
+
+void
+nsTString_CharT::StripChars( const char* aSet )
+ {
+ EnsureMutable();
+ mLength = nsBufferRoutines<CharT>::strip_chars(mData, mLength, aSet);
+ }
+
+void
+nsTString_CharT::StripChar( char_type aChar, PRInt32 aOffset )
+ {
+ if (mLength == 0 || aOffset >= PRInt32(mLength))
+ return;
+
+ EnsureMutable(); // XXX do this lazily?
+
+ // XXXdarin this code should defer writing until necessary.
+
+ char_type* to = mData + aOffset;
+ char_type* from = mData + aOffset;
+ char_type* end = mData + mLength;
+
+ while (from < end)
+ {
+ char_type theChar = *from++;
+ if (aChar != theChar)
+ *to++ = theChar;
+ }
+ *to = char_type(0); // add the null
+ mLength = to - mData;
+ }
+
+void
+nsTString_CharT::StripWhitespace()
+ {
+ StripChars(kWhitespace);
+ }
+
+
+ /**
+ * nsTString::ReplaceChar,ReplaceSubstring
+ */
+
+void
+nsTString_CharT::ReplaceChar( char_type aOldChar, char_type aNewChar )
+ {
+ EnsureMutable(); // XXX do this lazily?
+
+ for (PRUint32 i=0; i<mLength; ++i)
+ {
+ if (mData[i] == aOldChar)
+ mData[i] = aNewChar;
+ }
+ }
+
+void
+nsTString_CharT::ReplaceChar( const char* aSet, char_type aNewChar )
+ {
+ EnsureMutable(); // XXX do this lazily?
+
+ char_type* data = mData;
+ PRUint32 lenRemaining = mLength;
+
+ while (lenRemaining)
+ {
+ PRInt32 i = ::FindCharInSet(data, lenRemaining, aSet);
+ if (i == kNotFound)
+ break;
+
+ data[i++] = aNewChar;
+ data += i;
+ lenRemaining -= i;
+ }
+ }
+
+void
+nsTString_CharT::ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue )
+ {
+ ReplaceSubstring(nsTDependentString_CharT(aTarget),
+ nsTDependentString_CharT(aNewValue));
+ }
+
+void
+nsTString_CharT::ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue )
+ {
+ if (aTarget.Length() == 0)
+ return;
+
+ PRUint32 i = 0;
+ while (i < mLength)
+ {
+ PRInt32 r = FindSubstring(mData + i, mLength - i, aTarget.Data(), aTarget.Length(), PR_FALSE);
+ if (r == kNotFound)
+ break;
+
+ Replace(i + r, aTarget.Length(), aNewValue);
+ i += r + aNewValue.Length();
+ }
+ }
+
+
+ /**
+ * nsTString::Trim
+ */
+
+void
+nsTString_CharT::Trim( const char* aSet, PRBool aTrimLeading, PRBool aTrimTrailing, PRBool aIgnoreQuotes )
+ {
+ // the old implementation worried about aSet being null :-/
+ if (!aSet)
+ return;
+
+ char_type* start = mData;
+ char_type* end = mData + mLength;
+
+ // skip over quotes if requested
+ if (aIgnoreQuotes && mLength > 2 && mData[0] == mData[mLength - 1] &&
+ (mData[0] == '\'' || mData[0] == '"'))
+ {
+ ++start;
+ --end;
+ }
+
+ PRUint32 setLen = nsCharTraits<char>::length(aSet);
+
+ if (aTrimLeading)
+ {
+ PRUint32 cutStart = start - mData;
+ PRUint32 cutLength = 0;
+
+ // walk forward from start to end
+ for (; start != end; ++start, ++cutLength)
+ {
+ PRInt32 pos = FindChar1(aSet, setLen, 0, *start, setLen);
+ if (pos == kNotFound)
+ break;
+ }
+
+ if (cutLength)
+ {
+ Cut(cutStart, cutLength);
+
+ // reset iterators
+ start = mData + cutStart;
+ end = mData + mLength - cutStart;
+ }
+ }
+
+ if (aTrimTrailing)
+ {
+ PRUint32 cutEnd = end - mData;
+ PRUint32 cutLength = 0;
+
+ // walk backward from end to start
+ --end;
+ for (; end >= start; --end, ++cutLength)
+ {
+ PRInt32 pos = FindChar1(aSet, setLen, 0, *end, setLen);
+ if (pos == kNotFound)
+ break;
+ }
+
+ if (cutLength)
+ Cut(cutEnd - cutLength, cutLength);
+ }
+ }
+
+
+ /**
+ * nsTString::CompressWhitespace
+ */
+
+void
+nsTString_CharT::CompressWhitespace( PRBool aTrimLeading, PRBool aTrimTrailing )
+ {
+ const char* set = kWhitespace;
+
+ ReplaceChar(set, ' ');
+ Trim(set, aTrimLeading, aTrimTrailing);
+
+ // this one does some questionable fu... just copying the old code!
+ mLength = nsBufferRoutines<char_type>::compress_chars(mData, mLength, set);
+ }
+
+
+ /**
+ * nsTString::AssignWithConversion
+ */
+
+void
+nsTString_CharT::AssignWithConversion( const incompatible_char_type* aData, PRInt32 aLength )
+ {
+ // for compatibility with the old string implementation, we need to allow
+ // for a NULL input buffer :-(
+ if (!aData)
+ {
+ Truncate();
+ }
+ else
+ {
+ if (aLength < 0)
+ aLength = nsCharTraits<incompatible_char_type>::length(aData);
+
+ AssignWithConversion(Substring(aData, aData + aLength));
+ }
+ }
+
+
+ /**
+ * nsTString::AppendWithConversion
+ */
+
+void
+nsTString_CharT::AppendWithConversion( const incompatible_char_type* aData, PRInt32 aLength )
+ {
+ // for compatibility with the old string implementation, we need to allow
+ // for a NULL input buffer :-(
+ if (aData)
+ {
+ if (aLength < 0)
+ aLength = nsCharTraits<incompatible_char_type>::length(aData);
+
+ AppendWithConversion(Substring(aData, aData + aLength));
+ }
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp
new file mode 100644
index 00000000..e36b1863
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp
@@ -0,0 +1,656 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * helper function for down-casting a nsTSubstring to a nsTFixedString.
+ */
+inline const nsTFixedString_CharT*
+AsFixedString( const nsTSubstring_CharT* s )
+ {
+ return NS_STATIC_CAST(const nsTFixedString_CharT*, s);
+ }
+
+
+ /**
+ * this function is called to prepare mData for writing. the given capacity
+ * indicates the required minimum storage size for mData, in sizeof(char_type)
+ * increments. this function returns true if the operation succeeds. it also
+ * returns the old data and old flags members if mData is newly allocated.
+ * the old data must be released by the caller.
+ */
+PRBool
+nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint32* oldFlags )
+ {
+ // initialize to no old data
+ *oldData = nsnull;
+ *oldFlags = 0;
+
+ size_type curCapacity = Capacity();
+
+ // |curCapacity == size_type(-1)| means that the buffer is immutable, so we
+ // need to allocate a new buffer. we cannot use the existing buffer even
+ // though it might be large enough.
+
+ if (curCapacity != size_type(-1))
+ {
+ if (capacity <= curCapacity)
+ return PR_TRUE;
+
+ if (curCapacity > 0)
+ {
+ // use doubling algorithm when forced to increase available capacity,
+ // but always start out with exactly the requested amount.
+ PRUint32 temp = curCapacity;
+ while (temp < capacity)
+ temp <<= 1;
+ capacity = temp;
+ }
+ }
+
+ //
+ // several cases:
+ //
+ // (1) we have a shared buffer (mFlags & F_SHARED)
+ // (2) we have an owned buffer (mFlags & F_OWNED)
+ // (3) we have a fixed buffer (mFlags & F_FIXED)
+ // (4) we have a readonly buffer
+ //
+ // requiring that we in some cases preserve the data before creating
+ // a new buffer complicates things just a bit ;-)
+ //
+
+ size_type storageSize = (capacity + 1) * sizeof(char_type);
+
+ // case #1
+ if (mFlags & F_SHARED)
+ {
+ nsStringHeader* hdr = nsStringHeader::FromData(mData);
+ if (!hdr->IsReadonly())
+ {
+ nsStringHeader *newHdr = nsStringHeader::Realloc(hdr, storageSize);
+ if (newHdr)
+ {
+ hdr = newHdr;
+ mData = (char_type*) hdr->Data();
+ return PR_TRUE;
+ }
+ hdr->Release();
+ // out of memory!! put us in a consistent state at least.
+ mData = NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer);
+ mLength = 0;
+ SetDataFlags(F_TERMINATED);
+ return PR_FALSE;
+ }
+ }
+
+ char_type* newData;
+ PRUint32 newDataFlags;
+
+ // if we have a fixed buffer of sufficient size, then use it. this helps
+ // avoid heap allocations.
+ if ((mFlags & F_CLASS_FIXED) && (capacity < AsFixedString(this)->mFixedCapacity))
+ {
+ newData = AsFixedString(this)->mFixedBuf;
+ newDataFlags = F_TERMINATED | F_FIXED;
+ }
+ else
+ {
+ // if we reach here then, we must allocate a new buffer. we cannot
+ // make use of our F_OWNED or F_FIXED buffers because they are not
+ // large enough.
+
+ nsStringHeader* newHdr = nsStringHeader::Alloc(storageSize);
+ if (!newHdr)
+ return PR_FALSE; // we are still in a consistent state
+
+ newData = (char_type*) newHdr->Data();
+ newDataFlags = F_TERMINATED | F_SHARED;
+ }
+
+ // save old data and flags
+ *oldData = mData;
+ *oldFlags = mFlags;
+
+ mData = newData;
+ SetDataFlags(newDataFlags);
+
+ // mLength does not change
+
+ // though we are not necessarily terminated at the moment, now is probably
+ // still the best time to set F_TERMINATED.
+
+ return PR_TRUE;
+ }
+
+void
+nsTSubstring_CharT::Finalize()
+ {
+ ::ReleaseData(mData, mFlags);
+ // mData, mLength, and mFlags are purposefully left dangling
+ }
+
+void
+nsTSubstring_CharT::ReplacePrep( index_type cutStart, size_type cutLen, size_type fragLen )
+ {
+ // bound cut length
+ cutLen = NS_MIN(cutLen, mLength - cutStart);
+
+ PRUint32 newLen = mLength - cutLen + fragLen;
+
+ char_type* oldData;
+ PRUint32 oldFlags;
+ if (!MutatePrep(newLen, &oldData, &oldFlags))
+ return; // XXX out-of-memory error occured!
+
+ if (oldData)
+ {
+ // determine whether or not we need to copy part of the old string
+ // over to the new string.
+
+ if (cutStart > 0)
+ {
+ // copy prefix from old string
+ char_traits::copy(mData, oldData, cutStart);
+ }
+
+ if (cutStart + cutLen < mLength)
+ {
+ // copy suffix from old string to new offset
+ size_type from = cutStart + cutLen;
+ size_type fromLen = mLength - from;
+ PRUint32 to = cutStart + fragLen;
+ char_traits::copy(mData + to, oldData + from, fromLen);
+ }
+
+ ::ReleaseData(oldData, oldFlags);
+ }
+ else
+ {
+ // original data remains intact
+
+ // determine whether or not we need to move part of the existing string
+ // to make room for the requested hole.
+ if (fragLen != cutLen && cutStart + cutLen < mLength)
+ {
+ PRUint32 from = cutStart + cutLen;
+ PRUint32 fromLen = mLength - from;
+ PRUint32 to = cutStart + fragLen;
+ char_traits::move(mData + to, mData + from, fromLen);
+ }
+ }
+
+ // add null terminator (mutable mData always has room for the null-
+ // terminator).
+ mData[newLen] = char_type(0);
+ mLength = newLen;
+ }
+
+nsTSubstring_CharT::size_type
+nsTSubstring_CharT::Capacity() const
+ {
+ // return size_type(-1) to indicate an immutable buffer
+
+ size_type capacity;
+ if (mFlags & F_SHARED)
+ {
+ // if the string is readonly, then we pretend that it has no capacity.
+ nsStringHeader* hdr = nsStringHeader::FromData(mData);
+ if (hdr->IsReadonly())
+ capacity = size_type(-1);
+ else
+ capacity = (hdr->StorageSize() / sizeof(char_type)) - 1;
+ }
+ else if (mFlags & F_FIXED)
+ {
+ capacity = AsFixedString(this)->mFixedCapacity;
+ }
+ else if (mFlags & F_OWNED)
+ {
+ // we don't store the capacity of an adopted buffer because that would
+ // require an additional member field. the best we can do is base the
+ // capacity on our length. remains to be seen if this is the right
+ // trade-off.
+ capacity = mLength;
+ }
+ else
+ {
+ capacity = size_type(-1);
+ }
+
+ return capacity;
+ }
+
+void
+nsTSubstring_CharT::EnsureMutable()
+ {
+ if (mFlags & (F_FIXED | F_OWNED))
+ return;
+ if ((mFlags & F_SHARED) && !nsStringHeader::FromData(mData)->IsReadonly())
+ return;
+
+ // promote to a shared string buffer
+ Assign(string_type(mData, mLength));
+ }
+
+// ---------------------------------------------------------------------------
+
+void
+nsTSubstring_CharT::Assign( const char_type* data, size_type length )
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ Truncate();
+ return;
+ }
+
+ if (length == size_type(-1))
+ length = char_traits::length(data);
+
+ if (IsDependentOn(data, data + length))
+ {
+ // take advantage of sharing here...
+ Assign(string_type(data, length));
+ return;
+ }
+
+ ReplacePrep(0, mLength, length);
+ char_traits::copy(mData, data, length);
+ }
+
+void
+nsTSubstring_CharT::AssignASCII( const char* data, size_type length )
+ {
+ // A Unicode string can't depend on an ASCII string buffer,
+ // so this dependence check only applies to CStrings.
+#ifdef CharT_is_char
+ if (IsDependentOn(data, data + length))
+ {
+ // take advantage of sharing here...
+ Assign(string_type(data, length));
+ return;
+ }
+#endif
+
+ ReplacePrep(0, mLength, length);
+ char_traits::copyASCII(mData, data, length);
+ }
+
+void
+nsTSubstring_CharT::AssignASCII( const char* data )
+ {
+ AssignASCII(data, strlen(data));
+ }
+
+void
+nsTSubstring_CharT::Assign( const self_type& str )
+ {
+ // |str| could be sharable. we need to check its flags to know how to
+ // deal with it.
+
+ if (&str == this)
+ return;
+
+ if (str.mFlags & F_SHARED)
+ {
+ // nice! we can avoid a string copy :-)
+
+ // |str| should be null-terminated
+ NS_ASSERTION(str.mFlags & F_TERMINATED, "shared, but not terminated");
+
+ ::ReleaseData(mData, mFlags);
+
+ mData = str.mData;
+ mLength = str.mLength;
+ SetDataFlags(F_TERMINATED | F_SHARED);
+
+ // get an owning reference to the mData
+ nsStringHeader::FromData(mData)->AddRef();
+ }
+ else if (str.mFlags & F_VOIDED)
+ {
+ // inherit the F_VOIDED attribute
+ SetIsVoid(PR_TRUE);
+ }
+ else
+ {
+ // else, treat this like an ordinary assignment.
+ Assign(str.Data(), str.Length());
+ }
+ }
+
+void
+nsTSubstring_CharT::Assign( const substring_tuple_type& tuple )
+ {
+ if (tuple.IsDependentOn(mData, mData + mLength))
+ {
+ // take advantage of sharing here...
+ Assign(string_type(tuple));
+ return;
+ }
+
+ size_type length = tuple.Length();
+
+ ReplacePrep(0, mLength, length);
+ if (length)
+ tuple.WriteTo(mData, length);
+ }
+
+ // this is non-inline to reduce codesize at the callsite
+void
+nsTSubstring_CharT::Assign( const abstract_string_type& readable )
+ {
+ // promote to string if possible to take advantage of sharing
+ if (readable.mVTable == nsTObsoleteAString_CharT::sCanonicalVTable)
+ Assign(*readable.AsSubstring());
+ else
+ Assign(readable.ToSubstring());
+ }
+
+
+void
+nsTSubstring_CharT::Adopt( char_type* data, size_type length )
+ {
+ if (data)
+ {
+ ::ReleaseData(mData, mFlags);
+
+ if (length == size_type(-1))
+ length = char_traits::length(data);
+
+ mData = data;
+ mLength = length;
+ SetDataFlags(F_TERMINATED | F_OWNED);
+
+ STRING_STAT_INCREMENT(Adopt);
+ }
+ else
+ {
+ SetIsVoid(PR_TRUE);
+ }
+ }
+
+
+void
+nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length )
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ length = 0;
+ }
+ else
+ {
+ if (length == size_type(-1))
+ length = char_traits::length(data);
+
+ if (IsDependentOn(data, data + length))
+ {
+ nsTAutoString_CharT temp(data, length);
+ Replace(cutStart, cutLength, temp);
+ return;
+ }
+ }
+
+ cutStart = PR_MIN(cutStart, Length());
+
+ ReplacePrep(cutStart, cutLength, length);
+
+ if (length > 0)
+ char_traits::copy(mData + cutStart, data, length);
+ }
+
+void
+nsTSubstring_CharT::ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length )
+ {
+ if (length == size_type(-1))
+ length = strlen(data);
+
+ // A Unicode string can't depend on an ASCII string buffer,
+ // so this dependence check only applies to CStrings.
+#ifdef CharT_is_char
+ if (IsDependentOn(data, data + length))
+ {
+ nsTAutoString_CharT temp(data, length);
+ Replace(cutStart, cutLength, temp);
+ return;
+ }
+#endif
+
+ cutStart = PR_MIN(cutStart, Length());
+
+ ReplacePrep(cutStart, cutLength, length);
+
+ if (length > 0)
+ char_traits::copyASCII(mData + cutStart, data, length);
+ }
+
+void
+nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple )
+ {
+ if (tuple.IsDependentOn(mData, mData + mLength))
+ {
+ nsTAutoString_CharT temp(tuple);
+ Replace(cutStart, cutLength, temp);
+ return;
+ }
+
+ size_type length = tuple.Length();
+
+ cutStart = PR_MIN(cutStart, Length());
+
+ ReplacePrep(cutStart, cutLength, length);
+
+ if (length > 0)
+ tuple.WriteTo(mData + cutStart, length);
+ }
+
+void
+nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable )
+ {
+ Replace(cutStart, cutLength, readable.ToSubstring());
+ }
+
+void
+nsTSubstring_CharT::SetCapacity( size_type capacity )
+ {
+ // capacity does not include room for the terminating null char
+
+ // if our capacity is reduced to zero, then free our buffer.
+ if (capacity == 0)
+ {
+ ::ReleaseData(mData, mFlags);
+ mData = NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer);
+ mLength = 0;
+ SetDataFlags(F_TERMINATED);
+ }
+ else
+ {
+ char_type* oldData;
+ PRUint32 oldFlags;
+ if (!MutatePrep(capacity, &oldData, &oldFlags))
+ return; // XXX out-of-memory error occured!
+
+ // compute new string length
+ size_type newLen = NS_MIN(mLength, capacity);
+
+ if (oldData)
+ {
+ // preserve old data
+ if (mLength > 0)
+ char_traits::copy(mData, oldData, newLen);
+
+ ::ReleaseData(oldData, oldFlags);
+ }
+
+ // adjust mLength if our buffer shrunk down in size
+ if (newLen < mLength)
+ mLength = newLen;
+
+ // always null-terminate here, even if the buffer got longer. this is
+ // for backwards compat with the old string implementation.
+ mData[capacity] = char_type(0);
+ }
+ }
+
+void
+nsTSubstring_CharT::SetLength( size_type length )
+ {
+ SetCapacity(length);
+ mLength = length;
+ }
+
+void
+nsTSubstring_CharT::SetIsVoid( PRBool val )
+ {
+ if (val)
+ {
+ Truncate();
+ mFlags |= F_VOIDED;
+ }
+ else
+ {
+ mFlags &= ~F_VOIDED;
+ }
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const self_type& str ) const
+ {
+ return mLength == str.mLength && char_traits::compare(mData, str.mData, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const self_type& str, const comparator_type& comp ) const
+ {
+ return mLength == str.mLength && comp(mData, str.mData, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const abstract_string_type& readable ) const
+ {
+ const char_type* data;
+ size_type length = readable.GetReadableBuffer(&data);
+
+ return mLength == length && char_traits::compare(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const abstract_string_type& readable, const comparator_type& comp ) const
+ {
+ const char_type* data;
+ size_type length = readable.GetReadableBuffer(&data);
+
+ return mLength == length && comp(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const char_type* data ) const
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ NS_NOTREACHED("null data pointer");
+ return mLength == 0;
+ }
+
+ // XXX avoid length calculation?
+ size_type length = char_traits::length(data);
+ return mLength == length && char_traits::compare(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const char_type* data, const comparator_type& comp ) const
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ NS_NOTREACHED("null data pointer");
+ return mLength == 0;
+ }
+
+ // XXX avoid length calculation?
+ size_type length = char_traits::length(data);
+ return mLength == length && comp(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::EqualsASCII( const char* data, size_type len ) const
+ {
+ return mLength == len && char_traits::compareASCII(mData, data, len) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::EqualsASCII( const char* data ) const
+ {
+ return char_traits::compareASCIINullTerminated(mData, mLength, data) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::LowerCaseEqualsASCII( const char* data, size_type len ) const
+ {
+ return mLength == len && char_traits::compareLowerCaseToASCII(mData, data, len) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::LowerCaseEqualsASCII( const char* data ) const
+ {
+ return char_traits::compareLowerCaseToASCIINullTerminated(mData, mLength, data) == 0;
+ }
+
+nsTSubstring_CharT::size_type
+nsTSubstring_CharT::CountChar( char_type c ) const
+ {
+ const char_type *start = mData;
+ const char_type *end = mData + mLength;
+
+ return NS_COUNT(start, end, c);
+ }
+
+PRInt32
+nsTSubstring_CharT::FindChar( char_type c, index_type offset ) const
+ {
+ if (offset < mLength)
+ {
+ const char_type* result = char_traits::find(mData + offset, mLength - offset, c);
+ if (result)
+ return result - mData;
+ }
+ return -1;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp
new file mode 100644
index 00000000..7fff5175
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * computes the aggregate string length
+ */
+
+nsTSubstringTuple_CharT::size_type
+nsTSubstringTuple_CharT::Length() const
+ {
+ PRUint32 len;
+ if (mHead)
+ len = mHead->Length();
+ else
+ len = TO_SUBSTRING(mFragA).Length();
+
+ return len + TO_SUBSTRING(mFragB).Length();
+ }
+
+
+ /**
+ * writes the aggregate string to the given buffer. bufLen is assumed
+ * to be equal to or greater than the value returned by the Length()
+ * method. the string written to |buf| is not null-terminated.
+ */
+
+void
+nsTSubstringTuple_CharT::WriteTo( char_type *buf, PRUint32 bufLen ) const
+ {
+ const substring_type& b = TO_SUBSTRING(mFragB);
+
+ NS_ASSERTION(bufLen >= b.Length(), "buffer too small");
+ PRUint32 headLen = bufLen - b.Length();
+ if (mHead)
+ {
+ mHead->WriteTo(buf, headLen);
+ }
+ else
+ {
+ const substring_type& a = TO_SUBSTRING(mFragA);
+
+ NS_ASSERTION(a.Length() == headLen, "buffer incorrectly sized");
+ char_traits::copy(buf, a.Data(), a.Length());
+ }
+
+ char_traits::copy(buf + headLen, b.Data(), b.Length());
+
+#if 0
+ // we need to write out data into |buf|, ending at |buf+bufLen|. so our
+ // data needs to precede |buf+bufLen| exactly. we trust that the buffer
+ // was properly sized!
+
+ const substring_type& b = TO_SUBSTRING(mFragB);
+
+ NS_ASSERTION(bufLen >= b.Length(), "buffer is too small");
+ char_traits::copy(buf + bufLen - b.Length(), b.Data(), b.Length());
+
+ bufLen -= b.Length();
+
+ if (mHead)
+ {
+ mHead->WriteTo(buf, bufLen);
+ }
+ else
+ {
+ const substring_type& a = TO_SUBSTRING(mFragA);
+ NS_ASSERTION(bufLen == a.Length(), "buffer is too small");
+ char_traits::copy(buf, a.Data(), a.Length());
+ }
+#endif
+ }
+
+
+ /**
+ * returns true if this tuple is dependent on (i.e., overlapping with)
+ * the given char sequence.
+ */
+
+PRBool
+nsTSubstringTuple_CharT::IsDependentOn( const char_type *start, const char_type *end ) const
+ {
+ // we start with the right-most fragment since it is faster to check.
+
+ if (TO_SUBSTRING(mFragB).IsDependentOn(start, end))
+ return PR_TRUE;
+
+ if (mHead)
+ return mHead->IsDependentOn(start, end);
+
+ return TO_SUBSTRING(mFragA).IsDependentOn(start, end);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp b/src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp
new file mode 100644
index 00000000..ca9a76e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp
@@ -0,0 +1,261 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+#include "nsCharTraits.h"
+
+#define NS_STRINGAPI_IMPL
+#include "nsStringAPI.h"
+#include "nsNativeCharsetUtils.h"
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_StringContainerInit(nsStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsStringContainer) >= sizeof(nsString),
+ "nsStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsString object
+ new (&aContainer) nsString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_StringContainerFinish(nsStringContainer &aContainer)
+{
+ // call the nsString dtor
+ NS_REINTERPRET_CAST(nsString *, &aContainer)->~nsString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_StringGetData(const nsAString &aStr, const PRUnichar **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsAString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(PRUnichar *)
+NS_StringCloneData(const nsAString &aStr)
+{
+ return ToNewUnicode(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetData(nsAString &aStr, const PRUnichar *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetDataRange(nsAString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const PRUnichar *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringContainerInit(nsCStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsCStringContainer) >= sizeof(nsCString),
+ "nsCStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsCString object
+ new (&aContainer) nsCString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_CStringContainerFinish(nsCStringContainer &aContainer)
+{
+ // call the nsCString dtor
+ NS_REINTERPRET_CAST(nsCString *, &aContainer)->~nsCString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_CStringGetData(const nsACString &aStr, const char **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsACString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(char *)
+NS_CStringCloneData(const nsACString &aStr)
+{
+ return ToNewCString(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetData(nsACString &aStr, const char *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetDataRange(nsACString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const char *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringToUTF16(const nsACString &aSrc,
+ nsCStringEncoding aSrcEncoding,
+ nsAString &aDest)
+{
+ switch (aSrcEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ CopyASCIItoUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF8toUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyNativeToUnicode(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_UTF16ToCString(const nsAString &aSrc,
+ nsCStringEncoding aDestEncoding,
+ nsACString &aDest)
+{
+ switch (aDestEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ LossyCopyUTF16toASCII(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF16toUTF8(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyUnicodeToNative(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/.cvsignore
new file mode 100644
index 00000000..d01075e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/.cvsignore
@@ -0,0 +1,31 @@
+CvtURL
+FilesTest
+Makefile
+PropertiesTest
+RegFactory
+SizeTest01
+SizeTest02
+SizeTest03
+SizeTest04
+SizeTest05
+SizeTest06
+TestAtoms
+TestAutoLock
+TestBuffers
+TestCOMPtr
+TestCOMPtrEq
+TestArray
+TestCRT
+TestFactory
+TestID
+TestObserverService
+TestPermanentAtoms
+TestPipes
+TestThreads
+TestVoidBTree
+TestXPIDLString
+TestServMgr
+nsIFileEnumerator
+nsIFileTest
+TestCallTemplates
+TestDeque
diff --git a/src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp b/src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp
new file mode 100644
index 00000000..4dd052ac
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include <stdio.h>
+#include "nscore.h"
+#include "nsIConverterInputStream.h"
+#include "nsIURL.h"
+#include "nsNetUtil.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "prprf.h"
+#include "prtime.h"
+
+static nsString* ConvertCharacterSetName(const char* aName)
+{
+ return new nsString(NS_ConvertASCIItoUCS2(aName));
+}
+
+int main(int argc, char** argv)
+{
+ if (3 != argc) {
+ printf("usage: CvtURL url utf8\n");
+ return -1;
+ }
+
+ char* characterSetName = argv[2];
+ nsString* cset = ConvertCharacterSetName(characterSetName);
+ if (NS_PTR_TO_INT32(cset) < 0) {
+ printf("illegal character set name: '%s'\n", characterSetName);
+ return -1;
+ }
+
+ // Create url object
+ char* urlName = argv[1];
+ nsIURI* url;
+ nsresult rv;
+ rv = NS_NewURI(&url, urlName);
+ if (NS_OK != rv) {
+ printf("invalid URL: '%s'\n", urlName);
+ return -1;
+ }
+
+ // Get an input stream from the url
+ nsresult ec;
+ nsIInputStream* in;
+ ec = NS_OpenURI(&in, url);
+ if (nsnull == in) {
+ printf("open of url('%s') failed: error=%x\n", urlName, ec);
+ return -1;
+ }
+
+ // Translate the input using the argument character set id into
+ // unicode
+ nsCOMPtr<nsIConverterInputStream> uin =
+ do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ uin->Init(in, cset->get(), nsnull, PR_TRUE);
+ if (NS_OK != rv) {
+ printf("can't create converter input stream: %d\n", rv);
+ return -1;
+ }
+
+ // Read the input and write some output
+ PRTime start = PR_Now();
+ PRInt32 count = 0;
+ for (;;) {
+ PRUnichar buf[1000];
+ PRUint32 nb;
+ ec = uin->Read(buf, 0, 1000, &nb);
+ if (NS_FAILED(ec)) {
+ printf("i/o error: %d\n", ec);
+ break;
+ }
+ if (nb == 0) break; // EOF
+ count += nb;
+ }
+ PRTime end = PR_Now();
+ PRTime conversion, ustoms;
+ LL_I2L(ustoms, 1000);
+ LL_SUB(conversion, end, start);
+ LL_DIV(conversion, conversion, ustoms);
+ char buf[500];
+ PR_snprintf(buf, sizeof(buf),
+ "converting and discarding %d bytes took %lldms",
+ count, conversion);
+ puts(buf);
+
+ // Release the objects
+ in->Release();
+ url->Release();
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/Makefile.in
new file mode 100644
index 00000000..2bd730e9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/Makefile.in
@@ -0,0 +1,116 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = dynamic services
+ifeq ($(OS_ARCH),WINNT)
+DIRS += windows
+endif
+
+REQUIRES = \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ nsIFileEnumerator.cpp \
+ nsIFileTest.cpp \
+ TestArray.cpp \
+ TestAtoms.cpp \
+ TestAutoLock.cpp \
+ TestCallTemplates.cpp \
+ TestCOMPtr.cpp \
+ TestCOMPtrEq.cpp \
+ TestCRT.cpp \
+ TestFactory.cpp \
+ TestHashtables.cpp \
+ TestID.cpp \
+ TestObserverService.cpp \
+ TestPermanentAtoms.cpp \
+ TestPipes.cpp \
+ TestServMgr.cpp \
+ TestThreads.cpp \
+ TestXPIDLString.cpp \
+ TestDeque.cpp \
+ TestAutoPtr.cpp \
+ TestMinStringAPI.cpp \
+ TestStrings.cpp \
+ $(NULL)
+
+#CPPSRCS += TimerTest.cpp
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+LIBS += \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# Needed to resolve __yylex (?)
+ifeq ($(OS_ARCH)$(OS_RELEASE),FreeBSD2)
+LIBS += -lpcap
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../ds \
+ -I$(srcdir)/services \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CXX
+CXXFLAGS += -fexceptions
+else
+CXXFLAGS += -GX
+endif
+endif
+
+libs::
+ $(INSTALL) $(srcdir)/test.properties $(DIST)/bin/res
+
+install::
+ $(SYSINSTALL) $(IFLAGS1) $(srcdir)/test.properties $(DESTDIR)$(mozappdir)/res
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp b/src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp
new file mode 100644
index 00000000..79e53394
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <iostream.h>
+#include "plstr.h"
+#include "prlink.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+static PRBool gUnreg = PR_FALSE;
+
+void print_err(nsresult err)
+{
+ switch (err) {
+ case NS_ERROR_FACTORY_NOT_LOADED:
+ cerr << "Factory not loaded";
+ break;
+ case NS_NOINTERFACE:
+ cerr << "No Interface";
+ break;
+ case NS_ERROR_NULL_POINTER:
+ cerr << "Null pointer";
+ break;
+ case NS_ERROR_OUT_OF_MEMORY:
+ cerr << "Out of memory";
+ break;
+ default:
+ cerr << hex << err << dec;
+ }
+}
+
+nsresult Register(nsIComponentRegistrar* registrar, const char *path)
+{
+ nsCOMPtr<nsILocalFile> file;
+ nsresult rv =
+ NS_NewLocalFile(
+ NS_ConvertUTF8toUCS2(path),
+ PR_TRUE,
+ getter_AddRefs(file));
+ if (NS_FAILED(rv)) return rv;
+ rv = registrar->AutoRegister(file);
+ return rv;
+}
+
+nsresult Unregister(const char *path)
+{
+ /* NEEDS IMPLEMENTATION */
+#if 0
+ nsresult res = nsComponentManager::AutoUnregisterComponent(path);
+ return res;
+#else
+ return NS_ERROR_FAILURE;
+#endif
+}
+
+int ProcessArgs(nsIComponentRegistrar* registrar, int argc, char *argv[])
+{
+ int i = 1;
+ nsresult res;
+
+ while (i < argc) {
+ if (argv[i][0] == '-') {
+ int j;
+ for (j = 1; argv[i][j] != '\0'; j++) {
+ switch (argv[i][j]) {
+ case 'u':
+ gUnreg = PR_TRUE;
+ break;
+ default:
+ cerr << "Unknown option '" << argv[i][j] << "'\n";
+ }
+ }
+ i++;
+ } else {
+ if (gUnreg == PR_TRUE) {
+ res = Unregister(argv[i]);
+ if (NS_SUCCEEDED(res)) {
+ cout << "Successfully unregistered: " << argv[i] << "\n";
+ } else {
+ cerr << "Unregister failed (";
+ print_err(res);
+ cerr << "): " << argv[i] << "\n";
+ }
+ } else {
+ res = Register(registrar, argv[i]);
+ if (NS_SUCCEEDED(res)) {
+ cout << "Successfully registered: " << argv[i] << "\n";
+ } else {
+ cerr << "Register failed (";
+ print_err(res);
+ cerr << "): " << argv[i] << "\n";
+ }
+ }
+ i++;
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ nsresult rv;
+ {
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+
+ /* With no arguments, RegFactory will autoregister */
+ if (argc <= 1)
+ {
+ rv = registrar->AutoRegister(nsnull);
+ ret = (NS_FAILED(rv)) ? -1 : 0;
+ }
+ else
+ ret = ProcessArgs(registrar, argc, argv);
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM( NULL );
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return ret;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp
new file mode 100644
index 00000000..2d552a36
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp
@@ -0,0 +1,107 @@
+// Test01.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ This test file compares the generated code size of similar functions between raw
+ COM interface pointers (|AddRef|ing and |Release|ing by hand) and |nsCOMPtr|s.
+
+ Function size results were determined by examining dissassembly of the generated code.
+ mXXX is the size of the generated code on the Macintosh. wXXX is the size on Windows.
+ For these tests, all reasonable optimizations were enabled and exceptions were
+ disabled (just as we build for release).
+
+ The tests in this file explore only the simplest functionality: assigning a pointer
+ to be reference counted into a [raw, nsCOMPtr] object; ensuring that it is
+ |AddRef|ed and |Release|d appropriately; calling through the pointer to a function
+ supplied by the underlying COM interface.
+
+ Windows:
+ raw_optimized 31 bytes
+ raw, nsCOMPtr* 34
+ nsCOMPtr_optimized* 38
+ nsCOMPtr_optimized 42
+ nsCOMPtr 46
+
+ Macintosh:
+ raw_optimized, nsCOMPtr_optimized 112 bytes (1.0000)
+ nsCOMPtr 120 (1.0714) i.e., 7.14% bigger than raw_optimized et al
+ raw 140 (1.2500)
+
+ The overall difference in size between Windows and Macintosh is caused by the
+ the PowerPC RISC architecture where every instruction is 4 bytes.
+
+ On Macintosh, nsCOMPtr generates out-of-line destructors which are
+ not referenced, and which can be stripped by the linker.
+ */
+
+void
+Test01_raw( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m140, w34
+ {
+ /*
+ This test is designed to be more like a typical large function where,
+ because you are working with several resources, you don't just return when
+ one of them is |NULL|. Similarly: |Test01_nsCOMPtr00|, and |Test01_nsIPtr00|.
+ */
+
+ nsIDOMNode* node = aDOMNode;
+ NS_IF_ADDREF(node);
+
+ if ( node )
+ node->GetNodeName(*aResult);
+
+ NS_IF_RELEASE(node);
+ }
+
+void
+Test01_raw_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m112, w31
+ {
+ /*
+ This test simulates smaller functions where you _do_ just return
+ |NULL| at the first sign of trouble. Similarly: |Test01_nsCOMPtr01|,
+ and |Test01_nsIPtr01|.
+ */
+
+ /*
+ This test produces smaller code that |Test01_raw| because it avoids
+ the three tests: |NS_IF_...|, and |if ( node )|.
+ */
+
+// -- the following code is assumed, but is commented out so we compare only
+// the relevent generated code
+
+// if ( !aDOMNode )
+// return;
+
+ nsIDOMNode* node = aDOMNode;
+ NS_ADDREF(node);
+ node->GetNodeName(*aResult);
+ NS_RELEASE(node);
+ }
+
+void
+Test01_nsCOMPtr( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m120, w46/34
+ {
+ nsCOMPtr<nsIDOMNode> node = aDOMNode;
+
+ if ( node )
+ node->GetNodeName(*aResult);
+ }
+
+void
+Test01_nsCOMPtr_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m112, w42/38
+ {
+// if ( !aDOMNode )
+// return;
+
+ nsCOMPtr<nsIDOMNode> node = aDOMNode;
+ node->GetNodeName(*aResult);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp
new file mode 100644
index 00000000..8515fcb1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp
@@ -0,0 +1,93 @@
+// Test02.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ This test file compares the generated code size of similar functions between raw
+ COM interface pointers (|AddRef|ing and |Release|ing by hand) and |nsCOMPtr|s.
+
+ Function size results were determined by examining dissassembly of the generated code.
+ mXXX is the size of the generated code on the Macintosh. wXXX is the size on Windows.
+ For these tests, all reasonable optimizations were enabled and exceptions were
+ disabled (just as we build for release).
+
+ The tests in this file explore more complicated functionality: assigning a pointer
+ to be reference counted into a [raw, nsCOMPtr] object using |QueryInterface|;
+ ensuring that it is |AddRef|ed and |Release|d appropriately; calling through the pointer
+ to a function supplied by the underlying COM interface. The tests in this file expand
+ on the tests in "Test01.cpp" by adding |QueryInterface|.
+
+ Windows:
+ raw01 52
+ nsCOMPtr 63
+ raw 66
+ nsCOMPtr* 68
+
+ Macintosh:
+ nsCOMPtr 120 (1.0000)
+ Raw01 128 (1.1429) i.e., 14.29% bigger than nsCOMPtr
+ Raw00 144 (1.2000)
+ */
+
+
+void // nsresult
+Test02_Raw00( nsISupports* aDOMNode, nsString* aResult )
+ // m144, w66
+ {
+// -- the following code is assumed, but is commented out so we compare only
+// the relevent generated code
+
+// if ( !aDOMNode )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* node = 0;
+ nsresult status = aDOMNode->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&node);
+ if ( NS_SUCCEEDED(status) )
+ {
+ node->GetNodeName(*aResult);
+ }
+
+ NS_IF_RELEASE(node);
+
+// return status;
+ }
+
+void // nsresult
+Test02_Raw01( nsISupports* aDOMNode, nsString* aResult )
+ // m128, w52
+ {
+// if ( !aDOMNode )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* node;
+ nsresult status = aDOMNode->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&node);
+ if ( NS_SUCCEEDED(status) )
+ {
+ node->GetNodeName(*aResult);
+ NS_RELEASE(node);
+ }
+
+// return status;
+ }
+
+void // nsresult
+Test02_nsCOMPtr( nsISupports* aDOMNode, nsString* aResult )
+ // m120, w63/68
+ {
+ nsresult status;
+ nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aDOMNode, &status);
+
+ if ( node )
+ node->GetNodeName(*aResult);
+
+// return status;
+ }
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp
new file mode 100644
index 00000000..9ca71c72
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp
@@ -0,0 +1,101 @@
+// Test03.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ Windows:
+ nsCOMPtr_optimized* 45
+ raw_optimized 48
+ nsCOMPtr_optimized 50
+ nsCOMPtr 54
+ nsCOMPtr* 59
+ raw 62
+
+ Macintosh:
+ nsCOMPtr_optimized 112 (1.0000)
+ raw_optimized 124 bytes (1.1071) i.e., 10.71% bigger than nsCOMPtr_optimized
+ nsCOMPtr 144 (1.2857)
+ */
+
+void // nsresult
+Test03_raw( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m140, w62
+ {
+// -- the following code is assumed, but is commented out so we compare only
+// the relevent generated code
+
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* parent = 0;
+ nsresult status = aDOMNode->GetParentNode(&parent);
+
+ if ( NS_SUCCEEDED(status) )
+ {
+ parent->GetNodeName(*aResult);
+ }
+
+ NS_IF_RELEASE(parent);
+
+// return status;
+ }
+
+
+void // nsresult
+Test03_raw_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m124, w48
+ {
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* parent;
+ nsresult status = aDOMNode->GetParentNode(&parent);
+
+ if ( NS_SUCCEEDED(status) )
+ {
+ parent->GetNodeName(*aResult);
+ NS_RELEASE(parent);
+ }
+
+// return status;
+ }
+
+
+void // nsresult
+Test03_nsCOMPtr( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m144, w54/59
+ {
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsCOMPtr<nsIDOMNode> parent;
+ nsresult status = aDOMNode->GetParentNode( getter_AddRefs(parent) );
+ if ( parent )
+ parent->GetNodeName(*aResult);
+
+// return status;
+ }
+
+void // nsresult
+Test03_nsCOMPtr_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m112, w50/45
+ {
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* temp;
+ nsresult status = aDOMNode->GetParentNode(&temp);
+ nsCOMPtr<nsIDOMNode> parent( dont_AddRef(temp) );
+ if ( parent )
+ parent->GetNodeName(*aResult);
+
+// return status;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp
new file mode 100644
index 00000000..aad4ee68
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp
@@ -0,0 +1,72 @@
+// Test04.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ Windows:
+ nsCOMPtr 13
+ raw 36
+
+ Macintosh:
+ nsCOMPtr 36 bytes (1.0000)
+ raw 120 (3.3333) i.e., 333.33% bigger than nsCOMPtr
+ */
+
+class Test04_Raw
+ {
+ public:
+ Test04_Raw();
+ ~Test04_Raw();
+
+ void /*nsresult*/ SetNode( nsIDOMNode* newNode );
+
+ private:
+ nsIDOMNode* mNode;
+ };
+
+Test04_Raw::Test04_Raw()
+ : mNode(0)
+ {
+ // nothing else to do here
+ }
+
+Test04_Raw::~Test04_Raw()
+ {
+ NS_IF_RELEASE(mNode);
+ }
+
+void // nsresult
+Test04_Raw::SetNode( nsIDOMNode* newNode )
+ // m120, w36
+ {
+ NS_IF_ADDREF(newNode);
+ NS_IF_RELEASE(mNode);
+ mNode = newNode;
+
+// return NS_OK;
+ }
+
+
+
+class Test04_nsCOMPtr
+ {
+ public:
+ void /*nsresult*/ SetNode( nsIDOMNode* newNode );
+
+ private:
+ nsCOMPtr<nsIDOMNode> mNode;
+ };
+
+void // nsresult
+Test04_nsCOMPtr::SetNode( nsIDOMNode* newNode )
+ // m36, w13/13
+ {
+ mNode = newNode;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp
new file mode 100644
index 00000000..0211610e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp
@@ -0,0 +1,78 @@
+// Test05.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ Windows:
+ raw, nsCOMPtr 21 bytes
+
+ Macintosh:
+ Raw, nsCOMPtr 64 bytes
+ */
+
+class Test05_Raw
+ {
+ public:
+ Test05_Raw();
+ ~Test05_Raw();
+
+ void /*nsresult*/ GetNode( nsIDOMNode** aNode );
+
+ private:
+ nsIDOMNode* mNode;
+ };
+
+Test05_Raw::Test05_Raw()
+ : mNode(0)
+ {
+ // nothing else to do here
+ }
+
+Test05_Raw::~Test05_Raw()
+ {
+ NS_IF_RELEASE(mNode);
+ }
+
+void // nsresult
+Test05_Raw::GetNode( nsIDOMNode** aNode )
+ // m64, w21
+ {
+// if ( !aNode )
+// return NS_ERROR_NULL_POINTER;
+
+ *aNode = mNode;
+ NS_IF_ADDREF(*aNode);
+
+// return NS_OK;
+ }
+
+
+
+class Test05_nsCOMPtr
+ {
+ public:
+ void /*nsresult*/ GetNode( nsIDOMNode** aNode );
+
+ private:
+ nsCOMPtr<nsIDOMNode> mNode;
+ };
+
+void // nsresult
+Test05_nsCOMPtr::GetNode( nsIDOMNode** aNode )
+ // m64, w21
+ {
+// if ( !aNode )
+// return NS_ERROR_NULL_POINTER;
+
+ *aNode = mNode;
+ NS_IF_ADDREF(*aNode);
+
+// return NS_OK;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp
new file mode 100644
index 00000000..2c28e7f3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp
@@ -0,0 +1,231 @@
+// Test06.cpp
+
+#include "nsIDOMWindowInternal.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIWebShell.h"
+#include "nsIDocShell.h"
+#include "nsIWebShellWindow.h"
+#include "nsCOMPtr.h"
+
+NS_DEF_PTR(nsIScriptGlobalObject);
+NS_DEF_PTR(nsIWebShell);
+NS_DEF_PTR(nsIWebShellContainer);
+NS_DEF_PTR(nsIWebShellWindow);
+
+ /*
+ Windows:
+ nsCOMPtr_optimized 176
+ nsCOMPtr_as_found 181
+ nsCOMPtr_optimized* 182
+ nsCOMPtr02* 184
+ nsCOMPtr02 187
+ nsCOMPtr02* 188
+ nsCOMPtr03 189
+ raw_optimized, nsCOMPtr00 191
+ nsCOMPtr00* 199
+ nsCOMPtr_as_found* 201
+ raw 214
+
+ Macintosh:
+ nsCOMPtr_optimized 300 (1.0000)
+ nsCOMPtr02 320 (1.0667) i.e., 6.67% bigger than nsCOMPtr_optimized
+ nsCOMPtr00 328 (1.0933)
+ raw_optimized, nsCOMPtr03 332 (1.1067)
+ nsCOMPtr_as_found 344 (1.1467)
+ raw 388 (1.2933)
+
+ */
+
+
+void // nsresult
+Test06_raw(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m388, w214
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ nsIScriptGlobalObject* scriptGlobalObject = 0;
+ nsresult status = aDOMWindow->QueryInterface(NS_GET_IID(nsIScriptGlobalObject), (void**)&scriptGlobalObject);
+ nsIDocShell* docShell = 0;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(&docShell);
+ nsIWebShell* webShell = 0;
+ if (docShell)
+ status=docShell->QueryInterface(NS_GET_IID(nsIWebShell), (void**)&webShell);
+ nsIWebShell* rootWebShell = 0;
+ if (webShell)
+ //status = webShell->GetRootWebShellEvenIfChrome(rootWebShell);
+ {}
+ nsIWebShellContainer* webShellContainer = 0;
+ if (rootWebShell)
+ status = rootWebShell->GetContainer(webShellContainer);
+ if (webShellContainer)
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ else
+ (*aWebShellWindow) = 0;
+ NS_IF_RELEASE(webShellContainer);
+ NS_IF_RELEASE(rootWebShell);
+ NS_IF_RELEASE(webShell);
+ NS_IF_RELEASE(docShell);
+ NS_IF_RELEASE(scriptGlobalObject);
+// return status;
+}
+
+void // nsresult
+Test06_raw_optimized(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m332, w191
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ (*aWebShellWindow) = 0;
+ nsIScriptGlobalObject* scriptGlobalObject;
+ nsresult status = aDOMWindow->QueryInterface(NS_GET_IID(nsIScriptGlobalObject), (void**)&scriptGlobalObject);
+ if (NS_SUCCEEDED(status)) {
+ nsIDocShell* docShell = 0;
+ scriptGlobalObject->GetDocShell(&docShell);
+ if (docShell) {
+ nsIWebShell* webShell = 0;
+ docShell->QueryInterface(NS_GET_IID(nsIWebShell), (void**)webShell);
+ if (webShell) {
+ nsIWebShell* rootWebShell;
+ // status = webShell->GetRootWebShellEvenIfChrome(rootWebShell);
+ if (NS_SUCCEEDED(status)) {
+ nsIWebShellContainer* webShellContainer;
+ status = rootWebShell->GetContainer(webShellContainer);
+ if (NS_SUCCEEDED(status)) {
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ NS_RELEASE(webShellContainer);
+ }
+ NS_RELEASE(rootWebShell);
+ }
+ NS_RELEASE(webShell);
+ }
+ NS_RELEASE(docShell);
+ }
+ NS_RELEASE(scriptGlobalObject);
+ }
+// return status;
+}
+
+void
+Test06_nsCOMPtr_as_found(nsIDOMWindowInternal* aDOMWindow, nsCOMPtr<nsIWebShellWindow>* aWebShellWindow)
+ // m344, w181/201
+{
+// if (!aDOMWindow)
+// return;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow);
+ nsCOMPtr<nsIDocShell> docShell;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(getter_AddRefs(docShell));
+ nsCOMPtr<nsIWebShell> webShell;
+ if (docShell)
+ webShell = do_QueryInterface(docShell);
+ nsCOMPtr<nsIWebShell> rootWebShell;
+ if (webShell)
+ //webShell->GetRootWebShellEvenIfChrome(*getter_AddRefs(rootWebShell));
+ {}
+ nsCOMPtr<nsIWebShellContainer> webShellContainer;
+ if (rootWebShell)
+ rootWebShell->GetContainer(*getter_AddRefs(webShellContainer));
+ (*aWebShellWindow) = do_QueryInterface(webShellContainer);
+}
+
+void // nsresult
+Test06_nsCOMPtr00(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m328, w191/199
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ nsIDocShell* temp0 = 0;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIDocShell> docShell = dont_AddRef(temp0);
+ nsCOMPtr<nsIWebShell> webShell;
+ if (docShell)
+ webShell=do_QueryInterface(docShell, &status);
+ nsIWebShellContainer* temp2 = 0;
+ if (webShell)
+ status = webShell->GetContainer(temp2);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp2);
+ if (webShellContainer)
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ else
+ (*aWebShellWindow) = 0;
+// return status;
+}
+
+void // nsresult
+Test06_nsCOMPtr_optimized(nsIDOMWindowInternal* aDOMWindow, nsCOMPtr<nsIWebShellWindow>* aWebShellWindow)
+ // m300, w176/182
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ nsIDocShell* temp0 = 0;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIWebShell> webShell = do_QueryInterface(temp0, &status);
+ nsIWebShell* temp2 = 0;
+ if (webShell)
+ // status = webShell->GetRootWebShellEvenIfChrome(temp2);
+ {}
+ nsCOMPtr<nsIWebShell> rootWebShell = dont_AddRef(temp2);
+ nsIWebShellContainer* temp3 = 0;
+ if (rootWebShell)
+ status = rootWebShell->GetContainer(temp3);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp3);
+ (*aWebShellWindow) = do_QueryInterface(webShellContainer, &status);
+// return status;
+}
+
+void // nsresult
+Test06_nsCOMPtr02(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m320, w187/184
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ (*aWebShellWindow) = 0;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ if (scriptGlobalObject) {
+ nsIDocShell* temp0;
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIWebShell> webShell = do_QueryInterface(temp0);
+ if (webShell) {
+ nsIWebShellContainer* temp2;
+ status = webShell->GetContainer(temp2);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp2);
+ if (webShellContainer)
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ }
+ }
+// return status;
+}
+
+void // nsresult
+Test06_nsCOMPtr03(nsIDOMWindowInternal* aDOMWindow, nsCOMPtr<nsIWebShellWindow>* aWebShellWindow)
+ // m332, w189/188
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ (*aWebShellWindow) = 0;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ if (scriptGlobalObject) {
+ nsIDocShell* temp0;
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIDocShell> docShell = dont_AddRef(temp0);
+ if (docShell) {
+ nsCOMPtr<nsIWebShell> webShell = do_QueryInterface(docShell, &status);
+ if (webShell) {
+ nsIWebShellContainer* temp2;
+ status = webShell->GetContainer(temp2);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp2);
+ (*aWebShellWindow) = do_QueryInterface(webShellContainer, &status);
+ }
+ }
+ }
+// return status;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in
new file mode 100644
index 00000000..1ced5d3e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in
@@ -0,0 +1,76 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+PROGRAM = profile_strings
+#PROGRAM = test_main
+
+CPPSRCS = \
+ $(topsrcdir)/xpcom/ds/nsString2.cpp \
+ $(topsrcdir)/xpcom/ds/nsStr.cpp \
+ $(topsrcdir)/xpcom/ds/nsString.cpp \
+ $(topsrcdir)/xpcom/ds/nsCRT.cpp \
+ $(topsrcdir)/xpcom/base/nsAllocator.cpp \
+ $(topsrcdir)/xpcom/ds/nsDeque.cpp \
+ profile_main.cpp \
+ $(NULL)
+# test_main.cpp \
+
+
+LIBS += \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DNEW_STRING_APIS -DSTANDALONE_STRING_TESTS -UDEBUG -DNDEBUG
+#DEFINES += -DSTANDALONE_STRING_TESTS -UDEBUG -DNDEBUG
+INCLUDES += -I$(srcdir)/../public -I$(srcdir)/services
+
+libs::
+ $(INSTALL) $(srcdir)/test.properties $(DIST)/bin/res
+
+install::
+ $(SYSINSTALL) $(IFLAGS1) $(srcdir)/test.properties $(DESTDIR)$(mozappdir)/res
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix
new file mode 100644
index 00000000..b9580e49
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix
@@ -0,0 +1,4 @@
+// StringTest.Prefix
+
+#define STANDALONE_STRING_TESTS
+#define HAVE_CPP_2BYTE_WCHAR_T
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp
new file mode 100644
index 00000000..12b125ed
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix
new file mode 100644
index 00000000..3724af94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix
@@ -0,0 +1,4 @@
+#include "StringTest.Prefix"
+
+#define DEBUG 1
+#undef NDEBUG
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix
new file mode 100644
index 00000000..dddf8450
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix
@@ -0,0 +1,5 @@
+// StringTestNo_wchar_t.Prefix
+
+#include "StringTest.Prefix"
+
+#undef HAVE_CPP_2BYTE_WCHAR_T
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix
new file mode 100644
index 00000000..b6ca50d3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix
@@ -0,0 +1,3 @@
+// StringTestProfileNew.Prefix
+
+#include "StringTest.Prefix"
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix
new file mode 100644
index 00000000..d23e3ea9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix
@@ -0,0 +1,6 @@
+// StringTestProfileOld.Prefix
+
+#include "StringTest.Prefix"
+
+#define OLD_STRING_APIS
+#undef HAVE_CPP_2BYTE_WCHAR_T \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix
new file mode 100644
index 00000000..eb8a7a85
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix
@@ -0,0 +1,7 @@
+// StringTestProfileOld.Prefix
+
+#include "StringTest.Prefix"
+
+#define OLD_STRING_APIS
+#define TEST_STD_STRING
+#undef HAVE_CPP_2BYTE_WCHAR_T \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc
new file mode 100644
index 00000000..da114471
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc
@@ -0,0 +1,41 @@
+// To Do...
+
+ - Decide: do I really want to define |Equals| (i.e., so many extra signatures)
+
+ . Make |ns[C]String| rename its converting operations to, e.g., |EqualsWithConversion|,
+ |AssignWithConversion|, |CompareWithConversion|, |AppendWithConversion|, etc.
+
+ . Bring |Equals| and |Compare| into scope
+
+ . Implement chunky iterators
+
+ . Get "nsAReadableString.h" and "nsAWritableString.h" to added to the MANIFEST, etc.
+
+ - Get "nsAReadableString.h" and "nsAWritableString.h" to compile everywhere
+
+ - Add test for |Replace|...
+
+ - Add tests for Find and RFind
+
+ - Implement the Find and RFind signatures
+
+ . Fix Truncate / SetLength confusion (make SetLength the real function in |nsString|)
+
+ . Chop out conflicting |ns[C]String| operators
+
+ . Figure out how if we can make PRUnichar be wchar_t, so we get the cheap constructors,
+ ...and ensure the cheap constructors can be made to work everywhere
+
+ x Try the |static const unsigned long kLeftString = 1 - 1; /* because VC++ doesn't like =0 */| hack
+
+ . Add tests for |nsShared[C]String|
+
+ . Implement |nsShared[C]String|
+
+ - Add tests for the shared string smart pointer
+
+ . Implement the shared string smart pointer
+
+ . Figure out why StdStringWrapper isn't as good as raw std::string
+
+ - Implement a smart allocator for StdStringWrapper
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h
new file mode 100644
index 00000000..6e43b528
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h
@@ -0,0 +1,234 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsStdStringWrapper_h___
+#define nsStdStringWrapper_h___
+
+#include <string>
+
+#ifndef nsAString_h___
+#include "nsAString.h"
+#endif
+
+
+template <class T>
+class nsStringAllocator
+ : public std::allocator<T> // temporarily
+ {
+ // ...
+ };
+
+
+template < class CharT, class TraitsT = nsCharTraits<CharT>, class AllocatorT = nsStringAllocator<CharT> >
+class basic_nsStdStringWrapper
+ : public basic_nsAString<CharT>
+ /*
+ ...
+ */
+ {
+ protected:
+ std::basic_string<CharT, TraitsT, AllocatorT> mRawString;
+
+ typedef std::basic_string<CharT, TraitsT, AllocatorT> basic_string_t;
+
+ using typename basic_string_t::traits_type;
+ using typename basic_string_t::value_type;
+ using typename basic_string_t::allocator_type;
+ using typename basic_string_t::size_type;
+ using typename basic_string_t::difference_type;
+ using typename basic_string_t::reference;
+ using typename basic_string_t::const_reference;
+ using typename basic_string_t::pointer;
+ using typename basic_string_t::const_pointer;
+ using typename basic_string_t::iterator;
+ using typename basic_string_t::const_iterator;
+ using typename basic_string_t::reverse_iterator;
+ using typename basic_string_t::const_reverse_iterator;
+
+ static const size_type npos = size_type(-1);
+
+ protected:
+ virtual const void* Implementation() const;
+
+ virtual const CharT* GetReadableFragment( nsReadableFragment<CharT>&, nsFragmentRequest, PRUint32 ) const;
+ virtual CharT* GetWritableFragment( nsWritableFragment<CharT>&, nsFragmentRequest, PRUint32 );
+
+ public:
+ basic_nsStdStringWrapper() { }
+
+#if 0
+ explicit
+ basic_nsStdStringWrapper( const AllocatorT& a = AllocatorT() )
+ : mRawString(a)
+ {
+ }
+#endif
+
+ explicit
+ basic_nsStdStringWrapper( const basic_nsAString<CharT>& str )
+ {
+ Assign(str);
+ }
+
+#if 0
+ explicit
+ basic_nsStdStringWrapper( const basic_string_t& str, size_type pos = 0, size_type n = npos )
+ : mRawString(str, pos, n)
+ {
+ }
+
+ basic_nsStdStringWrapper( const basic_string_t& str, size_type pos, size_type n, const AllocatorT& a )
+ : mRawString(str, pos, n, a)
+ {
+ }
+#endif
+
+ basic_nsStdStringWrapper( const CharT* s, size_type n, const AllocatorT& a = AllocatorT() )
+ : mRawString(s, n, a)
+ {
+ }
+
+ explicit
+ basic_nsStdStringWrapper( const CharT* s, const AllocatorT& a = AllocatorT() )
+ : mRawString(s, a)
+ {
+ }
+
+#if 0
+ basic_nsStdStringWrapper( size_type n, CharT c, const AllocatorT& a = AllocatorT() )
+ : mRawString(n, c, a)
+ {
+ }
+#endif
+
+ virtual
+ PRUint32
+ Length() const
+ {
+ return mRawString.length();
+ }
+
+ virtual
+ void
+ SetCapacity( PRUint32 aNewCapacity )
+ {
+ mRawString.reserve(aNewCapacity);
+ }
+
+ virtual
+ void
+ SetLength( PRUint32 aNewLength )
+ {
+ mRawString.resize(aNewLength);
+ }
+
+ protected:
+ virtual void do_AssignFromReadable( const basic_nsAString<CharT>& );
+
+ // ...
+ };
+
+NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsStdStringWrapper<CharT>, CharT)
+
+
+
+template <class CharT, class TraitsT, class AllocatorT>
+const void*
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::Implementation() const
+ {
+ static const char* implementation = "nsStdStringWrapper";
+ return implementation;
+ }
+
+
+template <class CharT, class TraitsT, class AllocatorT>
+const CharT*
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::GetReadableFragment( nsReadableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
+ {
+ switch ( aRequest )
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ aFragment.mEnd = (aFragment.mStart = mRawString.data()) + mRawString.length();
+ return aFragment.mStart + aOffset;
+
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+
+template <class CharT, class TraitsT, class AllocatorT>
+CharT*
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::GetWritableFragment( nsWritableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
+ {
+ switch ( aRequest )
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ aFragment.mEnd = (aFragment.mStart = NS_CONST_CAST(CharT*, mRawString.data())) + mRawString.length();
+ return aFragment.mStart + aOffset;
+
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+
+template <class CharT, class TraitsT, class AllocatorT>
+void
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::do_AssignFromReadable( const basic_nsAString<CharT>& rhs )
+ {
+ typedef basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT> this_t;
+
+ if ( SameImplementation(*this, rhs) )
+ mRawString = NS_STATIC_CAST(this_t, rhs).mRawString;
+ else
+ basic_nsAString<CharT>::do_AssignFromReadable(rhs);
+ }
+
+
+typedef basic_nsStdStringWrapper<PRUnichar> nsStdString;
+typedef basic_nsStdStringWrapper<char> nsStdCString;
+
+
+#endif // !defined(nsStdStringWrapper_h___)
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp
new file mode 100644
index 00000000..d7c14621
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp
@@ -0,0 +1,497 @@
+// profile_main.cpp
+
+#include "nscore.h"
+#include <iostream.h>
+#include <string>
+#include <iomanip>
+
+#include "nsInt64.h"
+
+#ifdef XP_MAC
+#include <Timer.h>
+#include "Profiler.h"
+#else
+#include "prtime.h"
+#endif
+
+#ifndef TEST_STD_STRING
+#include "nsString.h"
+#else
+#include "nsStdStringWrapper.h"
+typedef nsStdCString nsCString;
+#endif
+
+static const int kTestSucceeded = 0;
+static const int kTestFailed = 1;
+
+static const size_t N = 100000;
+
+
+template <class T>
+inline
+PRUint32
+TotalLength( const T& s )
+ {
+ return s.Length();
+ }
+
+NS_SPECIALIZE_TEMPLATE
+inline
+PRUint32
+TotalLength( const string& s )
+ {
+ return s.length();
+ }
+
+template <class T>
+inline
+PRUint32
+Find( const T& text, const T& pattern )
+ {
+ return text.Find(pattern);
+ }
+
+NS_SPECIALIZE_TEMPLATE
+inline
+PRUint32
+Find( const string& text, const string& pattern )
+ {
+ return text.find(pattern);
+ }
+
+inline
+nsInt64
+GetTime()
+ {
+#ifdef XP_MAC
+ UnsignedWide time;
+ Microseconds(&time);
+ return nsInt64( *reinterpret_cast<PRInt64*>(&time) );
+#else
+ return nsInt64( PR_Now() );
+#endif
+ }
+
+class TestTimer
+ {
+ public:
+ TestTimer() : mStartTime(GetTime()) { }
+
+ ~TestTimer()
+ {
+ nsInt64 stopTime = GetTime();
+ nsInt64 totalTime = stopTime - mStartTime;
+#ifdef HAVE_LONG_LONG
+ cout << setw(10) << NS_STATIC_CAST(PRInt64, totalTime) << " µs : ";
+#else
+ cout << setw(10) << NS_STATIC_CAST(PRInt32, totalTime) << "µs : ";
+#endif
+ }
+
+ private:
+ nsInt64 mStartTime;
+ };
+
+inline
+int
+foo( const nsCString& )
+ {
+ return 1;
+ }
+
+static
+int
+test_construction()
+ {
+ cout << endl;
+
+ {
+ nsCString someCString;
+ int total = 0;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ total += foo( someCString );
+ }
+ }
+ cout << "null loop time for constructor" << endl;
+
+
+ {
+ int total = 0;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ total += foo( nsCString() );
+ }
+ }
+ cout << "nsCString()" << endl;
+
+
+ {
+ int total = 0;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ total += foo( nsCString("This is a reasonable length string with some text in it and it is good.") );
+ }
+ }
+ cout << "nsCString(\"abc\")" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_concat()
+ {
+ cout << endl;
+
+ //---------|---------|---------|---------|---------|---------|---------|
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+ nsCString s3("This is yet a third string that I will use in the concatenation test.");
+
+ PRUint32 len = TotalLength( s1 + s2 + s3 + s1 + s2 + s3 );
+ if ( len != (71 + 65 + 69 + 71 + 65 + 69) )
+ {
+ cout << "|test_concat()| FAILED" << endl;
+ return kTestFailed;
+ }
+
+
+ {
+ nsCString anEmptyCString;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ len += TotalLength( anEmptyCString );
+ }
+ }
+ cout << "null loop time for concat" << endl;
+
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ len += TotalLength( s1 + s2 + s3 + s1 + s2 + s3 );
+ }
+ cout << "TotalLength( s1 + s2 + s3 + s1 + s2 + s3 )" << endl;
+
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ len += TotalLength( s1 + s2 );
+ }
+ cout << "TotalLength( s1 + s2 )" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_concat_and_assign()
+ {
+ //---------|---------|---------|---------|---------|---------|---------|
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+ nsCString s3("This is yet a third string that I will use in the concatenation test.");
+
+ nsCString s4( s1 + s2 + s3 + s1 + s2 + s3 );
+ if ( TotalLength(s4) != (71 + 65 + 69 + 71 + 65 + 69) )
+ {
+ cout << "|test_concat()| FAILED" << endl;
+ return kTestFailed;
+ }
+
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ s4 = s1 + s2 + s3 + s1 + s2 + s3;
+ }
+ cout << "s4 = s1 + s2 + s3 + s1 + s2 + s3" << endl;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ s4 = s1 + s2;
+ }
+ cout << "s4 = s1 + s2" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_compare()
+ {
+ nsCString s1("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis is a reasonable length string with some text in it and it is good.");
+ nsCString s2("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis is a reasonable length string with some text in it and it is bad.");
+
+ int count = 0;
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ if ( s1 > s2 )
+ ++count;
+ }
+ cout << "s1 > s2" << endl;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ if ( s1 == s1 )
+ ++count;
+ }
+ cout << "s1 == s1" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_countchar()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+
+ if ( s1.CountChar('e') != 5 )
+ {
+ cout << "|test_countchar()| FAILED: found a count of " << s1.CountChar('e') << endl;
+ return kTestFailed;
+ }
+
+ PRUint32 total = 0;
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ total += s1.CountChar('e');
+ }
+ cout << "s1.CountChar('e')" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_append_string()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s3;
+ s3.Append(s1);
+ s3.Append(s2);
+ len += TotalLength(s3);
+ }
+ }
+ cout << "s3.Append(s1); s3.Append(s2)" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_repeated_append_string()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s3;
+ for ( int j=0; j<100; ++j )
+ {
+ s3.Append(s1);
+ s3.Append(s2);
+ len += TotalLength(s3);
+ }
+ }
+ }
+ cout << "repeated s3.Append(s1); s3.Append(s2)" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_append_char()
+ {
+ cout << endl;
+
+ PRUint32 len = 0;
+
+ nsCString s1("hello");
+ PRUint32 oldLength = s1.Length();
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ s1.SetLength(oldLength);
+ }
+ }
+ cout << "null loop time for append char" << endl;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ s1.Append('e');
+ s1.SetLength(oldLength);
+ }
+ }
+ cout << "s1.Append('e')" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_repeated_append_char()
+ {
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s1;
+ for ( int j=0; j<1000; ++j )
+ {
+ s1.Append('e');
+ len += TotalLength(s1);
+ }
+ }
+ }
+ cout << "repeated s1.Append('e')" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_insert_string()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s2("This is another string that I will use in the concatenation test.");
+ s2.Insert(s1, 3);
+ len += TotalLength(s2);
+ }
+ }
+ cout << "s2.Insert(s1, 3)" << endl;
+
+ return kTestSucceeded;
+ }
+
+#ifndef TEST_STD_STRING
+static
+int
+test_find_string()
+ {
+ nsCString text("aaaaaaaaaab");
+ nsCString pattern("aab");
+
+ PRUint32 position = 0;
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ position = Find(text, pattern);
+ }
+ cout << "text.Find(pattern)" << endl;
+
+ return kTestSucceeded;
+ }
+#endif
+
+class Profiler
+ {
+ public:
+ Profiler()
+ {
+#if 0
+ ProfilerInit(collectDetailed, bestTimeBase, 100, 32);
+#endif
+ }
+
+ void
+ Dump( const char* output_name )
+ {
+ }
+
+ void
+ Dump( const unsigned char* output_name )
+ {
+#if 0
+ ProfilerDump(output_name);
+#endif
+ }
+
+ ~Profiler()
+ {
+#if 0
+ ProfilerDump(mOutputName);
+ ProfilerTerm();
+#endif
+ }
+ };
+
+int
+main()
+ {
+
+ cout << "String performance profiling. Compiled " __DATE__ " " __TIME__ << endl;
+#ifdef TEST_STD_STRING
+ cout << "Testing std::string." << endl;
+#else
+ cout << "Testing factored nsString." << endl;
+#endif
+
+ int tests_failed = 0;
+
+ Profiler profiler;
+
+ tests_failed += test_construction();
+ tests_failed += test_concat();
+ tests_failed += test_concat_and_assign();
+ tests_failed += test_compare();
+ tests_failed += test_countchar();
+ tests_failed += test_append_string();
+ tests_failed += test_repeated_append_string();
+ tests_failed += test_append_char();
+ tests_failed += test_repeated_append_char();
+ tests_failed += test_insert_string();
+#ifndef TEST_STD_STRING
+ tests_failed += test_find_string();
+#endif
+
+#ifdef TEST_STD_STRING
+ profiler.Dump("\pStandard String.prof");
+#else
+ profiler.Dump("\pFactored String.prof");
+#endif
+
+ if ( tests_failed )
+ cout << "One or more tests FAILED. Measurements may be invalid." << endl;
+
+ cout << "End of string performance profiling." << endl;
+ return 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp
new file mode 100644
index 00000000..b8365dac
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp
@@ -0,0 +1,651 @@
+#include <iostream.h>
+#include "nsStringIO.h"
+
+//#define TEST_STD_STRING
+
+
+#include "nsString.h"
+#include "nsFragmentedString.h"
+#include "nsReadableUtils.h"
+#include "nsSlidingString.h"
+
+#ifdef TEST_STD_STRING
+#include "nsStdStringWrapper.h"
+#else
+ typedef nsString nsStdString;
+ typedef nsCString nsStdCString;
+#endif
+
+template <class CharT>
+basic_nsLiteralString<CharT>
+literal_hello( CharT* )
+ {
+ }
+
+NS_SPECIALIZE_TEMPLATE
+basic_nsLiteralString<char>
+literal_hello( char* )
+ {
+ return basic_nsLiteralString<char>("Hello");
+ }
+
+NS_SPECIALIZE_TEMPLATE
+basic_nsLiteralString<PRUnichar>
+literal_hello( PRUnichar* )
+ {
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ return basic_nsLiteralString<PRUnichar>(L"Hello");
+#else
+ static PRUnichar constant_unicode[] = { 'H', 'e', 'l', 'l', 'o', PRUnichar() };
+ return basic_nsLiteralString<PRUnichar>(constant_unicode);
+#endif
+ }
+
+template <class T>
+struct string_class_traits
+ {
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct string_class_traits<PRUnichar>
+ {
+ typedef PRUnichar* pointer;
+ typedef nsString implementation_t;
+
+ static basic_nsLiteralString<PRUnichar> literal_hello() { return ::literal_hello(pointer()); }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct string_class_traits<char>
+ {
+ typedef char* pointer;
+ typedef nsCString implementation_t;
+
+ static basic_nsLiteralString<char> literal_hello() { return ::literal_hello(pointer()); }
+ };
+
+
+static
+void
+CallCMid( nsACString& aResult, const nsACString& aSource, PRUint32 aStartPos, PRUint32 aLengthToCopy )
+ {
+ aSource.Mid(aResult, aStartPos, aLengthToCopy);
+ }
+
+
+
+template <class CharT>
+int
+test_multifragment_iterators( const basic_nsAString<CharT>& aString )
+ /*
+ ...this tests a problem that was present in |nsPromiseConcatenation| where,
+ because it originally stored some iteration state in the object itself, rather than
+ in the fragment, the iterators could get confused if used out of sequence.
+
+ This test should be run on any multi-fragment implementation to verify that it
+ does not have the same bug. Make sure the first fragment is only one character long.
+ */
+ {
+ typedef typename basic_nsAString<CharT>::const_iterator ConstIterator;
+
+ int tests_failed = 0;
+
+ ConstIterator iter1 = aString.BeginReading();
+ ConstIterator iter2 = aString.BeginReading();
+ ++iter2; ++iter2;
+
+ ConstIterator iter3 = aString.EndReading();
+ --iter3;
+ ++iter1; ++iter1;
+ if ( iter1 != iter2 )
+ {
+ cout << "FAILED in |test_multifragment_iterators|" << endl;
+ ++tests_failed;
+ }
+
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_Vidur_functions( const basic_nsAString<CharT>& aString )
+ {
+ char* char_copy = ToNewCString(aString);
+ PRUnichar* PRUnichar_copy = ToNewUnicode(aString);
+
+ nsMemory::Free(PRUnichar_copy);
+ nsMemory::Free(char_copy);
+
+ return 0;
+ }
+
+template <class CharT>
+int
+test_readable_hello( const basic_nsAString<CharT>& aReadable )
+ {
+ int tests_failed = 0;
+
+ if ( aReadable.Length() != 5 )
+ {
+ cout << "FAILED |test_readable_hello|: |Length()| --> " << aReadable.Length() << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable.First() != CharT('H') )
+ {
+ cout << "FAILED |test_readable_hello|: |First()| --> '" << aReadable.First() << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable.Last() != CharT('o') )
+ {
+ cout << "FAILED |test_readable_hello|: |Last()| --> '" << aReadable.Last() << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable[3] != CharT('l') )
+ {
+ cout << "FAILED |test_readable_hello|: |operator[]| --> '" << aReadable[3] << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable.CountChar( CharT('l') ) != 2 )
+ {
+ cout << "FAILED |test_readable_hello|: |CountChar('l')| --> " << aReadable.CountChar(CharT('l')) << endl;
+ ++tests_failed;
+ }
+
+ basic_nsAString<CharT>::const_iterator iter = aReadable.BeginReading();
+ if ( *iter != CharT('H') )
+ {
+ cout << "FAILED |test_readable_hello|: didn't start out pointing to the right thing, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
+ ++tests_failed;
+ }
+
+ ++iter;
+
+ if ( *iter != CharT('e') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be incremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
+ ++tests_failed;
+ }
+
+ iter = aReadable.EndReading();
+ --iter;
+ if ( *iter != CharT('o') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()|, or else couldn't be decremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
+ ++tests_failed;
+ }
+
+ basic_nsAString<CharT>::const_iterator iter1 = aReadable.BeginReading().advance(3);
+ if ( *iter1 != CharT('l') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be set to |BeginReading()+=n|, or else couldn't be dereferenced. --> '" << *iter1 << "'" << endl;
+ ++tests_failed;
+ }
+
+ basic_nsAString<CharT>::const_iterator iter2 = aReadable.EndReading().advance(-2);
+ if ( *iter2 != CharT('l') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()-=n|, or else couldn't be dereferenced. --> '" << *iter2 << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( iter1 != iter2 )
+ {
+ cout << "FAILED |test_readable_hello|: iterator comparison with !=." << endl;
+ ++tests_failed;
+ }
+
+ if ( !(iter1 == iter2) )
+ {
+ cout << "FAILED |test_readable_hello|: iterator comparison with ==." << endl;
+ ++tests_failed;
+ }
+
+ typedef CharT* CharT_ptr;
+ if ( aReadable != literal_hello(CharT_ptr()) )
+ {
+ cout << "FAILED |test_readable_hello|: comparison with \"Hello\"" << endl;
+ ++tests_failed;
+ }
+
+ tests_failed += test_multifragment_iterators(aReadable);
+ // tests_failed += test_deprecated_GetBufferGetUnicode(aReadable);
+
+ test_Vidur_functions(aReadable);
+
+ return tests_failed;
+ }
+
+
+template <class CharT>
+int
+test_SetLength( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+
+ size_t oldLength = aWritable.Length();
+
+ if ( oldValue != Substring(aWritable, 0, oldLength) )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, saving the value didn't work." << endl;
+ ++tests_failed;
+ }
+
+ size_t newLength = 2*(oldLength+1);
+
+ aWritable.SetLength(newLength);
+ if ( aWritable.Length() != newLength )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, length is wrong." << endl;
+ ++tests_failed;
+ }
+
+ if ( oldValue != Substring(aWritable, 0, oldLength) )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, contents damaged after growing." << endl;
+ ++tests_failed;
+ }
+
+ aWritable.SetLength(oldLength);
+ if ( aWritable.Length() != oldLength )
+ {
+ cout << "FAILED shrinking a string in |test_SetLength|." << endl;
+ ++tests_failed;
+ }
+
+ if ( oldValue != Substring(aWritable, 0, oldLength) )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, contents damaged after shrinking." << endl;
+ ++tests_failed;
+ }
+
+ return tests_failed;
+ }
+
+
+template <class CharT>
+int
+test_insert( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ if ( oldValue != aWritable )
+ {
+ cout << "FAILED saving the old string value in |test_insert|." << endl;
+ ++tests_failed;
+ }
+
+ string_class_traits<CharT>::implementation_t insertable( string_class_traits<CharT>::literal_hello() );
+
+ insertable.SetLength(1);
+ aWritable.Insert(insertable, 0);
+
+ if ( aWritable != (insertable + oldValue) )
+ {
+ cout << "FAILED in |test_insert|." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+
+ return tests_failed;
+ }
+
+
+template <class CharT>
+int
+test_cut( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+
+ aWritable.Cut(0, aWritable.Length()+5);
+
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_assign( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable = aWritable;
+ if ( aWritable != oldValue )
+ {
+ cout << "FAILED self assignment." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_append( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable += aWritable;
+ if ( aWritable != oldValue + oldValue )
+ {
+ cout << "FAILED self append." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_insert( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable.Insert(aWritable, 0);
+ if ( aWritable != oldValue + oldValue )
+ {
+ cout << "FAILED self insert." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_replace( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable.Replace(0, 0, aWritable);
+ if ( aWritable != oldValue + oldValue )
+ {
+ cout << "FAILED self insert." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+
+
+template <class CharT>
+int
+test_writable( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ // ...
+
+
+ {
+ typedef CharT* CharT_ptr;
+ aWritable = literal_hello(CharT_ptr());
+
+ if ( aWritable != literal_hello(CharT_ptr()) )
+ {
+ cout << "FAILED assignment and/or comparison in |test_writable|." << endl;
+ ++tests_failed;
+ }
+
+ tests_failed += test_readable_hello(aWritable);
+ }
+
+ tests_failed += test_SetLength(aWritable);
+ tests_failed += test_insert(aWritable);
+ tests_failed += test_cut(aWritable);
+ tests_failed += test_self_assign(aWritable);
+ tests_failed += test_self_append(aWritable);
+ tests_failed += test_self_insert(aWritable);
+ tests_failed += test_self_replace(aWritable);
+
+ return tests_failed;
+ }
+
+
+
+typedef void* void_ptr;
+
+int
+main()
+ {
+ int tests_failed = 0;
+ cout << "String unit tests. Compiled " __DATE__ " " __TIME__ << endl;
+
+#if 0
+ {
+ nsFragmentedCString fs0;
+ fs0.Append("Hello");
+ tests_failed += test_readable_hello(fs0);
+ tests_failed += test_writable(fs0);
+ }
+#endif
+
+ {
+ NS_NAMED_LITERAL_STRING(literal, "Hello");
+ PRUnichar* buffer = ToNewUnicode(literal);
+
+ nsSlidingString ss0(buffer, buffer+5, buffer+6);
+// ss0.AppendBuffer(buffer, buffer+5, buffer+6);
+ nsReadingIterator<PRUnichar> ri0;
+ ss0.BeginReading(ri0);
+
+ tests_failed += test_readable_hello(ss0);
+
+ nsSlidingSubstring ss1(ss0);
+ tests_failed += test_readable_hello(ss1);
+
+ buffer = ToNewUnicode(literal);
+ ss0.AppendBuffer(buffer, buffer+5, buffer+6);
+
+ ri0.advance(5);
+ ss0.DiscardPrefix(ri0);
+
+ tests_failed += test_readable_hello(ss0);
+ tests_failed += test_readable_hello(ss1);
+
+ nsReadingIterator<PRUnichar> ri1;
+ ss0.EndReading(ri1);
+
+ nsSlidingSubstring ss2(ss0, ri0, ri1);
+ tests_failed += test_readable_hello(ss2);
+ }
+
+
+ {
+ nsLiteralCString s0("Patrick Beard made me write this: \"This is just a test\"\n");
+ print_string(s0);
+
+ const char* raw_string = "He also made me write this.\n";
+ nsFileCharSink<char> output(stdout);
+ copy_string(raw_string, raw_string+nsCharTraits<char>::length(raw_string), output);
+
+ nsLiteralCString s1("This ", 5), s2("is ", 3), s3("a ", 2), s4("test\n", 5);
+ print_string(s1+s2+s3+s4);
+
+ nsLiteralCString s5( "This is " "a " "test" );
+ print_string(s5+NS_LITERAL_CSTRING("\n"));
+
+ print_string(nsLiteralCString("The value of the string |x| is \"") + Substring(s0, 0, s0.Length()-1) + NS_LITERAL_CSTRING("\". Hope you liked it."));
+ }
+
+
+ {
+ tests_failed += test_readable_hello(NS_LITERAL_STRING("Hello"));
+
+ nsLiteralCString s1("Hello");
+ tests_failed += test_readable_hello(s1);
+ }
+
+ {
+
+ nsString s3( NS_LITERAL_STRING("Hello") );
+
+ tests_failed += test_readable_hello(s3);
+ tests_failed += test_writable(s3);
+
+ nsCString s4("Hello");
+ tests_failed += test_readable_hello(s4);
+ tests_failed += test_writable(s4);
+ }
+
+ {
+ nsStdString s5( NS_LITERAL_STRING("Hello") );
+
+ tests_failed += test_readable_hello(s5);
+ tests_failed += test_writable(s5);
+
+ nsStdCString s6("Hello");
+ tests_failed += test_readable_hello(s6);
+ tests_failed += test_writable(s6);
+ }
+
+ {
+ nsLiteralString s7(NS_LITERAL_STRING("He"));
+ nsString s8(NS_LITERAL_STRING("l"));
+ nsStdString s9(NS_LITERAL_STRING("lo"));
+
+ tests_failed += test_readable_hello(s7+s8+s9);
+
+ nsString s13( s7 + s8 + s9 );
+ tests_failed += test_readable_hello(s13);
+
+ nsStdString s14( s7 + s8 + s9 );
+ tests_failed += test_readable_hello(s14);
+
+ nsCString s10("He");
+ nsLiteralCString s11("l");
+ nsStdCString s12("lo");
+
+ tests_failed += test_readable_hello(s10+s11+s12);
+
+
+ }
+
+ {
+ const char *foo = "this is a really long string";
+ nsCString origString;
+ nsCString string2;
+ nsCString string3;
+
+ origString = foo;
+
+ string2 = Substring(origString, 0, 5);
+ string3 = Substring(origString, 6, origString.Length() - 6);
+ }
+
+ {
+ nsLiteralCString s13("He");
+ nsCAutoString s14("l");
+ nsLiteralCString s15("lo");
+
+ s14.Assign(s13 + s14 + s15);
+
+ if ( int failures = test_readable_hello(s14) )
+ {
+ tests_failed += failures;
+ cout << "FAILED to keep a promise." << endl;
+ }
+ }
+
+
+ {
+ nsLiteralCString str1("Hello");
+ nsStdCString str2("Hello");
+
+ nsLiteralCString str3("Hello there");
+
+ if ( str1 != str2 )
+ {
+ cout << "string comparison using != failed" << endl;
+ ++tests_failed;
+ }
+
+ if ( !(str3 > str2) )
+ {
+ cout << "string comparison using > failed" << endl;
+ ++tests_failed;
+ }
+
+ if ( !(str2 < str3) )
+ {
+ cout << "string comparison using < failed" << endl;
+ ++tests_failed;
+ }
+
+ if ( str1 != "Hello" )
+ {
+ cout << "string comparison using == failed" << endl;
+ ++tests_failed;
+ }
+ }
+
+#if 0
+ nsStdCString extracted_middle("XXXXXXXXXX");
+ CallCMid(extracted_middle, part1+part2a+part2b, 1, 3);
+
+ cout << "The result of mid was \"" << extracted_middle << "\"" << endl;
+
+ nsLiteralCString middle_answer("ell");
+ if ( middle_answer != extracted_middle )
+ {
+ cout << "mid FAILED on nsConcatString" << endl;
+ ++tests_failed;
+ }
+
+
+
+ //
+ // |nsStdStringWrapper|, i.e., |nsStdCString|
+ //
+
+ {
+ nsStdCString extracted_middle;
+ CallCMid(extracted_middle, part1+part2a+part2b, 1, 3);
+
+ cout << "The result of mid was \"" << extracted_middle << "\"" << endl;
+
+ nsLiteralCString middle_answer("ell");
+ if ( middle_answer != extracted_middle )
+ {
+ cout << "mid FAILED on nsStdCString" << endl;
+ ++tests_failed;
+ }
+ }
+
+
+
+ nsStdCString leftString;
+ source.Left(leftString, 9);
+ // cout << static_cast<const nsACString>(leftString) << endl;
+
+
+
+ tests_failed += test_multifragment_iterators(part1+part2a+part2b);
+#endif
+
+
+
+ cout << "End of string unit tests." << endl;
+ if ( !tests_failed )
+ cout << "OK, all tests passed." << endl;
+ else
+ cout << "FAILED one or more tests." << endl;
+
+ return tests_failed;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestArray.cpp b/src/libs/xpcom18a4/xpcom/tests/TestArray.cpp
new file mode 100644
index 00000000..852938fe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestArray.cpp
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "nsISupportsArray.h"
+
+// {9e70a320-be02-11d1-8031-006008159b5a}
+#define NS_IFOO_IID \
+ {0x9e70a320, 0xbe02, 0x11d1, \
+ {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}}
+
+static const PRBool kExitOnError = PR_TRUE;
+
+class IFoo : public nsISupports {
+public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
+
+ NS_IMETHOD_(nsrefcnt) RefCnt() = 0;
+ NS_IMETHOD_(PRInt32) ID() = 0;
+};
+
+class Foo : public IFoo {
+public:
+
+ Foo(PRInt32 aID);
+
+ // nsISupports implementation
+ NS_DECL_ISUPPORTS
+
+ // IFoo implementation
+ NS_IMETHOD_(nsrefcnt) RefCnt() { return mRefCnt; }
+ NS_IMETHOD_(PRInt32) ID() { return mID; }
+
+ static PRInt32 gCount;
+
+ PRInt32 mID;
+
+private:
+ ~Foo();
+};
+
+PRInt32 Foo::gCount;
+
+Foo::Foo(PRInt32 aID)
+{
+ mID = aID;
+ ++gCount;
+ fprintf(stdout, "init: %d (%p), %d total)\n", mID, this, gCount);
+}
+
+Foo::~Foo()
+{
+ --gCount;
+ fprintf(stdout, "destruct: %d (%p), %d remain)\n", mID, this, gCount);
+}
+
+NS_IMPL_ISUPPORTS1(Foo, IFoo)
+
+const char* AssertEqual(PRInt32 aValue1, PRInt32 aValue2)
+{
+ if (aValue1 == aValue2) {
+ return "OK";
+ }
+ if (kExitOnError) {
+ exit(1);
+ }
+ return "ERROR";
+}
+
+void DumpArray(nsISupportsArray* aArray, PRInt32 aExpectedCount, PRInt32 aElementIDs[], PRInt32 aExpectedTotal)
+{
+ PRUint32 cnt = 0;
+ nsresult rv = aArray->Count(&cnt);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
+ PRInt32 count = cnt;
+ PRInt32 index;
+
+ fprintf(stdout, "object count %d = %d %s\n", Foo::gCount, aExpectedTotal,
+ AssertEqual(Foo::gCount, aExpectedTotal));
+ fprintf(stdout, "array count %d = %d %s\n", count, aExpectedCount,
+ AssertEqual(count, aExpectedCount));
+
+ for (index = 0; (index < count) && (index < aExpectedCount); index++) {
+ IFoo* foo = (IFoo*)(aArray->ElementAt(index));
+ fprintf(stdout, "%2d: %d=%d (%p) c: %d %s\n",
+ index, aElementIDs[index], foo->ID(), foo, foo->RefCnt() - 1,
+ AssertEqual(foo->ID(), aElementIDs[index]));
+ foo->Release();
+ }
+}
+
+void FillArray(nsISupportsArray* aArray, PRInt32 aCount)
+{
+ PRInt32 index;
+ for (index = 0; index < aCount; index++) {
+ nsCOMPtr<IFoo> foo = new Foo(index);
+ aArray->AppendElement(foo);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ nsISupportsArray* array;
+ nsresult rv;
+
+ if (NS_OK == (rv = NS_NewISupportsArray(&array))) {
+ FillArray(array, 10);
+ fprintf(stdout, "Array created:\n");
+ PRInt32 fillResult[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ DumpArray(array, 10, fillResult, 10);
+
+ // test insert
+ IFoo* foo = (IFoo*)array->ElementAt(3);
+ foo->Release(); // pre-release to fix ref count for dumps
+ array->InsertElementAt(foo, 5);
+ fprintf(stdout, "insert 3 at 5:\n");
+ PRInt32 insertResult[11] = {0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9};
+ DumpArray(array, 11, insertResult, 10);
+ fprintf(stdout, "insert 3 at 0:\n");
+ array->InsertElementAt(foo, 0);
+ PRInt32 insertResult2[12] = {3, 0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9};
+ DumpArray(array, 12, insertResult2, 10);
+ fprintf(stdout, "append 3:\n");
+ array->AppendElement(foo);
+ PRInt32 appendResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9, 3};
+ DumpArray(array, 13, appendResult, 10);
+
+
+ // test IndexOf && LastIndexOf
+ PRInt32 expectedIndex[5] = {0, 4, 6, 12, -1};
+ PRInt32 count = 0;
+ PRInt32 index = array->IndexOf(foo);
+ fprintf(stdout, "IndexOf(foo): %d=%d %s\n", index, expectedIndex[count],
+ AssertEqual(index, expectedIndex[count]));
+ while (-1 != index) {
+ count++;
+ index = array->IndexOfStartingAt(foo, index + 1);
+ if (-1 != index)
+ fprintf(stdout, "IndexOf(foo): %d=%d %s\n", index, expectedIndex[count],
+ AssertEqual(index, expectedIndex[count]));
+ }
+ index = array->LastIndexOf(foo);
+ count--;
+ fprintf(stdout, "LastIndexOf(foo): %d=%d %s\n", index, expectedIndex[count],
+ AssertEqual(index, expectedIndex[count]));
+
+ // test ReplaceElementAt
+ fprintf(stdout, "ReplaceElementAt(8):\n");
+ array->ReplaceElementAt(foo, 8);
+ PRInt32 replaceResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
+ DumpArray(array, 13, replaceResult, 9);
+
+ // test RemoveElementAt, RemoveElement RemoveLastElement
+ fprintf(stdout, "RemoveElementAt(0):\n");
+ array->RemoveElementAt(0);
+ PRInt32 removeResult[12] = {0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
+ DumpArray(array, 12, removeResult, 9);
+ fprintf(stdout, "RemoveElementAt(7):\n");
+ array->RemoveElementAt(7);
+ PRInt32 removeResult2[11] = {0, 1, 2, 3, 4, 3, 5, 7, 8, 9, 3};
+ DumpArray(array, 11, removeResult2, 9);
+ fprintf(stdout, "RemoveElement(foo):\n");
+ array->RemoveElement(foo);
+ PRInt32 removeResult3[10] = {0, 1, 2, 4, 3, 5, 7, 8, 9, 3};
+ DumpArray(array, 10, removeResult3, 9);
+ fprintf(stdout, "RemoveLastElement(foo):\n");
+ array->RemoveLastElement(foo);
+ PRInt32 removeResult4[9] = {0, 1, 2, 4, 3, 5, 7, 8, 9};
+ DumpArray(array, 9, removeResult4, 9);
+
+ // test clear
+ fprintf(stdout, "clear array:\n");
+ array->Clear();
+ DumpArray(array, 0, 0, 0);
+ fprintf(stdout, "add 4 new:\n");
+ FillArray(array, 4);
+ DumpArray(array, 4, fillResult, 4);
+
+ // test compact
+ fprintf(stdout, "compact array:\n");
+ array->Compact();
+ DumpArray(array, 4, fillResult, 4);
+
+ // test delete
+ fprintf(stdout, "release array:\n");
+ NS_RELEASE(array);
+ }
+ else {
+ fprintf(stdout, "error can't create array: %x\n", rv);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp b/src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp
new file mode 100644
index 00000000..48b2f603
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsIAtom.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "prprf.h"
+#include "prtime.h"
+#include <stdio.h>
+
+extern "C" int _CrtSetDbgFlag(int);
+
+int main(int argc, char** argv)
+{
+ FILE* fp = fopen("words.txt", "r");
+ if (nsnull == fp) {
+ printf("can't open words.txt\n");
+ return -1;
+ }
+
+ PRInt32 count = 0;
+ PRUnichar** strings = new PRUnichar*[60000];
+ nsIAtom** ids = new nsIAtom*[60000];
+ nsAutoString s1, s2;
+ PRTime start = PR_Now();
+ PRInt32 i;
+ for (i = 0; i < 30000; i++) {
+ char buf[1000];
+ char* s = fgets(buf, sizeof(buf), fp);
+ if (nsnull == s) {
+ break;
+ }
+ nsCAutoString sb;
+ sb.Assign(buf);
+ strings[count++] = ToNewUnicode(sb);
+ ToUpperCase(sb);
+ strings[count++] = ToNewUnicode(sb);
+ }
+ PRTime end0 = PR_Now();
+
+ // Find and create idents
+ for (i = 0; i < count; i++) {
+ ids[i] = NS_NewAtom(strings[i]);
+ }
+ PRUnichar qqs[1]; qqs[0] = 0;
+ nsIAtom* qq = NS_NewAtom(qqs);
+ PRTime end1 = PR_Now();
+
+ // Now make sure we can find all the idents we just made
+ for (i = 0; i < count; i++) {
+ const char *utf8String;
+ ids[i]->GetUTF8String(&utf8String);
+ nsIAtom* id = NS_NewAtom(utf8String);
+ if (id != ids[i]) {
+ id->ToString(s1);
+ ids[i]->ToString(s2);
+ printf("find failed: id='%s' ids[%d]='%s'\n",
+ NS_LossyConvertUCS2toASCII(s1).get(), i, NS_LossyConvertUCS2toASCII(s2).get());
+ return -1;
+ }
+ NS_RELEASE(id);
+ }
+ PRTime end2 = PR_Now();
+
+ // Destroy all the atoms we just made
+ NS_RELEASE(qq);
+ for (i = 0; i < count; i++) {
+ NS_RELEASE(ids[i]);
+ }
+
+ // Print out timings
+ PRTime end3 = PR_Now();
+ PRTime creates, finds, lookups, dtor, ustoms;
+ LL_I2L(ustoms, 1000);
+ LL_SUB(creates, end0, start);
+ LL_DIV(creates, creates, ustoms);
+ LL_SUB(finds, end1, end0);
+ LL_DIV(finds, finds, ustoms);
+ LL_SUB(lookups, end2, end1);
+ LL_DIV(lookups, lookups, ustoms);
+ LL_SUB(dtor, end3, end2);
+ char buf[500];
+ PR_snprintf(buf, sizeof(buf), "making %d ident strings took %lldms",
+ count, creates);
+ puts(buf);
+ PR_snprintf(buf, sizeof(buf), "%d new idents took %lldms",
+ count, finds);
+ puts(buf);
+ PR_snprintf(buf, sizeof(buf), "%d ident lookups took %lldms",
+ count, lookups);
+ puts(buf);
+ PR_snprintf(buf, sizeof(buf), "dtor took %lldusec", dtor);
+ puts(buf);
+
+ printf("%d live atoms\n", NS_GetNumberOfAtoms());
+ NS_POSTCONDITION(0 == NS_GetNumberOfAtoms(), "dangling atoms");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp b/src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp
new file mode 100644
index 00000000..4537044f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+
+ Some tests for nsAutoLock.
+
+ */
+
+#include "nsAutoLock.h"
+#include "prthread.h"
+
+PRLock* gLock;
+int gCount;
+
+static void PR_CALLBACK run(void* arg)
+{
+ for (int i = 0; i < 1000000; ++i) {
+ nsAutoLock guard(gLock);
+ ++gCount;
+ PR_ASSERT(gCount == 1);
+ --gCount;
+ }
+}
+
+
+int main(int argc, char** argv)
+{
+ gLock = PR_NewLock();
+ gCount = 0;
+
+ // This shouldn't compile
+ //nsAutoLock* l1 = new nsAutoLock(theLock);
+ //delete l1;
+
+ // Create a block-scoped lock. This should compile.
+ {
+ nsAutoLock l2(gLock);
+ }
+
+ // Fork a thread to access the shared variable in a tight loop
+ PRThread* t1 =
+ PR_CreateThread(PR_SYSTEM_THREAD,
+ run,
+ nsnull,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ // ...and now do the same thing ourselves
+ run(nsnull);
+
+ // Wait for the background thread to finish, if necessary.
+ PR_JoinThread(t1);
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp b/src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp
new file mode 100644
index 00000000..c48134a4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp
@@ -0,0 +1,566 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// vim:cindent:ts=4:et:sw=4:
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is TestCOMPtrEq.cpp.
+ *
+ * The Initial Developer of the Original Code is
+ * L. David Baron.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAutoPtr.h"
+#include <stdio.h>
+#include "nscore.h"
+
+class TestObjectBaseA {
+ public:
+ // Virtual dtor for deleting through base class pointer
+ virtual ~TestObjectBaseA() { };
+ int fooA;
+};
+
+class TestObjectBaseB {
+ public:
+ // Virtual dtor for deleting through base class pointer
+ virtual ~TestObjectBaseB() { };
+ int fooB;
+};
+
+class TestObject : public TestObjectBaseA, public TestObjectBaseB {
+ public:
+ TestObject()
+ {
+ printf(" Creating TestObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+
+ // Virtual dtor for deleting through base class pointer
+ virtual ~TestObject()
+ {
+ printf(" Destroying TestObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+};
+
+class TestRefObjectBaseA {
+ public:
+ int fooA;
+ // Must return |nsrefcnt| to keep |nsDerivedSafe| happy.
+ virtual nsrefcnt AddRef() = 0;
+ virtual nsrefcnt Release() = 0;
+};
+
+class TestRefObjectBaseB {
+ public:
+ int fooB;
+ virtual nsrefcnt AddRef() = 0;
+ virtual nsrefcnt Release() = 0;
+};
+
+class TestRefObject : public TestRefObjectBaseA, public TestRefObjectBaseB {
+ public:
+ TestRefObject()
+ : mRefCount(0)
+ {
+ printf(" Creating TestRefObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+
+ ~TestRefObject()
+ {
+ printf(" Destroying TestRefObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+
+ nsrefcnt AddRef()
+ {
+ ++mRefCount;
+ printf(" AddRef to %d on TestRefObject %p.\n",
+ mRefCount, NS_STATIC_CAST(void*, this));
+ return mRefCount;
+ }
+
+ nsrefcnt Release()
+ {
+ --mRefCount;
+ printf(" Release to %d on TestRefObject %p.\n",
+ mRefCount, NS_STATIC_CAST(void*, this));
+ if (mRefCount == 0) {
+ delete NS_CONST_CAST(TestRefObject*, this);
+ return 0;
+ }
+ return mRefCount;
+ }
+
+ protected:
+ PRUint32 mRefCount;
+
+};
+
+static void CreateTestObject(TestObject **aResult)
+{
+ *aResult = new TestObject();
+}
+
+static void CreateTestRefObject(TestRefObject **aResult)
+{
+ (*aResult = new TestRefObject())->AddRef();
+}
+
+static void DoSomethingWithTestObject(TestObject *aIn)
+{
+ printf(" Doing something with |TestObject| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestObject(const TestObject *aIn)
+{
+ printf(" Doing something with |const TestObject| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+static void DoSomethingWithTestRefObject(TestRefObject *aIn)
+{
+ printf(" Doing something with |TestRefObject| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestRefObject(const TestRefObject *aIn)
+{
+ printf(" Doing something with |const TestRefObject| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+static void DoSomethingWithTestObjectBaseB(TestObjectBaseB *aIn)
+{
+ printf(" Doing something with |TestObjectBaseB| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestObjectBaseB(const TestObjectBaseB *aIn)
+{
+ printf(" Doing something with |const TestObjectBaseB| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+static void DoSomethingWithTestRefObjectBaseB(TestRefObjectBaseB *aIn)
+{
+ printf(" Doing something with |TestRefObjectBaseB| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestRefObjectBaseB(const TestRefObjectBaseB *aIn)
+{
+ printf(" Doing something with |const TestRefObjectBaseB| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+int main()
+{
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj( new TestObject() );
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj( new TestObject() );
+ printf("Should create one |TestObject| and then destroy one:\n");
+ pobj = new TestObject();
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj( new TestObject[3] );
+ printf("Should create 5 |TestObject|s and then destroy 3:\n");
+ pobj = new TestObject[5];
+ printf("Should destroy 5 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj( new TestRefObject() );
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj( new TestRefObject() );
+ printf("Should create and AddRef one |TestRefObject| and then Release and destroy one:\n");
+ pobj = new TestRefObject();
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ printf("Should AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> p2( p1 );
+ printf("Should Release twice and destroy one |TestRefObject|:\n");
+ }
+
+ printf("\nTesting equality (with all const-ness combinations):\n");
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+#if 0 /* MSVC++ 6.0 can't be coaxed to accept this */
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+#endif /* Things that MSVC++ 6.0 can't be coaxed to accept */
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ printf("\nTesting getter_Transfers and getter_AddRefs.\n");
+
+ {
+ nsAutoPtr<TestObject> ptr;
+ printf("Should create one |TestObject|:\n");
+ CreateTestObject(getter_Transfers(ptr));
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ nsRefPtr<TestRefObject> ptr;
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ CreateTestRefObject(getter_AddRefs(ptr));
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ printf("\nTesting casts and equality tests.\n");
+
+ if ((void*)(TestObject*)0x1000 ==
+ (void*)(TestObjectBaseB*)(TestObject*)0x1000)
+ printf("\n\nAll these tests are meaningless!\n\n\n");
+
+ {
+ nsAutoPtr<TestObject> p1(new TestObject());
+ TestObjectBaseB *p2 = p1;
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ TestObject *p1 = new TestObject();
+ nsAutoPtr<TestObjectBaseB> p2(p1);
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1 = new TestRefObject();
+ // nsCOMPtr requires a |get| for something like this as well
+ nsRefPtr<TestRefObjectBaseB> p2 = p1.get();
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1 = new TestRefObject();
+ TestRefObjectBaseB *p2 = p1;
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ TestRefObject *p1 = new TestRefObject();
+ nsRefPtr<TestRefObjectBaseB> p2 = p1;
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ printf("\nTesting |forget()|.\n");
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj( new TestObject() );
+ printf("Should do nothing:\n");
+ nsAutoPtr<TestObject> pobj2( pobj.forget() );
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj( new TestObject[3] );
+ printf("Should do nothing:\n");
+ nsAutoArrayPtr<TestObject> pobj2( pobj.forget() );
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ printf("\nTesting construction.\n");
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ printf("\nTesting calling of functions (including array access and casts).\n");
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObject(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObject(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObjectBaseB(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObjectBaseB(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ const nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ const nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ const nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObject(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObject(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ const nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ const nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ const nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObjectBaseB(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObjectBaseB(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp
new file mode 100644
index 00000000..c48219e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp
@@ -0,0 +1,651 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <assert.h>
+#include <stdio.h>
+#include "nsCOMPtr.h"
+#include "nsISupports.h"
+
+#ifdef HAVE_CPP_NEW_CASTS
+ #define STATIC_CAST(T,x) static_cast<T>(x)
+ #define REINTERPRET_CAST(T,x) reinterpret_cast<T>(x)
+#else
+ #define STATIC_CAST(T,x) ((T)(x))
+ #define REINTERPRET_CAST(T,x) ((T)(x))
+#endif
+
+
+#define NS_IFOO_IID \
+{ 0x6f7652e0, 0xee43, 0x11d1, \
+ { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
+
+class IFoo : public nsISupports
+ {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
+
+ public:
+ IFoo();
+ // virtual dtor because IBar uses our Release()
+ virtual ~IFoo();
+
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+ static void print_totals();
+
+ private:
+ unsigned int refcount_;
+
+ static unsigned int total_constructions_;
+ static unsigned int total_destructions_;
+ };
+
+class IBar;
+
+ // some types I'll need
+typedef unsigned long NS_RESULT;
+
+ // some functions I'll need (and define below)
+ nsresult CreateIFoo( void** );
+ nsresult CreateIBar( void** result );
+ void AnIFooPtrPtrContext( IFoo** );
+ void AnISupportsPtrPtrContext( nsISupports** );
+ void AVoidPtrPtrContext( void** );
+ void set_a_IFoo( nsCOMPtr<IFoo>* result );
+nsCOMPtr<IFoo> return_a_IFoo();
+
+
+
+
+unsigned int IFoo::total_constructions_;
+unsigned int IFoo::total_destructions_;
+
+class test_message
+ {
+ public:
+ test_message()
+ {
+ printf("BEGIN unit tests for |nsCOMPtr|, compiled " __DATE__ "\n");
+ }
+
+ ~test_message()
+ {
+ IFoo::print_totals();
+ printf("END unit tests for |nsCOMPtr|.\n");
+ }
+ };
+
+test_message gTestMessage;
+
+
+ /*
+ ...
+ */
+
+void
+IFoo::print_totals()
+ {
+ printf("total constructions/destructions --> %d/%d\n",
+ total_constructions_, total_destructions_);
+ }
+
+IFoo::IFoo()
+ : refcount_(0)
+ {
+ ++total_constructions_;
+ printf(" new IFoo@%p [#%d]\n",
+ STATIC_CAST(void*, this), total_constructions_);
+ }
+
+IFoo::~IFoo()
+ {
+ ++total_destructions_;
+ printf("IFoo@%p::~IFoo() [#%d]\n",
+ STATIC_CAST(void*, this), total_destructions_);
+ }
+
+nsrefcnt
+IFoo::AddRef()
+ {
+ ++refcount_;
+ printf("IFoo@%p::AddRef(), refcount --> %d\n",
+ STATIC_CAST(void*, this), refcount_);
+ return refcount_;
+ }
+
+nsrefcnt
+IFoo::Release()
+ {
+ int wrap_message = (refcount_ == 1);
+ if ( wrap_message )
+ printf(">>");
+
+ nsrefcnt const newcount = --refcount_;
+ printf("IFoo@%p::Release(), refcount --> %d\n",
+ STATIC_CAST(void*, this), newcount);
+
+ if ( !newcount )
+ {
+ printf(" delete IFoo@%p\n", STATIC_CAST(void*, this));
+ delete this;
+ }
+
+ if ( wrap_message )
+ printf("<<IFoo@%p::Release()\n", STATIC_CAST(void*, this));
+
+ return newcount;
+ }
+
+nsresult
+IFoo::QueryInterface( const nsIID& aIID, void** aResult )
+ {
+ printf("IFoo@%p::QueryInterface()\n", STATIC_CAST(void*, this));
+ nsISupports* rawPtr = 0;
+ nsresult status = NS_OK;
+
+ if ( aIID.Equals(GetIID()) )
+ rawPtr = this;
+ else
+ {
+ nsID iid_of_ISupports = NS_ISUPPORTS_IID;
+ if ( aIID.Equals(iid_of_ISupports) )
+ rawPtr = STATIC_CAST(nsISupports*, this);
+ else
+ status = NS_ERROR_NO_INTERFACE;
+ }
+
+ NS_IF_ADDREF(rawPtr);
+ *aResult = rawPtr;
+
+ return status;
+ }
+
+nsresult
+CreateIFoo( void** result )
+ // a typical factory function (that calls AddRef)
+ {
+ printf(">>CreateIFoo() --> ");
+ IFoo* foop = new IFoo;
+ printf("IFoo@%p\n", STATIC_CAST(void*, foop));
+
+ foop->AddRef();
+ *result = foop;
+
+ printf("<<CreateIFoo()\n");
+ return 0;
+ }
+
+void
+set_a_IFoo( nsCOMPtr<IFoo>* result )
+ {
+ printf(">>set_a_IFoo()\n");
+ assert(result);
+
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+ *result = foop;
+ printf("<<set_a_IFoo()\n");
+ }
+
+nsCOMPtr<IFoo>
+return_a_IFoo()
+ {
+ printf(">>return_a_IFoo()\n");
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+ printf("<<return_a_IFoo()\n");
+ return foop;
+ }
+
+
+
+
+#define NS_IBAR_IID \
+{ 0x6f7652e1, 0xee43, 0x11d1, \
+ { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
+
+class IBar : public IFoo
+ {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBAR_IID)
+
+ public:
+ IBar();
+ virtual ~IBar();
+
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+ };
+
+IBar::IBar()
+ {
+ printf(" new IBar@%p\n", STATIC_CAST(void*, this));
+ }
+
+IBar::~IBar()
+ {
+ printf("IBar@%p::~IBar()\n", STATIC_CAST(void*, this));
+ }
+
+nsresult
+IBar::QueryInterface( const nsID& aIID, void** aResult )
+ {
+ printf("IBar@%p::QueryInterface()\n", STATIC_CAST(void*, this));
+ nsISupports* rawPtr = 0;
+ nsresult status = NS_OK;
+
+ if ( aIID.Equals(GetIID()) )
+ rawPtr = this;
+ else if ( aIID.Equals(NS_GET_IID(IFoo)) )
+ rawPtr = STATIC_CAST(IFoo*, this);
+ else
+ {
+ nsID iid_of_ISupports = NS_ISUPPORTS_IID;
+ if ( aIID.Equals(iid_of_ISupports) )
+ rawPtr = STATIC_CAST(nsISupports*, this);
+ else
+ status = NS_ERROR_NO_INTERFACE;
+ }
+
+ NS_IF_ADDREF(rawPtr);
+ *aResult = rawPtr;
+
+ return status;
+ }
+
+
+
+nsresult
+CreateIBar( void** result )
+ // a typical factory function (that calls AddRef)
+ {
+ printf(">>CreateIBar() --> ");
+ IBar* barp = new IBar;
+ printf("IBar@%p\n", STATIC_CAST(void*, barp));
+
+ barp->AddRef();
+ *result = barp;
+
+ printf("<<CreateIBar()\n");
+ return 0;
+ }
+
+void
+AnIFooPtrPtrContext( IFoo** )
+ {
+ }
+
+void
+AVoidPtrPtrContext( void** )
+ {
+ }
+
+void
+AnISupportsPtrPtrContext( nsISupports** )
+ {
+ }
+
+
+// Optimism
+#define TEST_EXCEPTIONS 1
+
+// HAVE_CPP_EXCEPTIONS is defined automagically on unix
+#if defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2)
+#if !defined(HAVE_CPP_EXCEPTIONS)
+#undef TEST_EXCEPTIONS
+#endif
+#endif
+
+#ifdef TEST_EXCEPTIONS
+static
+nsresult
+TestBloat_Raw()
+ {
+ IBar* barP = 0;
+ nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
+
+ if ( barP )
+ {
+ try
+ {
+ IFoo* fooP = 0;
+ if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), REINTERPRET_CAST(void**, &fooP)) ) )
+ {
+ try
+ {
+ fooP->print_totals();
+ }
+ catch( ... )
+ {
+ NS_RELEASE(fooP);
+ throw;
+ }
+
+ NS_RELEASE(fooP);
+ }
+ }
+ catch( ... )
+ {
+ NS_RELEASE(barP);
+ throw;
+ }
+
+ NS_RELEASE(barP);
+ }
+
+ return result;
+ }
+#endif // TEST_EXCEPTIONS
+
+static
+nsresult
+TestBloat_Raw_Unsafe()
+ {
+ IBar* barP = 0;
+ nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
+
+ if ( barP )
+ {
+ IFoo* fooP = 0;
+ if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), REINTERPRET_CAST(void**, &fooP)) ) )
+ {
+ fooP->print_totals();
+ NS_RELEASE(fooP);
+ }
+
+ NS_RELEASE(barP);
+ }
+
+ return result;
+ }
+
+
+static
+nsresult
+TestBloat_Smart()
+ {
+ nsCOMPtr<IBar> barP;
+ nsresult result = CreateIBar( getter_AddRefs(barP) );
+
+ nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &result) );
+
+ if ( fooP )
+ fooP->print_totals();
+
+ return result;
+ }
+
+
+
+
+nsCOMPtr<IFoo> gFoop;
+
+int
+main()
+ {
+ printf(">>main()\n");
+
+ printf("sizeof(nsCOMPtr<IFoo>) --> %zd\n", sizeof(nsCOMPtr<IFoo>));
+
+#ifdef TEST_EXCEPTIONS
+ TestBloat_Raw();
+#endif // TEST_EXCEPTIONS
+ TestBloat_Raw_Unsafe();
+ TestBloat_Smart();
+
+
+ {
+ printf("\n### Test 1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?\n");
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+
+ printf("\n### Test 2: will a |nsCOMPtr| |Release| its old pointer when a new one is assigned in?\n");
+ foop = do_QueryInterface(new IFoo);
+
+ // [Shouldn't compile] Is it a compile time error to try to |AddRef| by hand?
+ //foop->AddRef();
+
+ // [Shouldn't compile] Is it a compile time error to try to |Release| be hand?
+ //foop->Release();
+
+ // [Shouldn't compile] Is it a compile time error to try to |delete| an |nsCOMPtr|?
+ //delete foop;
+
+ printf("\n### Test 3: can you |AddRef| if you must?\n");
+ STATIC_CAST(IFoo*, foop)->AddRef();
+
+ printf("\n### Test 4: can you |Release| if you must?\n");
+ STATIC_CAST(IFoo*, foop)->Release();
+
+ printf("\n### Test 5: will a |nsCOMPtr| |Release| when it goes out of scope?\n");
+ }
+
+ {
+ printf("\n### Test 6: will a |nsCOMPtr| call the correct destructor?\n");
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IBar) );
+ }
+
+ {
+ printf("\n### Test 7: can you compare one |nsCOMPtr| with another [!=]?\n");
+
+ nsCOMPtr<IFoo> foo1p( do_QueryInterface(new IFoo) );
+
+ // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
+ //AnIFooPtrPtrContext(&foo1p);
+
+ // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
+ //AVoidPtrPtrContext(&foo1p);
+
+ nsCOMPtr<IFoo> foo2p( do_QueryInterface(new IFoo) );
+
+ if ( foo1p != foo2p )
+ printf("foo1p != foo2p\n");
+ else
+ printf("foo1p == foo2p\n");
+
+ printf("\n### Test 7.5: can you compare a |nsCOMPtr| with NULL, 0, nsnull [!=]?\n");
+ if ( foo1p != 0 )
+ printf("foo1p != 0\n");
+ if ( 0 != foo1p )
+ printf("0 != foo1p\n");
+ if ( foo1p == 0 )
+ printf("foo1p == 0\n");
+ if ( 0 == foo1p )
+ printf("0 == foo1p\n");
+
+
+ IFoo* raw_foo2p = foo2p.get();
+
+ printf("\n### Test 8: can you compare a |nsCOMPtr| with a raw interface pointer [!=]?\n");
+ if ( foo1p.get() != raw_foo2p )
+ printf("foo1p != raw_foo2p\n");
+ else
+ printf("foo1p == raw_foo2p\n");
+
+
+ printf("\n### Test 9: can you assign one |nsCOMPtr| into another?\n");
+ foo1p = foo2p;
+
+ printf("\n### Test 10: can you compare one |nsCOMPtr| with another [==]?\n");
+ if ( foo1p == foo2p )
+ printf("foo1p == foo2p\n");
+ else
+ printf("foo1p != foo2p\n");
+
+ printf("\n### Test 11: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
+ if ( raw_foo2p == foo2p.get() )
+ printf("raw_foo2p == foo2p\n");
+ else
+ printf("raw_foo2p != foo2p\n");
+
+#if 1
+ printf("\n### Test 11.5: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
+ if ( nsCOMPtr<IFoo>( raw_foo2p ) == foo2p )
+ printf("raw_foo2p == foo2p\n");
+ else
+ printf("raw_foo2p != foo2p\n");
+#endif
+
+ printf("\n### Test 12: bare pointer test?\n");
+ if ( foo1p )
+ printf("foo1p is not NULL\n");
+ else
+ printf("foo1p is NULL\n");
+
+ printf("\n### Test 13: numeric pointer test?\n");
+ if ( foo1p == 0 )
+ printf("foo1p is NULL\n");
+ else
+ printf("foo1p is not NULL\n");
+
+#if 0
+ if ( foo1p == 1 )
+ printf("foo1p allowed compare with in\n");
+#endif
+
+ printf("\n### Test 14: how about when two |nsCOMPtr|s referring to the same object go out of scope?\n");
+ }
+
+ {
+ printf("\n### Test 15,16 ...setup...\n");
+ IFoo* raw_foo1p = new IFoo;
+ raw_foo1p->AddRef();
+
+ IFoo* raw_foo2p = new IFoo;
+ raw_foo2p->AddRef();
+
+ printf("\n### Test 15: what if I don't want to |AddRef| when I construct?\n");
+ nsCOMPtr<IFoo> foo1p( dont_AddRef(raw_foo1p) );
+ //nsCOMPtr<IFoo> foo1p = dont_AddRef(raw_foo1p);
+
+ printf("\n### Test 16: what if I don't want to |AddRef| when I assign in?\n");
+ nsCOMPtr<IFoo> foo2p;
+ foo2p = dont_AddRef(raw_foo2p);
+ }
+
+
+
+
+
+
+
+ {
+ printf("\n### setup for Test 17\n");
+ nsCOMPtr<IFoo> foop;
+ printf("### Test 17: basic parameter behavior?\n");
+ CreateIFoo( nsGetterAddRefs<IFoo>(foop) );
+ }
+ printf("### End Test 17\n");
+
+
+ {
+ printf("\n### setup for Test 18\n");
+ nsCOMPtr<IFoo> foop;
+ printf("### Test 18: basic parameter behavior, using the short form?\n");
+ CreateIFoo( getter_AddRefs(foop) );
+ }
+ printf("### End Test 18\n");
+
+
+ {
+ printf("\n### setup for Test 19, 20\n");
+ nsCOMPtr<IFoo> foop;
+ printf("### Test 19: reference parameter behavior?\n");
+ set_a_IFoo(address_of(foop));
+
+ printf("### Test 20: return value behavior?\n");
+ foop = return_a_IFoo();
+ }
+ printf("### End Test 19, 20\n");
+
+ {
+ printf("\n### setup for Test 21\n");
+ nsCOMPtr<IFoo> fooP;
+
+ printf("### Test 21: is |QueryInterface| called on assigning in a raw pointer?\n");
+ fooP = do_QueryInterface(new IFoo);
+ }
+ printf("### End Test 21\n");
+
+ {
+ printf("\n### setup for Test 22\n");
+ nsCOMPtr<IFoo> fooP;
+ fooP = do_QueryInterface(new IFoo);
+
+ nsCOMPtr<IFoo> foo2P;
+
+ printf("### Test 22: is |QueryInterface| _not_ called when assigning in a smart-pointer of the same type?\n");
+ foo2P = fooP;
+ }
+ printf("### End Test 22\n");
+
+ {
+ printf("\n### setup for Test 23\n");
+ nsCOMPtr<IBar> barP( do_QueryInterface(new IBar) );
+
+ printf("### Test 23: is |QueryInterface| called when assigning in a smart-pointer of a different type?\n");
+
+ nsCOMPtr<IFoo> fooP( do_QueryInterface(barP) );
+ if ( fooP )
+ printf("an IBar* is an IFoo*\n");
+ }
+ printf("### End Test 23\n");
+
+
+ {
+ nsCOMPtr<IFoo> fooP;
+
+ AnIFooPtrPtrContext( getter_AddRefs(fooP) );
+ AVoidPtrPtrContext( getter_AddRefs(fooP) );
+ AnISupportsPtrPtrContext( getter_AddRefs(fooP) );
+ }
+
+
+ {
+ nsCOMPtr<nsISupports> supportsP;
+
+ AVoidPtrPtrContext( getter_AddRefs(supportsP) );
+ AnISupportsPtrPtrContext( getter_AddRefs(supportsP) );
+ }
+
+
+ printf("\n### Test 24: will a static |nsCOMPtr| |Release| before program termination?\n");
+ gFoop = do_QueryInterface(new IFoo);
+
+ printf("<<main()\n");
+ return 0;
+ }
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp
new file mode 100644
index 00000000..916a0775
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is TestCOMPtrEq.cpp.
+ *
+ * The Initial Developer of the Original Code is
+ * L. David Baron.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+ /**
+ * This attempts to test all the possible variations of |operator==|
+ * used with |nsCOMPtr|s. Currently only the tests where pointers
+ * are to the same class are enabled. It's not clear whether we
+ * should be supporting other tests, and some of them won't work
+ * on at least some platforms. If we add separate comparisons
+ * for nsCOMPtr<nsISupports> we'll need to add more tests for
+ * those cases.
+ */
+
+#include "nsCOMPtr.h"
+
+ // Don't test these now, since some of them won't work and it's
+ // not clear whether they should (see above).
+#undef NSCAP_EQTEST_TEST_ACROSS_TYPES
+
+#define NS_ICOMPTREQTESTFOO_IID \
+ {0x8eb5bbef, 0xd1a3, 0x4659, \
+ {0x9c, 0xf6, 0xfd, 0xf3, 0xe4, 0xd2, 0x00, 0x0e}}
+
+class nsICOMPtrEqTestFoo : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICOMPTREQTESTFOO_IID)
+};
+
+#ifdef NSCAP_EQTEST_TEST_ACROSS_TYPES
+
+#define NS_ICOMPTREQTESTFOO2_IID \
+ {0x6516387b, 0x36c5, 0x4036, \
+ {0x82, 0xc9, 0xa7, 0x4d, 0xd9, 0xe5, 0x92, 0x2f}}
+
+class nsICOMPtrEqTestFoo2 : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICOMPTREQTESTFOO2_IID)
+};
+
+#endif
+
+int
+main()
+ {
+ nsCOMPtr<nsICOMPtrEqTestFoo> s;
+ nsICOMPtrEqTestFoo* r = 0;
+ const nsCOMPtr<nsICOMPtrEqTestFoo> sc;
+ const nsICOMPtrEqTestFoo* rc = 0;
+ nsICOMPtrEqTestFoo* const rk = 0;
+ const nsICOMPtrEqTestFoo* const rkc = 0;
+ nsDerivedSafe<nsICOMPtrEqTestFoo>* d = s.get();
+
+#ifdef NSCAP_EQTEST_TEST_ACROSS_TYPES
+ nsCOMPtr<nsICOMPtrEqTestFoo2> s2;
+ nsICOMPtrEqTestFoo2* r2 = 0;
+ const nsCOMPtr<nsICOMPtrEqTestFoo2> sc2;
+ const nsICOMPtrEqTestFoo2* rc2 = 0;
+ nsICOMPtrEqTestFoo2* const rk2 = 0;
+ const nsICOMPtrEqTestFoo2* const rkc2 = 0;
+ nsDerivedSafe<nsICOMPtrEqTestFoo2>* d2 = s2.get();
+#endif
+
+ return (!(PR_TRUE &&
+ (s == s) &&
+ (s == r) &&
+ (s == sc) &&
+ (s == rc) &&
+ (s == rk) &&
+ (s == rkc) &&
+ (s == d) &&
+ (r == s) &&
+ (r == r) &&
+ (r == sc) &&
+ (r == rc) &&
+ (r == rk) &&
+ (r == rkc) &&
+ (r == d) &&
+ (sc == s) &&
+ (sc == r) &&
+ (sc == sc) &&
+ (sc == rc) &&
+ (sc == rk) &&
+ (sc == rkc) &&
+ (sc == d) &&
+ (rc == s) &&
+ (rc == r) &&
+ (rc == sc) &&
+ (rc == rc) &&
+ (rc == rk) &&
+ (rc == rkc) &&
+ (rc == d) &&
+ (rk == s) &&
+ (rk == r) &&
+ (rk == sc) &&
+ (rk == rc) &&
+ (rk == rk) &&
+ (rk == rkc) &&
+ (rk == d) &&
+ (rkc == s) &&
+ (rkc == r) &&
+ (rkc == sc) &&
+ (rkc == rc) &&
+ (rkc == rk) &&
+ (rkc == rkc) &&
+ (rkc == d) &&
+ (d == s) &&
+ (d == r) &&
+ (d == sc) &&
+ (d == rc) &&
+ (d == rk) &&
+ (d == rkc) &&
+ (d == d) &&
+#ifdef NSCAP_EQTEST_TEST_ACROSS_TYPES
+ (s == s2) &&
+ (s == r2) &&
+ (s == sc2) &&
+ (s == rc2) &&
+ (s == rk2) &&
+ (s == rkc2) &&
+ (s == d2) &&
+ (r == s2) &&
+ (r == r2) &&
+ (r == sc2) &&
+ (r == rc2) &&
+ (r == rk2) &&
+ (r == rkc2) &&
+ (r == d2) &&
+ (sc == s2) &&
+ (sc == r2) &&
+ (sc == sc2) &&
+ (sc == rc2) &&
+ (sc == rk2) &&
+ (sc == rkc2) &&
+ (sc == d2) &&
+ (rc == s2) &&
+ (rc == r2) &&
+ (rc == sc2) &&
+ (rc == rc2) &&
+ (rc == rk2) &&
+ (rc == rkc2) &&
+ (rc == d2) &&
+ (rk == s2) &&
+ (rk == r2) &&
+ (rk == sc2) &&
+ (rk == rc2) &&
+ (rk == rk2) &&
+ (rk == rkc2) &&
+ (rk == d2) &&
+ (rkc == s2) &&
+ (rkc == r2) &&
+ (rkc == sc2) &&
+ (rkc == rc2) &&
+ (rkc == rk2) &&
+ (rkc == rkc2) &&
+ (rkc == d2) &&
+ (d == s2) &&
+ (d == r2) &&
+ (d == sc2) &&
+ (d == rc2) &&
+ (d == rk2) &&
+ (d == rkc2) &&
+ (d == d2) &&
+#endif
+ PR_TRUE));
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp
new file mode 100644
index 00000000..11bdd512
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCRT.h"
+#include "nsString.h"
+#include "plstr.h"
+#include <stdlib.h>
+
+// The return from strcmp etc is only defined to be postive, zero or
+// negative. The magnitude of a non-zero return is irrelevant.
+PRIntn sign(PRIntn val) {
+ if (val == 0)
+ return 0;
+ else {
+ if (val > 0)
+ return 1;
+ else
+ return -1;
+ }
+}
+
+
+// Verify that nsCRT versions of string comparison routines get the
+// same answers as the native non-unicode versions. We only pass in
+// iso-latin-1 strings, so the comparison must be valid.
+static void Check(const char* s1, const char* s2, PRIntn n)
+{
+ PRIntn clib = PL_strcmp(s1, s2);
+ PRIntn clib_n = PL_strncmp(s1, s2, n);
+ PRIntn clib_case = PL_strcasecmp(s1, s2);
+ PRIntn clib_case_n = PL_strncasecmp(s1, s2, n);
+
+ nsAutoString t1,t2;
+ t1.AssignWithConversion(s1);
+ t2.AssignWithConversion(s2);
+ const PRUnichar* us1 = t1.get();
+ const PRUnichar* us2 = t2.get();
+
+ PRIntn u2 = nsCRT::strcmp(us1, us2);
+ PRIntn u2_n = nsCRT::strncmp(us1, us2, n);
+
+ NS_ASSERTION(sign(clib) == sign(u2), "strcmp");
+ NS_ASSERTION(sign(clib_n) == sign(u2_n), "strncmp");
+}
+
+struct Test {
+ const char* s1;
+ const char* s2;
+ PRIntn n;
+};
+
+static Test tests[] = {
+ { "foo", "foo", 3 },
+ { "foo", "fo", 3 },
+
+ { "foo", "bar", 3 },
+ { "foo", "ba", 3 },
+
+ { "foo", "zap", 3 },
+ { "foo", "za", 3 },
+
+ { "bar", "foo", 3 },
+ { "bar", "fo", 3 },
+
+ { "bar", "foo", 3 },
+ { "bar", "fo", 3 },
+};
+#define NUM_TESTS int((sizeof(tests) / sizeof(tests[0])))
+
+int main()
+{
+ Test* tp = tests;
+ for (int i = 0; i < NUM_TESTS; i++, tp++) {
+ Check(tp->s1, tp->s2, tp->n);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp
new file mode 100644
index 00000000..3ec9c29a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim:cindent:ts=8:et:sw=4:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This test is NOT intended to be run. It's a test to make sure
+ * a group of functions BUILD correctly.
+ */
+
+#include "nsISupportsUtils.h"
+#include "nsIWeakReference.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsWeakReference.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+
+#define NS_ITESTSERVICE_IID \
+ {0x127b5253, 0x37b1, 0x43c7, \
+ { 0x96, 0x2b, 0xab, 0xf1, 0x2d, 0x22, 0x56, 0xae }}
+
+class NS_NO_VTABLE nsITestService : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITESTSERVICE_IID)
+};
+
+class nsTestService : public nsITestService, public nsSupportsWeakReference
+{
+ public:
+ NS_DECL_ISUPPORTS
+};
+
+NS_IMPL_ISUPPORTS2(nsTestService, nsITestService, nsISupportsWeakReference)
+
+#define NS_TEST_SERVICE_CONTRACTID "@mozilla.org/test/testservice;1"
+#define NS_TEST_SERVICE_CID \
+ {0xa00c1406, 0x283a, 0x45c9, \
+ {0xae, 0xd2, 0x1a, 0xb6, 0xdd, 0xba, 0xfe, 0x53}}
+static NS_DEFINE_CID(kTestServiceCID, NS_TEST_SERVICE_CID);
+
+int main()
+{
+ /*
+ * NOTE: This does NOT demonstrate how these functions are
+ * intended to be used. They are intended for filling in out
+ * parameters that need to be |AddRef|ed. I'm just too lazy
+ * to write lots of little getter functions for a test program
+ * when I don't need to.
+ */
+
+ NS_NOTREACHED("This test is not intended to run, only to compile!");
+
+ /* Test CallQueryInterface */
+
+ nsISupports *mySupportsPtr = NS_REINTERPRET_CAST(nsISupports*, 0x1000);
+
+ nsITestService *myITestService = nsnull;
+ CallQueryInterface(mySupportsPtr, &myITestService);
+
+ nsTestService *myTestService =
+ NS_REINTERPRET_CAST(nsTestService*, mySupportsPtr);
+ nsISupportsWeakReference *mySupportsWeakRef;
+ CallQueryInterface(myTestService, &mySupportsWeakRef);
+
+ /* Test CallQueryReferent */
+
+ nsIWeakReference *myWeakRef =
+ NS_STATIC_CAST(nsIWeakReference*, mySupportsPtr);
+ CallQueryReferent(myWeakRef, &myITestService);
+
+ /* Test CallCreateInstance */
+
+ CallCreateInstance(kTestServiceCID, mySupportsPtr, &myITestService);
+ CallCreateInstance(kTestServiceCID, &myITestService);
+ CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, mySupportsPtr,
+ &myITestService);
+ CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, &myITestService);
+
+ /* Test CallGetService */
+ nsIShutdownListener *myShutdownListener = nsnull;
+ CallGetService(kTestServiceCID, &myITestService);
+ CallGetService(kTestServiceCID, myShutdownListener, &myITestService);
+ CallGetService(NS_TEST_SERVICE_CONTRACTID, &myITestService);
+ CallGetService(NS_TEST_SERVICE_CONTRACTID, myShutdownListener,
+ &myITestService);
+
+ /* Test CallGetInterface */
+ nsIInterfaceRequestor *myInterfaceRequestor =
+ NS_STATIC_CAST(nsIInterfaceRequestor*, mySupportsPtr);
+ CallGetInterface(myInterfaceRequestor, &myITestService);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp b/src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp
new file mode 100644
index 00000000..4b00c7fb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDeque.h"
+#include "nsCRT.h"
+#include <stdio.h>
+
+/**************************************************************
+ Now define the token deallocator class...
+ **************************************************************/
+class _TestDeque {
+public:
+ _TestDeque() {
+ SelfTest();
+ }
+ int SelfTest();
+ nsresult OriginalTest();
+ nsresult OriginalFlaw();
+ nsresult AssignFlaw();
+};
+static _TestDeque sTestDeque;
+
+class _Dealloc: public nsDequeFunctor {
+ virtual void* operator()(void* aObject) {
+ return 0;
+ }
+};
+
+/**
+ * conduct automated self test for this class
+ *
+ * @param
+ * @return
+ */
+int _TestDeque::SelfTest() {
+ /* the old deque should have failed a bunch of these tests */
+ int results=0;
+ results+=OriginalTest();
+ results+=OriginalFlaw();
+ results+=AssignFlaw();
+ return results;
+}
+
+nsresult _TestDeque::OriginalTest() {
+ int ints[200];
+ int count=sizeof(ints)/sizeof(int);
+ int i=0;
+ int* temp;
+ nsDeque theDeque(new _Dealloc); //construct a simple one...
+
+ for (i=0;i<count;i++) { //initialize'em
+ ints[i]=10*(1+i);
+ }
+ for (i=0;i<70;i++) {
+ theDeque.Push(&ints[i]);
+ }
+ for (i=0;i<56;i++) {
+ temp=(int*)theDeque.Pop();
+ }
+ for (i=0;i<55;i++) {
+ theDeque.Push(&ints[i]);
+ }
+ for (i=0;i<35;i++) {
+ temp=(int*)theDeque.Pop();
+ }
+ for (i=0;i<35;i++) {
+ theDeque.Push(&ints[i]);
+ }
+ for (i=0;i<38;i++) {
+ temp=(int*)theDeque.Pop();
+ }
+ return NS_OK;
+}
+
+nsresult _TestDeque::OriginalFlaw() {
+ int ints[200];
+ int i=0;
+ int* temp;
+ nsDeque secondDeque(new _Dealloc);
+ /**
+ * Test 1. Origin near end, semi full, call Peek().
+ * you start, mCapacity is 8
+ */
+ printf("fill array\n");
+ for (i=32; i; --i)
+ ints[i]=i*3+10;
+ printf("push 6 times\n");
+ for (i=0; i<6; i++)
+ secondDeque.Push(&ints[i]);
+ printf("popfront 4 times:\n");
+ for (i=4; i; --i) {
+ temp=(int*)secondDeque.PopFront();
+ printf("%d\t",*temp);
+ }
+ printf("push 4 times\n");
+ for (int j=4; j; --j)
+ secondDeque.Push(&ints[++i]);
+ printf("origin should now be about 4\n");
+ printf("and size should be 6\n");
+ printf("origin+size>capacity\n");
+
+ /*<akk> Oh, I see ... it's a circular buffer */
+ printf("but the old code wasn't behaving accordingly.\n");
+
+ /*right*/
+ printf("we shouldn't crash or anything interesting, ");
+
+ temp=(int*)secondDeque.Peek();
+ printf("peek: %d\n",*temp);
+ return NS_OK;
+}
+
+nsresult _TestDeque::AssignFlaw() {
+ nsDeque src(new _Dealloc),dest(new _Dealloc);
+ return NS_OK;
+}
+
+int main (void) {
+ _TestDeque test;
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp b/src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp
new file mode 100644
index 00000000..f0d5f777
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include "TestFactory.h"
+#include "nsISupports.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+
+NS_DEFINE_CID(kTestFactoryCID, NS_TESTFACTORY_CID);
+NS_DEFINE_CID(kTestLoadedFactoryCID, NS_TESTLOADEDFACTORY_CID);
+
+
+/**
+ * ITestClass implementation
+ */
+
+class TestClassImpl: public ITestClass {
+ NS_DECL_ISUPPORTS
+public:
+ TestClassImpl() {
+ }
+
+ void Test();
+};
+
+NS_IMPL_ISUPPORTS1(TestClassImpl, ITestClass)
+
+void TestClassImpl::Test() {
+ printf("hello, world!\n");
+}
+
+/**
+ * TestFactory implementation
+ */
+
+class TestFactory: public nsIFactory {
+ NS_DECL_ISUPPORTS
+
+public:
+ TestFactory() {
+ }
+
+ NS_IMETHOD CreateInstance(nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ NS_IMETHOD LockFactory(PRBool aLock) { return NS_OK; }
+};
+
+NS_IMPL_ISUPPORTS1(TestFactory, nsIFactory)
+
+nsresult TestFactory::CreateInstance(nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult) {
+ if (aDelegate != NULL) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ TestClassImpl *t = new TestClassImpl();
+
+ if (t == NULL) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult res = t->QueryInterface(aIID, aResult);
+
+ if (NS_FAILED(res)) {
+ *aResult = NULL;
+ delete t;
+ }
+
+ return res;
+}
+
+
+int main(int argc, char **argv) {
+ nsresult rv;
+
+ {
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->RegisterFactory(kTestFactoryCID,
+ nsnull,
+ nsnull,
+ new TestFactory());
+
+ ITestClass *t = NULL;
+ nsComponentManager::CreateInstance(kTestFactoryCID,
+ NULL,
+ NS_GET_IID(ITestClass),
+ (void **) &t);
+
+ if (t != NULL) {
+ t->Test();
+ t->Release();
+ } else {
+ printf("CreateInstance failed\n");
+ }
+
+ t = NULL;
+
+ nsComponentManager::CreateInstance(kTestLoadedFactoryCID,
+ NULL,
+ NS_GET_IID(ITestClass),
+ (void **) &t);
+
+ if (t != NULL) {
+ t->Test();
+ t->Release();
+ } else {
+ printf("Dynamic CreateInstance failed\n");
+ }
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestFactory.h b/src/libs/xpcom18a4/xpcom/tests/TestFactory.h
new file mode 100644
index 00000000..d81cefc7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestFactory.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __TestFactory_h
+#define __TestFactory_h
+
+#include "nsIFactory.h"
+
+// {8B330F20-A24A-11d1-A961-00805F8A7AC4}
+#define NS_TESTFACTORY_CID \
+{ 0x8b330f20, 0xa24a, 0x11d1, \
+ { 0xa9, 0x61, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+// {8B330F21-A24A-11d1-A961-00805F8A7AC4}
+#define NS_ITESTCLASS_IID \
+{ 0x8b330f21, 0xa24a, 0x11d1, \
+ { 0xa9, 0x61, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+// {8B330F22-A24A-11d1-A961-00805F8A7AC4}
+#define NS_TESTLOADEDFACTORY_CID \
+{ 0x8b330f22, 0xa24a, 0x11d1, \
+ { 0xa9, 0x61, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+#define NS_TESTLOADEDFACTORY_CONTRACTID "@mozilla.org/xpcom/dynamic-test;1"
+
+class ITestClass: public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITESTCLASS_IID)
+ virtual void Test() = 0;
+};
+
+extern "C" void RegisterTestFactories();
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp b/src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp
new file mode 100644
index 00000000..1b2d3671
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp
@@ -0,0 +1,939 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is C++ hashtable templates.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * 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 "nsTHashtable.h"
+#include "nsBaseHashtable.h"
+#include "nsDataHashtable.h"
+#include "nsInterfaceHashtable.h"
+#include "nsClassHashtable.h"
+
+#include "nsCOMPtr.h"
+#include "nsISupports.h"
+#include "nsCRT.h"
+#include "nsCOMArray.h"
+
+class TestUniChar // for nsClassHashtable
+{
+public:
+ TestUniChar(PRUint32 aWord)
+ {
+ printf(" TestUniChar::TestUniChar() %u\n", aWord);
+ mWord = aWord;
+ }
+
+ ~TestUniChar()
+ {
+ printf(" TestUniChar::~TestUniChar() %u\n", mWord);
+ }
+
+ PRUint32 GetChar() const { return mWord; }
+
+private:
+ PRUint32 mWord;
+};
+
+struct EntityNode {
+ const char* mStr; // never owns buffer
+ PRUint32 mUnicode;
+};
+
+EntityNode gEntities[] = {
+ {"nbsp",160},
+ {"iexcl",161},
+ {"cent",162},
+ {"pound",163},
+ {"curren",164},
+ {"yen",165},
+ {"brvbar",166},
+ {"sect",167},
+ {"uml",168},
+ {"copy",169},
+ {"ordf",170},
+ {"laquo",171},
+ {"not",172},
+ {"shy",173},
+ {"reg",174},
+ {"macr",175}
+};
+
+#define ENTITY_COUNT (sizeof(gEntities)/sizeof(EntityNode))
+
+class EntityToUnicodeEntry : public PLDHashEntryHdr
+{
+public:
+ typedef const char* KeyType;
+ typedef const char* KeyTypePointer;
+
+ EntityToUnicodeEntry(const char* aKey) { mNode = nsnull; }
+ EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
+ ~EntityToUnicodeEntry() { };
+
+ const char* GetKeyPointer() const { return mNode->mStr; }
+ PRBool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
+ static const char* KeyToPointer(const char* aEntity) { return aEntity; }
+ static PLDHashNumber HashKey(const char* aEntity) { return nsCRT::HashCode(aEntity); }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+ const EntityNode* mNode;
+};
+
+PLDHashOperator
+nsTEnumGo(EntityToUnicodeEntry* aEntry, void* userArg) {
+ printf(" enumerated \"%s\" = %u\n",
+ aEntry->mNode->mStr, aEntry->mNode->mUnicode);
+
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsTEnumStop(EntityToUnicodeEntry* aEntry, void* userArg) {
+ printf(" enumerated \"%s\" = %u\n",
+ aEntry->mNode->mStr, aEntry->mNode->mUnicode);
+
+ return PL_DHASH_REMOVE;
+}
+
+void
+testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, PRUint32 numEntries) {
+ printf("Filling hash with %d entries.\n", numEntries);
+
+ PRUint32 i;
+ for (i = 0; i < numEntries; ++i) {
+ printf(" Putting entry \"%s\"...", gEntities[i].mStr);
+ EntityToUnicodeEntry* entry =
+ hash.PutEntry(gEntities[i].mStr);
+
+ if (!entry) {
+ printf("FAILED\n");
+ exit (2);
+ }
+ printf("OK...");
+
+ if (entry->mNode) {
+ printf("entry already exists!\n");
+ exit (3);
+ }
+ printf("\n");
+
+ entry->mNode = &gEntities[i];
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < numEntries; ++i) {
+ printf(" Getting entry \"%s\"...", gEntities[i].mStr);
+ EntityToUnicodeEntry* entry =
+ hash.GetEntry(gEntities[i].mStr);
+
+ if (!entry) {
+ printf("FAILED\n");
+ exit (4);
+ }
+
+ printf("Found %u\n", entry->mNode->mUnicode);
+ }
+
+ printf("Testing non-existent entries...");
+
+ EntityToUnicodeEntry* entry =
+ hash.GetEntry("xxxy");
+
+ if (entry) {
+ printf("FOUND! BAD!\n");
+ exit (5);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+ PRUint32 count = hash.EnumerateEntries(nsTEnumGo, nsnull);
+ if (count != numEntries) {
+ printf(" Bad count!\n");
+ exit (6);
+ }
+}
+
+PLDHashOperator
+nsDEnumRead(const PRUint32& aKey, const char* aData, void* userArg) {
+ printf(" enumerated %u = \"%s\"\n", aKey, aData);
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsDEnum(const PRUint32& aKey, const char*& aData, void* userArg) {
+ printf(" enumerated %u = \"%s\"\n", aKey, aData);
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsCEnumRead(const nsACString& aKey, TestUniChar* aData, void* userArg) {
+ printf(" enumerated \"%s\" = %c\n",
+ PromiseFlatCString(aKey).get(), aData->GetChar());
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsCEnum(const nsACString& aKey, nsAutoPtr<TestUniChar>& aData, void* userArg) {
+ printf(" enumerated \"%s\" = %c\n",
+ PromiseFlatCString(aKey).get(), aData->GetChar());
+ return PL_DHASH_NEXT;
+}
+
+//
+// all this nsIFoo stuff was copied wholesale from TestCOMPTr.cpp
+//
+
+#define NS_IFOO_IID \
+{ 0x6f7652e0, 0xee43, 0x11d1, \
+ { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
+
+class IFoo : public nsISupports
+ {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
+
+ public:
+ IFoo();
+
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+ NS_IMETHOD SetString(const nsACString& /*in*/ aString);
+ NS_IMETHOD GetString(nsACString& /*out*/ aString);
+
+ static void print_totals();
+
+ private:
+ ~IFoo();
+
+ unsigned int refcount_;
+
+ static unsigned int total_constructions_;
+ static unsigned int total_destructions_;
+ nsCString mString;
+ };
+
+unsigned int IFoo::total_constructions_;
+unsigned int IFoo::total_destructions_;
+
+void
+IFoo::print_totals()
+ {
+ printf("total constructions/destructions --> %d/%d\n",
+ total_constructions_, total_destructions_);
+ }
+
+IFoo::IFoo()
+ : refcount_(0)
+ {
+ ++total_constructions_;
+ printf(" new IFoo@%p [#%d]\n",
+ NS_STATIC_CAST(void*, this), total_constructions_);
+ }
+
+IFoo::~IFoo()
+ {
+ ++total_destructions_;
+ printf("IFoo@%p::~IFoo() [#%d]\n",
+ NS_STATIC_CAST(void*, this), total_destructions_);
+ }
+
+nsrefcnt
+IFoo::AddRef()
+ {
+ ++refcount_;
+ printf("IFoo@%p::AddRef(), refcount --> %d\n",
+ NS_STATIC_CAST(void*, this), refcount_);
+ return refcount_;
+ }
+
+nsrefcnt
+IFoo::Release()
+ {
+ int wrap_message = (refcount_ == 1);
+ if ( wrap_message )
+ printf(">>");
+
+ nsrefcnt newrefcount = --refcount_;
+ printf("IFoo@%p::Release(), refcount --> %d\n",
+ NS_STATIC_CAST(void*, this), newrefcount);
+
+ if ( !newrefcount )
+ {
+ printf(" delete IFoo@%p\n", NS_STATIC_CAST(void*, this));
+ delete this;
+ }
+
+ if ( wrap_message )
+ printf(" delete IFoo@%p\n", NS_STATIC_CAST(void*, this));
+
+ return newrefcount;
+ }
+
+nsresult
+IFoo::QueryInterface( const nsIID& aIID, void** aResult )
+ {
+ printf("IFoo@%p::QueryInterface()\n", NS_STATIC_CAST(void*, this));
+ nsISupports* rawPtr = 0;
+ nsresult status = NS_OK;
+
+ if ( aIID.Equals(GetIID()) )
+ rawPtr = this;
+ else
+ {
+ nsID iid_of_ISupports = NS_ISUPPORTS_IID;
+ if ( aIID.Equals(iid_of_ISupports) )
+ rawPtr = NS_STATIC_CAST(nsISupports*, this);
+ else
+ status = NS_ERROR_NO_INTERFACE;
+ }
+
+ NS_IF_ADDREF(rawPtr);
+ *aResult = rawPtr;
+
+ return status;
+ }
+
+nsresult
+IFoo::SetString(const nsACString& aString)
+{
+ mString = aString;
+ return NS_OK;
+}
+
+nsresult
+IFoo::GetString(nsACString& aString)
+{
+ aString = mString;
+ return NS_OK;
+}
+
+nsresult
+CreateIFoo( IFoo** result )
+ // a typical factory function (that calls AddRef)
+ {
+ printf(" >>CreateIFoo() --> ");
+ IFoo* foop = new IFoo();
+ printf("IFoo@%p\n", NS_STATIC_CAST(void*, foop));
+
+ foop->AddRef();
+ *result = foop;
+
+ printf("<<CreateIFoo()\n");
+ return 0;
+ }
+
+PLDHashOperator
+nsIEnumRead(const PRUint32& aKey, IFoo* aFoo, void* userArg) {
+ nsCAutoString str;
+ aFoo->GetString(str);
+
+ printf(" enumerated %u = \"%s\"\n", aKey, str.get());
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsIEnum(const PRUint32& aKey, nsCOMPtr<IFoo>& aData, void* userArg) {
+ nsCAutoString str;
+ aData->GetString(str);
+
+ printf(" enumerated %u = \"%s\"\n", aKey, str.get());
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsIEnum2Read(nsISupports* aKey, PRUint32 aData, void* userArg) {
+ nsCAutoString str;
+ nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
+ foo->GetString(str);
+
+
+ printf(" enumerated \"%s\" = %u\n", str.get(), aData);
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsIEnum2(nsISupports* aKey, PRUint32& aData, void* userArg) {
+ nsCAutoString str;
+ nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
+ foo->GetString(str);
+
+ printf(" enumerated \"%s\" = %u\n", str.get(), aData);
+ return PL_DHASH_NEXT;
+}
+
+int
+main(void) {
+ // check an nsTHashtable
+ nsTHashtable<EntityToUnicodeEntry> EntityToUnicode;
+
+ printf("Initializing nsTHashtable...");
+ if (!EntityToUnicode.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (1);
+ }
+ printf("OK\n");
+
+ printf("Partially filling nsTHashtable:\n");
+ testTHashtable(EntityToUnicode, 5);
+
+ printf("Enumerate-removing...\n");
+ PRUint32 count = EntityToUnicode.EnumerateEntries(nsTEnumStop, nsnull);
+ if (count != 5) {
+ printf("wrong count\n");
+ exit (7);
+ }
+ printf("OK\n");
+
+ printf("Check enumeration...");
+ count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nsnull);
+ if (count) {
+ printf("entries remain in table!\n");
+ exit (8);
+ }
+ printf("OK\n");
+
+ printf("Filling nsTHashtable:\n");
+ testTHashtable(EntityToUnicode, ENTITY_COUNT);
+
+ printf("Clearing...");
+ EntityToUnicode.Clear();
+ printf("OK\n");
+
+ printf("Check enumeration...");
+ count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nsnull);
+ if (count) {
+ printf("entries remain in table!\n");
+ exit (9);
+ }
+ printf("OK\n");
+
+ //
+ // now check a data-hashtable
+ //
+
+ nsDataHashtable<nsUint32HashKey,const char*> UniToEntity;
+
+ printf("Initializing nsDataHashtable...");
+ if (!UniToEntity.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (10);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ PRUint32 i;
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntity.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
+ printf("FAILED\n");
+ exit (11);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+ const char* str;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntity.Get(gEntities[i].mUnicode, &str)) {
+ printf("FAILED\n");
+ exit (12);
+ }
+
+ printf("Found %s\n", str);
+ }
+
+ printf("Testing non-existent entries...");
+ if (UniToEntity.Get(99446, &str)) {
+ printf("FOUND! BAD!\n");
+ exit (13);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntity.EnumerateRead(nsDEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (14);
+ }
+
+ printf("Clearing...");
+ UniToEntity.Clear();
+ printf("OK\n");
+
+ printf("Checking count...");
+ count = UniToEntity.Enumerate(nsDEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (15);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a thread-safe data-hashtable
+ //
+
+ nsDataHashtableMT<nsUint32HashKey,const char*> UniToEntityL;
+
+ printf("Initializing nsDataHashtableMT...");
+ if (!UniToEntityL.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (10);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntityL.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
+ printf("FAILED\n");
+ exit (11);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntityL.Get(gEntities[i].mUnicode, &str)) {
+ printf("FAILED\n");
+ exit (12);
+ }
+
+ printf("Found %s\n", str);
+ }
+
+ printf("Testing non-existent entries...");
+ if (UniToEntityL.Get(99446, &str)) {
+ printf("FOUND! BAD!\n");
+ exit (13);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntityL.EnumerateRead(nsDEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (14);
+ }
+
+ printf("Clearing...");
+ UniToEntityL.Clear();
+ printf("OK\n");
+
+ printf("Checking count...");
+ count = UniToEntityL.Enumerate(nsDEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (15);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a class-hashtable
+ //
+
+ nsClassHashtable<nsCStringHashKey,TestUniChar> EntToUniClass;
+
+ printf("Initializing nsClassHashtable...");
+ if (!EntToUniClass.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (16);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
+
+ if (!EntToUniClass.Put(nsDependentCString(gEntities[i].mStr), temp)) {
+ printf("FAILED\n");
+ delete temp;
+ exit (17);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+ TestUniChar* myChar;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+ if (!EntToUniClass.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
+ printf("FAILED\n");
+ exit (18);
+ }
+
+ printf("Found %c\n", myChar->GetChar());
+ }
+
+ printf("Testing non-existent entries...");
+ if (EntToUniClass.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
+ printf("FOUND! BAD!\n");
+ exit (19);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = EntToUniClass.EnumerateRead(nsCEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (20);
+ }
+
+ printf("Clearing...\n");
+ EntToUniClass.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = EntToUniClass.Enumerate(nsCEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (21);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a thread-safe class-hashtable
+ //
+
+ nsClassHashtableMT<nsCStringHashKey,TestUniChar> EntToUniClassL;
+
+ printf("Initializing nsClassHashtableMT...");
+ if (!EntToUniClassL.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (16);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
+
+ if (!EntToUniClassL.Put(nsDependentCString(gEntities[i].mStr), temp)) {
+ printf("FAILED\n");
+ delete temp;
+ exit (17);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+ if (!EntToUniClassL.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
+ printf("FAILED\n");
+ exit (18);
+ }
+
+ printf("Found %c\n", myChar->GetChar());
+ }
+
+ printf("Testing non-existent entries...");
+ if (EntToUniClassL.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
+ printf("FOUND! BAD!\n");
+ exit (19);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = EntToUniClassL.EnumerateRead(nsCEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (20);
+ }
+
+ printf("Clearing...\n");
+ EntToUniClassL.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = EntToUniClassL.Enumerate(nsCEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (21);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a data-hashtable with an interface key
+ //
+
+ nsDataHashtable<nsISupportsHashKey,PRUint32> EntToUniClass2;
+
+ printf("Initializing nsDataHashtable with interface key...");
+ if (!EntToUniClass2.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (22);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ nsCOMArray<IFoo> fooArray;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ nsCOMPtr<IFoo> foo;
+ CreateIFoo(getter_AddRefs(foo));
+ foo->SetString(nsDependentCString(gEntities[i].mStr));
+
+
+ fooArray.InsertObjectAt(foo, i);
+
+ if (!EntToUniClass2.Put(foo, gEntities[i].mUnicode)) {
+ printf("FAILED\n");
+ exit (23);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+ PRUint32 myChar2;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+
+ if (!EntToUniClass2.Get(fooArray[i], &myChar2)) {
+ printf("FAILED\n");
+ exit (24);
+ }
+
+ printf("Found %c\n", myChar2);
+ }
+
+ printf("Testing non-existent entries...");
+ if (EntToUniClass2.Get((nsISupports*) 0x55443316, &myChar2)) {
+ printf("FOUND! BAD!\n");
+ exit (25);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = EntToUniClass2.EnumerateRead(nsIEnum2Read, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (26);
+ }
+
+ printf("Clearing...\n");
+ EntToUniClass2.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = EntToUniClass2.Enumerate(nsIEnum2, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (27);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check an interface-hashtable with an PRUint32 key
+ //
+
+ nsInterfaceHashtable<nsUint32HashKey,IFoo> UniToEntClass2;
+
+ printf("Initializing nsInterfaceHashtable...");
+ if (!UniToEntClass2.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (28);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ nsCOMPtr<IFoo> foo;
+ CreateIFoo(getter_AddRefs(foo));
+ foo->SetString(nsDependentCString(gEntities[i].mStr));
+
+ if (!UniToEntClass2.Put(gEntities[i].mUnicode, foo)) {
+ printf("FAILED\n");
+ exit (29);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+
+ nsCOMPtr<IFoo> myEnt;
+ if (!UniToEntClass2.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
+ printf("FAILED\n");
+ exit (30);
+ }
+
+ nsCAutoString str;
+ myEnt->GetString(str);
+ printf("Found %s\n", str.get());
+ }
+
+ printf("Testing non-existent entries...");
+ nsCOMPtr<IFoo> myEnt;
+ if (UniToEntClass2.Get(9462, getter_AddRefs(myEnt))) {
+ printf("FOUND! BAD!\n");
+ exit (31);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntClass2.EnumerateRead(nsIEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (32);
+ }
+
+ printf("Clearing...\n");
+ UniToEntClass2.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = UniToEntClass2.Enumerate(nsIEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (33);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a thread-safe interface hashtable
+ //
+
+ nsInterfaceHashtableMT<nsUint32HashKey,IFoo> UniToEntClass2L;
+
+ printf("Initializing nsInterfaceHashtableMT...");
+ if (!UniToEntClass2L.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (28);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ nsCOMPtr<IFoo> foo;
+ CreateIFoo(getter_AddRefs(foo));
+ foo->SetString(nsDependentCString(gEntities[i].mStr));
+
+ if (!UniToEntClass2L.Put(gEntities[i].mUnicode, foo)) {
+ printf("FAILED\n");
+ exit (29);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+
+ nsCOMPtr<IFoo> myEnt;
+ if (!UniToEntClass2L.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
+ printf("FAILED\n");
+ exit (30);
+ }
+
+ nsCAutoString str;
+ myEnt->GetString(str);
+ printf("Found %s\n", str.get());
+ }
+
+ printf("Testing non-existent entries...");
+ if (UniToEntClass2L.Get(9462, getter_AddRefs(myEnt))) {
+ printf("FOUND! BAD!\n");
+ exit (31);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntClass2L.EnumerateRead(nsIEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (32);
+ }
+
+ printf("Clearing...\n");
+ UniToEntClass2L.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = UniToEntClass2L.Enumerate(nsIEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (33);
+ }
+
+ printf("OK\n");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestID.cpp b/src/libs/xpcom18a4/xpcom/tests/TestID.cpp
new file mode 100644
index 00000000..f91fda9f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestID.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include <stdio.h>
+#include "plstr.h"
+#include "nsID.h"
+#include "prmem.h"
+
+static const char* const ids[] = {
+ "5C347B10-D55C-11D1-89B7-006008911B81",
+ "{5C347B10-D55C-11D1-89B7-006008911B81}",
+ "5c347b10-d55c-11d1-89b7-006008911b81",
+ "{5c347b10-d55c-11d1-89b7-006008911b81}",
+
+ "FC347B10-D55C-F1D1-F9B7-006008911B81",
+ "{FC347B10-D55C-F1D1-F9B7-006008911B81}",
+ "fc347b10-d55c-f1d1-f9b7-006008911b81",
+ "{fc347b10-d55c-f1d1-f9b7-006008911b81}",
+};
+#define NUM_IDS ((int) (sizeof(ids) / sizeof(ids[0])))
+
+int main(int argc, char** argv)
+{
+ nsID id;
+ for (int i = 0; i < NUM_IDS; i++) {
+ const char* idstr = ids[i];
+ if (!id.Parse(idstr)) {
+ fprintf(stderr, "TestID: Parse failed on test #%d\n", i);
+ return -1;
+ }
+ char* cp = id.ToString();
+ if (NULL == cp) {
+ fprintf(stderr, "TestID: ToString failed on test #%d\n", i);
+ return -1;
+ }
+ if (0 != PL_strcmp(cp, ids[4*(i/4) + 3])) {
+ fprintf(stderr, "TestID: compare of ToString failed on test #%d\n", i);
+ return -1;
+ }
+ PR_Free(cp);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp b/src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp
new file mode 100644
index 00000000..811df138
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp
@@ -0,0 +1,333 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsStringAPI.h"
+#include "nsCRT.h"
+
+static const char kAsciiData[] = "hello world";
+
+static const PRUnichar kUnicodeData[] =
+ {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
+
+static PRBool test_basic_1()
+ {
+ nsCStringContainer s;
+ NS_CStringContainerInit(s);
+
+ const char *ptr;
+ PRUint32 len;
+ char *clone;
+
+ NS_CStringGetData(s, &ptr);
+ if (ptr == nsnull || *ptr != '\0')
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_CStringSetData(s, kAsciiData, PR_UINT32_MAX);
+ len = NS_CStringGetData(s, &ptr);
+ if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kAsciiData)-1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ clone = NS_CStringCloneData(s);
+ if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ nsMemory::Free(clone);
+
+ nsCStringContainer temp;
+ NS_CStringContainerInit(temp);
+ NS_CStringCopy(temp, s);
+
+ len = NS_CStringGetData(temp, &ptr);
+ if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kAsciiData)-1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_CStringContainerFinish(temp);
+
+ NS_CStringContainerFinish(s);
+ return PR_TRUE;
+ }
+
+static PRBool test_basic_2()
+ {
+ nsStringContainer s;
+ NS_StringContainerInit(s);
+
+ const PRUnichar *ptr;
+ PRUint32 len;
+ PRUnichar *clone;
+
+ NS_StringGetData(s, &ptr);
+ if (ptr == nsnull || *ptr != '\0')
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_StringSetData(s, kUnicodeData, PR_UINT32_MAX);
+ len = NS_StringGetData(s, &ptr);
+ if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kUnicodeData)/2 - 1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ clone = NS_StringCloneData(s);
+ if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ nsMemory::Free(clone);
+
+ nsStringContainer temp;
+ NS_StringContainerInit(temp);
+ NS_StringCopy(temp, s);
+
+ len = NS_StringGetData(temp, &ptr);
+ if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kUnicodeData)/2 - 1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_StringContainerFinish(temp);
+
+ NS_StringContainerFinish(s);
+
+ return PR_TRUE;
+ }
+
+static PRBool test_convert()
+ {
+ nsStringContainer s;
+ NS_StringContainerInit(s);
+ NS_StringSetData(s, kUnicodeData, sizeof(kUnicodeData)/2 - 1);
+
+ nsCStringContainer temp;
+ NS_CStringContainerInit(temp);
+
+ const char *data;
+
+ NS_UTF16ToCString(s, NS_CSTRING_ENCODING_ASCII, temp);
+ NS_CStringGetData(temp, &data);
+ if (strcmp(data, kAsciiData) != 0)
+ return PR_FALSE;
+
+ NS_UTF16ToCString(s, NS_CSTRING_ENCODING_UTF8, temp);
+ NS_CStringGetData(temp, &data);
+ if (strcmp(data, kAsciiData) != 0)
+ return PR_FALSE;
+
+ NS_CStringContainerFinish(temp);
+
+ NS_StringContainerFinish(s);
+ return PR_TRUE;
+ }
+
+static PRBool test_append()
+ {
+ nsCStringContainer s;
+ NS_CStringContainerInit(s);
+
+ NS_CStringSetData(s, "foo");
+ NS_CStringAppendData(s, "bar");
+
+ NS_CStringContainerFinish(s);
+ return PR_TRUE;
+ }
+
+// Replace all occurances of |matchVal| with |newVal|
+static void ReplaceSubstring( nsACString& str,
+ const nsACString& matchVal,
+ const nsACString& newVal )
+ {
+ const char* sp, *mp, *np;
+ PRUint32 sl, ml, nl;
+
+ sl = NS_CStringGetData(str, &sp);
+ ml = NS_CStringGetData(matchVal, &mp);
+ nl = NS_CStringGetData(newVal, &np);
+
+ for (const char* iter = sp; iter <= sp + sl - ml; ++iter)
+ {
+ if (memcmp(iter, mp, ml) == 0)
+ {
+ PRUint32 offset = iter - sp;
+
+ NS_CStringSetDataRange(str, offset, ml, np, nl);
+
+ sl = NS_CStringGetData(str, &sp);
+
+ iter = sp + offset + nl - 1;
+ }
+ }
+ }
+
+static PRBool test_replace_driver(const char *strVal,
+ const char *matchVal,
+ const char *newVal,
+ const char *finalVal)
+ {
+ nsCStringContainer a;
+ NS_CStringContainerInit(a);
+ NS_CStringSetData(a, strVal);
+
+ nsCStringContainer b;
+ NS_CStringContainerInit(b);
+ NS_CStringSetData(b, matchVal);
+
+ nsCStringContainer c;
+ NS_CStringContainerInit(c);
+ NS_CStringSetData(c, newVal);
+
+ ReplaceSubstring(a, b, c);
+
+ const char *data;
+ NS_CStringGetData(a, &data);
+ if (strcmp(data, finalVal) != 0)
+ return PR_FALSE;
+
+ NS_CStringContainerFinish(c);
+ NS_CStringContainerFinish(b);
+ NS_CStringContainerFinish(a);
+ return PR_TRUE;
+ }
+
+static PRBool test_replace()
+ {
+ PRBool rv;
+
+ rv = test_replace_driver("hello world, hello again!",
+ "hello",
+ "goodbye",
+ "goodbye world, goodbye again!");
+ if (!rv)
+ return rv;
+
+ rv = test_replace_driver("foofoofoofoo!",
+ "foo",
+ "bar",
+ "barbarbarbar!");
+ if (!rv)
+ return rv;
+
+ rv = test_replace_driver("foo bar systems",
+ "xyz",
+ "crazy",
+ "foo bar systems");
+ if (!rv)
+ return rv;
+
+ rv = test_replace_driver("oh",
+ "xyz",
+ "crazy",
+ "oh");
+ if (!rv)
+ return rv;
+
+ return PR_TRUE;
+ }
+
+//----
+
+typedef PRBool (*TestFunc)();
+
+static const struct Test
+ {
+ const char* name;
+ TestFunc func;
+ }
+tests[] =
+ {
+ { "test_basic_1", test_basic_1 },
+ { "test_basic_2", test_basic_2 },
+ { "test_convert", test_convert },
+ { "test_append", test_append },
+ { "test_replace", test_replace },
+ { nsnull, nsnull }
+ };
+
+//----
+
+int main(int argc, char **argv)
+ {
+ int count = 1;
+ if (argc > 1)
+ count = atoi(argv[1]);
+
+ while (count--)
+ {
+ for (const Test* t = tests; t->name != nsnull; ++t)
+ {
+ printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE");
+ }
+ }
+
+ return 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp b/src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp
new file mode 100644
index 00000000..148400e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.h"
+#include "nsIComponentManager.h"
+#include "nsIObserverService.h"
+#include "nsIObserver.h"
+#include "nsIEnumerator.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "prprf.h"
+#include "nsWeakReference.h"
+
+static nsIObserverService *anObserverService = NULL;
+
+#ifdef VBOX
+static bool testResult( nsresult rv ) {
+ if ( NS_SUCCEEDED( rv ) ) {
+ printf("...ok\n");
+ return true;
+ }
+ printf("...failed, rv=0x%x\n", (int)rv);
+ return false;
+}
+#else
+static void testResult( nsresult rv ) {
+ if ( NS_SUCCEEDED( rv ) ) {
+ printf("...ok\n");
+ } else {
+ printf("...failed, rv=0x%x\n", (int)rv);
+ }
+ return;
+}
+#endif
+
+void printString(nsString &str) {
+#ifdef VBOX /* asan complains about mixing different allocators */
+ char *cstr = ToNewCString(str);
+ printf("%s", cstr);
+ nsMemory::Free(cstr);
+#else
+ const char *cstr = ToNewCString(str);
+ printf("%s", cstr);
+ delete [] (char*)cstr;
+#endif
+}
+
+class TestObserver : public nsIObserver, public nsSupportsWeakReference {
+public:
+ TestObserver( const nsAString &name )
+ : mName( name ) {
+ }
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ nsString mName;
+
+private:
+ ~TestObserver() {}
+};
+
+NS_IMPL_ISUPPORTS2( TestObserver, nsIObserver, nsISupportsWeakReference )
+
+NS_IMETHODIMP
+TestObserver::Observe( nsISupports *aSubject,
+ const char *aTopic,
+ const PRUnichar *someData ) {
+ nsCString topic( aTopic );
+ nsString data( someData );
+ /*
+ The annoying double-cast below is to work around an annoying bug in
+ the compiler currently used on wensleydale. This is a test.
+ */
+ printString(mName);
+ printf(" has observed something: subject@%p", (void*)aSubject);
+ printf(" name=");
+ printString(NS_REINTERPRET_CAST(TestObserver*, NS_REINTERPRET_CAST(void*, aSubject))->mName);
+ printf(" aTopic=%s", topic.get());
+ printf(" someData=");
+ printString(data);
+ printf("\n");
+ return NS_OK;
+}
+
+int main(int argc, char *argv[])
+{
+ nsCString topicA; topicA.Assign( "topic-A" );
+ nsCString topicB; topicB.Assign( "topic-B" );
+ nsresult rv;
+
+ nsresult res = nsComponentManager::CreateInstance("@mozilla.org/observer-service;1",
+ NULL,
+ NS_GET_IID(nsIObserverService),
+ (void **) &anObserverService);
+#ifdef VBOX
+ bool fSuccess = res == NS_OK;
+#endif
+
+ if (res == NS_OK) {
+
+ nsIObserver *aObserver = new TestObserver(NS_LITERAL_STRING("Observer-A"));
+ aObserver->AddRef();
+ nsIObserver *bObserver = new TestObserver(NS_LITERAL_STRING("Observer-B"));
+ bObserver->AddRef();
+
+ printf("Adding Observer-A as observer of topic-A...\n");
+ rv = anObserverService->AddObserver(aObserver, topicA.get(), PR_FALSE);
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Adding Observer-B as observer of topic-A...\n");
+ rv = anObserverService->AddObserver(bObserver, topicA.get(), PR_FALSE);
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Adding Observer-B as observer of topic-B...\n");
+ rv = anObserverService->AddObserver(bObserver, topicB.get(), PR_FALSE);
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Testing Notify(observer-A, topic-A)...\n");
+ rv = anObserverService->NotifyObservers( aObserver,
+ topicA.get(),
+ NS_LITERAL_STRING("Testing Notify(observer-A, topic-A)").get() );
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Testing Notify(observer-B, topic-B)...\n");
+ rv = anObserverService->NotifyObservers( bObserver,
+ topicB.get(),
+ NS_LITERAL_STRING("Testing Notify(observer-B, topic-B)").get() );
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Testing EnumerateObserverList (for topic-A)...\n");
+ nsCOMPtr<nsISimpleEnumerator> e;
+ rv = anObserverService->EnumerateObservers(topicA.get(), getter_AddRefs(e));
+
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Enumerating observers of topic-A...\n");
+ if ( e ) {
+ nsCOMPtr<nsIObserver> observer;
+ PRBool loop = PR_TRUE;
+ while( NS_SUCCEEDED(e->HasMoreElements(&loop)) && loop)
+ {
+ e->GetNext(getter_AddRefs(observer));
+ printf("Calling observe on enumerated observer ");
+ printString(NS_REINTERPRET_CAST(TestObserver*,
+ NS_REINTERPRET_CAST(void*, observer.get()))->mName);
+ printf("...\n");
+ rv = observer->Observe( observer,
+ topicA.get(),
+ NS_LITERAL_STRING("during enumeration").get() );
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+ }
+ }
+ printf("...done enumerating observers of topic-A\n");
+
+ printf("Removing Observer-A...\n");
+ rv = anObserverService->RemoveObserver(aObserver, topicA.get());
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+
+ printf("Removing Observer-B (topic-A)...\n");
+ rv = anObserverService->RemoveObserver(bObserver, topicB.get());
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+ printf("Removing Observer-B (topic-B)...\n");
+ rv = anObserverService->RemoveObserver(bObserver, topicA.get());
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+#ifdef VBOX
+ /* Cleanup: */
+ nsrefcnt refs = bObserver->Release();
+ fSuccess = fSuccess && refs == 0;
+ if (refs != 0)
+ printf("bObserver->Release() -> %d, expected 0\n", (int)refs);
+
+ refs = aObserver->Release();
+ fSuccess = fSuccess && refs == 0;
+ if (refs != 0)
+ printf("aObserver->Release() -> %d, expected 0\n", (int)refs);
+#endif
+ }
+#ifdef VBOX
+ return fSuccess ? 0 : 1;
+#else
+ return NS_OK;
+#endif
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp b/src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp
new file mode 100644
index 00000000..09b0b2e9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// vim:cindent:ts=8:et:sw=4:
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is TestPermanentAtoms.cpp.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.org> (original author)
+ *
+ * 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 "nsIAtom.h"
+#include "nsAtomTable.h"
+#include "nsCOMPtr.h"
+#include <stdio.h>
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+static void Assert(PRBool aCondition, const char* aStatement)
+{
+ printf("%s: %s\n", aCondition?"PASS":"FAIL", aStatement);
+}
+
+static void AssertString(nsIAtom *aAtom, const nsACString& aString)
+{
+ const char *str;
+ NS_STATIC_CAST(AtomImpl*,aAtom)->GetUTF8String(&str);
+ Assert(nsDependentCString(str) == aString, "string is correct");
+}
+
+static void AssertPermanence(nsIAtom *aAtom, PRBool aPermanence)
+{
+ Assert(NS_STATIC_CAST(AtomImpl*,aAtom)->IsPermanent() == aPermanence,
+ aPermanence ? "atom is permanent" : "atom is not permanent");
+}
+
+int main()
+{
+ nsCOMPtr<nsIAtom> foo = do_GetAtom("foo");
+ AssertString(foo, NS_LITERAL_CSTRING("foo"));
+ AssertPermanence(foo, PR_FALSE);
+
+ nsCOMPtr<nsIAtom> foop = do_GetPermanentAtom("foo");
+ AssertString(foop, NS_LITERAL_CSTRING("foo"));
+ AssertPermanence(foop, PR_TRUE);
+
+ Assert(foo == foop, "atoms are equal");
+
+ nsCOMPtr<nsIAtom> barp = do_GetPermanentAtom("bar");
+ AssertString(barp, NS_LITERAL_CSTRING("bar"));
+ AssertPermanence(barp, PR_TRUE);
+
+ nsCOMPtr<nsIAtom> bar = do_GetAtom("bar");
+ AssertString(bar, NS_LITERAL_CSTRING("bar"));
+ AssertPermanence(bar, PR_TRUE);
+
+ Assert(bar == barp, "atoms are equal");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp b/src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp
new file mode 100644
index 00000000..2d798a5b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp
@@ -0,0 +1,655 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsIServiceManager.h"
+#include "prprf.h"
+#include "prinrval.h"
+#include "plstr.h"
+#include "nsCRT.h"
+#include "nsCOMPtr.h"
+#include <stdio.h>
+#include "nsIPipe.h" // new implementation
+#include "nsAutoLock.h"
+#include <stdlib.h> // for rand
+
+#define KEY 0xa7
+#define ITERATIONS 33333
+char kTestPattern[] = "My hovercraft is full of eels.\n";
+
+PRBool gTrace = PR_FALSE;
+
+static nsresult
+WriteAll(nsIOutputStream *os, const char *buf, PRUint32 bufLen, PRUint32 *lenWritten)
+{
+ const char *p = buf;
+ *lenWritten = 0;
+ while (bufLen) {
+ PRUint32 n;
+ nsresult rv = os->Write(p, bufLen, &n);
+ if (NS_FAILED(rv)) return rv;
+ p += n;
+ bufLen -= n;
+ *lenWritten += n;
+ }
+ return NS_OK;
+}
+
+class nsReceiver : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsresult rv;
+ char buf[101];
+ PRUint32 count;
+ PRIntervalTime start = PR_IntervalNow();
+ while (PR_TRUE) {
+ rv = mIn->Read(buf, 100, &count);
+ if (NS_FAILED(rv)) {
+ printf("read failed\n");
+ break;
+ }
+ if (count == 0) {
+// printf("EOF count = %d\n", mCount);
+ break;
+ }
+
+ if (gTrace) {
+ printf("read: ");
+ buf[count] = '\0';
+ printf(buf);
+ printf("\n");
+ }
+ mCount += count;
+ }
+ PRIntervalTime end = PR_IntervalNow();
+ printf("read %d bytes, time = %dms\n", mCount,
+ PR_IntervalToMilliseconds(end - start));
+ return rv;
+ }
+
+ nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) {
+ NS_ADDREF(in);
+ }
+
+ PRUint32 GetBytesRead() { return mCount; }
+
+private:
+ ~nsReceiver() {
+ NS_RELEASE(mIn);
+ }
+
+protected:
+ nsIInputStream* mIn;
+ PRUint32 mCount;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsReceiver, nsIRunnable)
+
+nsresult
+TestPipe(nsIInputStream* in, nsIOutputStream* out)
+{
+ nsresult rv;
+ nsIThread* thread;
+ nsReceiver* receiver = new nsReceiver(in);
+ if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(receiver);
+
+ rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ PRUint32 total = 0;
+ PRIntervalTime start = PR_IntervalNow();
+ for (PRUint32 i = 0; i < ITERATIONS; i++) {
+ PRUint32 writeCount;
+ char *buf = PR_smprintf("%d %s", i, kTestPattern);
+ PRUint32 len = strlen(buf);
+ rv = WriteAll(out, buf, len, &writeCount);
+ if (gTrace) {
+ printf("wrote: ");
+ for (PRUint32 j = 0; j < writeCount; j++) {
+ putc(buf[j], stdout);
+ }
+ printf("\n");
+ }
+ PR_smprintf_free(buf);
+ if (NS_FAILED(rv)) return rv;
+ total += writeCount;
+ }
+ rv = out->Close();
+ if (NS_FAILED(rv)) return rv;
+
+ PRIntervalTime end = PR_IntervalNow();
+
+ thread->Join();
+
+ printf("wrote %d bytes, time = %dms\n", total,
+ PR_IntervalToMilliseconds(end - start));
+ NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything");
+
+ NS_RELEASE(thread);
+ NS_RELEASE(receiver);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsShortReader : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsresult rv;
+ char buf[101];
+ PRUint32 count;
+ PRUint32 total = 0;
+ while (PR_TRUE) {
+ //if (gTrace)
+ // printf("calling Read\n");
+ rv = mIn->Read(buf, 100, &count);
+ if (NS_FAILED(rv)) {
+ printf("read failed\n");
+ break;
+ }
+ if (count == 0) {
+ break;
+ }
+ buf[count] = '\0';
+ if (gTrace)
+ printf("read %d bytes: %s\n", count, buf);
+ Received(count);
+ total += count;
+ }
+ printf("read %d bytes\n", total);
+ return rv;
+ }
+
+ nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) {
+ NS_ADDREF(in);
+ }
+
+ void Received(PRUint32 count) {
+ nsAutoCMonitor mon(this);
+ mReceived += count;
+ mon.Notify();
+ }
+
+ PRUint32 WaitForReceipt() {
+ nsAutoCMonitor mon(this);
+ PRUint32 result = mReceived;
+ while (result == 0) {
+ mon.Wait();
+ NS_ASSERTION(mReceived >= 0, "failed to receive");
+ result = mReceived;
+ }
+ mReceived = 0;
+ return result;
+ }
+
+private:
+ ~nsShortReader() {
+ NS_RELEASE(mIn);
+ }
+
+protected:
+ nsIInputStream* mIn;
+ PRUint32 mReceived;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsShortReader, nsIRunnable)
+
+nsresult
+TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
+{
+ nsresult rv;
+ nsIThread* thread;
+ nsShortReader* receiver = new nsShortReader(in);
+ if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(receiver);
+
+ rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ PRUint32 total = 0;
+ for (PRUint32 i = 0; i < ITERATIONS; i++) {
+ PRUint32 writeCount;
+ char* buf = PR_smprintf("%d %s", i, kTestPattern);
+ PRUint32 len = strlen(buf);
+ len = len * rand() / RAND_MAX;
+ len = PR_MAX(1, len);
+ rv = WriteAll(out, buf, len, &writeCount);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(writeCount == len, "didn't write enough");
+ total += writeCount;
+
+ if (gTrace)
+ printf("wrote %d bytes: %s\n", writeCount, buf);
+ PR_smprintf_free(buf);
+ //printf("calling Flush\n");
+ out->Flush();
+ //printf("calling WaitForReceipt\n");
+ PRUint32 received = receiver->WaitForReceipt();
+ NS_ASSERTION(received == writeCount, "received wrong amount");
+ }
+ rv = out->Close();
+ if (NS_FAILED(rv)) return rv;
+
+ thread->Join();
+ printf("wrote %d bytes\n", total);
+
+ NS_RELEASE(thread);
+ NS_RELEASE(receiver);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+
+class nsPipeObserver : public nsIInputStreamObserver,
+ public nsIOutputStreamObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD OnFull(nsIOutputStream *outStr) {
+ printf("OnFull outStr=%p\n", outStr);
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnWrite(nsIOutputStream *outStr, PRUint32 amount) {
+ printf("OnWrite outStr=%p amount=%d\n", outStr, amount);
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnEmpty(nsIInputStream* inStr) {
+ printf("OnEmpty inStr=%p\n", inStr);
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnClose(nsIInputStream* inStr) {
+ printf("OnClose inStr=%p\n", inStr);
+ return NS_OK;
+ }
+
+ nsPipeObserver() { }
+
+private:
+ ~nsPipeObserver() {}
+};
+
+NS_IMPL_ISUPPORTS2(nsPipeObserver, nsIInputStreamObserver, nsIOutputStreamObserver)
+
+nsresult
+TestPipeObserver()
+{
+ nsresult rv;
+ nsPipeObserver* obs = new nsPipeObserver();
+ if (obs == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(obs);
+
+ printf("TestPipeObserver: OnWrite and OnFull should be called once, OnEmpty should be called twice.\n");
+ nsIInputStream* in;
+ nsIOutputStream* out;
+ rv = NS_NewPipe(&in, &out, 18, 36, PR_TRUE, PR_TRUE);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIObservableInputStream> observableIn(do_QueryInterface(in, &rv));
+ if (NS_FAILED(rv)) return rv;
+ nsCOMPtr<nsIObservableInputStream> observableOut(do_QueryInterface(out, &rv));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = observableIn->SetObserver(obs);
+ if (NS_FAILED(rv)) return rv;
+ rv = observableOut->SetObserver(obs);
+ if (NS_FAILED(rv)) return rv;
+
+ char buf[] = "puirt a beul: a style of Gaelic vocal music intended for dancing.";
+ PRUint32 cnt;
+ printf("> should see OnWrite message:\n");
+ rv = out->Write(buf, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 20, "Write failed");
+
+ printf("> should see OnWrite message followed by OnFull message:\n");
+ rv = out->Write(buf + 20, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 16, "Write failed");
+
+ rv = in->Available(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("available = %u\n", cnt);
+ NS_ASSERTION(cnt == 36, "Available failed");
+
+ char buf2[40];
+ printf("> should see OnEmpty message:\n");
+ rv = in->Read(buf2, 40, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("cnt = %u\n", cnt);
+ NS_ASSERTION(cnt == 36, "Read failed");
+ NS_ASSERTION(nsCRT::strncmp(buf, buf2, 36) == 0, "Read wrong stuff");
+
+ rv = in->Available(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("available = %u\n", cnt);
+ NS_ASSERTION(cnt == 0, "Available failed");
+
+ printf("> should see OnEmpty message:\n");
+ rv = in->Read(buf2, 2, &cnt);
+ if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) return rv;
+ NS_ASSERTION(cnt == 0 && rv == NS_BASE_STREAM_WOULD_BLOCK, "Read failed");
+
+ printf("> should see OnWrite message:\n");
+ rv = out->Write(buf, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 20, "Write failed");
+
+ rv = in->Available(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("available = %u\n", cnt);
+ NS_ASSERTION(cnt == 20, "Available failed");
+
+ printf("> should see OnEmpty message:\n");
+ rv = in->Read(buf2, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 20, "Read failed");
+
+ printf("> should see OnClose message:\n");
+ NS_RELEASE(obs);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ return NS_OK;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsPump : public nsIRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsresult rv;
+ PRUint32 count;
+ while (PR_TRUE) {
+ nsAutoCMonitor mon(this);
+ rv = mOut->WriteFrom(mIn, ~0U, &count);
+ if (NS_FAILED(rv)) {
+ printf("Write failed\n");
+ break;
+ }
+ if (count == 0) {
+ printf("EOF count = %d\n", mCount);
+ break;
+ }
+
+ if (gTrace) {
+ printf("Wrote: %d\n", count);
+ }
+ mCount += count;
+ }
+ mOut->Close();
+ return rv;
+ }
+
+ nsPump(nsIInputStream* in,
+ nsIOutputStream* out)
+ : mIn(in), mOut(out), mCount(0) {
+ }
+
+private:
+ ~nsPump() {}
+
+protected:
+ nsCOMPtr<nsIInputStream> mIn;
+ nsCOMPtr<nsIOutputStream> mOut;
+ PRUint32 mCount;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsPump,
+ nsIRunnable)
+
+nsresult
+TestChainedPipes()
+{
+ nsresult rv;
+ printf("TestChainedPipes\n");
+
+ nsIInputStream* in1;
+ nsIOutputStream* out1;
+ rv = NS_NewPipe(&in1, &out1, 20, 1999);
+ if (NS_FAILED(rv)) return rv;
+
+ nsIInputStream* in2;
+ nsIOutputStream* out2;
+ rv = NS_NewPipe(&in2, &out2, 200, 401);
+ if (NS_FAILED(rv)) return rv;
+
+ nsIThread* thread;
+ nsPump* pump = new nsPump(in1, out2);
+ if (pump == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(pump);
+
+ rv = NS_NewThread(&thread, pump, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ nsIThread* receiverThread;
+ nsReceiver* receiver = new nsReceiver(in2);
+ if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(receiver);
+
+ rv = NS_NewThread(&receiverThread, receiver, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ PRUint32 total = 0;
+ for (PRUint32 i = 0; i < ITERATIONS; i++) {
+ PRUint32 writeCount;
+ char* buf = PR_smprintf("%d %s", i, kTestPattern);
+ PRUint32 len = strlen(buf);
+ len = len * rand() / RAND_MAX;
+ len = PR_MAX(1, len);
+ rv = WriteAll(out1, buf, len, &writeCount);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(writeCount == len, "didn't write enough");
+ total += writeCount;
+
+ if (gTrace)
+ printf("wrote %d bytes: %s\n", writeCount, buf);
+
+ PR_smprintf_free(buf);
+ }
+ printf("wrote total of %d bytes\n", total);
+ rv = out1->Close();
+ if (NS_FAILED(rv)) return rv;
+
+ thread->Join();
+ receiverThread->Join();
+
+ NS_RELEASE(thread);
+ NS_RELEASE(pump);
+ NS_RELEASE(receiverThread);
+ NS_RELEASE(receiver);
+ NS_RELEASE(out2);
+ NS_RELEASE(in2);
+ NS_RELEASE(in1);
+ NS_RELEASE(out1);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void
+RunTests(PRUint32 segSize, PRUint32 segCount)
+{
+ nsresult rv;
+ nsIInputStream* in = 0; /* bird: initialize to quiet gcc. */
+ nsIOutputStream* out = 0; /* ditto */
+ PRUint32 bufSize;
+
+ bufSize = segSize * segCount;
+ printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize);
+
+ printf("Testing long writes...\n");
+ rv = NS_NewPipe(&in, &out, segSize, bufSize);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed");
+ rv = TestPipe(in, out);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
+
+ printf("Testing short writes...\n");
+ rv = NS_NewPipe(&in, &out, segSize, bufSize);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed");
+ rv = TestShortWrites(in, out);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#if 0
+void
+TestSearch(const char* delim, PRUint32 segSize)
+{
+ nsresult rv;
+ // need at least 2 segments to test boundary conditions:
+ PRUint32 bufDataSize = segSize * 2;
+ PRUint32 bufSize = segSize * 2;
+ nsIInputStream* in;
+ nsIOutputStream* out;
+ rv = NS_NewPipe(&in, &out, segSize, bufSize);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed");
+ out->SetNonBlocking(PR_TRUE);
+
+ PRUint32 i, j, amt;
+ PRUint32 delimLen = nsCRT::strlen(delim);
+ for (i = 0; i < bufDataSize; i++) {
+ // first fill the buffer
+ for (j = 0; j < i; j++) {
+ rv = out->Write("-", 1, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && amt == 1, "Write failed");
+ }
+ rv = out->Write(delim, delimLen, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Write failed");
+ if (i + amt < bufDataSize) {
+ for (j = i + amt; j < bufDataSize; j++) {
+ rv = out->Write("+", 1, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && amt == 1, "Write failed");
+ }
+ }
+
+ // now search for the delimiter
+ PRBool found;
+ PRUint32 offset;
+ rv = in->Search(delim, PR_FALSE, &found, &offset);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Search failed");
+
+ // print the results
+ char* bufferContents = new char[bufDataSize + 1];
+ rv = in->Read(bufferContents, bufDataSize, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && amt == bufDataSize, "Read failed");
+ bufferContents[bufDataSize] = '\0';
+ printf("Buffer: %s\nDelim: %s %s offset: %d\n", bufferContents,
+ delim, (found ? "found" : "not found"), offset);
+ }
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+}
+#endif
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG
+extern NS_COM void
+TestSegmentedBuffer();
+#endif
+
+int
+main(int argc, char* argv[])
+{
+ nsresult rv;
+ nsIServiceManager* servMgr;
+
+ rv = NS_InitXPCOM2(&servMgr, NULL, NULL);
+ if (NS_FAILED(rv)) return rv;
+
+ if (argc > 1 && nsCRT::strcmp(argv[1], "-trace") == 0)
+ gTrace = PR_TRUE;
+
+#ifdef DEBUG
+ TestSegmentedBuffer();
+#endif
+
+#if 0 // obsolete old implementation
+ rv = NS_NewPipe(&in, &out, 4096 * 4);
+ if (NS_FAILED(rv)) {
+ printf("NewPipe failed\n");
+ return -1;
+ }
+
+ rv = TestPipe(in, out);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ if (NS_FAILED(rv)) {
+ printf("TestPipe failed\n");
+ return -1;
+ }
+#endif
+#if 0
+ TestSearch("foo", 8);
+ TestSearch("bar", 6);
+ TestSearch("baz", 2);
+#endif
+
+ rv = TestChainedPipes();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
+ RunTests(16, 1);
+ RunTests(4096, 16);
+ NS_RELEASE(servMgr);
+ rv = NS_ShutdownXPCOM( NULL );
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp b/src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp
new file mode 100644
index 00000000..8eaaaa77
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "MyService.h"
+#include "nsXPCOM.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include <stdio.h>
+
+static NS_DEFINE_CID(kIMyServiceCID, NS_IMYSERVICE_CID);
+
+////////////////////////////////////////////////////////////////////////////////
+
+IMyService* myServ = NULL;
+
+nsresult
+BeginTest(int testNumber)
+{
+ nsresult err;
+ NS_ASSERTION(myServ == NULL, "myServ not reset");
+ err = nsServiceManager::GetService(kIMyServiceCID, NS_GET_IID(IMyService),
+ (nsISupports**)&myServ);
+ return err;
+}
+
+nsresult
+EndTest(int testNumber)
+{
+ nsresult err = NS_OK;
+
+ if (myServ) {
+ err = myServ->Doit();
+ if (err != NS_OK) return err;
+
+ err = nsServiceManager::ReleaseService(kIMyServiceCID, myServ);
+ if (err != NS_OK) return err;
+ myServ = NULL;
+ }
+
+ printf("test %d succeeded\n", testNumber);
+ return NS_OK;
+}
+
+nsresult
+SimpleTest(int testNumber)
+{
+ // This test just gets a service, uses it and releases it.
+
+ nsresult err;
+ err = BeginTest(testNumber);
+ if (err != NS_OK) return err;
+ err = EndTest(testNumber);
+ return err;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult
+AsyncShutdown(int testNumber)
+{
+ nsresult err;
+
+ // If the AsyncShutdown was truly asynchronous and happened on another
+ // thread, we'd have to protect all accesses to myServ throughout this
+ // code with a monitor.
+
+ err = nsServiceManager::UnregisterService(kIMyServiceCID);
+ if (err == NS_ERROR_SERVICE_NOT_AVAILABLE) {
+ printf("async shutdown -- service not found\n");
+ return NS_OK;
+ }
+ return err;
+}
+
+nsresult
+AsyncNoShutdownTest(int testNumber)
+{
+ // This test gets a service, and also gets an async request for shutdown,
+ // but the service doesn't get shut down because some other client (who's
+ // not participating in the async shutdown game as he should) is
+ // continuing to hang onto the service. This causes myServ variable to
+ // get set to NULL, but the service doesn't get unloaded right away as
+ // it should.
+
+ nsresult err;
+
+ err = BeginTest(testNumber);
+ if (err != NS_OK) return err;
+
+ // Create some other user of kIMyServiceCID, preventing it from
+ // really going away:
+ IMyService* otherClient;
+ err = nsServiceManager::GetService(kIMyServiceCID, NS_GET_IID(IMyService),
+ (nsISupports**)&otherClient);
+ if (err != NS_OK) return err;
+
+ err = AsyncShutdown(testNumber);
+ if (err != NS_OK) return err;
+ err = EndTest(testNumber);
+
+ // Finally, release the other client.
+ err = nsServiceManager::ReleaseService(kIMyServiceCID, otherClient);
+
+ return err;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int
+main(void)
+{
+ nsresult err;
+ int testNumber = 0;
+
+ err = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(err)) {
+ printf("NS_InitXPCOM2 failed\n");
+ return -1;
+ }
+
+ err = SimpleTest(++testNumber);
+ if (err != NS_OK)
+ goto error;
+
+ err = AsyncNoShutdownTest(++testNumber);
+ if (err != NS_OK)
+ goto error;
+
+ AsyncShutdown(++testNumber);
+
+ printf("there was great success\n");
+ return 0;
+
+ error:
+ printf("test %d failed\n", testNumber);
+ return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp b/src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp
new file mode 100644
index 00000000..259a7b31
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIServiceManager.h"
+
+// Gee this seems simple! It's for testing for memory leaks with Purify.
+
+void main(int argc, char* argv[])
+{
+ nsresult rv;
+ nsIServiceManager* servMgr;
+ rv = NS_InitXPCOM2(&servMgr, NULL, NULL);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_InitXPCOM failed");
+
+ // try loading a component and releasing it to see if it leaks
+ if (argc > 1 && argv[1] != nsnull) {
+ char* cidStr = argv[1];
+ nsISupports* obj = nsnull;
+ if (cidStr[0] == '{') {
+ nsCID cid;
+ cid.Parse(cidStr);
+ rv = nsComponentManager::CreateInstance(cid, nsnull,
+ NS_GET_IID(nsISupports),
+ (void**)&obj);
+ }
+ else {
+ // contractID case:
+ rv = nsComponentManager::CreateInstance(cidStr, nsnull,
+ NS_GET_IID(nsISupports),
+ (void**)&obj);
+ }
+ if (NS_SUCCEEDED(rv)) {
+ printf("Successfully created %s\n", cidStr);
+ NS_RELEASE(obj);
+ }
+ else {
+ printf("Failed to create %s (%x)\n", cidStr, rv);
+ }
+ }
+
+ rv = NS_ShutdownXPCOM(servMgr);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp b/src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp
new file mode 100644
index 00000000..76187edd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+#include "nsISupportsUtils.h"
+#include "nsTraceRefCntImpl.h"
+
+int main(int argc, char* argv[])
+{
+ nsTraceRefcntImpl::WalkTheStack(stdout);
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp b/src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp
new file mode 100644
index 00000000..b1b725a4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp
@@ -0,0 +1,643 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+
+void test_assign_helper(const nsACString& in, nsACString &_retval)
+ {
+ _retval = in;
+ }
+
+PRBool test_assign()
+ {
+ nsCString result;
+ test_assign_helper(NS_LITERAL_CSTRING("a") + NS_LITERAL_CSTRING("b"), result);
+ PRBool r = strcmp(result.get(), "ab") == 0;
+ if (!r)
+ printf("[result=%s]\n", result.get());
+ return r;
+ }
+
+PRBool test_assign_c()
+ {
+ nsCString c; c.Assign('c');
+ PRBool r = strcmp(c.get(), "c") == 0;
+ if (!r)
+ printf("[result=%s]\n", c.get());
+ return r;
+ }
+
+PRBool test1()
+ {
+ NS_NAMED_LITERAL_STRING(empty, "");
+ const nsAString& aStr = empty;
+
+ nsAutoString buf(aStr);
+
+ PRInt32 n = buf.FindChar(',');
+
+ n = buf.Length();
+
+ buf.Cut(0, n + 1);
+ n = buf.FindChar(',');
+
+ if (n != kNotFound)
+ printf("n=%d\n", n);
+
+ return n == kNotFound;
+ }
+
+PRBool test2()
+ {
+ nsCString data("hello world");
+ const nsACString& aStr = data;
+
+ nsCString temp(aStr);
+ temp.Cut(0, 6);
+
+ PRBool r = strcmp(temp.get(), "world") == 0;
+ if (!r)
+ printf("[temp=%s]\n", temp.get());
+ return r;
+ }
+
+PRBool test_find()
+ {
+ nsCString src("<!DOCTYPE blah blah blah>");
+
+ PRInt32 i = src.Find("DOCTYPE", PR_TRUE, 2, 1);
+ if (i == 2)
+ return PR_TRUE;
+
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+PRBool test_rfind()
+ {
+ const char text[] = "<!DOCTYPE blah blah blah>";
+ const char term[] = "bLaH";
+ nsCString src(text);
+ PRInt32 i;
+
+ i = src.RFind(term, PR_TRUE, 3, -1);
+ if (i != kNotFound)
+ {
+ printf("unexpected result searching from offset=3, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ i = src.RFind(term, PR_TRUE, -1, -1);
+ if (i != 20)
+ {
+ printf("unexpected result searching from offset=-1, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ i = src.RFind(term, PR_TRUE, 13, -1);
+ if (i != 10)
+ {
+ printf("unexpected result searching from offset=13, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ i = src.RFind(term, PR_TRUE, 22, 3);
+ if (i != 20)
+ {
+ printf("unexpected result searching from offset=22, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+PRBool test_rfind_2()
+ {
+ const char text[] = "<!DOCTYPE blah blah blah>";
+ nsCString src(text);
+ PRInt32 i = src.RFind("TYPE", PR_FALSE, 5, -1);
+ if (i == 5)
+ return PR_TRUE;
+
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+PRBool test_rfind_3()
+ {
+ const char text[] = "urn:mozilla:locale:en-US:necko";
+ nsCAutoString value(text);
+ PRInt32 i = value.RFind(":");
+ if (i == 24)
+ return PR_TRUE;
+
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+PRBool test_rfind_4()
+ {
+ nsCString value("a.msf");
+ PRInt32 i = value.RFind(".msf");
+ if (i != 1)
+ {
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+PRBool test_distance()
+ {
+ const char text[] = "abc-xyz";
+ nsCString s(text);
+ nsCString::const_iterator begin, end;
+ s.BeginReading(begin);
+ s.EndReading(end);
+ size_t d = Distance(begin, end);
+ PRBool r = (d == sizeof(text)-1);
+ if (!r)
+ printf("d=%zu\n", d);
+ return r;
+ }
+
+PRBool test_length()
+ {
+ const char text[] = "abc-xyz";
+ nsCString s(text);
+ size_t d = s.Length();
+ PRBool r = (d == sizeof(text)-1);
+ if (!r)
+ printf("d=%zu\n", d);
+ return r;
+ }
+
+PRBool test_trim()
+ {
+ const char text[] = " a\t $ ";
+ const char set[] = " \t$";
+
+ nsCString s(text);
+ s.Trim(set);
+ PRBool r = strcmp(s.get(), "a") == 0;
+ if (!r)
+ printf("[s=%s]\n", s.get());
+ return r;
+ }
+
+PRBool test_replace_substr()
+ {
+ const char text[] = "abc-ppp-qqq-ppp-xyz";
+ nsCString s(text);
+ s.ReplaceSubstring("ppp", "www");
+ PRBool r = strcmp(s.get(), "abc-www-qqq-www-xyz") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ s.Assign("foobar");
+ s.ReplaceSubstring("foo", "bar");
+ s.ReplaceSubstring("bar", "");
+ r = strcmp(s.get(), "") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ s.Assign("foofoofoo");
+ s.ReplaceSubstring("foo", "foo");
+ r = strcmp(s.get(), "foofoofoo") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ s.Assign("foofoofoo");
+ s.ReplaceSubstring("of", "fo");
+ r = strcmp(s.get(), "fofoofooo") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+PRBool test_replace_substr_2()
+ {
+ const char *oldName = nsnull;
+ const char *newName = "user";
+ nsString acctName; acctName.AssignLiteral("forums.foo.com");
+ nsAutoString newAcctName, oldVal, newVal;
+ oldVal.AssignWithConversion(oldName);
+ newVal.AssignWithConversion(newName);
+ newAcctName.Assign(acctName);
+
+ // here, oldVal is empty. we are testing that this function
+ // does not hang. see bug 235355.
+ newAcctName.ReplaceSubstring(oldVal, newVal);
+
+ // we expect that newAcctName will be unchanged.
+ if (!newAcctName.Equals(acctName))
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_strip_ws()
+ {
+ const char text[] = " a $ ";
+ nsCString s(text);
+ s.StripWhitespace();
+ PRBool r = strcmp(s.get(), "a$") == 0;
+ if (!r)
+ printf("[s=%s]\n", s.get());
+ return r;
+ }
+
+PRBool test_equals_ic()
+ {
+ nsCString s;
+ PRBool r = s.LowerCaseEqualsLiteral("view-source");
+ if (r)
+ printf("[r=%d]\n", r);
+ return !r;
+ }
+
+PRBool test_fixed_string()
+ {
+ char buf[256] = "hello world";
+
+ nsFixedCString s(buf, sizeof(buf));
+
+ if (s.Length() != strlen(buf))
+ return PR_FALSE;
+
+ if (strcmp(s.get(), buf) != 0)
+ return PR_FALSE;
+
+ s.Assign("foopy doopy doo");
+ if (s.get() != buf)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_concat()
+ {
+ nsCString bar("bar");
+ const nsACString& barRef = bar;
+
+ const nsPromiseFlatCString& result =
+ PromiseFlatCString(NS_LITERAL_CSTRING("foo") +
+ NS_LITERAL_CSTRING(",") +
+ barRef);
+ if (strcmp(result.get(), "foo,bar") == 0)
+ return PR_TRUE;
+
+ printf("[result=%s]\n", result.get());
+ return PR_FALSE;
+ }
+
+PRBool test_concat_2()
+ {
+ nsCString fieldTextStr("xyz");
+ nsCString text("text");
+ const nsACString& aText = text;
+
+ nsCAutoString result( fieldTextStr + aText );
+
+ if (strcmp(result.get(), "xyztext") == 0)
+ return PR_TRUE;
+
+ printf("[result=%s]\n", result.get());
+ return PR_FALSE;
+ }
+
+#if 0
+PRBool test_concat_3()
+ {
+ nsCString a("a"), b("b");
+
+ // THIS DOES NOT COMPILE
+ const nsACString& r = a + b;
+
+ return PR_TRUE;
+ }
+#endif
+
+PRBool test_xpidl_string()
+ {
+ nsXPIDLCString a, b;
+ a = b;
+ if (a != b)
+ return PR_FALSE;
+
+ a.Adopt(0);
+ if (a != b)
+ return PR_FALSE;
+
+ a.Append("foopy");
+ a.Assign(b);
+ if (a != b)
+ return PR_FALSE;
+
+ a.Insert("", 0);
+ a.Assign(b);
+ if (a != b)
+ return PR_FALSE;
+
+ const char text[] = "hello world";
+ *getter_Copies(a) = nsCRT::strdup(text);
+ if (strcmp(a, text) != 0)
+ return PR_FALSE;
+
+ b = a;
+ if (strcmp(a, b) != 0)
+ return PR_FALSE;
+
+ a.Adopt(0);
+ nsACString::const_iterator begin, end;
+ a.BeginReading(begin);
+ a.EndReading(end);
+ char *r = ToNewCString(Substring(begin, end));
+ if (strcmp(r, "") != 0)
+ return PR_FALSE;
+ nsMemory::Free(r);
+
+ a.Adopt(0);
+ if (a != (const char*) 0)
+ return PR_FALSE;
+
+ /*
+ PRInt32 index = a.FindCharInSet("xyz");
+ if (index != kNotFound)
+ return PR_FALSE;
+ */
+
+ return PR_TRUE;
+ }
+
+PRBool test_empty_assign()
+ {
+ nsCString a;
+ a.AssignLiteral("");
+
+ a.AppendLiteral("");
+
+ nsCString b;
+ b.SetCapacity(0);
+ return PR_TRUE;
+ }
+
+PRBool test_set_length()
+ {
+ const char kText[] = "Default Plugin";
+ nsCString buf;
+ buf.SetCapacity(sizeof(kText)-1);
+ buf.Assign(kText);
+ buf.SetLength(sizeof(kText)-1);
+ if (strcmp(buf.get(), kText) != 0)
+ return PR_FALSE;
+ return PR_TRUE;
+ }
+
+PRBool test_substring()
+ {
+ nsCString super("hello world"), sub("hello");
+
+ // this tests that |super| starts with |sub|,
+
+ PRBool r = sub.Equals(StringHead(super, sub.Length()));
+ if (!r)
+ return PR_FALSE;
+
+ // and verifies that |sub| does not start with |super|.
+
+ r = super.Equals(StringHead(sub, super.Length()));
+ if (r)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_appendint64()
+ {
+ nsCString str;
+
+ PRInt64 max = LL_MaxInt();
+ static const char max_expected[] = "9223372036854775807";
+ PRInt64 min = LL_MinInt();
+ static const char min_expected[] = "-9223372036854775808";
+ static const char min_expected_oct[] = "1000000000000000000000";
+ PRInt64 maxint_plus1 = LL_INIT(1, 0);
+ static const char maxint_plus1_expected[] = "4294967296";
+ static const char maxint_plus1_expected_x[] = "100000000";
+
+ str.AppendInt(max);
+
+ if (!str.Equals(max_expected)) {
+ fprintf(stderr, "Error appending LL_MaxInt(): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+
+ str.Truncate();
+ str.AppendInt(min);
+ if (!str.Equals(min_expected)) {
+ fprintf(stderr, "Error appending LL_MinInt(): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+ str.Truncate();
+ str.AppendInt(min, 8);
+ if (!str.Equals(min_expected_oct)) {
+ fprintf(stderr, "Error appending LL_MinInt() (oct): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+
+
+ str.Truncate();
+ str.AppendInt(maxint_plus1);
+ if (!str.Equals(maxint_plus1_expected)) {
+ fprintf(stderr, "Error appending PR_UINT32_MAX + 1: Got %s\n", str.get());
+ return PR_FALSE;
+ }
+ str.Truncate();
+ str.AppendInt(maxint_plus1, 16);
+ if (!str.Equals(maxint_plus1_expected_x)) {
+ fprintf(stderr, "Error appending PR_UINT32_MAX + 1 (hex): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+
+
+ return PR_TRUE;
+ }
+
+PRBool test_findcharinset()
+ {
+ nsCString buf("hello, how are you?");
+
+ PRInt32 index = buf.FindCharInSet(",?", 5);
+ if (index != 5)
+ return PR_FALSE;
+
+ index = buf.FindCharInSet("helo", 0);
+ if (index != 0)
+ return PR_FALSE;
+
+ index = buf.FindCharInSet("z?", 6);
+ if (index != (PRInt32) buf.Length()-1)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_rfindcharinset()
+ {
+ nsCString buf("hello, how are you?");
+
+ PRInt32 index = buf.RFindCharInSet(",?", 5);
+ if (index != 5)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("helo", 0);
+ if (index != 0)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("z?", 6);
+ if (index != kNotFound)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("l", 5);
+ if (index != 3)
+ return PR_FALSE;
+
+ buf.Assign("abcdefghijkabc");
+
+ index = buf.RFindCharInSet("ab");
+ if (index != 12)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("ab", 11);
+ if (index != 11)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("ab", 10);
+ if (index != 1)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("ab", 0);
+ if (index != 0)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("cd", 1);
+ if (index != kNotFound)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("h");
+ if (index != 7)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+//----
+
+typedef PRBool (*TestFunc)();
+
+static const struct Test
+ {
+ const char* name;
+ TestFunc func;
+ }
+tests[] =
+ {
+ { "test_assign", test_assign },
+ { "test_assign_c", test_assign_c },
+ { "test1", test1 },
+ { "test2", test2 },
+ { "test_find", test_find },
+ { "test_rfind", test_rfind },
+ { "test_rfind_2", test_rfind_2 },
+ { "test_rfind_3", test_rfind_3 },
+ { "test_rfind_4", test_rfind_4 },
+ { "test_distance", test_distance },
+ { "test_length", test_length },
+ { "test_trim", test_trim },
+ { "test_replace_substr", test_replace_substr },
+ { "test_replace_substr_2", test_replace_substr_2 },
+ { "test_strip_ws", test_strip_ws },
+ { "test_equals_ic", test_equals_ic },
+ { "test_fixed_string", test_fixed_string },
+ { "test_concat", test_concat },
+ { "test_concat_2", test_concat_2 },
+ { "test_xpidl_string", test_xpidl_string },
+ { "test_empty_assign", test_empty_assign },
+ { "test_set_length", test_set_length },
+ { "test_substring", test_substring },
+ { "test_appendint64", test_appendint64 },
+ { "test_findcharinset", test_findcharinset },
+ { "test_rfindcharinset", test_rfindcharinset },
+ { nsnull, nsnull }
+ };
+
+//----
+
+int main(int argc, char **argv)
+ {
+ int count = 1;
+ if (argc > 1)
+ count = atoi(argv[1]);
+
+ while (count--)
+ {
+ for (const Test* t = tests; t->name != nsnull; ++t)
+ {
+ printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE <--");
+ }
+ }
+
+ return 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp b/src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp
new file mode 100644
index 00000000..10025a05
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "nspr.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+
+class nsRunner : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsCOMPtr<nsIThread> thread;
+ nsresult rv = nsIThread::GetCurrent(getter_AddRefs(thread));
+ if (NS_FAILED(rv)) {
+ printf("failed to get current thread\n");
+ return rv;
+ }
+ printf("running %d on thread %p\n", mNum, (void *)thread.get());
+
+ // if we don't do something slow, we'll never see the other
+ // worker threads run
+ PR_Sleep(PR_MillisecondsToInterval(100));
+
+ return rv;
+ }
+
+ nsRunner(int num) : mNum(num) {
+ }
+
+protected:
+ int mNum;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunner, nsIRunnable)
+
+nsresult
+TestThreads()
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIThread> runner;
+ rv = NS_NewThread(getter_AddRefs(runner), new nsRunner(0), 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) {
+ printf("failed to create thread\n");
+ return rv;
+ }
+
+ nsCOMPtr<nsIThread> thread;
+ rv = nsIThread::GetCurrent(getter_AddRefs(thread));
+ if (NS_FAILED(rv)) {
+ printf("failed to get current thread\n");
+ return rv;
+ }
+
+ PRThreadScope scope;
+ rv = runner->GetScope(&scope);
+ if (NS_FAILED(rv)) {
+ printf("runner already exited\n");
+ }
+
+ rv = runner->Join(); // wait for the runner to die before quitting
+ if (NS_FAILED(rv)) {
+ printf("join failed\n");
+ }
+
+ rv = runner->GetScope(&scope); // this should fail after Join
+ if (NS_SUCCEEDED(rv)) {
+ printf("get scope failed\n");
+ }
+
+ rv = runner->Interrupt(); // this should fail after Join
+ if (NS_SUCCEEDED(rv)) {
+ printf("interrupt failed\n");
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // try an unjoinable thread
+ rv = NS_NewThread(getter_AddRefs(runner), new nsRunner(1));
+ if (NS_FAILED(rv)) {
+ printf("failed to create thread\n");
+ return rv;
+ }
+
+ rv = runner->Join(); // wait for the runner to die before quitting
+ if (NS_SUCCEEDED(rv)) {
+ printf("shouldn't have been able to join an unjoinable thread\n");
+ }
+
+ PR_Sleep(PR_MillisecondsToInterval(100)); // hopefully the runner will quit here
+
+ return NS_OK;
+}
+
+class nsStressRunner : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ NS_ASSERTION(!mWasRun, "run twice!");
+ mWasRun = PR_TRUE;
+ PR_Sleep(1);
+ if (!PR_AtomicDecrement(&gNum)) {
+ printf(" last thread was %d\n", mNum);
+ }
+ return NS_OK;
+ }
+
+ nsStressRunner(int num) : mNum(num), mWasRun(PR_FALSE) {
+ PR_AtomicIncrement(&gNum);
+ }
+
+ static PRInt32 GetGlobalCount() {return gNum;}
+
+private:
+ ~nsStressRunner() {
+ NS_ASSERTION(mWasRun, "never run!");
+ }
+
+protected:
+ static PRInt32 gNum;
+ PRInt32 mNum;
+ PRBool mWasRun;
+};
+
+PRInt32 nsStressRunner::gNum = 0;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsStressRunner, nsIRunnable)
+
+static int Stress(int loops, int threads)
+{
+
+ for (int i = 0; i < loops; i++) {
+ printf("Loop %d of %d\n", i+1, loops);
+
+ int k;
+ nsIThread** array = new nsIThread*[threads];
+ NS_ASSERTION(array, "out of memory");
+
+ NS_ASSERTION(!nsStressRunner::GetGlobalCount(), "bad count of runnables");
+
+ for (k = 0; k < threads; k++) {
+ nsCOMPtr<nsIThread> t;
+ nsresult rv = NS_NewThread(getter_AddRefs(t),
+ new nsStressRunner(k),
+ 0, PR_JOINABLE_THREAD);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "can't create thread");
+ NS_ADDREF(array[k] = t);
+ }
+
+ for (k = threads-1; k >= 0; k--) {
+ array[k]->Join();
+ NS_RELEASE(array[k]);
+ }
+ delete [] array;
+ }
+ return 0;
+}
+
+PR_STATIC_CALLBACK(void) threadProc(void *arg)
+{
+ // printf(" running thread %d\n", (int) arg);
+ PR_Sleep(1);
+ PR_ASSERT(PR_JOINABLE_THREAD == PR_GetThreadState(PR_GetCurrentThread()));
+}
+
+static int StressNSPR(int loops, int threads)
+{
+
+ for (int i = 0; i < loops; i++) {
+ printf("Loop %d of %d\n", i+1, loops);
+
+ int k;
+ PRThread** array = new PRThread*[threads];
+ PR_ASSERT(array);
+
+ for (k = 0; k < threads; k++) {
+ array[k] = PR_CreateThread(PR_USER_THREAD,
+ threadProc, (void*)(uintptr_t)k,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ PR_ASSERT(array[k]);
+ }
+
+ for (k = 0; k < threads; k++) {
+ PR_ASSERT(PR_JOINABLE_THREAD == PR_GetThreadState(array[k]));
+ }
+
+ for (k = threads-1; k >= 0; k--) {
+ PR_JoinThread(array[k]);
+ }
+ delete [] array;
+ }
+ return 0;
+}
+
+
+int
+main(int argc, char** argv)
+{
+ int retval = 0;
+ nsresult rv;
+
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+
+ if (argc > 1 && !strcmp(argv[1], "-stress")) {
+ int loops;
+ int threads;
+ if (argc != 4 || *argv[2] != '-' || *argv[3] != '-' ||
+ !(loops = atoi(argv[2]+1)) || !(threads = atoi(argv[3]+1))) {
+ printf("To use -stress you must pass loop count and thread count...\n"
+ " TestThreads -stress -1000 -50\n");
+ } else {
+ printf("Running stress test with %d loops of %d threads each\n",
+ loops, threads);
+ retval = Stress(loops, threads);
+ }
+ } else if (argc > 1 && !strcmp(argv[1], "-stress-nspr")) {
+ int loops;
+ int threads;
+ if (argc != 4 || *argv[2] != '-' || *argv[3] != '-' ||
+ !(loops = atoi(argv[2]+1)) || !(threads = atoi(argv[3]+1))) {
+ printf("To use -stress-nspr you must pass loop count and thread count...\n"
+ " TestThreads -stress -1000 -50\n");
+ } else {
+ printf("Running stress test with %d loops of %d threads each\n",
+ loops, threads);
+ retval = StressNSPR(loops, threads);
+ }
+ } else {
+ rv = TestThreads();
+ if (NS_FAILED(rv)) return -1;
+ }
+
+ rv = NS_ShutdownXPCOM(nsnull);
+ if (NS_FAILED(rv)) return -1;
+ return retval;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp b/src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp
new file mode 100644
index 00000000..956f179f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "nsVoidBTree.h"
+#include "nsVoidArray.h"
+
+#define COUNT 1024
+#define POINTER(i) NS_REINTERPRET_CAST(void*, 4 + 4 * (i))
+
+static PRBool
+Equal(const nsVoidArray& aControl, const nsVoidBTree& aTest)
+{
+ if (aControl.Count() != aTest.Count()) {
+ printf("counts not equal; ");
+ return PR_FALSE;
+ }
+
+ for (PRInt32 i = aControl.Count() - 1; i >= 0; --i) {
+ if (aControl[i] != aTest[i]) {
+ printf("element %d differs; ", i);
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+
+static void
+CheckForwardEnumeration(const nsVoidArray& aControl, const nsVoidBTree& aTest)
+{
+ PRInt32 index = 0;
+
+ nsVoidBTree::ConstIterator last = aTest.Last();
+ for (nsVoidBTree::ConstIterator element = aTest.First(); element != last; ++element, ++index) {
+ if (*element != aControl[index]) {
+ printf("failed forward enumeration\n");
+ exit(-1);
+ }
+ }
+
+ if (index != aControl.Count()) {
+ printf("erratic termination during forward enumeration\n");
+ exit(-1);
+ }
+}
+
+static void
+CheckBackwardEnumeration(const nsVoidArray& aControl, const nsVoidBTree& aTest)
+{
+ PRInt32 index = aControl.Count();
+ nsVoidBTree::ConstIterator first = aTest.First();
+ nsVoidBTree::ConstIterator element = aTest.Last();
+
+ if (first != element) {
+ do {
+ if (*--element != aControl[--index]) {
+ printf("failed backward enumeration\n");
+ exit(-1);
+ }
+ } while (element != first);
+ }
+
+ if (index != 0) {
+ printf("erratic termination during backward enumeration\n");
+ exit(-1);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ nsVoidBTree btree;
+
+ PRInt32 i;
+
+ //----------------------------------------
+ // Tail fill
+ for (i = 0; i < COUNT; ++i)
+ btree.InsertElementAt(NS_REINTERPRET_CAST(void*, POINTER(i)), i);
+
+ for (i = 0; i < COUNT; ++i) {
+ if (btree[i] != POINTER(i)) {
+ printf("tail fill failed\n");
+ return -1;
+ }
+ }
+
+ printf("tail fill succeeded\n");
+
+ //----------------------------------------
+ // Tail empty
+ for (i = COUNT - 1; i >= 0; --i)
+ btree.RemoveElementAt(i);
+
+ if (btree.Count() != 0) {
+ printf("tail empty failed\n");
+ return -1;
+ }
+
+ printf("tail empty succeeded\n");
+
+ // N.B. no intervening Clear() to verify that we handle the re-use
+ // case.
+
+ //----------------------------------------
+ // Front fill
+ for (i = 0; i < COUNT; ++i)
+ btree.InsertElementAt(POINTER(i), 0);
+
+ for (i = 0; i < COUNT; ++i) {
+ if (btree[COUNT - (i + 1)] != POINTER(i)) {
+ printf("simple front fill failed\n");
+ return -1;
+ }
+ }
+
+ printf("front fill succeeded\n");
+
+ //----------------------------------------
+ // Front empty
+ for (i = COUNT - 1; i >= 0; --i)
+ btree.RemoveElementAt(0);
+
+ if (btree.Count() != 0) {
+ printf("front empty failed\n");
+ return -1;
+ }
+
+ printf("front empty succeeded\n");
+ fflush(stdout);
+
+ //----------------------------------------
+ // Test boundary conditions with small btree
+
+ {
+ printf("small btree boundary conditions ");
+ fflush(stdout);
+
+ nsVoidArray control;
+ btree.Clear();
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ btree.AppendElement(POINTER(0));
+ control.AppendElement(POINTER(0));
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ btree.AppendElement(POINTER(1));
+ control.AppendElement(POINTER(1));
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ btree.RemoveElementAt(0);
+ btree.RemoveElementAt(0);
+ control.RemoveElementAt(0);
+ control.RemoveElementAt(0);
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ printf("succeeded\n");
+ }
+
+ //----------------------------------------
+ // Iterator
+ {
+ nsVoidArray control;
+ btree.Clear();
+
+ // Fill
+ for (i = 0; i < COUNT; ++i) {
+ PRInt32 slot = i ? rand() % i : 0;
+
+ btree.InsertElementAt(POINTER(i), slot);
+ control.InsertElementAt(POINTER(i), slot);
+
+ if (! Equal(control, btree)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+
+ for (nsVoidBTree::Iterator m = btree.First(); m != btree.Last(); ++m) {
+ nsVoidBTree::Iterator n;
+ for (n = m, ++n; n != btree.Last(); ++n) {
+ if (*m > *n) {
+ void* tmp = *m;
+ *m = *n;
+ *n = tmp;
+ }
+ }
+ }
+
+ nsVoidBTree::Iterator el;
+ for (el = btree.First(), i = 0; el != btree.Last(); ++el, ++i) {
+ if (*el != POINTER(i)) {
+ printf("bubble sort failed\n");
+ return -1;
+ }
+ }
+
+ printf("iteration succeeded\n");
+ }
+
+ //----------------------------------------
+ // Random hammering
+
+ printf("random fill/empty: ");
+
+ for (PRInt32 iter = 10; iter >= 1; --iter) {
+ printf("%d ", iter);
+ fflush(stdout);
+
+ nsVoidArray control;
+ btree.Clear();
+
+ // Fill
+ for (i = 0; i < COUNT; ++i) {
+ PRInt32 slot = i ? rand() % i : 0;
+
+ btree.InsertElementAt(POINTER(i), slot);
+ control.InsertElementAt(POINTER(i), slot);
+
+ if (! Equal(control, btree)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+
+ // IndexOf
+ for (i = 0; i < COUNT; ++i) {
+ void* element = control[i];
+ if (btree.IndexOf(element) != i) {
+ printf("failed IndexOf at %d\n", i);
+ return -1;
+ }
+ }
+
+ // Backward enumeration
+ CheckBackwardEnumeration(control, btree);
+
+ // Forward enumeration
+ CheckForwardEnumeration(control, btree);
+
+ // Empty
+ for (i = COUNT - 1; i >= 0; --i) {
+ PRInt32 slot = i ? rand() % i : 0;
+
+ btree.RemoveElementAt(slot);
+ control.RemoveElementAt(slot);
+
+ if (! Equal(control, btree)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+ }
+
+ printf("succeeded\n");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp b/src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp
new file mode 100644
index 00000000..f2802e1f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp
@@ -0,0 +1,18 @@
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsXPIDLString.h"
+
+static void
+nsXPIDLStringTest_Value(PRUnichar** aResult)
+{
+ *aResult = ToNewUnicode(NS_LITERAL_STRING("Hello, World"));
+}
+
+int
+main(int argc, char* argv[])
+{
+ nsXPIDLString s1;
+ nsXPIDLStringTest_Value(getter_Copies(s1));
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in
new file mode 100644
index 00000000..c17318c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in
@@ -0,0 +1,61 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+IS_COMPONENT = 1
+MODULE_NAME = nsTestDynamicModule
+MODULE = xpcom
+LIBRARY_NAME = testdynamic
+SHORT_LIBNAME = tdynamic
+
+CPPSRCS = TestDynamic.cpp
+
+include $(topsrcdir)/config/config.mk
+
+LOCAL_INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../public
+
+include $(topsrcdir)/config/rules.mk
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp b/src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp
new file mode 100644
index 00000000..a27d8ea9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Suresh Duddi <dp@netscape.com>
+ * Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include "TestFactory.h"
+#include "nsIGenericFactory.h"
+
+/**
+ * ITestClass implementation
+ */
+
+class TestDynamicClassImpl: public ITestClass {
+ NS_DECL_ISUPPORTS
+
+ TestDynamicClassImpl() {
+ }
+ void Test();
+};
+
+NS_IMPL_ISUPPORTS1(TestDynamicClassImpl, ITestClass)
+
+void TestDynamicClassImpl::Test() {
+ printf("hello, dynamic world!\n");
+}
+
+/**
+ * Generic Module
+ */
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(TestDynamicClassImpl)
+
+static const nsModuleComponentInfo components[] =
+{
+ { "Test Dynamic", NS_TESTLOADEDFACTORY_CID, NS_TESTLOADEDFACTORY_CONTRACTID,
+ TestDynamicClassImplConstructor
+ }
+};
+
+NS_IMPL_NSGETMODULE(nsTestDynamicModule, components)
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order b/src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order
new file mode 100644
index 00000000..bf181a81
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order
@@ -0,0 +1 @@
+_NSGetModule ; 1
diff --git a/src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp b/src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp
new file mode 100644
index 00000000..a5f3551d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp
@@ -0,0 +1,95 @@
+#include "nsILocalFile.h"
+#include "nsDependentString.h"
+#include "nsString.h"
+
+#include <stdio.h>
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+#include "nsISimpleEnumerator.h"
+
+
+PRBool LoopInDir(nsILocalFile* file)
+{
+ nsresult rv;
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = file->GetDirectoryEntries(getter_AddRefs(entries));
+ if(NS_FAILED(rv) || !entries)
+ return PR_FALSE;
+
+ PRBool hasMore;
+ while(NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> sup;
+ entries->GetNext(getter_AddRefs(sup));
+ if(!sup)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> file = do_QueryInterface(sup);
+ if(!file)
+ return PR_FALSE;
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ PRBool isDir;
+ printf("%s\n", name.get());
+ rv = file->IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ {
+ printf("IsDirectory Failed!!!\n");
+ return PR_FALSE;
+ }
+
+ if (isDir == PR_TRUE)
+ {
+ nsCOMPtr<nsILocalFile> lfile = do_QueryInterface(file);
+ LoopInDir(lfile);
+ }
+ }
+ return PR_TRUE;
+}
+
+
+int
+main(int argc, char* argv[])
+{
+ nsresult rv;
+ {
+ nsCOMPtr<nsILocalFile> topDir;
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->AutoRegister(nsnull);
+
+ if (argc > 1 && argv[1] != nsnull)
+ {
+ char* pathStr = argv[1];
+ NS_NewNativeLocalFile(nsDependentCString(pathStr), PR_FALSE, getter_AddRefs(topDir));
+ }
+
+ if (!topDir)
+ {
+ printf("No Top Dir\n");
+ return -1;
+ }
+ PRInt32 startTime = PR_IntervalNow();
+
+ LoopInDir(topDir);
+
+ PRInt32 endTime = PR_IntervalNow();
+
+ printf("\nTime: %d\n", PR_IntervalToMilliseconds(endTime - startTime));
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp b/src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp
new file mode 100644
index 00000000..1dd2cd54
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp
@@ -0,0 +1,475 @@
+#include "nsILocalFile.h"
+#if 0 /* too new */
+#include "nsStringGlue.h"
+#else
+#include "nsString.h"
+#endif
+
+#include <stdio.h>
+#include "nsXPCOM.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsIMemory.h"
+
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+
+void Passed();
+void Failed(const char* explanation = nsnull);
+void Inspect();
+void Banner(const char* bannerString);
+
+void VerifyResult(nsresult rv)
+{
+ if (NS_FAILED(rv))
+ {
+ Failed("rv failed");
+ printf("rv = %d\n", rv);
+ }
+}
+//----------------------------------------------------------------------------
+void Banner(const char* bannerString)
+//----------------------------------------------------------------------------
+{
+ printf("---------------------------\n");
+ printf("%s\n", bannerString);
+ printf("---------------------------\n");
+}
+
+//----------------------------------------------------------------------------
+void Passed()
+//----------------------------------------------------------------------------
+{
+ printf("Test passed.");
+}
+
+//----------------------------------------------------------------------------
+void Failed(const char* explanation)
+//----------------------------------------------------------------------------
+{
+ printf("ERROR : Test failed.\n");
+ printf("REASON: %s.\n", explanation);
+}
+
+//----------------------------------------------------------------------------
+void Inspect()
+//----------------------------------------------------------------------------
+{
+ printf("^^^^^^^^^^ PLEASE INSPECT OUTPUT FOR ERRORS\n");
+}
+
+void GetPaths(nsILocalFile* file)
+{
+ nsresult rv;
+ nsCAutoString pathName;
+
+ printf("Getting Path\n");
+
+ rv = file->GetNativePath(pathName);
+ VerifyResult(rv);
+
+ printf("filepath: %s\n", pathName.get());
+}
+
+void InitTest(const char* creationPath, const char* appendPath)
+{
+ nsILocalFile* file = nsnull;
+ nsresult rv = CallCreateInstance(NS_LOCAL_FILE_CONTRACTID, &file);
+
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ nsCAutoString leafName;
+
+ Banner("InitWithPath");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Getting Filename\n");
+ rv = file->GetNativeLeafName(leafName);
+ printf(" %s\n", leafName.get());
+ VerifyResult(rv);
+
+ printf("Appending %s \n", appendPath);
+ rv = file->AppendNative(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Getting Filename\n");
+ rv = file->GetNativeLeafName(leafName);
+ printf(" %s\n", leafName.get());
+ VerifyResult(rv);
+
+ GetPaths(file);
+
+
+ printf("Check For Existence\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ NS_RELEASE(file);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+}
+
+
+void CreationTest(const char* creationPath, const char* appendPath,
+ PRInt32 whatToCreate, PRInt32 perm)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ Banner("Creation Test");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Appending %s\n", appendPath);
+ rv = file->AppendRelativeNativePath(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Check For Existence\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+
+
+ rv = file->Create(whatToCreate, perm);
+ VerifyResult(rv);
+
+ rv = file->Exists(&exists);
+ VerifyResult(rv);
+
+
+ if (!exists)
+ {
+ Failed("Did not create file system object!");
+ return;
+ }
+
+}
+
+void CreateUniqueTest(const char* creationPath, const char* appendPath,
+ PRInt32 whatToCreate, PRInt32 perm)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ Banner("Creation Test");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Appending %s\n", appendPath);
+ rv = file->AppendNative(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Check For Existence\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+
+
+ rv = file->CreateUnique(whatToCreate, perm);
+ VerifyResult(rv);
+
+ rv = file->Exists(&exists);
+ VerifyResult(rv);
+
+
+ if (!exists)
+ {
+ Failed("Did not create file system object!");
+ return;
+ }
+
+}
+
+
+void
+CopyTest(const char *testFile, const char *targetDir)
+{
+ printf("start copy test\n");
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = file->InitWithNativePath(nsDependentCString(testFile));
+ VerifyResult(rv);
+
+ nsCOMPtr<nsILocalFile> dir =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!dir))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = dir->InitWithNativePath(nsDependentCString(targetDir));
+ VerifyResult(rv);
+
+ rv = file->CopyTo(dir, EmptyString());
+ VerifyResult(rv);
+
+ printf("end copy test\n");
+}
+
+void
+DeletionTest(const char* creationPath, const char* appendPath, PRBool recursive)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ Banner("Deletion Test");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Appending %s\n", appendPath);
+ rv = file->AppendNative(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Check For Existance\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+
+ rv = file->Remove(recursive);
+ VerifyResult(rv);
+
+ rv = file->Exists(&exists);
+ VerifyResult(rv);
+
+ if (exists)
+ {
+ Failed("Did not create delete system object!");
+ return;
+ }
+
+}
+
+void
+MoveTest(const char *testFile, const char *targetDir)
+{
+ Banner("Move Test");
+
+ printf("start move test\n");
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!file)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = file->InitWithNativePath(nsDependentCString(testFile));
+ VerifyResult(rv);
+
+ nsCOMPtr<nsILocalFile> dir(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!dir)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = dir->InitWithNativePath(nsDependentCString(targetDir));
+ VerifyResult(rv);
+
+ rv = file->MoveToNative(dir, NS_LITERAL_CSTRING("newtemp"));
+ VerifyResult(rv);
+ if (NS_FAILED(rv))
+ {
+ printf("MoveToNative() test Failed.\n");
+ }
+ printf("end move test\n");
+}
+
+// move up the number of directories in moveUpCount, then append "foo/bar"
+void
+NormalizeTest(const char *testPath, int moveUpCount,
+ const char *expected)
+{
+ Banner("Normalize Test");
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!file)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = file->InitWithNativePath(nsDependentCString(testPath));
+ VerifyResult(rv);
+
+ nsCOMPtr<nsIFile> parent;
+ nsAutoString path;
+ for (int i=0; i < moveUpCount; i++)
+ {
+ rv = file->GetParent(getter_AddRefs(parent));
+ VerifyResult(rv);
+ rv = parent->GetPath(path);
+ VerifyResult(rv);
+ rv = file->InitWithPath(path);
+ VerifyResult(rv);
+ }
+
+ if (!parent) {
+ printf("Getting parent failed!\n");
+ return;
+ }
+
+ rv = parent->Append(NS_LITERAL_STRING("foo"));
+ VerifyResult(rv);
+ rv = parent->Append(NS_LITERAL_STRING("bar"));
+ VerifyResult(rv);
+
+ rv = parent->Normalize();
+ VerifyResult(rv);
+
+ nsCAutoString newPath;
+ rv = parent->GetNativePath(newPath);
+ VerifyResult(rv);
+
+ nsCOMPtr<nsILocalFile>
+ expectedFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!expectedFile)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+ rv = expectedFile->InitWithNativePath(nsDependentCString(expected));
+ VerifyResult(rv);
+
+ rv = expectedFile->Normalize();
+ VerifyResult(rv);
+
+ nsCAutoString expectedPath;
+ rv = expectedFile->GetNativePath(expectedPath);
+ VerifyResult(rv);
+
+ if (!newPath.Equals(expectedPath)) {
+ printf("ERROR: Normalize() test Failed!\n");
+ printf(" Got: %s\n", newPath.get());
+ printf("Expected: %s\n", expectedPath.get());
+ }
+
+ printf("end normalize test.\n");
+}
+
+int main(void)
+{
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ InitTest("c:\\temp\\", "sub1/sub2/"); // expect failure
+ InitTest("d:\\temp\\", "sub1\\sub2\\"); // expect failure
+
+ CreationTest("c:\\temp\\", "file.txt", nsIFile::NORMAL_FILE_TYPE, 0644);
+ DeletionTest("c:\\temp\\", "file.txt", PR_FALSE);
+
+ MoveTest("c:\\newtemp\\", "d:");
+
+ CreationTest("c:\\temp\\", "mumble\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\", nsIFile::DIRECTORY_TYPE, 0644);
+ DeletionTest("c:\\temp\\", "mumble", PR_TRUE);
+
+ CreateUniqueTest("c:\\temp\\", "foo", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CreateUniqueTest("c:\\temp\\", "foo", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CreateUniqueTest("c:\\temp\\", "bar.xx", nsIFile::DIRECTORY_TYPE, 0644);
+ CreateUniqueTest("c:\\temp\\", "bar.xx", nsIFile::DIRECTORY_TYPE, 0644);
+ DeletionTest("c:\\temp\\", "foo", PR_TRUE);
+ DeletionTest("c:\\temp\\", "foo-1", PR_TRUE);
+ DeletionTest("c:\\temp\\", "bar.xx", PR_TRUE);
+ DeletionTest("c:\\temp\\", "bar-1.xx", PR_TRUE);
+
+#else
+#ifdef XP_UNIX
+ InitTest("/tmp/", "sub1/sub2/"); // expect failure
+
+ CreationTest("/tmp", "file.txt", nsIFile::NORMAL_FILE_TYPE, 0644);
+ DeletionTest("/tmp/", "file.txt", PR_FALSE);
+
+ CreationTest("/tmp", "mumble/a/b/c/d/e/f/g/h/i/j/k/", nsIFile::DIRECTORY_TYPE, 0644);
+ DeletionTest("/tmp", "mumble", PR_TRUE);
+
+ CreationTest("/tmp", "file", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CopyTest("/tmp/file", "/tmp/newDir");
+ MoveTest("/tmp/file", "/tmp/newDir/anotherNewDir");
+ DeletionTest("/tmp", "newDir", PR_TRUE);
+
+ CreationTest("/tmp", "qux/quux", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CreationTest("/tmp", "foo/bar", nsIFile::NORMAL_FILE_TYPE, 0644);
+ NormalizeTest("/tmp/qux/quux/..", 1, "/tmp/foo/bar");
+ DeletionTest("/tmp", "qux", PR_TRUE);
+ DeletionTest("/tmp", "foo", PR_TRUE);
+
+#endif /* XP_UNIX */
+#endif /* XP_WIN || XP_OS2 */
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/resources.h b/src/libs/xpcom18a4/xpcom/tests/resources.h
new file mode 100644
index 00000000..b82df25e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/resources.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Waterson <waterson@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef resources_h___
+#define resources_h___
+
+#define TIMER_1SECOND 40000
+#define TIMER_5SECOND 40001
+#define TIMER_10SECOND 40002
+
+#define TIMER_1REPEAT 40003
+#define TIMER_5REPEAT 40004
+#define TIMER_10REPEAT 40005
+
+#define TIMER_CANCEL 40006
+#define TIMER_EXIT 40010
+
+#endif /* resources_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/services/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/services/Makefile.in
new file mode 100644
index 00000000..84cd3c84
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/Makefile.in
@@ -0,0 +1,58 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+IS_COMPONENT = 1
+MODULE_NAME = MyService
+LIBRARY_NAME = MyService
+SHORT_LIBNAME = MyServce
+
+CPPSRCS = MyService.cpp
+
+LOCAL_INCLUDES = -I$(srcdir)/..
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp b/src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp
new file mode 100644
index 00000000..aec78449
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "MyService.h"
+#include "nsIServiceManager.h"
+#include "nsIGenericFactory.h"
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+class MyService : public IMyService {
+public:
+
+ NS_IMETHOD
+ Doit(void);
+
+ MyService();
+ NS_DECL_ISUPPORTS
+
+private:
+ ~MyService();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// MyService Implementation
+
+NS_IMPL_ISUPPORTS1(MyService, IMyService)
+
+MyService::MyService()
+{
+ printf(" creating my service\n");
+}
+
+MyService::~MyService()
+{
+ printf(" destroying my service\n");
+}
+
+nsresult
+MyService::Doit(void)
+{
+ printf(" invoking my service\n");
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MyServiceFactory Implementation
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(MyService)
+
+static const nsModuleComponentInfo myService_components[] = {
+ { "MyService", NS_IMYSERVICE_CID, nsnull, MyServiceConstructor },
+};
+
+NS_IMPL_NSGETMODULE(MyService, myService_components)
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/MyService.h b/src/libs/xpcom18a4/xpcom/tests/services/MyService.h
new file mode 100644
index 00000000..30b0e30a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/MyService.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MyService_h__
+#define MyService_h__
+
+#include "nsISupports.h"
+
+#define NS_IMYSERVICE_IID \
+{ /* fedc3380-3648-11d2-8163-006008119d7a */ \
+ 0xfedc3380, \
+ 0x3648, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+class IMyService : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMYSERVICE_IID)
+
+ NS_IMETHOD
+ Doit(void) = 0;
+
+};
+
+#define NS_IMYSERVICE_CID \
+{ /* 34876550-364b-11d2-8163-006008119d7a */ \
+ 0x34876550, \
+ 0x364b, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+#endif // MyService_h__
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/win32.order b/src/libs/xpcom18a4/xpcom/tests/services/win32.order
new file mode 100644
index 00000000..132a4357
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/win32.order
@@ -0,0 +1 @@
+_NSCanUnload ; 1
diff --git a/src/libs/xpcom18a4/xpcom/tests/test.properties b/src/libs/xpcom18a4/xpcom/tests/test.properties
new file mode 100644
index 00000000..4ed37783
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/test.properties
@@ -0,0 +1,46 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+1=1
+ 2=2
+3 =3
+ 4 =4
+5=5
+6= 6
+7=7
+8= 8
+# this is a comment
+9=this is the first part of a continued line \
+ and here is the 2nd part
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp b/src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp
new file mode 100644
index 00000000..13942f3b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsError.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+ int errorCode = 0;
+ char buffer[100];
+
+ if (argc != 2)
+ return -1;
+
+ sscanf( argv[1], "0x%x", &errorCode);
+ sprintf(buffer, "%d", errorCode);
+ sscanf( buffer, "%d", &errorCode);
+
+ printf( "Code: %d, Module: %d, Severity: %d\n",
+ NS_ERROR_GET_CODE(errorCode),
+ NS_ERROR_GET_MODULE(errorCode),
+ NS_ERROR_GET_SEVERITY(errorCode));
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/cp.js b/src/libs/xpcom18a4/xpcom/tests/utils/cp.js
new file mode 100644
index 00000000..a38c120b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/cp.js
@@ -0,0 +1,111 @@
+const nsILocalFile = Components.interfaces.nsILocalFile;
+var prefix = "";
+
+function rename(source, newName)
+{
+ try {
+ var sourceFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ sourceFile.initWithPath(source);
+
+ }
+ catch (e) {
+ dump("Could not create nsILocalFile\n");
+ }
+
+
+ try {
+ sourceFile.copyTo(null, newName);
+ }
+ catch (e) {
+ dump("error coping" + e + "\n");
+ }
+}
+
+
+function cp(source, dest, followLinks, newName)
+{
+ try {
+ var sourceFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ sourceFile.initWithPath(source);
+
+ var destFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ destFile.initWithPath(dest);
+
+ }
+ catch (e) {
+ dump("Could not create nsILocalFile\n");
+ }
+
+ try {
+
+ if (! destFile.isDirectory())
+ {
+ dump("destination not a directory!\n");
+ return;
+ }
+ }
+ catch (e) {
+ dump("error accessing dest");
+ }
+
+ try {
+ if (followLinks)
+ {
+ sourceFile.copyToFollowingLinks(destFile, newName);
+ }
+ else
+ {
+ sourceFile.copyTo(destFile, newName);
+ }
+ }
+ catch (e) {
+ dump("error coping" + e + "\n");
+ }
+}
+
+
+function mv(source, dest, followLinks, newName)
+{
+ try {
+ var sourceFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ sourceFile.initWithPath(source);
+
+ var destFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ destFile.initWithPath(dest);
+
+ }
+ catch (e) {
+ dump("Could not create nsILocalFile\n");
+ }
+
+ try {
+
+ if (! destFile.isDirectory())
+ {
+ dump("destination not a directory!\n");
+ return;
+ }
+ }
+ catch (e) {
+ dump("error accessing dest");
+ }
+
+ try {
+ if (followLinks)
+ {
+ sourceFile.moveToFollowingLinks(destFile, newName);
+ }
+ else
+ {
+ sourceFile.moveTo(destFile, newName);
+ }
+ }
+ catch (e) {
+ dump("error coping" + e + "\n");
+ }
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/dirs.js b/src/libs/xpcom18a4/xpcom/tests/utils/dirs.js
new file mode 100644
index 00000000..c3fc2479
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/dirs.js
@@ -0,0 +1,155 @@
+function dumpPathOfProperty(prop)
+{
+ dump(prop +' = ');
+
+ try
+ {
+ var file = dsprops.get(prop, Components.interfaces.nsIFile);
+ dump(file.path + '\n');
+ }
+ catch (ar)
+ {
+ dump('undefined or error \n');
+ }
+}
+
+var dscontractid = "@mozilla.org/file/directory_service;1"; // XXX old-style
+var ds = Components.classes[dscontractid].getService();
+var dsprops = ds.QueryInterface(Components.interfaces.nsIProperties);
+
+dump("xpcom locations::\n");
+// XPCOM Locations:
+ dumpPathOfProperty ("xpcom.currentProcess");
+ dumpPathOfProperty ("xpcom.currentProcess.componentRegistry");
+ dumpPathOfProperty ("xpcom.currentProcess.componentDirectory");
+ dumpPathOfProperty ("system.OS_DriveDirectory");
+ dumpPathOfProperty ("system.OS_TemporaryDirectory");
+ dumpPathOfProperty ("system.OS_CurrentProcessDirectory");
+ dumpPathOfProperty ("system.OS_CurrentWorkingDirectory");
+
+dump("Mac locations::\n");
+// Mac
+ dumpPathOfProperty ("system.SystemDirectory");
+ dumpPathOfProperty ("system.DesktopDirectory");
+ dumpPathOfProperty ("system.TrashDirectory");
+ dumpPathOfProperty ("system.StartupDirectory");
+ dumpPathOfProperty ("system.ShutdownDirectory");
+ dumpPathOfProperty ("system.AppleMenuDirectory");
+ dumpPathOfProperty ("system.ControlPanelDirectory");
+ dumpPathOfProperty ("system.ExtensionDirectory");
+ dumpPathOfProperty ("system.FontsDirectory");
+ dumpPathOfProperty ("system.PreferencesDirectory");
+ dumpPathOfProperty ("system.DocumentsDirectory");
+ dumpPathOfProperty ("system.InternetSearchDirectory");
+
+dump("PC locations::\n");
+// PC
+ dumpPathOfProperty ("system.SystemDirectory");
+ dumpPathOfProperty ("system.WindowsDirectory");
+ dumpPathOfProperty ("system.HomeDirectory");
+ dumpPathOfProperty ("system.Desktop");
+ dumpPathOfProperty ("system.Programs");
+ dumpPathOfProperty ("system.Controls");
+ dumpPathOfProperty ("system.Printers");
+ dumpPathOfProperty ("system.Personal");
+ dumpPathOfProperty ("system.Favorites");
+ dumpPathOfProperty ("system.Startup");
+ dumpPathOfProperty ("system.Recent");
+ dumpPathOfProperty ("system.Sendto");
+ dumpPathOfProperty ("system.Bitbucket");
+ dumpPathOfProperty ("system.Startmenu");
+ dumpPathOfProperty ("system.Desktopdirectory");
+ dumpPathOfProperty ("system.Drives");
+ dumpPathOfProperty ("system.Network");
+ dumpPathOfProperty ("system.Nethood");
+ dumpPathOfProperty ("system.Fonts");
+ dumpPathOfProperty ("system.Templates");
+ dumpPathOfProperty ("system.Common_Startmenu");
+ dumpPathOfProperty ("system.Common_Programs");
+ dumpPathOfProperty ("system.Common_Startup");
+ dumpPathOfProperty ("system.Common_Desktopdirectory");
+ dumpPathOfProperty ("system.Appdata");
+ dumpPathOfProperty ("system.Printhood");
+
+dump("Unix locations::\n");
+// Unix
+
+ dumpPathOfProperty ("system.LocalDirectory");
+ dumpPathOfProperty ("system.LibDirectory");
+ dumpPathOfProperty ("system.HomeDirectory");
+
+dump("Beos locations::\n");
+// Beos
+
+ dumpPathOfProperty ("system.SettingsDirectory");
+ dumpPathOfProperty ("system.HomeDirectory");
+ dumpPathOfProperty ("system.DesktopDirectory");
+ dumpPathOfProperty ("system.SystemDirectory");
+
+dump("OS2 locations::\n");
+// OS2
+ dumpPathOfProperty ("system.SystemDirectory");
+ dumpPathOfProperty ("system.OS2Directory");
+ dumpPathOfProperty ("system.DesktopDirectory");
+
+
+// XPFE locations:
+
+
+// application Directories:
+ dumpPathOfProperty ("app.res.directory");
+ dumpPathOfProperty ("app.defaults.directory");
+ dumpPathOfProperty ("app.chrome.directory");
+ dumpPathOfProperty ("app.chrome.user.directory");
+ dumpPathOfProperty ("app.plugins.directory");
+
+// application Files:
+
+ dumpPathOfProperty ("app.registry.file.4");
+ dumpPathOfProperty ("app.registry.file.5");
+ dumpPathOfProperty ("app.local.store.file.5");
+ dumpPathOfProperty ("app.history.file.5");
+ dumpPathOfProperty ("app.user.panels.5");
+
+// Preferences:
+
+// dumpPathOfProperty ("app.prefs.directory.3");
+// dumpPathOfProperty ("app.prefs.directory.4");
+ dumpPathOfProperty ("app.prefs.directory.5");
+ dumpPathOfProperty ("app.pref.default.directory.5");
+
+// dumpPathOfProperty ("app.prefs.file.3");
+// dumpPathOfProperty ("app.prefs.file.4");
+ dumpPathOfProperty ("app.prefs.file.5");
+
+// Profile:
+
+// dumpPathOfProperty ("app.profile.user.directory.3");
+// dumpPathOfProperty ("app.profile.user.directory.4");
+ dumpPathOfProperty ("app.profile.user.directory.5");
+// dumpPathOfProperty ("app.profile.default.user.directory.3");
+// dumpPathOfProperty ("app.profile.default.user.directory.4");
+ dumpPathOfProperty ("app.profile.default.user.directory.5");
+// dumpPathOfProperty ("app.profile.defaults.directory.3");
+// dumpPathOfProperty ("app.profile.defaults.directory.4");
+ dumpPathOfProperty ("app.profile.defaults.directory.5");
+
+
+
+// Bookmarks:
+
+// dumpPathOfProperty ("app.bookmark.file.3");
+// dumpPathOfProperty ("app.bookmark.file.4");
+ dumpPathOfProperty ("app.bookmark.file.5");
+
+// Search
+ dumpPathOfProperty ("app.search.file.5");
+ dumpPathOfProperty ("app.search.directory.5");
+
+
+// MailNews:
+
+ dumpPathOfProperty ("app.mail.directory.5");
+ dumpPathOfProperty ("app.mail.imap.directory.5");
+ dumpPathOfProperty ("app.mail.news.directory.5");
+ dumpPathOfProperty ("app.mail.messenger.cache.directory.5");
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/ls.js b/src/libs/xpcom18a4/xpcom/tests/utils/ls.js
new file mode 100644
index 00000000..8ae62f06
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/ls.js
@@ -0,0 +1,64 @@
+const nsILocalFile = Components.interfaces.nsILocalFile;
+var prefix = "";
+
+function ls(path, recur)
+{
+ var file = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ try {
+ file.initWithPath( path );
+
+ if (file.isDirectory() && arguments.length == 1)
+ ls_dir(file, recur);
+ else
+ ls_file(file, recur);
+ }
+ catch (e) {
+ dump("Error Returned " + e + "\n");
+ }
+}
+function ls_file(file, recur)
+{
+ dump(prefix);
+
+ try {
+ if (file.isDirectory()) {
+ dump("directory " + file.leafName + "\n");
+ if(recur)
+ ls_dir(file, true);
+ return;
+ }
+
+ dump(file.leafName + " " + file.fileSize);
+ if (file.isSymlink())
+ dump(" -> " + file.target);
+ dump("\n");
+ }
+
+ catch (e) {
+ dump(file.leafName + " (error accessing)\n");
+ }
+}
+
+function ls_dir(file, recur)
+{
+ var leafName = file.leafName;
+
+ var old = prefix;
+ prefix = prefix + " ";
+
+ iter = file.directoryEntries;
+ dump(iter + "\n");
+
+ foreach_iter(iter,
+ function (file) { ls_file(file, recur); });
+ prefix = old;
+}
+
+function foreach_iter(iter, fun)
+{
+ while (iter.hasMoreElements()) {
+ var item = iter.getNext().QueryInterface(nsILocalFile);
+ fun(item);
+ }
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in
new file mode 100644
index 00000000..8bd782c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+REQUIRES = string
+
+CPPSRCS = TestCOM.cpp
+#TestHelloXPLoop.cpp nsStringTest.cpp
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+include $(topsrcdir)/config/rules.mk
+
+OS_LIBS = $(call EXPAND_LIBNAME,rpcrt4 uuid)
+
+LIBS = $(XPCOM_LIBS) $(NSPR_LIBS)
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp b/src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp
new file mode 100644
index 00000000..b76eccb4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <windows.h>
+#include <unknwn.h>
+#include <stdio.h>
+#include "nsISupports.h"
+#include "nsIFactory.h"
+
+// unknwn.h is needed to build with WIN32_LEAN_AND_MEAN
+#include <unknwn.h>
+
+// {5846BA30-B856-11d1-A98A-00805F8A7AC4}
+#define NS_ITEST_COM_IID \
+{ 0x5846ba30, 0xb856, 0x11d1, \
+ { 0xa9, 0x8a, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+class nsITestCom: public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITEST_COM_IID)
+ NS_IMETHOD Test() = 0;
+};
+
+/*
+ * nsTestCom
+ */
+
+class nsTestCom: public nsITestCom {
+ NS_DECL_ISUPPORTS
+
+public:
+ nsTestCom() {
+ }
+
+ NS_IMETHOD Test() {
+ printf("Accessed nsITestCom::Test() from COM\n");
+ return NS_OK;
+ }
+
+private:
+ ~nsTestCom() {
+ printf("nsTestCom instance successfully deleted\n");
+ }
+};
+
+NS_IMPL_QUERY_INTERFACE1(nsTestCom, nsITestCom)
+
+nsrefcnt nsTestCom::AddRef()
+{
+ nsrefcnt res = ++mRefCnt;
+ NS_LOG_ADDREF(this, mRefCnt, "nsTestCom", sizeof(*this));
+ printf("nsTestCom: Adding ref = %d\n", res);
+ return res;
+}
+
+nsrefcnt nsTestCom::Release()
+{
+ nsrefcnt res = --mRefCnt;
+ NS_LOG_RELEASE(this, mRefCnt, "nsTestCom");
+ printf("nsTestCom: Releasing = %d\n", res);
+ if (res == 0) {
+ delete this;
+ }
+ return res;
+}
+
+class nsTestComFactory: public nsIFactory {
+ NS_DECL_ISUPPORTS
+public:
+ nsTestComFactory() {
+ }
+
+ NS_IMETHOD CreateInstance(nsISupports *aOuter,
+ const nsIID &aIID,
+ void **aResult);
+
+ NS_IMETHOD LockFactory(PRBool aLock) {
+ printf("nsTestComFactory: ");
+ printf("%s", (aLock == PR_TRUE ? "Locking server" : "Unlocking server"));
+ printf("\n");
+ return S_OK;
+ }
+};
+
+NS_IMPL_ISUPPORTS1(nsTestComFactory, nsIFactory)
+
+nsresult nsTestComFactory::CreateInstance(nsISupports *aOuter,
+ const nsIID &aIID,
+ void **aResult)
+{
+ if (aOuter != NULL) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ nsTestCom *t = new nsTestCom();
+
+ if (t == NULL) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(t);
+ nsresult res = t->QueryInterface(aIID, aResult);
+ NS_RELEASE(t);
+
+ if (NS_SUCCEEDED(res)) {
+ printf("nsTestComFactory: successfully created nsTestCom instance\n");
+ }
+
+ return res;
+}
+
+/*
+ * main
+ */
+
+int main(int argc, char *argv[])
+{
+ nsTestComFactory *inst = new nsTestComFactory();
+ IClassFactory *iFactory;
+ inst->QueryInterface(NS_GET_IID(nsIFactory), (void **) &iFactory);
+
+ IUnknown *iUnknown;
+ nsITestCom *iTestCom;
+
+ nsresult res;
+ iFactory->LockServer(TRUE);
+ res = iFactory->CreateInstance(NULL,
+ IID_IUnknown,
+ (void **) &iUnknown);
+ iFactory->LockServer(FALSE);
+
+ GUID testGUID = NS_ITEST_COM_IID;
+ HRESULT hres;
+ hres= iUnknown->QueryInterface(testGUID,
+ (void **) &iTestCom);
+
+ iTestCom->Test();
+
+ iUnknown->Release();
+ iTestCom->Release();
+ iFactory->Release();
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp b/src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp
new file mode 100644
index 00000000..fdfa1218
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Travis Bogard <travis@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+#include "nsCNativeApp.h"
+#include "nsIEventLoop.h"
+#include <windows.h>
+
+static NS_DEFINE_CID(kNativeAppCID, NS_NATIVE_APP_CID);
+
+LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void ErrorBox(LPSTR text)
+{
+ MessageBox(NULL, text, "XP Event Loop", MB_OK | MB_ICONSTOP);
+}
+
+void InfoBox(LPSTR text)
+{
+ MessageBox(NULL, text, "XP Event Loop", MB_OK | MB_ICONINFORMATION);
+}
+
+int WINAPI WinMain(HINSTANCE inst,
+ HINSTANCE prevInstance,
+ LPSTR lpszCmdLine,
+ int nShowCmd)
+{
+ char* lpszAppName = "HelloWorld";
+ HWND wnd;
+ WNDCLASSEX wndclass;
+ int retCode;
+
+ { // Needed to scope all nsCOMPtr within XPCOM Init and Shutdown
+ nsresult rv;
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if(NS_FAILED(rv))
+ {
+ ErrorBox("Failed to initalize xpcom.");
+ return -1;
+ }
+
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ nsCOMPtr<nsINativeApp> nativeAppService(do_GetService(kNativeAppCID, &rv));
+
+ if(NS_FAILED(rv))
+ {
+ ErrorBox("Failed to get nativeAppService");
+ return -1;
+ }
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = inst;
+ wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = lpszAppName;
+ wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+
+ RegisterClassEx(&wndclass) ;
+
+ wnd = CreateWindow(lpszAppName, "The Hello World",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, inst, NULL);
+
+ ShowWindow(wnd, nShowCmd);
+ UpdateWindow(wnd);
+
+ nsCOMPtr<nsIEventLoop> eventLoop;
+
+ if(NS_FAILED(nativeAppService->CreateEventLoop(L"_MainLoop",
+ nsEventLoopTypes::MainAppLoop, getter_AddRefs(eventLoop))))
+ {
+ ErrorBox("Failed to create event Loop");
+ return 0;
+ }
+
+ eventLoop->Run(nsnull, nsnull, nsnull, &retCode);
+ eventLoop = nsnull; // Clear out before Shutting down XPCOM
+
+ InfoBox("Hello World app is out of loop");
+ }
+ NS_ShutdownXPCOM(nsnull);
+ InfoBox("Hello World app is exiting");
+ return retCode;
+}
+
+LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+
+ switch(msg)
+ {
+ case WM_PAINT:
+ hdc = BeginPaint(wnd, &ps);
+
+ GetClientRect(wnd, &rect);
+
+ DrawText(hdc, "Hello, XP Event Loop!", -1, &rect,
+ DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+
+ EndPaint(wnd, &ps);
+ return 0;
+
+ case WM_DESTROY:
+ {
+ nsresult rv;
+ nsCOMPtr<nsINativeApp> nativeAppService =
+ do_GetService(kNativeAppCID, &rv);
+ if(NS_FAILED(rv))
+ {
+ ErrorBox("Could not get NativeAppService");
+ return 0;
+ }
+ nsCOMPtr<nsIEventLoop> eventLoop;
+
+ if(NS_FAILED(nativeAppService->FindEventLoop(L"_MainLoop",
+ getter_AddRefs(eventLoop))))
+ {
+ ErrorBox("Failed to find event Loop");
+ return 0;
+ }
+ eventLoop->Exit(0);
+ }
+ return 0;
+ }
+
+ return DefWindowProc(wnd, msg, wParam, lParam);
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp
new file mode 100644
index 00000000..6719ed38
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp
@@ -0,0 +1,33 @@
+
+#include <iostream.h>
+#include "nsStr.h"
+#include "nsStringTest2.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+int main(){
+
+ nsString temp("\t\t\n\r\n\r25,* \t \n\n \t");
+ temp.CompressWhitespace();
+
+ nsString temp1("\t\t\n\r\n\r25,* \t \n\n \t");
+ temp1.CompressSet("\t\n\r ",' ',false,false);
+
+ nsString temp3("");
+ char* s = ToNewCString(temp3);
+ delete s;
+
+ char* f = ToNewCString(nsAutoString(""));
+ char* f1 = ToNewCString(nsCAutoString(""));
+ delete f;
+ delete f1;
+
+
+ CStringTester gStringTester;
+
+ gStringTester.TestI18nString();
+
+ return 0;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h
new file mode 100644
index 00000000..8244a5a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h
@@ -0,0 +1,2277 @@
+/********************************************************************************************
+ *
+ * MODULES NOTES:
+ *
+ * This file is designed to help test the new nsString classes.
+ *
+ * Contributor(s):
+ * Rick Gessner <rickg@netscape.com>
+ *
+ * History:
+ *
+ * 02.29.2000: Original files (rickg)
+ * 03.02.2000: Flesh out the interface to be compatible with old library (rickg)
+ *
+ ********************************************************************************************/
+
+#ifndef _STRINGTEST
+#define _STRINGTEST
+
+
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include <time.h>
+
+#define USE_STL
+
+#ifdef USE_STL
+#include <string>
+using namespace std;
+#endif
+
+#define USE_WIDE 1
+#ifdef USE_WIDE
+ #define stringtype nsString
+ #define astringtype nsAutoString
+ #define chartype PRUnichar
+#else
+ #define stringtype nsCString
+ #define astringtype nsCAutoString
+ #define chartype char
+#endif
+
+
+#include <stdio.h>
+
+
+
+static const char* kConstructorError = "constructor error";
+static const char* kComparisonError = "Comparision error!";
+static const char* kEqualsError = "Equals error!";
+
+static char* kNumbers[]={"0123456789","0\01\02\03\04\05\06\07\08\09\0\0\0"};
+static char* kLetters[]={"abcdefghij","a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0\0\0"};
+static char* kAAA[]={"AAA","A\0A\0A\0\0\0"};
+static char* kBBB[]={"BBB","B\0B\0B\0\0\0"};
+static char* kHello[]={"hello","h\0e\0l\0l\0o\0\0\0"};
+static char* kWSHello[]={" hello "," \0 \0h\0e\0l\0l\0o\0 \0 \0\0\0"};
+
+
+
+/********************************************************
+
+ This class's only purpose in life is to test the
+ netscape string library. We exercise the string
+ API's here, and do a bit of performance testing
+ against the standard c++ library string (from STL).
+
+ ********************************************************/
+class CStringTester {
+public:
+ CStringTester() {
+ TestConstructors();
+ TestAutoStrings();
+ TestAppend();
+ TestAssignAndAdd();
+ TestInsert();
+ TestDelete();
+ TestTruncate();
+ TestLogical();
+ TestLexomorphic();
+ TestCreators();
+ TestNumerics();
+ TestExtractors();
+ TestSearching();
+ TestSubsumables();
+ TestRandomOps();
+ TestReplace();
+ TestRegressions();
+ TestStringPerformance();
+ TestWideStringPerformance();
+ }
+protected:
+ int TestConstructors();
+ int TestLogical();
+ int TestAutoStrings();
+ int TestAppend();
+ int TestAssignAndAdd();
+ int TestInsert();
+ int TestDelete();
+ int TestTruncate();
+ int TestLexomorphic();
+ int TestCreators();
+ int TestNumerics();
+ int TestExtractors();
+ int TestSearching();
+ int TestSubsumables();
+ int TestRandomOps();
+ int TestReplace();
+ int TestStringPerformance();
+ int TestWideStringPerformance();
+ int TestRegressions();
+};
+
+
+class Stopwatch {
+public:
+ Stopwatch() {
+ start=clock();
+ }
+
+ void Stop() {
+ stop=clock();
+ }
+
+ double Elapsed() {
+ return (double)(stop - start) / CLOCKS_PER_SEC;
+ }
+
+ void Print(const char* msg= "") {
+ printf("%s %f\n",msg,Elapsed());
+ }
+
+ clock_t start,stop;
+};
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestSearching(){
+ int result=0;
+
+
+
+ PRUnichar pbuf[10]={'e','f','g',0};
+ PRUnichar pbuf2[10]={'a','b','c',0};
+
+
+ //Since there is so much ground to cover with searching, we use a typedef to
+ //allow you to vary the string type being searched...
+
+
+ stringtype theDest("abcdefghijkabc");
+ nsString s1("ijk");
+ nsCString c1("ijk");
+
+ PRInt32 pos=theDest.Find(pbuf);
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.Find(pbuf2,PR_FALSE,-1);
+ NS_ASSERTION(pos==0,"Error: Find routine");
+
+ pos=theDest.Find(pbuf2,PR_FALSE,pos+1);
+ NS_ASSERTION(pos==11,"Error: Find routine");
+
+ pos=theDest.FindChar('a');
+ NS_ASSERTION(pos==0,"Error: Find routine");
+
+ pos=theDest.FindChar('a',PR_FALSE,pos+1);
+ NS_ASSERTION(pos==11,"Error: Find routine");
+
+ pos=theDest.Find("efg");
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.Find("EFG",PR_TRUE);
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.FindChar('d');
+ NS_ASSERTION(pos==3,"Error: Find char routine");
+
+ pos=theDest.Find(s1);
+ NS_ASSERTION(pos==8,"Error: Find char routine");
+
+ pos=theDest.FindCharInSet("12k");
+ NS_ASSERTION(pos==10,"Error: Findcharinset routine");
+
+ pos=theDest.FindCharInSet(pbuf);
+ NS_ASSERTION(pos==4,"Error: Findcharinset routine");
+
+ pos=theDest.FindCharInSet(s1);
+ NS_ASSERTION(pos==8,"Error: Findcharinset routine");
+
+ pos=theDest.Find("efg",PR_FALSE,2);
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.RFindCharInSet("12k");
+ NS_ASSERTION(pos==10,"Error: RFindcharinset routine");
+
+ pos=theDest.RFindCharInSet("xyz");
+ NS_ASSERTION(pos==-1,"Error: RFindcharinset routine");
+
+ pos=theDest.RFindCharInSet(pbuf);
+ NS_ASSERTION(pos==6,"Error: RFindcharinset routine");
+
+ pos=theDest.RFindCharInSet(s1);
+ NS_ASSERTION(pos==10,"Error: RFindcharinset routine");
+
+ pos=theDest.RFind("efg");
+ NS_ASSERTION(pos==4,"Error: RFind routine");
+
+ pos=theDest.RFind("xxx");
+ NS_ASSERTION(pos==-1,"Error: RFind routine"); //this should fail
+
+ pos=theDest.RFind("");
+ NS_ASSERTION(pos==-1,"Error: RFind routine"); //this too should fail.
+
+ pos=theDest.RFindChar('a',PR_FALSE,4);
+ NS_ASSERTION(pos==-1,"Error: RFind routine");
+
+
+ //now try searching with FindChar using offset and count...
+ {
+ stringtype s1("hello there rick");
+
+ PRInt32 pos=s1.FindChar('r'); //this will search from the beginning, and for the length of the string.
+ NS_ASSERTION(pos==9,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('r',PR_FALSE,0,5); //this will search from the front using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('r',PR_FALSE,0,10); //this will search from the front using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==9,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('i',PR_FALSE,5,5); //this will search from the middle using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('i',PR_FALSE,5,10); //this will search from the middle using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==13,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,2); //this will search from near the end using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,7); //this will search from near the end using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==15,"Error: FindChar() with offset and count");
+
+ //now let's try a few with bad data...
+
+ pos=s1.FindChar('k',PR_FALSE,100,2); //this will search from a bad offset. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,0); //this will search for a bad count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,20); //this will search for a bad count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==15,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,4); //this will search for a bad count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=10;
+ }
+
+ //now try searching with RFindChar using offset and count...
+ {
+ stringtype s1("hello there rick");
+
+ PRInt32 pos=s1.RFindChar('o'); //this will search from the end, and for the length of the string.
+ NS_ASSERTION(pos==4,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('i'); //this will search from the end, and for the length of the string.
+ NS_ASSERTION(pos==13,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar(' ',PR_FALSE,-1,4); //this will search from the end, and for the length of the string.
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count"); //THIS WILL FAIL
+
+ pos=s1.RFindChar(' ',PR_FALSE,12,1); //this will search from the middle, and for the length of 1.
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count"); //THIS WILL FAIL
+
+ pos=s1.RFindChar(' ',PR_FALSE,12,2); //this will search from the middle, and for the length of 2.
+ NS_ASSERTION(pos==11,"Error: RFindChar() with offset and count"); //THIS WILL SUCCEED
+
+ pos=s1.RFindChar('o',PR_FALSE,-1,5); //this will search from the end using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('o',PR_FALSE,-1,12); //this will search from the front using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==4,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('l',PR_FALSE,8,2); //this will search from the middle using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('l',PR_FALSE,8,7); //this will search from the middle using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==3,"Error: RFindChar() with offset and count");
+
+//***
+
+ pos=s1.RFindChar('h',PR_FALSE,3,2); //this will search from near the end using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('h',PR_FALSE,3,7); //this will search from near the end using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==0,"Error: RFindChar() with offset and count");
+
+ //now let's try a few with bad data...
+
+ pos=s1.RFindChar('k',PR_FALSE,100,2); //this will search from a bad offset. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('k',PR_FALSE,10,0); //this will search for a bad count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=10;
+ }
+
+ //now try searching with Find() using offset and count...
+ {
+ stringtype s1("hello there rick");
+
+ PRInt32 pos= s1.Find("there",PR_FALSE,0,4); //first search from front using offset
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.Find("there",PR_FALSE,0,8); //first search from front using count
+ NS_ASSERTION(pos==6,"Error: Find) with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("there",PR_FALSE,4,1); //first search from front using count
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.Find("there",PR_FALSE,5,2); //first search from front using count
+ NS_ASSERTION(pos==6,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("there",PR_FALSE,6,1); //first search from front using count
+ NS_ASSERTION(pos==6,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("there",PR_FALSE,6,0); //first search from front using a bogus count
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.Find("k",PR_FALSE,15,1); //first search from end using a count
+ NS_ASSERTION(pos==15,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("k",PR_FALSE,15,10); //first search from end using a LARGE count
+ NS_ASSERTION(pos==15,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("k",PR_FALSE,25,10); //first search from bogus offset using a LARGE count
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos=10;
+ }
+
+ //now try substringsearching with RFind() using offset and count...
+ {
+ nsString s1("abcdefghijklmnopqrstuvwxyz");
+
+ PRInt32 pos= s1.RFind("ghi"); //first search from end using count
+ NS_ASSERTION(pos==6,"Error: RFind() with offset and count"); //THIS WILL SUCCEED!
+
+ pos= s1.RFind("nop",PR_FALSE,-1,4); //first search from end using count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("nop",PR_FALSE,-1,15); //first search from end using count
+ NS_ASSERTION(pos==13,"Error: RFind() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.RFind("nop",PR_FALSE,16,3); //first search from middle using count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("nop",PR_FALSE,16,7); //first search from middle using count
+ NS_ASSERTION(pos==13,"Error: RFind() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.RFind("nop",PR_FALSE,0,1); //first search from front using count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("abc",PR_FALSE,0,1); //first search from middle using count
+ NS_ASSERTION(pos==0,"Error: RFind() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.RFind("foo",PR_FALSE,10,100); //first search from front using bogus count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("ghi",PR_FALSE,30,1); //first search from middle using bogus offset
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos=10;
+ }
+
+ //Various UNICODE tests...
+ {
+ //do some searching against chinese unicode chars...
+
+ PRUnichar chinese[] = {0x4e41,0x4e42, 0x4e43, 0x0000}; // 3 chinese unicode
+
+ nsString T2(chinese);
+ nsString T2copy(chinese);
+
+ pos = T2.FindCharInSet("A");
+ NS_ASSERTION(kNotFound==pos,"Error in FindCharInSet");
+
+ pos=T2.RFindCharInSet("A",2);
+ NS_ASSERTION(kNotFound==pos,"Error in RFindCharInSet");
+
+ pos=T2.Find("A", PR_FALSE, 0, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in Find");
+
+ pos=T2.RFind("A", PR_FALSE, 2, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in RFind");
+
+ T2.ReplaceChar("A",' ');
+ NS_ASSERTION(T2==T2copy,"Error in ReplaceChar");
+
+ //Here's the 3rd FTang unicode test...
+
+ static char test4[]="ABCDEF";
+ static char test4b[]=" BCDEF";
+
+ PRUnichar test5[]={0x4e41, 0x0000};
+ PRUnichar test6[]={0x0041, 0x0000};
+
+ nsCString T4(test4);
+ nsCString T4copy(test4);
+ nsCString T4copyb(test4b);
+ nsCString T5(test5);
+ nsCString T6(test6);
+
+ pos = T4.FindCharInSet(T5.get());
+ NS_ASSERTION(0==pos,"Error in FindcharInSet"); //This should succeed.
+
+ pos = T4.FindCharInSet(T6.get());
+ NS_ASSERTION(kNotFound<pos,"Error in FindcharInSet"); //This should succeed.
+
+ pos = T4.RFindCharInSet(T5.get(),2);
+ NS_ASSERTION(0==pos,"Error in RFindCharInSet"); //This should fail.
+
+ pos = T4.RFindCharInSet(T6.get(),2);
+ NS_ASSERTION(kNotFound<pos,"Error in RFindCharInSet"); //This should fail.
+
+ pos = T4.Find(T5.get(), PR_FALSE, 0, 1);
+ NS_ASSERTION(0==pos,"Error in Find"); //This should succeed.
+
+ pos= T4.Find(T6.get(), PR_FALSE, 0, 1);
+ NS_ASSERTION(kNotFound<pos,"Error in Find"); //This should fail.
+
+ pos = T4.RFind(T5.get(), PR_FALSE, 2, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in RFind");
+
+ pos =T4.RFind(T6.get(), PR_FALSE, 2, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in RFind");
+
+
+/*
+ NOT WORKING IN NEW STRING YET...
+
+ T4.ReplaceChar(PRUnichar(0x4E41),PRUnichar(' '));
+ if(T4 != T4copy)
+ printf("nsCString::ReplaceChar(PRUnichar, PRUnichar) error- replace when it should not\n");
+
+ T4 = test4;
+ T4.ReplaceChar(PRUnichar(0x0041),PRUnichar(' '));
+ if(T4 != T4copyb)
+ printf("nsCString::ReplaceChar(PRUnichar, PRUnichar) error- not replace when it should\n");
+
+*/
+
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestConstructors(){
+ int result=0;
+ PRUnichar pbuf[10]={'f','o','o',0};
+ PRUnichar* buf=pbuf;
+
+ nsString s1("hello world");
+ nsCString c1("what's up");
+
+
+ //Test nsCString constructors...
+ {
+ nsCString temp0;
+ nsCString temp1(s1);
+ NS_ASSERTION(temp1==s1,"nsCString Constructor error");
+
+ nsCString temp2(c1);
+ NS_ASSERTION(temp2==c1,"nsCString Constructor error");
+
+ nsCString temp3("hello world");
+ NS_ASSERTION(temp3=="hello world","nsCString Constructor error");
+
+ nsCString temp4(pbuf);
+ NS_ASSERTION(temp4==pbuf,"nsCString Constructor error");
+
+ nsCString temp5('a');
+ NS_ASSERTION(temp5=="a","nsCString Constructor error");
+
+ nsCString temp6(PRUnichar('a'));
+ NS_ASSERTION(temp5=="a","nsCString Constructor error");
+ }
+
+ //now just for fun, let's construct 2byte from 1byte and back...
+ {
+ nsCString temp0("hello");
+ nsString temp1(temp0);
+ nsCString temp2(temp1);
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestLogical(){
+ int result=0;
+ stringtype temp8("aaaa");
+ stringtype temp8a("AAAA");
+ stringtype temp9("bbbb");
+
+ const char* aaaa="aaaa";
+ const char* bbbb="bbbb";
+
+
+ //First, test a known error that got checked into the tree...
+ {
+ nsString mURL("file:///c|/test/foo.txt");
+ PRBool result=mURL.Equals("file:/",PR_FALSE);
+ NS_ASSERTION(!result,kEqualsError);
+ result=mURL.Equals("file:/",PR_FALSE,5);
+ NS_ASSERTION(result,kEqualsError);
+ result=mURL.Equals("file:/",PR_FALSE,-1);
+ NS_ASSERTION(!result,kEqualsError);
+
+ nsString s1("rick");
+ result=s1.Equals("rick",PR_FALSE,6);
+ result++;
+ }
+
+
+ {
+ //this little piece of code tests to see whether the PL_strcmp series works
+ //correctly even when we have strings whose buffers contain nulls.
+
+ char *buf1 = "what's up \0\0 doc?";
+ char *buf2 = "what's up \0\0 dog?";
+
+ nsString s1(buf2,17);
+
+ PRInt32 result=s1.Compare(buf1,PR_TRUE,17);
+ result=s1.FindChar('?');
+ result++;
+ }
+
+ {
+ nsString foo("__moz_text");
+ PRInt32 cmp=foo.Compare("pre",PR_FALSE,-1);
+ cmp=cmp;
+ }
+
+ //First test the string compare routines...
+
+ NS_ASSERTION(0>temp8.Compare(bbbb),kComparisonError);
+ NS_ASSERTION(0>temp8.Compare(temp9),kComparisonError);
+ NS_ASSERTION(0<temp9.Compare(temp8),kComparisonError);
+ NS_ASSERTION(0==temp8.Compare(temp8a,PR_TRUE),kComparisonError);
+ NS_ASSERTION(0==temp8.Compare(aaaa),kComparisonError);
+
+ //Now test the boolean operators...
+ NS_ASSERTION(temp8==temp8,kComparisonError);
+ NS_ASSERTION(temp8==aaaa,kComparisonError);
+
+ NS_ASSERTION(temp8!=temp9,kComparisonError);
+ NS_ASSERTION(temp8!=bbbb,kComparisonError);
+
+ NS_ASSERTION(((temp8<temp9) && (temp9>=temp8)),kComparisonError);
+
+ NS_ASSERTION(((temp9>temp8) && (temp8<=temp9)),kComparisonError);
+ NS_ASSERTION(temp9>aaaa,kComparisonError);
+
+ NS_ASSERTION(temp8<=temp8,kComparisonError);
+ NS_ASSERTION(temp8<=temp9,kComparisonError);
+ NS_ASSERTION(temp8<=bbbb,kComparisonError);
+
+ NS_ASSERTION(((temp9>=temp8) && (temp8<temp9)),kComparisonError);
+ NS_ASSERTION(temp9>=temp8,kComparisonError);
+ NS_ASSERTION(temp9>=aaaa,kComparisonError);
+
+ NS_ASSERTION(temp8.Equals(temp8),kEqualsError);
+ NS_ASSERTION(temp8.Equals(aaaa),kEqualsError);
+
+ stringtype temp10(temp8);
+ ToUpperCase(temp10);
+ NS_ASSERTION(temp8.Equals(temp10,PR_TRUE),kEqualsError);
+ NS_ASSERTION(temp8.Equals("AAAA",PR_TRUE),kEqualsError);
+
+
+ //now test the new string Equals APIs..
+ {
+ nsCString s1("hello there");
+ NS_ASSERTION(s1.Equals("hello there"),kEqualsError);
+ NS_ASSERTION(s1.Equals("hello rick",PR_FALSE,5),kEqualsError);
+ NS_ASSERTION(!s1.Equals("hello rick",PR_FALSE-1),kEqualsError);
+
+ nsCString s2("");
+ NS_ASSERTION(s2.Equals(""),kEqualsError);
+
+ nsCString s3("view-source:");
+ NS_ASSERTION(s3.Equals("VIEW-SOURCE:",PR_TRUE,12),kEqualsError);
+ }
+
+ //now test the count argument...
+ {
+ nsString s1("rickgessner");
+ nsString s2("rickricardo");
+ PRInt32 result=s1.Compare(s2); //assume no case conversion, and full-length comparison...
+ result=s1.Compare(s2,PR_FALSE,4);
+ result=s1.Compare(s2,PR_FALSE,5);
+
+ PRBool b=s1.Equals(s2);
+ b=s1.Equals("rick",PR_FALSE,4);
+ b=s1.Equals("rickz",PR_FALSE,5);
+
+ result=10;
+
+ nsString s3("view");
+
+#define kString "view-source"
+
+ b=s3.Equals(kString);
+ result=10;
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestAssignAndAdd(){
+ int result=0;
+
+ static const char* s1="hello";
+ static const char* s2="world";
+ static const PRUnichar pbuf[] = {' ','w','o','r','l','d',0};
+
+ nsString ns1("I'm an nsString");
+ nsCString nc1("I'm an nsCString");
+
+ nsAutoString as1("nsAutoString source");
+ nsCAutoString ac1("nsCAutoString source");
+
+
+ {
+ //**** Test assignments to nsCString...
+
+ nsCString theDest;
+ theDest.Assign(theDest); //assign nsString to itself
+ theDest.Assign(ns1); //assign an nsString to an nsString
+ NS_ASSERTION(theDest==ns1,"Assignment error");
+
+ theDest.Assign(nc1); //assign an nsCString to an nsString
+ NS_ASSERTION(theDest==nc1,"Assignment error");
+
+ theDest.Assign(as1); //assign an nsAutoString to an nsString
+// NS_ASSERTION(theDest==as1,"Assignment error");
+
+ theDest.Assign(ac1); //assign an nsCAutoString to an nsString
+// NS_ASSERTION(theDest==ac1,"Assignment error");
+
+ theDest.Assign("simple char*"); //assign a char* to an nsString
+ NS_ASSERTION(theDest=="simple char*","Assignment error");
+
+ theDest.Assign(pbuf); //assign a PRUnichar* to an nsString
+ NS_ASSERTION(theDest==pbuf,"Assignment error");
+
+ theDest.Assign('!'); //assign a char to an nsString
+ NS_ASSERTION(theDest=="!","Assignment error");
+
+ theDest.Assign(PRUnichar('$')); //assign a char to an nsString
+ NS_ASSERTION(theDest=="$","Assignment error");
+
+ theDest=ns1;
+ NS_ASSERTION(theDest==ns1,"Assignment error");
+
+ theDest=nc1;
+ NS_ASSERTION(theDest==nc1,"Assignment error");
+
+ theDest='a';
+ NS_ASSERTION(theDest=="a","Assignment error");
+
+ theDest=PRUnichar('a');
+ NS_ASSERTION(theDest=="a","Assignment error");
+
+ theDest=s1;
+ NS_ASSERTION(theDest==s1,"Assignment error");
+
+ theDest=pbuf;
+ NS_ASSERTION(theDest==pbuf,"Assignment error");
+
+ }
+
+ //test operator+()...
+ {
+
+ /* NOT WORKING YET...
+ nsString s1("hello");
+ nsString s2(" world");
+ nsCString c1(" world");
+
+ stringtype theDest;
+
+ theDest=s1+s2;
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+c1;
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+" world";
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+pbuf;
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+'!';
+ NS_ASSERTION(theDest=="hello!","Assignment error");
+
+ theDest=s1+PRUnichar('!');
+ NS_ASSERTION(theDest=="hello!","Assignment error");
+*/
+
+ }
+
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestAppend(){
+ int result=0;
+
+
+ static const char* s1="hello";
+ static const char* s2="world";
+ static const PRUnichar pbuf[] = {' ','w','o','r','l','d',0};
+ static const PRUnichar pbuf1[] = {'a','b','c','d','l','d'};
+
+
+ stringtype theDest;
+ theDest.Append((float)100.100);
+ NS_ASSERTION(theDest=="100.1","Append(float) error");
+
+ theDest.Truncate();
+ theDest.Append(12345);
+ NS_ASSERTION(theDest=="12345","Append(int) error");
+
+ theDest.Truncate();
+ theDest.Append(pbuf1,1);
+ NS_ASSERTION(theDest=="a","Append(PRUnichar*,count) error");
+
+ theDest.Truncate();
+ theDest.Append('a');
+ NS_ASSERTION(theDest=="a","Append(char) error");
+
+
+ static const PRUnichar pbuf2[] = {'w','h','a','t','s',' ','u','p',' ','d','o','c','?',0};
+
+ theDest.Truncate();
+ theDest.Append(pbuf,20); //try appending more chars than actual length of pbuf
+ NS_ASSERTION(theDest!=pbuf,"Append(PRUnichar*) error");
+ //(NOTE: if you tell me to append X chars, I'll assume you really have X chars, and the length
+ // get's set accordingly. This test really is correct; it just seems odd.
+
+ theDest.Truncate(0);
+ theDest.Append(pbuf,5); //try appending fewer chars than actual length of pbuf
+ NS_ASSERTION(theDest==" worl","Append(PRUnichar*) error");
+
+ theDest.Truncate(0);
+ theDest.Append(pbuf); //try appending all of pbuf
+ NS_ASSERTION(theDest==pbuf,"Append(PRUnichar*) error");
+
+ char* ss=0;
+ theDest.Truncate();
+ theDest.Append(ss); //try appending NULL
+ NS_ASSERTION(theDest=="","Append(nullstr) error");
+
+ theDest.Append(pbuf,0); //try appending nothing
+ NS_ASSERTION(theDest=="","Append(nullstr) error");
+
+
+ {
+ //test improvement to unichar appends...
+ stringtype s1("hello");
+ char c='!';
+ s1+=c;
+ NS_ASSERTION(s1=="hello!","operator+=() error");
+
+ c=(char)0xfa;
+ s1+=c;
+ s1.Append(c);
+
+ PRUnichar theChar='f';
+ s1+=theChar;
+
+ char theChar2='g';
+ s1+=theChar2;
+
+// long theLong= 1234;
+// s1+=theLong;
+
+ }
+
+ {
+ //this just proves we can append nulls in our buffers...
+ stringtype c("hello");
+ stringtype s(" there");
+ c.Append(s);
+ char buf[]={'a','b',0,'d','e'};
+ s.Append(buf,5);
+ }
+
+
+ stringtype temp2("there");
+
+ theDest.Append(temp2);
+ theDest.Append(" xxx ");
+ theDest.Append(pbuf);
+ theDest.Append('4');
+ theDest.Append(PRUnichar('Z'));
+
+ stringtype a(s1);
+ stringtype b(s2);
+
+ theDest.Truncate();
+ temp2.Truncate();
+
+/* NOT WORKING YET...
+ theDest=a+b;
+ temp2=a+"world!";
+ temp2=a+pbuf;
+ stringtype temp3;
+ temp3=temp2+'!';
+*/
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestExtractors(){
+ int result=0;
+
+ //first test the 2 byte version...
+
+
+ {
+ nsString temp1("hello there rick");
+ nsString temp2;
+
+ temp1.Left(temp2,10);
+ NS_ASSERTION(temp2=="hello ther","Left() error");
+
+ temp1.Mid(temp2,6,5);
+ NS_ASSERTION(temp2=="there","Mid() error");
+
+ temp1.Right(temp2,4);
+ NS_ASSERTION(temp2=="rick","Right() error");
+
+ //Now test the character accessor methods...
+ nsString theString("hello");
+ PRUint32 len=theString.Length();
+ PRUnichar theChar;
+ for(PRUint32 i=0;i<len;i++) {
+ theChar=theString.CharAt(i);
+ }
+
+/* NOT WORKING YET...
+ theChar=theString.First();
+ theChar=theString.Last();
+ theChar=theString[3];
+ theString.SetCharAt('X',3);
+*/
+ }
+
+ //now test the 1 byte version
+ {
+ nsCString temp1("hello there rick");
+ nsCString temp2;
+ temp1.Left(temp2,10);
+ temp1.Mid(temp2,6,5);
+ temp1.Right(temp2,4);
+
+ //Now test the character accessor methods...
+ nsCString theString("hello");
+ PRUint32 len=theString.Length();
+ char ch;
+ for(PRUint32 i=0;i<len;i++) {
+ ch=theString.CharAt(i);
+ }
+
+/* NOT WORKING YET...
+
+ ch=theString.First();
+ ch=theString.Last();
+ ch=theString[3];
+ theString.SetCharAt('X',3);
+*/
+ }
+
+
+ return result;
+}
+
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestCreators(){
+ int result=0;
+
+/* NOT WORKING YET
+ {
+ nsString theString5("");
+ char* str0 = ToNewCString(theString5);
+ Recycle(str0);
+
+ theString5+="hello rick";
+ nsString* theString6=theString5.ToNewString();
+ delete theString6;
+
+ nsString theString1("hello again");
+ PRUnichar* thePBuf=ToNewUnicode(theString1);
+ if(thePBuf)
+ Recycle(thePBuf);
+
+ char* str = ToNewCString(theString5);
+ if(str)
+ Recycle(str);
+
+ char buffer[6];
+ theString5.ToCString(buffer,sizeof(buffer));
+
+ }
+
+ {
+ nsCString theString5("hello rick");
+ nsCString* theString6=theString5.ToNewString();
+ delete theString6;
+
+ PRUnichar* thePBuf=ToNewUnicode(theString5);
+ if(thePBuf)
+ Recycle(thePBuf);
+
+ char* str = ToNewCString(theString5);
+ if(str)
+ Recycle(str);
+
+ char buffer[100];
+ theString5.ToCString(buffer,sizeof(buffer)-1);
+ nsCString theOther=theString5.GetBuffer();
+ }
+ */
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestInsert(){
+ int result=0;
+
+ {
+ static const char pbuf[] = " world";
+
+ nsCString temp1("hello rick");
+ temp1.Insert("there ",6); //char* insertion
+ NS_ASSERTION(temp1=="hello there rick","Insert error");
+
+ temp1.Insert(pbuf,3); //prunichar* insertion
+ NS_ASSERTION(temp1=="hel worldlo there rick","Insert error");
+
+ temp1.Insert("?",10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl?o there rick","Insert error");
+
+ temp1.Insert('*',10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl*?o there rick","Insert error");
+
+ temp1.Insert("xxx",100,3); //this should append.
+ NS_ASSERTION(temp1=="hel worldl*?o there rickxxx","Insert error");
+
+ nsCString temp2("abcdefghijklmnopqrstuvwxyz");
+// temp2.Insert(temp1,10);
+ temp2.Cut(20,5);
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ temp2.Cut(100,100); //this should fail.
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ }
+
+ {
+ static const PRUnichar pbuf[] = {' ','w','o','r','l','d',0};
+
+
+ nsString temp1("llo rick");
+
+ temp1.Insert("he",0); //char* insertion
+ NS_ASSERTION(temp1=="hello rick","Insert error");
+
+ temp1.Insert("there ",6); //char* insertion
+ NS_ASSERTION(temp1=="hello there rick","Insert error");
+
+ temp1.Insert(pbuf,3); //prunichar* insertion
+ NS_ASSERTION(temp1=="hel worldlo there rick","Insert error");
+
+ temp1.Insert("?",10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl?o there rick","Insert error");
+
+ temp1.Insert('*',10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl*?o there rick","Insert error");
+
+ temp1.Insert("xxx",100,3); //this should append.
+ NS_ASSERTION(temp1=="hel worldl*?o there rickxxx","Insert error");
+
+ nsString temp2("abcdefghijklmnopqrstuvwxyz");
+// temp2.Insert(temp1,10);
+ temp2.Cut(20,5);
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ temp2.Cut(100,100); //this should fail.
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ }
+
+ return result;
+}
+
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestDelete(){
+ int result=0;
+
+ //NOTE: You need to run this test program twice for this method to work.
+ // Once with USE_WIDE defined, and once without (to test nsCString)
+
+ //let's try some whacky string deleting calls
+ {
+ const char* pbuf = "whats up doc?";
+
+ nsCString s1(pbuf);
+ s1.Cut(3,20); //try deleting more chars than actual length of pbuf
+ NS_ASSERTION(s1=="wha","Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,-10);
+ NS_ASSERTION(s1==pbuf,"Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,2);
+ NS_ASSERTION(s1=="wha up doc?","Cut error");
+
+ }
+
+ //let's try some whacky string deleting calls
+ {
+ const PRUnichar pbuf[] = {'w','h','a','t','s',' ','u','p',' ','d','o','c','?',0};
+
+ nsString s1(pbuf);
+ s1.Cut(3,20); //try deleting more chars than actual length of pbuf
+ NS_ASSERTION(s1=="wha","Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,-10);
+ NS_ASSERTION(s1==pbuf,"Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,2);
+ NS_ASSERTION(s1=="wha up doc?","Cut error");
+ }
+
+
+ {
+ nsCString s;
+ int i;
+ for(i=0;i<518;i++) {
+ s.Append("0123456789");
+ }
+ s+="abc";
+ s.Cut(0,5);
+ }
+
+ {
+ astringtype ab("ab");
+ stringtype abcde("cde");
+ stringtype cut("abcdef");
+ cut.Cut(7,10); //this is out of bounds, so ignore...
+ //cut.DebugDump(cout);
+ cut.Cut(5,2); //cut last chars
+ //cut.DebugDump(cout);
+ cut.Cut(1,1); //cut first char
+ //cut.DebugDump(cout);
+ cut.Cut(2,1); //cut one from the middle
+ //cut.DebugDump(cout);
+ cut="Hello there Rick";
+ //cut.DebugDump(cout);
+}
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestTruncate(){
+ int result=0;
+ //test delete against a twobyte string...
+
+ {
+ nsCString s0;
+ nsCString s1(kNumbers[0]);
+ s0=s1;
+ s0.Truncate(100); //should fail
+ s0.Truncate(5); //should work
+ s0.Truncate(0); //should work
+ }
+
+ {
+ nsString s0;
+ nsString s1(kNumbers[0]);
+ s0=s1;
+ s0.Truncate(100); //should fail
+ s0.Truncate(5); //should work
+ s0.Truncate(0); //should work
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestNumerics(){
+ int result=0;
+
+ //try a few numeric conversion routines...
+ {
+ nsCString str1("-12345");
+ NS_ASSERTION(str1=="-12345","Append(int) error");
+
+ nsString str2("hello");
+ nsString str3;
+ nsString str4("0");
+ nsString str5("&#183;");
+ nsString str6("&xi;");
+ nsString str7("#xe3;");
+ nsString str8("#FF;");
+ nsCString str9("-#xa?a;"); //should return -10 (decimal)
+ nsCString str10("&#191;");
+ nsCString str11("&#vvv;");
+ nsCString str12("-vvv;");
+ nsCString str13("-f");
+
+ PRInt32 err;
+ PRInt32 theInt=str1.ToInteger(&err);
+ theInt=str2.ToInteger(&err);
+ NS_ASSERTION(theInt==14,"ToInteger error");
+
+ theInt=str3.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str4.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str5.ToInteger(&err);
+ NS_ASSERTION(theInt==183,"ToInteger error");
+
+ theInt=str6.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str7.ToInteger(&err,16);
+ NS_ASSERTION(theInt==227,"ToInteger error");
+
+ theInt=str8.ToInteger(&err,kAutoDetect);
+ NS_ASSERTION(theInt==255,"ToInteger error");
+
+ theInt=str9.ToInteger(&err,kAutoDetect);
+ NS_ASSERTION(theInt==-10,"ToInteger error");
+
+ theInt=str10.ToInteger(&err);
+ NS_ASSERTION(theInt==191,"ToInteger error");
+
+ theInt=str11.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str12.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str13.ToInteger(&err);
+ NS_ASSERTION(theInt==-15,"ToInteger error");
+
+
+ Stopwatch watch;
+ int i;
+ for(i=0;i<1000000;i++){
+ theInt=str1.ToInteger(&err,16);
+ }
+ watch.Stop();
+ watch.Print("ToInteger() ");
+
+ str1="100.100";
+ float theFloat=str1.ToFloat(&err);
+ }
+ //try a few numeric conversion routines...
+ {
+ nsCString str1("10000");
+ nsCString str2("hello");
+ nsCString str3;
+ PRInt32 err;
+ PRInt32 theInt=str1.ToInteger(&err);
+ NS_ASSERTION(theInt==10000,"ToInteger error");
+
+ theInt=str2.ToInteger(&err);
+ NS_ASSERTION(theInt==14,"ToInteger error");
+
+ theInt=str3.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ str1="100.100";
+ float theFloat=str1.ToFloat(&err);
+ }
+ return 0;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestLexomorphic(){
+ int result=0;
+ //test delete against a twobyte string...
+
+ //NOTE: You need to run this test program twice for this method to work.
+ // Once with USE_WIDE defined, and once without (to test nsCString)
+
+
+ {
+ nsString theTag("FOO");
+ nsString theLower;
+ theTag.ToLowerCase(theLower);
+ int x=5;
+ }
+
+ PRUnichar pbuf[] = {'h','e','l','l','o','\n','\n','\n','\n',250,'\n','\n','\n','\n','\n','\n','r','i','c','k',0};
+
+ //and hey, why not do a few lexo-morphic tests...
+ nsString s0(pbuf);
+ ToUpperCase(s0);
+ ToLowerCase(s0);
+ s0.StripChars("l");
+ s0.StripChars("\n");
+ s0.StripChar(250);
+ NS_ASSERTION(s0=="heorick","Stripchars error");
+
+ {
+ nsAutoString s1(pbuf);
+ s1.CompressSet("\n ",' ');
+ }
+
+ {
+
+ char pbuf[] = { 0x1C, 0x04, 0x1D, 0x04, 0x20, 0x00, 0x2D, 0x00, 0x20, 0x00, 0x23, 0x04, 0x20, 0x00, 0x40, 0x04,
+ 0x43, 0x04, 0x3B, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x30, 0x04, 0x40, 0x04, 0x3C, 0x04, 0x38, 0x04,
+ 0x38, 0x04, 0x20, 0x00, 0x2D, 0x00, 0x20, 0x00, 0x32, 0x04, 0x42, 0x04, 0x3E, 0x04, 0x40, 0x04,
+ 0x3E, 0x04, 0x41, 0x04, 0x42, 0x04, 0x35, 0x04, 0x3F, 0x04, 0x35, 0x04, 0x3D, 0x04, 0x3D, 0x04,
+ 0x4B, 0x04, 0x35, 0x04, 0x20, 0x00, 0x3B, 0x04, 0x38, 0x04, 0x46, 0x04, 0x30, 0x04, 0x20, 0x00,
+ 0x2D, 0x00, 0x20, 0x00, 0x30, 0x00, 0x39, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00,
+ 0x30, 0x00, 0x00, 0x00};
+
+ nsAutoString temp((PRUnichar*)pbuf);
+ nsAutoString temp1(temp);
+ temp.CompressWhitespace();
+ PRBool equals=temp.Equals(temp1);
+
+ }
+
+ {
+ nsString s1(" ");
+ s1.Trim("; \t");
+ s1="helvetica";
+ s1.Trim("; \t");
+ }
+
+ s0.Insert(" ",0);
+ NS_ASSERTION(s0==" heorick","Stripchars error");
+
+ s0.Append(" ");
+ NS_ASSERTION(s0==" heorick ","Stripchars error");
+
+ s0.Trim(" ",PR_TRUE,PR_TRUE);
+ NS_ASSERTION(s0=="heorick","Stripchars error");
+
+ s0.Append(" abc 123 xyz ");
+ s0.CompressWhitespace();
+ NS_ASSERTION(s0=="heorick abc 123 xyz","CompressWS error");
+
+ s0.ReplaceChar('r','b');
+ NS_ASSERTION(s0=="heobick abc 123 xyz","ReplaceChar error");
+
+ s0=pbuf;
+ ToUpperCase(s0);
+ ToLowerCase(s0);
+ s0.Append("\n\n\n \r \r \r \t \t \t");
+ s0.StripWhitespace();
+
+ nsCAutoString s1("\n\r hello \n\n\n\r\r\r\t rick \t\t ");
+ ToUpperCase(s1);
+ ToLowerCase(s1);
+ s1.StripChars("o");
+ s1.Trim(" ",PR_TRUE,PR_TRUE);
+ s1.CompressWhitespace();
+ NS_ASSERTION(s1=="hell rick","Compress Error");
+
+ s1.ReplaceChar('h','w');
+ NS_ASSERTION(s1=="well rick","Compress Error");
+
+ ToUpperCase(s1);
+ NS_ASSERTION(s1=="WELL RICK","Compress Error");
+
+ ToLowerCase(s1);
+ s1.Append("\n\n\n \r \r \r \t \t \t");
+ s1.StripWhitespace();
+ NS_ASSERTION(s1=="wellrick","Compress Error");
+
+ {
+ nsCString temp("aaaa");
+ int i;
+ for(i=0;i<100;i++) {
+ temp+="0123456789.";
+ }
+ temp.StripChars("a2468");
+ i=5;
+
+ temp=" hello rick ";
+ temp.StripChars("\n\r\t\b ");
+ NS_ASSERTION(temp=="hellorick","This isn't good");
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestAutoStrings(){
+ int result=0;
+
+ PRUnichar pbuf[] = {'h','e','l','l','o',0};
+
+ //this test makes sure that autostrings who assume ownership of a buffer,
+ //don't also try to copy that buffer onto itself... (was a bug)
+ {
+ nsAutoString temp0;
+ nsAutoString temp1("hello rick");
+ nsAutoString temp3(pbuf);
+
+/* NOT WORKING...
+ nsAutoString temp4(CBufDescriptor((char*)pbuf,PR_TRUE,5,5));
+*/
+ nsAutoString temp5(temp3);
+ nsString s(pbuf);
+ nsAutoString temp6(s);
+
+/* NOT WORKING...
+ char buffer[500];
+ nsAutoString temp7(CBufDescriptor((PRUnichar*)buffer,PR_TRUE,sizeof(buffer)-10/2,0));
+ temp7="hello, my name is inigo montoya.";
+*/
+
+ nsAutoString as;
+ int i;
+ for(i=0;i<30;i++){
+ as+='a';
+ }
+ PRBool b=PR_TRUE; //this line doesn't do anything, it just gives a convenient breakpoint.
+ NS_ASSERTION(as=="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","error in operator+=()");
+ }
+
+
+ {
+ nsCAutoString temp0;
+ nsCAutoString temp1("hello rick");
+
+
+ //nsCAutoString temp2("hello rick",PR_TRUE,5);
+ nsCAutoString temp3(pbuf);
+
+ {
+ const char* buf="hello rick";
+ int len=strlen(buf);
+
+// nsAutoString temp4(CBufDescriptor(buf,PR_TRUE,len+1,len)); //NOT WORKING
+ }
+
+ nsCAutoString temp5(temp3);
+ nsString s(pbuf);
+ nsCAutoString temp6(s); //create one from a nsString
+
+ nsCAutoString as;
+ int i;
+ for(i=0;i<30;i++){
+ as+='a';
+ }
+ PRBool b=PR_TRUE;
+
+#if 0
+
+/* NOT WORKING
+ char buffer[500];
+
+ nsCAutoString s3(CBufDescriptor(buffer,PR_TRUE,sizeof(buffer)-1,0));
+ s3="hello, my name is inigo montoya.";
+ */
+ //make an autostring that copies an nsString...
+ nsString s0("eat icecream");
+ nsCAutoString s4(s0);
+ nsCAutoString s5(s0.get());
+ nsString aaa("hi there rick");
+#endif
+ }
+
+ const char* st="hello again";
+ nsString s; //this also forces nsString to run it's selftest.
+ s=st;
+ nsAutoString astr;
+ astr=st;
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestSubsumables(){
+ int result=0;
+ char* buf="hello rick";
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestRandomOps(){
+ int result=0;
+
+#if 0
+
+ char* str[]={"abc ","xyz ","123 ","789 ","*** ","... "};
+
+ string theSTLString;
+ nsString theString;
+ nsString thePrevString;
+
+ enum ops {eNOP,eAppend,eDelete,eInsert};
+ char* opStrs[] = {"nop","append","delete","insert"};
+
+ srand( (unsigned)time( NULL ) );
+
+ int err[] = {1,7,9,6,0,4,1,1,1,1};
+
+ ops theOp=eNOP;
+ int pos,len,index;
+
+ fstream output("c:/temp/out.file",ios::out);
+ output<<"dump!";
+
+ for(int theOpIndex=0;theOpIndex<1000000;theOpIndex++){
+
+ int r=rand();
+ char buf[100];
+ sprintf(buf,"%i",r);
+ len=strlen(buf);
+ index=buf[len-1]-'0';
+
+ //debug... index=err[theOp];
+
+ switch(index) {
+ case 0:
+ case 1:
+ case 2:
+ theSTLString.append(str[index]);
+ theString.Append(str[index]);
+ theOp=eAppend;
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ theOp=eInsert;
+ if (theString.Length()>2) {
+ pos=theString.Length()/2;
+ theSTLString.insert(pos,str[index],4);
+ theString.Insert(str[index],pos);
+ }
+ break;
+
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ theOp=eDelete;
+ if(theString.Length()>10) {
+ len=theString.Length()/2;
+ pos=theString.Length()/4;
+ theSTLString.erase(pos,len);
+ theString.Cut(pos,len);
+ }
+ break;
+
+ default:
+ theOp=eNOP;
+
+ } //for
+
+ if(eNOP<theOp) {
+
+ int lendiff=theString.Length()-theSTLString.length();
+ PRBool equals=theString.Equals(theSTLString.c_str());
+ if(((lendiff)) || (!equals)) {
+ printf("Error in %s at:%i len:%i (%s)!\n",opStrs[theOp],pos,len,str[index]);
+ output.close();
+ theString.Equals(theSTLString.c_str());
+
+ if(theOp==eInsert) {
+ thePrevString.Insert(str[index],pos);
+ }
+ else if(theOp==eAppend) {
+ thePrevString.Append(str[index]);
+ }
+ return 0;
+ }
+
+#if FOO
+ output<< opStrs[theOp];
+ if((eInsert==theOp) || (eAppend==theOp)){
+ output<< "(" << str[index] << ", " << pos << ") ";
+ }
+
+ thePrevString.ToCString(buffer,1000,0);
+ output << " Old: [" << buffer << "]";
+ theString.ToCString(buffer,1000,0);
+ output << " New: [" << buffer << "]";
+ output << " STL: [" << theSTLString.c_str() << "]" << endl;
+
+ if(theString.mStringValue.mLength>300) {
+ theString.Truncate();
+ theSTLString.erase();
+ }
+#endif
+ thePrevString=theString;
+ }
+ }
+#endif
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestReplace(){
+ int result=0;
+
+ const char* find="..";
+ const char* rep= "+";
+
+ const char* s1="hello..there..rick..gessner.";
+ const char* s2="hello+there+rick+gessner.";
+
+ nsCString s(s1);
+ s.ReplaceSubstring(find,rep);
+ NS_ASSERTION(s==s2,"ReplaceSubstring error");
+
+ s.ReplaceSubstring(rep,find);
+ NS_ASSERTION(s==s1,"ReplaceSubstring error");
+
+ return result;
+}
+
+
+/**
+ * This method tests the performance of various methods.
+ *
+ *
+ * @return
+ */
+int CStringTester::TestWideStringPerformance() {
+
+ printf("Widestring performance tests...\n");
+
+ char* libname[] = {"STL","nsString",0};
+
+
+ //**************************************************
+ //Test Construction against STL::wstring...
+ //**************************************************
+ {
+ nsString theConst;
+ for(int z=0;z<10;z++){
+ theConst.Append("0123456789");
+ }
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000000;i++){
+ nsString s(theConst);
+ }
+ watch1.Stop();
+
+ wchar_t wbuf[] = {'a','b','c','d','e','f','g','h','i','j',0};
+ wstring theConst2;
+ for(int w=0;w<10;w++){
+ theConst2.append(wbuf);
+ }
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000000;i++){
+ wstring s(theConst2);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Construct(abcde) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+
+ //**************************************************
+ //Test append("abcde") against STL::wstring...
+ //**************************************************
+ {
+
+ PRUnichar pbuf[10]={'a','b','c','d','e',0};
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsString s;
+ for(int j=0;j<200;j++){
+ s.Append("abcde");
+ }
+ }
+ watch1.Stop();
+
+ wchar_t wbuf[10] = {'a','b','c','d','e',0};
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ wstring s;
+ for(int j=0;j<200;j++){
+ s.append(wbuf);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append(abcde) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Test append(char) against STL::wstring
+ //**************************************************
+ {
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<500;i++){
+ nsString s;
+ for(int j=0;j<200;j++){
+ s.Append('a');
+ }
+ }
+ watch1.Stop();
+
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<500;i++){
+ wstring s;
+ wchar_t theChar('a');
+ for(int j=0;j<200;j++){
+ s.append('a',1);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append('a') NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Test insert("123") against STL::wstring
+ //**************************************************
+ {
+
+ PRUnichar pbuf1[10]={'a','b','c','d','e','f',0};
+ PRUnichar pbuf2[10]={'1','2','3',0};
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsString s("abcdef");
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.Insert(pbuf2,inspos);
+ inspos+=3;
+ }
+ }
+ watch1.Stop();
+
+
+ wchar_t wbuf1[10] = {'a','b','c','d','e','f',0};
+ wchar_t wbuf2[10] = {'1','2','3',0};
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ wstring s(wbuf1);
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.insert(inspos,wbuf2);
+ inspos+=3;
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Insert(123) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Let's test substring searching performance...
+ //**************************************************
+ {
+ PRUnichar pbuf1[] = {'a','a','a','a','a','a','a','a','a','a','b',0};
+ PRUnichar pbuf2[] = {'a','a','b',0};
+
+ nsString s(pbuf1);
+ nsString target(pbuf2);
+
+ Stopwatch watch1;
+ int i;
+ for(i=-1;i<200000;i++) {
+ PRInt32 result=s.Find(target,PR_FALSE);
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ wchar_t wbuf1[] = {'a','a','a','a','a','a','a','a','a','a','b',0};
+ wchar_t wbuf2[] = {'a','a','b',0};
+ wstring ws(wbuf1);
+ wstring wtarget(wbuf2);
+
+ for(i=-1;i<200000;i++) {
+ PRInt32 result=ws.find(wtarget);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Find(aab) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Now let's test comparisons...
+ //**************************************************
+ {
+ nsString s("aaaaaaaaaaaaaaaaaaab");
+ PRUnichar target[]={'a','a','a','a','a','a','a','a','a','a','a','a','a','b',0};
+ size_t theLen=(sizeof(target)-1)/2;
+
+ Stopwatch watch1;
+ int result=0;
+ int i;
+ for(i=-1;i<1000000;i++) {
+ result=s.Compare(target,PR_FALSE,theLen);
+ result++;
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ wchar_t buf[]={'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','b',0};
+ wstring ws(buf);
+ wchar_t wtarget[]={'a','a','a','a','a','a','a','a','a','a','a','a','a','b',0};
+
+ for(i=-1;i<1000000;i++) {
+ result=ws.compare(0,theLen,wtarget);
+ result++;
+ }
+#endif
+ watch2.Stop();
+
+ printf("Compare(aaaaaaaab) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+
+ }
+
+ //**************************************************
+ //Now lets test string deletions...
+ //**************************************************
+ {
+
+ int strcount=6000;
+ int outerIter=100;
+ int innerIter=100;
+
+ PRUnichar pbuf[] = {'1','2','3','4','5','6','7','8','9','0',0};
+ nsString source1; //build up our target string...
+ int i;
+ for(i=0;i<strcount;i++) {
+ source1.Append(pbuf);
+ }
+
+ Stopwatch watch1;
+
+ for(i=0;i<outerIter;i++) {
+ nsString s1(source1);
+ for(int j=0;j<100;j++){
+ s1.Cut(20,50);
+ }
+ }
+ watch1.Stop();
+ printf("Cut(...) NSString: %f ",watch1.Elapsed());
+
+#ifdef USE_STL
+
+ wchar_t wbuf[] = {'1','2','3','4','5','6','7','8','9','0',0};
+ wstring source2; //build up our target string...
+
+ for(i=0;i<strcount;i++) {
+ source2.append(wbuf);
+ }
+
+ Stopwatch watch2;
+
+ for(i=0;i<outerIter;i++) {
+ wstring s2(source2);
+ for(int j=0;j<100;j++){
+ s2.erase(20,50);
+ }
+ }
+ watch2.Stop();
+
+ printf(" STL: %f",watch2.Elapsed());
+#endif
+ printf("\n");
+
+ }
+
+ //**************************************************
+ //Now let's test the findChar routine...
+ //**************************************************
+ {
+
+ nsString s1;
+ int i;
+ for(i=0;i<100;i++) {
+ s1.Append("1234567890",10);
+ }
+ s1+="xyz";
+
+ Stopwatch watch1;
+ for(i=0;i<100000;i++) {
+ int f=s1.FindChar('z',PR_FALSE,0);
+ }
+ watch1.Stop();
+ printf("FindChar('z') NSString: %f",watch1.Elapsed());
+
+#ifdef USE_STL
+ wchar_t wbuf[] = {'1','2','3','4','5','6','7','8','9','0',0};
+ wstring s2;
+ for( i=0;i<100;i++) {
+ s2.append(wbuf);
+ }
+ wchar_t wbuf2[] = {'x','y','z',0};
+ s2.append(wbuf2);
+
+ Stopwatch watch2;
+
+ for(i=0;i<100000;i++) {
+ int f=s2.find_first_of('z',0);
+ }
+ watch2.Stop();
+ printf(" STL: %f",watch2.Elapsed());
+#endif
+ printf("\n");
+
+ }
+ return 0;
+}
+
+
+/************************************************************************************************
+ *
+ * This method tests the performance of various methods.
+ *
+ ************************************************************************************************/
+int CStringTester::TestStringPerformance() {
+ printf("c-String performance tests...\n");
+
+ char* libname[] = {"STL","nsString",0};
+
+ //**************************************************
+ //Test Construction against STL::wstring...
+ //**************************************************
+ {
+ nsCString theConst;
+ for(int z=0;z<10;z++){
+ theConst.Append("0123456789");
+ }
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000000;i++){
+ nsCString s(theConst);
+ }
+ watch1.Stop();
+
+ char wbuf[] = {'a','b','c','d','e','f','g','h','i','j',0};
+ string theConst2;
+ for(int w=0;w<10;w++){
+ theConst2.append(wbuf);
+ }
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000000;i++){
+ string s(theConst2);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Construct(abcde) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Test append("abcde") against STL...
+ //**************************************************
+
+ {
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsCString s;
+ for(int j=0;j<200;j++){
+ s.Append("abcde",5);
+ }
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ string s;
+ for(int j=0;j<200;j++){
+ s.append("abcde",5);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append(abcde) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Test append(char) against STL
+ //**************************************************
+ {
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<500;i++){
+ nsCString s;
+ for(int j=0;j<200;j++){
+ s.Append('a');
+ }
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<500;i++){
+ string s;
+ wchar_t theChar('a');
+ for(int j=0;j<200;j++){
+ s.append('a',1);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append('a') NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Test insert("123") against STL
+ //**************************************************
+ {
+
+ char pbuf1[10]={'a','b','c','d','e','f',0};
+ char pbuf2[10]={'1','2','3',0};
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsCString s("abcdef");
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.Insert(pbuf2,inspos);
+ inspos+=3;
+ }
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ string s(pbuf1);
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.insert(inspos,pbuf2);
+ inspos+=3;
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("insert(123) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Let's test substring searching performance...
+ //**************************************************
+ {
+ char *pbuf1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aab";
+
+ char *pbuf2 = "aab";
+
+ nsCString s(pbuf1);
+
+ Stopwatch watch1;
+ int i;
+ for(i=-1;i<20000;i++) {
+ PRInt32 result=s.Find(pbuf2,PR_FALSE);
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ string ws(pbuf1);
+ for(i=-1;i<20000;i++) {
+ PRInt32 result=ws.find(pbuf2);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Find(aab) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Now let's test comparisons...
+ //**************************************************
+ {
+ char* target="aaaaaaaaaaaaab";
+ size_t theLen=strlen(target);
+
+ Stopwatch watch1;
+ nsCString s("aaaaaaaaaaaaaaaaaaab");
+ int result=0;
+ int i;
+ for(i=-1;i<1000000;i++) {
+ result=s.Compare(target,PR_FALSE,theLen);
+ result++;
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ string ws("aaaaaaaaaaaaaaaaaaab");
+ for(i=-1;i<1000000;i++) {
+ result=ws.compare(0,theLen,target);
+ result++;
+ }
+#endif
+ watch2.Stop();
+
+ printf("Compare(aaaaaaaab) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+
+ }
+
+ //**************************************************
+ //Now lets test string deletions...
+ //**************************************************
+ {
+
+ int strcount=6000;
+ int outerIter=100;
+ int innerIter=100;
+
+ char* buffer = "1234567890";
+ nsCString source1; //build up our target string...
+ int i;
+ for(i=0;i<strcount;i++) {
+ source1.Append(buffer);
+ }
+
+ Stopwatch watch1;
+ for(i=0;i<outerIter;i++) {
+ nsCString s1(source1);
+ for(int j=0;j<innerIter;j++){
+ s1.Cut(20,50);
+ }
+ }
+ watch1.Stop();
+ printf("Cut(...) NSCString: %f ",watch1.Elapsed());
+
+#ifdef USE_STL
+ string source2; //build up our target string...
+ for(i=0;i<strcount;i++) {
+ source2.append(buffer);
+ }
+
+ Stopwatch watch2;
+ for(i=0;i<outerIter;i++) {
+ string s2(source2);
+ for(int j=0;j<innerIter;j++){
+ s2.erase(20,50);
+ }
+ }
+ watch2.Stop();
+
+ printf(" STL: %f",watch2.Elapsed());
+#endif
+ printf("\n");
+ }
+
+
+ //**************************************************
+ //Now let's test the findChar routine...
+ //**************************************************
+ {
+
+ nsCString s1;
+ int i;
+ for(i=0;i<100;i++) {
+ s1.Append("1234567890",10);
+ }
+ s1+="xyz";
+
+ Stopwatch watch1;
+ for(i=0;i<100000;i++) {
+ int f=s1.FindChar('z',PR_FALSE,0);
+ }
+ watch1.Stop();
+ printf("FindChar('z') NSCString: %f ",watch1.Elapsed());
+
+#ifdef USE_STL
+ string s2;
+ for( i=0;i<100;i++) {
+ s2.append("1234567890");
+ }
+ s2.append("xyz");
+
+ Stopwatch watch2;
+ for(i=0;i<100000;i++) {
+ int f=s2.find_first_of('z',0);
+ }
+ watch2.Stop();
+ printf(" STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+#endif
+ printf("\n");
+
+ }
+ return 0;
+}
+
+
+/**
+ * This method is here as a place to put known regressions...
+ *
+ *
+ * @return
+ */
+int CStringTester::TestRegressions() {
+
+ nsString s("FTP: Netscape</a>");
+ PRInt32 result=s.Find("</A>",PR_TRUE);
+
+ //this was a known bug...
+ {
+ nsString s0("");
+ PRInt32 pos=s0.RFind("-->");
+ nsString s1("debug");
+ pos=s1.RFind("b");
+ pos=s1.RFind("de",PR_FALSE,1);
+ pos=10;
+ }
+
+ //this was a known bug...
+ {
+ nsString s0("RDF:RDF");
+ PRInt32 pos=s0.Find(":");
+ pos=10;
+ }
+
+ return result;
+}
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h
new file mode 100644
index 00000000..16ffc11a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h
@@ -0,0 +1,444 @@
+/********************************************************************************************
+ *
+ * MODULES NOTES:
+ *
+ * This file is designed to help test the new nsString classes.
+ *
+ * Contributor(s):
+ * Rick Gessner <rickg@netscape.com>
+ *
+ * History:
+ *
+ * 02.29.2000: Original files (rickg)
+ * 03.02.2000: Flesh out the interface to be compatible with old library (rickg)
+ *
+ ********************************************************************************************/
+
+#ifndef _STRINGTEST2
+#define _STRINGTEST2
+
+
+#include "nsString.h"
+#include <time.h>
+
+#define USE_STL
+
+#ifdef USE_STL
+#include <string>
+using namespace std;
+#endif
+
+#define USE_WIDE 1
+#ifdef USE_WIDE
+ #define stringtype nsString
+ #define astringtype nsAutoString
+ #define chartype PRUnichar
+#else
+ #define stringtype nsCString
+ #define astringtype nsCAutoString
+ #define chartype char
+#endif
+
+#include <stdio.h>
+const double gTicks = 1.0e-7;
+
+
+
+
+
+/********************************************************
+
+ This class's only purpose in life is to test the
+ netscape string library. We exercise the string
+ API's here, and do a bit of performance testing
+ against the standard c++ library string (from STL).
+
+ ********************************************************/
+class CStringTester {
+
+public:
+
+ int TestI18nString();
+
+};
+
+
+
+
+//test 1: unicode char is stripped correctly using StripChars()
+void nsStringTest1(){
+ PRUnichar test[]={0x0041,0x0051,0x0052,0x0000};
+ nsString T(test);
+ PRUnichar result[]={0x0051,0x0052,0x0000};
+ nsString R(result);
+ T.StripChars("ABC");
+ NS_ASSERTION(T.Equals(R), "Test 1: Unicode comparison error");
+}
+//test 2: unicode char is not matched and stripped when high-order byte is not 0x00
+void nsStringTest2(){
+ PRUnichar test[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.StripChars("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+ //test 3: unicode char is not matched and stripped when high-order byte is 0xFF
+void nsStringTest3(){
+
+ PRUnichar test[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(test);
+ T.StripChars("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest4(){
+ //test 4: unicode char is matched and stripped correctly using StripChar()
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.StripChar('A');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest5(){
+ //test 5: unicode char is not matched and stripped when high-order byte is not 0x00
+
+ PRUnichar test[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.StripChar('A');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest6(){
+ //test 6: unicode char is not matched and stripped when high-order byte is 0xFF
+
+ PRUnichar test[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.StripChar('A');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest7(){
+ //test 7: unicode char is matched and replaced correctly using ReplaceChar()
+
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0050,0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest8(){
+ //test 8: unicode char is not matched or replaced when high-order byte != 0x00
+
+ PRUnichar test[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest9(){
+ //test 9: unicode char is not matched or replaced when high-order byte matches search char
+
+ PRUnichar test[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest10(){
+ //test 10: unicode char is not matched or replaced when high-order byte == 0xFF
+
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+
+void nsStringTest11(){
+ //test 11: unicode char is correctly replaced when parameter 1 is a string
+
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0050,0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest12(){
+ //test 12: unicode char is not replaced when high-order byte != 0x00
+
+ PRUnichar test[] = {0x4e41,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e41,0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+void nsStringTest13(){
+ //test 13: unicode char is not replaced when high-order byte matches char in search string
+ PRUnichar test[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",'T');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+void nsStringTest14(){
+ PRUnichar test[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",'T');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest15(){
+ PRUnichar test[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ PRUnichar s = 0xc2; //compiler error on this line
+ T.ReplaceChar(s,'T');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+
+void nsStringTest16(){
+ /* TESTS for ReplaceSubstring()*/
+
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0044,0x0045,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0044,0x0045,0x0046,0x0044,0x0045};
+ nsAutoString R(result);
+ T.ReplaceSubstring("ABC","DEF");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+void nsStringTest17(){
+
+ PRUnichar test[] = {0x0041,0x4e42,0x0043,0x0044,0x0045,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0041,0x4e42,0x0043,0x0044,0x0045,0x0000};
+ nsAutoString R(result);
+ T.ReplaceSubstring("ABC","DEF");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest18(){
+ /*TESTS for Trim()*/
+
+ PRUnichar test[] = {0x0041,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R (result);
+ T.Trim("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest19(){
+ PRUnichar test[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.Trim("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest22(){
+ PRUnichar test[] = {0x4e51,0x4e52,0x4e53,0x4e41,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e51,0x4e52,0x4e53,0x4e41,0x0000};
+ nsAutoString R(result);
+ T.Trim("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+//void nsStringTest23(){
+// PRUnichar test[] = {0x4e51,0x4e52,0x4e53,0x4e22,0x0000};
+// nsAutoString T(test);
+// PRUnichar s(0x4e22);
+// PRUnichar result[] = {0x4e51,0x4e52,0x4e53,0x0000};
+// nsAutoString R(result);
+// T.Trim(s,PR_TRUE,PR_TRUE,PR_FALSE);
+// NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+//}
+void nsStringTest24(){
+ /*TESTS for Find()*/
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Find("ABC") == 0, "Unicode comparison error");
+
+}
+void nsStringTest25(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Find("ABC") == -1, "Unicode comparison error");
+
+}
+void nsStringTest26(){
+ PRUnichar test[] = {0xFFc1,0x0051,0x0052,0x0053,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0x51,0x52};
+ nsAutoString S(str);
+ NS_ASSERTION(T.Find(S) == -1, "Unicode comparison error");
+}
+void nsStringTest27(){
+ /*TESTS for FindChar()*/
+
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar('A') == 0, "Unicode comparison error");
+}
+void nsStringTest28(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar('A') == -1, "Unicode comparison error");
+}
+void nsStringTest29(){
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar(0xc1) == -1, "Unicode comparison error");
+
+}
+void nsStringTest30(){
+ PRUnichar test[] = {0x4132,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar('A1') == -1, "Unicode comparison error");
+}
+ /*TESTS for FindCharInSet()*/
+void nsStringTest31(){
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindCharInSet("ABC") == 0, "Unicode comparison error");
+}
+void nsStringTest32(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindCharInSet("ABC") == -1, "Unicode comparison error");
+
+}
+void nsStringTest33(){
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0x51,0x52};
+ nsAutoString s(str);
+ NS_ASSERTION(T.FindCharInSet(s) == -1, "Unicode comparison error");
+}
+void nsStringTest34(){
+ PRUnichar test[] = {0x4132,0x5132,0x5232,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindCharInSet("ABC") == -1, "Unicode comparison error");
+}
+ /*TESTS for RFind()*/
+void nsStringTest35(){
+
+ PRUnichar test[] = {0x0051,0x0052,0x0041,0x0042,0x0043,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFind("ABC") == 2, "Unicode comparison error");
+}
+void nsStringTest36(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFind("ABC") == -1, "Unicode comparison error");
+}
+void nsStringTest37(){
+ PRUnichar test[] = {0xFFc1,0xFFc2,0xFFc3,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0xc2,0xc3};
+ nsAutoString s(str);
+ NS_ASSERTION(T.RFind(s) == -1, "Unicode comparison error");
+}
+ /*TESTS for RFindCharInSet*/
+void nsStringTest38(){
+
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0000};
+ nsAutoString T(test);
+ int res = T.RFindCharInSet("ABC");
+ NS_ASSERTION(res==0, "Unicode comparison error");
+}
+void nsStringTest39(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFindCharInSet("ABC") == -1, "Unicode comparison error");
+}
+void nsStringTest40(){
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0xc2,0xc3};
+ nsAutoString s(str);
+ NS_ASSERTION(T.RFindCharInSet(s) == -1, "Unicode comparison error");
+}
+void nsStringTest41(){
+ PRUnichar test[] = {0x4132,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFindCharInSet("ABC") == -1, "Unicode comparison error");
+}
+ /* TESTS for Compare() */
+void nsStringTest42(){
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Compare("ABC") == 0, "Unicode comparison error");
+}
+void nsStringTest43(){
+ PRUnichar test[] = {0xc341,0xc342,0xc343};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Compare("ABC") == 1, "Unicode comparison error");
+}
+
+
+int CStringTester::TestI18nString(){
+ nsStringTest1();
+ nsStringTest2();
+ nsStringTest3();
+ nsStringTest4();
+ nsStringTest5();
+ nsStringTest6();
+ nsStringTest7();
+ nsStringTest8();
+ nsStringTest9();
+ nsStringTest10();
+ nsStringTest11();
+ nsStringTest12();
+ nsStringTest13();
+ nsStringTest14();
+ nsStringTest15();
+ nsStringTest16();
+ nsStringTest17();
+ nsStringTest18();
+ nsStringTest19();
+ //nsStringTest20();
+ //nsStringTest21();
+ nsStringTest22();
+ //nsStringTest23();
+ nsStringTest24();
+ nsStringTest25();
+ nsStringTest26();
+ nsStringTest27();
+ nsStringTest28();
+ nsStringTest29();
+ nsStringTest30();
+ nsStringTest31();
+ nsStringTest32();
+ nsStringTest33();
+ nsStringTest34();
+ nsStringTest35();
+ nsStringTest36();
+ nsStringTest37();
+ nsStringTest38();
+ nsStringTest39();
+ nsStringTest40();
+ nsStringTest41();
+ nsStringTest42();
+ nsStringTest43();
+
+ return 0;
+}
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/.cvsignore b/src/libs/xpcom18a4/xpcom/threads/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/threads/Makefile.in b/src/libs/xpcom18a4/xpcom/threads/Makefile.in
new file mode 100644
index 00000000..83433706
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/Makefile.in
@@ -0,0 +1,105 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+ifeq ($(OS_ARCH),WINNT)
+XPIDL_MODULE = xpcom_thread
+else
+XPIDL_MODULE = xpcom_threads
+endif
+LIBRARY_NAME = xpcomthreads_s
+GRE_MODULE = 1
+REQUIRES = string \
+ $(NULL)
+
+
+CSRCS = \
+ plevent.c \
+ $(NULL)
+
+CPPSRCS = \
+ nsAutoLock.cpp \
+ nsEnvironment.cpp \
+ nsEventQueue.cpp \
+ nsEventQueueService.cpp \
+ nsThread.cpp \
+ nsTimerImpl.cpp \
+ nsProcessCommon.cpp \
+ TimerThread.cpp \
+ $(NULL)
+
+EXPORTS = \
+ nsAutoLock.h \
+ plevent.h \
+ nsProcess.h \
+ nsEventQueueUtils.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIThread.idl \
+ nsITimer.idl \
+ nsITimerInternal.idl \
+ nsITimerManager.idl \
+ nsIRunnable.idl \
+ nsIEventTarget.idl \
+ nsIEventQueue.idl \
+ nsIEventQueueService.idl \
+ nsIEnvironment.idl \
+ nsIProcess.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+LOCAL_INCLUDES = -I$(srcdir)/../components
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp b/src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp
new file mode 100644
index 00000000..94076892
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTimerImpl.h"
+#include "TimerThread.h"
+
+#include "nsAutoLock.h"
+#include "pratom.h"
+
+#include "nsIObserverService.h"
+#include "nsIServiceManager.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(TimerThread, nsIRunnable, nsISupportsWeakReference, nsIObserver)
+
+TimerThread::TimerThread() :
+ mInitInProgress(0),
+ mInitialized(PR_FALSE),
+ mLock(nsnull),
+ mCondVar(nsnull),
+ mShutdown(PR_FALSE),
+ mWaiting(PR_FALSE),
+ mSleeping(PR_FALSE),
+ mDelayLineCounter(0),
+ mMinTimerPeriod(0),
+ mTimeoutAdjustment(0)
+{
+}
+
+TimerThread::~TimerThread()
+{
+ if (mCondVar)
+ PR_DestroyCondVar(mCondVar);
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ mThread = nsnull;
+
+ PRInt32 n = mTimers.Count();
+ while (--n >= 0) {
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl *, mTimers[n]);
+ NS_RELEASE(timer);
+ }
+
+ nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
+ if (observerService) {
+ observerService->RemoveObserver(this, "sleep_notification");
+ observerService->RemoveObserver(this, "wake_notification");
+ }
+
+}
+
+nsresult
+TimerThread::InitLocks()
+{
+ NS_ASSERTION(!mLock, "InitLocks called twice?");
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mCondVar = PR_NewCondVar(mLock);
+ if (!mCondVar)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+nsresult TimerThread::Init()
+{
+ if (mInitialized) {
+ if (!mThread)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+ }
+
+ if (PR_AtomicSet(&mInitInProgress, 1) == 0) {
+ nsresult rv;
+
+ mEventQueueService = do_GetService("@mozilla.org/event-queue-service;1", &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIObserverService> observerService
+ (do_GetService("@mozilla.org/observer-service;1", &rv));
+
+ if (NS_SUCCEEDED(rv)) {
+ // We hold on to mThread to keep the thread alive.
+ rv = NS_NewThread(getter_AddRefs(mThread),
+ NS_STATIC_CAST(nsIRunnable*, this),
+ 0,
+ PR_JOINABLE_THREAD,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD);
+
+ if (NS_FAILED(rv)) {
+ mThread = nsnull;
+ }
+ else {
+ observerService->AddObserver(this, "sleep_notification", PR_TRUE);
+ observerService->AddObserver(this, "wake_notification", PR_TRUE);
+ }
+ }
+ }
+
+ PR_Lock(mLock);
+ mInitialized = PR_TRUE;
+ PR_NotifyAllCondVar(mCondVar);
+ PR_Unlock(mLock);
+ }
+ else {
+ PR_Lock(mLock);
+ while (!mInitialized) {
+ PR_WaitCondVar(mCondVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(mLock);
+ }
+
+ if (!mThread)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+nsresult TimerThread::Shutdown()
+{
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ { // lock scope
+ nsAutoLock lock(mLock);
+
+ mShutdown = PR_TRUE;
+
+ // notify the cond var so that Run() can return
+ if (mCondVar && mWaiting)
+ PR_NotifyCondVar(mCondVar);
+
+ nsTimerImpl *timer;
+ for (PRInt32 i = mTimers.Count() - 1; i >= 0; i--) {
+ timer = NS_STATIC_CAST(nsTimerImpl*, mTimers[i]);
+ RemoveTimerInternal(timer);
+ }
+ }
+
+ mThread->Join(); // wait for the thread to die
+ return NS_OK;
+}
+
+// Keep track of how early (positive slack) or late (negative slack) timers
+// are running, and use the filtered slack number to adaptively estimate how
+// early timers should fire to be "on time".
+void TimerThread::UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout,
+ PRIntervalTime aNow)
+{
+ PRInt32 slack = (PRInt32) (aTimeout - aNow);
+ double smoothSlack = 0;
+ PRUint32 i, filterLength;
+ static PRIntervalTime kFilterFeedbackMaxTicks =
+ PR_MillisecondsToInterval(FILTER_FEEDBACK_MAX);
+
+ if (slack > 0) {
+ if (slack > (PRInt32)kFilterFeedbackMaxTicks)
+ slack = kFilterFeedbackMaxTicks;
+ } else {
+ if (slack < -(PRInt32)kFilterFeedbackMaxTicks)
+ slack = -(PRInt32)kFilterFeedbackMaxTicks;
+ }
+ mDelayLine[mDelayLineCounter & DELAY_LINE_LENGTH_MASK] = slack;
+ if (++mDelayLineCounter < DELAY_LINE_LENGTH) {
+ // Startup mode: accumulate a full delay line before filtering.
+ PR_ASSERT(mTimeoutAdjustment == 0);
+ filterLength = 0;
+ } else {
+ // Past startup: compute number of filter taps based on mMinTimerPeriod.
+ if (mMinTimerPeriod == 0) {
+ mMinTimerPeriod = (aDelay != 0) ? aDelay : 1;
+ } else if (aDelay != 0 && aDelay < mMinTimerPeriod) {
+ mMinTimerPeriod = aDelay;
+ }
+
+ filterLength = (PRUint32) (FILTER_DURATION / mMinTimerPeriod);
+ if (filterLength > DELAY_LINE_LENGTH)
+ filterLength = DELAY_LINE_LENGTH;
+ else if (filterLength < 4)
+ filterLength = 4;
+
+ for (i = 1; i <= filterLength; i++)
+ smoothSlack += mDelayLine[(mDelayLineCounter-i) & DELAY_LINE_LENGTH_MASK];
+ smoothSlack /= filterLength;
+
+ // XXXbe do we need amplification? hacking a fudge factor, need testing...
+ mTimeoutAdjustment = (PRInt32) (smoothSlack * 1.5);
+ }
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("UpdateFilter: smoothSlack = %g, filterLength = %u\n",
+ smoothSlack, filterLength));
+ }
+#endif
+}
+
+/* void Run(); */
+NS_IMETHODIMP TimerThread::Run()
+{
+ nsAutoLock lock(mLock);
+
+ while (!mShutdown) {
+ PRIntervalTime waitFor;
+
+ if (mSleeping) {
+ // Sleep for 0.1 seconds while not firing timers.
+ waitFor = PR_MillisecondsToInterval(100);
+ } else {
+ waitFor = PR_INTERVAL_NO_TIMEOUT;
+ PRIntervalTime now = PR_IntervalNow();
+ nsTimerImpl *timer = nsnull;
+
+ if (mTimers.Count() > 0) {
+ timer = NS_STATIC_CAST(nsTimerImpl*, mTimers[0]);
+
+ if (!TIMER_LESS_THAN(now, timer->mTimeout + mTimeoutAdjustment)) {
+ next:
+ // NB: AddRef before the Release under RemoveTimerInternal to avoid
+ // mRefCnt passing through zero, in case all other refs than the one
+ // from mTimers have gone away (the last non-mTimers[i]-ref's Release
+ // must be racing with us, blocked in gThread->RemoveTimer waiting
+ // for TimerThread::mLock, under nsTimerImpl::Release.
+
+ NS_ADDREF(timer);
+ RemoveTimerInternal(timer);
+
+ // We release mLock around the Fire call to avoid deadlock.
+ lock.unlock();
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("Timer thread woke up %dms from when it was supposed to\n",
+ (now >= timer->mTimeout)
+ ? PR_IntervalToMilliseconds(now - timer->mTimeout)
+ : -(PRInt32)PR_IntervalToMilliseconds(timer->mTimeout-now))
+ );
+ }
+#endif
+
+ // We are going to let the call to PostTimerEvent here handle the
+ // release of the timer so that we don't end up releasing the timer
+ // on the TimerThread instead of on the thread it targets.
+ timer->PostTimerEvent();
+ timer = nsnull;
+
+ lock.lock();
+ if (mShutdown)
+ break;
+
+ // Update now, as PostTimerEvent plus the locking may have taken a
+ // tick or two, and we may goto next below.
+ now = PR_IntervalNow();
+ }
+ }
+
+ if (mTimers.Count() > 0) {
+ timer = NS_STATIC_CAST(nsTimerImpl *, mTimers[0]);
+
+ PRIntervalTime timeout = timer->mTimeout + mTimeoutAdjustment;
+
+ // Don't wait at all (even for PR_INTERVAL_NO_WAIT) if the next timer
+ // is due now or overdue.
+ if (!TIMER_LESS_THAN(now, timeout))
+ goto next;
+ waitFor = timeout - now;
+ }
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ if (waitFor == PR_INTERVAL_NO_TIMEOUT)
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("waiting for PR_INTERVAL_NO_TIMEOUT\n"));
+ else
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("waiting for %u\n", PR_IntervalToMilliseconds(waitFor)));
+ }
+#endif
+ }
+
+ mWaiting = PR_TRUE;
+ PR_WaitCondVar(mCondVar, waitFor);
+ mWaiting = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
+{
+ nsAutoLock lock(mLock);
+
+ // Add the timer to our list.
+ PRInt32 i = AddTimerInternal(aTimer);
+ if (i < 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Awaken the timer thread.
+ if (mCondVar && mWaiting && i == 0)
+ PR_NotifyCondVar(mCondVar);
+
+ return NS_OK;
+}
+
+nsresult TimerThread::TimerDelayChanged(nsTimerImpl *aTimer)
+{
+ nsAutoLock lock(mLock);
+
+ // Our caller has a strong ref to aTimer, so it can't go away here under
+ // ReleaseTimerInternal.
+ RemoveTimerInternal(aTimer);
+
+ PRInt32 i = AddTimerInternal(aTimer);
+ if (i < 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Awaken the timer thread.
+ if (mCondVar && mWaiting && i == 0)
+ PR_NotifyCondVar(mCondVar);
+
+ return NS_OK;
+}
+
+nsresult TimerThread::RemoveTimer(nsTimerImpl *aTimer)
+{
+ nsAutoLock lock(mLock);
+
+ // Remove the timer from our array. Tell callers that aTimer was not found
+ // by returning NS_ERROR_NOT_AVAILABLE. Unlike the TimerDelayChanged case
+ // immediately above, our caller may be passing a (now-)weak ref in via the
+ // aTimer param, specifically when nsTimerImpl::Release loses a race with
+ // TimerThread::Run, must wait for the mLock auto-lock here, and during the
+ // wait Run drops the only remaining ref to aTimer via RemoveTimerInternal.
+
+ if (!RemoveTimerInternal(aTimer))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ // Awaken the timer thread.
+ if (mCondVar && mWaiting)
+ PR_NotifyCondVar(mCondVar);
+
+ return NS_OK;
+}
+
+// This function must be called from within a lock
+PRInt32 TimerThread::AddTimerInternal(nsTimerImpl *aTimer)
+{
+ PRIntervalTime now = PR_IntervalNow();
+ PRInt32 count = mTimers.Count();
+ PRInt32 i = 0;
+ for (; i < count; i++) {
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl *, mTimers[i]);
+
+ // Don't break till we have skipped any overdue timers. Do not include
+ // mTimeoutAdjustment here, because we are really trying to avoid calling
+ // TIMER_LESS_THAN(t, u), where the t is now + DELAY_INTERVAL_MAX, u is
+ // now - overdue, and DELAY_INTERVAL_MAX + overdue > DELAY_INTERVAL_LIMIT.
+ // In other words, we want to use now-based time, now adjusted time, even
+ // though "overdue" ultimately depends on adjusted time.
+
+ // XXX does this hold for TYPE_REPEATING_PRECISE? /be
+
+ if (TIMER_LESS_THAN(now, timer->mTimeout) &&
+ TIMER_LESS_THAN(aTimer->mTimeout, timer->mTimeout)) {
+ break;
+ }
+ }
+
+ if (!mTimers.InsertElementAt(aTimer, i))
+ return -1;
+
+ aTimer->mArmed = PR_TRUE;
+ NS_ADDREF(aTimer);
+ return i;
+}
+
+PRBool TimerThread::RemoveTimerInternal(nsTimerImpl *aTimer)
+{
+ if (!mTimers.RemoveElement(aTimer))
+ return PR_FALSE;
+
+ // Order is crucial here -- see nsTimerImpl::Release.
+ aTimer->mArmed = PR_FALSE;
+ NS_RELEASE(aTimer);
+ return PR_TRUE;
+}
+
+void TimerThread::DoBeforeSleep()
+{
+ mSleeping = PR_TRUE;
+}
+
+void TimerThread::DoAfterSleep()
+{
+ for (PRInt32 i = 0; i < mTimers.Count(); i ++) {
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl*, mTimers[i]);
+ // get and set the delay to cause its timeout to be recomputed
+ PRUint32 delay;
+ timer->GetDelay(&delay);
+ timer->SetDelay(delay);
+ }
+
+ // nuke the stored adjustments, so they get recalibrated
+ mTimeoutAdjustment = 0;
+ mDelayLineCounter = 0;
+ mSleeping = PR_FALSE;
+}
+
+
+/* void observe (in nsISupports aSubject, in string aTopic, in wstring aData); */
+NS_IMETHODIMP
+TimerThread::Observe(nsISupports* /* aSubject */, const char *aTopic, const PRUnichar* /* aData */)
+{
+ if (strcmp(aTopic, "sleep_notification") == 0)
+ DoBeforeSleep();
+ else if (strcmp(aTopic, "wake_notification") == 0)
+ DoAfterSleep();
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/TimerThread.h b/src/libs/xpcom18a4/xpcom/threads/TimerThread.h
new file mode 100644
index 00000000..fa23cfc9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/TimerThread.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef TimerThread_h___
+#define TimerThread_h___
+
+#include "nsWeakReference.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIObserver.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+
+#include "nsTimerImpl.h"
+
+#include "nsVoidArray.h"
+
+#include "prcvar.h"
+#include "prinrval.h"
+#include "prlock.h"
+
+class TimerThread : public nsSupportsWeakReference,
+ public nsIRunnable,
+ public nsIObserver
+{
+public:
+ TimerThread();
+ NS_HIDDEN_(nsresult) InitLocks();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRUNNABLE
+ NS_DECL_NSIOBSERVER
+
+ NS_HIDDEN_(nsresult) Init();
+ NS_HIDDEN_(nsresult) Shutdown();
+
+ nsresult AddTimer(nsTimerImpl *aTimer);
+ nsresult TimerDelayChanged(nsTimerImpl *aTimer);
+ nsresult RemoveTimer(nsTimerImpl *aTimer);
+
+#define FILTER_DURATION 1e3 /* one second */
+#define FILTER_FEEDBACK_MAX 100 /* 1/10th of a second */
+
+ void UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout,
+ PRIntervalTime aNow);
+
+ // For use by nsTimerImpl::Fire()
+ nsCOMPtr<nsIEventQueueService> mEventQueueService;
+
+ void DoBeforeSleep();
+ void DoAfterSleep();
+
+private:
+ ~TimerThread();
+
+ PRInt32 mInitInProgress;
+ PRBool mInitialized;
+
+ // These two internal helper methods must be called while mLock is held.
+ // AddTimerInternal returns the position where the timer was added in the
+ // list, or -1 if it failed.
+ PRInt32 AddTimerInternal(nsTimerImpl *aTimer);
+ PRBool RemoveTimerInternal(nsTimerImpl *aTimer);
+
+ nsCOMPtr<nsIThread> mThread;
+ PRLock *mLock;
+ PRCondVar *mCondVar;
+
+ PRPackedBool mShutdown;
+ PRPackedBool mWaiting;
+ PRPackedBool mSleeping;
+
+ nsVoidArray mTimers;
+
+#define DELAY_LINE_LENGTH_LOG2 5
+#define DELAY_LINE_LENGTH_MASK PR_BITMASK(DELAY_LINE_LENGTH_LOG2)
+#define DELAY_LINE_LENGTH PR_BIT(DELAY_LINE_LENGTH_LOG2)
+
+ PRInt32 mDelayLine[DELAY_LINE_LENGTH];
+ PRUint32 mDelayLineCounter;
+ PRUint32 mMinTimerPeriod; // milliseconds
+ PRInt32 mTimeoutAdjustment;
+};
+
+#endif /* TimerThread_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp
new file mode 100644
index 00000000..df89408c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp
@@ -0,0 +1,435 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAutoLock.h"
+
+#ifdef DEBUG
+
+#include "plhash.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "prthread.h"
+#include "nsDebug.h"
+#include "nsVoidArray.h"
+
+#ifdef NS_TRACE_MALLOC_XXX
+# include <stdio.h>
+# include "nsTraceMalloc.h"
+#endif
+
+static PRUintn LockStackTPI = (PRUintn)-1;
+static PLHashTable* OrderTable = 0;
+static PRLock* OrderTableLock = 0;
+
+static const char* const LockTypeNames[] = {"Lock", "Monitor", "CMonitor"};
+
+struct nsNamedVector : public nsVoidArray {
+ const char* mName;
+
+#ifdef NS_TRACE_MALLOC_XXX
+ // Callsites for the inner locks/monitors stored in our base nsVoidArray.
+ // This array parallels our base nsVoidArray.
+ nsVoidArray mInnerSites;
+#endif
+
+ nsNamedVector(const char* name = 0, PRUint32 initialSize = 0)
+ : nsVoidArray(initialSize),
+ mName(name)
+ {
+ }
+};
+
+static void * PR_CALLBACK
+_hash_alloc_table(void *pool, PRSize size)
+{
+ return operator new(size);
+}
+
+static void PR_CALLBACK
+_hash_free_table(void *pool, void *item)
+{
+ operator delete(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+_hash_alloc_entry(void *pool, const void *key)
+{
+ return new PLHashEntry;
+}
+
+/*
+ * Because monitors and locks may be associated with an nsAutoLockBase,
+ * without having had their associated nsNamedVector created explicitly in
+ * nsAutoMonitor::NewMonitor/DeleteMonitor, we need to provide a freeEntry
+ * PLHashTable hook, to avoid leaking nsNamedVectors which are replaced by
+ * nsAutoMonitor::NewMonitor.
+ *
+ * There is still a problem with the OrderTable containing orphaned
+ * nsNamedVector entries, for manually created locks wrapped by nsAutoLocks.
+ * (there should be no manually created monitors wrapped by nsAutoMonitors:
+ * you should use nsAutoMonitor::NewMonitor and nsAutoMonitor::DestroyMonitor
+ * instead of PR_NewMonitor and PR_DestroyMonitor). These lock vectors don't
+ * strictly leak, as they are killed on shutdown, but there are unnecessary
+ * named vectors in the hash table that outlive their associated locks.
+ *
+ * XXX so we should have nsLock, nsMonitor, etc. and strongly type their
+ * XXX nsAutoXXX counterparts to take only the non-auto types as inputs
+ */
+static void PR_CALLBACK
+_hash_free_entry(void *pool, PLHashEntry *entry, PRUintn flag)
+{
+ nsNamedVector* vec = (nsNamedVector*) entry->value;
+ if (vec) {
+ entry->value = 0;
+ delete vec;
+ }
+ if (flag == HT_FREE_ENTRY)
+ delete entry;
+}
+
+static const PLHashAllocOps _hash_alloc_ops = {
+ _hash_alloc_table, _hash_free_table,
+ _hash_alloc_entry, _hash_free_entry
+};
+
+PR_STATIC_CALLBACK(PRIntn)
+_purge_one(PLHashEntry* he, PRIntn cnt, void* arg)
+{
+ nsNamedVector* vec = (nsNamedVector*) he->value;
+
+ if (he->key == arg)
+ return HT_ENUMERATE_REMOVE;
+ vec->RemoveElement(arg);
+ return HT_ENUMERATE_NEXT;
+}
+
+PR_STATIC_CALLBACK(void)
+OnMonitorRecycle(void* addr)
+{
+ PR_Lock(OrderTableLock);
+ PL_HashTableEnumerateEntries(OrderTable, _purge_one, addr);
+ PR_Unlock(OrderTableLock);
+}
+
+PR_STATIC_CALLBACK(PLHashNumber)
+_hash_pointer(const void* key)
+{
+ return PLHashNumber(NS_PTR_TO_INT32(key)) >> 2;
+}
+
+// Must be single-threaded here, early in primordial thread.
+static void InitAutoLockStatics()
+{
+ (void) PR_NewThreadPrivateIndex(&LockStackTPI, 0);
+ OrderTable = PL_NewHashTable(64, _hash_pointer,
+ PL_CompareValues, PL_CompareValues,
+ &_hash_alloc_ops, 0);
+ if (OrderTable && !(OrderTableLock = PR_NewLock())) {
+ PL_HashTableDestroy(OrderTable);
+ OrderTable = 0;
+ }
+ PR_CSetOnMonitorRecycle(OnMonitorRecycle);
+}
+
+void _FreeAutoLockStatics()
+{
+ PLHashTable* table = OrderTable;
+ if (!table) return;
+
+ // Called at shutdown, so we don't need to lock.
+ PR_CSetOnMonitorRecycle(0);
+ PR_DestroyLock(OrderTableLock);
+ OrderTableLock = 0;
+ PL_HashTableDestroy(table);
+ OrderTable = 0;
+}
+
+static nsNamedVector* GetVector(PLHashTable* table, const void* key)
+{
+ PLHashNumber hash = _hash_pointer(key);
+ PLHashEntry** hep = PL_HashTableRawLookup(table, hash, key);
+ PLHashEntry* he = *hep;
+ if (he)
+ return (nsNamedVector*) he->value;
+ nsNamedVector* vec = new nsNamedVector();
+ if (vec)
+ PL_HashTableRawAdd(table, hep, hash, key, vec);
+ return vec;
+}
+
+// We maintain an acyclic graph in OrderTable, so recursion can't diverge.
+static PRBool Reachable(PLHashTable* table, const void* goal, const void* start)
+{
+ PR_ASSERT(goal);
+ PR_ASSERT(start);
+ nsNamedVector* vec = GetVector(table, start);
+ for (PRUint32 i = 0, n = vec->Count(); i < n; i++) {
+ void* addr = vec->ElementAt(i);
+ if (addr == goal || Reachable(table, goal, addr))
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static PRBool WellOrdered(const void* addr1, const void* addr2,
+ const void *callsite2, PRUint32* index2p,
+ nsNamedVector** vec1p, nsNamedVector** vec2p)
+{
+ PRBool rv = PR_TRUE;
+ PLHashTable* table = OrderTable;
+ if (!table) return rv;
+ PR_Lock(OrderTableLock);
+
+ // Check whether we've already asserted (addr1 < addr2).
+ nsNamedVector* vec1 = GetVector(table, addr1);
+ if (vec1) {
+ PRUint32 i, n;
+
+ for (i = 0, n = vec1->Count(); i < n; i++)
+ if (vec1->ElementAt(i) == addr2)
+ break;
+
+ if (i == n) {
+ // Now check for (addr2 < addr1) and return false if so.
+ nsNamedVector* vec2 = GetVector(table, addr2);
+ if (vec2) {
+ for (i = 0, n = vec2->Count(); i < n; i++) {
+ void* addri = vec2->ElementAt(i);
+ PR_ASSERT(addri);
+ if (addri == addr1 || Reachable(table, addr1, addri)) {
+ *index2p = i;
+ *vec1p = vec1;
+ *vec2p = vec2;
+ rv = PR_FALSE;
+ break;
+ }
+ }
+
+ if (rv) {
+ // Assert (addr1 < addr2) into the order table.
+ // XXX fix plvector/nsVector to use const void*
+ vec1->AppendElement((void*) addr2);
+#ifdef NS_TRACE_MALLOC_XXX
+ vec1->mInnerSites.AppendElement((void*) callsite2);
+#endif
+ }
+ }
+ }
+ }
+
+ PR_Unlock(OrderTableLock);
+ return rv;
+}
+
+nsAutoLockBase::nsAutoLockBase(void* addr, nsAutoLockType type)
+{
+ if (LockStackTPI == PRUintn(-1))
+ InitAutoLockStatics();
+
+ nsAutoLockBase* stackTop =
+ (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ if (stackTop) {
+ if (stackTop->mAddr == addr) {
+ // Ignore reentry: it's legal for monitors, and NSPR will assert
+ // if you reenter a PRLock.
+ } else if (!addr) {
+ // Ignore null addresses: the caller promises not to use the
+ // lock at all, and NSPR will assert if you enter it.
+ } else {
+ const void* node =
+#ifdef NS_TRACE_MALLOC_XXX
+ NS_GetStackTrace(1)
+#else
+ nsnull
+#endif
+ ;
+ nsNamedVector* vec1;
+ nsNamedVector* vec2;
+ PRUint32 i2;
+
+ if (!WellOrdered(stackTop->mAddr, addr, node, &i2, &vec1, &vec2)) {
+ char buf[128];
+ PR_snprintf(buf, sizeof buf,
+ "Potential deadlock between %s%s@%p and %s%s@%p",
+ vec1->mName ? vec1->mName : "",
+ LockTypeNames[stackTop->mType],
+ stackTop->mAddr,
+ vec2->mName ? vec2->mName : "",
+ LockTypeNames[type],
+ addr);
+#ifdef NS_TRACE_MALLOC_XXX
+ fprintf(stderr, "\n*** %s\n\nCurrent stack:\n", buf);
+ NS_DumpStackTrace(node, stderr);
+
+ fputs("\nPrevious stack:\n", stderr);
+ NS_DumpStackTrace(vec2->mInnerSites.ElementAt(i2), stderr);
+ putc('\n', stderr);
+#endif
+ NS_ERROR(buf);
+ }
+ }
+ }
+
+ mAddr = addr;
+ mDown = stackTop;
+ mType = type;
+ if (mAddr)
+ (void) PR_SetThreadPrivate(LockStackTPI, this);
+}
+
+nsAutoLockBase::~nsAutoLockBase()
+{
+ if (mAddr)
+ (void) PR_SetThreadPrivate(LockStackTPI, mDown);
+}
+
+void nsAutoLockBase::Show()
+{
+ if (!mAddr)
+ return;
+ nsAutoLockBase* curr = (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ nsAutoLockBase* prev = nsnull;
+ while (curr != mDown) {
+ prev = curr;
+ curr = prev->mDown;
+ }
+ if (!prev)
+ PR_SetThreadPrivate(LockStackTPI, this);
+ else
+ prev->mDown = this;
+}
+
+void nsAutoLockBase::Hide()
+{
+ if (!mAddr)
+ return;
+ nsAutoLockBase* curr = (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ nsAutoLockBase* prev = nsnull;
+ while (curr != this) {
+ prev = curr;
+ curr = prev->mDown;
+ }
+ if (!prev)
+ PR_SetThreadPrivate(LockStackTPI, mDown);
+ else
+ prev->mDown = mDown;
+}
+
+#endif /* DEBUG */
+
+PRMonitor* nsAutoMonitor::NewMonitor(const char* name)
+{
+ PRMonitor* mon = PR_NewMonitor();
+#ifdef DEBUG
+ if (mon && OrderTable) {
+ nsNamedVector* value = new nsNamedVector(name);
+ if (value) {
+ PR_Lock(OrderTableLock);
+ PL_HashTableAdd(OrderTable, mon, value);
+ PR_Unlock(OrderTableLock);
+ }
+ }
+#endif
+ return mon;
+}
+
+void nsAutoMonitor::DestroyMonitor(PRMonitor* mon)
+{
+#ifdef DEBUG
+ if (OrderTable)
+ OnMonitorRecycle(mon);
+#endif
+ PR_DestroyMonitor(mon);
+}
+
+void nsAutoMonitor::Enter()
+{
+#ifdef DEBUG
+ if (!mAddr) {
+ NS_ERROR("It is not legal to enter a null monitor");
+ return;
+ }
+ nsAutoLockBase* stackTop =
+ (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ NS_ASSERTION(stackTop == mDown, "non-LIFO nsAutoMonitor::Enter");
+ mDown = stackTop;
+ (void) PR_SetThreadPrivate(LockStackTPI, this);
+#endif
+ PR_EnterMonitor(mMonitor);
+ mLockCount += 1;
+}
+
+void nsAutoMonitor::Exit()
+{
+#ifdef DEBUG
+ if (!mAddr) {
+ NS_ERROR("It is not legal to exit a null monitor");
+ return;
+ }
+ (void) PR_SetThreadPrivate(LockStackTPI, mDown);
+#endif
+ PRStatus status = PR_ExitMonitor(mMonitor);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
+ mLockCount -= 1;
+}
+
+// XXX we don't worry about cached monitors being destroyed behind our back.
+// XXX current NSPR (mozilla/nsprpub/pr/src/threads/prcmon.c) never destroys
+// XXX a cached monitor! potential resource pig in conjunction with necko...
+
+void nsAutoCMonitor::Enter()
+{
+#ifdef DEBUG
+ nsAutoLockBase* stackTop =
+ (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ NS_ASSERTION(stackTop == mDown, "non-LIFO nsAutoCMonitor::Enter");
+ mDown = stackTop;
+ (void) PR_SetThreadPrivate(LockStackTPI, this);
+#endif
+ PR_CEnterMonitor(mLockObject);
+ mLockCount += 1;
+}
+
+void nsAutoCMonitor::Exit()
+{
+#ifdef DEBUG
+ (void) PR_SetThreadPrivate(LockStackTPI, mDown);
+#endif
+ PRStatus status = PR_CExitMonitor(mLockObject);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
+ mLockCount -= 1;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h
new file mode 100644
index 00000000..a82d6ffc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/*
+ A stack-based lock object that makes using PRLock a bit more
+ convenient. It acquires the monitor when constructed, and releases
+ it when it goes out of scope.
+
+ For example,
+
+ class Foo {
+ private:
+ PRLock* mLock;
+
+ public:
+ Foo(void) {
+ mLock = PR_NewLock();
+ }
+
+ ~Foo(void) {
+ PR_DestroyLock(mLock);
+ }
+
+ void ThreadSafeMethod(void) {
+ // we're don't hold the lock yet...
+
+ nsAutoLock lock(mLock);
+ // ...but now we do.
+
+ // we even can do wacky stuff like return from arbitrary places w/o
+ // worrying about forgetting to release the lock
+ if (some_weird_condition)
+ return;
+
+ // otherwise do some other stuff
+ }
+
+ void ThreadSafeBlockScope(void) {
+ // we're not in the lock here...
+
+ {
+ nsAutoLock lock(mLock);
+ // but we are now, at least until the block scope closes
+ }
+
+ // ...now we're not in the lock anymore
+ }
+ };
+
+ A similar stack-based locking object is available for PRMonitor. The
+ major difference is that the PRMonitor must be created and destroyed
+ via the static methods on nsAutoMonitor.
+
+ For example:
+ Foo::Foo() {
+ mMon = nsAutoMonitor::NewMonitor("FooMonitor");
+ }
+ nsresult Foo::MyMethod(...) {
+ nsAutoMonitor mon(mMon);
+ ...
+ // go ahead and do deeply nested returns...
+ return NS_ERROR_FAILURE;
+ ...
+ // or call Wait or Notify...
+ mon.Wait();
+ ...
+ // cleanup is automatic
+ }
+ */
+
+#ifndef nsAutoLock_h__
+#define nsAutoLock_h__
+
+#include "nscore.h"
+#include "prlock.h"
+#include "prlog.h"
+
+/**
+ * nsAutoLockBase
+ * This is the base class for the stack-based locking objects.
+ * Clients of derived classes need not play with this superclass.
+ **/
+class NS_COM nsAutoLockBase {
+protected:
+ nsAutoLockBase() {}
+ enum nsAutoLockType {eAutoLock, eAutoMonitor, eAutoCMonitor};
+
+#ifdef DEBUG
+ nsAutoLockBase(void* addr, nsAutoLockType type);
+ ~nsAutoLockBase();
+
+ void Show();
+ void Hide();
+
+ void* mAddr;
+ nsAutoLockBase* mDown;
+ nsAutoLockType mType;
+#else
+ nsAutoLockBase(void* addr, nsAutoLockType type) {}
+ ~nsAutoLockBase() {}
+
+ void Show() {}
+ void Hide() {}
+#endif
+};
+
+/**
+ * nsAutoLock
+ * Stack-based locking object for PRLock.
+ **/
+class NS_COM nsAutoLock : public nsAutoLockBase {
+private:
+ PRLock* mLock;
+ PRBool mLocked;
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // construct or assign an nsAutoLock object incorrectly.
+ nsAutoLock(void);
+ nsAutoLock(const nsAutoLock& /*aLock*/);
+ nsAutoLock& operator =(const nsAutoLock& /*aLock*/);
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // attempt to create an nsAutoLock object on the heap.
+ static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+ static void operator delete(void* /*memory*/);
+
+public:
+ /**
+ * Constructor
+ * The constructor aquires the given lock. The destructor
+ * releases the lock.
+ *
+ * @param aLock A valid PRLock* returned from the NSPR's
+ * PR_NewLock() function.
+ **/
+ nsAutoLock(PRLock* aLock)
+ : nsAutoLockBase(aLock, eAutoLock),
+ mLock(aLock),
+ mLocked(PR_TRUE) {
+ PR_ASSERT(mLock);
+
+ // This will assert deep in the bowels of NSPR if you attempt
+ // to re-enter the lock.
+ PR_Lock(mLock);
+ }
+
+ ~nsAutoLock(void) {
+ if (mLocked)
+ PR_Unlock(mLock);
+ }
+
+ /**
+ * lock
+ * Client may call this to reaquire the given lock. Take special
+ * note that attempting to aquire a locked lock will hang or crash.
+ **/
+ void lock() {
+ Show();
+ PR_ASSERT(!mLocked);
+ PR_Lock(mLock);
+ mLocked = PR_TRUE;
+ }
+
+
+ /**
+ * unlock
+ * Client may call this to release the given lock. Take special
+ * note unlocking an unlocked lock has undefined results.
+ **/
+ void unlock() {
+ PR_ASSERT(mLocked);
+ PR_Unlock(mLock);
+ mLocked = PR_FALSE;
+ Hide();
+ }
+};
+
+#include "prcmon.h"
+#include "nsError.h"
+#include "nsDebug.h"
+
+class NS_COM nsAutoMonitor : public nsAutoLockBase {
+public:
+
+ /**
+ * NewMonitor
+ * Allocates a new PRMonitor for use with nsAutoMonitor.
+ * @param name A (unique /be?) name which can reference this monitor
+ * @returns nsnull if failure
+ * A valid PRMonitor* is successful while must be destroyed
+ * by nsAutoMonitor::DestroyMonitor()
+ **/
+ static PRMonitor* NewMonitor(const char* name);
+ static void DestroyMonitor(PRMonitor* mon);
+
+
+ /**
+ * Constructor
+ * The constructor locks the given monitor. During destruction
+ * the monitor will be unlocked.
+ *
+ * @param mon A valid PRMonitor* returned from
+ * nsAutoMonitor::NewMonitor().
+ **/
+ nsAutoMonitor(PRMonitor* mon)
+ : nsAutoLockBase((void*)mon, eAutoMonitor),
+ mMonitor(mon), mLockCount(0)
+ {
+ NS_ASSERTION(mMonitor, "null monitor");
+ if (mMonitor) {
+ PR_EnterMonitor(mMonitor);
+ mLockCount = 1;
+ }
+ }
+
+ ~nsAutoMonitor() {
+ NS_ASSERTION(mMonitor, "null monitor");
+ if (mMonitor && mLockCount) {
+#ifdef DEBUG
+ PRStatus status =
+#endif
+ PR_ExitMonitor(mMonitor);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
+ }
+ }
+
+ /**
+ * Enter
+ * Client may call this to reenter the given monitor.
+ * @see prmon.h
+ **/
+ void Enter();
+
+ /**
+ * Exit
+ * Client may call this to exit the given monitor.
+ * @see prmon.h
+ **/
+ void Exit();
+
+ /**
+ * Wait
+ * @see prmon.h
+ **/
+ nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
+ return PR_Wait(mMonitor, interval) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ /**
+ * Notify
+ * @see prmon.h
+ **/
+ nsresult Notify() {
+ return PR_Notify(mMonitor) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ /**
+ * NotifyAll
+ * @see prmon.h
+ **/
+ nsresult NotifyAll() {
+ return PR_NotifyAll(mMonitor) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+private:
+ PRMonitor* mMonitor;
+ PRInt32 mLockCount;
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // construct or assign an nsAutoLock object incorrectly.
+ nsAutoMonitor(void);
+ nsAutoMonitor(const nsAutoMonitor& /*aMon*/);
+ nsAutoMonitor& operator =(const nsAutoMonitor& /*aMon*/);
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // attempt to create an nsAutoLock object on the heap.
+ static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+ static void operator delete(void* /*memory*/);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Once again, this time with a cache...
+// (Using this avoids the need to allocate a PRMonitor, which may be useful when
+// a large number of objects of the same class need associated monitors.)
+
+#include "prcmon.h"
+#include "nsError.h"
+
+class NS_COM nsAutoCMonitor : public nsAutoLockBase {
+public:
+ nsAutoCMonitor(void* lockObject)
+ : nsAutoLockBase(lockObject, eAutoCMonitor),
+ mLockObject(lockObject), mLockCount(0)
+ {
+ NS_ASSERTION(lockObject, "null lock object");
+ PR_CEnterMonitor(mLockObject);
+ mLockCount = 1;
+ }
+
+ ~nsAutoCMonitor() {
+ if (mLockCount) {
+#ifdef DEBUG
+ PRStatus status =
+#endif
+ PR_CExitMonitor(mLockObject);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
+ }
+ }
+
+ void Enter();
+ void Exit();
+
+ nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
+ return PR_CWait(mLockObject, interval) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ nsresult Notify() {
+ return PR_CNotify(mLockObject) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ nsresult NotifyAll() {
+ return PR_CNotifyAll(mLockObject) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+private:
+ void* mLockObject;
+ PRInt32 mLockCount;
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // construct or assign an nsAutoLock object incorrectly.
+ nsAutoCMonitor(void);
+ nsAutoCMonitor(const nsAutoCMonitor& /*aMon*/);
+ nsAutoCMonitor& operator =(const nsAutoCMonitor& /*aMon*/);
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // attempt to create an nsAutoLock object on the heap.
+ static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+ static void operator delete(void* /*memory*/);
+};
+
+#endif // nsAutoLock_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp
new file mode 100644
index 00000000..139b24a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla embedding code.
+ *
+ * The Initial Developers of the Original Code are
+ * Benjamin Smedberg <bsmedberg@covad.net> and
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003/2004
+ * 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 "nsEnvironment.h"
+#include "prenv.h"
+#include "prprf.h"
+#include "nsAutoLock.h"
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsPromiseFlatString.h"
+#include "nsDependentString.h"
+#include "nsNativeCharsetUtils.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsEnvironment, nsIEnvironment)
+
+NS_METHOD
+nsEnvironment::Create(nsISupports *aOuter, REFNSIID aIID,
+ void **aResult)
+{
+ nsresult rv;
+ *aResult = nsnull;
+
+ if (aOuter != nsnull) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ nsEnvironment* obj = new nsEnvironment();
+ if (!obj) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ obj->mLock = PR_NewLock();
+ if (!obj->mLock) {
+ delete obj;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = obj->QueryInterface(aIID, aResult);
+ if (NS_FAILED(rv)) {
+ delete obj;
+ }
+ return rv;
+}
+
+nsEnvironment::~nsEnvironment()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+NS_IMETHODIMP
+nsEnvironment::Exists(const nsAString& aName, PRBool *aOutValue)
+{
+ nsCAutoString nativeName;
+ nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCAutoString nativeVal;
+#if defined(XP_UNIX)
+ /* For Unix/Linux platforms we follow the Unix definition:
+ * An environment variable exists when |getenv()| returns a non-NULL value.
+ * An environment variable does not exist when |getenv()| returns NULL.
+ */
+ const char *value = PR_GetEnv(nativeName.get());
+
+ *aOutValue = (value)?(PR_TRUE):(PR_FALSE);
+#else
+ /* For non-Unix/Linux platforms we have to fall back to a
+ * "portable" definition (which is incorrect for Unix/Linux!!!!)
+ * which simply checks whether the string returned by |Get()| is empty
+ * or not.
+ */
+ nsAutoString value;
+ Get(aName, value);
+ *aOutValue = (value.IsEmpty())?(PR_FALSE):(PR_TRUE);
+#endif /* XP_UNIX */
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue)
+{
+ nsCAutoString nativeName;
+ nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCAutoString nativeVal;
+ const char *value = PR_GetEnv(nativeName.get());
+ if (value) {
+ rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue);
+ } else {
+ aOutValue.Truncate();
+ rv = NS_OK;
+ }
+
+ return rv;
+}
+
+/* Environment strings must have static duration; We're gonna leak all of this
+ * at shutdown: this is by design, caused how Unix/Linux implement environment
+ * vars.
+ */
+
+typedef nsBaseHashtableET<nsCStringHashKey,char*> EnvEntryType;
+typedef nsTHashtable<EnvEntryType> EnvHashType;
+
+static EnvHashType *gEnvHash = nsnull;
+
+static PRBool
+EnsureEnvHash()
+{
+ if (gEnvHash)
+ return PR_TRUE;
+
+ gEnvHash = new EnvHashType;
+ if (!gEnvHash)
+ return PR_FALSE;
+
+ if(gEnvHash->Init())
+ return PR_TRUE;
+
+ delete gEnvHash;
+ gEnvHash = nsnull;
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP
+nsEnvironment::Set(const nsAString& aName, const nsAString& aValue)
+{
+ nsCAutoString nativeName;
+ nsCAutoString nativeVal;
+
+ nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_CopyUnicodeToNative(aValue, nativeVal);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoLock lock(mLock); // autolock unlocks automagically
+
+ if (!EnsureEnvHash()){
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ EnvEntryType* entry = gEnvHash->PutEntry(nativeName);
+ if (!entry) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ char* newData = PR_smprintf("%s=%s",
+ nativeName.get(),
+ nativeVal.get());
+ if (!newData) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PR_SetEnv(newData);
+ if (entry->mData) {
+ PR_smprintf_free(entry->mData);
+ }
+ entry->mData = newData;
+ return NS_OK;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h
new file mode 100644
index 00000000..46e8d66a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla embedding code.
+ *
+ * The Initial Developers of the Original Code are
+ * Benjamin Smedberg <bsmedberg@covad.net> and
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003/2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsEnvironment_h__
+#define nsEnvironment_h__
+
+#include "nsIEnvironment.h"
+#include "prlock.h"
+
+#define NS_ENVIRONMENT_CID \
+ { 0X3D68F92UL, 0X9513, 0X4E25, \
+ { 0X9B, 0XE9, 0X7C, 0XB2, 0X39, 0X87, 0X41, 0X72 } }
+#define NS_ENVIRONMENT_CONTRACTID "@mozilla.org/process/environment;1"
+
+class nsEnvironment : public nsIEnvironment
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIENVIRONMENT
+
+ static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID,
+ void **aResult);
+
+private:
+ nsEnvironment() { }
+ ~nsEnvironment();
+
+ PRLock *mLock;
+};
+
+#endif /* !nsEnvironment_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp
new file mode 100644
index 00000000..7dc8f089
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp
@@ -0,0 +1,632 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+#include "nsEventQueue.h"
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+#include "nsIServiceManager.h"
+#include "nsIObserverService.h"
+
+#include "nsString.h"
+
+#include "prlog.h"
+
+#ifdef NS_DEBUG
+#include "prprf.h"
+#endif
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+/* found these logs useful in conjunction with netlibStreamEvent logging
+ from netwerk. */
+PRLogModuleInfo* gEventQueueLog = 0;
+PRUint32 gEventQueueLogCount = 0;
+PRUint32 gEventQueueLogPPCount = 0;
+static int gEventQueueLogPPLevel = 0;
+static PLEventQueue *gEventQueueLogQueue = 0;
+static PRThread *gEventQueueLogThread = 0;
+#endif
+
+// in a real system, these would be members in a header class...
+static const char gActivatedNotification[] = "nsIEventQueueActivated";
+static const char gDestroyedNotification[] = "nsIEventQueueDestroyed";
+
+nsEventQueueImpl::nsEventQueueImpl()
+{
+ NS_ADDREF_THIS();
+ /* The slightly weird ownership model for eventqueues goes like this:
+
+ General:
+ There's an addref from the factory generally held by whoever asked for
+ the queue. The queue addrefs itself (right here) and releases itself
+ after someone calls StopAcceptingEvents() on the queue and when it is
+ dark and empty (in CheckForDeactivation()).
+
+ Chained queues:
+
+ Eldest queue:
+ The eldest queue in a chain is held on to by the EventQueueService
+ in a hash table, so it is possible that the eldest queue may not be
+ released until the EventQueueService is shutdown.
+ You may not call StopAcceptingEvents() on this queue until you have
+ done so on all younger queues.
+
+ General:
+ Each queue holds a reference to their immediate elder link and a weak
+ reference to their immediate younger link. Because you must shut down
+ queues from youngest to eldest, all the references will be removed.
+
+ It happens something like:
+ queue->StopAcceptingEvents()
+ {
+ CheckForDeactivation()
+ {
+ -- hopefully we are able to shutdown now --
+ Unlink()
+ {
+ -- remove the reference we hold to our elder queue --
+ -- NULL out our elder queues weak reference to us --
+ }
+ RELEASE ourself (to balance the ADDREF here in the constructor)
+ -- and we should go away. --
+ }
+ }
+
+
+ Notes:
+ A dark queue no longer accepts events. An empty queue simply has no events.
+ */
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Created [queue=%lx]",(long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+
+ mYoungerQueue = nsnull;
+ mEventQueue = nsnull;
+ mAcceptingEvents = PR_TRUE;
+ mCouldHaveEvents = PR_TRUE;
+}
+
+nsEventQueueImpl::~nsEventQueueImpl()
+{
+ Unlink();
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Destroyed [queue=%lx]",(long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+
+ if (mEventQueue) {
+ NotifyObservers(gDestroyedNotification);
+ PL_DestroyEventQueue(mEventQueue);
+ }
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::Init(PRBool aNative)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ if (aNative)
+ mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread);
+ else
+ mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread);
+ NotifyObservers(gActivatedNotification);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::InitFromPRThread(PRThread* thread, PRBool aNative)
+{
+ if (thread == NS_CURRENT_THREAD)
+ {
+ thread = PR_GetCurrentThread();
+ }
+ else if (thread == NS_UI_THREAD)
+ {
+ nsCOMPtr<nsIThread> mainIThread;
+ nsresult rv;
+
+ // Get the primordial thread
+ rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mainIThread->GetPRThread(&thread);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ if (aNative)
+ mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread);
+ else
+ mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread);
+ NotifyObservers(gActivatedNotification);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::InitFromPLQueue(PLEventQueue* aQueue)
+{
+ mEventQueue = aQueue;
+ NotifyObservers(gActivatedNotification);
+ return NS_OK;
+}
+
+/* nsISupports interface implementation... */
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsEventQueueImpl,
+ nsIEventQueue,
+ nsIEventTarget,
+ nsPIEventQueueChain)
+
+/* nsIEventQueue interface implementation... */
+
+NS_IMETHODIMP
+nsEventQueueImpl::StopAcceptingEvents()
+{
+ // this assertion is bogus. I should be able to shut down the eldest queue,
+ // as long as there are no younger children
+
+
+ NS_ASSERTION(mElderQueue || !mYoungerQueue, "attempted to disable eldest queue in chain");
+ mAcceptingEvents = PR_FALSE;
+ CheckForDeactivation();
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: StopAccepting [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ return NS_OK;
+}
+
+// utility funtion to send observers a notification
+void
+nsEventQueueImpl::NotifyObservers(const char *aTopic)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIEventQueue> kungFuDeathGrip(this);
+ nsCOMPtr<nsISupports> us(do_QueryInterface(kungFuDeathGrip));
+ os->NotifyObservers(us, aTopic, NULL);
+ }
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::InitEvent(PLEvent* aEvent,
+ void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor)
+{
+ PL_InitEvent(aEvent, owner, handler, destructor);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::PostEvent(PLEvent* aEvent)
+{
+ if (!mAcceptingEvents) {
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Punt posted event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ nsresult rv = NS_ERROR_FAILURE;
+ NS_ASSERTION(mElderQueue, "event dropped because event chain is dead");
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ rv = elder->PostEvent(aEvent);
+ }
+ return rv;
+ }
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Posting event [queue=%lx]", (long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+ return PL_PostEvent(mEventQueue, aEvent) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::PostSynchronousEvent(PLEvent* aEvent, void** aResult)
+{
+ if (!mAcceptingEvents) {
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Punt posted synchronous event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ nsresult rv = NS_ERROR_NO_INTERFACE;
+ NS_ASSERTION(mElderQueue, "event dropped because event chain is dead");
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ rv = elder->PostSynchronousEvent(aEvent, aResult);
+ return rv;
+ }
+ return NS_ERROR_ABORT;
+ }
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Posting synchronous event [queue=%lx]", (long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+ void* result = PL_PostSynchronousEvent(mEventQueue, aEvent);
+ if (aResult)
+ *aResult = result;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::EnterMonitor()
+{
+ PL_ENTER_EVENT_QUEUE_MONITOR(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::ExitMonitor()
+{
+ PL_EXIT_EVENT_QUEUE_MONITOR(mEventQueue);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::RevokeEvents(void* owner)
+{
+ PL_RevokeEvents(mEventQueue, owner);
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ elder->RevokeEvents(owner);
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetPLEventQueue(PLEventQueue** aEventQueue)
+{
+ if (!mEventQueue)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEventQueue = mEventQueue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::IsOnCurrentThread(PRBool *aResult)
+{
+ *aResult = PL_IsQueueOnCurrentThread( mEventQueue );
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::IsQueueNative(PRBool *aResult)
+{
+ *aResult = PL_IsQueueNative(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::PendingEvents(PRBool *aResult)
+{
+ *aResult = PL_EventAvailable(mEventQueue);
+ if (!*aResult && mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ return elder->EventAvailable(*aResult);
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::ProcessPendingEvents()
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ ++gEventQueueLogPPLevel;
+ if ((gEventQueueLogQueue != mEventQueue || gEventQueueLogThread != PR_GetCurrentThread() ||
+ gEventQueueLogCount != gEventQueueLogPPCount) && gEventQueueLogPPLevel == 1) {
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Process pending [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ gEventQueueLogPPCount = ++gEventQueueLogCount;
+ gEventQueueLogQueue = mEventQueue;
+ gEventQueueLogThread = PR_GetCurrentThread();
+ }
+#endif
+ PL_ProcessPendingEvents(mEventQueue);
+
+ // if we're no longer accepting events and there are still events in the
+ // queue, then process remaining events.
+ if (!mAcceptingEvents && PL_EventAvailable(mEventQueue))
+ PL_ProcessPendingEvents(mEventQueue);
+
+ CheckForDeactivation();
+
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ elder->ProcessPendingEvents();
+ }
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ --gEventQueueLogPPLevel;
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::EventLoop()
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+
+ PL_EventLoop(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::EventAvailable(PRBool& aResult)
+{
+ aResult = PL_EventAvailable(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetEvent(PLEvent** aResult)
+{
+ *aResult = PL_GetEvent(mEventQueue);
+ CheckForDeactivation();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::HandleEvent(PLEvent* aEvent)
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: handle event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ PL_HandleEvent(aEvent);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::WaitForEvent(PLEvent** aResult)
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: wait for event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ *aResult = PL_WaitForEvent(mEventQueue);
+ CheckForDeactivation();
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsEventQueueImpl::GetEventQueueSelectFD()
+{
+ return PL_GetEventQueueSelectFD(mEventQueue);
+}
+
+NS_METHOD
+nsEventQueueImpl::Create(nsISupports *aOuter,
+ REFNSIID aIID,
+ void **aResult)
+{
+ nsEventQueueImpl* evt = new nsEventQueueImpl();
+ if (evt == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = evt->QueryInterface(aIID, aResult);
+ if (NS_FAILED(rv)) {
+ delete evt;
+ }
+ return rv;
+}
+
+// ---------------- nsPIEventQueueChain -----------------
+
+NS_IMETHODIMP
+nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue)
+{
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> end;
+ nsCOMPtr<nsPIEventQueueChain> queueChain(do_QueryInterface(aQueue));
+
+ if (!aQueue)
+ return NS_ERROR_NO_INTERFACE;
+
+/* this would be nice
+ NS_ASSERTION(aQueue->mYoungerQueue == NULL && aQueue->mElderQueue == NULL,
+ "event queue repeatedly appended to queue chain");
+*/
+ rv = NS_ERROR_NO_INTERFACE;
+
+#ifdef NS_DEBUG
+ int depth = 0;
+ nsEventQueueImpl *next = this;
+ while (next && depth < 100) {
+ next = NS_STATIC_CAST(nsEventQueueImpl *, next->mYoungerQueue);
+ ++depth;
+ }
+ if (depth > 5) {
+ char warning[80];
+ PR_snprintf(warning, sizeof(warning),
+ "event queue chain length is %d. this is almost certainly a leak.", depth);
+ NS_WARNING(warning);
+ }
+#endif
+
+ // (be careful doing this outside nsEventQueueService's mEventQMonitor)
+
+ GetYoungest(getter_AddRefs(end));
+ nsCOMPtr<nsPIEventQueueChain> endChain(do_QueryInterface(end));
+ if (endChain) {
+ endChain->SetYounger(queueChain);
+ queueChain->SetElder(endChain);
+ rv = NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::Unlink()
+{
+ nsCOMPtr<nsPIEventQueueChain> young = mYoungerQueue,
+ old = mElderQueue;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: unlink [queue=%lx, younger=%lx, elder=%lx]",
+ (long)mEventQueue,(long)mYoungerQueue, (long)mElderQueue.get()));
+ ++gEventQueueLogCount;
+#endif
+
+ // this is probably OK, but shouldn't happen by design, so tell me if it does
+ NS_ASSERTION(!mYoungerQueue, "event queue chain broken in middle");
+
+ // break links early in case the Release cascades back onto us
+ mYoungerQueue = nsnull;
+ mElderQueue = nsnull;
+
+ if (young)
+ young->SetElder(old);
+ if (old) {
+ old->SetYounger(young);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetYoungest(nsIEventQueue **aQueue)
+{
+ if (mYoungerQueue)
+ return mYoungerQueue->GetYoungest(aQueue);
+
+ nsIEventQueue *answer = NS_STATIC_CAST(nsIEventQueue *, this);
+ NS_ADDREF(answer);
+ *aQueue = answer;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetYoungestActive(nsIEventQueue **aQueue)
+{
+ nsCOMPtr<nsIEventQueue> answer;
+
+ if (mYoungerQueue)
+ mYoungerQueue->GetYoungestActive(getter_AddRefs(answer));
+ if (!answer) {
+ if (mAcceptingEvents && mCouldHaveEvents)
+ answer = NS_STATIC_CAST(nsIEventQueue *, this);
+ }
+ *aQueue = answer;
+ NS_IF_ADDREF(*aQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::SetYounger(nsPIEventQueueChain *aQueue)
+{
+ mYoungerQueue = aQueue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::SetElder(nsPIEventQueueChain *aQueue)
+{
+ mElderQueue = aQueue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetYounger(nsIEventQueue **aQueue)
+{
+ if (!mYoungerQueue) {
+ *aQueue = nsnull;
+ return NS_OK;
+ }
+ return mYoungerQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue);
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetElder(nsIEventQueue **aQueue)
+{
+ if (!mElderQueue) {
+ *aQueue = nsnull;
+ return NS_OK;
+ }
+ return mElderQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h
new file mode 100644
index 00000000..51f33e47
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prmon.h"
+#include "nsIEventQueue.h"
+#include "nsPIEventQueueChain.h"
+
+class nsEventQueueImpl : public nsIEventQueue,
+ public nsPIEventQueueChain
+{
+public:
+ nsEventQueueImpl();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEVENTTARGET
+ NS_DECL_NSIEVENTQUEUE
+
+ // Helpers
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ static const nsCID& CID() { static nsCID cid = NS_EVENTQUEUE_CID; return cid; }
+
+ // nsPIEventQueueChain interface
+ NS_IMETHOD AppendQueue(nsIEventQueue *aQueue);
+ NS_IMETHOD Unlink();
+ NS_IMETHOD GetYoungest(nsIEventQueue **aQueue);
+ NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue);
+ NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue);
+ NS_IMETHOD GetYounger(nsIEventQueue **aQueue);
+ NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue);
+ NS_IMETHOD GetElder(nsIEventQueue **aQueue);
+
+private:
+ ~nsEventQueueImpl();
+
+ PLEventQueue *mEventQueue;
+ PRBool mAcceptingEvents, // accept new events or pass them on?
+ mCouldHaveEvents; // accepting new ones, or still have old ones?
+ nsCOMPtr<nsPIEventQueueChain> mElderQueue; // younger can hold on to elder
+ nsPIEventQueueChain *mYoungerQueue; // but elder can't hold on to younger
+
+ void NotifyObservers(const char *aTopic);
+
+ void CheckForDeactivation() {
+ if (mCouldHaveEvents && !mAcceptingEvents && !PL_EventAvailable(mEventQueue)) {
+ if (PL_IsQueueOnCurrentThread(mEventQueue)) {
+ mCouldHaveEvents = PR_FALSE;
+ NS_RELEASE_THIS(); // balance ADDREF from the constructor
+ } else
+ NS_ERROR("CheckForDeactivation called from wrong thread!");
+ }
+ }
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp
new file mode 100644
index 00000000..4fbb65aa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp
@@ -0,0 +1,450 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Rick Potts <rpotts@netscape.com>
+ * Ramiro Estrugo <ramiro@netscape.com>
+ * Warren Harris <warren@netscape.com>
+ * Leaf Nunes <leaf@mozilla.org>
+ * David Matiskella <davidm@netscape.com>
+ * David Hyatt <hyatt@netscape.com>
+ * Seth Spitzer <sspitzer@netscape.com>
+ * Suresh Duddi <dp@netscape.com>
+ * Bruce Mitchener <bruce@cybersight.com>
+ * Scott Collins <scc@netscape.com>
+ * Daniel Matejka <danm@netscape.com>
+ * Doug Turner <dougt@netscape.com>
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Mike Kaply <mkaply@us.ibm.com>
+ * Dan Mosedale <dmose@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsEventQueueService.h"
+#include "prmon.h"
+#include "nsIComponentManager.h"
+#include "nsIThread.h"
+#include "nsPIEventQueueChain.h"
+
+#include "prlog.h"
+
+#if defined(PR_LOGGING) || defined(DEBUG_danm)
+extern PRLogModuleInfo* gEventQueueLog;
+extern PRUint32 gEventQueueLogCount;
+#endif
+
+static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID);
+
+nsEventQueueServiceImpl::nsEventQueueServiceImpl()
+{
+ mEventQMonitor = PR_NewMonitor();
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ if (!gEventQueueLog)
+ gEventQueueLog = PR_NewLogModule("nseventqueue");
+#endif
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+hash_enum_remove_queues(const void *aThread_ptr,
+ nsCOMPtr<nsIEventQueue>& aEldestQueue,
+ void* closure)
+{
+ // 'aQueue' should be the eldest queue.
+ nsCOMPtr<nsPIEventQueueChain> pie(do_QueryInterface(aEldestQueue));
+ nsCOMPtr<nsIEventQueue> q;
+
+ // stop accepting events for youngest to oldest
+ pie->GetYoungest(getter_AddRefs(q));
+ while (q) {
+ q->StopAcceptingEvents();
+
+ nsCOMPtr<nsPIEventQueueChain> pq(do_QueryInterface(q));
+ pq->GetElder(getter_AddRefs(q));
+ }
+
+ return PL_DHASH_REMOVE;
+}
+
+nsEventQueueServiceImpl::~nsEventQueueServiceImpl()
+{
+ // XXX make it so we only enum over this once
+ mEventQTable.Enumerate(hash_enum_remove_queues, nsnull); // call StopAcceptingEvents on everything and clear out the hashtable
+
+ PR_DestroyMonitor(mEventQMonitor);
+}
+
+nsresult
+nsEventQueueServiceImpl::Init()
+{
+ NS_ENSURE_TRUE(mEventQMonitor, NS_ERROR_OUT_OF_MEMORY);
+
+ // This will only be called once on the main thread, so it's safe to
+ // not enter the monitor here.
+ if (!mEventQTable.Init()) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // ensure that a main thread event queue exists!
+ nsresult rv;
+ nsCOMPtr<nsIThread> mainThread;
+ rv = nsIThread::GetMainThread(getter_AddRefs(mainThread));
+ if (NS_SUCCEEDED(rv)) {
+ PRThread *thr;
+ rv = mainThread->GetPRThread(&thr);
+ if (NS_SUCCEEDED(rv))
+ rv = CreateEventQueue(thr, PR_TRUE);
+ }
+ return rv;
+}
+
+/* nsISupports interface implementation... */
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsEventQueueServiceImpl, nsIEventQueueService)
+
+/* nsIEventQueueService interface implementation... */
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateThreadEventQueue()
+{
+ return CreateEventQueue(PR_GetCurrentThread(), PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateMonitoredThreadEventQueue()
+{
+ return CreateEventQueue(PR_GetCurrentThread(), PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateFromIThread(nsIThread *aThread, PRBool aNative,
+ nsIEventQueue **aResult)
+{
+ nsresult rv;
+ PRThread *prThread;
+
+ rv = aThread->GetPRThread(&prThread);
+ if (NS_SUCCEEDED(rv)) {
+ rv = CreateEventQueue(prThread, aNative); // addrefs
+ if (NS_SUCCEEDED(rv))
+ rv = GetThreadEventQueue(prThread, aResult); // addrefs
+ }
+ return rv;
+}
+
+// private method
+NS_IMETHODIMP
+nsEventQueueServiceImpl::MakeNewQueue(PRThread* thread,
+ PRBool aNative,
+ nsIEventQueue **aQueue)
+{
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv);
+
+ if (NS_SUCCEEDED(rv)) {
+ rv = queue->InitFromPRThread(thread, aNative);
+ }
+ *aQueue = queue;
+ NS_IF_ADDREF(*aQueue);
+ return rv;
+}
+
+// private method
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread, PRBool aNative)
+{
+ nsresult rv = NS_OK;
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ /* create only one event queue chain per thread... */
+ if (!mEventQTable.GetWeak(aThread)) {
+ nsCOMPtr<nsIEventQueue> queue;
+
+ // we don't have one in the table
+ rv = MakeNewQueue(aThread, aNative, getter_AddRefs(queue)); // create new queue
+ mEventQTable.Put(aThread, queue); // add to the table (initial addref)
+ }
+
+ // Release the EventQ lock...
+ PR_ExitMonitor(mEventQMonitor);
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::DestroyThreadEventQueue(void)
+{
+ nsresult rv = NS_OK;
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ PRThread* currentThread = PR_GetCurrentThread();
+ nsIEventQueue* queue = mEventQTable.GetWeak(currentThread);
+ if (queue) {
+ queue->StopAcceptingEvents(); // tell the queue to stop accepting events
+ queue = nsnull; // Queue may die on the next line
+ mEventQTable.Remove(currentThread); // remove nsIEventQueue from hash table (releases)
+ }
+
+ // Release the EventQ lock...
+ PR_ExitMonitor(mEventQMonitor);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult)
+{
+ // Create our thread queue using the component manager
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = queue->InitFromPLQueue(aPLEventQueue);
+ if (NS_FAILED(rv)) return rv;
+
+ *aResult = queue;
+ NS_IF_ADDREF(*aResult);
+ return NS_OK;
+}
+
+
+// Return the active event queue on our chain
+/* inline */
+nsresult nsEventQueueServiceImpl::GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult)
+{
+ nsCOMPtr<nsIEventQueue> answer;
+
+ if (queue) {
+ nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue));
+ if (ourChain)
+ ourChain->GetYoungestActive(getter_AddRefs(answer));
+ else
+ answer = queue;
+ }
+
+ *aResult = answer;
+ NS_IF_ADDREF(*aResult);
+ return NS_OK;
+}
+
+
+// create new event queue, append it to the current thread's chain of event queues.
+// return it, addrefed.
+NS_IMETHODIMP
+nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue)
+{
+ nsresult rv = NS_OK;
+ PRThread* currentThread = PR_GetCurrentThread();
+ PRBool native = PR_TRUE; // native by default as per old comment
+
+
+ NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param");
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ nsIEventQueue* queue = mEventQTable.GetWeak(currentThread);
+
+ NS_ASSERTION(queue, "pushed event queue on top of nothing");
+
+ if (queue) { // find out what kind of queue our relatives are
+ nsCOMPtr<nsIEventQueue> youngQueue;
+ GetYoungestEventQueue(queue, getter_AddRefs(youngQueue));
+ if (youngQueue) {
+ youngQueue->IsQueueNative(&native);
+ }
+ }
+
+ nsIEventQueue* newQueue = nsnull;
+ MakeNewQueue(currentThread, native, &newQueue); // create new queue; addrefs
+
+ if (!queue) {
+ // shouldn't happen. as a fallback, we guess you wanted a native queue
+ mEventQTable.Put(currentThread, newQueue);
+ }
+
+ // append to the event queue chain
+ nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue)); // QI the queue in the hash table
+ if (ourChain)
+ ourChain->AppendQueue(newQueue); // append new queue to it
+
+ *aNewQueue = newQueue;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PLEventQueue *equeue;
+ (*aNewQueue)->GetPLEventQueue(&equeue);
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Service push queue [queue=%lx]",(long)equeue));
+ ++gEventQueueLogCount;
+#endif
+
+ // Release the EventQ lock...
+ PR_ExitMonitor(mEventQMonitor);
+ return rv;
+}
+
+// disable and release the given queue (though the last one won't be released)
+NS_IMETHODIMP
+nsEventQueueServiceImpl::PopThreadEventQueue(nsIEventQueue *aQueue)
+{
+ PRThread* currentThread = PR_GetCurrentThread();
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ nsCOMPtr<nsIEventQueue> eldestQueue;
+ mEventQTable.Get(currentThread, getter_AddRefs(eldestQueue));
+
+ // If we are popping the eldest queue, remove its mEventQTable entry.
+ if (aQueue == eldestQueue)
+ mEventQTable.Remove(currentThread);
+
+ // Exit the monitor before processing pending events to avoid deadlock.
+ // Our reference from the eldestQueue nsCOMPtr will keep that object alive.
+ // Since it is thread-private, no one else can race with us here.
+ PR_ExitMonitor(mEventQMonitor);
+ if (!eldestQueue)
+ return NS_ERROR_FAILURE;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PLEventQueue *equeue;
+ aQueue->GetPLEventQueue(&equeue);
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Service pop queue [queue=%lx]",(long)equeue));
+ ++gEventQueueLogCount;
+#endif
+ aQueue->StopAcceptingEvents();
+ aQueue->ProcessPendingEvents(); // make sure we don't orphan any events
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** aResult)
+{
+ /* Parameter validation... */
+ if (NULL == aResult) return NS_ERROR_NULL_POINTER;
+
+ PRThread* keyThread = aThread;
+
+ if (keyThread == NS_CURRENT_THREAD)
+ {
+ keyThread = PR_GetCurrentThread();
+ }
+ else if (keyThread == NS_UI_THREAD)
+ {
+ nsCOMPtr<nsIThread> mainIThread;
+
+ // Get the primordial thread
+ nsresult rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mainIThread->GetPRThread(&keyThread);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ nsCOMPtr<nsIEventQueue> queue;
+ mEventQTable.Get(keyThread, getter_AddRefs(queue));
+
+ PR_ExitMonitor(mEventQMonitor);
+
+ if (queue) {
+ GetYoungestEventQueue(queue, aResult); // get the youngest active queue
+ } else {
+ *aResult = nsnull;
+ }
+ // XXX: Need error code for requesting an event queue when none exists...
+ if (!*aResult) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::ResolveEventQueue(nsIEventQueue* queueOrConstant, nsIEventQueue* *resultQueue)
+{
+ if (queueOrConstant == NS_CURRENT_EVENTQ) {
+ return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue);
+ }
+ else if (queueOrConstant == NS_UI_THREAD_EVENTQ) {
+ return GetThreadEventQueue(NS_UI_THREAD, resultQueue);
+ }
+
+ *resultQueue = queueOrConstant;
+ NS_ADDREF(*resultQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::GetSpecialEventQueue(PRInt32 aQueue,
+ nsIEventQueue* *_retval)
+{
+ nsresult rv;
+
+ // barf if someone gave us a zero pointer
+ //
+ if (!_retval) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ // try and get the requested event queue, returning NS_ERROR_FAILURE if there
+ // is a problem. GetThreadEventQueue() does the AddRef() for us.
+ //
+ switch (aQueue) {
+ case CURRENT_THREAD_EVENT_QUEUE:
+ rv = GetThreadEventQueue(NS_CURRENT_THREAD, _retval);
+ if (NS_FAILED(rv)) {
+ return NS_ERROR_FAILURE;
+ }
+ break;
+
+ case UI_THREAD_EVENT_QUEUE:
+ rv = GetThreadEventQueue(NS_UI_THREAD, _retval);
+ if (NS_FAILED(rv)) {
+ return NS_ERROR_FAILURE;
+ }
+ break;
+
+ // somebody handed us a bogus constant
+ //
+ default:
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ return NS_OK;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h
new file mode 100644
index 00000000..6fddb941
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsEventQueueService_h__
+#define nsEventQueueService_h__
+
+#include "nsIEventQueueService.h"
+#include "nsInterfaceHashtable.h"
+#include "nsHashKeys.h"
+#include "nsIEventQueue.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsEventQueueServiceImpl : public nsIEventQueueService
+{
+public:
+ nsEventQueueServiceImpl();
+
+ nsresult Init();
+
+ // nsISupports interface...
+ NS_DECL_ISUPPORTS
+
+ // nsIEventQueueService interface...
+ NS_DECL_NSIEVENTQUEUESERVICE
+
+private:
+ ~nsEventQueueServiceImpl();
+
+ /* Create a queue for the given thread if one does not exist.
+ Addref the descriptor in any case. parameter aNative is
+ ignored if the queue already exists. */
+ NS_IMETHOD CreateEventQueue(PRThread *aThread, PRBool aNative);
+ NS_IMETHOD MakeNewQueue(PRThread* thread, PRBool aNative, nsIEventQueue **aQueue);
+ inline nsresult GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult);
+
+ nsInterfaceHashtable<nsVoidPtrHashKey, nsIEventQueue> mEventQTable;
+ PRMonitor *mEventQMonitor;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsEventQueueService_h__
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h
new file mode 100644
index 00000000..5df2e406
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h
@@ -0,0 +1,78 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.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 ***** */
+
+#ifndef nsEventQueueUtils_h__
+#define nsEventQueueUtils_h__
+
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+inline nsresult
+NS_GetEventQueueService(nsIEventQueueService **result)
+{
+ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+ return CallGetService(kEventQueueServiceCID, result);
+}
+
+inline nsresult
+NS_GetCurrentEventQ(nsIEventQueue **result,
+ nsIEventQueueService *serv = nsnull)
+{
+ nsCOMPtr<nsIEventQueueService> eqs;
+ if (!serv) {
+ nsresult rv = NS_GetEventQueueService(getter_AddRefs(eqs));
+ if (NS_FAILED(rv)) return rv;
+ serv = eqs;
+ }
+ return serv->GetThreadEventQueue(NS_CURRENT_THREAD, result);
+}
+
+inline nsresult
+NS_GetMainEventQ(nsIEventQueue **result,
+ nsIEventQueueService *serv = nsnull)
+{
+ nsCOMPtr<nsIEventQueueService> eqs;
+ if (!serv) {
+ nsresult rv = NS_GetEventQueueService(getter_AddRefs(eqs));
+ if (NS_FAILED(rv)) return rv;
+ serv = eqs;
+ }
+ return serv->GetThreadEventQueue(NS_UI_THREAD, result);
+}
+
+#endif // !nsEventQueueUtils_h__
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl
new file mode 100644
index 00000000..95351346
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla embedding code.
+ *
+ * The Initial Developers of the Original Code are
+ * Benjamin Smedberg <bsmedberg@covad.net> and
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003/2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * Scriptable access to the current process environment.
+ *
+ */
+[scriptable, uuid(101d5941-d820-4e85-a266-9a3469940807)]
+interface nsIEnvironment : nsISupports
+{
+ /**
+ * Set the value of an environment variable.
+ *
+ * @param aName the variable name to set.
+ * @param aValue the value to set.
+ */
+ void set(in AString aName, in AString aValue);
+
+ /**
+ * Get the value of an environment variable.
+ *
+ * @param aName the variable name to retrieve.
+ * @return returns the value of the env variable. An empty string
+ * will be returned when the env variable does not exist or
+ * when the value itself is an empty string - please use
+ * |exists()| to probe whether the env variable exists
+ * or not.
+ */
+ AString get(in AString aName);
+
+ /**
+ * Check the existence of an environment variable.
+ * This method checks whether an environment variable is present in
+ * the environment or not.
+ *
+ * - For Unix/Linux platforms we follow the Unix definition:
+ * An environment variable exists when |getenv()| returns a non-NULL value.
+ * An environment variable does not exist when |getenv()| returns NULL.
+ * - For non-Unix/Linux platforms we have to fall back to a
+ * "portable" definition (which is incorrect for Unix/Linux!!!!)
+ * which simply checks whether the string returned by |Get()| is empty
+ * or not.
+ *
+ * @param aName the variable name to probe.
+ * @return if the variable has been set, the value returned is
+ * PR_TRUE. If the variable was not defined in the
+ * environment PR_FALSE will be returned.
+ */
+ boolean exists(in AString aName);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl
new file mode 100644
index 00000000..416c80a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * David Hyatt <hyatt@netscape.com>
+ * Suresh Duddi <dp@netscape.com>
+ * Doug Turner <dougt@netscape.com>
+ * Judson Valeski <valeski@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Ray Whitmer <rayw@netscape.com>
+ * Dan Mosedale <dmose@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIEventTarget.idl"
+
+%{C++
+#include "prthread.h"
+
+// {13D86C61-00A9-11d3-9F2A-00400553EEF0}
+#define NS_EVENTQUEUE_CID \
+{ 0x13d86c61, 0xa9, 0x11d3, { 0x9f, 0x2a, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } }
+
+#define NS_EVENTQUEUE_CONTRACTID "@mozilla.org/event-queue;1"
+#define NS_EVENTQUEUE_CLASSNAME "Event Queue"
+
+%}
+
+// some forward decls
+//
+[ptr] native PLEventQueuePtr(PLEventQueue);
+[ptr] native PRThreadPtr(PRThread);
+native PRStatus(PRStatus);
+[ref] native PRBoolRef(PRBool);
+native PLHandleEventProc(PLHandleEventProc);
+native PLDestroyEventProc(PLDestroyEventProc);
+
+[scriptable, uuid(176AFB41-00A4-11d3-9F2A-00400553EEF0)]
+interface nsIEventQueue : nsIEventTarget
+{
+ [noscript] void initEvent(in PLEventPtr aEvent,
+ in voidPtr owner,
+ in PLHandleEventProc handler,
+ in PLDestroyEventProc destructor);
+
+ [noscript] void postSynchronousEvent(in PLEventPtr aEvent,
+ out voidPtr aResult);
+
+ boolean pendingEvents();
+ void processPendingEvents();
+ void eventLoop();
+
+ [noscript] void eventAvailable(in PRBoolRef aResult);
+ [noscript] PLEventPtr getEvent();
+ [noscript] void handleEvent(in PLEventPtr aEvent);
+ [noscript] PLEventPtr waitForEvent();
+
+ [notxpcom] PRInt32 getEventQueueSelectFD();
+
+ void init(in boolean aNative);
+ [noscript] void initFromPRThread(in PRThreadPtr thread,
+ in boolean aNative);
+ [noscript] void initFromPLQueue(in PLEventQueuePtr aQueue);
+
+ void enterMonitor();
+ void exitMonitor();
+
+ [noscript] void revokeEvents(in voidPtr owner);
+ [noscript] PLEventQueuePtr getPLEventQueue();
+
+ boolean isQueueNative();
+
+ // effectively kill the queue. warning: the queue is allowed to delete
+ // itself any time after this.
+ void stopAcceptingEvents();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl
new file mode 100644
index 00000000..e9c93e86
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Rick Potts <rpotts@netscape.com>
+ * David Matiskella <davidm@netscape.com>
+ * David Hyatt <hyatt@netscape.com>
+ * Suresh Duddi <dp@netscape.com>
+ * Scott Collins <scc@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Doug Turner <dougt@netscape.com>
+ * Ray Whitmer <rayw@netscape.com>
+ * Dan Mosedale <dmose@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "nsIEventQueue.idl"
+
+%{C++
+#include "prthread.h"
+#include "plevent.h"
+
+/* be761f00-a3b0-11d2-996c-0080c7cb1080 */
+#define NS_EVENTQUEUESERVICE_CID \
+{ 0xbe761f00, 0xa3b0, 0x11d2, \
+ {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x80} }
+
+#define NS_EVENTQUEUESERVICE_CONTRACTID "@mozilla.org/event-queue-service;1"
+#define NS_EVENTQUEUESERVICE_CLASSNAME "Event Queue Service"
+
+#define NS_CURRENT_THREAD ((PRThread*)0)
+#define NS_CURRENT_EVENTQ ((nsIEventQueue*)0)
+
+#define NS_UI_THREAD ((PRThread*)1)
+#define NS_UI_THREAD_EVENTQ ((nsIEventQueue*)1)
+
+%}
+
+/* a forward decl */
+interface nsIThread;
+
+[scriptable, uuid(a6cf90dc-15b3-11d2-932e-00805f8add32)]
+interface nsIEventQueueService : nsISupports
+{
+ /**
+ * Creates and holds a native event queue for the current thread.
+ * "Native" queues have an associated callback mechanism which is
+ * automatically triggered when an event is posted. See plevent.c for
+ * details.
+ * @return NS_OK on success, or a host of failure indications
+ */
+ void createThreadEventQueue();
+
+ /**
+ * Creates and hold a monitored event queue for the current thread.
+ * "Monitored" queues have no callback processing mechanism.
+ * @return NS_OK on success, or a host of failure indications
+ */
+ void createMonitoredThreadEventQueue();
+
+ /**
+ * Somewhat misnamed, this method releases the service's hold on the event
+ * queue(s) for this thread. Subsequent attempts to access this thread's
+ * queue (GetThreadEventQueue, for example) may fail, though the queue itself
+ * will be destroyed only after all references to it are released and the
+ * queue itself is no longer actively processing events.
+ * @return nonsense.
+ */
+ void destroyThreadEventQueue();
+
+ nsIEventQueue createFromIThread(in nsIThread aThread,
+ in boolean aNative);
+
+ [noscript] nsIEventQueue createFromPLEventQueue(in PLEventQueuePtr
+ aPLEventQueue);
+
+ // Add a new event queue for the current thread, making it the "current"
+ // queue. Return that queue, addrefed.
+ nsIEventQueue pushThreadEventQueue();
+
+ // release and disable the queue
+ void popThreadEventQueue(in nsIEventQueue aQueue);
+
+ [noscript] nsIEventQueue getThreadEventQueue(in PRThreadPtr aThread);
+
+ /**
+ * @deprecated in favor of getSpecialEventQueue, since that's
+ * scriptable and this isn't.
+ *
+ * Check for any "magic" event queue constants (NS_CURRENT_EVENTQ,
+ * NS_UI_THREAD_EVENTQ) and return the real event queue that they
+ * represent, AddRef()ed. Otherwise, return the event queue passed
+ * in, AddRef()ed. This is not scriptable because the arguments in
+ * question may be magic constants rather than real nsIEventQueues.
+ *
+ * @arg queueOrConstant either a real event queue or a magic
+ * constant to be resolved
+ *
+ * @return a real event queue, AddRef()ed
+ */
+ [noscript] nsIEventQueue resolveEventQueue(in nsIEventQueue queueOrConstant);
+
+ /**
+ * Returns the appropriate special event queue, AddRef()ed. Really
+ * just a scriptable version of ResolveEventQueue.
+ *
+ * @arg aQueue Either CURRENT_THREAD_EVENT_QUEUE or
+ * UI_THREAD_EVENT_QUEUE
+ * @return The requested nsIEventQueue, AddRef()ed
+ * @exception NS_ERROR_NULL_POINTER Zero pointer passed in for return value
+ * @exception NS_ERROR_ILLEGAL_VALUE Bogus constant passed in aQueue
+ * @exception NS_ERROR_FAILURE Error while calling
+ * GetThreadEventQueue()
+ */
+ nsIEventQueue getSpecialEventQueue(in long aQueue);
+
+ const long CURRENT_THREAD_EVENT_QUEUE = 0;
+ const long UI_THREAD_EVENT_QUEUE = 1;
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl
new file mode 100644
index 00000000..3b19d9ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl
@@ -0,0 +1,67 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#include "plevent.h"
+%}
+
+[ptr] native PLEventPtr(PLEvent);
+
+/**
+ * nsIEventTarget
+ *
+ * This interface is used to dispatch events to a particular thread. In many
+ * cases the event target also supports nsIEventQueue.
+ */
+[scriptable, uuid(ea99ad5b-cc67-4efb-97c9-2ef620a59f2a)]
+interface nsIEventTarget : nsISupports
+{
+ /**
+ * Method for posting an asynchronous event to the event target. If this
+ * method succeeds, then the event will be dispatched on the target thread.
+ *
+ * @param aEvent
+ * The event to dispatched.
+ */
+ [noscript] void postEvent(in PLEventPtr aEvent);
+
+ /**
+ * This method returns true if the event target is the current thread.
+ */
+ boolean isOnCurrentThread();
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl b/src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl
new file mode 100644
index 00000000..07769cb7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl
@@ -0,0 +1,32 @@
+#include "nsIFile.idl"
+#include "nsISupports.idl"
+
+[scriptable, uuid(9da0b650-d07e-4617-a18a-250035572ac8)]
+
+interface nsIProcess : nsISupports
+{
+ void init(in nsIFile executable);
+ void initWithPid(in unsigned long pid);
+
+ void kill();
+
+ /** XXX what charset? **/
+ /** Executes the file this object was initialized with
+ * @param blocking Whether to wait until the process terminates before returning or not
+ * @param args An array of arguments to pass to the process
+ * @param count The length of the args array
+ * @return the PID of the newly spawned process */
+ unsigned long run(in boolean blocking, [array, size_is(count)] in string args, in unsigned long count);
+
+ readonly attribute nsIFile location;
+ readonly attribute unsigned long pid;
+ readonly attribute string processName;
+ readonly attribute unsigned long processSignature;
+ readonly attribute long exitValue;
+};
+
+%{C++
+
+#define NS_PROCESS_CONTRACTID "@mozilla.org/process/util;1"
+#define NS_PROCESS_CLASSNAME "Process Specification"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl b/src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl
new file mode 100644
index 00000000..1cedda38
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(4a2abaf0-6886-11d3-9382-00104ba0fd40)]
+interface nsIRunnable : nsISupports
+{
+ void run();
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIThread.idl b/src/libs/xpcom18a4/xpcom/threads/nsIThread.idl
new file mode 100644
index 00000000..f28d6ec9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIThread.idl
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#include "prthread.h"
+
+#define NS_THREAD_CID \
+{ /* 85CE5510-7808-11d3-A181-0050041CAF44 */ \
+ 0x85ce5510, \
+ 0x7808, \
+ 0x11d3, \
+ {0xa1, 0x81, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
+}
+
+#define NS_THREAD_CONTRACTID "@mozilla.org/thread;1"
+#define NS_THREAD_CLASSNAME "Thread"
+#if 0
+%}
+
+typedef PRUint32 PRThreadPriority;
+typedef PRUint32 PRThreadScope;
+typedef PRUint32 PRThreadState;
+
+%{C++
+#endif
+%}
+
+interface nsIRunnable;
+
+[ptr] native PRThread(PRThread);
+
+[scriptable, uuid(6be5e380-6886-11d3-9382-00104ba0fd40)]
+interface nsIThread : nsISupports
+{
+ // These must all match the values used in prthread.h
+ const PRUint32 PRIORITY_LOW = 0;
+ const PRUint32 PRIORITY_NORMAL = 1;
+ const PRUint32 PRIORITY_HIGH = 2;
+ const PRUint32 PRIORITY_URGENT = 3;
+
+ const PRUint32 SCOPE_LOCAL = 0;
+ const PRUint32 SCOPE_GLOBAL = 1;
+ const PRUint32 SCOPE_BOUND = 2;
+
+ const PRUint32 STATE_JOINABLE = 0;
+ const PRUint32 STATE_UNJOINABLE = 1;
+
+ void join();
+ void interrupt();
+
+ attribute PRThreadPriority priority;
+ readonly attribute PRThreadScope scope;
+ readonly attribute PRThreadState state;
+
+ [noscript] PRThread GetPRThread();
+
+ void init(in nsIRunnable aRunnable,
+ in PRUint32 aStackSize,
+ in PRThreadPriority aPriority,
+ in PRThreadScope aScope,
+ in PRThreadState aState);
+
+ /*
+ * Get the currently running thread (really a static method sort of thing).
+ */
+ readonly attribute nsIThread currentThread;
+
+ /*
+ * Sleep to at least this many milliseconds (only works on currrent thread).
+ */
+ void sleep(in PRUint32 msec);
+
+%{C++
+ // returns the nsIThread for the current thread:
+ static NS_COM nsresult GetCurrent(nsIThread* *result);
+
+ // returns the nsIThread for an arbitrary PRThread:
+ static NS_COM nsresult GetIThread(PRThread* prthread, nsIThread* *result);
+
+ // initializes the "main" thread (really, just saves the current thread
+ // at time of calling. meant to be called once at app startup, in lieu
+ // of proper static initializers, to save the primordial thread
+ // for later recall.)
+ static NS_COM nsresult SetMainThread();
+
+ // return the "main" thread
+ static NS_COM nsresult GetMainThread(nsIThread **result);
+
+ static NS_COM PRBool IsMainThread();
+%}
+};
+
+%{C++
+extern NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ nsIRunnable* runnable,
+ PRUint32 stackSize = 0,
+ PRThreadState state = PR_UNJOINABLE_THREAD,
+ PRThreadPriority priority = PR_PRIORITY_NORMAL,
+ PRThreadScope scope = PR_GLOBAL_THREAD);
+
+extern NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ PRUint32 stackSize = 0,
+ PRThreadState state = PR_UNJOINABLE_THREAD,
+ PRThreadPriority priority = PR_PRIORITY_NORMAL,
+ PRThreadScope scope = PR_GLOBAL_THREAD);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsITimer.idl b/src/libs/xpcom18a4/xpcom/threads/nsITimer.idl
new file mode 100644
index 00000000..855d538d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsITimer.idl
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIObserver;
+
+%{C++
+/**
+ * The signature of the timer callback function passed to initWithCallback. This
+ * is the function that will get called when the timer expires if the timer is
+ * initialized via initWithCallback.
+ *
+ * @param aTimer the timer which has expired
+ * @param aClosure opaque parameter passed to initWithCallback
+ *
+ * Implementers should return the following:
+ *
+ * @return NS_OK
+ *
+ */
+class nsITimer;
+typedef void (*nsTimerCallbackFunc) (nsITimer *aTimer, void *aClosure);
+%}
+
+native nsTimerCallbackFunc(nsTimerCallbackFunc);
+
+/**
+ * The callback interface for timers.
+ */
+interface nsITimer;
+
+[scriptable, uuid(a796816d-7d47-4348-9ab8-c7aeb3216a7d)]
+interface nsITimerCallback : nsISupports
+{
+ /**
+ * @param aTimer the timer which has expired
+ */
+ void notify(in nsITimer timer);
+};
+
+
+/**
+ * nsITimer instances must be initialized by calling one of the "init" methods
+ * documented below. You may also re-initialize an existing instance with new
+ * delay to avoid the overhead of destroying and creating a timer. It is not
+ * necessary to cancel the timer in that case.
+ */
+[scriptable, uuid(29ee628e-a3ea-471f-965d-dc9f11d1c183)]
+interface nsITimer : nsISupports
+{
+ /* Timer types */
+
+ /**
+ * Type of a timer that fires once only.
+ */
+ const short TYPE_ONE_SHOT = 0;
+
+ /**
+ * After firing, a TYPE_REPEATING_SLACK timer is stopped and not restarted
+ * until its callback completes. Specified timer period will be at least
+ * the time between when processing for last firing the callback completes
+ * and when the next firing occurs.
+ *
+ * This is the preferable repeating type for most situations.
+ */
+ const short TYPE_REPEATING_SLACK = 1;
+
+ /**
+ * An TYPE_REPEATING_PRECISE repeating timer aims to have constant period
+ * between firings. The processing time for each timer callback should not
+ * influence the timer period. However, if the processing for the last
+ * timer firing could not be completed until just before the next firing
+ * occurs, then you could have two timer notification routines being
+ * executed in quick succession.
+ */
+ const short TYPE_REPEATING_PRECISE = 2;
+
+ /**
+ * Initialize a timer that will fire after the said delay.
+ * A user must keep a reference to this timer till it is
+ * is no longer needed or has been cancelled.
+ *
+ * @param aObserver the callback object that observes the
+ * ``timer-callback'' topic with the subject being
+ * the timer itself when the timer fires:
+ *
+ * observe(nsISupports aSubject, => nsITimer
+ * string aTopic, => ``timer-callback''
+ * wstring data => null
+ *
+ * @param aDelay delay in milliseconds for timer to fire
+ * @param aType timer type per TYPE* consts defined above
+ */
+ void init(in nsIObserver aObserver, in unsigned long aDelay,
+ in unsigned long aType);
+
+
+ /**
+ * Initialize a timer to fire after the given millisecond interval.
+ * This version takes a function to call and a closure to pass to
+ * that function.
+ *
+ * @param aFunc The function to invoke
+ * @param aClosure An opaque pointer to pass to that function
+ * @param aDelay The millisecond interval
+ * @param aType Timer type per TYPE* consts defined above
+ */
+ [noscript] void initWithFuncCallback(in nsTimerCallbackFunc aCallback,
+ in voidPtr aClosure,
+ in unsigned long aDelay,
+ in unsigned long aType);
+
+ /**
+ * Initialize a timer to fire after the given millisecond interval.
+ * This version takes a function to call and a closure to pass to
+ * that function.
+ *
+ * @param aFunc nsITimerCallback interface to call when timer expires
+ * @param aDelay The millisecond interval
+ * @param aType Timer type per TYPE* consts defined above
+ */
+ void initWithCallback(in nsITimerCallback aCallback,
+ in unsigned long aDelay,
+ in unsigned long aType);
+
+ /**
+ * Cancel the timer. This method works on all types, not just on repeating
+ * timers -- you might want to cancel a TYPE_ONE_SHOT timer, and even reuse
+ * it by re-initializing it (to avoid object destruction and creation costs
+ * by conserving one timer instance).
+ */
+ void cancel();
+
+ /**
+ * The millisecond delay of the timeout
+ */
+ attribute unsigned long delay;
+
+ /**
+ * The timer type : one shot or repeating
+ */
+ attribute unsigned long type;
+
+ /**
+ * The opaque pointer pass to initWithCallback.
+ */
+ [noscript] readonly attribute voidPtr closure;
+};
+
+%{C++
+#define NS_TIMER_CONTRACTID "@mozilla.org/timer;1"
+#define NS_TIMER_CALLBACK_TOPIC "timer-callback"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl b/src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl
new file mode 100644
index 00000000..c334ae19
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+
+[scriptable, uuid(6dd8f185-ceb8-4878-8e38-2d13edc2d079)]
+interface nsITimerInternal : nsISupports
+{
+ attribute boolean idle;
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl b/src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl
new file mode 100644
index 00000000..f391d313
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(8fce8c6a-1dd2-11b2-8352-8cdd2b965efc)]
+interface nsITimerManager : nsISupports
+{
+ /**
+ * A flag that turns on the use of idle timers on the main thread.
+ * this should only be called once.
+ *
+ * By default, idle timers are off.
+ *
+ * One this is set to TRUE, you are expected to call hasIdleTimers/fireNextIdleTimer
+ * when you have time in your main loop.
+ */
+ attribute boolean useIdleTimers;
+
+ boolean hasIdleTimers();
+
+ // Fire next idle timers waiting on the current thread
+ void fireNextIdleTimer();
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h b/src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h
new file mode 100644
index 00000000..8d3c0933
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsPIEventQueueChain_h__
+#define nsPIEventQueueChain_h__
+
+#include "nsISupports.h"
+
+// {8f310040-82a7-11d3-95bc-0060083a0bcf}
+#define NS_IEVENTQUEUECHAIN_IID \
+{ 0x8f310040, 0x82a7, 0x11d3, { 0x95, 0xbc, 0x0, 0x60, 0x8, 0x3a, 0xb, 0xcf } }
+
+class nsIEventQueue;
+
+class nsPIEventQueueChain : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IEVENTQUEUECHAIN_IID);
+
+ /**
+ * Add the given queue as the new youngest member of our chain.
+ * It will not be addrefed.
+ * @param aQueue the queue. must not be null.
+ * @return error indication
+ */
+ NS_IMETHOD AppendQueue(nsIEventQueue *aQueue) = 0;
+
+ /**
+ * Remove this element from the chain.
+ * @return NS_OK
+ */
+ NS_IMETHOD Unlink() = 0;
+
+ /**
+ * Fetch (and addref) the youngest member of the chain.
+ * @param *aQueue the youngest queue. aQueue must not be null.
+ * @return error indication
+ */
+ NS_IMETHOD GetYoungest(nsIEventQueue **aQueue) = 0;
+
+ /**
+ * Fetch (and addref) the youngest member of the chain which is
+ * still accepting events, or at least still contains events in need
+ * of processing.
+ * @param *aQueue the youngest such queue. aQueue must not be null.
+ * *aQueue will be returned null, if no such queue is found.
+ * @return error indication -- can be NS_OK even if *aQueue is 0
+ */
+ NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue) = 0;
+
+ NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue) = 0;
+ NS_IMETHOD GetYounger(nsIEventQueue **aQueue) = 0;
+
+ NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue) = 0;
+ NS_IMETHOD GetElder(nsIEventQueue **aQueue) = 0;
+};
+
+#endif /* nsPIEventQueueChain_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsProcess.h b/src/libs/xpcom18a4/xpcom/threads/nsProcess.h
new file mode 100644
index 00000000..f061fe1c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsProcess.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Don Bragg <dbragg@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _nsPROCESSWIN_H_
+#define _nsPROCESSWIN_H_
+
+#include "nsIProcess.h"
+#include "nsIFile.h"
+#include "nsString.h"
+#include "prproces.h"
+
+#define NS_PROCESS_CID \
+{0x7b4eeb20, 0xd781, 0x11d4, \
+ {0x8A, 0x83, 0x00, 0x10, 0xa4, 0xe0, 0xc9, 0xca}}
+
+class nsProcess : public nsIProcess
+{
+public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROCESS
+
+ nsProcess();
+
+private:
+ ~nsProcess() {}
+
+ nsCOMPtr<nsIFile> mExecutable;
+ PRInt32 mExitValue;
+ nsCString mTargetPath;
+ PRProcess *mProcess;
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp b/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp
new file mode 100644
index 00000000..07087c2f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp
@@ -0,0 +1,363 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Don Bragg <dbragg@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*****************************************************************************
+ *
+ * nsProcess is used to execute new processes and specify if you want to
+ * wait (blocking) or continue (non-blocking).
+ *
+ *****************************************************************************
+ */
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsProcess.h"
+#include "prtypes.h"
+#include "prio.h"
+#include "prenv.h"
+#include "nsCRT.h"
+
+#include <stdlib.h>
+
+#if defined( XP_WIN )
+#include "prmem.h"
+#include "nsString.h"
+#include "nsLiteralString.h"
+#include "nsReadableUtils.h"
+#include <windows.h>
+#endif
+
+//-------------------------------------------------------------------//
+// nsIProcess implementation
+//-------------------------------------------------------------------//
+NS_IMPL_ISUPPORTS1(nsProcess, nsIProcess)
+
+//Constructor
+nsProcess::nsProcess():mExitValue(-1),
+ mProcess(nsnull)
+{
+}
+
+NS_IMETHODIMP
+nsProcess::Init(nsIFile* executable)
+{
+ PRBool isFile;
+
+ //First make sure the file exists
+ nsresult rv = executable->IsFile(&isFile);
+ if (NS_FAILED(rv)) return rv;
+ if (!isFile)
+ return NS_ERROR_FAILURE;
+
+ //Store the nsIFile in mExecutable
+ mExecutable = executable;
+ //Get the path because it is needed by the NSPR process creation
+#ifdef XP_WIN
+ rv = mExecutable->GetNativeTarget(mTargetPath);
+ if (NS_FAILED(rv) || mTargetPath.IsEmpty() )
+#endif
+ rv = mExecutable->GetNativePath(mTargetPath);
+
+ return rv;
+}
+
+
+#if defined( XP_WIN )
+static int assembleCmdLine(char *const *argv, char **cmdLine)
+{
+ char *const *arg;
+ char *p, *q;
+ int cmdLineSize;
+ int numBackslashes;
+ int i;
+ int argNeedQuotes;
+
+ /*
+ * Find out how large the command line buffer should be.
+ */
+ cmdLineSize = 0;
+ for (arg = argv; *arg; arg++) {
+ /*
+ * \ and " need to be escaped by a \. In the worst case,
+ * every character is a \ or ", so the string of length
+ * may double. If we quote an argument, that needs two ".
+ * Finally, we need a space between arguments, and
+ * a null byte at the end of command line.
+ */
+ cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
+ + 2 /* we quote every argument */
+ + 1; /* space in between, or final null */
+ }
+ p = *cmdLine = (char *) PR_MALLOC(cmdLineSize);
+ if (p == NULL) {
+ return -1;
+ }
+
+ for (arg = argv; *arg; arg++) {
+ /* Add a space to separates the arguments */
+ if (arg != argv) {
+ *p++ = ' ';
+ }
+ q = *arg;
+ numBackslashes = 0;
+ argNeedQuotes = 0;
+
+ /* If the argument contains white space, it needs to be quoted. */
+ if (strpbrk(*arg, " \f\n\r\t\v")) {
+ argNeedQuotes = 1;
+ }
+
+ if (argNeedQuotes) {
+ *p++ = '"';
+ }
+ while (*q) {
+ if (*q == '\\') {
+ numBackslashes++;
+ q++;
+ } else if (*q == '"') {
+ if (numBackslashes) {
+ /*
+ * Double the backslashes since they are followed
+ * by a quote
+ */
+ for (i = 0; i < 2 * numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ numBackslashes = 0;
+ }
+ /* To escape the quote */
+ *p++ = '\\';
+ *p++ = *q++;
+ } else {
+ if (numBackslashes) {
+ /*
+ * Backslashes are not followed by a quote, so
+ * don't need to double the backslashes.
+ */
+ for (i = 0; i < numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ numBackslashes = 0;
+ }
+ *p++ = *q++;
+ }
+ }
+
+ /* Now we are at the end of this argument */
+ if (numBackslashes) {
+ /*
+ * Double the backslashes if we have a quote string
+ * delimiter at the end.
+ */
+ if (argNeedQuotes) {
+ numBackslashes *= 2;
+ }
+ for (i = 0; i < numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ }
+ if (argNeedQuotes) {
+ *p++ = '"';
+ }
+ }
+
+ *p = '\0';
+ return 0;
+}
+#endif
+
+// XXXldb |args| has the wrong const-ness
+NS_IMETHODIMP
+nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid)
+{
+ nsresult rv = NS_OK;
+
+ // make sure that when we allocate we have 1 greater than the
+ // count since we need to null terminate the list for the argv to
+ // pass into PR_CreateProcess
+ char **my_argv = NULL;
+#ifdef VBOX
+ my_argv = (char **)nsMemory::Alloc(sizeof(char *) * (count + 2) );
+#else
+ my_argv = (char **)malloc(sizeof(char *) * (count + 2) );
+#endif
+ if (!my_argv) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // copy the args
+ PRUint32 i;
+ for (i=0; i < count; i++) {
+ my_argv[i+1] = NS_CONST_CAST(char*, args[i]);
+ }
+ // we need to set argv[0] to the program name.
+ my_argv[0] = mTargetPath.BeginWriting();
+ // null terminate the array
+ my_argv[count+1] = NULL;
+
+ #if defined(XP_WIN)
+ STARTUPINFO startupInfo;
+ PROCESS_INFORMATION procInfo;
+ BOOL retVal;
+ char *cmdLine;
+
+ if (assembleCmdLine(my_argv, &cmdLine) == -1) {
+ nsMemory::Free(my_argv);
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+ }
+
+ ZeroMemory(&startupInfo, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+
+ retVal = CreateProcess(NULL,
+ // NS_CONST_CAST(char*, mTargetPath.get()),
+ cmdLine,
+ NULL, /* security attributes for the new
+ * process */
+ NULL, /* security attributes for the primary
+ * thread in the new process */
+ FALSE, /* inherit handles */
+ 0, /* creation flags */
+ NULL, /* env */
+ NULL, /* current drive and directory */
+ &startupInfo,
+ &procInfo
+ );
+ PR_FREEIF( cmdLine );
+ if (blocking) {
+
+ // if success, wait for process termination. the early returns and such
+ // are a bit ugly but preserving the logic of the nspr code I copied to
+ // minimize our risk abit.
+
+ if ( retVal == TRUE ) {
+ DWORD dwRetVal;
+ unsigned long exitCode;
+
+ dwRetVal = WaitForSingleObject(procInfo.hProcess, INFINITE);
+ if (dwRetVal == WAIT_FAILED) {
+ nsMemory::Free(my_argv);
+ return PR_FAILURE;
+ }
+ if (GetExitCodeProcess(procInfo.hProcess, &exitCode) == FALSE) {
+ mExitValue = exitCode;
+ nsMemory::Free(my_argv);
+ return PR_FAILURE;
+ }
+ mExitValue = exitCode;
+ CloseHandle(procInfo.hProcess);
+ }
+ else
+ rv = PR_FAILURE;
+ }
+ else {
+
+ // map return value into success code
+
+ if ( retVal == TRUE )
+ rv = PR_SUCCESS;
+ else
+ rv = PR_FAILURE;
+ }
+
+#else
+ if ( blocking ) {
+ mProcess = PR_CreateProcess(mTargetPath.get(), my_argv, NULL, NULL);
+ if (mProcess)
+ rv = PR_WaitProcess(mProcess, &mExitValue);
+ }
+ else {
+ rv = PR_CreateProcessDetached(mTargetPath.get(), my_argv, NULL, NULL);
+ }
+#endif
+
+ // free up our argv
+ nsMemory::Free(my_argv);
+
+ if (rv != PR_SUCCESS)
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetLocation(nsIFile** aLocation)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetPid(PRUint32 *aPid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessName(char** aProcessName)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessSignature(PRUint32 *aProcessSignature)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::Kill()
+{
+ nsresult rv = NS_OK;
+ if (mProcess)
+ rv = PR_KillProcess(mProcess);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsProcess::GetExitValue(PRInt32 *aExitValue)
+{
+ *aExitValue = mExitValue;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp b/src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp
new file mode 100644
index 00000000..d6411f47
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Don Bragg <dbragg@netscape.com>
+ * Samir Gehani <sgehani@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*****************************************************************************
+ *
+ * nsProcess is used to execute new processes and specify if you want to
+ * wait (blocking) or continue (non-blocking).
+ *
+ *****************************************************************************
+ */
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+
+#include "nsProcess.h"
+
+#include "prtypes.h"
+#include "prio.h"
+#include "prenv.h"
+#include "nsCRT.h"
+#include "prthread.h"
+
+#include <stdlib.h>
+#include <Processes.h>
+
+#include "nsILocalFileMac.h"
+
+//-------------------------------------------------------------------//
+// nsIProcess implementation
+//-------------------------------------------------------------------//
+NS_IMPL_ISUPPORTS1(nsProcess, nsIProcess)
+
+//Constructor
+nsProcess::nsProcess()
+:mExitValue(-1),
+ mProcess(nsnull)
+{
+}
+
+NS_IMETHODIMP
+nsProcess::Init(nsIFile* executable)
+{
+ PRBool isFile;
+
+ //First make sure the file exists
+ nsresult rv = executable->IsFile(&isFile);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!isFile)
+ return NS_ERROR_FAILURE;
+
+ mExecutable = executable;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid)
+{
+ OSErr err = noErr;
+ LaunchParamBlockRec launchPB;
+ FSSpec resolvedSpec;
+ Boolean bDone = false;
+ ProcessInfoRec info;
+
+ nsCOMPtr<nsILocalFileMac> macExecutable = do_QueryInterface(mExecutable);
+ macExecutable->GetFSSpec(&resolvedSpec);
+
+ launchPB.launchAppSpec = &resolvedSpec;
+ launchPB.launchAppParameters = NULL;
+ launchPB.launchBlockID = extendedBlock;
+ launchPB.launchEPBLength = extendedBlockLen;
+ launchPB.launchFileFlags = NULL;
+ launchPB.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
+ if (!blocking)
+ launchPB.launchControlFlags += launchDontSwitch;
+
+ err = LaunchApplication(&launchPB);
+ if (err != noErr)
+ return NS_ERROR_FAILURE;
+
+ // NOTE: blocking mode assumes you are running on a thread
+ // other than the UI thread that has teh main event loop
+ if (blocking)
+ {
+ do
+ {
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = nil;
+ err = GetProcessInformation(&launchPB.launchProcessSN, &info);
+
+ if (err == noErr)
+ {
+ // still running so sleep some more (200 msecs)
+ PR_Sleep(200);
+ }
+ else
+ {
+ // no longer in process manager's internal list: so assume done
+ bDone = true;
+ }
+ }
+ while (!bDone);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetLocation(nsIFile** aLocation)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetPid(PRUint32 *aPid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessName(char** aProcessName)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessSignature(PRUint32 *aProcessSignature)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::Kill()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetExitValue(PRInt32 *aExitValue)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsThread.cpp b/src/libs/xpcom18a4/xpcom/threads/nsThread.cpp
new file mode 100644
index 00000000..b4cc15f4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsThread.cpp
@@ -0,0 +1,457 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsThread.h"
+#include "prmem.h"
+#include "prlog.h"
+#include "nsAutoLock.h"
+
+PRUintn nsThread::kIThreadSelfIndex = 0;
+static nsIThread *gMainThread = 0;
+
+#if defined(PR_LOGGING)
+//
+// Log module for nsIThread logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=nsIThread:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+//
+// gSocketLog is defined in nsSocketTransport.cpp
+//
+PRLogModuleInfo* nsIThreadLog = nsnull;
+
+#endif /* PR_LOGGING */
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsThread::nsThread()
+ : mThread(nsnull), mDead(PR_FALSE), mStartLock(nsnull)
+{
+#if defined(PR_LOGGING)
+ //
+ // Initialize the global PRLogModule for nsIThread logging
+ // if necessary...
+ //
+ if (nsIThreadLog == nsnull) {
+ nsIThreadLog = PR_NewLogModule("nsIThread");
+ }
+#endif /* PR_LOGGING */
+
+ // enforce matching of constants to enums in prthread.h
+ NS_ASSERTION(int(nsIThread::PRIORITY_LOW) == int(PR_PRIORITY_LOW) &&
+ int(nsIThread::PRIORITY_NORMAL) == int(PRIORITY_NORMAL) &&
+ int(nsIThread::PRIORITY_HIGH) == int(PRIORITY_HIGH) &&
+ int(nsIThread::PRIORITY_URGENT) == int(PRIORITY_URGENT) &&
+ int(nsIThread::SCOPE_LOCAL) == int(PR_LOCAL_THREAD) &&
+ int(nsIThread::SCOPE_GLOBAL) == int(PR_GLOBAL_THREAD) &&
+ int(nsIThread::STATE_JOINABLE) == int(PR_JOINABLE_THREAD) &&
+ int(nsIThread::STATE_UNJOINABLE) == int(PR_UNJOINABLE_THREAD),
+ "Bad constant in nsIThread!");
+}
+
+nsThread::~nsThread()
+{
+ if (mStartLock)
+ PR_DestroyLock(mStartLock);
+
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p destroyed\n", this));
+
+ // This code used to free the nsIThreadLog loginfo stuff
+ // Don't do that; loginfo structures are owned by nspr
+ // and would be freed if we ever called PR_Cleanup()
+ // see bug 142072
+}
+
+void
+nsThread::Main(void* arg)
+{
+ nsThread* self = (nsThread*)arg;
+
+ self->WaitUntilReadyToStartMain();
+
+ nsresult rv = NS_OK;
+ rv = self->RegisterThreadSelf();
+ NS_ASSERTION(rv == NS_OK, "failed to set thread self");
+
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p start run %p\n", self, self->mRunnable.get()));
+ rv = self->mRunnable->Run();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "runnable failed");
+
+#ifdef DEBUG
+ // Because a thread can die after gMainThread dies and takes nsIThreadLog with it,
+ // we need to check for it being null so that we don't crash on shutdown.
+ if (nsIThreadLog) {
+ PRThreadState state;
+ rv = self->GetState(&state);
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p end run %p\n", self, self->mRunnable.get()));
+ }
+#endif
+
+ // explicitly drop the runnable now in case there are circular references
+ // between it and the thread object
+ self->mRunnable = nsnull;
+}
+
+void
+nsThread::Exit(void* arg)
+{
+ nsThread* self = (nsThread*)arg;
+
+ if (self->mDead) {
+ NS_ERROR("attempt to Exit() thread twice");
+ return;
+ }
+
+ self->mDead = PR_TRUE;
+
+#if defined(PR_LOGGING)
+ if (nsIThreadLog) {
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p exited\n", self));
+ }
+#endif
+ NS_RELEASE(self);
+}
+
+NS_METHOD
+nsThread::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ nsThread* thread = new nsThread();
+ if (!thread) return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = thread->QueryInterface(aIID, aResult);
+ if (NS_FAILED(rv)) delete thread;
+ return rv;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsThread, nsIThread)
+
+NS_IMETHODIMP
+nsThread::Join()
+{
+ // don't check for mDead here because nspr calls Exit (cleaning up
+ // thread-local storage) before they let us join with the thread
+
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p start join\n", this));
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ PRStatus status = PR_JoinThread(mThread);
+ // XXX can't use NS_RELEASE here because the macro wants to set
+ // this to null (bad c++)
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p end join\n", this));
+ if (status == PR_SUCCESS) {
+ NS_RELEASE_THIS(); // most likely the final release of this thread
+ return NS_OK;
+ }
+ else
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsThread::GetPriority(PRThreadPriority *result)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ *result = PR_GetThreadPriority(mThread);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::SetPriority(PRThreadPriority value)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ PR_SetThreadPriority(mThread, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::Interrupt()
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ PRStatus status = PR_Interrupt(mThread);
+ return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsThread::GetScope(PRThreadScope *result)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ *result = PR_GetThreadScope(mThread);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::GetState(PRThreadState *result)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ *result = PR_GetThreadState(mThread);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::GetPRThread(PRThread* *result)
+{
+ if (mDead) {
+ *result = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+ *result = mThread;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::Init(nsIRunnable* runnable,
+ PRUint32 stackSize,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state)
+{
+ NS_ENSURE_ARG_POINTER(runnable);
+ mRunnable = runnable;
+
+ NS_ADDREF_THIS(); // released in nsThread::Exit
+ if (state == PR_JOINABLE_THREAD)
+ NS_ADDREF_THIS(); // released in nsThread::Join
+ mStartLock = PR_NewLock();
+ if (mStartLock == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ PR_Lock(mStartLock);
+ mThread = PR_CreateThread(PR_USER_THREAD, Main, this,
+ priority, scope, state, stackSize);
+ PR_Unlock(mStartLock);
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p created\n", this));
+
+ if (mThread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/* readonly attribute nsIThread currentThread; */
+NS_IMETHODIMP
+nsThread::GetCurrentThread(nsIThread * *aCurrentThread)
+{
+ return GetIThread(PR_GetCurrentThread(), aCurrentThread);
+}
+
+/* void sleep (in PRUint32 msec); */
+NS_IMETHODIMP
+nsThread::Sleep(PRUint32 msec)
+{
+ if (PR_GetCurrentThread() != mThread)
+ return NS_ERROR_FAILURE;
+
+ if (PR_Sleep(PR_MillisecondsToInterval(msec)) != PR_SUCCESS)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ nsIRunnable* runnable,
+ PRUint32 stackSize,
+ PRThreadState state,
+ PRThreadPriority priority,
+ PRThreadScope scope)
+{
+ nsresult rv;
+ nsThread* thread = new nsThread();
+ if (thread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(thread);
+
+ rv = thread->Init(runnable, stackSize, priority, scope, state);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(thread);
+ return rv;
+ }
+
+ *result = thread;
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ PRUint32 stackSize,
+ PRThreadState state,
+ PRThreadPriority priority,
+ PRThreadScope scope)
+{
+ nsThread* thread = new nsThread();
+ if (thread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(thread);
+ *result = thread;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult
+nsThread::RegisterThreadSelf()
+{
+ PRStatus status;
+
+ if (kIThreadSelfIndex == 0) {
+ status = PR_NewThreadPrivateIndex(&kIThreadSelfIndex, Exit);
+ if (status != PR_SUCCESS) return NS_ERROR_FAILURE;
+ }
+
+ status = PR_SetThreadPrivate(kIThreadSelfIndex, this);
+ if (status != PR_SUCCESS) return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+void
+nsThread::WaitUntilReadyToStartMain()
+{
+ PR_Lock(mStartLock);
+ PR_Unlock(mStartLock);
+ PR_DestroyLock(mStartLock);
+ mStartLock = nsnull;
+}
+
+NS_COM nsresult
+nsIThread::GetCurrent(nsIThread* *result)
+{
+ return GetIThread(PR_GetCurrentThread(), result);
+}
+
+NS_COM nsresult
+nsIThread::GetIThread(PRThread* prthread, nsIThread* *result)
+{
+ PRStatus status;
+ nsThread* thread;
+
+ if (nsThread::kIThreadSelfIndex == 0) {
+ status = PR_NewThreadPrivateIndex(&nsThread::kIThreadSelfIndex, nsThread::Exit);
+ if (status != PR_SUCCESS) return NS_ERROR_FAILURE;
+ }
+
+ thread = (nsThread*)PR_GetThreadPrivate(nsThread::kIThreadSelfIndex);
+ if (thread == nsnull) {
+ // if the current thread doesn't have an nsIThread associated
+ // with it, make one
+ thread = new nsThread();
+ if (thread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(thread); // released by Exit
+ thread->SetPRThread(prthread);
+ nsresult rv = thread->RegisterThreadSelf();
+ if (NS_FAILED(rv)) return rv;
+ }
+ NS_ADDREF(thread);
+ *result = thread;
+ return NS_OK;
+}
+
+NS_COM nsresult
+nsIThread::SetMainThread()
+{
+ // strictly speaking, it could be set twice. but practically speaking,
+ // it's almost certainly an error if it is
+ if (gMainThread != 0) {
+ NS_ERROR("Setting main thread twice?");
+ return NS_ERROR_FAILURE;
+ }
+ return GetCurrent(&gMainThread);
+}
+
+NS_COM nsresult
+nsIThread::GetMainThread(nsIThread **result)
+{
+ NS_ASSERTION(result, "bad result pointer");
+ if (gMainThread == 0)
+ return NS_ERROR_FAILURE;
+ *result = gMainThread;
+ NS_ADDREF(gMainThread);
+ return NS_OK;
+}
+
+NS_COM PRBool
+nsIThread::IsMainThread()
+{
+ if (gMainThread == 0)
+ return PR_TRUE;
+
+ PRThread *theMainThread;
+ gMainThread->GetPRThread(&theMainThread);
+ return theMainThread == PR_GetCurrentThread();
+}
+
+void
+nsThread::Shutdown()
+{
+ if (gMainThread) {
+ // XXX nspr doesn't seem to be calling the main thread's destructor
+ // callback, so let's help it out:
+ nsThread::Exit(NS_STATIC_CAST(nsThread*, gMainThread));
+ nsrefcnt cnt;
+ NS_RELEASE2(gMainThread, cnt);
+ NS_WARN_IF_FALSE(cnt == 0, "Main thread being held past XPCOM shutdown.");
+ gMainThread = nsnull;
+
+ kIThreadSelfIndex = 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsThread.h b/src/libs/xpcom18a4/xpcom/threads/nsThread.h
new file mode 100644
index 00000000..e75086a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsThread.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+#ifndef nsThread_h__
+#define nsThread_h__
+
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsCOMPtr.h"
+
+class nsThread : public nsIThread
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsIThread methods:
+ NS_DECL_NSITHREAD
+
+ // nsThread methods:
+ nsThread();
+
+ nsresult RegisterThreadSelf();
+ void SetPRThread(PRThread* thread) { mThread = thread; }
+ void WaitUntilReadyToStartMain();
+
+ static void PR_CALLBACK Main(void* arg);
+ static void PR_CALLBACK Exit(void* arg);
+ static void PR_CALLBACK Shutdown();
+
+ static PRUintn kIThreadSelfIndex;
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsThread();
+
+protected:
+ PRThread* mThread;
+ nsCOMPtr<nsIRunnable> mRunnable;
+ PRBool mDead;
+ PRLock* mStartLock;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsThread_h__
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp
new file mode 100644
index 00000000..dc19452f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp
@@ -0,0 +1,642 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTimerImpl.h"
+#include "TimerThread.h"
+#include "nsAutoLock.h"
+
+#include "nsVoidArray.h"
+
+#include "nsIEventQueue.h"
+
+#include "prmem.h"
+
+static PRInt32 gGenerator = 0;
+static TimerThread* gThread = nsnull;
+static PRBool gFireOnIdle = PR_FALSE;
+static nsTimerManager* gManager = nsnull;
+
+#ifdef DEBUG_TIMERS
+#include <math.h>
+
+double nsTimerImpl::sDeltaSumSquared = 0;
+double nsTimerImpl::sDeltaSum = 0;
+double nsTimerImpl::sDeltaNum = 0;
+
+static void
+myNS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
+ double *meanResult, double *stdDevResult)
+{
+ double mean = 0.0, var = 0.0, stdDev = 0.0;
+ if (n > 0.0 && sumOfValues >= 0) {
+ mean = sumOfValues / n;
+ double temp = (n * sumOfSquaredValues) - (sumOfValues * sumOfValues);
+ if (temp < 0.0 || n <= 1)
+ var = 0.0;
+ else
+ var = temp / (n * (n - 1));
+ // for some reason, Windows says sqrt(0.0) is "-1.#J" (?!) so do this:
+ stdDev = var != 0.0 ? sqrt(var) : 0.0;
+ }
+ *meanResult = mean;
+ *stdDevResult = stdDev;
+}
+#endif
+
+NS_IMPL_THREADSAFE_QUERY_INTERFACE2(nsTimerImpl, nsITimer, nsITimerInternal)
+NS_IMPL_THREADSAFE_ADDREF(nsTimerImpl)
+
+NS_IMETHODIMP_(nsrefcnt) nsTimerImpl::Release(void)
+{
+ nsrefcnt count;
+
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsTimerImpl");
+ if (count == 0) {
+ mRefCnt = 1; /* stabilize */
+
+ /* enable this to find non-threadsafe destructors: */
+ /* NS_ASSERT_OWNINGTHREAD(nsTimerImpl); */
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+
+ // If only one reference remains, and mArmed is set, then the ref must be
+ // from the TimerThread::mTimers array, so we Cancel this timer to remove
+ // the mTimers element, and return 0 if Cancel in fact disarmed the timer.
+ //
+ // We use an inlined version of nsTimerImpl::Cancel here to check for the
+ // NS_ERROR_NOT_AVAILABLE code returned by gThread->RemoveTimer when this
+ // timer is not found in the mTimers array -- i.e., when the timer was not
+ // in fact armed once we acquired TimerThread::mLock, in spite of mArmed
+ // being true here. That can happen if the armed timer is being fired by
+ // TimerThread::Run as we race and test mArmed just before it is cleared by
+ // the timer thread. If the RemoveTimer call below doesn't find this timer
+ // in the mTimers array, then the last ref to this timer is held manually
+ // and temporarily by the TimerThread, so we should fall through to the
+ // final return and return 1, not 0.
+ //
+ // The original version of this thread-based timer code kept weak refs from
+ // TimerThread::mTimers, removing this timer's weak ref in the destructor,
+ // but that leads to double-destructions in the race described above, and
+ // adding mArmed doesn't help, because destructors can't be deferred, once
+ // begun. But by combining reference-counting and a specialized Release
+ // method with "is this timer still in the mTimers array once we acquire
+ // the TimerThread's lock" testing, we defer destruction until we're sure
+ // that only one thread has its hot little hands on this timer.
+ //
+ // Note that both approaches preclude a timer creator, and everyone else
+ // except the TimerThread who might have a strong ref, from dropping all
+ // their strong refs without implicitly canceling the timer. Timers need
+ // non-mTimers-element strong refs to stay alive.
+
+ if (count == 1 && mArmed) {
+ mCanceled = PR_TRUE;
+
+ if (NS_SUCCEEDED(gThread->RemoveTimer(this)))
+ return 0;
+ }
+
+ return count;
+}
+
+nsTimerImpl::nsTimerImpl() :
+ mClosure(nsnull),
+ mCallbackType(CALLBACK_TYPE_UNKNOWN),
+ mIdle(PR_TRUE),
+ mFiring(PR_FALSE),
+ mArmed(PR_FALSE),
+ mCanceled(PR_FALSE),
+ mGeneration(0),
+ mDelay(0),
+ mTimeout(0)
+{
+ // XXXbsmedberg: shouldn't this be in Init()?
+ nsIThread::GetCurrent(getter_AddRefs(mCallingThread));
+
+ mCallback.c = nsnull;
+
+#ifdef DEBUG_TIMERS
+ mStart = 0;
+ mStart2 = 0;
+#endif
+}
+
+nsTimerImpl::~nsTimerImpl()
+{
+ ReleaseCallback();
+}
+
+//static
+nsresult
+nsTimerImpl::Startup()
+{
+ nsresult rv;
+
+ gThread = new TimerThread();
+ if (!gThread) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(gThread);
+ rv = gThread->InitLocks();
+
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(gThread);
+ }
+
+ return rv;
+}
+
+void nsTimerImpl::Shutdown()
+{
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ double mean = 0, stddev = 0;
+ myNS_MeanAndStdDev(sDeltaNum, sDeltaSum, sDeltaSumSquared, &mean, &stddev);
+
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("sDeltaNum = %f, sDeltaSum = %f, sDeltaSumSquared = %f\n", sDeltaNum, sDeltaSum, sDeltaSumSquared));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("mean: %fms, stddev: %fms\n", mean, stddev));
+ }
+#endif
+
+ if (!gThread)
+ return;
+
+ gThread->Shutdown();
+ NS_RELEASE(gThread);
+
+ gFireOnIdle = PR_FALSE;
+}
+
+
+nsresult nsTimerImpl::InitCommon(PRUint32 aType, PRUint32 aDelay)
+{
+ nsresult rv;
+
+ NS_ENSURE_TRUE(gThread, NS_ERROR_NOT_INITIALIZED);
+
+ rv = gThread->Init();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ /**
+ * In case of re-Init, both with and without a preceding Cancel, clear the
+ * mCanceled flag and assign a new mGeneration. But first, remove any armed
+ * timer from the timer thread's list.
+ *
+ * If we are racing with the timer thread to remove this timer and we lose,
+ * the RemoveTimer call made here will fail to find this timer in the timer
+ * thread's list, and will return false harmlessly. We test mArmed here to
+ * avoid the small overhead in RemoveTimer of locking the timer thread and
+ * checking its list for this timer. It's safe to test mArmed even though
+ * it might be cleared on another thread in the next cycle (or even already
+ * be cleared by another CPU whose store hasn't reached our CPU's cache),
+ * because RemoveTimer is idempotent.
+ */
+ if (mArmed)
+ gThread->RemoveTimer(this);
+ mCanceled = PR_FALSE;
+ mGeneration = PR_AtomicIncrement(&gGenerator);
+
+ mType = (PRUint8)aType;
+ SetDelayInternal(aDelay);
+
+ return gThread->AddTimer(this);
+}
+
+NS_IMETHODIMP nsTimerImpl::InitWithFuncCallback(nsTimerCallbackFunc aFunc,
+ void *aClosure,
+ PRUint32 aDelay,
+ PRUint32 aType)
+{
+ ReleaseCallback();
+ mCallbackType = CALLBACK_TYPE_FUNC;
+ mCallback.c = aFunc;
+ mClosure = aClosure;
+
+ return InitCommon(aType, aDelay);
+}
+
+NS_IMETHODIMP nsTimerImpl::InitWithCallback(nsITimerCallback *aCallback,
+ PRUint32 aDelay,
+ PRUint32 aType)
+{
+ ReleaseCallback();
+ mCallbackType = CALLBACK_TYPE_INTERFACE;
+ mCallback.i = aCallback;
+ NS_ADDREF(mCallback.i);
+
+ return InitCommon(aType, aDelay);
+}
+
+NS_IMETHODIMP nsTimerImpl::Init(nsIObserver *aObserver,
+ PRUint32 aDelay,
+ PRUint32 aType)
+{
+ ReleaseCallback();
+ mCallbackType = CALLBACK_TYPE_OBSERVER;
+ mCallback.o = aObserver;
+ NS_ADDREF(mCallback.o);
+
+ return InitCommon(aType, aDelay);
+}
+
+NS_IMETHODIMP nsTimerImpl::Cancel()
+{
+ mCanceled = PR_TRUE;
+
+ if (gThread)
+ gThread->RemoveTimer(this);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::SetDelay(PRUint32 aDelay)
+{
+ // If we're already repeating precisely, update mTimeout now so that the
+ // new delay takes effect in the future.
+ if (mTimeout != 0 && mType == TYPE_REPEATING_PRECISE)
+ mTimeout = PR_IntervalNow();
+
+ SetDelayInternal(aDelay);
+
+ if (!mFiring && gThread)
+ gThread->TimerDelayChanged(this);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::GetDelay(PRUint32* aDelay)
+{
+ *aDelay = mDelay;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::SetType(PRUint32 aType)
+{
+ mType = (PRUint8)aType;
+ // XXX if this is called, we should change the actual type.. this could effect
+ // repeating timers. we need to ensure in Fire() that if mType has changed
+ // during the callback that we don't end up with the timer in the queue twice.
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::GetType(PRUint32* aType)
+{
+ *aType = mType;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTimerImpl::GetClosure(void** aClosure)
+{
+ *aClosure = mClosure;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTimerImpl::GetIdle(PRBool *aIdle)
+{
+ *aIdle = mIdle;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::SetIdle(PRBool aIdle)
+{
+ mIdle = aIdle;
+ return NS_OK;
+}
+
+void nsTimerImpl::Fire()
+{
+ if (mCanceled)
+ return;
+
+ PRIntervalTime now = PR_IntervalNow();
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PRIntervalTime a = now - mStart; // actual delay in intervals
+ PRUint32 b = PR_MillisecondsToInterval(mDelay); // expected delay in intervals
+ PRUint32 d = PR_IntervalToMilliseconds((a > b) ? a - b : b - a); // delta in ms
+ sDeltaSum += d;
+ sDeltaSumSquared += double(d) * double(d);
+ sDeltaNum++;
+
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] expected delay time %4dms\n", this, mDelay));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] actual delay time %4dms\n", this, PR_IntervalToMilliseconds(a)));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] (mType is %d) -------\n", this, mType));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] delta %4dms\n", this, (a > b) ? (PRInt32)d : -(PRInt32)d));
+
+ mStart = mStart2;
+ mStart2 = 0;
+ }
+#endif
+
+ PRIntervalTime timeout = mTimeout;
+ if (mType == TYPE_REPEATING_PRECISE) {
+ // Precise repeating timers advance mTimeout by mDelay without fail before
+ // calling Fire().
+ timeout -= PR_MillisecondsToInterval(mDelay);
+ }
+ gThread->UpdateFilter(mDelay, timeout, now);
+
+ mFiring = PR_TRUE;
+
+ switch (mCallbackType) {
+ case CALLBACK_TYPE_FUNC:
+ mCallback.c(this, mClosure);
+ break;
+ case CALLBACK_TYPE_INTERFACE:
+ mCallback.i->Notify(this);
+ break;
+ case CALLBACK_TYPE_OBSERVER:
+ mCallback.o->Observe(NS_STATIC_CAST(nsITimer*,this),
+ NS_TIMER_CALLBACK_TOPIC,
+ nsnull);
+ break;
+ default:;
+ }
+
+ mFiring = PR_FALSE;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("[this=%p] Took %dms to fire timer callback\n",
+ this, PR_IntervalToMilliseconds(PR_IntervalNow() - now)));
+ }
+#endif
+
+ if (mType == TYPE_REPEATING_SLACK) {
+ SetDelayInternal(mDelay); // force mTimeout to be recomputed.
+ if (gThread)
+ gThread->AddTimer(this);
+ }
+}
+
+
+struct TimerEventType : public PLEvent {
+ PRInt32 mGeneration;
+#ifdef DEBUG_TIMERS
+ PRIntervalTime mInitTime;
+#endif
+};
+
+
+void* handleTimerEvent(TimerEventType* event)
+{
+ nsTimerImpl* timer = NS_STATIC_CAST(nsTimerImpl*, event->owner);
+ if (event->mGeneration != timer->GetGeneration())
+ return nsnull;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PRIntervalTime now = PR_IntervalNow();
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("[this=%p] time between PostTimerEvent() and Fire(): %dms\n",
+ event->owner, PR_IntervalToMilliseconds(now - event->mInitTime)));
+ }
+#endif
+
+ if (gFireOnIdle) {
+ PRBool idle = PR_FALSE;
+ timer->GetIdle(&idle);
+ if (idle) {
+ NS_ASSERTION(gManager, "Global Thread Manager is null!");
+ if (gManager)
+ gManager->AddIdleTimer(timer);
+ return nsnull;
+ }
+ }
+
+ timer->Fire();
+
+ return nsnull;
+}
+
+void destroyTimerEvent(TimerEventType* event)
+{
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl*, event->owner);
+ NS_RELEASE(timer);
+ PR_DELETE(event);
+}
+
+
+void nsTimerImpl::PostTimerEvent()
+{
+ // XXX we may want to reuse the PLEvent in the case of repeating timers.
+ TimerEventType* event;
+
+ // construct
+ event = PR_NEW(TimerEventType);
+ if (!event)
+ return;
+
+ // initialize
+ PL_InitEvent((PLEvent*)event, this,
+ (PLHandleEventProc)handleTimerEvent,
+ (PLDestroyEventProc)destroyTimerEvent);
+
+ // Since TimerThread addref'd 'this' for us, we don't need to addref here.
+ // We will release in destroyMyEvent. We do need to copy the generation
+ // number from this timer into the event, so we can avoid firing a timer
+ // that was re-initialized after being canceled.
+ event->mGeneration = mGeneration;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ event->mInitTime = PR_IntervalNow();
+ }
+#endif
+
+ // If this is a repeating precise timer, we need to calculate the time for
+ // the next timer to fire before we make the callback.
+ if (mType == TYPE_REPEATING_PRECISE) {
+ SetDelayInternal(mDelay);
+ if (gThread)
+ gThread->AddTimer(this);
+ }
+
+ PRThread *thread;
+ nsresult rv = mCallingThread->GetPRThread(&thread);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Dropping timer event because thread is dead");
+ return;
+ }
+
+ nsCOMPtr<nsIEventQueue> queue;
+ if (gThread)
+ gThread->mEventQueueService->GetThreadEventQueue(thread, getter_AddRefs(queue));
+ if (queue)
+ queue->PostEvent(event);
+}
+
+void nsTimerImpl::SetDelayInternal(PRUint32 aDelay)
+{
+ PRIntervalTime delayInterval = PR_MillisecondsToInterval(aDelay);
+ if (delayInterval > DELAY_INTERVAL_MAX) {
+ delayInterval = DELAY_INTERVAL_MAX;
+ aDelay = PR_IntervalToMilliseconds(delayInterval);
+ }
+
+ mDelay = aDelay;
+
+ PRIntervalTime now = PR_IntervalNow();
+ if (mTimeout == 0 || mType != TYPE_REPEATING_PRECISE)
+ mTimeout = now;
+
+ mTimeout += delayInterval;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ if (mStart == 0)
+ mStart = now;
+ else
+ mStart2 = now;
+ }
+#endif
+}
+
+/**
+ * Timer Manager code
+ */
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTimerManager, nsITimerManager)
+
+nsTimerManager::nsTimerManager()
+{
+ mLock = PR_NewLock();
+ gManager = this;
+}
+
+nsTimerManager::~nsTimerManager()
+{
+ gManager = nsnull;
+ PR_DestroyLock(mLock);
+
+ nsTimerImpl *theTimer;
+ PRInt32 count = mIdleTimers.Count();
+
+ for (PRInt32 i = 0; i < count; i++) {
+ theTimer = NS_STATIC_CAST(nsTimerImpl*, mIdleTimers[i]);
+ NS_IF_RELEASE(theTimer);
+ }
+}
+
+NS_IMETHODIMP nsTimerManager::SetUseIdleTimers(PRBool aUseIdleTimers)
+{
+ if (aUseIdleTimers == PR_FALSE && gFireOnIdle == PR_TRUE)
+ return NS_ERROR_FAILURE;
+
+ gFireOnIdle = aUseIdleTimers;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerManager::GetUseIdleTimers(PRBool *aUseIdleTimers)
+{
+ *aUseIdleTimers = gFireOnIdle;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerManager::HasIdleTimers(PRBool *aHasTimers)
+{
+ nsAutoLock lock (mLock);
+ PRUint32 count = mIdleTimers.Count();
+ *aHasTimers = (count != 0);
+ return NS_OK;
+}
+
+nsresult nsTimerManager::AddIdleTimer(nsITimer* timer)
+{
+ if (!timer)
+ return NS_ERROR_FAILURE;
+ nsAutoLock lock(mLock);
+ mIdleTimers.AppendElement(timer);
+ NS_ADDREF(timer);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerManager::FireNextIdleTimer()
+{
+ if (!gFireOnIdle || !nsIThread::IsMainThread()) {
+ return NS_OK;
+ }
+
+ nsTimerImpl *theTimer = nsnull;
+
+ {
+ nsAutoLock lock (mLock);
+ PRUint32 count = mIdleTimers.Count();
+
+ if (count == 0)
+ return NS_OK;
+
+ theTimer = NS_STATIC_CAST(nsTimerImpl*, mIdleTimers[0]);
+ mIdleTimers.RemoveElement(theTimer);
+ }
+
+ theTimer->Fire();
+
+ NS_RELEASE(theTimer);
+
+ return NS_OK;
+}
+
+
+// NOT FOR PUBLIC CONSUMPTION!
+nsresult
+NS_NewTimer(nsITimer* *aResult, nsTimerCallbackFunc aCallback, void *aClosure,
+ PRUint32 aDelay, PRUint32 aType)
+{
+ nsTimerImpl* timer = new nsTimerImpl();
+ if (timer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(timer);
+
+ nsresult rv = timer->InitWithFuncCallback(aCallback, aClosure,
+ aDelay, aType);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(timer);
+ return rv;
+ }
+
+ *aResult = timer;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h
new file mode 100644
index 00000000..98596f4e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTimerImpl_h___
+#define nsTimerImpl_h___
+
+//#define FORCE_PR_LOG /* Allow logging in the release build */
+
+#include "nsITimer.h"
+#include "nsVoidArray.h"
+#include "nsIThread.h"
+#include "nsITimerInternal.h"
+#include "nsIObserver.h"
+
+#include "nsCOMPtr.h"
+
+#include "prlog.h"
+
+#if defined(PR_LOGGING)
+static PRLogModuleInfo *gTimerLog = PR_NewLogModule("nsTimerImpl");
+#define DEBUG_TIMERS 1
+#else
+#undef DEBUG_TIMERS
+#endif
+
+#define NS_TIMER_CLASSNAME "Timer"
+#define NS_TIMER_CID \
+{ /* 5ff24248-1dd2-11b2-8427-fbab44f29bc8 */ \
+ 0x5ff24248, \
+ 0x1dd2, \
+ 0x11b2, \
+ {0x84, 0x27, 0xfb, 0xab, 0x44, 0xf2, 0x9b, 0xc8} \
+}
+
+enum {
+ CALLBACK_TYPE_UNKNOWN = 0,
+ CALLBACK_TYPE_INTERFACE = 1,
+ CALLBACK_TYPE_FUNC = 2,
+ CALLBACK_TYPE_OBSERVER = 3
+};
+
+// Two timer deadlines must differ by less than half the PRIntervalTime domain.
+#define DELAY_INTERVAL_LIMIT PR_BIT(8 * sizeof(PRIntervalTime) - 1)
+
+// Maximum possible delay (XXX rework to use ms rather than interval ticks).
+#define DELAY_INTERVAL_MAX (DELAY_INTERVAL_LIMIT - 1)
+
+// Is interval-time t less than u, even if t has wrapped PRIntervalTime?
+#define TIMER_LESS_THAN(t, u) ((t) - (u) > DELAY_INTERVAL_LIMIT)
+
+class nsTimerImpl : public nsITimer, public nsITimerInternal
+{
+public:
+
+ nsTimerImpl();
+
+ static NS_HIDDEN_(nsresult) Startup();
+ static NS_HIDDEN_(void) Shutdown();
+
+ friend class TimerThread;
+
+ void Fire();
+ void PostTimerEvent();
+ void SetDelayInternal(PRUint32 aDelay);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMER
+ NS_DECL_NSITIMERINTERNAL
+
+ PRInt32 GetGeneration() { return mGeneration; }
+
+private:
+ ~nsTimerImpl();
+
+ nsresult InitCommon(PRUint32 aType, PRUint32 aDelay);
+
+ void ReleaseCallback()
+ {
+ if (mCallbackType == CALLBACK_TYPE_INTERFACE)
+ NS_RELEASE(mCallback.i);
+ else if (mCallbackType == CALLBACK_TYPE_OBSERVER)
+ NS_RELEASE(mCallback.o);
+ }
+
+ nsCOMPtr<nsIThread> mCallingThread;
+
+ void * mClosure;
+
+ union {
+ nsTimerCallbackFunc c;
+ nsITimerCallback * i;
+ nsIObserver * o;
+ } mCallback;
+
+ // These members are set by Init (called from NS_NewTimer) and never reset.
+ PRUint8 mCallbackType;
+ PRPackedBool mIdle;
+
+ // These members are set by the initiating thread, when the timer's type is
+ // changed and during the period where it fires on that thread.
+ PRUint8 mType;
+ PRPackedBool mFiring;
+
+
+ // Use a PRBool (int) here to isolate loads and stores of these two members
+ // done on various threads under the protection of TimerThread::mLock, from
+ // loads and stores done on the initiating/type-changing/timer-firing thread
+ // to the above PRUint8/PRPackedBool members.
+ PRBool mArmed;
+ PRBool mCanceled;
+
+ // The generation number of this timer, re-generated each time the timer is
+ // initialized so one-shot timers can be canceled and re-initialized by the
+ // arming thread without any bad race conditions.
+ PRInt32 mGeneration;
+
+ PRUint32 mDelay;
+ PRIntervalTime mTimeout;
+
+#ifdef DEBUG_TIMERS
+ PRIntervalTime mStart, mStart2;
+ static double sDeltaSum;
+ static double sDeltaSumSquared;
+ static double sDeltaNum;
+#endif
+
+};
+
+#define NS_TIMERMANAGER_CONTRACTID "@mozilla.org/timer/manager;1"
+#define NS_TIMERMANAGER_CLASSNAME "Timer Manager"
+#define NS_TIMERMANAGER_CID \
+{ /* 4fe206fa-1dd2-11b2-8a0a-88bacbecc7d2 */ \
+ 0x4fe206fa, \
+ 0x1dd2, \
+ 0x11b2, \
+ {0x8a, 0x0a, 0x88, 0xba, 0xcb, 0xec, 0xc7, 0xd2} \
+}
+
+#include "nsITimerManager.h"
+
+class nsTimerManager : nsITimerManager
+{
+public:
+ nsTimerManager();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMERMANAGER
+
+ nsresult AddIdleTimer(nsITimer* timer);
+private:
+ ~nsTimerManager();
+
+ PRLock *mLock;
+ nsVoidArray mIdleTimers;
+};
+
+
+#endif /* nsTimerImpl_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/threads/plevent.c b/src/libs/xpcom18a4/xpcom/threads/plevent.c
new file mode 100644
index 00000000..c5e9040f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/plevent.c
@@ -0,0 +1,1774 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+#if defined(XP_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#include <os2.h>
+#define DefWindowProc WinDefWindowProc
+#endif /* XP_OS2 */
+
+#include "nspr.h"
+#include "plevent.h"
+
+#if !defined(WIN32)
+#include <errno.h>
+#include <stddef.h>
+#if !defined(XP_OS2)
+#include <unistd.h>
+#endif /* !XP_OS2 */
+#endif /* !Win32 */
+
+#if defined(XP_UNIX)
+/* for fcntl */
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#if defined(XP_BEOS)
+#include <kernel/OS.h>
+#endif
+
+#if defined(XP_MACOSX)
+#if defined(MOZ_WIDGET_COCOA)
+#include <CoreFoundation/CoreFoundation.h>
+#define MAC_USE_CFRUNLOOPSOURCE
+#elif defined(TARGET_CARBON)
+/* #include <CarbonEvents.h> */
+/* #define MAC_USE_CARBON_EVENT */
+#include <CoreFoundation/CoreFoundation.h>
+#define MAC_USE_CFRUNLOOPSOURCE
+#endif
+#endif
+
+#include "private/pprthred.h"
+
+#if defined(VMS)
+/*
+** On OpenVMS, XtAppAddInput doesn't want a regular fd, instead it
+** wants an event flag. So, we don't create and use a pipe for
+** notification of when an event queue has something ready, instead
+** we use an event flag. Shouldn't be a problem if we only have
+** a few event queues.
+*/
+#include <lib$routines.h>
+#include <starlet.h>
+#include <stsdef.h>
+#endif /* VMS */
+
+#if defined(_WIN32)
+/* Comment out the following USE_TIMER define to prevent
+ * WIN32 from using a WIN32 native timer for PLEvent notification.
+ * With USE_TIMER defined we will use a timer when pending input
+ * or paint events are starved, otherwise it will use a posted
+ * WM_APP msg for PLEvent notification.
+ */
+#define USE_TIMER
+
+/* Threshold defined in milliseconds for determining when the input
+ * and paint events have been held in the WIN32 msg queue too long
+ */
+#define INPUT_STARVATION_LIMIT 50
+/* The paint starvation limit is set to the smallest value which
+ * does not cause performance degradation while running page load tests
+ */
+#define PAINT_STARVATION_LIMIT 750
+/* The WIN9X paint starvation limit is larger because it was
+ * determined that the following value was required to prevent performance
+ * degradation on page load tests for WIN98/95 only.
+ */
+#define WIN9X_PAINT_STARVATION_LIMIT 3000
+
+#define TIMER_ID 0
+/* If _md_PerformanceSetting <=0 then no event starvation otherwise events will be starved */
+static PRInt32 _md_PerformanceSetting = 0;
+static PRUint32 _md_StarvationDelay = 0;
+static PRUint32 _md_SwitchTime = 0;
+#endif
+
+static PRLogModuleInfo *event_lm = NULL;
+
+/*******************************************************************************
+ * Private Stuff
+ ******************************************************************************/
+
+/*
+** EventQueueType -- Defines notification type for an event queue
+**
+*/
+typedef enum {
+ EventQueueIsNative = 1,
+ EventQueueIsMonitored = 2
+} EventQueueType;
+
+
+struct PLEventQueue {
+ const char* name;
+ PRCList queue;
+ PRMonitor* monitor;
+ PRThread* handlerThread;
+ EventQueueType type;
+ PRPackedBool processingEvents;
+ PRPackedBool notified;
+#if defined(_WIN32)
+ PRPackedBool timerSet;
+#endif
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+#if defined(VMS)
+ int efn;
+#else
+ PRInt32 eventPipe[2];
+#endif
+ PLGetEventIDFunc idFunc;
+ void* idFuncClosure;
+#elif defined(_WIN32) || defined(XP_OS2)
+ HWND eventReceiverWindow;
+ PRBool removeMsg;
+#elif defined(XP_BEOS)
+ port_id eventport;
+#elif defined(XP_MACOSX)
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+ CFRunLoopSourceRef mRunLoopSource;
+ CFRunLoopRef mMainRunLoop;
+ CFStringRef mRunLoopModeStr; /* vbox */
+#elif defined(MAC_USE_CARBON_EVENT)
+ EventHandlerUPP eventHandlerUPP;
+ EventHandlerRef eventHandlerRef;
+#endif
+#endif
+};
+
+#define PR_EVENT_PTR(_qp) \
+ ((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link)))
+
+static PRStatus _pl_SetupNativeNotifier(PLEventQueue* self);
+static void _pl_CleanupNativeNotifier(PLEventQueue* self);
+static PRStatus _pl_NativeNotify(PLEventQueue* self);
+static PRStatus _pl_AcknowledgeNativeNotify(PLEventQueue* self);
+static void _md_CreateEventQueue( PLEventQueue *eventQueue );
+static PRInt32 _pl_GetEventCount(PLEventQueue* self);
+
+
+#if defined(_WIN32) || defined(XP_OS2)
+#if defined(XP_OS2)
+ULONG _pr_PostEventMsgId;
+#else
+UINT _pr_PostEventMsgId;
+#endif /* OS2 */
+static char *_pr_eventWindowClass = "XPCOM:EventWindow";
+#endif /* Win32, OS2 */
+
+#if defined(_WIN32)
+
+static LPCTSTR _md_GetEventQueuePropName() {
+ static ATOM atom = 0;
+ if (!atom) {
+ atom = GlobalAddAtom("XPCOM_EventQueue");
+ }
+ return MAKEINTATOM(atom);
+}
+#endif
+
+#if defined(MAC_USE_CARBON_EVENT)
+enum {
+ kEventClassPL = FOUR_CHAR_CODE('PLEC'),
+
+ kEventProcessPLEvents = 1,
+
+ kEventParamPLEventQueue = FOUR_CHAR_CODE('OWNQ')
+};
+
+static pascal Boolean _md_CarbonEventComparator(EventRef inEvent, void *inCompareData);
+#endif
+
+/*******************************************************************************
+ * Event Queue Operations
+ ******************************************************************************/
+
+/*
+** _pl_CreateEventQueue() -- Create the event queue
+**
+**
+*/
+static PLEventQueue * _pl_CreateEventQueue(const char *name,
+ PRThread *handlerThread,
+ EventQueueType qtype)
+{
+ PRStatus err;
+ PLEventQueue* self = NULL;
+ PRMonitor* mon = NULL;
+
+ if (event_lm == NULL)
+ event_lm = PR_NewLogModule("event");
+
+ self = PR_NEWZAP(PLEventQueue);
+ if (self == NULL) return NULL;
+
+ mon = PR_NewNamedMonitor(name);
+ if (mon == NULL) goto error;
+
+ self->name = name;
+ self->monitor = mon;
+ self->handlerThread = handlerThread;
+ self->processingEvents = PR_FALSE;
+ self->type = qtype;
+#if defined(_WIN32)
+ self->timerSet = PR_FALSE;
+#endif
+#if defined(_WIN32) || defined(XP_OS2)
+ self->removeMsg = PR_TRUE;
+#endif
+
+ self->notified = PR_FALSE;
+
+ PR_INIT_CLIST(&self->queue);
+ if ( qtype == EventQueueIsNative ) {
+ err = _pl_SetupNativeNotifier(self);
+ if (err) goto error;
+ _md_CreateEventQueue( self );
+ }
+ return self;
+
+ error:
+ if (mon != NULL)
+ PR_DestroyMonitor(mon);
+ PR_DELETE(self);
+ return NULL;
+}
+
+PR_IMPLEMENT(PLEventQueue*)
+PL_CreateEventQueue(const char* name, PRThread* handlerThread)
+{
+ return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative ));
+}
+
+PR_EXTERN(PLEventQueue *)
+PL_CreateNativeEventQueue(const char *name, PRThread *handlerThread)
+{
+ return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative ));
+}
+
+PR_EXTERN(PLEventQueue *)
+PL_CreateMonitoredEventQueue(const char *name, PRThread *handlerThread)
+{
+ return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsMonitored ));
+}
+
+PR_IMPLEMENT(PRMonitor*)
+PL_GetEventQueueMonitor(PLEventQueue* self)
+{
+ return self->monitor;
+}
+
+static void PR_CALLBACK
+_pl_destroyEvent(PLEvent* event, void* data, PLEventQueue* queue)
+{
+ PL_DequeueEvent(event, queue);
+ PL_DestroyEvent(event);
+}
+
+PR_IMPLEMENT(void)
+PL_DestroyEventQueue(PLEventQueue* self)
+{
+ PR_EnterMonitor(self->monitor);
+
+ /* destroy undelivered events */
+ PL_MapEvents(self, _pl_destroyEvent, NULL);
+
+ if ( self->type == EventQueueIsNative )
+ _pl_CleanupNativeNotifier(self);
+
+ /* destroying the monitor also destroys the name */
+ PR_ExitMonitor(self->monitor);
+ PR_DestroyMonitor(self->monitor);
+ PR_DELETE(self);
+
+}
+
+PR_IMPLEMENT(PRStatus)
+PL_PostEvent(PLEventQueue* self, PLEvent* event)
+{
+ PRStatus err = PR_SUCCESS;
+ PRMonitor* mon;
+
+ if (self == NULL)
+ return PR_FAILURE;
+
+ mon = self->monitor;
+ PR_EnterMonitor(mon);
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ if (self->idFunc && event)
+ event->id = self->idFunc(self->idFuncClosure);
+#endif
+
+ /* insert event into thread's event queue: */
+ if (event != NULL) {
+ PR_APPEND_LINK(&event->link, &self->queue);
+ }
+
+ if (self->type == EventQueueIsNative && !self->notified) {
+ err = _pl_NativeNotify(self);
+
+ if (err != PR_SUCCESS)
+ goto error;
+
+ self->notified = PR_TRUE;
+ }
+
+ /*
+ * This may fall on deaf ears if we're really notifying the native
+ * thread, and no one has called PL_WaitForEvent (or PL_EventLoop):
+ */
+ err = PR_Notify(mon);
+
+error:
+ PR_ExitMonitor(mon);
+ return err;
+}
+
+PR_IMPLEMENT(void*)
+PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event)
+{
+ void* result;
+
+ if (self == NULL)
+ return NULL;
+
+ PR_ASSERT(event != NULL);
+
+ if (PR_GetCurrentThread() == self->handlerThread) {
+ /* Handle the case where the thread requesting the event handling
+ * is also the thread that's supposed to do the handling. */
+ result = event->handler(event);
+ }
+ else {
+ int i, entryCount;
+
+ event->lock = PR_NewLock();
+ if (!event->lock) {
+ return NULL;
+ }
+ event->condVar = PR_NewCondVar(event->lock);
+ if(!event->condVar) {
+ PR_DestroyLock(event->lock);
+ event->lock = NULL;
+ return NULL;
+ }
+
+ PR_Lock(event->lock);
+
+ entryCount = PR_GetMonitorEntryCount(self->monitor);
+
+ event->synchronousResult = (void*)PR_TRUE;
+
+ PL_PostEvent(self, event);
+
+ /* We need temporarily to give up our event queue monitor if
+ we're holding it, otherwise, the thread we're going to wait
+ for notification from won't be able to enter it to process
+ the event. */
+ if (entryCount) {
+ for (i = 0; i < entryCount; i++)
+ PR_ExitMonitor(self->monitor);
+ }
+
+ event->handled = PR_FALSE;
+
+ while (!event->handled) {
+ /* wait for event to be handled or destroyed */
+ PR_WaitCondVar(event->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ if (entryCount) {
+ for (i = 0; i < entryCount; i++)
+ PR_EnterMonitor(self->monitor);
+ }
+
+ result = event->synchronousResult;
+ event->synchronousResult = NULL;
+ PR_Unlock(event->lock);
+ }
+
+ /* For synchronous events, they're destroyed here on the caller's
+ thread before the result is returned. See PL_HandleEvent. */
+ PL_DestroyEvent(event);
+
+ return result;
+}
+
+PR_IMPLEMENT(PLEvent*)
+PL_GetEvent(PLEventQueue* self)
+{
+ PLEvent* event = NULL;
+ PRStatus err = PR_SUCCESS;
+
+ if (self == NULL)
+ return NULL;
+
+ PR_EnterMonitor(self->monitor);
+
+ if (!PR_CLIST_IS_EMPTY(&self->queue)) {
+ if ( self->type == EventQueueIsNative &&
+ self->notified &&
+ !self->processingEvents &&
+ 0 == _pl_GetEventCount(self) )
+ {
+ err = _pl_AcknowledgeNativeNotify(self);
+ self->notified = PR_FALSE;
+ }
+ if (err)
+ goto done;
+
+ /* then grab the event and return it: */
+ event = PR_EVENT_PTR(self->queue.next);
+ PR_REMOVE_AND_INIT_LINK(&event->link);
+ }
+
+ done:
+ PR_ExitMonitor(self->monitor);
+ return event;
+}
+
+PR_IMPLEMENT(PRBool)
+PL_EventAvailable(PLEventQueue* self)
+{
+ PRBool result = PR_FALSE;
+
+ if (self == NULL)
+ return PR_FALSE;
+
+ PR_EnterMonitor(self->monitor);
+
+ if (!PR_CLIST_IS_EMPTY(&self->queue))
+ result = PR_TRUE;
+
+ PR_ExitMonitor(self->monitor);
+ return result;
+}
+
+PR_IMPLEMENT(void)
+PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data)
+{
+ PRCList* qp;
+
+ if (self == NULL)
+ return;
+
+ PR_EnterMonitor(self->monitor);
+ qp = self->queue.next;
+ while (qp != &self->queue) {
+ PLEvent* event = PR_EVENT_PTR(qp);
+ qp = qp->next;
+ (*fun)(event, data, self);
+ }
+ PR_ExitMonitor(self->monitor);
+}
+
+static void PR_CALLBACK
+_pl_DestroyEventForOwner(PLEvent* event, void* owner, PLEventQueue* queue)
+{
+ PR_ASSERT(PR_GetMonitorEntryCount(queue->monitor) > 0);
+ if (event->owner == owner) {
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ \tdestroying event %0x for owner %0x", event, owner));
+ PL_DequeueEvent(event, queue);
+
+ if (event->synchronousResult == (void*)PR_TRUE) {
+ PR_Lock(event->lock);
+ event->synchronousResult = NULL;
+ event->handled = PR_TRUE;
+ PR_NotifyCondVar(event->condVar);
+ PR_Unlock(event->lock);
+ }
+ else {
+ PL_DestroyEvent(event);
+ }
+ }
+ else {
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ \tskipping event %0x for owner %0x", event, owner));
+ }
+}
+
+PR_IMPLEMENT(void)
+PL_RevokeEvents(PLEventQueue* self, void* owner)
+{
+ if (self == NULL)
+ return;
+
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ revoking events for owner %0x", owner));
+
+ /*
+ ** First we enter the monitor so that no one else can post any events
+ ** to the queue:
+ */
+ PR_EnterMonitor(self->monitor);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ owner %0x, entered monitor", owner));
+
+ /*
+ ** Discard any pending events for this owner:
+ */
+ PL_MapEvents(self, _pl_DestroyEventForOwner, owner);
+
+#ifdef DEBUG
+ {
+ PRCList* qp = self->queue.next;
+ while (qp != &self->queue) {
+ PLEvent* event = PR_EVENT_PTR(qp);
+ qp = qp->next;
+ PR_ASSERT(event->owner != owner);
+ }
+ }
+#endif /* DEBUG */
+
+ PR_ExitMonitor(self->monitor);
+
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ revoking events for owner %0x", owner));
+}
+
+static PRInt32
+_pl_GetEventCount(PLEventQueue* self)
+{
+ PRCList* node;
+ PRInt32 count = 0;
+
+ PR_EnterMonitor(self->monitor);
+ node = PR_LIST_HEAD(&self->queue);
+ while (node != &self->queue) {
+ count++;
+ node = PR_NEXT_LINK(node);
+ }
+ PR_ExitMonitor(self->monitor);
+
+ return count;
+}
+
+PR_IMPLEMENT(void)
+PL_ProcessPendingEvents(PLEventQueue* self)
+{
+ PRInt32 count;
+
+ if (self == NULL)
+ return;
+
+
+ PR_EnterMonitor(self->monitor);
+
+ if (self->processingEvents) {
+ _pl_AcknowledgeNativeNotify(self);
+ self->notified = PR_FALSE;
+ PR_ExitMonitor(self->monitor);
+ return;
+ }
+ self->processingEvents = PR_TRUE;
+
+ /* Only process the events that are already in the queue, and
+ * not any new events that get added. Do this by counting the
+ * number of events currently in the queue
+ */
+ count = _pl_GetEventCount(self);
+ PR_ExitMonitor(self->monitor);
+
+ while (count-- > 0) {
+ PLEvent* event = PL_GetEvent(self);
+ if (event == NULL)
+ break;
+
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
+ PL_HandleEvent(event);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
+ }
+
+ PR_EnterMonitor(self->monitor);
+
+ if (self->type == EventQueueIsNative) {
+ count = _pl_GetEventCount(self);
+
+ if (count <= 0) {
+ _pl_AcknowledgeNativeNotify(self);
+ self->notified = PR_FALSE;
+ }
+ else {
+ _pl_NativeNotify(self);
+ self->notified = PR_TRUE;
+ }
+
+ }
+ self->processingEvents = PR_FALSE;
+
+ PR_ExitMonitor(self->monitor);
+}
+
+/*******************************************************************************
+ * Event Operations
+ ******************************************************************************/
+
+PR_IMPLEMENT(void)
+PL_InitEvent(PLEvent* self, void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor)
+{
+#ifdef PL_POST_TIMINGS
+ self->postTime = PR_IntervalNow();
+#endif
+ PR_INIT_CLIST(&self->link);
+ self->handler = handler;
+ self->destructor = destructor;
+ self->owner = owner;
+ self->synchronousResult = NULL;
+ self->handled = PR_FALSE;
+ self->lock = NULL;
+ self->condVar = NULL;
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ self->id = 0;
+#endif
+}
+
+PR_IMPLEMENT(void*)
+PL_GetEventOwner(PLEvent* self)
+{
+ return self->owner;
+}
+
+PR_IMPLEMENT(void)
+PL_HandleEvent(PLEvent* self)
+{
+ void* result;
+ if (self == NULL)
+ return;
+
+ /* This event better not be on an event queue anymore. */
+ PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
+
+ result = self->handler(self);
+ if (NULL != self->synchronousResult) {
+ PR_Lock(self->lock);
+ self->synchronousResult = result;
+ self->handled = PR_TRUE;
+ PR_NotifyCondVar(self->condVar);
+ PR_Unlock(self->lock);
+ }
+ else {
+ /* For asynchronous events, they're destroyed by the event-handler
+ thread. See PR_PostSynchronousEvent. */
+ PL_DestroyEvent(self);
+ }
+}
+#ifdef PL_POST_TIMINGS
+static long s_eventCount = 0;
+static long s_totalTime = 0;
+#endif
+
+PR_IMPLEMENT(void)
+PL_DestroyEvent(PLEvent* self)
+{
+ if (self == NULL)
+ return;
+
+ /* This event better not be on an event queue anymore. */
+ PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
+
+ if(self->condVar)
+ PR_DestroyCondVar(self->condVar);
+ if(self->lock)
+ PR_DestroyLock(self->lock);
+
+#ifdef PL_POST_TIMINGS
+ s_totalTime += PR_IntervalNow() - self->postTime;
+ s_eventCount++;
+ printf("$$$ running avg (%d) \n", PR_IntervalToMilliseconds(s_totalTime/s_eventCount));
+#endif
+
+ self->destructor(self);
+}
+
+PR_IMPLEMENT(void)
+PL_DequeueEvent(PLEvent* self, PLEventQueue* queue)
+{
+ if (self == NULL)
+ return;
+
+ /* Only the owner is allowed to dequeue events because once the
+ client has put it in the queue, they have no idea whether it's
+ been processed and destroyed or not. */
+
+ PR_ASSERT(queue->handlerThread == PR_GetCurrentThread());
+
+ PR_EnterMonitor(queue->monitor);
+
+ PR_ASSERT(!PR_CLIST_IS_EMPTY(&self->link));
+
+#if 0
+ /* I do not think that we need to do this anymore.
+ if we do not acknowledge and this is the only
+ only event in the queue, any calls to process
+ the eventQ will be effective noop.
+ */
+ if (queue->type == EventQueueIsNative)
+ _pl_AcknowledgeNativeNotify(queue);
+#endif
+
+ PR_REMOVE_AND_INIT_LINK(&self->link);
+
+ PR_ExitMonitor(queue->monitor);
+}
+
+PR_IMPLEMENT(void)
+PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation,
+ PRUint32 starvationDelay)
+{
+#if defined(_WIN32)
+
+ _md_StarvationDelay = starvationDelay;
+
+ if (favorPerformanceOverEventStarvation) {
+ _md_PerformanceSetting++;
+ return;
+ }
+
+ _md_PerformanceSetting--;
+
+ if (_md_PerformanceSetting == 0) {
+ /* Switched from allowing event starvation to no event starvation so grab
+ the current time to determine when to actually switch to using timers
+ instead of posted WM_APP messages. */
+ _md_SwitchTime = PR_IntervalToMilliseconds(PR_IntervalNow());
+ }
+
+#endif
+}
+
+/*******************************************************************************
+ * Pure Event Queues
+ *
+ * For when you're only processing PLEvents and there is no native
+ * select, thread messages, or AppleEvents.
+ ******************************************************************************/
+
+PR_IMPLEMENT(PLEvent*)
+PL_WaitForEvent(PLEventQueue* self)
+{
+ PLEvent* event;
+ PRMonitor* mon;
+
+ if (self == NULL)
+ return NULL;
+
+ mon = self->monitor;
+ PR_EnterMonitor(mon);
+
+ while ((event = PL_GetEvent(self)) == NULL) {
+ PRStatus err;
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ waiting for event"));
+ err = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ if ((err == PR_FAILURE)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
+ }
+
+ PR_ExitMonitor(mon);
+ return event;
+}
+
+PR_IMPLEMENT(void)
+PL_EventLoop(PLEventQueue* self)
+{
+ if (self == NULL)
+ return;
+
+ while (PR_TRUE) {
+ PLEvent* event = PL_WaitForEvent(self);
+ if (event == NULL) {
+ /* This can only happen if the current thread is interrupted */
+ return;
+ }
+
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
+ PL_HandleEvent(event);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
+ }
+}
+
+/*******************************************************************************
+ * Native Event Queues
+ *
+ * For when you need to call select, or WaitNextEvent, and yet also want
+ * to handle PLEvents.
+ ******************************************************************************/
+
+static PRStatus
+_pl_SetupNativeNotifier(PLEventQueue* self)
+{
+#if defined(VMS)
+ unsigned int status;
+ self->idFunc = 0;
+ self->idFuncClosure = 0;
+ status = LIB$GET_EF(&self->efn);
+ if (!$VMS_STATUS_SUCCESS(status))
+ return PR_FAILURE;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ Allocated event flag %d", self->efn));
+ return PR_SUCCESS;
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+ int err;
+ int flags;
+
+ self->idFunc = 0;
+ self->idFuncClosure = 0;
+
+ err = pipe(self->eventPipe);
+ if (err != 0) {
+ return PR_FAILURE;
+ }
+#ifdef VBOX
+ fcntl(self->eventPipe[0], F_SETFD, FD_CLOEXEC);
+ fcntl(self->eventPipe[1], F_SETFD, FD_CLOEXEC);
+#endif
+
+ /* make the pipe nonblocking */
+ flags = fcntl(self->eventPipe[0], F_GETFL, 0);
+ if (flags == -1) {
+ goto failed;
+ }
+ err = fcntl(self->eventPipe[0], F_SETFL, flags | O_NONBLOCK);
+ if (err == -1) {
+ goto failed;
+ }
+ flags = fcntl(self->eventPipe[1], F_GETFL, 0);
+ if (flags == -1) {
+ goto failed;
+ }
+ err = fcntl(self->eventPipe[1], F_SETFL, flags | O_NONBLOCK);
+ if (err == -1) {
+ goto failed;
+ }
+ return PR_SUCCESS;
+
+failed:
+ close(self->eventPipe[0]);
+ close(self->eventPipe[1]);
+ return PR_FAILURE;
+#elif defined(XP_BEOS)
+ /* hook up to the nsToolkit queue, however the appshell
+ * isn't necessairly started, so we might have to create
+ * the queue ourselves
+ */
+ char portname[64];
+ char semname[64];
+ PR_snprintf(portname, sizeof(portname), "event%lx",
+ (long unsigned) self->handlerThread);
+ PR_snprintf(semname, sizeof(semname), "sync%lx",
+ (long unsigned) self->handlerThread);
+
+ if((self->eventport = find_port(portname)) < 0)
+ {
+ /* create port
+ */
+ self->eventport = create_port(500, portname);
+
+ /* We don't use the sem, but it has to be there
+ */
+ create_sem(0, semname);
+ }
+
+ return PR_SUCCESS;
+#else
+ return PR_SUCCESS;
+#endif
+}
+
+static void
+_pl_CleanupNativeNotifier(PLEventQueue* self)
+{
+#if defined(VMS)
+ {
+ unsigned int status;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ Freeing event flag %d", self->efn));
+ status = LIB$FREE_EF(&self->efn);
+ }
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+ close(self->eventPipe[0]);
+ close(self->eventPipe[1]);
+#elif defined(_WIN32)
+ if (self->timerSet) {
+ KillTimer(self->eventReceiverWindow, TIMER_ID);
+ self->timerSet = PR_FALSE;
+ }
+ RemoveProp(self->eventReceiverWindow, _md_GetEventQueuePropName());
+
+ /* DestroyWindow doesn't do anything when called from a non ui thread. Since
+ * self->eventReceiverWindow was created on the ui thread, it must be destroyed
+ * on the ui thread.
+ */
+ SendMessage(self->eventReceiverWindow, WM_CLOSE, 0, 0);
+
+#elif defined(XP_OS2)
+ WinDestroyWindow(self->eventReceiverWindow);
+#elif defined(MAC_USE_CFRUNLOOPSOURCE)
+
+ CFRunLoopRemoveSource(self->mMainRunLoop, self->mRunLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopRemoveSource(self->mMainRunLoop, self->mRunLoopSource, self->mRunLoopModeStr); /* vbox */
+ CFRelease(self->mRunLoopSource);
+ CFRelease(self->mMainRunLoop);
+ CFRelease(self->mRunLoopModeStr); /* vbox */
+
+#elif defined(MAC_USE_CARBON_EVENT)
+ EventComparatorUPP comparator = NewEventComparatorUPP(_md_CarbonEventComparator);
+ PR_ASSERT(comparator != NULL);
+ if (comparator) {
+ FlushSpecificEventsFromQueue(GetMainEventQueue(), comparator, self);
+ DisposeEventComparatorUPP(comparator);
+ }
+ DisposeEventHandlerUPP(self->eventHandlerUPP);
+ RemoveEventHandler(self->eventHandlerRef);
+#endif
+}
+
+#if defined(_WIN32)
+
+static PRBool _md_WasInputPending = PR_FALSE;
+static PRUint32 _md_InputTime = 0;
+static PRBool _md_WasPaintPending = PR_FALSE;
+static PRUint32 _md_PaintTime = 0;
+/* last mouse location */
+static POINT _md_LastMousePos;
+
+/*******************************************************************************
+ * Timer callback function. Timers are used on WIN32 instead of APP events
+ * when there are pending UI events because APP events can cause the GUI to lockup
+ * because posted messages are processed before other messages.
+ ******************************************************************************/
+
+static void CALLBACK _md_TimerProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
+{
+ PREventQueue* queue = (PREventQueue *) GetProp(hwnd, _md_GetEventQueuePropName());
+ PR_ASSERT(queue != NULL);
+
+ KillTimer(hwnd, TIMER_ID);
+ queue->timerSet = PR_FALSE;
+ queue->removeMsg = PR_FALSE;
+ PL_ProcessPendingEvents( queue );
+ queue->removeMsg = PR_TRUE;
+}
+
+static PRBool _md_IsWIN9X = PR_FALSE;
+static PRBool _md_IsOSSet = PR_FALSE;
+
+static void _md_DetermineOSType()
+{
+ OSVERSIONINFO os;
+ os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&os);
+ if (VER_PLATFORM_WIN32_WINDOWS == os.dwPlatformId) {
+ _md_IsWIN9X = PR_TRUE;
+ }
+}
+
+static PRUint32 _md_GetPaintStarvationLimit()
+{
+ if (! _md_IsOSSet) {
+ _md_DetermineOSType();
+ _md_IsOSSet = PR_TRUE;
+ }
+
+ if (_md_IsWIN9X) {
+ return WIN9X_PAINT_STARVATION_LIMIT;
+ }
+
+ return PAINT_STARVATION_LIMIT;
+}
+
+
+/*
+ * Determine if an event is being starved (i.e the starvation limit has
+ * been exceeded.
+ * Note: this function uses the current setting and updates the contents
+ * of the wasPending and lastTime arguments
+ *
+ * ispending: PR_TRUE if the event is currently pending
+ * starvationLimit: Threshold defined in milliseconds for determining when
+ * the event has been held in the queue too long
+ * wasPending: PR_TRUE if the last time _md_EventIsStarved was called
+ * the event was pending. This value is updated within
+ * this function.
+ * lastTime: Holds the last time the event was in the queue.
+ * This value is updated within this function
+ * returns: PR_TRUE if the event is starved, PR_FALSE otherwise
+ */
+
+static PRBool _md_EventIsStarved(PRBool isPending, PRUint32 starvationLimit,
+ PRBool *wasPending, PRUint32 *lastTime,
+ PRUint32 currentTime)
+{
+ if (*wasPending && isPending) {
+ /*
+ * It was pending previously and the event is still
+ * pending so check to see if the elapsed time is
+ * over the limit which indicates the event was starved
+ */
+ if ((currentTime - *lastTime) > starvationLimit) {
+ return PR_TRUE; /* pending and over the limit */
+ }
+
+ return PR_FALSE; /* pending but within the limit */
+ }
+
+ if (isPending) {
+ /*
+ * was_pending must be false so record the current time
+ * so the elapsed time can be computed the next time this
+ * function is called
+ */
+ *lastTime = currentTime;
+ *wasPending = PR_TRUE;
+ return PR_FALSE;
+ }
+
+ /* Event is no longer pending */
+ *wasPending = PR_FALSE;
+ return PR_FALSE;
+}
+
+/* Determines if the there is a pending Mouse or input event */
+
+static PRBool _md_IsInputPending(WORD qstatus)
+{
+ /* Return immediately there aren't any pending input or paints. */
+ if (qstatus == 0) {
+ return PR_FALSE;
+ }
+
+ /* Is there anything other than a QS_MOUSEMOVE pending? */
+ if ((qstatus & QS_MOUSEBUTTON) ||
+ (qstatus & QS_KEY) ||
+ (qstatus & QS_HOTKEY)) {
+ return PR_TRUE;
+ }
+
+ /*
+ * Mouse moves need extra processing to determine if the mouse
+ * pointer actually changed location because Windows automatically
+ * generates WM_MOVEMOVE events when a new window is created which
+ * we need to filter out.
+ */
+ if (qstatus & QS_MOUSEMOVE) {
+ POINT cursorPos;
+ GetCursorPos(&cursorPos);
+ if ((_md_LastMousePos.x == cursorPos.x) &&
+ (_md_LastMousePos.y == cursorPos.y)) {
+ return PR_FALSE; /* This is a fake mouse move */
+ }
+
+ /* Real mouse move */
+ _md_LastMousePos.x = cursorPos.x;
+ _md_LastMousePos.y = cursorPos.y;
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+#ifdef USE_TIMER
+ WORD qstatus;
+
+ PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
+
+ /* Since calls to set the _md_PerformanceSetting can be nested
+ * only performance setting values <= 0 will potentially trigger
+ * the use of a timer.
+ */
+ if ((_md_PerformanceSetting <= 0) &&
+ ((now - _md_SwitchTime) > _md_StarvationDelay)) {
+ SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc);
+ self->timerSet = PR_TRUE;
+ _md_WasInputPending = PR_FALSE;
+ _md_WasPaintPending = PR_FALSE;
+ return PR_SUCCESS;
+ }
+
+ qstatus = HIWORD(GetQueueStatus(QS_INPUT | QS_PAINT));
+
+ /* Check for starved input */
+ if (_md_EventIsStarved( _md_IsInputPending(qstatus),
+ INPUT_STARVATION_LIMIT,
+ &_md_WasInputPending,
+ &_md_InputTime,
+ now )) {
+ /*
+ * Use a timer for notification. Timers have the lowest priority.
+ * They are not processed until all other events have been processed.
+ * This allows any starved paints and input to be processed.
+ */
+ SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc);
+ self->timerSet = PR_TRUE;
+
+ /*
+ * Clear any pending paint. _md_WasInputPending was cleared in
+ * _md_EventIsStarved.
+ */
+ _md_WasPaintPending = PR_FALSE;
+ return PR_SUCCESS;
+ }
+
+ if (_md_EventIsStarved( (qstatus & QS_PAINT),
+ _md_GetPaintStarvationLimit(),
+ &_md_WasPaintPending,
+ &_md_PaintTime,
+ now) ) {
+ /*
+ * Use a timer for notification. Timers have the lowest priority.
+ * They are not processed until all other events have been processed.
+ * This allows any starved paints and input to be processed
+ */
+ SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc);
+ self->timerSet = PR_TRUE;
+
+ /*
+ * Clear any pending input. _md_WasPaintPending was cleared in
+ * _md_EventIsStarved.
+ */
+ _md_WasInputPending = PR_FALSE;
+ return PR_SUCCESS;
+ }
+
+ /*
+ * Nothing is being starved so post a message instead of using a timer.
+ * Posted messages are processed before other messages so they have the
+ * highest priority.
+ */
+#endif
+ PostMessage( self->eventReceiverWindow, _pr_PostEventMsgId,
+ (WPARAM)0, (LPARAM)self );
+
+ return PR_SUCCESS;
+}/* --- end _pl_NativeNotify() --- */
+#endif
+
+
+#if defined(XP_OS2)
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+ BOOL rc = WinPostMsg( self->eventReceiverWindow, _pr_PostEventMsgId,
+ 0, MPFROMP(self));
+ return (rc == TRUE) ? PR_SUCCESS : PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#endif /* XP_OS2 */
+
+#if defined(VMS)
+/* Just set the event flag */
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+ unsigned int status;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_NativeNotify: self=%p efn=%d",
+ self, self->efn));
+ status = SYS$SETEF(self->efn);
+ return ($VMS_STATUS_SUCCESS(status)) ? PR_SUCCESS : PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+#define NOTIFY_TOKEN 0xFA
+ PRInt32 count;
+ unsigned char buf[] = { NOTIFY_TOKEN };
+
+# ifdef VBOX
+ /* Don't write two chars, because we'll only acknowledge one and that'll
+ cause trouble for anyone selecting/polling on the read descriptor. */
+ if (self->notified)
+ return PR_SUCCESS;
+# endif
+
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_NativeNotify: self=%p",
+ self));
+ count = write(self->eventPipe[1], buf, 1);
+ if (count == 1)
+ return PR_SUCCESS;
+ if (count == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+ return PR_SUCCESS;
+ return PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#endif /* defined(XP_UNIX) && !defined(XP_MACOSX) */
+
+#if defined(XP_BEOS)
+struct ThreadInterfaceData
+{
+ void *data;
+ int32 sync;
+};
+
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+ struct ThreadInterfaceData id;
+ id.data = self;
+ id.sync = false;
+ write_port(self->eventport, 'natv', &id, sizeof(id));
+
+ return PR_SUCCESS; /* Is this correct? */
+}
+#endif /* XP_BEOS */
+
+#if defined(XP_MACOSX)
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+ CFRunLoopSourceSignal(self->mRunLoopSource);
+ CFRunLoopWakeUp(self->mMainRunLoop);
+#elif defined(MAC_USE_CARBON_EVENT)
+ OSErr err;
+ EventRef newEvent;
+ if (CreateEvent(NULL, kEventClassPL, kEventProcessPLEvents,
+ 0, kEventAttributeNone, &newEvent) != noErr)
+ return PR_FAILURE;
+ err = SetEventParameter(newEvent, kEventParamPLEventQueue,
+ typeUInt32, sizeof(PREventQueue*), &self);
+ if (err == noErr) {
+ err = PostEventToQueue(GetMainEventQueue(), newEvent, kEventPriorityLow);
+ ReleaseEvent(newEvent);
+ }
+ if (err != noErr)
+ return PR_FAILURE;
+#endif
+ return PR_SUCCESS;
+}
+#endif /* defined(XP_MACOSX) */
+
+static PRStatus
+_pl_AcknowledgeNativeNotify(PLEventQueue* self)
+{
+#if defined(_WIN32) || defined(XP_OS2)
+#ifdef XP_OS2
+ QMSG aMsg;
+#else
+ MSG aMsg;
+#endif
+ /*
+ * only remove msg when we've been called directly by
+ * PL_ProcessPendingEvents, not when we've been called by
+ * the window proc because the window proc will remove the
+ * msg for us.
+ */
+ if (self->removeMsg) {
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_AcknowledgeNativeNotify: self=%p", self));
+#ifdef XP_OS2
+ WinPeekMsg((HAB)0, &aMsg, self->eventReceiverWindow,
+ _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE);
+#else
+ PeekMessage(&aMsg, self->eventReceiverWindow,
+ _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE);
+ if (self->timerSet) {
+ KillTimer(self->eventReceiverWindow, TIMER_ID);
+ self->timerSet = PR_FALSE;
+ }
+#endif
+ }
+ return PR_SUCCESS;
+#elif defined(VMS)
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_AcknowledgeNativeNotify: self=%p efn=%d",
+ self, self->efn));
+ /*
+ ** If this is the last entry, then clear the event flag. Also make sure
+ ** the flag is cleared on any spurious wakeups.
+ */
+ sys$clref(self->efn);
+ return PR_SUCCESS;
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+
+ PRInt32 count;
+ unsigned char c;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_AcknowledgeNativeNotify: self=%p",
+ self));
+ /* consume the byte NativeNotify put in our pipe: */
+ count = read(self->eventPipe[0], &c, 1);
+ if ((count == 1) && (c == NOTIFY_TOKEN))
+ return PR_SUCCESS;
+ if ((count == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+ return PR_SUCCESS;
+ return PR_FAILURE;
+#elif defined(MAC_USE_CFRUNLOOPSOURCE) /* vbox */
+ /* vbox */
+ CFRunLoopRunInMode(self->mRunLoopModeStr, 0.0, 1); /* vbox */
+ return PR_SUCCESS; /* vbox */
+#else
+
+ /* nothing to do on the other platforms */
+ return PR_SUCCESS;
+#endif
+}
+
+PR_IMPLEMENT(PRInt32)
+PL_GetEventQueueSelectFD(PLEventQueue* self)
+{
+ if (self == NULL)
+ return -1;
+
+#if defined(VMS)
+ return -(self->efn);
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+ return self->eventPipe[0];
+#else
+ return -1; /* other platforms don't handle this (yet) */
+#endif
+}
+
+PR_IMPLEMENT(PRBool)
+PL_IsQueueOnCurrentThread( PLEventQueue *queue )
+{
+ PRThread *me = PR_GetCurrentThread();
+ return me == queue->handlerThread;
+}
+
+PR_EXTERN(PRBool)
+PL_IsQueueNative(PLEventQueue *queue)
+{
+ return queue->type == EventQueueIsNative ? PR_TRUE : PR_FALSE;
+}
+
+#if defined(_WIN32)
+/*
+** Global Instance handle...
+** In Win32 this is the module handle of the DLL.
+**
+*/
+static HINSTANCE _pr_hInstance;
+#endif
+
+
+#if defined(_WIN32)
+
+/*
+** Initialization routine for the DLL...
+*/
+
+BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ _pr_hInstance = hDLL;
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ _pr_hInstance = NULL;
+ break;
+ }
+
+ return TRUE;
+}
+#endif
+
+
+#if defined(_WIN32) || defined(XP_OS2)
+#ifdef XP_OS2
+MRESULT EXPENTRY
+_md_EventReceiverProc(HWND hwnd, ULONG uMsg, MPARAM wParam, MPARAM lParam)
+#else
+LRESULT CALLBACK
+_md_EventReceiverProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+#endif
+{
+ if (_pr_PostEventMsgId == uMsg )
+ {
+ PREventQueue *queue = (PREventQueue *)lParam;
+ queue->removeMsg = PR_FALSE;
+ PL_ProcessPendingEvents(queue);
+ queue->removeMsg = PR_TRUE;
+#ifdef XP_OS2
+ return MRFROMLONG(TRUE);
+#else
+ return TRUE;
+#endif
+ }
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static PRBool isInitialized;
+static PRCallOnceType once;
+static PRLock *initLock;
+
+/*
+** InitWinEventLib() -- Create the Windows initialization lock
+**
+*/
+static PRStatus InitEventLib( void )
+{
+ PR_ASSERT( initLock == NULL );
+
+ initLock = PR_NewLock();
+ return initLock ? PR_SUCCESS : PR_FAILURE;
+}
+
+#endif /* Win32, OS2 */
+
+#if defined(_WIN32)
+
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+ WNDCLASS wc;
+
+ /*
+ ** If this is the first call to PL_InitializeEventsLib(),
+ ** make the call to InitWinEventLib() to create the initLock.
+ **
+ ** Then lock the initializer lock to insure that
+ ** we have exclusive control over the initialization sequence.
+ **
+ */
+
+
+ /* Register the windows message for XPCOM Event notification */
+ _pr_PostEventMsgId = RegisterWindowMessage("XPCOM_PostEvent");
+
+ /* Register the class for the event receiver window */
+ if (!GetClassInfo(_pr_hInstance, _pr_eventWindowClass, &wc)) {
+ wc.style = 0;
+ wc.lpfnWndProc = _md_EventReceiverProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = _pr_hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = (HBRUSH) NULL;
+ wc.lpszMenuName = (LPCSTR) NULL;
+ wc.lpszClassName = _pr_eventWindowClass;
+ RegisterClass(&wc);
+ }
+
+ /* Create the event receiver window */
+ eventQueue->eventReceiverWindow = CreateWindow(_pr_eventWindowClass,
+ "XPCOM:EventReceiver",
+ 0, 0, 0, 10, 10,
+ NULL, NULL, _pr_hInstance,
+ NULL);
+ PR_ASSERT(eventQueue->eventReceiverWindow);
+ /* Set a property which can be used to retrieve the event queue
+ * within the _md_TimerProc callback
+ */
+ SetProp(eventQueue->eventReceiverWindow,
+ _md_GetEventQueuePropName(), (HANDLE)eventQueue);
+
+ return;
+} /* end _md_CreateEventQueue() */
+#endif /* Winxx */
+
+#if defined(XP_OS2)
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+ /* Must have HMQ for this & can't assume we already have appshell */
+ if( FALSE == WinQueryQueueInfo( HMQ_CURRENT, NULL, 0))
+ {
+ PPIB ppib;
+ PTIB ptib;
+ HAB hab;
+ HMQ hmq;
+
+ /* Set our app to be a PM app before attempting Win calls */
+ DosGetInfoBlocks(&ptib, &ppib);
+ ppib->pib_ultype = 3;
+
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab, 0);
+ PR_ASSERT(hmq);
+ }
+
+ if( !_pr_PostEventMsgId)
+ {
+ WinRegisterClass( 0 /* hab_current */,
+ _pr_eventWindowClass,
+ _md_EventReceiverProc,
+ 0, 0);
+
+ _pr_PostEventMsgId = WinAddAtom( WinQuerySystemAtomTable(),
+ "XPCOM_PostEvent");
+ }
+
+ eventQueue->eventReceiverWindow = WinCreateWindow( HWND_DESKTOP,
+ _pr_eventWindowClass,
+ "", 0,
+ 0, 0, 0, 0,
+ HWND_DESKTOP,
+ HWND_TOP,
+ 0,
+ NULL,
+ NULL);
+ PR_ASSERT(eventQueue->eventReceiverWindow);
+
+ return;
+} /* end _md_CreateEventQueue() */
+#endif /* XP_OS2 */
+
+#if (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS)
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+ /* there's really nothing special to do here,
+ ** the guts of the unix stuff is in the setupnativenotify
+ ** and related functions.
+ */
+ return;
+} /* end _md_CreateEventQueue() */
+#endif /* (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS) */
+
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+static void _md_EventReceiverProc(void *info)
+{
+ PLEventQueue *queue = (PLEventQueue*)info;
+ PL_ProcessPendingEvents(queue);
+}
+
+#elif defined(MAC_USE_CARBON_EVENT)
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+
+static pascal OSStatus _md_EventReceiverProc(EventHandlerCallRef nextHandler,
+ EventRef inEvent,
+ void* userData)
+{
+ if (GetEventClass(inEvent) == kEventClassPL &&
+ GetEventKind(inEvent) == kEventProcessPLEvents)
+ {
+ PREventQueue *queue;
+ if (GetEventParameter(inEvent, kEventParamPLEventQueue,
+ typeUInt32, NULL, sizeof(PREventQueue*), NULL,
+ &queue) == noErr)
+ {
+ PL_ProcessPendingEvents(queue);
+ return noErr;
+ }
+ }
+ return eventNotHandledErr;
+}
+
+static pascal Boolean _md_CarbonEventComparator(EventRef inEvent,
+ void *inCompareData)
+{
+ Boolean match = false;
+
+ if (GetEventClass(inEvent) == kEventClassPL &&
+ GetEventKind(inEvent) == kEventProcessPLEvents)
+ {
+ PREventQueue *queue;
+ match = ((GetEventParameter(inEvent, kEventParamPLEventQueue,
+ typeUInt32, NULL, sizeof(PREventQueue*), NULL,
+ &queue) == noErr) && (queue == inCompareData));
+ }
+ return match;
+}
+
+#endif /* defined(MAC_USE_CARBON_EVENT) */
+
+#if defined(XP_MACOSX)
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+ CFRunLoopSourceContext sourceContext = { 0 };
+ sourceContext.version = 0;
+ sourceContext.info = (void*)eventQueue;
+ sourceContext.perform = _md_EventReceiverProc;
+
+ /* make a run loop source */
+ eventQueue->mRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 /* order */, &sourceContext);
+ PR_ASSERT(eventQueue->mRunLoopSource);
+
+ eventQueue->mMainRunLoop = CFRunLoopGetCurrent();
+ CFRetain(eventQueue->mMainRunLoop);
+
+ /* and add it to the run loop */
+ CFRunLoopAddSource(eventQueue->mMainRunLoop, eventQueue->mRunLoopSource, kCFRunLoopCommonModes);
+
+ /* Add it again but with a unique mode name so we can acknowledge it
+ without processing any other message sources. */
+ { /* vbox */
+ char szModeName[80]; /* vbox */
+ snprintf(szModeName, sizeof(szModeName), "VBoxXPCOMQueueMode-%p", eventQueue); /* vbox */
+ eventQueue->mRunLoopModeStr = CFStringCreateWithCString(kCFAllocatorDefault, /* vbox */
+ szModeName, kCFStringEncodingASCII); /* vbox */
+ CFRunLoopAddSource(eventQueue->mMainRunLoop, /* vbox */
+ eventQueue->mRunLoopSource, eventQueue->mRunLoopModeStr); /* vbox */
+ } /* vbox */
+
+#elif defined(MAC_USE_CARBON_EVENT)
+ eventQueue->eventHandlerUPP = NewEventHandlerUPP(_md_EventReceiverProc);
+ PR_ASSERT(eventQueue->eventHandlerUPP);
+ if (eventQueue->eventHandlerUPP)
+ {
+ EventTypeSpec eventType;
+
+ eventType.eventClass = kEventClassPL;
+ eventType.eventKind = kEventProcessPLEvents;
+
+ InstallApplicationEventHandler(eventQueue->eventHandlerUPP, 1, &eventType,
+ eventQueue, &eventQueue->eventHandlerRef);
+ PR_ASSERT(eventQueue->eventHandlerRef);
+ }
+#endif
+} /* end _md_CreateEventQueue() */
+#endif /* defined(XP_MACOSX) */
+
+/* extra functions for unix */
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+
+PR_IMPLEMENT(PRInt32)
+PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID)
+{
+ PRInt32 count = 0;
+ PRInt32 fullCount;
+
+ if (aSelf == NULL)
+ return -1;
+
+ PR_EnterMonitor(aSelf->monitor);
+
+ if (aSelf->processingEvents) {
+ PR_ExitMonitor(aSelf->monitor);
+ return 0;
+ }
+
+ aSelf->processingEvents = PR_TRUE;
+
+ /* Only process the events that are already in the queue, and
+ * not any new events that get added. Do this by counting the
+ * number of events currently in the queue
+ */
+ fullCount = _pl_GetEventCount(aSelf);
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ fullCount is %d id is %ld\n", fullCount, aID));
+
+ if (fullCount == 0) {
+ aSelf->processingEvents = PR_FALSE;
+ PR_ExitMonitor(aSelf->monitor);
+ return 0;
+ }
+
+ PR_ExitMonitor(aSelf->monitor);
+
+ while (fullCount-- > 0) {
+ /* peek at the next event */
+ PLEvent *event;
+ event = PR_EVENT_PTR(aSelf->queue.next);
+ if (event == NULL)
+ break;
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event %ld\n",
+ event->id));
+ if (event->id >= aID) {
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ skipping event and breaking"));
+ break;
+ }
+
+ event = PL_GetEvent(aSelf);
+ PL_HandleEvent(event);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
+ count++;
+ }
+
+ PR_EnterMonitor(aSelf->monitor);
+
+ /* if full count still had items left then there's still items left
+ in the queue. Let the native notify token stay. */
+
+ if (aSelf->type == EventQueueIsNative) {
+ fullCount = _pl_GetEventCount(aSelf);
+
+ if (fullCount <= 0) {
+ _pl_AcknowledgeNativeNotify(aSelf);
+ aSelf->notified = PR_FALSE;
+ }
+ }
+
+ aSelf->processingEvents = PR_FALSE;
+
+ PR_ExitMonitor(aSelf->monitor);
+
+ return count;
+}
+
+PR_IMPLEMENT(void)
+PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
+ void *aClosure)
+{
+ aSelf->idFunc = aFunc;
+ aSelf->idFuncClosure = aClosure;
+}
+
+PR_IMPLEMENT(void)
+PL_UnregisterEventIDFunc(PLEventQueue *aSelf)
+{
+ aSelf->idFunc = 0;
+ aSelf->idFuncClosure = 0;
+}
+
+#endif /* defined(XP_UNIX) && !defined(XP_MACOSX) */
+
+/* --- end plevent.c --- */
diff --git a/src/libs/xpcom18a4/xpcom/threads/plevent.h b/src/libs/xpcom18a4/xpcom/threads/plevent.h
new file mode 100644
index 00000000..5bc9c89f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/plevent.h
@@ -0,0 +1,690 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**********************************************************************
+NSPL Events
+
+Defining Events
+---------------
+
+Events are essentially structures that represent argument lists for a
+function that will run on another thread. All event structures you
+define must include a PLEvent struct as their first field:
+
+ typedef struct MyEventType {
+ PLEvent e;
+ // arguments follow...
+ int x;
+ char* y;
+ } MyEventType;
+
+It is also essential that you establish a model of ownership for each
+argument passed in an event record, i.e. whether particular arguments
+will be deleted by the event destruction callback, or whether they
+only loaned to the event handler callback, and guaranteed to persist
+until the time at which the handler is called.
+
+Sending Events
+--------------
+
+Events are initialized by PL_InitEvent and can be sent via
+PL_PostEvent or PL_PostSynchronousEvent. Events can also have an
+owner. The owner of an event can revoke all the events in a given
+event-queue by calling PL_RevokeEvents. An owner might want
+to do this if, for instance, it is being destroyed, and handling the
+events after the owner's destruction would cause an error (e.g. an
+MWContext).
+
+Since the act of initializing and posting an event must be coordinated
+with it's possible revocation, it is essential that the event-queue's
+monitor be entered surrounding the code that constructs, initializes
+and posts the event:
+
+ void postMyEvent(MyOwner* owner, int x, char* y)
+ {
+ MyEventType* event;
+
+ PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
+
+ // construct
+ event = PR_NEW(MyEventType);
+ if (event == NULL) goto done;
+
+ // initialize
+ PL_InitEvent(event, owner,
+ (PLHandleEventProc)handleMyEvent,
+ (PLDestroyEventProc)destroyMyEvent);
+ event->x = x;
+ event->y = strdup(y);
+
+ // post
+ PL_PostEvent(myQueue, &event->e);
+
+ done:
+ PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
+ }
+
+If you don't call PL_InitEvent and PL_PostEvent within the
+event-queue's monitor, you'll get a big red assert.
+
+Handling Events
+---------------
+
+To handle an event you must write a callback that is passed the event
+record you defined containing the event's arguments:
+
+ void* handleMyEvent(MyEventType* event)
+ {
+ doit(event->x, event->y);
+ return NULL; // you could return a value for a sync event
+ }
+
+Similarly for the destruction callback:
+
+ void destroyMyEvent(MyEventType* event)
+ {
+ free(event->y); // created by strdup
+ free(event);
+ }
+
+Processing Events in Your Event Loop
+------------------------------------
+
+If your main loop only processes events delivered to the event queue,
+things are rather simple. You just get the next event (which may
+block), and then handle it:
+
+ while (1) {
+ event = PL_GetEvent(myQueue);
+ PL_HandleEvent(event);
+ }
+
+However, if other things must be waited on, you'll need to obtain a
+file-descriptor that represents your event queue, and hand it to select:
+
+ fd = PL_GetEventQueueSelectFD(myQueue);
+ ...add fd to select set...
+ while (select(...)) {
+ if (...fd...) {
+ PL_ProcessPendingEvents(myQueue);
+ }
+ ...
+ }
+
+Of course, with Motif and Windows it's more complicated than that, and
+on Mac it's completely different, but you get the picture.
+
+Revoking Events
+---------------
+If at any time an owner of events is about to be destroyed, you must
+take steps to ensure that no one tries to use the event queue after
+the owner is gone (or a crash may result). You can do this by either
+processing all the events in the queue before destroying the owner:
+
+ {
+ ...
+ PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
+ PL_ProcessPendingEvents(myQueue);
+ DestroyMyOwner(owner);
+ PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
+ ...
+ }
+
+or by revoking the events that are in the queue for that owner. This
+removes them from the queue and calls their destruction callback:
+
+ {
+ ...
+ PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
+ PL_RevokeEvents(myQueue, owner);
+ DestroyMyOwner(owner);
+ PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
+ ...
+ }
+
+In either case it is essential that you be in the event-queue's monitor
+to ensure that all events are removed from the queue for that owner,
+and to ensure that no more events will be delivered for that owner.
+**********************************************************************/
+
+#ifndef plevent_h___
+#define plevent_h___
+
+#include "prtypes.h"
+#include "prclist.h"
+#include "prthread.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prmon.h"
+
+/* For HWND */
+#if defined(XP_WIN32)
+#include <windef.h>
+#elif defined(XP_OS2)
+#define INCL_DOSMISC
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#include <os2.h>
+#endif
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_DestroyEvent VBoxNsplPL_DestroyEvent
+#define PL_HandleEvent VBoxNsplPL_HandleEvent
+#define PL_InitEvent VBoxNsplPL_InitEvent
+#define PL_CreateEventQueue VBoxNsplPL_CreateEventQueue
+#define PL_CreateMonitoredEventQueue VBoxNsplPL_CreateMonitoredEventQueue
+#define PL_CreateNativeEventQueue VBoxNsplPL_CreateNativeEventQueue
+#define PL_DequeueEvent VBoxNsplPL_DequeueEvent
+#define PL_DestroyEventQueue VBoxNsplPL_DestroyEventQueue
+#define PL_EventAvailable VBoxNsplPL_EventAvailable
+#define PL_EventLoop VBoxNsplPL_EventLoop
+#define PL_GetEvent VBoxNsplPL_GetEvent
+#define PL_GetEventOwner VBoxNsplPL_GetEventOwner
+#define PL_GetEventQueueMonitor VBoxNsplPL_GetEventQueueMonitor
+#define PL_GetEventQueueSelectFD VBoxNsplPL_GetEventQueueSelectFD
+#define PL_MapEvents VBoxNsplPL_MapEvents
+#define PL_PostEvent VBoxNsplPL_PostEvent
+#define PL_PostSynchronousEvent VBoxNsplPL_PostSynchronousEvent
+#define PL_ProcessEventsBeforeID VBoxNsplPL_ProcessEventsBeforeID
+#define PL_ProcessPendingEvents VBoxNsplPL_ProcessPendingEvents
+#define PL_RegisterEventIDFunc VBoxNsplPL_RegisterEventIDFunc
+#define PL_RevokeEvents VBoxNsplPL_RevokeEvents
+#define PL_UnregisterEventIDFunc VBoxNsplPL_UnregisterEventIDFunc
+#define PL_WaitForEvent VBoxNsplPL_WaitForEvent
+#define PL_IsQueueNative VBoxNsplPL_IsQueueNative
+#define PL_IsQueueOnCurrentThread VBoxNsplPL_IsQueueOnCurrentThread
+#define PL_FavorPerformanceHint VBoxNsplPL_FavorPerformanceHint
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/* Typedefs */
+
+typedef struct PLEvent PLEvent;
+typedef struct PLEventQueue PLEventQueue;
+
+/*******************************************************************************
+ * Event Queue Operations
+ ******************************************************************************/
+
+/*
+** Creates a new event queue. Returns NULL on failure.
+*/
+PR_EXTERN(PLEventQueue*)
+PL_CreateEventQueue(const char* name, PRThread* handlerThread);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_CreateNativeEventQueue()
+**
+** DESCRIPTION:
+** PL_CreateNativeEventQueue() creates an event queue that
+** uses platform specific notify mechanisms.
+**
+** For Unix, the platform specific notify mechanism provides
+** an FD that may be extracted using the function
+** PL_GetEventQueueSelectFD(). The FD returned may be used in
+** a select() function call.
+**
+** For Windows, the platform specific notify mechanism
+** provides an event receiver window that is called by
+** Windows to process the event using the windows message
+** pump engine.
+**
+** INPUTS:
+** name: A name, as a diagnostic aid.
+**
+** handlerThread: A pointer to the PRThread structure for
+** the thread that will "handle" events posted to this event
+** queue.
+**
+** RETURNS:
+** A pointer to a PLEventQueue structure or NULL.
+**
+*/
+PR_EXTERN(PLEventQueue *)
+ PL_CreateNativeEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_CreateMonitoredEventQueue()
+**
+** DESCRIPTION:
+** PL_CreateMonitoredEventQueue() creates an event queue. No
+** platform specific notify mechanism is created with the
+** event queue.
+**
+** Users of this type of event queue must explicitly poll the
+** event queue to retreive and process events.
+**
+**
+** INPUTS:
+** name: A name, as a diagnostic aid.
+**
+** handlerThread: A pointer to the PRThread structure for
+** the thread that will "handle" events posted to this event
+** queue.
+**
+** RETURNS:
+** A pointer to a PLEventQueue structure or NULL.
+**
+*/
+PR_EXTERN(PLEventQueue *)
+ PL_CreateMonitoredEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+
+/*
+** Destroys an event queue.
+*/
+PR_EXTERN(void)
+PL_DestroyEventQueue(PLEventQueue* self);
+
+/*
+** Returns the monitor associated with an event queue. This monitor is
+** selectable. The monitor should be entered to protect against anyone
+** calling PL_RevokeEvents while the event is trying to be constructed
+** and delivered.
+*/
+PR_EXTERN(PRMonitor*)
+PL_GetEventQueueMonitor(PLEventQueue* self);
+
+#define PL_ENTER_EVENT_QUEUE_MONITOR(queue) \
+ PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
+
+#define PL_EXIT_EVENT_QUEUE_MONITOR(queue) \
+ PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
+
+/*
+** Posts an event to an event queue, waking up any threads waiting for an
+** event. If event is NULL, notification still occurs, but no event will
+** be available.
+**
+** Any events delivered by this routine will be destroyed by PL_HandleEvent
+** when it is called (by the event-handling thread).
+*/
+PR_EXTERN(PRStatus)
+PL_PostEvent(PLEventQueue* self, PLEvent* event);
+
+/*
+** Like PL_PostEvent, this routine posts an event to the event handling
+** thread, but does so synchronously, waiting for the result. The result
+** which is the value of the handler routine is returned.
+**
+** Any events delivered by this routine will be not be destroyed by
+** PL_HandleEvent, but instead will be destroyed just before the result is
+** returned (by the current thread).
+*/
+PR_EXTERN(void*)
+PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
+
+/*
+** Gets an event from an event queue. Returns NULL if no event is
+** available.
+*/
+PR_EXTERN(PLEvent*)
+PL_GetEvent(PLEventQueue* self);
+
+/*
+** Returns true if there is an event available for PL_GetEvent.
+*/
+PR_EXTERN(PRBool)
+PL_EventAvailable(PLEventQueue* self);
+
+/*
+** This is the type of the function that must be passed to PL_MapEvents
+** (see description below).
+*/
+typedef void
+(PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
+
+/*
+** Applies a function to every event in the event queue. This can be used
+** to selectively handle, filter, or remove events. The data pointer is
+** passed to each invocation of the function fun.
+*/
+PR_EXTERN(void)
+PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
+
+/*
+** This routine walks an event queue and destroys any event whose owner is
+** the owner specified. The == operation is used to compare owners.
+*/
+PR_EXTERN(void)
+PL_RevokeEvents(PLEventQueue* self, void* owner);
+
+/*
+** This routine processes all pending events in the event queue. It can be
+** called from the thread's main event-processing loop whenever the event
+** queue's selectFD is ready (returned by PL_GetEventQueueSelectFD).
+*/
+PR_EXTERN(void)
+PL_ProcessPendingEvents(PLEventQueue* self);
+
+/*******************************************************************************
+ * Pure Event Queues
+ *
+ * For when you're only processing PLEvents and there is no native
+ * select, thread messages, or AppleEvents.
+ ******************************************************************************/
+
+/*
+** Blocks until an event can be returned from the event queue. This routine
+** may return NULL if the current thread is interrupted.
+*/
+PR_EXTERN(PLEvent*)
+PL_WaitForEvent(PLEventQueue* self);
+
+/*
+** One stop shopping if all you're going to do is process PLEvents. Just
+** call this and it loops forever processing events as they arrive. It will
+** terminate when your thread is interrupted or dies.
+*/
+PR_EXTERN(void)
+PL_EventLoop(PLEventQueue* self);
+
+/*******************************************************************************
+ * Native Event Queues
+ *
+ * For when you need to call select, or WaitNextEvent, and yet also want
+ * to handle PLEvents.
+ ******************************************************************************/
+
+/*
+** This routine allows you to grab the file descriptor associated with an
+** event queue and use it in the readFD set of select. Useful for platforms
+** that support select, and must wait on other things besides just PLEvents.
+*/
+PR_EXTERN(PRInt32)
+PL_GetEventQueueSelectFD(PLEventQueue* self);
+
+/*
+** This routine will allow you to check to see if the given eventQueue in
+** on the current thread. It will return PR_TRUE if so, else it will return
+** PR_FALSE
+*/
+PR_EXTERN(PRBool)
+ PL_IsQueueOnCurrentThread( PLEventQueue *queue );
+
+/*
+** Returns whether the queue is native (true) or monitored (false)
+*/
+PR_EXTERN(PRBool)
+PL_IsQueueNative(PLEventQueue *queue);
+
+/*******************************************************************************
+ * Event Operations
+ ******************************************************************************/
+
+/*
+** The type of an event handler function. This function is passed as an
+** initialization argument to PL_InitEvent, and called by
+** PL_HandleEvent. If the event is called synchronously, a void* result
+** may be returned (otherwise any result will be ignored).
+*/
+typedef void*
+(PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
+
+/*
+** The type of an event destructor function. This function is passed as
+** an initialization argument to PL_InitEvent, and called by
+** PL_DestroyEvent.
+*/
+typedef void
+(PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
+
+/*
+** Initializes an event. Usually events are embedded in a larger event
+** structure which holds event-specific data, so this is an initializer
+** for that embedded part of the structure.
+*/
+PR_EXTERN(void)
+PL_InitEvent(PLEvent* self, void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor);
+
+/*
+** Returns the owner of an event.
+*/
+PR_EXTERN(void*)
+PL_GetEventOwner(PLEvent* self);
+
+/*
+** Handles an event, calling the event's handler routine.
+*/
+PR_EXTERN(void)
+PL_HandleEvent(PLEvent* self);
+
+/*
+** Destroys an event, calling the event's destructor.
+*/
+PR_EXTERN(void)
+PL_DestroyEvent(PLEvent* self);
+
+/*
+** Removes an event from an event queue.
+*/
+PR_EXTERN(void)
+PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
+
+
+/*
+ * Give hint to native PL_Event notification mechanism. If the native
+ * platform needs to tradeoff performance vs. native event starvation
+ * this hint tells the native dispatch code which to favor.
+ * The default is to prevent event starvation.
+ *
+ * Calls to this function may be nested. When the number of calls that
+ * pass PR_TRUE is subtracted from the number of calls that pass PR_FALSE
+ * is greater than 0, performance is given precedence over preventing
+ * event starvation.
+ *
+ * The starvationDelay arg is only used when
+ * favorPerformanceOverEventStarvation is PR_FALSE. It is the
+ * amount of time in milliseconds to wait before the PR_FALSE actually
+ * takes effect.
+ */
+PR_EXTERN(void)
+PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay);
+
+
+/*******************************************************************************
+ * Private Stuff
+ ******************************************************************************/
+
+struct PLEvent {
+ PRCList link;
+ PLHandleEventProc handler;
+ PLDestroyEventProc destructor;
+ void* owner;
+ void* synchronousResult;
+ PRLock* lock;
+ PRCondVar* condVar;
+ PRBool handled;
+#ifdef PL_POST_TIMINGS
+ PRIntervalTime postTime;
+#endif
+#ifdef XP_UNIX
+ unsigned long id;
+#endif /* XP_UNIX */
+ /* other fields follow... */
+};
+
+/******************************************************************************/
+
+/*
+** Returns the event queue associated with the main thread.
+**
+*/
+#if defined(XP_WIN) || defined(XP_OS2)
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_GetNativeEventReceiverWindow()
+**
+** DESCRIPTION:
+** PL_GetNativeEventReceiverWindow() returns the windows
+** handle of the event receiver window associated with the
+** referenced PLEventQueue argument.
+**
+** INPUTS:
+** PLEventQueue pointer
+**
+** RETURNS:
+** event receiver window handle.
+**
+** RESTRICTIONS: MS-Windows ONLY.
+**
+*/
+PR_EXTERN(HWND)
+ PL_GetNativeEventReceiverWindow(
+ PLEventQueue *eqp
+ );
+#endif /* XP_WIN || XP_OS2 */
+
+#ifdef XP_UNIX
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_ProcessEventsBeforeID()
+**
+** DESCRIPTION:
+**
+** PL_ProcessEventsBeforeID() will process events in a native event
+** queue that have an id that is older than the ID passed in.
+**
+** INPUTS:
+** PLEventQueue *aSelf
+** unsigned long aID
+**
+** RETURNS:
+** PRInt32 number of requests processed, -1 on error.
+**
+** RESTRICTIONS: Unix only (well, X based unix only)
+*/
+PR_EXTERN(PRInt32)
+PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID);
+
+/* This prototype is a function that can be called when an event is
+ posted to stick an ID on it. */
+
+typedef unsigned long
+(PR_CALLBACK *PLGetEventIDFunc)(void *aClosure);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_RegisterEventIDFunc()
+**
+** DESCRIPTION:
+**
+** This function registers a function for getting the ID on unix for
+** this event queue.
+**
+** INPUTS:
+** PLEventQueue *aSelf
+** PLGetEventIDFunc func
+** void *aClosure
+**
+** RETURNS:
+** void
+**
+** RESTRICTIONS: Unix only (well, X based unix only) */
+PR_EXTERN(void)
+PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
+ void *aClosure);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_RegisterEventIDFunc()
+**
+** DESCRIPTION:
+**
+** This function unregisters a function for getting the ID on unix for
+** this event queue.
+**
+** INPUTS:
+** PLEventQueue *aSelf
+**
+** RETURNS:
+** void
+**
+** RESTRICTIONS: Unix only (well, X based unix only) */
+PR_EXTERN(void)
+PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
+
+#endif /* XP_UNIX */
+
+
+/* ----------------------------------------------------------------------- */
+
+#if defined(NO_NSPR_10_SUPPORT)
+#else
+/********* ???????????????? FIX ME ??????????????????????????? *****/
+/********************** Some old definitions *****************************/
+
+/* Re: prevent.h->plevent.h */
+#define PREvent PLEvent
+#define PREventQueue PLEventQueue
+#define PR_CreateEventQueue PL_CreateEventQueue
+#define PR_DestroyEventQueue PL_DestroyEventQueue
+#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
+#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
+#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
+#define PR_PostEvent PL_PostEvent
+#define PR_PostSynchronousEvent PL_PostSynchronousEvent
+#define PR_GetEvent PL_GetEvent
+#define PR_EventAvailable PL_EventAvailable
+#define PREventFunProc PLEventFunProc
+#define PR_MapEvents PL_MapEvents
+#define PR_RevokeEvents PL_RevokeEvents
+#define PR_ProcessPendingEvents PL_ProcessPendingEvents
+#define PR_WaitForEvent PL_WaitForEvent
+#define PR_EventLoop PL_EventLoop
+#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
+#define PRHandleEventProc PLHandleEventProc
+#define PRDestroyEventProc PLDestroyEventProc
+#define PR_InitEvent PL_InitEvent
+#define PR_GetEventOwner PL_GetEventOwner
+#define PR_HandleEvent PL_HandleEvent
+#define PR_DestroyEvent PL_DestroyEvent
+#define PR_DequeueEvent PL_DequeueEvent
+#define PR_GetMainEventQueue PL_GetMainEventQueue
+
+/********* ????????????? End Fix me ?????????????????????????????? *****/
+#endif /* NO_NSPR_10_SUPPORT */
+
+PR_END_EXTERN_C
+
+#endif /* plevent_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/tools/.cvsignore b/src/libs/xpcom18a4/xpcom/tools/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tools/Makefile.in b/src/libs/xpcom18a4/xpcom/tools/Makefile.in
new file mode 100644
index 00000000..be87de04
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = registry
+
+ifeq ($(OS_ARCH),WINNT)
+DIRS += windows
+endif
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl b/src/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl
new file mode 100755
index 00000000..81ccb212
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl
@@ -0,0 +1,177 @@
+#!/usr/local/bin/perl -w
+
+# Perl script to analyze the xpcom output file
+#
+# To create xpcom output file :
+#
+# setenv NSPR_LOG_MODULES nsComponentManager:5
+# setenv NSPR_LOG_FILE xpcom.out
+# ./mozilla
+#
+# Also to try to convert CID -> contractID this program looks for
+# a file reg.out in the current directory. To generate this file
+#
+# $ regExport > reg.out
+#
+# Usage: analyze-xpcom-log.pl < xpcom.out
+# [does better if ./reg.out is available]
+#
+# Suresh Duddi <dpsuresh@netscape.net>
+
+
+use strict;
+
+# forward declarations
+sub getContractID($);
+sub sum($);
+
+# Configuration parameters
+# Print all ?
+my $all = 0;
+
+# hash of cid -> contractid
+my %contractid;
+my %contractid_n;
+my %failedContractid_n;
+
+# count of instances of objects created
+my (%objs, %objs_contractid, %failedObjs) = ();
+
+# dlls loaded
+my @dlls;
+
+# temporaries
+my ($cid, $n, $str);
+
+while (<>) {
+ chomp;
+
+ # dlls loaded
+ if (/loading \"(.*)\"/) {
+ push @dlls, $1;
+ next;
+ }
+
+ # FAILED ContractIDToClassID
+ if (/ContractIDToClassID\((.*)\).*\[FAILED\]/) {
+ $failedContractid_n{$1}++;
+ next;
+ }
+
+ # ContractIDToClassID
+ if (/ContractIDToClassID\((.*)\).*\{(.*)\}/) {
+ $contractid{$2} = $1;
+ $contractid_n{$2}++;
+ next;
+ }
+
+ # CreateInstance()
+ if (/CreateInstance\(\{(.*)\}\) succeeded/) {
+ $objs{$1}++;
+ next;
+ }
+
+ # CreateInstanceByContractID()
+ if (/CreateInstanceByContractID\((.*)\) succeeded/) {
+ $objs_contractid{$1}++;
+ next;
+ }
+
+ # FAILED CreateInstance()
+ if (/CreateInstance\(\{(.*)\}\) FAILED/) {
+ $failedObjs{$1}++;
+ next;
+ }
+}
+
+# if there is a file named reg.out in the current dir
+# then use that to fill in the ContractIDToClassID mapping.
+my $REG;
+open REG, "<reg.out";
+while (<REG>) {
+ chomp;
+ if (/contractID - (.*)$/) {
+ my $id = $1;
+ $cid = <REG>;
+ chomp($cid);
+ $cid =~ s/^.*\{(.*)\}.*$/$1/;
+ $contractid{$cid} = $id;
+ }
+}
+
+# print results
+# ----------------------------------------------------------------------
+
+# dlls loaded
+print "dlls loaded [", scalar @dlls, "]\n";
+print "----------------------------------------------------------------------\n";
+for ($n = 0; $n < scalar @dlls; $n++) {
+ printf "%2d. %s\n", $n+1, $dlls[$n];
+}
+print "\n";
+
+# Objects created
+print "Object creations from CID [", sum(\%objs), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$objs{$b} <=> $objs{$a} } keys %objs) {
+ last if (!$all && $objs{$cid} < 50);
+ printf "%5d. %s - %s\n", $objs{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+print "Object creations from ContractID [", sum(\%objs_contractid), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$objs_contractid{$b} <=> $objs_contractid{$a} } keys %objs_contractid) {
+ last if (!$all && $objs_contractid{$cid} < 50);
+ printf "%5d. %s - %s\n", $objs_contractid{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+# FAILED Objects created
+print "FAILED Objects creations [", sum(\%failedObjs), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$failedObjs{$b} <=> $failedObjs{$a} } keys %failedObjs) {
+ last if (!$all && $failedObjs{$cid} < 50);
+ printf "%5d. %s - %s", $failedObjs{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+# ContractIDToClassID calls
+print "ContractIDToClassID() calls [", sum(\%contractid_n),"]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$contractid_n{$b} <=> $contractid_n{$a} } keys %contractid_n) {
+ last if (!$all && $contractid_n{$cid} < 50);
+ printf "%5d. %s - %s\n", $contractid_n{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+
+# FAILED ContractIDToClassID calls
+print "FAILED ContractIDToClassID() calls [", sum(\%failedContractid_n), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$failedContractid_n{$b} <=> $failedContractid_n{$a} } keys %failedContractid_n) {
+ last if (!$all && $failedContractid_n{$cid} < 50);
+ printf "%5d. %s\n", $failedContractid_n{$cid}, $cid;
+}
+print "\n";
+
+
+# Subroutines
+
+sub getContractID($) {
+ my $cid = shift;
+ my $ret = "";
+ $ret = $contractid{$cid} if (exists $contractid{$cid});
+ return $ret;
+}
+
+sub sum($) {
+ my $hash_ref = shift;
+ my %hash = %$hash_ref;
+ my $total = 0;
+ my $key;
+ foreach $key (keys %hash) {
+ $total += $hash{$key};
+ }
+ return $total;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore b/src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore
new file mode 100644
index 00000000..91acd38b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+regExport
+regxpcom
diff --git a/src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in b/src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in
new file mode 100644
index 00000000..5c19d014
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in
@@ -0,0 +1,77 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+CPPSRCS = regxpcom.cpp
+
+DEFINES += -DXPCOM_GLUE
+
+REQUIRES = \
+ string \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../build \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# Need to link with CoreFoundation on Mac
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+LIBS += \
+ $(TK_LIBS) \
+ $(NULL)
+endif
+
+SDK_BINARY = \
+ $(SIMPLE_PROGRAMS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp b/src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp
new file mode 100644
index 00000000..b8822b8f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp
@@ -0,0 +1,404 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Mike Shaver <shaver@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "stdlib.h"
+#include "prenv.h"
+#include "nspr.h"
+
+#include "nsXPCOMPrivate.h" // for XPCOM_DLL defines.
+
+#include "nsXPCOMGlue.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+#include "nsILocalFile.h"
+#include "nsEmbedString.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+
+
+static PRBool gUnreg = PR_FALSE, gQuiet = PR_FALSE;
+
+static const char* gXPCOMLocation = nsnull;
+static const char* gCompRegLocation = nsnull;
+static const char* gXPTIDatLocation = nsnull;
+static char* gPathEnvString = nsnull;
+
+class DirectoryServiceProvider : public nsIDirectoryServiceProvider
+{
+ public:
+ DirectoryServiceProvider() {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+
+ private:
+ ~DirectoryServiceProvider() {}
+};
+
+NS_IMPL_ISUPPORTS1(DirectoryServiceProvider, nsIDirectoryServiceProvider)
+
+NS_IMETHODIMP
+DirectoryServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
+{
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *_retval = nsnull;
+ *persistant = PR_TRUE;
+
+ const char* fileLocation = nsnull;
+
+ if(strcmp(prop, NS_XPCOM_CURRENT_PROCESS_DIR) == 0 && gXPCOMLocation)
+ {
+ fileLocation = gXPCOMLocation;
+ }
+ else if(strcmp(prop, NS_XPCOM_COMPONENT_REGISTRY_FILE) == 0 && gCompRegLocation)
+ {
+ fileLocation = gCompRegLocation;
+ }
+ else if(strcmp(prop, NS_XPCOM_XPTI_REGISTRY_FILE) == 0 && gXPTIDatLocation)
+ {
+ fileLocation = gXPTIDatLocation;
+ }
+ else
+ return NS_ERROR_FAILURE;
+
+ rv = NS_NewNativeLocalFile(nsEmbedCString(fileLocation), PR_TRUE, getter_AddRefs(localFile));
+ if (NS_FAILED(rv)) return rv;
+
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+}
+
+int startup_xpcom()
+{
+ nsresult rv;
+
+ if (gXPCOMLocation) {
+ int len = strlen(gXPCOMLocation);
+ char* xpcomPath = (char*) malloc(len + sizeof(XPCOM_DLL) + sizeof(XPCOM_FILE_PATH_SEPARATOR) + 1);
+ sprintf(xpcomPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, gXPCOMLocation);
+
+ rv = XPCOMGlueStartup(xpcomPath);
+
+ free(xpcomPath);
+
+ const char* path = PR_GetEnv(XPCOM_SEARCH_KEY);
+ if (!path) {
+ path = "";
+ }
+
+ if (gPathEnvString)
+ PR_smprintf_free(gPathEnvString);
+
+ gPathEnvString = PR_smprintf("%s=%s;%s",
+ XPCOM_SEARCH_KEY,
+ gXPCOMLocation,
+ path);
+
+ if (gXPCOMLocation)
+ PR_SetEnv(gPathEnvString);
+ }
+ else
+ {
+ rv = XPCOMGlueStartup(nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ {
+ printf("Can not initialize XPCOM Glue\n");
+ return -1;
+ }
+
+ DirectoryServiceProvider *provider = new DirectoryServiceProvider();
+ if ( !provider )
+ {
+ NS_WARNING("GRE_Startup failed");
+ XPCOMGlueShutdown();
+ return -1;
+ }
+
+ nsCOMPtr<nsILocalFile> file;
+ if (gXPCOMLocation)
+ {
+ rv = NS_NewNativeLocalFile(nsEmbedCString(gXPCOMLocation),
+ PR_TRUE,
+ getter_AddRefs(file));
+ }
+
+ NS_ADDREF(provider);
+ rv = NS_InitXPCOM2(nsnull, file, provider);
+ NS_RELEASE(provider);
+
+ if (NS_FAILED(rv)) {
+ printf("Can not initialize XPCOM\n");
+ XPCOMGlueShutdown();
+ return -1;
+ }
+
+ return 0;
+}
+
+void shutdown_xpcom()
+{
+ nsresult rv;
+
+ rv = NS_ShutdownXPCOM(nsnull);
+
+ if (NS_FAILED(rv)) {
+ printf("Can not shutdown XPCOM cleanly\n");
+ }
+
+ rv = XPCOMGlueShutdown();
+
+ if (NS_FAILED(rv)) {
+ printf("Can not shutdown XPCOM Glue cleanly\n");
+ }
+ if (gPathEnvString)
+ PR_smprintf_free(gPathEnvString);
+}
+
+
+nsresult Register(const char *path)
+{
+ startup_xpcom();
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> spec;
+
+ if (path) {
+ rv = NS_NewNativeLocalFile(nsEmbedCString(path),
+ PR_TRUE,
+ getter_AddRefs(spec));
+ }
+
+ nsCOMPtr<nsIComponentRegistrar> registrar;
+ rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
+ if (NS_FAILED(rv)) {
+ printf("Can not aquire component registrar\n");
+ return rv;
+ }
+
+ if (gUnreg)
+ rv = registrar->AutoUnregister(spec);
+ else
+ rv = registrar->AutoRegister(spec);
+
+ spec = 0;
+ registrar = 0;
+
+ shutdown_xpcom();
+ return rv;
+}
+
+
+void ReportSuccess(const char *file)
+{
+ if (gQuiet)
+ return;
+
+ if (gUnreg)
+ printf("Unregistration successful for %s\n", file);
+ else
+ printf("Registration successful for %s\n", file);
+}
+
+void ReportError(nsresult err, const char *file)
+{
+ if (gUnreg)
+ printf("Unregistration failed: (");
+ else
+ printf("Registration failed: (");
+
+ switch (err)
+ {
+ case NS_ERROR_FACTORY_NOT_LOADED:
+ printf("Factory not loaded");
+ break;
+ case NS_NOINTERFACE:
+ printf("No Interface");
+ break;
+ case NS_ERROR_NULL_POINTER:
+ printf("Null pointer");
+ break;
+ case NS_ERROR_OUT_OF_MEMORY:
+ printf("Out of memory");
+ break;
+ default:
+ printf("%x", (unsigned)err);
+ }
+
+ printf(") %s\n", file);
+}
+
+void printHelp()
+{
+ printf(
+"Mozilla regxpcom - a registration tool for xpcom components \n"
+" \n"
+"Usage: regxpcom [options] [file-or-directory] \n"
+" \n"
+"Options: \n"
+" -x path Specifies the location of a directory containing the \n"
+" xpcom library which will be used when registering new \n"
+" component libraries. This path will also be added to \n"
+" the \"load library\" path. If not specified, the \n"
+" current working directory will be used. \n"
+" -c path Specifies the location of the compreg.dat file. If \n"
+" not specifed, the compreg.dat file will be in its \n"
+" default location. \n"
+" -d path Specifies the location of the xpti.dat file. If not \n"
+" specifed, the xpti.dat file will be in its default \n"
+" location. \n"
+" -a Option to register all files in the default component \n"
+" directories. This is the default behavior if regxpcom \n"
+" is called without any arguments. \n"
+" -h Displays this help screen. Must be the only option \n"
+" specified. \n"
+" -u Option to uninstall the files-or-directory instead of \n"
+" registering them. \n"
+" -q Quiets some of the output of regxpcom. \n\n");
+}
+
+int ProcessArgs(int argc, char *argv[])
+{
+ int i = 1, result = 0;
+ nsresult res;
+
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ int j;
+ for (j = 1; argv[i][j] != '\0'; j++)
+ {
+ switch (argv[i][j])
+ {
+ case 'h':
+ printHelp();
+ return 0; // we are all done!
+
+ case 'u':
+ gUnreg = PR_TRUE;
+ break;
+
+ case 'q':
+ gQuiet = PR_TRUE;
+ break;
+
+ case 'a':
+ {
+ res = Register(nsnull);
+ if (NS_FAILED(res))
+ {
+ ReportError(res, "component directory");
+ result = -1;
+ }
+ else
+ {
+ ReportSuccess("component directory");
+ }
+ }
+ break;
+
+ case 'x':
+ gXPCOMLocation = argv[++i];
+ j = strlen(gXPCOMLocation) - 1;
+ break;
+
+ case 'c':
+ gCompRegLocation = argv[++i];
+ j = strlen(gCompRegLocation) - 1;
+ break;
+
+ case 'd':
+ gXPTIDatLocation = argv[++i];
+ j = strlen(gXPTIDatLocation) - 1;
+ break;
+
+ default:
+ printf("Unknown option '%c'\n", argv[i][j]);
+ }
+ }
+ }
+ else
+ {
+ res = Register(argv[i]);
+
+ if (NS_FAILED(res))
+ {
+ ReportError(res, argv[i]);
+ result = -1;
+ }
+ else
+ {
+ ReportSuccess(argv[i]);
+ }
+ }
+ i++;
+ }
+ return result;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ nsresult rv;
+
+ /* With no arguments, regxpcom will autoregister */
+ if (argc <= 1)
+ {
+ startup_xpcom();
+ nsCOMPtr<nsIComponentRegistrar> registrar;
+ rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
+ if (NS_FAILED(rv)) {
+ printf("Can not aquire component registrar\n");
+ return -1;
+ }
+ rv = registrar->AutoRegister(nsnull);
+ ret = (NS_FAILED(rv)) ? -1 : 0;
+ registrar = 0;
+ shutdown_xpcom();
+ } else
+ ret = ProcessArgs(argc, argv);
+
+ return ret;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore b/src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in b/src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in
new file mode 100644
index 00000000..f6ba7e69
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in
@@ -0,0 +1,52 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+SIMPLE_PROGRAMS = rebasedlls$(BIN_SUFFIX)
+
+CPPSRCS = rebasedlls.cpp
+
+OS_LIBS += $(call EXPAND_LIBNAME,imagehlp)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp b/src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp
new file mode 100644
index 00000000..321160e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include <windows.h>
+#include <stdio.h>
+#include <imagehlp.h>
+#include <time.h>
+
+static char* gSymbolPath = NULL;
+static DWORD gBaseAddr = (DWORD) 0x60000000;
+static time_t now;
+
+static void
+ReBase(char* aDLLName)
+{
+ DWORD oldsize, oldbase, newsize;
+ DWORD newbase = gBaseAddr;
+ BOOL b = ReBaseImage(aDLLName, gSymbolPath, TRUE, FALSE, FALSE,
+ 0, &oldsize, &oldbase, &newsize, &newbase,
+ now);
+ DWORD lastError = ::GetLastError();
+ printf("%-20s %08x %08x %08x %08x",
+ aDLLName, oldbase, oldsize, newbase, newsize);
+ if (!b) {
+ printf(" (failed: error=%d/0x%x)", lastError, lastError);
+ }
+ fputs("\n", stdout);
+
+ // advance base; round size up to nearest 64k
+ newsize = ((newsize + 65535) >> 16) << 16;
+ gBaseAddr = newbase + newsize;
+}
+
+static void
+Usage()
+{
+ printf("Usage: ReBase [-libs library-path] dlls...\n");
+}
+
+int
+main(int argc, char** argv)
+{
+ now = time(0);
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "-libs") == 0) {
+ if (i == argc - 1) {
+ Usage();
+ return -1;
+ }
+ gSymbolPath = argv[++i];
+ }
+ else {
+ Usage();
+ return -1;
+ }
+ }
+ else
+ break;
+ }
+
+ if (i < argc) {
+ printf("Library OldBase OldSize NewBase NewSize\n");
+ printf("------- ------- ------- ------- -------\n");
+ }
+ for (; i < argc; i++) {
+ ReBase(argv[i]);
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/Makefile.in
new file mode 100644
index 00000000..43d92023
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = xpt xpidl
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore
new file mode 100644
index 00000000..8e5eac0d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore
@@ -0,0 +1,2 @@
+xpidl
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in
new file mode 100644
index 00000000..ae228ef0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in
@@ -0,0 +1,88 @@
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+PROGRAM = xpidl$(BIN_SUFFIX)
+INTERNAL_TOOLS = 1
+
+# glib and libIDL link against the non-debug msvcrt
+MOZ_NO_DEBUG_RTL=1
+
+CSRCS = \
+ xpidl.c \
+ xpidl_idl.c \
+ xpidl_util.c \
+ xpidl_header.c \
+ xpidl_typelib.c \
+ xpidl_doc.c \
+ xpidl_java.c \
+ $(NULL)
+
+SDK_BINARY = \
+ $(PROGRAM) \
+ $(NULL)
+
+ifdef CROSS_COMPILE
+HOST_PROGRAM = host_xpidl$(HOST_BIN_SUFFIX)
+HOST_CSRCS = $(CSRCS)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+CFLAGS += $(LIBIDL_CFLAGS)
+
+# Compile directly against the static lib, so we can use xpidl during the build
+# without the shared library path being set.
+ifeq (WINNT,$(OS_ARCH))
+DEFINES += -DEXPORT_XPT_API
+ifndef GNU_CC
+LDFLAGS += -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRTD
+endif
+endif
+
+# Tell the $(PROGRAM) target that we need to be recompiled when libxpt changes.
+LIBS = $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX) $(LIBIDL_LIBS)
+EXTRA_DEPS = $(wildcard $(DIST)/lib/$(LIB_PREFIX)xpt.*)
+
+ifdef CROSS_COMPILE
+HOST_CFLAGS += $(HOST_LIBIDL_CFLAGS)
+HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX) $(HOST_LIBIDL_LIBS)
+HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*)
+
+ifdef HOST_NSPR_MDCPUCFG
+HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
+endif
+endif
+
+ifdef MACOS_SDK_DIR
+NEXT_ROOT=
+OS_LIBS := $(patsubst -L$(MACOS_SDK_DIR)/usr/lib%,,$(OS_LIBS))
+endif
+
+export::
+ @$(MAKE) libs
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/README b/src/libs/xpcom18a4/xpcom/typelib/xpidl/README
new file mode 100644
index 00000000..b7a400e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/README
@@ -0,0 +1,16 @@
+Wed Dec 2 14:35:41 EST 1998
+
+xpidl depends on Andrew Veliath and Elliot Lee's libIDL, a part of the
+GNOME ORBit C ORB. We currently require libIDL >= 0.6.3, which in turn
+requires glib >= 1.2.0.
+
+libIDL builds for Linux and Win32 can be found, along with source
+tarballs, at http://www.rpi.edu/~veliaa/libIDL/, and Win32 users will
+need glib 1.2 and glib 1.2-dev from
+http://user.sgic.fi/~tml/gimp/win32/. Source and Linux RPMs are also
+available from ftp://ftp.mozilla.org/pub/mozilla/libraries, and Win32
+binaries are included in the wintools.zip file at
+ftp://ftp.mozilla.org/pub/mozilla/source/wintools.zip. A Mac project
+is in progress, and should be appearing shortly.
+
+glib tarballs and RPMs for Linux can be found through http://www.gtk.org.
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc
new file mode 100644
index 00000000..fb06f6a3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc
new file mode 100644
index 00000000..bec7c043
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c
new file mode 100644
index 00000000..ecda11e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c
@@ -0,0 +1,139 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mac_console.h"
+
+#ifndef __CONSOLE__
+#include <console.h>
+#endif
+
+extern CWPluginContext gPluginContext;
+
+UInt32 mac_console_count = 0;
+CWMemHandle mac_console_handle = NULL;
+
+/*
+ * The following four functions provide the UI for the console package.
+ * Users wishing to replace SIOUX with their own console package need
+ * only provide the four functions below in a library.
+ */
+
+/*
+ * extern short InstallConsole(short fd);
+ *
+ * Installs the Console package, this function will be called right
+ * before any read or write to one of the standard streams.
+ *
+ * short fd: The stream which we are reading/writing to/from.
+ * returns short: 0 no error occurred, anything else error.
+ */
+
+short InstallConsole(short fd)
+{
+#pragma unused (fd)
+ mac_console_count = 0;
+ CWAllocMemHandle(gPluginContext, 8192, false, &mac_console_handle);
+ return 0;
+}
+
+/*
+ * extern void RemoveConsole(void);
+ *
+ * Removes the console package. It is called after all other streams
+ * are closed and exit functions (installed by either atexit or _atexit)
+ * have been called. Since there is no way to recover from an error,
+ * this function doesn't need to return any.
+ */
+
+void RemoveConsole(void)
+{
+ if (mac_console_handle != NULL) {
+ CWFreeMemHandle(gPluginContext, mac_console_handle);
+ mac_console_handle = NULL;
+ }
+}
+
+/*
+ * extern long WriteCharsToConsole(char *buffer, long n);
+ *
+ * Writes a stream of output to the Console window. This function is
+ * called by write.
+ *
+ * char *buffer: Pointer to the buffer to be written.
+ * long n: The length of the buffer to be written.
+ * returns short: Actual number of characters written to the stream,
+ * -1 if an error occurred.
+ */
+
+long WriteCharsToConsole(char *buffer, long n)
+{
+ long size = 0;
+ void* ptr = NULL;
+
+ if (CWGetMemHandleSize(gPluginContext, mac_console_handle, &size) == noErr) {
+ if (mac_console_count + n >= size) {
+ size += 8192;
+ if (CWResizeMemHandle(gPluginContext, mac_console_handle, size) != noErr)
+ return -1;
+ }
+ }
+
+ if (CWLockMemHandle(gPluginContext, mac_console_handle, false, &ptr) == noErr) {
+ BlockMoveData(buffer, (char *)ptr + mac_console_count, n);
+ mac_console_count += n;
+ CWUnlockMemHandle(gPluginContext, mac_console_handle);
+ }
+
+ return 0;
+}
+
+/*
+ * extern long ReadCharsFromConsole(char *buffer, long n);
+ *
+ * Reads from the Console into a buffer. This function is called by
+ * read.
+ *
+ * char *buffer: Pointer to the buffer which will recieve the input.
+ * long n: The maximum amount of characters to be read (size of
+ * buffer).
+ * returns short: Actual number of characters read from the stream,
+ * -1 if an error occurred.
+ */
+
+long ReadCharsFromConsole(char *buffer, long n)
+{
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h
new file mode 100644
index 00000000..88809f85
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h
@@ -0,0 +1,49 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_console.h
+ */
+
+#pragma once
+
+#include <Files.h>
+#include <Memory.h>
+
+#include "CWPlugins.h"
+
+extern UInt32 mac_console_count;
+extern CWMemHandle mac_console_handle;
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp
new file mode 100644
index 00000000..41d03d88
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp
@@ -0,0 +1,146 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_memory.cpp
+ */
+
+#include <new.h>
+#include <stdlib.h>
+
+#include <Files.h>
+#include <Memory.h>
+
+#include "DropInCompilerLinker.h"
+#include "CompilerMapping.h"
+#include "CWPluginErrors.h"
+
+extern CWPluginContext gPluginContext;
+
+/**
+ * Note: memory allocated by these operators will automatically be freed after the
+ * current call into xpidl_compiler completes. This should be fine in most cases,
+ * as we are also having the compiler be reloaded for every request to reinitialize
+ * global data. Just be careful out there!
+ */
+
+const Boolean kTemporaryAllocation = false;
+
+void* operator new(size_t size)
+{
+ void* ptr = NULL;
+ if (CWAllocateMemory(gPluginContext, size, kTemporaryAllocation, &ptr) == cwNoErr)
+ return ptr;
+ return NULL;
+}
+
+void operator delete(void* ptr)
+{
+ if (ptr != NULL)
+ CWFreeMemory(gPluginContext, ptr, kTemporaryAllocation);
+}
+
+void* operator new[] (size_t size)
+{
+ void* ptr = NULL;
+ if (CWAllocateMemory(gPluginContext, size, kTemporaryAllocation, &ptr) == cwNoErr)
+ return ptr;
+ return NULL;
+}
+
+void operator delete[](void* ptr)
+{
+ if (ptr != NULL)
+ CWFreeMemory(gPluginContext, ptr, kTemporaryAllocation);
+}
+
+namespace std {
+
+#define TRACK_ALLOCATION
+#define kTrackedCookie 'TRKD'
+
+void* malloc(size_t size)
+{
+#if defined(TRACK_ALLOCATION)
+ OSType* ptr = (OSType*) new char[sizeof(OSType) + size];
+ if (ptr != NULL)
+ *ptr++ = kTrackedCookie;
+ return ptr;
+#else
+ return new char[size];
+#endif
+}
+
+void free(void *ptr)
+{
+#if defined(TRACK_ALLOCATION)
+ OSType* type = (OSType*)ptr;
+ if (*--type == kTrackedCookie)
+ delete[] (char*) type;
+ else
+ DebugStr("\pillegal block passed to free.");
+#else
+ delete[] (char*) ptr;
+#endif
+}
+
+void* calloc(size_t nmemb, size_t size)
+{
+ size *= nmemb;
+ void* ptr = malloc(size);
+ if (ptr != NULL) {
+ BlockZero(ptr, size);
+ }
+ return ptr;
+}
+
+void* realloc(void * ptr, size_t size)
+{
+ void* newptr = NULL;
+
+ if (size > 0)
+ newptr = malloc(size);
+
+ if (ptr != NULL && newptr != NULL)
+ BlockMoveData(ptr, newptr, size);
+
+ if (ptr != NULL)
+ free(ptr);
+
+ return newptr;
+}
+
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp
new file mode 100644
index 00000000..881dcb0b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp
@@ -0,0 +1,58 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_stdlib.cpp
+
+ replacement functions for the CodeWarrior plugin.
+
+ by Patrick C. Beard.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+// simply throw us out of here!
+
+jmp_buf exit_jump;
+int exit_status = 0;
+
+void std::exit(int status)
+{
+ exit_status = status;
+ longjmp(exit_jump, -1);
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp
new file mode 100644
index 00000000..37e389e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp
@@ -0,0 +1,38 @@
+/*
+ mac_strings.cpp
+ */
+
+#include "mac_strings.h"
+
+#include <string.h>
+#include <Memory.h>
+#include <new>
+
+StringPtr c2p_strcpy(StringPtr pstr, const char* cstr)
+{
+ size_t len = ::strlen(cstr);
+ if (len > 255) len = 255;
+ BlockMoveData(cstr, pstr + 1, len);
+ pstr[0] = len;
+ return pstr;
+}
+
+char* p2c_strcpy(char* cstr, const StringPtr pstr)
+{
+ size_t len = pstr[0];
+ BlockMoveData(pstr + 1, cstr, len);
+ cstr[len] = '\0';
+ return cstr;
+}
+
+char* p2c_strdup(StringPtr pstr)
+{
+ size_t len = pstr[0];
+ char* cstr = new char[1 + len];
+ if (cstr != NULL) {
+ BlockMoveData(pstr + 1, cstr, len);
+ cstr[len] = '\0';
+ }
+ return cstr;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h
new file mode 100644
index 00000000..44f39312
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h
@@ -0,0 +1,47 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_strings.h
+ */
+
+#pragma once
+
+#include <MacTypes.h>
+
+StringPtr c2p_strcpy(StringPtr pstr, const char* cstr);
+char* p2c_strcpy(char* cstr, const StringPtr pstr);
+char* p2c_strdup(StringPtr pstr);
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp
new file mode 100644
index 00000000..49f061d9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp
@@ -0,0 +1,417 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpidl.cpp
+
+ Metrowerks Codewarrior IDL plugin.
+
+ by Patrick C. Beard.
+ */
+
+/* standard headers */
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <new.h>
+#include <setjmp.h>
+
+/* system headers */
+#include <Files.h>
+#include <Errors.h>
+#include <Strings.h>
+
+#include "FullPath.h"
+#include "MoreFilesExtras.h"
+
+/* compiler headers */
+#include "DropInCompilerLinker.h"
+#include "CompilerMapping.h"
+#include "CWPluginErrors.h"
+
+/* local headers. */
+#include "mac_xpidl.h"
+#include "mac_console.h"
+#include "mac_strings.h"
+#include "mac_xpidl_panel.h"
+
+/* prototypes of local functions */
+static CWResult Compile(CWPluginContext context);
+static CWResult Disassemble(CWPluginContext context);
+static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file);
+
+/* external variables */
+extern jmp_buf exit_jump;
+extern int exit_status;
+
+/* global variables */
+CWPluginContext gPluginContext;
+
+/* local variables */
+static CWFileSpec gSourceFile;
+static char* gSourcePath = NULL;
+static CWFileSpec gOutputFile;
+
+extern "C" {
+pascal short xpidl_compiler(CWPluginContext context);
+int xpidl_main(int argc, char* argv[]);
+int xptdump_main(int argc, char* argv[]);
+
+FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
+}
+
+pascal short xpidl_compiler(CWPluginContext context)
+{
+ long request;
+ if (CWGetPluginRequest(context, &request) != cwNoErr)
+ return cwErrRequestFailed;
+
+ gPluginContext = context;
+ short result = cwNoErr;
+
+ /* dispatch on compiler request */
+ switch (request) {
+ case reqInitCompiler:
+ /* compiler has just been loaded into memory */
+ break;
+
+ case reqTermCompiler:
+ /* compiler is about to be unloaded from memory */
+ break;
+
+ case reqCompile:
+ /* compile a source file */
+ result = Compile(context);
+ break;
+
+ case reqCompDisassemble:
+ /* disassemble a source file */
+ result = Disassemble(context);
+ break;
+
+ default:
+ result = cwErrRequestFailed;
+ break;
+ }
+
+ /* is this necessary? */
+ CWDonePluginRequest(context, result);
+
+ /* return result code */
+ return (result);
+}
+
+static char* full_path_to(const FSSpec& file)
+{
+ short len = 0;
+ Handle fullPath = NULL;
+ if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) {
+ char* path = new char[1 + len];
+ if (path != NULL) {
+ BlockMoveData(*fullPath, path, len);
+ path[len] = '\0';
+ }
+ DisposeHandle(fullPath);
+ return path;
+ }
+ return NULL;
+}
+
+static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings)
+{
+ CWMemHandle settingsHand;
+ CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ XPIDLSettings* settingsPtr = NULL;
+ err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ settings = *settingsPtr;
+
+ err = CWUnlockMemHandle(context, settingsHand);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ return noErr;
+}
+
+static CWResult Compile(CWPluginContext context)
+{
+ CWResult err = CWGetMainFileSpec(context, &gSourceFile);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ long fileNum;
+ err = CWGetMainFileNumber(context, &fileNum);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ // get the name of the source file to compile.
+ gSourcePath = p2c_strdup(gSourceFile.name);
+ if (gSourcePath == NULL)
+ return cwErrOutOfMemory;
+
+ // build an argument list and call the compiler.
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeHeader, false, false };
+ GetSettings(context, settings);
+
+#if 0
+ // if generating .xpt files, let the IDE tell us where to put the output file.
+ // otherwise, put them in the project's output directory.
+ if (settings.mode == kXPIDLModeTypelib)
+ err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
+ else
+ err = CWGetOutputFileDirectory(gPluginContext, &gOutputFile);
+#else
+ // always generate the output file into the project target's data directory.
+ err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
+#endif
+ if (!CWSUCCESS(err))
+ return (err);
+
+ int argc = 3;
+ char* modes[] = { "header", "java", "typelib", "doc" };
+ char* argv[] = { "xpidl", "-m", modes[settings.mode - 1], NULL, NULL, NULL, NULL, };
+ if (settings.warnings) argv[argc++] = "-w";
+ if (settings.verbose) argv[argc++] = "-v";
+ argv[argc++] = gSourcePath;
+
+ if (setjmp(exit_jump) == 0) {
+ if (xpidl_main(argc, argv) != 0)
+ err = cwErrRequestFailed;
+ } else {
+ // evidently the good old exit function got called.
+ if (exit_status != 0)
+ err = cwErrRequestFailed;
+ }
+
+ // if the compilation succeeded, tell CodeWarrior about the output file.
+ // this ensures several things: 1. if the output file is deleted by the user,
+ // then the IDE will know to recompile it, which is good for dirty builds,
+ // where the output files may be hand deleted; 2. if the user elects to remove
+ // objects, the output files are deleted. Thanks to robv@metrowerks.com for
+ // pointing this new CWPro4 API out.
+ if (err == cwNoErr) {
+ CWObjectData objectData;
+ BlockZero(&objectData, sizeof(objectData));
+
+ // for fun, show how large the output file is in the data area.
+ long dataSize, rsrcSize;
+ if (FSpGetFileSize(&gOutputFile, &dataSize, &rsrcSize) == noErr)
+ objectData.idatasize = dataSize;
+
+ // tell the IDE that this file was generated by the compiler.
+ objectData.objectfile = &gOutputFile;
+
+ err = CWStoreObjectData(context, fileNum, &objectData);
+ } else {
+ // an error occured, delete the output file, which might be a partial file.
+ if (gOutputFile.name[0] != 0) {
+ ::FSpDelete(&gOutputFile);
+ }
+ }
+
+ delete[] gSourcePath;
+ gSourcePath = NULL;
+
+ return (err);
+}
+
+static CWResult Disassemble(CWPluginContext context)
+{
+ // the disassembly code has moved to the linker.
+ return noErr;
+}
+
+static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file)
+{
+ /* prefill the CWFileInfo struct */
+ CWFileInfo fileinfo;
+ BlockZero(&fileinfo, sizeof(fileinfo));
+ // memset(&fileinfo, 0, sizeof(fileinfo));
+ fileinfo.fullsearch = true;
+ fileinfo.suppressload = true;
+ fileinfo.dependencyType = cwNormalDependency;
+ fileinfo.isdependentoffile = kCurrentCompiledFile;
+
+ /* locate the file name using the project's access paths */
+ CWResult err = CWFindAndLoadFile(context, filename, &fileinfo);
+ if (err == cwNoErr) {
+ file = fileinfo.filespec;
+ } else if (err == cwErrFileNotFound) {
+ char errmsg[200];
+ sprintf(errmsg, "Can't locate file \"%s\".", filename);
+ CWResult callbackResult = CWReportMessage(context, 0, errmsg, 0, messagetypeError, 0);
+ }
+
+ return (err);
+}
+
+/**
+ * Substitute for standard fopen, treats certain filenames specially,
+ * and also considers the mode argument. If a file is being opened
+ * for reading, the file is assumed to be locateable using CodeWarrior's
+ * standard access paths. If it's for writing, the file is opened in
+ * the current project's output directory.
+ */
+FILE* std::fopen(const char* filename, const char *mode)
+{
+ FSSpec filespec;
+ CWResult err = noErr;
+ do {
+ if (filename == gSourcePath || strcmp(filename, gSourcePath) == 0) {
+ // opening the main source file.
+ filespec = gSourceFile;
+ } else if (mode[0] == 'w') {
+ // if an output file, open it in the current compilation's output directory.
+ c2p_strcpy(filespec.name, filename);
+ filespec.vRefNum = gOutputFile.vRefNum;
+ filespec.parID = gOutputFile.parID;
+ c2p_strcpy(gOutputFile.name, filename);
+ } else {
+ // an input file, use CodeWarrior's search paths to find the named source file.
+ err = LocateFile(gPluginContext, filename, filespec);
+ }
+ } while (0);
+ // if all went well, we have a file to open.
+ return (err == noErr ? FSp_fopen(&filespec, mode) : NULL);
+}
+
+/**
+ * Returns the length of a file, assuming it is always located in the
+ * project's output directory.
+ */
+size_t mac_get_file_length(const char* filename)
+{
+ long dataSize= 0, rsrcSize = 0;
+ FSSpec filespec;
+ if (CWGetOutputFileDirectory(gPluginContext, &filespec) != noErr)
+ return 0;
+ c2p_strcpy(filespec.name, filename);
+ if (FSpGetFileSize(&filespec, &dataSize, &rsrcSize) != noErr)
+ return 0;
+ return dataSize;
+}
+
+void mac_warning(const char* warning_message)
+{
+ CWReportMessage(gPluginContext, 0, warning_message, 0, messagetypeWarning, 0);
+}
+
+void mac_error(const char* error_message)
+{
+ CWReportMessage(gPluginContext, 0, error_message, 0, messagetypeError, 0);
+}
+
+// plugin compiler exports.
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export on
+#endif
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize)
+{
+ static const DropInFlags sFlags = {
+ kCurrentDropInFlagsVersion,
+ CWDROPINCOMPILERTYPE,
+ DROPINCOMPILERLINKERAPIVERSION,
+ (kGeneratescode | /* kCandisassemble | */ kCompMultiTargAware | kCompAlwaysReload),
+ Lang_MISC,
+ DROPINCOMPILERLINKERAPIVERSION
+ };
+
+ *flags = &sFlags;
+ *flagsSize = sizeof(sFlags);
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName)
+{
+ static const char* sDropInName = "xpidl";
+
+ *dropinName = sDropInName;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName)
+{
+ static const char* sDisplayName = "xpidl";
+
+ *displayName = sDisplayName;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList)
+{
+ static const char* sPanelName = kXPIDLPanelName;
+ static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName };
+
+ *panelList = &sPanelList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList)
+{
+ static CWDataType sCPU = '****';
+ static CWDataType sOS = '****';
+ static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS };
+
+ *targetList = &sTargetList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList)
+{
+ static CWExtensionMapping sExtension = { 'TEXT', ".idl", 0 };
+ static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension };
+
+ *defaultMappingList = &sExtensionMapList;
+
+ return cwNoErr;
+}
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export off
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h
new file mode 100644
index 00000000..bb1c5048
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h
@@ -0,0 +1,25 @@
+/*
+ mac_xpidl.h
+
+ prototypes for the Mac CodeWarrior plugin version of xpidl.
+
+ by Patrick C. Beard.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _STDIO_H
+#include <stdio.h>
+#endif
+
+size_t mac_get_file_length(const char* filename);
+void mac_warning(const char* warning_message);
+void mac_error(const char* error_message);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp
new file mode 100644
index 00000000..b046071d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp
@@ -0,0 +1,695 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpidl_panel.cpp
+ */
+
+#define CW_STRICT_DIALOGS 1
+
+/* standard headers */
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+/* system headers */
+#include <AERegistry.h>
+#include <Drag.h>
+#include <Palettes.h>
+#include <Resources.h>
+#include <Scrap.h>
+#include <TextUtils.h>
+#include <Sound.h>
+
+/* compiler headers */
+#include <DropInPanel.h>
+
+/* project headers */
+#include "mac_xpidl_panel.h"
+
+enum {
+ kFactoryPrefsID = 128,
+ kCW7ItemListID = 128,
+ kCW8ItemListID = 129,
+
+ kXPIDLModeItem = 1,
+ kXPIDLWarningsItem,
+ kXPIDLVerboseItem,
+
+ kXPTLinkerOutputItem = 4
+};
+
+
+/* local variables */
+static RgnHandle sDragRgn;
+static Boolean sHighlightOn;
+
+
+/* prototypes of local functions */
+static short InitDialog(PanelParameterBlock *pb);
+static void TermDialog(PanelParameterBlock *pb);
+static void PutData(PanelParameterBlock *pb, Handle options);
+static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy);
+static void ByteSwapData(XPIDLSettingsHandle options);
+static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit);
+static void ItemHit(PanelParameterBlock *pb);
+static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset);
+static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings);
+static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings);
+static short GetFactory(Handle settings);
+static short UpdatePref(Handle settings);
+static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2);
+static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2);
+static void OutlineRect(const Rect* focusRect, Boolean outlineOn);
+static OSErr DragEnter(PanelParameterBlock *pb);
+static void DragWithin(PanelParameterBlock *pb);
+static void DragExit(PanelParameterBlock *pb);
+static void DragDrop(PanelParameterBlock *pb);
+
+extern "C" {
+
+pascal short xpidl_panel(PanelParameterBlock *pb);
+
+}
+
+/*
+ * main - entry-point for Drop-In Preferences Panel
+ *
+ */
+
+pascal short xpidl_panel(PanelParameterBlock *pb)
+{
+ short result;
+
+ result = noErr;
+
+ switch (pb->request)
+ {
+ case reqInitPanel:
+ /* panel has just been loaded into memory */
+ break;
+
+ case reqTermPanel:
+ /* panel is about to be unloaded from memory */
+ break;
+
+ case reqFirstLoad:
+ /* first time panel was loaded. */
+ break;
+
+ case reqInitDialog:
+ /* hook our dialog item list into the preferences dialog */
+ result = InitDialog(pb);
+ break;
+
+ case reqTermDialog:
+ /* unhook our dialog item list from the preferences dialog */
+ TermDialog(pb);
+ break;
+
+ case reqPutData:
+ /* put the data in the given handle into our dialog items */
+ PutData(pb, pb->currentPrefs);
+ break;
+
+ case reqGetData:
+ /* fill in the given handle with our dialog items */
+ result = GetData(pb, pb->currentPrefs, true);
+ break;
+
+ case reqByteSwapData:
+ /* byte swap the data in the handle */
+ ByteSwapData((XPIDLSettingsHandle)pb->currentPrefs);
+ break;
+
+ case reqFilter:
+ /* filter an event in the dialog */
+ result = Filter(pb, pb->event, &pb->itemHit);
+ break;
+
+ case reqItemHit:
+ /* handle a hit on one of our dialog items */
+ ItemHit(pb);
+ break;
+
+ case reqDrawCustomItem:
+ /* handle a request to draw one of our user items (CW/8 and later) */
+ break;
+
+ case reqActivateItem:
+ break;
+
+ case reqDeactivateItem:
+ break;
+
+ case reqHandleKey:
+ break;
+
+ case reqHandleClick:
+ break;
+
+ case reqFindStatus:
+ break;
+
+ case reqObeyCommand:
+ break;
+
+ case reqAEGetPref:
+ /* return one item in the given handle as an Apple Event descriptor */
+ result = GetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
+ break;
+
+ case reqAESetPref:
+ /* change one item in the given handle according to the given Apple Event descriptor */
+ result = SetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
+ break;
+
+ case reqValidate:
+ /* determine if we need to reset paths, recompile, or relink */
+ Validate(pb->originalPrefs, pb->currentPrefs, &pb->recompile, &pb->relink, &pb->reset);
+ break;
+
+ case reqGetFactory:
+ /* return our factory settings */
+ result = GetFactory(pb->factoryPrefs);
+ break;
+
+ case reqUpdatePref:
+ /* update the given handle to use the current format for our prefs data */
+ result = UpdatePref(pb->currentPrefs);
+ break;
+
+ case reqDragEnter:
+ /* determine if we can accept the drag and, if so, start tracking */
+ result = DragEnter(pb);
+ break;
+
+ case reqDragWithin:
+ /* continue tracking */
+ DragWithin(pb);
+ break;
+
+ case reqDragExit:
+ /* stop tracking */
+ DragExit(pb);
+ break;
+
+ case reqDragDrop:
+ /* the user has dropped in our panel */
+ DragDrop(pb);
+ break;
+
+ default:
+ result = paramErr;
+ break;
+ }
+
+ return (result);
+}
+
+/*
+ * InitDialog - initialize Dialog Box items for this panel
+ *
+ */
+
+static short InitDialog(PanelParameterBlock *pb)
+{
+ OSErr err;
+
+ // The library function will call the IDE to append the dialog items
+ // if possible; else it will call AppendDITL itself. This way, you
+ // don't have to worry about it.
+
+ err = CWPanlAppendItems(pb, kCW8ItemListID);
+ if (err != noErr)
+ return (err);
+
+ sDragRgn = NewRgn();
+
+ return (err);
+}
+
+/*
+ * TermDialog - destroy Dialog Box items for this panel
+ *
+ */
+
+static void TermDialog(PanelParameterBlock *pb)
+{
+ DisposeRgn(sDragRgn);
+}
+
+inline Boolean hasLinkerOutput(short mode)
+{
+ return (mode == kXPIDLModeHeader || mode == kXPIDLModeTypelib);
+}
+
+/*
+ * PutData - copy the options data from the handle to the screen
+ *
+ */
+
+static void PutData(PanelParameterBlock *pb, Handle options)
+{
+ // make sure the options are the right size.
+ UpdatePref(options);
+
+ XPIDLSettings prefsData = **(XPIDLSettingsHandle) options;
+
+ CWPanlSetItemValue(pb, kXPIDLModeItem, prefsData.mode);
+ CWPanlSetItemValue(pb, kXPIDLWarningsItem, prefsData.warnings);
+ CWPanlSetItemValue(pb, kXPIDLVerboseItem, prefsData.verbose);
+
+ CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(prefsData.mode));
+ CWPanlSetItemText(pb, kXPTLinkerOutputItem, prefsData.output);
+}
+
+/*
+ * GetData - copy the options data from screen to the handle
+ *
+ */
+
+static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy)
+{
+ XPIDLSettings prefsData = **(XPIDLSettingsHandle) options;
+ long mode, warnings, verbose;
+
+ CWPanlGetItemValue(pb, kXPIDLModeItem, &mode);
+ CWPanlGetItemValue(pb, kXPIDLWarningsItem, &warnings);
+ CWPanlGetItemValue(pb, kXPIDLVerboseItem, &verbose);
+
+ prefsData.mode = (short) mode;
+ prefsData.warnings = (Boolean) warnings;
+ prefsData.verbose = (Boolean) verbose;
+
+ CWPanlGetItemText(pb, kXPTLinkerOutputItem, prefsData.output, sizeof(Str32));
+
+ ** (XPIDLSettingsHandle) options = prefsData;
+
+ return (noErr);
+}
+
+static void ByteSwapShort(short* x)
+{
+ union {
+ short s;
+ char c[2];
+ } from,to;
+
+ from.s=*x;
+ to.c[0]=from.c[1];
+ to.c[1]=from.c[0];
+ *x = to.s;
+}
+
+/*
+ * ByteSwapData - byte-swap the options data
+ *
+ */
+
+static void ByteSwapData(XPIDLSettingsHandle options)
+{
+ ByteSwapShort(&(**options).version);
+ ByteSwapShort(&(**options).mode);
+}
+
+/*
+ * Filter - filter an event for the Preferences panel
+ *
+ */
+static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit)
+{
+#pragma unused(pb, event, itemHit)
+
+ return (noErr);
+}
+
+/*
+ * ItemHit - handle an itemHit in a Preferences panel
+ *
+ */
+
+static void ItemHit(PanelParameterBlock *pb)
+{
+ short theItem = pb->itemHit - pb->baseItems;
+ long oldValue;
+
+ switch (theItem) {
+ case kXPIDLModeItem:
+ CWPanlGetItemValue(pb, theItem, &oldValue);
+ CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(oldValue));
+ break;
+
+ case kXPIDLWarningsItem:
+ case kXPIDLVerboseItem:
+ CWPanlGetItemValue(pb, theItem, &oldValue);
+ break;
+ }
+
+ GetData(pb, pb->currentPrefs, false);
+
+ pb->canRevert = !ComparePrefs(pb->originalPrefs, pb->currentPrefs);
+ pb->canFactory = !ComparePrefs(pb->factoryPrefs, pb->currentPrefs);
+}
+
+/*
+ * Validate - check if panel's changes require a recompile or relink
+ *
+ */
+
+static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset)
+{
+#pragma unused(original, current)
+ XPIDLSettings& origSettings = **(XPIDLSettingsHandle) original;
+ XPIDLSettings& currentSettings = **(XPIDLSettingsHandle) current;
+
+ *recompile = currentSettings.mode != origSettings.mode;
+ *relink = *recompile && hasLinkerOutput(currentSettings.mode);
+ *reset = false;
+}
+
+/*
+ * GetPref - get a specified Preference setting for an AppleEvent request
+ *
+ */
+static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings)
+{
+#if 0
+ XPIDLSettings prefsData = ** (XPIDLSettingsHandle) settings;
+ DescType anEnum;
+ OSErr err;
+
+ switch (keyword) {
+ case prefsLN_GenerateSymFile:
+ err = AECreateDesc(typeBoolean, &prefsData.linksym, sizeof(Boolean), prefsDesc);
+ break;
+
+ case prefsPR_ProjectType:
+ switch (prefsData.projtype)
+ {
+ case kProjTypeApplication: anEnum = enum_Project_Application; break;
+ case kProjTypeLibrary: anEnum = enum_Project_Library; break;
+ case kProjTypeSharedLib: anEnum = enum_Project_SharedLibrary; break;
+ case kProjTypeCodeResource: anEnum = enum_Project_CodeResource; break;
+ case kProjTypeMPWTool: anEnum = enum_Project_MPWTool; break;
+ default: return (paramErr);
+ }
+ err = AECreateDesc(typeEnumeration, &anEnum, sizeof(anEnum), prefsDesc);
+ break;
+
+ case prefsPR_FileName:
+ err = AECreateDesc(typeChar, prefsData.outfile+1, StrLength(prefsData.outfile), prefsDesc);
+ break;
+
+ default:
+ err = errAECantHandleClass;
+ break;
+ }
+
+ return (err);
+#else
+ return (errAECantHandleClass);
+#endif
+}
+
+/*
+ * SetPref - set a specified Preference setting from an AppleEvent request
+ *
+ */
+
+static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings)
+{
+#if 0
+ XPIDLSettings prefsData = ** (XPIDLSettingsHandle) settings;
+ AEDesc toDesc = { typeNull, NULL };
+ OSErr err = noErr;
+ Handle dataHand;
+ Size textLength;
+ DescType anEnum;
+
+ switch (keyword)
+ {
+ case prefsLN_GenerateSymFile:
+ if (prefsDesc->descriptorType == typeBoolean)
+ {
+ dataHand = prefsDesc->dataHandle;
+ }
+ else
+ {
+ err = AECoerceDesc(prefsDesc, typeBoolean, &toDesc);
+ if (err == noErr)
+ dataHand = toDesc.dataHandle;
+ }
+ if (err == noErr)
+ {
+ prefsData.linksym = ** (Boolean **) dataHand;
+ }
+ break;
+
+ case prefsPR_ProjectType:
+ if (prefsDesc->descriptorType != typeEnumeration)
+ {
+ err = errAETypeError;
+ break;
+ }
+
+ anEnum = ** (DescType **) prefsDesc->dataHandle;
+
+ switch (anEnum)
+ {
+ case enum_Project_Application: prefsData.projtype = kProjTypeApplication; break;
+ case enum_Project_Library: prefsData.projtype = kProjTypeLibrary; break;
+ case enum_Project_SharedLibrary: prefsData.projtype = kProjTypeSharedLib; break;
+ case enum_Project_CodeResource: prefsData.projtype = kProjTypeCodeResource; break;
+ case enum_Project_MPWTool: prefsData.projtype = kProjTypeMPWTool; break;
+ default: return (errAECoercionFail);
+ }
+ break;
+
+ case prefsPR_FileName:
+ if (prefsDesc->descriptorType == typeChar)
+ {
+ dataHand = prefsDesc->dataHandle;
+ }
+ else
+ {
+ err = AECoerceDesc(prefsDesc, typeChar, &toDesc);
+ if (err == noErr)
+ dataHand = toDesc.dataHandle;
+ }
+ if (err == noErr)
+ {
+ textLength = GetHandleSize(dataHand);
+ if (textLength > sizeof(prefsData.outfile) - 1)
+ textLength = sizeof(prefsData.outfile) - 1;
+ BlockMoveData(*dataHand, prefsData.outfile+1, textLength);
+ prefsData.outfile[0] = textLength;
+ }
+ break;
+
+ default:
+ err = errAECantHandleClass;
+ break;
+ }
+
+ if (err == noErr)
+ {
+ ** (XPIDLSettingsHandle) settings = prefsData;
+ }
+
+ AEDisposeDesc(&toDesc);
+
+ return (err);
+#else
+ return (errAECantHandleClass);
+#endif
+}
+
+/*
+ * GetFactory - retrieve factory settings
+ *
+ */
+
+static short GetFactory(Handle settings)
+{
+ Handle factory;
+ Size size;
+ OSErr err;
+
+ factory = Get1Resource('pref', kFactoryPrefsID);
+ if (factory == NULL) {
+ err = ResError();
+ if (err == noErr)
+ err = resNotFound;
+ return (err);
+ }
+
+ size = GetHandleSize(factory);
+ SetHandleSize(settings, size);
+ err = MemError();
+
+ if (err == noErr) {
+ BlockMoveData(*factory, *settings, size);
+ }
+
+ return (err);
+}
+
+/*
+ * UpdatePref - "upgrade" a pref to the current version
+ */
+static short UpdatePref(Handle settings)
+{
+ if (GetHandleSize(settings) != sizeof(XPIDLSettings))
+ GetFactory(settings);
+
+ return (noErr);
+}
+
+/*
+ * ComparePrefs
+ *
+ */
+static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2)
+{
+ XPIDLSettings& prefs1 = **(XPIDLSettingsHandle) prefsHand1;
+ XPIDLSettings& prefs2 = **(XPIDLSettingsHandle) prefsHand2;
+
+ return ((prefs1.mode == prefs2.mode) &&
+ (prefs1.warnings == prefs2.warnings) &&
+ (prefs1.verbose == prefs2.verbose) &&
+ (EqualString(prefs1.output, prefs2.output, true, true)));
+}
+
+static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2)
+{
+ return ((prefs1.mode == prefs2.mode) &&
+ (prefs1.warnings == prefs2.warnings) &&
+ (prefs1.verbose == prefs2.verbose) &&
+ (EqualString(prefs1.output, prefs2.output, true, true)));
+}
+
+/*
+ * OutlineRect
+ *
+ */
+static void OutlineRect(const Rect* focusRect, Boolean outlineOn)
+{
+ ColorSpec savedForeColor, backColor;
+ PenState savedPen;
+
+ GetPenState(&savedPen);
+ PenNormal();
+
+ if (!outlineOn)
+ {
+ SaveFore(&savedForeColor);
+ SaveBack(&backColor);
+ RestoreFore(&backColor);
+ }
+
+ PenSize(2, 2);
+ FrameRect(focusRect);
+
+ SetPenState(&savedPen);
+
+ if (!outlineOn)
+ {
+ RestoreFore(&savedForeColor);
+ }
+}
+
+/*
+ * DragEnter
+ *
+ */
+static OSErr DragEnter(PanelParameterBlock *pb)
+{
+#if 0
+ short theItem = pb->itemHit - pb->baseItems;
+ unsigned short itemCount;
+ Rect itemRect;
+ OSErr err;
+#endif
+
+ /* Return paramErr if the user is on a item that can't be dropped on */
+ return (paramErr);
+}
+
+/*
+ * DragWithin
+ *
+ */
+static void DragWithin(PanelParameterBlock *pb)
+{
+#pragma unused(pb)
+
+ /* there's nothing to do */
+
+/// SysBreakStr("\preqDragWithin");
+}
+
+/*
+ * DragExit
+ *
+ */
+static void DragExit(PanelParameterBlock *pb)
+{
+ OSErr err;
+
+/// SysBreakStr("\preqDragExit");
+
+ if (sHighlightOn) {
+ err = HideDragHilite(pb->dragref);
+ if (err == noErr)
+ sHighlightOn = false;
+ }
+}
+
+/*
+ * DragDrop
+ *
+ */
+static void DragDrop(PanelParameterBlock *pb)
+{
+#if 0
+ Rect itemRect;
+#endif
+
+/// SysBreakStr("\preqDragDrop");
+
+ DragExit(pb);
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h
new file mode 100644
index 00000000..582b1055
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h
@@ -0,0 +1,106 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpidl_panel.h
+ */
+
+#pragma once
+
+#ifndef __MAC_XPIDL_PANEL__
+#define __MAC_XPIDL_PANEL__
+
+#ifndef __TYPES__
+#include <Types.h>
+#endif
+
+#pragma options align=mac68k
+
+/* this is the name of the panel, as shown in the Finder */
+#define kXPIDLPanelName "xpidl Settings"
+
+/*
+ * AppleScript dictionary info. As a rule of thumb, dropin panels should use the
+ * same terminology and numeric code in their 'aete' that the IDE uses if there
+ * is already a similar item in the IDE's 'aete'. That is the case here, so we
+ * merely duplicate applicable 68K Project and 68K Linker user terms below.
+ */
+
+enum {
+/* Symbolic Name Code AETE Terminology */
+ class_XPIDL = 'XIDL',
+
+ prefsPR_ProjectType = 'PR01', /* Project Type */
+ prefsPR_FileName = 'PR02', /* File Name */
+ prefsLN_GenerateSymFile = 'LN02', /* Generate SYM File */
+
+ /* enumeration for project type */
+ enumeration_ProjectType = 'PRPT',
+ enum_Project_Application = 'PRPA', /* application */
+ enum_Project_Library = 'PRPL', /* library */
+ enum_Project_SharedLibrary = 'PRPS', /* shared library */
+ enum_Project_CodeResource = 'PRPC', /* code resource */
+ enum_Project_MPWTool = 'PRPM' /* MPW tool */
+};
+
+enum {
+ kXPIDLModeHeader = 1,
+ kXPIDLModeJava,
+ kXPIDLModeTypelib,
+ kXPIDLModeDoc
+};
+
+/* This is the structure that is manipulated by the panel. The sample
+ * compiler & linker both "know" about this structure.
+ */
+
+enum {
+ kXPIDLSettingsVersion = 0x0100
+};
+
+struct XPIDLSettings {
+ short version; /* version # of settings data */
+ short mode; /* one of kXPIDLModeHeader, ... */
+ Boolean warnings; /* generate warnings. */
+ Boolean verbose; /* verbose mode */
+ Str32Field output; /* name of the output file */
+};
+
+typedef struct XPIDLSettings XPIDLSettings, **XPIDLSettingsHandle;
+
+#pragma options align=reset
+
+#endif /* __MAC_XPIDL_PANEL__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp
new file mode 100644
index 00000000..fe137959
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp
@@ -0,0 +1,546 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpt_linker.cpp
+
+ CodeWarrior plugin linker, links together multiple .xpt files.
+
+ by Patrick C. Beard.
+ */
+
+/* standard headers */
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+/* system headers */
+#include <Files.h>
+#include <Strings.h>
+#include <Aliases.h>
+#include <Resources.h>
+
+/* compiler headers */
+#include "DropInCompilerLinker.h"
+#include "CompilerMapping.h"
+#include "CWPluginErrors.h"
+
+/* project headers */
+#include "mac_xpidl_panel.h"
+#include "mac_console.h"
+#include "mac_strings.h"
+#include "FullPath.h"
+#include "MoreFilesExtras.h"
+
+/* use standard CodeWarrior debugger */
+#define kDebuggerCreator 'MWDB'
+
+/* prototypes of local functions */
+static CWResult Link(CWPluginContext context);
+static CWResult Disassemble(CWPluginContext context);
+static CWResult GetTargetInfo(CWPluginContext context);
+
+extern "C" {
+pascal short xpt_linker(CWPluginContext context);
+int xptlink_main(int argc, char* argv[]);
+int xptdump_main(int argc, char* argv[]);
+
+FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
+size_t mac_get_file_length(const char* filename);
+}
+
+/* external variables */
+extern jmp_buf exit_jump;
+extern int exit_status;
+
+/* global variables */
+CWPluginContext gPluginContext;
+
+/* local variables */
+static CWFileSpec gOutputDirectory;
+static CWFileSpec gObjectCodeDirectory;
+
+/*
+ * xpt_linker - main entry-point for linker plugin
+ *
+ */
+pascal short xpt_linker(CWPluginContext context)
+{
+ long request;
+ if (CWGetPluginRequest(context, &request) != cwNoErr)
+ return cwErrRequestFailed;
+
+ gPluginContext = context;
+ short result = cwNoErr;
+
+ /* dispatch on linker request */
+ switch (request) {
+ case reqInitLinker:
+ /* linker has just been loaded into memory */
+ break;
+
+ case reqTermLinker:
+ /* linker is about to be unloaded from memory */
+ break;
+
+ case reqLink:
+ /* build the final executable */
+ result = Link(context);
+ break;
+
+ case reqDisassemble:
+ /* disassemble object code for a given project file */
+ result = Disassemble(context);
+ break;
+
+ case reqTargetInfo:
+ /* return info describing target characteristics */
+ result = GetTargetInfo(context);
+ break;
+
+ default:
+ result = cwErrRequestFailed;
+ break;
+ }
+
+ result = CWDonePluginRequest(context, result);
+
+ /* return result code */
+ return result;
+}
+
+static char* full_path_to(const FSSpec& file)
+{
+ short len = 0;
+ Handle fullPath = NULL;
+ if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) {
+ char* path = new char[1 + len];
+ if (path != NULL) {
+ BlockMoveData(*fullPath, path, len);
+ path[len] = '\0';
+ }
+ DisposeHandle(fullPath);
+ return path;
+ }
+ return NULL;
+}
+
+/**
+ * Provides the full path name to a given directory.
+ */
+static char* full_path_to(short vRefNum, long dirID)
+{
+ long parID;
+ if (GetParentID(vRefNum, dirID, NULL, &parID) == noErr) {
+ FSSpec dirSpec = { vRefNum, parID };
+ if (GetDirName(vRefNum, dirID, dirSpec.name) == noErr) {
+ return full_path_to(dirSpec);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Returns the length of a file, assuming it is always located in the
+ * project's object code directory.
+ */
+size_t mac_get_file_length(const char* filename)
+{
+ FSSpec fileSpec = { gObjectCodeDirectory.vRefNum, gObjectCodeDirectory.parID };
+ c2p_strcpy(fileSpec.name, filename);
+ long dataSize, rsrcSize;
+ if (FSpGetFileSize(&fileSpec, &dataSize, &rsrcSize) != noErr)
+ dataSize = 0;
+ return dataSize;
+}
+
+/**
+ * replaces standard fopen -- opens files for writing in the project's output directory,
+ * and files for reading in the object code directory.
+ */
+FILE* std::fopen(const char* filename, const char *mode)
+{
+ CWFileSpec& fileDir = (mode[0] == 'r' ? gObjectCodeDirectory : gOutputDirectory);
+ FSSpec fileSpec = { fileDir.vRefNum, fileDir.parID };
+ c2p_strcpy(fileSpec.name, filename);
+ return FSp_fopen(&fileSpec, mode);
+}
+
+static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings)
+{
+ CWMemHandle settingsHand;
+ CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand);
+ if (!CWSUCCESS(err))
+ return err;
+
+ XPIDLSettings* settingsPtr = NULL;
+ err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr);
+ if (!CWSUCCESS(err))
+ return err;
+
+ settings = *settingsPtr;
+
+ err = CWUnlockMemHandle(context, settingsHand);
+ if (!CWSUCCESS(err))
+ return err;
+
+ return cwNoErr;
+}
+
+static CWResult LinkHeaders(CWPluginContext context, XPIDLSettings& settings)
+{
+ // find out how many files there are to link.
+ long fileCount = 0;
+ CWResult err = CWGetProjectFileCount(context, &fileCount);
+ if (err != cwNoErr || fileCount == 0)
+ return err;
+
+ // get the output directory.
+ FSSpec outputDir;
+ err = CWGetOutputFileDirectory(context, &outputDir);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // enumerate all of the output header files, and make aliases to them in
+ // the output directory.
+ for (long index = 0; (err == cwNoErr) && (index < fileCount); index++) {
+ // get the name of each output file.
+ CWFileSpec outputFile;
+ err = CWGetStoredObjectFileSpec(context, index, &outputFile);
+ if (err == cwNoErr) {
+ FInfo info;
+ err = FSpGetFInfo(&outputFile, &info);
+
+ FSSpec aliasFile = { outputDir.vRefNum, outputDir.parID };
+ BlockMoveData(outputFile.name, aliasFile.name, 1 + outputFile.name[0]);
+
+ AliasHandle alias = NULL;
+ if (NewAliasMinimal(&outputFile, &alias) == noErr) {
+ // recreate the alias file from scratch.
+ FSpDelete(&aliasFile);
+ FSpCreateResFile(&aliasFile, info.fdCreator, info.fdType, smRoman);
+ short refNum = FSpOpenResFile(&aliasFile, fsRdWrPerm);
+ if (refNum != -1) {
+ UseResFile(refNum);
+ AddResource(Handle(alias), rAliasType, 0, aliasFile.name);
+ ReleaseResource(Handle(alias));
+ UpdateResFile(refNum);
+ CloseResFile(refNum);
+ }
+ // finally, mark the newly created file as an alias file.
+ FSpGetFInfo(&aliasFile, &info);
+ info.fdFlags |= kIsAlias;
+ FSpSetFInfo(&aliasFile, &info);
+ }
+ }
+ }
+
+ // create the target file in the output directory.
+ BlockMoveData(settings.output, outputDir.name, 1 + settings.output[0]);
+ FILE* outputFile = FSp_fopen(&outputDir, "w");
+ if (outputFile != NULL) fclose(outputFile);
+
+ return err;
+}
+
+static CWResult LinkTypeLib(CWPluginContext context, XPIDLSettings& settings)
+{
+ // find out how many files there are to link.
+ long fileCount = 0;
+ CWResult err = CWGetProjectFileCount(context, &fileCount);
+ if (err != cwNoErr || fileCount == 0)
+ return err;
+
+ // assemble the argument list.
+ // { "xpt_link", outputFile, inputFile1, ..., inputFileN, NULL }
+ char** argv = new char*[2 + fileCount + 1];
+ int argc = 0;
+ argv[argc++] = "xpt_link";
+
+ // get the output directory.
+ err = CWGetOutputFileDirectory(context, &gOutputDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // get the object code directory.
+ err = CWGetStoredObjectFileSpec(context, 0, &gObjectCodeDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // push the output file name.
+ if ((argv[argc++] = p2c_strdup(settings.output)) == NULL)
+ return cwErrOutOfMemory;
+
+ for (long index = 0; (err == cwNoErr) && (index < fileCount); index++) {
+ // get the name of each output file.
+ CWFileSpec outputFile;
+ err = CWGetStoredObjectFileSpec(context, index, &outputFile);
+ if (err == cwNoErr) {
+ if ((argv[argc++] = p2c_strdup(outputFile.name)) == NULL) {
+ err = cwErrOutOfMemory;
+ break;
+ }
+ }
+ }
+
+ if (err != cwNoErr)
+ return err;
+
+ // trap calls to exit, which longjmp back to here.
+ if (setjmp(exit_jump) == 0) {
+ if (xptlink_main(argc, argv) != 0)
+ err = cwErrRequestFailed;
+ } else {
+ // evidently the good old exit function got called.
+ if (exit_status != 0)
+ err = cwErrRequestFailed;
+ }
+
+ return err;
+}
+
+static CWResult Link(CWPluginContext context)
+{
+ // load the relevant prefs.
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false };
+ CWResult err = GetSettings(context, settings);
+ if (err != cwNoErr)
+ return err;
+
+ switch (settings.mode) {
+ case kXPIDLModeHeader:
+ return LinkHeaders(context, settings);
+ case kXPIDLModeTypelib:
+ return LinkTypeLib(context, settings);
+ default:
+ return cwNoErr;
+ }
+}
+
+static CWResult Disassemble(CWPluginContext context)
+{
+ CWResult err = noErr;
+
+ // cache the project's output directory.
+ err = CWGetOutputFileDirectory(gPluginContext, &gOutputDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ long fileNum;
+ err = CWGetMainFileNumber(context, &fileNum);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // get the output file's location from the stored object data.
+ err = CWGetStoredObjectFileSpec(context, fileNum, &gObjectCodeDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ char* outputName = p2c_strdup(gObjectCodeDirectory.name);
+ if (outputName == NULL)
+ return cwErrOutOfMemory;
+
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false };
+ GetSettings(context, settings);
+
+ // build an argument list and call xpt_dump.
+ int argc = 1;
+ char* argv[] = { "xpt_dump", NULL, NULL, NULL };
+ if (settings.verbose) argv[argc++] = "-v";
+ argv[argc++] = outputName;
+
+ // trap calls to exit, which longjmp back to here.
+ if (setjmp(exit_jump) == 0) {
+ if (xptdump_main(argc, argv) != 0)
+ err = cwErrRequestFailed;
+ } else {
+ // evidently the good old exit function got called.
+ if (exit_status != 0)
+ err = cwErrRequestFailed;
+ }
+
+ delete[] outputName;
+
+ if (err == noErr) {
+ // display the disassembly in its own fresh text window.
+ CWNewTextDocumentInfo info = {
+ NULL,
+ mac_console_handle,
+ false
+ };
+ CWResizeMemHandle(context, mac_console_handle, mac_console_count);
+ err = CWCreateNewTextDocument(context, &info);
+ }
+
+ return err;
+}
+
+static CWResult GetTargetInfo(CWPluginContext context)
+{
+ CWTargetInfo targ;
+ memset(&targ, 0, sizeof(targ));
+
+ CWResult err = CWGetOutputFileDirectory(context, &targ.outfile);
+ targ.outputType = linkOutputFile;
+ targ.symfile = targ.outfile; /* location of SYM file */
+ targ.linkType = exelinkageFlat;
+ targ.targetCPU = '****';
+ targ.targetOS = '****';
+
+ // load the relevant settings.
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false };
+ err = GetSettings(context, settings);
+ if (err != cwNoErr)
+ return err;
+
+#if CWPLUGIN_HOST == CWPLUGIN_HOST_MACOS
+ // tell the IDE about the output file.
+ targ.outfileCreator = 'MMCH';
+ targ.outfileType = 'CWIE';
+ targ.debuggerCreator = kDebuggerCreator; /* so IDE can locate our debugger */
+
+ BlockMoveData(settings.output, targ.outfile.name, 1 + settings.output[0]);
+ targ.symfile.name[0] = 0;
+#endif
+
+#if CWPLUGIN_HOST == CWPLUGIN_HOST_WIN32
+ targ.debugHelperIsRegKey = true;
+ *(long*)targ.debugHelperName = kDebuggerCreator;
+ targ.debugHelperName[4] = 0;
+ strcat(targ.outfile.path, "\\");
+ strcat(targ.outfile.path, prefsData.outfile);
+ strcpy(targ.symfile.path, targ.outfile.path);
+ strcat(targ.symfile.path, ".SYM");
+#endif
+
+ targ.runfile = targ.outfile;
+ targ.linkAgainstFile = targ.outfile;
+
+ /* we can only run applications */
+ // targ.canRun = (prefsData.projtype == kProjTypeApplication);
+
+ /* we can only debug if we have a SYM file */
+ // targ.canDebug = prefsData.linksym;
+
+ err = CWSetTargetInfo(context, &targ);
+
+ return err;
+}
+
+#if 0
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export on
+#endif
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize)
+{
+ static const DropInFlags sFlags = {
+ kCurrentDropInFlagsVersion,
+ CWDROPINLINKERTYPE,
+ DROPINCOMPILERLINKERAPIVERSION_7,
+ (linkMultiTargAware | linkAlwaysReload),
+ 0,
+ DROPINCOMPILERLINKERAPIVERSION
+ };
+
+ *flags = &sFlags;
+ *flagsSize = sizeof(sFlags);
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName)
+{
+ static const char* sDropInName = "xpt Linker";
+ *dropinName = sDropInName;
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName)
+{
+ static const char* sDisplayName = "xpt Linker";
+ *displayName = sDisplayName;
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList)
+{
+ // +++Turn this on when the sample panel has been converted!
+ static const char* sPanelName = kXPIDLPanelName;
+ static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName };
+
+ *panelList = &sPanelList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList)
+{
+ static CWDataType sCPU = '****';
+ static CWDataType sOS = '****';
+ static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS };
+
+ *targetList = &sTargetList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList)
+{
+ static CWExtensionMapping sExtension = { 'MMCH', ".xpt", 0 };
+ static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension };
+
+ *defaultMappingList = &sExtensionMapList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY (CWPlugin_GetFamilyList)(const CWFamilyList** familyList)
+{
+ static CWFamily sFamily = { 'XIDL', "xpidl Settings" };
+ static CWFamilyList sFamilyList = { kCurrentCWFamilyListVersion, 0, &sFamily };
+
+ *familyList = &sFamilyList;
+
+ return cwNoErr;
+}
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export off
+#endif
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc
new file mode 100644
index 00000000..c5777088
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc
new file mode 100644
index 00000000..6737d356
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c
new file mode 100644
index 00000000..e1a7c58d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c
@@ -0,0 +1,275 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Main xpidl program entry point.
+ */
+
+#include "xpidl.h"
+
+static ModeData modes[] = {
+ {"header", "Generate C++ header", "h", xpidl_header_dispatch},
+ {"typelib", "Generate XPConnect typelib", "xpt", xpidl_typelib_dispatch},
+ {"doc", "Generate HTML documentation", "html", xpidl_doc_dispatch},
+ {"java", "Generate Java interface", "java", xpidl_java_dispatch},
+ {0, 0, 0, 0}
+};
+
+static ModeData *
+FindMode(char *mode)
+{
+ int i;
+ for (i = 0; modes[i].mode; i++) {
+ if (!strcmp(modes[i].mode, mode))
+ return &modes[i];
+ }
+ return NULL;
+}
+
+gboolean enable_debug = FALSE;
+gboolean enable_warnings = FALSE;
+gboolean verbose_mode = FALSE;
+gboolean emit_typelib_annotations = FALSE;
+gboolean explicit_output_filename = FALSE;
+
+/* The following globals are explained in xpt_struct.h */
+PRUint8 major_version = XPT_MAJOR_VERSION;
+PRUint8 minor_version = XPT_MINOR_VERSION;
+
+static char xpidl_usage_str[] =
+"Usage: %s -m mode [-w] [-v] [-t version number]\n"
+" [-I path] [-o basename | -e filename.ext] filename.idl\n"
+" -a emit annotations to typelib\n"
+" -w turn on warnings (recommended)\n"
+" -v verbose mode (NYI)\n"
+" -t create a typelib of a specific version number\n"
+" -I add entry to start of include path for ``#include \"nsIThing.idl\"''\n"
+" -o use basename (e.g. ``/tmp/nsIThing'') for output\n"
+" -e use explicit output filename\n"
+" -m specify output mode:\n";
+
+static void
+xpidl_usage(int argc, char *argv[])
+{
+ int i;
+ fprintf(stderr, xpidl_usage_str, argv[0]);
+ for (i = 0; modes[i].mode; i++) {
+ fprintf(stderr, " %-12s %-30s (.%s)\n", modes[i].mode,
+ modes[i].modeInfo, modes[i].suffix);
+ }
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+#define main xpidl_main
+int xpidl_main(int argc, char *argv[]);
+#endif
+
+int main(int argc, char *argv[])
+{
+ int i;
+ IncludePathEntry *inc, *inc_head, **inc_tail;
+ char *file_basename = NULL;
+ ModeData *mode = NULL;
+ gboolean create_old_typelib = FALSE;
+
+ /* turn this on for extra checking of our code */
+/* IDL_check_cast_enable(TRUE); */
+
+ inc_head = xpidl_malloc(sizeof *inc);
+#ifndef XP_MAC
+ inc_head->directory = ".";
+#else
+ inc_head->directory = "";
+#endif
+ inc_head->next = NULL;
+ inc_tail = &inc_head->next;
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-')
+ break;
+ switch (argv[i][1]) {
+ case '-':
+ argc++; /* pretend we didn't see this */
+ /* fall through */
+ case 0: /* - is a legal input filename (stdin) */
+ goto done_options;
+ case 'a':
+ emit_typelib_annotations = TRUE;
+ break;
+ case 'w':
+ enable_warnings = TRUE;
+ break;
+ case 'v':
+ verbose_mode = TRUE;
+ break;
+ case 't':
+ {
+ /* Parse for "-t version number" and store it into global boolean
+ * and string variables.
+ */
+ const gchar* typelib_version_string = NULL;
+
+ /*
+ * If -t is the last argument on the command line, we have a problem
+ */
+
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing version number after -t\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+
+ /* Do not allow more than one "-t" definition */
+ if (create_old_typelib) {
+ fprintf(stderr,
+ "ERROR: -t argument used twice. "
+ "Cannot specify more than one version\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+
+ /*
+ * Assume that the argument after "-t" is the version number string
+ * and search for it in our internal list of acceptable version
+ * numbers.
+ */
+ switch (XPT_ParseVersionString(argv[++i], &major_version,
+ &minor_version)) {
+ case XPT_VERSION_CURRENT:
+ break;
+ case XPT_VERSION_OLD:
+ create_old_typelib = TRUE;
+ break;
+ case XPT_VERSION_UNSUPPORTED:
+ fprintf(stderr, "ERROR: version \"%s\" not supported.\n",
+ argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ case XPT_VERSION_UNKNOWN:
+ default:
+ fprintf(stderr, "ERROR: version \"%s\" not recognised.\n",
+ argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ break;
+ }
+ case 'I':
+ if (argv[i][2] == '\0' && i == argc) {
+ fputs("ERROR: missing path after -I\n", stderr);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ inc = xpidl_malloc(sizeof *inc);
+ if (argv[i][2] == '\0') {
+ /* is it the -I foo form? */
+ inc->directory = argv[++i];
+ } else {
+ /* must be the -Ifoo form. Don't preincrement i. */
+ inc->directory = argv[i] + 2;
+ }
+#ifdef DEBUG_shaver_includes
+ fprintf(stderr, "adding %s to include path\n", inc->directory);
+#endif
+ inc->next = NULL;
+ *inc_tail = inc;
+ inc_tail = &inc->next;
+ break;
+ case 'o':
+ if (i == argc) {
+ fprintf(stderr, "ERROR: missing basename after -o\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ file_basename = argv[++i];
+ explicit_output_filename = FALSE;
+ break;
+ case 'e':
+ if (i == argc) {
+ fprintf(stderr, "ERROR: missing basename after -e\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ file_basename = argv[++i];
+ explicit_output_filename = TRUE;
+ break;
+ case 'm':
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing modename after -m\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ if (mode) {
+ fprintf(stderr,
+ "ERROR: must specify exactly one mode "
+ "(first \"%s\", now \"%s\")\n", mode->mode,
+ argv[i + 1]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ mode = FindMode(argv[++i]);
+ if (!mode) {
+ fprintf(stderr, "ERROR: unknown mode \"%s\"\n", argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "unknown option %s\n", argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ }
+ done_options:
+ if (!mode) {
+ fprintf(stderr, "ERROR: must specify output mode\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ if (argc != i + 1) {
+ fprintf(stderr, "ERROR: extra arguments after input file\n");
+ }
+
+ /*
+ * Don't try to process multiple files, given that we don't handle -o
+ * multiply.
+ */
+ if (xpidl_process_idl(argv[i], inc_head, file_basename, mode))
+ return 0;
+
+ return 1;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h
new file mode 100644
index 00000000..857bfdf8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h
@@ -0,0 +1,278 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Intramodule declarations.
+ */
+
+#ifndef __xpidl_h
+#define __xpidl_h
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <string.h> /* After glib.h to avoid warnings about shadowing 'index'. */
+
+#ifndef XP_MAC
+#include <libIDL/IDL.h>
+#else
+#include <IDL.h>
+#endif
+
+#include <xpt_struct.h>
+
+/*
+ * IDL_tree_warning bombs on libIDL version 6.5, and I don't want to not write
+ * warnings... so I define a versioned one here. Thanks to Mike Shaver for the
+ * this solution, which allows us to pass through varargs calls.
+ */
+#if !(LIBIDL_MAJOR_VERSION == 0 && LIBIDL_MINOR_VERSION == 6 && \
+ LIBIDL_MICRO_VERSION == 5) && !defined(DEBUG_shaver)
+/*
+ * This turns a varargs call to XPIDL_WARNING directly into a varargs
+ * call to IDL_tree_warning or xpidl_tree_warning as appropriate. The
+ * only tricky bit is that you must call XPIDL_WARNING with extra
+ * parens, e.g. XPIDL_WARNING((foo, bar, "sil"))
+ *
+ * Probably best removed when we leave 6.5. */
+#define XPIDL_WARNING(x) IDL_tree_warning x
+#else
+extern void xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...);
+#define XPIDL_WARNING(x) xpidl_tree_warning x
+#endif
+
+/*
+ * Internal operation flags.
+ */
+extern gboolean enable_debug;
+extern gboolean enable_warnings;
+extern gboolean verbose_mode;
+extern gboolean emit_typelib_annotations;
+extern gboolean explicit_output_filename;
+
+extern PRUint8 major_version;
+extern PRUint8 minor_version;
+
+typedef struct TreeState TreeState;
+
+/*
+ * A function to handle an IDL_tree type.
+ */
+typedef gboolean (*nodeHandler)(TreeState *);
+
+/*
+ * Struct containing functions to define the behavior of a given output mode.
+ */
+typedef struct backend {
+ nodeHandler *dispatch_table; /* nodeHandlers table, indexed by node type. */
+ nodeHandler emit_prolog; /* called at beginning of output generation. */
+ nodeHandler emit_epilog; /* called at end. */
+} backend;
+
+/* Function that produces a struct of output-generation functions */
+typedef backend *(*backendFactory)();
+
+extern backend *xpidl_header_dispatch(void);
+extern backend *xpidl_typelib_dispatch(void);
+extern backend *xpidl_doc_dispatch(void);
+extern backend *xpidl_java_dispatch(void);
+
+typedef struct ModeData {
+ char *mode;
+ char *modeInfo;
+ char *suffix;
+ backendFactory factory;
+} ModeData;
+
+typedef struct IncludePathEntry {
+ char *directory;
+ struct IncludePathEntry *next;
+} IncludePathEntry;
+
+struct TreeState {
+ FILE *file;
+ /* Maybe supplied by -o. Not related to (g_)basename from string.h or glib */
+ char *basename;
+ IDL_ns ns;
+ IDL_tree tree;
+ GSList *base_includes;
+ nodeHandler *dispatch;
+ void *priv; /* mode-private data */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ char *real_outname;
+#endif
+
+};
+
+/*
+ * Process an IDL file, generating InterfaceInfo, documentation and headers as
+ * appropriate.
+ */
+int
+xpidl_process_idl(char *filename, IncludePathEntry *include_path,
+ char *file_basename, ModeData *mode);
+
+/*
+ * Iterate over an IDLN_LIST -- why is this not part of libIDL?
+ */
+void
+xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data);
+
+/*
+ * Wrapper whines to stderr then exits after null return from malloc or strdup.
+ */
+void *
+xpidl_malloc(size_t nbytes);
+
+char *
+xpidl_strdup(const char *s);
+
+/*
+ * Return a newly allocated string to the start of the base filename of path.
+ * Free with g_free().
+ */
+char *
+xpidl_basename(const char * path);
+
+/*
+ * Process an XPIDL node and its kids, if any.
+ */
+gboolean
+xpidl_process_node(TreeState *state);
+
+/*
+ * Write a newline folllowed by an indented, one-line comment containing IDL
+ * source decompiled from state->tree.
+ */
+void
+xpidl_write_comment(TreeState *state, int indent);
+
+
+
+/*
+ * Functions for parsing and printing UUIDs.
+ */
+
+/*
+ * How large should the buffer supplied to xpidl_sprint_IID be?
+ */
+#define UUID_LENGTH 37
+
+/*
+ * Print an iid to into a supplied buffer; the buffer should be at least
+ * UUID_LENGTH bytes.
+ */
+gboolean
+xpidl_sprint_iid(nsID *iid, char iidbuf[]);
+
+/*
+ * Parse a uuid string into an nsID struct. We cannot link against libxpcom,
+ * so we re-implement nsID::Parse here.
+ */
+gboolean
+xpidl_parse_iid(nsID *id, const char *str);
+
+
+/* Try to common a little node-handling stuff. */
+
+/* is this node from an aggregate type (interface)? */
+#define UP_IS_AGGREGATE(node) \
+ (IDL_NODE_UP(node) && \
+ (IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_INTERFACE || \
+ IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_FORWARD_DCL))
+
+#define UP_IS_NATIVE(node) \
+ (IDL_NODE_UP(node) && \
+ IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_NATIVE)
+
+/* is this type output in the form "<foo> *"? */
+#define STARRED_TYPE(node) (IDL_NODE_TYPE(node) == IDLN_TYPE_STRING || \
+ IDL_NODE_TYPE(node) == IDLN_TYPE_WIDE_STRING || \
+ (IDL_NODE_TYPE(node) == IDLN_IDENT && \
+ UP_IS_AGGREGATE(node)))
+
+#define DIPPER_TYPE(node) \
+ (NULL != IDL_tree_property_get(node, "domstring") || \
+ NULL != IDL_tree_property_get(node, "utf8string") || \
+ NULL != IDL_tree_property_get(node, "cstring") || \
+ NULL != IDL_tree_property_get(node, "astring"))
+
+/*
+ * Find the underlying type of an identifier typedef. Returns NULL
+ * (and doesn't complain) on failure.
+ */
+IDL_tree /* IDL_TYPE_DCL */
+find_underlying_type(IDL_tree typedef_ident);
+
+/*
+ * Check that const declarations match their stated sign and are of the
+ * appropriate types.
+ */
+gboolean
+verify_const_declaration(IDL_tree const_tree);
+
+/*
+ * Check that scriptable attributes in scriptable interfaces actually are.
+ */
+gboolean
+verify_attribute_declaration(IDL_tree method_tree);
+
+/*
+ * Perform various validation checks on methods.
+ */
+gboolean
+verify_method_declaration(IDL_tree method_tree);
+
+/*
+ * Verifies the interface declaration
+ */
+gboolean
+verify_interface_declaration(IDL_tree method_tree);
+
+/*
+ * Verify that a native declaration has an associated C++ expression, i.e. that
+ * it's of the form native <idl-name>(<c++-name>)
+ */
+gboolean
+check_native(TreeState *state);
+
+void
+printlist(FILE *outfile, GSList *slist);
+
+#endif /* __xpidl_h */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c
new file mode 100644
index 00000000..d560e407
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c
@@ -0,0 +1,312 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xpidl.h"
+
+/*
+ * Generates documentation from javadoc-style comments in XPIDL files.
+ */
+
+static gboolean
+doc_prolog(TreeState *state)
+{
+ fprintf(state->file, "<html>\n");
+ fprintf(state->file, "<head>\n");
+
+ fprintf(state->file,
+ "<!-- this file is generated from %s.idl -->\n",
+ state->basename);
+ fprintf(state->file, "<title>documentation for %s.idl interfaces</title>\n",
+ state->basename);
+ fprintf(state->file, "</head>\n\n");
+ fprintf(state->file, "<body>\n");
+
+ return TRUE;
+}
+
+static gboolean
+doc_epilog(TreeState *state)
+{
+ fprintf(state->file, "</body>\n");
+ fprintf(state->file, "</html>\n");
+
+ return TRUE;
+}
+
+
+static gboolean
+doc_list(TreeState *state)
+{
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+print_list(FILE *outfile, IDL_tree list)
+{
+ if (list == NULL)
+ return TRUE;
+
+ fprintf(outfile, "<ul>\n");
+ while (list != NULL) {
+ fprintf(outfile, " <li>%s\n",
+ IDL_IDENT(IDL_LIST(list).data).str);
+ list = IDL_LIST(list).next;
+ }
+ fprintf(outfile, "</ul>\n");
+ return TRUE;
+}
+
+static gboolean
+doc_interface(TreeState *state)
+{
+ IDL_tree iface = state->tree;
+ IDL_tree iter;
+ IDL_tree orig;
+ char *classname = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
+ GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
+
+ fprintf(state->file, "interface %s<br>\n", classname);
+
+ /* Much more could happen at this step. */
+ /*
+ * If parsing doc comments, you might need to take some care with line
+ * endings, as the xpidl frontend will return comments containing of /r,
+ * /n, /r/n depending on the platform. It's best to leave out platform
+ * #defines and just treat them all as equivalent.
+ */
+ if (doc_comments != NULL) {
+ fprintf(state->file, "doc comments:<br>\n");
+ fprintf(state->file, "<pre>\n");
+ printlist(state->file, doc_comments);
+ fprintf(state->file, "</pre>\n");
+ fprintf(state->file, "<br>\n");
+ }
+
+ /* inherits from */
+ /*
+ * Note that we accept multiple inheritance here (for e.g. gnome idl)
+ * even though the header backend (specific to mozilla idl) rejects it.
+ */
+ if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
+ fprintf(state->file, "%s inherits from:<br>\n", classname);
+ print_list(state->file, iter);
+ fprintf(state->file, "<br>\n");
+ }
+
+ /*
+ * Call xpidl_process_node to recur through list of declarations in
+ * interface body; another option would be to explicitly iterate through
+ * the list. xpidl_process_node currently requires twiddling the state to
+ * get the right node; I'll fix that soon to just take the node. Makes it
+ * easier to follow what's going on, I think...
+ */
+ orig = state->tree;
+ state->tree = IDL_INTERFACE(iface).body;
+ if (state->tree && !xpidl_process_node(state))
+ return FALSE;
+ state->tree = orig;
+
+ return TRUE;
+}
+
+/*
+ * Copied from xpidl_header.c. You'll probably want to change it; if you can
+ * use it verbatim or abstract it, we could move it to xpidl_util.c and share
+ * it from there.
+ */
+static gboolean
+write_type(IDL_tree type_tree, FILE *outfile)
+{
+ if (!type_tree) {
+ fputs("void", outfile);
+ return TRUE;
+ }
+
+ switch (IDL_NODE_TYPE(type_tree)) {
+ case IDLN_TYPE_INTEGER: {
+ gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed;
+ switch (IDL_TYPE_INTEGER(type_tree).f_type) {
+ case IDL_INTEGER_TYPE_SHORT:
+ fputs(sign ? "PRInt16" : "PRUint16", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONG:
+ fputs(sign ? "PRInt32" : "PRUint32", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONGLONG:
+ fputs(sign ? "PRInt64" : "PRUint64", outfile);
+ break;
+ default:
+ g_error("Unknown integer type %d\n",
+ IDL_TYPE_INTEGER(type_tree).f_type);
+ return FALSE;
+ }
+ break;
+ }
+ case IDLN_TYPE_CHAR:
+ fputs("char", outfile);
+ break;
+ case IDLN_TYPE_WIDE_CHAR:
+ fputs("PRUnichar", outfile); /* wchar_t? */
+ break;
+ case IDLN_TYPE_WIDE_STRING:
+ fputs("PRUnichar *", outfile);
+ break;
+ case IDLN_TYPE_STRING:
+ fputs("char *", outfile);
+ break;
+ case IDLN_TYPE_BOOLEAN:
+ fputs("PRBool", outfile);
+ break;
+ case IDLN_TYPE_OCTET:
+ fputs("PRUint8", outfile);
+ break;
+ case IDLN_TYPE_FLOAT:
+ switch (IDL_TYPE_FLOAT(type_tree).f_type) {
+ case IDL_FLOAT_TYPE_FLOAT:
+ fputs("float", outfile);
+ break;
+ case IDL_FLOAT_TYPE_DOUBLE:
+ fputs("double", outfile);
+ break;
+ /* XXX 'long double' just ignored, or what? */
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ break;
+ case IDLN_IDENT:
+ if (UP_IS_NATIVE(type_tree)) {
+ fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile);
+ if (IDL_tree_property_get(type_tree, "ptr")) {
+ fputs(" *", outfile);
+ } else if (IDL_tree_property_get(type_tree, "ref")) {
+ fputs(" &", outfile);
+ }
+ } else {
+ fputs(IDL_IDENT(type_tree).str, outfile);
+ }
+ if (UP_IS_AGGREGATE(type_tree))
+ fputs(" *", outfile);
+ break;
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ return TRUE;
+}
+
+/* handle ATTR_DCL (attribute declaration) nodes */
+static gboolean
+doc_attribute_declaration(TreeState *state)
+{
+ IDL_tree attr = state->tree;
+
+ if (!verify_attribute_declaration(attr))
+ return FALSE;
+ /*
+ * Attribute idents can also take doc comments. They're ignored here;
+ * should they be?
+ */
+
+ if (IDL_ATTR_DCL(attr).f_readonly)
+ fprintf(state->file, "readonly ");
+
+ fprintf(state->file, "attribute ");
+
+ if (!write_type(IDL_ATTR_DCL(attr).param_type_spec, state->file))
+ return FALSE;
+
+ fprintf(state->file, "\n");
+ print_list(state->file, IDL_ATTR_DCL(attr).simple_declarations);
+ fprintf(state->file, "<br>\n");
+
+ return TRUE;
+}
+
+/* handle OP_DCL (method declaration) nodes */
+static gboolean
+doc_method_declaration(TreeState *state)
+{
+ /*
+ * Doc comment for attributes also applies here.
+ */
+
+ /*
+ * Look at 'write_method_signature' in xpidl_header.c for an example of how
+ * to navigate parse trees for methods. For here, I just print the method
+ * name.
+ */
+
+ fprintf(state->file,
+ "method %s<br>\n",
+ IDL_IDENT(IDL_OP_DCL(state->tree).ident).str);
+
+ return TRUE;
+}
+
+backend *
+xpidl_doc_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = doc_prolog;
+ result.emit_epilog = doc_epilog;
+
+ if (!initialized) {
+ /* Initialize non-NULL elements */
+
+ /* I just handle a few... many still to be filled in! */
+
+ table[IDLN_LIST] = doc_list;
+ table[IDLN_INTERFACE] = doc_interface;
+ table[IDLN_ATTR_DCL] = doc_attribute_declaration;
+ table[IDLN_OP_DCL] = doc_method_declaration;
+
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c
new file mode 100644
index 00000000..f4fe9d5b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c
@@ -0,0 +1,1196 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Generate XPCOM headers from XPIDL.
+ */
+
+#include "xpidl.h"
+#include <ctype.h>
+
+#define AS_DECL 0
+#define AS_CALL 1
+#define AS_IMPL 2
+
+static gboolean write_method_signature(IDL_tree method_tree, FILE *outfile,
+ int mode, const char *className);
+static gboolean write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
+ gboolean getter,
+ int mode, const char *className);
+
+static void
+write_indent(FILE *outfile) {
+ fputs(" ", outfile);
+}
+
+static gboolean
+header_prolog(TreeState *state)
+{
+ char *define = xpidl_basename(state->basename);
+ fprintf(state->file, "/*\n * DO NOT EDIT. THIS FILE IS GENERATED FROM"
+ " %s.idl\n */\n", state->basename);
+ fprintf(state->file,
+ "\n#ifndef __gen_%s_h__\n"
+ "#define __gen_%s_h__\n",
+ define, define);
+ g_free(define);
+ if (state->base_includes != NULL) {
+ guint len = g_slist_length(state->base_includes);
+ guint i;
+
+ fputc('\n', state->file);
+ for (i = 0; i < len; i++) {
+ char *ident, *dot;
+
+ ident = (char *)g_slist_nth_data(state->base_includes, i);
+
+ /* suppress any trailing .extension */
+
+ /* XXX use g_basename instead ? ? */
+
+ dot = strrchr(ident, '.');
+ if (dot != NULL)
+ *dot = '\0';
+
+
+ /* begin include guard */
+ fprintf(state->file,
+ "\n#ifndef __gen_%s_h__\n",
+ ident);
+
+ fprintf(state->file, "#include \"%s.h\"\n",
+ (char *)g_slist_nth_data(state->base_includes, i));
+
+ fprintf(state->file, "#endif\n");
+
+ }
+ if (i > 0)
+ fputc('\n', state->file);
+ }
+ /*
+ * Support IDL files that don't include a root IDL file that defines
+ * NS_NO_VTABLE.
+ */
+ fprintf(state->file,
+ "/* For IDL files that don't want to include root IDL files. */\n"
+ "#ifndef NS_NO_VTABLE\n"
+ "#define NS_NO_VTABLE\n"
+ "#endif\n");
+
+ return TRUE;
+}
+
+static gboolean
+header_epilog(TreeState *state)
+{
+ char *define = xpidl_basename(state->basename);
+ fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define);
+ g_free(define);
+ return TRUE;
+}
+
+static void
+write_classname_iid_define(FILE *file, const char *className)
+{
+ const char *iidName;
+ if (className[0] == 'n' && className[1] == 's') {
+ /* backcompat naming styles */
+ fputs("NS_", file);
+ iidName = className + 2;
+ } else {
+ iidName = className;
+ }
+ while (*iidName)
+ fputc(toupper(*iidName++), file);
+ fputs("_IID", file);
+}
+
+static gboolean
+interface(TreeState *state)
+{
+ IDL_tree iface = state->tree, iter, orig;
+ char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
+ char *classNameUpper = NULL;
+ char *classNameImpl = NULL;
+ char *cp;
+ gboolean ok = TRUE;
+ gboolean keepvtable;
+ const char *iid;
+ const char *name_space;
+ struct nsID id;
+ char iid_parsed[UUID_LENGTH];
+ GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
+
+ if (!verify_interface_declaration(iface))
+ return FALSE;
+
+#define FAIL do {ok = FALSE; goto out;} while(0)
+
+ fprintf(state->file, "\n/* starting interface: %s */\n",
+ className);
+
+ name_space = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "namespace");
+ if (name_space) {
+ fprintf(state->file, "/* namespace: %s */\n",
+ name_space);
+ fprintf(state->file, "/* fully qualified name: %s.%s */\n",
+ name_space,className);
+ }
+
+ iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid");
+ if (iid) {
+ /* Redundant, but a better error than 'cannot parse.' */
+ if (strlen(iid) != 36) {
+ IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid);
+ FAIL;
+ }
+
+ /*
+ * Parse uuid and then output resulting nsID to string, to validate
+ * uuid and normalize resulting .h files.
+ */
+ if (!xpidl_parse_iid(&id, iid)) {
+ IDL_tree_error(state->tree, "cannot parse IID %s\n", iid);
+ FAIL;
+ }
+ if (!xpidl_sprint_iid(&id, iid_parsed)) {
+ IDL_tree_error(state->tree, "error formatting IID %s\n", iid);
+ FAIL;
+ }
+
+ /* #define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046" */
+ fputs("#define ", state->file);
+ write_classname_iid_define(state->file, className);
+ fprintf(state->file, "_STR \"%s\"\n", iid_parsed);
+ fputc('\n', state->file);
+
+ /* #define NS_ISUPPORTS_IID { {0x00000000 .... 0x46 }} */
+ fprintf(state->file, "#define ");
+ write_classname_iid_define(state->file, className);
+ fprintf(state->file, " \\\n"
+ " {0x%.8x, 0x%.4x, 0x%.4x, \\\n"
+ " { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, "
+ "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }}\n",
+ id.m0, id.m1, id.m2,
+ id.m3[0], id.m3[1], id.m3[2], id.m3[3],
+ id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
+ fputc('\n', state->file);
+ } else {
+ IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n",
+ className);
+ FAIL;
+ }
+
+ if (doc_comments != NULL)
+ printlist(state->file, doc_comments);
+
+ /*
+ * NS_NO_VTABLE is defined in nsISupportsUtils.h, and defined on windows
+ * to __declspec(novtable) on windows. This optimization is safe
+ * whenever the constructor calls no virtual methods. Writing in IDL
+ * almost guarantees this, except for the case when a %{C++ block occurs in
+ * the interface. We detect that case, and emit a macro call that disables
+ * the optimization.
+ */
+ keepvtable = FALSE;
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+ if (IDL_NODE_TYPE(data) == IDLN_CODEFRAG)
+ keepvtable = TRUE;
+ }
+
+ /* The interface declaration itself. */
+ fprintf(state->file,
+ "class %s%s",
+ (keepvtable ? "" : "NS_NO_VTABLE "), className);
+
+ if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
+ fputs(" : ", state->file);
+ if (IDL_LIST(iter).next != NULL) {
+ IDL_tree_error(iter,
+ "multiple inheritance is not supported by xpidl");
+ FAIL;
+ }
+ fprintf(state->file, "public %s", IDL_IDENT(IDL_LIST(iter).data).str);
+ }
+ fputs(" {\n"
+ " public: \n\n", state->file);
+ if (iid) {
+ fputs(" NS_DEFINE_STATIC_IID_ACCESSOR(", state->file);
+ write_classname_iid_define(state->file, className);
+ fputs(")\n\n", state->file);
+ }
+
+ orig = state->tree; /* It would be nice to remove this state-twiddling. */
+
+ state->tree = IDL_INTERFACE(iface).body;
+
+ if (state->tree && !xpidl_process_node(state))
+ FAIL;
+
+ fputs("};\n", state->file);
+ fputc('\n', state->file);
+
+ /*
+ * #define NS_DECL_NSIFOO - create method prototypes that can be used in
+ * class definitions that support this interface.
+ *
+ * Walk the tree explicitly to prototype a reworking of xpidl to get rid of
+ * the callback mechanism.
+ */
+ state->tree = orig;
+ fputs("/* Use this macro when declaring classes that implement this "
+ "interface. */\n", state->file);
+ fputs("#define NS_DECL_", state->file);
+ classNameUpper = xpidl_strdup(className);
+ for (cp = classNameUpper; *cp != '\0'; cp++)
+ *cp = toupper(*cp);
+ fprintf(state->file, "%s \\\n", classNameUpper);
+ if (IDL_INTERFACE(state->tree).body == NULL) {
+ write_indent(state->file);
+ fputs("/* no methods! */\n", state->file);
+ }
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ write_indent(state->file);
+ write_method_signature(data, state->file, AS_DECL, NULL);
+ break;
+
+ case IDLN_ATTR_DCL:
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL))
+ FAIL;
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ fputs("; \\\n", state->file); /* Terminate the previous one. */
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_DECL, NULL))
+ FAIL;
+ /* '; \n' at end will clean up. */
+ }
+ break;
+
+ case IDLN_CONST_DCL:
+ /* ignore it here; it doesn't contribute to the macro. */
+ continue;
+
+ case IDLN_CODEFRAG:
+ XPIDL_WARNING((iter, IDL_WARNING1,
+ "%%{ .. %%} code fragment within interface "
+ "ignored when generating NS_DECL_%s macro; "
+ "if the code fragment contains method "
+ "declarations, the macro probably isn't "
+ "complete.", classNameUpper));
+ continue;
+
+ default:
+ IDL_tree_error(iter,
+ "unexpected node type %d! "
+ "Please file a bug against the xpidl component.",
+ IDL_NODE_TYPE(data));
+ FAIL;
+ }
+
+ if (IDL_LIST(iter).next != NULL) {
+ fprintf(state->file, "; \\\n");
+ } else {
+ fprintf(state->file, "; \n");
+ }
+ }
+ fputc('\n', state->file);
+
+ /* XXX abstract above and below into one function? */
+ /*
+ * #define NS_FORWARD_NSIFOO - create forwarding methods that can delegate
+ * behavior from in implementation to another object. As generated by
+ * idlc.
+ */
+ fprintf(state->file,
+ "/* Use this macro to declare functions that forward the "
+ "behavior of this interface to another object. */\n"
+ "#define NS_FORWARD_%s(_to) \\\n",
+ classNameUpper);
+ if (IDL_INTERFACE(state->tree).body == NULL) {
+ write_indent(state->file);
+ fputs("/* no methods! */\n", state->file);
+ }
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ write_indent(state->file);
+ write_method_signature(data, state->file, AS_DECL, NULL);
+ fputs(" { return _to ", state->file);
+ write_method_signature(data, state->file, AS_CALL, NULL);
+ break;
+
+ case IDLN_ATTR_DCL:
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return _to ", state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL))
+ FAIL;
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ fputs("; } \\\n", state->file); /* Terminate the previous one. */
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return _to ", state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_CALL, NULL))
+ FAIL;
+ /* '; } \n' at end will clean up. */
+ }
+ break;
+
+ case IDLN_CONST_DCL:
+ case IDLN_CODEFRAG:
+ continue;
+
+ default:
+ FAIL;
+ }
+
+ if (IDL_LIST(iter).next != NULL) {
+ fprintf(state->file, "; } \\\n");
+ } else {
+ fprintf(state->file, "; } \n");
+ }
+ }
+ fputc('\n', state->file);
+
+
+ /* XXX abstract above and below into one function? */
+ /*
+ * #define NS_FORWARD_SAFE_NSIFOO - create forwarding methods that can delegate
+ * behavior from in implementation to another object. As generated by
+ * idlc.
+ */
+ fprintf(state->file,
+ "/* Use this macro to declare functions that forward the "
+ "behavior of this interface to another object in a safe way. */\n"
+ "#define NS_FORWARD_SAFE_%s(_to) \\\n",
+ classNameUpper);
+ if (IDL_INTERFACE(state->tree).body == NULL) {
+ write_indent(state->file);
+ fputs("/* no methods! */\n", state->file);
+ }
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ write_indent(state->file);
+ write_method_signature(data, state->file, AS_DECL, NULL);
+ fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file);
+ write_method_signature(data, state->file, AS_CALL, NULL);
+ break;
+
+ case IDLN_ATTR_DCL:
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL))
+ FAIL;
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ fputs("; } \\\n", state->file); /* Terminate the previous one. */
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_CALL, NULL))
+ FAIL;
+ /* '; } \n' at end will clean up. */
+ }
+ break;
+
+ case IDLN_CONST_DCL:
+ case IDLN_CODEFRAG:
+ continue;
+
+ default:
+ FAIL;
+ }
+
+ if (IDL_LIST(iter).next != NULL) {
+ fprintf(state->file, "; } \\\n");
+ } else {
+ fprintf(state->file, "; } \n");
+ }
+ }
+ fputc('\n', state->file);
+
+ /*
+ * Build a sample implementation template.
+ */
+ if (strlen(className) >= 3 && className[2] == 'I') {
+ classNameImpl = xpidl_strdup(className);
+ if (!classNameImpl)
+ FAIL;
+ memmove(&classNameImpl[2], &classNameImpl[3], strlen(classNameImpl) - 2);
+ } else {
+ classNameImpl = xpidl_strdup("_MYCLASS_");
+ if (!classNameImpl)
+ FAIL;
+ }
+
+ fputs("#if 0\n"
+ "/* Use the code below as a template for the "
+ "implementation class for this interface. */\n"
+ "\n"
+ "/* Header file */"
+ "\n",
+ state->file);
+ fprintf(state->file, "class %s : public %s\n", classNameImpl, className);
+ fputs("{\n"
+ "public:\n", state->file);
+ write_indent(state->file);
+ fputs("NS_DECL_ISUPPORTS\n", state->file);
+ write_indent(state->file);
+ fprintf(state->file, "NS_DECL_%s\n", classNameUpper);
+ fputs("\n", state->file);
+ write_indent(state->file);
+ fprintf(state->file, "%s();\n", classNameImpl);
+ fputs("\n"
+ "private:\n", state->file);
+ write_indent(state->file);
+ fprintf(state->file, "~%s();\n", classNameImpl);
+ fputs("\n"
+ "protected:\n", state->file);
+ write_indent(state->file);
+ fputs("/* additional members */\n", state->file);
+ fputs("};\n\n", state->file);
+
+ fputs("/* Implementation file */\n", state->file);
+
+ fprintf(state->file,
+ "NS_IMPL_ISUPPORTS1(%s, %s)\n", classNameImpl, className);
+ fputs("\n", state->file);
+
+ fprintf(state->file, "%s::%s()\n", classNameImpl, classNameImpl);
+ fputs("{\n", state->file);
+ write_indent(state->file);
+ fputs("/* member initializers and constructor code */\n", state->file);
+ fputs("}\n\n", state->file);
+
+ fprintf(state->file, "%s::~%s()\n", classNameImpl, classNameImpl);
+ fputs("{\n", state->file);
+ write_indent(state->file);
+ fputs("/* destructor code */\n", state->file);
+ fputs("}\n\n", state->file);
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ /* It would be nice to remove this state-twiddling. */
+ orig = state->tree;
+ state->tree = data;
+ xpidl_write_comment(state, 0);
+ state->tree = orig;
+
+ write_method_signature(data, state->file, AS_IMPL, classNameImpl);
+ fputs("\n{\n", state->file);
+ write_indent(state->file);
+ write_indent(state->file);
+ fputs("return NS_ERROR_NOT_IMPLEMENTED;\n"
+ "}\n"
+ "\n", state->file);
+ break;
+
+ case IDLN_ATTR_DCL:
+ /* It would be nice to remove this state-twiddling. */
+ orig = state->tree;
+ state->tree = data;
+ xpidl_write_comment(state, 0);
+ state->tree = orig;
+
+ if (!write_attr_accessor(data, state->file, TRUE,
+ AS_IMPL, classNameImpl))
+ FAIL;
+ fputs("\n{\n", state->file);
+ write_indent(state->file);
+ write_indent(state->file);
+ fputs("return NS_ERROR_NOT_IMPLEMENTED;\n"
+ "}\n", state->file);
+
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ if (!write_attr_accessor(data, state->file, FALSE,
+ AS_IMPL, classNameImpl))
+ FAIL;
+ fputs("\n{\n", state->file);
+ write_indent(state->file);
+ write_indent(state->file);
+ fputs("return NS_ERROR_NOT_IMPLEMENTED;\n"
+ "}\n", state->file);
+ }
+ fputs("\n", state->file);
+ break;
+
+ case IDLN_CONST_DCL:
+ case IDLN_CODEFRAG:
+ continue;
+
+ default:
+ FAIL;
+ }
+ }
+
+ fputs("/* End of implementation class template. */\n"
+ "#endif\n"
+ "\n", state->file);
+
+#undef FAIL
+
+out:
+ if (classNameUpper)
+ free(classNameUpper);
+ if (classNameImpl)
+ free(classNameImpl);
+ return ok;
+}
+
+static gboolean
+list(TreeState *state)
+{
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+write_type(IDL_tree type_tree, gboolean is_out, FILE *outfile)
+{
+ if (!type_tree) {
+ fputs("void", outfile);
+ return TRUE;
+ }
+
+ switch (IDL_NODE_TYPE(type_tree)) {
+ case IDLN_TYPE_INTEGER: {
+ gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed;
+ switch (IDL_TYPE_INTEGER(type_tree).f_type) {
+ case IDL_INTEGER_TYPE_SHORT:
+ fputs(sign ? "PRInt16" : "PRUint16", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONG:
+ fputs(sign ? "PRInt32" : "PRUint32", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONGLONG:
+ fputs(sign ? "PRInt64" : "PRUint64", outfile);
+ break;
+ default:
+ g_error("Unknown integer type %d\n",
+ IDL_TYPE_INTEGER(type_tree).f_type);
+ return FALSE;
+ }
+ break;
+ }
+ case IDLN_TYPE_CHAR:
+ fputs("char", outfile);
+ break;
+ case IDLN_TYPE_WIDE_CHAR:
+ fputs("PRUnichar", outfile); /* wchar_t? */
+ break;
+ case IDLN_TYPE_WIDE_STRING:
+ fputs("PRUnichar *", outfile);
+ break;
+ case IDLN_TYPE_STRING:
+ fputs("char *", outfile);
+ break;
+ case IDLN_TYPE_BOOLEAN:
+ fputs("PRBool", outfile);
+ break;
+ case IDLN_TYPE_OCTET:
+ fputs("PRUint8", outfile);
+ break;
+ case IDLN_TYPE_FLOAT:
+ switch (IDL_TYPE_FLOAT(type_tree).f_type) {
+ case IDL_FLOAT_TYPE_FLOAT:
+ fputs("float", outfile);
+ break;
+ case IDL_FLOAT_TYPE_DOUBLE:
+ fputs("double", outfile);
+ break;
+ /* XXX 'long double' just ignored, or what? */
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ break;
+ case IDLN_IDENT:
+ if (UP_IS_NATIVE(type_tree)) {
+ if (IDL_tree_property_get(type_tree, "domstring") ||
+ IDL_tree_property_get(type_tree, "astring")) {
+ fputs("nsAString", outfile);
+ } else if (IDL_tree_property_get(type_tree, "utf8string")) {
+ fputs("nsACString", outfile);
+ } else if (IDL_tree_property_get(type_tree, "cstring")) {
+ fputs("nsACString", outfile);
+ } else {
+ fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile);
+ }
+ if (IDL_tree_property_get(type_tree, "ptr")) {
+ fputs(" *", outfile);
+ } else if (IDL_tree_property_get(type_tree, "ref")) {
+ fputs(" &", outfile);
+ }
+ } else {
+ fputs(IDL_IDENT(type_tree).str, outfile);
+ }
+ if (UP_IS_AGGREGATE(type_tree))
+ fputs(" *", outfile);
+ break;
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ return TRUE;
+}
+
+/*
+ * An attribute declaration looks like:
+ *
+ * [ IDL_ATTR_DCL]
+ * - param_type_spec [IDL_TYPE_* or NULL for void]
+ * - simple_declarations [IDL_LIST]
+ * - data [IDL_IDENT]
+ * - next [IDL_LIST or NULL if no more idents]
+ * - data [IDL_IDENT]
+ */
+
+#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
+#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
+#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
+
+/*
+ * AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)'
+ * AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)'
+ * AS_CALL writes 'foo(bar, sil)'
+ */
+static gboolean
+write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
+ gboolean getter, int mode, const char *className)
+{
+ char *attrname = ATTR_IDENT(attr_tree).str;
+
+ if (mode == AS_DECL) {
+ fputs("NS_IMETHOD ", outfile);
+ } else if (mode == AS_IMPL) {
+ fprintf(outfile, "NS_IMETHODIMP %s::", className);
+ }
+ fprintf(outfile, "%cet%c%s(",
+ getter ? 'G' : 'S',
+ toupper(*attrname), attrname + 1);
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ /* Setters for string, wstring, nsid, domstring, utf8string,
+ * cstring and astring get const.
+ */
+ if (!getter &&
+ (IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_STRING ||
+ IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_WIDE_STRING ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "nsid") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "domstring") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "utf8string") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "cstring") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "astring")))
+ {
+ fputs("const ", outfile);
+ }
+
+ if (!write_type(ATTR_TYPE_DECL(attr_tree), getter, outfile))
+ return FALSE;
+ fprintf(outfile, "%s%s",
+ (STARRED_TYPE(attr_tree) ? "" : " "),
+ (getter && !DIPPER_TYPE(ATTR_TYPE_DECL(attr_tree)))? "*" : "");
+ }
+ fprintf(outfile, "a%c%s)", toupper(attrname[0]), attrname + 1);
+ return TRUE;
+}
+
+static gboolean
+attr_dcl(TreeState *state)
+{
+ GSList *doc_comments;
+
+ if (!verify_attribute_declaration(state->tree))
+ return FALSE;
+
+ doc_comments =
+ IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
+ (state->tree).simple_declarations).data).comments;
+
+ if (doc_comments != NULL) {
+ write_indent(state->file);
+ printlist(state->file, doc_comments);
+ }
+
+ /*
+ * XXX lists of attributes with the same type, e.g.
+ * attribute string foo, bar sil;
+ * are legal IDL... but we don't do anything with 'em.
+ */
+ if (IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).next != NULL) {
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "multiple attributes in a single declaration aren't "
+ "currently supported by xpidl"));
+ }
+
+ xpidl_write_comment(state, 2);
+
+ write_indent(state->file);
+ if (!write_attr_accessor(state->tree, state->file, TRUE, AS_DECL, NULL))
+ return FALSE;
+ fputs(" = 0;\n", state->file);
+
+ if (!IDL_ATTR_DCL(state->tree).f_readonly) {
+ write_indent(state->file);
+ if (!write_attr_accessor(state->tree, state->file, FALSE, AS_DECL, NULL))
+ return FALSE;
+ fputs(" = 0;\n", state->file);
+ }
+ fputc('\n', state->file);
+
+ return TRUE;
+}
+
+static gboolean
+do_enum(TreeState *state)
+{
+ IDL_tree_error(state->tree, "enums not supported, "
+ "see http://bugzilla.mozilla.org/show_bug.cgi?id=8781");
+ return FALSE;
+}
+
+static gboolean
+do_const_dcl(TreeState *state)
+{
+ struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
+ const char *name = IDL_IDENT(dcl->ident).str;
+ gboolean is_signed;
+ GSList *doc_comments = IDL_IDENT(dcl->ident).comments;
+ IDL_tree real_type;
+ const char *const_format;
+
+ if (!verify_const_declaration(state->tree))
+ return FALSE;
+
+ if (doc_comments != NULL) {
+ write_indent(state->file);
+ printlist(state->file, doc_comments);
+ }
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(dcl->const_type);
+ real_type = real_type ? real_type : dcl->const_type;
+ is_signed = IDL_TYPE_INTEGER(real_type).f_signed;
+
+ const_format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "uU";
+ write_indent(state->file);
+ fprintf(state->file, "enum { %s = ", name);
+ fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value);
+ fprintf(state->file, " };\n\n");
+
+ return TRUE;
+}
+
+static gboolean
+do_typedef(TreeState *state)
+{
+ IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
+ IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
+ IDL_tree complex;
+ GSList *doc_comments;
+
+ if (IDL_NODE_TYPE(type) == IDLN_TYPE_SEQUENCE) {
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "sequences not supported, ignored"));
+ } else {
+ if (IDL_NODE_TYPE(complex = IDL_LIST(dcls).data) == IDLN_TYPE_ARRAY) {
+ IDL_tree dim = IDL_TYPE_ARRAY(complex).size_list;
+ doc_comments = IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).comments;
+
+ if (doc_comments != NULL)
+ printlist(state->file, doc_comments);
+
+ fputs("typedef ", state->file);
+ if (!write_type(type, FALSE, state->file))
+ return FALSE;
+ fputs(" ", state->file);
+
+ fprintf(state->file, "%s",
+ IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).str);
+ do {
+ fputc('[', state->file);
+ if (IDL_LIST(dim).data) {
+ fprintf(state->file, "%ld",
+ (long)IDL_INTEGER(IDL_LIST(dim).data).value);
+ }
+ fputc(']', state->file);
+ } while ((dim = IDL_LIST(dim).next) != NULL);
+ } else {
+ doc_comments = IDL_IDENT(IDL_LIST(dcls).data).comments;
+
+ if (doc_comments != NULL)
+ printlist(state->file, doc_comments);
+
+ fputs("typedef ", state->file);
+ if (!write_type(type, FALSE, state->file))
+ return FALSE;
+ fputs(" ", state->file);
+ fputs(IDL_IDENT(IDL_LIST(dcls).data).str, state->file);
+ }
+ fputs(";\n\n", state->file);
+ }
+ return TRUE;
+}
+
+/*
+ * param generation:
+ * in string foo --> nsString *foo
+ * out string foo --> nsString **foo;
+ * inout string foo --> nsString **foo;
+ */
+
+/* If notype is true, just write the param name. */
+static gboolean
+write_param(IDL_tree param_tree, FILE *outfile)
+{
+ IDL_tree param_type_spec = IDL_PARAM_DCL(param_tree).param_type_spec;
+ gboolean is_in = IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_IN;
+ /* in string, wstring, nsid, domstring, utf8string, cstring and
+ * astring any explicitly marked [const] are const
+ */
+
+ if (is_in &&
+ (IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_STRING ||
+ IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_WIDE_STRING ||
+ IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
+ "const") ||
+ IDL_tree_property_get(param_type_spec, "nsid") ||
+ IDL_tree_property_get(param_type_spec, "domstring") ||
+ IDL_tree_property_get(param_type_spec, "utf8string") ||
+ IDL_tree_property_get(param_type_spec, "cstring") ||
+ IDL_tree_property_get(param_type_spec, "astring"))) {
+ fputs("const ", outfile);
+ }
+ else if (IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_OUT &&
+ IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
+ "shared")) {
+ fputs("const ", outfile);
+ }
+
+ if (!write_type(param_type_spec, !is_in, outfile))
+ return FALSE;
+
+ /* unless the type ended in a *, add a space */
+ if (!STARRED_TYPE(param_type_spec))
+ fputc(' ', outfile);
+
+ /* out and inout params get a bonus '*' (unless this is type that has a
+ * 'dipper' class that is passed in to receive 'out' data)
+ */
+ if (IDL_PARAM_DCL(param_tree).attr != IDL_PARAM_IN &&
+ !DIPPER_TYPE(param_type_spec)) {
+ fputc('*', outfile);
+ }
+ /* arrays get a bonus * too */
+ /* XXX Should this be a leading '*' or a trailing "[]" ?*/
+ if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
+ "array"))
+ fputc('*', outfile);
+
+ fputs(IDL_IDENT(IDL_PARAM_DCL(param_tree).simple_declarator).str, outfile);
+
+ return TRUE;
+}
+
+/*
+ * A forward declaration, usually an interface.
+ */
+static gboolean
+forward_dcl(TreeState *state)
+{
+ IDL_tree iface = state->tree;
+ const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
+
+ if (!className)
+ return FALSE;
+
+ fprintf(state->file, "class %s; /* forward declaration */\n\n", className);
+ return TRUE;
+}
+
+/*
+ * Shared between the interface class declaration and the NS_DECL_IFOO macro
+ * provided to aid declaration of implementation classes.
+ * mode...
+ * AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)'
+ * AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)'
+ * AS_CALL writes 'foo(bar, sil)'
+ */
+static gboolean
+write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
+ const char *className)
+{
+ struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
+ gboolean no_generated_args = TRUE;
+ gboolean op_notxpcom =
+ (IDL_tree_property_get(op->ident, "notxpcom") != NULL);
+ const char *name;
+ IDL_tree iter;
+
+ if (mode == AS_DECL) {
+ if (op_notxpcom) {
+ fputs("NS_IMETHOD_(", outfile);
+ if (!write_type(op->op_type_spec, FALSE, outfile))
+ return FALSE;
+ fputc(')', outfile);
+ } else {
+ fputs("NS_IMETHOD", outfile);
+ }
+ fputc(' ', outfile);
+ }
+ else if (mode == AS_IMPL) {
+ if (op_notxpcom) {
+ fputs("NS_IMETHODIMP_(", outfile);
+ if (!write_type(op->op_type_spec, FALSE, outfile))
+ return FALSE;
+ fputc(')', outfile);
+ } else {
+ fputs("NS_IMETHODIMP", outfile);
+ }
+ fputc(' ', outfile);
+ }
+ name = IDL_IDENT(op->ident).str;
+ if (mode == AS_IMPL) {
+ fprintf(outfile, "%s::%c%s(", className, toupper(*name), name + 1);
+ } else {
+ fprintf(outfile, "%c%s(", toupper(*name), name + 1);
+ }
+ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ if (!write_param(IDL_LIST(iter).data, outfile))
+ return FALSE;
+ } else {
+ fputs(IDL_IDENT(IDL_PARAM_DCL(IDL_LIST(iter).data)
+ .simple_declarator).str,
+ outfile);
+ }
+ if ((IDL_LIST(iter).next ||
+ (!op_notxpcom && op->op_type_spec) || op->f_varargs))
+ fputs(", ", outfile);
+ no_generated_args = FALSE;
+ }
+
+ /* make IDL return value into trailing out argument */
+ if (op->op_type_spec && !op_notxpcom) {
+ IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
+ op->op_type_spec,
+ IDL_ident_new("_retval"));
+ if (!fake_param)
+ return FALSE;
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ if (!write_param(fake_param, outfile))
+ return FALSE;
+ } else {
+ fputs("_retval", outfile);
+ }
+ if (op->f_varargs)
+ fputs(", ", outfile);
+ no_generated_args = FALSE;
+ }
+
+ /* varargs go last */
+ if (op->f_varargs) {
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ fputs("nsVarArgs *", outfile);
+ }
+ fputs("_varargs", outfile);
+ no_generated_args = FALSE;
+ }
+
+ /*
+ * If generated method has no arguments, output 'void' to avoid C legacy
+ * behavior of disabling type checking.
+ */
+ if (no_generated_args && mode == AS_DECL) {
+ fputs("void", outfile);
+ }
+
+ fputc(')', outfile);
+
+ return TRUE;
+}
+
+/*
+ * A method is an `operation', therefore a method decl is an `op dcl'.
+ * I blame Elliot.
+ */
+static gboolean
+op_dcl(TreeState *state)
+{
+ GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments;
+
+ /*
+ * Verify that e.g. non-scriptable methods in [scriptable] interfaces
+ * are declared so. Do this in a separate verification pass?
+ */
+ if (!verify_method_declaration(state->tree))
+ return FALSE;
+
+ if (doc_comments != NULL) {
+ write_indent(state->file);
+ printlist(state->file, doc_comments);
+ }
+ xpidl_write_comment(state, 2);
+
+ write_indent(state->file);
+ if (!write_method_signature(state->tree, state->file, AS_DECL, NULL))
+ return FALSE;
+ fputs(" = 0;\n\n", state->file);
+
+ return TRUE;
+}
+
+static void
+write_codefrag_line(gpointer data, gpointer user_data)
+{
+ TreeState *state = (TreeState *)user_data;
+ const char *line = (const char *)data;
+ fputs(line, state->file);
+ fputc('\n', state->file);
+}
+
+static gboolean
+codefrag(TreeState *state)
+{
+ const char *desc = IDL_CODEFRAG(state->tree).desc;
+ GSList *lines = IDL_CODEFRAG(state->tree).lines;
+ guint fragment_length;
+
+ if (strcmp(desc, "C++") && /* libIDL bug? */ strcmp(desc, "C++\r")) {
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "ignoring '%%{%s' escape. "
+ "(Use '%%{C++' to escape verbatim C++ code.)", desc));
+
+ return TRUE;
+ }
+
+ /*
+ * Emit #file directive to point debuggers back to the original .idl file
+ * for the duration of the code fragment. We look at internal IDL node
+ * properties _file, _line to do this; hopefully they won't change.
+ *
+ * _line seems to refer to the line immediately after the closing %}, so
+ * we backtrack to get the proper line for the beginning of the block.
+ */
+ /*
+ * Looks like getting this right means maintaining an accurate line
+ * count of everything generated, so we can set the file back to the
+ * correct line in the generated file afterwards. Skipping for now...
+ */
+
+ fragment_length = g_slist_length(lines);
+/* fprintf(state->file, "#line %d \"%s\"\n", */
+/* state->tree->_line - fragment_length - 1, */
+/* state->tree->_file); */
+
+ g_slist_foreach(lines, write_codefrag_line, (gpointer)state);
+
+ return TRUE;
+}
+
+backend *
+xpidl_header_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = header_prolog;
+ result.emit_epilog = header_epilog;
+
+ if (!initialized) {
+ table[IDLN_LIST] = list;
+ table[IDLN_ATTR_DCL] = attr_dcl;
+ table[IDLN_OP_DCL] = op_dcl;
+ table[IDLN_FORWARD_DCL] = forward_dcl;
+ table[IDLN_TYPE_ENUM] = do_enum;
+ table[IDLN_INTERFACE] = interface;
+ table[IDLN_CODEFRAG] = codefrag;
+ table[IDLN_TYPE_DCL] = do_typedef;
+ table[IDLN_CONST_DCL] = do_const_dcl;
+ table[IDLN_NATIVE] = check_native;
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c
new file mode 100644
index 00000000..175f379a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c
@@ -0,0 +1,836 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Ang <mang@subcarrier.org>
+ *
+ * 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Common IDL-processing code.
+ */
+
+#include "xpidl.h"
+
+#ifdef XP_MAC
+#include <stat.h>
+#endif
+
+static gboolean parsed_empty_file;
+
+/*
+ * The bulk of the generation happens here.
+ */
+gboolean
+xpidl_process_node(TreeState *state)
+{
+ gint type;
+ nodeHandler *dispatch, handler;
+
+ XPT_ASSERT(state->tree);
+ type = IDL_NODE_TYPE(state->tree);
+
+ if ((dispatch = state->dispatch) && (handler = dispatch[type]))
+ return handler(state);
+ return TRUE;
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+extern void mac_warning(const char* warning_message);
+#endif
+
+static int
+msg_callback(int level, int num, int line, const char *file,
+ const char *message)
+{
+ char *warning_message;
+
+ /*
+ * Egregious hack to permit empty files.
+ * XXX libIDL needs an API to detect this case robustly.
+ */
+ if (0 == strcmp(message, "File empty after optimization")) {
+ parsed_empty_file = TRUE;
+ return 1;
+ }
+
+ if (!file)
+ file = "<unknown file>";
+ warning_message = g_strdup_printf("%s:%d: %s\n", file, line, message);
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+ mac_warning(warning_message);
+#else
+ fputs(warning_message, stderr);
+#endif
+
+ g_free(warning_message);
+ return 1;
+}
+
+/*
+ * To keep track of the state associated with a given input file. The 'next'
+ * field lets us maintain a stack of input files.
+ */
+typedef struct input_data {
+ char *filename; /* where did I come from? */
+ unsigned int lineno; /* last lineno processed */
+ char *buf; /* contents of file */
+ char *point; /* next char to feed to libIDL */
+ char *max; /* 1 past last char in buf */
+ struct input_data *next; /* file from which we were included */
+} input_data;
+
+/*
+ * Passed to us by libIDL. Holds global information and the current stack of
+ * include files.
+ */
+typedef struct input_callback_state {
+ struct input_data *input_stack; /* linked list of input_data */
+ GHashTable *already_included; /* to prevent redundant includes */
+ IncludePathEntry *include_path; /* search path for included files */
+ GSList *base_includes; /* to accumulate #includes from *first* file;
+ * for passing thru TreeState to
+ * xpidl_header backend. */
+} input_callback_state;
+
+static FILE *
+fopen_from_includes(const char *filename, const char *mode,
+ IncludePathEntry *include_path)
+{
+ IncludePathEntry *current_path = include_path;
+ char *pathname;
+ FILE *inputfile;
+ if (!strcmp(filename, "-"))
+ return stdin;
+
+ if (filename[0] != '/') {
+ while (current_path) {
+ pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ current_path->directory, filename);
+ if (!pathname)
+ return NULL;
+ inputfile = fopen(pathname, mode);
+ g_free(pathname);
+ if (inputfile)
+ return inputfile;
+ current_path = current_path->next;
+ }
+ } else {
+ inputfile = fopen(filename, mode);
+ if (inputfile)
+ return inputfile;
+ }
+ return NULL;
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+extern FILE* mac_fopen(const char* filename, const char *mode);
+#endif
+
+static input_data *
+new_input_data(const char *filename, IncludePathEntry *include_path)
+{
+ input_data *new_data;
+ FILE *inputfile;
+ char *buffer = NULL;
+ size_t offset = 0;
+ size_t buffer_size;
+#ifdef XP_MAC
+ size_t i;
+#endif
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+ /* on Mac, fopen knows how to find files. */
+ inputfile = fopen(filename, "r");
+#elif defined(XP_OS2) || defined(XP_WIN32)
+ /*
+ * if filename is fully qualified (starts with driver letter), then
+ * just call fopen(); else, go with fopen_from_includes()
+ */
+ if( filename[1] == ':' )
+ inputfile = fopen(filename, "r");
+ else
+ inputfile = fopen_from_includes(filename, "r", include_path);
+#else
+ inputfile = fopen_from_includes(filename, "r", include_path);
+#endif
+
+ if (!inputfile)
+ return NULL;
+
+#ifdef XP_MAC
+ {
+ struct stat input_stat;
+ if (fstat(fileno(inputfile), &input_stat))
+ return NULL;
+ buffer = malloc(input_stat.st_size + 1);
+ if (!buffer)
+ return NULL;
+ offset = fread(buffer, 1, input_stat.st_size, inputfile);
+ if (ferror(inputfile))
+ return NULL;
+ }
+#else
+ /*
+ * Rather than try to keep track of many different varieties of state
+ * around the boundaries of a circular buffer, we just read in the entire
+ * file.
+ *
+ * We iteratively grow the buffer here; an alternative would be to use
+ * stat to find the exact buffer size we need, as xpt_dump does.
+ */
+ for (buffer_size = 8191; ; buffer_size *= 2) {
+ size_t just_read;
+ buffer = realloc(buffer, buffer_size + 1); /* +1 for trailing nul */
+ just_read = fread(buffer + offset, 1, buffer_size - offset, inputfile);
+ if (ferror(inputfile))
+ return NULL;
+
+ if (just_read < buffer_size - offset || just_read == 0) {
+ /* Done reading. */
+ offset += just_read;
+ break;
+ }
+ offset += just_read;
+ }
+#endif
+
+ fclose(inputfile);
+
+#ifdef XP_MAC
+ /*
+ * libIDL doesn't speak '\r' properly - always make sure lines end with
+ * '\n'.
+ */
+ for (i = 0; i < offset; i++) {
+ if (buffer[i] == '\r')
+ buffer[i] = '\n';
+ }
+#endif
+
+ new_data = xpidl_malloc(sizeof (struct input_data));
+ new_data->point = new_data->buf = buffer;
+ new_data->max = buffer + offset;
+ *new_data->max = '\0';
+ new_data->filename = xpidl_strdup(filename);
+ /* libIDL expects the line number to be that of the *next* line */
+ new_data->lineno = 2;
+ new_data->next = NULL;
+
+ return new_data;
+}
+
+/* process pending raw section */
+static int
+NextIsRaw(input_data *data, char **startp, int *lenp)
+{
+ char *end, *start;
+
+ /*
+ * XXXmccabe still needed: an in_raw flag to handle the case where we're in
+ * a raw block, but haven't managed to copy it all to xpidl. This will
+ * happen when we have a raw block larger than
+ * IDL_input_data->fill.max_size (currently 8192.)
+ */
+ if (!(data->point[0] == '%' && data->point[1] == '{'))
+ return 0;
+
+ start = *startp = data->point;
+
+ end = NULL;
+ while (start < data->max && (end = strstr(start, "%}"))) {
+ if (end[-1] == '\r' ||
+ end[-1] == '\n')
+ break;
+ start = end + 1;
+ }
+
+ if (end && start < data->max) {
+ *lenp = end - data->point + 2;
+ return 1;
+ } else {
+ const char *filename;
+ int lineno;
+
+ IDL_file_get(&filename, &lineno);
+ msg_callback(IDL_ERROR, 0, lineno, filename,
+ "unterminated %{ block");
+ return -1;
+ }
+}
+
+/* process pending comment */
+static int
+NextIsComment(input_data *data, char **startp, int *lenp)
+{
+ char *end;
+
+ if (!(data->point[0] == '/' && data->point[1] == '*'))
+ return 0;
+
+ end = strstr(data->point, "*/");
+ *lenp = 0;
+ if (end) {
+ int skippedLines = 0;
+ char *tempPoint;
+
+ /* get current lineno */
+ IDL_file_get(NULL,(int *)&data->lineno);
+
+ /* get line count */
+ for (tempPoint = data->point; tempPoint < end; tempPoint++) {
+ if (*tempPoint == '\n')
+ skippedLines++;
+ }
+
+ data->lineno += skippedLines;
+ IDL_file_set(data->filename, (int)data->lineno);
+
+ *startp = end + 2;
+
+ /* If it's a ** comment, tell libIDL about it. */
+ if (data->point[2] == '*') {
+ /* hack termination. +2 to get past '*' '/' */
+ char t = *(end + 2);
+ *(end + 2) = '\0';
+ IDL_queue_new_ident_comment(data->point);
+ *(end + 2) = t;
+ }
+
+ data->point = *startp; /* XXXmccabe move this out of function? */
+ return 1;
+ } else {
+ const char *filename;
+ int lineno;
+
+ IDL_file_get(&filename, &lineno);
+ msg_callback(IDL_ERROR, 0, lineno, filename,
+ "unterminated comment");
+ return -1;
+ }
+}
+
+static int
+NextIsInclude(input_callback_state *callback_state, char **startp,
+ int *lenp)
+{
+ input_data *data = callback_state->input_stack;
+ input_data *new_data;
+ char *filename, *end;
+ const char *scratch;
+
+ /* process the #include that we're in now */
+ if (strncmp(data->point, "#include \"", 10)) {
+ return 0;
+ }
+
+ filename = data->point + 10; /* skip #include " */
+ XPT_ASSERT(filename < data->max);
+ end = filename;
+ while (end < data->max) {
+ if (*end == '\"' || *end == '\n' || *end == '\r')
+ break;
+ end++;
+ }
+
+ if (*end != '\"') {
+ /*
+ * Didn't find end of include file. Scan 'til next whitespace to find
+ * some reasonable approximation of the filename, and use it to report
+ * an error.
+ */
+
+ end = filename;
+ while (end < data->max) {
+ if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t')
+ break;
+ end++;
+ }
+ *end = '\0';
+
+ /* make sure we have accurate line info */
+ IDL_file_get(&scratch, (int *)&data->lineno);
+ fprintf(stderr,
+ "%s:%u: didn't find end of quoted include name \"%s\n",
+ scratch, data->lineno, filename);
+ return -1;
+ }
+
+ *end = '\0';
+ *startp = end + 1;
+
+ if (data->next == NULL) {
+ /*
+ * If we're in the initial file, add this filename to the list
+ * of filenames to be turned into #include "filename.h"
+ * directives in xpidl_header.c. We do it here rather than in the
+ * block below so it still gets added to the list even if it's
+ * already been recursively included from some other file.
+ */
+ char *filename_cp = xpidl_strdup(filename);
+
+ /* note that g_slist_append accepts and likes null as list-start. */
+ callback_state->base_includes =
+ g_slist_append(callback_state->base_includes, filename_cp);
+ }
+
+ /* store offset for when we pop, or if we skip this one */
+ data->point = *startp;
+
+ if (!g_hash_table_lookup(callback_state->already_included, filename)) {
+ filename = xpidl_strdup(filename);
+ g_hash_table_insert(callback_state->already_included,
+ filename, (void *)TRUE);
+ new_data = new_input_data(filename, callback_state->include_path);
+ if (!new_data) {
+ char *error_message;
+ IDL_file_get(&scratch, (int *)&data->lineno);
+ error_message =
+ g_strdup_printf("can't open included file %s for reading\n",
+ filename);
+ msg_callback(IDL_ERROR, 0,
+ data->lineno, scratch, error_message);
+ g_free(error_message);
+ return -1;
+ }
+
+ new_data->next = data;
+ /* tell libIDL to exclude this IDL from the toplevel tree */
+ IDL_inhibit_push();
+ IDL_file_get(&scratch, (int *)&data->lineno);
+ callback_state->input_stack = new_data;
+ IDL_file_set(new_data->filename, (int)new_data->lineno);
+ }
+
+ *lenp = 0; /* this is magic, see the comment below */
+ return 1;
+}
+
+static void
+FindSpecial(input_data *data, char **startp, int *lenp)
+{
+ char *point = data->point;
+
+ /* magic sequences are:
+ * "%{" raw block
+ * "/\*" comment
+ * "#include \"" include
+ * The first and last want a newline [\r\n] before, or the start of the
+ * file.
+ */
+
+#define LINE_START(data, point) (point == data->buf || \
+ (point > data->point && \
+ (point[-1] == '\r' || point[-1] == '\n')))
+
+ while (point < data->max) {
+ if (point[0] == '/' && point[1] == '*')
+ break;
+ if (LINE_START(data, point)) {
+ if (point[0] == '%' && point[1] == '{')
+ break;
+ if (point[0] == '#' && !strncmp(point + 1, "include \"", 9))
+ break;
+ }
+ point++;
+ }
+
+#undef LINE_START
+
+ *startp = data->point;
+ *lenp = point - data->point;
+}
+
+/* set this with a debugger to see exactly what libIDL sees */
+static FILE *tracefile;
+
+static int
+input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
+ gpointer user_data)
+{
+ input_callback_state *callback_state = user_data;
+ input_data *data = callback_state->input_stack;
+ input_data *new_data = NULL;
+ unsigned int len, copy;
+ int rv;
+ char *start;
+
+ switch(reason) {
+ case IDL_INPUT_REASON_INIT:
+ if (data == NULL || data->next == NULL) {
+ /*
+ * This is the first file being processed. As it's the target
+ * file, we only look for it in the first entry in the include
+ * path, which we assume to be the current directory.
+ */
+
+ /* XXXmccabe proper assumption? Do we handle files in other
+ directories? */
+
+ IncludePathEntry first_entry;
+
+ first_entry.directory = callback_state->include_path->directory;
+ first_entry.next = NULL;
+
+ new_data = new_input_data(cb_data->init.filename,
+ &first_entry);
+ } else {
+ new_data = new_input_data(cb_data->init.filename,
+ callback_state->include_path);
+ }
+
+ if (!new_data)
+ return -1;
+
+ IDL_file_set(new_data->filename, (int)new_data->lineno);
+ callback_state->input_stack = new_data;
+ return 0;
+
+ case IDL_INPUT_REASON_FILL:
+ start = NULL;
+ len = 0;
+
+ while (data->point >= data->max) {
+ if (!data->next)
+ return 0;
+
+ /* Current file is done; revert to including file */
+ callback_state->input_stack = data->next;
+ free(data->filename);
+ free(data->buf);
+ free(data);
+ data = callback_state->input_stack;
+
+ IDL_file_set(data->filename, (int)data->lineno);
+ IDL_inhibit_pop();
+ }
+
+ /*
+ * Now we scan for sequences which require special attention:
+ * \n#include begins an include statement
+ * \n%{ begins a raw-source block
+ * /\* begins a comment
+ *
+ * We used to be fancier here, so make sure that we sent the most
+ * data possible at any given time. To that end, we skipped over
+ * \n%{ raw \n%} blocks and then _continued_ the search for special
+ * sequences like \n#include or /\* comments .
+ *
+ * It was really ugly, though -- liberal use of goto! lots of implicit
+ * state! what fun! -- so now we just do this:
+ *
+ * if (special at start) {
+ * process that special -
+ * - raw: send it to libIDL, and don't look inside for specials
+ * - comments: adjust point and start over
+ * - includes: push new input_data struct for included file, and
+ * start over
+ * } else {
+ * scan for next special
+ * send data up to that special to libIDL
+ * }
+ *
+ * If len is set to zero, it is a sentinel value indicating we a comment
+ * or include was found, and parsing should start over.
+ *
+ * XXX const string foo = "/\*" will just screw us horribly.
+ * Hm but. We could treat strings as we treat raw blocks, eh?
+ */
+
+ /*
+ * Order is important, so that you can have /\* comments and
+ * #includes within raw sections, and so that you can comment out
+ * #includes.
+ */
+ rv = NextIsRaw(data, &start, (int *)&len);
+ if (rv == -1) return -1;
+ if (!rv) {
+ /*
+ * When NextIsComment succeeds, it returns a 0 len (requesting a
+ * restart) and adjusts data->point to pick up after the comment.
+ */
+ rv = NextIsComment(data, &start, (int *)&len);
+ if (rv == -1) return -1;
+ if (!rv) {
+ /*
+ * NextIsInclude might push a new input_data struct; if so, it
+ * will return a 0 len, letting the callback pick up the new
+ * file the next time around.
+ */
+ rv = NextIsInclude(callback_state, &start, (int *)&len);
+ if (rv == -1) return -1;
+ if (!rv)
+ FindSpecial(data, &start, (int *)&len);
+ }
+ }
+
+ if (len == 0) {
+ /*
+ * len == 0 is a sentinel value that means we found a comment or
+ * include. If we found a comment, point has been adjusted to
+ * point past the comment. If we found an include, a new input_data
+ * has been pushed. In both cases, calling the input_callback again
+ * will pick up the new state.
+ */
+ return input_callback(reason, cb_data, user_data);
+ }
+
+ copy = MIN(len, (unsigned int) cb_data->fill.max_size);
+ memcpy(cb_data->fill.buffer, start, copy);
+ data->point = start + copy;
+
+ if (tracefile)
+ fwrite(cb_data->fill.buffer, copy, 1, tracefile);
+
+ return copy;
+
+ case IDL_INPUT_REASON_ABORT:
+ case IDL_INPUT_REASON_FINISH:
+ while (data != NULL) {
+ input_data *next;
+
+ next = data->next;
+ free(data->filename);
+ free(data->buf);
+ free(data);
+ data = next;
+ }
+ return 0;
+
+ default:
+ g_error("unknown input reason %d!", reason);
+ return -1;
+ }
+}
+
+static void
+free_ghash_key(gpointer key, gpointer value, gpointer user_data)
+{
+ /* We're only storing TRUE in the value... */
+ free(key);
+}
+
+static void
+free_gslist_data(gpointer data, gpointer user_data)
+{
+ free(data);
+}
+
+/* Pick up unlink. */
+#ifdef XP_UNIX
+#include <unistd.h>
+#elif XP_WIN
+/* We get it from stdio.h. */
+#endif
+
+int
+xpidl_process_idl(char *filename, IncludePathEntry *include_path,
+ char *file_basename, ModeData *mode)
+{
+ char *tmp, *outname, *real_outname = NULL;
+ IDL_tree top;
+ TreeState state;
+ int rv;
+ input_callback_state callback_state;
+ gboolean ok = TRUE;
+ backend *emitter;
+
+ callback_state.input_stack = NULL;
+ callback_state.base_includes = NULL;
+ callback_state.include_path = include_path;
+ callback_state.already_included = g_hash_table_new(g_str_hash, g_str_equal);
+
+ if (!callback_state.already_included) {
+ fprintf(stderr, "failed to create hashtable. out of memory?\n");
+ return 0;
+ }
+
+ state.basename = xpidl_strdup(filename);
+
+ /* if basename has an .extension, truncate it. */
+ tmp = strrchr(state.basename, '.');
+ if (tmp)
+ *tmp = '\0';
+
+ if (!file_basename)
+ outname = xpidl_strdup(state.basename);
+ else
+ outname = xpidl_strdup(file_basename);
+
+ /* so we don't include it again! */
+ g_hash_table_insert(callback_state.already_included,
+ xpidl_strdup(filename), (void *)TRUE);
+
+ parsed_empty_file = FALSE;
+
+ rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state,
+ msg_callback, &top,
+ &state.ns,
+ IDLF_IGNORE_FORWARDS |
+ IDLF_XPIDL,
+ enable_warnings ? IDL_WARNING1 :
+ IDL_ERROR);
+ if (parsed_empty_file) {
+ /*
+ * If we've detected (via hack in msg_callback) that libIDL returned
+ * failure because it found a file with no IDL, set the parse tree to
+ * null and proceed. Allowing this is useful to permit .idl files that
+ * collect #includes.
+ */
+ top = NULL;
+ state.ns = NULL;
+ } else if (rv != IDL_SUCCESS) {
+ if (rv == -1) {
+ g_warning("Parse of %s failed: %s", filename, g_strerror(errno));
+ } else {
+ g_warning("Parse of %s failed", filename);
+ }
+ return 0;
+ }
+
+ state.basename = xpidl_strdup(filename);
+ tmp = strrchr(state.basename, '.');
+ if (tmp)
+ *tmp = '\0';
+
+ /* so xpidl_header.c can use it to generate a list of #include directives */
+ state.base_includes = callback_state.base_includes;
+
+ emitter = mode->factory();
+ state.dispatch = emitter->dispatch_table;
+
+ if (strcmp(outname, "-")) {
+ const char *fopen_mode;
+ char *out_basename;
+
+ /* explicit_output_filename can't be true without a filename */
+ if (explicit_output_filename) {
+ real_outname = g_strdup(outname);
+ } else {
+/*
+ *This combination seems a little strange, what about OS/2?
+ * Assume it's some build issue
+ */
+#if defined(XP_UNIX) || defined(XP_WIN)
+ if (!file_basename) {
+ out_basename = xpidl_basename(outname);
+ } else {
+ out_basename = outname;
+ }
+#else
+ out_basename = outname;
+#endif
+ real_outname = g_strdup_printf("%s.%s", out_basename, mode->suffix);
+ if (out_basename != outname)
+ g_free(out_basename);
+ }
+
+ /* Use binary write for typelib mode */
+ fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb";
+ state.file = fopen(real_outname, fopen_mode);
+ if (!state.file) {
+ perror("error opening output file");
+ return 0;
+ }
+ } else {
+ state.file = stdout;
+ }
+ state.tree = top;
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ state.real_outname = real_outname;
+#endif
+
+ if (emitter->emit_prolog)
+ emitter->emit_prolog(&state);
+ if (state.tree) /* Only if we have a tree to process. */
+ ok = xpidl_process_node(&state);
+ if (emitter->emit_epilog)
+ emitter->emit_epilog(&state);
+
+ if (state.file != stdout)
+ fclose(state.file);
+ free(state.basename);
+ free(outname);
+ g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL);
+ g_hash_table_destroy(callback_state.already_included);
+ g_slist_foreach(callback_state.base_includes, free_gslist_data, NULL);
+
+ if (state.ns)
+ IDL_ns_free(state.ns);
+ if (top)
+ IDL_tree_free(top);
+
+ if (real_outname != NULL) {
+ /*
+ * Delete partial output file on failure. (Mac does this in the plugin
+ * driver code, if the compiler returns failure.)
+ */
+#if defined(XP_UNIX) || defined(XP_WIN)
+ if (!ok)
+ unlink(real_outname);
+#endif
+ g_free(real_outname);
+ }
+
+ return ok;
+}
+
+/*
+ * Our own version of IDL_tree_warning, which we use when IDL_tree_warning
+ * would crash on us.
+ */
+void
+xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char *msg, *file;
+ int lineno;
+
+ /* XXX need to check against __IDL_max_msg_level, no accessor */
+ va_start(ap, fmt);
+ msg = g_strdup_vprintf(fmt, ap);
+
+ if (p) {
+ file = p->_file;
+ lineno = p->_line;
+ } else {
+ file = NULL;
+ lineno = 0;
+ }
+
+ /* call our message callback, like IDL_tree_warning would */
+ msg_callback(level, 0, lineno, file, msg);
+ g_free(msg);
+ va_end(ap);
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c
new file mode 100644
index 00000000..4f708027
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c
@@ -0,0 +1,1053 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Sun Microsystems,
+ * Inc. Portions created by Sun are
+ * Copyright (C) 1999 Sun Microsystems, Inc. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Allen (michael.allen@sun.com)
+ * Frank Mitchell (frank.mitchell@sun.com)
+ */
+
+/*
+ * Generate Java interfaces from XPIDL.
+ */
+
+#include "xpidl.h"
+#include <ctype.h>
+#include <glib.h>
+
+
+struct java_priv_data {
+ GHashTable *typedefTable;
+};
+
+#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable)
+
+static gboolean
+write_classname_iid_define(FILE *file, const char *className)
+{
+ const char *iidName;
+ if (className[0] == 'n' && className[1] == 's') {
+ /* backcompat naming styles */
+ fputs("NS_", file);
+ iidName = className + 2;
+ } else {
+ iidName = className;
+ }
+
+ while (*iidName) {
+ fputc(toupper(*iidName++), file);
+ }
+
+ fputs("_IID", file);
+ return TRUE;
+}
+
+static gboolean
+java_prolog(TreeState *state)
+{
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ const char *basename;
+ const char *ext;
+#endif
+
+ state->priv = calloc(1, sizeof(struct java_priv_data));
+ if (!state->priv)
+ return FALSE;
+ TYPEDEFS(state) = 0;
+ TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!TYPEDEFS(state)) {
+ /* XXX report error */
+ free(state->priv);
+ return FALSE;
+ }
+
+ /*
+ * First pass
+ */
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ basename = xpidl_basename(state->real_outname ? state->real_outname : state->basename);
+ ext = strrchr(basename, '.');
+ if (!ext)
+ ext = strchr(basename, '\0');
+ fprintf(state->file,
+ "/**\n"
+ " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n"
+ " * FOR THE FULL DOCUMENTATION AND LICENSE.\n"
+ " *\n"
+ " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=interface+%.*s\">\n"
+ " **/\n"
+ "\n"
+ "package org.mozilla.interfaces;\n\n"
+ "import java.math.BigInteger;\n\n"
+ "\n"
+ , ext - basename >= 19 ? 19 : (int)(ext - basename), basename);
+ g_free(basename);
+#else
+ fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
+ state->file);
+
+ fprintf(state->file,
+ " *\n * This file was automatically generated from %s.idl.\n",
+ state->basename);
+
+ fputs(" */\n\n", state->file);
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+java_epilog(TreeState *state)
+{
+ /* points to other elements of the tree, so just destroy the table */
+ g_hash_table_destroy(TYPEDEFS(state));
+ free(state->priv);
+ state->priv = NULL;
+
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ /*
+ * Last pass
+ */
+
+ fprintf(state->file, "\n/*\n * end\n */\n");
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+forward_declaration(TreeState *state)
+{
+ /*
+ * Java doesn't need forward declarations unless the declared
+ * class resides in a different package.
+ */
+#if 0
+ IDL_tree iface = state->tree;
+ const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
+ const char *pkgName = "org.mozilla.xpcom";
+ if (!className)
+ return FALSE;
+ /* XXX: Get package name and compare */
+ fprintf(state->file, "import %s.%s;\n", pkgName, className);
+#endif
+ return TRUE;
+}
+
+
+static gboolean
+interface_declaration(TreeState *state)
+{
+ IDL_tree interface = state->tree;
+ IDL_tree iterator = NULL;
+ char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
+ const char *iid = NULL;
+
+ if (!verify_interface_declaration(interface))
+ return FALSE;
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ /*
+ * Write out JavaDoc comment
+ */
+
+ fprintf(state->file, "\n/**\n * Interface %s\n", interface_name);
+#endif
+
+#ifndef LIBIDL_MAJOR_VERSION
+ iid = IDL_tree_property_get(interface, "uuid");
+#else
+ iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid");
+#endif
+
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ if (iid != NULL) {
+ fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid);
+ } else {
+ fputs(" */\n\n", state->file);
+ }
+#endif
+
+ /*
+ * Write "public interface <foo>"
+ */
+
+ fprintf(state->file, "public interface %s ", interface_name);
+
+ /*
+ * Check for inheritence, and iterator over the inherited names,
+ * if any.
+ */
+
+ if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
+ fputs("extends ", state->file);
+
+ do {
+
+ fprintf(state->file, "%s",
+ IDL_IDENT(IDL_LIST(iterator).data).str);
+
+ if (IDL_LIST(iterator).next) {
+ fputs(", ", state->file);
+ }
+ } while ((iterator = IDL_LIST(iterator).next));
+
+ }
+
+ fputs("\n{\n", state->file);
+
+ if (iid) {
+ /*
+ * Write interface constants for IID
+ */
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" public static final String ", state->file);
+#else
+ fputs(" public static final String ", state->file);
+#endif
+
+ /* XXX s.b just "IID" ? */
+ if (!write_classname_iid_define(state->file, interface_name)) {
+ return FALSE;
+ }
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs(" =\n \"{", state->file);
+ while (*iid) {
+ fputc(tolower(*iid++), state->file);
+ }
+ fputs("}\";\n", state->file);
+
+#else
+ fprintf(state->file, "_STRING =\n \"%s\";\n\n", iid);
+
+ fputs(" public static final nsID ", state->file);
+
+ /* XXX s.b just "IID" ? */
+ if (!write_classname_iid_define(state->file, interface_name)) {
+ return FALSE;
+ }
+
+ fprintf(state->file, " =\n new nsID(\"%s\");\n\n", iid);
+#endif
+ }
+
+ /*
+ * Advance the state of the tree, go on to process more
+ */
+
+ state->tree = IDL_INTERFACE(interface).body;
+
+ if (state->tree && !xpidl_process_node(state)) {
+ return FALSE;
+ }
+
+
+ fputs("\n}\n", state->file);
+
+ return TRUE;
+}
+
+static gboolean
+process_list(TreeState *state)
+{
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ /* To make the diffing simple, group the constants, methods and attributes. */
+ IDL_tree list = state->tree;
+ IDL_tree iter;
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_CONST_DCL) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_ATTR_DCL) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_OP_DCL) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if ( IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_CONST_DCL
+ && IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_OP_DCL
+ && IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_ATTR_DCL ) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+
+#else
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+#endif
+ return TRUE;
+}
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+static gboolean
+interface_declaration_wrapper(TreeState *state)
+{
+ IDL_tree interface = state->tree;
+ char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
+ FILE *org_file = state->file;
+ char *org_name = state->real_outname;
+ void *org_priv = state->priv;
+ gboolean rc;
+
+ /*
+ * Skip non-scriptable interfaces.
+ */
+ if ( !IDL_tree_property_get(IDL_INTERFACE(interface).ident, "scriptable")
+ && strcmp(interface_name, "nsIAppShell") )
+ return TRUE;
+
+ /*
+ * GROSS HACK: If the interface isn't the same as the file name,
+ * temporarily switch output file.
+ */
+ if (state->real_outname) {
+ const char *basename = xpidl_basename(state->real_outname);
+ const char *ext = strrchr(basename, '.');
+ if ( ext
+ && !strcmp(ext, ".java")
+ && ( strncmp(interface_name, basename, ext - basename)
+ || interface_name[ext - basename] != '.') ) {
+ size_t needed = strlen(state->real_outname) + strlen(interface_name) + strlen(".java") + 4;
+ char *tmp = malloc(needed);
+ if (basename != state->real_outname)
+ sprintf(tmp,"%.*s/%s.java", (int)(basename - state->real_outname - 1), state->real_outname, interface_name);
+ else
+ sprintf(tmp,"%s.java", interface_name);
+ state->file = fopen(tmp, "w");
+ if (!state->file) {
+ perror("error opening output file");
+ state->file = org_file;
+ free(tmp);
+ return FALSE;
+ }
+ state->real_outname = tmp;
+ java_prolog(state);
+ }
+ g_free(basename);
+ }
+
+ rc = interface_declaration(state);
+
+ if (state->file != org_file) {
+ java_epilog(state);
+ fclose(state->file);
+ free(state->real_outname);
+ state->file = org_file;
+ state->real_outname = org_name;
+ state->priv = org_priv;
+ }
+ return rc;
+}
+#endif /* VBOX_XPIDL_EMULATE_GENJIFACES */
+
+static gboolean
+xpcom_to_java_type (TreeState *state)
+{
+ if (!state->tree) {
+ fputs("Object", state->file);
+ return TRUE;
+ }
+
+ switch(IDL_NODE_TYPE(state->tree)) {
+
+ case IDLN_TYPE_INTEGER: {
+
+ switch(IDL_TYPE_INTEGER(state->tree).f_type) {
+
+ case IDL_INTEGER_TYPE_SHORT:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_TYPE_INTEGER(state->tree).f_signed)
+ fputs("short", state->file);
+ else
+ fputs("int", state->file);
+#else
+ fputs("short", state->file);
+#endif
+ break;
+
+ case IDL_INTEGER_TYPE_LONG:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_TYPE_INTEGER(state->tree).f_signed)
+ fputs("int", state->file);
+ else
+ fputs("long", state->file);
+#else
+ fputs("int", state->file);
+#endif
+ break;
+
+ case IDL_INTEGER_TYPE_LONGLONG:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_TYPE_INTEGER(state->tree).f_signed)
+ fputs("long", state->file);
+ else
+ fputs("double", state->file);
+#else
+ fputs("long", state->file);
+#endif
+ break;
+
+ default:
+ g_error(" Unknown integer type: %d\n",
+ IDL_TYPE_INTEGER(state->tree).f_type);
+ return FALSE;
+
+ }
+
+ break;
+ }
+
+ case IDLN_TYPE_CHAR:
+ case IDLN_TYPE_WIDE_CHAR:
+ fputs("char", state->file);
+ break;
+
+ case IDLN_TYPE_WIDE_STRING:
+ case IDLN_TYPE_STRING:
+ fputs("String", state->file);
+ break;
+
+ case IDLN_TYPE_BOOLEAN:
+ fputs("boolean", state->file);
+ break;
+
+ case IDLN_TYPE_OCTET:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("short", state->file);
+#else
+ fputs("byte", state->file);
+#endif
+ break;
+
+ case IDLN_TYPE_FLOAT:
+ switch(IDL_TYPE_FLOAT(state->tree).f_type) {
+
+ case IDL_FLOAT_TYPE_FLOAT:
+ fputs("float", state->file);
+ break;
+
+ case IDL_FLOAT_TYPE_DOUBLE:
+ fputs("double", state->file);
+ break;
+
+ default:
+ g_error(" Unknown floating point typ: %d\n",
+ IDL_NODE_TYPE(state->tree));
+ break;
+ }
+ break;
+
+
+ case IDLN_IDENT:
+ if (IDL_NODE_UP(state->tree) &&
+ IDL_NODE_TYPE(IDL_NODE_UP(state->tree)) == IDLN_NATIVE) {
+ const char *user_type = IDL_NATIVE(IDL_NODE_UP(state->tree)).user_type;
+ if (strcmp(user_type, "void") == 0) {
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("nsISupports", state->file);
+#else
+ fputs("Object", state->file);
+#endif
+ }
+ else if (strcmp(user_type, "nsID") == 0 ||
+ strcmp(user_type, "nsIID") == 0 ||
+ strcmp(user_type, "nsCID") == 0) {
+ /* XXX: s.b test for "iid" attribute */
+ /* XXX: special class for nsIDs */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("String", state->file);
+#else
+ fputs("nsID", state->file);
+#endif
+ }
+ else {
+ /* XXX: special class for opaque types */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("String", state->file);
+#else
+ fputs("OpaqueValue", state->file);
+#endif
+ }
+ } else {
+ const char *ident_str = IDL_IDENT(state->tree).str;
+
+ /* XXX: big kludge; s.b. way to match to typedefs */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (strcmp(ident_str, "PRInt8") == 0) {
+ fputs("byte", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt16") == 0 ||
+ strcmp(ident_str, "PRUint8") == 0) {
+ fputs("short", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt32") == 0 ||
+ strcmp(ident_str, "PRUint16") == 0) {
+ fputs("int", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt64") == 0 ||
+ strcmp(ident_str, "PRUint32") == 0 ||
+ strcmp(ident_str, "PRThreadPriority") == 0 ||
+ strcmp(ident_str, "PRThreadScope") == 0 ||
+ strcmp(ident_str, "PRThreadState") == 0) {
+ fputs("long", state->file);
+ }
+ else if (strcmp(ident_str, "PRUint64") == 0) {
+ fputs("double", state->file);
+ }
+#else
+ if (strcmp(ident_str, "PRInt8") == 0 ||
+ strcmp(ident_str, "PRUint8") == 0) {
+ fputs("byte", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt16") == 0 ||
+ strcmp(ident_str, "PRUint16") == 0) {
+ fputs("short", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt32") == 0 ||
+ strcmp(ident_str, "PRUint32") == 0) {
+ fputs("int", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt64") == 0 ||
+ strcmp(ident_str, "PRUint64") == 0) {
+ fputs("long", state->file);
+ }
+#endif
+ else if (strcmp(ident_str, "PRBool") == 0) {
+ fputs("boolean", state->file);
+ }
+ else if (strcmp(ident_str, "nsrefcnt") == 0) {
+ fputs("int", state->file);
+ }
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /* XXX: Use find_underlying_type instead? */
+ else if ( strcmp(ident_str, "nsresult") == 0
+ || strcmp(ident_str, "size_t") == 0) {
+ fputs("long", state->file);
+ }
+ else if ( strcmp(ident_str, "PRTime") == 0) {
+ fputs("double", state->file);
+ }
+ /* In Javaconnect, we handle weak references internally; no need for the
+ |nsIWeakReference| interface. So just return |nsISupports|. */
+ else if (strcmp(ident_str, "nsIWeakReference") == 0) {
+ fputs("nsISupports", state->file);
+ }
+#endif
+ else {
+ IDL_tree real_type =
+ g_hash_table_lookup(TYPEDEFS(state), ident_str);
+
+ if (real_type) {
+ IDL_tree orig_tree = state->tree;
+
+ state->tree = real_type;
+ xpcom_to_java_type(state);
+
+ state->tree = orig_tree;
+ }
+ else {
+ fputs(ident_str, state->file);
+ }
+ }
+ }
+
+ break;
+
+ case IDLN_TYPE_ENUM:
+ case IDLN_TYPE_OBJECT:
+ default:
+ g_error(" Unknown type: %d\n",
+ IDL_TYPE_FLOAT(state->tree).f_type);
+ break;
+ }
+
+ return TRUE;
+
+}
+
+static gboolean
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+xpcom_to_java_param(TreeState *state, unsigned nparam)
+#else
+xpcom_to_java_param(TreeState *state)
+#endif
+{
+ IDL_tree param = state->tree;
+ state->tree = IDL_PARAM_DCL(param).param_type_spec;
+
+ /*
+ * Put in type of parameter
+ */
+
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+
+ /*
+ * If the parameter is out or inout, make it a Java array of the
+ * appropriate type
+ */
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /* XXX: Causes nsILineInputStream::readLine(String[] arg1) where genjifaces drops the []. */
+#endif
+ if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
+ fputs("[]", state->file);
+ }
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /*XXX: nsIConsoleService::getMessageArray ends up with [][] arg1... */
+ /*else*/ if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array")) {
+ fputs("[]", state->file);
+ }
+#endif
+
+ /*
+ * Put in name of parameter
+ */
+
+ fputc(' ', state->file);
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fprintf(state->file, "arg%u", nparam+1);
+#else
+ fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file);
+#endif
+
+ return TRUE;
+}
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+static gboolean is_java_keyword(char ch0, const char *name)
+{
+ static const char * const kJavaKeywords[] = {
+ "abstract", "default", "if" , "private" , "this" ,
+ "boolean" , "do" , "implements", "protected" , "throw" ,
+ "break" , "double" , "import", "public" , "throws" ,
+ "byte" , "else" , "instanceof", "return" , "transient",
+ "case" , "extends", "int" , "short" , "try" ,
+ "catch" , "final" , "interface" , "static" , "void" ,
+ "char" , "finally", "long" , "strictfp" , "volatile" ,
+ "class" , "float" , "native" , "super" , "while" ,
+ "const" , "for" , "new" , "switch" ,
+ "continue", "goto" , "package" , "synchronized",
+ "assert" , /* added in Java 1.4 */
+ "enum" , /* added in Java 5.0 */
+ "clone" , /* clone is a member function of java.lang.Object */
+ "finalize" /* finalize is a member function of java.lang.Object */
+ };
+ unsigned i;
+ for (i = 0; i < sizeof(kJavaKeywords) / sizeof(kJavaKeywords[0]); i++) {
+ if (kJavaKeywords[i][0] == ch0 && !strcmp(&kJavaKeywords[i][1], &name[1])) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#endif
+
+static gboolean
+type_declaration(TreeState *state)
+{
+ /*
+ * Unlike C, Java has no type declaration directive.
+ * Instead, we record the mapping, and look up the actual type
+ * when needed.
+ */
+ IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
+ IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
+
+ /* XXX: check for illegal types */
+
+ g_hash_table_insert(TYPEDEFS(state),
+ IDL_IDENT(IDL_LIST(dcls).data).str,
+ type);
+
+ return TRUE;
+}
+
+static gboolean
+method_declaration(TreeState *state)
+{
+ /* IDL_tree method_tree = state->tree; */
+ struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree);
+ gboolean method_notxpcom =
+ (IDL_tree_property_get(method->ident, "notxpcom") != NULL);
+ gboolean method_noscript =
+ (IDL_tree_property_get(method->ident, "noscript") != NULL);
+ IDL_tree iterator = NULL;
+ IDL_tree retval_param = NULL;
+ const char *method_name = IDL_IDENT(method->ident).str;
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ unsigned nparam = 0;
+#endif
+
+ if (!verify_method_declaration(state->tree))
+ return FALSE;
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /*
+ * Skip most (todo) non-scriptable and not-xpcom methods.
+ */
+ if (method_noscript || method_notxpcom) {
+ return TRUE;
+ }
+#endif
+
+ fputc('\n', state->file);
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ xpidl_write_comment(state, 4);
+#endif
+
+ /*
+ * Write beginning of method declaration
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" ", state->file);
+#else
+ fputs(" ", state->file);
+#endif
+ if (!method_noscript) {
+ /* Nonscriptable methods become package-protected */
+ fputs("public ", state->file);
+ }
+
+ /*
+ * Write return type
+ * Unlike C++ headers, Java interfaces return the declared
+ * return value; an exception indicates XPCOM method failure.
+ */
+ if (method_notxpcom || method->op_type_spec) {
+ state->tree = method->op_type_spec;
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+ } else {
+ /* Check for retval attribute */
+ for (iterator = method->parameter_dcls; iterator != NULL;
+ iterator = IDL_LIST(iterator).next) {
+
+ IDL_tree original_tree = state->tree;
+
+ state->tree = IDL_LIST(iterator).data;
+
+ if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
+ "retval")) {
+ retval_param = iterator;
+
+ state->tree = IDL_PARAM_DCL(state->tree).param_type_spec;
+
+ /*
+ * Put in type of parameter
+ */
+
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_tree_property_get(IDL_PARAM_DCL(IDL_LIST(iterator).data).simple_declarator, "array")) {
+ fputs("[]", state->file);
+ }
+#endif
+ }
+
+ state->tree = original_tree;
+ }
+
+ if (retval_param == NULL) {
+ fputs("void", state->file);
+ }
+ }
+
+ /*
+ * Write method name
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (is_java_keyword(tolower(method_name[0]), method_name)) {
+ fprintf(state->file, " %c%s_(", tolower(method_name[0]), method_name + 1);
+ } else {
+ fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
+ }
+#else
+ fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
+#endif
+
+ /*
+ * Write parameters
+ */
+ for (iterator = method->parameter_dcls; iterator != NULL;
+ iterator = IDL_LIST(iterator).next) {
+
+ /* Skip "retval" */
+ if (iterator == retval_param) {
+ continue;
+ }
+
+ if (iterator != method->parameter_dcls) {
+ fputs(", ", state->file);
+ }
+
+ state->tree = IDL_LIST(iterator).data;
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ if (!xpcom_to_java_param(state, nparam++)) {
+#else
+ if (!xpcom_to_java_param(state)) {
+#endif
+ return FALSE;
+ }
+ }
+
+ fputs(")", state->file);
+
+ if (method->raises_expr) {
+ IDL_tree iter = method->raises_expr;
+ IDL_tree dataNode = IDL_LIST(iter).data;
+
+ fputs(" throws ", state->file);
+ fputs(IDL_IDENT(dataNode).str, state->file);
+ iter = IDL_LIST(iter).next;
+
+ while (iter) {
+ dataNode = IDL_LIST(iter).data;
+ fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
+ iter = IDL_LIST(iter).next;
+ }
+ }
+
+ fputs(";\n", state->file);
+
+ return TRUE;
+
+}
+
+
+static gboolean
+constant_declaration(TreeState *state)
+{
+ struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree);
+ const char *name = IDL_IDENT(declaration->ident).str;
+ IDL_tree real_type;
+
+ if (!verify_const_declaration(state->tree))
+ return FALSE;
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(declaration->const_type);
+ real_type = real_type ? real_type : declaration->const_type;
+
+ fputc('\n', state->file);
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ xpidl_write_comment(state, 4);
+#endif
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+# ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" public static final ", state->file);
+# else
+ fputs(" public static final ", state->file);
+# endif
+ if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) {
+ if (IDL_TYPE_INTEGER(real_type).f_signed)
+ fprintf(state->file, "int %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ else
+ fprintf(state->file, "long %s = %" IDL_LL "uL;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ } else {
+ if (IDL_TYPE_INTEGER(real_type).f_signed)
+ fprintf(state->file, "short %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ else
+ fprintf(state->file, "int %s = %" IDL_LL "u;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ }
+#else /* !VBOX_XPIDL_EMULATE_GENJIFACES */
+ fprintf(state->file, " public static final %s %s = %d;\n",
+ (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG
+ ? "long" : "short"),
+ name, (int) IDL_INTEGER(declaration->const_exp).value);
+#endif /* !VBOX_XPIDL_EMULATE_GENJIFACES */
+
+ return TRUE;
+
+}
+
+#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data))
+#define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)
+#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec)
+
+
+static gboolean
+attribute_declaration(TreeState *state)
+{
+ gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
+ char *attribute_name = ATTR_IDENT(state->tree).str;
+
+ gboolean method_noscript =
+ (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL);
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /*
+ * Skip most non-scriptable attributes.
+ */
+ if (method_noscript) {
+ return TRUE;
+ }
+#endif
+
+#if 0
+ /*
+ * Disabled here because I can't verify this check against possible
+ * users of the java xpidl backend.
+ */
+ if (!verify_attribute_declaration(state->tree))
+ return FALSE;
+#endif
+
+ /* Comment */
+ fputc('\n', state->file);
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ xpidl_write_comment(state, 4);
+#endif
+
+ state->tree = ATTR_TYPE_DECL(state->tree);
+
+ /*
+ * Write access permission ("public" unless nonscriptable)
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" ", state->file);
+#else
+ fputs(" ", state->file);
+#endif
+ if (!method_noscript) {
+ fputs("public ", state->file);
+ }
+
+ /*
+ * Write the proper Java return value for the get operation
+ */
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+
+ /*
+ * Write the name of the accessor ("get") method.
+ */
+ fprintf(state->file, " get%c%s();\n",
+ toupper(attribute_name[0]), attribute_name + 1);
+
+
+ if (!read_only) {
+ /* Nonscriptable methods become package-protected */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs("\n ", state->file);
+#else
+ fputs(" ", state->file);
+#endif
+ if (!method_noscript) {
+ fputs("public ", state->file);
+ }
+
+ /*
+ * Write attribute access method name and return type
+ */
+ fprintf(state->file, "void set%c%s(",
+ toupper(attribute_name[0]),
+ attribute_name+1);
+
+ /*
+ * Write the proper Java type for the set operation
+ */
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+
+ /*
+ * Write the name of the formal parameter.
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" arg1);\n", state->file);
+#else
+ fputs(" value);\n", state->file);
+#endif
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+enum_declaration(TreeState *state)
+{
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "enums not supported, enum \'%s\' ignored",
+ IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
+ return TRUE;
+}
+
+backend *
+xpidl_java_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = java_prolog;
+ result.emit_epilog = java_epilog;
+
+ if (!initialized) {
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ table[IDLN_INTERFACE] = interface_declaration_wrapper;
+#else
+ table[IDLN_INTERFACE] = interface_declaration;
+#endif
+ table[IDLN_LIST] = process_list;
+
+ table[IDLN_OP_DCL] = method_declaration;
+ table[IDLN_ATTR_DCL] = attribute_declaration;
+ table[IDLN_CONST_DCL] = constant_declaration;
+
+ table[IDLN_TYPE_DCL] = type_declaration;
+ table[IDLN_FORWARD_DCL] = forward_declaration;
+
+ table[IDLN_TYPE_ENUM] = enum_declaration;
+
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c
new file mode 100644
index 00000000..f2daae0d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c
@@ -0,0 +1,1237 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Generate typelib files for use with InterfaceInfo.
+ * http://www.mozilla.org/scriptable/typelib_file.html
+ */
+
+#include "xpidl.h"
+#include <xpt_xdr.h>
+#include <xpt_struct.h>
+#include <time.h> /* XXX XP? */
+
+struct priv_data {
+ XPTHeader *header;
+ uint16 ifaces;
+ GHashTable *interface_map;
+ XPTInterfaceDescriptor *current;
+ XPTArena *arena;
+ uint16 next_method;
+ uint16 next_const;
+ uint16 next_type; /* used for 'additional_types' for idl arrays */
+};
+
+#define HEADER(state) (((struct priv_data *)state->priv)->header)
+#define IFACES(state) (((struct priv_data *)state->priv)->ifaces)
+#define IFACE_MAP(state) (((struct priv_data *)state->priv)->interface_map)
+#define CURRENT(state) (((struct priv_data *)state->priv)->current)
+#define ARENA(state) (((struct priv_data *)state->priv)->arena)
+#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method)
+#define NEXT_CONST(state) (((struct priv_data *)state->priv)->next_const)
+#define NEXT_TYPE(state) (((struct priv_data *)state->priv)->next_type)
+
+#ifdef DEBUG_shaver
+/* #define DEBUG_shaver_sort */
+#endif
+
+typedef struct {
+ char *full_name;
+ char *name;
+ char *name_space;
+ char *iid;
+ gboolean is_forward_dcl;
+} NewInterfaceHolder;
+
+static NewInterfaceHolder*
+CreateNewInterfaceHolder(char *name, char *name_space, char *iid,
+ gboolean is_forward_dcl)
+{
+ NewInterfaceHolder *holder = calloc(1, sizeof(NewInterfaceHolder));
+ if (holder) {
+ holder->is_forward_dcl = is_forward_dcl;
+ if (name)
+ holder->name = xpidl_strdup(name);
+ if (name_space)
+ holder->name_space = xpidl_strdup(name_space);
+ if (holder->name && holder->name_space) {
+ holder->full_name = calloc(1, strlen(holder->name) +
+ strlen(holder->name_space) + 2);
+ }
+ if (holder->full_name) {
+ strcpy(holder->full_name, holder->name_space);
+ strcat(holder->full_name, ".");
+ strcat(holder->full_name, holder->name);
+ }
+ else
+ holder->full_name = holder->name;
+ if (iid)
+ holder->iid = xpidl_strdup(iid);
+ }
+ return holder;
+}
+
+static void
+DeleteNewInterfaceHolder(NewInterfaceHolder *holder)
+{
+ if (holder) {
+ if (holder->full_name && holder->full_name != holder->name)
+ free(holder->full_name);
+ if (holder->name)
+ free(holder->name);
+ if (holder->name_space)
+ free(holder->name_space);
+ if (holder->iid)
+ free(holder->iid);
+ free(holder);
+ }
+}
+
+/*
+ * If p is an ident for an interface, and we don't have an entry in the
+ * interface map yet, add one.
+ */
+static gboolean
+add_interface_maybe(IDL_tree_func_data *tfd, gpointer user_data)
+{
+ TreeState *state = user_data;
+ IDL_tree up;
+ if (IDL_NODE_TYPE(tfd->tree) == IDLN_IDENT) {
+ IDL_tree_type node_type = IDL_NODE_TYPE((up = IDL_NODE_UP(tfd->tree)));
+ if (node_type == IDLN_INTERFACE || node_type == IDLN_FORWARD_DCL) {
+
+ /* We only want to add a new entry if there is no entry by this
+ * name or if the previously found entry was just a forward
+ * declaration and the new entry is not.
+ */
+
+ char *iface = IDL_IDENT(tfd->tree).str;
+ NewInterfaceHolder *old_holder = (NewInterfaceHolder *)
+ g_hash_table_lookup(IFACE_MAP(state), iface);
+ if (old_holder && old_holder->is_forward_dcl &&
+ node_type != IDLN_FORWARD_DCL)
+ {
+ g_hash_table_remove(IFACE_MAP(state), iface);
+ DeleteNewInterfaceHolder(old_holder);
+ old_holder = NULL;
+ }
+ if (!old_holder) {
+ /* XXX should we parse here and store a struct nsID *? */
+ char *iid = (char *)IDL_tree_property_get(tfd->tree, "uuid");
+ char *name_space = (char *)
+ IDL_tree_property_get(tfd->tree, "namespace");
+ NewInterfaceHolder *holder =
+ CreateNewInterfaceHolder(iface, name_space, iid,
+ (gboolean) node_type == IDLN_FORWARD_DCL);
+ if (!holder)
+ return FALSE;
+ g_hash_table_insert(IFACE_MAP(state),
+ holder->full_name, holder);
+ IFACES(state)++;
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state),
+ iface, iid[0] ? iid : "<unresolved>");
+#endif
+ }
+ } else {
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "ident %s isn't an interface (%s)\n",
+ IDL_IDENT(tfd->tree).str, IDL_NODE_TYPE_NAME(up));
+#endif
+ }
+ }
+
+ return TRUE;
+}
+
+/* Find all the interfaces referenced in the tree (uses add_interface_maybe) */
+static gboolean
+find_interfaces(IDL_tree_func_data *tfd, gpointer user_data)
+{
+ IDL_tree node = NULL;
+
+ switch (IDL_NODE_TYPE(tfd->tree)) {
+ case IDLN_ATTR_DCL:
+ node = IDL_ATTR_DCL(tfd->tree).param_type_spec;
+ break;
+ case IDLN_OP_DCL:
+ IDL_tree_walk_in_order(IDL_OP_DCL(tfd->tree).parameter_dcls, find_interfaces,
+ user_data);
+ node = IDL_OP_DCL(tfd->tree).op_type_spec;
+ break;
+ case IDLN_PARAM_DCL:
+ node = IDL_PARAM_DCL(tfd->tree).param_type_spec;
+ break;
+ case IDLN_INTERFACE:
+ node = IDL_INTERFACE(tfd->tree).inheritance_spec;
+ if (node)
+ xpidl_list_foreach(node, add_interface_maybe, user_data);
+ node = IDL_INTERFACE(tfd->tree).ident;
+ break;
+ case IDLN_FORWARD_DCL:
+ node = IDL_FORWARD_DCL(tfd->tree).ident;
+ break;
+ default:
+ node = NULL;
+ }
+
+ if (node && IDL_NODE_TYPE(node) == IDLN_IDENT) {
+ IDL_tree_func_data new_tfd;
+ new_tfd.tree = node;
+ add_interface_maybe(&new_tfd, user_data);
+ }
+
+ return TRUE;
+}
+
+#ifdef DEBUG_shaver
+/* for calling from gdb */
+static void
+print_IID(struct nsID *iid, FILE *file)
+{
+ char iid_buf[UUID_LENGTH];
+
+ xpidl_sprint_iid(iid, iid_buf);
+ fprintf(file, "%s\n", iid_buf);
+}
+#endif
+
+/* fill the interface_directory IDE table from the interface_map */
+static gboolean
+fill_ide_table(gpointer key, gpointer value, gpointer user_data)
+{
+ TreeState *state = user_data;
+ NewInterfaceHolder *holder = (NewInterfaceHolder *) value;
+ struct nsID id;
+ XPTInterfaceDirectoryEntry *ide;
+
+ XPT_ASSERT(holder);
+
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "filling %s\n", holder->full_name);
+#endif
+
+ if (holder->iid) {
+ if (strlen(holder->iid) != 36) {
+ IDL_tree_error(state->tree, "IID %s is the wrong length\n",
+ holder->iid);
+ return FALSE;
+ }
+ if (!xpidl_parse_iid(&id, holder->iid)) {
+ IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid);
+ return FALSE;
+ }
+ } else {
+ memset(&id, 0, sizeof(id));
+ }
+
+ ide = &(HEADER(state)->interface_directory[IFACES(state)]);
+ if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name,
+ holder->name_space, NULL)) {
+ IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n",
+ holder->full_name);
+ return FALSE;
+ }
+
+ IFACES(state)++;
+ DeleteNewInterfaceHolder(holder);
+ return TRUE;
+}
+
+static int
+compare_IDEs(const void *ap, const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *a = ap, *b = bp;
+ const nsID *aid = &a->iid, *bid = &b->iid;
+ const char *ans, *bns;
+
+ int i;
+#define COMPARE(field) if (aid->field > bid->field) return 1; \
+ if (bid->field > aid->field) return -1;
+ COMPARE(m0);
+ COMPARE(m1);
+ COMPARE(m2);
+ for (i = 0; i < 8; i++) {
+ COMPARE(m3[i]);
+ }
+
+ /* defend against NULL name_space by using empty string. */
+ ans = a->name_space ? a->name_space : "";
+ bns = b->name_space ? b->name_space : "";
+
+ if (a->name_space && b->name_space) {
+ if ((i = strcmp(a->name_space, b->name_space)))
+ return i;
+ } else {
+ if (a->name_space || b->name_space) {
+ if (a->name_space)
+ return -1;
+ return 1;
+ }
+ }
+ /* these had better not be NULL... */
+ return strcmp(a->name, b->name);
+#undef COMPARE
+}
+
+/* sort the IDE block as per the typelib spec: IID order, unresolved first */
+static void
+sort_ide_block(TreeState *state)
+{
+ XPTInterfaceDirectoryEntry *ide;
+ int i;
+
+ /* boy, I sure hope qsort works correctly everywhere */
+#ifdef DEBUG_shaver_sort
+ fputs("before sort:\n", stderr);
+ for (i = 0; i < IFACES(state); i++) {
+ fputs(" ", stderr);
+ print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
+ fputc('\n', stderr);
+ }
+#endif
+ qsort(HEADER(state)->interface_directory, IFACES(state),
+ sizeof(*ide), compare_IDEs);
+#ifdef DEBUG_shaver_sort
+ fputs("after sort:\n", stderr);
+ for (i = 0; i < IFACES(state); i++) {
+ fputs(" ", stderr);
+ print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
+ fputc('\n', stderr);
+ }
+#endif
+
+ for (i = 0; i < IFACES(state); i++) {
+ ide = HEADER(state)->interface_directory + i;
+ g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1));
+ }
+
+ return;
+}
+
+static gboolean
+typelib_list(TreeState *state)
+{
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+typelib_prolog(TreeState *state)
+{
+ state->priv = calloc(1, sizeof(struct priv_data));
+ if (!state->priv)
+ return FALSE;
+ IFACES(state) = 0;
+ IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!IFACE_MAP(state)) {
+ /* XXX report error */
+ free(state->priv);
+ return FALSE;
+ }
+ /* find all interfaces, top-level and referenced by others */
+ IDL_tree_walk_in_order(state->tree, find_interfaces, state);
+ ARENA(state) = XPT_NewArena(1024, sizeof(double), "main xpidl arena");
+ HEADER(state) = XPT_NewHeader(ARENA(state), IFACES(state),
+ major_version, minor_version);
+
+ /* fill IDEs from hash table */
+ IFACES(state) = 0;
+ g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
+
+ /* if any are left then we must have failed in fill_ide_table */
+ if (g_hash_table_size(IFACE_MAP(state)))
+ return FALSE;
+
+ /* sort the IDEs by IID order and store indices in the interface map */
+ sort_ide_block(state);
+
+ return TRUE;
+}
+
+static gboolean
+typelib_epilog(TreeState *state)
+{
+ XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
+ XPTCursor curs, *cursor = &curs;
+ PRUint32 i, len, header_sz;
+ PRUint32 oldOffset;
+ PRUint32 newOffset;
+ char *data;
+
+ /* Write any annotations */
+ if (emit_typelib_annotations) {
+ PRUint32 annotation_len, written_so_far;
+ char *annotate_val, *timestr;
+ time_t now;
+ static char *annotation_format =
+ "Created from %s.idl\nCreation date: %sInterfaces:";
+
+ /* fill in the annotations, listing resolved interfaces in order */
+
+ (void)time(&now);
+ timestr = ctime(&now);
+
+ /* Avoid dependence on nspr; no PR_smprintf and friends. */
+
+ /* How large should the annotation string be? */
+ annotation_len = strlen(annotation_format) + strlen(state->basename) +
+ strlen(timestr);
+#ifdef VBOX
+ /* note that '%s' is contained two times in annotation_format and both
+ * format specifiers are replaced by a string. So in fact we reserve 4
+ * bytes minus one byte (for the terminating '\0') more than necessary. */
+#endif
+ for (i = 0; i < HEADER(state)->num_interfaces; i++) {
+ XPTInterfaceDirectoryEntry *ide;
+ ide = &HEADER(state)->interface_directory[i];
+ if (ide->interface_descriptor) {
+ annotation_len += strlen(ide->name) + 1;
+ }
+ }
+
+ annotate_val = (char *) malloc(annotation_len);
+ written_so_far = sprintf(annotate_val, annotation_format,
+ state->basename, timestr);
+
+ for (i = 0; i < HEADER(state)->num_interfaces; i++) {
+ XPTInterfaceDirectoryEntry *ide;
+ ide = &HEADER(state)->interface_directory[i];
+ if (ide->interface_descriptor) {
+ written_so_far += sprintf(annotate_val + written_so_far, " %s",
+ ide->name);
+ }
+ }
+
+ HEADER(state)->annotations =
+ XPT_NewAnnotation(ARENA(state),
+ XPT_ANN_LAST | XPT_ANN_PRIVATE,
+ XPT_NewStringZ(ARENA(state), "xpidl 0.99.9"),
+ XPT_NewStringZ(ARENA(state), annotate_val));
+ free(annotate_val);
+ } else {
+ HEADER(state)->annotations =
+ XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST, NULL, NULL);
+ }
+
+ if (!HEADER(state)->annotations) {
+ /* XXX report out of memory error */
+ return FALSE;
+ }
+
+ /* Write the typelib */
+ header_sz = XPT_SizeOfHeaderBlock(HEADER(state));
+
+ if (!xstate ||
+ !XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor))
+ goto destroy_header;
+ oldOffset = cursor->offset;
+ if (!XPT_DoHeader(ARENA(state), cursor, &HEADER(state)))
+ goto destroy;
+ newOffset = cursor->offset;
+ XPT_GetXDRDataLength(xstate, XPT_HEADER, &len);
+ HEADER(state)->file_length = len;
+ XPT_GetXDRDataLength(xstate, XPT_DATA, &len);
+ HEADER(state)->file_length += len;
+ XPT_SeekTo(cursor, oldOffset);
+ if (!XPT_DoHeaderPrologue(ARENA(state), cursor, &HEADER(state), NULL))
+ goto destroy;
+ XPT_SeekTo(cursor, newOffset);
+ XPT_GetXDRData(xstate, XPT_HEADER, &data, &len);
+ fwrite(data, len, 1, state->file);
+ XPT_GetXDRData(xstate, XPT_DATA, &data, &len);
+ fwrite(data, len, 1, state->file);
+
+ destroy:
+ XPT_DestroyXDRState(xstate);
+ destroy_header:
+ /* XXX XPT_DestroyHeader(HEADER(state)) */
+
+ XPT_FreeHeader(ARENA(state), HEADER(state));
+ XPT_DestroyArena(ARENA(state));
+
+ /* XXX should destroy priv_data here */
+
+ return TRUE;
+}
+
+static XPTInterfaceDirectoryEntry *
+FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces,
+ const char *name)
+{
+ uint16 i;
+ for (i = 0; i < num_interfaces; i++) {
+ if (!strcmp(ides[i].name, name))
+ return &ides[i];
+ }
+ return NULL;
+}
+
+static gboolean
+typelib_interface(TreeState *state)
+{
+ IDL_tree iface = state->tree, iter;
+ char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
+ XPTInterfaceDirectoryEntry *ide;
+ XPTInterfaceDescriptor *id;
+ uint16 parent_id = 0;
+ PRUint8 interface_flags = 0;
+
+ if (!verify_interface_declaration(iface))
+ return FALSE;
+
+ if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable"))
+ interface_flags |= XPT_ID_SCRIPTABLE;
+
+ if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function"))
+ interface_flags |= XPT_ID_FUNCTION;
+
+ ide = FindInterfaceByName(HEADER(state)->interface_directory,
+ HEADER(state)->num_interfaces, name);
+ if (!ide) {
+ IDL_tree_error(iface, "ERROR: didn't find interface %s in "
+ "IDE block. Giving up.\n", name);
+ return FALSE;
+ }
+
+ if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
+ char *parent;
+ if (IDL_LIST(iter).next) {
+ IDL_tree_error(iface,
+ "ERROR: more than one parent interface for %s\n",
+ name);
+ return FALSE;
+ }
+ parent = IDL_IDENT(IDL_LIST(iter).data).str;
+ parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state),
+ parent);
+ if (!parent_id) {
+ IDL_tree_error(iface,
+ "ERROR: no index found for %s. Giving up.\n",
+ parent);
+ return FALSE;
+ }
+ }
+
+ id = XPT_NewInterfaceDescriptor(ARENA(state), parent_id, 0, 0,
+ interface_flags);
+ if (!id)
+ return FALSE;
+
+ CURRENT(state) = ide->interface_descriptor = id;
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "DBG: starting interface %s @ %p\n", name, id);
+#endif
+
+ NEXT_METH(state) = 0;
+ NEXT_CONST(state) = 0;
+ NEXT_TYPE(state) = 0;
+
+ state->tree = IDL_INTERFACE(iface).body;
+ if (state->tree && !xpidl_process_node(state))
+ return FALSE;
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "DBG: ending interface %s\n", name);
+#endif
+ return TRUE;
+}
+
+static gboolean
+find_arg_with_name(TreeState *state, const char *name, int16 *argnum)
+{
+ int16 count;
+ IDL_tree params;
+
+ XPT_ASSERT(state);
+ XPT_ASSERT(name);
+ XPT_ASSERT(argnum);
+
+ params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls;
+ for (count = 0;
+ params != NULL && IDL_LIST(params).data != NULL;
+ params = IDL_LIST(params).next, count++)
+ {
+ const char *cur_name = IDL_IDENT(
+ IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str;
+ if (!strcmp(cur_name, name)) {
+ /* XXX ought to verify that this is the right type here */
+ /* XXX for iid_is this must be an iid */
+ /* XXX for size_is and length_is this must be a uint32 */
+ *argnum = count;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* return value is for success or failure */
+static gboolean
+get_size_and_length(TreeState *state, IDL_tree type,
+ int16 *size_is_argnum, int16 *length_is_argnum,
+ gboolean *has_size_is, gboolean *has_length_is)
+{
+ *has_size_is = FALSE;
+ *has_length_is = FALSE;
+
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
+ IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
+ const char *size_is;
+ const char *length_is;
+
+ /* only if size_is is found does any of this matter */
+ size_is = IDL_tree_property_get(sd, "size_is");
+ if (!size_is)
+ return TRUE;
+
+ if (!find_arg_with_name(state, size_is, size_is_argnum)) {
+ IDL_tree_error(state->tree, "can't find matching argument for "
+ "[size_is(%s)]\n", size_is);
+ return FALSE;
+ }
+ *has_size_is = TRUE;
+
+ /* length_is is optional */
+ length_is = IDL_tree_property_get(sd, "length_is");
+ if (length_is) {
+ *has_length_is = TRUE;
+ if (!find_arg_with_name(state, length_is, length_is_argnum)) {
+ IDL_tree_error(state->tree, "can't find matching argument for "
+ "[length_is(%s)]\n", length_is);
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type)
+{
+ IDL_tree up;
+ int16 size_is_argnum;
+ int16 length_is_argnum;
+ gboolean has_size_is;
+ gboolean has_length_is;
+ gboolean is_array = FALSE;
+
+ if (type) {
+
+ /* deal with array */
+
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
+ IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
+ if (IDL_tree_property_get(sd, "array")) {
+
+ is_array = TRUE;
+
+ /* size_is is required! */
+ if (!get_size_and_length(state, type,
+ &size_is_argnum, &length_is_argnum,
+ &has_size_is, &has_length_is)) {
+ /* error was reported by helper function */
+ return FALSE;
+ }
+
+ if (!has_size_is) {
+ IDL_tree_error(state->tree, "[array] requires [size_is()]\n");
+ return FALSE;
+ }
+
+ td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER;
+ td->argnum = size_is_argnum;
+
+ if (has_length_is)
+ td->argnum2 = length_is_argnum;
+ else
+ td->argnum2 = size_is_argnum;
+
+ /*
+ * XXX - NOTE - this will be broken for multidimensional
+ * arrays because of the realloc XPT_InterfaceDescriptorAddTypes
+ * uses. The underlying 'td' can change as we recurse in to get
+ * additional dimensions. Luckily, we don't yet support more
+ * than on dimension in the arrays
+ */
+ /* setup the additional_type */
+ if (!XPT_InterfaceDescriptorAddTypes(ARENA(state),
+ CURRENT(state), 1)) {
+ g_error("out of memory\n");
+ return FALSE;
+ }
+ td->type.additional_type = NEXT_TYPE(state);
+ td = &CURRENT(state)->additional_types[NEXT_TYPE(state)];
+ NEXT_TYPE(state)++ ;
+ }
+ }
+
+handle_typedef:
+ switch (IDL_NODE_TYPE(type)) {
+ case IDLN_TYPE_INTEGER: {
+ gboolean sign = IDL_TYPE_INTEGER(type).f_signed;
+ switch(IDL_TYPE_INTEGER(type).f_type) {
+ case IDL_INTEGER_TYPE_SHORT:
+ td->prefix.flags = sign ? TD_INT16 : TD_UINT16;
+ break;
+ case IDL_INTEGER_TYPE_LONG:
+ td->prefix.flags = sign ? TD_INT32 : TD_UINT32;
+ break;
+ case IDL_INTEGER_TYPE_LONGLONG:
+ td->prefix.flags = sign ? TD_INT64 : TD_UINT64;
+ break;
+ }
+ break;
+ }
+ case IDLN_TYPE_CHAR:
+ td->prefix.flags = TD_CHAR;
+ break;
+ case IDLN_TYPE_WIDE_CHAR:
+ td->prefix.flags = TD_WCHAR;
+ break;
+ case IDLN_TYPE_STRING:
+ if (is_array) {
+ td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
+ } else {
+ if (!get_size_and_length(state, type,
+ &size_is_argnum, &length_is_argnum,
+ &has_size_is, &has_length_is)) {
+ /* error was reported by helper function */
+ return FALSE;
+ }
+ if (has_size_is) {
+ td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER;
+ td->argnum = size_is_argnum;
+ if (has_length_is)
+ td->argnum2 = length_is_argnum;
+ else
+ td->argnum2 = size_is_argnum;
+ } else {
+ td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
+ }
+ }
+ break;
+ case IDLN_TYPE_WIDE_STRING:
+ if (is_array) {
+ td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
+ } else {
+ if (!get_size_and_length(state, type,
+ &size_is_argnum, &length_is_argnum,
+ &has_size_is, &has_length_is)) {
+ /* error was reported by helper function */
+ return FALSE;
+ }
+ if (has_size_is) {
+ td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER;
+ td->argnum = size_is_argnum;
+ if (has_length_is)
+ td->argnum2 = length_is_argnum;
+ else
+ td->argnum2 = size_is_argnum;
+ } else {
+ td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
+ }
+ }
+ break;
+ case IDLN_TYPE_BOOLEAN:
+ td->prefix.flags = TD_BOOL;
+ break;
+ case IDLN_TYPE_OCTET:
+ td->prefix.flags = TD_UINT8;
+ break;
+ case IDLN_TYPE_FLOAT:
+ switch (IDL_TYPE_FLOAT (type).f_type) {
+ case IDL_FLOAT_TYPE_FLOAT:
+ td->prefix.flags = TD_FLOAT;
+ break;
+ case IDL_FLOAT_TYPE_DOUBLE:
+ td->prefix.flags = TD_DOUBLE;
+ break;
+ /* XXX 'long double' just ignored, or what? */
+ default: break;
+ }
+ break;
+ case IDLN_IDENT:
+ if (!(up = IDL_NODE_UP(type))) {
+ IDL_tree_error(state->tree,
+ "ERROR: orphan ident %s in param list\n",
+ IDL_IDENT(type).str);
+ return FALSE;
+ }
+ switch (IDL_NODE_TYPE(up)) {
+ /* This whole section is abominably ugly */
+ case IDLN_FORWARD_DCL:
+ case IDLN_INTERFACE: {
+ XPTInterfaceDirectoryEntry *ide, *ides;
+ uint16 num_ifaces;
+ char *className;
+ const char *iid_is;
+handle_iid_is:
+ ides = HEADER(state)->interface_directory;
+ num_ifaces = HEADER(state)->num_interfaces;
+ /* might get here via the goto, so re-check type */
+ if (IDL_NODE_TYPE(up) == IDLN_INTERFACE)
+ className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
+ else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
+ className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str;
+ else
+ className = IDL_IDENT(IDL_NATIVE(up).ident).str;
+ iid_is = NULL;
+
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
+ iid_is =
+ IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
+ "iid_is");
+ }
+ if (iid_is) {
+ int16 argnum;
+ if (!find_arg_with_name(state, iid_is, &argnum)) {
+ IDL_tree_error(state->tree,
+ "can't find matching argument for "
+ "[iid_is(%s)]\n", iid_is);
+ return FALSE;
+ }
+ td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER;
+ td->argnum = argnum;
+ } else {
+ td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
+ ide = FindInterfaceByName(ides, num_ifaces, className);
+ if (!ide || ide < ides || ide > ides + num_ifaces) {
+ IDL_tree_error(state->tree,
+ "unknown iface %s in param\n",
+ className);
+ return FALSE;
+ }
+ td->type.iface = ide - ides + 1;
+#ifdef DEBUG_shaver_index
+ fprintf(stderr, "DBG: index %d for %s\n",
+ td->type.iface, className);
+#endif
+ }
+ break;
+ }
+ case IDLN_NATIVE: {
+ char *ident;
+
+ /* jband - adding goto for iid_is when type is native */
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL &&
+ IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
+ "iid_is"))
+ goto handle_iid_is;
+
+ ident = IDL_IDENT(type).str;
+ if (IDL_tree_property_get(type, "nsid")) {
+ td->prefix.flags = TD_PNSIID;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE;
+ else if (IDL_tree_property_get(type,"ptr"))
+ td->prefix.flags |= XPT_TDP_POINTER;
+ } else if (IDL_tree_property_get(type, "domstring")) {
+ td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else if (IDL_tree_property_get(type, "astring")) {
+ td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else if (IDL_tree_property_get(type, "utf8string")) {
+ td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else if (IDL_tree_property_get(type, "cstring")) {
+ td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else {
+ td->prefix.flags = TD_VOID | XPT_TDP_POINTER;
+ }
+ break;
+ }
+ default:
+ if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
+ /* restart with the underlying type */
+ IDL_tree new_type;
+ new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
+#ifdef DEBUG_shaver_misc
+ fprintf(stderr, "following %s typedef to %s\n",
+ IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type));
+#endif
+ /*
+ * Do a nice messy goto rather than recursion so that
+ * we can avoid screwing up the *array* information.
+ */
+/* return fill_td_from_type(state, td, new_type); */
+ if (new_type) {
+ type = new_type;
+ goto handle_typedef;
+ } else {
+ /* do what we would do in recursion if !type */
+ td->prefix.flags = TD_VOID;
+ return TRUE;
+ }
+ }
+ IDL_tree_error(state->tree,
+ "can't handle %s ident in param list\n",
+#ifdef DEBUG_shaver
+ /* XXX is this safe to use on Win now? */
+ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
+#else
+ "that type of"
+#endif
+ );
+#ifdef DEBUG_shaver
+ XPT_ASSERT(0);
+#endif
+ return FALSE;
+ }
+ break;
+ default:
+ IDL_tree_error(state->tree, "can't handle %s in param list\n",
+#ifdef DEBUG_shaver
+ /* XXX is this safe to use on Win now? */
+ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
+#else
+ "that type"
+#endif
+ );
+ return FALSE;
+ }
+ } else {
+ td->prefix.flags = TD_VOID;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags,
+ IDL_tree type)
+{
+ pd->flags = flags;
+ return fill_td_from_type(state, &pd->type, type);
+}
+
+static gboolean
+fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
+{
+ uint8 flags = 0;
+ gboolean is_dipper_type = DIPPER_TYPE(IDL_PARAM_DCL(tree).param_type_spec);
+
+ switch (IDL_PARAM_DCL(tree).attr) {
+ case IDL_PARAM_IN:
+ flags = XPT_PD_IN;
+ break;
+ case IDL_PARAM_OUT:
+ flags = XPT_PD_OUT;
+ break;
+ case IDL_PARAM_INOUT:
+ flags = XPT_PD_IN | XPT_PD_OUT;
+ break;
+ }
+
+ if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
+ "retval")) {
+ if (flags != XPT_PD_OUT) {
+ IDL_tree_error(tree, "can't have [retval] with in%s param "
+ "(only out)\n",
+ flags & XPT_PD_OUT ? "out" : "");
+ return FALSE;
+ }
+ flags |= XPT_PD_RETVAL;
+ }
+
+ if (is_dipper_type && (flags & XPT_PD_OUT)) {
+ flags &= ~XPT_PD_OUT;
+ flags |= XPT_PD_IN | XPT_PD_DIPPER;
+ }
+
+ if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
+ "shared")) {
+ if (flags & XPT_PD_IN) {
+ IDL_tree_error(tree, "can't have [shared] with in%s param "
+ "(only out)\n",
+ flags & XPT_PD_OUT ? "out" : "");
+ return FALSE;
+ }
+ flags |= XPT_PD_SHARED;
+ }
+
+ /* stick param where we can see it later */
+ state->tree = tree;
+ return fill_pd_from_type(state, pd, flags,
+ IDL_PARAM_DCL(tree).param_type_spec);
+}
+
+/* XXXshaver common with xpidl_header.c */
+#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
+#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
+#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
+
+static gboolean
+fill_pd_as_nsresult(XPTParamDescriptor *pd)
+{
+ pd->type.prefix.flags = TD_UINT32; /* TD_NSRESULT */
+ return TRUE;
+}
+
+static gboolean
+typelib_attr_accessor(TreeState *state, XPTMethodDescriptor *meth,
+ gboolean getter, gboolean hidden)
+{
+ uint8 methflags = 0;
+ uint8 pdflags = 0;
+
+ methflags |= getter ? XPT_MD_GETTER : XPT_MD_SETTER;
+ methflags |= hidden ? XPT_MD_HIDDEN : 0;
+ if (!XPT_FillMethodDescriptor(ARENA(state), meth, methflags,
+ ATTR_IDENT(state->tree).str, 1))
+ return FALSE;
+
+ if (getter) {
+ if (DIPPER_TYPE(ATTR_TYPE_DECL(state->tree))) {
+ pdflags |= (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER);
+ } else {
+ pdflags |= (XPT_PD_RETVAL | XPT_PD_OUT);
+ }
+ } else {
+ pdflags |= XPT_PD_IN;
+ }
+
+ if (!fill_pd_from_type(state, meth->params, pdflags,
+ ATTR_TYPE_DECL(state->tree)))
+ return FALSE;
+
+ fill_pd_as_nsresult(meth->result);
+ NEXT_METH(state)++;
+ return TRUE;
+}
+
+static gboolean
+typelib_attr_dcl(TreeState *state)
+{
+ XPTInterfaceDescriptor *id = CURRENT(state);
+ XPTMethodDescriptor *meth;
+ gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
+
+ /* XXX this only handles the first ident; elsewhere too... */
+ IDL_tree ident =
+ IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).data;
+
+ /* If it's marked [noscript], mark it as hidden in the typelib. */
+ gboolean hidden = (IDL_tree_property_get(ident, "noscript") != NULL);
+
+ if (!verify_attribute_declaration(state->tree))
+ return FALSE;
+
+ if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id,
+ (PRUint16) (read_only ? 1 : 2)))
+ return FALSE;
+
+ meth = &id->method_descriptors[NEXT_METH(state)];
+
+ return typelib_attr_accessor(state, meth, TRUE, hidden) &&
+ (read_only || typelib_attr_accessor(state, meth + 1, FALSE, hidden));
+}
+
+static gboolean
+typelib_op_dcl(TreeState *state)
+{
+ XPTInterfaceDescriptor *id = CURRENT(state);
+ XPTMethodDescriptor *meth;
+ struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree);
+ IDL_tree iter;
+ uint16 num_args = 0;
+ uint8 op_flags = 0;
+ gboolean op_notxpcom = (IDL_tree_property_get(op->ident, "notxpcom")
+ != NULL);
+ gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
+ != NULL);
+
+ if (!verify_method_declaration(state->tree))
+ return FALSE;
+
+ if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, 1))
+ return FALSE;
+
+ meth = &id->method_descriptors[NEXT_METH(state)];
+
+ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next)
+ num_args++; /* count params */
+ if (op->op_type_spec && !op_notxpcom)
+ num_args++; /* fake param for _retval */
+
+ if (op_noscript)
+ op_flags |= XPT_MD_HIDDEN;
+ if (op_notxpcom)
+ op_flags |= XPT_MD_NOTXPCOM;
+
+ /* XXXshaver constructor? */
+
+#ifdef DEBUG_shaver_method
+ fprintf(stdout, "DBG: adding method %s (nargs %d)\n",
+ IDL_IDENT(op->ident).str, num_args);
+#endif
+ if (!XPT_FillMethodDescriptor(ARENA(state), meth, op_flags,
+ IDL_IDENT(op->ident).str,
+ (uint8) num_args))
+ return FALSE;
+
+ for (num_args = 0, iter = op->parameter_dcls; iter;
+ iter = IDL_LIST(iter).next, num_args++) {
+ XPTParamDescriptor *pd = &meth->params[num_args];
+ if (!fill_pd_from_param(state, pd, IDL_LIST(iter).data))
+ return FALSE;
+ }
+
+ /* stick retval param where we can see it later */
+ state->tree = op->op_type_spec;
+
+ /* XXX unless [notxpcom] */
+ if (!op_notxpcom) {
+ if (op->op_type_spec) {
+ uint8 pdflags = DIPPER_TYPE(op->op_type_spec) ?
+ (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER) :
+ (XPT_PD_RETVAL | XPT_PD_OUT);
+
+ if (!fill_pd_from_type(state, &meth->params[num_args],
+ pdflags, op->op_type_spec))
+ return FALSE;
+ }
+
+ if (!fill_pd_as_nsresult(meth->result))
+ return FALSE;
+ } else {
+#ifdef DEBUG_shaver_notxpcom
+ fprintf(stderr, "%s is notxpcom\n", IDL_IDENT(op->ident).str);
+#endif
+ if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL,
+ op->op_type_spec))
+ return FALSE;
+ }
+ NEXT_METH(state)++;
+ return TRUE;
+}
+
+static gboolean
+typelib_const_dcl(TreeState *state)
+{
+ struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
+ const char *name = IDL_IDENT(dcl->ident).str;
+ gboolean is_long;
+ gboolean sign;
+ IDL_tree real_type;
+ XPTInterfaceDescriptor *id;
+ XPTConstDescriptor *cd;
+ IDL_longlong_t value;
+
+ if (!verify_const_declaration(state->tree))
+ return FALSE;
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(dcl->const_type);
+ real_type = real_type ? real_type : dcl->const_type;
+ is_long = (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG);
+
+ id = CURRENT(state);
+ if (!XPT_InterfaceDescriptorAddConsts(ARENA(state), id, 1))
+ return FALSE;
+ cd = &id->const_descriptors[NEXT_CONST(state)];
+
+ cd->name = IDL_IDENT(dcl->ident).str;
+#ifdef DEBUG_shaver_const
+ fprintf(stderr, "DBG: adding const %s\n", cd->name);
+#endif
+ if (!fill_td_from_type(state, &cd->type, dcl->const_type))
+ return FALSE;
+
+ value = IDL_INTEGER(dcl->const_exp).value;
+ sign = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
+ if (is_long) {
+ if (sign)
+ cd->value.i32 = value;
+ else
+ cd->value.ui32 = value;
+ } else {
+ if (sign)
+ cd->value.i16 = value;
+ else
+ cd->value.ui16 = value;
+ }
+ NEXT_CONST(state)++;
+ return TRUE;
+}
+
+static gboolean
+typelib_enum(TreeState *state)
+{
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "enums not supported, enum \'%s\' ignored",
+ IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
+ return TRUE;
+}
+
+backend *
+xpidl_typelib_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = typelib_prolog;
+ result.emit_epilog = typelib_epilog;
+
+ if (!initialized) {
+ /* Initialize non-NULL elements */
+ table[IDLN_LIST] = typelib_list;
+ table[IDLN_ATTR_DCL] = typelib_attr_dcl;
+ table[IDLN_OP_DCL] = typelib_op_dcl;
+ table[IDLN_INTERFACE] = typelib_interface;
+ table[IDLN_CONST_DCL] = typelib_const_dcl;
+ table[IDLN_TYPE_ENUM] = typelib_enum;
+ table[IDLN_NATIVE] = check_native;
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c
new file mode 100644
index 00000000..25d04212
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c
@@ -0,0 +1,851 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Utility functions called by various backends.
+ */
+
+#include "xpidl.h"
+
+/* XXXbe static */ char OOM[] = "ERROR: out of memory\n";
+
+void *
+xpidl_malloc(size_t nbytes)
+{
+ void *p = malloc(nbytes);
+ if (!p) {
+ fputs(OOM, stderr);
+ exit(1);
+ }
+ return p;
+}
+
+char *
+xpidl_strdup(const char *s)
+{
+#if defined(XP_MAC) || defined(XP_SOLARIS) /* bird: dunno why this is required, but whatever*/
+ size_t len = strlen(s);
+ char *ns = malloc(len + 1);
+ if (ns)
+ memcpy(ns, s, len + 1);
+#else
+ char *ns = strdup(s);
+#endif
+ if (!ns) {
+ fputs(OOM, stderr);
+ exit(1);
+ }
+ return ns;
+}
+
+void
+xpidl_write_comment(TreeState *state, int indent)
+{
+ fprintf(state->file, "%*s/* ", indent, "");
+ IDL_tree_to_IDL(state->tree, state->ns, state->file,
+ IDLF_OUTPUT_NO_NEWLINES |
+ IDLF_OUTPUT_NO_QUALIFY_IDENTS |
+ IDLF_OUTPUT_PROPERTIES);
+ fputs(" */\n", state->file);
+}
+
+/*
+ * Print an iid to into a supplied buffer; the buffer should be at least
+ * UUID_LENGTH bytes.
+ */
+gboolean
+xpidl_sprint_iid(nsID *id, char iidbuf[])
+{
+ int printed;
+
+ printed = sprintf(iidbuf,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2,
+ (PRUint32) id->m3[0], (PRUint32) id->m3[1],
+ (PRUint32) id->m3[2], (PRUint32) id->m3[3],
+ (PRUint32) id->m3[4], (PRUint32) id->m3[5],
+ (PRUint32) id->m3[6], (PRUint32) id->m3[7]);
+
+#ifdef SPRINTF_RETURNS_STRING
+ return (printed && strlen((char *)printed) == 36);
+#else
+ return (printed == 36);
+#endif
+}
+
+/* We only parse the {}-less format. */
+static const char nsIDFmt2[] =
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+
+/*
+ * Parse a uuid string into an nsID struct. We cannot link against libxpcom,
+ * so we re-implement nsID::Parse here.
+ */
+gboolean
+xpidl_parse_iid(nsID *id, const char *str)
+{
+ PRInt32 count = 0;
+ PRInt32 n1, n2, n3[8];
+ PRInt32 n0, i;
+
+ XPT_ASSERT(str != NULL);
+
+ if (strlen(str) != 36) {
+ return FALSE;
+ }
+
+#ifdef DEBUG_shaver_iid
+ fprintf(stderr, "parsing iid %s\n", str);
+#endif
+
+ count = sscanf(str, nsIDFmt2,
+ &n0, &n1, &n2,
+ &n3[0],&n3[1],&n3[2],&n3[3],
+ &n3[4],&n3[5],&n3[6],&n3[7]);
+
+ id->m0 = (PRInt32) n0;
+ id->m1 = (PRInt16) n1;
+ id->m2 = (PRInt16) n2;
+ for (i = 0; i < 8; i++) {
+ id->m3[i] = (PRInt8) n3[i];
+ }
+
+#ifdef DEBUG_shaver_iid
+ if (count == 11) {
+ fprintf(stderr, "IID parsed to ");
+ print_IID(id, stderr);
+ fputs("\n", stderr);
+ }
+#endif
+ return (gboolean)(count == 11);
+}
+
+gboolean
+verify_const_declaration(IDL_tree const_tree) {
+ struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(const_tree);
+ const char *name = IDL_IDENT(dcl->ident).str;
+ IDL_tree real_type;
+
+ /* const -> list -> interface */
+ if (!IDL_NODE_UP(IDL_NODE_UP(const_tree)) ||
+ IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(const_tree)))
+ != IDLN_INTERFACE) {
+ IDL_tree_error(const_tree,
+ "const declaration \'%s\' outside interface",
+ name);
+ return FALSE;
+ }
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(dcl->const_type);
+ real_type = real_type ? real_type : dcl->const_type;
+ if (IDL_NODE_TYPE(real_type) == IDLN_TYPE_INTEGER &&
+ (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_SHORT ||
+ IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG))
+ {
+ if (!IDL_TYPE_INTEGER(real_type).f_signed &&
+ IDL_INTEGER(dcl->const_exp).value < 0)
+ {
+#ifndef G_HAVE_GINT64
+ /*
+ * For platforms without longlong support turned on we can get
+ * confused by the high bit of the long value and think that it
+ * represents a negative value in an unsigned declaration.
+ * In that case we don't know if it is the programmer who is
+ * confused or the compiler. So we issue a warning instead of
+ * an error.
+ */
+ if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG)
+ {
+ XPIDL_WARNING((const_tree, IDL_WARNING1,
+ "unsigned const declaration \'%s\' "
+ "initialized with (possibly) negative constant",
+ name));
+ return TRUE;
+ }
+#endif
+ IDL_tree_error(const_tree,
+ "unsigned const declaration \'%s\' initialized with "
+ "negative constant",
+ name);
+ return FALSE;
+ }
+ } else {
+ IDL_tree_error(const_tree,
+ "const declaration \'%s\' must be of type short or long",
+ name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * This method consolidates error checking needed when coercing the XPIDL compiler
+ * via the -t flag to generate output for a specific version of XPConnect.
+ */
+static gboolean
+verify_type_fits_version(IDL_tree in_tree, IDL_tree error_tree)
+{
+ if (major_version == 1 && minor_version == 1)
+ {
+ /* XPIDL Version 1.1 checks */
+
+ /* utf8string, cstring, and astring types are not supported */
+ if (IDL_tree_property_get(in_tree, "utf8string") != NULL ||
+ IDL_tree_property_get(in_tree, "cstring") != NULL ||
+ IDL_tree_property_get(in_tree, "astring") != NULL)
+ {
+ IDL_tree_error(error_tree,
+ "Cannot use [utf8string], [cstring] and [astring] "
+ "types when generating version 1.1 typelibs\n");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+gboolean
+verify_attribute_declaration(IDL_tree attr_tree)
+{
+ IDL_tree iface;
+ IDL_tree ident;
+ IDL_tree attr_type;
+ gboolean scriptable_interface;
+
+ /* We don't support attributes named IID, conflicts with static GetIID
+ * member. The conflict is due to certain compilers (VC++) choosing a
+ * different vtable order, placing GetIID at the beginning regardless
+ * of it's placement
+ */
+ if (strcmp(
+ IDL_IDENT(
+ IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str,
+ "IID") == 0) {
+ IDL_tree_error(attr_tree,
+ "Attributes named IID not supported, causes vtable "
+ "ordering problems");
+ return FALSE;
+ }
+ /*
+ * Verify that we've been called on an interface, and decide if the
+ * interface was marked [scriptable].
+ */
+ if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) &&
+ IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree)))
+ == IDLN_INTERFACE)
+ {
+ scriptable_interface =
+ (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
+ != NULL);
+ } else {
+ IDL_tree_error(attr_tree,
+ "verify_attribute_declaration called on a non-interface?");
+ return FALSE;
+ }
+
+ /*
+ * Grab the first of the list of idents and hope that it'll
+ * say scriptable or no.
+ */
+ ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data;
+
+ /*
+ * If the interface isn't scriptable, or the attribute is marked noscript,
+ * there's no need to check.
+ */
+ if (!scriptable_interface ||
+ IDL_tree_property_get(ident, "noscript") != NULL)
+ return TRUE;
+
+ /*
+ * If it should be scriptable, check that the type is non-native. nsid,
+ * domstring, utf8string, cstring, astring are exempted.
+ */
+ attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec;
+
+ if (attr_type != NULL)
+ {
+ if (UP_IS_NATIVE(attr_type) &&
+ IDL_tree_property_get(attr_type, "nsid") == NULL &&
+ IDL_tree_property_get(attr_type, "domstring") == NULL &&
+ IDL_tree_property_get(attr_type, "utf8string") == NULL &&
+ IDL_tree_property_get(attr_type, "cstring") == NULL &&
+ IDL_tree_property_get(attr_type, "astring") == NULL)
+ {
+ IDL_tree_error(attr_tree,
+ "attributes in [scriptable] interfaces that are "
+ "non-scriptable because they refer to native "
+ "types must be marked [noscript]\n");
+ return FALSE;
+ }
+ /*
+ * We currently don't support properties of type nsid that aren't
+ * pointers or references, unless they are marked [notxpcom} and
+ * must be read-only
+ */
+
+ if ((IDL_tree_property_get(ident, "notxpcom") == NULL || !(IDL_ATTR_DCL(attr_tree).f_readonly)) &&
+ IDL_tree_property_get(attr_type,"nsid") != NULL &&
+ IDL_tree_property_get(attr_type,"ptr") == NULL &&
+ IDL_tree_property_get(attr_type,"ref") == NULL)
+ {
+ IDL_tree_error(attr_tree,
+ "Feature not currently supported: "
+ "attributes with a type of nsid must be marked "
+ "either [ptr] or [ref], or "
+ "else must be marked [notxpcom] "
+ "and must be read-only\n");
+ return FALSE;
+ }
+
+ /*
+ * Run additional error checks on the attribute type if targetting an
+ * older version of XPConnect.
+ */
+
+ if (!verify_type_fits_version(attr_type, attr_tree))
+ return FALSE;
+ }
+
+ if (IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).next != NULL)
+ {
+ IDL_tree_error(attr_tree,
+ "multiple attributes in a single declaration is not supported\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Find the underlying type of an identifier typedef.
+ *
+ * All the needed tree-walking seems pretty shaky; isn't there something in
+ * libIDL to automate this?
+ */
+IDL_tree /* IDL_TYPE_DCL */
+find_underlying_type(IDL_tree typedef_ident)
+{
+ IDL_tree up;
+
+ if (typedef_ident == NULL || IDL_NODE_TYPE(typedef_ident) != IDLN_IDENT)
+ return NULL;
+
+ up = IDL_NODE_UP(typedef_ident);
+ if (up == NULL || IDL_NODE_TYPE(up) != IDLN_LIST)
+ return NULL;
+ up = IDL_NODE_UP(up);
+ if (up == NULL || IDL_NODE_TYPE(up) != IDLN_TYPE_DCL)
+ return NULL;
+
+ return IDL_TYPE_DCL(up).type_spec;
+}
+
+static IDL_tree /* IDL_PARAM_DCL */
+find_named_parameter(IDL_tree method_tree, const char *param_name)
+{
+ IDL_tree iter;
+ for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree param = IDL_LIST(iter).data;
+ IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
+ const char *current_name = IDL_IDENT(simple_decl).str;
+ if (strcmp(current_name, param_name) == 0)
+ return param;
+ }
+ return NULL;
+}
+
+typedef enum ParamAttrType {
+ IID_IS,
+ LENGTH_IS,
+ SIZE_IS
+} ParamAttrType;
+
+/*
+ * Check that parameters referred to by attributes such as size_is exist and
+ * refer to parameters of the appropriate type.
+ */
+static gboolean
+check_param_attribute(IDL_tree method_tree, IDL_tree param,
+ ParamAttrType whattocheck)
+{
+ const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
+ const char *referred_name = NULL;
+ IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec;
+ IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
+ const char *param_name = IDL_IDENT(simple_decl).str;
+ const char *attr_name;
+ const char *needed_type;
+
+ if (whattocheck == IID_IS) {
+ attr_name = "iid_is";
+ needed_type = "IID";
+ } else if (whattocheck == LENGTH_IS) {
+ attr_name = "length_is";
+ needed_type = "unsigned long (or PRUint32)";
+ } else if (whattocheck == SIZE_IS) {
+ attr_name = "size_is";
+ needed_type = "unsigned long (or PRUint32)";
+ } else {
+ XPT_ASSERT("asked to check an unknown attribute type!");
+ return TRUE;
+ }
+
+ referred_name = IDL_tree_property_get(simple_decl, attr_name);
+ if (referred_name != NULL) {
+ IDL_tree referred_param = find_named_parameter(method_tree,
+ referred_name);
+ IDL_tree referred_param_type;
+ if (referred_param == NULL) {
+ IDL_tree_error(method_tree,
+ "attribute [%s(%s)] refers to missing "
+ "parameter \"%s\"",
+ attr_name, referred_name, referred_name);
+ return FALSE;
+ }
+ if (referred_param == param) {
+ IDL_tree_error(method_tree,
+ "attribute [%s(%s)] refers to it's own parameter",
+ attr_name, referred_name);
+ return FALSE;
+ }
+
+ referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec;
+ if (whattocheck == IID_IS) {
+ /* require IID type */
+ if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) {
+ IDL_tree_error(method_tree,
+ "target \"%s\" of [%s(%s)] attribute "
+ "must be of %s type",
+ referred_name, attr_name, referred_name,
+ needed_type);
+ return FALSE;
+ }
+ } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) {
+ /* require PRUint32 type */
+ IDL_tree real_type;
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(referred_param_type);
+ real_type = real_type ? real_type : referred_param_type;
+
+ if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER ||
+ IDL_TYPE_INTEGER(real_type).f_signed != FALSE ||
+ IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG)
+ {
+ IDL_tree_error(method_tree,
+ "target \"%s\" of [%s(%s)] attribute "
+ "must be of %s type",
+ referred_name, attr_name, referred_name,
+ needed_type);
+
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Common method verification code, called by *op_dcl in the various backends.
+ */
+gboolean
+verify_method_declaration(IDL_tree method_tree)
+{
+ struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
+ IDL_tree iface;
+ IDL_tree iter;
+ gboolean notxpcom;
+ gboolean scriptable_interface;
+ gboolean scriptable_method;
+ gboolean seen_retval = FALSE;
+ const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
+
+ /* We don't support attributes named IID, conflicts with static GetIID
+ * member. The conflict is due to certain compilers (VC++) choosing a
+ * different vtable order, placing GetIID at the beginning regardless
+ * of it's placement
+ */
+ if (strcmp(method_name, "GetIID") == 0) {
+ IDL_tree_error(method_tree,
+ "Methods named GetIID not supported, causes vtable "
+ "ordering problems");
+ return FALSE;
+ }
+ if (op->f_varargs) {
+ /* We don't currently support varargs. */
+ IDL_tree_error(method_tree, "varargs are not currently supported");
+ return FALSE;
+ }
+
+ /*
+ * Verify that we've been called on an interface, and decide if the
+ * interface was marked [scriptable].
+ */
+ if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
+ IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree)))
+ == IDLN_INTERFACE)
+ {
+ scriptable_interface =
+ (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
+ != NULL);
+ } else {
+ IDL_tree_error(method_tree,
+ "verify_method_declaration called on a non-interface?");
+ return FALSE;
+ }
+
+ /*
+ * Require that any method in an interface marked as [scriptable], that
+ * *isn't* scriptable because it refers to some native type, be marked
+ * [noscript] or [notxpcom].
+ *
+ * Also check that iid_is points to nsid, and length_is, size_is points
+ * to unsigned long.
+ */
+ notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL;
+
+ scriptable_method = scriptable_interface &&
+ !notxpcom &&
+ IDL_tree_property_get(op->ident, "noscript") == NULL;
+
+ /* Loop through the parameters and check. */
+ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
+ IDL_tree param = IDL_LIST(iter).data;
+ IDL_tree param_type =
+ IDL_PARAM_DCL(param).param_type_spec;
+ IDL_tree simple_decl =
+ IDL_PARAM_DCL(param).simple_declarator;
+ const char *param_name = IDL_IDENT(simple_decl).str;
+
+ /*
+ * Reject this method if it should be scriptable and some parameter is
+ * native that isn't marked with either nsid, domstring, utf8string,
+ * cstring, astring or iid_is.
+ */
+ if (scriptable_method &&
+ UP_IS_NATIVE(param_type) &&
+ IDL_tree_property_get(param_type, "nsid") == NULL &&
+ IDL_tree_property_get(simple_decl, "iid_is") == NULL &&
+ IDL_tree_property_get(param_type, "domstring") == NULL &&
+ IDL_tree_property_get(param_type, "utf8string") == NULL &&
+ IDL_tree_property_get(param_type, "cstring") == NULL &&
+ IDL_tree_property_get(param_type, "astring") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "methods in [scriptable] interfaces that are "
+ "non-scriptable because they refer to native "
+ "types (parameter \"%s\") must be marked "
+ "[noscript]", param_name);
+ return FALSE;
+ }
+
+ /*
+ * nsid's parameters that aren't ptr's or ref's are not currently
+ * supported in xpcom or non-xpcom (marked with [notxpcom]) methods
+ * as input parameters
+ */
+ if (!(notxpcom && IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) &&
+ IDL_tree_property_get(param_type, "nsid") != NULL &&
+ IDL_tree_property_get(param_type, "ptr") == NULL &&
+ IDL_tree_property_get(param_type, "ref") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "Feature currently not supported: "
+ "parameter \"%s\" is of type nsid and "
+ "must be marked either [ptr] or [ref] "
+ "or method \"%s\" must be marked [notxpcom] "
+ "and must not be an input parameter",
+ param_name,
+ method_name);
+ return FALSE;
+ }
+ /*
+ * Sanity checks on return values.
+ */
+ if (IDL_tree_property_get(simple_decl, "retval") != NULL) {
+ if (IDL_LIST(iter).next != NULL) {
+ IDL_tree_error(method_tree,
+ "only the last parameter can be marked [retval]");
+ return FALSE;
+ }
+ if (op->op_type_spec) {
+ IDL_tree_error(method_tree,
+ "can't have [retval] with non-void return type");
+ return FALSE;
+ }
+ /* In case XPConnect relaxes the retval-is-last restriction. */
+ if (seen_retval) {
+ IDL_tree_error(method_tree,
+ "can't have more than one [retval] parameter");
+ return FALSE;
+ }
+ seen_retval = TRUE;
+ }
+
+ /*
+ * Confirm that [shared] attributes are only used with string, wstring,
+ * or native (but not nsid, domstring, utf8string, cstring or astring)
+ * and can't be used with [array].
+ */
+ if (IDL_tree_property_get(simple_decl, "shared") != NULL) {
+ IDL_tree real_type;
+ real_type = find_underlying_type(param_type);
+ real_type = real_type ? real_type : param_type;
+
+ if (IDL_tree_property_get(simple_decl, "array") != NULL) {
+ IDL_tree_error(method_tree,
+ "[shared] parameter \"%s\" cannot "
+ "be of array type", param_name);
+ return FALSE;
+ }
+
+ if (!(IDL_NODE_TYPE(real_type) == IDLN_TYPE_STRING ||
+ IDL_NODE_TYPE(real_type) == IDLN_TYPE_WIDE_STRING ||
+ (UP_IS_NATIVE(real_type) &&
+ !IDL_tree_property_get(real_type, "nsid") &&
+ !IDL_tree_property_get(real_type, "domstring") &&
+ !IDL_tree_property_get(real_type, "utf8string") &&
+ !IDL_tree_property_get(real_type, "cstring") &&
+ !IDL_tree_property_get(real_type, "astring"))))
+ {
+ IDL_tree_error(method_tree,
+ "[shared] parameter \"%s\" must be of type "
+ "string, wstring or native", param_name);
+ return FALSE;
+ }
+ }
+
+ /*
+ * inout is not allowed with "domstring", "UTF8String", "CString"
+ * and "AString" types
+ */
+ if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT &&
+ UP_IS_NATIVE(param_type) &&
+ (IDL_tree_property_get(param_type, "domstring") != NULL ||
+ IDL_tree_property_get(param_type, "utf8string") != NULL ||
+ IDL_tree_property_get(param_type, "cstring") != NULL ||
+ IDL_tree_property_get(param_type, "astring") != NULL )) {
+ IDL_tree_error(method_tree,
+ "[domstring], [utf8string], [cstring], [astring] "
+ "types cannot be used as inout parameters");
+ return FALSE;
+ }
+
+
+ /*
+ * arrays of domstring, utf8string, cstring, astring types not allowed
+ */
+ if (IDL_tree_property_get(simple_decl, "array") != NULL &&
+ UP_IS_NATIVE(param_type) &&
+ (IDL_tree_property_get(param_type, "domstring") != NULL ||
+ IDL_tree_property_get(param_type, "utf8string") != NULL ||
+ IDL_tree_property_get(param_type, "cstring") != NULL ||
+ IDL_tree_property_get(param_type, "astring") != NULL)) {
+ IDL_tree_error(method_tree,
+ "[domstring], [utf8string], [cstring], [astring] "
+ "types cannot be used in array parameters");
+ return FALSE;
+ }
+
+ if (!check_param_attribute(method_tree, param, IID_IS) ||
+ !check_param_attribute(method_tree, param, LENGTH_IS) ||
+ !check_param_attribute(method_tree, param, SIZE_IS))
+ return FALSE;
+
+ /*
+ * Run additional error checks on the parameter type if targetting an
+ * older version of XPConnect.
+ */
+
+ if (!verify_type_fits_version(param_type, method_tree))
+ return FALSE;
+
+ }
+
+ /* XXX q: can return type be nsid? */
+ /* Native return type? */
+ if (scriptable_method &&
+ op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) &&
+ IDL_tree_property_get(op->op_type_spec, "nsid") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "domstring") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "cstring") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "astring") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "methods in [scriptable] interfaces that are "
+ "non-scriptable because they return native "
+ "types must be marked [noscript]");
+ return FALSE;
+ }
+
+
+ /*
+ * nsid's parameters that aren't ptr's or ref's are not currently
+ * supported in xpcom
+ */
+ if (!notxpcom &&
+ op->op_type_spec != NULL &&
+ IDL_tree_property_get(op->op_type_spec, "nsid") != NULL &&
+ IDL_tree_property_get(op->op_type_spec, "ptr") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "ref") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "Feature currently not supported: "
+ "return value is of type nsid and "
+ "must be marked either [ptr] or [ref], "
+ "or else method \"%s\" must be marked [notxpcom] ",
+ method_name);
+ return FALSE;
+ }
+
+ /*
+ * Run additional error checks on the return type if targetting an
+ * older version of XPConnect.
+ */
+
+ if (op->op_type_spec != NULL &&
+ !verify_type_fits_version(op->op_type_spec, method_tree))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Verify that a native declaration has an associated C++ expression, i.e. that
+ * it's of the form native <idl-name>(<c++-name>)
+ */
+gboolean
+check_native(TreeState *state)
+{
+ char *native_name;
+ /* require that native declarations give a native type */
+ if (IDL_NATIVE(state->tree).user_type)
+ return TRUE;
+ native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str;
+ IDL_tree_error(state->tree,
+ "``native %s;'' needs C++ type: ``native %s(<C++ type>);''",
+ native_name, native_name);
+ return FALSE;
+}
+
+/*
+ * Print a GSList as char strings to a file.
+ */
+void
+printlist(FILE *outfile, GSList *slist)
+{
+ guint i;
+ guint len = g_slist_length(slist);
+
+ for(i = 0; i < len; i++) {
+ fprintf(outfile,
+ "%s\n", (char *)g_slist_nth_data(slist, i));
+ }
+}
+
+void
+xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
+{
+ IDL_tree_func_data tfd;
+
+ while (p) {
+ struct _IDL_LIST *list = &IDL_LIST(p);
+ tfd.tree = list->data;
+ if (!foreach(&tfd, user_data))
+ return;
+ p = list->next;
+ }
+}
+
+/*
+ * Verify that the interface declaration is correct
+ */
+gboolean
+verify_interface_declaration(IDL_tree interface_tree)
+{
+ IDL_tree iter;
+ /*
+ * If we have the scriptable attribute then make sure all of our direct
+ * parents have it as well.
+ * NOTE: We don't recurse since all interfaces will fall through here
+ */
+ if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
+ "scriptable")) {
+ for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter;
+ iter = IDL_LIST(iter).next) {
+ if (IDL_tree_property_get(
+ IDL_INTERFACE(iter).ident, "scriptable") == 0) {
+ XPIDL_WARNING((interface_tree,IDL_WARNING1,
+ "%s is scriptable but inherits from the non-scriptable interface %s\n",
+ IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str,
+ IDL_IDENT(IDL_INTERFACE(iter).ident).str));
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Return a pointer to the start of the base filename of path
+ */
+char *
+xpidl_basename(const char * path)
+{
+ char * result = g_path_get_basename(path);
+ /*
+ *If this is windows then we'll handle either / or \ as a separator
+ * g_basename only handles \ for windows
+ */
+#if defined(XP_WIN32)
+# error adapt regarding g_basename() vs. g_path_get_basename()!
+ const char * slash = strrchr(path, '/');
+ /* If we found a slash and its after the current default OS separator */
+ if (slash != NULL && (slash > result))
+ result = slash + 1;
+#endif
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in
new file mode 100644
index 00000000..1447128f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in
@@ -0,0 +1,50 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+DIRS = public src tools
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in
new file mode 100644
index 00000000..3e452486
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in
@@ -0,0 +1,51 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+EXPORTS = xpt_arena.h xpt_struct.h xpt_xdr.h
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h
new file mode 100644
index 00000000..2b277467
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Simple arena allocator for xpt (which avoids using NSPR).
+ */
+
+#ifndef __xpt_arena_h__
+#define __xpt_arena_h__
+
+#include "prtypes.h"
+#include <stdlib.h>
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPT_NewArena VBoxNsxpXPT_NewArena
+#define XPT_ArenaMalloc VBoxNsxpXPT_ArenaMalloc
+#define XPT_DestroyArena VBoxNsxpXPT_DestroyArena
+#define XPT_ArenaFree VBoxNsxpXPT_ArenaFree
+#define XPT_DestroyArena VBoxNsxpXPT_DestroyArena
+#define XPT_DumpStats VBoxNsxpXPT_DumpStats
+#define XPT_NotifyDoneLoading VBoxNsxpXPT_NotifyDoneLoading
+#define XPT_ArenaStrDup VBoxNsxpXPT_ArenaStrDup
+#define XPT_AssertFailed VBoxNsxpXPT_AssertFailed
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*
+ * The linkage of XPT API functions differs depending on whether the file is
+ * used within the XPT library or not. Any source file within the XPT
+ * library should define EXPORT_XPT_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPT_API
+#define XPT_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPT_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#else
+#ifdef _WIN32
+# define XPT_PUBLIC_API(t) __declspec(dllimport) t
+# define XPT_PUBLIC_DATA(t) __declspec(dllimport) t
+#else
+# define XPT_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPT_PUBLIC_DATA(t) t
+#endif
+#endif
+#define XPT_FRIEND_API(t) XPT_PUBLIC_API(t)
+#define XPT_FRIEND_DATA(t) XPT_PUBLIC_DATA(t)
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Simple Arena support. Use with caution!
+ */
+
+typedef struct XPTArena XPTArena;
+
+XPT_PUBLIC_API(XPTArena *)
+XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name);
+
+XPT_PUBLIC_API(void)
+XPT_DestroyArena(XPTArena *arena);
+
+XPT_PUBLIC_API(void)
+XPT_DumpStats(XPTArena *arena);
+
+XPT_PUBLIC_API(void *)
+XPT_ArenaMalloc(XPTArena *arena, size_t size);
+
+XPT_PUBLIC_API(char *)
+XPT_ArenaStrDup(XPTArena *arena, const char * s);
+
+XPT_PUBLIC_API(void)
+XPT_NotifyDoneLoading(XPTArena *arena);
+
+XPT_PUBLIC_API(void)
+XPT_ArenaFree(XPTArena *arena, void* block);
+
+/* --------------------------------------------------------- */
+
+#define XPT_MALLOC(_arena, _bytes) \
+ XPT_ArenaMalloc((_arena), (_bytes))
+
+#ifdef DEBUG
+#define XPT_FREE(_arena, _ptr) \
+ XPT_ArenaFree((_arena), (_ptr))
+#else
+#define XPT_FREE(_arena, _ptr) \
+ ((void)0)
+#endif
+
+#define XPT_STRDUP(_arena, _s) \
+ XPT_ArenaStrDup((_arena), (_s))
+
+#define XPT_CALLOC(_arena, _size) XPT_MALLOC((_arena), (_size))
+#define XPT_NEW(_arena, _struct) ((_struct *) XPT_MALLOC((_arena), sizeof(_struct)))
+#define XPT_NEWZAP(_arena, _struct) XPT_NEW((_arena), _struct)
+#define XPT_DELETE(_arena, _ptr) do{XPT_FREE((_arena), (_ptr)); ((_ptr)) = NULL;}while(0)
+#define XPT_FREEIF(_arena, _ptr) do{if ((_ptr)) XPT_FREE((_arena), (_ptr));}while(0)
+
+/* --------------------------------------------------------- */
+
+#ifdef DEBUG
+XPT_PUBLIC_API(void)
+XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno);
+#define XPT_ASSERT(_expr) \
+ ((_expr)?((void)0):XPT_AssertFailed(# _expr, __FILE__, __LINE__))
+#else
+#define XPT_ASSERT(_expr) ((void)0)
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* __xpt_arena_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h
new file mode 100644
index 00000000..c7f36f2d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h
@@ -0,0 +1,562 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Structures matching the in-memory representation of typelib structures.
+ * http://www.mozilla.org/scriptable/typelib_file.html
+ */
+
+#ifndef __xpt_struct_h__
+#define __xpt_struct_h__
+
+#include "xpt_arena.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPT_NewHeader VBoxNsxpXPT_NewHeader
+#define XPT_NewStringZ VBoxNsxpXPT_NewStringZ
+#define XPT_NewAnnotation VBoxNsxpXPT_NewAnnotation
+#define XPT_SizeOfHeaderBlock VBoxNsxpXPT_SizeOfHeaderBlock
+#define XPT_NewInterfaceDescriptor VBoxNsxpXPT_NewInterfaceDescriptor
+#define XPT_FillInterfaceDirectoryEntry VBoxNsxpXPT_FillInterfaceDirectoryEntry
+#define XPT_FillMethodDescriptor VBoxNsxpXPT_FillMethodDescriptor
+#define XPT_FreeHeader VBoxNsxpXPT_FreeHeader
+#define XPT_ParseVersionString VBoxNsxpXPT_ParseVersionString
+#define XPT_DestroyInterfaceDirectoryEntry VBoxNsxpXPT_DestroyInterfaceDirectoryEntry
+#define XPT_FillParamDescriptor VBoxNsxpXPT_FillParamDescriptor
+#define XPT_FreeInterfaceDescriptor VBoxNsxpXPT_FreeInterfaceDescriptor
+#define XPT_InterfaceDescriptorAddConsts VBoxNsxpXPT_InterfaceDescriptorAddConsts
+#define XPT_InterfaceDescriptorAddMethods VBoxNsxpXPT_InterfaceDescriptorAddMethods
+#define XPT_InterfaceDescriptorAddTypes VBoxNsxpXPT_InterfaceDescriptorAddTypes
+#define XPT_GetInterfaceIndexByName VBoxNsxpXPT_GetInterfaceIndexByName
+#define XPT_NewString VBoxNsxpXPT_NewString
+#define XPT_SizeOfHeader VBoxNsxpXPT_SizeOfHeader
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Originally, I was going to have structures that exactly matched the on-disk
+ * representation, but that proved difficult: different compilers can pack
+ * their structs differently, and that makes overlaying them atop a
+ * read-from-disk byte buffer troublesome. So now I just have some structures
+ * that are used in memory, and we're going to write a nice XDR library to
+ * write them to disk and stuff. It is pure joy. -- shaver
+ */
+
+/* Structures for the typelib components */
+
+typedef struct XPTHeader XPTHeader;
+typedef struct XPTInterfaceDirectoryEntry XPTInterfaceDirectoryEntry;
+typedef struct XPTInterfaceDescriptor XPTInterfaceDescriptor;
+typedef struct XPTConstDescriptor XPTConstDescriptor;
+typedef struct XPTMethodDescriptor XPTMethodDescriptor;
+typedef struct XPTParamDescriptor XPTParamDescriptor;
+typedef struct XPTTypeDescriptor XPTTypeDescriptor;
+typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix;
+typedef struct XPTString XPTString;
+typedef struct XPTAnnotation XPTAnnotation;
+#ifndef nsID_h__
+/*
+ * We can't include nsID.h, because it's full of C++ goop and we're not doing
+ * C++ here, so we define our own minimal struct. We protect against multiple
+ * definitions of this struct, though, and use the same field naming.
+ */
+struct nsID {
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+};
+
+typedef struct nsID nsID;
+#endif
+
+#define XPT_COPY_IID(to, from) \
+ (to).m0 = (from).m0; \
+ (to).m1 = (from).m1; \
+ (to).m2 = (from).m2; \
+ (to).m3[0] = (from).m3[0]; \
+ (to).m3[1] = (from).m3[1]; \
+ (to).m3[2] = (from).m3[2]; \
+ (to).m3[3] = (from).m3[3]; \
+ (to).m3[4] = (from).m3[4]; \
+ (to).m3[5] = (from).m3[5]; \
+ (to).m3[6] = (from).m3[6]; \
+ (to).m3[7] = (from).m3[7];
+
+
+/*
+ * Every XPCOM typelib file begins with a header.
+ */
+struct XPTHeader {
+ PRUint8 magic[16];
+ PRUint8 major_version;
+ PRUint8 minor_version;
+ PRUint16 num_interfaces;
+ PRUint32 file_length;
+ XPTInterfaceDirectoryEntry *interface_directory;
+ PRUint32 data_pool;
+ XPTAnnotation *annotations;
+};
+
+#define XPT_MAGIC "XPCOM\nTypeLib\r\n\032"
+/* For error messages. */
+#define XPT_MAGIC_STRING "XPCOM\\nTypeLib\\r\\n\\032"
+#define XPT_MAJOR_VERSION 0x01
+#define XPT_MINOR_VERSION 0x02
+
+/* Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION
+ * or higher is to be considered incompatible by this version of xpt and
+ * we will refuse to read it. We will return a header with magic, major and
+ * minor versions set from the file. num_interfaces and file_length will be
+ * set to zero to confirm our inability to read the file; i.e. even if some
+ * client of this library gets out of sync with us regarding the agreed upon
+ * value for XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces and
+ * file_length are both zero we *know* that this library refused to read the
+ * file due to version imcompatibility.
+ */
+#define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02
+
+/*
+ * The "[-t version number]" cmd line parameter to the XPIDL compiler and XPT
+ * linker specifies the major and minor version number of the output
+ * type library.
+ *
+ * The goal is for the compiler to check that the input IDL file only uses
+ * constructs that are supported in the version specified. The linker will
+ * check that all typelib files it reads are of the version specified or
+ * below.
+ *
+ * Both the compiler and the linker will report errors and abort if these
+ * checks fail.
+ *
+ * When you rev up major or minor versions of the type library in the future,
+ * think about the new stuff that you added to the type library and add checks
+ * to make sure that occurrences of that new "stuff" will get caught when [-t
+ * version number] is used with the compiler. Here's what you'll probably
+ * have to do each time you rev up major/minor versions:
+ *
+ * 1) Add the current version number string (before your change) to the
+ * XPT_TYPELIB_VERSIONS list.
+ *
+ * 2) Do your changes add new features to XPIDL? Ensure that those new
+ * features are rejected by the XPIDL compiler when any version number in
+ * the XPT_TYPELIB_VERSIONS list is specified on the command line. The
+ * one place that currently does this kind of error checking is the function
+ * verify_type_fits_version() in xpidl_util.c. It currently checks
+ * attribute types, parameter types, and return types. You'll probably have
+ * to add to it or generalize it further based on what kind of changes you
+ * are making.
+ *
+ * 3) You will probably NOT need to make any changes to the error checking
+ * in the linker.
+ */
+
+#define XPT_VERSION_UNKNOWN 0
+#define XPT_VERSION_UNSUPPORTED 1
+#define XPT_VERSION_OLD 2
+#define XPT_VERSION_CURRENT 3
+
+typedef struct {
+ const char* str;
+ PRUint8 major;
+ PRUint8 minor;
+ PRUint16 code;
+} XPT_TYPELIB_VERSIONS_STRUCT;
+
+/* Currently accepted list of versions for typelibs */
+#define XPT_TYPELIB_VERSIONS { \
+ {"1.0", 1, 0, XPT_VERSION_UNSUPPORTED}, \
+ {"1.1", 1, 1, XPT_VERSION_OLD}, \
+ {"1.2", 1, 2, XPT_VERSION_CURRENT} \
+}
+
+extern XPT_PUBLIC_API(PRUint16)
+XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor);
+
+extern XPT_PUBLIC_API(XPTHeader *)
+XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces,
+ PRUint8 major_version, PRUint8 minor_version);
+
+extern XPT_PUBLIC_API(void)
+XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader);
+
+/* size of header and annotations */
+extern XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeader(XPTHeader *header);
+
+/* size of header and annotations and InterfaceDirectoryEntries */
+extern XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeaderBlock(XPTHeader *header);
+
+/*
+ * A contiguous array of fixed-size InterfaceDirectoryEntry records begins at
+ * the byte offset identified by the interface_directory field in the file
+ * header. The array is used to quickly locate an interface description
+ * using its IID. No interface should appear more than once in the array.
+ */
+struct XPTInterfaceDirectoryEntry {
+ nsID iid;
+ char *name;
+ char *name_space;
+ XPTInterfaceDescriptor *interface_descriptor;
+
+#if 0 /* not yet */
+ /* not stored on disk */
+ PRUint32 offset; /* the offset for an ID still to be read */
+#endif
+};
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry *ide,
+ nsID *iid, char *name, char *name_space,
+ XPTInterfaceDescriptor *descriptor);
+
+extern XPT_PUBLIC_API(void)
+XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry* ide);
+
+/*
+ * An InterfaceDescriptor is a variable-size record used to describe a
+ * single XPCOM interface, including all of its methods.
+ */
+struct XPTInterfaceDescriptor {
+ PRUint16 parent_interface;
+ PRUint16 num_methods;
+ XPTMethodDescriptor *method_descriptors;
+ PRUint16 num_constants;
+ XPTConstDescriptor *const_descriptors;
+ PRUint8 flags;
+
+ /* additional_types are used for arrays where we may need multiple
+ * XPTTypeDescriptors for a single XPTMethodDescriptor. Since we still
+ * want to have a simple array of XPTMethodDescriptor (each with a single
+ * embedded XPTTypeDescriptor), a XPTTypeDescriptor can have a reference
+ * to an 'additional_type'. That reference is an index in this
+ * "additional_types" array. So a given XPTMethodDescriptor might have
+ * a whole chain of these XPTTypeDescriptors to represent, say, a multi
+ * dimensional array.
+ *
+ * Note that in the typelib file these additional types are stored 'inline'
+ * in the MethodDescriptor. But, in the typelib MethodDescriptors can be
+ * of varying sizes, where in XPT's in memory mapping of the data we want
+ * them to be of fixed size. This additional_types scheme is here to allow
+ * for that.
+ */
+
+ XPTTypeDescriptor *additional_types;
+ PRUint16 num_additional_types;
+};
+
+#define XPT_ID_SCRIPTABLE 0x80
+#define XPT_ID_FUNCTION 0x40
+#define XPT_ID_FLAGMASK 0xc0
+#define XPT_ID_TAGMASK (~XPT_ID_FLAGMASK)
+#define XPT_ID_TAG(id) ((id).flags & XPT_ID_TAGMASK)
+
+#define XPT_ID_IS_SCRIPTABLE(flags) (flags & XPT_ID_SCRIPTABLE)
+#define XPT_ID_IS_FUNCTION(flags) (flags & XPT_ID_FUNCTION)
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
+ PRUint16 num_interfaces, char *name,
+ PRUint16 *indexp);
+
+extern XPT_PUBLIC_API(XPTInterfaceDescriptor *)
+XPT_NewInterfaceDescriptor(XPTArena *arena,
+ PRUint16 parent_interface, PRUint16 num_methods,
+ PRUint16 num_constants, PRUint8 flags);
+
+extern XPT_PUBLIC_API(void)
+XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num);
+
+/*
+ * This is our special string struct with a length value associated with it,
+ * which means that it can contains embedded NULs.
+ */
+struct XPTString {
+ PRUint16 length;
+ char *bytes;
+};
+
+extern XPT_PUBLIC_API(XPTString *)
+XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes);
+
+extern XPT_PUBLIC_API(XPTString *)
+XPT_NewStringZ(XPTArena *arena, char *bytes);
+
+/*
+ * A TypeDescriptor is a variable-size record used to identify the type of a
+ * method argument or return value.
+ *
+ * There are three types of TypeDescriptors:
+ *
+ * SimpleTypeDescriptor
+ * InterfaceTypeDescriptor
+ * InterfaceIsTypeDescriptor
+ *
+ * The tag field in the prefix indicates which of the variant TypeDescriptor
+ * records is being used, and hence the way any remaining fields should be
+ * parsed. Values from 0 to 17 refer to SimpleTypeDescriptors. The value 18
+ * designates an InterfaceTypeDescriptor, while 19 represents an
+ * InterfaceIsTypeDescriptor.
+ */
+
+/* why bother with a struct? - other code relies on this being a struct */
+struct XPTTypeDescriptorPrefix {
+ PRUint8 flags;
+};
+
+/* flag bits -- fur and jband were right, I was miserably wrong */
+#define XPT_TDP_POINTER 0x80
+#define XPT_TDP_UNIQUE_POINTER 0x40
+#define XPT_TDP_REFERENCE 0x20
+#define XPT_TDP_FLAGMASK 0xe0
+#define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK)
+#define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK)
+
+#define XPT_TDP_IS_POINTER(flags) (flags & XPT_TDP_POINTER)
+#define XPT_TDP_IS_UNIQUE_POINTER(flags) (flags & XPT_TDP_UNIQUE_POINTER)
+#define XPT_TDP_IS_REFERENCE(flags) (flags & XPT_TDP_REFERENCE)
+
+/*
+ * The following enum maps mnemonic names to the different numeric values
+ * of XPTTypeDescriptor->tag.
+ */
+enum XPTTypeDescriptorTags {
+ TD_INT8 = 0,
+ TD_INT16 = 1,
+ TD_INT32 = 2,
+ TD_INT64 = 3,
+ TD_UINT8 = 4,
+ TD_UINT16 = 5,
+ TD_UINT32 = 6,
+ TD_UINT64 = 7,
+ TD_FLOAT = 8,
+ TD_DOUBLE = 9,
+ TD_BOOL = 10,
+ TD_CHAR = 11,
+ TD_WCHAR = 12,
+ TD_VOID = 13,
+ TD_PNSIID = 14,
+ TD_DOMSTRING = 15,
+ TD_PSTRING = 16,
+ TD_PWSTRING = 17,
+ TD_INTERFACE_TYPE = 18,
+ TD_INTERFACE_IS_TYPE = 19,
+ TD_ARRAY = 20,
+ TD_PSTRING_SIZE_IS = 21,
+ TD_PWSTRING_SIZE_IS = 22,
+ TD_UTF8STRING = 23,
+ TD_CSTRING = 24,
+ TD_ASTRING = 25
+};
+
+struct XPTTypeDescriptor {
+ XPTTypeDescriptorPrefix prefix;
+ PRUint8 argnum; /* used for iid_is and size_is */
+ PRUint8 argnum2; /* used for length_is */
+ union {
+ PRUint16 iface; /* used for TD_INTERFACE_TYPE */
+ PRUint16 additional_type; /* used for TD_ARRAY */
+ } type;
+};
+
+#define XPT_COPY_TYPE(to, from) \
+ (to).prefix.flags = (from).prefix.flags; \
+ (to).argnum = (from).argnum; \
+ (to).argnum2 = (from).argnum2; \
+ (to).type.additional_type = (from).type.additional_type;
+
+/*
+ * A ConstDescriptor is a variable-size record that records the name and
+ * value of a scoped interface constant.
+ *
+ * The types of the method parameter are restricted to the following subset
+ * of TypeDescriptors:
+ *
+ * int8, uint8, int16, uint16, int32, uint32,
+ * int64, uint64, wchar_t, char, string
+ *
+ * The type (and thus the size) of the value record is determined by the
+ * contents of the associated TypeDescriptor record. For instance, if type
+ * corresponds to int16, then value is a two-byte record consisting of a
+ * 16-bit signed integer. For a ConstDescriptor type of string, the value
+ * record is of type String*, i.e. an offset within the data pool to a
+ * String record containing the constant string.
+ */
+union XPTConstValue {
+ PRInt8 i8;
+ PRUint8 ui8;
+ PRInt16 i16;
+ PRUint16 ui16;
+ PRInt32 i32;
+ PRUint32 ui32;
+ PRInt64 i64;
+ PRUint64 ui64;
+ float flt;
+ double dbl;
+ PRBool bul;
+ char ch;
+ PRUint16 wch;
+ nsID *iid;
+ XPTString *string;
+ char *str;
+ PRUint16 *wstr;
+}; /* varies according to type */
+
+struct XPTConstDescriptor {
+ char *name;
+ XPTTypeDescriptor type;
+ union XPTConstValue value;
+};
+
+/*
+ * A ParamDescriptor is a variable-size record used to describe either a
+ * single argument to a method or a method's result.
+ */
+struct XPTParamDescriptor {
+ PRUint8 flags;
+ XPTTypeDescriptor type;
+};
+
+/* flag bits -- jband and fur were right, and I was miserably wrong */
+#define XPT_PD_IN 0x80
+#define XPT_PD_OUT 0x40
+#define XPT_PD_RETVAL 0x20
+#define XPT_PD_SHARED 0x10
+#define XPT_PD_DIPPER 0x08
+#define XPT_PD_FLAGMASK 0xf8
+
+#define XPT_PD_IS_IN(flags) (flags & XPT_PD_IN)
+#define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT)
+#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
+#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
+#define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER)
+
+/* this is bogus
+#define XPT_PARAMDESCRIPTOR_SIZE (XPT_TYPEDESCRIPTOR_SIZE + 1)
+*/
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_FillParamDescriptor(XPTArena *arena,
+ XPTParamDescriptor *pd, PRUint8 flags,
+ XPTTypeDescriptor *type);
+
+/*
+ * A MethodDescriptor is a variable-size record used to describe a single
+ * interface method.
+ */
+struct XPTMethodDescriptor {
+ char *name;
+ XPTParamDescriptor *params;
+ XPTParamDescriptor *result;
+ PRUint8 flags;
+ PRUint8 num_args;
+};
+
+/* flag bits -- jband and fur were right, and I was miserably wrong */
+#define XPT_MD_GETTER 0x80
+#define XPT_MD_SETTER 0x40
+#define XPT_MD_NOTXPCOM 0x20
+#define XPT_MD_CTOR 0x10
+#define XPT_MD_HIDDEN 0x08
+#define XPT_MD_FLAGMASK 0xf8
+
+#define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER)
+#define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER)
+#define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM)
+#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR)
+#define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN)
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_FillMethodDescriptor(XPTArena *arena,
+ XPTMethodDescriptor *meth, PRUint8 flags, char *name,
+ PRUint8 num_args);
+
+/*
+ * Annotation records are variable-size records used to store secondary
+ * information about the typelib, e.g. such as the name of the tool that
+ * generated the typelib file, the date it was generated, etc. The
+ * information is stored with very loose format requirements so as to
+ * allow virtually any private data to be stored in the typelib.
+ *
+ * There are two types of Annotations:
+ *
+ * EmptyAnnotation
+ * PrivateAnnotation
+ *
+ * The tag field of the prefix discriminates among the variant record
+ * types for Annotation's. If the tag is 0, this record is an
+ * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to
+ * indicate an array of Annotation's that's completely empty. If the tag
+ * is 1, the record is a PrivateAnnotation.
+ */
+
+struct XPTAnnotation {
+ XPTAnnotation *next;
+ PRUint8 flags;
+ /* remaining fields are present in typelib iff XPT_ANN_IS_PRIVATE */
+ XPTString *creator;
+ XPTString *private_data;
+};
+
+#define XPT_ANN_LAST 0x80
+#define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST)
+#define XPT_ANN_PRIVATE 0x40
+#define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE)
+
+extern XPT_PUBLIC_API(XPTAnnotation *)
+XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator,
+ XPTString *private_data);
+
+PR_END_EXTERN_C
+
+#endif /* __xpt_struct_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h
new file mode 100644
index 00000000..89d1c3f6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h
@@ -0,0 +1,240 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Basic APIs for streaming typelib structures to/from disk.
+ */
+
+#ifndef __xpt_xdr_h__
+#define __xpt_xdr_h__
+
+#include "xpt_struct.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPT_Do8 VBoxNsxpXPT_Do8
+#define XPT_Do16 VBoxNsxpXPT_Do16
+#define XPT_Do32 VBoxNsxpXPT_Do32
+#define XPT_Do64 VBoxNsxpXPT_Do64
+#define XPT_DoIID VBoxNsxpXPT_DoIID
+#define XPT_DoCString VBoxNsxpXPT_DoCString
+#define XPT_DoString VBoxNsxpXPT_DoString
+#define XPT_DoStringInline VBoxNsxpXPT_DoStringInline
+#define XPT_NewXDRState VBoxNsxpXPT_NewXDRState
+#define XPT_SetDataOffset VBoxNsxpXPT_SetDataOffset
+#define XPT_SeekTo VBoxNsxpXPT_SeekTo
+#define XPT_MakeCursor VBoxNsxpXPT_MakeCursor
+#define XPT_DestroyXDRState VBoxNsxpXPT_DestroyXDRState
+#define XPT_GetXDRData VBoxNsxpXPT_GetXDRData
+#define XPT_GetXDRDataLength VBoxNsxpXPT_GetXDRDataLength
+#define XPT_DoHeader VBoxNsxpXPT_DoHeader
+#define XPT_DoHeaderPrologue VBoxNsxpXPT_DoHeaderPrologue
+#define XPT_UpdateFileLength VBoxNsxpXPT_UpdateFileLength
+#define XPT_DataOffset VBoxNsxpXPT_DataOffset
+#define XPT_GetOffsetForAddr VBoxNsxpXPT_GetOffsetForAddr
+#define XPT_SetOffsetForAddr VBoxNsxpXPT_SetOffsetForAddr
+#define XPT_SetAddrForOffset VBoxNsxpXPT_SetAddrForOffset
+#define XPT_GetAddrForOffset VBoxNsxpXPT_GetAddrForOffset
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct XPTState XPTState;
+typedef struct XPTDatapool XPTDatapool;
+typedef struct XPTCursor XPTCursor;
+
+/* Opaque type, for internal use */
+typedef struct XPTHashTable XPTHashTable;
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **strp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoIID(XPTCursor *cursor, nsID *iidp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do64(XPTCursor *cursor, PRInt64 *u64p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do32(XPTCursor *cursor, PRUint32 *u32p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do16(XPTCursor *cursor, PRUint16 *u16p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do8(XPTCursor *cursor, PRUint8 *u8p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset);
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp);
+
+typedef enum {
+ XPT_ENCODE,
+ XPT_DECODE
+} XPTMode;
+
+typedef enum {
+ XPT_HEADER = 0,
+ XPT_DATA = 1
+} XPTPool;
+
+struct XPTState {
+ XPTMode mode;
+ PRUint32 data_offset;
+ PRUint32 next_cursor[2];
+ XPTDatapool *pool;
+ XPTArena *arena;
+};
+
+struct XPTDatapool {
+ XPTHashTable *offset_map;
+ char *data;
+ PRUint32 count;
+ PRUint32 allocated;
+};
+
+struct XPTCursor {
+ XPTState *state;
+ XPTPool pool;
+ PRUint32 offset;
+ PRUint8 bits;
+};
+
+extern XPT_PUBLIC_API(XPTState *)
+XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_SeekTo(XPTCursor *cursor, PRUint32 offset);
+
+extern XPT_PUBLIC_API(void)
+XPT_DestroyXDRState(XPTState *state);
+
+/* Set file_length based on the data used in the state. (Only ENCODE.) */
+extern XPT_PUBLIC_API(PRBool)
+XPT_UpdateFileLength(XPTState *state);
+
+/* returns the length of the specified data block */
+extern XPT_PUBLIC_API(void)
+XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len);
+
+extern XPT_PUBLIC_API(void)
+XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len);
+
+/* set or get the data offset for the state, depending on mode */
+extern XPT_PUBLIC_API(void)
+XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp);
+
+extern XPT_PUBLIC_API(void)
+XPT_SetDataOffset(XPTState *state, PRUint32 data_offset);
+
+extern XPT_PUBLIC_API(PRUint32)
+XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr);
+
+extern XPT_PUBLIC_API(void *)
+XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset);
+
+/* all data structures are big-endian */
+
+#if defined IS_BIG_ENDIAN
+# ifdef VBOX
+# error "Misconfigured endian!"
+# endif
+# define XPT_SWAB32(x) x
+# define XPT_SWAB16(x) x
+#elif defined IS_LITTLE_ENDIAN
+# define XPT_SWAB32(x) (((x) >> 24) | \
+ (((x) >> 8) & 0xff00) | \
+ (((x) << 8) & 0xff0000) | \
+ ((x) << 24))
+# define XPT_SWAB16(x) (((x) >> 8) | ((x) << 8))
+#else
+# error "unknown byte order"
+#endif
+
+/*
+ * If we're decoding, we want to read the offset before we check
+ * for already-decoded values.
+ *
+ * Then we check for repetition: CheckForRepeat will see if we've already
+ * encoded/decoded this value, and if so will set offset/addr correctly
+ * and make already be true. If not, it will set up the cursor for
+ * encoding (reserve space) or decoding (seek to correct location) as
+ * appropriate. In the encode case, it will also set the addr->offset
+ * mapping.
+ */
+
+#define XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \
+ XPTMode mode = cursor->state->mode; \
+ if (!(mode == XPT_ENCODE || XPT_Do32(cursor, &new_curs.offset)) || \
+ !CheckForRepeat(cursor, (void **)addrp, pool, \
+ mode == XPT_ENCODE ? size : 0u, &new_curs, \
+ &already) || \
+ !(mode == XPT_DECODE || XPT_Do32(cursor, &new_curs.offset))) \
+ return PR_FALSE; \
+ if (already) \
+ return PR_TRUE; \
+
+#define XPT_PREAMBLE_NO_ALLOC(cursor, addrp, pool, size, new_curs, already) \
+ { \
+ XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \
+ }
+
+#define XPT_ERROR_HANDLE(arena, free_it) \
+ error: \
+ if (cursor->state->mode == XPT_DECODE) \
+ XPT_FREEIF(arena, free_it); \
+ return PR_FALSE;
+
+
+PR_END_EXTERN_C
+
+#endif /* __xpt_xdr_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in
new file mode 100644
index 00000000..e0578556
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in
@@ -0,0 +1,76 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xpt
+LIB_IS_C_ONLY = 1
+ifdef CROSS_COMPILE
+HOST_LIBRARY_NAME = hostxpt
+endif
+
+CSRCS = xpt_arena.c xpt_struct.c xpt_xdr.c
+HOST_CSRCS = $(CSRCS)
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPT_API
+HOST_CFLAGS += -DEXPORT_XPT_API
+
+# Build libxpt early so that it'll be available to xpidl, which also
+# must be built early.
+export::
+ @$(MAKE) libs
+
+ifdef CROSS_COMPILE
+ifdef HOST_NSPR_MDCPUCFG
+HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
+endif
+endif
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c
new file mode 100644
index 00000000..a0813b8f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c
@@ -0,0 +1,358 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Quick arena hack for xpt. */
+
+/* XXX This exists because we don't want to drag in NSPR. It *seemed*
+* to make more sense to write a quick and dirty arena than to clone
+* plarena (like js/src did). This is not optimal, but it works.
+* Half of the code here is instrumentation.
+*/
+
+#include "xpt_arena.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+
+/*************************/
+/* logging stats support */
+
+#if 0 && defined(DEBUG_jband)
+#define XPT_ARENA_LOGGING 1
+#endif
+
+#ifdef XPT_ARENA_LOGGING
+
+#define LOG_MALLOC(_a, _req, _used) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ ++(_a)->LOG_MallocCallCount; \
+ (_a)->LOG_MallocTotalBytesRequested += (_req); \
+ (_a)->LOG_MallocTotalBytesUsed += (_used); \
+ } while(0)
+
+#define LOG_REAL_MALLOC(_a, _size) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ ++(_a)->LOG_RealMallocCallCount; \
+ (_a)->LOG_RealMallocTotalBytesRequested += (_size); \
+ } while(0)
+
+#define LOG_FREE(_a) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ ++(_a)->LOG_FreeCallCount; \
+ } while(0)
+
+#define LOG_DONE_LOADING(_a) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ (_a)->LOG_LoadingFreeCallCount = (_a)->LOG_FreeCallCount; \
+ } while(0)
+
+#define PRINT_STATS(_a) xpt_DebugPrintArenaStats((_a))
+static void xpt_DebugPrintArenaStats(XPTArena *arena);
+
+#else /* !XPT_ARENA_LOGGING */
+
+#define LOG_MALLOC(_a, _req, _used) ((void)0)
+#define LOG_REAL_MALLOC(_a, _size) ((void)0)
+#define LOG_FREE(_a) ((void)0)
+
+#define LOG_DONE_LOADING(_a) ((void)0)
+#define PRINT_STATS(_a) ((void)0)
+
+#endif /* XPT_ARENA_LOGGING */
+
+/****************************************************/
+
+/* Block header for each block in the arena */
+typedef struct BLK_HDR BLK_HDR;
+struct BLK_HDR
+{
+ BLK_HDR *next;
+ size_t size;
+};
+
+#define XPT_MIN_BLOCK_SIZE 32
+
+/* XXX this is lame. Should clone the code to do this bitwise */
+#define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
+
+struct XPTArena
+{
+ BLK_HDR *first;
+ PRUint8 *next;
+ size_t space;
+ size_t alignment;
+ size_t block_size;
+ char *name;
+
+#ifdef XPT_ARENA_LOGGING
+ PRUint32 LOG_MallocCallCount;
+ PRUint32 LOG_MallocTotalBytesRequested;
+ PRUint32 LOG_MallocTotalBytesUsed;
+ PRUint32 LOG_FreeCallCount;
+ PRUint32 LOG_LoadingFreeCallCount;
+ PRUint32 LOG_RealMallocCallCount;
+ PRUint32 LOG_RealMallocTotalBytesRequested;
+#endif /* XPT_ARENA_LOGGING */
+};
+
+XPT_PUBLIC_API(XPTArena *)
+XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name)
+{
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ XPTArena *arena = RTMemAllocZ(sizeof(XPTArena));
+#else
+ XPTArena *arena = calloc(1, sizeof(XPTArena));
+#endif
+ if (arena) {
+ XPT_ASSERT(alignment);
+ if (alignment > sizeof(double))
+ alignment = sizeof(double);
+ arena->alignment = alignment;
+
+ if (block_size < XPT_MIN_BLOCK_SIZE)
+ block_size = XPT_MIN_BLOCK_SIZE;
+ arena->block_size = ALIGN_RND(block_size, alignment);
+
+ /* must have room for at least one item! */
+ XPT_ASSERT(arena->block_size >=
+ ALIGN_RND(sizeof(BLK_HDR), alignment) +
+ ALIGN_RND(1, alignment));
+
+ if (name) {
+ arena->name = XPT_STRDUP(arena, name);
+#ifdef XPT_ARENA_LOGGING
+ /* fudge the stats since we are using space in the arena */
+ arena->LOG_MallocCallCount = 0;
+ arena->LOG_MallocTotalBytesRequested = 0;
+ arena->LOG_MallocTotalBytesUsed = 0;
+#endif /* XPT_ARENA_LOGGING */
+ }
+ }
+ return arena;
+}
+
+XPT_PUBLIC_API(void)
+XPT_DestroyArena(XPTArena *arena)
+{
+ BLK_HDR* cur;
+ BLK_HDR* next;
+
+ cur = arena->first;
+ while (cur) {
+ next = cur->next;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(cur);
+#else
+ free(cur);
+#endif
+ cur = next;
+ }
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(arena);
+#else
+ free(arena);
+#endif
+}
+
+XPT_PUBLIC_API(void)
+XPT_DumpStats(XPTArena *arena)
+{
+ PRINT_STATS(arena);
+}
+
+
+/*
+* Our alignment rule is that we always round up the size of each allocation
+* so that the 'arena->next' pointer one will point to properly aligned space.
+*/
+
+XPT_PUBLIC_API(void *)
+XPT_ArenaMalloc(XPTArena *arena, size_t size)
+{
+ PRUint8 *cur;
+ size_t bytes;
+
+ if (!size)
+ return NULL;
+
+ if (!arena) {
+ XPT_ASSERT(0);
+ return NULL;
+ }
+
+ bytes = ALIGN_RND(size, arena->alignment);
+
+ LOG_MALLOC(arena, size, bytes);
+
+ if (bytes > arena->space) {
+ BLK_HDR* new_block;
+ size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment);
+ size_t new_space = arena->block_size;
+
+ if (bytes > new_space - block_header_size)
+ new_space += bytes;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ new_block = (BLK_HDR*) RTMemAllocZ(new_space/arena->alignment * (size_t)arena->alignment);
+#else
+ new_block = (BLK_HDR*) calloc(new_space/arena->alignment,
+ arena->alignment);
+#endif
+ if (!new_block) {
+ arena->next = NULL;
+ arena->space = 0;
+ return NULL;
+ }
+
+ LOG_REAL_MALLOC(arena, new_space);
+
+ /* link block into the list of blocks for use when we destroy */
+ new_block->next = arena->first;
+ arena->first = new_block;
+
+ /* save other block header info */
+ new_block->size = new_space;
+
+ /* set info for current block */
+ arena->next = ((PRUint8*)new_block) + block_header_size;
+ arena->space = new_space - block_header_size;
+
+#ifdef DEBUG
+ /* mark block for corruption check */
+ memset(arena->next, 0xcd, arena->space);
+#endif
+ }
+
+#ifdef DEBUG
+ {
+ /* do corruption check */
+ size_t i;
+ for (i = 0; i < bytes; ++i) {
+ XPT_ASSERT(arena->next[i] == 0xcd);
+ }
+ /* we guarantee that the block will be filled with zeros */
+ memset(arena->next, 0, bytes);
+ }
+#endif
+
+ cur = arena->next;
+ arena->next += bytes;
+ arena->space -= bytes;
+
+ return cur;
+}
+
+
+XPT_PUBLIC_API(char *)
+XPT_ArenaStrDup(XPTArena *arena, const char * s)
+{
+ size_t len;
+ char* cur;
+
+ if (!s)
+ return NULL;
+
+ len = strlen(s)+1;
+ cur = XPT_ArenaMalloc(arena, len);
+ memcpy(cur, s, len);
+ return cur;
+}
+
+XPT_PUBLIC_API(void)
+XPT_NotifyDoneLoading(XPTArena *arena)
+{
+#ifdef XPT_ARENA_LOGGING
+ if (arena) {
+ LOG_DONE_LOADING(arena);
+ }
+#endif
+}
+
+XPT_PUBLIC_API(void)
+XPT_ArenaFree(XPTArena *arena, void *block)
+{
+ LOG_FREE(arena);
+}
+
+#ifdef XPT_ARENA_LOGGING
+static void xpt_DebugPrintArenaStats(XPTArena *arena)
+{
+ printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
+ printf("Start xpt arena stats for \"%s\"\n",
+ arena->name ? arena->name : "unnamed arena");
+ printf("\n");
+ printf("%d times arena malloc called\n", (int) arena->LOG_MallocCallCount);
+ printf("%d total bytes requested from arena malloc\n", (int) arena->LOG_MallocTotalBytesRequested);
+ printf("%d average bytes requested per call to arena malloc\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
+ printf("%d average bytes used per call (accounts for alignment overhead)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0);
+ printf("%d average bytes used per call (accounts for all overhead and waste)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_RealMallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
+ printf("\n");
+ printf("%d during loading times arena free called\n", (int) arena->LOG_LoadingFreeCallCount);
+ printf("%d during loading approx total bytes not freed\n", (int) arena->LOG_LoadingFreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0));
+ printf("\n");
+ printf("%d total times arena free called\n", (int) arena->LOG_FreeCallCount);
+ printf("%d approx total bytes not freed until arena destruction\n", (int) arena->LOG_FreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0 ));
+ printf("\n");
+ printf("%d times arena called system malloc\n", (int) arena->LOG_RealMallocCallCount);
+ printf("%d total bytes arena requested from system\n", (int) arena->LOG_RealMallocTotalBytesRequested);
+ printf("%d byte block size specified at arena creation time\n", (int) arena->block_size);
+ printf("%d byte block alignment specified at arena creation time\n", (int) arena->alignment);
+ printf("\n");
+ printf("End xpt arena stats\n");
+ printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
+}
+#endif
+
+/***************************************************************************/
+
+#ifdef DEBUG
+XPT_PUBLIC_API(void)
+XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno)
+{
+ fprintf(stderr, "Assertion failed: %s, file %s, line %d\n",
+ s, file, lineno);
+ abort();
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c
new file mode 100644
index 00000000..93435910
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c
@@ -0,0 +1,956 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of XDR routines for typelib structures. */
+
+#include "xpt_xdr.h"
+#include "xpt_struct.h"
+#include <string.h>
+#include <stdio.h>
+
+/***************************************************************************/
+/* Forward declarations. */
+
+static PRUint32
+SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
+
+static PRUint32
+SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
+
+static PRUint32
+SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
+
+static PRUint32
+SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id);
+
+static PRBool
+DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index);
+
+static PRBool
+DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id);
+
+static PRBool
+DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id);
+
+static PRBool
+DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp);
+
+static PRBool
+DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp);
+
+static PRBool
+DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp);
+
+static PRBool
+DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id);
+
+static PRBool
+DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id);
+
+/***************************************************************************/
+
+XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeader(XPTHeader *header)
+{
+ XPTAnnotation *ann, *last;
+ PRUint32 size = 16 /* magic */ +
+ 1 /* major */ + 1 /* minor */ +
+ 2 /* num_interfaces */ + 4 /* file_length */ +
+ 4 /* interface_directory */ + 4 /* data_pool */;
+
+ ann = header->annotations;
+ do {
+ size += 1; /* Annotation prefix */
+ if (XPT_ANN_IS_PRIVATE(ann->flags))
+ size += 2 + ann->creator->length + 2 + ann->private_data->length;
+ last = ann;
+ ann = ann->next;
+ } while (!XPT_ANN_IS_LAST(last->flags));
+
+ return size;
+}
+
+XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeaderBlock(XPTHeader *header)
+{
+ PRUint32 size = XPT_SizeOfHeader(header);
+
+ size += header->num_interfaces * sizeof (XPTInterfaceDirectoryEntry);
+
+ return size;
+}
+
+XPT_PUBLIC_API(XPTHeader *)
+XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces, PRUint8 major_version, PRUint8 minor_version)
+{
+ XPTHeader *header = XPT_NEWZAP(arena, XPTHeader);
+ if (!header)
+ return NULL;
+ memcpy(header->magic, XPT_MAGIC, 16);
+ header->major_version = major_version;
+ header->minor_version = minor_version;
+ header->num_interfaces = num_interfaces;
+ if (num_interfaces) {
+ header->interface_directory =
+ XPT_CALLOC(arena,
+ num_interfaces * sizeof(XPTInterfaceDirectoryEntry));
+ if (!header->interface_directory) {
+ XPT_DELETE(arena, header);
+ return NULL;
+ }
+ }
+ header->data_pool = 0; /* XXX do we even need this struct any more? */
+
+ return header;
+}
+
+XPT_PUBLIC_API(void)
+XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader)
+{
+ if (aHeader) {
+ XPTAnnotation* ann;
+ XPTInterfaceDirectoryEntry* entry = aHeader->interface_directory;
+ XPTInterfaceDirectoryEntry* end = entry + aHeader->num_interfaces;
+ for (; entry < end; entry++) {
+ XPT_DestroyInterfaceDirectoryEntry(arena, entry);
+ }
+
+ ann = aHeader->annotations;
+ while (ann) {
+ XPTAnnotation* next = ann->next;
+ if (XPT_ANN_IS_PRIVATE(ann->flags)) {
+ XPT_FREEIF(arena, ann->creator);
+ XPT_FREEIF(arena, ann->private_data);
+ }
+ XPT_DELETE(arena, ann);
+ ann = next;
+ }
+
+ XPT_FREEIF(arena, aHeader->interface_directory);
+ XPT_DELETE(arena, aHeader);
+ }
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset)
+{
+ XPTMode mode = cursor->state->mode;
+ unsigned int i;
+ XPTHeader * header;
+
+ if (mode == XPT_DECODE) {
+ header = XPT_NEWZAP(arena, XPTHeader);
+ if (!header)
+ return PR_FALSE;
+ *headerp = header;
+ } else {
+ header = *headerp;
+ }
+
+ if (mode == XPT_ENCODE) {
+ /* IDEs appear after header, including annotations */
+ if (ide_offset != NULL)
+ {
+ *ide_offset = XPT_SizeOfHeader(*headerp) + 1; /* one-based offset */
+ }
+ header->data_pool = XPT_SizeOfHeaderBlock(*headerp);
+ XPT_SetDataOffset(cursor->state, header->data_pool);
+ }
+
+ for (i = 0; i < sizeof(header->magic); i++) {
+ if (!XPT_Do8(cursor, &header->magic[i]))
+ goto error;
+ }
+
+ if (mode == XPT_DECODE &&
+ strncmp((const char*)header->magic, XPT_MAGIC, 16) != 0)
+ {
+ /* Require that the header contain the proper magic */
+ fprintf(stderr,
+ "libxpt: bad magic header in input file; "
+ "found '%s', expected '%s'\n",
+ header->magic, XPT_MAGIC_STRING);
+ goto error;
+ }
+
+ if (!XPT_Do8(cursor, &header->major_version) ||
+ !XPT_Do8(cursor, &header->minor_version)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE &&
+ header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
+ /* This file is newer than we are and set to an incompatible version
+ * number. We must set the header state thusly and return.
+ */
+ header->num_interfaces = 0;
+ header->file_length = 0;
+ return PR_TRUE;
+ }
+
+ if (!XPT_Do16(cursor, &header->num_interfaces) ||
+ !XPT_Do32(cursor, &header->file_length) ||
+ (ide_offset != NULL && !XPT_Do32(cursor, ide_offset))) {
+ goto error;
+ }
+ return PR_TRUE;
+ /* XXX need to free child data sometimes! */
+ XPT_ERROR_HANDLE(arena, header);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
+{
+ const int HEADER_SIZE = 24;
+ XPTMode mode = cursor->state->mode;
+ XPTHeader * header;
+ PRUint32 ide_offset;
+ int i;
+ XPTAnnotation *ann, *next, **annp;
+
+ if (!XPT_DoHeaderPrologue(arena, cursor, headerp, &ide_offset))
+ return PR_FALSE;
+ header = *headerp;
+ /*
+ * Make sure the file length reported in the header is the same size as
+ * as our buffer unless it is zero (not set)
+ */
+ if (mode == XPT_DECODE && (header->file_length != 0 &&
+ cursor->state->pool->allocated < header->file_length)) {
+ fputs("libxpt: File length in header does not match actual length. File may be corrupt\n",
+ stderr);
+ goto error;
+ }
+
+ if (mode == XPT_ENCODE)
+ XPT_DataOffset(cursor->state, &header->data_pool);
+ if (!XPT_Do32(cursor, &header->data_pool))
+ goto error;
+ if (mode == XPT_DECODE)
+ XPT_DataOffset(cursor->state, &header->data_pool);
+
+ if (mode == XPT_DECODE && header->num_interfaces) {
+ header->interface_directory =
+ XPT_CALLOC(arena, header->num_interfaces *
+ sizeof(XPTInterfaceDirectoryEntry));
+ if (!header->interface_directory)
+ goto error;
+ }
+
+ /*
+ * Iterate through the annotations rather than recurring, to avoid blowing
+ * the stack on large xpt files.
+ */
+ ann = next = header->annotations;
+ annp = &header->annotations;
+ do {
+ ann = next;
+ if (!DoAnnotation(arena, cursor, &ann))
+ goto error;
+ if (mode == XPT_DECODE) {
+ /*
+ * Make sure that we store the address of the newly allocated
+ * annotation in the previous annotation's ``next'' slot, or
+ * header->annotations for the first one.
+ */
+ *annp = ann;
+ annp = &ann->next;
+ }
+ next = ann->next;
+ } while (!XPT_ANN_IS_LAST(ann->flags));
+
+ /* shouldn't be necessary now, but maybe later */
+ XPT_SeekTo(cursor, ide_offset);
+
+ for (i = 0; i < header->num_interfaces; i++) {
+ if (!DoInterfaceDirectoryEntry(arena, cursor,
+ &header->interface_directory[i],
+ (PRUint16)(i + 1)))
+ goto error;
+ }
+
+ return PR_TRUE;
+
+ /* XXX need to free child data sometimes! */
+ XPT_ERROR_HANDLE(arena, header);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry *ide,
+ nsID *iid, char *name, char *name_space,
+ XPTInterfaceDescriptor *descriptor)
+{
+ XPT_COPY_IID(ide->iid, *iid);
+ ide->name = name ? XPT_STRDUP(arena, name) : NULL; /* what good is it w/o a name? */
+ ide->name_space = name_space ? XPT_STRDUP(arena, name_space) : NULL;
+ ide->interface_descriptor = descriptor;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(void)
+XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry* ide)
+{
+ if (ide) {
+ if (ide->name) XPT_FREE(arena, ide->name);
+ if (ide->name_space) XPT_FREE(arena, ide->name_space);
+ XPT_FreeInterfaceDescriptor(arena, ide->interface_descriptor);
+ }
+}
+
+/* InterfaceDirectoryEntry records go in the header */
+PRBool
+DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index)
+{
+ XPTMode mode = cursor->state->mode;
+
+ /* write the IID in our cursor space */
+ if (!XPT_DoIID(cursor, &(ide->iid)) ||
+
+ /* write the name string in the data pool, and the offset in our
+ cursor space */
+ !XPT_DoCString(arena, cursor, &(ide->name)) ||
+
+ /* write the name_space string in the data pool, and the offset in our
+ cursor space */
+ !XPT_DoCString(arena, cursor, &(ide->name_space)) ||
+
+ /* do InterfaceDescriptors -- later, only on encode (see below) */
+ !DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE)
+ XPT_SetOffsetForAddr(cursor, ide, entry_index);
+
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, ide);
+}
+
+XPT_PUBLIC_API(XPTInterfaceDescriptor *)
+XPT_NewInterfaceDescriptor(XPTArena *arena,
+ PRUint16 parent_interface, PRUint16 num_methods,
+ PRUint16 num_constants, PRUint8 flags)
+{
+
+ XPTInterfaceDescriptor *id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
+ if (!id)
+ return NULL;
+
+ if (num_methods) {
+ id->method_descriptors = XPT_CALLOC(arena, num_methods *
+ sizeof(XPTMethodDescriptor));
+ if (!id->method_descriptors)
+ goto free_id;
+ id->num_methods = num_methods;
+ }
+
+ if (num_constants) {
+ id->const_descriptors = XPT_CALLOC(arena, num_constants *
+ sizeof(XPTConstDescriptor));
+ if (!id->const_descriptors)
+ goto free_meth;
+ id->num_constants = num_constants;
+ }
+
+ if (parent_interface) {
+ id->parent_interface = parent_interface;
+ } else {
+ id->parent_interface = 0;
+ }
+
+ id->flags = flags;
+
+ return id;
+
+ free_meth:
+ XPT_FREEIF(arena, id->method_descriptors);
+ free_id:
+ XPT_DELETE(arena, id);
+ return NULL;
+}
+
+XPT_PUBLIC_API(void)
+XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id)
+{
+ if (id) {
+ XPTMethodDescriptor *md, *mdend;
+ XPTConstDescriptor *cd, *cdend;
+
+ /* Free up method descriptors */
+ md = id->method_descriptors;
+ mdend = md + id->num_methods;
+ for (; md < mdend; md++) {
+ XPT_FREEIF(arena, md->name);
+ XPT_FREEIF(arena, md->params);
+ XPT_FREEIF(arena, md->result);
+ }
+ XPT_FREEIF(arena, id->method_descriptors);
+
+ /* Free up const descriptors */
+ cd = id->const_descriptors;
+ cdend = cd + id->num_constants;
+ for (; cd < cdend; cd++) {
+ XPT_FREEIF(arena, cd->name);
+ }
+ XPT_FREEIF(arena, id->const_descriptors);
+
+ /* Free up type descriptors */
+ XPT_FREEIF(arena, id->additional_types);
+
+ XPT_DELETE(arena, id);
+ }
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num)
+{
+ XPTTypeDescriptor *old = id->additional_types;
+ XPTTypeDescriptor *new;
+ size_t old_size = id->num_additional_types * sizeof(XPTTypeDescriptor);
+ size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size;
+
+ /* XXX should grow in chunks to minimize alloc overhead */
+ new = XPT_CALLOC(arena, new_size);
+ if (!new)
+ return PR_FALSE;
+ if (old) {
+ if (old_size)
+ memcpy(new, old, old_size);
+ XPT_FREE(arena, old);
+ }
+ id->additional_types = new;
+ id->num_additional_types += num;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num)
+{
+ XPTMethodDescriptor *old = id->method_descriptors;
+ XPTMethodDescriptor *new;
+ size_t old_size = id->num_methods * sizeof(XPTMethodDescriptor);
+ size_t new_size = (num * sizeof(XPTMethodDescriptor)) + old_size;
+
+ /* XXX should grow in chunks to minimize alloc overhead */
+ new = XPT_CALLOC(arena, new_size);
+ if (!new)
+ return PR_FALSE;
+ if (old) {
+ if (old_size)
+ memcpy(new, old, old_size);
+ XPT_FREE(arena, old);
+ }
+ id->method_descriptors = new;
+ id->num_methods += num;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num)
+{
+ XPTConstDescriptor *old = id->const_descriptors;
+ XPTConstDescriptor *new;
+ size_t old_size = id->num_constants * sizeof(XPTConstDescriptor);
+ size_t new_size = (num * sizeof(XPTConstDescriptor)) + old_size;
+
+ /* XXX should grow in chunks to minimize alloc overhead */
+ new = XPT_CALLOC(arena, new_size);
+ if (!new)
+ return PR_FALSE;
+ if (old) {
+ if (old_size)
+ memcpy(new, old, old_size);
+ XPT_FREE(arena, old);
+ }
+ id->const_descriptors = new;
+ id->num_constants += num;
+ return PR_TRUE;
+}
+
+PRUint32
+SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
+{
+ PRUint32 size = 1; /* prefix */
+
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_INTERFACE_TYPE:
+ size += 2; /* interface_index */
+ break;
+ case TD_INTERFACE_IS_TYPE:
+ size += 1; /* argnum */
+ break;
+ case TD_ARRAY:
+ size += 2 + SizeOfTypeDescriptor(
+ &id->additional_types[td->type.additional_type], id);
+ break;
+ case TD_PSTRING_SIZE_IS:
+ size += 2; /* argnum + argnum2 */
+ break;
+ case TD_PWSTRING_SIZE_IS:
+ size += 2; /* argnum + argnum2 */
+ break;
+ default:
+ /* nothing special */
+ break;
+ }
+ return size;
+}
+
+PRUint32
+SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
+{
+ PRUint32 i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */;
+
+ for (i = 0; i < md->num_args; i++)
+ size += 1 + SizeOfTypeDescriptor(&md->params[i].type, id);
+
+ size += 1 + SizeOfTypeDescriptor(&md->result->type, id);
+ return size;
+}
+
+PRUint32
+SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
+{
+ PRUint32 size = 4 /* name */ + SizeOfTypeDescriptor(&cd->type, id);
+
+ switch (XPT_TDP_TAG(cd->type.prefix)) {
+ case TD_INT8:
+ case TD_UINT8:
+ case TD_CHAR:
+ size ++;
+ break;
+ case TD_INT16:
+ case TD_UINT16:
+ case TD_WCHAR:
+ size += 2;
+ break;
+ case TD_INT32:
+ case TD_UINT32:
+ case TD_PSTRING:
+ size += 4;
+ break;
+ case TD_INT64:
+ case TD_UINT64:
+ size += 8;
+ break;
+ default:
+ fprintf(stderr, "libxpt: illegal type in ConstDescriptor: 0x%02x\n",
+ XPT_TDP_TAG(cd->type.prefix));
+ return 0;
+ }
+
+ return size;
+}
+
+PRUint32
+SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
+{
+ PRUint32 size = 2 /* parent interface */ + 2 /* num_methods */
+ + 2 /* num_constants */ + 1 /* flags */, i;
+ for (i = 0; i < id->num_methods; i++)
+ size += SizeOfMethodDescriptor(&id->method_descriptors[i], id);
+ for (i = 0; i < id->num_constants; i++)
+ size += SizeOfConstDescriptor(&id->const_descriptors[i], id);
+ return size;
+}
+
+PRBool
+DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
+ XPTInterfaceDescriptor **idp)
+{
+ XPTMode mode = outer->state->mode;
+ XPTInterfaceDescriptor *id;
+ XPTCursor curs, *cursor = &curs;
+ PRUint32 i, id_sz = 0;
+
+ if (mode == XPT_DECODE) {
+ id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
+ if (!id)
+ return PR_FALSE;
+ *idp = id;
+ } else {
+ id = *idp;
+ if (!id) {
+ id_sz = 0;
+ return XPT_Do32(outer, &id_sz);
+ }
+ id_sz = SizeOfInterfaceDescriptor(id);
+ }
+
+ if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
+ goto error;
+
+ if (!XPT_Do32(outer, &cursor->offset))
+ goto error;
+ if (mode == XPT_DECODE && !cursor->offset) {
+ XPT_DELETE(arena, *idp);
+ return PR_TRUE;
+ }
+ if(!XPT_Do16(cursor, &id->parent_interface) ||
+ !XPT_Do16(cursor, &id->num_methods)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE && id->num_methods) {
+ id->method_descriptors = XPT_CALLOC(arena, id->num_methods *
+ sizeof(XPTMethodDescriptor));
+ if (!id->method_descriptors)
+ goto error;
+ }
+
+ for (i = 0; i < id->num_methods; i++) {
+ if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id))
+ goto error;
+ }
+
+ if (!XPT_Do16(cursor, &id->num_constants)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE && id->num_constants) {
+ id->const_descriptors = XPT_CALLOC(arena, id->num_constants *
+ sizeof(XPTConstDescriptor));
+ if (!id->const_descriptors)
+ goto error;
+ }
+
+ for (i = 0; i < id->num_constants; i++) {
+ if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) {
+ goto error;
+ }
+ }
+
+ if (!XPT_Do8(cursor, &id->flags)) {
+ goto error;
+ }
+
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, id);
+}
+
+PRBool
+DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id)
+{
+ PRBool ok = PR_FALSE;
+
+ if (!XPT_DoCString(arena, cursor, &cd->name) ||
+ !DoTypeDescriptor(arena, cursor, &cd->type, id)) {
+
+ return PR_FALSE;
+ }
+
+ switch(XPT_TDP_TAG(cd->type.prefix)) {
+ case TD_INT8:
+ ok = XPT_Do8(cursor, (PRUint8*) &cd->value.i8);
+ break;
+ case TD_INT16:
+ ok = XPT_Do16(cursor, (PRUint16*) &cd->value.i16);
+ break;
+ case TD_INT32:
+ ok = XPT_Do32(cursor, (PRUint32*) &cd->value.i32);
+ break;
+ case TD_INT64:
+ ok = XPT_Do64(cursor, &cd->value.i64);
+ break;
+ case TD_UINT8:
+ ok = XPT_Do8(cursor, &cd->value.ui8);
+ break;
+ case TD_UINT16:
+ ok = XPT_Do16(cursor, &cd->value.ui16);
+ break;
+ case TD_UINT32:
+ ok = XPT_Do32(cursor, &cd->value.ui32);
+ break;
+ case TD_UINT64:
+ ok = XPT_Do64(cursor, (PRInt64 *)&cd->value.ui64);
+ break;
+ case TD_CHAR:
+ ok = XPT_Do8(cursor, (PRUint8*) &cd->value.ch);
+ break;
+ case TD_WCHAR:
+ ok = XPT_Do16(cursor, &cd->value.wch);
+ break;
+ /* fall-through */
+ default:
+ fprintf(stderr, "illegal type!\n");
+ break;
+ }
+
+ return ok;
+
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth,
+ PRUint8 flags, char *name, PRUint8 num_args)
+{
+ meth->flags = flags & XPT_MD_FLAGMASK;
+ meth->name = XPT_STRDUP(arena, name);
+ if (!meth->name)
+ return PR_FALSE;
+ meth->num_args = num_args;
+ if (num_args) {
+ meth->params = XPT_CALLOC(arena, num_args * sizeof(XPTParamDescriptor));
+ if (!meth->params)
+ goto free_name;
+ } else {
+ meth->params = NULL;
+ }
+ meth->result = XPT_NEWZAP(arena, XPTParamDescriptor);
+ if (!meth->result)
+ goto free_params;
+ return PR_TRUE;
+
+ free_params:
+ XPT_DELETE(arena, meth->params);
+ free_name:
+ XPT_DELETE(arena, meth->name);
+ return PR_FALSE;
+}
+
+PRBool
+DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id)
+{
+ XPTMode mode = cursor->state->mode;
+ int i;
+
+ if (!XPT_Do8(cursor, &md->flags) ||
+ !XPT_DoCString(arena, cursor, &md->name) ||
+ !XPT_Do8(cursor, &md->num_args))
+ return PR_FALSE;
+
+ if (mode == XPT_DECODE && md->num_args) {
+ md->params = XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor));
+ if (!md->params)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < md->num_args; i++) {
+ if (!DoParamDescriptor(arena, cursor, &md->params[i], id))
+ goto error;
+ }
+
+ if (mode == XPT_DECODE) {
+ md->result = XPT_NEWZAP(arena, XPTParamDescriptor);
+ if (!md->result)
+ return PR_FALSE;
+ }
+
+ if (!md->result ||
+ !DoParamDescriptor(arena, cursor, md->result, id))
+ goto error;
+
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, md->params);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_FillParamDescriptor(XPTArena *arena, XPTParamDescriptor *pd, PRUint8 flags,
+ XPTTypeDescriptor *type)
+{
+ pd->flags = flags & XPT_PD_FLAGMASK;
+ XPT_COPY_TYPE(pd->type, *type);
+ return PR_TRUE;
+}
+
+PRBool
+DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id)
+{
+ if (!XPT_Do8(cursor, &pd->flags) ||
+ !DoTypeDescriptor(arena, cursor, &pd->type, id))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+PRBool
+DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
+{
+ return XPT_Do8(cursor, &tdp->flags);
+}
+
+PRBool
+DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id)
+{
+ if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) {
+ goto error;
+ }
+
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_INTERFACE_TYPE:
+ if (!XPT_Do16(cursor, &td->type.iface))
+ goto error;
+ break;
+ case TD_INTERFACE_IS_TYPE:
+ if (!XPT_Do8(cursor, &td->argnum))
+ goto error;
+ break;
+ case TD_ARRAY:
+ if (!XPT_Do8(cursor, &td->argnum) ||
+ !XPT_Do8(cursor, &td->argnum2))
+ goto error;
+
+ if (cursor->state->mode == XPT_DECODE) {
+ if(!XPT_InterfaceDescriptorAddTypes(arena, id, 1))
+ goto error;
+ td->type.additional_type = id->num_additional_types - 1;
+ }
+
+ if (!DoTypeDescriptor(arena, cursor,
+ &id->additional_types[td->type.additional_type],
+ id))
+ goto error;
+ break;
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ if (!XPT_Do8(cursor, &td->argnum) ||
+ !XPT_Do8(cursor, &td->argnum2))
+ goto error;
+ break;
+
+ default:
+ /* nothing special */
+ break;
+ }
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, td);
+}
+
+XPT_PUBLIC_API(XPTAnnotation *)
+XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator,
+ XPTString *private_data)
+{
+ XPTAnnotation *ann = XPT_NEWZAP(arena, XPTAnnotation);
+ if (!ann)
+ return NULL;
+ ann->flags = flags;
+ if (XPT_ANN_IS_PRIVATE(flags)) {
+ ann->creator = creator;
+ ann->private_data = private_data;
+ }
+ return ann;
+}
+
+PRBool
+DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
+{
+ XPTMode mode = cursor->state->mode;
+ XPTAnnotation *ann;
+
+ if (mode == XPT_DECODE) {
+ ann = XPT_NEWZAP(arena, XPTAnnotation);
+ if (!ann)
+ return PR_FALSE;
+ *annp = ann;
+ } else {
+ ann = *annp;
+ }
+
+ if (!XPT_Do8(cursor, &ann->flags))
+ goto error;
+
+ if (XPT_ANN_IS_PRIVATE(ann->flags)) {
+ if (!XPT_DoStringInline(arena, cursor, &ann->creator) ||
+ !XPT_DoStringInline(arena, cursor, &ann->private_data))
+ goto error_2;
+ }
+
+ return PR_TRUE;
+
+ error_2:
+ if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) {
+ XPT_FREEIF(arena, ann->creator);
+ XPT_FREEIF(arena, ann->private_data);
+ }
+ XPT_ERROR_HANDLE(arena, ann);
+}
+
+PRBool
+XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
+ PRUint16 num_interfaces, char *name,
+ PRUint16 *indexp)
+{
+ int i;
+
+ for (i=1; i<=num_interfaces; i++) {
+ fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name);
+ if (strcmp(ide_block[i].name, name) == 0) {
+ *indexp = i;
+ return PR_TRUE;
+ }
+ }
+ *indexp = 0;
+ return PR_FALSE;
+}
+
+static XPT_TYPELIB_VERSIONS_STRUCT versions[] = XPT_TYPELIB_VERSIONS;
+#define XPT_TYPELIB_VERSIONS_COUNT (sizeof(versions) / sizeof(versions[0]))
+
+XPT_PUBLIC_API(PRUint16)
+XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor)
+{
+ int i;
+ for (i = 0; i < XPT_TYPELIB_VERSIONS_COUNT; i++) {
+ if (!strcmp(versions[i].str, str)) {
+ *major = versions[i].major;
+ *minor = versions[i].minor;
+ return versions[i].code;
+ }
+ }
+ return XPT_VERSION_UNKNOWN;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c
new file mode 100644
index 00000000..cd9261d0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c
@@ -0,0 +1,665 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Implementation of XDR primitives. */
+
+#include "xpt_xdr.h"
+#include "nspr.h"
+#include <string.h> /* strchr */
+
+static PRBool
+CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
+ XPTCursor *new_cursor, PRBool *already);
+
+#define ENCODING(cursor) \
+ ((cursor)->state->mode == XPT_ENCODE)
+
+#define CURS_POOL_OFFSET_RAW(cursor) \
+ ((cursor)->pool == XPT_HEADER \
+ ? (cursor)->offset \
+ : (XPT_ASSERT((cursor)->state->data_offset), \
+ (cursor)->offset + (cursor)->state->data_offset))
+
+#define CURS_POOL_OFFSET(cursor) \
+ (CURS_POOL_OFFSET_RAW(cursor) - 1)
+
+/* can be used as lvalue */
+#define CURS_POINT(cursor) \
+ ((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
+
+#if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe)
+#define DBG(x) printf##x
+#else
+#define DBG(x) (0)
+#endif
+
+/* XXX fail if XPT_DATA and !state->data_offset */
+#define CHECK_COUNT_(cursor, space) \
+ /* if we're in the header, then exceeding the data_offset is illegal */ \
+((cursor)->pool == XPT_HEADER ? \
+ (ENCODING(cursor) && \
+ ((cursor)->state->data_offset && \
+ ((cursor)->offset - 1 + (space) > (cursor)->state->data_offset)) \
+ ? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \
+ (space), (cursor)->state->data_offset)) && PR_FALSE) \
+ : PR_TRUE) : \
+ /* if we're in the data area and we're about to exceed the allocation */ \
+ (CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ? \
+ /* then grow if we're in ENCODE mode */ \
+ (ENCODING(cursor) ? GrowPool((cursor)->state->arena, \
+ (cursor)->state->pool, \
+ (cursor)->state->pool->allocated, \
+ 0, CURS_POOL_OFFSET(cursor) + (space)) \
+ /* and fail if we're in DECODE mode */ \
+ : (DBG(("can't extend in DECODE")) && PR_FALSE)) \
+ /* otherwise we're OK */ \
+ : PR_TRUE))
+
+#define CHECK_COUNT(cursor, space) \
+ (CHECK_COUNT_(cursor, space) \
+ ? PR_TRUE \
+ : (XPT_ASSERT(0), \
+ fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
+ PR_FALSE))
+
+/* increase the data allocation for the pool by XPT_GROW_CHUNK */
+#define XPT_GROW_CHUNK 8192
+
+/*
+ * quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib.
+ * XXXmccabe it might turn out that we could use a simpler data structure here.
+ */
+typedef struct XPTHashRecord {
+ void *key;
+ void *value;
+ struct XPTHashRecord *next;
+} XPTHashRecord;
+
+#define XPT_HASHSIZE 512
+
+struct XPTHashTable { /* it's already typedef'ed from before. */
+ XPTHashRecord *buckets[XPT_HASHSIZE];
+ XPTArena *arena;
+};
+
+static XPTHashTable *
+XPT_NewHashTable(XPTArena *arena) {
+ XPTHashTable *table;
+ table = XPT_NEWZAP(arena, XPTHashTable);
+ if (table)
+ table->arena = arena;
+ return table;
+}
+
+static void trimrecord(XPTArena* arena, XPTHashRecord *record) {
+ if (record == NULL)
+ return;
+ trimrecord(arena, record->next);
+ XPT_DELETE(arena, record);
+}
+
+static void
+XPT_HashTableDestroy(XPTHashTable *table) {
+ int i;
+ for (i = 0; i < XPT_HASHSIZE; i++)
+ trimrecord(table->arena, table->buckets[i]);
+ XPT_FREE(table->arena, table);
+}
+
+static void *
+XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) {
+ XPTHashRecord **bucketloc = table->buckets +
+ (((PRUint32)(uintptr_t)key) % XPT_HASHSIZE);
+ XPTHashRecord *bucket;
+
+ while (*bucketloc != NULL)
+ bucketloc = &((*bucketloc)->next);
+
+ bucket = XPT_NEW(table->arena, XPTHashRecord);
+ bucket->key = key;
+ bucket->value = value;
+ bucket->next = NULL;
+ *bucketloc = bucket;
+ return value;
+}
+
+static void *
+XPT_HashTableLookup(XPTHashTable *table, void *key) {
+ XPTHashRecord *bucket = table->buckets[(PRUint32)(uintptr_t)key % XPT_HASHSIZE];
+ while (bucket != NULL) {
+ if (bucket->key == key)
+ return bucket->value;
+ bucket = bucket->next;
+ }
+ return NULL;
+}
+
+XPT_PUBLIC_API(XPTState *)
+XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len)
+{
+ XPTState *state;
+ XPTArena *arena;
+
+ arena = XPT_NewArena(512, sizeof(double), "an XDRState");
+ if (!arena)
+ return NULL;
+
+ state = XPT_NEWZAP(arena, XPTState);
+ if (!state)
+ goto err_free_arena;
+
+ state->arena = arena;
+ state->mode = mode;
+ state->pool = XPT_NEW(arena, XPTDatapool);
+ state->next_cursor[0] = state->next_cursor[1] = 1;
+ if (!state->pool)
+ goto err_free_state;
+
+ state->pool->count = 0;
+ state->pool->offset_map = XPT_NewHashTable(arena);
+
+ if (!state->pool->offset_map)
+ goto err_free_pool;
+ if (mode == XPT_DECODE) {
+ state->pool->data = data;
+ state->pool->allocated = len;
+ } else {
+ state->pool->data = XPT_MALLOC(arena, XPT_GROW_CHUNK);
+ if (!state->pool->data)
+ goto err_free_hash;
+ state->pool->allocated = XPT_GROW_CHUNK;
+ }
+
+ return state;
+
+ err_free_hash:
+ XPT_HashTableDestroy(state->pool->offset_map);
+ err_free_pool:
+ XPT_DELETE(arena, state->pool);
+ err_free_state:
+ XPT_DELETE(arena, state);
+ err_free_arena:
+ if (arena)
+ XPT_DestroyArena(arena);
+ return NULL;
+}
+
+XPT_PUBLIC_API(void)
+XPT_DestroyXDRState(XPTState *state)
+{
+ XPTArena *arena = state->arena;
+
+ if (state->pool->offset_map)
+ XPT_HashTableDestroy(state->pool->offset_map);
+ if (state->mode == XPT_ENCODE)
+ XPT_DELETE(arena, state->pool->data);
+ XPT_DELETE(arena, state->pool);
+ XPT_DELETE(arena, state);
+ if (arena)
+ XPT_DestroyArena(arena);
+}
+
+XPT_PUBLIC_API(void)
+XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len)
+{
+ *len = state->next_cursor[pool] - 1;
+}
+
+XPT_PUBLIC_API(void)
+XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len)
+{
+ if (pool == XPT_HEADER) {
+ *data = state->pool->data;
+ } else {
+ *data = state->pool->data + state->data_offset;
+ }
+ *len = state->next_cursor[pool] - 1;
+}
+
+/* All offsets are 1-based */
+XPT_PUBLIC_API(void)
+XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp)
+{
+ if (state->mode == XPT_DECODE)
+ XPT_SetDataOffset(state, *data_offsetp);
+ else
+ *data_offsetp = state->data_offset;
+}
+
+/* if 'exact' is set use that, else grow by the next chunk but
+ * be sure to grow no less that 'at_least' so that we can't get
+ * behind on required space.
+ */
+static PRBool
+GrowPool(XPTArena *arena, XPTDatapool *pool, PRUint32 old_size,
+ PRUint32 exact, PRUint32 at_least)
+{
+ PRUint32 total_size;
+ char *newdata;
+
+ if (exact) {
+ XPT_ASSERT(exact > pool->allocated);
+ total_size = exact;
+ } else {
+ total_size = pool->allocated + XPT_GROW_CHUNK;
+ if (at_least > total_size)
+ total_size = at_least;
+ }
+
+ newdata = XPT_MALLOC(arena, total_size);
+ if (!newdata)
+ return PR_FALSE;
+ if (pool->data) {
+ if (old_size)
+ memcpy(newdata, pool->data, old_size);
+ XPT_FREE(arena, pool->data);
+ }
+ pool->data = newdata;
+ pool->allocated = total_size;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(void)
+XPT_SetDataOffset(XPTState *state, PRUint32 data_offset)
+{
+ state->data_offset = data_offset;
+ /* make sure we've allocated enough space for the header */
+ if (state->mode == XPT_ENCODE &&
+ data_offset > state->pool->allocated) {
+ (void)GrowPool(state->arena, state->pool, state->pool->allocated,
+ data_offset, 0);
+ }
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor)
+{
+ cursor->state = state;
+ cursor->pool = pool;
+ cursor->bits = 0;
+ cursor->offset = state->next_cursor[pool];
+
+ if (!(CHECK_COUNT(cursor, len)))
+ return PR_FALSE;
+
+ /* this check should be in CHECK_CURSOR */
+ if (pool == XPT_DATA && !state->data_offset) {
+ fprintf(stderr, "no data offset for XPT_DATA cursor!\n");
+ return PR_FALSE;
+ }
+
+ state->next_cursor[pool] += len;
+
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_SeekTo(XPTCursor *cursor, PRUint32 offset)
+{
+ /* XXX do some real checking and update len and stuff */
+ cursor->offset = offset;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(XPTString *)
+XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes)
+{
+ XPTString *str = XPT_NEW(arena, XPTString);
+ if (!str)
+ return NULL;
+ str->length = length;
+ /* Alloc one extra to store the trailing nul. */
+ str->bytes = XPT_MALLOC(arena, length + 1u);
+ if (!str->bytes) {
+ XPT_DELETE(arena, str);
+ return NULL;
+ }
+ memcpy(str->bytes, bytes, length);
+ /* nul-terminate it. */
+ str->bytes[length] = '\0';
+ return str;
+}
+
+XPT_PUBLIC_API(XPTString *)
+XPT_NewStringZ(XPTArena *arena, char *bytes)
+{
+ PRUint32 length = strlen(bytes);
+ if (length > 0xffff)
+ return NULL; /* too long */
+ return XPT_NewString(arena, (PRUint16)length, bytes);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
+{
+ XPTString *str = *strp;
+ XPTMode mode = cursor->state->mode;
+ int i;
+
+ if (mode == XPT_DECODE) {
+ str = XPT_NEWZAP(arena, XPTString);
+ if (!str)
+ return PR_FALSE;
+ *strp = str;
+ }
+
+ if (!XPT_Do16(cursor, &str->length))
+ goto error;
+
+ if (mode == XPT_DECODE)
+ if (!(str->bytes = XPT_MALLOC(arena, str->length + 1u)))
+ goto error;
+
+ for (i = 0; i < str->length; i++)
+ if (!XPT_Do8(cursor, (PRUint8 *)&str->bytes[i]))
+ goto error_2;
+
+ if (mode == XPT_DECODE)
+ str->bytes[str->length] = 0;
+
+ return PR_TRUE;
+ error_2:
+ XPT_DELETE(arena, str->bytes);
+ error:
+ XPT_DELETE(arena, str);
+ return PR_FALSE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
+{
+ XPTCursor my_cursor;
+ XPTString *str = *strp;
+ PRBool already;
+
+ XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
+ already)
+
+ return XPT_DoStringInline(arena, &my_cursor, strp);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp)
+{
+ XPTCursor my_cursor;
+ char *ident = *identp;
+ PRUint32 offset = 0;
+
+ XPTMode mode = cursor->state->mode;
+
+ if (mode == XPT_DECODE) {
+ char *start, *end;
+ int len;
+
+ if (!XPT_Do32(cursor, &offset))
+ return PR_FALSE;
+
+ if (!offset) {
+ *identp = NULL;
+ return PR_TRUE;
+ }
+
+ my_cursor.pool = XPT_DATA;
+ my_cursor.offset = offset;
+ my_cursor.state = cursor->state;
+ start = &CURS_POINT(&my_cursor);
+
+ end = strchr(start, 0); /* find the end of the string */
+ if (!end) {
+ fprintf(stderr, "didn't find end of string on decode!\n");
+ return PR_FALSE;
+ }
+ len = end - start;
+ XPT_ASSERT(len > 0);
+
+ ident = XPT_MALLOC(arena, len + 1u);
+ if (!ident)
+ return PR_FALSE;
+
+ memcpy(ident, start, (size_t)len);
+ ident[len] = 0;
+ *identp = ident;
+
+ } else {
+
+ if (!ident) {
+ offset = 0;
+ if (!XPT_Do32(cursor, &offset))
+ return PR_FALSE;
+ return PR_TRUE;
+ }
+
+ if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1,
+ &my_cursor) ||
+ !XPT_Do32(cursor, &my_cursor.offset))
+ return PR_FALSE;
+
+ while(*ident)
+ if (!XPT_Do8(&my_cursor, (PRUint8 *)ident++))
+ return PR_FALSE;
+ if (!XPT_Do8(&my_cursor, (PRUint8 *)ident)) /* write trailing zero */
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+/* XXXjband it bothers me that this is one hashtable instead of two.
+ */
+XPT_PUBLIC_API(PRUint32)
+XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
+{
+ return (PRUint32)(uintptr_t)XPT_HashTableLookup(cursor->state->pool->offset_map, addr);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset)
+{
+ return XPT_HashTableAdd(cursor->state->pool->offset_map,
+ addr, (void *)(uintptr_t)offset) != NULL;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr)
+{
+ return XPT_HashTableAdd(cursor->state->pool->offset_map,
+ (void *)(uintptr_t)offset, addr) != NULL;
+}
+
+XPT_PUBLIC_API(void *)
+XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset)
+{
+ return XPT_HashTableLookup(cursor->state->pool->offset_map, (void *)(uintptr_t)offset);
+}
+
+/* Used by XPT_PREAMBLE_NO_ALLOC. */
+static PRBool
+CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
+ XPTCursor *new_cursor, PRBool *already)
+{
+ void *last = *addrp;
+
+ *already = PR_FALSE;
+ new_cursor->state = cursor->state;
+ new_cursor->pool = pool;
+ new_cursor->bits = 0;
+
+ if (cursor->state->mode == XPT_DECODE) {
+
+ last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset);
+
+ if (last) {
+ *already = PR_TRUE;
+ *addrp = last;
+ }
+
+ } else {
+
+ new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last);
+ if (new_cursor->offset) {
+ *already = PR_TRUE;
+ return PR_TRUE;
+ }
+
+ /* haven't already found it, so allocate room for it. */
+ if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) ||
+ !XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset))
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/*
+ * IIDs are written in struct order, in the usual big-endian way. From the
+ * typelib file spec:
+ *
+ * "For example, this IID:
+ * {00112233-4455-6677-8899-aabbccddeeff}
+ * is converted to the 128-bit value
+ * 0x00112233445566778899aabbccddeeff
+ * Note that the byte storage order corresponds to the layout of the nsIID
+ * C-struct on a big-endian architecture."
+ *
+ * (http://www.mozilla.org/scriptable/typelib_file.html#iid)
+ */
+XPT_PUBLIC_API(PRBool)
+XPT_DoIID(XPTCursor *cursor, nsID *iidp)
+{
+ int i;
+
+ if (!XPT_Do32(cursor, &iidp->m0) ||
+ !XPT_Do16(cursor, &iidp->m1) ||
+ !XPT_Do16(cursor, &iidp->m2))
+ return PR_FALSE;
+
+ for (i = 0; i < 8; i++)
+ if (!XPT_Do8(cursor, (PRUint8 *)&iidp->m3[i]))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_Do64(XPTCursor *cursor, PRInt64 *u64p)
+{
+ return XPT_Do32(cursor, (PRUint32 *)u64p) &&
+ XPT_Do32(cursor, ((PRUint32 *)u64p) + 1);
+}
+
+/*
+ * When we're writing 32- or 16-bit quantities, we write a byte at a time to
+ * avoid alignment issues. Someone could come and optimize this to detect
+ * well-aligned cases and do a single store, if they cared. I might care
+ * later.
+ */
+XPT_PUBLIC_API(PRBool)
+XPT_Do32(XPTCursor *cursor, PRUint32 *u32p)
+{
+ union {
+ PRUint8 b8[4];
+ PRUint32 b32;
+ } u;
+
+ if (!CHECK_COUNT(cursor, 4))
+ return PR_FALSE;
+
+ if (ENCODING(cursor)) {
+ u.b32 = XPT_SWAB32(*u32p);
+ CURS_POINT(cursor) = u.b8[0];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[1];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[2];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[3];
+ } else {
+ u.b8[0] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[1] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[2] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[3] = CURS_POINT(cursor);
+ *u32p = XPT_SWAB32(u.b32);
+ }
+ cursor->offset++;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_Do16(XPTCursor *cursor, PRUint16 *u16p)
+{
+ union {
+ PRUint8 b8[2];
+ PRUint16 b16;
+ } u;
+
+ if (!CHECK_COUNT(cursor, 2))
+ return PR_FALSE;
+
+ if (ENCODING(cursor)) {
+ u.b16 = XPT_SWAB16(*u16p);
+ CURS_POINT(cursor) = u.b8[0];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[1];
+ } else {
+ u.b8[0] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[1] = CURS_POINT(cursor);
+ *u16p = XPT_SWAB16(u.b16);
+ }
+ cursor->offset++;
+
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_Do8(XPTCursor *cursor, PRUint8 *u8p)
+{
+ if (!CHECK_COUNT(cursor, 1))
+ return PR_FALSE;
+ if (cursor->state->mode == XPT_ENCODE)
+ CURS_POINT(cursor) = *u8p;
+ else
+ *u8p = CURS_POINT(cursor);
+
+ cursor->offset++;
+
+ return PR_TRUE;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore
new file mode 100644
index 00000000..ebc62d94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+PrimitiveTest
+SimpleTypeLib
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in
new file mode 100644
index 00000000..afdc31b3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in
@@ -0,0 +1,59 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+CPP_PROG_LINK = 1
+
+SIMPLE_PROGRAMS = PrimitiveTest$(BIN_SUFFIX) SimpleTypeLib$(BIN_SUFFIX)
+
+CSRCS = PrimitiveTest.c SimpleTypeLib.c
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPT_API
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c
new file mode 100644
index 00000000..aad33ccc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Test the xdr primitives from xpt_xdr.c */
+
+#include "xpt_xdr.h"
+#include <stdio.h>
+#include <string.h> /* for memcpy */
+
+#define PASS(msg) \
+ fprintf(stderr, "PASSED : %s\n", msg);
+
+#define FAIL(msg) \
+ fprintf(stderr, "FAILURE: %s\n", msg);
+
+#define TRY_(msg, cond, silent) \
+ if ((cond) && !silent) { \
+ PASS(msg); \
+ } else { \
+ FAIL(msg); \
+ return 1; \
+ }
+
+#define TRY(msg, cond) TRY_(msg, cond, 0)
+#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
+
+XPTString in_str = { 4, "bazz" };
+
+struct TestData {
+ PRUint32 bit32;
+ PRUint16 bit16;
+ PRUint8 bit8[2];
+ char *cstr;
+ XPTString *str;
+} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, "foobar", &in_str},
+ output = {0, 0, {0, 0}, NULL, NULL };
+
+void
+dump_struct(char *label, struct TestData *str)
+{
+ fprintf(stderr, "%s: {%#08x, %#04x, {%#02x, %#02x}, %s, %d/%s}\n",
+ label, str->bit32, str->bit16, str->bit8[0], str->bit8[1],
+ str->cstr, str->str->length, str->str->bytes);
+}
+
+PRBool
+XDR(XPTArena *arena, XPTCursor *cursor, struct TestData *str)
+{
+ TRY("Do32", XPT_Do32(cursor, &str->bit32));
+ TRY("Do16", XPT_Do16(cursor, &str->bit16));
+ TRY("Do8", XPT_Do8 (cursor, &str->bit8[0]));
+ TRY("Do8", XPT_Do8 (cursor, &str->bit8[1]));
+ TRY("DoCString", XPT_DoCString(arena, cursor, &str->cstr));
+ TRY("DoString", XPT_DoString(arena, cursor, &str->str));
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ XPTArena *arena;
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ char *header, *data, *whole;
+ PRUint32 hlen, dlen, i;
+
+ TRY("XPT_NewArena", (arena = XPT_NewArena(1024, sizeof(double), "main")));
+
+ TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0)));
+
+ XPT_SetDataOffset(state, sizeof input);
+
+ TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor));
+
+ dump_struct("before", &input);
+
+ if (XDR(arena, cursor, &input))
+ return 1;
+
+ fprintf(stderr, "ENCODE successful\n");
+ XPT_GetXDRData(state, XPT_HEADER, &header, &hlen);
+ fprintf(stderr, "XDR header %d bytes at %p:",
+ hlen, header);
+ for (i = 0; i < hlen; i++)
+ fprintf(stderr, "%c%02x", i ? ',' : ' ', (uint8)header[i]);
+ fprintf(stderr, "\n");
+
+ XPT_GetXDRData(state, XPT_DATA, &data, &dlen);
+
+ fprintf(stderr, "XDR data %d bytes at %p:",
+ dlen, data);
+ for (i = 0; i < dlen; i++)
+ fprintf(stderr, "%c%02x/%c", i ? ',' : ' ', (uint8)data[i],
+ (uint8)data[i]);
+ fprintf(stderr, "\n");
+
+ whole = malloc(dlen + hlen);
+ if (!whole) {
+ fprintf(stderr, "malloc %d failed!\n", dlen + hlen);
+ return 1;
+ }
+
+ /* TRY_Q("malloc", (data2 = malloc(len))); */
+ memcpy(whole, header, hlen);
+ memcpy(whole + hlen, data, dlen);
+ XPT_DestroyXDRState(state);
+
+ TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, whole,
+ hlen + dlen)));
+
+ TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor));
+ XPT_SetDataOffset(state, sizeof input);
+
+ if (XDR(arena, cursor, &output))
+ return 1;
+
+ dump_struct("after", &output);
+ XPT_DestroyXDRState(state);
+ XPT_DestroyArena(arena);
+ free(whole);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c
new file mode 100644
index 00000000..305b8520
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Test the structure creation and serialization APIs from xpt_struct.c */
+#include <stdio.h>
+
+#include "xpt_xdr.h"
+#include "xpt_struct.h"
+
+#define PASS(msg) \
+ fprintf(stderr, "PASSED : %s\n", msg);
+
+#define FAIL(msg) \
+ fprintf(stderr, "FAILURE: %s\n", msg);
+
+#define TRY_(msg, cond, silent) \
+ if ((cond) && !silent) { \
+ PASS(msg); \
+ } else { \
+ FAIL(msg); \
+ return 1; \
+ }
+
+#define TRY(msg, cond) TRY_(msg, cond, 0)
+#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
+
+struct nsID iid = {
+ 0x00112233,
+ 0x4455,
+ 0x6677,
+ {0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
+};
+
+XPTTypeDescriptor td_void;
+
+int
+main(int argc, char **argv)
+{
+ XPTArena *arena;
+ XPTHeader *header;
+ XPTAnnotation *ann;
+ XPTInterfaceDescriptor *id;
+ XPTMethodDescriptor *meth;
+
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ char *data, *head;
+ FILE *out;
+ PRUint32 len, header_sz;
+
+ PRBool ok;
+
+ td_void.prefix.flags = TD_VOID;
+
+#ifdef XP_MAC
+ if (argc == 0) {
+ static char* args[] = { "SimpleTypeLib", "simple.xpt", NULL };
+ argc = 2;
+ argv = args;
+ }
+#endif
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <filename.xpt>\n"
+ " Creates a simple typelib file.\n", argv[0]);
+
+ return 1;
+ }
+
+ arena = XPT_NewArena(1024, sizeof(double), "main");
+ TRY("XPT_NewArena", arena);
+
+ /* construct a header */
+ header = XPT_NewHeader(arena, 1, XPT_MAJOR_VERSION, XPT_MINOR_VERSION);
+ TRY("NewHeader", header);
+
+
+ ann = XPT_NewAnnotation(arena, XPT_ANN_LAST | XPT_ANN_PRIVATE,
+ XPT_NewStringZ(arena, "SimpleTypeLib 1.0"),
+ XPT_NewStringZ(arena, "See You In Rome"));
+ TRY("NewAnnotation", ann);
+ header->annotations = ann;
+
+ header_sz = XPT_SizeOfHeaderBlock(header);
+
+ id = XPT_NewInterfaceDescriptor(arena, 0, 2, 2, 0);
+ TRY("NewInterfaceDescriptor", id);
+
+ ok = XPT_FillInterfaceDirectoryEntry(arena, header->interface_directory, &iid,
+ "Interface", "NS", id);
+ TRY("FillInterfaceDirectoryEntry", ok);
+
+ /* void method1(void) */
+ meth = &id->method_descriptors[0];
+ ok = XPT_FillMethodDescriptor(arena, meth, 0, "method1", 0);
+ TRY("FillMethodDescriptor", ok);
+ meth->result->flags = 0;
+ meth->result->type.prefix.flags = TD_VOID;
+
+ /* wstring method2(in uint32, in bool) */
+ meth = &id->method_descriptors[1];
+ ok = XPT_FillMethodDescriptor(arena, meth, 0, "method2", 2);
+ TRY("FillMethodDescriptor", ok);
+
+ meth->result->flags = 0;
+ meth->result->type.prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
+ meth->params[0].type.prefix.flags = TD_UINT32;
+ meth->params[0].flags = XPT_PD_IN;
+ meth->params[1].type.prefix.flags = TD_BOOL;
+ meth->params[1].flags = XPT_PD_IN;
+
+#if 0
+ /* const one = 1; */
+ id->const_descriptors[0].name = "one";
+ id->const_descriptors[0].type.prefix.flags = TD_UINT16;
+ id->const_descriptors[0].value.ui16 = 1;
+
+ /* const squeamish = "ossifrage"; */
+ id->const_descriptors[1].name = "squeamish";
+ id->const_descriptors[1].type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER;
+ id->const_descriptors[1].value.string = XPT_NewStringZ(arena, "ossifrage");
+#endif
+
+ /* serialize it */
+ state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
+ TRY("NewState (ENCODE)", state);
+
+ ok = XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor);
+ TRY("MakeCursor", ok);
+
+ ok = XPT_DoHeader(arena, cursor, &header);
+ TRY("DoHeader", ok);
+
+ out = fopen(argv[1], "wb");
+ if (!out) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ XPT_GetXDRData(state, XPT_HEADER, &head, &len);
+ fwrite(head, len, 1, out);
+
+ XPT_GetXDRData(state, XPT_DATA, &data, &len);
+ fwrite(data, len, 1, out);
+
+ if (ferror(out) != 0 || fclose(out) != 0) {
+ fprintf(stderr, "\nError writing file: %s\n\n", argv[1]);
+ } else {
+ fprintf(stderr, "\nFile written: %s\n\n", argv[1]);
+ }
+ XPT_DestroyXDRState(state);
+
+ XPT_FreeHeader(arena, header);
+ XPT_DestroyArena(arena);
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore
new file mode 100644
index 00000000..985cc7a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+xpt_dump
+xpt_link
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in
new file mode 100644
index 00000000..bedece8e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in
@@ -0,0 +1,90 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+INTERNAL_TOOLS = 1
+
+SIMPLE_PROGRAMS = xpt_dump$(BIN_SUFFIX) xpt_link$(BIN_SUFFIX)
+
+CSRCS = xpt_dump.c xpt_link.c
+
+SDK_BINARY = \
+ $(SIMPLE_PROGRAMS) \
+ $(NULL)
+
+ifdef CROSS_COMPILE
+HOST_SIMPLE_PROGRAMS = $(addprefix host_, $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=$(HOST_BIN_SUFFIX)))
+HOST_CSRCS = $(CSRCS)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+# Compile directly against the static lib, so we can use the tools
+# during the build without the shared library path being set.
+ifeq ($(OS_ARCH),WINNT)
+DEFINES += -DEXPORT_XPT_API
+endif
+
+LIBS = $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX)
+
+# Tell the $(SIMPLE_PROGRAMS) target that we need to be recompiled
+# when libxpt changes.
+EXTRA_DEPS = $(wildcard $(DIST)/lib/$(LIB_PREFIX)xpt.*)
+
+ifdef CROSS_COMPILE
+HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX)
+HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*)
+
+ifdef HOST_NSPR_MDCPUCFG
+HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
+endif
+endif
+
+
+# Build xpt_link and xpt_dump early. (libs creates .deps used by libs.)
+export::
+ @$(MAKE) libs
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c
new file mode 100644
index 00000000..8926b9c9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c
@@ -0,0 +1,941 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * A utility for dumping the contents of a typelib file (.xpt) to screen
+ */
+
+#include "xpt_xdr.h"
+#include <stdio.h>
+#ifdef XP_MAC
+#include <stat.h>
+#include <StandardFile.h>
+#include "FullPath.h"
+#else
+#ifdef XP_OS2_EMX
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "prprf.h"
+
+#define BASE_INDENT 3
+
+static char *type_array[32] =
+ {"int8", "int16", "int32", "int64",
+ "uint8", "uint16", "uint32", "uint64",
+ "float", "double", "boolean", "char",
+ "wchar_t", "void", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved"};
+
+static char *ptype_array[32] =
+ {"int8 *", "int16 *", "int32 *", "int64 *",
+ "uint8 *", "uint16 *", "uint32 *", "uint64 *",
+ "float *", "double *", "boolean *", "char *",
+ "wchar_t *", "void *", "nsIID *", "DOMString *",
+ "string", "wstring", "Interface *", "InterfaceIs *",
+ "array", "string_s", "wstring_s", "UTF8String *",
+ "CString *", "AString *", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved"};
+
+static char *rtype_array[32] =
+ {"int8 &", "int16 &", "int32 &", "int64 &",
+ "uint8 &", "uint16 &", "uint32 &", "uint64 &",
+ "float &", "double &", "boolean &", "char &",
+ "wchar_t &", "void &", "nsIID &", "DOMString &",
+ "string &", "wstring &", "Interface &", "InterfaceIs &",
+ "array &", "string_s &", "wstring_s &", "UTF8String &",
+ "CString &", "AString &", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved"};
+
+PRBool param_problems = PR_FALSE;
+
+PRBool
+XPT_DumpHeader(XPTCursor *cursor, XPTHeader *header,
+ const int indent, PRBool verbose_mode);
+
+PRBool
+XPT_DumpAnnotations(XPTAnnotation *ann, const int indent, PRBool verbose_mode);
+
+PRBool
+XPT_DumpInterfaceDirectoryEntry(XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode);
+
+PRBool
+XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode);
+
+PRBool
+XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode);
+PRBool
+XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ char **type_string);
+
+PRBool
+XPT_DumpXPTString(XPTString *str);
+
+PRBool
+XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode,
+ PRBool is_result);
+
+PRBool
+XPT_DumpTypeDescriptor(XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ int indent, PRBool verbose_mode);
+
+PRBool
+XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode);
+
+static void
+xpt_dump_usage(char *argv[]) {
+ fprintf(stdout, "Usage: %s [-v] <filename.xpt>\n"
+ " -v verbose mode\n", argv[0]);
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+
+#define main xptdump_main
+int xptdump_main(int argc, char *argv[]);
+
+#define get_file_length mac_get_file_length
+extern size_t mac_get_file_length(const char* filename);
+
+#else /* !(XP_MAC && XPIDL_PLUGIN) */
+
+static size_t get_file_length(const char* filename)
+{
+ struct stat file_stat;
+ if (stat(filename, &file_stat) != 0) {
+ perror("FAILED: get_file_length");
+ exit(1);
+ }
+ return file_stat.st_size;
+}
+
+#endif /* !(XP_MAC && XPIDL_PLUGIN) */
+
+int
+main(int argc, char **argv)
+{
+ PRBool verbose_mode = PR_FALSE;
+ XPTArena *arena;
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ XPTHeader *header;
+ size_t flen;
+ char *name;
+ char *whole;
+ FILE *in;
+ int result = 1;
+
+ switch (argc) {
+ case 2:
+ if (argv[1][0] == '-') {
+ xpt_dump_usage(argv);
+ return 1;
+ }
+ name = argv[1];
+ flen = get_file_length(name);
+ in = fopen(name, "rb");
+ break;
+ case 3:
+ verbose_mode = PR_TRUE;
+ if (argv[1][0] != '-' || argv[1][1] != 'v') {
+ xpt_dump_usage(argv);
+ return 1;
+ }
+ name = argv[2];
+ flen = get_file_length(name);
+ in = fopen(name, "rb");
+ break;
+ default:
+ xpt_dump_usage(argv);
+ return 1;
+ }
+
+ if (!in) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ arena = XPT_NewArena(1024, sizeof(double), "main xpt_dump arena");
+ if (!arena) {
+ perror("XPT_NewArena failed");
+ return 1;
+ }
+
+ /* after arena creation all exits via 'goto out' */
+
+ whole = XPT_MALLOC(arena, flen);
+ if (!whole) {
+ perror("FAILED: XPT_MALLOC for whole");
+ goto out;
+ }
+
+ if (flen > 0) {
+ size_t rv = fread(whole, 1, flen, in);
+ if (rv < flen) {
+ fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen);
+ goto out;
+ }
+ if (ferror(in) != 0 || fclose(in) != 0)
+ perror("FAILED: Unable to read typelib file.\n");
+
+ state = XPT_NewXDRState(XPT_DECODE, whole, flen);
+ if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
+ fprintf(stdout, "XPT_MakeCursor failed for %s\n", name);
+ goto out;
+ }
+ if (!XPT_DoHeader(arena, cursor, &header)) {
+ fprintf(stdout,
+ "DoHeader failed for %s. Is %s a valid .xpt file?\n",
+ name, name);
+ goto out;
+ }
+
+ if (!XPT_DumpHeader(cursor, header, BASE_INDENT, verbose_mode)) {
+ perror("FAILED: XPT_DumpHeader");
+ goto out;
+ }
+
+ if (param_problems) {
+ fprintf(stdout, "\nWARNING: ParamDescriptors are present with "
+ "bad in/out/retval flag information.\n"
+ "These have been marked with 'XXX'.\n"
+ "Remember, retval params should always be marked as out!\n");
+ }
+
+ XPT_DestroyXDRState(state);
+ XPT_FREE(arena, whole);
+
+ } else {
+ fclose(in);
+ perror("FAILED: file length <= 0");
+ goto out;
+ }
+
+ result = 0;
+
+out:
+ XPT_DestroyArena(arena);
+ return result;
+}
+
+PRBool
+XPT_DumpHeader(XPTCursor *cursor, XPTHeader *header,
+ const int indent, PRBool verbose_mode)
+{
+ int i;
+
+ fprintf(stdout, "Header:\n");
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sMagic beans: ", indent, " ");
+ for (i=0; i<16; i++) {
+ fprintf(stdout, "%02x", header->magic[i]);
+ }
+ fprintf(stdout, "\n");
+ if (strncmp((const char*)header->magic, XPT_MAGIC, 16) == 0)
+ fprintf(stdout, "%*s PASSED\n", indent, " ");
+ else
+ fprintf(stdout, "%*s FAILED\n", indent, " ");
+ }
+ fprintf(stdout, "%*sMajor version: %d\n", indent, " ",
+ header->major_version);
+ fprintf(stdout, "%*sMinor version: %d\n", indent, " ",
+ header->minor_version);
+ fprintf(stdout, "%*sNumber of interfaces: %d\n", indent, " ",
+ header->num_interfaces);
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sFile length: %d\n", indent, " ",
+ header->file_length);
+ fprintf(stdout, "%*sData pool offset: %d\n\n", indent, " ",
+ header->data_pool);
+ }
+
+ fprintf(stdout, "%*sAnnotations:\n", indent, " ");
+ if (!XPT_DumpAnnotations(header->annotations, indent*2, verbose_mode))
+ return PR_FALSE;
+
+ fprintf(stdout, "\nInterface Directory:\n");
+ for (i=0; i<header->num_interfaces; i++) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sInterface #%d:\n", indent, " ", i);
+ if (!XPT_DumpInterfaceDirectoryEntry(cursor,
+ &header->interface_directory[i],
+ header, indent*2,
+ verbose_mode)) {
+ return PR_FALSE;
+ }
+ } else {
+ if (!XPT_DumpInterfaceDirectoryEntry(cursor,
+ &header->interface_directory[i],
+ header, indent,
+ verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpAnnotations(XPTAnnotation *ann, const int indent, PRBool verbose_mode)
+{
+ int i = -1;
+ XPTAnnotation *last;
+ int new_indent = indent + BASE_INDENT;
+
+ do {
+ i++;
+ if (XPT_ANN_IS_PRIVATE(ann->flags)) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sAnnotation #%d is private.\n",
+ indent, " ", i);
+ } else {
+ fprintf(stdout, "%*sAnnotation #%d:\n",
+ indent, " ", i);
+ }
+ fprintf(stdout, "%*sCreator: ", new_indent, " ");
+ if (!XPT_DumpXPTString(ann->creator))
+ return PR_FALSE;
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%*sPrivate Data: ", new_indent, " ");
+ if (!XPT_DumpXPTString(ann->private_data))
+ return PR_FALSE;
+ fprintf(stdout, "\n");
+ } else {
+ fprintf(stdout, "%*sAnnotation #%d is empty.\n",
+ indent, " ", i);
+ }
+ last = ann;
+ ann = ann->next;
+ } while (!XPT_ANN_IS_LAST(last->flags));
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sAnnotation #%d is the last annotation.\n",
+ indent, " ", i);
+ }
+
+ return PR_TRUE;
+}
+
+static void
+print_IID(struct nsID *iid, FILE *file)
+{
+ fprintf(file, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (PRUint32) iid->m0, (PRUint32) iid->m1,(PRUint32) iid->m2,
+ (PRUint32) iid->m3[0], (PRUint32) iid->m3[1],
+ (PRUint32) iid->m3[2], (PRUint32) iid->m3[3],
+ (PRUint32) iid->m3[4], (PRUint32) iid->m3[5],
+ (PRUint32) iid->m3[6], (PRUint32) iid->m3[7]);
+
+}
+
+PRBool
+XPT_DumpInterfaceDirectoryEntry(XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode)
+{
+ int new_indent = indent + BASE_INDENT;
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sIID: ", indent, " ");
+ print_IID(&ide->iid, stdout);
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "%*sName: %s\n",
+ indent, " ", ide->name);
+ fprintf(stdout, "%*sNamespace: %s\n",
+ indent, " ", ide->name_space ? ide->name_space : "none");
+ fprintf(stdout, "%*sAddress of interface descriptor: %p\n",
+ indent, " ", ide->interface_descriptor);
+
+ fprintf(stdout, "%*sDescriptor:\n", indent, " ");
+
+ if (!XPT_DumpInterfaceDescriptor(cursor, ide->interface_descriptor,
+ header, new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ } else {
+ fprintf(stdout, "%*s- %s::%s (", indent, " ",
+ ide->name_space ? ide->name_space : "", ide->name);
+ print_IID(&ide->iid, stdout);
+ fprintf(stdout, "):\n");
+ if (!XPT_DumpInterfaceDescriptor(cursor, ide->interface_descriptor,
+ header, new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode)
+{
+ XPTInterfaceDirectoryEntry *parent_ide;
+ int i;
+ int new_indent = indent + BASE_INDENT;
+ int more_indent = new_indent + BASE_INDENT;
+
+ if (!id) {
+ fprintf(stdout, "%*s[Unresolved]\n", indent, " ");
+ return PR_TRUE;
+ }
+
+ if (id->parent_interface) {
+
+ parent_ide = &header->interface_directory[id->parent_interface - 1];
+
+ fprintf(stdout, "%*sParent: %s::%s\n", indent, " ",
+ parent_ide->name_space ?
+ parent_ide->name_space : "",
+ parent_ide->name);
+ }
+
+ fprintf(stdout, "%*sFlags:\n", indent, " ");
+
+ fprintf(stdout, "%*sScriptable: %s\n", new_indent, " ",
+ XPT_ID_IS_SCRIPTABLE(id->flags) ? "TRUE" : "FALSE");
+
+ fprintf(stdout, "%*sFunction: %s\n", new_indent, " ",
+ XPT_ID_IS_FUNCTION(id->flags) ? "TRUE" : "FALSE");
+
+ if (verbose_mode) {
+ if (id->parent_interface) {
+ fprintf(stdout,
+ "%*sIndex of parent interface (in data pool): %d\n",
+ indent, " ", id->parent_interface);
+
+ }
+ } else {
+ }
+
+ if (id->num_methods > 0) {
+ if (verbose_mode) {
+ fprintf(stdout,
+ "%*s# of Method Descriptors: %d\n",
+ indent, " ", id->num_methods);
+ } else {
+ fprintf(stdout, "%*sMethods:\n", indent, " ");
+ }
+
+ for (i=0; i<id->num_methods; i++) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sMethod #%d:\n", new_indent, " ", i);
+ if (!XPT_DumpMethodDescriptor(header,
+ &id->method_descriptors[i], id,
+ more_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ } else {
+ if (!XPT_DumpMethodDescriptor(header,
+ &id->method_descriptors[i], id,
+ new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+ }
+ } else {
+ fprintf(stdout, "%*sMethods:\n", indent, " ");
+ fprintf(stdout, "%*sNo Methods\n", new_indent, " ");
+ }
+
+ if (id->num_constants > 0) {
+ if (verbose_mode) {
+ fprintf(stdout,
+ "%*s# of Constant Descriptors: %d\n",
+ indent, " ", id->num_constants);
+ } else {
+ fprintf(stdout, "%*sConstants:\n", indent, " ");
+ }
+
+ for (i=0; i<id->num_constants; i++) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sConstant #%d:\n", new_indent, " ", i);
+ if (!XPT_DumpConstDescriptor(header,
+ &id->const_descriptors[i], id,
+ more_indent, verbose_mode))
+ return PR_FALSE;
+ } else {
+ if (!XPT_DumpConstDescriptor(header,
+ &id->const_descriptors[i], id,
+ new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+ }
+ } else {
+ fprintf(stdout, "%*sConstants:\n", indent, " ");
+ fprintf(stdout, "%*sNo Constants\n", new_indent, " ");
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode)
+{
+ int i;
+ int new_indent = indent + BASE_INDENT;
+ int more_indent = new_indent + BASE_INDENT;
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sName: %s\n", indent, " ", md->name);
+ fprintf(stdout, "%*sIs Getter? ", indent, " ");
+ if (XPT_MD_IS_GETTER(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Setter? ", indent, " ");
+ if (XPT_MD_IS_SETTER(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs NotXPCOM? ", indent, " ");
+ if (XPT_MD_IS_NOTXPCOM(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Constructor? ", indent, " ");
+ if (XPT_MD_IS_CTOR(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Hidden? ", indent, " ");
+ if (XPT_MD_IS_HIDDEN(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*s# of arguments: %d\n", indent, " ", md->num_args);
+ fprintf(stdout, "%*sParameter Descriptors:\n", indent, " ");
+
+ for (i=0; i<md->num_args; i++) {
+ fprintf(stdout, "%*sParameter #%d:\n", new_indent, " ", i);
+
+ if (!XPT_DumpParamDescriptor(header, &md->params[i], id,
+ more_indent, verbose_mode, PR_FALSE))
+ return PR_FALSE;
+ }
+
+ fprintf(stdout, "%*sResult:\n", indent, " ");
+ if (!XPT_DumpParamDescriptor(header, md->result, id, new_indent,
+ verbose_mode, PR_TRUE)) {
+ return PR_FALSE;
+ }
+ } else {
+ char *param_type;
+ XPTParamDescriptor *pd;
+
+ if (!XPT_GetStringForType(header, &md->result->type, id, &param_type)) {
+ return PR_FALSE;
+ }
+ fprintf(stdout, "%*s%c%c%c%c%c %s %s(", indent - 6, " ",
+ XPT_MD_IS_GETTER(md->flags) ? 'G' : ' ',
+ XPT_MD_IS_SETTER(md->flags) ? 'S' : ' ',
+ XPT_MD_IS_HIDDEN(md->flags) ? 'H' : ' ',
+ XPT_MD_IS_NOTXPCOM(md->flags) ? 'N' : ' ',
+ XPT_MD_IS_CTOR(md->flags) ? 'C' : ' ',
+ param_type, md->name);
+ for (i=0; i<md->num_args; i++) {
+ if (i!=0) {
+ fprintf(stdout, ", ");
+ }
+ pd = &md->params[i];
+ if (XPT_PD_IS_IN(pd->flags)) {
+ fprintf(stdout, "in");
+ if (XPT_PD_IS_OUT(pd->flags)) {
+ fprintf(stdout, "out ");
+ if (XPT_PD_IS_RETVAL(pd->flags)) {
+ fprintf(stdout, "retval ");
+ }
+ if (XPT_PD_IS_SHARED(pd->flags)) {
+ fprintf(stdout, "shared ");
+ }
+ } else {
+ fprintf(stdout, " ");
+ if (XPT_PD_IS_DIPPER(pd->flags)) {
+ fprintf(stdout, "dipper ");
+ }
+ if (XPT_PD_IS_RETVAL(pd->flags)) {
+ fprintf(stdout, "retval ");
+ }
+ }
+ } else {
+ if (XPT_PD_IS_OUT(pd->flags)) {
+ fprintf(stdout, "out ");
+ if (XPT_PD_IS_RETVAL(pd->flags)) {
+ fprintf(stdout, "retval ");
+ }
+ if (XPT_PD_IS_SHARED(pd->flags)) {
+ fprintf(stdout, "shared ");
+ }
+ } else {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX ");
+ }
+ }
+ if (!XPT_GetStringForType(header, &pd->type, id, &param_type)) {
+ return PR_FALSE;
+ }
+ fprintf(stdout, "%s", param_type);
+ }
+ fprintf(stdout, ");\n");
+ }
+ return PR_TRUE;
+}
+
+PRBool
+XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ char **type_string)
+{
+ static char buf[128]; /* ugly non-reentrant use of static buffer! */
+ PRBool isArray = PR_FALSE;
+
+ int tag = XPT_TDP_TAG(td->prefix);
+
+ if (tag == TD_ARRAY) {
+ isArray = PR_TRUE;
+ td = &id->additional_types[td->type.additional_type];
+ tag = XPT_TDP_TAG(td->prefix);
+ }
+
+ if (tag == TD_INTERFACE_TYPE) {
+ int idx = td->type.iface;
+ if (!idx || idx > header->num_interfaces)
+ *type_string = "UNKNOWN_INTERFACE";
+ else
+ *type_string = header->interface_directory[idx-1].name;
+ } else if (XPT_TDP_IS_POINTER(td->prefix.flags)) {
+ if (XPT_TDP_IS_REFERENCE(td->prefix.flags))
+ *type_string = rtype_array[tag];
+ else
+ *type_string = ptype_array[tag];
+ } else {
+ *type_string = type_array[tag];
+ }
+
+ if(isArray) {
+ sprintf(buf, "%s []", *type_string);
+ *type_string = buf;
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpXPTString(XPTString *str)
+{
+ int i;
+ for (i=0; i<str->length; i++) {
+ fprintf(stdout, "%c", str->bytes[i]);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode,
+ PRBool is_result)
+{
+ int new_indent = indent + BASE_INDENT;
+
+ if (!XPT_PD_IS_IN(pd->flags) &&
+ !XPT_PD_IS_OUT(pd->flags) &&
+ (XPT_PD_IS_RETVAL(pd->flags) ||
+ XPT_PD_IS_SHARED(pd->flags))) {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX\n");
+ } else {
+ if (!XPT_PD_IS_IN(pd->flags) && !XPT_PD_IS_OUT(pd->flags)) {
+ if (is_result) {
+ if (XPT_TDP_TAG(pd->type.prefix) != TD_UINT32 &&
+ XPT_TDP_TAG(pd->type.prefix) != TD_VOID) {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX\n");
+ }
+ } else {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX\n");
+ }
+ }
+ }
+
+ fprintf(stdout, "%*sIn Param? ", indent, " ");
+ if (XPT_PD_IS_IN(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sOut Param? ", indent, " ");
+ if (XPT_PD_IS_OUT(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sRetval? ", indent, " ");
+ if (XPT_PD_IS_RETVAL(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sShared? ", indent, " ");
+ if (XPT_PD_IS_SHARED(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sDipper? ", indent, " ");
+ if (XPT_PD_IS_DIPPER(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+
+ fprintf(stdout, "%*sType Descriptor:\n", indent, " ");
+ if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpTypeDescriptor(XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ int indent, PRBool verbose_mode)
+{
+ int new_indent;
+
+ if (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ fprintf(stdout, "%*sArray (size in arg %d and length in arg %d) of...\n",
+ indent, " ", td->argnum, td->argnum2);
+ td = &id->additional_types[td->type.additional_type];
+ indent += BASE_INDENT;
+ }
+
+ new_indent = indent + BASE_INDENT;
+
+ fprintf(stdout, "%*sIs Pointer? ", indent, " ");
+ if (XPT_TDP_IS_POINTER(td->prefix.flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Unique Pointer? ", indent, " ");
+ if (XPT_TDP_IS_UNIQUE_POINTER(td->prefix.flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Reference? ", indent, " ");
+ if (XPT_TDP_IS_REFERENCE(td->prefix.flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sTag: %d\n", indent, " ",
+ XPT_TDP_TAG(td->prefix));
+
+ if (XPT_TDP_TAG(td->prefix) == TD_PSTRING_SIZE_IS ||
+ XPT_TDP_TAG(td->prefix) == TD_PWSTRING_SIZE_IS) {
+ fprintf(stdout, "%*s - size in arg %d and length in arg %d\n",
+ indent, " ", td->argnum, td->argnum2);
+ }
+
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
+ fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " ");
+ fprintf(stdout, "%*sIndex of IDE: %d\n", new_indent, " ",
+ td->type.iface);
+ }
+
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
+ fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " ");
+ fprintf(stdout, "%*sIndex of Method Argument: %d\n", new_indent, " ",
+ td->argnum);
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode)
+{
+ int new_indent = indent + BASE_INDENT;
+ char *const_type;
+/* char *out; */
+ PRUint32 uintout;
+ PRInt32 intout;
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sName: %s\n", indent, " ", cd->name);
+ fprintf(stdout, "%*sType Descriptor: \n", indent, " ");
+ if (!XPT_DumpTypeDescriptor(&cd->type, id, new_indent, verbose_mode))
+ return PR_FALSE;
+ fprintf(stdout, "%*sValue: ", indent, " ");
+ } else {
+ if (!XPT_GetStringForType(header, &cd->type, id, &const_type)) {
+ return PR_FALSE;
+ }
+ fprintf(stdout, "%*s%s %s = ", indent, " ", const_type, cd->name);
+ }
+
+ switch(XPT_TDP_TAG(cd->type.prefix)) {
+ case TD_INT8:
+ fprintf(stdout, "%d", cd->value.i8);
+ break;
+ case TD_INT16:
+ fprintf(stdout, "%d", cd->value.i16);
+ break;
+ case TD_INT64:
+ /* XXX punt for now to remove NSPR linkage...
+ * borrow from mozilla/nsprpub/pr/src/io/prprf.c::cvt_ll? */
+
+/* out = PR_smprintf("%lld", cd->value.i64); */
+/* fputs(out, stdout); */
+/* PR_smprintf_free(out); */
+ LL_L2I(intout, cd->value.i64);
+ fprintf(stdout, "%d", intout);
+ break;
+ case TD_INT32:
+ fprintf(stdout, "%d", cd->value.i32);
+ break;
+ case TD_UINT8:
+ fprintf(stdout, "%u", cd->value.ui8);
+ break;
+ case TD_UINT16:
+ fprintf(stdout, "%u", cd->value.ui16);
+ break;
+ case TD_UINT64:
+/* out = PR_smprintf("%lld", cd->value.ui64); */
+/* fputs(out, stdout); */
+/* PR_smprintf_free(out); */
+ /* XXX punt for now to remove NSPR linkage. */
+ LL_L2UI(uintout, cd->value.ui64);
+ fprintf(stdout, "%u", uintout);
+ break;
+ case TD_UINT32:
+ fprintf(stdout, "%u", cd->value.ui32);
+ break;
+ case TD_FLOAT:
+ fprintf(stdout, "%f", cd->value.flt);
+ break;
+ case TD_DOUBLE:
+ fprintf(stdout, "%g", cd->value.dbl);
+ break;
+ case TD_BOOL:
+ if (cd->value.bul)
+ fprintf(stdout, "TRUE");
+ else
+ fprintf(stdout, "FALSE");
+ break;
+ case TD_CHAR:
+ fprintf(stdout, "%c", cd->value.ch);
+ break;
+ case TD_WCHAR:
+ fprintf(stdout, "%c", cd->value.wch & 0xff);
+ break;
+ case TD_VOID:
+ fprintf(stdout, "VOID");
+ break;
+ case TD_PNSIID:
+ if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) {
+ print_IID(cd->value.iid, stdout);
+ } else
+ return PR_FALSE;
+ break;
+ case TD_PSTRING:
+ if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) {
+ fprintf(stdout, "%s", cd->value.str);
+ } else
+ return PR_FALSE;
+ break;
+ case TD_PWSTRING:
+ if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) {
+ PRUint16 *ch = cd->value.wstr;
+ while (*ch) {
+ fprintf(stdout, "%c", *ch & 0xff);
+ ch++;
+ }
+ } else
+ return PR_FALSE;
+ break;
+ default:
+ perror("Unrecognized type");
+ return PR_FALSE;
+ break;
+ }
+
+ if (verbose_mode) {
+ fprintf(stdout, "\n");
+ } else {
+ fprintf(stdout, ";\n");
+ }
+
+ return PR_TRUE;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c
new file mode 100644
index 00000000..872b96fd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c
@@ -0,0 +1,883 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * A utility for linking multiple typelib files.
+ */
+
+#include "xpt_xdr.h"
+#include <stdio.h>
+#ifdef XP_MAC
+#include <stat.h>
+#else
+#include <sys/stat.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "prlong.h"
+
+#ifndef NULL
+#define NULL (void *) 0
+#endif
+
+/* Forward declarations. */
+typedef struct fixElement fixElement;
+static int compare_IDEs_by_IID(const void *ap, const void *bp);
+static int compare_IDE_with_zero(const void *ap);
+static int compare_IDEs_by_name(const void *ap, const void *bp);
+static int compare_IDEs_by_name_space(const void *ap, const void *bp);
+static int compare_strings(const void *ap, const void *bp);
+static int compare_pointers(const void *ap, const void *bp);
+static int compare_fixElements_by_IID(const void *ap, const void *bp);
+static int compare_fixElements_by_name(const void *ap, const void *bp);
+static int compare_IIDs(const void *ap, const void *bp);
+PRBool shrink_IDE_array(XPTInterfaceDirectoryEntry *ide,
+ int element_to_delete, int num_interfaces);
+PRBool update_fix_array(XPTArena *arena, fixElement *fix, int element_to_delete,
+ int num_interfaces, int replacement);
+static int get_new_index(const fixElement *fix, int num_elements,
+ int target_file, int target_interface);
+PRBool copy_IDE(XPTInterfaceDirectoryEntry *from,
+ XPTInterfaceDirectoryEntry *to);
+PRBool copy_fixElement(fixElement *from, fixElement *to);
+static void print_IID(struct nsID *iid, FILE *file);
+static void xpt_link_usage(char *argv[]);
+
+struct fixElement {
+ nsID iid;
+ char* name;
+ int file_num;
+ int interface_num;
+ PRBool is_deleted;
+ /* These next two variables will point you to the substitute interface
+ * if this one has been deleted.
+ */
+ int maps_to_file_num;
+ int maps_to_interface_num;
+};
+
+/* Global variables. */
+PRUint16 trueNumberOfInterfaces = 0;
+PRUint16 totalNumberOfInterfaces = 0;
+PRUint16 oldTotalNumberOfInterfaces = 0;
+
+/* The following globals are explained in xpt_struct.h */
+PRUint8 major_version = XPT_MAJOR_VERSION;
+PRUint8 minor_version = XPT_MINOR_VERSION;
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+
+#define main xptlink_main
+int xptlink_main(int argc, char *argv[]);
+extern size_t mac_get_file_length(const char* filename);
+#define get_file_length mac_get_file_length
+
+#else
+
+static size_t get_file_length(const char* filename)
+{
+ struct stat file_stat;
+ if (stat(filename, &file_stat) != 0) {
+ perror("FAILED: get_file_length");
+ exit(1);
+ }
+ return file_stat.st_size;
+}
+
+#endif /* XP_MAC && XPIDL_PLUGIN */
+
+int
+main(int argc, char **argv)
+{
+ XPTArena *arena;
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ XPTHeader *header;
+ XPTInterfaceDirectoryEntry *IDE_array = NULL;
+ XPTInterfaceDescriptor *id;
+ XPTTypeDescriptor *td;
+ XPTAnnotation *ann, *first_ann;
+ PRUint32 header_sz, len;
+ PRUint32 oldOffset;
+ PRUint32 newOffset;
+ size_t flen = 0;
+ char *head, *data, *whole;
+ const char *outFileName;
+ FILE *in, *out;
+ fixElement *fix_array = NULL;
+ int i,j;
+ int k = 0;
+
+ if (argc < 3) {
+ xpt_link_usage(argv);
+ return 1;
+ }
+
+ arena = XPT_NewArena(1024 * 10, sizeof(double), "main xpt_link arena");
+ if (!arena) {
+ perror("FAILED: XPT_NewArena");
+ return 1;
+ }
+
+ first_ann = XPT_NewAnnotation(arena, XPT_ANN_LAST, NULL, NULL);
+
+ /* Check if the "-t version numnber" cmd line arg is present */
+ i = 1;
+ if (argv[i][0] == '-' && argv[i][1] == 't') {
+ /* Parse for "-t version number" */
+
+ /* If -t is the last argument on the command line, we have a problem */
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing version number after -t\n");
+ xpt_link_usage(argv);
+ return 1;
+ }
+
+ /*
+ * Assume that the argument after "-t" is the version number string
+ * and search for it in our internal list of acceptable version
+ * numbers.
+ */
+
+ switch (XPT_ParseVersionString(argv[++i], &major_version,
+ &minor_version)) {
+ case XPT_VERSION_CURRENT:
+ case XPT_VERSION_OLD:
+ break;
+ case XPT_VERSION_UNSUPPORTED:
+ fprintf(stderr, "ERROR: version \"%s\" not supported.\n",
+ argv[i]);
+ xpt_link_usage(argv);
+ return 1;
+ case XPT_VERSION_UNKNOWN:
+ default:
+ fprintf(stderr, "ERROR: version \"%s\" not recognised.\n",
+ argv[i]);
+ xpt_link_usage(argv);
+ return 1;
+ }
+
+ /* Hang onto the output file name. It's needed later. */
+ outFileName = argv[++i];
+
+ /* Increment i to the cmd line arg after outFileName */
+ i++;
+ }
+ else {
+ outFileName = argv[1];
+ i = 2;
+ }
+
+ for ( /* use i from earlier */ ; i < argc; i++) {
+ char *name = argv[i];
+
+ flen = get_file_length(name);
+ if (!flen) {
+ fprintf(stderr, "ERROR: file %s is zero length\n", name);
+ return 1;
+ }
+
+ in = fopen(name, "rb");
+ if (!in) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ whole = XPT_MALLOC(arena, flen);
+ if (!whole) {
+ perror("FAILED: XPT_MALLOC for whole");
+ return 1;
+ }
+
+ if (flen > 0) {
+ size_t rv = fread(whole, 1, flen, in);
+ if (rv < flen) {
+ fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen);
+ return 1;
+ }
+ if (ferror(in) != 0 || fclose(in) != 0) {
+ perror("FAILED: Unable to read typelib file.\n");
+ return 1;
+ }
+
+ state = XPT_NewXDRState(XPT_DECODE, whole, flen);
+ if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
+ fprintf(stdout, "XPT_MakeCursor failed for %s\n", name);
+ return 1;
+ }
+ if (!XPT_DoHeader(arena, cursor, &header)) {
+ fprintf(stdout,
+ "DoHeader failed for %s. Is %s a valid .xpt file?\n",
+ name, name);
+ return 1;
+ }
+
+ /*
+ * Make sure that the version of the typelib file is less than or
+ * equal to the version specified in the -t cmd line arg.
+ */
+
+ if (header &&
+ (header->major_version > major_version ||
+ (header->major_version == major_version &&
+ header->minor_version > minor_version))) {
+ fprintf(stderr, "FAILED: %s's version, %d.%d, is newer than "
+ "the version (%d.%d) specified in the -t "
+ "command line argument.\n",
+ name, header->major_version, header->minor_version,
+ major_version, minor_version);
+ return 1;
+ }
+
+ oldTotalNumberOfInterfaces = totalNumberOfInterfaces;
+ totalNumberOfInterfaces += header->num_interfaces;
+ if (header->num_interfaces > 0) {
+ XPTInterfaceDirectoryEntry *newIDE;
+ fixElement *newFix;
+
+ newIDE = (XPTInterfaceDirectoryEntry *)
+ XPT_MALLOC(arena, totalNumberOfInterfaces *
+ sizeof(XPTInterfaceDirectoryEntry));
+ if (!newIDE) {
+ perror("FAILED: XPT_MALLOC of IDE_array");
+ return 1;
+ }
+
+ if (IDE_array) {
+ if (oldTotalNumberOfInterfaces)
+ memcpy(newIDE, IDE_array,
+ oldTotalNumberOfInterfaces *
+ sizeof(XPTInterfaceDirectoryEntry));
+ XPT_FREE(arena, IDE_array);
+ }
+ IDE_array = newIDE;
+
+
+ newFix = (fixElement *)
+ XPT_MALLOC(arena,
+ totalNumberOfInterfaces * sizeof(fixElement));
+ if (!newFix) {
+ perror("FAILED: XPT_MALLOC of fix_array");
+ return 1;
+ }
+
+ if (fix_array) {
+ if (oldTotalNumberOfInterfaces)
+ memcpy(newFix, fix_array,
+ oldTotalNumberOfInterfaces *
+ sizeof(fixElement));
+ XPT_FREE(arena, fix_array);
+ }
+ fix_array = newFix;
+
+ for (j=0; j<header->num_interfaces; j++) {
+ if (!copy_IDE(&header->interface_directory[j],
+ &IDE_array[k])) {
+ perror("FAILED: 1st copying of IDE");
+ return 1;
+ }
+ fix_array[k].iid = IDE_array[k].iid;
+ fix_array[k].name = IDE_array[k].name;
+ fix_array[k].file_num = i-2;
+ fix_array[k].interface_num = j+1;
+ fix_array[k].is_deleted = PR_FALSE;
+ fix_array[k].maps_to_file_num = i-2;
+ fix_array[k].maps_to_interface_num = j+1;
+
+ k++;
+ }
+ }
+
+ /* Copy the annotations if they are not 'empty'
+ */
+ if (header->annotations != NULL &&
+ header->annotations->flags != XPT_ANN_LAST) {
+ ann = first_ann;
+ while (ann->next != NULL) {
+ ann = ann->next;
+ }
+ ann->next = header->annotations;
+ }
+
+ XPT_FREEIF(arena, header);
+ if (state)
+ XPT_DestroyXDRState(state);
+ XPT_FREE(arena, whole);
+ flen = 0;
+
+ } else {
+ fclose(in);
+ perror("FAILED: file length <= 0");
+ return 1;
+ }
+ }
+
+ /* Make sure the last annotation is the only one marked as XP_ANN_LAST.
+ */
+ ann = first_ann;
+ while (ann->next != NULL) {
+ ann->flags &= ~XPT_ANN_LAST;
+ ann = ann->next;
+ }
+ ann->flags |= XPT_ANN_LAST;
+
+ /* Sort both IDE_array and fix_array by name so we can check for
+ * name_space::name collisions.
+ */
+ qsort(IDE_array,
+ totalNumberOfInterfaces,
+ sizeof(XPTInterfaceDirectoryEntry),
+ compare_IDEs_by_name);
+
+ qsort(fix_array,
+ totalNumberOfInterfaces,
+ sizeof(fixElement),
+ compare_fixElements_by_name);
+
+ /* trueNumberOfInterfaces == number of interfaces left after deletions
+ * are made. Initialize it here to be the same as the total number of
+ * interfaces we'ce encountered thus far.
+ */
+ trueNumberOfInterfaces = totalNumberOfInterfaces;
+
+ /* Iterate through the sorted interfaces. Start at one so we don't
+ * accidentally walk off the end of the array.
+ */
+ i = 1;
+ while (i != trueNumberOfInterfaces) {
+
+ /* Check for name_space::name collision.
+ */
+ if (compare_strings(IDE_array[i-1].name,
+ IDE_array[i].name) == 0 &&
+ compare_strings(IDE_array[i-1].name_space,
+ IDE_array[i].name_space) == 0) {
+
+ /* If one of the interfaces is unresolved, delete that one
+ * preferentailly.
+ */
+ if (!IDE_array[i-1].interface_descriptor) {
+ /* Shrink the IDE_array to delete the duplicate interface.
+ */
+ if (!shrink_IDE_array(IDE_array,
+ i-1,
+ trueNumberOfInterfaces)) {
+ perror("FAILED: shrink_IDE_array");
+ return 1;
+ }
+ /* Update the fix array. This involves moving the deleted
+ * entry to the end of the array (rather than deleting it)
+ * and mapping it to the "replacement" element so we can
+ * update interface indices appropriately later.
+ */
+ update_fix_array(arena, fix_array, i-1,
+ totalNumberOfInterfaces, i);
+ /* Decrement the true number of interfaces since we just
+ * deleted one. There's more than one way to get out of
+ * this loop.
+ */
+ trueNumberOfInterfaces--;
+ } else {
+ if (!IDE_array[i].interface_descriptor ||
+ (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0))
+ {
+ /* Shrink the IDE_array to delete the duplicate interface.
+ */
+ if (!shrink_IDE_array(IDE_array,
+ i,
+ trueNumberOfInterfaces)) {
+ perror("FAILED: shrink_IDE_array");
+ return 1;
+ }
+ /* Update the fix array. This involves moving the deleted
+ * entry to the end of the array (rather than deleting it)
+ * and mapping it to the "replacement" element so we can
+ * update interface indices appropriately later.
+ */
+ update_fix_array(arena, fix_array, i,
+ totalNumberOfInterfaces, i-1);
+ /* Decrement the true number of interfaces since we just
+ * deleted one. There's more than one way to get out of
+ * this loop.
+ */
+ trueNumberOfInterfaces--;
+ } else {
+ /* Found interfaces with duplicate names but different
+ * iids! */
+ char *ns = IDE_array[i].name_space;
+ fprintf(stderr,
+ "ERROR: found duplicate definitions of interface "
+ "%s%s%s with iids \n",
+ ns ? ns : "", ns ? "::" : "", IDE_array[i].name);
+ print_IID(&IDE_array[i].iid, stderr);
+ fprintf(stderr, " and ");
+ print_IID(&IDE_array[i-1].iid, stderr);
+ fprintf(stderr, "\n");
+ return 1;
+ }
+ }
+ } else {
+ /* Only increment if there was no name_space::name collision.
+ */
+ i++;
+ }
+ }
+
+ /* Sort the IDE_array (put them in their final order) so that updating
+ * of indices will be meaningful.
+ */
+ qsort(IDE_array,
+ trueNumberOfInterfaces,
+ sizeof(XPTInterfaceDirectoryEntry),
+ compare_IDEs_by_IID);
+
+ /* Sort the fix_array to match the IDE_array.
+ */
+ qsort(fix_array,
+ trueNumberOfInterfaces,
+ sizeof(fixElement),
+ compare_fixElements_by_IID);
+
+ /* Iterate through the remaining interfaces (those not deleted)
+ * looking for references to interfaces (such as id->parent_interface)
+ * which need an updated index number.
+ */
+ for (i=0; i<trueNumberOfInterfaces; i++) {
+
+ /* Define id to save some keystrokes.
+ */
+ id = IDE_array[i].interface_descriptor;
+
+ /* Check for unresolved interface.
+ */
+ if (id) {
+
+ /* Fix parent_interface first.
+ */
+ if (id->parent_interface && id->parent_interface != 0) {
+ id->parent_interface =
+ get_new_index(fix_array, totalNumberOfInterfaces,
+ fix_array[i].file_num, id->parent_interface);
+ }
+ /* Iterate through the method descriptors looking for params of
+ * type TD_INTERFACE_TYPE.
+ */
+ for (j=0; j<id->num_methods; j++) {
+ /* Cycle through the params first.
+ */
+ for (k=0; k<id->method_descriptors[j].num_args; k++) {
+ /* Define td to save some keystrokes.
+ */
+ td = &id->method_descriptors[j].params[k].type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &id->additional_types[td->type.additional_type];
+ }
+
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
+ td->type.iface =
+ get_new_index(fix_array,
+ totalNumberOfInterfaces,
+ fix_array[i].file_num,
+ td->type.iface);
+ }
+ }
+
+ /* Check the result param too. Define td again to save
+ * some keystrokes.
+ */
+ td = &id->method_descriptors[j].result->type;
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
+ td->type.iface =
+ get_new_index(fix_array, totalNumberOfInterfaces,
+ fix_array[i].file_num,
+ td->type.iface);
+ }
+ }
+ }
+ }
+
+ /* Iterate through the array quickly looking for duplicate IIDS.
+ * This shouldn't happen, i.e. is a failure condition, so bail
+ * if we find a duplicate. If we have more than one entry, start
+ * at one so we don't accidentally grep the ether.
+ */
+ if (trueNumberOfInterfaces>1) {
+ for (i=1; i<trueNumberOfInterfaces; i++) {
+ /* Only complain if the IIDs are identical and nonzero. */
+ if (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0 &&
+ compare_IDE_with_zero(&IDE_array[i]) != 0) {
+ fprintf(stderr, "FATAL ERROR:\n"
+ "Duplicate IID detected (");
+ print_IID(&IDE_array[i-1].iid, stderr);
+ fprintf(stderr, ") in\n"
+ "interface %s::%s from %s\n"
+ "and\n"
+ "interface %s::%s from %s\n",
+ IDE_array[i-1].name_space ?
+ IDE_array[i-1].name_space : "",
+ IDE_array[i-1].name,
+ argv[fix_array[i-1].file_num+2],
+ IDE_array[i].name_space ?
+ IDE_array[i].name_space : "",
+ IDE_array[i].name,
+ argv[fix_array[i].file_num+2]);
+ return 1;
+ }
+ }
+ }
+
+ header = XPT_NewHeader(arena, (PRUint16)trueNumberOfInterfaces,
+ major_version, minor_version);
+
+ header->annotations = first_ann;
+ for (i=0; i<trueNumberOfInterfaces; i++) {
+ if (!copy_IDE(&IDE_array[i], &header->interface_directory[i])) {
+ perror("FAILED: 2nd copying of IDE");
+ return 1;
+ }
+ }
+
+ header_sz = XPT_SizeOfHeaderBlock(header);
+
+ state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
+ if (!state) {
+ perror("FAILED: error creating XDRState");
+ return 1;
+ }
+
+ XPT_SetDataOffset(state, header_sz);
+
+ if (!XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor)) {
+ perror("FAILED: error making cursor");
+ return 1;
+ }
+ oldOffset = cursor->offset;
+ if (!XPT_DoHeader(arena, cursor, &header)) {
+ perror("FAILED: error doing Header");
+ return 1;
+ }
+ newOffset = cursor->offset;
+ XPT_GetXDRDataLength(state, XPT_HEADER, &len);
+ header->file_length = len;
+ XPT_GetXDRDataLength(state, XPT_DATA, &len);
+ header->file_length += len;
+ XPT_SeekTo(cursor, oldOffset);
+ if (!XPT_DoHeaderPrologue(arena, cursor, &header, NULL)) {
+ perror("FAILED: error doing Header");
+ return 1;
+ }
+ XPT_SeekTo(cursor, newOffset);
+ out = fopen(outFileName, "wb");
+ if (!out) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ XPT_GetXDRData(state, XPT_HEADER, &head, &len);
+ fwrite(head, len, 1, out);
+
+ XPT_GetXDRData(state, XPT_DATA, &data, &len);
+ fwrite(data, len, 1, out);
+
+ if (ferror(out) != 0 || fclose(out) != 0) {
+ fprintf(stderr, "Error writing file: %s\n", argv[1]);
+ } else {
+/* fprintf(stderr, "File written: %s\n", argv[1]); */
+ }
+
+ if (state)
+ XPT_DestroyXDRState(state);
+
+ XPT_DestroyArena(arena);
+
+ return 0;
+}
+
+static int
+compare_IDEs_by_IID(const void *ap,
+ const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp;
+
+ int answer = compare_IIDs(&ide1->iid, &ide2->iid);
+ if(!answer)
+ answer = compare_strings(ide1->name, ide2->name);
+
+ return answer;
+}
+
+/* For detecting unresolved interfaces. */
+const nsID iid_zero = { 0x0, 0x0, 0x0,
+ { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+static int
+compare_IDE_with_zero(const void *ap)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap;
+
+ return compare_IIDs(&ide1->iid, &iid_zero);
+}
+
+static int
+compare_fixElements_by_IID(const void *ap,
+ const void *bp)
+{
+ const fixElement *fix1 = ap, *fix2 = bp;
+
+ int answer = compare_IIDs(&fix1->iid, &fix2->iid);
+ if(!answer)
+ answer = compare_strings(fix1->name, fix2->name);
+
+ return answer;
+}
+
+static int
+compare_IDEs_by_name(const void *ap,
+ const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp;
+
+ int answer = compare_strings(ide1->name, ide2->name);
+ if(!answer)
+ answer = compare_pointers(ide1->name, ide2->name);
+
+ return answer;
+}
+
+static int
+compare_IDEs_by_name_space(const void *ap,
+ const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp;
+
+ return compare_strings(ide1->name_space, ide2->name_space);
+}
+
+static int
+compare_strings(const void *ap, const void *bp)
+{
+ const char *string1 = ap, *string2 = bp;
+
+ if (!string1 && !string2)
+ return 0;
+ if (!string1)
+ return -1;
+ if (!string2)
+ return 1;
+
+ return strcmp(string1, string2);
+}
+
+static int
+compare_pointers(const void *ap, const void *bp)
+{
+ if (ap == bp) {
+#ifdef DEBUG_jband
+ perror("name addresses were equal!");
+#endif
+ return 0;
+ }
+ if (ap > bp)
+ return 1;
+ return -1;
+}
+
+static int
+compare_fixElements_by_name(const void *ap,
+ const void *bp)
+{
+ const fixElement *fix1 = ap, *fix2 = bp;
+
+ int answer= compare_strings(fix1->name, fix2->name);
+ if(!answer)
+ answer = compare_pointers(fix1->name, fix2->name);
+
+ return answer;
+}
+
+static int
+compare_IIDs(const void *ap, const void *bp)
+{
+ const nsID *a = ap, *b = bp;
+ int i;
+#define COMPARE(field) if (a->field > b->field) return 1; \
+ if (b->field > a->field) return -1;
+ COMPARE(m0);
+ COMPARE(m1);
+ COMPARE(m2);
+ for (i = 0; i < 8; i++) {
+ COMPARE(m3[i]);
+ }
+ return 0;
+#undef COMPARE
+}
+
+PRBool
+shrink_IDE_array(XPTInterfaceDirectoryEntry *ide, int element_to_delete,
+ int num_interfaces)
+{
+ int i;
+
+ if (element_to_delete >= num_interfaces) {
+ return PR_FALSE;
+ }
+
+ for (i=element_to_delete+1; i<num_interfaces; i++) {
+ if (!copy_IDE(&ide[i], &ide[i-1])) {
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+/* update_fix_array marks a fixElement as deleted, updates its mapping
+ * to point to the "replacement" element, and moves it to the end of
+ * the array.
+ */
+PRBool
+update_fix_array(XPTArena *arena, fixElement *fix, int element_to_delete,
+ int num_interfaces, int replacement)
+{
+ fixElement *deleted;
+ int i;
+
+ if (element_to_delete >= num_interfaces) {
+ return PR_FALSE;
+ }
+
+ deleted = XPT_CALLOC(arena, sizeof(fixElement));
+ if (!copy_fixElement(&fix[element_to_delete], deleted)) {
+ return PR_FALSE;
+ }
+ deleted->is_deleted = PR_TRUE;
+ deleted->maps_to_file_num = fix[replacement].file_num;
+ deleted->maps_to_interface_num = fix[replacement].interface_num;
+
+ for (i=element_to_delete+1; i<num_interfaces; i++) {
+ if (!copy_fixElement(&fix[i], &fix[i-1])) {
+ return PR_FALSE;
+ }
+ }
+
+ if (!copy_fixElement(deleted, &fix[num_interfaces-1])) {
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+/* get_new_index returns the new interface index by walking the fix_array
+ * until the file_num and interface_num match the target values. If a match
+ * is found, it checks to see if that element has been deleted. If it has
+ * been deleted, it follows that elements mapping until it gets to the
+ * proper interface (recursion). FYI, Indices are one-based; zero
+ * represents the special case (no parent interface).
+ */
+static int
+get_new_index(const fixElement *fix, int num_elements,
+ int target_file, int target_interface)
+{
+ int i;
+
+ for (i=0; i<num_elements; i++) {
+ if (fix[i].file_num == target_file &&
+ fix[i].interface_num == target_interface) {
+ if (fix[i].is_deleted) {
+ return get_new_index(fix, num_elements,
+ fix[i].maps_to_file_num,
+ fix[i].maps_to_interface_num);
+ }
+ return i+1;
+ }
+ }
+
+ return 0;
+}
+
+PRBool
+copy_IDE(XPTInterfaceDirectoryEntry *from, XPTInterfaceDirectoryEntry *to)
+{
+ if (!from || !to) {
+ return PR_FALSE;
+ }
+
+ to->iid = from->iid;
+ to->name = from->name;
+ to->name_space = from->name_space;
+ to->interface_descriptor = from->interface_descriptor;
+ return PR_TRUE;
+}
+
+PRBool
+copy_fixElement(fixElement *from, fixElement *to)
+{
+ if (!from || !to) {
+ return PR_FALSE;
+ }
+
+ to->iid = from->iid;
+ to->name = from->name;
+ to->file_num = from->file_num;
+ to->interface_num = from->interface_num;
+ to->is_deleted = from->is_deleted;
+ to->maps_to_file_num = from->maps_to_file_num;
+ to->maps_to_interface_num = from->maps_to_interface_num;
+
+ return PR_TRUE;
+}
+
+static void
+print_IID(struct nsID *iid, FILE *file)
+{
+ fprintf(file, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (PRUint32) iid->m0, (PRUint32) iid->m1,(PRUint32) iid->m2,
+ (PRUint32) iid->m3[0], (PRUint32) iid->m3[1],
+ (PRUint32) iid->m3[2], (PRUint32) iid->m3[3],
+ (PRUint32) iid->m3[4], (PRUint32) iid->m3[5],
+ (PRUint32) iid->m3[6], (PRUint32) iid->m3[7]);
+}
+
+static void
+xpt_link_usage(char *argv[])
+{
+ fprintf(stdout, "Usage: %s [-t version number] outfile file1.xpt file2.xpt ...\n"
+ " Links multiple typelib files into one outfile\n"
+ " -t create a typelib of an older version number\n", argv[0]);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore b/src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in b/src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in
new file mode 100644
index 00000000..da1bcfae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in
@@ -0,0 +1,50 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+SIMPLE_PROGRAMS = windbgdlg$(BIN_SUFFIX)
+
+CPPSRCS = windbgdlg.cpp
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp b/src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp
new file mode 100644
index 00000000..9023ef4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Bandhauer <jband@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Windows only app to show a modal debug dialog - launched by nsDebug.cpp */
+
+#include <windows.h>
+
+int WINAPI
+WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow)
+{
+ static char msg[4048];
+
+ wsprintf(msg,
+ "%s\n\nClick Abort to exit the Application.\n"
+ "Click Retry to Debug the Application..\n"
+ "Click Ignore to continue running the Application.",
+ lpszCmdLine);
+
+ return MessageBox(NULL, msg, "nsDebug::Assertion",
+ MB_ICONSTOP | MB_SYSTEMMODAL|
+ MB_ABORTRETRYIGNORE | MB_DEFBUTTON3);
+}
diff --git a/src/libs/xpcom18a4/xpcom/xpcom-config.h.in b/src/libs/xpcom18a4/xpcom/xpcom-config.h.in
new file mode 100644
index 00000000..5338a41d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/xpcom-config.h.in
@@ -0,0 +1,65 @@
+/* Global defines needed by xpcom clients */
+
+#ifndef _XPCOM_CONFIG_H_
+#define _XPCOM_CONFIG_H_
+
+/* Define this to throw() if the compiler complains about
+ * constructors returning NULL
+ */
+#undef CPP_THROW_NEW
+
+/* Define if the c++ compiler supports a 2-byte wchar_t */
+#undef HAVE_CPP_2BYTE_WCHAR_T
+
+/* Define if the c++ compiler supports changing access with |using| */
+#undef HAVE_CPP_ACCESS_CHANGING_USING
+
+/* Define if the c++ compiler can resolve ambiguity with |using| */
+#undef HAVE_CPP_AMBIGUITY_RESOLVING_USING
+
+/* Define if the c++ compiler has builtin Bool type */
+#undef HAVE_CPP_BOOL
+
+/* Define if a dyanmic_cast to void* gives the most derived object */
+#undef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
+
+/* Define if the c++ compiler supports the |explicit| keyword */
+#undef HAVE_CPP_EXPLICIT
+
+/* Define if the c++ compiler supports the modern template
+ * specialization syntax
+ */
+#undef HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+
+/* Define if the c++ compiler supports the |std| namespace */
+#undef HAVE_CPP_NAMESPACE_STD
+
+/* Define if the c++ compiler supports reinterpret_cast */
+#undef HAVE_CPP_NEW_CASTS
+
+/* Define if the c++ compiler supports partial template specialization */
+#undef HAVE_CPP_PARTIAL_SPECIALIZATION
+
+/* Define if the c++ compiler has trouble comparing a constant
+ * reference to a templatized class to zero
+ */
+#undef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+/* Define if the c++ compiler supports the |typename| keyword */
+#undef HAVE_CPP_TYPENAME
+
+/* Define if the stanard template operator!=() is ambiguous */
+#undef HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL
+
+/* Define if statvfs() is available */
+#undef HAVE_STATVFS
+
+/* Define if the c++ compiler requires implementations of
+ * unused virtual methods
+ */
+#undef NEED_CPP_UNUSED_IMPLEMENTATIONS
+
+/* Define to either <new> or <new.h> */
+#undef NEW_H
+
+#endif /* _XPCOM_CONFIG_H_ */
diff --git a/src/libs/xpcom18a4/xpcom/xpcom-private.h.in b/src/libs/xpcom18a4/xpcom/xpcom-private.h.in
new file mode 100644
index 00000000..ae1c4605
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/xpcom-private.h.in
@@ -0,0 +1,31 @@
+/* The following defines are only used by the xpcom implementation */
+
+#ifndef _XPCOM_PRIVATE_H_
+#define _XPCOM_PRIVATE_H_
+
+/* Define to build the static component loader */
+#undef ENABLE_STATIC_COMPONENT_LOADER
+
+/* Define if getpagesize() is available */
+#undef HAVE_GETPAGESIZE
+
+/* Define if iconv() is available */
+#undef HAVE_ICONV
+
+/* Define if iconv() supports const input */
+#undef HAVE_ICONV_WITH_CONST_INPUT
+
+/* Define if mbrtowc() is available */
+#undef HAVE_MBRTOWC
+
+/* Define if <sys/mount.h> is present */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define if <sys/vfs.h> is present */
+#undef HAVE_SYS_VFS_H
+
+/* Define if wcrtomb() is available */
+#undef HAVE_WCRTOMB
+
+#endif /* _XPCOM_PRIVATE_H_ */
+